Expand description
Compile-time dimensional analysis via generic types.
The core of the crate is the Unit trait, which marks a struct or enum as
being a representation of a dimensional unit. Units may have multiple
variants, each with a different scaling factor.
The most important exported type is Quantity. A Quantity is generic
over Unit types and numeric Value types, and serves to pair a
dimensionless value with a dimensional unit. The default scalar type is
f64, but Value is automatically implemented for any type that
implements the correct set of traits.
§Examples
The goal of dimensional analysis is to ensure correctness when doing calculations on physical quantities. Operations are only valid between quantities of compatible units, and units must be conserved in order to get correct results.
The fundamental principle of this library is to represent quantities with incompatible units as different types, so that attempting to use them together results in a compiler error.
The following function takes a distance an object has moved, as well as the amount of time it took to move that distance, and calculates the average speed of the object:
use dana::{Quantity, units::{Length, Speed, Time}};
fn speed(dist: Quantity<Length>, time: Quantity<Time>) -> Quantity<Speed> {
dist / time
}This calculation is correctly performed by dividing the distance moved by the time taken. Attempting to perform the wrong operation will produce the wrong type, resulting in a “mismatched types” error:
fn speed(dist: Quantity<Length>, time: Quantity<Time>) -> Quantity<Speed> {
time / dist
}§Defining Quantities
Using the full syntax is verbose to the point of near-unreadability:
use dana::{Quantity, units::*};
let grav: Quantity<UnitDiv<Length, UnitSquared<Time>>> = Quantity {
unit: UnitDiv::new(Length::Meter, UnitSquared::new(Time::Second)),
value: 9.81,
};This can be reduced somewhat by using type inference, Quantity::new or
Unit::quantity, standard library math operators, and the methods of
unit traits. The result is better, but still difficult to read for more
complex expressions:
use dana::{Quantity, units::{concrete::*, traits::CanSquare}};
let grav = Quantity::new(
Length::Meter / Time::Second.squared(),
9.81,
);To make large units more workable, the qty macro interprets combinations
of units using a wider range of operators than the standard library
traits provide:
use dana::{qty, units::concrete::*};
let grav = qty![9.81 Length::Meter / (Time::Second ^ 2)];Finally, the symbols module provides standard SI unit symbols as
constants and type aliases, bringing the syntax very close to a pure
mathematical form:
use dana::{qty, symbols::*};
let grav = qty![9.81 m/s^2];Re-exports§
Modules§
- constants
- Constant values for use in calculations.
- dimension
- Module for base dimensions underlying the unit system.
- equations
- Functions for mathematical relationships between quantities.
- error
- Module for error types.
- prelude
- Prelude module re-exporting
Quantity,Value, convenience macros, andUnittraits and types. - quantity
- The link between dimensionless
Values and dimensionalUnits. - symbols
- Module of aliases for dimensions and units, based on SI symbols.
- units
- Core module of the units system.
- value
- Module for the
Valuemarker trait.
Macros§
- assert_
qty_ approx - Asserts that one
Quantityis almost equal to another, by comparing their difference (in the units of the first quantity) to a limit (default1e-12). - debug_
assert_ qty_ approx - Equivalent to
assert_qty_approx!, but only runs in debug builds. - dim
- Macro to simplify
Dimensiondefinitions. - qty
- Macro to simplify
Quantitydefinitions. - qtype
- Macro to simplify
Quantitytype definitions. - unit
- Macro to simplify compound unit definitions.
- utype
- Macro to simplify compound unit type definitions.