Skip to content

Commit

Permalink
Merge branch 'master' into ref_docs
Browse files Browse the repository at this point in the history
  • Loading branch information
JohelEGP authored Nov 8, 2024
2 parents 6824068 + 5097096 commit a2f1b31
Show file tree
Hide file tree
Showing 20 changed files with 254 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ As we remember, the `quantity` class template is defined as follows:

```cpp
template<Reference auto R,
RepresentationOf<get_quantity_spec(R).character> Rep = double>
RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity;
```

Expand Down
19 changes: 16 additions & 3 deletions docs/users_guide/framework_basics/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,28 @@ A `Reference` can either be:
[value of a quantity](../../appendix/glossary.md#quantity-value).


### `RepresentationOf<T, Ch>` { #RepresentationOf }
### `RepresentationOf<T, V>` { #RepresentationOf }

`RepresentationOf` concept is satisfied by all `Representation` types that are of a specified
[quantity character](../../appendix/glossary.md#character) `Ch`.
`RepresentationOf` concept is satisfied:

- if the type of `V` satisfies [`QuantitySpec`](#QuantitySpec):

- by all [`Representation`](#Representation) types when `V` describes
a [quantity kind](../../appendix/glossary.md#kind),
- otherwise, by [`Representation`](#Representation) types that are of
a [quantity character](../../appendix/glossary.md#character) associated with a provided
quantity specification `V`.

- if `V` is of `quantity_character` type:

- by [`Representation`](#Representation) types that are of a provided
[quantity character](../../appendix/glossary.md#character).

A user can declare a custom representation type to be of a specific character by providing the specialization
with `true` for one or more of the following variable templates:

- `is_scalar<T>`
- `is_complex<T>`
- `is_vector<T>`
- `is_tensor<T>`

Expand Down
4 changes: 2 additions & 2 deletions docs/users_guide/framework_basics/design_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ This is why a `quantity` class template is defined in the library as:

```cpp
template<Reference auto R,
RepresentationOf<get_quantity_spec(R).character> Rep = double>
RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity;
```

Expand Down Expand Up @@ -365,7 +365,7 @@ In the **mp-units** library, the quantity point is implemented as:
```cpp
template<Reference auto R,
PointOriginFor<get_quantity_spec(R)> auto PO,
RepresentationOf<get_quantity_spec(R).character> Rep = double>
RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity_point;
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ In the **mp-units** library, a quantity is represented with the following class

```cpp
template<Reference auto R,
RepresentationOf<get_quantity_spec(R).character> Rep = double>
RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity;
```

Expand Down
2 changes: 1 addition & 1 deletion docs/users_guide/framework_basics/the_affine_space.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ origin:
```cpp
template<Reference auto R,
PointOriginFor<get_quantity_spec(R)> auto PO = default_point_origin(R),
RepresentationOf<get_quantity_spec(R).character> Rep = double>
RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity_point;
```

Expand Down
4 changes: 3 additions & 1 deletion src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ add_mp_units_module(
include/mp-units/framework/value_cast.h
include/mp-units/compat_macros.h
include/mp-units/concepts.h
include/mp-units/core.h
include/mp-units/framework.h
MODULE_INTERFACE_UNIT mp-units-core.cpp
)
Expand All @@ -90,9 +91,10 @@ if(NOT ${projectPrefix}API_FREESTANDING)
include/mp-units/bits/fmt.h
include/mp-units/bits/requires_hosted.h
include/mp-units/ext/format.h
include/mp-units/complex.h
include/mp-units/format.h
include/mp-units/math.h
include/mp-units/ostream.h
include/mp-units/format.h
include/mp-units/random.h
)
endif()
Expand Down
1 change: 1 addition & 0 deletions src/core/include/mp-units/bits/core_gmf.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#ifndef MP_UNITS_IMPORT_STD
#include <chrono>
#include <cmath>
#include <complex>
#include <locale>
#include <ostream>
#include <random>
Expand Down
43 changes: 43 additions & 0 deletions src/core/include/mp-units/complex.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#pragma once

#include <mp-units/bits/requires_hosted.h>
//
#include <mp-units/bits/module_macros.h>
#include <mp-units/framework/customization_points.h>

#ifndef MP_UNITS_IN_MODULE_INTERFACE
#ifdef MP_UNITS_IMPORT_STD
import std;
#else
#include <complex>
#endif
#endif

namespace mp_units {

template<typename T>
constexpr bool is_complex<std::complex<T>> = true;

}
1 change: 1 addition & 0 deletions src/core/include/mp-units/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <mp-units/framework.h>

#if MP_UNITS_HOSTED
#include <mp-units/complex.h>
#include <mp-units/format.h>
#include <mp-units/math.h>
#include <mp-units/ostream.h>
Expand Down
4 changes: 2 additions & 2 deletions src/core/include/mp-units/framework/construction_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace mp_units {

template<Reference R>
struct delta_ {
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{})> Rep = std::remove_cvref_t<FwdRep>>
[[nodiscard]] constexpr quantity<MP_UNITS_EXPRESSION_WORKAROUND(R{}), Rep> operator()(FwdRep&& lhs) const
{
return quantity{std::forward<FwdRep>(lhs), R{}};
Expand All @@ -48,7 +48,7 @@ struct delta_ {

template<Reference R>
struct absolute_ {
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{})> Rep = std::remove_cvref_t<FwdRep>>
[[nodiscard]] constexpr quantity_point<MP_UNITS_EXPRESSION_WORKAROUND(R{}), default_point_origin(R{}), Rep>
operator()(FwdRep&& lhs) const
{
Expand Down
78 changes: 38 additions & 40 deletions src/core/include/mp-units/framework/quantity.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,15 @@ concept QuantityConvertibleTo =
// deduced thus the function is evaluated here and may emit truncating conversion or other warnings)
requires(QFrom q) { sudo_cast<QTo>(q); };

template<quantity_character Ch, typename Func, typename T, typename U>
concept InvokeResultOf = std::regular_invocable<Func, T, U> && RepresentationOf<std::invoke_result_t<Func, T, U>, Ch>;
template<auto QS, typename Func, typename T, typename U>
concept InvokeResultOf = QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> && std::regular_invocable<Func, T, U> &&
RepresentationOf<std::invoke_result_t<Func, T, U>, QS>;

template<typename Func, typename Q1, typename Q2,
quantity_character Ch = std::invoke_result_t<Func, std::remove_const_t<decltype(Q1::quantity_spec)>,
std::remove_const_t<decltype(Q2::quantity_spec)>>::character>
concept InvocableQuantities =
Quantity<Q1> && Quantity<Q2> && InvokeResultOf<Ch, Func, typename Q1::rep, typename Q2::rep>;
auto QS = std::invoke_result_t<Func, std::remove_const_t<decltype(Q1::quantity_spec)>,
std::remove_const_t<decltype(Q2::quantity_spec)>>{}>
concept InvocableQuantities = QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> && Quantity<Q1> && Quantity<Q2> &&
InvokeResultOf<QS, Func, typename Q1::rep, typename Q2::rep>;

// TODO remove the following when clang diagnostics improve
// https://github.com/llvm/llvm-project/issues/96660
Expand All @@ -104,7 +105,7 @@ concept CommonlyInvocableQuantities =
Quantity<Q1> && Quantity<Q2> && HaveCommonReference<Q1::reference, Q2::reference> &&
std::convertible_to<Q1, common_quantity_for<Func, Q1, Q2>> &&
std::convertible_to<Q2, common_quantity_for<Func, Q1, Q2>> &&
InvocableQuantities<Func, Q1, Q2, get_common_quantity_spec(Q1::quantity_spec, Q2::quantity_spec).character>;
InvocableQuantities<Func, Q1, Q2, get_common_quantity_spec(Q1::quantity_spec, Q2::quantity_spec)>;

template<auto R1, auto R2, typename Rep1, typename Rep2>
concept SameValueAs = (equivalent(get_unit(R1), get_unit(R2))) && std::convertible_to<Rep1, Rep2>;
Expand All @@ -128,7 +129,7 @@ MP_UNITS_EXPORT_BEGIN
* @tparam R a reference of the quantity providing all information about quantity properties
* @tparam Rep a type to be used to represent values of a quantity
*/
template<Reference auto R, RepresentationOf<get_quantity_spec(R).character> Rep = double>
template<Reference auto R, RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity {
public:
Rep numerical_value_is_an_implementation_detail_; ///< needs to be public for a structural type
Expand Down Expand Up @@ -227,14 +228,14 @@ class quantity {
return quantity<detail::make_reference(quantity_spec, ToU{}), Rep>{*this};
}

template<RepresentationOf<quantity_spec.character> ToRep>
template<RepresentationOf<quantity_spec> ToRep>
requires detail::QuantityConvertibleTo<quantity, quantity<reference, ToRep>>
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto in() const
{
return quantity<reference, ToRep>{*this};
}

template<RepresentationOf<quantity_spec.character> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
template<RepresentationOf<quantity_spec> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
requires detail::QuantityConvertibleTo<quantity, quantity<detail::make_reference(quantity_spec, ToU{}), ToRep>>
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto in(ToU) const
{
Expand All @@ -248,14 +249,14 @@ class quantity {
return value_cast<ToU{}>(*this);
}

template<RepresentationOf<quantity_spec.character> ToRep>
template<RepresentationOf<quantity_spec> ToRep>
requires requires(quantity q) { value_cast<ToRep>(q); }
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto force_in() const
{
return value_cast<ToRep>(*this);
}

template<RepresentationOf<quantity_spec.character> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
template<RepresentationOf<quantity_spec> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
requires requires(quantity q) { value_cast<ToU{}, ToRep>(q); }
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto force_in(ToU) const
{
Expand Down Expand Up @@ -474,17 +475,15 @@ class quantity {
ret::reference};
}

template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
requires(Q::unit == ::mp_units::one) &&
detail::InvokeResultOf<quantity_character::scalar, std::plus<>, Rep, const Value&>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && detail::InvokeResultOf<quantity_spec, std::plus<>, Rep, const Value&>
[[nodiscard]] friend constexpr Quantity auto operator+(const Q& lhs, const Value& rhs)
{
return lhs + ::mp_units::quantity{rhs};
}

template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
requires(Q::unit == ::mp_units::one) &&
detail::InvokeResultOf<quantity_character::scalar, std::plus<>, Rep, const Value&>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && detail::InvokeResultOf<quantity_spec, std::plus<>, Rep, const Value&>
[[nodiscard]] friend constexpr Quantity auto operator+(const Value& lhs, const Q& rhs)
{
return ::mp_units::quantity{lhs} + rhs;
Expand All @@ -501,17 +500,15 @@ class quantity {
ret::reference};
}

template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
requires(Q::unit == ::mp_units::one) &&
detail::InvokeResultOf<quantity_character::scalar, std::minus<>, Rep, const Value&>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && detail::InvokeResultOf<quantity_spec, std::minus<>, Rep, const Value&>
[[nodiscard]] friend constexpr Quantity auto operator-(const Q& lhs, const Value& rhs)
{
return lhs - ::mp_units::quantity{rhs};
}

template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
requires(Q::unit == ::mp_units::one) &&
detail::InvokeResultOf<quantity_character::scalar, std::minus<>, Rep, const Value&>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && detail::InvokeResultOf<quantity_spec, std::minus<>, Rep, const Value&>
[[nodiscard]] friend constexpr Quantity auto operator-(const Value& lhs, const Q& rhs)
{
return ::mp_units::quantity{lhs} - rhs;
Expand All @@ -530,17 +527,15 @@ class quantity {
ret::reference};
}

template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
requires(Q::unit == ::mp_units::one) &&
detail::InvokeResultOf<quantity_character::scalar, std::modulus<>, Rep, const Value&>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && detail::InvokeResultOf<quantity_spec, std::modulus<>, Rep, const Value&>
[[nodiscard]] friend constexpr Quantity auto operator%(const Q& lhs, const Value& rhs)
{
return lhs % ::mp_units::quantity{rhs};
}

template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
requires(Q::unit == ::mp_units::one) &&
detail::InvokeResultOf<quantity_character::scalar, std::modulus<>, Rep, const Value&>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && detail::InvokeResultOf<quantity_spec, std::modulus<>, Rep, const Value&>
[[nodiscard]] friend constexpr Quantity auto operator%(const Value& lhs, const Q& rhs)
{
return ::mp_units::quantity{lhs} % rhs;
Expand All @@ -555,15 +550,15 @@ class quantity {

template<std::derived_from<quantity> Q, typename Value>
requires(!Quantity<Value>) &&
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::multiplies<>, Rep, const Value&>
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec, std::multiplies<>, Rep, const Value&>
[[nodiscard]] friend constexpr QuantityOf<quantity_spec> auto operator*(const Q& q, const Value& v)
{
return ::mp_units::quantity{q.numerical_value_ref_in(unit) * v, R};
}

template<typename Value, std::derived_from<quantity> Q>
requires(!Quantity<Value>) &&
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::multiplies<>, const Value&, Rep>
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec, std::multiplies<>, const Value&, Rep>
[[nodiscard]] friend constexpr QuantityOf<quantity_spec> auto operator*(const Value& v, const Q& q)
{
return ::mp_units::quantity{v * q.numerical_value_ref_in(unit), R};
Expand All @@ -579,7 +574,7 @@ class quantity {

template<std::derived_from<quantity> Q, typename Value>
requires(!Quantity<Value>) &&
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::divides<>, Rep, const Value&>
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec, std::divides<>, Rep, const Value&>
[[nodiscard]] friend constexpr QuantityOf<quantity_spec> auto operator/(const Q& q, const Value& v)
{
MP_UNITS_EXPECTS_DEBUG(v != quantity_values<Value>::zero());
Expand All @@ -588,7 +583,7 @@ class quantity {

template<typename Value, std::derived_from<quantity> Q>
requires(!Quantity<Value>) &&
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::divides<>, const Value&, Rep>
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec, std::divides<>, const Value&, Rep>
[[nodiscard]] friend constexpr QuantityOf<inverse(quantity_spec)> auto operator/(const Value& v, const Q& q)
{
return ::mp_units::quantity{v / q.numerical_value_ref_in(unit), ::mp_units::one / R};
Expand All @@ -605,7 +600,7 @@ class quantity {
return ct_lhs.numerical_value_ref_in(ct::unit) == ct_rhs.numerical_value_ref_in(ct::unit);
}

template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && std::equality_comparable_with<Rep, Value>
[[nodiscard]] friend constexpr bool operator==(const Q& lhs, const Value& rhs)
{
Expand All @@ -623,7 +618,7 @@ class quantity {
return ct_lhs.numerical_value_ref_in(ct::unit) <=> ct_rhs.numerical_value_ref_in(ct::unit);
}

template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && std::three_way_comparable_with<Rep, Value>
[[nodiscard]] friend constexpr auto operator<=>(const Q& lhs, const Value& rhs)
{
Expand All @@ -650,18 +645,21 @@ template<mp_units::Quantity Q1, mp_units::Quantity Q2>
requires requires {
{ mp_units::get_common_reference(Q1::reference, Q2::reference) } -> mp_units::Reference;
typename std::common_type_t<typename Q1::rep, typename Q2::rep>;
requires mp_units::RepresentationOf<std::common_type_t<typename Q1::rep, typename Q2::rep>,
mp_units::get_common_quantity_spec(Q1::quantity_spec, Q2::quantity_spec)>;
}
struct std::common_type<Q1, Q2> {
using type = mp_units::quantity<mp_units::get_common_reference(Q1::reference, Q2::reference),
std::common_type_t<typename Q1::rep, typename Q2::rep>>;
};

template<mp_units::Quantity Q, mp_units::RepresentationOf<mp_units::quantity_character::scalar> Value>
requires(Q::unit == mp_units::one) && requires { typename std::common_type_t<typename Q::rep, Value>; }
template<mp_units::Quantity Q, mp_units::Representation Value>
requires(Q::unit == mp_units::one) &&
requires { typename mp_units::quantity<Q::reference, std::common_type_t<typename Q::rep, Value>>; }
struct std::common_type<Q, Value> {
using type = mp_units::quantity<Q::reference, std::common_type_t<typename Q::rep, Value>>;
};

template<mp_units::Quantity Q, mp_units::RepresentationOf<mp_units::quantity_character::scalar> Value>
requires(Q::unit == mp_units::one) && requires { typename std::common_type_t<typename Q::rep, Value>; }
template<mp_units::Quantity Q, mp_units::Representation Value>
requires requires { typename std::common_type<Q, Value>; }
struct std::common_type<Value, Q> : std::common_type<Q, Value> {};
Loading

0 comments on commit a2f1b31

Please sign in to comment.