All files / src/utils qr-polynomial.js

100% Statements 89/89
100% Branches 16/16
100% Functions 7/7
100% Lines 89/89

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 901x 1x 1x 1108x 1108x 1108x 1108x 1108x 1108x 1108x 1108x 1108x 1108x 1108x 1108x 140x 140x 1108x 1108x 1108x 9280x 9280x 1108x 1108x 1108x 1108x 1108x 1108x 1108x 86x 86x 1108x 1108x 1326x 1326x 1108x 1108x 1108x 1108x 1108x 1108x 464x 464x 464x 464x 464x 464x 4930x 9860x 9860x 4930x 464x 464x 464x 1108x 1108x 1108x 1108x 1108x 1108x 148x 148x 148x 148x 8x 8x 140x 140x 140x 140x 140x 148x 1708x 1708x 140x 140x 140x 140x 1108x 1x 1x 1x 1x 1x 1x 1x 1x 504x 1x  
import { gexp, glog } from './qr-math.util.js'
 
class QRPolynomial {
  /** @type {Readonly<number[]>} */
  array
 
  /**
   * @param {ArrayLike<number>} num - polynomial value
   * @param {number} shift - shift value
   */
  constructor (num, shift = 0) {
    let offset = 0
    const numLen = num.length
 
    while (offset < numLen && num[offset] === 0) {
      offset += 1
    }
    const lengthAfterOffset = numLen - offset
    const array = new Array(lengthAfterOffset + shift)
    for (let i = 0; i < lengthAfterOffset; i += 1) {
      array[i] = num[i + offset]
    }
 
    this.array = Object.freeze(array)
    return Object.freeze(this)
  }
 
  /** @param {number} index - value position */
  getAt (index) {
    return this.array[index]
  }
 
  get length () {
    return this.array.length
  }
 
  /**
   * @param {QRPolynomial} other - right side of operation
   * @returns {QRPolynomial} multiplication result
   */
  multiply (other) {
    const { length, array } = this
    const { length: otherLength, array: otherArray } = other
 
    const num = new Array(length + otherLength - 1)
 
    for (let i = 0; i < length; i += 1) {
      for (let j = 0; j < otherLength; j += 1) {
        num[i + j] ^= gexp(glog(array[i]) + glog(otherArray[j]))
      }
    }
 
    return new QRPolynomial(num, 0)
  }
 
  /**
   * @param {Readonly<QRPolynomial>} other - right side of operation
   * @returns {QRPolynomial} mod result
   */
  mod (other) {
    const { length, array } = this
    const { length: otherLength, array: otherArray } = other
 
    if (length - otherLength < 0) {
      return this
    }
 
    const ratio = glog(array[0]) - glog(otherArray[0])
 
    const num = Uint32Array.from(array)
 
    for (let i = 0; i < otherLength; i += 1) {
      num[i] ^= gexp(glog(otherArray[i]) + ratio)
    }
 
    // recursive call
    return new QRPolynomial(num, 0).mod(other)
  };
}
 
/**
 * Transforms array into a polynomial
 * @param {ArrayLike<number>} num - polynomial values
 * @param {number} [shift] - shift value
 * @returns {Readonly<QRPolynomial>} polynomial
 */
export function QrPolynomial (num, shift = 0) {
  return new QRPolynomial(num, shift)
};