@tempots/std 0.9.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 (132) hide show
  1. package/dist/arrays.d.ts +49 -0
  2. package/dist/arrays.js +249 -0
  3. package/dist/async-result.d.ts +37 -0
  4. package/dist/async-result.js +75 -0
  5. package/dist/bigint.d.ts +18 -0
  6. package/dist/bigint.js +110 -0
  7. package/dist/booleans.d.ts +23 -0
  8. package/dist/booleans.js +68 -0
  9. package/dist/colors/cmyk.d.ts +21 -0
  10. package/dist/colors/cmyk.js +54 -0
  11. package/dist/colors/convert.d.ts +283 -0
  12. package/dist/colors/convert.js +742 -0
  13. package/dist/colors/hsl.d.ts +24 -0
  14. package/dist/colors/hsl.js +56 -0
  15. package/dist/colors/hsla.d.ts +18 -0
  16. package/dist/colors/hsla.js +35 -0
  17. package/dist/colors/hsluv.d.ts +24 -0
  18. package/dist/colors/hsluv.js +56 -0
  19. package/dist/colors/hsv.d.ts +24 -0
  20. package/dist/colors/hsv.js +54 -0
  21. package/dist/colors/lab.d.ts +24 -0
  22. package/dist/colors/lab.js +54 -0
  23. package/dist/colors/lch.d.ts +19 -0
  24. package/dist/colors/lch.js +44 -0
  25. package/dist/colors/luv.d.ts +19 -0
  26. package/dist/colors/luv.js +45 -0
  27. package/dist/colors/rgb.d.ts +13 -0
  28. package/dist/colors/rgb.js +47 -0
  29. package/dist/colors/rgba.d.ts +12 -0
  30. package/dist/colors/rgba.js +44 -0
  31. package/dist/colors/srgb.d.ts +24 -0
  32. package/dist/colors/srgb.js +51 -0
  33. package/dist/colors/xyz.d.ts +19 -0
  34. package/dist/colors/xyz.js +41 -0
  35. package/dist/edit.d.ts +20 -0
  36. package/dist/edit.js +29 -0
  37. package/dist/equals.d.ts +3 -0
  38. package/dist/equals.js +122 -0
  39. package/dist/functions.d.ts +20 -0
  40. package/dist/functions.js +38 -0
  41. package/dist/json.d.ts +14 -0
  42. package/dist/json.js +33 -0
  43. package/dist/match.d.ts +16 -0
  44. package/dist/match.js +45 -0
  45. package/dist/maybe.d.ts +9 -0
  46. package/dist/maybe.js +25 -0
  47. package/dist/memoize.d.ts +1 -0
  48. package/dist/memoize.js +9 -0
  49. package/dist/newtype.d.ts +28 -0
  50. package/dist/newtype.js +29 -0
  51. package/dist/numbers.d.ts +104 -0
  52. package/dist/numbers.js +183 -0
  53. package/dist/objects.d.ts +9 -0
  54. package/dist/objects.js +33 -0
  55. package/dist/ord.d.ts +19 -0
  56. package/dist/ord.js +73 -0
  57. package/dist/reg-exps.d.ts +10 -0
  58. package/dist/reg-exps.js +43 -0
  59. package/dist/result.d.ts +31 -0
  60. package/dist/result.js +95 -0
  61. package/dist/strings.d.ts +314 -0
  62. package/dist/strings.js +685 -0
  63. package/dist/types/assert.d.ts +12 -0
  64. package/dist/types/assert.js +13 -0
  65. package/dist/types/differentiate.d.ts +13 -0
  66. package/dist/types/differentiate.js +14 -0
  67. package/dist/types/functions.d.ts +22 -0
  68. package/dist/types/functions.js +13 -0
  69. package/dist/types/generic.d.ts +9 -0
  70. package/dist/types/generic.js +13 -0
  71. package/dist/types/objects.d.ts +50 -0
  72. package/dist/types/objects.js +13 -0
  73. package/dist/types/tuples.d.ts +44 -0
  74. package/dist/types/tuples.js +24 -0
  75. package/dist/types/utility.d.ts +2 -0
  76. package/dist/types/utility.js +1 -0
  77. package/dist/uuid.d.ts +13 -0
  78. package/dist/uuid.js +56 -0
  79. package/dist/validation.d.ts +23 -0
  80. package/dist/validation.js +44 -0
  81. package/package.json +36 -0
  82. package/src/arrays.ts +296 -0
  83. package/src/async-result.ts +103 -0
  84. package/src/bigint.ts +111 -0
  85. package/src/booleans.ts +73 -0
  86. package/src/colors/cmyk.ts +84 -0
  87. package/src/colors/convert.ts +1093 -0
  88. package/src/colors/hsl.ts +73 -0
  89. package/src/colors/hsla.ts +45 -0
  90. package/src/colors/hsluv.ts +73 -0
  91. package/src/colors/hsv.ts +75 -0
  92. package/src/colors/lab.ts +69 -0
  93. package/src/colors/lch.ts +53 -0
  94. package/src/colors/luv.ts +56 -0
  95. package/src/colors/rgb.ts +55 -0
  96. package/src/colors/rgba.ts +53 -0
  97. package/src/colors/srgb.ts +72 -0
  98. package/src/colors/xyz.ts +52 -0
  99. package/src/edit.ts +29 -0
  100. package/src/equals.ts +116 -0
  101. package/src/functions.ts +108 -0
  102. package/src/json.ts +52 -0
  103. package/src/match.ts +88 -0
  104. package/src/maybe.ts +32 -0
  105. package/src/memoize.ts +9 -0
  106. package/src/newtype.ts +59 -0
  107. package/src/numbers.ts +222 -0
  108. package/src/objects.ts +47 -0
  109. package/src/ord.ts +79 -0
  110. package/src/reg-exps.ts +48 -0
  111. package/src/result.ts +140 -0
  112. package/src/strings.ts +768 -0
  113. package/src/types/assert.ts +96 -0
  114. package/src/types/differentiate.ts +89 -0
  115. package/src/types/functions.ts +114 -0
  116. package/src/types/generic.ts +42 -0
  117. package/src/types/objects.ts +212 -0
  118. package/src/types/tuples.ts +244 -0
  119. package/src/types/utility.ts +3 -0
  120. package/src/uuid.ts +61 -0
  121. package/src/validation.ts +69 -0
  122. package/test/arrays.spec.ts +410 -0
  123. package/test/colors.spec.ts +406 -0
  124. package/test/commmon.ts +9 -0
  125. package/test/equals.spec.ts +165 -0
  126. package/test/functions.spec.ts +9 -0
  127. package/test/index.d.ts +20 -0
  128. package/test/objects.spec.ts +22 -0
  129. package/test/reg-exps.spec.ts +33 -0
  130. package/test/strings.spec.ts +333 -0
  131. package/test/uuid.spec.ts +35 -0
  132. package/tsconfig.json +19 -0
package/src/arrays.ts ADDED
@@ -0,0 +1,296 @@
1
+ /*
2
+ Copyright 2019 Google LLC
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+ https://www.apache.org/licenses/LICENSE-2.0
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
12
+ */
13
+
14
+ /**
15
+ * Utility functions to manipulate `Array` values.
16
+ */
17
+
18
+ import { Maybe } from './maybe'
19
+ import { type Ordering, type Compare } from './ord'
20
+ import { type Primitive } from './types/utility'
21
+ import { keys } from './objects'
22
+
23
+ export function map<A, B> (arr: A[], f: (a: A, index: number) => B): B[] {
24
+ return Array.from({ length: arr.length }, (_, i) => f(arr[i], i))
25
+ }
26
+
27
+ export function mapNotNull<A, B> (
28
+ arr: A[],
29
+ f: (a: A, index: number) => B | null | undefined
30
+ ): B[] {
31
+ const buff = [] as B[]
32
+ for (let i = 0; i < arr.length; i++) {
33
+ const v = f(arr[i], i)
34
+ if (v != null) {
35
+ buff.push(v)
36
+ }
37
+ }
38
+ return buff
39
+ }
40
+
41
+ export function flatMap<A, B> (arr: A[], f: (a: A) => B[]): B[] {
42
+ const buff = []
43
+ for (const el of arr) {
44
+ buff.push(...f(el))
45
+ }
46
+ return buff
47
+ }
48
+
49
+ export function head<A> (arr: A[]): Maybe<A> {
50
+ return arr.length > 0 ? arr[0] : Maybe.nothing
51
+ }
52
+
53
+ export function tail<A> (arr: A[]): A[] {
54
+ return arr.slice(1)
55
+ }
56
+
57
+ export function equals<T> (a: T[], b: T[], equality: (a: T, b: T) => boolean): boolean {
58
+ if (a.length !== b.length) return false
59
+ else {
60
+ for (let i = 0; i < a.length; i++) {
61
+ if (!equality(a[i], b[i])) return false
62
+ }
63
+ return true
64
+ }
65
+ }
66
+
67
+ export function makeEquals<T> (equality: (a: T, b: T) => boolean) {
68
+ return function (a: T[], b: T[]) {
69
+ return equals(a, b, equality)
70
+ }
71
+ }
72
+
73
+ export function isEmpty<T> (arr: T[]): arr is [] {
74
+ return arr.length === 0
75
+ }
76
+
77
+ export function hasValues<T> (arr: T[]): arr is [T, ...T[]] {
78
+ return arr.length > 0
79
+ }
80
+
81
+ export function filter<T> (arr: T[], predicate: (v: T) => boolean): T[] {
82
+ const buff = [] as T[]
83
+ for (const a of arr) if (predicate(a)) buff.push(a)
84
+ return buff
85
+ }
86
+
87
+ export function filterNulls<T> (arr: Array<T | null | undefined>): T[] {
88
+ return filter(arr, v => v != null) as T[]
89
+ }
90
+
91
+ export function flatten<T> (arr: T[][]): T[] {
92
+ return ([] as T[]).concat(...arr)
93
+ }
94
+
95
+ export function foldLeft<T, B> (arr: T[], f: (acc: B, curr: T) => B, b: B): B {
96
+ for (const a of arr) {
97
+ b = f(b, a)
98
+ }
99
+ return b
100
+ }
101
+
102
+ export function all<T> (arr: T[], predicate: (v: T) => boolean): boolean {
103
+ for (const a of arr) {
104
+ if (!predicate(a)) {
105
+ return false
106
+ }
107
+ }
108
+ return true
109
+ }
110
+
111
+ export function any<T> (arr: T[], predicate: (v: T) => boolean): boolean {
112
+ for (const a of arr) {
113
+ if (predicate(a)) {
114
+ return true
115
+ }
116
+ }
117
+ return false
118
+ }
119
+
120
+ export function each<T> (arr: T[], f: (v: T) => void): void {
121
+ for (const a of arr) f(a)
122
+ }
123
+
124
+ export function concat<A> (...arrs: A[][]): A[] {
125
+ return ([] as A[]).concat(...arrs)
126
+ }
127
+
128
+ export function makeCompare<A> (comparef: Compare<A>, shorterFirst = true) {
129
+ return function (a: A[], b: A[]) {
130
+ if (a.length < b.length) {
131
+ return -1 * (shorterFirst ? 1 : -1)
132
+ } else if (a.length > b.length) {
133
+ return 1 * (shorterFirst ? 1 : -1)
134
+ }
135
+ for (let i = 0; i < a.length; i++) {
136
+ const ord = comparef(a[i], b[i])
137
+ if (ord !== 0) return ord
138
+ }
139
+ return 0
140
+ }
141
+ }
142
+
143
+ export function sort<A> (compare: (a: A, b: A) => Ordering, arr: A[]): A[] {
144
+ return arr.slice().sort(compare)
145
+ }
146
+
147
+ export function range<A> (length: number, f: (index: number) => A): A[] {
148
+ return Array.from({ length }, (_, i) => f(i))
149
+ }
150
+
151
+ export function numbersRange (length: number, startAt = 0): number[] {
152
+ return range(length, i => startAt + i)
153
+ }
154
+
155
+ export function fill<A> (length: number, value: A): A[] {
156
+ return range(length, () => value)
157
+ }
158
+
159
+ export function distinctPrimitive<T extends Primitive> (values: T[]): T[] {
160
+ return Array.from(new Set(values))
161
+ }
162
+
163
+ export function distinctByPredicate<T> (
164
+ values: T[],
165
+ predicate: (a: T) => string
166
+ ): T[] {
167
+ const map: Record<string, T> = {}
168
+ values.forEach(v => {
169
+ map[predicate(v)] = v
170
+ })
171
+ return keys(map).map(k => map[k])
172
+ }
173
+
174
+ export function remove<A> (
175
+ arr: A[],
176
+ item: A,
177
+ predicate?: (a: A) => boolean
178
+ ): boolean {
179
+ let index
180
+ if (predicate !== undefined) {
181
+ index = arr.findIndex(predicate)
182
+ } else {
183
+ index = arr.indexOf(item)
184
+ }
185
+ if (index < 0) {
186
+ return false
187
+ } else {
188
+ arr.splice(index, 1)
189
+ return true
190
+ }
191
+ }
192
+
193
+ export function ofIterableIterator<A> (it: IterableIterator<A>): A[] {
194
+ const buff = [] as A[]
195
+ for (let r = it.next(); !(r.done ?? false); r = it.next()) {
196
+ buff.push(r.value)
197
+ }
198
+ return buff
199
+ }
200
+
201
+ export interface DiffOperations<T> {
202
+ removals: Array<{ at: number, qt: number }>
203
+ swaps: Array<{ from: number, to: number }>
204
+ inserts: Array<{ at: number, values: T[] }>
205
+ }
206
+
207
+ export function diffOperations<T, K> (
208
+ from: T[],
209
+ to: T[],
210
+ getKey: (v: T) => K
211
+ ): DiffOperations<T> {
212
+ const ops: DiffOperations<T> = {
213
+ removals: [],
214
+ swaps: [],
215
+ inserts: []
216
+ }
217
+ const { removals, inserts, swaps } = ops
218
+ const mapB = new Map<K, number>()
219
+ to.forEach((v, i) => mapB.set(getKey(v), i))
220
+
221
+ const indexesOfAThatDoNotExistInB = from
222
+ .map((v, i) => [v, i] as const)
223
+ .filter(([v]) => !mapB.has(getKey(v)))
224
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
225
+ .map(([_, i]) => i)
226
+ for (let i = indexesOfAThatDoNotExistInB.length - 1; i >= 0; i--) {
227
+ const p = indexesOfAThatDoNotExistInB[i]
228
+ const last = removals.length > 0 ? removals[removals.length - 1] : undefined
229
+ if ((last != null) && last.at === p + 1) {
230
+ last.at--
231
+ last.qt++
232
+ } else {
233
+ removals.push({ at: p, qt: 1 })
234
+ }
235
+ }
236
+
237
+ const mapA = new Map<K, number>()
238
+ from.forEach((v, i) => mapA.set(getKey(v), i))
239
+
240
+ const indexesOfBThatDoNotExistInA = to
241
+ .map((v, i) => [v, i] as const)
242
+ .filter(([v]) => !mapA.has(getKey(v)))
243
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
244
+ .map(([_, i]) => i)
245
+ for (const p of indexesOfBThatDoNotExistInA) {
246
+ const last = inserts.length > 0 ? inserts[inserts.length - 1] : undefined
247
+ if ((last != null) && last.at + last.values.length === p) {
248
+ last.values.push(to[p])
249
+ } else {
250
+ inserts.push({ at: p, values: [to[p]] })
251
+ }
252
+ }
253
+
254
+ const ra = from.filter((_, i) => !indexesOfAThatDoNotExistInB.includes(i))
255
+ const mapRA = new Map<K, number>()
256
+ for (let i = 0; i < ra.length; i++) {
257
+ mapRA.set(getKey(ra[i]), i)
258
+ }
259
+
260
+ const rb = to.filter((_, i) => !indexesOfBThatDoNotExistInA.includes(i))
261
+ for (let i = 0; i < rb.length; i++) {
262
+ const bk = getKey(rb[i])
263
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
264
+ const ai = mapRA.get(bk)!
265
+ if (ai == null || i === ai) continue
266
+ const ak = getKey(ra[i])
267
+ mapRA.delete(ak)
268
+ swaps.push({ from: i, to: ai })
269
+ }
270
+ return ops
271
+ }
272
+
273
+ export function applyOperations<T> (
274
+ operations: DiffOperations<T>,
275
+ start: T[]
276
+ ): T[] {
277
+ const buff = [...start]
278
+ for (const { at, qt } of operations.removals) {
279
+ buff.splice(at, qt)
280
+ }
281
+ for (const { from, to } of operations.swaps) {
282
+ const t = buff[to]
283
+ buff[to] = buff[from]
284
+ buff[from] = t
285
+ }
286
+ for (const op of operations.inserts) {
287
+ buff.splice(op.at, 0, ...op.values)
288
+ }
289
+ return buff
290
+ }
291
+
292
+ export function joinWithConjunction<A> (arr: A[], conjunction = ' and ', separator = ', '): string {
293
+ if (arr.length === 0) return ''
294
+ if (arr.length === 1) return String(arr[0])
295
+ return `${arr.slice(0, -1).join(separator)}${conjunction}${String(arr[arr.length - 1])}`
296
+ }
@@ -0,0 +1,103 @@
1
+ export interface Idle {
2
+ type: 'idle'
3
+ }
4
+ export interface Loading {
5
+ type: 'loading'
6
+ }
7
+ export interface Success<V> {
8
+ type: 'success'
9
+ value: V
10
+ }
11
+ export interface Failure<E> {
12
+ type: 'failure'
13
+ error: E
14
+ }
15
+
16
+ export type AsyncResult<V, E> = Idle | Loading | Success<V> | Failure<E>
17
+
18
+ // eslint-disable-next-line @typescript-eslint/no-redeclare
19
+ export const AsyncResult = {
20
+ idle: { type: 'idle' } satisfies AsyncResult<never, never>,
21
+ loading: { type: 'loading' } satisfies AsyncResult<never, never>,
22
+ success<V>(value: V): AsyncResult<V, never> {
23
+ return { type: 'success', value }
24
+ },
25
+ failure<E>(error: E): AsyncResult<never, E> {
26
+ return { type: 'failure', error }
27
+ },
28
+ isSuccess<V, E>(r: AsyncResult<V, E>): r is Success<V> {
29
+ return r.type === 'success'
30
+ },
31
+ isFailure<V, E>(r: AsyncResult<V, E>): r is Failure<E> {
32
+ return r.type === 'failure'
33
+ },
34
+ isIdle<V, E>(r: AsyncResult<V, E>): r is Idle {
35
+ return r.type === 'idle'
36
+ },
37
+ isLoading<V, E>(r: AsyncResult<V, E>): r is Loading {
38
+ return r.type === 'loading'
39
+ },
40
+ getOrElse<V, E>(r: AsyncResult<V, E>, alt: V): V {
41
+ return AsyncResult.isSuccess(r) ? r.value : alt
42
+ },
43
+ getOrElseLazy<V, E>(r: AsyncResult<V, E>, altf: () => V): V {
44
+ return AsyncResult.isSuccess(r) ? r.value : altf()
45
+ },
46
+ getOrNull<V, E>(r: AsyncResult<V, E>): V | null {
47
+ return AsyncResult.isSuccess(r) ? r.value : null
48
+ },
49
+ getOrUndefined<V, E>(r: AsyncResult<V, E>): V | undefined {
50
+ return AsyncResult.isSuccess(r) ? r.value : undefined
51
+ },
52
+ cmatch:
53
+ <V1, V2, E>(
54
+ success: (value: V1) => V2,
55
+ failure: (error: E) => V2,
56
+ loading: () => V2,
57
+ idle: () => V2 = loading
58
+ ) =>
59
+ (r: AsyncResult<V1, E>): V2 => {
60
+ if (AsyncResult.isSuccess(r)) {
61
+ return success(r.value)
62
+ } else if (AsyncResult.isFailure(r)) {
63
+ return failure(r.error)
64
+ } else if (AsyncResult.isIdle(r)) {
65
+ return idle()
66
+ } else {
67
+ return loading()
68
+ }
69
+ },
70
+ match: <V1, V2, E>(
71
+ r: AsyncResult<V1, E>,
72
+ success: (value: V1) => V2,
73
+ failure: (error: E) => V2,
74
+ loading: () => V2,
75
+ idle: () => V2 = loading
76
+ ): V2 => {
77
+ if (AsyncResult.isSuccess(r)) {
78
+ return success(r.value)
79
+ } else if (AsyncResult.isFailure(r)) {
80
+ return failure(r.error)
81
+ } else if (AsyncResult.isIdle(r)) {
82
+ return idle()
83
+ } else {
84
+ return loading()
85
+ }
86
+ },
87
+ whenSuccess:
88
+ <V, E>(apply: (v: V) => void) =>
89
+ (r: AsyncResult<V, E>): AsyncResult<V, E> => {
90
+ if (AsyncResult.isSuccess(r)) {
91
+ apply(r.value)
92
+ }
93
+ return r
94
+ },
95
+ whenFailure:
96
+ <V, E>(apply: (e: E) => void) =>
97
+ (r: AsyncResult<V, E>): AsyncResult<V, E> => {
98
+ if (AsyncResult.isFailure(r)) {
99
+ apply(r.error)
100
+ }
101
+ return r
102
+ }
103
+ }
package/src/bigint.ts ADDED
@@ -0,0 +1,111 @@
1
+ export function ceilDiv (x: bigint, y: bigint): bigint {
2
+ if (y < 0n) {
3
+ x = -x
4
+ y = -y
5
+ }
6
+ return x <= 0n ? x / y : (x - 1n) / y + 1n
7
+ }
8
+
9
+ export function floorDiv (x: bigint, y: bigint): bigint {
10
+ if (y < 0n) {
11
+ x = -x
12
+ y = -y
13
+ }
14
+ return x >= 0n ? x / y : (x + 1n) / y - 1n
15
+ }
16
+
17
+ export function compare (x: bigint, y: bigint): number {
18
+ return x < y ? -1 : x > y ? 1 : 0
19
+ }
20
+
21
+ export function abs (x: bigint): bigint {
22
+ return x < 0n ? -x : x
23
+ }
24
+
25
+ export function min (x: bigint, y: bigint): bigint {
26
+ return x < y ? x : y
27
+ }
28
+
29
+ export function max (x: bigint, y: bigint): bigint {
30
+ return x > y ? x : y
31
+ }
32
+
33
+ export function pow (x: bigint, y: bigint): bigint {
34
+ if (y < 0n) throw new Error('negative exponent')
35
+ let result = 1n
36
+ while (y > 0n) {
37
+ if ((y & 1n) !== 0n) result *= x
38
+ y >>= 1n
39
+ x *= x
40
+ }
41
+ return result
42
+ }
43
+
44
+ export function gcd (x: bigint, y: bigint): bigint {
45
+ x = abs(x)
46
+ y = abs(y)
47
+ while (y > 0n) {
48
+ const t = y
49
+ y = x % y
50
+ x = t
51
+ }
52
+ return x
53
+ }
54
+
55
+ export function lcm (x: bigint, y: bigint): bigint {
56
+ return abs(x * y) / gcd(x, y)
57
+ }
58
+
59
+ export function isPrime (x: bigint): boolean {
60
+ if (x < 2n) return false
61
+ if (x === 2n || x === 3n) return true
62
+ if (x % 2n === 0n || x % 3n === 0n) return false
63
+ let i = 5n
64
+ while (i * i <= x) {
65
+ if (x % i === 0n || x % (i + 2n) === 0n) return false
66
+ i += 6n
67
+ }
68
+ return true
69
+ }
70
+
71
+ export function nextPrime (x: bigint): bigint {
72
+ if (x < 2n) return 2n
73
+ if (x === 2n) return 3n
74
+ if (x % 2n === 0n) x++
75
+ else x += 2n
76
+ while (!isPrime(x)) x += 2n
77
+ return x
78
+ }
79
+
80
+ export function prevPrime (x: bigint): bigint {
81
+ if (x <= 2n) throw new Error('no previous prime')
82
+ if (x === 3n) return 2n
83
+ if (x % 2n === 0n) x--
84
+ else x -= 2n
85
+ while (!isPrime(x)) x -= 2n
86
+ return x
87
+ }
88
+
89
+ export function isEven (x: bigint): boolean {
90
+ return x % 2n === 0n
91
+ }
92
+
93
+ export function isOdd (x: bigint): boolean {
94
+ return x % 2n !== 0n
95
+ }
96
+
97
+ export function isZero (x: bigint): boolean {
98
+ return x === 0n
99
+ }
100
+
101
+ export function isOne (x: bigint): boolean {
102
+ return x === 1n
103
+ }
104
+
105
+ export function isNegative (x: bigint): boolean {
106
+ return x < 0n
107
+ }
108
+
109
+ export function isPositive (x: bigint): boolean {
110
+ return x > 0n
111
+ }
@@ -0,0 +1,73 @@
1
+ /*
2
+ Copyright 2019 Google LLC
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+ https://www.apache.org/licenses/LICENSE-2.0
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
12
+ */
13
+
14
+ /**
15
+ * Utility functions to manipulate `boolean` values.
16
+ */
17
+
18
+ /**
19
+ * Returns a comparison value (`Int`) from two boolean values.
20
+ */
21
+ export function compare (a: boolean, b: boolean): number {
22
+ return a === b ? 0 : a ? -1 : 1
23
+ }
24
+
25
+ /**
26
+ * Converts a boolean to an integer value (`true` => `1`, `false` => `0`).
27
+ */
28
+ export function toInt (v: boolean): number {
29
+ return v ? 1 : 0
30
+ }
31
+
32
+ /**
33
+ * Returns `true` if the passed value is either `true` or `false` (case insensitive).
34
+ */
35
+ export function canParse (v: string): boolean {
36
+ if (v == null) return false
37
+ switch (v.toLowerCase()) {
38
+ case 'true':
39
+ case 'false':
40
+ case '0':
41
+ case '1':
42
+ case 'on':
43
+ case 'off':
44
+ return true
45
+ default:
46
+ return false
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Returns `true`/`false` if the passed value is `true`/`false` (case insensitive) with any other value it will return null.
52
+ */
53
+ export function parse (v: string): boolean {
54
+ switch (v.toLowerCase()) {
55
+ case 'true':
56
+ case '1':
57
+ case 'on':
58
+ return true
59
+ case 'false':
60
+ case '0':
61
+ case 'off':
62
+ return false
63
+ default:
64
+ throw new Error(`unable to parse '${v}'`)
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Returns `true` when arguments are different.
70
+ */
71
+ export function xor (a: boolean, b: boolean): boolean {
72
+ return a !== b
73
+ }
@@ -0,0 +1,84 @@
1
+ import { clamp, nearEquals } from '../numbers'
2
+
3
+ const TOLLERANCE = 0.0001
4
+
5
+ export class CMYK {
6
+ static fromString (s: string): CMYK {
7
+ const m = s.match(
8
+ /^cmyk\((\d+(?:\.\d+)?)%, ?(\d+(?:\.\d+)?)%, ?(\d+(?:\.\d+)?)%, ?(\d+(?:\.\d+)?)%\)$/
9
+ )
10
+ if (m != null) {
11
+ const [, cyan, magenta, y, k] = m
12
+ return new CMYK(
13
+ parseFloat(cyan),
14
+ parseFloat(magenta),
15
+ parseFloat(y),
16
+ parseFloat(k)
17
+ )
18
+ }
19
+ throw new Error(`Invalid CMYK string: ${s}`)
20
+ }
21
+
22
+ static ofChannels ([cyan, magenta, yellow, black]: [
23
+ cyan: number,
24
+ magenta: number,
25
+ yellow: number,
26
+ black: number
27
+ ]): CMYK {
28
+ return new CMYK(
29
+ clamp(cyan * 100, 0, 100),
30
+ clamp(magenta * 100, 0, 100),
31
+ clamp(yellow * 100, 0, 100),
32
+ clamp(black * 100, 0, 100)
33
+ )
34
+ }
35
+
36
+ readonly cyan: number
37
+ readonly magenta: number
38
+ readonly yellow: number
39
+ readonly black: number
40
+ constructor (cyan: number, magenta: number, yellow: number, black: number) {
41
+ this.cyan = clamp(cyan, 0, 100)
42
+ this.magenta = clamp(magenta, 0, 100)
43
+ this.yellow = clamp(yellow, 0, 100)
44
+ this.black = clamp(black, 0, 100)
45
+ }
46
+
47
+ withCyan (cyan: number): CMYK {
48
+ return new CMYK(cyan, this.magenta, this.yellow, this.black)
49
+ }
50
+
51
+ withMagenta (magenta: number): CMYK {
52
+ return new CMYK(this.cyan, magenta, this.yellow, this.black)
53
+ }
54
+
55
+ withYellow (yellow: number): CMYK {
56
+ return new CMYK(this.cyan, this.magenta, yellow, this.black)
57
+ }
58
+
59
+ withBlack (black: number): CMYK {
60
+ return new CMYK(this.cyan, this.magenta, this.yellow, black)
61
+ }
62
+
63
+ toChannels (): [number, number, number, number] {
64
+ return [
65
+ this.cyan / 100,
66
+ this.magenta / 100,
67
+ this.yellow / 100,
68
+ this.black / 100
69
+ ]
70
+ }
71
+
72
+ toString (): string {
73
+ return `cmyk(${this.cyan}%, ${this.magenta}%, ${this.yellow}%, ${this.black}%)`
74
+ }
75
+
76
+ equals (other: CMYK, tollerance = TOLLERANCE): boolean {
77
+ return (
78
+ nearEquals(this.cyan, other.cyan, tollerance) &&
79
+ nearEquals(this.magenta, other.magenta, tollerance) &&
80
+ nearEquals(this.yellow, other.yellow, tollerance) &&
81
+ nearEquals(this.black, other.black, tollerance)
82
+ )
83
+ }
84
+ }