Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Downloads
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Forums
  - IRC
  - Community Discord
  - Wiki
  - GitHub
  - Issues
  - Get involved
  - Contributors
  - Foundation
  - Security Team
  - Donate
  - Sponsors
- Resources
  - Tour
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - run.dlang.io
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

# std.math.operations

This is a submodule of std.math.
It contains several functions for work with floating point numbers.
License:
Boost License 1.0.
Authors:
Walter Bright, Don Clugston, Conversion of CEPHES math library to D by Iain Buclaw and David Nadlinger

Source std/math/operations.d

pure nothrow @nogc @trusted real `NaN`(ulong `payload`);
  Create a quiet NAN, storing an integer inside the payload.
  For floats, the largest possible payload is 0x3F_FFFF. For doubles, it is 0x3_FFFF_FFFF_FFFF. For 80-bit or 128-bit reals, it is 0x3FFF_FFFF_FFFF_FFFF.
  Examples:

      import std.math.traits : isNaN;

      real a = NaN(1_000_000);
      assert(isNaN(a));
      writeln(getNaNPayload(a)); // 1_000_000

pure nothrow @nogc @trusted ulong `getNaNPayload`(real `x`);
  Extract an integral payload from a NAN.
  Returns:
  the integer payload as a ulong.
  For floats, the largest possible payload is 0x3F_FFFF. For doubles, it is 0x3_FFFF_FFFF_FFFF. For 80-bit or 128-bit reals, it is 0x3FFF_FFFF_FFFF_FFFF.
  Examples:

      import std.math.traits : isNaN;

      real a = NaN(1_000_000);
      assert(isNaN(a));
      writeln(getNaNPayload(a)); // 1_000_000

pure nothrow @nogc @trusted real `nextUp`(real `x`);
pure nothrow @nogc @trusted double `nextUp`(double `x`);
pure nothrow @nogc @trusted float `nextUp`(float `x`);
  Calculate the next largest floating point value after x.
  Return the least number greater than x that is representable as a real; thus, it gives the next point on the IEEE number line.

  Special Values
  x | nextUp(x)
  --- | ---
  -∞ | -real.max
  ±0.0 | real.min_normal*real.epsilon
  real.max | ∞
  ∞ | ∞
  NAN | NAN

  Examples:

      assert(nextUp(1.0 - 1.0e-6).feqrel(0.999999) > 16);
      assert(nextUp(1.0 - real.epsilon).feqrel(1.0) > 16);

pure nothrow @nogc @safe real `nextDown`(real `x`);
pure nothrow @nogc @safe double `nextDown`(double `x`);
pure nothrow @nogc @safe float `nextDown`(float `x`);
  Calculate the next smallest floating point value before x.
  Return the greatest number less than x that is representable as a real; thus, it gives the previous point on the IEEE number line.

  Special Values
  x | nextDown(x)
  --- | ---
  ∞ | real.max
  ±0.0 | -real.min_normal*real.epsilon
  -real.max | -∞
  -∞ | -∞
  NAN | NAN

  Examples:

      writeln(nextDown(1.0 + real.epsilon)); // 1.0

pure nothrow @nogc @safe T `nextafter`(T)(const T `x`, const T `y`);
  Calculates the next representable value after x in the direction of y.
  If y > x, the result will be the next largest floating-point value; if y < x, the result will be the next smallest value. If x == y, the result is y. If x or y is a NaN, the result is a NaN.

  Remarks This function is not generally very useful; it's almost always better to use the faster functions nextUp() or nextDown() instead.

  The FE_INEXACT and FE_OVERFLOW exceptions will be raised if x is finite and the function result is infinite. The FE_INEXACT and FE_UNDERFLOW exceptions will be raised if the function value is subnormal, and x is not equal to y.
  Examples:

      import std.math.traits : isNaN;

      float a = 1;
      assert(is(typeof(nextafter(a, a)) == float));
      assert(nextafter(a, a.infinity) > a);
      assert(isNaN(nextafter(a, a.nan)));
      assert(isNaN(nextafter(a.nan, a)));

      double b = 2;
      assert(is(typeof(nextafter(b, b)) == double));
      assert(nextafter(b, b.infinity) > b);
      assert(isNaN(nextafter(b, b.nan)));
      assert(isNaN(nextafter(b.nan, b)));

      real c = 3;
      assert(is(typeof(nextafter(c, c)) == real));
      assert(nextafter(c, c.infinity) > c);
      assert(isNaN(nextafter(c, c.nan)));
      assert(isNaN(nextafter(c.nan, c)));

pure nothrow @nogc @safe real `fdim`(real `x`, real `y`);
  Returns the positive difference between x and y.
  Equivalent to fmax(`x`-`y`, 0).
  Returns:

  Special Values
  x, y | fdim(x, y)
  --- | ---
  x > y | x - y
  x <= y | +0.0

  Examples:

      import std.math.traits : isNaN;

      writeln(fdim(2.0, 0.0)); // 2.0
      writeln(fdim(-2.0, 0.0)); // 0.0
      writeln(fdim(real.infinity, 2.0)); // real.infinity
      assert(isNaN(fdim(real.nan, 2.0)));
      assert(isNaN(fdim(2.0, real.nan)));
      assert(isNaN(fdim(real.nan, real.nan)));

pure nothrow @nogc @safe F `fmax`(F)(const F `x`, const F `y`)
if (__traits(isFloating, F));
  Returns the larger of `x` and `y`.
  If one of the arguments is a NaN, the other is returned.
  See Also:
  std.algorithm.comparison.max is faster because it does not perform the isNaN test.
  Examples:

      import std.meta : AliasSeq;
      static foreach (F; AliasSeq!(float, double, real))
      {
          writeln(fmax(F(0.0), F(2.0))); // 2.0
          writeln(fmax(F(-2.0), 0.0)); // F(0.0)
          writeln(fmax(F.infinity, F(2.0))); // F.infinity
          writeln(fmax(F.nan, F(2.0))); // F(2.0)
          writeln(fmax(F(2.0), F.nan)); // F(2.0)
      }

pure nothrow @nogc @safe F `fmin`(F)(const F `x`, const F `y`)
if (__traits(isFloating, F));
  Returns the smaller of `x` and `y`.
  If one of the arguments is a NaN, the other is returned.
  See Also:
  std.algorithm.comparison.min is faster because it does not perform the isNaN test.
  Examples:

      import std.meta : AliasSeq;
      static foreach (F; AliasSeq!(float, double, real))
      {
          writeln(fmin(F(0.0), F(2.0))); // 0.0
          writeln(fmin(F(-2.0), F(0.0))); // -2.0
          writeln(fmin(F.infinity, F(2.0))); // 2.0
          writeln(fmin(F.nan, F(2.0))); // 2.0
          writeln(fmin(F(2.0), F.nan)); // 2.0
      }

pure nothrow @nogc @safe real `fma`(real `x`, real `y`, real `z`);
  Returns (x * y) + z, rounding only once according to the current rounding mode.
  Bugs:
  Not currently implemented - rounds twice.
  Examples:

      writeln(fma(0.0, 2.0, 2.0)); // 2.0
      writeln(fma(2.0, 2.0, 2.0)); // 6.0
      writeln(fma(real.infinity, 2.0, 2.0)); // real.infinity
      assert(fma(real.nan, 2.0, 2.0) is real.nan);
      assert(fma(2.0, 2.0, real.nan) is real.nan);

pure nothrow @nogc @trusted int `feqrel`(X)(const X `x`, const X `y`)
if (isFloatingPoint!X);
  To what precision is x equal to y?
  Returns:
  the number of mantissa bits which are equal in x and y. eg, 0x1.F8p+60 and 0x1.F1p+60 are equal to 5 bits of precision.

  Special Values
  x | y | feqrel(x, y)
  --- | --- | ---
  x | x | real.mant_dig
  x | >= 2*x | 0
  x | <= x/2 | 0
  NAN | any | 0
  any | NAN | 0

  Examples:

      writeln(feqrel(2.0, 2.0)); // 53
      writeln(feqrel(2.0f, 2.0f)); // 24
      writeln(feqrel(2.0, double.nan)); // 0

      // Test that numbers are within n digits of each
      // other by testing if feqrel > n * log2(10)

      // five digits
      assert(feqrel(2.0, 2.00001) > 16);
      // ten digits
      assert(feqrel(2.0, 2.00000000001) > 33);

bool `approxEqual`(T, U, V)(T `value`, U `reference`, V `maxRelDiff` = 0.01, V `maxAbsDiff` = 1e-05);
  Computes whether a values is approximately equal to a reference value, admitting a maximum relative difference, and a maximum absolute difference.

  Warning This template is considered out-dated. It will be removed from Phobos in 2.106.0. Please use isClose instead. To achieve a similar behaviour to `approxEqual`(a, b) use isClose(a, b, 1e-2, 1e-5). In case of comparing to 0.0, isClose(a, b, 0.0, eps) should be used, where eps represents the accepted deviation from 0.0."

  Parameters:

  T `value` | Value to compare.
  U `reference` | Reference value.
  V `maxRelDiff` | Maximum allowable difference relative to `reference`. Setting to 0.0 disables this check. Defaults to 1e-2.
  V `maxAbsDiff` | Maximum absolute difference. This is mainly usefull for comparing values to zero. Setting to 0.0 disables this check. Defaults to 1e-5.

  Returns:
  true if `value` is approximately equal to `reference` under either criterium. It is sufficient, when `value` satisfies one of the two criteria.
  If one item is a range, and the other is a single value, then the result is the logical and-ing of calling `approxEqual` on each element of the ranged item against the single item. If both items are ranges, then `approxEqual` returns true if and only if the ranges have the same number of elements and if `approxEqual` evaluates to true for each pair of elements.
  See Also:
  Use feqrel to get the number of equal bits in the mantissa.
bool `isClose`(T, U, V = CommonType!(FloatingPointBaseType!T, FloatingPointBaseType!U))(T `lhs`, U `rhs`, V `maxRelDiff` = CommonDefaultFor!(T, U), V `maxAbsDiff` = 0.0);
  Computes whether two values are approximately equal, admitting a maximum relative difference, and a maximum absolute difference.
  Parameters:

  T `lhs` | First item to compare.
  U `rhs` | Second item to compare.
  V `maxRelDiff` | Maximum allowable relative difference. Setting to 0.0 disables this check. Default depends on the type of `lhs` and `rhs`: It is approximately half the number of decimal digits of precision of the smaller type.
  V `maxAbsDiff` | Maximum absolute difference. This is mainly usefull for comparing values to zero. Setting to 0.0 disables this check. Defaults to 0.0.

  Returns:
  true if the two items are approximately equal under either criterium. It is sufficient, when value satisfies one of the two criteria.
  If one item is a range, and the other is a single value, then the result is the logical and-ing of calling `isClose` on each element of the ranged item against the single item. If both items are ranges, then `isClose` returns true if and only if the ranges have the same number of elements and if `isClose` evaluates to true for each pair of elements.
  See Also:
  Use feqrel to get the number of equal bits in the mantissa.
  Examples:

      assert(isClose(1.0,0.999_999_999));
      assert(isClose(0.001, 0.000_999_999_999));
      assert(isClose(1_000_000_000.0,999_999_999.0));

      assert(isClose(17.123_456_789, 17.123_456_78));
      assert(!isClose(17.123_456_789, 17.123_45));

      // use explicit 3rd parameter for less (or more) accuracy
      assert(isClose(17.123_456_789, 17.123_45, 1e-6));
      assert(!isClose(17.123_456_789, 17.123_45, 1e-7));

      // use 4th parameter when comparing close to zero
      assert(!isClose(1e-100, 0.0));
      assert(isClose(1e-100, 0.0, 0.0, 1e-90));
      assert(!isClose(1e-10, -1e-10));
      assert(isClose(1e-10, -1e-10, 0.0, 1e-9));
      assert(!isClose(1e-300, 1e-298));
      assert(isClose(1e-300, 1e-298, 0.0, 1e-200));

      // different default limits for different floating point types
      assert(isClose(1.0f, 0.999_99f));
      assert(!isClose(1.0, 0.999_99));
      static if (real.sizeof > double.sizeof)
          assert(!isClose(1.0L, 0.999_999_999L));

  Examples:

      assert(isClose([1.0, 2.0, 3.0], [0.999_999_999, 2.000_000_001, 3.0]));
      assert(!isClose([1.0, 2.0], [0.999_999_999, 2.000_000_001, 3.0]));
      assert(!isClose([1.0, 2.0, 3.0], [0.999_999_999, 2.000_000_001]));

      assert(isClose([2.0, 1.999_999_999, 2.000_000_001], 2.0));
      assert(isClose(2.0, [2.0, 1.999_999_999, 2.000_000_001]));

pure nothrow @nogc @trusted int `cmp`(T)(const(T) `x`, const(T) `y`)
if (isFloatingPoint!T);
  Defines a total order on all floating-point numbers.
  The order is defined as follows:
  - All numbers in [-∞, +∞] are ordered the same way as by built-in comparison, with the exception of -0.0, which is less than +0.0;
  - If the sign bit is set (that is, it's 'negative'), NAN is less than any number; if the sign bit is not set (it is 'positive'), NAN is greater than any number;
  - NANs of the same sign are ordered by the payload ('negative' ones - in reverse order).
  Returns:
  negative value if `x` precedes `y` in the order specified above; 0 if `x` and `y` are identical, and positive value otherwise.
  See Also:
  isIdentical
  Standards:
  Conforms to IEEE 754-2008
  Examples:
  Most numbers are ordered naturally.

      assert(cmp(-double.infinity, -double.max) < 0);
      assert(cmp(-double.max, -100.0) < 0);
      assert(cmp(-100.0, -0.5) < 0);
      assert(cmp(-0.5, 0.0) < 0);
      assert(cmp(0.0, 0.5) < 0);
      assert(cmp(0.5, 100.0) < 0);
      assert(cmp(100.0, double.max) < 0);
      assert(cmp(double.max, double.infinity) < 0);

      writeln(cmp(1.0, 1.0)); // 0

  Examples:
  Positive and negative zeroes are distinct.

      assert(cmp(-0.0, +0.0) < 0);
      assert(cmp(+0.0, -0.0) > 0);

  Examples:
  Depending on the sign, NANs go to either end of the spectrum.

      assert(cmp(-double.nan, -double.infinity) < 0);
      assert(cmp(double.infinity, double.nan) < 0);
      assert(cmp(-double.nan, double.nan) < 0);

  Examples:
  NANs of the same sign are ordered by the payload.

      assert(cmp(NaN(10), NaN(20)) < 0);
      assert(cmp(-NaN(20), -NaN(10)) < 0);

Copyright © 1999-2023 by the D Language Foundation | Page generated by Ddoc on Fri Jun 2 09:00:23 2023