add approxequal (#15766)

* add approxequal

* Address review comments, tests that pass

* more wikipedia links [ci skip]

* forgot since

Co-authored-by: b3liever <b3liever@yandex.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
Antonis Geralis
2020-10-30 10:56:28 +02:00
committed by GitHub
parent b5df823191
commit c274d9aed6
2 changed files with 26 additions and 1 deletions

View File

@@ -7,6 +7,7 @@
- `prelude` now works with the JavaScript target.
- Added `ioutils` module containing `duplicate` and `duplicateTo` to duplicate `FileHandle` using C function `dup` and `dup2`.
- Added `almostEqual` in `math` for comparing two float values using a machine epsilon.
- The JSON module can now handle integer literals and floating point literals of arbitrary length and precision.
Numbers that do not fit the underlying `BiggestInt` or `BiggestFloat` fields are kept as string literals and
@@ -16,6 +17,7 @@
- Added `randState` template that exposes the default random number generator. Useful for library authors.
## Language changes

View File

@@ -56,7 +56,7 @@ import std/private/since
{.push debugger: off.} # the user does not want to trace a part
# of the standard library!
import bitops
import bitops, fenv
proc binom*(n, k: int): int {.noSideEffect.} =
## Computes the `binomial coefficient <https://en.wikipedia.org/wiki/Binomial_coefficient>`_.
@@ -158,6 +158,29 @@ proc classify*(x: float): FloatClass =
return fcSubnormal
return fcNormal
proc almostEqual*[T: SomeFloat](x, y: T; unitsInLastPlace: Natural = 4): bool {.
since: (1, 5), inline, noSideEffect.} =
## Checks if two float values are almost equal, using
## `machine epsilon <https://en.wikipedia.org/wiki/Machine_epsilon>`_.
##
## `unitsInLastPlace` is the max number of
## `units in 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.
##
# taken from: https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon
runnableExamples:
doAssert almostEqual(3.141592653589793, 3.1415926535897936)
doAssert almostEqual(1.6777215e7'f32, 1.6777216e7'f32)
let diff = abs(x - y)
result = diff <= epsilon(T) * abs(x + y) * T(unitsInLastPlace) or
diff < minimumPositiveValue(T)
proc isPowerOfTwo*(x: int): bool {.noSideEffect.} =
## Returns ``true``, if ``x`` is a power of two, ``false`` otherwise.
##