From 07bfe2d0364f817ecf25d46a779c24d2c8a1cd8d Mon Sep 17 00:00:00 2001 From: tehforsch Date: Sun, 25 Feb 2024 14:44:38 +0100 Subject: [PATCH] update docs --- README.md | 52 ++++++++++++++++-------------------------------- src/lib.rs | 58 +++++++++++++++++------------------------------------- 2 files changed, 35 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index 7041fad..38576d4 100644 --- a/README.md +++ b/README.md @@ -168,8 +168,11 @@ let time: Time = 1.0 * seconds; assert_eq!(format!("{:?}", length / time), "5000 m s^-1") ``` -# Design - For example, in order to represent the [SI system of units](https://www.nist.gov/pml/owm/metric-si/si-units), the quantity type would be defined using the `unit_system!` macro as follows: +# Custom unit systems +## The `unit_system` macro +Diman also provides the `unit_system` macro for defining custom +unit systems for everything that is not covered by SI alone. +As an example, consider the following macro call: ```rust diman::unit_system!( quantity_type Quantity; @@ -178,26 +181,10 @@ diman::unit_system!( dimension Length; dimension Time; dimension Mass; - dimension Temperature; - dimension Current; - dimension AmountOfSubstance; - dimension LuminousIntensity; -); -``` -The first two statements imply that the macro should define a `Quantity` type, which is user-facing, and a `Dimension` type, which is used only internally and will surface in compiler error messages. -The macro will automatically implement all the required traits and methods for the `Quantity` type, such that addition and subtraction of two quantities is only allowed for quantities with the same `Dimension` type. During multiplication of two quantities, all the entries of the two dimensions are added. See below for a more comprehensive list of the implemented methods on `Quantity`. - -The `unit_system!` macro also allows defining derived dimensions and units: - -```rust -diman::unit_system!( - quantity_type Quantity; - dimension_type Dimension; - - dimension Length; - dimension Time; dimension Velocity = Length / Time; + dimension Frequency = 1 / Time; + dimension Energy = Mass * Velocity^2; #[prefix(kilo, milli)] #[base(Length)] @@ -211,28 +198,23 @@ diman::unit_system!( unit hours: Time = 3600 * seconds; unit meters_per_second: Velocity = meters / seconds; unit kilometers_per_hour: Velocity = kilometers / hours; - constant MY_FAVORITE_VELOCITY = 1000 * kilometers_per_hour; + constant SPEED_OF_LIGHT = 299792458 * meters_per_second; ); -fn fast_enough(x: Length, t: Time) { - let vel = x / t; - if vel > 1.0 * MY_FAVORITE_VELOCITY { - println!("{} m/s is definitely fast enough!", vel.value_in(meters_per_second)); - } +fn too_fast(x: Length, t: Time) -> bool { + x / t > 0.1f64 * SPEED_OF_LIGHT } -fast_enough(100.0 * kilometers, 0.3 * hours); +too_fast(100.0 * kilometers, 0.3 * hours); ``` -Here, `dimension` defines Quantities, which are concrete types, `unit` defines units, which are methods on the corresponding quantities and `constant` defines constants. -Dimensions without a right hand side are base dimensions (such as length, time, mass, temperature, ... in the SI system of units), whereas dimensions with a right hand side are derived dimensions. -The same thing holds for units - every unit is either a base unit for a given base dimension (denoted by the `#[base(...)]` attribute), or derived from base units and other derived units. Base units have the special property that the internal representation of the quantity will be in terms of the base unit (for example, a stored value `1.0` for a quantity with a `Length` dimension corresponds to `meter` in the above definitions). -Other than this, there are no differences between base dimensions and dimensions or base units and units and they can be treated equally in user code. -The macro also accepts more complex expressions such as `dimension Energy = Mass (Length / Time)^2`. -The definitions do not have to be in any specific order. +The macro accepts three different keywords: +1. `dimension` defines a new dimension which is a type. Dimensions without a right hand side are base dimensions (such as `Length` and `Time` in this example), whereas dimensions with a right hand side are derived dimensions (such as `Velocity` in this example). +2. `unit` defines a new units, which are methods on the corresponding quantities and `constant` defines constants. Units without a right-hand side are the base units to one specific base dimension, meaning that they are the unit that will internally be represented with a conversion factor of 1. Base units require the `#[base(...)]` attribute in order to specify which dimension they are the base unit of. Units with a right hand side are derived from other units. +3. `constant` defines a new constant. -# Prefixes +## Prefixes Unit prefixes can automatically be generated with the `#[prefix(...)]` attribute for unit statements. For example ```rust @@ -244,7 +226,7 @@ unit meters; will automatically generate the unit `meters` with symbol `m`, as well as `kilometers` and `millimeters` with symbols `km` and `mm` corresponding to `1e3 m` and `1e-3 m`. For simplicity, the attribute `#[metric_prefixes]` is provided, which will generate all metric prefixes from `atto-` to `exa-` automatically. -# Aliases +## Aliases Unit aliases can automatically be generated with the `#[alias(...)]` macro. For example ```rust #[alias(metres)] diff --git a/src/lib.rs b/src/lib.rs index 5b4db95..5f78762 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -207,8 +207,11 @@ //! assert_eq!(format!("{:?}", length / time), "5000 m s^-1") //! ``` //! -//! # Design -//! For example, in order to represent the [SI system of units](https://www.nist.gov/pml/owm/metric-si/si-units), the quantity type would be defined using the `unit_system!` macro as follows: +//! # Custom unit systems +//! ## The `unit_system` macro +//! Diman also provides the `unit_system` macro for defining custom +//! unit systems for everything that is not covered by SI alone. +//! As an example, consider the following macro call: //! ``` //! # #![allow(incomplete_features)] //! # #![feature(generic_const_exprs, adt_const_params)] @@ -220,30 +223,10 @@ //! dimension Length; //! dimension Time; //! dimension Mass; -//! dimension Temperature; -//! dimension Current; -//! dimension AmountOfSubstance; -//! dimension LuminousIntensity; -//! ); -//! # } -//! ``` -//! The first two statements imply that the macro should define a `Quantity` type, which is user-facing, and a `Dimension` type, which is used only internally and will surface in compiler error messages. -//! The macro will automatically implement all the required traits and methods for the `Quantity` type, such that addition and subtraction of two quantities is only allowed for quantities with the same `Dimension` type. During multiplication of two quantities, all the entries of the two dimensions are added. See below for a more comprehensive list of the implemented methods on `Quantity`. -//! -//! The `unit_system!` macro also allows defining derived dimensions and units: -//! -//! ``` -//! # #![allow(incomplete_features)] -//! # #![feature(generic_const_exprs, adt_const_params)] -//! # mod surround { -//! diman::unit_system!( -//! quantity_type Quantity; -//! dimension_type Dimension; -//! -//! dimension Length; -//! dimension Time; //! //! dimension Velocity = Length / Time; +//! dimension Frequency = 1 / Time; +//! dimension Energy = Mass * Velocity^2; //! //! #[prefix(kilo, milli)] //! #[base(Length)] @@ -257,32 +240,27 @@ //! unit hours: Time = 3600 * seconds; //! unit meters_per_second: Velocity = meters / seconds; //! unit kilometers_per_hour: Velocity = kilometers / hours; -//! constant MY_FAVORITE_VELOCITY = 1000 * kilometers_per_hour; +//! constant SPEED_OF_LIGHT = 299792458 * meters_per_second; //! ); //! # } //! //! # use surround::dimensions::{Length, Time, Velocity}; //! # use surround::units::{meters_per_second,kilometers,hours}; -//! # use surround::constants::MY_FAVORITE_VELOCITY; +//! # use surround::constants::SPEED_OF_LIGHT; //! -//! fn fast_enough(x: Length, t: Time) { -//! let vel = x / t; -//! if vel > 1.0 * MY_FAVORITE_VELOCITY { -//! println!("{} m/s is definitely fast enough!", vel.value_in(meters_per_second)); -//! } +//! fn too_fast(x: Length, t: Time) -> bool { +//! x / t > 0.1f64 * SPEED_OF_LIGHT //! } //! -//! fast_enough(100.0 * kilometers, 0.3 * hours); +//! too_fast(100.0 * kilometers, 0.3 * hours); //! ``` //! -//! Here, `dimension` defines Quantities, which are concrete types, `unit` defines units, which are methods on the corresponding quantities and `constant` defines constants. -//! Dimensions without a right hand side are base dimensions (such as length, time, mass, temperature, ... in the SI system of units), whereas dimensions with a right hand side are derived dimensions. -//! The same thing holds for units - every unit is either a base unit for a given base dimension (denoted by the `#[base(...)]` attribute), or derived from base units and other derived units. Base units have the special property that the internal representation of the quantity will be in terms of the base unit (for example, a stored value `1.0` for a quantity with a `Length` dimension corresponds to `meter` in the above definitions). -//! Other than this, there are no differences between base dimensions and dimensions or base units and units and they can be treated equally in user code. -//! The macro also accepts more complex expressions such as `dimension Energy = Mass (Length / Time)^2`. -//! The definitions do not have to be in any specific order. +//! The macro accepts three different keywords: +//! 1. `dimension` defines a new dimension which is a type. Dimensions without a right hand side are base dimensions (such as `Length` and `Time` in this example), whereas dimensions with a right hand side are derived dimensions (such as `Velocity` in this example). +//! 2. `unit` defines a new units, which are methods on the corresponding quantities and `constant` defines constants. Units without a right-hand side are the base units to one specific base dimension, meaning that they are the unit that will internally be represented with a conversion factor of 1. Base units require the `#[base(...)]` attribute in order to specify which dimension they are the base unit of. Units with a right hand side are derived from other units. +//! 3. `constant` defines a new constant. //! -//! # Prefixes +//! ## Prefixes //! Unit prefixes can automatically be generated with the `#[prefix(...)]` attribute for unit statements. //! For example //! ``` @@ -303,7 +281,7 @@ //! will automatically generate the unit `meters` with symbol `m`, as well as `kilometers` and `millimeters` with symbols `km` and `mm` corresponding to `1e3 m` and `1e-3 m`. //! For simplicity, the attribute `#[metric_prefixes]` is provided, which will generate all metric prefixes from `atto-` to `exa-` automatically. //! -//! # Aliases +//! ## Aliases //! Unit aliases can automatically be generated with the `#[alias(...)]` macro. For example //! ``` //! # #![allow(incomplete_features)]