1#ifndef LIBSBX_MATH_ANGLE_HPP_
2#define LIBSBX_MATH_ANGLE_HPP_
8#include <libsbx/math/concepts.hpp>
9#include <libsbx/math/smooth_value.hpp>
13template<
floating_po
int Type>
18 using value_type = Type;
21 inline static constexpr basic_degree max{value_type{360}};
25 template<scalar Other>
26 requires (std::is_convertible_v<Other, Type>)
28 : _value{
static_cast<Type
>(value)} { }
30 template<
floating_po
int Other>
31 requires (std::is_convertible_v<Other, Type>)
33 : _value{
static_cast<Type
>(other._value)} { }
37 template<
floating_po
int Other>
38 requires (std::is_convertible_v<Other, Type>)
40 _value =
static_cast<Type
>(other._value);
45 template<
floating_po
int Other>
46 requires (std::is_convertible_v<Other, Type>)
48 _value +=
static_cast<Type
>(rhs._value);
53 template<
floating_po
int Other>
54 requires (std::is_convertible_v<Other, Type>)
56 _value -=
static_cast<Type
>(rhs._value);
61 template<
floating_po
int Other>
62 requires (std::is_convertible_v<Other, Type>)
64 _value *=
static_cast<Type
>(rhs);
69 template<
floating_po
int Other>
70 requires (std::is_convertible_v<Other, Type>)
72 _value /=
static_cast<Type
>(rhs);
77 constexpr auto value()
const noexcept -> value_type {
81 constexpr operator value_type()
const noexcept {
85 constexpr auto data()
noexcept -> value_type* {
95template<
floating_po
int Type>
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>
101constexpr auto operator<=>(
const basic_degree<Type>& lhs,
const basic_degree<Other>& rhs)
noexcept -> std::partial_ordering {
102 return static_cast<basic_degree<Type>::value_type
>(lhs) <=>
static_cast<basic_degree<Type>::value_type
>(rhs);
105template<
floating_po
int Type,
floating_po
int Other>
106requires (std::is_convertible_v<Other, Type>)
107constexpr auto operator+(basic_degree<Type> lhs,
const basic_degree<Other>& rhs)
noexcept -> basic_degree<Type> {
111template<
floating_po
int Type,
floating_po
int Other>
112requires (std::is_convertible_v<Other, Type>)
113constexpr auto operator-(basic_degree<Type> lhs,
const basic_degree<Other>& rhs)
noexcept -> basic_degree<Type> {
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, std::convertible_to<Type> Other>
123constexpr auto operator/(basic_degree<Type> lhs,
const Other rhs)
noexcept -> basic_degree<Type> {
124 return lhs /=
static_cast<Type
>(rhs);
127template<
floating_po
int Type>
128constexpr auto clamp(
const basic_degree<Type>& value,
const basic_degree<Type>& min,
const basic_degree<Type>& max) ->
const basic_degree<Type>& {
140using degree = basic_degree<std::float_t>;
142template<
floating_po
int Type>
145template<
floating_po
int Type>
151 return base_trait::equal(lhs.value(), rhs.value());
156template<
floating_po
int Type>
161template<
floating_po
int Type>
166 using value_type = Type;
168 inline static constexpr basic_radian min{value_type{0}};
169 inline static constexpr basic_radian max{value_type{2 * std::numbers::pi_v<value_type>}};
173 template<scalar Other>
174 requires (std::is_convertible_v<Other, Type>)
176 : _value{
static_cast<Type
>(value)} { }
178 template<
floating_po
int Other>
179 requires (std::is_convertible_v<Other, Type>)
181 : _value{
static_cast<Type
>(other._value)} { }
185 template<
floating_po
int Other>
186 requires (std::is_convertible_v<Other, Type>)
188 _value =
static_cast<Type
>(other._value);
193 template<
floating_po
int Other>
194 requires (std::is_convertible_v<Other, Type>)
196 _value +=
static_cast<Type
>(rhs._value);
201 template<
floating_po
int Other>
202 requires (std::is_convertible_v<Other, Type>)
204 _value -=
static_cast<Type
>(rhs._value);
209 template<
floating_po
int Other>
210 requires (std::is_convertible_v<Other, Type>)
212 _value *=
static_cast<Type
>(rhs);
217 constexpr auto value()
const noexcept -> value_type {
221 constexpr operator value_type()
const noexcept {
225 constexpr auto data()
noexcept -> value_type* {
235template<
floating_po
int Type>
237 return static_cast<basic_radian<Type>::value_type
>(lhs) ==
static_cast<basic_radian<Type>::value_type
>(rhs);
240template<
floating_po
int Type,
floating_po
int Other>
241constexpr auto operator<=>(
const basic_radian<Type>& lhs,
const basic_radian<Other>& rhs)
noexcept -> std::partial_ordering {
242 return static_cast<basic_radian<Type>::value_type
>(lhs) <=>
static_cast<basic_radian<Type>::value_type
>(rhs);
245template<
floating_po
int Type,
floating_po
int Other>
246requires (std::is_convertible_v<Other, Type>)
247constexpr auto operator+(basic_radian<Type> lhs,
const basic_radian<Other>& rhs)
noexcept -> basic_radian<Type> {
251template<
floating_po
int Type,
floating_po
int Other>
252requires (std::is_convertible_v<Other, Type>)
253constexpr auto operator-(basic_radian<Type> lhs,
const basic_radian<Other>& rhs)
noexcept -> basic_radian<Type> {
257template<
floating_po
int Type, std::convertible_to<Type> Other>
258requires (std::is_convertible_v<Other, Type>)
259constexpr auto operator*(basic_radian<Type> lhs,
const Other rhs)
noexcept -> basic_radian<Type> {
260 return lhs *=
static_cast<Type
>(rhs);
263template<
floating_po
int Type>
264constexpr auto clamp(
const basic_radian<Type>& value,
const basic_radian<Type>& min,
const basic_radian<Type>& max) ->
const basic_radian<Type>& {
276using radian = basic_radian<std::float_t>;
278template<
floating_po
int Type>
283 using value_type = Type;
286 : _radian{
degree.value() * std::numbers::pi_v<value_type> /
static_cast<value_type
>(180)} {}
291 template<
floating_po
int Other>
292 requires (std::is_convertible_v<Other, Type>)
294 : _radian{other._radian} { }
296 template<
floating_po
int Other>
297 requires (std::is_convertible_v<Other, Type>)
304 template<
floating_po
int Other>
305 requires (std::is_convertible_v<Other, Type>)
310 template<
floating_po
int Other>
311 requires (std::is_convertible_v<Other, Type>)
316 template<
floating_po
int Other>
317 requires (std::is_convertible_v<Other, Type>)
324 template<
floating_po
int Other>
325 requires (std::is_convertible_v<Other, Type>)
330 template<
floating_po
int Other>
331 requires (std::is_convertible_v<Other, Type>)
336 template<
floating_po
int Other>
337 requires (std::is_convertible_v<Other, Type>)
358template<
floating_po
int Type>
360 return lhs.to_radians() == rhs.to_radians();
363template<
floating_po
int Type,
floating_po
int Other>
364constexpr auto operator<=>(
const basic_angle<Type>& lhs,
const basic_angle<Other>& rhs)
noexcept -> std::partial_ordering {
365 return lhs.to_radians() <=> rhs.to_radians();
368template<
floating_po
int LhsType,
floating_po
int RhsType>
369requires (std::is_convertible_v<RhsType, LhsType>)
370constexpr auto operator+(basic_angle<LhsType> lhs,
const basic_angle<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
374template<
floating_po
int LhsType,
floating_po
int RhsType>
375requires (std::is_convertible_v<RhsType, LhsType>)
376constexpr auto operator+(basic_angle<LhsType> lhs,
const basic_degree<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
377 return lhs += basic_angle<LhsType>(rhs);
380template<
floating_po
int LhsType,
floating_po
int RhsType>
381requires (std::is_convertible_v<RhsType, LhsType>)
382constexpr auto operator+(basic_angle<LhsType> lhs,
const basic_radian<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
383 return lhs += basic_angle<LhsType>(rhs);
386template<
floating_po
int LhsType,
floating_po
int RhsType>
387requires (std::is_convertible_v<RhsType, LhsType>)
388constexpr auto operator-(basic_angle<LhsType> lhs,
const basic_angle<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
392template<
floating_po
int LhsType,
floating_po
int RhsType>
393requires (std::is_convertible_v<RhsType, LhsType>)
394constexpr auto operator-(basic_angle<LhsType> lhs,
const basic_degree<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
395 return lhs -= basic_angle<LhsType>(rhs);
398template<
floating_po
int LhsType,
floating_po
int RhsType>
399requires (std::is_convertible_v<RhsType, LhsType>)
400constexpr auto operator-(basic_angle<LhsType> lhs,
const basic_radian<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
401 return lhs -= basic_angle<LhsType>(rhs);
404template<
floating_po
int LhsType,
floating_po
int RhsType>
405requires (std::is_convertible_v<RhsType, LhsType>)
406constexpr auto operator*(basic_angle<LhsType> lhs,
const RhsType rhs)
noexcept -> basic_angle<LhsType> {
410template<
floating_po
int Type>
411constexpr auto clamp(
const basic_angle<Type>& value,
const basic_angle<Type>& min,
const basic_angle<Type>& max) ->
const basic_angle<Type>& {
423using angle = basic_angle<std::float_t>;
425template<
floating_po
int Type>
426constexpr auto to_degrees(
const basic_radian<Type>& radian)
noexcept -> basic_degree<Type> {
427 return basic_angle<Type>{radian}.to_degrees();
430template<
floating_po
int Type>
431constexpr auto to_radians(
const basic_degree<Type>& degree)
noexcept -> basic_radian<Type> {
432 return basic_angle<Type>{degree}.to_radians();
435template<
floating_po
int Type>
436constexpr auto sin(
const basic_angle<Type>& angle)
noexcept -> Type {
437 return std::sin(angle.to_radians().value());
440template<
floating_po
int Type>
441constexpr auto sin(
const basic_degree<Type>& degree)
noexcept -> Type {
442 return sin(basic_angle<Type>{degree});
445template<
floating_po
int Type>
446constexpr auto sin(
const basic_radian<Type>& radian)
noexcept -> Type {
447 return sin(basic_angle<Type>{radian});
450template<
floating_po
int Type>
451constexpr auto cos(
const basic_angle<Type>& angle)
noexcept -> Type {
452 return std::cos(angle.to_radians().value());
455template<
floating_po
int Type>
456constexpr auto cos(
const basic_degree<Type>& degree)
noexcept -> Type {
457 return cos(basic_angle<Type>{degree});
460template<
floating_po
int Type>
461constexpr auto cos(
const basic_radian<Type>& radian)
noexcept -> Type {
462 return cos(basic_angle<Type>{radian});
465template<
floating_po
int Type>
466constexpr auto tan(
const basic_angle<Type>& angle)
noexcept -> Type {
467 return std::tan(angle.to_radians().value());
472constexpr auto operator""_deg(
long double value)
noexcept -> degree {
473 return degree{
static_cast<std::float_t
>(value)};
476constexpr auto operator""_deg(
unsigned long long value)
noexcept -> degree {
477 return degree{
static_cast<std::float_t
>(value)};
480constexpr auto operator""_rad(
long double value)
noexcept -> radian {
481 return radian{
static_cast<std::float_t
>(value)};
484constexpr auto operator""_rad(
unsigned long long value)
noexcept -> radian {
485 return radian{
static_cast<std::float_t
>(value)};
Definition: angle.hpp:279
Definition: angle.hpp:162
Definition: traits.hpp:13
Definition: traits.hpp:10
Definition: smooth_value.hpp:25