aureooms/js-integer-big-endian

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

Summary

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

import _iadd_limb from '../arithmetic/add/_iadd_limb.js';
import _imul_limb from '../arithmetic/mul/_imul_limb.js';

/**
 *
 * O(N^2). f < t.
 *
 * @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_larger_slow(f, t, a, ai, aj, b, bi, bj) {
    assert(f >= 2);
    assert(f <= t);
    assert(ai >= 0 && aj <= a.length);
    assert(bi >= 0 && bj <= b.length);
    assert(aj - ai >= 0);
    assert(bj - bi >= 0);

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

    const rounds = ((aj - ai) / batch) | 0;
    const first = (aj - ai) % batch;

    if (first > 0) {
        let w1 = a[ai];
        for (let j = 1; j < first; ++j) {
            w1 *= f;
            w1 += a[ai + j];
        }

        b[bj - 1] = w1;
    }

    const _ai = ai + first;
    let _bi = bj - 1;

    for (let i = 0; i < rounds; ++i) {
        if (b[_bi] !== 0 && _bi > bi) --_bi;
        _imul_limb(t, shift, b, _bi, bj);
        if (b[_bi] !== 0 && _bi > bi) --_bi;
        let w = 0;
        let j = _ai + i * batch;
        const _end = j + batch;
        do {
            w *= f;
            w += a[j];
        } while (++j < _end);

        _iadd_limb(t, w, b, _bi, bj);
    }
}