import { joinTypes, typeOfDependency, Dependency, ImpType, ImpReturns } from '../core/Dispatcher.js' export type Complex = {re: T; im: T;} export type UnderlyingReal = T extends Complex ? UnderlyingReal : T export const Complex_type = { test: (dep: {testT: (z: unknown) => z is T}) => (z: unknown): z is Complex => typeof z === 'object' && 're' in z && 'im' in z && dep.testT(z.re) && dep.testT(z.im), infer: (dep: typeOfDependency) => (z: Complex) => joinTypes(dep.typeOf(z.re), dep.typeOf(z.im)), from: { T: (dep: Dependency<'zero', [T]>) => (t: T) => ({re: t, im: dep.zero(t)}), Complex: (dep: {convert: (from: U) => T}) => (z: Complex) => ({re: dep.convert(z.re), im: dep.convert(z.im)}) } } export interface ComplexImpTypes { complex: (a: T, b?: T) => Complex zero: T extends Complex ? (a: Complex) => Complex> : never one: T extends Complex ? (a: Complex) => Complex> : never nan: T extends Complex ? (a: Complex) => Complex> : never re: T extends Complex ? (a: Complex) => UnderlyingReal : never } export const complex_unary = (dep: Dependency<'zero', [T]>): ImpType<'complex', [T]> => t => ({re: t, im: dep.zero(t)}) export const complex_binary = (t: T, u: T): ImpReturns<'complex', [T,T]> => ({re: t, im: u}) export const zero = (dep: Dependency<'zero', [T]>): ImpType<'zero', [Complex]> => z => complex_binary(dep.zero(z.re), dep.zero(z.im)) export const one = (dep: Dependency<'zero' | 'one', [T]>): ImpType<'one', [Complex]> => z => // Must provide parameter T, else TS narrows to return type of dep.one complex_binary(dep.one(z.re), dep.zero(z.im)) export const nan = (dep: Dependency<'nan', [T]>): ImpType<'nan', [Complex]> => z => complex_binary(dep.nan(z.re), dep.nan(z.im)) export const re = (dep: Dependency<'re', [T]>): ImpType<'re', [Complex]> => z => dep.re(z.re)