1#ifndef LIBSBX_MATH_ANGLE_HPP_
2#define LIBSBX_MATH_ANGLE_HPP_
8#include <libsbx/math/concepts.hpp>
12template<
floating_po
int Type>
17 using value_type = Type;
20 inline static constexpr basic_degree max{value_type{360}};
24 template<scalar Other>
25 requires (std::is_convertible_v<Other, Type>)
27 : _value{
static_cast<Type
>(value)} { }
29 template<
floating_po
int Other>
30 requires (std::is_convertible_v<Other, Type>)
32 : _value{
static_cast<Type
>(other._value)} { }
36 template<
floating_po
int Other>
37 requires (std::is_convertible_v<Other, Type>)
39 _value =
static_cast<Type
>(other._value);
44 template<
floating_po
int Other>
45 requires (std::is_convertible_v<Other, Type>)
47 _value +=
static_cast<Type
>(rhs._value);
52 template<
floating_po
int Other>
53 requires (std::is_convertible_v<Other, Type>)
55 _value -=
static_cast<Type
>(rhs._value);
60 template<
floating_po
int Other>
61 requires (std::is_convertible_v<Other, Type>)
63 _value *=
static_cast<Type
>(rhs);
68 template<
floating_po
int Other>
69 requires (std::is_convertible_v<Other, Type>)
71 _value /=
static_cast<Type
>(rhs);
76 constexpr auto value()
const noexcept -> value_type {
80 constexpr operator value_type()
const noexcept {
90template<
floating_po
int Type>
92 return static_cast<basic_degree<Type>::value_type
>(lhs) ==
static_cast<basic_degree<Type>::value_type
>(rhs);
95template<
floating_po
int Type,
floating_po
int Other>
96constexpr auto operator<=>(
const basic_degree<Type>& lhs,
const basic_degree<Other>& rhs)
noexcept -> std::partial_ordering {
97 return static_cast<basic_degree<Type>::value_type
>(lhs) <=>
static_cast<basic_degree<Type>::value_type
>(rhs);
100template<
floating_po
int Type,
floating_po
int Other>
101requires (std::is_convertible_v<Other, Type>)
102constexpr auto operator+(basic_degree<Type> lhs,
const basic_degree<Other>& rhs)
noexcept -> basic_degree<Type> {
106template<
floating_po
int Type,
floating_po
int Other>
107requires (std::is_convertible_v<Other, Type>)
108constexpr auto operator-(basic_degree<Type> lhs,
const basic_degree<Other>& rhs)
noexcept -> basic_degree<Type> {
112template<
floating_po
int Type, std::convertible_to<Type> Other>
113constexpr auto operator*(basic_degree<Type> lhs,
const Other rhs)
noexcept -> basic_degree<Type> {
114 return lhs *=
static_cast<Type
>(rhs);
117template<
floating_po
int Type, std::convertible_to<Type> Other>
118constexpr auto operator/(basic_degree<Type> lhs,
const Other rhs)
noexcept -> basic_degree<Type> {
119 return lhs /=
static_cast<Type
>(rhs);
122template<
floating_po
int Type>
123constexpr auto clamp(
const basic_degree<Type>& value,
const basic_degree<Type>& min,
const basic_degree<Type>& max) ->
const basic_degree<Type>& {
135using degree = basic_degree<std::float_t>;
137template<
floating_po
int Type>
142 using value_type = Type;
144 inline static constexpr basic_radian min{value_type{0}};
145 inline static constexpr basic_radian max{value_type{2 * std::numbers::pi_v<value_type>}};
149 template<scalar Other>
150 requires (std::is_convertible_v<Other, Type>)
152 : _value{
static_cast<Type
>(value)} { }
154 template<
floating_po
int Other>
155 requires (std::is_convertible_v<Other, Type>)
157 : _value{
static_cast<Type
>(other._value)} { }
161 template<
floating_po
int Other>
162 requires (std::is_convertible_v<Other, Type>)
164 _value =
static_cast<Type
>(other._value);
169 template<
floating_po
int Other>
170 requires (std::is_convertible_v<Other, Type>)
172 _value +=
static_cast<Type
>(rhs._value);
177 template<
floating_po
int Other>
178 requires (std::is_convertible_v<Other, Type>)
180 _value -=
static_cast<Type
>(rhs._value);
185 template<
floating_po
int Other>
186 requires (std::is_convertible_v<Other, Type>)
188 _value *=
static_cast<Type
>(rhs);
193 constexpr auto value()
const noexcept -> value_type {
197 constexpr operator value_type()
const noexcept {
207template<
floating_po
int Type>
209 return static_cast<basic_radian<Type>::value_type
>(lhs) ==
static_cast<basic_radian<Type>::value_type
>(rhs);
212template<
floating_po
int Type,
floating_po
int Other>
213constexpr auto operator<=>(
const basic_radian<Type>& lhs,
const basic_radian<Other>& rhs)
noexcept -> std::partial_ordering {
214 return static_cast<basic_radian<Type>::value_type
>(lhs) <=>
static_cast<basic_radian<Type>::value_type
>(rhs);
217template<
floating_po
int Type,
floating_po
int Other>
218requires (std::is_convertible_v<Other, Type>)
219constexpr auto operator+(basic_radian<Type> lhs,
const basic_radian<Other>& rhs)
noexcept -> basic_radian<Type> {
223template<
floating_po
int Type,
floating_po
int Other>
224requires (std::is_convertible_v<Other, Type>)
225constexpr auto operator-(basic_radian<Type> lhs,
const basic_radian<Other>& rhs)
noexcept -> basic_radian<Type> {
229template<
floating_po
int Type, std::convertible_to<Type> Other>
230requires (std::is_convertible_v<Other, Type>)
231constexpr auto operator*(basic_radian<Type> lhs,
const Other rhs)
noexcept -> basic_radian<Type> {
232 return lhs *=
static_cast<Type
>(rhs);
235template<
floating_po
int Type>
236constexpr auto clamp(
const basic_radian<Type>& value,
const basic_radian<Type>& min,
const basic_radian<Type>& max) ->
const basic_radian<Type>& {
248using radian = basic_radian<std::float_t>;
250template<
floating_po
int Type>
255 using value_type = Type;
258 : _radian{
degree.value() * std::numbers::pi_v<value_type> /
static_cast<value_type
>(180)} {}
263 template<
floating_po
int Other>
264 requires (std::is_convertible_v<Other, Type>)
266 : _radian{other._radian} { }
268 template<
floating_po
int Other>
269 requires (std::is_convertible_v<Other, Type>)
276 template<
floating_po
int Other>
277 requires (std::is_convertible_v<Other, Type>)
282 template<
floating_po
int Other>
283 requires (std::is_convertible_v<Other, Type>)
288 template<
floating_po
int Other>
289 requires (std::is_convertible_v<Other, Type>)
296 template<
floating_po
int Other>
297 requires (std::is_convertible_v<Other, Type>)
302 template<
floating_po
int Other>
303 requires (std::is_convertible_v<Other, Type>)
308 template<
floating_po
int Other>
309 requires (std::is_convertible_v<Other, Type>)
330template<
floating_po
int Type>
332 return lhs.to_radians() == rhs.to_radians();
335template<
floating_po
int Type,
floating_po
int Other>
336constexpr auto operator<=>(
const basic_angle<Type>& lhs,
const basic_angle<Other>& rhs)
noexcept -> std::partial_ordering {
337 return lhs.to_radians() <=> rhs.to_radians();
340template<
floating_po
int LhsType,
floating_po
int RhsType>
341requires (std::is_convertible_v<RhsType, LhsType>)
342constexpr auto operator+(basic_angle<LhsType> lhs,
const basic_angle<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
346template<
floating_po
int LhsType,
floating_po
int RhsType>
347requires (std::is_convertible_v<RhsType, LhsType>)
348constexpr auto operator+(basic_angle<LhsType> lhs,
const basic_degree<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
349 return lhs += basic_angle<LhsType>(rhs);
352template<
floating_po
int LhsType,
floating_po
int RhsType>
353requires (std::is_convertible_v<RhsType, LhsType>)
354constexpr auto operator+(basic_angle<LhsType> lhs,
const basic_radian<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
355 return lhs += basic_angle<LhsType>(rhs);
358template<
floating_po
int LhsType,
floating_po
int RhsType>
359requires (std::is_convertible_v<RhsType, LhsType>)
360constexpr auto operator-(basic_angle<LhsType> lhs,
const basic_angle<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
364template<
floating_po
int LhsType,
floating_po
int RhsType>
365requires (std::is_convertible_v<RhsType, LhsType>)
366constexpr auto operator*(basic_angle<LhsType> lhs,
const RhsType rhs)
noexcept -> basic_angle<LhsType> {
370template<
floating_po
int Type>
371constexpr auto clamp(
const basic_angle<Type>& value,
const basic_angle<Type>& min,
const basic_angle<Type>& max) ->
const basic_angle<Type>& {
383using angle = basic_angle<std::float_t>;
385template<
floating_po
int Type>
386constexpr auto to_degrees(
const basic_radian<Type>& radian)
noexcept -> basic_degree<Type> {
387 return basic_angle<Type>{radian}.to_degrees();
390template<
floating_po
int Type>
391constexpr auto to_radians(
const basic_degree<Type>& degree)
noexcept -> basic_radian<Type> {
392 return basic_angle<Type>{degree}.to_radians();
397constexpr auto operator""_deg(
long double value)
noexcept -> degree {
398 return degree{
static_cast<std::float_t
>(value)};
401constexpr auto operator""_deg(
unsigned long long value)
noexcept -> degree {
402 return degree{
static_cast<std::float_t
>(value)};
405constexpr auto operator""_rad(
long double value)
noexcept -> radian {
406 return radian{
static_cast<std::float_t
>(value)};
409constexpr auto operator""_rad(
unsigned long long value)
noexcept -> radian {
410 return radian{
static_cast<std::float_t
>(value)};
Definition: angle.hpp:251
Definition: angle.hpp:138