UNPKG

hkt-toolbelt

Version:

Functional and composable type utilities

120 lines (119 loc) 5.28 kB
import { Type, Kind, Digit, DigitList } from '..'; type _$divideBySubtraction2< /** * A represents the digit list to be divided, i.e., the dividend. */ A extends DigitList.DigitList, /** * B represents the digit list by which A is to be divided, i.e., the * divisor. */ B extends DigitList.DigitList, /** * OPERATION specifies the operation to perform (either "DIVIDE" or "MODULO"). * * Default is "DIVIDE". The reason that we 'combine' the divide and modulo * operations into one implementation is that they're very similar in nature, * and the only difference is the final result. */ OPERATION extends 'DIVIDE' | 'MODULO' = 'DIVIDE', /** * QUOTIENT is our current guess and accumulator of the result of division. * Initially, it is assigned '0' - so that we can increment it as we subtract * from the remainder. */ QUOTIENT extends DigitList.DigitList = [Digit.Zero], /** * REMAINDER or the rest of the numbers that were not yet covered by the * multiples of B, starts as the original input number A. * * As we iterate, we reduce this variable by subtracting B from it. Once * REMAINDER is less than B, we know that we've covered all the multiples of B * in A, and that the remainder is the result of the modulo operation. */ REMAINDER extends DigitList.DigitList = A, /** * NEXT_QUOTIENT prepares our next version of the quotient by incrementing * the current one, to be carried over to the next operation. */ NEXT_QUOTIENT extends DigitList.DigitList = DigitList._$increment<QUOTIENT>, /** * NEXT_REMAINDER is the result of subtracting the divisor B from the current * remainder, which will be carried into the next round of operation. */ NEXT_REMAINDER extends DigitList.DigitList = DigitList._$subtract<REMAINDER, B>, /** * PERFECTLY_DIVISIBLE indicates if the remainder is perfectly divisible by B. */ PERFECTLY_DIVISIBLE extends boolean = REMAINDER extends B ? true : false, /** * DONE is a type predicate that helps us establish if we've successfully * completed the division operation - when the remainder equals 0 or when the * number is perfectly divisible by the divisor. */ DONE extends boolean = NEXT_REMAINDER extends [Digit.Zero] ? true : PERFECTLY_DIVISIBLE, /** * DIV_RESULT holds the final result of division if A was perfectly divisible * by B. */ DIV_RESULT extends DigitList.DigitList = PERFECTLY_DIVISIBLE extends true ? NEXT_QUOTIENT : QUOTIENT, /** * MOD_RESULT holds the final result of modulo operation if A was perfectly * divisible by B. */ MOD_RESULT extends DigitList.DigitList = PERFECTLY_DIVISIBLE extends true ? [Digit.Zero] : REMAINDER, /** * RESULT holds the final result of the operation. */ RESULT extends DigitList.DigitList = OPERATION extends 'DIVIDE' ? DIV_RESULT : MOD_RESULT> = DONE extends true ? RESULT : _$divideBySubtraction2<A, B, OPERATION, NEXT_QUOTIENT, NEXT_REMAINDER>; /** * `_$divideBySubtraction` is a type-level function that performs the division or modulo operation by subtraction. * It takes in two digit lists `A` and `B` representing the dividend and divisor respectively, and an operation type * which can be either "DIVIDE" or "MODULO". It returns the result of the operation (division or substraction). * * @template A - A digit list representing a number to divide. * @template B - A digit list representing a number to divide by. * @template OPERATION - A string type representing the operation to be performed. Can be either "DIVIDE" or "MODULO". * * @example * For example, we can use `_$divideBySubtraction` to divide a digit list representing the number 10 by 2: * * ```ts * import { DigitList } from "hkt-toolbelt"; * * type Result = DigitList._$divideBySubtraction<["1", "0"], ["2"]>; // ["5"] * ``` * * @example * We can also use `_$divideBySubtraction` to find the remainder when a digit list representing the number 123 is divided by 17: * * ```ts * import { DigitList } from "hkt-toolbelt"; * * type Result = DigitList._$divideBySubtraction<["1", "2", "3"], ["1", "7"], "MODULO">; // ["4"] * ``` */ export type _$divideBySubtraction<A extends DigitList.DigitList, B extends DigitList.DigitList, OPERATION extends 'DIVIDE' | 'MODULO' = 'DIVIDE'> = B extends [Digit.Zero] ? [Digit.Zero] : B extends ['1'] ? OPERATION extends 'DIVIDE' ? A : [Digit.Zero] : _$divideBySubtraction2<A, B, OPERATION>; interface DivideBySubtraction_T<A extends DigitList.DigitList> extends Kind.Kind { f(x: Type._$cast<this[Kind._], DigitList.DigitList>): _$divideBySubtraction<A, typeof x>; } /** * `DivideBySubtraction` is a type-level function that performs a division by subtraction. * It returns the result of the division. * * @template A - A digit list representing a number to divide. * @template B - A digit list representing a number to divide by. * * @example * For example, we can use `DivideBySubtraction` to divide a digit list representing the number 10 by 2: * * ```ts * import { $, DigitList } from "hkt-toolbelt"; * * type Result = $<$<DigitList.DivideBySubtraction, ["1", "0"]>, ["2"]>; // ["5"] quotient is 5, and the remainder is 0. * ``` */ export interface DivideBySubtraction extends Kind.Kind { f(x: Type._$cast<this[Kind._], DigitList.DigitList>): DivideBySubtraction_T<typeof x>; } export {};