00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef NTG_REAL_BEHAVIOUR_HH
00029 # define NTG_REAL_BEHAVIOUR_HH
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 # include <mlc/bool.hh>
00040 # include <mlc/contract.hh>
00041 # include <mlc/is_a.hh>
00042
00043 # include <ntg/core/contract.hh>
00044 # include <ntg/core/macros.hh>
00045 # include <ntg/core/type_traits.hh>
00046 # include <ntg/core/value.hh>
00047 # include <ntg/core/internal/macros.hh>
00048 # include <ntg/real/optraits_real.hh>
00049 # include <ntg/real/real_value.hh>
00050 # include <ntg/utils/debug.hh>
00051 # include <ntg/utils/cast.hh>
00052
00053 # include <string>
00054 # include <sstream>
00055
00056
00057
00058
00059
00060
00061 namespace ntg
00062 {
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00077
00080 struct unsafe
00081 {
00082 template <class T>
00083 struct get
00084 {
00085 typedef ntgi_storage_type(T) storage_type;
00086
00087 template <class T1, class T2>
00088 static T
00089 check_plus (T1 lhs, T2 rhs)
00090 { return lhs + rhs; }
00091
00092 template <class T1, class T2>
00093 static T
00094 check_minus (T1 lhs, T2 rhs)
00095 { return lhs - rhs; }
00096
00097 template <class T1, class T2>
00098 static T
00099 check_times (T1 lhs, T2 rhs)
00100 { return lhs * rhs; }
00101
00102 template <class T1, class T2>
00103 static T
00104 check_div (T1 lhs, T2 rhs)
00105 { return lhs / rhs; }
00106
00107 template <class P>
00108 static storage_type
00109 check (const P& p)
00110 { return storage_type(p); }
00111 };
00112
00113 static std::string
00114 name()
00115 { return "unsafe"; }
00116 };
00117
00118
00119
00120
00122
00137 struct force
00138 {
00139 template <class T>
00140 struct get
00141 {
00142 typedef ntgi_storage_type(T) storage_type;
00143
00144 template <class T1, class T2>
00145 static T
00146 check_plus (T1 lhs, T2 rhs)
00147 { return cast::force<T>(lhs + rhs); }
00148
00149 template <class T1, class T2>
00150 static T
00151 check_minus (T1 lhs, T2 rhs)
00152 { return cast::force<T>(lhs - rhs); }
00153
00154 template <class T1, class T2>
00155 static T
00156 check_times (T1 lhs, T2 rhs)
00157 { return cast::force<T>(lhs * rhs); }
00158
00159 template <class T1, class T2>
00160 static T
00161 check_div (T1 lhs, T2 rhs)
00162 { return cast::force<T>(lhs / rhs); }
00163
00164 template <class P>
00165 static storage_type
00166 check (const P& p)
00167 { return cast::force<T>(p); }
00168 };
00169
00170 static std::string
00171 name()
00172 { return "force"; }
00173 };
00174
00175
00176
00177
00179 struct strict
00180 {
00181 template <class T>
00182 struct get
00183 {
00184 typedef ntgi_storage_type(T) storage_type;
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 template <class T1, class T2>
00195 static T
00196 check_plus (T1 lhs, T2 rhs)
00197 {
00198 T ret = lhs + rhs;
00199 if (rhs > 0)
00200 ntg_assert(ntg_cast(ret) > lhs);
00201 else
00202 ntg_assert(ntg_cast(ret) <= lhs);
00203 return ret;
00204 }
00205
00206 template <class T1, class T2>
00207 static T
00208 check_minus (T1 lhs, T2 rhs)
00209 {
00210 T ret = lhs - rhs;
00211 if (rhs > 0)
00212 ntg_assert(ntg_cast(ret) < lhs);
00213 else
00214 ntg_assert(ntg_cast(ret) >= lhs);
00215 return ret;
00216 }
00217
00218
00219 template <class T1, class T2>
00220 static T
00221 check_times (T1 lhs, T2 rhs)
00222 {
00223 T ret = lhs * rhs;
00224 if (rhs != 0)
00225 ntg_assert((ret / rhs) == lhs);
00226 return ret;
00227 }
00228
00229 template <class T1, class T2>
00230 static T
00231 check_div (T1 lhs, T2 rhs)
00232 { return lhs / rhs; }
00233
00234 template <class P>
00235 static storage_type
00236 check (const P& p)
00237 {
00238 ntg_assert(ntg_cast(p) <= ntg_max_val(T));
00239 ntg_assert(ntg_cast(p) >= ntg_min_val(T));
00240
00241 return static_cast<storage_type>(p);
00242 }
00243 };
00244
00245 static std::string
00246 name()
00247 { return "strict"; }
00248 };
00249
00250
00251
00252
00254 struct saturate
00255 {
00256 template <class T>
00257 struct get
00258 {
00259 typedef ntgi_storage_type(T) storage_type;
00260
00261 template <class T1, class T2>
00262 static T
00263 check_plus (T1 lhs, T2 rhs)
00264 {
00265 T ret = lhs + rhs;
00266 if (rhs > 0)
00267 {
00268 if (ntg_cast(ret) <= lhs)
00269 ret = ntg_max_val(T);
00270 }
00271 else if (ntg_cast(ret) > lhs)
00272 ret = ntg_min_val(T);
00273 return ret;
00274 }
00275
00276 template <class T1, class T2>
00277 static T
00278 check_minus (T1 lhs, T2 rhs)
00279 {
00280 T ret = lhs - rhs;
00281 if (rhs > 0)
00282 {
00283 if (ntg_cast(ret) > lhs)
00284 ret = ntg_min_val(T);
00285 }
00286 else if (rhs != 0 && ntg_cast(ret) <= lhs)
00287 ret = ntg_max_val(T);
00288 return ret;
00289 }
00290
00291
00292 template <class T1, class T2>
00293 static T
00294 check_times (T1 lhs, T2 rhs)
00295 {
00296 T ret = lhs * rhs;
00297 if ((ret / rhs) != lhs)
00298 {
00299
00300 if ((lhs > 0 && rhs > 0) || (-lhs > 0 && -rhs > 0))
00301 ret = ntg_max_val(T);
00302 else
00303 ret = ntg_min_val(T);
00304 }
00305 return ret;
00306 }
00307
00308 template <class T1, class T2>
00309 static T
00310 check_div (T1 lhs, T2 rhs)
00311 { return lhs / rhs; }
00312
00313 template <class P>
00314 static storage_type
00315 check (const P& p)
00316 {
00317 if (ntg_cast(p) > ntg_max_val(T))
00318 return ntg_max_val(T);
00319
00320 if (ntg_cast(p) < ntg_min_val(T))
00321 return ntg_min_val(T);
00322
00323 return static_cast<storage_type>(p);
00324 }
00325 };
00326
00327 static std::string
00328 name()
00329 { return "saturate"; }
00330 };
00331
00332
00333
00334
00336
00342 struct cycle_behavior
00343 {
00344 template <class T>
00345 struct get
00346 {
00347 typedef ntgi_storage_type(T) storage_type;
00348
00349
00350
00351 template <class T1, class T2>
00352 static T check_plus (T1 lhs, T2 rhs)
00353 { return lhs + rhs; }
00354
00355 template <class T1, class T2>
00356 static T check_minus (T1 lhs, T2 rhs)
00357 { return lhs - rhs; }
00358
00359 template <class T1, class T2>
00360 static T check_times (T1 lhs, T2 rhs)
00361 { return lhs * rhs; }
00362
00363 template <class T1, class T2>
00364 static T check_div (T1 lhs, T2 rhs)
00365 { return lhs / rhs; }
00366
00367
00368 struct cycle_fmod
00369 {
00370 static double
00371 exec(double lhs, double rhs)
00372 { return fmod(lhs, rhs); }
00373 };
00374
00375
00376 struct cycle_mod
00377 {
00378 template <class T1, class T2>
00379 static T1
00380 exec(const T1& lhs, const T2& rhs)
00381 { return lhs % rhs; }
00382 };
00383
00384
00385 template <class P>
00386 static storage_type
00387 check (const P& rhs)
00388 {
00389 typedef typename mlc::if_<ntg_is_a(P, decimal)::ret,
00390 cycle_fmod,
00391 cycle_mod>::ret cycle_op;
00392
00393 ntg_type(P) tmp = cycle_op::exec(std::abs(ntg_signed_cast(rhs)),
00394 ntg_max_val(T) - ntg_min_val(T));
00395
00396 if (to_ntg(rhs) < 0)
00397 tmp = -tmp;
00398
00399 if (tmp < ntg_min_val(T))
00400 return ntg_max_val(T) - ntg_min_val(T) + tmp;
00401 else if (tmp >= ntg_max_val(T))
00402 return ntg_min_val(T) - ntg_max_val(T) + tmp;
00403
00404 return tmp;
00405 }
00406 };
00407
00408 static std::string
00409 name() { return "cycle_behavior"; }
00410 };
00411
00412 namespace internal {
00413
00414
00415
00416
00417
00419
00424 template <class B1, class B2>
00425 struct deduce_op_behavior
00426 { typedef strict ret; };
00427
00428 template <class B>
00429 struct deduce_op_behavior<B, B>
00430 { typedef B ret; };
00431
00432
00433
00434
00435
00437
00446 template <bool need_check, class Ret>
00447 struct ret_behavior_if
00448 {
00449 typedef typename typetraits<Ret>::abstract_behavior_type ret;
00450 };
00451
00452 template <class Ret>
00453 struct ret_behavior_if<false, Ret>
00454 {
00455 typedef ntg::force ret;
00456 };
00457
00458 }
00459
00460 }
00461
00462 #endif // !NTG_REAL_BEHAVIOUR_HH