Use fastnum::d128 (#41)
This commit is contained in:
parent
3bbc5c53a1
commit
2d89355566
@ -1,5 +1,9 @@
|
||||
# Changelog
|
||||
|
||||
## Next
|
||||
- Switch to the fastnum crate's d128
|
||||
- Fix exp function
|
||||
|
||||
## 2.0.0 - 2025 May 30
|
||||
- Remove the `degrees` keyword which referred to `celcius` by default
|
||||
- Remove the `default_degrees` argument from `eval()` and `lex()`. Not necessary now that the `degrees` keyword is removed
|
||||
|
||||
103
Cargo.lock
generated
103
Cargo.lock
generated
@ -12,78 +12,42 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
name = "autocfg"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.24"
|
||||
name = "bnum"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
checksum = "f781dba93de3a5ef6dc5b17c9958b208f6f3f021623b360fb605ea51ce443f10"
|
||||
|
||||
[[package]]
|
||||
name = "cpc"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"decimal",
|
||||
"fastnum",
|
||||
"regex",
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "decimal"
|
||||
version = "2.1.0"
|
||||
name = "fastnum"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a8ab77e91baeb15034c3be91e87bff4665c9036216148e4996d9a9f5792114d"
|
||||
checksum = "86cde0c9334bfed5ced962bd7acc266e02e254d71494787e4255d8ec4f7296d4"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"libc",
|
||||
"ord_subset",
|
||||
"serde",
|
||||
"autocfg",
|
||||
"bnum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "ord_subset"
|
||||
version = "3.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7ce14664caf5b27f5656ff727defd68ae1eb75ef3c4d95259361df1eb376bef"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.1"
|
||||
@ -113,49 +77,6 @@ version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.12.0"
|
||||
|
||||
@ -19,11 +19,8 @@ categories = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
decimal = { version = "2.1", default-features = false, features = [
|
||||
"serde",
|
||||
"ord_subset",
|
||||
] }
|
||||
unicode-segmentation = "1.10"
|
||||
fastnum = "0.2"
|
||||
unicode-segmentation = "1.12"
|
||||
|
||||
[dev-dependencies]
|
||||
regex = "1.11"
|
||||
|
||||
51
README.md
51
README.md
@ -11,9 +11,6 @@ It also lets you mix units, so for example `1 km - 1m` results in `999 Meter`.
|
||||
|
||||
[List of all supported units](https://docs.rs/cpc/latest/cpc/units/enum.Unit.html)
|
||||
|
||||
> [!TIP]
|
||||
> [fend](https://github.com/printfn/fend) is a great alternative to cpc
|
||||
|
||||
## CLI Installation
|
||||
Install using `cargo`:
|
||||
```
|
||||
@ -27,26 +24,6 @@ To install it manually, grab the appropriate binary from the [GitHub Releases pa
|
||||
cpc '2h/3 to min'
|
||||
```
|
||||
|
||||
## API Installation
|
||||
Add `cpc` as a dependency in `Cargo.toml`.
|
||||
|
||||
## API Usage
|
||||
|
||||
```rust
|
||||
use cpc::eval;
|
||||
use cpc::units::Unit;
|
||||
|
||||
match eval("3m + 1cm", true, Unit::Celsius, false) {
|
||||
Ok(answer) => {
|
||||
// answer: Number { value: 301, unit: Unit::Centimeter }
|
||||
println!("Evaluated value: {} {:?}", answer.value, answer.unit)
|
||||
},
|
||||
Err(e) => {
|
||||
println!("{e}")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
```
|
||||
3 + 4 * 2
|
||||
@ -84,14 +61,29 @@ round(sqrt(2)^4)! liters
|
||||
- Speed
|
||||
- Temperature
|
||||
|
||||
## API Installation
|
||||
Add `cpc` as a dependency in `Cargo.toml`.
|
||||
|
||||
## API Usage
|
||||
|
||||
```rust
|
||||
use cpc::eval;
|
||||
use cpc::units::Unit;
|
||||
|
||||
match eval("3m + 1cm", true, Unit::Celsius, false) {
|
||||
Ok(answer) => {
|
||||
// answer: Number { value: 301, unit: Unit::Centimeter }
|
||||
println!("Evaluated value: {} {:?}", answer.value, answer.unit)
|
||||
},
|
||||
Err(e) => {
|
||||
println!("{e}")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Accuracy
|
||||
cpc uses 128-bit Decimal Floating Point (d128) numbers instead of Binary Coded Decimals for better accuracy. The result cpc gives will still not always be 100% accurate. I would recommend rounding the result to 20 decimals or less.
|
||||
|
||||
## Performance
|
||||
It's pretty fast and scales well. In my case, it usually runs in under 0.1ms. The biggest performance hit is functions like `log()`. `log(12345)` evaluates in 0.12ms, and `log(e)` in 0.25ms.
|
||||
|
||||
To see how fast it is, you can pass the `--verbose` flag in CLI, or the `verbose` argument to `eval()`.
|
||||
|
||||
## Dev Instructions
|
||||
|
||||
### Get started
|
||||
@ -165,9 +157,6 @@ match string {
|
||||
|
||||
### Potential Improvements
|
||||
- Support for conversion between Power, Current, Resistance and Voltage. Multiplication and division is currently supported, but not conversions using sqrt or pow.
|
||||
- Move to pure-rust decimal implementation
|
||||
- `rust_decimal`: Only supports numbers up to ~1E+29
|
||||
- `bigdecimal`: Lacking math functions
|
||||
- E notation, like 2E+10
|
||||
- Unit types
|
||||
- Currency: How to go about dynamically updating the weights?
|
||||
|
||||
116
src/evaluator.rs
116
src/evaluator.rs
@ -7,7 +7,7 @@ use crate::Operator::{Caret, Divide, Minus, Modulo, Multiply, Plus};
|
||||
use crate::TextOperator::{Of, To};
|
||||
use crate::UnaryOperator::{Factorial, Percent};
|
||||
use crate::{Number, Token};
|
||||
use decimal::d128;
|
||||
use fastnum::{dec128 as d, D128};
|
||||
|
||||
/// Evaluate an [`AstNode`] into a [`Number`]
|
||||
pub fn evaluate(ast: &AstNode) -> Result<Number, String> {
|
||||
@ -20,14 +20,14 @@ pub fn evaluate(ast: &AstNode) -> Result<Number, String> {
|
||||
/// Factorials do not work with decimal numbers.
|
||||
///
|
||||
/// All return values of this function are hard-coded.
|
||||
pub fn factorial(input: d128) -> d128 {
|
||||
lookup_factorial(input.into())
|
||||
pub fn factorial(input: D128) -> D128 {
|
||||
lookup_factorial(input.try_into().unwrap())
|
||||
}
|
||||
|
||||
/// Returns the square root of a [`struct@d128`]
|
||||
pub fn sqrt(input: d128) -> d128 {
|
||||
let mut n = d128!(1);
|
||||
let half = d128!(0.5);
|
||||
pub fn sqrt(input: D128) -> D128 {
|
||||
let mut n = d!(1);
|
||||
let half = d!(0.5);
|
||||
for _ in 0..10 {
|
||||
n = (n + input / n) * half;
|
||||
}
|
||||
@ -35,10 +35,10 @@ pub fn sqrt(input: d128) -> d128 {
|
||||
}
|
||||
|
||||
/// Returns the cube root of a [`struct@d128`]
|
||||
pub fn cbrt(input: d128) -> d128 {
|
||||
let mut n: d128 = input;
|
||||
pub fn cbrt(input: D128) -> D128 {
|
||||
let mut n: D128 = input;
|
||||
// hope that 20 iterations makes it accurate enough
|
||||
let three = d128!(3);
|
||||
let three = d!(3);
|
||||
for _ in 0..20 {
|
||||
let z2 = n * n;
|
||||
n = n - ((n * z2 - input) / (three * z2));
|
||||
@ -46,60 +46,23 @@ pub fn cbrt(input: d128) -> d128 {
|
||||
n
|
||||
}
|
||||
|
||||
fn pi() -> d128 {
|
||||
d128!(3.14159265358979323846264338327950288)
|
||||
}
|
||||
fn pi2() -> d128 {
|
||||
d128!(6.283185307179586476925286766559005768)
|
||||
}
|
||||
fn pi_half() -> d128 {
|
||||
d128!(1.570796326794896619231321691639751)
|
||||
}
|
||||
fn eulers_number() -> d128 {
|
||||
d128!(2.718281828459045235360287471352662)
|
||||
}
|
||||
fn rounding_base() -> d128 {
|
||||
// DO NOT add trailing zeroes
|
||||
d128!(0.0000000000000000000000000000001)
|
||||
}
|
||||
|
||||
/// Returns the sine of a [`struct@d128`]
|
||||
pub fn sin(mut input: d128) -> d128 {
|
||||
input %= pi2();
|
||||
|
||||
let negative_correction = if input.is_negative() {
|
||||
input -= pi();
|
||||
d128!(-1)
|
||||
} else {
|
||||
d128!(1)
|
||||
};
|
||||
|
||||
let one = d128!(1);
|
||||
let two = d128!(2);
|
||||
let neg_one = -one;
|
||||
|
||||
let precision = 37;
|
||||
let mut result = d128!(0);
|
||||
for i_int in 0..precision {
|
||||
let i = d128::from(i_int);
|
||||
let calc_result = two * i + one;
|
||||
result += neg_one.pow(i) * (input.pow(calc_result) / factorial(calc_result));
|
||||
pub fn sin(input: D128) -> D128 {
|
||||
let result =input.sin();
|
||||
match result.is_zero() {
|
||||
true => D128::ZERO,
|
||||
false => result,
|
||||
}
|
||||
|
||||
let unrounded_result = negative_correction * result;
|
||||
|
||||
// This uses bankers rounding
|
||||
unrounded_result.quantize(rounding_base())
|
||||
}
|
||||
|
||||
/// Returns the cosine of a [`struct@d128`]
|
||||
pub fn cos(input: d128) -> d128 {
|
||||
sin(pi_half() - input)
|
||||
pub fn cos(input: D128) -> D128 {
|
||||
input.cos()
|
||||
}
|
||||
|
||||
/// Returns the tangent of a [`struct@d128`]
|
||||
pub fn tan(input: d128) -> d128 {
|
||||
sin(input) / cos(input)
|
||||
pub fn tan(input: D128) -> D128 {
|
||||
input.tan()
|
||||
}
|
||||
|
||||
/// Evaluate an [`AstNode`] into a [`Number`]
|
||||
@ -110,11 +73,11 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
|
||||
Token::Number(number) => Ok(Number::new(*number, Unit::NoUnit)),
|
||||
Token::Constant(constant) => match constant {
|
||||
Pi => Ok(Number::new(
|
||||
pi(),
|
||||
D128::PI,
|
||||
Unit::NoUnit,
|
||||
)),
|
||||
E => Ok(Number::new(
|
||||
eulers_number(),
|
||||
D128::E,
|
||||
Unit::NoUnit,
|
||||
)),
|
||||
},
|
||||
@ -148,8 +111,7 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
|
||||
}
|
||||
Ln => {
|
||||
if child_answer.unit.category() == UnitType::NoType {
|
||||
let unrounded_result = child_answer.value.ln();
|
||||
let result = unrounded_result.quantize(unrounded_result * d128!(10));
|
||||
let result = child_answer.value.ln();
|
||||
Ok(Number::new(result, child_answer.unit))
|
||||
} else {
|
||||
Err("ln() only accepts UnitType::NoType".to_string())
|
||||
@ -157,7 +119,7 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
|
||||
}
|
||||
Exp => {
|
||||
if child_answer.unit.category() == UnitType::NoType {
|
||||
let result = child_answer.value.exp(child_answer.value);
|
||||
let result = child_answer.value.exp();
|
||||
Ok(Number::new(result, child_answer.unit))
|
||||
} else {
|
||||
Err("exp() only accepts UnitType::NoType".to_string())
|
||||
@ -165,35 +127,35 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
|
||||
}
|
||||
Round => {
|
||||
// .quantize() rounds .5 to nearest even integer, so we correct that
|
||||
let mut result = child_answer.value.quantize(d128!(1));
|
||||
let mut result = child_answer.value.quantize(d!(1));
|
||||
let rounding_change = result - child_answer.value;
|
||||
// If the result was rounded down by 0.5, correct by +1
|
||||
if rounding_change == d128!(-0.5) {
|
||||
result += d128!(1);
|
||||
if rounding_change == d!(-0.5) {
|
||||
result += d!(1);
|
||||
}
|
||||
Ok(Number::new(result, child_answer.unit))
|
||||
}
|
||||
Ceil => {
|
||||
let mut result = child_answer.value.quantize(d128!(1));
|
||||
let mut result = child_answer.value.quantize(d!(1));
|
||||
let rounding_change = result - child_answer.value;
|
||||
if rounding_change.is_negative() {
|
||||
result += d128!(1);
|
||||
result += d!(1);
|
||||
}
|
||||
Ok(Number::new(result, child_answer.unit))
|
||||
}
|
||||
Floor => {
|
||||
let mut result = child_answer.value.quantize(d128!(1));
|
||||
let mut result = child_answer.value.quantize(d!(1));
|
||||
let rounding_change = result - child_answer.value;
|
||||
if !rounding_change.is_negative() {
|
||||
result -= d128!(1);
|
||||
result -= d!(1);
|
||||
}
|
||||
Ok(Number::new(result, child_answer.unit))
|
||||
}
|
||||
Abs => {
|
||||
let mut result = child_answer.value.abs();
|
||||
let rounding_change = result - child_answer.value;
|
||||
if rounding_change == d128!(-0.5) {
|
||||
result += d128!(1);
|
||||
if rounding_change == d!(-0.5) {
|
||||
result += d!(1);
|
||||
}
|
||||
Ok(Number::new(result, child_answer.unit))
|
||||
}
|
||||
@ -232,7 +194,7 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
|
||||
let child_answer = evaluate_node(child_node)?;
|
||||
match operator {
|
||||
Percent => Ok(Number::new(
|
||||
child_answer.value / d128!(100),
|
||||
child_answer.value / d!(100),
|
||||
child_answer.unit,
|
||||
)),
|
||||
Factorial => {
|
||||
@ -326,7 +288,7 @@ mod tests {
|
||||
let result = eval(input, true, false).unwrap();
|
||||
assert_eq!(result.unit, Unit::NoUnit);
|
||||
|
||||
result.get_simplified_value().to_string()
|
||||
result.to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -334,7 +296,7 @@ mod tests {
|
||||
assert_eq!(eval_num("-2(-3)"), "6");
|
||||
assert_eq!(eval_num("-2(3)"), "-6");
|
||||
assert_eq!(eval_num("(3)-2"), "1");
|
||||
assert_eq!(eval_default("-1km to m"), Number::new(d128!(-1000), Unit::Meter));
|
||||
assert_eq!(eval_default("-1km to m"), Number::new(d!(-1000), Unit::Meter));
|
||||
assert_eq!(eval_num("2*-3*0.5"), "-3");
|
||||
assert_eq!(eval_num("-3^2"), "-9");
|
||||
assert_eq!(eval_num("-1+2"), "1");
|
||||
@ -347,13 +309,15 @@ mod tests {
|
||||
assert_eq!(eval_num("sqrt(25)"), "5");
|
||||
|
||||
assert_eq!(eval_num("log(100)"), "2");
|
||||
assert_eq!(eval_num("log(2)"), "0.301029995663981195213738894724493");
|
||||
assert_eq!(eval_num("log(2)"), "0.301029995663981195213738894724493026768");
|
||||
|
||||
assert_eq!(eval_num("ln(1)"), "0");
|
||||
assert_eq!(eval_num("ln(2)"), "0.693147180559945309417232121458177");
|
||||
assert_eq!(eval_num("ln(2)"), "0.69314718055994530941723212145817656808");
|
||||
assert_eq!(eval_num("ln(e)"), "1");
|
||||
assert_eq!(eval_num("ln(e^2)"), "2");
|
||||
|
||||
assert_eq!(eval_num("exp(1)"), "2.71828182845904523536028747135266249776");
|
||||
|
||||
assert_eq!(eval_num("round(1.4)"), "1");
|
||||
assert_eq!(eval_num("round(1.6)"), "2");
|
||||
assert_eq!(eval_num("round(1.5)"), "2");
|
||||
@ -367,7 +331,7 @@ mod tests {
|
||||
|
||||
assert_eq!(eval_num("abs(-3)"), "3");
|
||||
|
||||
assert_eq!(eval_num("sin(2)"), "0.9092974268256816953960198659117");
|
||||
assert_eq!(eval_num("sin(-2)"), "-0.9092974268256816953960198659117");
|
||||
assert_eq!(eval_num("sin(2)"), "0.9092974268256816953960198659117448427");
|
||||
assert_eq!(eval_num("sin(-2)"), "-0.9092974268256816953960198659117448427");
|
||||
}
|
||||
}
|
||||
|
||||
11
src/lexer.rs
11
src/lexer.rs
@ -1,6 +1,6 @@
|
||||
use std::iter::Peekable;
|
||||
use std::str::FromStr;
|
||||
use decimal::d128;
|
||||
use fastnum::decimal::Context;
|
||||
use fastnum::D128;
|
||||
use crate::Token;
|
||||
use crate::Operator::{Caret, Divide, LeftParen, Minus, Modulo, Multiply, Plus, RightParen};
|
||||
use crate::UnaryOperator::{Percent, Factorial};
|
||||
@ -98,14 +98,9 @@ fn parse_token(c: &str, lexer: &mut Lexer) -> Result<(), String> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
d128::set_status(decimal::Status::empty());
|
||||
match d128::from_str(&number_string) {
|
||||
match D128::from_str(&number_string, Context::default()) {
|
||||
Ok(number) => {
|
||||
if d128::get_status().is_empty() {
|
||||
tokens.push(Token::Number(number));
|
||||
} else {
|
||||
return Err(format!("Error lexing d128 number: {}", number_string));
|
||||
}
|
||||
},
|
||||
Err(_e) => {
|
||||
return Err(format!("Error lexing d128 number: {}", number_string));
|
||||
|
||||
39
src/lib.rs
39
src/lib.rs
@ -23,7 +23,7 @@
|
||||
//! ```
|
||||
|
||||
use crate::units::Unit;
|
||||
use decimal::d128;
|
||||
use fastnum::{dec128 as d, D128};
|
||||
use std::fmt::{self, Display};
|
||||
use std::time::Instant;
|
||||
|
||||
@ -47,37 +47,32 @@ pub mod units;
|
||||
/// ```rust
|
||||
/// use cpc::{eval,Number};
|
||||
/// use cpc::units::Unit;
|
||||
/// use decimal::d128;
|
||||
/// use fastnum::dec128;
|
||||
///
|
||||
/// let x = Number {
|
||||
/// value: d128!(100),
|
||||
/// value: dec128!(100),
|
||||
/// unit: Unit::Meter,
|
||||
/// };
|
||||
/// ```
|
||||
pub struct Number {
|
||||
/// The number part of a [`Number`] struct
|
||||
pub value: d128,
|
||||
pub value: D128,
|
||||
/// The unit of a [`Number`] struct. This can be [`NoType`](units::UnitType::NoType)
|
||||
pub unit: Unit,
|
||||
}
|
||||
|
||||
impl Number {
|
||||
pub const fn new(value: d128, unit: Unit) -> Number {
|
||||
pub const fn new(value: D128, unit: Unit) -> Number {
|
||||
Number { value, unit }
|
||||
}
|
||||
pub fn get_simplified_value(&self) -> d128 {
|
||||
// The order here matters, reduce must be first
|
||||
// sin(pi) results in 0E-32, but .reduce() changes is to 0
|
||||
let mut value = self.value.reduce();
|
||||
// 0.2/0.01 results in 2E+1, but adding 0 changes it to 20
|
||||
value = value + d128!(0);
|
||||
value
|
||||
pub fn get_simplified_value(&self) -> D128 {
|
||||
self.value.reduce()
|
||||
}
|
||||
}
|
||||
impl Display for Number {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let value = self.get_simplified_value();
|
||||
let word = match self.value == d128!(1) {
|
||||
let word = match self.value == d!(1) {
|
||||
true => self.unit.singular(),
|
||||
false => self.unit.plural(),
|
||||
};
|
||||
@ -199,7 +194,7 @@ pub enum LexerKeyword {
|
||||
pub enum Token {
|
||||
Operator(Operator),
|
||||
UnaryOperator(UnaryOperator),
|
||||
Number(d128),
|
||||
Number(D128),
|
||||
FunctionIdentifier(FunctionIdentifier),
|
||||
Constant(Constant),
|
||||
/// Used by the parser only
|
||||
@ -218,7 +213,7 @@ pub enum Token {
|
||||
#[macro_export]
|
||||
macro_rules! numtok {
|
||||
( $num:literal ) => {
|
||||
Token::Number(d128!($num))
|
||||
Token::Number(fastnum::dec128!($num))
|
||||
};
|
||||
}
|
||||
|
||||
@ -305,12 +300,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_evaluations() {
|
||||
assert_eq!(default_eval("-2(-3)"), Number::new(d128!(6), Unit::NoUnit));
|
||||
assert_eq!(default_eval("-2(3)"), Number::new(d128!(-6), Unit::NoUnit));
|
||||
assert_eq!(default_eval("(3)-2"), Number::new(d128!(1), Unit::NoUnit));
|
||||
assert_eq!(default_eval("-1km to m"), Number::new(d128!(-1000), Unit::Meter));
|
||||
assert_eq!(default_eval("2*-3*0.5"), Number::new(d128!(-3), Unit::NoUnit));
|
||||
assert_eq!(default_eval("-3^2"), Number::new(d128!(-9), Unit::NoUnit));
|
||||
assert_eq!(default_eval("-1+2"), Number::new(d128!(1), Unit::NoUnit));
|
||||
assert_eq!(default_eval("-2(-3)"), Number::new(d!(6), Unit::NoUnit));
|
||||
assert_eq!(default_eval("-2(3)"), Number::new(d!(-6), Unit::NoUnit));
|
||||
assert_eq!(default_eval("(3)-2"), Number::new(d!(1), Unit::NoUnit));
|
||||
assert_eq!(default_eval("-1km to m"), Number::new(d!(-1000), Unit::Meter));
|
||||
assert_eq!(default_eval("2*-3*0.5"), Number::new(d!(-3), Unit::NoUnit));
|
||||
assert_eq!(default_eval("-3^2"), Number::new(d!(-9), Unit::NoUnit));
|
||||
assert_eq!(default_eval("-1+2"), Number::new(d!(1), Unit::NoUnit));
|
||||
}
|
||||
}
|
||||
|
||||
2062
src/lookup.rs
2062
src/lookup.rs
File diff suppressed because it is too large
Load Diff
541
src/units.rs
541
src/units.rs
@ -1,4 +1,4 @@
|
||||
use decimal::d128;
|
||||
use fastnum::{dec128 as d, D128, D256};
|
||||
use crate::Number;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
@ -62,7 +62,7 @@ macro_rules! create_units {
|
||||
),*
|
||||
}
|
||||
}
|
||||
pub fn weight(&self) -> d128 {
|
||||
pub fn weight(&self) -> D128 {
|
||||
match self {
|
||||
$(
|
||||
Unit::$variant => $properties.1
|
||||
@ -88,229 +88,229 @@ macro_rules! create_units {
|
||||
}
|
||||
|
||||
create_units!(
|
||||
NoUnit: (NoType, d128!(1), "", ""),
|
||||
NoUnit: (NoType, d!(1), "", ""),
|
||||
|
||||
Nanosecond: (Time, d128!(1), "nanosecond", "nanoseconds"),
|
||||
Microsecond: (Time, d128!(1000), "microsecond", "microseconds"),
|
||||
Millisecond: (Time, d128!(1000000), "millisecond", "milliseconds"),
|
||||
Second: (Time, d128!(1000000000), "second", "seconds"),
|
||||
Minute: (Time, d128!(60000000000), "minute", "minutes"),
|
||||
Hour: (Time, d128!(3600000000000), "hour", "hours"),
|
||||
Day: (Time, d128!(86400000000000), "day", "days"),
|
||||
Week: (Time, d128!(604800000000000), "week", "weeks"),
|
||||
Month: (Time, d128!(2629746000000000), "month", "months"),
|
||||
Quarter: (Time, d128!(7889238000000000), "quarter", "quarters"),
|
||||
Year: (Time, d128!(31556952000000000), "year", "years"),
|
||||
Decade: (Time, d128!(315569520000000000), "decade", "decades"),
|
||||
Century: (Time, d128!(3155695200000000000), "century", "centuries"),
|
||||
Millenium: (Time, d128!(31556952000000000000), "millenium", "millenia"),
|
||||
Nanosecond: (Time, d!(1), "nanosecond", "nanoseconds"),
|
||||
Microsecond: (Time, d!(1000), "microsecond", "microseconds"),
|
||||
Millisecond: (Time, d!(1000000), "millisecond", "milliseconds"),
|
||||
Second: (Time, d!(1000000000), "second", "seconds"),
|
||||
Minute: (Time, d!(60000000000), "minute", "minutes"),
|
||||
Hour: (Time, d!(3600000000000), "hour", "hours"),
|
||||
Day: (Time, d!(86400000000000), "day", "days"),
|
||||
Week: (Time, d!(604800000000000), "week", "weeks"),
|
||||
Month: (Time, d!(2629746000000000), "month", "months"),
|
||||
Quarter: (Time, d!(7889238000000000), "quarter", "quarters"),
|
||||
Year: (Time, d!(31556952000000000), "year", "years"),
|
||||
Decade: (Time, d!(315569520000000000), "decade", "decades"),
|
||||
Century: (Time, d!(3155695200000000000), "century", "centuries"),
|
||||
Millenium: (Time, d!(31556952000000000000), "millenium", "millenia"),
|
||||
|
||||
Millimeter: (Length, d128!(1), "millimeter", "millimeters"),
|
||||
Centimeter: (Length, d128!(10), "centimeter", "centimeters"),
|
||||
Decimeter: (Length, d128!(100), "decimeter", "decimeters"),
|
||||
Meter: (Length, d128!(1000), "meter", "meters"),
|
||||
Kilometer: (Length, d128!(1000000), "kilometer", "kilometers"),
|
||||
Inch: (Length, d128!(25.4), "inch", "inches"),
|
||||
Foot: (Length, d128!(304.8), "foot", "feet"),
|
||||
Yard: (Length, d128!(914.4), "yard", "yards"),
|
||||
Mile: (Length, d128!(1609344), "mile", "miles"),
|
||||
Millimeter: (Length, d!(1), "millimeter", "millimeters"),
|
||||
Centimeter: (Length, d!(10), "centimeter", "centimeters"),
|
||||
Decimeter: (Length, d!(100), "decimeter", "decimeters"),
|
||||
Meter: (Length, d!(1000), "meter", "meters"),
|
||||
Kilometer: (Length, d!(1000000), "kilometer", "kilometers"),
|
||||
Inch: (Length, d!(25.4), "inch", "inches"),
|
||||
Foot: (Length, d!(304.8), "foot", "feet"),
|
||||
Yard: (Length, d!(914.4), "yard", "yards"),
|
||||
Mile: (Length, d!(1609344), "mile", "miles"),
|
||||
// 1-dimensional only:
|
||||
Marathon: (Length, d128!(42195000), "marathon", "marathons"),
|
||||
NauticalMile: (Length, d128!(1852000), "nautical mile", "nautical miles"),
|
||||
LightYear: (Length, d128!(9460730472580800000), "light year", "light years"),
|
||||
LightSecond: (Length, d128!(299792458000), "light second", "light seconds"),
|
||||
Marathon: (Length, d!(42195000), "marathon", "marathons"),
|
||||
NauticalMile: (Length, d!(1852000), "nautical mile", "nautical miles"),
|
||||
LightYear: (Length, d!(9460730472580800000), "light year", "light years"),
|
||||
LightSecond: (Length, d!(299792458000), "light second", "light seconds"),
|
||||
|
||||
SquareMillimeter: (Area, d128!(1), "square millimeter", "square millimeters"),
|
||||
SquareCentimeter: (Area, d128!(100), "square centimeter", "square centimeters"),
|
||||
SquareDecimeter: (Area, d128!(10000), "square decimeter", "square decimeters"),
|
||||
SquareMeter: (Area, d128!(1000000), "square meter", "square meters"),
|
||||
SquareKilometer: (Area, d128!(1000000000000), "square kilometer", "square kilometers"),
|
||||
SquareInch: (Area, d128!(645.16), "square inch", "square inches"),
|
||||
SquareFoot: (Area, d128!(92903.04), "square foot", "square feet"),
|
||||
SquareYard: (Area, d128!(836127.36), "square yard", "square yards"),
|
||||
SquareMile: (Area, d128!(2589988110336.00), "square mile", "square miles"),
|
||||
SquareMillimeter: (Area, d!(1), "square millimeter", "square millimeters"),
|
||||
SquareCentimeter: (Area, d!(100), "square centimeter", "square centimeters"),
|
||||
SquareDecimeter: (Area, d!(10000), "square decimeter", "square decimeters"),
|
||||
SquareMeter: (Area, d!(1000000), "square meter", "square meters"),
|
||||
SquareKilometer: (Area, d!(1000000000000), "square kilometer", "square kilometers"),
|
||||
SquareInch: (Area, d!(645.16), "square inch", "square inches"),
|
||||
SquareFoot: (Area, d!(92903.04), "square foot", "square feet"),
|
||||
SquareYard: (Area, d!(836127.36), "square yard", "square yards"),
|
||||
SquareMile: (Area, d!(2589988110336.00), "square mile", "square miles"),
|
||||
// 2-dimensional only
|
||||
Are: (Area, d128!(100000000), "are", "ares"),
|
||||
Decare: (Area, d128!(1000000000), "decare", "decare"),
|
||||
Hectare: (Area, d128!(10000000000), "hectare", "hectares"),
|
||||
Acre: (Area, d128!(4046856422.40), "acre", "acres"),
|
||||
Are: (Area, d!(100000000), "are", "ares"),
|
||||
Decare: (Area, d!(1000000000), "decare", "decare"),
|
||||
Hectare: (Area, d!(10000000000), "hectare", "hectares"),
|
||||
Acre: (Area, d!(4046856422.40), "acre", "acres"),
|
||||
|
||||
CubicMillimeter: (Volume, d128!(1), "cubic millimeter", "cubic millimeters"),
|
||||
CubicCentimeter: (Volume, d128!(1000), "cubic centimeter", "cubic centimeters"),
|
||||
CubicDecimeter: (Volume, d128!(1000000), "cubic decimeter", "cubic decimeters"),
|
||||
CubicMeter: (Volume, d128!(1000000000), "cubic meter", "cubic meters"),
|
||||
CubicKilometer: (Volume, d128!(1000000000000000000), "cubic kilometer", "cubic kilometers"),
|
||||
CubicInch: (Volume, d128!(16387.064), "cubic inch", "cubic inches"),
|
||||
CubicFoot: (Volume, d128!(28316846.592), "cubic foot", "cubic feet"),
|
||||
CubicYard: (Volume, d128!(764554857.984), "cubic yard", "cubic yards"),
|
||||
CubicMile: (Volume, d128!(4168181825440579584), "cubic mile", "cubic miles"),
|
||||
CubicMillimeter: (Volume, d!(1), "cubic millimeter", "cubic millimeters"),
|
||||
CubicCentimeter: (Volume, d!(1000), "cubic centimeter", "cubic centimeters"),
|
||||
CubicDecimeter: (Volume, d!(1000000), "cubic decimeter", "cubic decimeters"),
|
||||
CubicMeter: (Volume, d!(1000000000), "cubic meter", "cubic meters"),
|
||||
CubicKilometer: (Volume, d!(1000000000000000000), "cubic kilometer", "cubic kilometers"),
|
||||
CubicInch: (Volume, d!(16387.064), "cubic inch", "cubic inches"),
|
||||
CubicFoot: (Volume, d!(28316846.592), "cubic foot", "cubic feet"),
|
||||
CubicYard: (Volume, d!(764554857.984), "cubic yard", "cubic yards"),
|
||||
CubicMile: (Volume, d!(4168181825440579584), "cubic mile", "cubic miles"),
|
||||
// 3-dimensional only
|
||||
Milliliter: (Volume, d128!(1000), "milliliter", "milliliters"),
|
||||
Centiliter: (Volume, d128!(10000), "centiliter", "centiliters"),
|
||||
Deciliter: (Volume, d128!(100000), "deciliter", "deciliters"),
|
||||
Liter: (Volume, d128!(1000000), "liter", "liters"),
|
||||
Teaspoon: (Volume, d128!(4928.92159375), "teaspoon", "teaspoons"),
|
||||
Tablespoon: (Volume, d128!(14786.76478125), "tablespoon", "tablespoons"),
|
||||
FluidOunce: (Volume, d128!(29573.5295625), "fluid ounce", "fluid ounces"),
|
||||
Cup: (Volume, d128!(236588.2365), "cup", "cups"),
|
||||
Pint: (Volume, d128!(473176.473), "pint", "pints"),
|
||||
Quart: (Volume, d128!(946352.946), "quart", "quarts"),
|
||||
Gallon: (Volume, d128!(3785411.784), "gallon", "gallons"),
|
||||
OilBarrel: (Volume, d128!(158987294.928), "oil barrel", "oil barrels"),
|
||||
Milliliter: (Volume, d!(1000), "milliliter", "milliliters"),
|
||||
Centiliter: (Volume, d!(10000), "centiliter", "centiliters"),
|
||||
Deciliter: (Volume, d!(100000), "deciliter", "deciliters"),
|
||||
Liter: (Volume, d!(1000000), "liter", "liters"),
|
||||
Teaspoon: (Volume, d!(4928.92159375), "teaspoon", "teaspoons"),
|
||||
Tablespoon: (Volume, d!(14786.76478125), "tablespoon", "tablespoons"),
|
||||
FluidOunce: (Volume, d!(29573.5295625), "fluid ounce", "fluid ounces"),
|
||||
Cup: (Volume, d!(236588.2365), "cup", "cups"),
|
||||
Pint: (Volume, d!(473176.473), "pint", "pints"),
|
||||
Quart: (Volume, d!(946352.946), "quart", "quarts"),
|
||||
Gallon: (Volume, d!(3785411.784), "gallon", "gallons"),
|
||||
OilBarrel: (Volume, d!(158987294.928), "oil barrel", "oil barrels"),
|
||||
|
||||
Milligram: (Mass, d128!(0.001), "milligram", "milligrams"),
|
||||
Gram: (Mass, d128!(1), "gram", "grams"),
|
||||
Hectogram: (Mass, d128!(100), "hectogram", "hectograms"),
|
||||
Kilogram: (Mass, d128!(1000), "kilogram", "kilograms"),
|
||||
MetricTon: (Mass, d128!(1000000), "metric ton", "metric tons"),
|
||||
Ounce: (Mass, d128!(28.349523125), "ounce", "ounces"),
|
||||
Pound: (Mass, d128!(453.59237), "pound", "pounds"),
|
||||
Stone: (Mass, d128!(6350.29318), "stone", "stones"),
|
||||
ShortTon: (Mass, d128!(907184.74), "short ton", "short tons"),
|
||||
LongTon: (Mass, d128!(1016046.9088), "long ton", "long tons"),
|
||||
Milligram: (Mass, d!(0.001), "milligram", "milligrams"),
|
||||
Gram: (Mass, d!(1), "gram", "grams"),
|
||||
Hectogram: (Mass, d!(100), "hectogram", "hectograms"),
|
||||
Kilogram: (Mass, d!(1000), "kilogram", "kilograms"),
|
||||
MetricTon: (Mass, d!(1000000), "metric ton", "metric tons"),
|
||||
Ounce: (Mass, d!(28.349523125), "ounce", "ounces"),
|
||||
Pound: (Mass, d!(453.59237), "pound", "pounds"),
|
||||
Stone: (Mass, d!(6350.29318), "stone", "stones"),
|
||||
ShortTon: (Mass, d!(907184.74), "short ton", "short tons"),
|
||||
LongTon: (Mass, d!(1016046.9088), "long ton", "long tons"),
|
||||
|
||||
Bit: (DigitalStorage, d128!(1), "bit", "bits"),
|
||||
Kilobit: (DigitalStorage, d128!(1000), "kilobit", "kilobits"),
|
||||
Megabit: (DigitalStorage, d128!(1000000), "megabit", "megabits"),
|
||||
Gigabit: (DigitalStorage, d128!(1000000000), "gigabit", "gigabits"),
|
||||
Terabit: (DigitalStorage, d128!(1000000000000), "terabit", "terabits"),
|
||||
Petabit: (DigitalStorage, d128!(1000000000000000), "petabit", "petabits"),
|
||||
Exabit: (DigitalStorage, d128!(1000000000000000000), "exabit", "exabits"),
|
||||
Zettabit: (DigitalStorage, d128!(1000000000000000000000), "zettabit", "zettabits"),
|
||||
Yottabit: (DigitalStorage, d128!(1000000000000000000000000), "yottabit", "yottabits"),
|
||||
Kibibit: (DigitalStorage, d128!(1024), "kibibit", "kibibits"),
|
||||
Mebibit: (DigitalStorage, d128!(1048576), "mebibit", "mebibits"),
|
||||
Gibibit: (DigitalStorage, d128!(1073741824), "gibibit", "gibibits"),
|
||||
Tebibit: (DigitalStorage, d128!(1099511627776), "tebibit", "tebibits"),
|
||||
Pebibit: (DigitalStorage, d128!(1125899906842624), "pebibit", "pebibits"),
|
||||
Exbibit: (DigitalStorage, d128!(1152921504606846976), "exbibit", "exbibits"),
|
||||
Zebibit: (DigitalStorage, d128!(1180591620717411303424), "zebibit", "zebibits"),
|
||||
Yobibit: (DigitalStorage, d128!(1208925819614629174706176), "yobibit", "yobibits"),
|
||||
Byte: (DigitalStorage, d128!(8), "byte", "bytes"),
|
||||
Kilobyte: (DigitalStorage, d128!(8000), "kilobyte", "kilobytes"),
|
||||
Megabyte: (DigitalStorage, d128!(8000000), "megabyte", "megabytes"),
|
||||
Gigabyte: (DigitalStorage, d128!(8000000000), "gigabyte", "gigabytes"),
|
||||
Terabyte: (DigitalStorage, d128!(8000000000000), "terabyte", "terabytes"),
|
||||
Petabyte: (DigitalStorage, d128!(8000000000000000), "petabyte", "petabytes"),
|
||||
Exabyte: (DigitalStorage, d128!(8000000000000000000), "exabyte", "exabytes"),
|
||||
Zettabyte: (DigitalStorage, d128!(8000000000000000000000), "zettabyte", "zettabytes"),
|
||||
Yottabyte: (DigitalStorage, d128!(8000000000000000000000000), "yottabyte", "yottabytes"),
|
||||
Kibibyte: (DigitalStorage, d128!(8192), "kibibyte", "kibibytes"),
|
||||
Mebibyte: (DigitalStorage, d128!(8388608), "mebibyte", "mebibytes"),
|
||||
Gibibyte: (DigitalStorage, d128!(8589934592), "gibibyte", "gibibytes"),
|
||||
Tebibyte: (DigitalStorage, d128!(8796093022208), "tebibyte", "tebibytes"),
|
||||
Pebibyte: (DigitalStorage, d128!(9007199254740992), "pebibyte", "pebibytes"),
|
||||
Exbibyte: (DigitalStorage, d128!(9223372036854775808), "exbibyte", "exbibytes"),
|
||||
Zebibyte: (DigitalStorage, d128!(9444732965739290427392), "zebibyte", "zebibytes"),
|
||||
Yobibyte: (DigitalStorage, d128!(9671406556917033397649408), "yobibyte", "yobibytes"),
|
||||
Bit: (DigitalStorage, d!(1), "bit", "bits"),
|
||||
Kilobit: (DigitalStorage, d!(1000), "kilobit", "kilobits"),
|
||||
Megabit: (DigitalStorage, d!(1000000), "megabit", "megabits"),
|
||||
Gigabit: (DigitalStorage, d!(1000000000), "gigabit", "gigabits"),
|
||||
Terabit: (DigitalStorage, d!(1000000000000), "terabit", "terabits"),
|
||||
Petabit: (DigitalStorage, d!(1000000000000000), "petabit", "petabits"),
|
||||
Exabit: (DigitalStorage, d!(1000000000000000000), "exabit", "exabits"),
|
||||
Zettabit: (DigitalStorage, d!(1000000000000000000000), "zettabit", "zettabits"),
|
||||
Yottabit: (DigitalStorage, d!(1000000000000000000000000), "yottabit", "yottabits"),
|
||||
Kibibit: (DigitalStorage, d!(1024), "kibibit", "kibibits"),
|
||||
Mebibit: (DigitalStorage, d!(1048576), "mebibit", "mebibits"),
|
||||
Gibibit: (DigitalStorage, d!(1073741824), "gibibit", "gibibits"),
|
||||
Tebibit: (DigitalStorage, d!(1099511627776), "tebibit", "tebibits"),
|
||||
Pebibit: (DigitalStorage, d!(1125899906842624), "pebibit", "pebibits"),
|
||||
Exbibit: (DigitalStorage, d!(1152921504606846976), "exbibit", "exbibits"),
|
||||
Zebibit: (DigitalStorage, d!(1180591620717411303424), "zebibit", "zebibits"),
|
||||
Yobibit: (DigitalStorage, d!(1208925819614629174706176), "yobibit", "yobibits"),
|
||||
Byte: (DigitalStorage, d!(8), "byte", "bytes"),
|
||||
Kilobyte: (DigitalStorage, d!(8000), "kilobyte", "kilobytes"),
|
||||
Megabyte: (DigitalStorage, d!(8000000), "megabyte", "megabytes"),
|
||||
Gigabyte: (DigitalStorage, d!(8000000000), "gigabyte", "gigabytes"),
|
||||
Terabyte: (DigitalStorage, d!(8000000000000), "terabyte", "terabytes"),
|
||||
Petabyte: (DigitalStorage, d!(8000000000000000), "petabyte", "petabytes"),
|
||||
Exabyte: (DigitalStorage, d!(8000000000000000000), "exabyte", "exabytes"),
|
||||
Zettabyte: (DigitalStorage, d!(8000000000000000000000), "zettabyte", "zettabytes"),
|
||||
Yottabyte: (DigitalStorage, d!(8000000000000000000000000), "yottabyte", "yottabytes"),
|
||||
Kibibyte: (DigitalStorage, d!(8192), "kibibyte", "kibibytes"),
|
||||
Mebibyte: (DigitalStorage, d!(8388608), "mebibyte", "mebibytes"),
|
||||
Gibibyte: (DigitalStorage, d!(8589934592), "gibibyte", "gibibytes"),
|
||||
Tebibyte: (DigitalStorage, d!(8796093022208), "tebibyte", "tebibytes"),
|
||||
Pebibyte: (DigitalStorage, d!(9007199254740992), "pebibyte", "pebibytes"),
|
||||
Exbibyte: (DigitalStorage, d!(9223372036854775808), "exbibyte", "exbibytes"),
|
||||
Zebibyte: (DigitalStorage, d!(9444732965739290427392), "zebibyte", "zebibytes"),
|
||||
Yobibyte: (DigitalStorage, d!(9671406556917033397649408), "yobibyte", "yobibytes"),
|
||||
|
||||
BitsPerSecond: (DataTransferRate, d128!(1), "bit per second", "bits per second"),
|
||||
KilobitsPerSecond: (DataTransferRate, d128!(1000), "kilobit per second", "kilobits per second"),
|
||||
MegabitsPerSecond: (DataTransferRate, d128!(1000000), "megabit per second", "megabits per second"),
|
||||
GigabitsPerSecond: (DataTransferRate, d128!(1000000000), "gigabit per second", "gigabits per second"),
|
||||
TerabitsPerSecond: (DataTransferRate, d128!(1000000000000), "terabit per second", "terabits per second"),
|
||||
PetabitsPerSecond: (DataTransferRate, d128!(1000000000000000), "petabit per second", "petabits per second"),
|
||||
ExabitsPerSecond: (DataTransferRate, d128!(1000000000000000000), "exabit per second", "exabits per second"),
|
||||
ZettabitsPerSecond: (DataTransferRate, d128!(1000000000000000000000), "zettabit per second", "zettabits per second"),
|
||||
YottabitsPerSecond: (DataTransferRate, d128!(1000000000000000000000000), "yottabit per second", "yottabits per second"),
|
||||
KibibitsPerSecond: (DataTransferRate, d128!(1024), "kibibit per second", "kibibits per second"),
|
||||
MebibitsPerSecond: (DataTransferRate, d128!(1048576), "mebibit per second", "mebibits per second"),
|
||||
GibibitsPerSecond: (DataTransferRate, d128!(1073741824), "gibibit per second", "gibibits per second"),
|
||||
TebibitsPerSecond: (DataTransferRate, d128!(1099511627776), "tebibit per second", "tebibits per second"),
|
||||
PebibitsPerSecond: (DataTransferRate, d128!(1125899906842624), "pebibit per second", "pebibits per second"),
|
||||
ExbibitsPerSecond: (DataTransferRate, d128!(1152921504606846976), "exbibit per second", "exbibits per second"),
|
||||
ZebibitsPerSecond: (DataTransferRate, d128!(1180591620717411303424), "zebibit per second", "zebibits per second"),
|
||||
YobibitsPerSecond: (DataTransferRate, d128!(1208925819614629174706176), "yobibit per second", "yobibits per second"),
|
||||
BytesPerSecond: (DataTransferRate, d128!(8), "byte per second", "bytes per second"),
|
||||
KilobytesPerSecond: (DataTransferRate, d128!(8000), "kilobyte per second", "kilobytes per second"),
|
||||
MegabytesPerSecond: (DataTransferRate, d128!(8000000), "megabyte per second", "megabytes per second"),
|
||||
GigabytesPerSecond: (DataTransferRate, d128!(8000000000), "gigabyte per second", "gigabytes per second"),
|
||||
TerabytesPerSecond: (DataTransferRate, d128!(8000000000000), "terabyte per second", "terabytes per second"),
|
||||
PetabytesPerSecond: (DataTransferRate, d128!(8000000000000000), "petabyte per second", "petabytes per second"),
|
||||
ExabytesPerSecond: (DataTransferRate, d128!(8000000000000000000), "exabyte per second", "exabytes per second"),
|
||||
ZettabytesPerSecond: (DataTransferRate, d128!(8000000000000000000000), "zettabyte per second", "zettabytes per second"),
|
||||
YottabytesPerSecond: (DataTransferRate, d128!(8000000000000000000000000), "yottabyte per second", "yottabytes per second"),
|
||||
KibibytesPerSecond: (DataTransferRate, d128!(8192), "kibibyte per second", "kibibytes per second"),
|
||||
MebibytesPerSecond: (DataTransferRate, d128!(8388608), "mebibyte per second", "mebibytes per second"),
|
||||
GibibytesPerSecond: (DataTransferRate, d128!(8589934592), "gibibyte per second", "gibibytes per second"),
|
||||
TebibytesPerSecond: (DataTransferRate, d128!(8796093022208), "tebibyte per second", "tebibytes per second"),
|
||||
PebibytesPerSecond: (DataTransferRate, d128!(9007199254740992), "pebibyte per second", "pebibytes per second"),
|
||||
ExbibytesPerSecond: (DataTransferRate, d128!(9223372036854775808), "exbibyte per second", "exbibytes per second"),
|
||||
ZebibytesPerSecond: (DataTransferRate, d128!(9444732965739290427392), "zebibyte per second", "zebibytes per second"),
|
||||
YobibytesPerSecond: (DataTransferRate, d128!(9671406556917033397649408), "yobibyte per second", "yobibytes per second"),
|
||||
BitsPerSecond: (DataTransferRate, d!(1), "bit per second", "bits per second"),
|
||||
KilobitsPerSecond: (DataTransferRate, d!(1000), "kilobit per second", "kilobits per second"),
|
||||
MegabitsPerSecond: (DataTransferRate, d!(1000000), "megabit per second", "megabits per second"),
|
||||
GigabitsPerSecond: (DataTransferRate, d!(1000000000), "gigabit per second", "gigabits per second"),
|
||||
TerabitsPerSecond: (DataTransferRate, d!(1000000000000), "terabit per second", "terabits per second"),
|
||||
PetabitsPerSecond: (DataTransferRate, d!(1000000000000000), "petabit per second", "petabits per second"),
|
||||
ExabitsPerSecond: (DataTransferRate, d!(1000000000000000000), "exabit per second", "exabits per second"),
|
||||
ZettabitsPerSecond: (DataTransferRate, d!(1000000000000000000000), "zettabit per second", "zettabits per second"),
|
||||
YottabitsPerSecond: (DataTransferRate, d!(1000000000000000000000000), "yottabit per second", "yottabits per second"),
|
||||
KibibitsPerSecond: (DataTransferRate, d!(1024), "kibibit per second", "kibibits per second"),
|
||||
MebibitsPerSecond: (DataTransferRate, d!(1048576), "mebibit per second", "mebibits per second"),
|
||||
GibibitsPerSecond: (DataTransferRate, d!(1073741824), "gibibit per second", "gibibits per second"),
|
||||
TebibitsPerSecond: (DataTransferRate, d!(1099511627776), "tebibit per second", "tebibits per second"),
|
||||
PebibitsPerSecond: (DataTransferRate, d!(1125899906842624), "pebibit per second", "pebibits per second"),
|
||||
ExbibitsPerSecond: (DataTransferRate, d!(1152921504606846976), "exbibit per second", "exbibits per second"),
|
||||
ZebibitsPerSecond: (DataTransferRate, d!(1180591620717411303424), "zebibit per second", "zebibits per second"),
|
||||
YobibitsPerSecond: (DataTransferRate, d!(1208925819614629174706176), "yobibit per second", "yobibits per second"),
|
||||
BytesPerSecond: (DataTransferRate, d!(8), "byte per second", "bytes per second"),
|
||||
KilobytesPerSecond: (DataTransferRate, d!(8000), "kilobyte per second", "kilobytes per second"),
|
||||
MegabytesPerSecond: (DataTransferRate, d!(8000000), "megabyte per second", "megabytes per second"),
|
||||
GigabytesPerSecond: (DataTransferRate, d!(8000000000), "gigabyte per second", "gigabytes per second"),
|
||||
TerabytesPerSecond: (DataTransferRate, d!(8000000000000), "terabyte per second", "terabytes per second"),
|
||||
PetabytesPerSecond: (DataTransferRate, d!(8000000000000000), "petabyte per second", "petabytes per second"),
|
||||
ExabytesPerSecond: (DataTransferRate, d!(8000000000000000000), "exabyte per second", "exabytes per second"),
|
||||
ZettabytesPerSecond: (DataTransferRate, d!(8000000000000000000000), "zettabyte per second", "zettabytes per second"),
|
||||
YottabytesPerSecond: (DataTransferRate, d!(8000000000000000000000000), "yottabyte per second", "yottabytes per second"),
|
||||
KibibytesPerSecond: (DataTransferRate, d!(8192), "kibibyte per second", "kibibytes per second"),
|
||||
MebibytesPerSecond: (DataTransferRate, d!(8388608), "mebibyte per second", "mebibytes per second"),
|
||||
GibibytesPerSecond: (DataTransferRate, d!(8589934592), "gibibyte per second", "gibibytes per second"),
|
||||
TebibytesPerSecond: (DataTransferRate, d!(8796093022208), "tebibyte per second", "tebibytes per second"),
|
||||
PebibytesPerSecond: (DataTransferRate, d!(9007199254740992), "pebibyte per second", "pebibytes per second"),
|
||||
ExbibytesPerSecond: (DataTransferRate, d!(9223372036854775808), "exbibyte per second", "exbibytes per second"),
|
||||
ZebibytesPerSecond: (DataTransferRate, d!(9444732965739290427392), "zebibyte per second", "zebibytes per second"),
|
||||
YobibytesPerSecond: (DataTransferRate, d!(9671406556917033397649408), "yobibyte per second", "yobibytes per second"),
|
||||
|
||||
Millijoule: (Energy, d128!(0.001), "millijoule", "millijoules"),
|
||||
Joule: (Energy, d128!(1), "joule", "joules"),
|
||||
NewtonMeter: (Energy, d128!(1), "newton meter", "newton meters"),
|
||||
Kilojoule: (Energy, d128!(1000), "kilojoule", "kilojoules"),
|
||||
Megajoule: (Energy, d128!(1000000), "megajoule", "megajoules"),
|
||||
Gigajoule: (Energy, d128!(1000000000), "gigajoule", "gigajoules"),
|
||||
Terajoule: (Energy, d128!(1000000000000), "terajoule", "terajoules"),
|
||||
Calorie: (Energy, d128!(4.1868), "calorie", "calories"),
|
||||
KiloCalorie: (Energy, d128!(4186.8), "kilocalorie", "kilocalories"),
|
||||
BritishThermalUnit: (Energy, d128!(1055.05585262), "British thermal unit", "British thermal units"),
|
||||
WattHour: (Energy, d128!(3600), "watt-hour", "watt-hours"),
|
||||
KilowattHour: (Energy, d128!(3600000), "kilowatt-hour", "kilowatt-hours"),
|
||||
MegawattHour: (Energy, d128!(3600000000), "megawatt-hour", "megawatt-hours"),
|
||||
GigawattHour: (Energy, d128!(3600000000000), "gigawatt-hour", "gigawatt-hours"),
|
||||
TerawattHour: (Energy, d128!(3600000000000000), "terawatt-hour", "terawatt-hours"),
|
||||
PetawattHour: (Energy, d128!(3600000000000000000), "petawatt-hour", "petawatt-hours"),
|
||||
Millijoule: (Energy, d!(0.001), "millijoule", "millijoules"),
|
||||
Joule: (Energy, d!(1), "joule", "joules"),
|
||||
NewtonMeter: (Energy, d!(1), "newton meter", "newton meters"),
|
||||
Kilojoule: (Energy, d!(1000), "kilojoule", "kilojoules"),
|
||||
Megajoule: (Energy, d!(1000000), "megajoule", "megajoules"),
|
||||
Gigajoule: (Energy, d!(1000000000), "gigajoule", "gigajoules"),
|
||||
Terajoule: (Energy, d!(1000000000000), "terajoule", "terajoules"),
|
||||
Calorie: (Energy, d!(4.1868), "calorie", "calories"),
|
||||
KiloCalorie: (Energy, d!(4186.8), "kilocalorie", "kilocalories"),
|
||||
BritishThermalUnit: (Energy, d!(1055.05585262), "British thermal unit", "British thermal units"),
|
||||
WattHour: (Energy, d!(3600), "watt-hour", "watt-hours"),
|
||||
KilowattHour: (Energy, d!(3600000), "kilowatt-hour", "kilowatt-hours"),
|
||||
MegawattHour: (Energy, d!(3600000000), "megawatt-hour", "megawatt-hours"),
|
||||
GigawattHour: (Energy, d!(3600000000000), "gigawatt-hour", "gigawatt-hours"),
|
||||
TerawattHour: (Energy, d!(3600000000000000), "terawatt-hour", "terawatt-hours"),
|
||||
PetawattHour: (Energy, d!(3600000000000000000), "petawatt-hour", "petawatt-hours"),
|
||||
|
||||
Milliwatt: (Power, d128!(0.001), "milliwatt", "milliwatts"),
|
||||
Watt: (Power, d128!(1), "watt", "watts"),
|
||||
Kilowatt: (Power, d128!(1000), "kilowatt", "kilowatts"),
|
||||
Megawatt: (Power, d128!(1000000), "megawatt", "megawatts"),
|
||||
Gigawatt: (Power, d128!(1000000000), "gigawatt", "gigawatts"),
|
||||
Terawatt: (Power, d128!(1000000000000), "terawatt", "terawatts"),
|
||||
Petawatt: (Power, d128!(1000000000000000), "petawatt", "petawatts"),
|
||||
Milliwatt: (Power, d!(0.001), "milliwatt", "milliwatts"),
|
||||
Watt: (Power, d!(1), "watt", "watts"),
|
||||
Kilowatt: (Power, d!(1000), "kilowatt", "kilowatts"),
|
||||
Megawatt: (Power, d!(1000000), "megawatt", "megawatts"),
|
||||
Gigawatt: (Power, d!(1000000000), "gigawatt", "gigawatts"),
|
||||
Terawatt: (Power, d!(1000000000000), "terawatt", "terawatts"),
|
||||
Petawatt: (Power, d!(1000000000000000), "petawatt", "petawatts"),
|
||||
// probably inexact:
|
||||
BritishThermalUnitsPerMinute: (Power, d128!(0.0568690272188), "british thermal unit per minute", "british thermal units per minute"),
|
||||
BritishThermalUnitsPerMinute: (Power, d!(0.0568690272188), "british thermal unit per minute", "british thermal units per minute"),
|
||||
// probably inexact:
|
||||
BritishThermalUnitsPerHour: (Power, d128!(3.412141633128), "british thermal unit per hour", "british thermal units per hour"),
|
||||
BritishThermalUnitsPerHour: (Power, d!(3.412141633128), "british thermal unit per hour", "british thermal units per hour"),
|
||||
// exact according to wikipedia:
|
||||
Horsepower: (Power, d128!(745.69987158227022), "horsepower", "horsepower"),
|
||||
MetricHorsepower: (Power, d128!(735.49875), "metric horsepower", "metric horsepower"),
|
||||
Horsepower: (Power, d!(745.69987158227022), "horsepower", "horsepower"),
|
||||
MetricHorsepower: (Power, d!(735.49875), "metric horsepower", "metric horsepower"),
|
||||
|
||||
Milliampere: (ElectricCurrent, d128!(0.001), "milliampere", "milliamperes"),
|
||||
Ampere: (ElectricCurrent, d128!(1), "ampere", "amperes"),
|
||||
Kiloampere: (ElectricCurrent, d128!(1000), "kiloampere", "kiloamperes"),
|
||||
Abampere: (ElectricCurrent, d128!(10), "abampere", "abamperes"),
|
||||
Milliampere: (ElectricCurrent, d!(0.001), "milliampere", "milliamperes"),
|
||||
Ampere: (ElectricCurrent, d!(1), "ampere", "amperes"),
|
||||
Kiloampere: (ElectricCurrent, d!(1000), "kiloampere", "kiloamperes"),
|
||||
Abampere: (ElectricCurrent, d!(10), "abampere", "abamperes"),
|
||||
|
||||
Milliohm: (Resistance, d128!(0.001), "milliohm", "milliohms"),
|
||||
Ohm: (Resistance, d128!(1), "ohm", "ohms"),
|
||||
Kiloohm: (Resistance, d128!(1000), "kiloohm", "kiloohms"),
|
||||
Milliohm: (Resistance, d!(0.001), "milliohm", "milliohms"),
|
||||
Ohm: (Resistance, d!(1), "ohm", "ohms"),
|
||||
Kiloohm: (Resistance, d!(1000), "kiloohm", "kiloohms"),
|
||||
|
||||
Millivolt: (Voltage, d128!(0.001), "millivolt", "millivolts"),
|
||||
Volt: (Voltage, d128!(1), "volt", "volts"),
|
||||
Kilovolt: (Voltage, d128!(1000), "kilovolt", "kilovolts"),
|
||||
Millivolt: (Voltage, d!(0.001), "millivolt", "millivolts"),
|
||||
Volt: (Voltage, d!(1), "volt", "volts"),
|
||||
Kilovolt: (Voltage, d!(1000), "kilovolt", "kilovolts"),
|
||||
|
||||
Pascal: (Pressure, d128!(1), "pascal", "pascals"),
|
||||
Kilopascal: (Pressure, d128!(1000), "kilopascal", "kilopascals"),
|
||||
Atmosphere: (Pressure, d128!(101325), "atmosphere", "atmospheres"),
|
||||
Millibar: (Pressure, d128!(100), "millibar", "millibars"),
|
||||
Bar: (Pressure, d128!(100000), "bar", "bars"),
|
||||
InchOfMercury: (Pressure, d128!(3386.389), "inch of mercury", "inches of mercury"),
|
||||
Pascal: (Pressure, d!(1), "pascal", "pascals"),
|
||||
Kilopascal: (Pressure, d!(1000), "kilopascal", "kilopascals"),
|
||||
Atmosphere: (Pressure, d!(101325), "atmosphere", "atmospheres"),
|
||||
Millibar: (Pressure, d!(100), "millibar", "millibars"),
|
||||
Bar: (Pressure, d!(100000), "bar", "bars"),
|
||||
InchOfMercury: (Pressure, d!(3386.389), "inch of mercury", "inches of mercury"),
|
||||
// inexact:
|
||||
PoundsPerSquareInch: (Pressure, d128!(6894.757293168361), "pound per square inch", "pounds per square inch"),
|
||||
Torr: (Pressure, d128!(162.12), "torr", "torr"),
|
||||
PoundsPerSquareInch: (Pressure, d!(6894.757293168361), "pound per square inch", "pounds per square inch"),
|
||||
Torr: (Pressure, d!(162.12), "torr", "torr"),
|
||||
|
||||
Hertz: (Frequency, d128!(1), "hertz", "hertz"),
|
||||
Kilohertz: (Frequency, d128!(1000), "kilohertz", "kilohertz"),
|
||||
Megahertz: (Frequency, d128!(1000000), "megahertz", "megahertz"),
|
||||
Gigahertz: (Frequency, d128!(1000000000), "gigahertz", "gigahertz"),
|
||||
Terahertz: (Frequency, d128!(1000000000000), "terahertz", "terahertz"),
|
||||
Petahertz: (Frequency, d128!(1000000000000000), "petahertz", "petahertz"),
|
||||
RevolutionsPerMinute: (Frequency, d128!(60), "revolution per minute", "revolutions per minute"),
|
||||
Hertz: (Frequency, d!(1), "hertz", "hertz"),
|
||||
Kilohertz: (Frequency, d!(1000), "kilohertz", "kilohertz"),
|
||||
Megahertz: (Frequency, d!(1000000), "megahertz", "megahertz"),
|
||||
Gigahertz: (Frequency, d!(1000000000), "gigahertz", "gigahertz"),
|
||||
Terahertz: (Frequency, d!(1000000000000), "terahertz", "terahertz"),
|
||||
Petahertz: (Frequency, d!(1000000000000000), "petahertz", "petahertz"),
|
||||
RevolutionsPerMinute: (Frequency, d!(60), "revolution per minute", "revolutions per minute"),
|
||||
|
||||
KilometersPerHour: (Speed, d128!(1), "kilometer per hour", "kilometers per hour"),
|
||||
MetersPerSecond: (Speed, d128!(3.6), "meter per second", "meters per second"),
|
||||
MilesPerHour: (Speed, d128!(1.609344), "mile per hour", "miles per hour"),
|
||||
FeetPerSecond: (Speed, d128!(1.09728), "foot per second", "feet per second"),
|
||||
Knot: (Speed, d128!(1.852), "knot", "knots"),
|
||||
KilometersPerHour: (Speed, d!(1), "kilometer per hour", "kilometers per hour"),
|
||||
MetersPerSecond: (Speed, d!(3.6), "meter per second", "meters per second"),
|
||||
MilesPerHour: (Speed, d!(1.609344), "mile per hour", "miles per hour"),
|
||||
FeetPerSecond: (Speed, d!(1.09728), "foot per second", "feet per second"),
|
||||
Knot: (Speed, d!(1.852), "knot", "knots"),
|
||||
|
||||
Kelvin: (Temperature, d128!(0), "kelvin", "kelvin"),
|
||||
Celsius: (Temperature, d128!(0), "celsius", "celsius"),
|
||||
Fahrenheit: (Temperature, d128!(0), "fahrenheit", "fahrenheit"),
|
||||
Kelvin: (Temperature, d!(0), "kelvin", "kelvin"),
|
||||
Celsius: (Temperature, d!(0), "celsius", "celsius"),
|
||||
Fahrenheit: (Temperature, d!(0), "fahrenheit", "fahrenheit"),
|
||||
);
|
||||
|
||||
/// Returns the conversion factor between two units.
|
||||
@ -320,7 +320,7 @@ create_units!(
|
||||
/// is 60.
|
||||
///
|
||||
/// This is not sufficient for [`Temperature`] units.
|
||||
pub fn get_conversion_factor(unit: Unit, to_unit: Unit) -> d128 {
|
||||
pub fn get_conversion_factor(unit: Unit, to_unit: Unit) -> D128 {
|
||||
unit.weight() / to_unit.weight()
|
||||
}
|
||||
|
||||
@ -336,14 +336,14 @@ pub fn convert(number: Number, to_unit: Unit) -> Result<Number, String> {
|
||||
if number.unit.category() == UnitType::Temperature {
|
||||
match (number.unit, to_unit) {
|
||||
(Kelvin, Kelvin) => ok(value),
|
||||
(Kelvin, Celsius) => ok(value-d128!(273.15)),
|
||||
(Kelvin, Fahrenheit) => ok(value*d128!(1.8)-d128!(459.67)),
|
||||
(Kelvin, Celsius) => ok(value-d!(273.15)),
|
||||
(Kelvin, Fahrenheit) => ok(value*d!(1.8)-d!(459.67)),
|
||||
(Celsius, Celsius) => ok(value),
|
||||
(Celsius, Kelvin) => ok(value+d128!(273.15)),
|
||||
(Celsius, Fahrenheit) => ok(value*d128!(1.8)+d128!(32)),
|
||||
(Celsius, Kelvin) => ok(value+d!(273.15)),
|
||||
(Celsius, Fahrenheit) => ok(value*d!(1.8)+d!(32)),
|
||||
(Fahrenheit, Fahrenheit) => ok(value),
|
||||
(Fahrenheit, Kelvin) => ok((value+d128!(459.67))*d128!(5)/d128!(9)),
|
||||
(Fahrenheit, Celsius) => ok((value-d128!(32))/d128!(1.8)),
|
||||
(Fahrenheit, Kelvin) => ok((value+d!(459.67))*d!(5)/d!(9)),
|
||||
(Fahrenheit, Celsius) => ok((value-d!(32))/d!(1.8)),
|
||||
_ => Err(format!("Error converting temperature {:?} to {:?}", number.unit, to_unit)),
|
||||
}
|
||||
} else {
|
||||
@ -400,113 +400,113 @@ pub fn subtract(left: Number, right: Number) -> Result<Number, String> {
|
||||
pub fn to_ideal_unit(number: Number) -> Number {
|
||||
let value = number.value * number.unit.weight();
|
||||
if number.unit.category() == Length {
|
||||
if value >= d128!(1000000000000000000) { // ≈ 0.1 light years
|
||||
if value >= d!(1000000000000000000) { // ≈ 0.1 light years
|
||||
return Number::new(value/LightYear.weight(), LightYear)
|
||||
} else if value >= d128!(1000000) { // 1 km
|
||||
} else if value >= d!(1000000) { // 1 km
|
||||
return Number::new(value/Kilometer.weight(), Kilometer)
|
||||
} else if value >= d128!(1000) { // 1 m
|
||||
} else if value >= d!(1000) { // 1 m
|
||||
return Number::new(value/Meter.weight(), Meter)
|
||||
} else if value >= d128!(10) { // 1 cm
|
||||
} else if value >= d!(10) { // 1 cm
|
||||
return Number::new(value/Centimeter.weight(), Centimeter)
|
||||
} else {
|
||||
return Number::new(value, Millimeter)
|
||||
}
|
||||
} else if number.unit.category() == Time {
|
||||
if value >= d128!(31556952000000000) {
|
||||
if value >= d!(31556952000000000) {
|
||||
return Number::new(value/Year.weight(), Year);
|
||||
} else if value >= d128!(86400000000000) {
|
||||
} else if value >= d!(86400000000000) {
|
||||
return Number::new(value/Day.weight(), Day);
|
||||
} else if value >= d128!(3600000000000) {
|
||||
} else if value >= d!(3600000000000) {
|
||||
return Number::new(value/Hour.weight(), Hour);
|
||||
} else if value >= d128!(60000000000) {
|
||||
} else if value >= d!(60000000000) {
|
||||
return Number::new(value/Minute.weight(), Minute);
|
||||
} else if value >= d128!(1000000000) {
|
||||
} else if value >= d!(1000000000) {
|
||||
return Number::new(value/Second.weight(), Second);
|
||||
} else if value >= d128!(1000000) {
|
||||
} else if value >= d!(1000000) {
|
||||
return Number::new(value/Millisecond.weight(), Millisecond);
|
||||
} else if value >= d128!(1000) {
|
||||
} else if value >= d!(1000) {
|
||||
return Number::new(value/Microsecond.weight(), Microsecond);
|
||||
} else {
|
||||
return Number::new(value, Nanosecond);
|
||||
}
|
||||
} else if number.unit.category() == Area {
|
||||
if value >= d128!(1000000000000) { // 1 km2
|
||||
if value >= d!(1000000000000) { // 1 km2
|
||||
return Number::new(value/SquareKilometer.weight(), SquareKilometer)
|
||||
} else if value >= d128!(10000000000) { // 1 hectare
|
||||
} else if value >= d!(10000000000) { // 1 hectare
|
||||
return Number::new(value/Hectare.weight(), Hectare)
|
||||
} else if value >= d128!(1000000) { // 1 m2
|
||||
} else if value >= d!(1000000) { // 1 m2
|
||||
return Number::new(value/SquareMeter.weight(), SquareMeter)
|
||||
} else if value >= d128!(100) { // 1 cm2
|
||||
} else if value >= d!(100) { // 1 cm2
|
||||
return Number::new(value/SquareCentimeter.weight(), SquareCentimeter)
|
||||
} else {
|
||||
return Number::new(value, SquareMillimeter)
|
||||
}
|
||||
} else if number.unit.category() == Volume {
|
||||
if value >= d128!(1000000000000000000) { // 1 km3
|
||||
if value >= d!(1000000000000000000) { // 1 km3
|
||||
return Number::new(value/CubicKilometer.weight(), CubicKilometer)
|
||||
} else if value >= d128!(1000000000) { // 1 m3
|
||||
} else if value >= d!(1000000000) { // 1 m3
|
||||
return Number::new(value/CubicMeter.weight(), CubicMeter)
|
||||
} else if value >= d128!(1000000) { // 1 l
|
||||
} else if value >= d!(1000000) { // 1 l
|
||||
return Number::new(value/Liter.weight(), Liter)
|
||||
} else if value >= d128!(1000) { // 1 ml
|
||||
} else if value >= d!(1000) { // 1 ml
|
||||
return Number::new(value/Milliliter.weight(), Milliliter)
|
||||
} else {
|
||||
return Number::new(value, CubicMillimeter)
|
||||
}
|
||||
} else if number.unit.category() == Energy {
|
||||
if value >= d128!(3600000000000000000) { // 1 petawatthour
|
||||
if value >= d!(3600000000000000000) { // 1 petawatthour
|
||||
return Number::new(value/PetawattHour.weight(), PetawattHour)
|
||||
} else if value >= d128!(3600000000000000) { // 1 terawatthour
|
||||
} else if value >= d!(3600000000000000) { // 1 terawatthour
|
||||
return Number::new(value/TerawattHour.weight(), TerawattHour)
|
||||
} else if value >= d128!(3600000000000) { // 1 gigawatthour
|
||||
} else if value >= d!(3600000000000) { // 1 gigawatthour
|
||||
return Number::new(value/GigawattHour.weight(), GigawattHour)
|
||||
} else if value >= d128!(3600000000) { // 1 megawatthour
|
||||
} else if value >= d!(3600000000) { // 1 megawatthour
|
||||
return Number::new(value/MegawattHour.weight(), MegawattHour)
|
||||
} else if value >= d128!(3600000) { // 1 kilowatthour
|
||||
} else if value >= d!(3600000) { // 1 kilowatthour
|
||||
return Number::new(value/KilowattHour.weight(), KilowattHour)
|
||||
} else if value >= d128!(3600) { // 1 watthour
|
||||
} else if value >= d!(3600) { // 1 watthour
|
||||
return Number::new(value/WattHour.weight(), WattHour)
|
||||
} else if value >= d128!(1) { // 1 joule
|
||||
} else if value >= d!(1) { // 1 joule
|
||||
return Number::new(value, Joule)
|
||||
} else {
|
||||
return Number::new(value/Millijoule.weight(), Millijoule)
|
||||
}
|
||||
} else if number.unit.category() == Power {
|
||||
if value >= d128!(1000000000000000) { // 1 petawatt
|
||||
if value >= d!(1000000000000000) { // 1 petawatt
|
||||
return Number::new(value/Petawatt.weight(), Petawatt)
|
||||
} else if value >= d128!(1000000000000) { // 1 terawatt
|
||||
} else if value >= d!(1000000000000) { // 1 terawatt
|
||||
return Number::new(value/Terawatt.weight(), Terawatt)
|
||||
} else if value >= d128!(1000000000) { // 1 gigawatt
|
||||
} else if value >= d!(1000000000) { // 1 gigawatt
|
||||
return Number::new(value/Gigawatt.weight(), Gigawatt)
|
||||
} else if value >= d128!(1000000) { // megawatt
|
||||
} else if value >= d!(1000000) { // megawatt
|
||||
return Number::new(value/Megawatt.weight(), Megawatt)
|
||||
} else if value >= d128!(1000) { // 1 kilowatt
|
||||
} else if value >= d!(1000) { // 1 kilowatt
|
||||
return Number::new(value/Kilowatt.weight(), Kilowatt)
|
||||
} else if value >= d128!(1) { // 1 watt
|
||||
} else if value >= d!(1) { // 1 watt
|
||||
return Number::new(value, Watt)
|
||||
} else {
|
||||
return Number::new(value/Milliwatt.weight(), Milliwatt)
|
||||
}
|
||||
} else if number.unit.category() == ElectricCurrent {
|
||||
if value >= d128!(1000) { // 1 kiloampere
|
||||
if value >= d!(1000) { // 1 kiloampere
|
||||
return Number::new(value/Kiloampere.weight(), Kiloampere)
|
||||
} else if value >= d128!(1) { // 1 ampere
|
||||
} else if value >= d!(1) { // 1 ampere
|
||||
return Number::new(value, Ampere)
|
||||
} else {
|
||||
return Number::new(value/Milliampere.weight(), Milliampere)
|
||||
}
|
||||
} else if number.unit.category() == Resistance {
|
||||
if value >= d128!(1000) { // 1 kiloohm
|
||||
if value >= d!(1000) { // 1 kiloohm
|
||||
return Number::new(value/Kiloohm.weight(), Kiloohm)
|
||||
} else if value >= d128!(1) { // 1 ohm
|
||||
} else if value >= d!(1) { // 1 ohm
|
||||
return Number::new(value, Ohm)
|
||||
} else {
|
||||
return Number::new(value/Milliohm.weight(), Milliohm)
|
||||
}
|
||||
} else if number.unit.category() == Voltage {
|
||||
if value >= d128!(1000) { // 1 kilovolt
|
||||
if value >= d!(1000) { // 1 kilovolt
|
||||
return Number::new(value/Kilovolt.weight(), Kilovolt)
|
||||
} else if value >= d128!(1) { // 1 volt
|
||||
} else if value >= d!(1) { // 1 volt
|
||||
return Number::new(value, Volt)
|
||||
} else {
|
||||
return Number::new(value/Millivolt.weight(), Millivolt)
|
||||
@ -519,15 +519,15 @@ pub fn to_ideal_unit(number: Number) -> Number {
|
||||
pub fn to_ideal_joule_unit(number: Number) -> Number {
|
||||
let value = number.value * number.unit.weight();
|
||||
if number.unit.category() == Energy {
|
||||
if value >= d128!(1000000000000) { // 1 terajoule
|
||||
if value >= d!(1000000000000) { // 1 terajoule
|
||||
return Number::new(value/Terajoule.weight(), Terajoule)
|
||||
} else if value >= d128!(1000000000) { // 1 gigajoule
|
||||
} else if value >= d!(1000000000) { // 1 gigajoule
|
||||
return Number::new(value/Gigajoule.weight(), Gigajoule)
|
||||
} else if value >= d128!(1000000) { // 1 megajoule
|
||||
} else if value >= d!(1000000) { // 1 megajoule
|
||||
return Number::new(value/Megajoule.weight(), Megajoule)
|
||||
} else if value >= d128!(1000) { // 1 kilojoule
|
||||
} else if value >= d!(1000) { // 1 kilojoule
|
||||
return Number::new(value/Kilojoule.weight(), Kilojoule)
|
||||
} else if value >= d128!(1) { // 1 joule
|
||||
} else if value >= d!(1) { // 1 joule
|
||||
return Number::new(value/Joule.weight(), Joule)
|
||||
} else {
|
||||
return Number::new(value/Millijoule.weight(), Millijoule)
|
||||
@ -754,6 +754,15 @@ pub fn modulo(left: Number, right: Number) -> Result<Number, String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn do_pow(left: D128, right: D128) -> D128 {
|
||||
// Do pow with d256 for higher accuracy
|
||||
let left = D256::try_from(left.transmute()).unwrap();
|
||||
let right = D256::try_from(right.transmute()).unwrap();
|
||||
let result = left.pow(right);
|
||||
let result_d128: D128 = result.transmute();
|
||||
result_d128
|
||||
}
|
||||
|
||||
/// Returns a [`Number`] to the power of another [`Number`]
|
||||
///
|
||||
/// - If you take [`Length`] to the power of [`NoType`], the result has a unit of [`Area`].
|
||||
@ -765,28 +774,28 @@ pub fn pow(left: Number, right: Number) -> Result<Number, String> {
|
||||
let rcat = left.unit.category();
|
||||
if left.unit == NoUnit && right.unit == NoUnit {
|
||||
// 3 ^ 2
|
||||
Ok(Number::new(left.value.pow(right.value), left.unit))
|
||||
} else if right.value == d128!(1) && right.unit == NoUnit {
|
||||
Ok(Number::new(do_pow(left.value, right.value), left.unit))
|
||||
} else if right.value == d!(1) && right.unit == NoUnit {
|
||||
Ok(left)
|
||||
} else if lcat == Length && right.unit == NoUnit && right.value == d128!(2) {
|
||||
} else if lcat == Length && right.unit == NoUnit && right.value == d!(2) {
|
||||
// x km ^ 2
|
||||
let result = (left.value * left.unit.weight()).pow(right.value);
|
||||
let result = do_pow(left.value * left.unit.weight(), right.value);
|
||||
Ok(to_ideal_unit(Number::new(result, SquareMillimeter)))
|
||||
} else if lcat == Length && right.unit == NoUnit && right.value == d128!(3) {
|
||||
} else if lcat == Length && right.unit == NoUnit && right.value == d!(3) {
|
||||
// x km ^ 3
|
||||
let result = (left.value * left.unit.weight()).pow(right.value);
|
||||
let result = do_pow(left.value * left.unit.weight(), right.value);
|
||||
Ok(to_ideal_unit(Number::new(result, CubicMillimeter)))
|
||||
} else if lcat == Length && rcat == Length && right.value == d128!(1) {
|
||||
} else if lcat == Length && rcat == Length && right.value == d!(1) {
|
||||
// x km ^ 1 km
|
||||
Ok(multiply(left, right)?)
|
||||
} else if lcat == Length && rcat == Length && right.value == d128!(2) {
|
||||
} else if lcat == Length && rcat == Length && right.value == d!(2) {
|
||||
// x km ^ 2 km
|
||||
let pow2 = multiply(left, Number::new(d128!(1), right.unit))?;
|
||||
let pow3 = multiply(pow2, Number::new(d128!(1), right.unit))?;
|
||||
let pow2 = multiply(left, Number::new(d!(1), right.unit))?;
|
||||
let pow3 = multiply(pow2, Number::new(d!(1), right.unit))?;
|
||||
Ok(pow3)
|
||||
} else if lcat == Length && rcat == Area && right.value == d128!(1) {
|
||||
} else if lcat == Length && rcat == Area && right.value == d!(1) {
|
||||
// x km ^ km2
|
||||
Ok(multiply(left, Number::new(d128!(1), right.unit))?)
|
||||
Ok(multiply(left, Number::new(d!(1), right.unit))?)
|
||||
} else {
|
||||
Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
||||
}
|
||||
@ -794,6 +803,8 @@ pub fn pow(left: Number, right: Number) -> Result<Number, String> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use fastnum::decimal::Context;
|
||||
|
||||
use super::*;
|
||||
|
||||
macro_rules! assert_float_eq {
|
||||
@ -808,7 +819,7 @@ mod tests {
|
||||
use std::str::FromStr;
|
||||
|
||||
let value_string = &value.to_string();
|
||||
let value_d128 = d128::from_str(value_string).unwrap();
|
||||
let value_d128 = D128::from_str(value_string, Context::default()).unwrap();
|
||||
let number = Number::new(value_d128, unit);
|
||||
|
||||
let result = convert(number, to_unit);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user