annotate DEPENDENCIES/generic/include/boost/numeric/interval/arith2.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 /* Boost interval/arith2.hpp template implementation file
Chris@16 2 *
Chris@16 3 * This header provides some auxiliary arithmetic
Chris@16 4 * functions: fmod, sqrt, square, pov, inverse and
Chris@16 5 * a multi-interval division.
Chris@16 6 *
Chris@16 7 * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
Chris@16 8 *
Chris@16 9 * Distributed under the Boost Software License, Version 1.0.
Chris@16 10 * (See accompanying file LICENSE_1_0.txt or
Chris@16 11 * copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 12 */
Chris@16 13
Chris@16 14 #ifndef BOOST_NUMERIC_INTERVAL_ARITH2_HPP
Chris@16 15 #define BOOST_NUMERIC_INTERVAL_ARITH2_HPP
Chris@16 16
Chris@16 17 #include <boost/config.hpp>
Chris@16 18 #include <boost/numeric/interval/detail/interval_prototype.hpp>
Chris@16 19 #include <boost/numeric/interval/detail/test_input.hpp>
Chris@16 20 #include <boost/numeric/interval/detail/bugs.hpp>
Chris@16 21 #include <boost/numeric/interval/detail/division.hpp>
Chris@16 22 #include <boost/numeric/interval/arith.hpp>
Chris@16 23 #include <boost/numeric/interval/policies.hpp>
Chris@16 24 #include <algorithm>
Chris@16 25 #include <cassert>
Chris@16 26 #include <boost/config/no_tr1/cmath.hpp>
Chris@16 27
Chris@16 28 namespace boost {
Chris@16 29 namespace numeric {
Chris@16 30
Chris@16 31 template<class T, class Policies> inline
Chris@16 32 interval<T, Policies> fmod(const interval<T, Policies>& x,
Chris@16 33 const interval<T, Policies>& y)
Chris@16 34 {
Chris@16 35 if (interval_lib::detail::test_input(x, y))
Chris@16 36 return interval<T, Policies>::empty();
Chris@16 37 typename Policies::rounding rnd;
Chris@16 38 typedef typename interval_lib::unprotect<interval<T, Policies> >::type I;
Chris@16 39 T const &yb = interval_lib::user::is_neg(x.lower()) ? y.lower() : y.upper();
Chris@16 40 T n = rnd.int_down(rnd.div_down(x.lower(), yb));
Chris@16 41 return (const I&)x - n * (const I&)y;
Chris@16 42 }
Chris@16 43
Chris@16 44 template<class T, class Policies> inline
Chris@16 45 interval<T, Policies> fmod(const interval<T, Policies>& x, const T& y)
Chris@16 46 {
Chris@16 47 if (interval_lib::detail::test_input(x, y))
Chris@16 48 return interval<T, Policies>::empty();
Chris@16 49 typename Policies::rounding rnd;
Chris@16 50 typedef typename interval_lib::unprotect<interval<T, Policies> >::type I;
Chris@16 51 T n = rnd.int_down(rnd.div_down(x.lower(), y));
Chris@16 52 return (const I&)x - n * I(y);
Chris@16 53 }
Chris@16 54
Chris@16 55 template<class T, class Policies> inline
Chris@16 56 interval<T, Policies> fmod(const T& x, const interval<T, Policies>& y)
Chris@16 57 {
Chris@16 58 if (interval_lib::detail::test_input(x, y))
Chris@16 59 return interval<T, Policies>::empty();
Chris@16 60 typename Policies::rounding rnd;
Chris@16 61 typedef typename interval_lib::unprotect<interval<T, Policies> >::type I;
Chris@16 62 T const &yb = interval_lib::user::is_neg(x) ? y.lower() : y.upper();
Chris@16 63 T n = rnd.int_down(rnd.div_down(x, yb));
Chris@16 64 return x - n * (const I&)y;
Chris@16 65 }
Chris@16 66
Chris@16 67 namespace interval_lib {
Chris@16 68
Chris@16 69 template<class T, class Policies> inline
Chris@16 70 interval<T, Policies> division_part1(const interval<T, Policies>& x,
Chris@16 71 const interval<T, Policies>& y, bool& b)
Chris@16 72 {
Chris@16 73 typedef interval<T, Policies> I;
Chris@16 74 b = false;
Chris@16 75 if (detail::test_input(x, y))
Chris@16 76 return I::empty();
Chris@16 77 if (zero_in(y))
Chris@16 78 if (!user::is_zero(y.lower()))
Chris@16 79 if (!user::is_zero(y.upper()))
Chris@16 80 return detail::div_zero_part1(x, y, b);
Chris@16 81 else
Chris@16 82 return detail::div_negative(x, y.lower());
Chris@16 83 else
Chris@16 84 if (!user::is_zero(y.upper()))
Chris@16 85 return detail::div_positive(x, y.upper());
Chris@16 86 else
Chris@16 87 return I::empty();
Chris@16 88 else
Chris@16 89 return detail::div_non_zero(x, y);
Chris@16 90 }
Chris@16 91
Chris@16 92 template<class T, class Policies> inline
Chris@16 93 interval<T, Policies> division_part2(const interval<T, Policies>& x,
Chris@16 94 const interval<T, Policies>& y, bool b = true)
Chris@16 95 {
Chris@16 96 if (!b) return interval<T, Policies>::empty();
Chris@16 97 return detail::div_zero_part2(x, y);
Chris@16 98 }
Chris@16 99
Chris@16 100 template<class T, class Policies> inline
Chris@16 101 interval<T, Policies> multiplicative_inverse(const interval<T, Policies>& x)
Chris@16 102 {
Chris@16 103 typedef interval<T, Policies> I;
Chris@16 104 if (detail::test_input(x))
Chris@16 105 return I::empty();
Chris@16 106 T one = static_cast<T>(1);
Chris@16 107 typename Policies::rounding rnd;
Chris@16 108 if (zero_in(x)) {
Chris@16 109 typedef typename Policies::checking checking;
Chris@16 110 if (!user::is_zero(x.lower()))
Chris@16 111 if (!user::is_zero(x.upper()))
Chris@16 112 return I::whole();
Chris@16 113 else
Chris@16 114 return I(checking::neg_inf(), rnd.div_up(one, x.lower()), true);
Chris@16 115 else
Chris@16 116 if (!user::is_zero(x.upper()))
Chris@16 117 return I(rnd.div_down(one, x.upper()), checking::pos_inf(), true);
Chris@16 118 else
Chris@16 119 return I::empty();
Chris@16 120 } else
Chris@16 121 return I(rnd.div_down(one, x.upper()), rnd.div_up(one, x.lower()), true);
Chris@16 122 }
Chris@16 123
Chris@16 124 namespace detail {
Chris@16 125
Chris@16 126 template<class T, class Rounding> inline
Chris@16 127 T pow_dn(const T& x_, int pwr, Rounding& rnd) // x and pwr are positive
Chris@16 128 {
Chris@16 129 T x = x_;
Chris@16 130 T y = (pwr & 1) ? x_ : static_cast<T>(1);
Chris@16 131 pwr >>= 1;
Chris@16 132 while (pwr > 0) {
Chris@16 133 x = rnd.mul_down(x, x);
Chris@16 134 if (pwr & 1) y = rnd.mul_down(x, y);
Chris@16 135 pwr >>= 1;
Chris@16 136 }
Chris@16 137 return y;
Chris@16 138 }
Chris@16 139
Chris@16 140 template<class T, class Rounding> inline
Chris@16 141 T pow_up(const T& x_, int pwr, Rounding& rnd) // x and pwr are positive
Chris@16 142 {
Chris@16 143 T x = x_;
Chris@16 144 T y = (pwr & 1) ? x_ : static_cast<T>(1);
Chris@16 145 pwr >>= 1;
Chris@16 146 while (pwr > 0) {
Chris@16 147 x = rnd.mul_up(x, x);
Chris@16 148 if (pwr & 1) y = rnd.mul_up(x, y);
Chris@16 149 pwr >>= 1;
Chris@16 150 }
Chris@16 151 return y;
Chris@16 152 }
Chris@16 153
Chris@16 154 } // namespace detail
Chris@16 155 } // namespace interval_lib
Chris@16 156
Chris@16 157 template<class T, class Policies> inline
Chris@16 158 interval<T, Policies> pow(const interval<T, Policies>& x, int pwr)
Chris@16 159 {
Chris@16 160 BOOST_USING_STD_MAX();
Chris@16 161 using interval_lib::detail::pow_dn;
Chris@16 162 using interval_lib::detail::pow_up;
Chris@16 163 typedef interval<T, Policies> I;
Chris@16 164
Chris@16 165 if (interval_lib::detail::test_input(x))
Chris@16 166 return I::empty();
Chris@16 167
Chris@16 168 if (pwr == 0)
Chris@16 169 if (interval_lib::user::is_zero(x.lower())
Chris@16 170 && interval_lib::user::is_zero(x.upper()))
Chris@16 171 return I::empty();
Chris@16 172 else
Chris@16 173 return I(static_cast<T>(1));
Chris@16 174 else if (pwr < 0)
Chris@16 175 return interval_lib::multiplicative_inverse(pow(x, -pwr));
Chris@16 176
Chris@16 177 typename Policies::rounding rnd;
Chris@16 178
Chris@16 179 if (interval_lib::user::is_neg(x.upper())) { // [-2,-1]
Chris@16 180 T yl = pow_dn(static_cast<T>(-x.upper()), pwr, rnd);
Chris@16 181 T yu = pow_up(static_cast<T>(-x.lower()), pwr, rnd);
Chris@16 182 if (pwr & 1) // [-2,-1]^1
Chris@16 183 return I(-yu, -yl, true);
Chris@16 184 else // [-2,-1]^2
Chris@16 185 return I(yl, yu, true);
Chris@16 186 } else if (interval_lib::user::is_neg(x.lower())) { // [-1,1]
Chris@16 187 if (pwr & 1) { // [-1,1]^1
Chris@16 188 return I(-pow_up(static_cast<T>(-x.lower()), pwr, rnd), pow_up(x.upper(), pwr, rnd), true);
Chris@16 189 } else { // [-1,1]^2
Chris@16 190 return I(static_cast<T>(0), pow_up(max BOOST_PREVENT_MACRO_SUBSTITUTION(static_cast<T>(-x.lower()), x.upper()), pwr, rnd), true);
Chris@16 191 }
Chris@16 192 } else { // [1,2]
Chris@16 193 return I(pow_dn(x.lower(), pwr, rnd), pow_up(x.upper(), pwr, rnd), true);
Chris@16 194 }
Chris@16 195 }
Chris@16 196
Chris@16 197 template<class T, class Policies> inline
Chris@16 198 interval<T, Policies> sqrt(const interval<T, Policies>& x)
Chris@16 199 {
Chris@16 200 typedef interval<T, Policies> I;
Chris@16 201 if (interval_lib::detail::test_input(x) || interval_lib::user::is_neg(x.upper()))
Chris@16 202 return I::empty();
Chris@16 203 typename Policies::rounding rnd;
Chris@16 204 T l = !interval_lib::user::is_pos(x.lower()) ? static_cast<T>(0) : rnd.sqrt_down(x.lower());
Chris@16 205 return I(l, rnd.sqrt_up(x.upper()), true);
Chris@16 206 }
Chris@16 207
Chris@16 208 template<class T, class Policies> inline
Chris@16 209 interval<T, Policies> square(const interval<T, Policies>& x)
Chris@16 210 {
Chris@16 211 typedef interval<T, Policies> I;
Chris@16 212 if (interval_lib::detail::test_input(x))
Chris@16 213 return I::empty();
Chris@16 214 typename Policies::rounding rnd;
Chris@16 215 const T& xl = x.lower();
Chris@16 216 const T& xu = x.upper();
Chris@16 217 if (interval_lib::user::is_neg(xu))
Chris@16 218 return I(rnd.mul_down(xu, xu), rnd.mul_up(xl, xl), true);
Chris@16 219 else if (interval_lib::user::is_pos(x.lower()))
Chris@16 220 return I(rnd.mul_down(xl, xl), rnd.mul_up(xu, xu), true);
Chris@16 221 else
Chris@16 222 return I(static_cast<T>(0), (-xl > xu ? rnd.mul_up(xl, xl) : rnd.mul_up(xu, xu)), true);
Chris@16 223 }
Chris@16 224
Chris@16 225 namespace interval_lib {
Chris@16 226 namespace detail {
Chris@16 227
Chris@16 228 template< class I > inline
Chris@16 229 I root_aux(typename I::base_type const &x, int k) // x and k are bigger than one
Chris@16 230 {
Chris@16 231 typedef typename I::base_type T;
Chris@16 232 T tk(k);
Chris@16 233 I y(static_cast<T>(1), x, true);
Chris@16 234 for(;;) {
Chris@16 235 T y0 = median(y);
Chris@16 236 I yy = intersect(y, y0 - (pow(I(y0, y0, true), k) - x) / (tk * pow(y, k - 1)));
Chris@16 237 if (equal(y, yy)) return y;
Chris@16 238 y = yy;
Chris@16 239 }
Chris@16 240 }
Chris@16 241
Chris@16 242 template< class I > inline // x is positive and k bigger than one
Chris@16 243 typename I::base_type root_aux_dn(typename I::base_type const &x, int k)
Chris@16 244 {
Chris@16 245 typedef typename I::base_type T;
Chris@16 246 typedef typename I::traits_type Policies;
Chris@16 247 typename Policies::rounding rnd;
Chris@16 248 T one(1);
Chris@16 249 if (x > one) return root_aux<I>(x, k).lower();
Chris@16 250 if (x == one) return one;
Chris@16 251 return rnd.div_down(one, root_aux<I>(rnd.div_up(one, x), k).upper());
Chris@16 252 }
Chris@16 253
Chris@16 254 template< class I > inline // x is positive and k bigger than one
Chris@16 255 typename I::base_type root_aux_up(typename I::base_type const &x, int k)
Chris@16 256 {
Chris@16 257 typedef typename I::base_type T;
Chris@16 258 typedef typename I::traits_type Policies;
Chris@16 259 typename Policies::rounding rnd;
Chris@16 260 T one(1);
Chris@16 261 if (x > one) return root_aux<I>(x, k).upper();
Chris@16 262 if (x == one) return one;
Chris@16 263 return rnd.div_up(one, root_aux<I>(rnd.div_down(one, x), k).lower());
Chris@16 264 }
Chris@16 265
Chris@16 266 } // namespace detail
Chris@16 267 } // namespace interval_lib
Chris@16 268
Chris@16 269 template< class T, class Policies > inline
Chris@16 270 interval<T, Policies> nth_root(interval<T, Policies> const &x, int k)
Chris@16 271 {
Chris@16 272 typedef interval<T, Policies> I;
Chris@16 273 if (interval_lib::detail::test_input(x)) return I::empty();
Chris@16 274 assert(k > 0);
Chris@16 275 if (k == 1) return x;
Chris@16 276 typename Policies::rounding rnd;
Chris@16 277 typedef typename interval_lib::unprotect<I>::type R;
Chris@16 278 if (!interval_lib::user::is_pos(x.upper())) {
Chris@16 279 if (interval_lib::user::is_zero(x.upper())) {
Chris@16 280 T zero(0);
Chris@16 281 if (!(k & 1) || interval_lib::user::is_zero(x.lower())) // [-1,0]^/2 or [0,0]
Chris@16 282 return I(zero, zero, true);
Chris@16 283 else // [-1,0]^/3
Chris@16 284 return I(-interval_lib::detail::root_aux_up<R>(-x.lower(), k), zero, true);
Chris@16 285 } else if (!(k & 1)) // [-2,-1]^/2
Chris@16 286 return I::empty();
Chris@16 287 else { // [-2,-1]^/3
Chris@16 288 return I(-interval_lib::detail::root_aux_up<R>(-x.lower(), k),
Chris@16 289 -interval_lib::detail::root_aux_dn<R>(-x.upper(), k), true);
Chris@16 290 }
Chris@16 291 }
Chris@16 292 T u = interval_lib::detail::root_aux_up<R>(x.upper(), k);
Chris@16 293 if (!interval_lib::user::is_pos(x.lower()))
Chris@16 294 if (!(k & 1) || interval_lib::user::is_zero(x.lower())) // [-1,1]^/2 or [0,1]
Chris@16 295 return I(static_cast<T>(0), u, true);
Chris@16 296 else // [-1,1]^/3
Chris@16 297 return I(-interval_lib::detail::root_aux_up<R>(-x.lower(), k), u, true);
Chris@16 298 else // [1,2]
Chris@16 299 return I(interval_lib::detail::root_aux_dn<R>(x.lower(), k), u, true);
Chris@16 300 }
Chris@16 301
Chris@16 302 } // namespace numeric
Chris@16 303 } // namespace boost
Chris@16 304
Chris@16 305 #endif // BOOST_NUMERIC_INTERVAL_ARITH2_HPP