Merge pull request #22 from djmattyg007/data_rates

Add support for data rate units
This commit is contained in:
Kasper 2021-08-16 06:00:03 +02:00 committed by GitHub
commit 1196fcf458
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 357 additions and 0 deletions

View File

@ -1,5 +1,6 @@
## Next ## Next
- Add support for dividing length units by speed units (like 10 km / 100 kph) - Add support for dividing length units by speed units (like 10 km / 100 kph)
- Add support for data transfer rate units (eg. megabytes per second)
## 1.7.0 - 2021 Jul 14 ## 1.7.0 - 2021 Jul 14
- Add operator words `plus`, `minus` and `times` - Add operator words `plus`, `minus` and `times`

View File

@ -428,6 +428,16 @@ fn parse_word(word: &str, lexer: &mut Lexer) -> Result<(), String> {
"zib" | "zebibyte" | "zebibytes" => Token::Unit(Zebibyte), "zib" | "zebibyte" | "zebibytes" => Token::Unit(Zebibyte),
"yib" | "yobibyte" | "yobibytes" => Token::Unit(Yobibyte), "yib" | "yobibyte" | "yobibytes" => Token::Unit(Yobibyte),
"bps" => Token::Unit(BitsPerSecond),
"kbps" => Token::Unit(KilobitsPerSecond),
"mbps" => Token::Unit(MegabitsPerSecond),
"gbps" => Token::Unit(GigabitsPerSecond),
"tbps" => Token::Unit(TerabitsPerSecond),
"pbps" => Token::Unit(PetabitsPerSecond),
"ebps" => Token::Unit(ExabitsPerSecond),
"zbps" => Token::Unit(ZettabitsPerSecond),
"ybps" => Token::Unit(YottabitsPerSecond),
"millijoule" | "millijoules" => Token::Unit(Millijoule), "millijoule" | "millijoules" => Token::Unit(Millijoule),
"j"| "joule" | "joules" => Token::Unit(Joule), "j"| "joule" | "joules" => Token::Unit(Joule),
"nm" => Token::Unit(NewtonMeter), "nm" => Token::Unit(NewtonMeter),
@ -750,6 +760,142 @@ pub fn lex(input: &str, remove_trailing_operator: bool, default_degree: Unit) ->
(Token::Unit(Foot), Token::LexerKeyword(Per), Token::Unit(Second)) => { (Token::Unit(Foot), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(FeetPerSecond); tokens[token_index-2] = Token::Unit(FeetPerSecond);
}, },
// bits per second
(Token::Unit(Bit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(BitsPerSecond);
},
// kilobits per second
(Token::Unit(Kilobit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(KilobitsPerSecond);
},
// megabits per second
(Token::Unit(Megabit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(MegabitsPerSecond);
},
// gigabits per second
(Token::Unit(Gigabit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(GigabitsPerSecond);
},
// terabits per second
(Token::Unit(Terabit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(TerabitsPerSecond);
},
// petabits per second
(Token::Unit(Petabit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(PetabitsPerSecond);
},
// exabits per second
(Token::Unit(Exabit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(ExabitsPerSecond);
},
// zettabits per second
(Token::Unit(Zettabit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(ZettabitsPerSecond);
},
// yottabits per second
(Token::Unit(Yottabit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(YottabitsPerSecond);
},
// kibibits per second
(Token::Unit(Kibibit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(KibibitsPerSecond);
},
// mebibits per second
(Token::Unit(Mebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(MebibitsPerSecond);
},
// gibibits per second
(Token::Unit(Gibibit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(GibibitsPerSecond);
},
// tebibits per second
(Token::Unit(Tebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(TebibitsPerSecond);
},
// pebibits per second
(Token::Unit(Pebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(PebibitsPerSecond);
},
// exbibits per second
(Token::Unit(Exbibit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(ExbibitsPerSecond);
},
// zebibits per second
(Token::Unit(Zebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(ZebibitsPerSecond);
},
// yobibits per second
(Token::Unit(Yobibit), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(YobibitsPerSecond);
},
// bytes per second
(Token::Unit(Byte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(BytesPerSecond);
},
// kilobytes per second
(Token::Unit(Kilobyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(KilobytesPerSecond);
},
// megabytes per second
(Token::Unit(Megabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(MegabytesPerSecond);
},
// gigabytes per second
(Token::Unit(Gigabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(GigabytesPerSecond);
},
// terabytes per second
(Token::Unit(Terabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(TerabytesPerSecond);
},
// petabytes per second
(Token::Unit(Petabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(PetabytesPerSecond);
},
// exabytes per second
(Token::Unit(Exabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(ExabytesPerSecond);
},
// zettabytes per second
(Token::Unit(Zettabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(ZettabytesPerSecond);
},
// yottabytes per second
(Token::Unit(Yottabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(YottabytesPerSecond);
},
// kibibytes per second
(Token::Unit(Kibibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(KibibytesPerSecond);
},
// mebibytes per second
(Token::Unit(Mebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(MebibytesPerSecond);
},
// gibibytes per second
(Token::Unit(Gibibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(GibibytesPerSecond);
},
// tebibytes per second
(Token::Unit(Tebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(TebibytesPerSecond);
},
// pebibytes per second
(Token::Unit(Pebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(PebibytesPerSecond);
},
// exbibytes per second
(Token::Unit(Exbibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(ExbibytesPerSecond);
},
// zebibytes per second
(Token::Unit(Zebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(ZebibytesPerSecond);
},
// yobibytes per second
(Token::Unit(Yobibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => {
tokens[token_index-2] = Token::Unit(YobibytesPerSecond);
},
// btu/min // btu/min
(Token::Unit(BritishThermalUnit), Token::LexerKeyword(Per), Token::Unit(Minute)) => { (Token::Unit(BritishThermalUnit), Token::LexerKeyword(Per), Token::Unit(Minute)) => {
tokens[token_index-2] = Token::Unit(BritishThermalUnitsPerMinute); tokens[token_index-2] = Token::Unit(BritishThermalUnitsPerMinute);
@ -800,6 +946,7 @@ mod tests {
fn test_lex() { fn test_lex() {
let strip_operator_spacing = Regex::new(r" ([+\-*/]) ").unwrap(); let strip_operator_spacing = Regex::new(r" ([+\-*/]) ").unwrap();
let strip_afterdigit_spacing = Regex::new(r"(\d) ").unwrap(); let strip_afterdigit_spacing = Regex::new(r"(\d) ").unwrap();
let nonplural_data_units = Regex::new(r"(bit|byte)s").unwrap();
let run_lex = |input: &str, expected_tokens: Vec<Token>| { let run_lex = |input: &str, expected_tokens: Vec<Token>| {
let tokens = match lex(input, false, Unit::Celsius) { let tokens = match lex(input, false, Unit::Celsius) {
@ -827,6 +974,16 @@ mod tests {
assert!(tokens_afterdigit_stripped_spaces == expected_tokens, "{}", info_msg); assert!(tokens_afterdigit_stripped_spaces == expected_tokens, "{}", info_msg);
}; };
let run_datarate_lex = |input: &str, expected_tokens: Vec<Token>| {
run_lex(input, (*expected_tokens).to_vec());
// Prove plural and non-plural data units behave identically
let input_nonplural_units = nonplural_data_units.replace_all(input, "$1");
let tokens_nonplural_units = lex(&input_nonplural_units, false, Unit::Celsius).unwrap();
let info_msg = format!("run_datarate_lex input: {}\nexpected: {:?}\nreceived: {:?}", input, expected_tokens, tokens_nonplural_units);
assert!(tokens_nonplural_units == expected_tokens, "{}", info_msg);
};
run_lex("88 kilometres * 2", vec![numtok!(88), Token::Unit(Kilometer), Token::Operator(Multiply), numtok!(2)]); run_lex("88 kilometres * 2", vec![numtok!(88), Token::Unit(Kilometer), Token::Operator(Multiply), numtok!(2)]);
run_lex("100 nmi", vec![numtok!(100), Token::Unit(NauticalMile)]); run_lex("100 nmi", vec![numtok!(100), Token::Unit(NauticalMile)]);
run_lex("101 nautical miles", vec![numtok!(101), Token::Unit(NauticalMile)]); run_lex("101 nautical miles", vec![numtok!(101), Token::Unit(NauticalMile)]);
@ -861,6 +1018,85 @@ mod tests {
run_lex("3 short tons", vec![numtok!(3), Token::Unit(ShortTon)]); run_lex("3 short tons", vec![numtok!(3), Token::Unit(ShortTon)]);
run_lex("4 lt", vec![numtok!(4), Token::Unit(LongTon)]); run_lex("4 lt", vec![numtok!(4), Token::Unit(LongTon)]);
run_lex("4 long tonnes", vec![numtok!(4), Token::Unit(LongTon)]); run_lex("4 long tonnes", vec![numtok!(4), Token::Unit(LongTon)]);
run_datarate_lex("1 bit", vec![numtok!(1), Token::Unit(Bit)]);
run_datarate_lex("8 bits", vec![numtok!(8), Token::Unit(Bit)]);
run_datarate_lex("63 kilobits", vec![numtok!(63), Token::Unit(Kilobit)]);
run_datarate_lex("32 megabits", vec![numtok!(32), Token::Unit(Megabit)]);
run_datarate_lex("3.5 gigabits", vec![numtok!(3.5), Token::Unit(Gigabit)]);
run_datarate_lex("2.1 terabits", vec![numtok!(2.1), Token::Unit(Terabit)]);
run_datarate_lex("1.08 petabits", vec![numtok!(1.08), Token::Unit(Petabit)]);
run_datarate_lex("0.73 exabits", vec![numtok!(0.73), Token::Unit(Exabit)]);
run_datarate_lex("0.49 zettabits", vec![numtok!(0.49), Token::Unit(Zettabit)]);
run_datarate_lex("0.23 yottabits", vec![numtok!(0.23), Token::Unit(Yottabit)]);
run_datarate_lex("63 kibibits", vec![numtok!(63), Token::Unit(Kibibit)]);
run_datarate_lex("32 mebibits", vec![numtok!(32), Token::Unit(Mebibit)]);
run_datarate_lex("3.5 gibibits", vec![numtok!(3.5), Token::Unit(Gibibit)]);
run_datarate_lex("2.1 tebibits", vec![numtok!(2.1), Token::Unit(Tebibit)]);
run_datarate_lex("1.08 pebibits", vec![numtok!(1.08), Token::Unit(Pebibit)]);
run_datarate_lex("0.73 exbibits", vec![numtok!(0.73), Token::Unit(Exbibit)]);
run_datarate_lex("0.49 zebibits", vec![numtok!(0.49), Token::Unit(Zebibit)]);
run_datarate_lex("0.23 yobibits", vec![numtok!(0.23), Token::Unit(Yobibit)]);
run_datarate_lex("1 byte", vec![numtok!(1), Token::Unit(Byte)]);
run_datarate_lex("3 bytes", vec![numtok!(3), Token::Unit(Byte)]);
run_datarate_lex("63 kilobytes", vec![numtok!(63), Token::Unit(Kilobyte)]);
run_datarate_lex("32 megabytes", vec![numtok!(32), Token::Unit(Megabyte)]);
run_datarate_lex("3.5 gigabytes", vec![numtok!(3.5), Token::Unit(Gigabyte)]);
run_datarate_lex("2.1 terabytes", vec![numtok!(2.1), Token::Unit(Terabyte)]);
run_datarate_lex("1.08 petabytes", vec![numtok!(1.08), Token::Unit(Petabyte)]);
run_datarate_lex("0.73 exabytes", vec![numtok!(0.73), Token::Unit(Exabyte)]);
run_datarate_lex("0.49 zettabytes", vec![numtok!(0.49), Token::Unit(Zettabyte)]);
run_datarate_lex("0.23 yottabytes", vec![numtok!(0.23), Token::Unit(Yottabyte)]);
run_datarate_lex("63 kibibytes", vec![numtok!(63), Token::Unit(Kibibyte)]);
run_datarate_lex("32 mebibytes", vec![numtok!(32), Token::Unit(Mebibyte)]);
run_datarate_lex("3.5 gibibytes", vec![numtok!(3.5), Token::Unit(Gibibyte)]);
run_datarate_lex("2.1 tebibytes", vec![numtok!(2.1), Token::Unit(Tebibyte)]);
run_datarate_lex("1.08 pebibytes", vec![numtok!(1.08), Token::Unit(Pebibyte)]);
run_datarate_lex("0.73 exbibytes", vec![numtok!(0.73), Token::Unit(Exbibyte)]);
run_datarate_lex("0.49 zebibytes", vec![numtok!(0.49), Token::Unit(Zebibyte)]);
run_datarate_lex("0.23 yobibytes", vec![numtok!(0.23), Token::Unit(Yobibyte)]);
run_lex("432 bps", vec![numtok!(432), Token::Unit(BitsPerSecond)]);
run_lex("56 kbps", vec![numtok!(56), Token::Unit(KilobitsPerSecond)]);
run_lex("12 mbps", vec![numtok!(12), Token::Unit(MegabitsPerSecond)]);
run_lex("4.2 gbps", vec![numtok!(4.2), Token::Unit(GigabitsPerSecond)]);
run_lex("2.2 tbps", vec![numtok!(2.2), Token::Unit(TerabitsPerSecond)]);
run_lex("1.7 pbps", vec![numtok!(1.7), Token::Unit(PetabitsPerSecond)]);
run_lex("0.99 ebps", vec![numtok!(0.99), Token::Unit(ExabitsPerSecond)]);
run_lex("0.64 zbps", vec![numtok!(0.64), Token::Unit(ZettabitsPerSecond)]);
run_lex("0.278 ybps", vec![numtok!(0.278), Token::Unit(YottabitsPerSecond)]);
run_datarate_lex("4 bits per second", vec![numtok!(4), Token::Unit(BitsPerSecond)]);
run_datarate_lex("5 kilobits per second", vec![numtok!(5), Token::Unit(KilobitsPerSecond)]);
run_datarate_lex("6 megabits per second", vec![numtok!(6), Token::Unit(MegabitsPerSecond)]);
run_datarate_lex("7 gigabits per second", vec![numtok!(7), Token::Unit(GigabitsPerSecond)]);
run_datarate_lex("8 terabits per second", vec![numtok!(8), Token::Unit(TerabitsPerSecond)]);
run_datarate_lex("9 petabits per second", vec![numtok!(9), Token::Unit(PetabitsPerSecond)]);
run_datarate_lex("10 exabits per second", vec![numtok!(10), Token::Unit(ExabitsPerSecond)]);
run_datarate_lex("11 zettabits per second", vec![numtok!(11), Token::Unit(ZettabitsPerSecond)]);
run_datarate_lex("12 yottabits per second", vec![numtok!(12), Token::Unit(YottabitsPerSecond)]);
run_datarate_lex("13 kibibits per second", vec![numtok!(13), Token::Unit(KibibitsPerSecond)]);
run_datarate_lex("14 mebibits per second", vec![numtok!(14), Token::Unit(MebibitsPerSecond)]);
run_datarate_lex("15 gibibits per second", vec![numtok!(15), Token::Unit(GibibitsPerSecond)]);
run_datarate_lex("16 tebibits per second", vec![numtok!(16), Token::Unit(TebibitsPerSecond)]);
run_datarate_lex("17 pebibits per second", vec![numtok!(17), Token::Unit(PebibitsPerSecond)]);
run_datarate_lex("18 exbibits per second", vec![numtok!(18), Token::Unit(ExbibitsPerSecond)]);
run_datarate_lex("19 zebibits per second", vec![numtok!(19), Token::Unit(ZebibitsPerSecond)]);
run_datarate_lex("20 yobibits per second", vec![numtok!(20), Token::Unit(YobibitsPerSecond)]);
run_datarate_lex("4 bytes per second", vec![numtok!(4), Token::Unit(BytesPerSecond)]);
run_datarate_lex("5 kilobytes per second", vec![numtok!(5), Token::Unit(KilobytesPerSecond)]);
run_datarate_lex("6 megabytes per second", vec![numtok!(6), Token::Unit(MegabytesPerSecond)]);
run_datarate_lex("7 gigabytes per second", vec![numtok!(7), Token::Unit(GigabytesPerSecond)]);
run_datarate_lex("8 terabytes per second", vec![numtok!(8), Token::Unit(TerabytesPerSecond)]);
run_datarate_lex("9 petabytes per second", vec![numtok!(9), Token::Unit(PetabytesPerSecond)]);
run_datarate_lex("10 exabytes per second", vec![numtok!(10), Token::Unit(ExabytesPerSecond)]);
run_datarate_lex("11 zettabytes per second", vec![numtok!(11), Token::Unit(ZettabytesPerSecond)]);
run_datarate_lex("12 yottabytes per second", vec![numtok!(12), Token::Unit(YottabytesPerSecond)]);
run_datarate_lex("13 kibibytes per second", vec![numtok!(13), Token::Unit(KibibytesPerSecond)]);
run_datarate_lex("14 mebibytes per second", vec![numtok!(14), Token::Unit(MebibytesPerSecond)]);
run_datarate_lex("15 gibibytes per second", vec![numtok!(15), Token::Unit(GibibytesPerSecond)]);
run_datarate_lex("16 tebibytes per second", vec![numtok!(16), Token::Unit(TebibytesPerSecond)]);
run_datarate_lex("17 pebibytes per second", vec![numtok!(17), Token::Unit(PebibytesPerSecond)]);
run_datarate_lex("18 exbibytes per second", vec![numtok!(18), Token::Unit(ExbibytesPerSecond)]);
run_datarate_lex("19 zebibytes per second", vec![numtok!(19), Token::Unit(ZebibytesPerSecond)]);
run_datarate_lex("20 yobibytes per second", vec![numtok!(20), Token::Unit(YobibytesPerSecond)]);
run_lex("234 wh", vec![numtok!(234), Token::Unit(WattHour)]); run_lex("234 wh", vec![numtok!(234), Token::Unit(WattHour)]);
run_lex("1 w", vec![numtok!(1), Token::Unit(Watt)]); run_lex("1 w", vec![numtok!(1), Token::Unit(Watt)]);
run_lex("1 watt", vec![numtok!(1), Token::Unit(Watt)]); run_lex("1 watt", vec![numtok!(1), Token::Unit(Watt)]);

View File

@ -19,6 +19,8 @@ pub enum UnitType {
Mass, Mass,
/// A unit of digital storage, for example [`Kilobyte`] /// A unit of digital storage, for example [`Kilobyte`]
DigitalStorage, DigitalStorage,
/// A unit of data rate transfer, for example [`KilobytesPerSecond`]
DataTransferRate,
/// A unit of energy, for example [`Joule`] or [`KilowattHour`] /// A unit of energy, for example [`Joule`] or [`KilowattHour`]
Energy, Energy,
/// A unit of power, for example [`Watt`] /// A unit of power, for example [`Watt`]
@ -187,6 +189,41 @@ create_units!(
Zebibyte: (DigitalStorage, d128!(9444732965739290427392)), Zebibyte: (DigitalStorage, d128!(9444732965739290427392)),
Yobibyte: (DigitalStorage, d128!(9671406556917033397649408)), Yobibyte: (DigitalStorage, d128!(9671406556917033397649408)),
BitsPerSecond: (DataTransferRate, d128!(1)),
KilobitsPerSecond: (DataTransferRate, d128!(1000)),
MegabitsPerSecond: (DataTransferRate, d128!(1000000)),
GigabitsPerSecond: (DataTransferRate, d128!(1000000000)),
TerabitsPerSecond: (DataTransferRate, d128!(1000000000000)),
PetabitsPerSecond: (DataTransferRate, d128!(1000000000000000)),
ExabitsPerSecond: (DataTransferRate, d128!(1000000000000000000)),
ZettabitsPerSecond: (DataTransferRate, d128!(1000000000000000000000)),
YottabitsPerSecond: (DataTransferRate, d128!(1000000000000000000000000)),
KibibitsPerSecond: (DataTransferRate, d128!(1024)),
MebibitsPerSecond: (DataTransferRate, d128!(1048576)),
GibibitsPerSecond: (DataTransferRate, d128!(1073741824)),
TebibitsPerSecond: (DataTransferRate, d128!(1099511627776)),
PebibitsPerSecond: (DataTransferRate, d128!(1125899906842624)),
ExbibitsPerSecond: (DataTransferRate, d128!(1152921504606846976)),
ZebibitsPerSecond: (DataTransferRate, d128!(1180591620717411303424)),
YobibitsPerSecond: (DataTransferRate, d128!(1208925819614629174706176)),
BytesPerSecond: (DataTransferRate, d128!(8)),
KilobytesPerSecond: (DataTransferRate, d128!(8000)),
MegabytesPerSecond: (DataTransferRate, d128!(8000000)),
GigabytesPerSecond: (DataTransferRate, d128!(8000000000)),
TerabytesPerSecond: (DataTransferRate, d128!(8000000000000)),
PetabytesPerSecond: (DataTransferRate, d128!(8000000000000000)),
ExabytesPerSecond: (DataTransferRate, d128!(8000000000000000000)),
ZettabytesPerSecond: (DataTransferRate, d128!(8000000000000000000000)),
YottabytesPerSecond: (DataTransferRate, d128!(8000000000000000000000000)),
KibibytesPerSecond: (DataTransferRate, d128!(8192)),
MebibytesPerSecond: (DataTransferRate, d128!(8388608)),
GibibytesPerSecond: (DataTransferRate, d128!(8589934592)),
TebibytesPerSecond: (DataTransferRate, d128!(8796093022208)),
PebibytesPerSecond: (DataTransferRate, d128!(9007199254740992)),
ExbibytesPerSecond: (DataTransferRate, d128!(9223372036854775808)),
ZebibytesPerSecond: (DataTransferRate, d128!(9444732965739290427392)),
YobibytesPerSecond: (DataTransferRate, d128!(9671406556917033397649408)),
// ! If updating Millijoule, also update get_inverted_millijoule_weight() // ! If updating Millijoule, also update get_inverted_millijoule_weight()
Millijoule: (Energy, d128!(0.001)), Millijoule: (Energy, d128!(0.001)),
Joule: (Energy, d128!(1)), Joule: (Energy, d128!(1)),
@ -551,6 +588,50 @@ fn actual_multiply(left: Number, right: Number, swapped: bool) -> Result<Number,
}; };
let kilometers = Number::new(result, Kilometer); let kilometers = Number::new(result, Kilometer);
Ok(convert(kilometers, final_unit)?) Ok(convert(kilometers, final_unit)?)
} else if lcat == DataTransferRate && rcat == Time {
// 8 megabytes per second * 1 minute
let data_rate_value = left.value * left.unit.weight();
let seconds = convert(right, Second)?;
let result = data_rate_value * seconds.value;
let final_unit = match left.unit {
BitsPerSecond => Bit,
KilobitsPerSecond => Kilobit,
MegabitsPerSecond => Megabit,
GigabitsPerSecond => Gigabit,
TerabitsPerSecond => Terabit,
PetabitsPerSecond => Petabit,
ExabitsPerSecond => Exabit,
ZettabitsPerSecond => Zettabit,
YottabitsPerSecond => Yottabit,
KibibitsPerSecond => Kibibit,
MebibitsPerSecond => Mebibit,
GibibitsPerSecond => Gibibit,
TebibitsPerSecond => Tebibit,
PebibitsPerSecond => Pebibit,
ExbibitsPerSecond => Exbibit,
ZebibitsPerSecond => Zebibit,
YobibitsPerSecond => Yobibit,
BytesPerSecond => Byte,
KilobytesPerSecond => Kilobyte,
MegabytesPerSecond => Megabyte,
GigabytesPerSecond => Gigabyte,
TerabytesPerSecond => Terabyte,
PetabytesPerSecond => Petabyte,
ExabytesPerSecond => Exabyte,
ZettabytesPerSecond => Zettabyte,
YottabytesPerSecond => Yottabyte,
KibibytesPerSecond => Kibibyte,
MebibytesPerSecond => Mebibyte,
GibibytesPerSecond => Gibibyte,
TebibytesPerSecond => Tebibyte,
PebibytesPerSecond => Pebibyte,
ExbibytesPerSecond => Exbibyte,
ZebibytesPerSecond => Zebibyte,
YobibytesPerSecond => Yobibyte,
_ => Bit,
};
let data_storage = Number::new(result, Bit);
Ok(convert(data_storage, final_unit)?)
} else if lcat == Voltage && rcat == ElectricCurrent { } else if lcat == Voltage && rcat == ElectricCurrent {
// 1 volt * 1 ampere = 1 watt // 1 volt * 1 ampere = 1 watt
let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight());
@ -631,6 +712,12 @@ pub fn divide(left: Number, right: Number) -> Result<Number, String> {
let kilometers_per_hour = convert(right, KilometersPerHour)?; let kilometers_per_hour = convert(right, KilometersPerHour)?;
let hour = Number::new(kilometers.value / kilometers_per_hour.value, Hour); let hour = Number::new(kilometers.value / kilometers_per_hour.value, Hour);
Ok(to_ideal_unit(hour)) Ok(to_ideal_unit(hour))
} else if lcat == DigitalStorage && rcat == DataTransferRate {
// 1 kilobit / 1 bit per second
let bits = convert(left, Bit)?;
let bits_per_second = convert(right, BitsPerSecond)?;
let seconds = Number::new(bits.value / bits_per_second.value, Second);
Ok(to_ideal_unit(seconds))
} else if lcat == Power && rcat == ElectricCurrent { } else if lcat == Power && rcat == ElectricCurrent {
// 1 watt / 1 ampere = 1 volt // 1 watt / 1 ampere = 1 volt
let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight());
@ -840,6 +927,39 @@ mod tests {
assert_float_eq!(convert_test(1024.0, Exbibyte, Zebibyte), 1.0); assert_float_eq!(convert_test(1024.0, Exbibyte, Zebibyte), 1.0);
assert_float_eq!(convert_test(1024.0, Zebibyte, Yobibyte), 1.0); assert_float_eq!(convert_test(1024.0, Zebibyte, Yobibyte), 1.0);
assert_float_eq!(convert_test(1000.0, BitsPerSecond, KilobitsPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, KilobitsPerSecond, MegabitsPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, MegabitsPerSecond, GigabitsPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, GigabitsPerSecond, TerabitsPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, TerabitsPerSecond, PetabitsPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, PetabitsPerSecond, ExabitsPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, ExabitsPerSecond, ZettabitsPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, ZettabitsPerSecond, YottabitsPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, BitsPerSecond, KibibitsPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, KibibitsPerSecond, MebibitsPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, MebibitsPerSecond, GibibitsPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, GibibitsPerSecond, TebibitsPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, TebibitsPerSecond, PebibitsPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, PebibitsPerSecond, ExbibitsPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, ExbibitsPerSecond, ZebibitsPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, ZebibitsPerSecond, YobibitsPerSecond), 1.0);
assert_float_eq!(convert_test(8.0, BitsPerSecond, BytesPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, BytesPerSecond, KilobytesPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, KilobytesPerSecond, MegabytesPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, MegabytesPerSecond, GigabytesPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, GigabytesPerSecond, TerabytesPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, TerabytesPerSecond, PetabytesPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, PetabytesPerSecond, ExabytesPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, ExabytesPerSecond, ZettabytesPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, ZettabytesPerSecond, YottabytesPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, KibibytesPerSecond, MebibytesPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, MebibytesPerSecond, GibibytesPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, GibibytesPerSecond, TebibytesPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, TebibytesPerSecond, PebibytesPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, PebibytesPerSecond, ExbibytesPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, ExbibytesPerSecond, ZebibytesPerSecond), 1.0);
assert_float_eq!(convert_test(1024.0, ZebibytesPerSecond, YobibytesPerSecond), 1.0);
assert_float_eq!(convert_test(1000.0, Millijoule, Joule), 1.0); assert_float_eq!(convert_test(1000.0, Millijoule, Joule), 1.0);
assert_float_eq!(convert_test(1000.0, Joule, Kilojoule), 1.0); assert_float_eq!(convert_test(1000.0, Joule, Kilojoule), 1.0);
assert_float_eq!(convert_test(1.0, NewtonMeter, Joule), 1.0); assert_float_eq!(convert_test(1.0, NewtonMeter, Joule), 1.0);