summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2018-09-28 05:40:33 +0200
committerEugen Wissner <belka@caraus.de>2018-09-28 05:40:33 +0200
commitc5eb2f27be3a524f9c6e7de356e286146d00ed49 (patch)
treead84795419aeb658b1a51bd1d74ec990faccf124 /source
parent349e6dfede4e22ca9309b703d488b99351d8c15c (diff)
downloadtanya-c5eb2f27be3a524f9c6e7de356e286146d00ed49.tar.gz
Add algorithm.iterationv0.12.0
Diffstat (limited to 'source')
-rw-r--r--source/tanya/algorithm/iteration.d169
-rw-r--r--source/tanya/math/mp.d16
2 files changed, 176 insertions, 9 deletions
diff --git a/source/tanya/algorithm/iteration.d b/source/tanya/algorithm/iteration.d
index 9d0a4a8..27fce71 100644
--- a/source/tanya/algorithm/iteration.d
+++ b/source/tanya/algorithm/iteration.d
@@ -407,3 +407,172 @@ if (isInputRange!R)
assert(slice.back == 3);
}
}
+
+/**
+ * Iterates a bidirectional range backwards.
+ *
+ * If $(D_PARAM Range) is a random-access range as well, the resulting range
+ * is a random-access range too.
+ *
+ * Params:
+ * Range = Bidirectional range type.
+ * range = Bidirectional range.
+ *
+ * Returns: Bidirectional range with the elements order reversed.
+ */
+auto retro(Range)(Range range)
+if (isBidirectionalRange!Range)
+{
+ static struct Retro
+ {
+ Range source;
+
+ @disable this();
+
+ private this(Range source)
+ {
+ this.source = source;
+ }
+
+ Retro save()
+ {
+ return this;
+ }
+
+ @property auto ref front()
+ in (!empty)
+ {
+ return this.source.back;
+ }
+
+ void popFront()
+ in (!empty)
+ {
+ this.source.popBack();
+ }
+
+ @property auto ref back()
+ in (!empty)
+ {
+ return this.source.front;
+ }
+
+ void popBack()
+ in (!empty)
+ {
+ this.source.popFront();
+ }
+
+ @property bool empty()
+ {
+ return this.source.empty;
+ }
+
+ static if (hasLength!Range)
+ {
+ @property size_t length()
+ {
+ return this.source.length;
+ }
+ }
+
+ static if (isRandomAccessRange!Range && hasLength!Range)
+ {
+ auto ref opIndex(size_t i)
+ in (i < length)
+ {
+ return this.source[$ - ++i];
+ }
+ }
+
+ static if (hasAssignableElements!Range)
+ {
+ @property void front(ref ElementType!Range value)
+ in (!empty)
+ {
+ this.source.back = value;
+ }
+
+ @property void front(ElementType!Range value)
+ in (!empty)
+ {
+ this.source.back = move(value);
+ }
+
+ @property void back(ref ElementType!Range value)
+ in (!empty)
+ {
+ this.source.front = value;
+ }
+
+ @property void back(ElementType!Range value)
+ in (!empty)
+ {
+ this.source.front = move(value);
+ }
+
+ static if (isRandomAccessRange!Range && hasLength!Range)
+ {
+ void opIndexAssign(ref ElementType!Range value, size_t i)
+ in (i < length)
+ {
+ this.source[$ - ++i] = value;
+ }
+
+ void opIndexAssign(ElementType!Range value, size_t i)
+ in (i < length)
+ {
+ this.source[$ - ++i] = move(value);
+ }
+ }
+ }
+ }
+
+ return Retro(range);
+}
+
+///
+@nogc nothrow pure @safe unittest
+{
+ import tanya.algorithm.comparison : equal;
+
+ const int[3] given = [1, 2, 3];
+ const int[3] expected = [3, 2, 1];
+
+ auto actual = retro(given[]);
+
+ assert(actual.length == expected.length);
+ assert(!actual.empty);
+ assert(equal(actual, expected[]));
+}
+
+// Elements are accessible in reverse order
+@nogc nothrow pure @safe unittest
+{
+ const int[3] given = [1, 2, 3];
+ auto actual = retro(given[]);
+
+ assert(actual.back == given[].front);
+ assert(actual[0] == 3);
+ assert(actual[2] == 1);
+
+ actual.popBack();
+ assert(actual.back == 2);
+ assert(actual[1] == 2);
+}
+
+// Elements can be assigned
+@nogc nothrow pure @safe unittest
+{
+ int[4] given = [1, 2, 3, 4];
+ auto actual = retro(given[]);
+
+ actual.front = 5;
+ assert(given[].back == 5);
+
+ actual.back = 8;
+ assert(given[].front == 8);
+
+ actual[2] = 10;
+ assert(given[1] == 10);
+}
diff --git a/source/tanya/math/mp.d b/source/tanya/math/mp.d
index ed47c1e..5ee1f39 100644
--- a/source/tanya/math/mp.d
+++ b/source/tanya/math/mp.d
@@ -14,15 +14,16 @@
*/
module tanya.math.mp;
-import std.algorithm.mutation : fill, reverse;
-import std.range;
+import std.algorithm.mutation : fill;
import tanya.algorithm.comparison;
+import tanya.algorithm.iteration;
import tanya.algorithm.mutation;
import tanya.container.array;
import tanya.encoding.ascii;
import tanya.memory;
import tanya.meta.trait;
import tanya.meta.transform;
+import tanya.range;
/**
* Algebraic sign.
@@ -929,7 +930,7 @@ struct Integer
const shift = digitBitCount - bit;
digit carry;
- foreach (ref d; this.rep[0 .. this.size].retro)
+ foreach_reverse (ref d; this.rep[0 .. this.size])
{
const newCarry = d & mask;
d = (d >> bit) | (carry << shift);
@@ -1505,14 +1506,11 @@ struct Integer
tmp = this;
}
- do
+ array.length = length;
+ for (size_t i = array.length - 1; tmp != 0; tmp >>= 8, --i)
{
- array.insertBack(cast(ubyte) (tmp.rep[0] & 0xff));
- tmp >>= 8;
+ array[i] = (cast(ubyte) (tmp.rep[0] & 0xff));
}
- while (tmp != 0);
-
- array[].reverse();
return array;
}