numerix_doc 0.4
/Users/mourrain/Devel/mmx/numerix/include/numerix/ball_rough.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : ball_rough.hpp
00004 * DESCRIPTION: More efficient but rough ball arithmetic
00005 * COPYRIGHT  : (C) 2010  Joris van der Hoeven
00006 *******************************************************************************
00007 * This file implements a more efficient implementation of ball arithmetic,
00008 * which works for all rounding modes and never changes the rounding mode.
00009 * Nevertheless, it does assume IEEE 754 compliant floating point types.
00010 * The implementation does not attempt to provide correctness for
00011 * infinite ball argnuments. Furthermore, some operations which should
00012 * return a fuzzy ball with an infinite radius are allowed to only return
00013 * a ball with a largest possible finite radius Largest(C).
00014 *******************************************************************************
00015 * This software falls under the GNU general public license and comes WITHOUT
00016 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00017 * If you don't have this file, write to the Free Software Foundation, Inc.,
00018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019 ******************************************************************************/
00020 
00021 #ifndef __MMX_BALL_ROUGH_HPP
00022 #define __MMX_BALL_ROUGH_HPP
00023 #include <numerix/ball_rounded.hpp>
00024 namespace mmx {
00025 #define TMPL template<typename C,typename R,typename V>
00026 #define Ball ball<C,R,V>
00027 
00028 /******************************************************************************
00029 * The ball_rough variant
00030 ******************************************************************************/
00031 
00032 struct ball_rough {};
00033 
00034 template<typename F, typename V>
00035 struct implementation<F,V,ball_rough>:
00036   public implementation<F,V,ball_rounded> {};
00037 
00038 STMPL
00039 struct ball_variant_helper<double> {
00040   typedef ball_rough BV;
00041 };
00042 
00043 /******************************************************************************
00044 * Additive operations
00045 ******************************************************************************/
00046 
00047 TMPL inline void
00048 add_rough_additive_error (Ball& d) {
00049   radius (d) += additive_error (center (d));
00050   radius (d) *= (1 + incexp2 (Accuracy (R), 2));
00051 }
00052 
00053 template<typename V> inline void
00054 add_rough_additive_error (ball<double,double,V>& d) {
00055   const double alpha= 1.000000000000008882;
00056   radius (d)= alpha * (radius (d) + ldexp (abs (center (d)), -50));
00057 }
00058 
00059 template<typename W>
00060 struct implementation<ball_additive,W,ball_rough> {
00061 
00062 TMPL static inline void
00063 neg (Ball& d, const Ball& z) {
00064   center (d)= -center (z);
00065   radius (d)= radius (z);
00066 }
00067 
00068 TMPL static inline void
00069 add (Ball& d, const Ball& z1, const Ball& z2) {
00070   center (d)= center (z1) + center (z2);
00071   radius (d)= radius (z1) + radius (z2);
00072   add_rough_additive_error (d);
00073 }
00074 
00075 TMPL static inline void
00076 add (Ball& d, const C& z1, const Ball& z2) {
00077   center (d)= z1 + center (z2);
00078   radius (d)= radius (z2);
00079   add_rough_additive_error (d);
00080 }
00081 
00082 TMPL static inline void
00083 add (Ball& d, const Ball& z1, const C& z2) {
00084   center (d)= center (z1) + z2;
00085   radius (d)= radius (z1);
00086   add_rough_additive_error (d);
00087 }
00088 
00089 TMPL static inline void
00090 sub (Ball& d, const Ball& z1, const Ball& z2) {
00091   center (d)= center (z1) - center (z2);
00092   radius (d)= radius (z1) + radius (z2);
00093   add_rough_additive_error (d);
00094 }
00095 
00096 TMPL static inline void
00097 sub (Ball& d, const C& z1, const Ball& z2) {
00098   center (d)= z1 - center (z2);
00099   radius (d)= radius (z2);
00100   add_rough_additive_error (d);
00101 }
00102 
00103 TMPL static inline void
00104 sub (Ball& d, const Ball& z1, const C& z2) {
00105   center (d)= center (z1) - z2;
00106   radius (d)= radius (z1);
00107   add_rough_additive_error (d);
00108 }
00109 
00110 }; // implementation<ball_additive,W,ball_rough>
00111 
00112 /******************************************************************************
00113 * Multiplicative operations
00114 ******************************************************************************/
00115 
00116 TMPL inline void
00117 add_rough_multiplicative_error (Ball& d) {
00118   radius (d) += multiplicative_error (center (d));
00119   radius (d) *= (1 + incexp2 (Accuracy (R), 4));
00120   radius (d) += incexp2 (Smallest (R), 4);
00121 }
00122 
00123 template<typename V> inline void
00124 add_rough_multiplicative_error (ball<double,double,V>& d) {
00125   const double alpha= 1.000000000000001777;
00126   const double beta = 3.952525166729972354e-323;
00127   radius (d)= alpha * (radius (d) + ldexp (abs (center (d)), -50)) + beta;
00128 }
00129 
00130 template<typename C> inline C
00131 rough_next_above (const C& z) {
00132   return (1 + Accuracy (C)) * z;
00133 }
00134 
00135 inline double
00136 rough_next_above (const double& z) {
00137   const double alpha= 1.000000000000000223;
00138   return alpha * z;
00139 }
00140 
00141 template<typename W>
00142 struct implementation<ball_multiplicative,W,ball_rough> {
00143 
00144 TMPL static inline void
00145 mul (Ball& d, const Ball& z1, const Ball& z2) {
00146   R a1= as<R> (abs (center (z1))) + radius (z1);
00147   R a2= as<R> (abs (center (z2)));
00148   center (d)= center (z1) * center (z2);
00149   radius (d)= a1 * radius (z2) + radius (z1) * a2;
00150   add_rough_multiplicative_error (d);
00151 }
00152 
00153 TMPL static inline void
00154 mul (Ball& d, const C& z1, const Ball& z2) {
00155   R a1= as<R> (abs (z1));
00156   center (d)= z1 * center (z2);
00157   radius (d)= a1 * radius (z2);
00158   add_rough_multiplicative_error (d);
00159 }
00160 
00161 TMPL static inline void
00162 mul (Ball& d, const Ball& z1, const C& z2) {
00163   R a2= as<R> (abs (z2));
00164   center (d)= center (z1) * z2;
00165   radius (d)= radius (z1) * a2;
00166   add_rough_multiplicative_error (d);
00167 }
00168 
00169 TMPL static inline void
00170 square (Ball& d, const Ball& z) {
00171   R a= as<R> (abs (center (z)));
00172   center (d)= square_op::op (center (z));
00173   radius (d)= (a + a + radius (z)) * radius (z);
00174   add_rough_multiplicative_error (d);
00175 }
00176 
00177 TMPL static inline void
00178 invert (Ball& d, const Ball& z) {
00179   R a= max (as<R> (abs (center (z))) - rough_next_above (radius (z)), R(0));
00180   center (d)= invert_op::op (center (z));
00181   radius (d)= radius (z) / square_op::op (a);
00182   add_rough_multiplicative_error (d);
00183 }
00184 
00185 TMPL static inline void
00186 invert (Ball& d, const C& z) {
00187   center (d)= invert_op::op (z);
00188   radius (d)= multiplicative_error (center (d));
00189 }
00190 
00191 TMPL static inline void
00192 div (Ball& d, const Ball& z1, const Ball& z2) {
00193   d= z1 * invert_op::op (z2);
00194 }
00195 
00196 TMPL static inline void
00197 div (Ball& d, const Ball& z1, const C& z2) {
00198   d= z1 * invert_op::op (z2);
00199 }
00200 
00201 TMPL static inline void
00202 div (Ball& d, const C& z1, const Ball& z2) {
00203   d= z1 * invert_op::op (z2);
00204 }
00205 
00206 }; // implementation<ball_multiplicative,W,ball_rough>
00207 
00208 /******************************************************************************
00209 * Square root related functions
00210 ******************************************************************************/
00211 
00212 template<typename W>
00213 struct implementation<ball_root,W,ball_rough> {
00214 
00215 TMPL static void
00216 sqrt (Ball& d, const Ball& z) {
00217   R l= as<R> (center (z)) - rough_next_above (radius (z));
00218   if (l <= 0) d= Nan (Ball);
00219   else {
00220     center (d)= sqrt_op::op (center (z));
00221     radius (d)= decexp2 (radius (z)) / sqrt_op::op (l);
00222     add_rough_multiplicative_error (d);
00223   }
00224 }
00225 
00226 TMPL static void
00227 hypot (Ball& d, const Ball& x, const Ball& y) {
00228   center (d)= hypot_op::op (center (x), center (y));
00229   radius (d)= hypot_op::op (radius (x), radius (y));
00230   add_rough_multiplicative_error (d);
00231 }
00232 
00233 }; // implementation<ball_root,W,ball_rough>
00234 
00235 /******************************************************************************
00236 * Shift operations
00237 ******************************************************************************/
00238 
00239 template<typename W>
00240 struct implementation<ball_shift,W,ball_rough> {
00241 
00242 TMPL static inline void
00243 shiftl (Ball& d, const xint& shift) {
00244   center (d)= incexp2 (center (d), shift);
00245   radius (d)= incexp2 (radius (d), shift) + Smallest (R);
00246 }
00247 
00248 TMPL static inline void
00249 shiftl (Ball& d, const Ball& z, const xint& shift) {
00250   center (d)= incexp2 (center (z), shift);
00251   radius (d)= incexp2 (radius (z), shift) + Smallest (R);
00252 }
00253 
00254 TMPL static inline void
00255 shiftr (Ball& d, const xint& shift) {
00256   center (d)= decexp2 (center (d), shift);
00257   radius (d)= decexp2 (radius (d), shift) + Smallest (R);
00258 }
00259 
00260 TMPL static inline void
00261 shiftr (Ball& d, const Ball& z, const xint& shift) {
00262   center (d)= decexp2 (center (z), shift);
00263   radius (d)= decexp2 (radius (z), shift) + Smallest (R);
00264 }
00265 
00266 }; // implementation<ball_shift,W,ball_rough>
00267 
00268 #undef TMPL
00269 #undef Ball
00270 } // namespace mmx
00271 #endif // __MMX_BALL_ROUGH_HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines