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 
44 namespace boost {
45 
46 namespace units {
47 
48 template<class Unit,class Y>
49 inline
50 bool
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q)51 isfinite 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 
57 template<class Unit,class Y>
58 inline
59 bool
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q)60 isinf 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 
66 template<class Unit,class Y>
67 inline
68 bool
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q)69 isnan 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 
75 template<class Unit,class Y>
76 inline
77 bool
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q)78 isnormal 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 
84 template<class Unit,class Y>
85 inline
86 bool
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)87 isgreater 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 
94 template<class Unit,class Y>
95 inline
96 bool
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)97 isgreaterequal 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 
104 template<class Unit,class Y>
105 inline
106 bool
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)107 isless 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 
114 template<class Unit,class Y>
115 inline
116 bool
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)117 islessequal 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 
124 template<class Unit,class Y>
125 inline
126 bool
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)127 islessgreater 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 
134 template<class Unit,class Y>
135 inline
136 bool
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)137 isunordered 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 
144 template<class Unit,class Y>
145 inline
146 quantity<Unit,Y>
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q)147 abs 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 
156 template<class Unit,class Y>
157 inline
158 quantity<Unit,Y>
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q)159 ceil 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 
168 template<class Unit,class Y>
169 inline
170 quantity<Unit,Y>
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)171 copysign 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 
181 template<class Unit,class Y>
182 inline
183 quantity<Unit,Y>
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q)184 fabs 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 
193 template<class Unit,class Y>
194 inline
195 quantity<Unit,Y>
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q)196 floor 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 
205 template<class Unit,class Y>
206 inline
207 quantity<Unit,Y>
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)208 fdim 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 
220 template<class Unit1,class Unit2,class Unit3,class Y>
221 inline
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)
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 
244 template<class Unit,class Y>
245 inline
246 quantity<Unit,Y>
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)247 fmax 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 
257 template<class Unit,class Y>
258 inline
259 quantity<Unit,Y>
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)260 fmin 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 
270 template<class Unit,class Y>
271 inline
272 int
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q)273 fpclassify 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 
280 template<class Unit,class Y>
281 inline
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
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)289 hypot 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 
330 template<class Unit,class Y>
331 inline
332 quantity<Unit,Y>
333 nearbyint 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 
344 template<class Unit,class Y>
345 inline
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)346 quantity<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 }
355 template<class Unit,class Y>
356 inline
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)357 quantity<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 
372 template<class Unit,class Y>
373 inline
374 quantity<Unit,Y>
375 rint 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 
386 template<class Unit,class Y>
387 inline
388 quantity<Unit,Y>
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q)389 round 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 
398 template<class Unit,class Y>
399 inline
400 int
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q)401 signbit 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 
408 template<class Unit,class Y>
409 inline
410 quantity<Unit,Y>
BOOST_PREVENT_MACRO_SUBSTITUTION(const quantity<Unit,Y> & q)411 trunc 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 
420 template<class Unit,class Y>
421 inline
422 quantity<Unit, Y>
fmod(const quantity<Unit,Y> & q1,const quantity<Unit,Y> & q2)423 fmod(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 
432 template<class Unit, class Y>
433 inline
434 quantity<Unit, Y>
modf(const quantity<Unit,Y> & q1,quantity<Unit,Y> * q2)435 modf(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 
444 template<class Unit, class Y, class Int>
445 inline
446 quantity<Unit, Y>
frexp(const quantity<Unit,Y> & q,Int * ex)447 frexp(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.
458 template<class S, class Y>
459 inline
460 quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>
pow(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT (S),Y> & q1,const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT (S),Y> & q2)461 pow(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 
471 template<class S, class Y>
472 inline
473 quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>
exp(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT (S),Y> & q)474 exp(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 
483 template<class Unit, class Y, class Int>
484 inline
485 quantity<Unit, Y>
ldexp(const quantity<Unit,Y> & q,const Int & ex)486 ldexp(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 
495 template<class S, class Y>
496 inline
497 quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>
log(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT (S),Y> & q)498 log(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 
507 template<class S, class Y>
508 inline
509 quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(S), Y>
log10(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT (S),Y> & q)510 log10(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 
519 template<class Unit,class Y>
520 inline
521 typename root_typeof_helper<
522                             quantity<Unit,Y>,
523                             static_rational<2>
524                            >::type
sqrt(const quantity<Unit,Y> & q)525 sqrt(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 
541 namespace boost {
542 
543 namespace units {
544 
545 // trig functions with si argument/return types
546 
547 /// cos of theta in radians
548 template<class Y>
549 typename dimensionless_quantity<si::system,Y>::type
cos(const quantity<si::plane_angle,Y> & theta)550 cos(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
557 template<class Y>
558 typename dimensionless_quantity<si::system,Y>::type
sin(const quantity<si::plane_angle,Y> & theta)559 sin(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
566 template<class Y>
567 typename dimensionless_quantity<si::system,Y>::type
tan(const quantity<si::plane_angle,Y> & theta)568 tan(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
575 template<class System,class Y>
576 typename dimensionless_quantity<System,Y>::type
cos(const quantity<unit<plane_angle_dimension,System>,Y> & theta)577 cos(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
583 template<class System,class Y>
584 typename dimensionless_quantity<System,Y>::type
sin(const quantity<unit<plane_angle_dimension,System>,Y> & theta)585 sin(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
591 template<class System,class Y>
592 typename dimensionless_quantity<System,Y>::type
tan(const quantity<unit<plane_angle_dimension,System>,Y> & theta)593 tan(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
599 template<class Y,class System>
600 quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>
acos(const quantity<unit<dimensionless_type,homogeneous_system<System>>,Y> & val)601 acos(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
608 template<class Y>
609 quantity<angle::radian_base_unit::unit_type,Y>
acos(const quantity<unit<dimensionless_type,heterogeneous_dimensionless_system>,Y> & val)610 acos(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
617 template<class Y,class System>
618 quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>
asin(const quantity<unit<dimensionless_type,homogeneous_system<System>>,Y> & val)619 asin(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
626 template<class Y>
627 quantity<angle::radian_base_unit::unit_type,Y>
asin(const quantity<unit<dimensionless_type,heterogeneous_dimensionless_system>,Y> & val)628 asin(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
635 template<class Y,class System>
636 quantity<unit<plane_angle_dimension, homogeneous_system<System> >,Y>
atan(const quantity<unit<dimensionless_type,homogeneous_system<System>>,Y> & val)637 atan(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
644 template<class Y>
645 quantity<angle::radian_base_unit::unit_type,Y>
atan(const quantity<unit<dimensionless_type,heterogeneous_dimensionless_system>,Y> & val)646 atan(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
653 template<class Y, class Dimension, class System>
654 quantity<unit<plane_angle_dimension, homogeneous_system<System> >, Y>
atan2(const quantity<unit<Dimension,homogeneous_system<System>>,Y> & y,const quantity<unit<Dimension,homogeneous_system<System>>,Y> & x)655 atan2(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
663 template<class Y, class Dimension, class System>
664 quantity<angle::radian_base_unit::unit_type,Y>
atan2(const quantity<unit<Dimension,heterogeneous_system<System>>,Y> & y,const quantity<unit<Dimension,heterogeneous_system<System>>,Y> & x)665 atan2(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