Crate dana

Crate dana 

Source
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§

pub use quantity::Quantity;
pub use units::Unit;
pub use value::Value;

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, and Unit traits and types.
quantity
The link between dimensionless Values and dimensional Units.
symbols
Module of aliases for dimensions and units, based on SI symbols.
units
Core module of the units system.
value
Module for the Value marker trait.

Macros§

assert_qty_approx
Asserts that one Quantity is almost equal to another, by comparing their difference (in the units of the first quantity) to a limit (default 1e-12).
debug_assert_qty_approx
Equivalent to assert_qty_approx!, but only runs in debug builds.
dim
Macro to simplify Dimension definitions.
qty
Macro to simplify Quantity definitions.
qtype
Macro to simplify Quantity type definitions.
unit
Macro to simplify compound unit definitions.
utype
Macro to simplify compound unit type definitions.