|
|
nono 1.7.0
/*
* Copyright (C) 2026 Tetsuya Isaki
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include "header.h"
#include <vector>
// uint64 に 64 ビットを詰め込んだ std::vector<bool> っぽいクラス。
// std::vector<bool> 特殊化より制約と抽象度を少し下げたもので、
// 内部構造が uint64 であることを見せている。
// 現状 capacity の概念はなく、要素数は64個単位で増減する。
//
// std::vector 互換のメソッドは小文字(というか同名)にする。
class VectorBool64
{
static constexpr std::size_t NBITS = 64;
public:
// 初期サイズ 0 で作成する。
VectorBool64() { }
// 初期サイズを指定して作成する。初期値は false。
explicit VectorBool64(std::size_t bits) {
Resize(bits);
}
// 初期サイズと初期値を指定して作成する。
VectorBool64(std::size_t bits, const bool c) {
Resize(bits, c);
}
// デストラクタ不要。
// デフォルト値を設定する。
void SetDefault(bool c) {
defval = c;
}
// 要素数(ビット数) を返す。std::vector 互換のはず。
std::size_t size() const noexcept { return capacity(); }
// メモリを再確保せずに格納できる要素数を返す。std::vector 互換のはず。
std::size_t capacity() const noexcept { return value.size() * NBITS; }
// 64 ビットバケット数を返す。
std::size_t DataSize() const noexcept { return value.size(); }
// コンテナが空なら true を返す。std::vector 互換のはず。
bool empty() const noexcept { return value.empty(); }
// 初期値 b を指定して要素数(ビット数)を sz に変更する。
// ただし bits が 64 で割り切れない場合は 64 単位に切り上げる。
void Resize(std::size_t sz, const bool b) {
auto n = howmany(sz, NBITS);
if (n != value.size()) {
uint64 initval = b ? -1 : 0;
value.resize(n, initval);
}
}
void Resize(std::size_t sz) { Resize(sz, defval); }
// 要素数(ビット数)を sz まで増やす。
// つまり増える方向だけの Resize(sz, c)。
void Expand(std::size_t sz, const bool c) {
auto n = howmany(sz, NBITS);
if (n > size()) {
Resize(sz, c);
}
}
void Expand(std::size_t sz) { Expand(sz, defval); }
// n 番目のビットを返す。
// n が範囲外なら defval を返す。
bool GetBit(std::size_t n) const {
if (__predict_false(n >= size())) {
return defval;
}
std::size_t idx = n / NBITS;
std::size_t off = n % NBITS;
return ((GetData(idx) >> off) & 1) ? true : false;
}
// n 番目にビットを b に更新する。
// n が範囲外なら何もしない?
void SetBit(std::size_t n, bool b) {
if (__predict_false(n >= size())) {
return;
}
std::size_t idx = n / NBITS;
std::size_t off = n % NBITS;
uint64 val = GetData(idx);
if (b) {
val |= 1ULL << off;
} else {
val &= ~(1ULL << off);
}
SetData(idx, val);
}
// n 番目のビットを立てる。オーバーロード…。
void SetBit(std::size_t n) { SetBit(n, true); }
// n 番目のビットをクリアする。
void ClearBit(std::size_t n) { SetBit(n, false); }
// idx 番目の 64 ビットバケットを返す。
// idx が範囲外なら defval で構成された 64 ビットを返す。
uint64 GetData(std::size_t idx) const noexcept {
if (idx < value.size()) {
return value[idx];
} else {
return defval ? -1 : 0;
}
}
// data を idx 番目の 64 ビットバケットを代入する。
// idx が範囲外なら何もしない?
void SetData(std::size_t idx, uint64 data) {
if (idx < value.size()) {
value[idx] = data;
} else {
// どうする?
}
}
private:
std::vector<uint64> value {};
// デフォルト値。
// 要素数を拡大した時の初期値と、範囲外を読んだ時の値に使われる。
bool defval {};
};
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.