Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions BREAKING-CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -1041,13 +1041,15 @@ list its poles beside the other points it has no value at, which says nothing ne

**Silent: `max(x, x)` and `min(x, x)` simplify to `x provided x in RR`, where they were `x`.** The complex numbers are
not ordered, and both nodes are read over the reals, so `max(i, i)` has no value. Their condition said they were
defined everywhere, and `max(x, x)` simplified to `x`, which has a value at `i`. A comparison of two real arguments is
unchanged ([#2256](https://github.com/asc-community/AngouriMath/issues/2256)).
defined everywhere, and `max(x, x)` simplified to `x`, which has a value at `i`. Compiled by either compiler over
`Complex`, `max(x, x)` was `x` there too, and is `NaN`. A comparison of two real arguments is unchanged
([#2256](https://github.com/asc-community/AngouriMath/issues/2256)).

| Input | Was (2.6.0) | Now |
|---|---|---|
| `"max(x, x)".ToEntity().Simplify()` | `x` | `x provided x in RR` |
| `"max(x, 2)".ToEntity().DomainCondition` | `True` | `x in RR` |
| `"max(x, x)".ToEntity().Compile("x").Call(new Complex(0.5, 1.2))` | `<0.5; 1.2>` | `<NaN; NaN>` |

### Over the complex numbers, an equation in and out of a modulus is solved in the parts of `x`

Expand Down
12 changes: 7 additions & 5 deletions Sources/AngouriMath/Functions/Compilation/RealOnly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ public static NumericsComplex Mod(NumericsComplex a, NumericsComplex b)
}

/// <summary>
/// The larger of two numbers, or NaN where they differ and are not both real: the complex
/// numbers are not ordered, and the interpreter leaves <c>max(2, 1 + i)</c> unevaluated.
/// Two equal arguments are their own maximum, which the interpreter says as well.
/// The larger of two numbers, or NaN where they are not both real: the complex numbers are
/// not ordered, and the interpreter leaves <c>max(2, 1 + i)</c> unevaluated and gives
/// <c>max(i, i)</c> no value. Two equal complex arguments had themselves for a maximum
/// here after the interpreter stopped saying so, and compiled <c>max(x, x)</c> was
/// <c>x</c> off the real line. https://github.com/asc-community/AngouriMath/issues/2256
/// </summary>
public static NumericsComplex Max(NumericsComplex a, NumericsComplex b)
=> Ordered(a, b, larger: true);
Expand All @@ -59,9 +61,9 @@ public static NumericsComplex Min(NumericsComplex a, NumericsComplex b)
=> Ordered(a, b, larger: false);

private static NumericsComplex Ordered(NumericsComplex a, NumericsComplex b, bool larger)
=> a == b ? a
: a.Imaginary is not 0 || b.Imaginary is not 0 || double.IsNaN(a.Real) || double.IsNaN(b.Real)
=> a.Imaginary is not 0 || b.Imaginary is not 0 || double.IsNaN(a.Real) || double.IsNaN(b.Real)
? new NumericsComplex(double.NaN, double.NaN)
: a == b ? a
: new NumericsComplex(larger == a.Real >= b.Real ? a.Real : b.Real, 0);
}
}
23 changes: 23 additions & 0 deletions Sources/Tests/UnitTests/Convenience/MaxMinOffTheRealLineTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,28 @@ public void ASimplificationHasNoValueWhereTheOriginalHasNone(string expression)
Assert.True(simplified.Substitute("x", "i".ToEntity()).Evaled.IsNaN, $"{simplified} at i");
Assert.Equal(Entity.Number.Integer.Create(3), simplified.Substitute("x", 3).Evaled);
}

/// <summary>
/// Compiled, they have no value where evaluation has none. FastExpression and the LINQ
/// compiler over <c>Complex</c> answered <c>max(x, x)</c> at <c>1/2 + 6/5 i</c> with
/// <c>1/2 + 6/5 i</c>, and so <c>max(x, x) * 2</c> with <c>1 + 12/5 i</c>.
/// </summary>
[Theory]
[InlineData("max(x, x)")]
[InlineData("min(x, x)")]
[InlineData("max(x, x) * 2")]
public void CompiledItHasNoValueWhereEvaluationHasNone(string expression)
{
var entity = expression.ToEntity();
var fastExpression = entity.Compile("x");
var linq = entity.Compile<System.Numerics.Complex, System.Numerics.Complex>("x");
var offTheLine = new System.Numerics.Complex(0.5, 1.2);
Assert.True(double.IsNaN(fastExpression.Call(offTheLine).Real), $"FastExpression gives {fastExpression.Call(offTheLine)}");
Assert.True(double.IsNaN(linq(offTheLine).Real), $"LINQ gives {linq(offTheLine)}");
var onTheLine = new System.Numerics.Complex(0.5, 0);
var value = entity.Substitute("x", "1/2".ToEntity()).EvalNumerical().RealPart.EDecimal.ToDouble();
Assert.Equal(value, fastExpression.Call(onTheLine).Real);
Assert.Equal(value, linq(onTheLine).Real);
}
}
}
Loading