Add algorithm.iteration
This commit is contained in:
parent
349e6dfede
commit
c5eb2f27be
@ -407,3 +407,172 @@ if (isInputRange!R)
|
|||||||
assert(slice.back == 3);
|
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);
|
||||||
|
}
|
||||||
|
@ -14,15 +14,16 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.math.mp;
|
module tanya.math.mp;
|
||||||
|
|
||||||
import std.algorithm.mutation : fill, reverse;
|
import std.algorithm.mutation : fill;
|
||||||
import std.range;
|
|
||||||
import tanya.algorithm.comparison;
|
import tanya.algorithm.comparison;
|
||||||
|
import tanya.algorithm.iteration;
|
||||||
import tanya.algorithm.mutation;
|
import tanya.algorithm.mutation;
|
||||||
import tanya.container.array;
|
import tanya.container.array;
|
||||||
import tanya.encoding.ascii;
|
import tanya.encoding.ascii;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
import tanya.meta.transform;
|
import tanya.meta.transform;
|
||||||
|
import tanya.range;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Algebraic sign.
|
* Algebraic sign.
|
||||||
@ -929,7 +930,7 @@ struct Integer
|
|||||||
const shift = digitBitCount - bit;
|
const shift = digitBitCount - bit;
|
||||||
digit carry;
|
digit carry;
|
||||||
|
|
||||||
foreach (ref d; this.rep[0 .. this.size].retro)
|
foreach_reverse (ref d; this.rep[0 .. this.size])
|
||||||
{
|
{
|
||||||
const newCarry = d & mask;
|
const newCarry = d & mask;
|
||||||
d = (d >> bit) | (carry << shift);
|
d = (d >> bit) | (carry << shift);
|
||||||
@ -1505,14 +1506,11 @@ struct Integer
|
|||||||
tmp = this;
|
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));
|
array[i] = (cast(ubyte) (tmp.rep[0] & 0xff));
|
||||||
tmp >>= 8;
|
|
||||||
}
|
}
|
||||||
while (tmp != 0);
|
|
||||||
|
|
||||||
array[].reverse();
|
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user