aureooms/js-integer-big-endian

View on GitHub
src/core/arithmetic/pow/_pow_double_recursive.js

Summary

Maintainability
A
1 hr
Test Coverage
import assert from 'assert';

import jz from '../../../api/compare/jz.js';
import _copy from '../../array/_copy.js';
import _zeros from '../../array/_zeros.js';
import _mul from '../mul/_mul.js';

/**
 * Computes <code>pow(a,x) = a^x</code> using exponentiation by squaring.
 * Writes result to output array.
 *
 * /!\ |A| >= 1, |C| >= 1, |C| >= |A| * x, |C| = 000...0
 *
 * @param {Number} r The base to work with.
 * @param {Number} x The power to raise <code>a</code> to.
 * @param {Array} a The base array.
 * @param {Number} ai <code>a</code> left.
 * @param {Number} aj <code>b</code> right.
 * @param {Array} c The output array.
 * @param {Number} ci <code>a</code> left.
 * @param {Number} cj <code>b</code> right.
 */
export default function _pow_double_recursive(r, x, a, ai, aj, c, ci, cj) {
    assert(r >= 2);
    assert(x >= 0);
    assert(ai >= 0 && aj <= a.length);
    assert(ci >= 0 && cj <= c.length);
    assert(aj - ai >= 1);
    assert(cj - ci >= 1);
    assert(cj - ci >= (aj - ai) * x);
    assert(jz(c, ci, cj));

    if (x === 0) {
        c[cj - 1] = 1;
    } else if (x === 1) {
        _copy(a, ai, aj, c, cj - (aj - ai));
    } else if (x & 1) {
        const p = x - 1;
        const n = (aj - ai) * p;
        const u = _zeros(n);

        _pow_double_recursive(r, p, a, ai, aj, u, 0, n);
        _mul(r, u, 0, n, a, ai, aj, c, ci, cj); // Largest must be put first
    } else {
        const p = (x / 2) | 0;
        const n = (aj - ai) * p;
        const u = _zeros(n);

        _pow_double_recursive(r, p, a, ai, aj, u, 0, n);
        _mul(r, u, 0, n, u, 0, n, c, ci, cj); // TODO use squaring function here
    }
}