atomic-fns 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/.editorconfig +12 -0
  2. package/.eslintignore +1 -0
  3. package/.eslintrc.json +34 -0
  4. package/.prettierrc +19 -0
  5. package/LICENSE +201 -0
  6. package/README.md +1 -0
  7. package/build/collections.d.ts +204 -0
  8. package/build/collections.js +545 -0
  9. package/build/datetime.d.ts +1 -0
  10. package/build/datetime.js +1 -0
  11. package/build/functools.d.ts +36 -0
  12. package/build/functools.js +79 -0
  13. package/build/globals.d.ts +175 -0
  14. package/build/globals.js +332 -0
  15. package/build/index.d.ts +7 -0
  16. package/build/index.js +7 -0
  17. package/build/itertools.d.ts +16 -0
  18. package/build/itertools.js +102 -0
  19. package/build/math.d.ts +16 -0
  20. package/build/math.js +67 -0
  21. package/build/objects.d.ts +0 -0
  22. package/build/objects.js +1 -0
  23. package/build/operators.d.ts +29 -0
  24. package/build/operators.js +128 -0
  25. package/build/random.d.ts +5 -0
  26. package/build/random.js +28 -0
  27. package/build/strings.d.ts +0 -0
  28. package/build/strings.js +1 -0
  29. package/build/util.d.ts +0 -0
  30. package/build/util.js +1 -0
  31. package/jasmine.json +14 -0
  32. package/package.json +71 -0
  33. package/src/collections.ts +614 -0
  34. package/src/datetime.ts +1 -0
  35. package/src/functools.ts +89 -0
  36. package/src/globals.d.ts +5 -0
  37. package/src/globals.ts +377 -0
  38. package/src/index.ts +7 -0
  39. package/src/itertools.ts +113 -0
  40. package/src/math.ts +73 -0
  41. package/src/objects.ts +0 -0
  42. package/src/operators.ts +126 -0
  43. package/src/random.ts +29 -0
  44. package/src/strings.ts +0 -0
  45. package/src/util.ts +0 -0
  46. package/tests/collections.spec.ts +199 -0
  47. package/tests/globals.spec.ts +232 -0
  48. package/tests/itertools.spec.ts +87 -0
  49. package/tests/operators.spec.ts +62 -0
  50. package/tsconfig.json +103 -0
  51. package/tsconfig.node.json +18 -0
  52. package/tsconfig.xo.json +9 -0
package/src/globals.ts ADDED
@@ -0,0 +1,377 @@
1
+ export type Comp = (x, y) => number
2
+
3
+ export type Function = (...args) => any
4
+
5
+ export type Iteratee = (value, key?, arr?) => any
6
+
7
+ export const True = () => true
8
+
9
+ export const False = () => false
10
+
11
+ /**
12
+ * A custom error class that inherits from the Error object.
13
+ *
14
+ * @export
15
+ * @class CustomError
16
+ * @extends {Error}
17
+ */
18
+ export class CustomError extends Error {
19
+ /**
20
+ * Returns a new CustomError with the specified message.
21
+ * @param message
22
+ * @constructor
23
+ */
24
+ constructor(message?) {
25
+ super(message)
26
+ this.name = this.constructor.name
27
+ if (typeof Error.captureStackTrace === 'function') {
28
+ Error.captureStackTrace(this, this.constructor)
29
+ } else {
30
+ this.stack = new Error(message).stack
31
+ }
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Custom error to signal an invalid index access.
37
+ * @extends {CustomError}
38
+ */
39
+ export class IndexError extends CustomError {}
40
+
41
+ /**
42
+ * Raised when a system function returns an I/O failure such as "file not found"
43
+ * or "disk full".
44
+ * @extends {CustomError}
45
+ */
46
+ export class IOError extends CustomError {}
47
+
48
+ /**
49
+ * Custom error to signal an invalid key access.
50
+ * @extends {CustomError}
51
+ */
52
+ export class KeyError extends CustomError {}
53
+
54
+ /**
55
+ * Custom error to signal an invalid operation.
56
+ * @extends {CustomError}
57
+ */
58
+ export class NotImplementedError extends CustomError {}
59
+
60
+ /**
61
+ * Custom error to signal an invalid value.
62
+ * @extends {CustomError}
63
+ */
64
+ export class ValueError extends CustomError {}
65
+
66
+ /**
67
+ * Raised when the second argument of a division or modulo operation is zero.
68
+ * @extends {CustomError}
69
+ */
70
+ export class ZeroDivisionError extends CustomError {}
71
+
72
+ /**
73
+ * Returns the true type of any value with correct detection for null, Array,
74
+ * Object, Promise, Symbol, and NaN.
75
+ *
76
+ * @export
77
+ * @param {*} value
78
+ * @return
79
+ */
80
+ export function type(value) {
81
+ const result = typeof value
82
+ if (result === 'object') {
83
+ if (value) {
84
+ if (value instanceof String) return 'string'
85
+ if (value instanceof Boolean) return 'boolean'
86
+ if (value instanceof Function) return 'function'
87
+ // IE improperly marshals typeof across execution contexts, but a
88
+ // cross-context object will still return false for "instanceof Object".
89
+ if (value instanceof Array) return 'array'
90
+
91
+ const className = str(value)
92
+ // In Firefox 3.6, attempting to access iframe window objects' length
93
+ // property throws an NS_ERROR_FAILURE, so we need to special-case it
94
+ // here.
95
+ if (className === '[object Window]') return 'object'
96
+
97
+ // We cannot always use constructor === Array or instanceof Array because
98
+ // different frames have different Array objects.
99
+ // Mark Miller noticed that Object.prototype.toString
100
+ // allows access to the unforgeable [[Class]] property.
101
+ // 15.2.4.2 Object.prototype.toString ( )
102
+ // When the toString method is called, the following steps are taken:
103
+ // 1. Get the [[Class]] property of this object.
104
+ // 2. Compute a string value by concatenating the three strings
105
+ // "[object ", Result(1), and "]".
106
+ // 3. Return Result(2).
107
+ // and this behavior survives the destruction of the execution context.
108
+ if (className.endsWith('Array]') || Array.isArray(value)) {
109
+ return 'array'
110
+ }
111
+ // HACK: There is still an array case that fails.
112
+ // function ArrayImpostor() {}
113
+ // ArrayImpostor.prototype = [];
114
+ // var impostor = new ArrayImpostor;
115
+ // this can be fixed by getting rid of the fast path
116
+ // (value instanceof Array) and solely relying on
117
+ // (value && Object.prototype.toString.vall(value) === '[object Array]')
118
+ // but that would require many more function calls and is not warranted
119
+ // unless closure code is receiving objects from untrusted sources.
120
+
121
+ // IE in cross-window calls does not correctly marshal the function type
122
+ // (it appears just as an object) so we cannot use just typeof val ==
123
+ // 'function'. However, if the object has a call property, it is a
124
+ // function.
125
+ if (className.endsWith('Function]') || typeof value.call === 'function') {
126
+ return 'function'
127
+ }
128
+ if (className === '[object Promise]' || value instanceof Promise) {
129
+ return 'promise'
130
+ }
131
+ if (className === '[object Symbol]') {
132
+ return 'symbol'
133
+ }
134
+ } else {
135
+ return 'null'
136
+ }
137
+ } else if (result === 'function' && typeof value.call === 'undefined') {
138
+ // In Safari typeof nodeList returns 'function', and on Firefox typeof
139
+ // behaves similarly for HTML{Applet,Embed,Object}, Elements and RegExps. We
140
+ // would like to return object for those and we can detect an invalid
141
+ // function by making sure that the function object has a call method.
142
+ return 'object'
143
+ } else if (Number.isNaN(value)) return 'NaN'
144
+ return result
145
+ }
146
+
147
+ /** Same as calling toString() */
148
+ export const str = (x): string => {
149
+ if (isNull(x)) return ''
150
+ return x.toString?.() ?? String(x)
151
+ }
152
+
153
+ /** Check if value is a boolean type */
154
+ export const isBool = (x) => type(x) === 'boolean'
155
+
156
+ /** Check if value is an object type */
157
+ export const isObject = (x) => typeof x === 'object' && type(x) === 'object'
158
+
159
+ /** Check if value is a string type */
160
+ export const isString = (x) => type(x) === 'string'
161
+
162
+ /** Check if value is an Array type */
163
+ export const isArray = (x) => type(x) === 'array'
164
+
165
+ /** Check if value is Array-like type.
166
+ * A value is considered array-like if it's not a function and has a
167
+ * `.length` number property.
168
+ */
169
+ export const isArrayLike = (x) => {
170
+ const T = type(x)
171
+ return T === 'array' || (T === 'object' && isNumber(x.length))
172
+ }
173
+
174
+ /** Check if value is a function type */
175
+ export const isFunc = (x) => type(x) === 'function'
176
+
177
+ /** Check if value is a number type */
178
+ export const isNumber = (x) => type(x) === 'number'
179
+
180
+ /** Check if value is a Bigint type */
181
+ export const isBigint = (x) => type(x) === 'bigint'
182
+
183
+ /** Check if value is NaN based on `Number.isNaN` */
184
+ export const isNaN = (x) => Number.isNaN(x)
185
+
186
+ /** Check if value is a Promise type */
187
+ export const isPromise = (x) => type(x) === 'promise'
188
+
189
+ /** Check if value is an async function type */
190
+ export const isAsync = (x) => x?.constructor.name === 'AsyncFunction'
191
+
192
+ /** Check if value is a generator function type */
193
+ export const isGenerator = (x) => {
194
+ return x?.constructor.constructor?.name === 'GeneratorFunction'
195
+ }
196
+
197
+ /** Check if value is null or undefined */
198
+ export const isNull = (x) => x == null
199
+
200
+ /** Check if value is not null or undefined */
201
+ export const notNull = (x) => x != null
202
+
203
+ export function len(x) {
204
+ if (isNumber(x?.length)) {
205
+ return x.length
206
+ }
207
+ if (isFunc(x?.size)) {
208
+ return x.size()
209
+ }
210
+ if (isObject(x)) {
211
+ return Object.keys(x).length
212
+ }
213
+ }
214
+
215
+ /** Returns true for objects without length or falsey values. */
216
+ export const isEmpty = (x) => (len(x) === 0 ? true : !x)
217
+
218
+ /** Check if value is a Symbol type */
219
+ export const isSymbol = (x) => type(x) === 'symbol'
220
+
221
+ /**
222
+ * Generates a unique ID using random numbers.
223
+ * If prefix is given, the ID is appended to it
224
+ */
225
+ export const uniqueId = (pre: string = '') =>
226
+ // @ts-expect-error
227
+ (pre || 0) + ((Math.random() * 1e10) >>> 0)
228
+
229
+ /**
230
+ * Checks if `obj.key` is a function, and calls it with any `args`.
231
+ *
232
+ * @export
233
+ * @param {*} obj
234
+ * @param {PropertyKey} key
235
+ * @param {...any[]} args
236
+ * @return `obj.key(...args)`
237
+ */
238
+ export function call(obj: any, key: PropertyKey, ...args: any[]) {
239
+ if (isFunc(get(obj, key))) {
240
+ return obj[key](...args)
241
+ }
242
+ }
243
+
244
+ /** Convert number to unicode character */
245
+ export const chr = (x: number) => String.fromCodePoint(x)
246
+
247
+ /** Convert character to Unicode code point */
248
+ export const ord = (x: string) => x.charCodeAt(0)
249
+
250
+ /** `Object.keys(x)` */
251
+ export const keys = (x) => Object.keys(x)
252
+
253
+ /** `Object.values(x)` */
254
+ export const values = (x) => Object.values(x)
255
+
256
+ /**
257
+ * Round `x` to the number of digits after the decimal point. If `digits` is
258
+ * omitted, it returns the nearest integer to x.
259
+ * @export
260
+ * @param {number} x
261
+ * @param {number} [digits=0]
262
+ */
263
+ export function round(x: number, digits = 0) {
264
+ const base = 10 ** digits
265
+ return Math.round(x * base) / base
266
+ }
267
+
268
+ export const floor = (x: number) => Math.floor(x)
269
+
270
+ export const ceil = (x: number) => Math.ceil(x)
271
+
272
+ /**
273
+ * Yields elements like [index, item] from an iterable.
274
+ *
275
+ * @export
276
+ * @template T
277
+ * @param {Iterable<T>} iterable
278
+ */
279
+ export function* enumerate<T = unknown>(iterable: Iterable<T>) {
280
+ let i = 0
281
+ for (const item of iterable) {
282
+ yield [i++, item]
283
+ }
284
+ }
285
+
286
+ export const has = (obj, attr: PropertyKey) => obj && attr in obj
287
+
288
+ /**
289
+ * Check if the attribute is present in the object, or return optional default.
290
+ *
291
+ * @export
292
+ * @param {*} obj
293
+ * @param {PropertyKey} key
294
+ * @param {*} [value=undefined]
295
+ * @return The property value or default value
296
+ */
297
+ export function get(obj: any, key: PropertyKey | PropertyKey[], value: any = undefined) {
298
+ if (obj == null) {
299
+ return value ?? obj
300
+ }
301
+
302
+ let paths = Array.isArray(key) ? key : [key]
303
+ if (typeof key === 'string') {
304
+ paths = key.split('.')
305
+ }
306
+
307
+ try {
308
+ let result = obj
309
+ for (const k of paths) {
310
+ result = result[k]
311
+ }
312
+ return result ?? value
313
+ } catch (error) {
314
+ return value
315
+ }
316
+ }
317
+
318
+ export function del(x, attr) {
319
+ if (x != null) delete x[attr]
320
+ return x
321
+ }
322
+
323
+ export function set(self: any, attr: PropertyKey, value, writable = false, enumerable = false) {
324
+ return Object.defineProperty(self, attr, {
325
+ value,
326
+ enumerable,
327
+ writable
328
+ })
329
+ }
330
+
331
+ export const HASH_KEY = Symbol.for('HASH_KEY')
332
+
333
+ export function hash(obj) {
334
+ if (typeof obj === 'string') {
335
+ return hashCode(obj)
336
+ }
337
+
338
+ if (typeof obj === 'object') {
339
+ if (obj[HASH_KEY] == null) {
340
+ set(obj, HASH_KEY, uniqueId())
341
+ }
342
+ return obj[HASH_KEY]
343
+ }
344
+
345
+ return obj
346
+ }
347
+
348
+ /**
349
+ * A hash value generator for strings
350
+ * @export
351
+ * @param {string} str
352
+ * @return {number}
353
+ * @see http://isthe.com/chongo/tech/comp/fnv/
354
+ */
355
+ export function hashCode(str: string) {
356
+ const FNV1_32A_INIT = 0x811c9dc5
357
+ let hval = FNV1_32A_INIT
358
+ for (let i = 0; i < str.length; ++i) {
359
+ hval ^= str.charCodeAt(i)
360
+ hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24)
361
+ }
362
+ return hval >>> 0
363
+ }
364
+
365
+ export const bin = (n: number) => n.toString(2)
366
+
367
+ export const hex = (n: number) => n.toString(16)
368
+
369
+ export const oct = (n: number) => n.toString(8)
370
+
371
+ export const float = (x) => parseFloat(x)
372
+
373
+ export const int = (x, base = 10) => parseInt(x, base)
374
+
375
+ export const list = (arr?) => (arr ? Array.from(arr) : [])
376
+
377
+ export const next = (iter: Iterator<unknown>) => iter.next().value
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ export * from './globals'
2
+ export * from './operators'
3
+ export * from './collections'
4
+ export * from './datetime'
5
+ export * from './itertools'
6
+ export * from './math'
7
+ export * from './random'
@@ -0,0 +1,113 @@
1
+ import { Comp, Function, isObject, len } from './globals.js'
2
+ import { comp, id } from './operators.js'
3
+
4
+ const compKey = (cmp: Comp, key) => (x, y) => cmp(key(x), key(y))
5
+
6
+ export function* range(...args: number[]) {
7
+ if (args.length === 1) {
8
+ const stop = args[0]
9
+ for (let i = 0; i < stop; i++) {
10
+ yield i
11
+ }
12
+ } else if (args.length === 2) {
13
+ let [start, stop] = args
14
+ for (; start < stop; start++) {
15
+ yield start
16
+ }
17
+ } else {
18
+ let [start, stop, step] = args
19
+ for (; start < stop; start += step) {
20
+ yield start
21
+ }
22
+ }
23
+ }
24
+
25
+ /** Creates a new list with the elements from the iterable in reverse order. */
26
+ export function reversed(iterable: Iterable<any>) {
27
+ return Array.from(iterable).reverse()
28
+ }
29
+
30
+ export function sorted(args: any[]): any[]
31
+ export function sorted(args: any[], reverse: boolean): any[]
32
+ export function sorted(args: any[], reverse: boolean, comp: Comp): any[]
33
+ export function sorted(args: any[], key: Function): any[]
34
+ export function sorted(args: any[], key: Function, reverse: boolean): any[]
35
+
36
+ /**
37
+ * Creates a new list from `args` and sorts it. This can be called many ways:
38
+ * - sorted([...], true) => reverse order
39
+ * - sorted([...], fn = (x) => any) => using a key fn
40
+ * - sorted([...], fn = (x) => any, true) => reverse order using key
41
+ * - sorted([...], false, (x, y) => number) => using custom compare
42
+ * - sorted([...], fn = (x) => any, true, (x, y) => number) => custom key, reverse and compare
43
+ *
44
+ * If `args` is an Object, returns the sorted keys.
45
+ *
46
+ * @export
47
+ * @param {(Array | Object)} args
48
+ * @param {(boolean | Function)} [key]
49
+ * @param {(boolean | Comp)} [reverse]
50
+ * @param {Comp} [compareFn]
51
+ * @return
52
+ */
53
+ export function sorted(args, key?: boolean | Function, reverse?: boolean | Comp, compareFn?: Comp) {
54
+ if (isObject(args)) args = Object.keys(args)
55
+ if (typeof key === 'boolean') {
56
+ if (typeof reverse === 'function') {
57
+ compareFn = reverse
58
+ reverse = false
59
+ } else {
60
+ reverse = true
61
+ }
62
+ key = id
63
+ }
64
+ const copy = Array.from(args)
65
+ const _compare = compKey(compareFn ?? comp, key ?? id)
66
+ copy.sort(_compare)
67
+ if (reverse) copy.reverse()
68
+ return copy
69
+ }
70
+
71
+ export function sort(args: any[]): any[]
72
+ export function sort(args: any[], reverse: boolean): any[]
73
+ export function sort(args: any[], compareFn: Comp): any[]
74
+ export function sort(args: any[], reverse: boolean, compareFn: Comp): any[]
75
+
76
+ /**
77
+ * Sort `args` in place. Can be called like this:
78
+ * - sort([...], true) => reverse order
79
+ * - sort([...], (x, y) => number) => using custom compare
80
+ * - sort([...], true, (x, y) => number) => reverse and using custom compare
81
+ * @export
82
+ * @param {any[]} args
83
+ * @param {(boolean | Comp)} [reverse]
84
+ * @param {Comp} [compareFn]
85
+ * @return
86
+ */
87
+ export function sort(args: any[], reverse?: boolean | Comp, compareFn?: Comp) {
88
+ compareFn ??= comp
89
+ if (typeof reverse === 'function') {
90
+ compareFn = reverse
91
+ reverse = false
92
+ }
93
+ args.sort(compareFn)
94
+ if (reverse === true) args.reverse()
95
+ return args
96
+ }
97
+
98
+ /** Returns a generator that calls `fn(index)` for each index < n */
99
+ export function* times(n: number, fn: (index: number) => any) {
100
+ for (let i = 0; i < n; i++) yield fn(i)
101
+ }
102
+
103
+ export function* zip(...args) {
104
+ const size = len(args[0])
105
+ for (let i = 0; i < size; i++) {
106
+ const tuple = [] as any
107
+ for (let k = 0; k < args.length; k++) {
108
+ const item = args[k][i]
109
+ tuple.push(item)
110
+ }
111
+ yield tuple
112
+ }
113
+ }
package/src/math.ts ADDED
@@ -0,0 +1,73 @@
1
+ import { call, isFunc } from './globals.js'
2
+ import { comp } from './operators.js'
3
+
4
+ export function abs(x: number) {
5
+ const op = call(x, 'abs')
6
+ if (op != null) return op
7
+ return Math.abs(x)
8
+ }
9
+
10
+ /**
11
+ * Returns a tuple like (x / y, x % y)
12
+ * @export
13
+ * @param {number} x
14
+ * @param {number} y
15
+ * @return {number[]}
16
+ */
17
+ export function divmod(x: number, y: number) {
18
+ return [Math.floor(x / y), x % y]
19
+ }
20
+
21
+ export function log2(x) {
22
+ if (x > 0) {
23
+ return Math.log(x) * 1.442695
24
+ }
25
+ return Number.NaN
26
+ }
27
+
28
+ export function logBase(x, y) {
29
+ if (x > 0 && y > 0) {
30
+ return Math.log(y) / Math.log(x)
31
+ }
32
+ return Number.NaN
33
+ }
34
+
35
+ /** First argument can be a comparer func */
36
+ export function min(args) {
37
+ // Uses `le` by default
38
+ let cmp = comp
39
+ if (isFunc(args[0])) {
40
+ cmp = args.shift()
41
+ }
42
+ let res = args[0]
43
+ for (const x of args) {
44
+ if (cmp(x, res) === -1) {
45
+ res = x
46
+ }
47
+ }
48
+ return res
49
+ }
50
+
51
+ /** First argument can be a comparer func */
52
+ export function max(args) {
53
+ // Uses ge by default
54
+ let cmp = comp
55
+ if (isFunc(args[0])) {
56
+ cmp = args.shift()
57
+ }
58
+ let res = args[0]
59
+ for (const x of args) {
60
+ if (cmp(x, res) === 1) {
61
+ res = x
62
+ }
63
+ }
64
+ return res
65
+ }
66
+
67
+ export function sum(args) {
68
+ let total = 0
69
+ for (const x of args) {
70
+ total += x
71
+ }
72
+ return total
73
+ }
package/src/objects.ts ADDED
File without changes
@@ -0,0 +1,126 @@
1
+ import { call, isNumber, isObject } from './globals.js'
2
+
3
+ export const id = (x) => x
4
+
5
+ export const bool = (x) => !!x
6
+
7
+ export const not = (x) => !x
8
+
9
+ export const isinstance = (x, y) => x instanceof y
10
+
11
+ export const all = (arr: any[], fn = bool) => arr.every(fn)
12
+
13
+ export const any = (arr: any[], fn = bool) => arr.some(fn)
14
+
15
+ export const and = all
16
+
17
+ export const or = any
18
+
19
+ export function comp(x, y) {
20
+ const op = call(x, 'compare', y)
21
+ if (isNumber(op)) return op
22
+ if (eq(x, y)) return 0
23
+ if (le(x, y)) return -1
24
+ if (ge(x, y)) return 1
25
+ return 0
26
+ }
27
+
28
+ export function eq(x, y) {
29
+ const op = call(x, 'eq', y)
30
+ if (op != null) return op
31
+ return x === y
32
+ }
33
+
34
+ export function shallowEqual(x, y) {
35
+ if (!x || !y) return x === y
36
+ if (Array.isArray(x)) {
37
+ for (let i = 0; i < x.length; i++) {
38
+ if (!eq(x[i], y[i])) return false
39
+ }
40
+ return true
41
+ }
42
+ if (isObject(x)) {
43
+ if (eq(x, y)) return true
44
+ for (const key in x) {
45
+ if (!eq(x[key], y[key])) return false
46
+ }
47
+ return true
48
+ }
49
+ return eq(x, y)
50
+ }
51
+
52
+ export function lt(x, y) {
53
+ const op = call(x, 'lt', y)
54
+ if (op != null) return op
55
+ return x < y
56
+ }
57
+
58
+ export function le(x, y) {
59
+ let op = call(x, 'le', y)
60
+ if (op != null) return op
61
+ op = call(x, 'eq', y)
62
+ if (op === true) return op
63
+ op = call(x, 'lt', y)
64
+ if (op != null) return op
65
+ return x <= y
66
+ }
67
+
68
+ export function gt(x, y) {
69
+ const op = call(x, 'gt', y)
70
+ if (op != null) return op
71
+ return x > y
72
+ }
73
+
74
+ export function ge(x, y) {
75
+ let op = call(x, 'ge', y)
76
+ if (op != null) return op
77
+ op = call(x, 'eq', y)
78
+ if (op === true) return op
79
+ op = call(x, 'gt', y)
80
+ if (op != null) return op
81
+ return x >= y
82
+ }
83
+
84
+ export function add(x, y) {
85
+ const op = call(x, 'add', y)
86
+ if (op != null) return op
87
+ return x + y
88
+ }
89
+
90
+ export function sub(x, y) {
91
+ const op = call(x, 'sub', y)
92
+ if (op != null) return op
93
+ return x - y
94
+ }
95
+
96
+ export function mult(x, y) {
97
+ const op = call(x, 'mult', y)
98
+ if (op != null) return op
99
+ return x * y
100
+ }
101
+
102
+ export function div(x, y) {
103
+ const op = call(x, 'div', y)
104
+ if (op != null) return op
105
+ return x / y
106
+ }
107
+
108
+ export function mod(x, y) {
109
+ const op = call(x, 'mod', y)
110
+ if (op != null) return op
111
+ return x % y
112
+ }
113
+
114
+ /**
115
+ * Calculates `x` to the power of `y`. If `x` implements a custom `pow` operator
116
+ * it will return `x.pow(y)`.
117
+ * @export
118
+ * @param {*} x
119
+ * @param {*} y
120
+ * @return `x` raised to the power `y`
121
+ */
122
+ export function pow(x, y) {
123
+ const op = call(x, 'pow', y)
124
+ if (op != null) return op
125
+ return x ** y
126
+ }