⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_n.hpp

📁 矩阵运算源码最新版本
💻 HPP
字号:
// Software License for MTL// // Copyright (c) 2007 The Trustees of Indiana University. All rights reserved.// Authors: Peter Gottschling and Andrew Lumsdaine// // This file is part of the Matrix Template Library// // See also license.mtl.txt in the distribution.#ifndef MTL_MOD_N_INCLUDE#define MTL_MOD_N_INCLUDE#include <iostream>#include <boost/operators.hpp>#include <cassert>#include <boost/config/concept_macros.hpp> #ifdef __GXX_CONCEPTS__#  include <bits/concepts.h>#endif#include <boost/numeric/linear_algebra/identity.hpp>#include <boost/numeric/linear_algebra/is_invertible.hpp>#include <boost/numeric/linear_algebra/inverse.hpp>#include <boost/numeric/linear_algebra/operators.hpp>#include <boost/numeric/linear_algebra/concepts.hpp>#include <boost/numeric/meta_math/is_prime.hpp>namespace mtl {template<typename T, T N>//  where std::Integral<T>class mod_n_t   : boost::totally_ordered< mod_n_t<T, N> >,    boost::arithmetic< mod_n_t<T, N> >{    // or BOOST_STATIC_ASSERT((IS_INTEGRAL))    T                 value; public:    typedef T         value_type;    typedef mod_n_t   self;    static T const modulo= N;    mod_n_t() : value(0) {}    explicit mod_n_t(T const& v)    {	value= v >= 0 ? v%modulo : modulo - -v%modulo;     }    // modulo of negative numbers can be bizarre    // better use constructor for T    explicit mod_n_t(int v)     {	value= v >= 0 ? v%modulo : modulo - -v%modulo;     }    // copy constructor    mod_n_t(const mod_n_t<T, N>& m): value(m.get()) {}      // assignment    mod_n_t<T, N>& operator= (const mod_n_t<T, N>& m)     {	value= m.value; 	return *this;     }    mod_n_t<T, N>& operator= (T const& v)    {	value= v >= 0 ? v%modulo : modulo - -v%modulo; 	return *this;     }        // conversion from other moduli must be called explicitly    template<T OtherN>    mod_n_t<T, N>& convert(const mod_n_t<T, OtherN>& m)     {	value= m.value >= 0 ? m.value%modulo : modulo - -m.value%modulo; 	return *this;     }    T get() const     {	return value;     }    bool operator==(self const& y) const    {	check(*this); check(y);	return this->value == y.value;    }    bool operator<(self const& y) const    {	check(*this); check(y);	return this->value < y.value;    }    self& operator+= (self const& y)    {	check(*this); check(y);	this->value += y.value;	this->value %= modulo;	return *this;    }    self& operator-= (self const& y)    {	check(*this); check(y);	// add n to avoid negative numbers esp. if T is unsigned	this->value += modulo;	this->value -= y.value;	this->value %= modulo;	return *this;    }    self& operator*= (self const& y)    {	check(*this); check(y);	this->value *= y.value;	this->value %= modulo;	return *this;    }    self& operator/= (self const& y);    };template<typename T, T N>inline void check(const mod_n_t<T, N>& x){    assert(x.get() >= 0 && x.get() < N);}template<typename T, T N>inline std::ostream& operator<< (std::ostream& stream, const mod_n_t<T, N>& a) {    check(a);    return stream << a.get(); }// Extended Euclidian algorithm in vector notation    // uu = (u1, u2, u3) := (1, 0, u)    // vv = (v1, v2, v3) := (0, 1, v)    // while (u3 % v3 != 0) {    //   q= u3 / v3    //   rr= uu - q * vv    //   uu= vv    //   vv= rr }    //     // with u = N and v = y    // --> v2 * v mod u == gcd(u, v)    // --> v2 * y mod N == 1    // --> x * v2 == x / y    // v1, u1, and r1 not usedtemplate<typename T, T N>inline mod_n_t<T, N>& mod_n_t<T, N>::operator/= (const mod_n_t<T, N>& y) {    check(*this); check(y);    if (y.get() == 0) throw "Division by 0";    // Goes wrong with unsigned b/c some values will be negative (even if the result isn't)    // Something like remove_sign<T>::type would be cute    int u= N, v= y.get(), /* u1= 1, */  u2= 0, /* v1= 0, */  v2= 1, q, r, /* r1, */  r2;    while (u % v != 0) {	q= u / v;	r= u % v; /* r1= u1 - q * v1; */ r2= u2 - q * v2;	u= v; /* u1= v1; */ u2= v2;	v= r; /* v1= r1; */ v2= r2;    }    return *this *= mod_n_t<T, N>(v2); }inline int gcd(int u, int v){    int r;    while ((r= u % v) != 0) {	u= v; v= r;    }    return v;}} // namespace mtlnamespace math {    using mtl::mod_n_t;    template<typename T, T N>    struct identity_t< add< mod_n_t<T, N> >, mod_n_t<T, N> >    {	typedef mod_n_t<T, N> mod_t;	mod_t operator() (add<mod_t> const&, mod_t const& v) const	{	    return mod_t(0);	}    };    // Reverse definition, a little more efficient if / uses inverse    template<typename T, T N>    struct inverse_t< add< mod_n_t<T, N> >, mod_n_t<T, N> >    {	typedef mod_n_t<T, N> mod_t;	mod_t operator() (add<mod_t> const& op, mod_t const& v) const	{	    return identity(op, v) - v;	}    };        template<typename T, T N>    struct is_invertible_t< add< mod_n_t<T, N> >, mod_n_t<T, N> >    {	typedef mod_n_t<T, N> mod_t;	bool operator() (add<mod_t> const&, mod_t const& v) const	{ return true; }    };        template<typename T, T N>    struct identity_t< mult< mod_n_t<T, N> >, mod_n_t<T, N> >    {	typedef mod_n_t<T, N> mod_t;	mod_t operator() (mult<mod_t> const&, mod_t const& v) const	{	    return mod_t(1);	}    };    // Reverse definition, a little more efficient if / uses inverse    template<typename T, T N>    struct inverse_t< mult< mod_n_t<T, N> >, mod_n_t<T, N> >    {	typedef mod_n_t<T, N> mod_t;	mod_t operator() (mult<mod_t> const&, mod_t const& v) const	{	    return mod_t(1) / v;	}    };        template<typename T, T N>    struct is_invertible_t< mult< mod_n_t<T, N> >, mod_n_t<T, N> >    {	typedef mod_n_t<T, N> mod_t;	bool operator() (mult<mod_t> const&, mod_t const& v) const	{#           ifdef MTL_TRACE_MOD_N_INVERTIBILITY_DISPATCHING                 std::cout << "[slow mod n inversion test] ";#           endif	    T value = v.get();	    return value != 0 && mtl::gcd(N, value) == 1;	}    };    # ifdef __GXX_CONCEPTS__    // With Concept we can provide a faster invertibility test for prime numbers:    //  only 0 is not invertible and gcd doesn't need to be called    template<typename T, T N>        where meta_math::Prime<N>    struct is_invertible_t< mult< mod_n_t<T, N> >, mod_n_t<T, N> >    {	typedef mod_n_t<T, N> mod_t;	bool operator() (mult<mod_t> const&, mod_t const& v) const	{#           ifdef MTL_TRACE_MOD_N_INVERTIBILITY_DISPATCHING                 std::cout << "[fast mod n inversion test] ";#           endif 	    return v.get() != 0;	}    };// Concept mapping// All modulo sets are commutative rings with identity// but only if N is prime it is also a field// Due to some mapping nesting trouble we define normally derived mapstemplate <typename T, T N>concept_map CommutativeRingWithIdentity< mod_n_t<T, N> > {    // Why do we need the typedefs???        typedef mod_n_t<T, N>& plus_assign_result_type;    typedef mod_n_t<T, N>  addition_result_type;    typedef mod_n_t<T, N>  unary_result_type;    typedef mod_n_t<T, N>& minus_assign_result_type;    typedef mod_n_t<T, N>  subtraction_result_type;    typedef mod_n_t<T, N>& mult_assign_result_type;    typedef mod_n_t<T, N>  mult_result_type;    typedef mod_n_t<T, N>& divide_assign_result_type;    typedef mod_n_t<T, N>  division_result_type;    typedef mod_n_t<T, N>  inverse_result_type;    typedef mod_n_t<T, N>  identity_result_type;    typedef bool           is_invertible_result_type;}template <typename T, T N>concept_map MultiplicativePartiallyInvertibleMonoid< mod_n_t<T, N> >{    // Why do we need the typedefs???    typedef mod_n_t<T, N>& mult_assign_result_type;    typedef mod_n_t<T, N>  mult_result_type;    typedef mod_n_t<T, N>& divide_assign_result_type;    typedef mod_n_t<T, N>  division_result_type;    typedef mod_n_t<T, N>  inverse_result_type;    typedef mod_n_t<T, N>  identity_result_type;    typedef bool           is_invertible_result_type;}template <typename T, T N>    where meta_math::Prime<N>concept_map Field< mod_n_t<T, N> >{    // Why do we need the typedefs???    typedef mod_n_t<T, N>& plus_assign_result_type;    typedef mod_n_t<T, N>  addition_result_type;    typedef mod_n_t<T, N>  unary_result_type;    typedef mod_n_t<T, N>& minus_assign_result_type;    typedef mod_n_t<T, N>  subtraction_result_type;    typedef mod_n_t<T, N>& mult_assign_result_type;    typedef mod_n_t<T, N>  mult_result_type;    typedef mod_n_t<T, N>& divide_assign_result_type;    typedef mod_n_t<T, N>  division_result_type;    typedef mod_n_t<T, N>  inverse_result_type;    typedef mod_n_t<T, N>  identity_result_type;    typedef bool           is_invertible_result_type;}# endif // __GXX_CONCEPTS__} // namespace math#endif // MTL_MOD_N_INCLUDE

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -