From d605cf61ed23e7fb16344e6adc8ed4adec5fde5d Mon Sep 17 00:00:00 2001 From: Patrick Roberts Date: Sun, 19 Dec 2021 22:30:47 -0600 Subject: [PATCH] Added modulo and truncation --- src/complex.test.ts | 7 +++++-- src/complex.ts | 6 +++++- src/index.ts | 2 +- src/methods/index.ts | 1 + src/methods/mod.test.ts | 36 ++++++++++++++++++++++++++++++++++++ src/methods/mod.ts | 9 +++++++++ src/methods/trunc.test.ts | 30 ++++++++++++++++++++++++++++++ src/methods/trunc.ts | 9 +++++++++ src/static/index.ts | 2 ++ src/static/mod.test.ts | 21 +++++++++++++++++++++ src/static/mod.ts | 6 ++++++ src/static/trunc.test.ts | 20 ++++++++++++++++++++ src/static/trunc.ts | 6 ++++++ 13 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 src/methods/mod.test.ts create mode 100644 src/methods/mod.ts create mode 100644 src/methods/trunc.test.ts create mode 100644 src/methods/trunc.ts create mode 100644 src/static/mod.test.ts create mode 100644 src/static/mod.ts create mode 100644 src/static/trunc.test.ts create mode 100644 src/static/trunc.ts diff --git a/src/complex.test.ts b/src/complex.test.ts index cb460fd..1b5fbc7 100644 --- a/src/complex.test.ts +++ b/src/complex.test.ts @@ -4,7 +4,7 @@ import mock from './__fixtures__/mock'; import Complex from './complex'; import { Component, principal } from './internal'; import { real, imag, abs, arg, norm } from './accessors'; -import { add, sub, mul, div, pow, toString } from './methods'; +import { add, sub, mul, div, mod, pow, toString } from './methods'; jest.mock('./internal/principal'); jest.mock('./accessors/real'); @@ -16,6 +16,7 @@ jest.mock('./methods/add'); jest.mock('./methods/sub'); jest.mock('./methods/mul'); jest.mock('./methods/div'); +jest.mock('./methods/mod'); jest.mock('./methods/pow'); jest.mock('./methods/toString'); @@ -30,6 +31,7 @@ beforeEach(() => { mock(sub).mockClear(); mock(mul).mockClear(); mock(div).mockClear(); + mock(mod).mockClear(); mock(pow).mockClear(); }); @@ -90,11 +92,12 @@ describe.each<['real' | 'imag' | 'abs' | 'arg' | 'norm', typeof real]>([ }); }); -describe.each<['add' | 'sub' | 'mul' | 'div' | 'pow', typeof add]>([ +describe.each<['add' | 'sub' | 'mul' | 'div' | 'mod' | 'pow', typeof add]>([ ['add', add], ['sub', sub], ['mul', mul], ['div', div], + ['mod', mod], ['pow', pow], ])('methods', (name, impl) => { describe(`Complex.prototype.${name}`, () => { diff --git a/src/complex.ts b/src/complex.ts index 8255470..560f33b 100644 --- a/src/complex.ts +++ b/src/complex.ts @@ -1,6 +1,6 @@ import { Component, principal } from './internal'; import { real, imag, abs, arg, norm } from './accessors'; -import { add, sub, mul, div, pow, toString } from './methods'; +import { add, sub, mul, div, mod, pow, toString } from './methods'; export default class Complex { /** @internal */ @@ -63,6 +63,10 @@ export default class Complex { return div(Complex, this, z); } + public mod(this: Complex, z: Complex): Complex { + return mod(Complex, this, z); + } + public pow(this: Complex, z: Complex): Complex { return pow(Complex, this, z); } diff --git a/src/index.ts b/src/index.ts index 87d2dea..00f79a2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,6 @@ export { default as Complex } from './complex'; export { E, I, LN10, LN2, LOG10E, LOG2E, PI, SQRT1_2, SQRT2 } from './constants'; export { acos, acosh, add, asin, asinh, atan, atanh, cartesian, cbrt, conj, cos, cosh, div, exp, from, log, - mul, polar, pow, proj, sin, sinh, sqrt, sub, tan, tanh, + mod, mul, polar, pow, proj, sin, sinh, sqrt, sub, tan, tanh, trunc, } from './static'; export { BinaryExpression, CallExpression, Expression, Identifier, Literal, UnaryExpression, parse } from './parser'; diff --git a/src/methods/index.ts b/src/methods/index.ts index 7dd07c7..0c62c64 100644 --- a/src/methods/index.ts +++ b/src/methods/index.ts @@ -2,5 +2,6 @@ export { default as add } from './add'; export { default as sub } from './sub'; export { default as mul } from './mul'; export { default as div } from './div'; +export { default as mod } from './mod'; export { default as pow } from './pow'; export { default as toString } from './toString'; diff --git a/src/methods/mod.test.ts b/src/methods/mod.test.ts new file mode 100644 index 0000000..50c5732 --- /dev/null +++ b/src/methods/mod.test.ts @@ -0,0 +1,36 @@ +import mock from '../__fixtures__/mock'; + +import Complex from '../complex'; +import div from './div'; +import mul from './mul'; +import sub from './sub'; +import trunc from './trunc'; +import sut from './mod'; + +jest.mock('./div'); +jest.mock('./sub'); +jest.mock('./mul'); +jest.mock('./trunc'); + +it('should delegate implementation to alternate form', () => { + const lhs = {} as Complex; + const rhs = {} as Complex; + const divLhsRhs = {} as Complex; + const truncDivLhsRhs = {} as Complex; + const mulTruncDivLhsRhsRhs = {} as Complex; + const subLhsMulTruncDivLhsRhsRhs = {} as Complex; + + mock(div).mockReturnValueOnce(divLhsRhs); + mock(trunc).mockReturnValueOnce(truncDivLhsRhs); + mock(mul).mockReturnValueOnce(mulTruncDivLhsRhsRhs); + mock(sub).mockReturnValueOnce(subLhsMulTruncDivLhsRhsRhs); + + const actual = sut(Complex, lhs, rhs); + + expect(div).toHaveBeenCalledWith(Complex, lhs, rhs); + expect(trunc).toHaveBeenCalledWith(Complex, divLhsRhs); + expect(mul).toHaveBeenCalledWith(Complex, truncDivLhsRhs, rhs); + expect(sub).toHaveBeenCalledWith(Complex, lhs, mulTruncDivLhsRhsRhs); + + expect(actual).toBe(subLhsMulTruncDivLhsRhsRhs); +}); diff --git a/src/methods/mod.ts b/src/methods/mod.ts new file mode 100644 index 0000000..fbe882e --- /dev/null +++ b/src/methods/mod.ts @@ -0,0 +1,9 @@ +import Complex from '../complex'; +import div from './div'; +import mul from './mul'; +import sub from './sub'; +import trunc from './trunc'; + +export default (Ctor: typeof Complex, lhs: Complex, rhs: Complex): Complex => ( + sub(Ctor, lhs, mul(Ctor, trunc(Ctor, div(Ctor, lhs, rhs)), rhs)) +); diff --git a/src/methods/trunc.test.ts b/src/methods/trunc.test.ts new file mode 100644 index 0000000..faa9989 --- /dev/null +++ b/src/methods/trunc.test.ts @@ -0,0 +1,30 @@ +import _ from '../__fixtures__/any/number'; +import mock from '../__fixtures__/mock'; + +import Complex from '../complex'; +import Component from '../internal/component'; +import { real, imag } from '../accessors'; +import sut from './trunc'; + +jest.mock('../complex'); +jest.mock('../accessors/real'); +jest.mock('../accessors/imag'); + +it('should initialize polar components from cartesian components', () => { + const testReal = 3.5; + const testImag = -4.5; + const z = new Complex(testReal, testImag, _, _, Component.CARTESIAN); + const expected = {} as Complex; + + mock(Complex).mockClear(); + mock(Complex).mockReturnValueOnce(expected); + + const actual = sut(Complex, z); + + expect(real).toHaveBeenCalledWith(Complex, z); + expect(imag).toHaveBeenCalledWith(Complex, z); + expect(Complex).toHaveBeenCalledWith( + Math.trunc(testReal), Math.trunc(testImag), _, _, Component.CARTESIAN, + ); + expect(actual).toBe(expected); +}); diff --git a/src/methods/trunc.ts b/src/methods/trunc.ts new file mode 100644 index 0000000..9821dec --- /dev/null +++ b/src/methods/trunc.ts @@ -0,0 +1,9 @@ +import Complex from '../complex'; +import Component from '../internal/component'; +import { real, imag } from '../accessors'; + +const trunc = (Ctor: typeof Complex, z: Complex): Complex => new Ctor( + Math.trunc(real(Ctor, z)), Math.trunc(imag(Ctor, z)), 0, 0, Component.CARTESIAN, +); + +export default trunc; diff --git a/src/static/index.ts b/src/static/index.ts index 7380f61..8ef6de9 100644 --- a/src/static/index.ts +++ b/src/static/index.ts @@ -14,6 +14,7 @@ export { default as div } from './div'; export { default as exp } from './exp'; export { default as from } from './from'; export { default as log } from './log'; +export { default as mod } from './mod'; export { default as mul } from './mul'; export { default as polar } from './polar'; export { default as pow } from './pow'; @@ -24,3 +25,4 @@ export { default as sqrt } from './sqrt'; export { default as sub } from './sub'; export { default as tan } from './tan'; export { default as tanh } from './tanh'; +export { default as trunc } from './trunc'; diff --git a/src/static/mod.test.ts b/src/static/mod.test.ts new file mode 100644 index 0000000..9b1d72d --- /dev/null +++ b/src/static/mod.test.ts @@ -0,0 +1,21 @@ +import mock from '../__fixtures__/mock'; + +import Complex from '../complex'; +import mod from '../methods/mod'; +import sut from './mod'; + +jest.mock('../complex'); +jest.mock('../methods/mod'); + +it('should delegate to mod method', () => { + const lhs = {} as Complex; + const rhs = {} as Complex; + const expected = {} as Complex; + + mock(mod).mockReturnValueOnce(expected); + + const actual = sut(lhs, rhs); + + expect(mod).toHaveBeenCalledWith(Complex, lhs, rhs); + expect(actual).toBe(expected); +}); diff --git a/src/static/mod.ts b/src/static/mod.ts new file mode 100644 index 0000000..d605cfb --- /dev/null +++ b/src/static/mod.ts @@ -0,0 +1,6 @@ +import Complex from '../complex'; +import _mod from '../methods/mod'; + +const mod = (lhs: Complex, rhs: Complex): Complex => _mod(Complex, lhs, rhs); + +export default mod; diff --git a/src/static/trunc.test.ts b/src/static/trunc.test.ts new file mode 100644 index 0000000..9d9a26d --- /dev/null +++ b/src/static/trunc.test.ts @@ -0,0 +1,20 @@ +import mock from '../__fixtures__/mock'; + +import Complex from '../complex'; +import trunc from '../methods/trunc'; +import sut from './trunc'; + +jest.mock('../complex'); +jest.mock('../methods/trunc'); + +it('should delegate to trunc method', () => { + const z = {} as Complex; + const expected = {} as Complex; + + mock(trunc).mockReturnValueOnce(expected); + + const actual = sut(z); + + expect(trunc).toHaveBeenCalledWith(Complex, z); + expect(actual).toBe(expected); +}); diff --git a/src/static/trunc.ts b/src/static/trunc.ts new file mode 100644 index 0000000..eb04af2 --- /dev/null +++ b/src/static/trunc.ts @@ -0,0 +1,6 @@ +import Complex from '../complex'; +import _trunc from '../methods/trunc'; + +const trunc = (z: Complex): Complex => _trunc(Complex, z); + +export default trunc;