MCPcopy Create free account
hub / github.com/cortex-js/compute-engine / applyN

Function applyN

src/compute-engine/boxed-expression/apply.ts:133–187  ·  view source on GitHub ↗
(
  ops: ReadonlyArray<Expression>,
  fn: (...xs: number[]) => number | Complex,
  bigFn?: (...xs: BigDecimal[]) => BigDecimal | Complex | number,
  complexFn?: (...xs: Complex[]) => Complex
)

Source from the content-addressed store, hash-verified

131 if (complexFn && Number.isFinite(re) && isNaNKernelResult(result))
132 result = complexFn(ce.complex(re, 0));
133 }
134
135 if (result === undefined) return undefined;
136 if (result instanceof Complex)
137 return ce.number(ce._numericValue({ re: result.re, im: result.im }));
138 if (typeof result === 'number') return boxMachineNumber(ce, result);
139 return ce.number(result);
140}
141
142/**
143 * N-ary kernel dispatcher for special functions.
144 *
145 * Routing:
146 * - any complex operand → `complexFn`
147 * - bignum preferred and `bigFn` available → `bigFn`
148 * - otherwise → machine `fn`; if `fn` returns NaN on finite inputs and a
149 * `complexFn` is available, retry it (the value may be complex for real
150 * inputs, e.g. EllipticK(m) for m > 1).
151 *
152 * A NaN result on finite inputs yields `undefined` (the expression stays
153 * symbolic) rather than a NaN literal: the kernels use NaN to signal
154 * "outside the implemented domain", not a mathematical result.
155 */
156export function applyN(
157 ops: ReadonlyArray<Expression>,
158 fn: (...xs: number[]) => number | Complex,
159 bigFn?: (...xs: BigDecimal[]) => BigDecimal | Complex | number,
160 complexFn?: (...xs: Complex[]) => Complex
161): Expression | undefined {
162 if (!ops.every((op) => isNumber(op))) return undefined;
163 const ce = ops[0].engine;
164
165 if (ops.some((op) => Number.isNaN(op.re) || Number.isNaN(op.im)))
166 return ce.NaN;
167
168 let result: number | Complex | BigDecimal | undefined = undefined;
169
170 const isNaNResult = (r: typeof result): boolean =>
171 r === undefined ||
172 (typeof r === 'number'
173 ? Number.isNaN(r)
174 : r instanceof Complex
175 ? r.isNaN()
176 : r.isNaN());
177
178 if (ops.some((op) => op.im !== 0)) {
179 result = complexFn?.(...ops.map((op) => ce.complex(op.re, op.im)));
180 } else {
181 // Cascade: bignum (if preferred) → machine → complex. A NaN from a
182 // kernel means "outside this kernel's implemented domain", so a
183 // lower-precision or complex-valued answer is better than none.
184 if (bignumPreferred(ce) && bigFn)
185 result = bigFn(...ops.map((op) => op.bignumRe ?? ce.bignum(op.re)));
186 if (isNaNResult(result)) result = fn(...ops.map((op) => op.re));
187 if (
188 isNaNResult(result) &&
189 complexFn &&
190 ops.every((op) => Number.isFinite(op.re))

Callers 3

distributions.tsFile · 0.90
arithmetic.tsFile · 0.90

Calls 13

isNumberFunction · 0.90
bignumPreferredFunction · 0.90
isNaNResultFunction · 0.85
fnFunction · 0.85
boxMachineNumberFunction · 0.85
complexMethod · 0.80
mapMethod · 0.65
numberMethod · 0.65
_numericValueMethod · 0.65
chopMethod · 0.65
isNaNMethod · 0.45
bignumMethod · 0.45

Tested by

no test coverage detected