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