Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ All notable changes to `qtty-cpp` are documented in this file.
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.4.5] - 01-06-2026

### Changed

- Updated bundled `qtty` integration to `0.8.5` to pick up the latest
unit inventory and FFI fixes.
- `qtty-ffi` discriminants: appended `Ratio` (`UNIT_ID_RATIO = 330006`) to the
dimensionless family so ratios and fractions are available to C++ consumers.
- Added `qtty::sin`, `qtty::cos`, and `qtty::tan` overloads for angular
quantities, matching the Rust trig helpers already exposed by `qtty-core`.
- Bumped project version and headers to `0.4.5`.

## [0.4.4] - 2026-05-15

### Changed
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.15)
project(qtty_cpp VERSION 0.4.3 LANGUAGES CXX)
project(qtty_cpp VERSION 0.4.5 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand Down
8 changes: 4 additions & 4 deletions gen_cpp_units/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 19 additions & 5 deletions include/qtty/angles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ template <class Tag> struct AngularTraits {
static constexpr bool is_angular = false;
};

#define QTTY_MARK_ANGULAR(Tag) \
template <> struct AngularTraits<Tag> { \
static constexpr bool is_angular = true; \
#define QTTY_MARK_ANGULAR(Tag) \
template <> struct AngularTraits<Tag> { \
static constexpr bool is_angular = true; \
}

QTTY_MARK_ANGULAR(MilliradianTag);
Expand All @@ -46,8 +46,22 @@ QTTY_MARK_ANGULAR(HourAngleTag);

#undef QTTY_MARK_ANGULAR

template <class Tag>
inline constexpr bool is_angular_v = AngularTraits<Tag>::is_angular;
template <class Tag> inline constexpr bool is_angular_v = AngularTraits<Tag>::is_angular;

template <class Tag> inline auto sin(Quantity<Tag> a) {
static_assert(is_angular_v<Tag>, "sin requires an angular quantity");
return std::sin(a.template to<RadianTag>().value());
}

template <class Tag> inline auto cos(Quantity<Tag> a) {
static_assert(is_angular_v<Tag>, "cos requires an angular quantity");
return std::cos(a.template to<RadianTag>().value());
}

template <class Tag> inline auto tan(Quantity<Tag> a) {
static_assert(is_angular_v<Tag>, "tan requires an angular quantity");
return std::tan(a.template to<RadianTag>().value());
}

namespace detail {

Expand Down
14 changes: 4 additions & 10 deletions include/qtty/ffi_core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
* @brief Core quantity template and error translation utilities.
*/

#include <cmath>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <limits>
Expand Down Expand Up @@ -345,22 +345,16 @@ template <typename UnitTag> class Quantity {
// Scalar Reductions (same unit) — mirror Rust `min`/`max`/`clamp`/`mean`
// ========================================================================

Quantity min(const Quantity &other) const {
return Quantity(std::min(m_value, other.m_value));
}
Quantity min(const Quantity &other) const { return Quantity(std::min(m_value, other.m_value)); }

Quantity max(const Quantity &other) const {
return Quantity(std::max(m_value, other.m_value));
}
Quantity max(const Quantity &other) const { return Quantity(std::max(m_value, other.m_value)); }

Quantity clamp(const Quantity &min_val, const Quantity &max_val) const {
return Quantity(std::max(min_val.m_value, std::min(m_value, max_val.m_value)));
}

// Arithmetic mean of two same-unit quantities.
Quantity mean(const Quantity &other) const {
return Quantity((m_value + other.m_value) * 0.5);
}
Quantity mean(const Quantity &other) const { return Quantity((m_value + other.m_value) * 0.5); }

// ========================================================================
// Floating-point Predicates — mirror Rust `is_nan`/`is_infinite`/`is_finite`
Expand Down
3 changes: 3 additions & 0 deletions include/qtty/math.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
* q.ln() qtty::ln(q)
* q.powi(n) qtty::powi(q, n)
* q.powf(exp) qtty::powf(q, exp)
* q.sin() qtty::sin(q)
* q.cos() qtty::cos(q)
* q.tan() qtty::tan(q)
* q.asin_angle() qtty::asin_angle(q)
* q.acos_angle() qtty::acos_angle(q)
* q.atan_angle() qtty::atan_angle(q)
Expand Down
5 changes: 3 additions & 2 deletions include/qtty/qtty.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@
// User-defined literals
#include "literals.hpp"

// Dimension-aware math helpers (ratio_to, exp/ln/powi/powf, asin/acos/atan_angle)
// Dimension-aware math helpers (ratio_to, exp/ln/powi/powf, sin/cos/tan,
// asin/acos/atan_angle)
#include "math.hpp"

// Angle wrapping / separation helpers (qtty_core angular methods)
Expand All @@ -100,7 +101,7 @@ namespace qtty {
inline constexpr struct {
int major = 0;
int minor = 4;
int patch = 0;
int patch = 5;
} version;

/**
Expand Down
7 changes: 7 additions & 0 deletions tests/test_math_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ TEST_F(MathHelpersTest, InverseTrigReturnsRadians) {
EXPECT_NEAR(deg.value(), 30.0, 1e-9);
}

TEST_F(MathHelpersTest, TrigFunctionsOnAnglesReturnScalars) {
Degree angle(30.0);
EXPECT_NEAR(sin(angle), 0.5, 1e-12);
EXPECT_NEAR(cos(angle), std::sqrt(3.0) / 2.0, 1e-12);
EXPECT_NEAR(tan(angle), 1.0 / std::sqrt(3.0), 1e-12);
}

TEST_F(MathHelpersTest, DimensionlessTraitSelectivity) {
static_assert(is_dimensionless_v<RatioTag>, "Ratio must be dimensionless");
static_assert(is_dimensionless_v<AirmassTag>, "Airmass must be dimensionless");
Expand Down
Loading