function countFalsy( arrays ) {
	var isCmplx;
	var ndims;
	var xmmv;
	var shx;
	var iox;
	var len;
	var sx;
	var ox;
	var ns;
	var x;
	var d;
	var i;

	// Unpack the ndarray and standardize ndarray meta data:
	x = ndarray2object( arrays[ 0 ] );
	shx = x.shape;
	ndims = shx.length;

	// Check for known array types which can be reinterpreted for better iteration performance...
	if ( isBooleanArray( x.data ) ) {
		x.data = reinterpretBoolean( x.data, 0 );
		x.accessorProtocol = false;
	} else if ( isComplexArray( x.data ) ) {
		x.data = reinterpretComplex( x.data, 0 );
		x.accessorProtocol = false;
		x.strides = gscal( ndims, 2, x.strides, 1 );
		x.offset *= 2;
		isCmplx = true;
	}
	// Determine whether we can avoid iteration altogether...
	if ( ndims === 0 ) {
		if ( x.accessorProtocol ) {
			return ACCESSOR_COUNT[ ndims ]( x );
		}
		if ( isCmplx ) {
			return COMPLEX_COUNT[ ndims ]( x );
		}
		return COUNT[ ndims ]( x );
	}
	// Compute the number of elements and the number of singleton dimensions...
	len = 1; // number of elements
	ns = 0;  // number of singleton dimensions
	for ( i = 0; i < ndims; i++ ) {
		d = shx[ i ];

		// Note that, if one of the dimensions is `0`, the length will be `0`...
		len *= d;

		// Check whether the current dimension is a singleton dimension...
		if ( d === 1 ) {
			ns += 1;
		}
	}
	// Check whether we were provided an empty ndarray...
	if ( len === 0 ) {
		return true;
	}
	// Determine whether the ndarray is one-dimensional and thus readily translates to a one-dimensional strided array...
	if ( ndims === 1 ) {
		if ( x.accessorProtocol ) {
			return ACCESSOR_COUNT[ ndims ]( x );
		}
		if ( isCmplx ) {
			return COMPLEX_COUNT[ ndims ]( x );
		}
		return COUNT[ ndims ]( x );
	}
	sx = x.strides;

	// Determine whether the ndarray has only **one** non-singleton dimension (e.g., ndims=4, shape=[10,1,1,1]) so that we can treat an ndarray as being equivalent to a one-dimensional strided array...
	if ( ns === ndims-1 ) {
		// Get the index of the non-singleton dimension...
		for ( i = 0; i < ndims; i++ ) {
			if ( shx[ i ] !== 1 ) {
				break;
			}
		}
		x.shape = [ shx[i] ];
		x.strides = [ sx[i] ];
		if ( x.accessorProtocol ) {
			return ACCESSOR_COUNT[ 1 ]( x );
		}
		if ( isCmplx ) {
			return COMPLEX_COUNT[ 1 ]( x );
		}
		return COUNT[ 1 ]( x );
	}
	iox = iterationOrder( sx ); // +/-1

	// Determine whether we can avoid blocked iteration...
	if ( iox !== 0 ) {
		// Determine the minimum and maximum linear indices which are accessible by the array view:
		xmmv = minmaxViewBufferIndex( shx, sx, x.offset );

		// Determine whether we can ignore shape (and strides) and treat the ndarray as a linear one-dimensional strided array...
		if ( len === ( xmmv[1]-xmmv[0]+1 ) || ( isCmplx && len*2 === ( xmmv[1]-xmmv[0]+1 ) ) ) { // eslint-disable-line max-len
			// Note: the above is equivalent to @stdlib/ndarray/base/assert/is-contiguous, but in-lined so we can retain computed values...
			if ( iox === 1 ) {
				ox = xmmv[ 0 ];
			} else {
				ox = xmmv[ 1 ];
			}
			x.shape = [ len ];
			x.strides = [ ( isCmplx ) ? iox*2 : iox ];
			x.offset = ox;
			if ( x.accessorProtocol ) {
				return ACCESSOR_COUNT[ 1 ]( x );
			}
			if ( isCmplx ) {
				return COMPLEX_COUNT[ 1 ]( x );
			}
			return COUNT[ 1 ]( x );
		}
		// The ndarray is non-contiguous, so we cannot directly use one-dimensional array functionality...

		// Determine whether we can use simple nested loops...
		if ( ndims <= MAX_DIMS ) {
			// So long as iteration always moves in the same direction (i.e., no mixed sign strides), we can leverage cache-optimal (i.e., normal) nested loops without resorting to blocked iteration...
			if ( x.accessorProtocol ) {
				return ACCESSOR_COUNT[ ndims ]( x );
			}
			if ( isCmplx ) {
				return COMPLEX_COUNT[ ndims ]( x );
			}
			return COUNT[ ndims ]( x );
		}
		// Fall-through to blocked iteration...
	}
	// At this point, we're either dealing with a non-contiguous n-dimensional array or a high dimensional n-dimensional array, so our only hope is that we can still perform blocked iteration...

	// Determine whether we can perform blocked iteration...
	if ( ndims <= MAX_DIMS ) {
		if ( x.accessorProtocol ) {
			return BLOCKED_ACCESSOR_COUNT[ ndims-2 ]( x );
		}
		if ( isCmplx ) {
			return BLOCKED_COMPLEX_COUNT[ ndims-2 ]( x );
		}
		return BLOCKED_COUNT[ ndims-2 ]( x );
	}
	// Fall-through to linear view iteration without regard for how data is stored in memory (i.e., take the slow path)...
	if ( x.accessorProtocol ) {
		return accessorcountnd( x );
	}
	if ( isCmplx ) {
		return complexcountnd( x );
	}
	return countnd( x );
}
Counts the number of falsy elements in an ndarray.

## Notes

-   A provided ndarray should be an `object` with the following properties:

    -   **dtype**: data type.
    -   **data**: data buffer.
    -   **shape**: dimensions.
    -   **strides**: stride lengths.
    -   **offset**: index offset.
    -   **order**: specifies whether an ndarray is row-major (C-style) or column major (Fortran-style).

@param {ArrayLikeObject<Object>} arrays - array-like object containing one input array
@returns {NonNegativeInteger} result

@example
var Float64Array = require( '@stdlib/array/float64' );

// Create a data buffer:
var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 0.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] );

// Define the shape of the input array:
var shape = [ 3, 1, 2 ];

// Define the array strides:
var sx = [ 4, 4, 1 ];

// Define the index offset:
var ox = 1;

// Create the input ndarray-like object:
var x = {
    'dtype': 'float64',
    'data': xbuf,
    'shape': shape,
    'strides': sx,
    'offset': ox,
    'order': 'row-major'
};

// Perform operation:
var out = countFalsy( [ x ] );
// returns 1