numerix_doc 0.4
/Users/mourrain/Devel/mmx/numerix/include/numerix/affine.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines