function nCartesianProduct( x1, x2 ) {
	var nargs;
	var dims;
	var arr;
	var out;
	var tmp;
	var arg;
	var idx;
	var N;
	var s;
	var i;
	var j;
	var k;

	nargs = arguments.length;

	// Initialize the list of arrays:
	arr = [ x1, x2 ];

	// Initialize the list of array dimensions (equivalent to ndarray shape):
	dims = [ x1.length, x2.length ];

	// Initialize a list of indices for indexing into each array (equivalent to ndarray subscripts):
	idx = [ 0, 0 ];

	// Compute the total number of ordered tuples:
	N = dims[ 0 ] * dims[ 1 ];

	// Update loop variables for any additional arrays...
	for ( i = 2; i < nargs; i++ ) {
		arg = arguments[ i ];
		arr.push( arg );
		dims.push( arg.length );
		idx.push( 0 );
		N *= dims[ i ];
	}
	// Compute the n-fold Cartesian product...
	out = [];
	for ( i = 0; i < N; i++ ) {
		// Resolve a linear index to array indices (logic is equivalent to what is found in ndarray/base/ind2sub for an ndarray stored in row-major order; see https://github.com/stdlib-js/stdlib/blob/215ca5355f3404f15996fd0ced58a98e46f22be6/lib/node_modules/%40stdlib/ndarray/base/ind2sub/lib/assign.js)...
		k = i;
		for ( j = nargs-1; j >= 0; j-- ) {
			s = k % dims[ j ];
			k -= s;
			k /= dims[ j ];
			idx[ j ] = s;
		}
		// Generate the next ordered tuple...
		tmp = [];
		for ( j = 0; j < nargs; j++ ) {
			tmp.push( arr[ j ][ idx[ j ] ] );
		}
		out.push( tmp );
	}
	return out;
}
Returns the n-fold Cartesian product.

## Notes

-   The main insight of this implementation is that the n-fold Cartesian product can be presented as an n-dimensional array stored in row-major order. As such, we can

    -   Compute the total number of tuples, which is simply the product of the size of each provided array (set). For n-dimensional arrays, this is the equivalent of computing the product of array dimensions to determine the total number of elements.
    -   Initialize an array for storing indices for indexing into each provided array. For n-dimensional arrays, the index array is equivalent to an array of subscripts for indexing into each dimension.
    -   For the outermost loop, treat the loop index as a linear index into an n-dimensional array and resolve the corresponding subscripts.
    -   Continue iterating until all tuples have been generated.

@param {ArrayLikeObject} x1 - first input array
@param {ArrayLikeObject} x2 - second input array
@param {ArrayLikeObject} [...args] - additional input arrays
@returns {Array<Array>} list of ordered tuples comprising the n-fold Cartesian product

@example
var x1 = [ 1, 2, 3 ];
var x2 = [ 4, 5 ];

var out = nCartesianProduct( x1, x2 );
// returns [ [ 1, 4 ], [ 1, 5 ], [ 2, 4 ], [ 2, 5 ], [ 3, 4 ], [ 3, 5 ] ]