Home Manual Reference Source

src/array/core/stable.js

import assert from 'assert';
import {_identity} from '@combinatorics/permutation';
import alloc from './alloc.js';
import zeros from './zeros.js';
import reset from './reset.js';
import cumulativeHistogram from './cumulativeHistogram.js';
import rank from './rank.js';
import permute from './permute.js';
import compose from './compose.js';

/**
 * O(kM + kN) time where k is the number of arrays, M is the radix, and
 * N is the length of each array. The product kN corresponds to the input size.
 */
const stable = (M, current, rest) => {
	console.debug('stable', M, current, rest);
	assert(current !== undefined);
	const N = current.length;
	const permutation1 = alloc(N);
	_identity(permutation1, N); // TODO Not needed if rest is empty (k=1)
	const ch = zeros(M + 1); // O(M)
	// eslint-disable-next-line no-constant-condition
	while (true) {
		// Repeated k times.
		cumulativeHistogram(current, 0, N, ch, 1); // O(N)
		console.debug('stable step', current, ch);
		assert(ch[0] === 0);
		const permutation2 = alloc(N);
		rank(ch, current, 0, current.length, permutation2); // O(N)
		compose(permutation2, permutation1);
		const {value: next, done} = rest.next();
		if (done) {
			return permutation1;
		}

		assert(next.length === N);
		permute(permutation1, next, 0, N, current, 0);
		reset(ch); // O(M)
	}
};

export default stable;