diff --git a/au/BUILD.bazel b/au/BUILD.bazel index 27a89d48..1ee74f1f 100644 --- a/au/BUILD.bazel +++ b/au/BUILD.bazel @@ -25,7 +25,9 @@ cc_library( deps = [ ":chrono_interop", ":constant", + ":constants", ":math", + ":units", ], ) diff --git a/docs/alternatives/index.md b/docs/alternatives/index.md index 5badf78e..e82c0d81 100644 --- a/docs/alternatives/index.md +++ b/docs/alternatives/index.md @@ -908,15 +908,12 @@ features. href="https://mpusz.github.io/mp-units/2.0/users_guide/framework_basics/faster_than_lightspeed_constants/">"Faster than lightspeed" constants - + diff --git a/docs/howto/index.md b/docs/howto/index.md index c3f07fbb..d8d4b046 100644 --- a/docs/howto/index.md +++ b/docs/howto/index.md @@ -6,6 +6,8 @@ using the library. Here's a summary of what you'll find. - **[New units](./new-units.md).** How to add a new unit of measure that the library doesn't include. +- **[New constants](./new-constants.md).** How to add a custom physical constant. + - **[New dimensions](./new-dimensions.md).** How to add a new, independent base dimension. - **[Inter-library Interoperation](./interop/index.md).** How to set up automatic correspondence diff --git a/docs/howto/new-constants.md b/docs/howto/new-constants.md new file mode 100644 index 00000000..d3060584 --- /dev/null +++ b/docs/howto/new-constants.md @@ -0,0 +1,83 @@ +# Defining new constants + +This page explains how to define new constants that aren't [included in the +library](../reference/constant.md#built-in). + +!!! tip + If you think it _should_ be included in the library, feel free to [file an + issue](https://github.com/aurora-opensource/au/issues): there's no harm in asking. + + In order for us to consider it, it should be relatively widely used. It also needs to have an + _exact_ value: we don't have a great way to deal with values that can change over time. + + If these conditions don't apply, then follow the directions in this guide to define a _custom_ + constant for your project. + +## Methods of definition + +There are two ways to define a new constant. The only difference is _whether you need a label_ for +your constant. In either case, you create a constant by calling `make_constant(...)`. The argument +is a [unit slot](../discussion/idioms/unit-slots.md), so you can pass it anything that goes into +a unit slot. + +### Ad hoc (no special label) + +Pass any ad hoc unit expression to the unit slot. The constant will produce correct results in +code, in every situation. It will even have _a_ label, which will identify it exactly. The label +will simply be cumbersome. + +!!! example "Example: speed of light in an ad hoc manner" + Here's how to create a constant for the speed of light, without giving it a special symbol. + + ```cpp + constexpr auto c = make_constant(meters / second * mag<299'792'458>()); + ``` + + Here's an example use case, in user code: + + ```cpp + std::cout << (0.8 * c) << std::endl; + ``` + + The above prints `"0.8 [299792458 m/s]"`. Notice how the unit label, `"[299792458 m/s]"`, is + _correct_, but _cumbersome_. + +### Full unit definition (includes custom label) + +First, follow a stripped down version of the [new unit instructions](./new-units.md) to define +a _unit_ for the constant. The only thing you need to give it is a _label_; you can omit the +instructions for quantity makers and so on. + +Next, pass an instance of this custom unit to `make_constant`. + +!!! example "Example: speed of light with full unit definition" + Here's how to create a constant for the speed of light using a full custom unit, with label. + + === "C++14" + ```cpp + // In `.hh` file: + struct SpeedOfLightUnit : decltype(Meters{} / Seconds{} * mag<299'792'458>()) { + static constexpr const char label[] = "c"; + }; + constexpr auto c = make_constant(SpeedOfLightUnit{}); + + // In `.cc` file: + constexpr const char SpeedOfLightUnit::label[]; + ``` + + === "C++17" + ```cpp + // In `.hh` file: + struct SpeedOfLightUnit : decltype(Meters{} / Seconds{} * mag<299'792'458>()) { + static constexpr inline const char label[] = "c"; + }; + constexpr auto c = make_constant(SpeedOfLightUnit{}); + ``` + + Here's an example use case, in user code: + + ```cpp + std::cout << (0.8 * c) << std::endl; + ``` + + The above prints `"0.8 c"`. diff --git a/docs/install.md b/docs/install.md index d14fe1ad..ccf5b453 100644 --- a/docs/install.md +++ b/docs/install.md @@ -120,7 +120,7 @@ to your `deps` attribute, and include the appropriate files. | Dependency | Headers provided | Notes | |------------|------------------|-------| -| `@au//au` | `"au/au.hh"`
`"au/fwd.hh"`
`"au/units/*.hh"`
`"au/units/*_fwd.hh"` | Core library functionality. See [all available units](https://github.com/aurora-opensource/au/tree/main/au/units) | +| `@au//au` | `"au/au.hh"`
`"au/fwd.hh"`
`"au/units/*.hh"`
`"au/units/*_fwd.hh"`
`"au/constants/*.hh"` | Core library functionality. See [all available units](https://github.com/aurora-opensource/au/tree/main/au/units) and [constants](./reference/constant.md#built-in) | | `@au//au:io` | `"au/io.hh"` | `operator<<` support | | `@au//au:testing` | `"au/testing.hh"` | Utilities for writing googletest tests
_Note:_ `testonly = True` | @@ -141,7 +141,7 @@ In either case, here are the main targets and include files provided by the Au l | Target | Headers provided | Notes | |--------|------------------|-------| -| `Au::au` | `"au/au.hh"`
`"au/fwd.hh"`
`"au/io.hh"`
`"au/units/*.hh"`
`"au/units/*_fwd.hh"` | Core library functionality. See [all available units](https://github.com/aurora-opensource/au/tree/main/au/units) | +| `Au::au` | `"au/au.hh"`
`"au/fwd.hh"`
`"au/io.hh"`
`"au/units/*.hh"`
`"au/units/*_fwd.hh"`
`"au/constants/*.hh"` | Core library functionality. See [all available units](https://github.com/aurora-opensource/au/tree/main/au/units) | | `Au::testing` | `"au/testing.hh"` | Utilities for writing googletest tests | !!! note @@ -336,7 +336,10 @@ Here's how: creates a file, `~/au.hh`, which packages the entire library in a single file with these three units. - To see the full list of available units, search the `.hh` files in the `au/units/` folder. For - example, `meters` will include the contents of `au/units/meters.hh`. + example, `meters` will include the contents of `"au/units/meters.hh"`. + - Similarly, to see the full list of available constants, search the `.hh` files in the + `au/constants/` folder. For example, `speed_of_light` will include the contents of + `"au/constants/speed_of_light.hh"`, which provides the constant `au::SPEED_OF_LIGHT`. - Provide the `--noio` flag if you prefer to avoid the expense of the `` library. Now you have a file, `~/au.hh`, which you can add to your `third_party` folder. diff --git a/docs/reference/constant.md b/docs/reference/constant.md index cc777e83..61b19b33 100644 --- a/docs/reference/constant.md +++ b/docs/reference/constant.md @@ -23,6 +23,45 @@ still store `5` under the hood. This approach means that if subsequent operations cancel out the constant, this cancellation is both _exact_ and has _zero runtime cost_. +## Built-in constants included with Au {#built-in} + +Au includes a number of built-in constants. Each constant is in its own include file, in the folder +`"au/constant"` --- for example, `"au/constant/speed_of_light.hh"`. + +The constant object itself is in the top-level `au::` namespace, and uses an UPPERCASE naming +convention, as with all other constants in the library --- for example, `au::SPEED_OF_LIGHT`. + +We spell out the constant name in full to avoid ambiguity. However, this can be overly verbose. We +encourage users to define their own copy of each constant, with a more usable name --- for example: + +```cpp +constexpr auto c = au::SPEED_OF_LIGHT; +``` + +This "copy" is essentially free, because the constant is a [monovalue +type](./detail/monovalue_types.md), and therefore empty. + +Here are the constants that we include with Au: + +| Name | Symbol | Value | Include (under `"au/constants/"`) | Object name (under `au::` namespace) | +| ---- | ------ | ----- | ------- | ----------- | +| Avogadro constant | $N_A$ | $6.022\,140\,76 \times 10^{23}\,\, \text{mol}^{-1}$ | `avogadro_constant.hh` | `AVOGADRO_CONSTANT` | +| Boltzmann constant | $k_B$ | $1.380\,649 \times 10^{-23}\,\, \text{J} / \text{K}$ | `boltzmann_constant.hh` | `BOLTZMANN_CONSTANT` | +| Cesium hyperfine transition frequency | $\Delta \nu_{Cs}$ | $9\,192\,631\,770\,\, \text{Hz}$ | `cesium_hyperfine_transition_frequency.hh` | `CESIUM_HYPERFINE_TRANSITION_FREQUENCY` | +| Elementary charge | $e$ | $1.602\,176\,634 \times 10^{-19}\,\, \text{C}$ | `elementary_charge.hh` | `ELEMENTARY_CHARGE` | +| Luminous efficacy of light at $540\,\, \text{THz}$ | $K_{cd}$ | $683\,\, \text{lm} / \text{W}$ | `luminous_efficacy_540_terahertz.hh` | `LUMINOUS_EFFICACY_540_TERAHERTZ` | +| Planck constant | $h$ | $6.626\,070\,15 \times 10^{-34}\,\, \text{J} \cdot \text{s}$ | `planck_constant.hh` | `PLANCK_CONSTANT` | +| Reduced Planck constant | $\hbar$ | $1.054\,571\,817 \times 10^{-34}\,\, \text{J} \cdot \text{s}$ | `reduced_planck_constant.hh` | `REDUCED_PLANCK_CONSTANT` | +| Speed of light | $c$ | $299\,792\,458\,\, \text{m} / \text{s}$ | `speed_of_light.hh` | `SPEED_OF_LIGHT` | + +Our policy is to include only exactly defined constants with the library. This rules out many +useful constants, such as the universal gravitational constant $G$, the _new_ (post-2019) permeability +of free space $\mu_0$, and so on. For these, we can't reasonably provide values that will satisfy +all users at all times. However, defining custom constants for your own project is straightforward, +as we explain in the next section, and in our [how-to guide for custom +constants](../howto/new-constants.md). + + ## Constructing `Constant` `Constant` encodes all information about the value in its type. Moreover, it has only a single diff --git a/docs/reference/detail/monovalue_types.md b/docs/reference/detail/monovalue_types.md index 89c8fc02..32c297a7 100644 --- a/docs/reference/detail/monovalue_types.md +++ b/docs/reference/detail/monovalue_types.md @@ -37,6 +37,7 @@ Here are some canonical examples in Au. | `Zero` | `ZERO` | Comparing to any `Quantity` | | `Magnitude<>` | `ONE` | | | `Radians` (and other units) | `Radians{}` (no special pre-formed instance) | Arithmetic with other units, such as `Radians{} / Meters{}` | +| `Constant<...>` | `SPEED_OF_LIGHT` | | ## Switching between types and values {#switching}