numerix_doc 0.4
|
00001 00002 /****************************************************************************** 00003 * MODULE : affine.hpp 00004 * DESCRIPTION: Affine numbers 00005 * COPYRIGHT : (C) 2011 Joris van der Hoeven 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_AFFINE_HPP 00014 #define __MMX_AFFINE_HPP 00015 #include <basix/function.hpp> 00016 #include <numerix/ball.hpp> 00017 namespace mmx { 00018 #define TMPL_DEF template<typename C, typename VC= C> 00019 #define TMPL template<typename C, typename VC> 00020 #define R Radius_type(C) 00021 #define VR typename affine_limits_helper<C,VC>::VT 00022 #define Affine affine<C,VC> 00023 #define Affine_rep affine_rep<C,VC> 00024 #define Abs_affine affine<Abs_type(C),Abs_type(VC) > 00025 #define Real_affine affine<Real_type(C),Real_type(VC) > 00026 TMPL class affine; 00027 TMPL struct affine_limits_helper; 00028 TMPL inline C base (const Affine& z); 00029 TMPL inline VC slope (const Affine& z); 00030 TMPL inline VR limits (const Affine& z); 00031 TMPL inline Affine operator - (const Affine& z1, const Affine& z2); 00032 00033 /****************************************************************************** 00034 * Routines for domains of affine numbers 00035 ******************************************************************************/ 00036 00037 template<typename C> inline C dot (const C& x, const C& y) { return x * y; } 00038 00039 TMPL 00040 struct affine_limits_helper { 00041 typedef Radius_type(VC) VT; 00042 static inline VT infinite () { 00043 return Maximal (VT); } 00044 static inline VC get_linear (const VC& lin, const VC& dom) { 00045 return lin + sharpen (dom); } 00046 static inline VT get_limits (const VC& dom) { 00047 return radius (dom); } 00048 static inline VC get_domain (const VT& lim) { 00049 return blur (VC (0), lim); } 00050 static inline C truncate (const VC& lin, const VT& lim) { 00051 return dot (lin, get_domain (lim)); } 00052 static inline VT common (const VT& lim1, const VT& lim2) { 00053 if (hard_eq (lim1, lim2)) return lim1; 00054 return inf (radius (lim1), radius (lim2)); } 00055 }; 00056 00057 /****************************************************************************** 00058 * The affine type 00059 ******************************************************************************/ 00060 00061 TMPL_DEF 00062 class affine { 00063 MMX_ALLOCATORS 00064 private: 00065 C cst; 00066 VC lin; 00067 VR lim; 00068 00069 public: 00070 typedef affine_limits_helper<C,VC> Helper; 00071 inline affine (): 00072 cst (0), lin (0), lim (Helper::infinite ()) {} 00073 inline affine (const format<C>& fm1, const format<VC>& fm2): 00074 cst (promote (0, fm1)), lin (promote (0, fm2)), 00075 lim (Helper::infinite ()) {} 00076 template<typename T> affine (const T& cst2): 00077 cst (cst2), lin (0), lim (Helper::infinite ()) {} 00078 inline affine (const C& z): 00079 cst (copy (z)), lin (0), lim (Helper::infinite ()) {} 00080 inline affine (const C& cst2, const VC& lin2): 00081 cst (cst2), lin (lin2), lim (Helper::infinite ()) {} 00082 inline affine (const C& cst2, const VC& lin2, const VR& lim2): 00083 cst (cst2), lin (lin2), lim (lim2) {} 00084 template<typename CT,typename VCT> inline affine (const affine<CT,VCT>& z): 00085 cst (as<C> (base (z))), 00086 lin (as<VC> (slope (z))), 00087 lim (as<VR > (limits (z))) {} 00088 friend C base LESSGTR (const Affine& z); 00089 friend VC slope LESSGTR (const Affine& z); 00090 friend VR limits LESSGTR (const Affine& z); 00091 }; 00092 DEFINE_BINARY_FORMAT_2 (affine) 00093 00094 TMPL struct rounding_helper<Affine >: public rounding_helper<C> {}; 00095 00096 STYPE_TO_TYPE(TMPL,scalar_type,Affine,C); 00097 UNARY_RETURN_TYPE(TMPL,Re_op,Affine,Real_affine); 00098 UNARY_RETURN_TYPE(TMPL,abs_op,Affine,Abs_affine); 00099 00100 /****************************************************************************** 00101 * Basic routines 00102 ******************************************************************************/ 00103 00104 TMPL inline C base (const Affine& z) { 00105 return z.cst; } 00106 TMPL inline VC slope (const Affine& z) { 00107 return z.lin; } 00108 TMPL inline VR limits (const Affine& z) { 00109 return z.lim; } 00110 TMPL inline format<C> CF1 (const Affine& z) { 00111 return get_format (base (z)); } 00112 TMPL inline format<VC> CF2 (const Affine& z) { 00113 return get_format (slope (z)); } 00114 TMPL inline C truncate (const Affine& z) { 00115 typedef affine_limits_helper<C,VC> Helper; 00116 return base (z) + Helper::truncate (slope (z), limits (z)); } 00117 TMPL inline VR common_limits (const Affine& z1, const Affine& z2) { 00118 typedef affine_limits_helper<C,VC> Helper; 00119 return Helper::common (limits (z1), limits (z2)); } 00120 00121 TMPL inline Affine make_affine (const C& cst, const VC& lin, const VC& dom) { 00122 typedef affine_limits_helper<C,VC> Helper; 00123 return Affine (cst, Helper::get_linear (lin, dom), 00124 Helper::get_limits (dom)); } 00125 TMPL inline VC domain (const Affine& z) { 00126 typedef affine_limits_helper<C,VC> Helper; 00127 return Helper::get_domain (limits (z)); } 00128 00129 00130 TMPL inline Affine copy (const Affine& z) { 00131 return Affine (copy (base (z)), copy (slope (z)), copy (limits (z))); } 00132 TMPL inline Affine duplicate (const Affine& z) { 00133 return Affine (duplicate (base (z)), duplicate (slope (z)), 00134 duplicate (limits (z))); } 00135 00136 template<typename Op, typename C, typename VC> nat 00137 unary_hash (const Affine& x) { 00138 nat h= Op::op (base (x)); 00139 h += (h<<3) ^ (h<<11) ^ (h>>29) ^ Op::op (slope (x)); 00140 return (h<<3) ^ (h<<11) ^ (h>>29) ^ Op::op (limits (x)); 00141 } 00142 00143 template<typename Op, typename C, typename VC> bool 00144 binary_test (const Affine& x1, const Affine& x2) { 00145 return Op::op (base (x1), base (x2)) && 00146 Op::op (slope (x1), slope (x2)) && 00147 Op::op (limits (x1), limits (x2)); 00148 } 00149 00150 template<typename CS, typename CD, typename DS, typename DD> affine<CD,DD> 00151 map (const function_1<CD,Argument(CS) >& funC, 00152 const function_1<DD,Argument(DS) >& funD, 00153 const affine<CS,DS>& z, 00154 const format<CD>& fmC, 00155 const format<DD>& fmD) { 00156 return affine<CD,DD> (funC (base (z)), funD (slope (z))); 00157 } 00158 00159 TRUE_IDENTITY_OP_SUGAR(TMPL,Affine) 00160 EXACT_IDENTITY_OP_SUGAR(TMPL,Affine) 00161 HARD_IDENTITY_OP_SUGAR(TMPL,Affine) 00162 00163 TMPL syntactic 00164 flatten (const Affine& z) { 00165 return apply ("affine", flatten (base (z)), flatten (slope (z)), 00166 flatten (limits (z))); 00167 } 00168 00169 TMPL 00170 struct binary_helper<Affine >: public void_binary_helper<Affine > { 00171 static inline string short_type_name () { 00172 return "Af" * Short_type_name (C) * Short_type_name (VC); } 00173 static inline generic full_type_name () { 00174 return gen ("Affine", Full_type_name (C)); } 00175 static inline generic disassemble (const Affine& z) { 00176 return gen_vec (as<generic> (base (z)), 00177 as<generic> (slope (z)), 00178 as<generic> (limits (z))); } 00179 static inline Affine assemble (const generic& v) { 00180 return Affine (as<C> (vector_access (v, 0)), 00181 as<VC> (vector_access (v, 1)), 00182 as<VR> (vector_access (v, 2))); } 00183 static inline void write (const port& out, const Affine& z) { 00184 binary_write<C> (out, base (z)); 00185 binary_write<VC> (out, slope (z)); 00186 binary_write<VC> (out, limits (z)); } 00187 static inline Affine read (const port& in) { 00188 C b= binary_read<C> (in); 00189 VC s= binary_read<VC> (in); 00190 VR d= binary_read<VR> (in); 00191 return Affine (b, s, d); } 00192 }; 00193 00194 /****************************************************************************** 00195 * Constants 00196 ******************************************************************************/ 00197 00198 TMPL inline void set_nan (Affine& x) { x= Affine (Nan (C), 0); } 00199 TMPL inline void set_maximal (Affine& x) { x= Affine (Maximal (C), 0); } 00200 TMPL inline void set_minimal (Affine& x) { x= Affine (Minimal (C), 0); } 00201 TMPL inline void set_infinity (Affine& x) { x= Affine (Infinity (C), 0); } 00202 TMPL inline void set_fuzz (Affine& x) { x= Affine (Fuzz (C), 0); } 00203 TMPL inline void set_smallest (Affine& x) { x= Affine (Smallest (C), 0); } 00204 TMPL inline void set_largest (Affine& x) { x= Affine (Largest (C), 0); } 00205 TMPL inline void set_accuracy (Affine& x) { x= Affine (Accuracy (C), 0); } 00206 TMPL inline void set_log2 (Affine& x) { x= Affine (Log2 (C), 0); } 00207 TMPL inline void set_pi (Affine& x) { x= Affine (Pi (C), 0); } 00208 TMPL inline void set_euler (Affine& x) { x= Affine (Euler (C), 0); } 00209 TMPL inline void set_imaginary (Affine& x) { x= Affine (Imaginary (C), 0); } 00210 00211 TMPL inline Affine times_infinity (const Affine& x) { 00212 return x * infinity_cst<Affine > (); } 00213 00214 /****************************************************************************** 00215 * Basic arithmetic 00216 ******************************************************************************/ 00217 00218 TMPL inline Affine 00219 operator - (const Affine& z) { 00220 return Affine (-base (z), -slope (z), limits (z)); 00221 } 00222 00223 TMPL inline Affine 00224 operator + (const Affine& z1, const Affine& z2) { 00225 VR lim= common_limits (z1, z2); 00226 return Affine (base (z1) + base (z2), slope (z1) + slope (z2), lim); 00227 } 00228 00229 TMPL inline Affine 00230 operator + (const C& z1, const Affine& z2) { 00231 return Affine (z1 + base (z2), slope (z2), limits (z2)); 00232 } 00233 00234 TMPL inline Affine 00235 operator + (const Affine& z1, const C& z2) { 00236 return Affine (base (z1) + z2, slope (z1), limits (z1)); 00237 } 00238 00239 TMPL inline Affine 00240 operator - (const Affine& z1, const Affine& z2) { 00241 return Affine (base (z1) - base (z2), slope (z1) - slope (z2)); 00242 } 00243 00244 TMPL inline Affine 00245 operator - (const C& z1, const Affine& z2) { 00246 return Affine (z1 - base (z2), slope (z2), limits (z2)); 00247 } 00248 00249 TMPL inline Affine 00250 operator - (const Affine& z1, const C& z2) { 00251 return Affine (base (z1) - z2, slope (z1), limits (z1)); 00252 } 00253 00254 TMPL inline Affine 00255 operator * (const Affine& z1, const Affine& z2) { 00256 VR lim= common_limits (z1, z2); 00257 return Affine (base (z1) * base (z2), 00258 truncate (z1) * slope (z2) + slope (z1) * truncate (z2), lim); 00259 } 00260 00261 TMPL inline Affine 00262 operator * (const C& z1, const Affine& z2) { 00263 return Affine (z1 * base (z2), z1 * slope (z2), limits (z2)); 00264 } 00265 00266 TMPL inline Affine 00267 operator * (const Affine& z1, const C& z2) { 00268 return Affine (base (z1) * z2, slope (z1) * z2, limits (z1)); 00269 } 00270 00271 TMPL inline Affine 00272 square (const Affine& z) { 00273 return Affine (square (base (z)), 00274 (base (z) + truncate (z)) * slope (z), limits (z)); 00275 } 00276 00277 TMPL inline Affine 00278 invert (const Affine& z) { 00279 ERROR ("not yet implemented"); 00280 //C inv= invert (base (z)); 00281 //return Affine (inv, - square (inv) * slope (z)); 00282 } 00283 00284 TMPL inline Affine 00285 operator / (const Affine& z1, const Affine& z2) { 00286 ERROR ("not yet implemented"); 00287 //C inv= invert (base (z2)); 00288 //return Affine (inv * base (z1), 00289 // inv * (slope (z1) - inv * base (z1) * slope (z2))); 00290 } 00291 00292 TMPL inline Affine 00293 operator / (const C& z1, const Affine& z2) { 00294 ERROR ("not yet implemented"); 00295 //C inv= invert (base (z2)); 00296 //return Affine (inv * z1, - square (inv) * z1 * slope (z2)); 00297 } 00298 00299 TMPL inline Affine 00300 operator / (const Affine& z1, const C& z2) { 00301 C inv= invert (z2); 00302 return Affine (inv * base (z1), inv * slope (z1), limits (z1)); 00303 } 00304 00305 ARITH_INT_SUGAR(TMPL,Affine); 00306 00307 /****************************************************************************** 00308 * Elementary functions 00309 ******************************************************************************/ 00310 00311 /* 00312 TMPL inline Affine 00313 sqrt (const Affine& z) { 00314 C s= sqrt (base (z)); 00315 return Affine (s, slope (z) / (2 * s)); 00316 } 00317 00318 TMPL inline Affine 00319 exp (const Affine& z) { 00320 C e= exp (base (z)); 00321 return Affine (e, e * slope (z)); 00322 } 00323 00324 TMPL inline Affine 00325 log (const Affine& z) { 00326 return Affine (log (base (z)), slope (z) / base (z)); 00327 } 00328 00329 template<typename C, typename VC, typename K> inline Affine 00330 pow (const Affine& z, const K& y) { 00331 return exp (Affine (y) * log (z)); 00332 } 00333 00334 TMPL inline Affine 00335 cos (const Affine& z) { 00336 return Affine (cos (base (z)), -sin (base (z)) * slope (z)); 00337 } 00338 00339 TMPL inline Affine 00340 sin (const Affine& z) { 00341 return Affine (sin (base (z)), cos (base (z)) * slope (z)); 00342 } 00343 00344 TMPL inline Affine 00345 tan (const Affine& z) { 00346 return sin (z) / cos (z); 00347 } 00348 00349 TMPL inline Affine 00350 cosh (const Affine& z) { 00351 return Affine (cosh (base (z)), sinh (base (z)) * slope (z)); 00352 } 00353 00354 TMPL inline Affine 00355 sinh (const Affine& z) { 00356 return Affine (sinh (base (z)), cosh (base (z)) * slope (z)); 00357 } 00358 00359 TMPL Affine 00360 tanh (const Affine& z) { 00361 return sinh (z) / cosh (z); 00362 } 00363 00364 TMPL Affine 00365 acos (const Affine& z) { 00366 C df= -1 / sqrt (1 - square (base (z))); 00367 return Affine (acos (base (z)), df * slope (z)); 00368 } 00369 00370 TMPL Affine 00371 asin (const Affine& z) { 00372 C df= 1 / sqrt (1 - square (base (z))); 00373 return Affine (asin (base (z)), df * slope (z)); 00374 } 00375 00376 TMPL Affine 00377 atan (const Affine& z) { 00378 C df= 1 / (1 + square (base (z))); 00379 return Affine (asin (base (z)), df * slope (z)); 00380 } 00381 00382 TMPL Affine 00383 atan2 (const Affine& y, const Affine& x) { 00384 ERROR ("not yet implemented"); 00385 return Affine (atan2 (base (y), base (x)), 0); 00386 } 00387 00388 HYPOT_SUGAR(TMPL,Affine) 00389 INV_TRIGO_SUGAR(TMPL,Affine) 00390 INV_HYPER_SUGAR(TMPL,Affine) 00391 ARG_HYPER_SUGAR(TMPL,Affine) 00392 */ 00393 00394 /****************************************************************************** 00395 * Comparisons and other order related functions 00396 ******************************************************************************/ 00397 00398 TMPL inline bool 00399 operator <= (const Affine& z1, const Affine& z2) { 00400 return base (z1) < base (z2) || z1 == z2; 00401 } 00402 00403 TMPL inline bool 00404 operator < (const Affine& z1, const Affine& z2) { 00405 return base (z1) < base (z2); 00406 } 00407 00408 TMPL inline bool 00409 operator >= (const Affine& z1, const Affine& z2) { 00410 return base (z1) > base (z2) || z1 == z2; 00411 } 00412 00413 TMPL inline bool 00414 operator > (const Affine& z1, const Affine& z2) { 00415 return base (z1) > base (z2); 00416 } 00417 00418 TMPL inline Affine 00419 min (const Affine& z1, const Affine& z2) { 00420 if (z1 <= z2) return z1; else return z2; 00421 } 00422 00423 TMPL Affine 00424 max (const Affine& z1, const Affine& z2) { 00425 if (z1 >= z2) return z1; else return z2; 00426 } 00427 00428 EQUAL_INT_SUGAR(TMPL,Affine); 00429 COMPARE_INT_SUGAR(TMPL,Affine); 00430 00431 /****************************************************************************** 00432 * Floating point related functions 00433 ******************************************************************************/ 00434 00435 TMPL inline bool is_finite (const Affine& z) { 00436 return is_finite (base (z)) && is_finite (slope (z)); } 00437 TMPL inline bool is_nan (const Affine& z) { 00438 return is_nan (base (z)) || is_nan (slope (z)); } 00439 TMPL inline bool is_infinite (const Affine& z) { 00440 return !is_nan (z) && (is_infinite (base (z)) || is_infinite (slope (z))); } 00441 TMPL inline bool is_fuzz (const Affine& z) { 00442 return !is_nan (z) && (is_fuzz (base (z)) || is_fuzz (slope (z))); } 00443 TMPL inline bool is_reliable (const Affine& z) { 00444 return is_reliable (base (z)); } 00445 00446 TMPL inline Affine change_precision (const Affine& z, xnat prec) { 00447 return Affine (change_precision (base (z), prec), 00448 change_precision (slope (z), prec), 00449 change_precision (limits (z), prec)); } 00450 TMPL inline xnat precision (const Affine& z) { 00451 return precision (base (z)); } 00452 TMPL inline Affine additive_error (const Affine& z) { 00453 return Affine (additive_error (base (z)), 00454 additive_error (slope (z)), 00455 limits (z)); } 00456 00457 TMPL inline double magnitude (const Affine& z) { 00458 return magnitude (base (z)); } 00459 TMPL inline xint exponent (const Affine& z) { 00460 return exponent (base (z)); } 00461 TMPL inline Affine operator << (const Affine& z, const xint& s) { 00462 return Affine (incexp2 (base (z), s), incexp2 (slope (z), s), limits (z)); } 00463 TMPL inline Affine operator >> (const Affine& z, const xint& s) { 00464 return Affine (decexp2 (base (z), s), decexp2 (slope (z), s), limits (z)); } 00465 00466 TMPL inline Affine sharpen (const Affine& z) { 00467 return Affine (sharpen (base (z)), sharpen (slope (z)), limits (z)); } 00468 template<typename C, typename VC, typename C2, typename VC2> inline Affine 00469 blur (const Affine& z, const affine<C2,VC2>& r) { 00470 return Affine (blur (base (z), base (r)), blur (slope (z), slope (r)), 00471 limits (z)); } 00472 00473 /****************************************************************************** 00474 * Complex affine numbers 00475 ******************************************************************************/ 00476 00477 TMPL inline Abs_affine 00478 abs (const Affine& z) { 00479 // FIXME: this is not really nice 00480 return Abs_affine (abs (base (z)), abs (slope (z)), limits (z)); 00481 } 00482 00483 TMPL inline Real_affine 00484 Re (const Affine& z) { 00485 return Real_affine (Re (base (z)), Re (slope (z)), limits (z)); 00486 } 00487 00488 TMPL inline Real_affine 00489 Im (const Affine& z) { 00490 return Real_affine (Im (base (z)), Im (slope (z)), limits (z)); 00491 } 00492 00493 #undef TMPL_DEF 00494 #undef TMPL 00495 #undef R 00496 #undef VR 00497 #undef Affine 00498 #undef Affine_rep 00499 } // namespace mmx 00500 #endif // __MMX_AFFINE_HPP