unitforge 0.4.0

A library for unit and quantity consistent computations in Rust
Documentation
#![cfg(feature = "serde")]

use ndarray::arr1;
use unitforge::quantities::{Force, ForceUnit};
use unitforge::small_linalg::{Matrix3, Vector3};
use unitforge::{PhysicsQuantity, MAX_ABS_QUANTITY_POWER};

#[test]
fn roundtrip_quantity() {
    let original = Force::new(100.0, ForceUnit::kN);

    let json = serde_json::to_string(&original).expect("Failed to serialize");
    let deserialized: Force = serde_json::from_str(&json).expect("Failed to deserialize");

    assert_eq!(deserialized.to(ForceUnit::N), original.to(ForceUnit::N));
}

#[test]
fn roundtrip_quantity_ndarray() {
    let original = arr1(&[
        Force::new(50.0, ForceUnit::kN),
        Force::new(75.0, ForceUnit::kN),
    ]);

    let json = serde_json::to_string(&original).expect("Failed to serialize");
    let deserialized: ndarray::Array1<Force> =
        serde_json::from_str(&json).expect("Failed to deserialize");

    assert_eq!(deserialized[1].to(ForceUnit::N), original[1].to(ForceUnit::N));
}

#[test]
fn roundtrip_vector() {
    let original: Vector3<Force> = Vector3::from_f64([1.0, 2.0, 3.0]);

    let json = serde_json::to_string(&original).expect("Failed to serialize");
    let deserialized: Vector3<Force> = serde_json::from_str(&json).expect("Failed to deserialize");

    assert_eq!(deserialized, original);
}

#[test]
fn roundtrip_matrix() {
    let mat = Matrix3::new([[3.0_f64; 3]; 3]);
    let force = Force::new(1.0, ForceUnit::kN);
    let original = mat * force;

    let json = serde_json::to_string(&original).expect("Failed to serialize");
    let deserialized: Matrix3<Force> = serde_json::from_str(&json).expect("Failed to deserialize");

    for i in 0..3 {
        for j in 0..3 {
            assert_eq!(deserialized[(i, j)], Force::new(3.0, ForceUnit::kN));
        }
    }
}

#[test]
fn deserialize_canonicalizes_unnormalized_quantity_parts() {
    let deserialized: Force =
        serde_json::from_str(r#"{"multiplier":1000.0,"power":0}"#).expect("deserialize force");

    assert_eq!(deserialized.get_tuple(), (1.0, 3));
    assert_eq!(deserialized.to(ForceUnit::N), 1000.0);
}

#[test]
fn deserialize_saturates_large_positive_power_to_infinity() {
    let json = format!(r#"{{"multiplier":1.0,"power":{}}}"#, MAX_ABS_QUANTITY_POWER);
    let deserialized: Force = serde_json::from_str(&json).expect("deserialize force");

    assert!(deserialized.as_f64().is_infinite());
    assert!(deserialized.as_f64().is_sign_positive());
    assert_eq!(deserialized.get_power(), 0);
}

#[test]
fn deserialize_saturates_large_negative_power_to_zero() {
    let json = format!(r#"{{"multiplier":1.0,"power":{}}}"#, -MAX_ABS_QUANTITY_POWER);
    let deserialized: Force = serde_json::from_str(&json).expect("deserialize force");

    assert_eq!(deserialized.get_tuple(), (0.0, 0));
    assert_eq!(deserialized.to(ForceUnit::N), 0.0);
}