function nditerColumnEntries( x ) {
	var options;
	var shape;
	var ndims;
	var opts;
	var iter;
	var FLG;
	var idx;
	var dim;
	var S0;
	var N;
	var i;

	if ( !isndarrayLike( x ) ) {
		throw new TypeError( format( 'invalid argument. First argument must be an ndarray. Value: `%s`.', x ) );
	}
	opts = {
		'writable': false
	};
	if ( arguments.length > 1 ) {
		options = arguments[ 1 ];
		if ( !isPlainObject( options ) ) {
			throw new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', options ) );
		}
		if ( hasOwnProp( options, 'readonly' ) ) {
			if ( !isBoolean( options.readonly ) ) {
				throw new TypeError( format( 'invalid option. `%s` option must be a boolean. Option: `%s`.', 'readonly', options.readonly ) );
			}
			opts.writable = !options.readonly;
			if ( opts.writable && isReadOnly( x ) ) {
				throw new Error( format( 'invalid option. Cannot write to read-only array.' ) );
			}
		}
	}
	// Retrieve input array meta data:
	shape = getShape( x );
	ndims = shape.length;

	// Ensure that the input array has sufficient dimensions...
	if ( ndims < 2 ) {
		throw new TypeError( 'invalid argument. First argument must be an ndarray having at least two dimensions.' );
	}

	// Check whether the input array is empty...
	N = numel( shape );
	if ( N === 0 ) {
		FLG = true;
	}
	// Compute the number of columns across all stacks of matrices:
	N /= shape[ ndims-2 ];
	dim = ndims - 1;
	S0 = shape[ dim ];

	// Initialize a counter:
	i = -1;

	// Initialize an index array:
	idx = zeros( ndims );

	// Set the second-to-last element to `null` to indicate that we want a full "slice" for the second-to-last dimension:
	idx[ ndims-2 ] = null;

	// Create an iterator protocol-compliant object:
	iter = {};
	setReadOnly( iter, 'next', next );
	setReadOnly( iter, 'return', end );

	// If an environment supports `Symbol.iterator`, make the iterator iterable:
	if ( iteratorSymbol ) {
		setReadOnly( iter, iteratorSymbol, factory );
	}
	return iter;

	/**
	* Returns an iterator protocol-compliant object containing the next iterated value.
	*
	* @private
	* @returns {Object} iterator protocol-compliant object
	*/
	function next() {
		var indices;
		var s;
		var j;
		i += 1;
		if ( FLG || i >= N ) {
			return {
				'done': true
			};
		}
		// Cache the current state of the index array:
		indices = idx.slice();

		// Create a multi-slice for the current view:
		s = args2multislice( idx );

		// Update the index array:
		j = ( idx[ dim ] + 1 ) % S0;
		idx[ dim ] = j;
		if ( j === 0 ) {
			// If we've iterated over all the columns in the current matrix, move on to the next matrix in the stack:
			idx = nextCartesianIndex( shape, 'row-major', idx, dim-2, idx );
		}
		// Return the next row entry:
		return {
			'value': [ indices, slice( x, s, true, opts.writable ) ],
			'done': false
		};
	}

	/**
	* Finishes an iterator.
	*
	* @private
	* @param {*} [value] - value to return
	* @returns {Object} iterator protocol-compliant object
	*/
	function end( value ) {
		FLG = true;
		if ( arguments.length ) {
			return {
				'value': value,
				'done': true
			};
		}
		return {
			'done': true
		};
	}

	/**
	* Returns a new iterator.
	*
	* @private
	* @returns {Iterator} iterator
	*/
	function factory() {
		return nditerColumnEntries( x, opts );
	}
}
Returns an iterator which returns `[index, column]` pairs for each column in a matrix (or stack of matrices).

@param {ndarray} x - input array
@param {Options} [options] - function options
@param {boolean} [options.readonly=true] - boolean indicating whether returned views should be read-only
@throws {TypeError} first argument must be an ndarray
@throws {TypeError} first argument must have at least two dimensions
@throws {TypeError} options argument must be an object
@throws {TypeError} must provide valid options
@throws {Error} cannot write to a read-only array
@returns {Iterator} iterator

@example
var ndarray2array = require( '@stdlib/ndarray/to-array' );
var array = require( '@stdlib/ndarray/array' );

var x = array( [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 5, 6 ], [ 7, 8 ] ] ] );
// returns <ndarray>

var iter = nditerColumnEntries( x );

var v = iter.next().value;
// returns [...]

var idx = v[ 0 ];
// returns [ 0, null, 0 ]

var col = ndarray2array( v[ 1 ] );
// returns [ 1, 3 ]

v = iter.next().value;
// returns [...]

idx = v[ 0 ];
// returns [ 0, null, 1 ]

col = ndarray2array( v[ 1 ] );
// returns [ 2, 4 ]

// ...