functionalscript
Advanced tools
Comparing version 0.4.2 to 0.4.3
import type { Array16, Array8 } from '../../types/array/module.f.ts'; | ||
import { type Vec } from '../../types/bit_vec/module.f.ts'; | ||
import { type List } from '../../types/list/module.f.ts'; | ||
export type V8 = Array8<bigint>; | ||
@@ -44,2 +45,10 @@ export type V16 = Array16<bigint>; | ||
/** | ||
* A hash length. | ||
*/ | ||
readonly hashLength: bigint; | ||
/** | ||
* An internal block length. | ||
*/ | ||
readonly blockLength: bigint; | ||
/** | ||
* Initial state of the SHA-2 algorithm. | ||
@@ -64,2 +73,3 @@ */ | ||
}; | ||
export declare const computeSync: ({ append, init, end }: Sha2) => (list: List<Vec>) => Vec; | ||
export declare const base32: Base; | ||
@@ -66,0 +76,0 @@ export declare const base64: Base; |
import { mask } from "../../types/bigint/module.f.js"; | ||
import { vec, length, empty, msb } from "../../types/bit_vec/module.f.js"; | ||
import { flip } from "../../types/function/module.f.js"; | ||
import { fold } from "../../types/list/module.f.js"; | ||
const { concat, popFront, front } = msb; | ||
@@ -141,2 +143,3 @@ const lastOne = vec(1n)(1n); | ||
const offset = (bitLength << 3n) - hashLength; | ||
const result = vec(hashLength); | ||
return (state) => { | ||
@@ -152,3 +155,3 @@ const { len, remainder } = state; | ||
} | ||
return fromV8(compress(hash)(u | (len + rLen))) >> offset; | ||
return result(fromV8(compress(hash)(u | (len + rLen))) >> offset); | ||
}; | ||
@@ -158,3 +161,5 @@ } | ||
}; | ||
const sha2 = ({ append, end }, hash, hashLength) => ({ | ||
const sha2 = ({ append, end, chunkLength }, hash, hashLength) => ({ | ||
hashLength, | ||
blockLength: chunkLength, | ||
init: { | ||
@@ -168,2 +173,6 @@ hash, | ||
}); | ||
export const computeSync = ({ append, init, end }) => { | ||
const f = fold(flip(append))(init); | ||
return (list) => end(f(list)); | ||
}; | ||
export const base32 = base({ | ||
@@ -170,0 +179,0 @@ logBitLen: 5n, |
import { msbUtf8 } from "../../text/module.f.js"; | ||
import { empty, msb, vec } from "../../types/bit_vec/module.f.js"; | ||
import { map } from "../../types/list/module.f.js"; | ||
import { repeat } from "../../types/monoid/module.f.js"; | ||
import { base32, base64, sha224, sha256, sha384, sha512, sha512x224, sha512x256, } from "./module.f.js"; | ||
import { base32, base64, computeSync, sha224, sha256, sha384, sha512, sha512x224, sha512x256, } from "./module.f.js"; | ||
const { concat: beConcat } = msb; | ||
@@ -25,3 +26,3 @@ const checkEmpty = ({ init, end }) => (x) => { | ||
if (result !== x) { | ||
throw [result, x]; | ||
throw [result.toString(16), x.toString(16)]; | ||
} | ||
@@ -74,25 +75,31 @@ }, | ||
sha2: { | ||
sha256: () => checkEmpty(sha256)(0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855n), | ||
sha224: () => checkEmpty(sha224)(0xd14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42fn), | ||
sha512: () => checkEmpty(sha512)(0xcf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3en), | ||
sha384: () => checkEmpty(sha384)(0x38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95bn), | ||
sha512x256: () => checkEmpty(sha512x256)(0xc672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967an), | ||
sha512x224: () => checkEmpty(sha512x224)(0x6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4n), | ||
sha256: () => checkEmpty(sha256)(0x1e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855n), | ||
sha224: () => checkEmpty(sha224)(0x1d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42fn), | ||
sha512: () => checkEmpty(sha512)(0x1cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3en), | ||
sha384: () => checkEmpty(sha384)(0x138b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95bn), | ||
sha512x256: () => checkEmpty(sha512x256)(0x1c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967an), | ||
sha512x224: () => checkEmpty(sha512x224)(0x16ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4n), | ||
}, | ||
utf8: [ | ||
() => { | ||
const s = msbUtf8("The quick brown fox jumps over the lazy dog"); | ||
let state = sha224.init; | ||
state = sha224.append(state)(s); | ||
const h = sha224.end(state); | ||
if (h !== 0x730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525n) { | ||
throw h; | ||
const e = 0x1730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525n; | ||
{ | ||
const s = msbUtf8("The quick brown fox jumps over the lazy dog"); | ||
const h = computeSync(sha224)([s]); | ||
if (h !== e) { | ||
throw h; | ||
} | ||
} | ||
{ | ||
const s = ['The', ' quick', ' brown', ' fox', ' jumps', ' over', ' the', ' lazy', ' dog']; | ||
const h = computeSync(sha224)(map(msbUtf8)(s)); | ||
if (h !== e) { | ||
throw h; | ||
} | ||
} | ||
}, | ||
() => { | ||
const s = msbUtf8("The quick brown fox jumps over the lazy dog."); | ||
let state = sha224.init; | ||
state = sha224.append(state)(s); | ||
const h = sha224.end(state); | ||
if (h !== 0x619cba8e8e05826e9b8c519c0a5c68f4fb653e8a3d8aa04bb2c8cd4cn) { | ||
const h = computeSync(sha224)([s]); | ||
if (h !== 0x1619cba8e8e05826e9b8c519c0a5c68f4fb653e8a3d8aa04bb2c8cd4cn) { | ||
throw h; | ||
@@ -109,3 +116,3 @@ } | ||
const h = sha256.end(state); | ||
if (h !== 0xb94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9n) { | ||
if (h !== 0x1b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9n) { | ||
throw h; | ||
@@ -123,3 +130,3 @@ } | ||
const h = sha256.end(state); | ||
if (h >> 224n !== 0x8a83665fn) { | ||
if (h >> 224n !== 0x18a83665fn) { | ||
throw h; | ||
@@ -133,3 +140,3 @@ } | ||
const h = sha256.end(state); | ||
if (h !== 0x3138bb9bc78df27c473ecfd1410f7bd45ebac1f59cf3ff9cfe4db77aab7aedd3n) { | ||
if (h !== 0x13138bb9bc78df27c473ecfd1410f7bd45ebac1f59cf3ff9cfe4db77aab7aedd3n) { | ||
throw h; | ||
@@ -136,0 +143,0 @@ } |
{ | ||
"name": "functionalscript", | ||
"version": "0.4.2", | ||
"version": "0.4.3", | ||
"type": "module", | ||
@@ -5,0 +5,0 @@ "files": [ |
/** | ||
* A collection of utility functions for working with `bigint` values. | ||
* Utility functions for working with `bigint` values. | ||
* | ||
@@ -17,2 +17,3 @@ * @module | ||
* const m = min(3n)(13n) // 3n | ||
* const c = combination([3n, 2n, 1n]) // 60n | ||
* ``` | ||
@@ -23,8 +24,57 @@ */ | ||
import { type List } from '../list/module.f.ts'; | ||
/** | ||
* Type representing a unary operation on `bigint`. | ||
*/ | ||
export type Unary = Operator.Unary<bigint, bigint>; | ||
/** | ||
* Type representing a reduction operation on `bigint` values. | ||
*/ | ||
export type Reduce = Operator.Reduce<bigint>; | ||
/** | ||
* Adds two `bigint` values. | ||
* | ||
* @param a - The first bigint value. | ||
* @returns A function that takes the second bigint value and returns the sum. | ||
*/ | ||
export declare const addition: Reduce; | ||
/** | ||
* Calculates the sum of a list of `bigint` values. | ||
* | ||
* @param input - A list of bigint values. | ||
* @returns The sum of all values in the list. | ||
*/ | ||
export declare const sum: (input: List<bigint>) => bigint; | ||
/** | ||
* Multiplies two `bigint` values. | ||
* | ||
* @param a - The first bigint value. | ||
* @returns A function that takes the second bigint value and returns the product. | ||
*/ | ||
export declare const multiple: Reduce; | ||
/** | ||
* Calculates the product of a list of `bigint` values. | ||
* | ||
* @param input - A list of bigint values. | ||
* @returns The product of all values in the list. | ||
*/ | ||
export declare const product: (input: List<bigint>) => bigint; | ||
/** | ||
* Calculates the absolute value of a `bigint`. | ||
* | ||
* @param a - The bigint value. | ||
* @returns The absolute value of the input bigint. | ||
*/ | ||
export declare const abs: Unary; | ||
/** | ||
* Determines the sign of a `bigint`. | ||
* @param a - The bigint value. | ||
* @returns `1` if positive, `-1` if negative, and `0` if zero. | ||
*/ | ||
export declare const sign: (a: bigint) => Sign; | ||
/** | ||
* Serializes a `bigint` to a string representation. | ||
* | ||
* @param a - The bigint value. | ||
* @returns A string representation of the bigint (e.g., '123n'). | ||
*/ | ||
export declare const serialize: (a: bigint) => string; | ||
@@ -86,4 +136,35 @@ /** | ||
/** | ||
* A minimal value. | ||
* Returns the smaller of two `bigint` values. | ||
* | ||
* @param a - The first bigint. | ||
* @returns A function that takes the second bigint and returns the smaller value. | ||
*/ | ||
export declare const min: (a: bigint) => (b: bigint) => bigint; | ||
/** | ||
* Returns the larger of two `bigint` values. | ||
* | ||
* @param a - The first bigint. | ||
* @returns A function that takes the second bigint and returns the larger value. | ||
*/ | ||
export declare const max: (a: bigint) => (b: bigint) => bigint; | ||
/** | ||
* Calculates the partial factorial `b!/a!`. | ||
* | ||
* @param a - The starting bigint value. | ||
* @returns A function that takes `b` and computes `b!/a!`. | ||
*/ | ||
export declare const partialFactorial: (a: bigint) => (b: bigint) => bigint; | ||
/** | ||
* Calculates the factorial of a `bigint`. | ||
* | ||
* @param b - The bigint value. | ||
* @returns The factorial of the input. | ||
*/ | ||
export declare const factorial: (b: bigint) => bigint; | ||
/** | ||
* Calculates the number of combinations for a list of `bigint` values. | ||
* | ||
* @param k - A list of bigint values. | ||
* @returns The number of combinations. | ||
*/ | ||
export declare const combination: (...k: readonly bigint[]) => bigint; |
/** | ||
* A collection of utility functions for working with `bigint` values. | ||
* Utility functions for working with `bigint` values. | ||
* | ||
@@ -17,2 +17,3 @@ * @module | ||
* const m = min(3n)(13n) // 3n | ||
* const c = combination([3n, 2n, 1n]) // 60n | ||
* ``` | ||
@@ -22,6 +23,49 @@ */ | ||
import { reduce } from "../list/module.f.js"; | ||
/** | ||
* Adds two `bigint` values. | ||
* | ||
* @param a - The first bigint value. | ||
* @returns A function that takes the second bigint value and returns the sum. | ||
*/ | ||
export const addition = a => b => a + b; | ||
/** | ||
* Calculates the sum of a list of `bigint` values. | ||
* | ||
* @param input - A list of bigint values. | ||
* @returns The sum of all values in the list. | ||
*/ | ||
export const sum = reduce(addition)(0n); | ||
/** | ||
* Multiplies two `bigint` values. | ||
* | ||
* @param a - The first bigint value. | ||
* @returns A function that takes the second bigint value and returns the product. | ||
*/ | ||
export const multiple = a => b => a * b; | ||
/** | ||
* Calculates the product of a list of `bigint` values. | ||
* | ||
* @param input - A list of bigint values. | ||
* @returns The product of all values in the list. | ||
*/ | ||
export const product = reduce(multiple)(1n); | ||
/** | ||
* Calculates the absolute value of a `bigint`. | ||
* | ||
* @param a - The bigint value. | ||
* @returns The absolute value of the input bigint. | ||
*/ | ||
export const abs = a => a >= 0 ? a : -a; | ||
/** | ||
* Determines the sign of a `bigint`. | ||
* @param a - The bigint value. | ||
* @returns `1` if positive, `-1` if negative, and `0` if zero. | ||
*/ | ||
export const sign = (a) => unsafeCmp(a)(0n); | ||
/** | ||
* Serializes a `bigint` to a string representation. | ||
* | ||
* @param a - The bigint value. | ||
* @returns A string representation of the bigint (e.g., '123n'). | ||
*/ | ||
export const serialize = (a) => `${a}n`; | ||
@@ -144,4 +188,56 @@ const { isFinite } = Number; | ||
/** | ||
* A minimal value. | ||
* Returns the smaller of two `bigint` values. | ||
* | ||
* @param a - The first bigint. | ||
* @returns A function that takes the second bigint and returns the smaller value. | ||
*/ | ||
export const min = (a) => (b) => a < b ? a : b; | ||
/** | ||
* Returns the larger of two `bigint` values. | ||
* | ||
* @param a - The first bigint. | ||
* @returns A function that takes the second bigint and returns the larger value. | ||
*/ | ||
export const max = (a) => (b) => a < b ? b : a; | ||
/** | ||
* Calculates the partial factorial `b!/a!`. | ||
* | ||
* @param a - The starting bigint value. | ||
* @returns A function that takes `b` and computes `b!/a!`. | ||
*/ | ||
export const partialFactorial = (a) => (b) => { | ||
let result = b; | ||
while (true) { | ||
--b; | ||
if (b <= a) { | ||
return result; | ||
} | ||
result *= b; | ||
} | ||
}; | ||
/** | ||
* Calculates the factorial of a `bigint`. | ||
* | ||
* @param b - The bigint value. | ||
* @returns The factorial of the input. | ||
*/ | ||
export const factorial = partialFactorial(1n); | ||
/** | ||
* Calculates the number of combinations for a list of `bigint` values. | ||
* | ||
* @param k - A list of bigint values. | ||
* @returns The number of combinations. | ||
*/ | ||
export const combination = (...k) => { | ||
let s = 0n; | ||
let m = 1n; | ||
let p = 1n; | ||
for (let i of k) { | ||
s += i; | ||
if (i >= m) { | ||
[i, m] = [m, i]; | ||
} | ||
p *= factorial(i); | ||
} | ||
return partialFactorial(m)(s) / p; | ||
}; |
@@ -26,3 +26,7 @@ export declare const clz32Log2: (v: bigint) => bigint; | ||
}; | ||
factorial: () => void; | ||
combination: () => void; | ||
combination50x50: () => void; | ||
combination3: () => void; | ||
}; | ||
export default _default; |
@@ -1,2 +0,2 @@ | ||
import { sum, abs, serialize, log2, bitLength, mask, min } from "./module.f.js"; | ||
import { sum, abs, serialize, log2, bitLength, mask, min, combination, factorial } from "./module.f.js"; | ||
const oldLog2 = (v) => { | ||
@@ -177,11 +177,15 @@ if (v <= 0n) { | ||
} | ||
const c = combination(3n, 2n, 1n); // 60n | ||
if (c !== 60n) { | ||
throw c; | ||
} | ||
}, | ||
benchmark: () => { | ||
const list = { | ||
strBinLog2, | ||
strHexLog2, | ||
// strBinLog2, | ||
// strHexLog2, | ||
str32Log2, | ||
oldLog2, | ||
clz32Log2, | ||
m1023log2, | ||
// oldLog2, | ||
// clz32Log2, | ||
// m1023log2, | ||
log2, | ||
@@ -395,3 +399,59 @@ }; | ||
] | ||
}, | ||
factorial: () => { | ||
{ | ||
const r = factorial(3n); | ||
if (r !== 6n) { | ||
throw r; | ||
} | ||
} | ||
{ | ||
const r = factorial(5n); | ||
if (r !== 120n) { | ||
throw r; | ||
} | ||
} | ||
}, | ||
combination: () => { | ||
const r = combination(2n, 3n); | ||
if (r != 120n / (2n * 6n)) { | ||
throw r; | ||
} | ||
}, | ||
combination50x50: () => { | ||
{ | ||
const r = combination(1n, 1n); | ||
if (r !== 2n) { | ||
throw r; | ||
} | ||
} | ||
{ | ||
const r = combination(2n, 2n); | ||
if (r !== 6n) { | ||
throw r; | ||
} | ||
} | ||
{ | ||
const r = combination(3n, 3n); | ||
if (r !== 20n) { | ||
throw r; | ||
} | ||
} | ||
{ | ||
const r = combination(4n, 4n); | ||
if (r !== 70n) { | ||
throw r; | ||
} | ||
} | ||
}, | ||
combination3: () => { | ||
const r = combination(2n, 3n, 4n, 2n); | ||
// 2! * 3! * 4! * 2! : 2! * 2! * 3! | ||
// 2+3+4+2 = 5*6*7*8*9*10*11 | ||
// e = 5 * 6 * 7 * 8 * 9 * 10 * 11 / (2n * 2n * 6n) = | ||
// e = 5 * 7 * 2 * 9 * 10 * 11 = 69300 | ||
if (r !== 69300n) { | ||
throw r; | ||
} | ||
} | ||
}; |
@@ -9,3 +9,3 @@ import { type List, type Thunk } from '../list/module.f.ts'; | ||
*/ | ||
export declare const empty = 1n; | ||
export declare const empty: Vec; | ||
/** | ||
@@ -12,0 +12,0 @@ * Calculates the length of the given vector of bits. |
@@ -7,1 +7,5 @@ import { type List } from '../list/module.f.ts'; | ||
export declare const cmp: (a: number) => (b: number) => Sign; | ||
/** | ||
* Count a number of ones in 32 bit number | ||
*/ | ||
export declare const countOnes: (n: number) => number; |
@@ -8,1 +8,17 @@ import { reduce } from "../list/module.f.js"; | ||
export const cmp = unsafeCmp; | ||
const mo = [ | ||
[0x5555_5555, 1], | ||
[0x3333_3333, 2], | ||
[0x0F0F_0F0F, 4], | ||
[0x00FF_00FF, 8], | ||
[0x0000_FFFF, 16], | ||
]; | ||
/** | ||
* Count a number of ones in 32 bit number | ||
*/ | ||
export const countOnes = (n) => { | ||
for (const [mask, offset] of mo) { | ||
n = (n & mask) + ((n >> offset) & mask); | ||
} | ||
return n; | ||
}; |
@@ -10,3 +10,4 @@ declare const _default: { | ||
standard: () => void; | ||
countOnes: (() => void)[]; | ||
}; | ||
export default _default; |
@@ -1,2 +0,2 @@ | ||
import { sum, min, max, cmp } from "./module.f.js"; | ||
import { sum, min, max, cmp, countOnes } from "./module.f.js"; | ||
export default { | ||
@@ -37,3 +37,3 @@ sum: () => { | ||
const check = a => b => { | ||
if (BigInt(Number(a)) != b) { | ||
if (BigInt(Number(a)) !== b) { | ||
throw [a, b]; | ||
@@ -123,3 +123,19 @@ } | ||
check(142693895881191444n)(142693895881191440n); | ||
} | ||
}, | ||
countOnes: [ | ||
() => { | ||
// 1121 2231 = 5 + 8 = 13 | ||
const r = countOnes(0x1234_5678); | ||
if (r !== 13) { | ||
throw r; | ||
} | ||
}, | ||
() => { | ||
// 2232 3340 = 9 + 10 = 19 | ||
const r = countOnes(0x9ABC_DEF0); | ||
if (r !== 19) { | ||
throw r; | ||
} | ||
} | ||
] | ||
}; |
566195
225
16209