Narrow imports in std.math.

This commit is contained in:
berni44 2021-04-19 21:37:27 +02:00 committed by The Dlang Bot
parent 943cf022ea
commit 0c4dcb32a0
8 changed files with 246 additions and 143 deletions

View file

@ -63,7 +63,7 @@ if ((is(immutable Num == immutable short) || is(immutable Num == immutable byte)
/// ditto
@safe pure nothrow @nogc unittest
{
import std.math : isIdentical, isNaN;
import std.math.traits : isIdentical, isNaN;
assert(isIdentical(abs(-0.0L), 0.0L));
assert(isNaN(abs(real.nan)));
@ -147,7 +147,7 @@ float fabs(float f) @trusted pure nothrow @nogc
///
@safe unittest
{
import std.math : isIdentical;
import std.math.traits : isIdentical;
assert(isIdentical(fabs(0.0f), 0.0f));
assert(isIdentical(fabs(-0.0f), 0.0f));
@ -204,7 +204,8 @@ real sqrt(real x) @nogc @safe pure nothrow { return core.math.sqrt(x); }
///
@safe pure nothrow @nogc unittest
{
import std.math : feqrel, isNaN;
import std.math.operations : feqrel;
import std.math.traits : isNaN;
assert(sqrt(2.0).feqrel(1.4142) > 16);
assert(sqrt(9.0).feqrel(3.0) > 16);
@ -255,7 +256,8 @@ real cbrt(real x) @trusted nothrow @nogc
{
version (CRuntime_Microsoft)
{
import std.math : copysign, exp2;
import std.math.traits : copysign;
import std.math.exponential : exp2;
version (INLINE_YL2X)
return copysign(exp2(core.math.yl2x(fabs(x), 1.0L/3.0L)), x);
@ -269,7 +271,7 @@ real cbrt(real x) @trusted nothrow @nogc
///
@safe unittest
{
import std.math : feqrel;
import std.math.operations : feqrel;
assert(cbrt(1.0).feqrel(1.0) > 16);
assert(cbrt(27.0).feqrel(3.0) > 16);
@ -351,7 +353,7 @@ real hypot(real x, real y) @safe pure nothrow @nogc
///
@safe unittest
{
import std.math : feqrel;
import std.math.operations : feqrel;
assert(hypot(1.0, 1.0).feqrel(1.4142) > 16);
assert(hypot(3.0, 4.0).feqrel(5.0) > 16);
@ -361,7 +363,8 @@ real hypot(real x, real y) @safe pure nothrow @nogc
@safe unittest
{
import std.math : feqrel, isIdentical;
import std.math.operations : feqrel;
import std.math.traits : isIdentical;
static real[3][] vals = // x,y,hypot
[
@ -415,7 +418,7 @@ real hypot(real x, real y) @safe pure nothrow @nogc
T hypot(T)(const T x, const T y, const T z) @safe pure nothrow @nogc
if (isFloatingPoint!T)
{
import std.math : fmax;
import std.math.operations : fmax;
const absx = fabs(x);
const absy = fabs(y);
const absz = fabs(z);
@ -433,7 +436,7 @@ if (isFloatingPoint!T)
///
@safe unittest
{
import std.math : isClose;
import std.math.operations : isClose;
assert(isClose(hypot(1.0, 2.0, 2.0), 3.0));
assert(isClose(hypot(2.0, 3.0, 6.0), 7.0));
@ -443,7 +446,8 @@ if (isFloatingPoint!T)
@safe unittest
{
import std.meta : AliasSeq;
import std.math : isIdentical, isClose;
import std.math.traits : isIdentical;
import std.math.operations : isClose;
static foreach (T; AliasSeq!(float, double, real))
{{
static T[4][] vals = [
@ -825,7 +829,7 @@ if (isFloatingPoint!T)
@safe @nogc pure nothrow unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
import std.meta : AliasSeq;
static foreach (T; AliasSeq!(float, double, real))
@ -957,7 +961,7 @@ if (isFloatingPoint!T)
@safe @nogc pure nothrow unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
import std.meta : AliasSeq;
static foreach (T; AliasSeq!(float, double, real))
@ -1005,7 +1009,8 @@ private T powIntegralImpl(PowType type, T)(T val)
private T powFloatingPointImpl(PowType type, T)(T x)
{
import std.math : copysign, frexp, isFinite, ldexp;
import std.math.traits : copysign, isFinite;
import std.math.exponential : frexp, ldexp;
if (!x.isFinite)
return x;

View file

@ -64,7 +64,9 @@ version (D_HardFloat)
Unqual!F pow(F, G)(F x, G n) @nogc @trusted pure nothrow
if (isFloatingPoint!(F) && isIntegral!(G))
{
import std.math : abs, floor, isNaN, log2;
import std.math.algebraic : abs;
import std.math.rounding : floor;
import std.math.traits : isNaN;
import std.traits : Unsigned;
// NaN ^^ 0 is an exception defined by IEEE (yields 1 instead of NaN)
@ -174,7 +176,7 @@ if (isFloatingPoint!(F) && isIntegral!(G))
///
@safe pure nothrow @nogc unittest
{
import std.math : feqrel;
import std.math.operations : feqrel;
assert(pow(2.0, 5) == 32.0);
assert(pow(1.5, 9).feqrel(38.4433) > 16);
@ -184,7 +186,7 @@ if (isFloatingPoint!(F) && isIntegral!(G))
@safe pure nothrow @nogc unittest
{
import std.math : isClose, feqrel;
import std.math.operations : isClose, feqrel;
// Make sure it instantiates and works properly on immutable values and
// with various integer and float types.
@ -218,7 +220,7 @@ if (isFloatingPoint!(F) && isIntegral!(G))
@safe @nogc nothrow unittest
{
import std.math : isClose;
import std.math.operations : isClose;
assert(isClose(pow(2.0L, 10L), 1024, 1e-18));
}
@ -241,7 +243,8 @@ if (isFloatingPoint!(F) && isIntegral!(G))
@safe @nogc nothrow unittest
{
import std.math : isClose, isInfinity;
import std.math.operations : isClose;
import std.math.traits : isInfinity;
static float f1 = 19100.0f;
static float f2 = 0.000012f;
@ -273,7 +276,7 @@ if (isFloatingPoint!(F) && isIntegral!(G))
@safe @nogc nothrow pure unittest
{
import std.math : isClose;
import std.math.operations : isClose;
enum f1 = 19100.0f;
enum f2 = 0.000012f;
@ -487,7 +490,8 @@ if (isIntegral!I && isFloatingPoint!F)
Unqual!(Largest!(F, G)) pow(F, G)(F x, G y) @nogc @trusted pure nothrow
if (isFloatingPoint!(F) && isFloatingPoint!(G))
{
import std.math : exp2, fabs, isInfinity, isNaN, log2, signbit, sqrt;
import std.math.algebraic : fabs, sqrt;
import std.math.traits : isInfinity, isNaN, signbit;
alias Float = typeof(return);
@ -701,7 +705,7 @@ if (isFloatingPoint!(F) && isFloatingPoint!(G))
///
@safe pure nothrow @nogc unittest
{
import std.math : isClose;
import std.math.operations : isClose;
assert(isClose(pow(2.0, 3.0), 8.0));
assert(isClose(pow(1.5, 10.0), 57.6650390625));
@ -734,11 +738,11 @@ if (isFloatingPoint!(F) && isFloatingPoint!(G))
///
@safe pure nothrow @nogc unittest
{
import std.math : isClose;
import std.math.operations : isClose;
// the result is a complex number
// which cannot be represented as floating point number
import std.math : isNaN;
import std.math.traits : isNaN;
assert(isNaN(pow(-2.5, -1.5)));
// use the ^^-operator of std.complex instead
@ -753,7 +757,7 @@ if (isFloatingPoint!(F) && isFloatingPoint!(G))
@safe pure nothrow @nogc unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
assert(pow(1.5, real.infinity) == real.infinity);
assert(pow(0.5, real.infinity) == 0.0);
@ -775,14 +779,16 @@ if (isFloatingPoint!(F) && isFloatingPoint!(G))
@safe @nogc nothrow unittest
{
import std.math : isClose;
import std.math.operations : isClose;
assert(isClose(pow(2.0L, 10.0L), 1024, 1e-18));
}
@safe pure nothrow @nogc unittest
{
import std.math : isClose, isIdentical, isNaN, PI;
import std.math.operations : isClose;
import std.math.traits : isIdentical, isNaN;
import std.math.constants : PI;
// Test all the special values. These unittests can be run on Windows
// by temporarily changing the version (linux) to version (all).
@ -852,7 +858,7 @@ if (isFloatingPoint!(F) && isFloatingPoint!(G))
// https://issues.dlang.org/show_bug.cgi?id=20508
@safe pure nothrow @nogc unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
assert(isNaN(pow(-double.infinity, 0.5)));
@ -876,7 +882,7 @@ if (isFloatingPoint!(F) && isFloatingPoint!(G))
pragma(inline, true)
real exp(real x) @trusted pure nothrow @nogc // TODO: @safe
{
import std.math : LOG2E;
import std.math.constants : LOG2E;
version (InlineAsm_X87)
{
@ -900,7 +906,8 @@ float exp(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) exp(ca
///
@safe unittest
{
import std.math : feqrel, E;
import std.math.operations : feqrel;
import std.math.constants : E;
assert(exp(0.0) == 1.0);
assert(exp(3.0).feqrel(E * E * E) > 16);
@ -908,7 +915,11 @@ float exp(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) exp(ca
private T expImpl(T)(T x) @safe pure nothrow @nogc
{
import std.math : floatTraits, RealFormat, isNaN, floor, poly, LOG2E;
import std.math : floatTraits, RealFormat;
import std.math.traits : isNaN;
import std.math.rounding : floor;
import std.math.algebraic : poly;
import std.math.constants : LOG2E;
alias F = floatTraits!T;
static if (F.realFormat == RealFormat.ieeeSingle)
@ -1045,12 +1056,16 @@ private T expImpl(T)(T x) @safe pure nothrow @nogc
@safe @nogc nothrow unittest
{
import std.math : floatTraits, RealFormat, NaN, E, feqrel, isIdentical, abs, isClose;
import std.math : floatTraits, RealFormat;
import std.math.operations : NaN, feqrel, isClose;
import std.math.constants : E;
import std.math.traits : isIdentical;
import std.math.algebraic : abs;
version (IeeeFlagsSupport) import std.math : IeeeFlags, resetIeeeFlags, ieeeFlags;
version (IeeeFlagsSupport) import std.math.hardware : IeeeFlags, resetIeeeFlags, ieeeFlags;
version (FloatingPointControlSupport)
{
import std.math : FloatingPointControl;
import std.math.hardware : FloatingPointControl;
FloatingPointControl ctrl;
if (FloatingPointControl.hasExceptionTraps)
@ -1237,7 +1252,8 @@ float expm1(float x) @safe pure nothrow @nogc
///
@safe unittest
{
import std.math : isIdentical, feqrel;
import std.math.traits : isIdentical;
import std.math.operations : feqrel;
assert(isIdentical(expm1(0.0), 0.0));
assert(expm1(1.0).feqrel(1.71828) > 16);
@ -1414,7 +1430,10 @@ L_largenegative:
private T expm1Impl(T)(T x) @safe pure nothrow @nogc
{
import std.math : floatTraits, RealFormat, floor, poly, LN2;
import std.math : floatTraits, RealFormat;
import std.math.rounding : floor;
import std.math.algebraic : poly;
import std.math.constants : LN2;
// Coefficients for exp(x) - 1 and overflow/underflow limits.
enum realFormat = floatTraits!T.realFormat;
@ -1533,7 +1552,8 @@ private T expm1Impl(T)(T x) @safe pure nothrow @nogc
@safe @nogc nothrow unittest
{
import std.math : isNaN, isClose, CommonDefaultFor;
import std.math.traits : isNaN;
import std.math.operations : isClose, CommonDefaultFor;
static void testExpm1(T)()
{
@ -1588,7 +1608,8 @@ float exp2(float x) @nogc @safe pure nothrow { return __ctfe ? cast(float) exp2(
///
@safe unittest
{
import std.math : isIdentical, feqrel;
import std.math.traits : isIdentical;
import std.math.operations : feqrel;
assert(isIdentical(exp2(0.0), 1.0));
assert(exp2(2.0).feqrel(4.0) > 16);
@ -1801,7 +1822,10 @@ L_was_nan:
private T exp2Impl(T)(T x) @nogc @safe pure nothrow
{
import std.math : floatTraits, RealFormat, isNaN, floor, poly;
import std.math : floatTraits, RealFormat;
import std.math.traits : isNaN;
import std.math.rounding : floor;
import std.math.algebraic : poly;
// Coefficients for exp2(x)
enum realFormat = floatTraits!T.realFormat;
@ -1920,7 +1944,9 @@ private T exp2Impl(T)(T x) @nogc @safe pure nothrow
@safe @nogc nothrow unittest
{
import std.math : feqrel, NaN, isIdentical, SQRT2, isClose;
import std.math.operations : feqrel, NaN, isClose;
import std.math.traits : isIdentical;
import std.math.constants : SQRT2;
assert(feqrel(exp2(0.5L), SQRT2) >= real.mant_dig -1);
assert(exp2(8.0L) == 256.0);
@ -1985,7 +2011,8 @@ private T exp2Impl(T)(T x) @nogc @safe pure nothrow
T frexp(T)(const T value, out int exp) @trusted pure nothrow @nogc
if (isFloatingPoint!T)
{
import std.math : isSubnormal, floatTraits, RealFormat;
import std.math : floatTraits, RealFormat;
import std.math.traits : isSubnormal;
if (__ctfe)
{
@ -2211,7 +2238,7 @@ if (isFloatingPoint!T)
///
@safe unittest
{
import std.math : isClose;
import std.math.operations : isClose;
int exp;
real mantissa = frexp(123.456L, exp);
@ -2228,7 +2255,7 @@ if (isFloatingPoint!T)
@safe @nogc nothrow unittest
{
import std.math : isClose;
import std.math.operations : isClose;
int exp;
real mantissa = frexp(123.456L, exp);
@ -2239,7 +2266,8 @@ if (isFloatingPoint!T)
@safe unittest
{
import std.math : isIdentical, floatTraits, RealFormat;
import std.math : floatTraits, RealFormat;
import std.math.traits : isIdentical;
import std.meta : AliasSeq;
import std.typecons : tuple, Tuple;
@ -2570,7 +2598,8 @@ alias FP_ILOGBNAN = core.stdc.math.FP_ILOGBNAN;
@safe nothrow @nogc unittest
{
import std.math : nextUp, floatTraits, RealFormat;
import std.math : floatTraits, RealFormat;
import std.math.operations : nextUp;
import std.meta : AliasSeq;
import std.typecons : Tuple;
static foreach (F; AliasSeq!(float, double, real))
@ -2720,7 +2749,7 @@ float ldexp(float n, int exp) @safe pure nothrow @nogc { return core.math.ldex
@safe @nogc nothrow unittest
{
import std.math : isClose;
import std.math.operations : isClose;
static real[3][] vals = // value,exp,ldexp
[
@ -2861,7 +2890,9 @@ private
*/
real log(real x) @safe pure nothrow @nogc
{
import std.math : LN2, LOG2, isInfinity, isNaN, signbit, SQRT1_2, poly;
import std.math.constants : LN2, LOG2, SQRT1_2;
import std.math.traits : isInfinity, isNaN, signbit;
import std.math.algebraic : poly;
version (INLINE_YL2X)
return core.math.yl2x(x, LN2);
@ -2941,7 +2972,8 @@ real log(real x) @safe pure nothrow @nogc
///
@safe pure nothrow @nogc unittest
{
import std.math : feqrel, E;
import std.math.operations : feqrel;
import std.math.constants : E;
assert(feqrel(log(E), 1) >= real.mant_dig - 1);
}
@ -2958,7 +2990,9 @@ real log(real x) @safe pure nothrow @nogc
*/
real log10(real x) @safe pure nothrow @nogc
{
import std.math : LOG2, LN2, fabs, isNaN, isInfinity, signbit, SQRT1_2;
import std.math.constants : LOG2, LN2, SQRT1_2;
import std.math.algebraic : fabs;
import std.math.traits : isNaN, isInfinity, signbit;
version (INLINE_YL2X)
return core.math.yl2x(x, LOG2);
@ -3042,7 +3076,7 @@ real log10(real x) @safe pure nothrow @nogc
///
@safe pure nothrow @nogc unittest
{
import std.math : fabs;
import std.math.algebraic : fabs;
assert(fabs(log10(1000) - 3) < .000001);
}
@ -3063,7 +3097,9 @@ real log10(real x) @safe pure nothrow @nogc
*/
real log1p(real x) @safe pure nothrow @nogc
{
import std.math : fabs, isNaN, isInfinity, signbit, LN2;
import std.math.algebraic : fabs;
import std.math.traits : isNaN, isInfinity, signbit;
import std.math.constants : LN2;
version (INLINE_YL2X)
{
@ -3090,7 +3126,8 @@ real log1p(real x) @safe pure nothrow @nogc
///
@safe pure unittest
{
import std.math : isIdentical, isNaN, feqrel;
import std.math.traits : isIdentical, isNaN;
import std.math.operations : feqrel;
assert(isIdentical(log1p(0.0), 0.0));
assert(log1p(1.0).feqrel(0.69314) > 16);
@ -3115,7 +3152,9 @@ real log1p(real x) @safe pure nothrow @nogc
*/
real log2(real x) @safe pure nothrow @nogc
{
import std.math : isNaN, isInfinity, signbit, SQRT1_2, poly;
import std.math.traits : isNaN, isInfinity, signbit;
import std.math.constants : SQRT1_2;
import std.math.algebraic : poly;
version (INLINE_YL2X)
return core.math.yl2x(x, 1.0L);
@ -3190,14 +3229,14 @@ real log2(real x) @safe pure nothrow @nogc
///
@safe unittest
{
import std.math : isClose;
import std.math.operations : isClose;
assert(isClose(log2(1024.0L), 10));
}
@safe @nogc nothrow unittest
{
import std.math : isClose;
import std.math.operations : isClose;
// check if values are equal to 19 decimal digits of precision
assert(isClose(log2(1024.0L), 10, 1e-18));
@ -3292,7 +3331,7 @@ float scalbn(float x, int n) @safe pure nothrow @nogc { return _scalbn(x,n); }
pragma(inline, true)
private F _scalbn(F)(F x, int n)
{
import std.math : isInfinity;
import std.math.traits : isInfinity;
if (__ctfe)
{

View file

@ -245,7 +245,7 @@ public:
///
@safe unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
static void func() {
int a = 10 * 10;
@ -350,7 +350,7 @@ void resetIeeeFlags() @trusted nothrow @nogc
///
@safe nothrow unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
pragma(inline, false) static void blockopt(ref real x) {}
resetIeeeFlags();
@ -854,7 +854,7 @@ private:
///
@safe unittest
{
import std.math : lrint;
import std.math.rounding : lrint;
FloatingPointControl fpctrl;

View file

@ -127,7 +127,7 @@ real NaN(ulong payload) @trusted pure nothrow @nogc
///
@safe @nogc pure nothrow unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
real a = NaN(1_000_000);
assert(isNaN(a));
@ -212,7 +212,7 @@ ulong getNaNPayload(real x) @trusted pure nothrow @nogc
///
@safe @nogc pure nothrow unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
real a = NaN(1_000_000);
assert(isNaN(a));
@ -221,7 +221,7 @@ ulong getNaNPayload(real x) @trusted pure nothrow @nogc
@safe @nogc pure nothrow unittest
{
import std.math : isIdentical, isNaN;
import std.math.traits : isIdentical, isNaN;
enum real a = NaN(1_000_000);
static assert(isNaN(a));
@ -522,7 +522,8 @@ float nextDown(float x) @safe pure nothrow @nogc
@safe pure nothrow @nogc unittest
{
import std.math : floatTraits, RealFormat, isIdentical;
import std.math : floatTraits, RealFormat;
import std.math.traits : isIdentical;
static if (floatTraits!(real).realFormat == RealFormat.ieeeExtended ||
floatTraits!(real).realFormat == RealFormat.ieeeDouble ||
@ -662,7 +663,7 @@ float nextDown(float x) @safe pure nothrow @nogc
*/
T nextafter(T)(const T x, const T y) @safe pure nothrow @nogc
{
import std.math : isNaN;
import std.math.traits : isNaN;
if (x == y || isNaN(y))
{
@ -680,7 +681,7 @@ T nextafter(T)(const T x, const T y) @safe pure nothrow @nogc
///
@safe pure nothrow @nogc unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
float a = 1;
assert(is(typeof(nextafter(a, a)) == float));
@ -703,7 +704,7 @@ T nextafter(T)(const T x, const T y) @safe pure nothrow @nogc
@safe pure nothrow @nogc unittest
{
import std.math : isNaN, signbit;
import std.math.traits : isNaN, signbit;
// CTFE
enum float a = 1;
@ -753,7 +754,7 @@ real fdim(real x, real y) @safe pure nothrow @nogc
///
@safe pure nothrow @nogc unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
assert(fdim(2.0, 0.0) == 2.0);
assert(fdim(-2.0, 0.0) == 0.0);
@ -773,7 +774,7 @@ real fdim(real x, real y) @safe pure nothrow @nogc
F fmax(F)(const F x, const F y) @safe pure nothrow @nogc
if (__traits(isFloating, F))
{
import std.math : isNaN;
import std.math.traits : isNaN;
// Do the more predictable test first. Generates 0 branches with ldc and 1 branch with gdc.
// See https://godbolt.org/z/erxrW9
@ -805,7 +806,7 @@ if (__traits(isFloating, F))
F fmin(F)(const F x, const F y) @safe pure nothrow @nogc
if (__traits(isFloating, F))
{
import std.math : isNaN;
import std.math.traits : isNaN;
// Do the more predictable test first. Generates 0 branches with ldc and 1 branch with gdc.
// See https://godbolt.org/z/erxrW9
@ -864,7 +865,8 @@ real fma(real x, real y, real z) @safe pure nothrow @nogc { return (x * y) + z;
int feqrel(X)(const X x, const X y) @trusted pure nothrow @nogc
if (isFloatingPoint!(X))
{
import std.math : floatTraits, RealFormat, fabs;
import std.math : floatTraits, RealFormat;
import std.math.algebraic : fabs;
/* Public Domain. Author: Don Clugston, 18 Aug 2005.
*/
@ -1033,7 +1035,7 @@ if (isFloatingPoint!(X))
deprecated("approxEqual will be removed in 2.106.0. Please use isClose instead.")
bool approxEqual(T, U, V)(T value, U reference, V maxRelDiff = 1e-2, V maxAbsDiff = 1e-5)
{
import std.math : fabs;
import std.math.algebraic : fabs;
import std.range.primitives : empty, front, isInputRange, popFront;
static if (isInputRange!T)
{
@ -1287,7 +1289,7 @@ bool isClose(T, U, V = CommonType!(FloatingPointBaseType!T,FloatingPointBaseType
lhs == -lhs.infinity || rhs == -rhs.infinity) return false;
}
import std.math : abs;
import std.math.algebraic : abs;
auto diff = abs(lhs - rhs);
@ -1594,7 +1596,7 @@ if (isFloatingPoint!T)
// IBM Extended doubledouble does not follow the general
// sign-exponent-significand layout, so has to be handled generically
import std.math : signbit, isNaN, getNaNPayload;
import std.math.traits : signbit, isNaN;
const int xSign = signbit(x),
ySign = signbit(y);

View file

@ -51,7 +51,8 @@ real fmod(real x, real y) @trusted nothrow @nogc
///
@safe unittest
{
import std.math : feqrel, isIdentical, isNaN;
import std.math.operations : feqrel;
import std.math.traits : isIdentical, isNaN;
assert(isIdentical(fmod(0.0, 1.0), 0.0));
assert(fmod(5.0, 3.0).feqrel(2.0) > 16);
@ -73,7 +74,8 @@ real modf(real x, ref real i) @trusted nothrow @nogc
{
version (CRuntime_Microsoft)
{
import std.math : copysign, isInfinity, trunc;
import std.math.traits : copysign, isInfinity;
import std.math.rounding : trunc;
i = trunc(x);
return copysign(isInfinity(x) ? 0.0 : x - i, x);
@ -85,7 +87,7 @@ real modf(real x, ref real i) @trusted nothrow @nogc
///
@safe unittest
{
import std.math : feqrel;
import std.math.operations : feqrel;
real frac;
real intpart;
@ -129,7 +131,8 @@ real remquo(real x, real y, out int n) @trusted nothrow @nogc /// ditto
///
@safe @nogc nothrow unittest
{
import std.math : feqrel, isNaN;
import std.math.operations : feqrel;
import std.math.traits : isNaN;
assert(remainder(5.1, 3.0).feqrel(-0.9) > 16);
assert(remainder(-5.1, 3.0).feqrel(0.9) > 16);
@ -142,7 +145,7 @@ real remquo(real x, real y, out int n) @trusted nothrow @nogc /// ditto
///
@safe @nogc nothrow unittest
{
import std.math : feqrel;
import std.math.operations : feqrel;
int n;

View file

@ -83,7 +83,7 @@ real ceil(real x) @trusted pure nothrow @nogc
}
else
{
import std.math : isInfinity, isNaN;
import std.math.traits : isInfinity, isNaN;
// Special cases.
if (isNaN(x) || isInfinity(x))
@ -100,7 +100,7 @@ real ceil(real x) @trusted pure nothrow @nogc
///
@safe pure nothrow @nogc unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
assert(ceil(+123.456L) == +124);
assert(ceil(-123.456L) == -123);
@ -117,7 +117,7 @@ real ceil(real x) @trusted pure nothrow @nogc
/// ditto
double ceil(double x) @trusted pure nothrow @nogc
{
import std.math : isInfinity, isNaN;
import std.math.traits : isInfinity, isNaN;
// Special cases.
if (isNaN(x) || isInfinity(x))
@ -132,7 +132,7 @@ double ceil(double x) @trusted pure nothrow @nogc
@safe pure nothrow @nogc unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
assert(ceil(+123.456) == +124);
assert(ceil(-123.456) == -123);
@ -149,7 +149,7 @@ double ceil(double x) @trusted pure nothrow @nogc
/// ditto
float ceil(float x) @trusted pure nothrow @nogc
{
import std.math : isInfinity, isNaN;
import std.math.traits : isInfinity, isNaN;
// Special cases.
if (isNaN(x) || isInfinity(x))
@ -164,7 +164,7 @@ float ceil(float x) @trusted pure nothrow @nogc
@safe pure nothrow @nogc unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
assert(ceil(+123.456f) == +124);
assert(ceil(-123.456f) == -123);
@ -226,7 +226,7 @@ real floor(real x) @trusted pure nothrow @nogc
}
else
{
import std.math : isInfinity, isNaN;
import std.math.traits : isInfinity, isNaN;
// Special cases.
if (isNaN(x) || isInfinity(x) || x == 0.0)
@ -239,7 +239,7 @@ real floor(real x) @trusted pure nothrow @nogc
///
@safe pure nothrow @nogc unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
assert(floor(+123.456L) == +123);
assert(floor(-123.456L) == -124);
@ -258,7 +258,7 @@ real floor(real x) @trusted pure nothrow @nogc
/// ditto
double floor(double x) @trusted pure nothrow @nogc
{
import std.math : isInfinity, isNaN;
import std.math.traits : isInfinity, isNaN;
// Special cases.
if (isNaN(x) || isInfinity(x) || x == 0.0)
@ -269,7 +269,7 @@ double floor(double x) @trusted pure nothrow @nogc
@safe pure nothrow @nogc unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
assert(floor(+123.456) == +123);
assert(floor(-123.456) == -124);
@ -288,7 +288,7 @@ double floor(double x) @trusted pure nothrow @nogc
/// ditto
float floor(float x) @trusted pure nothrow @nogc
{
import std.math : isInfinity, isNaN;
import std.math.traits : isInfinity, isNaN;
// Special cases.
if (isNaN(x) || isInfinity(x) || x == 0.0)
@ -299,7 +299,7 @@ float floor(float x) @trusted pure nothrow @nogc
@safe pure nothrow @nogc unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
assert(floor(+123.456f) == +123);
assert(floor(-123.456f) == -124);
@ -331,7 +331,7 @@ float floor(float x) @trusted pure nothrow @nogc
Unqual!F quantize(alias rfunc = rint, F)(const F val, const F unit)
if (is(typeof(rfunc(F.init)) : F) && isFloatingPoint!F)
{
import std.math : isInfinity;
import std.math.traits : isInfinity;
typeof(return) ret = val;
if (unit != 0)
@ -346,7 +346,7 @@ if (is(typeof(rfunc(F.init)) : F) && isFloatingPoint!F)
///
@safe pure nothrow @nogc unittest
{
import std.math : floor, isClose;
import std.math.operations : isClose;
assert(isClose(12345.6789L.quantize(0.01L), 12345.68L));
assert(isClose(12345.6789L.quantize!floor(0.01L), 12345.67L));
@ -356,7 +356,8 @@ if (is(typeof(rfunc(F.init)) : F) && isFloatingPoint!F)
///
@safe pure nothrow @nogc unittest
{
import std.math : isClose, isNaN;
import std.math.operations : isClose;
import std.math.traits : isNaN;
assert(isClose(12345.6789L.quantize(0), 12345.6789L));
assert(12345.6789L.quantize(real.infinity).isNaN);
@ -376,7 +377,7 @@ if (is(typeof(rfunc(F.init)) : F) && isFloatingPoint!F)
Unqual!F quantize(real base, alias rfunc = rint, F, E)(const F val, const E exp)
if (is(typeof(rfunc(F.init)) : F) && isFloatingPoint!F && isIntegral!E)
{
import std.math : pow;
import std.math.exponential : pow;
// TODO: Compile-time optimization for power-of-two bases?
return quantize!rfunc(val, pow(cast(F) base, exp));
@ -386,7 +387,7 @@ if (is(typeof(rfunc(F.init)) : F) && isFloatingPoint!F && isIntegral!E)
Unqual!F quantize(real base, long exp = 1, alias rfunc = rint, F)(const F val)
if (is(typeof(rfunc(F.init)) : F) && isFloatingPoint!F)
{
import std.math : pow;
import std.math.exponential : pow;
enum unit = cast(F) pow(base, exp);
return quantize!rfunc(val, unit);
@ -395,7 +396,7 @@ if (is(typeof(rfunc(F.init)) : F) && isFloatingPoint!F)
///
@safe pure nothrow @nogc unittest
{
import std.math : floor, isClose;
import std.math.operations : isClose;
assert(isClose(12345.6789L.quantize!10(-2), 12345.68L));
assert(isClose(12345.6789L.quantize!(10, -2), 12345.68L));
@ -408,7 +409,8 @@ if (is(typeof(rfunc(F.init)) : F) && isFloatingPoint!F)
@safe pure nothrow @nogc unittest
{
import std.math : floor, log10, pow, isClose;
import std.math.exponential : log10, pow;
import std.math.operations : isClose;
import std.meta : AliasSeq;
static foreach (F; AliasSeq!(real, double, float))
@ -443,7 +445,7 @@ real nearbyint(real x) @safe pure nothrow @nogc
///
@safe pure unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
assert(nearbyint(0.4) == 0);
assert(nearbyint(0.5) == 0);
@ -486,7 +488,7 @@ float rint(float x) @safe pure nothrow @nogc
///
@safe unittest
{
import std.math : isNaN;
import std.math.traits : isNaN;
version (IeeeFlagsSupport) resetIeeeFlags();
assert(rint(0.4) == 0);
@ -731,7 +733,7 @@ auto round(real x) @trusted nothrow @nogc
{
version (CRuntime_Microsoft)
{
import std.math : FloatingPointControl;
import std.math.hardware : FloatingPointControl;
auto old = FloatingPointControl.getControlState();
FloatingPointControl.setControlState(

View file

@ -722,7 +722,7 @@ Returns:
bool isPowerOf2(X)(const X x) pure @safe nothrow @nogc
if (isNumeric!X)
{
import std.math : frexp;
import std.math.exponential : frexp;
static if (isFloatingPoint!X)
{
@ -748,7 +748,7 @@ if (isNumeric!X)
///
@safe unittest
{
import std.math : pow;
import std.math.exponential : pow;
assert( isPowerOf2(1.0L));
assert( isPowerOf2(2.0L));
@ -779,7 +779,7 @@ if (isNumeric!X)
@safe unittest
{
import std.math : pow;
import std.math.exponential : pow;
import std.meta : AliasSeq;
enum smallP2 = pow(2.0L, -62);

View file

@ -75,7 +75,7 @@ float cos(float x) @safe pure nothrow @nogc { return core.math.cos(x); }
///
@safe unittest
{
import std.math : isClose;
import std.math.operations : isClose;
assert(cos(0.0) == 1.0);
assert(cos(1.0).isClose(0.5403023059));
@ -90,7 +90,7 @@ float cos(float x) @safe pure nothrow @nogc { return core.math.cos(x); }
@safe pure nothrow @nogc unittest
{
import std.math : fabs;
import std.math.algebraic : fabs;
float f = cos(-2.0f);
assert(fabs(f - -0.416147f) < .00001);
@ -133,7 +133,7 @@ float sin(float x) @safe pure nothrow @nogc { return core.math.sin(x); }
///
@safe unittest
{
import std.math : sin, PI;
import std.math.constants : PI;
import std.stdio : writefln;
void someFunc()
@ -152,7 +152,7 @@ float sin(float x) @safe pure nothrow @nogc { return core.math.sin(x); }
@safe pure nothrow @nogc unittest
{
import std.math : fabs;
import std.math.algebraic : fabs;
float f = sin(-2.0f);
assert(fabs(f - -0.909297f) < .00001);
@ -196,7 +196,10 @@ float tan(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) tan(ca
///
@safe unittest
{
import std.math : isClose, isIdentical, PI, sqrt;
import std.math.operations : isClose;
import std.math.traits : isIdentical;
import std.math.constants : PI;
import std.math.algebraic : sqrt;
assert(isIdentical(tan(0.0), 0.0));
assert(tan(PI).isClose(0, 0.0, 1e-10));
@ -300,7 +303,11 @@ Lret: {}
private T tanImpl(T)(T x) @safe pure nothrow @nogc
{
import std.math : floatTraits, floor, isInfinity, isNaN, poly, PI, PI_4, RealFormat, signbit;
import std.math : floatTraits, RealFormat;
import std.math.constants : PI, PI_4;
import std.math.rounding : floor;
import std.math.algebraic : poly;
import std.math.traits : isInfinity, isNaN, signbit;
// Coefficients for tan(x) and PI/4 split into three parts.
enum realFormat = floatTraits!T.realFormat;
@ -437,7 +444,9 @@ private T tanImpl(T)(T x) @safe pure nothrow @nogc
{
static void testTan(T)()
{
import std.math : CommonDefaultFor, isClose, isIdentical, isNaN, NaN, PI, PI_4;
import std.math.operations : CommonDefaultFor, isClose, NaN;
import std.math.traits : isIdentical, isNaN;
import std.math.constants : PI, PI_4;
// ±0
const T zero = 0.0;
@ -501,13 +510,16 @@ private T tanImpl(T)(T x) @safe pure nothrow @nogc
foreach (T; AliasSeq!(real, double, float))
testTan!T();
import std.math : isClose, PI, sqrt;
import std.math.operations : isClose;
import std.math.constants : PI;
import std.math.algebraic : sqrt;
assert(isClose(tan(PI / 3), sqrt(3.0L), real.sizeof > double.sizeof ? 1e-15 : 1e-14));
}
@safe pure nothrow @nogc unittest
{
import std.math : fabs, isNaN;
import std.math.algebraic : fabs;
import std.math.traits : isNaN;
float f = tan(-2.0f);
assert(fabs(f - 2.18504f) < .00001);
@ -541,7 +553,7 @@ private T tanImpl(T)(T x) @safe pure nothrow @nogc
*/
real acos(real x) @safe pure nothrow @nogc
{
import std.math : sqrt;
import std.math.algebraic : sqrt;
return atan2(sqrt(1-x*x), x);
}
@ -555,7 +567,9 @@ float acos(float x) @safe pure nothrow @nogc { return acos(cast(real) x); }
///
@safe unittest
{
import std.math : isClose, isNaN, PI;
import std.math.operations : isClose;
import std.math.traits : isNaN;
import std.math.constants : PI;
assert(acos(0.0).isClose(1.570796327));
assert(acos(0.5).isClose(PI / 3));
@ -564,7 +578,8 @@ float acos(float x) @safe pure nothrow @nogc { return acos(cast(real) x); }
@safe @nogc nothrow unittest
{
import std.math : isClose, PI;
import std.math.operations : isClose;
import std.math.constants : PI;
assert(isClose(acos(0.5), PI / 3, real.sizeof > double.sizeof ? 1e-15 : 1e-14));
}
@ -582,7 +597,7 @@ float acos(float x) @safe pure nothrow @nogc { return acos(cast(real) x); }
*/
real asin(real x) @safe pure nothrow @nogc
{
import std.math : sqrt;
import std.math.algebraic : sqrt;
return atan2(x, sqrt(1-x*x));
}
@ -596,7 +611,9 @@ float asin(float x) @safe pure nothrow @nogc { return asin(cast(real) x); }
///
@safe unittest
{
import std.math : isClose, isIdentical, isNaN, PI;
import std.math.operations : isClose;
import std.math.traits : isIdentical, isNaN;
import std.math.constants : PI;
assert(isIdentical(asin(0.0), 0.0));
assert(asin(0.5).isClose(PI / 6));
@ -605,7 +622,8 @@ float asin(float x) @safe pure nothrow @nogc { return asin(cast(real) x); }
@safe @nogc nothrow unittest
{
import std.math : isClose, PI;
import std.math.operations : isClose;
import std.math.constants : PI;
assert(isClose(asin(0.5), PI / 6, real.sizeof > double.sizeof ? 1e-15 : 1e-14));
}
@ -642,7 +660,10 @@ float atan(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) atan(
///
@safe unittest
{
import std.math : isClose, isIdentical, PI, sqrt;
import std.math.operations : isClose;
import std.math.traits : isIdentical;
import std.math.constants : PI;
import std.math.algebraic : sqrt;
assert(isIdentical(atan(0.0), 0.0));
assert(atan(sqrt(3.0)).isClose(PI / 3));
@ -650,7 +671,10 @@ float atan(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) atan(
private T atanImpl(T)(T x) @safe pure nothrow @nogc
{
import std.math : copysign, floatTraits, isInfinity, PI_2, PI_4, poly, RealFormat, signbit;
import std.math : floatTraits, RealFormat;
import std.math.traits : copysign, isInfinity, signbit;
import std.math.constants : PI_2, PI_4;
import std.math.algebraic : poly;
// Coefficients for atan(x)
enum realFormat = floatTraits!T.realFormat;
@ -810,7 +834,9 @@ private T atanImpl(T)(T x) @safe pure nothrow @nogc
{
static void testAtan(T)()
{
import std.math : CommonDefaultFor, isClose, isIdentical, NaN, PI_2, PI_4;
import std.math.operations : CommonDefaultFor, isClose, NaN;
import std.math.traits : isIdentical;
import std.math.constants : PI_2, PI_4;
// ±0
const T zero = 0.0;
@ -855,7 +881,9 @@ private T atanImpl(T)(T x) @safe pure nothrow @nogc
foreach (T; AliasSeq!(real, double, float))
testAtan!T();
import std.math : isClose, sqrt, PI;
import std.math.operations : isClose;
import std.math.algebraic : sqrt;
import std.math.constants : PI;
assert(isClose(atan(sqrt(3.0L)), PI / 3, real.sizeof > double.sizeof ? 1e-15 : 1e-14));
}
@ -908,7 +936,9 @@ float atan2(float y, float x) @safe pure nothrow @nogc
///
@safe unittest
{
import std.math : isClose, PI, sqrt;
import std.math.operations : isClose;
import std.math.constants : PI;
import std.math.algebraic : sqrt;
assert(atan2(1.0, sqrt(3.0)).isClose(PI / 6));
}
@ -938,7 +968,8 @@ private real atan2Asm(real y, real x) @trusted pure nothrow @nogc
private T atan2Impl(T)(T y, T x) @safe pure nothrow @nogc
{
import std.math : copysign, isInfinity, isNaN, PI, PI_2, PI_4, signbit;
import std.math.traits : copysign, isInfinity, isNaN, signbit;
import std.math.constants : PI, PI_2, PI_4;
// Special cases.
if (isNaN(x) || isNaN(y))
@ -993,7 +1024,9 @@ private T atan2Impl(T)(T y, T x) @safe pure nothrow @nogc
{
static void testAtan2(T)()
{
import std.math : isClose, isIdentical, isNaN, PI, PI_2, PI_4;
import std.math.operations : isClose;
import std.math.traits : isIdentical, isNaN;
import std.math.constants : PI, PI_2, PI_4;
// NaN
const T nan = T.nan;
@ -1063,7 +1096,9 @@ private T atan2Impl(T)(T y, T x) @safe pure nothrow @nogc
foreach (T; AliasSeq!(real, double, float))
testAtan2!T();
import std.math : isClose, sqrt, PI;
import std.math.operations : isClose;
import std.math.algebraic : sqrt;
import std.math.constants : PI;
assert(isClose(atan2(1.0L, sqrt(3.0L)), PI / 6, real.sizeof > double.sizeof ? 1e-15 : 1e-14));
}
@ -1077,7 +1112,7 @@ private T atan2Impl(T)(T y, T x) @safe pure nothrow @nogc
*/
real cosh(real x) @safe pure nothrow @nogc
{
import std.math : exp;
import std.math.exponential : exp;
// cosh = (exp(x)+exp(-x))/2.
// The naive implementation works correctly.
@ -1094,7 +1129,8 @@ float cosh(float x) @safe pure nothrow @nogc { return cosh(cast(real) x); }
///
@safe unittest
{
import std.math : E, isClose;
import std.math.constants : E;
import std.math.operations : isClose;
assert(cosh(0.0) == 1.0);
assert(cosh(1.0).isClose((E + 1.0 / E) / 2));
@ -1102,7 +1138,8 @@ float cosh(float x) @safe pure nothrow @nogc { return cosh(cast(real) x); }
@safe @nogc nothrow unittest
{
import std.math : isClose, E;
import std.math.constants : E;
import std.math.operations : isClose;
assert(isClose(cosh(1.0), (E + 1.0 / E) / 2, real.sizeof > double.sizeof ? 1e-15 : 1e-14));
}
@ -1127,7 +1164,9 @@ float sinh(float x) @safe pure nothrow @nogc { return _sinh(x); }
///
@safe unittest
{
import std.math : E, isClose, isIdentical;
import std.math.constants : E;
import std.math.operations : isClose;
import std.math.traits : isIdentical;
enum sinh1 = (E - 1.0 / E) / 2;
import std.meta : AliasSeq;
@ -1140,7 +1179,10 @@ float sinh(float x) @safe pure nothrow @nogc { return _sinh(x); }
private F _sinh(F)(F x)
{
import std.math : copysign, exp, expm1, fabs, LN2;
import std.math.traits : copysign;
import std.math.exponential : exp, expm1;
import std.math.algebraic : fabs;
import std.math.constants : LN2;
// sinh(x) = (exp(x)-exp(-x))/2;
// Very large arguments could cause an overflow, but
@ -1157,7 +1199,8 @@ private F _sinh(F)(F x)
@safe @nogc nothrow unittest
{
import std.math : isClose, E;
import std.math.constants : E;
import std.math.operations : isClose;
assert(isClose(sinh(1.0L), real((E - 1.0 / E) / 2), real.sizeof > double.sizeof ? 1e-15 : 1e-14));
}
@ -1181,7 +1224,8 @@ float tanh(float x) @safe pure nothrow @nogc { return _tanh(x); }
///
@safe unittest
{
import std.math : isClose, isIdentical;
import std.math.operations : isClose;
import std.math.traits : isIdentical;
assert(isIdentical(tanh(0.0), 0.0));
assert(tanh(1.0).isClose(sinh(1.0) / cosh(1.0)));
@ -1189,7 +1233,10 @@ float tanh(float x) @safe pure nothrow @nogc { return _tanh(x); }
private F _tanh(F)(F x)
{
import std.math : copysign, expm1, fabs, LN2;
import std.math.traits : copysign;
import std.math.exponential : expm1;
import std.math.algebraic : fabs;
import std.math.constants : LN2;
// tanh(x) = (exp(x) - exp(-x))/(exp(x)+exp(-x))
if (fabs(x) > F.mant_dig * F(LN2))
@ -1203,7 +1250,7 @@ private F _tanh(F)(F x)
@safe @nogc nothrow unittest
{
import std.math : isClose;
import std.math.operations : isClose;
assert(isClose(tanh(1.0L), sinh(1.0L) / cosh(1.0L), real.sizeof > double.sizeof ? 1e-15 : 1e-14));
}
@ -1237,7 +1284,7 @@ float acosh(float x) @safe pure nothrow @nogc { return _acosh(x); }
///
@safe @nogc nothrow unittest
{
import std.math : isIdentical, isNaN;
import std.math.traits : isIdentical, isNaN;
assert(isNaN(acosh(0.9)));
assert(isNaN(acosh(real.nan)));
@ -1248,7 +1295,9 @@ float acosh(float x) @safe pure nothrow @nogc { return _acosh(x); }
private F _acosh(F)(F x) @safe pure nothrow @nogc
{
import std.math : LN2, log, sqrt;
import std.math.constants : LN2;
import std.math.exponential : log;
import std.math.algebraic : sqrt;
if (x > 1/F.epsilon)
return F(LN2) + log(x);
@ -1258,7 +1307,7 @@ private F _acosh(F)(F x) @safe pure nothrow @nogc
@safe @nogc nothrow unittest
{
import std.math : isClose;
import std.math.operations : isClose;
assert(isClose(acosh(cosh(3.0L)), 3.0L, real.sizeof > double.sizeof ? 1e-15 : 1e-14));
}
@ -1290,7 +1339,7 @@ float asinh(float x) @safe pure nothrow @nogc { return _asinh(x); }
///
@safe @nogc nothrow unittest
{
import std.math : isIdentical, isNaN;
import std.math.traits : isIdentical, isNaN;
assert(isIdentical(asinh(0.0), 0.0));
assert(isIdentical(asinh(-0.0), -0.0));
@ -1301,7 +1350,10 @@ float asinh(float x) @safe pure nothrow @nogc { return _asinh(x); }
private F _asinh(F)(F x)
{
import std.math : copysign, fabs, log, log1p, LN2, sqrt;
import std.math.traits : copysign;
import std.math.algebraic : fabs, sqrt;
import std.math.exponential : log, log1p;
import std.math.constants : LN2;
return (fabs(x) > 1 / F.epsilon)
// beyond this point, x*x + 1 == x*x
@ -1312,7 +1364,7 @@ private F _asinh(F)(F x)
@safe unittest
{
import std.math : isClose;
import std.math.operations : isClose;
assert(isClose(asinh(sinh(3.0L)), 3.0L, real.sizeof > double.sizeof ? 1e-15 : 1e-14));
}
@ -1337,7 +1389,7 @@ private F _asinh(F)(F x)
*/
real atanh(real x) @safe pure nothrow @nogc
{
import std.math : log1p;
import std.math.exponential : log1p;
// log( (1+x)/(1-x) ) == log ( 1 + (2*x)/(1-x) )
return 0.5 * log1p( 2 * x / (1 - x) );
@ -1352,7 +1404,7 @@ float atanh(float x) @safe pure nothrow @nogc { return atanh(cast(real) x); }
///
@safe @nogc nothrow unittest
{
import std.math : isIdentical, isNaN;
import std.math.traits : isIdentical, isNaN;
assert(isIdentical(atanh(0.0), 0.0));
assert(isIdentical(atanh(-0.0),-0.0));
@ -1363,7 +1415,7 @@ float atanh(float x) @safe pure nothrow @nogc { return atanh(cast(real) x); }
@safe unittest
{
import std.math : isClose;
import std.math.operations : isClose;
assert(isClose(atanh(tanh(0.5L)), 0.5, real.sizeof > double.sizeof ? 1e-15 : 1e-14));
}