[READ-ONLY] Mirror of https://github.com/probablykasper/cpc. Text calculator with support for units and conversion cpc.kasper.space
calculator cli conversion converter library math package units units-converter wasm website
0

Configure Feed

Select the types of activity you want to include in your feed.

WIP units with exponents

Kasper (Jun 24, 2026, 8:54 AM +0200) 8823332d 23c6f8ea

+2339 -1054
+82 -52
src/evaluator.rs
··· 1 - use crate::lookup::{lookup_factorial, lookup_named_number}; 2 - use crate::parser::AstNode; 3 - use crate::units::{add, convert, divide, modulo, multiply, pow, subtract, Unit, UnitType}; 4 - use crate::Constant::{Pi, E}; 1 + use crate::Constant::{E, Pi}; 5 2 use crate::FunctionIdentifier::*; 6 3 use crate::Operator::{Caret, Divide, Minus, Modulo, Multiply, Plus}; 7 4 use crate::TextOperator::{Of, To}; 8 5 use crate::UnaryOperator::{Factorial, Percent}; 6 + use crate::lookup::{lookup_factorial, lookup_named_number}; 7 + use crate::parser::AstNode; 8 + use crate::units::{add, convert, divide, modulo, multiply, pow, subtract}; 9 9 use crate::{Number, Token}; 10 - use fastnum::{dec128 as d, decimal::RoundingMode, D128}; 10 + use fastnum::{D128, dec128 as d, decimal::RoundingMode}; 11 11 12 12 /// Evaluate an [`AstNode`] into a [`Number`] 13 13 pub fn evaluate(ast: &AstNode) -> Result<Number, String> { ··· 61 61 let token = &ast_node.token; 62 62 let children = &ast_node.children; 63 63 match token { 64 - Token::Number(number) => Ok(Number::new(*number, Unit::NoUnit)), 64 + Token::Number(number) => Ok(Number::new_unitless(*number)), 65 65 Token::Constant(constant) => match constant { 66 - Pi => Ok(Number::new( 67 - D128::PI, 68 - Unit::NoUnit, 69 - )), 70 - E => Ok(Number::new( 71 - D128::E, 72 - Unit::NoUnit, 73 - )), 66 + Pi => Ok(Number::new_unitless(D128::PI)), 67 + E => Ok(Number::new_unitless(D128::E)), 74 68 }, 75 69 Token::FunctionIdentifier(function) => { 76 70 let child_node = children.get(0).ok_or("Paren has no child[0]")?; 77 71 let child_answer = evaluate_node(child_node)?; 78 72 match function { 79 73 Cbrt => { 80 - if child_answer.unit.category() == UnitType::NoType { 74 + if child_answer.is_unitless() { 81 75 let result = cbrt(child_answer.value); 82 - Ok(Number::new(result, child_answer.unit)) 76 + Ok(Number::with_unit(result, child_answer.unit)) 83 77 } else { 84 78 Err("log() only accepts UnitType::NoType".to_string()) 85 79 } 86 80 } 87 81 Sqrt => { 88 - if child_answer.unit.category() == UnitType::NoType { 82 + if child_answer.is_unitless() { 89 83 let result = sqrt(child_answer.value); 90 - Ok(Number::new(result, child_answer.unit)) 84 + Ok(Number::with_unit(result, child_answer.unit)) 91 85 } else { 92 86 Err("log() only accepts UnitType::NoType".to_string()) 93 87 } 94 88 } 95 89 Log => { 96 - if child_answer.unit.category() == UnitType::NoType { 90 + if child_answer.is_unitless() { 97 91 let result = child_answer.value.log10(); 98 - Ok(Number::new(result, child_answer.unit)) 92 + Ok(Number::with_unit(result, child_answer.unit)) 99 93 } else { 100 94 Err("log() only accepts UnitType::NoType".to_string()) 101 95 } 102 96 } 103 97 Ln => { 104 - if child_answer.unit.category() == UnitType::NoType { 98 + if child_answer.is_unitless() { 105 99 let result = child_answer.value.ln(); 106 - Ok(Number::new(result, child_answer.unit)) 100 + Ok(Number::with_unit(result, child_answer.unit)) 107 101 } else { 108 102 Err("ln() only accepts UnitType::NoType".to_string()) 109 103 } 110 104 } 111 105 Exp => { 112 - if child_answer.unit.category() == UnitType::NoType { 106 + if child_answer.is_unitless() { 113 107 let result = child_answer.value.exp(); 114 - Ok(Number::new(result, child_answer.unit)) 108 + Ok(Number::with_unit(result, child_answer.unit)) 115 109 } else { 116 110 Err("exp() only accepts UnitType::NoType".to_string()) 117 111 } ··· 122 116 .value 123 117 .with_rounding_mode(RoundingMode::HalfUp) 124 118 .round(0); 125 - Ok(Number::new(result, child_answer.unit)) 119 + Ok(Number::with_unit(result, child_answer.unit)) 126 120 } 127 121 Ceil => { 128 122 let result = child_answer.value.ceil(); 129 - Ok(Number::new(result, child_answer.unit)) 123 + Ok(Number::with_unit(result, child_answer.unit)) 130 124 } 131 125 Floor => { 132 126 let result = child_answer.value.floor(); 133 - Ok(Number::new(result, child_answer.unit)) 127 + Ok(Number::with_unit(result, child_answer.unit)) 134 128 } 135 129 Abs => { 136 130 let result = child_answer.value.abs(); 137 - Ok(Number::new(result, child_answer.unit)) 131 + Ok(Number::with_unit(result, child_answer.unit)) 138 132 } 139 133 Sin => { 140 134 let result = sin(child_answer.value); 141 - Ok(Number::new(result, child_answer.unit)) 135 + Ok(Number::with_unit(result, child_answer.unit)) 142 136 } 143 137 Cos => { 144 138 let result = cos(child_answer.value); 145 - Ok(Number::new(result, child_answer.unit)) 139 + Ok(Number::with_unit(result, child_answer.unit)) 146 140 } 147 141 Tan => { 148 142 let result = tan(child_answer.value); 149 - Ok(Number::new(result, child_answer.unit)) 143 + Ok(Number::with_unit(result, child_answer.unit)) 150 144 } 151 145 } 152 146 } 153 147 Token::Unit(unit) => { 154 148 let child_node = children.get(0).ok_or("Unit has no child[0]")?; 155 149 let child_answer = evaluate_node(child_node)?; 156 - Ok(Number::new(child_answer.value, *unit)) 150 + Ok(Number::with_basic_unit(child_answer.value, *unit)) 157 151 } 158 152 Token::Negative => { 159 153 let child_node = children.get(0).ok_or("Negative has no child[0]")?; 160 154 let child_answer = evaluate_node(child_node)?; 161 - Ok(Number::new(-child_answer.value, child_answer.unit)) 155 + Ok(Number::with_unit(-child_answer.value, child_answer.unit)) 162 156 } 163 157 Token::Paren => { 164 158 let child_node = children.get(0).ok_or("Paren has no child[0]")?; ··· 170 164 .ok_or(format!("Token {:?} has no child[0]", token))?; 171 165 let child_answer = evaluate_node(child_node)?; 172 166 match operator { 173 - Percent => Ok(Number::new( 167 + Percent => Ok(Number::with_unit( 174 168 child_answer.value / d!(100), 175 169 child_answer.unit, 176 170 )), ··· 181 175 "Can only perform factorial on integers from 0 to 1000".to_string() 182 176 ); 183 177 } 184 - Ok(Number::new(result, child_answer.unit)) 178 + Ok(Number::with_unit(result, child_answer.unit)) 185 179 } 186 180 } 187 181 } ··· 198 192 } 199 193 let child_answer = evaluate_node(child_node)?; 200 194 let result = child_answer.value * named_number_value; 201 - Ok(Number::new(result, child_answer.unit)) 195 + Ok(Number::with_unit(result, child_answer.unit)) 202 196 } 203 197 Token::TextOperator(operator) => { 204 198 let left_child = children ··· 212 206 To => { 213 207 if let Token::Unit(right_unit) = right_child.token { 214 208 let left = evaluate_node(left_child)?; 215 - let result = convert(left, right_unit)?; 209 + let result = convert(left, vec![(right_unit, 1)])?; 216 210 Ok(result) 217 211 } else { 218 212 Err("Right side of To operator needs to be a unit".to_string()) ··· 221 215 Of => { 222 216 let left = evaluate_node(left_child)?; 223 217 let right = evaluate_node(right_child)?; 224 - if left.unit == Unit::NoUnit { 225 - Ok(Number::new(left.value * right.value, right.unit)) 218 + if left.is_unitless() { 219 + Ok(Number::with_unit(left.value * right.value, right.unit)) 226 220 } else { 227 221 Err("Left side of the Of operator must be NoUnit".to_string()) 228 222 } ··· 254 248 255 249 #[cfg(test)] 256 250 mod tests { 257 - use crate::eval; 258 251 use super::*; 252 + use crate::eval; 259 253 260 254 fn eval_default<'a>(input: &'a str) -> Number { 261 255 let result = eval(input, true, false).unwrap(); ··· 273 267 assert_eq!(eval_num("-2(-3)"), "6"); 274 268 assert_eq!(eval_num("-2(3)"), "-6"); 275 269 assert_eq!(eval_num("(3)-2"), "1"); 276 - assert_eq!(eval_default("-1km to m"), Number::new(d!(-1000), Unit::Meter)); 270 + assert_eq!( 271 + eval_default("-1km to m"), 272 + Number::new(d!(-1000), Unit::Meter) 273 + ); 277 274 assert_eq!(eval_num("2*-3*0.5"), "-3"); 278 275 assert_eq!(eval_num("-3^2"), "-9"); 279 276 assert_eq!(eval_num("e^2"), "7.3890560989306502272304274605750078132"); 280 - assert_eq!(eval_num("e^2.5"), "12.1824939607034734380701759511679661832"); 277 + assert_eq!( 278 + eval_num("e^2.5"), 279 + "12.1824939607034734380701759511679661832" 280 + ); 281 281 assert_eq!(eval_num("-1+2"), "1"); 282 282 } 283 283 284 284 #[test] 285 285 fn test_functions() { 286 286 assert_eq!(eval_num("cbrt(125)"), "5"); 287 - assert_eq!(eval_num("cbrt(2)"), "1.25992104989487316476721060727822835057"); 287 + assert_eq!( 288 + eval_num("cbrt(2)"), 289 + "1.25992104989487316476721060727822835057" 290 + ); 288 291 289 292 assert_eq!(eval_num("sqrt(25)"), "5"); 290 - assert_eq!(eval_num("sqrt(2)"), "1.41421356237309504880168872420969807857"); 293 + assert_eq!( 294 + eval_num("sqrt(2)"), 295 + "1.41421356237309504880168872420969807857" 296 + ); 291 297 292 298 assert_eq!(eval_num("log(100)"), "2"); 293 - assert_eq!(eval_num("log(2)"), "0.301029995663981195213738894724493026768"); 299 + assert_eq!( 300 + eval_num("log(2)"), 301 + "0.301029995663981195213738894724493026768" 302 + ); 294 303 295 304 assert_eq!(eval_num("ln(1)"), "0"); 296 - assert_eq!(eval_num("ln(2)"), "0.69314718055994530941723212145817656808"); 305 + assert_eq!( 306 + eval_num("ln(2)"), 307 + "0.69314718055994530941723212145817656808" 308 + ); 297 309 assert_eq!(eval_num("ln(e)"), "1"); 298 310 assert_eq!(eval_num("ln(e^2)"), "2"); 299 311 300 - assert_eq!(eval_num("exp(1)"), "2.71828182845904523536028747135266249776"); 312 + assert_eq!( 313 + eval_num("exp(1)"), 314 + "2.71828182845904523536028747135266249776" 315 + ); 301 316 302 317 assert_eq!(eval_num("round(1.4)"), "1"); 303 318 assert_eq!(eval_num("round(1.6)"), "2"); ··· 312 327 313 328 assert_eq!(eval_num("abs(-3)"), "3"); 314 329 315 - assert_eq!(eval_num("sin(2)"), "0.9092974268256816953960198659117448427"); 316 - assert_eq!(eval_num("sin(-2)"), "-0.9092974268256816953960198659117448427"); 330 + assert_eq!( 331 + eval_num("sin(2)"), 332 + "0.9092974268256816953960198659117448427" 333 + ); 334 + assert_eq!( 335 + eval_num("sin(-2)"), 336 + "-0.9092974268256816953960198659117448427" 337 + ); 317 338 318 - assert_eq!(eval_num("cos(2)"), "-0.41614683654714238699756822950076218977"); 319 - assert_eq!(eval_num("cos(-2)"), "-0.41614683654714238699756822950076218977"); 320 - assert_eq!(eval_num("tan(2)"), "-2.18503986326151899164330610231368254343"); 339 + assert_eq!( 340 + eval_num("cos(2)"), 341 + "-0.41614683654714238699756822950076218977" 342 + ); 343 + assert_eq!( 344 + eval_num("cos(-2)"), 345 + "-0.41614683654714238699756822950076218977" 346 + ); 347 + assert_eq!( 348 + eval_num("tan(2)"), 349 + "-2.18503986326151899164330610231368254343" 350 + ); 321 351 } 322 352 }
+1457 -532
src/lexer.rs
··· 1 - use std::iter::Peekable; 2 - use fastnum::decimal::Context; 3 - use fastnum::D128; 4 - use crate::Token; 1 + use crate::Constant::{E, Pi}; 2 + use crate::FunctionIdentifier::{Abs, Cbrt, Ceil, Cos, Exp, Floor, Ln, Log, Round, Sin, Sqrt, Tan}; 3 + use crate::LexerKeyword::{ 4 + DoubleQuotes, Force, Hg, In, Mercury, Per, PercentChar, PoundForce, Revolution, 5 + }; 6 + use crate::NamedNumber::*; 5 7 use crate::Operator::{Caret, Divide, LeftParen, Minus, Modulo, Multiply, Plus, RightParen}; 6 - use crate::UnaryOperator::{Percent, Factorial}; 7 8 use crate::TextOperator::{Of, To}; 8 - use crate::NamedNumber::*; 9 - use crate::Constant::{E, Pi}; 10 - use crate::LexerKeyword::{In, PercentChar, Per, Mercury, Hg, PoundForce, Force, DoubleQuotes, Revolution}; 11 - use crate::FunctionIdentifier::{Cbrt, Ceil, Cos, Exp, Abs, Floor, Ln, Log, Round, Sin, Sqrt, Tan}; 9 + use crate::Token; 10 + use crate::UnaryOperator::{Factorial, Percent}; 12 11 use crate::units::Unit::*; 12 + use fastnum::D128; 13 + use fastnum::decimal::Context; 14 + use std::iter::Peekable; 13 15 use unicode_segmentation::{Graphemes, UnicodeSegmentation}; 14 16 15 17 fn is_word_char_str(input: &str) -> bool { 16 18 match input { 17 - "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" 18 - | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" 19 - | "Y" | "Z" => true, 20 - "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" 21 - | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" 22 - | "y" | "z" => true, 19 + "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" 20 + | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" => true, 21 + "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" 22 + | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" => true, 23 23 "Ω" | "Ω" | "µ" | "μ" => true, 24 24 _ => false, 25 25 } 26 26 } 27 27 28 28 fn is_numeric_str(input: &str) -> bool { 29 - matches!(input, "." | "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9") 29 + matches!( 30 + input, 31 + "." | "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" 32 + ) 30 33 } 31 34 32 35 /// Read next characters as a word, otherwise return empty string. ··· 70 73 "2" | "²" => { 71 74 word += "2"; 72 75 chars.next(); 73 - }, 76 + } 74 77 "3" | "³" => { 75 78 word += "3"; 76 79 chars.next(); 77 - }, 78 - _ => {}, 80 + } 81 + _ => {} 79 82 } 80 83 } 81 84 word ··· 84 87 fn parse_token(c: &str, lexer: &mut Lexer) -> Result<(), String> { 85 88 let tokens = &mut lexer.tokens; 86 89 match c { 87 - value if value.trim().is_empty() => {}, 90 + value if value.trim().is_empty() => {} 88 91 value if is_word_char_str(value) => { 89 92 parse_word(read_word(c, lexer).as_str(), lexer)?; 90 - }, 93 + } 91 94 value if is_numeric_str(value) => { 92 95 let mut number_string = value.to_owned(); 93 96 while let Some(number_char) = lexer.chars.peek() { ··· 101 104 match D128::from_str(&number_string, Context::default()) { 102 105 Ok(number) => { 103 106 tokens.push(Token::Number(number)); 104 - }, 107 + } 105 108 Err(_e) => { 106 109 return Err(format!("Error lexing d128 number: {}", number_string)); 107 110 } 108 111 }; 109 - }, 112 + } 110 113 "+" => tokens.push(Token::Operator(Plus)), 111 114 "-" => tokens.push(Token::Operator(Minus)), 112 115 "*" => tokens.push(Token::Operator(Multiply)), ··· 117 120 "(" => { 118 121 lexer.left_paren_count += 1; 119 122 tokens.push(Token::Operator(LeftParen)); 120 - }, 123 + } 121 124 ")" => { 122 125 lexer.right_paren_count += 1; 123 126 tokens.push(Token::Operator(RightParen)); 124 - }, 127 + } 125 128 "π" => tokens.push(Token::Constant(Pi)), 126 129 "'" => tokens.push(Token::Unit(Foot)), 127 130 "\"" | "“" | "”" | "″" => tokens.push(Token::LexerKeyword(DoubleQuotes)), 128 131 _ => { 129 132 return Err(format!("Invalid character: {}", c)); 130 - }, 133 + } 131 134 } 132 135 Ok(()) 133 136 } ··· 135 138 fn parse_word_if_non_empty(word: &str, lexer: &mut Lexer) -> Result<(), String> { 136 139 match word { 137 140 "" => Ok(()), 138 - _ => parse_word(word, lexer) 141 + _ => parse_word(word, lexer), 139 142 } 140 143 } 141 144 ··· 175 178 "plus" => Token::Operator(Plus), 176 179 "minus" => Token::Operator(Minus), 177 180 "times" => Token::Operator(Multiply), 178 - "multiplied" => { 179 - match read_word("", lexer).as_str() { 180 - "by" => Token::Operator(Multiply), 181 - string => return Err(format!("Invalid string: {}", string)), 182 - } 181 + "multiplied" => match read_word("", lexer).as_str() { 182 + "by" => Token::Operator(Multiply), 183 + string => return Err(format!("Invalid string: {}", string)), 183 184 }, 184 - "divided" => { 185 - match read_word("", lexer).as_str() { 186 - "by" => Token::Operator(Divide), 187 - string => return Err(format!("Invalid string: {}", string)), 188 - } 185 + "divided" => match read_word("", lexer).as_str() { 186 + "by" => Token::Operator(Divide), 187 + string => return Err(format!("Invalid string: {}", string)), 189 188 }, 190 189 "mod" => Token::Operator(Modulo), 191 190 ··· 210 209 211 210 "ns" | "nanosec" | "nanosecs" | "nanosecond" | "nanoseconds" => Token::Unit(Nanosecond), 212 211 // µ and μ are two different characters 213 - "µs" | "μs" | "microsec" | "microsecs" | "microsecond" | "microseconds" => Token::Unit(Microsecond), 214 - "ms" | "millisec" | "millisecs" | "millisecond" | "milliseconds" => Token::Unit(Millisecond), 212 + "µs" | "μs" | "microsec" | "microsecs" | "microsecond" | "microseconds" => { 213 + Token::Unit(Microsecond) 214 + } 215 + "ms" | "millisec" | "millisecs" | "millisecond" | "milliseconds" => { 216 + Token::Unit(Millisecond) 217 + } 215 218 "s" | "sec" | "secs" | "second" | "seconds" => Token::Unit(Second), 216 219 "min" | "mins" | "minute" | "minutes" => Token::Unit(Minute), 217 220 "h" | "hr" | "hrs" | "hour" | "hours" => Token::Unit(Hour), ··· 224 227 "century" | "centuries" => Token::Unit(Century), 225 228 "millenium" | "millenia" | "milleniums" => Token::Unit(Millennium), 226 229 227 - "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => Token::Unit(Millimeter), 228 - "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => Token::Unit(Centimeter), 230 + "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => { 231 + Token::Unit(Millimeter) 232 + } 233 + "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => { 234 + Token::Unit(Centimeter) 235 + } 229 236 "dm" | "decimeter" | "decimeters" | "decimetre" | "decimetres" => Token::Unit(Decimeter), 230 237 "m" | "meter" | "meters" | "metre" | "metres" => Token::Unit(Meter), 231 238 "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => Token::Unit(Kilometer), ··· 236 243 "mi" | "mile" | "miles" => Token::Unit(Mile), 237 244 "marathon" | "marathons" => Token::Unit(Marathon), 238 245 "nmi" => Token::Unit(NauticalMile), 239 - "nautical" => { 240 - match read_word("", lexer).as_str() { 241 - "mile" | "miles" => Token::Unit(NauticalMile), 242 - string => return Err(format!("Invalid string: {}", string)), 243 - } 246 + "nautical" => match read_word("", lexer).as_str() { 247 + "mile" | "miles" => Token::Unit(NauticalMile), 248 + string => return Err(format!("Invalid string: {}", string)), 244 249 }, 245 250 "ly" | "lightyear" | "lightyears" => Token::Unit(LightYear), 246 251 "lightsec" | "lightsecs" | "lightsecond" | "lightseconds" => Token::Unit(LightSecond), 247 - "light" => { 248 - match read_word("", lexer).as_str() { 249 - "yr" | "yrs" | "year" | "years" => Token::Unit(LightYear), 250 - "sec" | "secs" | "second" | "seconds" => Token::Unit(LightSecond), 251 - string => return Err(format!("Invalid string: {}", string)), 252 - } 252 + "light" => match read_word("", lexer).as_str() { 253 + "yr" | "yrs" | "year" | "years" => Token::Unit(LightYear), 254 + "sec" | "secs" | "second" | "seconds" => Token::Unit(LightSecond), 255 + string => return Err(format!("Invalid string: {}", string)), 256 + }, 257 + 258 + "sqmm" | "mm2" | "millimeter2" | "millimeters2" | "millimetre2" | "millimetres2" => { 259 + Token::Unit(SquareMillimeter) 260 + } 261 + "sqcm" | "cm2" | "centimeter2" | "centimeters2" | "centimetre2" | "centimetres2" => { 262 + Token::Unit(SquareCentimeter) 263 + } 264 + "sqdm" | "dm2" | "decimeter2" | "decimeters2" | "decimetre2" | "decimetres2" => { 265 + Token::Unit(SquareDecimeter) 253 266 } 254 - 255 - "sqmm" | "mm2" | "millimeter2" | "millimeters2" | "millimetre2" | "millimetres2" => Token::Unit(SquareMillimeter), 256 - "sqcm" | "cm2" | "centimeter2" | "centimeters2" | "centimetre2" | "centimetres2" => Token::Unit(SquareCentimeter), 257 - "sqdm" | "dm2" | "decimeter2" | "decimeters2" | "decimetre2" | "decimetres2" => Token::Unit(SquareDecimeter), 258 267 "sqm" | "m2" | "meter2" | "meters2" | "metre2" | "metres2" => Token::Unit(SquareMeter), 259 - "sqkm" | "km2" | "kilometer2" | "kilometers2" | "kilometre2" | "kilometres2" => Token::Unit(SquareKilometer), 268 + "sqkm" | "km2" | "kilometer2" | "kilometers2" | "kilometre2" | "kilometres2" => { 269 + Token::Unit(SquareKilometer) 270 + } 260 271 "sqin" | "in2" | "inch2" | "inches2" => Token::Unit(SquareInch), 261 272 "sqft" | "ft2" | "foot2" | "feet2" => Token::Unit(SquareFoot), 262 273 "sqyd" | "yd2" | "yard2" | "yards2" => Token::Unit(SquareYard), 263 274 "sqmi" | "mi2" | "mile2" | "miles2" => Token::Unit(SquareMile), 264 - "sq" | "square" => { 265 - match read_word("", lexer).as_str() { 266 - "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => Token::Unit(SquareMillimeter), 267 - "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => Token::Unit(SquareCentimeter), 268 - "dm" | "decimeter" | "decimeters" | "decimetre" | "decimetres" => Token::Unit(SquareDecimeter), 269 - "m" | "meter" | "meters" | "metre" | "metres" => Token::Unit(SquareMeter), 270 - "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => Token::Unit(SquareKilometer), 271 - "in" | "inch" | "inches" => Token::Unit(SquareInch), 272 - "ft" | "foot" | "feet" => Token::Unit(SquareFoot), 273 - "yd" | "yard" | "yards" => Token::Unit(SquareYard), 274 - "mi" | "mile" | "miles" => Token::Unit(SquareMile), 275 - string => return Err(format!("Invalid string: {}", string)), 275 + "sq" | "square" => match read_word("", lexer).as_str() { 276 + "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => { 277 + Token::Unit(SquareMillimeter) 278 + } 279 + "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => { 280 + Token::Unit(SquareCentimeter) 281 + } 282 + "dm" | "decimeter" | "decimeters" | "decimetre" | "decimetres" => { 283 + Token::Unit(SquareDecimeter) 284 + } 285 + "m" | "meter" | "meters" | "metre" | "metres" => Token::Unit(SquareMeter), 286 + "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => { 287 + Token::Unit(SquareKilometer) 276 288 } 277 - } 289 + "in" | "inch" | "inches" => Token::Unit(SquareInch), 290 + "ft" | "foot" | "feet" => Token::Unit(SquareFoot), 291 + "yd" | "yard" | "yards" => Token::Unit(SquareYard), 292 + "mi" | "mile" | "miles" => Token::Unit(SquareMile), 293 + string => return Err(format!("Invalid string: {}", string)), 294 + }, 278 295 "are" | "ares" => Token::Unit(Are), 279 296 "decare" | "decares" => Token::Unit(Decare), 280 297 "ha" | "hectare" | "hectares" => Token::Unit(Hectare), 281 298 "acre" | "acres" => Token::Unit(Acre), 282 299 283 - "mm3" | "millimeter3" | "millimeters3" | "millimetre3" | "millimetres3" => Token::Unit(CubicMillimeter), 284 - "cm3" | "centimeter3" | "centimeters3" | "centimetre3" | "centimetres3" => Token::Unit(CubicCentimeter), 285 - "dm3" | "decimeter3" | "decimeters3" | "decimetre3" | "decimetres3" => Token::Unit(CubicDecimeter), 300 + "mm3" | "millimeter3" | "millimeters3" | "millimetre3" | "millimetres3" => { 301 + Token::Unit(CubicMillimeter) 302 + } 303 + "cm3" | "centimeter3" | "centimeters3" | "centimetre3" | "centimetres3" => { 304 + Token::Unit(CubicCentimeter) 305 + } 306 + "dm3" | "decimeter3" | "decimeters3" | "decimetre3" | "decimetres3" => { 307 + Token::Unit(CubicDecimeter) 308 + } 286 309 "m3" | "meter3" | "meters3" | "metre3" | "metres3" => Token::Unit(CubicMeter), 287 - "km3" | "kilometer3" | "kilometers3" | "kilometre3" | "kilometres3" => Token::Unit(CubicKilometer), 310 + "km3" | "kilometer3" | "kilometers3" | "kilometre3" | "kilometres3" => { 311 + Token::Unit(CubicKilometer) 312 + } 288 313 "inc3" | "inch3" | "inches3" => Token::Unit(CubicInch), 289 314 "ft3" | "foot3" | "feet3" => Token::Unit(CubicFoot), 290 315 "yd3" | "yard3" | "yards3" => Token::Unit(CubicYard), 291 316 "mi3" | "mile3" | "miles3" => Token::Unit(CubicMile), 292 - "cubic" => { 293 - match read_word("", lexer).as_str() { 294 - "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => Token::Unit(CubicMillimeter), 295 - "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => Token::Unit(CubicCentimeter), 296 - "dm" | "decimeter" | "decimeters" | "decimetre" | "decimetres" => Token::Unit(CubicDecimeter), 297 - "m" | "meter" | "meters" | "metre" | "metres" => Token::Unit(CubicMeter), 298 - "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => Token::Unit(CubicKilometer), 299 - "in" | "inch" | "inches" => Token::Unit(CubicInch), 300 - "ft" | "foot" | "feet" => Token::Unit(CubicFoot), 301 - "yd" | "yard" | "yards" => Token::Unit(CubicYard), 302 - "mi" | "mile" | "miles" => Token::Unit(CubicMile), 303 - string => return Err(format!("Invalid string: {}", string)), 317 + "cubic" => match read_word("", lexer).as_str() { 318 + "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => { 319 + Token::Unit(CubicMillimeter) 304 320 } 321 + "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => { 322 + Token::Unit(CubicCentimeter) 323 + } 324 + "dm" | "decimeter" | "decimeters" | "decimetre" | "decimetres" => { 325 + Token::Unit(CubicDecimeter) 326 + } 327 + "m" | "meter" | "meters" | "metre" | "metres" => Token::Unit(CubicMeter), 328 + "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => { 329 + Token::Unit(CubicKilometer) 330 + } 331 + "in" | "inch" | "inches" => Token::Unit(CubicInch), 332 + "ft" | "foot" | "feet" => Token::Unit(CubicFoot), 333 + "yd" | "yard" | "yards" => Token::Unit(CubicYard), 334 + "mi" | "mile" | "miles" => Token::Unit(CubicMile), 335 + string => return Err(format!("Invalid string: {}", string)), 305 336 }, 306 - "ml" | "milliliter" | "milliliters" | "millilitre" | "millilitres" => Token::Unit(Milliliter), 307 - "cl" | "centiliter" | "centiliters" | "centilitre" | "centilitres" => Token::Unit(Centiliter), 337 + "ml" | "milliliter" | "milliliters" | "millilitre" | "millilitres" => { 338 + Token::Unit(Milliliter) 339 + } 340 + "cl" | "centiliter" | "centiliters" | "centilitre" | "centilitres" => { 341 + Token::Unit(Centiliter) 342 + } 308 343 "dl" | "deciliter" | "deciliters" | "decilitre" | "decilitres" => Token::Unit(Deciliter), 309 344 "l" | "liter" | "liters" | "litre" | "litres" => Token::Unit(Liter), 310 345 "ts" | "tsp" | "tspn" | "tspns" | "teaspoon" | "teaspoons" => Token::Unit(Teaspoon), 311 346 "tbs" | "tbsp" | "tablespoon" | "tablespoons" => Token::Unit(Tablespoon), 312 347 "floz" => Token::Unit(FluidOunce), 313 - "fl" | "fluid" => { 314 - match read_word("", lexer).as_str() { 315 - "oz" | "ounce" | "ounces" => Token::Unit(FluidOunce), 316 - string => return Err(format!("Invalid string: {}", string)), 317 - } 348 + "fl" | "fluid" => match read_word("", lexer).as_str() { 349 + "oz" | "ounce" | "ounces" => Token::Unit(FluidOunce), 350 + string => return Err(format!("Invalid string: {}", string)), 318 351 }, 319 352 "cup" | "cups" => Token::Unit(Cup), 320 353 "pt" | "pint" | "pints" => Token::Unit(Pint), 321 354 "qt" | "quart" | "quarts" => Token::Unit(Quart), 322 355 "gal" | "gallon" | "gallons" => Token::Unit(Gallon), 323 356 "bbl" => Token::Unit(OilBarrel), 324 - "oil" => { 325 - match read_word("", lexer).as_str() { 326 - "barrel" | "barrels" => Token::Unit(OilBarrel), 327 - string => return Err(format!("Invalid string: {}", string)), 328 - } 357 + "oil" => match read_word("", lexer).as_str() { 358 + "barrel" | "barrels" => Token::Unit(OilBarrel), 359 + string => return Err(format!("Invalid string: {}", string)), 329 360 }, 330 361 331 - "metric" => { 332 - match read_word("", lexer).as_str() { 333 - "ton" | "tons" | "tonne" | "tonnes" => Token::Unit(MetricTon), 334 - "hp" | "hps" | "horsepower" | "horsepowers" => Token::Unit(MetricHorsepower), 335 - string => return Err(format!("Invalid string: {}", string)), 336 - } 362 + "metric" => match read_word("", lexer).as_str() { 363 + "ton" | "tons" | "tonne" | "tonnes" => Token::Unit(MetricTon), 364 + "hp" | "hps" | "horsepower" | "horsepowers" => Token::Unit(MetricHorsepower), 365 + string => return Err(format!("Invalid string: {}", string)), 337 366 }, 338 367 339 368 "mg" | "milligram" | "milligrams" => Token::Unit(Milligram), ··· 343 372 "t" | "tonne" | "tonnes" => Token::Unit(MetricTon), 344 373 "oz" | "ounces" => Token::Unit(Ounce), 345 374 "lb" | "lbs" => Token::Unit(Pound), 346 - "pound" | "pounds" => { 347 - match lexer.chars.next() { 348 - Some("-") => { 349 - match read_word_plain(&mut lexer.chars).as_str() { 350 - "force" => Token::LexerKeyword(PoundForce), 351 - other => { 352 - lexer.tokens.push(Token::Unit(Pound)); 353 - lexer.tokens.push(Token::Operator(Minus)); 354 - parse_word_if_non_empty(other, lexer)?; 355 - return Ok(()); 356 - } 357 - } 358 - }, 359 - Some(c) => { 360 - lexer.tokens.push(Token::Unit(Pound)); 361 - parse_token(c, lexer)?; 362 - return Ok(()); 363 - }, 364 - None => { 375 + "pound" | "pounds" => match lexer.chars.next() { 376 + Some("-") => match read_word_plain(&mut lexer.chars).as_str() { 377 + "force" => Token::LexerKeyword(PoundForce), 378 + other => { 365 379 lexer.tokens.push(Token::Unit(Pound)); 380 + lexer.tokens.push(Token::Operator(Minus)); 381 + parse_word_if_non_empty(other, lexer)?; 366 382 return Ok(()); 367 - }, 383 + } 384 + }, 385 + Some(c) => { 386 + lexer.tokens.push(Token::Unit(Pound)); 387 + parse_token(c, lexer)?; 388 + return Ok(()); 389 + } 390 + None => { 391 + lexer.tokens.push(Token::Unit(Pound)); 392 + return Ok(()); 368 393 } 369 394 }, 370 395 "stone" | "stones" => Token::Unit(Stone), 371 396 "st" | "ton" | "tons" => Token::Unit(ShortTon), 372 - "short" => { 373 - match read_word("", lexer).as_str() { 374 - "ton" | "tons" | "tonne" | "tonnes" => Token::Unit(ShortTon), 375 - string => return Err(format!("Invalid string: {}", string)), 376 - } 397 + "short" => match read_word("", lexer).as_str() { 398 + "ton" | "tons" | "tonne" | "tonnes" => Token::Unit(ShortTon), 399 + string => return Err(format!("Invalid string: {}", string)), 377 400 }, 378 401 "lt" => Token::Unit(LongTon), 379 - "long" => { 380 - match read_word("", lexer).as_str() { 381 - "ton" | "tons" | "tonne" | "tonnes" => Token::Unit(LongTon), 382 - string => return Err(format!("Invalid string: {}", string)), 383 - } 402 + "long" => match read_word("", lexer).as_str() { 403 + "ton" | "tons" | "tonne" | "tonnes" => Token::Unit(LongTon), 404 + string => return Err(format!("Invalid string: {}", string)), 384 405 }, 385 406 386 407 "bit" | "bits" => Token::Unit(Bit), ··· 453 474 "qflops" | "quettaflops" => Token::Unit(QuettaFlopPerSecond), 454 475 455 476 "millijoule" | "millijoules" => Token::Unit(Millijoule), 456 - "j"| "joule" | "joules" => Token::Unit(Joule), 477 + "j" | "joule" | "joules" => Token::Unit(Joule), 457 478 "nm" => Token::Unit(NewtonMeter), 458 - "newton" => { 459 - match lexer.chars.next() { 460 - Some("-") => { 461 - match read_word_plain(&mut lexer.chars).as_str() { 462 - "meter" | "meters" | "metre" | "metres" => Token::Unit(NewtonMeter), 463 - string => return Err(format!("Invalid string: {}", string)), 464 - } 465 - }, 466 - Some(c) => { 467 - match read_word(c, lexer).as_str() { 468 - "meter" | "meters" | "metre" | "metres" => Token::Unit(NewtonMeter), 469 - string => return Err(format!("Invalid string: {}", string)), 470 - } 471 - }, 472 - None => return Err(format!("Invalid string: {}", word)), 473 - } 479 + "newton" => match lexer.chars.next() { 480 + Some("-") => match read_word_plain(&mut lexer.chars).as_str() { 481 + "meter" | "meters" | "metre" | "metres" => Token::Unit(NewtonMeter), 482 + string => return Err(format!("Invalid string: {}", string)), 483 + }, 484 + Some(c) => match read_word(c, lexer).as_str() { 485 + "meter" | "meters" | "metre" | "metres" => Token::Unit(NewtonMeter), 486 + string => return Err(format!("Invalid string: {}", string)), 487 + }, 488 + None => return Err(format!("Invalid string: {}", word)), 474 489 }, 475 490 "kj" | "kilojoule" | "kilojoules" => Token::Unit(Kilojoule), 476 491 "mj" | "megajoule" | "megajoules" => Token::Unit(Megajoule), ··· 479 494 "cal" | "calorie" | "calories" => Token::Unit(Calorie), 480 495 "kcal" | "kilocalorie" | "kilocalories" => Token::Unit(KiloCalorie), 481 496 "btu" => Token::Unit(BritishThermalUnit), 482 - "british" => { 483 - match read_word("", lexer).as_str() { 484 - "thermal" => { 485 - match read_word("", lexer).as_str() { 486 - "unit" | "units" => Token::Unit(BritishThermalUnit), 487 - string => return Err(format!("Invalid string: {}", string)), 488 - } 489 - }, 497 + "british" => match read_word("", lexer).as_str() { 498 + "thermal" => match read_word("", lexer).as_str() { 499 + "unit" | "units" => Token::Unit(BritishThermalUnit), 490 500 string => return Err(format!("Invalid string: {}", string)), 491 - } 501 + }, 502 + string => return Err(format!("Invalid string: {}", string)), 492 503 }, 493 504 "wh" => Token::Unit(WattHour), 494 505 "kwh" => Token::Unit(KilowattHour), ··· 507 518 "hp" | "hps" | "horsepower" | "horsepowers" => Token::Unit(Horsepower), 508 519 "mhp" | "hpm" => Token::Unit(MetricHorsepower), 509 520 510 - "watt" => { 511 - match read_word("", lexer).as_str() { 512 - "hr" | "hrs" | "hour" | "hours" => Token::Unit(WattHour), 513 - other => { 514 - lexer.tokens.push(Token::Unit(Watt)); 515 - parse_word_if_non_empty(other, lexer)?; 516 - return Ok(()); 517 - }, 521 + "watt" => match read_word("", lexer).as_str() { 522 + "hr" | "hrs" | "hour" | "hours" => Token::Unit(WattHour), 523 + other => { 524 + lexer.tokens.push(Token::Unit(Watt)); 525 + parse_word_if_non_empty(other, lexer)?; 526 + return Ok(()); 518 527 } 519 - } 520 - "kilowatt" => { 521 - match read_word("", lexer).as_str() { 522 - "hr" | "hrs" | "hour" | "hours" => Token::Unit(KilowattHour), 523 - other => { 524 - lexer.tokens.push(Token::Unit(Kilowatt)); 525 - parse_word_if_non_empty(other, lexer)?; 526 - return Ok(()); 527 - }, 528 + }, 529 + "kilowatt" => match read_word("", lexer).as_str() { 530 + "hr" | "hrs" | "hour" | "hours" => Token::Unit(KilowattHour), 531 + other => { 532 + lexer.tokens.push(Token::Unit(Kilowatt)); 533 + parse_word_if_non_empty(other, lexer)?; 534 + return Ok(()); 528 535 } 529 - } 530 - "megawatt" => { 531 - match read_word("", lexer).as_str() { 532 - "hr" | "hrs" | "hour" | "hours" => Token::Unit(MegawattHour), 533 - other => { 534 - lexer.tokens.push(Token::Unit(Megawatt)); 535 - parse_word_if_non_empty(other, lexer)?; 536 - return Ok(()); 537 - }, 536 + }, 537 + "megawatt" => match read_word("", lexer).as_str() { 538 + "hr" | "hrs" | "hour" | "hours" => Token::Unit(MegawattHour), 539 + other => { 540 + lexer.tokens.push(Token::Unit(Megawatt)); 541 + parse_word_if_non_empty(other, lexer)?; 542 + return Ok(()); 538 543 } 539 - } 540 - "gigawatt" => { 541 - match read_word("", lexer).as_str() { 542 - "hr" | "hrs" | "hour" | "hours" => Token::Unit(GigawattHour), 543 - other => { 544 - lexer.tokens.push(Token::Unit(Gigawatt)); 545 - parse_word_if_non_empty(other, lexer)?; 546 - return Ok(()); 547 - }, 544 + }, 545 + "gigawatt" => match read_word("", lexer).as_str() { 546 + "hr" | "hrs" | "hour" | "hours" => Token::Unit(GigawattHour), 547 + other => { 548 + lexer.tokens.push(Token::Unit(Gigawatt)); 549 + parse_word_if_non_empty(other, lexer)?; 550 + return Ok(()); 548 551 } 549 - } 550 - "terawatt" => { 551 - match read_word("", lexer).as_str() { 552 - "hr" | "hrs" | "hour" | "hours" => Token::Unit(TerawattHour), 553 - other => { 554 - lexer.tokens.push(Token::Unit(Terawatt)); 555 - parse_word_if_non_empty(other, lexer)?; 556 - return Ok(()); 557 - }, 552 + }, 553 + "terawatt" => match read_word("", lexer).as_str() { 554 + "hr" | "hrs" | "hour" | "hours" => Token::Unit(TerawattHour), 555 + other => { 556 + lexer.tokens.push(Token::Unit(Terawatt)); 557 + parse_word_if_non_empty(other, lexer)?; 558 + return Ok(()); 558 559 } 559 - } 560 - "petawatt" => { 561 - match read_word("", lexer).as_str() { 562 - "hr" | "hrs" | "hour" | "hours" => Token::Unit(PetawattHour), 563 - other => { 564 - lexer.tokens.push(Token::Unit(Petawatt)); 565 - parse_word_if_non_empty(other, lexer)?; 566 - return Ok(()); 567 - }, 560 + }, 561 + "petawatt" => match read_word("", lexer).as_str() { 562 + "hr" | "hrs" | "hour" | "hours" => Token::Unit(PetawattHour), 563 + other => { 564 + lexer.tokens.push(Token::Unit(Petawatt)); 565 + parse_word_if_non_empty(other, lexer)?; 566 + return Ok(()); 568 567 } 569 - } 568 + }, 570 569 571 - "ma" | "milliamp" | "milliamps" | "milliampere" | "milliamperes" => Token::Unit(Milliampere), 570 + "ma" | "milliamp" | "milliamps" | "milliampere" | "milliamperes" => { 571 + Token::Unit(Milliampere) 572 + } 572 573 "a" | "amp" | "amps" | "ampere" | "amperes" => Token::Unit(Ampere), 573 574 "ka" | "kiloamp" | "kiloamps" | "kiloampere" | "kiloamperes" => Token::Unit(Kiloampere), 574 575 "bi" | "biot" | "biots" | "aba" | "abampere" | "abamperes" => Token::Unit(Abampere), ··· 637 638 match &input.chars().last().unwrap_or('x') { 638 639 '+' | '-' | '*' | '/' | '^' | '(' => { 639 640 input.pop(); 640 - }, 641 - _ => {}, 641 + } 642 + _ => {} 642 643 } 643 644 } 644 645 ··· 679 680 Some(Token::TextOperator(Of)) => { 680 681 // "10% of 1km" should be percentage 681 682 tokens[token_index] = Token::UnaryOperator(Percent); 682 - }, 683 + } 683 684 Some(Token::Operator(operator)) => { 684 685 match operator { 685 686 LeftParen => { 686 687 // "10%(2)" should be modulo 687 688 tokens[token_index] = Token::Operator(Modulo); 688 - }, 689 + } 689 690 _ => { 690 691 // "10%*2" should be a percentage 691 692 tokens[token_index] = Token::UnaryOperator(Percent); 692 693 } 693 694 } 694 - }, 695 + } 695 696 Some(Token::UnaryOperator(_)) => { 696 697 // "10%!" should be a percentage 697 698 tokens[token_index] = Token::UnaryOperator(Percent); 698 - }, 699 + } 699 700 Some(Token::LexerKeyword(PercentChar)) => { 700 701 // "10%%" should be a percentage 701 702 tokens[token_index] = Token::UnaryOperator(Percent); 702 - }, 703 + } 703 704 None => { 704 705 // percent if there's no element afterwards 705 706 tokens[token_index] = Token::UnaryOperator(Percent); 706 - }, 707 + } 707 708 _ => { 708 709 // everything else should be modulo, for example if the % is 709 710 // before a number, function or constants 710 711 tokens[token_index] = Token::Operator(Modulo); 711 - }, 712 + } 712 713 } 713 - }, 714 + } 714 715 // decide if " is 'inch' or 'inch of mercury' 715 716 Token::LexerKeyword(DoubleQuotes) => { 716 717 match tokens.get(token_index + 1) { ··· 718 719 // "hg should be inch of mercury 719 720 tokens[token_index] = Token::Unit(InchOfMercury); 720 721 tokens.remove(token_index + 1); 721 - }, 722 + } 722 723 _ => { 723 724 // otherwise, Inch 724 725 tokens[token_index] = Token::Unit(Inch); 725 - }, 726 + } 726 727 } 727 - }, 728 + } 728 729 // if hg wasn't already turned into inch of mercury, it's hectogram 729 730 Token::LexerKeyword(Hg) => { 730 731 tokens[token_index] = Token::Unit(Hectogram); 731 - }, 732 + } 732 733 // decide if "in" is Inch or To 733 734 Token::LexerKeyword(In) => { 734 735 match tokens.get(token_index + 1) { 735 736 Some(Token::Unit(_)) => { 736 737 // "in" should be To 737 738 tokens[token_index] = Token::TextOperator(To); 738 - }, 739 + } 739 740 _ => { 740 741 // otherwise, Inch 741 742 tokens[token_index] = Token::Unit(Inch); 742 - }, 743 + } 743 744 } 744 - }, 745 - _ => {}, 745 + } 746 + _ => {} 746 747 } 747 748 // parse units like km/h, lbf per square inch 748 749 if token_index >= 2 { 749 - let token1 = &tokens[token_index-2]; 750 - let token2 = match &tokens[token_index-1] { 750 + let token1 = &tokens[token_index - 2]; 751 + let token2 = match &tokens[token_index - 1] { 751 752 // treat km/h the same as km per h 752 753 Token::Operator(Divide) => &Token::LexerKeyword(Per), 753 - _ => &tokens[token_index-1], 754 + _ => &tokens[token_index - 1], 754 755 }; 755 756 let token3 = &tokens[token_index]; 756 757 let mut replaced = true; 757 758 match (token1, token2, token3) { 758 759 // km/h 759 760 (Token::Unit(Kilometer), Token::LexerKeyword(Per), Token::Unit(Hour)) => { 760 - tokens[token_index-2] = Token::Unit(KilometersPerHour); 761 - }, 761 + tokens[token_index - 2] = Token::Unit(KilometersPerHour); 762 + } 762 763 // mi/h 763 764 (Token::Unit(Mile), Token::LexerKeyword(Per), Token::Unit(Hour)) => { 764 - tokens[token_index-2] = Token::Unit(MilesPerHour); 765 - }, 765 + tokens[token_index - 2] = Token::Unit(MilesPerHour); 766 + } 766 767 // m/s 767 768 (Token::Unit(Meter), Token::LexerKeyword(Per), Token::Unit(Second)) => { 768 - tokens[token_index-2] = Token::Unit(MetersPerSecond); 769 - }, 769 + tokens[token_index - 2] = Token::Unit(MetersPerSecond); 770 + } 770 771 // ft/s 771 772 (Token::Unit(Foot), Token::LexerKeyword(Per), Token::Unit(Second)) => { 772 - tokens[token_index-2] = Token::Unit(FeetPerSecond); 773 - }, 773 + tokens[token_index - 2] = Token::Unit(FeetPerSecond); 774 + } 774 775 // bits per second 775 776 (Token::Unit(Bit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 776 - tokens[token_index-2] = Token::Unit(BitsPerSecond); 777 - }, 777 + tokens[token_index - 2] = Token::Unit(BitsPerSecond); 778 + } 778 779 // kilobits per second 779 780 (Token::Unit(Kilobit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 780 - tokens[token_index-2] = Token::Unit(KilobitsPerSecond); 781 - }, 781 + tokens[token_index - 2] = Token::Unit(KilobitsPerSecond); 782 + } 782 783 // megabits per second 783 784 (Token::Unit(Megabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 784 - tokens[token_index-2] = Token::Unit(MegabitsPerSecond); 785 - }, 785 + tokens[token_index - 2] = Token::Unit(MegabitsPerSecond); 786 + } 786 787 // gigabits per second 787 788 (Token::Unit(Gigabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 788 - tokens[token_index-2] = Token::Unit(GigabitsPerSecond); 789 - }, 789 + tokens[token_index - 2] = Token::Unit(GigabitsPerSecond); 790 + } 790 791 // terabits per second 791 792 (Token::Unit(Terabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 792 - tokens[token_index-2] = Token::Unit(TerabitsPerSecond); 793 - }, 793 + tokens[token_index - 2] = Token::Unit(TerabitsPerSecond); 794 + } 794 795 // petabits per second 795 796 (Token::Unit(Petabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 796 - tokens[token_index-2] = Token::Unit(PetabitsPerSecond); 797 - }, 797 + tokens[token_index - 2] = Token::Unit(PetabitsPerSecond); 798 + } 798 799 // exabits per second 799 800 (Token::Unit(Exabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 800 - tokens[token_index-2] = Token::Unit(ExabitsPerSecond); 801 - }, 801 + tokens[token_index - 2] = Token::Unit(ExabitsPerSecond); 802 + } 802 803 // zettabits per second 803 804 (Token::Unit(Zettabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 804 - tokens[token_index-2] = Token::Unit(ZettabitsPerSecond); 805 - }, 805 + tokens[token_index - 2] = Token::Unit(ZettabitsPerSecond); 806 + } 806 807 // yottabits per second 807 808 (Token::Unit(Yottabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 808 - tokens[token_index-2] = Token::Unit(YottabitsPerSecond); 809 - }, 809 + tokens[token_index - 2] = Token::Unit(YottabitsPerSecond); 810 + } 810 811 // kibibits per second 811 812 (Token::Unit(Kibibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 812 - tokens[token_index-2] = Token::Unit(KibibitsPerSecond); 813 - }, 813 + tokens[token_index - 2] = Token::Unit(KibibitsPerSecond); 814 + } 814 815 // mebibits per second 815 816 (Token::Unit(Mebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 816 - tokens[token_index-2] = Token::Unit(MebibitsPerSecond); 817 - }, 817 + tokens[token_index - 2] = Token::Unit(MebibitsPerSecond); 818 + } 818 819 // gibibits per second 819 820 (Token::Unit(Gibibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 820 - tokens[token_index-2] = Token::Unit(GibibitsPerSecond); 821 - }, 821 + tokens[token_index - 2] = Token::Unit(GibibitsPerSecond); 822 + } 822 823 // tebibits per second 823 824 (Token::Unit(Tebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 824 - tokens[token_index-2] = Token::Unit(TebibitsPerSecond); 825 - }, 825 + tokens[token_index - 2] = Token::Unit(TebibitsPerSecond); 826 + } 826 827 // pebibits per second 827 828 (Token::Unit(Pebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 828 - tokens[token_index-2] = Token::Unit(PebibitsPerSecond); 829 - }, 829 + tokens[token_index - 2] = Token::Unit(PebibitsPerSecond); 830 + } 830 831 // exbibits per second 831 832 (Token::Unit(Exbibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 832 - tokens[token_index-2] = Token::Unit(ExbibitsPerSecond); 833 - }, 833 + tokens[token_index - 2] = Token::Unit(ExbibitsPerSecond); 834 + } 834 835 // zebibits per second 835 836 (Token::Unit(Zebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 836 - tokens[token_index-2] = Token::Unit(ZebibitsPerSecond); 837 - }, 837 + tokens[token_index - 2] = Token::Unit(ZebibitsPerSecond); 838 + } 838 839 // yobibits per second 839 840 (Token::Unit(Yobibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { 840 - tokens[token_index-2] = Token::Unit(YobibitsPerSecond); 841 - }, 841 + tokens[token_index - 2] = Token::Unit(YobibitsPerSecond); 842 + } 842 843 // bytes per second 843 844 (Token::Unit(Byte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 844 - tokens[token_index-2] = Token::Unit(BytesPerSecond); 845 - }, 845 + tokens[token_index - 2] = Token::Unit(BytesPerSecond); 846 + } 846 847 // kilobytes per second 847 848 (Token::Unit(Kilobyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 848 - tokens[token_index-2] = Token::Unit(KilobytesPerSecond); 849 - }, 849 + tokens[token_index - 2] = Token::Unit(KilobytesPerSecond); 850 + } 850 851 // megabytes per second 851 852 (Token::Unit(Megabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 852 - tokens[token_index-2] = Token::Unit(MegabytesPerSecond); 853 - }, 853 + tokens[token_index - 2] = Token::Unit(MegabytesPerSecond); 854 + } 854 855 // gigabytes per second 855 856 (Token::Unit(Gigabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 856 - tokens[token_index-2] = Token::Unit(GigabytesPerSecond); 857 - }, 857 + tokens[token_index - 2] = Token::Unit(GigabytesPerSecond); 858 + } 858 859 // terabytes per second 859 860 (Token::Unit(Terabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 860 - tokens[token_index-2] = Token::Unit(TerabytesPerSecond); 861 - }, 861 + tokens[token_index - 2] = Token::Unit(TerabytesPerSecond); 862 + } 862 863 // petabytes per second 863 864 (Token::Unit(Petabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 864 - tokens[token_index-2] = Token::Unit(PetabytesPerSecond); 865 - }, 865 + tokens[token_index - 2] = Token::Unit(PetabytesPerSecond); 866 + } 866 867 // exabytes per second 867 868 (Token::Unit(Exabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 868 - tokens[token_index-2] = Token::Unit(ExabytesPerSecond); 869 - }, 869 + tokens[token_index - 2] = Token::Unit(ExabytesPerSecond); 870 + } 870 871 // zettabytes per second 871 872 (Token::Unit(Zettabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 872 - tokens[token_index-2] = Token::Unit(ZettabytesPerSecond); 873 - }, 873 + tokens[token_index - 2] = Token::Unit(ZettabytesPerSecond); 874 + } 874 875 // yottabytes per second 875 876 (Token::Unit(Yottabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 876 - tokens[token_index-2] = Token::Unit(YottabytesPerSecond); 877 - }, 877 + tokens[token_index - 2] = Token::Unit(YottabytesPerSecond); 878 + } 878 879 // kibibytes per second 879 880 (Token::Unit(Kibibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 880 - tokens[token_index-2] = Token::Unit(KibibytesPerSecond); 881 - }, 881 + tokens[token_index - 2] = Token::Unit(KibibytesPerSecond); 882 + } 882 883 // mebibytes per second 883 884 (Token::Unit(Mebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 884 - tokens[token_index-2] = Token::Unit(MebibytesPerSecond); 885 - }, 885 + tokens[token_index - 2] = Token::Unit(MebibytesPerSecond); 886 + } 886 887 // gibibytes per second 887 888 (Token::Unit(Gibibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 888 - tokens[token_index-2] = Token::Unit(GibibytesPerSecond); 889 - }, 889 + tokens[token_index - 2] = Token::Unit(GibibytesPerSecond); 890 + } 890 891 // tebibytes per second 891 892 (Token::Unit(Tebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 892 - tokens[token_index-2] = Token::Unit(TebibytesPerSecond); 893 - }, 893 + tokens[token_index - 2] = Token::Unit(TebibytesPerSecond); 894 + } 894 895 // pebibytes per second 895 896 (Token::Unit(Pebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 896 - tokens[token_index-2] = Token::Unit(PebibytesPerSecond); 897 - }, 897 + tokens[token_index - 2] = Token::Unit(PebibytesPerSecond); 898 + } 898 899 // exbibytes per second 899 900 (Token::Unit(Exbibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 900 - tokens[token_index-2] = Token::Unit(ExbibytesPerSecond); 901 - }, 901 + tokens[token_index - 2] = Token::Unit(ExbibytesPerSecond); 902 + } 902 903 // zebibytes per second 903 904 (Token::Unit(Zebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 904 - tokens[token_index-2] = Token::Unit(ZebibytesPerSecond); 905 - }, 905 + tokens[token_index - 2] = Token::Unit(ZebibytesPerSecond); 906 + } 906 907 // yobibytes per second 907 908 (Token::Unit(Yobibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 908 - tokens[token_index-2] = Token::Unit(YobibytesPerSecond); 909 - }, 909 + tokens[token_index - 2] = Token::Unit(YobibytesPerSecond); 910 + } 910 911 // FLOP per second 911 912 (Token::Unit(Flop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 912 - tokens[token_index-2] = Token::Unit(FlopPerSecond); 913 - }, 913 + tokens[token_index - 2] = Token::Unit(FlopPerSecond); 914 + } 914 915 // kiloFLOP per second 915 916 (Token::Unit(KiloFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 916 - tokens[token_index-2] = Token::Unit(KiloFlopPerSecond); 917 - }, 917 + tokens[token_index - 2] = Token::Unit(KiloFlopPerSecond); 918 + } 918 919 // megaFLOP per second 919 920 (Token::Unit(MegaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 920 - tokens[token_index-2] = Token::Unit(MegaFlopPerSecond); 921 - }, 921 + tokens[token_index - 2] = Token::Unit(MegaFlopPerSecond); 922 + } 922 923 // gigaFLOP per second 923 924 (Token::Unit(GigaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 924 - tokens[token_index-2] = Token::Unit(GigaFlopPerSecond); 925 - }, 925 + tokens[token_index - 2] = Token::Unit(GigaFlopPerSecond); 926 + } 926 927 // teraFLOP per second 927 928 (Token::Unit(TeraFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 928 - tokens[token_index-2] = Token::Unit(TeraFlopPerSecond); 929 - }, 929 + tokens[token_index - 2] = Token::Unit(TeraFlopPerSecond); 930 + } 930 931 // petaFLOP per second 931 932 (Token::Unit(PetaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 932 - tokens[token_index-2] = Token::Unit(PetaFlopPerSecond); 933 - }, 933 + tokens[token_index - 2] = Token::Unit(PetaFlopPerSecond); 934 + } 934 935 // exaFLOP per second 935 936 (Token::Unit(ExaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 936 - tokens[token_index-2] = Token::Unit(ExaFlopPerSecond); 937 - }, 937 + tokens[token_index - 2] = Token::Unit(ExaFlopPerSecond); 938 + } 938 939 // zettaFLOP per second 939 940 (Token::Unit(ZettaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 940 - tokens[token_index-2] = Token::Unit(ZettaFlopPerSecond); 941 - }, 941 + tokens[token_index - 2] = Token::Unit(ZettaFlopPerSecond); 942 + } 942 943 // yottaFLOP per second 943 944 (Token::Unit(YottaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 944 - tokens[token_index-2] = Token::Unit(YottaFlopPerSecond); 945 - }, 945 + tokens[token_index - 2] = Token::Unit(YottaFlopPerSecond); 946 + } 946 947 // ronnaFLOP per second 947 948 (Token::Unit(RonnaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 948 - tokens[token_index-2] = Token::Unit(RonnaFlopPerSecond); 949 - }, 949 + tokens[token_index - 2] = Token::Unit(RonnaFlopPerSecond); 950 + } 950 951 // quettaFLOP per second 951 952 (Token::Unit(QuettaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 952 - tokens[token_index-2] = Token::Unit(QuettaFlopPerSecond); 953 - }, 953 + tokens[token_index - 2] = Token::Unit(QuettaFlopPerSecond); 954 + } 954 955 // btu/min 955 - (Token::Unit(BritishThermalUnit), Token::LexerKeyword(Per), Token::Unit(Minute)) => { 956 - tokens[token_index-2] = Token::Unit(BritishThermalUnitsPerMinute); 957 - }, 956 + ( 957 + Token::Unit(BritishThermalUnit), 958 + Token::LexerKeyword(Per), 959 + Token::Unit(Minute), 960 + ) => { 961 + tokens[token_index - 2] = Token::Unit(BritishThermalUnitsPerMinute); 962 + } 958 963 // btu/h 959 964 (Token::Unit(BritishThermalUnit), Token::LexerKeyword(Per), Token::Unit(Hour)) => { 960 - tokens[token_index-2] = Token::Unit(BritishThermalUnitsPerHour); 961 - }, 965 + tokens[token_index - 2] = Token::Unit(BritishThermalUnitsPerHour); 966 + } 962 967 // lbs/sqin 963 - (Token::LexerKeyword(PoundForce), Token::LexerKeyword(Per), Token::Unit(SquareInch)) => { 964 - tokens[token_index-2] = Token::Unit(PoundsPerSquareInch); 965 - }, 968 + ( 969 + Token::LexerKeyword(PoundForce), 970 + Token::LexerKeyword(Per), 971 + Token::Unit(SquareInch), 972 + ) => { 973 + tokens[token_index - 2] = Token::Unit(PoundsPerSquareInch); 974 + } 966 975 // inch of mercury 967 976 (Token::Unit(Inch), Token::TextOperator(Of), Token::LexerKeyword(Mercury)) => { 968 - tokens[token_index-2] = Token::Unit(InchOfMercury); 969 - }, 977 + tokens[token_index - 2] = Token::Unit(InchOfMercury); 978 + } 970 979 // revolutions per minute 971 - (Token::LexerKeyword(Revolution), Token::LexerKeyword(Per), Token::Unit(Minute)) => { 972 - tokens[token_index-2] = Token::Unit(RevolutionsPerMinute); 973 - }, 980 + ( 981 + Token::LexerKeyword(Revolution), 982 + Token::LexerKeyword(Per), 983 + Token::Unit(Minute), 984 + ) => { 985 + tokens[token_index - 2] = Token::Unit(RevolutionsPerMinute); 986 + } 974 987 _ => { 975 988 replaced = false; 976 - }, 989 + } 977 990 } 978 991 if replaced { 979 992 tokens.remove(token_index); 980 - tokens.remove(token_index-1); 993 + tokens.remove(token_index - 1); 981 994 token_index -= 2; 982 995 } 983 996 } 984 - if token_index == tokens.len()-1 { 997 + if token_index == tokens.len() - 1 { 985 998 break; 986 999 } else { 987 1000 token_index += 1; ··· 1010 1023 panic!("lex error: {}\nrun_lex input: {}", e, input); 1011 1024 } 1012 1025 }; 1013 - let info_msg = format!("run_lex input: {}\nexpected: {:?}\nreceived: {:?}", input, expected_tokens, tokens); 1026 + let info_msg = format!( 1027 + "run_lex input: {}\nexpected: {:?}\nreceived: {:?}", 1028 + input, expected_tokens, tokens 1029 + ); 1014 1030 assert!(tokens == expected_tokens, "{info_msg}"); 1015 1031 1016 1032 // Prove we can handle multiple spaces wherever we handle a single space ··· 1024 1040 assert!(tokens_stripped_spaces == expected_tokens, "{info_msg}"); 1025 1041 1026 1042 // Prove we don't need a space after a digit 1027 - let input_afterdigit_stripped_spaces = strip_afterdigit_spacing.replace_all(input, "$1"); 1028 - let tokens_afterdigit_stripped_spaces = lex(&input_afterdigit_stripped_spaces, false).unwrap(); 1029 - assert!(tokens_afterdigit_stripped_spaces == expected_tokens, "{info_msg}"); 1043 + let input_afterdigit_stripped_spaces = 1044 + strip_afterdigit_spacing.replace_all(input, "$1"); 1045 + let tokens_afterdigit_stripped_spaces = 1046 + lex(&input_afterdigit_stripped_spaces, false).unwrap(); 1047 + assert!( 1048 + tokens_afterdigit_stripped_spaces == expected_tokens, 1049 + "{info_msg}" 1050 + ); 1030 1051 }; 1031 1052 1032 1053 let run_datarate_lex = |input: &str, expected_tokens: Vec<Token>| { ··· 1035 1056 // Prove plural and non-plural data units behave identically 1036 1057 let input_nonplural_units = nonplural_data_units.replace_all(input, "$1"); 1037 1058 let tokens_nonplural_units = lex(&input_nonplural_units, false).unwrap(); 1038 - let info_msg = format!("run_datarate_lex input: {}\nexpected: {:?}\nreceived: {:?}", input, expected_tokens, tokens_nonplural_units); 1059 + let info_msg = format!( 1060 + "run_datarate_lex input: {}\nexpected: {:?}\nreceived: {:?}", 1061 + input, expected_tokens, tokens_nonplural_units 1062 + ); 1039 1063 assert!(tokens_nonplural_units == expected_tokens, "{info_msg}"); 1040 1064 }; 1041 1065 1042 - run_lex("88 kilometres * 2", vec![numtok!(88), Token::Unit(Kilometer), Token::Operator(Multiply), numtok!(2)]); 1066 + run_lex( 1067 + "88 kilometres * 2", 1068 + vec![ 1069 + numtok!(88), 1070 + Token::Unit(Kilometer), 1071 + Token::Operator(Multiply), 1072 + numtok!(2), 1073 + ], 1074 + ); 1043 1075 run_lex("0.5 marathon", vec![numtok!(0.5), Token::Unit(Marathon)]); 1044 1076 run_lex("100 nmi", vec![numtok!(100), Token::Unit(NauticalMile)]); 1045 - run_lex("101 nautical miles", vec![numtok!(101), Token::Unit(NauticalMile)]); 1077 + run_lex( 1078 + "101 nautical miles", 1079 + vec![numtok!(101), Token::Unit(NauticalMile)], 1080 + ); 1046 1081 run_lex("2 lightyears", vec![numtok!(2), Token::Unit(LightYear)]); 1047 1082 run_lex("1 light year", vec![numtok!(1), Token::Unit(LightYear)]); 1048 1083 run_lex("10 lightsec", vec![numtok!(10), Token::Unit(LightSecond)]); 1049 1084 run_lex("12 light secs", vec![numtok!(12), Token::Unit(LightSecond)]); 1050 - run_lex("33.3 square meters", vec![numtok!(33.3), Token::Unit(SquareMeter)]); 1085 + run_lex( 1086 + "33.3 square meters", 1087 + vec![numtok!(33.3), Token::Unit(SquareMeter)], 1088 + ); 1051 1089 run_lex("54 m2", vec![numtok!(54), Token::Unit(SquareMeter)]); 1052 1090 run_lex("87 sq miles", vec![numtok!(87), Token::Unit(SquareMile)]); 1053 1091 run_lex("500 feet2", vec![numtok!(500), Token::Unit(SquareFoot)]); 1054 1092 run_lex("500 feet²", vec![numtok!(500), Token::Unit(SquareFoot)]); 1055 1093 run_lex("4 cubic metres", vec![numtok!(4), Token::Unit(CubicMeter)]); 1056 - run_lex("34 cubic feet + 23 cubic yards", vec![numtok!(34), Token::Unit(CubicFoot), Token::Operator(Plus), numtok!(23), Token::Unit(CubicYard)]); 1057 - run_lex("66 inches3 + 65 millimetre³", vec![numtok!(66), Token::Unit(CubicInch), Token::Operator(Plus), numtok!(65), Token::Unit(CubicMillimeter)]); 1058 - run_lex("66 inches³ + 65 millimetre3", vec![numtok!(66), Token::Unit(CubicInch), Token::Operator(Plus), numtok!(65), Token::Unit(CubicMillimeter)]); 1094 + run_lex( 1095 + "34 cubic feet + 23 cubic yards", 1096 + vec![ 1097 + numtok!(34), 1098 + Token::Unit(CubicFoot), 1099 + Token::Operator(Plus), 1100 + numtok!(23), 1101 + Token::Unit(CubicYard), 1102 + ], 1103 + ); 1104 + run_lex( 1105 + "66 inches3 + 65 millimetre³", 1106 + vec![ 1107 + numtok!(66), 1108 + Token::Unit(CubicInch), 1109 + Token::Operator(Plus), 1110 + numtok!(65), 1111 + Token::Unit(CubicMillimeter), 1112 + ], 1113 + ); 1114 + run_lex( 1115 + "66 inches³ + 65 millimetre3", 1116 + vec![ 1117 + numtok!(66), 1118 + Token::Unit(CubicInch), 1119 + Token::Operator(Plus), 1120 + numtok!(65), 1121 + Token::Unit(CubicMillimeter), 1122 + ], 1123 + ); 1059 1124 run_lex("42 millilitres", vec![numtok!(42), Token::Unit(Milliliter)]); 1060 1125 run_lex("3 tbs", vec![numtok!(3), Token::Unit(Tablespoon)]); 1061 1126 run_lex("6 floz", vec![numtok!(6), Token::Unit(FluidOunce)]); ··· 1069 1134 run_lex("210 lbs", vec![numtok!(210), Token::Unit(Pound)]); 1070 1135 run_lex("210 pound", vec![numtok!(210), Token::Unit(Pound)]); 1071 1136 run_lex("210 pounds", vec![numtok!(210), Token::Unit(Pound)]); 1072 - run_lex("210 pounds-force", vec![numtok!(210), Token::LexerKeyword(PoundForce)]); 1137 + run_lex( 1138 + "210 pounds-force", 1139 + vec![numtok!(210), Token::LexerKeyword(PoundForce)], 1140 + ); 1073 1141 run_lex("3 ton", vec![numtok!(3), Token::Unit(ShortTon)]); 1074 1142 run_lex("3 short tons", vec![numtok!(3), Token::Unit(ShortTon)]); 1075 1143 run_lex("4 lt", vec![numtok!(4), Token::Unit(LongTon)]); ··· 1100 1168 run_datarate_lex("2.1 terabytes", vec![numtok!(2.1), Token::Unit(Terabyte)]); 1101 1169 run_datarate_lex("1.08 petabytes", vec![numtok!(1.08), Token::Unit(Petabyte)]); 1102 1170 run_datarate_lex("0.73 exabytes", vec![numtok!(0.73), Token::Unit(Exabyte)]); 1103 - run_datarate_lex("0.49 zettabytes", vec![numtok!(0.49), Token::Unit(Zettabyte)]); 1104 - run_datarate_lex("0.23 yottabytes", vec![numtok!(0.23), Token::Unit(Yottabyte)]); 1171 + run_datarate_lex( 1172 + "0.49 zettabytes", 1173 + vec![numtok!(0.49), Token::Unit(Zettabyte)], 1174 + ); 1175 + run_datarate_lex( 1176 + "0.23 yottabytes", 1177 + vec![numtok!(0.23), Token::Unit(Yottabyte)], 1178 + ); 1105 1179 run_datarate_lex("63 kibibytes", vec![numtok!(63), Token::Unit(Kibibyte)]); 1106 1180 run_datarate_lex("32 mebibytes", vec![numtok!(32), Token::Unit(Mebibyte)]); 1107 1181 run_datarate_lex("3.5 gibibytes", vec![numtok!(3.5), Token::Unit(Gibibyte)]); ··· 1113 1187 run_lex("432 bps", vec![numtok!(432), Token::Unit(BitsPerSecond)]); 1114 1188 run_lex("56 kbps", vec![numtok!(56), Token::Unit(KilobitsPerSecond)]); 1115 1189 run_lex("12 mbps", vec![numtok!(12), Token::Unit(MegabitsPerSecond)]); 1116 - run_lex("4.2 gbps", vec![numtok!(4.2), Token::Unit(GigabitsPerSecond)]); 1117 - run_lex("2.2 tbps", vec![numtok!(2.2), Token::Unit(TerabitsPerSecond)]); 1118 - run_lex("1.7 pbps", vec![numtok!(1.7), Token::Unit(PetabitsPerSecond)]); 1119 - run_lex("0.99 ebps", vec![numtok!(0.99), Token::Unit(ExabitsPerSecond)]); 1120 - run_lex("0.64 zbps", vec![numtok!(0.64), Token::Unit(ZettabitsPerSecond)]); 1121 - run_lex("0.278 ybps", vec![numtok!(0.278), Token::Unit(YottabitsPerSecond)]); 1122 - run_datarate_lex("4 bits per second", vec![numtok!(4), Token::Unit(BitsPerSecond)]); 1123 - run_datarate_lex("5 kilobits per second", vec![numtok!(5), Token::Unit(KilobitsPerSecond)]); 1124 - run_datarate_lex("6 megabits per second", vec![numtok!(6), Token::Unit(MegabitsPerSecond)]); 1125 - run_datarate_lex("7 gigabits per second", vec![numtok!(7), Token::Unit(GigabitsPerSecond)]); 1126 - run_datarate_lex("8 terabits per second", vec![numtok!(8), Token::Unit(TerabitsPerSecond)]); 1127 - run_datarate_lex("9 petabits per second", vec![numtok!(9), Token::Unit(PetabitsPerSecond)]); 1128 - run_datarate_lex("10 exabits per second", vec![numtok!(10), Token::Unit(ExabitsPerSecond)]); 1129 - run_datarate_lex("11 zettabits per second", vec![numtok!(11), Token::Unit(ZettabitsPerSecond)]); 1130 - run_datarate_lex("12 yottabits per second", vec![numtok!(12), Token::Unit(YottabitsPerSecond)]); 1131 - run_datarate_lex("13 kibibits per second", vec![numtok!(13), Token::Unit(KibibitsPerSecond)]); 1132 - run_datarate_lex("14 mebibits per second", vec![numtok!(14), Token::Unit(MebibitsPerSecond)]); 1133 - run_datarate_lex("15 gibibits per second", vec![numtok!(15), Token::Unit(GibibitsPerSecond)]); 1134 - run_datarate_lex("16 tebibits per second", vec![numtok!(16), Token::Unit(TebibitsPerSecond)]); 1135 - run_datarate_lex("17 pebibits per second", vec![numtok!(17), Token::Unit(PebibitsPerSecond)]); 1136 - run_datarate_lex("18 exbibits per second", vec![numtok!(18), Token::Unit(ExbibitsPerSecond)]); 1137 - run_datarate_lex("19 zebibits per second", vec![numtok!(19), Token::Unit(ZebibitsPerSecond)]); 1138 - run_datarate_lex("20 yobibits per second", vec![numtok!(20), Token::Unit(YobibitsPerSecond)]); 1139 - run_datarate_lex("4 bytes per second", vec![numtok!(4), Token::Unit(BytesPerSecond)]); 1140 - run_datarate_lex("5 kilobytes per second", vec![numtok!(5), Token::Unit(KilobytesPerSecond)]); 1141 - run_datarate_lex("6 megabytes per second", vec![numtok!(6), Token::Unit(MegabytesPerSecond)]); 1142 - run_datarate_lex("7 gigabytes per second", vec![numtok!(7), Token::Unit(GigabytesPerSecond)]); 1143 - run_datarate_lex("8 terabytes per second", vec![numtok!(8), Token::Unit(TerabytesPerSecond)]); 1144 - run_datarate_lex("9 petabytes per second", vec![numtok!(9), Token::Unit(PetabytesPerSecond)]); 1145 - run_datarate_lex("10 exabytes per second", vec![numtok!(10), Token::Unit(ExabytesPerSecond)]); 1146 - run_datarate_lex("11 zettabytes per second", vec![numtok!(11), Token::Unit(ZettabytesPerSecond)]); 1147 - run_datarate_lex("12 yottabytes per second", vec![numtok!(12), Token::Unit(YottabytesPerSecond)]); 1148 - run_datarate_lex("13 kibibytes per second", vec![numtok!(13), Token::Unit(KibibytesPerSecond)]); 1149 - run_datarate_lex("14 mebibytes per second", vec![numtok!(14), Token::Unit(MebibytesPerSecond)]); 1150 - run_datarate_lex("15 gibibytes per second", vec![numtok!(15), Token::Unit(GibibytesPerSecond)]); 1151 - run_datarate_lex("16 tebibytes per second", vec![numtok!(16), Token::Unit(TebibytesPerSecond)]); 1152 - run_datarate_lex("17 pebibytes per second", vec![numtok!(17), Token::Unit(PebibytesPerSecond)]); 1153 - run_datarate_lex("18 exbibytes per second", vec![numtok!(18), Token::Unit(ExbibytesPerSecond)]); 1154 - run_datarate_lex("19 zebibytes per second", vec![numtok!(19), Token::Unit(ZebibytesPerSecond)]); 1155 - run_datarate_lex("20 yobibytes per second", vec![numtok!(20), Token::Unit(YobibytesPerSecond)]); 1190 + run_lex( 1191 + "4.2 gbps", 1192 + vec![numtok!(4.2), Token::Unit(GigabitsPerSecond)], 1193 + ); 1194 + run_lex( 1195 + "2.2 tbps", 1196 + vec![numtok!(2.2), Token::Unit(TerabitsPerSecond)], 1197 + ); 1198 + run_lex( 1199 + "1.7 pbps", 1200 + vec![numtok!(1.7), Token::Unit(PetabitsPerSecond)], 1201 + ); 1202 + run_lex( 1203 + "0.99 ebps", 1204 + vec![numtok!(0.99), Token::Unit(ExabitsPerSecond)], 1205 + ); 1206 + run_lex( 1207 + "0.64 zbps", 1208 + vec![numtok!(0.64), Token::Unit(ZettabitsPerSecond)], 1209 + ); 1210 + run_lex( 1211 + "0.278 ybps", 1212 + vec![numtok!(0.278), Token::Unit(YottabitsPerSecond)], 1213 + ); 1214 + run_datarate_lex( 1215 + "4 bits per second", 1216 + vec![numtok!(4), Token::Unit(BitsPerSecond)], 1217 + ); 1218 + run_datarate_lex( 1219 + "5 kilobits per second", 1220 + vec![numtok!(5), Token::Unit(KilobitsPerSecond)], 1221 + ); 1222 + run_datarate_lex( 1223 + "6 megabits per second", 1224 + vec![numtok!(6), Token::Unit(MegabitsPerSecond)], 1225 + ); 1226 + run_datarate_lex( 1227 + "7 gigabits per second", 1228 + vec![numtok!(7), Token::Unit(GigabitsPerSecond)], 1229 + ); 1230 + run_datarate_lex( 1231 + "8 terabits per second", 1232 + vec![numtok!(8), Token::Unit(TerabitsPerSecond)], 1233 + ); 1234 + run_datarate_lex( 1235 + "9 petabits per second", 1236 + vec![numtok!(9), Token::Unit(PetabitsPerSecond)], 1237 + ); 1238 + run_datarate_lex( 1239 + "10 exabits per second", 1240 + vec![numtok!(10), Token::Unit(ExabitsPerSecond)], 1241 + ); 1242 + run_datarate_lex( 1243 + "11 zettabits per second", 1244 + vec![numtok!(11), Token::Unit(ZettabitsPerSecond)], 1245 + ); 1246 + run_datarate_lex( 1247 + "12 yottabits per second", 1248 + vec![numtok!(12), Token::Unit(YottabitsPerSecond)], 1249 + ); 1250 + run_datarate_lex( 1251 + "13 kibibits per second", 1252 + vec![numtok!(13), Token::Unit(KibibitsPerSecond)], 1253 + ); 1254 + run_datarate_lex( 1255 + "14 mebibits per second", 1256 + vec![numtok!(14), Token::Unit(MebibitsPerSecond)], 1257 + ); 1258 + run_datarate_lex( 1259 + "15 gibibits per second", 1260 + vec![numtok!(15), Token::Unit(GibibitsPerSecond)], 1261 + ); 1262 + run_datarate_lex( 1263 + "16 tebibits per second", 1264 + vec![numtok!(16), Token::Unit(TebibitsPerSecond)], 1265 + ); 1266 + run_datarate_lex( 1267 + "17 pebibits per second", 1268 + vec![numtok!(17), Token::Unit(PebibitsPerSecond)], 1269 + ); 1270 + run_datarate_lex( 1271 + "18 exbibits per second", 1272 + vec![numtok!(18), Token::Unit(ExbibitsPerSecond)], 1273 + ); 1274 + run_datarate_lex( 1275 + "19 zebibits per second", 1276 + vec![numtok!(19), Token::Unit(ZebibitsPerSecond)], 1277 + ); 1278 + run_datarate_lex( 1279 + "20 yobibits per second", 1280 + vec![numtok!(20), Token::Unit(YobibitsPerSecond)], 1281 + ); 1282 + run_datarate_lex( 1283 + "4 bytes per second", 1284 + vec![numtok!(4), Token::Unit(BytesPerSecond)], 1285 + ); 1286 + run_datarate_lex( 1287 + "5 kilobytes per second", 1288 + vec![numtok!(5), Token::Unit(KilobytesPerSecond)], 1289 + ); 1290 + run_datarate_lex( 1291 + "6 megabytes per second", 1292 + vec![numtok!(6), Token::Unit(MegabytesPerSecond)], 1293 + ); 1294 + run_datarate_lex( 1295 + "7 gigabytes per second", 1296 + vec![numtok!(7), Token::Unit(GigabytesPerSecond)], 1297 + ); 1298 + run_datarate_lex( 1299 + "8 terabytes per second", 1300 + vec![numtok!(8), Token::Unit(TerabytesPerSecond)], 1301 + ); 1302 + run_datarate_lex( 1303 + "9 petabytes per second", 1304 + vec![numtok!(9), Token::Unit(PetabytesPerSecond)], 1305 + ); 1306 + run_datarate_lex( 1307 + "10 exabytes per second", 1308 + vec![numtok!(10), Token::Unit(ExabytesPerSecond)], 1309 + ); 1310 + run_datarate_lex( 1311 + "11 zettabytes per second", 1312 + vec![numtok!(11), Token::Unit(ZettabytesPerSecond)], 1313 + ); 1314 + run_datarate_lex( 1315 + "12 yottabytes per second", 1316 + vec![numtok!(12), Token::Unit(YottabytesPerSecond)], 1317 + ); 1318 + run_datarate_lex( 1319 + "13 kibibytes per second", 1320 + vec![numtok!(13), Token::Unit(KibibytesPerSecond)], 1321 + ); 1322 + run_datarate_lex( 1323 + "14 mebibytes per second", 1324 + vec![numtok!(14), Token::Unit(MebibytesPerSecond)], 1325 + ); 1326 + run_datarate_lex( 1327 + "15 gibibytes per second", 1328 + vec![numtok!(15), Token::Unit(GibibytesPerSecond)], 1329 + ); 1330 + run_datarate_lex( 1331 + "16 tebibytes per second", 1332 + vec![numtok!(16), Token::Unit(TebibytesPerSecond)], 1333 + ); 1334 + run_datarate_lex( 1335 + "17 pebibytes per second", 1336 + vec![numtok!(17), Token::Unit(PebibytesPerSecond)], 1337 + ); 1338 + run_datarate_lex( 1339 + "18 exbibytes per second", 1340 + vec![numtok!(18), Token::Unit(ExbibytesPerSecond)], 1341 + ); 1342 + run_datarate_lex( 1343 + "19 zebibytes per second", 1344 + vec![numtok!(19), Token::Unit(ZebibytesPerSecond)], 1345 + ); 1346 + run_datarate_lex( 1347 + "20 yobibytes per second", 1348 + vec![numtok!(20), Token::Unit(YobibytesPerSecond)], 1349 + ); 1156 1350 run_lex("1 flop", vec![numtok!(1), Token::Unit(Flop)]); 1157 1351 run_lex("2 kflop", vec![numtok!(2), Token::Unit(KiloFlop)]); 1158 1352 run_lex("3 mflop", vec![numtok!(3), Token::Unit(MegaFlop)]); ··· 1165 1359 run_lex("10 rflop", vec![numtok!(10), Token::Unit(RonnaFlop)]); 1166 1360 run_lex("11 qflop", vec![numtok!(11), Token::Unit(QuettaFlop)]); 1167 1361 run_lex("1 flop/s", vec![numtok!(1), Token::Unit(FlopPerSecond)]); 1168 - run_lex("2 kflop/s", vec![numtok!(2), Token::Unit(KiloFlopPerSecond)]); 1169 - run_lex("3 mflop/s", vec![numtok!(3), Token::Unit(MegaFlopPerSecond)]); 1170 - run_lex("4 gflop/s", vec![numtok!(4), Token::Unit(GigaFlopPerSecond)]); 1171 - run_lex("5 tflop/s", vec![numtok!(5), Token::Unit(TeraFlopPerSecond)]); 1172 - run_lex("6 pflop/s", vec![numtok!(6), Token::Unit(PetaFlopPerSecond)]); 1362 + run_lex( 1363 + "2 kflop/s", 1364 + vec![numtok!(2), Token::Unit(KiloFlopPerSecond)], 1365 + ); 1366 + run_lex( 1367 + "3 mflop/s", 1368 + vec![numtok!(3), Token::Unit(MegaFlopPerSecond)], 1369 + ); 1370 + run_lex( 1371 + "4 gflop/s", 1372 + vec![numtok!(4), Token::Unit(GigaFlopPerSecond)], 1373 + ); 1374 + run_lex( 1375 + "5 tflop/s", 1376 + vec![numtok!(5), Token::Unit(TeraFlopPerSecond)], 1377 + ); 1378 + run_lex( 1379 + "6 pflop/s", 1380 + vec![numtok!(6), Token::Unit(PetaFlopPerSecond)], 1381 + ); 1173 1382 run_lex("7 eflop/s", vec![numtok!(7), Token::Unit(ExaFlopPerSecond)]); 1174 - run_lex("8 zflop/s", vec![numtok!(8), Token::Unit(ZettaFlopPerSecond)]); 1175 - run_lex("9 yflop/s", vec![numtok!(9), Token::Unit(YottaFlopPerSecond)]); 1176 - run_lex("10 rflop/s", vec![numtok!(10), Token::Unit(RonnaFlopPerSecond)]); 1177 - run_lex("11 qflop/s", vec![numtok!(11), Token::Unit(QuettaFlopPerSecond)]); 1178 - run_lex("1 flop per second", vec![numtok!(1), Token::Unit(FlopPerSecond)]); 1179 - run_lex("2 kflop per second", vec![numtok!(2), Token::Unit(KiloFlopPerSecond)]); 1180 - run_lex("3 mflop per second", vec![numtok!(3), Token::Unit(MegaFlopPerSecond)]); 1181 - run_lex("4 gflop per second", vec![numtok!(4), Token::Unit(GigaFlopPerSecond)]); 1182 - run_lex("5 tflop per second", vec![numtok!(5), Token::Unit(TeraFlopPerSecond)]); 1183 - run_lex("6 pflop per second", vec![numtok!(6), Token::Unit(PetaFlopPerSecond)]); 1184 - run_lex("7 eflop per second", vec![numtok!(7), Token::Unit(ExaFlopPerSecond)]); 1185 - run_lex("8 zflop per second", vec![numtok!(8), Token::Unit(ZettaFlopPerSecond)]); 1186 - run_lex("9 yflop per second", vec![numtok!(9), Token::Unit(YottaFlopPerSecond)]); 1187 - run_lex("10 rflop per second", vec![numtok!(10), Token::Unit(RonnaFlopPerSecond)]); 1188 - run_lex("11 qflop per second", vec![numtok!(11), Token::Unit(QuettaFlopPerSecond)]); 1383 + run_lex( 1384 + "8 zflop/s", 1385 + vec![numtok!(8), Token::Unit(ZettaFlopPerSecond)], 1386 + ); 1387 + run_lex( 1388 + "9 yflop/s", 1389 + vec![numtok!(9), Token::Unit(YottaFlopPerSecond)], 1390 + ); 1391 + run_lex( 1392 + "10 rflop/s", 1393 + vec![numtok!(10), Token::Unit(RonnaFlopPerSecond)], 1394 + ); 1395 + run_lex( 1396 + "11 qflop/s", 1397 + vec![numtok!(11), Token::Unit(QuettaFlopPerSecond)], 1398 + ); 1399 + run_lex( 1400 + "1 flop per second", 1401 + vec![numtok!(1), Token::Unit(FlopPerSecond)], 1402 + ); 1403 + run_lex( 1404 + "2 kflop per second", 1405 + vec![numtok!(2), Token::Unit(KiloFlopPerSecond)], 1406 + ); 1407 + run_lex( 1408 + "3 mflop per second", 1409 + vec![numtok!(3), Token::Unit(MegaFlopPerSecond)], 1410 + ); 1411 + run_lex( 1412 + "4 gflop per second", 1413 + vec![numtok!(4), Token::Unit(GigaFlopPerSecond)], 1414 + ); 1415 + run_lex( 1416 + "5 tflop per second", 1417 + vec![numtok!(5), Token::Unit(TeraFlopPerSecond)], 1418 + ); 1419 + run_lex( 1420 + "6 pflop per second", 1421 + vec![numtok!(6), Token::Unit(PetaFlopPerSecond)], 1422 + ); 1423 + run_lex( 1424 + "7 eflop per second", 1425 + vec![numtok!(7), Token::Unit(ExaFlopPerSecond)], 1426 + ); 1427 + run_lex( 1428 + "8 zflop per second", 1429 + vec![numtok!(8), Token::Unit(ZettaFlopPerSecond)], 1430 + ); 1431 + run_lex( 1432 + "9 yflop per second", 1433 + vec![numtok!(9), Token::Unit(YottaFlopPerSecond)], 1434 + ); 1435 + run_lex( 1436 + "10 rflop per second", 1437 + vec![numtok!(10), Token::Unit(RonnaFlopPerSecond)], 1438 + ); 1439 + run_lex( 1440 + "11 qflop per second", 1441 + vec![numtok!(11), Token::Unit(QuettaFlopPerSecond)], 1442 + ); 1189 1443 run_lex("1 flops", vec![numtok!(1), Token::Unit(FlopPerSecond)]); 1190 1444 run_lex("2 kflops", vec![numtok!(2), Token::Unit(KiloFlopPerSecond)]); 1191 1445 run_lex("3 mflops", vec![numtok!(3), Token::Unit(MegaFlopPerSecond)]); ··· 1193 1447 run_lex("5 tflops", vec![numtok!(5), Token::Unit(TeraFlopPerSecond)]); 1194 1448 run_lex("6 pflops", vec![numtok!(6), Token::Unit(PetaFlopPerSecond)]); 1195 1449 run_lex("7 eflops", vec![numtok!(7), Token::Unit(ExaFlopPerSecond)]); 1196 - run_lex("8 zflops", vec![numtok!(8), Token::Unit(ZettaFlopPerSecond)]); 1197 - run_lex("9 yflops", vec![numtok!(9), Token::Unit(YottaFlopPerSecond)]); 1198 - run_lex("10 rflops", vec![numtok!(10), Token::Unit(RonnaFlopPerSecond)]); 1199 - run_lex("11 qflops", vec![numtok!(11), Token::Unit(QuettaFlopPerSecond)]); 1450 + run_lex( 1451 + "8 zflops", 1452 + vec![numtok!(8), Token::Unit(ZettaFlopPerSecond)], 1453 + ); 1454 + run_lex( 1455 + "9 yflops", 1456 + vec![numtok!(9), Token::Unit(YottaFlopPerSecond)], 1457 + ); 1458 + run_lex( 1459 + "10 rflops", 1460 + vec![numtok!(10), Token::Unit(RonnaFlopPerSecond)], 1461 + ); 1462 + run_lex( 1463 + "11 qflops", 1464 + vec![numtok!(11), Token::Unit(QuettaFlopPerSecond)], 1465 + ); 1200 1466 run_lex("234 wh", vec![numtok!(234), Token::Unit(WattHour)]); 1201 1467 run_lex("1 w", vec![numtok!(1), Token::Unit(Watt)]); 1202 1468 run_lex("1 watt", vec![numtok!(1), Token::Unit(Watt)]); 1203 1469 run_lex("1 watts", vec![numtok!(1), Token::Unit(Watt)]); 1204 1470 run_lex("1 watt hour", vec![numtok!(1), Token::Unit(WattHour)]); 1205 - run_lex("0 watt + 1 watts", vec![numtok!(0), Token::Unit(Watt), Token::Operator(Plus), numtok!(1), Token::Unit(Watt)]); 1206 - run_lex("0 watt * 1", vec![numtok!(0), Token::Unit(Watt), Token::Operator(Multiply), numtok!(1)]); 1207 - run_lex("2 watts + 3 watts", vec![numtok!(2), Token::Unit(Watt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1208 - run_lex("2 watts * 3", vec![numtok!(2), Token::Unit(Watt), Token::Operator(Multiply), numtok!(3)]); 1209 - run_lex("4 watt plus 5 watts", vec![numtok!(4), Token::Unit(Watt), Token::Operator(Plus), numtok!(5), Token::Unit(Watt)]); 1210 - run_lex("4 watt times 5", vec![numtok!(4), Token::Unit(Watt), Token::Operator(Multiply), numtok!(5)]); 1211 - run_lex("6 watts plus 7 watts", vec![numtok!(6), Token::Unit(Watt), Token::Operator(Plus), numtok!(7), Token::Unit(Watt)]); 1212 - run_lex("6 watts times 7", vec![numtok!(6), Token::Unit(Watt), Token::Operator(Multiply), numtok!(7)]); 1471 + run_lex( 1472 + "0 watt + 1 watts", 1473 + vec![ 1474 + numtok!(0), 1475 + Token::Unit(Watt), 1476 + Token::Operator(Plus), 1477 + numtok!(1), 1478 + Token::Unit(Watt), 1479 + ], 1480 + ); 1481 + run_lex( 1482 + "0 watt * 1", 1483 + vec![ 1484 + numtok!(0), 1485 + Token::Unit(Watt), 1486 + Token::Operator(Multiply), 1487 + numtok!(1), 1488 + ], 1489 + ); 1490 + run_lex( 1491 + "2 watts + 3 watts", 1492 + vec![ 1493 + numtok!(2), 1494 + Token::Unit(Watt), 1495 + Token::Operator(Plus), 1496 + numtok!(3), 1497 + Token::Unit(Watt), 1498 + ], 1499 + ); 1500 + run_lex( 1501 + "2 watts * 3", 1502 + vec![ 1503 + numtok!(2), 1504 + Token::Unit(Watt), 1505 + Token::Operator(Multiply), 1506 + numtok!(3), 1507 + ], 1508 + ); 1509 + run_lex( 1510 + "4 watt plus 5 watts", 1511 + vec![ 1512 + numtok!(4), 1513 + Token::Unit(Watt), 1514 + Token::Operator(Plus), 1515 + numtok!(5), 1516 + Token::Unit(Watt), 1517 + ], 1518 + ); 1519 + run_lex( 1520 + "4 watt times 5", 1521 + vec![ 1522 + numtok!(4), 1523 + Token::Unit(Watt), 1524 + Token::Operator(Multiply), 1525 + numtok!(5), 1526 + ], 1527 + ); 1528 + run_lex( 1529 + "6 watts plus 7 watts", 1530 + vec![ 1531 + numtok!(6), 1532 + Token::Unit(Watt), 1533 + Token::Operator(Plus), 1534 + numtok!(7), 1535 + Token::Unit(Watt), 1536 + ], 1537 + ); 1538 + run_lex( 1539 + "6 watts times 7", 1540 + vec![ 1541 + numtok!(6), 1542 + Token::Unit(Watt), 1543 + Token::Operator(Multiply), 1544 + numtok!(7), 1545 + ], 1546 + ); 1213 1547 run_lex("2.3 kwh", vec![numtok!(2.3), Token::Unit(KilowattHour)]); 1214 1548 run_lex("1 kw", vec![numtok!(1), Token::Unit(Kilowatt)]); 1215 1549 run_lex("1 kilowatt", vec![numtok!(1), Token::Unit(Kilowatt)]); 1216 1550 run_lex("1 kilowatts", vec![numtok!(1), Token::Unit(Kilowatt)]); 1217 - run_lex("1 kilowatt hour", vec![numtok!(1), Token::Unit(KilowattHour)]); 1218 - run_lex("2 kilowatt + 3 watt", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1219 - run_lex("2 kilowatt * 4", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Multiply), numtok!(4)]); 1220 - run_lex("2 kilowatt times 4", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Multiply), numtok!(4)]); 1221 - run_lex("2 kilowatt + 3 watts", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1222 - run_lex("2 kilowatts + 3 watt", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1223 - run_lex("2 kilowatts + 3 watts", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1224 - run_lex("2 kilowatt plus 3 watt", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1225 - run_lex("2 kilowatt plus 3 watts", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1226 - run_lex("2 kilowatts plus 3 watt", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1227 - run_lex("2 kilowatts plus 3 watts", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1228 - run_lex("6.6 watts + 4 kilowatts", vec![numtok!(6.6), Token::Unit(Watt), Token::Operator(Plus), numtok!(4), Token::Unit(Kilowatt)]); 1229 - run_lex("6.6 watts plus 4 kilowatts", vec![numtok!(6.6), Token::Unit(Watt), Token::Operator(Plus), numtok!(4), Token::Unit(Kilowatt)]); 1551 + run_lex( 1552 + "1 kilowatt hour", 1553 + vec![numtok!(1), Token::Unit(KilowattHour)], 1554 + ); 1555 + run_lex( 1556 + "2 kilowatt + 3 watt", 1557 + vec![ 1558 + numtok!(2), 1559 + Token::Unit(Kilowatt), 1560 + Token::Operator(Plus), 1561 + numtok!(3), 1562 + Token::Unit(Watt), 1563 + ], 1564 + ); 1565 + run_lex( 1566 + "2 kilowatt * 4", 1567 + vec![ 1568 + numtok!(2), 1569 + Token::Unit(Kilowatt), 1570 + Token::Operator(Multiply), 1571 + numtok!(4), 1572 + ], 1573 + ); 1574 + run_lex( 1575 + "2 kilowatt times 4", 1576 + vec![ 1577 + numtok!(2), 1578 + Token::Unit(Kilowatt), 1579 + Token::Operator(Multiply), 1580 + numtok!(4), 1581 + ], 1582 + ); 1583 + run_lex( 1584 + "2 kilowatt + 3 watts", 1585 + vec![ 1586 + numtok!(2), 1587 + Token::Unit(Kilowatt), 1588 + Token::Operator(Plus), 1589 + numtok!(3), 1590 + Token::Unit(Watt), 1591 + ], 1592 + ); 1593 + run_lex( 1594 + "2 kilowatts + 3 watt", 1595 + vec![ 1596 + numtok!(2), 1597 + Token::Unit(Kilowatt), 1598 + Token::Operator(Plus), 1599 + numtok!(3), 1600 + Token::Unit(Watt), 1601 + ], 1602 + ); 1603 + run_lex( 1604 + "2 kilowatts + 3 watts", 1605 + vec![ 1606 + numtok!(2), 1607 + Token::Unit(Kilowatt), 1608 + Token::Operator(Plus), 1609 + numtok!(3), 1610 + Token::Unit(Watt), 1611 + ], 1612 + ); 1613 + run_lex( 1614 + "2 kilowatt plus 3 watt", 1615 + vec![ 1616 + numtok!(2), 1617 + Token::Unit(Kilowatt), 1618 + Token::Operator(Plus), 1619 + numtok!(3), 1620 + Token::Unit(Watt), 1621 + ], 1622 + ); 1623 + run_lex( 1624 + "2 kilowatt plus 3 watts", 1625 + vec![ 1626 + numtok!(2), 1627 + Token::Unit(Kilowatt), 1628 + Token::Operator(Plus), 1629 + numtok!(3), 1630 + Token::Unit(Watt), 1631 + ], 1632 + ); 1633 + run_lex( 1634 + "2 kilowatts plus 3 watt", 1635 + vec![ 1636 + numtok!(2), 1637 + Token::Unit(Kilowatt), 1638 + Token::Operator(Plus), 1639 + numtok!(3), 1640 + Token::Unit(Watt), 1641 + ], 1642 + ); 1643 + run_lex( 1644 + "2 kilowatts plus 3 watts", 1645 + vec![ 1646 + numtok!(2), 1647 + Token::Unit(Kilowatt), 1648 + Token::Operator(Plus), 1649 + numtok!(3), 1650 + Token::Unit(Watt), 1651 + ], 1652 + ); 1653 + run_lex( 1654 + "6.6 watts + 4 kilowatts", 1655 + vec![ 1656 + numtok!(6.6), 1657 + Token::Unit(Watt), 1658 + Token::Operator(Plus), 1659 + numtok!(4), 1660 + Token::Unit(Kilowatt), 1661 + ], 1662 + ); 1663 + run_lex( 1664 + "6.6 watts plus 4 kilowatts", 1665 + vec![ 1666 + numtok!(6.6), 1667 + Token::Unit(Watt), 1668 + Token::Operator(Plus), 1669 + numtok!(4), 1670 + Token::Unit(Kilowatt), 1671 + ], 1672 + ); 1230 1673 run_lex("2.3 mwh", vec![numtok!(2.3), Token::Unit(MegawattHour)]); 1231 1674 run_lex("1 mw", vec![numtok!(1), Token::Unit(Megawatt)]); 1232 1675 run_lex("1 megawatt", vec![numtok!(1), Token::Unit(Megawatt)]); 1233 - run_lex("1 megawatt hour", vec![numtok!(1), Token::Unit(MegawattHour)]); 1234 - run_lex("2 megawatt + 3 watt", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1235 - run_lex("2 megawatt * 6", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Multiply), numtok!(6)]); 1236 - run_lex("2 megawatt times 6", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Multiply), numtok!(6)]); 1237 - run_lex("2 megawatt + 3 watts", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1238 - run_lex("2 megawatts + 3 watt", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1239 - run_lex("2 megawatts + 3 watts", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1240 - run_lex("2 megawatt plus 3 watt", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1241 - run_lex("2 megawatt plus 3 watts", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1242 - run_lex("2 megawatts plus 3 watt", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1243 - run_lex("2 megawatts plus 3 watts", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); 1244 - run_lex("6.6 watts + 4 megawatts", vec![numtok!(6.6), Token::Unit(Watt), Token::Operator(Plus), numtok!(4), Token::Unit(Megawatt)]); 1245 - run_lex("6.6 watts plus 4 megawatts", vec![numtok!(6.6), Token::Unit(Watt), Token::Operator(Plus), numtok!(4), Token::Unit(Megawatt)]); 1676 + run_lex( 1677 + "1 megawatt hour", 1678 + vec![numtok!(1), Token::Unit(MegawattHour)], 1679 + ); 1680 + run_lex( 1681 + "2 megawatt + 3 watt", 1682 + vec![ 1683 + numtok!(2), 1684 + Token::Unit(Megawatt), 1685 + Token::Operator(Plus), 1686 + numtok!(3), 1687 + Token::Unit(Watt), 1688 + ], 1689 + ); 1690 + run_lex( 1691 + "2 megawatt * 6", 1692 + vec![ 1693 + numtok!(2), 1694 + Token::Unit(Megawatt), 1695 + Token::Operator(Multiply), 1696 + numtok!(6), 1697 + ], 1698 + ); 1699 + run_lex( 1700 + "2 megawatt times 6", 1701 + vec![ 1702 + numtok!(2), 1703 + Token::Unit(Megawatt), 1704 + Token::Operator(Multiply), 1705 + numtok!(6), 1706 + ], 1707 + ); 1708 + run_lex( 1709 + "2 megawatt + 3 watts", 1710 + vec![ 1711 + numtok!(2), 1712 + Token::Unit(Megawatt), 1713 + Token::Operator(Plus), 1714 + numtok!(3), 1715 + Token::Unit(Watt), 1716 + ], 1717 + ); 1718 + run_lex( 1719 + "2 megawatts + 3 watt", 1720 + vec![ 1721 + numtok!(2), 1722 + Token::Unit(Megawatt), 1723 + Token::Operator(Plus), 1724 + numtok!(3), 1725 + Token::Unit(Watt), 1726 + ], 1727 + ); 1728 + run_lex( 1729 + "2 megawatts + 3 watts", 1730 + vec![ 1731 + numtok!(2), 1732 + Token::Unit(Megawatt), 1733 + Token::Operator(Plus), 1734 + numtok!(3), 1735 + Token::Unit(Watt), 1736 + ], 1737 + ); 1738 + run_lex( 1739 + "2 megawatt plus 3 watt", 1740 + vec![ 1741 + numtok!(2), 1742 + Token::Unit(Megawatt), 1743 + Token::Operator(Plus), 1744 + numtok!(3), 1745 + Token::Unit(Watt), 1746 + ], 1747 + ); 1748 + run_lex( 1749 + "2 megawatt plus 3 watts", 1750 + vec![ 1751 + numtok!(2), 1752 + Token::Unit(Megawatt), 1753 + Token::Operator(Plus), 1754 + numtok!(3), 1755 + Token::Unit(Watt), 1756 + ], 1757 + ); 1758 + run_lex( 1759 + "2 megawatts plus 3 watt", 1760 + vec![ 1761 + numtok!(2), 1762 + Token::Unit(Megawatt), 1763 + Token::Operator(Plus), 1764 + numtok!(3), 1765 + Token::Unit(Watt), 1766 + ], 1767 + ); 1768 + run_lex( 1769 + "2 megawatts plus 3 watts", 1770 + vec![ 1771 + numtok!(2), 1772 + Token::Unit(Megawatt), 1773 + Token::Operator(Plus), 1774 + numtok!(3), 1775 + Token::Unit(Watt), 1776 + ], 1777 + ); 1778 + run_lex( 1779 + "6.6 watts + 4 megawatts", 1780 + vec![ 1781 + numtok!(6.6), 1782 + Token::Unit(Watt), 1783 + Token::Operator(Plus), 1784 + numtok!(4), 1785 + Token::Unit(Megawatt), 1786 + ], 1787 + ); 1788 + run_lex( 1789 + "6.6 watts plus 4 megawatts", 1790 + vec![ 1791 + numtok!(6.6), 1792 + Token::Unit(Watt), 1793 + Token::Operator(Plus), 1794 + numtok!(4), 1795 + Token::Unit(Megawatt), 1796 + ], 1797 + ); 1246 1798 run_lex("234 gwh", vec![numtok!(234), Token::Unit(GigawattHour)]); 1247 1799 run_lex("1 gw", vec![numtok!(1), Token::Unit(Gigawatt)]); 1248 1800 run_lex("1 gigawatt", vec![numtok!(1), Token::Unit(Gigawatt)]); 1249 1801 run_lex("1 gigawatts", vec![numtok!(1), Token::Unit(Gigawatt)]); 1250 - run_lex("1 gigawatt hour", vec![numtok!(1), Token::Unit(GigawattHour)]); 1251 - run_lex("0 gigawatt + 1 gigawatts", vec![numtok!(0), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(1), Token::Unit(Gigawatt)]); 1252 - run_lex("0 gigawatt * 1", vec![numtok!(0), Token::Unit(Gigawatt), Token::Operator(Multiply), numtok!(1)]); 1253 - run_lex("2 gigawatts + 3 gigawatts", vec![numtok!(2), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Gigawatt)]); 1254 - run_lex("2 gigawatts * 3", vec![numtok!(2), Token::Unit(Gigawatt), Token::Operator(Multiply), numtok!(3)]); 1255 - run_lex("4 gigawatt plus 5 watt", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Watt)]); 1256 - run_lex("4 gigawatt plus 5 megawatt", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Megawatt)]); 1257 - run_lex("4 gigawatt plus 5 gigawatt", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Gigawatt)]); 1258 - run_lex("4 gigawatt plus 5 watts", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Watt)]); 1259 - run_lex("4 gigawatt plus 5 megawatts", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Megawatt)]); 1260 - run_lex("4 gigawatt plus 5 gigawatts", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Gigawatt)]); 1261 - run_lex("4 gigawatt times 5", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Multiply), numtok!(5)]); 1262 - run_lex("6 gigawatts plus 7 watt", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Watt)]); 1263 - run_lex("6 gigawatts plus 7 megawatt", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Megawatt)]); 1264 - run_lex("6 gigawatts plus 7 gigawatt", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Gigawatt)]); 1265 - run_lex("6 gigawatts plus 7 watts", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Watt)]); 1266 - run_lex("6 gigawatts plus 7 megawatts", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Megawatt)]); 1267 - run_lex("6 gigawatts plus 7 gigawatts", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Gigawatt)]); 1268 - run_lex("6 gigawatts times 7", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Multiply), numtok!(7)]); 1269 - run_lex("88 mw * 3", vec![numtok!(88), Token::Unit(Megawatt), Token::Operator(Multiply), numtok!(3)]); 1270 - run_lex("88 mw times 3", vec![numtok!(88), Token::Unit(Megawatt), Token::Operator(Multiply), numtok!(3)]); 1802 + run_lex( 1803 + "1 gigawatt hour", 1804 + vec![numtok!(1), Token::Unit(GigawattHour)], 1805 + ); 1806 + run_lex( 1807 + "0 gigawatt + 1 gigawatts", 1808 + vec![ 1809 + numtok!(0), 1810 + Token::Unit(Gigawatt), 1811 + Token::Operator(Plus), 1812 + numtok!(1), 1813 + Token::Unit(Gigawatt), 1814 + ], 1815 + ); 1816 + run_lex( 1817 + "0 gigawatt * 1", 1818 + vec![ 1819 + numtok!(0), 1820 + Token::Unit(Gigawatt), 1821 + Token::Operator(Multiply), 1822 + numtok!(1), 1823 + ], 1824 + ); 1825 + run_lex( 1826 + "2 gigawatts + 3 gigawatts", 1827 + vec![ 1828 + numtok!(2), 1829 + Token::Unit(Gigawatt), 1830 + Token::Operator(Plus), 1831 + numtok!(3), 1832 + Token::Unit(Gigawatt), 1833 + ], 1834 + ); 1835 + run_lex( 1836 + "2 gigawatts * 3", 1837 + vec![ 1838 + numtok!(2), 1839 + Token::Unit(Gigawatt), 1840 + Token::Operator(Multiply), 1841 + numtok!(3), 1842 + ], 1843 + ); 1844 + run_lex( 1845 + "4 gigawatt plus 5 watt", 1846 + vec![ 1847 + numtok!(4), 1848 + Token::Unit(Gigawatt), 1849 + Token::Operator(Plus), 1850 + numtok!(5), 1851 + Token::Unit(Watt), 1852 + ], 1853 + ); 1854 + run_lex( 1855 + "4 gigawatt plus 5 megawatt", 1856 + vec![ 1857 + numtok!(4), 1858 + Token::Unit(Gigawatt), 1859 + Token::Operator(Plus), 1860 + numtok!(5), 1861 + Token::Unit(Megawatt), 1862 + ], 1863 + ); 1864 + run_lex( 1865 + "4 gigawatt plus 5 gigawatt", 1866 + vec![ 1867 + numtok!(4), 1868 + Token::Unit(Gigawatt), 1869 + Token::Operator(Plus), 1870 + numtok!(5), 1871 + Token::Unit(Gigawatt), 1872 + ], 1873 + ); 1874 + run_lex( 1875 + "4 gigawatt plus 5 watts", 1876 + vec![ 1877 + numtok!(4), 1878 + Token::Unit(Gigawatt), 1879 + Token::Operator(Plus), 1880 + numtok!(5), 1881 + Token::Unit(Watt), 1882 + ], 1883 + ); 1884 + run_lex( 1885 + "4 gigawatt plus 5 megawatts", 1886 + vec![ 1887 + numtok!(4), 1888 + Token::Unit(Gigawatt), 1889 + Token::Operator(Plus), 1890 + numtok!(5), 1891 + Token::Unit(Megawatt), 1892 + ], 1893 + ); 1894 + run_lex( 1895 + "4 gigawatt plus 5 gigawatts", 1896 + vec![ 1897 + numtok!(4), 1898 + Token::Unit(Gigawatt), 1899 + Token::Operator(Plus), 1900 + numtok!(5), 1901 + Token::Unit(Gigawatt), 1902 + ], 1903 + ); 1904 + run_lex( 1905 + "4 gigawatt times 5", 1906 + vec![ 1907 + numtok!(4), 1908 + Token::Unit(Gigawatt), 1909 + Token::Operator(Multiply), 1910 + numtok!(5), 1911 + ], 1912 + ); 1913 + run_lex( 1914 + "6 gigawatts plus 7 watt", 1915 + vec![ 1916 + numtok!(6), 1917 + Token::Unit(Gigawatt), 1918 + Token::Operator(Plus), 1919 + numtok!(7), 1920 + Token::Unit(Watt), 1921 + ], 1922 + ); 1923 + run_lex( 1924 + "6 gigawatts plus 7 megawatt", 1925 + vec![ 1926 + numtok!(6), 1927 + Token::Unit(Gigawatt), 1928 + Token::Operator(Plus), 1929 + numtok!(7), 1930 + Token::Unit(Megawatt), 1931 + ], 1932 + ); 1933 + run_lex( 1934 + "6 gigawatts plus 7 gigawatt", 1935 + vec![ 1936 + numtok!(6), 1937 + Token::Unit(Gigawatt), 1938 + Token::Operator(Plus), 1939 + numtok!(7), 1940 + Token::Unit(Gigawatt), 1941 + ], 1942 + ); 1943 + run_lex( 1944 + "6 gigawatts plus 7 watts", 1945 + vec![ 1946 + numtok!(6), 1947 + Token::Unit(Gigawatt), 1948 + Token::Operator(Plus), 1949 + numtok!(7), 1950 + Token::Unit(Watt), 1951 + ], 1952 + ); 1953 + run_lex( 1954 + "6 gigawatts plus 7 megawatts", 1955 + vec![ 1956 + numtok!(6), 1957 + Token::Unit(Gigawatt), 1958 + Token::Operator(Plus), 1959 + numtok!(7), 1960 + Token::Unit(Megawatt), 1961 + ], 1962 + ); 1963 + run_lex( 1964 + "6 gigawatts plus 7 gigawatts", 1965 + vec![ 1966 + numtok!(6), 1967 + Token::Unit(Gigawatt), 1968 + Token::Operator(Plus), 1969 + numtok!(7), 1970 + Token::Unit(Gigawatt), 1971 + ], 1972 + ); 1973 + run_lex( 1974 + "6 gigawatts times 7", 1975 + vec![ 1976 + numtok!(6), 1977 + Token::Unit(Gigawatt), 1978 + Token::Operator(Multiply), 1979 + numtok!(7), 1980 + ], 1981 + ); 1982 + run_lex( 1983 + "88 mw * 3", 1984 + vec![ 1985 + numtok!(88), 1986 + Token::Unit(Megawatt), 1987 + Token::Operator(Multiply), 1988 + numtok!(3), 1989 + ], 1990 + ); 1991 + run_lex( 1992 + "88 mw times 3", 1993 + vec![ 1994 + numtok!(88), 1995 + Token::Unit(Megawatt), 1996 + Token::Operator(Multiply), 1997 + numtok!(3), 1998 + ], 1999 + ); 1271 2000 run_lex("999 kb", vec![numtok!(999), Token::Unit(Kilobyte)]); 1272 - run_lex("200 gb - 100 mb", vec![numtok!(200), Token::Unit(Gigabyte), Token::Operator(Minus), numtok!(100), Token::Unit(Megabyte)]); 2001 + run_lex( 2002 + "200 gb - 100 mb", 2003 + vec![ 2004 + numtok!(200), 2005 + Token::Unit(Gigabyte), 2006 + Token::Operator(Minus), 2007 + numtok!(100), 2008 + Token::Unit(Megabyte), 2009 + ], 2010 + ); 1273 2011 run_lex("999 kib", vec![numtok!(999), Token::Unit(Kibibyte)]); 1274 - run_lex("200 gib - 100 mib", vec![numtok!(200), Token::Unit(Gibibyte), Token::Operator(Minus), numtok!(100), Token::Unit(Mebibyte)]); 2012 + run_lex( 2013 + "200 gib - 100 mib", 2014 + vec![ 2015 + numtok!(200), 2016 + Token::Unit(Gibibyte), 2017 + Token::Operator(Minus), 2018 + numtok!(100), 2019 + Token::Unit(Mebibyte), 2020 + ], 2021 + ); 1275 2022 run_lex("45 btu", vec![numtok!(45), Token::Unit(BritishThermalUnit)]); 1276 - run_lex("45.5 british thermal unit", vec![numtok!(45.5), Token::Unit(BritishThermalUnit)]); 1277 - run_lex("46 british thermal units", vec![numtok!(46), Token::Unit(BritishThermalUnit)]); 1278 - run_lex("5432 newton metres", vec![numtok!(5432), Token::Unit(NewtonMeter)]); 1279 - run_lex("2345 newton-meters", vec![numtok!(2345), Token::Unit(NewtonMeter)]); 2023 + run_lex( 2024 + "45.5 british thermal unit", 2025 + vec![numtok!(45.5), Token::Unit(BritishThermalUnit)], 2026 + ); 2027 + run_lex( 2028 + "46 british thermal units", 2029 + vec![numtok!(46), Token::Unit(BritishThermalUnit)], 2030 + ); 2031 + run_lex( 2032 + "5432 newton metres", 2033 + vec![numtok!(5432), Token::Unit(NewtonMeter)], 2034 + ); 2035 + run_lex( 2036 + "2345 newton-meters", 2037 + vec![numtok!(2345), Token::Unit(NewtonMeter)], 2038 + ); 1280 2039 run_lex("20 lbf", vec![numtok!(20), Token::LexerKeyword(PoundForce)]); 1281 2040 run_lex("60 hz", vec![numtok!(60), Token::Unit(Hertz)]); 1282 - run_lex("1100 rpm", vec![numtok!(1100), Token::Unit(RevolutionsPerMinute)]); 1283 - run_lex("1150 revolutions per minute", vec![numtok!(1150), Token::Unit(RevolutionsPerMinute)]); 1284 - run_lex("1 revolution per min", vec![numtok!(1), Token::Unit(RevolutionsPerMinute)]); 1285 - run_lex("4 revolution / mins", vec![numtok!(4), Token::Unit(RevolutionsPerMinute)]); 1286 - run_lex("1250 r / min", vec![numtok!(1250), Token::Unit(RevolutionsPerMinute)]); 1287 - run_lex("1300 rev / min", vec![numtok!(1300), Token::Unit(RevolutionsPerMinute)]); 1288 - run_lex("1350 rev / minute", vec![numtok!(1350), Token::Unit(RevolutionsPerMinute)]); 1289 - run_lex("1250 r per min", vec![numtok!(1250), Token::Unit(RevolutionsPerMinute)]); 1290 - run_lex("1300 rev per min", vec![numtok!(1300), Token::Unit(RevolutionsPerMinute)]); 1291 - run_lex("1350 rev per minute", vec![numtok!(1350), Token::Unit(RevolutionsPerMinute)]); 1292 - run_lex("100 kph", vec![numtok!(100), Token::Unit(KilometersPerHour)]); 1293 - run_lex("100 kmh", vec![numtok!(100), Token::Unit(KilometersPerHour)]); 1294 - run_lex("100 kilometers per hour", vec![numtok!(100), Token::Unit(KilometersPerHour)]); 1295 - run_lex("100 kilometre / hrs", vec![numtok!(100), Token::Unit(KilometersPerHour)]); 2041 + run_lex( 2042 + "1100 rpm", 2043 + vec![numtok!(1100), Token::Unit(RevolutionsPerMinute)], 2044 + ); 2045 + run_lex( 2046 + "1150 revolutions per minute", 2047 + vec![numtok!(1150), Token::Unit(RevolutionsPerMinute)], 2048 + ); 2049 + run_lex( 2050 + "1 revolution per min", 2051 + vec![numtok!(1), Token::Unit(RevolutionsPerMinute)], 2052 + ); 2053 + run_lex( 2054 + "4 revolution / mins", 2055 + vec![numtok!(4), Token::Unit(RevolutionsPerMinute)], 2056 + ); 2057 + run_lex( 2058 + "1250 r / min", 2059 + vec![numtok!(1250), Token::Unit(RevolutionsPerMinute)], 2060 + ); 2061 + run_lex( 2062 + "1300 rev / min", 2063 + vec![numtok!(1300), Token::Unit(RevolutionsPerMinute)], 2064 + ); 2065 + run_lex( 2066 + "1350 rev / minute", 2067 + vec![numtok!(1350), Token::Unit(RevolutionsPerMinute)], 2068 + ); 2069 + run_lex( 2070 + "1250 r per min", 2071 + vec![numtok!(1250), Token::Unit(RevolutionsPerMinute)], 2072 + ); 2073 + run_lex( 2074 + "1300 rev per min", 2075 + vec![numtok!(1300), Token::Unit(RevolutionsPerMinute)], 2076 + ); 2077 + run_lex( 2078 + "1350 rev per minute", 2079 + vec![numtok!(1350), Token::Unit(RevolutionsPerMinute)], 2080 + ); 2081 + run_lex( 2082 + "100 kph", 2083 + vec![numtok!(100), Token::Unit(KilometersPerHour)], 2084 + ); 2085 + run_lex( 2086 + "100 kmh", 2087 + vec![numtok!(100), Token::Unit(KilometersPerHour)], 2088 + ); 2089 + run_lex( 2090 + "100 kilometers per hour", 2091 + vec![numtok!(100), Token::Unit(KilometersPerHour)], 2092 + ); 2093 + run_lex( 2094 + "100 kilometre / hrs", 2095 + vec![numtok!(100), Token::Unit(KilometersPerHour)], 2096 + ); 1296 2097 run_lex("3.6 mps", vec![numtok!(3.6), Token::Unit(MetersPerSecond)]); 1297 - run_lex("3.6 meters per second", vec![numtok!(3.6), Token::Unit(MetersPerSecond)]); 1298 - run_lex("3.6 metre / secs", vec![numtok!(3.6), Token::Unit(MetersPerSecond)]); 2098 + run_lex( 2099 + "3.6 meters per second", 2100 + vec![numtok!(3.6), Token::Unit(MetersPerSecond)], 2101 + ); 2102 + run_lex( 2103 + "3.6 metre / secs", 2104 + vec![numtok!(3.6), Token::Unit(MetersPerSecond)], 2105 + ); 1299 2106 run_lex("60 mph", vec![numtok!(60), Token::Unit(MilesPerHour)]); 1300 - run_lex("60 miles per hour", vec![numtok!(60), Token::Unit(MilesPerHour)]); 2107 + run_lex( 2108 + "60 miles per hour", 2109 + vec![numtok!(60), Token::Unit(MilesPerHour)], 2110 + ); 1301 2111 run_lex("60 mile / hr", vec![numtok!(60), Token::Unit(MilesPerHour)]); 1302 2112 run_lex("35 fps", vec![numtok!(35), Token::Unit(FeetPerSecond)]); 1303 2113 run_lex("35 ft / sec", vec![numtok!(35), Token::Unit(FeetPerSecond)]); 1304 - run_lex("35 ft per seconds", vec![numtok!(35), Token::Unit(FeetPerSecond)]); 1305 - run_lex("35 foot / secs", vec![numtok!(35), Token::Unit(FeetPerSecond)]); 1306 - run_lex("35 foot per seconds", vec![numtok!(35), Token::Unit(FeetPerSecond)]); 1307 - run_lex("35 feet / sec", vec![numtok!(35), Token::Unit(FeetPerSecond)]); 1308 - run_lex("35 feet per second", vec![numtok!(35), Token::Unit(FeetPerSecond)]); 2114 + run_lex( 2115 + "35 ft per seconds", 2116 + vec![numtok!(35), Token::Unit(FeetPerSecond)], 2117 + ); 2118 + run_lex( 2119 + "35 foot / secs", 2120 + vec![numtok!(35), Token::Unit(FeetPerSecond)], 2121 + ); 2122 + run_lex( 2123 + "35 foot per seconds", 2124 + vec![numtok!(35), Token::Unit(FeetPerSecond)], 2125 + ); 2126 + run_lex( 2127 + "35 feet / sec", 2128 + vec![numtok!(35), Token::Unit(FeetPerSecond)], 2129 + ); 2130 + run_lex( 2131 + "35 feet per second", 2132 + vec![numtok!(35), Token::Unit(FeetPerSecond)], 2133 + ); 1309 2134 run_lex("30 pa", vec![numtok!(30), Token::Unit(Pascal)]); 1310 - run_lex("23 celsius + 4 celsius", vec![numtok!(23), Token::Unit(Celsius), Token::Operator(Plus), numtok!(4), Token::Unit(Celsius)]); 1311 - run_lex("54 f - 1.5 fahrenheit", vec![numtok!(54), Token::Unit(Fahrenheit), Token::Operator(Minus), numtok!(1.5), Token::Unit(Fahrenheit)]); 1312 - run_lex("50 metric tonnes", vec![numtok!(50), Token::Unit(MetricTon)]); 1313 - run_lex("77 metric hps", vec![numtok!(77), Token::Unit(MetricHorsepower)]); 2135 + run_lex( 2136 + "23 celsius + 4 celsius", 2137 + vec![ 2138 + numtok!(23), 2139 + Token::Unit(Celsius), 2140 + Token::Operator(Plus), 2141 + numtok!(4), 2142 + Token::Unit(Celsius), 2143 + ], 2144 + ); 2145 + run_lex( 2146 + "54 f - 1.5 fahrenheit", 2147 + vec![ 2148 + numtok!(54), 2149 + Token::Unit(Fahrenheit), 2150 + Token::Operator(Minus), 2151 + numtok!(1.5), 2152 + Token::Unit(Fahrenheit), 2153 + ], 2154 + ); 2155 + run_lex( 2156 + "50 metric tonnes", 2157 + vec![numtok!(50), Token::Unit(MetricTon)], 2158 + ); 2159 + run_lex( 2160 + "77 metric hps", 2161 + vec![numtok!(77), Token::Unit(MetricHorsepower)], 2162 + ); 1314 2163 1315 - run_lex("100 + 99", vec![numtok!(100), Token::Operator(Plus), numtok!(99)]); 1316 - run_lex("100 plus 99", vec![numtok!(100), Token::Operator(Plus), numtok!(99)]); 1317 - run_lex("12 - 4", vec![numtok!(12), Token::Operator(Minus), numtok!(4)]); 1318 - run_lex("12 minus 4", vec![numtok!(12), Token::Operator(Minus), numtok!(4)]); 1319 - run_lex("50.5 * 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]); 1320 - run_lex("50.5 times 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]); 1321 - run_lex("50.5 multiplied by 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]); 1322 - run_lex("6 / 3", vec![numtok!(6), Token::Operator(Divide), numtok!(3)]); 1323 - run_lex("50 / 10", vec![numtok!(50), Token::Operator(Divide), numtok!(10)]); 1324 - run_lex("52 ÷ 12", vec![numtok!(52), Token::Operator(Divide), numtok!(12)]); 1325 - run_lex("6 divided by 3", vec![numtok!(6), Token::Operator(Divide), numtok!(3)]); 1326 - run_lex("7 mod 5", vec![numtok!(7), Token::Operator(Modulo), numtok!(5)]); 2164 + run_lex( 2165 + "100 + 99", 2166 + vec![numtok!(100), Token::Operator(Plus), numtok!(99)], 2167 + ); 2168 + run_lex( 2169 + "100 plus 99", 2170 + vec![numtok!(100), Token::Operator(Plus), numtok!(99)], 2171 + ); 2172 + run_lex( 2173 + "12 - 4", 2174 + vec![numtok!(12), Token::Operator(Minus), numtok!(4)], 2175 + ); 2176 + run_lex( 2177 + "12 minus 4", 2178 + vec![numtok!(12), Token::Operator(Minus), numtok!(4)], 2179 + ); 2180 + run_lex( 2181 + "50.5 * 2", 2182 + vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)], 2183 + ); 2184 + run_lex( 2185 + "50.5 times 2", 2186 + vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)], 2187 + ); 2188 + run_lex( 2189 + "50.5 multiplied by 2", 2190 + vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)], 2191 + ); 2192 + run_lex( 2193 + "6 / 3", 2194 + vec![numtok!(6), Token::Operator(Divide), numtok!(3)], 2195 + ); 2196 + run_lex( 2197 + "50 / 10", 2198 + vec![numtok!(50), Token::Operator(Divide), numtok!(10)], 2199 + ); 2200 + run_lex( 2201 + "52 ÷ 12", 2202 + vec![numtok!(52), Token::Operator(Divide), numtok!(12)], 2203 + ); 2204 + run_lex( 2205 + "6 divided by 3", 2206 + vec![numtok!(6), Token::Operator(Divide), numtok!(3)], 2207 + ); 2208 + run_lex( 2209 + "7 mod 5", 2210 + vec![numtok!(7), Token::Operator(Modulo), numtok!(5)], 2211 + ); 1327 2212 1328 - run_lex("(2 + 3) * 4", vec![Token::Operator(LeftParen), numtok!(2), Token::Operator(Plus), numtok!(3), Token::Operator(RightParen), Token::Operator(Multiply), numtok!(4)]); 1329 - run_lex("52 weeks * (12 hrs + 12 hours)", vec![numtok!(52), Token::Unit(Week), Token::Operator(Multiply), Token::Operator(LeftParen), numtok!(12), Token::Unit(Hour), Token::Operator(Plus), numtok!(12), Token::Unit(Hour), Token::Operator(RightParen)]); 1330 - run_lex("12 pound+", vec![numtok!(12), Token::Unit(Pound), Token::Operator(Plus)]); 2213 + run_lex( 2214 + "(2 + 3) * 4", 2215 + vec![ 2216 + Token::Operator(LeftParen), 2217 + numtok!(2), 2218 + Token::Operator(Plus), 2219 + numtok!(3), 2220 + Token::Operator(RightParen), 2221 + Token::Operator(Multiply), 2222 + numtok!(4), 2223 + ], 2224 + ); 2225 + run_lex( 2226 + "52 weeks * (12 hrs + 12 hours)", 2227 + vec![ 2228 + numtok!(52), 2229 + Token::Unit(Week), 2230 + Token::Operator(Multiply), 2231 + Token::Operator(LeftParen), 2232 + numtok!(12), 2233 + Token::Unit(Hour), 2234 + Token::Operator(Plus), 2235 + numtok!(12), 2236 + Token::Unit(Hour), 2237 + Token::Operator(RightParen), 2238 + ], 2239 + ); 2240 + run_lex( 2241 + "12 pound+", 2242 + vec![numtok!(12), Token::Unit(Pound), Token::Operator(Plus)], 2243 + ); 1331 2244 1332 - run_lex("5 π m", vec![numtok!(5), Token::Constant(Pi), Token::Unit(Meter)]); 1333 - run_lex("5 Ω + 2 mΩ", vec![numtok!(5), Token::Unit(Ohm), Token::Operator(Plus), numtok!(2), Token::Unit(Milliohm)]); 2245 + run_lex( 2246 + "5 π m", 2247 + vec![numtok!(5), Token::Constant(Pi), Token::Unit(Meter)], 2248 + ); 2249 + run_lex( 2250 + "5 Ω + 2 mΩ", 2251 + vec![ 2252 + numtok!(5), 2253 + Token::Unit(Ohm), 2254 + Token::Operator(Plus), 2255 + numtok!(2), 2256 + Token::Unit(Milliohm), 2257 + ], 2258 + ); 1334 2259 } 1335 2260 }
+83 -16
src/lib.rs
··· 22 22 //! } 23 23 //! ``` 24 24 25 - use crate::units::Unit; 26 - use fastnum::{dec128 as d, D128}; 25 + use crate::units::{Unit, UnitType, primitive_unit}; 26 + use fastnum::{D128, dec128 as d}; 27 27 use std::fmt::{self, Display}; 28 28 use web_time::Instant; 29 29 ··· 55 55 /// }; 56 56 /// ``` 57 57 pub struct Number { 58 - /// The number part of a [`Number`] struct 58 + /// The value of the number 59 59 pub value: D128, 60 - /// The unit of a [`Number`] struct. This can be [`NoType`](units::UnitType::NoType) 61 - pub unit: Unit, 60 + /// The unit and exponent 61 + pub unit: Vec<(Unit, isize)>, 62 62 } 63 63 64 64 impl Number { 65 - pub const fn new(value: D128, unit: Unit) -> Number { 65 + pub fn new_unitless(value: D128) -> Number { 66 + Number { 67 + value, 68 + unit: vec![], 69 + } 70 + } 71 + pub fn with_basic_unit(value: D128, unit: Unit) -> Number { 72 + Number { 73 + value, 74 + unit: vec![(unit, 1)], 75 + } 76 + } 77 + pub fn with_unit(value: D128, unit: Vec<(Unit, isize)>) -> Number { 66 78 Number { value, unit } 67 79 } 80 + pub fn has_unit(&self) -> bool { 81 + !self.unit.is_empty() 82 + } 83 + pub fn is_unitless(&self) -> bool { 84 + self.unit.is_empty() 85 + } 68 86 pub fn get_simplified_value(&self) -> D128 { 69 87 self.value.reduce() 70 88 } 89 + pub fn primitive_unit(&self) -> Vec<(Unit, isize)> { 90 + primitive_unit(&self.unit) 91 + } 92 + pub fn contains_primitive(&self, unit: UnitType) -> bool { 93 + self.unit.iter().any(|(u, _)| u.category() == unit) 94 + } 95 + pub fn singular(&self) -> String { 96 + let mut s = String::new(); 97 + for (i, unit) in self.unit.iter().enumerate() { 98 + if i != 0 { 99 + match unit.1.is_positive() { 100 + true => s.push_str(" * "), 101 + false => s.push_str(" / "), 102 + } 103 + } 104 + s.push_str(unit.0.plural()); 105 + } 106 + s 107 + } 108 + pub fn plural(&self) -> String { 109 + let mut s = String::new(); 110 + for (i, unit) in self.unit.iter().enumerate() { 111 + if i != 0 { 112 + match unit.1.is_positive() { 113 + true => s.push_str(" * "), 114 + false => s.push_str(" / "), 115 + } 116 + } 117 + s.push_str(unit.0.plural()); 118 + } 119 + s 120 + } 71 121 } 72 122 impl Display for Number { 73 123 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 74 124 let value = self.get_simplified_value(); 75 125 let word = match self.value == d!(1) { 76 - true => self.unit.singular(), 77 - false => self.unit.plural(), 126 + true => self.singular(), 127 + false => self.plural(), 78 128 }; 79 - let output = match word { 129 + let output = match word.as_str() { 80 130 "" => format!("{value}"), 81 131 _ => format!("{value} {word}"), 82 132 }; ··· 187 237 Revolution, 188 238 } 189 239 190 - #[derive(Clone, Debug, PartialEq)] 240 + #[derive(Clone, PartialEq)] 191 241 /// A token like a [`Number`](Token::Number), [`Operator`](Token::Operator), [`Unit`](Token::Unit) etc. 192 242 /// 193 243 /// Strings can be divided up into these tokens by the [`lexer`], and then put into the [`parser`]. ··· 209 259 Negative, 210 260 Unit(units::Unit), 211 261 } 262 + impl fmt::Debug for Token { 263 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 264 + match self { 265 + Token::Operator(op) => write!(f, "Operator({:?})", op), 266 + Token::UnaryOperator(op) => write!(f, "UnaryOperator({:?})", op), 267 + Token::Number(num) => write!(f, "Number({num})"), 268 + Token::FunctionIdentifier(id) => write!(f, "FunctionIdentifier({:?})", id), 269 + Token::Constant(c) => write!(f, "Constant({:?})", c), 270 + Token::Paren => write!(f, "Paren"), 271 + Token::Per => write!(f, "Per"), 272 + Token::LexerKeyword(op) => write!(f, "LexerKeyword({:?})", op), 273 + Token::TextOperator(op) => write!(f, "TextOperator({:?})", op), 274 + Token::NamedNumber(num) => write!(f, "NamedNumber({:?})", num), 275 + Token::Negative => write!(f, "Negative"), 276 + Token::Unit(u) => write!(f, "Unit({:?})", u), 277 + } 278 + } 279 + } 212 280 213 281 #[macro_export] 214 282 macro_rules! numtok { ··· 234 302 /// } 235 303 /// } 236 304 /// ``` 237 - pub fn eval( 238 - input: &str, 239 - allow_trailing_operators: bool, 240 - verbose: bool, 241 - ) -> Result<Number, String> { 305 + pub fn eval(input: &str, allow_trailing_operators: bool, verbose: bool) -> Result<Number, String> { 242 306 let lex_start = Instant::now(); 243 307 244 308 match lexer::lex(input, allow_trailing_operators) { ··· 318 382 assert_eq!(default_eval("-2(-3)"), Number::new(d!(6), Unit::NoUnit)); 319 383 assert_eq!(default_eval("-2(3)"), Number::new(d!(-6), Unit::NoUnit)); 320 384 assert_eq!(default_eval("(3)-2"), Number::new(d!(1), Unit::NoUnit)); 321 - assert_eq!(default_eval("-1km to m"), Number::new(d!(-1000), Unit::Meter)); 385 + assert_eq!( 386 + default_eval("-1km to m"), 387 + Number::new(d!(-1000), Unit::Meter) 388 + ); 322 389 assert_eq!(default_eval("2*-3*0.5"), Number::new(d!(-3), Unit::NoUnit)); 323 390 assert_eq!(default_eval("-3^2"), Number::new(d!(-9), Unit::NoUnit)); 324 391 assert_eq!(default_eval("-1+2"), Number::new(d!(1), Unit::NoUnit));
+717 -454
src/units.rs
··· 1 - use fastnum::{dec128 as d, D128}; 2 1 use crate::Number; 2 + use fastnum::{D128, dec128 as d}; 3 3 4 4 #[derive(Clone, Copy, PartialEq, Debug)] 5 5 /// An enum of all possible unit types, like [`Length`], [`DigitalStorage`] etc. 6 - /// There is also a [`NoType`] unit type for normal numbers. 7 6 pub enum UnitType { 8 - /// A normal number, for example `5` 9 - NoType, 10 7 /// A unit of time, for example [`Hour`] 11 8 Time, 12 9 /// A unit of length, for example [`Mile`] ··· 44 41 /// A unit of temperature, for example [`Kelvin`] 45 42 Temperature, 46 43 } 44 + impl UnitType { 45 + fn primitive(&self) -> Vec<(Unit, isize)> { 46 + match self { 47 + // Time => vec![(Time, 1)], 48 + // Length => vec![(Length, 1)], 49 + // Area => vec![(Length, 2)], 50 + // Volume => vec![(Length, 3)], 51 + // Mass => vec![(Mass, 1)], 52 + // DigitalStorage => vec![(DigitalStorage, 1)], 53 + // DataTransferRate => vec![(DigitalStorage, 1), (Time, -1)], 54 + // FlopCount => vec![(FlopCount, 1)], 55 + // FlopRate => vec![(FlopCount, 1), (Time, -1)], 56 + // Energy => vec![(Mass, 1), (Length, 2), (Time, -2)], 57 + // Power => vec![(Mass, 1), (Length, 2), (Time, -3)], 58 + // ElectricCurrent => vec![(ElectricCurrent, 1)], 59 + // Resistance => vec![(Mass, 1), (Length, 2), (Time, -3), (ElectricCurrent, -2)], 60 + // Voltage => vec![(Mass, 1), (Length, 2), (Time, -3), (ElectricCurrent, -1)], 61 + // Pressure => vec![(Mass, 1), (Length, -1), (Time, -2)], 62 + // Frequency => vec![(Time, -1)], 63 + // Speed => vec![(Length, 1), (Time, -1)], 64 + // Temperature => vec![(Temperature, 1)], 65 + Time => vec![(Nanosecond, 1)], 66 + Length => vec![(Millimeter, 1)], 67 + Area => vec![(SquareMillimeter, 2)], 68 + Volume => vec![(CubicMillimeter, 3)], 69 + Mass => vec![(Gram, 1)], 70 + DigitalStorage => vec![(Bit, 1)], 71 + DataTransferRate => vec![(Bit, 1), (Nanosecond, -1)], 72 + FlopCount => vec![(Flop, 1)], 73 + FlopRate => vec![(Flop, 1), (Nanosecond, -1)], 74 + Energy => vec![(Gram, 1), (SquareMillimeter, 2), (Nanosecond, -2)], 75 + Power => vec![(Gram, 1), (SquareMillimeter, 2), (Nanosecond, -3)], 76 + ElectricCurrent => vec![(Ampere, 1)], 77 + Resistance => vec![ 78 + (Gram, 1), 79 + (SquareMillimeter, 2), 80 + (Nanosecond, -3), 81 + (Ampere, -2), 82 + ], 83 + Voltage => vec![ 84 + (Gram, 1), 85 + (SquareMillimeter, 2), 86 + (Nanosecond, -3), 87 + (Ampere, -1), 88 + ], 89 + Pressure => vec![(Gram, 1), (Millimeter, -1), (Nanosecond, -2)], 90 + Frequency => vec![(Nanosecond, -1)], 91 + Speed => vec![(Millimeter, 1), (Nanosecond, -1)], 92 + Temperature => vec![(Kelvin, 1)], 93 + } 94 + } 95 + } 47 96 use UnitType::*; 97 + 98 + pub fn primitive_unit(unit: &Vec<(Unit, isize)>) -> Vec<(Unit, isize)> { 99 + let mut primitives: Vec<(Unit, isize)> = Vec::new(); 100 + for (unit, exponent) in unit { 101 + for (primitive, primitive_exponent) in unit.category().primitive() { 102 + let existing = primitives.iter_mut().find(|(u, _)| u == &primitive); 103 + match existing { 104 + Some(existing) => existing.1 += primitive_exponent * exponent, 105 + None => primitives.push((primitive, primitive_exponent * exponent)), 106 + } 107 + } 108 + } 109 + primitives.retain(|(_, exponent)| exponent != &0); 110 + primitives 111 + } 48 112 49 113 // Macro for creating units. Not possible to extend/change the default units 50 114 // with this because the default units are imported into the lexer, parser ··· 92 156 } 93 157 94 158 create_units!( 95 - NoUnit: (NoType, d!(1), "", ""), 96 - 97 159 Nanosecond: (Time, d!(1), "nanosecond", "nanoseconds"), 98 160 Microsecond: (Time, d!(1000), "microsecond", "microseconds"), 99 161 Millisecond: (Time, d!(1000000), "millisecond", "milliseconds"), ··· 342 404 ); 343 405 344 406 /// Returns the conversion factor between two units. 345 - /// 407 + /// 346 408 /// The conversion factor is what you need to multiply `unit` with to get 347 409 /// `to_unit`. For example, the conversion factor from 1 minute to 1 second 348 410 /// is 60. 349 - /// 411 + /// 350 412 /// This is not sufficient for [`Temperature`] units. 351 413 pub fn get_conversion_factor(unit: Unit, to_unit: Unit) -> D128 { 352 414 unit.weight() / to_unit.weight() 415 + } 416 + 417 + fn combined_weight(unit: &[(Unit, isize)]) -> D128 { 418 + unit.iter().fold(D128::from(1), |acc, (u, exp)| { 419 + acc * integer_power(u.weight(), *exp) 420 + }) 421 + } 422 + 423 + fn integer_power(base: D128, exp: isize) -> D128 { 424 + let positive = (0..exp.unsigned_abs()).fold(D128::from(1), |acc, _| acc * base); 425 + if exp >= 0 { 426 + positive 427 + } else { 428 + D128::from(1) / positive 429 + } 353 430 } 354 431 355 432 /// Convert a [`Number`] to a specified [`Unit`]. 356 - pub fn convert(number: Number, to_unit: Unit) -> Result<Number, String> { 357 - if number.unit.category() != to_unit.category() { 358 - return Err(format!("Cannot convert from {:?} to {:?}", number.unit, to_unit)); 433 + pub fn convert(number: Number, to_unit: Vec<(Unit, isize)>) -> Result<Number, String> { 434 + if number.primitive_unit() != primitive_unit(&to_unit) { 435 + return Err(format!( 436 + "Cannot convert from {:?} to {:?}", 437 + number.unit, to_unit 438 + )); 359 439 } 360 440 let value = number.value; 361 - let ok = |new_value| { 362 - Ok(Number::new(new_value, to_unit)) 363 - }; 364 - if number.unit.category() == UnitType::Temperature { 365 - match (number.unit, to_unit) { 366 - (Kelvin, Kelvin) => ok(value), 367 - (Kelvin, Celsius) => ok(value-d!(273.15)), 368 - (Kelvin, Fahrenheit) => ok(value*d!(1.8)-d!(459.67)), 369 - (Celsius, Celsius) => ok(value), 370 - (Celsius, Kelvin) => ok(value+d!(273.15)), 371 - (Celsius, Fahrenheit) => ok(value*d!(1.8)+d!(32)), 372 - (Fahrenheit, Fahrenheit) => ok(value), 373 - (Fahrenheit, Kelvin) => ok((value+d!(459.67))*d!(5)/d!(9)), 374 - (Fahrenheit, Celsius) => ok((value-d!(32))/d!(1.8)), 375 - _ => Err(format!("Error converting temperature {:?} to {:?}", number.unit, to_unit)), 376 - } 441 + // let ok = |new_value| Ok(Number::with_unit(new_value, to_unit)); 442 + let primitive_u = number.primitive_unit(); 443 + if number.primitive_unit() == vec![(Kelvin, 1)] { 444 + todo!(); 445 + // match (number.unit.0, to_unit) { 446 + // (Kelvin, Kelvin) => ok(value), 447 + // (Kelvin, Celsius) => ok(value - d!(273.15)), 448 + // (Kelvin, Fahrenheit) => ok(value * d!(1.8) - d!(459.67)), 449 + // (Celsius, Celsius) => ok(value), 450 + // (Celsius, Kelvin) => ok(value + d!(273.15)), 451 + // (Celsius, Fahrenheit) => ok(value * d!(1.8) + d!(32)), 452 + // (Fahrenheit, Fahrenheit) => ok(value), 453 + // (Fahrenheit, Kelvin) => ok((value + d!(459.67)) * d!(5) / d!(9)), 454 + // (Fahrenheit, Celsius) => ok((value - d!(32)) / d!(1.8)), 455 + // _ => Err(format!( 456 + // "Error converting temperature {:?} to {:?}", 457 + // number.unit, to_unit 458 + // )), 459 + // } 377 460 } else { 378 - let conversion_factor = get_conversion_factor(number.unit, to_unit); 379 - ok(number.value * conversion_factor) 461 + // let conversion_factor = get_conversion_factor(number.unit, to_unit); 462 + 463 + let source_weight = combined_weight(&number.unit); 464 + let target_weight = combined_weight(&to_unit); 465 + 466 + Ok(Number { 467 + value: number.value * source_weight / target_weight, 468 + unit: to_unit.to_vec(), 469 + }) 380 470 } 381 471 } 382 472 383 473 /// If one of two provided [`Number`]s has a larger [`Unit`] than the other, convert 384 474 /// the large one to the unit of the small one. 385 475 pub fn convert_to_lowest(left: Number, right: Number) -> Result<(Number, Number), String> { 386 - if left.unit.weight() == right.unit.weight() { 387 - Ok((left, right)) 388 - } else if left.unit.weight() > right.unit.weight() { 389 - let left_converted = convert(left, right.unit)?; 390 - Ok((left_converted, right)) 391 - } else { 392 - let right_converted = convert(right, left.unit)?; 393 - Ok((left, right_converted)) 394 - } 476 + todo!(); 477 + // if left.unit.weight() == right.unit.weight() { 478 + // Ok((left, right)) 479 + // } else if left.unit.weight() > right.unit.weight() { 480 + // let left_converted = convert(left, right.unit)?; 481 + // Ok((left_converted, right)) 482 + // } else { 483 + // let right_converted = convert(right, left.unit)?; 484 + // Ok((left, right_converted)) 485 + // } 395 486 } 396 487 397 488 /// Return the sum of two [`Number`]s 398 489 pub fn add(left: Number, right: Number) -> Result<Number, String> { 399 490 if left.unit == right.unit { 400 - Ok(Number::new(left.value + right.value, left.unit)) 401 - } else if left.unit.category() == right.unit.category() && left.unit.category() != Temperature { 491 + Ok(Number::with_unit(left.value + right.value, left.unit)) 492 + } else if left.primitive_unit() == right.primitive_unit() 493 + && !left.contains_primitive(Temperature) 494 + { 402 495 let (left, right) = convert_to_lowest(left, right)?; 403 - Ok(Number::new(left.value + right.value, left.unit)) 496 + Ok(Number::with_unit(left.value + right.value, left.unit)) 404 497 } else { 405 498 Err(format!("Cannot add {:?} and {:?}", left.unit, right.unit)) 406 499 } ··· 409 502 /// Subtract a [`Number`] from another [`Number`] 410 503 pub fn subtract(left: Number, right: Number) -> Result<Number, String> { 411 504 if left.unit == right.unit { 412 - Ok(Number::new(left.value - right.value, left.unit)) 413 - } else if left.unit.category() == right.unit.category() && left.unit.category() != Temperature { 505 + Ok(Number::with_unit(left.value - right.value, left.unit)) 506 + } else if left.primitive_unit() == right.primitive_unit() 507 + && !left.contains_primitive(Temperature) 508 + { 414 509 let (left, right) = convert_to_lowest(left, right)?; 415 - Ok(Number::new(left.value - right.value, left.unit)) 510 + Ok(Number::with_unit(left.value - right.value, left.unit)) 416 511 } else { 417 - Err(format!("Cannot subtract {:?} by {:?}", left.unit, right.unit)) 512 + Err(format!( 513 + "Cannot subtract {:?} by {:?}", 514 + left.unit, right.unit 515 + )) 418 516 } 419 517 } 420 518 421 519 /// Convert a [`Number`] to an ideal unit. 422 - /// 520 + /// 423 521 /// If you have 1,000,000 millimeters, this will return 1 kilometer. 424 - /// 522 + /// 425 523 /// This only affects units of `Length`, `Time`, `Area`, `Volume`, 426 524 /// `Energy`, `Power`, `ElectricCurrent`, `Resistance`, and `Voltage`. 427 525 /// Other units are passed through. 428 526 pub fn to_ideal_unit(number: Number) -> Number { 429 - let value = number.value * number.unit.weight(); 430 - if number.unit.category() == Length { 431 - if value >= d!(1000000000000000000) { // ≈ 0.1 light years 432 - return Number::new(value/LightYear.weight(), LightYear) 433 - } else if value >= d!(1000000) { // 1 km 434 - return Number::new(value/Kilometer.weight(), Kilometer) 435 - } else if value >= d!(1000) { // 1 m 436 - return Number::new(value/Meter.weight(), Meter) 437 - } else if value >= d!(10) { // 1 cm 438 - return Number::new(value/Centimeter.weight(), Centimeter) 439 - } else { 440 - return Number::new(value, Millimeter) 441 - } 442 - } else if number.unit.category() == Time { 443 - if value >= d!(31556952000000000) { 444 - return Number::new(value/Year.weight(), Year); 445 - } else if value >= d!(86400000000000) { 446 - return Number::new(value/Day.weight(), Day); 447 - } else if value >= d!(3600000000000) { 448 - return Number::new(value/Hour.weight(), Hour); 449 - } else if value >= d!(60000000000) { 450 - return Number::new(value/Minute.weight(), Minute); 451 - } else if value >= d!(1000000000) { 452 - return Number::new(value/Second.weight(), Second); 453 - } else if value >= d!(1000000) { 454 - return Number::new(value/Millisecond.weight(), Millisecond); 455 - } else if value >= d!(1000) { 456 - return Number::new(value/Microsecond.weight(), Microsecond); 457 - } else { 458 - return Number::new(value, Nanosecond); 459 - } 460 - } else if number.unit.category() == Area { 461 - if value >= d!(1000000000000) { // 1 km2 462 - return Number::new(value/SquareKilometer.weight(), SquareKilometer) 463 - } else if value >= d!(10000000000) { // 1 hectare 464 - return Number::new(value/Hectare.weight(), Hectare) 465 - } else if value >= d!(1000000) { // 1 m2 466 - return Number::new(value/SquareMeter.weight(), SquareMeter) 467 - } else if value >= d!(100) { // 1 cm2 468 - return Number::new(value/SquareCentimeter.weight(), SquareCentimeter) 469 - } else { 470 - return Number::new(value, SquareMillimeter) 471 - } 472 - } else if number.unit.category() == Volume { 473 - if value >= d!(1000000000000000000) { // 1 km3 474 - return Number::new(value/CubicKilometer.weight(), CubicKilometer) 475 - } else if value >= d!(1000000000) { // 1 m3 476 - return Number::new(value/CubicMeter.weight(), CubicMeter) 477 - } else if value >= d!(1000000) { // 1 l 478 - return Number::new(value/Liter.weight(), Liter) 479 - } else if value >= d!(1000) { // 1 ml 480 - return Number::new(value/Milliliter.weight(), Milliliter) 481 - } else { 482 - return Number::new(value, CubicMillimeter) 483 - } 484 - } else if number.unit.category() == Energy { 485 - if value >= d!(3600000000000000000) { // 1 petawatthour 486 - return Number::new(value/PetawattHour.weight(), PetawattHour) 487 - } else if value >= d!(3600000000000000) { // 1 terawatthour 488 - return Number::new(value/TerawattHour.weight(), TerawattHour) 489 - } else if value >= d!(3600000000000) { // 1 gigawatthour 490 - return Number::new(value/GigawattHour.weight(), GigawattHour) 491 - } else if value >= d!(3600000000) { // 1 megawatthour 492 - return Number::new(value/MegawattHour.weight(), MegawattHour) 493 - } else if value >= d!(3600000) { // 1 kilowatthour 494 - return Number::new(value/KilowattHour.weight(), KilowattHour) 495 - } else if value >= d!(3600) { // 1 watthour 496 - return Number::new(value/WattHour.weight(), WattHour) 497 - } else if value >= d!(1) { // 1 joule 498 - return Number::new(value, Joule) 499 - } else { 500 - return Number::new(value/Millijoule.weight(), Millijoule) 501 - } 502 - } else if number.unit.category() == Power { 503 - if value >= d!(1000000000000000) { // 1 petawatt 504 - return Number::new(value/Petawatt.weight(), Petawatt) 505 - } else if value >= d!(1000000000000) { // 1 terawatt 506 - return Number::new(value/Terawatt.weight(), Terawatt) 507 - } else if value >= d!(1000000000) { // 1 gigawatt 508 - return Number::new(value/Gigawatt.weight(), Gigawatt) 509 - } else if value >= d!(1000000) { // megawatt 510 - return Number::new(value/Megawatt.weight(), Megawatt) 511 - } else if value >= d!(1000) { // 1 kilowatt 512 - return Number::new(value/Kilowatt.weight(), Kilowatt) 513 - } else if value >= d!(1) { // 1 watt 514 - return Number::new(value, Watt) 515 - } else { 516 - return Number::new(value/Milliwatt.weight(), Milliwatt) 517 - } 518 - } else if number.unit.category() == ElectricCurrent { 519 - if value >= d!(1000) { // 1 kiloampere 520 - return Number::new(value/Kiloampere.weight(), Kiloampere) 521 - } else if value >= d!(1) { // 1 ampere 522 - return Number::new(value, Ampere) 523 - } else { 524 - return Number::new(value/Milliampere.weight(), Milliampere) 525 - } 526 - } else if number.unit.category() == Resistance { 527 - if value >= d!(1000) { // 1 kiloohm 528 - return Number::new(value/Kiloohm.weight(), Kiloohm) 529 - } else if value >= d!(1) { // 1 ohm 530 - return Number::new(value, Ohm) 531 - } else { 532 - return Number::new(value/Milliohm.weight(), Milliohm) 533 - } 534 - } else if number.unit.category() == Voltage { 535 - if value >= d!(1000) { // 1 kilovolt 536 - return Number::new(value/Kilovolt.weight(), Kilovolt) 537 - } else if value >= d!(1) { // 1 volt 538 - return Number::new(value, Volt) 539 - } else { 540 - return Number::new(value/Millivolt.weight(), Millivolt) 541 - } 542 - } 543 - number 527 + todo!(); 528 + // let value = number.value * number.unit.weight(); 529 + // if number.unit.category() == Length { 530 + // if value >= d!(1000000000000000000) { 531 + // // ≈ 0.1 light years 532 + // return Number::new(value / LightYear.weight(), LightYear); 533 + // } else if value >= d!(1000000) { 534 + // // 1 km 535 + // return Number::new(value / Kilometer.weight(), Kilometer); 536 + // } else if value >= d!(1000) { 537 + // // 1 m 538 + // return Number::new(value / Meter.weight(), Meter); 539 + // } else if value >= d!(10) { 540 + // // 1 cm 541 + // return Number::new(value / Centimeter.weight(), Centimeter); 542 + // } else { 543 + // return Number::new(value, Millimeter); 544 + // } 545 + // } else if number.unit.category() == Time { 546 + // if value >= d!(31556952000000000) { 547 + // return Number::new(value / Year.weight(), Year); 548 + // } else if value >= d!(86400000000000) { 549 + // return Number::new(value / Day.weight(), Day); 550 + // } else if value >= d!(3600000000000) { 551 + // return Number::new(value / Hour.weight(), Hour); 552 + // } else if value >= d!(60000000000) { 553 + // return Number::new(value / Minute.weight(), Minute); 554 + // } else if value >= d!(1000000000) { 555 + // return Number::new(value / Second.weight(), Second); 556 + // } else if value >= d!(1000000) { 557 + // return Number::new(value / Millisecond.weight(), Millisecond); 558 + // } else if value >= d!(1000) { 559 + // return Number::new(value / Microsecond.weight(), Microsecond); 560 + // } else { 561 + // return Number::new(value, Nanosecond); 562 + // } 563 + // } else if number.unit.category() == Area { 564 + // if value >= d!(1000000000000) { 565 + // // 1 km2 566 + // return Number::new(value / SquareKilometer.weight(), SquareKilometer); 567 + // } else if value >= d!(10000000000) { 568 + // // 1 hectare 569 + // return Number::new(value / Hectare.weight(), Hectare); 570 + // } else if value >= d!(1000000) { 571 + // // 1 m2 572 + // return Number::new(value / SquareMeter.weight(), SquareMeter); 573 + // } else if value >= d!(100) { 574 + // // 1 cm2 575 + // return Number::new(value / SquareCentimeter.weight(), SquareCentimeter); 576 + // } else { 577 + // return Number::new(value, SquareMillimeter); 578 + // } 579 + // } else if number.unit.category() == Volume { 580 + // if value >= d!(1000000000000000000) { 581 + // // 1 km3 582 + // return Number::new(value / CubicKilometer.weight(), CubicKilometer); 583 + // } else if value >= d!(1000000000) { 584 + // // 1 m3 585 + // return Number::new(value / CubicMeter.weight(), CubicMeter); 586 + // } else if value >= d!(1000000) { 587 + // // 1 l 588 + // return Number::new(value / Liter.weight(), Liter); 589 + // } else if value >= d!(1000) { 590 + // // 1 ml 591 + // return Number::new(value / Milliliter.weight(), Milliliter); 592 + // } else { 593 + // return Number::new(value, CubicMillimeter); 594 + // } 595 + // } else if number.unit.category() == Energy { 596 + // if value >= d!(3600000000000000000) { 597 + // // 1 petawatthour 598 + // return Number::new(value / PetawattHour.weight(), PetawattHour); 599 + // } else if value >= d!(3600000000000000) { 600 + // // 1 terawatthour 601 + // return Number::new(value / TerawattHour.weight(), TerawattHour); 602 + // } else if value >= d!(3600000000000) { 603 + // // 1 gigawatthour 604 + // return Number::new(value / GigawattHour.weight(), GigawattHour); 605 + // } else if value >= d!(3600000000) { 606 + // // 1 megawatthour 607 + // return Number::new(value / MegawattHour.weight(), MegawattHour); 608 + // } else if value >= d!(3600000) { 609 + // // 1 kilowatthour 610 + // return Number::new(value / KilowattHour.weight(), KilowattHour); 611 + // } else if value >= d!(3600) { 612 + // // 1 watthour 613 + // return Number::new(value / WattHour.weight(), WattHour); 614 + // } else if value >= d!(1) { 615 + // // 1 joule 616 + // return Number::new(value, Joule); 617 + // } else { 618 + // return Number::new(value / Millijoule.weight(), Millijoule); 619 + // } 620 + // } else if number.unit.category() == Power { 621 + // if value >= d!(1000000000000000) { 622 + // // 1 petawatt 623 + // return Number::new(value / Petawatt.weight(), Petawatt); 624 + // } else if value >= d!(1000000000000) { 625 + // // 1 terawatt 626 + // return Number::new(value / Terawatt.weight(), Terawatt); 627 + // } else if value >= d!(1000000000) { 628 + // // 1 gigawatt 629 + // return Number::new(value / Gigawatt.weight(), Gigawatt); 630 + // } else if value >= d!(1000000) { 631 + // // megawatt 632 + // return Number::new(value / Megawatt.weight(), Megawatt); 633 + // } else if value >= d!(1000) { 634 + // // 1 kilowatt 635 + // return Number::new(value / Kilowatt.weight(), Kilowatt); 636 + // } else if value >= d!(1) { 637 + // // 1 watt 638 + // return Number::new(value, Watt); 639 + // } else { 640 + // return Number::new(value / Milliwatt.weight(), Milliwatt); 641 + // } 642 + // } else if number.unit.category() == ElectricCurrent { 643 + // if value >= d!(1000) { 644 + // // 1 kiloampere 645 + // return Number::new(value / Kiloampere.weight(), Kiloampere); 646 + // } else if value >= d!(1) { 647 + // // 1 ampere 648 + // return Number::new(value, Ampere); 649 + // } else { 650 + // return Number::new(value / Milliampere.weight(), Milliampere); 651 + // } 652 + // } else if number.unit.category() == Resistance { 653 + // if value >= d!(1000) { 654 + // // 1 kiloohm 655 + // return Number::new(value / Kiloohm.weight(), Kiloohm); 656 + // } else if value >= d!(1) { 657 + // // 1 ohm 658 + // return Number::new(value, Ohm); 659 + // } else { 660 + // return Number::new(value / Milliohm.weight(), Milliohm); 661 + // } 662 + // } else if number.unit.category() == Voltage { 663 + // if value >= d!(1000) { 664 + // // 1 kilovolt 665 + // return Number::new(value / Kilovolt.weight(), Kilovolt); 666 + // } else if value >= d!(1) { 667 + // // 1 volt 668 + // return Number::new(value, Volt); 669 + // } else { 670 + // return Number::new(value / Millivolt.weight(), Millivolt); 671 + // } 672 + // } 673 + // number 544 674 } 545 675 546 676 /// Convert a [`Number`] to an ideal [`Joule`] unit, if the number is a unit of [`Energy`]. 547 677 pub fn to_ideal_joule_unit(number: Number) -> Number { 548 - let value = number.value * number.unit.weight(); 549 - if number.unit.category() == Energy { 550 - if value >= d!(1000000000000) { // 1 terajoule 551 - return Number::new(value/Terajoule.weight(), Terajoule) 552 - } else if value >= d!(1000000000) { // 1 gigajoule 553 - return Number::new(value/Gigajoule.weight(), Gigajoule) 554 - } else if value >= d!(1000000) { // 1 megajoule 555 - return Number::new(value/Megajoule.weight(), Megajoule) 556 - } else if value >= d!(1000) { // 1 kilojoule 557 - return Number::new(value/Kilojoule.weight(), Kilojoule) 558 - } else if value >= d!(1) { // 1 joule 559 - return Number::new(value/Joule.weight(), Joule) 560 - } else { 561 - return Number::new(value/Millijoule.weight(), Millijoule) 562 - } 563 - } 564 - number 678 + todo!(); 679 + // let value = number.value * number.unit.weight(); 680 + // if number.unit.category() == Energy { 681 + // if value >= d!(1000000000000) { // 1 terajoule 682 + // return Number::new(value/Terajoule.weight(), Terajoule) 683 + // } else if value >= d!(1000000000) { // 1 gigajoule 684 + // return Number::new(value/Gigajoule.weight(), Gigajoule) 685 + // } else if value >= d!(1000000) { // 1 megajoule 686 + // return Number::new(value/Megajoule.weight(), Megajoule) 687 + // } else if value >= d!(1000) { // 1 kilojoule 688 + // return Number::new(value/Kilojoule.weight(), Kilojoule) 689 + // } else if value >= d!(1) { // 1 joule 690 + // return Number::new(value/Joule.weight(), Joule) 691 + // } else { 692 + // return Number::new(value/Millijoule.weight(), Millijoule) 693 + // } 694 + // } 695 + // number 565 696 } 566 697 567 698 /// Multiply two [`Number`]s 568 - /// 699 + /// 569 700 /// - Temperatures don't work 570 - /// - If you multiply [`NoType`] with any other unit, the result gets that other unit 701 + /// - If you multiply a unit with a unitless number, the result gets that other unit 571 702 /// - If you multiply [`Length`] with [`Length`], the result has a unit of [`Area`], etc. 572 703 /// - If you multiply [`Speed`] with [`Time`], the result has a unit of [`Length`] 573 704 /// - If you multiply [`Voltage`] with [`ElectricCurrent`], the result has a unit of [`Power`] ··· 578 709 } 579 710 580 711 fn actual_multiply(left: Number, right: Number, swapped: bool) -> Result<Number, String> { 581 - let lcat = left.unit.category(); 582 - let rcat = right.unit.category(); 583 - if left.unit == NoUnit && right.unit == NoUnit { 584 - // 3 * 2 585 - Ok(Number::new(left.value * right.value, left.unit)) 586 - } else if left.unit.category() == Temperature || right.unit.category() == Temperature { 587 - // if temperature 588 - Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit)) 589 - } else if left.unit == NoUnit && right.unit != NoUnit { 590 - // 3 * 2 anyunit 591 - Ok(Number::new(left.value * right.value, right.unit)) 592 - } else if lcat == Length && rcat == Length { 593 - // length * length 594 - let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); 595 - Ok(to_ideal_unit(Number::new(result, SquareMillimeter))) 596 - } else if lcat == Length && rcat == Area { 597 - // length * area 598 - let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); 599 - Ok(to_ideal_unit(Number::new(result, CubicMillimeter))) 600 - } else if lcat == Speed && rcat == Time { 601 - // 1 km/h * 1h 602 - let kph_value = left.value * left.unit.weight(); 603 - let hours = convert(right, Hour)?; 604 - let result = kph_value * hours.value; 605 - let final_unit = match left.unit { 606 - KilometersPerHour => Kilometer, 607 - MetersPerSecond => Meter, 608 - MilesPerHour => Mile, 609 - FeetPerSecond => Foot, 610 - Knot => NauticalMile, 611 - _ => Meter, 612 - }; 613 - let kilometers = Number::new(result, Kilometer); 614 - Ok(convert(kilometers, final_unit)?) 615 - } else if lcat == DataTransferRate && rcat == Time { 616 - // 8 megabytes per second * 1 minute 617 - let data_rate_value = left.value * left.unit.weight(); 618 - let seconds = convert(right, Second)?; 619 - let result = data_rate_value * seconds.value; 620 - let final_unit = match left.unit { 621 - BitsPerSecond => Bit, 622 - KilobitsPerSecond => Kilobit, 623 - MegabitsPerSecond => Megabit, 624 - GigabitsPerSecond => Gigabit, 625 - TerabitsPerSecond => Terabit, 626 - PetabitsPerSecond => Petabit, 627 - ExabitsPerSecond => Exabit, 628 - ZettabitsPerSecond => Zettabit, 629 - YottabitsPerSecond => Yottabit, 630 - KibibitsPerSecond => Kibibit, 631 - MebibitsPerSecond => Mebibit, 632 - GibibitsPerSecond => Gibibit, 633 - TebibitsPerSecond => Tebibit, 634 - PebibitsPerSecond => Pebibit, 635 - ExbibitsPerSecond => Exbibit, 636 - ZebibitsPerSecond => Zebibit, 637 - YobibitsPerSecond => Yobibit, 638 - BytesPerSecond => Byte, 639 - KilobytesPerSecond => Kilobyte, 640 - MegabytesPerSecond => Megabyte, 641 - GigabytesPerSecond => Gigabyte, 642 - TerabytesPerSecond => Terabyte, 643 - PetabytesPerSecond => Petabyte, 644 - ExabytesPerSecond => Exabyte, 645 - ZettabytesPerSecond => Zettabyte, 646 - YottabytesPerSecond => Yottabyte, 647 - KibibytesPerSecond => Kibibyte, 648 - MebibytesPerSecond => Mebibyte, 649 - GibibytesPerSecond => Gibibyte, 650 - TebibytesPerSecond => Tebibyte, 651 - PebibytesPerSecond => Pebibyte, 652 - ExbibytesPerSecond => Exbibyte, 653 - ZebibytesPerSecond => Zebibyte, 654 - YobibytesPerSecond => Yobibyte, 655 - _ => Bit, 656 - }; 657 - let data_storage = Number::new(result, Bit); 658 - Ok(convert(data_storage, final_unit)?) 659 - } else if lcat == FlopRate && rcat == Time { 660 - // 8 megaFLOP per second * 1 minute 661 - let compute_perf_value = left.value * left.unit.weight(); 662 - let seconds = convert(right, Second)?; 663 - let result = compute_perf_value * seconds.value; 664 - let final_unit = match left.unit { 665 - FlopPerSecond => Flop, 666 - KiloFlopPerSecond => KiloFlop, 667 - MegaFlopPerSecond => MegaFlop, 668 - GigaFlopPerSecond => GigaFlop, 669 - TeraFlopPerSecond => TeraFlop, 670 - PetaFlopPerSecond => PetaFlop, 671 - ExaFlopPerSecond => ExaFlop, 672 - ZettaFlopPerSecond => ZettaFlop, 673 - YottaFlopPerSecond => YottaFlop, 674 - RonnaFlopPerSecond => RonnaFlop, 675 - QuettaFlopPerSecond => QuettaFlop, 676 - _ => Flop, 677 - }; 678 - let compute_work = Number::new(result, Flop); 679 - Ok(convert(compute_work, final_unit)?) 680 - } else if lcat == Voltage && rcat == ElectricCurrent { 681 - // 1 volt * 1 ampere = 1 watt 682 - let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); 683 - Ok(to_ideal_unit(Number::new(result, Watt))) 684 - } else if lcat == ElectricCurrent && rcat == Resistance { 685 - // 1 amp * 1 ohm = 1 volt 686 - let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); 687 - Ok(to_ideal_unit(Number::new(result, Watt))) 688 - } else if lcat == Power && rcat == Time { 689 - // 1 watt * 1 second = 1 joule 690 - let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight() / Unit::Second.weight()); 691 - match right.unit { 692 - Second => Ok(to_ideal_joule_unit(Number::new(result, Joule))), 693 - _ => Ok(to_ideal_unit(Number::new(result, Joule))), 694 - } 695 - } else if swapped { 696 - Err(format!("Cannot multiply {:?} and {:?}", right.unit, left.unit)) 697 - } else { 698 - actual_multiply(right, left, true) 699 - } 712 + todo!(); 713 + // let lcat = left.unit.category(); 714 + // let rcat = right.unit.category(); 715 + // if left.unit == NoUnit && right.unit == NoUnit { 716 + // // 3 * 2 717 + // Ok(Number::new(left.value * right.value, left.unit)) 718 + // } else if left.unit.category() == Temperature || right.unit.category() == Temperature { 719 + // // if temperature 720 + // Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit)) 721 + // } else if left.unit == NoUnit && right.unit != NoUnit { 722 + // // 3 * 2 anyunit 723 + // Ok(Number::new(left.value * right.value, right.unit)) 724 + // } else if lcat == Length && rcat == Length { 725 + // // length * length 726 + // let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); 727 + // Ok(to_ideal_unit(Number::new(result, SquareMillimeter))) 728 + // } else if lcat == Length && rcat == Area { 729 + // // length * area 730 + // let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); 731 + // Ok(to_ideal_unit(Number::new(result, CubicMillimeter))) 732 + // } else if lcat == Speed && rcat == Time { 733 + // // 1 km/h * 1h 734 + // let kph_value = left.value * left.unit.weight(); 735 + // let hours = convert(right, Hour)?; 736 + // let result = kph_value * hours.value; 737 + // let final_unit = match left.unit { 738 + // KilometersPerHour => Kilometer, 739 + // MetersPerSecond => Meter, 740 + // MilesPerHour => Mile, 741 + // FeetPerSecond => Foot, 742 + // Knot => NauticalMile, 743 + // _ => Meter, 744 + // }; 745 + // let kilometers = Number::new(result, Kilometer); 746 + // Ok(convert(kilometers, final_unit)?) 747 + // } else if lcat == DataTransferRate && rcat == Time { 748 + // // 8 megabytes per second * 1 minute 749 + // let data_rate_value = left.value * left.unit.weight(); 750 + // let seconds = convert(right, Second)?; 751 + // let result = data_rate_value * seconds.value; 752 + // let final_unit = match left.unit { 753 + // BitsPerSecond => Bit, 754 + // KilobitsPerSecond => Kilobit, 755 + // MegabitsPerSecond => Megabit, 756 + // GigabitsPerSecond => Gigabit, 757 + // TerabitsPerSecond => Terabit, 758 + // PetabitsPerSecond => Petabit, 759 + // ExabitsPerSecond => Exabit, 760 + // ZettabitsPerSecond => Zettabit, 761 + // YottabitsPerSecond => Yottabit, 762 + // KibibitsPerSecond => Kibibit, 763 + // MebibitsPerSecond => Mebibit, 764 + // GibibitsPerSecond => Gibibit, 765 + // TebibitsPerSecond => Tebibit, 766 + // PebibitsPerSecond => Pebibit, 767 + // ExbibitsPerSecond => Exbibit, 768 + // ZebibitsPerSecond => Zebibit, 769 + // YobibitsPerSecond => Yobibit, 770 + // BytesPerSecond => Byte, 771 + // KilobytesPerSecond => Kilobyte, 772 + // MegabytesPerSecond => Megabyte, 773 + // GigabytesPerSecond => Gigabyte, 774 + // TerabytesPerSecond => Terabyte, 775 + // PetabytesPerSecond => Petabyte, 776 + // ExabytesPerSecond => Exabyte, 777 + // ZettabytesPerSecond => Zettabyte, 778 + // YottabytesPerSecond => Yottabyte, 779 + // KibibytesPerSecond => Kibibyte, 780 + // MebibytesPerSecond => Mebibyte, 781 + // GibibytesPerSecond => Gibibyte, 782 + // TebibytesPerSecond => Tebibyte, 783 + // PebibytesPerSecond => Pebibyte, 784 + // ExbibytesPerSecond => Exbibyte, 785 + // ZebibytesPerSecond => Zebibyte, 786 + // YobibytesPerSecond => Yobibyte, 787 + // _ => Bit, 788 + // }; 789 + // let data_storage = Number::new(result, Bit); 790 + // Ok(convert(data_storage, final_unit)?) 791 + // } else if lcat == FlopRate && rcat == Time { 792 + // // 8 megaFLOP per second * 1 minute 793 + // let compute_perf_value = left.value * left.unit.weight(); 794 + // let seconds = convert(right, Second)?; 795 + // let result = compute_perf_value * seconds.value; 796 + // let final_unit = match left.unit { 797 + // FlopPerSecond => Flop, 798 + // KiloFlopPerSecond => KiloFlop, 799 + // MegaFlopPerSecond => MegaFlop, 800 + // GigaFlopPerSecond => GigaFlop, 801 + // TeraFlopPerSecond => TeraFlop, 802 + // PetaFlopPerSecond => PetaFlop, 803 + // ExaFlopPerSecond => ExaFlop, 804 + // ZettaFlopPerSecond => ZettaFlop, 805 + // YottaFlopPerSecond => YottaFlop, 806 + // RonnaFlopPerSecond => RonnaFlop, 807 + // QuettaFlopPerSecond => QuettaFlop, 808 + // _ => Flop, 809 + // }; 810 + // let compute_work = Number::new(result, Flop); 811 + // Ok(convert(compute_work, final_unit)?) 812 + // } else if lcat == Voltage && rcat == ElectricCurrent { 813 + // // 1 volt * 1 ampere = 1 watt 814 + // let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); 815 + // Ok(to_ideal_unit(Number::new(result, Watt))) 816 + // } else if lcat == ElectricCurrent && rcat == Resistance { 817 + // // 1 amp * 1 ohm = 1 volt 818 + // let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); 819 + // Ok(to_ideal_unit(Number::new(result, Watt))) 820 + // } else if lcat == Power && rcat == Time { 821 + // // 1 watt * 1 second = 1 joule 822 + // let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight() / Unit::Second.weight()); 823 + // match right.unit { 824 + // Second => Ok(to_ideal_joule_unit(Number::new(result, Joule))), 825 + // _ => Ok(to_ideal_unit(Number::new(result, Joule))), 826 + // } 827 + // } else if swapped { 828 + // Err(format!("Cannot multiply {:?} and {:?}", right.unit, left.unit)) 829 + // } else { 830 + // actual_multiply(right, left, true) 831 + // } 700 832 } 701 833 702 834 /// Divide a [`Number`] by another [`Number`] 703 - /// 835 + /// 704 836 /// - Temperatures don't work 705 - /// - If you divide a unit by that same unit, the result has a unit of [`NoType`] 837 + /// - If you divide a unit by that same unit, the result has no unit 706 838 /// - If you divide [`Volume`] by [`Length`], the result has a unit of [`Area`], etc. 707 839 /// - If you divide [`Length`] by [`Time`], the result has a unit of [`Speed`] 708 840 /// - If you divide [`Length`] by [`Speed`], the result has a unit of [`Time`] ··· 712 844 /// - If you divide [`Power`] by [`Voltage`], the result has a unit of [`Ampere`] 713 845 /// - If you divide [`Energy`] by [`Time`], the result has a unit of [`Power`] 714 846 pub fn divide(left: Number, right: Number) -> Result<Number, String> { 715 - let lcat = left.unit.category(); 716 - let rcat = right.unit.category(); 717 - if left.unit == NoUnit && right.unit == NoUnit { 718 - // 3 / 2 719 - Ok(Number::new(left.value / right.value, left.unit)) 720 - } else if lcat == Temperature || rcat == Temperature { 721 - // if temperature 722 - Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit)) 723 - } else if left.unit != NoUnit && right.unit == NoUnit { 724 - // 1 km / 2 725 - Ok(Number::new(left.value / right.value, left.unit)) 726 - } else if lcat == rcat { 727 - // 4 km / 2 km 728 - let (left, right) = convert_to_lowest(left, right)?; 729 - Ok(Number::new(left.value / right.value, NoUnit)) 730 - } else if (lcat == Area && rcat == Length) || (lcat == Volume && rcat == Area) { 731 - // 1 km2 / 1 km, 1 km3 / 1 km2 732 - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); 733 - Ok(to_ideal_unit(Number::new(result, Millimeter))) 734 - } else if lcat == Volume && rcat == Length { 735 - // 1 km3 / 1 km 736 - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); 737 - Ok(to_ideal_unit(Number::new(result, SquareMillimeter))) 738 - } else if lcat == Length && rcat == Time { 739 - // 1 km / 2s 740 - let final_unit = match (left.unit, right.unit) { 741 - (Kilometer, Hour) => KilometersPerHour, 742 - (Meter, Second) => MetersPerSecond, 743 - (Mile, Hour) => MilesPerHour, 744 - (Foot, Second) => FeetPerSecond, 745 - (NauticalMile, Hour) => Knot, 746 - _ => KilometersPerHour, 747 - }; 748 - let kilometers = convert(left, Kilometer)?; 749 - let hours = convert(right, Hour)?; 750 - let kph = Number::new(kilometers.value / hours.value, KilometersPerHour); 751 - Ok(convert(kph, final_unit)?) 752 - } else if lcat == Length && rcat == Speed { 753 - // 12 km / 100 kph 754 - let kilometers = convert(left, Kilometer)?; 755 - let kilometers_per_hour = convert(right, KilometersPerHour)?; 756 - let hour = Number::new(kilometers.value / kilometers_per_hour.value, Hour); 757 - Ok(to_ideal_unit(hour)) 758 - } else if lcat == DigitalStorage && rcat == DataTransferRate { 759 - // 1 kilobit / 1 bit per second 760 - let bits = convert(left, Bit)?; 761 - let bits_per_second = convert(right, BitsPerSecond)?; 762 - let seconds = Number::new(bits.value / bits_per_second.value, Second); 763 - Ok(to_ideal_unit(seconds)) 764 - } else if lcat == FlopCount && rcat == FlopRate { 765 - // 1 kiloFLOP / 1 FLOP per second 766 - let flop = convert(left, Flop)?; 767 - let flop_per_second = convert(right, FlopPerSecond)?; 768 - let seconds = Number::new(flop.value / flop_per_second.value, Second); 769 - Ok(to_ideal_unit(seconds)) 770 - } else if lcat == Power && rcat == ElectricCurrent { 771 - // 1 watt / 1 ampere = 1 volt 772 - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); 773 - Ok(to_ideal_unit(Number::new(result, Volt))) 774 - } else if lcat == Voltage && rcat == ElectricCurrent { 775 - // 1 volt / 1 ampere = 1 ohm 776 - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); 777 - Ok(to_ideal_unit(Number::new(result, Ohm))) 778 - } else if lcat == Voltage && rcat == Resistance { 779 - // 1 volt / 1 ohm = 1 amp 780 - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); 781 - Ok(to_ideal_unit(Number::new(result, Ampere))) 782 - } else if lcat == Power && rcat == Voltage { 783 - // 1 watt / 1 volt = 1 amp 784 - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); 785 - Ok(to_ideal_unit(Number::new(result, Ampere))) 786 - } else if lcat == Energy && rcat == Time { 787 - // 1 joule / 1 second = 1 watt 788 - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight() / Unit::Second.weight()); 789 - Ok(to_ideal_unit(Number::new(result, Watt))) 790 - } else { 791 - Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit)) 792 - } 847 + todo!(); 848 + // let lcat = left.unit.category(); 849 + // let rcat = right.unit.category(); 850 + // if left.unit == NoUnit && right.unit == NoUnit { 851 + // // 3 / 2 852 + // Ok(Number::new(left.value / right.value, left.unit)) 853 + // } else if lcat == Temperature || rcat == Temperature { 854 + // // if temperature 855 + // Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit)) 856 + // } else if left.has_unit() && right.unit == NoUnit { 857 + // // 1 km / 2 858 + // Ok(Number::new(left.value / right.value, left.unit)) 859 + // } else if lcat == rcat { 860 + // // 4 km / 2 km 861 + // let (left, right) = convert_to_lowest(left, right)?; 862 + // Ok(Number::new(left.value / right.value, NoUnit)) 863 + // } else if (lcat == Area && rcat == Length) || (lcat == Volume && rcat == Area) { 864 + // // 1 km2 / 1 km, 1 km3 / 1 km2 865 + // let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); 866 + // Ok(to_ideal_unit(Number::new(result, Millimeter))) 867 + // } else if lcat == Volume && rcat == Length { 868 + // // 1 km3 / 1 km 869 + // let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); 870 + // Ok(to_ideal_unit(Number::new(result, SquareMillimeter))) 871 + // } else if lcat == Length && rcat == Time { 872 + // // 1 km / 2s 873 + // let final_unit = match (left.unit, right.unit) { 874 + // (Kilometer, Hour) => KilometersPerHour, 875 + // (Meter, Second) => MetersPerSecond, 876 + // (Mile, Hour) => MilesPerHour, 877 + // (Foot, Second) => FeetPerSecond, 878 + // (NauticalMile, Hour) => Knot, 879 + // _ => KilometersPerHour, 880 + // }; 881 + // let kilometers = convert(left, Kilometer)?; 882 + // let hours = convert(right, Hour)?; 883 + // let kph = Number::new(kilometers.value / hours.value, KilometersPerHour); 884 + // Ok(convert(kph, final_unit)?) 885 + // } else if lcat == Length && rcat == Speed { 886 + // // 12 km / 100 kph 887 + // let kilometers = convert(left, Kilometer)?; 888 + // let kilometers_per_hour = convert(right, KilometersPerHour)?; 889 + // let hour = Number::new(kilometers.value / kilometers_per_hour.value, Hour); 890 + // Ok(to_ideal_unit(hour)) 891 + // } else if lcat == DigitalStorage && rcat == DataTransferRate { 892 + // // 1 kilobit / 1 bit per second 893 + // let bits = convert(left, Bit)?; 894 + // let bits_per_second = convert(right, BitsPerSecond)?; 895 + // let seconds = Number::new(bits.value / bits_per_second.value, Second); 896 + // Ok(to_ideal_unit(seconds)) 897 + // } else if lcat == FlopCount && rcat == FlopRate { 898 + // // 1 kiloFLOP / 1 FLOP per second 899 + // let flop = convert(left, Flop)?; 900 + // let flop_per_second = convert(right, FlopPerSecond)?; 901 + // let seconds = Number::new(flop.value / flop_per_second.value, Second); 902 + // Ok(to_ideal_unit(seconds)) 903 + // } else if lcat == Power && rcat == ElectricCurrent { 904 + // // 1 watt / 1 ampere = 1 volt 905 + // let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); 906 + // Ok(to_ideal_unit(Number::new(result, Volt))) 907 + // } else if lcat == Voltage && rcat == ElectricCurrent { 908 + // // 1 volt / 1 ampere = 1 ohm 909 + // let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); 910 + // Ok(to_ideal_unit(Number::new(result, Ohm))) 911 + // } else if lcat == Voltage && rcat == Resistance { 912 + // // 1 volt / 1 ohm = 1 amp 913 + // let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); 914 + // Ok(to_ideal_unit(Number::new(result, Ampere))) 915 + // } else if lcat == Power && rcat == Voltage { 916 + // // 1 watt / 1 volt = 1 amp 917 + // let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); 918 + // Ok(to_ideal_unit(Number::new(result, Ampere))) 919 + // } else if lcat == Energy && rcat == Time { 920 + // // 1 joule / 1 second = 1 watt 921 + // let result = (left.value * left.unit.weight()) 922 + // / (right.value * right.unit.weight() / Unit::Second.weight()); 923 + // Ok(to_ideal_unit(Number::new(result, Watt))) 924 + // } else { 925 + // Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit)) 926 + // } 793 927 } 794 928 /// Modulo a [`Number`] by another [`Number`]. 795 - /// 929 + /// 796 930 /// `left` and `right` need to have the same [`UnitType`], and the result will have that same [`UnitType`]. 797 931 /// 798 932 /// Temperatures don't work. 799 933 pub fn modulo(left: Number, right: Number) -> Result<Number, String> { 800 - if left.unit.category() == Temperature || right.unit.category() == Temperature { 801 - // if temperature 802 - Err(format!("Cannot modulo {:?} by {:?}", left.unit, right.unit)) 803 - } else if left.unit.category() == right.unit.category() { 804 - // 5 km % 3 m 805 - let (left, right) = convert_to_lowest(left, right)?; 806 - Ok(Number::new(left.value % right.value, left.unit)) 807 - } else { 808 - Err(format!("Cannot modulo {:?} by {:?}", left.unit, right.unit)) 809 - } 934 + todo!(); 935 + // if left.unit.category() == Temperature || right.unit.category() == Temperature { 936 + // // if temperature 937 + // Err(format!("Cannot modulo {:?} by {:?}", left.unit, right.unit)) 938 + // } else if left.unit.category() == right.unit.category() { 939 + // // 5 km % 3 m 940 + // let (left, right) = convert_to_lowest(left, right)?; 941 + // Ok(Number::new(left.value % right.value, left.unit)) 942 + // } else { 943 + // Err(format!("Cannot modulo {:?} by {:?}", left.unit, right.unit)) 944 + // } 810 945 } 811 946 812 947 /// Returns a [`Number`] to the power of another [`Number`] 813 - /// 948 + /// 814 949 /// - If you take [`Length`] to the power of [`NoType`], the result has a unit of [`Area`]. 815 950 /// - If you take [`Length`] to the power of [`Length`], the result has a unit of [`Area`] 816 951 /// - If you take [`Length`] to the power of [`Area`], the result has a unit of [`Volume`] 817 952 /// - etc. 818 953 pub fn pow(left: Number, right: Number) -> Result<Number, String> { 819 - // I tried converting `right` to use powi, but somehow that was slower 820 - let lcat = left.unit.category(); 821 - let rcat = left.unit.category(); 822 - if left.unit == NoUnit && right.unit == NoUnit { 823 - // 3 ^ 2 824 - Ok(Number::new(left.value.pow(right.value), left.unit)) 825 - } else if right.value == d!(1) && right.unit == NoUnit { 826 - Ok(left) 827 - } else if lcat == Length && right.unit == NoUnit && right.value == d!(2) { 828 - // x km ^ 2 829 - let result = (left.value * left.unit.weight()).pow(right.value); 830 - Ok(to_ideal_unit(Number::new(result, SquareMillimeter))) 831 - } else if lcat == Length && right.unit == NoUnit && right.value == d!(3) { 832 - // x km ^ 3 833 - let result = (left.value * left.unit.weight()).pow(right.value); 834 - Ok(to_ideal_unit(Number::new(result, CubicMillimeter))) 835 - } else { 836 - Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit)) 837 - } 954 + todo!(); 955 + // // I tried converting `right` to use powi, but somehow that was slower 956 + // let lcat = left.unit.category(); 957 + // let rcat = left.unit.category(); 958 + // if left.unit == NoUnit && right.unit == NoUnit { 959 + // // 3 ^ 2 960 + // Ok(Number::new(left.value.pow(right.value), left.unit)) 961 + // } else if right.value == d!(1) && right.unit == NoUnit { 962 + // Ok(left) 963 + // } else if lcat == Length && right.unit == NoUnit && right.value == d!(2) { 964 + // // x km ^ 2 965 + // let result = (left.value * left.unit.weight()).pow(right.value); 966 + // Ok(to_ideal_unit(Number::new(result, SquareMillimeter))) 967 + // } else if lcat == Length && right.unit == NoUnit && right.value == d!(3) { 968 + // // x km ^ 3 969 + // let result = (left.value * left.unit.weight()).pow(right.value); 970 + // Ok(to_ideal_unit(Number::new(result, CubicMillimeter))) 971 + // } else { 972 + // Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit)) 973 + // } 838 974 } 839 975 840 976 #[cfg(test)] 841 977 mod tests { 842 978 use fastnum::decimal::Context; 843 979 844 - use super::*; 980 + use super::*; 845 981 846 982 macro_rules! assert_float_eq { 847 983 ( $actual:expr, $expected:literal ) => { 848 984 assert!(($actual - $expected).abs() < f64::EPSILON); 849 - } 985 + }; 850 986 } 851 987 852 988 #[test] ··· 970 1106 assert_float_eq!(convert_test(1024.0, Zebibyte, Yobibyte), 1.0); 971 1107 972 1108 assert_float_eq!(convert_test(1000.0, BitsPerSecond, KilobitsPerSecond), 1.0); 973 - assert_float_eq!(convert_test(1000.0, KilobitsPerSecond, MegabitsPerSecond), 1.0); 974 - assert_float_eq!(convert_test(1000.0, MegabitsPerSecond, GigabitsPerSecond), 1.0); 975 - assert_float_eq!(convert_test(1000.0, GigabitsPerSecond, TerabitsPerSecond), 1.0); 976 - assert_float_eq!(convert_test(1000.0, TerabitsPerSecond, PetabitsPerSecond), 1.0); 977 - assert_float_eq!(convert_test(1000.0, PetabitsPerSecond, ExabitsPerSecond), 1.0); 978 - assert_float_eq!(convert_test(1000.0, ExabitsPerSecond, ZettabitsPerSecond), 1.0); 979 - assert_float_eq!(convert_test(1000.0, ZettabitsPerSecond, YottabitsPerSecond), 1.0); 1109 + assert_float_eq!( 1110 + convert_test(1000.0, KilobitsPerSecond, MegabitsPerSecond), 1111 + 1.0 1112 + ); 1113 + assert_float_eq!( 1114 + convert_test(1000.0, MegabitsPerSecond, GigabitsPerSecond), 1115 + 1.0 1116 + ); 1117 + assert_float_eq!( 1118 + convert_test(1000.0, GigabitsPerSecond, TerabitsPerSecond), 1119 + 1.0 1120 + ); 1121 + assert_float_eq!( 1122 + convert_test(1000.0, TerabitsPerSecond, PetabitsPerSecond), 1123 + 1.0 1124 + ); 1125 + assert_float_eq!( 1126 + convert_test(1000.0, PetabitsPerSecond, ExabitsPerSecond), 1127 + 1.0 1128 + ); 1129 + assert_float_eq!( 1130 + convert_test(1000.0, ExabitsPerSecond, ZettabitsPerSecond), 1131 + 1.0 1132 + ); 1133 + assert_float_eq!( 1134 + convert_test(1000.0, ZettabitsPerSecond, YottabitsPerSecond), 1135 + 1.0 1136 + ); 980 1137 assert_float_eq!(convert_test(1024.0, BitsPerSecond, KibibitsPerSecond), 1.0); 981 - assert_float_eq!(convert_test(1024.0, KibibitsPerSecond, MebibitsPerSecond), 1.0); 982 - assert_float_eq!(convert_test(1024.0, MebibitsPerSecond, GibibitsPerSecond), 1.0); 983 - assert_float_eq!(convert_test(1024.0, GibibitsPerSecond, TebibitsPerSecond), 1.0); 984 - assert_float_eq!(convert_test(1024.0, TebibitsPerSecond, PebibitsPerSecond), 1.0); 985 - assert_float_eq!(convert_test(1024.0, PebibitsPerSecond, ExbibitsPerSecond), 1.0); 986 - assert_float_eq!(convert_test(1024.0, ExbibitsPerSecond, ZebibitsPerSecond), 1.0); 987 - assert_float_eq!(convert_test(1024.0, ZebibitsPerSecond, YobibitsPerSecond), 1.0); 1138 + assert_float_eq!( 1139 + convert_test(1024.0, KibibitsPerSecond, MebibitsPerSecond), 1140 + 1.0 1141 + ); 1142 + assert_float_eq!( 1143 + convert_test(1024.0, MebibitsPerSecond, GibibitsPerSecond), 1144 + 1.0 1145 + ); 1146 + assert_float_eq!( 1147 + convert_test(1024.0, GibibitsPerSecond, TebibitsPerSecond), 1148 + 1.0 1149 + ); 1150 + assert_float_eq!( 1151 + convert_test(1024.0, TebibitsPerSecond, PebibitsPerSecond), 1152 + 1.0 1153 + ); 1154 + assert_float_eq!( 1155 + convert_test(1024.0, PebibitsPerSecond, ExbibitsPerSecond), 1156 + 1.0 1157 + ); 1158 + assert_float_eq!( 1159 + convert_test(1024.0, ExbibitsPerSecond, ZebibitsPerSecond), 1160 + 1.0 1161 + ); 1162 + assert_float_eq!( 1163 + convert_test(1024.0, ZebibitsPerSecond, YobibitsPerSecond), 1164 + 1.0 1165 + ); 988 1166 assert_float_eq!(convert_test(8.0, BitsPerSecond, BytesPerSecond), 1.0); 989 - assert_float_eq!(convert_test(1000.0, BytesPerSecond, KilobytesPerSecond), 1.0); 990 - assert_float_eq!(convert_test(1000.0, KilobytesPerSecond, MegabytesPerSecond), 1.0); 991 - assert_float_eq!(convert_test(1000.0, MegabytesPerSecond, GigabytesPerSecond), 1.0); 992 - assert_float_eq!(convert_test(1000.0, GigabytesPerSecond, TerabytesPerSecond), 1.0); 993 - assert_float_eq!(convert_test(1000.0, TerabytesPerSecond, PetabytesPerSecond), 1.0); 994 - assert_float_eq!(convert_test(1000.0, PetabytesPerSecond, ExabytesPerSecond), 1.0); 995 - assert_float_eq!(convert_test(1000.0, ExabytesPerSecond, ZettabytesPerSecond), 1.0); 996 - assert_float_eq!(convert_test(1000.0, ZettabytesPerSecond, YottabytesPerSecond), 1.0); 997 - assert_float_eq!(convert_test(1024.0, KibibytesPerSecond, MebibytesPerSecond), 1.0); 998 - assert_float_eq!(convert_test(1024.0, MebibytesPerSecond, GibibytesPerSecond), 1.0); 999 - assert_float_eq!(convert_test(1024.0, GibibytesPerSecond, TebibytesPerSecond), 1.0); 1000 - assert_float_eq!(convert_test(1024.0, TebibytesPerSecond, PebibytesPerSecond), 1.0); 1001 - assert_float_eq!(convert_test(1024.0, PebibytesPerSecond, ExbibytesPerSecond), 1.0); 1002 - assert_float_eq!(convert_test(1024.0, ExbibytesPerSecond, ZebibytesPerSecond), 1.0); 1003 - assert_float_eq!(convert_test(1024.0, ZebibytesPerSecond, YobibytesPerSecond), 1.0); 1167 + assert_float_eq!( 1168 + convert_test(1000.0, BytesPerSecond, KilobytesPerSecond), 1169 + 1.0 1170 + ); 1171 + assert_float_eq!( 1172 + convert_test(1000.0, KilobytesPerSecond, MegabytesPerSecond), 1173 + 1.0 1174 + ); 1175 + assert_float_eq!( 1176 + convert_test(1000.0, MegabytesPerSecond, GigabytesPerSecond), 1177 + 1.0 1178 + ); 1179 + assert_float_eq!( 1180 + convert_test(1000.0, GigabytesPerSecond, TerabytesPerSecond), 1181 + 1.0 1182 + ); 1183 + assert_float_eq!( 1184 + convert_test(1000.0, TerabytesPerSecond, PetabytesPerSecond), 1185 + 1.0 1186 + ); 1187 + assert_float_eq!( 1188 + convert_test(1000.0, PetabytesPerSecond, ExabytesPerSecond), 1189 + 1.0 1190 + ); 1191 + assert_float_eq!( 1192 + convert_test(1000.0, ExabytesPerSecond, ZettabytesPerSecond), 1193 + 1.0 1194 + ); 1195 + assert_float_eq!( 1196 + convert_test(1000.0, ZettabytesPerSecond, YottabytesPerSecond), 1197 + 1.0 1198 + ); 1199 + assert_float_eq!( 1200 + convert_test(1024.0, KibibytesPerSecond, MebibytesPerSecond), 1201 + 1.0 1202 + ); 1203 + assert_float_eq!( 1204 + convert_test(1024.0, MebibytesPerSecond, GibibytesPerSecond), 1205 + 1.0 1206 + ); 1207 + assert_float_eq!( 1208 + convert_test(1024.0, GibibytesPerSecond, TebibytesPerSecond), 1209 + 1.0 1210 + ); 1211 + assert_float_eq!( 1212 + convert_test(1024.0, TebibytesPerSecond, PebibytesPerSecond), 1213 + 1.0 1214 + ); 1215 + assert_float_eq!( 1216 + convert_test(1024.0, PebibytesPerSecond, ExbibytesPerSecond), 1217 + 1.0 1218 + ); 1219 + assert_float_eq!( 1220 + convert_test(1024.0, ExbibytesPerSecond, ZebibytesPerSecond), 1221 + 1.0 1222 + ); 1223 + assert_float_eq!( 1224 + convert_test(1024.0, ZebibytesPerSecond, YobibytesPerSecond), 1225 + 1.0 1226 + ); 1004 1227 1005 1228 assert_float_eq!(convert_test(1000.0, Flop, KiloFlop), 1.0); 1006 1229 assert_float_eq!(convert_test(1000.0, KiloFlop, MegaFlop), 1.0); ··· 1014 1237 assert_float_eq!(convert_test(1000.0, RonnaFlop, QuettaFlop), 1.0); 1015 1238 1016 1239 assert_float_eq!(convert_test(1000.0, FlopPerSecond, KiloFlopPerSecond), 1.0); 1017 - assert_float_eq!(convert_test(1000.0, KiloFlopPerSecond, MegaFlopPerSecond), 1.0); 1018 - assert_float_eq!(convert_test(1000.0, MegaFlopPerSecond, GigaFlopPerSecond), 1.0); 1019 - assert_float_eq!(convert_test(1000.0, GigaFlopPerSecond, TeraFlopPerSecond), 1.0); 1020 - assert_float_eq!(convert_test(1000.0, TeraFlopPerSecond, PetaFlopPerSecond), 1.0); 1021 - assert_float_eq!(convert_test(1000.0, PetaFlopPerSecond, ExaFlopPerSecond), 1.0); 1022 - assert_float_eq!(convert_test(1000.0, ExaFlopPerSecond, ZettaFlopPerSecond), 1.0); 1023 - assert_float_eq!(convert_test(1000.0, ZettaFlopPerSecond, YottaFlopPerSecond), 1.0); 1024 - assert_float_eq!(convert_test(1000.0, YottaFlopPerSecond, RonnaFlopPerSecond), 1.0); 1025 - assert_float_eq!(convert_test(1000.0, RonnaFlopPerSecond, QuettaFlopPerSecond), 1.0); 1240 + assert_float_eq!( 1241 + convert_test(1000.0, KiloFlopPerSecond, MegaFlopPerSecond), 1242 + 1.0 1243 + ); 1244 + assert_float_eq!( 1245 + convert_test(1000.0, MegaFlopPerSecond, GigaFlopPerSecond), 1246 + 1.0 1247 + ); 1248 + assert_float_eq!( 1249 + convert_test(1000.0, GigaFlopPerSecond, TeraFlopPerSecond), 1250 + 1.0 1251 + ); 1252 + assert_float_eq!( 1253 + convert_test(1000.0, TeraFlopPerSecond, PetaFlopPerSecond), 1254 + 1.0 1255 + ); 1256 + assert_float_eq!( 1257 + convert_test(1000.0, PetaFlopPerSecond, ExaFlopPerSecond), 1258 + 1.0 1259 + ); 1260 + assert_float_eq!( 1261 + convert_test(1000.0, ExaFlopPerSecond, ZettaFlopPerSecond), 1262 + 1.0 1263 + ); 1264 + assert_float_eq!( 1265 + convert_test(1000.0, ZettaFlopPerSecond, YottaFlopPerSecond), 1266 + 1.0 1267 + ); 1268 + assert_float_eq!( 1269 + convert_test(1000.0, YottaFlopPerSecond, RonnaFlopPerSecond), 1270 + 1.0 1271 + ); 1272 + assert_float_eq!( 1273 + convert_test(1000.0, RonnaFlopPerSecond, QuettaFlopPerSecond), 1274 + 1.0 1275 + ); 1026 1276 1027 1277 assert_float_eq!(convert_test(1000.0, Millijoule, Joule), 1.0); 1028 1278 assert_float_eq!(convert_test(1000.0, Joule, Kilojoule), 1.0); ··· 1046 1296 assert_float_eq!(convert_test(1000.0, Megawatt, Gigawatt), 1.0); 1047 1297 assert_float_eq!(convert_test(1000.0, Gigawatt, Terawatt), 1.0); 1048 1298 assert_float_eq!(convert_test(1000.0, Terawatt, Petawatt), 1.0); 1049 - assert_float_eq!(convert_test(17.584264210333, Watt, BritishThermalUnitsPerMinute), 1.0); 1050 - assert_float_eq!(convert_test(59.999999999999317571673374406441452784, BritishThermalUnitsPerHour, BritishThermalUnitsPerMinute), 1.0); 1299 + assert_float_eq!( 1300 + convert_test(17.584264210333, Watt, BritishThermalUnitsPerMinute), 1301 + 1.0 1302 + ); 1303 + assert_float_eq!( 1304 + convert_test( 1305 + 59.999999999999317571673374406441452784, 1306 + BritishThermalUnitsPerHour, 1307 + BritishThermalUnitsPerMinute 1308 + ), 1309 + 1.0 1310 + ); 1051 1311 assert_float_eq!(convert_test(745.6998715822702, Watt, Horsepower), 1.0); 1052 1312 assert_float_eq!(convert_test(735.49875, Watt, MetricHorsepower), 1.0); 1053 1313 ··· 1066 1326 assert_float_eq!(convert_test(100.0, Pascal, Millibar), 1.0); 1067 1327 assert_float_eq!(convert_test(1000.0, Millibar, Bar), 1.0); 1068 1328 assert_float_eq!(convert_test(3386.389, Pascal, InchOfMercury), 1.0); 1069 - assert_float_eq!(convert_test(6894.757293168361, Pascal, PoundsPerSquareInch), 1.0); 1329 + assert_float_eq!( 1330 + convert_test(6894.757293168361, Pascal, PoundsPerSquareInch), 1331 + 1.0 1332 + ); 1070 1333 assert_float_eq!(convert_test(133.3223684210526, Pascal, Torr), 1.0); 1071 1334 1072 1335 assert_float_eq!(convert_test(1000.0, Hertz, Kilohertz), 1.0);