WPILibC++ 2025.0.0-alpha-1-9-ga2beb75
math.h
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5// Copyright (c) 2016 Nic Holthaus
6//
7// The MIT License (MIT)
8//
9// Permission is hereby granted, free of charge, to any person obtaining a copy
10// of this software and associated documentation files (the "Software"), to deal
11// in the Software without restriction, including without limitation the rights
12// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the Software is
14// furnished to do so, subject to the following conditions:
15//
16// The above copyright notice and this permission notice shall be included in
17// all copies or substantial portions of the Software.
18//
19// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25// SOFTWARE.
26
27#pragma once
28
29#include <cmath>
30
31#include <gcem.hpp>
32
33#include "units/angle.h"
34#include "units/base.h"
35#include "units/dimensionless.h"
36
37//----------------------------------
38// UNIT-ENABLED CMATH FUNCTIONS
39//----------------------------------
40
41/**
42 * @brief namespace for unit-enabled versions of the `<cmath>` library
43 * @details Includes trigonometric functions, exponential/log functions,
44 * rounding functions, etc.
45 * @sa See `unit_t` for more information on unit type containers.
46 */
47namespace units::math {
48//----------------------------------
49// TRIGONOMETRIC FUNCTIONS
50//----------------------------------
51
52/**
53 * @ingroup UnitMath
54 * @brief Compute cosine
55 * @details The input value can be in any unit of angle, including radians or
56 * degrees.
57 * @tparam AngleUnit any `unit_t` type of `category::angle_unit`.
58 * @param[in] angle angle to compute the cosine of
59 * @returns Returns the cosine of <i>angle</i>
60 */
61#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
62template <class AngleUnit>
63constexpr dimensionless::scalar_t cos(const AngleUnit angle) noexcept {
64 static_assert(
65 traits::is_angle_unit<AngleUnit>::value,
66 "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
68 gcem::cos(angle.template convert<angle::radian>()()));
69}
70#endif
71
72/**
73 * @ingroup UnitMath
74 * @brief Compute sine
75 * @details The input value can be in any unit of angle, including radians or
76 * degrees.
77 * @tparam AngleUnit any `unit_t` type of `category::angle_unit`.
78 * @param[in] angle angle to compute the since of
79 * @returns Returns the sine of <i>angle</i>
80 */
81#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
82template <class AngleUnit>
83constexpr dimensionless::scalar_t sin(const AngleUnit angle) noexcept {
84 static_assert(
85 traits::is_angle_unit<AngleUnit>::value,
86 "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
88 gcem::sin(angle.template convert<angle::radian>()()));
89}
90#endif
91/**
92 * @ingroup UnitMath
93 * @brief Compute tangent
94 * @details The input value can be in any unit of angle, including radians or
95 * degrees.
96 * @tparam AngleUnit any `unit_t` type of `category::angle_unit`.
97 * @param[in] angle angle to compute the tangent of
98 * @returns Returns the tangent of <i>angle</i>
99 */
100#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
101template <class AngleUnit>
102constexpr dimensionless::scalar_t tan(const AngleUnit angle) noexcept {
103 static_assert(
104 traits::is_angle_unit<AngleUnit>::value,
105 "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
107 gcem::tan(angle.template convert<angle::radian>()()));
108}
109#endif
110
111/**
112 * @ingroup UnitMath
113 * @brief Compute arc cosine
114 * @details Returns the principal value of the arc cosine of x, expressed in
115 * radians.
116 * @param[in] x Value whose arc cosine is computed, in the interval [-1,+1].
117 * @returns Principal arc cosine of x, in the interval [0,pi] radians.
118 */
119#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
120template <class ScalarUnit>
121constexpr angle::radian_t acos(const ScalarUnit x) noexcept {
122 static_assert(
124 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
125 return angle::radian_t(gcem::acos(x()));
126}
127#endif
128
129/**
130 * @ingroup UnitMath
131 * @brief Compute arc sine
132 * @details Returns the principal value of the arc sine of x, expressed in
133 * radians.
134 * @param[in] x Value whose arc sine is computed, in the interval [-1,+1].
135 * @returns Principal arc sine of x, in the interval [-pi/2,+pi/2] radians.
136 */
137#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
138template <class ScalarUnit>
139constexpr angle::radian_t asin(const ScalarUnit x) noexcept {
140 static_assert(
142 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
143 return angle::radian_t(gcem::asin(x()));
144}
145#endif
146
147/**
148 * @ingroup UnitMath
149 * @brief Compute arc tangent
150 * @details Returns the principal value of the arc tangent of x, expressed in
151 * radians. Notice that because of the sign ambiguity, the function
152 * cannot determine with certainty in which quadrant the angle falls
153 * only by its tangent value. See atan2 for an alternative that takes a
154 * fractional argument instead.
155 * @tparam AngleUnit any `unit_t` type of `category::angle_unit`.
156 * @param[in] x Value whose arc tangent is computed, in the interval [-1,+1].
157 * @returns Principal arc tangent of x, in the interval [-pi/2,+pi/2] radians.
158 */
159#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
160template <class ScalarUnit>
161constexpr angle::radian_t atan(const ScalarUnit x) noexcept {
162 static_assert(
164 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
165 return angle::radian_t(gcem::atan(x()));
166}
167#endif
168
169/**
170 * @ingroup UnitMath
171 * @brief Compute arc tangent with two parameters
172 * @details To compute the value, the function takes into account the sign of
173 * both arguments in order to determine the quadrant.
174 * @param[in] y y-component of the triangle expressed.
175 * @param[in] x x-component of the triangle expressed.
176 * @returns Returns the principal value of the arc tangent of <i>y/x</i>,
177 * expressed in radians.
178 */
179#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
180template <class Y, class X>
181constexpr angle::radian_t atan2(const Y y, const X x) noexcept {
182 static_assert(traits::is_dimensionless_unit<decltype(y / x)>::value,
183 "The quantity y/x must yield a dimensionless ratio.");
184
185 // X and Y could be different length units, so normalize them
186 return angle::radian_t(
187 gcem::atan2(y.template convert<
188 typename units::traits::unit_t_traits<X>::unit_type>()(),
189 x()));
190}
191#endif
192
193//----------------------------------
194// HYPERBOLIC TRIG FUNCTIONS
195//----------------------------------
196
197/**
198 * @ingroup UnitMath
199 * @brief Compute hyperbolic cosine
200 * @details The input value can be in any unit of angle, including radians or
201 * degrees.
202 * @tparam AngleUnit any `unit_t` type of `category::angle_unit`.
203 * @param[in] angle angle to compute the hyperbolic cosine of
204 * @returns Returns the hyperbolic cosine of <i>angle</i>
205 */
206#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
207template <class AngleUnit>
208constexpr dimensionless::scalar_t cosh(const AngleUnit angle) noexcept {
209 static_assert(
210 traits::is_angle_unit<AngleUnit>::value,
211 "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
213 gcem::cosh(angle.template convert<angle::radian>()()));
214}
215#endif
216
217/**
218 * @ingroup UnitMath
219 * @brief Compute hyperbolic sine
220 * @details The input value can be in any unit of angle, including radians or
221 * degrees.
222 * @tparam AngleUnit any `unit_t` type of `category::angle_unit`.
223 * @param[in] angle angle to compute the hyperbolic sine of
224 * @returns Returns the hyperbolic sine of <i>angle</i>
225 */
226#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
227template <class AngleUnit>
228constexpr dimensionless::scalar_t sinh(const AngleUnit angle) noexcept {
229 static_assert(
230 traits::is_angle_unit<AngleUnit>::value,
231 "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
233 gcem::sinh(angle.template convert<angle::radian>()()));
234}
235#endif
236
237/**
238 * @ingroup UnitMath
239 * @brief Compute hyperbolic tangent
240 * @details The input value can be in any unit of angle, including radians or
241 * degrees.
242 * @tparam AngleUnit any `unit_t` type of `category::angle_unit`.
243 * @param[in] angle angle to compute the hyperbolic tangent of
244 * @returns Returns the hyperbolic tangent of <i>angle</i>
245 */
246#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
247template <class AngleUnit>
248constexpr dimensionless::scalar_t tanh(const AngleUnit angle) noexcept {
249 static_assert(
250 traits::is_angle_unit<AngleUnit>::value,
251 "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
253 gcem::tanh(angle.template convert<angle::radian>()()));
254}
255#endif
256
257/**
258 * @ingroup UnitMath
259 * @brief Compute arc hyperbolic cosine
260 * @details Returns the nonnegative arc hyperbolic cosine of x, expressed in
261 * radians.
262 * @param[in] x Value whose arc hyperbolic cosine is computed. If the argument
263 * is less than 1, a domain error occurs.
264 * @returns Nonnegative arc hyperbolic cosine of x, in the interval
265 * [0,+INFINITY] radians.
266 */
267#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
268template <class ScalarUnit>
269constexpr angle::radian_t acosh(const ScalarUnit x) noexcept {
270 static_assert(
272 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
273 return angle::radian_t(gcem::acosh(x()));
274}
275#endif
276
277/**
278 * @ingroup UnitMath
279 * @brief Compute arc hyperbolic sine
280 * @details Returns the arc hyperbolic sine of x, expressed in radians.
281 * @param[in] x Value whose arc hyperbolic sine is computed.
282 * @returns Arc hyperbolic sine of x, in radians.
283 */
284#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
285template <class ScalarUnit>
286constexpr angle::radian_t asinh(const ScalarUnit x) noexcept {
287 static_assert(
289 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
290 return angle::radian_t(gcem::asinh(x()));
291}
292#endif
293
294/**
295 * @ingroup UnitMath
296 * @brief Compute arc hyperbolic tangent
297 * @details Returns the arc hyperbolic tangent of x, expressed in radians.
298 * @param[in] x Value whose arc hyperbolic tangent is computed, in the interval
299 * [-1,+1]. If the argument is out of this interval, a domain error
300 * occurs. For values of -1 and +1, a pole error may occur.
301 * @returns units::angle::radian_t
302 */
303#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
304template <class ScalarUnit>
305constexpr angle::radian_t atanh(const ScalarUnit x) noexcept {
306 static_assert(
308 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
309 return angle::radian_t(gcem::atanh(x()));
310}
311#endif
312
313//----------------------------------
314// TRANSCENDENTAL FUNCTIONS
315//----------------------------------
316
317// it makes NO SENSE to put dimensioned units into a transcendental function,
318// and if you think it does you are demonstrably wrong.
319// https://en.wikipedia.org/wiki/Transcendental_function#Dimensional_analysis
320
321/**
322 * @ingroup UnitMath
323 * @brief Compute exponential function
324 * @details Returns the base-e exponential function of x, which is e raised to
325 * the power x: ex.
326 * @param[in] x scalar value of the exponent.
327 * @returns Exponential value of x.
328 * If the magnitude of the result is too large to be represented by a
329 * value of the return type, the function returns HUGE_VAL (or
330 * HUGE_VALF or HUGE_VALL) with the proper sign, and an overflow range
331 * error occurs.
332 */
333template <class ScalarUnit>
334constexpr dimensionless::scalar_t exp(const ScalarUnit x) noexcept {
335 static_assert(
337 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
339}
340
341/**
342 * @ingroup UnitMath
343 * @brief Compute natural logarithm
344 * @details Returns the natural logarithm of x.
345 * @param[in] x scalar value whose logarithm is calculated. If the argument is
346 * negative, a domain error occurs.
347 * @sa log10 for more common base-10 logarithms
348 * @returns Natural logarithm of x.
349 */
350template <class ScalarUnit>
351constexpr dimensionless::scalar_t log(const ScalarUnit x) noexcept {
352 static_assert(
354 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
356}
357
358/**
359 * @ingroup UnitMath
360 * @brief Compute common logarithm
361 * @details Returns the common (base-10) logarithm of x.
362 * @param[in] x Value whose logarithm is calculated. If the argument is
363 * negative, a domain error occurs.
364 * @returns Common logarithm of x.
365 */
366template <class ScalarUnit>
367constexpr dimensionless::scalar_t log10(const ScalarUnit x) noexcept {
368 static_assert(
370 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
372}
373
374/**
375 * @ingroup UnitMath
376 * @brief Break into fractional and integral parts.
377 * @details The integer part is stored in the object pointed by intpart, and the
378 * fractional part is returned by the function. Both parts have the
379 * same sign as x.
380 * @param[in] x scalar value to break into parts.
381 * @param[in] intpart Pointer to an object (of the same type as x) where the
382 * integral part is stored with the same sign as x.
383 * @returns The fractional part of x, with the same sign.
384 */
385template <class ScalarUnit>
386dimensionless::scalar_t modf(const ScalarUnit x, ScalarUnit* intpart) noexcept {
387 static_assert(
389 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
390
392 dimensionless::scalar_t fracpart =
394 *intpart = intp;
395 return fracpart;
396}
397
398/**
399 * @ingroup UnitMath
400 * @brief Compute binary exponential function
401 * @details Returns the base-2 exponential function of x, which is 2 raised to
402 * the power x: 2^x. 2param[in] x Value of the exponent.
403 * @returns 2 raised to the power of x.
404 */
405template <class ScalarUnit>
406dimensionless::scalar_t exp2(const ScalarUnit x) noexcept {
407 static_assert(
409 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
411}
412
413/**
414 * @ingroup UnitMath
415 * @brief Compute exponential minus one
416 * @details Returns e raised to the power x minus one: e^x-1. For small
417 * magnitude values of x, expm1 may be more accurate than exp(x)-1.
418 * @param[in] x Value of the exponent.
419 * @returns e raised to the power of x, minus one.
420 */
421template <class ScalarUnit>
422constexpr dimensionless::scalar_t expm1(const ScalarUnit x) noexcept {
423 static_assert(
425 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
427}
428
429/**
430 * @ingroup UnitMath
431 * @brief Compute logarithm plus one
432 * @details Returns the natural logarithm of one plus x. For small magnitude
433 * values of x, logp1 may be more accurate than log(1+x).
434 * @param[in] x Value whose logarithm is calculated. If the argument is less
435 * than -1, a domain error occurs.
436 * @returns The natural logarithm of (1+x).
437 */
438template <class ScalarUnit>
439constexpr dimensionless::scalar_t log1p(const ScalarUnit x) noexcept {
440 static_assert(
442 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
444}
445
446/**
447 * @ingroup UnitMath
448 * @brief Compute binary logarithm
449 * @details Returns the binary (base-2) logarithm of x.
450 * @param[in] x Value whose logarithm is calculated. If the argument is
451 * negative, a domain error occurs.
452 * @returns The binary logarithm of x: log2x.
453 */
454template <class ScalarUnit>
455constexpr dimensionless::scalar_t log2(const ScalarUnit x) noexcept {
456 static_assert(
458 "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
460}
461
462//----------------------------------
463// POWER FUNCTIONS
464//----------------------------------
465
466/* pow is implemented earlier in the library since a lot of the unit definitions
467 * depend on it */
468
469/**
470 * @ingroup UnitMath
471 * @brief computes the square root of <i>value</i>
472 * @details Only implemented for linear_scale units.
473 * @param[in] value `unit_t` derived type to compute the square root of.
474 * @returns new unit_t, whose units are the square root of value's.
475 * E.g. if values had units of `square_meter`, then the return type
476 * will have units of `meter`.
477 * @note `sqrt` provides a _rational approximation_ of the square root of
478 * <i>value</i>. In some cases, _both_ the returned value _and_ conversion
479 * factor of the returned unit type may have errors no larger than
480 * `1e-10`.
481 */
482template <
483 class UnitType,
484 std::enable_if_t<units::traits::has_linear_scale<UnitType>::value, int> = 0>
485inline constexpr auto sqrt(const UnitType& value) noexcept
486 -> unit_t<
488 typename units::traits::unit_t_traits<UnitType>::underlying_type,
489 linear_scale> {
490 return unit_t<
492 typename units::traits::unit_t_traits<UnitType>::underlying_type,
493 linear_scale>(gcem::sqrt(value()));
494}
495
496/**
497 * @ingroup UnitMath
498 * @brief Computes the square root of the sum-of-squares of x and y.
499 * @details Only implemented for linear_scale units.
500 * @param[in] x unit_t type value
501 * @param[in] y unit_t type value
502 * @returns square root of the sum-of-squares of x and y in the same units as x.
503 */
504template <class UnitTypeLhs, class UnitTypeRhs,
507 int> = 0>
508inline constexpr UnitTypeLhs hypot(const UnitTypeLhs& x, const UnitTypeRhs& y) {
510 "Parameters of hypot() function are not compatible units.");
511 return UnitTypeLhs(gcem::hypot(
512 x(),
513 y.template convert<
514 typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
515}
516
517//----------------------------------
518// ROUNDING FUNCTIONS
519//----------------------------------
520
521/**
522 * @ingroup UnitMath
523 * @brief Round up value
524 * @details Rounds x upward, returning the smallest integral value that is not
525 * less than x.
526 * @param[in] x Unit value to round up.
527 * @returns The smallest integral value that is not less than x.
528 */
529template <class UnitType,
530 class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
531constexpr UnitType ceil(const UnitType x) noexcept {
532 return UnitType(gcem::ceil(x()));
533}
534
535/**
536 * @ingroup UnitMath
537 * @brief Round down value
538 * @details Rounds x downward, returning the largest integral value that is not
539 * greater than x.
540 * @param[in] x Unit value to round down.
541 * @returns The value of x rounded downward.
542 */
543template <class UnitType,
544 class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
545constexpr UnitType floor(const UnitType x) noexcept {
546 return UnitType(gcem::floor(x()));
547}
548
549/**
550 * @ingroup UnitMath
551 * @brief Compute remainder of division
552 * @details Returns the floating-point remainder of numer/denom (rounded towards
553 * zero).
554 * @param[in] numer Value of the quotient numerator.
555 * @param[in] denom Value of the quotient denominator.
556 * @returns The remainder of dividing the arguments.
557 */
558template <class UnitTypeLhs, class UnitTypeRhs,
559 class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value &&
561constexpr UnitTypeLhs fmod(const UnitTypeLhs numer,
562 const UnitTypeRhs denom) noexcept {
564 "Parameters of fmod() function are not compatible units.");
565 return UnitTypeLhs(gcem::fmod(
566 numer(),
567 denom.template convert<
568 typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
569}
570
571/**
572 * @ingroup UnitMath
573 * @brief Truncate value
574 * @details Rounds x toward zero, returning the nearest integral value that is
575 * not larger in magnitude than x. Effectively rounds towards 0.
576 * @param[in] x Value to truncate
577 * @returns The nearest integral value that is not larger in magnitude than x.
578 */
579template <class UnitType,
580 class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
581constexpr UnitType trunc(const UnitType x) noexcept {
582 return UnitType(gcem::trunc(x()));
583}
584
585/**
586 * @ingroup UnitMath
587 * @brief Round to nearest
588 * @details Returns the integral value that is nearest to x, with halfway cases
589 * rounded away from zero.
590 * @param[in] x value to round.
591 * @returns The value of x rounded to the nearest integral.
592 */
593template <class UnitType,
594 class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
595constexpr UnitType round(const UnitType x) noexcept {
596 return UnitType(gcem::round(x()));
597}
598
599//----------------------------------
600// FLOATING POINT MANIPULATION
601//----------------------------------
602
603/**
604 * @ingroup UnitMath
605 * @brief Copy sign
606 * @details Returns a value with the magnitude and dimension of x, and the sign
607 * of y. Values x and y do not have to be compatible units.
608 * @param[in] x Value with the magnitude of the resulting value.
609 * @param[in] y Value with the sign of the resulting value.
610 * @returns value with the magnitude and dimension of x, and the sign of y.
611 */
612template <class UnitTypeLhs, class UnitTypeRhs,
613 class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value &&
615constexpr UnitTypeLhs copysign(const UnitTypeLhs x,
616 const UnitTypeRhs y) noexcept {
617 return UnitTypeLhs(gcem::copysign(
618 x(), y())); // no need for conversion to get the correct sign.
619}
620
621/// Overload to copy the sign from a raw double
622template <class UnitTypeLhs,
623 class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value>>
624constexpr UnitTypeLhs copysign(const UnitTypeLhs x,
625 const UNIT_LIB_DEFAULT_TYPE y) noexcept {
626 return UnitTypeLhs(gcem::copysign(x(), y));
627}
628
629//----------------------------------
630// MIN / MAX / DIFFERENCE
631//----------------------------------
632
633/**
634 * @ingroup UnitMath
635 * @brief Positive difference
636 * @details The function returns x-y if x>y, and zero otherwise, in the same
637 * units as x. Values x and y do not have to be the same type of units,
638 * but they do have to be compatible.
639 * @param[in] x Values whose difference is calculated.
640 * @param[in] y Values whose difference is calculated.
641 * @returns The positive difference between x and y.
642 */
643template <class UnitTypeLhs, class UnitTypeRhs,
644 class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value &&
646UnitTypeLhs fdim(const UnitTypeLhs x, const UnitTypeRhs y) noexcept {
648 "Parameters of fdim() function are not compatible units.");
649 return UnitTypeLhs(std::fdim(
650 x(),
651 y.template convert<
652 typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
653}
654
655/**
656 * @ingroup UnitMath
657 * @brief Maximum value
658 * @details Returns the larger of its arguments: either x or y, in the same
659 * units as x. Values x and y do not have to be the same type of units,
660 * but they do have to be compatible.
661 * @param[in] x Values among which the function selects a maximum.
662 * @param[in] y Values among which the function selects a maximum.
663 * @returns The maximum numeric value of its arguments.
664 */
665template <class UnitTypeLhs, class UnitTypeRhs,
666 class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value &&
668constexpr UnitTypeLhs fmax(const UnitTypeLhs x, const UnitTypeRhs y) noexcept {
670 "Parameters of fmax() function are not compatible units.");
671 return UnitTypeLhs(gcem::max<double, double>(
672 x(),
673 y.template convert<
674 typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
675}
676
677/**
678 * @ingroup UnitMath
679 * @brief Minimum value
680 * @details Returns the smaller of its arguments: either x or y, in the same
681 * units as x. If one of the arguments in a NaN, the other is returned.
682 * Values x and y do not have to be the same type of units, but they do
683 * have to be compatible.
684 * @param[in] x Values among which the function selects a minimum.
685 * @param[in] y Values among which the function selects a minimum.
686 * @returns The minimum numeric value of its arguments.
687 */
688template <class UnitTypeLhs, class UnitTypeRhs,
689 class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value &&
691constexpr UnitTypeLhs fmin(const UnitTypeLhs x, const UnitTypeRhs y) noexcept {
693 "Parameters of fmin() function are not compatible units.");
694 return UnitTypeLhs(gcem::min<double, double>(
695 x(),
696 y.template convert<
697 typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
698}
699
700//----------------------------------
701// OTHER FUNCTIONS
702//----------------------------------
703
704/**
705 * @ingroup UnitMath
706 * @brief Compute absolute value
707 * @details Returns the absolute value of x, i.e. |x|.
708 * @param[in] x Value whose absolute value is returned.
709 * @returns The absolute value of x.
710 */
711template <class UnitType,
712 class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
713constexpr UnitType fabs(const UnitType x) noexcept {
714 return UnitType(gcem::abs(x()));
715}
716
717/**
718 * @ingroup UnitMath
719 * @brief Compute absolute value
720 * @details Returns the absolute value of x, i.e. |x|.
721 * @param[in] x Value whose absolute value is returned.
722 * @returns The absolute value of x.
723 */
724template <class UnitType,
725 class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
726constexpr UnitType abs(const UnitType x) noexcept {
727 return UnitType(gcem::abs(x()));
728}
729
730/**
731 * @ingroup UnitMath
732 * @brief Multiply-add
733 * @details Returns x*y+z. The function computes the result without losing
734 * precision in any intermediate result. The resulting unit type is a
735 * compound unit of x* y.
736 * @param[in] x Values to be multiplied.
737 * @param[in] y Values to be multiplied.
738 * @param[in] z Value to be added.
739 * @returns The result of x*y+z
740 */
741template <class UnitTypeLhs, class UnitMultiply, class UnitAdd,
742 class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value &&
745auto fma(const UnitTypeLhs x, const UnitMultiply y,
746 const UnitAdd z) noexcept -> decltype(x * y) {
747 using resultType = decltype(x * y);
748 static_assert(
751 typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type,
752 typename units::traits::unit_t_traits<UnitMultiply>::unit_type>,
753 typename units::traits::unit_t_traits<UnitAdd>::unit_type>::value,
754 "Unit types are not compatible.");
755 return resultType(std::fma(x(), y(), resultType(z)()));
756}
757} // namespace units::math
#define UNIT_LIB_DEFAULT_TYPE
Definition: base.h:59
Container for values which represent quantities of a given unit.
Definition: base.h:1928
typename std::enable_if< B, T >::type enable_if_t
Definition: core.h:271
static constexpr T convert(const T &value) noexcept
converts a value from one type to another.
Definition: base.h:1650
typename units::detail::sqrt_impl< U, Eps >::type square_root
represents the square root of type class U.
Definition: base.h:1403
constexpr dimensionless::scalar_t tan(const AngleUnit angle) noexcept
Compute tangent.
Definition: math.h:102
constexpr UnitTypeLhs fmin(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Minimum value.
Definition: math.h:691
constexpr UnitTypeLhs fmax(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Maximum value.
Definition: math.h:668
constexpr UnitType abs(const UnitType x) noexcept
Compute absolute value.
Definition: math.h:726
constexpr UnitType ceil(const UnitType x) noexcept
Round up value.
Definition: math.h:531
constexpr UnitTypeLhs copysign(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Copy sign.
Definition: math.h:615
constexpr UnitType fabs(const UnitType x) noexcept
Compute absolute value.
Definition: math.h:713
constexpr UnitType floor(const UnitType x) noexcept
Round down value.
Definition: math.h:545
constexpr auto sqrt(const UnitType &value) noexcept -> unit_t< square_root< typename units::traits::unit_t_traits< UnitType >::unit_type >, typename units::traits::unit_t_traits< UnitType >::underlying_type, linear_scale >
computes the square root of value
Definition: math.h:485
constexpr dimensionless::scalar_t log2(const ScalarUnit x) noexcept
Compute binary logarithm.
Definition: math.h:455
constexpr angle::radian_t acosh(const ScalarUnit x) noexcept
Compute arc hyperbolic cosine.
Definition: math.h:269
constexpr dimensionless::scalar_t log1p(const ScalarUnit x) noexcept
Compute logarithm plus one.
Definition: math.h:439
constexpr angle::radian_t asin(const ScalarUnit x) noexcept
Compute arc sine.
Definition: math.h:139
constexpr UnitTypeLhs hypot(const UnitTypeLhs &x, const UnitTypeRhs &y)
Computes the square root of the sum-of-squares of x and y.
Definition: math.h:508
constexpr angle::radian_t acos(const ScalarUnit x) noexcept
Compute arc cosine.
Definition: math.h:121
constexpr dimensionless::scalar_t sinh(const AngleUnit angle) noexcept
Compute hyperbolic sine.
Definition: math.h:228
auto fma(const UnitTypeLhs x, const UnitMultiply y, const UnitAdd z) noexcept -> decltype(x *y)
Multiply-add.
Definition: math.h:745
UnitTypeLhs fdim(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Positive difference.
Definition: math.h:646
constexpr UnitTypeLhs fmod(const UnitTypeLhs numer, const UnitTypeRhs denom) noexcept
Compute remainder of division.
Definition: math.h:561
dimensionless::scalar_t modf(const ScalarUnit x, ScalarUnit *intpart) noexcept
Break into fractional and integral parts.
Definition: math.h:386
dimensionless::scalar_t exp2(const ScalarUnit x) noexcept
Compute binary exponential function.
Definition: math.h:406
constexpr angle::radian_t atan2(const Y y, const X x) noexcept
Compute arc tangent with two parameters.
Definition: math.h:181
constexpr dimensionless::scalar_t sin(const AngleUnit angle) noexcept
Compute sine.
Definition: math.h:83
constexpr dimensionless::scalar_t log(const ScalarUnit x) noexcept
Compute natural logarithm.
Definition: math.h:351
constexpr UnitType trunc(const UnitType x) noexcept
Truncate value.
Definition: math.h:581
constexpr dimensionless::scalar_t log10(const ScalarUnit x) noexcept
Compute common logarithm.
Definition: math.h:367
constexpr dimensionless::scalar_t tanh(const AngleUnit angle) noexcept
Compute hyperbolic tangent.
Definition: math.h:248
constexpr dimensionless::scalar_t cos(const AngleUnit angle) noexcept
Compute cosine.
Definition: math.h:63
constexpr dimensionless::scalar_t cosh(const AngleUnit angle) noexcept
Compute hyperbolic cosine.
Definition: math.h:208
constexpr angle::radian_t atan(const ScalarUnit x) noexcept
Compute arc tangent.
Definition: math.h:161
constexpr angle::radian_t atanh(const ScalarUnit x) noexcept
Compute arc hyperbolic tangent.
Definition: math.h:305
constexpr dimensionless::scalar_t exp(const ScalarUnit x) noexcept
Compute exponential function.
Definition: math.h:334
constexpr angle::radian_t asinh(const ScalarUnit x) noexcept
Compute arc hyperbolic sine.
Definition: math.h:286
constexpr UnitType round(const UnitType x) noexcept
Round to nearest.
Definition: math.h:595
constexpr dimensionless::scalar_t expm1(const ScalarUnit x) noexcept
Compute exponential minus one.
Definition: math.h:422
typename units::detail::compound_impl< U, Us... >::type compound_unit
Represents a unit type made up from other units.
Definition: base.h:1436
constexpr return_t< T > cosh(const T x) noexcept
Compile-time hyperbolic cosine function.
Definition: cosh.hpp:65
constexpr return_t< T > round(const T x) noexcept
Compile-time round function.
Definition: round.hpp:125
constexpr T abs(const T x) noexcept
Compile-time absolute value function.
Definition: abs.hpp:40
constexpr return_t< T > log10(const T x) noexcept
Compile-time common logarithm function.
Definition: log10.hpp:59
constexpr return_t< T > atan(const T x) noexcept
Compile-time arctangent function.
Definition: atan.hpp:155
constexpr return_t< T > ceil(const T x) noexcept
Compile-time ceil function.
Definition: ceil.hpp:130
constexpr return_t< T > tan(const T x) noexcept
Compile-time tangent function.
Definition: tan.hpp:140
constexpr return_t< T > sinh(const T x) noexcept
Compile-time hyperbolic sine function.
Definition: sinh.hpp:65
constexpr return_t< T > asin(const T x) noexcept
Compile-time arcsine function.
Definition: asin.hpp:82
constexpr common_return_t< T1, T2 > fmod(const T1 x, const T2 y) noexcept
Compile-time remainder of division function.
Definition: fmod.hpp:70
constexpr T1 copysign(const T1 x, const T2 y) noexcept
Compile-time copy sign function.
Definition: copysign.hpp:41
constexpr return_t< T > log(const T x) noexcept
Compile-time natural logarithm function.
Definition: log.hpp:186
constexpr return_t< T > cos(const T x) noexcept
Compile-time cosine function.
Definition: cos.hpp:83
constexpr return_t< T > sin(const T x) noexcept
Compile-time sine function.
Definition: sin.hpp:85
constexpr return_t< T > acosh(const T x) noexcept
Compile-time inverse hyperbolic cosine function.
Definition: acosh.hpp:68
constexpr return_t< T > trunc(const T x) noexcept
Compile-time trunc function.
Definition: trunc.hpp:121
constexpr return_t< T > log2(const T x) noexcept
Compile-time binary logarithm function.
Definition: log2.hpp:59
constexpr common_return_t< T1, T2 > hypot(const T1 x, const T2 y) noexcept
Compile-time Pythagorean addition function.
Definition: hypot.hpp:147
constexpr return_t< T > sqrt(const T x) noexcept
Compile-time square-root function.
Definition: sqrt.hpp:109
constexpr return_t< T > floor(const T x) noexcept
Compile-time floor function.
Definition: floor.hpp:130
constexpr return_t< T > atanh(const T x) noexcept
Compile-time inverse hyperbolic tangent function.
Definition: atanh.hpp:79
constexpr return_t< T > exp(const T x) noexcept
Compile-time exponential function.
Definition: exp.hpp:130
constexpr return_t< T > acos(const T x) noexcept
Compile-time arccosine function.
Definition: acos.hpp:84
constexpr return_t< T > log1p(const T x) noexcept
Compile-time natural-logarithm-plus-1 function.
Definition: log1p.hpp:80
constexpr return_t< T > expm1(const T x) noexcept
Compile-time exponential-minus-1 function.
Definition: expm1.hpp:76
constexpr common_return_t< T1, T2 > atan2(const T1 y, const T2 x) noexcept
Compile-time two-argument arctangent function.
Definition: atan2.hpp:88
constexpr return_t< T > tanh(const T x) noexcept
Compile-time hyperbolic tangent function.
Definition: tanh.hpp:89
constexpr return_t< T > asinh(const T x) noexcept
Compile-time inverse hyperbolic sine function.
Definition: asinh.hpp:65
unit_t< scalar > scalar_t
Definition: base.h:2515
namespace for unit-enabled versions of the <cmath> library
Definition: math.h:47
unit_t scale which is linear
Definition: base.h:2489
Trait which tests whether a type is inherited from a linear scale.
Definition: base.h:2417
Trait which tests whether two container types derived from unit_t are convertible to each other.
Definition: base.h:1828
Traits which tests if a class is a unit
Definition: base.h:1866