Rustでビット精度の整数型を使えるようにするライブラリを作った
はじめに
Rustのプリミティブ整数型のビット幅は他の多くの言語と同様に8の倍数です。
殆どの場合はこれで十分だと思いますが、7ビットなどの8の倍数でないビット幅の整数型が欲しい場合がまれにあると思います。
今回紹介するbit-int
クレートは、そのような場合に利用できる任意のビット精度であることを保証した整数型を使えるようにするライブラリです。
作った理由
最近、C23に興味を持って調べていたときに、ビット精度の整数型の_BitInt(n)
が追加されたことを知り、Rustでもビット精度の整数型を実装してみたいと思ったので作りました。
データ型
符号付き整数型はBitInt
として実装しており、符号無し整数型はBitUint
として実装しています。
BitInt
は以下のように定義されています:
pub struct BitInt<T: Signed + PrimInt, const N: u32>(T);
T
にはnum-traits
クレートのSigned
トレイトとPrimInt
トレイトを実装している型(全てのプリミティブ符号付き整数型)を指定できます。
N
は符号ビットも含めた値のビット数です。
BitUint
は以下のように定義されています:
pub struct BitUint<T: Unsigned + PrimInt, const N: u32>(T);
T
にはnum-traits
クレートのUnsigned
トレイトとPrimInt
トレイトを実装している型(全てのプリミティブ符号無し整数型)を指定できます。
N
は値のビット数です。
N
の範囲は1
からT::BITS
で、範囲外のビット数を指定した場合にはコンパイルエラーになります。
使い方
初期化にはnew
メソッドかnew_unchecked
メソッドを使います。
前者は与えられた値がN
ビットに収まるかを検査し、収まる場合はSome
を返し、そうでない場合はNone
を返します。
後者は検査をしないで初期化をするunsafe
メソッドで、与えられた値がN
ビットに収まらないときの動作は未定義です。
値をプリミティブ型として取得するにはget
メソッドを使います。
let n = BitInt::<i32, 7>::new(42);
assert_eq!(n.map(BitInt::get), Some(42));
let m = BitInt::<i32, 6>::new(42);
assert!(m.is_none());
プリミティブ整数型と同様に、最小値、最大値、ビット数を表す定数を定義しています。
assert_eq!(BitInt::<i32, 7>::MIN.get(), -64);
assert_eq!(BitInt::<i32, 7>::MAX.get(), 63);
assert_eq!(BitInt::<i32, 7>::BITS, 7);
演算は現時点では四則演算だけ実装しています。
今後、プリミティブ型にある他の演算も実装するつもりです。
let n = BitInt::<i32, 7>::new(42).unwrap();
assert_eq!(n.checked_add(21).map(BitInt::get), Some(63));
assert!(n.checked_add(22).is_none());
終わりに
Rustでビット精度の整数型を使えるようにするライブラリのbit-int
クレートを紹介しました。
開発を始めたばかりで機能が少ないので、今後機能を強化できたら良いと思います。
Discussion