diff --git a/.github/workflows/ci-conan.yml b/.github/workflows/ci-conan.yml
index e7a66487..8825a9d1 100644
--- a/.github/workflows/ci-conan.yml
+++ b/.github/workflows/ci-conan.yml
@@ -116,18 +116,18 @@ jobs:
lib: "libc++",
conan-config: "",
}
- # - {
- # name: "Apple Clang 13",
- # os: macos-11,
- # compiler:
- # {
- # type: APPLE_CLANG,
- # version: "13.0",
- # cc: "clang",
- # cxx: "clang++",
- # },
- # conan-config: "",
- # }
+ - {
+ name: "Apple Clang 15",
+ os: macos-13,
+ compiler:
+ {
+ type: APPLE_CLANG,
+ version: "15.0",
+ cc: "clang",
+ cxx: "clang++",
+ },
+ conan-config: "",
+ }
build_type: ["Release", "Debug"]
env:
@@ -174,11 +174,11 @@ jobs:
shell: bash
run: |
sudo apt install -y libc++-${{ matrix.config.compiler.version }}-dev libc++abi-${{ matrix.config.compiler.version }}-dev libunwind-${{ matrix.config.compiler.version }}-dev
- - name: Select Xcode 13.0
- if: matrix.config.compiler.type == 'APPLE_CLANG' && matrix.config.compiler.version == '13.0'
+ - name: Select Xcode version
+ if: matrix.config.compiler.type == 'APPLE_CLANG'
shell: bash
run: |
- sudo xcode-select -s "/Applications/Xcode_13.0.app"
+ sudo xcode-select -s /Applications/Xcode_${{ matrix.config.compiler.version }}.app && /usr/bin/xcodebuild -version
- name: Install Ninja
shell: bash
run: |
diff --git a/.github/workflows/ci-test-package-cmake.yml b/.github/workflows/ci-test-package-cmake.yml
index acbadc38..a621125a 100644
--- a/.github/workflows/ci-test-package-cmake.yml
+++ b/.github/workflows/ci-test-package-cmake.yml
@@ -111,17 +111,18 @@ jobs:
lib: "libc++",
conan-config: "",
}
- # - {
- # name: "Apple Clang 13",
- # os: macos-11,
- # compiler:
- # {
- # type: APPLE_CLANG,
- # version: "13.0",
- # cc: "clang",
- # cxx: "clang++",
- # },
- # }
+ - {
+ name: "Apple Clang 15",
+ os: macos-13,
+ compiler:
+ {
+ type: APPLE_CLANG,
+ version: "15.0",
+ cc: "clang",
+ cxx: "clang++",
+ },
+ conan-config: "",
+ }
build_type: ["Release", "Debug"]
env:
@@ -167,11 +168,11 @@ jobs:
shell: bash
run: |
sudo apt install -y libc++-${{ matrix.config.compiler.version }}-dev libc++abi-${{ matrix.config.compiler.version }}-dev libunwind-${{ matrix.config.compiler.version }}-dev
- - name: Select Xcode 13.0
- if: matrix.config.compiler.type == 'APPLE_CLANG' && matrix.config.compiler.version == '13.0'
+ - name: Select Xcode version
+ if: matrix.config.compiler.type == 'APPLE_CLANG'
shell: bash
run: |
- sudo xcode-select -s "/Applications/Xcode_13.0.app"
+ sudo xcode-select -s /Applications/Xcode_${{ matrix.config.compiler.version }}.app && /usr/bin/xcodebuild -version
- name: Install Ninja
shell: bash
run: |
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d4e4f97b..5d632e7b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,13 +2,19 @@
## mp-units
-### 2.1.0 WIP { id="2.1.0" }
+### 2.2.0 WIP { id="2.2.0" }
+
+
+### 2.1.0 December 9, 2023 { id="2.1.0" }
- (!) feat: `inverse()` support added for dimensions, quantity_spec, units, and references
(`1 / s` will now create `quantity` and not a `Unit`)
- (!) feat: `quantity_point` does not provide `zero()` anymore
- (!) feat: `quantity_spec` and its kind should not compare equal
- (!) feat: mutating interface removed from `fixed_string`
+- (!) feat: `common_type` with a raw value is not needed anymore as for a long time now raw values are
+ not convertible to the dimensionless quantities
+- (!) feat: `symbol_text` definition simplified
- feat: `basic_fixed_string(const CharT*, std::integral_constant)` constructor added
- feat: `isq::activity` added and `becquerel` definition updated to benefit from it
- feat: `gray` and `sievert` now have correct associated quantity kinds
@@ -18,16 +24,42 @@
- feat: interoperability with other libraries redesigned
- feat: equality for dimensions now will allow derived classes as well (but not from `derived_dimension`)
- feat: `zero_Fahrenheit` point origin added
+- feat: users are now allowed to inherit their ow types from absolute point origins
+- feat: equivalent point origins handling improved
+- feat(example): unit symbols added to the currency example
- (!) refactor: `unit_symbol(U)` signature refactored and the resulting text can now also be used at runtime
+- (!) refactor: `make_xxx` factory functions replaced with two-parameter constructors
+- (!) refactor: `unit_symbol` changed to `consteval`
- refactor: `in(U)` and `force_in(U)` now return `auto` to provide better diagnostics on clang
+- refactor: `quantity` operators constraints refactored
+- refactor: more type members added to `fixed_string` definition
+- refactor: `unit_symbol_formatting` enums now use `std::int8_t` as a representation type
- fix: symbols of named dimensionless units with the ratio = 1 were not printed
- fix: iterator is now properly updated for all cases in `unit_symbol`
- fix: Fahrenheit conversion ratio was inverted
+- fix: `CommonlyInvocableQuantities` was overconstrained for the current library design
+- fix: `are_ingredients_convertible` now mandates explicit conversion for `To` dimensionless quantities
+- fix: `quantity_point::point_for(PO)` constraints fixed
- fix(example): `latitude` and `longitude` fixed to include `0` for `N` and `E` respectively
- ci: clang-17 enabled
+- ci: apple-clang-15 enabled
- ci: Added C++23 builds to the CI matrix
+- docs: "Getting Started" chapters updated
+- docs: "Basic Concepts" and "Interface Introduction" chapters updated
+- docs: "Design Overview" chapter added and "Concepts" chapter reworked
+- docs: "Output stream formatting" chapter updated
+- docs: "Default formatting" chapter updated
+- docs: "Derived unit symbols generation" chapter added
+- docs: outdated affine space chapter updated
- docs: `CameCase` concept identifiers FAQ added
- docs: `gravitational_potential_energy` equation fixed on a graph
+- docs: YouTube video link updated to the C++ on Sea 2023
+- docs: ISO papers reference added to docs and README
+- docs: a representation type in a dimensionless quantity FAQ fixed
+- docs: titles added to some important admonitions
+- docs: "Terms and Definitions" slightly updated
+- docs: "canonical unit" added to glossary and its documentation in code was updated
+- docs: Design overview graph updated
### 2.0.0 September 24, 2023 { id="2.0.0" }
diff --git a/README.md b/README.md
index 6a5c783c..2bc55115 100644
--- a/README.md
+++ b/README.md
@@ -7,16 +7,16 @@
[](https://github.com/mpusz/mp-units/actions?query=workflow%3ADocumentation+branch%3Amaster)
[](https://conan.io/center/mp-units)
-[](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units/2.1.0)
+[](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units/2.2.0)
-# `mp-units` - A Physical Quantities and Units library for C++
+# `mp-units` - A Quantities and Units library for C++
**The mp-units library might be the subject of ISO standardization for C++29. More on this can
be found in the following ISO C++ proposals:**
- [P1935: A C++ Approach to Physical Units](https://wg21.link/p1935),
-- [P2980: A motivation, scope, and plan for a physical quantities and units library](https://wg21.link/p2980),
+- [P2980: A motivation, scope, and plan for a quantities and units library](https://wg21.link/p2980),
- [P2981: Improving our safety with a physical quantities and units library](https://wg21.link/p2981),
- [P2982: `std::quantity` as a numeric type](https://wg21.link/p2982).
diff --git a/conanfile.py b/conanfile.py
index 9565ec1e..83098f97 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -36,7 +36,7 @@ required_conan_version = ">=2.0.0"
class MPUnitsConan(ConanFile):
name = "mp-units"
homepage = "https://github.com/mpusz/mp-units"
- description = "A Physical Quantities and Units library for C++"
+ description = "A Quantities and Units library for C++"
topics = (
"units",
"dimensions",
@@ -74,8 +74,9 @@ class MPUnitsConan(ConanFile):
def _minimum_compilers_version(self):
return {
"gcc": "11",
- "clang": "16"
- # , "apple-clang": "13", "msvc": "192"
+ "clang": "16",
+ "apple-clang": "15"
+ # , "msvc": "192"
}
@property
diff --git a/docs/getting_started/installation_and_usage.md b/docs/getting_started/installation_and_usage.md
index 51457786..164a652d 100644
--- a/docs/getting_started/installation_and_usage.md
+++ b/docs/getting_started/installation_and_usage.md
@@ -18,6 +18,7 @@
- please note that we observed some ICEs on gcc-11
- no problems with gcc-12.2+
- clang-16
+ - apple-clang-15
## Repository Structure and Dependencies
@@ -283,7 +284,7 @@ The following steps may be performed to obtain an official library release:
```ini title="conanfile.txt"
[requires]
- mp-units/2.0.0
+ mp-units/2.1.0
[layout]
cmake_layout
@@ -340,7 +341,7 @@ with the following differences:
```ini title="conanfile.txt" hl_lines="2"
[requires]
- mp-units/2.1.0@mpusz/testing
+ mp-units/2.2.0@mpusz/testing
[layout]
cmake_layout
@@ -443,5 +444,5 @@ The above will create a Conan package and run tests provided in _./test_package_
## Uploading **mp-units** Package to the Conan Server
```shell
-conan upload -r --all mp-units/2.0.0@/
+conan upload -r --all mp-units/2.1.0@/
```
diff --git a/docs/index.md b/docs/index.md
index 3ced2ddb..7dec4ba6 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -37,3 +37,4 @@ The library source code is hosted on [GitHub](https://github.com/mpusz/mp-units)
- please note that we observed some ICEs on gcc-11
- no problems with gcc-12.2+
- clang-16
+ - apple-clang-15
diff --git a/docs/users_guide/framework_basics/the_affine_space.md b/docs/users_guide/framework_basics/the_affine_space.md
index 608246f2..10fc026f 100644
--- a/docs/users_guide/framework_basics/the_affine_space.md
+++ b/docs/users_guide/framework_basics/the_affine_space.md
@@ -2,8 +2,8 @@
The affine space has two types of entities:
-- **_point_** - a position specified with coordinate values (e.g. location, address, etc.)
-- **_vector_** - the difference between two points (e.g. shift, offset, displacement, duration, etc.)
+- **_point_** - a position specified with coordinate values (e.g., location, address, etc.)
+- **_vector_** - the difference between two points (e.g., shift, offset, displacement, duration, etc.)
!!! note
@@ -38,16 +38,33 @@ Here are the primary operations one can do in the affine space:
- multiply nor divide _points_ with anything else.
+## _Points_ are more common than most of us imagine
+
+_Point_ abstractions should be used more often in the C++ software.
+They are not only about temperature or time. _Points_ are everywhere around us and should become
+more popular in the products we implement. They can be used to implement:
+
+- temperature points,
+- timestamps,
+- daily mass readouts from the scale,
+- altitudes of mountain peaks on a map,
+- current speed displayed on a car's speed-o-meter,
+- today's price of instruments on the market,
+- and many more.
+
+Improving the affine space's _points_ intuition will allow us to write better and safer software.
+
+
## _Vector_ is modeled by `quantity`
-Up until now, each time when we used a `quantity` in our code, we were modeling some kind of a
+Up until now, each time we used a `quantity` in our code, we were modeling some kind of a
difference between two things:
-- the distance between two points
-- duration between two time points
-- the difference in speed (even if relative to `0`)
+- the distance between two points,
+- duration between two time points,
+- the difference in speed (even if relative to zero).
-As we already know, a `quantity` type provides all operations required for _vector_ type in
+As we already know, a `quantity` type provides all operations required for a _vector_ type in
the affine space.
@@ -327,7 +344,7 @@ The following operations are not allowed in the affine space:
- **adding** two `quantity_point` objects
- It is physically impossible to add positions of home and Denver airports.
- **subtracting** a `quantity_point` from a `quantity`
- - What would it mean to subtract DEN airport location from the distance to it?
+ - What would it mean to subtract the DEN airport location from the distance to it?
- **multiplying/dividing** a `quantity_point` with a scalar
- What is the position of `2 *` DEN airport location?
- **multiplying/dividing** a `quantity_point` with a quantity
@@ -337,13 +354,13 @@ The following operations are not allowed in the affine space:
- **mixing** `quantity_points` of different quantity kinds
- It is physically impossible to subtract time from length.
- **mixing** `quantity_points` of inconvertible quantities
- - What does it mean to subtract a distance point to DEN airport from the Mount Everest base camp
- altitude?
+ - What does subtracting a distance point to DEN airport from the Mount Everest base camp
+ altitude mean?
- **mixing** `quantity_points` of convertible quantities but with unrelated origins
- - How to subtract a point on our trip to CppCon measured relatively to our home location from
+ - How do we subtract a point on our trip to CppCon measured relatively to our home location from
a point measured relative to the center of the Solar System?
!!! important "Important: The affine space improves safety"
- The usage of `quantity_point` and affine space types in general, improves expressiveness and
+ The usage of `quantity_point` and affine space types, in general, improves expressiveness and
type-safety of the code we write.
diff --git a/example/include/geographic.h b/example/include/geographic.h
index a647459a..0ccda628 100644
--- a/example/include/geographic.h
+++ b/example/include/geographic.h
@@ -66,7 +66,8 @@ namespace geographic {
inline constexpr struct equator : mp_units::absolute_point_origin {
} equator;
-inline constexpr struct prime_meridian : mp_units::absolute_point_origin {
+inline constexpr struct prime_meridian :
+ mp_units::absolute_point_origin {
} prime_meridian;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4c7027a4..739e553e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -21,7 +21,7 @@
# SOFTWARE.
cmake_minimum_required(VERSION 3.19)
-project(mp-units VERSION 2.1.0 LANGUAGES CXX)
+project(mp-units VERSION 2.2.0 LANGUAGES CXX)
set(projectPrefix MP_UNITS_)
diff --git a/src/utility/include/mp-units/math.h b/src/utility/include/mp-units/math.h
index c613fea3..ab04e2a3 100644
--- a/src/utility/include/mp-units/math.h
+++ b/src/utility/include/mp-units/math.h
@@ -144,19 +144,31 @@ template
* @param b: Addend
* @return Quantity: The nearest floating point representable to ax+b
*/
-template
-[[nodiscard]] constexpr quantity fma(const quantity& a, const quantity& x,
- const quantity& b) noexcept
+
+template
+[[nodiscard]] constexpr QuantityOf auto
+fma( // QuantityOf takes a QuantitySpec as an argument
+ const quantity& a, const quantity& x, const quantity& b) noexcept
requires requires {
- fma(a.numerical_value_ref_in(a.unit), x.numerical_value_ref_in(x.unit), b.numerical_value_ref_in(b.unit));
- } || requires {
- std::fma(a.numerical_value_ref_in(a.unit), x.numerical_value_ref_in(x.unit), b.numerical_value_ref_in(b.unit));
- }
+ common_quantity_spec(get_quantity_spec(R) * get_quantity_spec(S), get_quantity_spec(T));
+ } && // or just common_reference but I wanted to express that the quantity types must match here and we don't care
+ // too much about units
+ (get_unit(R) * get_unit(S) ==
+ get_unit(T)) && // units that we want to add are equivalent (have the same magnitude)
+ (
+ requires {
+ fma(a.numerical_value_ref_in(a.unit), x.numerical_value_ref_in(x.unit),
+ b.numerical_value_ref_in(b.unit));
+ } ||
+ requires {
+ std::fma(a.numerical_value_ref_in(a.unit), x.numerical_value_ref_in(x.unit),
+ b.numerical_value_ref_in(b.unit));
+ })
{
using std::fma;
- return {static_cast(
- fma(a.numerical_value_ref_in(a.unit), x.numerical_value_ref_in(x.unit), b.numerical_value_ref_in(b.unit))),
- R};
+ return quantity{
+ fma(a.numerical_value_ref_in(a.unit), x.numerical_value_ref_in(x.unit), b.numerical_value_ref_in(b.unit)), T};
}
diff --git a/test/unit_test/runtime/math_test.cpp b/test/unit_test/runtime/math_test.cpp
index d7518de7..1726f7c1 100644
--- a/test/unit_test/runtime/math_test.cpp
+++ b/test/unit_test/runtime/math_test.cpp
@@ -62,9 +62,9 @@ TEST_CASE("'cbrt()' on quantity changes the value and the dimension accordingly"
REQUIRE(cbrt(8 * isq::volume[m3]) == 2 * isq::length[m]);
}
-TEST_CASE("'fma()' on quantity changes the value and the dimension accordingly", "[math][cbrt]")
+TEST_CASE("'fma()' on quantity changes the value and the dimension accordingly", "[math][fma]")
{
- REQUIRE(fma(1.0 * isq::length[m], 2.0, 2.0 * isq::length[m]) == 4.0 * isq::length[m]);
+ REQUIRE(fma(1.0 * isq::length[m], 2.0 * one, 2.0 * isq::length[m]) == 4.0 * isq::length[m]);
}
diff --git a/test/unit_test/static/math_test.cpp b/test/unit_test/static/math_test.cpp
index 7d877927..4874aabb 100644
--- a/test/unit_test/static/math_test.cpp
+++ b/test/unit_test/static/math_test.cpp
@@ -40,11 +40,10 @@ template
#if __cpp_lib_constexpr_cmath || MP_UNITS_COMP_GCC
-static_assert(compare(fma(2 * m, 3 * m, 1 * m2), 7 * m2));
-static_assert(compare(fma(2.0 * s, 3.0 * Hz, 1.0), 7.0));
-static_assert(compare(fma(2 * s, 3 * Hz, 1), 7));
-static_assert(compare(fma(2.0, 3.0*m, 1.0*m), 7*m);
-static_assert(compare(fma(2.0*m, 3.0, 1.0*m), 7*m));
+static_assert(compare(fma(2.0 * s, 3.0 * Hz, 1.0 * one), 7.0 * one));
+static_assert(compare(fma(2.0 * one, 3.0 * m, 1.0 * m), 7.0 * m));
+static_assert(compare(fma(2.0 * m, 3.0 * one, 1.0 * m), 7.0 * m));
+static_assert(compare(fma(2 * m, 3.0f * m, 1.0 * m2), 7.0 * m2));
static_assert(compare(pow<0>(2 * m), 1 * one));
static_assert(compare(pow<1>(2 * m), 2 * m));
static_assert(compare(pow<2>(2 * m), 4 * pow<2>(m), 4 * m2));