00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00024 #ifndef _ARAGELI_residue_hpp_
00025 #define _ARAGELI_residue_hpp_
00026
00027 #include "config.hpp"
00028
00029 #include <iostream>
00030 #include <sstream>
00031
00032 #include "_utility.hpp"
00033 #include "factory.hpp"
00034 #include "intalg.hpp"
00035
00036 #include "std_import.hpp"
00037
00038
00039 namespace Arageli
00040 {
00041
00042
00043 template <typename T, typename M>
00044 struct residue_config_default
00045 {
00046 static void init (T& x, const M& m) { normalize(x, m); }
00047 static void get_value (const T& x, const M& m) {}
00048 static void before_oper (const T& x, const M& m) {}
00049 static void after_oper (T& x, const M& m) { normalize(x, m); }
00050 static bool is_normal (const T& x, const M& m) { return is_null(m) || is_null(x/m); }
00051 static void normalize (T& x, const M& m) {if(!is_null(m))x = prrem(x, m);}
00052 };
00053
00054
00055
00056 template
00057 <
00058 typename T, typename M = T,
00059 typename Config = residue_config_default<T, M>
00060 >
00061 class residue
00062 {
00063 mutable T value_m;
00064 M module_m;
00065 Config config_m;
00066
00067 template <typename T2, typename M2, typename Config2>
00068 friend class residue;
00069
00070 public:
00071
00072 typedef T value_type;
00073 typedef M module_type;
00074 typedef Config config_type;
00075
00077 residue () : value_m(null<T>()), module_m(null<M>()) {}
00078
00080 template <typename T1>
00081 residue (const T1& x) : value_m(x), module_m(null<M>()) {}
00082
00083
00084 template <typename T1>
00085 residue (const residue<T1>& x) : value_m(x.value()), module_m(x.module()) {}
00086
00087
00088 residue (const T& x, const M& m) : value_m(x), module_m(m)
00089 { config_m.init(value_m, module_m); }
00090
00091
00092 residue (const char* s);
00093
00094
00096 const T& value () const
00097 {
00098 config_m.get_value(value_m, module_m);
00099 return value_m;
00100 }
00101
00103 const M& module () const { return module_m; }
00104
00106 T& value ()
00107 {
00108 config_m.get_value(value_m, module_m);
00109 return value_m;
00110 }
00111
00113 M& module () { return module_m; }
00114
00115
00117 bool is_normal () const { return config_m.is_normal(value_m, module_m); }
00118
00120 void normalize () const { config_m.normalize(value_m, module_m); }
00121
00122
00123 residue operator- () const
00124 {
00125 config_m.before_oper(value_m, module_m);
00126 return residue(-value_m, module_m);
00127 }
00128
00129 const residue& operator+ () const { return *this; }
00130
00131 residue& operator++ ()
00132 {
00133 config_m.before_oper(value_m, module_m);
00134 ++value_m;
00135 config_m.after_oper(value_m, module_m);
00136 return *this;
00137 }
00138
00139 residue& operator-- ()
00140 {
00141 config_m.before_oper(value_m, module_m);
00142 --value_m;
00143 config_m.after_oper(value_m, module_m);
00144 return *this;
00145 }
00146
00147 residue operator++ (int) { residue t = *this; operator++(); return t; }
00148 residue operator-- (int) { residue t = *this; operator--(); return t; }
00149
00150 template <typename T1, typename M1, typename Config1>
00151 residue& operator+= (const residue<T1, M1, Config1>& x)
00152 {
00153 ARAGELI_ASSERT_0
00154 (module_m == x.module_m || is_null(x.module_m) || is_null(module_m));
00155
00156 config_m.before_oper(value_m, module_m);
00157
00158 value_m += x.value_m;
00159 if(is_null(module_m) && !is_null(x.module_m))
00160 module_m = x.module_m;
00161
00162 config_m.after_oper(value_m, module_m);
00163 return *this;
00164 }
00165
00166 template <typename T1, typename M1, typename Config1>
00167 residue& operator-= (const residue<T1, M1, Config1>& x)
00168 {
00169 ARAGELI_ASSERT_0
00170 (module_m == x.module_m || is_null(x.module_m) || is_null(module_m));
00171
00172 config_m.before_oper(value_m, module_m);
00173
00174 value_m -= x.value_m;
00175 if(is_null(module_m) && !is_null(x.module_m))
00176 module_m = x.module_m;
00177
00178 config_m.after_oper(value_m, module_m);
00179 return *this;
00180 }
00181
00182 template <typename T1, typename M1, typename Config1>
00183 residue& operator*= (const residue<T1, M1, Config1>& x)
00184 {
00185 ARAGELI_ASSERT_0
00186 (module_m == x.module_m || is_null(x.module_m) || is_null(module_m));
00187
00188 config_m.before_oper(value_m, module_m);
00189
00190 value_m *= x.value_m;
00191 if(is_null(module_m) && !is_null(x.module_m))
00192 module_m = x.module_m;
00193
00194 config_m.after_oper(value_m, module_m);
00195 return *this;
00196 }
00197
00198 template <typename T1, typename M1, typename Config1>
00199 residue& operator/= (const residue<T1, M1, Config1>& x)
00200 {
00201 ARAGELI_ASSERT_0
00202 (module_m == x.module_m || is_null(x.module_m) || is_null(module_m));
00203
00204 config_m.before_oper(value_m, module_m);
00205
00206 if(is_null(module_m) && !is_null(x.module_m))
00207 module_m = x.module_m;
00208
00209 if(is_null(module_m))
00210 value_m /= x.value_m;
00211 else
00212 value_m *= inverse_mod(x.value_m, T1(module_m));
00213
00214 config_m.after_oper(value_m, module_m);
00215 return *this;
00216 }
00217
00218 template <typename T1, typename M1, typename Config1>
00219 residue& operator%= (const residue<T1, M1, Config1>& x)
00220 { return residue(null(value_m), module_m); }
00221
00222 bool operator! () const { return is_null(value_m); }
00223 operator bool () const { return !!(*this); }
00224
00225 operator T () const { return value(); }
00226
00227 };
00228
00229
00230 #define ARAGELI_RESIDUE_BINARY_OP(OP, OPASS) \
00231 template \
00232 < \
00233 typename T1, typename M1, typename Config1, \
00234 typename T2, typename M2, typename Config2 \
00235 > \
00236 inline residue<T1, M1, Config1> operator OP \
00237 (residue<T1, M1, Config1> a, const residue<T2, M2, Config2>& b) \
00238 { return a OPASS b; }
00239
00240 ARAGELI_RESIDUE_BINARY_OP(+, +=)
00241 ARAGELI_RESIDUE_BINARY_OP(-, -=)
00242 ARAGELI_RESIDUE_BINARY_OP(*, *=)
00243 ARAGELI_RESIDUE_BINARY_OP(/, /=)
00244 ARAGELI_RESIDUE_BINARY_OP(%, %=)
00245
00246
00247 #define ARAGELI_RESIDUE_LOGIC_OP(OP) \
00248 template \
00249 < \
00250 typename T1, typename M1, typename Config1, \
00251 typename T2, typename M2, typename Config2 \
00252 > \
00253 inline bool operator OP \
00254 (const residue<T1, M1, Config1>& a, \
00255 const residue<T2, M2, Config2>& b) \
00256 { return a.value() OP b.value(); } \
00257 \
00258 template \
00259 < \
00260 typename T1, typename M1, typename Config1, \
00261 typename T2 \
00262 > \
00263 inline bool operator OP \
00264 (const residue<T1, M1, Config1>& a, const T2& b) \
00265 { return a.value() OP b; } \
00266 \
00267 template \
00268 < \
00269 typename T1, \
00270 typename T2, typename M2, typename Config2 \
00271 > \
00272 inline bool operator OP \
00273 (const T1& a, const residue<T2, M2, Config2>& b) \
00274 { return a OP b.value(); }
00275
00276
00277
00278 ARAGELI_RESIDUE_LOGIC_OP(==)
00279 ARAGELI_RESIDUE_LOGIC_OP(!=)
00280 ARAGELI_RESIDUE_LOGIC_OP(<)
00281 ARAGELI_RESIDUE_LOGIC_OP(<=)
00282 ARAGELI_RESIDUE_LOGIC_OP(>)
00283 ARAGELI_RESIDUE_LOGIC_OP(>=)
00284
00285
00286 template
00287 <
00288 typename T1, typename M1, typename Config1,
00289 typename T2, typename M2, typename Config2
00290 >
00291 inline int cmp
00292 (residue<T1, M1, Config1> a, const residue<T2, M2, Config2>& b)
00293 { return cmp(a.value(), b.value()); }
00294
00295
00296 template <typename T, typename M, typename Config>
00297 inline std::ostream& operator<< (std::ostream& out, const residue<T, M, Config>& x)
00298 { return out << x.value() << "(mod " << x.module() << ")"; }
00299
00300
00301 template <typename T, typename M, typename Config>
00302 std::istream& operator>> (std::istream& in, residue<T, M, Config>& x)
00303 {
00304 char ch = 0;
00305 in >> ch;
00306 bool brackets = false;
00307 if(ch == '(')brackets = true;
00308 else in.putback(ch);
00309
00310 T value;
00311 in >> value;
00312
00313 if(!in)
00314 {
00315 in.clear(std::ios_base::badbit);
00316 return in;
00317 }
00318
00319 M module;
00320
00321 if(_Internal::read_literal(in, "("))
00322 {
00323 if(!_Internal::read_literal(in, "mod"))
00324 {
00325 in.clear(std::ios_base::badbit);
00326 return in;
00327 }
00328
00329 in >> module;
00330
00331 if(!in)
00332 {
00333 in.clear(std::ios_base::badbit);
00334 return in;
00335 }
00336
00337 if(!_Internal::read_literal(in, ")"))
00338 {
00339 in.clear(std::ios_base::badbit);
00340 return in;
00341 }
00342 }
00343 else module = null<M>(value);
00344
00345 if(brackets && !_Internal::read_literal(in, ")"))
00346 {
00347 in.clear(std::ios_base::badbit);
00348 return in;
00349 }
00350
00351 x = residue<T, M, Config>(value, module);
00352
00353 return in;
00354 }
00355
00356
00357 template <typename T, typename M, typename Config>
00358 residue<T, M, Config>::residue (const char* s)
00359 {
00360 std::istringstream buf(s);
00361 buf >> *this;
00362 }
00363
00364
00365 template <typename T, typename M, typename Config>
00366 const residue<T, M, Config>& abs (const residue<T, M, Config>& x)
00367 { return x; }
00368
00369
00370
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380 #endif