math-types/src/Addition.ts

30 lines
1.6 KiB
TypeScript

import { DigitsToNumber, SplitDigits, Digit, TupleForDigit } from ".";
export type Add<A extends number, B extends number> = DigitsToNumber<AddDigitArrays<SplitDigits<A>, SplitDigits<B>>> & number
type AddDigitArrays<A extends Digit[], B extends Digit[], Carry extends boolean = false> =
[A, B] extends [[...infer HeadA extends Digit[], infer TailA extends Digit], [...infer HeadB extends Digit[], infer TailB extends Digit]]
? AddTails<HeadA, TailA, HeadB, TailB, Carry>
: [A, B] extends [[...infer HeadA extends Digit[], infer TailA extends Digit], []]
? AddTails<HeadA, TailA, [], 0, Carry>
: [A, B] extends [[], [...infer HeadB extends Digit[], infer TailB extends Digit]]
? AddTails<[], 0, HeadB, TailB, Carry>
: [A, B] extends [[], []]
? Carry extends true
? [1]
: []
: []
type AddTails<HeadA extends Digit[], TailA extends Digit, HeadB extends Digit[], TailB extends Digit, Carry extends boolean> =
SplitDigits<AddDigits<TailA, TailB, Carry>> extends [1, infer Result extends Digit]
? [...AddDigitArrays<HeadA, HeadB, true>, Result]
: [...AddDigitArrays<HeadA, HeadB>, SplitDigits<AddDigits<TailA, TailB, Carry>>[0]]
type AddDigits<A extends Digit, B extends Digit, Carry extends boolean = false> =
[...TupleForDigit<A>, ...TupleForDigit<B>, ...(Carry extends false ? [] : [0])]['length'] & number
export function add<A extends number, B extends number>(a: A, b: B) {
return a + b as Add<A, B>
}