Move BitVector from the crypto branch
This commit is contained in:
		
							
								
								
									
										510
									
								
								source/tanya/container/bitvector.d
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										510
									
								
								source/tanya/container/bitvector.d
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,510 @@
 | 
			
		||||
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
			
		||||
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
			
		||||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Single-dimensioned bit array.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright: Eugene Wissner 2016-2017.
 | 
			
		||||
 * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
 | 
			
		||||
 *                  Mozilla Public License, v. 2.0).
 | 
			
		||||
 * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
 | 
			
		||||
 */
 | 
			
		||||
module tanya.container.bitvector;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Wrapper that allows bit manipulation on $(D_KEYWORD ubyte[]) array.
 | 
			
		||||
 */
 | 
			
		||||
struct BitVector
 | 
			
		||||
{
 | 
			
		||||
    protected ubyte[] vector;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Params:
 | 
			
		||||
     *  array = Array should be manipulated on.
 | 
			
		||||
     */
 | 
			
		||||
    this(inout(ubyte[]) array) inout pure nothrow @safe @nogc
 | 
			
		||||
    in
 | 
			
		||||
    {
 | 
			
		||||
        assert(array.length <= size_t.max / 8);
 | 
			
		||||
        assert(array !is null);
 | 
			
		||||
    }
 | 
			
		||||
    body
 | 
			
		||||
    {
 | 
			
		||||
        vector = array;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        ubyte[5] array1 = [234, 3, 252, 10, 18];
 | 
			
		||||
        ubyte[3] array2 = [65, 13, 173];
 | 
			
		||||
        auto bits = BitVector(array1);
 | 
			
		||||
 | 
			
		||||
        assert(bits[] is array1);
 | 
			
		||||
        assert(bits[] !is array2);
 | 
			
		||||
 | 
			
		||||
        bits = BitVector(array2);
 | 
			
		||||
        assert(bits[] is array2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns: Number of bits in the vector.
 | 
			
		||||
     */
 | 
			
		||||
    @property inout(size_t) length() inout const pure nothrow @safe @nogc
 | 
			
		||||
    {
 | 
			
		||||
        return vector.length * 8;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Ditto.
 | 
			
		||||
    inout(size_t) opDollar() inout const pure nothrow @safe @nogc
 | 
			
		||||
    {
 | 
			
		||||
        return vector.length * 8;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        // [01000001, 00001101, 10101101]
 | 
			
		||||
        ubyte[3] arr = [65, 13, 173];
 | 
			
		||||
        auto bits = BitVector(arr);
 | 
			
		||||
 | 
			
		||||
        assert(bits.length == 24);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Params:
 | 
			
		||||
     *  bit = Bit position.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: $(D_KEYWORD true) if the bit on position $(D_PARAM bit) is set,
 | 
			
		||||
     *          $(D_KEYWORD false) if not set.
 | 
			
		||||
     */
 | 
			
		||||
    inout(bool) opIndex(size_t bit) inout const pure nothrow @safe @nogc
 | 
			
		||||
    in
 | 
			
		||||
    {
 | 
			
		||||
        assert(bit / 8 <= vector.length);
 | 
			
		||||
    }
 | 
			
		||||
    body
 | 
			
		||||
    {
 | 
			
		||||
        return (vector[bit / 8] & (0x80 >> (bit % 8))) != 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        // [01000001, 00001101, 10101101]
 | 
			
		||||
        ubyte[3] arr = [65, 13, 173];
 | 
			
		||||
        auto bits = BitVector(arr);
 | 
			
		||||
 | 
			
		||||
        assert(!bits[0]);
 | 
			
		||||
        assert(bits[1]);
 | 
			
		||||
        assert(bits[7]);
 | 
			
		||||
        assert(!bits[8]);
 | 
			
		||||
        assert(!bits[11]);
 | 
			
		||||
        assert(bits[12]);
 | 
			
		||||
        assert(bits[20]);
 | 
			
		||||
        assert(bits[23]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns: Underlying array.
 | 
			
		||||
     */
 | 
			
		||||
    inout(ubyte[]) opIndex() inout pure nothrow @safe @nogc
 | 
			
		||||
    {
 | 
			
		||||
        return vector;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        // [01000001, 00001101, 10101101]
 | 
			
		||||
        ubyte[3] arr = [65, 13, 173];
 | 
			
		||||
        auto bits = BitVector(arr);
 | 
			
		||||
 | 
			
		||||
        assert(bits[] is arr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Params:
 | 
			
		||||
     *  value = $(D_KEYWORD true) if the bit should be set,
 | 
			
		||||
     *          $(D_KEYWORD false) if cleared.
 | 
			
		||||
     *  bit   = Bit position.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: $(D_PSYMBOL this).
 | 
			
		||||
     */
 | 
			
		||||
    bool opIndexAssign(bool value, size_t bit) pure nothrow @safe @nogc
 | 
			
		||||
    in
 | 
			
		||||
    {
 | 
			
		||||
        assert(bit / 8 <= vector.length);
 | 
			
		||||
    }
 | 
			
		||||
    body
 | 
			
		||||
    {
 | 
			
		||||
        if (value)
 | 
			
		||||
        {
 | 
			
		||||
            vector[bit / 8] |= (0x80 >> (bit % 8));
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            vector[bit / 8] &= ~(0x80 >> (bit % 8));
 | 
			
		||||
        }
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        // [01000001, 00001101, 10101101]
 | 
			
		||||
        ubyte[3] arr = [65, 13, 173];
 | 
			
		||||
        auto bits = BitVector(arr);
 | 
			
		||||
 | 
			
		||||
        bits[5] = bits[6] = true;
 | 
			
		||||
        assert(bits[][0] == 71);
 | 
			
		||||
 | 
			
		||||
        bits[14] = true;
 | 
			
		||||
        bits[15] = false;
 | 
			
		||||
        assert(bits[][1] == 14);
 | 
			
		||||
 | 
			
		||||
        bits[16] = bits[23] = false;
 | 
			
		||||
        assert(bits[][2] == 44);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Copies bits from $(D_PARAM vector) into this $(D_PSYMBOL BitVector).
 | 
			
		||||
     *
 | 
			
		||||
     * The array that should be assigned, can be smaller (but not larger) than
 | 
			
		||||
     * the underlying array of this $(D_PSYMBOL BitVector), leading zeros will
 | 
			
		||||
     * be added in this case to the left.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     *  vector = $(D_KEYWORD ubyte[]) array not larger than
 | 
			
		||||
     *           `$(D_PSYMBOL length) / 8`.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: $(D_KEYWORD this).
 | 
			
		||||
     */
 | 
			
		||||
    BitVector opAssign(ubyte[] vector) pure nothrow @safe @nogc
 | 
			
		||||
    in
 | 
			
		||||
    {
 | 
			
		||||
        assert(vector.length <= this.vector.length);
 | 
			
		||||
    }
 | 
			
		||||
    body
 | 
			
		||||
    {
 | 
			
		||||
        immutable delta = this.vector.length - vector.length;
 | 
			
		||||
        if (delta > 0)
 | 
			
		||||
        {
 | 
			
		||||
            this.vector[0..delta] = 0;
 | 
			
		||||
        }
 | 
			
		||||
        this.vector[delta..$] = vector[0..$];
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        ubyte[5] array1 = [234, 3, 252, 10, 18];
 | 
			
		||||
        ubyte[3] array2 = [65, 13, 173];
 | 
			
		||||
        auto bits = BitVector(array1);
 | 
			
		||||
 | 
			
		||||
        bits = array2;
 | 
			
		||||
        assert(bits[][0] == 0);
 | 
			
		||||
        assert(bits[][1] == 0);
 | 
			
		||||
        assert(bits[][2] == 65);
 | 
			
		||||
        assert(bits[][3] == 13);
 | 
			
		||||
        assert(bits[][4] == 173);
 | 
			
		||||
 | 
			
		||||
        bits = array2[0..2];
 | 
			
		||||
        assert(bits[][0] == 0);
 | 
			
		||||
        assert(bits[][1] == 0);
 | 
			
		||||
        assert(bits[][2] == 0);
 | 
			
		||||
        assert(bits[][3] == 65);
 | 
			
		||||
        assert(bits[][4] == 13);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Support for bitwise operations.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     *  that = Another bit vector.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: $(D_KEYWORD this).
 | 
			
		||||
     */
 | 
			
		||||
    BitVector opOpAssign(string op)(BitVector that) pure nothrow @safe @nogc
 | 
			
		||||
        if ((op == "^") || (op == "|") || (op == "&"))
 | 
			
		||||
    {
 | 
			
		||||
        return opOpAssign(op)(that.vector);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Ditto.
 | 
			
		||||
    BitVector opOpAssign(string op)(ubyte[] that) pure nothrow @safe @nogc
 | 
			
		||||
        if ((op == "^") || (op == "|") || (op == "&"))
 | 
			
		||||
    in
 | 
			
		||||
    {
 | 
			
		||||
        assert(that.length <= vector.length);
 | 
			
		||||
    }
 | 
			
		||||
    body
 | 
			
		||||
    {
 | 
			
		||||
        for (int i = cast(int) vector.length - 1; i >= 0; --i)
 | 
			
		||||
        {
 | 
			
		||||
            mixin("vector[i] " ~  op ~ "= " ~ "that[i];");
 | 
			
		||||
        }
 | 
			
		||||
        immutable delta = vector.length - that.length;
 | 
			
		||||
        if (delta)
 | 
			
		||||
        {
 | 
			
		||||
            static if (op == "&")
 | 
			
		||||
            {
 | 
			
		||||
                vector[0..delta] = 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        // [01000001, 00001101, 10101101]
 | 
			
		||||
        ubyte[3] array1 = [65, 13, 173];
 | 
			
		||||
        ubyte[3] array2 = [0b01010010, 0b10111110, 0b10111110];
 | 
			
		||||
        auto bits = BitVector(array1);
 | 
			
		||||
 | 
			
		||||
        bits |= array2;
 | 
			
		||||
        assert(bits[][0] == 0b01010011);
 | 
			
		||||
        assert(bits[][1] == 0b10111111);
 | 
			
		||||
        assert(bits[][2] == 0b10111111);
 | 
			
		||||
 | 
			
		||||
        bits &= array2;
 | 
			
		||||
        assert(bits[][0] == array2[0]);
 | 
			
		||||
        assert(bits[][1] == array2[1]);
 | 
			
		||||
        assert(bits[][2] == array2[2]);
 | 
			
		||||
 | 
			
		||||
        bits ^= array2;
 | 
			
		||||
        assert(bits[][0] == 0);
 | 
			
		||||
        assert(bits[][1] == 0);
 | 
			
		||||
        assert(bits[][2] == 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Support for shift operations.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     *  n = Number of bits.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: $(D_KEYWORD this).
 | 
			
		||||
     */
 | 
			
		||||
    BitVector opOpAssign(string op)(in size_t n) pure nothrow @safe @nogc
 | 
			
		||||
        if ((op == "<<") || (op == ">>"))
 | 
			
		||||
    {
 | 
			
		||||
        if (n >= length)
 | 
			
		||||
        {
 | 
			
		||||
            vector[0..$] = 0;
 | 
			
		||||
        }
 | 
			
		||||
        else if (n != 0)
 | 
			
		||||
        {
 | 
			
		||||
            immutable bit = n % 8, step = n / 8;
 | 
			
		||||
            immutable delta = 8 - bit;
 | 
			
		||||
            size_t i, j;
 | 
			
		||||
 | 
			
		||||
            static if (op == "<<")
 | 
			
		||||
            {
 | 
			
		||||
                for (j = step; j < vector.length - 1; ++i)
 | 
			
		||||
                {
 | 
			
		||||
                    vector[i] = cast(ubyte)((vector[j] << bit)
 | 
			
		||||
                              | vector[++j] >> delta);
 | 
			
		||||
                }
 | 
			
		||||
                vector[i] = cast(ubyte)(vector[j] << bit);
 | 
			
		||||
                vector[$ - step ..$] = 0;
 | 
			
		||||
            }
 | 
			
		||||
            else static if (op == ">>")
 | 
			
		||||
            {
 | 
			
		||||
                for (i = vector.length - 1, j = i - step; j > 0; --i)
 | 
			
		||||
                {
 | 
			
		||||
                    vector[i] = cast(ubyte)((vector[j] >> bit)
 | 
			
		||||
                              | vector[--j] << delta);
 | 
			
		||||
                }
 | 
			
		||||
                vector[i] = cast(ubyte)(vector[j] >> bit);
 | 
			
		||||
                vector[0..step] = 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ///
 | 
			
		||||
    nothrow @safe @nogc unittest
 | 
			
		||||
    {
 | 
			
		||||
        ubyte[4] arr = [0b10111110, 0b11110010, 0b01010010, 0b01010011];
 | 
			
		||||
        auto bits = BitVector(arr);
 | 
			
		||||
 | 
			
		||||
        bits <<= 0;
 | 
			
		||||
        assert(bits[][0] == 0b10111110 && bits[][1] == 0b11110010
 | 
			
		||||
            && bits[][2] == 0b01010010 && bits[][3] == 0b01010011);
 | 
			
		||||
 | 
			
		||||
        bits <<= 2;
 | 
			
		||||
        assert(bits[][0] == 0b11111011 && bits[][1] == 0b11001001
 | 
			
		||||
            && bits[][2] == 0b01001001 && bits[][3] == 0b01001100);
 | 
			
		||||
 | 
			
		||||
        bits <<= 4;
 | 
			
		||||
        assert(bits[][0] == 0b10111100 && bits[][1] == 0b10010100
 | 
			
		||||
            && bits[][2] == 0b10010100 && bits[][3] == 0b11000000);
 | 
			
		||||
 | 
			
		||||
        bits <<= 8;
 | 
			
		||||
        assert(bits[][0] == 0b10010100 && bits[][1] == 0b10010100
 | 
			
		||||
            && bits[][2] == 0b11000000 && bits[][3] == 0b00000000);
 | 
			
		||||
 | 
			
		||||
        bits <<= 7;
 | 
			
		||||
        assert(bits[][0] == 0b01001010 && bits[][1] == 0b01100000
 | 
			
		||||
            && bits[][2] == 0b00000000 && bits[][3] == 0b00000000);
 | 
			
		||||
 | 
			
		||||
        bits <<= 25;
 | 
			
		||||
        assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000
 | 
			
		||||
            && bits[][2] == 0b00000000 && bits[][3] == 0b00000000);
 | 
			
		||||
 | 
			
		||||
        arr = [0b00110011, 0b11001100, 0b11111111, 0b01010101];
 | 
			
		||||
        bits <<= 24;
 | 
			
		||||
        assert(bits[][0] == 0b01010101 && bits[][1] == 0b00000000
 | 
			
		||||
            && bits[][2] == 0b00000000 && bits[][3] == 0b00000000);
 | 
			
		||||
 | 
			
		||||
        arr[1] = 0b11001100;
 | 
			
		||||
        arr[2] = 0b11111111;
 | 
			
		||||
        arr[3] = 0b01010101;
 | 
			
		||||
        bits <<= 12;
 | 
			
		||||
        assert(bits[][0] == 0b11001111 && bits[][1] == 0b11110101
 | 
			
		||||
            && bits[][2] == 0b01010000 && bits[][3] == 0b00000000);
 | 
			
		||||
 | 
			
		||||
        bits <<= 100;
 | 
			
		||||
        assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000
 | 
			
		||||
            && bits[][2] == 0b00000000 && bits[][3] == 0b00000000);
 | 
			
		||||
 | 
			
		||||
        arr = [0b10111110, 0b11110010, 0b01010010, 0b01010011];
 | 
			
		||||
        bits >>= 0;
 | 
			
		||||
        assert(bits[][0] == 0b10111110 && bits[][1] == 0b11110010
 | 
			
		||||
            && bits[][2] == 0b01010010 && bits[][3] == 0b01010011);
 | 
			
		||||
 | 
			
		||||
        bits >>= 2;
 | 
			
		||||
        assert(bits[][0] == 0b00101111 && bits[][1] == 0b10111100
 | 
			
		||||
            && bits[][2] == 0b10010100 && bits[][3] == 0b10010100);
 | 
			
		||||
 | 
			
		||||
        bits >>= 4;
 | 
			
		||||
        assert(bits[][0] == 0b00000010 && bits[][1] == 0b11111011
 | 
			
		||||
            && bits[][2] == 0b11001001 && bits[][3] == 0b01001001);
 | 
			
		||||
 | 
			
		||||
        bits >>= 8;
 | 
			
		||||
        assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000010
 | 
			
		||||
            && bits[][2] == 0b11111011 && bits[][3] == 0b11001001);
 | 
			
		||||
 | 
			
		||||
        bits >>= 7;
 | 
			
		||||
        assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000
 | 
			
		||||
            && bits[][2] == 0b00000101 && bits[][3] == 0b11110111);
 | 
			
		||||
 | 
			
		||||
        bits >>= 25;
 | 
			
		||||
        assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000
 | 
			
		||||
            && bits[][2] == 0b00000000 && bits[][3] == 0b00000000);
 | 
			
		||||
 | 
			
		||||
        arr = [0b00110011, 0b11001100, 0b11111111, 0b01010101];
 | 
			
		||||
        bits >>= 24;
 | 
			
		||||
        assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000
 | 
			
		||||
            && bits[][2] == 0b00000000 && bits[][3] == 0b00110011);
 | 
			
		||||
 | 
			
		||||
        arr[1] = 0b11001100;
 | 
			
		||||
        arr[2] = 0b11111111;
 | 
			
		||||
        arr[3] = 0b01010101;
 | 
			
		||||
        bits >>= 12;
 | 
			
		||||
        assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000
 | 
			
		||||
            && bits[][2] == 0b00001100 && bits[][3] == 0b11001111);
 | 
			
		||||
 | 
			
		||||
        bits >>= 100;
 | 
			
		||||
        assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000
 | 
			
		||||
            && bits[][2] == 0b00000000 && bits[][3] == 0b00000000);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Negates all bits.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: $(D_KEYWORD this).
 | 
			
		||||
     */
 | 
			
		||||
    BitVector opUnary(string op)() pure nothrow @safe @nogc
 | 
			
		||||
        if (op == "~")
 | 
			
		||||
    {
 | 
			
		||||
        foreach (ref b; vector)
 | 
			
		||||
        {
 | 
			
		||||
            b = ~b;
 | 
			
		||||
        }
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        // [01000001, 00001101, 10101101]
 | 
			
		||||
        ubyte[3] arr = [65, 13, 173];
 | 
			
		||||
        auto bits = BitVector(arr);
 | 
			
		||||
 | 
			
		||||
        ~bits;
 | 
			
		||||
        assert(bits[][0] == 0b10111110);
 | 
			
		||||
        assert(bits[][1] == 0b11110010);
 | 
			
		||||
        assert(bits[][2] == 0b01010010);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Iterates through all bits.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     *  dg = $(D_KEYWORD foreach) delegate.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: By $(D_PARAM dg) returned value.
 | 
			
		||||
     */
 | 
			
		||||
    int opApply(int delegate(size_t, bool) dg)
 | 
			
		||||
    {
 | 
			
		||||
        int result;
 | 
			
		||||
        foreach (i, ref v; vector)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (c; 0..8)
 | 
			
		||||
            {
 | 
			
		||||
                result = dg(i * 8 + c, (v & (0x80 >> c)) != 0);
 | 
			
		||||
                if (result)
 | 
			
		||||
                {
 | 
			
		||||
                    return result;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Ditto.
 | 
			
		||||
    int opApply(int delegate(bool) dg)
 | 
			
		||||
    {
 | 
			
		||||
        int result;
 | 
			
		||||
        foreach (ref v; vector)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (c; 0..8)
 | 
			
		||||
            {
 | 
			
		||||
                result = dg((v & (0x80 >> c)) != 0);
 | 
			
		||||
                if (result)
 | 
			
		||||
                {
 | 
			
		||||
                    return result;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        ubyte[2] arr = [0b01000001, 0b00001101];
 | 
			
		||||
        auto bits = BitVector(arr);
 | 
			
		||||
        size_t c;
 | 
			
		||||
 | 
			
		||||
        foreach (i, v; bits)
 | 
			
		||||
        {
 | 
			
		||||
            assert(i == c);
 | 
			
		||||
            if (i == 1 || i == 7 || i == 15 || i == 13 || i == 12)
 | 
			
		||||
            {
 | 
			
		||||
                assert(v);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                assert(!v);
 | 
			
		||||
            }
 | 
			
		||||
            ++c;
 | 
			
		||||
        }
 | 
			
		||||
        assert(c == 16);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -9,14 +9,14 @@
 | 
			
		||||
 * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
 | 
			
		||||
 *                  Mozilla Public License, v. 2.0).
 | 
			
		||||
 * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
 | 
			
		||||
 */  
 | 
			
		||||
 */
 | 
			
		||||
module tanya.container.entry;
 | 
			
		||||
 | 
			
		||||
package struct SEntry(T)
 | 
			
		||||
{
 | 
			
		||||
	/// Item content.
 | 
			
		||||
	T content;
 | 
			
		||||
    /// Item content.
 | 
			
		||||
    T content;
 | 
			
		||||
 | 
			
		||||
	/// Next item.
 | 
			
		||||
	SEntry* next;
 | 
			
		||||
    /// Next item.
 | 
			
		||||
    SEntry* next;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,13 +3,16 @@
 | 
			
		||||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Abstract data types whose instances are collections of other objects.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright: Eugene Wissner 2016-2017.
 | 
			
		||||
 * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
 | 
			
		||||
 *                  Mozilla Public License, v. 2.0).
 | 
			
		||||
 * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
 | 
			
		||||
 */  
 | 
			
		||||
 */
 | 
			
		||||
module tanya.container;
 | 
			
		||||
 | 
			
		||||
public import tanya.container.bitvector;
 | 
			
		||||
public import tanya.container.buffer;
 | 
			
		||||
public import tanya.container.list;
 | 
			
		||||
public import tanya.container.vector;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,11 +3,13 @@
 | 
			
		||||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * FIFO queue.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright: Eugene Wissner 2016-2017.
 | 
			
		||||
 * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
 | 
			
		||||
 *                  Mozilla Public License, v. 2.0).
 | 
			
		||||
 * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
 | 
			
		||||
 */  
 | 
			
		||||
 */
 | 
			
		||||
module tanya.container.queue;
 | 
			
		||||
 | 
			
		||||
import core.exception;
 | 
			
		||||
@@ -20,267 +22,267 @@ import tanya.memory;
 | 
			
		||||
 * FIFO queue.
 | 
			
		||||
 *
 | 
			
		||||
 * Params:
 | 
			
		||||
 * 	T = Content type.
 | 
			
		||||
 *  T = Content type.
 | 
			
		||||
 */
 | 
			
		||||
struct Queue(T)
 | 
			
		||||
{
 | 
			
		||||
	/**
 | 
			
		||||
	 * Removes all elements from the queue.
 | 
			
		||||
	 */
 | 
			
		||||
	~this()
 | 
			
		||||
	{
 | 
			
		||||
		while (!empty)
 | 
			
		||||
		{
 | 
			
		||||
			dequeue();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
    /**
 | 
			
		||||
     * Removes all elements from the queue.
 | 
			
		||||
     */
 | 
			
		||||
    ~this()
 | 
			
		||||
    {
 | 
			
		||||
        while (!empty)
 | 
			
		||||
        {
 | 
			
		||||
            dequeue();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Returns how many elements are in the queue. It iterates through the queue
 | 
			
		||||
	 * to count the elements.
 | 
			
		||||
	 *
 | 
			
		||||
	 * Returns: How many elements are in the queue.
 | 
			
		||||
	 */
 | 
			
		||||
	size_t length() const
 | 
			
		||||
	{
 | 
			
		||||
		size_t len;
 | 
			
		||||
		for (const(SEntry!T)* i = first; i !is null; i = i.next)
 | 
			
		||||
		{
 | 
			
		||||
			++len;
 | 
			
		||||
		}
 | 
			
		||||
		return len;
 | 
			
		||||
	}
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns how many elements are in the queue. It iterates through the queue
 | 
			
		||||
     * to count the elements.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: How many elements are in the queue.
 | 
			
		||||
     */
 | 
			
		||||
    size_t length() const
 | 
			
		||||
    {
 | 
			
		||||
        size_t len;
 | 
			
		||||
        for (const(SEntry!T)* i = first; i !is null; i = i.next)
 | 
			
		||||
        {
 | 
			
		||||
            ++len;
 | 
			
		||||
        }
 | 
			
		||||
        return len;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	unittest
 | 
			
		||||
	{
 | 
			
		||||
		Queue!int q;
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        Queue!int q;
 | 
			
		||||
 | 
			
		||||
		assert(q.length == 0);
 | 
			
		||||
		q.enqueue(5);
 | 
			
		||||
		assert(q.length == 1);
 | 
			
		||||
		q.enqueue(4);
 | 
			
		||||
		assert(q.length == 2);
 | 
			
		||||
		q.enqueue(9);
 | 
			
		||||
		assert(q.length == 3);
 | 
			
		||||
        assert(q.length == 0);
 | 
			
		||||
        q.enqueue(5);
 | 
			
		||||
        assert(q.length == 1);
 | 
			
		||||
        q.enqueue(4);
 | 
			
		||||
        assert(q.length == 2);
 | 
			
		||||
        q.enqueue(9);
 | 
			
		||||
        assert(q.length == 3);
 | 
			
		||||
 | 
			
		||||
		q.dequeue();
 | 
			
		||||
		assert(q.length == 2);
 | 
			
		||||
		q.dequeue();
 | 
			
		||||
		assert(q.length == 1);
 | 
			
		||||
		q.dequeue();
 | 
			
		||||
		assert(q.length == 0);
 | 
			
		||||
	}
 | 
			
		||||
        q.dequeue();
 | 
			
		||||
        assert(q.length == 2);
 | 
			
		||||
        q.dequeue();
 | 
			
		||||
        assert(q.length == 1);
 | 
			
		||||
        q.dequeue();
 | 
			
		||||
        assert(q.length == 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	private void enqueueEntry(ref SEntry!T* entry)
 | 
			
		||||
	{
 | 
			
		||||
		if (empty)
 | 
			
		||||
		{
 | 
			
		||||
			first = rear = entry;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			rear.next = entry;
 | 
			
		||||
			rear = rear.next;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
    private void enqueueEntry(ref SEntry!T* entry)
 | 
			
		||||
    {
 | 
			
		||||
        if (empty)
 | 
			
		||||
        {
 | 
			
		||||
            first = rear = entry;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            rear.next = entry;
 | 
			
		||||
            rear = rear.next;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	private SEntry!T* allocateEntry()
 | 
			
		||||
	{
 | 
			
		||||
		auto temp = cast(SEntry!T*) allocator.allocate(SEntry!T.sizeof);
 | 
			
		||||
		if (temp is null)
 | 
			
		||||
		{
 | 
			
		||||
			onOutOfMemoryError();
 | 
			
		||||
		}
 | 
			
		||||
		return temp;
 | 
			
		||||
	}
 | 
			
		||||
    private SEntry!T* allocateEntry()
 | 
			
		||||
    {
 | 
			
		||||
        auto temp = cast(SEntry!T*) allocator.allocate(SEntry!T.sizeof);
 | 
			
		||||
        if (temp is null)
 | 
			
		||||
        {
 | 
			
		||||
            onOutOfMemoryError();
 | 
			
		||||
        }
 | 
			
		||||
        return temp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Inserts a new element.
 | 
			
		||||
	 *
 | 
			
		||||
	 * Params:
 | 
			
		||||
	 * 	x = New element.
 | 
			
		||||
	 */
 | 
			
		||||
	void enqueue(ref T x)
 | 
			
		||||
	{
 | 
			
		||||
		auto temp = allocateEntry();
 | 
			
		||||
    /**
 | 
			
		||||
     * Inserts a new element.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     *  x = New element.
 | 
			
		||||
     */
 | 
			
		||||
    void enqueue(ref T x)
 | 
			
		||||
    {
 | 
			
		||||
        auto temp = allocateEntry();
 | 
			
		||||
 | 
			
		||||
		*temp = SEntry!T.init;
 | 
			
		||||
		temp.content = x;
 | 
			
		||||
        *temp = SEntry!T.init;
 | 
			
		||||
        temp.content = x;
 | 
			
		||||
 | 
			
		||||
		enqueueEntry(temp);
 | 
			
		||||
	}
 | 
			
		||||
        enqueueEntry(temp);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/// Ditto.
 | 
			
		||||
	void enqueue(T x)
 | 
			
		||||
	{
 | 
			
		||||
		auto temp = allocateEntry();
 | 
			
		||||
    /// Ditto.
 | 
			
		||||
    void enqueue(T x)
 | 
			
		||||
    {
 | 
			
		||||
        auto temp = allocateEntry();
 | 
			
		||||
 | 
			
		||||
		moveEmplace(x, (*temp).content);
 | 
			
		||||
		(*temp).next = null;
 | 
			
		||||
        moveEmplace(x, (*temp).content);
 | 
			
		||||
        (*temp).next = null;
 | 
			
		||||
 | 
			
		||||
		enqueueEntry(temp);
 | 
			
		||||
	}
 | 
			
		||||
        enqueueEntry(temp);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	unittest
 | 
			
		||||
	{
 | 
			
		||||
		Queue!int q;
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        Queue!int q;
 | 
			
		||||
 | 
			
		||||
		assert(q.empty);
 | 
			
		||||
		q.enqueue(8);
 | 
			
		||||
		q.enqueue(9);
 | 
			
		||||
		assert(q.dequeue() == 8);
 | 
			
		||||
		assert(q.dequeue() == 9);
 | 
			
		||||
	}
 | 
			
		||||
        assert(q.empty);
 | 
			
		||||
        q.enqueue(8);
 | 
			
		||||
        q.enqueue(9);
 | 
			
		||||
        assert(q.dequeue() == 8);
 | 
			
		||||
        assert(q.dequeue() == 9);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Returns: $(D_KEYWORD true) if the queue is empty.
 | 
			
		||||
	 */
 | 
			
		||||
	@property bool empty() const
 | 
			
		||||
	{
 | 
			
		||||
		return first is null;
 | 
			
		||||
	}
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns: $(D_KEYWORD true) if the queue is empty.
 | 
			
		||||
     */
 | 
			
		||||
    @property bool empty() const
 | 
			
		||||
    {
 | 
			
		||||
        return first is null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	unittest
 | 
			
		||||
	{
 | 
			
		||||
		Queue!int q;
 | 
			
		||||
		int value = 7;
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        Queue!int q;
 | 
			
		||||
        int value = 7;
 | 
			
		||||
 | 
			
		||||
		assert(q.empty);
 | 
			
		||||
		q.enqueue(value);
 | 
			
		||||
		assert(!q.empty);
 | 
			
		||||
	}
 | 
			
		||||
        assert(q.empty);
 | 
			
		||||
        q.enqueue(value);
 | 
			
		||||
        assert(!q.empty);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Move the position to the next element.
 | 
			
		||||
	 *
 | 
			
		||||
	 * Returns: Dequeued element.
 | 
			
		||||
	 */
 | 
			
		||||
	T dequeue()
 | 
			
		||||
	in
 | 
			
		||||
	{
 | 
			
		||||
		assert(!empty);
 | 
			
		||||
	}
 | 
			
		||||
	body
 | 
			
		||||
	{
 | 
			
		||||
		auto n = first.next;
 | 
			
		||||
		T ret = move(first.content);
 | 
			
		||||
    /**
 | 
			
		||||
     * Move the position to the next element.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: Dequeued element.
 | 
			
		||||
     */
 | 
			
		||||
    T dequeue()
 | 
			
		||||
    in
 | 
			
		||||
    {
 | 
			
		||||
        assert(!empty);
 | 
			
		||||
    }
 | 
			
		||||
    body
 | 
			
		||||
    {
 | 
			
		||||
        auto n = first.next;
 | 
			
		||||
        T ret = move(first.content);
 | 
			
		||||
 | 
			
		||||
		allocator.dispose(first);
 | 
			
		||||
		first = n;
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
        allocator.dispose(first);
 | 
			
		||||
        first = n;
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	unittest
 | 
			
		||||
	{
 | 
			
		||||
		Queue!int q;
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        Queue!int q;
 | 
			
		||||
 | 
			
		||||
		q.enqueue(8);
 | 
			
		||||
		q.enqueue(9);
 | 
			
		||||
		assert(q.dequeue() == 8);
 | 
			
		||||
		assert(q.dequeue() == 9);
 | 
			
		||||
	}
 | 
			
		||||
        q.enqueue(8);
 | 
			
		||||
        q.enqueue(9);
 | 
			
		||||
        assert(q.dequeue() == 8);
 | 
			
		||||
        assert(q.dequeue() == 9);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * $(D_KEYWORD foreach) iteration. The elements will be automatically
 | 
			
		||||
	 * dequeued.
 | 
			
		||||
	 *
 | 
			
		||||
	 * Params:
 | 
			
		||||
	 * 	dg = $(D_KEYWORD foreach) body.
 | 
			
		||||
	 *
 | 
			
		||||
	 * Returns: The value returned from $(D_PARAM dg).
 | 
			
		||||
	 */
 | 
			
		||||
	int opApply(scope int delegate(ref size_t i, ref T) @nogc dg)
 | 
			
		||||
	{
 | 
			
		||||
		int result;
 | 
			
		||||
    /**
 | 
			
		||||
     * $(D_KEYWORD foreach) iteration. The elements will be automatically
 | 
			
		||||
     * dequeued.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     *  dg = $(D_KEYWORD foreach) body.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: The value returned from $(D_PARAM dg).
 | 
			
		||||
     */
 | 
			
		||||
    int opApply(scope int delegate(ref size_t i, ref T) @nogc dg)
 | 
			
		||||
    {
 | 
			
		||||
        int result;
 | 
			
		||||
 | 
			
		||||
		for (size_t i = 0; !empty; ++i)
 | 
			
		||||
		{
 | 
			
		||||
			auto e = dequeue();
 | 
			
		||||
			if ((result = dg(i, e)) != 0)
 | 
			
		||||
			{
 | 
			
		||||
				return result;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return result;
 | 
			
		||||
	}
 | 
			
		||||
        for (size_t i = 0; !empty; ++i)
 | 
			
		||||
        {
 | 
			
		||||
            auto e = dequeue();
 | 
			
		||||
            if ((result = dg(i, e)) != 0)
 | 
			
		||||
            {
 | 
			
		||||
                return result;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/// Ditto.
 | 
			
		||||
	int opApply(scope int delegate(ref T) @nogc dg)
 | 
			
		||||
	{
 | 
			
		||||
		int result;
 | 
			
		||||
    /// Ditto.
 | 
			
		||||
    int opApply(scope int delegate(ref T) @nogc dg)
 | 
			
		||||
    {
 | 
			
		||||
        int result;
 | 
			
		||||
 | 
			
		||||
		while (!empty)
 | 
			
		||||
		{
 | 
			
		||||
			auto e = dequeue();
 | 
			
		||||
			if ((result = dg(e)) != 0)
 | 
			
		||||
			{
 | 
			
		||||
				return result;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return result;
 | 
			
		||||
	}
 | 
			
		||||
        while (!empty)
 | 
			
		||||
        {
 | 
			
		||||
            auto e = dequeue();
 | 
			
		||||
            if ((result = dg(e)) != 0)
 | 
			
		||||
            {
 | 
			
		||||
                return result;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	///
 | 
			
		||||
	unittest
 | 
			
		||||
	{
 | 
			
		||||
		Queue!int q;
 | 
			
		||||
    ///
 | 
			
		||||
    unittest
 | 
			
		||||
    {
 | 
			
		||||
        Queue!int q;
 | 
			
		||||
 | 
			
		||||
		size_t j;
 | 
			
		||||
		q.enqueue(5);
 | 
			
		||||
		q.enqueue(4);
 | 
			
		||||
		q.enqueue(9);
 | 
			
		||||
		foreach (i, e; q)
 | 
			
		||||
		{
 | 
			
		||||
			assert(i != 2 || e == 9);
 | 
			
		||||
			assert(i != 1 || e == 4);
 | 
			
		||||
			assert(i != 0 || e == 5);
 | 
			
		||||
			++j;
 | 
			
		||||
		}
 | 
			
		||||
		assert(j == 3);
 | 
			
		||||
		assert(q.empty);
 | 
			
		||||
        size_t j;
 | 
			
		||||
        q.enqueue(5);
 | 
			
		||||
        q.enqueue(4);
 | 
			
		||||
        q.enqueue(9);
 | 
			
		||||
        foreach (i, e; q)
 | 
			
		||||
        {
 | 
			
		||||
            assert(i != 2 || e == 9);
 | 
			
		||||
            assert(i != 1 || e == 4);
 | 
			
		||||
            assert(i != 0 || e == 5);
 | 
			
		||||
            ++j;
 | 
			
		||||
        }
 | 
			
		||||
        assert(j == 3);
 | 
			
		||||
        assert(q.empty);
 | 
			
		||||
 | 
			
		||||
		j = 0;
 | 
			
		||||
		q.enqueue(5);
 | 
			
		||||
		q.enqueue(4);
 | 
			
		||||
		q.enqueue(9);
 | 
			
		||||
		foreach (e; q)
 | 
			
		||||
		{
 | 
			
		||||
			assert(j != 2 || e == 9);
 | 
			
		||||
			assert(j != 1 || e == 4);
 | 
			
		||||
			assert(j != 0 || e == 5);
 | 
			
		||||
			++j;
 | 
			
		||||
		}
 | 
			
		||||
		assert(j == 3);
 | 
			
		||||
		assert(q.empty);
 | 
			
		||||
	}
 | 
			
		||||
        j = 0;
 | 
			
		||||
        q.enqueue(5);
 | 
			
		||||
        q.enqueue(4);
 | 
			
		||||
        q.enqueue(9);
 | 
			
		||||
        foreach (e; q)
 | 
			
		||||
        {
 | 
			
		||||
            assert(j != 2 || e == 9);
 | 
			
		||||
            assert(j != 1 || e == 4);
 | 
			
		||||
            assert(j != 0 || e == 5);
 | 
			
		||||
            ++j;
 | 
			
		||||
        }
 | 
			
		||||
        assert(j == 3);
 | 
			
		||||
        assert(q.empty);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	private SEntry!T* first;
 | 
			
		||||
	private SEntry!T* rear;
 | 
			
		||||
    private SEntry!T* first;
 | 
			
		||||
    private SEntry!T* rear;
 | 
			
		||||
 | 
			
		||||
	mixin DefaultAllocator;
 | 
			
		||||
    mixin DefaultAllocator;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///
 | 
			
		||||
unittest
 | 
			
		||||
{
 | 
			
		||||
	Queue!int q;
 | 
			
		||||
    Queue!int q;
 | 
			
		||||
 | 
			
		||||
	q.enqueue(5);
 | 
			
		||||
	assert(!q.empty);
 | 
			
		||||
    q.enqueue(5);
 | 
			
		||||
    assert(!q.empty);
 | 
			
		||||
 | 
			
		||||
	q.enqueue(4);
 | 
			
		||||
	q.enqueue(9);
 | 
			
		||||
    q.enqueue(4);
 | 
			
		||||
    q.enqueue(9);
 | 
			
		||||
 | 
			
		||||
	assert(q.dequeue() == 5);
 | 
			
		||||
    assert(q.dequeue() == 5);
 | 
			
		||||
 | 
			
		||||
	foreach (i, ref e; q)
 | 
			
		||||
	{
 | 
			
		||||
		assert(i != 0 || e == 4);
 | 
			
		||||
		assert(i != 1 || e == 9);
 | 
			
		||||
	}
 | 
			
		||||
	assert(q.empty);
 | 
			
		||||
    foreach (i, ref e; q)
 | 
			
		||||
    {
 | 
			
		||||
        assert(i != 0 || e == 4);
 | 
			
		||||
        assert(i != 1 || e == 9);
 | 
			
		||||
    }
 | 
			
		||||
    assert(q.empty);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * One-dimensional array.
 | 
			
		||||
 * Single-dimensioned array.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright: Eugene Wissner 2016-2017.
 | 
			
		||||
 * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
 | 
			
		||||
@@ -166,10 +166,10 @@ struct Vector(T)
 | 
			
		||||
     * range or a static array $(D_PARAM init).
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	R         = Type of the initial range or size of the static array.
 | 
			
		||||
     * 	init      = Values to initialize the array with.
 | 
			
		||||
     * 	            to generate a list.
 | 
			
		||||
     * 	allocator = Allocator.
 | 
			
		||||
     *  R         = Type of the initial range or size of the static array.
 | 
			
		||||
     *  init      = Values to initialize the array with.
 | 
			
		||||
     *              to generate a list.
 | 
			
		||||
     *  allocator = Allocator.
 | 
			
		||||
     */
 | 
			
		||||
    this(size_t R)(T[R] init, shared Allocator allocator = defaultAllocator)
 | 
			
		||||
    {
 | 
			
		||||
@@ -200,9 +200,9 @@ struct Vector(T)
 | 
			
		||||
     * If $(D_PARAM init) is passed by reference, it will be copied.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	R         = Vector type.
 | 
			
		||||
     * 	init      = Source vector.
 | 
			
		||||
     * 	allocator = Allocator.
 | 
			
		||||
     *  R         = Vector type.
 | 
			
		||||
     *  init      = Source vector.
 | 
			
		||||
     *  allocator = Allocator.
 | 
			
		||||
     */
 | 
			
		||||
    this(R)(ref R init, shared Allocator allocator = defaultAllocator)
 | 
			
		||||
        if (is(Unqual!R == Vector))
 | 
			
		||||
@@ -268,8 +268,8 @@ struct Vector(T)
 | 
			
		||||
     * Creates a new $(D_PSYMBOL Vector).
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	len       = Initial length of the vector.
 | 
			
		||||
     * 	allocator = Allocator.
 | 
			
		||||
     *  len       = Initial length of the vector.
 | 
			
		||||
     *  allocator = Allocator.
 | 
			
		||||
     */
 | 
			
		||||
    this(in size_t len, shared Allocator allocator = defaultAllocator)
 | 
			
		||||
    {
 | 
			
		||||
@@ -281,9 +281,9 @@ struct Vector(T)
 | 
			
		||||
     * Creates a new $(D_PSYMBOL Vector).
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	len       = Initial length of the vector.
 | 
			
		||||
     * 	init      = Initial value to fill the vector with.
 | 
			
		||||
     * 	allocator = Allocator.
 | 
			
		||||
     *  len       = Initial length of the vector.
 | 
			
		||||
     *  init      = Initial value to fill the vector with.
 | 
			
		||||
     *  allocator = Allocator.
 | 
			
		||||
     */
 | 
			
		||||
    this(in size_t len, T init, shared Allocator allocator = defaultAllocator) @trusted
 | 
			
		||||
    {
 | 
			
		||||
@@ -399,7 +399,7 @@ struct Vector(T)
 | 
			
		||||
     * Expands/shrinks the vector.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	len = New length.
 | 
			
		||||
     *  len = New length.
 | 
			
		||||
     */
 | 
			
		||||
    @property void length(in size_t len) @trusted
 | 
			
		||||
    {
 | 
			
		||||
@@ -456,7 +456,7 @@ struct Vector(T)
 | 
			
		||||
     * affected.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	size = Desired size.
 | 
			
		||||
     *  size = Desired size.
 | 
			
		||||
     */
 | 
			
		||||
    void reserve(in size_t size) @trusted
 | 
			
		||||
    {
 | 
			
		||||
@@ -514,7 +514,7 @@ struct Vector(T)
 | 
			
		||||
     * $(D_PARAM length).
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	size = Desired size.
 | 
			
		||||
     *  size = Desired size.
 | 
			
		||||
     */
 | 
			
		||||
    void shrink(in size_t size) @trusted
 | 
			
		||||
    {
 | 
			
		||||
@@ -585,7 +585,7 @@ struct Vector(T)
 | 
			
		||||
     * length, all elements are removed.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	howMany = How many elements should be removed.
 | 
			
		||||
     *  howMany = How many elements should be removed.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: The number of elements removed
 | 
			
		||||
     */
 | 
			
		||||
@@ -618,7 +618,7 @@ struct Vector(T)
 | 
			
		||||
     * Remove all elements beloning to $(D_PARAM r).
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	r = Range originally obtained from this vector.
 | 
			
		||||
     *  r = Range originally obtained from this vector.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: Elements in $(D_PARAM r) after removing.
 | 
			
		||||
     *
 | 
			
		||||
@@ -674,8 +674,8 @@ struct Vector(T)
 | 
			
		||||
     * Inserts the $(D_PARAM el) into the vector.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	R  = Type of the inserted value(s) (single value, range or static array).
 | 
			
		||||
     * 	el = Value(s) should be inserted.
 | 
			
		||||
     *  R  = Type of the inserted value(s) (single value, range or static array).
 | 
			
		||||
     *  el = Value(s) should be inserted.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: The number of elements inserted.
 | 
			
		||||
     */
 | 
			
		||||
@@ -767,9 +767,9 @@ struct Vector(T)
 | 
			
		||||
     * Inserts $(D_PARAM el) before or after $(D_PARAM r).
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	R  = Type of the inserted value(s) (single value, range or static array).
 | 
			
		||||
     * 	r = Range originally obtained from this vector.
 | 
			
		||||
     * 	el = Value(s) should be inserted.
 | 
			
		||||
     *  R  = Type of the inserted value(s) (single value, range or static array).
 | 
			
		||||
     *  r  = Range originally obtained from this vector.
 | 
			
		||||
     *  el = Value(s) should be inserted.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: The number of elements inserted.
 | 
			
		||||
     */
 | 
			
		||||
@@ -946,8 +946,8 @@ struct Vector(T)
 | 
			
		||||
     * Assigns a value to the element with the index $(D_PARAM pos).
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	value = Value.
 | 
			
		||||
     * 	pos   = Position.
 | 
			
		||||
     *  value = Value.
 | 
			
		||||
     *  pos   = Position.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: Assigned value.
 | 
			
		||||
     *
 | 
			
		||||
@@ -987,8 +987,8 @@ struct Vector(T)
 | 
			
		||||
     * Assigns a range or a static array.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	R     = Range type or static array length.
 | 
			
		||||
     * 	value = Value.
 | 
			
		||||
     *  R     = Range type or static array length.
 | 
			
		||||
     *  value = Value.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: Assigned value.
 | 
			
		||||
     *
 | 
			
		||||
@@ -1025,7 +1025,7 @@ struct Vector(T)
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	pos = Index.
 | 
			
		||||
     *  pos = Index.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: The value at a specified index.
 | 
			
		||||
     *
 | 
			
		||||
@@ -1073,7 +1073,7 @@ struct Vector(T)
 | 
			
		||||
     * Comparison for equality.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	that = The vector to compare with.
 | 
			
		||||
     *  that = The vector to compare with.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: $(D_KEYWORD true) if the vectors are equal, $(D_KEYWORD false)
 | 
			
		||||
     *          otherwise.
 | 
			
		||||
@@ -1099,8 +1099,8 @@ struct Vector(T)
 | 
			
		||||
     * Comparison for equality.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	R    = Right hand side type.
 | 
			
		||||
     * 	that = Right hand side vector range.
 | 
			
		||||
     *  R    = Right hand side type.
 | 
			
		||||
     *  that = Right hand side vector range.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: $(D_KEYWORD true) if the vector and the range are equal,
 | 
			
		||||
     *          $(D_KEYWORD false) otherwise.
 | 
			
		||||
@@ -1135,7 +1135,7 @@ struct Vector(T)
 | 
			
		||||
     * $(D_KEYWORD foreach) iteration.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	dg = $(D_KEYWORD foreach) body.
 | 
			
		||||
     *  dg = $(D_KEYWORD foreach) body.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: The value returned from $(D_PARAM dg).
 | 
			
		||||
     */
 | 
			
		||||
@@ -1301,8 +1301,8 @@ struct Vector(T)
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Params:
 | 
			
		||||
     * 	i = Slice start.
 | 
			
		||||
     * 	j = Slice end.
 | 
			
		||||
     *  i = Slice start.
 | 
			
		||||
     *  j = Slice end.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: A range that iterates over elements of the container from
 | 
			
		||||
     *          index $(D_PARAM i) up to (excluding) index $(D_PARAM j).
 | 
			
		||||
@@ -1380,11 +1380,11 @@ struct Vector(T)
 | 
			
		||||
     * Slicing assignment.
 | 
			
		||||
     *
 | 
			
		||||
     * Params:
 | 
			
		||||
     *	R     = Type of the assigned slice or length of the static array should be
 | 
			
		||||
     *	        assigned.
 | 
			
		||||
     * 	value = New value (single value, input range or static array).
 | 
			
		||||
     * 	i     = Slice start.
 | 
			
		||||
     * 	j     = Slice end.
 | 
			
		||||
     *  R     = Type of the assigned slice or length of the static array should be
 | 
			
		||||
     *          assigned.
 | 
			
		||||
     *  value = New value (single value, input range or static array).
 | 
			
		||||
     *  i     = Slice start.
 | 
			
		||||
     *  j     = Slice end.
 | 
			
		||||
     *
 | 
			
		||||
     * Returns: Slice with the assigned part of the vector.
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user