Merge branch 'development'

This commit is contained in:
Peter Johnson
2024-04-21 20:15:51 -07:00
149 changed files with 2211 additions and 2189 deletions

View File

@@ -6,7 +6,6 @@
#include <algorithm>
#include <wpi/deprecated.h>
#include <wpi/timestamp.h>
#include "units/time.h"

View File

@@ -4,8 +4,6 @@
#pragma once
#include <wpi/deprecated.h>
#include "units/time.h"
#include "wpimath/MathShared.h"
@@ -114,10 +112,10 @@ class TrapezoidProfile {
* @deprecated Pass the desired and current state into calculate instead of
* constructing a new TrapezoidProfile with the desired and current state
*/
WPI_DEPRECATED(
[[deprecated(
"Pass the desired and current state into calculate instead of "
"constructing a new TrapezoidProfile with the desired and current "
"state")
"state")]]
TrapezoidProfile(Constraints constraints, State goal,
State initial = State{Distance_t{0}, Velocity_t{0}});

View File

@@ -81,6 +81,8 @@
#include <fmt/format.h>
#endif
#include <gcem.hpp>
//------------------------------
// STRING FORMATTER
//------------------------------
@@ -2803,10 +2805,10 @@ namespace units
* @returns new unit_t, raised to the given exponent
*/
template<int power, class UnitType, class = typename std::enable_if<traits::has_linear_scale<UnitType>::value, int>>
inline auto pow(const UnitType& value) noexcept -> unit_t<typename units::detail::power_of_unit<power, typename units::traits::unit_t_traits<UnitType>::unit_type>::type, typename units::traits::unit_t_traits<UnitType>::underlying_type, linear_scale>
inline constexpr auto pow(const UnitType& value) noexcept -> unit_t<typename units::detail::power_of_unit<power, typename units::traits::unit_t_traits<UnitType>::unit_type>::type, typename units::traits::unit_t_traits<UnitType>::underlying_type, linear_scale>
{
return unit_t<typename units::detail::power_of_unit<power, typename units::traits::unit_t_traits<UnitType>::unit_type>::type, typename units::traits::unit_t_traits<UnitType>::underlying_type, linear_scale>
(std::pow(value(), power));
(gcem::pow(value(), power));
}
/**

View File

@@ -28,6 +28,8 @@
#include <cmath>
#include <gcem.hpp>
#include "units/angle.h"
#include "units/base.h"
#include "units/dimensionless.h"
@@ -58,12 +60,12 @@ namespace units::math {
*/
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
template <class AngleUnit>
dimensionless::scalar_t cos(const AngleUnit angle) noexcept {
constexpr dimensionless::scalar_t cos(const AngleUnit angle) noexcept {
static_assert(
traits::is_angle_unit<AngleUnit>::value,
"Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
return dimensionless::scalar_t(
std::cos(angle.template convert<angle::radian>()()));
gcem::cos(angle.template convert<angle::radian>()()));
}
#endif
@@ -78,12 +80,12 @@ dimensionless::scalar_t cos(const AngleUnit angle) noexcept {
*/
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
template <class AngleUnit>
dimensionless::scalar_t sin(const AngleUnit angle) noexcept {
constexpr dimensionless::scalar_t sin(const AngleUnit angle) noexcept {
static_assert(
traits::is_angle_unit<AngleUnit>::value,
"Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
return dimensionless::scalar_t(
std::sin(angle.template convert<angle::radian>()()));
gcem::sin(angle.template convert<angle::radian>()()));
}
#endif
/**
@@ -97,12 +99,12 @@ dimensionless::scalar_t sin(const AngleUnit angle) noexcept {
*/
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
template <class AngleUnit>
dimensionless::scalar_t tan(const AngleUnit angle) noexcept {
constexpr dimensionless::scalar_t tan(const AngleUnit angle) noexcept {
static_assert(
traits::is_angle_unit<AngleUnit>::value,
"Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
return dimensionless::scalar_t(
std::tan(angle.template convert<angle::radian>()()));
gcem::tan(angle.template convert<angle::radian>()()));
}
#endif
@@ -116,11 +118,11 @@ dimensionless::scalar_t tan(const AngleUnit angle) noexcept {
*/
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
template <class ScalarUnit>
angle::radian_t acos(const ScalarUnit x) noexcept {
constexpr angle::radian_t acos(const ScalarUnit x) noexcept {
static_assert(
traits::is_dimensionless_unit<ScalarUnit>::value,
"Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
return angle::radian_t(std::acos(x()));
return angle::radian_t(gcem::acos(x()));
}
#endif
@@ -134,11 +136,11 @@ angle::radian_t acos(const ScalarUnit x) noexcept {
*/
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
template <class ScalarUnit>
angle::radian_t asin(const ScalarUnit x) noexcept {
constexpr angle::radian_t asin(const ScalarUnit x) noexcept {
static_assert(
traits::is_dimensionless_unit<ScalarUnit>::value,
"Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
return angle::radian_t(std::asin(x()));
return angle::radian_t(gcem::asin(x()));
}
#endif
@@ -156,11 +158,11 @@ angle::radian_t asin(const ScalarUnit x) noexcept {
*/
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
template <class ScalarUnit>
angle::radian_t atan(const ScalarUnit x) noexcept {
constexpr angle::radian_t atan(const ScalarUnit x) noexcept {
static_assert(
traits::is_dimensionless_unit<ScalarUnit>::value,
"Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
return angle::radian_t(std::atan(x()));
return angle::radian_t(gcem::atan(x()));
}
#endif
@@ -176,15 +178,15 @@ angle::radian_t atan(const ScalarUnit x) noexcept {
*/
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
template <class Y, class X>
angle::radian_t atan2(const Y y, const X x) noexcept {
constexpr angle::radian_t atan2(const Y y, const X x) noexcept {
static_assert(traits::is_dimensionless_unit<decltype(y / x)>::value,
"The quantity y/x must yield a dimensionless ratio.");
// X and Y could be different length units, so normalize them
return angle::radian_t(
std::atan2(y.template convert<
typename units::traits::unit_t_traits<X>::unit_type>()(),
x()));
gcem::atan2(y.template convert<
typename units::traits::unit_t_traits<X>::unit_type>()(),
x()));
}
#endif
@@ -203,12 +205,12 @@ angle::radian_t atan2(const Y y, const X x) noexcept {
*/
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
template <class AngleUnit>
dimensionless::scalar_t cosh(const AngleUnit angle) noexcept {
constexpr dimensionless::scalar_t cosh(const AngleUnit angle) noexcept {
static_assert(
traits::is_angle_unit<AngleUnit>::value,
"Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
return dimensionless::scalar_t(
std::cosh(angle.template convert<angle::radian>()()));
gcem::cosh(angle.template convert<angle::radian>()()));
}
#endif
@@ -223,12 +225,12 @@ dimensionless::scalar_t cosh(const AngleUnit angle) noexcept {
*/
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
template <class AngleUnit>
dimensionless::scalar_t sinh(const AngleUnit angle) noexcept {
constexpr dimensionless::scalar_t sinh(const AngleUnit angle) noexcept {
static_assert(
traits::is_angle_unit<AngleUnit>::value,
"Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
return dimensionless::scalar_t(
std::sinh(angle.template convert<angle::radian>()()));
gcem::sinh(angle.template convert<angle::radian>()()));
}
#endif
@@ -243,12 +245,12 @@ dimensionless::scalar_t sinh(const AngleUnit angle) noexcept {
*/
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
template <class AngleUnit>
dimensionless::scalar_t tanh(const AngleUnit angle) noexcept {
constexpr dimensionless::scalar_t tanh(const AngleUnit angle) noexcept {
static_assert(
traits::is_angle_unit<AngleUnit>::value,
"Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
return dimensionless::scalar_t(
std::tanh(angle.template convert<angle::radian>()()));
gcem::tanh(angle.template convert<angle::radian>()()));
}
#endif
@@ -264,11 +266,11 @@ dimensionless::scalar_t tanh(const AngleUnit angle) noexcept {
*/
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
template <class ScalarUnit>
angle::radian_t acosh(const ScalarUnit x) noexcept {
constexpr angle::radian_t acosh(const ScalarUnit x) noexcept {
static_assert(
traits::is_dimensionless_unit<ScalarUnit>::value,
"Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
return angle::radian_t(std::acosh(x()));
return angle::radian_t(gcem::acosh(x()));
}
#endif
@@ -281,11 +283,11 @@ angle::radian_t acosh(const ScalarUnit x) noexcept {
*/
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
template <class ScalarUnit>
angle::radian_t asinh(const ScalarUnit x) noexcept {
constexpr angle::radian_t asinh(const ScalarUnit x) noexcept {
static_assert(
traits::is_dimensionless_unit<ScalarUnit>::value,
"Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
return angle::radian_t(std::asinh(x()));
return angle::radian_t(gcem::asinh(x()));
}
#endif
@@ -300,11 +302,11 @@ angle::radian_t asinh(const ScalarUnit x) noexcept {
*/
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
template <class ScalarUnit>
angle::radian_t atanh(const ScalarUnit x) noexcept {
constexpr angle::radian_t atanh(const ScalarUnit x) noexcept {
static_assert(
traits::is_dimensionless_unit<ScalarUnit>::value,
"Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
return angle::radian_t(std::atanh(x()));
return angle::radian_t(gcem::atanh(x()));
}
#endif
@@ -329,11 +331,11 @@ angle::radian_t atanh(const ScalarUnit x) noexcept {
* error occurs.
*/
template <class ScalarUnit>
dimensionless::scalar_t exp(const ScalarUnit x) noexcept {
constexpr dimensionless::scalar_t exp(const ScalarUnit x) noexcept {
static_assert(
traits::is_dimensionless_unit<ScalarUnit>::value,
"Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
return dimensionless::scalar_t(std::exp(x()));
return dimensionless::scalar_t(gcem::exp(x()));
}
/**
@@ -346,11 +348,11 @@ dimensionless::scalar_t exp(const ScalarUnit x) noexcept {
* @returns Natural logarithm of x.
*/
template <class ScalarUnit>
dimensionless::scalar_t log(const ScalarUnit x) noexcept {
constexpr dimensionless::scalar_t log(const ScalarUnit x) noexcept {
static_assert(
traits::is_dimensionless_unit<ScalarUnit>::value,
"Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
return dimensionless::scalar_t(std::log(x()));
return dimensionless::scalar_t(gcem::log(x()));
}
/**
@@ -362,11 +364,11 @@ dimensionless::scalar_t log(const ScalarUnit x) noexcept {
* @returns Common logarithm of x.
*/
template <class ScalarUnit>
dimensionless::scalar_t log10(const ScalarUnit x) noexcept {
constexpr dimensionless::scalar_t log10(const ScalarUnit x) noexcept {
static_assert(
traits::is_dimensionless_unit<ScalarUnit>::value,
"Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
return dimensionless::scalar_t(std::log10(x()));
return dimensionless::scalar_t(gcem::log10(x()));
}
/**
@@ -417,11 +419,11 @@ dimensionless::scalar_t exp2(const ScalarUnit x) noexcept {
* @returns e raised to the power of x, minus one.
*/
template <class ScalarUnit>
dimensionless::scalar_t expm1(const ScalarUnit x) noexcept {
constexpr dimensionless::scalar_t expm1(const ScalarUnit x) noexcept {
static_assert(
traits::is_dimensionless_unit<ScalarUnit>::value,
"Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
return dimensionless::scalar_t(std::expm1(x()));
return dimensionless::scalar_t(gcem::expm1(x()));
}
/**
@@ -434,11 +436,11 @@ dimensionless::scalar_t expm1(const ScalarUnit x) noexcept {
* @returns The natural logarithm of (1+x).
*/
template <class ScalarUnit>
dimensionless::scalar_t log1p(const ScalarUnit x) noexcept {
constexpr dimensionless::scalar_t log1p(const ScalarUnit x) noexcept {
static_assert(
traits::is_dimensionless_unit<ScalarUnit>::value,
"Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
return dimensionless::scalar_t(std::log1p(x()));
return dimensionless::scalar_t(gcem::log1p(x()));
}
/**
@@ -450,11 +452,11 @@ dimensionless::scalar_t log1p(const ScalarUnit x) noexcept {
* @returns The binary logarithm of x: log2x.
*/
template <class ScalarUnit>
dimensionless::scalar_t log2(const ScalarUnit x) noexcept {
constexpr dimensionless::scalar_t log2(const ScalarUnit x) noexcept {
static_assert(
traits::is_dimensionless_unit<ScalarUnit>::value,
"Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
return dimensionless::scalar_t(std::log2(x()));
return dimensionless::scalar_t(gcem::log2(x()));
}
//----------------------------------
@@ -480,14 +482,15 @@ dimensionless::scalar_t log2(const ScalarUnit x) noexcept {
template <
class UnitType,
std::enable_if_t<units::traits::has_linear_scale<UnitType>::value, int> = 0>
inline 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> {
inline 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> {
return unit_t<
square_root<typename units::traits::unit_t_traits<UnitType>::unit_type>,
typename units::traits::unit_t_traits<UnitType>::underlying_type,
linear_scale>(std::sqrt(value()));
linear_scale>(gcem::sqrt(value()));
}
/**
@@ -502,10 +505,10 @@ template <class UnitTypeLhs, class UnitTypeRhs,
std::enable_if_t<
units::traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value,
int> = 0>
inline UnitTypeLhs hypot(const UnitTypeLhs& x, const UnitTypeRhs& y) {
inline constexpr UnitTypeLhs hypot(const UnitTypeLhs& x, const UnitTypeRhs& y) {
static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value,
"Parameters of hypot() function are not compatible units.");
return UnitTypeLhs(std::hypot(
return UnitTypeLhs(gcem::hypot(
x(),
y.template convert<
typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
@@ -525,8 +528,8 @@ inline UnitTypeLhs hypot(const UnitTypeLhs& x, const UnitTypeRhs& y) {
*/
template <class UnitType,
class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
UnitType ceil(const UnitType x) noexcept {
return UnitType(std::ceil(x()));
constexpr UnitType ceil(const UnitType x) noexcept {
return UnitType(gcem::ceil(x()));
}
/**
@@ -539,8 +542,8 @@ UnitType ceil(const UnitType x) noexcept {
*/
template <class UnitType,
class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
UnitType floor(const UnitType x) noexcept {
return UnitType(std::floor(x()));
constexpr UnitType floor(const UnitType x) noexcept {
return UnitType(gcem::floor(x()));
}
/**
@@ -555,10 +558,11 @@ UnitType floor(const UnitType x) noexcept {
template <class UnitTypeLhs, class UnitTypeRhs,
class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value &&
traits::is_unit_t<UnitTypeRhs>::value>>
UnitTypeLhs fmod(const UnitTypeLhs numer, const UnitTypeRhs denom) noexcept {
constexpr UnitTypeLhs fmod(const UnitTypeLhs numer,
const UnitTypeRhs denom) noexcept {
static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value,
"Parameters of fmod() function are not compatible units.");
return UnitTypeLhs(std::fmod(
return UnitTypeLhs(gcem::fmod(
numer(),
denom.template convert<
typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
@@ -574,8 +578,8 @@ UnitTypeLhs fmod(const UnitTypeLhs numer, const UnitTypeRhs denom) noexcept {
*/
template <class UnitType,
class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
UnitType trunc(const UnitType x) noexcept {
return UnitType(std::trunc(x()));
constexpr UnitType trunc(const UnitType x) noexcept {
return UnitType(gcem::trunc(x()));
}
/**
@@ -588,8 +592,8 @@ UnitType trunc(const UnitType x) noexcept {
*/
template <class UnitType,
class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
UnitType round(const UnitType x) noexcept {
return UnitType(std::round(x()));
constexpr UnitType round(const UnitType x) noexcept {
return UnitType(gcem::round(x()));
}
//----------------------------------
@@ -608,17 +612,18 @@ UnitType round(const UnitType x) noexcept {
template <class UnitTypeLhs, class UnitTypeRhs,
class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value &&
traits::is_unit_t<UnitTypeRhs>::value>>
UnitTypeLhs copysign(const UnitTypeLhs x, const UnitTypeRhs y) noexcept {
return UnitTypeLhs(std::copysign(
constexpr UnitTypeLhs copysign(const UnitTypeLhs x,
const UnitTypeRhs y) noexcept {
return UnitTypeLhs(gcem::copysign(
x(), y())); // no need for conversion to get the correct sign.
}
/// Overload to copy the sign from a raw double
template <class UnitTypeLhs,
class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value>>
UnitTypeLhs copysign(const UnitTypeLhs x,
const UNIT_LIB_DEFAULT_TYPE y) noexcept {
return UnitTypeLhs(std::copysign(x(), y));
constexpr UnitTypeLhs copysign(const UnitTypeLhs x,
const UNIT_LIB_DEFAULT_TYPE y) noexcept {
return UnitTypeLhs(gcem::copysign(x(), y));
}
//----------------------------------
@@ -660,10 +665,10 @@ UnitTypeLhs fdim(const UnitTypeLhs x, const UnitTypeRhs y) noexcept {
template <class UnitTypeLhs, class UnitTypeRhs,
class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value &&
traits::is_unit_t<UnitTypeRhs>::value>>
UnitTypeLhs fmax(const UnitTypeLhs x, const UnitTypeRhs y) noexcept {
constexpr UnitTypeLhs fmax(const UnitTypeLhs x, const UnitTypeRhs y) noexcept {
static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value,
"Parameters of fmax() function are not compatible units.");
return UnitTypeLhs(std::fmax(
return UnitTypeLhs(gcem::max<double, double>(
x(),
y.template convert<
typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
@@ -683,10 +688,10 @@ UnitTypeLhs fmax(const UnitTypeLhs x, const UnitTypeRhs y) noexcept {
template <class UnitTypeLhs, class UnitTypeRhs,
class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value &&
traits::is_unit_t<UnitTypeRhs>::value>>
UnitTypeLhs fmin(const UnitTypeLhs x, const UnitTypeRhs y) noexcept {
constexpr UnitTypeLhs fmin(const UnitTypeLhs x, const UnitTypeRhs y) noexcept {
static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value,
"Parameters of fmin() function are not compatible units.");
return UnitTypeLhs(std::fmin(
return UnitTypeLhs(gcem::min<double, double>(
x(),
y.template convert<
typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
@@ -705,8 +710,8 @@ UnitTypeLhs fmin(const UnitTypeLhs x, const UnitTypeRhs y) noexcept {
*/
template <class UnitType,
class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
UnitType fabs(const UnitType x) noexcept {
return UnitType(std::fabs(x()));
constexpr UnitType fabs(const UnitType x) noexcept {
return UnitType(gcem::abs(x()));
}
/**
@@ -718,8 +723,8 @@ UnitType fabs(const UnitType x) noexcept {
*/
template <class UnitType,
class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
UnitType abs(const UnitType x) noexcept {
return UnitType(std::fabs(x()));
constexpr UnitType abs(const UnitType x) noexcept {
return UnitType(gcem::abs(x()));
}
/**
@@ -737,8 +742,8 @@ template <class UnitTypeLhs, class UnitMultiply, class UnitAdd,
class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value &&
traits::is_unit_t<UnitMultiply>::value &&
traits::is_unit_t<UnitAdd>::value>>
auto fma(const UnitTypeLhs x, const UnitMultiply y, const UnitAdd z) noexcept
-> decltype(x * y) {
auto fma(const UnitTypeLhs x, const UnitMultiply y,
const UnitAdd z) noexcept -> decltype(x * y) {
using resultType = decltype(x * y);
static_assert(
traits::is_convertible_unit_t<