os/ossrv/ossrv_pub/boost_apis/boost/numeric/interval/arith.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* Boost interval/arith.hpp template implementation file
sl@0
     2
 *
sl@0
     3
 * Copyright 2000 Jens Maurer
sl@0
     4
 * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
sl@0
     5
 *
sl@0
     6
 * Distributed under the Boost Software License, Version 1.0.
sl@0
     7
 * (See accompanying file LICENSE_1_0.txt or
sl@0
     8
 * copy at http://www.boost.org/LICENSE_1_0.txt)
sl@0
     9
 */
sl@0
    10
sl@0
    11
#ifndef BOOST_NUMERIC_INTERVAL_ARITH_HPP
sl@0
    12
#define BOOST_NUMERIC_INTERVAL_ARITH_HPP
sl@0
    13
sl@0
    14
#include <boost/config.hpp>
sl@0
    15
#include <boost/numeric/interval/interval.hpp>
sl@0
    16
#include <boost/numeric/interval/detail/bugs.hpp>
sl@0
    17
#include <boost/numeric/interval/detail/test_input.hpp>
sl@0
    18
#include <boost/numeric/interval/detail/division.hpp>
sl@0
    19
#include <algorithm>
sl@0
    20
sl@0
    21
namespace boost {
sl@0
    22
namespace numeric {
sl@0
    23
sl@0
    24
/*
sl@0
    25
 * Basic arithmetic operators
sl@0
    26
 */
sl@0
    27
sl@0
    28
template<class T, class Policies> inline
sl@0
    29
const interval<T, Policies>& operator+(const interval<T, Policies>& x)
sl@0
    30
{
sl@0
    31
  return x;
sl@0
    32
}
sl@0
    33
sl@0
    34
template<class T, class Policies> inline
sl@0
    35
interval<T, Policies> operator-(const interval<T, Policies>& x)
sl@0
    36
{
sl@0
    37
  if (interval_lib::detail::test_input(x))
sl@0
    38
    return interval<T, Policies>::empty();
sl@0
    39
  return interval<T, Policies>(-x.upper(), -x.lower(), true);
sl@0
    40
}
sl@0
    41
sl@0
    42
template<class T, class Policies> inline
sl@0
    43
interval<T, Policies>& interval<T, Policies>::operator+=(const interval<T, Policies>& r)
sl@0
    44
{
sl@0
    45
  if (interval_lib::detail::test_input(*this, r))
sl@0
    46
    set_empty();
sl@0
    47
  else {
sl@0
    48
    typename Policies::rounding rnd;
sl@0
    49
    set(rnd.add_down(low, r.low), rnd.add_up(up, r.up));
sl@0
    50
  }
sl@0
    51
  return *this;
sl@0
    52
}
sl@0
    53
sl@0
    54
template<class T, class Policies> inline
sl@0
    55
interval<T, Policies>& interval<T, Policies>::operator+=(const T& r)
sl@0
    56
{
sl@0
    57
  if (interval_lib::detail::test_input(*this, r))
sl@0
    58
    set_empty();
sl@0
    59
  else {
sl@0
    60
    typename Policies::rounding rnd;
sl@0
    61
    set(rnd.add_down(low, r), rnd.add_up(up, r));
sl@0
    62
  }
sl@0
    63
  return *this;
sl@0
    64
}
sl@0
    65
sl@0
    66
template<class T, class Policies> inline
sl@0
    67
interval<T, Policies>& interval<T, Policies>::operator-=(const interval<T, Policies>& r)
sl@0
    68
{
sl@0
    69
  if (interval_lib::detail::test_input(*this, r))
sl@0
    70
    set_empty();
sl@0
    71
  else {
sl@0
    72
    typename Policies::rounding rnd;
sl@0
    73
    set(rnd.sub_down(low, r.up), rnd.sub_up(up, r.low));
sl@0
    74
  }
sl@0
    75
  return *this;
sl@0
    76
}
sl@0
    77
sl@0
    78
template<class T, class Policies> inline
sl@0
    79
interval<T, Policies>& interval<T, Policies>::operator-=(const T& r)
sl@0
    80
{
sl@0
    81
  if (interval_lib::detail::test_input(*this, r))
sl@0
    82
    set_empty();
sl@0
    83
  else {
sl@0
    84
    typename Policies::rounding rnd;
sl@0
    85
    set(rnd.sub_down(low, r), rnd.sub_up(up, r));
sl@0
    86
  }
sl@0
    87
  return *this;
sl@0
    88
}
sl@0
    89
sl@0
    90
template<class T, class Policies> inline
sl@0
    91
interval<T, Policies>& interval<T, Policies>::operator*=(const interval<T, Policies>& r)
sl@0
    92
{
sl@0
    93
  return *this = *this * r;
sl@0
    94
}
sl@0
    95
sl@0
    96
template<class T, class Policies> inline
sl@0
    97
interval<T, Policies>& interval<T, Policies>::operator*=(const T& r)
sl@0
    98
{
sl@0
    99
  return *this = r * *this;
sl@0
   100
}
sl@0
   101
sl@0
   102
template<class T, class Policies> inline
sl@0
   103
interval<T, Policies>& interval<T, Policies>::operator/=(const interval<T, Policies>& r)
sl@0
   104
{
sl@0
   105
  return *this = *this / r;
sl@0
   106
}
sl@0
   107
sl@0
   108
template<class T, class Policies> inline
sl@0
   109
interval<T, Policies>& interval<T, Policies>::operator/=(const T& r)
sl@0
   110
{
sl@0
   111
  return *this = *this / r;
sl@0
   112
}
sl@0
   113
sl@0
   114
template<class T, class Policies> inline
sl@0
   115
interval<T, Policies> operator+(const interval<T, Policies>& x,
sl@0
   116
                                const interval<T, Policies>& y)
sl@0
   117
{
sl@0
   118
  if (interval_lib::detail::test_input(x, y))
sl@0
   119
    return interval<T, Policies>::empty();
sl@0
   120
  typename Policies::rounding rnd;
sl@0
   121
  return interval<T,Policies>(rnd.add_down(x.lower(), y.lower()),
sl@0
   122
                              rnd.add_up  (x.upper(), y.upper()), true);
sl@0
   123
}
sl@0
   124
sl@0
   125
template<class T, class Policies> inline
sl@0
   126
interval<T, Policies> operator+(const T& x, const interval<T, Policies>& y)
sl@0
   127
{
sl@0
   128
  if (interval_lib::detail::test_input(x, y))
sl@0
   129
    return interval<T, Policies>::empty();
sl@0
   130
  typename Policies::rounding rnd;
sl@0
   131
  return interval<T,Policies>(rnd.add_down(x, y.lower()),
sl@0
   132
                              rnd.add_up  (x, y.upper()), true);
sl@0
   133
}
sl@0
   134
sl@0
   135
template<class T, class Policies> inline
sl@0
   136
interval<T, Policies> operator+(const interval<T, Policies>& x, const T& y)
sl@0
   137
{ return y + x; }
sl@0
   138
sl@0
   139
template<class T, class Policies> inline
sl@0
   140
interval<T, Policies> operator-(const interval<T, Policies>& x,
sl@0
   141
                                const interval<T, Policies>& y)
sl@0
   142
{
sl@0
   143
  if (interval_lib::detail::test_input(x, y))
sl@0
   144
    return interval<T, Policies>::empty();
sl@0
   145
  typename Policies::rounding rnd;
sl@0
   146
  return interval<T,Policies>(rnd.sub_down(x.lower(), y.upper()),
sl@0
   147
                              rnd.sub_up  (x.upper(), y.lower()), true);
sl@0
   148
}
sl@0
   149
sl@0
   150
template<class T, class Policies> inline
sl@0
   151
interval<T, Policies> operator-(const T& x, const interval<T, Policies>& y)
sl@0
   152
{
sl@0
   153
  if (interval_lib::detail::test_input(x, y))
sl@0
   154
    return interval<T, Policies>::empty();
sl@0
   155
  typename Policies::rounding rnd;
sl@0
   156
  return interval<T,Policies>(rnd.sub_down(x, y.upper()),
sl@0
   157
                              rnd.sub_up  (x, y.lower()), true);
sl@0
   158
}
sl@0
   159
sl@0
   160
template<class T, class Policies> inline
sl@0
   161
interval<T, Policies> operator-(const interval<T, Policies>& x, const T& y)
sl@0
   162
{
sl@0
   163
  if (interval_lib::detail::test_input(x, y))
sl@0
   164
    return interval<T, Policies>::empty();
sl@0
   165
  typename Policies::rounding rnd;
sl@0
   166
  return interval<T,Policies>(rnd.sub_down(x.lower(), y),
sl@0
   167
                              rnd.sub_up  (x.upper(), y), true);
sl@0
   168
}
sl@0
   169
sl@0
   170
template<class T, class Policies> inline
sl@0
   171
interval<T, Policies> operator*(const interval<T, Policies>& x,
sl@0
   172
                                const interval<T, Policies>& y)
sl@0
   173
{
sl@0
   174
  BOOST_USING_STD_MIN();
sl@0
   175
  BOOST_USING_STD_MAX();
sl@0
   176
  typedef interval<T, Policies> I;
sl@0
   177
  if (interval_lib::detail::test_input(x, y))
sl@0
   178
    return I::empty();
sl@0
   179
  typename Policies::rounding rnd;
sl@0
   180
  const T& xl = x.lower();
sl@0
   181
  const T& xu = x.upper();
sl@0
   182
  const T& yl = y.lower();
sl@0
   183
  const T& yu = y.upper();
sl@0
   184
sl@0
   185
  if (interval_lib::user::is_neg(xl))
sl@0
   186
    if (interval_lib::user::is_pos(xu))
sl@0
   187
      if (interval_lib::user::is_neg(yl))
sl@0
   188
        if (interval_lib::user::is_pos(yu)) // M * M
sl@0
   189
          return I(min BOOST_PREVENT_MACRO_SUBSTITUTION(rnd.mul_down(xl, yu), rnd.mul_down(xu, yl)),
sl@0
   190
                   max BOOST_PREVENT_MACRO_SUBSTITUTION(rnd.mul_up  (xl, yl), rnd.mul_up  (xu, yu)), true);
sl@0
   191
        else                    // M * N
sl@0
   192
          return I(rnd.mul_down(xu, yl), rnd.mul_up(xl, yl), true);
sl@0
   193
      else
sl@0
   194
        if (interval_lib::user::is_pos(yu)) // M * P
sl@0
   195
          return I(rnd.mul_down(xl, yu), rnd.mul_up(xu, yu), true);
sl@0
   196
        else                    // M * Z
sl@0
   197
          return I(static_cast<T>(0), static_cast<T>(0), true);
sl@0
   198
    else
sl@0
   199
      if (interval_lib::user::is_neg(yl))
sl@0
   200
        if (interval_lib::user::is_pos(yu)) // N * M
sl@0
   201
          return I(rnd.mul_down(xl, yu), rnd.mul_up(xl, yl), true);
sl@0
   202
        else                    // N * N
sl@0
   203
          return I(rnd.mul_down(xu, yu), rnd.mul_up(xl, yl), true);
sl@0
   204
      else
sl@0
   205
        if (interval_lib::user::is_pos(yu)) // N * P
sl@0
   206
          return I(rnd.mul_down(xl, yu), rnd.mul_up(xu, yl), true);
sl@0
   207
        else                    // N * Z
sl@0
   208
          return I(static_cast<T>(0), static_cast<T>(0), true);
sl@0
   209
  else
sl@0
   210
    if (interval_lib::user::is_pos(xu))
sl@0
   211
      if (interval_lib::user::is_neg(yl))
sl@0
   212
        if (interval_lib::user::is_pos(yu)) // P * M
sl@0
   213
          return I(rnd.mul_down(xu, yl), rnd.mul_up(xu, yu), true);
sl@0
   214
        else                    // P * N
sl@0
   215
          return I(rnd.mul_down(xu, yl), rnd.mul_up(xl, yu), true);
sl@0
   216
      else
sl@0
   217
        if (interval_lib::user::is_pos(yu)) // P * P
sl@0
   218
          return I(rnd.mul_down(xl, yl), rnd.mul_up(xu, yu), true);
sl@0
   219
        else                    // P * Z
sl@0
   220
          return I(static_cast<T>(0), static_cast<T>(0), true);
sl@0
   221
    else                        // Z * ?
sl@0
   222
      return I(static_cast<T>(0), static_cast<T>(0), true);
sl@0
   223
}
sl@0
   224
sl@0
   225
template<class T, class Policies> inline
sl@0
   226
interval<T, Policies> operator*(const T& x, const interval<T, Policies>& y)
sl@0
   227
{ 
sl@0
   228
  typedef interval<T, Policies> I;
sl@0
   229
  if (interval_lib::detail::test_input(x, y))
sl@0
   230
    return I::empty();
sl@0
   231
  typename Policies::rounding rnd;
sl@0
   232
  const T& yl = y.lower();
sl@0
   233
  const T& yu = y.upper();
sl@0
   234
  // x is supposed not to be infinite
sl@0
   235
  if (interval_lib::user::is_neg(x))
sl@0
   236
    return I(rnd.mul_down(x, yu), rnd.mul_up(x, yl), true);
sl@0
   237
  else if (interval_lib::user::is_zero(x))
sl@0
   238
    return I(static_cast<T>(0), static_cast<T>(0), true);
sl@0
   239
  else
sl@0
   240
    return I(rnd.mul_down(x, yl), rnd.mul_up(x, yu), true);
sl@0
   241
}
sl@0
   242
sl@0
   243
template<class T, class Policies> inline
sl@0
   244
interval<T, Policies> operator*(const interval<T, Policies>& x, const T& y)
sl@0
   245
{ return y * x; }
sl@0
   246
sl@0
   247
template<class T, class Policies> inline
sl@0
   248
interval<T, Policies> operator/(const interval<T, Policies>& x,
sl@0
   249
                                const interval<T, Policies>& y)
sl@0
   250
{
sl@0
   251
  if (interval_lib::detail::test_input(x, y))
sl@0
   252
    return interval<T, Policies>::empty();
sl@0
   253
  if (zero_in(y))
sl@0
   254
    if (!interval_lib::user::is_zero(y.lower()))
sl@0
   255
      if (!interval_lib::user::is_zero(y.upper()))
sl@0
   256
        return interval_lib::detail::div_zero(x);
sl@0
   257
      else
sl@0
   258
        return interval_lib::detail::div_negative(x, y.lower());
sl@0
   259
    else
sl@0
   260
      if (!interval_lib::user::is_zero(y.upper()))
sl@0
   261
        return interval_lib::detail::div_positive(x, y.upper());
sl@0
   262
      else
sl@0
   263
        return interval<T, Policies>::empty();
sl@0
   264
  else
sl@0
   265
    return interval_lib::detail::div_non_zero(x, y);
sl@0
   266
}
sl@0
   267
sl@0
   268
template<class T, class Policies> inline
sl@0
   269
interval<T, Policies> operator/(const T& x, const interval<T, Policies>& y)
sl@0
   270
{
sl@0
   271
  if (interval_lib::detail::test_input(x, y))
sl@0
   272
    return interval<T, Policies>::empty();
sl@0
   273
  if (zero_in(y))
sl@0
   274
    if (!interval_lib::user::is_zero(y.lower()))
sl@0
   275
      if (!interval_lib::user::is_zero(y.upper()))
sl@0
   276
        return interval_lib::detail::div_zero<T, Policies>(x);
sl@0
   277
      else
sl@0
   278
        return interval_lib::detail::div_negative<T, Policies>(x, y.lower());
sl@0
   279
    else
sl@0
   280
      if (!interval_lib::user::is_zero(y.upper()))
sl@0
   281
        return interval_lib::detail::div_positive<T, Policies>(x, y.upper());
sl@0
   282
      else
sl@0
   283
        return interval<T, Policies>::empty();
sl@0
   284
  else
sl@0
   285
    return interval_lib::detail::div_non_zero(x, y);
sl@0
   286
}
sl@0
   287
sl@0
   288
template<class T, class Policies> inline
sl@0
   289
interval<T, Policies> operator/(const interval<T, Policies>& x, const T& y)
sl@0
   290
{
sl@0
   291
  if (interval_lib::detail::test_input(x, y) || interval_lib::user::is_zero(y))
sl@0
   292
    return interval<T, Policies>::empty();
sl@0
   293
  typename Policies::rounding rnd;
sl@0
   294
  const T& xl = x.lower();
sl@0
   295
  const T& xu = x.upper();
sl@0
   296
  if (interval_lib::user::is_neg(y))
sl@0
   297
    return interval<T, Policies>(rnd.div_down(xu, y), rnd.div_up(xl, y), true);
sl@0
   298
  else
sl@0
   299
    return interval<T, Policies>(rnd.div_down(xl, y), rnd.div_up(xu, y), true);
sl@0
   300
}
sl@0
   301
sl@0
   302
} // namespace numeric
sl@0
   303
} // namespace boost
sl@0
   304
sl@0
   305
#endif // BOOST_NUMERIC_INTERVAL_ARITH_HPP