diff --git a/example/currency.cpp b/example/currency.cpp index 62ae32e9..ae326766 100644 --- a/example/currency.cpp +++ b/example/currency.cpp @@ -91,6 +91,6 @@ int main() quantity_point price_usd = zero + 100 * us_dollar; quantity_point price_euro = exchange_to(price_usd); - std::cout << price_usd.quantity_ref_from(zero) << " -> " << price_euro.quantity_ref_from(zero) << "\n"; - // std::cout << price_usd.quantity_ref_from(zero) + price_euro.quantity_ref_from(zero) << "\n"; // does not compile + std::cout << price_usd.quantity_from(zero) << " -> " << price_euro.quantity_from(zero) << "\n"; + // std::cout << price_usd.quantity_from(zero) + price_euro.quantity_from(zero) << "\n"; // does not compile } diff --git a/example/include/geographic.h b/example/include/geographic.h index 3f5d77ca..c422fa76 100644 --- a/example/include/geographic.h +++ b/example/include/geographic.h @@ -138,7 +138,7 @@ struct MP_UNITS_STD_FMT::formatter> : auto format(geographic::latitude lat, FormatContext& ctx) { formatter::quantity_type>::format( - is_gt_zero(lat) ? lat.quantity_ref_from(geographic::equator) : -lat.quantity_ref_from(geographic::equator), ctx); + is_gt_zero(lat) ? lat.quantity_from(geographic::equator) : -lat.quantity_from(geographic::equator), ctx); MP_UNITS_STD_FMT::format_to(ctx.out(), "{}", is_gt_zero(lat) ? " N" : "S"); return ctx.out(); } @@ -151,8 +151,7 @@ struct MP_UNITS_STD_FMT::formatter> : auto format(geographic::longitude lon, FormatContext& ctx) { formatter::quantity_type>::format( - is_gt_zero(lon) ? lon.quantity_ref_from(geographic::prime_meridian) - : -lon.quantity_ref_from(geographic::prime_meridian), + is_gt_zero(lon) ? lon.quantity_from(geographic::prime_meridian) : -lon.quantity_from(geographic::prime_meridian), ctx); MP_UNITS_STD_FMT::format_to(ctx.out(), "{}", is_gt_zero(lon) ? " E" : " W"); return ctx.out(); @@ -173,28 +172,29 @@ template distance spherical_distance(position from, position to) { using namespace mp_units; - constexpr auto earth_radius = 6'371 * isq::radius[si::kilo]; + constexpr quantity earth_radius = 6'371 * isq::radius[si::kilo]; using isq::sin, isq::cos, isq::asin, isq::acos; - const auto& from_lat = from.lat.quantity_ref_from(equator); - const auto& from_lon = from.lon.quantity_ref_from(prime_meridian); - const auto& to_lat = to.lat.quantity_ref_from(equator); - const auto& to_lon = to.lon.quantity_ref_from(prime_meridian); + const quantity from_lat = from.lat.quantity_from(equator); + const quantity from_lon = from.lon.quantity_from(prime_meridian); + const quantity to_lat = to.lat.quantity_from(equator); + const quantity to_lon = to.lon.quantity_from(prime_meridian); // https://en.wikipedia.org/wiki/Great-circle_distance#Formulae if constexpr (sizeof(T) >= 8) { // spherical law of cosines - const auto central_angle = acos(sin(from_lat) * sin(to_lat) + cos(from_lat) * cos(to_lat) * cos(to_lon - from_lon)); + const quantity central_angle = + acos(sin(from_lat) * sin(to_lat) + cos(from_lat) * cos(to_lat) * cos(to_lon - from_lon)); // const auto central_angle = 2 * asin(sqrt(0.5 - cos(to_lat - from_lat) / 2 + cos(from_lat) * cos(to_lat) * (1 // - cos(lon2_rad - from_lon)) / 2)); return quantity_cast(earth_radius * central_angle); } else { // the haversine formula - const auto sin_lat = sin((to_lat - from_lat) / 2); - const auto sin_lon = sin((to_lon - from_lon) / 2); - const auto central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(from_lat) * cos(to_lat) * sin_lon * sin_lon)); + const quantity sin_lat = sin((to_lat - from_lat) / 2); + const quantity sin_lon = sin((to_lon - from_lon) / 2); + const quantity central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(from_lat) * cos(to_lat) * sin_lon * sin_lon)); return quantity_cast(earth_radius * central_angle); } diff --git a/example/unmanned_aerial_vehicle.cpp b/example/unmanned_aerial_vehicle.cpp index ff83668a..f880ba56 100644 --- a/example/unmanned_aerial_vehicle.cpp +++ b/example/unmanned_aerial_vehicle.cpp @@ -97,8 +97,8 @@ template hae_altitude to_hae(msl_altitude msl, position pos) { const auto geoid_undulation = - isq::height(GeographicLibWhatsMyOffset(pos.lat.quantity_ref_from(equator).numerical_value_in(si::degree), - pos.lon.quantity_ref_from(prime_meridian).numerical_value_in(si::degree)) * + isq::height(GeographicLibWhatsMyOffset(pos.lat.quantity_from(equator).numerical_value_in(si::degree), + pos.lon.quantity_from(prime_meridian).numerical_value_in(si::degree)) * si::metre); return height_above_ellipsoid + (msl - mean_sea_level - geoid_undulation); } @@ -115,7 +115,7 @@ using hal_altitude = quantity_point std::basic_ostream& operator<<(std::basic_ostream& os, const hal_altitude& a) { - return os << a.quantity_ref_from(height_above_launch) << " HAL"; + return os << a.quantity_from(height_above_launch) << " HAL"; } template<> @@ -123,7 +123,7 @@ struct MP_UNITS_STD_FMT::formatter : formatter auto format(const hal_altitude& a, FormatContext& ctx) { - formatter::format(a.quantity_ref_from(height_above_launch), ctx); + formatter::format(a.quantity_from(height_above_launch), ctx); return MP_UNITS_STD_FMT::format_to(ctx.out(), " HAL"); } }; diff --git a/src/core/include/mp-units/quantity_point.h b/src/core/include/mp-units/quantity_point.h index ae046af5..99db2d97 100644 --- a/src/core/include/mp-units/quantity_point.h +++ b/src/core/include/mp-units/quantity_point.h @@ -174,6 +174,13 @@ public: } #endif + template + requires requires { quantity_point{} - PO2{}; } + [[nodiscard]] constexpr Quantity auto quantity_from(PO2) const + { + return *this - PO2{}; + } + template requires detail::QuantityConvertibleTo{}, Rep>> [[nodiscard]] constexpr quantity_point<::mp_units::reference{}, PO, Rep> in(U) const diff --git a/test/unit_test/static/quantity_point_test.cpp b/test/unit_test/static/quantity_point_test.cpp index 559cbd81..7805b2c1 100644 --- a/test/unit_test/static/quantity_point_test.cpp +++ b/test/unit_test/static/quantity_point_test.cpp @@ -1105,6 +1105,17 @@ static_assert((ground_level + 42 * m) - other_ground_level == -39 * m); static_assert((other_ground_level + 42 * m) - tower_peak == 81 * m); static_assert((tower_peak + 42 * m) - other_ground_level == 3 * m); +static_assert((mean_sea_level + 42 * m).quantity_from(ground_level) == 0 * m); +static_assert((ground_level + 42 * m).quantity_from(mean_sea_level) == 84 * m); +static_assert((tower_peak + 42 * m).quantity_from(ground_level) == 84 * m); +static_assert((ground_level + 42 * m).quantity_from(tower_peak) == 0 * m); +static_assert((tower_peak + 42 * m).quantity_from(mean_sea_level) == 126 * m); +static_assert((mean_sea_level + 42 * m).quantity_from(tower_peak) == -42 * m); +static_assert((other_ground_level + 42 * m).quantity_from(ground_level) == 123 * m); +static_assert((ground_level + 42 * m).quantity_from(other_ground_level) == -39 * m); +static_assert((other_ground_level + 42 * m).quantity_from(tower_peak) == 81 * m); +static_assert((tower_peak + 42 * m).quantity_from(other_ground_level) == 3 * m); + static_assert(mean_sea_level - (ground_level + 42 * m) == -84 * m); static_assert(ground_level - (mean_sea_level + 42 * m) == 0 * m); static_assert(tower_peak - (ground_level + 42 * m) == 0 * m);