mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-05 05:04:27 +02:00
Merge branch 'mpusz:master' into add_fma
This commit is contained in:
30
.github/workflows/ci-conan.yml
vendored
30
.github/workflows/ci-conan.yml
vendored
@@ -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: |
|
||||
|
29
.github/workflows/ci-test-package-cmake.yml
vendored
29
.github/workflows/ci-test-package-cmake.yml
vendored
@@ -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: |
|
||||
|
34
CHANGELOG.md
34
CHANGELOG.md
@@ -2,13 +2,19 @@
|
||||
|
||||
## mp-units
|
||||
|
||||
### 2.1.0 <small>WIP</small> { id="2.1.0" }
|
||||
### 2.2.0 <small>WIP</small> { id="2.2.0" }
|
||||
|
||||
|
||||
### 2.1.0 <small>December 9, 2023</small> { 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<std::size_t, N>)` 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<fmt>(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 <small>September 24, 2023</small> { id="2.0.0" }
|
||||
|
||||
|
@@ -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).
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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 <remote-name> --all mp-units/2.0.0@<user>/<channel>
|
||||
conan upload -r <remote-name> --all mp-units/2.1.0@<user>/<channel>
|
||||
```
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
@@ -66,7 +66,8 @@ namespace geographic {
|
||||
|
||||
inline constexpr struct equator : mp_units::absolute_point_origin<equator, mp_units::isq::angular_measure> {
|
||||
} equator;
|
||||
inline constexpr struct prime_meridian : mp_units::absolute_point_origin<prime_meridian, mp_units::isq::angular_measure> {
|
||||
inline constexpr struct prime_meridian :
|
||||
mp_units::absolute_point_origin<prime_meridian, mp_units::isq::angular_measure> {
|
||||
} prime_meridian;
|
||||
|
||||
|
||||
|
@@ -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_)
|
||||
|
||||
|
@@ -144,19 +144,31 @@ template<auto R, typename Rep>
|
||||
* @param b: Addend
|
||||
* @return Quantity: The nearest floating point representable to ax+b
|
||||
*/
|
||||
template<auto R, auto S, typename Rep>
|
||||
[[nodiscard]] constexpr quantity<R, Rep> fma(const quantity<R, Rep>& a, const quantity<S, Rep>& x,
|
||||
const quantity<R, Rep>& b) noexcept
|
||||
|
||||
template<auto R, auto S, auto T, typename Rep1, typename Rep2, typename Rep3>
|
||||
[[nodiscard]] constexpr QuantityOf<common_quantity_spec(get_quantity_spec(R) * get_quantity_spec(S),
|
||||
get_quantity_spec(T))> auto
|
||||
fma( // QuantityOf takes a QuantitySpec as an argument
|
||||
const quantity<R, Rep1>& a, const quantity<S, Rep2>& x, const quantity<T, Rep3>& 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<Rep>(
|
||||
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};
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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]);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -40,11 +40,10 @@ template<typename T1, typename T2, typename... Ts>
|
||||
|
||||
#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));
|
||||
|
Reference in New Issue
Block a user