30 lines
1.6 KiB
TypeScript
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>
|
|
}
|