* New core.math.toPrec templates have been added as an intrinsic.
Some floating point algorithms, such as Kahan-Babuska-Neumaier
Summation, require rounding to specific precisions. Rounding to
precision after every operation, however, loses overall precision in
the general case and is a runtime performance problem.
Adding these functions guarantee the rounding at required points in
the code, and document where in the algorithm the requirement exists.
* Support IBM long double types in core.internal.convert.
* Add missing aliases for 64-bit vectors in core.simd.
* RUNNABLE_PHOBOS_TEST directive has been properly integrated into the
D2 language testsuite.
Reviewed-on: https://github.com/dlang/druntime/pull/3063
https://github.com/dlang/dmd/pull/11054
gcc/d/ChangeLog:
* intrinsics.cc (expand_intrinsic_toprec): New function.
(maybe_expand_intrinsic): Handle toPrec intrinsics.
* intrinsics.def (TOPRECF, TOPREC, TOPRECL): Add toPrec intrinsics.
+2020-04-25 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * intrinsics.cc (expand_intrinsic_toprec): New function.
+ (maybe_expand_intrinsic): Handle toPrec intrinsics.
+ * intrinsics.def (TOPRECF, TOPREC, TOPRECL): Add toPrec intrinsics.
+
2020-04-24 Iain Buclaw <ibuclaw@gdcproject.org>
* d-spec.cc (need_phobos): Remove.
-62ce36f3737de691217c21f0173f411734eb1d43
+09db0c41ee922502fa0966bde24c1cb9b15ad436
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
base, exponent);
}
+/* Expand a front-end intrinsic call to toPrec(). This takes one argument, the
+ signature to which can be either:
+
+ T toPrec(T)(float f);
+ T toPrec(T)(double f);
+ T toPrec(T)(real f);
+
+ This rounds the argument F to the precision of the specified floating
+ point type T. The original call expression is held in CALLEXP. */
+
+static tree
+expand_intrinsic_toprec (tree callexp)
+{
+ tree f = CALL_EXPR_ARG (callexp, 0);
+ tree type = TREE_TYPE (callexp);
+
+ return convert (type, f);
+}
+
/* Expand a front-end intrinsic call to va_arg(). This takes either one or two
arguments, the signature to which can be either:
CALL_EXPR_ARG (callexp, 1),
CALL_EXPR_ARG (callexp, 2));
+ case INTRINSIC_TOPREC:
+ return expand_intrinsic_toprec (callexp);
+
case INTRINSIC_VA_ARG:
case INTRINSIC_C_VA_ARG:
return expand_intrinsic_vaarg (callexp);
DEF_D_BUILTIN (SQRTF, SQRTF, "sqrt", "core.math", "FNaNbNiNffZf")
DEF_D_BUILTIN (SQRT, SQRT, "sqrt", "core.math", "FNaNbNiNfdZd")
DEF_D_BUILTIN (SQRTL, SQRTL, "sqrt", "core.math", "FNaNbNiNfeZe")
+DEF_D_BUILTIN (TOPRECF, TOPREC, "toPrec", "core.math", "FNaNbNffZI1T")
+DEF_D_BUILTIN (TOPREC, TOPREC, "toPrec", "core.math", "FNaNbNfdZI1T")
+DEF_D_BUILTIN (TOPRECL, TOPREC, "toPrec", "core.math", "FNaNbNfeZI1T")
/* std.math intrinsics. */
static assert(!__traits(compiles, { alias bug18057 = RBNode!int; }));
+/************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=9937
+
+int test9937()
+{
+ import core.math;
+
+ float x = float.max;
+ x *= 2;
+ x = toPrec!float(x);
+ x /= 2;
+ assert(x == float.infinity);
+ return 1;
+}
+
+static assert(test9937());
+// RUNNABLE_PHOBOS_TEST
import std.stdio;
import std.math;
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
import std.stdio;
return 0;
}
-// RUNNABLE_PHOBOS_TEST
#! blah
-
+// RUNNABLE_PHOBOS_TEST
static assert(__LINE__ == 3); // fails as __LINE__ is 2
import std.stdio;
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
-
+// RUNNABLE_PHOBOS_TEST
import core.stdc.stdio;
import std.stdio;
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
import std.stdio;
struct S {
}
}
-// RUNNABLE_PHOBOS_TEST
-
+// RUNNABLE_PHOBOS_TEST
import std.stdio;
/***********************************/
writefln("Success");
}
-// RUNNABLE_PHOBOS_TEST
-
+// RUNNABLE_PHOBOS_TEST
import std.stdio;
/*******************************************************/
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
-
+// RUNNABLE_PHOBOS_TEST
import std.stdio;
template Tuple(A...)
assert(s2.values[1].value == 1); // OK
}
+/************************************************/
+// toPrec
+
+void testToPrec()
+{
+ import core.math;
+
+ enum real ctpir = 0xc.90fdaa22168c235p-2;
+ enum double ctpid = 0x1.921fb54442d18p+1;
+ enum float ctpif = 0x1.921fb6p+1;
+ static assert(toPrec!float(ctpir) == ctpif);
+ static assert(toPrec!double(ctpir) == ctpid);
+ static assert(toPrec!real(ctpir) == ctpir);
+ static assert(toPrec!float(ctpid) == ctpif);
+ static assert(toPrec!double(ctpid) == ctpid);
+ static assert(toPrec!real(ctpid) == ctpid);
+ static assert(toPrec!float(ctpif) == ctpif);
+ static assert(toPrec!double(ctpif) == ctpif);
+ static assert(toPrec!real(ctpif) == ctpif);
+
+ assert(toPrec!float(ctpir) == ctpif);
+ assert(toPrec!double(ctpir) == ctpid);
+ assert(toPrec!real(ctpir) == ctpir);
+ assert(toPrec!float(ctpid) == ctpif);
+ assert(toPrec!double(ctpid) == ctpid);
+ assert(toPrec!real(ctpid) == ctpid);
+ assert(toPrec!float(ctpif) == ctpif);
+ assert(toPrec!double(ctpif) == ctpif);
+ assert(toPrec!real(ctpif) == ctpif);
+
+ static real rtpir = 0xc.90fdaa22168c235p-2;
+ static double rtpid = 0x1.921fb54442d18p+1;
+ static float rtpif = 0x1.921fb6p+1;
+ assert(toPrec!float(rtpir) == rtpif);
+ assert(toPrec!double(rtpir) == rtpid);
+ assert(toPrec!real(rtpir) == rtpir);
+ assert(toPrec!float(rtpid) == rtpif);
+ assert(toPrec!double(rtpid) == rtpid);
+ assert(toPrec!real(rtpid) == rtpid);
+ assert(toPrec!float(rtpif) == rtpif);
+ assert(toPrec!double(rtpif) == rtpif);
+ assert(toPrec!real(rtpif) == rtpif);
+}
+
/************************************************/
int main()
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
import std.random;
void main()
{
double t = 1.0 - uniform(0.0, 1.0);
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
import core.vararg;
import std.stdio;
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
/*
+RUNNABLE_PHOBOS_TEST
REQUIRED_ARGS: -mcpu=native
PERMUTE_ARGS: -O -inline
*/
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
-
+// RUNNABLE_PHOBOS_TEST
module mixin1;
import std.stdio;
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
import std.stdio;
/*********************************************/
writeln("Success");
}
-// RUNNABLE_PHOBOS_TEST
-
+// RUNNABLE_PHOBOS_TEST
import std.stdio;
/***********************************/
writefln("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
import core.stdc.stdio : printf;
}
}
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
import std.stdio;
import core.stdc.stdio;
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
module breaker;
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// REQUIRED_ARGS: -g
import std.string;
void main() { }
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// REQUIRED_ARGS:
extern(C) int printf(const char*, ...);
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS: -unittest -O -release -inline -fPIC -g
extern(C) int printf(const char*, ...);
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// import std.math;
void foo(T)(T[] b)
foo(a);
assert(a[0] == 10000);
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// REQUIRED_ARGS:
// EXTRA_FILES: extra-files/test15.txt
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// REQUIRED_ARGS:
import std.math: poly;
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// REQUIRED_ARGS:
module test;
printf("Success\n");
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// EXTRA_SOURCES: imports/test24a.d imports/test24b.d
// PERMUTE_ARGS:
// REQUIRED_ARGS:
{
string hi = std.string.format("%s", 3);
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// COMPILE_SEPARATELY
// EXTRA_SOURCES: imports/test27a.d
// PERMUTE_ARGS:
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
module test;
import core.vararg;
printf("Success\n");
}
-// RUNNABLE_PHOBOS_TEST
-
+// RUNNABLE_PHOBOS_TEST
module test34;
import std.stdio;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
// REQUIRED_ARGS: -Jrunnable/extra-files
// EXTRA_FILES: extra-files/foo37.txt extra-files/std14198/uni.d
// imports in a subdirectory of the -J path
writefln(import("std14198/uni.d"));
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// REQUIRED_ARGS:
-//
module test42;
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// https://issues.dlang.org/show_bug.cgi?id=5305
import std.math;
int main() { map(&sqrt); return 0; }
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
import std.stdio;
import std.algorithm;
writeln("Success");
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS: -fPIC
/* Test associative arrays */
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
import std.bitmanip;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
module dstress.run.module_01;
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
import std.file;
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
import std.stdio;
std.stdio.writefln("Success");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
// $HeadURL$
writeln(str);
assert(str[start .. start+3]=="(1)");
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
// REQUIRED_ARGS:
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// REQUIRED_ARGS: -dip25
import core.stdc.stdio;
printf("Success\n");
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
import std.stdio;
import std.signals;
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
import std.stdio;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
// EXTRA_FILES: extra-files/teststdio.txt
} while (!feof(fp));
//fclose(fp);
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
import std.algorithm : map;
}
}
-// RUNNABLE_PHOBOS_TEST
-
+// RUNNABLE_PHOBOS_TEST
import core.vararg;
import std.stdio;
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
module traits;
writeln("Success");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
// EXECUTE_ARGS: runnable/wc.d
}
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
// EXECUTE_ARGS: runnable/wc2.d
}
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
// EXECUTE_ARGS: runnable/extra-files/alice30.txt
// EXTRA_FILES: extra-files/alice30.txt
}
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS: -unittest -O -release -inline -fPIC -g
import std.stdio;
printf("Success\n");
return 0;
}
-// RUNNABLE_PHOBOS_TEST
+// RUNNABLE_PHOBOS_TEST
// PERMUTE_ARGS:
import core.memory, std.stdio;
return 0;
}
-// RUNNABLE_PHOBOS_TEST
-c9c209e2c62ce43a2c08ddd61d647730716b2d0f
+e68a5ae36790fa9dc5bab6155bc450eb6bf8c12c
The first line of this file holds the git revision number of the last
merge done from the dlang/druntime repository.
{
asm pure nothrow @nogc {
"cpuid" : "=a" (pnb[0]), "=b" (pnb[1]), "=c" (pnb[ 2]), "=d" (pnb[ 3]) : "a" (0x8000_0002);
- "cpuid" : "=a" (pnb[4]), "=b" (pnb[5]), "=c" (pnb[ 6]), "=d" (pnb[ 7]) : "a" (0x8000_0003);
+ "cpuid" : "=a" (pnb[4]), "=b" (pnb[5]), "=c" (pnb[ 6]), "=d" (pnb[ 7]) : "a" (0x8000_0003);
"cpuid" : "=a" (pnb[8]), "=b" (pnb[9]), "=c" (pnb[10]), "=d" (pnb[11]) : "a" (0x8000_0004);
}
}
const(ubyte)[] toUbyte(T)(const ref T val) if (is(Unqual!T == float) || is(Unqual!T == double) || is(Unqual!T == real) ||
is(Unqual!T == ifloat) || is(Unqual!T == idouble) || is(Unqual!T == ireal))
{
- static const(ubyte)[] reverse_(const(ubyte)[] arr)
- {
- ubyte[] buff = ctfe_alloc(arr.length);
- foreach (k, v; arr)
- {
- buff[$-k-1] = v;
- }
- return buff;
- }
if (__ctfe)
{
- auto parsed = parse(val);
-
- ulong mantissa = parsed.mantissa;
- uint exp = parsed.exponent;
- uint sign = parsed.sign;
-
- ubyte[] buff = ctfe_alloc(T.sizeof);
- size_t off_bytes = 0;
- size_t off_bits = 0;
- // Quadruples won't fit in one ulong, so check for that.
- enum mantissaMax = FloatTraits!T.MANTISSA < ulong.sizeof*8 ?
- FloatTraits!T.MANTISSA : ulong.sizeof*8;
-
- for (; off_bytes < mantissaMax/8; ++off_bytes)
+ static if (T.mant_dig == float.mant_dig || T.mant_dig == double.mant_dig)
{
- buff[off_bytes] = cast(ubyte)mantissa;
- mantissa >>= 8;
+ static if (is(T : ireal)) // https://issues.dlang.org/show_bug.cgi?id=19932
+ const f = val.im;
+ else
+ alias f = val;
+ static if (T.sizeof == uint.sizeof)
+ uint bits = *cast(const uint*) &f;
+ else static if (T.sizeof == ulong.sizeof)
+ ulong bits = *cast(const ulong*) &f;
+ ubyte[] result = ctfe_alloc(T.sizeof);
+ version (BigEndian)
+ {
+ foreach_reverse (ref b; result)
+ {
+ b = cast(ubyte) bits;
+ bits >>= 8;
+ }
+ }
+ else
+ {
+ foreach (ref b; result)
+ {
+ b = cast(ubyte) bits;
+ bits >>= 8;
+ }
+ }
+ return result;
}
-
- static if (floatFormat!T == FloatFormat.Quadruple)
+ else static if (floatFormat!T == FloatFormat.DoubleDouble)
{
- ulong mantissa2 = parsed.mantissa2;
- off_bytes--; // go back one, since mantissa only stored data in 56
- // bits, ie 7 bytes
- for (; off_bytes < FloatTraits!T.MANTISSA/8; ++off_bytes)
+ // Parse DoubleDoubles as a pair of doubles.
+ // The layout of the type is:
+ //
+ // [1| 7 | 56 ][ 8 | 56 ]
+ // [S| Exp | Fraction (hi) ][ Unused | Fraction (low) ]
+ //
+ // We can get the least significant bits by subtracting the IEEE
+ // double precision portion from the real value.
+
+ import core.math : toPrec;
+
+ ubyte[] buff = ctfe_alloc(T.sizeof);
+ enum msbSize = double.sizeof;
+
+ double hi = toPrec!double(val);
+ buff[0 .. msbSize] = toUbyte(hi)[];
+
+ if (val is cast(T)0.0 || val is cast(T)-0.0 ||
+ val is T.nan || val is -T.nan ||
+ val is T.infinity || val > T.max ||
+ val is -T.infinity || val < -T.max)
+ {
+ // Zero, NaN, and Inf are all representable as doubles, so the
+ // least significant part can be 0.0.
+ buff[msbSize .. $] = 0;
+ }
+ else
{
- buff[off_bytes] = cast(ubyte)mantissa2;
- mantissa2 >>= 8;
+ double low = toPrec!double(val - hi);
+ buff[msbSize .. $] = toUbyte(low)[];
}
+
+ // Arrays don't index differently between little and big-endian targets.
+ return buff;
}
else
{
- off_bits = FloatTraits!T.MANTISSA%8;
- buff[off_bytes] = cast(ubyte)mantissa;
- }
+ auto parsed = parse(val);
- for (size_t i=0; i<FloatTraits!T.EXPONENT/8; ++i)
- {
- ubyte cur_exp = cast(ubyte)exp;
- exp >>= 8;
- buff[off_bytes] |= (cur_exp << off_bits);
- ++off_bytes;
- buff[off_bytes] |= cur_exp >> 8 - off_bits;
- }
+ ulong mantissa = parsed.mantissa;
+ uint exp = parsed.exponent;
+ uint sign = parsed.sign;
+ ubyte[] buff = ctfe_alloc(T.sizeof);
+ size_t off_bytes = 0;
+ size_t off_bits = 0;
+ // Quadruples won't fit in one ulong, so check for that.
+ enum mantissaMax = FloatTraits!T.MANTISSA < ulong.sizeof*8 ?
+ FloatTraits!T.MANTISSA : ulong.sizeof*8;
- exp <<= 8 - FloatTraits!T.EXPONENT%8 - 1;
- buff[off_bytes] |= exp;
- sign <<= 7;
- buff[off_bytes] |= sign;
+ for (; off_bytes < mantissaMax/8; ++off_bytes)
+ {
+ buff[off_bytes] = cast(ubyte)mantissa;
+ mantissa >>= 8;
+ }
- version (LittleEndian)
- {
+ static if (floatFormat!T == FloatFormat.Quadruple)
+ {
+ ulong mantissa2 = parsed.mantissa2;
+ off_bytes--; // go back one, since mantissa only stored data in 56
+ // bits, ie 7 bytes
+ for (; off_bytes < FloatTraits!T.MANTISSA/8; ++off_bytes)
+ {
+ buff[off_bytes] = cast(ubyte)mantissa2;
+ mantissa2 >>= 8;
+ }
+ }
+ else
+ {
+ off_bits = FloatTraits!T.MANTISSA%8;
+ buff[off_bytes] = cast(ubyte)mantissa;
+ }
+
+ for (size_t i=0; i<FloatTraits!T.EXPONENT/8; ++i)
+ {
+ ubyte cur_exp = cast(ubyte)exp;
+ exp >>= 8;
+ buff[off_bytes] |= (cur_exp << off_bits);
+ ++off_bytes;
+ buff[off_bytes] |= cur_exp >> 8 - off_bits;
+ }
+
+
+ exp <<= 8 - FloatTraits!T.EXPONENT%8 - 1;
+ buff[off_bytes] |= exp;
+ sign <<= 7;
+ buff[off_bytes] |= sign;
+
+ version (BigEndian)
+ {
+ for (size_t left = 0, right = buff.length - 1; left < right; left++, right--)
+ {
+ const swap = buff[left];
+ buff[left] = buff[right];
+ buff[right] = swap;
+ }
+ }
return buff;
}
- else
- {
- return reverse_(buff);
- }
}
else
{
}
}
+/*************************************
+ * Round argument to a specific precision.
+ *
+ * D language types specify a minimum precision, not a maximum. The
+ * `toPrec()` function forces rounding of the argument `f` to the
+ * precision of the specified floating point type `T`.
+ *
+ * Params:
+ * T = precision type to round to
+ * f = value to convert
+ * Returns:
+ * f in precision of type `T`
+ */
+@safe pure nothrow
+T toPrec(T:float)(float f) { pragma(inline, false); return f; }
+/// ditto
+@safe pure nothrow
+T toPrec(T:float)(double f) { pragma(inline, false); return cast(T) f; }
+/// ditto
+@safe pure nothrow
+T toPrec(T:float)(real f) { pragma(inline, false); return cast(T) f; }
+/// ditto
+@safe pure nothrow
+T toPrec(T:double)(float f) { pragma(inline, false); return f; }
+/// ditto
+@safe pure nothrow
+T toPrec(T:double)(double f) { pragma(inline, false); return f; }
+/// ditto
+@safe pure nothrow
+T toPrec(T:double)(real f) { pragma(inline, false); return cast(T) f; }
+/// ditto
+@safe pure nothrow
+T toPrec(T:real)(float f) { pragma(inline, false); return f; }
+/// ditto
+@safe pure nothrow
+T toPrec(T:real)(double f) { pragma(inline, false); return f; }
+/// ditto
+@safe pure nothrow
+T toPrec(T:real)(real f) { pragma(inline, false); return f; }
+
+@safe unittest
+{
+ static float f = 1.1f;
+ static double d = 1.1;
+ static real r = 1.1L;
+ f = toPrec!float(f + f);
+ f = toPrec!float(d + d);
+ f = toPrec!float(r + r);
+ d = toPrec!double(f + f);
+ d = toPrec!double(d + d);
+ d = toPrec!double(r + r);
+ r = toPrec!real(f + f);
+ r = toPrec!real(d + d);
+ r = toPrec!real(r + r);
+
+ /+ Uncomment these once compiler support has been added.
+ enum real PIR = 0xc.90fdaa22168c235p-2;
+ enum double PID = 0x1.921fb54442d18p+1;
+ enum float PIF = 0x1.921fb6p+1;
+
+ assert(toPrec!float(PIR) == PIF);
+ assert(toPrec!double(PIR) == PID);
+ assert(toPrec!real(PIR) == PIR);
+ assert(toPrec!float(PID) == PIF);
+ assert(toPrec!double(PID) == PID);
+ assert(toPrec!real(PID) == PID);
+ assert(toPrec!float(PIF) == PIF);
+ assert(toPrec!double(PIF) == PIF);
+ assert(toPrec!real(PIF) == PIF);
+ +/
+}
* Authors: $(WEB digitalmars.com, Walter Bright),
*/
-/* NOTE: This file has been patched from the original DMD distribution to
- * work with the GDC compiler.
- */
module core.simd;
pure:
/* Handy aliases
*/
static if (is(Vector!(void[8]))) alias Vector!(void[8]) void8; ///
+static if (is(Vector!(double[1]))) alias Vector!(double[1]) double1; ///
static if (is(Vector!(float[2]))) alias Vector!(float[2]) float2; ///
static if (is(Vector!(byte[8]))) alias Vector!(byte[8]) byte8; ///
static if (is(Vector!(ubyte[8]))) alias Vector!(ubyte[8]) ubyte8; ///
static if (is(Vector!(ushort[4]))) alias Vector!(ushort[4]) ushort4; ///
static if (is(Vector!(int[2]))) alias Vector!(int[2]) int2; ///
static if (is(Vector!(uint[2]))) alias Vector!(uint[2]) uint2; ///
+static if (is(Vector!(long[1]))) alias Vector!(long[1]) long1; ///
+static if (is(Vector!(ulong[1]))) alias Vector!(ulong[1]) ulong1; ///
static if (is(Vector!(void[16]))) alias Vector!(void[16]) void16; ///
static if (is(Vector!(double[2]))) alias Vector!(double[2]) double2; ///