import type { SAdd } from "./Add"; import type { SCompare } from "./Compare"; import type { SMul } from "./Mul"; import type { SSub } from "./Sub"; import type { LT, Nat } from "../aliases"; import type { _ReplaceAllCharsWithZero } from "../internals/_ReplaceAllCharsWithZero"; import type { _StrToNum } from "../internals/_StrToNum"; import type { _RemoveStrPaddingZeroes } from "./internals/_RemoveStrPaddingZeroes"; /** * Get the quotient and remainder of dividing two {@link Nat}s. * * Sig: `(n: Nat, m: Nat) => [Nat, Nat]` */ export type DivMod = N extends N ? M extends M ? Nat extends N | M ? [Nat, Nat] : M extends 0 ? never : SDivMod<`${N}`, `${M}`> extends [infer Q extends string, infer R extends string] ? [_StrToNum, _StrToNum] : never : never : never; /** * Get the quotient and remainder of dividing two string representations of {@link Nat}s. * @private */ export type SDivMod = _TakeSameLength extends [infer Left extends string, infer Right extends string] ? _SDivMod : never; export type _SDivMod< Left extends string, Right extends string, M extends string, Q extends string, > = __SDivMod extends [infer Div extends string, infer Mod extends string] ? Right extends "" ? [SAdd, Mod] : Div extends "0" ? Right extends `${infer F}${infer R}` ? _SDivMod<`${Left}${F}`, R, M, `${Q}0`> : never : Right extends `${infer F}${infer R}` ? _SDivMod<_RemoveStrPaddingZeroes<`${Mod}${F}`>, R, M, `${SAdd}0`> : never : never; type __SDivMod = SMul extends infer R extends string ? SCompare extends LT ? __SDivMod> : [Try, SSub] : never; /** * @private * * @example * ```typescript * type R = _DivModSameLength<"4567", "12">; * // ^ = type R = ["45", "67"] * ``` */ type _TakeSameLength = N extends `${infer F}${infer R}` ? M extends `${string}${infer S}` ? _TakeSameLength : [Result, N] : [Result, ""];