From 97596b81a289c17232df5aaadcdaf5e34f37c31a Mon Sep 17 00:00:00 2001 From: Rafael Vuijk Date: Wed, 28 Oct 2026 21:54:18 +0000 Subject: [PATCH] A number's conjugate is made under the setting in force Complex.Conjugate was kept on the instance, made by Complex.Create under whatever downcasting setting its first caller had. A division by a complex number conjugates the divisor, so a division by i with the downcasting off left 0 - 1i, in decimals, as the conjugate of Complex.ImaginaryOne, the one instance every i is. conj(i) was that for every caller after it, in every thread. Two tests on #2190's branch failed in the full suite and passed alone: conj(i) against -i, and MathS.Conjugate's documented example. Which ran first decided it. The conjugate is now made each time it is asked for, under the setting in force, as every other number is: the division that asks for it reads the modulus the same way (#1615). A regression test divides by i with the downcasting off first; it fails without the change, with 0 - 1i. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura --- BREAKING-CHANGES.md | 10 ++++++++++ .../Entity.Continuous.Complex.Definition.cs | 9 +++++++-- Sources/Tests/UnitTests/Core/Numeric.cs | 15 +++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index e225fe99c..f14f321d2 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -319,6 +319,16 @@ Both are real, `im(3 + 4i)` being `4`, real-linear, and turned by the conjugate | `"im(3 + 4i)".ToEntity().Simplify()` | `(3 + 4i) * im` | `4` | | `"re * x".ToEntity()` | `re * x` | `re * x` | +### A number's conjugate is made under the setting in force + +**Silent: `Complex.Conjugate` is made under the downcasting setting of the caller, where the first caller's setting was +kept on the number for every caller after it.** A division by `i` with the downcasting off conjugates `i`, and left its +conjugate as `0 - 1i`, in decimals, on the one instance that every `i` is, in every thread from then on. + +| Input | Was (2.6.0) | Now | +|---|---|---| +| `Complex.ImaginaryOne.Conjugate`, after `(1 / Complex.ImaginaryOne).Evaled` with `DowncastingEnabled` off | `0 - 1i` | `-i` | + ### `conjugate`, `conj` and `arg` are functions **Not silent: these names followed by a bracket are now the complex conjugate and the principal argument, where they diff --git a/Sources/AngouriMath/Core/Entity/Continuous/Entity.Continuous.Complex.Definition.cs b/Sources/AngouriMath/Core/Entity/Continuous/Entity.Continuous.Complex.Definition.cs index 766d4027a..829f33a64 100644 --- a/Sources/AngouriMath/Core/Entity/Continuous/Entity.Continuous.Complex.Definition.cs +++ b/Sources/AngouriMath/Core/Entity/Continuous/Entity.Continuous.Complex.Definition.cs @@ -40,8 +40,13 @@ private protected Complex(Real? real, Real? imaginary) => /// /// Conjugate of a complex number. Given this = a + ib, Conjugate = a - ib /// - public Complex Conjugate => conjugate.GetValue(static @this => Create(@this.RealPart, -@this.ImaginaryPart), this); - private LazyPropertyA conjugate; + /// + /// Made under the downcasting setting in force, as any other number is, and so not kept + /// on the instance: the first to ask decided it for everyone. A division by i with + /// the downcasting off left 0 - 1i, in decimals, on , and + /// conj(i) was that from then on, in every thread. + /// + public Complex Conjugate => Create(RealPart, -ImaginaryPart); internal override Priority Priority => (RealPart, ImaginaryPart) switch diff --git a/Sources/Tests/UnitTests/Core/Numeric.cs b/Sources/Tests/UnitTests/Core/Numeric.cs index fd165c123..b8d87a6ba 100644 --- a/Sources/Tests/UnitTests/Core/Numeric.cs +++ b/Sources/Tests/UnitTests/Core/Numeric.cs @@ -458,5 +458,20 @@ public void AModulusIsMadeUnderTheDowncastingInForce() Assert.Equal(Integer.Create(325), Complex.Create(EDecimal.FromInt32(75), rootOf100000).Abs()); } } + + /// + /// A conjugate is made under the setting in force, as every other number is. It was kept on + /// the instance, so a division by i with the downcasting off left 0 - 1i, in + /// decimals, as the conjugate of , and conj(i) was + /// that for every caller after it: two tests failed or passed by the order the suite ran in. + /// + [Fact] + public void AConjugateIsMadeUnderTheSettingInForce() + { + using (MathS.Settings.DowncastingEnabled.Set(false)) + Assert.IsType((1 / Complex.ImaginaryOne).Evaled); + Assert.Equal(Complex.MinusImaginaryOne, Complex.ImaginaryOne.Conjugate); + Assert.Equal(Complex.MinusImaginaryOne, "conj(i)".ToEntity().InnerSimplified); + } } }