File:  [Isaki's NoNo m68k/m88k emulator] / nono / lib / vectorbool64.h
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:56 2026 UTC (3 months ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
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 {};
};

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.