diff options
author | Angel Ezquerra <AngelEzquerra@users.noreply.github.com> | 2024-05-08 22:53:01 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-08 14:53:01 -0600 |
commit | d8e1504ed1fd2371f2ab7784c0f4b5f6376325a5 (patch) | |
tree | 852a054de2c93e73a8024bc9f03e5160e4680eb7 | |
parent | 09bd9d0b19a69a56b875eff6e6d119aaf67664fd (diff) | |
download | Nim-d8e1504ed1fd2371f2ab7784c0f4b5f6376325a5.tar.gz |
Add Complex version of almostEqual function (#23549)
This adds a version of `almostEqual` (which was already available for floats) thata works with `Complex[SomeFloat]`. Proof that this is needed is that the first thing that the complex.nim runnable examples block did before this commit was define (an incomplete) `almostEqual` function that worked with complex values.
-rw-r--r-- | lib/pure/complex.nim | 21 | ||||
-rw-r--r-- | tests/stdlib/tcomplex.nim | 3 |
2 files changed, 21 insertions, 3 deletions
diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim index 8234db410..b48811eae 100644 --- a/lib/pure/complex.nim +++ b/lib/pure/complex.nim @@ -15,9 +15,6 @@ runnableExamples: from std/math import almostEqual, sqrt - func almostEqual(a, b: Complex): bool = - almostEqual(a.re, b.re) and almostEqual(a.im, b.im) - let z1 = complex(1.0, 2.0) z2 = complex(3.0, -4.0) @@ -412,6 +409,24 @@ func rect*[T](r, phi: T): Complex[T] = ## * `polar func<#polar,Complex[T]>`_ for the inverse operation complex(r * cos(phi), r * sin(phi)) +func almostEqual*[T: SomeFloat](x, y: Complex[T]; unitsInLastPlace: Natural = 4): bool = + ## Checks if two complex values are almost equal, using the + ## [machine epsilon](https://en.wikipedia.org/wiki/Machine_epsilon). + ## + ## Two complex values are considered almost equal if their real and imaginary + ## components are almost equal. + ## + ## `unitsInLastPlace` is the max number of + ## [units in the last place](https://en.wikipedia.org/wiki/Unit_in_the_last_place) + ## difference tolerated when comparing two numbers. The larger the value, the + ## more error is allowed. A `0` value means that two numbers must be exactly the + ## same to be considered equal. + ## + ## The machine epsilon has to be scaled to the magnitude of the values used + ## and multiplied by the desired precision in ULPs unless the difference is + ## subnormal. + almostEqual(x.re, y.re, unitsInLastPlace = unitsInLastPlace) and + almostEqual(x.im, y.im, unitsInLastPlace = unitsInLastPlace) func `$`*(z: Complex): string = ## Returns `z`'s string representation as `"(re, im)"`. diff --git a/tests/stdlib/tcomplex.nim b/tests/stdlib/tcomplex.nim index 812bcdc77..ca83314b9 100644 --- a/tests/stdlib/tcomplex.nim +++ b/tests/stdlib/tcomplex.nim @@ -84,6 +84,9 @@ let t = polar(a) doAssert(rect(t.r, t.phi) =~ a) doAssert(rect(1.0, 2.0) =~ complex(-0.4161468365471424, 0.9092974268256817)) +doAssert(almostEqual(a, a + complex(1e-16, 1e-16))) +doAssert(almostEqual(a, a + complex(2e-15, 2e-15), unitsInLastPlace = 5)) + let i64: Complex32 = complex(0.0f, 1.0f) |