├── .gitattributes ├── tsconfig.json ├── .gitignore ├── package.json ├── src ├── index.ts ├── utils.ts ├── decimal.ts ├── floating.ts ├── multiply.ts ├── eval.ts ├── bitwise.ts ├── integer.ts └── add.ts ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "commonjs", 5 | "incremental": true, 6 | "esModuleInterop": true, 7 | "moduleResolution": "node", 8 | "allowJs": true, 9 | "outDir": "dist" 10 | }, 11 | "include": [ 12 | "src" 13 | ] 14 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | temp 3 | 4 | todo.md 5 | yarn.lock 6 | node_modules/ 7 | npm-debug.log 8 | yarn-debug.log 9 | yarn-error.log 10 | package-lock.json 11 | tsconfig.tsbuildinfo 12 | report.*.json 13 | 14 | .eslintcache 15 | .DS_Store 16 | .idea 17 | .vscode 18 | .yarn 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typed-eval", 3 | "description": "Type-based calculation does right.", 4 | "version": "2.1.0", 5 | "main": "dist/index.js", 6 | "typings": "dist/index.d.ts", 7 | "files": [ 8 | "lib" 9 | ], 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/shigma/typed-eval.git" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/shigma/typed-eval/issues" 16 | }, 17 | "homepage": "https://github.com/shigma/typed-eval", 18 | "author": "Shigma <1700011071@pku.edu.cn>", 19 | "license": "MIT", 20 | "keywords": [ 21 | "type", 22 | "typings", 23 | "typescript", 24 | "math", 25 | "eval", 26 | "ieee754", 27 | "float", 28 | "int32", 29 | "int64", 30 | "double", 31 | "calc" 32 | ], 33 | "devDependencies": { 34 | "typescript": "^4.9.5" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { sub, add } from './add' 2 | import { calc } from './eval' 3 | import { divmod, mul } from './multiply' 4 | 5 | export * from './add' 6 | export * from './bitwise' 7 | export * from './decimal' 8 | export * from './eval' 9 | export * from './floating' 10 | export * from './integer' 11 | export * from './multiply' 12 | export * from './add' 13 | export * from './utils' 14 | 15 | type P1 = add<114514, 1919810> 16 | // ^? 17 | 18 | const P2 = add(114514, -1919810) 19 | // ^? 20 | 21 | type S1 = sub<-114514, 1919810> 22 | // ^? 23 | 24 | const S2 = sub(-114514, -1919810) 25 | // ^? 26 | 27 | type M1 = mul<114, 514> 28 | // ^? 29 | 30 | const M2 = mul(2000, 5000) 31 | // ^? 32 | 33 | type D1 = divmod<10, 3> 34 | // ^? 35 | 36 | const D2 = divmod(-514, 114) 37 | // ^? 38 | 39 | type C1 = calc<'114 + 514 + 1919 + 810'> 40 | // ^? 41 | 42 | const C2 = calc('100 - (2 - 3 * 4) * 5') 43 | // ^? 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Shigma 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | export type numeric = number | bigint 2 | export type primitive = string | numeric | boolean | null | undefined 3 | export type digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 4 | 5 | export type ToString = `${T}` 6 | export type ToNumber = T extends `${infer N extends number}` ? N : never 7 | export type ToBigInt = T extends `${infer N extends bigint}` ? N : never 8 | 9 | export type PadStart = 10 | | R['length'] extends T 11 | ? R 12 | : PadStart 13 | 14 | export type PadEnd = 15 | | R['length'] extends T 16 | ? R 17 | : PadEnd 18 | 19 | export type TrimStart = 20 | | T extends [V, ...infer R extends number[]] 21 | ? TrimStart 22 | : T 23 | 24 | export type TrimEnd = 25 | | T extends [...infer L extends number[], V] 26 | ? TrimEnd 27 | : T 28 | 29 | export type Last = 30 | | T extends [...number[], infer R extends number] 31 | ? R 32 | : never 33 | 34 | export type Rest = 35 | | T extends [number, ...infer R extends number[]] 36 | ? R 37 | : [] 38 | 39 | export type OrMap = [[0, 1], [1, 1]] 40 | export type AndMap = [[0, 0], [0, 1]] 41 | export type XorMap = [[0, 1], [1, 0]] 42 | export type NotMap = [1, 0] 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # typed-eval 2 | 3 | Type-based high-precision computation does right. 4 | 5 | ## Features 6 | 7 | - Data types: int32, int64, float (WIP), double (WIP) 8 | - Operators: 9 | - Arithmetic: `+`, `-`, `*`, `%`, `//`, `/` (WIP), `**` (WIP) 10 | - Comparison: `>`, `<`, `>=`, `<=`, `==`, `!=` 11 | - Bitwise: `&`, `|`, `^`, `~` (WIP), `<<`, `>>`, `>>>` 12 | - Logical: `&&` (WIP), `||` (WIP), `!` (WIP) 13 | - Parentheses: `()` 14 | - Expression with operator precedence 15 | 16 | ## Basic Usage 17 | 18 | ```ts 19 | import { add, sub, mul, divmod, calc } from 'typed-eval' 20 | 21 | type P1 = add<114514, 1919810> 22 | // ^? type P1 = 2034324 23 | 24 | const P2 = add(114514, -1919810) 25 | // ^? const P2 = -1805296 26 | 27 | type S1 = sub<-114514, 1919810> 28 | // ^? type S1 = -2034324 29 | 30 | const S2 = sub(-114514, -1919810) 31 | // ^? const S2 = 1805296 32 | 33 | type M1 = mul<114, 514> 34 | // ^? type M1 = 58596 35 | 36 | const M2 = mul(2000, 5000) 37 | // ^? type M2 = 10000000 38 | 39 | type D1 = divmod<10, 3> 40 | // ^? type D1 = [3, 1] 41 | 42 | const D2 = divmod(-514, 114) 43 | // ^? const D2 = [-4, -58] 44 | 45 | type C1 = calc<'114 + 514 + 1919 + 810'> 46 | // ^? type C1: 3357 47 | 48 | const C2 = calc('100 - (2 - 3 * 4) * 5') 49 | // ^? const C2: 150 50 | ``` 51 | 52 | ## Advanced Usage 53 | 54 | Computations are performed under 32-bit (int32 and float) by default. 55 | You can change the data type by importing the corresponding namespace. 56 | 57 | ```ts 58 | import { int32, int64 } from 'typed-eval' 59 | 60 | // compute under int32 (by default) 61 | type M1 = int32.mul<11111111, 11111111> 62 | // ^? type M1 = -2047269199 (overflow) 63 | 64 | // compute under int64 65 | type M2 = int64.mul<11111111, 11111111> 66 | // ^? type M2 = 123456787654321 67 | ``` 68 | 69 | Note that due to the stack depth limitation of TypeScript, computations under 64-bit types may fail. 70 | 71 | ## License 72 | 73 | Released under the [MIT](./LICENSE) license. 74 | -------------------------------------------------------------------------------- /src/decimal.ts: -------------------------------------------------------------------------------- 1 | import { TrimEnd } from './utils' 2 | 3 | export namespace Digits { 4 | export type Encode = 5 | | A extends [infer L extends number, ...infer R extends number[]] 6 | ? Encode 7 | : S 8 | 9 | export type Decode = 10 | | T extends `${infer L extends number}${infer R}` 11 | ? Decode 12 | : U 13 | } 14 | 15 | export type Concat = 16 | | A extends [infer L extends number[], ...infer R extends number[][]] 17 | ? Concat 18 | : S 19 | 20 | export type Slice = 21 | | U extends [...infer A extends number[][], infer B extends number[]] 22 | ? S extends [infer X extends number, ...infer Y extends number[]] 23 | ? B['length'] extends X 24 | ? Slice 25 | : T extends [infer L extends number, ...infer R extends number[]] 26 | ? Slice 27 | : never 28 | : [...A, T] 29 | : never 30 | 31 | type FromInteger = 32 | | A extends '0' 33 | ? [] 34 | : Digits.Decode 35 | 36 | type _Encode = 37 | | T extends `${infer L}.${infer R}` 38 | ? [FromInteger, Digits.Decode] 39 | : [FromInteger, []] 40 | 41 | type ToInteger = 42 | | A['length'] extends 0 43 | ? '0' 44 | : Digits.Encode 45 | 46 | type ToFractional = 47 | | A['length'] extends 0 48 | ? '' 49 | : `.${Digits.Encode}` 50 | 51 | export type Decimal = [sign: number, integer: number[], fractional: number[]] 52 | 53 | export namespace Decimal { 54 | export type Decode = 55 | | T extends `-${infer R}` 56 | ? [1, ..._Encode] 57 | : [0, ..._Encode] 58 | 59 | export type Encode = 60 | | `${['', '-'][X[0]]}${ToInteger}${ToFractional>}` 61 | } 62 | 63 | export type Scientific = [sign: number, exponent: number, digits: number[]] 64 | 65 | export namespace Scientific { 66 | export type Encode = 67 | | `${['', '-'][X[0]]}${ToFractional}e${X[1]}` 68 | } 69 | -------------------------------------------------------------------------------- /src/floating.ts: -------------------------------------------------------------------------------- 1 | import { Concat, Decimal, Digits, Slice } from './decimal' 2 | import { Binary, Integer } from './integer' 3 | import { numeric, PadStart, Rest, ToNumber, ToString, TrimEnd } from './utils' 4 | 5 | export namespace Fractional { 6 | export type Encode = 7 | | R['length'] extends T 8 | ? Binary.Round, R> 9 | : Binary.Mul2 extends [infer Y extends number[], infer S extends number] 10 | ? Encode 11 | : never 12 | 13 | export type Decode = 14 | | X extends [...infer L extends number[], infer R extends number] 15 | ? Decode[0]> 16 | : V 17 | } 18 | 19 | export type Floating = [sign: number[], exponent: number[], mantissa: number[]] 20 | 21 | export namespace Floating { 22 | export type Encode = [ 23 | [D[0]], 24 | Integer.Add['length']>>>>>, 25 | Rest>>, 26 | ] 27 | 28 | type DecimalRound = 29 | | S[1] extends [] 30 | ? S[0] 31 | : S[1] extends [5] 32 | ? S[0] // FIXME 33 | : S[0] // FIXME 34 | 35 | export type Decode = 36 | | Slice>>>]> extends [infer L extends number[], infer R extends number[]] 37 | ? Binary.Decode<[1, ...L]> extends infer U extends number[] 38 | ? [F[0][0], U, DecimalRound, [T], [U]>> extends [...U, ...infer V extends number[]] ? V : never] 39 | : never 40 | : never 41 | } 42 | 43 | export namespace float { 44 | export type Encode = Floating.Encode>, 24, [0, 1, 1, 1, 1, 1, 1, 0]> 45 | export type Decode = ToNumber>> 46 | 47 | // @ts-expect-error 48 | export type encode = Digits.Encode>> 49 | export type decode = Decode, [1, 8]>> 50 | } 51 | -------------------------------------------------------------------------------- /src/multiply.ts: -------------------------------------------------------------------------------- 1 | import { int32, Integer } from './integer' 2 | import { numeric, PadEnd, PadStart, XorMap } from './utils' 3 | 4 | declare module './integer' { 5 | namespace Integer { 6 | export type Mul = 7 | | A extends [...infer X extends number[], infer Z extends number] 8 | ? B extends [number, ...infer Y extends number[]] 9 | ? Z extends 0 10 | ? Mul 11 | : Add> 12 | : O 13 | : O 14 | 15 | type _DivMod = 16 | | B extends [...infer X extends number[], infer Y extends number] 17 | ? C extends [...infer Z extends number[], number] 18 | ? [Y, ...Z] extends O 19 | ? _DivMod 20 | : Gte extends 0 21 | ? _DivMod 22 | : _DivMod, X, O, [Y, ...Z], [...Q, 1]> 23 | : [Q, A] 24 | : [Q, A] 25 | 26 | export type DivMod = 27 | | _DivMod, Flip, O> extends [infer Q extends Integer, infer R extends Integer] 28 | ? [Flip, Flip] 29 | : never 30 | } 31 | 32 | namespace int32 { 33 | export type mul = Decode, Encode, Zero>> 34 | export type div = divmod[0] 35 | export type mod = divmod[1] 36 | export type divmod = 37 | | Integer.DivMod, Encode, Zero> extends [infer Q extends Integer, infer R extends Integer] 38 | ? [Decode, Decode] 39 | : never 40 | } 41 | 42 | namespace int64 { 43 | export type mul = Decode, Encode, Zero>> 44 | export type div = divmod[0] 45 | export type mod = divmod[1] 46 | export type divmod = 47 | | Integer.DivMod, Encode, Zero> extends [infer Q extends Integer, infer R extends Integer] 48 | ? [Decode, Decode] 49 | : never 50 | } 51 | } 52 | 53 | export type mul = int32.mul 54 | export function mul(x: X, y: Y): mul { 55 | return (x * y) as any 56 | } 57 | 58 | export type divmod = int32.divmod 59 | export function divmod(x: X, y: Y): divmod { 60 | const r = x % y 61 | const q = (x - r) / y 62 | return [q, r] as any 63 | } 64 | 65 | export type div = int32.div 66 | export function div(x: X, y: Y): div { 67 | return divmod(x, y)[0] as any 68 | } 69 | 70 | export type mod = int32.mod 71 | export function mod(x: X, y: Y): mod { 72 | return divmod(x, y)[1] as any 73 | } 74 | -------------------------------------------------------------------------------- /src/eval.ts: -------------------------------------------------------------------------------- 1 | import { sub, add, lt, gt, lte, gte, eq, ne } from './add' 2 | import { and, lshift, or, rshift, urshift, xor } from './bitwise' 3 | import { div, mod, mul } from './multiply' 4 | import { digit, ToNumber } from './utils' 5 | 6 | type Precedence = [ 7 | '**', 8 | '*' | '/' | '//' | '%', 9 | '+' | '-', 10 | '<<' | '>>' | '>>>', 11 | '<' | '<=' | '>' | '>=', 12 | '==' | '!=', 13 | '&', 14 | '^', 15 | '|', 16 | '&&', 17 | '||', 18 | ] 19 | 20 | type Operators = [ 21 | '>>>', 22 | '**' | '//' | '<<' | '>>' | '==' | '!=' | '&&' | '||' | '<=' | '>=', 23 | '*' | '/' | '%' | '+' | '-' | '<' | '>' | '&' | '^' | '|' | '(' | ')', 24 | ] 25 | 26 | type LexerNumber = 27 | | S extends `${infer L extends digit}${infer R}` 28 | ? LexerNumber 29 | : [ToNumber, ...Lexer] 30 | 31 | type Lexer = 32 | | S extends ` ${infer R}` 33 | ? Lexer 34 | : S extends `${digit}${string}` 35 | ? LexerNumber 36 | : S extends `${Operators[0]}${infer R}` 37 | ? S extends `${infer L}${R}` ? [L, ...Lexer] : never 38 | : S extends `${Operators[1]}${infer R}` 39 | ? S extends `${infer L}${R}` ? [L, ...Lexer] : never 40 | : S extends `${Operators[2]}${infer R}` 41 | ? S extends `${infer L}${R}` ? [L, ...Lexer] : never 42 | : [] 43 | 44 | type Enclose = 45 | | S extends ['(', ...infer V] 46 | ? Parser 47 | : S extends [infer U, ...infer V] 48 | ? [U, ...Enclose] 49 | : never 50 | 51 | type Precedent = 52 | | P extends [infer L extends string, ...infer R extends string[]] 53 | ? K extends L ? L : L | Precedent 54 | : never 55 | 56 | type Parser = 57 | | T extends ['(', ...infer R] 58 | ? Parser 59 | : T extends [')', ...infer R] 60 | ? Enclose 61 | : T extends [infer L extends Precedence[number], ...infer R] 62 | ? S extends [infer U extends Precedent, ...infer V] 63 | ? [U, ...Parser] 64 | : Parser 65 | : T extends [infer L, ...infer R] 66 | ? [L, ...Parser] 67 | : S 68 | 69 | interface BinaryOperator { 70 | '+': add 71 | '-': sub 72 | '*': mul 73 | '/': div 74 | '//': div 75 | '%': mod 76 | '<': lt 77 | '>': gt 78 | '<=': lte 79 | '>=': gte 80 | '==': eq 81 | '!=': ne 82 | '&': and 83 | '|': or 84 | '^': xor 85 | '<<': lshift 86 | '>>': rshift 87 | '>>>': urshift 88 | } 89 | 90 | type Calc = 91 | | T extends [infer K extends keyof BinaryOperator, ...infer R] 92 | ? S extends [infer U extends number, infer V extends number, ...infer W] 93 | ? Calc[K], ...W]> 94 | : never 95 | : T extends [infer L extends number, ...infer R] 96 | ? Calc 97 | : S[0] 98 | 99 | export type calc = Calc>> 100 | export function calc(expr: S): calc { 101 | return eval(expr) 102 | } 103 | -------------------------------------------------------------------------------- /src/bitwise.ts: -------------------------------------------------------------------------------- 1 | import { int32 } from './integer' 2 | import { AndMap, numeric, OrMap, XorMap } from './utils' 3 | 4 | declare module './integer' { 5 | export type And = 6 | | A extends [number, ...infer X extends number[]] 7 | ? B extends [number, ...infer Y extends number[]] 8 | ? And 9 | : R 10 | : R 11 | 12 | export type Or = 13 | | A extends [number, ...infer X extends number[]] 14 | ? B extends [number, ...infer Y extends number[]] 15 | ? Or 16 | : R 17 | : R 18 | 19 | export type Xor = 20 | | A extends [number, ...infer X extends number[]] 21 | ? B extends [number, ...infer Y extends number[]] 22 | ? Xor 23 | : R 24 | : R 25 | 26 | export type LShift = 27 | | C['length'] extends B 28 | ? A 29 | : A extends [number, ...infer X extends number[]] 30 | ? LShift<[...X, 0], B, [...C, 0]> 31 | : never 32 | 33 | export type RShift = 34 | | C['length'] extends B 35 | ? A 36 | : A extends [...infer X extends number[], number] 37 | ? RShift<[A[0], ...X], B, [...C, 0]> 38 | : never 39 | 40 | export type URShift = 41 | | C['length'] extends B 42 | ? A 43 | : A extends [...infer X extends number[], number] 44 | ? RShift<[0, ...X], B, [...C, 0]> 45 | : never 46 | 47 | namespace int32 { 48 | export type and = Decode, Encode>> 49 | export type or = Decode, Encode>> 50 | export type xor = Decode, Encode>> 51 | export type lshift = Decode, Y>> 52 | export type rshift = Decode, Y>> 53 | export type urshift = Decode, Y>> 54 | } 55 | 56 | namespace int64 { 57 | export type and = Decode, Encode>> 58 | export type or = Decode, Encode>> 59 | export type xor = Decode, Encode>> 60 | export type lshift = Decode, Y>> 61 | export type rshift = Decode, Y>> 62 | export type urshift = Decode, Y>> 63 | } 64 | } 65 | 66 | export type and = int32.and 67 | export function and(x: X, y: Y): and { 68 | return (x & y) as any 69 | } 70 | 71 | export type or = int32.or 72 | export function or(x: X, y: Y): or { 73 | return (x | y) as any 74 | } 75 | 76 | export type xor = int32.xor 77 | export function xor(x: X, y: Y): xor { 78 | return (x ^ y) as any 79 | } 80 | 81 | export type lshift = int32.lshift 82 | export function lshift(x: X, y: Y): lshift { 83 | return (x << y) as any 84 | } 85 | 86 | export type rshift = int32.rshift 87 | export function rshift(x: X, y: Y): rshift { 88 | return (x >> y) as any 89 | } 90 | 91 | export type urshift = int32.urshift 92 | export function urshift(x: X, y: Y): urshift { 93 | return (x >>> y) as any 94 | } 95 | -------------------------------------------------------------------------------- /src/integer.ts: -------------------------------------------------------------------------------- 1 | import { AndMap, Last, numeric, OrMap, PadStart, ToBigInt, ToNumber, ToString, XorMap } from './utils' 2 | import { Decimal, Digits } from './decimal' 3 | 4 | export namespace Binary { 5 | export type Carry = 6 | | A extends [...infer X extends number[], infer U extends number] 7 | ? Carry 8 | : R 9 | 10 | export type Round = 11 | | X extends [] 12 | ? R 13 | : X extends [5] 14 | ? Carry> 15 | : Carry 16 | 17 | export namespace Div2 { 18 | export type Result = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4] 19 | export type Carry = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] 20 | export type Matrix = [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]] 21 | } 22 | 23 | type TrimFirst = T extends [0, ...infer R extends number[]] ? R : T 24 | 25 | export type Div2 = 26 | | A extends [infer X extends number, ...infer Y extends number[]] 27 | ? Div2 28 | : [TrimFirst, C] 29 | 30 | export type Encode = 31 | | X extends [...number[], infer Y extends number] 32 | ? Encode[0], [Div2.Carry[Y], ...R]> 33 | : R 34 | 35 | export namespace Mul2 { 36 | export type Result = [0, 1, 2, 3, 4, 0, 1, 2, 3, 4] 37 | export type Carry = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] 38 | export type Matrix = [[0, 2, 4, 6, 8], [1, 3, 5, 7, 9]] 39 | } 40 | 41 | type PadFirst = T[1] extends 0 ? T[0] : [1, ...T[0]] 42 | 43 | export type Mul2 = 44 | | A extends [...infer X extends number[], infer Y extends number] 45 | ? Mul2 46 | : [R, C] 47 | 48 | export type Decode = 49 | | X extends [infer L extends number, ...infer R extends number[]] 50 | ? Decode>> 51 | : V 52 | } 53 | 54 | export type Complement = 55 | | A extends [...infer L extends number[], infer R extends number] 56 | ? [...Complement, XorMap[S][R]] 57 | : [] 58 | 59 | export type Flip = S extends 0 ? X : Complement 60 | 61 | export type Integer = number[] 62 | 63 | export namespace Integer { 64 | export type Encode = Flip>, X[0]> 65 | export type Decode = [X[0], Binary.Decode>, []] 66 | } 67 | 68 | export namespace int32 { 69 | export type Encode = Integer.Encode>, 32> 70 | export type Decode = ToNumber>> 71 | export type Zero = PadStart<32, 0> 72 | 73 | export type encode = Digits.Encode> 74 | export function encode(x: S): encode { 75 | if (x >= 0) return x.toString(2).padStart(32, '0') as any 76 | let y = (-1 - x).toString(2) 77 | if (y === '0') y = '' 78 | return y.padStart(32, '1') as any 79 | } 80 | 81 | export type decode = Decode> 82 | export function decode(s: S): decode { 83 | const v = parseInt(s, 2) 84 | if (!s[31]) return v as any 85 | return v - (1 << 32) as any 86 | } 87 | } 88 | 89 | export namespace int64 { 90 | export type Encode = Integer.Encode>, 64> 91 | export type Decode = ToBigInt>> 92 | export type Zero = PadStart<64, 0> 93 | 94 | export type encode = Digits.Encode> 95 | export function encode(x: S): encode { 96 | if (x >= 0) return x.toString(2).padStart(32, '0') as any 97 | let y = (-1 - x).toString(2) 98 | if (y === '0') y = '' 99 | return y.padStart(32, '1') as any 100 | } 101 | 102 | export type decode = Decode> 103 | export function decode(s: S): decode { 104 | const v = (BigInt(parseInt(s.slice(0, 32), 2)) << 32n) + BigInt(parseInt(s.slice(32), 2)) 105 | if (!s[63]) return v as any 106 | return v - (1n << 64n) as any 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/add.ts: -------------------------------------------------------------------------------- 1 | import { int32 } from './integer' 2 | import { AndMap, NotMap, numeric, OrMap, XorMap } from './utils' 3 | 4 | declare module './integer' { 5 | namespace Integer { 6 | export type Add = 7 | | A extends [...infer X extends number[], infer U extends number] 8 | ? B extends [...infer Y extends number[], infer V extends number] 9 | ? Add 10 | : R 11 | : R 12 | 13 | export type Sub = Add> 14 | 15 | export type Eq = 16 | | A extends [infer U extends number, ...infer X extends number[]] 17 | ? B extends [infer V extends number, ...infer Y extends number[]] 18 | ? XorMap[U][V] extends 0 ? Eq : 0 19 | : 1 20 | : 1 21 | 22 | export type Gt = 23 | | A extends [infer U extends number, ...infer X extends number[]] 24 | ? B extends [infer V extends number, ...infer Y extends number[]] 25 | ? XorMap[U][V] extends 0 ? Gt : U 26 | : 0 27 | : 0 28 | 29 | export type Lt = Gt 30 | export type Ne = NotMap[Eq] 31 | export type Gte = NotMap[Gt] 32 | export type Lte = NotMap[Gt] 33 | } 34 | 35 | namespace int32 { 36 | export type add = Decode, Encode>> 37 | export type sub = Decode, Encode>> 38 | export type eq = Integer.Eq, Encode> 39 | export type ne = Integer.Ne, Encode> 40 | export type gt = Integer.Gt, Encode> 41 | export type lt = Integer.Lt, Encode> 42 | export type gte = Integer.Gte, Encode> 43 | export type lte = Integer.Lte, Encode> 44 | } 45 | 46 | namespace int64 { 47 | export type add = Decode, Encode>> 48 | export type sub = Decode, Encode>> 49 | export type eq = Integer.Eq, Encode> 50 | export type ne = Integer.Ne, Encode> 51 | export type gt = Integer.Gt, Encode> 52 | export type lt = Integer.Lt, Encode> 53 | export type gte = Integer.Gte, Encode> 54 | export type lte = Integer.Lte, Encode> 55 | } 56 | } 57 | 58 | export type add = int32.add 59 | export function add(x: X, y: Y): add { 60 | return (x + y) as any 61 | } 62 | 63 | export type sub = int32.sub 64 | export function sub(x: X, y: Y): sub { 65 | return (x - y) as any 66 | } 67 | 68 | export type eq = int32.eq 69 | export function eq(x: X, y: Y): eq { 70 | return +(x as any === y) as any 71 | } 72 | 73 | export type ne = int32.ne 74 | export function ne(x: X, y: Y): ne { 75 | return +(x as any !== y) as any 76 | } 77 | 78 | export type gt = int32.gt 79 | export function gt(x: X, y: Y): gt { 80 | return +(x > y) as any 81 | } 82 | 83 | export type gte = int32.gte 84 | export function gte(x: X, y: Y): gte { 85 | return +(x >= y) as any 86 | } 87 | 88 | export type lt = int32.lt 89 | export function lt(x: X, y: Y): lt { 90 | return +(x < y) as any 91 | } 92 | 93 | export type lte = int32.lte 94 | export function lte(x: X, y: Y): lte { 95 | return +(x <= y) as any 96 | } 97 | --------------------------------------------------------------------------------