function ndarray( dtype, buffer, shape, strides, offset, order, options ) {
	var ndims;
	var opts;
	var err;
	var sh;
	var st;

	if ( !(this instanceof ndarray) ) {
		if ( arguments.length < 7 ) {
			return new ndarray( dtype, buffer, shape, strides, offset, order );
		}
		return new ndarray( dtype, buffer, shape, strides, offset, order, options ); // eslint-disable-line max-len
	}
	if ( !isDataType( dtype ) ) {
		throw new TypeError( format( 'invalid argument. First argument must be a supported ndarray data type. Value: `%s`.', dtype ) );
	}
	if ( !isCollection( buffer ) ) {
		throw new TypeError( format( 'invalid argument. Second argument must be an array-like object, typed-array-like, or a Buffer. Value: `%s`.', buffer ) );
	} else if ( buffer.get && buffer.set && ( !isFunction( buffer.get ) || !isFunction( buffer.set ) ) ) { // eslint-disable-line max-len
		throw new TypeError( format( 'invalid argument. Second argument `get` and `set` properties must be functions. Value: `%s`.', buffer ) );
	}
	if ( !isNonNegativeIntegerArray( shape ) ) {
		if ( !isCollection( shape) || shape.length > 0 ) {
			throw new TypeError( format( 'invalid argument. Third argument must be an array-like object containing nonnegative integers. Value: `%s`.', shape ) );
		}
	}
	ndims = shape.length;
	if ( ndims > MAX_DIMS ) {
		throw new RangeError( format( 'invalid argument. Number of dimensions must not exceed %u due to stack limits. Value: `%u`.', MAX_DIMS, ndims ) );
	}
	if ( !isIntegerArray( strides ) ) {
		throw new TypeError( format( 'invalid argument. Fourth argument must be an array-like object containing integers. Value: `%s`.', strides ) );
	}
	if ( ndims > 0 ) {
		if ( strides.length !== ndims ) {
			throw new RangeError( format( 'invalid argument. Fourth argument length must match the number of dimensions. Expected number of dimensions: `%u`. Strides length: `%u`.', ndims, strides.length ) );
		}
	} else if ( strides.length !== 1 ) {
		throw new RangeError( 'invalid argument. Fourth argument length must be equal to 1 when creating a zero-dimensional ndarray.' );
	} else if ( strides[ 0 ] !== 0 ) {
		throw new RangeError( format( 'invalid argument. Fourth argument must contain a single element equal to 0. Value: `%d`.', strides[ 0 ] ) );
	}
	if ( !isNonNegativeInteger( offset ) ) {
		throw new TypeError( format( 'invalid argument. Fifth argument must be a nonnegative integer. Value: `%s`.', offset ) );
	}
	if ( !isOrder( order ) ) {
		throw new TypeError( format( 'invalid argument. Sixth argument must be a supported order. Value: `%s`.', order ) );
	}
	if ( ndims > 0 && !isBufferLengthCompatible( buffer.length, shape, strides, offset ) && numel( shape ) > 0 ) { // eslint-disable-line max-len
		throw new Error( 'invalid arguments. Input buffer is incompatible with the specified meta data. Ensure that the offset is valid with regard to the strides array and that the buffer has enough elements to satisfy the desired array shape.' );
	}
	opts = {};
	opts.mode = INDEX_MODE;
	opts.readonly = READONLY;
	if ( arguments.length > 6 ) {
		err = validate( opts, options );
		if ( err ) {
			throw err;
		}
	}
	this._mode = opts.mode;
	if ( opts.submode === void 0 ) {
		opts.submode = [ this._mode ];
	}
	this._submode = opts.submode;

	// Copy `shape` and `strides` to prevent external mutation:
	sh = copy( shape, ndims );
	st = copy( strides, ndims || 1 );

	// Call the parent constructor:
	parent.call( this, dtype, buffer, sh, st, offset, order );
	this._flags.READONLY = opts.readonly;

	return this;

	/* eslint-enable no-invalid-this */
}
ndarray constructor.

@constructor
@param {string} dtype - data type
@param {Collection} buffer - data buffer
@param {NonNegativeIntegerArray} shape - array shape
@param {IntegerArray} strides - array strides
@param {NonNegativeInteger} offset - index offset
@param {string} order - specifies whether an array is row-major (C-style) or column-major (Fortran-style)
@param {Options} [options] - function options
@param {string} [options.mode="throw"] - specifies how to handle indices which exceed array dimensions
@param {StringArray} [options.submode=["throw"]] - specifies how to handle subscripts which exceed array dimensions on a per dimension basis
@param {boolean} [options.readonly=false] - boolean indicating whether an array should be read-only
@throws {TypeError} `dtype` argument must be a supported ndarray data type
@throws {TypeError} `buffer` argument must be an array-like object, typed-array-like, or a Buffer
@throws {TypeError} `buffer` argument `get` and `set` properties must be functions
@throws {TypeError} `shape` argument must be an array-like object containing nonnegative integers
@throws {Error} `shape` argument length must equal the number of dimensions
@throws {TypeError} `strides` argument must be an array-like object containing integers
@throws {Error} `strides` argument length must equal the number of dimensions (except for zero-dimensional arrays; in which case, the `strides` argument length must be equal to `1`)
@throws {Error} for zero-dimensional ndarrays, the `strides` argument must contain a single element equal to `0`
@throws {TypeError} `offset` argument must be a nonnegative integer
@throws {TypeError} `order` argument must be a supported ndarray order
@throws {Error} `buffer` argument must be compatible with specified meta data
@throws {TypeError} options argument must be an object
@throws {TypeError} must provide valid options
@throws {RangeError} too many dimensions
@returns {ndarray} ndarray instance

@example
var buffer = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ];
var shape = [ 3, 2 ];
var strides = [ 2, 1 ];
var offset = 0;

var out = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );