Skip to content

Commit

Permalink
Merge pull request #77 from MajorLift/230518-number-arithmetic
Browse files Browse the repository at this point in the history
Add `Integer` type and arithmetic methods
  • Loading branch information
MajorLift authored Dec 20, 2023
2 parents 301df3b + 7244fbb commit e075f6b
Show file tree
Hide file tree
Showing 92 changed files with 4,153 additions and 30 deletions.
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ import {
$, $$, $N,
Boolean, Conditional, Function,
List, Object, String, Union,
Number, NaturalNumber,
Number, Integer, NaturalNumber,
Kind, Type, Combinator, Parser,
} from "hkt-toolbelt";
```
Expand Down
31 changes: 31 additions & 0 deletions src/digit-list/increment.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
import { Type, Kind, Digit, DigitList } from '..'

/**
* `_$increment` is a type-level function that takes in a digit list `A` and
* returns a new digit list representing the result of incrementing the input
* digit list by 1. If the input digit list is empty or represents zero, the
* result will be a digit list representing zero.
*
* @template A - A digit list type.
*
* @example
* For example, we can use `_$increment` to increment a digit list representing
* the number 42 by 1. In this example, the digit list `["4", "2"]` is passed as
* a type argument to the type-level function:
*
* ```ts
* import { DigitList } from "hkt-toolbelt";
*
* type Result = DigitList._$increment<["4", "2"]>; // ["4", "3"]
* ```
*
* @example
* We can also use `_$increment` with an empty digit list or a digit list
* representing zero. In both cases, the result will be a digit list
* representing one:
*
* ```ts
* import { DigitList } from "hkt-toolbelt";
*
* type Result1 = DigitList._$increment<[]>; // ["1"]
* type Result2 = DigitList._$increment<["0"]>; // ["1"]
* ```
*/
export type _$increment<
/**
* The digit-list to increment.
Expand Down
1 change: 1 addition & 0 deletions src/digit-list/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ export * from './subtract'
export * from './to-string'
export * from './to-number'
export * from './trim'
export * from './trim-right'
32 changes: 23 additions & 9 deletions src/digit-list/multiply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,23 +71,30 @@ type _$multiply2<
> = DONE extends true ? SUM : _$multiply2<POP_A, B, NEXT_SCALE, ADD>

/**
* `_$multiplyDigit` is a type-level function that multiplies a digit list by a single digit.
* `_$multiply` is a type-level function that multiplies a digit list by another digit list.
* It returns the result of the multiplication operation.
*
* @template A - The digit list.
* @template B - The single digit.
* @template B - A digit list.
*
* @example
* For example, we can use `_$multiplyDigit` to multiply a digit list by a single digit:
* For example, we can use `_$multiply` to multiply a digit list ["4", "2"] by another digit list ["1", "2"]:
*
* ```ts
* import { DigitList } from "hkt-toolbelt";
*
* type Result = DigitList._$multiplyDigit<["3"], "2">; // ["6"]
* type Is504 = DigitList._$multiply<["4", "2"], ["1", "2"]>; // ["5", "0", "4"]
* ```
*
* In this example, `Result` is a type that represents ["6"], which is the result of multiplying ["3"] by "2".
* @example
* If one of the inputs is an empty digit list or the zero digit, the result will be the zero digit.
*
* ```ts
* import { DigitList } from "hkt-toolbelt";
*
* type IsZero = DigitList._$multiply<["4", "2"], []>; // ["0"]
* type IsZero2 = DigitList._$multiply<["4", "2"], ["0"]>; // ["0"]
* ```
*/
export type _$multiply<
A extends DigitList.DigitList,
Expand All @@ -99,22 +106,29 @@ interface Multiply_T<T extends DigitList.DigitList> extends Kind.Kind {
}

/**
* `MultiplyDigit` is a type-level function that multiplies a digit list by a single digit.
* `Multiply` is a type-level function that multiplies a digit list by another digit list.
* It returns the result of the multiplication operation.
*
* @template A - The digit list.
* @template B - The single digit.
*
* @example
* For example, we can use `MultiplyDigit` to multiply a digit list by a single digit:
* For example, we can use `Multiply` to multiply a digit list ["4", "2"] by another digit list ["1", "2"]:
*
* ```ts
* import { $, DigitList } from "hkt-toolbelt";
*
* type Result = $<$<DigitList.MultiplyDigit, "2">, ["3"]>; // ["6"]
* type Is504 = $<$<DigitList.Multiply, ["1", "2"]>, ["4", "2"]>; // ["5", "0", "4"]
* ```
*
* In this example, `Result` is a type that represents ["6"], which is the result of multiplying ["3"] by "2".
* @example
* If one of the inputs is an empty digit list or the zero digit, the result will be the zero digit.
*
* ```ts
* import { DigitList } from "hkt-toolbelt";
*
* type IsZero = $<$<DigitList.Multiply, []>, ["4", "2"]>; // ["0"]
* type IsZero2 = $<$<DigitList.Multiply, ["0"], ["4", "2"]>; // ["0"]
*/
export interface Multiply extends Kind.Kind {
f(x: Type._$cast<this[Kind._], DigitList.DigitList>): Multiply_T<typeof x>
Expand Down
33 changes: 33 additions & 0 deletions src/digit-list/trim-right.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { $, Test, DigitList } from '..'

type TrimRight_Spec = [
/**
* Trimming zero should result in zero.
*/
Test.Expect<$<DigitList.TrimRight, ['0']>, ['0']>,

/**
* Trimming an empty zero should result in zero.
*/
Test.Expect<$<DigitList.TrimRight, []>, ['0']>,

/**
* Trimming a single digit should result in the same digit.
*/
Test.Expect<$<DigitList.TrimRight, ['1']>, ['1']>,

/**
* Trimming a digit with trailing zeros should result in the same digit.
*/
Test.Expect<$<DigitList.TrimRight, ['1', '0']>, ['1']>,

/**
* Should be able to handle multiple trailing zeros.
*/
Test.Expect<$<DigitList.TrimRight, ['1', '0', '0']>, ['1']>,

/**
* Should be able to handle all zeroes.
*/
Test.Expect<$<DigitList.TrimRight, ['0', '0', '0']>, ['0']>
]
53 changes: 53 additions & 0 deletions src/digit-list/trim-right.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Type, Kind, DigitList } from '..'

type _$trimRight2<A extends DigitList.DigitList> = A extends [
...infer Rest extends DigitList.DigitList,
'0'
]
? _$trimRight2<Rest>
: A

/**
* `_$trimRight` is a type-level function that trims trailing zeros from a digit list.
* It returns the trimmed digit list.
*
* @template A - The digit list to trim.
* @template TRIM - The digit list after trimming trailing zeros.
* @template OUTPUT - The final output after trimming. If the trimmed list is empty, it returns ["0"].
*
* @example
* For example, we can use `_$trimRight` to trim trailing zeros from a digit list:
*
* ```ts
* import { DigitList } from "hkt-toolbelt";
*
* type Result = DigitList._$trimRight<["1", "2", "3", "0"]>; // ["1", "2", "3"]
* ```
*
* In this example, `Result` is a type that represents the digit list ["1", "2", "3"], which is the result of trimming the trailing zeros from the digit list ["1", "2", "3", "0"].
*
*/
export type _$trimRight<
A extends DigitList.DigitList,
TRIM extends DigitList.DigitList = _$trimRight2<A>,
OUTPUT extends DigitList.DigitList = TRIM extends [] ? ['0'] : TRIM
> = OUTPUT

/**
* `TrimRight` is a type-level function that trims trailing zeros from a digit list.
* It returns the trimmed digit list.
*
* @template x - A digit list to trim trailing zeros from.
*
* @example
* For example, we can use `TrimRight` to trim trailing zeros from a digit list:
*
* ```ts
* import { $, DigitList } from "hkt-toolbelt";
*
* type Result = $<DigitList.TrimRight, ["3", "0", "0"]>; // ["3"]
* ```
*/
export interface TrimRight extends Kind.Kind {
f(x: Type._$cast<this[Kind._], DigitList.DigitList>): _$trimRight<typeof x>
}
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export * as Digit from './digit'
import * as Function from './function'
export * as Function from './function'

import * as Integer from './integer'
export * as Integer from './integer'

import * as Kind from './kind'
export * as Kind from './kind'

Expand Down
1 change: 1 addition & 0 deletions src/integer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './integer/'
39 changes: 39 additions & 0 deletions src/integer/add.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { $, Test, Integer } from '..'

export type Add_Spec = [
/**
* Can add two zeros.
*/
Test.Expect<$<$<Integer.Add, 0>, 0>, 0>,
Test.Expect<$<$<Integer.Add, 0>, -0>, 0>,

/**
* Can add two positive numbers.
*/
Test.Expect<$<$<Integer.Add, 5>, 5>, 10>,

/**
* Can add two negative numbers.
*/
Test.Expect<$<$<Integer.Add, -1>, -1>, -2>,
Test.Expect<$<$<Integer.Add, -7>, -4>, -11>,

/**
* Can add a positive number to a negative number.
*/
Test.Expect<$<$<Integer.Add, -1>, 0>, -1>,
Test.Expect<$<$<Integer.Add, -1>, 1>, 0>,
Test.Expect<$<$<Integer.Add, -100>, 1>, -99>,

/**
* Can add large numbers.
*/
Test.Expect<$<$<Integer.Add, 123456789>, 123456789>, 246913578>,
Test.Expect<$<$<Integer.Add, -123456789>, -123456789>, -246913578>,

/**
* Can add numbers as strings.
*/
Test.Expect<$<$<Integer.Add, '-123456789'>, '-123456789'>, -246913578>,
Test.Expect<$<$<Integer.Add, '-123456789'>, '123456789'>, 0>
]
113 changes: 113 additions & 0 deletions src/integer/add.stress.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { $, Test, Integer, List } from '..'

export type Add_Spec = [
/**
* Can add large numbers.
*/
Test.Expect<$<$<Integer.Add, -123456789>, -123456789>, -246913578>,

/**
* Can add numbers as strings.
*/
Test.Expect<$<$<Integer.Add, '-123456789'>, '-123456789'>, -246913578>,

/**
* Can add very large numbers.
*/
Test.Expect<
$<$<Integer.Add, -9007199254740991>, -9007199254740991>,
-18014398509481982
>,

/**
* Can add bigint numbers.
*/
Test.Expect<
$<$<Integer.Add, 9007199254740991n>, 9007199254740991n>,
18014398509481982
>,

/**
* Can map and add over lists.
*/
Test.Expect<
$<$<List.Map, $<Integer.Add, -10>>, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]>,
[-9, -8, -7, -6, -5, -4, -3, -2, -1, 0]
>,

/**
* Can add a lot of negative numbers in a nested way.
*/
Test.Expect<
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<
$<Integer.Add, -10>,
$<$<Integer.Add, -10>, -10>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>,
-200
>,

/**
* Can add numbers with hundreds of digits.
*/
Test.Expect<
$<
$<
Integer.Add,
'123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789'
>,
'123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789'
>,
246913578246913578246913578246913578246913578246913578246913578246913578246913578246913578246913578246913578246913578246913578246913578246913578246913578246913578246913578246913578n
>
]
Loading

0 comments on commit e075f6b

Please sign in to comment.