# limitint.hpp

Go to the documentation of this file.

    00001 /*********************************************************************/
    00002 // dar - disk archive - a backup/restoration program
    00003 // Copyright (C) 2002-2052 Denis Corbin
    00004 //
    00005 // This program is free software; you can redistribute it and/or
    00006 // modify it under the terms of the GNU General Public License
    00007 // as published by the Free Software Foundation; either version 2
    00008 // of the License, or (at your option) any later version.
    00009 //
    00010 // This program is distributed in the hope that it will be useful,
    00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00013 // GNU General Public License for more details.
    00014 //
    00015 // You should have received a copy of the GNU General Public License
    00016 // along with this program; if not, write to the Free Software
    00017 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    00018 //
    00019 // to contact the author : dar.linux@free.fr
    00020 /*********************************************************************/
    00021 // $Id: limitint.hpp,v 1.18.2.4 2009/04/07 08:45:29 edrusb Rel $
    00022 //
    00023 /*********************************************************************/
    00024
    00032
    00033 #ifndef LIMITINT_HPP
    00034 #define LIMITINT_HPP
    00035
    00036 #include "../my_config.h"
    00037
    00038 extern "C"
    00039 {
    00040 #if HAVE_SYS_TYPES_H
    00041 #include <sys/types.h>
    00042 #endif
    00043
    00044 #if HAVE_UNISTD_H
    00045 #include <unistd.h>
    00046 #endif
    00047 } // end extern "C"
    00048
    00049 #include <typeinfo>
    00050 #include "integers.hpp"
    00051 #include "erreurs.hpp"
    00052 #include "special_alloc.hpp"
    00053 #include "int_tools.hpp"
    00054
    00055 namespace libdar
    00056 {
    00057
    00058     class generic_file;
    00059     class user_interaction;
    00060
    00062
    00072
    00073     template<class B> class limitint
    00074     {
    00075     public :
    00076
    00077 #if SIZEOF_OFF_T > SIZEOF_TIME_T
    00078 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
    00079         limitint(off_t a = 0)
    00080             { E_BEGIN; limitint_from(a); E_END("limitint::limitint", "off_t"); };
    00081 #else
    00082         limitint(size_t a = 0)
    00083             { E_BEGIN; limitint_from(a); E_END("limitint::limitint", "size_t"); };
    00084 #endif
    00085 #else
    00086 #if SIZEOF_TIME_T > SIZEOF_SIZE_T
    00087         limitint(time_t a = 0)
    00088             { E_BEGIN; limitint_from(a); E_END("limitint::limitint", "time_t"); };
    00089 #else
    00090         limitint(size_t a = 0)
    00091             { E_BEGIN; limitint_from(a); E_END("limitint::limitint", "size_t"); };
    00092 #endif
    00093 #endif
    00094
    00095         limitint(user_interaction & dialog, S_I *fd, generic_file *x); // read an limitint from a file
    00096
    00097
    00098         void dump(user_interaction & dialog, S_I fd) const; // write byte sequence to file
    00099         void dump(generic_file &x) const; // write byte sequence to file
    00100         void read(generic_file &f) { build_from_file(f); };
    00101
    00102         limitint & operator += (const limitint & ref);
    00103         limitint & operator -= (const limitint & ref);
    00104         limitint & operator *= (const limitint & ref);
    00105         template <class T> limitint power(const T & exponent) const;
    00106         limitint & operator /= (const limitint & ref);
    00107         limitint & operator %= (const limitint & ref);
    00108         limitint & operator &= (const limitint & ref);
    00109         limitint & operator |= (const limitint & ref);
    00110         limitint & operator ^= (const limitint & ref);
    00111         limitint & operator >>= (U_32 bit);
    00112         limitint & operator >>= (limitint bit);
    00113         limitint & operator <<= (U_32 bit);
    00114         limitint & operator <<= (limitint bit);
    00115         limitint operator ++(int a)
    00116             { E_BEGIN; limitint ret = *this; ++(*this); return ret; E_END("limitint::operator ++", "int"); };
    00117         limitint operator --(int a)
    00118             { E_BEGIN; limitint ret = *this; --(*this); return ret; E_END("limitint::operator --", "int"); };
    00119         limitint & operator ++()
    00120             { E_BEGIN; return *this += 1; E_END("limitint::operator ++", "()"); };
    00121         limitint & operator --()
    00122             { E_BEGIN; return *this -= 1; E_END("limitint::operator --", "()"); };
    00123
    00124         U_32 operator % (U_32 arg) const;
    00125
    00126             // increment the argument up to a legal value for its storage type and decrement the object in consequence
    00127             // note that the initial value of the argument is not ignored !
    00128             // when the object is null the value of the argument stays the same as before
    00129         template <class T>void unstack(T &v)
    00130             { E_BEGIN; limitint_unstack_to(v); E_END("limitint::unstack", typeid(v).name()); }
    00131
    00132         limitint get_storage_size() const;
    00133             // it returns number of byte of information necessary to store the integer
    00134
    00135         unsigned char operator [] (const limitint & position) const;
    00136             // return in big endian order the information byte storing the integer
    00137
    00138
    00139         bool operator < (const limitint &x) const { return field < x.field; };
    00140         bool operator == (const limitint &x) const { return field == x.field; };
    00141         bool operator > (const limitint &x) const { return field > x.field; };
    00142         bool operator <= (const limitint &x) const { return field <= x.field; };
    00143         bool operator != (const limitint &x) const { return field != x.field; };
    00144         bool operator >= (const limitint &x) const { return field >= x.field; };
    00145
    00146 #ifdef LIBDAR_SPECIAL_ALLOC
    00147         USE_SPECIAL_ALLOC(limitint);
    00148 #endif
    00149
    00150         B debug_get_max() const { return max_value; };
    00151         B debug_get_bytesize() const { return bytesize; };
    00152
    00153     private :
    00154         static const int TG = 4;
    00155         static const U_32 sizeof_field = sizeof(B);
    00156
    00157         enum endian { big_endian, little_endian, not_initialized };
    00158         typedef unsigned char group[TG];
    00159
    00160         B field;
    00161
    00162         void build_from_file(generic_file & x);
    00163         template <class T> void limitint_from(T a);
    00164         template <class T> void limitint_unstack_to(T &a);
    00165
    00167             // static statments
    00168             //
    00169         static endian used_endian;
    00170         static const U_I bytesize = sizeof(B);
    00171         static const B max_value = ~B(0) > 0 ? ~B(0) : ~(B(1) << (bytesize*8 - 1));
    00172         static void setup_endian();
    00173     };
    00174
    00175     template <class B> limitint<B> operator + (const limitint<B> &, const limitint<B> &);
    00176     template <class B> inline limitint<B> operator + (const limitint<B> & a, U_I b)
    00177     { return a + limitint<B>(b); }
    00178     template <class B> limitint<B> operator - (const limitint<B> &, const limitint<B> &);
    00179     template <class B> inline limitint<B> operator - (const limitint<B> & a, U_I b)
    00180     { return a - limitint<B>(b); }
    00181     template <class B> limitint<B> operator * (const limitint<B> &, const limitint<B> &);
    00182     template <class B> inline limitint<B> operator * (const limitint<B> & a, U_I b)
    00183     { return a * limitint<B>(b); }
    00184     template <class B> limitint<B> operator / (const limitint<B> &, const limitint<B> &);
    00185     template <class B> limitint<B> operator / (const limitint<B> & a, U_I b)
    00186     { return a / limitint<B>(b); }
    00187     template <class B> limitint<B> operator % (const limitint<B> &, const limitint<B> &);
    00188     template <class B> limitint<B> operator >> (const limitint<B> & a, U_32 bit);
    00189     template <class B> limitint<B> operator >> (const limitint<B> & a, const limitint<B> & bit);
    00190     template <class B> limitint<B> operator << (const limitint<B> & a, U_32 bit);
    00191     template <class B> limitint<B> operator << (const limitint<B> & a, const limitint<B> & bit);
    00192     template <class B> limitint<B> operator & (const limitint<B> & a, U_32  bit);
    00193     template <class B> limitint<B> operator & (const limitint<B> & a, const limitint<B> & bit);
    00194     template <class B> limitint<B> operator | (const limitint<B> & a, U_32  bit);
    00195     template <class B> limitint<B> operator | (const limitint<B> & a, const limitint<B> & bit);
    00196     template <class B> limitint<B> operator ^ (const limitint<B> & a, U_32  bit);
    00197     template <class B> limitint<B> operator ^ (const limitint<B> & a, const limitint<B> & bit);
    00198
    00199     template <class T> inline void euclide(T a, T b, T & q, T &r)
    00200     {
    00201         E_BEGIN;
    00202         q = a/b; r = a%b;
    00203         E_END("euclide", "");
    00204     }
    00205
    00206     template <class B> inline void euclide(limitint<B> a, U_I b, limitint<B> & q, limitint<B> &r)
    00207     {
    00208         euclide(a, limitint<B>(b), q, r);
    00209     }
    00210
    00211 #ifndef INFININT_BASE_TYPE
    00212 #error INFININT_BASE_TYPE not defined cannot instantiate template
    00213 #else
    00214     typedef limitint<INFININT_BASE_TYPE> infinint;
    00215 #endif
    00216 } // end of namespace
    00220
    00221 #include "generic_file.hpp"
    00222 #include "user_interaction.hpp"
    00223
    00224 namespace libdar
    00225 {
    00226
    00227     template <class B> typename limitint<B>::endian limitint<B>::used_endian = not_initialized;
    00228
    00229     template <class B> limitint<B>::limitint(user_interaction & dialog, S_I *fd, generic_file *x)
    00230     {
    00231         if(fd != NULL && x != NULL)
    00232             throw Erange("limitint::limitint(file, file)", "Both arguments are not NULL, please choose one or the other, not both"); // message not translated, expected
    00233         if(fd != NULL)
    00234         {
    00235             fichier f = fichier(dialog, dup(*fd));
    00236             build_from_file(f);
    00237         }
    00238         else
    00239             if(x != NULL)
    00240                 build_from_file(*x);
    00241             else
    00242                 throw Erange("limitint::limitint(file, file)", "Cannot read from file, both arguments are NULL"); // message not translated, expected
    00243     }
    00244
    00245     template <class B> void limitint<B>::dump(user_interaction & dialog, S_I fd) const
    00246     {
    00247         fichier f = fichier(dialog, dup(fd));
    00248         dump(f);
    00249     }
    00250
    00251     template <class B> void limitint<B>::build_from_file(generic_file & x)
    00252     {
    00253         E_BEGIN;
    00254         unsigned char a;
    00255         bool fin = false;
    00256         limitint<B> skip = 0;
    00257         char *ptr = (char *)&field;
    00258         S_I lu;
    00259         int_tools_bitfield bf;
    00260
    00261         while(!fin)
    00262         {
    00263             lu = x.read((char *)&a, 1);
    00264
    00265             if(lu <= 0)
    00266                 throw Erange("limitint::build_from_file(generic_file)", gettext("Reached end of file before all data could be read"));
    00267
    00268             if(a == 0)
    00269                 ++skip;
    00270             else // end of size field
    00271             {
    00272                     // computing the size to read
    00273                 U_I pos = 0;
    00274
    00275                 int_tools_expand_byte(a, bf);
    00276                 for(S_I i = 0; i < 8; ++i)
    00277                     pos += bf[i];
    00278                 if(pos != 1)
    00279                     throw Erange("limitint::build_from_file(generic_file)", gettext("Badly formed infinint or not supported format")); // more than 1 bit is set to 1
    00280
    00281                 pos = 0;
    00282                 while(bf[pos] == 0)
    00283                     ++pos;
    00284                 pos += 1; // bf starts at zero, but bit zero means 1 TG of length
    00285
    00286                 skip *= 8;
    00287                 skip += pos;
    00288                 skip *= TG;
    00289
    00290                 if(skip.field > bytesize)
    00291                     throw Elimitint();
    00292
    00293                 field = 0; // important to also clear "unread" bytes by the following call
    00294                 lu = x.read(ptr, skip.field);
    00295
    00296                 if(used_endian == not_initialized)
    00297                     setup_endian();
    00298                 if(used_endian == big_endian)
    00299                     int_tools_swap_bytes((unsigned char *)ptr, skip.field);
    00300                 else
    00301                     field >>= (bytesize - skip.field)*8;
    00302                 fin = true;
    00303             }
    00304         }
    00305         E_END("limitint::read_from_file", "generic_file");
    00306     }
    00307
    00308
    00309     template <class B> void limitint<B>::dump(generic_file & x) const
    00310     {
    00311         E_BEGIN;
    00312         B width = bytesize;
    00313         B pos;
    00314         unsigned char last_width;
    00315         B justification;
    00316         S_I direction = +1;
    00317         unsigned char *ptr, *fin;
    00318
    00319
    00320         if(used_endian == not_initialized)
    00321             setup_endian();
    00322
    00323         if(used_endian == big_endian)
    00324         {
    00325             direction = -1;
    00326             ptr = (unsigned char *)(&field) + (bytesize - 1);
    00327             fin = (unsigned char *)(&field) - 1;
    00328         }
    00329         else
    00330         {
    00331             direction = +1;
    00332             ptr = (unsigned char *)(&field);
    00333             fin = (unsigned char *)(&field) + bytesize;
    00334         }
    00335
    00336         while(ptr != fin && *ptr == 0)
    00337         {
    00338             ptr += direction;
    00339             --width;
    00340         }
    00341         if(width == 0)
    00342             width = 1; // minimum size of information is 1 byte
    00343
    00344             // "width" is the informational field size in byte
    00345             // TG is the width in TG, thus the number of bit that must have
    00346             // the preamble
    00347         euclide(width, (const B)(TG), width, justification);
    00348         if(justification != 0)
    00349                 // in case we need to add some bytes to have a width multiple of TG
    00350             ++width;  // we need then one more group to have a width multiple of TG
    00351
    00352         euclide(width, (const B)(8), width, pos);
    00353         if(pos == 0)
    00354         {
    00355             width--; // division is exact, only last bit of the preambule is set
    00356             last_width = 0x80 >> 7;
    00357                 // as we add the last byte separately width gets shorter by 1 byte
    00358         }
    00359         else // division non exact, the last_width (last byte), make the rounding
    00360         {
    00361             U_16 pos_s = (U_16)(0xFFFF & pos);
    00362             last_width = 0x80 >> (pos_s - 1);
    00363         }
    00364
    00365             // now we write the preamble except the last byte. All these are zeros.
    00366
    00367         unsigned char u = 0x00;
    00368
    00369         while(width-- > 0)
    00370             if(x.write((char *)(&u), 1) < 1)
    00371                 throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file"));
    00372
    00373
    00374             // now we write the last byte of the preambule, which as only one bit set
    00375
    00376         if(x.write((char *)&last_width, 1) < 1)
    00377             throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file"));
    00378
    00379             // we need now to write some justification byte to have an informational field multiple of TG
    00380
    00381         if(justification != 0)
    00382         {
    00383             justification = TG - justification;
    00384             while(justification-- > 0)
    00385                 if(x.write((char *)(&u), 1) < 1)
    00386                     throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file"));
    00387         }
    00388
    00389             // now we continue dumping the informational bytes:
    00390         if(ptr == fin) // field is equal to zero
    00391         {
    00392             if(x.write((char *)(&u), 1) < 1)
    00393                 throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file"));
    00394         }
    00395         else // we have some bytes to write down
    00396             while(ptr != fin)
    00397             {
    00398                 if(x.write((char *)ptr, 1) < 1)
    00399                     throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file"));
    00400                 else
    00401                     ptr += direction;
    00402             }
    00403
    00404         E_END("limitint::dump", "generic_file");
    00405     }
    00406
    00407     template<class B> limitint<B> & limitint<B>::operator += (const limitint & arg)
    00408     {
    00409         E_BEGIN;
    00410         B res = field + arg.field;
    00411         if(res < field || res < arg.field)
    00412             throw Elimitint();
    00413         else
    00414             field = res;
    00415
    00416         return *this;
    00417         E_END("limitint::operator +=", "");
    00418     }
    00419
    00420     template <class B> limitint<B> & limitint<B>::operator -= (const limitint & arg)
    00421     {
    00422         E_BEGIN;
    00423         if(field < arg.field)
    00424             throw Erange("limitint::operator", gettext("Subtracting a infinint greater than the first, infinint cannot be negative"));
    00425
    00426             // now processing the operation
    00427
    00428         field -= arg.field;
    00429         return *this;
    00430         E_END("limitint::operator -=", "");
    00431     }
    00432
    00433
    00434     template <class B> limitint<B> & limitint<B>::operator *= (const limitint & arg)
    00435     {
    00436         E_BEGIN;
    00437         static const B max_power = bytesize*8 - 1;
    00438
    00439         B total = int_tools_higher_power_of_2(field) + int_tools_higher_power_of_2(arg.field) + 1; // for an explaination about "+2" see NOTES
    00440         if(total > max_power) // this is a bit too much restrictive, but unless remaking bit by bit, the operation,
    00441                 // I don't see how to simply (and fast) know the result has not overflowed.
    00442                 // of course, it would be fast and easy to access the CPU flag register to check for overflow,
    00443                 // but that would not be portable, and unfortunately I haven't found any standart C++ expression that
    00444                 // could transparently access to it.
    00445             throw Elimitint();
    00446
    00447         total = field*arg.field;
    00448         if(field != 0 && arg.field != 0)
    00449             if(total < field || total < arg.field)
    00450                 throw Elimitint();
    00451         field = total;
    00452         return *this;
    00453         E_END("limitint::operator *=", "");
    00454     }
    00455
    00456     template <class B> template<class T> limitint<B> limitint<B>::power(const T & exponent) const
    00457     {
    00458         limitint ret = 1;
    00459         for(T count = 0; count < exponent; ++count)
    00460             ret *= *this;
    00461
    00462         return ret;
    00463     }
    00464
    00465     template <class B> limitint<B> & limitint<B>::operator /= (const limitint & arg)
    00466     {
    00467         E_BEGIN;
    00468         if(arg == 0)
    00469             throw Einfinint("limitint.cpp : operator /=", gettext("Division by zero"));
    00470
    00471         field /= arg.field;
    00472         return *this;
    00473         E_END("limitint::operator /=", "");
    00474     }
    00475
    00476     template <class B> limitint<B> & limitint<B>::operator %= (const limitint & arg)
    00477     {
    00478         E_BEGIN;
    00479         if(arg == 0)
    00480             throw Einfinint("limitint.cpp : operator %=", gettext("Division by zero"));
    00481
    00482         field %= arg.field;
    00483         return *this;
    00484         E_END("limitint::operator /=", "");
    00485     }
    00486
    00487     template <class B> limitint<B> & limitint<B>::operator >>= (U_32 bit)
    00488     {
    00489         E_BEGIN;
    00490         if(bit >= sizeof_field)
    00491             field = 0;
    00492         else
    00493             field >>= bit;
    00494         return *this;
    00495         E_END("limitint::operator >>=", "U_32");
    00496     }
    00497
    00498     template <class B> limitint<B> & limitint<B>::operator >>= (limitint bit)
    00499     {
    00500         E_BEGIN;
    00501         field >>= bit.field;
    00502         return *this;
    00503         E_END("limitint::operator >>=", "limitint");
    00504     }
    00505
    00506     template <class B> limitint<B> & limitint<B>::operator <<= (U_32 bit)
    00507     {
    00508         E_BEGIN;
    00509         if(bit + int_tools_higher_power_of_2(field) >= bytesize*8)
    00510             throw Elimitint();
    00511         field <<= bit;
    00512         return *this;
    00513         E_END("limitint::operator <<=", "U_32");
    00514     }
    00515
    00516     template <class B> limitint<B> & limitint<B>::operator <<= (limitint bit)
    00517     {
    00518         E_BEGIN;
    00519         if(bit.field + int_tools_higher_power_of_2(field) >= bytesize*8)
    00520             throw Elimitint();
    00521         field <<= bit.field;
    00522         return *this;
    00523         E_END("limitint::operator <<=", "limitint");
    00524     }
    00525
    00526     template <class B> limitint<B> & limitint<B>::operator &= (const limitint & arg)
    00527     {
    00528         E_BEGIN;
    00529         field &= arg.field;
    00530         return *this;
    00531         E_END("limitint::operator &=", "");
    00532     }
    00533
    00534     template <class B> limitint<B> & limitint<B>::operator |= (const limitint & arg)
    00535     {
    00536         E_BEGIN;
    00537         field |= arg.field;
    00538         return *this;
    00539         E_END("limitint::operator |=", "");
    00540     }
    00541
    00542     template <class B> limitint<B> & limitint<B>::operator ^= (const limitint & arg)
    00543     {
    00544         E_BEGIN;
    00545         field ^= arg.field;
    00546         return *this;
    00547         E_END("limitint::operator ^=", "");
    00548     }
    00549
    00550     template <class B> U_32 limitint<B>::operator % (U_32 arg) const
    00551     {
    00552         E_BEGIN;
    00553         return U_32(field % arg);
    00554         E_END("limitint::modulo", "");
    00555     }
    00556
    00557     template <class B> template <class T> void limitint<B>::limitint_from(T a)
    00558     {
    00559         E_BEGIN;
    00560         if(sizeof(a) <= bytesize || a <= (T)(max_value))
    00561             field = B(a);
    00562         else
    00563             throw Elimitint();
    00564         E_END("limitint::limitint_from", "");
    00565     }
    00566
    00567     template <class B> template <class T> void limitint<B>::limitint_unstack_to(T &a)
    00568     {
    00569         E_BEGIN;
    00570             // T is supposed to be an unsigned "integer"
    00571             // (ie.: sizeof returns the width of the storage bit field  and no sign bit is present)
    00572             // Note : static here avoids the recalculation of max_T at each call
    00573         static const T max_T = ~T(0) > 0 ? ~T(0) : ~int_tools_rotate_right_one_bit(T(1));
    00574         T step = max_T - a;
    00575
    00576         if(field < (B)(step) && (T)(field) < step)
    00577         {
    00578             a += field;
    00579             field = 0;
    00580         }
    00581         else
    00582         {
    00583             field -= step;
    00584             a = max_T;
    00585         }
    00586
    00587         E_END("limitint::limitint_unstack_to", "");
    00588     }
    00589
    00590     template <class B> limitint<B> limitint<B>::get_storage_size() const
    00591     {
    00592         B tmp = field;
    00593         B ret = 0;
    00594
    00595         while(tmp != 0)
    00596         {
    00597             tmp >>= 8;
    00598             ret++;
    00599         }
    00600
    00601         return limitint<B>(ret);
    00602     }
    00603
    00604     template <class B> unsigned char limitint<B>::operator [] (const limitint & position) const
    00605     {
    00606         B tmp = field;
    00607         B index = position.field; // C++ has only class protection, not object protection
    00608
    00609         while(index > 0)
    00610         {
    00611             tmp >>= 8;
    00612             index--;
    00613         }
    00614
    00615         return (unsigned char)(tmp & 0xFF);
    00616     }
    00617
    00618     template <class B> void limitint<B>::setup_endian()
    00619     {
    00620         E_BEGIN;
    00621         U_16 u = 1;
    00622         unsigned char *ptr = (unsigned char *)(&u);
    00623
    00624         if(ptr[0] == 1)
    00625             used_endian = big_endian;
    00626         else
    00627             used_endian = little_endian;
    00628         E_END("limitint::setup_endian", "");
    00629     }
    00630
    00631
    00632
    00633
    00637
    00638     template <class B> limitint<B> operator + (const limitint<B> & a, const limitint<B> & b)
    00639     {
    00640         E_BEGIN;
    00641         limitint<B> ret = a;
    00642         ret += b;
    00643
    00644         return ret;
    00645         E_END("operator +", "limitint");
    00646     }
    00647
    00648     template <class B> limitint<B> operator - (const limitint<B> & a, const limitint<B> & b)
    00649     {
    00650         E_BEGIN;
    00651         limitint<B> ret = a;
    00652         ret -= b;
    00653
    00654         return ret;
    00655         E_END("operator -", "limitint");
    00656     }
    00657
    00658     template <class B> limitint<B> operator * (const limitint<B> & a, const limitint<B> & b)
    00659     {
    00660         E_BEGIN;
    00661         limitint<B> ret = a;
    00662         ret *= b;
    00663
    00664         return ret;
    00665         E_END("operator *", "limitint");
    00666     }
    00667
    00668     template <class B> limitint<B> operator / (const limitint<B> & a, const limitint<B> & b)
    00669     {
    00670         E_BEGIN;
    00671         limitint<B> ret = a;
    00672         ret /= b;
    00673
    00674         return ret;
    00675         E_END("operator / ", "limitint");
    00676     }
    00677
    00678     template <class B> limitint<B> operator % (const limitint<B> & a, const limitint<B> & b)
    00679     {
    00680         E_BEGIN;
    00681         limitint<B> ret = a;
    00682         ret %= b;
    00683
    00684         return ret;
    00685         E_END("operator %", "limitint");
    00686     }
    00687
    00688     template <class B> limitint<B> operator >> (const limitint<B> & a, U_32 bit)
    00689     {
    00690         E_BEGIN;
    00691         limitint<B> ret = a;
    00692         ret >>= bit;
    00693         return ret;
    00694         E_END("operator >>", "limitint, U_32");
    00695     }
    00696
    00697     template <class B> limitint<B> operator >> (const limitint<B> & a, const limitint<B> & bit)
    00698     {
    00699         E_BEGIN;
    00700         limitint<B> ret = a;
    00701         ret >>= bit;
    00702         return ret;
    00703         E_END("operator >>", "limitint");
    00704     }
    00705
    00706     template <class B> limitint<B> operator << (const limitint<B> & a, U_32 bit)
    00707     {
    00708         E_BEGIN;
    00709         limitint<B> ret = a;
    00710         ret <<= bit;
    00711         return ret;
    00712         E_END("operator <<", "limitint, U_32");
    00713     }
    00714
    00715     template <class B> limitint<B> operator << (const limitint<B> & a, const limitint<B> & bit)
    00716     {
    00717         E_BEGIN;
    00718         limitint<B> ret = a;
    00719         ret <<= bit;
    00720         return ret;
    00721         E_END("operator <<", "limitint");
    00722     }
    00723
    00724     template <class B> limitint<B> operator & (const limitint<B> & a, U_32 bit)
    00725     {
    00726         E_BEGIN;
    00727         limitint<B> ret = a;
    00728         ret &= bit;
    00729         return ret;
    00730         E_END("operator &", "limitint");
    00731     }
    00732
    00733     template <class B> limitint<B> operator & (const limitint<B> & a, const limitint<B> & bit)
    00734     {
    00735         E_BEGIN;
    00736         limitint<B> ret = a;
    00737         ret &= bit;
    00738         return ret;
    00739         E_END("operator &", "limitint");
    00740     }
    00741
    00742     template <class B> limitint<B> operator | (const limitint<B> & a, U_32 bit)
    00743     {
    00744         E_BEGIN;
    00745         limitint<B> ret = a;
    00746         ret |= bit;
    00747         return ret;
    00748         E_END("operator |", "U_32");
    00749     }
    00750
    00751     template <class B> limitint<B> operator | (const limitint<B> & a, const limitint<B> & bit)
    00752     {
    00753         E_BEGIN;
    00754         limitint<B> ret = a;
    00755         ret |= bit;
    00756         return ret;
    00757         E_END("operator |", "limitint");
    00758     }
    00759
    00760     template <class B> limitint<B> operator ^ (const limitint<B> & a, U_32 bit)
    00761     {
    00762         E_BEGIN;
    00763         limitint<B> ret = a;
    00764         ret ^= bit;
    00765         return ret;
    00766         E_END("operator ^", "U_32");
    00767     }
    00768
    00769     template <class B> limitint<B> operator ^ (const limitint<B> & a, const limitint<B> & bit)
    00770     {
    00771         E_BEGIN;
    00772         limitint<B> ret = a;
    00773         ret ^= bit;
    00774         return ret;
    00775         E_END("operator ^", "limitint");
    00776     }
    00777
    00778
    00779 } // end of namespace
    00780
    00781 #endif