Std

Mainly a port of Rust's std.
git clone https://git.philomathiclife.com/repos/Std
Log | Files | Refs | README

VecDeque.cs (28023B)


      1 using Std.Clone;
      2 using Std.Cmp;
      3 using Std.Convert;
      4 using Std.Iter;
      5 using Std.Maybe;
      6 using Std.Num;
      7 using Std.Ops;
      8 using Std.Vec;
      9 using System;
     10 using Std.Result;
     11 using System.Runtime.CompilerServices;
     12 using System.Runtime.InteropServices;
     13 #region Namespaces
     14 namespace Std.Collections.VecDeque {
     15     #region Types
     16     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 0)]
     17     public struct IntoIterator<T>: IDoubleEndedIterator<T>, IExactSizeIterator<T>, IFusedIterator<T>, IInto<IntoIterator<T>>, IIntoIterator<T, IntoIterator<T>> where T: notnull {
     18 
     19         #region Type-level Constructors
     20         #endregion
     21 
     22         #region Instance Constructors
     23         public IntoIterator() => throw new InvalidOperationException("Parameterless constructor is not allowed to be called!");
     24         [MethodImpl(MethodImplOptions.AggressiveInlining)]
     25         internal IntoIterator(VecDeque<T> inner) => _inner = inner;
     26         #endregion
     27 
     28         #region Type-level Fields
     29         #endregion
     30 
     31         #region Instance Fields
     32         VecDeque<T> _inner;
     33         #endregion
     34 
     35         #region Type-level Properties
     36         #endregion
     37 
     38         #region Instance Properties
     39         #endregion
     40 
     41         #region Type-level Functions
     42         #endregion
     43 
     44         #region Instance Functions
     45         public Result<Unit, ulong> AdvanceBy(ulong n) => IIterator<T>.AdvanceByDefault(ref this, n);
     46         public Result<Unit, ulong> AdvanceBackBy(ulong n) => IDoubleEndedIterator<T>.AdvanceBackByDefault(ref this, n);
     47         public ulong Count() => IIterator<T>.CountDefault(ref this);
     48         public override readonly bool Equals(object? _) => false;
     49         public TInit Fold<TInit>(TInit init, Fn<TInit, T, TInit> f) where TInit: notnull => IIterator<T>.FoldDefault(ref this, init, f);
     50         public override readonly int GetHashCode() => 0;
     51         public readonly IntoIterator<T> Into() => this;
     52         public readonly IntoIterator<T> IntoIter() => this;
     53         public readonly bool IsEmpty() => _inner.IsEmpty;
     54         public Maybe<T> Last() => IIterator<T>.LastDefault(ref this);
     55         public readonly ulong Len() => SizeHint().Item0;
     56         [MethodImpl(MethodImplOptions.AggressiveInlining)]
     57         public Maybe<T> Next() => _inner.PopFront();
     58         public Maybe<T> NextBack() => _inner.PopBack();
     59         public TInit RFold<TInit>(TInit init, Fn<TInit, T, TInit> f) where TInit: notnull => IDoubleEndedIterator<T>.RFoldDefault(ref this, init, f);
     60         public readonly Prod<ulong, Maybe<ulong>> SizeHint() {
     61 
     62             var len = _inner.Len;
     63             return new(len, new(len));
     64         }
     65         public override readonly string ToString() => string.Empty;
     66         public Result<TInit, TErr> TryFold<TInit, TErr>(TInit init, Fn<TInit, T, Result<TInit, TErr>> f) where TInit: notnull where TErr: notnull => IIterator<T>.TryFoldDefault(ref this, init, f);
     67         readonly Result<IntoIterator<T>, Bottom> ITryInto<IntoIterator<T>, Bottom>.TryInto() => new(this);
     68         public Result<TInit, TErr> TryRFold<TInit, TErr>(TInit init, Fn<TInit, T, Result<TInit, TErr>> f) where TInit: notnull where TErr: notnull => IDoubleEndedIterator<T>.TryRFoldDefault(ref this, init, f);
     69         #endregion
     70 
     71         #region Operators
     72         #endregion
     73 
     74         #region Types
     75         #endregion
     76     }
     77     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 0)]
     78     public struct VecDeque<T>: IExtend<T>, IIndex<uint, T>, IIndexMut<uint, T>, IInto<VecDeque<T>>, IIntoIterator<T, IntoIterator<T>> where T: notnull {
     79 
     80         #region Type-level Constructors
     81         #endregion
     82 
     83         #region Instance Constructors
     84         [MethodImpl(MethodImplOptions.AggressiveInlining)]
     85         public VecDeque() => (_buf, _tail, _head) = (Vec<T>.WithCapacity(Math.Max(Functions.INITIAL_CAPACITY + 1u, Functions.MINIMUM_CAPACITY + 1u).NextPowerOfTwo()), uint.MinValue, uint.MinValue);
     86         [MethodImpl(MethodImplOptions.AggressiveInlining)]
     87         public VecDeque(uint capacity) => (_buf, _tail, _head) = (Vec<T>.WithCapacity(Math.Max(capacity + 1u, Functions.MINIMUM_CAPACITY + 1u).NextPowerOfTwo()), uint.MinValue, uint.MinValue);
     88         [MethodImpl(MethodImplOptions.AggressiveInlining)]
     89         internal VecDeque(Vec<T> buf, uint tail, uint head) => (_buf, _tail, _head) = (buf, tail, head);
     90         #endregion
     91 
     92         #region Type-level Fields
     93         static T? _dummy = default;
     94         #endregion
     95 
     96         #region Instance Fields
     97         internal Vec<T> _buf;
     98         internal uint _tail;
     99         internal uint _head;
    100         #endregion
    101 
    102         #region Type-level Properties
    103         #endregion
    104 
    105         #region Instance Properties
    106         readonly uint Cap => _buf.Capacity;
    107         public readonly uint Capacity => Cap - 1u;
    108         public readonly bool IsEmpty => _tail == _head;
    109         public readonly ref readonly T this[uint index] {
    110             [MethodImpl(MethodImplOptions.AggressiveInlining)]
    111             get {
    112                 if (index < Len) {
    113                     return ref Ptr()[(int)WrapAdd(_tail, index)];
    114                 } else {
    115                     throw new InvalidOperationException($"The index, {index.ToString()}, is greater than or equal to the length, {Len.ToString()}, of the VecDeque.");
    116                 }
    117             }
    118         }
    119         public readonly uint Len => Count(_tail, _head, Cap);
    120         #endregion
    121 
    122         #region Type-level Functions
    123         static uint Count(uint tail, uint head, uint size) => (head.WrappingSub(tail)) & (size - 1u);
    124         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    125         public static VecDeque<T> New() => new(uint.MinValue);
    126         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    127         public static VecDeque<T> WithCapacity(uint capacity) => new(capacity);
    128         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    129         static uint WrapIndex(uint index, uint size) => index & (size - 1u);
    130         #endregion
    131 
    132         #region Instance Functions
    133         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    134         readonly T[] Ptr() => _buf.Array;
    135         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    136         public Unit Append(ref VecDeque<T> other) {
    137 
    138             _ = Reserve(other.Len);
    139             _ = other.AsSlices(out var left, out var right);
    140             _ = CopySlice(_head, left);
    141             _ = CopySlice(WrapAdd(_head, (uint)left.Length), right);
    142             _head = WrapAdd(_head, other.Len);
    143             other._tail = other._head;
    144             return new Unit();
    145         }
    146         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    147         public readonly Unit AsMutSlices(out Span<T> v0, out Span<T> v1) {
    148 
    149             var head = _head;
    150             var tail = _tail;
    151             var buf = BufferAsMutSlice();
    152             _ = buf.RingSlices(head, tail, out v0, out v1);
    153             return new Unit();
    154         }
    155         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    156         public readonly Unit AsSlices(out ReadOnlySpan<T> v0, out ReadOnlySpan<T> v1) {
    157 
    158             var buf = BufferAsSlice();
    159             var slices = buf.RingSlices(_head, _tail, out v0, out v1);
    160             return new Unit();
    161         }
    162         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    163         public readonly Maybe<T> Back() => Get(Len.WrappingSub(1u));
    164         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    165         public readonly ref T BackMut(out bool exists) => ref GetMut(Len.WrappingSub(1u), out exists);
    166         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    167         readonly Span<T> BufferAsMutSlice() => Ptr().AsSpan(0, (int)Cap);
    168         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    169         readonly ReadOnlySpan<T> BufferAsSlice() => Ptr().AsSpan(0, (int)Cap);
    170         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    171         readonly T BufferRead(uint off) => Ptr()[(int)off];
    172         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    173         readonly Unit BufferWrite(uint off, T value) {
    174 
    175             Ptr()[(int)off] = value;
    176             return new Unit();
    177         }
    178         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    179         readonly Unit Copy(uint dst, uint src, uint len) {
    180 
    181             var arr = Ptr();
    182             Array.Copy(arr, (int)src, arr, (int)dst, (int)len);
    183             return new Unit();
    184         }
    185         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    186         Unit CopySlice(uint dst, ReadOnlySpan<T> src) {
    187 
    188             var headRoom = Cap - dst;
    189             if ((uint)src.Length <= headRoom) {
    190                 src.CopyTo(Ptr().AsSpan((int)dst));
    191             } else {
    192                 var left = src[..(int)headRoom];
    193                 var right = src[(int)headRoom..];
    194                 var arr = Ptr();
    195                 left.CopyTo(arr.AsSpan((int)dst));
    196                 right.CopyTo(arr.AsSpan());
    197             }
    198             return new Unit();
    199         }
    200         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    201         public Unit Clear() => Truncate(uint.MinValue);
    202         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    203         readonly Unit CopyNonOverlapping(uint dst, uint src, uint len) {
    204 
    205             var ptr = Ptr();
    206             Array.Copy(ptr, (int)src, ptr, (int)dst, (int)len);
    207             return new Unit();
    208         }
    209         public override readonly bool Equals(object? _) => false;
    210         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    211         public Unit Extend<TIter>(TIter iter) where TIter: notnull, IIterator<T> {
    212 
    213             Maybe<T> mbe;
    214             while ((mbe = iter.Next()).IsSome) {
    215                 if (Len == Cap) {
    216                     var (lower, _) = iter.SizeHint();
    217                     _ = Reserve((uint)lower.SaturatingAdd(1ul));
    218                 }
    219                 var head = _head;
    220                 _head = WrapAdd(_head, 1u);
    221                 _ = BufferWrite(head, mbe.Unwrap());
    222             }
    223             return new Unit();
    224         }
    225         public Unit ExtendOne(T val) => PushBack(val);
    226         public Unit ExtendReserve(uint additional) => Reserve(additional);
    227         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    228         public readonly Maybe<T> Front() => Get(uint.MinValue);
    229         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    230         public readonly ref T FrontMut(out bool exists) => ref GetMut(uint.MinValue, out exists);
    231         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    232         public readonly Maybe<T> Get(uint index) => index < Len ? new(Ptr()[(int)WrapAdd(_tail, index)]) : Maybe<T>.None();
    233         public override readonly int GetHashCode() => 0;
    234         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    235         public readonly ref T GetMut(uint index, out bool exists) {
    236 
    237             if (index < Len) {
    238                 exists = true;
    239                 return ref Ptr()[(int)WrapAdd(_tail, index)];
    240             } else {
    241                 exists = false;
    242                 return ref _dummy!;
    243             }
    244         }
    245         [MethodImpl(MethodImplOptions.NoInlining)]
    246         Unit Grow() {
    247 
    248             var oldCap = Cap;
    249             _ = _buf.ReserveExact(oldCap);
    250             return HandleCapacityIncrease(oldCap);
    251         }
    252         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    253         Unit HandleCapacityIncrease(uint oldCapacity) {
    254 
    255             var newCapacity = Cap;
    256             if (_tail <= _head) {
    257             } else if (_head < oldCapacity - _tail) {
    258                 _ = CopyNonOverlapping(oldCapacity, uint.MinValue, _head);
    259                 _head += oldCapacity;
    260             } else {
    261                 var newTail = newCapacity - (oldCapacity - _tail);
    262                 _ = CopyNonOverlapping(newTail, _tail, oldCapacity - _tail);
    263                 _tail = newTail;
    264             }
    265             return new Unit();
    266         }
    267         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    268         public Unit Insert(uint index, T value) {
    269 
    270             if (IsFull()) { _ = Grow(); }
    271             var idx = WrapAdd(_tail, index);
    272             var distanceToTail = index;
    273             var distanceToHead = Len - index;
    274             var contiguous = IsContiguous();
    275             var dTailLEdHead = distanceToTail <= distanceToHead;
    276             var idxGETail = idx >= _tail;
    277             if (contiguous && dTailLEdHead && index == uint.MinValue) {
    278                 _tail = WrapSub(_tail, 1u);
    279             } else if (contiguous && dTailLEdHead) {
    280                 var newTail = WrapSub(_tail, 1u);
    281                 _ = Copy(newTail, _tail, 1u);
    282                 _ = Copy(_tail, _tail + 1u, index - 1u);
    283                 _tail = newTail;
    284             } else if (contiguous && !dTailLEdHead) {
    285                 _ = Copy(idx + 1u, idx, _head - idx);
    286                 _head = WrapAdd(_head, 1u);
    287             } else if (!contiguous && dTailLEdHead && idxGETail) {
    288                 _ = Copy(_tail - 1u, _tail, index);
    289                 _tail -= 1u;
    290             } else if (!contiguous && dTailLEdHead && !idxGETail && idx == uint.MinValue) {
    291                 _ = Copy(_tail - 1u, _tail, Cap - _tail);
    292                 _ = Copy(Cap - 1u, uint.MinValue, 1u);
    293                 _tail -= 1u;
    294             } else if (!contiguous && dTailLEdHead && !idxGETail ) {
    295                 _ = Copy(_tail - 1u, _tail, Cap - _tail);
    296                 _ = Copy(Cap - 1u, uint.MinValue, 1u);
    297                 _ = Copy(uint.MinValue, 1u, idx - 1u);
    298                 _tail -= 1u;
    299             } else {
    300                 _ = Copy(idx + 1u, idx, _head - idx);
    301                 _head += 1u;
    302             }
    303             var newIdx = WrapAdd(_tail, index);
    304             return BufferWrite(newIdx, value);
    305         }
    306         public readonly IntoIterator<T> IntoIter() => new(this);
    307         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    308         readonly bool IsContiguous() => _tail <= _head;
    309         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    310         readonly bool IsFull() => Cap - Len == 1u;
    311         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    312         public readonly ref T ItemMut(uint index) {
    313 
    314             if (index < Len) {
    315                 return ref Ptr()[(int)WrapAdd(_tail, index)];
    316             } else {
    317                 throw new InvalidOperationException($"The index, {index.ToString()}, is greater than or equal to the length, {Len.ToString()}, of the VecDeque.");
    318             }
    319         }
    320         public readonly VecDeque<T> Into() => this;
    321         public Span<T> MakeContiguous() {
    322 
    323             if (IsContiguous()) {
    324                 var t = _tail;
    325                 var h = _head;
    326                 _ = BufferAsMutSlice().RingSlices(h, t, out var w0, out var _);
    327                 return w0;
    328             }
    329             var buf = Ptr();
    330             var cap = Cap;
    331             var len = Len;
    332             var free = _tail - _head;
    333             var tailLen = cap - _tail;
    334             if (free >= tailLen) {
    335                 Array.Copy(buf, 0, buf, (int)tailLen, (int)_head);
    336                 Array.Copy(buf, (int)_tail, buf, 0, (int)tailLen);
    337                 _tail = uint.MinValue;
    338                 _head = len;
    339             } else if (free > _head) {
    340                 Array.Copy(buf, (int)_tail, buf, (int)_head, (int)tailLen);
    341                 Array.Copy(buf, 0, buf, (int)(_head + tailLen), (int)_head);
    342                 _tail = _head;
    343                 _head = WrapAdd(_tail, len);
    344             } else {
    345                 var leftEdge = uint.MinValue;
    346                 var rightEdge = _tail;
    347                 while (leftEdge < len && rightEdge != cap) {
    348                     var rightOffset = uint.MinValue;
    349                     for (var i = leftEdge; i < rightEdge; i++) {
    350                         rightOffset = (i - leftEdge) % (cap - rightEdge);
    351                         _ = buf.AsSpan().Swap(i, rightEdge + rightOffset);
    352                     }
    353                     var nOps = rightEdge - leftEdge;
    354                     leftEdge += nOps;
    355                     rightEdge += rightOffset + 1u;
    356                 }
    357                 _tail = uint.MinValue;
    358                 _head = len;
    359             }
    360             var tail = _tail;
    361             var head = _head;
    362             _ = BufferAsMutSlice().RingSlices(head, tail, out var v0, out var _);
    363             return v0;
    364         }
    365         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    366         public Maybe<T> PopBack() {
    367 
    368             if (IsEmpty) {
    369                 return Maybe<T>.None();
    370             } else {
    371                 _head = WrapSub(_head, 1u);
    372                 var head = _head;
    373                 return new(BufferRead(head));
    374             }
    375         }
    376         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    377         public Maybe<T> PopFront() {
    378 
    379             if (IsEmpty) {
    380                 return Maybe<T>.None();
    381             } else {
    382                 var tail = _tail;
    383                 _tail = WrapAdd(_tail, 1u);
    384                 return new(BufferRead(tail));
    385             }
    386         }
    387         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    388         public Unit PushBack(T value) {
    389 
    390             if (IsFull()) { _ = Grow(); }
    391             var head = _head;
    392             _head = WrapAdd(_head, 1u);
    393             return BufferWrite(head, value);
    394         }
    395         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    396         public Unit PushFront(T value) {
    397 
    398             if (IsFull()) { _ = Grow(); }
    399             _tail = WrapSub(_tail, 1u);
    400             var tail = _tail;
    401             return BufferWrite(tail, value);
    402         }
    403         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    404         public Maybe<T> Remove(uint index) {
    405 
    406             if (IsEmpty || Len <= index) { return Maybe<T>.None(); }
    407             var idx = WrapAdd(_tail, index);
    408             var elem = new Maybe<T>(BufferRead(idx));
    409             var distanceToTail = index;
    410             var distanceToHead = Len - index;
    411             var contiguous = IsContiguous();
    412             var dTailLEdHead = distanceToTail <= distanceToHead;
    413             var idxGETail = idx >= _tail;
    414             if (contiguous && dTailLEdHead) {
    415                 _ = Copy(_tail + 1u, _tail, index);
    416                 _tail += 1u;
    417             } else if (contiguous && !dTailLEdHead) {
    418                 _ = Copy(idx, idx + 1u, _head - idx - 1u);
    419                 _head -= 1u;
    420             } else if (!contiguous && dTailLEdHead && idxGETail) {
    421                 _ = Copy(_tail + 1u, _tail, index);
    422                 _tail = WrapAdd(_tail, 1u);
    423             } else if (!contiguous && !dTailLEdHead && !idxGETail) {
    424                 _ = Copy(idx, idx + 1u, _head - idx - 1u);
    425                 _head -= 1u;
    426             } else if (!contiguous && !dTailLEdHead && idxGETail) {
    427                 _ = Copy(idx, idx + 1u, Cap - idx - 1u);
    428                 if (_head != uint.MinValue) {
    429                     _ = Copy(Cap - 1u, uint.MinValue, 1u);
    430                     _ = Copy(uint.MinValue, 1u, _head - 1u);
    431                 }
    432                 _head = WrapSub(_head, 1u);
    433             } else {
    434                 _ = Copy(1u, uint.MinValue, idx);
    435                 _ = Copy(uint.MinValue, Cap - 1u, 1u);
    436                 _ = Copy(_tail + 1u, _tail, Cap - _tail - 1u);
    437                 _tail = WrapAdd(_tail, 1u);
    438             }
    439             return elem;
    440         }
    441         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    442         public Unit Reserve(uint additional) {
    443 
    444             var oldCap = Cap;
    445             var usedCap = Len + 1u;
    446             var newCap = usedCap.CheckedAdd(additional).AndThen(Functions.f).Expect("Capacity overflow.");
    447             if (newCap > oldCap) {
    448                 _ = _buf.ReserveExact(newCap - usedCap);
    449                 _ = HandleCapacityIncrease(oldCap);
    450             }
    451             return new Unit();
    452         }
    453         public Unit ReserveExact(uint additional) => Reserve(additional);
    454         public Unit ResizeWith(uint newLen, Fn<T> f) {
    455 
    456             var len = Len;
    457             return newLen > len ? Extend(new RepeatWith<T>(f).Take<RepeatWith<T>, T>(newLen - len)) : Truncate(newLen);
    458         }
    459         public Unit Retain(FnIn<T, bool> f) {
    460 
    461             var len = Len;
    462             var del = uint.MinValue;
    463             var iter = IntoIter();
    464             Maybe<T> mbe;
    465             var i = uint.MinValue;
    466             while ((mbe = iter.Next()).IsSome) {
    467                 if (!f(mbe.Unwrap())) {
    468                     del += 1u;
    469                 } else if (del > uint.MinValue) {
    470                     _ = Swap(i - del, i);
    471                 }
    472                 i++;
    473             }
    474             return del > uint.MinValue ? Truncate(len - del) : new Unit();
    475         }
    476         public Unit ShrinkTo(uint minCapacity) {
    477 
    478             minCapacity = Math.Min(minCapacity, Capacity);
    479             var targetCap = Math.Max(Math.Max(minCapacity, Len + 1u), Functions.MINIMUM_CAPACITY + 1u).NextPowerOfTwo();
    480             if (targetCap < Cap) {
    481                 var headOutside = _head == uint.MinValue || _head >= targetCap;
    482                 if (_tail >= targetCap && headOutside) {
    483                    _ = CopyNonOverlapping(uint.MinValue, _tail, Len);
    484                     _head = Len;
    485                     _tail = uint.MinValue;
    486                 } else if (_tail == uint.MinValue && _tail < targetCap && headOutside) {
    487                     var len = WrapSub(_head, targetCap);
    488                     _ = CopyNonOverlapping(uint.MinValue, targetCap, len);
    489                     _head = len;
    490                 } else if (_tail >= targetCap) {
    491                     var len = Cap - _tail;
    492                     var newTail = targetCap - len;
    493                     _ = CopyNonOverlapping(newTail, _tail, len);
    494                     _tail = newTail;
    495                 }
    496                 _ = _buf.ShrinkTo(targetCap);
    497             }
    498             return new Unit();
    499         }
    500         public Unit ShrinkToFit() => ShrinkTo(uint.MinValue);
    501         public VecDeque<T> SplitOff(uint at) {
    502 
    503             var len = Len;
    504             var otherLen = len - at;
    505             var other = WithCapacity(otherLen);
    506             _ = AsSlices(out var firstHalf, out var secondHalf);
    507             var firstLen = (uint)firstHalf.Length;
    508             if (at < firstLen) {
    509                 var amountInFirst = firstLen - at;
    510                 firstHalf[(int)at..].CopyTo(other.Ptr().AsSpan());
    511                 secondHalf.CopyTo(other.Ptr().AsSpan((int)amountInFirst));
    512             } else {
    513                 var offset = at - firstLen;
    514                 secondHalf[(int)offset..].CopyTo(other.Ptr().AsSpan());
    515             }
    516             _head = WrapSub(_head, otherLen);
    517             other._head = other.WrapIndex(otherLen);
    518             return other;
    519         }
    520         public readonly Unit Swap(uint i, uint j) {
    521 
    522             var ri = WrapAdd(_tail, i);
    523             var rj = WrapAdd(_tail, j);
    524             var arr = Ptr();
    525             return arr.AsSpan().Swap(ri, rj);
    526         }
    527         public Maybe<T> SwapRemoveBack(uint index) {
    528 
    529             var length = Len;
    530             if (length > uint.MinValue && index < length - 1u) {
    531                 _ = Swap(index, length - 1u);
    532             } else if (index >= length) {
    533                 return Maybe<T>.None();
    534             }
    535             return PopBack();
    536         }
    537         public Maybe<T> SwapRemoveFront(uint index) {
    538 
    539             var length = Len;
    540             if (length > uint.MinValue && index < length && index != uint.MinValue) {
    541                 _ = Swap(index, uint.MinValue);
    542             } else if (index >= length) {
    543                 return Maybe<T>.None();
    544             }
    545             return PopFront();
    546         }
    547         public override readonly string ToString() => string.Empty;
    548         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    549         public Unit Truncate(uint len) {
    550 
    551             if (len <= Len) { _head = WrapSub(_head, Len - len); }
    552             return new Unit();
    553         }
    554         readonly Result<VecDeque<T>, Bottom> ITryInto<VecDeque<T>, Bottom>.TryInto() => new(this);
    555         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    556         readonly uint WrapAdd(uint idx, uint addend) => WrapIndex(idx.WrappingAdd(addend), Cap);
    557         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    558         readonly uint WrapIndex(uint idx) => WrapIndex(idx, Cap);
    559         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    560         readonly uint WrapSub(uint idx, uint subtrahend) => WrapIndex(idx.WrappingSub(subtrahend), Cap);
    561         #endregion
    562 
    563         #region Operators
    564         #endregion
    565 
    566         #region Types
    567         #endregion
    568     }
    569     public static class Functions {
    570 
    571         #region Type-level Constructors
    572         #endregion
    573 
    574         #region Instance Constructors
    575         #endregion
    576 
    577         #region Type-level Fields
    578         internal static readonly Fn<uint, Maybe<uint>> f = (u) => u.CheckedNextPowerOfTwo();
    579         internal const uint INITIAL_CAPACITY = 7u;
    580         internal const uint MINIMUM_CAPACITY = 1u;
    581         #endregion
    582 
    583         #region Instance Fields
    584         #endregion
    585 
    586         #region Type-level Properties
    587         #endregion
    588 
    589         #region Instance Properties
    590         #endregion
    591 
    592         #region Type-level Functions
    593         public static VecDeque<T> Clone<T>(in this VecDeque<T> self) where T: notnull, IClone<T> => new(self._buf.Clone(), self._tail, self._head);
    594         // Normal queues are used when you know for sure data is to be sorted in FIFO order; however sometimes there are situations where
    595         // this is not a guarantee and only a strong statisical likelihood. In such a situation, performing a linear scan and removing the value
    596         // is going to be the fastest way to search for T (since most of the time the item will be found immediately).
    597         // If code knows for sure the queue is in FIFO, then code SHOULD use the PopBack/PopFront functions.
    598         // If code is not confident of the order, then a VecDeque should likely not be used at all.
    599         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    600         public static Maybe<uint> LinearSearch<T>(in this VecDeque<T> self, in T x) where T: notnull, IEq<T> {
    601 
    602             var iter = self.IntoIter();
    603             Maybe<T> mbe;
    604             var index = uint.MinValue;
    605             while ((mbe = iter.Next()).IsSome) {
    606                 if (mbe.Unwrap() == x) {
    607                     return new(index);
    608                 } else {
    609                     index++;
    610                 }
    611             }
    612             return new();
    613         }
    614         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    615         public static uint LinearSearchUnsafe<T>(in this VecDeque<T> self, in T x) where T: notnull, IEq<T> {
    616 
    617             var iter = self.IntoIter();
    618             Maybe<T> mbe;
    619             var index = uint.MinValue;
    620             while ((mbe = iter.Next()).IsSome) {
    621                 if (mbe.Unwrap() == x) {
    622                     return index;
    623                 } else {
    624                     index++;
    625                 }
    626             }
    627             throw new ArgumentException("The value does not exist in the VecDeque.", nameof(x));
    628         }
    629         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    630         public static Maybe<T> LinearSearchAndPop<T>(ref this VecDeque<T> self, in T x) where T: notnull, IEq<T> {
    631 
    632             var iter = self.IntoIter();
    633             Maybe<T> mbe;
    634             var index = uint.MinValue;
    635             while ((mbe = iter.Next()).IsSome) {
    636                 if (mbe.Unwrap() == x) {
    637                     return self.Remove(index);
    638                 } else {
    639                     index++;
    640                 }
    641             }
    642             return Maybe<T>.None();
    643         }
    644         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    645         public static T LinearSearchAndPopUnsafe<T>(ref this VecDeque<T> self, in T x) where T: notnull, IEq<T> {
    646 
    647             var iter = self.IntoIter();
    648             Maybe<T> mbe;
    649             var index = uint.MinValue;
    650             while ((mbe = iter.Next()).IsSome) {
    651                 if (mbe.Unwrap() == x) {
    652                     return self.Remove(index).Unwrap();
    653                 } else {
    654                     index++;
    655                 }
    656             }
    657             throw new ArgumentException("The value does not exist in the VecDeque.", nameof(x));
    658         }
    659         #endregion
    660 
    661         #region Instance Functions
    662         #endregion
    663 
    664         #region Operators
    665         #endregion
    666 
    667         #region Types
    668         #endregion
    669     }
    670     #endregion
    671 
    672     #region Namespaces
    673     #endregion
    674 }
    675 #endregion