mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-29 18:07:16 +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:
|
jobs:
|
||||||
check:
|
check:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Set up Python 3.8
|
- name: Set up Python 3.8
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: 3.8
|
python-version: 3.8
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
- name: Check
|
- name: Check
|
||||||
run: |
|
run: |
|
||||||
pre-commit run --all-files
|
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:
|
paths-ignore:
|
||||||
- "docs/**"
|
- "docs/**"
|
||||||
|
|
||||||
|
env:
|
||||||
|
CHANNEL: ${{ fromJSON('["testing", "stable"]')[github.ref_type == 'tag' && startsWith(github.ref_name, 'v')] }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: ${{ matrix.config.name }} ${{ matrix.build_type }} [downcast=${{ matrix.downcast_mode }}]
|
name: ${{ matrix.config.name }} ${{ matrix.build_type }} [downcast=${{ matrix.downcast_mode }}]
|
||||||
@ -42,15 +45,17 @@ jobs:
|
|||||||
name: "Windows MSVC 14.2",
|
name: "Windows MSVC 14.2",
|
||||||
os: windows-2019,
|
os: windows-2019,
|
||||||
compiler: { type: VISUAL, version: 16, cc: "", cxx: "", std: 20 },
|
compiler: { type: VISUAL, version: 16, cc: "", cxx: "", std: 20 },
|
||||||
|
conan-config: "-c user.build:skip_la=True",
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
name: "Windows MSVC 14.3",
|
name: "Windows MSVC 14.3",
|
||||||
os: windows-2022,
|
os: windows-2022,
|
||||||
compiler: { type: MSVC, version: 193, cc: "", cxx: "", std: 23 },
|
compiler: { type: MSVC, version: 193, cc: "", cxx: "", std: 23 },
|
||||||
|
conan-config: "",
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
name: "Ubuntu GCC-10",
|
name: "Ubuntu GCC-10",
|
||||||
os: ubuntu-20.04,
|
os: ubuntu-22.04,
|
||||||
compiler:
|
compiler:
|
||||||
{
|
{
|
||||||
type: GCC,
|
type: GCC,
|
||||||
@ -59,11 +64,11 @@ jobs:
|
|||||||
cxx: "g++-10",
|
cxx: "g++-10",
|
||||||
std: 20,
|
std: 20,
|
||||||
},
|
},
|
||||||
lib: "libstdc++11",
|
conan-config: "",
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
name: "Ubuntu GCC-11",
|
name: "Ubuntu GCC-11",
|
||||||
os: ubuntu-20.04,
|
os: ubuntu-22.04,
|
||||||
compiler:
|
compiler:
|
||||||
{
|
{
|
||||||
type: GCC,
|
type: GCC,
|
||||||
@ -72,7 +77,20 @@ jobs:
|
|||||||
cxx: "g++-11",
|
cxx: "g++-11",
|
||||||
std: 20,
|
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",
|
name: "Ubuntu Clang-12 + libstdc++11",
|
||||||
@ -86,6 +104,7 @@ jobs:
|
|||||||
std: 20,
|
std: 20,
|
||||||
},
|
},
|
||||||
lib: "libstdc++11",
|
lib: "libstdc++11",
|
||||||
|
conan-config: "",
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
name: "Ubuntu Clang-12 + libc++",
|
name: "Ubuntu Clang-12 + libc++",
|
||||||
@ -99,10 +118,11 @@ jobs:
|
|||||||
std: 20,
|
std: 20,
|
||||||
},
|
},
|
||||||
lib: "libc++",
|
lib: "libc++",
|
||||||
|
conan-config: "",
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
name: "Ubuntu Clang-13 + libc++",
|
name: "Ubuntu Clang-13 + libc++",
|
||||||
os: ubuntu-20.04,
|
os: ubuntu-22.04,
|
||||||
compiler:
|
compiler:
|
||||||
{
|
{
|
||||||
type: CLANG,
|
type: CLANG,
|
||||||
@ -112,10 +132,11 @@ jobs:
|
|||||||
std: 20,
|
std: 20,
|
||||||
},
|
},
|
||||||
lib: "libc++",
|
lib: "libc++",
|
||||||
|
conan-config: "",
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
name: "Ubuntu Clang-14 + libc++",
|
name: "Ubuntu Clang-14 + libc++",
|
||||||
os: ubuntu-20.04,
|
os: ubuntu-22.04,
|
||||||
compiler:
|
compiler:
|
||||||
{
|
{
|
||||||
type: CLANG,
|
type: CLANG,
|
||||||
@ -125,6 +146,35 @@ jobs:
|
|||||||
std: 20,
|
std: 20,
|
||||||
},
|
},
|
||||||
lib: "libc++",
|
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",
|
name: "MacOS Apple Clang 13",
|
||||||
@ -137,6 +187,7 @@ jobs:
|
|||||||
cxx: "clang++",
|
cxx: "clang++",
|
||||||
std: 20,
|
std: 20,
|
||||||
},
|
},
|
||||||
|
conan-config: "",
|
||||||
}
|
}
|
||||||
build_type: ["Release", "Debug"]
|
build_type: ["Release", "Debug"]
|
||||||
downcast_mode: ["on", "auto"]
|
downcast_mode: ["on", "auto"]
|
||||||
@ -146,25 +197,27 @@ jobs:
|
|||||||
CXX: ${{ matrix.config.compiler.cxx }}
|
CXX: ${{ matrix.config.compiler.cxx }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Cache Conan data
|
- name: Cache Conan data
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
env:
|
env:
|
||||||
cache-name: cache-conan-data
|
cache-name: cache-conan-data
|
||||||
with:
|
with:
|
||||||
path: ~/.conan/data
|
path: ~/.conan2/p
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/metadata.json') }}
|
key: build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-${{ matrix.config.lib }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-${{ matrix.config.lib }}
|
||||||
${{ runner.os }}-build-
|
build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-
|
||||||
${{ runner.os }}-
|
build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-
|
||||||
- uses: hendrikmuhs/ccache-action@v1
|
build-${{ matrix.config.os }}-${{ matrix.build_type }}-
|
||||||
|
build-${{ matrix.config.os }}-
|
||||||
|
- uses: hendrikmuhs/ccache-action@v1.2
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
with:
|
with:
|
||||||
key: ${{ matrix.config.os }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-${{ matrix.config.lib }}-${{ matrix.build_type }}-${{ matrix.downcast_mode }}
|
key: ${{ matrix.config.os }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-${{ matrix.config.lib }}-${{ matrix.build_type }}-${{ matrix.downcast_mode }}
|
||||||
max-size: 50M
|
max-size: 50M
|
||||||
- name: Install gcc-11
|
- name: Install gcc-12
|
||||||
if: matrix.config.compiler.type == 'GCC' && matrix.config.compiler.version == '11'
|
if: matrix.config.compiler.type == 'GCC' && matrix.config.compiler.version == '12'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sudo apt install -y g++-${{ matrix.config.compiler.version }}
|
sudo apt install -y g++-${{ matrix.config.compiler.version }}
|
||||||
@ -201,7 +254,7 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: "3.8"
|
python-version: "3.8"
|
||||||
- name: Install Conan
|
- name: Install Conan
|
||||||
@ -211,37 +264,76 @@ jobs:
|
|||||||
- name: Configure Conan
|
- name: Configure Conan
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
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 }}" == "CLANG" ]]; then
|
||||||
if [[ "${{ matrix.config.compiler.type }}" == "GCC" || "${{ matrix.config.compiler.type }}" == "CLANG" ]]; then
|
sed -i.backup '/^\[settings\]$/,/^\[/ s/^compiler.libcxx=.*/compiler.libcxx=${{ matrix.config.lib }}/' ~/.conan2/profiles/default
|
||||||
conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default
|
|
||||||
fi
|
fi
|
||||||
conan profile update settings.compiler.cppstd=${{ matrix.config.compiler.std }} default
|
sed -i.backup '/^\[settings\]$/,/^\[/ s/^compiler.cppstd=.*/compiler.cppstd=${{ matrix.config.compiler.std }}/' ~/.conan2/profiles/default
|
||||||
conan profile update settings.build_type=${{ matrix.build_type }} default
|
sed -i.backup '/^\[settings\]$/,/^\[/ s/^build_type=.*/build_type=${{ matrix.build_type }}/' ~/.conan2/profiles/default
|
||||||
conan profile update conf.tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" default
|
conan profile show -pr default
|
||||||
conan profile show default
|
|
||||||
# - name: Add support for clang-13 to Conan's settings.yml
|
# - name: Add support for clang-13 to Conan's settings.yml
|
||||||
# # TODO Remove when Conan will support clang-13
|
# # TODO Remove when Conan will support clang-13
|
||||||
# if: matrix.config.compiler.type == 'CLANG'
|
# if: matrix.config.compiler.type == 'CLANG'
|
||||||
# shell: bash
|
# shell: bash
|
||||||
# run: |
|
# run: |
|
||||||
# sed -i -e 's/"8", "9", "10", "11", "12"]/"8", "9", "10", "11", "12", "13"]/' ~/.conan/settings.yml
|
# 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
|
- name: Create Conan package
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
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
|
conan create . --user mpusz --channel ${CHANNEL} --lockfile-out=package.lock \
|
||||||
- name: Upload mp-units Conan package
|
-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'
|
if: github.ref == 'refs/heads/master' || env.CHANNEL == 'stable'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
conan user ${{ secrets.CONAN_LOGIN_USERNAME }} -r artifactory -p ${{ secrets.CONAN_PASSWORD }}
|
conan remote add conan-mpusz-ci https://mpusz.jfrog.io/artifactory/api/conan/conan-ci
|
||||||
conan upload "mp-units*" --all -r artifactory --confirm
|
conan remote login conan-mpusz-ci ${{ secrets.CONAN_LOGIN_USERNAME }} -p ${{ secrets.CONAN_CI_PASSWORD }}
|
||||||
- name: Remove mp-units package from Conan local cache
|
conan upload ${{ steps.get-package-ref.outputs.package_ref }} -r conan-mpusz-ci --confirm
|
||||||
|
- name: Clean Conan cache before backup
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
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",
|
name: "Ubuntu GCC-10",
|
||||||
os: ubuntu-20.04,
|
os: ubuntu-22.04,
|
||||||
compiler:
|
compiler:
|
||||||
{
|
{
|
||||||
type: GCC,
|
type: GCC,
|
||||||
@ -63,11 +63,10 @@ jobs:
|
|||||||
cxx: "g++-10",
|
cxx: "g++-10",
|
||||||
std: 20,
|
std: 20,
|
||||||
},
|
},
|
||||||
lib: "libstdc++11",
|
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
name: "Ubuntu GCC-11",
|
name: "Ubuntu GCC-11",
|
||||||
os: ubuntu-20.04,
|
os: ubuntu-22.04,
|
||||||
compiler:
|
compiler:
|
||||||
{
|
{
|
||||||
type: GCC,
|
type: GCC,
|
||||||
@ -76,7 +75,18 @@ jobs:
|
|||||||
cxx: "g++-11",
|
cxx: "g++-11",
|
||||||
std: 20,
|
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",
|
name: "Ubuntu Clang-12 + libstdc++11",
|
||||||
@ -106,7 +116,7 @@ jobs:
|
|||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
name: "Ubuntu Clang-13 + libc++",
|
name: "Ubuntu Clang-13 + libc++",
|
||||||
os: ubuntu-20.04,
|
os: ubuntu-22.04,
|
||||||
compiler:
|
compiler:
|
||||||
{
|
{
|
||||||
type: CLANG,
|
type: CLANG,
|
||||||
@ -119,7 +129,7 @@ jobs:
|
|||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
name: "Ubuntu Clang-14 + libc++",
|
name: "Ubuntu Clang-14 + libc++",
|
||||||
os: ubuntu-20.04,
|
os: ubuntu-22.04,
|
||||||
compiler:
|
compiler:
|
||||||
{
|
{
|
||||||
type: CLANG,
|
type: CLANG,
|
||||||
@ -130,6 +140,32 @@ jobs:
|
|||||||
},
|
},
|
||||||
lib: "libc++",
|
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",
|
name: "MacOS Apple Clang 13",
|
||||||
os: macos-11,
|
os: macos-11,
|
||||||
@ -154,18 +190,20 @@ jobs:
|
|||||||
uses: ASzc/change-string-case-action@v2
|
uses: ASzc/change-string-case-action@v2
|
||||||
with:
|
with:
|
||||||
string: ${{ matrix.build_type }}
|
string: ${{ matrix.build_type }}
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Cache Conan data
|
- name: Cache Conan data
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
env:
|
env:
|
||||||
cache-name: cache-conan-data
|
cache-name: cache-conan-data
|
||||||
with:
|
with:
|
||||||
path: ~/.conan/data
|
path: ~/.conan2/p
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/metadata.json') }}
|
key: build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-${{ matrix.config.lib }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-${{ matrix.config.lib }}
|
||||||
${{ runner.os }}-build-
|
build-${{ matrix.config.os }}-${{ matrix.build_type }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-
|
||||||
${{ runner.os }}-
|
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
|
- name: Install gcc-11
|
||||||
if: matrix.config.compiler.type == 'GCC' && matrix.config.compiler.version == '11'
|
if: matrix.config.compiler.type == 'GCC' && matrix.config.compiler.version == '11'
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -204,7 +242,7 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: "3.8"
|
python-version: "3.8"
|
||||||
- name: Install Conan
|
- name: Install Conan
|
||||||
@ -214,15 +252,14 @@ jobs:
|
|||||||
- name: Configure Conan
|
- name: Configure Conan
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
conan config init
|
conan profile detect --force
|
||||||
conan remote add artifactory https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
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
|
if [[ "${{ matrix.config.compiler.type }}" == "CLANG" ]]; then
|
||||||
conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default
|
sed -i.backup '/^\[settings\]$/,/^\[/ s/^compiler.libcxx=.*/compiler.libcxx=${{ matrix.config.lib }}/' ~/.conan2/profiles/default
|
||||||
fi
|
fi
|
||||||
conan profile update settings.compiler.cppstd=${{ matrix.config.compiler.std }} default
|
sed -i.backup '/^\[settings\]$/,/^\[/ s/^compiler.cppstd=.*/compiler.cppstd=${{ matrix.config.compiler.std }}/' ~/.conan2/profiles/default
|
||||||
conan profile update settings.build_type=${{ matrix.build_type }} default
|
sed -i.backup '/^\[settings\]$/,/^\[/ s/^build_type=.*/build_type=${{ matrix.build_type }}/' ~/.conan2/profiles/default
|
||||||
conan profile update conf.tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" default
|
conan profile show -pr default
|
||||||
conan profile show default
|
|
||||||
# - name: Add support for clang-13 to Conan's settings.yml
|
# - name: Add support for clang-13 to Conan's settings.yml
|
||||||
# # TODO Remove when Conan will support clang-13
|
# # TODO Remove when Conan will support clang-13
|
||||||
# if: matrix.config.compiler.type == 'CLANG'
|
# if: matrix.config.compiler.type == 'CLANG'
|
||||||
@ -232,7 +269,7 @@ jobs:
|
|||||||
- name: Install Conan dependencies
|
- name: Install Conan dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
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
|
mv CMakeUserPresets.json src
|
||||||
- name: Configure mp-units CMake
|
- name: Configure mp-units CMake
|
||||||
if: matrix.config.compiler.type == 'VISUAL' || matrix.config.compiler.type == 'MSVC'
|
if: matrix.config.compiler.type == 'VISUAL' || matrix.config.compiler.type == 'MSVC'
|
||||||
@ -241,19 +278,19 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cmake --version
|
cmake --version
|
||||||
call ..\build\generators\conanvcvars.bat
|
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
|
- name: Configure mp-units CMake
|
||||||
if: matrix.config.compiler.type != 'VISUAL' && matrix.config.compiler.type != 'MSVC'
|
if: matrix.config.compiler.type != 'VISUAL' && matrix.config.compiler.type != 'MSVC'
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: src
|
working-directory: src
|
||||||
run: |
|
run: |
|
||||||
cmake --version
|
cmake --version
|
||||||
cmake --preset default -DCMAKE_INSTALL_PREFIX=../out
|
cmake --preset conan-default -DCMAKE_INSTALL_PREFIX=../out
|
||||||
- name: Install mp-units
|
- name: Install mp-units
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: src
|
working-directory: src
|
||||||
run: |
|
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
|
- name: Provide dependencies for test_package
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: test_package
|
working-directory: test_package
|
||||||
@ -265,14 +302,14 @@ jobs:
|
|||||||
working-directory: test_package
|
working-directory: test_package
|
||||||
run: |
|
run: |
|
||||||
call ..\build\generators\conanvcvars.bat
|
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 }}
|
cmake --build build/local --config ${{ matrix.build_type }}
|
||||||
- name: Build test_package CMake (local build)
|
- name: Build test_package CMake (local build)
|
||||||
if: matrix.config.compiler.type != 'VISUAL' && matrix.config.compiler.type != 'MSVC'
|
if: matrix.config.compiler.type != 'VISUAL' && matrix.config.compiler.type != 'MSVC'
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: test_package
|
working-directory: test_package
|
||||||
run: |
|
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 }}
|
cmake --build build/local --config ${{ matrix.build_type }}
|
||||||
- name: Run test_package (local build)
|
- name: Run test_package (local build)
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -285,14 +322,14 @@ jobs:
|
|||||||
working-directory: test_package
|
working-directory: test_package
|
||||||
run: |
|
run: |
|
||||||
call ..\build\generators\conanvcvars.bat
|
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 }}
|
cmake --build build/install --config ${{ matrix.build_type }}
|
||||||
- name: Build test_package CMake (installation)
|
- name: Build test_package CMake (installation)
|
||||||
if: matrix.config.compiler.type != 'VISUAL' && matrix.config.compiler.type != 'MSVC'
|
if: matrix.config.compiler.type != 'VISUAL' && matrix.config.compiler.type != 'MSVC'
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: test_package
|
working-directory: test_package
|
||||||
run: |
|
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 }}
|
cmake --build build/install --config ${{ matrix.build_type }}
|
||||||
- name: Run test_package (installation)
|
- name: Run test_package (installation)
|
||||||
shell: bash
|
shell: bash
|
||||||
|
2
.github/workflows/citation.yml
vendored
2
.github/workflows/citation.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
# This is needed for workflows running on
|
# This is needed for workflows running on
|
||||||
# ubuntu-20.04 or later
|
# 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:
|
jobs:
|
||||||
analyze:
|
analyze:
|
||||||
name: Analyze
|
name: Analyze
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ${{ matrix.os }}
|
||||||
env:
|
env:
|
||||||
CC: gcc-10
|
CC: gcc-10
|
||||||
CXX: g++-10
|
CXX: g++-10
|
||||||
|
BUILD_TYPE: Debug
|
||||||
|
COMPILER_TYPE: GCC
|
||||||
|
COMPILER_VERSION: 10
|
||||||
|
STDLIB: libstdc++11
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
language: ["cpp", "python"]
|
language: ["cpp", "python"]
|
||||||
|
os: ["ubuntu-latest"]
|
||||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||||
# Learn more...
|
# Learn more...
|
||||||
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
|
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
@ -63,29 +67,29 @@ jobs:
|
|||||||
|
|
||||||
- name: Cache Conan data
|
- name: Cache Conan data
|
||||||
if: matrix.language == 'cpp'
|
if: matrix.language == 'cpp'
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
env:
|
env:
|
||||||
cache-name: cache-conan-data
|
cache-name: cache-conan-data
|
||||||
with:
|
with:
|
||||||
path: ~/.conan/data
|
path: ~/.conan2/p
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/metadata.json') }}
|
key: build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-$COMPILER_VERSION-$STDLIB
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-$COMPILER_VERSION-
|
||||||
${{ runner.os }}-build-
|
build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-
|
||||||
${{ runner.os }}-
|
build-${{ matrix.os }}-$BUILD_TYPE-
|
||||||
|
build-${{ matrix.os }}-
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
if: matrix.language == 'cpp'
|
if: matrix.language == 'cpp'
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: "3.8"
|
python-version: "3.8"
|
||||||
- name: Conan build
|
- name: Conan build
|
||||||
if: matrix.language == 'cpp'
|
if: matrix.language == 'cpp'
|
||||||
run: |
|
run: |
|
||||||
pip install -U conan
|
pip install -U conan
|
||||||
conan config init
|
conan profile detect --force
|
||||||
conan remote add upload https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
conan remote add artifactory https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||||
mkdir _lgtm_build_dir && cd _lgtm_build_dir
|
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 .. -s compiler.cppstd=20 -s compiler.libcxx=$STDLIB -c user.build:all=True -c user.build:skip_docs=True -b missing
|
||||||
conan build ..
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v1
|
uses: github/codeql-action/analyze@v1
|
||||||
|
51
.github/workflows/documentation.yml
vendored
51
.github/workflows/documentation.yml
vendored
@ -35,35 +35,44 @@ on:
|
|||||||
- "docs/**"
|
- "docs/**"
|
||||||
- "src/**"
|
- "src/**"
|
||||||
- "example/**"
|
- "example/**"
|
||||||
|
|
||||||
env:
|
|
||||||
CC: gcc-10
|
|
||||||
CXX: g++-10
|
|
||||||
CMAKE_GENERATOR: Ninja
|
|
||||||
CONAN_CMAKE_GENERATOR: Ninja
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docs:
|
docs:
|
||||||
name: Generate documentation
|
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:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Cache Conan data
|
- name: Cache Conan data
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
env:
|
env:
|
||||||
cache-name: cache-conan-data
|
cache-name: cache-conan-data
|
||||||
with:
|
with:
|
||||||
path: ~/.conan/data
|
path: ~/.conan2/p
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/metadata.json') }}
|
key: build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-$COMPILER_VERSION-$STDLIB-docs
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-$COMPILER_VERSION-$STDLIB
|
||||||
${{ runner.os }}-build-
|
build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-$COMPILER_VERSION-
|
||||||
${{ runner.os }}-
|
build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-
|
||||||
|
build-${{ matrix.os }}-$BUILD_TYPE-
|
||||||
|
build-${{ matrix.os }}-
|
||||||
- name: Install Ninja
|
- name: Install Ninja
|
||||||
run: |
|
run: |
|
||||||
sudo apt install -y ninja-build
|
sudo apt install -y ninja-build
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: "3.8"
|
python-version: "3.8"
|
||||||
- name: Install Python dependencies
|
- name: Install Python dependencies
|
||||||
@ -74,17 +83,17 @@ jobs:
|
|||||||
pip install -U conan
|
pip install -U conan
|
||||||
- name: Configure Conan
|
- name: Configure Conan
|
||||||
run: |
|
run: |
|
||||||
conan config init
|
conan profile detect --force
|
||||||
conan remote add -i 0 upload https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
conan remote add artifactory https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||||
- name: Install Conan dependencies
|
- name: Install Conan dependencies
|
||||||
run: |
|
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
|
- name: Configure CMake
|
||||||
run: |
|
run: |
|
||||||
cmake --preset default
|
cmake --preset conan-default
|
||||||
- name: Generate documentation
|
- name: Generate documentation
|
||||||
run: |
|
run: |
|
||||||
cmake --build --preset release --target documentation
|
cmake --build --preset conan-release --target documentation
|
||||||
- name: Deploy documentation
|
- name: Deploy documentation
|
||||||
if: github.ref == 'refs/heads/master'
|
if: github.ref == 'refs/heads/master'
|
||||||
uses: peaceiris/actions-gh-pages@v3
|
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
|
# Add clang-12 and clang-15 apt repositories
|
||||||
RUN lsb_rel=`lsb_release -cs` \
|
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}-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"
|
&& 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
|
# Install older compilers supported by the project as well as clang-format-15 for code formatting
|
||||||
RUN sudo install-packages \
|
RUN sudo install-packages \
|
||||||
g++-10 \
|
g++-10 \
|
||||||
clang-12 \
|
g++-11 \
|
||||||
clang-13 \
|
clang-13 \
|
||||||
clang-format-15
|
clang-14
|
||||||
|
122
.gitpod.yml
122
.gitpod.yml
@ -36,8 +36,7 @@ vscode:
|
|||||||
- vivaxy.vscode-conventional-commits
|
- vivaxy.vscode-conventional-commits
|
||||||
- hbenl.vscode-test-explorer
|
- hbenl.vscode-test-explorer
|
||||||
- matepek.vscode-catch2-test-adapter
|
- matepek.vscode-catch2-test-adapter
|
||||||
- trond-snekvik.simple-rst
|
- redhat.vscode-yaml
|
||||||
- lextudio.restructuredtext
|
|
||||||
- ritwickdey.liveserver
|
- ritwickdey.liveserver
|
||||||
- ms-python.python
|
- ms-python.python
|
||||||
|
|
||||||
@ -49,24 +48,28 @@ tasks:
|
|||||||
mkdir -p "$PWD/.vscode";
|
mkdir -p "$PWD/.vscode";
|
||||||
cat << 'EOF' > "$PWD/.vscode/settings.json"
|
cat << 'EOF' > "$PWD/.vscode/settings.json"
|
||||||
{
|
{
|
||||||
"cmake.buildDirectory": "${workspaceFolder}/build/${buildKitVendor}-${buildKitVersionMajor}",
|
|
||||||
"cmake.configureArgs": [
|
|
||||||
"--toolchain conan_toolchain.cmake"
|
|
||||||
],
|
|
||||||
"cmake.generator": "Ninja Multi-Config",
|
"cmake.generator": "Ninja Multi-Config",
|
||||||
"cmake.configureOnOpen": true,
|
"cmake.configureOnOpen": true,
|
||||||
"clang-format.executable": "/usr/bin/clang-format-15",
|
"clang-format.executable": "/usr/bin/clang-format-15",
|
||||||
"editor.tabSize": 2,
|
"editor.tabSize": 2,
|
||||||
"editor.formatOnPaste": true,
|
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.formatOnType": true,
|
|
||||||
"editor.bracketPairColorization.enabled": true,
|
"editor.bracketPairColorization.enabled": true,
|
||||||
"editor.guides.bracketPairs": "active",
|
"editor.guides.bracketPairs": "active",
|
||||||
"restructuredtext.preview.scrollEditorWithPreview": false,
|
"restructuredtext.preview.scrollEditorWithPreview": false,
|
||||||
"restructuredtext.preview.scrollPreviewWithEditor": false,
|
"restructuredtext.preview.scrollPreviewWithEditor": false,
|
||||||
"liveServer.settings.root": "/build/docs/docs/sphinx/",
|
"liveServer.settings.root": "/build/docs/docs/sphinx/",
|
||||||
"esbonio.sphinx.confDir": "${workspaceFolder}/docs",
|
"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
|
EOF
|
||||||
@ -77,96 +80,103 @@ tasks:
|
|||||||
conan config init
|
conan config init
|
||||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||||
conan profile update settings.compiler.cppstd=20 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
|
conan remote add -i 0 conan-mpusz https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||||
pushd /workspace/.conan/profiles
|
pushd /workspace/.conan/profiles
|
||||||
cp default gcc10
|
cp default gcc10
|
||||||
cp default gcc11
|
cp default gcc11
|
||||||
cp default clang12
|
cp default gcc12
|
||||||
cp default clang13
|
cp default clang13
|
||||||
cp default clang14
|
cp default clang14
|
||||||
|
cp default clang15
|
||||||
popd
|
popd
|
||||||
conan profile update settings.compiler.version=10 gcc10
|
conan profile update settings.compiler.version=10 gcc10
|
||||||
conan profile update env.CXX=/usr/bin/g++-10 gcc10
|
conan profile update 'conf.tools.build.compiler_executables={"c": "gcc-10", "cpp": "g++-10"}' gcc10
|
||||||
conan profile update env.CC=/usr/bin/gcc-10 gcc10
|
conan profile update settings.compiler.version=11 gcc11
|
||||||
conan profile update settings.compiler=clang clang12
|
conan profile update 'conf.tools.build.compiler_executables={"c": "gcc-11", "cpp": "g++-11"}' gcc11
|
||||||
conan profile update settings.compiler.version=12 clang12
|
conan profile update settings.compiler.version=11 gcc12
|
||||||
conan profile update settings.compiler.libcxx=libstdc++11 clang12
|
conan profile update 'conf.tools.build.compiler_executables={"c": "gcc-12", "cpp": "g++-12"}' gcc12
|
||||||
conan profile update env.CXX=/usr/bin/clang++-12 clang12
|
|
||||||
conan profile update env.CC=/usr/bin/clang-12 clang12
|
|
||||||
conan profile update settings.compiler=clang clang13
|
conan profile update settings.compiler=clang clang13
|
||||||
conan profile update settings.compiler.version=13 clang13
|
conan profile update settings.compiler.version=13 clang13
|
||||||
conan profile update settings.compiler.libcxx=libstdc++11 clang13
|
conan profile update settings.compiler.libcxx=libstdc++11 clang13
|
||||||
conan profile update env.CXX=/usr/bin/clang++-13 clang13
|
conan profile update 'conf.tools.build.compiler_executables={"c": "clang-13", "cpp": "clang++-13"}' clang13
|
||||||
conan profile update env.CC=/usr/bin/clang-13 clang13
|
|
||||||
conan profile update settings.compiler=clang clang14
|
conan profile update settings.compiler=clang clang14
|
||||||
conan profile update settings.compiler.version=14 clang14
|
conan profile update settings.compiler.version=14 clang14
|
||||||
conan profile update settings.compiler.libcxx=libc++ clang14
|
conan profile update settings.compiler.libcxx=libstdc++11 clang14
|
||||||
conan profile update env.CXX=/usr/bin/clang++-14 clang14
|
conan profile update 'conf.tools.build.compiler_executables={"c": "clang-14", "cpp": "clang++-14"}' clang14
|
||||||
conan profile update env.CC=/usr/bin/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
|
gp sync-done conan-init
|
||||||
exit
|
exit
|
||||||
- name: gcc-10
|
- name: gcc-10
|
||||||
init: |
|
init: |
|
||||||
gp sync-await conan-init
|
gp sync-await conan-init
|
||||||
mkdir -p build/GCC-10 && cd build/GCC-10
|
conan install . -pr gcc10 -c user.build:all=True -c user.build:skip_docs=True -b outdated
|
||||||
conan install ../.. -pr gcc10 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated
|
conan install . -pr gcc10 -c user.build:all=True -c user.build:skip_docs=True -b outdated -s build_type=Debug
|
||||||
conan install ../.. -pr gcc10 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated -s build_type=Debug
|
cmake --preset gcc-10
|
||||||
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 --preset gcc-10-release -j
|
||||||
cmake --build . --config Release -j
|
cmake --build --preset gcc-10-debug -j
|
||||||
cmake --build . --config Debug -j
|
|
||||||
ctest -C Release
|
ctest -C Release
|
||||||
ctest -C Debug
|
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. 🛠️"
|
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
|
- name: gcc-11
|
||||||
init: |
|
init: |
|
||||||
gp sync-await conan-init
|
gp sync-await conan-init
|
||||||
mkdir -p build/GCC-11 && cd build/GCC-11
|
conan install . -pr gcc11 -c user.build:all=True -c user.build:skip_docs=True -b outdated
|
||||||
conan install ../.. -pr gcc11 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated
|
conan install . -pr gcc11 -c user.build:all=True -c user.build:skip_docs=True -b outdated -s build_type=Debug
|
||||||
gp sync-done conan-gcc-install
|
cmake --preset gcc-11
|
||||||
conan install ../.. -pr gcc11 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated -s build_type=Debug
|
cmake --build --preset gcc-11-release -j
|
||||||
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 --preset gcc-11-debug -j
|
||||||
cmake --build . --config Release -j
|
|
||||||
cmake --build . --config Debug -j
|
|
||||||
ctest -C Release
|
ctest -C Release
|
||||||
ctest -C Debug
|
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. 🛠️"
|
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: |
|
init: |
|
||||||
gp sync-await conan-init
|
gp sync-await conan-init
|
||||||
mkdir -p build/Clang-12 && cd build/Clang-12
|
conan install . -pr gcc12 -c user.build:all=True -c user.build:skip_docs=True -b outdated
|
||||||
conan install ../.. -pr clang12 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated
|
conan install . -pr gcc12 -c user.build:all=True -c user.build:skip_docs=True -b outdated -s build_type=Debug
|
||||||
conan install ../.. -pr clang12 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated -s build_type=Debug
|
cmake --preset gcc-12
|
||||||
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 --preset gcc-12-release -j
|
||||||
cmake --build . --config Release -j
|
cmake --build --preset gcc-12-debug -j
|
||||||
cmake --build . --config Debug -j
|
|
||||||
ctest -C Release
|
ctest -C Release
|
||||||
ctest -C Debug
|
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
|
- name: clang-13
|
||||||
init: |
|
init: |
|
||||||
gp sync-await conan-init
|
gp sync-await conan-init
|
||||||
mkdir -p build/Clang-13 && cd build/Clang-13
|
conan install . -pr clang13 -c user.build:all=True -c user.build:skip_docs=True -b outdated
|
||||||
conan install ../.. -pr clang13 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated
|
conan install . -pr clang13 -c user.build:all=True -c user.build:skip_docs=True -b outdated -s build_type=Debug
|
||||||
conan install ../.. -pr clang13 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated -s build_type=Debug
|
cmake --preset clang-13
|
||||||
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 --preset clang-13-release -j
|
||||||
cmake --build . --config Release -j
|
cmake --build --preset clang-13-debug -j
|
||||||
cmake --build . --config Debug -j
|
|
||||||
ctest -C Release
|
ctest -C Release
|
||||||
ctest -C Debug
|
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. 🛠️"
|
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
|
- name: clang-14
|
||||||
init: |
|
init: |
|
||||||
gp sync-await conan-init
|
gp sync-await conan-init
|
||||||
mkdir -p build/Clang-14 && cd build/Clang-14
|
conan install . -pr clang14 -c user.build:all=True -c user.build:skip_docs=True -b outdated
|
||||||
conan install ../.. -pr clang4 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated
|
conan install . -pr clang14 -c user.build:all=True -c user.build:skip_docs=True -b outdated -s build_type=Debug
|
||||||
conan install ../.. -pr clang14 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated -s build_type=Debug
|
cmake --preset clang-14
|
||||||
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 --preset clang-14-release -j
|
||||||
cmake --build . --config Release -j
|
cmake --build --preset clang-14-debug -j
|
||||||
cmake --build . --config Debug -j
|
|
||||||
ctest -C Release
|
ctest -C Release
|
||||||
ctest -C Debug
|
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. 🛠️"
|
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
|
- name: documentation
|
||||||
init: |
|
init: |
|
||||||
gp sync-await conan-init
|
gp sync-await conan-init
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
default_stages: [commit]
|
default_stages: [commit]
|
||||||
|
|
||||||
repos:
|
repos:
|
||||||
|
- repo: meta
|
||||||
|
hooks:
|
||||||
|
- id: check-hooks-apply
|
||||||
|
- id: check-useless-excludes
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.2.0
|
rev: v4.3.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
# - repo: https://github.com/pocc/pre-commit-hooks
|
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||||
# rev: v1.3.5
|
rev: v16.0.0
|
||||||
# hooks:
|
hooks:
|
||||||
# - id: clang-format
|
- id: clang-format
|
||||||
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
||||||
rev: v0.6.13
|
rev: v0.6.13
|
||||||
hooks:
|
hooks:
|
||||||
@ -19,16 +23,16 @@ repos:
|
|||||||
# additional_dependencies: ["cmakelang"]
|
# additional_dependencies: ["cmakelang"]
|
||||||
# exclude: "cmake/.*"
|
# exclude: "cmake/.*"
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 22.3.0
|
rev: 22.10.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
language_version: python3
|
language_version: python3
|
||||||
- repo: https://github.com/PyCQA/isort
|
- repo: https://github.com/PyCQA/isort
|
||||||
rev: 5.10.1
|
rev: 5.12.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: isort
|
- id: isort
|
||||||
args: [--profile, black, --multi-line, "3"]
|
args: [--profile, black, --multi-line, "3"]
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 4.0.1
|
rev: 5.0.4
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
|
@ -27,6 +27,8 @@ authors:
|
|||||||
orcid: https://orcid.org/0000-0003-0680-0765
|
orcid: https://orcid.org/0000-0003-0680-0765
|
||||||
- given-names: "Johel Ernesto"
|
- given-names: "Johel Ernesto"
|
||||||
family-names: "Guerrero Peña"
|
family-names: "Guerrero Peña"
|
||||||
|
- given-names: "Chip"
|
||||||
|
family-names: "Hogg"
|
||||||
- name: "The mp-units project team"
|
- name: "The mp-units project team"
|
||||||
|
|
||||||
contact:
|
contact:
|
||||||
@ -34,9 +36,9 @@ contact:
|
|||||||
given-names: Mateusz
|
given-names: Mateusz
|
||||||
family-names: Pusz
|
family-names: Pusz
|
||||||
|
|
||||||
repository-code: 'https://github.com/mpusz/units'
|
repository-code: "https://github.com/mpusz/units"
|
||||||
url: 'https://mpusz.github.io/units'
|
url: "https://mpusz.github.io/units"
|
||||||
repository-artifact: 'https://conan.io/center/mp-units'
|
repository-artifact: "https://conan.io/center/mp-units"
|
||||||
|
|
||||||
version: 0.7.0
|
version: 0.7.0
|
||||||
date-released: "2021-05-11"
|
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:
|
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 Conan dependencies preinstalled on the machine
|
||||||
- all documentation generation tools ready to use
|
- all documentation generation tools ready to use
|
||||||
- completed prebuilds for all targets (each compiler as well as a documentation)
|
- completed prebuilds for all targets (Debug and Release builds for each compiler as well as a documentation)
|
||||||
- `clang-format-15` for source code formatting
|
|
||||||
- VSCode preconfigured to benefit from all the above
|
- VSCode preconfigured to benefit from all the above
|
||||||
|
|
||||||
## Download, Build, Install
|
## 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)
|
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.
|
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
|
## Naming Conventions
|
||||||
|
|
||||||
@ -40,18 +46,6 @@ Here are the main rules for naming things in this repo:
|
|||||||
- template parameters in a `PascalCase`
|
- 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)
|
- 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
|
## 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.
|
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
|
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).
|
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)
|
[](./LICENSE.md)
|
||||||
[](https://github.com/mpusz/units/actions?query=workflow%3A%22Conan%20CI%22+branch%3Amaster)
|
[](https://en.cppreference.com/w/cpp/compiler_support#cpp20)
|
||||||
[](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%3A%22Conan%20CI%22+branch%3Amaster)
|
||||||
[](https://github.com/mpusz/units/actions?query=workflow%3ADocumentation+branch%3Amaster)
|
[](https://github.com/mpusz/units/actions?query=workflow%3A%22CMake+Test+Package+CI%22+branch%3Amaster)
|
||||||
[](https://conan.io/center/mp-units)
|
[](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)
|
[](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units/0.8.0)
|
||||||
|
|
||||||
|
|
||||||
# `mp-units` - A Units Library for C++
|
# `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
|
**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).
|
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
|
## TL;DR
|
||||||
|
|
||||||
`mp-units` is a compile-time enabled Modern C++ library that provides compile-time dimensional
|
`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);
|
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
|
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
|
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
|
import re
|
||||||
|
|
||||||
from conan import ConanFile
|
from conan import ConanFile
|
||||||
|
from conan.errors import ConanInvalidConfiguration
|
||||||
from conan.tools.build import check_min_cppstd
|
from conan.tools.build import check_min_cppstd
|
||||||
from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
|
from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
|
||||||
from conan.tools.files import copy, load, rmdir
|
from conan.tools.files import copy, load, rmdir
|
||||||
from conan.tools.scm import Version
|
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):
|
class MPUnitsConan(ConanFile):
|
||||||
name = "mp-units"
|
name = "mp-units"
|
||||||
homepage = "https://github.com/mpusz/units"
|
homepage = "https://github.com/mpusz/units"
|
||||||
description = "Physical Units library for C++"
|
description = "Physical Quantities and Units library for C++"
|
||||||
topics = (
|
topics = (
|
||||||
"units",
|
"units",
|
||||||
"dimensions",
|
"dimensions",
|
||||||
@ -45,15 +45,15 @@ class MPUnitsConan(ConanFile):
|
|||||||
"physical-quantities",
|
"physical-quantities",
|
||||||
"physical-units",
|
"physical-units",
|
||||||
"system-of-units",
|
"system-of-units",
|
||||||
"cpp23",
|
"system-of-quantities",
|
||||||
"cpp20",
|
"isq",
|
||||||
|
"si",
|
||||||
"library",
|
"library",
|
||||||
"quantity-manipulation",
|
"quantity-manipulation",
|
||||||
)
|
)
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
url = "https://github.com/mpusz/units"
|
url = "https://github.com/mpusz/units"
|
||||||
settings = "os", "compiler", "build_type", "arch"
|
settings = "os", "arch", "compiler", "build_type"
|
||||||
requires = "gsl-lite/0.40.0"
|
|
||||||
exports = ["LICENSE.md"]
|
exports = ["LICENSE.md"]
|
||||||
exports_sources = [
|
exports_sources = [
|
||||||
"docs/*",
|
"docs/*",
|
||||||
@ -63,24 +63,34 @@ class MPUnitsConan(ConanFile):
|
|||||||
"example/*",
|
"example/*",
|
||||||
"CMakeLists.txt",
|
"CMakeLists.txt",
|
||||||
]
|
]
|
||||||
|
package_type = "header-library"
|
||||||
no_copy_source = True
|
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
|
@property
|
||||||
def _build_all(self):
|
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
|
@property
|
||||||
def _skip_docs(self):
|
def _skip_docs(self):
|
||||||
return bool(self.conf["user.build:skip_docs"])
|
return bool(self.conf.get("user.build:skip_docs", default=True))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _use_libfmt(self):
|
def _use_libfmt(self):
|
||||||
compiler = self.settings.compiler
|
compiler = self.settings.compiler
|
||||||
version = Version(self.settings.compiler.version)
|
version = Version(self.settings.compiler.version)
|
||||||
std_support = (
|
std_support = compiler == "msvc" and version >= 193 and compiler.cppstd == 23
|
||||||
compiler == "Visual Studio" and version >= 17 and compiler.cppstd == 23
|
|
||||||
) or (compiler == "msvc" and version >= 193 and compiler.cppstd == 23)
|
|
||||||
return not std_support
|
return not std_support
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -89,14 +99,6 @@ class MPUnitsConan(ConanFile):
|
|||||||
version = Version(self.settings.compiler.version)
|
version = Version(self.settings.compiler.version)
|
||||||
return "clang" in compiler and compiler.libcxx == "libc++" and version < 14
|
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):
|
def set_version(self):
|
||||||
content = load(self, os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
|
content = load(self, os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
|
||||||
version = re.search(
|
version = re.search(
|
||||||
@ -105,51 +107,42 @@ class MPUnitsConan(ConanFile):
|
|||||||
self.version = version.strip()
|
self.version = version.strip()
|
||||||
|
|
||||||
def requirements(self):
|
def requirements(self):
|
||||||
|
self.requires("gsl-lite/0.40.0")
|
||||||
if self._use_libfmt:
|
if self._use_libfmt:
|
||||||
self.requires("fmt/8.1.1")
|
self.requires("fmt/8.1.1")
|
||||||
|
|
||||||
if self._use_range_v3:
|
if self._use_range_v3:
|
||||||
self.requires("range-v3/0.11.0")
|
self.requires("range-v3/0.11.0")
|
||||||
|
|
||||||
def build_requirements(self):
|
def build_requirements(self):
|
||||||
if self._build_all:
|
if self._build_all:
|
||||||
self.test_requires("catch2/3.1.0")
|
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:
|
if not self._skip_docs:
|
||||||
self.tool_requires("doxygen/1.9.4")
|
self.tool_requires("doxygen/1.9.4")
|
||||||
|
|
||||||
# TODO Replace with `valdate()` for Conan 2.0 (https://github.com/conan-io/conan/issues/10723)
|
def validate(self):
|
||||||
def configure(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
|
compiler = self.settings.compiler
|
||||||
version = Version(self.settings.compiler.version)
|
min_version = self._minimum_compilers_version.get(str(compiler))
|
||||||
if compiler == "gcc":
|
if min_version and loose_lt_semver(str(compiler.version), min_version):
|
||||||
if version < 10:
|
raise ConanInvalidConfiguration(
|
||||||
raise ConanInvalidConfiguration("mp-units requires at least g++-10")
|
f"{self.ref} requires at least {compiler} {min_version} ({compiler.version} in use)"
|
||||||
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)
|
|
||||||
|
|
||||||
def layout(self):
|
def layout(self):
|
||||||
cmake_layout(self)
|
cmake_layout(self)
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
tc = CMakeToolchain(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_BUILD_DOCS"] = self._build_all and not self._skip_docs
|
||||||
tc.variables["UNITS_USE_LIBFMT"] = self._use_libfmt
|
tc.variables["UNITS_USE_LIBFMT"] = self._use_libfmt
|
||||||
tc.generate()
|
tc.generate()
|
||||||
@ -182,7 +175,7 @@ class MPUnitsConan(ConanFile):
|
|||||||
|
|
||||||
# core
|
# core
|
||||||
self.cpp_info.components["core"].requires = ["gsl-lite::gsl-lite"]
|
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"]
|
self.cpp_info.components["core"].cxxflags = ["/utf-8"]
|
||||||
if self._use_range_v3:
|
if self._use_range_v3:
|
||||||
self.cpp_info.components["core"].requires.append("range-v3::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"]
|
self.cpp_info.components["core-fmt"].requires = ["core"]
|
||||||
if self._use_libfmt:
|
if self._use_libfmt:
|
||||||
self.cpp_info.components["core-fmt"].requires.append("fmt::fmt")
|
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"].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"].requires = ["isq"]
|
||||||
self.cpp_info.components["si-cgs"].requires = ["si"]
|
self.cpp_info.components["cgs"].requires = ["si"]
|
||||||
self.cpp_info.components["si-fps"].requires = ["si-international"]
|
self.cpp_info.components["hep"].requires = ["si"]
|
||||||
self.cpp_info.components["si-hep"].requires = ["si"]
|
self.cpp_info.components["iau"].requires = ["si"]
|
||||||
self.cpp_info.components["si-iau"].requires = ["si"]
|
self.cpp_info.components["imperial"].requires = ["si"]
|
||||||
self.cpp_info.components["si-imperial"].requires = ["si"]
|
self.cpp_info.components["international"].requires = ["si"]
|
||||||
self.cpp_info.components["si-international"].requires = ["si"]
|
self.cpp_info.components["typographic"].requires = ["usc"]
|
||||||
self.cpp_info.components["si-typographic"].requires = ["si"]
|
self.cpp_info.components["usc"].requires = ["international"]
|
||||||
self.cpp_info.components["si-uscs"].requires = ["si"]
|
self.cpp_info.components["iec80000"].requires = ["isq", "si"]
|
||||||
self.cpp_info.components["isq-iec80000"].requires = ["si"]
|
|
||||||
self.cpp_info.components["systems"].requires = [
|
self.cpp_info.components["systems"].requires = [
|
||||||
"isq",
|
"isq",
|
||||||
"isq-natural",
|
"angular",
|
||||||
|
"isq_angular",
|
||||||
|
"natural",
|
||||||
"si",
|
"si",
|
||||||
"si-cgs",
|
"cgs",
|
||||||
"si-fps",
|
"hep",
|
||||||
"si-hep",
|
"iau",
|
||||||
"si-iau",
|
"imperial",
|
||||||
"si-imperial",
|
"international",
|
||||||
"si-international",
|
"typographic",
|
||||||
"si-typographic",
|
"usc",
|
||||||
"si-uscs",
|
"iec80000",
|
||||||
"isq-iec80000",
|
|
||||||
]
|
]
|
||||||
|
@ -46,6 +46,10 @@ set(unitsSphinxDocs
|
|||||||
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/units.svg"
|
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/units.svg"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/quantity_like.svg"
|
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/quantity_like.svg"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG.md"
|
"${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.rst"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/design/directories.rst"
|
"${CMAKE_CURRENT_SOURCE_DIR}/design/directories.rst"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/design/downcasting.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}/examples/kalman_filter/kalman.rst"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/faq.rst"
|
"${CMAKE_CURRENT_SOURCE_DIR}/faq.rst"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework.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/arithmetics.rst"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/basic_concepts.rst"
|
"${CMAKE_CURRENT_SOURCE_DIR}/framework/basic_concepts.rst"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/constants.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.
|
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
|
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/arithmetics
|
||||||
framework/constants
|
framework/constants
|
||||||
framework/conversions_and_casting
|
framework/conversions_and_casting
|
||||||
framework/angular_units
|
|
||||||
framework/text_output
|
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. This means that they are created by multiplying or dividing
|
||||||
quantities of other dimensions.
|
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
|
Looking at the previous code snippets the area, speed, or frequency are
|
||||||
the examples of such quantities. Each derived quantity can be represented
|
the examples of such quantities. Each derived quantity can be represented
|
||||||
as a unique list of exponents of base quantities. For example:
|
as a unique list of exponents of base quantities. For example:
|
||||||
|
@ -313,7 +313,7 @@ Quantity References vs Unit-specific Aliases
|
|||||||
- Unit-specific Aliases
|
- Unit-specific Aliases
|
||||||
|
|
||||||
As aliases are defined in terms of types rather variables no major shadowing issues were found
|
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.
|
namespaces prefixed in front of the alias.
|
||||||
|
|
||||||
2. Adjustable verbosity
|
2. Adjustable verbosity
|
||||||
@ -385,7 +385,7 @@ Quantity References vs Unit-specific Aliases
|
|||||||
- Quantity References
|
- Quantity References
|
||||||
|
|
||||||
The syntax for references uses ``*`` operator which has some predefined precedence. This operator
|
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
|
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::
|
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
|
- 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
|
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
|
can be constructed using the provided ones already even if they do not correspond to any predefined
|
||||||
dimension::
|
dimension::
|
||||||
|
@ -49,4 +49,4 @@ Unlike `quantity`, the library provides:
|
|||||||
- no dimension-specific concepts, such as ``LengthPoint``
|
- no dimension-specific concepts, such as ``LengthPoint``
|
||||||
(there's the dimension-agnostic `QuantityPoint`),
|
(there's the dimension-agnostic `QuantityPoint`),
|
||||||
- a more limited set of operations on quantity points
|
- 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 {
|
namespace si {
|
||||||
|
|
||||||
struct yocto : prefix<yocto, "y", pow<-24>(mag<10>())> {};
|
struct yocto : prefix<yocto, "y", mag_power<10, -24>()> {};
|
||||||
struct zepto : prefix<zepto, "z", pow<-21>(mag<10>())> {};
|
struct zepto : prefix<zepto, "z", mag_power<10, -21>()> {};
|
||||||
struct atto : prefix<atto, "a", pow<-18>(mag<10>())> {};
|
struct atto : prefix<atto, "a", mag_power<10, -18>()> {};
|
||||||
struct femto : prefix<femto, "f", pow<-15>(mag<10>())> {};
|
struct femto : prefix<femto, "f", mag_power<10, -15>()> {};
|
||||||
struct pico : prefix<pico, "p", pow<-12>(mag<10>())> {};
|
struct pico : prefix<pico, "p", mag_power<10, -12>()> {};
|
||||||
struct nano : prefix<nano, "n", pow<-9>(mag<10>())> {};
|
struct nano : prefix<nano, "n", mag_power<10, -9>()> {};
|
||||||
struct micro : prefix<micro, basic_symbol_text{"\u00b5", "u"},
|
struct micro : prefix<micro, basic_symbol_text{"\u00b5", "u"},
|
||||||
pow<-6>(mag<10>())> {};
|
mag_power<10, -6>()> {};
|
||||||
struct milli : prefix<milli, "m", pow<-3>(mag<10>())> {};
|
struct milli : prefix<milli, "m", mag_power<10, -3>()> {};
|
||||||
struct centi : prefix<centi, "c", pow<-2>(mag<10>())> {};
|
struct centi : prefix<centi, "c", mag_power<10, -2>()> {};
|
||||||
struct deci : prefix<deci, "d", pow<-1>(mag<10>())> {};
|
struct deci : prefix<deci, "d", mag_power<10, -1>()> {};
|
||||||
struct deca : prefix<deca, "da", pow<1>(mag<10>())> {};
|
struct deca : prefix<deca, "da", mag_power<10, 1>()> {};
|
||||||
struct hecto : prefix<hecto, "h", pow<2>(mag<10>())> {};
|
struct hecto : prefix<hecto, "h", mag_power<10, 2>()> {};
|
||||||
struct kilo : prefix<kilo, "k", pow<3>(mag<10>())> {};
|
struct kilo : prefix<kilo, "k", mag_power<10, 3>()> {};
|
||||||
struct mega : prefix<mega, "M", pow<6>(mag<10>())> {};
|
struct mega : prefix<mega, "M", mag_power<10, 6>()> {};
|
||||||
struct giga : prefix<giga, "G", pow<9>(mag<10>())> {};
|
struct giga : prefix<giga, "G", mag_power<10, 9>()> {};
|
||||||
struct tera : prefix<tera, "T", pow<12>(mag<10>())> {};
|
struct tera : prefix<tera, "T", mag_power<10, 12>()> {};
|
||||||
struct peta : prefix<peta, "P", pow<15>(mag<10>())> {};
|
struct peta : prefix<peta, "P", mag_power<10, 15>()> {};
|
||||||
struct exa : prefix<exa, "E", pow<18>(mag<10>())> {};
|
struct exa : prefix<exa, "E", mag_power<10, 18>()> {};
|
||||||
struct zetta : prefix<zetta, "Z", pow<21>(mag<10>())> {};
|
struct zetta : prefix<zetta, "Z", mag_power<10, 21>()> {};
|
||||||
struct yotta : prefix<yotta, "Y", pow<24>(mag<10>())> {};
|
struct yotta : prefix<yotta, "Y", mag_power<10, 24>()> {};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,14 +232,14 @@ domain::
|
|||||||
|
|
||||||
namespace iec80000 {
|
namespace iec80000 {
|
||||||
|
|
||||||
struct kibi : prefix<kibi, "Ki", pow<10>(mag<2>())> {};
|
struct kibi : prefix<kibi, "Ki", mag_power<2, 10>()> {};
|
||||||
struct mebi : prefix<mebi, "Mi", pow<20>(mag<2>())> {};
|
struct mebi : prefix<mebi, "Mi", mag_power<2, 20>()> {};
|
||||||
struct gibi : prefix<gibi, "Gi", pow<30>(mag<2>())> {};
|
struct gibi : prefix<gibi, "Gi", mag_power<2, 30>()> {};
|
||||||
struct tebi : prefix<tebi, "Ti", pow<40>(mag<2>())> {};
|
struct tebi : prefix<tebi, "Ti", mag_power<2, 40>()> {};
|
||||||
struct pebi : prefix<pebi, "Pi", pow<50>(mag<2>())> {};
|
struct pebi : prefix<pebi, "Pi", mag_power<2, 50>()> {};
|
||||||
struct exbi : prefix<exbi, "Ei", pow<60>(mag<2>())> {};
|
struct exbi : prefix<exbi, "Ei", mag_power<2, 60>()> {};
|
||||||
struct zebi : prefix<zebi, "Zi", pow<70>(mag<2>())> {};
|
struct zebi : prefix<zebi, "Zi", mag_power<2, 70>()> {};
|
||||||
struct yobi : prefix<yobi, "Yi", pow<80>(mag<2>())> {};
|
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).
|
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
|
Derived Units
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@ -268,10 +276,21 @@ Derived Units
|
|||||||
names (i.e. ``N`` (newton)) or can be composed from the names of units of quantities
|
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``).
|
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
|
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``
|
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
|
(pascal)) and they are defined in the same way as base units (which
|
||||||
always have to be a named unit)::
|
always have to be a named unit)::
|
||||||
|
@ -73,9 +73,9 @@ ISO 80000 [1]_ definitions
|
|||||||
tensor character.
|
tensor character.
|
||||||
- In a given `system of quantities`:
|
- In a given `system of quantities`:
|
||||||
|
|
||||||
- `quantities <quantity>` of the same `kind` have the same quantity dimension,
|
- `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>` 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>` having the same quantity dimension are not necessarily of the same `kind`.
|
||||||
|
|
||||||
quantity of dimension one
|
quantity of dimension one
|
||||||
dimensionless quantity
|
dimensionless quantity
|
||||||
@ -168,7 +168,15 @@ ISO 80000 [1]_ definitions
|
|||||||
value of a quantity
|
value of a quantity
|
||||||
value
|
value
|
||||||
- Number and reference together expressing magnitude of a `quantity`.
|
- 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.
|
- 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
|
Other definitions
|
||||||
|
@ -30,6 +30,7 @@ with a permissive `MIT license <https://github.com/mpusz/units/blob/master/LICEN
|
|||||||
introduction
|
introduction
|
||||||
quick_start
|
quick_start
|
||||||
framework
|
framework
|
||||||
|
defining_systems
|
||||||
use_cases
|
use_cases
|
||||||
design
|
design
|
||||||
examples
|
examples
|
||||||
|
@ -32,7 +32,7 @@ Here is a small example of possible operations::
|
|||||||
|
|
||||||
.. admonition:: Try it on Compiler Explorer
|
.. 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
|
This library requires some C++20 features (concepts, classes as
|
||||||
:abbr:`NTTP (Non-Type Template Parameter)`, ...). Thanks to them the user gets a powerful
|
: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
|
.. admonition:: Try it on Compiler Explorer
|
||||||
|
|
||||||
`Example #2 <https://godbolt.org/z/bcb87Kvea>`_
|
`Example #2 <https://godbolt.org/z/b4a3Ya6dY>`_
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Sotrage Capacity
|
Storage Capacity
|
||||||
================
|
================
|
||||||
|
|
||||||
.. doxygenfile:: iec80000/storage_capacity.h
|
.. 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
|
:maxdepth: 2
|
||||||
|
|
||||||
si/uscs/length
|
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.
|
.. [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::
|
.. 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
|
`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>`_.
|
<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:
|
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
|
Conan Configuration Properties
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
build_all
|
user.build:all
|
||||||
+++++++++
|
++++++++++++++
|
||||||
|
|
||||||
**Values**: ``True``/``False``
|
**Values**: ``True``/``False``
|
||||||
|
|
||||||
@ -158,14 +158,24 @@ To support this it requires some additional Conan build dependencies described i
|
|||||||
`Repository Structure and Dependencies`_.
|
`Repository Structure and Dependencies`_.
|
||||||
It also runs unit tests during Conan build (unless ``tools.build:skip_test`` configuration property is set to ``True``)
|
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``
|
**Values**: ``True``/``False``
|
||||||
|
|
||||||
**Defaulted to**: ``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.
|
turns on the project documentation generation. Such behavior can be disabled with this option.
|
||||||
|
|
||||||
CMake Options
|
CMake Options
|
||||||
@ -181,6 +191,16 @@ UNITS_AS_SYSTEM_HEADERS
|
|||||||
Exports library 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
|
UNITS_BUILD_DOCS
|
||||||
++++++++++++++++
|
++++++++++++++++
|
||||||
|
|
||||||
@ -387,8 +407,8 @@ differences:
|
|||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -b=outdated -u
|
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -b=outdated -u
|
||||||
cmake --preset default
|
cmake --preset conan-default
|
||||||
cmake --build --preset release
|
cmake --build --preset conan-release
|
||||||
|
|
||||||
|
|
||||||
Install
|
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
|
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing
|
||||||
mv CMakeUserPresets.json src
|
mv CMakeUserPresets.json src
|
||||||
cd src
|
cd src
|
||||||
cmake --preset default -DCMAKE_INSTALL_PREFIX=<your_installation_path>
|
cmake --preset conan-default -DCMAKE_INSTALL_PREFIX=<your_installation_path>
|
||||||
cmake --build --preset release --target install
|
cmake --build --preset conan-release --target install
|
||||||
|
|
||||||
|
|
||||||
Contributing (or just building all the tests and examples)
|
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:
|
you should:
|
||||||
|
|
||||||
1. Use the *CMakeLists.txt* from the top-level directory.
|
1. Use the *CMakeLists.txt* from the top-level directory.
|
||||||
2. Run Conan with `build_all`_ = ``True``
|
2. Run Conan with `user.build:all`_ = ``True``
|
||||||
(use ``-o build_docs=False`` if you want to skip the documentation generation).
|
(use ``-c user.build:skip_docs=True`` if you want to skip the documentation generation).
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
git clone https://github.com/mpusz/units.git && cd units
|
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 .
|
conan build .
|
||||||
|
|
||||||
The above will download and install all of the dependencies needed for the development of the library,
|
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
|
.. code-block:: shell
|
||||||
|
|
||||||
cmake --preset default
|
cmake --preset conan-default
|
||||||
cmake --build --preset release
|
cmake --build --preset conan-release
|
||||||
cmake --build --preset release --target test
|
cmake --build --preset conan-release --target test
|
||||||
|
|
||||||
|
|
||||||
Building documentation
|
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.
|
1. Use the *CMakeLists.txt* from the top-level directory.
|
||||||
2. Obtain Python dependencies.
|
2. Obtain Python dependencies.
|
||||||
3. Run Conan with `build_all`_ = ``True``.
|
3. Run Conan with `user.build:all`_ = ``True``.
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
git clone https://github.com/mpusz/units.git && cd units
|
git clone https://github.com/mpusz/units.git && cd units
|
||||||
pip3 install -r docs/requirements.txt
|
pip3 install -r docs/requirements.txt
|
||||||
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -c user.build:all=True -b missing
|
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -c user.build:all=True -b missing
|
||||||
cmake --preset default
|
cmake --preset conan-default
|
||||||
cmake --build --preset release --target documentation
|
cmake --build --preset conan-release --target documentation
|
||||||
|
|
||||||
The above will download and install all of the dependencies needed and build the 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
|
.. 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.
|
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>`_.
|
or `Conan <https://conan.io/center/wg21-linear_algebra>`_.
|
||||||
Also, to simplify the examples all of them assume::
|
Also, to simplify the examples all of them assume::
|
||||||
|
|
||||||
using namespace std::math;
|
using namespace STD_LA;
|
||||||
|
|
||||||
|
|
||||||
Linear Algebra of Quantities
|
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::
|
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 };
|
fixed_size_column_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 };
|
fixed_size_column_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::kilometre>, 3> t = { 3 * km, 2 * km, 1 * km };
|
||||||
|
|
||||||
Having such definitions we can perform full dimensional analysis operations for the operations
|
Having such definitions we can perform full dimensional analysis operations for the operations
|
||||||
allowed by the Linear Algebra rules. For example::
|
allowed by the Linear Algebra rules. For example::
|
||||||
|
|
||||||
std::cout << "v + u = " << v + u << "\n";
|
std::cout << "v + u = " << v + u << "\n";
|
||||||
std::cout << "v + t = " << v + t << "\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 << "v * u = " << v * u << "\n";
|
||||||
std::cout << "2 * m * v = " << 2 * m * v << "\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::
|
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, fixed_size_column_vector<int, 3>> v(fixed_size_column_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::metre, fixed_size_column_vector<int, 3>> u(fixed_size_column_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::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
|
Now the same code doing basic Linear Algebra operations will provide the following
|
||||||
output:
|
output:
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
Math
|
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(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)
|
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(glide_computer)
|
||||||
add_subdirectory(kalman_filter)
|
add_subdirectory(kalman_filter)
|
||||||
|
@ -113,7 +113,7 @@ void calcs_comparison()
|
|||||||
const auto L1A = 2.f * fm;
|
const auto L1A = 2.f * fm;
|
||||||
const auto L2A = 3.f * fm;
|
const auto L2A = 3.f * fm;
|
||||||
const auto LrA = L1A + L2A;
|
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"
|
std::cout << "The single unit method must convert large\n"
|
||||||
"or small values in other units to the base unit.\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 L1B = L1A[m];
|
||||||
const auto L2B = L2A[m];
|
const auto L2B = L2A[m];
|
||||||
const auto LrB = L1B + L2B;
|
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";
|
std::cout << "In multiplication and division:\n\n";
|
||||||
|
|
||||||
const quantity<isq::area[square<fm>], float> ArA = L1A * L2A;
|
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";
|
std::cout << "similar problems arise\n\n";
|
||||||
|
|
||||||
const quantity<isq::area[m2], float> ArB = L1B * L2B;
|
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
|
} // namespace
|
||||||
|
@ -48,13 +48,13 @@ int main()
|
|||||||
constexpr auto lengthA = 2.0 * m;
|
constexpr auto lengthA = 2.0 * m;
|
||||||
constexpr auto lengthB = lengthA[mm];
|
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";
|
<< "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,
|
std::cout << UNITS_STD_FMT::format("conversion factor from lengthA::unit of {:%q} to lengthB::unit of {:%q}:\n\n",
|
||||||
lengthB)
|
lengthA, lengthB)
|
||||||
<< STD_FMT::format("lengthB.number( {} ) == lengthA.number( {} ) * conversion_factor( {} )\n",
|
<< UNITS_STD_FMT::format("lengthB.number( {} ) == lengthA.number( {} ) * conversion_factor( {} )\n",
|
||||||
lengthB.number(), lengthA.number(), conversion_factor(lengthB, lengthA));
|
lengthB.number(), lengthA.number(), conversion_factor(lengthB, lengthA));
|
||||||
}
|
}
|
||||||
|
@ -52,24 +52,25 @@ struct Ship {
|
|||||||
template<Unit auto... Us, Quantity Q>
|
template<Unit auto... Us, Quantity Q>
|
||||||
auto fmt_line(const Q& 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
|
// 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)
|
void print_details(std::string_view description, const Ship& ship)
|
||||||
{
|
{
|
||||||
const auto waterDensity = 62.4 * isq::density[lb / cubic<ft>];
|
const auto waterDensity = 62.4 * isq::density[lb / cubic<ft>];
|
||||||
std::cout << STD_FMT::format("{}\n", description);
|
std::cout << UNITS_STD_FMT::format("{}\n", description);
|
||||||
std::cout << STD_FMT::format("{:20} : {}\n", "length", fmt_line<yd, m>(ship.length))
|
std::cout << UNITS_STD_FMT::format("{:20} : {}\n", "length", fmt_line<yd, m>(ship.length))
|
||||||
<< STD_FMT::format("{:20} : {}\n", "draft", fmt_line<yd, m>(ship.draft))
|
<< UNITS_STD_FMT::format("{:20} : {}\n", "draft", fmt_line<yd, m>(ship.draft))
|
||||||
<< STD_FMT::format("{:20} : {}\n", "beam", fmt_line<yd, m>(ship.beam))
|
<< UNITS_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))
|
<< UNITS_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))
|
<< UNITS_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))
|
<< UNITS_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))
|
<< UNITS_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))
|
<< UNITS_STD_FMT::format("{:20} : {}\n", "fire shells weighing",
|
||||||
<< STD_FMT::format("{:20} : {}\n", "fire shells at", fmt_line<mph, km / h>(ship.shellSpeed))
|
fmt_line<imperial::long_ton, kg>(ship.shellMass))
|
||||||
<< STD_FMT::format("{:20} : {}\n", "volume underwater", fmt_line<m3, l>(ship.mass / waterDensity));
|
<< 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()
|
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,
|
void print(std::string_view phase_name, timestamp start_ts, const glide_computer::flight_point& point,
|
||||||
const glide_computer::flight_point& new_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}) "
|
"| {:<12} | {:>9%.1Q %q} (Total: {:>9%.1Q %q}) | {:>8%.1Q %q} (Total: {:>8%.1Q %q}) | {:>7%.0Q %q} ({:>6%.0Q %q}) "
|
||||||
"|\n",
|
"|\n",
|
||||||
phase_name, value_cast<si::minute>(new_point.ts - point.ts), value_cast<si::minute>(new_point.ts - start_ts),
|
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,
|
void estimate(timestamp start_ts, const glider& g, const weather& w, const task& t, const safety& s,
|
||||||
const aircraft_tow& at)
|
const aircraft_tow& at)
|
||||||
{
|
{
|
||||||
std::cout << STD_FMT::format("| {:<12} | {:^28} | {:^26} | {:^21} |\n", "Flight phase", "Duration", "Distance",
|
std::cout << UNITS_STD_FMT::format("| {:<12} | {:^28} | {:^26} | {:^21} |\n", "Flight phase", "Duration", "Distance",
|
||||||
"Height");
|
"Height");
|
||||||
std::cout << STD_FMT::format("|{0:-^14}|{0:-^30}|{0:-^28}|{0:-^23}|\n", "");
|
std::cout << UNITS_STD_FMT::format("|{0:-^14}|{0:-^30}|{0:-^28}|{0:-^23}|\n", "");
|
||||||
|
|
||||||
// ready to takeoff
|
// ready to takeoff
|
||||||
flight_point pos = takeoff(start_ts, t);
|
flight_point pos = takeoff(start_ts, t);
|
||||||
|
@ -84,7 +84,7 @@ void print(const R& gliders)
|
|||||||
std::cout << "- Polar:\n";
|
std::cout << "- Polar:\n";
|
||||||
for (const auto& p : g.polar) {
|
for (const auto& p : g.polar) {
|
||||||
const auto ratio = value_cast<one>(glide_ratio(g.polar[0]));
|
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
|
// TODO is it possible to make ADL work below (we need another set of trig functions
|
||||||
// for strong angle in a different namespace)
|
// for strong angle in a different namespace)
|
||||||
value_cast<si::degree>(isq::asin(1 / ratio)));
|
value_cast<si::degree>(isq::asin(1 / ratio)));
|
||||||
@ -102,8 +102,8 @@ void print(const R& conditions)
|
|||||||
for (const auto& c : conditions) {
|
for (const auto& c : conditions) {
|
||||||
std::cout << "- " << c.first << "\n";
|
std::cout << "- " << c.first << "\n";
|
||||||
const auto& w = c.second;
|
const auto& w = c.second;
|
||||||
std::cout << " * Cloud base: " << STD_FMT::format("{:%.0Q %q}", w.cloud_base) << " AGL\n";
|
std::cout << " * Cloud base: " << UNITS_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 << " * Thermals strength: " << UNITS_STD_FMT::format("{:%.1Q %q}", w.thermal_strength) << "\n";
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,7 +115,7 @@ void print(const R& waypoints)
|
|||||||
std::cout << "Waypoints:\n";
|
std::cout << "Waypoints:\n";
|
||||||
std::cout << "==========\n";
|
std::cout << "==========\n";
|
||||||
for (const auto& w : waypoints)
|
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";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,12 +126,12 @@ void print(const task& t)
|
|||||||
|
|
||||||
std::cout << "- Start: " << t.get_start().name << "\n";
|
std::cout << "- Start: " << t.get_start().name << "\n";
|
||||||
std::cout << "- Finish: " << t.get_finish().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: "
|
std::cout << "- Legs: "
|
||||||
<< "\n";
|
<< "\n";
|
||||||
for (const auto& l : t.get_legs())
|
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";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ void print(const safety& s)
|
|||||||
{
|
{
|
||||||
std::cout << "Safety:\n";
|
std::cout << "Safety:\n";
|
||||||
std::cout << "=======\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";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,8 +148,8 @@ void print(const aircraft_tow& tow)
|
|||||||
std::cout << "Tow:\n";
|
std::cout << "Tow:\n";
|
||||||
std::cout << "====\n";
|
std::cout << "====\n";
|
||||||
std::cout << "- Type: aircraft\n";
|
std::cout << "- Type: aircraft\n";
|
||||||
std::cout << "- Height: " << STD_FMT::format("{:%.0Q %q}", tow.height_agl) << "\n";
|
std::cout << "- Height: " << UNITS_STD_FMT::format("{:%.0Q %q}", tow.height_agl) << "\n";
|
||||||
std::cout << "- Performance: " << STD_FMT::format("{:%.1Q %q}", tow.performance) << "\n";
|
std::cout << "- Performance: " << UNITS_STD_FMT::format("{:%.1Q %q}", tow.performance) << "\n";
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ void example()
|
|||||||
for (const auto& c : weather_conditions) {
|
for (const auto& c : weather_conditions) {
|
||||||
std::string txt = "Scenario: Glider = " + g.name + ", Weather = " + c.first;
|
std::string txt = "Scenario: Glider = " + g.name + ", Weather = " + c.first;
|
||||||
std::cout << txt << "\n";
|
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);
|
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 v6 = value_cast<m / s>(v4);
|
||||||
constexpr auto v7 = value_cast<int>(v6);
|
constexpr auto v7 = value_cast<int>(v6);
|
||||||
|
|
||||||
std::cout << v1 << '\n'; // 110 km/h
|
std::cout << v1 << '\n'; // 110 km/h
|
||||||
std::cout << v2 << '\n'; // 70 mi/h
|
std::cout << v2 << '\n'; // 70 mi/h
|
||||||
std::cout << STD_FMT::format("{}", v3) << '\n'; // 110 km/h
|
std::cout << UNITS_STD_FMT::format("{}", v3) << '\n'; // 110 km/h
|
||||||
std::cout << STD_FMT::format("{:*^14}", v4) << '\n'; // ***70 mi/h****
|
std::cout << UNITS_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 << UNITS_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 << UNITS_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 << 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
|
} // namespace geographic
|
||||||
|
|
||||||
template<>
|
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>
|
template<typename FormatContext>
|
||||||
auto format(const geographic::msl_altitude& a, FormatContext& ctx)
|
auto format(const geographic::msl_altitude& a, FormatContext& ctx)
|
||||||
{
|
{
|
||||||
formatter<geographic::msl_altitude::quantity_type>::format(a.absolute(), 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>
|
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>
|
template<typename FormatContext>
|
||||||
auto format(geographic::latitude<T> lat, FormatContext& ctx)
|
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);
|
return formatter<T>::format(lat > geographic::latitude<T>::zero() ? lat.number() : -lat.number(), ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
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>
|
template<typename FormatContext>
|
||||||
auto format(geographic::longitude<T> lon, FormatContext& ctx)
|
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);
|
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/bits/external/hacks.h>
|
||||||
#include <mp-units/customization_points.h>
|
#include <mp-units/customization_points.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <concepts>
|
||||||
#include <type_traits>
|
#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; };
|
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>);
|
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>> {
|
class ranged_representation : public validated_type<T, is_in_range_t<T, Min, Max>> {
|
||||||
public:
|
public:
|
||||||
using validated_type<T, is_in_range_t<T, Min, Max>>::validated_type;
|
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{}) {}
|
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>
|
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>)
|
constexpr explicit validated_type(const T& value) noexcept(std::is_nothrow_copy_constructible_v<T>)
|
||||||
requires std::copyable<T>
|
requires std::copyable<T>
|
||||||
: value_(value)
|
: value_(value)
|
||||||
{
|
{
|
||||||
gsl_Expects(validate(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>)
|
constexpr validated_type(const T& value, validated_tag) noexcept(std::is_nothrow_copy_constructible_v<T>)
|
||||||
requires std::copyable<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>)
|
constexpr explicit(false) operator T() const noexcept(std::is_nothrow_copy_constructible_v<T>)
|
||||||
requires std::copyable<T>
|
requires std::copyable<T>
|
||||||
{
|
{
|
||||||
return value_;
|
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 T& value() & noexcept = delete;
|
||||||
constexpr const T& value() const& noexcept { return value_; }
|
constexpr const T& value() const& noexcept { return value_; }
|
||||||
constexpr T&& value() && noexcept { return std::move(value_); }
|
constexpr T&& value() && noexcept { return std::move(value_); }
|
||||||
|
@ -79,13 +79,9 @@ public:
|
|||||||
uncertainty_type uncertainty;
|
uncertainty_type uncertainty;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if UNITS_COMP_CLANG <= 14
|
|
||||||
|
|
||||||
template<QuantityOrQuantityPoint QQP, mp_units::Quantity U>
|
template<QuantityOrQuantityPoint QQP, mp_units::Quantity U>
|
||||||
estimation(state<QQP>, U) -> estimation<QQP>;
|
estimation(state<QQP>, U) -> estimation<QQP>;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// kalman gain
|
// kalman gain
|
||||||
template<mp_units::Quantity Q>
|
template<mp_units::Quantity Q>
|
||||||
constexpr mp_units::quantity<mp_units::dimensionless[mp_units::one]> kalman_gain(Q estimate_uncertainty,
|
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
|
} // namespace kalman
|
||||||
|
|
||||||
template<typename... Qs>
|
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)
|
constexpr auto parse(format_parse_context& ctx)
|
||||||
{
|
{
|
||||||
mp_units::detail::dynamic_specs_handler handler(specs, 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);
|
auto to_value_buffer = std::back_inserter(value_buffer);
|
||||||
if (specs.precision != -1) {
|
if (specs.precision != -1) {
|
||||||
if constexpr (sizeof...(Qs) == 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)
|
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),
|
UNITS_STD_FMT::format_to(to_value_buffer, "{{ {1:%.{0}Q %q}, {2:%.{0}Q %q} }}", specs.precision,
|
||||||
kalman::get<1>(s));
|
kalman::get<0>(s), kalman::get<1>(s));
|
||||||
else
|
else
|
||||||
STD_FMT::format_to(to_value_buffer, "{{ {1:%.{0}Q %q}, {2:%.{0}Q %q}, {3:%.{0}Q %q} }}", specs.precision,
|
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));
|
kalman::get<0>(s), kalman::get<1>(s), kalman::get<2>(s));
|
||||||
} else {
|
} else {
|
||||||
if constexpr (sizeof...(Qs) == 1)
|
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)
|
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
|
else
|
||||||
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),
|
||||||
kalman::get<2>(s));
|
kalman::get<2>(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string global_format_buffer;
|
std::string global_format_buffer;
|
||||||
mp_units::detail::quantity_global_format_specs<char> global_specs = {specs.fill, specs.align, specs.width};
|
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);
|
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:
|
private:
|
||||||
mp_units::detail::dynamic_format_specs<char> specs;
|
mp_units::detail::dynamic_format_specs<char> specs;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Q>
|
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)
|
constexpr auto parse(format_parse_context& ctx)
|
||||||
{
|
{
|
||||||
mp_units::detail::dynamic_specs_handler handler(specs, 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;
|
std::string value_buffer;
|
||||||
auto to_value_buffer = std::back_inserter(value_buffer);
|
auto to_value_buffer = std::back_inserter(value_buffer);
|
||||||
if (specs.precision != -1) {
|
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 {
|
} 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;
|
std::string global_format_buffer;
|
||||||
mp_units::detail::quantity_global_format_specs<char> global_specs = {specs.fill, specs.align, specs.width};
|
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);
|
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:
|
private:
|
||||||
mp_units::detail::dynamic_format_specs<char> specs;
|
mp_units::detail::dynamic_format_specs<char> specs;
|
||||||
|
@ -33,15 +33,15 @@ using namespace mp_units;
|
|||||||
|
|
||||||
void print_header(const kalman::State auto& initial)
|
void print_header(const kalman::State auto& initial)
|
||||||
{
|
{
|
||||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
std::cout << UNITS_STD_FMT::format("Initial: {}\n", initial);
|
||||||
std::cout << STD_FMT::format("{:>2} | {:>9} | {:>8} | {:>14} | {:>14}\n", "N", "Gain", "Measured", "Curr. Estimate",
|
std::cout << UNITS_STD_FMT::format("{:>2} | {:>9} | {:>8} | {:>14} | {:>14}\n", "N", "Gain", "Measured",
|
||||||
"Next Estimate");
|
"Curr. Estimate", "Next Estimate");
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(auto iteration, QuantityOf<dimensionless> auto gain, Quantity auto measured,
|
void print(auto iteration, QuantityOf<dimensionless> auto gain, Quantity auto measured,
|
||||||
const kalman::State auto& current, const kalman::State auto& next)
|
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()
|
int main()
|
||||||
|
@ -37,13 +37,14 @@ using namespace mp_units;
|
|||||||
|
|
||||||
void print_header(const kalman::State auto& initial)
|
void print_header(const kalman::State auto& initial)
|
||||||
{
|
{
|
||||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
std::cout << UNITS_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("{:>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)
|
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()
|
int main()
|
||||||
|
@ -37,13 +37,14 @@ using namespace mp_units;
|
|||||||
|
|
||||||
void print_header(const kalman::State auto& initial)
|
void print_header(const kalman::State auto& initial)
|
||||||
{
|
{
|
||||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
std::cout << UNITS_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("{:>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)
|
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()
|
int main()
|
||||||
|
@ -37,13 +37,14 @@ using namespace mp_units;
|
|||||||
|
|
||||||
void print_header(const kalman::State auto& initial)
|
void print_header(const kalman::State auto& initial)
|
||||||
{
|
{
|
||||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
std::cout << UNITS_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("{:>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)
|
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()
|
int main()
|
||||||
|
@ -35,16 +35,16 @@ using namespace mp_units;
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
void print_header(kalman::estimation<Q> initial)
|
void print_header(kalman::estimation<Q> initial)
|
||||||
{
|
{
|
||||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
std::cout << UNITS_STD_FMT::format("Initial: {}\n", initial);
|
||||||
std::cout << STD_FMT::format("{:>2} | {:>5} | {:>8} | {:>16} | {:>16}\n", "N", "Gain", "Measured", "Curr. Estimate",
|
std::cout << UNITS_STD_FMT::format("{:>2} | {:>5} | {:>8} | {:>16} | {:>16}\n", "N", "Gain", "Measured",
|
||||||
"Next Estimate");
|
"Curr. Estimate", "Next Estimate");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Quantity Q, QuantityOf<dimensionless> K>
|
template<Quantity Q, QuantityOf<dimensionless> K>
|
||||||
void print(auto iteration, K gain, Q measured, kalman::estimation<Q> current, kalman::estimation<Q> next)
|
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,
|
std::cout << UNITS_STD_FMT::format("{:2} | {:5%.2Q} | {:8} | {:>16.2} | {:>16.2}\n", iteration, gain, measured,
|
||||||
next);
|
current, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
@ -36,16 +36,16 @@ using namespace mp_units;
|
|||||||
template<QuantityPoint QP>
|
template<QuantityPoint QP>
|
||||||
void print_header(kalman::estimation<QP> initial)
|
void print_header(kalman::estimation<QP> initial)
|
||||||
{
|
{
|
||||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
std::cout << UNITS_STD_FMT::format("Initial: {}\n", initial);
|
||||||
std::cout << STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>18} | {:>18}\n", "N", "Gain", "Measured", "Curr. Estimate",
|
std::cout << UNITS_STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>18} | {:>18}\n", "N", "Gain", "Measured",
|
||||||
"Next Estimate");
|
"Curr. Estimate", "Next Estimate");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityPoint QP, QuantityOf<dimensionless> K>
|
template<QuantityPoint QP, QuantityOf<dimensionless> K>
|
||||||
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
|
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,
|
std::cout << UNITS_STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain,
|
||||||
measured.relative(), current, next);
|
measured.relative(), current, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
@ -36,16 +36,16 @@ using namespace mp_units;
|
|||||||
template<QuantityPoint QP>
|
template<QuantityPoint QP>
|
||||||
void print_header(kalman::estimation<QP> initial)
|
void print_header(kalman::estimation<QP> initial)
|
||||||
{
|
{
|
||||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
std::cout << UNITS_STD_FMT::format("Initial: {}\n", initial);
|
||||||
std::cout << STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>18} | {:>18}\n", "N", "Gain", "Measured", "Curr. Estimate",
|
std::cout << UNITS_STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>18} | {:>18}\n", "N", "Gain", "Measured",
|
||||||
"Next Estimate");
|
"Curr. Estimate", "Next Estimate");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityPoint QP, QuantityOf<dimensionless> K>
|
template<QuantityPoint QP, QuantityOf<dimensionless> K>
|
||||||
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
|
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,
|
std::cout << UNITS_STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain,
|
||||||
measured.relative(), current, next);
|
measured.relative(), current, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
@ -36,16 +36,16 @@ using namespace mp_units;
|
|||||||
template<QuantityPoint QP>
|
template<QuantityPoint QP>
|
||||||
void print_header(kalman::estimation<QP> initial)
|
void print_header(kalman::estimation<QP> initial)
|
||||||
{
|
{
|
||||||
std::cout << STD_FMT::format("Initial: {}\n", initial);
|
std::cout << UNITS_STD_FMT::format("Initial: {}\n", initial);
|
||||||
std::cout << STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>16} | {:>16}\n", "N", "Gain", "Measured", "Curr. Estimate",
|
std::cout << UNITS_STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>16} | {:>16}\n", "N", "Gain", "Measured",
|
||||||
"Next Estimate");
|
"Curr. Estimate", "Next Estimate");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityPoint QP, QuantityOf<dimensionless> K>
|
template<QuantityPoint QP, QuantityOf<dimensionless> K>
|
||||||
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
|
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,
|
std::cout << UNITS_STD_FMT::format("{:2} | {:7%.3Q} | {:10%.3Q %q} | {:>16.2} | {:>16.2}\n", iteration, gain,
|
||||||
measured.relative(), current, next);
|
measured.relative(), current, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
@ -35,20 +35,20 @@ int main()
|
|||||||
using namespace mp_units::si::unit_symbols;
|
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 << "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,
|
||||||
(1. * si2019::hyperfine_structure_transition_frequency_of_cs)[Hz]);
|
(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]);
|
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]);
|
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]);
|
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]);
|
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]);
|
1. * si2019::avogadro_constant, (1. * si2019::avogadro_constant)[1 / mol]);
|
||||||
// TODO uncomment the below when ISQ is done
|
// 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]);
|
// si2019::luminous_efficacy(1.)[lm / W]);
|
||||||
}
|
}
|
||||||
|
@ -119,10 +119,10 @@ int main()
|
|||||||
|
|
||||||
const auto fill_ratio = fill_level / height;
|
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 << UNITS_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 << UNITS_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 << UNITS_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 << UNITS_STD_FMT::format("input flow rate = {}\n", input_flow_rate);
|
||||||
std::cout << STD_FMT::format("float rise rate = {}\n", float_rise_rate);
|
std::cout << UNITS_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("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>
|
template<QuantityPoint QP>
|
||||||
requires(is_hae(QP::absolute_point_origin))
|
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>
|
template<typename FormatContext>
|
||||||
auto format(const QP& a, FormatContext& ctx)
|
auto format(const QP& a, FormatContext& ctx)
|
||||||
{
|
{
|
||||||
formatter<typename QP::quantity_type>::format(a.absolute(), 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<>
|
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>
|
template<typename FormatContext>
|
||||||
auto format(const hal_altitude& a, FormatContext& ctx)
|
auto format(const hal_altitude& a, FormatContext& ctx)
|
||||||
{
|
{
|
||||||
formatter<hal_altitude::quantity_type>::format(a.absolute(), 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;
|
unmanned_aerial_vehicle uav;
|
||||||
uav.take_off(msl_altitude{6'000 * ft});
|
uav.take_off(msl_altitude{6'000 * ft});
|
||||||
uav.current(msl_altitude{10'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};
|
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 {
|
struct waypoint {
|
||||||
std::string name;
|
std::string name;
|
||||||
@ -162,6 +162,6 @@ int main()
|
|||||||
};
|
};
|
||||||
|
|
||||||
waypoint wpt = {"EPPR", {54.24772_N, 18.6745_E}, msl_altitude{16. * ft}};
|
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));
|
to_hae<earth_gravity_model::egm2008_1>(wpt.msl_alt, wpt.pos));
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
conan
|
conan
|
||||||
pre-commit
|
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}>)
|
target_compile_definitions(mp-units-core-fmt INTERFACE ${projectPrefix}USE_LIBFMT=$<BOOL:${${projectPrefix}USE_LIBFMT}>)
|
||||||
|
|
||||||
if(${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)
|
target_link_libraries(mp-units-core-fmt INTERFACE fmt::fmt)
|
||||||
endif()
|
endif()
|
||||||
|
@ -55,7 +55,7 @@ public:
|
|||||||
constexpr fill_t& operator=(std::basic_string_view<Char> str)
|
constexpr fill_t& operator=(std::basic_string_view<Char> str)
|
||||||
{
|
{
|
||||||
auto size = str.size();
|
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];
|
for (size_t i = 0; i < size; ++i) data_[i] = str[i];
|
||||||
size_ = static_cast<unsigned char>(size);
|
size_ = static_cast<unsigned char>(size);
|
||||||
return *this;
|
return *this;
|
||||||
@ -98,11 +98,11 @@ struct width_checker {
|
|||||||
{
|
{
|
||||||
if constexpr (is_integer<T>) {
|
if constexpr (is_integer<T>) {
|
||||||
if constexpr (std::numeric_limits<T>::is_signed) {
|
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);
|
return static_cast<unsigned long long>(value);
|
||||||
} else {
|
} 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 (is_integer<T>) {
|
||||||
if constexpr (std::numeric_limits<T>::is_signed) {
|
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);
|
return static_cast<unsigned long long>(value);
|
||||||
} else {
|
} 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)
|
[[nodiscard]] constexpr int verify_dynamic_arg_index_in_range(size_t idx)
|
||||||
{
|
{
|
||||||
if (idx > static_cast<size_t>(std::numeric_limits<int>::max())) {
|
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);
|
return static_cast<int>(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename CharT>
|
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);
|
return verify_dynamic_arg_index_in_range(arg_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename CharT>
|
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>
|
template<class Handler, typename FormatContext>
|
||||||
[[nodiscard]] constexpr int get_dynamic_spec(int index, FormatContext& ctx)
|
[[nodiscard]] constexpr int get_dynamic_spec(int index, FormatContext& ctx)
|
||||||
{
|
{
|
||||||
const unsigned long long value =
|
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())) {
|
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);
|
return static_cast<int>(value);
|
||||||
}
|
}
|
||||||
@ -195,7 +195,7 @@ template<std::input_iterator It, std::sentinel_for<It> S>
|
|||||||
++begin;
|
++begin;
|
||||||
} while (begin != end && '0' <= *begin && *begin <= '9');
|
} 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;
|
return begin;
|
||||||
}
|
}
|
||||||
@ -222,12 +222,12 @@ template<std::input_iterator It, std::sentinel_for<It> S, typename IDHandler>
|
|||||||
else
|
else
|
||||||
++begin;
|
++begin;
|
||||||
if (begin == end || (*begin != '}' && *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
|
else
|
||||||
handler(index);
|
handler(index);
|
||||||
return begin;
|
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>
|
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)
|
if (width != -1)
|
||||||
handler.on_width(width);
|
handler.on_width(width);
|
||||||
else
|
else
|
||||||
throw STD_FMT::format_error("number is too big");
|
UNITS_THROW(UNITS_STD_FMT::format_error("number is too big"));
|
||||||
} else if (*begin == '{') {
|
} else if (*begin == '{') {
|
||||||
++begin;
|
++begin;
|
||||||
if (begin != end) begin = parse_arg_id(begin, end, width_adapter{handler});
|
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;
|
++begin;
|
||||||
}
|
}
|
||||||
return begin;
|
return begin;
|
||||||
@ -305,13 +305,13 @@ template<std::input_iterator It, std::sentinel_for<It> S, typename Handler>
|
|||||||
if (precision != -1)
|
if (precision != -1)
|
||||||
handler.on_precision(precision);
|
handler.on_precision(precision);
|
||||||
else
|
else
|
||||||
throw STD_FMT::format_error("number is too big");
|
UNITS_THROW(UNITS_STD_FMT::format_error("number is too big"));
|
||||||
} else if (c == '{') {
|
} else if (c == '{') {
|
||||||
++begin;
|
++begin;
|
||||||
if (begin != end) begin = parse_arg_id(begin, end, precision_adapter{handler});
|
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 {
|
} else {
|
||||||
throw STD_FMT::format_error("missing precision specifier");
|
UNITS_THROW(UNITS_STD_FMT::format_error("missing precision specifier"));
|
||||||
}
|
}
|
||||||
return begin;
|
return begin;
|
||||||
}
|
}
|
||||||
@ -355,7 +355,7 @@ template<std::input_iterator It, std::sentinel_for<It> S, typename Handler>
|
|||||||
if (align != fmt_align::none) {
|
if (align != fmt_align::none) {
|
||||||
if (p != begin) {
|
if (p != begin) {
|
||||||
auto c = *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)));
|
handler.on_fill(std::basic_string_view<std::iter_value_t<It>>(&*begin, static_cast<size_t>(p - begin)));
|
||||||
begin = p + 1;
|
begin = p + 1;
|
||||||
} else
|
} else
|
||||||
|
@ -41,10 +41,24 @@ UNITS_DIAGNOSTIC_IGNORE_SHADOW
|
|||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
UNITS_DIAGNOSTIC_POP
|
UNITS_DIAGNOSTIC_POP
|
||||||
|
|
||||||
#define STD_FMT fmt
|
#define UNITS_STD_FMT fmt
|
||||||
#define FMT_LOCALE(loc) (loc).template get<std::locale>()
|
#define UNITS_FMT_LOCALE(loc) (loc).template get<std::locale>()
|
||||||
#define FMT_TO_ARG_ID(arg) static_cast<int>(arg)
|
#define UNITS_FMT_TO_ARG_ID(arg) static_cast<int>(arg)
|
||||||
#define FMT_FROM_ARG_ID(arg) static_cast<size_t>(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
|
#else
|
||||||
|
|
||||||
@ -54,9 +68,10 @@ UNITS_DIAGNOSTIC_POP
|
|||||||
|
|
||||||
#include <format>
|
#include <format>
|
||||||
|
|
||||||
#define STD_FMT std
|
#define UNITS_STD_FMT std
|
||||||
#define FMT_LOCALE(loc) loc
|
#define UNITS_FMT_LOCALE(loc) loc
|
||||||
#define FMT_TO_ARG_ID(arg) arg
|
#define UNITS_FMT_TO_ARG_ID(arg) arg
|
||||||
#define FMT_FROM_ARG_ID(arg) arg
|
#define UNITS_FMT_FROM_ARG_ID(arg) arg
|
||||||
|
#define UNITS_THROW(arg) throw arg
|
||||||
|
|
||||||
#endif
|
#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) {
|
if (treat_as_floating_point) {
|
||||||
begin = parse_precision(begin, end, handler);
|
begin = parse_precision(begin, end, handler);
|
||||||
} else
|
} 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;
|
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);
|
if (begin != ptr) handler.on_text(begin, ptr);
|
||||||
begin = ++ptr; // consume '%'
|
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++;
|
c = *ptr++;
|
||||||
|
|
||||||
constexpr auto units_types = std::string_view{"Qq"};
|
constexpr auto units_types = std::string_view{"Qq"};
|
||||||
const auto new_end = find_first_of(begin, end, units_types.begin(), units_types.end());
|
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') {
|
if (*new_end == 'Q') {
|
||||||
handler.on_quantity_value(begin, new_end); // Edit `on_quantity_value` to add rep modifiers
|
handler.on_quantity_value(begin, new_end); // Edit `on_quantity_value` to add rep modifiers
|
||||||
} else {
|
} else {
|
||||||
@ -152,43 +152,43 @@ template<typename CharT, typename Rep, typename OutputIt, typename Locale>
|
|||||||
std::basic_string<CharT> buffer;
|
std::basic_string<CharT> buffer;
|
||||||
auto to_buffer = std::back_inserter(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) {
|
switch (rep_specs.sign) {
|
||||||
case fmt_sign::none:
|
case fmt_sign::none:
|
||||||
break;
|
break;
|
||||||
case fmt_sign::plus:
|
case fmt_sign::plus:
|
||||||
STD_FMT::format_to(to_buffer, "+");
|
UNITS_STD_FMT::format_to(to_buffer, "+");
|
||||||
break;
|
break;
|
||||||
case fmt_sign::minus:
|
case fmt_sign::minus:
|
||||||
STD_FMT::format_to(to_buffer, "-");
|
UNITS_STD_FMT::format_to(to_buffer, "-");
|
||||||
break;
|
break;
|
||||||
case fmt_sign::space:
|
case fmt_sign::space:
|
||||||
STD_FMT::format_to(to_buffer, " ");
|
UNITS_STD_FMT::format_to(to_buffer, " ");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rep_specs.alt) {
|
if (rep_specs.alt) {
|
||||||
STD_FMT::format_to(to_buffer, "#");
|
UNITS_STD_FMT::format_to(to_buffer, "#");
|
||||||
}
|
}
|
||||||
auto type = rep_specs.type;
|
auto type = rep_specs.type;
|
||||||
if (auto precision = rep_specs.precision; precision >= 0) {
|
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>) {
|
} 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 {
|
} else {
|
||||||
if (type != '\0') {
|
if (type != '\0') {
|
||||||
STD_FMT::format_to(to_buffer, "{}", type);
|
UNITS_STD_FMT::format_to(to_buffer, "{}", type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rep_specs.localized) {
|
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) {
|
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
|
// Creates a global format string
|
||||||
@ -196,25 +196,25 @@ template<typename CharT, typename Rep, typename OutputIt, typename Locale>
|
|||||||
template<typename CharT, typename OutputIt>
|
template<typename CharT, typename OutputIt>
|
||||||
OutputIt format_global_buffer(OutputIt out, const quantity_global_format_specs<CharT>& specs)
|
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] != ' ') {
|
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) {
|
switch (specs.align) {
|
||||||
case fmt_align::left:
|
case fmt_align::left:
|
||||||
STD_FMT::format_to(out, "<");
|
UNITS_STD_FMT::format_to(out, "<");
|
||||||
break;
|
break;
|
||||||
case fmt_align::right:
|
case fmt_align::right:
|
||||||
STD_FMT::format_to(out, ">");
|
UNITS_STD_FMT::format_to(out, ">");
|
||||||
break;
|
break;
|
||||||
case fmt_align::center:
|
case fmt_align::center:
|
||||||
STD_FMT::format_to(out, "^");
|
UNITS_STD_FMT::format_to(out, "^");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (specs.width >= 1) STD_FMT::format_to(out, "{}", specs.width);
|
if (specs.width >= 1) UNITS_STD_FMT::format_to(out, "{}", specs.width);
|
||||||
return STD_FMT::format_to(out, "}}");
|
return UNITS_STD_FMT::format_to(out, "}}");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto Reference, typename Rep, typename Locale, typename CharT, typename OutputIt>
|
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());
|
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)
|
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) +
|
throw UNITS_STD_FMT::format_error("only one of '" + std::string(modifiers) +
|
||||||
"' unit modifiers may be used in the format spec");
|
"' unit modifiers may be used in the format spec");
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mp_units::detail
|
} // namespace mp_units::detail
|
||||||
|
|
||||||
template<auto Reference, typename Rep, typename CharT>
|
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:
|
private:
|
||||||
using quantity = mp_units::quantity<Reference, Rep>;
|
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_value = false;
|
||||||
bool quantity_unit = false;
|
bool quantity_unit = false;
|
||||||
@ -274,7 +274,7 @@ private:
|
|||||||
|
|
||||||
struct spec_handler {
|
struct spec_handler {
|
||||||
formatter& f;
|
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_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; }
|
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) {
|
if (valid_rep_types.find(type) != std::string_view::npos) {
|
||||||
f.specs.rep.type = type;
|
f.specs.rep.type = type;
|
||||||
} else {
|
} 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"};
|
constexpr auto valid_modifiers = std::string_view{"UAoansd"};
|
||||||
for (auto it = begin; it != end; ++it) {
|
for (auto it = begin; it != end; ++it) {
|
||||||
if (valid_modifiers.find(*it) == std::string_view::npos)
|
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) {
|
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;
|
f.specs.unit.separator = mp_units::unit_symbol_separator::space;
|
||||||
else {
|
else {
|
||||||
if (f.specs.unit.encoding == mp_units::text_encoding::ascii)
|
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;
|
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 begin = ctx.begin();
|
||||||
auto end = ctx.end();
|
auto end = ctx.end();
|
||||||
@ -409,7 +409,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
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);
|
auto range = do_parse(ctx);
|
||||||
if (range.first != range.second)
|
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);
|
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`
|
// Format the `quantity buffer` using specs from `global_format_buffer`
|
||||||
// In the example, equivalent to STD_FMT::format("{:*^10}", "1.2_m")
|
// In the example, equivalent to UNITS_STD_FMT::format("{:*^10}", "1.2_m")
|
||||||
return STD_FMT::vformat_to(ctx.out(), global_format_buffer, STD_FMT::make_format_args(quantity_buffer));
|
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()) {
|
if (os.width()) {
|
||||||
// std::setw() applies to the whole quantity output so it has to be first put into std::string
|
// std::setw() applies to the whole quantity output so it has to be first put into std::string
|
||||||
std::basic_ostringstream<CharT, Traits> s;
|
std::basic_ostringstream<CharT, Traits> oss;
|
||||||
s.flags(os.flags());
|
oss.flags(os.flags());
|
||||||
s.imbue(os.getloc());
|
oss.imbue(os.getloc());
|
||||||
s.precision(os.precision());
|
oss.precision(os.precision());
|
||||||
detail::to_stream(s, q);
|
detail::to_stream(oss, q);
|
||||||
return os << s.str();
|
return os << std::move(oss).str();
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::to_stream(os, q);
|
detail::to_stream(os, q);
|
||||||
|
@ -23,7 +23,9 @@
|
|||||||
cmake_minimum_required(VERSION 3.19)
|
cmake_minimum_required(VERSION 3.19)
|
||||||
|
|
||||||
# find dependencies
|
# 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
|
# check if libc++ is being used
|
||||||
include(CheckLibcxxInUse)
|
include(CheckLibcxxInUse)
|
||||||
@ -81,7 +83,9 @@ target_include_directories(
|
|||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
if(${projectPrefix}LIBCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "14")
|
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)
|
target_link_libraries(mp-units-core INTERFACE range-v3::range-v3)
|
||||||
endif()
|
endif()
|
||||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
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 <compare>
|
||||||
#include <concepts>
|
#include <concepts>
|
||||||
|
|
||||||
#if UNITS_COMP_MSVC || UNITS_COMP_CLANG
|
#if UNITS_COMP_MSVC || (UNITS_COMP_CLANG && UNITS_COMP_CLANG < 16)
|
||||||
|
|
||||||
#define TYPENAME typename
|
#define TYPENAME typename
|
||||||
|
|
||||||
@ -108,11 +108,21 @@
|
|||||||
|
|
||||||
#if UNITS_COMP_MSVC
|
#if UNITS_COMP_MSVC
|
||||||
|
|
||||||
#define UNITS_MSVC_WORKAROUND(X)
|
#define UNITS_CONSTRAINED_AUTO_WORKAROUND(X)
|
||||||
|
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <numbers>
|
#include <numbers>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace mp_units {
|
namespace mp_units {
|
||||||
|
|
||||||
@ -243,10 +242,10 @@ using widen_t = conditional<std::is_arithmetic_v<T>,
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
[[nodiscard]] consteval T int_power(T base, std::integral auto exp)
|
[[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
|
// As this function should only be called at compile time, the terminations herein function as
|
||||||
// "parameter-compatible static_asserts", and should not result in exceptions at runtime.
|
// "parameter-compatible static_asserts", and should not result in terminations at runtime.
|
||||||
if (exp < 0) {
|
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) {
|
constexpr auto checked_multiply = [](auto a, auto b) {
|
||||||
@ -254,7 +253,7 @@ template<typename T>
|
|||||||
UNITS_DIAGNOSTIC_PUSH
|
UNITS_DIAGNOSTIC_PUSH
|
||||||
UNITS_DIAGNOSTIC_IGNORE_FLOAT_EQUAL
|
UNITS_DIAGNOSTIC_IGNORE_FLOAT_EQUAL
|
||||||
if (result / a != b) {
|
if (result / a != b) {
|
||||||
throw std::overflow_error{"Wraparound detected"};
|
std::terminate(); // Wraparound detected
|
||||||
}
|
}
|
||||||
UNITS_DIAGNOSTIC_POP
|
UNITS_DIAGNOSTIC_POP
|
||||||
return result;
|
return result;
|
||||||
@ -284,15 +283,15 @@ template<typename T>
|
|||||||
// need to write a custom function.
|
// need to write a custom function.
|
||||||
//
|
//
|
||||||
// Note that since this function should only be called at compile time, the point of these
|
// 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);
|
const auto exp = get_exponent(el);
|
||||||
if (exp.den != 1) {
|
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 (exp.num < 0) {
|
||||||
if constexpr (std::is_integral_v<T>) {
|
if constexpr (std::is_integral_v<T>) {
|
||||||
throw std::invalid_argument{"Cannot represent reciprocal as integer"};
|
std::terminate(); // Cannot represent reciprocal as integer
|
||||||
} else {
|
} else {
|
||||||
return T{1} / compute_base_power<T>(inverse(el));
|
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>)
|
requires(!std::is_integral_v<To> || std::is_integral_v<From>)
|
||||||
[[nodiscard]] consteval To checked_static_cast(From x)
|
[[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.
|
// to produce compiler errors, because we cannot `static_assert` on function arguments.
|
||||||
if constexpr (std::is_integral_v<To>) {
|
if constexpr (std::is_integral_v<To>) {
|
||||||
if (!std::in_range<To>(x)) {
|
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>
|
template<typename T>
|
||||||
inline constexpr bool is_derived_from_specialization_of_magnitude =
|
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>
|
template<typename T>
|
||||||
requires is_derived_from_specialization_of_magnitude<T>
|
requires is_derived_from_specialization_of_magnitude<T>
|
||||||
|
@ -50,7 +50,7 @@ namespace mp_units {
|
|||||||
*/
|
*/
|
||||||
template<Magnitude auto M, Unit U>
|
template<Magnitude auto M, Unit U>
|
||||||
struct scaled_unit {
|
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{};
|
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;
|
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:
|
private:
|
||||||
const T& target_;
|
const T& target_;
|
||||||
|
@ -53,9 +53,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
|||||||
|
|
||||||
SECTION("iostream") { CHECK(os.str() == "60 W"); }
|
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")
|
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("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("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")
|
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("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")
|
SECTION("volume")
|
||||||
@ -106,9 +106,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
|||||||
|
|
||||||
SECTION("iostream") { CHECK(os.str() == "2 m³"); }
|
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")
|
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("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("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")
|
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("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")
|
SECTION("compressibility")
|
||||||
@ -157,9 +157,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
|||||||
|
|
||||||
SECTION("iostream") { CHECK(os.str() == "123 1/Pa"); }
|
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")
|
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("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("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")
|
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("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")
|
SECTION("percents")
|
||||||
@ -210,9 +210,9 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
|||||||
|
|
||||||
SECTION("iostream") { CHECK(os.str() == "15 %"); }
|
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("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("floating-point representation")
|
||||||
{
|
{
|
||||||
SECTION("positive value")
|
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")
|
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")
|
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")
|
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")
|
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")
|
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
|
// TODO enable this when resistance is defined
|
||||||
// CHECK(STD_FMT::format("{:%Uq}", 123 * isq::resistance[kilo<ohm>]) == "kΩ");
|
// CHECK(UNITS_STD_FMT::format("{:%Uq}", 123 * isq::resistance[kilo<ohm>]) == "kΩ");
|
||||||
CHECK(STD_FMT::format("{:%Uq}", 123 * isq::time[us]) == "µs");
|
CHECK(UNITS_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::acceleration[m / s2]) == "m/s²");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Unicode text output is used by default")
|
SECTION("Unicode text output is used by default")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("{:%q}", 123 * isq::speed[km / h]) == "km/h");
|
CHECK(UNITS_STD_FMT::format("{:%q}", 123 * isq::speed[km / h]) == "km/h");
|
||||||
// CHECK(STD_FMT::format("{:%q}", 123 * isq::resistance[kilo<ohm>]) == "kΩ");
|
// CHECK(UNITS_STD_FMT::format("{:%q}", 123 * isq::resistance[kilo<ohm>]) == "kΩ");
|
||||||
CHECK(STD_FMT::format("{:%q}", 123 * isq::time[us]) == "µs");
|
CHECK(UNITS_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::acceleration[m / s2]) == "m/s²");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("ASCII text output")
|
SECTION("ASCII text output")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("{:%Aq}", 123 * isq::speed[km / h]) == "km/h");
|
CHECK(UNITS_STD_FMT::format("{:%Aq}", 123 * isq::speed[km / h]) == "km/h");
|
||||||
// CHECK(STD_FMT::format("{:%Aq}", 123 * isq::resistance[kilo<ohm>]) == "kohm");
|
// CHECK(UNITS_STD_FMT::format("{:%Aq}", 123 * isq::resistance[kilo<ohm>]) == "kohm");
|
||||||
CHECK(STD_FMT::format("{:%Aq}", 123 * isq::time[us]) == "us");
|
CHECK(UNITS_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::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")
|
SECTION("Solidus for only one element in denominator")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("{:%oq}", 123 * isq::speed[km / h]) == "km/h");
|
CHECK(UNITS_STD_FMT::format("{:%oq}", 123 * isq::speed[km / h]) == "km/h");
|
||||||
CHECK(STD_FMT::format("{:%oq}", 123 * isq::acceleration[m / s2]) == "m/s²");
|
CHECK(UNITS_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::pressure[kg / m / s2]) == "kg m⁻¹ s⁻²");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Solidus for only one element in denominator is used by default")
|
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(UNITS_STD_FMT::format("{:%q}", 123 * isq::speed[km / h]) == "km/h");
|
||||||
CHECK(STD_FMT::format("{:%q}", 123 * isq::acceleration[m / s2]) == "m/s²");
|
CHECK(UNITS_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::pressure[kg / m / s2]) == "kg m⁻¹ s⁻²");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Always use solidus")
|
SECTION("Always use solidus")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("{:%aq}", 123 * isq::speed[km / h]) == "km/h");
|
CHECK(UNITS_STD_FMT::format("{:%aq}", 123 * isq::speed[km / h]) == "km/h");
|
||||||
CHECK(STD_FMT::format("{:%aq}", 123 * isq::acceleration[m / s2]) == "m/s²");
|
CHECK(UNITS_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::pressure[kg / m / s2]) == "kg/(m s²)");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Never use solidus")
|
SECTION("Never use solidus")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("{:%nq}", 123 * isq::speed[km / h]) == "km h⁻¹");
|
CHECK(UNITS_STD_FMT::format("{:%nq}", 123 * isq::speed[km / h]) == "km h⁻¹");
|
||||||
CHECK(STD_FMT::format("{:%nq}", 123 * isq::acceleration[m / s2]) == "m s⁻²");
|
CHECK(UNITS_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::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")
|
SECTION("Space")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("{:%sq}", 123 * isq::force[kg * m / s2]) == "kg m/s²");
|
CHECK(UNITS_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(UNITS_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("{:%asq}", 123 * isq::pressure[kg / m / s2]) == "kg/(m s²)");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Space is used by default")
|
SECTION("Space is used by default")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("{:%q}", 123 * isq::force[kg * m / s2]) == "kg m/s²");
|
CHECK(UNITS_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(UNITS_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("{:%aq}", 123 * isq::pressure[kg / m / s2]) == "kg/(m s²)");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Dot")
|
SECTION("Dot")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("{:%dq}", 123 * isq::force[kg * m / s2]) == "kg⋅m/s²");
|
CHECK(UNITS_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(UNITS_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("{:%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")
|
SECTION("only the invalid modifier")
|
||||||
{
|
{
|
||||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%xq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%xq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
UNITS_STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("invalid modifier in the front")
|
SECTION("invalid modifier in the front")
|
||||||
{
|
{
|
||||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%xUdaq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%xUdaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
UNITS_STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("invalid modifier in the end")
|
SECTION("invalid modifier in the end")
|
||||||
{
|
{
|
||||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%Udaxq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%Udaxq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
UNITS_STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("invalid modifier in the middle")
|
SECTION("invalid modifier in the middle")
|
||||||
{
|
{
|
||||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%Udxaq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%Udxaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified"));
|
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")
|
SECTION("text encoding")
|
||||||
{
|
{
|
||||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%UdaUq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%UdaUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dUaUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dUUaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("solidus")
|
SECTION("solidus")
|
||||||
{
|
{
|
||||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%aUdaq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%aUdaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%daUaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%daaUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("separator")
|
SECTION("separator")
|
||||||
{
|
{
|
||||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%dUadq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dUadq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec"));
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dadUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec"));
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%addUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec"));
|
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")
|
SECTION("text encoding")
|
||||||
{
|
{
|
||||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%UdaAq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%UdaAq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dAaUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dAUaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
Catch::Matchers::Message("only one of 'UA' unit modifiers may be used in the format spec"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("solidus")
|
SECTION("solidus")
|
||||||
{
|
{
|
||||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%aUdnq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%aUdnq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dnUaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%daoUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
Catch::Matchers::Message("only one of 'oan' unit modifiers may be used in the format spec"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("separator")
|
SECTION("separator")
|
||||||
{
|
{
|
||||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%dUasq}", STD_FMT::make_format_args(1 * isq::length[m])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dUasq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec"));
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%sadUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec"));
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%adsUq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec"));
|
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]")
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%dAaq}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("dot unit separator allowed only for Unicode encoding"));
|
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]")
|
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]")
|
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")
|
SECTION("default format {} on a quantity")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("|{:0}|", 123 * isq::length[m]) == "|123 m|");
|
CHECK(UNITS_STD_FMT::format("|{:0}|", 123 * isq::length[m]) == "|123 m|");
|
||||||
CHECK(STD_FMT::format("|{:10}|", 123 * isq::length[m]) == "| 123 m|");
|
CHECK(UNITS_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("|{:<10}|", 123 * isq::length[m]) == "|123 m |");
|
||||||
CHECK(STD_FMT::format("|{:>10}|", 123 * isq::length[m]) == "| 123 m|");
|
CHECK(UNITS_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("|{:^10}|", 123 * isq::length[m]) == "| 123 m |");
|
||||||
CHECK(STD_FMT::format("|{:*<10}|", 123 * isq::length[m]) == "|123 m*****|");
|
CHECK(UNITS_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("|{:*>10}|", 123 * isq::length[m]) == "|*****123 m|");
|
||||||
CHECK(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")
|
SECTION("full format {:%Q %q} on a quantity")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("|{:0%Q%q}|", 123 * isq::length[m]) == "|123m|");
|
CHECK(UNITS_STD_FMT::format("|{:0%Q%q}|", 123 * isq::length[m]) == "|123m|");
|
||||||
CHECK(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(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(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(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(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(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(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")
|
SECTION("value only format {:%Q} on a quantity")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("|{:0%Q}|", 123 * isq::length[m]) == "|123|");
|
CHECK(UNITS_STD_FMT::format("|{:0%Q}|", 123 * isq::length[m]) == "|123|");
|
||||||
CHECK(STD_FMT::format("|{:10%Q}|", 123 * isq::length[m]) == "| 123|");
|
CHECK(UNITS_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("|{:<10%Q}|", 123 * isq::length[m]) == "|123 |");
|
||||||
CHECK(STD_FMT::format("|{:>10%Q}|", 123 * isq::length[m]) == "| 123|");
|
CHECK(UNITS_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("|{:^10%Q}|", 123 * isq::length[m]) == "| 123 |");
|
||||||
CHECK(STD_FMT::format("|{:*<10%Q}|", 123 * isq::length[m]) == "|123*******|");
|
CHECK(UNITS_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("|{:*>10%Q}|", 123 * isq::length[m]) == "|*******123|");
|
||||||
CHECK(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")
|
SECTION("symbol only format {:%q} on a quantity")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("|{:0%q}|", 123 * isq::length[m]) == "|m|");
|
CHECK(UNITS_STD_FMT::format("|{:0%q}|", 123 * isq::length[m]) == "|m|");
|
||||||
CHECK(STD_FMT::format("|{:10%q}|", 123 * isq::length[m]) == "| m|");
|
CHECK(UNITS_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("|{:<10%q}|", 123 * isq::length[m]) == "|m |");
|
||||||
CHECK(STD_FMT::format("|{:>10%q}|", 123 * isq::length[m]) == "| m|");
|
CHECK(UNITS_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("|{:^10%q}|", 123 * isq::length[m]) == "| m |");
|
||||||
CHECK(STD_FMT::format("|{:*<10%q}|", 123 * isq::length[m]) == "|m*********|");
|
CHECK(UNITS_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("|{:*>10%q}|", 123 * isq::length[m]) == "|*********m|");
|
||||||
CHECK(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")
|
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(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(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(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}", 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}", nan) == "nanm,+nanm,nanm, nanm");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("value only format {:%Q} on a quantity")
|
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(UNITS_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(UNITS_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(UNITS_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}", nan) == "nan,+nan,nan, nan");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,24 +589,24 @@ TEST_CASE("precision specification", "[text][fmt]")
|
|||||||
{
|
{
|
||||||
SECTION("full format {:%Q %q} on a quantity")
|
SECTION("full format {:%Q %q} on a quantity")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("{:%.0Q %q}", 1.2345 * isq::length[m]) == "1 m");
|
CHECK(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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("{:%.10Q %q}", 1.2345 * isq::length[m]) == "1.2345000000 m");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("value only format {:%Q} on a quantity")
|
SECTION("value only format {:%Q} on a quantity")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("{:%.0Q}", 1.2345 * isq::length[m]) == "1");
|
CHECK(UNITS_STD_FMT::format("{:%.0Q}", 1.2345 * isq::length[m]) == "1");
|
||||||
CHECK(STD_FMT::format("{:%.1Q}", 1.2345 * isq::length[m]) == "1.2");
|
CHECK(UNITS_STD_FMT::format("{:%.1Q}", 1.2345 * isq::length[m]) == "1.2");
|
||||||
CHECK(STD_FMT::format("{:%.2Q}", 1.2345 * isq::length[m]) == "1.23");
|
CHECK(UNITS_STD_FMT::format("{:%.2Q}", 1.2345 * isq::length[m]) == "1.23");
|
||||||
CHECK(STD_FMT::format("{:%.3Q}", 1.2345 * isq::length[m]) == "1.234");
|
CHECK(UNITS_STD_FMT::format("{:%.3Q}", 1.2345 * isq::length[m]) == "1.234");
|
||||||
CHECK(STD_FMT::format("{:%.4Q}", 1.2345 * isq::length[m]) == "1.2345");
|
CHECK(UNITS_STD_FMT::format("{:%.4Q}", 1.2345 * isq::length[m]) == "1.2345");
|
||||||
CHECK(STD_FMT::format("{:%.5Q}", 1.2345 * isq::length[m]) == "1.23450");
|
CHECK(UNITS_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("{:%.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")
|
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])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%.1Q %q}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("precision not allowed for integral quantity representation"));
|
Catch::Matchers::Message("precision not allowed for integral quantity representation"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("value only format {:%Q} on a quantity")
|
SECTION("value only format {:%Q} on a quantity")
|
||||||
{
|
{
|
||||||
REQUIRE_THROWS_MATCHES(STD_FMT::vformat("{:%.1Q}", STD_FMT::make_format_args(1 * isq::length[m])),
|
REQUIRE_THROWS_MATCHES(UNITS_STD_FMT::vformat("{:%.1Q}", UNITS_STD_FMT::make_format_args(1 * isq::length[m])),
|
||||||
STD_FMT::format_error,
|
UNITS_STD_FMT::format_error,
|
||||||
Catch::Matchers::Message("precision not allowed for integral quantity representation"));
|
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")
|
SECTION("full format {:%Q %q} on a quantity")
|
||||||
{
|
{
|
||||||
CHECK(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(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(STD_FMT::format("{:%dQ %q}", 42 * isq::length[m]) == "42 m");
|
CHECK(UNITS_STD_FMT::format("{:%dQ %q}", 42 * isq::length[m]) == "42 m");
|
||||||
CHECK(STD_FMT::format("{:%oQ %q}", 42 * isq::length[m]) == "52 m");
|
CHECK(UNITS_STD_FMT::format("{:%oQ %q}", 42 * isq::length[m]) == "52 m");
|
||||||
CHECK(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("{:%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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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("{:%.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(UNITS_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(UNITS_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(UNITS_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("{:%.3GQ %q}", 1.2345678e8 * isq::length[m]) == "1.23E+08 m");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("value only format {:%Q} on a quantity")
|
SECTION("value only format {:%Q} on a quantity")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("{:%bQ}", 42 * isq::length[m]) == "101010");
|
CHECK(UNITS_STD_FMT::format("{:%bQ}", 42 * isq::length[m]) == "101010");
|
||||||
CHECK(STD_FMT::format("{:%BQ}", 42 * isq::length[m]) == "101010");
|
CHECK(UNITS_STD_FMT::format("{:%BQ}", 42 * isq::length[m]) == "101010");
|
||||||
CHECK(STD_FMT::format("{:%dQ}", 42 * isq::length[m]) == "42");
|
CHECK(UNITS_STD_FMT::format("{:%dQ}", 42 * isq::length[m]) == "42");
|
||||||
CHECK(STD_FMT::format("{:%oQ}", 42 * isq::length[m]) == "52");
|
CHECK(UNITS_STD_FMT::format("{:%oQ}", 42 * isq::length[m]) == "52");
|
||||||
CHECK(STD_FMT::format("{:%xQ}", 42 * isq::length[m]) == "2a");
|
CHECK(UNITS_STD_FMT::format("{:%xQ}", 42 * isq::length[m]) == "2a");
|
||||||
CHECK(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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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(UNITS_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("{:%.3gQ}", 1.2345678e8 * isq::length[m]) == "1.23e+08");
|
||||||
CHECK(STD_FMT::format("{:%GQ}", 1.2345678 * isq::length[m]) == "1.23457");
|
CHECK(UNITS_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(UNITS_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(UNITS_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("{:%.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")
|
SECTION("full format {:%Q %q} on a quantity")
|
||||||
{
|
{
|
||||||
CHECK(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(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(STD_FMT::format("{:%#oQ %q}", 42 * isq::length[m]) == "052 m");
|
CHECK(UNITS_STD_FMT::format("{:%#oQ %q}", 42 * isq::length[m]) == "052 m");
|
||||||
CHECK(STD_FMT::format("{:%#xQ %q}", 42 * isq::length[m]) == "0x2a m");
|
CHECK(UNITS_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("{:%#XQ %q}", 42 * isq::length[m]) == "0X2A m");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("value only format {:%Q} on a quantity")
|
SECTION("value only format {:%Q} on a quantity")
|
||||||
{
|
{
|
||||||
CHECK(STD_FMT::format("{:%#bQ}", 42 * isq::length[m]) == "0b101010");
|
CHECK(UNITS_STD_FMT::format("{:%#bQ}", 42 * isq::length[m]) == "0b101010");
|
||||||
CHECK(STD_FMT::format("{:%#BQ}", 42 * isq::length[m]) == "0B101010");
|
CHECK(UNITS_STD_FMT::format("{:%#BQ}", 42 * isq::length[m]) == "0B101010");
|
||||||
CHECK(STD_FMT::format("{:%#oQ}", 42 * isq::length[m]) == "052");
|
CHECK(UNITS_STD_FMT::format("{:%#oQ}", 42 * isq::length[m]) == "052");
|
||||||
CHECK(STD_FMT::format("{:%#xQ}", 42 * isq::length[m]) == "0x2a");
|
CHECK(UNITS_STD_FMT::format("{:%#xQ}", 42 * isq::length[m]) == "0x2a");
|
||||||
CHECK(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")
|
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(UNITS_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(grp3, "{:%LQ %q}", 299792458 * isq::speed[m / s]) == "299'792'458 m/s");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,28 +23,26 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from conan import ConanFile
|
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
|
from conan.tools.cmake import CMake, cmake_layout
|
||||||
|
|
||||||
|
|
||||||
class TestPackageConan(ConanFile):
|
class TestPackageConan(ConanFile):
|
||||||
settings = "os", "compiler", "build_type", "arch"
|
settings = "os", "arch", "compiler", "build_type"
|
||||||
generators = "CMakeDeps", "CMakeToolchain", "VirtualBuildEnv", "VirtualRunEnv"
|
generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv"
|
||||||
apply_env = False
|
|
||||||
test_type = "explicit" # TODO Remove for Conan 2.0
|
|
||||||
|
|
||||||
def requirements(self):
|
def requirements(self):
|
||||||
self.requires(self.tested_reference_str)
|
self.requires(self.tested_reference_str)
|
||||||
|
|
||||||
|
def layout(self):
|
||||||
|
cmake_layout(self)
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
cmake = CMake(self)
|
cmake = CMake(self)
|
||||||
cmake.configure()
|
cmake.configure()
|
||||||
cmake.build()
|
cmake.build()
|
||||||
|
|
||||||
def layout(self):
|
|
||||||
cmake_layout(self)
|
|
||||||
|
|
||||||
def test(self):
|
def test(self):
|
||||||
if not cross_building(self):
|
if can_run(self):
|
||||||
cmd = os.path.join(self.cpp.build.bindirs[0], "test_package")
|
bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package")
|
||||||
self.run(cmd, env="conanrun")
|
self.run(bin_path, env="conanrun")
|
||||||
|
Reference in New Issue
Block a user