Coder Social home page Coder Social logo

uom's People

Contributors

adamreichold avatar aehmlo avatar apopiak avatar baarkerlounger avatar bheisler avatar calbaker avatar crystal-growth avatar dmit avatar eagle941 avatar gonzaponte avatar groscoe2 avatar hellow554 avatar iliekturtles avatar jacg avatar nemo157 avatar nick-pascucci-spire avatar nicodemus26 avatar niklasvousten avatar nvzqz avatar octronics avatar okkn avatar radix avatar robinohs avatar swaits avatar tobtobxx avatar uzaaft avatar waywardmonkeys avatar xvapx avatar yacinelakel avatar zdimension avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uom's Issues

non-deterministic failure in rem test

While I was working on an unrelated PR, I got this error during a test run:

---- tests::quantities_macro::fractional::f32::rem stdout ----
        thread 'tests::quantities_macro::fractional::f32::rem' panicked at '[quickcheck] TEST FAILED. Arguments: (A { v: 99.59967 }, A { v: 16.073349 })', C:\Users\radix\.cargo\registry\src\github.com-1ecc6299db9ec823\quickcheck-0.5.0\src\tester.rs:171:27
note: Run with `RUST_BACKTRACE=1` for a backtrace.


failures:
    tests::quantities_macro::fractional::f32::rem

test result: FAILED. 147 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

Can't create "large" integer quantities when using smaller-than-default base units

I haven't had a chance to dig into this yet but I noticed a crash when trying to create reasonably large u64 Lengths.

This is some example code that fails at runtime when creating the Length quantity:

#[macro_use]
extern crate uom;
use uom::si::length::{centimeter, meter};
use uom::si;

mod u64units {
  ISQ!(
    uom::si,
    u64,
    (centimeter, gram, second, ampere, kelvin, mole, candela)
  );
}

fn main() {
  let max_u64 = u64::max_value();
  u64units::Length::new::<centimeter>(max_u64 / 16 + 1);
}

Here's my traceback:

thread 'main' panicked at 'attempt to multiply with overflow', C:\projects\rust\src\libcore\ops\arith.rs:309:45

   9: core::ops::arith::{{impl}}::mul
             at C:\projects\rust\src\libcore\ops\arith.rs:309
  10: num_rational::{{impl}}::div<u64>
             at ...\num-rational-0.1.40\src\lib.rs:442
  11: num_rational::{{impl}}::div<u64>
             at ...\num-rational-0.1.40\src\lib.rs:375
  12: uom::si::Quantity<Dimension, Units<u64>, u64>::new<Units<u64>,u64,uom::si::length::centimeter>
             at ...\uom-570397b139e674d8\595b3ae\src\quantity.rs:227
  13: uomtest::main
             at .\src\bin\uomtest.rs:39
  14: panic_unwind::__rust_maybe_catch_panic
             at C:\projects\rust\src\libpanic_unwind\lib.rs:99
  15: std::rt::lang_start
             at C:\projects\rust\src\libstd\rt.rs:52
  16: main

Using max_u64 / 16 instead of max_u64 / 16 + 1 works. This also seems to only happen when using lengths with a base unit smaller than meter -- if I use meter as my base unit I can create quantities up to u64::max_value().

comparison of integral Quantities is very slow

The short version: comparing integral quantities with Eq can be many orders of magnitude slower than regular comparison. This is magnified for the bigger types, with i64 being about a few thousand times slower than comparing plain i64 values. I assume the same happens for the PartialOrd implementation.

     Running `C:\Users\radix\Projects\pandt\target\release\deps\uom_ops-6068a9413eff2c40.exe --bench`

simple u32              time:   [376.27 ps 383.53 ps 390.64 ps]
Found 4 outliers among 100 measurements (4.00%)
  3 (3.00%) high mild
  1 (1.00%) high severe

simple i64              time:   [366.59 ps 369.57 ps 372.66 ps]
Found 8 outliers among 100 measurements (8.00%)
  2 (2.00%) low mild
  3 (3.00%) high mild
  3 (3.00%) high severe

uom u32                 time:   [808.11 ns 814.27 ns 821.16 ns]
Found 9 outliers among 100 measurements (9.00%)
  3 (3.00%) low mild
  2 (2.00%) high mild
  4 (4.00%) high severe

uom i64                 time:   [1.5856 us 1.5981 us 1.6113 us]
Found 13 outliers among 100 measurements (13.00%)
  1 (1.00%) low severe
  4 (4.00%) low mild
  4 (4.00%) high mild
  4 (4.00%) high severe

Here's the benchmark:

#[macro_use] extern crate criterion;
extern crate uom;
extern crate pandt;

use uom::si::length::centimeter;
use criterion::Criterion;
use pandt::types::{u32units, i64units};

fn simple_eq_u32(n: u32, n2: u32) -> bool { n == n2 }
fn simple_eq_i64(n: u64, n2: u64) -> bool { n == n2 }

fn uom_eq_u32(n: u32units::Length, n2: u32units::Length) -> bool { n == n2 }
fn uom_eq_i64(n: i64units::Length, n2: i64units::Length) -> bool { n == n2 }


fn simple_benchmark(c: &mut Criterion) {
  c.bench_function("simple u32", |b| b.iter(|| simple_eq_u32(100, 200)));
  c.bench_function("simple i64", |b| b.iter(|| simple_eq_i64(100, 200)));
}

fn uom_benchmark(c: &mut Criterion) {
  let u32n = u32units::Length::new::<centimeter>(100);
  let u32n2 = u32units::Length::new::<centimeter>(200);
  let i64n = i64units::Length::new::<centimeter>(100);
  let i64n2 = i64units::Length::new::<centimeter>(200);
  c.bench_function("uom u32", |b| b.iter(|| uom_eq_u32(u32n, u32n2)));
  c.bench_function("uom i64", |b| b.iter(|| uom_eq_i64(i64n, i64n2)));
}

criterion_group!(benches, simple_benchmark, uom_benchmark);
criterion_main!(benches);

By my reading of the code, this stems from the fact that Quantities that aren't from the same ISQ! are compatible with each other -- but at the cost of having to perform a conversion, apparently using num-rational. This is something I would be happy to forego - if uom's Eq implementation had a Rhs = Self, it could just perform a simple comparison. Perhaps a flag to the ISQ! macro could turn off this conversion generation and only support comparison of identical types?

Implement overflowing operations

  • overflowing_abs
  • overflowing_add
  • overflowing_div
  • overflowing_mul
  • overflowing_neg
  • overflowing_rem
  • overflowing_shl (?)
  • overflowing_shr (?)
  • overflowing_sub

Implement operations for Quantity references

impl Op<Quantity<...>> for Quantity<..> is already complete. Add the following reference implementations:

  • impl<'a, 'b> Op<&'a Quantity<...>> for &'b Quantity<..>
  • impl<'a> Op<&'a Quantity<...>> for Quantity<..>
  • impl<'a> Op<Quantity<...>> for &'a Quantity<..>

test failures with integers enabled

I didn't realize that I didn't have integers enabled when running tests until I tried to write integer-specific tests for the new Saturating support I'm working on. When I tried to run them, I got these failures (with master, with u32 enabled):

    si::acceleration::tests::u32::check_units
    si::area::tests::u32::check_units
    si::force::tests::u32::check_units
    si::frequency::tests::u32::check_units
    si::velocity::test::u32::check_units
    si::volume::tests::u32::check_units
    tests::system_macro::op_assign::u32::sub_assign
    tests::system_macro::u32::sub

It seems that travis isn't running tests with ints enabled either.

Failure in tests::quantities_macro::float::f64::rem_assign

rem_assign arguments -99.32110293556526 and 4.277491538217234

---- tests::quantities_macro::float::f64::rem_assign stdout ----
	thread 'tests::quantities_macro::float::f64::rem_assign' panicked at '[quickcheck] TEST FAILED. Arguments: (A { v: -99.32110293556526 }, A { v: 4.277491538217234 })', C:\Users\appveyor\.cargo\registry\src\github.com-1ecc6299db9ec823\quickcheck-0.5.0\src\tester.rs:171:27
note: Run with `RUST_BACKTRACE=1` for a backtrace.

Implement float methods

https://doc.rust-lang.org/std/primitive.f32.html

Add support for integral types as the underlying storage type

Add support for integral types (i8, u8, i16, u16, i32, u32, i64, u64, usize? isize?, i128, u128) as the underlying storage type so that users can create new systems which do not use a floating point type. Use features to control code generation. Not all methods may be applicable. Types shouldn't be implemented for the ISQ.

Add tests for code generated by system! macro

  • Quantity<D, U, V>
    • Add
    • AddAssign
    • Sub
    • SubAssign
    • Mul
    • MulAssign
    • Div
    • DivAssign
    • Neg
    • Rem
    • RemAssign
  • Dimension
  • Units<D, V>
    • conversion
  • Unit
  • Conversion<V>
  • $quantities<$symbol>
    • Add
    • Sub
  • One
  • Debug
    • fmt
  • BaseUnits
    • Add
    • Sub
  • Units
  • $quantities!

Create constructor method for unnamed quantities

Create constructor method for unnamed quantities:

/// https://en.wikipedia.org/wiki/Gravitational_constant
let G = Quantity::<ISQ<P3, N1, N2, Z0, Z0, Z0, Z0>, SI<f64>, f64>::new(6.674e-11);

Handle overflows in conversion factors

Handle overflows in conversion factors so that factors that exceed the underlying storage type's min/max values do not cause errors. Currently tests are failing because conversion factors overflow the underlying storage type.

  • Don't implement Conversion for types that can't represent the conversion factor? e.g. don't implement Conversion for kilometer when the underlying storage type is u8.
  • Implement Conversion but have tests skip factors that can't accurately be represented?

Implement Display, LowerExp, UpperExp, ...

https://doc.rust-lang.org/core/fmt/trait.Binary.html
https://doc.rust-lang.org/core/fmt/trait.Display.html
https://doc.rust-lang.org/core/fmt/trait.LowerExp.html
https://doc.rust-lang.org/core/fmt/trait.LowerHex.html
https://doc.rust-lang.org/core/fmt/trait.Octal.html
https://doc.rust-lang.org/core/fmt/trait.UpperExp.html
https://doc.rust-lang.org/core/fmt/trait.UpperHex.html

Is there a way to use the fmt syntax or flags to include an implicit unit conversion, unit abbreviation, or unit label?

// What replaces `...` to allow the following outputs: 10 m, 10 meters, 32.8084 ft, 32.8084 feet
println!("{...}", new Length(10, meter));
  • Quantity
  • $quantities (Dimension)
  • BaseUnits
  • $unit (Measurement units)

Improve compile times

Compiling uom with all features enabled takes a significant amount of time. -Ztime-passes shows that the issue is in privacy checking:

$ RUSTFLAGS="-Ztime-passes" cargo +nightly test --no-run
...
time: 172.929; rss: 507MB	privacy checking
...

Timing for this pass increases linearly with the number of underlying storage types enabled. Enabling features for underlying storage types adds impl blocks and type aliases for existing types. No new types are added. Additionally, all structs and traits are pub in uom.

The graph below shows compile times, as reported by cargo for test --no-run in blue and build in red:
image

Test Build Features
15.74 5.5 f64
20.4 5.43 f32,f64
38.84 6.24 bigrational,f32,f64
37.75 7.4 rational64,bigrational,f32,f64
48.28 8.26 rational32,rational64,bigrational,f32,f64
55.52 9.26 rational,rational32,rational64,bigrational,f32,f64
67.57 10.89 biguint,rational,rational32,rational64,bigrational,f32,f64
96.81 12.5 bigint,biguint,rational,rational32,rational64,bigrational,f32,f64
94.53 15.21 i64,bigint,biguint,rational,rational32,rational64,bigrational,f32,f64
106.92 16.4 i32,i64,bigint,biguint,rational,rational32,rational64,bigrational,f32,f64
116.34 18.17 i16,i32,i64,bigint,biguint,rational,rational32,rational64,bigrational,f32,f64
131.29 20.2 i8,i16,i32,i64,bigint,biguint,rational,rational32,rational64,bigrational,f32,f64
144.3 22.19 isize,i8,i16,i32,i64,bigint,biguint,rational,rational32,rational64,bigrational,f32,f64
137.48 24.67 u64,isize,i8,i16,i32,i64,bigint,biguint,rational,rational32,rational64,bigrational,f32,f64
158.4 26.93 u32,u64,isize,i8,i16,i32,i64,bigint,biguint,rational,rational32,rational64,bigrational,f32,f64
194.9 29.69 u16,u32,u64,isize,i8,i16,i32,i64,bigint,biguint,rational,rational32,rational64,bigrational,f32,f64
211.47 33.53 u8,u16,u32,u64,isize,i8,i16,i32,i64,bigint,biguint,rational,rational32,rational64,bigrational,f32,f64
198.5 36.63 usize,u8,u16,u32,u64,isize,i8,i16,i32,i64,bigint,biguint,rational,rational32,rational64,bigrational,f32,f64

num dependency should have default-features=false

My application which uses uom doesn't need additional num-* crates. Given that num has optional dependencies which are enabled by default, I tried setting default-features = false in my Cargo.toml, but the default features were still enabled. I eventually figured out that this is because uom is depending on num without specifying default-features = false.

Add support for bytes?

Would support for 'bytes' be within scope for this library? Would that work out well with using f32 / f64 storage? It seems like perhaps using u64 for bytes, but floating point for all larger units might be useful?

Implement wrapping operations / num_traits::ops::wrapping

  • wrapping_abs
  • wrapping_add
  • wrapping_div
  • wrapping_mul
  • wrapping_neg
  • wrapping_rem
  • wrapping_shl (?)
  • wrapping_shr (?)
  • wrapping_sub
  • num_traits::ops::wrapping::WrappingAdd
  • num_traits::ops::wrapping::WrappingMul
  • num_traits::ops::wrapping::WrappingSub

no_std doesn't seem to be transitive

This might just be me being new to rust, but I'm having a really tough time cross compiling uom for ARM. Starting from a lib crate that builds fine, if I add

[dependencies.uom]
default-features = false
features = [ "si", "usize" ]
version = "*"

to Cargo.toml and then run xargo build it tells me

error[E0463]: can't find crate for `std`
  |
  = note: the `thumbv7em-none-eabihf` target may not be installed

error: aborting due to previous error

error: Could not compile `num-traits`.

Caused by:
  process didn't exit successfully: `rustc --crate-name num_traits ~/.cargo/registry/src/github.com-1ecc6299db9ec823/num-traits-0.2.0/src/lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 --cfg feature="default" --cfg feature="std" -C metadata=459f1b7f38ae1057 -C extra-filename=-459f1b7f38ae1057 --out-dir target/thumbv7em-none-eabihf/debug/deps --target thumbv7em-none-eabihf -L dependency=target/thumbv7em-none-eabihf/debug/deps -L dependency=target/debug/deps --cap-lints allow -C link-arg=-Tlink.x -C linker=cortex-m-rt-ld -Z linker-flavor=ld -Z thinlto=no --sysroot ~/.xargo` (exit code: 101)

of special note there is the part that says --cfg feature="std". It seems that specifying no_std for uom isn't enforcing that constraint on upstream dependencies.

Allow constants to be defined in system! or quantity! macro

Allow one location? Both?

Constant created by system macro (e.g. ISQ!) with the appropriate unit. Accessed in a submodule so there are no name collisions? let _ = uom::si::f32::velocity::c;

quantity! {
    quantity: Velocity; "velocity";
    dimension: ...;
    units { ... }
    constants {
        c: 299_792_458 meter_per_second,
    }
}

Constant created by system macro (e.g. ISQ!) with appropriate base units. let _ = uom::si::f32::G;

system! {
    quantities: ISQ {
        length: meter, L;
        ...
    }
    units: SI { ... }
    constants:{
        G: 6.674_083_1_E-11 ISQ<P3, N1, N2, Z0, Z0, Z0, Z0>,
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.