00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef _ARAGELI_random_hpp_
00015 #define _ARAGELI_random_hpp_
00016
00017 #include <cstdlib>
00018
00019 #include "big_int.hpp"
00020 #include "rational.hpp"
00021 #include "vector.hpp"
00022 #include "matrix.hpp"
00023 #include "sparse_polynom.hpp"
00024
00025 namespace Arageli{
00026
00027 struct rand_config
00028 {
00029 enum {
00030 integer_min = -100,
00031 integer_max = 100,
00032 degree_max = 10,
00033 vector_len_max = 10,
00034 matrix_dim_max = 6
00035 };
00036 };
00037
00038 namespace _Internal
00039 {
00040 template<bool cond, class _then, class _else>
00041 struct IF {typedef _then ret;};
00042 template<class _then, class _else>
00043 struct IF<false,_then,_else> {typedef _else ret;};
00044
00045 template<typename T> struct IS_TYPE_BASE {enum{ret = false};};
00046
00047 template<> struct IS_TYPE_BASE<signed char> {enum{ret = true};};
00048 template<> struct IS_TYPE_BASE<unsigned char> {enum{ret = true};};
00049 template<> struct IS_TYPE_BASE<signed short> {enum{ret = true};};
00050 template<> struct IS_TYPE_BASE<unsigned short> {enum{ret = true};};
00051 template<> struct IS_TYPE_BASE<signed int> {enum{ret = true};};
00052 template<> struct IS_TYPE_BASE<unsigned int> {enum{ret = true};};
00053 template<> struct IS_TYPE_BASE<signed long> {enum{ret = true};};
00054 template<> struct IS_TYPE_BASE<unsigned long> {enum{ret = true};};
00055 #if defined(ARAGELI_LONG_LONG_SUPPORT)
00056 template<> struct IS_TYPE_BASE<signed long long> {enum{ret = true};};
00057 template<> struct IS_TYPE_BASE<unsigned long long> {enum{ret = true};};
00058 #endif // ARAGELI_LONG_LONG_SUPPORT
00059 #if defined(ARAGELI_INT64_SUPPORT)
00060 template<> struct IS_TYPE_BASE<signed __int64> {enum{ret = true};};
00061 template<> struct IS_TYPE_BASE<unsigned __int64> {enum{ret = true};};
00062 #endif // ARAGELI_INT64_SUPPORT
00063 template<> struct IS_TYPE_BASE<float> {enum{ret = true};};
00064 template<> struct IS_TYPE_BASE<double> {enum{ret = true};};
00065 template<> struct IS_TYPE_BASE<long double> {enum{ret = true};};
00066
00067 template<> struct IS_TYPE_BASE<big_int> {enum{ret = true};};
00068
00069
00070 template<typename T, class Conf>
00071 struct rand_nolimited{
00072 static T rand(void) {return T();}
00073 };
00074 template<typename T, int min, int max>
00075 struct rand_limited{
00076 static T rand(void) {return T();}
00077 };
00078 #define RAND (std::rand())
00079 #define SPECIALIZE_RAND(type,gen_alg,lim_gen_alg) \
00080 template<class Conf> \
00081 struct rand_nolimited<type,Conf>{\
00082 static type rand(void) {return (type)(gen_alg);}\
00083 };\
00084 template<int min, int max>\
00085 struct rand_limited<type,min,max>{\
00086 static type rand(void) {return (type)(lim_gen_alg);}\
00087 }
00088
00089 SPECIALIZE_RAND(signed int,(Conf::integer_min + RAND % (Conf::integer_max - Conf::integer_min)),(min + RAND % (max - min)));
00090 SPECIALIZE_RAND(unsigned int,(RAND % Conf::integer_max),(min + RAND % (max - min)));
00091 SPECIALIZE_RAND(signed char,(Conf::integer_min + RAND % (Conf::integer_max - Conf::integer_min)),(min + RAND % (max - min)));
00092 SPECIALIZE_RAND(unsigned char,(RAND % Conf::integer_max),(min + RAND % (max - min)));
00093 SPECIALIZE_RAND(signed short,(Conf::integer_min + RAND % (Conf::integer_max - Conf::integer_min)),(min + RAND % (max - min)));
00094 SPECIALIZE_RAND(unsigned short,(RAND % Conf::integer_max),(min + RAND % (max - min)));
00095 SPECIALIZE_RAND(signed long,(Conf::integer_min + RAND % (Conf::integer_max - Conf::integer_min)),(min + RAND % (max - min)));
00096 SPECIALIZE_RAND(unsigned long,(RAND % Conf::integer_max),(min + RAND % (max - min)));
00097 #if defined(ARAGELI_LONG_LONG_SUPPORT)
00098 SPECIALIZE_RAND(signed long long,(Conf::integer_min + RAND % (Conf::integer_max - Conf::integer_min)),(min + RAND % (max - min)));
00099 SPECIALIZE_RAND(unsigned long long,(RAND % Conf::integer_max),(min + RAND % (max - min)));
00100 #endif // ARAGELI_LONG_LONG_SUPPORT
00101 #if defined(ARAGELI_INT64_SUPPORT)
00102 SPECIALIZE_RAND(signed __int64,(Conf::integer_min + RAND % (Conf::integer_max - Conf::integer_min)),(min + RAND % (max - min)));
00103 SPECIALIZE_RAND(unsigned __int64,(RAND % Conf::integer_max),(min + RAND % (max - min)));
00104 #endif // ARAGELI_INT64_SUPPORT
00105 SPECIALIZE_RAND(float,(RAND / (1. + RAND)),(RAND / (1. + RAND)));
00106 SPECIALIZE_RAND(double,(RAND / (1. + RAND)),(RAND / (1. + RAND)));
00107 SPECIALIZE_RAND(long double,(RAND / (1. + RAND)),(RAND / (1. + RAND)));
00108
00109 SPECIALIZE_RAND(big_int,(big_int::random_in_range(big_int(Conf::integer_max - Conf::integer_min)) + Conf::integer_min),
00110 (big_int::random_in_range(big_int(max - min)) + min));
00111
00112 template<typename T, class Conf>
00113 struct rand_nolimited<rational<T>,Conf>{
00114 typedef typename IF<IS_TYPE_BASE<T>::ret,rand_limited<T,Conf::integer_min,Conf::integer_max>,rand_nolimited<T,Conf> >::ret r_type;
00115 static rational<T> rand(void)
00116 {
00117 T den;
00118 do{den = r_type::rand(); }while(is_null(den));
00119 return rational<T>(r_type::rand(),den);
00120 }
00121 };
00122
00123 template<typename F, typename I, class Conf>
00124 struct rand_nolimited<monom<F, I>,Conf>{
00125 typedef typename IF<IS_TYPE_BASE<F>::ret,rand_limited<F,Conf::integer_min,Conf::integer_max>,rand_nolimited<F,Conf> >::ret F_type;
00126 typedef typename IF<IS_TYPE_BASE<I>::ret,rand_limited<I,0,Conf::degree_max>,rand_nolimited<I,Conf> >::ret I_type;
00127 static monom<F, I> rand(void)
00128 {
00129 return monom<F, I>(F_type::rand(),I_type::rand());
00130 }
00131 };
00132
00133 template<typename F, typename I, bool REFCNT, class Conf>
00134 struct rand_nolimited<sparse_polynom<F, I, REFCNT>,Conf>{
00135 static sparse_polynom<F, I, REFCNT> rand(void)
00136 {
00137 sparse_polynom<F, I, REFCNT> res;
00138 for (int i = 0; i < Conf::degree_max; ++i)
00139 {
00140 monom<F,I> mon = rand_nolimited<monom<F, I>,Conf>::rand();
00141 bool fl = true;
00142 for(typename sparse_polynom<F, I, REFCNT>::degree_iterator i = res.degrees_begin(), j = res.degrees_end(); i != j && fl; ++i)
00143 if(*i == mon.degree()) fl = false;
00144 if(fl)res += mon;
00145 }
00146 return res;
00147 }
00148 };
00149
00150 template<typename T, bool REFCNT, class Conf>
00151 struct rand_nolimited<matrix<T, REFCNT>,Conf>{
00152 typedef typename IF<IS_TYPE_BASE<T>::ret,rand_limited<T,Conf::integer_min,Conf::integer_max>,rand_nolimited<T,Conf> >::ret r_type;
00153 static matrix<T, REFCNT> rand(void)
00154 {
00155 matrix<T, REFCNT> res
00156 (
00157 rand_limited<typename matrix<T, REFCNT>::size_type,1,Conf::matrix_dim_max>::rand(),
00158 rand_limited<typename matrix<T, REFCNT>::size_type,1,Conf::matrix_dim_max>::rand()
00159 );
00160
00161 for (typename matrix<T, REFCNT>::size_type i = 0; i < res.nrows(); i++)
00162 for (typename matrix<T, REFCNT>::size_type j = 0; j < res.ncols(); j++)
00163 res.el(i,j) = r_type::rand();
00164 return res;
00165 }
00166 };
00167
00168 template<typename T, bool REFCNT, class Conf>
00169 struct rand_nolimited<vector<T, REFCNT>,Conf>{
00170 typedef typename IF<IS_TYPE_BASE<T>::ret,rand_limited<T,Conf::integer_min,Conf::integer_max>,rand_nolimited<T,Conf> >::ret r_type;
00171 static vector<T, REFCNT> rand(void)
00172 {
00173 vector<T, REFCNT> res(rand_limited<typename vector<T, REFCNT>::size_type,1,Conf::vector_len_max>::rand());
00174 for (typename vector<T, REFCNT>::size_type i = 0; i < res.size(); i++)
00175 res.el(i) = r_type::rand();
00176 return res;
00177 }
00178 };
00179
00180 }
00181
00182 template<typename T, class Conf = rand_config>
00183 struct rnd
00184 {
00185 static T rand() {return _Internal::rand_nolimited<T,Conf>::rand();}
00186 };
00187
00188 }
00189
00190
00191 #endif //_ARAGELI_random_hpp_