1 // Boost.Units - A C++ library for zero-overhead dimensional analysis and
2 // unit/quantity manipulation and conversion
4 // Copyright (C) 2003-2008 Matthias Christian Schabel
5 // Copyright (C) 2007-2008 Steven Watanabe
7 // Distributed under the Boost Software License, Version 1.0. (See
8 // accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
11 #ifndef BOOST_UNITS_CMATH_HPP
12 #define BOOST_UNITS_CMATH_HPP
14 #include <boost/config/no_tr1/cmath.hpp>
17 #include <boost/math/special_functions/fpclassify.hpp>
18 #include <boost/math/special_functions/hypot.hpp>
19 #include <boost/math/special_functions/next.hpp>
20 #include <boost/math/special_functions/round.hpp>
21 #include <boost/math/special_functions/sign.hpp>
23 #include <boost/units/dimensionless_quantity.hpp>
24 #include <boost/units/pow.hpp>
25 #include <boost/units/quantity.hpp>
26 #include <boost/units/detail/cmath_impl.hpp>
28 #include <boost/units/systems/si/plane_angle.hpp>
31 /// \brief Overloads of functions in \<cmath\> for quantities
33 /// \detailed Only functions for which a dimensionally-correct result type
34 /// can be determined are overloaded. All functions work with dimensionless
37 // BOOST_PREVENT_MACRO_SUBSTITUTION is needed on certain compilers that define
38 // some <cmath> functions as macros; it is used for all functions even though it
39 // isn't necessary -- I didn't want to think :)
41 // the form using namespace detail; return(f(x)); is used
42 // to enable ADL for UDTs
48 template<class Unit
,class Y
>
51 isfinite
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
53 using boost::math::isfinite
;
54 return isfinite
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value());
57 template<class Unit
,class Y
>
60 isinf
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
62 using boost::math::isinf
;
63 return isinf
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value());
66 template<class Unit
,class Y
>
69 isnan
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
71 using boost::math::isnan
;
72 return isnan
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value());
75 template<class Unit
,class Y
>
78 isnormal
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
80 using boost::math::isnormal
;
81 return isnormal
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value());
84 template<class Unit
,class Y
>
87 isgreater
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q1
,
88 const quantity
<Unit
,Y
>& q2
)
90 using namespace detail
;
91 return isgreater
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value());
94 template<class Unit
,class Y
>
97 isgreaterequal
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q1
,
98 const quantity
<Unit
,Y
>& q2
)
100 using namespace detail
;
101 return isgreaterequal
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value());
104 template<class Unit
,class Y
>
107 isless
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q1
,
108 const quantity
<Unit
,Y
>& q2
)
110 using namespace detail
;
111 return isless
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value());
114 template<class Unit
,class Y
>
117 islessequal
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q1
,
118 const quantity
<Unit
,Y
>& q2
)
120 using namespace detail
;
121 return islessequal
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value());
124 template<class Unit
,class Y
>
127 islessgreater
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q1
,
128 const quantity
<Unit
,Y
>& q2
)
130 using namespace detail
;
131 return islessgreater
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value());
134 template<class Unit
,class Y
>
137 isunordered
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q1
,
138 const quantity
<Unit
,Y
>& q2
)
140 using namespace detail
;
141 return isunordered
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value());
144 template<class Unit
,class Y
>
147 abs
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
151 typedef quantity
<Unit
,Y
> quantity_type
;
153 return quantity_type::from_value(abs
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value()));
156 template<class Unit
,class Y
>
159 ceil
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
163 typedef quantity
<Unit
,Y
> quantity_type
;
165 return quantity_type::from_value(ceil
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value()));
168 template<class Unit
,class Y
>
171 copysign
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q1
,
172 const quantity
<Unit
,Y
>& q2
)
174 using boost::math::copysign
;
176 typedef quantity
<Unit
,Y
> quantity_type
;
178 return quantity_type::from_value(copysign
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value()));
181 template<class Unit
,class Y
>
184 fabs
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
188 typedef quantity
<Unit
,Y
> quantity_type
;
190 return quantity_type::from_value(fabs
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value()));
193 template<class Unit
,class Y
>
196 floor
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
200 typedef quantity
<Unit
,Y
> quantity_type
;
202 return quantity_type::from_value(floor
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value()));
205 template<class Unit
,class Y
>
208 fdim
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q1
,
209 const quantity
<Unit
,Y
>& q2
)
211 using namespace detail
;
213 typedef quantity
<Unit
,Y
> quantity_type
;
215 return quantity_type::from_value(fdim
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value()));
220 template<class Unit1
,class Unit2
,class Unit3
,class Y
>
222 typename add_typeof_helper
<
223 typename multiply_typeof_helper
<quantity
<Unit1
,Y
>,
224 quantity
<Unit2
,Y
> >::type
,
225 quantity
<Unit3
,Y
> >::type
226 fma
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit1
,Y
>& q1
,
227 const quantity
<Unit2
,Y
>& q2
,
228 const quantity
<Unit3
,Y
>& q3
)
230 using namespace detail
;
232 typedef quantity
<Unit1
,Y
> type1
;
233 typedef quantity
<Unit2
,Y
> type2
;
234 typedef quantity
<Unit3
,Y
> type3
;
236 typedef typename multiply_typeof_helper
<type1
,type2
>::type prod_type
;
237 typedef typename add_typeof_helper
<prod_type
,type3
>::type quantity_type
;
239 return quantity_type::from_value(fma
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value(),q3
.value()));
244 template<class Unit
,class Y
>
247 fmax
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q1
,
248 const quantity
<Unit
,Y
>& q2
)
250 using namespace detail
;
252 typedef quantity
<Unit
,Y
> quantity_type
;
254 return quantity_type::from_value(fmax
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value()));
257 template<class Unit
,class Y
>
260 fmin
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q1
,
261 const quantity
<Unit
,Y
>& q2
)
263 using namespace detail
;
265 typedef quantity
<Unit
,Y
> quantity_type
;
267 return quantity_type::from_value(fmin
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value()));
270 template<class Unit
,class Y
>
273 fpclassify
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
275 using boost::math::fpclassify
;
277 return fpclassify
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value());
280 template<class Unit
,class Y
>
282 typename root_typeof_helper
<
283 typename add_typeof_helper
<
284 typename power_typeof_helper
<quantity
<Unit
,Y
>,
285 static_rational
<2> >::type
,
286 typename power_typeof_helper
<quantity
<Unit
,Y
>,
287 static_rational
<2> >::type
>::type
,
288 static_rational
<2> >::type
289 hypot
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q1
,const quantity
<Unit
,Y
>& q2
)
291 using boost::math::hypot
;
293 typedef quantity
<Unit
,Y
> type1
;
295 typedef typename power_typeof_helper
<type1
,static_rational
<2> >::type pow_type
;
296 typedef typename add_typeof_helper
<pow_type
,pow_type
>::type add_type
;
297 typedef typename root_typeof_helper
<add_type
,static_rational
<2> >::type quantity_type
;
299 return quantity_type::from_value(hypot
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value()));
302 // does ISO C++ support long long? g++ claims not
303 //template<class Unit,class Y>
305 //quantity<Unit,long long>
306 //llrint BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
308 // using namespace detail;
310 // typedef quantity<Unit,long long> quantity_type;
312 // return quantity_type::from_value(llrint BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
315 // does ISO C++ support long long? g++ claims not
316 //template<class Unit,class Y>
318 //quantity<Unit,long long>
319 //llround BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
321 // using namespace detail;
323 // typedef quantity<Unit,long long> quantity_type;
325 // return quantity_type::from_value(llround BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
330 template<class Unit
,class Y
>
333 nearbyint
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
335 using namespace detail
;
337 typedef quantity
<Unit
,Y
> quantity_type
;
339 return quantity_type::from_value(nearbyint
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value()));
344 template<class Unit
,class Y
>
346 quantity
<Unit
,Y
> nextafter
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q1
,
347 const quantity
<Unit
,Y
>& q2
)
349 using boost::math::nextafter
;
351 typedef quantity
<Unit
,Y
> quantity_type
;
353 return quantity_type::from_value(nextafter
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value()));
355 template<class Unit
,class Y
>
357 quantity
<Unit
,Y
> nexttoward
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q1
,
358 const quantity
<Unit
,Y
>& q2
)
360 // the only difference between nextafter and nexttowards is
361 // in the argument types. Since we are requiring identical
362 // argument types, there is no difference.
363 using boost::math::nextafter
;
365 typedef quantity
<Unit
,Y
> quantity_type
;
367 return quantity_type::from_value(nextafter
BOOST_PREVENT_MACRO_SUBSTITUTION (q1
.value(),q2
.value()));
372 template<class Unit
,class Y
>
375 rint
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
377 using namespace detail
;
379 typedef quantity
<Unit
,Y
> quantity_type
;
381 return quantity_type::from_value(rint
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value()));
386 template<class Unit
,class Y
>
389 round
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
391 using boost::math::round
;
393 typedef quantity
<Unit
,Y
> quantity_type
;
395 return quantity_type::from_value(round
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value()));
398 template<class Unit
,class Y
>
401 signbit
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
403 using boost::math::signbit
;
405 return signbit
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value());
408 template<class Unit
,class Y
>
411 trunc
BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity
<Unit
,Y
>& q
)
413 using namespace detail
;
415 typedef quantity
<Unit
,Y
> quantity_type
;
417 return quantity_type::from_value(trunc
BOOST_PREVENT_MACRO_SUBSTITUTION (q
.value()));
420 template<class Unit
,class Y
>
423 fmod(const quantity
<Unit
,Y
>& q1
, const quantity
<Unit
,Y
>& q2
)
427 typedef quantity
<Unit
,Y
> quantity_type
;
429 return quantity_type::from_value(fmod(q1
.value(), q2
.value()));
432 template<class Unit
, class Y
>
435 modf(const quantity
<Unit
, Y
>& q1
, quantity
<Unit
, Y
>* q2
)
439 typedef quantity
<Unit
,Y
> quantity_type
;
441 return quantity_type::from_value(modf(q1
.value(), &quantity_cast
<Y
&>(*q2
)));
444 template<class Unit
, class Y
, class Int
>
447 frexp(const quantity
<Unit
, Y
>& q
,Int
* ex
)
451 typedef quantity
<Unit
,Y
> quantity_type
;
453 return quantity_type::from_value(frexp(q
.value(),ex
));
456 /// For non-dimensionless quantities, integral and rational powers
457 /// and roots can be computed by @c pow<Ex> and @c root<Rt> respectively.
458 template<class S
, class Y
>
460 quantity
<BOOST_UNITS_DIMENSIONLESS_UNIT(S
), Y
>
461 pow(const quantity
<BOOST_UNITS_DIMENSIONLESS_UNIT(S
), Y
>& q1
,
462 const quantity
<BOOST_UNITS_DIMENSIONLESS_UNIT(S
), Y
>& q2
)
466 typedef quantity
<BOOST_UNITS_DIMENSIONLESS_UNIT(S
),Y
> quantity_type
;
468 return quantity_type::from_value(pow(q1
.value(), q2
.value()));
471 template<class S
, class Y
>
473 quantity
<BOOST_UNITS_DIMENSIONLESS_UNIT(S
), Y
>
474 exp(const quantity
<BOOST_UNITS_DIMENSIONLESS_UNIT(S
), Y
>& q
)
478 typedef quantity
<BOOST_UNITS_DIMENSIONLESS_UNIT(S
), Y
> quantity_type
;
480 return quantity_type::from_value(exp(q
.value()));
483 template<class Unit
, class Y
, class Int
>
486 ldexp(const quantity
<Unit
, Y
>& q
,const Int
& ex
)
490 typedef quantity
<Unit
,Y
> quantity_type
;
492 return quantity_type::from_value(ldexp(q
.value(), ex
));
495 template<class S
, class Y
>
497 quantity
<BOOST_UNITS_DIMENSIONLESS_UNIT(S
), Y
>
498 log(const quantity
<BOOST_UNITS_DIMENSIONLESS_UNIT(S
), Y
>& q
)
502 typedef quantity
<BOOST_UNITS_DIMENSIONLESS_UNIT(S
), Y
> quantity_type
;
504 return quantity_type::from_value(log(q
.value()));
507 template<class S
, class Y
>
509 quantity
<BOOST_UNITS_DIMENSIONLESS_UNIT(S
), Y
>
510 log10(const quantity
<BOOST_UNITS_DIMENSIONLESS_UNIT(S
), Y
>& q
)
514 typedef quantity
<BOOST_UNITS_DIMENSIONLESS_UNIT(S
), Y
> quantity_type
;
516 return quantity_type::from_value(log10(q
.value()));
519 template<class Unit
,class Y
>
521 typename root_typeof_helper
<
525 sqrt(const quantity
<Unit
,Y
>& q
)
529 typedef typename root_typeof_helper
<
532 >::type quantity_type
;
534 return quantity_type::from_value(sqrt(q
.value()));
545 // trig functions with si argument/return types
547 /// cos of theta in radians
549 typename dimensionless_quantity
<si::system
,Y
>::type
550 cos(const quantity
<si::plane_angle
,Y
>& theta
)
553 return cos(theta
.value());
556 /// sin of theta in radians
558 typename dimensionless_quantity
<si::system
,Y
>::type
559 sin(const quantity
<si::plane_angle
,Y
>& theta
)
562 return sin(theta
.value());
565 /// tan of theta in radians
567 typename dimensionless_quantity
<si::system
,Y
>::type
568 tan(const quantity
<si::plane_angle
,Y
>& theta
)
571 return tan(theta
.value());
574 /// cos of theta in other angular units
575 template<class System
,class Y
>
576 typename dimensionless_quantity
<System
,Y
>::type
577 cos(const quantity
<unit
<plane_angle_dimension
,System
>,Y
>& theta
)
579 return cos(quantity
<si::plane_angle
,Y
>(theta
));
582 /// sin of theta in other angular units
583 template<class System
,class Y
>
584 typename dimensionless_quantity
<System
,Y
>::type
585 sin(const quantity
<unit
<plane_angle_dimension
,System
>,Y
>& theta
)
587 return sin(quantity
<si::plane_angle
,Y
>(theta
));
590 /// tan of theta in other angular units
591 template<class System
,class Y
>
592 typename dimensionless_quantity
<System
,Y
>::type
593 tan(const quantity
<unit
<plane_angle_dimension
,System
>,Y
>& theta
)
595 return tan(quantity
<si::plane_angle
,Y
>(theta
));
598 /// acos of dimensionless quantity returning angle in same system
599 template<class Y
,class System
>
600 quantity
<unit
<plane_angle_dimension
, homogeneous_system
<System
> >,Y
>
601 acos(const quantity
<unit
<dimensionless_type
, homogeneous_system
<System
> >,Y
>& val
)
604 return quantity
<unit
<plane_angle_dimension
, homogeneous_system
<System
> >,Y
>(acos(val
.value())*si::radians
);
607 /// asin of dimensionless quantity returning angle in same system
608 template<class Y
,class System
>
609 quantity
<unit
<plane_angle_dimension
, homogeneous_system
<System
> >,Y
>
610 asin(const quantity
<unit
<dimensionless_type
, homogeneous_system
<System
> >,Y
>& val
)
613 return quantity
<unit
<plane_angle_dimension
, homogeneous_system
<System
> >,Y
>(asin(val
.value())*si::radians
);
616 /// atan of dimensionless quantity returning angle in same system
617 template<class Y
,class System
>
618 quantity
<unit
<plane_angle_dimension
, homogeneous_system
<System
> >,Y
>
619 atan(const quantity
<unit
<dimensionless_type
, homogeneous_system
<System
> >, Y
>& val
)
622 return quantity
<unit
<plane_angle_dimension
, homogeneous_system
<System
> >,Y
>(atan(val
.value())*si::radians
);
625 /// atan2 of @c value_type returning angle in radians
626 template<class Y
, class System
>
627 quantity
<unit
<plane_angle_dimension
, homogeneous_system
<System
> >, Y
>
628 atan2(const quantity
<unit
<dimensionless_type
, homogeneous_system
<System
> >, Y
>& y
,
629 const quantity
<unit
<dimensionless_type
, homogeneous_system
<System
> >, Y
>& x
)
632 return quantity
<unit
<plane_angle_dimension
, homogeneous_system
<System
> >, Y
>(atan2(y
.value(),x
.value())*si::radians
);
639 #endif // BOOST_UNITS_CMATH_HPP