1// Boost.Units - A C++ library for zero-overhead dimensional analysis and
2// unit/quantity manipulation and conversion
3//
4// Copyright (C) 2003-2008 Matthias Christian Schabel
5// Copyright (C) 2007-2008 Steven Watanabe
6//
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)
10
11#ifndef BOOST_UNITS_CMATH_HPP
12#define BOOST_UNITS_CMATH_HPP
13
14#include <boost/config/no_tr1/cmath.hpp>
15#include <cstdlib>
16
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>
22
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>
28
29#include <boost/units/systems/si/plane_angle.hpp>
30
31/// \file
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.
36
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 :)
40//
41// the form using namespace detail; return(f(x)); is used
42// to enable ADL for UDTs.
43
44namespace boost {
45
46namespace units {
47
48template<class Unit,class Y>
49inline
50bool
51isfinite BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
52{
53 using boost::math::isfinite;
54 return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION (q.value());
55}
56
57template<class Unit,class Y>
58inline
59bool
60isinf BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
61{
62 using boost::math::isinf;
63 return isinf BOOST_PREVENT_MACRO_SUBSTITUTION (q.value());
64}
65
66template<class Unit,class Y>
67inline
68bool
69isnan BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
70{
71 using boost::math::isnan;
72 return isnan BOOST_PREVENT_MACRO_SUBSTITUTION (q.value());
73}
74
75template<class Unit,class Y>
76inline
77bool
78isnormal BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
79{
80 using boost::math::isnormal;
81 return isnormal BOOST_PREVENT_MACRO_SUBSTITUTION (q.value());
82}
83
84template<class Unit,class Y>
85inline
86bool
87isgreater BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
88 const quantity<Unit,Y>& q2)
89{
90 using namespace detail;
91 return isgreater BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value());
92}
93
94template<class Unit,class Y>
95inline
96bool
97isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
98 const quantity<Unit,Y>& q2)
99{
100 using namespace detail;
101 return isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value());
102}
103
104template<class Unit,class Y>
105inline
106bool
107isless BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
108 const quantity<Unit,Y>& q2)
109{
110 using namespace detail;
111 return isless BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value());
112}
113
114template<class Unit,class Y>
115inline
116bool
117islessequal BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
118 const quantity<Unit,Y>& q2)
119{
120 using namespace detail;
121 return islessequal BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value());
122}
123
124template<class Unit,class Y>
125inline
126bool
127islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
128 const quantity<Unit,Y>& q2)
129{
130 using namespace detail;
131 return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value());
132}
133
134template<class Unit,class Y>
135inline
136bool
137isunordered BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
138 const quantity<Unit,Y>& q2)
139{
140 using namespace detail;
141 return isunordered BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value());
142}
143
144template<class Unit,class Y>
145inline
146quantity<Unit,Y>
147abs BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
148{
149 using std::abs;
150
151 typedef quantity<Unit,Y> quantity_type;
152
153 return quantity_type::from_value(abs BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
154}
155
156template<class Unit,class Y>
157inline
158quantity<Unit,Y>
159ceil BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
160{
161 using std::ceil;
162
163 typedef quantity<Unit,Y> quantity_type;
164
165 return quantity_type::from_value(ceil BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
166}
167
168template<class Unit,class Y>
169inline
170quantity<Unit,Y>
171copysign BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
172 const quantity<Unit,Y>& q2)
173{
174 using boost::math::copysign;
175
176 typedef quantity<Unit,Y> quantity_type;
177
178 return quantity_type::from_value(copysign BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
179}
180
181template<class Unit,class Y>
182inline
183quantity<Unit,Y>
184fabs BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
185{
186 using std::fabs;
187
188 typedef quantity<Unit,Y> quantity_type;
189
190 return quantity_type::from_value(fabs BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
191}
192
193template<class Unit,class Y>
194inline
195quantity<Unit,Y>
196floor BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
197{
198 using std::floor;
199
200 typedef quantity<Unit,Y> quantity_type;
201
202 return quantity_type::from_value(floor BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
203}
204
205template<class Unit,class Y>
206inline
207quantity<Unit,Y>
208fdim BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
209 const quantity<Unit,Y>& q2)
210{
211 using namespace detail;
212
213 typedef quantity<Unit,Y> quantity_type;
214
215 return quantity_type::from_value(fdim BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
216}
217
218#if 0
219
220template<class Unit1,class Unit2,class Unit3,class Y>
221inline
222typename add_typeof_helper<
223 typename multiply_typeof_helper<quantity<Unit1,Y>,
224 quantity<Unit2,Y> >::type,
225 quantity<Unit3,Y> >::type
226fma BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit1,Y>& q1,
227 const quantity<Unit2,Y>& q2,
228 const quantity<Unit3,Y>& q3)
229{
230 using namespace detail;
231
232 typedef quantity<Unit1,Y> type1;
233 typedef quantity<Unit2,Y> type2;
234 typedef quantity<Unit3,Y> type3;
235
236 typedef typename multiply_typeof_helper<type1,type2>::type prod_type;
237 typedef typename add_typeof_helper<prod_type,type3>::type quantity_type;
238
239 return quantity_type::from_value(fma BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value(),q3.value()));
240}
241
242#endif
243
244template<class Unit,class Y>
245inline
246quantity<Unit,Y>
247fmax BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
248 const quantity<Unit,Y>& q2)
249{
250 using namespace detail;
251
252 typedef quantity<Unit,Y> quantity_type;
253
254 return quantity_type::from_value(fmax BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
255}
256
257template<class Unit,class Y>
258inline
259quantity<Unit,Y>
260fmin BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
261 const quantity<Unit,Y>& q2)
262{
263 using namespace detail;
264
265 typedef quantity<Unit,Y> quantity_type;
266
267 return quantity_type::from_value(fmin BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
268}
269
270template<class Unit,class Y>
271inline
272int
273fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
274{
275 using boost::math::fpclassify;
276
277 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION (q.value());
278}
279
280template<class Unit,class Y>
281inline
282typename 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
289hypot BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,const quantity<Unit,Y>& q2)
290{
291 using boost::math::hypot;
292
293 typedef quantity<Unit,Y> type1;
294
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;
298
299 return quantity_type::from_value(hypot BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
300}
301
302// does ISO C++ support long long? g++ claims not
303//template<class Unit,class Y>
304//inline
305//quantity<Unit,long long>
306//llrint BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
307//{
308// using namespace detail;
309//
310// typedef quantity<Unit,long long> quantity_type;
311//
312// return quantity_type::from_value(llrint BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
313//}
314
315// does ISO C++ support long long? g++ claims not
316//template<class Unit,class Y>
317//inline
318//quantity<Unit,long long>
319//llround BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
320//{
321// using namespace detail;
322//
323// typedef quantity<Unit,long long> quantity_type;
324//
325// return quantity_type::from_value(llround BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
326//}
327
328#if 0
329
330template<class Unit,class Y>
331inline
332quantity<Unit,Y>
333nearbyint BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
334{
335 using namespace detail;
336
337 typedef quantity<Unit,Y> quantity_type;
338
339 return quantity_type::from_value(nearbyint BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
340}
341
342#endif
343
344template<class Unit,class Y>
345inline
346quantity<Unit,Y> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
347 const quantity<Unit,Y>& q2)
348{
349 using boost::math::nextafter;
350
351 typedef quantity<Unit,Y> quantity_type;
352
353 return quantity_type::from_value(nextafter BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
354}
355template<class Unit,class Y>
356inline
357quantity<Unit,Y> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q1,
358 const quantity<Unit,Y>& q2)
359{
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;
364
365 typedef quantity<Unit,Y> quantity_type;
366
367 return quantity_type::from_value(nextafter BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()));
368}
369
370#if 0
371
372template<class Unit,class Y>
373inline
374quantity<Unit,Y>
375rint BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
376{
377 using namespace detail;
378
379 typedef quantity<Unit,Y> quantity_type;
380
381 return quantity_type::from_value(rint BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
382}
383
384#endif
385
386template<class Unit,class Y>
387inline
388quantity<Unit,Y>
389round BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
390{
391 using boost::math::round;
392
393 typedef quantity<Unit,Y> quantity_type;
394
395 return quantity_type::from_value(round BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
396}
397
398template<class Unit,class Y>
399inline
400int
401signbit BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
402{
403 using boost::math::signbit;
404
405 return signbit BOOST_PREVENT_MACRO_SUBSTITUTION (q.value());
406}
407
408template<class Unit,class Y>
409inline
410quantity<Unit,Y>
411trunc BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity<Unit,Y>& q)
412{
413 using namespace detail;
414
415 typedef quantity<Unit,Y> quantity_type;
416
417 return quantity_type::from_value(trunc BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()));
418}
419
420template<class Unit,class Y>
421inline
422quantity<Unit, Y>
423fmod(const quantity<Unit,Y>& q1, const quantity<Unit,Y>& q2)
424{
425 using std::fmod;
426
427 typedef quantity<Unit,Y> quantity_type;
428
429 return quantity_type::from_value(fmod(q1.value(), q2.value()));
430}
431
432template<class Unit, class Y>
433inline
434quantity<Unit, Y>
435modf(const quantity<Unit, Y>& q1, quantity<Unit, Y>* q2)
436{
437 using std::modf;
438
439 typedef quantity<Unit,Y> quantity_type;
440
441 return quantity_type::from_value(modf(q1.value(), &quantity_cast<Y&>(*q2)));
442}
443
444template<class Unit, class Y, class Int>
445inline
446quantity<Unit, Y>
447frexp(const quantity<Unit, Y>& q,Int* ex)
448{
449 using std::frexp;
450
451 typedef quantity<Unit,Y> quantity_type;
452
453 return quantity_type::from_value(frexp(q.value(),ex));
454}
455
456/// For non-dimensionless quantities, integral and rational powers
457/// and roots can be computed by @c pow<Ex> and @c root<Rt> respectively.
458template<class S, class Y>
459inline
460quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>
461pow(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>& q1,
462 const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>& q2)
463{
464 using std::pow;
465
466 typedef quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S),Y> quantity_type;
467
468 return quantity_type::from_value(pow(q1.value(), q2.value()));
469}
470
471template<class S, class Y>
472inline
473quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>
474exp(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>& q)
475{
476 using std::exp;
477
478 typedef quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y> quantity_type;
479
480 return quantity_type::from_value(exp(q.value()));
481}
482
483template<class Unit, class Y, class Int>
484inline
485quantity<Unit, Y>
486ldexp(const quantity<Unit, Y>& q,const Int& ex)
487{
488 using std::ldexp;
489
490 typedef quantity<Unit,Y> quantity_type;
491
492 return quantity_type::from_value(ldexp(q.value(), ex));
493}
494
495template<class S, class Y>
496inline
497quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>
498log(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>& q)
499{
500 using std::log;
501
502 typedef quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y> quantity_type;
503
504 return quantity_type::from_value(log(q.value()));
505}
506
507template<class S, class Y>
508inline
509quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>
510log10(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>& q)
511{
512 using std::log10;
513
514 typedef quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y> quantity_type;
515
516 return quantity_type::from_value(log10(q.value()));
517}
518
519template<class Unit,class Y>
520inline
521typename root_typeof_helper<
522 quantity<Unit,Y>,
523 static_rational<2>
524 >::type
525sqrt(const quantity<Unit,Y>& q)
526{
527 using std::sqrt;
528
529 typedef typename root_typeof_helper<
530 quantity<Unit,Y>,
531 static_rational<2>
532 >::type quantity_type;
533
534 return quantity_type::from_value(sqrt(q.value()));
535}
536
537} // namespace units
538
539} // namespace boost
540
541namespace boost {
542
543namespace units {
544
545// trig functions with si argument/return types
546
547/// cos of theta in radians
548template<class Y>
549typename dimensionless_quantity<si::system,Y>::type
550cos(const quantity<si::plane_angle,Y>& theta)
551{
552 using std::cos;
553 return cos(theta.value());
554}
555
556/// sin of theta in radians
557template<class Y>
558typename dimensionless_quantity<si::system,Y>::type
559sin(const quantity<si::plane_angle,Y>& theta)
560{
561 using std::sin;
562 return sin(theta.value());
563}
564
565/// tan of theta in radians
566template<class Y>
567typename dimensionless_quantity<si::system,Y>::type
568tan(const quantity<si::plane_angle,Y>& theta)
569{
570 using std::tan;
571 return tan(theta.value());
572}
573
574/// cos of theta in other angular units
575template<class System,class Y>
576typename dimensionless_quantity<System,Y>::type
577cos(const quantity<unit<plane_angle_dimension,System>,Y>& theta)
578{
579 return cos(quantity<si::plane_angle,Y>(theta));
580}
581
582/// sin of theta in other angular units
583template<class System,class Y>
584typename dimensionless_quantity<System,Y>::type
585sin(const quantity<unit<plane_angle_dimension,System>,Y>& theta)
586{
587 return sin(quantity<si::plane_angle,Y>(theta));
588}
589
590/// tan of theta in other angular units
591template<class System,class Y>
592typename dimensionless_quantity<System,Y>::type
593tan(const quantity<unit<plane_angle_dimension,System>,Y>& theta)
594{
595 return tan(quantity<si::plane_angle,Y>(theta));
596}
597
598/// acos of dimensionless quantity returning angle in same system
599template<class Y,class System>
600quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>
601acos(const quantity<unit<dimensionless_type, homogeneous_system<System> >,Y>& val)
602{
603 using std::acos;
604 return quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>(acos(val.value())*si::radians);
605}
606
607/// acos of dimensionless quantity returning angle in radians
608template<class Y>
609quantity<angle::radian_base_unit::unit_type,Y>
610acos(const quantity<unit<dimensionless_type, heterogeneous_dimensionless_system>,Y>& val)
611{
612 using std::acos;
613 return quantity<angle::radian_base_unit::unit_type,Y>::from_value(acos(val.value()));
614}
615
616/// asin of dimensionless quantity returning angle in same system
617template<class Y,class System>
618quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>
619asin(const quantity<unit<dimensionless_type, homogeneous_system<System> >,Y>& val)
620{
621 using std::asin;
622 return quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>(asin(val.value())*si::radians);
623}
624
625/// asin of dimensionless quantity returning angle in radians
626template<class Y>
627quantity<angle::radian_base_unit::unit_type,Y>
628asin(const quantity<unit<dimensionless_type, heterogeneous_dimensionless_system>,Y>& val)
629{
630 using std::asin;
631 return quantity<angle::radian_base_unit::unit_type,Y>::from_value(asin(val.value()));
632}
633
634/// atan of dimensionless quantity returning angle in same system
635template<class Y,class System>
636quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>
637atan(const quantity<unit<dimensionless_type, homogeneous_system<System> >, Y>& val)
638{
639 using std::atan;
640 return quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>(atan(val.value())*si::radians);
641}
642
643/// atan of dimensionless quantity returning angle in radians
644template<class Y>
645quantity<angle::radian_base_unit::unit_type,Y>
646atan(const quantity<unit<dimensionless_type, heterogeneous_dimensionless_system>, Y>& val)
647{
648 using std::atan;
649 return quantity<angle::radian_base_unit::unit_type,Y>::from_value(atan(val.value()));
650}
651
652/// atan2 of @c value_type returning angle in radians
653template<class Y, class Dimension, class System>
654quantity<unit<plane_angle_dimension, homogeneous_system<System> >, Y>
655atan2(const quantity<unit<Dimension, homogeneous_system<System> >, Y>& y,
656 const quantity<unit<Dimension, homogeneous_system<System> >, Y>& x)
657{
658 using std::atan2;
659 return quantity<unit<plane_angle_dimension, homogeneous_system<System> >, Y>(atan2(y.value(),x.value())*si::radians);
660}
661
662/// atan2 of @c value_type returning angle in radians
663template<class Y, class Dimension, class System>
664quantity<angle::radian_base_unit::unit_type,Y>
665atan2(const quantity<unit<Dimension, heterogeneous_system<System> >, Y>& y,
666 const quantity<unit<Dimension, heterogeneous_system<System> >, Y>& x)
667{
668 using std::atan2;
669 return quantity<angle::radian_base_unit::unit_type,Y>::from_value(atan2(y.value(),x.value()));
670}
671
672} // namespace units
673
674} // namespace boost
675
676#endif // BOOST_UNITS_CMATH_HPP
677

source code of boost/boost/units/cmath.hpp