mirror of
https://github.com/mpusz/mp-units.git
synced 2025-06-25 01:01:33 +02:00
merge branch master
This commit is contained in:
26
.github/workflows/ci-check.yml
vendored
26
.github/workflows/ci-check.yml
vendored
@ -26,17 +26,17 @@ on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
- name: Check
|
||||
run: |
|
||||
pre-commit run --all-files
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
- name: Check
|
||||
run: |
|
||||
pre-commit run --all-files
|
||||
|
164
.github/workflows/ci-conan.yml
vendored
164
.github/workflows/ci-conan.yml
vendored
@ -30,6 +30,9 @@ on:
|
||||
paths-ignore:
|
||||
- "docs/**"
|
||||
|
||||
env:
|
||||
CHANNEL: ${{ fromJSON('["testing", "stable"]')[github.ref_type == 'tag' && startsWith(github.ref_name, 'v')] }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.config.name }} ${{ matrix.build_type }} [downcast=${{ matrix.downcast_mode }}]
|
||||
@ -42,15 +45,17 @@ jobs:
|
||||
name: "Windows MSVC 14.2",
|
||||
os: windows-2019,
|
||||
compiler: { type: VISUAL, version: 16, cc: "", cxx: "", std: 20 },
|
||||
conan-config: "-c user.build:skip_la=True",
|
||||
}
|
||||
- {
|
||||
name: "Windows MSVC 14.3",
|
||||
os: windows-2022,
|
||||
compiler: { type: MSVC, version: 193, cc: "", cxx: "", std: 23 },
|
||||
conan-config: "",
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu GCC-10",
|
||||
os: ubuntu-20.04,
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: GCC,
|
||||
@ -59,11 +64,11 @@ jobs:
|
||||
cxx: "g++-10",
|
||||
std: 20,
|
||||
},
|
||||
lib: "libstdc++11",
|
||||
conan-config: "",
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu GCC-11",
|
||||
os: ubuntu-20.04,
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: GCC,
|
||||
@ -72,7 +77,20 @@ jobs:
|
||||
cxx: "g++-11",
|
||||
std: 20,
|
||||
},
|
||||
lib: "libstdc++11",
|
||||
conan-config: "",
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu GCC-12",
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: GCC,
|
||||
version: 12,
|
||||
cc: "gcc-12",
|
||||
cxx: "g++-12",
|
||||
std: 20,
|
||||
},
|
||||
conan-config: "",
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu Clang-12 + libstdc++11",
|
||||
@ -86,6 +104,7 @@ jobs:
|
||||
std: 20,
|
||||
},
|
||||
lib: "libstdc++11",
|
||||
conan-config: "",
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu Clang-12 + libc++",
|
||||
@ -99,10 +118,11 @@ jobs:
|
||||
std: 20,
|
||||
},
|
||||
lib: "libc++",
|
||||
conan-config: "",
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu Clang-13 + libc++",
|
||||
os: ubuntu-20.04,
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: CLANG,
|
||||
@ -112,10 +132,11 @@ jobs:
|
||||
std: 20,
|
||||
},
|
||||
lib: "libc++",
|
||||
conan-config: "",
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu Clang-14 + libc++",
|
||||
os: ubuntu-20.04,
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: CLANG,
|
||||
@ -125,6 +146,35 @@ jobs:
|
||||
std: 20,
|
||||
},
|
||||
lib: "libc++",
|
||||
conan-config: "",
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu Clang-15 + libc++",
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: CLANG,
|
||||
version: 15,
|
||||
cc: "clang-15",
|
||||
cxx: "clang++-15",
|
||||
std: 20,
|
||||
},
|
||||
lib: "libc++",
|
||||
conan-config: "",
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu Clang-16 + libc++",
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: CLANG,
|
||||
version: 16,
|
||||
cc: "clang-16",
|
||||
cxx: "clang++-16",
|
||||
std: 20,
|
||||
},
|
||||
lib: "libc++",
|
||||
conan-config: "",
|
||||
}
|
||||
- {
|
||||
name: "MacOS Apple Clang 13",
|
||||
@ -137,6 +187,7 @@ jobs:
|
||||
cxx: "clang++",
|
||||
std: 20,
|
||||
},
|
||||
conan-config: "",
|
||||
}
|
||||
build_type: ["Release", "Debug"]
|
||||
downcast_mode: ["on", "auto"]
|
||||
@ -146,25 +197,27 @@ jobs:
|
||||
CXX: ${{ matrix.config.compiler.cxx }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Cache Conan data
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-conan-data
|
||||
with:
|
||||
path: ~/.conan/data
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/metadata.json') }}
|
||||
path: ~/.conan2/p
|
||||
key: build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-${{ matrix.config.lib }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- uses: hendrikmuhs/ccache-action@v1
|
||||
build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-${{ matrix.config.lib }}
|
||||
build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-
|
||||
build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-
|
||||
build-${{ matrix.config.os }}-${{ matrix.build_type }}-
|
||||
build-${{ matrix.config.os }}-
|
||||
- uses: hendrikmuhs/ccache-action@v1.2
|
||||
if: runner.os == 'Linux'
|
||||
with:
|
||||
key: ${{ matrix.config.os }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-${{ matrix.config.lib }}-${{ matrix.build_type }}-${{ matrix.downcast_mode }}
|
||||
max-size: 50M
|
||||
- name: Install gcc-11
|
||||
if: matrix.config.compiler.type == 'GCC' && matrix.config.compiler.version == '11'
|
||||
- name: Install gcc-12
|
||||
if: matrix.config.compiler.type == 'GCC' && matrix.config.compiler.version == '12'
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt install -y g++-${{ matrix.config.compiler.version }}
|
||||
@ -201,7 +254,7 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.8"
|
||||
- name: Install Conan
|
||||
@ -211,37 +264,76 @@ jobs:
|
||||
- name: Configure Conan
|
||||
shell: bash
|
||||
run: |
|
||||
conan config init
|
||||
conan remote add artifactory https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||
if [[ "${{ matrix.config.compiler.type }}" == "GCC" || "${{ matrix.config.compiler.type }}" == "CLANG" ]]; then
|
||||
conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default
|
||||
conan profile detect --force
|
||||
if [[ "${{ matrix.config.compiler.type }}" == "CLANG" ]]; then
|
||||
sed -i.backup '/^\[settings\]$/,/^\[/ s/^compiler.libcxx=.*/compiler.libcxx=${{ matrix.config.lib }}/' ~/.conan2/profiles/default
|
||||
fi
|
||||
conan profile update settings.compiler.cppstd=${{ matrix.config.compiler.std }} default
|
||||
conan profile update settings.build_type=${{ matrix.build_type }} default
|
||||
conan profile update conf.tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" default
|
||||
conan profile show default
|
||||
sed -i.backup '/^\[settings\]$/,/^\[/ s/^compiler.cppstd=.*/compiler.cppstd=${{ matrix.config.compiler.std }}/' ~/.conan2/profiles/default
|
||||
sed -i.backup '/^\[settings\]$/,/^\[/ s/^build_type=.*/build_type=${{ matrix.build_type }}/' ~/.conan2/profiles/default
|
||||
conan profile show -pr default
|
||||
# - name: Add support for clang-13 to Conan's settings.yml
|
||||
# # TODO Remove when Conan will support clang-13
|
||||
# if: matrix.config.compiler.type == 'CLANG'
|
||||
# shell: bash
|
||||
# run: |
|
||||
# sed -i -e 's/"8", "9", "10", "11", "12"]/"8", "9", "10", "11", "12", "13"]/' ~/.conan/settings.yml
|
||||
- name: Set channel
|
||||
shell: bash
|
||||
run: |
|
||||
[[ `git tag --contains ${{ github.sha }}` =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] && CHANNEL=stable || CHANNEL=testing
|
||||
echo "CHANNEL=${CHANNEL}" >> ${GITHUB_ENV}
|
||||
- name: Create Conan package
|
||||
shell: bash
|
||||
run: |
|
||||
conan create . mpusz/testing -o mp-units:downcast_mode=${{ matrix.downcast_mode }} -c user.build:all=True -c user.build:skip_docs=True -b mp-units -b outdated -u
|
||||
- name: Upload mp-units Conan package
|
||||
conan create . --user mpusz --channel ${CHANNEL} --lockfile-out=package.lock \
|
||||
-b mp-units/* -b missing -c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" \
|
||||
-o downcast_mode=${{ matrix.downcast_mode }} -c user.build:all=True -c user.build:skip_docs=True ${{ matrix.config.conan-config }}
|
||||
- name: Obtain package reference
|
||||
id: get-package-ref
|
||||
shell: bash
|
||||
run: |
|
||||
echo "PACKAGE_REF=`egrep -o mp-units[^%]+ package.lock`" >> ${GITHUB_OUTPUT}
|
||||
- name: Upload mp-units Conan package to Conan CI repository
|
||||
if: github.ref == 'refs/heads/master' || env.CHANNEL == 'stable'
|
||||
shell: bash
|
||||
run: |
|
||||
conan user ${{ secrets.CONAN_LOGIN_USERNAME }} -r artifactory -p ${{ secrets.CONAN_PASSWORD }}
|
||||
conan upload "mp-units*" --all -r artifactory --confirm
|
||||
- name: Remove mp-units package from Conan local cache
|
||||
conan remote add conan-mpusz-ci https://mpusz.jfrog.io/artifactory/api/conan/conan-ci
|
||||
conan remote login conan-mpusz-ci ${{ secrets.CONAN_LOGIN_USERNAME }} -p ${{ secrets.CONAN_CI_PASSWORD }}
|
||||
conan upload ${{ steps.get-package-ref.outputs.package_ref }} -r conan-mpusz-ci --confirm
|
||||
- name: Clean Conan cache before backup
|
||||
shell: bash
|
||||
run: |
|
||||
conan remove mp-units -c
|
||||
conan remove mp-units --confirm
|
||||
conan remove *#!latest --confirm
|
||||
conan remove *:*#!latest --confirm
|
||||
conan cache clean "*" -s -b -d
|
||||
outputs:
|
||||
package_ref: ${{ steps.get-package-ref.outputs.PACKAGE_REF }}
|
||||
|
||||
promote_package:
|
||||
if: github.ref == 'refs/heads/master' || (github.ref_type == 'tag' && startsWith(github.ref_name, 'v'))
|
||||
needs: build
|
||||
name: Promote Conan package
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.8"
|
||||
- name: Install Conan
|
||||
shell: bash
|
||||
run: |
|
||||
pip install -U conan
|
||||
- name: Configure Conan
|
||||
shell: bash
|
||||
run: |
|
||||
conan remote add conan-mpusz-ci https://mpusz.jfrog.io/artifactory/api/conan/conan-ci
|
||||
conan remote add conan-mpusz-oss https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||
- name: Promote mp-units Conan package
|
||||
shell: bash
|
||||
run: |
|
||||
conan remote login conan-mpusz-ci ${{ secrets.CONAN_LOGIN_USERNAME }} -p ${{ secrets.CONAN_CI_PASSWORD }}
|
||||
conan remote login conan-mpusz-oss ${{ secrets.CONAN_LOGIN_USERNAME }} -p ${{ secrets.CONAN_PASSWORD }}
|
||||
conan download ${{ needs.build.outputs.package_ref }} -r conan-mpusz-ci
|
||||
conan upload ${{ needs.build.outputs.package_ref }} -r conan-mpusz-oss --confirm
|
||||
- name: Do housekeeping on conan-mpusz-oss
|
||||
shell: bash
|
||||
run: |
|
||||
conan remove mp-units/*#!latest --confirm -r conan-mpusz-oss
|
||||
conan remove mp-units/*:*#!latest --confirm -r conan-mpusz-oss
|
||||
|
95
.github/workflows/ci-test-package-cmake.yml
vendored
95
.github/workflows/ci-test-package-cmake.yml
vendored
@ -54,7 +54,7 @@ jobs:
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu GCC-10",
|
||||
os: ubuntu-20.04,
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: GCC,
|
||||
@ -63,11 +63,10 @@ jobs:
|
||||
cxx: "g++-10",
|
||||
std: 20,
|
||||
},
|
||||
lib: "libstdc++11",
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu GCC-11",
|
||||
os: ubuntu-20.04,
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: GCC,
|
||||
@ -76,7 +75,18 @@ jobs:
|
||||
cxx: "g++-11",
|
||||
std: 20,
|
||||
},
|
||||
lib: "libstdc++11",
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu GCC-12",
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: GCC,
|
||||
version: 12,
|
||||
cc: "gcc-12",
|
||||
cxx: "g++-12",
|
||||
std: 20,
|
||||
},
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu Clang-12 + libstdc++11",
|
||||
@ -106,7 +116,7 @@ jobs:
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu Clang-13 + libc++",
|
||||
os: ubuntu-20.04,
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: CLANG,
|
||||
@ -119,7 +129,7 @@ jobs:
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu Clang-14 + libc++",
|
||||
os: ubuntu-20.04,
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: CLANG,
|
||||
@ -130,6 +140,32 @@ jobs:
|
||||
},
|
||||
lib: "libc++",
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu Clang-15 + libc++",
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: CLANG,
|
||||
version: 15,
|
||||
cc: "clang-15",
|
||||
cxx: "clang++-15",
|
||||
std: 20,
|
||||
},
|
||||
lib: "libc++",
|
||||
}
|
||||
- {
|
||||
name: "Ubuntu Clang-16 + libc++",
|
||||
os: ubuntu-22.04,
|
||||
compiler:
|
||||
{
|
||||
type: CLANG,
|
||||
version: 16,
|
||||
cc: "clang-16",
|
||||
cxx: "clang++-16",
|
||||
std: 20,
|
||||
},
|
||||
lib: "libc++",
|
||||
}
|
||||
- {
|
||||
name: "MacOS Apple Clang 13",
|
||||
os: macos-11,
|
||||
@ -154,18 +190,20 @@ jobs:
|
||||
uses: ASzc/change-string-case-action@v2
|
||||
with:
|
||||
string: ${{ matrix.build_type }}
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Cache Conan data
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-conan-data
|
||||
with:
|
||||
path: ~/.conan/data
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/metadata.json') }}
|
||||
path: ~/.conan2/p
|
||||
key: build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-${{ matrix.config.lib }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-${{ matrix.config.lib }}
|
||||
build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-
|
||||
build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-
|
||||
build-${{ matrix.config.os }}-${{ matrix.build_type }}-
|
||||
build-${{ matrix.config.os }}-
|
||||
- name: Install gcc-11
|
||||
if: matrix.config.compiler.type == 'GCC' && matrix.config.compiler.version == '11'
|
||||
shell: bash
|
||||
@ -204,7 +242,7 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.8"
|
||||
- name: Install Conan
|
||||
@ -214,15 +252,14 @@ jobs:
|
||||
- name: Configure Conan
|
||||
shell: bash
|
||||
run: |
|
||||
conan config init
|
||||
conan profile detect --force
|
||||
conan remote add artifactory https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||
if [[ "${{ matrix.config.compiler.type }}" == "GCC" || "${{ matrix.config.compiler.type }}" == "CLANG" ]]; then
|
||||
conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default
|
||||
if [[ "${{ matrix.config.compiler.type }}" == "CLANG" ]]; then
|
||||
sed -i.backup '/^\[settings\]$/,/^\[/ s/^compiler.libcxx=.*/compiler.libcxx=${{ matrix.config.lib }}/' ~/.conan2/profiles/default
|
||||
fi
|
||||
conan profile update settings.compiler.cppstd=${{ matrix.config.compiler.std }} default
|
||||
conan profile update settings.build_type=${{ matrix.build_type }} default
|
||||
conan profile update conf.tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" default
|
||||
conan profile show default
|
||||
sed -i.backup '/^\[settings\]$/,/^\[/ s/^compiler.cppstd=.*/compiler.cppstd=${{ matrix.config.compiler.std }}/' ~/.conan2/profiles/default
|
||||
sed -i.backup '/^\[settings\]$/,/^\[/ s/^build_type=.*/build_type=${{ matrix.build_type }}/' ~/.conan2/profiles/default
|
||||
conan profile show -pr default
|
||||
# - name: Add support for clang-13 to Conan's settings.yml
|
||||
# # TODO Remove when Conan will support clang-13
|
||||
# if: matrix.config.compiler.type == 'CLANG'
|
||||
@ -232,7 +269,7 @@ jobs:
|
||||
- name: Install Conan dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
conan install . -b outdated -u
|
||||
conan install . -b missing -c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" -c user.build:all=False
|
||||
mv CMakeUserPresets.json src
|
||||
- name: Configure mp-units CMake
|
||||
if: matrix.config.compiler.type == 'VISUAL' || matrix.config.compiler.type == 'MSVC'
|
||||
@ -241,19 +278,19 @@ jobs:
|
||||
run: |
|
||||
cmake --version
|
||||
call ..\build\generators\conanvcvars.bat
|
||||
cmake --preset default -DCMAKE_INSTALL_PREFIX=../out
|
||||
cmake --preset conan-default -DCMAKE_INSTALL_PREFIX=../out
|
||||
- name: Configure mp-units CMake
|
||||
if: matrix.config.compiler.type != 'VISUAL' && matrix.config.compiler.type != 'MSVC'
|
||||
shell: bash
|
||||
working-directory: src
|
||||
run: |
|
||||
cmake --version
|
||||
cmake --preset default -DCMAKE_INSTALL_PREFIX=../out
|
||||
cmake --preset conan-default -DCMAKE_INSTALL_PREFIX=../out
|
||||
- name: Install mp-units
|
||||
shell: bash
|
||||
working-directory: src
|
||||
run: |
|
||||
cmake --build --preset ${{ steps.build_type.outputs.lowercase }} --target install
|
||||
cmake --build --preset conan-${{ steps.build_type.outputs.lowercase }} --target install
|
||||
- name: Provide dependencies for test_package
|
||||
shell: bash
|
||||
working-directory: test_package
|
||||
@ -265,14 +302,14 @@ jobs:
|
||||
working-directory: test_package
|
||||
run: |
|
||||
call ..\build\generators\conanvcvars.bat
|
||||
cmake --preset default -Dmp-units_DIR=../build -Bbuild/local
|
||||
cmake --preset conan-default -Dmp-units_DIR=../build -Bbuild/local
|
||||
cmake --build build/local --config ${{ matrix.build_type }}
|
||||
- name: Build test_package CMake (local build)
|
||||
if: matrix.config.compiler.type != 'VISUAL' && matrix.config.compiler.type != 'MSVC'
|
||||
shell: bash
|
||||
working-directory: test_package
|
||||
run: |
|
||||
cmake --preset default -Dmp-units_DIR=../build -Bbuild/local
|
||||
cmake --preset conan-default -Dmp-units_DIR=../build -Bbuild/local
|
||||
cmake --build build/local --config ${{ matrix.build_type }}
|
||||
- name: Run test_package (local build)
|
||||
shell: bash
|
||||
@ -285,14 +322,14 @@ jobs:
|
||||
working-directory: test_package
|
||||
run: |
|
||||
call ..\build\generators\conanvcvars.bat
|
||||
cmake --preset default -DCMAKE_INSTALL_PREFIX=../out -Bbuild/install
|
||||
cmake --preset conan-default -DCMAKE_INSTALL_PREFIX=../out -Bbuild/install
|
||||
cmake --build build/install --config ${{ matrix.build_type }}
|
||||
- name: Build test_package CMake (installation)
|
||||
if: matrix.config.compiler.type != 'VISUAL' && matrix.config.compiler.type != 'MSVC'
|
||||
shell: bash
|
||||
working-directory: test_package
|
||||
run: |
|
||||
cmake --preset default -DCMAKE_INSTALL_PREFIX=../out -Bbuild/install
|
||||
cmake --preset conan-default -DCMAKE_INSTALL_PREFIX=../out -Bbuild/install
|
||||
cmake --build build/install --config ${{ matrix.build_type }}
|
||||
- name: Run test_package (installation)
|
||||
shell: bash
|
||||
|
2
.github/workflows/citation.yml
vendored
2
.github/workflows/citation.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# This is needed for workflows running on
|
||||
# ubuntu-20.04 or later
|
||||
|
32
.github/workflows/codeql-analysis.yml
vendored
32
.github/workflows/codeql-analysis.yml
vendored
@ -25,22 +25,26 @@ on:
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CC: gcc-10
|
||||
CXX: g++-10
|
||||
|
||||
BUILD_TYPE: Debug
|
||||
COMPILER_TYPE: GCC
|
||||
COMPILER_VERSION: 10
|
||||
STDLIB: libstdc++11
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ["cpp", "python"]
|
||||
os: ["ubuntu-latest"]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more...
|
||||
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
@ -63,29 +67,29 @@ jobs:
|
||||
|
||||
- name: Cache Conan data
|
||||
if: matrix.language == 'cpp'
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-conan-data
|
||||
with:
|
||||
path: ~/.conan/data
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/metadata.json') }}
|
||||
path: ~/.conan2/p
|
||||
key: build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-$COMPILER_VERSION-$STDLIB
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-$COMPILER_VERSION-
|
||||
build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-
|
||||
build-${{ matrix.os }}-$BUILD_TYPE-
|
||||
build-${{ matrix.os }}-
|
||||
- name: Set up Python
|
||||
if: matrix.language == 'cpp'
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.8"
|
||||
- name: Conan build
|
||||
if: matrix.language == 'cpp'
|
||||
run: |
|
||||
pip install -U conan
|
||||
conan config init
|
||||
conan remote add upload https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||
conan profile detect --force
|
||||
conan remote add artifactory https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||
mkdir _lgtm_build_dir && cd _lgtm_build_dir
|
||||
conan install .. -s compiler.cppstd=20 -s compiler.libcxx=libstdc++11 -c user.build:all=True -c user.build:skip_docs=True -b outdated -u
|
||||
conan build ..
|
||||
conan build .. -s compiler.cppstd=20 -s compiler.libcxx=$STDLIB -c user.build:all=True -c user.build:skip_docs=True -b missing
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
|
51
.github/workflows/documentation.yml
vendored
51
.github/workflows/documentation.yml
vendored
@ -35,35 +35,44 @@ on:
|
||||
- "docs/**"
|
||||
- "src/**"
|
||||
- "example/**"
|
||||
|
||||
env:
|
||||
CC: gcc-10
|
||||
CXX: g++-10
|
||||
CMAKE_GENERATOR: Ninja
|
||||
CONAN_CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
name: Generate documentation
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CC: gcc-10
|
||||
CXX: g++-10
|
||||
CMAKE_GENERATOR: Ninja
|
||||
CONAN_CMAKE_GENERATOR: Ninja
|
||||
OS: ubuntu-22.04
|
||||
BUILD_TYPE: Debug
|
||||
COMPILER_TYPE: GCC
|
||||
COMPILER_VERSION: 10
|
||||
STDLIB: libstdc++11
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ["ubuntu-latest"]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Cache Conan data
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-conan-data
|
||||
with:
|
||||
path: ~/.conan/data
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/metadata.json') }}
|
||||
path: ~/.conan2/p
|
||||
key: build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-$COMPILER_VERSION-$STDLIB-docs
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-$COMPILER_VERSION-$STDLIB
|
||||
build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-$COMPILER_VERSION-
|
||||
build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-
|
||||
build-${{ matrix.os }}-$BUILD_TYPE-
|
||||
build-${{ matrix.os }}-
|
||||
- name: Install Ninja
|
||||
run: |
|
||||
sudo apt install -y ninja-build
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.8"
|
||||
- name: Install Python dependencies
|
||||
@ -74,17 +83,17 @@ jobs:
|
||||
pip install -U conan
|
||||
- name: Configure Conan
|
||||
run: |
|
||||
conan config init
|
||||
conan remote add -i 0 upload https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||
conan profile detect --force
|
||||
conan remote add artifactory https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||
- name: Install Conan dependencies
|
||||
run: |
|
||||
conan install . -s compiler.cppstd=20 -s compiler.libcxx=libstdc++11 -c user.build:all=True -c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" -b outdated -u
|
||||
conan install . -s compiler.cppstd=20 -s compiler.libcxx=$STDLIB -c user.build:all=True -c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" -b missing
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
cmake --preset default
|
||||
cmake --preset conan-default
|
||||
- name: Generate documentation
|
||||
run: |
|
||||
cmake --build --preset release --target documentation
|
||||
cmake --build --preset conan-release --target documentation
|
||||
- name: Deploy documentation
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
|
6
.gitpod.Dockerfile
vendored
6
.gitpod.Dockerfile
vendored
@ -2,13 +2,13 @@ FROM trainiteu/gitpod-cpp
|
||||
|
||||
# Add clang-12 and clang-15 apt repositories
|
||||
RUN lsb_rel=`lsb_release -cs` \
|
||||
&& sudo add-apt-repository "deb http://apt.llvm.org/${lsb_rel}/ llvm-toolchain-${lsb_rel}-12 main" \
|
||||
&& sudo add-apt-repository "deb http://apt.llvm.org/${lsb_rel}/ llvm-toolchain-${lsb_rel}-13 main" \
|
||||
&& sudo add-apt-repository "deb http://apt.llvm.org/${lsb_rel}/ llvm-toolchain-${lsb_rel}-14 main" \
|
||||
&& sudo add-apt-repository "deb http://apt.llvm.org/${lsb_rel}/ llvm-toolchain-${lsb_rel} main"
|
||||
|
||||
# Install older compilers supported by the project as well as clang-format-15 for code formatting
|
||||
RUN sudo install-packages \
|
||||
g++-10 \
|
||||
clang-12 \
|
||||
g++-11 \
|
||||
clang-13 \
|
||||
clang-format-15
|
||||
clang-14
|
||||
|
122
.gitpod.yml
122
.gitpod.yml
@ -36,8 +36,7 @@ vscode:
|
||||
- vivaxy.vscode-conventional-commits
|
||||
- hbenl.vscode-test-explorer
|
||||
- matepek.vscode-catch2-test-adapter
|
||||
- trond-snekvik.simple-rst
|
||||
- lextudio.restructuredtext
|
||||
- redhat.vscode-yaml
|
||||
- ritwickdey.liveserver
|
||||
- ms-python.python
|
||||
|
||||
@ -49,24 +48,28 @@ tasks:
|
||||
mkdir -p "$PWD/.vscode";
|
||||
cat << 'EOF' > "$PWD/.vscode/settings.json"
|
||||
{
|
||||
"cmake.buildDirectory": "${workspaceFolder}/build/${buildKitVendor}-${buildKitVersionMajor}",
|
||||
"cmake.configureArgs": [
|
||||
"--toolchain conan_toolchain.cmake"
|
||||
],
|
||||
"cmake.generator": "Ninja Multi-Config",
|
||||
"cmake.configureOnOpen": true,
|
||||
"clang-format.executable": "/usr/bin/clang-format-15",
|
||||
"editor.tabSize": 2,
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnType": true,
|
||||
"editor.bracketPairColorization.enabled": true,
|
||||
"editor.guides.bracketPairs": "active",
|
||||
"restructuredtext.preview.scrollEditorWithPreview": false,
|
||||
"restructuredtext.preview.scrollPreviewWithEditor": false,
|
||||
"liveServer.settings.root": "/build/docs/docs/sphinx/",
|
||||
"esbonio.sphinx.confDir": "${workspaceFolder}/docs",
|
||||
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools"
|
||||
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
|
||||
"yaml.schemas": {
|
||||
"https://squidfunk.github.io/mkdocs-material/schema.json": "mkdocs.yml"
|
||||
},
|
||||
"yaml.customTags": [
|
||||
"!ENV scalar",
|
||||
"!ENV sequence",
|
||||
"tag:yaml.org,2002:python/name:materialx.emoji.to_svg",
|
||||
"tag:yaml.org,2002:python/name:materialx.emoji.twemoji",
|
||||
"tag:yaml.org,2002:python/name:pymdownx.superfences.fence_code_format"
|
||||
]
|
||||
}
|
||||
|
||||
EOF
|
||||
@ -77,96 +80,103 @@ tasks:
|
||||
conan config init
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
conan profile update settings.compiler.cppstd=20 default
|
||||
conan profile update conf.tools.cmake.cmaketoolchain:generator=Ninja default
|
||||
conan remote add -i 0 conan-mpusz https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||
pushd /workspace/.conan/profiles
|
||||
cp default gcc10
|
||||
cp default gcc11
|
||||
cp default clang12
|
||||
cp default gcc12
|
||||
cp default clang13
|
||||
cp default clang14
|
||||
cp default clang15
|
||||
popd
|
||||
conan profile update settings.compiler.version=10 gcc10
|
||||
conan profile update env.CXX=/usr/bin/g++-10 gcc10
|
||||
conan profile update env.CC=/usr/bin/gcc-10 gcc10
|
||||
conan profile update settings.compiler=clang clang12
|
||||
conan profile update settings.compiler.version=12 clang12
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 clang12
|
||||
conan profile update env.CXX=/usr/bin/clang++-12 clang12
|
||||
conan profile update env.CC=/usr/bin/clang-12 clang12
|
||||
conan profile update 'conf.tools.build.compiler_executables={"c": "gcc-10", "cpp": "g++-10"}' gcc10
|
||||
conan profile update settings.compiler.version=11 gcc11
|
||||
conan profile update 'conf.tools.build.compiler_executables={"c": "gcc-11", "cpp": "g++-11"}' gcc11
|
||||
conan profile update settings.compiler.version=11 gcc12
|
||||
conan profile update 'conf.tools.build.compiler_executables={"c": "gcc-12", "cpp": "g++-12"}' gcc12
|
||||
conan profile update settings.compiler=clang clang13
|
||||
conan profile update settings.compiler.version=13 clang13
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 clang13
|
||||
conan profile update env.CXX=/usr/bin/clang++-13 clang13
|
||||
conan profile update env.CC=/usr/bin/clang-13 clang13
|
||||
conan profile update 'conf.tools.build.compiler_executables={"c": "clang-13", "cpp": "clang++-13"}' clang13
|
||||
conan profile update settings.compiler=clang clang14
|
||||
conan profile update settings.compiler.version=14 clang14
|
||||
conan profile update settings.compiler.libcxx=libc++ clang14
|
||||
conan profile update env.CXX=/usr/bin/clang++-14 clang14
|
||||
conan profile update env.CC=/usr/bin/clang-14 clang14
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 clang14
|
||||
conan profile update 'conf.tools.build.compiler_executables={"c": "clang-14", "cpp": "clang++-14"}' clang14
|
||||
conan profile update settings.compiler=clang clang15
|
||||
conan profile update settings.compiler.version=15 clang15
|
||||
conan profile update settings.compiler.libcxx=libc++ clang15
|
||||
conan profile update 'conf.tools.build.compiler_executables={"c": "clang-15", "cpp": "clang++-15"}' clang15
|
||||
echo 'tools.cmake.cmaketoolchain:generator=Ninja Multi-Config' > /workspace/.conan/global.conf
|
||||
echo 'tools.cmake.cmake_layout:build_folder_vars=["settings.compiler", "settings.compiler.version"]' >> /workspace/.conan/global.conf
|
||||
gp sync-done conan-init
|
||||
exit
|
||||
- name: gcc-10
|
||||
init: |
|
||||
gp sync-await conan-init
|
||||
mkdir -p build/GCC-10 && cd build/GCC-10
|
||||
conan install ../.. -pr gcc10 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated
|
||||
conan install ../.. -pr gcc10 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated -s build_type=Debug
|
||||
cmake ../.. --no-warn-unused-cli --toolchain conan_toolchain.cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE -DCMAKE_C_COMPILER=/usr/bin/gcc-10 -DCMAKE_CXX_COMPILER=/usr/bin/g++-10
|
||||
cmake --build . --config Release -j
|
||||
cmake --build . --config Debug -j
|
||||
conan install . -pr gcc10 -c user.build:all=True -c user.build:skip_docs=True -b outdated
|
||||
conan install . -pr gcc10 -c user.build:all=True -c user.build:skip_docs=True -b outdated -s build_type=Debug
|
||||
cmake --preset gcc-10
|
||||
cmake --build --preset gcc-10-release -j
|
||||
cmake --build --preset gcc-10-debug -j
|
||||
ctest -C Release
|
||||
ctest -C Debug
|
||||
echo "🛠️ gcc-10 pre-build done! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️"
|
||||
- name: gcc-11
|
||||
init: |
|
||||
gp sync-await conan-init
|
||||
mkdir -p build/GCC-11 && cd build/GCC-11
|
||||
conan install ../.. -pr gcc11 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated
|
||||
gp sync-done conan-gcc-install
|
||||
conan install ../.. -pr gcc11 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated -s build_type=Debug
|
||||
cmake ../.. --no-warn-unused-cli --toolchain conan_toolchain.cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE -DCMAKE_C_COMPILER=/usr/bin/gcc -DCMAKE_CXX_COMPILER=/usr/bin/g++
|
||||
cmake --build . --config Release -j
|
||||
cmake --build . --config Debug -j
|
||||
conan install . -pr gcc11 -c user.build:all=True -c user.build:skip_docs=True -b outdated
|
||||
conan install . -pr gcc11 -c user.build:all=True -c user.build:skip_docs=True -b outdated -s build_type=Debug
|
||||
cmake --preset gcc-11
|
||||
cmake --build --preset gcc-11-release -j
|
||||
cmake --build --preset gcc-11-debug -j
|
||||
ctest -C Release
|
||||
ctest -C Debug
|
||||
echo "🛠️ gcc-11 pre-build done! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️"
|
||||
- name: clang-12
|
||||
- name: gcc-12
|
||||
init: |
|
||||
gp sync-await conan-init
|
||||
mkdir -p build/Clang-12 && cd build/Clang-12
|
||||
conan install ../.. -pr clang12 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated
|
||||
conan install ../.. -pr clang12 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated -s build_type=Debug
|
||||
cmake ../.. --no-warn-unused-cli --toolchain conan_toolchain.cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE -DCMAKE_C_COMPILER=/usr/bin/clang-12 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-12
|
||||
cmake --build . --config Release -j
|
||||
cmake --build . --config Debug -j
|
||||
conan install . -pr gcc12 -c user.build:all=True -c user.build:skip_docs=True -b outdated
|
||||
conan install . -pr gcc12 -c user.build:all=True -c user.build:skip_docs=True -b outdated -s build_type=Debug
|
||||
cmake --preset gcc-12
|
||||
cmake --build --preset gcc-12-release -j
|
||||
cmake --build --preset gcc-12-debug -j
|
||||
ctest -C Release
|
||||
ctest -C Debug
|
||||
echo "🛠️ clang-12 pre-build done! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️"
|
||||
echo "🛠️ gcc-12 pre-build done! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️"
|
||||
- name: clang-13
|
||||
init: |
|
||||
gp sync-await conan-init
|
||||
mkdir -p build/Clang-13 && cd build/Clang-13
|
||||
conan install ../.. -pr clang13 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated
|
||||
conan install ../.. -pr clang13 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated -s build_type=Debug
|
||||
cmake ../.. --no-warn-unused-cli --toolchain conan_toolchain.cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE -DCMAKE_C_COMPILER=/usr/bin/clang-13 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-13
|
||||
cmake --build . --config Release -j
|
||||
cmake --build . --config Debug -j
|
||||
conan install . -pr clang13 -c user.build:all=True -c user.build:skip_docs=True -b outdated
|
||||
conan install . -pr clang13 -c user.build:all=True -c user.build:skip_docs=True -b outdated -s build_type=Debug
|
||||
cmake --preset clang-13
|
||||
cmake --build --preset clang-13-release -j
|
||||
cmake --build --preset clang-13-debug -j
|
||||
ctest -C Release
|
||||
ctest -C Debug
|
||||
echo "🛠️ clang-13 pre-build done! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️"
|
||||
- name: clang-14
|
||||
init: |
|
||||
gp sync-await conan-init
|
||||
mkdir -p build/Clang-14 && cd build/Clang-14
|
||||
conan install ../.. -pr clang4 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated
|
||||
conan install ../.. -pr clang14 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated -s build_type=Debug
|
||||
cmake ../.. --no-warn-unused-cli --toolchain conan_toolchain.cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE -DCMAKE_C_COMPILER=/usr/bin/clang-14 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-14
|
||||
cmake --build . --config Release -j
|
||||
cmake --build . --config Debug -j
|
||||
conan install . -pr clang14 -c user.build:all=True -c user.build:skip_docs=True -b outdated
|
||||
conan install . -pr clang14 -c user.build:all=True -c user.build:skip_docs=True -b outdated -s build_type=Debug
|
||||
cmake --preset clang-14
|
||||
cmake --build --preset clang-14-release -j
|
||||
cmake --build --preset clang-14-debug -j
|
||||
ctest -C Release
|
||||
ctest -C Debug
|
||||
echo "🛠️ clang-14 pre-build done! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️"
|
||||
- name: clang-15
|
||||
init: |
|
||||
gp sync-await conan-init
|
||||
conan install . -pr clang15 -c user.build:all=True -c user.build:skip_docs=True -b outdated
|
||||
conan install . -pr clang15 -c user.build:all=True -c user.build:skip_docs=True -b outdated -s build_type=Debug
|
||||
cmake --preset clang-15
|
||||
cmake --build --preset clang-15-release -j
|
||||
cmake --build --preset clang-15-debug -j
|
||||
ctest -C Release
|
||||
ctest -C Debug
|
||||
echo "🛠️ clang-15 pre-build done! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️"
|
||||
- name: documentation
|
||||
init: |
|
||||
gp sync-await conan-init
|
||||
|
@ -1,15 +1,19 @@
|
||||
default_stages: [commit]
|
||||
|
||||
repos:
|
||||
- repo: meta
|
||||
hooks:
|
||||
- id: check-hooks-apply
|
||||
- id: check-useless-excludes
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.2.0
|
||||
rev: v4.3.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
# - repo: https://github.com/pocc/pre-commit-hooks
|
||||
# rev: v1.3.5
|
||||
# hooks:
|
||||
# - id: clang-format
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v16.0.0
|
||||
hooks:
|
||||
- id: clang-format
|
||||
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
||||
rev: v0.6.13
|
||||
hooks:
|
||||
@ -19,16 +23,16 @@ repos:
|
||||
# additional_dependencies: ["cmakelang"]
|
||||
# exclude: "cmake/.*"
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.3.0
|
||||
rev: 22.10.0
|
||||
hooks:
|
||||
- id: black
|
||||
language_version: python3
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.10.1
|
||||
rev: 5.12.0
|
||||
hooks:
|
||||
- id: isort
|
||||
args: [--profile, black, --multi-line, "3"]
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 4.0.1
|
||||
rev: 5.0.4
|
||||
hooks:
|
||||
- id: flake8
|
||||
|
@ -27,6 +27,8 @@ authors:
|
||||
orcid: https://orcid.org/0000-0003-0680-0765
|
||||
- given-names: "Johel Ernesto"
|
||||
family-names: "Guerrero Peña"
|
||||
- given-names: "Chip"
|
||||
family-names: "Hogg"
|
||||
- name: "The mp-units project team"
|
||||
|
||||
contact:
|
||||
@ -34,9 +36,9 @@ contact:
|
||||
given-names: Mateusz
|
||||
family-names: Pusz
|
||||
|
||||
repository-code: 'https://github.com/mpusz/units'
|
||||
url: 'https://mpusz.github.io/units'
|
||||
repository-artifact: 'https://conan.io/center/mp-units'
|
||||
repository-code: "https://github.com/mpusz/units"
|
||||
url: "https://mpusz.github.io/units"
|
||||
repository-artifact: "https://conan.io/center/mp-units"
|
||||
|
||||
version: 0.7.0
|
||||
date-released: "2021-05-11"
|
||||
|
@ -12,11 +12,11 @@ below or prefix any `mp-units` URL (main branch, other branches, issues, PRs, ..
|
||||
|
||||
The above environment provides you with:
|
||||
|
||||
- all supported compilers for Linux development (`g++-10`, `g++-11`, `clang-12`, `clang-13`) and build tools like `cmake` and `conan`
|
||||
- all supported compilers for Linux development (`g++-10`, `g++-11`, `g++12`, `clang-13`, `clang-14`, and `clang-15`)
|
||||
and the latest version of build tools like `cmake` and `conan`
|
||||
- all Conan dependencies preinstalled on the machine
|
||||
- all documentation generation tools ready to use
|
||||
- completed prebuilds for all targets (each compiler as well as a documentation)
|
||||
- `clang-format-15` for source code formatting
|
||||
- completed prebuilds for all targets (Debug and Release builds for each compiler as well as a documentation)
|
||||
- VSCode preconfigured to benefit from all the above
|
||||
|
||||
## Download, Build, Install
|
||||
@ -24,13 +24,19 @@ The above environment provides you with:
|
||||
Alternatively, please refer to our official docs for [download, build, and install instructions](https://mpusz.github.io/units/usage.html)
|
||||
if you want to setup a development environment on your local machine.
|
||||
|
||||
## Where to start?
|
||||
## Code Formatting
|
||||
|
||||
If you are looking for a good issue to start with, please check the following:
|
||||
There is a formatting standard enforced with the `pre-commit` script. Before committing your changes please do the following:
|
||||
|
||||
```bash
|
||||
pip3 install -U pre-commit
|
||||
pre-commit run --all-files
|
||||
```
|
||||
|
||||
This will run `clang-format` for code formatting with the `.clang-format` file provided in the repo, `cmake-format` to format the CMake files, and some other check as well.
|
||||
The script will run on all the files in the repo and will apply the changes in-place when needed.
|
||||
After the script is done please make sure to stage all those changes to git commit.
|
||||
|
||||
- [good first issue](https://github.com/mpusz/units/labels/good%20first%20issue) - issues that should be pretty simple to implement.
|
||||
- [help wanted](https://github.com/mpusz/units/labels/help%20wanted) - issues that typically are a bit more involved than beginner issues.
|
||||
- [high priority](https://github.com/mpusz/units/labels/high%20priority) - things to fix ASAP but often of higher complexity.
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
@ -40,18 +46,6 @@ Here are the main rules for naming things in this repo:
|
||||
- template parameters in a `PascalCase`
|
||||
- C++20 concepts names for now in a `PascalCase` but we plan to change it (see <https://github.com/mpusz/units/issues/93> for more details)
|
||||
|
||||
## Code Formatting
|
||||
|
||||
Please use `clang-format-15` for code formatting with the `.clang-format` file provided in the repo.
|
||||
|
||||
If you are unable to install or use `clang-format-15`, here are the main rules to follow:
|
||||
|
||||
- LF line endings
|
||||
- 2 spaces for indentation
|
||||
- `requires` clause indented with 2 spaces as well
|
||||
- no indentation for namespaces
|
||||
- function opening brace in the new line
|
||||
- all other opening braces attached to the current context at the end of the same line
|
||||
|
||||
## Backward Compatibility
|
||||
|
||||
@ -59,3 +53,12 @@ Before submission, please remember to check if the code compiles fine on the sup
|
||||
The CI will check it anyway but it is good to check at least some of the configurations before pushing changes.
|
||||
Especially older compilers can be tricky as those do not support all the C++20 features well enough. The official
|
||||
list of supported compilers can be always found on our [Usage page](https://mpusz.github.io/units/usage.html).
|
||||
|
||||
|
||||
## Where to start?
|
||||
|
||||
If you are looking for a good issue to start with, please check the following:
|
||||
|
||||
- [good first issue](https://github.com/mpusz/units/labels/good%20first%20issue) - issues that should be pretty simple to implement.
|
||||
- [help wanted](https://github.com/mpusz/units/labels/help%20wanted) - issues that typically are a bit more involved than beginner issues.
|
||||
- [high priority](https://github.com/mpusz/units/labels/high%20priority) - things to fix ASAP but often of higher complexity.
|
||||
|
27
README.md
27
README.md
@ -1,11 +1,15 @@
|
||||
[](./LICENSE.md)
|
||||
[](https://github.com/mpusz/units/actions?query=workflow%3A%22Conan%20CI%22+branch%3Amaster)
|
||||
[](https://github.com/mpusz/units/actions?query=workflow%3A%22CMake+Test+Package+CI%22+branch%3Amaster)
|
||||
[](https://github.com/mpusz/units/actions?query=workflow%3A%22Check%20CI%22+branch%3Amaster)
|
||||
[](https://github.com/mpusz/units/actions?query=workflow%3ADocumentation+branch%3Amaster)
|
||||
[](https://conan.io/center/mp-units)
|
||||
[](https://en.cppreference.com/w/cpp/compiler_support#cpp20)
|
||||
|
||||
[](https://github.com/mpusz/units/actions?query=workflow%3A%22Conan%20CI%22+branch%3Amaster)
|
||||
[](https://github.com/mpusz/units/actions?query=workflow%3A%22CMake+Test+Package+CI%22+branch%3Amaster)
|
||||
[](https://github.com/mpusz/units/actions?query=workflow%3A%22Check%20CI%22+branch%3Amaster)
|
||||
[](https://github.com/mpusz/units/actions?query=workflow%3ADocumentation+branch%3Amaster)
|
||||
|
||||
[](https://conan.io/center/mp-units)
|
||||
[](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units/0.8.0)
|
||||
|
||||
|
||||
# `mp-units` - A Units Library for C++
|
||||
|
||||
**The mp-units library is the subject of ISO standardization for C++23/26. More on this can
|
||||
@ -22,6 +26,15 @@ An extensive project documentation including installation instructions and user'
|
||||
guide can be found on [mp-units GitHub Pages](https://mpusz.github.io/units).
|
||||
|
||||
|
||||
## Terms and Definitions
|
||||
|
||||
This project uses the official metrology vocabulary defined by the ISO and BIPM.
|
||||
Please familiarize yourself with those terms to better understand the documentation
|
||||
and improve domain-related communication and discussions. You can find essential
|
||||
project-related definitions in [our documentation's "Glossary" chapter](https://mpusz.github.io/units/glossary.html).
|
||||
Even more terms are provided in the official vocabulary of the [ISO](https://www.iso.org/obp/ui#iso:std:iso-iec:guide:99:ed-1:v2:en)
|
||||
and [BIPM](https://jcgm.bipm.org/vim/en).
|
||||
|
||||
## TL;DR
|
||||
|
||||
`mp-units` is a compile-time enabled Modern C++ library that provides compile-time dimensional
|
||||
@ -59,7 +72,7 @@ static_assert(10 * km / (5 * km) == 2);
|
||||
static_assert(1000 / (1 * s) == 1 * kHz);
|
||||
```
|
||||
|
||||
_Try it on the [Compiler Explorer](https://godbolt.org/z/5dvY8Woh1)._
|
||||
_Try it on the [Compiler Explorer](https://godbolt.org/z/qbbbnfK3s)._
|
||||
|
||||
This library requires some C++20 features (concepts, classes as NTTPs, ...). Thanks to
|
||||
them the user gets a powerful but still easy to use interface and all unit conversions
|
||||
@ -107,4 +120,4 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
_Try it on the [Compiler Explorer](https://godbolt.org/z/bcb87Kvea)._
|
||||
_Try it on the [Compiler Explorer](https://godbolt.org/z/b4a3Ya6dY)._
|
||||
|
134
conanfile.py
134
conanfile.py
@ -24,19 +24,19 @@ import os
|
||||
import re
|
||||
|
||||
from conan import ConanFile
|
||||
from conan.errors import ConanInvalidConfiguration
|
||||
from conan.tools.build import check_min_cppstd
|
||||
from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
|
||||
from conan.tools.files import copy, load, rmdir
|
||||
from conan.tools.scm import Version
|
||||
from conans.errors import ConanInvalidConfiguration
|
||||
|
||||
required_conan_version = ">=1.50.0"
|
||||
required_conan_version = ">=2.0.0"
|
||||
|
||||
|
||||
class MPUnitsConan(ConanFile):
|
||||
name = "mp-units"
|
||||
homepage = "https://github.com/mpusz/units"
|
||||
description = "Physical Units library for C++"
|
||||
description = "Physical Quantities and Units library for C++"
|
||||
topics = (
|
||||
"units",
|
||||
"dimensions",
|
||||
@ -45,15 +45,15 @@ class MPUnitsConan(ConanFile):
|
||||
"physical-quantities",
|
||||
"physical-units",
|
||||
"system-of-units",
|
||||
"cpp23",
|
||||
"cpp20",
|
||||
"system-of-quantities",
|
||||
"isq",
|
||||
"si",
|
||||
"library",
|
||||
"quantity-manipulation",
|
||||
)
|
||||
license = "MIT"
|
||||
url = "https://github.com/mpusz/units"
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
requires = "gsl-lite/0.40.0"
|
||||
settings = "os", "arch", "compiler", "build_type"
|
||||
exports = ["LICENSE.md"]
|
||||
exports_sources = [
|
||||
"docs/*",
|
||||
@ -63,24 +63,34 @@ class MPUnitsConan(ConanFile):
|
||||
"example/*",
|
||||
"CMakeLists.txt",
|
||||
]
|
||||
package_type = "header-library"
|
||||
no_copy_source = True
|
||||
generators = "cmake_paths"
|
||||
|
||||
@property
|
||||
def _min_cppstd(self):
|
||||
return "20"
|
||||
|
||||
@property
|
||||
def _minimum_compilers_version(self):
|
||||
return {"gcc": "10.3", "clang": "12", "apple-clang": "13", "msvc": "192"}
|
||||
|
||||
@property
|
||||
def _build_all(self):
|
||||
return bool(self.conf["user.build:all"])
|
||||
return bool(self.conf.get("user.build:all", default=False))
|
||||
|
||||
@property
|
||||
def _skip_la(self):
|
||||
return bool(self.conf.get("user.build:skip_la", default=False))
|
||||
|
||||
@property
|
||||
def _skip_docs(self):
|
||||
return bool(self.conf["user.build:skip_docs"])
|
||||
return bool(self.conf.get("user.build:skip_docs", default=True))
|
||||
|
||||
@property
|
||||
def _use_libfmt(self):
|
||||
compiler = self.settings.compiler
|
||||
version = Version(self.settings.compiler.version)
|
||||
std_support = (
|
||||
compiler == "Visual Studio" and version >= 17 and compiler.cppstd == 23
|
||||
) or (compiler == "msvc" and version >= 193 and compiler.cppstd == 23)
|
||||
std_support = compiler == "msvc" and version >= 193 and compiler.cppstd == 23
|
||||
return not std_support
|
||||
|
||||
@property
|
||||
@ -89,14 +99,6 @@ class MPUnitsConan(ConanFile):
|
||||
version = Version(self.settings.compiler.version)
|
||||
return "clang" in compiler and compiler.libcxx == "libc++" and version < 14
|
||||
|
||||
@property
|
||||
def _msvc_version(self):
|
||||
compiler = self.settings.compiler
|
||||
if compiler.update:
|
||||
return int(f"{compiler.version}{compiler.update}")
|
||||
else:
|
||||
return int(f"{compiler.version}0")
|
||||
|
||||
def set_version(self):
|
||||
content = load(self, os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
|
||||
version = re.search(
|
||||
@ -105,51 +107,42 @@ class MPUnitsConan(ConanFile):
|
||||
self.version = version.strip()
|
||||
|
||||
def requirements(self):
|
||||
self.requires("gsl-lite/0.40.0")
|
||||
if self._use_libfmt:
|
||||
self.requires("fmt/8.1.1")
|
||||
|
||||
if self._use_range_v3:
|
||||
self.requires("range-v3/0.11.0")
|
||||
|
||||
def build_requirements(self):
|
||||
if self._build_all:
|
||||
self.test_requires("catch2/3.1.0")
|
||||
self.test_requires("wg21-linear_algebra/0.7.2")
|
||||
if not self._skip_la:
|
||||
self.test_requires("wg21-linear_algebra/0.7.3")
|
||||
if not self._skip_docs:
|
||||
self.tool_requires("doxygen/1.9.4")
|
||||
|
||||
# TODO Replace with `valdate()` for Conan 2.0 (https://github.com/conan-io/conan/issues/10723)
|
||||
def configure(self):
|
||||
def validate(self):
|
||||
check_min_cppstd(self, self._min_cppstd)
|
||||
|
||||
def loose_lt_semver(v1, v2):
|
||||
lv1 = [int(v) for v in v1.split(".")]
|
||||
lv2 = [int(v) for v in v2.split(".")]
|
||||
min_length = min(len(lv1), len(lv2))
|
||||
return lv1[:min_length] < lv2[:min_length]
|
||||
|
||||
compiler = self.settings.compiler
|
||||
version = Version(self.settings.compiler.version)
|
||||
if compiler == "gcc":
|
||||
if version < 10:
|
||||
raise ConanInvalidConfiguration("mp-units requires at least g++-10")
|
||||
elif compiler == "clang":
|
||||
if version < 12:
|
||||
raise ConanInvalidConfiguration("mp-units requires at least clang++-12")
|
||||
elif compiler == "apple-clang":
|
||||
if version < 13:
|
||||
raise ConanInvalidConfiguration(
|
||||
"mp-units requires at least AppleClang 13"
|
||||
)
|
||||
elif compiler == "Visual Studio":
|
||||
if version < 16:
|
||||
raise ConanInvalidConfiguration(
|
||||
"mp-units requires at least Visual Studio 16.9"
|
||||
)
|
||||
elif compiler == "msvc":
|
||||
if self._msvc_version < 1928:
|
||||
raise ConanInvalidConfiguration("mp-units requires at least MSVC 19.28")
|
||||
else:
|
||||
raise ConanInvalidConfiguration("Unsupported compiler")
|
||||
check_min_cppstd(self, 20)
|
||||
min_version = self._minimum_compilers_version.get(str(compiler))
|
||||
if min_version and loose_lt_semver(str(compiler.version), min_version):
|
||||
raise ConanInvalidConfiguration(
|
||||
f"{self.ref} requires at least {compiler} {min_version} ({compiler.version} in use)"
|
||||
)
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
|
||||
def generate(self):
|
||||
tc = CMakeToolchain(self)
|
||||
tc.variables["UNITS_BUILD_LA"] = self._build_all and not self._skip_la
|
||||
tc.variables["UNITS_BUILD_DOCS"] = self._build_all and not self._skip_docs
|
||||
tc.variables["UNITS_USE_LIBFMT"] = self._use_libfmt
|
||||
tc.generate()
|
||||
@ -182,7 +175,7 @@ class MPUnitsConan(ConanFile):
|
||||
|
||||
# core
|
||||
self.cpp_info.components["core"].requires = ["gsl-lite::gsl-lite"]
|
||||
if compiler == "Visual Studio":
|
||||
if compiler == "msvc":
|
||||
self.cpp_info.components["core"].cxxflags = ["/utf-8"]
|
||||
if self._use_range_v3:
|
||||
self.cpp_info.components["core"].requires.append("range-v3::range-v3")
|
||||
@ -192,29 +185,32 @@ class MPUnitsConan(ConanFile):
|
||||
self.cpp_info.components["core-fmt"].requires = ["core"]
|
||||
if self._use_libfmt:
|
||||
self.cpp_info.components["core-fmt"].requires.append("fmt::fmt")
|
||||
self.cpp_info.components["utility"].requires = ["core", "isq", "si", "angular"]
|
||||
self.cpp_info.components["isq"].requires = ["core"]
|
||||
self.cpp_info.components["isq-natural"].requires = ["isq"]
|
||||
self.cpp_info.components["angular"].requires = ["isq"]
|
||||
self.cpp_info.components["isq_angular"].requires = ["isq", "angular"]
|
||||
self.cpp_info.components["natural"].requires = ["isq"]
|
||||
self.cpp_info.components["si"].requires = ["isq"]
|
||||
self.cpp_info.components["si-cgs"].requires = ["si"]
|
||||
self.cpp_info.components["si-fps"].requires = ["si-international"]
|
||||
self.cpp_info.components["si-hep"].requires = ["si"]
|
||||
self.cpp_info.components["si-iau"].requires = ["si"]
|
||||
self.cpp_info.components["si-imperial"].requires = ["si"]
|
||||
self.cpp_info.components["si-international"].requires = ["si"]
|
||||
self.cpp_info.components["si-typographic"].requires = ["si"]
|
||||
self.cpp_info.components["si-uscs"].requires = ["si"]
|
||||
self.cpp_info.components["isq-iec80000"].requires = ["si"]
|
||||
self.cpp_info.components["cgs"].requires = ["si"]
|
||||
self.cpp_info.components["hep"].requires = ["si"]
|
||||
self.cpp_info.components["iau"].requires = ["si"]
|
||||
self.cpp_info.components["imperial"].requires = ["si"]
|
||||
self.cpp_info.components["international"].requires = ["si"]
|
||||
self.cpp_info.components["typographic"].requires = ["usc"]
|
||||
self.cpp_info.components["usc"].requires = ["international"]
|
||||
self.cpp_info.components["iec80000"].requires = ["isq", "si"]
|
||||
self.cpp_info.components["systems"].requires = [
|
||||
"isq",
|
||||
"isq-natural",
|
||||
"angular",
|
||||
"isq_angular",
|
||||
"natural",
|
||||
"si",
|
||||
"si-cgs",
|
||||
"si-fps",
|
||||
"si-hep",
|
||||
"si-iau",
|
||||
"si-imperial",
|
||||
"si-international",
|
||||
"si-typographic",
|
||||
"si-uscs",
|
||||
"isq-iec80000",
|
||||
"cgs",
|
||||
"hep",
|
||||
"iau",
|
||||
"imperial",
|
||||
"international",
|
||||
"typographic",
|
||||
"usc",
|
||||
"iec80000",
|
||||
]
|
||||
|
@ -46,6 +46,10 @@ set(unitsSphinxDocs
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/units.svg"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/quantity_like.svg"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG.md"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/defining_systems.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/defining_systems/angular_units.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/defining_systems/isq.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/defining_systems/si.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/design.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/design/directories.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/design/downcasting.rst"
|
||||
@ -82,7 +86,6 @@ set(unitsSphinxDocs
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/kalman.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/faq.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/angular_units.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/arithmetics.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/basic_concepts.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/constants.rst"
|
||||
|
9
docs/defining_systems.rst
Normal file
9
docs/defining_systems.rst
Normal file
@ -0,0 +1,9 @@
|
||||
Defining Systems
|
||||
================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
defining_systems/isq
|
||||
defining_systems/si
|
||||
defining_systems/angular_units
|
@ -59,6 +59,36 @@ Paul Quincey summarizes that with the above in action:
|
||||
can be measured in terms of the Planck constant.
|
||||
|
||||
|
||||
Angular quantities in the :term:`SI`
|
||||
------------------------------------
|
||||
|
||||
Even though the :term:`SI` somehow ignores the dimensionality of angle:
|
||||
|
||||
Plane and solid angles, when expressed in radians and steradians respectively, are in effect
|
||||
also treated within the SI as quantities with the unit one. The symbols :math:`rad`
|
||||
and :math:`sr` are written explicitly where appropriate, in order to emphasize that, for radians or
|
||||
steradians, the quantity being considered is, or involves the plane angle or solid angle
|
||||
respectively. For steradians it emphasizes the distinction between units of flux and intensity
|
||||
in radiometry and photometry for example. However, it is a long-established practice in
|
||||
mathematics and across all areas of science to make use of :math:`rad = 1` and :math:`sr = 1`.
|
||||
For historical reasons the radian and steradian are treated as derived units.
|
||||
|
||||
It also explicitly states:
|
||||
|
||||
The SI unit of frequency is hertz, the SI unit of angular velocity and angular frequency is
|
||||
radian per second, and the SI unit of activity is becquerel, implying counts per second.
|
||||
Although it is formally correct to write all three of these units as the reciprocal second, the
|
||||
use of the different names emphasizes the different nature of the quantities concerned. It is
|
||||
especially important to carefully distinguish frequencies from angular frequencies, because
|
||||
by definition their numerical values differ by a factor of :math:`2\pi`. Ignoring this fact may cause
|
||||
an error of :math:`2\pi`. Note that in some countries, frequency values are conventionally expressed
|
||||
using “cycle/s” or “cps” instead of the SI unit :math:`Hz`, although “cycle” and “cps” are not units
|
||||
in the SI. Note also that it is common, although not recommended, to use the term
|
||||
frequency for quantities expressed in :math:`rad/s`. Because of this, it is recommended that
|
||||
quantities called “frequency”, “angular frequency”, and “angular velocity” always be given
|
||||
explicit units of :math:`Hz` or :math:`rad/s`` and not :math:`s^{-1}`.
|
||||
|
||||
|
||||
Angular quantities in the library
|
||||
---------------------------------
|
||||
|
48
docs/defining_systems/isq.rst
Normal file
48
docs/defining_systems/isq.rst
Normal file
@ -0,0 +1,48 @@
|
||||
.. namespace:: units
|
||||
|
||||
International System of Quantities (ISQ)
|
||||
========================================
|
||||
|
||||
According to [ISO80000]_:
|
||||
|
||||
The system of quantities, including the relations among them the quantities used as the basis of the units of
|
||||
the SI, is named the **International System of Quantities**, denoted "ISQ", in all languages.
|
||||
|
||||
|
||||
Base dimensions and their symbols
|
||||
---------------------------------
|
||||
|
||||
According to the [SIBrochure]_:
|
||||
|
||||
Physical quantities can be organized in a system of dimensions, where the system used is
|
||||
decided by convention. Each of the seven base quantities used in the SI is regarded as
|
||||
having its own dimension. The symbols used for the base quantities and the symbols used
|
||||
to denote their dimension are shown in Table 3.
|
||||
|
||||
Following that the library provides the following definitions::
|
||||
|
||||
namespace units::isq {
|
||||
|
||||
template<Unit U> struct dim_time : base_dimension<"T", U> {};
|
||||
template<Unit U> struct dim_length : base_dimension<"L", U> {};
|
||||
template<Unit U> struct dim_mass : base_dimension<"M", U> {};
|
||||
template<Unit U> struct dim_electric_current : base_dimension<"I", U> {};
|
||||
template<Unit U> struct dim_thermodynamic_temperature : base_dimension<"Θ", U> {};
|
||||
template<Unit U> struct dim_amount_of_substance : base_dimension<"N", U> {};
|
||||
template<Unit U> struct dim_luminous_intensity : base_dimension<"J", U> {};
|
||||
|
||||
}
|
||||
|
||||
Base dimension symbols provided above are consistently defined by both [SIBrochure]_ and [ISO80000]_.
|
||||
|
||||
|
||||
Derived dimensions
|
||||
------------------
|
||||
|
||||
[SIBrochure]_ states:
|
||||
|
||||
Since the number of quantities is without limit, it is not possible to
|
||||
provide a complete list of derived quantities and derived units.
|
||||
|
||||
The authors of this library decided to limit the set of defined quantities to all
|
||||
quantities defined in the [ISO80000]_ series of documents.
|
231
docs/defining_systems/si.rst
Normal file
231
docs/defining_systems/si.rst
Normal file
@ -0,0 +1,231 @@
|
||||
.. namespace:: units
|
||||
|
||||
The International System of Units (SI)
|
||||
======================================
|
||||
|
||||
The :term:`SI` system is defined in the [SIBrochure]_ and standardizes units for quantities provided in
|
||||
the :term:`ISQ` system:
|
||||
|
||||
The SI is a consistent system of units for use in all aspects of life, including international
|
||||
trade, manufacturing, security, health and safety, protection of the environment, and in the
|
||||
basic science that underpins all of these. The system of quantities underlying the SI and the
|
||||
equations relating them are based on the present description of nature and are familiar to all
|
||||
scientists, technologists and engineers.
|
||||
|
||||
As the :term:`SI` is defined on top of the :term:`ISQ` the C++ namespace for all of its definitions
|
||||
is ``units::isq::si``.
|
||||
|
||||
Base units
|
||||
----------
|
||||
|
||||
Even though from 2019 the :term:`SI` system is defined in terms of the `Defining constants`_,
|
||||
base units still are really important. As the [SIBrochure]_ states:
|
||||
|
||||
Prior to the definitions adopted in 2018, the SI was defined through seven base units from
|
||||
which the derived units were constructed as products of powers of the base units. Defining
|
||||
the SI by fixing the numerical values of seven defining constants has the effect that this
|
||||
distinction is, in principle, not needed, since all units, base as well as derived units, may be
|
||||
constructed directly from the defining constants. Nevertheless, the concept of base and
|
||||
derived units is maintained because it is useful and historically well established, noting
|
||||
also that the ISO/IEC 80000 series of Standards specify base and derived quantities which
|
||||
necessarily correspond to the SI base and derived units defined here.
|
||||
|
||||
The base units and quantities of the :term:`SI` system are defined as follows::
|
||||
|
||||
namespace units::isq::si {
|
||||
|
||||
struct second : named_unit<second, "s"> {};
|
||||
struct dim_time : isq::dim_time<second> {};
|
||||
template<UnitOf<dim_time> U, Representation Rep = double>
|
||||
using time = quantity<dim_time, U, Rep>;
|
||||
|
||||
struct metre : named_unit<metre, "m"> {};
|
||||
struct dim_length : isq::dim_length<metre> {};
|
||||
template<UnitOf<dim_length> U, Representation Rep = double>
|
||||
using length = quantity<dim_length, U, Rep>;
|
||||
|
||||
struct gram : named_unit<gram, "g"> {};
|
||||
struct kilogram : prefixed_unit<kilogram, kilo, gram> {};
|
||||
struct dim_mass : isq::dim_mass<kilogram> {};
|
||||
template<UnitOf<dim_mass> U, Representation Rep = double>
|
||||
using mass = quantity<dim_mass, U, Rep>;
|
||||
|
||||
struct ampere : named_unit<ampere, "A"> {};
|
||||
struct dim_electric_current : isq::dim_electric_current<ampere> {};
|
||||
template<UnitOf<dim_electric_current> U, Representation Rep = double>
|
||||
using electric_current = quantity<dim_electric_current, U, Rep>;
|
||||
|
||||
struct kelvin : named_unit<kelvin, "K"> {};
|
||||
struct dim_thermodynamic_temperature : isq::dim_thermodynamic_temperature<kelvin> {};
|
||||
template<UnitOf<dim_thermodynamic_temperature> U, Representation Rep = double>
|
||||
using thermodynamic_temperature = quantity<dim_thermodynamic_temperature, U, Rep>;
|
||||
|
||||
struct mole : named_unit<mole, "mol"> {};
|
||||
struct dim_amount_of_substance : isq::dim_amount_of_substance<mole> {};
|
||||
template<UnitOf<dim_amount_of_substance> U, Representation Rep = double>
|
||||
using amount_of_substance = quantity<dim_amount_of_substance, U, Rep>;
|
||||
|
||||
struct candela : named_unit<candela, "cd"> {};
|
||||
struct dim_luminous_intensity : isq::dim_luminous_intensity<candela> {};
|
||||
template<UnitOf<dim_luminous_intensity> U, Representation Rep = double>
|
||||
using luminous_intensity = quantity<dim_luminous_intensity, U, Rep>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Derived units
|
||||
-------------
|
||||
|
||||
The [SIBrochure]_ states:
|
||||
|
||||
Derived units are defined as products of powers of the base units. When the numerical
|
||||
factor of this product is one, the derived units are called coherent derived units. The base
|
||||
and coherent derived units of the SI form a coherent set, designated the set of coherent SI
|
||||
units. The word “coherent” here means that equations between the numerical values of
|
||||
quantities take exactly the same form as the equations between the quantities themselves.
|
||||
Some of the coherent derived units in the SI are given special names. ... Together with the
|
||||
seven base units they form the core of the set of SI units. All other SI units are combinations
|
||||
of some of these 29 units.
|
||||
|
||||
|
||||
Unit prefixes
|
||||
-------------
|
||||
|
||||
According to [SIBrochure]_:
|
||||
|
||||
Prefixes may be used with any of the 29 SI units with special names with
|
||||
the exception of the base unit kilogram.
|
||||
|
||||
Here is a complete list of all the :term:`SI` prefixes supported by the library::
|
||||
|
||||
namespace si {
|
||||
|
||||
struct yocto : prefix<yocto, "y", mag_power<10, -24>()> {};
|
||||
struct zepto : prefix<zepto, "z", mag_power<10, -21>()> {};
|
||||
struct atto : prefix<atto, "a", mag_power<10, -18>()> {};
|
||||
struct femto : prefix<femto, "f", mag_power<10, -15>()> {};
|
||||
struct pico : prefix<pico, "p", mag_power<10, -12>()> {};
|
||||
struct nano : prefix<nano, "n", mag_power<10, -9>()> {};
|
||||
struct micro : prefix<micro, basic_symbol_text{"\u00b5", "u"},
|
||||
mag_power<10, -6>()> {};
|
||||
struct milli : prefix<milli, "m", mag_power<10, -3>()> {};
|
||||
struct centi : prefix<centi, "c", mag_power<10, -2>()> {};
|
||||
struct deci : prefix<deci, "d", mag_power<10, -1>()> {};
|
||||
struct deca : prefix<deca, "da", mag_power<10, 1>()> {};
|
||||
struct hecto : prefix<hecto, "h", mag_power<10, 2>()> {};
|
||||
struct kilo : prefix<kilo, "k", mag_power<10, 3>()> {};
|
||||
struct mega : prefix<mega, "M", mag_power<10, 6>()> {};
|
||||
struct giga : prefix<giga, "G", mag_power<10, 9>()> {};
|
||||
struct tera : prefix<tera, "T", mag_power<10, 12>()> {};
|
||||
struct peta : prefix<peta, "P", mag_power<10, 15>()> {};
|
||||
struct exa : prefix<exa, "E", mag_power<10, 18>()> {};
|
||||
struct zetta : prefix<zetta, "Z", mag_power<10, 21>()> {};
|
||||
struct yotta : prefix<yotta, "Y", mag_power<10, 24>()> {};
|
||||
|
||||
}
|
||||
|
||||
|
||||
Other definitions for names units
|
||||
---------------------------------
|
||||
|
||||
For all of the above units the library also provides:
|
||||
|
||||
- prefixed versions using SI prefixes::
|
||||
|
||||
namespace units::isq::si {
|
||||
|
||||
struct millisecond : prefixed_unit<millisecond, milli, second> {};
|
||||
|
||||
}
|
||||
|
||||
- :ref:`framework/quantities:Quantity References (Experimental)`::
|
||||
|
||||
namespace units::isq::si {
|
||||
|
||||
namespace time_references {
|
||||
|
||||
inline constexpr auto s = reference<dim_time, second>{};
|
||||
|
||||
}
|
||||
|
||||
namespace references {
|
||||
|
||||
using namespace time_references;
|
||||
|
||||
}
|
||||
|
||||
- :ref:`framework/quantities:Unit-Specific Aliases (Experimental)`::
|
||||
|
||||
namespace units::aliases::isq::si::inline time {
|
||||
|
||||
template<Representation Rep = double>
|
||||
using s = units::isq::si::time<units::isq::si::second, Rep>;
|
||||
|
||||
}
|
||||
|
||||
- :ref:`framework/quantities:User Defined Literals (Experimental)`::
|
||||
|
||||
namespace units::isq::si::inline literals {
|
||||
|
||||
constexpr auto operator"" _q_s(unsigned long long l)
|
||||
{
|
||||
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
|
||||
return time<second, std::int64_t>(static_cast<std::int64_t>(l));
|
||||
}
|
||||
constexpr auto operator"" _q_s(long double l) { return time<second, long double>(l); }
|
||||
|
||||
}
|
||||
|
||||
For some of the units, when accepted by the :term:`SI`, other non-standard scaled versions are also provided::
|
||||
|
||||
namespace units::isq::si {
|
||||
|
||||
struct minute : named_scaled_unit<minute, "min", mag<60>(), second> {};
|
||||
struct hour : named_scaled_unit<hour, "h", mag<60>(), minute> {};
|
||||
struct day : named_scaled_unit<day, "d", mag<24>(), hour> {};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Defining constants
|
||||
------------------
|
||||
|
||||
[SIBrochure]_ states that:
|
||||
|
||||
The definition of the SI units is established in terms of a set of seven defining constants.
|
||||
The complete system of units can be derived from the fixed values of these defining
|
||||
constants, expressed in the units of the SI.
|
||||
|
||||
Those constants are provided in the *units/isq/si/constants.h* header file as::
|
||||
|
||||
namespace units::isq::si::si2019 {
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto hyperfine_structure_transition_frequency = frequency<hertz, Rep>(Rep{9'192'631'770});
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto speed_of_light = speed<metre_per_second, Rep>(299'792'458);
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto planck_constant = energy<joule, Rep>(6.62607015e-34) * time<second, Rep>(1);
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto elementary_charge = electric_charge<coulomb, Rep>(1.602176634e-19);
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto boltzmann_constant = energy<joule, Rep>(1.380649e-23) / thermodynamic_temperature<kelvin, Rep>(1);
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto avogadro_constant = Rep(6.02214076e23) / amount_of_substance<mole, Rep>(1);
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto luminous_efficacy = luminous_flux<lumen, Rep>(683) / power<watt, Rep>(1);
|
||||
|
||||
}
|
||||
|
||||
.. note::
|
||||
|
||||
Please note the nested `si2019` namespace. It is introduced in case those constants were changed/updated
|
||||
by the :term:`SI` in the future.
|
@ -22,5 +22,4 @@ Framework Basics
|
||||
framework/arithmetics
|
||||
framework/constants
|
||||
framework/conversions_and_casting
|
||||
framework/angular_units
|
||||
framework/text_output
|
||||
|
@ -50,6 +50,20 @@ The quantities of derived dimensions are called
|
||||
quantities. This means that they are created by multiplying or dividing
|
||||
quantities of other dimensions.
|
||||
|
||||
The [SIBrochure]_ states:
|
||||
|
||||
All other quantities, with the exception of counts, are derived quantities, which may be
|
||||
written in terms of base quantities according to the equations of physics. The dimensions of
|
||||
the derived quantities are written as products of powers of the dimensions of the base
|
||||
quantities using the equations that relate the derived quantities to the base quantities.
|
||||
In general the dimension of any quantity :math:`Q` is written in the form of a dimensional product,
|
||||
|
||||
:math:`dim Q = T^\alpha L^\beta M^\gamma I^\delta \Theta^\varepsilon N^\zeta J^\eta`
|
||||
|
||||
where the exponents :math:`\alpha`, :math:`\beta`, :math:`\gamma`, :math:`\delta`, :math:`\varepsilon`,
|
||||
:math:`\zeta` and :math:`\eta`, which are generally small integers, which can be positive,
|
||||
negative, or zero, are called the dimensional exponents.
|
||||
|
||||
Looking at the previous code snippets the area, speed, or frequency are
|
||||
the examples of such quantities. Each derived quantity can be represented
|
||||
as a unique list of exponents of base quantities. For example:
|
||||
|
@ -313,7 +313,7 @@ Quantity References vs Unit-specific Aliases
|
||||
- Unit-specific Aliases
|
||||
|
||||
As aliases are defined in terms of types rather variables no major shadowing issues were found
|
||||
so far. In case of identifiers abiguity it was always possible to disambiguate with more
|
||||
so far. In case of identifiers ambiguity it was always possible to disambiguate with more
|
||||
namespaces prefixed in front of the alias.
|
||||
|
||||
2. Adjustable verbosity
|
||||
@ -385,7 +385,7 @@ Quantity References vs Unit-specific Aliases
|
||||
- Quantity References
|
||||
|
||||
The syntax for references uses ``*`` operator which has some predefined precedence. This operator
|
||||
always takes a magnitude or a reference as ``lhs`` and a reference as ``rhs``. All other comibnations
|
||||
always takes a magnitude or a reference as ``lhs`` and a reference as ``rhs``. All other combinations
|
||||
are not allowed. It means that in order to satisfy the operators precedence sometimes quite a lot
|
||||
of parenthesis have to be sprinkled in the code in order for the code to compile::
|
||||
|
||||
@ -399,7 +399,7 @@ Quantity References vs Unit-specific Aliases
|
||||
|
||||
- Quantity References
|
||||
|
||||
References have only to be defined for named units. Also for the user's conveniance references are
|
||||
References have only to be defined for named units. Also for the user's convenience references are
|
||||
predefined for units raised to a specific power (e.g. ``m2``, ``km3``, etc). All other derived units
|
||||
can be constructed using the provided ones already even if they do not correspond to any predefined
|
||||
dimension::
|
||||
|
@ -49,4 +49,4 @@ Unlike `quantity`, the library provides:
|
||||
- no dimension-specific concepts, such as ``LengthPoint``
|
||||
(there's the dimension-agnostic `QuantityPoint`),
|
||||
- a more limited set of operations on quantity points
|
||||
(see the :ref:`framework/dimensions:Quantity Points` chapter)
|
||||
(see the :ref:`framework/arithmetics:Quantity Points` chapter)
|
||||
|
@ -203,27 +203,27 @@ complete list of all the :term:`SI` prefixes supported by the library::
|
||||
|
||||
namespace si {
|
||||
|
||||
struct yocto : prefix<yocto, "y", pow<-24>(mag<10>())> {};
|
||||
struct zepto : prefix<zepto, "z", pow<-21>(mag<10>())> {};
|
||||
struct atto : prefix<atto, "a", pow<-18>(mag<10>())> {};
|
||||
struct femto : prefix<femto, "f", pow<-15>(mag<10>())> {};
|
||||
struct pico : prefix<pico, "p", pow<-12>(mag<10>())> {};
|
||||
struct nano : prefix<nano, "n", pow<-9>(mag<10>())> {};
|
||||
struct yocto : prefix<yocto, "y", mag_power<10, -24>()> {};
|
||||
struct zepto : prefix<zepto, "z", mag_power<10, -21>()> {};
|
||||
struct atto : prefix<atto, "a", mag_power<10, -18>()> {};
|
||||
struct femto : prefix<femto, "f", mag_power<10, -15>()> {};
|
||||
struct pico : prefix<pico, "p", mag_power<10, -12>()> {};
|
||||
struct nano : prefix<nano, "n", mag_power<10, -9>()> {};
|
||||
struct micro : prefix<micro, basic_symbol_text{"\u00b5", "u"},
|
||||
pow<-6>(mag<10>())> {};
|
||||
struct milli : prefix<milli, "m", pow<-3>(mag<10>())> {};
|
||||
struct centi : prefix<centi, "c", pow<-2>(mag<10>())> {};
|
||||
struct deci : prefix<deci, "d", pow<-1>(mag<10>())> {};
|
||||
struct deca : prefix<deca, "da", pow<1>(mag<10>())> {};
|
||||
struct hecto : prefix<hecto, "h", pow<2>(mag<10>())> {};
|
||||
struct kilo : prefix<kilo, "k", pow<3>(mag<10>())> {};
|
||||
struct mega : prefix<mega, "M", pow<6>(mag<10>())> {};
|
||||
struct giga : prefix<giga, "G", pow<9>(mag<10>())> {};
|
||||
struct tera : prefix<tera, "T", pow<12>(mag<10>())> {};
|
||||
struct peta : prefix<peta, "P", pow<15>(mag<10>())> {};
|
||||
struct exa : prefix<exa, "E", pow<18>(mag<10>())> {};
|
||||
struct zetta : prefix<zetta, "Z", pow<21>(mag<10>())> {};
|
||||
struct yotta : prefix<yotta, "Y", pow<24>(mag<10>())> {};
|
||||
mag_power<10, -6>()> {};
|
||||
struct milli : prefix<milli, "m", mag_power<10, -3>()> {};
|
||||
struct centi : prefix<centi, "c", mag_power<10, -2>()> {};
|
||||
struct deci : prefix<deci, "d", mag_power<10, -1>()> {};
|
||||
struct deca : prefix<deca, "da", mag_power<10, 1>()> {};
|
||||
struct hecto : prefix<hecto, "h", mag_power<10, 2>()> {};
|
||||
struct kilo : prefix<kilo, "k", mag_power<10, 3>()> {};
|
||||
struct mega : prefix<mega, "M", mag_power<10, 6>()> {};
|
||||
struct giga : prefix<giga, "G", mag_power<10, 9>()> {};
|
||||
struct tera : prefix<tera, "T", mag_power<10, 12>()> {};
|
||||
struct peta : prefix<peta, "P", mag_power<10, 15>()> {};
|
||||
struct exa : prefix<exa, "E", mag_power<10, 18>()> {};
|
||||
struct zetta : prefix<zetta, "Z", mag_power<10, 21>()> {};
|
||||
struct yotta : prefix<yotta, "Y", mag_power<10, 24>()> {};
|
||||
|
||||
}
|
||||
|
||||
@ -232,14 +232,14 @@ domain::
|
||||
|
||||
namespace iec80000 {
|
||||
|
||||
struct kibi : prefix<kibi, "Ki", pow<10>(mag<2>())> {};
|
||||
struct mebi : prefix<mebi, "Mi", pow<20>(mag<2>())> {};
|
||||
struct gibi : prefix<gibi, "Gi", pow<30>(mag<2>())> {};
|
||||
struct tebi : prefix<tebi, "Ti", pow<40>(mag<2>())> {};
|
||||
struct pebi : prefix<pebi, "Pi", pow<50>(mag<2>())> {};
|
||||
struct exbi : prefix<exbi, "Ei", pow<60>(mag<2>())> {};
|
||||
struct zebi : prefix<zebi, "Zi", pow<70>(mag<2>())> {};
|
||||
struct yobi : prefix<yobi, "Yi", pow<80>(mag<2>())> {};
|
||||
struct kibi : prefix<kibi, "Ki", mag_power<2, 10>()> {};
|
||||
struct mebi : prefix<mebi, "Mi", mag_power<2, 20>()> {};
|
||||
struct gibi : prefix<gibi, "Gi", mag_power<2, 30>()> {};
|
||||
struct tebi : prefix<tebi, "Ti", mag_power<2, 40>()> {};
|
||||
struct pebi : prefix<pebi, "Pi", mag_power<2, 50>()> {};
|
||||
struct exbi : prefix<exbi, "Ei", mag_power<2, 60>()> {};
|
||||
struct zebi : prefix<zebi, "Zi", mag_power<2, 70>()> {};
|
||||
struct yobi : prefix<yobi, "Yi", mag_power<2, 80>()> {};
|
||||
|
||||
}
|
||||
|
||||
@ -260,6 +260,14 @@ example we can define ``si::kilometre`` as::
|
||||
as ``km²`` would be invalid).
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
[SIBrochure]_ states:
|
||||
|
||||
However, when prefixes are used with SI units, the resulting units are no
|
||||
longer coherent, because the prefix introduces a numerical factor other than one.
|
||||
|
||||
|
||||
Derived Units
|
||||
-------------
|
||||
|
||||
@ -268,10 +276,21 @@ Derived Units
|
||||
names (i.e. ``N`` (newton)) or can be composed from the names of units of quantities
|
||||
used to define thier derived quantity (i.e. ``km/h``).
|
||||
|
||||
The [SIBrochure]_ states:
|
||||
|
||||
Derived units are defined as products of powers of the base units. When the numerical
|
||||
factor of this product is one, the derived units are called coherent derived units. The base
|
||||
and coherent derived units of the SI form a coherent set, designated the set of coherent SI
|
||||
units. The word “coherent” here means that equations between the numerical values of
|
||||
quantities take exactly the same form as the equations between the quantities themselves.
|
||||
|
||||
Derived Named Units
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The [SIBrochure]_ also says:
|
||||
|
||||
Some of the coherent derived units in the SI are given special names.
|
||||
|
||||
Derived named units have a unique symbol (i.e. ``N`` (newton) or ``Pa``
|
||||
(pascal)) and they are defined in the same way as base units (which
|
||||
always have to be a named unit)::
|
||||
|
@ -73,9 +73,9 @@ ISO 80000 [1]_ definitions
|
||||
tensor character.
|
||||
- In a given `system of quantities`:
|
||||
|
||||
- `quantities <quantity>` of the same `kind` have the same quantity dimension,
|
||||
- `quantities <quantity>` of different quantity dimensions are always of different `kinds <kind>`,
|
||||
- `quantities <quantity>` having the same quantity dimension are not necessarily of the same `kind`.
|
||||
- `quantities <quantity>` of the same `kind` have the same quantity dimension,
|
||||
- `quantities <quantity>` of different quantity dimensions are always of different `kinds <kind>`,
|
||||
- `quantities <quantity>` having the same quantity dimension are not necessarily of the same `kind`.
|
||||
|
||||
quantity of dimension one
|
||||
dimensionless quantity
|
||||
@ -168,7 +168,15 @@ ISO 80000 [1]_ definitions
|
||||
value of a quantity
|
||||
value
|
||||
- Number and reference together expressing magnitude of a `quantity`.
|
||||
- The number can be complex.
|
||||
- A quantity value can be presented in more than one way.
|
||||
- In the case of vector or tensor quantities, each component has a quantity value.
|
||||
|
||||
- For example, force acting on a given particle, e.g. in Cartesian components
|
||||
:math:`(F_x; F_y; F_z) = (−31,5; 43,2; 17,0) N`, where
|
||||
:math:`(−31,5; 43,2; 17,0)` is a numerical-value vector and :math:`N` (newton)
|
||||
is the unit, or :math:`(F_x; F_y; F_z) = (−31,5 N; 43,2 N; 17,0 N)`
|
||||
where each component is a quantity.
|
||||
|
||||
|
||||
Other definitions
|
||||
|
@ -30,6 +30,7 @@ with a permissive `MIT license <https://github.com/mpusz/units/blob/master/LICEN
|
||||
introduction
|
||||
quick_start
|
||||
framework
|
||||
defining_systems
|
||||
use_cases
|
||||
design
|
||||
examples
|
||||
|
@ -32,7 +32,7 @@ Here is a small example of possible operations::
|
||||
|
||||
.. admonition:: Try it on Compiler Explorer
|
||||
|
||||
`Example #1 <https://godbolt.org/z/5dvY8Woh1>`_
|
||||
`Example #1 <https://godbolt.org/z/qbbbnfK3s>`_
|
||||
|
||||
This library requires some C++20 features (concepts, classes as
|
||||
:abbr:`NTTP (Non-Type Template Parameter)`, ...). Thanks to them the user gets a powerful
|
||||
@ -81,7 +81,7 @@ of basic library features::
|
||||
|
||||
.. admonition:: Try it on Compiler Explorer
|
||||
|
||||
`Example #2 <https://godbolt.org/z/bcb87Kvea>`_
|
||||
`Example #2 <https://godbolt.org/z/b4a3Ya6dY>`_
|
||||
|
||||
.. seealso::
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
Sotrage Capacity
|
||||
Storage Capacity
|
||||
================
|
||||
|
||||
.. doxygenfile:: iec80000/storage_capacity.h
|
||||
|
4
docs/reference/systems/isq/si/uscs/pressure.rst
Normal file
4
docs/reference/systems/isq/si/uscs/pressure.rst
Normal file
@ -0,0 +1,4 @@
|
||||
Pressure
|
||||
========
|
||||
|
||||
.. doxygenfile:: si/uscs/pressure.h
|
@ -5,3 +5,4 @@ U.S. Customary Units (based on SI)
|
||||
:maxdepth: 2
|
||||
|
||||
si/uscs/length
|
||||
si/uscs/pressure
|
||||
|
@ -2,4 +2,5 @@ References
|
||||
==========
|
||||
|
||||
.. [ISO80000] `ISO 80000-1:2009(E) "Quantities and units — Part 1: General" <https://www.iso.org/standard/30669.html>`_, International Organization for Standardization.
|
||||
.. [Quincey] `"Angles in the SI: a detailed proposal for solving the problem" <https://arxiv.org/pdf/2108.05704.pdf>`_, Quincey, Paul (1 October 2021)
|
||||
.. [SIBrochure] `The International System of Units (SI) <https://www.bipm.org/documents/20126/41483022/SI-Brochure-9-EN.pdf>`_, International Bureau of Weights and Measures (20 May 2019), ISBN 978-92-822-2272-0.
|
||||
.. [Quincey] `"Angles in the SI: a detailed proposal for solving the problem" <https://arxiv.org/pdf/2108.05704.pdf>`_, Quincey, Paul (1 October 2021).
|
||||
|
@ -111,7 +111,7 @@ generators. For example:
|
||||
|
||||
.. note::
|
||||
|
||||
*~/.conan/global.conf* file may also set ``tools.cmake.cmake_layout:build_folder_vars``` which
|
||||
*~/.conan/global.conf* file may also set ``tools.cmake.cmake_layout:build_folder_vars`` which
|
||||
`makes working with several compilers or build configurations easier
|
||||
<https://docs.conan.io/en/latest/reference/conanfile/tools/cmake/cmake_layout.html#multi-setting-option-cmake-layout>`_.
|
||||
For example the below line will force Conan to generate separate CMake presets and folders for each compiler:
|
||||
@ -146,8 +146,8 @@ Specifies how :ref:`design/downcasting:The Downcasting Facility` works:
|
||||
Conan Configuration Properties
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
build_all
|
||||
+++++++++
|
||||
user.build:all
|
||||
++++++++++++++
|
||||
|
||||
**Values**: ``True``/``False``
|
||||
|
||||
@ -158,14 +158,24 @@ To support this it requires some additional Conan build dependencies described i
|
||||
`Repository Structure and Dependencies`_.
|
||||
It also runs unit tests during Conan build (unless ``tools.build:skip_test`` configuration property is set to ``True``)
|
||||
|
||||
skip_docs
|
||||
+++++++++
|
||||
user.build:skip_la
|
||||
++++++++++++++++++
|
||||
|
||||
**Values**: ``True``/``False``
|
||||
|
||||
**Defaulted to**: ``False``
|
||||
|
||||
If `build_all`_ is enabled, among others, Conan installs the documentation generation dependencies (i.e. doxygen) and
|
||||
If `user.build:all`_ is enabled, among others, Conan installs the external `wg21-linear_algebra <https://conan.io/center/wg21-linear_algebra>`_
|
||||
dependency and enables compilation of linear algebra based usage examples. Such behavior can be disabled with this option.
|
||||
|
||||
user.build:skip_docs
|
||||
++++++++++++++++++++
|
||||
|
||||
**Values**: ``True``/``False``
|
||||
|
||||
**Defaulted to**: ``False``
|
||||
|
||||
If `user.build:all`_ is enabled, among others, Conan installs the documentation generation dependencies (i.e. doxygen) and
|
||||
turns on the project documentation generation. Such behavior can be disabled with this option.
|
||||
|
||||
CMake Options
|
||||
@ -181,6 +191,16 @@ UNITS_AS_SYSTEM_HEADERS
|
||||
Exports library as system headers.
|
||||
|
||||
|
||||
UNITS_BUILD_LA
|
||||
++++++++++++++
|
||||
|
||||
**Values**: ``ON``/``OFF``
|
||||
|
||||
**Defaulted to**: ``ON``
|
||||
|
||||
Enables building code depending on the linear algebra library.
|
||||
|
||||
|
||||
UNITS_BUILD_DOCS
|
||||
++++++++++++++++
|
||||
|
||||
@ -387,8 +407,8 @@ differences:
|
||||
.. code-block:: shell
|
||||
|
||||
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -b=outdated -u
|
||||
cmake --preset default
|
||||
cmake --build --preset release
|
||||
cmake --preset conan-default
|
||||
cmake --build --preset conan-release
|
||||
|
||||
|
||||
Install
|
||||
@ -403,8 +423,8 @@ to find it, it is enough to perform the following steps:
|
||||
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing
|
||||
mv CMakeUserPresets.json src
|
||||
cd src
|
||||
cmake --preset default -DCMAKE_INSTALL_PREFIX=<your_installation_path>
|
||||
cmake --build --preset release --target install
|
||||
cmake --preset conan-default -DCMAKE_INSTALL_PREFIX=<your_installation_path>
|
||||
cmake --build --preset conan-release --target install
|
||||
|
||||
|
||||
Contributing (or just building all the tests and examples)
|
||||
@ -414,13 +434,13 @@ In case you would like to build all the source code (with unit tests and example
|
||||
you should:
|
||||
|
||||
1. Use the *CMakeLists.txt* from the top-level directory.
|
||||
2. Run Conan with `build_all`_ = ``True``
|
||||
(use ``-o build_docs=False`` if you want to skip the documentation generation).
|
||||
2. Run Conan with `user.build:all`_ = ``True``
|
||||
(use ``-c user.build:skip_docs=True`` if you want to skip the documentation generation).
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git clone https://github.com/mpusz/units.git && cd units
|
||||
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -c user.build:all=True -c user.build:skip_docs=True -b outdated -u
|
||||
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -c user.build:all=True -c user.build:skip_docs=True -b missing
|
||||
conan build .
|
||||
|
||||
The above will download and install all of the dependencies needed for the development of the library,
|
||||
@ -431,9 +451,9 @@ step with the explicit CMake build:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
cmake --preset default
|
||||
cmake --build --preset release
|
||||
cmake --build --preset release --target test
|
||||
cmake --preset conan-default
|
||||
cmake --build --preset conan-release
|
||||
cmake --build --preset conan-release --target test
|
||||
|
||||
|
||||
Building documentation
|
||||
@ -443,15 +463,15 @@ In case you would like to build the project's documentation, you should:
|
||||
|
||||
1. Use the *CMakeLists.txt* from the top-level directory.
|
||||
2. Obtain Python dependencies.
|
||||
3. Run Conan with `build_all`_ = ``True``.
|
||||
3. Run Conan with `user.build:all`_ = ``True``.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git clone https://github.com/mpusz/units.git && cd units
|
||||
pip3 install -r docs/requirements.txt
|
||||
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -c user.build:all=True -b missing
|
||||
cmake --preset default
|
||||
cmake --build --preset release --target documentation
|
||||
cmake --preset conan-default
|
||||
cmake --build --preset conan-release --target documentation
|
||||
|
||||
The above will download and install all of the dependencies needed and build the documentation.
|
||||
|
||||
@ -463,7 +483,7 @@ To test CMake installation and Conan packaging or create a Conan package run:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
conan create . <username>/<channel> -pr <your_conan_profile> -s compiler.cppstd=20 -c user.build:all=True -c user.build:skip_docs=True -b outdated -u
|
||||
conan create . <username>/<channel> -pr <your_conan_profile> -s compiler.cppstd=20 -c user.build:all=True -c user.build:skip_docs=True -b missing
|
||||
|
||||
The above will create a Conan package and run tests provided in *./test_package* directory.
|
||||
|
||||
|
@ -14,7 +14,7 @@ enough to be used with other Linear Algebra libraries existing on the market.
|
||||
or `Conan <https://conan.io/center/wg21-linear_algebra>`_.
|
||||
Also, to simplify the examples all of them assume::
|
||||
|
||||
using namespace std::math;
|
||||
using namespace STD_LA;
|
||||
|
||||
|
||||
Linear Algebra of Quantities
|
||||
@ -27,16 +27,16 @@ The official :term:`quantity` definition states:
|
||||
|
||||
So the most common use case would be to create a vector or matrix of quantities::
|
||||
|
||||
fs_vector<si::length<si::metre>, 3> v = { 1 * m, 2 * m, 3 * m };
|
||||
fs_vector<si::length<si::metre>, 3> u = { 3 * m, 2 * m, 1 * m };
|
||||
fs_vector<si::length<si::kilometre>, 3> t = { 3 * km, 2 * km, 1 * km };
|
||||
fixed_size_column_vector<si::length<si::metre>, 3> v = { 1 * m, 2 * m, 3 * m };
|
||||
fixed_size_column_vector<si::length<si::metre>, 3> u = { 3 * m, 2 * m, 1 * m };
|
||||
fixed_size_column_vector<si::length<si::kilometre>, 3> t = { 3 * km, 2 * km, 1 * km };
|
||||
|
||||
Having such definitions we can perform full dimensional analysis operations for the operations
|
||||
allowed by the Linear Algebra rules. For example::
|
||||
|
||||
std::cout << "v + u = " << v + u << "\n";
|
||||
std::cout << "v + t = " << v + t << "\n";
|
||||
std::cout << "t[m] = " << fs_vector<si::length<si::metre>, 3>(t) << "\n";
|
||||
std::cout << "t[m] = " << fixed_size_column_vector<si::length<si::metre>, 3>(t) << "\n";
|
||||
std::cout << "v * u = " << v * u << "\n";
|
||||
std::cout << "2 * m * v = " << 2 * m * v << "\n";
|
||||
|
||||
@ -66,9 +66,9 @@ types provided to a `quantity` class template.
|
||||
|
||||
With this the above vector definitions can be rewritten as follows::
|
||||
|
||||
si::length<si::metre, fs_vector<int, 3>> v(fs_vector<int, 3>{ 1, 2, 3 });
|
||||
si::length<si::metre, fs_vector<int, 3>> u(fs_vector<int, 3>{ 3, 2, 1 });
|
||||
si::length<si::kilometre, fs_vector<int, 3>> t(fs_vector<int, 3>{ 3, 2, 1 });
|
||||
si::length<si::metre, fixed_size_column_vector<int, 3>> v(fixed_size_column_vector<int, 3>{ 1, 2, 3 });
|
||||
si::length<si::metre, fixed_size_column_vector<int, 3>> u(fixed_size_column_vector<int, 3>{ 3, 2, 1 });
|
||||
si::length<si::kilometre, fixed_size_column_vector<int, 3>> t(fixed_size_column_vector<int, 3>{ 3, 2, 1 });
|
||||
|
||||
Now the same code doing basic Linear Algebra operations will provide the following
|
||||
output:
|
||||
|
@ -1,10 +1,10 @@
|
||||
Math
|
||||
====
|
||||
|
||||
.. doxygenfunction:: units::pow
|
||||
.. doxygenfunction:: mp_units::pow
|
||||
|
||||
.. doxygenfunction:: units::sqrt
|
||||
.. doxygenfunction:: mp_units::sqrt
|
||||
|
||||
.. doxygenfunction:: units::abs
|
||||
.. doxygenfunction:: mp_units::abs
|
||||
|
||||
.. doxygenfunction:: units::epsilon
|
||||
.. doxygenfunction:: mp_units::epsilon
|
||||
|
@ -60,9 +60,5 @@ add_example(
|
||||
add_example(total_energy mp-units::core-io mp-units::si mp-units::natural mp-units::utility)
|
||||
add_example(unmanned_aerial_vehicle mp-units::core-fmt mp-units::core-io mp-units::si mp-units::international mp-units::utility example_utils)
|
||||
|
||||
find_package(wg21_linear_algebra CONFIG REQUIRED)
|
||||
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)
|
||||
target_link_libraries(linear_algebra PRIVATE wg21_linear_algebra::wg21_linear_algebra)
|
||||
|
||||
add_subdirectory(glide_computer)
|
||||
add_subdirectory(kalman_filter)
|
||||
|
@ -113,7 +113,7 @@ void calcs_comparison()
|
||||
const auto L1A = 2.f * fm;
|
||||
const auto L2A = 3.f * fm;
|
||||
const auto LrA = L1A + L2A;
|
||||
std::cout << STD_FMT::format("{:%.30Q %q}\n + {:%.30Q %q}\n = {:%.30Q %q}\n\n", L1A, L2A, LrA);
|
||||
std::cout << UNITS_STD_FMT::format("{:%.30Q %q}\n + {:%.30Q %q}\n = {:%.30Q %q}\n\n", L1A, L2A, LrA);
|
||||
|
||||
std::cout << "The single unit method must convert large\n"
|
||||
"or small values in other units to the base unit.\n"
|
||||
@ -122,17 +122,17 @@ void calcs_comparison()
|
||||
const auto L1B = L1A[m];
|
||||
const auto L2B = L2A[m];
|
||||
const auto LrB = L1B + L2B;
|
||||
std::cout << STD_FMT::format("{:%.30eQ %q}\n + {:%.30eQ %q}\n = {:%.30eQ %q}\n\n", L1B, L2B, LrB);
|
||||
std::cout << UNITS_STD_FMT::format("{:%.30eQ %q}\n + {:%.30eQ %q}\n = {:%.30eQ %q}\n\n", L1B, L2B, LrB);
|
||||
|
||||
std::cout << "In multiplication and division:\n\n";
|
||||
|
||||
const quantity<isq::area[square<fm>], float> ArA = L1A * L2A;
|
||||
std::cout << STD_FMT::format("{:%.30Q %q}\n * {:%.30Q %q}\n = {:%.30Q %q}\n\n", L1A, L2A, ArA);
|
||||
std::cout << UNITS_STD_FMT::format("{:%.30Q %q}\n * {:%.30Q %q}\n = {:%.30Q %q}\n\n", L1A, L2A, ArA);
|
||||
|
||||
std::cout << "similar problems arise\n\n";
|
||||
|
||||
const quantity<isq::area[m2], float> ArB = L1B * L2B;
|
||||
std::cout << STD_FMT::format("{:%.30eQ %q}\n * {:%.30eQ %q}\n = {:%.30eQ %q}\n\n", L1B, L2B, ArB);
|
||||
std::cout << UNITS_STD_FMT::format("{:%.30eQ %q}\n * {:%.30eQ %q}\n = {:%.30eQ %q}\n\n", L1B, L2B, ArB);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -48,13 +48,13 @@ int main()
|
||||
constexpr auto lengthA = 2.0 * m;
|
||||
constexpr auto lengthB = lengthA[mm];
|
||||
|
||||
std::cout << STD_FMT::format("lengthA( {} ) and lengthB( {} )\n", lengthA, lengthB)
|
||||
std::cout << UNITS_STD_FMT::format("lengthA( {} ) and lengthB( {} )\n", lengthA, lengthB)
|
||||
<< "represent the same length in different units.\n\n";
|
||||
|
||||
std::cout << STD_FMT::format("therefore ratio lengthA / lengthB == {}\n\n", lengthA / lengthB);
|
||||
std::cout << UNITS_STD_FMT::format("therefore ratio lengthA / lengthB == {}\n\n", lengthA / lengthB);
|
||||
|
||||
std::cout << STD_FMT::format("conversion factor from lengthA::unit of {:%q} to lengthB::unit of {:%q}:\n\n", lengthA,
|
||||
lengthB)
|
||||
<< STD_FMT::format("lengthB.number( {} ) == lengthA.number( {} ) * conversion_factor( {} )\n",
|
||||
lengthB.number(), lengthA.number(), conversion_factor(lengthB, lengthA));
|
||||
std::cout << UNITS_STD_FMT::format("conversion factor from lengthA::unit of {:%q} to lengthB::unit of {:%q}:\n\n",
|
||||
lengthA, lengthB)
|
||||
<< UNITS_STD_FMT::format("lengthB.number( {} ) == lengthA.number( {} ) * conversion_factor( {} )\n",
|
||||
lengthB.number(), lengthA.number(), conversion_factor(lengthB, lengthA));
|
||||
}
|
||||
|
@ -52,24 +52,25 @@ struct Ship {
|
||||
template<Unit auto... Us, Quantity Q>
|
||||
auto fmt_line(const Q& q)
|
||||
{
|
||||
return STD_FMT::format("{:22}", q) + (STD_FMT::format(",{:20}", value_cast<Us>(q)) + ...);
|
||||
return UNITS_STD_FMT::format("{:22}", q) + (UNITS_STD_FMT::format(",{:20}", value_cast<Us>(q)) + ...);
|
||||
}
|
||||
|
||||
// Print the ship details in the units as defined in the Ship struct, in other si::imperial units, and in SI
|
||||
void print_details(std::string_view description, const Ship& ship)
|
||||
{
|
||||
const auto waterDensity = 62.4 * isq::density[lb / cubic<ft>];
|
||||
std::cout << STD_FMT::format("{}\n", description);
|
||||
std::cout << STD_FMT::format("{:20} : {}\n", "length", fmt_line<yd, m>(ship.length))
|
||||
<< STD_FMT::format("{:20} : {}\n", "draft", fmt_line<yd, m>(ship.draft))
|
||||
<< STD_FMT::format("{:20} : {}\n", "beam", fmt_line<yd, m>(ship.beam))
|
||||
<< STD_FMT::format("{:20} : {}\n", "mass", fmt_line<imperial::long_ton, t>(ship.mass))
|
||||
<< STD_FMT::format("{:20} : {}\n", "speed", fmt_line<kt, km / h>(ship.speed))
|
||||
<< STD_FMT::format("{:20} : {}\n", "power", fmt_line<hp, kW>(ship.power))
|
||||
<< STD_FMT::format("{:20} : {}\n", "main guns", fmt_line<in, mm>(ship.mainGuns))
|
||||
<< STD_FMT::format("{:20} : {}\n", "fire shells weighing", fmt_line<imperial::long_ton, kg>(ship.shellMass))
|
||||
<< STD_FMT::format("{:20} : {}\n", "fire shells at", fmt_line<mph, km / h>(ship.shellSpeed))
|
||||
<< STD_FMT::format("{:20} : {}\n", "volume underwater", fmt_line<m3, l>(ship.mass / waterDensity));
|
||||
std::cout << UNITS_STD_FMT::format("{}\n", description);
|
||||
std::cout << UNITS_STD_FMT::format("{:20} : {}\n", "length", fmt_line<yd, m>(ship.length))
|
||||
<< UNITS_STD_FMT::format("{:20} : {}\n", "draft", fmt_line<yd, m>(ship.draft))
|
||||
<< UNITS_STD_FMT::format("{:20} : {}\n", "beam", fmt_line<yd, m>(ship.beam))
|
||||
<< UNITS_STD_FMT::format("{:20} : {}\n", "mass", fmt_line<imperial::long_ton, t>(ship.mass))
|
||||
<< UNITS_STD_FMT::format("{:20} : {}\n", "speed", fmt_line<kt, km / h>(ship.speed))
|
||||
<< UNITS_STD_FMT::format("{:20} : {}\n", "power", fmt_line<hp, kW>(ship.power))
|
||||
<< UNITS_STD_FMT::format("{:20} : {}\n", "main guns", fmt_line<in, mm>(ship.mainGuns))
|
||||
<< UNITS_STD_FMT::format("{:20} : {}\n", "fire shells weighing",
|
||||
fmt_line<imperial::long_ton, kg>(ship.shellMass))
|
||||
<< UNITS_STD_FMT::format("{:20} : {}\n", "fire shells at", fmt_line<mph, km / h>(ship.shellSpeed))
|
||||
<< UNITS_STD_FMT::format("{:20} : {}\n", "volume underwater", fmt_line<m3, l>(ship.mass / waterDensity));
|
||||
}
|
||||
|
||||
int main()
|
||||
|
@ -76,7 +76,7 @@ using namespace glide_computer;
|
||||
void print(std::string_view phase_name, timestamp start_ts, const glide_computer::flight_point& point,
|
||||
const glide_computer::flight_point& new_point)
|
||||
{
|
||||
std::cout << STD_FMT::format(
|
||||
std::cout << UNITS_STD_FMT::format(
|
||||
"| {:<12} | {:>9%.1Q %q} (Total: {:>9%.1Q %q}) | {:>8%.1Q %q} (Total: {:>8%.1Q %q}) | {:>7%.0Q %q} ({:>6%.0Q %q}) "
|
||||
"|\n",
|
||||
phase_name, value_cast<si::minute>(new_point.ts - point.ts), value_cast<si::minute>(new_point.ts - start_ts),
|
||||
@ -142,9 +142,9 @@ namespace glide_computer {
|
||||
void estimate(timestamp start_ts, const glider& g, const weather& w, const task& t, const safety& s,
|
||||
const aircraft_tow& at)
|
||||
{
|
||||
std::cout << STD_FMT::format("| {:<12} | {:^28} | {:^26} | {:^21} |\n", "Flight phase", "Duration", "Distance",
|
||||
"Height");
|
||||
std::cout << STD_FMT::format("|{0:-^14}|{0:-^30}|{0:-^28}|{0:-^23}|\n", "");
|
||||
std::cout << UNITS_STD_FMT::format("| {:<12} | {:^28} | {:^26} | {:^21} |\n", "Flight phase", "Duration", "Distance",
|
||||
"Height");
|
||||
std::cout << UNITS_STD_FMT::format("|{0:-^14}|{0:-^30}|{0:-^28}|{0:-^23}|\n", "");
|
||||
|
||||
// ready to takeoff
|
||||
flight_point pos = takeoff(start_ts, t);
|
||||
|
@ -84,7 +84,7 @@ void print(const R& gliders)
|
||||
std::cout << "- Polar:\n";
|
||||
for (const auto& p : g.polar) {
|
||||
const auto ratio = value_cast<one>(glide_ratio(g.polar[0]));
|
||||
std::cout << STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q} ({:%.1Q %q})\n", p.climb, p.v, ratio,
|
||||
std::cout << UNITS_STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q} ({:%.1Q %q})\n", p.climb, p.v, ratio,
|
||||
// TODO is it possible to make ADL work below (we need another set of trig functions
|
||||
// for strong angle in a different namespace)
|
||||
value_cast<si::degree>(isq::asin(1 / ratio)));
|
||||
@ -102,8 +102,8 @@ void print(const R& conditions)
|
||||
for (const auto& c : conditions) {
|
||||
std::cout << "- " << c.first << "\n";
|
||||
const auto& w = c.second;
|
||||
std::cout << " * Cloud base: " << STD_FMT::format("{:%.0Q %q}", w.cloud_base) << " AGL\n";
|
||||
std::cout << " * Thermals strength: " << STD_FMT::format("{:%.1Q %q}", w.thermal_strength) << "\n";
|
||||
std::cout << " * Cloud base: " << UNITS_STD_FMT::format("{:%.0Q %q}", w.cloud_base) << " AGL\n";
|
||||
std::cout << " * Thermals strength: " << UNITS_STD_FMT::format("{:%.1Q %q}", w.thermal_strength) << "\n";
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
@ -115,7 +115,7 @@ void print(const R& waypoints)
|
||||
std::cout << "Waypoints:\n";
|
||||
std::cout << "==========\n";
|
||||
for (const auto& w : waypoints)
|
||||
std::cout << STD_FMT::format("- {}: {} {}, {:%.1Q %q}\n", w.name, w.pos.lat, w.pos.lon, w.alt);
|
||||
std::cout << UNITS_STD_FMT::format("- {}: {} {}, {:%.1Q %q}\n", w.name, w.pos.lat, w.pos.lon, w.alt);
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
@ -126,12 +126,12 @@ void print(const task& t)
|
||||
|
||||
std::cout << "- Start: " << t.get_start().name << "\n";
|
||||
std::cout << "- Finish: " << t.get_finish().name << "\n";
|
||||
std::cout << "- Length: " << STD_FMT::format("{:%.1Q %q}", t.get_distance()) << "\n";
|
||||
std::cout << "- Length: " << UNITS_STD_FMT::format("{:%.1Q %q}", t.get_distance()) << "\n";
|
||||
|
||||
std::cout << "- Legs: "
|
||||
<< "\n";
|
||||
for (const auto& l : t.get_legs())
|
||||
std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_distance());
|
||||
std::cout << UNITS_STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_distance());
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
@ -139,7 +139,7 @@ void print(const safety& s)
|
||||
{
|
||||
std::cout << "Safety:\n";
|
||||
std::cout << "=======\n";
|
||||
std::cout << "- Min AGL separation: " << STD_FMT::format("{:%.0Q %q}", s.min_agl_height) << "\n";
|
||||
std::cout << "- Min AGL separation: " << UNITS_STD_FMT::format("{:%.0Q %q}", s.min_agl_height) << "\n";
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
@ -148,8 +148,8 @@ void print(const aircraft_tow& tow)
|
||||
std::cout << "Tow:\n";
|
||||
std::cout << "====\n";
|
||||
std::cout << "- Type: aircraft\n";
|
||||
std::cout << "- Height: " << STD_FMT::format("{:%.0Q %q}", tow.height_agl) << "\n";
|
||||
std::cout << "- Performance: " << STD_FMT::format("{:%.1Q %q}", tow.performance) << "\n";
|
||||
std::cout << "- Height: " << UNITS_STD_FMT::format("{:%.0Q %q}", tow.height_agl) << "\n";
|
||||
std::cout << "- Performance: " << UNITS_STD_FMT::format("{:%.1Q %q}", tow.performance) << "\n";
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
@ -178,7 +178,7 @@ void example()
|
||||
for (const auto& c : weather_conditions) {
|
||||
std::string txt = "Scenario: Glider = " + g.name + ", Weather = " + c.first;
|
||||
std::cout << txt << "\n";
|
||||
std::cout << STD_FMT::format("{0:=^{1}}\n\n", "", txt.size());
|
||||
std::cout << UNITS_STD_FMT::format("{0:=^{1}}\n\n", "", txt.size());
|
||||
|
||||
estimate(start_time, g, c.second, t, sfty, tow);
|
||||
|
||||
|
@ -47,11 +47,11 @@ int main()
|
||||
constexpr auto v6 = value_cast<m / s>(v4);
|
||||
constexpr auto v7 = value_cast<int>(v6);
|
||||
|
||||
std::cout << v1 << '\n'; // 110 km/h
|
||||
std::cout << v2 << '\n'; // 70 mi/h
|
||||
std::cout << STD_FMT::format("{}", v3) << '\n'; // 110 km/h
|
||||
std::cout << STD_FMT::format("{:*^14}", v4) << '\n'; // ***70 mi/h****
|
||||
std::cout << STD_FMT::format("{:%Q in %q}", v5) << '\n'; // 30.5556 in m/s
|
||||
std::cout << STD_FMT::format("{0:%Q} in {0:%q}", v6) << '\n'; // 31.2928 in m/s
|
||||
std::cout << STD_FMT::format("{:%Q}", v7) << '\n'; // 31
|
||||
std::cout << v1 << '\n'; // 110 km/h
|
||||
std::cout << v2 << '\n'; // 70 mi/h
|
||||
std::cout << UNITS_STD_FMT::format("{}", v3) << '\n'; // 110 km/h
|
||||
std::cout << UNITS_STD_FMT::format("{:*^14}", v4) << '\n'; // ***70 mi/h****
|
||||
std::cout << UNITS_STD_FMT::format("{:%Q in %q}", v5) << '\n'; // 30.5556 in m/s
|
||||
std::cout << UNITS_STD_FMT::format("{0:%Q} in {0:%q}", v6) << '\n'; // 31.2928 in m/s
|
||||
std::cout << UNITS_STD_FMT::format("{:%Q}", v7) << '\n'; // 31
|
||||
}
|
||||
|
@ -53,12 +53,12 @@ std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>&
|
||||
} // namespace geographic
|
||||
|
||||
template<>
|
||||
struct STD_FMT::formatter<geographic::msl_altitude> : formatter<geographic::msl_altitude::quantity_type> {
|
||||
struct UNITS_STD_FMT::formatter<geographic::msl_altitude> : formatter<geographic::msl_altitude::quantity_type> {
|
||||
template<typename FormatContext>
|
||||
auto format(const geographic::msl_altitude& a, FormatContext& ctx)
|
||||
{
|
||||
formatter<geographic::msl_altitude::quantity_type>::format(a.absolute(), ctx);
|
||||
return STD_FMT::format_to(ctx.out(), " AMSL");
|
||||
return UNITS_STD_FMT::format_to(ctx.out(), " AMSL");
|
||||
}
|
||||
};
|
||||
|
||||
@ -145,21 +145,21 @@ class std::numeric_limits<geographic::longitude<T>> : public numeric_limits<T> {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct STD_FMT::formatter<geographic::latitude<T>> : formatter<T> {
|
||||
struct UNITS_STD_FMT::formatter<geographic::latitude<T>> : formatter<T> {
|
||||
template<typename FormatContext>
|
||||
auto format(geographic::latitude<T> lat, FormatContext& ctx)
|
||||
{
|
||||
STD_FMT::format_to(ctx.out(), "{}", lat > geographic::latitude<T>::zero() ? 'N' : 'S');
|
||||
UNITS_STD_FMT::format_to(ctx.out(), "{}", lat > geographic::latitude<T>::zero() ? 'N' : 'S');
|
||||
return formatter<T>::format(lat > geographic::latitude<T>::zero() ? lat.number() : -lat.number(), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct STD_FMT::formatter<geographic::longitude<T>> : formatter<T> {
|
||||
struct UNITS_STD_FMT::formatter<geographic::longitude<T>> : formatter<T> {
|
||||
template<typename FormatContext>
|
||||
auto format(geographic::longitude<T> lon, FormatContext& ctx)
|
||||
{
|
||||
STD_FMT::format_to(ctx.out(), "{}", lon > geographic::longitude<T>::zero() ? 'E' : 'W');
|
||||
UNITS_STD_FMT::format_to(ctx.out(), "{}", lon > geographic::longitude<T>::zero() ? 'E' : 'W');
|
||||
return formatter<T>::format(lon > geographic::longitude<T>::zero() ? lon.number() : -lon.number(), ctx);
|
||||
}
|
||||
};
|
||||
|
@ -26,21 +26,29 @@
|
||||
#include <mp-units/bits/external/hacks.h>
|
||||
#include <mp-units/customization_points.h>
|
||||
#include <algorithm>
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
||||
template<typename T, auto Min, auto Max>
|
||||
template<std::movable T, UNITS_CONSTRAINED_NTTP_WORKAROUND(std::convertible_to<T>) auto Min,
|
||||
UNITS_CONSTRAINED_NTTP_WORKAROUND(std::convertible_to<T>) auto Max>
|
||||
inline constexpr auto is_in_range = [](const auto& v) { return std::clamp(v, T{Min}, T{Max}) == v; };
|
||||
|
||||
template<typename T, auto Min, auto Max>
|
||||
template<std::movable T, UNITS_CONSTRAINED_NTTP_WORKAROUND(std::convertible_to<T>) auto Min,
|
||||
UNITS_CONSTRAINED_NTTP_WORKAROUND(std::convertible_to<T>) auto Max>
|
||||
using is_in_range_t = decltype(is_in_range<T, Min, Max>);
|
||||
|
||||
template<typename T, auto Min, auto Max>
|
||||
template<std::movable T, UNITS_CONSTRAINED_NTTP_WORKAROUND(std::convertible_to<T>) auto Min,
|
||||
UNITS_CONSTRAINED_NTTP_WORKAROUND(std::convertible_to<T>) auto Max>
|
||||
class ranged_representation : public validated_type<T, is_in_range_t<T, Min, Max>> {
|
||||
public:
|
||||
using validated_type<T, is_in_range_t<T, Min, Max>>::validated_type;
|
||||
constexpr ranged_representation() : validated_type<T, is_in_range_t<T, Min, Max>>(T{}) {}
|
||||
|
||||
[[nodiscard]] constexpr ranged_representation operator-() const { return ranged_representation(-this->value()); }
|
||||
[[nodiscard]] constexpr ranged_representation operator-() const
|
||||
requires requires(T t) { -t; }
|
||||
{
|
||||
return ranged_representation(-this->value());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, auto Min, auto Max>
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
|
||||
constexpr explicit validated_type(const T& value) noexcept(std::is_nothrow_copy_constructible_v<T>)
|
||||
requires std::copyable<T>
|
||||
: value_(value)
|
||||
: value_(value)
|
||||
{
|
||||
gsl_Expects(validate(value_));
|
||||
}
|
||||
@ -52,7 +52,7 @@ public:
|
||||
|
||||
constexpr validated_type(const T& value, validated_tag) noexcept(std::is_nothrow_copy_constructible_v<T>)
|
||||
requires std::copyable<T>
|
||||
: value_(value)
|
||||
: value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
@ -61,12 +61,30 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#if UNITS_COMP_MSVC && UNITS_COMP_MSVC < 1930
|
||||
|
||||
constexpr explicit(false) operator T() const noexcept(std::is_nothrow_copy_constructible_v<T>)
|
||||
requires std::copyable<T>
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
constexpr explicit(false) operator T() const& noexcept(std::is_nothrow_copy_constructible_v<T>)
|
||||
requires std::copyable<T>
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
constexpr explicit(false) operator T() && noexcept(std::is_nothrow_move_constructible_v<T>)
|
||||
{
|
||||
return std::move(value_);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
constexpr T& value() & noexcept = delete;
|
||||
constexpr const T& value() const& noexcept { return value_; }
|
||||
constexpr T&& value() && noexcept { return std::move(value_); }
|
||||
|
@ -79,13 +79,9 @@ public:
|
||||
uncertainty_type uncertainty;
|
||||
};
|
||||
|
||||
#if UNITS_COMP_CLANG <= 14
|
||||
|
||||
template<QuantityOrQuantityPoint QQP, mp_units::Quantity U>
|
||||
estimation(state<QQP>, U) -> estimation<QQP>;
|
||||
|
||||
#endif
|
||||
|
||||
// kalman gain
|
||||
template<mp_units::Quantity Q>
|
||||
constexpr mp_units::quantity<mp_units::dimensionless[mp_units::one]> kalman_gain(Q estimate_uncertainty,
|
||||
@ -159,7 +155,7 @@ constexpr Q covariance_extrapolation(Q uncertainty, Q process_noise_variance)
|
||||
} // namespace kalman
|
||||
|
||||
template<typename... Qs>
|
||||
struct STD_FMT::formatter<kalman::state<Qs...>> {
|
||||
struct UNITS_STD_FMT::formatter<kalman::state<Qs...>> {
|
||||
constexpr auto parse(format_parse_context& ctx)
|
||||
{
|
||||
mp_units::detail::dynamic_specs_handler handler(specs, ctx);
|
||||
@ -173,35 +169,35 @@ struct STD_FMT::formatter<kalman::state<Qs...>> {
|
||||
auto to_value_buffer = std::back_inserter(value_buffer);
|
||||
if (specs.precision != -1) {
|
||||
if constexpr (sizeof...(Qs) == 1)
|
||||
STD_FMT::format_to(to_value_buffer, "{1:%.{0}Q %q}", specs.precision, kalman::get<0>(s));
|
||||
UNITS_STD_FMT::format_to(to_value_buffer, "{1:%.{0}Q %q}", specs.precision, kalman::get<0>(s));
|
||||
else if constexpr (sizeof...(Qs) == 2)
|
||||
STD_FMT::format_to(to_value_buffer, "{{ {1:%.{0}Q %q}, {2:%.{0}Q %q} }}", specs.precision, kalman::get<0>(s),
|
||||
kalman::get<1>(s));
|
||||
UNITS_STD_FMT::format_to(to_value_buffer, "{{ {1:%.{0}Q %q}, {2:%.{0}Q %q} }}", specs.precision,
|
||||
kalman::get<0>(s), kalman::get<1>(s));
|
||||
else
|
||||
STD_FMT::format_to(to_value_buffer, "{{ {1:%.{0}Q %q}, {2:%.{0}Q %q}, {3:%.{0}Q %q} }}", specs.precision,
|
||||
kalman::get<0>(s), kalman::get<1>(s), kalman::get<2>(s));
|
||||
UNITS_STD_FMT::format_to(to_value_buffer, "{{ {1:%.{0}Q %q}, {2:%.{0}Q %q}, {3:%.{0}Q %q} }}", specs.precision,
|
||||
kalman::get<0>(s), kalman::get<1>(s), kalman::get<2>(s));
|
||||
} else {
|
||||
if constexpr (sizeof...(Qs) == 1)
|
||||
STD_FMT::format_to(to_value_buffer, "{}", kalman::get<0>(s));
|
||||
UNITS_STD_FMT::format_to(to_value_buffer, "{}", kalman::get<0>(s));
|
||||
else if constexpr (sizeof...(Qs) == 2)
|
||||
STD_FMT::format_to(to_value_buffer, "{{ {}, {} }}", kalman::get<0>(s), kalman::get<1>(s));
|
||||
UNITS_STD_FMT::format_to(to_value_buffer, "{{ {}, {} }}", kalman::get<0>(s), kalman::get<1>(s));
|
||||
else
|
||||
STD_FMT::format_to(to_value_buffer, "{{ {}, {}, {} }}", kalman::get<0>(s), kalman::get<1>(s),
|
||||
kalman::get<2>(s));
|
||||
UNITS_STD_FMT::format_to(to_value_buffer, "{{ {}, {}, {} }}", kalman::get<0>(s), kalman::get<1>(s),
|
||||
kalman::get<2>(s));
|
||||
}
|
||||
|
||||
std::string global_format_buffer;
|
||||
mp_units::detail::quantity_global_format_specs<char> global_specs = {specs.fill, specs.align, specs.width};
|
||||
mp_units::detail::format_global_buffer(std::back_inserter(global_format_buffer), global_specs);
|
||||
|
||||
return STD_FMT::vformat_to(ctx.out(), global_format_buffer, STD_FMT::make_format_args(value_buffer));
|
||||
return UNITS_STD_FMT::vformat_to(ctx.out(), global_format_buffer, UNITS_STD_FMT::make_format_args(value_buffer));
|
||||
}
|
||||
private:
|
||||
mp_units::detail::dynamic_format_specs<char> specs;
|
||||
};
|
||||
|
||||
template<typename Q>
|
||||
struct STD_FMT::formatter<kalman::estimation<Q>> {
|
||||
struct UNITS_STD_FMT::formatter<kalman::estimation<Q>> {
|
||||
constexpr auto parse(format_parse_context& ctx)
|
||||
{
|
||||
mp_units::detail::dynamic_specs_handler handler(specs, ctx);
|
||||
@ -221,16 +217,17 @@ struct STD_FMT::formatter<kalman::estimation<Q>> {
|
||||
std::string value_buffer;
|
||||
auto to_value_buffer = std::back_inserter(value_buffer);
|
||||
if (specs.precision != -1) {
|
||||
STD_FMT::format_to(to_value_buffer, "{0:%.{2}Q} ± {1:%.{2}Q} {0:%q}", q, sqrt(e.uncertainty), specs.precision);
|
||||
UNITS_STD_FMT::format_to(to_value_buffer, "{0:%.{2}Q} ± {1:%.{2}Q} {0:%q}", q, sqrt(e.uncertainty),
|
||||
specs.precision);
|
||||
} else {
|
||||
STD_FMT::format_to(to_value_buffer, "{0:%Q} ± {1:%Q} {0:%q}", q, sqrt(e.uncertainty));
|
||||
UNITS_STD_FMT::format_to(to_value_buffer, "{0:%Q} ± {1:%Q} {0:%q}", q, sqrt(e.uncertainty));
|
||||
}
|
||||
|
||||
std::string global_format_buffer;
|
||||
mp_units::detail::quantity_global_format_specs<char> global_specs = {specs.fill, specs.align, specs.width};
|
||||
mp_units::detail::format_global_buffer(std::back_inserter(global_format_buffer), global_specs);
|
||||
|
||||
return STD_FMT::vformat_to(ctx.out(), global_format_buffer, STD_FMT::make_format_args(value_buffer));
|
||||
return UNITS_STD_FMT::vformat_to(ctx.out(), global_format_buffer, UNITS_STD_FMT::make_format_args(value_buffer));
|
||||
}
|
||||
private:
|
||||
mp_units::detail::dynamic_format_specs<char> specs;
|
||||
|
@ -33,15 +33,15 @@ using namespace mp_units;
|
||||
|
||||
void print_header(const kalman::State auto& initial)
|
||||
{
|
||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << STD_FMT::format("{:>2} | {:>9} | {:>8} | {:>14} | {:>14}\n", "N", "Gain", "Measured", "Curr. Estimate",
|
||||
"Next Estimate");
|
||||
std::cout << UNITS_STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << UNITS_STD_FMT::format("{:>2} | {:>9} | {:>8} | {:>14} | {:>14}\n", "N", "Gain", "Measured",
|
||||
"Curr. Estimate", "Next Estimate");
|
||||
}
|
||||
|
||||
void print(auto iteration, QuantityOf<dimensionless> auto gain, Quantity auto measured,
|
||||
const kalman::State auto& current, const kalman::State auto& next)
|
||||
{
|
||||
std::cout << STD_FMT::format("{:2} | {:9} | {:8} | {:14} | {:14}\n", iteration, gain, measured, current, next);
|
||||
std::cout << UNITS_STD_FMT::format("{:2} | {:9} | {:8} | {:14} | {:14}\n", iteration, gain, measured, current, next);
|
||||
}
|
||||
|
||||
int main()
|
||||
|
@ -37,13 +37,14 @@ using namespace mp_units;
|
||||
|
||||
void print_header(const kalman::State auto& initial)
|
||||
{
|
||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << STD_FMT::format("{:>2} | {:>8} | {:>23} | {:>23}\n", "N", "Measured", "Curr. Estimate", "Next Estimate");
|
||||
std::cout << UNITS_STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << UNITS_STD_FMT::format("{:>2} | {:>8} | {:>23} | {:>23}\n", "N", "Measured", "Curr. Estimate",
|
||||
"Next Estimate");
|
||||
}
|
||||
|
||||
void print(auto iteration, Quantity auto measured, const kalman::State auto& current, const kalman::State auto& next)
|
||||
{
|
||||
std::cout << STD_FMT::format("{:2} | {:8} | {:.1} | {:.1}\n", iteration, measured, current, next);
|
||||
std::cout << UNITS_STD_FMT::format("{:2} | {:8} | {:.1} | {:.1}\n", iteration, measured, current, next);
|
||||
}
|
||||
|
||||
int main()
|
||||
|
@ -37,13 +37,14 @@ using namespace mp_units;
|
||||
|
||||
void print_header(const kalman::State auto& initial)
|
||||
{
|
||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << STD_FMT::format("{:>2} | {:>8} | {:>24} | {:>24}\n", "N", "Measured", "Curr. Estimate", "Next Estimate");
|
||||
std::cout << UNITS_STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << UNITS_STD_FMT::format("{:>2} | {:>8} | {:>24} | {:>24}\n", "N", "Measured", "Curr. Estimate",
|
||||
"Next Estimate");
|
||||
}
|
||||
|
||||
void print(auto iteration, Quantity auto measured, const kalman::State auto& current, const kalman::State auto& next)
|
||||
{
|
||||
std::cout << STD_FMT::format("{:2} | {:8} | {:>24.1} | {:>24.1}\n", iteration, measured, current, next);
|
||||
std::cout << UNITS_STD_FMT::format("{:2} | {:8} | {:>24.1} | {:>24.1}\n", iteration, measured, current, next);
|
||||
}
|
||||
|
||||
int main()
|
||||
|
@ -37,13 +37,14 @@ using namespace mp_units;
|
||||
|
||||
void print_header(const kalman::State auto& initial)
|
||||
{
|
||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << STD_FMT::format("{:>2} | {:>8} | {:>35} | {:>35}\n", "N", "Measured", "Curr. Estimate", "Next Estimate");
|
||||
std::cout << UNITS_STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << UNITS_STD_FMT::format("{:>2} | {:>8} | {:>35} | {:>35}\n", "N", "Measured", "Curr. Estimate",
|
||||
"Next Estimate");
|
||||
}
|
||||
|
||||
void print(auto iteration, Quantity auto measured, const kalman::State auto& current, const kalman::State auto& next)
|
||||
{
|
||||
std::cout << STD_FMT::format("{:2} | {:8} | {:>35.1} | {:>35.1}\n", iteration, measured, current, next);
|
||||
std::cout << UNITS_STD_FMT::format("{:2} | {:8} | {:>35.1} | {:>35.1}\n", iteration, measured, current, next);
|
||||
}
|
||||
|
||||
int main()
|
||||
|
@ -35,16 +35,16 @@ using namespace mp_units;
|
||||
template<Quantity Q>
|
||||
void print_header(kalman::estimation<Q> initial)
|
||||
{
|
||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << STD_FMT::format("{:>2} | {:>5} | {:>8} | {:>16} | {:>16}\n", "N", "Gain", "Measured", "Curr. Estimate",
|
||||
"Next Estimate");
|
||||
std::cout << UNITS_STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << UNITS_STD_FMT::format("{:>2} | {:>5} | {:>8} | {:>16} | {:>16}\n", "N", "Gain", "Measured",
|
||||
"Curr. Estimate", "Next Estimate");
|
||||
}
|
||||
|
||||
template<Quantity Q, QuantityOf<dimensionless> K>
|
||||
void print(auto iteration, K gain, Q measured, kalman::estimation<Q> current, kalman::estimation<Q> next)
|
||||
{
|
||||
std::cout << STD_FMT::format("{:2} | {:5%.2Q} | {:8} | {:>16.2} | {:>16.2}\n", iteration, gain, measured, current,
|
||||
next);
|
||||
std::cout << UNITS_STD_FMT::format("{:2} | {:5%.2Q} | {:8} | {:>16.2} | {:>16.2}\n", iteration, gain, measured,
|
||||
current, next);
|
||||
}
|
||||
|
||||
int main()
|
||||
|
@ -36,16 +36,16 @@ using namespace mp_units;
|
||||
template<QuantityPoint QP>
|
||||
void print_header(kalman::estimation<QP> initial)
|
||||
{
|
||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>18} | {:>18}\n", "N", "Gain", "Measured", "Curr. Estimate",
|
||||
"Next Estimate");
|
||||
std::cout << UNITS_STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << UNITS_STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>18} | {:>18}\n", "N", "Gain", "Measured",
|
||||
"Curr. Estimate", "Next Estimate");
|
||||
}
|
||||
|
||||
template<QuantityPoint QP, QuantityOf<dimensionless> K>
|
||||
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
|
||||
{
|
||||
std::cout << STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain,
|
||||
measured.relative(), current, next);
|
||||
std::cout << UNITS_STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain,
|
||||
measured.relative(), current, next);
|
||||
}
|
||||
|
||||
int main()
|
||||
|
@ -36,16 +36,16 @@ using namespace mp_units;
|
||||
template<QuantityPoint QP>
|
||||
void print_header(kalman::estimation<QP> initial)
|
||||
{
|
||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>18} | {:>18}\n", "N", "Gain", "Measured", "Curr. Estimate",
|
||||
"Next Estimate");
|
||||
std::cout << UNITS_STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << UNITS_STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>18} | {:>18}\n", "N", "Gain", "Measured",
|
||||
"Curr. Estimate", "Next Estimate");
|
||||
}
|
||||
|
||||
template<QuantityPoint QP, QuantityOf<dimensionless> K>
|
||||
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
|
||||
{
|
||||
std::cout << STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain,
|
||||
measured.relative(), current, next);
|
||||
std::cout << UNITS_STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain,
|
||||
measured.relative(), current, next);
|
||||
}
|
||||
|
||||
int main()
|
||||
|
@ -36,16 +36,16 @@ using namespace mp_units;
|
||||
template<QuantityPoint QP>
|
||||
void print_header(kalman::estimation<QP> initial)
|
||||
{
|
||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>16} | {:>16}\n", "N", "Gain", "Measured", "Curr. Estimate",
|
||||
"Next Estimate");
|
||||
std::cout << UNITS_STD_FMT::format("Initial: {}\n", initial);
|
||||
std::cout << UNITS_STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>16} | {:>16}\n", "N", "Gain", "Measured",
|
||||
"Curr. Estimate", "Next Estimate");
|
||||
}
|
||||
|
||||
template<QuantityPoint QP, QuantityOf<dimensionless> K>
|
||||
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
|
||||
{
|
||||
std::cout << STD_FMT::format("{:2} | {:7%.3Q} | {:10%.3Q %q} | {:>16.2} | {:>16.2}\n", iteration, gain,
|
||||
measured.relative(), current, next);
|
||||
std::cout << UNITS_STD_FMT::format("{:2} | {:7%.3Q} | {:10%.3Q %q} | {:>16.2} | {:>16.2}\n", iteration, gain,
|
||||
measured.relative(), current, next);
|
||||
}
|
||||
|
||||
int main()
|
||||
|
@ -35,20 +35,20 @@ int main()
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
std::cout << "The seven defining constants of the SI and the seven corresponding units they define:\n";
|
||||
std::cout << STD_FMT::format("- hyperfine transition frequency of Cs: {} = {:%.0Q %q}\n",
|
||||
std::cout << UNITS_STD_FMT::format("- hyperfine transition frequency of Cs: {} = {:%.0Q %q}\n",
|
||||
1. * si2019::hyperfine_structure_transition_frequency_of_cs,
|
||||
(1. * si2019::hyperfine_structure_transition_frequency_of_cs)[Hz]);
|
||||
std::cout << STD_FMT::format("- speed of light in vacuum: {} = {:%.0Q %q}\n",
|
||||
std::cout << UNITS_STD_FMT::format("- speed of light in vacuum: {} = {:%.0Q %q}\n",
|
||||
1. * si2019::speed_of_light_in_vacuum, (1. * si2019::speed_of_light_in_vacuum)[m / s]);
|
||||
std::cout << STD_FMT::format("- Planck constant: {} = {:%.8eQ %q}\n",
|
||||
std::cout << UNITS_STD_FMT::format("- Planck constant: {} = {:%.8eQ %q}\n",
|
||||
1. * si2019::planck_constant, (1. * si2019::planck_constant)[J * s]);
|
||||
std::cout << STD_FMT::format("- elementary charge: {} = {:%.9eQ %q}\n",
|
||||
std::cout << UNITS_STD_FMT::format("- elementary charge: {} = {:%.9eQ %q}\n",
|
||||
1. * si2019::elementary_charge, (1. * si2019::elementary_charge)[C]);
|
||||
std::cout << STD_FMT::format("- Boltzmann constant: {} = {:%.6eQ %q}\n",
|
||||
std::cout << UNITS_STD_FMT::format("- Boltzmann constant: {} = {:%.6eQ %q}\n",
|
||||
1. * si2019::boltzmann_constant, (1. * si2019::boltzmann_constant)[J / K]);
|
||||
std::cout << STD_FMT::format("- Avogadro constant: {} = {:%.8eQ %q}\n",
|
||||
std::cout << UNITS_STD_FMT::format("- Avogadro constant: {} = {:%.8eQ %q}\n",
|
||||
1. * si2019::avogadro_constant, (1. * si2019::avogadro_constant)[1 / mol]);
|
||||
// TODO uncomment the below when ISQ is done
|
||||
// std::cout << STD_FMT::format("- luminous efficacy: {} = {}\n", si2019::luminous_efficacy(1.),
|
||||
// std::cout << UNITS_STD_FMT::format("- luminous efficacy: {} = {}\n", si2019::luminous_efficacy(1.),
|
||||
// si2019::luminous_efficacy(1.)[lm / W]);
|
||||
}
|
||||
|
@ -119,10 +119,10 @@ int main()
|
||||
|
||||
const auto fill_ratio = fill_level / height;
|
||||
|
||||
std::cout << STD_FMT::format("fill height at {} = {} ({} full)\n", fill_time, fill_level, fill_ratio[percent]);
|
||||
std::cout << STD_FMT::format("fill weight at {} = {} ({})\n", fill_time, filled_weight, filled_weight[N]);
|
||||
std::cout << STD_FMT::format("spare capacity at {} = {}\n", fill_time, spare_capacity);
|
||||
std::cout << STD_FMT::format("input flow rate = {}\n", input_flow_rate);
|
||||
std::cout << STD_FMT::format("float rise rate = {}\n", float_rise_rate);
|
||||
std::cout << STD_FMT::format("tank full E.T.A. at current flow rate = {}\n", fill_time_left[s]);
|
||||
std::cout << UNITS_STD_FMT::format("fill height at {} = {} ({} full)\n", fill_time, fill_level, fill_ratio[percent]);
|
||||
std::cout << UNITS_STD_FMT::format("fill weight at {} = {} ({})\n", fill_time, filled_weight, filled_weight[N]);
|
||||
std::cout << UNITS_STD_FMT::format("spare capacity at {} = {}\n", fill_time, spare_capacity);
|
||||
std::cout << UNITS_STD_FMT::format("input flow rate = {}\n", input_flow_rate);
|
||||
std::cout << UNITS_STD_FMT::format("float rise rate = {}\n", float_rise_rate);
|
||||
std::cout << UNITS_STD_FMT::format("tank full E.T.A. at current flow rate = {}\n", fill_time_left[s]);
|
||||
}
|
||||
|
@ -75,12 +75,12 @@ std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>&
|
||||
|
||||
template<QuantityPoint QP>
|
||||
requires(is_hae(QP::absolute_point_origin))
|
||||
struct STD_FMT::formatter<QP> : formatter<typename QP::quantity_type> {
|
||||
struct UNITS_STD_FMT::formatter<QP> : formatter<typename QP::quantity_type> {
|
||||
template<typename FormatContext>
|
||||
auto format(const QP& a, FormatContext& ctx)
|
||||
{
|
||||
formatter<typename QP::quantity_type>::format(a.absolute(), ctx);
|
||||
return STD_FMT::format_to(ctx.out(), " HAE({})", to_text(QP::absolute_point_origin.egm));
|
||||
return UNITS_STD_FMT::format_to(ctx.out(), " HAE({})", to_text(QP::absolute_point_origin.egm));
|
||||
}
|
||||
};
|
||||
|
||||
@ -116,12 +116,12 @@ std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>&
|
||||
}
|
||||
|
||||
template<>
|
||||
struct STD_FMT::formatter<hal_altitude> : formatter<hal_altitude::quantity_type> {
|
||||
struct UNITS_STD_FMT::formatter<hal_altitude> : formatter<hal_altitude::quantity_type> {
|
||||
template<typename FormatContext>
|
||||
auto format(const hal_altitude& a, FormatContext& ctx)
|
||||
{
|
||||
formatter<hal_altitude::quantity_type>::format(a.absolute(), ctx);
|
||||
return STD_FMT::format_to(ctx.out(), " HAL");
|
||||
return UNITS_STD_FMT::format_to(ctx.out(), " HAL");
|
||||
}
|
||||
};
|
||||
|
||||
@ -150,10 +150,10 @@ int main()
|
||||
unmanned_aerial_vehicle uav;
|
||||
uav.take_off(msl_altitude{6'000 * ft});
|
||||
uav.current(msl_altitude{10'000 * ft});
|
||||
std::cout << STD_FMT::format("hal = {}\n", uav.hal());
|
||||
std::cout << UNITS_STD_FMT::format("hal = {}\n", uav.hal());
|
||||
|
||||
msl_altitude ground_level{123 * m};
|
||||
std::cout << STD_FMT::format("agl = {}\n", uav.current() - ground_level);
|
||||
std::cout << UNITS_STD_FMT::format("agl = {}\n", uav.current() - ground_level);
|
||||
|
||||
struct waypoint {
|
||||
std::string name;
|
||||
@ -162,6 +162,6 @@ int main()
|
||||
};
|
||||
|
||||
waypoint wpt = {"EPPR", {54.24772_N, 18.6745_E}, msl_altitude{16. * ft}};
|
||||
std::cout << STD_FMT::format("{}: {} {}, {:%.2Q %q}, {:%.2Q %q}\n", wpt.name, wpt.pos.lat, wpt.pos.lon, wpt.msl_alt,
|
||||
std::cout << UNITS_STD_FMT::format("{}: {} {}, {:%.2Q %q}, {:%.2Q %q}\n", wpt.name, wpt.pos.lat, wpt.pos.lon, wpt.msl_alt,
|
||||
to_hae<earth_gravity_model::egm2008_1>(wpt.msl_alt, wpt.pos));
|
||||
}
|
||||
|
@ -1,2 +1,3 @@
|
||||
conan
|
||||
pre-commit
|
||||
identify
|
||||
|
@ -29,6 +29,8 @@ add_units_module(core-fmt DEPENDENCIES mp-units::core HEADERS include/mp-units/f
|
||||
target_compile_definitions(mp-units-core-fmt INTERFACE ${projectPrefix}USE_LIBFMT=$<BOOL:${${projectPrefix}USE_LIBFMT}>)
|
||||
|
||||
if(${projectPrefix}USE_LIBFMT)
|
||||
find_package(fmt CONFIG REQUIRED)
|
||||
if(NOT TARGET fmt::fmt)
|
||||
find_package(fmt CONFIG REQUIRED)
|
||||
endif()
|
||||
target_link_libraries(mp-units-core-fmt INTERFACE fmt::fmt)
|
||||
endif()
|
||||
|
@ -55,7 +55,7 @@ public:
|
||||
constexpr fill_t& operator=(std::basic_string_view<Char> str)
|
||||
{
|
||||
auto size = str.size();
|
||||
if (size > max_size) throw STD_FMT::format_error("invalid fill");
|
||||
if (size > max_size) UNITS_THROW(UNITS_STD_FMT::format_error("invalid fill"));
|
||||
for (size_t i = 0; i < size; ++i) data_[i] = str[i];
|
||||
size_ = static_cast<unsigned char>(size);
|
||||
return *this;
|
||||
@ -98,11 +98,11 @@ struct width_checker {
|
||||
{
|
||||
if constexpr (is_integer<T>) {
|
||||
if constexpr (std::numeric_limits<T>::is_signed) {
|
||||
if (value < 0) throw STD_FMT::format_error("negative width");
|
||||
if (value < 0) UNITS_THROW(UNITS_STD_FMT::format_error("negative width"));
|
||||
}
|
||||
return static_cast<unsigned long long>(value);
|
||||
} else {
|
||||
throw STD_FMT::format_error("width is not integer");
|
||||
UNITS_THROW(UNITS_STD_FMT::format_error("width is not integer"));
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -113,11 +113,11 @@ struct precision_checker {
|
||||
{
|
||||
if constexpr (is_integer<T>) {
|
||||
if constexpr (std::numeric_limits<T>::is_signed) {
|
||||
if (value < 0) throw STD_FMT::format_error("negative precision");
|
||||
if (value < 0) UNITS_THROW(UNITS_STD_FMT::format_error("negative precision"));
|
||||
}
|
||||
return static_cast<unsigned long long>(value);
|
||||
} else {
|
||||
throw STD_FMT::format_error("precision is not integer");
|
||||
UNITS_THROW(UNITS_STD_FMT::format_error("precision is not integer"));
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -147,31 +147,31 @@ struct dynamic_format_specs : basic_format_specs<Char> {
|
||||
[[nodiscard]] constexpr int verify_dynamic_arg_index_in_range(size_t idx)
|
||||
{
|
||||
if (idx > static_cast<size_t>(std::numeric_limits<int>::max())) {
|
||||
throw STD_FMT::format_error("Dynamic width or precision index too large.");
|
||||
UNITS_THROW(UNITS_STD_FMT::format_error("Dynamic width or precision index too large."));
|
||||
}
|
||||
return static_cast<int>(idx);
|
||||
}
|
||||
|
||||
template<typename CharT>
|
||||
[[nodiscard]] constexpr int on_dynamic_arg(size_t arg_id, STD_FMT::basic_format_parse_context<CharT>& context)
|
||||
[[nodiscard]] constexpr int on_dynamic_arg(size_t arg_id, UNITS_STD_FMT::basic_format_parse_context<CharT>& context)
|
||||
{
|
||||
context.check_arg_id(FMT_TO_ARG_ID(arg_id));
|
||||
context.check_arg_id(UNITS_FMT_TO_ARG_ID(arg_id));
|
||||
return verify_dynamic_arg_index_in_range(arg_id);
|
||||
}
|
||||
|
||||
template<typename CharT>
|
||||
[[nodiscard]] constexpr int on_dynamic_arg(auto_id, STD_FMT::basic_format_parse_context<CharT>& context)
|
||||
[[nodiscard]] constexpr int on_dynamic_arg(auto_id, UNITS_STD_FMT::basic_format_parse_context<CharT>& context)
|
||||
{
|
||||
return verify_dynamic_arg_index_in_range(FMT_FROM_ARG_ID(context.next_arg_id()));
|
||||
return verify_dynamic_arg_index_in_range(UNITS_FMT_FROM_ARG_ID(context.next_arg_id()));
|
||||
}
|
||||
|
||||
template<class Handler, typename FormatContext>
|
||||
[[nodiscard]] constexpr int get_dynamic_spec(int index, FormatContext& ctx)
|
||||
{
|
||||
const unsigned long long value =
|
||||
STD_FMT::visit_format_arg(Handler{}, ctx.arg(FMT_TO_ARG_ID(static_cast<size_t>(index))));
|
||||
UNITS_STD_FMT::visit_format_arg(Handler{}, ctx.arg(UNITS_FMT_TO_ARG_ID(static_cast<size_t>(index))));
|
||||
if (value > static_cast<unsigned long long>(std::numeric_limits<int>::max())) {
|
||||
throw STD_FMT::format_error("number is too big");
|
||||
UNITS_THROW(UNITS_STD_FMT::format_error("number is too big"));
|
||||
}
|
||||
return static_cast<int>(value);
|
||||
}
|
||||
@ -195,7 +195,7 @@ template<std::input_iterator It, std::sentinel_for<It> S>
|
||||
++begin;
|
||||
} while (begin != end && '0' <= *begin && *begin <= '9');
|
||||
|
||||
if (value > max_int) throw STD_FMT::format_error("Number is too big");
|
||||
if (value > max_int) UNITS_THROW(UNITS_STD_FMT::format_error("Number is too big"));
|
||||
|
||||
return begin;
|
||||
}
|
||||
@ -222,12 +222,12 @@ template<std::input_iterator It, std::sentinel_for<It> S, typename IDHandler>
|
||||
else
|
||||
++begin;
|
||||
if (begin == end || (*begin != '}' && *begin != ':'))
|
||||
throw STD_FMT::format_error("invalid format string");
|
||||
UNITS_THROW(UNITS_STD_FMT::format_error("invalid format string"));
|
||||
else
|
||||
handler(index);
|
||||
return begin;
|
||||
}
|
||||
throw STD_FMT::format_error("invalid format string");
|
||||
UNITS_THROW(UNITS_STD_FMT::format_error("invalid format string"));
|
||||
}
|
||||
|
||||
template<std::input_iterator It, std::sentinel_for<It> S, typename IDHandler>
|
||||
@ -278,11 +278,11 @@ template<std::input_iterator It, std::sentinel_for<It> S, typename Handler>
|
||||
if (width != -1)
|
||||
handler.on_width(width);
|
||||
else
|
||||
throw STD_FMT::format_error("number is too big");
|
||||
UNITS_THROW(UNITS_STD_FMT::format_error("number is too big"));
|
||||
} else if (*begin == '{') {
|
||||
++begin;
|
||||
if (begin != end) begin = parse_arg_id(begin, end, width_adapter{handler});
|
||||
if (begin == end || *begin != '}') throw STD_FMT::format_error("invalid format string");
|
||||
if (begin == end || *begin != '}') UNITS_THROW(UNITS_STD_FMT::format_error("invalid format string"));
|
||||
++begin;
|
||||
}
|
||||
return begin;
|
||||
@ -305,13 +305,13 @@ template<std::input_iterator It, std::sentinel_for<It> S, typename Handler>
|
||||
if (precision != -1)
|
||||
handler.on_precision(precision);
|
||||
else
|
||||
throw STD_FMT::format_error("number is too big");
|
||||
UNITS_THROW(UNITS_STD_FMT::format_error("number is too big"));
|
||||
} else if (c == '{') {
|
||||
++begin;
|
||||
if (begin != end) begin = parse_arg_id(begin, end, precision_adapter{handler});
|
||||
if (begin == end || *begin++ != '}') throw STD_FMT::format_error("invalid format string");
|
||||
if (begin == end || *begin++ != '}') UNITS_THROW(UNITS_STD_FMT::format_error("invalid format string"));
|
||||
} else {
|
||||
throw STD_FMT::format_error("missing precision specifier");
|
||||
UNITS_THROW(UNITS_STD_FMT::format_error("missing precision specifier"));
|
||||
}
|
||||
return begin;
|
||||
}
|
||||
@ -355,7 +355,7 @@ template<std::input_iterator It, std::sentinel_for<It> S, typename Handler>
|
||||
if (align != fmt_align::none) {
|
||||
if (p != begin) {
|
||||
auto c = *begin;
|
||||
if (c == '{') throw STD_FMT::format_error("invalid fill character '{'");
|
||||
if (c == '{') UNITS_THROW(UNITS_STD_FMT::format_error("invalid fill character '{'"));
|
||||
handler.on_fill(std::basic_string_view<std::iter_value_t<It>>(&*begin, static_cast<size_t>(p - begin)));
|
||||
begin = p + 1;
|
||||
} else
|
||||
|
@ -41,10 +41,24 @@ UNITS_DIAGNOSTIC_IGNORE_SHADOW
|
||||
#include <fmt/format.h>
|
||||
UNITS_DIAGNOSTIC_POP
|
||||
|
||||
#define STD_FMT fmt
|
||||
#define FMT_LOCALE(loc) (loc).template get<std::locale>()
|
||||
#define FMT_TO_ARG_ID(arg) static_cast<int>(arg)
|
||||
#define FMT_FROM_ARG_ID(arg) static_cast<size_t>(arg)
|
||||
#define UNITS_STD_FMT fmt
|
||||
#define UNITS_FMT_LOCALE(loc) (loc).template get<std::locale>()
|
||||
#define UNITS_FMT_TO_ARG_ID(arg) static_cast<int>(arg)
|
||||
#define UNITS_FMT_FROM_ARG_ID(arg) static_cast<size_t>(arg)
|
||||
|
||||
// This re-uses code from fmt;
|
||||
#if FMT_EXCEPTIONS
|
||||
#if FMT_MSC_VERSION || defined(__NVCC__)
|
||||
#define UNITS_THROW(x) ::fmt::detail::do_throw(x)
|
||||
#else
|
||||
#define UNITS_THROW(x) throw x
|
||||
#endif
|
||||
#else
|
||||
#define UNITS_THROW(x) \
|
||||
do { \
|
||||
FMT_ASSERT(false, (x).what()); \
|
||||
} while (false)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
@ -54,9 +68,10 @@ UNITS_DIAGNOSTIC_POP
|
||||
|
||||
#include <format>
|
||||
|
||||
#define STD_FMT std
|
||||
#define FMT_LOCALE(loc) loc
|
||||
#define FMT_TO_ARG_ID(arg) arg
|
||||
#define FMT_FROM_ARG_ID(arg) arg
|
||||
#define UNITS_STD_FMT std
|
||||
#define UNITS_FMT_LOCALE(loc) loc
|
||||
#define UNITS_FMT_TO_ARG_ID(arg) arg
|
||||
#define UNITS_FMT_FROM_ARG_ID(arg) arg
|
||||
#define UNITS_THROW(arg) throw arg
|
||||
|
||||
#endif
|
||||
|
@ -96,7 +96,7 @@ constexpr It parse_units_rep(It begin, S end, Handler&& handler, bool treat_as_f
|
||||
if (treat_as_floating_point) {
|
||||
begin = parse_precision(begin, end, handler);
|
||||
} else
|
||||
throw STD_FMT::format_error("precision not allowed for integral quantity representation");
|
||||
throw UNITS_STD_FMT::format_error("precision not allowed for integral quantity representation");
|
||||
if (begin == end) return begin;
|
||||
}
|
||||
|
||||
@ -126,12 +126,12 @@ constexpr It parse_units_format(It begin, S end, Handler&& handler)
|
||||
}
|
||||
if (begin != ptr) handler.on_text(begin, ptr);
|
||||
begin = ++ptr; // consume '%'
|
||||
if (ptr == end) throw STD_FMT::format_error("invalid format");
|
||||
if (ptr == end) throw UNITS_STD_FMT::format_error("invalid format");
|
||||
c = *ptr++;
|
||||
|
||||
constexpr auto units_types = std::string_view{"Qq"};
|
||||
const auto new_end = find_first_of(begin, end, units_types.begin(), units_types.end());
|
||||
if (new_end == end) throw STD_FMT::format_error("invalid format");
|
||||
if (new_end == end) throw UNITS_STD_FMT::format_error("invalid format");
|
||||
if (*new_end == 'Q') {
|
||||
handler.on_quantity_value(begin, new_end); // Edit `on_quantity_value` to add rep modifiers
|
||||
} else {
|
||||
@ -152,43 +152,43 @@ template<typename CharT, typename Rep, typename OutputIt, typename Locale>
|
||||
std::basic_string<CharT> buffer;
|
||||
auto to_buffer = std::back_inserter(buffer);
|
||||
|
||||
STD_FMT::format_to(to_buffer, "{{:");
|
||||
UNITS_STD_FMT::format_to(to_buffer, "{{:");
|
||||
switch (rep_specs.sign) {
|
||||
case fmt_sign::none:
|
||||
break;
|
||||
case fmt_sign::plus:
|
||||
STD_FMT::format_to(to_buffer, "+");
|
||||
UNITS_STD_FMT::format_to(to_buffer, "+");
|
||||
break;
|
||||
case fmt_sign::minus:
|
||||
STD_FMT::format_to(to_buffer, "-");
|
||||
UNITS_STD_FMT::format_to(to_buffer, "-");
|
||||
break;
|
||||
case fmt_sign::space:
|
||||
STD_FMT::format_to(to_buffer, " ");
|
||||
UNITS_STD_FMT::format_to(to_buffer, " ");
|
||||
break;
|
||||
}
|
||||
|
||||
if (rep_specs.alt) {
|
||||
STD_FMT::format_to(to_buffer, "#");
|
||||
UNITS_STD_FMT::format_to(to_buffer, "#");
|
||||
}
|
||||
auto type = rep_specs.type;
|
||||
if (auto precision = rep_specs.precision; precision >= 0) {
|
||||
STD_FMT::format_to(to_buffer, ".{}{}", precision, type == '\0' ? 'f' : type);
|
||||
UNITS_STD_FMT::format_to(to_buffer, ".{}{}", precision, type == '\0' ? 'f' : type);
|
||||
} else if constexpr (treat_as_floating_point<Rep>) {
|
||||
STD_FMT::format_to(to_buffer, "{}", type == '\0' ? 'g' : type);
|
||||
UNITS_STD_FMT::format_to(to_buffer, "{}", type == '\0' ? 'g' : type);
|
||||
} else {
|
||||
if (type != '\0') {
|
||||
STD_FMT::format_to(to_buffer, "{}", type);
|
||||
UNITS_STD_FMT::format_to(to_buffer, "{}", type);
|
||||
}
|
||||
}
|
||||
if (rep_specs.localized) {
|
||||
STD_FMT::format_to(to_buffer, "L");
|
||||
UNITS_STD_FMT::format_to(to_buffer, "L");
|
||||
}
|
||||
|
||||
STD_FMT::format_to(to_buffer, "}}");
|
||||
UNITS_STD_FMT::format_to(to_buffer, "}}");
|
||||
if (rep_specs.localized) {
|
||||
return STD_FMT::vformat_to(out, FMT_LOCALE(loc), buffer, STD_FMT::make_format_args(val));
|
||||
return UNITS_STD_FMT::vformat_to(out, UNITS_FMT_LOCALE(loc), buffer, UNITS_STD_FMT::make_format_args(val));
|
||||
}
|
||||
return STD_FMT::vformat_to(out, buffer, STD_FMT::make_format_args(val));
|
||||
return UNITS_STD_FMT::vformat_to(out, buffer, UNITS_STD_FMT::make_format_args(val));
|
||||
}
|
||||
|
||||
// Creates a global format string
|
||||
@ -196,25 +196,25 @@ template<typename CharT, typename Rep, typename OutputIt, typename Locale>
|
||||
template<typename CharT, typename OutputIt>
|
||||
OutputIt format_global_buffer(OutputIt out, const quantity_global_format_specs<CharT>& specs)
|
||||
{
|
||||
STD_FMT::format_to(out, "{{:");
|
||||
UNITS_STD_FMT::format_to(out, "{{:");
|
||||
if (specs.fill.size() != 1 || specs.fill[0] != ' ') {
|
||||
STD_FMT::format_to(out, "{}", specs.fill.data());
|
||||
UNITS_STD_FMT::format_to(out, "{}", specs.fill.data());
|
||||
}
|
||||
switch (specs.align) {
|
||||
case fmt_align::left:
|
||||
STD_FMT::format_to(out, "<");
|
||||
UNITS_STD_FMT::format_to(out, "<");
|
||||
break;
|
||||
case fmt_align::right:
|
||||
STD_FMT::format_to(out, ">");
|
||||
UNITS_STD_FMT::format_to(out, ">");
|
||||
break;
|
||||
case fmt_align::center:
|
||||
STD_FMT::format_to(out, "^");
|
||||
UNITS_STD_FMT::format_to(out, "^");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (specs.width >= 1) STD_FMT::format_to(out, "{}", specs.width);
|
||||
return STD_FMT::format_to(out, "}}");
|
||||
if (specs.width >= 1) UNITS_STD_FMT::format_to(out, "{}", specs.width);
|
||||
return UNITS_STD_FMT::format_to(out, "}}");
|
||||
}
|
||||
|
||||
template<auto Reference, typename Rep, typename Locale, typename CharT, typename OutputIt>
|
||||
@ -254,18 +254,18 @@ template<std::input_iterator It, std::sentinel_for<It> S>
|
||||
{
|
||||
auto it = find_first_of(begin, end, modifiers.begin(), modifiers.end());
|
||||
if (it != end && find_first_of(it + 1, end, modifiers.begin(), modifiers.end()) != end)
|
||||
throw STD_FMT::format_error("only one of '" + std::string(modifiers) +
|
||||
"' unit modifiers may be used in the format spec");
|
||||
throw UNITS_STD_FMT::format_error("only one of '" + std::string(modifiers) +
|
||||
"' unit modifiers may be used in the format spec");
|
||||
return it;
|
||||
}
|
||||
|
||||
} // namespace mp_units::detail
|
||||
|
||||
template<auto Reference, typename Rep, typename CharT>
|
||||
struct STD_FMT::formatter<mp_units::quantity<Reference, Rep>, CharT> {
|
||||
struct UNITS_STD_FMT::formatter<mp_units::quantity<Reference, Rep>, CharT> {
|
||||
private:
|
||||
using quantity = mp_units::quantity<Reference, Rep>;
|
||||
using iterator = TYPENAME STD_FMT::basic_format_parse_context<CharT>::iterator;
|
||||
using iterator = TYPENAME UNITS_STD_FMT::basic_format_parse_context<CharT>::iterator;
|
||||
|
||||
bool quantity_value = false;
|
||||
bool quantity_unit = false;
|
||||
@ -274,7 +274,7 @@ private:
|
||||
|
||||
struct spec_handler {
|
||||
formatter& f;
|
||||
STD_FMT::basic_format_parse_context<CharT>& context;
|
||||
UNITS_STD_FMT::basic_format_parse_context<CharT>& context;
|
||||
|
||||
constexpr void on_fill(std::basic_string_view<CharT> fill) { f.specs.global.fill = fill; }
|
||||
constexpr void on_align(mp_units::detail::fmt_align align) { f.specs.global.align = align; }
|
||||
@ -290,7 +290,7 @@ private:
|
||||
if (valid_rep_types.find(type) != std::string_view::npos) {
|
||||
f.specs.rep.type = type;
|
||||
} else {
|
||||
throw STD_FMT::format_error("invalid quantity type specifier");
|
||||
throw UNITS_STD_FMT::format_error("invalid quantity type specifier");
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,7 +326,7 @@ private:
|
||||
constexpr auto valid_modifiers = std::string_view{"UAoansd"};
|
||||
for (auto it = begin; it != end; ++it) {
|
||||
if (valid_modifiers.find(*it) == std::string_view::npos)
|
||||
throw STD_FMT::format_error("invalid unit modifier specified");
|
||||
throw UNITS_STD_FMT::format_error("invalid unit modifier specified");
|
||||
}
|
||||
|
||||
if (auto it = mp_units::detail::at_most_one_of(begin, end, "UA"); it != end) {
|
||||
@ -350,7 +350,7 @@ private:
|
||||
f.specs.unit.separator = mp_units::unit_symbol_separator::space;
|
||||
else {
|
||||
if (f.specs.unit.encoding == mp_units::text_encoding::ascii)
|
||||
throw STD_FMT::format_error("dot unit separator allowed only for Unicode encoding");
|
||||
throw UNITS_STD_FMT::format_error("dot unit separator allowed only for Unicode encoding");
|
||||
f.specs.unit.separator = mp_units::unit_symbol_separator::dot;
|
||||
}
|
||||
}
|
||||
@ -359,7 +359,7 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
[[nodiscard]] constexpr std::pair<iterator, iterator> do_parse(STD_FMT::basic_format_parse_context<CharT>& ctx)
|
||||
[[nodiscard]] constexpr std::pair<iterator, iterator> do_parse(UNITS_STD_FMT::basic_format_parse_context<CharT>& ctx)
|
||||
{
|
||||
auto begin = ctx.begin();
|
||||
auto end = ctx.end();
|
||||
@ -409,7 +409,7 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
[[nodiscard]] constexpr auto parse(STD_FMT::basic_format_parse_context<CharT>& ctx)
|
||||
[[nodiscard]] constexpr auto parse(UNITS_STD_FMT::basic_format_parse_context<CharT>& ctx)
|
||||
{
|
||||
auto range = do_parse(ctx);
|
||||
if (range.first != range.second)
|
||||
@ -446,8 +446,9 @@ public:
|
||||
mp_units::detail::format_global_buffer<CharT>(std::back_inserter(global_format_buffer), specs.global);
|
||||
|
||||
// Format the `quantity buffer` using specs from `global_format_buffer`
|
||||
// In the example, equivalent to STD_FMT::format("{:*^10}", "1.2_m")
|
||||
return STD_FMT::vformat_to(ctx.out(), global_format_buffer, STD_FMT::make_format_args(quantity_buffer));
|
||||
// In the example, equivalent to UNITS_STD_FMT::format("{:*^10}", "1.2_m")
|
||||
return UNITS_STD_FMT::vformat_to(ctx.out(), global_format_buffer,
|
||||
UNITS_STD_FMT::make_format_args(quantity_buffer));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -49,12 +49,12 @@ std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>&
|
||||
{
|
||||
if (os.width()) {
|
||||
// std::setw() applies to the whole quantity output so it has to be first put into std::string
|
||||
std::basic_ostringstream<CharT, Traits> s;
|
||||
s.flags(os.flags());
|
||||
s.imbue(os.getloc());
|
||||
s.precision(os.precision());
|
||||
detail::to_stream(s, q);
|
||||
return os << s.str();
|
||||
std::basic_ostringstream<CharT, Traits> oss;
|
||||
oss.flags(os.flags());
|
||||
oss.imbue(os.getloc());
|
||||
oss.precision(os.precision());
|
||||
detail::to_stream(oss, q);
|
||||
return os << std::move(oss).str();
|
||||
}
|
||||
|
||||
detail::to_stream(os, q);
|
||||
|
@ -23,7 +23,9 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
|
||||
# find dependencies
|
||||
find_package(gsl-lite CONFIG REQUIRED)
|
||||
if(NOT TARGET gsl::gsl-lite)
|
||||
find_package(gsl-lite CONFIG REQUIRED)
|
||||
endif()
|
||||
|
||||
# check if libc++ is being used
|
||||
include(CheckLibcxxInUse)
|
||||
@ -81,7 +83,9 @@ target_include_directories(
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
if(${projectPrefix}LIBCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "14")
|
||||
find_package(range-v3 CONFIG REQUIRED)
|
||||
if(NOT TARGET range-v3::range-v3)
|
||||
find_package(range-v3 CONFIG REQUIRED)
|
||||
endif()
|
||||
target_link_libraries(mp-units-core INTERFACE range-v3::range-v3)
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
|
16
src/core/include/mp-units/bits/external/hacks.h
vendored
16
src/core/include/mp-units/bits/external/hacks.h
vendored
@ -96,7 +96,7 @@
|
||||
#include <compare>
|
||||
#include <concepts>
|
||||
|
||||
#if UNITS_COMP_MSVC || UNITS_COMP_CLANG
|
||||
#if UNITS_COMP_MSVC || (UNITS_COMP_CLANG && UNITS_COMP_CLANG < 16)
|
||||
|
||||
#define TYPENAME typename
|
||||
|
||||
@ -108,11 +108,21 @@
|
||||
|
||||
#if UNITS_COMP_MSVC
|
||||
|
||||
#define UNITS_MSVC_WORKAROUND(X)
|
||||
#define UNITS_CONSTRAINED_AUTO_WORKAROUND(X)
|
||||
|
||||
#else
|
||||
|
||||
#define UNITS_MSVC_WORKAROUND(X) X
|
||||
#define UNITS_CONSTRAINED_AUTO_WORKAROUND(X) X
|
||||
|
||||
#endif
|
||||
|
||||
#if UNITS_COMP_MSVC || (UNITS_COMP_GCC && UNITS_COMP_GCC < 11)
|
||||
|
||||
#define UNITS_CONSTRAINED_NTTP_WORKAROUND(X)
|
||||
|
||||
#else
|
||||
|
||||
#define UNITS_CONSTRAINED_NTTP_WORKAROUND(X) X
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include <cstdint>
|
||||
#include <numbers>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace mp_units {
|
||||
|
||||
@ -243,10 +242,10 @@ using widen_t = conditional<std::is_arithmetic_v<T>,
|
||||
template<typename T>
|
||||
[[nodiscard]] consteval T int_power(T base, std::integral auto exp)
|
||||
{
|
||||
// As this function should only be called at compile time, the exceptions herein function as
|
||||
// "parameter-compatible static_asserts", and should not result in exceptions at runtime.
|
||||
// As this function should only be called at compile time, the terminations herein function as
|
||||
// "parameter-compatible static_asserts", and should not result in terminations at runtime.
|
||||
if (exp < 0) {
|
||||
throw std::invalid_argument{"int_power only supports positive integer powers"};
|
||||
std::terminate(); // int_power only supports positive integer powers
|
||||
}
|
||||
|
||||
constexpr auto checked_multiply = [](auto a, auto b) {
|
||||
@ -254,7 +253,7 @@ template<typename T>
|
||||
UNITS_DIAGNOSTIC_PUSH
|
||||
UNITS_DIAGNOSTIC_IGNORE_FLOAT_EQUAL
|
||||
if (result / a != b) {
|
||||
throw std::overflow_error{"Wraparound detected"};
|
||||
std::terminate(); // Wraparound detected
|
||||
}
|
||||
UNITS_DIAGNOSTIC_POP
|
||||
return result;
|
||||
@ -284,15 +283,15 @@ template<typename T>
|
||||
// need to write a custom function.
|
||||
//
|
||||
// Note that since this function should only be called at compile time, the point of these
|
||||
// exceptions is to act as "static_assert substitutes", not to throw actual exceptions at runtime.
|
||||
// terminations is to act as "static_assert substitutes", not to actually terminate at runtime.
|
||||
const auto exp = get_exponent(el);
|
||||
if (exp.den != 1) {
|
||||
throw std::invalid_argument{"Rational powers not yet supported"};
|
||||
std::terminate(); // Rational powers not yet supported
|
||||
}
|
||||
|
||||
if (exp.num < 0) {
|
||||
if constexpr (std::is_integral_v<T>) {
|
||||
throw std::invalid_argument{"Cannot represent reciprocal as integer"};
|
||||
std::terminate(); // Cannot represent reciprocal as integer
|
||||
} else {
|
||||
return T{1} / compute_base_power<T>(inverse(el));
|
||||
}
|
||||
@ -311,11 +310,11 @@ template<typename To, typename From>
|
||||
requires(!std::is_integral_v<To> || std::is_integral_v<From>)
|
||||
[[nodiscard]] consteval To checked_static_cast(From x)
|
||||
{
|
||||
// This function should only ever be called at compile time. The purpose of these exceptions is
|
||||
// This function should only ever be called at compile time. The purpose of these terminations is
|
||||
// to produce compiler errors, because we cannot `static_assert` on function arguments.
|
||||
if constexpr (std::is_integral_v<To>) {
|
||||
if (!std::in_range<To>(x)) {
|
||||
throw std::invalid_argument{"Cannot represent magnitude in this type"};
|
||||
std::terminate(); // Cannot represent magnitude in this type
|
||||
}
|
||||
}
|
||||
|
||||
@ -473,7 +472,7 @@ void to_base_specialization_of_magnitude(const volatile magnitude<Ms...>*);
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_derived_from_specialization_of_magnitude =
|
||||
requires(T * t) { to_base_specialization_of_magnitude(t); };
|
||||
requires(T* t) { to_base_specialization_of_magnitude(t); };
|
||||
|
||||
template<typename T>
|
||||
requires is_derived_from_specialization_of_magnitude<T>
|
||||
|
@ -50,7 +50,7 @@ namespace mp_units {
|
||||
*/
|
||||
template<Magnitude auto M, Unit U>
|
||||
struct scaled_unit {
|
||||
static constexpr UNITS_MSVC_WORKAROUND(Magnitude) auto mag = M;
|
||||
static constexpr UNITS_CONSTRAINED_AUTO_WORKAROUND(Magnitude) auto mag = M;
|
||||
static constexpr U reference_unit{};
|
||||
};
|
||||
|
||||
|
@ -42,7 +42,7 @@ struct AlmostEqualsMatcher : Catch::Matchers::MatcherGenericBase {
|
||||
return abs(x - y) <= std::numeric_limits<typename T::rep>::epsilon() * maxXYOne;
|
||||
}
|
||||
|
||||
std::string describe() const override { return "almost equals: " + STD_FMT::format("{}", target_); }
|
||||
std::string describe() const override { return "almost equals: " + UNITS_STD_FMT::format("{}", target_); }
|
||||
|
||||
private:
|
||||
const T& target_;
|
||||
|
@ -53,9 +53,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "60 W"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(STD_FMT::format("{}", q) == os.str()); }
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(UNITS_STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
}
|
||||
|
||||
SECTION("floating-point representation")
|
||||
@ -65,9 +65,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "1023.5 Pa"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(STD_FMT::format("{}", q) == os.str()); }
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(UNITS_STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,9 +78,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "125 µs"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(STD_FMT::format("{}", q) == os.str()); }
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(UNITS_STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
}
|
||||
|
||||
SECTION("quantity with a derived unit")
|
||||
@ -94,9 +94,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "10 m/s²"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(STD_FMT::format("{}", q) == os.str()); }
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(UNITS_STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
}
|
||||
|
||||
SECTION("volume")
|
||||
@ -106,9 +106,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "2 m³"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(STD_FMT::format("{}", q) == os.str()); }
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(UNITS_STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
}
|
||||
|
||||
SECTION("surface tension")
|
||||
@ -118,9 +118,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "10 N/m"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(STD_FMT::format("{}", q) == os.str()); }
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(UNITS_STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,9 +133,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "10 km/h"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(STD_FMT::format("{}", q) == os.str()); }
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(UNITS_STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
}
|
||||
|
||||
SECTION("angular impulse")
|
||||
@ -145,9 +145,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "123 N m s"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(STD_FMT::format("{}", q) == os.str()); }
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(UNITS_STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
}
|
||||
|
||||
SECTION("compressibility")
|
||||
@ -157,9 +157,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "123 1/Pa"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(STD_FMT::format("{}", q) == os.str()); }
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(UNITS_STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
}
|
||||
|
||||
SECTION("angular acceleration")
|
||||
@ -169,9 +169,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "123 rad/s²"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(STD_FMT::format("{}", q) == os.str()); }
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(UNITS_STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -186,9 +186,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "2"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(STD_FMT::format("{}", q) == os.str()); }
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(STD_FMT::format("{:%Q %q}", q) == "2 "); }
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(UNITS_STD_FMT::format("{:%Q %q}", q) == "2 "); }
|
||||
}
|
||||
|
||||
SECTION("one with ratio.exp != 0")
|
||||
@ -198,9 +198,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "2 km/m"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(STD_FMT::format("{}", q) == os.str()); }
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(STD_FMT::format("{:%Q %q}", q) == "2 km/m"); }
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(UNITS_STD_FMT::format("{:%Q %q}", q) == "2 km/m"); }
|
||||
}
|
||||
|
||||
SECTION("percents")
|
||||
@ -210,9 +210,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "15 %"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(STD_FMT::format("{}", q) == os.str()); }
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(UNITS_STD_FMT::format("{:%Q %q}", q) == os.str()); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -221,36 +221,39 @@ TEST_CASE("format string with only %Q should print quantity value only", "[text]
|
||||
{
|
||||
SECTION("integral representation")
|
||||
{
|
||||
SECTION("positive value") { CHECK(STD_FMT::format("{:%Q}", 123 * isq::speed[km / h]) == "123"); }
|
||||
SECTION("positive value") { CHECK(UNITS_STD_FMT::format("{:%Q}", 123 * isq::speed[km / h]) == "123"); }
|
||||
|
||||
SECTION("negative value") { CHECK(STD_FMT::format("{:%Q}", 5 * isq::length[m] - 10 * isq::length[m]) == "-5"); }
|
||||
SECTION("negative value")
|
||||
{
|
||||
CHECK(UNITS_STD_FMT::format("{:%Q}", 5 * isq::length[m] - 10 * isq::length[m]) == "-5");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("floating-point representation")
|
||||
{
|
||||
SECTION("positive value")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%Q}", 221. * isq::length[km] / (2 * isq::time[h])) == "110.5");
|
||||
CHECK(UNITS_STD_FMT::format("{:%Q}", 221. * isq::length[km] / (2 * isq::time[h])) == "110.5");
|
||||
}
|
||||
|
||||
SECTION("negative value")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%Q}", 3.14 * isq::length[m] - 10 * isq::length[m]) == "-6.86");
|
||||
CHECK(UNITS_STD_FMT::format("{:%Q}", 3.14 * isq::length[m] - 10 * isq::length[m]) == "-6.86");
|
||||
}
|
||||
|
||||
SECTION("nan")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%Q}", std::numeric_limits<double>::quiet_NaN() * isq::length[m]) == "nan");
|
||||
CHECK(UNITS_STD_FMT::format("{:%Q}", std::numeric_limits<double>::quiet_NaN() * isq::length[m]) == "nan");
|
||||
}
|
||||
|
||||
SECTION("inf")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%Q}", std::numeric_limits<double>::infinity() * isq::length[m]) == "inf");
|
||||
CHECK(UNITS_STD_FMT::format("{:%Q}", std::numeric_limits<double>::infinity() * isq::length[m]) == "inf");
|
||||
}
|
||||
|
||||
SECTION("-inf")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%Q}", -std::numeric_limits<double>::infinity() * isq::length[m]) == "-inf");
|
||||
CHECK(UNITS_STD_FMT::format("{:%Q}", -std::numeric_limits<double>::infinity() * isq::length[m]) == "-inf");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -261,27 +264,27 @@ TEST_CASE("format string with only %q should print quantity unit symbol only", "
|
||||
{
|
||||
SECTION("Unicode text output")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%Uq}", 123 * isq::speed[km / h]) == "km/h");
|
||||
CHECK(UNITS_STD_FMT::format("{:%Uq}", 123 * isq::speed[km / h]) == "km/h");
|
||||
// TODO enable this when resistance is defined
|
||||
// CHECK(STD_FMT::format("{:%Uq}", 123 * isq::resistance[kilo<ohm>]) == "kΩ");
|
||||
CHECK(STD_FMT::format("{:%Uq}", 123 * isq::time[us]) == "µs");
|
||||
CHECK(STD_FMT::format("{:%Uq}", 123 * isq::acceleration[m / s2]) == "m/s²");
|
||||
// CHECK(UNITS_STD_FMT::format("{:%Uq}", 123 * isq::resistance[kilo<ohm>]) == "kΩ");
|
||||
CHECK(UNITS_STD_FMT::format("{:%Uq}", 123 * isq::time[us]) == "µs");
|
||||
CHECK(UNITS_STD_FMT::format("{:%Uq}", 123 * isq::acceleration[m / s2]) == "m/s²");
|
||||
}
|
||||
|
||||
SECTION("Unicode text output is used by default")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%q}", 123 * isq::speed[km / h]) == "km/h");
|
||||
// CHECK(STD_FMT::format("{:%q}", 123 * isq::resistance[kilo<ohm>]) == "kΩ");
|
||||
CHECK(STD_FMT::format("{:%q}", 123 * isq::time[us]) == "µs");
|
||||
CHECK(STD_FMT::format("{:%q}", 123 * isq::acceleration[m / s2]) == "m/s²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%q}", 123 * isq::speed[km / h]) == "km/h");
|
||||
// CHECK(UNITS_STD_FMT::format("{:%q}", 123 * isq::resistance[kilo<ohm>]) == "kΩ");
|
||||
CHECK(UNITS_STD_FMT::format("{:%q}", 123 * isq::time[us]) == "µs");
|
||||
CHECK(UNITS_STD_FMT::format("{:%q}", 123 * isq::acceleration[m / s2]) == "m/s²");
|
||||
}
|
||||
|
||||
SECTION("ASCII text output")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%Aq}", 123 * isq::speed[km / h]) == "km/h");
|
||||
// CHECK(STD_FMT::format("{:%Aq}", 123 * isq::resistance[kilo<ohm>]) == "kohm");
|
||||
CHECK(STD_FMT::format("{:%Aq}", 123 * isq::time[us]) == "us");
|
||||
CHECK(STD_FMT::format("{:%Aq}", 123 * isq::acceleration[m / s2]) == "m/s^2");
|
||||
CHECK(UNITS_STD_FMT::format("{:%Aq}", 123 * isq::speed[km / h]) == "km/h");
|
||||
// CHECK(UNITS_STD_FMT::format("{:%Aq}", 123 * isq::resistance[kilo<ohm>]) == "kohm");
|
||||
CHECK(UNITS_STD_FMT::format("{:%Aq}", 123 * isq::time[us]) == "us");
|
||||
CHECK(UNITS_STD_FMT::format("{:%Aq}", 123 * isq::acceleration[m / s2]) == "m/s^2");
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,30 +292,30 @@ TEST_CASE("format string with only %q should print quantity unit symbol only", "
|
||||
{
|
||||
SECTION("Solidus for only one element in denominator")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%oq}", 123 * isq::speed[km / h]) == "km/h");
|
||||
CHECK(STD_FMT::format("{:%oq}", 123 * isq::acceleration[m / s2]) == "m/s²");
|
||||
CHECK(STD_FMT::format("{:%oq}", 123 * isq::pressure[kg / m / s2]) == "kg m⁻¹ s⁻²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%oq}", 123 * isq::speed[km / h]) == "km/h");
|
||||
CHECK(UNITS_STD_FMT::format("{:%oq}", 123 * isq::acceleration[m / s2]) == "m/s²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%oq}", 123 * isq::pressure[kg / m / s2]) == "kg m⁻¹ s⁻²");
|
||||
}
|
||||
|
||||
SECTION("Solidus for only one element in denominator is used by default")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%q}", 123 * isq::speed[km / h]) == "km/h");
|
||||
CHECK(STD_FMT::format("{:%q}", 123 * isq::acceleration[m / s2]) == "m/s²");
|
||||
CHECK(STD_FMT::format("{:%q}", 123 * isq::pressure[kg / m / s2]) == "kg m⁻¹ s⁻²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%q}", 123 * isq::speed[km / h]) == "km/h");
|
||||
CHECK(UNITS_STD_FMT::format("{:%q}", 123 * isq::acceleration[m / s2]) == "m/s²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%q}", 123 * isq::pressure[kg / m / s2]) == "kg m⁻¹ s⁻²");
|
||||
}
|
||||
|
||||
SECTION("Always use solidus")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%aq}", 123 * isq::speed[km / h]) == "km/h");
|
||||
CHECK(STD_FMT::format("{:%aq}", 123 * isq::acceleration[m / s2]) == "m/s²");
|
||||
CHECK(STD_FMT::format("{:%aq}", 123 * isq::pressure[kg / m / s2]) == "kg/(m s²)");
|
||||
CHECK(UNITS_STD_FMT::format("{:%aq}", 123 * isq::speed[km / h]) == "km/h");
|
||||
CHECK(UNITS_STD_FMT::format("{:%aq}", 123 * isq::acceleration[m / s2]) == "m/s²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%aq}", 123 * isq::pressure[kg / m / s2]) == "kg/(m s²)");
|
||||
}
|
||||
|
||||
SECTION("Never use solidus")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%nq}", 123 * isq::speed[km / h]) == "km h⁻¹");
|
||||
CHECK(STD_FMT::format("{:%nq}", 123 * isq::acceleration[m / s2]) == "m s⁻²");
|
||||
CHECK(STD_FMT::format("{:%nq}", 123 * isq::pressure[kg / m / s2]) == "kg m⁻¹ s⁻²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%nq}", 123 * isq::speed[km / h]) == "km h⁻¹");
|
||||
CHECK(UNITS_STD_FMT::format("{:%nq}", 123 * isq::acceleration[m / s2]) == "m s⁻²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%nq}", 123 * isq::pressure[kg / m / s2]) == "kg m⁻¹ s⁻²");
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,23 +323,23 @@ TEST_CASE("format string with only %q should print quantity unit symbol only", "
|
||||
{
|
||||
SECTION("Space")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%sq}", 123 * isq::force[kg * m / s2]) == "kg m/s²");
|
||||
CHECK(STD_FMT::format("{:%sq}", 123 * isq::pressure[kg / m / s2]) == "kg m⁻¹ s⁻²");
|
||||
CHECK(STD_FMT::format("{:%asq}", 123 * isq::pressure[kg / m / s2]) == "kg/(m s²)");
|
||||
CHECK(UNITS_STD_FMT::format("{:%sq}", 123 * isq::force[kg * m / s2]) == "kg m/s²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%sq}", 123 * isq::pressure[kg / m / s2]) == "kg m⁻¹ s⁻²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%asq}", 123 * isq::pressure[kg / m / s2]) == "kg/(m s²)");
|
||||
}
|
||||
|
||||
SECTION("Space is used by default")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%q}", 123 * isq::force[kg * m / s2]) == "kg m/s²");
|
||||
CHECK(STD_FMT::format("{:%q}", 123 * isq::pressure[kg / m / s2]) == "kg m⁻¹ s⁻²");
|
||||
CHECK(STD_FMT::format("{:%aq}", 123 * isq::pressure[kg / m / s2]) == "kg/(m s²)");
|
||||
CHECK(UNITS_STD_FMT::format("{:%q}", 123 * isq::force[kg * m / s2]) == "kg m/s²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%q}", 123 * isq::pressure[kg / m / s2]) == "kg m⁻¹ s⁻²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%aq}", 123 * isq::pressure[kg / m / s2]) == "kg/(m s²)");
|
||||
}
|
||||
|
||||
SECTION("Dot")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%dq}", 123 * isq::force[kg * m / s2]) == "kg⋅m/s²");
|
||||
CHECK(STD_FMT::format("{:%dq}", 123 * isq::pressure[kg / m / s2]) == "kg⋅m⁻¹⋅s⁻²");
|
||||
CHECK(STD_FMT::format("{:%adq}", 123 * isq::pressure[kg / m / s2]) == "kg/(m⋅s²)");
|
||||
CHECK(UNITS_STD_FMT::format("{:%dq}", 123 * isq::force[kg * m / s2]) == "kg⋅m/s²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%dq}", 123 * isq::pressure[kg / m / s2]) == "kg⋅m⁻¹⋅s⁻²");
|
||||
CHECK(UNITS_STD_FMT::format("{:%adq}", 123 * isq::pressure[kg / m / s2]) == "kg/(m⋅s²)");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -345,26 +348,26 @@ TEST_CASE("unknown unit modifiers should throw", "[text][fmt][exception]")
|
||||
{
|
||||
SECTION("only the invalid modifier")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%xq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%xq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
||||
}
|
||||
|
||||
SECTION("invalid modifier in the front")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%xUdaq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%xUdaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
||||
}
|
||||
|
||||
SECTION("invalid modifier in the end")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%Udaxq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%Udaxq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
||||
}
|
||||
|
||||
SECTION("invalid modifier in the middle")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%Udxaq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%Udxaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,40 +375,40 @@ TEST_CASE("repeated unit modifiers should throw", "[text][fmt][exception]")
|
||||
{
|
||||
SECTION("text encoding")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%UdaUq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%UdaUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%dUaUq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dUaUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%dUUaq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dUUaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
||||
}
|
||||
|
||||
SECTION("solidus")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%aUdaq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%aUdaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%daUaq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%daUaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%daaUq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%daaUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
||||
}
|
||||
|
||||
SECTION("separator")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%dUadq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dUadq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec"));
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%dadUq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dadUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec"));
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%addUq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%addUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec"));
|
||||
}
|
||||
}
|
||||
@ -414,58 +417,58 @@ TEST_CASE("more then one modifier of the same kind should throw", "[text][fmt][e
|
||||
{
|
||||
SECTION("text encoding")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%UdaAq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%UdaAq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%dAaUq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dAaUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%dAUaq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dAUaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
||||
}
|
||||
|
||||
SECTION("solidus")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%aUdnq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%aUdnq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%dnUaq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dnUaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%daoUq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%daoUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
||||
}
|
||||
|
||||
SECTION("separator")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%dUasq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dUasq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec"));
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%sadUq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%sadUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec"));
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%adsUq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%adsUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("dot separator requested for ASCII encoding should throw", "[text][fmt][exception]")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%dAaq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dAaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("dot unit separator allowed only for Unicode encoding"));
|
||||
}
|
||||
|
||||
TEST_CASE("%q and %Q can be put anywhere in a format string", "[text][fmt]")
|
||||
{
|
||||
SECTION("no space") { CHECK(STD_FMT::format("{:%Q%q}", 123 * isq::speed[km / h]) == "123km/h"); }
|
||||
SECTION("no space") { CHECK(UNITS_STD_FMT::format("{:%Q%q}", 123 * isq::speed[km / h]) == "123km/h"); }
|
||||
|
||||
SECTION("separator") { CHECK(STD_FMT::format("{:%Q###%q}", 123 * isq::speed[km / h]) == "123###km/h"); }
|
||||
SECTION("separator") { CHECK(UNITS_STD_FMT::format("{:%Q###%q}", 123 * isq::speed[km / h]) == "123###km/h"); }
|
||||
|
||||
SECTION("opposite order") { CHECK(STD_FMT::format("{:%q %Q}", 123 * isq::speed[km / h]) == "km/h 123"); }
|
||||
SECTION("opposite order") { CHECK(UNITS_STD_FMT::format("{:%q %Q}", 123 * isq::speed[km / h]) == "km/h 123"); }
|
||||
}
|
||||
|
||||
TEST_CASE("fill and align specification", "[text][fmt][ostream]")
|
||||
@ -513,50 +516,50 @@ TEST_CASE("fill and align specification", "[text][fmt][ostream]")
|
||||
|
||||
SECTION("default format {} on a quantity")
|
||||
{
|
||||
CHECK(STD_FMT::format("|{:0}|", 123 * isq::length[m]) == "|123 m|");
|
||||
CHECK(STD_FMT::format("|{:10}|", 123 * isq::length[m]) == "| 123 m|");
|
||||
CHECK(STD_FMT::format("|{:<10}|", 123 * isq::length[m]) == "|123 m |");
|
||||
CHECK(STD_FMT::format("|{:>10}|", 123 * isq::length[m]) == "| 123 m|");
|
||||
CHECK(STD_FMT::format("|{:^10}|", 123 * isq::length[m]) == "| 123 m |");
|
||||
CHECK(STD_FMT::format("|{:*<10}|", 123 * isq::length[m]) == "|123 m*****|");
|
||||
CHECK(STD_FMT::format("|{:*>10}|", 123 * isq::length[m]) == "|*****123 m|");
|
||||
CHECK(STD_FMT::format("|{:*^10}|", 123 * isq::length[m]) == "|**123 m***|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:0}|", 123 * isq::length[m]) == "|123 m|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:10}|", 123 * isq::length[m]) == "| 123 m|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:<10}|", 123 * isq::length[m]) == "|123 m |");
|
||||
CHECK(UNITS_STD_FMT::format("|{:>10}|", 123 * isq::length[m]) == "| 123 m|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:^10}|", 123 * isq::length[m]) == "| 123 m |");
|
||||
CHECK(UNITS_STD_FMT::format("|{:*<10}|", 123 * isq::length[m]) == "|123 m*****|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:*>10}|", 123 * isq::length[m]) == "|*****123 m|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:*^10}|", 123 * isq::length[m]) == "|**123 m***|");
|
||||
}
|
||||
|
||||
SECTION("full format {:%Q %q} on a quantity")
|
||||
{
|
||||
CHECK(STD_FMT::format("|{:0%Q%q}|", 123 * isq::length[m]) == "|123m|");
|
||||
CHECK(STD_FMT::format("|{:10%Q%q}|", 123 * isq::length[m]) == "| 123m|");
|
||||
CHECK(STD_FMT::format("|{:<10%Q%q}|", 123 * isq::length[m]) == "|123m |");
|
||||
CHECK(STD_FMT::format("|{:>10%Q%q}|", 123 * isq::length[m]) == "| 123m|");
|
||||
CHECK(STD_FMT::format("|{:^10%Q%q}|", 123 * isq::length[m]) == "| 123m |");
|
||||
CHECK(STD_FMT::format("|{:*<10%Q%q}|", 123 * isq::length[m]) == "|123m******|");
|
||||
CHECK(STD_FMT::format("|{:*>10%Q%q}|", 123 * isq::length[m]) == "|******123m|");
|
||||
CHECK(STD_FMT::format("|{:*^10%Q%q}|", 123 * isq::length[m]) == "|***123m***|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:0%Q%q}|", 123 * isq::length[m]) == "|123m|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:10%Q%q}|", 123 * isq::length[m]) == "| 123m|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:<10%Q%q}|", 123 * isq::length[m]) == "|123m |");
|
||||
CHECK(UNITS_STD_FMT::format("|{:>10%Q%q}|", 123 * isq::length[m]) == "| 123m|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:^10%Q%q}|", 123 * isq::length[m]) == "| 123m |");
|
||||
CHECK(UNITS_STD_FMT::format("|{:*<10%Q%q}|", 123 * isq::length[m]) == "|123m******|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:*>10%Q%q}|", 123 * isq::length[m]) == "|******123m|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:*^10%Q%q}|", 123 * isq::length[m]) == "|***123m***|");
|
||||
}
|
||||
|
||||
SECTION("value only format {:%Q} on a quantity")
|
||||
{
|
||||
CHECK(STD_FMT::format("|{:0%Q}|", 123 * isq::length[m]) == "|123|");
|
||||
CHECK(STD_FMT::format("|{:10%Q}|", 123 * isq::length[m]) == "| 123|");
|
||||
CHECK(STD_FMT::format("|{:<10%Q}|", 123 * isq::length[m]) == "|123 |");
|
||||
CHECK(STD_FMT::format("|{:>10%Q}|", 123 * isq::length[m]) == "| 123|");
|
||||
CHECK(STD_FMT::format("|{:^10%Q}|", 123 * isq::length[m]) == "| 123 |");
|
||||
CHECK(STD_FMT::format("|{:*<10%Q}|", 123 * isq::length[m]) == "|123*******|");
|
||||
CHECK(STD_FMT::format("|{:*>10%Q}|", 123 * isq::length[m]) == "|*******123|");
|
||||
CHECK(STD_FMT::format("|{:*^10%Q}|", 123 * isq::length[m]) == "|***123****|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:0%Q}|", 123 * isq::length[m]) == "|123|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:10%Q}|", 123 * isq::length[m]) == "| 123|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:<10%Q}|", 123 * isq::length[m]) == "|123 |");
|
||||
CHECK(UNITS_STD_FMT::format("|{:>10%Q}|", 123 * isq::length[m]) == "| 123|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:^10%Q}|", 123 * isq::length[m]) == "| 123 |");
|
||||
CHECK(UNITS_STD_FMT::format("|{:*<10%Q}|", 123 * isq::length[m]) == "|123*******|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:*>10%Q}|", 123 * isq::length[m]) == "|*******123|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:*^10%Q}|", 123 * isq::length[m]) == "|***123****|");
|
||||
}
|
||||
|
||||
SECTION("symbol only format {:%q} on a quantity")
|
||||
{
|
||||
CHECK(STD_FMT::format("|{:0%q}|", 123 * isq::length[m]) == "|m|");
|
||||
CHECK(STD_FMT::format("|{:10%q}|", 123 * isq::length[m]) == "| m|");
|
||||
CHECK(STD_FMT::format("|{:<10%q}|", 123 * isq::length[m]) == "|m |");
|
||||
CHECK(STD_FMT::format("|{:>10%q}|", 123 * isq::length[m]) == "| m|");
|
||||
CHECK(STD_FMT::format("|{:^10%q}|", 123 * isq::length[m]) == "| m |");
|
||||
CHECK(STD_FMT::format("|{:*<10%q}|", 123 * isq::length[m]) == "|m*********|");
|
||||
CHECK(STD_FMT::format("|{:*>10%q}|", 123 * isq::length[m]) == "|*********m|");
|
||||
CHECK(STD_FMT::format("|{:*^10%q}|", 123 * isq::length[m]) == "|****m*****|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:0%q}|", 123 * isq::length[m]) == "|m|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:10%q}|", 123 * isq::length[m]) == "| m|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:<10%q}|", 123 * isq::length[m]) == "|m |");
|
||||
CHECK(UNITS_STD_FMT::format("|{:>10%q}|", 123 * isq::length[m]) == "| m|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:^10%q}|", 123 * isq::length[m]) == "| m |");
|
||||
CHECK(UNITS_STD_FMT::format("|{:*<10%q}|", 123 * isq::length[m]) == "|m*********|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:*>10%q}|", 123 * isq::length[m]) == "|*********m|");
|
||||
CHECK(UNITS_STD_FMT::format("|{:*^10%q}|", 123 * isq::length[m]) == "|****m*****|");
|
||||
}
|
||||
}
|
||||
|
||||
@ -567,18 +570,18 @@ TEST_CASE("sign specification", "[text][fmt]")
|
||||
|
||||
SECTION("full format {:%Q %q} on a quantity")
|
||||
{
|
||||
CHECK(STD_FMT::format("{0:%Q%q},{0:%+Q%q},{0:%-Q%q},{0:% Q%q}", 1 * isq::length[m]) == "1m,+1m,1m, 1m");
|
||||
CHECK(STD_FMT::format("{0:%Q%q},{0:%+Q%q},{0:%-Q%q},{0:% Q%q}", -1 * isq::length[m]) == "-1m,-1m,-1m,-1m");
|
||||
CHECK(STD_FMT::format("{0:%Q%q},{0:%+Q%q},{0:%-Q%q},{0:% Q%q}", inf) == "infm,+infm,infm, infm");
|
||||
CHECK(STD_FMT::format("{0:%Q%q},{0:%+Q%q},{0:%-Q%q},{0:% Q%q}", nan) == "nanm,+nanm,nanm, nanm");
|
||||
CHECK(UNITS_STD_FMT::format("{0:%Q%q},{0:%+Q%q},{0:%-Q%q},{0:% Q%q}", 1 * isq::length[m]) == "1m,+1m,1m, 1m");
|
||||
CHECK(UNITS_STD_FMT::format("{0:%Q%q},{0:%+Q%q},{0:%-Q%q},{0:% Q%q}", -1 * isq::length[m]) == "-1m,-1m,-1m,-1m");
|
||||
CHECK(UNITS_STD_FMT::format("{0:%Q%q},{0:%+Q%q},{0:%-Q%q},{0:% Q%q}", inf) == "infm,+infm,infm, infm");
|
||||
CHECK(UNITS_STD_FMT::format("{0:%Q%q},{0:%+Q%q},{0:%-Q%q},{0:% Q%q}", nan) == "nanm,+nanm,nanm, nanm");
|
||||
}
|
||||
|
||||
SECTION("value only format {:%Q} on a quantity")
|
||||
{
|
||||
CHECK(STD_FMT::format("{0:%Q},{0:%+Q},{0:%-Q},{0:% Q}", 1 * isq::length[m]) == "1,+1,1, 1");
|
||||
CHECK(STD_FMT::format("{0:%Q},{0:%+Q},{0:%-Q},{0:% Q}", -1 * isq::length[m]) == "-1,-1,-1,-1");
|
||||
CHECK(STD_FMT::format("{0:%Q},{0:%+Q},{0:%-Q},{0:% Q}", inf) == "inf,+inf,inf, inf");
|
||||
CHECK(STD_FMT::format("{0:%Q},{0:%+Q},{0:%-Q},{0:% Q}", nan) == "nan,+nan,nan, nan");
|
||||
CHECK(UNITS_STD_FMT::format("{0:%Q},{0:%+Q},{0:%-Q},{0:% Q}", 1 * isq::length[m]) == "1,+1,1, 1");
|
||||
CHECK(UNITS_STD_FMT::format("{0:%Q},{0:%+Q},{0:%-Q},{0:% Q}", -1 * isq::length[m]) == "-1,-1,-1,-1");
|
||||
CHECK(UNITS_STD_FMT::format("{0:%Q},{0:%+Q},{0:%-Q},{0:% Q}", inf) == "inf,+inf,inf, inf");
|
||||
CHECK(UNITS_STD_FMT::format("{0:%Q},{0:%+Q},{0:%-Q},{0:% Q}", nan) == "nan,+nan,nan, nan");
|
||||
}
|
||||
}
|
||||
|
||||
@ -586,24 +589,24 @@ TEST_CASE("precision specification", "[text][fmt]")
|
||||
{
|
||||
SECTION("full format {:%Q %q} on a quantity")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%.0Q %q}", 1.2345 * isq::length[m]) == "1 m");
|
||||
CHECK(STD_FMT::format("{:%.1Q %q}", 1.2345 * isq::length[m]) == "1.2 m");
|
||||
CHECK(STD_FMT::format("{:%.2Q %q}", 1.2345 * isq::length[m]) == "1.23 m");
|
||||
CHECK(STD_FMT::format("{:%.3Q %q}", 1.2345 * isq::length[m]) == "1.234 m");
|
||||
CHECK(STD_FMT::format("{:%.4Q %q}", 1.2345 * isq::length[m]) == "1.2345 m");
|
||||
CHECK(STD_FMT::format("{:%.5Q %q}", 1.2345 * isq::length[m]) == "1.23450 m");
|
||||
CHECK(STD_FMT::format("{:%.10Q %q}", 1.2345 * isq::length[m]) == "1.2345000000 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.0Q %q}", 1.2345 * isq::length[m]) == "1 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.1Q %q}", 1.2345 * isq::length[m]) == "1.2 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.2Q %q}", 1.2345 * isq::length[m]) == "1.23 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3Q %q}", 1.2345 * isq::length[m]) == "1.234 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.4Q %q}", 1.2345 * isq::length[m]) == "1.2345 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.5Q %q}", 1.2345 * isq::length[m]) == "1.23450 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.10Q %q}", 1.2345 * isq::length[m]) == "1.2345000000 m");
|
||||
}
|
||||
|
||||
SECTION("value only format {:%Q} on a quantity")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%.0Q}", 1.2345 * isq::length[m]) == "1");
|
||||
CHECK(STD_FMT::format("{:%.1Q}", 1.2345 * isq::length[m]) == "1.2");
|
||||
CHECK(STD_FMT::format("{:%.2Q}", 1.2345 * isq::length[m]) == "1.23");
|
||||
CHECK(STD_FMT::format("{:%.3Q}", 1.2345 * isq::length[m]) == "1.234");
|
||||
CHECK(STD_FMT::format("{:%.4Q}", 1.2345 * isq::length[m]) == "1.2345");
|
||||
CHECK(STD_FMT::format("{:%.5Q}", 1.2345 * isq::length[m]) == "1.23450");
|
||||
CHECK(STD_FMT::format("{:%.10Q}", 1.2345 * isq::length[m]) == "1.2345000000");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.0Q}", 1.2345 * isq::length[m]) == "1");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.1Q}", 1.2345 * isq::length[m]) == "1.2");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.2Q}", 1.2345 * isq::length[m]) == "1.23");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3Q}", 1.2345 * isq::length[m]) == "1.234");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.4Q}", 1.2345 * isq::length[m]) == "1.2345");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.5Q}", 1.2345 * isq::length[m]) == "1.23450");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.10Q}", 1.2345 * isq::length[m]) == "1.2345000000");
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,15 +614,15 @@ TEST_CASE("precision specification for integral representation should throw", "[
|
||||
{
|
||||
SECTION("full format {:%Q %q} on a quantity")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%.1Q %q}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%.1Q %q}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("precision not allowed for integral quantity representation"));
|
||||
}
|
||||
|
||||
SECTION("value only format {:%Q} on a quantity")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%.1Q}", STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
STD_FMT::format_error,
|
||||
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%.1Q}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||
UNITS_STD_FMT::format_error,
|
||||
Catch::Matchers::Message("precision not allowed for integral quantity representation"));
|
||||
}
|
||||
}
|
||||
@ -628,56 +631,56 @@ TEST_CASE("type specification", "[text][fmt]")
|
||||
{
|
||||
SECTION("full format {:%Q %q} on a quantity")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%bQ %q}", 42 * isq::length[m]) == "101010 m");
|
||||
CHECK(STD_FMT::format("{:%BQ %q}", 42 * isq::length[m]) == "101010 m");
|
||||
CHECK(STD_FMT::format("{:%dQ %q}", 42 * isq::length[m]) == "42 m");
|
||||
CHECK(STD_FMT::format("{:%oQ %q}", 42 * isq::length[m]) == "52 m");
|
||||
CHECK(STD_FMT::format("{:%xQ %q}", 42 * isq::length[m]) == "2a m");
|
||||
CHECK(STD_FMT::format("{:%XQ %q}", 42 * isq::length[m]) == "2A m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%bQ %q}", 42 * isq::length[m]) == "101010 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%BQ %q}", 42 * isq::length[m]) == "101010 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%dQ %q}", 42 * isq::length[m]) == "42 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%oQ %q}", 42 * isq::length[m]) == "52 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%xQ %q}", 42 * isq::length[m]) == "2a m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%XQ %q}", 42 * isq::length[m]) == "2A m");
|
||||
|
||||
CHECK(STD_FMT::format("{:%aQ %q}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0 m");
|
||||
CHECK(STD_FMT::format("{:%.3aQ %q}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0 m");
|
||||
CHECK(STD_FMT::format("{:%AQ %q}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0 m");
|
||||
CHECK(STD_FMT::format("{:%.3AQ %q}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0 m");
|
||||
CHECK(STD_FMT::format("{:%eQ %q}", 1.2345678 * isq::length[m]) == "1.234568e+00 m");
|
||||
CHECK(STD_FMT::format("{:%.3eQ %q}", 1.2345678 * isq::length[m]) == "1.235e+00 m");
|
||||
CHECK(STD_FMT::format("{:%EQ %q}", 1.2345678 * isq::length[m]) == "1.234568E+00 m");
|
||||
CHECK(STD_FMT::format("{:%.3EQ %q}", 1.2345678 * isq::length[m]) == "1.235E+00 m");
|
||||
CHECK(STD_FMT::format("{:%gQ %q}", 1.2345678 * isq::length[m]) == "1.23457 m");
|
||||
CHECK(STD_FMT::format("{:%gQ %q}", 1.2345678e8 * isq::length[m]) == "1.23457e+08 m");
|
||||
CHECK(STD_FMT::format("{:%.3gQ %q}", 1.2345678 * isq::length[m]) == "1.23 m");
|
||||
CHECK(STD_FMT::format("{:%.3gQ %q}", 1.2345678e8 * isq::length[m]) == "1.23e+08 m");
|
||||
CHECK(STD_FMT::format("{:%GQ %q}", 1.2345678 * isq::length[m]) == "1.23457 m");
|
||||
CHECK(STD_FMT::format("{:%GQ %q}", 1.2345678e8 * isq::length[m]) == "1.23457E+08 m");
|
||||
CHECK(STD_FMT::format("{:%.3GQ %q}", 1.2345678 * isq::length[m]) == "1.23 m");
|
||||
CHECK(STD_FMT::format("{:%.3GQ %q}", 1.2345678e8 * isq::length[m]) == "1.23E+08 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%aQ %q}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3aQ %q}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%AQ %q}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3AQ %q}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%eQ %q}", 1.2345678 * isq::length[m]) == "1.234568e+00 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3eQ %q}", 1.2345678 * isq::length[m]) == "1.235e+00 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%EQ %q}", 1.2345678 * isq::length[m]) == "1.234568E+00 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3EQ %q}", 1.2345678 * isq::length[m]) == "1.235E+00 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%gQ %q}", 1.2345678 * isq::length[m]) == "1.23457 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%gQ %q}", 1.2345678e8 * isq::length[m]) == "1.23457e+08 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3gQ %q}", 1.2345678 * isq::length[m]) == "1.23 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3gQ %q}", 1.2345678e8 * isq::length[m]) == "1.23e+08 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%GQ %q}", 1.2345678 * isq::length[m]) == "1.23457 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%GQ %q}", 1.2345678e8 * isq::length[m]) == "1.23457E+08 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3GQ %q}", 1.2345678 * isq::length[m]) == "1.23 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3GQ %q}", 1.2345678e8 * isq::length[m]) == "1.23E+08 m");
|
||||
}
|
||||
|
||||
SECTION("value only format {:%Q} on a quantity")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%bQ}", 42 * isq::length[m]) == "101010");
|
||||
CHECK(STD_FMT::format("{:%BQ}", 42 * isq::length[m]) == "101010");
|
||||
CHECK(STD_FMT::format("{:%dQ}", 42 * isq::length[m]) == "42");
|
||||
CHECK(STD_FMT::format("{:%oQ}", 42 * isq::length[m]) == "52");
|
||||
CHECK(STD_FMT::format("{:%xQ}", 42 * isq::length[m]) == "2a");
|
||||
CHECK(STD_FMT::format("{:%XQ}", 42 * isq::length[m]) == "2A");
|
||||
CHECK(UNITS_STD_FMT::format("{:%bQ}", 42 * isq::length[m]) == "101010");
|
||||
CHECK(UNITS_STD_FMT::format("{:%BQ}", 42 * isq::length[m]) == "101010");
|
||||
CHECK(UNITS_STD_FMT::format("{:%dQ}", 42 * isq::length[m]) == "42");
|
||||
CHECK(UNITS_STD_FMT::format("{:%oQ}", 42 * isq::length[m]) == "52");
|
||||
CHECK(UNITS_STD_FMT::format("{:%xQ}", 42 * isq::length[m]) == "2a");
|
||||
CHECK(UNITS_STD_FMT::format("{:%XQ}", 42 * isq::length[m]) == "2A");
|
||||
|
||||
CHECK(STD_FMT::format("{:%aQ}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0");
|
||||
CHECK(STD_FMT::format("{:%.3aQ}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0");
|
||||
CHECK(STD_FMT::format("{:%AQ}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0");
|
||||
CHECK(STD_FMT::format("{:%.3AQ}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0");
|
||||
CHECK(STD_FMT::format("{:%eQ}", 1.2345678 * isq::length[m]) == "1.234568e+00");
|
||||
CHECK(STD_FMT::format("{:%.3eQ}", 1.2345678 * isq::length[m]) == "1.235e+00");
|
||||
CHECK(STD_FMT::format("{:%EQ}", 1.2345678 * isq::length[m]) == "1.234568E+00");
|
||||
CHECK(STD_FMT::format("{:%.3EQ}", 1.2345678 * isq::length[m]) == "1.235E+00");
|
||||
CHECK(STD_FMT::format("{:%gQ}", 1.2345678 * isq::length[m]) == "1.23457");
|
||||
CHECK(STD_FMT::format("{:%gQ}", 1.2345678e8 * isq::length[m]) == "1.23457e+08");
|
||||
CHECK(STD_FMT::format("{:%.3gQ}", 1.2345678 * isq::length[m]) == "1.23");
|
||||
CHECK(STD_FMT::format("{:%.3gQ}", 1.2345678e8 * isq::length[m]) == "1.23e+08");
|
||||
CHECK(STD_FMT::format("{:%GQ}", 1.2345678 * isq::length[m]) == "1.23457");
|
||||
CHECK(STD_FMT::format("{:%GQ}", 1.2345678e8 * isq::length[m]) == "1.23457E+08");
|
||||
CHECK(STD_FMT::format("{:%.3GQ}", 1.2345678 * isq::length[m]) == "1.23");
|
||||
CHECK(STD_FMT::format("{:%.3GQ}", 1.2345678e8 * isq::length[m]) == "1.23E+08");
|
||||
CHECK(UNITS_STD_FMT::format("{:%aQ}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3aQ}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0");
|
||||
CHECK(UNITS_STD_FMT::format("{:%AQ}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3AQ}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0");
|
||||
CHECK(UNITS_STD_FMT::format("{:%eQ}", 1.2345678 * isq::length[m]) == "1.234568e+00");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3eQ}", 1.2345678 * isq::length[m]) == "1.235e+00");
|
||||
CHECK(UNITS_STD_FMT::format("{:%EQ}", 1.2345678 * isq::length[m]) == "1.234568E+00");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3EQ}", 1.2345678 * isq::length[m]) == "1.235E+00");
|
||||
CHECK(UNITS_STD_FMT::format("{:%gQ}", 1.2345678 * isq::length[m]) == "1.23457");
|
||||
CHECK(UNITS_STD_FMT::format("{:%gQ}", 1.2345678e8 * isq::length[m]) == "1.23457e+08");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3gQ}", 1.2345678 * isq::length[m]) == "1.23");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3gQ}", 1.2345678e8 * isq::length[m]) == "1.23e+08");
|
||||
CHECK(UNITS_STD_FMT::format("{:%GQ}", 1.2345678 * isq::length[m]) == "1.23457");
|
||||
CHECK(UNITS_STD_FMT::format("{:%GQ}", 1.2345678e8 * isq::length[m]) == "1.23457E+08");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3GQ}", 1.2345678 * isq::length[m]) == "1.23");
|
||||
CHECK(UNITS_STD_FMT::format("{:%.3GQ}", 1.2345678e8 * isq::length[m]) == "1.23E+08");
|
||||
}
|
||||
}
|
||||
|
||||
@ -685,20 +688,20 @@ TEST_CASE("different base types with the # specifier", "[text][fmt]")
|
||||
{
|
||||
SECTION("full format {:%Q %q} on a quantity")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%#bQ %q}", 42 * isq::length[m]) == "0b101010 m");
|
||||
CHECK(STD_FMT::format("{:%#BQ %q}", 42 * isq::length[m]) == "0B101010 m");
|
||||
CHECK(STD_FMT::format("{:%#oQ %q}", 42 * isq::length[m]) == "052 m");
|
||||
CHECK(STD_FMT::format("{:%#xQ %q}", 42 * isq::length[m]) == "0x2a m");
|
||||
CHECK(STD_FMT::format("{:%#XQ %q}", 42 * isq::length[m]) == "0X2A m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%#bQ %q}", 42 * isq::length[m]) == "0b101010 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%#BQ %q}", 42 * isq::length[m]) == "0B101010 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%#oQ %q}", 42 * isq::length[m]) == "052 m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%#xQ %q}", 42 * isq::length[m]) == "0x2a m");
|
||||
CHECK(UNITS_STD_FMT::format("{:%#XQ %q}", 42 * isq::length[m]) == "0X2A m");
|
||||
}
|
||||
|
||||
SECTION("value only format {:%Q} on a quantity")
|
||||
{
|
||||
CHECK(STD_FMT::format("{:%#bQ}", 42 * isq::length[m]) == "0b101010");
|
||||
CHECK(STD_FMT::format("{:%#BQ}", 42 * isq::length[m]) == "0B101010");
|
||||
CHECK(STD_FMT::format("{:%#oQ}", 42 * isq::length[m]) == "052");
|
||||
CHECK(STD_FMT::format("{:%#xQ}", 42 * isq::length[m]) == "0x2a");
|
||||
CHECK(STD_FMT::format("{:%#XQ}", 42 * isq::length[m]) == "0X2A");
|
||||
CHECK(UNITS_STD_FMT::format("{:%#bQ}", 42 * isq::length[m]) == "0b101010");
|
||||
CHECK(UNITS_STD_FMT::format("{:%#BQ}", 42 * isq::length[m]) == "0B101010");
|
||||
CHECK(UNITS_STD_FMT::format("{:%#oQ}", 42 * isq::length[m]) == "052");
|
||||
CHECK(UNITS_STD_FMT::format("{:%#xQ}", 42 * isq::length[m]) == "0x2a");
|
||||
CHECK(UNITS_STD_FMT::format("{:%#XQ}", 42 * isq::length[m]) == "0X2A");
|
||||
}
|
||||
}
|
||||
|
||||
@ -719,8 +722,8 @@ TEST_CASE("localization with the 'L' specifier", "[text][fmt][localization]")
|
||||
|
||||
SECTION("full format {:%LQ %q} on a quantity")
|
||||
{
|
||||
CHECK(STD_FMT::format(grp2, "{:%LQ %q}", 299792458 * isq::speed[m / s]) == "2_99_79_24_58 m/s");
|
||||
CHECK(STD_FMT::format(grp3, "{:%LQ %q}", 299792458 * isq::speed[m / s]) == "299'792'458 m/s");
|
||||
CHECK(UNITS_STD_FMT::format(grp2, "{:%LQ %q}", 299792458 * isq::speed[m / s]) == "2_99_79_24_58 m/s");
|
||||
CHECK(UNITS_STD_FMT::format(grp3, "{:%LQ %q}", 299792458 * isq::speed[m / s]) == "299'792'458 m/s");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,28 +23,26 @@
|
||||
import os
|
||||
|
||||
from conan import ConanFile
|
||||
from conan.tools.build import cross_building
|
||||
from conan.tools.build import can_run
|
||||
from conan.tools.cmake import CMake, cmake_layout
|
||||
|
||||
|
||||
class TestPackageConan(ConanFile):
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
generators = "CMakeDeps", "CMakeToolchain", "VirtualBuildEnv", "VirtualRunEnv"
|
||||
apply_env = False
|
||||
test_type = "explicit" # TODO Remove for Conan 2.0
|
||||
settings = "os", "arch", "compiler", "build_type"
|
||||
generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv"
|
||||
|
||||
def requirements(self):
|
||||
self.requires(self.tested_reference_str)
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
cmake.configure()
|
||||
cmake.build()
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
|
||||
def test(self):
|
||||
if not cross_building(self):
|
||||
cmd = os.path.join(self.cpp.build.bindirs[0], "test_package")
|
||||
self.run(cmd, env="conanrun")
|
||||
if can_run(self):
|
||||
bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package")
|
||||
self.run(bin_path, env="conanrun")
|
||||
|
Reference in New Issue
Block a user