UNPKG

4.03 kBJavaScriptView Raw
1'use strict'
2
3function factory (type, config, load, typed) {
4 const matrix = load(require('../../type/matrix/function/matrix'))
5 const latex = require('../../utils/latex')
6
7 const algorithm02 = load(require('../../type/matrix/utils/algorithm02'))
8 const algorithm03 = load(require('../../type/matrix/utils/algorithm03'))
9 const algorithm05 = load(require('../../type/matrix/utils/algorithm05'))
10 const algorithm11 = load(require('../../type/matrix/utils/algorithm11'))
11 const algorithm12 = load(require('../../type/matrix/utils/algorithm12'))
12 const algorithm13 = load(require('../../type/matrix/utils/algorithm13'))
13 const algorithm14 = load(require('../../type/matrix/utils/algorithm14'))
14
15 /**
16 * Calculates the modulus, the remainder of an integer division.
17 *
18 * For matrices, the function is evaluated element wise.
19 *
20 * The modulus is defined as:
21 *
22 * x - y * floor(x / y)
23 *
24 * See https://en.wikipedia.org/wiki/Modulo_operation.
25 *
26 * Syntax:
27 *
28 * math.mod(x, y)
29 *
30 * Examples:
31 *
32 * math.mod(8, 3) // returns 2
33 * math.mod(11, 2) // returns 1
34 *
35 * function isOdd(x) {
36 * return math.mod(x, 2) != 0
37 * }
38 *
39 * isOdd(2) // returns false
40 * isOdd(3) // returns true
41 *
42 * See also:
43 *
44 * divide
45 *
46 * @param {number | BigNumber | Fraction | Array | Matrix} x Dividend
47 * @param {number | BigNumber | Fraction | Array | Matrix} y Divisor
48 * @return {number | BigNumber | Fraction | Array | Matrix} Returns the remainder of `x` divided by `y`.
49 */
50 const mod = typed('mod', {
51
52 'number, number': _mod,
53
54 'BigNumber, BigNumber': function (x, y) {
55 return y.isZero() ? x : x.mod(y)
56 },
57
58 'Fraction, Fraction': function (x, y) {
59 return x.mod(y)
60 },
61
62 'SparseMatrix, SparseMatrix': function (x, y) {
63 return algorithm05(x, y, mod, false)
64 },
65
66 'SparseMatrix, DenseMatrix': function (x, y) {
67 return algorithm02(y, x, mod, true)
68 },
69
70 'DenseMatrix, SparseMatrix': function (x, y) {
71 return algorithm03(x, y, mod, false)
72 },
73
74 'DenseMatrix, DenseMatrix': function (x, y) {
75 return algorithm13(x, y, mod)
76 },
77
78 'Array, Array': function (x, y) {
79 // use matrix implementation
80 return mod(matrix(x), matrix(y)).valueOf()
81 },
82
83 'Array, Matrix': function (x, y) {
84 // use matrix implementation
85 return mod(matrix(x), y)
86 },
87
88 'Matrix, Array': function (x, y) {
89 // use matrix implementation
90 return mod(x, matrix(y))
91 },
92
93 'SparseMatrix, any': function (x, y) {
94 return algorithm11(x, y, mod, false)
95 },
96
97 'DenseMatrix, any': function (x, y) {
98 return algorithm14(x, y, mod, false)
99 },
100
101 'any, SparseMatrix': function (x, y) {
102 return algorithm12(y, x, mod, true)
103 },
104
105 'any, DenseMatrix': function (x, y) {
106 return algorithm14(y, x, mod, true)
107 },
108
109 'Array, any': function (x, y) {
110 // use matrix implementation
111 return algorithm14(matrix(x), y, mod, false).valueOf()
112 },
113
114 'any, Array': function (x, y) {
115 // use matrix implementation
116 return algorithm14(matrix(y), x, mod, true).valueOf()
117 }
118 })
119
120 mod.toTex = {
121 2: `\\left(\${args[0]}${latex.operators['mod']}\${args[1]}\\right)`
122 }
123
124 return mod
125
126 /**
127 * Calculate the modulus of two numbers
128 * @param {number} x
129 * @param {number} y
130 * @returns {number} res
131 * @private
132 */
133 function _mod (x, y) {
134 if (y > 0) {
135 // We don't use JavaScript's % operator here as this doesn't work
136 // correctly for x < 0 and x === 0
137 // see https://en.wikipedia.org/wiki/Modulo_operation
138 return x - y * Math.floor(x / y)
139 } else if (y === 0) {
140 return x
141 } else { // y < 0
142 // TODO: implement mod for a negative divisor
143 throw new Error('Cannot calculate mod for a negative divisor')
144 }
145 }
146}
147
148exports.name = 'mod'
149exports.factory = factory