diff --git a/std/datetime/timezone.d b/std/datetime/timezone.d index 80604f50a63..ff5c1f7c463 100644 --- a/std/datetime/timezone.d +++ b/std/datetime/timezone.d @@ -334,6 +334,7 @@ public: else version(DragonFlyBSD) enum utcZone = "UTC"; else version(linux) enum utcZone = "UTC"; else version(OSX) enum utcZone = "UTC"; + else version(Solaris) enum utcZone = "UTC"; else static assert(0, "The location of the UTC timezone file on this Posix platform must be set."); auto tzs = [testTZ("America/Los_Angeles", "PST", "PDT", dur!"hours"(-8), dur!"hours"(1)), @@ -2007,6 +2008,14 @@ public: // Android concatenates all time zone data into a single file and stores it here. enum defaultTZDatabaseDir = "/system/usr/share/zoneinfo/"; } + else version(Solaris) + { + /++ + The default directory where the TZ Database files are. It's empty + for Windows, since Windows doesn't have them. + +/ + enum defaultTZDatabaseDir = "/usr/share/lib/zoneinfo/"; + } else version(Posix) { /++ diff --git a/std/digest/murmurhash.d b/std/digest/murmurhash.d index 4d23aebca9b..1fffc792510 100644 --- a/std/digest/murmurhash.d +++ b/std/digest/murmurhash.d @@ -38,6 +38,11 @@ $(BR) $(LINK2 https://en.wikipedia.org/wiki/MurmurHash, Wikipedia) */ module std.digest.murmurhash; +version (X86) + version = HaveUnalignedLoads; +else version (X86_64) + version = HaveUnalignedLoads; + /// @safe unittest { @@ -500,28 +505,74 @@ struct MurmurHash3(uint size /* 32 or 128 */ , uint opt = size_t.sizeof == 8 ? 6 // Buffer should never be full while entering this function. assert(bufferSize < Element.sizeof); - // Check if we have some leftover data in the buffer. Then fill the first block buffer. + // Check if we don't fill up a whole block buffer. if (bufferSize + data.length < Element.sizeof) { buffer.data[bufferSize .. bufferSize + data.length] = data[]; bufferSize += data.length; return; } - const bufferLeeway = Element.sizeof - bufferSize; - assert(bufferLeeway <= Element.sizeof); - buffer.data[bufferSize .. $] = data[0 .. bufferLeeway]; - putElement(buffer.block); - data = data[bufferLeeway .. $]; + + // Check if we have some leftover data in the buffer. Then fill the first block buffer. + if (bufferSize != 0) + { + const bufferLeeway = Element.sizeof - bufferSize; + buffer.data[bufferSize .. $] = data[0 .. bufferLeeway]; + putElement(buffer.block); + element_count += Element.sizeof; + data = data[bufferLeeway .. $]; + } // Do main work: process chunks of `Element.sizeof` bytes. const numElements = data.length / Element.sizeof; const remainderStart = numElements * Element.sizeof; - foreach (ref const Element block; cast(const(Element[]))(data[0 .. remainderStart])) + version (HaveUnalignedLoads) { - putElement(block); + foreach (ref const Element block; cast(const(Element[])) data[0 .. remainderStart]) + { + putElement(block); + } } - // +1 for bufferLeeway Element. - element_count += (numElements + 1) * Element.sizeof; + else + { + void processChunks(T)() @trusted + { + alias TChunk = T[Element.sizeof / T.sizeof]; + foreach (ref const chunk; cast(const(TChunk[])) data[0 .. remainderStart]) + { + static if (T.alignof >= Element.alignof) + { + putElement(*cast(const(Element)*) chunk.ptr); + } + else + { + Element[1] alignedCopy = void; + (cast(T[]) alignedCopy)[] = chunk[]; + putElement(alignedCopy[0]); + } + } + } + + const startAddress = cast(size_t) data.ptr; + static if (size >= 64) + { + if ((startAddress & 7) == 0) + { + processChunks!ulong(); + goto L_end; + } + } + static assert(size >= 32); + if ((startAddress & 3) == 0) + processChunks!uint(); + else if ((startAddress & 1) == 0) + processChunks!ushort(); + else + processChunks!ubyte(); + +L_end: + } + element_count += numElements * Element.sizeof; data = data[remainderStart .. $]; // Now add remaining data to buffer. @@ -743,10 +794,13 @@ version (unittest) // Pushing unaligned data and making sure the result is still coherent. void testUnalignedHash(H)() { - immutable ubyte[1025] data = 0xAC; - immutable alignedHash = digest!H(data[0 .. $ - 1]); // 0 .. 1023 - immutable unalignedHash = digest!H(data[1 .. $]); // 1 .. 1024 - assert(alignedHash == unalignedHash); + immutable ubyte[1028] data = 0xAC; + immutable alignedHash = digest!H(data[0 .. 1024]); + foreach (i; 1 .. 5) + { + immutable unalignedHash = digest!H(data[i .. 1024 + i]); + assert(alignedHash == unalignedHash); + } } testUnalignedHash!(MurmurHash3!32)(); diff --git a/std/math.d b/std/math.d index c5fe28f2968..5ee82a10fa6 100644 --- a/std/math.d +++ b/std/math.d @@ -152,6 +152,8 @@ version (X86) version = X86_Any; version (X86_64) version = X86_Any; version (PPC) version = PPC_Any; version (PPC64) version = PPC_Any; +version (MIPS) version = MIPS_Any; +version (MIPS64) version = MIPS_Any; version(D_InlineAsm_X86) { @@ -169,7 +171,7 @@ version (StaticallyHaveSSE) { private enum bool haveSSE = true; } -else +else version (X86) { static import core.cpuid; private alias haveSSE = core.cpuid.sse; @@ -881,8 +883,10 @@ Lret: {} } else { + enum realFormat = floatTraits!real.realFormat; + // Coefficients for tan(x) and PI/4 split into three parts. - static if (floatTraits!real.realFormat == RealFormat.ieeeQuadruple) + static if (realFormat == RealFormat.ieeeQuadruple) { static immutable real[6] P = [ 2.883414728874239697964612246732416606301E10L, @@ -946,9 +950,10 @@ Lret: {} // Compute x mod PI/4. real y = floor(x / PI_4); // Strip high bits of integer part. - real z = ldexp(y, -4); - // Compute y - 16 * (y / 16). - z = y - ldexp(floor(z), 4); + enum numHighBits = (realFormat == RealFormat.ieeeDouble ? 3 : 4); + real z = ldexp(y, -numHighBits); + // Compute y - 2^numHighBits * (y / 2^numHighBits). + z = y - ldexp(floor(z), numHighBits); // Integer and fraction part modulo one octant. int j = cast(int)(z); @@ -963,7 +968,8 @@ Lret: {} z = ((x - y * P1) - y * P2) - y * P3; const real zz = z * z; - if (zz > 1.0e-20L) + enum zzThreshold = (realFormat == RealFormat.ieeeDouble ? 1.0e-14L : 1.0e-20L); + if (zz > zzThreshold) y = z + z * (zz * poly(zz, P) / poly(zz, Q)); else y = z; @@ -4880,6 +4886,18 @@ version(X86_Any) { version = IeeeFlagsSupport; } +else version(PPC_Any) +{ + version = IeeeFlagsSupport; +} +else version(MIPS_Any) +{ + version = IeeeFlagsSupport; +} +else version(AArch64) +{ + version = IeeeFlagsSupport; +} else version(ARM) { version = IeeeFlagsSupport; @@ -5024,6 +5042,21 @@ struct FloatingPointControl allExceptions, /// ditto } } + else version(AArch64) + { + enum : ExceptionMask + { + inexactException = 0x1000, + underflowException = 0x0800, + overflowException = 0x0400, + divByZeroException = 0x0200, + invalidException = 0x0100, + severeExceptions = overflowException | divByZeroException + | invalidException, + allExceptions = severeExceptions | underflowException + | inexactException, + } + } else version(ARM) { enum : ExceptionMask @@ -5055,6 +5088,21 @@ struct FloatingPointControl | inexactException, } } + else version(MIPS_Any) + { + enum : ExceptionMask + { + inexactException = 0x0800, + divByZeroException = 0x0400, + overflowException = 0x0200, + underflowException = 0x0100, + invalidException = 0x0080, + severeExceptions = overflowException | divByZeroException + | invalidException, + allExceptions = severeExceptions | underflowException + | inexactException, + } + } else version (X86_Any) { enum : ExceptionMask @@ -5082,6 +5130,18 @@ public: return true; else version(PPC_Any) return true; + else version(MIPS_Any) + return true; + else version(AArch64) + { + auto oldState = getControlState(); + // If exceptions are not supported, we set the bit but read it back as zero + // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/aarch64/fpu/feenablxcpth.c + setControlState(oldState | (divByZeroException & allExceptions)); + immutable result = (getControlState() & allExceptions) != 0; + setControlState(oldState); + return result; + } else version(ARM) { auto oldState = getControlState(); @@ -5141,7 +5201,11 @@ private: bool initialized = false; - version(ARM) + version(AArch64) + { + alias ControlState = uint; + } + else version(ARM) { alias ControlState = uint; } @@ -5149,6 +5213,10 @@ private: { alias ControlState = uint; } + else version(MIPS_Any) + { + alias ControlState = uint; + } else version (X86_Any) { alias ControlState = ushort; @@ -7687,9 +7755,12 @@ bool approxEqual(T, U)(T lhs, U rhs) // Verify correct behavior for large inputs assert(!isNaN(tan(0x1p63))); - assert(!isNaN(tan(0x1p300L))); assert(!isNaN(tan(-0x1p63))); - assert(!isNaN(tan(-0x1p300L))); + static if (real.mant_dig >= 64) + { + assert(!isNaN(tan(0x1p300L))); + assert(!isNaN(tan(-0x1p300L))); + } } @safe pure nothrow unittest