galois-field.js 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. var BufferUtil = require('../utils/buffer')
  2. var EXP_TABLE = BufferUtil.alloc(512)
  3. var LOG_TABLE = BufferUtil.alloc(256)
  4. /**
  5. * Precompute the log and anti-log tables for faster computation later
  6. *
  7. * For each possible value in the galois field 2^8, we will pre-compute
  8. * the logarithm and anti-logarithm (exponential) of this value
  9. *
  10. * ref {@link https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders#Introduction_to_mathematical_fields}
  11. */
  12. ;(function initTables () {
  13. var x = 1
  14. for (var i = 0; i < 255; i++) {
  15. EXP_TABLE[i] = x
  16. LOG_TABLE[x] = i
  17. x <<= 1 // multiply by 2
  18. // The QR code specification says to use byte-wise modulo 100011101 arithmetic.
  19. // This means that when a number is 256 or larger, it should be XORed with 0x11D.
  20. if (x & 0x100) { // similar to x >= 256, but a lot faster (because 0x100 == 256)
  21. x ^= 0x11D
  22. }
  23. }
  24. // Optimization: double the size of the anti-log table so that we don't need to mod 255 to
  25. // stay inside the bounds (because we will mainly use this table for the multiplication of
  26. // two GF numbers, no more).
  27. // @see {@link mul}
  28. for (i = 255; i < 512; i++) {
  29. EXP_TABLE[i] = EXP_TABLE[i - 255]
  30. }
  31. }())
  32. /**
  33. * Returns log value of n inside Galois Field
  34. *
  35. * @param {Number} n
  36. * @return {Number}
  37. */
  38. exports.log = function log (n) {
  39. if (n < 1) throw new Error('log(' + n + ')')
  40. return LOG_TABLE[n]
  41. }
  42. /**
  43. * Returns anti-log value of n inside Galois Field
  44. *
  45. * @param {Number} n
  46. * @return {Number}
  47. */
  48. exports.exp = function exp (n) {
  49. return EXP_TABLE[n]
  50. }
  51. /**
  52. * Multiplies two number inside Galois Field
  53. *
  54. * @param {Number} x
  55. * @param {Number} y
  56. * @return {Number}
  57. */
  58. exports.mul = function mul (x, y) {
  59. if (x === 0 || y === 0) return 0
  60. // should be EXP_TABLE[(LOG_TABLE[x] + LOG_TABLE[y]) % 255] if EXP_TABLE wasn't oversized
  61. // @see {@link initTables}
  62. return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]]
  63. }