import {Complex} from './Complex.js' import {Returns} from "#core/Type.js" import {Any, match} from "#core/TypePatterns.js" import {BooleanT} from '#boolean/BooleanT.js' import {NumberT} from '#number/NumberT.js' export const complex = [ match(Any, (math, T) => { const z = math.zero(T) if (math.hasnan(T)) { const isnan = math.isnan.resolve([T]) const compnan = math.nan(Complex(T)) return Returns(Complex(T), r => { if (isnan(r)) return compnan return {re: r, im: z} }) } return Returns(Complex(T), r => ({re: r, im: z})) }), match([Any, Any], (math, [T, U]) => { if (T !== U) { throw new RangeError( 'mixed complex types disallowed ' + `(real ${T}, imaginary ${U})`) } return Returns(Complex(T), (r, m) => ({re: r, im: m})) }) ] export const arg = match( Complex(NumberT), Returns(NumberT, z => Math.atan2(z.im, z.re))) /* Returns true if w is z multiplied by a complex unit */ export const associate = match([Complex, Complex], (math, [W, Z]) => { if (Z.Component.complex) { throw new Error( `The group of units of type ${Z} is not yet implemented`) } const eq = math.equal.resolve([W, Z]) const neg = math.negate.resolve(Z) const eqN = math.equal.resolve([W, neg.returns]) const mult = math.multiply.resolve([Z, Z]) const eqM = math.equal.resolve([W, mult.returns]) const negM = math.negate.resolve(mult.returns) const eqNM = math.equal.resolve([W, negM.returns]) const iZ = math.complex(math.zero(Z.Component), math.one(Z.Component)) return Returns(BooleanT, (w, z) => { if (eq(w, z) || eqN(w, neg(z))) return true const iz = mult(iZ, z) return eqM(w, iz) || eqNM(w, negM(iz)) }) }) export const cis = match(NumberT, Returns(Complex(NumberT), t => ({ re: Math.cos(t), im: Math.sin(t)})))