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>
27 #include <boost/units/detail/dimensionless_unit.hpp>
29 #include <boost/units/systems/si/plane_angle.hpp>
32 /// \brief Overloads of functions in \<cmath\> for quantities.
33 /// \details Only functions for which a dimensionally-correct result type
34 /// can be determined are overloaded.
35 /// All functions work with dimensionless quantities.
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>
52 isfinite BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
54 using boost::math::isfinite;
55 return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION (q.value());
58 template<class Unit,class Y>
62 isinf BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
64 using boost::math::isinf;
65 return isinf BOOST_PREVENT_MACRO_SUBSTITUTION (q.value());
68 template<class Unit,class Y>
72 isnan BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
74 using boost::math::isnan;
75 return isnan BOOST_PREVENT_MACRO_SUBSTITUTION (q.value());
78 template<class Unit,class Y>
82 isnormal BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
84 using boost::math::isnormal;
85 return isnormal BOOST_PREVENT_MACRO_SUBSTITUTION (q.value());
88 template<class Unit,class Y>
92 isgreater BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
93 const quantity<Unit,Y>& q2)
95 using namespace detail;
96 return isgreater BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value());
99 template<class Unit,class Y>
103 isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
104 const quantity<Unit,Y>& q2)
106 using namespace detail;
107 return isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value());
110 template<class Unit,class Y>
114 isless BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
115 const quantity<Unit,Y>& q2)
117 using namespace detail;
118 return isless BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value());
121 template<class Unit,class Y>
125 islessequal BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
126 const quantity<Unit,Y>& q2)
128 using namespace detail;
129 return islessequal BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value());
132 template<class Unit,class Y>
136 islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
137 const quantity<Unit,Y>& q2)
139 using namespace detail;
140 return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value());
143 template<class Unit,class Y>
147 isunordered BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
148 const quantity<Unit,Y>& q2)
150 using namespace detail;
151 return isunordered BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value());
154 template<class Unit,class Y>
158 abs BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
162 typedef quantity<Unit,Y> quantity_type;
164 return quantity_type::from_value(abs BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
167 template<class Unit,class Y>
171 ceil BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
175 typedef quantity<Unit,Y> quantity_type;
177 return quantity_type::from_value(ceil BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
180 template<class Unit,class Y>
184 copysign BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
185 const quantity<Unit,Y>& q2)
187 using boost::math::copysign;
189 typedef quantity<Unit,Y> quantity_type;
191 return quantity_type::from_value(copysign BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
194 template<class Unit,class Y>
198 fabs BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
202 typedef quantity<Unit,Y> quantity_type;
204 return quantity_type::from_value(fabs BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
207 template<class Unit,class Y>
211 floor BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
215 typedef quantity<Unit,Y> quantity_type;
217 return quantity_type::from_value(floor BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
220 template<class Unit,class Y>
224 fdim BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
225 const quantity<Unit,Y>& q2)
227 using namespace detail;
229 typedef quantity<Unit,Y> quantity_type;
231 return quantity_type::from_value(fdim BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
236 template<class Unit1,class Unit2,class Unit3,class Y>
239 typename add_typeof_helper<
240 typename multiply_typeof_helper<quantity<Unit1,Y>,
241 quantity<Unit2,Y> >::type,
242 quantity<Unit3,Y> >::type
243 fma BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit1,Y>& q1,
244 const quantity<Unit2,Y>& q2,
245 const quantity<Unit3,Y>& q3)
247 using namespace detail;
249 typedef quantity<Unit1,Y> type1;
250 typedef quantity<Unit2,Y> type2;
251 typedef quantity<Unit3,Y> type3;
253 typedef typename multiply_typeof_helper<type1,type2>::type prod_type;
254 typedef typename add_typeof_helper<prod_type,type3>::type quantity_type;
256 return quantity_type::from_value(fma BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value(),q3.value()));
261 template<class Unit,class Y>
265 fmax BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
266 const quantity<Unit,Y>& q2)
268 using namespace detail;
270 typedef quantity<Unit,Y> quantity_type;
272 return quantity_type::from_value(fmax BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
275 template<class Unit,class Y>
279 fmin BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
280 const quantity<Unit,Y>& q2)
282 using namespace detail;
284 typedef quantity<Unit,Y> quantity_type;
286 return quantity_type::from_value(fmin BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
289 template<class Unit,class Y>
293 fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
295 using boost::math::fpclassify;
297 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION (q.value());
300 template<class Unit,class Y>
303 typename root_typeof_helper<
304 typename add_typeof_helper<
305 typename power_typeof_helper<quantity<Unit,Y>,
306 static_rational<2> >::type,
307 typename power_typeof_helper<quantity<Unit,Y>,
308 static_rational<2> >::type>::type,
309 static_rational<2> >::type
310 hypot BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,const quantity<Unit,Y>& q2)
312 using boost::math::hypot;
314 typedef quantity<Unit,Y> type1;
316 typedef typename power_typeof_helper<type1,static_rational<2> >::type pow_type;
317 typedef typename add_typeof_helper<pow_type,pow_type>::type add_type;
318 typedef typename root_typeof_helper<add_type,static_rational<2> >::type quantity_type;
320 return quantity_type::from_value(hypot BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
323 // does ISO C++ support long long? g++ claims not
324 //template<class Unit,class Y>
327 //quantity<Unit,long long>
328 //llrint BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
330 // using namespace detail;
332 // typedef quantity<Unit,long long> quantity_type;
334 // return quantity_type::from_value(llrint BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
337 // does ISO C++ support long long? g++ claims not
338 //template<class Unit,class Y>
341 //quantity<Unit,long long>
342 //llround BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
344 // using namespace detail;
346 // typedef quantity<Unit,long long> quantity_type;
348 // return quantity_type::from_value(llround BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
353 template<class Unit,class Y>
357 nearbyint BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
359 using namespace detail;
361 typedef quantity<Unit,Y> quantity_type;
363 return quantity_type::from_value(nearbyint BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
368 template<class Unit,class Y>
371 quantity<Unit,Y> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
372 const quantity<Unit,Y>& q2)
374 using boost::math::nextafter;
376 typedef quantity<Unit,Y> quantity_type;
378 return quantity_type::from_value(nextafter BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
380 template<class Unit,class Y>
383 quantity<Unit,Y> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
384 const quantity<Unit,Y>& q2)
386 // the only difference between nextafter and nexttowards is
387 // in the argument types. Since we are requiring identical
388 // argument types, there is no difference.
389 using boost::math::nextafter;
391 typedef quantity<Unit,Y> quantity_type;
393 return quantity_type::from_value(nextafter BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
398 template<class Unit,class Y>
402 rint BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
404 using namespace detail;
406 typedef quantity<Unit,Y> quantity_type;
408 return quantity_type::from_value(rint BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
413 template<class Unit,class Y>
417 round BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
419 using boost::math::round;
421 typedef quantity<Unit,Y> quantity_type;
423 return quantity_type::from_value(round BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
426 template<class Unit,class Y>
430 signbit BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
432 using boost::math::signbit;
434 return signbit BOOST_PREVENT_MACRO_SUBSTITUTION (q.value());
437 template<class Unit,class Y>
441 trunc BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
443 using namespace detail;
445 typedef quantity<Unit,Y> quantity_type;
447 return quantity_type::from_value(trunc BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
450 template<class Unit,class Y>
454 fmod(const quantity<Unit,Y>& q1, const quantity<Unit,Y>& q2)
458 typedef quantity<Unit,Y> quantity_type;
460 return quantity_type::from_value(fmod(q1.value(), q2.value()));
463 template<class Unit, class Y>
467 modf(const quantity<Unit, Y>& q1, quantity<Unit, Y>* q2)
471 typedef quantity<Unit,Y> quantity_type;
473 return quantity_type::from_value(modf(q1.value(), &quantity_cast<Y&>(*q2)));
476 template<class Unit, class Y, class Int>
480 frexp(const quantity<Unit, Y>& q,Int* ex)
484 typedef quantity<Unit,Y> quantity_type;
486 return quantity_type::from_value(frexp(q.value(),ex));
489 /// For non-dimensionless quantities, integral and rational powers
490 /// and roots can be computed by @c pow<Ex> and @c root<Rt> respectively.
491 template<class S, class Y>
494 quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>
495 pow(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>& q1,
496 const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>& q2)
500 typedef quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S),Y> quantity_type;
502 return quantity_type::from_value(pow(q1.value(), q2.value()));
505 template<class S, class Y>
508 quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>
509 exp(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>& q)
513 typedef quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y> quantity_type;
515 return quantity_type::from_value(exp(q.value()));
518 template<class Unit, class Y, class Int>
522 ldexp(const quantity<Unit, Y>& q,const Int& ex)
526 typedef quantity<Unit,Y> quantity_type;
528 return quantity_type::from_value(ldexp(q.value(), ex));
531 template<class S, class Y>
534 quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>
535 log(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>& q)
539 typedef quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y> quantity_type;
541 return quantity_type::from_value(log(q.value()));
544 template<class S, class Y>
547 quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>
548 log10(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>& q)
552 typedef quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y> quantity_type;
554 return quantity_type::from_value(log10(q.value()));
557 template<class Unit,class Y>
560 typename root_typeof_helper<
564 sqrt(const quantity<Unit,Y>& q)
568 typedef typename root_typeof_helper<
571 >::type quantity_type;
573 return quantity_type::from_value(sqrt(q.value()));
584 // trig functions with si argument/return types
586 /// cos of theta in radians
589 typename dimensionless_quantity<si::system,Y>::type
590 cos(const quantity<si::plane_angle,Y>& theta)
593 return cos(theta.value());
596 /// sin of theta in radians
599 typename dimensionless_quantity<si::system,Y>::type
600 sin(const quantity<si::plane_angle,Y>& theta)
603 return sin(theta.value());
606 /// tan of theta in radians
609 typename dimensionless_quantity<si::system,Y>::type
610 tan(const quantity<si::plane_angle,Y>& theta)
613 return tan(theta.value());
616 /// cos of theta in other angular units
617 template<class System,class Y>
619 typename dimensionless_quantity<System,Y>::type
620 cos(const quantity<unit<plane_angle_dimension,System>,Y>& theta)
622 return cos(quantity<si::plane_angle,Y>(theta));
625 /// sin of theta in other angular units
626 template<class System,class Y>
628 typename dimensionless_quantity<System,Y>::type
629 sin(const quantity<unit<plane_angle_dimension,System>,Y>& theta)
631 return sin(quantity<si::plane_angle,Y>(theta));
634 /// tan of theta in other angular units
635 template<class System,class Y>
637 typename dimensionless_quantity<System,Y>::type
638 tan(const quantity<unit<plane_angle_dimension,System>,Y>& theta)
640 return tan(quantity<si::plane_angle,Y>(theta));
643 /// acos of dimensionless quantity returning angle in same system
644 template<class Y,class System>
646 quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>
647 acos(const quantity<unit<dimensionless_type, homogeneous_system<System> >,Y>& val)
650 return quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>(acos(val.value())*si::radians);
653 /// acos of dimensionless quantity returning angle in radians
656 quantity<angle::radian_base_unit::unit_type,Y>
657 acos(const quantity<unit<dimensionless_type, heterogeneous_dimensionless_system>,Y>& val)
660 return quantity<angle::radian_base_unit::unit_type,Y>::from_value(acos(val.value()));
663 /// asin of dimensionless quantity returning angle in same system
664 template<class Y,class System>
666 quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>
667 asin(const quantity<unit<dimensionless_type, homogeneous_system<System> >,Y>& val)
670 return quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>(asin(val.value())*si::radians);
673 /// asin of dimensionless quantity returning angle in radians
676 quantity<angle::radian_base_unit::unit_type,Y>
677 asin(const quantity<unit<dimensionless_type, heterogeneous_dimensionless_system>,Y>& val)
680 return quantity<angle::radian_base_unit::unit_type,Y>::from_value(asin(val.value()));
683 /// atan of dimensionless quantity returning angle in same system
684 template<class Y,class System>
686 quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>
687 atan(const quantity<unit<dimensionless_type, homogeneous_system<System> >, Y>& val)
690 return quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>(atan(val.value())*si::radians);
693 /// atan of dimensionless quantity returning angle in radians
696 quantity<angle::radian_base_unit::unit_type,Y>
697 atan(const quantity<unit<dimensionless_type, heterogeneous_dimensionless_system>, Y>& val)
700 return quantity<angle::radian_base_unit::unit_type,Y>::from_value(atan(val.value()));
703 /// atan2 of @c value_type returning angle in radians
704 template<class Y, class Dimension, class System>
706 quantity<unit<plane_angle_dimension, homogeneous_system<System> >, Y>
707 atan2(const quantity<unit<Dimension, homogeneous_system<System> >, Y>& y,
708 const quantity<unit<Dimension, homogeneous_system<System> >, Y>& x)
711 return quantity<unit<plane_angle_dimension, homogeneous_system<System> >, Y>(atan2(y.value(),x.value())*si::radians);
714 /// atan2 of @c value_type returning angle in radians
715 template<class Y, class Dimension, class System>
717 quantity<angle::radian_base_unit::unit_type,Y>
718 atan2(const quantity<unit<Dimension, heterogeneous_system<System> >, Y>& y,
719 const quantity<unit<Dimension, heterogeneous_system<System> >, Y>& x)
722 return quantity<angle::radian_base_unit::unit_type,Y>::from_value(atan2(y.value(),x.value()));
729 #endif // BOOST_UNITS_CMATH_HPP