qtty-cpp 0.4.5
Header-only C++ wrapper for qtty
Loading...
Searching...
No Matches
angles.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2// Copyright (C) 2026 Vallés Puig, Ramon
3
4#pragma once
5
17#include <cmath>
18#include <type_traits>
19
20#include "ffi_core.hpp"
21#include "units/angular.hpp"
22
23namespace qtty {
24
27template <class Tag> struct AngularTraits {
28 static constexpr bool is_angular = false;
29};
30
31#define QTTY_MARK_ANGULAR(Tag) \
32 template <> struct AngularTraits<Tag> { \
33 static constexpr bool is_angular = true; \
34 }
35
46
47#undef QTTY_MARK_ANGULAR
48
49template <class Tag> inline constexpr bool is_angular_v = AngularTraits<Tag>::is_angular;
50
51template <class Tag> inline auto sin(Quantity<Tag> a) {
52 static_assert(is_angular_v<Tag>, "sin requires an angular quantity");
53 return std::sin(a.template to<RadianTag>().value());
54}
55
56template <class Tag> inline auto cos(Quantity<Tag> a) {
57 static_assert(is_angular_v<Tag>, "cos requires an angular quantity");
58 return std::cos(a.template to<RadianTag>().value());
59}
60
61template <class Tag> inline auto tan(Quantity<Tag> a) {
62 static_assert(is_angular_v<Tag>, "tan requires an angular quantity");
63 return std::tan(a.template to<RadianTag>().value());
64}
65
66namespace detail {
67
68inline double rem_euclid(double a, double b) {
69 double r = std::fmod(a, b);
70 return (r < 0.0) ? r + std::abs(b) : r;
71}
72
73} // namespace detail
74
76template <class Tag, class = std::enable_if_t<is_angular_v<Tag>>>
77inline double angular_full_turn() {
78 constexpr double tau = 6.283185307179586476925286766559;
79 return Quantity<RadianTag>(tau).template to<Tag>().value();
80}
81
83template <class Tag, class = std::enable_if_t<is_angular_v<Tag>>>
87
89template <class Tag, class = std::enable_if_t<is_angular_v<Tag>>>
91 return wrap_pos(a);
92}
93
95template <class Tag, class = std::enable_if_t<is_angular_v<Tag>>>
98 double half = 0.5 * full;
99 double y = detail::rem_euclid(a.value() + half, full) - half;
100 double norm = (y <= -half) ? y + full : y;
101 return Quantity<Tag>(norm);
102}
103
105template <class Tag, class = std::enable_if_t<is_angular_v<Tag>>>
107 double full = angular_full_turn<Tag>();
108 double half = 0.5 * full;
109 double y = wrap_signed(a).value();
110 if (y >= half) {
111 y -= full;
112 }
113 return Quantity<Tag>(y);
114}
115
117template <class Tag, class = std::enable_if_t<is_angular_v<Tag>>>
119 double full = angular_full_turn<Tag>();
120 double half = 0.5 * full;
121 double quarter = 0.25 * full;
122 double y = detail::rem_euclid(a.value() + quarter, full);
123 return Quantity<Tag>(quarter - std::abs(y - half));
124}
125
127template <class Tag, class = std::enable_if_t<is_angular_v<Tag>>>
131
133template <class Tag, class = std::enable_if_t<is_angular_v<Tag>>>
137
138} // namespace qtty
#define QTTY_MARK_ANGULAR(Tag)
Definition angles.hpp:31
Core quantity template and error translation utilities.
double rem_euclid(double a, double b)
Definition angles.hpp:68
auto cos(Quantity< Tag > a)
Definition angles.hpp:56
Quantity< Tag > signed_separation(Quantity< Tag > a, Quantity< Tag > b)
Signed smallest angular separation in (-HALF_TURN, HALF_TURN].
Definition angles.hpp:128
constexpr bool is_angular_v
Definition angles.hpp:49
double angular_full_turn()
Magnitude of one full revolution expressed in the angular unit Tag.
Definition angles.hpp:77
Quantity< Tag > wrap_signed(Quantity< Tag > a)
Wrap into the signed range (-HALF_TURN, HALF_TURN].
Definition angles.hpp:96
Quantity< Tag > wrap_signed_lo(Quantity< Tag > a)
Wrap into the alternate signed range [-HALF_TURN, HALF_TURN).
Definition angles.hpp:106
auto sin(Quantity< Tag > a)
Definition angles.hpp:51
Quantity< Tag > wrap_pos(Quantity< Tag > a)
Wrap into the canonical positive range [0, FULL_TURN).
Definition angles.hpp:84
Quantity< Tag > abs_separation(Quantity< Tag > a, Quantity< Tag > b)
Absolute smallest angular separation (magnitude only).
Definition angles.hpp:134
Quantity< Tag > wrap_quarter_fold(Quantity< Tag > a)
"Latitude fold": map into [-QUARTER_TURN, +QUARTER_TURN].
Definition angles.hpp:118
Quantity< Tag > normalize(Quantity< Tag > a)
Alias of wrap_pos: normalize into [0, FULL_TURN).
Definition angles.hpp:90
auto tan(Quantity< Tag > a)
Definition angles.hpp:61
static constexpr bool is_angular
Definition angles.hpp:28