-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathangle.h
153 lines (125 loc) · 5.05 KB
/
angle.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//
// Created by Vincent on 04/12/2019.
//
#ifndef ANGLE_ANGLE_H
#define ANGLE_ANGLE_H
#include <concepts>
#include <cmath>
namespace ang {
template<typename T> concept floating_point = std::is_floating_point_v<T>;
constexpr double m_pi = 3.14159265358979323846;
constexpr double m_2pi = 2 * m_pi;
template<floating_point rep>
rep wrap_fp(rep val) noexcept {
return -m_pi + std::fmod(m_2pi + std::fmod(val + m_pi, m_2pi), m_2pi);
}
template<floating_point rep, auto wrap>
class basic_angle {
rep value; // [-pi, pi)
public:
constexpr basic_angle() = default;
constexpr explicit basic_angle(rep value) noexcept(std::is_arithmetic_v<rep>)
: value(wrap(value)) {};
constexpr basic_angle &operator+=(const basic_angle &o) noexcept(std::is_arithmetic_v<rep>) {
value = wrap(value + o.value);
return *this;
}
constexpr basic_angle &operator-=(const basic_angle &o) noexcept(std::is_arithmetic_v<rep>) {
value = wrap(value - o.value);
return *this;
}
constexpr basic_angle &operator*=(const rep &o) noexcept(std::is_arithmetic_v<rep>) {
value = wrap(value * o);
return *this;
}
constexpr basic_angle &operator/=(const rep &o) noexcept(std::is_arithmetic_v<rep>) {
value = wrap(value / o);
return *this;
}
[[nodiscard]] constexpr rep radians() const noexcept(std::is_arithmetic_v<rep>) {
return value;
}
[[nodiscard]] constexpr rep degrees() const noexcept(std::is_arithmetic_v<rep>) {
return value * 180.0 / m_pi;
}
};
template<floating_point rep, auto wrap>
[[nodiscard]] constexpr basic_angle<rep, wrap>
operator+(basic_angle<rep, wrap> l, const basic_angle<rep, wrap> &r) noexcept(std::is_arithmetic_v<rep>) {
l += r;
return l;
}
template<floating_point rep, auto wrap>
[[nodiscard]] constexpr basic_angle<rep, wrap>
operator-(basic_angle<rep, wrap> l, const basic_angle<rep, wrap> &r) noexcept(std::is_arithmetic_v<rep>) {
l -= r;
return l;
}
template<floating_point rep, auto wrap>
[[nodiscard]] constexpr basic_angle<rep, wrap>
operator-(const basic_angle<rep, wrap> &r) noexcept(std::is_arithmetic_v<rep>) {
return basic_angle<rep, wrap>(-r.radians());
}
template<floating_point rep, auto wrap>
[[nodiscard]] constexpr basic_angle<rep, wrap>
operator*(basic_angle<rep, wrap> l, const rep &r) noexcept(std::is_arithmetic_v<rep>) {
l *= r;
return l;
}
template<floating_point rep, auto wrap>
[[nodiscard]] constexpr basic_angle<rep, wrap>
operator*(const rep &l, const basic_angle<rep, wrap> &r) noexcept(std::is_arithmetic_v<rep>) {
return basic_angle<rep, wrap>(l * r.radians());
}
template<floating_point rep, auto wrap>
[[nodiscard]] constexpr basic_angle<rep, wrap>
operator/(basic_angle<rep, wrap> l, const rep &r) noexcept(std::is_arithmetic_v<rep>) {
l /= r;
return l;
}
template<floating_point rep, auto wrap>
[[nodiscard]] constexpr basic_angle<rep, wrap>
operator/(const rep &l, const basic_angle<rep, wrap> &r) noexcept(std::is_arithmetic_v<rep>) {
return basic_angle<rep, wrap>(l / r.radians());
}
template<floating_point rep, auto wrap>
[[nodiscard]] constexpr bool
operator==(const basic_angle<rep, wrap> &l, const basic_angle<rep, wrap> &r) noexcept(std::is_arithmetic_v<rep>) {
return l.radians() == r.radians();
}
template<floating_point rep, auto wrap>
[[nodiscard]] constexpr bool
operator!=(const basic_angle<rep, wrap> &l, const basic_angle<rep, wrap> &r) noexcept(std::is_arithmetic_v<rep>) {
return !(l == r);
}
template<floating_point rep, auto wrap>
[[nodiscard]] constexpr bool
operator<(const basic_angle<rep, wrap> &l, const basic_angle<rep, wrap> &r) noexcept(std::is_arithmetic_v<rep>) {
return l.radians() < r.radians();
}
template<floating_point rep, auto wrap>
[[nodiscard]] constexpr bool
operator<=(const basic_angle<rep, wrap> &l, const basic_angle<rep, wrap> &r) noexcept(std::is_arithmetic_v<rep>) {
return !(r < l);
}
template<floating_point rep, auto wrap>
[[nodiscard]] constexpr bool
operator>(const basic_angle<rep, wrap> &l, const basic_angle<rep, wrap> &r) noexcept(std::is_arithmetic_v<rep>) {
return r < l;
}
template<floating_point rep, auto wrap>
[[nodiscard]] constexpr bool
operator>=(const basic_angle<rep, wrap> &l, const basic_angle<rep, wrap> &r) noexcept(std::is_arithmetic_v<rep>) {
return !(l < r);
}
using angle = basic_angle<double, wrap_fp<double>>;
namespace literals {
constexpr angle operator ""_rad(long double value) {
return angle(value);
}
constexpr angle operator ""_deg(long double value) {
return angle(value * m_pi / 180.0);
}
}
}
#endif //ANGLE_ANGLE_H