algebramix_doc 0.3
|
00001 00002 /****************************************************************************** 00003 * MODULE : base_integer.hpp 00004 * DESCRIPTION: Change of base for integers 00005 * COPYRIGHT : (C) 2009 Joris van der Hoeven and Gregoire Lecerf 00006 ******************************************************************************* 00007 * This software falls under the GNU general public license and comes WITHOUT 00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details. 00009 * If you don't have this file, write to the Free Software Foundation, Inc., 00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00011 ******************************************************************************/ 00012 00013 #ifndef __MMX_BASE_INTEGER_HPP 00014 #define __MMX_BASE_INTEGER_HPP 00015 #include <numerix/modular_integer.hpp> 00016 #include <algebramix/base.hpp> 00017 #include <algebramix/base_blocks.hpp> 00018 #include <algebramix/base_int.hpp> 00019 00020 namespace mmx { 00021 00022 /****************************************************************************** 00023 * Variants / Note that default is signed 00024 ******************************************************************************/ 00025 00026 DEFINE_VARIANT(base_naive_integer,base_signed<base_naive>) 00027 DEFINE_VARIANT(base_dicho_integer,base_signed<base_dicho<base_naive> >) 00028 00029 STMPL 00030 struct base_naive_variant_helper<integer> { 00031 typedef base_naive_integer BV; 00032 }; 00033 00034 STMPL 00035 struct base_dicho_variant_helper<integer> { 00036 typedef base_dicho_integer BV; 00037 }; 00038 00039 STMPL 00040 struct base_transformer_helper<integer,integer> { 00041 typedef base_dicho_transformer<integer> Baser; 00042 }; 00043 00044 STMPL 00045 struct base_transformer_helper_unsigned<integer,integer> { 00046 typedef base_dicho_transformer<integer,std_base_dicho<integer>, 00047 base_dicho<base_naive> > Baser; 00048 }; 00049 00050 template<typename I> 00051 struct size_bound_in_base_helper<integer,I> { 00052 static inline nat 00053 size (const integer& s, const I& p) { 00054 ASSERT (bit_size (p) > 1, "invalid base"); 00055 return 1 + (1 + bit_size (s)) / (bit_size (p) - 1); } 00056 }; 00057 00058 /****************************************************************************** 00059 * Threshold 00060 ******************************************************************************/ 00061 00062 STMPL 00063 struct threshold_helper<integer,base_blocks_threshold> { 00064 typedef fixed_value<nat,32> impl; 00065 }; 00066 00067 /****************************************************************************** 00068 * Special transformer 00069 ******************************************************************************/ 00070 00071 template<typename I> 00072 struct base_integer_transformer { 00073 typedef integer C; 00074 00075 // default internal type is 'int' for speed 00076 static const nat internal_size= 00077 sizeof(I) > sizeof(int) ? sizeof(I) : sizeof(int); 00078 typedef typename unsigned_int_with_size_at_least_helper< 00079 internal_size>::type uJ; 00080 typedef typename signed_of_helper<uJ>::type J; 00081 00082 typedef typename Modulus_variant(I) modulus_base_variant; 00083 typedef modulus<I, modulus_base_variant> M; 00084 00085 typedef typename Modulus_variant(J) modulus_middle_variant; 00086 typedef modulus<J, modulus_middle_variant> N; 00087 00088 typedef C base; 00089 typedef I modulus_base; 00090 00091 struct std_J_I { 00092 typedef J base; 00093 typedef I modulus_base; 00094 typedef typename Modulus_variant(I) modulus_base_variant; 00095 }; 00096 typedef base_naive_transformer<J,std_J_I> Baser_I; 00097 00098 struct std_C_J { 00099 typedef C base; 00100 typedef J modulus_base; 00101 typedef modulus_middle_variant modulus_base_variant; 00102 }; 00103 typedef base_blocks_transformer< 00104 Baser_I, 00105 base_naive_transformer<C,std_C_J> > Baser_low; 00106 00107 typedef base_dicho_transformer<integer, 00108 std_base_dicho<integer> > Baser_high; 00109 typedef base_blocks_transformer<Baser_low, Baser_high> Baser; 00110 00111 M p; 00112 Baser* baser; 00113 00114 template<typename K> 00115 inline base_integer_transformer (const K& _p) : p (_p) { 00116 J p_s= * p; nat s= 1; 00117 while ((p_s * * p) / * p == p_s) { p_s *= * p; s++; } 00118 baser= mmx_new<Baser> (1, mmx_new<Baser_low> (1, p, s)); 00119 } 00120 00121 inline ~base_integer_transformer () { 00122 mmx_delete<Baser> (baser, 1); } 00123 00124 inline nat direct_transform (I* c, nat n, const C& a) { 00125 return direct_base (c, n, a, * baser); } 00126 00127 inline void inverse_transform (C& a, const I* c, nat n) { 00128 return inverse_base (a, c, n, * baser); } 00129 }; 00130 00131 #define IMPLEMENTATION_HELPER(I) \ 00132 STMPL struct base_transformer_helper<integer,I> { \ 00133 typedef base_integer_transformer<I> Baser; }; 00134 IMPLEMENTATION_HELPER(signed char) 00135 IMPLEMENTATION_HELPER(short int) 00136 IMPLEMENTATION_HELPER(int) 00137 IMPLEMENTATION_HELPER(long int) 00138 IMPLEMENTATION_HELPER(long long int) 00139 #undef IMPLEMENTATION_HELPER 00140 00141 /****************************************************************************** 00142 * Special transformer for nonnegative integers 00143 ******************************************************************************/ 00144 00145 template<typename I> 00146 struct base_unsigned_integer_transformer { 00147 typedef integer C; 00148 00149 // default internal type is 'unsigned int' for speed 00150 static const nat internal_size= 00151 sizeof(I) > sizeof(int) ? sizeof(I) : sizeof(int); 00152 typedef typename unsigned_int_with_size_at_least_helper< 00153 internal_size>::type J; 00154 00155 typedef typename Modulus_variant(I) modulus_base_variant; 00156 typedef modulus<I, modulus_base_variant> M; 00157 00158 typedef typename Modulus_variant(J) modulus_middle_variant; 00159 typedef modulus<J, modulus_middle_variant> N; 00160 00161 typedef C base; 00162 typedef I modulus_base; 00163 00164 struct std_J_I { 00165 typedef J base; 00166 typedef I modulus_base; 00167 typedef typename Modulus_variant(I) modulus_base_variant; 00168 }; 00169 typedef base_naive_transformer<J,std_J_I, base_naive> Baser_I; 00170 00171 struct std_C_J { 00172 typedef C base; 00173 typedef J modulus_base; 00174 typedef modulus_middle_variant modulus_base_variant; 00175 }; 00176 typedef base_blocks_transformer< 00177 Baser_I, 00178 base_naive_transformer<C,std_C_J,base_naive> > Baser_low; 00179 00180 typedef base_dicho_transformer<integer, std_base_dicho<integer>, 00181 base_dicho<base_naive> > Baser_high; 00182 typedef base_blocks_transformer<Baser_low, Baser_high> Baser; 00183 00184 M p; 00185 Baser* baser; 00186 00187 template<typename K> 00188 inline base_unsigned_integer_transformer (const K& _p) : p (_p) { 00189 J p_s= * p; nat s= 1; 00190 while ((p_s * * p) / * p == p_s) { p_s *= * p; s++; } 00191 baser= mmx_new<Baser> (1, mmx_new<Baser_low> (1, p, s)); 00192 } 00193 00194 inline ~base_unsigned_integer_transformer () { 00195 mmx_delete<Baser> (baser, 1); } 00196 00197 inline nat direct_transform (I* c, nat n, const C& a) { 00198 ASSERT (a >= 0, "invalid negative argument"); 00199 return direct_base (c, n, a, * baser); } 00200 00201 inline void inverse_transform (C& a, const I* c, nat n) { 00202 return inverse_base (a, c, n, * baser); } 00203 }; 00204 00205 #define IMPLEMENTATION_HELPER(I) \ 00206 STMPL struct base_transformer_helper<integer,I> { \ 00207 typedef base_unsigned_integer_transformer<I> Baser; }; 00208 IMPLEMENTATION_HELPER(unsigned char) 00209 IMPLEMENTATION_HELPER(unsigned short) 00210 IMPLEMENTATION_HELPER(unsigned int) 00211 IMPLEMENTATION_HELPER(unsigned long int) 00212 IMPLEMENTATION_HELPER(unsigned long long int) 00213 #undef IMPLEMENTATION_HELPER 00214 00215 #define IMPLEMENTATION_HELPER(I) \ 00216 STMPL struct base_transformer_helper_unsigned<integer,I> { \ 00217 typedef base_unsigned_integer_transformer<I> Baser; }; 00218 IMPLEMENTATION_HELPER(signed char) 00219 IMPLEMENTATION_HELPER(short int) 00220 IMPLEMENTATION_HELPER(int) 00221 IMPLEMENTATION_HELPER(long int) 00222 IMPLEMENTATION_HELPER(long long int) 00223 #undef IMPLEMENTATION_HELPER 00224 00225 } // namespace mmx 00226 #endif // __MMX_BASE_INTEGER_HPP