function assign( arrays ) {
	var ndims;
	var xmmv;
	var ymmv;
	var shx;
	var shy;
	var iox;
	var ioy;
	var len;
	var ord;
	var sx;
	var sy;
	var ox;
	var oy;
	var ns;
	var x;
	var y;
	var d;
	var i;

	// Unpack the ndarrays and standardize ndarray meta data:
	x = ndarray2object( arrays[ 0 ] );
	y = ndarray2object( arrays[ 1 ] );

	// Check for known array types which can be reinterpreted for better iteration performance...
	if ( isBooleanArray( x.data ) && isBooleanArray( y.data ) ) {
		x = boolean2uint8( x );
		y = boolean2uint8( y );
	} else if ( isComplexArray( x.data ) && isComplexArray( y.data ) ) {
		x = complex2real( x );
		y = complex2real( y );
	}
	// Determine whether we are casting a real data type to a complex data type and we need to use a specialized accessor (note: we don't support the other way, complex-to-real, as this is not an allowed (mostly) safe cast; note: we cannot create a specialized view for assigning only real components, as the imaginary component for each element in `y` also needs to be set to zero and while we could perform two passes, it's not clear it's worth the effort)...
	else if ( isRealDataType( x.dtype ) && isComplexDataType( y.dtype ) ) {
		x.accessorProtocol = true;
		x.accessors[ 0 ] = castReturn( x.accessors[ 0 ], 2, complexCtors( y.dtype ) ); // eslint-disable-line max-len
	}
	// Verify that the input and output arrays have the same number of dimensions...
	shx = x.shape;
	shy = y.shape;
	ndims = shx.length;
	if ( ndims !== shy.length ) {
		throw new Error( 'invalid arguments. Arrays must have the same number of dimensions (i.e., same rank). ndims(x) == '+ndims+'. ndims(y) == '+shy.length+'.' );
	}
	// Determine whether we can avoid iteration altogether...
	if ( ndims === 0 ) {
		if ( x.accessorProtocol || y.accessorProtocol ) {
			return ACCESSOR_ASSIGN[ ndims ]( x, y );
		}
		return ASSIGN[ ndims ]( x, y );
	}
	// Verify that the input and output arrays have the same dimensions...
	len = 1; // number of elements
	ns = 0;  // number of singleton dimensions
	for ( i = 0; i < ndims; i++ ) {
		d = shx[ i ];
		if ( d !== shy[ i ] ) {
			throw new Error( 'invalid arguments. Arrays must have the same shape.' );
		}
		// 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 empty ndarrays...
	if ( len === 0 ) {
		return;
	}
	// Determine whether the ndarrays are one-dimensional and thus readily translate to one-dimensional strided arrays...
	if ( ndims === 1 ) {
		if ( x.accessorProtocol || y.accessorProtocol ) {
			return ACCESSOR_ASSIGN[ ndims ]( x, y );
		}
		return ASSIGN[ ndims ]( x, y );
	}
	sx = x.strides;
	sy = y.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 the ndarrays as being equivalent to one-dimensional strided arrays...
	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] ];
		y.shape = x.shape;
		x.strides = [ sx[i] ];
		y.strides = [ sy[i] ];
		if ( x.accessorProtocol || y.accessorProtocol ) {
			return ACCESSOR_ASSIGN[ 1 ]( x, y );
		}
		return ASSIGN[ 1 ]( x, y );
	}
	iox = iterationOrder( sx ); // +/-1
	ioy = iterationOrder( sy ); // +/-1

	// Determine whether we can avoid blocked iteration...
	ord = strides2order( sx );
	if ( iox !== 0 && ioy !== 0 && ord === strides2order( sy ) ) {
		// Determine the minimum and maximum linear indices which are accessible by the array views:
		xmmv = minmaxViewBufferIndex( shx, sx, x.offset );
		ymmv = minmaxViewBufferIndex( shy, sy, y.offset );

		// Determine whether we can ignore shape (and strides) and treat the ndarrays as linear one-dimensional strided arrays...
		if ( len === ( xmmv[1]-xmmv[0]+1 ) && len === ( ymmv[1]-ymmv[0]+1 ) ) {
			// 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 ];
			}
			if ( ioy === 1 ) {
				oy = ymmv[ 0 ];
			} else {
				oy = ymmv[ 1 ];
			}
			x.shape = [ len ];
			y.shape = x.shape;
			x.strides = [ iox ];
			y.strides = [ ioy ];
			x.offset = ox;
			y.offset = oy;
			if ( x.accessorProtocol || y.accessorProtocol ) {
				return ACCESSOR_ASSIGN[ 1 ]( x, y );
			}
			return ASSIGN[ 1 ]( x, y );
		}
		// At least one 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 for each respective array 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 || y.accessorProtocol ) {
				return ACCESSOR_ASSIGN[ ndims ]( x, y, ord === 1 );
			}
			return ASSIGN[ ndims ]( x, y, ord === 1 );
		}
		// Fall-through to blocked iteration...
	}
	// At this point, we're either dealing with non-contiguous n-dimensional arrays, high dimensional n-dimensional arrays, and/or arrays having differing memory layouts, 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 || y.accessorProtocol ) {
			return BLOCKED_ACCESSOR_ASSIGN[ ndims-2 ]( x, y );
		}
		return BLOCKED_ASSIGN[ ndims-2 ]( x, y );
	}
	// Fall-through to linear view iteration without regard for how data is stored in memory (i.e., take the slow path)...
	if ( x.accessorProtocol || y.accessorProtocol ) {
		return accessorassignnd( x, y );
	}
	assignnd( x, y );
}
Assigns elements in an input ndarray to elements in an output ndarray.

## Notes

-   Each 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 and one output array
@throws {Error} arrays must have the same number of dimensions
@throws {Error} arrays must have the same shape
@returns {void}

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

// Create data buffers:
var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] );
var ybuf = new Float64Array( 6 );

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

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

// Define the index offsets:
var ox = 1;
var oy = 0;

// Create the input and output ndarray-like objects:
var x = {
    'dtype': 'float64',
    'data': xbuf,
    'shape': shape,
    'strides': sx,
    'offset': ox,
    'order': 'row-major'
};
var y = {
    'dtype': 'float64',
    'data': ybuf,
    'shape': shape,
    'strides': sy,
    'offset': oy,
    'order': 'row-major'
};

// Copy elements:
assign( [ x, y ] );

console.log( y.data );
// => <Float64Array>[ 2.0, 3.0, 6.0, 7.0, 10.0, 11.0 ]