aureooms/js-integer-big-endian

View on GitHub
src/core/convert/_convert_to_smaller_slow.js

Summary

Maintainability
A
2 hrs
Test Coverage
import assert from 'assert';

import _idivmod_limb from '../arithmetic/div/_idivmod_limb.js';
import _alloc from '../array/_alloc.js';
import _copy from '../array/_copy.js';

import _trim_positive from './_trim_positive.js';

/**
 *
 * O(N^2). f > t.
 *
 * |A| >= 1
 * |B| is large enough to hold the result
 *
 * @param {Number} f the base to convert from
 * @param {Number} t the base to convert to
 * @param {Array} a the origin array
 * @param {Number} ai start offset in the origin array
 * @param {Number} aj end offset in the origin array
 * @param {Array} b the destination array
 * @param {Number} bi start offset in the destination array
 * @param {Number} bj end offset in the destination array
 */

export default function _convert_to_smaller_slow(f, t, a, ai, aj, b, bi, bj) {
    assert(f >= t);
    assert(ai >= 0 && aj <= a.length);
    assert(bi >= 0 && bj <= b.length);
    assert(aj - ai >= 1);
    assert(bj - bi >= aj - ai);

    let batch = 1;
    let shift = t;
    for (; shift * t <= f; shift *= t, ++batch);

    const m = aj - ai;
    let q = _alloc(m);
    let r = _alloc(m); // NOTE that this copy is unnecessary when
    _copy(a, ai, aj, r, 0); // Called from parse since we can discard it.

    let i = 0;

    while (true) {
        _idivmod_limb(f, shift, r, i, m, q, i);

        const end = Math.max(bi, bj - batch);
        let block = r[m - 1];

        do {
            b[--bj] = block % t;
            block = (block / t) | 0;
        } while (bj > end);

        i = _trim_positive(q, i, m);
        if (i === m) return;

        // _copy( q , i , m , r , i ) ;
        const tmp = q;
        q = r;
        r = tmp;
    }
}