00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00030
00031 #ifndef REAL_INFININT_HPP
00032 #define REAL_INFININT_HPP
00033
00034 #include "../my_config.h"
00035
00036 extern "C"
00037 {
00038 #if HAVE_SYS_TYPES_H
00039 #include <sys/types.h>
00040 #endif
00041 }
00042
00043 #include <typeinfo>
00044 #include "storage.hpp"
00045 #include "integers.hpp"
00046 #include "int_tools.hpp"
00047
00048 namespace libdar
00049 {
00050 class generic_file;
00051 class user_interaction;
00052
00054
00057 class infinint
00058 {
00059 public :
00060
00061 #if SIZEOF_OFF_T > SIZEOF_TIME_T
00062 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
00063 infinint(off_t a = 0)
00064 { E_BEGIN infinint_from(a); E_END("infinint::infinint", "off_t") };
00065 #else
00066 infinint(size_t a = 0)
00067 { E_BEGIN infinint_from(a); E_END("infinint::infinint", "size_t") };
00068 #endif
00069 #else
00070 #if SIZEOF_TIME_T > SIZEOF_SIZE_T
00071 infinint(time_t a = 0)
00072 { E_BEGIN infinint_from(a); E_END("infinint::infinint", "time_t") };
00073 #else
00074 infinint(size_t a = 0)
00075 { E_BEGIN infinint_from(a); E_END("infinint::infinint", "size_t") };
00076 #endif
00077 #endif
00078
00079 infinint(const infinint & ref)
00080 { E_BEGIN; copy_from(ref); E_END("infinint::infinint", "const infinint &"); }
00081 infinint(user_interaction & dialog, S_I *fd, generic_file *x);
00082 ~infinint()
00083 { E_BEGIN detruit(); E_END("infinint::~infinint","") };
00084
00085 infinint & operator = (const infinint & ref)
00086 { E_BEGIN detruit(); copy_from(ref); return *this; E_END("infinint::operator =","") };
00087
00088 void dump(user_interaction & dialog, int fd) const;
00089 void dump(generic_file &x) const;
00090 void read(generic_file &f) { detruit(); build_from_file(f); };
00091
00092 infinint & operator += (const infinint & ref);
00093 infinint & operator -= (const infinint & ref);
00094 infinint & operator *= (unsigned char arg);
00095 infinint & operator *= (const infinint & ref);
00096 template <class T> infinint power(const T & exponent) const;
00097 inline infinint & operator /= (const infinint & ref);
00098 inline infinint & operator %= (const infinint & ref);
00099 infinint & operator >>= (U_32 bit);
00100 infinint & operator >>= (infinint bit);
00101 infinint & operator <<= (U_32 bit);
00102 infinint & operator <<= (infinint bit);
00103 infinint operator ++(int a)
00104 { E_BEGIN infinint ret = *this; ++(*this); return ret; E_END("infinint::operator ++", "int") };
00105 infinint operator --(int a)
00106 { E_BEGIN infinint ret = *this; --(*this); return ret; E_END("infinint::operator --", "int") };
00107 infinint & operator ++()
00108 { E_BEGIN return *this += 1; E_END("infinint::operator ++", "()") };
00109 infinint & operator --()
00110 { E_BEGIN return *this -= 1; E_END("infinint::operator --", "()") };
00111
00112 U_32 operator % (U_32 arg) const
00113 { E_BEGIN return modulo(arg); E_END("infinint::operator %","") };
00114
00115
00116
00117
00118 template <class T>void unstack(T &v)
00119 { E_BEGIN infinint_unstack_to(v); E_END("infinint::unstack", typeid(v).name()) }
00120
00121 infinint get_storage_size() const { return field->size(); };
00122
00123
00124 unsigned char operator [] (const infinint & position) const;
00125
00126
00127 friend bool operator < (const infinint &, const infinint &);
00128 friend bool operator == (const infinint &, const infinint &);
00129 friend bool operator > (const infinint &, const infinint &);
00130 friend bool operator <= (const infinint &, const infinint &);
00131 friend bool operator != (const infinint &, const infinint &);
00132 friend bool operator >= (const infinint &, const infinint &);
00133 friend void euclide(infinint a, const infinint &b, infinint &q, infinint &r);
00134
00135 private :
00136 static const int TG = 4;
00137
00138 enum endian { big_endian, little_endian, not_initialized };
00139 typedef unsigned char group[TG];
00140
00141 storage *field;
00142
00143 bool is_valid() const;
00144 void build_from_file(generic_file & x);
00145 void reduce();
00146 void copy_from(const infinint & ref);
00147 void detruit();
00148 void make_at_least_as_wider_as(const infinint & ref);
00149 template <class T> void infinint_from(T a);
00150 template <class T> void infinint_unstack_to(T &a);
00151 template <class T> T modulo(T arg) const;
00152 signed int difference(const infinint & b) const;
00153
00155
00156
00157 static endian used_endian;
00158 static void setup_endian();
00159 };
00160
00161
00162 #define OPERATOR(OP) inline bool operator OP (const infinint &a, const infinint &b) \
00163 { \
00164 E_BEGIN \
00165 return a.difference(b) OP 0; \
00166 E_END("operator OP", "infinint, infinint") \
00167 }
00168
00169 OPERATOR(<)
00170 OPERATOR(>)
00171 OPERATOR(<=)
00172 OPERATOR(>=)
00173 OPERATOR(==)
00174 OPERATOR(!=)
00175
00176 infinint operator + (const infinint &, const infinint &);
00177 infinint operator - (const infinint &, const infinint &);
00178 infinint operator * (const infinint &, const infinint &);
00179 infinint operator * (const infinint &, const unsigned char);
00180 infinint operator * (const unsigned char, const infinint &);
00181 infinint operator / (const infinint &, const infinint &);
00182 infinint operator % (const infinint &, const infinint &);
00183 infinint operator >> (const infinint & a, U_32 bit);
00184 infinint operator >> (const infinint & a, const infinint & bit);
00185 infinint operator << (const infinint & a, U_32 bit);
00186 infinint operator << (const infinint & a, const infinint & bit);
00187 void euclide(infinint a, const infinint &b, infinint &q, infinint &r);
00188 template <class T> inline void euclide(T a, T b, T & q, T &r)
00189 {
00190 E_BEGIN
00191 q = a/b; r = a%b;
00192 E_END("euclide", "")
00193 }
00194
00195 inline infinint & infinint::operator /= (const infinint & ref)
00196 {
00197 E_BEGIN
00198 *this = *this / ref;
00199 return *this;
00200 E_END("infinint::operator /=", "")
00201 }
00202
00203 inline infinint & infinint::operator %= (const infinint & ref)
00204 {
00205 E_BEGIN
00206 *this = *this % ref;
00207 return *this;
00208 E_END("infinint::operator %=", "")
00209 }
00210
00211
00215
00216 template <class T> infinint infinint::power(const T & exponent) const
00217 {
00218 infinint ret = 1;
00219 for(T count = 0; count < exponent; count++)
00220 ret *= *this;
00221
00222 return ret;
00223 }
00224
00225 template <class T> T infinint::modulo(T arg) const
00226 {
00227 E_BEGIN
00228 infinint tmp = *this % infinint(arg);
00229 T ret = 0;
00230 unsigned char *debut = (unsigned char *)(&ret);
00231 unsigned char *ptr = debut + sizeof(T) - 1;
00232 storage::iterator it = tmp.field->rbegin();
00233
00234 while(it != tmp.field->rend() && ptr >= debut)
00235 *(ptr--) = *(it--);
00236
00237 if(it != tmp.field->rend())
00238 throw SRC_BUG;
00239
00240 if(used_endian == big_endian)
00241 int_tools_swap_bytes(debut, sizeof(T));
00242
00243 return ret;
00244 E_END("infinint::modulo", "")
00245 }
00246
00247
00248 template <class T> void infinint::infinint_from(T a)
00249 {
00250 E_BEGIN
00251 U_I size = sizeof(a);
00252 S_I direction = +1;
00253 unsigned char *ptr, *fin;
00254
00255 if(used_endian == not_initialized)
00256 setup_endian();
00257
00258 if(used_endian == big_endian)
00259 {
00260 direction = -1;
00261 ptr = (unsigned char *)(&a) + (size - 1);
00262 fin = (unsigned char *)(&a) - 1;
00263 }
00264 else
00265 {
00266 direction = +1;
00267 ptr = (unsigned char *)(&a);
00268 fin = (unsigned char *)(&a) + size;
00269 }
00270
00271 while(ptr != fin && *ptr == 0)
00272 {
00273 ptr += direction;
00274 size--;
00275 }
00276
00277 if(size == 0)
00278 {
00279 size = 1;
00280 ptr -= direction;
00281 }
00282
00283 field = new storage(size);
00284 if(field != NULL)
00285 {
00286 storage::iterator it = field->begin();
00287
00288 while(ptr != fin)
00289 {
00290 *(it++) = *ptr;
00291 ptr += direction;
00292 }
00293 if(it != field->end())
00294 throw SRC_BUG;
00295 }
00296 else
00297 throw Ememory("template infinint::infinint_from");
00298
00299 E_END("infinint::infinint_from", "")
00300 }
00301
00302 template <class T> void infinint::infinint_unstack_to(T &a)
00303 {
00304 E_BEGIN
00305
00306
00307
00308 static const T max_T = int_tools_maxof_agregate(T(0));
00309 infinint step = max_T - a;
00310
00311 if(*this < step)
00312 {
00313 T transfert = 0;
00314 unsigned char *debut = (unsigned char *)&transfert;
00315 unsigned char *ptr = debut + sizeof(transfert) - 1;
00316 storage::iterator it = field->rbegin();
00317
00318 while(ptr >= debut && it != field->rend())
00319 *(ptr--) = *(it--);
00320
00321 if(used_endian == big_endian)
00322 int_tools_swap_bytes(debut, sizeof(transfert));
00323 a += transfert;
00324 *this -= *this;
00325 }
00326 else
00327 {
00328 *this -= step;
00329 a = max_T;
00330 }
00331 E_END("infinint::infinint_unstack_to", "")
00332 }
00333
00334 }
00335
00336 #endif