//================================================================ /** * @packageDocumentation * @module std */ //================================================================ import { IForwardIterator } from "../iterator/IForwardIterator"; import { General } from "../internal/functional/General"; import { Writeonly } from "../internal/functional/Writeonly"; import { plus, minus, multiplies } from "./operators"; import { IPointer } from "../functional/IPointer"; /** * Greatest Common Divider. */ export function gcd(x: number, y: number): number { y = y.valueOf(); // `Number` to `number` while (y !== 0) [x, y] = [y, x % y]; return x; } /** * Least Common Multiple. */ export function lcm(x: number, y: number): number { return (x * y) / gcd(x, y); } /* --------------------------------------------------------- COMMON ALGORITHMS --------------------------------------------------------- */ export function iota< ForwardIterator extends General>, >(first: ForwardIterator, last: ForwardIterator, value: number): void { for (; !first.equals(last); first = first.next()) first.value = value++; } export function accumulate< InputIterator extends General< IForwardIterator, InputIterator> >, >( first: InputIterator, last: InputIterator, init: IPointer.ValueType, op: Operator = plus, ): IPointer.ValueType { for (; !first.equals(last); first = first.next()) init = op(init, first.value); return init; } export function inner_product< InputIterator1 extends General< IForwardIterator, InputIterator1> >, InputIterator2 extends General< IForwardIterator, InputIterator2> >, >( first1: InputIterator1, last1: InputIterator1, first2: InputIterator2, value: IPointer.ValueType, adder: Operator = plus, multiplier: Operator = multiplies, ): IPointer.ValueType { for (; !first1.equals(last1); first1 = first1.next()) { value = adder(value, multiplier(first1.value, first2.value)); first2 = first2.next(); } return value; } export function adjacent_difference< InputIterator extends Readonly< IForwardIterator, InputIterator> >, OutputIterator extends Writeonly< IForwardIterator, OutputIterator> >, >( first: InputIterator, last: InputIterator, output: OutputIterator, subtracter: Operator = minus, ): OutputIterator { if (first.equals(last)) return output; // INITIALIZE let before: IPointer.ValueType; [first, output, before] = _Initialize( first, output, ); // COMPUTE OPERATIONS for (; !first.equals(last); first = first.next()) { output.value = subtracter(first.value, before); before = first.value; output = output.next(); } return output; } export function partial_sum< InputIterator extends Readonly< IForwardIterator, InputIterator> >, OutputIterator extends Writeonly< IForwardIterator, OutputIterator> >, >( first: InputIterator, last: InputIterator, output: OutputIterator, adder: Operator = plus, ): OutputIterator { if (first.equals(last)) return output; // INITIALIZE let sum: IPointer.ValueType; [first, output, sum] = _Initialize( first, output, ); // COMPUTE OPERATIONS for (; !first.equals(last); first = first.next()) { sum = adder(sum, first.value); output.value = sum; output = output.next(); } return output; } /* --------------------------------------------------------- PREFIX SUMS --------------------------------------------------------- */ export function inclusive_scan< InputIterator extends Readonly< IForwardIterator, InputIterator> >, OutputIterator extends Writeonly< IForwardIterator, OutputIterator> >, >( first: InputIterator, last: InputIterator, output: OutputIterator, adder: Operator = plus, init?: IPointer.ValueType, ): OutputIterator { return transform_inclusive_scan( first, last, output, adder, (val) => val, init, ); } export function exclusive_scan< InputIterator extends Readonly< IForwardIterator, InputIterator> >, OutputIterator extends Writeonly< IForwardIterator, OutputIterator> >, >( first: InputIterator, last: InputIterator, output: OutputIterator, init: IPointer.ValueType, op: Operator = plus, ): OutputIterator { return transform_exclusive_scan( first, last, output, init, op, (val) => val, ); } export function transform_inclusive_scan< InputIterator extends Readonly< IForwardIterator, InputIterator> >, OutputIterator extends Writeonly< IForwardIterator, OutputIterator> >, >( first: InputIterator, last: InputIterator, output: OutputIterator, binary: Operator, unary: Transformer, init?: IPointer.ValueType, ): OutputIterator { if (first.equals(last)) return output; // INITIALIZE let before: IPointer.ValueType; [first, output, before] = _Transform_initialize(first, output, unary, init); // COMPUTE OPERATIONS for (; !first.equals(last); first = first.next()) { before = binary(before, unary(first.value)); output.value = before; output = output.next(); } return output; } export function transform_exclusive_scan< InputIterator extends Readonly< IForwardIterator, InputIterator> >, OutputIterator extends Writeonly< IForwardIterator, OutputIterator> >, >( first: InputIterator, last: InputIterator, output: OutputIterator, init: IPointer.ValueType, binary: Operator, unary: Transformer, ): OutputIterator { if (first.equals(last)) return output; // INITIALIZE let x: IPointer.ValueType = unary(first.value); let y: IPointer.ValueType; [first, output, y] = _Transform_initialize(first, output, unary, init); // COMPUTE OPERATIONS for (; !first.equals(last); first = first.next()) { y = binary(x, y); x = unary(first.value); output.value = y; output = output.next(); } return output; } /* --------------------------------------------------------- BACK-GROUNDS --------------------------------------------------------- */ type Operator< Iterator1 extends Readonly< IForwardIterator, Iterator1> >, Iterator2 extends Readonly< IForwardIterator, Iterator2> >, > = ( x: IPointer.ValueType, y: IPointer.ValueType, ) => IPointer.ValueType; type Transformer< InputIterator extends Readonly< IForwardIterator, InputIterator> >, OutputIterator extends Writeonly< IForwardIterator, OutputIterator> >, > = ( val: IPointer.ValueType, ) => IPointer.ValueType; function _Initialize< InputIterator extends Readonly< IForwardIterator, InputIterator> >, OutputIterator extends Writeonly< IForwardIterator, OutputIterator> >, >( first: InputIterator, output: OutputIterator, init?: IPointer.ValueType, ): [InputIterator, OutputIterator, IPointer.ValueType] { return _Transform_initialize(first, output, (val) => val, init); } function _Transform_initialize< InputIterator extends Readonly< IForwardIterator, InputIterator> >, OutputIterator extends Writeonly< IForwardIterator, OutputIterator> >, >( first: InputIterator, output: OutputIterator, unary: Transformer, init?: IPointer.ValueType, ): [InputIterator, OutputIterator, IPointer.ValueType] { // WRITE THE FIRST OR INITIAL VALUE const ret: IPointer.ValueType = unary( init === undefined ? first.value : init, ); output.value = ret; // RETURNS WITH ADVANCES return [first.next(), output.next(), ret]; }