Skip to content

Commit

Permalink
Merge branch 'main' into feature/barrett
Browse files Browse the repository at this point in the history
  • Loading branch information
kzrnm authored Sep 25, 2023
2 parents 70bc067 + 7245509 commit e7df6db
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 23 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased] - 2023-09-24
## [Unreleased]
### Added
- Add `Deque<T>.Grow(int capacity)`

### Changed
- `AtCoder.Internal.Barrett` for `2^31` < m < `2^32`
- Fix empty `Deque<T>.GetEnumerator()`

## [3.1.0] - 2023-09-24
### Added
Expand Down Expand Up @@ -36,7 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [3.0.0-pre5] - 2023-01-26
### Changed
- Fix LCPArray ¨ LcpArray
- Fix LCPArray ¨ LcpArray

## [3.0.0-pre4] - 2023-01-26
### Added
Expand Down
70 changes: 49 additions & 21 deletions Source/ac-library-csharp/STL/Deque.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;
using AtCoder.Internal;

Expand All @@ -14,7 +15,6 @@ namespace AtCoder
[DebuggerDisplay("Count = {" + nameof(Count) + "}")]
public class Deque<T> : IEnumerable<T>, IReadOnlyCollection<T>, ICollection<T>
{

[EditorBrowsable(Never)]
public T[] data;

Expand All @@ -30,14 +30,8 @@ public class Deque<T> : IEnumerable<T>, IReadOnlyCollection<T>, ICollection<T>
public Deque() : this(1) { }
public Deque(int capacity)
{
capacity =
#if NET7_0_OR_GREATER
(int)System.Numerics.BitOperations.RoundUpToPowerOf2((uint)capacity + 1u);
#else
1 << (InternalBit.CeilPow2(capacity + 1));
#endif
data = new T[capacity];
mask = capacity - 1;
data = Array.Empty<T>();
Grow(capacity);
}

public int Count => (tail - head) & mask;
Expand All @@ -64,28 +58,58 @@ public T PopLast()
[MethodImpl(256)]
public void AddFirst(T item)
{
data[head = (head - 1) & mask] = item;
if (head == tail) Resize();
var nxt = (head - 1) & mask;
if (nxt == tail)
{
Grow();
nxt = (head - 1) & mask;
}
data[nxt] = item;
head = nxt;
}
[MethodImpl(256)]
public void AddLast(T item)
{
var nxt = (tail + 1) & mask;
if (head == nxt)
{
Grow();
nxt = (tail + 1) & mask;
}
data[tail] = item;
tail = (tail + 1) & mask;
if (head == tail) Resize();
tail = nxt;
}

[EditorBrowsable(Never)]
public void Resize()
public void Grow() => Grow(Math.Max(mask << 1, 0b11));

[EditorBrowsable(Never)]
public void Grow(int capacity)
{
var oldSize = data.Length;
var newArray = new T[oldSize << 1];
capacity =
#if NET7_0_OR_GREATER
(int)BitOperations.RoundUpToPowerOf2((uint)capacity + 1u);
#else
1 << (InternalBit.CeilPow2(capacity + 1));
#endif
Debug.Assert(BitOperations.PopCount((uint)capacity) == 1);
if (capacity <= data.Length) return;
var oldSize = Count;
var newArray = new T[capacity];
if (head <= tail)
{
Array.Copy(data, head, newArray, 0, oldSize);
}
else
{
var hsize = data.Length - head;
Debug.Assert(hsize + tail == oldSize);
Array.Copy(data, head, newArray, 0, hsize);
Array.Copy(data, 0, newArray, hsize, tail);
}

var hsize = oldSize - head;
Array.Copy(data, head, newArray, 0, hsize);
Array.Copy(data, 0, newArray, hsize, tail);
data = newArray;
mask = data.Length - 1;
mask = capacity - 1;
head = 0;
tail = oldSize;
}
Expand Down Expand Up @@ -143,7 +167,11 @@ public Enumerator(Deque<T> deque, bool isReverse)
{
this.deque = deque;
this.isReverse = isReverse;
if (isReverse)
if (deque.head == deque.tail)
{
index = last = 0;
}
else if (isReverse)
{
index = deque.tail;
last = deque.head;
Expand Down
162 changes: 162 additions & 0 deletions Test/ac-library-csharp.Test/STL/DequeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,113 @@
using System.Linq;
using AtCoder.Internal;
using FluentAssertions;
using MersenneTwister;
using Xunit;

namespace AtCoder
{
public class DequeTest
{
[Fact]
public void Empty()
{
Impl(new Deque<int>());
for (int capacity = 0; capacity < 10; capacity++)
{
Impl(new Deque<int>(capacity));

var deque = new Deque<int>(capacity);
deque.AddFirst(0);
deque.PopLast();
Impl(new Deque<int>(capacity));
}

static void Impl(Deque<int> deque)
{
deque.GetEnumerator().MoveNext().Should().BeFalse();
deque.Count.Should().Be(0);
deque.Should().BeEmpty();
deque.Should().Equal(Array.Empty<int>());
}
}

[Fact]
public void Lengths()
{
for (int size = 1; size < 10; size++)
{
var orig = Enumerable.Range(1, size).ToArray();
var deque = new Deque<int>();
foreach (var num in orig)
deque.AddLast(num);
deque.Count.Should().Be(size);
deque.Should().Equal(orig);
}
}

[Fact]
public void Random()
{
var mt = MTRandom.Create();
var deque = new Deque<int>();
var list = new LinkedList<int>();

void AddFirst(int num)
{
deque.AddFirst(num);
list.AddFirst(num);
deque.Should().Equal(list);
}

void AddLast(int num)
{
deque.AddLast(num);
list.AddLast(num);
deque.Should().Equal(list);
}
void PopFirst()
{
deque.PopFirst();
list.RemoveFirst();
deque.Should().Equal(list);
}

void PopLast()
{
deque.PopLast();
list.RemoveLast();
deque.Should().Equal(list);
}


for (int q = 0; q < 10000; q++)
{
var type = mt.Next(4);
if (deque.Count == 0) type %= 2;

switch (type)
{
case 0: AddFirst(mt.Next()); break;
case 1: AddLast(mt.Next()); break;
case 2: PopFirst(); break;
case 3: PopLast(); break;
}
}

for (int q = 0; q < 10000; q++)
{
var type = mt.Next(6);
if (deque.Count == 0) type %= 2;
switch (type)
{
case 0: AddFirst(mt.Next()); break;
case 1: AddLast(mt.Next()); break;
case 2: case 4: PopFirst(); break;
case 3: case 5: PopLast(); break;
}
}
}

[Fact]
public void Simple()
{
Expand Down Expand Up @@ -129,5 +230,66 @@ public void Enumerate()
deque.Should().Equal(new[] { 1, 2, 3, 4, 5 });
deque.Reversed().Should().Equal(new[] { 5, 4, 3, 2, 1 });
}

[Fact]
public void Grow()
{
{
var deque = new Deque<int> { 1, };
deque.Should().Equal(new[] { 1, });
deque.Grow(6);
deque.data.Should().HaveCount(8);
deque.Should().Equal(new[] { 1, });
}
{
var deque = new Deque<int> { 1, 2, 3, };
deque.Should().Equal(new[] { 1, 2, 3, });
deque.Grow(6);
deque.data.Should().HaveCount(8);
deque.Should().Equal(new[] { 1, 2, 3, });
}
{
var deque = new Deque<int> { 1, 2, 3, };
deque.Should().Equal(new[] { 1, 2, 3, });
deque.PopFirst();
deque.Grow(6);
deque.data.Should().HaveCount(8);
deque.Should().Equal(new[] { 2, 3, });
}
{
var deque = new Deque<int> { 1, 2, 3, };
deque.Should().Equal(new[] { 1, 2, 3, });
deque.PopFirst();
deque.PopFirst();
deque.AddLast(-1);
deque.AddLast(-2);
deque.PopFirst();
deque.Grow(6);
deque.data.Should().HaveCount(8);
deque.Should().Equal(new[] { -1, -2, });
}
{
var deque = new Deque<int> { 1, 2, 3, };
deque.Should().Equal(new[] { 1, 2, 3, });
deque.PopFirst();
deque.PopFirst();
deque.PopFirst();
deque.Should().BeEmpty();
deque.Grow(6);
deque.data.Should().HaveCount(8);
deque.Should().BeEmpty();
}
{
var deque = new Deque<int> { 1, 2, 3, };
deque.Should().Equal(new[] { 1, 2, 3, });
deque.PopLast();
deque.PopFirst();
deque.PopFirst();
deque.Should().BeEmpty();
deque.Grow(6);
deque.data.Should().HaveCount(8);
deque.Should().BeEmpty();
}
}
}
}

0 comments on commit e7df6db

Please sign in to comment.