bigar.hpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002     
00003     bigar.hpp.
00004 
00005     This file is a part of the Arageli library.
00006     
00007     WARNING. This is internal header of Arageli library.
00008     Do not use it directly in you code other then Arageli code.
00009 
00010     Copyright (C) Nikolai Yu. Zolotykh, 1999 -- 2005
00011     University of Nizhni Novgorod, Russia
00012 
00013 *****************************************************************************/
00014 
00015 #ifndef __ARAGELI_bigar_hpp__
00016 #define __ARAGELI_bigar_hpp__
00017 
00018 #include "config.hpp"
00019 
00020 #include <cstddef>
00021 #include <cstdlib>
00022 #include <limits>
00023 
00024 #include "std_import.hpp"
00025 
00026 
00027 namespace Arageli { namespace _Internal
00028 {
00029 
00030 // WARNING for the whole file!
00031 // Sizes, types and masks can be failed on some platforms.
00032 // This is a temporary implementation.
00033     
00034 // The following macroswitches have been got from 1.03n version of Arageli.
00035 
00036 //#ifdef USE_ASM
00037 //#  if defined(__WIN32__) || defined (__WATCOMC__)
00038 //     typedef unsigned int digit; // 4 bytes
00039 //     const digit max_digit = 0xFFFFFFFF;
00040 //     const int bits_per_digit = 32;
00041 //#    include"bigar32.h"
00042 //#  else
00043 //     typedef unsigned int digit;
00044 //     const digit max_digit = 0xFFFF;
00045 //     const int bits_per_digit = 16;
00046 //#    include"bigarbc.h"
00047 //#  endif
00048 //#else
00049 
00050 #if defined(_MSC_VER) && defined (_WIN32) || 0 && defined(__BORLANDC__) && defined(__WIN32__) 
00051 //   The following works well for Ms C (Win32)
00052 //   Also you can use these for Borland C 5.5 compiler.
00053 //   but surprisingly the code will be more slower than for settings by default (see below)
00054 //   For Microsoft Visual C++ use /O2 optimizing option
00055 
00056     typedef unsigned long digit;
00057     typedef unsigned __int64 doubledigit;    
00058     typedef unsigned __int64 extendeddigit;  
00059     typedef unsigned short int bit;      
00060     const digit max_digit = 0xFFFFFFFF;      
00061     const extendeddigit BASE = 0x100000000l; 
00062     const int bits_per_digit = 32;       
00063 
00064     //typedef unsigned short digit;
00065     //typedef unsigned int doubledigit;    
00066     //typedef unsigned int extendeddigit;  
00067     //typedef unsigned short int bit;      
00068     //const digit max_digit = 0xFFFF;      
00069     //const extendeddigit BASE = 0x10000; 
00070     //const int bits_per_digit = 16;       
00071 
00072 #elif defined ARAGELI_LONG_LONG_SUPPORT
00073     typedef unsigned long digit;
00074     typedef unsigned long long doubledigit;    
00075     typedef unsigned long long extendeddigit;  
00076     typedef unsigned short int bit;      
00077     const digit max_digit = 0xFFFFFFFF;      
00078     const extendeddigit BASE = 0x100000000l; 
00079     const int bits_per_digit = 32;       
00080 #else
00081 //   For others compilers we can also TRY this
00082 //   These setting works well for a lot of compilers (Microsoft, Borland, gcc)
00083 //   For Borlan C++ use -O2 optimizing option
00084 //   For gcc use /O3 optimizing option
00085      typedef unsigned short digit;    
00086      typedef unsigned long doubledigit;    
00087      typedef unsigned long extendeddigit;  
00088      typedef unsigned short bit;      
00089      const digit max_digit = 0xFFFF;      
00090      const extendeddigit BASE = 0x10000l; 
00091      const int bits_per_digit = 16;       
00092 #endif
00093 
00094 
00095 std::size_t do_big_int_to_bdn (digit* a, digit* b, std::size_t n, digit bdn_radix);
00096 std::size_t do_bdn_to_big_int (digit* a, digit* b, std::size_t n, digit bdn_radix);
00097 std::size_t do_add (digit* p1, const digit* p2, std::size_t m, std::size_t n);
00098 int     do_sub (digit* p1, const digit* p2, std::size_t m, std::size_t n);
00099 std::size_t do_optimize (const digit* a, std::size_t n);
00100 std::size_t do_mult (const digit* u, const digit* v, digit* w, std::size_t m, std::size_t n);
00101 //std::size_t   do_mult_by_digit (digit* a, digit* p, std::size_t n, std::size_t d);    // not using
00102 digit   do_divide_by_digit (const digit* a, digit* p, std::size_t n, digit d);
00103 std::size_t do_divide (digit* u, digit* v, digit* q, std::size_t m, std::size_t n);
00104 
00105 }
00106 
00107 #if 0
00108 
00109 namespace Bigar
00110 {
00111 
00112 template <typename D> struct doubledigit;
00113 template <typename D> struct extendeddigit;
00114 template <typename D> struct bits_per_digit;
00115 template <typename D> struct max_digit;
00116 template <typename D> struct base;
00117 
00118 // temporary definitions
00119 template <> struct doubledigit<unsigned long>
00120 { typedef unsigned __int64 type; };
00121 
00122 template <> struct extendeddigit<unsigned long>
00123 { typedef unsigned __int64 type; };
00124 
00125 template <> struct bits_per_digit<unsigned long>
00126 {
00127     static const unsigned int
00128         value = std::numeric_limits<unsigned long>::digits;
00129 };
00130 
00131 template <> struct max_digit<unsigned long>
00132 {
00133     static const unsigned long value;
00134 };
00135 
00136 const unsigned long max_digit<unsigned long>::value
00137     = std::numeric_limits<unsigned long>::max();
00138 
00139 template <> struct base<unsigned long>
00140 {
00141 private:
00142     typedef extendeddigit<unsigned long>::type exdig;
00143 public:
00144     static const exdig
00145         value/* = static_cast<exdig>(max_digit<unsigned long>::value) + 1*/;
00146 };
00147 
00148 const extendeddigit<unsigned long>::type
00149 base<unsigned long>::value = static_cast<exdig>(max_digit<unsigned long>::value) + 1;
00150 
00151 typedef unsigned char bit;
00152 
00153 template <typename D> struct digit_info
00154 {
00155     typedef typename Bigar::doubledigit<D>::type doubledigit;
00156     typedef typename Bigar::extendeddigit<D>::type extendeddigit;
00157     static const unsigned int bits_per_digit = Bigar::bits_per_digit<D>::value;
00158     static const D max_digit = Bigar::max_digit<D>::value;
00159     static const extendeddigit base = Bigar::base<D>::value;
00160 };
00161 
00162 
00163 template <typename In, typename Out>
00164 typename std::iterator_traits<Out>::difference_type
00165 addseq
00166 (
00167     Out res,
00168     In in,
00169     typename std::iterator_traits<Out>::difference_type size_res,
00170     typename std::iterator_traits<Out>::difference_type size_in
00171 );
00172 
00173 template <typename In, typename Out>
00174 typename std::iterator_traits<Out>::difference_type
00175 addseq
00176 (
00177     Out res,
00178     In in,
00179     typename std::iterator_traits<Out>::difference_type size_res,
00180     typename std::iterator_traits<Out>::difference_type size_in
00181 )
00182 {
00183     ARAGELI_ASSERT_1(size_res >= size_in);
00184 
00185     typedef std::iterator_traits<Out> Out_traits;
00186     typedef typename Out_traits::difference_type pos_type;
00187     typedef digit_info<typename Out_traits::value_type> digit_info;
00188 
00189     // actually, length of p1 must be m+1 - reserved for carry
00190     // do_add returns amount of main digits (m without carry or m+1 with carry) 
00191 
00192     ARAGELI_ASSERT_1(m >= n);
00193 
00194     bit carry = 0;
00195 
00196     // 1. loop for 0 to n-1 - add digits of p2 to p1
00197 
00198     for(pos_type i = 0; i < n; i++)
00199     {
00200         typename digit_info::doubledigit
00201             tmp = static_cast<typename digit_info::doubledigit>(p1[i])
00202                 + p2[i] + carry;
00203         
00204         res[i] = digit(tmp % digit_info::base);
00205         carry = digit(tmp / digit_info::base);
00206     }
00207 
00208     // 2. loop for add carry
00209 
00210     for(pos_type i = n; i < m; i++)
00211     {
00212         doubledigit tmp = doubledigit(p1[i]) + carry;
00213         p1[i] = digit(tmp % BASE);
00214         carry = digit(tmp / BASE);
00215         if(carry == 0) break;
00216     }
00217 
00218     if(carry)
00219     {
00220         p1[m] = 1;
00221         return m + 1;
00222     }
00223     else return m;
00224 }
00225 
00226 
00227 
00228 }
00229 
00230 #endif
00231 
00232 
00233 }
00234 
00235 #endif

Generated on Thu Aug 31 17:38:05 2006 for Arageli by  doxygen 1.4.7