Repository navigation
Complex and Fuzzy number improvements and bug fixes
Number Library — Release Notes since 1.8.1
Version 1.9.3
Work Item 8 — Complex Logarithm
- Implemented
log(z)for complexzvia the identitylog(r·e^(iθ)) = log(r) + iθ IsEulerextractor introduced for structural matching of Euler-form expressions- Complex log rules placed in
UniFunction.identitiesMatcherto avoid infinite
expansion loops - Special angle identities:
exp(iπ) = -1,exp(iπ/2) = i, etc. - Euler special-value cases with
.normalizeonLiteral(Angle)to handle all
canonical angle representations
Work Item 9 — Complex Trig/Hyperbolic Structural Rules
- Structural simplification rules for complex trig and hyperbolic functions:
cos(ix) = cosh(x),sin(ix) = i·sinh(x),cosh(ix) = cos(x),
sinh(ix) = i·sin(x) IsImaginaryExpressionextractor for matching expressions of the formn·ioperandsMatcherguards prevent eager evaluation of trig arguments containing
Ibefore structural rules fire- Special angle identities for concrete values:
sin(π/6) = 1/2, etc.
Work Item 10 — Complex Approximation
approximationComplexpath added tomaterializefor approximate evaluation
of complex expressionsapplyCompleximplemented onExpressionMonoFunctionapproximationComplexonApproximateand subtypes:ValueExpression,
UniFunction,BiFunction,Expressionmaterializefalls back via.orElse(approximationComplex)when symbolic
simplification cannot fully reduce an expressionIsImaginaryExpressionextractor generalised;n*irule added as bonus- Known limitation:
fuzzy.toDoublereturns modulus for complex values
Work Item 11 — Pythagorean Identities
sin²(z) + cos²(z) = 1andcosh²(z) - sinh²(z) = 1for symbolic complexzleaveOperandsAsIsmechanism onCompositeExpressionprevents eager expansion
of hyperbolic functions before identity matchers fireIsHyperbolicextractor introduced;leaveOperandsAsIsextended to protect
all hyperbolicBiFunctionpairsshouldStaySymbolicexempts trig/hyperbolic functions with complex arguments,
allowingsimplifyExpandto fire correctlycontainsImethod added toExpression- Deferred:
cos²(x) - sin²(x) = cos(2x)symbolic identity (Issue #194) - Deferred: Pythagorean identity for fully evaluable concrete numeric
x
(architecturally blocked — requires symbolic variable support)
Work Item 12 — Canonical Ordering of BiFunction Operands
given Ordering[Expression]inExpressioncompanion object: primary key
AtomExpression < CompositeExpression; within atoms by type rank; within
composites by depthIsCommutativeextractor added forSumandProductBiFunctionsstructuralMatcherrule swaps non-canonical commutative operands:
BiFunction(composite, atom, f) → BiFunction(atom, composite, f)BiFunctionTableSpecadded with comprehensive table-driven tests for all
BiFunctionmatcher rules
Bug fixes uncovered by WI12
BiFunction.equals: use===(CatsEq) inoperandsMatchinstead of==matchBiFunctionIdentitiesPower: added missing1^x → 1andx^0 → 1casesisSame(ComplexPolar/Cartesian): convert polar to Cartesian for
subtraction rather than Cartesian to polarBiFunction.leaveOperandsAsIs: extended to protect all hyperbolicBiFunction
pairs, not justIsCoshSquared/IsSinhSquaredMatchers.scalacode review:eitherOrtriple-evaluation bug fixed;retype[S]
method added for phantom-typeMisscasts;simplifyLazyrenamed to
simplifyExpand
Known issues deferred from WI12
- Issue #196:
Box/Gaussianfuzz combination too strict in subtraction;
workaround applied in affected tests usingNumber("x.xxxx(20)")notation - Issue #197:
Complex + Realasymmetric addition;IsImaginaryExpressionCommutative
rule commented out pending fix
Version 1.9.1
Scala 3 Migration of core module
coremodule migrated from Scala 2 to Scala 3given/usingreplacesimplicit val/implicit defthroughout- New Scala 3 control structure syntax adopted
- Cross-module consistency achieved: all modules now on Scala 3
Version 1.9.2 (unreleased)
Work Item 13 — Trapezoid Fuzz Shape
Trapezoid(a, b)case class added toShapehierarchy, representing the
convolution of twoBoxdistributions with half-widthsa ≤ bwiggleformula: flat-top region returnsb - a; ramp region returns
(a + b) - 2√(ab·confidence); thresholda/bguards flat-top branchprobabilityformula: flat-top regionx/b; ramp region uses quadratic formulasigma = √((a² + b²) / 3)for CLT conversion atn ≥ 3Box convolutionsAbsoluteFuzz.*updated:Box ⊗ Box → Trapezoid(a, b)(orBoxif one is
negligible vianegligibleRatio)RelativeFuzz.*similarly updated for Box⊗Box → TrapezoidnegligibleRatio = 1E6introduced to suppress spurious Trapezoid creation
Work Item 14 — Suppress Machine-Epsilon Fuzz
maybeAddFuzzinGeneralNumbersuppresses machine-epsilon fuzz when real
fuzz is already presentnegligibleRatio = 1E6constant prevents spurious Trapezoid creation from
double-precision noise
Version 1.9.3 (unreleased — in progress)
Work Item 15 — Fix Fuzz Combination Machinery
The full Box⊗Box subtraction pipeline now correctly produces Trapezoid fuzz
end-to-end. A chain of interconnected issues was identified and fixed:
Root cause fixes
maybeAddFuzzrestored to only add fuzz whenfuzz.isEmpty; intelligence
for suppression moved entirely intoFuzziness.*via the new three-tier rules.
Previously,specializewould unconditionally convolve fresh Box fuzz onto
numbers already carrying Trapezoid fuzz, burying the Trapezoid under Gaussian.combinewas gatingBox⊗Boxconvolution onrelative == true, causing
AbsoluteFuzz Box⊗Boxto fall through tonormalizeShape→ Gaussian.
Guard simplified tof1.shape == Box && f2.shape == Boxregardless of style.AbsoluteFuzz.*was missing cross-shape cases (Box⊗Trapezoid,
Trapezoid⊗Gaussian,Trapezoid⊗Trapezoid). All now handled uniformly via
sigma conversion.RelativeFuzz.*made fully consistent withAbsoluteFuzz.*for all
cross-shape combinations.monadicFuzzinessnow short-circuits for exact linear operations (negation,
scale by Rational) viaop.fuzz: Option[Int], preserving absolute/relative
style and Box shape through negation. Previously,MonadicOperationNegate
withfuzz: Int = 0always introduced double-precision fuzz.
New three-tier combination rules (Fuzziness.applyRules)
Rule 2 (applied first): if larger/smaller > negligibleRatio (9),
keep larger unchanged — prevents spurious shape promotion.
Rule 1 (applied second): if either magnitude < doublePrecisionFloor (≈ 4.4E-16),
scale larger by sqrt(2), keep shape — double-precision noise stays noise.
Rule 3: full convolution — Box⊗Box → Trapezoid, all else → Gaussian.
negligibleRatioreduced from1E6to9doublePrecisionFloor = DoublePrecisionTolerance * 2introduced- NaN/zero guard added to
applyRulesto preventTrapezoid(NaN, NaN) sanitizehelper added toFuzzinesscompanion: stripsNaN/infinite
magnitudes at the boundary of fuzz arithmetic inmonadicFuzzinessand
applyCoefficients
Other fixes
Shape.effectiveMagnitude(l)added toShapetrait;Trapezoidreturns
sigma,BoxandGaussianreturnl. Used byAbsoluteFuzz.getQualifiedString
to fix runaway rendering of Trapezoid-fuzz numbers (was producing
"3.000...000[]"instead of"3.00(41)").getPowerCoefficients:math.log(math.abs(z))fixes ancient NaN bug
for negative base values.- Default confidence changed from
0.5tooneSigma = 0.317, corresponding
to the standard "1 sigma" statistical threshold (P ≈ 68.3%). Gives
isProbablyZeroa natural, distribution-agnostic interpretation.
Shape promotion table
| this \ convolute | Box | Trapezoid | Gaussian |
|---|---|---|---|
| Box | Trapezoid | Gaussian | Gaussian |
| Trapezoid | Gaussian | Gaussian | Gaussian |
| Gaussian | Gaussian | Gaussian | Gaussian |
(Subject to Rules 1 and 2 suppressing promotion when magnitudes differ greatly.)
Result: 3,825 passing, 4 ignored (net +3 vs prior commit).
Known Deferred Issues (as of WI15)
- Issue #196:
Box/Gaussianfuzz combination too strict in subtraction - Issue #197:
Complex + Realasymmetric addition - Issue #193: Symbolic Pythagorean identities for concrete numeric arguments
(requires symbolic variable support) - Issue #194:
cos²(x) - sin²(x) = cos(2x)identity FuzzyNumberwithNonefuzz should beExactNumbertan/tanhas first-class functions (currentlySin/Cosdivision)