import {configDependency} from '../core/Config.js' import { Signature, ConservativeBinary, ConservativeUnary, Dependency, ImpType } from '../core/Dispatcher.js' import type {Complex, UnderlyingReal} from '../Complex/type.js' declare module "./type" { interface NumbersReturn { // This description loses information: some subtypes like NumInt or // Positive are closed under addition, but this says that the result // of add is just a number, not still of the reduced type // add: Signature // Whereas this one preserves information, but lies // because it claims all subtypes of number are closed under addition, // which is not true for `1 | 2 | 3`, for example. But because in // generics that use add we often need to assign the result of add // to something of the exact generic type, generics using add won't // compile unless we lie in this way and assert that add returns // the subtype. add: ConservativeBinary // Not sure how this will need to go when we introduce NumInt. addReal: Params extends [infer R, infer S] ? R extends number ? S extends R ? R : never : never : never unaryMinus: ConservativeUnary conj: ConservativeUnary subtract: ConservativeBinary multiply: ConservativeBinary absquare: Params extends [infer R] ? R extends number ? UnderlyingReal : never : never reciprocal: ConservativeUnary divide: ConservativeBinary divideByReal: Params extends [infer R, infer S] ? R extends number ? S extends R ? R : never : never : never // best square root that remains the same type conservativeSqrt: ConservativeUnary // Best we can do for sqrt at compile time, since actual return // type depends on config. Not sure how this will play out // when we make a number-only bundle, but at least the import type // above for Complex<> does not lead to any emitted JavaScript. sqrt: Signature> } } export const add: ImpType<'add', [number, number]> = (a, b) => a + b export const addReal = add export const unaryMinus: ImpType<'unaryMinus', [number]> = a => -a export const conj: ImpType<'conj', [number]> = a => a export const subtract: ImpType<'subtract', [number, number]> = (a, b) => a - b export const multiply: ImpType<'multiply', [number, number]> = (a, b) => a * b export const absquare: ImpType<'absquare', [number]> = a => a*a export const reciprocal: ImpType<'reciprocal', [number]> = a => 1/a export const divide: ImpType<'divide', [number, number]> = (a, b) => a / b export const divideByReal: ImpType<'divideByReal', [number, number]> = divide export const conservativeSqrt: ImpType<'conservativeSqrt', [number]> = a => isNaN(a) ? NaN : Math.sqrt(a) export const sqrt = (dep: configDependency & Dependency<'complex', [number, number]>): ImpType<'sqrt', [number]> => { if (dep.config.predictable || !dep.complex) return conservativeSqrt return a => { if (isNaN(a)) return NaN if (a >= 0) return Math.sqrt(a) return dep.complex(0, Math.sqrt(unaryMinus(a))) } }