From b0ce5eaee9246d5c113615c6a321da549630fc38 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 23 May 2024 14:44:00 -0400 Subject: [PATCH] xo-unit ++ docs ++ quantity arithmetic + example --- docs/CMakeLists.txt | 6 +- docs/basis-unit-class.rst | 2 +- docs/basis-unit-constants.rst | 2 +- docs/basis-unit-reference.rst | 2 +- docs/bpu-class.rst | 2 +- docs/bu-store-class.rst | 2 +- docs/conf.py | 1 + docs/dimension-enum.rst | 2 +- docs/glossary.rst | 47 ++-- docs/implementation.rst | 39 ++-- docs/index.rst | 13 +- docs/install.rst | 47 ++-- docs/natural-unit-class.rst | 2 +- docs/quantity-class.rst | 51 +++-- docs/quantity-factoryfunctions.rst | 15 +- docs/quantity-reference.rst | 4 +- docs/quantity-source-code.rst | 11 + docs/quantity-unitvars.rst | 59 +++-- docs/scaled-unit-class.rst | 2 +- docs/scaled-unit-constants.rst | 4 +- docs/scaled-unit-reference.rst | 2 +- docs/ubuntu-github-workflow.rst | 9 + docs/xquantity-class.rst | 60 +++++ docs/xquantity-reference.rst | 3 +- example/CMakeLists.txt | 1 + example/ex8/ex8.cpp | 14 +- example/ex_qty/CMakeLists.txt | 12 + example/ex_qty/ex_qty.cpp | 18 ++ include/xo/unit/mpl/quantity.hpp | 2 +- include/xo/unit/quantity.hpp | 281 ++++++++++++++++++++---- include/xo/unit/quantity_ops.hpp | 41 +++- include/xo/unit/scaled_unit.hpp | 3 + include/xo/unit/scaled_unit_concept.hpp | 23 ++ include/xo/unit/xquantity.hpp | 104 ++++++++- 34 files changed, 713 insertions(+), 173 deletions(-) create mode 100644 docs/quantity-source-code.rst create mode 100644 docs/ubuntu-github-workflow.rst create mode 100644 example/ex_qty/CMakeLists.txt create mode 100644 example/ex_qty/ex_qty.cpp create mode 100644 include/xo/unit/scaled_unit_concept.hpp diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index e40b680..9dd4af8 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -3,8 +3,8 @@ xo_doxygen_collect_deps() xo_docdir_doxygen_config() xo_docdir_sphinx_config( - index.rst examples.rst glossary.rst install.rst implementation.rst development.rst - quantity-reference.rst quantity-class.rst quantity-factoryfunctions.rst quantity-unitvars.rst + index.rst examples.rst glossary.rst install.rst implementation.rst + quantity-reference.rst quantity-class.rst quantity-factoryfunctions.rst quantity-unitvars.rst quantity-source-code.rst xquantity-reference.rst xquantity-class.rst scaled-unit-reference.rst scaled-unit-class.rst scaled-unit-constants.rst natural-unit-class.rst @@ -12,5 +12,7 @@ xo_docdir_sphinx_config( bu-store-class.rst basis-unit-reference.rst basis-unit-class.rst basis-unit-constants.rst dimension-enum.rst + development.rst + ubuntu-github-workflow.rst ) #xo_utest_coverage_config2() diff --git a/docs/basis-unit-class.rst b/docs/basis-unit-class.rst index 01f0b23..cf809a9 100644 --- a/docs/basis-unit-class.rst +++ b/docs/basis-unit-class.rst @@ -22,7 +22,7 @@ Context +----------------+ | | bu_store | | +----------------+---------------+ - |cYEL basis_unit | + |cBLU basis_unit | +--------------------------------+ | dimension | +--------------------------------+ diff --git a/docs/basis-unit-constants.rst b/docs/basis-unit-constants.rst index 15bdc55..caa833f 100644 --- a/docs/basis-unit-constants.rst +++ b/docs/basis-unit-constants.rst @@ -22,7 +22,7 @@ Context +----------------+ | | bu_store | | +----------------+---------------+ - |cYEL basis_unit | + |cBLU basis_unit | +--------------------------------+ | dimension | +--------------------------------+ diff --git a/docs/basis-unit-reference.rst b/docs/basis-unit-reference.rst index a026f00..6ee84cc 100644 --- a/docs/basis-unit-reference.rst +++ b/docs/basis-unit-reference.rst @@ -19,7 +19,7 @@ Built-in named units for each native dimension +----------------+ | | bu_store | | +----------------+---------------+ - |cYEL basis_unit | + |cBLU basis_unit | +--------------------------------+ | dimension | +--------------------------------+ diff --git a/docs/bpu-class.rst b/docs/bpu-class.rst index 1706768..eb8c6ae 100644 --- a/docs/bpu-class.rst +++ b/docs/bpu-class.rst @@ -18,7 +18,7 @@ Context +--------------------------------+ | natural_unit | +--------------------------------+ - |cYEL bpu | + |cBLU bpu | +----------------+ | | bu_store | | +----------------+---------------+ diff --git a/docs/bu-store-class.rst b/docs/bu-store-class.rst index 3214945..9228330 100644 --- a/docs/bu-store-class.rst +++ b/docs/bu-store-class.rst @@ -15,7 +15,7 @@ Basis Unit Store +--------------------------------+ | bpu | +----------------+ | - |cYEL bu_store | | + |cBLU bu_store | | +----------------+---------------+ | basis_unit | +--------------------------------+ diff --git a/docs/conf.py b/docs/conf.py index ed3a291..1740254 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -15,6 +15,7 @@ #extensions = [] extensions = [ "breathe", + "sphinx.ext.mathjax", # inline math "sphinx.ext.autodoc", # generate info from docstrings "sphinxcontrib.ditaa", # diagrams-through-ascii-art "sphinxcontrib.plantuml" # text -> uml diagrams diff --git a/docs/dimension-enum.rst b/docs/dimension-enum.rst index 15a6202..863c38d 100644 --- a/docs/dimension-enum.rst +++ b/docs/dimension-enum.rst @@ -24,7 +24,7 @@ Context +----------------+---------------+ | basis_unit | +--------------------------------+ - |cYEL dimension | + |cBLU dimension | +--------------------------------+ Introduction diff --git a/docs/glossary.rst b/docs/glossary.rst index e12cc19..51895cc 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -4,26 +4,35 @@ Glossary -------- .. glossary:: - basis dimension - Orthogonal directions associated with basis units, for example *mass*, *length*, *time*. - In xo-unit these are represented by the enum ``xo::qty::dim``. - - basis unit (bu) - An implementation type representing a quantity (with associated scale) in the direction of a single :term:`basis dimension`. - For example *milliseconds*, *seconds*, and *hours* stand for different basis units with the *time* dimension. - In xo-unit these are represented by the template type ``xo::qty::basis_unit``. - + dimension + dim + | Fundamental, orthogonal directions associated available for constructing units. + | For example *mass*, *length*, *time*. + | In *xo-unit* these are represented by the enum :doc:`xo::qty::dimension`. + + basis unit + bu + | An implementation type representing a quantity (with associated scale) in the direction of a single :term:`dimension`. + | For example *milliseconds*, *seconds*, and *hours* stand for different basis units within the *time* dimension. + | In *xo-unit* these are represented by the template type :doc:`xo::qty::basis_unit`. + + basis power unit bpu - A rational power of a (single) basis unit. For example *s\ :sup:-2* or *hr\ :sup:-(1/2)*. - In xo-unit these are represented by the template type ``xo::qty::bpu``. - - natural unit (nu) - A cartesian product of basis power units (bpus). For example *kg.m.s\ :sup:-2* or *hr\ :sup:-(1/2)*. - In xo-unit these are represented by template type ``xo::qty::natural_unit``. - - scaled unit (su) - A dimensionless multiple of a natural unit. Used as intermediate value when coalescing quantities involving different units. - In xo-unit these are represented by template type ``xo::qty::scaled_unit``. + | A rational power of a (single) basis unit. + | For example :math:`s^{-2}` for unit "per second squared" or :math:`yr^{-(1/2)}` for "per square-root of a year". + | In *xo-unit* these are represented by the template type :doc:`xo::qty::bpu` + + natural unit + nu + | A cartesian product of basis power units (bpus); + | For example :math:`kg.m.s^{-2}` or :math:`hr^{-(1/2)}`. + | In *xo-unit* these are represented by template type :doc:`xo::qty::natural_unit`. + + scaled unit + su + | A dimensionless multiple of a natural unit. + | Used as intermediate value when coalescing quantities involving different units. + | In *xo-unit* these are represented by template type :doc:`xo::qty::scaled_unit`. XO A set of integrated c++ libraries for complex event processing, with browser and python integration. diff --git a/docs/implementation.rst b/docs/implementation.rst index 54a7efd..86ec396 100644 --- a/docs/implementation.rst +++ b/docs/implementation.rst @@ -3,7 +3,7 @@ Components ========== -Library dependencies for *xo-unit*: +Library dependency tower for *xo-unit*: .. ditaa:: @@ -14,28 +14,31 @@ Library dependencies for *xo-unit*: +-----------------+ | xo_flatstring | +-----------------+ + | xo_cmake | + +-----------------+ -``xo-unit`` also depends on ``xo-cmake`` macros. +Install instructions :doc:`here` Abstraction tower for *xo-unit* components: .. ditaa:: - - +-----------+-----------+ - | quantity | xquantity | - +-----------+-----------+ - | scaled_unit | - +-----------------------+ - | natural_unit | - +-----------------------+ - | bpu | - +-----------+ | - | bu_store | | - +-----------+-----------+ - | basis_unit | - +-----------------------+ - | dimension | - +-----------------------+ + :--scale: 0.85 + + +----------------+---------------+ + | quantity | xquantity | + +----------------+---------------+ + | scaled_unit | + +--------------------------------+ + | natural_unit | + +--------------------------------+ + | bpu | + +----------------+ | + | bu_store | | + +----------------+---------------+ + | basis_unit | + +--------------------------------+ + | dimension | + +--------------------------------+ - :doc:`quantity`: diff --git a/docs/index.rst b/docs/index.rst index 87c3b9f..86ae0e6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -28,7 +28,7 @@ runtime (since we can't construct new c++ types at runtime). .. toctree:: :maxdepth: 2 - :caption: xo-unit contents: + :caption: xo-unit contents install examples @@ -42,10 +42,7 @@ runtime (since we can't construct new c++ types at runtime). basis-unit-reference dimension-enum development - -Indices and Tables ------------------- - -* :ref:`glossary` -* :ref:`genindex` -* :ref:`search` + ubuntu-github-workflow + glossary + genindex + search diff --git a/docs/install.rst b/docs/install.rst index 7000af9..049efc8 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -7,26 +7,35 @@ Install ======= ``xo-unit`` uses supporting header-only libraries ``xo-ratio`` and ``xo-flatstring``. -All three are on github: +and (optionally) cmake macros ``xo-cmake``. These are on github: -- `xo-unit source`_ -- `xo-ratio source`_ -- `xo-flatstring source`_ +- `xo-unit source`_ (constexpr quantities, units and dimension-checking) +- `xo-ratio source`_ (constexpr exact ratios) +- `xo-flatstring source`_ (constexpr strings) +- `xo-cmake source`_ (shared cmake macros) .. _xo-unit source: https://github.com/rconybea/xo-unit .. _xo-ratio source: https://github.com/rconybea/xo-ratio .. _xo-flatstring source: https://github.com/rconybea/xo-flatstring +.. _xo-cmake source: https://github.com/rconybea/xo-cmake -Implementation relies on some c++20 features (for example class-instances as template arguments). -Tested with gcc 12.3, 13.2 +`xo-cmake` is nccessary to invoke `xo` cmake build for: -``xo-unit`` also relies on sister header-only libraries: +- site install +- example programs +- unit tests -One way to use ``xo-unit`` in a project is to import the source tree directly: +Can omit to instead copy `xo_unit`, `xo-ratio` and `xo-flatstring` source trees; +see instructions below for including as git submodule + +Implementation relies on some c++20 features (for example class-instances as template arguments). +Tested with gcc 12.3, 13.2 Include as submodule -------------------- +One way to use ``xo-unit`` in a project is to import the source tree directly: + .. code-block:: bash cd myproject @@ -50,21 +59,18 @@ to c++ source files that rely on xo-unit Ubuntu Install Pattern ---------------------- -Example instructions (from github actions CI) for build starting from stock ubuntu are in `ubuntu-main.yml`_ - -.. _ubuntu-main.yml: https://github.com/Rconybea/xo-unit/blob/main/.github/workflows/ubuntu-main.yml - +:doc:`Example instructions` (used for github actions CI) for build starting from stock ubuntu Installing from source ---------------------- -Although the xo-unit, xo-ratio and xo-flatstring libraries are header-only, -they do have a build dependency on shared cmake macros, and a bootstrap script `xo-cmake-config`. +Install scripts for `xo-unit`, `xo-ratio` and `xo-flatstring` depend on shared cmake macros +and a bootstrap script `xo-cmake-config`. * `xo-cmake`_ source .. _xo-cmake: https://github.com/rconybea/xo-cmake - + Preamble: .. code-block:: bash @@ -183,7 +189,7 @@ Preamble: git clone https://github.com/rconybea/xo-unit PREFIX=~/local # ..or other desired installation prefix - + Build and Install `catch2` (assuming ubuntu here): .. code-block:: bash @@ -216,7 +222,7 @@ Build and Install `xo-randomgen` (no unit tests yet): cmake --build xo-randomgen/.build -j cmake --install xo-randomgen/.build -Build, Test and Install `xo-flatstring`: +Build, Test and Install `xo-flatstring`: .. code-block:: bash @@ -255,7 +261,7 @@ To enable building example programs: cd ~/proj/xo cmake -DCMAKE_INSTALL_PREFIX=$PREFIX -DXO_ENABLE_EXAMPLES=1 -B xo-unit/.build -S xo-unit - + Run examples from the build directory: .. code-block:: bash @@ -288,17 +294,16 @@ Preamble (assuming ubuntu here): sudo apt-get install python3-sphinx-rtd-theme sudo apt-get install python3-breathe -Build `xo-unit` docs +Build `xo-unit` docs .. code-block:: bash cd ~/proj/xo cmake -DCMAKE_INSTALL_PREFIX=$PREFIX -B xo-unit/.build - cmake --build xo-unit/.build -- docs + cmake --build xo-unit/.build -- docs cmake --install xo-unit/.build # if docs built, installs to $PREFIX/share/doc/xo_unit/html Supported compilers ------------------- * developed with gcc 12.3.0 and gcc 13.2.0; github CI using gcc 11.4.0 (asof March 2024) - diff --git a/docs/natural-unit-class.rst b/docs/natural-unit-class.rst index b7eea47..61504af 100644 --- a/docs/natural-unit-class.rst +++ b/docs/natural-unit-class.rst @@ -16,7 +16,7 @@ Context +----------------+---------------+ | scaled_unit | +--------------------------------+ - |cYEL natural_unit | + |cBLU natural_unit | +--------------------------------+ | bpu | +----------------+ | diff --git a/docs/quantity-class.rst b/docs/quantity-class.rst index 7e74abb..fd9006e 100644 --- a/docs/quantity-class.rst +++ b/docs/quantity-class.rst @@ -3,10 +3,16 @@ Quantity ======== +Dimensioned quantity with compile-time unit checking/conversion + +Context +------- + .. ditaa:: + :--scale: 0.85 +----------------+---------------+ - |cYEL quantity | xquantity | + |cBLU quantity | xquantity | +----------------+---------------+ | scaled_unit | +--------------------------------+ @@ -36,15 +42,37 @@ Quantity rectangle constexpr #e0f0ff { - object unit<> + object unit<> + unit : is_natural() = true - qty1 o-- unit : s_unit (static constexpr) + qty1 o-- unit : s_scaled_unit (static constexpr) } -Arithmetic on :doc:`xo::qty::quantity` instances -does *not* use ``xo::qty::quantity::s_scaled_unit`` at runtime; -instead gets everything it needs at compile time. +- Arithmetic on :doc:`xo::qty::quantity` instances + does *not* use ``xo::qty::quantity::s_scaled_unit`` at runtime; + instead gets everything it needs at compile time. + +- The :code:`xo::qty::quantity` template takes a :doc:`xo::qty::scaled_unit` instance, + but only accepts values with :code:`xo::qty::scaled_unit::is_natural() == true`. + + This accomodation (instead of requiring a :doc:`xo::qty::natural_unit` instance + is to make possible code like this possible: + + .. code-block:: cpp + + #include "xo/unit/quantity.hpp" + + using namespace xo::qty; + + quantity x; + quantity y; + + while rejecting attempt to mix multiple scales in the same quantity value: + + .. code-block:: cpp + + quantity x; // will not compile Class ----- @@ -81,19 +109,16 @@ Assignment ---------- .. doxygengroup:: quantity-assignment - :content-only: Access Methods -------------- .. doxygengroup:: quantity-access-methods - :content-only: Constants --------- .. doxygengroup:: quantity-constants - :content-only: Conversion Methods ------------------ @@ -101,13 +126,11 @@ Conversion Methods Amount-preserving conversion to quantities with different units and/or representation. .. doxygengroup:: quantity-unit-conversion - :content-only: -Arithmetic ----------- +Arithmetic Operators +-------------------- -.. doxygengroup:: quantity-arithmetic - :content-only: +.. doxygengroup:: quantity-operators Support methods for arithmetic operations diff --git a/docs/quantity-factoryfunctions.rst b/docs/quantity-factoryfunctions.rst index 3f68c3c..a447d75 100644 --- a/docs/quantity-factoryfunctions.rst +++ b/docs/quantity-factoryfunctions.rst @@ -1,9 +1,18 @@ .. _quantity_factoryfunctions: +Quantity Factory Functions +========================== + +Convenience functions for creating quantities with compile-time units + +Context +------- + .. ditaa:: + :--scale: 0.85 +----------------+---------------+ - |cYEL quantity | xquantity | + |cBLU quantity | xquantity | +----------------+---------------+ | scaled_unit | +--------------------------------+ @@ -21,8 +30,8 @@ .. toctree:: :maxdepth: 2 -Quantity Factory Functions -========================== +Introduction +------------ .. code-block:: cpp diff --git a/docs/quantity-reference.rst b/docs/quantity-reference.rst index 44095ce..9d98503 100644 --- a/docs/quantity-reference.rst +++ b/docs/quantity-reference.rst @@ -4,9 +4,10 @@ Quantity Reference ================== .. ditaa:: + :--scale: 0.85 +----------------+---------------+ - |cYEL quantity | xquantity | + |cBLU quantity | xquantity | +----------------+---------------+ | scaled_unit | +--------------------------------+ @@ -27,3 +28,4 @@ Quantity Reference quantity-class quantity-factoryfunctions quantity-unitvars + quantity-source-code diff --git a/docs/quantity-source-code.rst b/docs/quantity-source-code.rst new file mode 100644 index 0000000..4461ee1 --- /dev/null +++ b/docs/quantity-source-code.rst @@ -0,0 +1,11 @@ +.. _quantity-source-code: + +Quantity Source Code +==================== + +github: `quantity.hpp @github.com`_ + +.. _`quantity.hpp @github.com`: https://github.com/rconybea/xo-unit/blob/main/include/xo/unit/quantity.hpp + +.. literalinclude:: ../include/xo/unit/quantity.hpp + :language: c++ diff --git a/docs/quantity-unitvars.rst b/docs/quantity-unitvars.rst index 719197b..ee32e4d 100644 --- a/docs/quantity-unitvars.rst +++ b/docs/quantity-unitvars.rst @@ -1,11 +1,35 @@ .. _quantity-unitvars: -.. toctree:: - :maxdepth: 2 - Quantity Unit Variables ======================= +Built-in unit quantities + +Context +------- + +.. ditaa:: + :--scale: 0.85 + + +----------------+---------------+ + |cBLU quantity | xquantity | + +----------------+---------------+ + | scaled_unit | + +--------------------------------+ + | natural_unit | + +--------------------------------+ + | bpu | + +----------------+ | + | bu_store | | + +----------------+---------------+ + | basis_unit | + +--------------------------------+ + | dimension | + +--------------------------------+ + +Introduction +------------ + .. code-block:: cpp #include @@ -28,11 +52,16 @@ Can use these to assemble unit quantities with compound dimensions Mass ---- +.. doxygenvariable:: xo::qty::qty::picogram +.. doxygenvariable:: xo::qty::qty::nanogram +.. doxygenvariable:: xo::qty::qty::microgram .. doxygenvariable:: xo::qty::qty::milligram .. doxygenvariable:: xo::qty::qty::gram .. doxygenvariable:: xo::qty::qty::kilogram .. doxygenvariable:: xo::qty::qty::tonne .. doxygenvariable:: xo::qty::qty::kilotonne +.. doxygenvariable:: xo::qty::qty::megatonne +.. doxygenvariable:: xo::qty::qty::gigatonne Distance -------- @@ -46,20 +75,24 @@ Distance .. doxygenvariable:: xo::qty::qty::gigameter .. doxygenvariable:: xo::qty::qty::lightsecond .. doxygenvariable:: xo::qty::qty::astronomicalunit +.. doxygenvariable:: xo::qty::qty::inch +.. doxygenvariable:: xo::qty::qty::foot +.. doxygenvariable:: xo::qty::qty::yard +.. doxygenvariable:: xo::qty::qty::mile Time ---- -.. notyet .. doxygenvariable:: xo::qty::qty::picosecond -.. notyet .. doxygenvariable:: xo::qty::qty::nanosecond -.. notyet .. doxygenvariable:: xo::qty::qty::microsecond -.. notyet .. doxygenvariable:: xo::qty::qty::millisecond +.. doxygenvariable:: xo::qty::qty::picosecond +.. doxygenvariable:: xo::qty::qty::nanosecond +.. doxygenvariable:: xo::qty::qty::microsecond +.. doxygenvariable:: xo::qty::qty::millisecond .. doxygenvariable:: xo::qty::qty::second .. doxygenvariable:: xo::qty::qty::minute .. doxygenvariable:: xo::qty::qty::hour .. doxygenvariable:: xo::qty::qty::day -.. notyet doxygenvariable:: xo::qty::qty::week -.. notyet doxygenvariable:: xo::qty::qty::month -.. notyet doxygenvariable:: xo::qty::qty::year -.. notyet doxygenvariable:: xo::qty::qty::year250 -.. notyet doxygenvariable:: xo::qty::qty::year360 -.. notyet doxygenvariable:: xo::qty::qty::year365 +.. doxygenvariable:: xo::qty::qty::week +.. doxygenvariable:: xo::qty::qty::month +.. doxygenvariable:: xo::qty::qty::year +.. doxygenvariable:: xo::qty::qty::year250 +.. doxygenvariable:: xo::qty::qty::year360 +.. doxygenvariable:: xo::qty::qty::year365 diff --git a/docs/scaled-unit-class.rst b/docs/scaled-unit-class.rst index 7193edd..42725e0 100644 --- a/docs/scaled-unit-class.rst +++ b/docs/scaled-unit-class.rst @@ -14,7 +14,7 @@ Context +----------------+----------------+ | quantity | xquantity | +----------------+----------------+ - |cYEL scaled_unit | + |cBLU scaled_unit | +---------------------------------+ | natural_unit | +---------------------------------+ diff --git a/docs/scaled-unit-constants.rst b/docs/scaled-unit-constants.rst index 46757c0..f0b00b6 100644 --- a/docs/scaled-unit-constants.rst +++ b/docs/scaled-unit-constants.rst @@ -3,7 +3,7 @@ Scaled Unit Constants ===================== -Built-in unit constants. +Built-in unit constants, for use with conversions Context ------- @@ -14,7 +14,7 @@ Context +----------------+---------------+ | quantity | xquantity | +----------------+---------------+ - |cYEL scaled_unit | + |cBLU scaled_unit | +--------------------------------+ | natural_unit | +--------------------------------+ diff --git a/docs/scaled-unit-reference.rst b/docs/scaled-unit-reference.rst index 61ec0de..699db70 100644 --- a/docs/scaled-unit-reference.rst +++ b/docs/scaled-unit-reference.rst @@ -11,7 +11,7 @@ A dimensionless multiple of a :doc:`natural_unit` +----------------+---------------+ | quantity | xquantity | +----------------+---------------+ - |cYEL scaled_unit | + |cBLU scaled_unit | +--------------------------------+ | natural_unit | +--------------------------------+ diff --git a/docs/ubuntu-github-workflow.rst b/docs/ubuntu-github-workflow.rst new file mode 100644 index 0000000..012ee9a --- /dev/null +++ b/docs/ubuntu-github-workflow.rst @@ -0,0 +1,9 @@ +.. ubuntu-github-workflow: + +Ubuntu Github Workflow +====================== + +Instructions for build starting on a stock ubuntu platform (see `xo-unit/.github/workflows/ubuntu_main.yml`) + +.. literalinclude:: ../.github/workflows/ubuntu-main.yml + :language: yaml diff --git a/docs/xquantity-class.rst b/docs/xquantity-class.rst index dba2ca5..abd48fd 100644 --- a/docs/xquantity-class.rst +++ b/docs/xquantity-class.rst @@ -3,13 +3,73 @@ Xquantity ========= +Polymorphic dimensioned quantity with runtime unit checking/conversion + +Context +------- + +.. ditaa:: + :--scale: 0.85 + + +----------------+---------------+ + | quantity |cBLU xquantity | + +----------------+---------------+ + | scaled_unit | + +--------------------------------+ + | natural_unit | + +--------------------------------+ + | bpu | + +----------------+ | + | bu_store | | + +----------------+---------------+ + | basis_unit | + +--------------------------------+ + | dimension | + +--------------------------------+ + .. code-block:: cpp #include +.. uml:: + :scale: 99% + :align: center + + allowmixing + + object qty1<> + qty1 : scale = 1.23 + qty1 : unit = unit + + object unit<> + unit : is_natural() = true + + qty1 o-- unit + + Class ----- Class with run-time unit representation. .. doxygenclass:: xo::qty::xquantity + +Member Variables +---------------- + +.. doxygengroup:: xquantity-instance-vars + +Constructors +------------ + +.. doxygengroup:: xquantity-ctors + +Access Methods +-------------- + +.. doxygengroup:: xquantity-access-methods + +General Methods +--------------- + +.. doxygengroup:: xquantity-methods diff --git a/docs/xquantity-reference.rst b/docs/xquantity-reference.rst index 511f4db..c3ee476 100644 --- a/docs/xquantity-reference.rst +++ b/docs/xquantity-reference.rst @@ -4,9 +4,10 @@ Xquantity Reference =================== .. ditaa:: + :--scale: 0.85 +----------------+---------------+ - | quantity |cYEL xquantity | + | quantity |cBLU xquantity | +----------------+---------------+ | scaled_unit | +--------------------------------+ diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 41c95a8..42c20ac 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -7,3 +7,4 @@ add_subdirectory(ex6) add_subdirectory(ex7) add_subdirectory(ex8) add_subdirectory(ex_su) +add_subdirectory(ex_qty) diff --git a/example/ex8/ex8.cpp b/example/ex8/ex8.cpp index ba5113a..30d303f 100644 --- a/example/ex8/ex8.cpp +++ b/example/ex8/ex8.cpp @@ -8,11 +8,12 @@ int main () { using namespace xo::qty; namespace u = xo::qty::u; - //namespace q = xo::qty::qty; using namespace std; - xquantity qty1(7, u::foot); - xquantity qty2(6.0, u::inch); + constexpr xquantity qty1(7, u::foot); + constexpr xquantity qty2(6.0, u::inch); + + // constexpr not supported for xquantity addition xquantity qty3 = qty1 + qty2; cerr << "qty1: " << qty1 << endl; @@ -24,6 +25,13 @@ main () { /* 2286mm */ cerr << "res: " << res << endl; + + /* 12 */ + xquantity qty4 = qty1 / qty2; + + auto res2 = qty4 + 4; + + cerr << "res2: " << res << endl; } /** end ex8.cpp */ diff --git a/example/ex_qty/CMakeLists.txt b/example/ex_qty/CMakeLists.txt new file mode 100644 index 0000000..5da961a --- /dev/null +++ b/example/ex_qty/CMakeLists.txt @@ -0,0 +1,12 @@ +# xo-unit/example/ex_qty/CMakeLists.txt + +set(SELF_EXE xo_unit_ex_qty) +set(SELF_SRCS ex_qty.cpp) + +if (XO_ENABLE_EXAMPLES) + xo_add_executable(${SELF_EXE} ${SELF_SRCS}) + xo_self_headeronly_dependency(${SELF_EXE} xo_unit) + xo_dependency(${SELF_EXE} xo_flatstring) +endif() + +# end CMakeLists.txt diff --git a/example/ex_qty/ex_qty.cpp b/example/ex_qty/ex_qty.cpp new file mode 100644 index 0000000..b9c9a08 --- /dev/null +++ b/example/ex_qty/ex_qty.cpp @@ -0,0 +1,18 @@ +/* @file ex_qty.cpp */ + +#include "xo/unit/quantity.hpp" +#include "xo/unit/quantity_iostream.hpp" + +using namespace std; + +int +main() { + using namespace xo::qty; + namespace u = xo::qty::u; + + static_assert(u::meter.n_bpu() == 1); + + //constexpr auto q = qty::meters(2) + u::meter; +} + +/* end ex_qty.cpp */ diff --git a/include/xo/unit/mpl/quantity.hpp b/include/xo/unit/mpl/quantity.hpp index 1897e96..c58ba08 100644 --- a/include/xo/unit/mpl/quantity.hpp +++ b/include/xo/unit/mpl/quantity.hpp @@ -399,7 +399,7 @@ namespace xo { } ///@} - /** @defgroup quantity-arithmetic **/ + /** @defgroup mpl-quantity-arithmetic **/ ///@{ /** @brief add quantity in-place * diff --git a/include/xo/unit/quantity.hpp b/include/xo/unit/quantity.hpp index 96078c4..2691e23 100644 --- a/include/xo/unit/quantity.hpp +++ b/include/xo/unit/quantity.hpp @@ -8,6 +8,7 @@ #include "quantity_ops.hpp" #include "natural_unit.hpp" #include "scaled_unit.hpp" +#include "scaled_unit_concept.hpp" namespace xo { namespace qty { @@ -70,22 +71,40 @@ namespace xo { /** @defgroup quantity-access-methods quantity access methods **/ ///@{ + /** @brief value of @c scale_ in quantity representing amount (@c scale_ * @c s_unit) **/ constexpr const repr_type & scale() const { return scale_; } + /** @brief s_unit in quantity representing amount (@c scale_ * @c s_unit) **/ constexpr const unit_type & unit() const { return s_scaled_unit; } /** @brief true iff this quantity represents a dimensionless value **/ - constexpr bool is_dimensionless() const { + static constexpr bool is_dimensionless() { return s_scaled_unit.is_dimensionless(); } - ///@} - // unit_qty - // zero_qty + /** abbreviated suffix for quantities with this unit **/ + constexpr nu_abbrev_type abbrev() const { + return s_scaled_unit.natural_unit_.abbrev(); + } + + ///@} /** @defgroup quantity-arithmetic-support **/ ///@{ + + /** create unit quantity with same unit as @c this **/ + constexpr + auto unit_qty() const { + return quantity(1); + } + + /** create zero quantity with same unit as @c this **/ + constexpr + auto zero_qty() const { + return quantity(0); + } + constexpr auto reciprocal() const { return quantity(x * this->scale_); } - // divide_by - // divide_into + /** create quantity representing this quantity divided by dimensionless value @p x + * + * @pre x must be an arithmetic type such as @c int or @c double + **/ + template + requires std::is_arithmetic_v + constexpr auto divide_by(Dimensionless x) const { + using r_repr_type = std::common_type_t; + + return quantity(this->scale_ / x); + } + + /** create quantity representing dimensionless value @x divided by this quantity + * + * @pre x must be an arithmetic type such as @c int or @c double + **/ + template + requires std::is_arithmetic_v + constexpr auto divide_into(Dimensionless x) const { + using r_repr_type = std::common_type_t; + + return quantity(static_cast(x) / this->scale_, + s_scaled_unit.reciprocal()); + } - // divide - // add - // subtract + ///@} /** @defgroup quantity-comparison-support **/ ///@{ + /** compare two @c quantity instances, under three-way comparison **/ template static constexpr @@ -188,18 +231,43 @@ namespace xo { return x.scale() <=> y2.scale(); } + ///@} - // operator- - // operator+= - // operator-= + /** @defgroup quantity-operators **/ + ///@{ + + /** unary negation; preserves unit information **/ + quantity operator-() const { + return quantity(-scale_); + } + + /** add @p y in-place, converting units if necessary **/ + template + constexpr + quantity & operator+=(const Quantity2 & y) { + quantity y2 = y.template rescale_ext(); + + this->scale_ += y2.scale(); + + return *this; + } + + /** subtract @p y in-place, converting units if necessary **/ + template + constexpr + quantity & operator-=(const Quantity2 & y) { + quantity y2 = y.template rescale_ext(); + + this->scale_ -= y2.scale(); + + return *this; + } + // operator*= // operator/= - /** **/ - constexpr nu_abbrev_type abbrev() const { - return s_scaled_unit.natural_unit_.abbrev(); - } + ///@} /** @defgroup quantity-assignment quantity assignment operators **/ ///@{ @@ -429,6 +497,9 @@ namespace xo { return x.template with_repr(); } + /** @addtogroup quantity-operators **/ + ///@{ + /** note: won't have constexpr result w/ fractional dimension until c++26 (when ::sqrt(), ::pow() are constexpr) **/ template @@ -442,7 +513,27 @@ namespace xo { return detail::quantity_util::multiply(x, y); } - /** note: won't have constexpr result w/ fractional dimension until c++26 (when ::sqrt(), ::pow() are constexpr) + /** note: does not require unit scaling, so constexpr with c++23 **/ + template + requires std::is_arithmetic_v && quantity_concept + constexpr auto + operator* (const Quantity & x, Dimensionless y) + { + return x.scale_by(y); + } + + /** note: does not require unit scaling, so constexpr with c++23 **/ + template + requires std::is_arithmetic_v && quantity_concept + constexpr auto + operator* (Dimensionless x, const Quantity & y) + { + return y.scale_by(x); + } + + /** divide quantity @p x by quantity @p y. + * + * note: won't have constexpr result w/ fractional dimension until c++26 (when ::sqrt(), ::pow() are constexpr) **/ template requires (quantity_concept @@ -455,7 +546,30 @@ namespace xo { return detail::quantity_util::divide(x, y); } - /** note: won't have constexpr result w/ fractional dimension until c++26 (when ::sqrt(), ::pow() are constexpr) + /** divide quantity @p x by dimensionless value @p y **/ + template + requires std::is_arithmetic_v && quantity_concept + constexpr auto + operator/ (const Quantity & x, Dimensionless y) + { + return x.divide_by(y); + } + + /** divide dimensionless value @p x by quantity @p y **/ + template + requires std::is_arithmetic_v && quantity_concept + constexpr auto + operator/ (Dimensionless x, const Quantity & y) + { + return y.divide_into(x); + } + + /** add quantity @p y to quantity @p x. Result will have the same units as @p x. + * Representation will be the widest of {@c x::repr_type, @c y::repr_type}. + * + * note: won't have constexpr result w/ fractional dimension until c++26 (when ::sqrt(), ::pow() are constexpr) + * + * @pre @p x and @p y expected to have consistent dimensions **/ template requires (quantity_concept @@ -468,7 +582,46 @@ namespace xo { return detail::quantity_util::add(x, y); } - /** note: won't have constexpr result w/ fractional dimension until c++26 (when ::sqrt(), ::pow() are constexpr) + /** subtract an arithmetic value from a dimensionless quantity **/ + template + requires (quantity_concept + && Quantity::is_dimensionless() + && std::is_arithmetic_v) + constexpr auto + operator+ (const Quantity & x, Dimensionless y) + { + using repr_type = std::common_type_t; + + auto xp = static_cast(x.scale()); + auto yp = static_cast(y); + + return xp + yp; + } + + /** subtract a dimensionless quantity from an arithmetic value **/ + template + requires (std::is_arithmetic_v + && quantity_concept + && Quantity::is_dimensionless()) + constexpr auto + operator+ (Dimensionless x, const Quantity & y) + { + using repr_type = std::common_type_t; + + auto xp = static_cast(x); + auto yp = static_cast(y.scale()); + + return xp + yp; + } + + /** subtract quantity @p y from quantity @p x. Result will have the same units as @p x. + * Representation will be the widest of {@c x::repr_type, @c y::repr_type} + * + * note: won't have constexpr result w/ fractional dimension until c++26 (when ::sqrt(), ::pow() are constexpr) + * + * @pre @p x and @p y expected to have consistent dimensions **/ template requires (quantity_concept @@ -481,6 +634,8 @@ namespace xo { return detail::quantity_util::subtract(x, y); } + ///@} + namespace qty { // ----- mass ----- @@ -528,22 +683,26 @@ namespace xo { namespace qty { // ----- mass constants ---- - /** @brief a quantity representing 1 picogram of mass, with compile-time unit representation **/ + /** a quantity representing 1 picogram of mass, with compile-time unit representation **/ static constexpr auto picogram = picograms(1); - /** @brief a quantity representing 1 nanogram of mass, with compile-time unit representation **/ + /** a quantity representing 1 nanogram of mass, with compile-time unit representation **/ static constexpr auto nanogram = nanograms(1); - /** @brief a quantity representing 1 microgram of mass, with compile-time unit representation **/ + /** a quantity representing 1 microgram of mass, with compile-time unit representation **/ static constexpr auto microgram = micrograms(1); - /** @brief a quantity representing 1 milligram of mass, with compile-time unit representation **/ + /** a quantity representing 1 milligram of mass, with compile-time unit representation **/ static constexpr auto milligram = milligrams(1); - /** @brief a quantity representing 1 gram of mass, with compile-time unit representation **/ + /** a quantity representing 1 gram of mass, with compile-time unit representation **/ static constexpr auto gram = grams(1); - /** @brief a quantity representing 1 kilogram of mass, with compile-time unit representation **/ + /** a quantity representing 1 kilogram of mass, with compile-time unit representation **/ static constexpr auto kilogram = kilograms(1); - /** @brief a quantity representing 1 metric tonne of mass, with compile-time unit representation **/ + /** a quantity representing 1 metric tonne of mass, with compile-time unit representation **/ static constexpr auto tonne = tonnes(1); - /** @brief a quantity representing 1 metric kilotonne of mass, with compile-time unit representation **/ + /** a quantity representing 1 metric kilotonne of mass, with compile-time unit representation **/ static constexpr auto kilotonne = kilotonnes(1); + /** a quantity representing 1 metric megatonne of mass, with compile-time unit representation **/ + static constexpr auto megatonne = megatonnes(1); + /** a quantity representing 1 metric gigatonne of mass, with compile-time unit representation **/ + static constexpr auto gigatonne = gigatonnes(1); } /*namespace qty*/ namespace qty { @@ -618,22 +777,37 @@ namespace xo { static constexpr auto nanometer = nanometers(1); /** a quantity representing 1 micrometer of distance, with compile-time unit representation **/ static constexpr auto micrometer = micrometers(1); - /** @brief a quantity representing 1 millimeter of distance, with compile-time unit representation **/ + /** a quantity representing 1 millimeter of distance, with compile-time unit representation **/ static constexpr auto millimeter = millimeters(1); - /** @brief a quantity representing 1 meter of distance, with compile-time unit representation **/ + /** a quantity representing 1 meter of distance, with compile-time unit representation **/ static constexpr auto meter = meters(1); - /** @brief a quantity representing 1 kilometer of distance, with compile-time unit representation **/ + /** a quantity representing 1 kilometer of distance, with compile-time unit representation **/ static constexpr auto kilometer = kilometers(1); - /** @brief a quantity representing 1 megameter of distance, with compile-time unit representation **/ + /** a quantity representing 1 megameter of distance, with compile-time unit representation **/ static constexpr auto megameter = megameters(1); - /** @brief a quantity representing 1 gigameter of distance, with compile-time unit representation **/ + /** a quantity representing 1 gigameter of distance, with compile-time unit representation **/ static constexpr auto gigameter = gigameters(1); - /** @brief a quantity representing exactly 1 lightsecond of distance, with compile-time unit representation **/ + /** a quantity representing exactly 1 lightsecond of distance, + * with compile-time unit representation + **/ static constexpr auto lightsecond = lightseconds(1); - /** @brief a quantity representing exactly 1 astronomical unit of distance, with compile-time unit representation **/ + /** a quantity representing exactly 1 astronomical unit of distance, + * with compile-time unit representation + **/ static constexpr auto astronomicalunit = astronomicalunits(1); + /** a quantity representing 1 inch of distance, with compile-time unit operations **/ + static constexpr auto inch = inches(1); + + /** a quantity representing 1 foot of distance, with compile-time unit operations **/ + static constexpr auto foot = feet(1); + + /** a quantity representing 1 yard of distance, with compile-time unit operations **/ + static constexpr auto yard = yards(1); + + /** a quantity representing 1 mile of distance, with compile-time unit operations **/ + static constexpr auto mile = miles(1); } /*namespace qty*/ namespace qty { @@ -707,17 +881,48 @@ namespace xo { namespace qty { // ----- time constants ---- - /** @brief a quantity representing 1 second of time, with compile-time unit representation **/ + /** a quantity representing 1 picosecond of time, with compile-time unit representation **/ + static constexpr auto picosecond = picoseconds(1); + + /** a quantity representing 1 nanosecond of time, with compile-time unit representation **/ + static constexpr auto nanosecond = nanoseconds(1); + + /** a quantity representing 1 microsecond of time, with compile-time unit representation **/ + static constexpr auto microsecond = microseconds(1); + + /** a quantity representing 1 millisecond of time, with compile-time unit representation **/ + static constexpr auto millisecond = milliseconds(1); + + /** a quantity representing 1 second of time, with compile-time unit representation **/ static constexpr auto second = seconds(1); - /** @brief a quantity representing 1 minute of time, with compile-time unit representation **/ + /** a quantity representing 1 minute of time, with compile-time unit representation **/ static constexpr auto minute = minutes(1); - /** @brief a quantity representing 1 hour of time, with compile-time unit representation **/ + /** a quantity representing 1 hour of time, with compile-time unit representation **/ static constexpr auto hour = hours(1); - /** @brief a quantity representing 1 day of time (exactly 24 hours), with compile-time unit representation **/ + /** a quantity representing 1 day of time (exactly 24 hours), with compile-time unit representation **/ static constexpr auto day = days(1); + + /** a quantity representing 1 week of time (7 24-hour days), with compile-time unit representation **/ + static constexpr auto week = weeks(1); + + /** a quantity representing 1 month of time (30 24-hour days), with compile-time unit representation **/ + static constexpr auto month = months(1); + + /** a quantity representing 1 year of time (365.25 24-hour days), with compile-time unit representation **/ + static constexpr auto year = years(1); + + /** a quantity representing 1 250-day year of time, with compile-time unit representation **/ + static constexpr auto year250 = year250s(1); + + /** a quantity representing 1 360-day year of time, with compile-time unit representation **/ + static constexpr auto year360 = year360s(1); + + /** a quantity representing 1 365-day year of time, with compile-time unit representation **/ + static constexpr auto year365 = year365s(1); + } /*namespace qty*/ namespace qty { diff --git a/include/xo/unit/quantity_ops.hpp b/include/xo/unit/quantity_ops.hpp index 8fa532c..8f13402 100644 --- a/include/xo/unit/quantity_ops.hpp +++ b/include/xo/unit/quantity_ops.hpp @@ -9,24 +9,45 @@ namespace xo { namespace qty { - /** note: does not require unit scaling, so constexpr with c++23 **/ - template - requires std::is_arithmetic_v && quantity_concept + /** @defgroup quantity-dimensionless-operators **/ + ///@{ + + /** subtract an arithmetic value from a dimensionless quantity **/ + template + requires (quantity_concept + && Quantity::is_dimensionless() + && std::is_arithmetic_v) constexpr auto - operator* (Dimensionless x, const Quantity & y) + operator- (const Quantity & x, Dimensionless y) { - return y.scale_by(x); + using repr_type = std::common_type_t; + + auto xp = static_cast(x.scale()); + auto yp = static_cast(y); + + return xp - yp; } - /** note: does not require unit scaling, so constexpr with c++23 **/ - template - requires std::is_arithmetic_v && quantity_concept + /** subtract a dimensionless quantity from an arithmetic value **/ + template + requires (std::is_arithmetic_v + && quantity_concept + && Quantity::is_dimensionless()) constexpr auto - operator* (const Quantity & x, Dimensionless y) + operator- (Dimensionless x, const Quantity & y) { - return x.scale_by(y); + using repr_type = std::common_type_t; + + auto xp = static_cast(x); + auto yp = static_cast(y.scale()); + + return xp - yp; } + ///@} + /** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr) **/ template diff --git a/include/xo/unit/scaled_unit.hpp b/include/xo/unit/scaled_unit.hpp index fa9320f..0be1660 100644 --- a/include/xo/unit/scaled_unit.hpp +++ b/include/xo/unit/scaled_unit.hpp @@ -44,6 +44,9 @@ namespace xo { /** @defgroup scaled-unit-access-methods scaled-unit access methods **/ ///@{ + /** always true for scaled_unit **/ + static constexpr bool is_scaled_unit_type_v = true; + /** always true for scaled_unit **/ constexpr bool is_scaled_unit_type() const { return true; } diff --git a/include/xo/unit/scaled_unit_concept.hpp b/include/xo/unit/scaled_unit_concept.hpp new file mode 100644 index 0000000..f05a050 --- /dev/null +++ b/include/xo/unit/scaled_unit_concept.hpp @@ -0,0 +1,23 @@ +/** @file scaled_unit_concept.hpp **/ + +#pragma once + +#include + +namespace xo { + namespace qty { + template + concept scaled_unit_concept = requires(ScaledUnit su) + { + typename ScaledUnit::ratio_int_type; + + { su.is_scaled_unit_type() } -> std::same_as; + { su.is_natural() } -> std::same_as; + { su.is_dimensionless() } -> std::same_as; + + } && ScaledUnit::is_scaled_unit_type_v; + } /*namespace qty*/ +} /*namespace xo*/ + + +/** end scaled_unit_concept.hpp **/ diff --git a/include/xo/unit/xquantity.hpp b/include/xo/unit/xquantity.hpp index 91fa74c..40ada9d 100644 --- a/include/xo/unit/xquantity.hpp +++ b/include/xo/unit/xquantity.hpp @@ -18,7 +18,7 @@ namespace xo { * * Constexpr implementation, but units are explicitly represented: * @code - * sizeof(Quantity2) > sizeof(Repr) + * sizeof(xquantity) > sizeof(xquantity::repr_type) * @endcode * * Explicit unit representation allows introducing units at runtime, @@ -32,22 +32,47 @@ namespace xo { * - Repr supports conversion from double. **/ template > + typename Int = std::int64_t> class xquantity { public: + /** @defgroup xquantity-type-traits xquantity type traits **/ + ///@{ + /** @brief runtime representation for this value's scale **/ using repr_type = Repr; + /** @brief runtime representation for this value's unit **/ using unit_type = natural_unit; + /** @brief type used for numerator and denominator in basis-unit scalefactor ratios **/ using ratio_int_type = Int; - using ratio_int2x_type = Int2x; + /** @brief double-width type for numerator and denominator of intermediate + * scalefactor ratios. Use to mitigate loss of precision during computation + * of conversion factors between units with widely-differing magnitude + **/ + using ratio_int2x_type = detail::width2x_t; + ///@} public: - /* zero, dimensionless */ + /** @defgroup xquantity-ctors xquantity constructors **/ + ///@{ + + /** create dimensionless, zero quantity **/ constexpr xquantity() : scale_{0}, unit_{natural_unit()} {} + /** create quantity representing multiple of @p scale times @p unit **/ constexpr xquantity(Repr scale, const natural_unit & unit) : scale_{scale}, unit_{unit} {} + /** create quantity representing multiple of @p scale times @p unit. + * + * Collects outer scalefactors (if any) from @p unit, + * so for example: + * + * @code + * using namespace xo::qty; + * xquantity q(123, u::meter * u::millimeter); + * + * q.scale() --> 0.123 + * @endcode + **/ constexpr xquantity(Repr scale, const scaled_unit & unit) : @@ -59,17 +84,39 @@ namespace xo { ), unit_{unit.natural_unit_} {} + ///@} + static constexpr bool always_constexpr_unit = false; + /** @defgroup xquantity-access-methods xquantity access methods **/ + ///@{ + + /** get member @ref scale_ **/ constexpr const repr_type & scale() const { return scale_; } + /** get member @ref unit_ **/ constexpr const unit_type & unit() const { return unit_; } + /** true iff this quantity has no dimension **/ constexpr bool is_dimensionless() const { return unit_.is_dimensionless(); } + /** return abbreviation for quantities with this unit **/ + constexpr nu_abbrev_type abbrev() const { return unit_.abbrev(); } + + ///@} + + /** @defgroup xquantity-methods xquantity methods **/ + ///@{ + + /** create unit quantity with same unit as @c this **/ constexpr xquantity unit_qty() const { return xquantity(1, unit_); } + + /** create zero quantity with same unit as @c this **/ constexpr xquantity zero_qty() const { return xquantity(0, unit_); } + + /** create quantity representing reciprocal of @c this **/ constexpr xquantity reciprocal() const { return xquantity(1.0 / scale_, unit_.reciprocal()); } + /** create quantity representing the same value, but in units of @p unit2 **/ constexpr auto rescale(const natural_unit & unit2) const { /* conversion factor from .unit -> unit2*/ @@ -86,24 +133,28 @@ namespace xo { } } + /** create quantity representing this value scaled by dimensionless mutliplier @p x **/ template requires std::is_arithmetic_v constexpr auto scale_by(Dimensionless x) const { return xquantity(x * this->scale_, this->unit_); } + /** create quantity representing this value scaled by dimensionless multiplier @p 1/x **/ template requires std::is_arithmetic_v constexpr auto divide_by(Dimensionless x) const { return xquantity(this->scale_ / x, this->unit_); } + /** create quantity representing dimensionless numerator @p x divided by this value **/ template requires std::is_arithmetic_v constexpr auto divide_into(Dimensionless x) const { return xquantity(x / this->scale_, this->unit_.reciprocal()); } + /** multiply two @c xquantity values, or a mixed (@c xquantity, @c quantity) pair **/ template static constexpr auto multiply(const xquantity & x, const Quantity2 & y) { @@ -125,6 +176,7 @@ namespace xo { rr.natural_unit_); } + /** compute quotient @p x / @p y, where @p x and @p y are xquantities **/ template static constexpr auto divide(const xquantity & x, const Quantity2 & y) { @@ -149,6 +201,7 @@ namespace xo { rr.natural_unit_); } + /** compute sum @p x + @p y, where @p x and @p y are xquantities **/ template static constexpr auto add(const xquantity & x, const Quantity2 & y) { @@ -176,6 +229,7 @@ namespace xo { } } + /** compute difference @p x - @p y, where @p x and @p y are xquantities **/ template static constexpr auto subtract(const xquantity & x, const Quantity2 & y) { @@ -203,6 +257,7 @@ namespace xo { } } + /** perform 3-way comparison between @c xquantity values @p x and @p y **/ template static constexpr auto compare(const xquantity & x, const Quantity2 & y) { @@ -211,6 +266,10 @@ namespace xo { return x.scale() <=> y2.scale(); } + ///@} + + /** @defgroup xquantity-operators xquantity operators **/ + ///@{ xquantity operator-() const { return xquantity(-scale_, unit_); } @@ -228,16 +287,20 @@ namespace xo { *this = *this / x; return *this; } + ///@} // TODO: operator+=, operator-= - constexpr nu_abbrev_type abbrev() const { return unit_.abbrev(); } - private: - /** @brief quantity represents this multiple of a unit amount **/ + /** @defgroup xquantity-instance-vars **/ + ///@{ + + /** quantity represents this multiple of a unit amount **/ Repr scale_ = Repr{}; - /** @brief unit for this quantity **/ + /** unit for this quantity **/ natural_unit unit_; + + ///@} }; /*xquantity*/ /** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr) @@ -273,6 +336,26 @@ namespace xo { return Q1::multiply(x, y); } + /** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr) + **/ + template + requires quantity_concept + constexpr auto + operator* (double x, const Quantity & y) + { + return y.scale_by(x); + } + + /** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr) + **/ + template + requires quantity_concept + constexpr auto + operator* (const Quantity & x, double y) + { + return x.scale_by(y); + } + /** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr) **/ template @@ -334,7 +417,8 @@ namespace xo { /** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr) **/ template - requires quantity_concept && quantity_concept + requires (quantity_concept + && quantity_concept) constexpr auto operator- (const Quantity & x, const Quantity2 & y) {