aboutsummaryrefslogtreecommitdiff
path: root/libphobos/src/std
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2023-03-05 01:47:19 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2023-03-16 17:29:57 +0100
commit8da8c7d337123b28fdeb539a283d00732118712e (patch)
tree74096a23b9e2f64a7e25ec1e8d4d3b1d8934842e /libphobos/src/std
parentc5e2c3dd6afcf9b152df72b30e205b0180c0afd5 (diff)
downloadgcc-8da8c7d337123b28fdeb539a283d00732118712e.zip
gcc-8da8c7d337123b28fdeb539a283d00732118712e.tar.gz
gcc-8da8c7d337123b28fdeb539a283d00732118712e.tar.bz2
d: Merge upstream dmd, druntime 4ca4140e58, phobos 454dff14d.
D front-end changes: - Import dmd v2.103.0-beta.1. - Using `alias this' for classes has been deprecated. - The feature `-fpreview=dip25` is now enabled by default. - The compile-time traits `isVirtualFunction' and `getVirtualFunctions' have been deprecated. D runtime changes: - Import druntime v2.103.0-beta.1. Phobos changes: - Import phobos v2.103.0-beta.1. - Updated unicode grapheme walking updated to conform to Unicode version 15. - Improved friendliness of error messages when instantiating `std.algorithm.iteration.joiner' and `std.algorithm.sorting.sort' with wrong inputs. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 4ca4140e58. * dmd/VERSION: Bump version to v2.103.0-beta.1. * Make-lang.in (D_FRONTEND_OBJS): Add d/errorsink.o. * d-ctfloat.cc (CTFloat::sprint): Update signature for new front-end interface. * d-frontend.cc (getTypeInfoType): Likewise. * d-lang.cc (d_handle_option): Remove handling of -fpreview=dip25 and -frevert=dip25. (d_post_options): Remove enabling of sealed references language feature when scoped pointers is enabled. * d-tree.h (create_typeinfo): Update signature. * decl.cc (DeclVisitor::finish_vtable): Update for new front-end interface. (DeclVisitor::visit (VarDeclaration *)): Likewise. (DeclVisitor::visit (FuncDeclaration *)): Check skipCodegen to see if front-end explicitly requested not to generate code. * expr.cc (ExprVisitor::visit (NewExp *)): Update for new front-end interface. * lang.opt (fpreview=dip25): Remove. (frevert=dip25): Remove. * modules.cc (layout_moduleinfo_fields): Update for new front-end interface. (layout_moduleinfo): Likewise. * runtime.def (NEWCLASS): Remove. * toir.cc (IRVisitor::visit (IfStatement *)): Don't generate IR for if statement list when condition is `__ctfe'. * typeinfo.cc (create_typeinfo): Add generate parameter. * types.cc (layout_aggregate_members): Update for new front-end interface. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 4ca4140e58. * libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add core/factory.d. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos 454dff14d. * testsuite/libphobos.hash/test_hash.d: Update test. * testsuite/libphobos.shared/finalize.d: Update test. * libdruntime/core/factory.d: New file. gcc/testsuite/ChangeLog: * gdc.dg/torture/simd23084.d: New test. * gdc.dg/torture/simd23085.d: New test. * gdc.dg/torture/simd23218.d: New test.
Diffstat (limited to 'libphobos/src/std')
-rw-r--r--libphobos/src/std/algorithm/iteration.d20
-rw-r--r--libphobos/src/std/algorithm/package.d1
-rw-r--r--libphobos/src/std/algorithm/sorting.d79
-rw-r--r--libphobos/src/std/array.d18
-rw-r--r--libphobos/src/std/bitmanip.d25
-rw-r--r--libphobos/src/std/concurrency.d155
-rw-r--r--libphobos/src/std/container/binaryheap.d40
-rw-r--r--libphobos/src/std/exception.d23
-rw-r--r--libphobos/src/std/file.d37
-rw-r--r--libphobos/src/std/format/internal/write.d176
-rw-r--r--libphobos/src/std/format/read.d31
-rw-r--r--libphobos/src/std/getopt.d2
-rw-r--r--libphobos/src/std/internal/unicode_grapheme.d28
-rw-r--r--libphobos/src/std/math/exponential.d495
-rw-r--r--libphobos/src/std/net/curl.d12
-rw-r--r--libphobos/src/std/process.d60
-rw-r--r--libphobos/src/std/range/primitives.d14
-rw-r--r--libphobos/src/std/regex/internal/parser.d14
-rw-r--r--libphobos/src/std/socket.d10
-rw-r--r--libphobos/src/std/stdio.d5
-rw-r--r--libphobos/src/std/traits.d54
-rw-r--r--libphobos/src/std/typecons.d102
-rw-r--r--libphobos/src/std/uni/package.d367
-rw-r--r--libphobos/src/std/utf.d2
24 files changed, 1250 insertions, 520 deletions
diff --git a/libphobos/src/std/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d
index 967d2a6..8236076 100644
--- a/libphobos/src/std/algorithm/iteration.d
+++ b/libphobos/src/std/algorithm/iteration.d
@@ -2969,10 +2969,24 @@ iterated from the back to the front, the separator will still be consumed from
front to back, even if it is a bidirectional range too.
*/
auto joiner(RoR, Separator)(RoR r, Separator sep)
-if (isInputRange!RoR && isInputRange!(ElementType!RoR)
- && isForwardRange!Separator
- && is(ElementType!Separator : ElementType!(ElementType!RoR)))
{
+ static assert(isInputRange!RoR, "The type of RoR '", RoR.stringof
+ , " must be an InputRange (isInputRange!", RoR.stringof, ").");
+ static assert(isInputRange!(ElementType!RoR), "The ElementyType of RoR '"
+ , ElementType!(RoR).stringof, "' must be an InputRange "
+ , "(isInputRange!(ElementType!(", RoR.stringof , "))).");
+ static assert(isForwardRange!Separator, "The type of the Seperator '"
+ , Seperator.stringof, "' must be a ForwardRange (isForwardRange!("
+ , Seperator.stringof, ")).");
+ static assert(is(ElementType!Separator : ElementType!(ElementType!RoR))
+ , "The type of the elements of the separator range does not match "
+ , "the type of the elements that are joined. Separator type '"
+ , ElementType!(Separator).stringof, "' is not implicitly"
+ , "convertible to range element type '"
+ , ElementType!(ElementType!RoR).stringof, "' (is(ElementType!"
+ , Separator.stringof, " : ElementType!(ElementType!", RoR.stringof
+ , "))).");
+
static struct Result
{
private RoR _items;
diff --git a/libphobos/src/std/algorithm/package.d b/libphobos/src/std/algorithm/package.d
index 6aacd51..71bd1d9 100644
--- a/libphobos/src/std/algorithm/package.d
+++ b/libphobos/src/std/algorithm/package.d
@@ -103,6 +103,7 @@ $(TR
$(SUBREF sorting, multiSort)
$(SUBREF sorting, nextEvenPermutation)
$(SUBREF sorting, nextPermutation)
+ $(SUBREF sorting, nthPermutation)
$(SUBREF sorting, partialSort)
$(SUBREF sorting, partition)
$(SUBREF sorting, partition3)
diff --git a/libphobos/src/std/algorithm/sorting.d b/libphobos/src/std/algorithm/sorting.d
index ddb80b8..c5b085d 100644
--- a/libphobos/src/std/algorithm/sorting.d
+++ b/libphobos/src/std/algorithm/sorting.d
@@ -1922,14 +1922,8 @@ See_Also:
$(REF binaryFun, std,functional)
*/
SortedRange!(Range, less)
-sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable,
- Range)(Range r)
-if (((ss == SwapStrategy.unstable && (hasSwappableElements!Range ||
- hasAssignableElements!Range)) ||
- (ss != SwapStrategy.unstable && hasAssignableElements!Range)) &&
- isRandomAccessRange!Range &&
- hasSlicing!Range &&
- hasLength!Range)
+sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)
+(Range r)
/+ Unstable sorting uses the quicksort algorithm, which uses swapAt,
which either uses swap(...), requiring swappable elements, or just
swaps using assignment.
@@ -1937,21 +1931,46 @@ if (((ss == SwapStrategy.unstable && (hasSwappableElements!Range ||
requiring assignable elements. +/
{
import std.range : assumeSorted;
- alias lessFun = binaryFun!(less);
- alias LessRet = typeof(lessFun(r.front, r.front)); // instantiate lessFun
- static if (is(LessRet == bool))
+ static if (ss == SwapStrategy.unstable)
{
- static if (ss == SwapStrategy.unstable)
- quickSortImpl!(lessFun)(r, r.length);
- else //use Tim Sort for semistable & stable
- TimSortImpl!(lessFun, Range).sort(r, null);
-
- assert(isSorted!lessFun(r), "Failed to sort range of type " ~ Range.stringof);
+ static assert(hasSwappableElements!Range || hasAssignableElements!Range,
+ "When using SwapStrategy.unstable, the passed Range '"
+ ~ Range.stringof ~ "' must"
+ ~ " either fulfill hasSwappableElements, or"
+ ~ " hasAssignableElements, both were not the case");
}
else
{
- static assert(false, "Invalid predicate passed to sort: " ~ less.stringof);
+ static assert(hasAssignableElements!Range, "When using a SwapStrategy"
+ ~ " != unstable, the"
+ ~ " passed Range '" ~ Range.stringof ~ "' must fulfill"
+ ~ " hasAssignableElements, which it did not");
}
+
+ static assert(isRandomAccessRange!Range, "The passed Range '"
+ ~ Range.stringof ~ "' must be a Random AccessRange "
+ ~ "(isRandomAccessRange)");
+
+ static assert(hasSlicing!Range, "The passed Range '"
+ ~ Range.stringof ~ "' must allow Slicing (hasSlicing)");
+
+ static assert(hasLength!Range, "The passed Range '"
+ ~ Range.stringof ~ "' must have a length (hasLength)");
+
+ alias lessFun = binaryFun!(less);
+ alias LessRet = typeof(lessFun(r.front, r.front)); // instantiate lessFun
+
+ static assert(is(LessRet == bool), "The return type of the template"
+ ~ " argument 'less' when used with the binaryFun!less template"
+ ~ " must be a bool. This is not the case, the returned type is '"
+ ~ LessRet.stringof ~ "'");
+
+ static if (ss == SwapStrategy.unstable)
+ quickSortImpl!(lessFun)(r, r.length);
+ else //use Tim Sort for semistable & stable
+ TimSortImpl!(lessFun, Range).sort(r, null);
+
+ assert(isSorted!lessFun(r), "Failed to sort range of type " ~ Range.stringof);
return assumeSorted!less(r);
}
@@ -2599,8 +2618,16 @@ private template TimSortImpl(alias pred, R)
//Test for overflow
if (newSize < minCapacity) newSize = minCapacity;
- if (__ctfe) temp.length = newSize;
- else temp = () @trusted { return uninitializedArray!(T[])(newSize); }();
+ // can't use `temp.length` if there's no default constructor
+ static if (__traits(compiles, { T defaultConstructed; cast(void) defaultConstructed; }))
+ {
+ if (__ctfe) temp.length = newSize;
+ else temp = () @trusted { return uninitializedArray!(T[])(newSize); }();
+ }
+ else
+ {
+ temp = () @trusted { return uninitializedArray!(T[])(newSize); }();
+ }
}
return temp;
}
@@ -3037,6 +3064,18 @@ private template TimSortImpl(alias pred, R)
sort!(cmp, SwapStrategy.stable)(makeArray(minMerge + 5));
}
+// https://issues.dlang.org/show_bug.cgi?id=23668
+@safe unittest
+{
+ static struct S
+ {
+ int opCmp(const S) const { return 1; }
+ @disable this();
+ }
+ S[] array;
+ array.sort!("a < b", SwapStrategy.stable);
+}
+
// schwartzSort
/**
Alternative sorting method that should be used when comparing keys involves an
diff --git a/libphobos/src/std/array.d b/libphobos/src/std/array.d
index daa103a..4584dcc 100644
--- a/libphobos/src/std/array.d
+++ b/libphobos/src/std/array.d
@@ -170,7 +170,7 @@ if (isIterable!Range && !isAutodecodableString!Range && !isInfinite!Range)
/// ditto
ForeachType!(typeof((*Range).init))[] array(Range)(Range r)
-if (is(Range : U*, U) && isIterable!U && !isAutodecodableString!Range && !isInfinite!Range)
+if (is(Range == U*, U) && isIterable!U && !isAutodecodableString!Range && !isInfinite!Range)
{
return array(*r);
}
@@ -2294,22 +2294,6 @@ if (isInputRange!RoR &&
}
}
-// https://issues.dlang.org/show_bug.cgi?id=10895
-@safe unittest
-{
- static class A
- {
- string name;
- alias name this;
- this(string name) { this.name = name; }
- }
- auto a = [new A(`foo`)];
- assert(a[0].length == 3);
- auto temp = join(a, " ");
- assert(a[0].length == 3);
- assert(temp.length == 3);
-}
-
// https://issues.dlang.org/show_bug.cgi?id=14230
@safe unittest
{
diff --git a/libphobos/src/std/bitmanip.d b/libphobos/src/std/bitmanip.d
index 559f8da..b84a676 100644
--- a/libphobos/src/std/bitmanip.d
+++ b/libphobos/src/std/bitmanip.d
@@ -89,22 +89,21 @@ private template createAccessors(
}
else
{
- enum ulong
- maskAllElse = ((~0uL) >> (64 - len)) << offset,
- signBitCheck = 1uL << (len - 1);
+ enum ulong maskAllElse = ((~0uL) >> (64 - len)) << offset;
+ enum TSize = 8 * T.sizeof;
+ enum SignShift = TSize - len;
static if (T.min < 0)
{
enum long minVal = -(1uL << (len - 1));
enum ulong maxVal = (1uL << (len - 1)) - 1;
- alias UT = Unsigned!(T);
- enum UT extendSign = cast(UT)~((~0uL) >> (64 - len));
+ enum RightShiftOp = ">>=";
}
else
{
enum ulong minVal = 0;
enum ulong maxVal = (~0uL) >> (64 - len);
- enum extendSign = 0;
+ enum RightShiftOp = ">>>=";
}
static if (is(T == bool))
@@ -121,15 +120,11 @@ private template createAccessors(
else
{
// getter
- enum createAccessors = "@property "~T.stringof~" "~name~"() @safe pure nothrow @nogc const { auto result = "
- ~"("~store~" & "
- ~ myToString(maskAllElse) ~ ") >>"
- ~ myToString(offset) ~ ";"
- ~ (T.min < 0
- ? "if (result >= " ~ myToString(signBitCheck)
- ~ ") result |= " ~ myToString(extendSign) ~ ";"
- : "")
- ~ " return cast("~T.stringof~") result;}\n"
+ enum createAccessors = "@property "~T.stringof~" "~name~"() @safe pure nothrow @nogc const {"
+ ~ "auto result = cast("~T.stringof~") (" ~ store ~ " >>" ~ myToString(offset) ~ ");"
+ ~ "result <<= " ~ myToString(SignShift) ~ ";"
+ ~ "result " ~ RightShiftOp ~ myToString(SignShift) ~ ";"
+ ~ " return result;}\n"
// setter
~"@property void "~name~"("~T.stringof~" v) @safe pure nothrow @nogc { "
~"assert(v >= "~name~`_min, "Value is smaller than the minimum value of bitfield '`~name~`'"); `
diff --git a/libphobos/src/std/concurrency.d b/libphobos/src/std/concurrency.d
index 323926a..7fe52ba 100644
--- a/libphobos/src/std/concurrency.d
+++ b/libphobos/src/std/concurrency.d
@@ -46,7 +46,7 @@
*
* This is a low-level messaging API upon which more structured or restrictive
* APIs may be built. The general idea is that every messageable entity is
- * represented by a common handle type called a Tid, which allows messages to
+ * represented by a common handle type called a `Tid`, which allows messages to
* be sent to logical threads that are executing in both the current process
* and in external processes using the same interface. This is an important
* aspect of scalability because it allows the components of a program to be
@@ -55,11 +55,11 @@
*
* A logical thread is an execution context that has its own stack and which
* runs asynchronously to other logical threads. These may be preemptively
- * scheduled kernel threads, fibers (cooperative user-space threads), or some
- * other concept with similar behavior.
+ * scheduled kernel threads, $(MREF_ALTTEXT fibers, core, thread, fiber)
+ * (cooperative user-space threads), or some other concept with similar behavior.
*
* The type of concurrency used when logical threads are created is determined
- * by the Scheduler selected at initialization time. The default behavior is
+ * by the $(LREF Scheduler) selected at initialization time. The default behavior is
* currently to create a new kernel thread per call to spawn, but other
* schedulers are available that multiplex fibers across the main thread or
* use some combination of the two approaches.
@@ -274,7 +274,7 @@ static ~this()
// Exceptions
/**
- * Thrown on calls to `receiveOnly` if a message other than the type
+ * Thrown on calls to $(LREF receiveOnly) if a message other than the type
* the receiving thread expected is sent.
*/
class MessageMismatch : Exception
@@ -287,7 +287,7 @@ class MessageMismatch : Exception
}
/**
- * Thrown on calls to `receive` if the thread that spawned the receiving
+ * Thrown on calls to $(LREF receive) if the thread that spawned the receiving
* thread has terminated and no more messages exist.
*/
class OwnerTerminated : Exception
@@ -354,7 +354,7 @@ class MailboxFull : Exception
}
/**
- * Thrown when a Tid is missing, e.g. when `ownerTid` doesn't
+ * Thrown when a `Tid` is missing, e.g. when $(LREF ownerTid) doesn't
* find an owner thread.
*/
class TidMissingException : Exception
@@ -384,11 +384,11 @@ private:
public:
/**
- * Generate a convenient string for identifying this Tid. This is only
- * useful to see if Tid's that are currently executing are the same or
+ * Generate a convenient string for identifying this `Tid`. This is only
+ * useful to see if `Tid`'s that are currently executing are the same or
* different, e.g. for logging and debugging. It is potentially possible
- * that a Tid executed in the future will have the same toString() output
- * as another Tid that has already terminated.
+ * that a `Tid` executed in the future will have the same `toString()` output
+ * as another `Tid` that has already terminated.
*/
void toString(W)(ref W w) const
{
@@ -420,7 +420,7 @@ public:
}
/**
- * Returns: The $(LREF Tid) of the caller's thread.
+ * Returns: The `Tid` of the caller's thread.
*/
@property Tid thisTid() @safe
{
@@ -437,7 +437,7 @@ public:
}
/**
- * Return the Tid of the thread which spawned the caller's thread.
+ * Return the `Tid` of the thread which spawned the caller's thread.
*
* Throws: A `TidMissingException` exception if
* there is no owner thread.
@@ -493,7 +493,7 @@ private template isSpawnable(F, T...)
}
/**
- * Starts fn(args) in a new logical thread.
+ * Starts `fn(args)` in a new logical thread.
*
* Executes the supplied function in a new logical thread represented by
* `Tid`. The calling thread is designated as the owner of the new thread.
@@ -506,7 +506,7 @@ private template isSpawnable(F, T...)
* args = Arguments to the function.
*
* Returns:
- * A Tid representing the new logical thread.
+ * A `Tid` representing the new logical thread.
*
* Notes:
* `args` must not have unshared aliasing. In other words, all arguments
@@ -573,16 +573,16 @@ if (isSpawnable!(F, T))
}
/**
- * Starts fn(args) in a logical thread and will receive a LinkTerminated
+ * Starts `fn(args)` in a logical thread and will receive a `LinkTerminated`
* message when the operation terminates.
*
* Executes the supplied function in a new logical thread represented by
- * Tid. This new thread is linked to the calling thread so that if either
- * it or the calling thread terminates a LinkTerminated message will be sent
- * to the other, causing a LinkTerminated exception to be thrown on receive().
- * The owner relationship from spawn() is preserved as well, so if the link
+ * `Tid`. This new thread is linked to the calling thread so that if either
+ * it or the calling thread terminates a `LinkTerminated` message will be sent
+ * to the other, causing a `LinkTerminated` exception to be thrown on `receive()`.
+ * The owner relationship from `spawn()` is preserved as well, so if the link
* between threads is broken, owner termination will still result in an
- * OwnerTerminated exception to be thrown on receive().
+ * `OwnerTerminated` exception to be thrown on `receive()`.
*
* Params:
* fn = The function to execute.
@@ -1021,7 +1021,7 @@ do
enum OnCrowding
{
block, /// Wait until room is available.
- throwException, /// Throw a MailboxFull exception.
+ throwException, /// Throw a $(LREF MailboxFull) exception.
ignore /// Abort the send and return.
}
@@ -1178,13 +1178,13 @@ bool unregister(string name)
}
/**
- * Gets the Tid associated with name.
+ * Gets the `Tid` associated with name.
*
* Params:
* name = The name to locate within the registry.
*
* Returns:
- * The associated Tid or Tid.init if name is not registered.
+ * The associated `Tid` or `Tid.init` if name is not registered.
*/
Tid locate(string name)
{
@@ -1199,7 +1199,7 @@ Tid locate(string name)
/**
* Encapsulates all implementation-level data needed for scheduling.
*
- * When defining a Scheduler, an instance of this struct must be associated
+ * When defining a $(LREF Scheduler), an instance of this struct must be associated
* with each logical thread. It contains all implementation-level information
* needed by the internal API.
*/
@@ -1210,11 +1210,11 @@ struct ThreadInfo
Tid owner;
/**
- * Gets a thread-local instance of ThreadInfo.
+ * Gets a thread-local instance of `ThreadInfo`.
*
- * Gets a thread-local instance of ThreadInfo, which should be used as the
+ * Gets a thread-local instance of `ThreadInfo`, which should be used as the
* default instance when info is requested for a thread not created by the
- * Scheduler.
+ * `Scheduler`.
*/
static @property ref thisInfo() nothrow
{
@@ -1253,15 +1253,15 @@ struct ThreadInfo
}
/**
- * A Scheduler controls how threading is performed by spawn.
+ * A `Scheduler` controls how threading is performed by spawn.
*
- * Implementing a Scheduler allows the concurrency mechanism used by this
+ * Implementing a `Scheduler` allows the concurrency mechanism used by this
* module to be customized according to different needs. By default, a call
* to spawn will create a new kernel thread that executes the supplied routine
- * and terminates when finished. But it is possible to create Schedulers that
- * reuse threads, that multiplex Fibers (coroutines) across a single thread,
- * or any number of other approaches. By making the choice of Scheduler a
- * user-level option, std.concurrency may be used for far more types of
+ * and terminates when finished. But it is possible to create `Scheduler`s that
+ * reuse threads, that multiplex `Fiber`s (coroutines) across a single thread,
+ * or any number of other approaches. By making the choice of `Scheduler` a
+ * user-level option, `std.concurrency` may be used for far more types of
* application than if this behavior were predefined.
*
* Example:
@@ -1280,25 +1280,25 @@ struct ThreadInfo
* ---
*
* Some schedulers have a dispatching loop that must run if they are to work
- * properly, so for the sake of consistency, when using a scheduler, start()
- * must be called within main(). This yields control to the scheduler and
+ * properly, so for the sake of consistency, when using a scheduler, `start()`
+ * must be called within `main()`. This yields control to the scheduler and
* will ensure that any spawned threads are executed in an expected manner.
*/
interface Scheduler
{
/**
- * Spawns the supplied op and starts the Scheduler.
+ * Spawns the supplied op and starts the `Scheduler`.
*
* This is intended to be called at the start of the program to yield all
- * scheduling to the active Scheduler instance. This is necessary for
+ * scheduling to the active `Scheduler` instance. This is necessary for
* schedulers that explicitly dispatch threads rather than simply relying
* on the operating system to do so, and so start should always be called
- * within main() to begin normal program execution.
+ * within `main()` to begin normal program execution.
*
* Params:
* op = A wrapper for whatever the main thread would have done in the
* absence of a custom scheduler. It will be automatically executed
- * via a call to spawn by the Scheduler.
+ * via a call to spawn by the `Scheduler`.
*/
void start(void delegate() op);
@@ -1307,8 +1307,8 @@ interface Scheduler
*
* This routine is called by spawn. It is expected to instantiate a new
* logical thread and run the supplied operation. This thread must call
- * thisInfo.cleanup() when the thread terminates if the scheduled thread
- * is not a kernel thread--all kernel threads will have their ThreadInfo
+ * `thisInfo.cleanup()` when the thread terminates if the scheduled thread
+ * is not a kernel thread--all kernel threads will have their `ThreadInfo`
* cleaned up automatically by a thread-local destructor.
*
* Params:
@@ -1329,36 +1329,36 @@ interface Scheduler
void yield() nothrow;
/**
- * Returns an appropriate ThreadInfo instance.
+ * Returns an appropriate `ThreadInfo` instance.
*
- * Returns an instance of ThreadInfo specific to the logical thread that
+ * Returns an instance of `ThreadInfo` specific to the logical thread that
* is calling this routine or, if the calling thread was not create by
- * this scheduler, returns ThreadInfo.thisInfo instead.
+ * this scheduler, returns `ThreadInfo.thisInfo` instead.
*/
@property ref ThreadInfo thisInfo() nothrow;
/**
- * Creates a Condition variable analog for signaling.
+ * Creates a `Condition` variable analog for signaling.
*
- * Creates a new Condition variable analog which is used to check for and
+ * Creates a new `Condition` variable analog which is used to check for and
* to signal the addition of messages to a thread's message queue. Like
* yield, some schedulers may need to define custom behavior so that calls
- * to Condition.wait() yield to another thread when no new messages are
+ * to `Condition.wait()` yield to another thread when no new messages are
* available instead of blocking.
*
* Params:
- * m = The Mutex that will be associated with this condition. It will be
+ * m = The `Mutex` that will be associated with this condition. It will be
* locked prior to any operation on the condition, and so in some
- * cases a Scheduler may need to hold this reference and unlock the
+ * cases a `Scheduler` may need to hold this reference and unlock the
* mutex before yielding execution to another logical thread.
*/
Condition newCondition(Mutex m) nothrow;
}
/**
- * An example Scheduler using kernel threads.
+ * An example `Scheduler` using kernel threads.
*
- * This is an example Scheduler that mirrors the default scheduling behavior
+ * This is an example `Scheduler` that mirrors the default scheduling behavior
* of creating one kernel thread per call to spawn. It is fully functional
* and may be instantiated and used, but is not a necessary part of the
* default functioning of this module.
@@ -1392,8 +1392,8 @@ class ThreadScheduler : Scheduler
}
/**
- * Returns ThreadInfo.thisInfo, since it is a thread-local instance of
- * ThreadInfo, which is the correct behavior for this scheduler.
+ * Returns `ThreadInfo.thisInfo`, since it is a thread-local instance of
+ * `ThreadInfo`, which is the correct behavior for this scheduler.
*/
@property ref ThreadInfo thisInfo() nothrow
{
@@ -1401,7 +1401,7 @@ class ThreadScheduler : Scheduler
}
/**
- * Creates a new Condition variable. No custom behavior is needed here.
+ * Creates a new `Condition` variable. No custom behavior is needed here.
*/
Condition newCondition(Mutex m) nothrow
{
@@ -1410,15 +1410,15 @@ class ThreadScheduler : Scheduler
}
/**
- * An example Scheduler using Fibers.
+ * An example `Scheduler` using $(MREF_ALTTEXT `Fiber`s, core, thread, fiber).
*
- * This is an example scheduler that creates a new Fiber per call to spawn
+ * This is an example scheduler that creates a new `Fiber` per call to spawn
* and multiplexes the execution of all fibers within the main thread.
*/
class FiberScheduler : Scheduler
{
/**
- * This creates a new Fiber for the supplied op and then starts the
+ * This creates a new `Fiber` for the supplied op and then starts the
* dispatcher.
*/
void start(void delegate() op)
@@ -1428,7 +1428,7 @@ class FiberScheduler : Scheduler
}
/**
- * This created a new Fiber for the supplied op and adds it to the
+ * This created a new `Fiber` for the supplied op and adds it to the
* dispatch list.
*/
void spawn(void delegate() op) nothrow
@@ -1438,8 +1438,8 @@ class FiberScheduler : Scheduler
}
/**
- * If the caller is a scheduled Fiber, this yields execution to another
- * scheduled Fiber.
+ * If the caller is a scheduled `Fiber`, this yields execution to another
+ * scheduled `Fiber`.
*/
void yield() nothrow
{
@@ -1451,11 +1451,11 @@ class FiberScheduler : Scheduler
}
/**
- * Returns an appropriate ThreadInfo instance.
+ * Returns an appropriate `ThreadInfo` instance.
*
- * Returns a ThreadInfo instance specific to the calling Fiber if the
- * Fiber was created by this dispatcher, otherwise it returns
- * ThreadInfo.thisInfo.
+ * Returns a `ThreadInfo` instance specific to the calling `Fiber` if the
+ * `Fiber` was created by this dispatcher, otherwise it returns
+ * `ThreadInfo.thisInfo`.
*/
@property ref ThreadInfo thisInfo() nothrow
{
@@ -1467,10 +1467,10 @@ class FiberScheduler : Scheduler
}
/**
- * Returns a Condition analog that yields when wait or notify is called.
+ * Returns a `Condition` analog that yields when wait or notify is called.
*
* Bug:
- * For the default implementation, `notifyAll`will behave like `notify`.
+ * For the default implementation, `notifyAll` will behave like `notify`.
*
* Params:
* m = A `Mutex` to use for locking if the condition needs to be waited on
@@ -1485,7 +1485,7 @@ class FiberScheduler : Scheduler
protected:
/**
- * Creates a new Fiber which calls the given delegate.
+ * Creates a new `Fiber` which calls the given delegate.
*
* Params:
* op = The delegate the fiber should call
@@ -1505,7 +1505,7 @@ protected:
}
/**
- * Fiber which embeds a ThreadInfo
+ * `Fiber` which embeds a `ThreadInfo`
*/
static class InfoFiber : Fiber
{
@@ -1650,10 +1650,10 @@ private:
}
/**
- * Sets the Scheduler behavior within the program.
+ * Sets the `Scheduler` behavior within the program.
*
- * This variable sets the Scheduler behavior within this program. Typically,
- * when setting a Scheduler, scheduler.start() should be called in main. This
+ * This variable sets the `Scheduler` behavior within this program. Typically,
+ * when setting a `Scheduler`, `scheduler.start()` should be called in `main`. This
* routine will not return until program execution is complete.
*/
__gshared Scheduler scheduler;
@@ -1661,8 +1661,8 @@ __gshared Scheduler scheduler;
// Generator
/**
- * If the caller is a Fiber and is not a Generator, this function will call
- * scheduler.yield() or Fiber.yield(), as appropriate.
+ * If the caller is a `Fiber` and is not a $(LREF Generator), this function will call
+ * `scheduler.yield()` or `Fiber.yield()`, as appropriate.
*/
void yield() nothrow
{
@@ -1684,8 +1684,9 @@ private interface IsGenerator {}
/**
- * A Generator is a Fiber that periodically returns values of type T to the
- * caller via yield. This is represented as an InputRange.
+ * A Generator is a $(MREF_ALTTEXT Fiber, core, thread, fiber)
+ * that periodically returns values of type `T` to the
+ * caller via `yield`. This is represented as an InputRange.
*/
class Generator(T) :
Fiber, IsGenerator, InputRange!T
@@ -1829,7 +1830,7 @@ class Generator(T) :
/**
* Returns the most recently generated value without executing a
* copy contructor. Will not compile for element types defining a
- * postblit, because Generator does not return by reference.
+ * postblit, because `Generator` does not return by reference.
*/
final T moveFront()
{
diff --git a/libphobos/src/std/container/binaryheap.d b/libphobos/src/std/container/binaryheap.d
index 7ff14fc..0fd3452 100644
--- a/libphobos/src/std/container/binaryheap.d
+++ b/libphobos/src/std/container/binaryheap.d
@@ -597,3 +597,43 @@ BinaryHeap!(Store, less) heapify(alias less = "a < b", Store)(Store s,
heap.insert(6);
assert(equal(heap, [6, 5]));
}
+
+/**
+Example for unintuitive behaviour
+It is important not to use the Store after a Heap has been instantiated from
+it, at least in the cases of Dynamic Arrays. For example, inserting a new element
+in a Heap, which is using a Dyamic Array as a Store, will cause a reallocation of
+the Store, if the Store is already full. The Heap will not point anymore to the
+original Dyamic Array, but point to a new Dynamic Array.
+ */
+
+// https://issues.dlang.org/show_bug.cgi?id=18333
+@system unittest
+{
+ import std.stdio;
+ import std.algorithm.comparison : equal;
+ import std.container.binaryheap;
+
+ int[] a = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ];
+ auto h = heapify(a);
+
+ // Internal representation of Binary Heap tree
+ assert(a.equal([16, 14, 10, 8, 7, 9, 3, 2, 4, 1]));
+
+ h.replaceFront(30);
+ // Value 16 was replaced by 30
+ assert(a.equal([30, 14, 10, 8, 7, 9, 3, 2, 4, 1]));
+
+ // Making changes to the Store will be seen in the Heap
+ a[0] = 40;
+ assert(h.front() == 40);
+
+ // Inserting a new element will reallocate the Store, leaving
+ // the original Store unchanged.
+ h.insert(20);
+ assert(a.equal([40, 14, 10, 8, 7, 9, 3, 2, 4, 1]));
+
+ // Making changes to the original Store will not affect the Heap anymore
+ a[0] = 60;
+ assert(h.front() == 40);
+}
diff --git a/libphobos/src/std/exception.d b/libphobos/src/std/exception.d
index b699a8e..6ffc0f7 100644
--- a/libphobos/src/std/exception.d
+++ b/libphobos/src/std/exception.d
@@ -1069,9 +1069,9 @@ as the language is free to assume objects don't have internal pointers
*/
bool doesPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @nogc @trusted pure nothrow
if (__traits(isRef, source) || isDynamicArray!S ||
- is(S : U*, U) || is(S == class))
+ is(S == U*, U) || is(S == class))
{
- static if (is(S : U*, U) || is(S == class) || is(S == interface))
+ static if (is(S == U*, U) || is(S == class) || is(S == interface))
{
const m = *cast(void**) &source;
const b = cast(void*) &target;
@@ -1115,9 +1115,9 @@ bool doesPointTo(S, T)(auto ref const shared S source, ref const shared T target
/// ditto
bool mayPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @trusted pure nothrow
if (__traits(isRef, source) || isDynamicArray!S ||
- is(S : U*, U) || is(S == class))
+ is(S == U*, U) || is(S == class))
{
- static if (is(S : U*, U) || is(S == class) || is(S == interface))
+ static if (is(S == U*, U) || is(S == class) || is(S == interface))
{
const m = *cast(void**) &source;
const b = cast(void*) &target;
@@ -1533,21 +1533,6 @@ version (StdUnittest)
assert( doesPointTo(cast(int*) s, i));
assert(!doesPointTo(cast(int*) s, j));
}
-@safe unittest //more alias this opCast
-{
- void* p;
- class A
- {
- void* opCast(T)() if (is(T == void*))
- {
- return p;
- }
- alias foo = opCast!(void*);
- alias foo this;
- }
- assert(!doesPointTo(A.init, p));
- assert(!mayPointTo(A.init, p));
-}
/+
Returns true if the field at index `i` in ($D T) shares its address with another field.
diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d
index d031096..b7bd3fc 100644
--- a/libphobos/src/std/file.d
+++ b/libphobos/src/std/file.d
@@ -1575,7 +1575,7 @@ private void setTimesImpl(scope const(char)[] names, scope const(FSChar)* namez,
const ta = SysTimeToFILETIME(accessTime);
const tm = SysTimeToFILETIME(modificationTime);
alias defaults =
- AliasSeq!(GENERIC_WRITE,
+ AliasSeq!(FILE_WRITE_ATTRIBUTES,
0,
null,
OPEN_EXISTING,
@@ -1664,6 +1664,16 @@ private void setTimesImpl(scope const(char)[] names, scope const(FSChar)* namez,
rmdirRecurse(newdir);
}
+// https://issues.dlang.org/show_bug.cgi?id=23683
+@safe unittest
+{
+ scope(exit) deleteme.remove;
+ import std.stdio : File;
+ auto f = File(deleteme, "wb");
+ SysTime time = SysTime(DateTime(2018, 10, 4, 0, 0, 30));
+ setTimes(deleteme, time, time);
+}
+
/++
Returns the time that the given file was last modified.
@@ -4930,7 +4940,10 @@ alias DirIterator = _DirIterator!dip1000Enabled;
$(LREF DirEntry).
Throws:
- $(LREF FileException) if the directory does not exist.
+ $(UL
+ $(LI $(LREF FileException) if the $(B path) directory does not exist or read permission is denied.)
+ $(LI $(LREF FileException) if $(B mode) is not `shallow` and a subdirectory cannot be read.)
+ )
Example:
--------------------
@@ -4971,7 +4984,25 @@ auto dFiles = dirEntries("","*.{d,di}",SpanMode.depth);
foreach (d; dFiles)
writeln(d.name);
--------------------
- +/
+To handle subdirectories with denied read permission, use `SpanMode.shallow`:
+---
+void scan(string path)
+{
+ foreach (DirEntry entry; dirEntries(path, SpanMode.shallow))
+ {
+ try
+ {
+ writeln(entry.name);
+ if (entry.isDir)
+ scan(entry.name);
+ }
+ catch (FileException fe) { continue; } // ignore
+ }
+}
+
+scan("");
+---
++/
// For some reason, doing the same alias-to-a-template trick as with DirIterator
// does not work here.
diff --git a/libphobos/src/std/format/internal/write.d b/libphobos/src/std/format/internal/write.d
index 32c82995..7f127c0 100644
--- a/libphobos/src/std/format/internal/write.d
+++ b/libphobos/src/std/format/internal/write.d
@@ -50,27 +50,6 @@ if (is(BooleanTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
@safe unittest
{
- class C1
- {
- bool val;
- alias val this;
- this(bool v){ val = v; }
- }
-
- class C2 {
- bool val;
- alias val this;
- this(bool v){ val = v; }
- override string toString() const { return "C"; }
- }
-
- () @trusted {
- formatTest(new C1(false), "false");
- formatTest(new C1(true), "true");
- formatTest(new C2(false), "C");
- formatTest(new C2(true), "C");
- } ();
-
struct S1
{
bool val;
@@ -411,26 +390,6 @@ private uint baseOfSpec(in char spec) @safe pure
@safe unittest
{
- class C1
- {
- long val;
- alias val this;
- this(long v){ val = v; }
- }
-
- class C2
- {
- long val;
- alias val this;
- this(long v){ val = v; }
- override string toString() const { return "C"; }
- }
-
- () @trusted {
- formatTest(new C1(10), "10");
- formatTest(new C2(10), "C");
- } ();
-
struct S1
{
long val;
@@ -709,26 +668,6 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
{
formatTest(2.25, "2.25");
- class C1
- {
- double val;
- alias val this;
- this(double v){ val = v; }
- }
-
- class C2
- {
- double val;
- alias val this;
- this(double v){ val = v; }
- override string toString() const { return "C"; }
- }
-
- () @trusted {
- formatTest(new C1(2.25), "2.25");
- formatTest(new C2(2.25), "C");
- } ();
-
struct S1
{
double val;
@@ -1078,26 +1017,6 @@ if (is(CharTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
@safe unittest
{
- class C1
- {
- char val;
- alias val this;
- this(char v){ val = v; }
- }
-
- class C2
- {
- char val;
- alias val this;
- this(char v){ val = v; }
- override string toString() const { return "C"; }
- }
-
- () @trusted {
- formatTest(new C1('c'), "c");
- formatTest(new C2('c'), "C");
- } ();
-
struct S1
{
char val;
@@ -1165,26 +1084,6 @@ if (is(StringTypeOf!T) && !is(StaticArrayTypeOf!T) && !is(T == enum) && !hasToSt
@safe unittest
{
- // Test for bug 5371 for classes
- class C1
- {
- const string var;
- alias var this;
- this(string s){ var = s; }
- }
-
- class C2
- {
- string var;
- alias var this;
- this(string s){ var = s; }
- }
-
- () @trusted {
- formatTest(new C1("c1"), "c1");
- formatTest(new C2("c2"), "c2");
- } ();
-
// Test for bug 5371 for structs
struct S1
{
@@ -1204,16 +1103,6 @@ if (is(StringTypeOf!T) && !is(StaticArrayTypeOf!T) && !is(T == enum) && !hasToSt
@safe unittest
{
- class C3
- {
- string val;
- alias val this;
- this(string s){ val = s; }
- override string toString() const { return "C"; }
- }
-
- () @trusted { formatTest(new C3("c3"), "C"); } ();
-
struct S3
{
string val; alias val this;
@@ -1436,36 +1325,6 @@ if (is(DynamicArrayTypeOf!T) && !is(StringTypeOf!T) && !is(T == enum) && !hasToS
formatTest(S!0b101([0, 1, 2]), "S"); // Test for bug 7628
formatTest(S!0b110([0, 1, 2]), "S");
formatTest(S!0b111([0, 1, 2]), "S");
-
- class C(uint flags)
- {
- int[] arr;
- static if (flags & 1)
- alias arr this;
-
- this(int[] a) { arr = a; }
-
- static if (flags & 2)
- {
- @property bool empty() const { return arr.length == 0; }
- @property int front() const { return arr[0] * 2; }
- void popFront() { arr = arr[1 .. $]; }
- }
-
- static if (flags & 4)
- override string toString() const { return "C"; }
- }
-
- () @trusted {
- formatTest(new C!0b000([0, 1, 2]), (new C!0b000([])).toString());
- formatTest(new C!0b001([0, 1, 2]), "[0, 1, 2]"); // Test for bug 7628
- formatTest(new C!0b010([0, 1, 2]), "[0, 2, 4]");
- formatTest(new C!0b011([0, 1, 2]), "[0, 2, 4]");
- formatTest(new C!0b100([0, 1, 2]), "C");
- formatTest(new C!0b101([0, 1, 2]), "C"); // Test for bug 7628
- formatTest(new C!0b110([0, 1, 2]), "C");
- formatTest(new C!0b111([0, 1, 2]), "C");
- } ();
}
@safe unittest
@@ -1901,26 +1760,6 @@ if (is(AssocArrayTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
@safe unittest
{
- class C1
- {
- int[char] val;
- alias val this;
- this(int[char] v){ val = v; }
- }
-
- class C2
- {
- int[char] val;
- alias val this;
- this(int[char] v){ val = v; }
- override string toString() const { return "C"; }
- }
-
- () @trusted {
- formatTest(new C1(['c':1, 'd':2]), [`['c':1, 'd':2]`, `['d':2, 'c':1]`]);
- formatTest(new C2(['c':1, 'd':2]), "C");
- } ();
-
struct S1
{
int[char] val;
@@ -1990,7 +1829,8 @@ enum HasToStringResult
customPutWriterFormatSpec,
}
-private enum hasPreviewIn = !is(typeof(mixin(q{(in ref int a) => a})));
+private alias DScannerBug895 = int[256];
+private immutable bool hasPreviewIn = ((in DScannerBug895 a) { return __traits(isRef, a); })(DScannerBug895.init);
template hasToString(T, Char)
{
@@ -3167,18 +3007,6 @@ if (isPointer!T && !is(T == enum) && !hasToString!(T, Char))
formatTest(q, "FFEECCAA");
}
-// https://issues.dlang.org/show_bug.cgi?id=8186
-@system unittest
-{
- class B
- {
- int* a;
- this() { a = new int; }
- alias a this;
- }
- formatTest(B.init, "null");
-}
-
// https://issues.dlang.org/show_bug.cgi?id=9336
@system pure unittest
{
diff --git a/libphobos/src/std/format/read.d b/libphobos/src/std/format/read.d
index 144fa8c..da9d0dc 100644
--- a/libphobos/src/std/format/read.d
+++ b/libphobos/src/std/format/read.d
@@ -303,8 +303,23 @@ uint formattedRead(alias fmt, Range, Args...)(auto ref Range r, auto ref Args ar
if (isSomeString!(typeof(fmt)))
{
import std.format : checkFormatException;
+ import std.meta : staticMap;
+ import std.typecons : Tuple;
+
- alias e = checkFormatException!(fmt, Args);
+ // formattedRead supports std.typecons.Tuple
+ // however, checkFormatException does not
+ // this means that all std.typecons.Tuple's types in Args must be unwrapped
+ // and passed to checkFormatException
+ template Flatten(T)
+ {
+ static if (is(T : Tuple!Args, Args...))
+ alias Flatten = Args;
+ else
+ alias Flatten = T;
+ }
+
+ alias e = checkFormatException!(fmt, staticMap!(Flatten, Args));
static assert(!e, e);
return .formattedRead(r, fmt, args);
}
@@ -361,6 +376,20 @@ if (isSomeString!(typeof(fmt)))
assert(t[0] == 1 && t[1] == 2.125);
}
+// https://issues.dlang.org/show_bug.cgi?id=23600
+@safe pure unittest
+{
+ import std.typecons : Tuple, tuple;
+
+ string h, w;
+ Tuple!(int, float) t;
+
+ assert("hello 1 2.34 world".formattedRead!"%s %d %f %s"(h, t, w) == 3);
+ assert(h == "hello");
+ assert(t == tuple(1, 2.34f));
+ assert(w == "world");
+}
+
@safe unittest
{
import std.math.operations : isClose;
diff --git a/libphobos/src/std/getopt.d b/libphobos/src/std/getopt.d
index c85247f..42aeb40 100644
--- a/libphobos/src/std/getopt.d
+++ b/libphobos/src/std/getopt.d
@@ -558,7 +558,7 @@ private template optionValidator(A...)
import std.format : format;
enum fmt = "getopt validator: %s (at position %d)";
- enum isReceiver(T) = is(T : U*, U) || (is(T == function)) || (is(T == delegate));
+ enum isReceiver(T) = is(T == U*, U) || (is(T == function)) || (is(T == delegate));
enum isOptionStr(T) = isSomeString!T || isSomeChar!T;
auto validator()
diff --git a/libphobos/src/std/internal/unicode_grapheme.d b/libphobos/src/std/internal/unicode_grapheme.d
index d7b2c29..093ebd1 100644
--- a/libphobos/src/std/internal/unicode_grapheme.d
+++ b/libphobos/src/std/internal/unicode_grapheme.d
@@ -22,10 +22,16 @@ static if (size_t.sizeof == 4)
enum hangulLVTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0x80], [ 0x100, 0x80, 0xa00], [ 0x0, 0x20100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20001, 0x40003, 0x60005, 0x10007, 0x30002, 0x50004, 0x70006, 0x20001, 0x40003, 0x60005, 0x10007, 0x30002, 0x50004, 0x70006, 0x20001, 0x40003, 0x60005, 0x10007, 0x30002, 0x50004, 0x70006, 0x80001, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
//832 bytes
enum hangulLVTTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0x80], [ 0x100, 0x80, 0xa00], [ 0x0, 0x20100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20001, 0x40003, 0x60005, 0x10007, 0x30002, 0x50004, 0x70006, 0x20001, 0x40003, 0x60005, 0x10007, 0x30002, 0x50004, 0x70006, 0x20001, 0x40003, 0x60005, 0x10007, 0x30002, 0x50004, 0x70006, 0x80001, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
-//1920 bytes
-enum mcTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0xc0], [ 0x100, 0x100, 0x2400], [ 0x2020100, 0x2020302, 0x5020204, 0x2060202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000, 0x30002, 0x50004, 0x60000, 0x7, 0x0, 0x0, 0x80000, 0x90000, 0xb000a, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf000e, 0x110010, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x130012, 0x150014, 0x170016, 0x190018, 0x1b001a, 0x1c, 0x1e001d, 0x20001f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x210000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x220000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xc8000000, 0xde01, 0x0, 0xc, 0xc0000000, 0x801981, 0x0, 0x8, 0xc0000000, 0x1, 0x0, 0x8, 0xc0000000, 0x1a01, 0x0, 0xc, 0x40000000, 0x801981, 0x0, 0x0, 0xc0000000, 0x801dc6, 0x0, 0xe, 0x0, 0x1e, 0x0, 0xc, 0x40000000, 0x600d9f, 0x80000, 0xc, 0xc0000000, 0x801dc1, 0x0, 0xc, 0x0, 0xff038000, 0xc0000, 0x0, 0xc0000000, 0x0, 0x80000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19021800, 0xc00000, 0x3f9c, 0x1c009f98, 0x0, 0x0, 0x0, 0x200000, 0x100000, 0x0, 0x0, 0x0, 0xc0400000, 0x1bf, 0x0, 0x0, 0x1fb0e78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000000, 0x0, 0xa00000, 0x7e01a, 0x0, 0x0, 0x0, 0x0, 0x10, 0xe8200000, 0x1b, 0x0, 0x4, 0x4c2, 0x0, 0xc5c80, 0x0, 0x300ff0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800002, 0x0, 0xc000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x98, 0x0, 0x0, 0x3, 0xfff00000, 0xf, 0x0, 0x0, 0x0, 0xc0000, 0x0, 0x8, 0xcc300000, 0x1, 0x0, 0x0, 0x198000, 0x2000, 0x28000000, 0x0, 0x0, 0x0, 0x20c800, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16d8, 0x5, 0x0, 0x0, 0x0, 0x4, 0x1870000, 0x0, 0x0, 0x0, 0x1000, 0x60, 0x0, 0x4, 0x80380000, 0x4001, 0x0, 0x0, 0x2c7000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc, 0xc0000000, 0x80399e, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe00000, 0x23, 0x0, 0x0, 0x7a070000, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f038000, 0x0, 0x0, 0x0, 0x58070000, 0x0, 0x0, 0x0, 0x40d000, 0x0, 0x0, 0x0, 0x43, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1007000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21bf0000, 0x5, 0x0, 0x0, 0x0, 0xf00e0000, 0x10, 0x0, 0x2000000, 0x1800000, 0x0, 0x800000, 0x0, 0x0, 0x0, 0x0, 0x40008000, 0x0, 0x0, 0x0, 0x120200, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x587c00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600000, 0x8, 0xc0300000, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfffe0000, 0xffffffff, 0xff, 0x0, 0x0, 0x30000, 0x0, 0x0, 0x0, 0x7e060, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
-//3456 bytes
-enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0x110], [ 0x100, 0x1a0, 0x4a00], [ 0x2020100, 0x4020302, 0x7020605, 0xa090802, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x202020b, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000, 0x30002, 0x50004, 0x70006, 0x90008, 0xb000a, 0xd000c, 0xe, 0xf0000, 0x0, 0x100000, 0x120011, 0x140013, 0x160015, 0x0, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x190018, 0x0, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1d001c, 0x1f001e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200000, 0x0, 0x220021, 0x230000, 0x250024, 0x0, 0x0, 0x0, 0x26, 0x270000, 0x290028, 0x2b002a, 0x2d002c, 0x2f002e, 0x310030, 0x330032, 0x34, 0x360035, 0x380037, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3b003a, 0x0, 0x3c0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e0000, 0x3f0000, 0x40, 0x0, 0x0, 0x0, 0x41, 0x0, 0x0, 0x3b0042, 0x43, 0x44, 0x0, 0x460045, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x480047, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfffe0000, 0xbfffffff, 0xb6, 0x0, 0x7ff0000, 0x0, 0xfffff800, 0x10000, 0x0, 0x0, 0x9fc00000, 0x3d9f, 0x20000, 0xffff0000, 0x7ff, 0x0, 0x0, 0x1ffc0, 0x0, 0x200ff800, 0xfbc00000, 0x3eef, 0xe000000, 0x0, 0xff000000, 0x0, 0xfffffc00, 0xfffffffb, 0x7, 0x14000000, 0xfe21fe, 0xc, 0x2, 0x50000000, 0x80201e, 0x4000000c, 0x6, 0x10000000, 0x23986, 0x230000, 0x6, 0x10000000, 0x21be, 0xfc00000c, 0x2, 0xd0000000, 0xe0201e, 0xc, 0x4, 0x40000000, 0x802001, 0x0, 0x11, 0xd0000000, 0x603dc1, 0xc, 0x2, 0x90000000, 0x603044, 0xc, 0x3, 0x58000000, 0x80201e, 0xc, 0x2, 0x0, 0x805c8400, 0x0, 0x0, 0x7f20000, 0x7f80, 0x0, 0x0, 0x1ff20000, 0x7f00, 0x0, 0x3000000, 0x2a00000, 0x0, 0x7ffe0000, 0xfeffe0df, 0x1fffffff, 0x40, 0x0, 0x0, 0x66fde000, 0xc3000000, 0x1e0001, 0x20002064, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c0000, 0xc0000, 0xc0000, 0xc0000, 0x0, 0x3fb00000, 0x200ffe40, 0x0, 0xb800, 0x0, 0x0, 0x0, 0x60, 0x200, 0x0, 0x0, 0x0, 0xe040187, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9800000, 0x0, 0x7f400000, 0x9ff81fe5, 0x0, 0xffff0000, 0x7fff, 0x0, 0xf, 0x17f00000, 0x4, 0xff800, 0x3, 0x3b3c, 0x0, 0x3a340, 0x0, 0xcff000, 0x0, 0x0, 0x0, 0x0, 0xfff70000, 0x31021fd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff0000, 0x1ffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38000, 0x0, 0x0, 0x0, 0x80000000, 0x0, 0x0, 0x0, 0xffffffff, 0x0, 0xfc00, 0x0, 0x0, 0x6000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3ff78000, 0xc0000000, 0x0, 0x0, 0x30000, 0x844, 0x1060, 0x0, 0x0, 0x0, 0x0, 0x30, 0x8003ffff, 0x0, 0x3fc0, 0x3ff80, 0x0, 0x7, 0x33c80000, 0x0, 0x20, 0x0, 0x667e00, 0x1008, 0x10000000, 0x0, 0xc19d0000, 0x2, 0x403000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2120, 0x40000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x7c00000, 0x0, 0x0, 0x0, 0x0, 0xf06e, 0x87000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x0, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1800, 0x0, 0xe0000000, 0x0, 0x0, 0x1ffc0, 0x0, 0x3c, 0x0, 0x0, 0x0, 0x2, 0xff000000, 0x7f, 0x80190000, 0x3, 0x6780000, 0x4, 0x0, 0x7, 0x1fef80, 0x0, 0x80000, 0x3, 0x7fc00000, 0x9e00, 0x0, 0x0, 0x40d38000, 0x2, 0x0, 0x0, 0x0, 0x80000000, 0x7f8, 0x3, 0x58000000, 0x800001, 0x1f1fc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff000000, 0x4000005c, 0x0, 0x0, 0xa5f90000, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb03c8000, 0x30000001, 0x0, 0x0, 0xa7f80000, 0x1, 0x0, 0x0, 0xbf2800, 0x0, 0x0, 0xe0000000, 0xfbc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6ff8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x58010000, 0x8, 0x0, 0x0, 0x0, 0xcf00000, 0x1, 0x7fe, 0x79f80000, 0xe7e0080, 0x0, 0x37ffc00, 0x0, 0x0, 0x0, 0x0, 0xbf7f0000, 0x0, 0x0, 0xfffc0000, 0x6dfcff, 0x0, 0x0, 0x0, 0xb47e0000, 0xbf, 0x0, 0xa30000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180000, 0x3, 0x7c00000, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3fff81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f0000, 0x0, 0x7f0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8000, 0x0, 0x78000, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x60000000, 0x0, 0x0, 0x0, 0xffffffff, 0xffff3fff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf807c3a0, 0xfe7, 0x3c00, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xf87fffff, 0xffffffff, 0x201fff, 0xf8000010, 0xfffe, 0x0, 0x0, 0xf9ffff7f, 0x7db, 0x0, 0x0, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000, 0x0, 0xf000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f0000, 0x0, 0x0, 0x0, 0x7f0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
+//896 bytes
+enum prependTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0x80], [ 0x100, 0x80, 0xc00], [ 0x1010100, 0x1010101, 0x1010102, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20001, 0x3, 0x0, 0x40000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005, 0x0, 0x0, 0x0, 0x70000, 0x8, 0x90000, 0xa0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20000000, 0x0, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30000, 0x0, 0x0, 0x4, 0x0, 0x0, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20000000, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x80000000, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000000, 0x0, 0x0, 0x3f0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
+//1280 bytes
+enum controlTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0xd0], [ 0x100, 0x120, 0xe00], [ 0x2020100, 0x3020202, 0x2020402, 0x2060502, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020207, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000, 0x10001, 0x10001, 0x10002, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10003, 0x10001, 0x10001, 0x10001, 0x10004, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x60005, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10007, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10008, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x90001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0xb000a, 0xc000c, 0xc000c, 0xc000c, 0xc000c, 0xc000c, 0xc000c, 0xc000c, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0xffffdbff, 0x0, 0x0, 0x80000000, 0xffffffff, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc800, 0x7f00, 0x0, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfff0000, 0x0, 0xffff0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f80000, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff0000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
+//1856 bytes
+enum spacingMarkTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0xb0], [ 0x100, 0xe0, 0x2400], [ 0x1010100, 0x1010201, 0x4010103, 0x1050101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000, 0x30002, 0x50004, 0x70006, 0x8, 0x0, 0x0, 0x90000, 0xa0000, 0xc000b, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf000e, 0x110010, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x130012, 0x150014, 0x170016, 0x190018, 0x1b001a, 0x1c, 0x1e001d, 0x20001f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x210000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x220000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xc8000000, 0xde01, 0x0, 0xc, 0x80000000, 0x1981, 0x0, 0x8, 0xc0000000, 0x1, 0x0, 0x8, 0xc0000000, 0x1a01, 0x0, 0xc, 0x0, 0x1981, 0x0, 0x0, 0x80000000, 0x1dc6, 0x0, 0xe, 0x0, 0x1e, 0x0, 0xc, 0x40000000, 0xd9b, 0x80000, 0xc, 0x80000000, 0x1dc1, 0x0, 0xc, 0x0, 0x7f030000, 0xc0000, 0x0, 0x80000, 0x0, 0x0, 0x0, 0x80000, 0x0, 0x0, 0x0, 0xc0000000, 0x0, 0x80000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18020000, 0xc00000, 0x0, 0x10, 0x0, 0x0, 0x0, 0x200000, 0x100000, 0x0, 0x0, 0x0, 0xc0400000, 0x1bf, 0x0, 0x0, 0x1fb0e78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000000, 0x0, 0xa00000, 0x7e000, 0x0, 0x0, 0x0, 0x0, 0x10, 0xe8000000, 0x1b, 0x0, 0x4, 0x4c2, 0x0, 0xc5c80, 0x0, 0x300ff0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800002, 0x0, 0x98, 0x0, 0x0, 0x3, 0xfff00000, 0xf, 0x0, 0x0, 0x0, 0xc0000, 0x0, 0x8, 0xcc300000, 0x1, 0x0, 0x0, 0x198000, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x20c800, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16d8, 0x5, 0x0, 0x0, 0x0, 0x4, 0x1870000, 0x0, 0x0, 0x0, 0x1000, 0x60, 0x0, 0x4, 0x80380000, 0x4001, 0x0, 0x0, 0x2c7000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc, 0x80000000, 0x399e, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe00000, 0x23, 0x0, 0x0, 0x5a060000, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f030000, 0x0, 0x0, 0x0, 0x58070000, 0x0, 0x0, 0x0, 0x40d000, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1007000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21be0000, 0x5, 0x0, 0x0, 0x0, 0xf00e0000, 0x10, 0x0, 0x2000000, 0x1800000, 0x0, 0x800000, 0x0, 0x0, 0x0, 0x0, 0x40008000, 0x0, 0x0, 0x0, 0x120200, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x587c00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600000, 0x8, 0xc0300000, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfffe0000, 0xffffffff, 0xff, 0x0, 0x0, 0x30000, 0x0, 0x0, 0x0, 0x2040, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
+//3488 bytes
+enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0x110], [ 0x100, 0x1a0, 0x4b00], [ 0x2020100, 0x4020302, 0x7020605, 0xa090802, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x202020b, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000, 0x30002, 0x50004, 0x70006, 0x90008, 0xb000a, 0xd000c, 0xe, 0xf0000, 0x0, 0x100000, 0x120011, 0x140013, 0x160015, 0x0, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x190018, 0x0, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1d001c, 0x1f001e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200000, 0x0, 0x220021, 0x230000, 0x250024, 0x0, 0x0, 0x0, 0x26, 0x270000, 0x290028, 0x2b002a, 0x2d002c, 0x2f002e, 0x310030, 0x330032, 0x34, 0x360035, 0x380037, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3b003a, 0x0, 0x3c0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e0000, 0x3f0000, 0x40, 0x0, 0x0, 0x0, 0x41, 0x0, 0x0, 0x3b0042, 0x43, 0x44, 0x0, 0x460045, 0x0, 0x0, 0x0, 0x0, 0x470000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x490048, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfffe0000, 0xbfffffff, 0xb6, 0x0, 0x7ff0000, 0x0, 0xfffff800, 0x10000, 0x0, 0x0, 0x9fc00000, 0x3d9f, 0x20000, 0xffff0000, 0x7ff, 0x0, 0x0, 0x1ffc0, 0x0, 0x200ff800, 0xfbc00000, 0x3eef, 0xe000000, 0x0, 0xff000000, 0x0, 0xfffffc00, 0xfffffffb, 0x7, 0x14000000, 0xfe21fe, 0xc, 0x2, 0x50000000, 0x80201e, 0x4000000c, 0x6, 0x10000000, 0x23986, 0x230000, 0x6, 0x10000000, 0x21be, 0xfc00000c, 0x2, 0xd0000000, 0xe0201e, 0xc, 0x4, 0x40000000, 0x802001, 0x0, 0x11, 0xd0000000, 0x603dc1, 0xc, 0x2, 0x90000000, 0x603044, 0xc, 0x3, 0x58000000, 0x80201e, 0xc, 0x2, 0x0, 0x805c8400, 0x0, 0x0, 0x7f20000, 0x7f80, 0x0, 0x0, 0x1ff20000, 0x7f00, 0x0, 0x3000000, 0x2a00000, 0x0, 0x7ffe0000, 0xfeffe0df, 0x1fffffff, 0x40, 0x0, 0x0, 0x66fde000, 0xc3000000, 0x1e0001, 0x20002064, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c0000, 0xc0000, 0xc0000, 0xc0000, 0x0, 0x3fb00000, 0x200ffe40, 0x0, 0xb800, 0x0, 0x0, 0x0, 0x60, 0x200, 0x0, 0x0, 0x0, 0xe040187, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9800000, 0x0, 0x7f400000, 0x9ff81fe5, 0x0, 0xffff0000, 0x7fff, 0x0, 0xf, 0x17f00000, 0x4, 0xff800, 0x3, 0x3b3c, 0x0, 0x3a340, 0x0, 0xcff000, 0x0, 0x0, 0x0, 0x0, 0xfff70000, 0x31021fd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff0000, 0x1ffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38000, 0x0, 0x0, 0x0, 0x80000000, 0x0, 0x0, 0x0, 0xffffffff, 0x0, 0xfc00, 0x0, 0x0, 0x6000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3ff78000, 0xc0000000, 0x0, 0x0, 0x30000, 0x844, 0x1060, 0x0, 0x0, 0x0, 0x0, 0x30, 0x8003ffff, 0x0, 0x3fc0, 0x3ff80, 0x0, 0x7, 0x33c80000, 0x0, 0x20, 0x0, 0x667e00, 0x1008, 0x10000000, 0x0, 0xc19d0000, 0x2, 0x403000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2120, 0x40000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x7c00000, 0x0, 0x0, 0x0, 0x0, 0xf06e, 0x87000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x0, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1800, 0x0, 0xe0000000, 0x0, 0x0, 0x1ffc0, 0x0, 0x3c, 0x0, 0x0, 0x0, 0x2, 0xff000000, 0x7f, 0x80190000, 0x3, 0x6780000, 0x4, 0x0, 0x7, 0x1fef80, 0x0, 0x80000, 0x3, 0x7fc00000, 0x9e00, 0x0, 0x0, 0x40d38000, 0x2, 0x0, 0x0, 0x0, 0x80000000, 0x7f8, 0x3, 0x58000000, 0x800001, 0x1f1fc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff000000, 0x4000005c, 0x0, 0x0, 0xa5f90000, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb03c8000, 0x30000001, 0x0, 0x0, 0xa7f80000, 0x1, 0x0, 0x0, 0xbf2800, 0x0, 0x0, 0xe0000000, 0xfbc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6ff8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x58010000, 0x8, 0x0, 0x0, 0x0, 0xcf00000, 0x1, 0x7fe, 0x79f80000, 0xe7e0080, 0x0, 0x37ffc00, 0x0, 0x0, 0x0, 0x0, 0xbf7f0000, 0x0, 0x0, 0xfffc0000, 0x6dfcff, 0x0, 0x0, 0x0, 0xb47e0000, 0xbf, 0x0, 0xa30000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180000, 0x3, 0x7c00000, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3fff81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f0000, 0x0, 0x7f0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8000, 0x0, 0x78000, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x60000000, 0x0, 0x0, 0x0, 0xffffffff, 0xffff3fff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf807c3a0, 0xfe7, 0x3c00, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xf87fffff, 0xffffffff, 0x201fff, 0xf8000010, 0xfffe, 0x0, 0x0, 0xf9ffff7f, 0x7db, 0x0, 0x0, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000, 0x0, 0xf000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f0000, 0x0, 0x0, 0x0, 0x7f0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8000000, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
+//1344 bytes
+enum Extended_PictographicTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0x90], [ 0x100, 0xa0, 0x1800], [ 0x2020100, 0x2020202, 0x2020202, 0x3020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x30002, 0x40001, 0x60005, 0x80007, 0x90001, 0xa0001, 0x10001, 0x10001, 0x1000b, 0x1000c, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0xe000d, 0x10000f, 0x11000d, 0x130012, 0x150014, 0x1000d, 0xd000d, 0x16000d, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4200, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000000, 0x200, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000004, 0x0, 0x0, 0x3f00000, 0x600, 0x0, 0x0, 0xc000000, 0x100, 0x0, 0x0, 0x100, 0x0, 0x8000, 0x70ffe00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400c00, 0x1, 0x78000000, 0xfff7ffbf, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff003f, 0xffffffff, 0xffffffff, 0xffffffff, 0x2057ff3f, 0x180102, 0xb85090, 0xf8, 0xe00000, 0x80010002, 0x0, 0x0, 0x0, 0x300000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180000e0, 0x0, 0x210000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20010000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2800000, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xe000, 0x8000, 0x0, 0xc003f000, 0x7fe4000, 0xffffe000, 0xffffffff, 0x3f, 0x400fffe, 0xf7fc8000, 0xfffffe00, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x7ffffff, 0xffffffff, 0x3fffffff, 0xffffffc0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0, 0x0, 0x0, 0xfff00000, 0x0, 0x0, 0xffe00000, 0xffffffff, 0xf000, 0x0, 0xfc00ff00, 0x0, 0xff00, 0xffffc000, 0xffffffff, 0xffffffff, 0xfffff000, 0xf7ffffff, 0xffffffbf, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x3fffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
}
@@ -36,10 +42,16 @@ static if (size_t.sizeof == 8)
enum hangulLVTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x40], [ 0x100, 0x80, 0xa00], [ 0x2010000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000300020001, 0x1000700060005, 0x5000400030002, 0x2000100070006, 0x6000500040003, 0x3000200010007, 0x7000600050004, 0x4000300020001, 0x1000700060005, 0x5000400030002, 0x8000100070006, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x100000010000001, 0x1000000100000, 0x10000001000, 0x1000000100000010, 0x10000001000000, 0x100000010000, 0x1000000100, 0x100000010000001, 0x1000000100000, 0x10000001000, 0x1000000100000010, 0x10000001000000, 0x100000010000, 0x1000000100, 0x100000010000001, 0x1000000100000, 0x10000001000, 0x1000000100000010, 0x10000001000000, 0x100000010000, 0x1000000100, 0x100000010000001, 0x1000000100000, 0x10000001000, 0x1000000100000010, 0x10000001000000, 0x100000010000, 0x1000000100, 0x10000001000000, 0x100000010000, 0x100, 0x0, 0x0, 0x0, 0x0, 0x0]);
//832 bytes
enum hangulLVTTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x40], [ 0x100, 0x80, 0xa00], [ 0x2010000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000300020001, 0x1000700060005, 0x5000400030002, 0x2000100070006, 0x6000500040003, 0x3000200010007, 0x7000600050004, 0x4000300020001, 0x1000700060005, 0x5000400030002, 0x8000100070006, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfeffffffeffffffe, 0xfffeffffffefffff, 0xfffffeffffffefff, 0xeffffffeffffffef, 0xffeffffffeffffff, 0xffffeffffffeffff, 0xffffffeffffffeff, 0xfeffffffeffffffe, 0xfffeffffffefffff, 0xfffffeffffffefff, 0xeffffffeffffffef, 0xffeffffffeffffff, 0xffffeffffffeffff, 0xffffffeffffffeff, 0xfeffffffeffffffe, 0xfffeffffffefffff, 0xfffffeffffffefff, 0xeffffffeffffffef, 0xffeffffffeffffff, 0xffffeffffffeffff, 0xffffffeffffffeff, 0xfeffffffeffffffe, 0xfffeffffffefffff, 0xfffffeffffffefff, 0xeffffffeffffffef, 0xffeffffffeffffff, 0xffffeffffffeffff, 0xffffffeffffffeff, 0xffeffffffeffffff, 0xffffeffffffeffff, 0xffffffeff, 0x0, 0x0, 0x0, 0x0, 0x0]);
-//1920 bytes
-enum mcTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x60], [ 0x100, 0x100, 0x2400], [ 0x202030202020100, 0x206020205020204, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3000200010000, 0x6000000050004, 0x7, 0x8000000000000, 0xb000a00090000, 0xc, 0x0, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x110010000f000e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15001400130012, 0x19001800170016, 0x1c001b001a, 0x20001f001e001d, 0x0, 0x0, 0x0, 0x21000000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x220000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc800000000000008, 0xde01, 0xc00000000000000c, 0x801981, 0xc000000000000008, 0x1, 0xc000000000000008, 0x1a01, 0x400000000000000c, 0x801981, 0xc000000000000000, 0x801dc6, 0xe, 0x1e, 0x400000000000000c, 0x8000000600d9f, 0xc00000000000000c, 0x801dc1, 0xc, 0xc0000ff038000, 0xc000000000000000, 0x8000000000000000, 0x0, 0x0, 0x1902180000000000, 0x3f9c00c00000, 0x1c009f98, 0x0, 0x10000000200000, 0x0, 0xc040000000000000, 0x1bf, 0x1fb0e7800000000, 0x0, 0x0, 0x0, 0x6000000, 0x7e01a00a00000, 0x0, 0x0, 0xe820000000000010, 0x1b, 0x4c200000004, 0xc5c8000000000, 0x300ff000000000, 0x0, 0x0, 0x80000200000000, 0xc00000000000, 0x0, 0x0, 0x0, 0x9800000000, 0x0, 0xfff0000000000003, 0xf, 0x0, 0xc0000, 0xcc30000000000008, 0x1, 0x19800000000000, 0x2800000000002000, 0x0, 0x20c80000000000, 0x0, 0x0, 0x0, 0x16d800000000, 0x5, 0x0, 0x187000000000004, 0x0, 0x100000000000, 0x60, 0x8038000000000004, 0x4001, 0x2c700000000000, 0x0, 0x0, 0x700000000, 0xc00000000000000c, 0xc0080399e, 0x0, 0x0, 0xe0000000000000, 0x23, 0x7a07000000000000, 0x2, 0x0, 0x0, 0x4f03800000000000, 0x0, 0x5807000000000000, 0x0, 0x40d00000000000, 0x0, 0x4300000000, 0x0, 0x0, 0x0, 0x100700000000000, 0x0, 0x0, 0x0, 0x21bf000000000000, 0x5, 0x0, 0x10f00e0000, 0x200000000000000, 0x1800000, 0x800000, 0x0, 0x4000800000000000, 0x0, 0x12020000000000, 0x0, 0x0, 0x0, 0x587c00, 0x0, 0x0, 0x0, 0x0, 0x60000000000000, 0xc030000000000008, 0x2, 0x0, 0x0, 0x0, 0xfffffffffffe0000, 0xff, 0x3000000000000, 0x0, 0x7e06000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
-//3456 bytes
-enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x88], [ 0x100, 0x1a0, 0x4a00], [ 0x402030202020100, 0xa09080207020605, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x20202020202020b, 0x202020202020202, 0x202020202020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000000000000, 0x5000400030002, 0x9000800070006, 0xd000c000b000a, 0xf00000000000e, 0x10000000000000, 0x14001300120011, 0x160015, 0x17, 0x0, 0x0, 0x190018, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b00000000, 0x1f001e001d001c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20000000000000, 0x22002100000000, 0x25002400230000, 0x0, 0x2600000000, 0x29002800270000, 0x2d002c002b002a, 0x310030002f002e, 0x3400330032, 0x38003700360035, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x3b003a00000000, 0x3c000000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x3e000000000000, 0x40003f0000, 0x0, 0x4100000000, 0x0, 0x43003b0042, 0x44, 0x460045, 0x0, 0x0, 0x0, 0x0, 0x0, 0x480047, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x3f8, 0x0, 0x0, 0x0, 0xbffffffffffe0000, 0xb6, 0x7ff0000, 0x10000fffff800, 0x0, 0x3d9f9fc00000, 0xffff000000020000, 0x7ff, 0x1ffc000000000, 0x200ff80000000000, 0x3eeffbc00000, 0xe000000, 0xff000000, 0xfffffffbfffffc00, 0x1400000000000007, 0xc00fe21fe, 0x5000000000000002, 0x4000000c0080201e, 0x1000000000000006, 0x23000000023986, 0x1000000000000006, 0xfc00000c000021be, 0xd000000000000002, 0xc00e0201e, 0x4000000000000004, 0x802001, 0xd000000000000011, 0xc00603dc1, 0x9000000000000002, 0xc00603044, 0x5800000000000003, 0xc0080201e, 0x2, 0x805c8400, 0x7f2000000000000, 0x7f80, 0x1ff2000000000000, 0x7f00, 0x2a0000003000000, 0x7ffe000000000000, 0x1ffffffffeffe0df, 0x40, 0x66fde00000000000, 0x1e0001c3000000, 0x20002064, 0x0, 0x0, 0xe0000000, 0x0, 0x0, 0xc0000001c0000, 0xc0000000c0000, 0x3fb0000000000000, 0x200ffe40, 0xb800, 0x0, 0x20000000060, 0x0, 0xe04018700000000, 0x0, 0x0, 0x0, 0x9800000, 0x9ff81fe57f400000, 0xffff000000000000, 0x7fff, 0x17f000000000000f, 0xff80000000004, 0x3b3c00000003, 0x3a34000000000, 0xcff00000000000, 0x0, 0x0, 0x31021fdfff70000, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x1000, 0x0, 0x0, 0x1ffffffff0000, 0x0, 0x0, 0x0, 0x3800000000000, 0x0, 0x8000000000000000, 0x0, 0xffffffff00000000, 0xfc0000000000, 0x0, 0x6000000, 0x0, 0x0, 0x3ff7800000000000, 0xc0000000, 0x3000000000000, 0x106000000844, 0x0, 0x0, 0x8003ffff00000030, 0x3fc000000000, 0x3ff80, 0x33c8000000000007, 0x2000000000, 0x667e0000000000, 0x1000000000001008, 0xc19d000000000000, 0x40300000000002, 0x0, 0x0, 0x0, 0x212000000000, 0x40000000, 0x0, 0x0, 0x0, 0xffff0000ffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0000000, 0x0, 0x0, 0x0, 0x0, 0x2000000000000000, 0x0, 0x0, 0x0, 0x100000000, 0x0, 0x7c0000000000000, 0x0, 0x0, 0x870000000000f06e, 0x0, 0x0, 0x6000000000, 0xf000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180000000000, 0xe000000000000000, 0x0, 0x1ffc0, 0x3c, 0x0, 0xff00000000000002, 0x801900000000007f, 0x678000000000003, 0x4, 0x1fef8000000007, 0x8000000000000, 0x7fc0000000000003, 0x9e00, 0x40d3800000000000, 0x2, 0x0, 0x7f880000000, 0x5800000000000003, 0x1f1fc000800001, 0x0, 0x0, 0xff00000000000000, 0x4000005c, 0xa5f9000000000000, 0xd, 0x0, 0x0, 0xb03c800000000000, 0x30000001, 0xa7f8000000000000, 0x1, 0xbf280000000000, 0x0, 0xfbce0000000, 0x0, 0x0, 0x0, 0x6ff800000000000, 0x0, 0x0, 0x0, 0x5801000000000000, 0x8, 0x0, 0x10cf00000, 0x79f80000000007fe, 0xe7e0080, 0x37ffc00, 0x0, 0xbf7f000000000000, 0x0, 0x6dfcfffffc0000, 0x0, 0xb47e000000000000, 0xbf, 0xa30000, 0x0, 0x0, 0x0, 0x0, 0x18000000000000, 0x7c0000000000003, 0x5, 0x0, 0x0, 0x0, 0x3fff81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f000000000000, 0x7f000000000000, 0x0, 0x0, 0x0, 0x0, 0x8000, 0x78000, 0x1000000000, 0x0, 0x0, 0x60000000, 0x0, 0xffff3fffffffffff, 0x7f, 0x0, 0x0, 0x0, 0xf807c3a000000000, 0x3c0000000fe7, 0x0, 0x0, 0x1c, 0x0, 0x0, 0xf87fffffffffffff, 0x201fffffffffff, 0xfffef8000010, 0x0, 0x7dbf9ffff7f, 0x0, 0x8000, 0x0, 0x0, 0x0, 0x400000000000, 0xf00000000000, 0x0, 0x0, 0x0, 0xf00000000000, 0x0, 0x0, 0x0, 0x7f0000, 0x0, 0x7f0, 0x0, 0x0, 0xffffffff00000000, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffff, 0x0, 0x0, 0x0, 0x0]);
+//896 bytes
+enum prependTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x40], [ 0x100, 0x80, 0xc00], [ 0x101010101010100, 0x101010101010102, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000100000000, 0x3, 0x40000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005, 0x0, 0x800070000, 0xa000000090000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x0, 0x0, 0x20000000, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30000, 0x400000000, 0x0, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x2000000000000000, 0x2000, 0x0, 0x0, 0x0, 0xc, 0x8000000000000000, 0x2, 0x0, 0x0, 0x400000000000000, 0x0, 0x3f0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
+//1280 bytes
+enum controlTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x68], [ 0x100, 0x120, 0xe00], [ 0x302020202020100, 0x206050202020402, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020207, 0x202020202020202, 0x202020202020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000100010000, 0x1000200010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010003, 0x1000100010001, 0x1000100010004, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x6000500010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010007, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010008, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100090001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0xc000c000b000a, 0xc000c000c000c, 0xc000c000c000c, 0xc000c000c000c, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0xffffdbff, 0x8000000000000000, 0x2000ffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000000, 0x0, 0x0, 0x0, 0x4000, 0x0, 0x0, 0x0, 0x7f000000c800, 0xffff00000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8000000000000000, 0x0, 0x0, 0x0, 0xfff000000000000, 0xffff000000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf00000000, 0x0, 0x0, 0x7f8000000000000, 0x0, 0x0, 0xffffffff, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0xffff000000000000, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0]);
+//1856 bytes
+enum spacingMarkTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x58], [ 0x100, 0xe0, 0x2400], [ 0x101020101010100, 0x105010104010103, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3000200010000, 0x7000600050004, 0x8, 0x9000000000000, 0xc000b000a0000, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x110010000f000e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15001400130012, 0x19001800170016, 0x1c001b001a, 0x20001f001e001d, 0x0, 0x0, 0x0, 0x21000000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x220000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc800000000000008, 0xde01, 0x800000000000000c, 0x1981, 0xc000000000000008, 0x1, 0xc000000000000008, 0x1a01, 0xc, 0x1981, 0x8000000000000000, 0x1dc6, 0xe, 0x1e, 0x400000000000000c, 0x8000000000d9b, 0x800000000000000c, 0x1dc1, 0xc, 0xc00007f030000, 0x8000000000000, 0x0, 0x8000000000000, 0x0, 0xc000000000000000, 0x8000000000000000, 0x0, 0x0, 0x1802000000000000, 0xc00000, 0x10, 0x0, 0x10000000200000, 0x0, 0xc040000000000000, 0x1bf, 0x1fb0e7800000000, 0x0, 0x0, 0x0, 0x6000000, 0x7e00000a00000, 0x0, 0x0, 0xe800000000000010, 0x1b, 0x4c200000004, 0xc5c8000000000, 0x300ff000000000, 0x0, 0x0, 0x80000200000000, 0x9800000000, 0x0, 0xfff0000000000003, 0xf, 0x0, 0xc0000, 0xcc30000000000008, 0x1, 0x19800000000000, 0x2000, 0x0, 0x20c80000000000, 0x0, 0x0, 0x0, 0x16d800000000, 0x5, 0x0, 0x187000000000004, 0x0, 0x100000000000, 0x60, 0x8038000000000004, 0x4001, 0x2c700000000000, 0x0, 0x0, 0x700000000, 0x800000000000000c, 0xc0000399e, 0x0, 0x0, 0xe0000000000000, 0x23, 0x5a06000000000000, 0x2, 0x0, 0x0, 0x4f03000000000000, 0x0, 0x5807000000000000, 0x0, 0x40d00000000000, 0x0, 0x4000000000, 0x0, 0x0, 0x0, 0x100700000000000, 0x0, 0x0, 0x0, 0x21be000000000000, 0x5, 0x0, 0x10f00e0000, 0x200000000000000, 0x1800000, 0x800000, 0x0, 0x4000800000000000, 0x0, 0x12020000000000, 0x0, 0x0, 0x0, 0x587c00, 0x0, 0x0, 0x0, 0x0, 0x60000000000000, 0xc030000000000008, 0x2, 0x0, 0x0, 0x0, 0xfffffffffffe0000, 0xff, 0x3000000000000, 0x0, 0x204000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
+//3488 bytes
+enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x88], [ 0x100, 0x1a0, 0x4b00], [ 0x402030202020100, 0xa09080207020605, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x20202020202020b, 0x202020202020202, 0x202020202020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000000000000, 0x5000400030002, 0x9000800070006, 0xd000c000b000a, 0xf00000000000e, 0x10000000000000, 0x14001300120011, 0x160015, 0x17, 0x0, 0x0, 0x190018, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b00000000, 0x1f001e001d001c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20000000000000, 0x22002100000000, 0x25002400230000, 0x0, 0x2600000000, 0x29002800270000, 0x2d002c002b002a, 0x310030002f002e, 0x3400330032, 0x38003700360035, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x3b003a00000000, 0x3c000000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x3e000000000000, 0x40003f0000, 0x0, 0x4100000000, 0x0, 0x43003b0042, 0x44, 0x460045, 0x0, 0x47000000000000, 0x0, 0x0, 0x0, 0x490048, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x3f8, 0x0, 0x0, 0x0, 0xbffffffffffe0000, 0xb6, 0x7ff0000, 0x10000fffff800, 0x0, 0x3d9f9fc00000, 0xffff000000020000, 0x7ff, 0x1ffc000000000, 0x200ff80000000000, 0x3eeffbc00000, 0xe000000, 0xff000000, 0xfffffffbfffffc00, 0x1400000000000007, 0xc00fe21fe, 0x5000000000000002, 0x4000000c0080201e, 0x1000000000000006, 0x23000000023986, 0x1000000000000006, 0xfc00000c000021be, 0xd000000000000002, 0xc00e0201e, 0x4000000000000004, 0x802001, 0xd000000000000011, 0xc00603dc1, 0x9000000000000002, 0xc00603044, 0x5800000000000003, 0xc0080201e, 0x2, 0x805c8400, 0x7f2000000000000, 0x7f80, 0x1ff2000000000000, 0x7f00, 0x2a0000003000000, 0x7ffe000000000000, 0x1ffffffffeffe0df, 0x40, 0x66fde00000000000, 0x1e0001c3000000, 0x20002064, 0x0, 0x0, 0xe0000000, 0x0, 0x0, 0xc0000001c0000, 0xc0000000c0000, 0x3fb0000000000000, 0x200ffe40, 0xb800, 0x0, 0x20000000060, 0x0, 0xe04018700000000, 0x0, 0x0, 0x0, 0x9800000, 0x9ff81fe57f400000, 0xffff000000000000, 0x7fff, 0x17f000000000000f, 0xff80000000004, 0x3b3c00000003, 0x3a34000000000, 0xcff00000000000, 0x0, 0x0, 0x31021fdfff70000, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x1000, 0x0, 0x0, 0x1ffffffff0000, 0x0, 0x0, 0x0, 0x3800000000000, 0x0, 0x8000000000000000, 0x0, 0xffffffff00000000, 0xfc0000000000, 0x0, 0x6000000, 0x0, 0x0, 0x3ff7800000000000, 0xc0000000, 0x3000000000000, 0x106000000844, 0x0, 0x0, 0x8003ffff00000030, 0x3fc000000000, 0x3ff80, 0x33c8000000000007, 0x2000000000, 0x667e0000000000, 0x1000000000001008, 0xc19d000000000000, 0x40300000000002, 0x0, 0x0, 0x0, 0x212000000000, 0x40000000, 0x0, 0x0, 0x0, 0xffff0000ffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0000000, 0x0, 0x0, 0x0, 0x0, 0x2000000000000000, 0x0, 0x0, 0x0, 0x100000000, 0x0, 0x7c0000000000000, 0x0, 0x0, 0x870000000000f06e, 0x0, 0x0, 0x6000000000, 0xf000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180000000000, 0xe000000000000000, 0x0, 0x1ffc0, 0x3c, 0x0, 0xff00000000000002, 0x801900000000007f, 0x678000000000003, 0x4, 0x1fef8000000007, 0x8000000000000, 0x7fc0000000000003, 0x9e00, 0x40d3800000000000, 0x2, 0x0, 0x7f880000000, 0x5800000000000003, 0x1f1fc000800001, 0x0, 0x0, 0xff00000000000000, 0x4000005c, 0xa5f9000000000000, 0xd, 0x0, 0x0, 0xb03c800000000000, 0x30000001, 0xa7f8000000000000, 0x1, 0xbf280000000000, 0x0, 0xfbce0000000, 0x0, 0x0, 0x0, 0x6ff800000000000, 0x0, 0x0, 0x0, 0x5801000000000000, 0x8, 0x0, 0x10cf00000, 0x79f80000000007fe, 0xe7e0080, 0x37ffc00, 0x0, 0xbf7f000000000000, 0x0, 0x6dfcfffffc0000, 0x0, 0xb47e000000000000, 0xbf, 0xa30000, 0x0, 0x0, 0x0, 0x0, 0x18000000000000, 0x7c0000000000003, 0x5, 0x0, 0x0, 0x0, 0x3fff81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f000000000000, 0x7f000000000000, 0x0, 0x0, 0x0, 0x0, 0x8000, 0x78000, 0x1000000000, 0x0, 0x0, 0x60000000, 0x0, 0xffff3fffffffffff, 0x7f, 0x0, 0x0, 0x0, 0xf807c3a000000000, 0x3c0000000fe7, 0x0, 0x0, 0x1c, 0x0, 0x0, 0xf87fffffffffffff, 0x201fffffffffff, 0xfffef8000010, 0x0, 0x7dbf9ffff7f, 0x0, 0x8000, 0x0, 0x0, 0x0, 0x400000000000, 0xf00000000000, 0x0, 0x0, 0x0, 0xf00000000000, 0x0, 0x0, 0x0, 0x7f0000, 0x0, 0x7f0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf800000000000000, 0xffffffff00000000, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffff, 0x0, 0x0, 0x0, 0x0]);
+//1344 bytes
+enum Extended_PictographicTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x48], [ 0x100, 0xa0, 0x1800], [ 0x202020202020100, 0x302020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000100010000, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x4000100030002, 0x8000700060005, 0xa000100090001, 0x1000100010001, 0x1000c0001000b, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x10000f000e000d, 0x1300120011000d, 0x1000d00150014, 0x16000d000d000d, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x0, 0x0, 0x420000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000000000000000, 0x200, 0x0, 0x0, 0x200000400000000, 0x0, 0x60003f00000, 0x0, 0x1000c000000, 0x0, 0x100, 0x70ffe0000008000, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x400c0000000000, 0x7800000000000001, 0xfffffffffff7ffbf, 0xffffffffffffffff, 0xffffffffffff003f, 0xffffffffffffffff, 0x1801022057ff3f, 0xf800b85090, 0x8001000200e00000, 0x0, 0x30000000000000, 0x0, 0x0, 0x0, 0x180000e0, 0x210000, 0x0, 0x0, 0x2001000000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2800000, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x80000000e000, 0xc003f00000000000, 0xffffe00007fe4000, 0x3fffffffff, 0xf7fc80000400fffe, 0xfffffffffffffe00, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x7ffffffffffffff, 0x3fffffffffffffff, 0xffffffffffffffc0, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0xfff0000000000000, 0x0, 0xffffffffffe00000, 0xf000, 0xfc00ff00, 0xffffc0000000ff00, 0xffffffffffffffff, 0xf7fffffffffff000, 0xffffffffffffffbf, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x3fffffffffffffff, 0x0, 0x0, 0x0, 0x0]);
}
diff --git a/libphobos/src/std/math/exponential.d b/libphobos/src/std/math/exponential.d
index 66f4b8a..fd1ff24 100644
--- a/libphobos/src/std/math/exponential.d
+++ b/libphobos/src/std/math/exponential.d
@@ -39,7 +39,8 @@ static import core.stdc.math;
version (DigitalMars)
{
- version = INLINE_YL2X; // x87 has opcodes for these
+ version (OSX) { } // macOS 13 (M1) has issues emulating instruction
+ else version = INLINE_YL2X; // x87 has opcodes for these
}
version (D_InlineAsm_X86) version = InlineAsm_X86_Any;
@@ -2862,7 +2863,7 @@ float ldexp(float n, int exp) @safe pure nothrow @nogc { return core.math.ldex
private
{
- // Coefficients shared across log(), log2(), log10().
+ // Coefficients shared across log(), log2(), log10(), log1p().
template LogCoeffs(T)
{
import std.math : floatTraits, RealFormat;
@@ -3022,6 +3023,25 @@ private
alias log2Q = logQ;
// Coefficients for log(1 + x) = x - x^^2/2 + x^^3 P(x)/Q(x)
+ static immutable double[7] logp1P = [
+ 2.0039553499201281259648E1,
+ 5.7112963590585538103336E1,
+ 6.0949667980987787057556E1,
+ 2.9911919328553073277375E1,
+ 6.5787325942061044846969E0,
+ 4.9854102823193375972212E-1,
+ 4.5270000862445199635215E-5,
+ ];
+ static immutable double[7] logp1Q = [
+ 1.0000000000000000000000E0,
+ 6.0118660497603843919306E1,
+ 2.1642788614495947685003E2,
+ 3.0909872225312059774938E2,
+ 2.2176239823732856465394E2,
+ 8.3047565967967209469434E1,
+ 1.5062909083469192043167E1,
+ ];
+
static immutable double[7] log10P = [
1.98892446572874072159E1,
5.67349287391754285487E1,
@@ -3070,6 +3090,26 @@ private
7.0376836292E-2,
];
+ // Coefficients for log(1 + x) = x - x^^2/2 + x^^3 P(x)/Q(x)
+ static immutable float[7] logp1P = [
+ 2.0039553499E1,
+ 5.7112963590E1,
+ 6.0949667980E1,
+ 2.9911919328E1,
+ 6.5787325942E0,
+ 4.9854102823E-1,
+ 4.5270000862E-5,
+ ];
+ static immutable float[7] logp1Q = [
+ 1.00000000000E0,
+ 6.01186604976E1,
+ 2.16427886144E2,
+ 3.09098722253E2,
+ 2.21762398237E2,
+ 8.30475659679E1,
+ 1.50629090834E1,
+ ];
+
// log2 and log10 uses the same coefficients as log.
alias log2P = logP;
alias log10P = logP;
@@ -3135,7 +3175,7 @@ real log(ulong x) @safe pure nothrow @nogc { return log(cast(real) x); }
assert(feqrel(log(E), 1) >= real.mant_dig - 1);
}
-private T logImpl(T)(T x) @safe pure nothrow @nogc
+private T logImpl(T, bool LOG1P = false)(T x) @safe pure nothrow @nogc
{
import std.math.constants : SQRT1_2;
import std.math.algebraic : poly;
@@ -3145,6 +3185,12 @@ private T logImpl(T)(T x) @safe pure nothrow @nogc
alias coeffs = LogCoeffs!T;
alias F = floatTraits!T;
+ static if (LOG1P)
+ {
+ const T xm1 = x;
+ x = x + 1.0;
+ }
+
static if (F.realFormat == RealFormat.ieeeExtended ||
F.realFormat == RealFormat.ieeeExtended53 ||
F.realFormat == RealFormat.ieeeQuadruple)
@@ -3219,11 +3265,28 @@ private T logImpl(T)(T x) @safe pure nothrow @nogc
if (x < SQRT1_2)
{
exp -= 1;
- x = 2.0 * x - 1.0;
+ static if (LOG1P)
+ {
+ if (exp != 0)
+ x = 2.0 * x - 1.0;
+ else
+ x = xm1;
+ }
+ else
+ x = 2.0 * x - 1.0;
+
}
else
{
- x = x - 1.0;
+ static if (LOG1P)
+ {
+ if (exp != 0)
+ x = x - 1.0;
+ else
+ x = xm1;
+ }
+ else
+ x = x - 1.0;
}
z = x * x;
static if (F.realFormat == RealFormat.ieeeSingle)
@@ -3241,6 +3304,84 @@ private T logImpl(T)(T x) @safe pure nothrow @nogc
return z;
}
+@safe @nogc nothrow unittest
+{
+ import std.math : floatTraits, RealFormat;
+ import std.meta : AliasSeq;
+
+ static void testLog(T)(T[2][] vals)
+ {
+ import std.math.operations : isClose;
+ import std.math.traits : isNaN;
+ foreach (ref pair; vals)
+ {
+ if (isNaN(pair[1]))
+ assert(isNaN(log(pair[0])));
+ else
+ assert(isClose(log(pair[0]), pair[1]));
+ }
+ }
+ static foreach (F; AliasSeq!(float, double, real))
+ {{
+ F[2][24] vals = [
+ [F(1), F(0x0p+0)], [F(2), F(0x1.62e42fefa39ef358p-1)],
+ [F(4), F(0x1.62e42fefa39ef358p+0)], [F(8), F(0x1.0a2b23f3bab73682p+1)],
+ [F(16), F(0x1.62e42fefa39ef358p+1)], [F(32), F(0x1.bb9d3beb8c86b02ep+1)],
+ [F(64), F(0x1.0a2b23f3bab73682p+2)], [F(128), F(0x1.3687a9f1af2b14ecp+2)],
+ [F(256), F(0x1.62e42fefa39ef358p+2)], [F(512), F(0x1.8f40b5ed9812d1c2p+2)],
+ [F(1024), F(0x1.bb9d3beb8c86b02ep+2)], [F(2048), F(0x1.e7f9c1e980fa8e98p+2)],
+ [F(3), F(0x1.193ea7aad030a976p+0)], [F(5), F(0x1.9c041f7ed8d336bp+0)],
+ [F(7), F(0x1.f2272ae325a57546p+0)], [F(15), F(0x1.5aa16394d481f014p+1)],
+ [F(17), F(0x1.6aa6bc1fa7f79cfp+1)], [F(31), F(0x1.b78ce48912b59f12p+1)],
+ [F(33), F(0x1.bf8d8f4d5b8d1038p+1)], [F(63), F(0x1.09291e8e3181b20ep+2)],
+ [F(65), F(0x1.0b292939429755ap+2)], [F(-0), -F.infinity], [F(0), -F.infinity],
+ [F(10000), F(0x1.26bb1bbb5551582ep+3)],
+ ];
+ testLog(vals);
+ }}
+ {
+ float[2][16] vals = [
+ [float.nan, float.nan],[-float.nan, float.nan],
+ [float.infinity, float.infinity], [-float.infinity, float.nan],
+ [float.min_normal, -0x1.5d58ap+6f], [-float.min_normal, float.nan],
+ [float.max, 0x1.62e43p+6f], [-float.max, float.nan],
+ [float.min_normal / 2, -0x1.601e68p+6f], [-float.min_normal / 2, float.nan],
+ [float.max / 2, 0x1.601e68p+6f], [-float.max / 2, float.nan],
+ [float.min_normal / 3, -0x1.61bd9ap+6f], [-float.min_normal / 3, float.nan],
+ [float.max / 3, 0x1.5e7f36p+6f], [-float.max / 3, float.nan],
+ ];
+ testLog(vals);
+ }
+ {
+ double[2][16] vals = [
+ [double.nan, double.nan],[-double.nan, double.nan],
+ [double.infinity, double.infinity], [-double.infinity, double.nan],
+ [double.min_normal, -0x1.6232bdd7abcd2p+9], [-double.min_normal, double.nan],
+ [double.max, 0x1.62e42fefa39efp+9], [-double.max, double.nan],
+ [double.min_normal / 2, -0x1.628b76e3a7b61p+9], [-double.min_normal / 2, double.nan],
+ [double.max / 2, 0x1.628b76e3a7b61p+9], [-double.max / 2, double.nan],
+ [double.min_normal / 3, -0x1.62bf5d2b81354p+9], [-double.min_normal / 3, double.nan],
+ [double.max / 3, 0x1.6257909bce36ep+9], [-double.max / 3, double.nan],
+ ];
+ testLog(vals);
+ }
+ alias F = floatTraits!real;
+ static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple)
+ {{
+ real[2][16] vals = [
+ [real.nan, real.nan],[-real.nan, real.nan],
+ [real.infinity, real.infinity], [-real.infinity, real.nan],
+ [real.min_normal, -0x1.62d918ce2421d66p+13L], [-real.min_normal, real.nan],
+ [real.max, 0x1.62e42fefa39ef358p+13L], [-real.max, real.nan],
+ [real.min_normal / 2, -0x1.62dea45ee3e064dcp+13L], [-real.min_normal / 2, real.nan],
+ [real.max / 2, 0x1.62dea45ee3e064dcp+13L], [-real.max / 2, real.nan],
+ [real.min_normal / 3, -0x1.62e1e2c3617857e6p+13L], [-real.min_normal / 3, real.nan],
+ [real.max / 3, 0x1.62db65fa664871d2p+13L], [-real.max / 3, real.nan],
+ ];
+ testLog(vals);
+ }}
+}
+
/**************************************
* Calculate the base-10 logarithm of x.
*
@@ -3296,6 +3437,14 @@ real log10(ulong x) @safe pure nothrow @nogc { return log10(cast(real) x); }
assert(fabs(log10(1000.0L) - 3) < .000001);
}
+@safe pure nothrow @nogc unittest
+{
+ import std.math.algebraic : fabs;
+
+ assert(fabs(log10(1000.0) - 3) < .000001);
+ assert(fabs(log10(1000.0f) - 3) < .000001);
+}
+
private T log10Impl(T)(T x) @safe pure nothrow @nogc
{
import std.math.constants : SQRT1_2;
@@ -3404,6 +3553,84 @@ Ldone:
return z;
}
+@safe @nogc nothrow unittest
+{
+ import std.math : floatTraits, RealFormat;
+ import std.meta : AliasSeq;
+
+ static void testLog10(T)(T[2][] vals)
+ {
+ import std.math.operations : isClose;
+ import std.math.traits : isNaN;
+ foreach (ref pair; vals)
+ {
+ if (isNaN(pair[1]))
+ assert(isNaN(log10(pair[0])));
+ else
+ assert(isClose(log10(pair[0]), pair[1]));
+ }
+ }
+ static foreach (F; AliasSeq!(float, double, real))
+ {{
+ F[2][24] vals = [
+ [F(1), F(0x0p+0)], [F(2), F(0x1.34413509f79fef32p-2)],
+ [F(4), F(0x1.34413509f79fef32p-1)], [F(8), F(0x1.ce61cf8ef36fe6cap-1)],
+ [F(16), F(0x1.34413509f79fef32p+0)], [F(32), F(0x1.8151824c7587eafep+0)],
+ [F(64), F(0x1.ce61cf8ef36fe6cap+0)], [F(128), F(0x1.0db90e68b8abf14cp+1)],
+ [F(256), F(0x1.34413509f79fef32p+1)], [F(512), F(0x1.5ac95bab3693ed18p+1)],
+ [F(1024), F(0x1.8151824c7587eafep+1)], [F(2048), F(0x1.a7d9a8edb47be8e4p+1)],
+ [F(3), F(0x1.e8927964fd5fd08cp-2)], [F(5), F(0x1.65df657b04300868p-1)],
+ [F(7), F(0x1.b0b0b0b78cc3f296p-1)], [F(15), F(0x1.2d145116c16ff856p+0)],
+ [F(17), F(0x1.3afeb354b7d9731ap+0)], [F(31), F(0x1.7dc9e145867e62eap+0)],
+ [F(33), F(0x1.84bd545e4baeddp+0)], [F(63), F(0x1.cca1950e4511e192p+0)],
+ [F(65), F(0x1.d01b16f9433cf7b8p+0)], [F(-0), -F.infinity], [F(0), -F.infinity],
+ [F(10000), F(0x1p+2)],
+ ];
+ testLog10(vals);
+ }}
+ {
+ float[2][16] vals = [
+ [float.nan, float.nan],[-float.nan, float.nan],
+ [float.infinity, float.infinity], [-float.infinity, float.nan],
+ [float.min_normal, -0x1.2f703p+5f], [-float.min_normal, float.nan],
+ [float.max, 0x1.344136p+5f], [-float.max, float.nan],
+ [float.min_normal / 2, -0x1.31d8b2p+5f], [-float.min_normal / 2, float.nan],
+ [float.max / 2, 0x1.31d8b2p+5f], [-float.max / 2, float.nan],
+ [float.min_normal / 3, -0x1.334156p+5f], [-float.min_normal / 3, float.nan],
+ [float.max / 3, 0x1.30701p+5f], [-float.max / 3, float.nan],
+ ];
+ testLog10(vals);
+ }
+ {
+ double[2][16] vals = [
+ [double.nan, double.nan],[-double.nan, double.nan],
+ [double.infinity, double.infinity], [-double.infinity, double.nan],
+ [double.min_normal, -0x1.33a7146f72a42p+8], [-double.min_normal, double.nan],
+ [double.max, 0x1.34413509f79ffp+8], [-double.max, double.nan],
+ [double.min_normal / 2, -0x1.33f424bcb522p+8], [-double.min_normal / 2, double.nan],
+ [double.max / 2, 0x1.33f424bcb522p+8], [-double.max / 2, double.nan],
+ [double.min_normal / 3, -0x1.3421390dcbe37p+8], [-double.min_normal / 3, double.nan],
+ [double.max / 3, 0x1.33c7106b9e609p+8], [-double.max / 3, double.nan],
+ ];
+ testLog10(vals);
+ }
+ alias F = floatTraits!real;
+ static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple)
+ {{
+ real[2][16] vals = [
+ [real.nan, real.nan],[-real.nan, real.nan],
+ [real.infinity, real.infinity], [-real.infinity, real.nan],
+ [real.min_normal, -0x1.343793004f503232p+12L], [-real.min_normal, real.nan],
+ [real.max, 0x1.34413509f79fef32p+12L], [-real.max, real.nan],
+ [real.min_normal / 2, -0x1.343c6405237810b2p+12L], [-real.min_normal / 2, real.nan],
+ [real.max / 2, 0x1.343c6405237810b2p+12L], [-real.max / 2, real.nan],
+ [real.min_normal / 3, -0x1.343f354a34e427bp+12L], [-real.min_normal / 3, real.nan],
+ [real.max / 3, 0x1.343992c0120bf9b2p+12L], [-real.max / 3, real.nan],
+ ];
+ testLog10(vals);
+ }}
+}
+
/**
* Calculates the natural logarithm of 1 + x.
*
@@ -3476,6 +3703,9 @@ real log1p(ulong x) @safe pure nothrow @nogc { return log1p(cast(real) x); }
private T log1pImpl(T)(T x) @safe pure nothrow @nogc
{
import std.math.traits : isNaN, isInfinity, signbit;
+ import std.math.algebraic : poly;
+ import std.math.constants : SQRT1_2, SQRT2;
+ import std.math : floatTraits, RealFormat;
// Special cases.
if (isNaN(x) || x == 0.0)
@@ -3487,7 +3717,104 @@ private T log1pImpl(T)(T x) @safe pure nothrow @nogc
if (x < -1.0)
return T.nan;
- return logImpl(x + 1.0);
+ alias F = floatTraits!T;
+ static if (F.realFormat == RealFormat.ieeeSingle ||
+ F.realFormat == RealFormat.ieeeDouble)
+ {
+ // When the input is within the range 1/sqrt(2) <= x+1 <= sqrt(2), compute
+ // log1p inline. Forwarding to log() would otherwise result in inaccuracies.
+ const T xp1 = x + 1.0;
+ if (xp1 >= SQRT1_2 && xp1 <= SQRT2)
+ {
+ alias coeffs = LogCoeffs!T;
+
+ T px = poly(x, coeffs.logp1P);
+ T qx = poly(x, coeffs.logp1Q);
+ const T xx = x * x;
+ qx = x + ((cast(T) -0.5) * xx + x * (xx * px / qx));
+ return qx;
+ }
+ }
+
+ return logImpl!(T, true)(x);
+}
+
+@safe @nogc nothrow unittest
+{
+ import std.math : floatTraits, RealFormat;
+ import std.meta : AliasSeq;
+
+ static void testLog1p(T)(T[2][] vals)
+ {
+ import std.math.operations : isClose;
+ import std.math.traits : isNaN;
+ foreach (ref pair; vals)
+ {
+ if (isNaN(pair[1]))
+ assert(isNaN(log1p(pair[0])));
+ else
+ assert(isClose(log1p(pair[0]), pair[1]));
+ }
+ }
+ static foreach (F; AliasSeq!(float, double, real))
+ {{
+ F[2][24] vals = [
+ [F(1), F(0x1.62e42fefa39ef358p-1)], [F(2), F(0x1.193ea7aad030a976p+0)],
+ [F(4), F(0x1.9c041f7ed8d336bp+0)], [F(8), F(0x1.193ea7aad030a976p+1)],
+ [F(16), F(0x1.6aa6bc1fa7f79cfp+1)], [F(32), F(0x1.bf8d8f4d5b8d1038p+1)],
+ [F(64), F(0x1.0b292939429755ap+2)], [F(128), F(0x1.37072a9b5b6cb31p+2)],
+ [F(256), F(0x1.63241004e9010ad8p+2)], [F(512), F(0x1.8f60adf041bde2a8p+2)],
+ [F(1024), F(0x1.bbad39ebe1cc08b6p+2)], [F(2048), F(0x1.e801c1698ba4395cp+2)],
+ [F(3), F(0x1.62e42fefa39ef358p+0)], [F(5), F(0x1.cab0bfa2a2002322p+0)],
+ [F(7), F(0x1.0a2b23f3bab73682p+1)], [F(15), F(0x1.62e42fefa39ef358p+1)],
+ [F(17), F(0x1.71f7b3a6b918664cp+1)], [F(31), F(0x1.bb9d3beb8c86b02ep+1)],
+ [F(33), F(0x1.c35fc81b90df59c6p+1)], [F(63), F(0x1.0a2b23f3bab73682p+2)],
+ [F(65), F(0x1.0c234da4a23a6686p+2)], [F(-0), F(-0x0p+0)], [F(0), F(0x0p+0)],
+ [F(10000), F(0x1.26bbed6fbd84182ep+3)],
+ ];
+ testLog1p(vals);
+ }}
+ {
+ float[2][16] vals = [
+ [float.nan, float.nan],[-float.nan, float.nan],
+ [float.infinity, float.infinity], [-float.infinity, float.nan],
+ [float.min_normal, 0x1p-126f], [-float.min_normal, -0x1p-126f],
+ [float.max, 0x1.62e43p+6f], [-float.max, float.nan],
+ [float.min_normal / 2, 0x0.8p-126f], [-float.min_normal / 2, -0x0.8p-126f],
+ [float.max / 2, 0x1.601e68p+6f], [-float.max / 2, float.nan],
+ [float.min_normal / 3, 0x0.555556p-126f], [-float.min_normal / 3, -0x0.555556p-126f],
+ [float.max / 3, 0x1.5e7f36p+6f], [-float.max / 3, float.nan],
+ ];
+ testLog1p(vals);
+ }
+ {
+ double[2][16] vals = [
+ [double.nan, double.nan],[-double.nan, double.nan],
+ [double.infinity, double.infinity], [-double.infinity, double.nan],
+ [double.min_normal, 0x1p-1022], [-double.min_normal, -0x1p-1022],
+ [double.max, 0x1.62e42fefa39efp+9], [-double.max, double.nan],
+ [double.min_normal / 2, 0x0.8p-1022], [-double.min_normal / 2, -0x0.8p-1022],
+ [double.max / 2, 0x1.628b76e3a7b61p+9], [-double.max / 2, double.nan],
+ [double.min_normal / 3, 0x0.5555555555555p-1022], [-double.min_normal / 3, -0x0.5555555555555p-1022],
+ [double.max / 3, 0x1.6257909bce36ep+9], [-double.max / 3, double.nan],
+ ];
+ testLog1p(vals);
+ }
+ alias F = floatTraits!real;
+ static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple)
+ {{
+ real[2][16] vals = [
+ [real.nan, real.nan],[-real.nan, real.nan],
+ [real.infinity, real.infinity], [-real.infinity, real.nan],
+ [real.min_normal, 0x1p-16382L], [-real.min_normal, -0x1p-16382L],
+ [real.max, 0x1.62e42fefa39ef358p+13L], [-real.max, real.nan],
+ [real.min_normal / 2, 0x0.8p-16382L], [-real.min_normal / 2, -0x0.8p-16382L],
+ [real.max / 2, 0x1.62dea45ee3e064dcp+13L], [-real.max / 2, real.nan],
+ [real.min_normal / 3, 0x0.5555555555555556p-16382L], [-real.min_normal / 3, -0x0.5555555555555556p-16382L],
+ [real.max / 3, 0x1.62db65fa664871d2p+13L], [-real.max / 3, real.nan],
+ ];
+ testLog1p(vals);
+ }}
}
/***************************************
@@ -3635,6 +3962,84 @@ Ldone:
return z;
}
+@safe @nogc nothrow unittest
+{
+ import std.math : floatTraits, RealFormat;
+ import std.meta : AliasSeq;
+
+ static void testLog2(T)(T[2][] vals)
+ {
+ import std.math.operations : isClose;
+ import std.math.traits : isNaN;
+ foreach (ref pair; vals)
+ {
+ if (isNaN(pair[1]))
+ assert(isNaN(log2(pair[0])));
+ else
+ assert(isClose(log2(pair[0]), pair[1]));
+ }
+ }
+ static foreach (F; AliasSeq!(float, double, real))
+ {{
+ F[2][24] vals = [
+ [F(1), F(0x0p+0)], [F(2), F(0x1p+0)],
+ [F(4), F(0x1p+1)], [F(8), F(0x1.8p+1)],
+ [F(16), F(0x1p+2)], [F(32), F(0x1.4p+2)],
+ [F(64), F(0x1.8p+2)], [F(128), F(0x1.cp+2)],
+ [F(256), F(0x1p+3)], [F(512), F(0x1.2p+3)],
+ [F(1024), F(0x1.4p+3)], [F(2048), F(0x1.6p+3)],
+ [F(3), F(0x1.95c01a39fbd687ap+0)], [F(5), F(0x1.2934f0979a3715fcp+1)],
+ [F(7), F(0x1.675767f54042cd9ap+1)], [F(15), F(0x1.f414fdb4982259ccp+1)],
+ [F(17), F(0x1.0598fdbeb244c5ap+2)], [F(31), F(0x1.3d118d66c4d4e554p+2)],
+ [F(33), F(0x1.42d75a6eb1dfb0e6p+2)], [F(63), F(0x1.7e8bc1179e0caa9cp+2)],
+ [F(65), F(0x1.816e79685c2d2298p+2)], [F(-0), -F.infinity], [F(0), -F.infinity],
+ [F(10000), F(0x1.a934f0979a3715fcp+3)],
+ ];
+ testLog2(vals);
+ }}
+ {
+ float[2][16] vals = [
+ [float.nan, float.nan],[-float.nan, float.nan],
+ [float.infinity, float.infinity], [-float.infinity, float.nan],
+ [float.min_normal, -0x1.f8p+6f], [-float.min_normal, float.nan],
+ [float.max, 0x1p+7f], [-float.max, float.nan],
+ [float.min_normal / 2, -0x1.fcp+6f], [-float.min_normal / 2, float.nan],
+ [float.max / 2, 0x1.fcp+6f], [-float.max / 2, float.nan],
+ [float.min_normal / 3, -0x1.fe57p+6f], [-float.min_normal / 3, float.nan],
+ [float.max / 3, 0x1.f9a9p+6f], [-float.max / 3, float.nan],
+ ];
+ testLog2(vals);
+ }
+ {
+ double[2][16] vals = [
+ [double.nan, double.nan],[-double.nan, double.nan],
+ [double.infinity, double.infinity], [-double.infinity, double.nan],
+ [double.min_normal, -0x1.ffp+9], [-double.min_normal, double.nan],
+ [double.max, 0x1p+10], [-double.max, double.nan],
+ [double.min_normal / 2, -0x1.ff8p+9], [-double.min_normal / 2, double.nan],
+ [double.max / 2, 0x1.ff8p+9], [-double.max / 2, double.nan],
+ [double.min_normal / 3, -0x1.ffcae00d1cfdfp+9], [-double.min_normal / 3, double.nan],
+ [double.max / 3, 0x1.ff351ff2e3021p+9], [-double.max / 3, double.nan],
+ ];
+ testLog2(vals);
+ }
+ alias F = floatTraits!real;
+ static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple)
+ {{
+ real[2][16] vals = [
+ [real.nan, real.nan],[-real.nan, real.nan],
+ [real.infinity, real.infinity], [-real.infinity, real.nan],
+ [real.min_normal, -0x1.fffp+13L], [-real.min_normal, real.nan],
+ [real.max, 0x1p+14L], [-real.max, real.nan],
+ [real.min_normal / 2, -0x1.fff8p+13L], [-real.min_normal / 2, real.nan],
+ [real.max / 2, 0x1.fff8p+13L], [-real.max / 2, real.nan],
+ [real.min_normal / 3, -0x1.fffcae00d1cfdeb4p+13L], [-real.min_normal / 3, real.nan],
+ [real.max / 3, 0x1.fff351ff2e30214cp+13L], [-real.max / 3, real.nan],
+ ];
+ testLog2(vals);
+ }}
+}
+
/*****************************************
* Extracts the exponent of x as a signed integral value.
*
@@ -3754,6 +4159,84 @@ private T logbImpl(T)(T x) @trusted pure nothrow @nogc
return ilogb(x);
}
+@safe @nogc nothrow unittest
+{
+ import std.math : floatTraits, RealFormat;
+ import std.meta : AliasSeq;
+
+ static void testLogb(T)(T[2][] vals)
+ {
+ import std.math.operations : isClose;
+ import std.math.traits : isNaN;
+ foreach (ref pair; vals)
+ {
+ if (isNaN(pair[1]))
+ assert(isNaN(logb(pair[0])));
+ else
+ assert(isClose(logb(pair[0]), pair[1]));
+ }
+ }
+ static foreach (F; AliasSeq!(float, double, real))
+ {{
+ F[2][24] vals = [
+ [F(1), F(0x0p+0)], [F(2), F(0x1p+0)],
+ [F(4), F(0x1p+1)], [F(8), F(0x1.8p+1)],
+ [F(16), F(0x1p+2)], [F(32), F(0x1.4p+2)],
+ [F(64), F(0x1.8p+2)], [F(128), F(0x1.cp+2)],
+ [F(256), F(0x1p+3)], [F(512), F(0x1.2p+3)],
+ [F(1024), F(0x1.4p+3)], [F(2048), F(0x1.6p+3)],
+ [F(3), F(0x1p+0)], [F(5), F(0x1p+1)],
+ [F(7), F(0x1p+1)], [F(15), F(0x1.8p+1)],
+ [F(17), F(0x1p+2)], [F(31), F(0x1p+2)],
+ [F(33), F(0x1.4p+2)], [F(63), F(0x1.4p+2)],
+ [F(65), F(0x1.8p+2)], [F(-0), -F.infinity], [F(0), -F.infinity],
+ [F(10000), F(0x1.ap+3)],
+ ];
+ testLogb(vals);
+ }}
+ {
+ float[2][16] vals = [
+ [float.nan, float.nan],[-float.nan, float.nan],
+ [float.infinity, float.infinity], [-float.infinity, float.infinity],
+ [float.min_normal, -0x1.f8p+6f], [-float.min_normal, -0x1.f8p+6f],
+ [float.max, 0x1.fcp+6f], [-float.max, 0x1.fcp+6f],
+ [float.min_normal / 2, -0x1.fcp+6f], [-float.min_normal / 2, -0x1.fcp+6f],
+ [float.max / 2, 0x1.f8p+6f], [-float.max / 2, 0x1.f8p+6f],
+ [float.min_normal / 3, -0x1p+7f], [-float.min_normal / 3, -0x1p+7f],
+ [float.max / 3, 0x1.f8p+6f], [-float.max / 3, 0x1.f8p+6f],
+ ];
+ testLogb(vals);
+ }
+ {
+ double[2][16] vals = [
+ [double.nan, double.nan],[-double.nan, double.nan],
+ [double.infinity, double.infinity], [-double.infinity, double.infinity],
+ [double.min_normal, -0x1.ffp+9], [-double.min_normal, -0x1.ffp+9],
+ [double.max, 0x1.ff8p+9], [-double.max, 0x1.ff8p+9],
+ [double.min_normal / 2, -0x1.ff8p+9], [-double.min_normal / 2, -0x1.ff8p+9],
+ [double.max / 2, 0x1.ffp+9], [-double.max / 2, 0x1.ffp+9],
+ [double.min_normal / 3, -0x1p+10], [-double.min_normal / 3, -0x1p+10],
+ [double.max / 3, 0x1.ffp+9], [-double.max / 3, 0x1.ffp+9],
+ ];
+ testLogb(vals);
+ }
+ alias F = floatTraits!real;
+ static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple)
+ {{
+ real[2][16] vals = [
+ [real.nan, real.nan],[-real.nan, real.nan],
+ [real.infinity, real.infinity], [-real.infinity, real.infinity],
+ [real.min_normal, -0x1.fffp+13L], [-real.min_normal, -0x1.fffp+13L],
+ [real.max, 0x1.fff8p+13L], [-real.max, 0x1.fff8p+13L],
+ [real.min_normal / 2, -0x1.fff8p+13L], [-real.min_normal / 2, -0x1.fff8p+13L],
+ [real.max / 2, 0x1.fffp+13L], [-real.max / 2, 0x1.fffp+13L],
+ [real.min_normal / 3, -0x1p+14L], [-real.min_normal / 3, -0x1p+14L],
+ [real.max / 3, 0x1.fffp+13L], [-real.max / 3, 0x1.fffp+13L],
+ ];
+ testLogb(vals);
+ }}
+}
+
/*************************************
* Efficiently calculates x * 2$(SUPERSCRIPT n).
*
diff --git a/libphobos/src/std/net/curl.d b/libphobos/src/std/net/curl.d
index 8745bbd..42a34b9 100644
--- a/libphobos/src/std/net/curl.d
+++ b/libphobos/src/std/net/curl.d
@@ -2171,7 +2171,7 @@ private mixin template Protocol()
*
* Example:
* ----
- * import std.net.curl, std.stdio;
+ * import std.net.curl, std.stdio, std.conv;
* auto client = HTTP("dlang.org");
* client.onReceive = (ubyte[] data)
* {
@@ -2817,7 +2817,7 @@ struct HTTP
*
* Example:
* ----
- * import std.net.curl, std.stdio;
+ * import std.net.curl, std.stdio, std.conv;
* auto client = HTTP("dlang.org");
* client.onReceive = (ubyte[] data)
* {
@@ -3054,7 +3054,7 @@ struct HTTP
*
* Example:
* ----
- * import std.net.curl, std.stdio;
+ * import std.net.curl, std.stdio, std.conv;
* auto http = HTTP("http://www.mydomain.com");
* http.onReceive = (ubyte[] data) { writeln(to!(const(char)[])(data)); return data.length; };
* http.postData = [1,2,3,4,5];
@@ -3073,7 +3073,7 @@ struct HTTP
*
* Example:
* ----
- * import std.net.curl, std.stdio;
+ * import std.net.curl, std.stdio, std.conv;
* auto http = HTTP("http://www.mydomain.com");
* http.onReceive = (ubyte[] data) { writeln(to!(const(char)[])(data)); return data.length; };
* http.postData = "The quick....";
@@ -3145,7 +3145,7 @@ struct HTTP
*
* Example:
* ----
- * import std.net.curl, std.stdio;
+ * import std.net.curl, std.stdio, std.conv;
* auto http = HTTP("dlang.org");
* http.onReceive = (ubyte[] data) { writeln(to!(const(char)[])(data)); return data.length; };
* http.onReceiveHeader = (in char[] key, in char[] value) { writeln(key, " = ", value); };
@@ -4551,7 +4551,7 @@ struct Curl
*
* Example:
* ----
- * import std.net.curl, std.stdio;
+ * import std.net.curl, std.stdio, std.conv;
* Curl curl;
* curl.initialize();
* curl.set(CurlOption.url, "http://dlang.org");
diff --git a/libphobos/src/std/process.d b/libphobos/src/std/process.d
index 3eaa283..494910f 100644
--- a/libphobos/src/std/process.d
+++ b/libphobos/src/std/process.d
@@ -2505,7 +2505,7 @@ version (Windows)
import std.exception : collectException;
import std.typecons : tuple;
- TestScript prog = ":Loop\ngoto Loop;";
+ TestScript prog = ":Loop\r\n" ~ "goto Loop";
auto pid = spawnProcess(prog.path);
// Doesn't block longer than one second
@@ -3658,7 +3658,7 @@ string escapeShellCommand(scope const(char[])[] args...) @safe pure
{
args : ["foo bar", "hello"],
windows : `"foo bar" hello`,
- posix : `'foo bar' 'hello'`
+ posix : `'foo bar' hello`
},
{
args : ["foo bar", "hello world"],
@@ -3668,20 +3668,34 @@ string escapeShellCommand(scope const(char[])[] args...) @safe pure
{
args : ["foo bar", "hello", "world"],
windows : `"foo bar" hello world`,
- posix : `'foo bar' 'hello' 'world'`
+ posix : `'foo bar' hello world`
},
{
args : ["foo bar", `'"^\`],
windows : `"foo bar" ^"'\^"^^\\^"`,
posix : `'foo bar' ''\''"^\'`
},
+ {
+ args : ["foo bar", ""],
+ windows : `"foo bar" ^"^"`,
+ posix : `'foo bar' ''`
+ },
+ {
+ args : ["foo bar", "2"],
+ windows : `"foo bar" ^"2^"`,
+ posix : `'foo bar' '2'`
+ },
];
foreach (test; tests)
+ {
+ auto actual = escapeShellCommand(test.args);
version (Windows)
- assert(escapeShellCommand(test.args) == test.windows);
+ string expected = test.windows;
else
- assert(escapeShellCommand(test.args) == test.posix );
+ string expected = test.posix;
+ assert(actual == expected, "\nExpected: " ~ expected ~ "\nGot: " ~ actual);
+ }
}
private string escapeShellCommandString(return scope string command) @safe pure
@@ -3922,6 +3936,37 @@ private char[] escapePosixArgumentImpl(alias allocator)(scope const(char)[] arg)
@safe nothrow
if (is(typeof(allocator(size_t.init)[0] = char.init)))
{
+ bool needQuoting = {
+ import std.ascii : isAlphaNum, isDigit;
+ import std.algorithm.comparison : among;
+
+ // Empty arguments need to be specified as ''
+ if (arg.length == 0)
+ return true;
+ // Arguments ending with digits need to be escaped,
+ // to disambiguate with 1>file redirection syntax
+ if (isDigit(arg[$-1]))
+ return true;
+
+ // Obtained using:
+ // for n in $(seq 1 255) ; do
+ // c=$(printf \\$(printf "%o" $n))
+ // q=$(/bin/printf '%q' "$c")
+ // if [[ "$q" == "$c" ]] ; then printf "%s, " "'$c'" ; fi
+ // done
+ // printf '\n'
+ foreach (char c; arg)
+ if (!isAlphaNum(c) && !c.among('%', '+', ',', '-', '.', '/', ':', '@', ']', '_'))
+ return true;
+ return false;
+ }();
+ if (!needQuoting)
+ {
+ auto buf = allocator(arg.length);
+ buf[] = arg;
+ return buf;
+ }
+
// '\'' means: close quoted part of argument, append an escaped
// single quote, and reopen quotes
@@ -3995,6 +4040,11 @@ version (unittest_burnin)
// Then, test this module with:
// rdmd --main -unittest -version=unittest_burnin process.d
+ import std.file : readText, remove;
+ import std.format : format;
+ import std.path : absolutePath;
+ import std.random : uniform;
+
auto helper = absolutePath("std_process_unittest_helper");
assert(executeShell(helper ~ " hello").output.split("\0")[1..$] == ["hello"], "Helper malfunction");
diff --git a/libphobos/src/std/range/primitives.d b/libphobos/src/std/range/primitives.d
index cdab401..748fde3 100644
--- a/libphobos/src/std/range/primitives.d
+++ b/libphobos/src/std/range/primitives.d
@@ -171,9 +171,9 @@ Returns:
*/
enum bool isInputRange(R) =
is(typeof(R.init) == R)
- && is(ReturnType!((R r) => r.empty) == bool)
+ && is(typeof((R r) { return r.empty; } (R.init)) == bool)
&& (is(typeof((return ref R r) => r.front)) || is(typeof(ref (return ref R r) => r.front)))
- && !is(ReturnType!((R r) => r.front) == void)
+ && !is(typeof((R r) { return r.front; } (R.init)) == void)
&& is(typeof((R r) => r.popFront));
///
@@ -998,7 +998,7 @@ See_Also:
The header of $(MREF std,range) for tutorials on ranges.
*/
enum bool isForwardRange(R) = isInputRange!R
- && is(ReturnType!((R r) => r.save) == R);
+ && is(typeof((R r) { return r.save; } (R.init)) == R);
///
@safe unittest
@@ -1041,7 +1041,7 @@ See_Also:
*/
enum bool isBidirectionalRange(R) = isForwardRange!R
&& is(typeof((R r) => r.popBack))
- && is(ReturnType!((R r) => r.back) == ElementType!R);
+ && is(typeof((R r) { return r.back; } (R.init)) == ElementType!R);
///
@safe unittest
@@ -1674,8 +1674,8 @@ The following expression must be true for `hasSlicing` to be `true`:
----
isForwardRange!R
- && !isNarrowString!R
- && is(ReturnType!((R r) => r[1 .. 1].length) == size_t)
+ && !(isAutodecodableString!R && !isAggregateType!R)
+ && is(typeof((R r) { return r[1 .. 1].length; } (R.init)) == size_t)
&& (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R)
&& (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 .. $]) == R))
&& (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R
@@ -1688,7 +1688,7 @@ The following expression must be true for `hasSlicing` to be `true`:
*/
enum bool hasSlicing(R) = isForwardRange!R
&& !(isAutodecodableString!R && !isAggregateType!R)
- && is(ReturnType!((R r) => r[1 .. 1].length) == size_t)
+ && is(typeof((R r) { return r[1 .. 1].length; } (R.init)) == size_t)
&& (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R)
&& (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 .. $]) == R))
&& (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R
diff --git a/libphobos/src/std/regex/internal/parser.d b/libphobos/src/std/regex/internal/parser.d
index 448bb99..ab2b297 100644
--- a/libphobos/src/std/regex/internal/parser.d
+++ b/libphobos/src/std/regex/internal/parser.d
@@ -1010,12 +1010,14 @@ if (isForwardRange!R && is(ElementType!R : dchar))
//
@trusted void error(string msg)
{
- import std.array : appender;
- import std.format.write : formattedWrite;
- auto app = appender!string();
- formattedWrite(app, "%s\nPattern with error: `%s` <--HERE-- `%s`",
- msg, origin[0..$-pat.length], pat);
- throw new RegexException(app.data);
+ import std.conv : text;
+ string app = msg;
+ app ~= "\nPattern with error: `";
+ app ~= origin[0..$-pat.length].text;
+ app ~= "` <--HERE-- `";
+ app ~= pat.text;
+ app ~= "`";
+ throw new RegexException(app);
}
alias Char = BasicElementOf!R;
diff --git a/libphobos/src/std/socket.d b/libphobos/src/std/socket.d
index 593052e..3359c8e 100644
--- a/libphobos/src/std/socket.d
+++ b/libphobos/src/std/socket.d
@@ -802,10 +802,14 @@ class InternetHost
{
string getHostNameFromInt = ih.name.dup;
- assert(ih.getHostByAddr(ia.toAddrString()));
- string getHostNameFromStr = ih.name.dup;
+ // This randomly fails in the compiler test suite
+ //assert(ih.getHostByAddr(ia.toAddrString()));
- assert(getHostNameFromInt == getHostNameFromStr);
+ if (ih.getHostByAddr(ia.toAddrString()))
+ {
+ string getHostNameFromStr = ih.name.dup;
+ assert(getHostNameFromInt == getHostNameFromStr);
+ }
}
}
diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d
index 802aa128..92e4906 100644
--- a/libphobos/src/std/stdio.d
+++ b/libphobos/src/std/stdio.d
@@ -1374,8 +1374,9 @@ Throws: `Exception` if the file is not opened.
}
/**
-Calls $(HTTP cplusplus.com/reference/clibrary/cstdio/ftell.html, ftell) for the
-managed file handle.
+Calls $(HTTP cplusplus.com/reference/cstdio/ftell.html, ftell)
+for the managed file handle, which returns the current value of
+the position indicator of the file handle.
Throws: `Exception` if the file is not opened.
`ErrnoException` if the call to `ftell` fails.
diff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d
index e5f305b..bbbca69 100644
--- a/libphobos/src/std/traits.d
+++ b/libphobos/src/std/traits.d
@@ -10,6 +10,7 @@
* $(TR $(TH Category) $(TH Templates))
* $(TR $(TD Symbol Name traits) $(TD
* $(LREF fullyQualifiedName)
+ * $(LREF mangledName)
* $(LREF moduleName)
* $(LREF packageName)
* ))
@@ -67,9 +68,7 @@
* $(LREF isCovariantWith)
* $(LREF isImplicitlyConvertible)
* ))
- * $(TR $(TD SomethingTypeOf) $(TD
- * $(LREF rvalueOf)
- * $(LREF lvalueOf)
+ * $(TR $(TD Type Constructors) $(TD
* $(LREF InoutOf)
* $(LREF ConstOf)
* $(LREF SharedOf)
@@ -138,7 +137,8 @@
* $(LREF Promoted)
* ))
* $(TR $(TD Misc) $(TD
- * $(LREF mangledName)
+ * $(LREF lvalueOf)
+ * $(LREF rvalueOf)
* $(LREF Select)
* $(LREF select)
* ))
@@ -889,7 +889,7 @@ private template fqnType(T,
);
}
}
- else static if (is(T : U*, U))
+ else static if (is(T == U*, U))
{
enum fqnType = chain!(
fqnType!(U, qualifiers) ~ "*"
@@ -986,6 +986,10 @@ private template fqnType(T,
* or a class with an `opCall`. Please note that $(D_KEYWORD ref)
* is not part of a type, but the attribute of the function
* (see template $(LREF functionAttributes)).
+ *
+ * $(NOTE To reduce template instantiations, consider instead using
+ * $(D typeof(() { return func(args); } ())) if the argument types are known or
+ * $(D static if (is(typeof(func) Ret == return))) if only that basic test is needed.)
*/
template ReturnType(alias func)
if (isCallable!func)
@@ -2302,7 +2306,7 @@ if (isCallable!func)
int test(int);
int test() @property;
}
- alias ov = __traits(getVirtualFunctions, Overloads, "test");
+ alias ov = __traits(getVirtualMethods, Overloads, "test");
alias F_ov0 = FunctionTypeOf!(ov[0]);
alias F_ov1 = FunctionTypeOf!(ov[1]);
alias F_ov2 = FunctionTypeOf!(ov[2]);
@@ -3925,7 +3929,7 @@ template hasStaticMember(T, string member)
{
static if (__traits(hasMember, T, member))
{
- static if (is(T : V*, V))
+ static if (is(T == V*, V))
alias U = V;
else
alias U = T;
@@ -4529,7 +4533,7 @@ if (is(C == class) || is(C == interface))
static if (__traits(hasMember, Node, name) && __traits(compiles, __traits(getMember, Node, name)))
{
// Get all overloads in sight (not hidden).
- alias inSight = __traits(getVirtualFunctions, Node, name);
+ alias inSight = __traits(getVirtualMethods, Node, name);
// And collect all overloads in ancestor classes to reveal hidden
// methods. The result may contain duplicates.
@@ -5297,7 +5301,8 @@ enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = lv
static assert(!isAssignable!S5);
// `-preview=in` is enabled
- static if (!is(typeof(mixin(q{(in ref int a) => a}))))
+ alias DScannerBug895 = int[256];
+ static if (((in DScannerBug895 a) { return __traits(isRef, a); })(DScannerBug895.init))
{
struct S6 { void opAssign(in S5); }
@@ -6066,7 +6071,7 @@ template StringTypeOf(T)
static assert(is(Q!T[] == StringTypeOf!( SubTypeOf!(Q!T[]) )));
alias Str = Q!T[];
- class C(S) { S val; alias val this; }
+ struct C(S) { S val; alias val this; }
static assert(is(StringTypeOf!(C!Str) == Str));
}}
}
@@ -7481,24 +7486,10 @@ Params:
Returns:
A `bool`
*/
-template isSomeFunction(alias T)
-{
- static if (is(typeof(& T) U : U*) && is(U == function) || is(typeof(& T) U == delegate))
- {
- // T is a (nested) function symbol.
- enum bool isSomeFunction = true;
- }
- else static if (is(T W) || is(typeof(T) W))
- {
- // T is an expression or a type. Take the type of it and examine.
- static if (is(W F : F*) && is(F == function))
- enum bool isSomeFunction = true; // function pointer
- else
- enum bool isSomeFunction = is(W == function) || is(W == delegate);
- }
- else
- enum bool isSomeFunction = false;
-}
+enum bool isSomeFunction(alias T) =
+ is(T == return) ||
+ is(typeof(T) == return) ||
+ is(typeof(&T) == return); // @property
///
@safe unittest
@@ -7513,17 +7504,16 @@ template isSomeFunction(alias T)
auto c = new C;
auto fp = &func;
auto dg = &c.method;
- real val;
static assert( isSomeFunction!func);
static assert( isSomeFunction!prop);
static assert( isSomeFunction!(C.method));
static assert( isSomeFunction!(C.prop));
static assert( isSomeFunction!(c.prop));
- static assert( isSomeFunction!(c.prop));
static assert( isSomeFunction!fp);
static assert( isSomeFunction!dg);
+ real val;
static assert(!isSomeFunction!int);
static assert(!isSomeFunction!val);
}
@@ -7969,7 +7959,7 @@ has both opApply and a range interface.
*/
template ForeachType(T)
{
- alias ForeachType = ReturnType!(typeof(
+ alias ForeachType = typeof(
(inout int x = 0)
{
foreach (elem; T.init)
@@ -7977,7 +7967,7 @@ template ForeachType(T)
return elem;
}
assert(0);
- }));
+ }());
}
///
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index 25cf9e0..bde8439 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -3160,12 +3160,6 @@ struct Nullable(T)
}
/// ditto
- inout(typeof(this)) opIndex() inout
- {
- return this;
- }
-
- /// ditto
inout(typeof(this)) opIndex(size_t[2] dim) inout
in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0])
{
@@ -3192,6 +3186,74 @@ struct Nullable(T)
{
return get();
}
+
+ /**
+ * Converts `Nullable` to a range. Works even when the contained type is `immutable`.
+ */
+ auto opSlice(this This)()
+ {
+ static struct NullableRange
+ {
+ private This value;
+
+ // starts out true if value is null
+ private bool empty_;
+
+ @property bool empty() const @safe pure nothrow
+ {
+ return empty_;
+ }
+
+ void popFront() @safe pure nothrow
+ {
+ empty_ = true;
+ }
+
+ alias popBack = popFront;
+
+ @property ref inout(typeof(value.get())) front() inout @safe pure nothrow
+ {
+ return value.get();
+ }
+
+ alias back = front;
+
+ @property inout(typeof(this)) save() inout
+ {
+ return this;
+ }
+
+ size_t[2] opSlice(size_t dim : 0)(size_t from, size_t to) const
+ {
+ return [from, to];
+ }
+
+ @property size_t length() const @safe pure nothrow
+ {
+ return !empty;
+ }
+
+ alias opDollar(size_t dim : 0) = length;
+
+ ref inout(typeof(value.get())) opIndex(size_t index) inout @safe pure nothrow
+ in (index < length)
+ {
+ return value.get();
+ }
+
+ inout(typeof(this)) opIndex(size_t[2] dim) inout
+ in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0])
+ {
+ return (dim[0] == 0 && dim[1] == 1) ? this : this.init;
+ }
+
+ auto opIndex() inout
+ {
+ return this;
+ }
+ }
+ return NullableRange(this, isNull);
+ }
}
/// ditto
@@ -3774,6 +3836,34 @@ auto nullable(T)(T t)
assert(hasLvalueElements!(Nullable!int));
}
+// https://issues.dlang.org/show_bug.cgi?id=23640
+@safe pure nothrow unittest
+{
+ import std.algorithm.comparison : equal;
+ import std.range : only;
+ import std.range.primitives : hasLength, hasSlicing,
+ isRandomAccessRange;
+ static immutable struct S { int[] array; }
+ auto value = S([42]);
+ alias ImmutableNullable = immutable Nullable!S;
+ auto a = ImmutableNullable(value)[];
+ alias Range = typeof(a);
+ assert(isRandomAccessRange!Range);
+ assert(hasLength!Range);
+ assert(hasSlicing!Range);
+ assert(!a.empty);
+ assert(a.front == value);
+ assert(a.back == value);
+ assert(a[0] == value);
+ assert(a.equal(only(value)));
+ assert(a[0 .. $].equal(only(value)));
+ Range b = a.save();
+ assert(!b.empty);
+ b.popFront();
+ assert(!a.empty);
+ assert(b.empty);
+}
+
/**
Just like `Nullable!T`, except that the null state is defined as a
particular value. For example, $(D Nullable!(uint, uint.max)) is an
diff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d
index 5c0659e..e2a0de7 100644
--- a/libphobos/src/std/uni/package.d
+++ b/libphobos/src/std/uni/package.d
@@ -712,6 +712,8 @@ import std.traits : isConvertibleToString, isIntegral, isSomeChar,
isSomeString, Unqual, isDynamicArray;
// debug = std_uni;
+import std.internal.unicode_tables; // generated file
+
debug(std_uni) import std.stdio; // writefln, writeln
private:
@@ -6962,23 +6964,192 @@ private:
enum EMPTY_CASE_TRIE = ushort.max;// from what gen_uni uses internally
-// control - '\r'
-enum controlSwitch = `
- case '\u0000':..case '\u0008':case '\u000E':..case '\u001F':case '\u007F':..
- case '\u0084':case '\u0086':..case '\u009F': case '\u0009':..case '\u000C': case '\u0085':
-`;
// TODO: redo the most of hangul stuff algorithmically in case of Graphemes too
-// kill unrolled switches
+// Use combined trie instead of checking for '\r' | '\n' | ccTrie,
+// or extend | '\u200D' separately
private static bool isRegionalIndicator(dchar ch) @safe pure @nogc nothrow
{
return ch >= '\U0001F1E6' && ch <= '\U0001F1FF';
}
+// Our grapheme decoder is a state machine, this is list of all possible
+// states before each code point.
+private enum GraphemeState
+{
+ Start,
+ CR,
+ RI,
+ L,
+ V,
+ LVT,
+ Emoji,
+ EmojiZWJ,
+ Prepend,
+ End
+}
+
+// Message values whether end of grapheme is reached
+private enum TransformRes
+{
+ // No, unless the source range ends here
+ // (GB2 - break at end of text, unless text is empty)
+ goOn,
+ redo, // Run last character again with new state
+ retInclude, // Yes, after the just iterated character
+ retExclude // Yes, before the just iterated character
+}
+
+// The logic of the grapheme decoding is all here
+// GB# means Grapheme Breaking rule number # - see Unicode standard annex #29
+// Note, getting GB1 (break at start of text, unless text is empty) right
+// relies on the user starting grapheme walking from beginning of the text, and
+// not attempting to walk an empty text.
+private enum TransformRes
+ function(ref GraphemeState, dchar) @safe pure nothrow @nogc [] graphemeTransforms =
+[
+ GraphemeState.Start: (ref state, ch)
+ {
+ // GB4. Break after controls.
+ if (graphemeControlTrie[ch] || ch == '\n')
+ return TransformRes.retInclude;
+
+ with (GraphemeState) state =
+ ch == '\r' ? CR :
+ isRegionalIndicator(ch) ? RI :
+ isHangL(ch) ? L :
+ hangLV[ch] || isHangV(ch) ? V :
+ hangLVT[ch] || isHangT(ch) ? LVT :
+ prependTrie[ch] ? Prepend :
+ xpictoTrie[ch] ? Emoji :
+ End;
+
+ // No matter what we encountered, we always include the
+ // first code point in the grapheme.
+ return TransformRes.goOn;
+ },
+
+ // GB3, GB4. Do not break between a CR and LF.
+ // Otherwise, break after controls.
+ GraphemeState.CR: (ref state, ch) => ch == '\n' ?
+ TransformRes.retInclude :
+ TransformRes.retExclude,
+
+ // GB12 - GB13. Do not break within emoji flag sequences.
+ // That is, do not break between regional indicator (RI) symbols if
+ // there is an odd number of RI characters before the break point.
+ // This state applies if one and only one RI code point has been
+ // encountered.
+ GraphemeState.RI: (ref state, ch)
+ {
+ state = GraphemeState.End;
+
+ return isRegionalIndicator(ch) ?
+ TransformRes.goOn :
+ TransformRes.redo;
+ },
+
+ // GB6. Do not break Hangul syllable sequences.
+ GraphemeState.L: (ref state, ch)
+ {
+ if (isHangL(ch))
+ return TransformRes.goOn;
+ else if (isHangV(ch) || hangLV[ch])
+ {
+ state = GraphemeState.V;
+ return TransformRes.goOn;
+ }
+ else if (hangLVT[ch])
+ {
+ state = GraphemeState.LVT;
+ return TransformRes.goOn;
+ }
+
+ state = GraphemeState.End;
+ return TransformRes.redo;
+ },
+
+ // GB7. Do not break Hangul syllable sequences.
+ GraphemeState.V: (ref state, ch)
+ {
+ if (isHangV(ch))
+ return TransformRes.goOn;
+ else if (isHangT(ch))
+ {
+ state = GraphemeState.LVT;
+ return TransformRes.goOn;
+ }
+
+ state = GraphemeState.End;
+ return TransformRes.redo;
+ },
+
+ // GB8. Do not break Hangul syllable sequences.
+ GraphemeState.LVT: (ref state, ch)
+ {
+ if (isHangT(ch))
+ return TransformRes.goOn;
+
+ state = GraphemeState.End;
+ return TransformRes.redo;
+ },
+
+ // GB11. Do not break within emoji modifier sequences or emoji
+ // zwj sequences. This state applies when the last code point was
+ // NOT a ZWJ.
+ GraphemeState.Emoji: (ref state, ch)
+ {
+ if (graphemeExtendTrie[ch])
+ return TransformRes.goOn;
+
+ static assert(!graphemeExtendTrie['\u200D']);
+
+ if (ch == '\u200D')
+ {
+ state = GraphemeState.EmojiZWJ;
+ return TransformRes.goOn;
+ }
+
+ state = GraphemeState.End;
+ // There might still be spacing marks are
+ // at the end, which are not allowed in
+ // middle of emoji sequences
+ return TransformRes.redo;
+ },
+
+ // GB11. Do not break within emoji modifier sequences or emoji
+ // zwj sequences. This state applies when the last code point was
+ // a ZWJ.
+ GraphemeState.EmojiZWJ: (ref state, ch)
+ {
+ state = GraphemeState.Emoji;
+ if (xpictoTrie[ch])
+ return TransformRes.goOn;
+ return TransformRes.redo;
+ },
+
+ // GB9b. Do not break after Prepend characters.
+ GraphemeState.Prepend: (ref state, ch)
+ {
+ // GB5. Break before controls.
+ if (graphemeControlTrie[ch] || ch == '\r' || ch == '\n')
+ return TransformRes.retExclude;
+
+ state = GraphemeState.Start;
+ return TransformRes.redo;
+ },
+
+ // GB9, GB9a. Do not break before extending characters, ZWJ
+ // or SpacingMarks.
+ // GB999. Otherwise, break everywhere.
+ GraphemeState.End: (ref state, ch)
+ => !graphemeExtendTrie[ch] && !spacingMarkTrie[ch] && ch != '\u200D' ?
+ TransformRes.retExclude :
+ TransformRes.goOn
+];
+
template genericDecodeGrapheme(bool getValue)
{
- alias graphemeExtend = graphemeExtendTrie;
- alias spacingMark = mcTrie;
static if (getValue)
alias Value = Grapheme;
else
@@ -6986,115 +7157,44 @@ template genericDecodeGrapheme(bool getValue)
Value genericDecodeGrapheme(Input)(ref Input range)
{
- import std.internal.unicode_tables : isHangL, isHangT, isHangV; // generated file
- enum GraphemeState {
- Start,
- CR,
- RI,
- L,
- V,
- LVT
- }
static if (getValue)
Grapheme grapheme;
auto state = GraphemeState.Start;
- enum eat = q{
- static if (getValue)
- grapheme ~= ch;
- range.popFront();
- };
-
dchar ch;
+
assert(!range.empty, "Attempting to decode grapheme from an empty " ~ Input.stringof);
+ outer:
while (!range.empty)
{
ch = range.front;
- final switch (state) with(GraphemeState)
+
+ rerun:
+ final switch (graphemeTransforms[state](state, ch))
+ with(TransformRes)
{
- case Start:
- mixin(eat);
- if (ch == '\r')
- state = CR;
- else if (isRegionalIndicator(ch))
- state = RI;
- else if (isHangL(ch))
- state = L;
- else if (hangLV[ch] || isHangV(ch))
- state = V;
- else if (hangLVT[ch])
- state = LVT;
- else if (isHangT(ch))
- state = LVT;
- else
- {
- switch (ch)
- {
- mixin(controlSwitch);
- goto L_End;
- default:
- goto L_End_Extend;
- }
- }
- break;
- case CR:
- if (ch == '\n')
- mixin(eat);
- goto L_End_Extend;
- case RI:
- if (isRegionalIndicator(ch))
- mixin(eat);
- goto L_End_Extend;
- case L:
- if (isHangL(ch))
- mixin(eat);
- else if (isHangV(ch) || hangLV[ch])
- {
- state = V;
- mixin(eat);
- }
- else if (hangLVT[ch])
- {
- state = LVT;
- mixin(eat);
- }
- else
- goto L_End_Extend;
- break;
- case V:
- if (isHangV(ch))
- mixin(eat);
- else if (isHangT(ch))
- {
- state = LVT;
- mixin(eat);
- }
- else
- goto L_End_Extend;
- break;
- case LVT:
- if (isHangT(ch))
- {
- mixin(eat);
- }
- else
- goto L_End_Extend;
- break;
+ case goOn:
+ static if (getValue)
+ grapheme ~= ch;
+ range.popFront();
+ continue;
+
+ case redo:
+ goto rerun;
+
+ case retInclude:
+ static if (getValue)
+ grapheme ~= ch;
+ range.popFront();
+ break outer;
+
+ case retExclude:
+ break outer;
}
}
- L_End_Extend:
- while (!range.empty)
- {
- ch = range.front;
- // extend & spacing marks
- if (!graphemeExtend[ch] && !spacingMark[ch])
- break;
- mixin(eat);
- }
- L_End:
+
static if (getValue)
return grapheme;
}
-
}
public: // Public API continues
@@ -7143,6 +7243,31 @@ if (is(C : dchar))
static assert(c2 == 3); // \u0301 has 2 UTF-8 code units
}
+// TODO: make this @nogc. Probably no big deal since the state machine is
+// already GC-free.
+@safe pure nothrow unittest
+{
+ // grinning face ~ emoji modifier fitzpatrick type-5 ~ grinning face
+ assert(graphemeStride("\U0001F600\U0001f3FE\U0001F600"d, 0) == 2);
+ // skier ~ female sign ~ '€'
+ assert(graphemeStride("\u26F7\u2640€"d, 0) == 1);
+ // skier ~ emoji modifier fitzpatrick type-5 ~ female sign ~ '€'
+ assert(graphemeStride("\u26F7\U0001f3FE\u2640€"d, 0) == 2);
+ // skier ~ zero-width joiner ~ female sign ~ '€'
+ assert(graphemeStride("\u26F7\u200D\u2640€"d, 0) == 3);
+ // skier ~ emoji modifier fitzpatrick type-5 ~ zero-width joiner
+ // ~ female sign ~ '€'
+ assert(graphemeStride("\u26F7\U0001f3FE\u200D\u2640€"d, 0) == 4);
+ // skier ~ zero-width joiner ~ '€'
+ assert(graphemeStride("\u26F7\u200D€"d, 0) == 2);
+ //'€' ~ zero-width joiner ~ skier
+ assert(graphemeStride("€\u200D\u26F7"d, 0) == 2);
+ // Kaithi number sign ~ Devanagari digit four ~ Devanagari digit two
+ assert(graphemeStride("\U000110BD\u096A\u0968"d, 0) == 2);
+ // Kaithi number sign ~ null
+ assert(graphemeStride("\U000110BD\0"d, 0) == 1);
+}
+
/++
Reads one full grapheme cluster from an
$(REF_ALTTEXT input range, isInputRange, std,range,primitives) of dchar `inp`.
@@ -7285,6 +7410,13 @@ private static @safe struct InputRangeString
assert(nonForwardRange.walkLength == 4);
}
+// Issue 23474
+@safe pure unittest
+{
+ import std.range.primitives : walkLength;
+ assert(byGrapheme("\r\u0308").walkLength == 2);
+}
+
/++
$(P Lazily transform a range of $(LREF Grapheme)s to a range of code points.)
@@ -10530,8 +10662,6 @@ private:
@safe pure nothrow @nogc @property
{
- import std.internal.unicode_tables; // generated file
-
// It's important to use auto return here, so that the compiler
// only runs semantic on the return type if the function gets
// used. Also these are functions rather than templates to not
@@ -10578,10 +10708,10 @@ private:
}
//grapheme breaking algorithm tables
- auto mcTrie()
+ auto spacingMarkTrie()
{
- import std.internal.unicode_grapheme : mcTrieEntries;
- static immutable res = asTrie(mcTrieEntries);
+ import std.internal.unicode_grapheme : spacingMarkTrieEntries;
+ static immutable res = asTrie(spacingMarkTrieEntries);
return res;
}
@@ -10606,6 +10736,27 @@ private:
return res;
}
+ auto prependTrie()
+ {
+ import std.internal.unicode_grapheme : prependTrieEntries;
+ static immutable res = asTrie(prependTrieEntries);
+ return res;
+ }
+
+ auto graphemeControlTrie()
+ {
+ import std.internal.unicode_grapheme : controlTrieEntries;
+ static immutable res = asTrie(controlTrieEntries);
+ return res;
+ }
+
+ auto xpictoTrie()
+ {
+ import std.internal.unicode_grapheme : Extended_PictographicTrieEntries;
+ static immutable res = asTrie(Extended_PictographicTrieEntries);
+ return res;
+ }
+
// tables below are used for composition/decomposition
auto combiningClassTrie()
{
diff --git a/libphobos/src/std/utf.d b/libphobos/src/std/utf.d
index 7a0556d..3eef5cb 100644
--- a/libphobos/src/std/utf.d
+++ b/libphobos/src/std/utf.d
@@ -3136,7 +3136,7 @@ private T toUTFImpl(T, S)(scope S s)
collection cycle and cause a nasty bug when the C code tries to use it.
+/
template toUTFz(P)
-if (is(P : C*, C) && isSomeChar!C)
+if (is(P == C*, C) && isSomeChar!C)
{
P toUTFz(S)(S str) @safe pure
if (isSomeString!S)