|
|
1.1 root 1: //
2: // nono
1.1.1.4 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.8 root 7: //
8: // 固定長キュー
9: //
10:
1.1.1.3 root 11: #pragma once
12:
1.1 root 13: #include "header.h"
14: #include <vector>
15:
16: // 固定長キュー
17: // std::queue では出来ないことがいくつかあるので仕方なく車輪の再開発。
1.1.1.6 root 18: // std::vector を親に使っているが empty() と Empty() の動作が異なるなど
19: // しているため public にせず private 継承している。
1.1 root 20: //
21: // T 型で上限 capacity 個のキュー。
22: // スレッドセーフではない。
1.1.1.10 root 23: template <typename T, uint capacity>
24: class FixedQueue final : private std::vector<T>
1.1 root 25: {
1.1.1.6 root 26: using inherited = std::vector<T>;
1.1 root 27: public:
28: // コンストラクタ
29: FixedQueue()
1.1.1.6 root 30: : inherited(capacity)
1.1 root 31: {
32: }
33:
34: // デストラクタ
1.1.1.10 root 35: ~FixedQueue() {
1.1 root 36: }
37:
38: // 空にする
39: void Clear() {
40: start = 0;
41: length = 0;
42: }
43:
1.1.1.6 root 44: // 空きがあれば追加して true を返す。
45: // 空きがなければ何もせず false を返す。
1.1.1.8 root 46: bool Enqueue(const T& val) {
1.1.1.6 root 47: if (IsFull()) {
48: return false;
49: } else {
50: (*this)[(start + length) % capacity] = val;
1.1 root 51: length++;
52: return true;
53: }
54: }
55:
1.1.1.6 root 56: // 空きがなければ古いのを捨てて追加する。
1.1.1.8 root 57: void EnqueueForce(const T& val) {
1.1.1.6 root 58: if (IsFull()) {
59: Dequeue();
60: }
61: Enqueue(val);
62: }
63:
1.1 root 64: // 取り出し
65: // 要素が1つ以上あれば *outp に取り出して true を返す。
66: // キューが空なら false を返す。
67: bool Dequeue(T *outp) {
68: if (length > 0) {
69: // 1つ以上あれば取り出し
1.1.1.6 root 70: *outp = (*this)[start];
1.1 root 71: start = (start + 1) % capacity;
72: length--;
73: return true;
74: } else {
75: return false;
76: }
77: }
78:
79: // 取り出し
80: // 先頭の要素を取り出して返す。
1.1.1.6 root 81: // キューが空の時に呼ぶと T() が返る。
1.1 root 82: T Dequeue() {
83: if (length > 0) {
1.1.1.6 root 84: T val = (*this)[start];
1.1 root 85: start = (start + 1) % capacity;
86: length--;
1.1.1.6 root 87: return val;
88: } else {
89: return T();
1.1 root 90: }
91: }
92:
93: // 現在の要素数を取得
94: uint Length() const {
95: return length;
96: }
97:
1.1.1.6 root 98: // 要素が空なら true を返す
99: bool Empty() const {
100: return (length == 0);
101: }
102:
1.1.1.2 root 103: // 要素が一杯なら true を返す
104: bool IsFull() const {
1.1.1.6 root 105: return (Length() >= capacity);
1.1.1.2 root 106: }
107:
1.1 root 108: // 要素を覗き見る。
109: // idx は 0 .. length-1 までで、0 がキューの先頭。
1.1.1.10 root 110: T Peek(uint idx) const {
1.1 root 111: // XXX 範囲チェックすべきだがとりあえず
1.1.1.6 root 112: return (*this)[(start + idx) % capacity];
113: }
1.1.1.12! root 114: // 最新の要素を覗き見る。
! 115: T PeekLatest() const {
! 116: return Peek(Length() - 1);
! 117: }
1.1.1.6 root 118:
119: // 要素数を返す
1.1.1.10 root 120: constexpr uint Capacity() const {
1.1.1.6 root 121: return capacity;
1.1 root 122: }
123:
1.1.1.9 root 124: // 先頭側から追加する。
125: // 空きがなければ何もせず false を返す。
126: bool PushFront(const T& val) {
127: if (IsFull()) {
128: return false;
129: } else {
130: start = (start + capacity - 1) % capacity;
131: (*this)[start] = val;
132: length++;
133: return true;
134: }
135: }
136:
1.1.1.11 root 137: // 移動平均値を返す。(T が数値型のときに限る)
138: T GetMovingAverage() const
139: {
140: static_assert(std::is_arithmetic<T>::value, "T must be arithmetic");
141:
142: if (Empty()) {
143: return 0;
144: }
145: T sum = 0;
146: for (uint i = 0; i < length; i++) {
147: sum += Peek(i);
148: }
149: return sum / length;
150: }
151:
1.1 root 152: private:
1.1.1.5 root 153: uint start {}; // 開始位置
154: uint length {}; // 現在有効な長さ
1.1 root 155: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.