行列係数型でテンプレート化された線形代数コードをいくつか開発しています。可能なタイプの一つは、次のように単純に実装され、 剰余演算を行うためのクラスです:プログラムはModular<int>
係数で実行する場合しかし、それはint
係数を実行したときに比べて数 倍遅いC++でモジュラ演算を最適化する
template<typename val_t> // `val_t` is an integer type
class Modular
{
val_t val_;
static val_t modulus_;
public:
Modular(const val_t& value) : val_(value) { };
static void global_set_modulus(const val_t& modulus) { modulus_ = modulus; };
Modular<val_t>& operator=(const Modular<val_t>& other) { val_ = other.val_; return *this; }
Modular<val_t>& operator+=(const Modular<val_t>& other) { val_ += other.val_; val_ %= modulus_; return *this; }
Modular<val_t>& operator-=(const Modular<val_t>& other) { val_ -= other.val_; val_ %= modulus_; return *this; }
Modular<val_t>& operator*=(const Modular<val_t>& other) { val_ *= other.val_; val_ %= modulus_; return *this; }
Modular<val_t>& operator/=(const Modular<val_t>& other) { val_ *= other.inverse().val_; val_ %= modulus_; return *this; }
friend Modular<val_t> operator+(const Modular<val_t>& a, const Modular<val_t>& b) { return Modular<val_t>((a.val_ + b.val_) % Modular<val_t>::modulus_); };
friend Modular<val_t> operator-(const Modular<val_t>& a, const Modular<val_t>& b) { return Modular<val_t>((a.val_ - b.val_) % Modular<val_t>::modulus_); };
// ...etc.
};
。
最高のパフォーマンスを得るために、 オーダーの「モジュラー」クラスで変更する必要があるものは何ですか?
(((a.val_*b.val_) % modulus) + ((c.val_*d.val_ % modulus) % modulus) % modulus)
どのようなプログラミング環境で実行されていますか?あなたはコンパイラの最適化を立てましたか? – wallyk
オーバーフローを防ぐために、乗算の前に減算を実行したい場合があります。 –
モジュラスが2の累乗である場合、 "x%モジュラス"の代わりに "x&(モジュラス-1)"を使用できます。 (-10%8は-2ですが、-10&(8-1)は6) –