From 4ac7e74c6b968d9cfe6298af36d58660aa0e203e Mon Sep 17 00:00:00 2001 From: Kasper Date: Mon, 12 Sep 2022 00:47:20 +0200 Subject: [PATCH] Switch indentation to tabs --- rustfmt.toml | 2 +- src/evaluator.rs | 512 +++++------ src/lexer.rs | 2270 +++++++++++++++++++++++----------------------- src/lib.rs | 280 +++--- src/lookup.rs | 2060 ++++++++++++++++++++--------------------- src/main.rs | 116 +-- src/parser.rs | 622 ++++++------- src/units.rs | 1730 +++++++++++++++++------------------ 8 files changed, 3800 insertions(+), 3792 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 28781c7..7c224aa 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1 +1 @@ -tab_spaces=2 +hard_tabs=true diff --git a/src/evaluator.rs b/src/evaluator.rs index 02e14a1..f0ba49f 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -11,8 +11,8 @@ use decimal::d128; /// Evaluate an [`AstNode`] into a [`Number`] pub fn evaluate(ast: &AstNode) -> Result { - let answer = evaluate_node(ast)?; - Ok(answer) + let answer = evaluate_node(ast)?; + Ok(answer) } /// Returns the factorial of a [`struct@d128`] up to `1000!` without doing any math @@ -21,287 +21,289 @@ pub fn evaluate(ast: &AstNode) -> Result { /// /// All return values of this function are hard-coded. pub fn factorial(input: d128) -> d128 { - lookup_factorial(input.into()) + lookup_factorial(input.into()) } /// Returns the square root of a [`struct@d128`] pub fn sqrt(input: d128) -> d128 { - let mut n = d128!(1); - let half = d128!(0.5); - for _ in 0..10 { - n = (n + input / n) * half; - } - n + let mut n = d128!(1); + let half = d128!(0.5); + for _ in 0..10 { + n = (n + input / n) * half; + } + n } /// Returns the cube root of a [`struct@d128`] pub fn cbrt(input: d128) -> d128 { - let mut n: d128 = input; - // hope that 20 iterations makes it accurate enough - let three = d128!(3); - for _ in 0..20 { - let z2 = n * n; - n = n - ((n * z2 - input) / (three * z2)); - } - n + let mut n: d128 = input; + // hope that 20 iterations makes it accurate enough + let three = d128!(3); + for _ in 0..20 { + let z2 = n * n; + n = n - ((n * z2 - input) / (three * z2)); + } + n } /// Returns the sine of a [`struct@d128`] pub fn sin(mut input: d128) -> d128 { - let pi = d128!(3.141592653589793238462643383279503); - let pi2 = d128!(6.283185307179586476925286766559006); + let pi = d128!(3.141592653589793238462643383279503); + let pi2 = d128!(6.283185307179586476925286766559006); - input %= pi2; + input %= pi2; - let negative_correction = if input.is_negative() { - input -= pi; - d128!(-1) - } else { - d128!(1) - }; + let negative_correction = if input.is_negative() { + input -= pi; + d128!(-1) + } else { + d128!(1) + }; - let one = d128!(1); - let two = d128!(2); - let neg_one = -one; + let one = d128!(1); + let two = d128!(2); + let neg_one = -one; - let precision = 37; - let mut result = d128!(0); - for i_int in 0..precision { - let i = d128::from(i_int); - let calc_result = two * i + one; - result += neg_one.pow(i) * (input.pow(calc_result) / factorial(calc_result)); - } + let precision = 37; + let mut result = d128!(0); + for i_int in 0..precision { + let i = d128::from(i_int); + let calc_result = two * i + one; + result += neg_one.pow(i) * (input.pow(calc_result) / factorial(calc_result)); + } - negative_correction * result + negative_correction * result } /// Returns the cosine of a [`struct@d128`] pub fn cos(input: d128) -> d128 { - let half_pi = d128!(1.570796326794896619231321691639751); - sin(half_pi - input) + let half_pi = d128!(1.570796326794896619231321691639751); + sin(half_pi - input) } /// Returns the tangent of a [`struct@d128`] pub fn tan(input: d128) -> d128 { - sin(input) / cos(input) + sin(input) / cos(input) } /// Evaluate an [`AstNode`] into a [`Number`] fn evaluate_node(ast_node: &AstNode) -> Result { - let token = &ast_node.token; - let children = &ast_node.children; - match token { - Token::Number(number) => Ok(Number::new(*number, Unit::NoUnit)), - Token::Constant(constant) => match constant { - Pi => Ok(Number::new( - d128!(3.141592653589793238462643383279503), - Unit::NoUnit, - )), - E => Ok(Number::new( - d128!(2.718281828459045235360287471352662), - Unit::NoUnit, - )), - }, - Token::FunctionIdentifier(function) => { - let child_node = children.get(0).ok_or("Paren has no child[0]")?; - let child_answer = evaluate_node(child_node)?; - match function { - Cbrt => { - if child_answer.unit.category() == UnitType::NoType { - let result = cbrt(child_answer.value); - Ok(Number::new(result, child_answer.unit)) - } else { - Err("log() only accepts UnitType::NoType".to_string()) - } - } - Sqrt => { - if child_answer.unit.category() == UnitType::NoType { - let result = sqrt(child_answer.value); - Ok(Number::new(result, child_answer.unit)) - } else { - Err("log() only accepts UnitType::NoType".to_string()) - } - } - Log => { - if child_answer.unit.category() == UnitType::NoType { - let result = child_answer.value.log10(); - Ok(Number::new(result, child_answer.unit)) - } else { - Err("log() only accepts UnitType::NoType".to_string()) - } - } - Ln => { - if child_answer.unit.category() == UnitType::NoType { - let result = child_answer.value.ln(); - Ok(Number::new(result, child_answer.unit)) - } else { - Err("ln() only accepts UnitType::NoType".to_string()) - } - } - Exp => { - if child_answer.unit.category() == UnitType::NoType { - let result = child_answer.value.exp(child_answer.value); - Ok(Number::new(result, child_answer.unit)) - } else { - Err("exp() only accepts UnitType::NoType".to_string()) - } - } - Round => { - // .quantize() rounds .5 to nearest even integer, so we correct that - let mut result = child_answer.value.quantize(d128!(1)); - let rounding_change = result - child_answer.value; - // If the result was rounded down by 0.5, correct by +1 - if rounding_change == d128!(-0.5) { - result += d128!(1); - } - Ok(Number::new(result, child_answer.unit)) - } - Ceil => { - let mut result = child_answer.value.quantize(d128!(1)); - let rounding_change = result - child_answer.value; - if rounding_change.is_negative() { - result += d128!(1); - } - Ok(Number::new(result, child_answer.unit)) - } - Floor => { - let mut result = child_answer.value.quantize(d128!(1)); - let rounding_change = result - child_answer.value; - if !rounding_change.is_negative() { - result -= d128!(1); - } - Ok(Number::new(result, child_answer.unit)) - } - Abs => { - let mut result = child_answer.value.abs(); - let rounding_change = result - child_answer.value; - if rounding_change == d128!(-0.5) { - result += d128!(1); - } - Ok(Number::new(result, child_answer.unit)) - } - Sin => { - let result = sin(child_answer.value); - Ok(Number::new(result, child_answer.unit)) - } - Cos => { - let result = cos(child_answer.value); - Ok(Number::new(result, child_answer.unit)) - } - Tan => { - let result = tan(child_answer.value); - Ok(Number::new(result, child_answer.unit)) - } - } - } - Token::Unit(unit) => { - let child_node = children.get(0).ok_or("Unit has no child[0]")?; - let child_answer = evaluate_node(child_node)?; - Ok(Number::new(child_answer.value, *unit)) - } - Token::Negative => { - let child_node = children.get(0).ok_or("Negative has no child[0]")?; - let child_answer = evaluate_node(child_node)?; - Ok(Number::new(-child_answer.value, child_answer.unit)) - } - Token::Paren => { - let child_node = children.get(0).ok_or("Paren has no child[0]")?; - evaluate_node(child_node) - } - Token::UnaryOperator(operator) => { - let child_node = children - .get(0) - .ok_or(format!("Token {:?} has no child[0]", token))?; - let child_answer = evaluate_node(child_node)?; - match operator { - Percent => Ok(Number::new( - child_answer.value / d128!(100), - child_answer.unit, - )), - Factorial => { - let result = factorial(child_answer.value); - if result.is_nan() { - return Err("Can only perform factorial on integers from 0 to 1000".to_string()); - } - Ok(Number::new(result, child_answer.unit)) - } - } - } - Token::NamedNumber(named_number) => { - let child_node = children - .get(0) - .ok_or(format!("Token {:?} has no child[0]", token))?; - let named_number_value = lookup_named_number(named_number); - if let Token::NamedNumber(child_nn) = &child_node.token { - let child_nn_value = lookup_named_number(child_nn); - if child_nn_value > named_number_value { - return Err(format!("Unexpected smaller token {:?}", token)); - } - } - let child_answer = evaluate_node(child_node)?; - let result = child_answer.value * named_number_value; - Ok(Number::new(result, child_answer.unit)) - } - Token::TextOperator(operator) => { - let left_child = children - .get(0) - .ok_or(format!("Token {:?} has no child[0]", token))?; - let right_child = children - .get(1) - .ok_or(format!("Token {:?} has no child[1]", token))?; + let token = &ast_node.token; + let children = &ast_node.children; + match token { + Token::Number(number) => Ok(Number::new(*number, Unit::NoUnit)), + Token::Constant(constant) => match constant { + Pi => Ok(Number::new( + d128!(3.141592653589793238462643383279503), + Unit::NoUnit, + )), + E => Ok(Number::new( + d128!(2.718281828459045235360287471352662), + Unit::NoUnit, + )), + }, + Token::FunctionIdentifier(function) => { + let child_node = children.get(0).ok_or("Paren has no child[0]")?; + let child_answer = evaluate_node(child_node)?; + match function { + Cbrt => { + if child_answer.unit.category() == UnitType::NoType { + let result = cbrt(child_answer.value); + Ok(Number::new(result, child_answer.unit)) + } else { + Err("log() only accepts UnitType::NoType".to_string()) + } + } + Sqrt => { + if child_answer.unit.category() == UnitType::NoType { + let result = sqrt(child_answer.value); + Ok(Number::new(result, child_answer.unit)) + } else { + Err("log() only accepts UnitType::NoType".to_string()) + } + } + Log => { + if child_answer.unit.category() == UnitType::NoType { + let result = child_answer.value.log10(); + Ok(Number::new(result, child_answer.unit)) + } else { + Err("log() only accepts UnitType::NoType".to_string()) + } + } + Ln => { + if child_answer.unit.category() == UnitType::NoType { + let result = child_answer.value.ln(); + Ok(Number::new(result, child_answer.unit)) + } else { + Err("ln() only accepts UnitType::NoType".to_string()) + } + } + Exp => { + if child_answer.unit.category() == UnitType::NoType { + let result = child_answer.value.exp(child_answer.value); + Ok(Number::new(result, child_answer.unit)) + } else { + Err("exp() only accepts UnitType::NoType".to_string()) + } + } + Round => { + // .quantize() rounds .5 to nearest even integer, so we correct that + let mut result = child_answer.value.quantize(d128!(1)); + let rounding_change = result - child_answer.value; + // If the result was rounded down by 0.5, correct by +1 + if rounding_change == d128!(-0.5) { + result += d128!(1); + } + Ok(Number::new(result, child_answer.unit)) + } + Ceil => { + let mut result = child_answer.value.quantize(d128!(1)); + let rounding_change = result - child_answer.value; + if rounding_change.is_negative() { + result += d128!(1); + } + Ok(Number::new(result, child_answer.unit)) + } + Floor => { + let mut result = child_answer.value.quantize(d128!(1)); + let rounding_change = result - child_answer.value; + if !rounding_change.is_negative() { + result -= d128!(1); + } + Ok(Number::new(result, child_answer.unit)) + } + Abs => { + let mut result = child_answer.value.abs(); + let rounding_change = result - child_answer.value; + if rounding_change == d128!(-0.5) { + result += d128!(1); + } + Ok(Number::new(result, child_answer.unit)) + } + Sin => { + let result = sin(child_answer.value); + Ok(Number::new(result, child_answer.unit)) + } + Cos => { + let result = cos(child_answer.value); + Ok(Number::new(result, child_answer.unit)) + } + Tan => { + let result = tan(child_answer.value); + Ok(Number::new(result, child_answer.unit)) + } + } + } + Token::Unit(unit) => { + let child_node = children.get(0).ok_or("Unit has no child[0]")?; + let child_answer = evaluate_node(child_node)?; + Ok(Number::new(child_answer.value, *unit)) + } + Token::Negative => { + let child_node = children.get(0).ok_or("Negative has no child[0]")?; + let child_answer = evaluate_node(child_node)?; + Ok(Number::new(-child_answer.value, child_answer.unit)) + } + Token::Paren => { + let child_node = children.get(0).ok_or("Paren has no child[0]")?; + evaluate_node(child_node) + } + Token::UnaryOperator(operator) => { + let child_node = children + .get(0) + .ok_or(format!("Token {:?} has no child[0]", token))?; + let child_answer = evaluate_node(child_node)?; + match operator { + Percent => Ok(Number::new( + child_answer.value / d128!(100), + child_answer.unit, + )), + Factorial => { + let result = factorial(child_answer.value); + if result.is_nan() { + return Err( + "Can only perform factorial on integers from 0 to 1000".to_string() + ); + } + Ok(Number::new(result, child_answer.unit)) + } + } + } + Token::NamedNumber(named_number) => { + let child_node = children + .get(0) + .ok_or(format!("Token {:?} has no child[0]", token))?; + let named_number_value = lookup_named_number(named_number); + if let Token::NamedNumber(child_nn) = &child_node.token { + let child_nn_value = lookup_named_number(child_nn); + if child_nn_value > named_number_value { + return Err(format!("Unexpected smaller token {:?}", token)); + } + } + let child_answer = evaluate_node(child_node)?; + let result = child_answer.value * named_number_value; + Ok(Number::new(result, child_answer.unit)) + } + Token::TextOperator(operator) => { + let left_child = children + .get(0) + .ok_or(format!("Token {:?} has no child[0]", token))?; + let right_child = children + .get(1) + .ok_or(format!("Token {:?} has no child[1]", token))?; - match operator { - To => { - if let Token::Unit(right_unit) = right_child.token { - let left = evaluate_node(left_child)?; - let result = convert(left, right_unit)?; - Ok(result) - } else { - Err("Right side of To operator needs to be a unit".to_string()) - } - } - Of => { - let left = evaluate_node(left_child)?; - let right = evaluate_node(right_child)?; - if left.unit == Unit::NoUnit { - Ok(Number::new(left.value * right.value, right.unit)) - } else { - Err("Left side of the Of operator must be NoUnit".to_string()) - } - } - } - } - Token::Operator(operator) => { - let left_child = children - .get(0) - .ok_or(format!("Token {:?} has no child[0]", token))?; - let right_child = children - .get(1) - .ok_or(format!("Token {:?} has no child[1]", token))?; - let left = evaluate_node(left_child)?; - let right = evaluate_node(right_child)?; - match operator { - Plus => Ok(add(left, right)?), - Minus => Ok(subtract(left, right)?), - Multiply => { - Ok(multiply(left, right)?) - // } - } - Divide => { - Ok(divide(left, right)?) - // } - } - Modulo => { - Ok(modulo(left, right)?) - // } - } - Caret => { - Ok(pow(left, right)?) - // } - } - _ => Err(format!("Unexpected operator {:?}", operator)), - } - } - _ => Err(format!("Unexpected token {:?}", token)), - } + match operator { + To => { + if let Token::Unit(right_unit) = right_child.token { + let left = evaluate_node(left_child)?; + let result = convert(left, right_unit)?; + Ok(result) + } else { + Err("Right side of To operator needs to be a unit".to_string()) + } + } + Of => { + let left = evaluate_node(left_child)?; + let right = evaluate_node(right_child)?; + if left.unit == Unit::NoUnit { + Ok(Number::new(left.value * right.value, right.unit)) + } else { + Err("Left side of the Of operator must be NoUnit".to_string()) + } + } + } + } + Token::Operator(operator) => { + let left_child = children + .get(0) + .ok_or(format!("Token {:?} has no child[0]", token))?; + let right_child = children + .get(1) + .ok_or(format!("Token {:?} has no child[1]", token))?; + let left = evaluate_node(left_child)?; + let right = evaluate_node(right_child)?; + match operator { + Plus => Ok(add(left, right)?), + Minus => Ok(subtract(left, right)?), + Multiply => { + Ok(multiply(left, right)?) + // } + } + Divide => { + Ok(divide(left, right)?) + // } + } + Modulo => { + Ok(modulo(left, right)?) + // } + } + Caret => { + Ok(pow(left, right)?) + // } + } + _ => Err(format!("Unexpected operator {:?}", operator)), + } + } + _ => Err(format!("Unexpected token {:?}", token)), + } } diff --git a/src/lexer.rs b/src/lexer.rs index e6d4d61..efc9869 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -14,1217 +14,1217 @@ use crate::units::Unit::*; use unicode_segmentation::{Graphemes, UnicodeSegmentation}; fn is_word_char_str(input: &str) -> bool { - match input { - "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" - | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" - | "Y" | "Z" => true, - "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" - | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" - | "y" | "z" => true, - "Ω" | "Ω" | "µ" | "μ" => true, - _ => false, - } + match input { + "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" + | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" + | "Y" | "Z" => true, + "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" + | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" + | "y" | "z" => true, + "Ω" | "Ω" | "µ" | "μ" => true, + _ => false, + } } fn is_numeric_str(input: &str) -> bool { - matches!(input, "." | "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9") + matches!(input, "." | "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9") } /// Read next characters as a word, otherwise return empty string. /// Returns an empty string if there's leading whitespace. fn read_word_plain(chars: &mut Peekable) -> String { - let mut word = String::new(); - while let Some(next_char) = chars.peek() { - if is_word_char_str(next_char) { - word += chars.next().unwrap(); - } else { - break; - } - } - word + let mut word = String::new(); + while let Some(next_char) = chars.peek() { + if is_word_char_str(next_char) { + word += chars.next().unwrap(); + } else { + break; + } + } + word } /// Read next as a word, otherwise return empty string. /// Leading whitespace is ignored. A trailing digit may be included. fn read_word(first_c: &str, lexer: &mut Lexer) -> String { - let chars = &mut lexer.chars; - let mut word = first_c.trim().to_owned(); - if word.is_empty() { - // skip whitespace - while let Some(current_char) = chars.peek() { - if current_char.trim().is_empty() { - chars.next(); - } else { - break; - } - } - } - while let Some(next_char) = chars.peek() { - if is_word_char_str(next_char) { - word += chars.next().unwrap(); - } else { - break; - } - } - if !word.is_empty() { - match *chars.peek().unwrap_or(&"") { - "2" | "²" => { - word += "2"; - chars.next(); - }, - "3" | "³" => { - word += "3"; - chars.next(); - }, - _ => {}, - } - } - word + let chars = &mut lexer.chars; + let mut word = first_c.trim().to_owned(); + if word.is_empty() { + // skip whitespace + while let Some(current_char) = chars.peek() { + if current_char.trim().is_empty() { + chars.next(); + } else { + break; + } + } + } + while let Some(next_char) = chars.peek() { + if is_word_char_str(next_char) { + word += chars.next().unwrap(); + } else { + break; + } + } + if !word.is_empty() { + match *chars.peek().unwrap_or(&"") { + "2" | "²" => { + word += "2"; + chars.next(); + }, + "3" | "³" => { + word += "3"; + chars.next(); + }, + _ => {}, + } + } + word } fn parse_token(c: &str, lexer: &mut Lexer) -> Result<(), String> { - let tokens = &mut lexer.tokens; - match c { - value if value.trim().is_empty() => {}, - value if is_word_char_str(value) => { - parse_word(read_word(c, lexer).as_str(), lexer)?; - }, - value if is_numeric_str(value) => { - let mut number_string = value.to_owned(); - while let Some(number_char) = lexer.chars.peek() { - if is_numeric_str(number_char) { - number_string += number_char; - lexer.chars.next(); - } else { - break; - } - } - d128::set_status(decimal::Status::empty()); - match d128::from_str(&number_string) { - Ok(number) => { - if d128::get_status().is_empty() { - tokens.push(Token::Number(number)); - } else { - return Err(format!("Error lexing d128 number: {}", number_string)); - } - }, - Err(_e) => { - return Err(format!("Error lexing d128 number: {}", number_string)); - } - }; - }, - "+" => tokens.push(Token::Operator(Plus)), - "-" => tokens.push(Token::Operator(Minus)), - "*" => tokens.push(Token::Operator(Multiply)), - "/" | "÷" => tokens.push(Token::Operator(Divide)), - "%" => tokens.push(Token::LexerKeyword(PercentChar)), - "^" => tokens.push(Token::Operator(Caret)), - "!" => tokens.push(Token::UnaryOperator(Factorial)), - "(" => { - lexer.left_paren_count += 1; - tokens.push(Token::Operator(LeftParen)); - }, - ")" => { - lexer.right_paren_count += 1; - tokens.push(Token::Operator(RightParen)); - }, - "π" => tokens.push(Token::Constant(Pi)), - "'" => tokens.push(Token::Unit(Foot)), - "\"" | "“" | "”" | "″" => tokens.push(Token::LexerKeyword(DoubleQuotes)), - _ => { - return Err(format!("Invalid character: {}", c)); - }, - } - Ok(()) + let tokens = &mut lexer.tokens; + match c { + value if value.trim().is_empty() => {}, + value if is_word_char_str(value) => { + parse_word(read_word(c, lexer).as_str(), lexer)?; + }, + value if is_numeric_str(value) => { + let mut number_string = value.to_owned(); + while let Some(number_char) = lexer.chars.peek() { + if is_numeric_str(number_char) { + number_string += number_char; + lexer.chars.next(); + } else { + break; + } + } + d128::set_status(decimal::Status::empty()); + match d128::from_str(&number_string) { + Ok(number) => { + if d128::get_status().is_empty() { + tokens.push(Token::Number(number)); + } else { + return Err(format!("Error lexing d128 number: {}", number_string)); + } + }, + Err(_e) => { + return Err(format!("Error lexing d128 number: {}", number_string)); + } + }; + }, + "+" => tokens.push(Token::Operator(Plus)), + "-" => tokens.push(Token::Operator(Minus)), + "*" => tokens.push(Token::Operator(Multiply)), + "/" | "÷" => tokens.push(Token::Operator(Divide)), + "%" => tokens.push(Token::LexerKeyword(PercentChar)), + "^" => tokens.push(Token::Operator(Caret)), + "!" => tokens.push(Token::UnaryOperator(Factorial)), + "(" => { + lexer.left_paren_count += 1; + tokens.push(Token::Operator(LeftParen)); + }, + ")" => { + lexer.right_paren_count += 1; + tokens.push(Token::Operator(RightParen)); + }, + "π" => tokens.push(Token::Constant(Pi)), + "'" => tokens.push(Token::Unit(Foot)), + "\"" | "“" | "”" | "″" => tokens.push(Token::LexerKeyword(DoubleQuotes)), + _ => { + return Err(format!("Invalid character: {}", c)); + }, + } + Ok(()) } fn parse_word_if_non_empty(word: &str, lexer: &mut Lexer) -> Result<(), String> { - match word { - "" => Ok(()), - _ => parse_word(word, lexer) - } + match word { + "" => Ok(()), + _ => parse_word(word, lexer) + } } fn parse_word(word: &str, lexer: &mut Lexer) -> Result<(), String> { - let token = match word { - "to" => Token::TextOperator(To), - "of" => Token::TextOperator(Of), + let token = match word { + "to" => Token::TextOperator(To), + "of" => Token::TextOperator(Of), - "hundred" => Token::NamedNumber(Hundred), - "thousand" => Token::NamedNumber(Thousand), - "mil" | "mill" | "million" => Token::NamedNumber(Million), - "bil" | "bill" | "billion" => Token::NamedNumber(Billion), - "tri" | "tril" | "trillion" => Token::NamedNumber(Trillion), - "quadrillion" => Token::NamedNumber(Quadrillion), - "quintillion" => Token::NamedNumber(Quintillion), - "sextillion" => Token::NamedNumber(Sextillion), - "septillion" => Token::NamedNumber(Septillion), - "octillion" => Token::NamedNumber(Octillion), - "nonillion" => Token::NamedNumber(Nonillion), - "decillion" => Token::NamedNumber(Decillion), - "undecillion" => Token::NamedNumber(Undecillion), - "duodecillion" => Token::NamedNumber(Duodecillion), - "tredecillion" => Token::NamedNumber(Tredecillion), - "quattuordecillion" => Token::NamedNumber(Quattuordecillion), - "quindecillion" => Token::NamedNumber(Quindecillion), - "sexdecillion" => Token::NamedNumber(Sexdecillion), - "septendecillion" => Token::NamedNumber(Septendecillion), - "octodecillion" => Token::NamedNumber(Octodecillion), - "novemdecillion" => Token::NamedNumber(Novemdecillion), - "vigintillion" => Token::NamedNumber(Vigintillion), - "centillion" => Token::NamedNumber(Centillion), - "googol" => Token::NamedNumber(Googol), + "hundred" => Token::NamedNumber(Hundred), + "thousand" => Token::NamedNumber(Thousand), + "mil" | "mill" | "million" => Token::NamedNumber(Million), + "bil" | "bill" | "billion" => Token::NamedNumber(Billion), + "tri" | "tril" | "trillion" => Token::NamedNumber(Trillion), + "quadrillion" => Token::NamedNumber(Quadrillion), + "quintillion" => Token::NamedNumber(Quintillion), + "sextillion" => Token::NamedNumber(Sextillion), + "septillion" => Token::NamedNumber(Septillion), + "octillion" => Token::NamedNumber(Octillion), + "nonillion" => Token::NamedNumber(Nonillion), + "decillion" => Token::NamedNumber(Decillion), + "undecillion" => Token::NamedNumber(Undecillion), + "duodecillion" => Token::NamedNumber(Duodecillion), + "tredecillion" => Token::NamedNumber(Tredecillion), + "quattuordecillion" => Token::NamedNumber(Quattuordecillion), + "quindecillion" => Token::NamedNumber(Quindecillion), + "sexdecillion" => Token::NamedNumber(Sexdecillion), + "septendecillion" => Token::NamedNumber(Septendecillion), + "octodecillion" => Token::NamedNumber(Octodecillion), + "novemdecillion" => Token::NamedNumber(Novemdecillion), + "vigintillion" => Token::NamedNumber(Vigintillion), + "centillion" => Token::NamedNumber(Centillion), + "googol" => Token::NamedNumber(Googol), - "pi" => Token::Constant(Pi), - "e" => Token::Constant(E), + "pi" => Token::Constant(Pi), + "e" => Token::Constant(E), - "plus" => Token::Operator(Plus), - "minus" => Token::Operator(Minus), - "times" => Token::Operator(Multiply), - "multiplied" => { - match read_word("", lexer).as_str() { - "by" => Token::Operator(Multiply), - string => return Err(format!("Invalid string: {}", string)), - } - }, - "divided" => { - match read_word("", lexer).as_str() { - "by" => Token::Operator(Divide), - string => return Err(format!("Invalid string: {}", string)), - } - }, - "mod" => Token::Operator(Modulo), + "plus" => Token::Operator(Plus), + "minus" => Token::Operator(Minus), + "times" => Token::Operator(Multiply), + "multiplied" => { + match read_word("", lexer).as_str() { + "by" => Token::Operator(Multiply), + string => return Err(format!("Invalid string: {}", string)), + } + }, + "divided" => { + match read_word("", lexer).as_str() { + "by" => Token::Operator(Divide), + string => return Err(format!("Invalid string: {}", string)), + } + }, + "mod" => Token::Operator(Modulo), - "sqrt" => Token::FunctionIdentifier(Sqrt), - "cbrt" => Token::FunctionIdentifier(Cbrt), + "sqrt" => Token::FunctionIdentifier(Sqrt), + "cbrt" => Token::FunctionIdentifier(Cbrt), - "log" => Token::FunctionIdentifier(Log), - "ln" => Token::FunctionIdentifier(Ln), - "exp" => Token::FunctionIdentifier(Exp), + "log" => Token::FunctionIdentifier(Log), + "ln" => Token::FunctionIdentifier(Ln), + "exp" => Token::FunctionIdentifier(Exp), - "round" | "rint" => Token::FunctionIdentifier(Round), - "ceil" => Token::FunctionIdentifier(Ceil), - "floor" => Token::FunctionIdentifier(Floor), - "abs" | "fabs" => Token::FunctionIdentifier(Abs), + "round" | "rint" => Token::FunctionIdentifier(Round), + "ceil" => Token::FunctionIdentifier(Ceil), + "floor" => Token::FunctionIdentifier(Floor), + "abs" | "fabs" => Token::FunctionIdentifier(Abs), - "sin" => Token::FunctionIdentifier(Sin), - "cos" => Token::FunctionIdentifier(Cos), - "tan" => Token::FunctionIdentifier(Tan), + "sin" => Token::FunctionIdentifier(Sin), + "cos" => Token::FunctionIdentifier(Cos), + "tan" => Token::FunctionIdentifier(Tan), - "per" => Token::LexerKeyword(Per), - "hg" => Token::LexerKeyword(Hg), // can be hectogram or mercury + "per" => Token::LexerKeyword(Per), + "hg" => Token::LexerKeyword(Hg), // can be hectogram or mercury - "ns" | "nanosec" | "nanosecs" | "nanosecond" | "nanoseconds" => Token::Unit(Nanosecond), - // µ and μ are two different characters - "µs" | "μs" | "microsec" | "microsecs" | "microsecond" | "microseconds" => Token::Unit(Microsecond), - "ms" | "millisec" | "millisecs" | "millisecond" | "milliseconds" => Token::Unit(Millisecond), - "s" | "sec" | "secs" | "second" | "seconds" => Token::Unit(Second), - "min" | "mins" | "minute" | "minutes" => Token::Unit(Minute), - "h" | "hr" | "hrs" | "hour" | "hours" => Token::Unit(Hour), - "day" | "days" => Token::Unit(Day), - "wk" | "wks" | "week" | "weeks" => Token::Unit(Week), - "mo" | "mos" | "month" | "months" => Token::Unit(Month), - "q" | "quarter" | "quarters" => Token::Unit(Quarter), - "yr" | "yrs" | "year" | "years" => Token::Unit(Year), - "decade" | "decades" => Token::Unit(Decade), - "century" | "centuries" => Token::Unit(Century), - "millenium" | "millenia" | "milleniums" => Token::Unit(Millenium), + "ns" | "nanosec" | "nanosecs" | "nanosecond" | "nanoseconds" => Token::Unit(Nanosecond), + // µ and μ are two different characters + "µs" | "μs" | "microsec" | "microsecs" | "microsecond" | "microseconds" => Token::Unit(Microsecond), + "ms" | "millisec" | "millisecs" | "millisecond" | "milliseconds" => Token::Unit(Millisecond), + "s" | "sec" | "secs" | "second" | "seconds" => Token::Unit(Second), + "min" | "mins" | "minute" | "minutes" => Token::Unit(Minute), + "h" | "hr" | "hrs" | "hour" | "hours" => Token::Unit(Hour), + "day" | "days" => Token::Unit(Day), + "wk" | "wks" | "week" | "weeks" => Token::Unit(Week), + "mo" | "mos" | "month" | "months" => Token::Unit(Month), + "q" | "quarter" | "quarters" => Token::Unit(Quarter), + "yr" | "yrs" | "year" | "years" => Token::Unit(Year), + "decade" | "decades" => Token::Unit(Decade), + "century" | "centuries" => Token::Unit(Century), + "millenium" | "millenia" | "milleniums" => Token::Unit(Millenium), - "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => Token::Unit(Millimeter), - "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => Token::Unit(Centimeter), - "dm" | "decimeter" | "decimeters" | "decimetre" | "decimetres" => Token::Unit(Decimeter), - "m" | "meter" | "meters" | "metre" | "metres" => Token::Unit(Meter), - "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => Token::Unit(Kilometer), - "in" => Token::LexerKeyword(In), - "inch" | "inches" => Token::Unit(Inch), - "ft" | "foot" | "feet" => Token::Unit(Foot), - "yd" | "yard" | "yards" => Token::Unit(Yard), - "mi" | "mile" | "miles" => Token::Unit(Mile), - "nmi" => Token::Unit(NauticalMile), - "nautical" => { - match read_word("", lexer).as_str() { - "mile" | "miles" => Token::Unit(NauticalMile), - string => return Err(format!("Invalid string: {}", string)), - } - }, - "ly" | "lightyear" | "lightyears" => Token::Unit(LightYear), - "lightsec" | "lightsecs" | "lightsecond" | "lightseconds" => Token::Unit(LightSecond), - "light" => { - match read_word("", lexer).as_str() { - "yr" | "yrs" | "year" | "years" => Token::Unit(LightYear), - "sec" | "secs" | "second" | "seconds" => Token::Unit(LightSecond), - string => return Err(format!("Invalid string: {}", string)), - } - } + "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => Token::Unit(Millimeter), + "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => Token::Unit(Centimeter), + "dm" | "decimeter" | "decimeters" | "decimetre" | "decimetres" => Token::Unit(Decimeter), + "m" | "meter" | "meters" | "metre" | "metres" => Token::Unit(Meter), + "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => Token::Unit(Kilometer), + "in" => Token::LexerKeyword(In), + "inch" | "inches" => Token::Unit(Inch), + "ft" | "foot" | "feet" => Token::Unit(Foot), + "yd" | "yard" | "yards" => Token::Unit(Yard), + "mi" | "mile" | "miles" => Token::Unit(Mile), + "nmi" => Token::Unit(NauticalMile), + "nautical" => { + match read_word("", lexer).as_str() { + "mile" | "miles" => Token::Unit(NauticalMile), + string => return Err(format!("Invalid string: {}", string)), + } + }, + "ly" | "lightyear" | "lightyears" => Token::Unit(LightYear), + "lightsec" | "lightsecs" | "lightsecond" | "lightseconds" => Token::Unit(LightSecond), + "light" => { + match read_word("", lexer).as_str() { + "yr" | "yrs" | "year" | "years" => Token::Unit(LightYear), + "sec" | "secs" | "second" | "seconds" => Token::Unit(LightSecond), + string => return Err(format!("Invalid string: {}", string)), + } + } - "sqmm" | "mm2" | "millimeter2" | "millimeters2" | "millimetre2" | "millimetres2" => Token::Unit(SquareMillimeter), - "sqcm" | "cm2" | "centimeter2" | "centimeters2" | "centimetre2" | "centimetres2" => Token::Unit(SquareCentimeter), - "sqdm" | "dm2" | "decimeter2" | "decimeters2" | "decimetre2" | "decimetres2" => Token::Unit(SquareDecimeter), - "sqm" | "m2" | "meter2" | "meters2" | "metre2" | "metres2" => Token::Unit(SquareMeter), - "sqkm" | "km2" | "kilometer2" | "kilometers2" | "kilometre2" | "kilometres2" => Token::Unit(SquareKilometer), - "sqin" | "in2" | "inch2" | "inches2" => Token::Unit(SquareInch), - "sqft" | "ft2" | "foot2" | "feet2" => Token::Unit(SquareFoot), - "sqyd" | "yd2" | "yard2" | "yards2" => Token::Unit(SquareYard), - "sqmi" | "mi2" | "mile2" | "miles2" => Token::Unit(SquareMile), - "sq" | "square" => { - match read_word("", lexer).as_str() { - "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => Token::Unit(SquareMillimeter), - "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => Token::Unit(SquareCentimeter), - "dm" | "decimeter" | "decimeters" | "decimetre" | "decimetres" => Token::Unit(SquareDecimeter), - "m" | "meter" | "meters" | "metre" | "metres" => Token::Unit(SquareMeter), - "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => Token::Unit(SquareKilometer), - "in" | "inch" | "inches" => Token::Unit(SquareInch), - "ft" | "foot" | "feet" => Token::Unit(SquareFoot), - "yd" | "yard" | "yards" => Token::Unit(SquareYard), - "mi" | "mile" | "miles" => Token::Unit(SquareMile), - string => return Err(format!("Invalid string: {}", string)), - } - } - "are" | "ares" => Token::Unit(Are), - "decare" | "decares" => Token::Unit(Decare), - "ha" | "hectare" | "hectares" => Token::Unit(Hectare), - "acre" | "acres" => Token::Unit(Acre), + "sqmm" | "mm2" | "millimeter2" | "millimeters2" | "millimetre2" | "millimetres2" => Token::Unit(SquareMillimeter), + "sqcm" | "cm2" | "centimeter2" | "centimeters2" | "centimetre2" | "centimetres2" => Token::Unit(SquareCentimeter), + "sqdm" | "dm2" | "decimeter2" | "decimeters2" | "decimetre2" | "decimetres2" => Token::Unit(SquareDecimeter), + "sqm" | "m2" | "meter2" | "meters2" | "metre2" | "metres2" => Token::Unit(SquareMeter), + "sqkm" | "km2" | "kilometer2" | "kilometers2" | "kilometre2" | "kilometres2" => Token::Unit(SquareKilometer), + "sqin" | "in2" | "inch2" | "inches2" => Token::Unit(SquareInch), + "sqft" | "ft2" | "foot2" | "feet2" => Token::Unit(SquareFoot), + "sqyd" | "yd2" | "yard2" | "yards2" => Token::Unit(SquareYard), + "sqmi" | "mi2" | "mile2" | "miles2" => Token::Unit(SquareMile), + "sq" | "square" => { + match read_word("", lexer).as_str() { + "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => Token::Unit(SquareMillimeter), + "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => Token::Unit(SquareCentimeter), + "dm" | "decimeter" | "decimeters" | "decimetre" | "decimetres" => Token::Unit(SquareDecimeter), + "m" | "meter" | "meters" | "metre" | "metres" => Token::Unit(SquareMeter), + "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => Token::Unit(SquareKilometer), + "in" | "inch" | "inches" => Token::Unit(SquareInch), + "ft" | "foot" | "feet" => Token::Unit(SquareFoot), + "yd" | "yard" | "yards" => Token::Unit(SquareYard), + "mi" | "mile" | "miles" => Token::Unit(SquareMile), + string => return Err(format!("Invalid string: {}", string)), + } + } + "are" | "ares" => Token::Unit(Are), + "decare" | "decares" => Token::Unit(Decare), + "ha" | "hectare" | "hectares" => Token::Unit(Hectare), + "acre" | "acres" => Token::Unit(Acre), - "mm3" | "millimeter3" | "millimeters3" | "millimetre3" | "millimetres3" => Token::Unit(CubicMillimeter), - "cm3" | "centimeter3" | "centimeters3" | "centimetre3" | "centimetres3" => Token::Unit(CubicCentimeter), - "dm3" | "decimeter3" | "decimeters3" | "decimetre3" | "decimetres3" => Token::Unit(CubicDecimeter), - "m3" | "meter3" | "meters3" | "metre3" | "metres3" => Token::Unit(CubicMeter), - "km3" | "kilometer3" | "kilometers3" | "kilometre3" | "kilometres3" => Token::Unit(CubicKilometer), - "inc3" | "inch3" | "inches3" => Token::Unit(CubicInch), - "ft3" | "foot3" | "feet3" => Token::Unit(CubicFoot), - "yd3" | "yard3" | "yards3" => Token::Unit(CubicYard), - "mi3" | "mile3" | "miles3" => Token::Unit(CubicMile), - "cubic" => { - match read_word("", lexer).as_str() { - "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => Token::Unit(CubicMillimeter), - "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => Token::Unit(CubicCentimeter), - "dm" | "decimeter" | "decimeters" | "decimetre" | "decimetres" => Token::Unit(CubicDecimeter), - "m" | "meter" | "meters" | "metre" | "metres" => Token::Unit(CubicMeter), - "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => Token::Unit(CubicKilometer), - "in" | "inch" | "inches" => Token::Unit(CubicInch), - "ft" | "foot" | "feet" => Token::Unit(CubicFoot), - "yd" | "yard" | "yards" => Token::Unit(CubicYard), - "mi" | "mile" | "miles" => Token::Unit(CubicMile), - string => return Err(format!("Invalid string: {}", string)), - } - }, - "ml" | "milliliter" | "milliliters" | "millilitre" | "millilitres" => Token::Unit(Milliliter), - "cl" | "centiliter" | "centiliters" | "centilitre" | "centilitres" => Token::Unit(Centiliter), - "dl" | "deciliter" | "deciliters" | "decilitre" | "decilitres" => Token::Unit(Deciliter), - "l" | "liter" | "liters" | "litre" | "litres" => Token::Unit(Liter), - "ts" | "tsp" | "tspn" | "tspns" | "teaspoon" | "teaspoons" => Token::Unit(Teaspoon), - "tbs" | "tbsp" | "tablespoon" | "tablespoons" => Token::Unit(Tablespoon), - "floz" => Token::Unit(FluidOunce), - "fl" | "fluid" => { - match read_word("", lexer).as_str() { - "oz" | "ounce" | "ounces" => Token::Unit(FluidOunce), - string => return Err(format!("Invalid string: {}", string)), - } - }, - "cup" | "cups" => Token::Unit(Cup), - "pt" | "pint" | "pints" => Token::Unit(Pint), - "qt" | "quart" | "quarts" => Token::Unit(Quart), - "gal" | "gallon" | "gallons" => Token::Unit(Gallon), - "bbl" => Token::Unit(OilBarrel), - "oil" => { - match read_word("", lexer).as_str() { - "barrel" | "barrels" => Token::Unit(OilBarrel), - string => return Err(format!("Invalid string: {}", string)), - } - }, + "mm3" | "millimeter3" | "millimeters3" | "millimetre3" | "millimetres3" => Token::Unit(CubicMillimeter), + "cm3" | "centimeter3" | "centimeters3" | "centimetre3" | "centimetres3" => Token::Unit(CubicCentimeter), + "dm3" | "decimeter3" | "decimeters3" | "decimetre3" | "decimetres3" => Token::Unit(CubicDecimeter), + "m3" | "meter3" | "meters3" | "metre3" | "metres3" => Token::Unit(CubicMeter), + "km3" | "kilometer3" | "kilometers3" | "kilometre3" | "kilometres3" => Token::Unit(CubicKilometer), + "inc3" | "inch3" | "inches3" => Token::Unit(CubicInch), + "ft3" | "foot3" | "feet3" => Token::Unit(CubicFoot), + "yd3" | "yard3" | "yards3" => Token::Unit(CubicYard), + "mi3" | "mile3" | "miles3" => Token::Unit(CubicMile), + "cubic" => { + match read_word("", lexer).as_str() { + "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => Token::Unit(CubicMillimeter), + "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => Token::Unit(CubicCentimeter), + "dm" | "decimeter" | "decimeters" | "decimetre" | "decimetres" => Token::Unit(CubicDecimeter), + "m" | "meter" | "meters" | "metre" | "metres" => Token::Unit(CubicMeter), + "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => Token::Unit(CubicKilometer), + "in" | "inch" | "inches" => Token::Unit(CubicInch), + "ft" | "foot" | "feet" => Token::Unit(CubicFoot), + "yd" | "yard" | "yards" => Token::Unit(CubicYard), + "mi" | "mile" | "miles" => Token::Unit(CubicMile), + string => return Err(format!("Invalid string: {}", string)), + } + }, + "ml" | "milliliter" | "milliliters" | "millilitre" | "millilitres" => Token::Unit(Milliliter), + "cl" | "centiliter" | "centiliters" | "centilitre" | "centilitres" => Token::Unit(Centiliter), + "dl" | "deciliter" | "deciliters" | "decilitre" | "decilitres" => Token::Unit(Deciliter), + "l" | "liter" | "liters" | "litre" | "litres" => Token::Unit(Liter), + "ts" | "tsp" | "tspn" | "tspns" | "teaspoon" | "teaspoons" => Token::Unit(Teaspoon), + "tbs" | "tbsp" | "tablespoon" | "tablespoons" => Token::Unit(Tablespoon), + "floz" => Token::Unit(FluidOunce), + "fl" | "fluid" => { + match read_word("", lexer).as_str() { + "oz" | "ounce" | "ounces" => Token::Unit(FluidOunce), + string => return Err(format!("Invalid string: {}", string)), + } + }, + "cup" | "cups" => Token::Unit(Cup), + "pt" | "pint" | "pints" => Token::Unit(Pint), + "qt" | "quart" | "quarts" => Token::Unit(Quart), + "gal" | "gallon" | "gallons" => Token::Unit(Gallon), + "bbl" => Token::Unit(OilBarrel), + "oil" => { + match read_word("", lexer).as_str() { + "barrel" | "barrels" => Token::Unit(OilBarrel), + string => return Err(format!("Invalid string: {}", string)), + } + }, - "metric" => { - match read_word("", lexer).as_str() { - "ton" | "tons" | "tonne" | "tonnes" => Token::Unit(MetricTon), - "hp" | "hps" | "horsepower" | "horsepowers" => Token::Unit(MetricHorsepower), - string => return Err(format!("Invalid string: {}", string)), - } - }, + "metric" => { + match read_word("", lexer).as_str() { + "ton" | "tons" | "tonne" | "tonnes" => Token::Unit(MetricTon), + "hp" | "hps" | "horsepower" | "horsepowers" => Token::Unit(MetricHorsepower), + string => return Err(format!("Invalid string: {}", string)), + } + }, - "mg" | "milligram" | "milligrams" => Token::Unit(Milligram), - "g" | "gram" | "grams" => Token::Unit(Gram), - "hectogram" | "hectograms" => Token::Unit(Hectogram), - "kg" | "kilo" | "kilos" | "kilogram" | "kilograms" => Token::Unit(Kilogram), - "t" | "tonne" | "tonnes" => Token::Unit(MetricTon), - "oz" | "ounces" => Token::Unit(Ounce), - "lb" | "lbs" => Token::Unit(Pound), - "pound" | "pounds" => { - match lexer.chars.next() { - Some("-") => { - match read_word_plain(&mut lexer.chars).as_str() { - "force" => Token::LexerKeyword(PoundForce), - other => { - lexer.tokens.push(Token::Unit(Pound)); - lexer.tokens.push(Token::Operator(Minus)); - parse_word_if_non_empty(other, lexer)?; - return Ok(()); - } - } - }, - Some(c) => { - lexer.tokens.push(Token::Unit(Pound)); - parse_token(c, lexer)?; - return Ok(()); - }, - None => { - lexer.tokens.push(Token::Unit(Pound)); - return Ok(()); - }, - } - }, - "stone" | "stones" => Token::Unit(Stone), - "st" | "ton" | "tons" => Token::Unit(ShortTon), - "short" => { - match read_word("", lexer).as_str() { - "ton" | "tons" | "tonne" | "tonnes" => Token::Unit(ShortTon), - string => return Err(format!("Invalid string: {}", string)), - } - }, - "lt" => Token::Unit(LongTon), - "long" => { - match read_word("", lexer).as_str() { - "ton" | "tons" | "tonne" | "tonnes" => Token::Unit(LongTon), - string => return Err(format!("Invalid string: {}", string)), - } - }, + "mg" | "milligram" | "milligrams" => Token::Unit(Milligram), + "g" | "gram" | "grams" => Token::Unit(Gram), + "hectogram" | "hectograms" => Token::Unit(Hectogram), + "kg" | "kilo" | "kilos" | "kilogram" | "kilograms" => Token::Unit(Kilogram), + "t" | "tonne" | "tonnes" => Token::Unit(MetricTon), + "oz" | "ounces" => Token::Unit(Ounce), + "lb" | "lbs" => Token::Unit(Pound), + "pound" | "pounds" => { + match lexer.chars.next() { + Some("-") => { + match read_word_plain(&mut lexer.chars).as_str() { + "force" => Token::LexerKeyword(PoundForce), + other => { + lexer.tokens.push(Token::Unit(Pound)); + lexer.tokens.push(Token::Operator(Minus)); + parse_word_if_non_empty(other, lexer)?; + return Ok(()); + } + } + }, + Some(c) => { + lexer.tokens.push(Token::Unit(Pound)); + parse_token(c, lexer)?; + return Ok(()); + }, + None => { + lexer.tokens.push(Token::Unit(Pound)); + return Ok(()); + }, + } + }, + "stone" | "stones" => Token::Unit(Stone), + "st" | "ton" | "tons" => Token::Unit(ShortTon), + "short" => { + match read_word("", lexer).as_str() { + "ton" | "tons" | "tonne" | "tonnes" => Token::Unit(ShortTon), + string => return Err(format!("Invalid string: {}", string)), + } + }, + "lt" => Token::Unit(LongTon), + "long" => { + match read_word("", lexer).as_str() { + "ton" | "tons" | "tonne" | "tonnes" => Token::Unit(LongTon), + string => return Err(format!("Invalid string: {}", string)), + } + }, - "bit" | "bits" => Token::Unit(Bit), - "kbit" | "kilobit" | "kilobits" => Token::Unit(Kilobit), - "mbit" | "megabit" | "megabits" => Token::Unit(Megabit), - "gbit" | "gigabit" | "gigabits" => Token::Unit(Gigabit), - "tbit" | "terabit" | "terabits" => Token::Unit(Terabit), - "pbit" | "petabit" | "petabits" => Token::Unit(Petabit), - "ebit" | "exabit" | "exabits" => Token::Unit(Exabit), - "zbit" | "zettabit" | "zettabits" => Token::Unit(Zettabit), - "ybit" | "yottabit" | "yottabits" => Token::Unit(Yottabit), - "kibit" | "kibibit" | "kibibits" => Token::Unit(Kibibit), - "mibit" | "mebibit" | "mebibits" => Token::Unit(Mebibit), - "gibit" | "gibibit" | "gibibits" => Token::Unit(Gibibit), - "tibit" | "tebibit" | "tebibits" => Token::Unit(Tebibit), - "pibit" | "pebibit" | "pebibits" => Token::Unit(Pebibit), - "eibit" | "exbibit" | "exbibits" => Token::Unit(Exbibit), - "zibit" | "zebibit" | "zebibits" => Token::Unit(Zebibit), - "yibit" | "yobibit" | "yobibits" => Token::Unit(Yobibit), - "byte" | "bytes" => Token::Unit(Byte), - "kb" | "kilobyte" | "kilobytes" => Token::Unit(Kilobyte), - "mb" | "megabyte" | "megabytes" => Token::Unit(Megabyte), - "gb" | "gigabyte" | "gigabytes" => Token::Unit(Gigabyte), - "tb" | "terabyte" | "terabytes" => Token::Unit(Terabyte), - "pb" | "petabyte" | "petabytes" => Token::Unit(Petabyte), - "eb" | "exabyte" | "exabytes" => Token::Unit(Exabyte), - "zb" | "zettabyte" | "zettabytes" => Token::Unit(Zettabyte), - "yb" | "yottabyte" | "yottabytes" => Token::Unit(Yottabyte), - "kib" | "kibibyte" | "kibibytes" => Token::Unit(Kibibyte), - "mib" | "mebibyte" | "mebibytes" => Token::Unit(Mebibyte), - "gib" | "gibibyte" | "gibibytes" => Token::Unit(Gibibyte), - "tib" | "tebibyte" | "tebibytes" => Token::Unit(Tebibyte), - "pib" | "pebibyte" | "pebibytes" => Token::Unit(Pebibyte), - "eib" | "exbibyte" | "exbibytes" => Token::Unit(Exbibyte), - "zib" | "zebibyte" | "zebibytes" => Token::Unit(Zebibyte), - "yib" | "yobibyte" | "yobibytes" => Token::Unit(Yobibyte), + "bit" | "bits" => Token::Unit(Bit), + "kbit" | "kilobit" | "kilobits" => Token::Unit(Kilobit), + "mbit" | "megabit" | "megabits" => Token::Unit(Megabit), + "gbit" | "gigabit" | "gigabits" => Token::Unit(Gigabit), + "tbit" | "terabit" | "terabits" => Token::Unit(Terabit), + "pbit" | "petabit" | "petabits" => Token::Unit(Petabit), + "ebit" | "exabit" | "exabits" => Token::Unit(Exabit), + "zbit" | "zettabit" | "zettabits" => Token::Unit(Zettabit), + "ybit" | "yottabit" | "yottabits" => Token::Unit(Yottabit), + "kibit" | "kibibit" | "kibibits" => Token::Unit(Kibibit), + "mibit" | "mebibit" | "mebibits" => Token::Unit(Mebibit), + "gibit" | "gibibit" | "gibibits" => Token::Unit(Gibibit), + "tibit" | "tebibit" | "tebibits" => Token::Unit(Tebibit), + "pibit" | "pebibit" | "pebibits" => Token::Unit(Pebibit), + "eibit" | "exbibit" | "exbibits" => Token::Unit(Exbibit), + "zibit" | "zebibit" | "zebibits" => Token::Unit(Zebibit), + "yibit" | "yobibit" | "yobibits" => Token::Unit(Yobibit), + "byte" | "bytes" => Token::Unit(Byte), + "kb" | "kilobyte" | "kilobytes" => Token::Unit(Kilobyte), + "mb" | "megabyte" | "megabytes" => Token::Unit(Megabyte), + "gb" | "gigabyte" | "gigabytes" => Token::Unit(Gigabyte), + "tb" | "terabyte" | "terabytes" => Token::Unit(Terabyte), + "pb" | "petabyte" | "petabytes" => Token::Unit(Petabyte), + "eb" | "exabyte" | "exabytes" => Token::Unit(Exabyte), + "zb" | "zettabyte" | "zettabytes" => Token::Unit(Zettabyte), + "yb" | "yottabyte" | "yottabytes" => Token::Unit(Yottabyte), + "kib" | "kibibyte" | "kibibytes" => Token::Unit(Kibibyte), + "mib" | "mebibyte" | "mebibytes" => Token::Unit(Mebibyte), + "gib" | "gibibyte" | "gibibytes" => Token::Unit(Gibibyte), + "tib" | "tebibyte" | "tebibytes" => Token::Unit(Tebibyte), + "pib" | "pebibyte" | "pebibytes" => Token::Unit(Pebibyte), + "eib" | "exbibyte" | "exbibytes" => Token::Unit(Exbibyte), + "zib" | "zebibyte" | "zebibytes" => Token::Unit(Zebibyte), + "yib" | "yobibyte" | "yobibytes" => Token::Unit(Yobibyte), - "bps" => Token::Unit(BitsPerSecond), - "kbps" => Token::Unit(KilobitsPerSecond), - "mbps" => Token::Unit(MegabitsPerSecond), - "gbps" => Token::Unit(GigabitsPerSecond), - "tbps" => Token::Unit(TerabitsPerSecond), - "pbps" => Token::Unit(PetabitsPerSecond), - "ebps" => Token::Unit(ExabitsPerSecond), - "zbps" => Token::Unit(ZettabitsPerSecond), - "ybps" => Token::Unit(YottabitsPerSecond), + "bps" => Token::Unit(BitsPerSecond), + "kbps" => Token::Unit(KilobitsPerSecond), + "mbps" => Token::Unit(MegabitsPerSecond), + "gbps" => Token::Unit(GigabitsPerSecond), + "tbps" => Token::Unit(TerabitsPerSecond), + "pbps" => Token::Unit(PetabitsPerSecond), + "ebps" => Token::Unit(ExabitsPerSecond), + "zbps" => Token::Unit(ZettabitsPerSecond), + "ybps" => Token::Unit(YottabitsPerSecond), - "millijoule" | "millijoules" => Token::Unit(Millijoule), - "j"| "joule" | "joules" => Token::Unit(Joule), - "nm" => Token::Unit(NewtonMeter), - "newton" => { - match lexer.chars.next() { - Some("-") => { - match read_word_plain(&mut lexer.chars).as_str() { - "meter" | "meters" | "metre" | "metres" => Token::Unit(NewtonMeter), - string => return Err(format!("Invalid string: {}", string)), - } - }, - Some(c) => { - match read_word(c, lexer).as_str() { - "meter" | "meters" | "metre" | "metres" => Token::Unit(NewtonMeter), - string => return Err(format!("Invalid string: {}", string)), - } - }, - None => return Err(format!("Invalid string: {}", word)), - } - }, - "kj" | "kilojoule" | "kilojoules" => Token::Unit(Kilojoule), - "mj" | "megajoule" | "megajoules" => Token::Unit(Megajoule), - "gj" | "gigajoule" | "gigajoules" => Token::Unit(Gigajoule), - "tj" | "terajoule" | "terajoules" => Token::Unit(Terajoule), - "cal" | "calorie" | "calories" => Token::Unit(Calorie), - "kcal" | "kilocalorie" | "kilocalories" => Token::Unit(KiloCalorie), - "btu" => Token::Unit(BritishThermalUnit), - "british" => { - match read_word("", lexer).as_str() { - "thermal" => { - match read_word("", lexer).as_str() { - "unit" | "units" => Token::Unit(BritishThermalUnit), - string => return Err(format!("Invalid string: {}", string)), - } - }, - string => return Err(format!("Invalid string: {}", string)), - } - }, - "wh" => Token::Unit(WattHour), - "kwh" => Token::Unit(KilowattHour), - "mwh" => Token::Unit(MegawattHour), - "gwh" => Token::Unit(GigawattHour), - "twh" => Token::Unit(TerawattHour), - "pwh" => Token::Unit(PetawattHour), + "millijoule" | "millijoules" => Token::Unit(Millijoule), + "j"| "joule" | "joules" => Token::Unit(Joule), + "nm" => Token::Unit(NewtonMeter), + "newton" => { + match lexer.chars.next() { + Some("-") => { + match read_word_plain(&mut lexer.chars).as_str() { + "meter" | "meters" | "metre" | "metres" => Token::Unit(NewtonMeter), + string => return Err(format!("Invalid string: {}", string)), + } + }, + Some(c) => { + match read_word(c, lexer).as_str() { + "meter" | "meters" | "metre" | "metres" => Token::Unit(NewtonMeter), + string => return Err(format!("Invalid string: {}", string)), + } + }, + None => return Err(format!("Invalid string: {}", word)), + } + }, + "kj" | "kilojoule" | "kilojoules" => Token::Unit(Kilojoule), + "mj" | "megajoule" | "megajoules" => Token::Unit(Megajoule), + "gj" | "gigajoule" | "gigajoules" => Token::Unit(Gigajoule), + "tj" | "terajoule" | "terajoules" => Token::Unit(Terajoule), + "cal" | "calorie" | "calories" => Token::Unit(Calorie), + "kcal" | "kilocalorie" | "kilocalories" => Token::Unit(KiloCalorie), + "btu" => Token::Unit(BritishThermalUnit), + "british" => { + match read_word("", lexer).as_str() { + "thermal" => { + match read_word("", lexer).as_str() { + "unit" | "units" => Token::Unit(BritishThermalUnit), + string => return Err(format!("Invalid string: {}", string)), + } + }, + string => return Err(format!("Invalid string: {}", string)), + } + }, + "wh" => Token::Unit(WattHour), + "kwh" => Token::Unit(KilowattHour), + "mwh" => Token::Unit(MegawattHour), + "gwh" => Token::Unit(GigawattHour), + "twh" => Token::Unit(TerawattHour), + "pwh" => Token::Unit(PetawattHour), - "milliwatt" | "milliwatts" => Token::Unit(Milliwatt), - "w" | "watts" => Token::Unit(Watt), - "kw" | "kilowatts" => Token::Unit(Kilowatt), - "mw" | "megawatts" => Token::Unit(Megawatt), - "gw" | "gigawatts" => Token::Unit(Gigawatt), - "tw" | "terawatts" => Token::Unit(Terawatt), - "pw" | "petawatts" => Token::Unit(Petawatt), - "hp" | "hps" | "horsepower" | "horsepowers" => Token::Unit(Horsepower), - "mhp" | "hpm" => Token::Unit(MetricHorsepower), + "milliwatt" | "milliwatts" => Token::Unit(Milliwatt), + "w" | "watts" => Token::Unit(Watt), + "kw" | "kilowatts" => Token::Unit(Kilowatt), + "mw" | "megawatts" => Token::Unit(Megawatt), + "gw" | "gigawatts" => Token::Unit(Gigawatt), + "tw" | "terawatts" => Token::Unit(Terawatt), + "pw" | "petawatts" => Token::Unit(Petawatt), + "hp" | "hps" | "horsepower" | "horsepowers" => Token::Unit(Horsepower), + "mhp" | "hpm" => Token::Unit(MetricHorsepower), - "watt" => { - match read_word("", lexer).as_str() { - "hr" | "hrs" | "hour" | "hours" => Token::Unit(WattHour), - other => { - lexer.tokens.push(Token::Unit(Watt)); - parse_word_if_non_empty(other, lexer)?; - return Ok(()); - }, - } - } - "kilowatt" => { - match read_word("", lexer).as_str() { - "hr" | "hrs" | "hour" | "hours" => Token::Unit(KilowattHour), - other => { - lexer.tokens.push(Token::Unit(Kilowatt)); - parse_word_if_non_empty(other, lexer)?; - return Ok(()); - }, - } - } - "megawatt" => { - match read_word("", lexer).as_str() { - "hr" | "hrs" | "hour" | "hours" => Token::Unit(MegawattHour), - other => { - lexer.tokens.push(Token::Unit(Megawatt)); - parse_word_if_non_empty(other, lexer)?; - return Ok(()); - }, - } - } - "gigawatt" => { - match read_word("", lexer).as_str() { - "hr" | "hrs" | "hour" | "hours" => Token::Unit(GigawattHour), - other => { - lexer.tokens.push(Token::Unit(Gigawatt)); - parse_word_if_non_empty(other, lexer)?; - return Ok(()); - }, - } - } - "terawatt" => { - match read_word("", lexer).as_str() { - "hr" | "hrs" | "hour" | "hours" => Token::Unit(TerawattHour), - other => { - lexer.tokens.push(Token::Unit(Terawatt)); - parse_word_if_non_empty(other, lexer)?; - return Ok(()); - }, - } - } - "petawatt" => { - match read_word("", lexer).as_str() { - "hr" | "hrs" | "hour" | "hours" => Token::Unit(PetawattHour), - other => { - lexer.tokens.push(Token::Unit(Petawatt)); - parse_word_if_non_empty(other, lexer)?; - return Ok(()); - }, - } - } + "watt" => { + match read_word("", lexer).as_str() { + "hr" | "hrs" | "hour" | "hours" => Token::Unit(WattHour), + other => { + lexer.tokens.push(Token::Unit(Watt)); + parse_word_if_non_empty(other, lexer)?; + return Ok(()); + }, + } + } + "kilowatt" => { + match read_word("", lexer).as_str() { + "hr" | "hrs" | "hour" | "hours" => Token::Unit(KilowattHour), + other => { + lexer.tokens.push(Token::Unit(Kilowatt)); + parse_word_if_non_empty(other, lexer)?; + return Ok(()); + }, + } + } + "megawatt" => { + match read_word("", lexer).as_str() { + "hr" | "hrs" | "hour" | "hours" => Token::Unit(MegawattHour), + other => { + lexer.tokens.push(Token::Unit(Megawatt)); + parse_word_if_non_empty(other, lexer)?; + return Ok(()); + }, + } + } + "gigawatt" => { + match read_word("", lexer).as_str() { + "hr" | "hrs" | "hour" | "hours" => Token::Unit(GigawattHour), + other => { + lexer.tokens.push(Token::Unit(Gigawatt)); + parse_word_if_non_empty(other, lexer)?; + return Ok(()); + }, + } + } + "terawatt" => { + match read_word("", lexer).as_str() { + "hr" | "hrs" | "hour" | "hours" => Token::Unit(TerawattHour), + other => { + lexer.tokens.push(Token::Unit(Terawatt)); + parse_word_if_non_empty(other, lexer)?; + return Ok(()); + }, + } + } + "petawatt" => { + match read_word("", lexer).as_str() { + "hr" | "hrs" | "hour" | "hours" => Token::Unit(PetawattHour), + other => { + lexer.tokens.push(Token::Unit(Petawatt)); + parse_word_if_non_empty(other, lexer)?; + return Ok(()); + }, + } + } - "ma" | "milliamp" | "milliamps" | "milliampere" | "milliamperes" => Token::Unit(Milliampere), - "a" | "amp" | "amps" | "ampere" | "amperes" => Token::Unit(Ampere), - "ka" | "kiloamp" | "kiloamps" | "kiloampere" | "kiloamperes" => Token::Unit(Kiloampere), - "bi" | "biot" | "biots" | "aba" | "abampere" | "abamperes" => Token::Unit(Abampere), + "ma" | "milliamp" | "milliamps" | "milliampere" | "milliamperes" => Token::Unit(Milliampere), + "a" | "amp" | "amps" | "ampere" | "amperes" => Token::Unit(Ampere), + "ka" | "kiloamp" | "kiloamps" | "kiloampere" | "kiloamperes" => Token::Unit(Kiloampere), + "bi" | "biot" | "biots" | "aba" | "abampere" | "abamperes" => Token::Unit(Abampere), - "mΩ" | "mΩ" | "milliohm" | "milliohms" => Token::Unit(Milliohm), - "Ω" | "Ω" | "ohm" | "ohms" => Token::Unit(Ohm), - "kΩ" | "kΩ" | "kiloohm" | "kiloohms" => Token::Unit(Kiloohm), + "mΩ" | "mΩ" | "milliohm" | "milliohms" => Token::Unit(Milliohm), + "Ω" | "Ω" | "ohm" | "ohms" => Token::Unit(Ohm), + "kΩ" | "kΩ" | "kiloohm" | "kiloohms" => Token::Unit(Kiloohm), - "mv" | "millivolt" | "millivolts" => Token::Unit(Millivolt), - "v" | "volt" | "volts" => Token::Unit(Volt), - "kv" | "kilovolt" | "kilovolts" => Token::Unit(Kilovolt), + "mv" | "millivolt" | "millivolts" => Token::Unit(Millivolt), + "v" | "volt" | "volts" => Token::Unit(Volt), + "kv" | "kilovolt" | "kilovolts" => Token::Unit(Kilovolt), - // for pound-force per square inch - "lbf" => Token::LexerKeyword(PoundForce), - "force" => Token::LexerKeyword(Force), + // for pound-force per square inch + "lbf" => Token::LexerKeyword(PoundForce), + "force" => Token::LexerKeyword(Force), - "pa" | "pascal" | "pascals" => Token::Unit(Pascal), - "kpa" | "kilopascal" | "kilopascals" => Token::Unit(Kilopascal), - "atm" | "atms" | "atmosphere" | "atmospheres" => Token::Unit(Atmosphere), - "mbar" | "mbars" | "millibar" | "millibars" => Token::Unit(Millibar), - "bar" | "bars" => Token::Unit(Bar), - "inhg" => Token::Unit(InchOfMercury), - "mercury" => Token::LexerKeyword(Mercury), - "psi" => Token::Unit(PoundsPerSquareInch), - "torr" | "torrs" => Token::Unit(Torr), + "pa" | "pascal" | "pascals" => Token::Unit(Pascal), + "kpa" | "kilopascal" | "kilopascals" => Token::Unit(Kilopascal), + "atm" | "atms" | "atmosphere" | "atmospheres" => Token::Unit(Atmosphere), + "mbar" | "mbars" | "millibar" | "millibars" => Token::Unit(Millibar), + "bar" | "bars" => Token::Unit(Bar), + "inhg" => Token::Unit(InchOfMercury), + "mercury" => Token::LexerKeyword(Mercury), + "psi" => Token::Unit(PoundsPerSquareInch), + "torr" | "torrs" => Token::Unit(Torr), - "hz" | "hertz" => Token::Unit(Hertz), - "khz" | "kilohertz" => Token::Unit(Kilohertz), - "mhz" | "megahertz" => Token::Unit(Megahertz), - "ghz" | "gigahertz" => Token::Unit(Gigahertz), - "thz" | "terahertz" => Token::Unit(Terahertz), - "phz" | "petahertz" => Token::Unit(Petahertz), - "rpm" => Token::Unit(RevolutionsPerMinute), - "r" | "rev" | "revolution" | "revolutions" => Token::LexerKeyword(Revolution), + "hz" | "hertz" => Token::Unit(Hertz), + "khz" | "kilohertz" => Token::Unit(Kilohertz), + "mhz" | "megahertz" => Token::Unit(Megahertz), + "ghz" | "gigahertz" => Token::Unit(Gigahertz), + "thz" | "terahertz" => Token::Unit(Terahertz), + "phz" | "petahertz" => Token::Unit(Petahertz), + "rpm" => Token::Unit(RevolutionsPerMinute), + "r" | "rev" | "revolution" | "revolutions" => Token::LexerKeyword(Revolution), - "kph" | "kmh" => Token::Unit(KilometersPerHour), - "mps" => Token::Unit(MetersPerSecond), - "mph" => Token::Unit(MilesPerHour), - "fps" => Token::Unit(FeetPerSecond), - "kn" | "kt" | "knot" | "knots" => Token::Unit(Knot), + "kph" | "kmh" => Token::Unit(KilometersPerHour), + "mps" => Token::Unit(MetersPerSecond), + "mph" => Token::Unit(MilesPerHour), + "fps" => Token::Unit(FeetPerSecond), + "kn" | "kt" | "knot" | "knots" => Token::Unit(Knot), - "k" | "kelvin" | "kelvins" => Token::Unit(Kelvin), - "c" | "celsius" => Token::Unit(Celsius), - "f" | "fahrenheit" | "fahrenheits" => Token::Unit(Fahrenheit), - "deg" | "degree" | "degrees" => Token::Unit(lexer.default_degree), + "k" | "kelvin" | "kelvins" => Token::Unit(Kelvin), + "c" | "celsius" => Token::Unit(Celsius), + "f" | "fahrenheit" | "fahrenheits" => Token::Unit(Fahrenheit), + "deg" | "degree" | "degrees" => Token::Unit(lexer.default_degree), - string => { - return Err(format!("Invalid string: {}", string)); - } - }; - lexer.tokens.push(token); - Ok(()) + string => { + return Err(format!("Invalid string: {}", string)); + } + }; + lexer.tokens.push(token); + Ok(()) } struct Lexer<'a> { - left_paren_count: u16, - right_paren_count: u16, - chars: Peekable>, - tokens: Vec, - default_degree: Unit, + left_paren_count: u16, + right_paren_count: u16, + chars: Peekable>, + tokens: Vec, + default_degree: Unit, } /// Lex an input string and returns [`Token`]s pub fn lex(input: &str, remove_trailing_operator: bool, default_degree: Unit) -> Result, String> { - let mut input = input.replace(',', "").to_ascii_lowercase(); + let mut input = input.replace(',', "").to_ascii_lowercase(); - if remove_trailing_operator { - match &input.chars().last().unwrap_or('x') { - '+' | '-' | '*' | '/' | '^' | '(' => { - input.pop(); - }, - _ => {}, - } - } + if remove_trailing_operator { + match &input.chars().last().unwrap_or('x') { + '+' | '-' | '*' | '/' | '^' | '(' => { + input.pop(); + }, + _ => {}, + } + } - let mut lexer = Lexer { - left_paren_count: 0, - right_paren_count: 0, - chars: UnicodeSegmentation::graphemes(input.as_str(), true).peekable(), - tokens: Vec::new(), - default_degree, - }; + let mut lexer = Lexer { + left_paren_count: 0, + right_paren_count: 0, + chars: UnicodeSegmentation::graphemes(input.as_str(), true).peekable(), + tokens: Vec::new(), + default_degree, + }; - while let Some(c) = lexer.chars.next() { - parse_token(c, &mut lexer)?; - } - let tokens = &mut lexer.tokens; - // auto insert missing parentheses in first and last position - if lexer.left_paren_count > lexer.right_paren_count { - let missing_right_parens = lexer.left_paren_count - lexer.right_paren_count; - for _ in 0..missing_right_parens { - tokens.push(Token::Operator(RightParen)); - } - } else if lexer.left_paren_count < lexer.right_paren_count { - let missing_left_parens = lexer.right_paren_count - lexer.left_paren_count; - for _ in 0..missing_left_parens { - tokens.insert(0, Token::Operator(LeftParen)); - } - } + while let Some(c) = lexer.chars.next() { + parse_token(c, &mut lexer)?; + } + let tokens = &mut lexer.tokens; + // auto insert missing parentheses in first and last position + if lexer.left_paren_count > lexer.right_paren_count { + let missing_right_parens = lexer.left_paren_count - lexer.right_paren_count; + for _ in 0..missing_right_parens { + tokens.push(Token::Operator(RightParen)); + } + } else if lexer.left_paren_count < lexer.right_paren_count { + let missing_left_parens = lexer.right_paren_count - lexer.left_paren_count; + for _ in 0..missing_left_parens { + tokens.insert(0, Token::Operator(LeftParen)); + } + } - if tokens.is_empty() { - return Err("Input was empty".to_string()); - } + if tokens.is_empty() { + return Err("Input was empty".to_string()); + } - let mut token_index = 0; - loop { - match tokens[token_index] { - // decide if % is percent or modulo - Token::LexerKeyword(PercentChar) => { - match tokens.get(token_index + 1) { - Some(Token::TextOperator(Of)) => { - // "10% of 1km" should be percentage - tokens[token_index] = Token::UnaryOperator(Percent); - }, - Some(Token::Operator(operator)) => { - match operator { - LeftParen => { - // "10%(2)" should be modulo - tokens[token_index] = Token::Operator(Modulo); - }, - _ => { - // "10%*2" should be a percentage - tokens[token_index] = Token::UnaryOperator(Percent); - } - } - }, - Some(Token::UnaryOperator(_)) => { - // "10%!" should be a percentage - tokens[token_index] = Token::UnaryOperator(Percent); - }, - Some(Token::LexerKeyword(PercentChar)) => { - // "10%%" should be a percentage - tokens[token_index] = Token::UnaryOperator(Percent); - }, - None => { - // percent if there's no element afterwards - tokens[token_index] = Token::UnaryOperator(Percent); - }, - _ => { - // everything else should be modulo, for example if the % is - // before a number, function or constants - tokens[token_index] = Token::Operator(Modulo); - }, - } - }, - // decide if " is 'inch' or 'inch of mercury' - Token::LexerKeyword(DoubleQuotes) => { - match tokens.get(token_index + 1) { - Some(Token::LexerKeyword(Hg)) => { - // "hg should be inch of mercury - tokens[token_index] = Token::Unit(InchOfMercury); - tokens.remove(token_index + 1); - }, - _ => { - // otherwise, Inch - tokens[token_index] = Token::Unit(Inch); - }, - } - }, - // if hg wasn't already turned into inch of mercury, it's hectogram - Token::LexerKeyword(Hg) => { - tokens[token_index] = Token::Unit(Hectogram); - }, - // decide if "in" is Inch or To - Token::LexerKeyword(In) => { - match tokens.get(token_index + 1) { - Some(Token::Unit(_)) => { - // "in" should be To - tokens[token_index] = Token::TextOperator(To); - }, - _ => { - // otherwise, Inch - tokens[token_index] = Token::Unit(Inch); - }, - } - }, - _ => {}, - } - // parse units like km/h, lbf per square inch - if token_index >= 2 { - let token1 = &tokens[token_index-2]; - let token2 = match &tokens[token_index-1] { - // treat km/h the same as km per h - Token::Operator(Divide) => &Token::LexerKeyword(Per), - _ => &tokens[token_index-1], - }; - let token3 = &tokens[token_index]; - let mut replaced = true; - match (token1, token2, token3) { - // km/h - (Token::Unit(Kilometer), Token::LexerKeyword(Per), Token::Unit(Hour)) => { - tokens[token_index-2] = Token::Unit(KilometersPerHour); - }, - // mi/h - (Token::Unit(Mile), Token::LexerKeyword(Per), Token::Unit(Hour)) => { - tokens[token_index-2] = Token::Unit(MilesPerHour); - }, - // m/s - (Token::Unit(Meter), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(MetersPerSecond); - }, - // ft/s - (Token::Unit(Foot), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(FeetPerSecond); - }, - // bits per second - (Token::Unit(Bit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(BitsPerSecond); - }, - // kilobits per second - (Token::Unit(Kilobit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(KilobitsPerSecond); - }, - // megabits per second - (Token::Unit(Megabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(MegabitsPerSecond); - }, - // gigabits per second - (Token::Unit(Gigabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(GigabitsPerSecond); - }, - // terabits per second - (Token::Unit(Terabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(TerabitsPerSecond); - }, - // petabits per second - (Token::Unit(Petabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(PetabitsPerSecond); - }, - // exabits per second - (Token::Unit(Exabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(ExabitsPerSecond); - }, - // zettabits per second - (Token::Unit(Zettabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(ZettabitsPerSecond); - }, - // yottabits per second - (Token::Unit(Yottabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(YottabitsPerSecond); - }, - // kibibits per second - (Token::Unit(Kibibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(KibibitsPerSecond); - }, - // mebibits per second - (Token::Unit(Mebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(MebibitsPerSecond); - }, - // gibibits per second - (Token::Unit(Gibibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(GibibitsPerSecond); - }, - // tebibits per second - (Token::Unit(Tebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(TebibitsPerSecond); - }, - // pebibits per second - (Token::Unit(Pebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(PebibitsPerSecond); - }, - // exbibits per second - (Token::Unit(Exbibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(ExbibitsPerSecond); - }, - // zebibits per second - (Token::Unit(Zebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(ZebibitsPerSecond); - }, - // yobibits per second - (Token::Unit(Yobibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(YobibitsPerSecond); - }, - // bytes per second - (Token::Unit(Byte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(BytesPerSecond); - }, - // kilobytes per second - (Token::Unit(Kilobyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(KilobytesPerSecond); - }, - // megabytes per second - (Token::Unit(Megabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(MegabytesPerSecond); - }, - // gigabytes per second - (Token::Unit(Gigabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(GigabytesPerSecond); - }, - // terabytes per second - (Token::Unit(Terabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(TerabytesPerSecond); - }, - // petabytes per second - (Token::Unit(Petabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(PetabytesPerSecond); - }, - // exabytes per second - (Token::Unit(Exabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(ExabytesPerSecond); - }, - // zettabytes per second - (Token::Unit(Zettabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(ZettabytesPerSecond); - }, - // yottabytes per second - (Token::Unit(Yottabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(YottabytesPerSecond); - }, - // kibibytes per second - (Token::Unit(Kibibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(KibibytesPerSecond); - }, - // mebibytes per second - (Token::Unit(Mebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(MebibytesPerSecond); - }, - // gibibytes per second - (Token::Unit(Gibibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(GibibytesPerSecond); - }, - // tebibytes per second - (Token::Unit(Tebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(TebibytesPerSecond); - }, - // pebibytes per second - (Token::Unit(Pebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(PebibytesPerSecond); - }, - // exbibytes per second - (Token::Unit(Exbibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(ExbibytesPerSecond); - }, - // zebibytes per second - (Token::Unit(Zebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(ZebibytesPerSecond); - }, - // yobibytes per second - (Token::Unit(Yobibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { - tokens[token_index-2] = Token::Unit(YobibytesPerSecond); - }, - // btu/min - (Token::Unit(BritishThermalUnit), Token::LexerKeyword(Per), Token::Unit(Minute)) => { - tokens[token_index-2] = Token::Unit(BritishThermalUnitsPerMinute); - }, - // btu/h - (Token::Unit(BritishThermalUnit), Token::LexerKeyword(Per), Token::Unit(Hour)) => { - tokens[token_index-2] = Token::Unit(BritishThermalUnitsPerHour); - }, - // lbs/sqin - (Token::LexerKeyword(PoundForce), Token::LexerKeyword(Per), Token::Unit(SquareInch)) => { - tokens[token_index-2] = Token::Unit(PoundsPerSquareInch); - }, - // inch of mercury - (Token::Unit(Inch), Token::TextOperator(Of), Token::LexerKeyword(Mercury)) => { - tokens[token_index-2] = Token::Unit(InchOfMercury); - }, - // revolutions per minute - (Token::LexerKeyword(Revolution), Token::LexerKeyword(Per), Token::Unit(Minute)) => { - tokens[token_index-2] = Token::Unit(RevolutionsPerMinute); - }, - _ => { - replaced = false; - }, - } - if replaced { - tokens.remove(token_index); - tokens.remove(token_index-1); - token_index -= 2; - } - } - if token_index == tokens.len()-1 { - break; - } else { - token_index += 1; - } - } + let mut token_index = 0; + loop { + match tokens[token_index] { + // decide if % is percent or modulo + Token::LexerKeyword(PercentChar) => { + match tokens.get(token_index + 1) { + Some(Token::TextOperator(Of)) => { + // "10% of 1km" should be percentage + tokens[token_index] = Token::UnaryOperator(Percent); + }, + Some(Token::Operator(operator)) => { + match operator { + LeftParen => { + // "10%(2)" should be modulo + tokens[token_index] = Token::Operator(Modulo); + }, + _ => { + // "10%*2" should be a percentage + tokens[token_index] = Token::UnaryOperator(Percent); + } + } + }, + Some(Token::UnaryOperator(_)) => { + // "10%!" should be a percentage + tokens[token_index] = Token::UnaryOperator(Percent); + }, + Some(Token::LexerKeyword(PercentChar)) => { + // "10%%" should be a percentage + tokens[token_index] = Token::UnaryOperator(Percent); + }, + None => { + // percent if there's no element afterwards + tokens[token_index] = Token::UnaryOperator(Percent); + }, + _ => { + // everything else should be modulo, for example if the % is + // before a number, function or constants + tokens[token_index] = Token::Operator(Modulo); + }, + } + }, + // decide if " is 'inch' or 'inch of mercury' + Token::LexerKeyword(DoubleQuotes) => { + match tokens.get(token_index + 1) { + Some(Token::LexerKeyword(Hg)) => { + // "hg should be inch of mercury + tokens[token_index] = Token::Unit(InchOfMercury); + tokens.remove(token_index + 1); + }, + _ => { + // otherwise, Inch + tokens[token_index] = Token::Unit(Inch); + }, + } + }, + // if hg wasn't already turned into inch of mercury, it's hectogram + Token::LexerKeyword(Hg) => { + tokens[token_index] = Token::Unit(Hectogram); + }, + // decide if "in" is Inch or To + Token::LexerKeyword(In) => { + match tokens.get(token_index + 1) { + Some(Token::Unit(_)) => { + // "in" should be To + tokens[token_index] = Token::TextOperator(To); + }, + _ => { + // otherwise, Inch + tokens[token_index] = Token::Unit(Inch); + }, + } + }, + _ => {}, + } + // parse units like km/h, lbf per square inch + if token_index >= 2 { + let token1 = &tokens[token_index-2]; + let token2 = match &tokens[token_index-1] { + // treat km/h the same as km per h + Token::Operator(Divide) => &Token::LexerKeyword(Per), + _ => &tokens[token_index-1], + }; + let token3 = &tokens[token_index]; + let mut replaced = true; + match (token1, token2, token3) { + // km/h + (Token::Unit(Kilometer), Token::LexerKeyword(Per), Token::Unit(Hour)) => { + tokens[token_index-2] = Token::Unit(KilometersPerHour); + }, + // mi/h + (Token::Unit(Mile), Token::LexerKeyword(Per), Token::Unit(Hour)) => { + tokens[token_index-2] = Token::Unit(MilesPerHour); + }, + // m/s + (Token::Unit(Meter), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(MetersPerSecond); + }, + // ft/s + (Token::Unit(Foot), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(FeetPerSecond); + }, + // bits per second + (Token::Unit(Bit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(BitsPerSecond); + }, + // kilobits per second + (Token::Unit(Kilobit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(KilobitsPerSecond); + }, + // megabits per second + (Token::Unit(Megabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(MegabitsPerSecond); + }, + // gigabits per second + (Token::Unit(Gigabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(GigabitsPerSecond); + }, + // terabits per second + (Token::Unit(Terabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(TerabitsPerSecond); + }, + // petabits per second + (Token::Unit(Petabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(PetabitsPerSecond); + }, + // exabits per second + (Token::Unit(Exabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(ExabitsPerSecond); + }, + // zettabits per second + (Token::Unit(Zettabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(ZettabitsPerSecond); + }, + // yottabits per second + (Token::Unit(Yottabit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(YottabitsPerSecond); + }, + // kibibits per second + (Token::Unit(Kibibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(KibibitsPerSecond); + }, + // mebibits per second + (Token::Unit(Mebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(MebibitsPerSecond); + }, + // gibibits per second + (Token::Unit(Gibibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(GibibitsPerSecond); + }, + // tebibits per second + (Token::Unit(Tebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(TebibitsPerSecond); + }, + // pebibits per second + (Token::Unit(Pebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(PebibitsPerSecond); + }, + // exbibits per second + (Token::Unit(Exbibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(ExbibitsPerSecond); + }, + // zebibits per second + (Token::Unit(Zebibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(ZebibitsPerSecond); + }, + // yobibits per second + (Token::Unit(Yobibit), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(YobibitsPerSecond); + }, + // bytes per second + (Token::Unit(Byte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(BytesPerSecond); + }, + // kilobytes per second + (Token::Unit(Kilobyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(KilobytesPerSecond); + }, + // megabytes per second + (Token::Unit(Megabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(MegabytesPerSecond); + }, + // gigabytes per second + (Token::Unit(Gigabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(GigabytesPerSecond); + }, + // terabytes per second + (Token::Unit(Terabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(TerabytesPerSecond); + }, + // petabytes per second + (Token::Unit(Petabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(PetabytesPerSecond); + }, + // exabytes per second + (Token::Unit(Exabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(ExabytesPerSecond); + }, + // zettabytes per second + (Token::Unit(Zettabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(ZettabytesPerSecond); + }, + // yottabytes per second + (Token::Unit(Yottabyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(YottabytesPerSecond); + }, + // kibibytes per second + (Token::Unit(Kibibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(KibibytesPerSecond); + }, + // mebibytes per second + (Token::Unit(Mebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(MebibytesPerSecond); + }, + // gibibytes per second + (Token::Unit(Gibibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(GibibytesPerSecond); + }, + // tebibytes per second + (Token::Unit(Tebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(TebibytesPerSecond); + }, + // pebibytes per second + (Token::Unit(Pebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(PebibytesPerSecond); + }, + // exbibytes per second + (Token::Unit(Exbibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(ExbibytesPerSecond); + }, + // zebibytes per second + (Token::Unit(Zebibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(ZebibytesPerSecond); + }, + // yobibytes per second + (Token::Unit(Yobibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { + tokens[token_index-2] = Token::Unit(YobibytesPerSecond); + }, + // btu/min + (Token::Unit(BritishThermalUnit), Token::LexerKeyword(Per), Token::Unit(Minute)) => { + tokens[token_index-2] = Token::Unit(BritishThermalUnitsPerMinute); + }, + // btu/h + (Token::Unit(BritishThermalUnit), Token::LexerKeyword(Per), Token::Unit(Hour)) => { + tokens[token_index-2] = Token::Unit(BritishThermalUnitsPerHour); + }, + // lbs/sqin + (Token::LexerKeyword(PoundForce), Token::LexerKeyword(Per), Token::Unit(SquareInch)) => { + tokens[token_index-2] = Token::Unit(PoundsPerSquareInch); + }, + // inch of mercury + (Token::Unit(Inch), Token::TextOperator(Of), Token::LexerKeyword(Mercury)) => { + tokens[token_index-2] = Token::Unit(InchOfMercury); + }, + // revolutions per minute + (Token::LexerKeyword(Revolution), Token::LexerKeyword(Per), Token::Unit(Minute)) => { + tokens[token_index-2] = Token::Unit(RevolutionsPerMinute); + }, + _ => { + replaced = false; + }, + } + if replaced { + tokens.remove(token_index); + tokens.remove(token_index-1); + token_index -= 2; + } + } + if token_index == tokens.len()-1 { + break; + } else { + token_index += 1; + } + } - Ok(lexer.tokens) + Ok(lexer.tokens) } #[cfg(test)] mod tests { - use super::*; - use crate::numtok; - use regex::Regex; + use super::*; + use crate::numtok; + use regex::Regex; - #[test] - fn test_lex() { - let strip_operator_spacing = Regex::new(r" ([+\-*/]) ").unwrap(); - let strip_afterdigit_spacing = Regex::new(r"(\d) ").unwrap(); - let nonplural_data_units = Regex::new(r"(bit|byte)s").unwrap(); + #[test] + fn test_lex() { + let strip_operator_spacing = Regex::new(r" ([+\-*/]) ").unwrap(); + let strip_afterdigit_spacing = Regex::new(r"(\d) ").unwrap(); + let nonplural_data_units = Regex::new(r"(bit|byte)s").unwrap(); - let run_lex = |input: &str, expected_tokens: Vec| { - let tokens = match lex(input, false, Unit::Celsius) { - Ok(tokens) => tokens, - Err(e) => { - panic!("lex error: {}\nrun_lex input: {}", e, input); - } - }; - let info_msg = format!("run_lex input: {}\nexpected: {:?}\nreceived: {:?}", input, expected_tokens, tokens); - assert!(tokens == expected_tokens, "{}", info_msg); + let run_lex = |input: &str, expected_tokens: Vec| { + let tokens = match lex(input, false, Unit::Celsius) { + Ok(tokens) => tokens, + Err(e) => { + panic!("lex error: {}\nrun_lex input: {}", e, input); + } + }; + let info_msg = format!("run_lex input: {}\nexpected: {:?}\nreceived: {:?}", input, expected_tokens, tokens); + assert!(tokens == expected_tokens, "{}", info_msg); - // Prove we can handle multiple spaces wherever we handle a single space - let input_extra_spaces = input.replace(" ", " "); - let tokens_extra_spaces = lex(&input_extra_spaces, false, Unit::Celsius).unwrap(); - assert!(tokens_extra_spaces == expected_tokens, "{}", info_msg); + // Prove we can handle multiple spaces wherever we handle a single space + let input_extra_spaces = input.replace(" ", " "); + let tokens_extra_spaces = lex(&input_extra_spaces, false, Unit::Celsius).unwrap(); + assert!(tokens_extra_spaces == expected_tokens, "{}", info_msg); - // Prove we don't need spaces around operators - let input_stripped_spaces = strip_operator_spacing.replace_all(input, "$1"); - let tokens_stripped_spaces = lex(&input_stripped_spaces, false, Unit::Celsius).unwrap(); - assert!(tokens_stripped_spaces == expected_tokens, "{}", info_msg); + // Prove we don't need spaces around operators + let input_stripped_spaces = strip_operator_spacing.replace_all(input, "$1"); + let tokens_stripped_spaces = lex(&input_stripped_spaces, false, Unit::Celsius).unwrap(); + assert!(tokens_stripped_spaces == expected_tokens, "{}", info_msg); - // Prove we don't need a space after a digit - let input_afterdigit_stripped_spaces = strip_afterdigit_spacing.replace_all(input, "$1"); - let tokens_afterdigit_stripped_spaces = lex(&input_afterdigit_stripped_spaces, false, Unit::Celsius).unwrap(); - assert!(tokens_afterdigit_stripped_spaces == expected_tokens, "{}", info_msg); - }; + // Prove we don't need a space after a digit + let input_afterdigit_stripped_spaces = strip_afterdigit_spacing.replace_all(input, "$1"); + let tokens_afterdigit_stripped_spaces = lex(&input_afterdigit_stripped_spaces, false, Unit::Celsius).unwrap(); + assert!(tokens_afterdigit_stripped_spaces == expected_tokens, "{}", info_msg); + }; - let run_datarate_lex = |input: &str, expected_tokens: Vec| { - run_lex(input, (*expected_tokens).to_vec()); + let run_datarate_lex = |input: &str, expected_tokens: Vec| { + run_lex(input, (*expected_tokens).to_vec()); - // Prove plural and non-plural data units behave identically - let input_nonplural_units = nonplural_data_units.replace_all(input, "$1"); - let tokens_nonplural_units = lex(&input_nonplural_units, false, Unit::Celsius).unwrap(); - let info_msg = format!("run_datarate_lex input: {}\nexpected: {:?}\nreceived: {:?}", input, expected_tokens, tokens_nonplural_units); - assert!(tokens_nonplural_units == expected_tokens, "{}", info_msg); - }; + // Prove plural and non-plural data units behave identically + let input_nonplural_units = nonplural_data_units.replace_all(input, "$1"); + let tokens_nonplural_units = lex(&input_nonplural_units, false, Unit::Celsius).unwrap(); + let info_msg = format!("run_datarate_lex input: {}\nexpected: {:?}\nreceived: {:?}", input, expected_tokens, tokens_nonplural_units); + assert!(tokens_nonplural_units == expected_tokens, "{}", info_msg); + }; - run_lex("88 kilometres * 2", vec![numtok!(88), Token::Unit(Kilometer), Token::Operator(Multiply), numtok!(2)]); - run_lex("100 nmi", vec![numtok!(100), Token::Unit(NauticalMile)]); - run_lex("101 nautical miles", vec![numtok!(101), Token::Unit(NauticalMile)]); - run_lex("2 lightyears", vec![numtok!(2), Token::Unit(LightYear)]); - run_lex("1 light year", vec![numtok!(1), Token::Unit(LightYear)]); - run_lex("10 lightsec", vec![numtok!(10), Token::Unit(LightSecond)]); - run_lex("12 light secs", vec![numtok!(12), Token::Unit(LightSecond)]); - run_lex("33.3 square meters", vec![numtok!(33.3), Token::Unit(SquareMeter)]); - run_lex("54 m2", vec![numtok!(54), Token::Unit(SquareMeter)]); - run_lex("87 sq miles", vec![numtok!(87), Token::Unit(SquareMile)]); - run_lex("500 feet2", vec![numtok!(500), Token::Unit(SquareFoot)]); - run_lex("500 feet²", vec![numtok!(500), Token::Unit(SquareFoot)]); - run_lex("4 cubic metres", vec![numtok!(4), Token::Unit(CubicMeter)]); - run_lex("34 cubic feet + 23 cubic yards", vec![numtok!(34), Token::Unit(CubicFoot), Token::Operator(Plus), numtok!(23), Token::Unit(CubicYard)]); - run_lex("66 inches3 + 65 millimetre³", vec![numtok!(66), Token::Unit(CubicInch), Token::Operator(Plus), numtok!(65), Token::Unit(CubicMillimeter)]); - run_lex("66 inches³ + 65 millimetre3", vec![numtok!(66), Token::Unit(CubicInch), Token::Operator(Plus), numtok!(65), Token::Unit(CubicMillimeter)]); - run_lex("42 millilitres", vec![numtok!(42), Token::Unit(Milliliter)]); - run_lex("3 tbs", vec![numtok!(3), Token::Unit(Tablespoon)]); - run_lex("6 floz", vec![numtok!(6), Token::Unit(FluidOunce)]); - run_lex("6 fl oz", vec![numtok!(6), Token::Unit(FluidOunce)]); - run_lex("6 fluid ounces", vec![numtok!(6), Token::Unit(FluidOunce)]); - run_lex("3 oil barrels", vec![numtok!(3), Token::Unit(OilBarrel)]); - run_lex("67 kg", vec![numtok!(67), Token::Unit(Kilogram)]); - run_lex("34 oz", vec![numtok!(34), Token::Unit(Ounce)]); - run_lex("34 ounces", vec![numtok!(34), Token::Unit(Ounce)]); - run_lex("210 lb", vec![numtok!(210), Token::Unit(Pound)]); - run_lex("210 lbs", vec![numtok!(210), Token::Unit(Pound)]); - run_lex("210 pound", vec![numtok!(210), Token::Unit(Pound)]); - run_lex("210 pounds", vec![numtok!(210), Token::Unit(Pound)]); - run_lex("210 pounds-force", vec![numtok!(210), Token::LexerKeyword(PoundForce)]); - run_lex("3 ton", vec![numtok!(3), Token::Unit(ShortTon)]); - run_lex("3 short tons", vec![numtok!(3), Token::Unit(ShortTon)]); - run_lex("4 lt", vec![numtok!(4), Token::Unit(LongTon)]); - run_lex("4 long tonnes", vec![numtok!(4), Token::Unit(LongTon)]); - run_datarate_lex("1 bit", vec![numtok!(1), Token::Unit(Bit)]); - run_datarate_lex("8 bits", vec![numtok!(8), Token::Unit(Bit)]); - run_datarate_lex("63 kilobits", vec![numtok!(63), Token::Unit(Kilobit)]); - run_datarate_lex("32 megabits", vec![numtok!(32), Token::Unit(Megabit)]); - run_datarate_lex("3.5 gigabits", vec![numtok!(3.5), Token::Unit(Gigabit)]); - run_datarate_lex("2.1 terabits", vec![numtok!(2.1), Token::Unit(Terabit)]); - run_datarate_lex("1.08 petabits", vec![numtok!(1.08), Token::Unit(Petabit)]); - run_datarate_lex("0.73 exabits", vec![numtok!(0.73), Token::Unit(Exabit)]); - run_datarate_lex("0.49 zettabits", vec![numtok!(0.49), Token::Unit(Zettabit)]); - run_datarate_lex("0.23 yottabits", vec![numtok!(0.23), Token::Unit(Yottabit)]); - run_datarate_lex("63 kibibits", vec![numtok!(63), Token::Unit(Kibibit)]); - run_datarate_lex("32 mebibits", vec![numtok!(32), Token::Unit(Mebibit)]); - run_datarate_lex("3.5 gibibits", vec![numtok!(3.5), Token::Unit(Gibibit)]); - run_datarate_lex("2.1 tebibits", vec![numtok!(2.1), Token::Unit(Tebibit)]); - run_datarate_lex("1.08 pebibits", vec![numtok!(1.08), Token::Unit(Pebibit)]); - run_datarate_lex("0.73 exbibits", vec![numtok!(0.73), Token::Unit(Exbibit)]); - run_datarate_lex("0.49 zebibits", vec![numtok!(0.49), Token::Unit(Zebibit)]); - run_datarate_lex("0.23 yobibits", vec![numtok!(0.23), Token::Unit(Yobibit)]); - run_datarate_lex("1 byte", vec![numtok!(1), Token::Unit(Byte)]); - run_datarate_lex("3 bytes", vec![numtok!(3), Token::Unit(Byte)]); - run_datarate_lex("63 kilobytes", vec![numtok!(63), Token::Unit(Kilobyte)]); - run_datarate_lex("32 megabytes", vec![numtok!(32), Token::Unit(Megabyte)]); - run_datarate_lex("3.5 gigabytes", vec![numtok!(3.5), Token::Unit(Gigabyte)]); - run_datarate_lex("2.1 terabytes", vec![numtok!(2.1), Token::Unit(Terabyte)]); - run_datarate_lex("1.08 petabytes", vec![numtok!(1.08), Token::Unit(Petabyte)]); - run_datarate_lex("0.73 exabytes", vec![numtok!(0.73), Token::Unit(Exabyte)]); - run_datarate_lex("0.49 zettabytes", vec![numtok!(0.49), Token::Unit(Zettabyte)]); - run_datarate_lex("0.23 yottabytes", vec![numtok!(0.23), Token::Unit(Yottabyte)]); - run_datarate_lex("63 kibibytes", vec![numtok!(63), Token::Unit(Kibibyte)]); - run_datarate_lex("32 mebibytes", vec![numtok!(32), Token::Unit(Mebibyte)]); - run_datarate_lex("3.5 gibibytes", vec![numtok!(3.5), Token::Unit(Gibibyte)]); - run_datarate_lex("2.1 tebibytes", vec![numtok!(2.1), Token::Unit(Tebibyte)]); - run_datarate_lex("1.08 pebibytes", vec![numtok!(1.08), Token::Unit(Pebibyte)]); - run_datarate_lex("0.73 exbibytes", vec![numtok!(0.73), Token::Unit(Exbibyte)]); - run_datarate_lex("0.49 zebibytes", vec![numtok!(0.49), Token::Unit(Zebibyte)]); - run_datarate_lex("0.23 yobibytes", vec![numtok!(0.23), Token::Unit(Yobibyte)]); - run_lex("432 bps", vec![numtok!(432), Token::Unit(BitsPerSecond)]); - run_lex("56 kbps", vec![numtok!(56), Token::Unit(KilobitsPerSecond)]); - run_lex("12 mbps", vec![numtok!(12), Token::Unit(MegabitsPerSecond)]); - run_lex("4.2 gbps", vec![numtok!(4.2), Token::Unit(GigabitsPerSecond)]); - run_lex("2.2 tbps", vec![numtok!(2.2), Token::Unit(TerabitsPerSecond)]); - run_lex("1.7 pbps", vec![numtok!(1.7), Token::Unit(PetabitsPerSecond)]); - run_lex("0.99 ebps", vec![numtok!(0.99), Token::Unit(ExabitsPerSecond)]); - run_lex("0.64 zbps", vec![numtok!(0.64), Token::Unit(ZettabitsPerSecond)]); - run_lex("0.278 ybps", vec![numtok!(0.278), Token::Unit(YottabitsPerSecond)]); - run_datarate_lex("4 bits per second", vec![numtok!(4), Token::Unit(BitsPerSecond)]); - run_datarate_lex("5 kilobits per second", vec![numtok!(5), Token::Unit(KilobitsPerSecond)]); - run_datarate_lex("6 megabits per second", vec![numtok!(6), Token::Unit(MegabitsPerSecond)]); - run_datarate_lex("7 gigabits per second", vec![numtok!(7), Token::Unit(GigabitsPerSecond)]); - run_datarate_lex("8 terabits per second", vec![numtok!(8), Token::Unit(TerabitsPerSecond)]); - run_datarate_lex("9 petabits per second", vec![numtok!(9), Token::Unit(PetabitsPerSecond)]); - run_datarate_lex("10 exabits per second", vec![numtok!(10), Token::Unit(ExabitsPerSecond)]); - run_datarate_lex("11 zettabits per second", vec![numtok!(11), Token::Unit(ZettabitsPerSecond)]); - run_datarate_lex("12 yottabits per second", vec![numtok!(12), Token::Unit(YottabitsPerSecond)]); - run_datarate_lex("13 kibibits per second", vec![numtok!(13), Token::Unit(KibibitsPerSecond)]); - run_datarate_lex("14 mebibits per second", vec![numtok!(14), Token::Unit(MebibitsPerSecond)]); - run_datarate_lex("15 gibibits per second", vec![numtok!(15), Token::Unit(GibibitsPerSecond)]); - run_datarate_lex("16 tebibits per second", vec![numtok!(16), Token::Unit(TebibitsPerSecond)]); - run_datarate_lex("17 pebibits per second", vec![numtok!(17), Token::Unit(PebibitsPerSecond)]); - run_datarate_lex("18 exbibits per second", vec![numtok!(18), Token::Unit(ExbibitsPerSecond)]); - run_datarate_lex("19 zebibits per second", vec![numtok!(19), Token::Unit(ZebibitsPerSecond)]); - run_datarate_lex("20 yobibits per second", vec![numtok!(20), Token::Unit(YobibitsPerSecond)]); - run_datarate_lex("4 bytes per second", vec![numtok!(4), Token::Unit(BytesPerSecond)]); - run_datarate_lex("5 kilobytes per second", vec![numtok!(5), Token::Unit(KilobytesPerSecond)]); - run_datarate_lex("6 megabytes per second", vec![numtok!(6), Token::Unit(MegabytesPerSecond)]); - run_datarate_lex("7 gigabytes per second", vec![numtok!(7), Token::Unit(GigabytesPerSecond)]); - run_datarate_lex("8 terabytes per second", vec![numtok!(8), Token::Unit(TerabytesPerSecond)]); - run_datarate_lex("9 petabytes per second", vec![numtok!(9), Token::Unit(PetabytesPerSecond)]); - run_datarate_lex("10 exabytes per second", vec![numtok!(10), Token::Unit(ExabytesPerSecond)]); - run_datarate_lex("11 zettabytes per second", vec![numtok!(11), Token::Unit(ZettabytesPerSecond)]); - run_datarate_lex("12 yottabytes per second", vec![numtok!(12), Token::Unit(YottabytesPerSecond)]); - run_datarate_lex("13 kibibytes per second", vec![numtok!(13), Token::Unit(KibibytesPerSecond)]); - run_datarate_lex("14 mebibytes per second", vec![numtok!(14), Token::Unit(MebibytesPerSecond)]); - run_datarate_lex("15 gibibytes per second", vec![numtok!(15), Token::Unit(GibibytesPerSecond)]); - run_datarate_lex("16 tebibytes per second", vec![numtok!(16), Token::Unit(TebibytesPerSecond)]); - run_datarate_lex("17 pebibytes per second", vec![numtok!(17), Token::Unit(PebibytesPerSecond)]); - run_datarate_lex("18 exbibytes per second", vec![numtok!(18), Token::Unit(ExbibytesPerSecond)]); - run_datarate_lex("19 zebibytes per second", vec![numtok!(19), Token::Unit(ZebibytesPerSecond)]); - run_datarate_lex("20 yobibytes per second", vec![numtok!(20), Token::Unit(YobibytesPerSecond)]); - run_lex("234 wh", vec![numtok!(234), Token::Unit(WattHour)]); - run_lex("1 w", vec![numtok!(1), Token::Unit(Watt)]); - run_lex("1 watt", vec![numtok!(1), Token::Unit(Watt)]); - run_lex("1 watts", vec![numtok!(1), Token::Unit(Watt)]); - run_lex("1 watt hour", vec![numtok!(1), Token::Unit(WattHour)]); - run_lex("0 watt + 1 watts", vec![numtok!(0), Token::Unit(Watt), Token::Operator(Plus), numtok!(1), Token::Unit(Watt)]); - run_lex("0 watt * 1", vec![numtok!(0), Token::Unit(Watt), Token::Operator(Multiply), numtok!(1)]); - run_lex("2 watts + 3 watts", vec![numtok!(2), Token::Unit(Watt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 watts * 3", vec![numtok!(2), Token::Unit(Watt), Token::Operator(Multiply), numtok!(3)]); - run_lex("4 watt plus 5 watts", vec![numtok!(4), Token::Unit(Watt), Token::Operator(Plus), numtok!(5), Token::Unit(Watt)]); - run_lex("4 watt times 5", vec![numtok!(4), Token::Unit(Watt), Token::Operator(Multiply), numtok!(5)]); - run_lex("6 watts plus 7 watts", vec![numtok!(6), Token::Unit(Watt), Token::Operator(Plus), numtok!(7), Token::Unit(Watt)]); - run_lex("6 watts times 7", vec![numtok!(6), Token::Unit(Watt), Token::Operator(Multiply), numtok!(7)]); - run_lex("2.3 kwh", vec![numtok!(2.3), Token::Unit(KilowattHour)]); - run_lex("1 kw", vec![numtok!(1), Token::Unit(Kilowatt)]); - run_lex("1 kilowatt", vec![numtok!(1), Token::Unit(Kilowatt)]); - run_lex("1 kilowatts", vec![numtok!(1), Token::Unit(Kilowatt)]); - run_lex("1 kilowatt hour", vec![numtok!(1), Token::Unit(KilowattHour)]); - run_lex("2 kilowatt + 3 watt", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 kilowatt * 4", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Multiply), numtok!(4)]); - run_lex("2 kilowatt times 4", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Multiply), numtok!(4)]); - run_lex("2 kilowatt + 3 watts", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 kilowatts + 3 watt", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 kilowatts + 3 watts", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 kilowatt plus 3 watt", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 kilowatt plus 3 watts", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 kilowatts plus 3 watt", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 kilowatts plus 3 watts", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("6.6 watts + 4 kilowatts", vec![numtok!(6.6), Token::Unit(Watt), Token::Operator(Plus), numtok!(4), Token::Unit(Kilowatt)]); - run_lex("6.6 watts plus 4 kilowatts", vec![numtok!(6.6), Token::Unit(Watt), Token::Operator(Plus), numtok!(4), Token::Unit(Kilowatt)]); - run_lex("2.3 mwh", vec![numtok!(2.3), Token::Unit(MegawattHour)]); - run_lex("1 mw", vec![numtok!(1), Token::Unit(Megawatt)]); - run_lex("1 megawatt", vec![numtok!(1), Token::Unit(Megawatt)]); - run_lex("1 megawatt hour", vec![numtok!(1), Token::Unit(MegawattHour)]); - run_lex("2 megawatt + 3 watt", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 megawatt * 6", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Multiply), numtok!(6)]); - run_lex("2 megawatt times 6", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Multiply), numtok!(6)]); - run_lex("2 megawatt + 3 watts", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 megawatts + 3 watt", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 megawatts + 3 watts", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 megawatt plus 3 watt", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 megawatt plus 3 watts", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 megawatts plus 3 watt", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("2 megawatts plus 3 watts", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); - run_lex("6.6 watts + 4 megawatts", vec![numtok!(6.6), Token::Unit(Watt), Token::Operator(Plus), numtok!(4), Token::Unit(Megawatt)]); - run_lex("6.6 watts plus 4 megawatts", vec![numtok!(6.6), Token::Unit(Watt), Token::Operator(Plus), numtok!(4), Token::Unit(Megawatt)]); - run_lex("234 gwh", vec![numtok!(234), Token::Unit(GigawattHour)]); - run_lex("1 gw", vec![numtok!(1), Token::Unit(Gigawatt)]); - run_lex("1 gigawatt", vec![numtok!(1), Token::Unit(Gigawatt)]); - run_lex("1 gigawatts", vec![numtok!(1), Token::Unit(Gigawatt)]); - run_lex("1 gigawatt hour", vec![numtok!(1), Token::Unit(GigawattHour)]); - run_lex("0 gigawatt + 1 gigawatts", vec![numtok!(0), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(1), Token::Unit(Gigawatt)]); - run_lex("0 gigawatt * 1", vec![numtok!(0), Token::Unit(Gigawatt), Token::Operator(Multiply), numtok!(1)]); - run_lex("2 gigawatts + 3 gigawatts", vec![numtok!(2), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Gigawatt)]); - run_lex("2 gigawatts * 3", vec![numtok!(2), Token::Unit(Gigawatt), Token::Operator(Multiply), numtok!(3)]); - run_lex("4 gigawatt plus 5 watt", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Watt)]); - run_lex("4 gigawatt plus 5 megawatt", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Megawatt)]); - run_lex("4 gigawatt plus 5 gigawatt", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Gigawatt)]); - run_lex("4 gigawatt plus 5 watts", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Watt)]); - run_lex("4 gigawatt plus 5 megawatts", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Megawatt)]); - run_lex("4 gigawatt plus 5 gigawatts", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Gigawatt)]); - run_lex("4 gigawatt times 5", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Multiply), numtok!(5)]); - run_lex("6 gigawatts plus 7 watt", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Watt)]); - run_lex("6 gigawatts plus 7 megawatt", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Megawatt)]); - run_lex("6 gigawatts plus 7 gigawatt", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Gigawatt)]); - run_lex("6 gigawatts plus 7 watts", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Watt)]); - run_lex("6 gigawatts plus 7 megawatts", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Megawatt)]); - run_lex("6 gigawatts plus 7 gigawatts", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Gigawatt)]); - run_lex("6 gigawatts times 7", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Multiply), numtok!(7)]); - run_lex("88 mw * 3", vec![numtok!(88), Token::Unit(Megawatt), Token::Operator(Multiply), numtok!(3)]); - run_lex("88 mw times 3", vec![numtok!(88), Token::Unit(Megawatt), Token::Operator(Multiply), numtok!(3)]); - run_lex("999 kb", vec![numtok!(999), Token::Unit(Kilobyte)]); - run_lex("200 gb - 100 mb", vec![numtok!(200), Token::Unit(Gigabyte), Token::Operator(Minus), numtok!(100), Token::Unit(Megabyte)]); - run_lex("999 kib", vec![numtok!(999), Token::Unit(Kibibyte)]); - run_lex("200 gib - 100 mib", vec![numtok!(200), Token::Unit(Gibibyte), Token::Operator(Minus), numtok!(100), Token::Unit(Mebibyte)]); - run_lex("45 btu", vec![numtok!(45), Token::Unit(BritishThermalUnit)]); - run_lex("45.5 british thermal unit", vec![numtok!(45.5), Token::Unit(BritishThermalUnit)]); - run_lex("46 british thermal units", vec![numtok!(46), Token::Unit(BritishThermalUnit)]); - run_lex("5432 newton metres", vec![numtok!(5432), Token::Unit(NewtonMeter)]); - run_lex("2345 newton-meters", vec![numtok!(2345), Token::Unit(NewtonMeter)]); - run_lex("20 lbf", vec![numtok!(20), Token::LexerKeyword(PoundForce)]); - run_lex("60 hz", vec![numtok!(60), Token::Unit(Hertz)]); - run_lex("1100 rpm", vec![numtok!(1100), Token::Unit(RevolutionsPerMinute)]); - run_lex("1150 revolutions per minute", vec![numtok!(1150), Token::Unit(RevolutionsPerMinute)]); - run_lex("1 revolution per min", vec![numtok!(1), Token::Unit(RevolutionsPerMinute)]); - run_lex("4 revolution / mins", vec![numtok!(4), Token::Unit(RevolutionsPerMinute)]); - run_lex("1250 r / min", vec![numtok!(1250), Token::Unit(RevolutionsPerMinute)]); - run_lex("1300 rev / min", vec![numtok!(1300), Token::Unit(RevolutionsPerMinute)]); - run_lex("1350 rev / minute", vec![numtok!(1350), Token::Unit(RevolutionsPerMinute)]); - run_lex("1250 r per min", vec![numtok!(1250), Token::Unit(RevolutionsPerMinute)]); - run_lex("1300 rev per min", vec![numtok!(1300), Token::Unit(RevolutionsPerMinute)]); - run_lex("1350 rev per minute", vec![numtok!(1350), Token::Unit(RevolutionsPerMinute)]); - run_lex("100 kph", vec![numtok!(100), Token::Unit(KilometersPerHour)]); - run_lex("100 kmh", vec![numtok!(100), Token::Unit(KilometersPerHour)]); - run_lex("100 kilometers per hour", vec![numtok!(100), Token::Unit(KilometersPerHour)]); - run_lex("100 kilometre / hrs", vec![numtok!(100), Token::Unit(KilometersPerHour)]); - run_lex("3.6 mps", vec![numtok!(3.6), Token::Unit(MetersPerSecond)]); - run_lex("3.6 meters per second", vec![numtok!(3.6), Token::Unit(MetersPerSecond)]); - run_lex("3.6 metre / secs", vec![numtok!(3.6), Token::Unit(MetersPerSecond)]); - run_lex("60 mph", vec![numtok!(60), Token::Unit(MilesPerHour)]); - run_lex("60 miles per hour", vec![numtok!(60), Token::Unit(MilesPerHour)]); - run_lex("60 mile / hr", vec![numtok!(60), Token::Unit(MilesPerHour)]); - run_lex("35 fps", vec![numtok!(35), Token::Unit(FeetPerSecond)]); - run_lex("35 ft / sec", vec![numtok!(35), Token::Unit(FeetPerSecond)]); - run_lex("35 ft per seconds", vec![numtok!(35), Token::Unit(FeetPerSecond)]); - run_lex("35 foot / secs", vec![numtok!(35), Token::Unit(FeetPerSecond)]); - run_lex("35 foot per seconds", vec![numtok!(35), Token::Unit(FeetPerSecond)]); - run_lex("35 feet / sec", vec![numtok!(35), Token::Unit(FeetPerSecond)]); - run_lex("35 feet per second", vec![numtok!(35), Token::Unit(FeetPerSecond)]); - run_lex("30 pa", vec![numtok!(30), Token::Unit(Pascal)]); - run_lex("23 celsius + 4 celsius", vec![numtok!(23), Token::Unit(Celsius), Token::Operator(Plus), numtok!(4), Token::Unit(Celsius)]); - run_lex("54 f - 1.5 fahrenheit", vec![numtok!(54), Token::Unit(Fahrenheit), Token::Operator(Minus), numtok!(1.5), Token::Unit(Fahrenheit)]); - run_lex("50 metric tonnes", vec![numtok!(50), Token::Unit(MetricTon)]); - run_lex("77 metric hps", vec![numtok!(77), Token::Unit(MetricHorsepower)]); + run_lex("88 kilometres * 2", vec![numtok!(88), Token::Unit(Kilometer), Token::Operator(Multiply), numtok!(2)]); + run_lex("100 nmi", vec![numtok!(100), Token::Unit(NauticalMile)]); + run_lex("101 nautical miles", vec![numtok!(101), Token::Unit(NauticalMile)]); + run_lex("2 lightyears", vec![numtok!(2), Token::Unit(LightYear)]); + run_lex("1 light year", vec![numtok!(1), Token::Unit(LightYear)]); + run_lex("10 lightsec", vec![numtok!(10), Token::Unit(LightSecond)]); + run_lex("12 light secs", vec![numtok!(12), Token::Unit(LightSecond)]); + run_lex("33.3 square meters", vec![numtok!(33.3), Token::Unit(SquareMeter)]); + run_lex("54 m2", vec![numtok!(54), Token::Unit(SquareMeter)]); + run_lex("87 sq miles", vec![numtok!(87), Token::Unit(SquareMile)]); + run_lex("500 feet2", vec![numtok!(500), Token::Unit(SquareFoot)]); + run_lex("500 feet²", vec![numtok!(500), Token::Unit(SquareFoot)]); + run_lex("4 cubic metres", vec![numtok!(4), Token::Unit(CubicMeter)]); + run_lex("34 cubic feet + 23 cubic yards", vec![numtok!(34), Token::Unit(CubicFoot), Token::Operator(Plus), numtok!(23), Token::Unit(CubicYard)]); + run_lex("66 inches3 + 65 millimetre³", vec![numtok!(66), Token::Unit(CubicInch), Token::Operator(Plus), numtok!(65), Token::Unit(CubicMillimeter)]); + run_lex("66 inches³ + 65 millimetre3", vec![numtok!(66), Token::Unit(CubicInch), Token::Operator(Plus), numtok!(65), Token::Unit(CubicMillimeter)]); + run_lex("42 millilitres", vec![numtok!(42), Token::Unit(Milliliter)]); + run_lex("3 tbs", vec![numtok!(3), Token::Unit(Tablespoon)]); + run_lex("6 floz", vec![numtok!(6), Token::Unit(FluidOunce)]); + run_lex("6 fl oz", vec![numtok!(6), Token::Unit(FluidOunce)]); + run_lex("6 fluid ounces", vec![numtok!(6), Token::Unit(FluidOunce)]); + run_lex("3 oil barrels", vec![numtok!(3), Token::Unit(OilBarrel)]); + run_lex("67 kg", vec![numtok!(67), Token::Unit(Kilogram)]); + run_lex("34 oz", vec![numtok!(34), Token::Unit(Ounce)]); + run_lex("34 ounces", vec![numtok!(34), Token::Unit(Ounce)]); + run_lex("210 lb", vec![numtok!(210), Token::Unit(Pound)]); + run_lex("210 lbs", vec![numtok!(210), Token::Unit(Pound)]); + run_lex("210 pound", vec![numtok!(210), Token::Unit(Pound)]); + run_lex("210 pounds", vec![numtok!(210), Token::Unit(Pound)]); + run_lex("210 pounds-force", vec![numtok!(210), Token::LexerKeyword(PoundForce)]); + run_lex("3 ton", vec![numtok!(3), Token::Unit(ShortTon)]); + run_lex("3 short tons", vec![numtok!(3), Token::Unit(ShortTon)]); + run_lex("4 lt", vec![numtok!(4), Token::Unit(LongTon)]); + run_lex("4 long tonnes", vec![numtok!(4), Token::Unit(LongTon)]); + run_datarate_lex("1 bit", vec![numtok!(1), Token::Unit(Bit)]); + run_datarate_lex("8 bits", vec![numtok!(8), Token::Unit(Bit)]); + run_datarate_lex("63 kilobits", vec![numtok!(63), Token::Unit(Kilobit)]); + run_datarate_lex("32 megabits", vec![numtok!(32), Token::Unit(Megabit)]); + run_datarate_lex("3.5 gigabits", vec![numtok!(3.5), Token::Unit(Gigabit)]); + run_datarate_lex("2.1 terabits", vec![numtok!(2.1), Token::Unit(Terabit)]); + run_datarate_lex("1.08 petabits", vec![numtok!(1.08), Token::Unit(Petabit)]); + run_datarate_lex("0.73 exabits", vec![numtok!(0.73), Token::Unit(Exabit)]); + run_datarate_lex("0.49 zettabits", vec![numtok!(0.49), Token::Unit(Zettabit)]); + run_datarate_lex("0.23 yottabits", vec![numtok!(0.23), Token::Unit(Yottabit)]); + run_datarate_lex("63 kibibits", vec![numtok!(63), Token::Unit(Kibibit)]); + run_datarate_lex("32 mebibits", vec![numtok!(32), Token::Unit(Mebibit)]); + run_datarate_lex("3.5 gibibits", vec![numtok!(3.5), Token::Unit(Gibibit)]); + run_datarate_lex("2.1 tebibits", vec![numtok!(2.1), Token::Unit(Tebibit)]); + run_datarate_lex("1.08 pebibits", vec![numtok!(1.08), Token::Unit(Pebibit)]); + run_datarate_lex("0.73 exbibits", vec![numtok!(0.73), Token::Unit(Exbibit)]); + run_datarate_lex("0.49 zebibits", vec![numtok!(0.49), Token::Unit(Zebibit)]); + run_datarate_lex("0.23 yobibits", vec![numtok!(0.23), Token::Unit(Yobibit)]); + run_datarate_lex("1 byte", vec![numtok!(1), Token::Unit(Byte)]); + run_datarate_lex("3 bytes", vec![numtok!(3), Token::Unit(Byte)]); + run_datarate_lex("63 kilobytes", vec![numtok!(63), Token::Unit(Kilobyte)]); + run_datarate_lex("32 megabytes", vec![numtok!(32), Token::Unit(Megabyte)]); + run_datarate_lex("3.5 gigabytes", vec![numtok!(3.5), Token::Unit(Gigabyte)]); + run_datarate_lex("2.1 terabytes", vec![numtok!(2.1), Token::Unit(Terabyte)]); + run_datarate_lex("1.08 petabytes", vec![numtok!(1.08), Token::Unit(Petabyte)]); + run_datarate_lex("0.73 exabytes", vec![numtok!(0.73), Token::Unit(Exabyte)]); + run_datarate_lex("0.49 zettabytes", vec![numtok!(0.49), Token::Unit(Zettabyte)]); + run_datarate_lex("0.23 yottabytes", vec![numtok!(0.23), Token::Unit(Yottabyte)]); + run_datarate_lex("63 kibibytes", vec![numtok!(63), Token::Unit(Kibibyte)]); + run_datarate_lex("32 mebibytes", vec![numtok!(32), Token::Unit(Mebibyte)]); + run_datarate_lex("3.5 gibibytes", vec![numtok!(3.5), Token::Unit(Gibibyte)]); + run_datarate_lex("2.1 tebibytes", vec![numtok!(2.1), Token::Unit(Tebibyte)]); + run_datarate_lex("1.08 pebibytes", vec![numtok!(1.08), Token::Unit(Pebibyte)]); + run_datarate_lex("0.73 exbibytes", vec![numtok!(0.73), Token::Unit(Exbibyte)]); + run_datarate_lex("0.49 zebibytes", vec![numtok!(0.49), Token::Unit(Zebibyte)]); + run_datarate_lex("0.23 yobibytes", vec![numtok!(0.23), Token::Unit(Yobibyte)]); + run_lex("432 bps", vec![numtok!(432), Token::Unit(BitsPerSecond)]); + run_lex("56 kbps", vec![numtok!(56), Token::Unit(KilobitsPerSecond)]); + run_lex("12 mbps", vec![numtok!(12), Token::Unit(MegabitsPerSecond)]); + run_lex("4.2 gbps", vec![numtok!(4.2), Token::Unit(GigabitsPerSecond)]); + run_lex("2.2 tbps", vec![numtok!(2.2), Token::Unit(TerabitsPerSecond)]); + run_lex("1.7 pbps", vec![numtok!(1.7), Token::Unit(PetabitsPerSecond)]); + run_lex("0.99 ebps", vec![numtok!(0.99), Token::Unit(ExabitsPerSecond)]); + run_lex("0.64 zbps", vec![numtok!(0.64), Token::Unit(ZettabitsPerSecond)]); + run_lex("0.278 ybps", vec![numtok!(0.278), Token::Unit(YottabitsPerSecond)]); + run_datarate_lex("4 bits per second", vec![numtok!(4), Token::Unit(BitsPerSecond)]); + run_datarate_lex("5 kilobits per second", vec![numtok!(5), Token::Unit(KilobitsPerSecond)]); + run_datarate_lex("6 megabits per second", vec![numtok!(6), Token::Unit(MegabitsPerSecond)]); + run_datarate_lex("7 gigabits per second", vec![numtok!(7), Token::Unit(GigabitsPerSecond)]); + run_datarate_lex("8 terabits per second", vec![numtok!(8), Token::Unit(TerabitsPerSecond)]); + run_datarate_lex("9 petabits per second", vec![numtok!(9), Token::Unit(PetabitsPerSecond)]); + run_datarate_lex("10 exabits per second", vec![numtok!(10), Token::Unit(ExabitsPerSecond)]); + run_datarate_lex("11 zettabits per second", vec![numtok!(11), Token::Unit(ZettabitsPerSecond)]); + run_datarate_lex("12 yottabits per second", vec![numtok!(12), Token::Unit(YottabitsPerSecond)]); + run_datarate_lex("13 kibibits per second", vec![numtok!(13), Token::Unit(KibibitsPerSecond)]); + run_datarate_lex("14 mebibits per second", vec![numtok!(14), Token::Unit(MebibitsPerSecond)]); + run_datarate_lex("15 gibibits per second", vec![numtok!(15), Token::Unit(GibibitsPerSecond)]); + run_datarate_lex("16 tebibits per second", vec![numtok!(16), Token::Unit(TebibitsPerSecond)]); + run_datarate_lex("17 pebibits per second", vec![numtok!(17), Token::Unit(PebibitsPerSecond)]); + run_datarate_lex("18 exbibits per second", vec![numtok!(18), Token::Unit(ExbibitsPerSecond)]); + run_datarate_lex("19 zebibits per second", vec![numtok!(19), Token::Unit(ZebibitsPerSecond)]); + run_datarate_lex("20 yobibits per second", vec![numtok!(20), Token::Unit(YobibitsPerSecond)]); + run_datarate_lex("4 bytes per second", vec![numtok!(4), Token::Unit(BytesPerSecond)]); + run_datarate_lex("5 kilobytes per second", vec![numtok!(5), Token::Unit(KilobytesPerSecond)]); + run_datarate_lex("6 megabytes per second", vec![numtok!(6), Token::Unit(MegabytesPerSecond)]); + run_datarate_lex("7 gigabytes per second", vec![numtok!(7), Token::Unit(GigabytesPerSecond)]); + run_datarate_lex("8 terabytes per second", vec![numtok!(8), Token::Unit(TerabytesPerSecond)]); + run_datarate_lex("9 petabytes per second", vec![numtok!(9), Token::Unit(PetabytesPerSecond)]); + run_datarate_lex("10 exabytes per second", vec![numtok!(10), Token::Unit(ExabytesPerSecond)]); + run_datarate_lex("11 zettabytes per second", vec![numtok!(11), Token::Unit(ZettabytesPerSecond)]); + run_datarate_lex("12 yottabytes per second", vec![numtok!(12), Token::Unit(YottabytesPerSecond)]); + run_datarate_lex("13 kibibytes per second", vec![numtok!(13), Token::Unit(KibibytesPerSecond)]); + run_datarate_lex("14 mebibytes per second", vec![numtok!(14), Token::Unit(MebibytesPerSecond)]); + run_datarate_lex("15 gibibytes per second", vec![numtok!(15), Token::Unit(GibibytesPerSecond)]); + run_datarate_lex("16 tebibytes per second", vec![numtok!(16), Token::Unit(TebibytesPerSecond)]); + run_datarate_lex("17 pebibytes per second", vec![numtok!(17), Token::Unit(PebibytesPerSecond)]); + run_datarate_lex("18 exbibytes per second", vec![numtok!(18), Token::Unit(ExbibytesPerSecond)]); + run_datarate_lex("19 zebibytes per second", vec![numtok!(19), Token::Unit(ZebibytesPerSecond)]); + run_datarate_lex("20 yobibytes per second", vec![numtok!(20), Token::Unit(YobibytesPerSecond)]); + run_lex("234 wh", vec![numtok!(234), Token::Unit(WattHour)]); + run_lex("1 w", vec![numtok!(1), Token::Unit(Watt)]); + run_lex("1 watt", vec![numtok!(1), Token::Unit(Watt)]); + run_lex("1 watts", vec![numtok!(1), Token::Unit(Watt)]); + run_lex("1 watt hour", vec![numtok!(1), Token::Unit(WattHour)]); + run_lex("0 watt + 1 watts", vec![numtok!(0), Token::Unit(Watt), Token::Operator(Plus), numtok!(1), Token::Unit(Watt)]); + run_lex("0 watt * 1", vec![numtok!(0), Token::Unit(Watt), Token::Operator(Multiply), numtok!(1)]); + run_lex("2 watts + 3 watts", vec![numtok!(2), Token::Unit(Watt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 watts * 3", vec![numtok!(2), Token::Unit(Watt), Token::Operator(Multiply), numtok!(3)]); + run_lex("4 watt plus 5 watts", vec![numtok!(4), Token::Unit(Watt), Token::Operator(Plus), numtok!(5), Token::Unit(Watt)]); + run_lex("4 watt times 5", vec![numtok!(4), Token::Unit(Watt), Token::Operator(Multiply), numtok!(5)]); + run_lex("6 watts plus 7 watts", vec![numtok!(6), Token::Unit(Watt), Token::Operator(Plus), numtok!(7), Token::Unit(Watt)]); + run_lex("6 watts times 7", vec![numtok!(6), Token::Unit(Watt), Token::Operator(Multiply), numtok!(7)]); + run_lex("2.3 kwh", vec![numtok!(2.3), Token::Unit(KilowattHour)]); + run_lex("1 kw", vec![numtok!(1), Token::Unit(Kilowatt)]); + run_lex("1 kilowatt", vec![numtok!(1), Token::Unit(Kilowatt)]); + run_lex("1 kilowatts", vec![numtok!(1), Token::Unit(Kilowatt)]); + run_lex("1 kilowatt hour", vec![numtok!(1), Token::Unit(KilowattHour)]); + run_lex("2 kilowatt + 3 watt", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 kilowatt * 4", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Multiply), numtok!(4)]); + run_lex("2 kilowatt times 4", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Multiply), numtok!(4)]); + run_lex("2 kilowatt + 3 watts", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 kilowatts + 3 watt", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 kilowatts + 3 watts", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 kilowatt plus 3 watt", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 kilowatt plus 3 watts", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 kilowatts plus 3 watt", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 kilowatts plus 3 watts", vec![numtok!(2), Token::Unit(Kilowatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("6.6 watts + 4 kilowatts", vec![numtok!(6.6), Token::Unit(Watt), Token::Operator(Plus), numtok!(4), Token::Unit(Kilowatt)]); + run_lex("6.6 watts plus 4 kilowatts", vec![numtok!(6.6), Token::Unit(Watt), Token::Operator(Plus), numtok!(4), Token::Unit(Kilowatt)]); + run_lex("2.3 mwh", vec![numtok!(2.3), Token::Unit(MegawattHour)]); + run_lex("1 mw", vec![numtok!(1), Token::Unit(Megawatt)]); + run_lex("1 megawatt", vec![numtok!(1), Token::Unit(Megawatt)]); + run_lex("1 megawatt hour", vec![numtok!(1), Token::Unit(MegawattHour)]); + run_lex("2 megawatt + 3 watt", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 megawatt * 6", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Multiply), numtok!(6)]); + run_lex("2 megawatt times 6", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Multiply), numtok!(6)]); + run_lex("2 megawatt + 3 watts", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 megawatts + 3 watt", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 megawatts + 3 watts", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 megawatt plus 3 watt", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 megawatt plus 3 watts", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 megawatts plus 3 watt", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("2 megawatts plus 3 watts", vec![numtok!(2), Token::Unit(Megawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Watt)]); + run_lex("6.6 watts + 4 megawatts", vec![numtok!(6.6), Token::Unit(Watt), Token::Operator(Plus), numtok!(4), Token::Unit(Megawatt)]); + run_lex("6.6 watts plus 4 megawatts", vec![numtok!(6.6), Token::Unit(Watt), Token::Operator(Plus), numtok!(4), Token::Unit(Megawatt)]); + run_lex("234 gwh", vec![numtok!(234), Token::Unit(GigawattHour)]); + run_lex("1 gw", vec![numtok!(1), Token::Unit(Gigawatt)]); + run_lex("1 gigawatt", vec![numtok!(1), Token::Unit(Gigawatt)]); + run_lex("1 gigawatts", vec![numtok!(1), Token::Unit(Gigawatt)]); + run_lex("1 gigawatt hour", vec![numtok!(1), Token::Unit(GigawattHour)]); + run_lex("0 gigawatt + 1 gigawatts", vec![numtok!(0), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(1), Token::Unit(Gigawatt)]); + run_lex("0 gigawatt * 1", vec![numtok!(0), Token::Unit(Gigawatt), Token::Operator(Multiply), numtok!(1)]); + run_lex("2 gigawatts + 3 gigawatts", vec![numtok!(2), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(3), Token::Unit(Gigawatt)]); + run_lex("2 gigawatts * 3", vec![numtok!(2), Token::Unit(Gigawatt), Token::Operator(Multiply), numtok!(3)]); + run_lex("4 gigawatt plus 5 watt", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Watt)]); + run_lex("4 gigawatt plus 5 megawatt", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Megawatt)]); + run_lex("4 gigawatt plus 5 gigawatt", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Gigawatt)]); + run_lex("4 gigawatt plus 5 watts", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Watt)]); + run_lex("4 gigawatt plus 5 megawatts", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Megawatt)]); + run_lex("4 gigawatt plus 5 gigawatts", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(5), Token::Unit(Gigawatt)]); + run_lex("4 gigawatt times 5", vec![numtok!(4), Token::Unit(Gigawatt), Token::Operator(Multiply), numtok!(5)]); + run_lex("6 gigawatts plus 7 watt", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Watt)]); + run_lex("6 gigawatts plus 7 megawatt", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Megawatt)]); + run_lex("6 gigawatts plus 7 gigawatt", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Gigawatt)]); + run_lex("6 gigawatts plus 7 watts", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Watt)]); + run_lex("6 gigawatts plus 7 megawatts", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Megawatt)]); + run_lex("6 gigawatts plus 7 gigawatts", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Plus), numtok!(7), Token::Unit(Gigawatt)]); + run_lex("6 gigawatts times 7", vec![numtok!(6), Token::Unit(Gigawatt), Token::Operator(Multiply), numtok!(7)]); + run_lex("88 mw * 3", vec![numtok!(88), Token::Unit(Megawatt), Token::Operator(Multiply), numtok!(3)]); + run_lex("88 mw times 3", vec![numtok!(88), Token::Unit(Megawatt), Token::Operator(Multiply), numtok!(3)]); + run_lex("999 kb", vec![numtok!(999), Token::Unit(Kilobyte)]); + run_lex("200 gb - 100 mb", vec![numtok!(200), Token::Unit(Gigabyte), Token::Operator(Minus), numtok!(100), Token::Unit(Megabyte)]); + run_lex("999 kib", vec![numtok!(999), Token::Unit(Kibibyte)]); + run_lex("200 gib - 100 mib", vec![numtok!(200), Token::Unit(Gibibyte), Token::Operator(Minus), numtok!(100), Token::Unit(Mebibyte)]); + run_lex("45 btu", vec![numtok!(45), Token::Unit(BritishThermalUnit)]); + run_lex("45.5 british thermal unit", vec![numtok!(45.5), Token::Unit(BritishThermalUnit)]); + run_lex("46 british thermal units", vec![numtok!(46), Token::Unit(BritishThermalUnit)]); + run_lex("5432 newton metres", vec![numtok!(5432), Token::Unit(NewtonMeter)]); + run_lex("2345 newton-meters", vec![numtok!(2345), Token::Unit(NewtonMeter)]); + run_lex("20 lbf", vec![numtok!(20), Token::LexerKeyword(PoundForce)]); + run_lex("60 hz", vec![numtok!(60), Token::Unit(Hertz)]); + run_lex("1100 rpm", vec![numtok!(1100), Token::Unit(RevolutionsPerMinute)]); + run_lex("1150 revolutions per minute", vec![numtok!(1150), Token::Unit(RevolutionsPerMinute)]); + run_lex("1 revolution per min", vec![numtok!(1), Token::Unit(RevolutionsPerMinute)]); + run_lex("4 revolution / mins", vec![numtok!(4), Token::Unit(RevolutionsPerMinute)]); + run_lex("1250 r / min", vec![numtok!(1250), Token::Unit(RevolutionsPerMinute)]); + run_lex("1300 rev / min", vec![numtok!(1300), Token::Unit(RevolutionsPerMinute)]); + run_lex("1350 rev / minute", vec![numtok!(1350), Token::Unit(RevolutionsPerMinute)]); + run_lex("1250 r per min", vec![numtok!(1250), Token::Unit(RevolutionsPerMinute)]); + run_lex("1300 rev per min", vec![numtok!(1300), Token::Unit(RevolutionsPerMinute)]); + run_lex("1350 rev per minute", vec![numtok!(1350), Token::Unit(RevolutionsPerMinute)]); + run_lex("100 kph", vec![numtok!(100), Token::Unit(KilometersPerHour)]); + run_lex("100 kmh", vec![numtok!(100), Token::Unit(KilometersPerHour)]); + run_lex("100 kilometers per hour", vec![numtok!(100), Token::Unit(KilometersPerHour)]); + run_lex("100 kilometre / hrs", vec![numtok!(100), Token::Unit(KilometersPerHour)]); + run_lex("3.6 mps", vec![numtok!(3.6), Token::Unit(MetersPerSecond)]); + run_lex("3.6 meters per second", vec![numtok!(3.6), Token::Unit(MetersPerSecond)]); + run_lex("3.6 metre / secs", vec![numtok!(3.6), Token::Unit(MetersPerSecond)]); + run_lex("60 mph", vec![numtok!(60), Token::Unit(MilesPerHour)]); + run_lex("60 miles per hour", vec![numtok!(60), Token::Unit(MilesPerHour)]); + run_lex("60 mile / hr", vec![numtok!(60), Token::Unit(MilesPerHour)]); + run_lex("35 fps", vec![numtok!(35), Token::Unit(FeetPerSecond)]); + run_lex("35 ft / sec", vec![numtok!(35), Token::Unit(FeetPerSecond)]); + run_lex("35 ft per seconds", vec![numtok!(35), Token::Unit(FeetPerSecond)]); + run_lex("35 foot / secs", vec![numtok!(35), Token::Unit(FeetPerSecond)]); + run_lex("35 foot per seconds", vec![numtok!(35), Token::Unit(FeetPerSecond)]); + run_lex("35 feet / sec", vec![numtok!(35), Token::Unit(FeetPerSecond)]); + run_lex("35 feet per second", vec![numtok!(35), Token::Unit(FeetPerSecond)]); + run_lex("30 pa", vec![numtok!(30), Token::Unit(Pascal)]); + run_lex("23 celsius + 4 celsius", vec![numtok!(23), Token::Unit(Celsius), Token::Operator(Plus), numtok!(4), Token::Unit(Celsius)]); + run_lex("54 f - 1.5 fahrenheit", vec![numtok!(54), Token::Unit(Fahrenheit), Token::Operator(Minus), numtok!(1.5), Token::Unit(Fahrenheit)]); + run_lex("50 metric tonnes", vec![numtok!(50), Token::Unit(MetricTon)]); + run_lex("77 metric hps", vec![numtok!(77), Token::Unit(MetricHorsepower)]); - run_lex("100 + 99", vec![numtok!(100), Token::Operator(Plus), numtok!(99)]); - run_lex("100 plus 99", vec![numtok!(100), Token::Operator(Plus), numtok!(99)]); - run_lex("12 - 4", vec![numtok!(12), Token::Operator(Minus), numtok!(4)]); - run_lex("12 minus 4", vec![numtok!(12), Token::Operator(Minus), numtok!(4)]); - run_lex("50.5 * 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]); - run_lex("50.5 times 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]); - run_lex("50.5 multiplied by 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]); - run_lex("6 / 3", vec![numtok!(6), Token::Operator(Divide), numtok!(3)]); - run_lex("50 / 10", vec![numtok!(50), Token::Operator(Divide), numtok!(10)]); - run_lex("52 ÷ 12", vec![numtok!(52), Token::Operator(Divide), numtok!(12)]); - run_lex("6 divided by 3", vec![numtok!(6), Token::Operator(Divide), numtok!(3)]); - run_lex("7 mod 5", vec![numtok!(7), Token::Operator(Modulo), numtok!(5)]); + run_lex("100 + 99", vec![numtok!(100), Token::Operator(Plus), numtok!(99)]); + run_lex("100 plus 99", vec![numtok!(100), Token::Operator(Plus), numtok!(99)]); + run_lex("12 - 4", vec![numtok!(12), Token::Operator(Minus), numtok!(4)]); + run_lex("12 minus 4", vec![numtok!(12), Token::Operator(Minus), numtok!(4)]); + run_lex("50.5 * 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]); + run_lex("50.5 times 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]); + run_lex("50.5 multiplied by 2", vec![numtok!(50.5), Token::Operator(Multiply), numtok!(2)]); + run_lex("6 / 3", vec![numtok!(6), Token::Operator(Divide), numtok!(3)]); + run_lex("50 / 10", vec![numtok!(50), Token::Operator(Divide), numtok!(10)]); + run_lex("52 ÷ 12", vec![numtok!(52), Token::Operator(Divide), numtok!(12)]); + run_lex("6 divided by 3", vec![numtok!(6), Token::Operator(Divide), numtok!(3)]); + run_lex("7 mod 5", vec![numtok!(7), Token::Operator(Modulo), numtok!(5)]); - run_lex("(2 + 3) * 4", vec![Token::Operator(LeftParen), numtok!(2), Token::Operator(Plus), numtok!(3), Token::Operator(RightParen), Token::Operator(Multiply), numtok!(4)]); - 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)]); - run_lex("12 pound+", vec![numtok!(12), Token::Unit(Pound), Token::Operator(Plus)]); + run_lex("(2 + 3) * 4", vec![Token::Operator(LeftParen), numtok!(2), Token::Operator(Plus), numtok!(3), Token::Operator(RightParen), Token::Operator(Multiply), numtok!(4)]); + 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)]); + run_lex("12 pound+", vec![numtok!(12), Token::Unit(Pound), Token::Operator(Plus)]); - run_lex("5 π m", vec![numtok!(5), Token::Constant(Pi), Token::Unit(Meter)]); - run_lex("5 Ω + 2 mΩ", vec![numtok!(5), Token::Unit(Ohm), Token::Operator(Plus), numtok!(2), Token::Unit(Milliohm)]); - } + run_lex("5 π m", vec![numtok!(5), Token::Constant(Pi), Token::Unit(Meter)]); + run_lex("5 Ω + 2 mΩ", vec![numtok!(5), Token::Unit(Ohm), Token::Operator(Plus), numtok!(2), Token::Unit(Milliohm)]); + } } diff --git a/src/lib.rs b/src/lib.rs index 7cd1a14..26ac1f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,10 @@ #![cfg_attr( - feature = "cargo-clippy", - allow( - clippy::comparison_chain, - clippy::if_same_then_else, - clippy::match_like_matches_macro, - ) + feature = "cargo-clippy", + allow( + clippy::comparison_chain, + clippy::if_same_then_else, + clippy::match_like_matches_macro, + ) )] //! calculation + conversion //! @@ -63,110 +63,110 @@ pub mod units; /// }; /// ``` pub struct Number { - /// The number part of a [`Number`] struct - pub value: d128, - /// The unit of a [`Number`] struct. This can be [`NoType`](units::UnitType::NoType) - pub unit: Unit, + /// The number part of a [`Number`] struct + pub value: d128, + /// The unit of a [`Number`] struct. This can be [`NoType`](units::UnitType::NoType) + pub unit: Unit, } impl Number { - pub const fn new(value: d128, unit: Unit) -> Number { - Number { value, unit } - } + pub const fn new(value: d128, unit: Unit) -> Number { + Number { value, unit } + } } impl Display for Number { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // 0.2/0.01 results in 2E+1, but if we add zero it becomes 20 - let fixed_value = self.value + d128!(0); - let output = match self.unit { - Unit::NoUnit => format!("{}", fixed_value), - unit => format!("{} {:?}", fixed_value, unit), - }; - write!(f, "{}", output) - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // 0.2/0.01 results in 2E+1, but if we add zero it becomes 20 + let fixed_value = self.value + d128!(0); + let output = match self.unit { + Unit::NoUnit => format!("{}", fixed_value), + unit => format!("{} {:?}", fixed_value, unit), + }; + write!(f, "{}", output) + } } #[derive(Clone, Debug, PartialEq)] /// Math operators like [`Multiply`](Operator::Multiply), parentheses, etc. pub enum Operator { - Plus, - Minus, - Multiply, - Divide, - Modulo, - Caret, - LeftParen, // lexer only - RightParen, // lexer only + Plus, + Minus, + Multiply, + Divide, + Modulo, + Caret, + LeftParen, // lexer only + RightParen, // lexer only } #[derive(Clone, Debug, PartialEq)] /// Unary operators like [`Percent`](UnaryOperator::Percent) and [`Factorial`](UnaryOperator::Factorial). pub enum UnaryOperator { - Percent, - Factorial, + Percent, + Factorial, } #[derive(Clone, Debug, PartialEq)] /// A Text operator like [`To`](TextOperator::To) or [`Of`](TextOperator::Of). pub enum TextOperator { - To, - Of, + To, + Of, } #[derive(Clone, Debug, PartialEq)] /// A named number like [`Million`](NamedNumber::Million). pub enum NamedNumber { - Hundred, - Thousand, - Million, - Billion, - Trillion, - Quadrillion, - Quintillion, - Sextillion, - Septillion, - Octillion, - Nonillion, - Decillion, - Undecillion, - Duodecillion, - Tredecillion, - Quattuordecillion, - Quindecillion, - Sexdecillion, - Septendecillion, - Octodecillion, - Novemdecillion, - Vigintillion, - Centillion, - Googol, + Hundred, + Thousand, + Million, + Billion, + Trillion, + Quadrillion, + Quintillion, + Sextillion, + Septillion, + Octillion, + Nonillion, + Decillion, + Undecillion, + Duodecillion, + Tredecillion, + Quattuordecillion, + Quindecillion, + Sexdecillion, + Septendecillion, + Octodecillion, + Novemdecillion, + Vigintillion, + Centillion, + Googol, } #[derive(Clone, Debug, PartialEq)] /// A constant like [`Pi`](Constant::Pi) or [`E`](Constant::E). pub enum Constant { - Pi, - E, + Pi, + E, } #[derive(Clone, Debug, PartialEq)] /// Functions identifiers like [`Sqrt`](FunctionIdentifier::Sqrt), [`Sin`](FunctionIdentifier::Sin), [`Round`](FunctionIdentifier::Round), etc. pub enum FunctionIdentifier { - Sqrt, - Cbrt, + Sqrt, + Cbrt, - Log, - Ln, - Exp, + Log, + Ln, + Exp, - Round, - Ceil, - Floor, - Abs, + Round, + Ceil, + Floor, + Abs, - Sin, - Cos, - Tan, + Sin, + Cos, + Tan, } #[derive(Clone, Debug, PartialEq)] @@ -178,15 +178,15 @@ pub enum FunctionIdentifier { /// dependingon them, turns it into a [`Percent`](UnaryOperator::Percent) or /// [`Modulo`](Operator::Modulo) [`Token`]. pub enum LexerKeyword { - Per, - PercentChar, - In, - DoubleQuotes, - Mercury, - Hg, - PoundForce, - Force, - Revolution, + Per, + PercentChar, + In, + DoubleQuotes, + Mercury, + Hg, + PoundForce, + Force, + Revolution, } #[derive(Clone, Debug, PartialEq)] @@ -194,29 +194,29 @@ pub enum LexerKeyword { /// /// Strings can be divided up into these tokens by the [`lexer`], and then put into the [`parser`]. pub enum Token { - Operator(Operator), - UnaryOperator(UnaryOperator), - Number(d128), - FunctionIdentifier(FunctionIdentifier), - Constant(Constant), - /// Used by the parser only - Paren, - /// Used by the lexer only - Per, - /// Used by the parser only - LexerKeyword(LexerKeyword), - TextOperator(TextOperator), - NamedNumber(NamedNumber), - /// The `-` symbol, specifically when used as `-5` and not `5-5`. Used by the parser only - Negative, - Unit(units::Unit), + Operator(Operator), + UnaryOperator(UnaryOperator), + Number(d128), + FunctionIdentifier(FunctionIdentifier), + Constant(Constant), + /// Used by the parser only + Paren, + /// Used by the lexer only + Per, + /// Used by the parser only + LexerKeyword(LexerKeyword), + TextOperator(TextOperator), + NamedNumber(NamedNumber), + /// The `-` symbol, specifically when used as `-5` and not `5-5`. Used by the parser only + Negative, + Unit(units::Unit), } #[macro_export] macro_rules! numtok { - ( $num:literal ) => { - Token::Number(d128!($num)) - }; + ( $num:literal ) => { + Token::Number(d128!($num)) + }; } /// Evaluates a string into a resulting [`Number`]. @@ -237,48 +237,52 @@ macro_rules! numtok { /// } /// ``` pub fn eval( - input: &str, - allow_trailing_operators: bool, - default_degree: Unit, - verbose: bool, + input: &str, + allow_trailing_operators: bool, + default_degree: Unit, + verbose: bool, ) -> Result { - let lex_start = Instant::now(); + let lex_start = Instant::now(); - match lexer::lex(input, allow_trailing_operators, default_degree) { - Ok(tokens) => { - let lex_time = Instant::now().duration_since(lex_start).as_nanos() as f32; - if verbose { - println!("Lexed TokenVector: {:?}", tokens); - } + match lexer::lex(input, allow_trailing_operators, default_degree) { + Ok(tokens) => { + let lex_time = Instant::now().duration_since(lex_start).as_nanos() as f32; + if verbose { + println!("Lexed TokenVector: {:?}", tokens); + } - let parse_start = Instant::now(); - match parser::parse(&tokens) { - Ok(ast) => { - let parse_time = Instant::now().duration_since(parse_start).as_nanos() as f32; - if verbose { - println!("Parsed AstNode: {:#?}", ast); - } + let parse_start = Instant::now(); + match parser::parse(&tokens) { + Ok(ast) => { + let parse_time = Instant::now().duration_since(parse_start).as_nanos() as f32; + if verbose { + println!("Parsed AstNode: {:#?}", ast); + } - let eval_start = Instant::now(); - match evaluator::evaluate(&ast) { - Ok(answer) => { - let eval_time = Instant::now().duration_since(eval_start).as_nanos() as f32; + let eval_start = Instant::now(); + match evaluator::evaluate(&ast) { + Ok(answer) => { + let eval_time = + Instant::now().duration_since(eval_start).as_nanos() as f32; - if verbose { - println!("Evaluated value: {} {:?}", answer.value, answer.unit); - println!("\u{23f1} {:.3}ms lexing", lex_time / 1000.0 / 1000.0); - println!("\u{23f1} {:.3}ms parsing", parse_time / 1000.0 / 1000.0); - println!("\u{23f1} {:.3}ms evaluation", eval_time / 1000.0 / 1000.0); - } + if verbose { + println!("Evaluated value: {} {:?}", answer.value, answer.unit); + println!("\u{23f1} {:.3}ms lexing", lex_time / 1000.0 / 1000.0); + println!("\u{23f1} {:.3}ms parsing", parse_time / 1000.0 / 1000.0); + println!( + "\u{23f1} {:.3}ms evaluation", + eval_time / 1000.0 / 1000.0 + ); + } - Ok(answer) - } - Err(e) => Err(format!("Eval error: {}", e)), - } - } - Err(e) => Err(format!("Parsing error: {}", e)), - } - } - Err(e) => Err(format!("Lexing error: {}", e)), - } + Ok(answer) + } + Err(e) => Err(format!("Eval error: {}", e)), + } + } + Err(e) => Err(format!("Parsing error: {}", e)), + } + } + Err(e) => Err(format!("Lexing error: {}", e)), + } } diff --git a/src/lookup.rs b/src/lookup.rs index 67cb10a..92e5f3e 100644 --- a/src/lookup.rs +++ b/src/lookup.rs @@ -4,1038 +4,1038 @@ use decimal::d128; /// Returns the corresponding [`d128`] of a [`NamedNumber`] pub fn lookup_named_number(named_number: &NamedNumber) -> d128 { - match named_number { - Hundred => d128!(100), - Thousand => d128!(1000), - Million => d128!(1000000), - Billion => d128!(1000000000), - Trillion => d128!(1000000000000), - Quadrillion => d128!(1000000000000000), - Quintillion => d128!(1000000000000000000), - Sextillion => d128!(1000000000000000000000), - Septillion => d128!(1000000000000000000000000), - Octillion => d128!(1000000000000000000000000000), - Nonillion => d128!(1000000000000000000000000000000), - Decillion => d128!(1000000000000000000000000000000000), - Undecillion => d128!(1000000000000000000000000000000000000), - Duodecillion => d128!(1E+39), - Tredecillion => d128!(1E+42), - Quattuordecillion => d128!(1E+45), - Quindecillion => d128!(1E+48), - Sexdecillion => d128!(1E+51), - Septendecillion => d128!(1E+54), - Octodecillion => d128!(1E+57), - Novemdecillion => d128!(1E+60), - Vigintillion => d128!(1E+63), - Googol => d128!(1E+100), - Centillion => d128!(1E+303), - } + match named_number { + Hundred => d128!(100), + Thousand => d128!(1000), + Million => d128!(1000000), + Billion => d128!(1000000000), + Trillion => d128!(1000000000000), + Quadrillion => d128!(1000000000000000), + Quintillion => d128!(1000000000000000000), + Sextillion => d128!(1000000000000000000000), + Septillion => d128!(1000000000000000000000000), + Octillion => d128!(1000000000000000000000000000), + Nonillion => d128!(1000000000000000000000000000000), + Decillion => d128!(1000000000000000000000000000000000), + Undecillion => d128!(1000000000000000000000000000000000000), + Duodecillion => d128!(1E+39), + Tredecillion => d128!(1E+42), + Quattuordecillion => d128!(1E+45), + Quindecillion => d128!(1E+48), + Sexdecillion => d128!(1E+51), + Septendecillion => d128!(1E+54), + Octodecillion => d128!(1E+57), + Novemdecillion => d128!(1E+60), + Vigintillion => d128!(1E+63), + Googol => d128!(1E+100), + Centillion => d128!(1E+303), + } } /// Returns the factorial of an `i32` as a [`struct@d128`] pub fn lookup_factorial(n: i32) -> d128 { - match n { - 0 => d128!(1), - 1 => d128!(1), - 2 => d128!(2), - 3 => d128!(6), - 4 => d128!(24), - 5 => d128!(120), - 6 => d128!(720), - 7 => d128!(5040), - 8 => d128!(40320), - 9 => d128!(362880), - 10 => d128!(3628800), - 11 => d128!(39916800), - 12 => d128!(479001600), - 13 => d128!(6227020800), - 14 => d128!(87178291200), - 15 => d128!(1307674368000), - 16 => d128!(20922789888000), - 17 => d128!(355687428096000), - 18 => d128!(6402373705728000), - 19 => d128!(121645100408832000), - 20 => d128!(2432902008176640000), - 21 => d128!(51090942171709440000), - 22 => d128!(1124000727777607680000), - 23 => d128!(25852016738884976640000), - 24 => d128!(620448401733239439360000), - 25 => d128!(15511210043330985984000000), - 26 => d128!(403291461126605635584000000), - 27 => d128!(10888869450418352160768000000), - 28 => d128!(304888344611713860501504000000), - 29 => d128!(8841761993739701954543616000000), - 30 => d128!(265252859812191058636308480000000), - 31 => d128!(8222838654177922817725562880000000), - 32 => d128!(2.631308369336935301672180121600000E+35), - 33 => d128!(8.683317618811886495518194401280000E+36), - 34 => d128!(2.952327990396041408476186096435200E+38), - 35 => d128!(1.033314796638614492966665133752320E+40), - 36 => d128!(3.719933267899012174679994481508352E+41), - 37 => d128!(1.376375309122634504631597958158090E+43), - 38 => d128!(5.230226174666011117600072241000742E+44), - 39 => d128!(2.039788208119744335864028173990289E+46), - 40 => d128!(8.159152832478977343456112695961156E+47), - 41 => d128!(3.345252661316380710817006205344074E+49), - 42 => d128!(1.405006117752879898543142606244511E+51), - 43 => d128!(6.041526306337383563735513206851397E+52), - 44 => d128!(2.658271574788448768043625811014615E+54), - 45 => d128!(1.196222208654801945619631614956577E+56), - 46 => d128!(5.502622159812088949850305428800254E+57), - 47 => d128!(2.586232415111681806429643551536119E+59), - 48 => d128!(1.241391559253607267086228904737337E+61), - 49 => d128!(6.082818640342675608722521633212951E+62), - 50 => d128!(3.041409320171337804361260816606476E+64), - 51 => d128!(1.551118753287382280224243016469303E+66), - 52 => d128!(8.065817517094387857166063685640376E+67), - 53 => d128!(4.274883284060025564298013753389399E+69), - 54 => d128!(2.308436973392413804720927426830275E+71), - 55 => d128!(1.269640335365827592596510084756651E+73), - 56 => d128!(7.109985878048634518540456474637246E+74), - 57 => d128!(4.052691950487721675568060190543230E+76), - 58 => d128!(2.350561331282878571829474910515073E+78), - 59 => d128!(1.386831185456898357379390197203893E+80), - 60 => d128!(8.320987112741390144276341183223358E+81), - 61 => d128!(5.075802138772247988008568121766248E+83), - 62 => d128!(3.146997326038793752565312235495074E+85), - 63 => d128!(1.982608315404440064116146708361897E+87), - 64 => d128!(1.268869321858841641034333893351614E+89), - 65 => d128!(8.247650592082470666723170306785491E+90), - 66 => d128!(5.443449390774430640037292402478424E+92), - 67 => d128!(3.647111091818868528824985909660544E+94), - 68 => d128!(2.480035542436830599600990418569170E+96), - 69 => d128!(1.711224524281413113724683388812727E+98), - 70 => d128!(1.197857166996989179607278372168909E+100), - 71 => d128!(8.504785885678623175211676442399254E+101), - 72 => d128!(6.123445837688608686152407038527463E+103), - 73 => d128!(4.470115461512684340891257138125048E+105), - 74 => d128!(3.307885441519386412259530282212536E+107), - 75 => d128!(2.480914081139539809194647711659402E+109), - 76 => d128!(1.885494701666050254987932260861146E+111), - 77 => d128!(1.451830920282858696340707840863082E+113), - 78 => d128!(1.132428117820629783145752115873204E+115), - 79 => d128!(8.946182130782975286851441715398312E+116), - 80 => d128!(7.156945704626380229481153372318650E+118), - 81 => d128!(5.797126020747367985879734231578106E+120), - 82 => d128!(4.753643337012841748421382069894047E+122), - 83 => d128!(3.945523969720658651189747118012059E+124), - 84 => d128!(3.314240134565353266999387579130130E+126), - 85 => d128!(2.817104114380550276949479442260610E+128), - 86 => d128!(2.422709538367273238176552320344125E+130), - 87 => d128!(2.107757298379527717213600518699389E+132), - 88 => d128!(1.854826422573984391147968456455462E+134), - 89 => d128!(1.650795516090846108121691926245361E+136), - 90 => d128!(1.485715964481761497309522733620825E+138), - 91 => d128!(1.352001527678402962551665687594951E+140), - 92 => d128!(1.243841405464130725547532432587355E+142), - 93 => d128!(1.156772507081641574759205162306240E+144), - 94 => d128!(1.087366156656743080273652852567866E+146), - 95 => d128!(1.032997848823905926259970209939473E+148), - 96 => d128!(9.916779348709496892095714015418941E+149), - 97 => d128!(9.619275968248211985332842594956373E+151), - 98 => d128!(9.426890448883247745626185743057246E+153), - 99 => d128!(9.332621544394415268169923885626674E+155), - 100 => d128!(9.332621544394415268169923885626674E+157), - 101 => d128!(9.425947759838359420851623124482941E+159), - 102 => d128!(9.614466715035126609268655586972600E+161), - 103 => d128!(9.902900716486180407546715254581778E+163), - 104 => d128!(1.029901674514562762384858386476505E+166), - 105 => d128!(1.081396758240290900504101305800330E+168), - 106 => d128!(1.146280563734708354534347384148350E+170), - 107 => d128!(1.226520203196137939351751701038734E+172), - 108 => d128!(1.324641819451828974499891837121833E+174), - 109 => d128!(1.443859583202493582204882102462798E+176), - 110 => d128!(1.588245541522742940425370312709078E+178), - 111 => d128!(1.762952551090244663872161047107077E+180), - 112 => d128!(1.974506857221074023536820372759926E+182), - 113 => d128!(2.231192748659813646596607021218716E+184), - 114 => d128!(2.543559733472187557120132004189336E+186), - 115 => d128!(2.925093693493015690688151804817736E+188), - 116 => d128!(3.393108684451898201198256093588574E+190), - 117 => d128!(3.969937160808720895401959629498632E+192), - 118 => d128!(4.684525849754290656574312362808386E+194), - 119 => d128!(5.574585761207605881323431711741979E+196), - 120 => d128!(6.689502913449127057588118054090375E+198), - 121 => d128!(8.094298525273443739681622845449354E+200), - 122 => d128!(9.875044200833601362411579871448212E+202), - 123 => d128!(1.214630436702532967576624324188130E+205), - 124 => d128!(1.506141741511140879795014161993281E+207), - 125 => d128!(1.882677176888926099743767702491601E+209), - 126 => d128!(2.372173242880046885677147305139417E+211), - 127 => d128!(3.012660018457659544809977077527060E+213), - 128 => d128!(3.856204823625804217356770659234637E+215), - 129 => d128!(4.974504222477287440390234150412682E+217), - 130 => d128!(6.466855489220473672507304395536487E+219), - 131 => d128!(8.471580690878820510984568758152798E+221), - 132 => d128!(1.118248651196004307449963076076169E+224), - 133 => d128!(1.487270706090685728908450891181305E+226), - 134 => d128!(1.992942746161518876737324194182949E+228), - 135 => d128!(2.690472707318050483595387662146981E+230), - 136 => d128!(3.659042881952548657689727220519894E+232), - 137 => d128!(5.012888748274991661034926292112255E+234), - 138 => d128!(6.917786472619488492228198283114912E+236), - 139 => d128!(9.615723196941089004197195613529728E+238), - 140 => d128!(1.346201247571752460587607385894162E+241), - 141 => d128!(1.898143759076170969428526414110768E+243), - 142 => d128!(2.695364137888162776588507508037291E+245), - 143 => d128!(3.854370717180072770521565736493326E+247), - 144 => d128!(5.550293832739304789551054660550389E+249), - 145 => d128!(8.047926057471991944849029257798064E+251), - 146 => d128!(1.174997204390910823947958271638517E+254), - 147 => d128!(1.727245890454638911203498659308620E+256), - 148 => d128!(2.556323917872865588581178015776758E+258), - 149 => d128!(3.808922637630569726985955243507369E+260), - 150 => d128!(5.713383956445854590478932865261054E+262), - 151 => d128!(8.627209774233240431623188626544192E+264), - 152 => d128!(1.311335885683452545606724671234717E+267), - 153 => d128!(2.006343905095682394778288746989117E+269), - 154 => d128!(3.089769613847350887958564670363240E+271), - 155 => d128!(4.789142901463393876335775239063022E+273), - 156 => d128!(7.471062926282894447083809372938314E+275), - 157 => d128!(1.172956879426414428192158071551315E+278), - 158 => d128!(1.853271869493734796543609753051078E+280), - 159 => d128!(2.946702272495038326504339507351214E+282), - 160 => d128!(4.714723635992061322406943211761942E+284), - 161 => d128!(7.590705053947218729075178570936727E+286), - 162 => d128!(1.229694218739449434110178928491750E+289), - 163 => d128!(2.004401576545302577599591653441552E+291), - 164 => d128!(3.287218585534296227263330311644145E+293), - 165 => d128!(5.423910666131588774984495014212839E+295), - 166 => d128!(9.003691705778437366474261723593313E+297), - 167 => d128!(1.503616514864999040201201707840083E+300), - 168 => d128!(2.526075744973198387538018869171339E+302), - 169 => d128!(4.269068009004705274939251888899563E+304), - 170 => d128!(7.257415615307998967396728211129257E+306), - 171 => d128!(1.241018070217667823424840524103103E+309), - 172 => d128!(2.134551080774388656290725701457337E+311), - 173 => d128!(3.692773369739692375382955463521193E+313), - 174 => d128!(6.425425663347064733166342506526876E+315), - 175 => d128!(1.124449491085736328304109938642203E+318), - 176 => d128!(1.979031104310895937815233492010277E+320), - 177 => d128!(3.502885054630285809932963280858190E+322), - 178 => d128!(6.235135397241908741680674639927578E+324), - 179 => d128!(1.116089236106301664760840760547036E+327), - 180 => d128!(2.008960624991342996569513368984665E+329), - 181 => d128!(3.636218731234330823790819197862244E+331), - 182 => d128!(6.617918090846482099299290940109284E+333), - 183 => d128!(1.211079010624906224171770242039999E+336), - 184 => d128!(2.228385379549827452476057245353598E+338), - 185 => d128!(4.122512952167180787080705903904156E+340), - 186 => d128!(7.667874091030956263970112981261730E+342), - 187 => d128!(1.433892455022788821362411127495944E+345), - 188 => d128!(2.695717815442842984161332919692375E+347), - 189 => d128!(5.094906671186973240064919218218589E+349), - 190 => d128!(9.680322675255249156123346514615319E+351), - 191 => d128!(1.848941630973752588819559184291526E+354), - 192 => d128!(3.549967931469604970533553633839730E+356), - 193 => d128!(6.851438107736337593129758513310679E+358), - 194 => d128!(1.329178992900849493067173151582272E+361), - 195 => d128!(2.591899036156656511480987645585430E+363), - 196 => d128!(5.080122110867046762502735785347443E+365), - 197 => d128!(1.000784055840808212213038949713446E+368), - 198 => d128!(1.981552430564800260181817120432623E+370), - 199 => d128!(3.943289336823952517761816069660920E+372), - 200 => d128!(7.886578673647905035523632139321840E+374), - 201 => d128!(1.585202313403228912140250060003690E+377), - 202 => d128!(3.202108673074522402523305121207454E+379), - 203 => d128!(6.500280606341280477122309396051132E+381), - 204 => d128!(1.326057243693621217332951116794431E+384), - 205 => d128!(2.718417349571923495532549789428584E+386), - 206 => d128!(5.599939740118162400797052566222883E+388), - 207 => d128!(1.159187526204459616964989881208137E+391), - 208 => d128!(2.411110054505276003287178952912925E+393), - 209 => d128!(5.039220013916026846870204011588013E+395), - 210 => d128!(1.058236202922365637842742842433483E+398), - 211 => d128!(2.232878388166191495848187397534649E+400), - 212 => d128!(4.733702182912325971198157282773456E+402), - 213 => d128!(1.008278564960325431865207501230746E+405), - 214 => d128!(2.157716129015096424191544052633796E+407), - 215 => d128!(4.639089677382457312011819713162661E+409), - 216 => d128!(1.002043370314610779394553058043135E+412), - 217 => d128!(2.174434113582705391286180135953603E+414), - 218 => d128!(4.740266367610297753003872696378855E+416), - 219 => d128!(1.038118334506655207907848120506969E+419), - 220 => d128!(2.283860335914641457397265865115332E+421), - 221 => d128!(5.047331342371357620847957561904884E+423), - 222 => d128!(1.120507558006441391828246578742884E+426), - 223 => d128!(2.498731854354364303776989870596631E+428), - 224 => d128!(5.597159353753776040460457310136453E+430), - 225 => d128!(1.259360854594599609103602894780702E+433), - 226 => d128!(2.846155531383795116574142542204387E+435), - 227 => d128!(6.460773056241214914623303570803958E+437), - 228 => d128!(1.473056256822997000534113214143302E+440), - 229 => d128!(3.373298828124663131223119260388162E+442), - 230 => d128!(7.758587304686725201813174298892773E+444), - 231 => d128!(1.792233667382633521618843263044231E+447), - 232 => d128!(4.157982108327709770155716370262616E+449), - 233 => d128!(9.688098312403563764462819142711895E+451), - 234 => d128!(2.267015005102433920884299679394583E+454), - 235 => d128!(5.327485261990719714078104246577270E+456), - 236 => d128!(1.257286521829809852522432602192236E+459), - 237 => d128!(2.979769056736649350478165267195599E+461), - 238 => d128!(7.091850355033225454138033335925526E+463), - 239 => d128!(1.694952234852940883538989967286201E+466), - 240 => d128!(4.067885363647058120493575921486882E+468), - 241 => d128!(9.803603726389410070389517970783386E+470), - 242 => d128!(2.372472101786237237034263348929579E+473), - 243 => d128!(5.765107207340556485993259937898877E+475), - 244 => d128!(1.406686158591095782582355424847326E+478), - 245 => d128!(3.446381088548184667326770790875949E+480), - 246 => d128!(8.478097477828534281623856145554835E+482), - 247 => d128!(2.094090077023647967561092467952044E+485), - 248 => d128!(5.193343391018646959551509320521069E+487), - 249 => d128!(1.293142504363643092928325820809746E+490), - 250 => d128!(3.232856260909107732320814552024365E+492), - 251 => d128!(8.114469214881860408125244525581156E+494), - 252 => d128!(2.044846242150228822847561620446451E+497), - 253 => d128!(5.173460992640078921804330899729521E+499), - 254 => d128!(1.314059092130580046138300048531298E+502), - 255 => d128!(3.350850684932979117652665123754810E+504), - 256 => d128!(8.578177753428426541190822716812314E+506), - 257 => d128!(2.204591682631105621086041438220765E+509), - 258 => d128!(5.687846541188252502401986910609574E+511), - 259 => d128!(1.473152254167757398122114609847880E+514), - 260 => d128!(3.830195860836169235117497985604488E+516), - 261 => d128!(9.996811196782401703656669742427714E+518), - 262 => d128!(2.619164533556989246358047472516061E+521), - 263 => d128!(6.888402723254881717921664852717240E+523), - 264 => d128!(1.818538318939288773531319521117351E+526), - 265 => d128!(4.819126545189115249857996730960980E+528), - 266 => d128!(1.281887661020304656462227130435621E+531), - 267 => d128!(3.422640054924213432754146438263108E+533), - 268 => d128!(9.172675347196891999781112454545129E+535), - 269 => d128!(2.467449668395963947941119250272640E+538), - 270 => d128!(6.662114104669102659441021975736128E+540), - 271 => d128!(1.805432922365326820708516955424491E+543), - 272 => d128!(4.910777548833688952327166118754616E+545), - 273 => d128!(1.340642270831597083985316350420010E+548), - 274 => d128!(3.673359822078576010119766800150827E+550), - 275 => d128!(1.010173951071608402782935870041477E+553), - 276 => d128!(2.788080104957639191680903001314477E+555), - 277 => d128!(7.722981890732660560956101313641101E+557), - 278 => d128!(2.146988965623679635945796165192226E+560), - 279 => d128!(5.990099214090066184288771300886311E+562), - 280 => d128!(1.677227779945218531600855964248167E+565), - 281 => d128!(4.713010061646064073798405259537349E+567), - 282 => d128!(1.329068837384190068811150283189532E+570), - 283 => d128!(3.761264809797257894735555301426376E+572), - 284 => d128!(1.068199205982421242104897705605091E+575), - 285 => d128!(3.044367737049900539998958460974509E+577), - 286 => d128!(8.706891727962715544397021198387096E+579), - 287 => d128!(2.498877925925299361241945083937097E+582), - 288 => d128!(7.196768426664862160376801841738839E+584), - 289 => d128!(2.079866075306145164348895732262524E+587), - 290 => d128!(6.031611618387820976611797623561320E+589), - 291 => d128!(1.755198980950855904194033108456344E+592), - 292 => d128!(5.125181024376499240246576676692524E+594), - 293 => d128!(1.501678040142314277392246966270910E+597), - 294 => d128!(4.414933438018403975533206080836475E+599), - 295 => d128!(1.302405364215429172782295793846760E+602), - 296 => d128!(3.855119878077670351435595549786410E+604), - 297 => d128!(1.144970603789068094376371878286564E+607), - 298 => d128!(3.412012399291422921241588197293961E+609), - 299 => d128!(1.020191707388135453451234870990894E+612), - 300 => d128!(3.060575122164406360353704612972682E+614), - 301 => d128!(9.212331117714863144664650885047773E+616), - 302 => d128!(2.782123997549888669688724567284427E+619), - 303 => d128!(8.429835712576162669156835438871814E+621), - 304 => d128!(2.562670056623153451423677973417031E+624), - 305 => d128!(7.816143672700618026842217818921945E+626), - 306 => d128!(2.391739963846389116213718652590115E+629), - 307 => d128!(7.342641689008414586776116263451653E+631), - 308 => d128!(2.261533640214591692727043809143109E+634), - 309 => d128!(6.988138948263088330526565370252207E+636), - 310 => d128!(2.166323073961557382463235264778184E+639), - 311 => d128!(6.737264760020443459460661673460152E+641), - 312 => d128!(2.102026605126378359351726442119567E+644), - 313 => d128!(6.579343274045564264770903763834245E+646), - 314 => d128!(2.065913788050307179138063781843953E+649), - 315 => d128!(6.507628432358467614284900912808452E+651), - 316 => d128!(2.056410584625275766114028688447471E+654), - 317 => d128!(6.518821553262124178581470942378483E+656), - 318 => d128!(2.072985253937355488788907759676358E+659), - 319 => d128!(6.612822960060164009236615753367582E+661), - 320 => d128!(2.116103347219252482955717041077626E+664), - 321 => d128!(6.792691744573800470287851701859179E+666), - 322 => d128!(2.187246741752763751432688247998656E+669), - 323 => d128!(7.064806975861426917127583041035659E+671), - 324 => d128!(2.288997460179102321149336905295554E+674), - 325 => d128!(7.439241745582082543735344942210550E+676), - 326 => d128!(2.425192809059758909257722451160639E+679), - 327 => d128!(7.930380485625411633272752415295290E+681), - 328 => d128!(2.601164799285135015713462792216855E+684), - 329 => d128!(8.557832189648094201697292586393453E+686), - 330 => d128!(2.824084622583871086560106553509839E+689), - 331 => d128!(9.347720100752613296513952692117567E+691), - 332 => d128!(3.103443073449867614442632293783032E+694), - 333 => d128!(1.033446543458805915609396553829750E+697), - 334 => d128!(3.451711455152411758135384489791365E+699), - 335 => d128!(1.156323337476057938975353804080107E+702), - 336 => d128!(3.885246413919554674957188781709160E+704), - 337 => d128!(1.309328041490889925460572619435987E+707), - 338 => d128!(4.425528780239207948056735453693636E+709), - 339 => d128!(1.500254256501091494391233318802143E+712), - 340 => d128!(5.100864472103711080930193283927286E+714), - 341 => d128!(1.739394784987365478597195909819205E+717), - 342 => d128!(5.948730164656789936802410011581681E+719), - 343 => d128!(2.040414446477278948323226633972517E+722), - 344 => d128!(7.019025695881839582231899620865458E+724), - 345 => d128!(2.421563865079234655870005369198583E+727), - 346 => d128!(8.378610973174151909310218577427097E+729), - 347 => d128!(2.907378007691430712530645846367203E+732), - 348 => d128!(1.011767546676617887960664754535787E+735), - 349 => d128!(3.531068737901396428982719993329897E+737), - 350 => d128!(1.235874058265488750143951997665464E+740), - 351 => d128!(4.337917944511865513005271511805779E+742), - 352 => d128!(1.526947116468176660577855572155634E+745), - 353 => d128!(5.390123321132663611839830169709388E+747), - 354 => d128!(1.908103655680962918591299880077123E+750), - 355 => d128!(6.773767977667418360999114574273787E+752), - 356 => d128!(2.411461400049600936515684788441468E+755), - 357 => d128!(8.608917198177075343360994694736041E+757), - 358 => d128!(3.081992356947392972923236100715503E+760), - 359 => d128!(1.106435256144114077279441760156866E+763), - 360 => d128!(3.983166922118810678205990336564718E+765), - 361 => d128!(1.437923258884890654832362511499863E+768), - 362 => d128!(5.205282197163304170493152291629504E+770), - 363 => d128!(1.889517437570279413889014281861510E+773), - 364 => d128!(6.877843472755817066556011985975896E+775), - 365 => d128!(2.510412867555873229292944374881202E+778), - 366 => d128!(9.188111095254496019212176412065199E+780), - 367 => d128!(3.372036771958400039050868743227928E+783), - 368 => d128!(1.240909532080691214370719697507878E+786), - 369 => d128!(4.578956173377750581027955683804070E+788), - 370 => d128!(1.694213784149767714980343603007506E+791), - 371 => d128!(6.285533139195638222577074767157847E+793), - 372 => d128!(2.338218327780777418798671813382719E+796), - 373 => d128!(8.721554362622299772119045863917542E+798), - 374 => d128!(3.261861331620740114772523153105161E+801), - 375 => d128!(1.223197999357777543039696182414435E+804), - 376 => d128!(4.599224477585243561829257645878276E+806), - 377 => d128!(1.733907628049636822809630132496110E+809), - 378 => d128!(6.554170834027627190220401900835296E+811), - 379 => d128!(2.484030746096470705093532320416577E+814), - 380 => d128!(9.439316835166588679355422817582993E+816), - 381 => d128!(3.596379714198470286834416093499120E+819), - 382 => d128!(1.373817050823815649570746947716664E+822), - 383 => d128!(5.261719304655213937855960809754823E+824), - 384 => d128!(2.020500212987602152136688950945852E+827), - 385 => d128!(7.778925820002268285726252461141530E+829), - 386 => d128!(3.002665366520875558290333450000631E+832), - 387 => d128!(1.162031496843578841058359045150244E+835), - 388 => d128!(4.508682207753085903306433095182947E+837), - 389 => d128!(1.753877378815950416386202474026166E+840), - 390 => d128!(6.840121777382206623906189648702047E+842), - 391 => d128!(2.674487614956442789947320152642500E+845), - 392 => d128!(1.048399145062925573659349499835860E+848), - 393 => d128!(4.120208640097297504481243534354930E+850), - 394 => d128!(1.623362204198335216765609952535842E+853), - 395 => d128!(6.412280706583424106224159312516576E+855), - 396 => d128!(2.539263159807035946064767087756564E+858), - 397 => d128!(1.008087474443393270587712533839356E+861), - 398 => d128!(4.012188148284705216939095884680637E+863), - 399 => d128!(1.600863071165597381558699257987574E+866), - 400 => d128!(6.403452284662389526234797031950296E+868), - 401 => d128!(2.567784366149618200020153609812069E+871), - 402 => d128!(1.032249315192146516408101751144452E+874), - 403 => d128!(4.159964740224350461124650057112142E+876), - 404 => d128!(1.680625755050637586294358623073305E+879), - 405 => d128!(6.806534307955082224492152423446885E+881), - 406 => d128!(2.763452929029763383143813883919435E+884), - 407 => d128!(1.124725342115113696939532250755210E+887), - 408 => d128!(4.588879395829663883513291583081257E+889), - 409 => d128!(1.876851672894332528356936257480234E+892), - 410 => d128!(7.695091858866763366263438655668959E+894), - 411 => d128!(3.162682753994239743534273287479942E+897), - 412 => d128!(1.303025294645626774336120594441736E+900), - 413 => d128!(5.381494466886438578008178055044370E+902), - 414 => d128!(2.227938709290985571295385714788369E+905), - 415 => d128!(9.245945643557590120875850716371731E+907), - 416 => d128!(3.846313387719957490284353898010640E+910), - 417 => d128!(1.603912682679222273448575575470437E+913), - 418 => d128!(6.704355013599149103015045905466427E+915), - 419 => d128!(2.809124750698043474163304234390433E+918), - 420 => d128!(1.179832395293178259148587778443982E+921), - 421 => d128!(4.967094384184280471015554547249164E+923), - 422 => d128!(2.096113830125766358768564018939147E+926), - 423 => d128!(8.866561501431991697591025800112592E+928), - 424 => d128!(3.759422076607164479778594939247739E+931), - 425 => d128!(1.597754382558044903905902849180289E+934), - 426 => d128!(6.806433669697271290639146137508031E+936), - 427 => d128!(2.906347176960734841102915400715929E+939), - 428 => d128!(1.243916591739194511992047791506418E+942), - 429 => d128!(5.336402178561144456445885025562533E+944), - 430 => d128!(2.294652936781292116271730560991889E+947), - 431 => d128!(9.889954157527369021131158717875042E+949), - 432 => d128!(4.272460196051823417128660566122018E+952), - 433 => d128!(1.849975264890439539616710025130834E+955), - 434 => d128!(8.028892649624507601936521509067820E+957), - 435 => d128!(3.492568302586660806842386856444502E+960), - 436 => d128!(1.522759779927784111783280669409803E+963), - 437 => d128!(6.654460238284416568492936525320839E+965), - 438 => d128!(2.914653584368574456999906198090527E+968), - 439 => d128!(1.279532923537804186622958820961741E+971), - 440 => d128!(5.629944863566338421141018812231660E+973), - 441 => d128!(2.482805684832755243723189296194162E+976), - 442 => d128!(1.097400112696077817725649668917820E+979), - 443 => d128!(4.861482499243624732524628033305943E+981), - 444 => d128!(2.158498229664169381240934846787839E+984), - 445 => d128!(9.605317122005553746522160068205884E+986), - 446 => d128!(4.283971436414476970948883390419824E+989), - 447 => d128!(1.914935232077271206014150875517661E+992), - 448 => d128!(8.578909839706175002943395922319121E+994), - 449 => d128!(3.851930518028072576321584769121285E+997), - 450 => d128!(1.733368733112632659344713146104578E+1000), - 451 => d128!(7.817492986337973293644656288931647E+1002), - 452 => d128!(3.533506829824763928727384642597104E+1005), - 453 => d128!(1.600678593910618059713505243096488E+1008), - 454 => d128!(7.267080816354205991099313803658056E+1010), - 455 => d128!(3.306521771441163725950187780664415E+1013), - 456 => d128!(1.507773927777170659033285627982973E+1016), - 457 => d128!(6.890526849941669911782115319882187E+1018), - 458 => d128!(3.155861297273284819596208816506042E+1021), - 459 => d128!(1.448540335448437732194659846776273E+1024), - 460 => d128!(6.663285543062813568095435295170856E+1026), - 461 => d128!(3.071774635351957054891995671073765E+1029), - 462 => d128!(1.419159881532604159360102000036079E+1032), - 463 => d128!(6.570710251495957257837272260167046E+1034), - 464 => d128!(3.048809556694124167636494328717509E+1037), - 465 => d128!(1.417696443862767737950969862853642E+1040), - 466 => d128!(6.606465428400497658851519560897972E+1042), - 467 => d128!(3.085219355063032406683659634939353E+1045), - 468 => d128!(1.443882658169499166327952709151617E+1048), - 469 => d128!(6.771809666814951090078098205921084E+1050), - 470 => d128!(3.182750543403027012336706156782909E+1053), - 471 => d128!(1.499075505942825722810588599844750E+1056), - 472 => d128!(7.075636388050137411665978191267220E+1058), - 473 => d128!(3.346776011547714995718007684469395E+1061), - 474 => d128!(1.586371829473616907970335642438493E+1064), - 475 => d128!(7.535266189999680312859094301582842E+1066), - 476 => d128!(3.586786706439847828920928887553433E+1069), - 477 => d128!(1.710897258971807414395283079362988E+1072), - 478 => d128!(8.178088897885239440809453119355083E+1074), - 479 => d128!(3.917304582087029692147728044171085E+1077), - 480 => d128!(1.880306199401774252230909461202121E+1080), - 481 => d128!(9.044272819122534153230674508382202E+1082), - 482 => d128!(4.359339498817061461857185113040221E+1085), - 483 => d128!(2.105560977928640686077020409598427E+1088), - 484 => d128!(1.019091513317462092061277878245639E+1091), - 485 => d128!(4.942593839589691146497197709491349E+1093), - 486 => d128!(2.402100606040589897197638086812796E+1096), - 487 => d128!(1.169822995141767279935249748277832E+1099), - 488 => d128!(5.708736216291824326084018771595820E+1101), - 489 => d128!(2.791572009766702095455085179310356E+1104), - 490 => d128!(1.367870284785684026772991737862074E+1107), - 491 => d128!(6.716243098297708571455389432902783E+1109), - 492 => d128!(3.304391604362472617156051600988169E+1112), - 493 => d128!(1.629065060950699000257933439287167E+1115), - 494 => d128!(8.047581401096453061274191190078605E+1117), - 495 => d128!(3.983552793542744265330724639088909E+1120), - 496 => d128!(1.975842185597201155604039420988099E+1123), - 497 => d128!(9.819935662418089743352075922310852E+1125), - 498 => d128!(4.890327959884208692189333809310804E+1128), - 499 => d128!(2.440273651982220137402477570846091E+1131), - 500 => d128!(1.220136825991110068701238785423046E+1134), - 501 => d128!(6.112885498215461444193206314969460E+1136), - 502 => d128!(3.068668520104161644984989570114669E+1139), - 503 => d128!(1.543540265612393307427449753767679E+1142), - 504 => d128!(7.779442938686462269434346758989102E+1144), - 505 => d128!(3.928618684036663446064345113289497E+1147), - 506 => d128!(1.987881054122551703708558627324485E+1150), - 507 => d128!(1.007855694440133713780239224053514E+1153), - 508 => d128!(5.119906927755879266003615258191851E+1155), - 509 => d128!(2.606032626227742546395840166419652E+1158), - 510 => d128!(1.329076639376148698661878484874023E+1161), - 511 => d128!(6.791581627212119850162199057706258E+1163), - 512 => d128!(3.477289793132605363283045917545604E+1166), - 513 => d128!(1.783849663877026551364202555700895E+1169), - 514 => d128!(9.168987272327916474012001136302600E+1171), - 515 => d128!(4.722028445248876984116180585195839E+1174), - 516 => d128!(2.436566677748420523803949181961053E+1177), - 517 => d128!(1.259704972395933410806641727073864E+1180), - 518 => d128!(6.525271757010935067978404146242616E+1182), - 519 => d128!(3.386616041888675300280791751899918E+1185), - 520 => d128!(1.761040341782111156146011710987957E+1188), - 521 => d128!(9.175020180684799123520721014247256E+1190), - 522 => d128!(4.789360534317465142477816369437068E+1193), - 523 => d128!(2.504835559448034269515897961215587E+1196), - 524 => d128!(1.312533833150769957226330531676968E+1199), - 525 => d128!(6.890802624041542275438235291304082E+1201), - 526 => d128!(3.624562180245851236880511763225947E+1204), - 527 => d128!(1.910144268989563601836029699220074E+1207), - 528 => d128!(1.008556174026489581769423681188199E+1210), - 529 => d128!(5.335262160600129887560251273485573E+1212), - 530 => d128!(2.827688945118068840406933174947354E+1215), - 531 => d128!(1.501502829857694554256081515897045E+1218), - 532 => d128!(7.987995054842935028642353664572279E+1220), - 533 => d128!(4.257601364231284370266374503217025E+1223), - 534 => d128!(2.273559128499505853722243984717891E+1226), - 535 => d128!(1.216354133747235631741400531824072E+1229), - 536 => d128!(6.519658156885182986133906850577026E+1231), - 537 => d128!(3.501056430247343263553907978759863E+1234), - 538 => d128!(1.883568359473070675792002492572806E+1237), - 539 => d128!(1.015243345755985094251889343496742E+1240), - 540 => d128!(5.482314067082319508960202454882407E+1242), - 541 => d128!(2.965931910291534854347469528091382E+1245), - 542 => d128!(1.607535095378011891056328484225529E+1248), - 543 => d128!(8.728915567902604568435863669344622E+1250), - 544 => d128!(4.748530068939016885229109836123474E+1253), - 545 => d128!(2.587948887571764202449864860687293E+1256), - 546 => d128!(1.413020092614183254537626213935262E+1259), - 547 => d128!(7.729219906599582402320815390225883E+1261), - 548 => d128!(4.235612508816571156471806833843784E+1264), - 549 => d128!(2.325351267340297564903021951780237E+1267), - 550 => d128!(1.278943197037163660696662073479130E+1270), - 551 => d128!(7.046977015674771770438608024870006E+1272), - 552 => d128!(3.889931312652474017282111629728243E+1275), - 553 => d128!(2.151132015896818131557007731239718E+1278), - 554 => d128!(1.191727136806837244882582283106804E+1281), - 555 => d128!(6.614085609277946709098331671242762E+1283), - 556 => d128!(3.677431598758538370258672409210976E+1286), - 557 => d128!(2.048329400508505872234080531930514E+1289), - 558 => d128!(1.142967805483746276706616936817227E+1292), - 559 => d128!(6.389190032654141686789988676808299E+1294), - 560 => d128!(3.577946418286319344602393659012647E+1297), - 561 => d128!(2.007227940658625152321942842706095E+1300), - 562 => d128!(1.128062102650147335604931877600825E+1303), - 563 => d128!(6.350989637920329499455766470892645E+1305), - 564 => d128!(3.581958155787065837693052289583452E+1308), - 565 => d128!(2.023806358019692198296574543614650E+1311), - 566 => d128!(1.145474398639145784235861191685892E+1314), - 567 => d128!(6.494839840283956596617332956859008E+1316), - 568 => d128!(3.689069029281287346878645119495917E+1319), - 569 => d128!(2.099080277661052500373949072993177E+1322), - 570 => d128!(1.196475758266799925213150971606111E+1325), - 571 => d128!(6.831876579703427572967092047870894E+1327), - 572 => d128!(3.907833403590360571737176651382151E+1330), - 573 => d128!(2.239188540257276607605402221241973E+1333), - 574 => d128!(1.285294222107676772765500874992893E+1336), - 575 => d128!(7.390441777119141443401630031209135E+1338), - 576 => d128!(4.256894463620625471399338897976462E+1341), - 577 => d128!(2.456228105509100896997418544132419E+1344), - 578 => d128!(1.419699844984260318464507918508538E+1347), - 579 => d128!(8.220062102458867243909500848164435E+1349), - 580 => d128!(4.767636019426143001467510491935372E+1352), - 581 => d128!(2.769996527286589083852623595814451E+1355), - 582 => d128!(1.612137978880794846802226932764010E+1358), - 583 => d128!(9.398764416875033956856983018014178E+1360), - 584 => d128!(5.488878419455019830804478082520280E+1363), - 585 => d128!(3.210993875381186601020619678274364E+1366), - 586 => d128!(1.881642410973375348198083131468777E+1369), - 587 => d128!(1.104524095241371329392274798172172E+1372), - 588 => d128!(6.494601680019263416826575813252371E+1374), - 589 => d128!(3.825320389531346152510853154005647E+1377), - 590 => d128!(2.256939029823494229981403360863332E+1380), - 591 => d128!(1.333850966625685089919009386270229E+1383), - 592 => d128!(7.896397722424055732320535566719756E+1385), - 593 => d128!(4.682563849397465049266077591064815E+1388), - 594 => d128!(2.781442926542094239264050089092500E+1391), - 595 => d128!(1.654958541292546072362109803010038E+1394), - 596 => d128!(9.863552906103574591278174425939826E+1396), - 597 => d128!(5.888541084943834030993070132286076E+1399), - 598 => d128!(3.521347568796412750533855939107073E+1402), - 599 => d128!(2.109287193709051237569779707525137E+1405), - 600 => d128!(1.265572316225430742541867824515082E+1408), - 601 => d128!(7.606089620514838762676625625335643E+1410), - 602 => d128!(4.578865951549932935131328626452057E+1413), - 603 => d128!(2.761056168784609559884191161750590E+1416), - 604 => d128!(1.667677925945904174170051461697356E+1419), - 605 => d128!(1.008945145197272025372881134326900E+1422), - 606 => d128!(6.114207579895468473759659674021014E+1424), - 607 => d128!(3.711324000996549363572113422130755E+1427), - 608 => d128!(2.256484992605902013051844960655499E+1430), - 609 => d128!(1.374199360496994325948573581039199E+1433), - 610 => d128!(8.382616099031665388286298844339114E+1435), - 611 => d128!(5.121778436508347552242928593891199E+1438), - 612 => d128!(3.134528403143108701972672299461414E+1441), - 613 => d128!(1.921465911126725634309248119569847E+1444), - 614 => d128!(1.179780069431809539465878345415886E+1447), - 615 => d128!(7.255647427005628667715151824307699E+1449), - 616 => d128!(4.469478815035467259312533523773543E+1452), - 617 => d128!(2.757668428876883298995833184168276E+1455), - 618 => d128!(1.704239089045913878779424907815995E+1458), - 619 => d128!(1.054923996119420690964464017938101E+1461), - 620 => d128!(6.540528775940408283979676911216226E+1463), - 621 => d128!(4.061668369858993544351379361865276E+1466), - 622 => d128!(2.526357726052293984586557963080202E+1469), - 623 => d128!(1.573920863330579152397425610998966E+1472), - 624 => d128!(9.821266187182813910959935812633548E+1474), - 625 => d128!(6.138291366989258694349959882895968E+1477), - 626 => d128!(3.842570395735275942663074886692876E+1480), - 627 => d128!(2.409291638126018016049747953956433E+1483), - 628 => d128!(1.513035148743139314079241715084640E+1486), - 629 => d128!(9.516991085594346285558430387882386E+1488), - 630 => d128!(5.995704383924438159901811144365903E+1491), - 631 => d128!(3.783289466256320478898042832094885E+1494), - 632 => d128!(2.391038942673994542663563069883967E+1497), - 633 => d128!(1.513527650712638545506035423236551E+1500), - 634 => d128!(9.595765305518128378508264583319733E+1502), - 635 => d128!(6.093310969004011520352748010408030E+1505), - 636 => d128!(3.875345776286551326944347734619507E+1508), - 637 => d128!(2.468595259494533195263549506952626E+1511), - 638 => d128!(1.574963775557512178578144585435775E+1514), - 639 => d128!(1.006401852581250282111434390093460E+1517), - 640 => d128!(6.440971856520001805513180096598144E+1519), - 641 => d128!(4.128662960029321157333948441919410E+1522), - 642 => d128!(2.650601620338824183008394899712261E+1525), - 643 => d128!(1.704336841877863949674397920514984E+1528), - 644 => d128!(1.097592926169344383590312260811650E+1531), - 645 => d128!(7.079474373792271274157514082235142E+1533), - 646 => d128!(4.573340445469807243105754097123902E+1536), - 647 => d128!(2.958951268218965286289422900839165E+1539), - 648 => d128!(1.917400421805889505515546039743779E+1542), - 649 => d128!(1.244392873752022289079589379793713E+1545), - 650 => d128!(8.088553679388144879017330968659134E+1547), - 651 => d128!(5.265648445281682316240282460597096E+1550), - 652 => d128!(3.433202786323656870188664164309307E+1553), - 653 => d128!(2.241881419469347936233197699293977E+1556), - 654 => d128!(1.466190448332953550296511295338261E+1559), - 655 => d128!(9.603547436580845754442148984465610E+1561), - 656 => d128!(6.299927118397034814914049733809440E+1564), - 657 => d128!(4.139052116786851873398530675112802E+1567), - 658 => d128!(2.723496292845748532696233184224224E+1570), - 659 => d128!(1.794784056985348283046817668403764E+1573), - 660 => d128!(1.184557477610329866810899661146484E+1576), - 661 => d128!(7.829924927004280419620046760178259E+1578), - 662 => d128!(5.183410301676833637788470955238007E+1581), - 663 => d128!(3.436601030011740701853756243322799E+1584), - 664 => d128!(2.281903083927795826030894145566339E+1587), - 665 => d128!(1.517465550811984224310544606801615E+1590), - 666 => d128!(1.010632056840781493390822708129876E+1593), - 667 => d128!(6.740915819128012560916787463226273E+1595), - 668 => d128!(4.502931767177512390692414025435150E+1598), - 669 => d128!(3.012461352241755789373224983016115E+1601), - 670 => d128!(2.018349106001976378880060738620797E+1604), - 671 => d128!(1.354312250127326150228520755614555E+1607), - 672 => d128!(9.100978320855631729535659477729810E+1609), - 673 => d128!(6.124958409935840153977498828512162E+1612), - 674 => d128!(4.128221968296756263780834210417197E+1615), - 675 => d128!(2.786549828600310478052063092031608E+1618), - 676 => d128!(1.883707684133809883163194650213367E+1621), - 677 => d128!(1.275270102158589290901482778194449E+1624), - 678 => d128!(8.646331292635235392312053236158364E+1626), - 679 => d128!(5.870858947699324831379884147351529E+1629), - 680 => d128!(3.992184084435540885338321220199040E+1632), - 681 => d128!(2.718677361500603342915396750955546E+1635), - 682 => d128!(1.854137960543411479868300584151682E+1638), - 683 => d128!(1.266376227051150040750049298975599E+1641), - 684 => d128!(8.662013393029866278730337204993097E+1643), - 685 => d128!(5.933479174225458400930280985420271E+1646), - 686 => d128!(4.070366713518664463038172755998306E+1649), - 687 => d128!(2.796341932187322486107224683370836E+1652), - 688 => d128!(1.923883249344877870441770582159135E+1655), - 689 => d128!(1.325555558798620852734379931107644E+1658), - 690 => d128!(9.146333355710483883867221524642744E+1660), - 691 => d128!(6.320116348795944363752250073528136E+1663), - 692 => d128!(4.373520513366793499716557050881470E+1666), - 693 => d128!(3.030849715763187895303574036260859E+1669), - 694 => d128!(2.103409702739652399340680381165036E+1672), - 695 => d128!(1.461869743404058417541772864909700E+1675), - 696 => d128!(1.017461341409224658609073913977151E+1678), - 697 => d128!(7.091705549622295870505245180420742E+1680), - 698 => d128!(4.950010473636362517612661135933678E+1683), - 699 => d128!(3.460057321071817399811250134017641E+1686), - 700 => d128!(2.422040124750272179867875093812349E+1689), - 701 => d128!(1.697850127449940798087380440762457E+1692), - 702 => d128!(1.191890789469858440257341069415245E+1695), - 703 => d128!(8.378992249973104835009107717989172E+1697), - 704 => d128!(5.898810543981065803846411833464377E+1700), - 705 => d128!(4.158661433506651391711720342592386E+1703), - 706 => d128!(2.936014972055695882548474561870225E+1706), - 707 => d128!(2.075762585243376988961771515242249E+1709), - 708 => d128!(1.469639910352310908184934232791512E+1712), - 709 => d128!(1.041974696439788433903118371049182E+1715), - 710 => d128!(7.398020344722497880712140434449192E+1717), - 711 => d128!(5.259992465097695993186331848893376E+1720), - 712 => d128!(3.745114635149559547148668276412084E+1723), - 713 => d128!(2.670266734861635957117000481081816E+1726), - 714 => d128!(1.906570448691208073381538343492417E+1729), - 715 => d128!(1.363197870814213772467799915597078E+1732), - 716 => d128!(9.760496755029770610869447395675078E+1734), - 717 => d128!(6.998276173356345527993393782699031E+1737), - 718 => d128!(5.024762292469856089099256735977904E+1740), - 719 => d128!(3.612804088285826528062365593168113E+1743), - 720 => d128!(2.601218943565795100204903227081041E+1746), - 721 => d128!(1.875478858310938267247735226725431E+1749), - 722 => d128!(1.354095735700497428952864833695761E+1752), - 723 => d128!(9.790112169114596411329212747620352E+1754), - 724 => d128!(7.088041210438967801802350029277135E+1757), - 725 => d128!(5.138829877568251656306703771225923E+1760), - 726 => d128!(3.730790491114550702478666937910020E+1763), - 727 => d128!(2.712284687040278360701990863860585E+1766), - 728 => d128!(1.974543252165322646591049348890506E+1769), - 729 => d128!(1.439442030828520209364874975341179E+1772), - 730 => d128!(1.050792682504819752836358731999061E+1775), - 731 => d128!(7.681294509110232393233782330913136E+1777), - 732 => d128!(5.622707580668690111847128666228416E+1780), - 733 => d128!(4.121444656630149851983945312345429E+1783), - 734 => d128!(3.025140377966529991356215859261545E+1786), - 735 => d128!(2.223478177805399543646818656557236E+1789), - 736 => d128!(1.636479938864774064124058531226126E+1792), - 737 => d128!(1.206085714943338485259431137513655E+1795), - 738 => d128!(8.900912576281838021214601794850774E+1797), - 739 => d128!(6.577774393872278297677590726394722E+1800), - 740 => d128!(4.867553051465485940281417137532094E+1803), - 741 => d128!(3.606856811135925081748530098911282E+1806), - 742 => d128!(2.676287753862856410657409333392171E+1809), - 743 => d128!(1.988481801120102313118455134710383E+1812), - 744 => d128!(1.479430460033356120960130620224525E+1815), - 745 => d128!(1.102175692724850310115297312067271E+1818), - 746 => d128!(8.222230667727383313460117948021842E+1820), - 747 => d128!(6.142006308792355335154708107172316E+1823), - 748 => d128!(4.594220718976681790695721664164892E+1826), - 749 => d128!(3.441071318513534661231095526459504E+1829), - 750 => d128!(2.580803488885150995923321644844628E+1832), - 751 => d128!(1.938183420152748397938414555278316E+1835), - 752 => d128!(1.457513931954866795249687745569294E+1838), - 753 => d128!(1.097507990762014696823014872413678E+1841), - 754 => d128!(8.275210250345590814045532137999132E+1843), - 755 => d128!(6.247783739010921064604376764189345E+1846), - 756 => d128!(4.723324506692256324840908833727145E+1849), - 757 => d128!(3.575556651566038037904567987131449E+1852), - 758 => d128!(2.710271941887056832731662534245638E+1855), - 759 => d128!(2.057096403892276136043331863492439E+1858), - 760 => d128!(1.563393266958129863392932216254254E+1861), - 761 => d128!(1.189742276155136826042021416569487E+1864), - 762 => d128!(9.065836144302142614440203194259491E+1866), - 763 => d128!(6.917232978102534814817875037219992E+1869), - 764 => d128!(5.284765995270336598520856528436074E+1872), - 765 => d128!(4.042845986381807497868455244253597E+1875), - 766 => d128!(3.096820025568464543367236717098255E+1878), - 767 => d128!(2.375260959611012304762670562014362E+1881), - 768 => d128!(1.824200416981257450057730991627030E+1884), - 769 => d128!(1.402810120658586979094395132561186E+1887), - 770 => d128!(1.080163792907111973902684252072113E+1890), - 771 => d128!(8.328062843313833318789695583475991E+1892), - 772 => d128!(6.429264515038279322105644990443465E+1895), - 773 => d128!(4.969821470124589915987663577612798E+1898), - 774 => d128!(3.846641817876432594974451609072306E+1901), - 775 => d128!(2.981147408854235261105199997031037E+1904), - 776 => d128!(2.313370389270886562617635197696085E+1907), - 777 => d128!(1.797488792463478859153902548609858E+1910), - 778 => d128!(1.398446280536586552421736182818470E+1913), - 779 => d128!(1.089389652538000924336532486415588E+1916), - 780 => d128!(8.497239289796407209824953394041586E+1918), - 781 => d128!(6.636343885330994030873288600746479E+1921), - 782 => d128!(5.189620918328837332142911685783747E+1924), - 783 => d128!(4.063473179051479631067899849968674E+1927), - 784 => d128!(3.185762972376360030757233482375440E+1930), - 785 => d128!(2.500823933315442624144428283664720E+1933), - 786 => d128!(1.965647611585937902577520630960470E+1936), - 787 => d128!(1.546964670318133129328508736565890E+1939), - 788 => d128!(1.219008160210688905910864884413921E+1942), - 789 => d128!(9.617974384062335467636723938025837E+1944), - 790 => d128!(7.598199763409245019433011911040411E+1947), - 791 => d128!(6.010176012856712810371512421632965E+1950), - 792 => d128!(4.760059402182516545814237837933308E+1953), - 793 => d128!(3.774727105930735620830690605481113E+1956), - 794 => d128!(2.997133322109004082939568340752004E+1959), - 795 => d128!(2.382720991076658245936956830897843E+1962), - 796 => d128!(1.896645908897019963765817637394683E+1965), - 797 => d128!(1.511626789390924911121356657003562E+1968), - 798 => d128!(1.206278177933958079074842612288842E+1971), - 799 => d128!(9.638162641692325051807992472187848E+1973), - 800 => d128!(7.710530113353860041446393977750278E+1976), - 801 => d128!(6.176134620796441893198561576177973E+1979), - 802 => d128!(4.953259965878746398345246384094734E+1982), - 803 => d128!(3.977467752600633357871232846428071E+1985), - 804 => d128!(3.197884073090909219728471208528169E+1988), - 805 => d128!(2.574296678838181921881419322865176E+1991), - 806 => d128!(2.074883123143574629036423974229332E+1994), - 807 => d128!(1.674430680376864725632394147203071E+1997), - 808 => d128!(1.352939989744506698310974470940081E+2000), - 809 => d128!(1.094528451703305918933578346990526E+2003), - 810 => d128!(8.865680458796777943361984610623261E+2005), - 811 => d128!(7.190066852084186912066569519215465E+2008), - 812 => d128!(5.838334283892359772598054449602958E+2011), - 813 => d128!(4.746565772804488495122218267527205E+2014), - 814 => d128!(3.863704539062853635029485669767145E+2017), - 815 => d128!(3.148919199336225712549030820860223E+2020), - 816 => d128!(2.569518066658360181440009149821942E+2023), - 817 => d128!(2.099296260459880268236487475404527E+2026), - 818 => d128!(1.717224341056182059417446754880903E+2029), - 819 => d128!(1.406406735325013106662888892247460E+2032), - 820 => d128!(1.153253522966510747463568891642917E+2035), - 821 => d128!(9.468211423555053236675900600388349E+2037), - 822 => d128!(7.782869790162253760547590293519223E+2040), - 823 => d128!(6.405301837303534844930666811566321E+2043), - 824 => d128!(5.277968713938112712222869452730649E+2046), - 825 => d128!(4.354324188998942987583867298502785E+2049), - 826 => d128!(3.596671780113126907744274388563300E+2052), - 827 => d128!(2.974447562153555952704514919341849E+2055), - 828 => d128!(2.462842581463144328839338353215051E+2058), - 829 => d128!(2.041696500032946648607811494815277E+2061), - 830 => d128!(1.694608095027345718344483540696680E+2064), - 831 => d128!(1.408219326967724291944265822318941E+2067), - 832 => d128!(1.171638480037146610897629164169359E+2070), - 833 => d128!(9.759748538709431268777250937530760E+2072), - 834 => d128!(8.139630281283665678160227281900654E+2075), - 835 => d128!(6.796591284871860841263789780387046E+2078), - 836 => d128!(5.681950314152875663296528256403570E+2081), - 837 => d128!(4.755792412945956930179194150609788E+2084), - 838 => d128!(3.985354042048711907490164698211002E+2087), - 839 => d128!(3.343712041278869290384248181799031E+2090), - 840 => d128!(2.808718114674250203922768472711186E+2093), - 841 => d128!(2.362131934441044421499048285550107E+2096), - 842 => d128!(1.988915088799359402902198656433190E+2099), - 843 => d128!(1.676655419857859976646553467373179E+2102), - 844 => d128!(1.415097174360033820289691126462963E+2105), - 845 => d128!(1.195757112334228578144789001861204E+2108), - 846 => d128!(1.011610517034757377110491495574579E+2111), - 847 => d128!(8.568341079284394984125862967516684E+2113), - 848 => d128!(7.265953235233166946538731796454148E+2116), - 849 => d128!(6.168794296712958737611383295189572E+2119), - 850 => d128!(5.243475152206014926969675800911136E+2122), - 851 => d128!(4.462197354527318702851194106575377E+2125), - 852 => d128!(3.801792146057275534829217378802221E+2128), - 853 => d128!(3.242928700586856031209322424118295E+2131), - 854 => d128!(2.769461110301175050652761350197024E+2134), - 855 => d128!(2.367889249307504668308110954418456E+2137), - 856 => d128!(2.026913197407223996071742976982198E+2140), - 857 => d128!(1.737064610177990964633483731273744E+2143), - 858 => d128!(1.490401435532716247655529041432872E+2146), - 859 => d128!(1.280254833122603256736099446590837E+2149), - 860 => d128!(1.101019156485438800793045524068120E+2152), - 861 => d128!(9.479774937339628074828121962226513E+2154), - 862 => d128!(8.171565995986759400501841131439254E+2157), - 863 => d128!(7.052061454536573362633088896432076E+2160), - 864 => d128!(6.092981096719599385314988806517314E+2163), - 865 => d128!(5.270428648662453468297465317637477E+2166), - 866 => d128!(4.564191209741684703545604965074055E+2169), - 867 => d128!(3.957153778846040637974039504719206E+2172), - 868 => d128!(3.434809480038363273761466290096271E+2175), - 869 => d128!(2.984849438153337684898714206093659E+2178), - 870 => d128!(2.596819011193403785861881359301483E+2181), - 871 => d128!(2.261829358749454697485698663951592E+2184), - 872 => d128!(1.972315200829524496207529234965788E+2187), - 873 => d128!(1.721831170324174885189173022125133E+2190), - 874 => d128!(1.504880442863328849655337221337366E+2193), - 875 => d128!(1.316770387505412743448420068670195E+2196), - 876 => d128!(1.153490859454741563260815980155091E+2199), - 877 => d128!(1.011611483741808350979735614596015E+2202), - 878 => d128!(8.881948827253077321602078696153012E+2204), - 879 => d128!(7.807233019155454965688227173918498E+2207), - 880 => d128!(6.870365056856800369805639913048278E+2210), - 881 => d128!(6.052791615090841125798768763395533E+2213), - 882 => d128!(5.338562204510121872954514049314860E+2216), - 883 => d128!(4.713950426582437613818835905545021E+2219), - 884 => d128!(4.167132177098874850615850940501799E+2222), - 885 => d128!(3.687911976732504242795028082344092E+2225), - 886 => d128!(3.267490011384998759116394880956866E+2228), - 887 => d128!(2.898263640098493899336242259408740E+2231), - 888 => d128!(2.573658112407462582610583126354961E+2234), - 889 => d128!(2.287982061930234235940808399329560E+2237), - 890 => d128!(2.036304035117908469987319475403308E+2240), - 891 => d128!(1.814346895290056446758701652584347E+2243), - 892 => d128!(1.618397430598730350508761874105238E+2246), - 893 => d128!(1.445228905524666203004324353575978E+2249), - 894 => d128!(1.292034641539051585485865972096924E+2252), - 895 => d128!(1.156371004177451169009850045026747E+2255), - 896 => d128!(1.036108419742996247432825640343965E+2258), - 897 => d128!(9.293892525094676339472445993885366E+2260), - 898 => d128!(8.345915487535019352846256502509059E+2263), - 899 => d128!(7.502978023293982398208784595755644E+2266), - 900 => d128!(6.752680220964584158387906136180080E+2269), - 901 => d128!(6.084164879089090326707503428698252E+2272), - 902 => d128!(5.487916720938359474690168092685823E+2275), - 903 => d128!(4.955588799007338605645221787695298E+2278), - 904 => d128!(4.479852274302634099503280496076549E+2281), - 905 => d128!(4.054266308243883860050468848949277E+2284), - 906 => d128!(3.673165275268958777205724777148045E+2287), - 907 => d128!(3.331560904668945610925592372873277E+2290), - 908 => d128!(3.025057301439402614720437874568936E+2293), - 909 => d128!(2.749777087008416976780878027983163E+2296), - 910 => d128!(2.502297149177659448870599005464678E+2299), - 911 => d128!(2.279592702900847757921115693978322E+2302), - 912 => d128!(2.078988545045573155224057512908230E+2305), - 913 => d128!(1.898116541626608290719564509285214E+2308), - 914 => d128!(1.734878519046719977717681961486686E+2311), - 915 => d128!(1.587413844927748779611678994760318E+2314), - 916 => d128!(1.454071081953817882124297959200451E+2317), - 917 => d128!(1.333383182151650997907981228586814E+2320), - 918 => d128!(1.224045761215215616079526767842695E+2323), - 919 => d128!(1.124898054556783151177085099647437E+2326), - 920 => d128!(1.034906210192240499082918291675642E+2329), - 921 => d128!(9.531486195870534996553677466332663E+2331), - 922 => d128!(8.788030272592633266822490623958715E+2334), - 923 => d128!(8.111351941603000505277158845913894E+2337), - 924 => d128!(7.494889194041172466876094773624438E+2340), - 925 => d128!(6.932772504488084531860387665602605E+2343), - 926 => d128!(6.419747339155966276502718978348012E+2346), - 927 => d128!(5.951105783397580738318020492928607E+2349), - 928 => d128!(5.522626166992954925159123017437747E+2352), - 929 => d128!(5.130519709136455125472825283199667E+2355), - 930 => d128!(4.771383329496903266689727513375690E+2358), - 931 => d128!(4.442157879761616941288136314952767E+2361), - 932 => d128!(4.140091143937826989280543045535979E+2364), - 933 => d128!(3.862705037293992580998746661485068E+2367), - 934 => d128!(3.607766504832589070652829381827054E+2370), - 935 => d128!(3.373261682018470781060395472008295E+2373), - 936 => d128!(3.157372934369288651072530161799764E+2376), - 937 => d128!(2.958458439504023466054960761606379E+2379), - 938 => d128!(2.775034016254774011159553194386784E+2382), - 939 => d128!(2.605756941263232796478820449529190E+2385), - 940 => d128!(2.449411524787438828690091222557439E+2388), - 941 => d128!(2.304896244824979937797375840426550E+2391), - 942 => d128!(2.171212262625131101405128041681810E+2394), - 943 => d128!(2.047453163655498628625035743305947E+2397), - 944 => d128!(1.932795786490790705422033741680814E+2400), - 945 => d128!(1.826492018233797216623821885888369E+2403), - 946 => d128!(1.727861449249172166926135504050397E+2406), - 947 => d128!(1.636284792438966042079050322335726E+2409), - 948 => d128!(1.551197983232139807890939705574268E+2412), - 949 => d128!(1.472086886087300677688501780589980E+2415), - 950 => d128!(1.398482541782935643804076691560481E+2418), - 951 => d128!(1.329956897235571797257676933674017E+2421), - 952 => d128!(1.266118966168264350989308440857664E+2424), - 953 => d128!(1.206611374758355926492810944137354E+2427), - 954 => d128!(1.151107251519471553874141640707036E+2430), - 955 => d128!(1.099307425201095333949805266875219E+2433), - 956 => d128!(1.050937898492247139256013835132709E+2436), - 957 => d128!(1.005747568857080512268005240222003E+2439), - 958 => d128!(9.635061709650831307527490201326789E+2441), - 959 => d128!(9.240024179555147223918863103072391E+2444), - 960 => d128!(8.870423212372941334962108578949495E+2447), - 961 => d128!(8.524476707090396622898586344370465E+2450), - 962 => d128!(8.200546592220961551228440063284387E+2453), - 963 => d128!(7.897126368308785973832987780942865E+2456), - 964 => d128!(7.612829819049669678775000220828922E+2459), - 965 => d128!(7.346380775382931240017875213099910E+2462), - 966 => d128!(7.096603829019911577857267455854513E+2465), - 967 => d128!(6.862415902662254495787977629811314E+2468), - 968 => d128!(6.642818593777062351922762345657352E+2471), - 969 => d128!(6.436891217369973419013156712941974E+2474), - 970 => d128!(6.243784480848874216442762011553715E+2477), - 971 => d128!(6.062714730904256864165921913218657E+2480), - 972 => d128!(5.892958718438937671969276099648535E+2483), - 973 => d128!(5.733848833041086354826105644958025E+2486), - 974 => d128!(5.584768763382018109600626898189116E+2489), - 975 => d128!(5.445149544297467656860611225734388E+2492), - 976 => d128!(5.314465955234328433095956556316763E+2495), - 977 => d128!(5.192233238263938879134749555521477E+2498), - 978 => d128!(5.078004107022132223793785065300005E+2501), - 979 => d128!(4.971366020774667447094115578928705E+2504), - 980 => d128!(4.871938700359174098152233267350131E+2507), - 981 => d128!(4.779371865052349790287340835270479E+2510), - 982 => d128!(4.693343171481407494062168700235610E+2513), - 983 => d128!(4.613556337566223566663111832331605E+2516), - 984 => d128!(4.539739436165163989596502043014299E+2519), - 985 => d128!(4.471643344622686529752554512369085E+2522), - 986 => d128!(4.409040337797968918336018749195918E+2525), - 987 => d128!(4.351722813406595322397650505456371E+2528), - 988 => d128!(4.299502139645716178528878699390895E+2531), - 989 => d128!(4.252207616109613300565061033697595E+2534), - 990 => d128!(4.209685539948517167559410423360619E+2537), - 991 => d128!(4.171798370088980513051375729550373E+2540), - 992 => d128!(4.138423983128268668946964723713970E+2543), - 993 => d128!(4.109455015246370788264335970647972E+2546), - 994 => d128!(4.084798285154892563534749954824084E+2549), - 995 => d128!(4.064374293729118100717076205049964E+2552), - 996 => d128!(4.048116796554201628314207900229764E+2555), - 997 => d128!(4.035972446164539023429265276529075E+2558), - 998 => d128!(4.027900501272209945382406745976017E+2561), - 999 => d128!(4.023872600770937735437024339230041E+2564), - 1000 => d128!(4.023872600770937735437024339230041E+2567), - _ => d128!("NaN"), - } + match n { + 0 => d128!(1), + 1 => d128!(1), + 2 => d128!(2), + 3 => d128!(6), + 4 => d128!(24), + 5 => d128!(120), + 6 => d128!(720), + 7 => d128!(5040), + 8 => d128!(40320), + 9 => d128!(362880), + 10 => d128!(3628800), + 11 => d128!(39916800), + 12 => d128!(479001600), + 13 => d128!(6227020800), + 14 => d128!(87178291200), + 15 => d128!(1307674368000), + 16 => d128!(20922789888000), + 17 => d128!(355687428096000), + 18 => d128!(6402373705728000), + 19 => d128!(121645100408832000), + 20 => d128!(2432902008176640000), + 21 => d128!(51090942171709440000), + 22 => d128!(1124000727777607680000), + 23 => d128!(25852016738884976640000), + 24 => d128!(620448401733239439360000), + 25 => d128!(15511210043330985984000000), + 26 => d128!(403291461126605635584000000), + 27 => d128!(10888869450418352160768000000), + 28 => d128!(304888344611713860501504000000), + 29 => d128!(8841761993739701954543616000000), + 30 => d128!(265252859812191058636308480000000), + 31 => d128!(8222838654177922817725562880000000), + 32 => d128!(2.631308369336935301672180121600000E+35), + 33 => d128!(8.683317618811886495518194401280000E+36), + 34 => d128!(2.952327990396041408476186096435200E+38), + 35 => d128!(1.033314796638614492966665133752320E+40), + 36 => d128!(3.719933267899012174679994481508352E+41), + 37 => d128!(1.376375309122634504631597958158090E+43), + 38 => d128!(5.230226174666011117600072241000742E+44), + 39 => d128!(2.039788208119744335864028173990289E+46), + 40 => d128!(8.159152832478977343456112695961156E+47), + 41 => d128!(3.345252661316380710817006205344074E+49), + 42 => d128!(1.405006117752879898543142606244511E+51), + 43 => d128!(6.041526306337383563735513206851397E+52), + 44 => d128!(2.658271574788448768043625811014615E+54), + 45 => d128!(1.196222208654801945619631614956577E+56), + 46 => d128!(5.502622159812088949850305428800254E+57), + 47 => d128!(2.586232415111681806429643551536119E+59), + 48 => d128!(1.241391559253607267086228904737337E+61), + 49 => d128!(6.082818640342675608722521633212951E+62), + 50 => d128!(3.041409320171337804361260816606476E+64), + 51 => d128!(1.551118753287382280224243016469303E+66), + 52 => d128!(8.065817517094387857166063685640376E+67), + 53 => d128!(4.274883284060025564298013753389399E+69), + 54 => d128!(2.308436973392413804720927426830275E+71), + 55 => d128!(1.269640335365827592596510084756651E+73), + 56 => d128!(7.109985878048634518540456474637246E+74), + 57 => d128!(4.052691950487721675568060190543230E+76), + 58 => d128!(2.350561331282878571829474910515073E+78), + 59 => d128!(1.386831185456898357379390197203893E+80), + 60 => d128!(8.320987112741390144276341183223358E+81), + 61 => d128!(5.075802138772247988008568121766248E+83), + 62 => d128!(3.146997326038793752565312235495074E+85), + 63 => d128!(1.982608315404440064116146708361897E+87), + 64 => d128!(1.268869321858841641034333893351614E+89), + 65 => d128!(8.247650592082470666723170306785491E+90), + 66 => d128!(5.443449390774430640037292402478424E+92), + 67 => d128!(3.647111091818868528824985909660544E+94), + 68 => d128!(2.480035542436830599600990418569170E+96), + 69 => d128!(1.711224524281413113724683388812727E+98), + 70 => d128!(1.197857166996989179607278372168909E+100), + 71 => d128!(8.504785885678623175211676442399254E+101), + 72 => d128!(6.123445837688608686152407038527463E+103), + 73 => d128!(4.470115461512684340891257138125048E+105), + 74 => d128!(3.307885441519386412259530282212536E+107), + 75 => d128!(2.480914081139539809194647711659402E+109), + 76 => d128!(1.885494701666050254987932260861146E+111), + 77 => d128!(1.451830920282858696340707840863082E+113), + 78 => d128!(1.132428117820629783145752115873204E+115), + 79 => d128!(8.946182130782975286851441715398312E+116), + 80 => d128!(7.156945704626380229481153372318650E+118), + 81 => d128!(5.797126020747367985879734231578106E+120), + 82 => d128!(4.753643337012841748421382069894047E+122), + 83 => d128!(3.945523969720658651189747118012059E+124), + 84 => d128!(3.314240134565353266999387579130130E+126), + 85 => d128!(2.817104114380550276949479442260610E+128), + 86 => d128!(2.422709538367273238176552320344125E+130), + 87 => d128!(2.107757298379527717213600518699389E+132), + 88 => d128!(1.854826422573984391147968456455462E+134), + 89 => d128!(1.650795516090846108121691926245361E+136), + 90 => d128!(1.485715964481761497309522733620825E+138), + 91 => d128!(1.352001527678402962551665687594951E+140), + 92 => d128!(1.243841405464130725547532432587355E+142), + 93 => d128!(1.156772507081641574759205162306240E+144), + 94 => d128!(1.087366156656743080273652852567866E+146), + 95 => d128!(1.032997848823905926259970209939473E+148), + 96 => d128!(9.916779348709496892095714015418941E+149), + 97 => d128!(9.619275968248211985332842594956373E+151), + 98 => d128!(9.426890448883247745626185743057246E+153), + 99 => d128!(9.332621544394415268169923885626674E+155), + 100 => d128!(9.332621544394415268169923885626674E+157), + 101 => d128!(9.425947759838359420851623124482941E+159), + 102 => d128!(9.614466715035126609268655586972600E+161), + 103 => d128!(9.902900716486180407546715254581778E+163), + 104 => d128!(1.029901674514562762384858386476505E+166), + 105 => d128!(1.081396758240290900504101305800330E+168), + 106 => d128!(1.146280563734708354534347384148350E+170), + 107 => d128!(1.226520203196137939351751701038734E+172), + 108 => d128!(1.324641819451828974499891837121833E+174), + 109 => d128!(1.443859583202493582204882102462798E+176), + 110 => d128!(1.588245541522742940425370312709078E+178), + 111 => d128!(1.762952551090244663872161047107077E+180), + 112 => d128!(1.974506857221074023536820372759926E+182), + 113 => d128!(2.231192748659813646596607021218716E+184), + 114 => d128!(2.543559733472187557120132004189336E+186), + 115 => d128!(2.925093693493015690688151804817736E+188), + 116 => d128!(3.393108684451898201198256093588574E+190), + 117 => d128!(3.969937160808720895401959629498632E+192), + 118 => d128!(4.684525849754290656574312362808386E+194), + 119 => d128!(5.574585761207605881323431711741979E+196), + 120 => d128!(6.689502913449127057588118054090375E+198), + 121 => d128!(8.094298525273443739681622845449354E+200), + 122 => d128!(9.875044200833601362411579871448212E+202), + 123 => d128!(1.214630436702532967576624324188130E+205), + 124 => d128!(1.506141741511140879795014161993281E+207), + 125 => d128!(1.882677176888926099743767702491601E+209), + 126 => d128!(2.372173242880046885677147305139417E+211), + 127 => d128!(3.012660018457659544809977077527060E+213), + 128 => d128!(3.856204823625804217356770659234637E+215), + 129 => d128!(4.974504222477287440390234150412682E+217), + 130 => d128!(6.466855489220473672507304395536487E+219), + 131 => d128!(8.471580690878820510984568758152798E+221), + 132 => d128!(1.118248651196004307449963076076169E+224), + 133 => d128!(1.487270706090685728908450891181305E+226), + 134 => d128!(1.992942746161518876737324194182949E+228), + 135 => d128!(2.690472707318050483595387662146981E+230), + 136 => d128!(3.659042881952548657689727220519894E+232), + 137 => d128!(5.012888748274991661034926292112255E+234), + 138 => d128!(6.917786472619488492228198283114912E+236), + 139 => d128!(9.615723196941089004197195613529728E+238), + 140 => d128!(1.346201247571752460587607385894162E+241), + 141 => d128!(1.898143759076170969428526414110768E+243), + 142 => d128!(2.695364137888162776588507508037291E+245), + 143 => d128!(3.854370717180072770521565736493326E+247), + 144 => d128!(5.550293832739304789551054660550389E+249), + 145 => d128!(8.047926057471991944849029257798064E+251), + 146 => d128!(1.174997204390910823947958271638517E+254), + 147 => d128!(1.727245890454638911203498659308620E+256), + 148 => d128!(2.556323917872865588581178015776758E+258), + 149 => d128!(3.808922637630569726985955243507369E+260), + 150 => d128!(5.713383956445854590478932865261054E+262), + 151 => d128!(8.627209774233240431623188626544192E+264), + 152 => d128!(1.311335885683452545606724671234717E+267), + 153 => d128!(2.006343905095682394778288746989117E+269), + 154 => d128!(3.089769613847350887958564670363240E+271), + 155 => d128!(4.789142901463393876335775239063022E+273), + 156 => d128!(7.471062926282894447083809372938314E+275), + 157 => d128!(1.172956879426414428192158071551315E+278), + 158 => d128!(1.853271869493734796543609753051078E+280), + 159 => d128!(2.946702272495038326504339507351214E+282), + 160 => d128!(4.714723635992061322406943211761942E+284), + 161 => d128!(7.590705053947218729075178570936727E+286), + 162 => d128!(1.229694218739449434110178928491750E+289), + 163 => d128!(2.004401576545302577599591653441552E+291), + 164 => d128!(3.287218585534296227263330311644145E+293), + 165 => d128!(5.423910666131588774984495014212839E+295), + 166 => d128!(9.003691705778437366474261723593313E+297), + 167 => d128!(1.503616514864999040201201707840083E+300), + 168 => d128!(2.526075744973198387538018869171339E+302), + 169 => d128!(4.269068009004705274939251888899563E+304), + 170 => d128!(7.257415615307998967396728211129257E+306), + 171 => d128!(1.241018070217667823424840524103103E+309), + 172 => d128!(2.134551080774388656290725701457337E+311), + 173 => d128!(3.692773369739692375382955463521193E+313), + 174 => d128!(6.425425663347064733166342506526876E+315), + 175 => d128!(1.124449491085736328304109938642203E+318), + 176 => d128!(1.979031104310895937815233492010277E+320), + 177 => d128!(3.502885054630285809932963280858190E+322), + 178 => d128!(6.235135397241908741680674639927578E+324), + 179 => d128!(1.116089236106301664760840760547036E+327), + 180 => d128!(2.008960624991342996569513368984665E+329), + 181 => d128!(3.636218731234330823790819197862244E+331), + 182 => d128!(6.617918090846482099299290940109284E+333), + 183 => d128!(1.211079010624906224171770242039999E+336), + 184 => d128!(2.228385379549827452476057245353598E+338), + 185 => d128!(4.122512952167180787080705903904156E+340), + 186 => d128!(7.667874091030956263970112981261730E+342), + 187 => d128!(1.433892455022788821362411127495944E+345), + 188 => d128!(2.695717815442842984161332919692375E+347), + 189 => d128!(5.094906671186973240064919218218589E+349), + 190 => d128!(9.680322675255249156123346514615319E+351), + 191 => d128!(1.848941630973752588819559184291526E+354), + 192 => d128!(3.549967931469604970533553633839730E+356), + 193 => d128!(6.851438107736337593129758513310679E+358), + 194 => d128!(1.329178992900849493067173151582272E+361), + 195 => d128!(2.591899036156656511480987645585430E+363), + 196 => d128!(5.080122110867046762502735785347443E+365), + 197 => d128!(1.000784055840808212213038949713446E+368), + 198 => d128!(1.981552430564800260181817120432623E+370), + 199 => d128!(3.943289336823952517761816069660920E+372), + 200 => d128!(7.886578673647905035523632139321840E+374), + 201 => d128!(1.585202313403228912140250060003690E+377), + 202 => d128!(3.202108673074522402523305121207454E+379), + 203 => d128!(6.500280606341280477122309396051132E+381), + 204 => d128!(1.326057243693621217332951116794431E+384), + 205 => d128!(2.718417349571923495532549789428584E+386), + 206 => d128!(5.599939740118162400797052566222883E+388), + 207 => d128!(1.159187526204459616964989881208137E+391), + 208 => d128!(2.411110054505276003287178952912925E+393), + 209 => d128!(5.039220013916026846870204011588013E+395), + 210 => d128!(1.058236202922365637842742842433483E+398), + 211 => d128!(2.232878388166191495848187397534649E+400), + 212 => d128!(4.733702182912325971198157282773456E+402), + 213 => d128!(1.008278564960325431865207501230746E+405), + 214 => d128!(2.157716129015096424191544052633796E+407), + 215 => d128!(4.639089677382457312011819713162661E+409), + 216 => d128!(1.002043370314610779394553058043135E+412), + 217 => d128!(2.174434113582705391286180135953603E+414), + 218 => d128!(4.740266367610297753003872696378855E+416), + 219 => d128!(1.038118334506655207907848120506969E+419), + 220 => d128!(2.283860335914641457397265865115332E+421), + 221 => d128!(5.047331342371357620847957561904884E+423), + 222 => d128!(1.120507558006441391828246578742884E+426), + 223 => d128!(2.498731854354364303776989870596631E+428), + 224 => d128!(5.597159353753776040460457310136453E+430), + 225 => d128!(1.259360854594599609103602894780702E+433), + 226 => d128!(2.846155531383795116574142542204387E+435), + 227 => d128!(6.460773056241214914623303570803958E+437), + 228 => d128!(1.473056256822997000534113214143302E+440), + 229 => d128!(3.373298828124663131223119260388162E+442), + 230 => d128!(7.758587304686725201813174298892773E+444), + 231 => d128!(1.792233667382633521618843263044231E+447), + 232 => d128!(4.157982108327709770155716370262616E+449), + 233 => d128!(9.688098312403563764462819142711895E+451), + 234 => d128!(2.267015005102433920884299679394583E+454), + 235 => d128!(5.327485261990719714078104246577270E+456), + 236 => d128!(1.257286521829809852522432602192236E+459), + 237 => d128!(2.979769056736649350478165267195599E+461), + 238 => d128!(7.091850355033225454138033335925526E+463), + 239 => d128!(1.694952234852940883538989967286201E+466), + 240 => d128!(4.067885363647058120493575921486882E+468), + 241 => d128!(9.803603726389410070389517970783386E+470), + 242 => d128!(2.372472101786237237034263348929579E+473), + 243 => d128!(5.765107207340556485993259937898877E+475), + 244 => d128!(1.406686158591095782582355424847326E+478), + 245 => d128!(3.446381088548184667326770790875949E+480), + 246 => d128!(8.478097477828534281623856145554835E+482), + 247 => d128!(2.094090077023647967561092467952044E+485), + 248 => d128!(5.193343391018646959551509320521069E+487), + 249 => d128!(1.293142504363643092928325820809746E+490), + 250 => d128!(3.232856260909107732320814552024365E+492), + 251 => d128!(8.114469214881860408125244525581156E+494), + 252 => d128!(2.044846242150228822847561620446451E+497), + 253 => d128!(5.173460992640078921804330899729521E+499), + 254 => d128!(1.314059092130580046138300048531298E+502), + 255 => d128!(3.350850684932979117652665123754810E+504), + 256 => d128!(8.578177753428426541190822716812314E+506), + 257 => d128!(2.204591682631105621086041438220765E+509), + 258 => d128!(5.687846541188252502401986910609574E+511), + 259 => d128!(1.473152254167757398122114609847880E+514), + 260 => d128!(3.830195860836169235117497985604488E+516), + 261 => d128!(9.996811196782401703656669742427714E+518), + 262 => d128!(2.619164533556989246358047472516061E+521), + 263 => d128!(6.888402723254881717921664852717240E+523), + 264 => d128!(1.818538318939288773531319521117351E+526), + 265 => d128!(4.819126545189115249857996730960980E+528), + 266 => d128!(1.281887661020304656462227130435621E+531), + 267 => d128!(3.422640054924213432754146438263108E+533), + 268 => d128!(9.172675347196891999781112454545129E+535), + 269 => d128!(2.467449668395963947941119250272640E+538), + 270 => d128!(6.662114104669102659441021975736128E+540), + 271 => d128!(1.805432922365326820708516955424491E+543), + 272 => d128!(4.910777548833688952327166118754616E+545), + 273 => d128!(1.340642270831597083985316350420010E+548), + 274 => d128!(3.673359822078576010119766800150827E+550), + 275 => d128!(1.010173951071608402782935870041477E+553), + 276 => d128!(2.788080104957639191680903001314477E+555), + 277 => d128!(7.722981890732660560956101313641101E+557), + 278 => d128!(2.146988965623679635945796165192226E+560), + 279 => d128!(5.990099214090066184288771300886311E+562), + 280 => d128!(1.677227779945218531600855964248167E+565), + 281 => d128!(4.713010061646064073798405259537349E+567), + 282 => d128!(1.329068837384190068811150283189532E+570), + 283 => d128!(3.761264809797257894735555301426376E+572), + 284 => d128!(1.068199205982421242104897705605091E+575), + 285 => d128!(3.044367737049900539998958460974509E+577), + 286 => d128!(8.706891727962715544397021198387096E+579), + 287 => d128!(2.498877925925299361241945083937097E+582), + 288 => d128!(7.196768426664862160376801841738839E+584), + 289 => d128!(2.079866075306145164348895732262524E+587), + 290 => d128!(6.031611618387820976611797623561320E+589), + 291 => d128!(1.755198980950855904194033108456344E+592), + 292 => d128!(5.125181024376499240246576676692524E+594), + 293 => d128!(1.501678040142314277392246966270910E+597), + 294 => d128!(4.414933438018403975533206080836475E+599), + 295 => d128!(1.302405364215429172782295793846760E+602), + 296 => d128!(3.855119878077670351435595549786410E+604), + 297 => d128!(1.144970603789068094376371878286564E+607), + 298 => d128!(3.412012399291422921241588197293961E+609), + 299 => d128!(1.020191707388135453451234870990894E+612), + 300 => d128!(3.060575122164406360353704612972682E+614), + 301 => d128!(9.212331117714863144664650885047773E+616), + 302 => d128!(2.782123997549888669688724567284427E+619), + 303 => d128!(8.429835712576162669156835438871814E+621), + 304 => d128!(2.562670056623153451423677973417031E+624), + 305 => d128!(7.816143672700618026842217818921945E+626), + 306 => d128!(2.391739963846389116213718652590115E+629), + 307 => d128!(7.342641689008414586776116263451653E+631), + 308 => d128!(2.261533640214591692727043809143109E+634), + 309 => d128!(6.988138948263088330526565370252207E+636), + 310 => d128!(2.166323073961557382463235264778184E+639), + 311 => d128!(6.737264760020443459460661673460152E+641), + 312 => d128!(2.102026605126378359351726442119567E+644), + 313 => d128!(6.579343274045564264770903763834245E+646), + 314 => d128!(2.065913788050307179138063781843953E+649), + 315 => d128!(6.507628432358467614284900912808452E+651), + 316 => d128!(2.056410584625275766114028688447471E+654), + 317 => d128!(6.518821553262124178581470942378483E+656), + 318 => d128!(2.072985253937355488788907759676358E+659), + 319 => d128!(6.612822960060164009236615753367582E+661), + 320 => d128!(2.116103347219252482955717041077626E+664), + 321 => d128!(6.792691744573800470287851701859179E+666), + 322 => d128!(2.187246741752763751432688247998656E+669), + 323 => d128!(7.064806975861426917127583041035659E+671), + 324 => d128!(2.288997460179102321149336905295554E+674), + 325 => d128!(7.439241745582082543735344942210550E+676), + 326 => d128!(2.425192809059758909257722451160639E+679), + 327 => d128!(7.930380485625411633272752415295290E+681), + 328 => d128!(2.601164799285135015713462792216855E+684), + 329 => d128!(8.557832189648094201697292586393453E+686), + 330 => d128!(2.824084622583871086560106553509839E+689), + 331 => d128!(9.347720100752613296513952692117567E+691), + 332 => d128!(3.103443073449867614442632293783032E+694), + 333 => d128!(1.033446543458805915609396553829750E+697), + 334 => d128!(3.451711455152411758135384489791365E+699), + 335 => d128!(1.156323337476057938975353804080107E+702), + 336 => d128!(3.885246413919554674957188781709160E+704), + 337 => d128!(1.309328041490889925460572619435987E+707), + 338 => d128!(4.425528780239207948056735453693636E+709), + 339 => d128!(1.500254256501091494391233318802143E+712), + 340 => d128!(5.100864472103711080930193283927286E+714), + 341 => d128!(1.739394784987365478597195909819205E+717), + 342 => d128!(5.948730164656789936802410011581681E+719), + 343 => d128!(2.040414446477278948323226633972517E+722), + 344 => d128!(7.019025695881839582231899620865458E+724), + 345 => d128!(2.421563865079234655870005369198583E+727), + 346 => d128!(8.378610973174151909310218577427097E+729), + 347 => d128!(2.907378007691430712530645846367203E+732), + 348 => d128!(1.011767546676617887960664754535787E+735), + 349 => d128!(3.531068737901396428982719993329897E+737), + 350 => d128!(1.235874058265488750143951997665464E+740), + 351 => d128!(4.337917944511865513005271511805779E+742), + 352 => d128!(1.526947116468176660577855572155634E+745), + 353 => d128!(5.390123321132663611839830169709388E+747), + 354 => d128!(1.908103655680962918591299880077123E+750), + 355 => d128!(6.773767977667418360999114574273787E+752), + 356 => d128!(2.411461400049600936515684788441468E+755), + 357 => d128!(8.608917198177075343360994694736041E+757), + 358 => d128!(3.081992356947392972923236100715503E+760), + 359 => d128!(1.106435256144114077279441760156866E+763), + 360 => d128!(3.983166922118810678205990336564718E+765), + 361 => d128!(1.437923258884890654832362511499863E+768), + 362 => d128!(5.205282197163304170493152291629504E+770), + 363 => d128!(1.889517437570279413889014281861510E+773), + 364 => d128!(6.877843472755817066556011985975896E+775), + 365 => d128!(2.510412867555873229292944374881202E+778), + 366 => d128!(9.188111095254496019212176412065199E+780), + 367 => d128!(3.372036771958400039050868743227928E+783), + 368 => d128!(1.240909532080691214370719697507878E+786), + 369 => d128!(4.578956173377750581027955683804070E+788), + 370 => d128!(1.694213784149767714980343603007506E+791), + 371 => d128!(6.285533139195638222577074767157847E+793), + 372 => d128!(2.338218327780777418798671813382719E+796), + 373 => d128!(8.721554362622299772119045863917542E+798), + 374 => d128!(3.261861331620740114772523153105161E+801), + 375 => d128!(1.223197999357777543039696182414435E+804), + 376 => d128!(4.599224477585243561829257645878276E+806), + 377 => d128!(1.733907628049636822809630132496110E+809), + 378 => d128!(6.554170834027627190220401900835296E+811), + 379 => d128!(2.484030746096470705093532320416577E+814), + 380 => d128!(9.439316835166588679355422817582993E+816), + 381 => d128!(3.596379714198470286834416093499120E+819), + 382 => d128!(1.373817050823815649570746947716664E+822), + 383 => d128!(5.261719304655213937855960809754823E+824), + 384 => d128!(2.020500212987602152136688950945852E+827), + 385 => d128!(7.778925820002268285726252461141530E+829), + 386 => d128!(3.002665366520875558290333450000631E+832), + 387 => d128!(1.162031496843578841058359045150244E+835), + 388 => d128!(4.508682207753085903306433095182947E+837), + 389 => d128!(1.753877378815950416386202474026166E+840), + 390 => d128!(6.840121777382206623906189648702047E+842), + 391 => d128!(2.674487614956442789947320152642500E+845), + 392 => d128!(1.048399145062925573659349499835860E+848), + 393 => d128!(4.120208640097297504481243534354930E+850), + 394 => d128!(1.623362204198335216765609952535842E+853), + 395 => d128!(6.412280706583424106224159312516576E+855), + 396 => d128!(2.539263159807035946064767087756564E+858), + 397 => d128!(1.008087474443393270587712533839356E+861), + 398 => d128!(4.012188148284705216939095884680637E+863), + 399 => d128!(1.600863071165597381558699257987574E+866), + 400 => d128!(6.403452284662389526234797031950296E+868), + 401 => d128!(2.567784366149618200020153609812069E+871), + 402 => d128!(1.032249315192146516408101751144452E+874), + 403 => d128!(4.159964740224350461124650057112142E+876), + 404 => d128!(1.680625755050637586294358623073305E+879), + 405 => d128!(6.806534307955082224492152423446885E+881), + 406 => d128!(2.763452929029763383143813883919435E+884), + 407 => d128!(1.124725342115113696939532250755210E+887), + 408 => d128!(4.588879395829663883513291583081257E+889), + 409 => d128!(1.876851672894332528356936257480234E+892), + 410 => d128!(7.695091858866763366263438655668959E+894), + 411 => d128!(3.162682753994239743534273287479942E+897), + 412 => d128!(1.303025294645626774336120594441736E+900), + 413 => d128!(5.381494466886438578008178055044370E+902), + 414 => d128!(2.227938709290985571295385714788369E+905), + 415 => d128!(9.245945643557590120875850716371731E+907), + 416 => d128!(3.846313387719957490284353898010640E+910), + 417 => d128!(1.603912682679222273448575575470437E+913), + 418 => d128!(6.704355013599149103015045905466427E+915), + 419 => d128!(2.809124750698043474163304234390433E+918), + 420 => d128!(1.179832395293178259148587778443982E+921), + 421 => d128!(4.967094384184280471015554547249164E+923), + 422 => d128!(2.096113830125766358768564018939147E+926), + 423 => d128!(8.866561501431991697591025800112592E+928), + 424 => d128!(3.759422076607164479778594939247739E+931), + 425 => d128!(1.597754382558044903905902849180289E+934), + 426 => d128!(6.806433669697271290639146137508031E+936), + 427 => d128!(2.906347176960734841102915400715929E+939), + 428 => d128!(1.243916591739194511992047791506418E+942), + 429 => d128!(5.336402178561144456445885025562533E+944), + 430 => d128!(2.294652936781292116271730560991889E+947), + 431 => d128!(9.889954157527369021131158717875042E+949), + 432 => d128!(4.272460196051823417128660566122018E+952), + 433 => d128!(1.849975264890439539616710025130834E+955), + 434 => d128!(8.028892649624507601936521509067820E+957), + 435 => d128!(3.492568302586660806842386856444502E+960), + 436 => d128!(1.522759779927784111783280669409803E+963), + 437 => d128!(6.654460238284416568492936525320839E+965), + 438 => d128!(2.914653584368574456999906198090527E+968), + 439 => d128!(1.279532923537804186622958820961741E+971), + 440 => d128!(5.629944863566338421141018812231660E+973), + 441 => d128!(2.482805684832755243723189296194162E+976), + 442 => d128!(1.097400112696077817725649668917820E+979), + 443 => d128!(4.861482499243624732524628033305943E+981), + 444 => d128!(2.158498229664169381240934846787839E+984), + 445 => d128!(9.605317122005553746522160068205884E+986), + 446 => d128!(4.283971436414476970948883390419824E+989), + 447 => d128!(1.914935232077271206014150875517661E+992), + 448 => d128!(8.578909839706175002943395922319121E+994), + 449 => d128!(3.851930518028072576321584769121285E+997), + 450 => d128!(1.733368733112632659344713146104578E+1000), + 451 => d128!(7.817492986337973293644656288931647E+1002), + 452 => d128!(3.533506829824763928727384642597104E+1005), + 453 => d128!(1.600678593910618059713505243096488E+1008), + 454 => d128!(7.267080816354205991099313803658056E+1010), + 455 => d128!(3.306521771441163725950187780664415E+1013), + 456 => d128!(1.507773927777170659033285627982973E+1016), + 457 => d128!(6.890526849941669911782115319882187E+1018), + 458 => d128!(3.155861297273284819596208816506042E+1021), + 459 => d128!(1.448540335448437732194659846776273E+1024), + 460 => d128!(6.663285543062813568095435295170856E+1026), + 461 => d128!(3.071774635351957054891995671073765E+1029), + 462 => d128!(1.419159881532604159360102000036079E+1032), + 463 => d128!(6.570710251495957257837272260167046E+1034), + 464 => d128!(3.048809556694124167636494328717509E+1037), + 465 => d128!(1.417696443862767737950969862853642E+1040), + 466 => d128!(6.606465428400497658851519560897972E+1042), + 467 => d128!(3.085219355063032406683659634939353E+1045), + 468 => d128!(1.443882658169499166327952709151617E+1048), + 469 => d128!(6.771809666814951090078098205921084E+1050), + 470 => d128!(3.182750543403027012336706156782909E+1053), + 471 => d128!(1.499075505942825722810588599844750E+1056), + 472 => d128!(7.075636388050137411665978191267220E+1058), + 473 => d128!(3.346776011547714995718007684469395E+1061), + 474 => d128!(1.586371829473616907970335642438493E+1064), + 475 => d128!(7.535266189999680312859094301582842E+1066), + 476 => d128!(3.586786706439847828920928887553433E+1069), + 477 => d128!(1.710897258971807414395283079362988E+1072), + 478 => d128!(8.178088897885239440809453119355083E+1074), + 479 => d128!(3.917304582087029692147728044171085E+1077), + 480 => d128!(1.880306199401774252230909461202121E+1080), + 481 => d128!(9.044272819122534153230674508382202E+1082), + 482 => d128!(4.359339498817061461857185113040221E+1085), + 483 => d128!(2.105560977928640686077020409598427E+1088), + 484 => d128!(1.019091513317462092061277878245639E+1091), + 485 => d128!(4.942593839589691146497197709491349E+1093), + 486 => d128!(2.402100606040589897197638086812796E+1096), + 487 => d128!(1.169822995141767279935249748277832E+1099), + 488 => d128!(5.708736216291824326084018771595820E+1101), + 489 => d128!(2.791572009766702095455085179310356E+1104), + 490 => d128!(1.367870284785684026772991737862074E+1107), + 491 => d128!(6.716243098297708571455389432902783E+1109), + 492 => d128!(3.304391604362472617156051600988169E+1112), + 493 => d128!(1.629065060950699000257933439287167E+1115), + 494 => d128!(8.047581401096453061274191190078605E+1117), + 495 => d128!(3.983552793542744265330724639088909E+1120), + 496 => d128!(1.975842185597201155604039420988099E+1123), + 497 => d128!(9.819935662418089743352075922310852E+1125), + 498 => d128!(4.890327959884208692189333809310804E+1128), + 499 => d128!(2.440273651982220137402477570846091E+1131), + 500 => d128!(1.220136825991110068701238785423046E+1134), + 501 => d128!(6.112885498215461444193206314969460E+1136), + 502 => d128!(3.068668520104161644984989570114669E+1139), + 503 => d128!(1.543540265612393307427449753767679E+1142), + 504 => d128!(7.779442938686462269434346758989102E+1144), + 505 => d128!(3.928618684036663446064345113289497E+1147), + 506 => d128!(1.987881054122551703708558627324485E+1150), + 507 => d128!(1.007855694440133713780239224053514E+1153), + 508 => d128!(5.119906927755879266003615258191851E+1155), + 509 => d128!(2.606032626227742546395840166419652E+1158), + 510 => d128!(1.329076639376148698661878484874023E+1161), + 511 => d128!(6.791581627212119850162199057706258E+1163), + 512 => d128!(3.477289793132605363283045917545604E+1166), + 513 => d128!(1.783849663877026551364202555700895E+1169), + 514 => d128!(9.168987272327916474012001136302600E+1171), + 515 => d128!(4.722028445248876984116180585195839E+1174), + 516 => d128!(2.436566677748420523803949181961053E+1177), + 517 => d128!(1.259704972395933410806641727073864E+1180), + 518 => d128!(6.525271757010935067978404146242616E+1182), + 519 => d128!(3.386616041888675300280791751899918E+1185), + 520 => d128!(1.761040341782111156146011710987957E+1188), + 521 => d128!(9.175020180684799123520721014247256E+1190), + 522 => d128!(4.789360534317465142477816369437068E+1193), + 523 => d128!(2.504835559448034269515897961215587E+1196), + 524 => d128!(1.312533833150769957226330531676968E+1199), + 525 => d128!(6.890802624041542275438235291304082E+1201), + 526 => d128!(3.624562180245851236880511763225947E+1204), + 527 => d128!(1.910144268989563601836029699220074E+1207), + 528 => d128!(1.008556174026489581769423681188199E+1210), + 529 => d128!(5.335262160600129887560251273485573E+1212), + 530 => d128!(2.827688945118068840406933174947354E+1215), + 531 => d128!(1.501502829857694554256081515897045E+1218), + 532 => d128!(7.987995054842935028642353664572279E+1220), + 533 => d128!(4.257601364231284370266374503217025E+1223), + 534 => d128!(2.273559128499505853722243984717891E+1226), + 535 => d128!(1.216354133747235631741400531824072E+1229), + 536 => d128!(6.519658156885182986133906850577026E+1231), + 537 => d128!(3.501056430247343263553907978759863E+1234), + 538 => d128!(1.883568359473070675792002492572806E+1237), + 539 => d128!(1.015243345755985094251889343496742E+1240), + 540 => d128!(5.482314067082319508960202454882407E+1242), + 541 => d128!(2.965931910291534854347469528091382E+1245), + 542 => d128!(1.607535095378011891056328484225529E+1248), + 543 => d128!(8.728915567902604568435863669344622E+1250), + 544 => d128!(4.748530068939016885229109836123474E+1253), + 545 => d128!(2.587948887571764202449864860687293E+1256), + 546 => d128!(1.413020092614183254537626213935262E+1259), + 547 => d128!(7.729219906599582402320815390225883E+1261), + 548 => d128!(4.235612508816571156471806833843784E+1264), + 549 => d128!(2.325351267340297564903021951780237E+1267), + 550 => d128!(1.278943197037163660696662073479130E+1270), + 551 => d128!(7.046977015674771770438608024870006E+1272), + 552 => d128!(3.889931312652474017282111629728243E+1275), + 553 => d128!(2.151132015896818131557007731239718E+1278), + 554 => d128!(1.191727136806837244882582283106804E+1281), + 555 => d128!(6.614085609277946709098331671242762E+1283), + 556 => d128!(3.677431598758538370258672409210976E+1286), + 557 => d128!(2.048329400508505872234080531930514E+1289), + 558 => d128!(1.142967805483746276706616936817227E+1292), + 559 => d128!(6.389190032654141686789988676808299E+1294), + 560 => d128!(3.577946418286319344602393659012647E+1297), + 561 => d128!(2.007227940658625152321942842706095E+1300), + 562 => d128!(1.128062102650147335604931877600825E+1303), + 563 => d128!(6.350989637920329499455766470892645E+1305), + 564 => d128!(3.581958155787065837693052289583452E+1308), + 565 => d128!(2.023806358019692198296574543614650E+1311), + 566 => d128!(1.145474398639145784235861191685892E+1314), + 567 => d128!(6.494839840283956596617332956859008E+1316), + 568 => d128!(3.689069029281287346878645119495917E+1319), + 569 => d128!(2.099080277661052500373949072993177E+1322), + 570 => d128!(1.196475758266799925213150971606111E+1325), + 571 => d128!(6.831876579703427572967092047870894E+1327), + 572 => d128!(3.907833403590360571737176651382151E+1330), + 573 => d128!(2.239188540257276607605402221241973E+1333), + 574 => d128!(1.285294222107676772765500874992893E+1336), + 575 => d128!(7.390441777119141443401630031209135E+1338), + 576 => d128!(4.256894463620625471399338897976462E+1341), + 577 => d128!(2.456228105509100896997418544132419E+1344), + 578 => d128!(1.419699844984260318464507918508538E+1347), + 579 => d128!(8.220062102458867243909500848164435E+1349), + 580 => d128!(4.767636019426143001467510491935372E+1352), + 581 => d128!(2.769996527286589083852623595814451E+1355), + 582 => d128!(1.612137978880794846802226932764010E+1358), + 583 => d128!(9.398764416875033956856983018014178E+1360), + 584 => d128!(5.488878419455019830804478082520280E+1363), + 585 => d128!(3.210993875381186601020619678274364E+1366), + 586 => d128!(1.881642410973375348198083131468777E+1369), + 587 => d128!(1.104524095241371329392274798172172E+1372), + 588 => d128!(6.494601680019263416826575813252371E+1374), + 589 => d128!(3.825320389531346152510853154005647E+1377), + 590 => d128!(2.256939029823494229981403360863332E+1380), + 591 => d128!(1.333850966625685089919009386270229E+1383), + 592 => d128!(7.896397722424055732320535566719756E+1385), + 593 => d128!(4.682563849397465049266077591064815E+1388), + 594 => d128!(2.781442926542094239264050089092500E+1391), + 595 => d128!(1.654958541292546072362109803010038E+1394), + 596 => d128!(9.863552906103574591278174425939826E+1396), + 597 => d128!(5.888541084943834030993070132286076E+1399), + 598 => d128!(3.521347568796412750533855939107073E+1402), + 599 => d128!(2.109287193709051237569779707525137E+1405), + 600 => d128!(1.265572316225430742541867824515082E+1408), + 601 => d128!(7.606089620514838762676625625335643E+1410), + 602 => d128!(4.578865951549932935131328626452057E+1413), + 603 => d128!(2.761056168784609559884191161750590E+1416), + 604 => d128!(1.667677925945904174170051461697356E+1419), + 605 => d128!(1.008945145197272025372881134326900E+1422), + 606 => d128!(6.114207579895468473759659674021014E+1424), + 607 => d128!(3.711324000996549363572113422130755E+1427), + 608 => d128!(2.256484992605902013051844960655499E+1430), + 609 => d128!(1.374199360496994325948573581039199E+1433), + 610 => d128!(8.382616099031665388286298844339114E+1435), + 611 => d128!(5.121778436508347552242928593891199E+1438), + 612 => d128!(3.134528403143108701972672299461414E+1441), + 613 => d128!(1.921465911126725634309248119569847E+1444), + 614 => d128!(1.179780069431809539465878345415886E+1447), + 615 => d128!(7.255647427005628667715151824307699E+1449), + 616 => d128!(4.469478815035467259312533523773543E+1452), + 617 => d128!(2.757668428876883298995833184168276E+1455), + 618 => d128!(1.704239089045913878779424907815995E+1458), + 619 => d128!(1.054923996119420690964464017938101E+1461), + 620 => d128!(6.540528775940408283979676911216226E+1463), + 621 => d128!(4.061668369858993544351379361865276E+1466), + 622 => d128!(2.526357726052293984586557963080202E+1469), + 623 => d128!(1.573920863330579152397425610998966E+1472), + 624 => d128!(9.821266187182813910959935812633548E+1474), + 625 => d128!(6.138291366989258694349959882895968E+1477), + 626 => d128!(3.842570395735275942663074886692876E+1480), + 627 => d128!(2.409291638126018016049747953956433E+1483), + 628 => d128!(1.513035148743139314079241715084640E+1486), + 629 => d128!(9.516991085594346285558430387882386E+1488), + 630 => d128!(5.995704383924438159901811144365903E+1491), + 631 => d128!(3.783289466256320478898042832094885E+1494), + 632 => d128!(2.391038942673994542663563069883967E+1497), + 633 => d128!(1.513527650712638545506035423236551E+1500), + 634 => d128!(9.595765305518128378508264583319733E+1502), + 635 => d128!(6.093310969004011520352748010408030E+1505), + 636 => d128!(3.875345776286551326944347734619507E+1508), + 637 => d128!(2.468595259494533195263549506952626E+1511), + 638 => d128!(1.574963775557512178578144585435775E+1514), + 639 => d128!(1.006401852581250282111434390093460E+1517), + 640 => d128!(6.440971856520001805513180096598144E+1519), + 641 => d128!(4.128662960029321157333948441919410E+1522), + 642 => d128!(2.650601620338824183008394899712261E+1525), + 643 => d128!(1.704336841877863949674397920514984E+1528), + 644 => d128!(1.097592926169344383590312260811650E+1531), + 645 => d128!(7.079474373792271274157514082235142E+1533), + 646 => d128!(4.573340445469807243105754097123902E+1536), + 647 => d128!(2.958951268218965286289422900839165E+1539), + 648 => d128!(1.917400421805889505515546039743779E+1542), + 649 => d128!(1.244392873752022289079589379793713E+1545), + 650 => d128!(8.088553679388144879017330968659134E+1547), + 651 => d128!(5.265648445281682316240282460597096E+1550), + 652 => d128!(3.433202786323656870188664164309307E+1553), + 653 => d128!(2.241881419469347936233197699293977E+1556), + 654 => d128!(1.466190448332953550296511295338261E+1559), + 655 => d128!(9.603547436580845754442148984465610E+1561), + 656 => d128!(6.299927118397034814914049733809440E+1564), + 657 => d128!(4.139052116786851873398530675112802E+1567), + 658 => d128!(2.723496292845748532696233184224224E+1570), + 659 => d128!(1.794784056985348283046817668403764E+1573), + 660 => d128!(1.184557477610329866810899661146484E+1576), + 661 => d128!(7.829924927004280419620046760178259E+1578), + 662 => d128!(5.183410301676833637788470955238007E+1581), + 663 => d128!(3.436601030011740701853756243322799E+1584), + 664 => d128!(2.281903083927795826030894145566339E+1587), + 665 => d128!(1.517465550811984224310544606801615E+1590), + 666 => d128!(1.010632056840781493390822708129876E+1593), + 667 => d128!(6.740915819128012560916787463226273E+1595), + 668 => d128!(4.502931767177512390692414025435150E+1598), + 669 => d128!(3.012461352241755789373224983016115E+1601), + 670 => d128!(2.018349106001976378880060738620797E+1604), + 671 => d128!(1.354312250127326150228520755614555E+1607), + 672 => d128!(9.100978320855631729535659477729810E+1609), + 673 => d128!(6.124958409935840153977498828512162E+1612), + 674 => d128!(4.128221968296756263780834210417197E+1615), + 675 => d128!(2.786549828600310478052063092031608E+1618), + 676 => d128!(1.883707684133809883163194650213367E+1621), + 677 => d128!(1.275270102158589290901482778194449E+1624), + 678 => d128!(8.646331292635235392312053236158364E+1626), + 679 => d128!(5.870858947699324831379884147351529E+1629), + 680 => d128!(3.992184084435540885338321220199040E+1632), + 681 => d128!(2.718677361500603342915396750955546E+1635), + 682 => d128!(1.854137960543411479868300584151682E+1638), + 683 => d128!(1.266376227051150040750049298975599E+1641), + 684 => d128!(8.662013393029866278730337204993097E+1643), + 685 => d128!(5.933479174225458400930280985420271E+1646), + 686 => d128!(4.070366713518664463038172755998306E+1649), + 687 => d128!(2.796341932187322486107224683370836E+1652), + 688 => d128!(1.923883249344877870441770582159135E+1655), + 689 => d128!(1.325555558798620852734379931107644E+1658), + 690 => d128!(9.146333355710483883867221524642744E+1660), + 691 => d128!(6.320116348795944363752250073528136E+1663), + 692 => d128!(4.373520513366793499716557050881470E+1666), + 693 => d128!(3.030849715763187895303574036260859E+1669), + 694 => d128!(2.103409702739652399340680381165036E+1672), + 695 => d128!(1.461869743404058417541772864909700E+1675), + 696 => d128!(1.017461341409224658609073913977151E+1678), + 697 => d128!(7.091705549622295870505245180420742E+1680), + 698 => d128!(4.950010473636362517612661135933678E+1683), + 699 => d128!(3.460057321071817399811250134017641E+1686), + 700 => d128!(2.422040124750272179867875093812349E+1689), + 701 => d128!(1.697850127449940798087380440762457E+1692), + 702 => d128!(1.191890789469858440257341069415245E+1695), + 703 => d128!(8.378992249973104835009107717989172E+1697), + 704 => d128!(5.898810543981065803846411833464377E+1700), + 705 => d128!(4.158661433506651391711720342592386E+1703), + 706 => d128!(2.936014972055695882548474561870225E+1706), + 707 => d128!(2.075762585243376988961771515242249E+1709), + 708 => d128!(1.469639910352310908184934232791512E+1712), + 709 => d128!(1.041974696439788433903118371049182E+1715), + 710 => d128!(7.398020344722497880712140434449192E+1717), + 711 => d128!(5.259992465097695993186331848893376E+1720), + 712 => d128!(3.745114635149559547148668276412084E+1723), + 713 => d128!(2.670266734861635957117000481081816E+1726), + 714 => d128!(1.906570448691208073381538343492417E+1729), + 715 => d128!(1.363197870814213772467799915597078E+1732), + 716 => d128!(9.760496755029770610869447395675078E+1734), + 717 => d128!(6.998276173356345527993393782699031E+1737), + 718 => d128!(5.024762292469856089099256735977904E+1740), + 719 => d128!(3.612804088285826528062365593168113E+1743), + 720 => d128!(2.601218943565795100204903227081041E+1746), + 721 => d128!(1.875478858310938267247735226725431E+1749), + 722 => d128!(1.354095735700497428952864833695761E+1752), + 723 => d128!(9.790112169114596411329212747620352E+1754), + 724 => d128!(7.088041210438967801802350029277135E+1757), + 725 => d128!(5.138829877568251656306703771225923E+1760), + 726 => d128!(3.730790491114550702478666937910020E+1763), + 727 => d128!(2.712284687040278360701990863860585E+1766), + 728 => d128!(1.974543252165322646591049348890506E+1769), + 729 => d128!(1.439442030828520209364874975341179E+1772), + 730 => d128!(1.050792682504819752836358731999061E+1775), + 731 => d128!(7.681294509110232393233782330913136E+1777), + 732 => d128!(5.622707580668690111847128666228416E+1780), + 733 => d128!(4.121444656630149851983945312345429E+1783), + 734 => d128!(3.025140377966529991356215859261545E+1786), + 735 => d128!(2.223478177805399543646818656557236E+1789), + 736 => d128!(1.636479938864774064124058531226126E+1792), + 737 => d128!(1.206085714943338485259431137513655E+1795), + 738 => d128!(8.900912576281838021214601794850774E+1797), + 739 => d128!(6.577774393872278297677590726394722E+1800), + 740 => d128!(4.867553051465485940281417137532094E+1803), + 741 => d128!(3.606856811135925081748530098911282E+1806), + 742 => d128!(2.676287753862856410657409333392171E+1809), + 743 => d128!(1.988481801120102313118455134710383E+1812), + 744 => d128!(1.479430460033356120960130620224525E+1815), + 745 => d128!(1.102175692724850310115297312067271E+1818), + 746 => d128!(8.222230667727383313460117948021842E+1820), + 747 => d128!(6.142006308792355335154708107172316E+1823), + 748 => d128!(4.594220718976681790695721664164892E+1826), + 749 => d128!(3.441071318513534661231095526459504E+1829), + 750 => d128!(2.580803488885150995923321644844628E+1832), + 751 => d128!(1.938183420152748397938414555278316E+1835), + 752 => d128!(1.457513931954866795249687745569294E+1838), + 753 => d128!(1.097507990762014696823014872413678E+1841), + 754 => d128!(8.275210250345590814045532137999132E+1843), + 755 => d128!(6.247783739010921064604376764189345E+1846), + 756 => d128!(4.723324506692256324840908833727145E+1849), + 757 => d128!(3.575556651566038037904567987131449E+1852), + 758 => d128!(2.710271941887056832731662534245638E+1855), + 759 => d128!(2.057096403892276136043331863492439E+1858), + 760 => d128!(1.563393266958129863392932216254254E+1861), + 761 => d128!(1.189742276155136826042021416569487E+1864), + 762 => d128!(9.065836144302142614440203194259491E+1866), + 763 => d128!(6.917232978102534814817875037219992E+1869), + 764 => d128!(5.284765995270336598520856528436074E+1872), + 765 => d128!(4.042845986381807497868455244253597E+1875), + 766 => d128!(3.096820025568464543367236717098255E+1878), + 767 => d128!(2.375260959611012304762670562014362E+1881), + 768 => d128!(1.824200416981257450057730991627030E+1884), + 769 => d128!(1.402810120658586979094395132561186E+1887), + 770 => d128!(1.080163792907111973902684252072113E+1890), + 771 => d128!(8.328062843313833318789695583475991E+1892), + 772 => d128!(6.429264515038279322105644990443465E+1895), + 773 => d128!(4.969821470124589915987663577612798E+1898), + 774 => d128!(3.846641817876432594974451609072306E+1901), + 775 => d128!(2.981147408854235261105199997031037E+1904), + 776 => d128!(2.313370389270886562617635197696085E+1907), + 777 => d128!(1.797488792463478859153902548609858E+1910), + 778 => d128!(1.398446280536586552421736182818470E+1913), + 779 => d128!(1.089389652538000924336532486415588E+1916), + 780 => d128!(8.497239289796407209824953394041586E+1918), + 781 => d128!(6.636343885330994030873288600746479E+1921), + 782 => d128!(5.189620918328837332142911685783747E+1924), + 783 => d128!(4.063473179051479631067899849968674E+1927), + 784 => d128!(3.185762972376360030757233482375440E+1930), + 785 => d128!(2.500823933315442624144428283664720E+1933), + 786 => d128!(1.965647611585937902577520630960470E+1936), + 787 => d128!(1.546964670318133129328508736565890E+1939), + 788 => d128!(1.219008160210688905910864884413921E+1942), + 789 => d128!(9.617974384062335467636723938025837E+1944), + 790 => d128!(7.598199763409245019433011911040411E+1947), + 791 => d128!(6.010176012856712810371512421632965E+1950), + 792 => d128!(4.760059402182516545814237837933308E+1953), + 793 => d128!(3.774727105930735620830690605481113E+1956), + 794 => d128!(2.997133322109004082939568340752004E+1959), + 795 => d128!(2.382720991076658245936956830897843E+1962), + 796 => d128!(1.896645908897019963765817637394683E+1965), + 797 => d128!(1.511626789390924911121356657003562E+1968), + 798 => d128!(1.206278177933958079074842612288842E+1971), + 799 => d128!(9.638162641692325051807992472187848E+1973), + 800 => d128!(7.710530113353860041446393977750278E+1976), + 801 => d128!(6.176134620796441893198561576177973E+1979), + 802 => d128!(4.953259965878746398345246384094734E+1982), + 803 => d128!(3.977467752600633357871232846428071E+1985), + 804 => d128!(3.197884073090909219728471208528169E+1988), + 805 => d128!(2.574296678838181921881419322865176E+1991), + 806 => d128!(2.074883123143574629036423974229332E+1994), + 807 => d128!(1.674430680376864725632394147203071E+1997), + 808 => d128!(1.352939989744506698310974470940081E+2000), + 809 => d128!(1.094528451703305918933578346990526E+2003), + 810 => d128!(8.865680458796777943361984610623261E+2005), + 811 => d128!(7.190066852084186912066569519215465E+2008), + 812 => d128!(5.838334283892359772598054449602958E+2011), + 813 => d128!(4.746565772804488495122218267527205E+2014), + 814 => d128!(3.863704539062853635029485669767145E+2017), + 815 => d128!(3.148919199336225712549030820860223E+2020), + 816 => d128!(2.569518066658360181440009149821942E+2023), + 817 => d128!(2.099296260459880268236487475404527E+2026), + 818 => d128!(1.717224341056182059417446754880903E+2029), + 819 => d128!(1.406406735325013106662888892247460E+2032), + 820 => d128!(1.153253522966510747463568891642917E+2035), + 821 => d128!(9.468211423555053236675900600388349E+2037), + 822 => d128!(7.782869790162253760547590293519223E+2040), + 823 => d128!(6.405301837303534844930666811566321E+2043), + 824 => d128!(5.277968713938112712222869452730649E+2046), + 825 => d128!(4.354324188998942987583867298502785E+2049), + 826 => d128!(3.596671780113126907744274388563300E+2052), + 827 => d128!(2.974447562153555952704514919341849E+2055), + 828 => d128!(2.462842581463144328839338353215051E+2058), + 829 => d128!(2.041696500032946648607811494815277E+2061), + 830 => d128!(1.694608095027345718344483540696680E+2064), + 831 => d128!(1.408219326967724291944265822318941E+2067), + 832 => d128!(1.171638480037146610897629164169359E+2070), + 833 => d128!(9.759748538709431268777250937530760E+2072), + 834 => d128!(8.139630281283665678160227281900654E+2075), + 835 => d128!(6.796591284871860841263789780387046E+2078), + 836 => d128!(5.681950314152875663296528256403570E+2081), + 837 => d128!(4.755792412945956930179194150609788E+2084), + 838 => d128!(3.985354042048711907490164698211002E+2087), + 839 => d128!(3.343712041278869290384248181799031E+2090), + 840 => d128!(2.808718114674250203922768472711186E+2093), + 841 => d128!(2.362131934441044421499048285550107E+2096), + 842 => d128!(1.988915088799359402902198656433190E+2099), + 843 => d128!(1.676655419857859976646553467373179E+2102), + 844 => d128!(1.415097174360033820289691126462963E+2105), + 845 => d128!(1.195757112334228578144789001861204E+2108), + 846 => d128!(1.011610517034757377110491495574579E+2111), + 847 => d128!(8.568341079284394984125862967516684E+2113), + 848 => d128!(7.265953235233166946538731796454148E+2116), + 849 => d128!(6.168794296712958737611383295189572E+2119), + 850 => d128!(5.243475152206014926969675800911136E+2122), + 851 => d128!(4.462197354527318702851194106575377E+2125), + 852 => d128!(3.801792146057275534829217378802221E+2128), + 853 => d128!(3.242928700586856031209322424118295E+2131), + 854 => d128!(2.769461110301175050652761350197024E+2134), + 855 => d128!(2.367889249307504668308110954418456E+2137), + 856 => d128!(2.026913197407223996071742976982198E+2140), + 857 => d128!(1.737064610177990964633483731273744E+2143), + 858 => d128!(1.490401435532716247655529041432872E+2146), + 859 => d128!(1.280254833122603256736099446590837E+2149), + 860 => d128!(1.101019156485438800793045524068120E+2152), + 861 => d128!(9.479774937339628074828121962226513E+2154), + 862 => d128!(8.171565995986759400501841131439254E+2157), + 863 => d128!(7.052061454536573362633088896432076E+2160), + 864 => d128!(6.092981096719599385314988806517314E+2163), + 865 => d128!(5.270428648662453468297465317637477E+2166), + 866 => d128!(4.564191209741684703545604965074055E+2169), + 867 => d128!(3.957153778846040637974039504719206E+2172), + 868 => d128!(3.434809480038363273761466290096271E+2175), + 869 => d128!(2.984849438153337684898714206093659E+2178), + 870 => d128!(2.596819011193403785861881359301483E+2181), + 871 => d128!(2.261829358749454697485698663951592E+2184), + 872 => d128!(1.972315200829524496207529234965788E+2187), + 873 => d128!(1.721831170324174885189173022125133E+2190), + 874 => d128!(1.504880442863328849655337221337366E+2193), + 875 => d128!(1.316770387505412743448420068670195E+2196), + 876 => d128!(1.153490859454741563260815980155091E+2199), + 877 => d128!(1.011611483741808350979735614596015E+2202), + 878 => d128!(8.881948827253077321602078696153012E+2204), + 879 => d128!(7.807233019155454965688227173918498E+2207), + 880 => d128!(6.870365056856800369805639913048278E+2210), + 881 => d128!(6.052791615090841125798768763395533E+2213), + 882 => d128!(5.338562204510121872954514049314860E+2216), + 883 => d128!(4.713950426582437613818835905545021E+2219), + 884 => d128!(4.167132177098874850615850940501799E+2222), + 885 => d128!(3.687911976732504242795028082344092E+2225), + 886 => d128!(3.267490011384998759116394880956866E+2228), + 887 => d128!(2.898263640098493899336242259408740E+2231), + 888 => d128!(2.573658112407462582610583126354961E+2234), + 889 => d128!(2.287982061930234235940808399329560E+2237), + 890 => d128!(2.036304035117908469987319475403308E+2240), + 891 => d128!(1.814346895290056446758701652584347E+2243), + 892 => d128!(1.618397430598730350508761874105238E+2246), + 893 => d128!(1.445228905524666203004324353575978E+2249), + 894 => d128!(1.292034641539051585485865972096924E+2252), + 895 => d128!(1.156371004177451169009850045026747E+2255), + 896 => d128!(1.036108419742996247432825640343965E+2258), + 897 => d128!(9.293892525094676339472445993885366E+2260), + 898 => d128!(8.345915487535019352846256502509059E+2263), + 899 => d128!(7.502978023293982398208784595755644E+2266), + 900 => d128!(6.752680220964584158387906136180080E+2269), + 901 => d128!(6.084164879089090326707503428698252E+2272), + 902 => d128!(5.487916720938359474690168092685823E+2275), + 903 => d128!(4.955588799007338605645221787695298E+2278), + 904 => d128!(4.479852274302634099503280496076549E+2281), + 905 => d128!(4.054266308243883860050468848949277E+2284), + 906 => d128!(3.673165275268958777205724777148045E+2287), + 907 => d128!(3.331560904668945610925592372873277E+2290), + 908 => d128!(3.025057301439402614720437874568936E+2293), + 909 => d128!(2.749777087008416976780878027983163E+2296), + 910 => d128!(2.502297149177659448870599005464678E+2299), + 911 => d128!(2.279592702900847757921115693978322E+2302), + 912 => d128!(2.078988545045573155224057512908230E+2305), + 913 => d128!(1.898116541626608290719564509285214E+2308), + 914 => d128!(1.734878519046719977717681961486686E+2311), + 915 => d128!(1.587413844927748779611678994760318E+2314), + 916 => d128!(1.454071081953817882124297959200451E+2317), + 917 => d128!(1.333383182151650997907981228586814E+2320), + 918 => d128!(1.224045761215215616079526767842695E+2323), + 919 => d128!(1.124898054556783151177085099647437E+2326), + 920 => d128!(1.034906210192240499082918291675642E+2329), + 921 => d128!(9.531486195870534996553677466332663E+2331), + 922 => d128!(8.788030272592633266822490623958715E+2334), + 923 => d128!(8.111351941603000505277158845913894E+2337), + 924 => d128!(7.494889194041172466876094773624438E+2340), + 925 => d128!(6.932772504488084531860387665602605E+2343), + 926 => d128!(6.419747339155966276502718978348012E+2346), + 927 => d128!(5.951105783397580738318020492928607E+2349), + 928 => d128!(5.522626166992954925159123017437747E+2352), + 929 => d128!(5.130519709136455125472825283199667E+2355), + 930 => d128!(4.771383329496903266689727513375690E+2358), + 931 => d128!(4.442157879761616941288136314952767E+2361), + 932 => d128!(4.140091143937826989280543045535979E+2364), + 933 => d128!(3.862705037293992580998746661485068E+2367), + 934 => d128!(3.607766504832589070652829381827054E+2370), + 935 => d128!(3.373261682018470781060395472008295E+2373), + 936 => d128!(3.157372934369288651072530161799764E+2376), + 937 => d128!(2.958458439504023466054960761606379E+2379), + 938 => d128!(2.775034016254774011159553194386784E+2382), + 939 => d128!(2.605756941263232796478820449529190E+2385), + 940 => d128!(2.449411524787438828690091222557439E+2388), + 941 => d128!(2.304896244824979937797375840426550E+2391), + 942 => d128!(2.171212262625131101405128041681810E+2394), + 943 => d128!(2.047453163655498628625035743305947E+2397), + 944 => d128!(1.932795786490790705422033741680814E+2400), + 945 => d128!(1.826492018233797216623821885888369E+2403), + 946 => d128!(1.727861449249172166926135504050397E+2406), + 947 => d128!(1.636284792438966042079050322335726E+2409), + 948 => d128!(1.551197983232139807890939705574268E+2412), + 949 => d128!(1.472086886087300677688501780589980E+2415), + 950 => d128!(1.398482541782935643804076691560481E+2418), + 951 => d128!(1.329956897235571797257676933674017E+2421), + 952 => d128!(1.266118966168264350989308440857664E+2424), + 953 => d128!(1.206611374758355926492810944137354E+2427), + 954 => d128!(1.151107251519471553874141640707036E+2430), + 955 => d128!(1.099307425201095333949805266875219E+2433), + 956 => d128!(1.050937898492247139256013835132709E+2436), + 957 => d128!(1.005747568857080512268005240222003E+2439), + 958 => d128!(9.635061709650831307527490201326789E+2441), + 959 => d128!(9.240024179555147223918863103072391E+2444), + 960 => d128!(8.870423212372941334962108578949495E+2447), + 961 => d128!(8.524476707090396622898586344370465E+2450), + 962 => d128!(8.200546592220961551228440063284387E+2453), + 963 => d128!(7.897126368308785973832987780942865E+2456), + 964 => d128!(7.612829819049669678775000220828922E+2459), + 965 => d128!(7.346380775382931240017875213099910E+2462), + 966 => d128!(7.096603829019911577857267455854513E+2465), + 967 => d128!(6.862415902662254495787977629811314E+2468), + 968 => d128!(6.642818593777062351922762345657352E+2471), + 969 => d128!(6.436891217369973419013156712941974E+2474), + 970 => d128!(6.243784480848874216442762011553715E+2477), + 971 => d128!(6.062714730904256864165921913218657E+2480), + 972 => d128!(5.892958718438937671969276099648535E+2483), + 973 => d128!(5.733848833041086354826105644958025E+2486), + 974 => d128!(5.584768763382018109600626898189116E+2489), + 975 => d128!(5.445149544297467656860611225734388E+2492), + 976 => d128!(5.314465955234328433095956556316763E+2495), + 977 => d128!(5.192233238263938879134749555521477E+2498), + 978 => d128!(5.078004107022132223793785065300005E+2501), + 979 => d128!(4.971366020774667447094115578928705E+2504), + 980 => d128!(4.871938700359174098152233267350131E+2507), + 981 => d128!(4.779371865052349790287340835270479E+2510), + 982 => d128!(4.693343171481407494062168700235610E+2513), + 983 => d128!(4.613556337566223566663111832331605E+2516), + 984 => d128!(4.539739436165163989596502043014299E+2519), + 985 => d128!(4.471643344622686529752554512369085E+2522), + 986 => d128!(4.409040337797968918336018749195918E+2525), + 987 => d128!(4.351722813406595322397650505456371E+2528), + 988 => d128!(4.299502139645716178528878699390895E+2531), + 989 => d128!(4.252207616109613300565061033697595E+2534), + 990 => d128!(4.209685539948517167559410423360619E+2537), + 991 => d128!(4.171798370088980513051375729550373E+2540), + 992 => d128!(4.138423983128268668946964723713970E+2543), + 993 => d128!(4.109455015246370788264335970647972E+2546), + 994 => d128!(4.084798285154892563534749954824084E+2549), + 995 => d128!(4.064374293729118100717076205049964E+2552), + 996 => d128!(4.048116796554201628314207900229764E+2555), + 997 => d128!(4.035972446164539023429265276529075E+2558), + 998 => d128!(4.027900501272209945382406745976017E+2561), + 999 => d128!(4.023872600770937735437024339230041E+2564), + 1000 => d128!(4.023872600770937735437024339230041E+2567), + _ => d128!("NaN"), + } } diff --git a/src/main.rs b/src/main.rs index b57b652..1808b6f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,70 +6,70 @@ use std::process::exit; const VERSION: &str = env!("CARGO_PKG_VERSION"); fn print_help() { - println!(concat!( - "Usage: cpc '' [options]", - "\n", - "\nOptions:", - "\n --verbose Enable verbose logging", - "\n --version Show cpc version", - "\n --help Show this help page", - )); + println!(concat!( + "Usage: cpc '' [options]", + "\n", + "\nOptions:", + "\n --verbose Enable verbose logging", + "\n --version Show cpc version", + "\n --help Show this help page", + )); } fn get_args() -> env::Args { - let mut args = env::args(); - args.next(); // skip binary name - args + let mut args = env::args(); + args.next(); // skip binary name + args } /// CLI interface fn main() { - // parse these first so they work if there are unexpected args - for arg in get_args() { - match arg.as_str() { - "--version" => { - println!("{}", VERSION); - exit(0); - } - "--help" => { - print_help(); - exit(0); - } - _ => {} - } - } - let mut verbose = false; - let mut expression_opt = None; - for arg in get_args() { - match arg.as_str() { - "-v" | "--verbose" => verbose = true, - _ => { - if expression_opt.is_none() { - expression_opt = Some(arg); - } else { - eprintln!("Unexpected argument: {}", arg); - exit(1); - } - } - } - } - let expression = match expression_opt { - Some(expression) => expression, - None => { - print_help(); - exit(0); - } - }; + // parse these first so they work if there are unexpected args + for arg in get_args() { + match arg.as_str() { + "--version" => { + println!("{}", VERSION); + exit(0); + } + "--help" => { + print_help(); + exit(0); + } + _ => {} + } + } + let mut verbose = false; + let mut expression_opt = None; + for arg in get_args() { + match arg.as_str() { + "-v" | "--verbose" => verbose = true, + _ => { + if expression_opt.is_none() { + expression_opt = Some(arg); + } else { + eprintln!("Unexpected argument: {}", arg); + exit(1); + } + } + } + } + let expression = match expression_opt { + Some(expression) => expression, + None => { + print_help(); + exit(0); + } + }; - match eval(&expression, true, Unit::Celsius, verbose) { - Ok(answer) => { - if !verbose { - println!("{}", answer); - } - } - Err(e) => { - eprintln!("{}", e); - exit(1); - } - } + match eval(&expression, true, Unit::Celsius, verbose) { + Ok(answer) => { + if !verbose { + println!("{}", answer); + } + } + Err(e) => { + eprintln!("{}", e); + exit(1); + } + } } diff --git a/src/parser.rs b/src/parser.rs index 7889ed9..471af90 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -7,295 +7,295 @@ use crate::UnaryOperator::{Factorial, Percent}; #[derive(Debug)] /// A struct with a [`Token`](AstNode::token) and [`AstNode`] [`children`](AstNode::children) pub struct AstNode { - /// The children of the [`AstNode`] - pub children: Vec, - /// The token of the [`AstNode`] - pub token: Token, + /// The children of the [`AstNode`] + pub children: Vec, + /// The token of the [`AstNode`] + pub token: Token, } impl AstNode { - pub const fn new(token: Token) -> AstNode { - AstNode { - children: Vec::new(), - token, - } - } + pub const fn new(token: Token) -> AstNode { + AstNode { + children: Vec::new(), + token, + } + } } /// Parse [`Token`]s into an Abstract Syntax Tree ([`AstNode`]) pub fn parse(tokens: &[Token]) -> Result { - parse_level_1(tokens, 0).and_then(|(ast, next_pos)| { - if next_pos == tokens.len() { - Ok(ast) - } else { - Err(format!( - "Expected end of input, found {:?} at {}", - tokens[next_pos], next_pos - )) - } - }) + parse_level_1(tokens, 0).and_then(|(ast, next_pos)| { + if next_pos == tokens.len() { + Ok(ast) + } else { + Err(format!( + "Expected end of input, found {:?} at {}", + tokens[next_pos], next_pos + )) + } + }) } // level 1 precedence (lowest): to, of /// Parse [`To`](crate::TextOperator::To) and [`Of`](crate::TextOperator::Of) pub fn parse_level_1(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> { - // do higher precedences first, then come back down - let (mut node, mut pos) = parse_level_2(tokens, pos)?; - // now we loop through the next tokens - loop { - let token = tokens.get(pos); - match token { - // if there's a match, we once again do higher precedences, then come - // back down again and continue the loop - Some(&Token::TextOperator(To)) | Some(&Token::TextOperator(Of)) => { - let (right_node, next_pos) = parse_level_2(tokens, pos + 1)?; - let mut new_node = AstNode::new(token.unwrap().clone()); - new_node.children.push(node); - new_node.children.push(right_node); - node = new_node; - pos = next_pos; - } - // if there's no match, we go down to a lower precedence (or, in this - // case, we're done) - _ => { - return Ok((node, pos)); - } - } - } + // do higher precedences first, then come back down + let (mut node, mut pos) = parse_level_2(tokens, pos)?; + // now we loop through the next tokens + loop { + let token = tokens.get(pos); + match token { + // if there's a match, we once again do higher precedences, then come + // back down again and continue the loop + Some(&Token::TextOperator(To)) | Some(&Token::TextOperator(Of)) => { + let (right_node, next_pos) = parse_level_2(tokens, pos + 1)?; + let mut new_node = AstNode::new(token.unwrap().clone()); + new_node.children.push(node); + new_node.children.push(right_node); + node = new_node; + pos = next_pos; + } + // if there's no match, we go down to a lower precedence (or, in this + // case, we're done) + _ => { + return Ok((node, pos)); + } + } + } } // level 2 precedence: +, - /// Parse [`Plus`](crate::Operator::Plus) and [`Minus`](crate::Operator::Minus) pub fn parse_level_2(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> { - let (mut node, mut pos) = parse_level_3(tokens, pos)?; - loop { - let token = tokens.get(pos); - match token { - Some(&Token::Operator(Plus)) | Some(&Token::Operator(Minus)) => { - let (right_node, next_pos) = parse_level_3(tokens, pos + 1)?; - let mut new_node = AstNode::new(token.unwrap().clone()); - new_node.children.push(node); - new_node.children.push(right_node); - node = new_node; - pos = next_pos; - } - _ => { - return Ok((node, pos)); - } - } - } + let (mut node, mut pos) = parse_level_3(tokens, pos)?; + loop { + let token = tokens.get(pos); + match token { + Some(&Token::Operator(Plus)) | Some(&Token::Operator(Minus)) => { + let (right_node, next_pos) = parse_level_3(tokens, pos + 1)?; + let mut new_node = AstNode::new(token.unwrap().clone()); + new_node.children.push(node); + new_node.children.push(right_node); + node = new_node; + pos = next_pos; + } + _ => { + return Ok((node, pos)); + } + } + } } // level 3 precedence: *, /, modulo, implicative multiplication, foot-inch 6'4" /// Parse [`Multiply`](crate::Operator::Multiply), [`Divide`](crate::Operator::Divide), [`Modulo`](crate::Operator::Modulo) and implicative multiplication (for example`2pi`) pub fn parse_level_3(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> { - // parse foot-inch syntax 6'4" - let token0 = tokens.get(pos); - if let Some(Token::Number(_number)) = token0 { - let token1 = tokens.get(pos + 1); - if let Some(Token::Unit(Foot)) = token1 { - let token2 = tokens.get(pos + 2); - if let Some(Token::Number(_number)) = token2 { - let token3 = tokens.get(pos + 3); - if let Some(Token::Unit(Inch)) = token3 { - let new_node = AstNode { - children: vec![ - AstNode { - children: vec![AstNode::new(token0.unwrap().clone())], - token: Token::Unit(Foot), - }, - AstNode { - children: vec![AstNode::new(token2.unwrap().clone())], - token: Token::Unit(Inch), - }, - ], - token: Token::Operator(Plus), - }; - return Ok((new_node, pos + 4)); - } - } - } - } + // parse foot-inch syntax 6'4" + let token0 = tokens.get(pos); + if let Some(Token::Number(_number)) = token0 { + let token1 = tokens.get(pos + 1); + if let Some(Token::Unit(Foot)) = token1 { + let token2 = tokens.get(pos + 2); + if let Some(Token::Number(_number)) = token2 { + let token3 = tokens.get(pos + 3); + if let Some(Token::Unit(Inch)) = token3 { + let new_node = AstNode { + children: vec![ + AstNode { + children: vec![AstNode::new(token0.unwrap().clone())], + token: Token::Unit(Foot), + }, + AstNode { + children: vec![AstNode::new(token2.unwrap().clone())], + token: Token::Unit(Inch), + }, + ], + token: Token::Operator(Plus), + }; + return Ok((new_node, pos + 4)); + } + } + } + } - let (mut node, mut pos) = parse_level_4(tokens, pos)?; + let (mut node, mut pos) = parse_level_4(tokens, pos)?; - loop { - let token = tokens.get(pos); - match token { - Some(&Token::Operator(Multiply)) - | Some(&Token::Operator(Divide)) - | Some(&Token::Operator(Modulo)) => { - let (right_node, next_pos) = parse_level_4(tokens, pos + 1)?; - let mut new_node = AstNode::new(token.unwrap().clone()); - new_node.children.push(node); - new_node.children.push(right_node); - node = new_node; - pos = next_pos; - } + loop { + let token = tokens.get(pos); + match token { + Some(&Token::Operator(Multiply)) + | Some(&Token::Operator(Divide)) + | Some(&Token::Operator(Modulo)) => { + let (right_node, next_pos) = parse_level_4(tokens, pos + 1)?; + let mut new_node = AstNode::new(token.unwrap().clone()); + new_node.children.push(node); + new_node.children.push(right_node); + node = new_node; + pos = next_pos; + } - // Below is implicative multiplication, for example '2pi'. Constants and - // such will only end up here if they were unable to be parsed as part of - // other operators. - // Note that this match statement matches an AstNode token, but the - // matches nested inside check the [`Token`]s. That's why we for example - // match a FunctionIdentifier, and inside that, a RightParen. + // Below is implicative multiplication, for example '2pi'. Constants and + // such will only end up here if they were unable to be parsed as part of + // other operators. + // Note that this match statement matches an AstNode token, but the + // matches nested inside check the [`Token`]s. That's why we for example + // match a FunctionIdentifier, and inside that, a RightParen. - // pi2, )2 - Some(&Token::Number(_)) => { - let last_token = tokens.get(pos - 1); - match last_token { - Some(&Token::Constant(_)) | Some(&Token::Operator(RightParen)) => { - let (right_node, next_pos) = parse_level_4(tokens, pos)?; - let mut new_node = AstNode::new(Token::Operator(Multiply)); - new_node.children.push(node); - new_node.children.push(right_node); - node = new_node; - pos = next_pos; - } - _ => { - return Ok((node, pos)); - } - } - } - // 2pi, )pi - Some(&Token::Constant(_)) => { - let last_token = tokens.get(pos - 1); - match last_token { - Some(&Token::Number(_)) | Some(&Token::Operator(RightParen)) => { - let (right_node, next_pos) = parse_level_4(tokens, pos)?; - let mut new_node = AstNode::new(Token::Operator(Multiply)); - new_node.children.push(node); - new_node.children.push(right_node); - node = new_node; - pos = next_pos; - } - _ => { - return Ok((node, pos)); - } - } - } - // 2log(1), )log(1) - Some(&Token::FunctionIdentifier(_)) => { - let last_token = tokens.get(pos - 1); - match last_token { - Some(&Token::Number(_)) | Some(&Token::Operator(RightParen)) => { - let (right_node, next_pos) = parse_level_4(tokens, pos)?; - let mut new_node = AstNode::new(Token::Operator(Multiply)); - new_node.children.push(node); - new_node.children.push(right_node); - node = new_node; - pos = next_pos; - } - _ => { - return Ok((node, pos)); - } - } - } - // 2(3), pi(3), )(3) - Some(&Token::Operator(LeftParen)) => { - let last_token = tokens.get(pos - 1); - match last_token { - Some(&Token::Number(_)) - | Some(&Token::Constant(_)) - | Some(&Token::Operator(RightParen)) => { - let (right_node, next_pos) = parse_level_4(tokens, pos)?; - let mut new_node = AstNode::new(Token::Operator(Multiply)); - new_node.children.push(node); - new_node.children.push(right_node); - node = new_node; - pos = next_pos; - } - _ => { - return Ok((node, pos)); - } - } - } - _ => { - return Ok((node, pos)); - } - } - } + // pi2, )2 + Some(&Token::Number(_)) => { + let last_token = tokens.get(pos - 1); + match last_token { + Some(&Token::Constant(_)) | Some(&Token::Operator(RightParen)) => { + let (right_node, next_pos) = parse_level_4(tokens, pos)?; + let mut new_node = AstNode::new(Token::Operator(Multiply)); + new_node.children.push(node); + new_node.children.push(right_node); + node = new_node; + pos = next_pos; + } + _ => { + return Ok((node, pos)); + } + } + } + // 2pi, )pi + Some(&Token::Constant(_)) => { + let last_token = tokens.get(pos - 1); + match last_token { + Some(&Token::Number(_)) | Some(&Token::Operator(RightParen)) => { + let (right_node, next_pos) = parse_level_4(tokens, pos)?; + let mut new_node = AstNode::new(Token::Operator(Multiply)); + new_node.children.push(node); + new_node.children.push(right_node); + node = new_node; + pos = next_pos; + } + _ => { + return Ok((node, pos)); + } + } + } + // 2log(1), )log(1) + Some(&Token::FunctionIdentifier(_)) => { + let last_token = tokens.get(pos - 1); + match last_token { + Some(&Token::Number(_)) | Some(&Token::Operator(RightParen)) => { + let (right_node, next_pos) = parse_level_4(tokens, pos)?; + let mut new_node = AstNode::new(Token::Operator(Multiply)); + new_node.children.push(node); + new_node.children.push(right_node); + node = new_node; + pos = next_pos; + } + _ => { + return Ok((node, pos)); + } + } + } + // 2(3), pi(3), )(3) + Some(&Token::Operator(LeftParen)) => { + let last_token = tokens.get(pos - 1); + match last_token { + Some(&Token::Number(_)) + | Some(&Token::Constant(_)) + | Some(&Token::Operator(RightParen)) => { + let (right_node, next_pos) = parse_level_4(tokens, pos)?; + let mut new_node = AstNode::new(Token::Operator(Multiply)); + new_node.children.push(node); + new_node.children.push(right_node); + node = new_node; + pos = next_pos; + } + _ => { + return Ok((node, pos)); + } + } + } + _ => { + return Ok((node, pos)); + } + } + } } // level 4 precedence: ^ /// Parse [`Caret`](crate::Operator::Caret) pub fn parse_level_4(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> { - let (mut node, mut pos) = parse_level_5(tokens, pos)?; - loop { - let token = tokens.get(pos); - match token { - Some(&Token::Operator(Caret)) => { - let (right_node, next_pos) = parse_level_5(tokens, pos + 1)?; - let mut new_node = AstNode::new(token.unwrap().clone()); - new_node.children.push(node); - new_node.children.push(right_node); - node = new_node; - pos = next_pos; - } - _ => { - return Ok((node, pos)); - } - } - } + let (mut node, mut pos) = parse_level_5(tokens, pos)?; + loop { + let token = tokens.get(pos); + match token { + Some(&Token::Operator(Caret)) => { + let (right_node, next_pos) = parse_level_5(tokens, pos + 1)?; + let mut new_node = AstNode::new(token.unwrap().clone()); + new_node.children.push(node); + new_node.children.push(right_node); + node = new_node; + pos = next_pos; + } + _ => { + return Ok((node, pos)); + } + } + } } // level 5 precedence: - (as in -5, but not 4-5) /// Parse [`Negative`](Token::Negative) pub fn parse_level_5(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> { - // Here we parse the negative unary operator. If the current token - // is a minus, we wrap the right_node inside a Negative AstNode. - // - // Why doesn't this parse 4-5? First, we will first get a 4. In which case, - // we just return the result of parse_level_6(), which will include the pos - // of +. This will then go down to level 2 and be parsed as a normal minus - // operator. - // The difference is that in other levels, we parse higher priorities - // immediately, while in this one we instead check if the current token - // is a minus, and if not, we then return the higher priority as normal. - let token = tokens.get(pos); - match token { - Some(&Token::Operator(Minus)) => { - let (right_node, next_pos) = parse_level_6(tokens, pos + 1)?; - let mut new_node = AstNode::new(Token::Negative); - new_node.children.push(right_node); - Ok((new_node, next_pos)) - } - _ => parse_level_6(tokens, pos), - } + // Here we parse the negative unary operator. If the current token + // is a minus, we wrap the right_node inside a Negative AstNode. + // + // Why doesn't this parse 4-5? First, we will first get a 4. In which case, + // we just return the result of parse_level_6(), which will include the pos + // of +. This will then go down to level 2 and be parsed as a normal minus + // operator. + // The difference is that in other levels, we parse higher priorities + // immediately, while in this one we instead check if the current token + // is a minus, and if not, we then return the higher priority as normal. + let token = tokens.get(pos); + match token { + Some(&Token::Operator(Minus)) => { + let (right_node, next_pos) = parse_level_6(tokens, pos + 1)?; + let mut new_node = AstNode::new(Token::Negative); + new_node.children.push(right_node); + Ok((new_node, next_pos)) + } + _ => parse_level_6(tokens, pos), + } } // level 6 precedence: !, percent, units attached to values /// Parse [`Factorial`](crate::UnaryOperator::Factorial) and [`Percent`](crate::UnaryOperator::Percent) pub fn parse_level_6(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> { - let (mut node, mut pos) = parse_level_7(tokens, pos)?; - loop { - let token = tokens.get(pos); - match token { - Some(&Token::UnaryOperator(Factorial)) - | Some(&Token::UnaryOperator(Percent)) - | Some(&Token::NamedNumber(_)) => { - // Here we are handling unary operators, aka stuff written as - // "Number Operator" (3!) instead of "Number Operator Number" (3+3). - // Therefore, if we find a match, we don't parse what comes after it. - let mut new_node = AstNode::new(token.unwrap().clone()); - new_node.children.push(node); - node = new_node; - pos += 1; - } - Some(&Token::Unit(_unit)) => { - // We won't allow units to repeat, like "1min min", so we end the loop if it's found. - let mut new_node = AstNode::new(token.unwrap().clone()); - new_node.children.push(node); - return Ok((new_node, pos + 1)); - } - _ => { - // let's say we parse 1+2. parse_level_7 then returns 1, and token - // is set to plus. Plus has lower precedence than level 4, so we - // don't do anything, and pass the number down to a lower precedence. - return Ok((node, pos)); - } - } - } + let (mut node, mut pos) = parse_level_7(tokens, pos)?; + loop { + let token = tokens.get(pos); + match token { + Some(&Token::UnaryOperator(Factorial)) + | Some(&Token::UnaryOperator(Percent)) + | Some(&Token::NamedNumber(_)) => { + // Here we are handling unary operators, aka stuff written as + // "Number Operator" (3!) instead of "Number Operator Number" (3+3). + // Therefore, if we find a match, we don't parse what comes after it. + let mut new_node = AstNode::new(token.unwrap().clone()); + new_node.children.push(node); + node = new_node; + pos += 1; + } + Some(&Token::Unit(_unit)) => { + // We won't allow units to repeat, like "1min min", so we end the loop if it's found. + let mut new_node = AstNode::new(token.unwrap().clone()); + new_node.children.push(node); + return Ok((new_node, pos + 1)); + } + _ => { + // let's say we parse 1+2. parse_level_7 then returns 1, and token + // is set to plus. Plus has lower precedence than level 4, so we + // don't do anything, and pass the number down to a lower precedence. + return Ok((node, pos)); + } + } + } } // level 7 precedence: numbers, standalone units, constants, functions, parens @@ -305,66 +305,68 @@ pub fn parse_level_6(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), S /// [`FunctionIdentifier`](Token::FunctionIdentifier), /// [`Paren`](Token::Paren) pub fn parse_level_7(tokens: &[Token], pos: usize) -> Result<(AstNode, usize), String> { - let token: &Token = tokens - .get(pos) - .ok_or(format!("Unexpected end of input at {}", pos))?; - match token { - &Token::Number(_number) => { - let node = AstNode::new(token.clone()); - Ok((node, pos + 1)) - } - &Token::Unit(_unit) => { - let node = AstNode::new(token.clone()); - Ok((node, pos + 1)) - } - Token::Constant(_constant) => { - let node = AstNode::new(token.clone()); - Ok((node, pos + 1)) - } - Token::FunctionIdentifier(_function_identifier) => { - let left_paren_pos = pos + 1; - let left_paren_token = tokens.get(left_paren_pos); - // check if '(' comes after function identifier, like 'log(' - match left_paren_token { - Some(&Token::Operator(LeftParen)) => { - // parse everything inside as you would with normal parentheses, - // then put it inside an ast node. - parse_level_1(tokens, left_paren_pos + 1).and_then(|(node, next_pos)| { - if let Some(&Token::Operator(RightParen)) = tokens.get(next_pos) { - let mut function_node = AstNode::new(token.clone()); - function_node.children.push(node); - Ok((function_node, next_pos + 1)) - } else { - Err(format!( - "Expected closing paren at {} but found {:?}", - next_pos, - tokens.get(next_pos) - )) - } - }) - } - _ => Err(format!( - "Expected ( after {} at {:?} but found {:?}", - left_paren_pos, token, left_paren_token - )), - } - } - Token::Operator(LeftParen) => parse_level_1(tokens, pos + 1).and_then(|(node, next_pos)| { - if let Some(&Token::Operator(RightParen)) = tokens.get(next_pos) { - let mut paren_node = AstNode::new(Token::Paren); - paren_node.children.push(node); - Ok((paren_node, next_pos + 1)) - } else { - Err(format!( - "Expected closing paren at {} but found {:?}", - next_pos, - tokens.get(next_pos) - )) - } - }), - _ => Err(format!( - "Unexpected token {:?}, expected paren or number", - token - )), - } + let token: &Token = tokens + .get(pos) + .ok_or(format!("Unexpected end of input at {}", pos))?; + match token { + &Token::Number(_number) => { + let node = AstNode::new(token.clone()); + Ok((node, pos + 1)) + } + &Token::Unit(_unit) => { + let node = AstNode::new(token.clone()); + Ok((node, pos + 1)) + } + Token::Constant(_constant) => { + let node = AstNode::new(token.clone()); + Ok((node, pos + 1)) + } + Token::FunctionIdentifier(_function_identifier) => { + let left_paren_pos = pos + 1; + let left_paren_token = tokens.get(left_paren_pos); + // check if '(' comes after function identifier, like 'log(' + match left_paren_token { + Some(&Token::Operator(LeftParen)) => { + // parse everything inside as you would with normal parentheses, + // then put it inside an ast node. + parse_level_1(tokens, left_paren_pos + 1).and_then(|(node, next_pos)| { + if let Some(&Token::Operator(RightParen)) = tokens.get(next_pos) { + let mut function_node = AstNode::new(token.clone()); + function_node.children.push(node); + Ok((function_node, next_pos + 1)) + } else { + Err(format!( + "Expected closing paren at {} but found {:?}", + next_pos, + tokens.get(next_pos) + )) + } + }) + } + _ => Err(format!( + "Expected ( after {} at {:?} but found {:?}", + left_paren_pos, token, left_paren_token + )), + } + } + Token::Operator(LeftParen) => { + parse_level_1(tokens, pos + 1).and_then(|(node, next_pos)| { + if let Some(&Token::Operator(RightParen)) = tokens.get(next_pos) { + let mut paren_node = AstNode::new(Token::Paren); + paren_node.children.push(node); + Ok((paren_node, next_pos + 1)) + } else { + Err(format!( + "Expected closing paren at {} but found {:?}", + next_pos, + tokens.get(next_pos) + )) + } + }) + } + _ => Err(format!( + "Unexpected token {:?}, expected paren or number", + token + )), + } } diff --git a/src/units.rs b/src/units.rs index 6540590..c97253d 100644 --- a/src/units.rs +++ b/src/units.rs @@ -5,40 +5,40 @@ use crate::Number; /// An enum of all possible unit types, like [`Length`], [`DigitalStorage`] etc. /// There is also a [`NoType`] unit type for normal numbers. pub enum UnitType { - /// A normal number, for example `5` - NoType, - /// A unit of time, for example [`Hour`] - Time, - /// A unit of length, for example [`Mile`] - Length, - /// A unit of area, for example [`SquareKilometer`] - Area, - /// A unit of volume, for example [`Liter`] or [`Tablespoon`] - Volume, - /// A unit of mass, for example [`Gram`] - Mass, - /// A unit of digital storage, for example [`Kilobyte`] - DigitalStorage, - /// A unit of data rate transfer, for example [`KilobytesPerSecond`] - DataTransferRate, - /// A unit of energy, for example [`Joule`] or [`KilowattHour`] - Energy, - /// A unit of power, for example [`Watt`] - Power, - /// A unit of electrical current, for example [`Ampere`] - ElectricCurrent, - /// A unit of electric resistance, for example [`Ohm`] - Resistance, - /// A unit of voltage, for example [`Volt`] - Voltage, - /// A unit of pressure, for example [`Bar`] - Pressure, - /// A unit of frequency, for example [`Hertz`] - Frequency, - /// A unit of x, for example [`KilometersPerHour`] - Speed, - /// A unit of temperature, for example [`Kelvin`] - Temperature, + /// A normal number, for example `5` + NoType, + /// A unit of time, for example [`Hour`] + Time, + /// A unit of length, for example [`Mile`] + Length, + /// A unit of area, for example [`SquareKilometer`] + Area, + /// A unit of volume, for example [`Liter`] or [`Tablespoon`] + Volume, + /// A unit of mass, for example [`Gram`] + Mass, + /// A unit of digital storage, for example [`Kilobyte`] + DigitalStorage, + /// A unit of data rate transfer, for example [`KilobytesPerSecond`] + DataTransferRate, + /// A unit of energy, for example [`Joule`] or [`KilowattHour`] + Energy, + /// A unit of power, for example [`Watt`] + Power, + /// A unit of electrical current, for example [`Ampere`] + ElectricCurrent, + /// A unit of electric resistance, for example [`Ohm`] + Resistance, + /// A unit of voltage, for example [`Volt`] + Voltage, + /// A unit of pressure, for example [`Bar`] + Pressure, + /// A unit of frequency, for example [`Hertz`] + Frequency, + /// A unit of x, for example [`KilometersPerHour`] + Speed, + /// A unit of temperature, for example [`Kelvin`] + Temperature, } use UnitType::*; @@ -46,275 +46,275 @@ use UnitType::*; // with this because the default units are imported into the lexer, parser // and evaluator macro_rules! create_units { - ( $( $variant:ident : $properties:expr ),*, ) => { - #[derive(Clone, Copy, PartialEq, Debug)] - /// A Unit enum. Note that it can also be [`NoUnit`]. - pub enum Unit { - $($variant),* - } - use Unit::*; + ( $( $variant:ident : $properties:expr ),*, ) => { + #[derive(Clone, Copy, PartialEq, Debug)] + /// A Unit enum. Note that it can also be [`NoUnit`]. + pub enum Unit { + $($variant),* + } + use Unit::*; - impl Unit { - pub fn category(&self) -> UnitType { - match self { - $( - Unit::$variant => $properties.0 - ),* - } - } - pub fn weight(&self) -> d128 { - match self { - $( - Unit::$variant => $properties.1 - ),* - } - } - } - } + impl Unit { + pub fn category(&self) -> UnitType { + match self { + $( + Unit::$variant => $properties.0 + ),* + } + } + pub fn weight(&self) -> d128 { + match self { + $( + Unit::$variant => $properties.1 + ),* + } + } + } + } } create_units!( - NoUnit: (NoType, d128!(1)), + NoUnit: (NoType, d128!(1)), - Nanosecond: (Time, d128!(1)), - Microsecond: (Time, d128!(1000)), - Millisecond: (Time, d128!(1000000)), - Second: (Time, d128!(1000000000)), - Minute: (Time, d128!(60000000000)), - Hour: (Time, d128!(3600000000000)), - Day: (Time, d128!(86400000000000)), - Week: (Time, d128!(604800000000000)), - Month: (Time, d128!(2629746000000000)), - Quarter: (Time, d128!(7889238000000000)), - Year: (Time, d128!(31556952000000000)), - Decade: (Time, d128!(315569520000000000)), - Century: (Time, d128!(3155695200000000000)), - Millenium: (Time, d128!(31556952000000000000)), + Nanosecond: (Time, d128!(1)), + Microsecond: (Time, d128!(1000)), + Millisecond: (Time, d128!(1000000)), + Second: (Time, d128!(1000000000)), + Minute: (Time, d128!(60000000000)), + Hour: (Time, d128!(3600000000000)), + Day: (Time, d128!(86400000000000)), + Week: (Time, d128!(604800000000000)), + Month: (Time, d128!(2629746000000000)), + Quarter: (Time, d128!(7889238000000000)), + Year: (Time, d128!(31556952000000000)), + Decade: (Time, d128!(315569520000000000)), + Century: (Time, d128!(3155695200000000000)), + Millenium: (Time, d128!(31556952000000000000)), - Millimeter: (Length, d128!(1)), - Centimeter: (Length, d128!(10)), - Decimeter: (Length, d128!(100)), - Meter: (Length, d128!(1000)), - Kilometer: (Length, d128!(1000000)), - Inch: (Length, d128!(25.4)), - Foot: (Length, d128!(304.8)), - Yard: (Length, d128!(914.4)), - Mile: (Length, d128!(1609344)), - // 1-dimensional only: - NauticalMile: (Length, d128!(1852000)), - LightYear: (Length, d128!(9460730472580800000)), - LightSecond: (Length, d128!(299792458000)), + Millimeter: (Length, d128!(1)), + Centimeter: (Length, d128!(10)), + Decimeter: (Length, d128!(100)), + Meter: (Length, d128!(1000)), + Kilometer: (Length, d128!(1000000)), + Inch: (Length, d128!(25.4)), + Foot: (Length, d128!(304.8)), + Yard: (Length, d128!(914.4)), + Mile: (Length, d128!(1609344)), + // 1-dimensional only: + NauticalMile: (Length, d128!(1852000)), + LightYear: (Length, d128!(9460730472580800000)), + LightSecond: (Length, d128!(299792458000)), - SquareMillimeter: (Area, d128!(1)), - SquareCentimeter: (Area, d128!(100)), - SquareDecimeter: (Area, d128!(10000)), - SquareMeter: (Area, d128!(1000000)), - SquareKilometer: (Area, d128!(1000000000000)), - SquareInch: (Area, d128!(645.16)), - SquareFoot: (Area, d128!(92903.04)), - SquareYard: (Area, d128!(836127.36)), - SquareMile: (Area, d128!(2589988110336.00)), - // 2-dimensional only - Are: (Area, d128!(100000000)), - Decare: (Area, d128!(1000000000)), - Hectare: (Area, d128!(10000000000)), - Acre: (Area, d128!(4046856422.40)), + SquareMillimeter: (Area, d128!(1)), + SquareCentimeter: (Area, d128!(100)), + SquareDecimeter: (Area, d128!(10000)), + SquareMeter: (Area, d128!(1000000)), + SquareKilometer: (Area, d128!(1000000000000)), + SquareInch: (Area, d128!(645.16)), + SquareFoot: (Area, d128!(92903.04)), + SquareYard: (Area, d128!(836127.36)), + SquareMile: (Area, d128!(2589988110336.00)), + // 2-dimensional only + Are: (Area, d128!(100000000)), + Decare: (Area, d128!(1000000000)), + Hectare: (Area, d128!(10000000000)), + Acre: (Area, d128!(4046856422.40)), - CubicMillimeter: (Volume, d128!(1)), - CubicCentimeter: (Volume, d128!(1000)), - CubicDecimeter: (Volume, d128!(1000000)), - CubicMeter: (Volume, d128!(1000000000)), - CubicKilometer: (Volume, d128!(1000000000000000000)), - CubicInch: (Volume, d128!(16387.064)), - CubicFoot: (Volume, d128!(28316846.592)), - CubicYard: (Volume, d128!(764554857.984)), - CubicMile: (Volume, d128!(4168181825440579584)), - // 3-dimensional only - Milliliter: (Volume, d128!(1000)), - Centiliter: (Volume, d128!(10000)), - Deciliter: (Volume, d128!(100000)), - Liter: (Volume, d128!(1000000)), - Teaspoon: (Volume, d128!(4928.92159375)), - Tablespoon: (Volume, d128!(14786.76478125)), - FluidOunce: (Volume, d128!(29573.5295625)), - Cup: (Volume, d128!(236588.2365)), - Pint: (Volume, d128!(473176.473)), - Quart: (Volume, d128!(946352.946)), - Gallon: (Volume, d128!(3785411.784)), - OilBarrel: (Volume, d128!(158987294.928)), + CubicMillimeter: (Volume, d128!(1)), + CubicCentimeter: (Volume, d128!(1000)), + CubicDecimeter: (Volume, d128!(1000000)), + CubicMeter: (Volume, d128!(1000000000)), + CubicKilometer: (Volume, d128!(1000000000000000000)), + CubicInch: (Volume, d128!(16387.064)), + CubicFoot: (Volume, d128!(28316846.592)), + CubicYard: (Volume, d128!(764554857.984)), + CubicMile: (Volume, d128!(4168181825440579584)), + // 3-dimensional only + Milliliter: (Volume, d128!(1000)), + Centiliter: (Volume, d128!(10000)), + Deciliter: (Volume, d128!(100000)), + Liter: (Volume, d128!(1000000)), + Teaspoon: (Volume, d128!(4928.92159375)), + Tablespoon: (Volume, d128!(14786.76478125)), + FluidOunce: (Volume, d128!(29573.5295625)), + Cup: (Volume, d128!(236588.2365)), + Pint: (Volume, d128!(473176.473)), + Quart: (Volume, d128!(946352.946)), + Gallon: (Volume, d128!(3785411.784)), + OilBarrel: (Volume, d128!(158987294.928)), - Milligram: (Mass, d128!(0.001)), - Gram: (Mass, d128!(1)), - Hectogram: (Mass, d128!(100)), - Kilogram: (Mass, d128!(1000)), - MetricTon: (Mass, d128!(1000000)), - Ounce: (Mass, d128!(28.349523125)), - Pound: (Mass, d128!(453.59237)), - Stone: (Mass, d128!(6350.29318)), - ShortTon: (Mass, d128!(907184.74)), - LongTon: (Mass, d128!(1016046.9088)), + Milligram: (Mass, d128!(0.001)), + Gram: (Mass, d128!(1)), + Hectogram: (Mass, d128!(100)), + Kilogram: (Mass, d128!(1000)), + MetricTon: (Mass, d128!(1000000)), + Ounce: (Mass, d128!(28.349523125)), + Pound: (Mass, d128!(453.59237)), + Stone: (Mass, d128!(6350.29318)), + ShortTon: (Mass, d128!(907184.74)), + LongTon: (Mass, d128!(1016046.9088)), - Bit: (DigitalStorage, d128!(1)), - Kilobit: (DigitalStorage, d128!(1000)), - Megabit: (DigitalStorage, d128!(1000000)), - Gigabit: (DigitalStorage, d128!(1000000000)), - Terabit: (DigitalStorage, d128!(1000000000000)), - Petabit: (DigitalStorage, d128!(1000000000000000)), - Exabit: (DigitalStorage, d128!(1000000000000000000)), - Zettabit: (DigitalStorage, d128!(1000000000000000000000)), - Yottabit: (DigitalStorage, d128!(1000000000000000000000000)), - Kibibit: (DigitalStorage, d128!(1024)), - Mebibit: (DigitalStorage, d128!(1048576)), - Gibibit: (DigitalStorage, d128!(1073741824)), - Tebibit: (DigitalStorage, d128!(1099511627776)), - Pebibit: (DigitalStorage, d128!(1125899906842624)), - Exbibit: (DigitalStorage, d128!(1152921504606846976)), - Zebibit: (DigitalStorage, d128!(1180591620717411303424)), - Yobibit: (DigitalStorage, d128!(1208925819614629174706176)), - Byte: (DigitalStorage, d128!(8)), - Kilobyte: (DigitalStorage, d128!(8000)), - Megabyte: (DigitalStorage, d128!(8000000)), - Gigabyte: (DigitalStorage, d128!(8000000000)), - Terabyte: (DigitalStorage, d128!(8000000000000)), - Petabyte: (DigitalStorage, d128!(8000000000000000)), - Exabyte: (DigitalStorage, d128!(8000000000000000000)), - Zettabyte: (DigitalStorage, d128!(8000000000000000000000)), - Yottabyte: (DigitalStorage, d128!(8000000000000000000000000)), - Kibibyte: (DigitalStorage, d128!(8192)), - Mebibyte: (DigitalStorage, d128!(8388608)), - Gibibyte: (DigitalStorage, d128!(8589934592)), - Tebibyte: (DigitalStorage, d128!(8796093022208)), - Pebibyte: (DigitalStorage, d128!(9007199254740992)), - Exbibyte: (DigitalStorage, d128!(9223372036854775808)), - Zebibyte: (DigitalStorage, d128!(9444732965739290427392)), - Yobibyte: (DigitalStorage, d128!(9671406556917033397649408)), + Bit: (DigitalStorage, d128!(1)), + Kilobit: (DigitalStorage, d128!(1000)), + Megabit: (DigitalStorage, d128!(1000000)), + Gigabit: (DigitalStorage, d128!(1000000000)), + Terabit: (DigitalStorage, d128!(1000000000000)), + Petabit: (DigitalStorage, d128!(1000000000000000)), + Exabit: (DigitalStorage, d128!(1000000000000000000)), + Zettabit: (DigitalStorage, d128!(1000000000000000000000)), + Yottabit: (DigitalStorage, d128!(1000000000000000000000000)), + Kibibit: (DigitalStorage, d128!(1024)), + Mebibit: (DigitalStorage, d128!(1048576)), + Gibibit: (DigitalStorage, d128!(1073741824)), + Tebibit: (DigitalStorage, d128!(1099511627776)), + Pebibit: (DigitalStorage, d128!(1125899906842624)), + Exbibit: (DigitalStorage, d128!(1152921504606846976)), + Zebibit: (DigitalStorage, d128!(1180591620717411303424)), + Yobibit: (DigitalStorage, d128!(1208925819614629174706176)), + Byte: (DigitalStorage, d128!(8)), + Kilobyte: (DigitalStorage, d128!(8000)), + Megabyte: (DigitalStorage, d128!(8000000)), + Gigabyte: (DigitalStorage, d128!(8000000000)), + Terabyte: (DigitalStorage, d128!(8000000000000)), + Petabyte: (DigitalStorage, d128!(8000000000000000)), + Exabyte: (DigitalStorage, d128!(8000000000000000000)), + Zettabyte: (DigitalStorage, d128!(8000000000000000000000)), + Yottabyte: (DigitalStorage, d128!(8000000000000000000000000)), + Kibibyte: (DigitalStorage, d128!(8192)), + Mebibyte: (DigitalStorage, d128!(8388608)), + Gibibyte: (DigitalStorage, d128!(8589934592)), + Tebibyte: (DigitalStorage, d128!(8796093022208)), + Pebibyte: (DigitalStorage, d128!(9007199254740992)), + Exbibyte: (DigitalStorage, d128!(9223372036854775808)), + Zebibyte: (DigitalStorage, d128!(9444732965739290427392)), + Yobibyte: (DigitalStorage, d128!(9671406556917033397649408)), - BitsPerSecond: (DataTransferRate, d128!(1)), - KilobitsPerSecond: (DataTransferRate, d128!(1000)), - MegabitsPerSecond: (DataTransferRate, d128!(1000000)), - GigabitsPerSecond: (DataTransferRate, d128!(1000000000)), - TerabitsPerSecond: (DataTransferRate, d128!(1000000000000)), - PetabitsPerSecond: (DataTransferRate, d128!(1000000000000000)), - ExabitsPerSecond: (DataTransferRate, d128!(1000000000000000000)), - ZettabitsPerSecond: (DataTransferRate, d128!(1000000000000000000000)), - YottabitsPerSecond: (DataTransferRate, d128!(1000000000000000000000000)), - KibibitsPerSecond: (DataTransferRate, d128!(1024)), - MebibitsPerSecond: (DataTransferRate, d128!(1048576)), - GibibitsPerSecond: (DataTransferRate, d128!(1073741824)), - TebibitsPerSecond: (DataTransferRate, d128!(1099511627776)), - PebibitsPerSecond: (DataTransferRate, d128!(1125899906842624)), - ExbibitsPerSecond: (DataTransferRate, d128!(1152921504606846976)), - ZebibitsPerSecond: (DataTransferRate, d128!(1180591620717411303424)), - YobibitsPerSecond: (DataTransferRate, d128!(1208925819614629174706176)), - BytesPerSecond: (DataTransferRate, d128!(8)), - KilobytesPerSecond: (DataTransferRate, d128!(8000)), - MegabytesPerSecond: (DataTransferRate, d128!(8000000)), - GigabytesPerSecond: (DataTransferRate, d128!(8000000000)), - TerabytesPerSecond: (DataTransferRate, d128!(8000000000000)), - PetabytesPerSecond: (DataTransferRate, d128!(8000000000000000)), - ExabytesPerSecond: (DataTransferRate, d128!(8000000000000000000)), - ZettabytesPerSecond: (DataTransferRate, d128!(8000000000000000000000)), - YottabytesPerSecond: (DataTransferRate, d128!(8000000000000000000000000)), - KibibytesPerSecond: (DataTransferRate, d128!(8192)), - MebibytesPerSecond: (DataTransferRate, d128!(8388608)), - GibibytesPerSecond: (DataTransferRate, d128!(8589934592)), - TebibytesPerSecond: (DataTransferRate, d128!(8796093022208)), - PebibytesPerSecond: (DataTransferRate, d128!(9007199254740992)), - ExbibytesPerSecond: (DataTransferRate, d128!(9223372036854775808)), - ZebibytesPerSecond: (DataTransferRate, d128!(9444732965739290427392)), - YobibytesPerSecond: (DataTransferRate, d128!(9671406556917033397649408)), + BitsPerSecond: (DataTransferRate, d128!(1)), + KilobitsPerSecond: (DataTransferRate, d128!(1000)), + MegabitsPerSecond: (DataTransferRate, d128!(1000000)), + GigabitsPerSecond: (DataTransferRate, d128!(1000000000)), + TerabitsPerSecond: (DataTransferRate, d128!(1000000000000)), + PetabitsPerSecond: (DataTransferRate, d128!(1000000000000000)), + ExabitsPerSecond: (DataTransferRate, d128!(1000000000000000000)), + ZettabitsPerSecond: (DataTransferRate, d128!(1000000000000000000000)), + YottabitsPerSecond: (DataTransferRate, d128!(1000000000000000000000000)), + KibibitsPerSecond: (DataTransferRate, d128!(1024)), + MebibitsPerSecond: (DataTransferRate, d128!(1048576)), + GibibitsPerSecond: (DataTransferRate, d128!(1073741824)), + TebibitsPerSecond: (DataTransferRate, d128!(1099511627776)), + PebibitsPerSecond: (DataTransferRate, d128!(1125899906842624)), + ExbibitsPerSecond: (DataTransferRate, d128!(1152921504606846976)), + ZebibitsPerSecond: (DataTransferRate, d128!(1180591620717411303424)), + YobibitsPerSecond: (DataTransferRate, d128!(1208925819614629174706176)), + BytesPerSecond: (DataTransferRate, d128!(8)), + KilobytesPerSecond: (DataTransferRate, d128!(8000)), + MegabytesPerSecond: (DataTransferRate, d128!(8000000)), + GigabytesPerSecond: (DataTransferRate, d128!(8000000000)), + TerabytesPerSecond: (DataTransferRate, d128!(8000000000000)), + PetabytesPerSecond: (DataTransferRate, d128!(8000000000000000)), + ExabytesPerSecond: (DataTransferRate, d128!(8000000000000000000)), + ZettabytesPerSecond: (DataTransferRate, d128!(8000000000000000000000)), + YottabytesPerSecond: (DataTransferRate, d128!(8000000000000000000000000)), + KibibytesPerSecond: (DataTransferRate, d128!(8192)), + MebibytesPerSecond: (DataTransferRate, d128!(8388608)), + GibibytesPerSecond: (DataTransferRate, d128!(8589934592)), + TebibytesPerSecond: (DataTransferRate, d128!(8796093022208)), + PebibytesPerSecond: (DataTransferRate, d128!(9007199254740992)), + ExbibytesPerSecond: (DataTransferRate, d128!(9223372036854775808)), + ZebibytesPerSecond: (DataTransferRate, d128!(9444732965739290427392)), + YobibytesPerSecond: (DataTransferRate, d128!(9671406556917033397649408)), - // ! If updating Millijoule, also update get_inverted_millijoule_weight() - Millijoule: (Energy, d128!(0.001)), - Joule: (Energy, d128!(1)), - NewtonMeter: (Energy, d128!(1)), - Kilojoule: (Energy, d128!(1000)), - Megajoule: (Energy, d128!(1000000)), - Gigajoule: (Energy, d128!(1000000000)), - Terajoule: (Energy, d128!(1000000000000)), - Calorie: (Energy, d128!(4.1868)), - KiloCalorie: (Energy, d128!(4186.8)), - BritishThermalUnit: (Energy, d128!(1055.05585262)), - WattHour: (Energy, d128!(3600)), - KilowattHour: (Energy, d128!(3600000)), - MegawattHour: (Energy, d128!(3600000000)), - GigawattHour: (Energy, d128!(3600000000000)), - TerawattHour: (Energy, d128!(3600000000000000)), - PetawattHour: (Energy, d128!(3600000000000000000)), + // ! If updating Millijoule, also update get_inverted_millijoule_weight() + Millijoule: (Energy, d128!(0.001)), + Joule: (Energy, d128!(1)), + NewtonMeter: (Energy, d128!(1)), + Kilojoule: (Energy, d128!(1000)), + Megajoule: (Energy, d128!(1000000)), + Gigajoule: (Energy, d128!(1000000000)), + Terajoule: (Energy, d128!(1000000000000)), + Calorie: (Energy, d128!(4.1868)), + KiloCalorie: (Energy, d128!(4186.8)), + BritishThermalUnit: (Energy, d128!(1055.05585262)), + WattHour: (Energy, d128!(3600)), + KilowattHour: (Energy, d128!(3600000)), + MegawattHour: (Energy, d128!(3600000000)), + GigawattHour: (Energy, d128!(3600000000000)), + TerawattHour: (Energy, d128!(3600000000000000)), + PetawattHour: (Energy, d128!(3600000000000000000)), - // ! If updating Milliwatt, also update get_inverted_milliwatt_weight() - Milliwatt: (Power, d128!(0.001)), - Watt: (Power, d128!(1)), - Kilowatt: (Power, d128!(1000)), - Megawatt: (Power, d128!(1000000)), - Gigawatt: (Power, d128!(1000000000)), - Terawatt: (Power, d128!(1000000000000)), - Petawatt: (Power, d128!(1000000000000000)), - BritishThermalUnitsPerMinute: (Power, d128!(0.0568690272188)), // probably inexact - BritishThermalUnitsPerHour: (Power, d128!(3.412141633128)), // probably inexact - Horsepower: (Power, d128!(745.69987158227022)), // exact according to wikipedia - MetricHorsepower: (Power, d128!(735.49875)), + // ! If updating Milliwatt, also update get_inverted_milliwatt_weight() + Milliwatt: (Power, d128!(0.001)), + Watt: (Power, d128!(1)), + Kilowatt: (Power, d128!(1000)), + Megawatt: (Power, d128!(1000000)), + Gigawatt: (Power, d128!(1000000000)), + Terawatt: (Power, d128!(1000000000000)), + Petawatt: (Power, d128!(1000000000000000)), + BritishThermalUnitsPerMinute: (Power, d128!(0.0568690272188)), // probably inexact + BritishThermalUnitsPerHour: (Power, d128!(3.412141633128)), // probably inexact + Horsepower: (Power, d128!(745.69987158227022)), // exact according to wikipedia + MetricHorsepower: (Power, d128!(735.49875)), - // ! If updating Milliampere, also update get_inverted_milliampere_weight() - Milliampere: (ElectricCurrent, d128!(0.001)), - Ampere: (ElectricCurrent, d128!(1)), - Kiloampere: (ElectricCurrent, d128!(1000)), - Abampere: (ElectricCurrent, d128!(10)), + // ! If updating Milliampere, also update get_inverted_milliampere_weight() + Milliampere: (ElectricCurrent, d128!(0.001)), + Ampere: (ElectricCurrent, d128!(1)), + Kiloampere: (ElectricCurrent, d128!(1000)), + Abampere: (ElectricCurrent, d128!(10)), - // ! If updating Milliohm, also update get_inverted_milliohm_weight() - Milliohm: (Resistance, d128!(0.001)), - Ohm: (Resistance, d128!(1)), - Kiloohm: (Resistance, d128!(1000)), + // ! If updating Milliohm, also update get_inverted_milliohm_weight() + Milliohm: (Resistance, d128!(0.001)), + Ohm: (Resistance, d128!(1)), + Kiloohm: (Resistance, d128!(1000)), - // ! If updating Millivolt, also update get_inverted_millivolt_weight() - Millivolt: (Voltage, d128!(0.001)), - Volt: (Voltage, d128!(1)), - Kilovolt: (Voltage, d128!(1000)), + // ! If updating Millivolt, also update get_inverted_millivolt_weight() + Millivolt: (Voltage, d128!(0.001)), + Volt: (Voltage, d128!(1)), + Kilovolt: (Voltage, d128!(1000)), - Pascal: (Pressure, d128!(1)), - Kilopascal: (Pressure, d128!(1000)), - Atmosphere: (Pressure, d128!(101325)), - Millibar: (Pressure, d128!(100)), - Bar: (Pressure, d128!(100000)), - InchOfMercury: (Pressure, d128!(3386.389)), - PoundsPerSquareInch: (Pressure, d128!(6894.757293168361)), // inexact - Torr: (Pressure, d128!(162.12)), + Pascal: (Pressure, d128!(1)), + Kilopascal: (Pressure, d128!(1000)), + Atmosphere: (Pressure, d128!(101325)), + Millibar: (Pressure, d128!(100)), + Bar: (Pressure, d128!(100000)), + InchOfMercury: (Pressure, d128!(3386.389)), + PoundsPerSquareInch: (Pressure, d128!(6894.757293168361)), // inexact + Torr: (Pressure, d128!(162.12)), - Hertz: (Frequency, d128!(1)), - Kilohertz: (Frequency, d128!(1000)), - Megahertz: (Frequency, d128!(1000000)), - Gigahertz: (Frequency, d128!(1000000000)), - Terahertz: (Frequency, d128!(1000000000000)), - Petahertz: (Frequency, d128!(1000000000000000)), - RevolutionsPerMinute: (Frequency, d128!(60)), + Hertz: (Frequency, d128!(1)), + Kilohertz: (Frequency, d128!(1000)), + Megahertz: (Frequency, d128!(1000000)), + Gigahertz: (Frequency, d128!(1000000000)), + Terahertz: (Frequency, d128!(1000000000000)), + Petahertz: (Frequency, d128!(1000000000000000)), + RevolutionsPerMinute: (Frequency, d128!(60)), - KilometersPerHour: (Speed, d128!(1)), - MetersPerSecond: (Speed, d128!(3.6)), - MilesPerHour: (Speed, d128!(1.609344)), - FeetPerSecond: (Speed, d128!(1.09728)), - Knot: (Speed, d128!(1.852)), + KilometersPerHour: (Speed, d128!(1)), + MetersPerSecond: (Speed, d128!(3.6)), + MilesPerHour: (Speed, d128!(1.609344)), + FeetPerSecond: (Speed, d128!(1.09728)), + Knot: (Speed, d128!(1.852)), - Kelvin: (Temperature, d128!(0)), - Celsius: (Temperature, d128!(0)), - Fahrenheit: (Temperature, d128!(0)), + Kelvin: (Temperature, d128!(0)), + Celsius: (Temperature, d128!(0)), + Fahrenheit: (Temperature, d128!(0)), ); // These functions are here to avoid dividing by small numbers like 0.01, // because d128 gives numbers in E notation in that case. fn get_inverted_millijoule_weight() -> d128 { - d128!(1000) + d128!(1000) } fn get_inverted_milliwatt_weight() -> d128 { - d128!(1000) + d128!(1000) } fn get_inverted_milliohm_weight() -> d128 { - d128!(1000) + d128!(1000) } fn get_inverted_milliampere_weight() -> d128 { - d128!(1000) + d128!(1000) } fn get_inverted_millivolt_weight() -> d128 { - d128!(1000) + d128!(1000) } /// Returns the conversion factor between two units. @@ -325,73 +325,73 @@ fn get_inverted_millivolt_weight() -> d128 { /// /// This is not sufficient for [`Temperature`] units. pub fn get_conversion_factor(unit: Unit, to_unit: Unit) -> d128 { - unit.weight() / to_unit.weight() + unit.weight() / to_unit.weight() } /// Convert a [`Number`] to a specified [`Unit`]. pub fn convert(number: Number, to_unit: Unit) -> Result { - if number.unit.category() != to_unit.category() { - return Err(format!("Cannot convert from {:?} to {:?}", number.unit, to_unit)); - } - let value = number.value; - let ok = |new_value| { - Ok(Number::new(new_value, to_unit)) - }; - if number.unit.category() == UnitType::Temperature { - match (number.unit, to_unit) { - (Kelvin, Kelvin) => ok(value), - (Kelvin, Celsius) => ok(value-d128!(273.15)), - (Kelvin, Fahrenheit) => ok(value*d128!(1.8)-d128!(459.67)), - (Celsius, Celsius) => ok(value), - (Celsius, Kelvin) => ok(value+d128!(273.15)), - (Celsius, Fahrenheit) => ok(value*d128!(1.8)+d128!(32)), - (Fahrenheit, Fahrenheit) => ok(value), - (Fahrenheit, Kelvin) => ok((value+d128!(459.67))*d128!(5)/d128!(9)), - (Fahrenheit, Celsius) => ok((value-d128!(32))/d128!(1.8)), - _ => Err(format!("Error converting temperature {:?} to {:?}", number.unit, to_unit)), - } - } else { - let conversion_factor = get_conversion_factor(number.unit, to_unit); - ok(number.value * conversion_factor) - } + if number.unit.category() != to_unit.category() { + return Err(format!("Cannot convert from {:?} to {:?}", number.unit, to_unit)); + } + let value = number.value; + let ok = |new_value| { + Ok(Number::new(new_value, to_unit)) + }; + if number.unit.category() == UnitType::Temperature { + match (number.unit, to_unit) { + (Kelvin, Kelvin) => ok(value), + (Kelvin, Celsius) => ok(value-d128!(273.15)), + (Kelvin, Fahrenheit) => ok(value*d128!(1.8)-d128!(459.67)), + (Celsius, Celsius) => ok(value), + (Celsius, Kelvin) => ok(value+d128!(273.15)), + (Celsius, Fahrenheit) => ok(value*d128!(1.8)+d128!(32)), + (Fahrenheit, Fahrenheit) => ok(value), + (Fahrenheit, Kelvin) => ok((value+d128!(459.67))*d128!(5)/d128!(9)), + (Fahrenheit, Celsius) => ok((value-d128!(32))/d128!(1.8)), + _ => Err(format!("Error converting temperature {:?} to {:?}", number.unit, to_unit)), + } + } else { + let conversion_factor = get_conversion_factor(number.unit, to_unit); + ok(number.value * conversion_factor) + } } /// If one of two provided [`Number`]s has a larger [`Unit`] than the other, convert /// the large one to the unit of the small one. pub fn convert_to_lowest(left: Number, right: Number) -> Result<(Number, Number), String> { - if left.unit.weight() == right.unit.weight() { - Ok((left, right)) - } else if left.unit.weight() > right.unit.weight() { - let left_converted = convert(left, right.unit)?; - Ok((left_converted, right)) - } else { - let right_converted = convert(right, left.unit)?; - Ok((left, right_converted)) - } + if left.unit.weight() == right.unit.weight() { + Ok((left, right)) + } else if left.unit.weight() > right.unit.weight() { + let left_converted = convert(left, right.unit)?; + Ok((left_converted, right)) + } else { + let right_converted = convert(right, left.unit)?; + Ok((left, right_converted)) + } } /// Return the sum of two [`Number`]s pub fn add(left: Number, right: Number) -> Result { - if left.unit == right.unit { - Ok(Number::new(left.value + right.value, left.unit)) - } else if left.unit.category() == right.unit.category() && left.unit.category() != Temperature { - let (left, right) = convert_to_lowest(left, right)?; - Ok(Number::new(left.value + right.value, left.unit)) - } else { - Err(format!("Cannot add {:?} and {:?}", left.unit, right.unit)) - } + if left.unit == right.unit { + Ok(Number::new(left.value + right.value, left.unit)) + } else if left.unit.category() == right.unit.category() && left.unit.category() != Temperature { + let (left, right) = convert_to_lowest(left, right)?; + Ok(Number::new(left.value + right.value, left.unit)) + } else { + Err(format!("Cannot add {:?} and {:?}", left.unit, right.unit)) + } } /// Subtract a [`Number`] from another [`Number`] pub fn subtract(left: Number, right: Number) -> Result { - if left.unit == right.unit { - Ok(Number::new(left.value - right.value, left.unit)) - } else if left.unit.category() == right.unit.category() && left.unit.category() != Temperature { - let (left, right) = convert_to_lowest(left, right)?; - Ok(Number::new(left.value - right.value, left.unit)) - } else { - Err(format!("Cannot subtract {:?} by {:?}", left.unit, right.unit)) - } + if left.unit == right.unit { + Ok(Number::new(left.value - right.value, left.unit)) + } else if left.unit.category() == right.unit.category() && left.unit.category() != Temperature { + let (left, right) = convert_to_lowest(left, right)?; + Ok(Number::new(left.value - right.value, left.unit)) + } else { + Err(format!("Cannot subtract {:?} by {:?}", left.unit, right.unit)) + } } /// Convert a [`Number`] to an ideal unit. @@ -402,142 +402,142 @@ pub fn subtract(left: Number, right: Number) -> Result { /// `Energy`, `Power`, `ElectricCurrent`, `Resistance`, and `Voltage`. /// Other units are passed through. pub fn to_ideal_unit(number: Number) -> Number { - let value = number.value * number.unit.weight(); - if number.unit.category() == Length { - if value >= d128!(1000000000000000000) { // ≈ 0.1 light years - return Number::new(value/Kilometer.weight(), Kilometer) - } else if value >= d128!(1000000) { // 1 km - return Number::new(value/Kilometer.weight(), Kilometer) - } else if value >= d128!(1000) { // 1 m - return Number::new(value/Meter.weight(), Meter) - } else if value >= d128!(10) { // 1 cm - return Number::new(value/Centimeter.weight(), Centimeter) - } else { - return Number::new(value, Millimeter) - } - } else if number.unit.category() == Time { - if value >= d128!(31556952000000000) { - return Number::new(value/Year.weight(), Year); - } else if value >= d128!(86400000000000) { - return Number::new(value/Day.weight(), Day); - } else if value >= d128!(3600000000000) { - return Number::new(value/Hour.weight(), Hour); - } else if value >= d128!(60000000000) { - return Number::new(value/Minute.weight(), Minute); - } else if value >= d128!(1000000000) { - return Number::new(value/Second.weight(), Second); - } else if value >= d128!(1000000) { - return Number::new(value/Millisecond.weight(), Millisecond); - } else if value >= d128!(1000) { - return Number::new(value/Microsecond.weight(), Microsecond); - } else { - return Number::new(value, Nanosecond); - } - } else if number.unit.category() == Area { - if value >= d128!(1000000000000) { // 1 km2 - return Number::new(value/SquareKilometer.weight(), SquareKilometer) - } else if value >= d128!(10000000000) { // 1 hectare - return Number::new(value/Hectare.weight(), Hectare) - } else if value >= d128!(1000000) { // 1 m2 - return Number::new(value/SquareMeter.weight(), SquareMeter) - } else if value >= d128!(100) { // 1 cm2 - return Number::new(value/SquareCentimeter.weight(), SquareCentimeter) - } else { - return Number::new(value, SquareMillimeter) - } - } else if number.unit.category() == Volume { - if value >= d128!(1000000000000000000) { // 1 km3 - return Number::new(value/CubicKilometer.weight(), CubicKilometer) - } else if value >= d128!(1000000000) { // 1 m3 - return Number::new(value/CubicMeter.weight(), CubicMeter) - } else if value >= d128!(1000000) { // 1 l - return Number::new(value/Liter.weight(), Liter) - } else if value >= d128!(1000) { // 1 ml - return Number::new(value/Milliliter.weight(), Milliliter) - } else { - return Number::new(value, CubicMillimeter) - } - } else if number.unit.category() == Energy { - if value >= d128!(3600000000000000000) { // 1 petawatthour - return Number::new(value/PetawattHour.weight(), PetawattHour) - } else if value >= d128!(3600000000000000) { // 1 terawatthour - return Number::new(value/TerawattHour.weight(), TerawattHour) - } else if value >= d128!(3600000000000) { // 1 gigawatthour - return Number::new(value/GigawattHour.weight(), GigawattHour) - } else if value >= d128!(3600000000) { // 1 megawatthour - return Number::new(value/MegawattHour.weight(), MegawattHour) - } else if value >= d128!(3600000) { // 1 kilowatthour - return Number::new(value/KilowattHour.weight(), KilowattHour) - } else if value >= d128!(3600) { // 1 watthour - return Number::new(value/WattHour.weight(), WattHour) - } else if value >= d128!(1) { // 1 joule - return Number::new(value, Joule) - } else { - return Number::new(value * get_inverted_millijoule_weight(), Millijoule) - } - } else if number.unit.category() == Power { - if value >= d128!(1000000000000000) { // 1 petawatt - return Number::new(value/Petawatt.weight(), Petawatt) - } else if value >= d128!(1000000000000) { // 1 terawatt - return Number::new(value/Terawatt.weight(), Terawatt) - } else if value >= d128!(1000000000) { // 1 gigawatt - return Number::new(value/Gigawatt.weight(), Gigawatt) - } else if value >= d128!(1000000) { // megawatt - return Number::new(value/Megawatt.weight(), Megawatt) - } else if value >= d128!(1000) { // 1 kilowatt - return Number::new(value/Kilowatt.weight(), Kilowatt) - } else if value >= d128!(1) { // 1 watt - return Number::new(value, Watt) - } else { - return Number::new(value * get_inverted_milliwatt_weight(), Milliwatt) - } - } else if number.unit.category() == ElectricCurrent { - if value >= d128!(1000) { // 1 kiloampere - return Number::new(value/Kiloampere.weight(), Kiloampere) - } else if value >= d128!(1) { // 1 ampere - return Number::new(value, Ampere) - } else { - return Number::new(value * get_inverted_milliampere_weight(), Milliampere) - } - } else if number.unit.category() == Resistance { - if value >= d128!(1000) { // 1 kiloohm - return Number::new(value/Kiloohm.weight(), Kiloohm) - } else if value >= d128!(1) { // 1 ohm - return Number::new(value, Ohm) - } else { - return Number::new(value * get_inverted_milliohm_weight(), Milliohm) - } - } else if number.unit.category() == Voltage { - if value >= d128!(1000) { // 1 kilovolt - return Number::new(value/Kilovolt.weight(), Kilovolt) - } else if value >= d128!(1) { // 1 volt - return Number::new(value, Volt) - } else { - return Number::new(value * get_inverted_millivolt_weight(), Millivolt) - } - } - number + let value = number.value * number.unit.weight(); + if number.unit.category() == Length { + if value >= d128!(1000000000000000000) { // ≈ 0.1 light years + return Number::new(value/Kilometer.weight(), Kilometer) + } else if value >= d128!(1000000) { // 1 km + return Number::new(value/Kilometer.weight(), Kilometer) + } else if value >= d128!(1000) { // 1 m + return Number::new(value/Meter.weight(), Meter) + } else if value >= d128!(10) { // 1 cm + return Number::new(value/Centimeter.weight(), Centimeter) + } else { + return Number::new(value, Millimeter) + } + } else if number.unit.category() == Time { + if value >= d128!(31556952000000000) { + return Number::new(value/Year.weight(), Year); + } else if value >= d128!(86400000000000) { + return Number::new(value/Day.weight(), Day); + } else if value >= d128!(3600000000000) { + return Number::new(value/Hour.weight(), Hour); + } else if value >= d128!(60000000000) { + return Number::new(value/Minute.weight(), Minute); + } else if value >= d128!(1000000000) { + return Number::new(value/Second.weight(), Second); + } else if value >= d128!(1000000) { + return Number::new(value/Millisecond.weight(), Millisecond); + } else if value >= d128!(1000) { + return Number::new(value/Microsecond.weight(), Microsecond); + } else { + return Number::new(value, Nanosecond); + } + } else if number.unit.category() == Area { + if value >= d128!(1000000000000) { // 1 km2 + return Number::new(value/SquareKilometer.weight(), SquareKilometer) + } else if value >= d128!(10000000000) { // 1 hectare + return Number::new(value/Hectare.weight(), Hectare) + } else if value >= d128!(1000000) { // 1 m2 + return Number::new(value/SquareMeter.weight(), SquareMeter) + } else if value >= d128!(100) { // 1 cm2 + return Number::new(value/SquareCentimeter.weight(), SquareCentimeter) + } else { + return Number::new(value, SquareMillimeter) + } + } else if number.unit.category() == Volume { + if value >= d128!(1000000000000000000) { // 1 km3 + return Number::new(value/CubicKilometer.weight(), CubicKilometer) + } else if value >= d128!(1000000000) { // 1 m3 + return Number::new(value/CubicMeter.weight(), CubicMeter) + } else if value >= d128!(1000000) { // 1 l + return Number::new(value/Liter.weight(), Liter) + } else if value >= d128!(1000) { // 1 ml + return Number::new(value/Milliliter.weight(), Milliliter) + } else { + return Number::new(value, CubicMillimeter) + } + } else if number.unit.category() == Energy { + if value >= d128!(3600000000000000000) { // 1 petawatthour + return Number::new(value/PetawattHour.weight(), PetawattHour) + } else if value >= d128!(3600000000000000) { // 1 terawatthour + return Number::new(value/TerawattHour.weight(), TerawattHour) + } else if value >= d128!(3600000000000) { // 1 gigawatthour + return Number::new(value/GigawattHour.weight(), GigawattHour) + } else if value >= d128!(3600000000) { // 1 megawatthour + return Number::new(value/MegawattHour.weight(), MegawattHour) + } else if value >= d128!(3600000) { // 1 kilowatthour + return Number::new(value/KilowattHour.weight(), KilowattHour) + } else if value >= d128!(3600) { // 1 watthour + return Number::new(value/WattHour.weight(), WattHour) + } else if value >= d128!(1) { // 1 joule + return Number::new(value, Joule) + } else { + return Number::new(value * get_inverted_millijoule_weight(), Millijoule) + } + } else if number.unit.category() == Power { + if value >= d128!(1000000000000000) { // 1 petawatt + return Number::new(value/Petawatt.weight(), Petawatt) + } else if value >= d128!(1000000000000) { // 1 terawatt + return Number::new(value/Terawatt.weight(), Terawatt) + } else if value >= d128!(1000000000) { // 1 gigawatt + return Number::new(value/Gigawatt.weight(), Gigawatt) + } else if value >= d128!(1000000) { // megawatt + return Number::new(value/Megawatt.weight(), Megawatt) + } else if value >= d128!(1000) { // 1 kilowatt + return Number::new(value/Kilowatt.weight(), Kilowatt) + } else if value >= d128!(1) { // 1 watt + return Number::new(value, Watt) + } else { + return Number::new(value * get_inverted_milliwatt_weight(), Milliwatt) + } + } else if number.unit.category() == ElectricCurrent { + if value >= d128!(1000) { // 1 kiloampere + return Number::new(value/Kiloampere.weight(), Kiloampere) + } else if value >= d128!(1) { // 1 ampere + return Number::new(value, Ampere) + } else { + return Number::new(value * get_inverted_milliampere_weight(), Milliampere) + } + } else if number.unit.category() == Resistance { + if value >= d128!(1000) { // 1 kiloohm + return Number::new(value/Kiloohm.weight(), Kiloohm) + } else if value >= d128!(1) { // 1 ohm + return Number::new(value, Ohm) + } else { + return Number::new(value * get_inverted_milliohm_weight(), Milliohm) + } + } else if number.unit.category() == Voltage { + if value >= d128!(1000) { // 1 kilovolt + return Number::new(value/Kilovolt.weight(), Kilovolt) + } else if value >= d128!(1) { // 1 volt + return Number::new(value, Volt) + } else { + return Number::new(value * get_inverted_millivolt_weight(), Millivolt) + } + } + number } /// Convert a [`Number`] to an ideal [`Joule`] unit, if the number is a unit of [`Energy`]. pub fn to_ideal_joule_unit(number: Number) -> Number { - let value = number.value * number.unit.weight(); - if number.unit.category() == Energy { - if value >= d128!(1000000000000) { // 1 terajoule - return Number::new(value/Terajoule.weight(), Terajoule) - } else if value >= d128!(1000000000) { // 1 gigajoule - return Number::new(value/Gigajoule.weight(), Gigajoule) - } else if value >= d128!(1000000) { // 1 megajoule - return Number::new(value/Megajoule.weight(), Megajoule) - } else if value >= d128!(1000) { // 1 kilojoule - return Number::new(value/Kilojoule.weight(), Kilojoule) - } else if value >= d128!(1) { // 1 joule - return Number::new(value/Joule.weight(), Joule) - } else { - return Number::new(value * get_inverted_millijoule_weight(), Millijoule) - } - } - number + let value = number.value * number.unit.weight(); + if number.unit.category() == Energy { + if value >= d128!(1000000000000) { // 1 terajoule + return Number::new(value/Terajoule.weight(), Terajoule) + } else if value >= d128!(1000000000) { // 1 gigajoule + return Number::new(value/Gigajoule.weight(), Gigajoule) + } else if value >= d128!(1000000) { // 1 megajoule + return Number::new(value/Megajoule.weight(), Megajoule) + } else if value >= d128!(1000) { // 1 kilojoule + return Number::new(value/Kilojoule.weight(), Kilojoule) + } else if value >= d128!(1) { // 1 joule + return Number::new(value/Joule.weight(), Joule) + } else { + return Number::new(value * get_inverted_millijoule_weight(), Millijoule) + } + } + number } /// Multiply two [`Number`]s @@ -550,108 +550,108 @@ pub fn to_ideal_joule_unit(number: Number) -> Number { /// - If you multiply [`ElectricCurrent`] with [`Resistance`], the result has a unit of [`Voltage`] /// - If you multiply [`Power`] with [`Time`], the result has a unit of [`Energy`] pub fn multiply(left: Number, right: Number) -> Result { - actual_multiply(left, right, false) + actual_multiply(left, right, false) } fn actual_multiply(left: Number, right: Number, swapped: bool) -> Result { - let lcat = left.unit.category(); - let rcat = right.unit.category(); - if left.unit == NoUnit && right.unit == NoUnit { - // 3 * 2 - Ok(Number::new(left.value * right.value, left.unit)) - } else if left.unit.category() == Temperature || right.unit.category() == Temperature { - // if temperature - Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit)) - } else if left.unit == NoUnit && right.unit != NoUnit { - // 3 * 2 anyunit - Ok(Number::new(left.value * right.value, right.unit)) - } else if lcat == Length && rcat == Length { - // length * length - let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); - Ok(to_ideal_unit(Number::new(result, SquareMillimeter))) - } else if lcat == Length && rcat == Area { - // length * area - let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); - Ok(to_ideal_unit(Number::new(result, CubicMillimeter))) - } else if lcat == Speed && rcat == Time { - // 1 km/h * 1h - let kph_value = left.value * left.unit.weight(); - let hours = convert(right, Hour)?; - let result = kph_value * hours.value; - let final_unit = match left.unit { - KilometersPerHour => Kilometer, - MetersPerSecond => Meter, - MilesPerHour => Mile, - FeetPerSecond => Foot, - Knot => NauticalMile, - _ => Meter, - }; - let kilometers = Number::new(result, Kilometer); - Ok(convert(kilometers, final_unit)?) - } else if lcat == DataTransferRate && rcat == Time { - // 8 megabytes per second * 1 minute - let data_rate_value = left.value * left.unit.weight(); - let seconds = convert(right, Second)?; - let result = data_rate_value * seconds.value; - let final_unit = match left.unit { - BitsPerSecond => Bit, - KilobitsPerSecond => Kilobit, - MegabitsPerSecond => Megabit, - GigabitsPerSecond => Gigabit, - TerabitsPerSecond => Terabit, - PetabitsPerSecond => Petabit, - ExabitsPerSecond => Exabit, - ZettabitsPerSecond => Zettabit, - YottabitsPerSecond => Yottabit, - KibibitsPerSecond => Kibibit, - MebibitsPerSecond => Mebibit, - GibibitsPerSecond => Gibibit, - TebibitsPerSecond => Tebibit, - PebibitsPerSecond => Pebibit, - ExbibitsPerSecond => Exbibit, - ZebibitsPerSecond => Zebibit, - YobibitsPerSecond => Yobibit, - BytesPerSecond => Byte, - KilobytesPerSecond => Kilobyte, - MegabytesPerSecond => Megabyte, - GigabytesPerSecond => Gigabyte, - TerabytesPerSecond => Terabyte, - PetabytesPerSecond => Petabyte, - ExabytesPerSecond => Exabyte, - ZettabytesPerSecond => Zettabyte, - YottabytesPerSecond => Yottabyte, - KibibytesPerSecond => Kibibyte, - MebibytesPerSecond => Mebibyte, - GibibytesPerSecond => Gibibyte, - TebibytesPerSecond => Tebibyte, - PebibytesPerSecond => Pebibyte, - ExbibytesPerSecond => Exbibyte, - ZebibytesPerSecond => Zebibyte, - YobibytesPerSecond => Yobibyte, - _ => Bit, - }; - let data_storage = Number::new(result, Bit); - Ok(convert(data_storage, final_unit)?) - } else if lcat == Voltage && rcat == ElectricCurrent { - // 1 volt * 1 ampere = 1 watt - let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); - Ok(to_ideal_unit(Number::new(result, Watt))) - } else if lcat == ElectricCurrent && rcat == Resistance { - // 1 amp * 1 ohm = 1 volt - let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); - Ok(to_ideal_unit(Number::new(result, Watt))) - } else if lcat == Power && rcat == Time { - // 1 watt * 1 second = 1 joule - let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight() / Unit::Second.weight()); - match right.unit { - Second => Ok(to_ideal_joule_unit(Number::new(result, Joule))), - _ => Ok(to_ideal_unit(Number::new(result, Joule))), - } - } else if swapped { - Err(format!("Cannot multiply {:?} and {:?}", right.unit, left.unit)) - } else { - actual_multiply(right, left, true) - } + let lcat = left.unit.category(); + let rcat = right.unit.category(); + if left.unit == NoUnit && right.unit == NoUnit { + // 3 * 2 + Ok(Number::new(left.value * right.value, left.unit)) + } else if left.unit.category() == Temperature || right.unit.category() == Temperature { + // if temperature + Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit)) + } else if left.unit == NoUnit && right.unit != NoUnit { + // 3 * 2 anyunit + Ok(Number::new(left.value * right.value, right.unit)) + } else if lcat == Length && rcat == Length { + // length * length + let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); + Ok(to_ideal_unit(Number::new(result, SquareMillimeter))) + } else if lcat == Length && rcat == Area { + // length * area + let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); + Ok(to_ideal_unit(Number::new(result, CubicMillimeter))) + } else if lcat == Speed && rcat == Time { + // 1 km/h * 1h + let kph_value = left.value * left.unit.weight(); + let hours = convert(right, Hour)?; + let result = kph_value * hours.value; + let final_unit = match left.unit { + KilometersPerHour => Kilometer, + MetersPerSecond => Meter, + MilesPerHour => Mile, + FeetPerSecond => Foot, + Knot => NauticalMile, + _ => Meter, + }; + let kilometers = Number::new(result, Kilometer); + Ok(convert(kilometers, final_unit)?) + } else if lcat == DataTransferRate && rcat == Time { + // 8 megabytes per second * 1 minute + let data_rate_value = left.value * left.unit.weight(); + let seconds = convert(right, Second)?; + let result = data_rate_value * seconds.value; + let final_unit = match left.unit { + BitsPerSecond => Bit, + KilobitsPerSecond => Kilobit, + MegabitsPerSecond => Megabit, + GigabitsPerSecond => Gigabit, + TerabitsPerSecond => Terabit, + PetabitsPerSecond => Petabit, + ExabitsPerSecond => Exabit, + ZettabitsPerSecond => Zettabit, + YottabitsPerSecond => Yottabit, + KibibitsPerSecond => Kibibit, + MebibitsPerSecond => Mebibit, + GibibitsPerSecond => Gibibit, + TebibitsPerSecond => Tebibit, + PebibitsPerSecond => Pebibit, + ExbibitsPerSecond => Exbibit, + ZebibitsPerSecond => Zebibit, + YobibitsPerSecond => Yobibit, + BytesPerSecond => Byte, + KilobytesPerSecond => Kilobyte, + MegabytesPerSecond => Megabyte, + GigabytesPerSecond => Gigabyte, + TerabytesPerSecond => Terabyte, + PetabytesPerSecond => Petabyte, + ExabytesPerSecond => Exabyte, + ZettabytesPerSecond => Zettabyte, + YottabytesPerSecond => Yottabyte, + KibibytesPerSecond => Kibibyte, + MebibytesPerSecond => Mebibyte, + GibibytesPerSecond => Gibibyte, + TebibytesPerSecond => Tebibyte, + PebibytesPerSecond => Pebibyte, + ExbibytesPerSecond => Exbibyte, + ZebibytesPerSecond => Zebibyte, + YobibytesPerSecond => Yobibyte, + _ => Bit, + }; + let data_storage = Number::new(result, Bit); + Ok(convert(data_storage, final_unit)?) + } else if lcat == Voltage && rcat == ElectricCurrent { + // 1 volt * 1 ampere = 1 watt + let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); + Ok(to_ideal_unit(Number::new(result, Watt))) + } else if lcat == ElectricCurrent && rcat == Resistance { + // 1 amp * 1 ohm = 1 volt + let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); + Ok(to_ideal_unit(Number::new(result, Watt))) + } else if lcat == Power && rcat == Time { + // 1 watt * 1 second = 1 joule + let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight() / Unit::Second.weight()); + match right.unit { + Second => Ok(to_ideal_joule_unit(Number::new(result, Joule))), + _ => Ok(to_ideal_unit(Number::new(result, Joule))), + } + } else if swapped { + Err(format!("Cannot multiply {:?} and {:?}", right.unit, left.unit)) + } else { + actual_multiply(right, left, true) + } } /// Divide a [`Number`] by another [`Number`] @@ -667,78 +667,78 @@ fn actual_multiply(left: Number, right: Number, swapped: bool) -> Result Result { - let lcat = left.unit.category(); - let rcat = right.unit.category(); - if left.unit == NoUnit && right.unit == NoUnit { - // 3 / 2 - Ok(Number::new(left.value / right.value, left.unit)) - } else if lcat == Temperature || rcat == Temperature { - // if temperature - Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit)) - } else if left.unit != NoUnit && right.unit == NoUnit { - // 1 km / 2 - Ok(Number::new(left.value / right.value, left.unit)) - } else if lcat == rcat { - // 4 km / 2 km - let (left, right) = convert_to_lowest(left, right)?; - Ok(Number::new(left.value / right.value, NoUnit)) - } else if (lcat == Area && rcat == Length) || (lcat == Volume && rcat == Area) { - // 1 km2 / 1 km, 1 km3 / 1 km2 - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); - Ok(to_ideal_unit(Number::new(result, Millimeter))) - } else if lcat == Volume && rcat == Length { - // 1 km3 / 1 km - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); - Ok(to_ideal_unit(Number::new(result, SquareMillimeter))) - } else if lcat == Length && rcat == Time { - // 1 km / 2s - let final_unit = match (left.unit, right.unit) { - (Kilometer, Hour) => KilometersPerHour, - (Meter, Second) => MetersPerSecond, - (Mile, Hour) => MilesPerHour, - (Foot, Second) => FeetPerSecond, - (NauticalMile, Hour) => Knot, - _ => KilometersPerHour, - }; - let kilometers = convert(left, Kilometer)?; - let hours = convert(right, Hour)?; - let kph = Number::new(kilometers.value / hours.value, KilometersPerHour); - Ok(convert(kph, final_unit)?) - } else if lcat == Length && rcat == Speed { - // 12 km / 100 kph - let kilometers = convert(left, Kilometer)?; - let kilometers_per_hour = convert(right, KilometersPerHour)?; - let hour = Number::new(kilometers.value / kilometers_per_hour.value, Hour); - Ok(to_ideal_unit(hour)) - } else if lcat == DigitalStorage && rcat == DataTransferRate { - // 1 kilobit / 1 bit per second - let bits = convert(left, Bit)?; - let bits_per_second = convert(right, BitsPerSecond)?; - let seconds = Number::new(bits.value / bits_per_second.value, Second); - Ok(to_ideal_unit(seconds)) - } else if lcat == Power && rcat == ElectricCurrent { - // 1 watt / 1 ampere = 1 volt - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); - Ok(to_ideal_unit(Number::new(result, Volt))) - } else if lcat == Voltage && rcat == ElectricCurrent { - // 1 volt / 1 ampere = 1 ohm - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); - Ok(to_ideal_unit(Number::new(result, Ohm))) - } else if lcat == Voltage && rcat == Resistance { - // 1 volt / 1 ohm = 1 amp - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); - Ok(to_ideal_unit(Number::new(result, Ampere))) - } else if lcat == Power && rcat == Voltage { - // 1 watt / 1 volt = 1 amp - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); - Ok(to_ideal_unit(Number::new(result, Ampere))) - } else if lcat == Energy && rcat == Time { - // 1 joule / 1 second = 1 watt - let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight() / Unit::Second.weight()); - Ok(to_ideal_unit(Number::new(result, Watt))) - } else { - Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit)) - } + let lcat = left.unit.category(); + let rcat = right.unit.category(); + if left.unit == NoUnit && right.unit == NoUnit { + // 3 / 2 + Ok(Number::new(left.value / right.value, left.unit)) + } else if lcat == Temperature || rcat == Temperature { + // if temperature + Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit)) + } else if left.unit != NoUnit && right.unit == NoUnit { + // 1 km / 2 + Ok(Number::new(left.value / right.value, left.unit)) + } else if lcat == rcat { + // 4 km / 2 km + let (left, right) = convert_to_lowest(left, right)?; + Ok(Number::new(left.value / right.value, NoUnit)) + } else if (lcat == Area && rcat == Length) || (lcat == Volume && rcat == Area) { + // 1 km2 / 1 km, 1 km3 / 1 km2 + let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); + Ok(to_ideal_unit(Number::new(result, Millimeter))) + } else if lcat == Volume && rcat == Length { + // 1 km3 / 1 km + let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); + Ok(to_ideal_unit(Number::new(result, SquareMillimeter))) + } else if lcat == Length && rcat == Time { + // 1 km / 2s + let final_unit = match (left.unit, right.unit) { + (Kilometer, Hour) => KilometersPerHour, + (Meter, Second) => MetersPerSecond, + (Mile, Hour) => MilesPerHour, + (Foot, Second) => FeetPerSecond, + (NauticalMile, Hour) => Knot, + _ => KilometersPerHour, + }; + let kilometers = convert(left, Kilometer)?; + let hours = convert(right, Hour)?; + let kph = Number::new(kilometers.value / hours.value, KilometersPerHour); + Ok(convert(kph, final_unit)?) + } else if lcat == Length && rcat == Speed { + // 12 km / 100 kph + let kilometers = convert(left, Kilometer)?; + let kilometers_per_hour = convert(right, KilometersPerHour)?; + let hour = Number::new(kilometers.value / kilometers_per_hour.value, Hour); + Ok(to_ideal_unit(hour)) + } else if lcat == DigitalStorage && rcat == DataTransferRate { + // 1 kilobit / 1 bit per second + let bits = convert(left, Bit)?; + let bits_per_second = convert(right, BitsPerSecond)?; + let seconds = Number::new(bits.value / bits_per_second.value, Second); + Ok(to_ideal_unit(seconds)) + } else if lcat == Power && rcat == ElectricCurrent { + // 1 watt / 1 ampere = 1 volt + let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); + Ok(to_ideal_unit(Number::new(result, Volt))) + } else if lcat == Voltage && rcat == ElectricCurrent { + // 1 volt / 1 ampere = 1 ohm + let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); + Ok(to_ideal_unit(Number::new(result, Ohm))) + } else if lcat == Voltage && rcat == Resistance { + // 1 volt / 1 ohm = 1 amp + let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); + Ok(to_ideal_unit(Number::new(result, Ampere))) + } else if lcat == Power && rcat == Voltage { + // 1 watt / 1 volt = 1 amp + let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight()); + Ok(to_ideal_unit(Number::new(result, Ampere))) + } else if lcat == Energy && rcat == Time { + // 1 joule / 1 second = 1 watt + let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight() / Unit::Second.weight()); + Ok(to_ideal_unit(Number::new(result, Watt))) + } else { + Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit)) + } } /// Modulo a [`Number`] by another [`Number`]. /// @@ -746,16 +746,16 @@ pub fn divide(left: Number, right: Number) -> Result { /// /// Temperatures don't work. pub fn modulo(left: Number, right: Number) -> Result { - if left.unit.category() == Temperature || right.unit.category() == Temperature { - // if temperature - Err(format!("Cannot modulo {:?} by {:?}", left.unit, right.unit)) - } else if left.unit.category() == right.unit.category() { - // 5 km % 3 m - let (left, right) = convert_to_lowest(left, right)?; - Ok(Number::new(left.value % right.value, left.unit)) - } else { - Err(format!("Cannot modulo {:?} by {:?}", left.unit, right.unit)) - } + if left.unit.category() == Temperature || right.unit.category() == Temperature { + // if temperature + Err(format!("Cannot modulo {:?} by {:?}", left.unit, right.unit)) + } else if left.unit.category() == right.unit.category() { + // 5 km % 3 m + let (left, right) = convert_to_lowest(left, right)?; + Ok(Number::new(left.value % right.value, left.unit)) + } else { + Err(format!("Cannot modulo {:?} by {:?}", left.unit, right.unit)) + } } /// Returns a [`Number`] to the power of another [`Number`] @@ -765,261 +765,261 @@ pub fn modulo(left: Number, right: Number) -> Result { /// - If you take [`Length`] to the power of [`Area`], the result has a unit of [`Volume`] /// - etc. pub fn pow(left: Number, right: Number) -> Result { - let lcat = left.unit.category(); - let rcat = left.unit.category(); - if left.unit == NoUnit && right.unit == NoUnit { - // 3 ^ 2 - Ok(Number::new(left.value.pow(right.value), left.unit)) - } else if right.value == d128!(1) && right.unit == NoUnit { - Ok(left) - } else if lcat == Length && right.unit == NoUnit && right.value == d128!(2) { - // x km ^ 2 - let result = (left.value * left.unit.weight()).pow(right.value); - Ok(to_ideal_unit(Number::new(result, SquareMillimeter))) - } else if lcat == Length && right.unit == NoUnit && right.value == d128!(3) { - // x km ^ 3 - let result = (left.value * left.unit.weight()).pow(right.value); - Ok(to_ideal_unit(Number::new(result, CubicMillimeter))) - } else if lcat == Length && rcat == Length && right.value == d128!(1) { - // x km ^ 1 km - Ok(multiply(left, right)?) - } else if lcat == Length && rcat == Length && right.value == d128!(2) { - // x km ^ 2 km - let pow2 = multiply(left, Number::new(d128!(1), right.unit))?; - let pow3 = multiply(pow2, Number::new(d128!(1), right.unit))?; - Ok(pow3) - } else if lcat == Length && rcat == Area && right.value == d128!(1) { - // x km ^ km2 - Ok(multiply(left, Number::new(d128!(1), right.unit))?) - } else { - Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit)) - } + let lcat = left.unit.category(); + let rcat = left.unit.category(); + if left.unit == NoUnit && right.unit == NoUnit { + // 3 ^ 2 + Ok(Number::new(left.value.pow(right.value), left.unit)) + } else if right.value == d128!(1) && right.unit == NoUnit { + Ok(left) + } else if lcat == Length && right.unit == NoUnit && right.value == d128!(2) { + // x km ^ 2 + let result = (left.value * left.unit.weight()).pow(right.value); + Ok(to_ideal_unit(Number::new(result, SquareMillimeter))) + } else if lcat == Length && right.unit == NoUnit && right.value == d128!(3) { + // x km ^ 3 + let result = (left.value * left.unit.weight()).pow(right.value); + Ok(to_ideal_unit(Number::new(result, CubicMillimeter))) + } else if lcat == Length && rcat == Length && right.value == d128!(1) { + // x km ^ 1 km + Ok(multiply(left, right)?) + } else if lcat == Length && rcat == Length && right.value == d128!(2) { + // x km ^ 2 km + let pow2 = multiply(left, Number::new(d128!(1), right.unit))?; + let pow3 = multiply(pow2, Number::new(d128!(1), right.unit))?; + Ok(pow3) + } else if lcat == Length && rcat == Area && right.value == d128!(1) { + // x km ^ km2 + Ok(multiply(left, Number::new(d128!(1), right.unit))?) + } else { + Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit)) + } } #[cfg(test)] mod tests { - use super::*; + use super::*; - macro_rules! assert_float_eq { - ( $actual:expr, $expected:literal ) => { - assert!(($actual - $expected).abs() < f64::EPSILON); - } - } + macro_rules! assert_float_eq { + ( $actual:expr, $expected:literal ) => { + assert!(($actual - $expected).abs() < f64::EPSILON); + } + } - #[test] - fn test_convert() { - pub fn convert_test(value: f64, unit: Unit, to_unit: Unit) -> f64 { - use std::str::FromStr; + #[test] + fn test_convert() { + pub fn convert_test(value: f64, unit: Unit, to_unit: Unit) -> f64 { + use std::str::FromStr; - let value_string = &value.to_string(); - let value_d128 = d128::from_str(value_string).unwrap(); - let number = Number::new(value_d128, unit); + let value_string = &value.to_string(); + let value_d128 = d128::from_str(value_string).unwrap(); + let number = Number::new(value_d128, unit); - let result = convert(number, to_unit); - let string_result = &result.unwrap().value.to_string(); - let float_result = f64::from_str(string_result).unwrap(); + let result = convert(number, to_unit); + let string_result = &result.unwrap().value.to_string(); + let float_result = f64::from_str(string_result).unwrap(); - return float_result; - } + return float_result; + } - assert_float_eq!(convert_test(1000.0, Nanosecond, Microsecond), 1.0); - assert_float_eq!(convert_test(1000.0, Nanosecond, Microsecond), 1.0); - assert_float_eq!(convert_test(1000.0, Microsecond, Millisecond), 1.0); - assert_float_eq!(convert_test(1000.0, Millisecond, Second), 1.0); - assert_float_eq!(convert_test(60.0, Second, Minute), 1.0); - assert_float_eq!(convert_test(60.0, Minute, Hour), 1.0); - assert_float_eq!(convert_test(24.0, Hour, Day), 1.0); - assert_float_eq!(convert_test(7.0, Day, Week), 1.0); - assert_float_eq!(convert_test(30.436875, Day, Month), 1.0); - assert_float_eq!(convert_test(3.0, Month, Quarter), 1.0); - assert_float_eq!(convert_test(4.0, Quarter, Year), 1.0); - assert_float_eq!(convert_test(10.0, Year, Decade), 1.0); - assert_float_eq!(convert_test(10.0, Decade, Century), 1.0); - assert_float_eq!(convert_test(10.0, Century, Millenium), 1.0); + assert_float_eq!(convert_test(1000.0, Nanosecond, Microsecond), 1.0); + assert_float_eq!(convert_test(1000.0, Nanosecond, Microsecond), 1.0); + assert_float_eq!(convert_test(1000.0, Microsecond, Millisecond), 1.0); + assert_float_eq!(convert_test(1000.0, Millisecond, Second), 1.0); + assert_float_eq!(convert_test(60.0, Second, Minute), 1.0); + assert_float_eq!(convert_test(60.0, Minute, Hour), 1.0); + assert_float_eq!(convert_test(24.0, Hour, Day), 1.0); + assert_float_eq!(convert_test(7.0, Day, Week), 1.0); + assert_float_eq!(convert_test(30.436875, Day, Month), 1.0); + assert_float_eq!(convert_test(3.0, Month, Quarter), 1.0); + assert_float_eq!(convert_test(4.0, Quarter, Year), 1.0); + assert_float_eq!(convert_test(10.0, Year, Decade), 1.0); + assert_float_eq!(convert_test(10.0, Decade, Century), 1.0); + assert_float_eq!(convert_test(10.0, Century, Millenium), 1.0); - assert_float_eq!(convert_test(10.0, Millimeter, Centimeter), 1.0); - assert_float_eq!(convert_test(10.0, Centimeter, Decimeter), 1.0); - assert_float_eq!(convert_test(10.0, Decimeter, Meter), 1.0); - assert_float_eq!(convert_test(1000.0, Meter, Kilometer), 1.0); - assert_float_eq!(convert_test(2.54, Centimeter, Inch), 1.0); - assert_float_eq!(convert_test(12.0, Inch, Foot), 1.0); - assert_float_eq!(convert_test(3.0, Foot, Yard), 1.0); - assert_float_eq!(convert_test(1760.0, Yard, Mile), 1.0); - assert_float_eq!(convert_test(1852.0, Meter, NauticalMile), 1.0); - assert_float_eq!(convert_test(9460730472580800.0, Meter, LightYear), 1.0); - assert_float_eq!(convert_test(299792458.0, Meter, LightSecond), 1.0); + assert_float_eq!(convert_test(10.0, Millimeter, Centimeter), 1.0); + assert_float_eq!(convert_test(10.0, Centimeter, Decimeter), 1.0); + assert_float_eq!(convert_test(10.0, Decimeter, Meter), 1.0); + assert_float_eq!(convert_test(1000.0, Meter, Kilometer), 1.0); + assert_float_eq!(convert_test(2.54, Centimeter, Inch), 1.0); + assert_float_eq!(convert_test(12.0, Inch, Foot), 1.0); + assert_float_eq!(convert_test(3.0, Foot, Yard), 1.0); + assert_float_eq!(convert_test(1760.0, Yard, Mile), 1.0); + assert_float_eq!(convert_test(1852.0, Meter, NauticalMile), 1.0); + assert_float_eq!(convert_test(9460730472580800.0, Meter, LightYear), 1.0); + assert_float_eq!(convert_test(299792458.0, Meter, LightSecond), 1.0); - assert_float_eq!(convert_test(100.0, SquareMillimeter, SquareCentimeter), 1.0); - assert_float_eq!(convert_test(100.0, SquareCentimeter, SquareDecimeter), 1.0); - assert_float_eq!(convert_test(100.0, SquareDecimeter, SquareMeter), 1.0); - assert_float_eq!(convert_test(1000000.0, SquareMeter, SquareKilometer), 1.0); - assert_float_eq!(convert_test(645.16, SquareMillimeter, SquareInch), 1.0); - assert_float_eq!(convert_test(144.0, SquareInch, SquareFoot), 1.0); - assert_float_eq!(convert_test(9.0, SquareFoot, SquareYard), 1.0); - assert_float_eq!(convert_test(3097600.0, SquareYard, SquareMile), 1.0); - assert_float_eq!(convert_test(100.0, SquareMeter, Are), 1.0); - assert_float_eq!(convert_test(10.0, Are, Decare), 1.0); - assert_float_eq!(convert_test(10.0, Decare, Hectare), 1.0); - assert_float_eq!(convert_test(640.0, Acre, SquareMile), 1.0); + assert_float_eq!(convert_test(100.0, SquareMillimeter, SquareCentimeter), 1.0); + assert_float_eq!(convert_test(100.0, SquareCentimeter, SquareDecimeter), 1.0); + assert_float_eq!(convert_test(100.0, SquareDecimeter, SquareMeter), 1.0); + assert_float_eq!(convert_test(1000000.0, SquareMeter, SquareKilometer), 1.0); + assert_float_eq!(convert_test(645.16, SquareMillimeter, SquareInch), 1.0); + assert_float_eq!(convert_test(144.0, SquareInch, SquareFoot), 1.0); + assert_float_eq!(convert_test(9.0, SquareFoot, SquareYard), 1.0); + assert_float_eq!(convert_test(3097600.0, SquareYard, SquareMile), 1.0); + assert_float_eq!(convert_test(100.0, SquareMeter, Are), 1.0); + assert_float_eq!(convert_test(10.0, Are, Decare), 1.0); + assert_float_eq!(convert_test(10.0, Decare, Hectare), 1.0); + assert_float_eq!(convert_test(640.0, Acre, SquareMile), 1.0); - assert_float_eq!(convert_test(1000.0, CubicMillimeter, CubicCentimeter), 1.0); - assert_float_eq!(convert_test(1000.0, CubicCentimeter, CubicDecimeter), 1.0); - assert_float_eq!(convert_test(1000.0, CubicDecimeter, CubicMeter), 1.0); - assert_float_eq!(convert_test(1000000000.0, CubicMeter, CubicKilometer), 1.0); - assert_float_eq!(convert_test(1728.0, CubicInch, CubicFoot), 1.0); - assert_float_eq!(convert_test(27.0, CubicFoot, CubicYard), 1.0); - assert_float_eq!(convert_test(5451776000.0, CubicYard, CubicMile), 1.0); - assert_float_eq!(convert_test(1.0, Milliliter, CubicCentimeter), 1.0); - assert_float_eq!(convert_test(10.0, Milliliter, Centiliter), 1.0); - assert_float_eq!(convert_test(10.0, Centiliter, Deciliter), 1.0); - assert_float_eq!(convert_test(10.0, Deciliter, Liter), 1.0); - assert_float_eq!(convert_test(4.92892159375, Milliliter, Teaspoon), 1.0); - assert_float_eq!(convert_test(3.0, Teaspoon, Tablespoon), 1.0); - assert_float_eq!(convert_test(2.0, Tablespoon, FluidOunce), 1.0); - assert_float_eq!(convert_test(8.0, FluidOunce, Cup), 1.0); - assert_float_eq!(convert_test(2.0, Cup, Pint), 1.0); - assert_float_eq!(convert_test(2.0, Pint, Quart), 1.0); - assert_float_eq!(convert_test(4.0, Quart, Gallon), 1.0); - assert_float_eq!(convert_test(42.0, Gallon, OilBarrel), 1.0); + assert_float_eq!(convert_test(1000.0, CubicMillimeter, CubicCentimeter), 1.0); + assert_float_eq!(convert_test(1000.0, CubicCentimeter, CubicDecimeter), 1.0); + assert_float_eq!(convert_test(1000.0, CubicDecimeter, CubicMeter), 1.0); + assert_float_eq!(convert_test(1000000000.0, CubicMeter, CubicKilometer), 1.0); + assert_float_eq!(convert_test(1728.0, CubicInch, CubicFoot), 1.0); + assert_float_eq!(convert_test(27.0, CubicFoot, CubicYard), 1.0); + assert_float_eq!(convert_test(5451776000.0, CubicYard, CubicMile), 1.0); + assert_float_eq!(convert_test(1.0, Milliliter, CubicCentimeter), 1.0); + assert_float_eq!(convert_test(10.0, Milliliter, Centiliter), 1.0); + assert_float_eq!(convert_test(10.0, Centiliter, Deciliter), 1.0); + assert_float_eq!(convert_test(10.0, Deciliter, Liter), 1.0); + assert_float_eq!(convert_test(4.92892159375, Milliliter, Teaspoon), 1.0); + assert_float_eq!(convert_test(3.0, Teaspoon, Tablespoon), 1.0); + assert_float_eq!(convert_test(2.0, Tablespoon, FluidOunce), 1.0); + assert_float_eq!(convert_test(8.0, FluidOunce, Cup), 1.0); + assert_float_eq!(convert_test(2.0, Cup, Pint), 1.0); + assert_float_eq!(convert_test(2.0, Pint, Quart), 1.0); + assert_float_eq!(convert_test(4.0, Quart, Gallon), 1.0); + assert_float_eq!(convert_test(42.0, Gallon, OilBarrel), 1.0); - assert_float_eq!(convert_test(1000.0, Milligram, Gram), 1.0); - assert_float_eq!(convert_test(100.0, Gram, Hectogram), 1.0); - assert_float_eq!(convert_test(1000.0, Gram, Kilogram), 1.0); - assert_float_eq!(convert_test(1000.0, Kilogram, MetricTon), 1.0); - assert_float_eq!(convert_test(0.45359237, Kilogram, Pound), 1.0); - assert_float_eq!(convert_test(16.0, Ounce, Pound), 1.0); - assert_float_eq!(convert_test(14.0, Pound, Stone), 1.0); - assert_float_eq!(convert_test(2000.0, Pound, ShortTon), 1.0); - assert_float_eq!(convert_test(2240.0, Pound, LongTon), 1.0); + assert_float_eq!(convert_test(1000.0, Milligram, Gram), 1.0); + assert_float_eq!(convert_test(100.0, Gram, Hectogram), 1.0); + assert_float_eq!(convert_test(1000.0, Gram, Kilogram), 1.0); + assert_float_eq!(convert_test(1000.0, Kilogram, MetricTon), 1.0); + assert_float_eq!(convert_test(0.45359237, Kilogram, Pound), 1.0); + assert_float_eq!(convert_test(16.0, Ounce, Pound), 1.0); + assert_float_eq!(convert_test(14.0, Pound, Stone), 1.0); + assert_float_eq!(convert_test(2000.0, Pound, ShortTon), 1.0); + assert_float_eq!(convert_test(2240.0, Pound, LongTon), 1.0); - assert_float_eq!(convert_test(1000.0, Bit, Kilobit), 1.0); - assert_float_eq!(convert_test(1000.0, Kilobit, Megabit), 1.0); - assert_float_eq!(convert_test(1000.0, Megabit, Gigabit), 1.0); - assert_float_eq!(convert_test(1000.0, Gigabit, Terabit), 1.0); - assert_float_eq!(convert_test(1000.0, Terabit, Petabit), 1.0); - assert_float_eq!(convert_test(1000.0, Petabit, Exabit), 1.0); - assert_float_eq!(convert_test(1000.0, Exabit, Zettabit), 1.0); - assert_float_eq!(convert_test(1000.0, Zettabit, Yottabit), 1.0); - assert_float_eq!(convert_test(1024.0, Bit, Kibibit), 1.0); - assert_float_eq!(convert_test(1024.0, Kibibit, Mebibit), 1.0); - assert_float_eq!(convert_test(1024.0, Mebibit, Gibibit), 1.0); - assert_float_eq!(convert_test(1024.0, Gibibit, Tebibit), 1.0); - assert_float_eq!(convert_test(1024.0, Tebibit, Pebibit), 1.0); - assert_float_eq!(convert_test(1024.0, Pebibit, Exbibit), 1.0); - assert_float_eq!(convert_test(1024.0, Exbibit, Zebibit), 1.0); - assert_float_eq!(convert_test(1024.0, Zebibit, Yobibit), 1.0); - assert_float_eq!(convert_test(8.0, Bit, Byte), 1.0); - assert_float_eq!(convert_test(1000.0, Byte, Kilobyte), 1.0); - assert_float_eq!(convert_test(1000.0, Kilobyte, Megabyte), 1.0); - assert_float_eq!(convert_test(1000.0, Megabyte, Gigabyte), 1.0); - assert_float_eq!(convert_test(1000.0, Gigabyte, Terabyte), 1.0); - assert_float_eq!(convert_test(1000.0, Terabyte, Petabyte), 1.0); - assert_float_eq!(convert_test(1000.0, Petabyte, Exabyte), 1.0); - assert_float_eq!(convert_test(1000.0, Exabyte, Zettabyte), 1.0); - assert_float_eq!(convert_test(1000.0, Zettabyte, Yottabyte), 1.0); - assert_float_eq!(convert_test(1024.0, Kibibyte, Mebibyte), 1.0); - assert_float_eq!(convert_test(1024.0, Mebibyte, Gibibyte), 1.0); - assert_float_eq!(convert_test(1024.0, Gibibyte, Tebibyte), 1.0); - assert_float_eq!(convert_test(1024.0, Tebibyte, Pebibyte), 1.0); - assert_float_eq!(convert_test(1024.0, Pebibyte, Exbibyte), 1.0); - assert_float_eq!(convert_test(1024.0, Exbibyte, Zebibyte), 1.0); - assert_float_eq!(convert_test(1024.0, Zebibyte, Yobibyte), 1.0); + assert_float_eq!(convert_test(1000.0, Bit, Kilobit), 1.0); + assert_float_eq!(convert_test(1000.0, Kilobit, Megabit), 1.0); + assert_float_eq!(convert_test(1000.0, Megabit, Gigabit), 1.0); + assert_float_eq!(convert_test(1000.0, Gigabit, Terabit), 1.0); + assert_float_eq!(convert_test(1000.0, Terabit, Petabit), 1.0); + assert_float_eq!(convert_test(1000.0, Petabit, Exabit), 1.0); + assert_float_eq!(convert_test(1000.0, Exabit, Zettabit), 1.0); + assert_float_eq!(convert_test(1000.0, Zettabit, Yottabit), 1.0); + assert_float_eq!(convert_test(1024.0, Bit, Kibibit), 1.0); + assert_float_eq!(convert_test(1024.0, Kibibit, Mebibit), 1.0); + assert_float_eq!(convert_test(1024.0, Mebibit, Gibibit), 1.0); + assert_float_eq!(convert_test(1024.0, Gibibit, Tebibit), 1.0); + assert_float_eq!(convert_test(1024.0, Tebibit, Pebibit), 1.0); + assert_float_eq!(convert_test(1024.0, Pebibit, Exbibit), 1.0); + assert_float_eq!(convert_test(1024.0, Exbibit, Zebibit), 1.0); + assert_float_eq!(convert_test(1024.0, Zebibit, Yobibit), 1.0); + assert_float_eq!(convert_test(8.0, Bit, Byte), 1.0); + assert_float_eq!(convert_test(1000.0, Byte, Kilobyte), 1.0); + assert_float_eq!(convert_test(1000.0, Kilobyte, Megabyte), 1.0); + assert_float_eq!(convert_test(1000.0, Megabyte, Gigabyte), 1.0); + assert_float_eq!(convert_test(1000.0, Gigabyte, Terabyte), 1.0); + assert_float_eq!(convert_test(1000.0, Terabyte, Petabyte), 1.0); + assert_float_eq!(convert_test(1000.0, Petabyte, Exabyte), 1.0); + assert_float_eq!(convert_test(1000.0, Exabyte, Zettabyte), 1.0); + assert_float_eq!(convert_test(1000.0, Zettabyte, Yottabyte), 1.0); + assert_float_eq!(convert_test(1024.0, Kibibyte, Mebibyte), 1.0); + assert_float_eq!(convert_test(1024.0, Mebibyte, Gibibyte), 1.0); + assert_float_eq!(convert_test(1024.0, Gibibyte, Tebibyte), 1.0); + assert_float_eq!(convert_test(1024.0, Tebibyte, Pebibyte), 1.0); + assert_float_eq!(convert_test(1024.0, Pebibyte, Exbibyte), 1.0); + assert_float_eq!(convert_test(1024.0, Exbibyte, Zebibyte), 1.0); + assert_float_eq!(convert_test(1024.0, Zebibyte, Yobibyte), 1.0); - assert_float_eq!(convert_test(1000.0, BitsPerSecond, KilobitsPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, KilobitsPerSecond, MegabitsPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, MegabitsPerSecond, GigabitsPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, GigabitsPerSecond, TerabitsPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, TerabitsPerSecond, PetabitsPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, PetabitsPerSecond, ExabitsPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, ExabitsPerSecond, ZettabitsPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, ZettabitsPerSecond, YottabitsPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, BitsPerSecond, KibibitsPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, KibibitsPerSecond, MebibitsPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, MebibitsPerSecond, GibibitsPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, GibibitsPerSecond, TebibitsPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, TebibitsPerSecond, PebibitsPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, PebibitsPerSecond, ExbibitsPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, ExbibitsPerSecond, ZebibitsPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, ZebibitsPerSecond, YobibitsPerSecond), 1.0); - assert_float_eq!(convert_test(8.0, BitsPerSecond, BytesPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, BytesPerSecond, KilobytesPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, KilobytesPerSecond, MegabytesPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, MegabytesPerSecond, GigabytesPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, GigabytesPerSecond, TerabytesPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, TerabytesPerSecond, PetabytesPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, PetabytesPerSecond, ExabytesPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, ExabytesPerSecond, ZettabytesPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, ZettabytesPerSecond, YottabytesPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, KibibytesPerSecond, MebibytesPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, MebibytesPerSecond, GibibytesPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, GibibytesPerSecond, TebibytesPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, TebibytesPerSecond, PebibytesPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, PebibytesPerSecond, ExbibytesPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, ExbibytesPerSecond, ZebibytesPerSecond), 1.0); - assert_float_eq!(convert_test(1024.0, ZebibytesPerSecond, YobibytesPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, BitsPerSecond, KilobitsPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, KilobitsPerSecond, MegabitsPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, MegabitsPerSecond, GigabitsPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, GigabitsPerSecond, TerabitsPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, TerabitsPerSecond, PetabitsPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, PetabitsPerSecond, ExabitsPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, ExabitsPerSecond, ZettabitsPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, ZettabitsPerSecond, YottabitsPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, BitsPerSecond, KibibitsPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, KibibitsPerSecond, MebibitsPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, MebibitsPerSecond, GibibitsPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, GibibitsPerSecond, TebibitsPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, TebibitsPerSecond, PebibitsPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, PebibitsPerSecond, ExbibitsPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, ExbibitsPerSecond, ZebibitsPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, ZebibitsPerSecond, YobibitsPerSecond), 1.0); + assert_float_eq!(convert_test(8.0, BitsPerSecond, BytesPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, BytesPerSecond, KilobytesPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, KilobytesPerSecond, MegabytesPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, MegabytesPerSecond, GigabytesPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, GigabytesPerSecond, TerabytesPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, TerabytesPerSecond, PetabytesPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, PetabytesPerSecond, ExabytesPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, ExabytesPerSecond, ZettabytesPerSecond), 1.0); + assert_float_eq!(convert_test(1000.0, ZettabytesPerSecond, YottabytesPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, KibibytesPerSecond, MebibytesPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, MebibytesPerSecond, GibibytesPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, GibibytesPerSecond, TebibytesPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, TebibytesPerSecond, PebibytesPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, PebibytesPerSecond, ExbibytesPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, ExbibytesPerSecond, ZebibytesPerSecond), 1.0); + assert_float_eq!(convert_test(1024.0, ZebibytesPerSecond, YobibytesPerSecond), 1.0); - assert_float_eq!(convert_test(1000.0, Millijoule, Joule), 1.0); - assert_float_eq!(convert_test(1000.0, Joule, Kilojoule), 1.0); - assert_float_eq!(convert_test(1.0, NewtonMeter, Joule), 1.0); - assert_float_eq!(convert_test(1000.0, Kilojoule, Megajoule), 1.0); - assert_float_eq!(convert_test(1000.0, Megajoule, Gigajoule), 1.0); - assert_float_eq!(convert_test(1000.0, Gigajoule, Terajoule), 1.0); - assert_float_eq!(convert_test(4.1868, Joule, Calorie), 1.0); - assert_float_eq!(convert_test(1000.0, Calorie, KiloCalorie), 1.0); - assert_float_eq!(convert_test(1055.05585262, Joule, BritishThermalUnit), 1.0); - assert_float_eq!(convert_test(3600.0, Joule, WattHour), 1.0); - assert_float_eq!(convert_test(1000.0, WattHour, KilowattHour), 1.0); - assert_float_eq!(convert_test(1000.0, KilowattHour, MegawattHour), 1.0); - assert_float_eq!(convert_test(1000.0, MegawattHour, GigawattHour), 1.0); - assert_float_eq!(convert_test(1000.0, GigawattHour, TerawattHour), 1.0); - assert_float_eq!(convert_test(1000.0, TerawattHour, PetawattHour), 1.0); + assert_float_eq!(convert_test(1000.0, Millijoule, Joule), 1.0); + assert_float_eq!(convert_test(1000.0, Joule, Kilojoule), 1.0); + assert_float_eq!(convert_test(1.0, NewtonMeter, Joule), 1.0); + assert_float_eq!(convert_test(1000.0, Kilojoule, Megajoule), 1.0); + assert_float_eq!(convert_test(1000.0, Megajoule, Gigajoule), 1.0); + assert_float_eq!(convert_test(1000.0, Gigajoule, Terajoule), 1.0); + assert_float_eq!(convert_test(4.1868, Joule, Calorie), 1.0); + assert_float_eq!(convert_test(1000.0, Calorie, KiloCalorie), 1.0); + assert_float_eq!(convert_test(1055.05585262, Joule, BritishThermalUnit), 1.0); + assert_float_eq!(convert_test(3600.0, Joule, WattHour), 1.0); + assert_float_eq!(convert_test(1000.0, WattHour, KilowattHour), 1.0); + assert_float_eq!(convert_test(1000.0, KilowattHour, MegawattHour), 1.0); + assert_float_eq!(convert_test(1000.0, MegawattHour, GigawattHour), 1.0); + assert_float_eq!(convert_test(1000.0, GigawattHour, TerawattHour), 1.0); + assert_float_eq!(convert_test(1000.0, TerawattHour, PetawattHour), 1.0); - assert_float_eq!(convert_test(1000.0, Milliwatt, Watt), 1.0); - assert_float_eq!(convert_test(1000.0, Watt, Kilowatt), 1.0); - assert_float_eq!(convert_test(1000.0, Kilowatt, Megawatt), 1.0); - assert_float_eq!(convert_test(1000.0, Megawatt, Gigawatt), 1.0); - assert_float_eq!(convert_test(1000.0, Gigawatt, Terawatt), 1.0); - assert_float_eq!(convert_test(1000.0, Terawatt, Petawatt), 1.0); - assert_float_eq!(convert_test(0.0568690272188, Watt, BritishThermalUnitsPerMinute), 1.0); - assert_float_eq!(convert_test(60.0, BritishThermalUnitsPerMinute, BritishThermalUnitsPerHour), 1.0); - assert_float_eq!(convert_test(745.6998715822702, Watt, Horsepower), 1.0); - assert_float_eq!(convert_test(735.49875, Watt, MetricHorsepower), 1.0); + assert_float_eq!(convert_test(1000.0, Milliwatt, Watt), 1.0); + assert_float_eq!(convert_test(1000.0, Watt, Kilowatt), 1.0); + assert_float_eq!(convert_test(1000.0, Kilowatt, Megawatt), 1.0); + assert_float_eq!(convert_test(1000.0, Megawatt, Gigawatt), 1.0); + assert_float_eq!(convert_test(1000.0, Gigawatt, Terawatt), 1.0); + assert_float_eq!(convert_test(1000.0, Terawatt, Petawatt), 1.0); + assert_float_eq!(convert_test(0.0568690272188, Watt, BritishThermalUnitsPerMinute), 1.0); + assert_float_eq!(convert_test(60.0, BritishThermalUnitsPerMinute, BritishThermalUnitsPerHour), 1.0); + assert_float_eq!(convert_test(745.6998715822702, Watt, Horsepower), 1.0); + assert_float_eq!(convert_test(735.49875, Watt, MetricHorsepower), 1.0); - assert_float_eq!(convert_test(1000.0, Milliampere, Ampere), 1.0); - assert_float_eq!(convert_test(1000.0, Ampere, Kiloampere), 1.0); - assert_float_eq!(convert_test(10.0, Ampere, Abampere), 1.0); + assert_float_eq!(convert_test(1000.0, Milliampere, Ampere), 1.0); + assert_float_eq!(convert_test(1000.0, Ampere, Kiloampere), 1.0); + assert_float_eq!(convert_test(10.0, Ampere, Abampere), 1.0); - assert_float_eq!(convert_test(1000.0, Milliohm, Ohm), 1.0); - assert_float_eq!(convert_test(1000.0, Ohm, Kiloohm), 1.0); + assert_float_eq!(convert_test(1000.0, Milliohm, Ohm), 1.0); + assert_float_eq!(convert_test(1000.0, Ohm, Kiloohm), 1.0); - assert_float_eq!(convert_test(1000.0, Millivolt, Volt), 1.0); - assert_float_eq!(convert_test(1000.0, Volt, Kilovolt), 1.0); + assert_float_eq!(convert_test(1000.0, Millivolt, Volt), 1.0); + assert_float_eq!(convert_test(1000.0, Volt, Kilovolt), 1.0); - assert_float_eq!(convert_test(1000.0, Pascal, Kilopascal), 1.0); - assert_float_eq!(convert_test(101325.0, Pascal, Atmosphere), 1.0); - assert_float_eq!(convert_test(100.0, Pascal, Millibar), 1.0); - assert_float_eq!(convert_test(1000.0, Millibar, Bar), 1.0); - assert_float_eq!(convert_test(3386.389, Pascal, InchOfMercury), 1.0); - assert_float_eq!(convert_test(6894.757293168361, Pascal, PoundsPerSquareInch), 1.0); - assert_float_eq!(convert_test(162.12, Pascal, Torr), 1.0); + assert_float_eq!(convert_test(1000.0, Pascal, Kilopascal), 1.0); + assert_float_eq!(convert_test(101325.0, Pascal, Atmosphere), 1.0); + assert_float_eq!(convert_test(100.0, Pascal, Millibar), 1.0); + assert_float_eq!(convert_test(1000.0, Millibar, Bar), 1.0); + assert_float_eq!(convert_test(3386.389, Pascal, InchOfMercury), 1.0); + assert_float_eq!(convert_test(6894.757293168361, Pascal, PoundsPerSquareInch), 1.0); + assert_float_eq!(convert_test(162.12, Pascal, Torr), 1.0); - assert_float_eq!(convert_test(1000.0, Hertz, Kilohertz), 1.0); - assert_float_eq!(convert_test(1000.0, Kilohertz, Megahertz), 1.0); - assert_float_eq!(convert_test(1000.0, Megahertz, Gigahertz), 1.0); - assert_float_eq!(convert_test(1000.0, Gigahertz, Terahertz), 1.0); - assert_float_eq!(convert_test(1000.0, Terahertz, Petahertz), 1.0); - assert_float_eq!(convert_test(60.0, Hertz, RevolutionsPerMinute), 1.0); + assert_float_eq!(convert_test(1000.0, Hertz, Kilohertz), 1.0); + assert_float_eq!(convert_test(1000.0, Kilohertz, Megahertz), 1.0); + assert_float_eq!(convert_test(1000.0, Megahertz, Gigahertz), 1.0); + assert_float_eq!(convert_test(1000.0, Gigahertz, Terahertz), 1.0); + assert_float_eq!(convert_test(1000.0, Terahertz, Petahertz), 1.0); + assert_float_eq!(convert_test(60.0, Hertz, RevolutionsPerMinute), 1.0); - assert_float_eq!(convert_test(3.6, KilometersPerHour, MetersPerSecond), 1.0); - assert_float_eq!(convert_test(0.3048, MetersPerSecond, FeetPerSecond), 1.0); - assert_float_eq!(convert_test(1.609344, KilometersPerHour, MilesPerHour), 1.0); - assert_float_eq!(convert_test(1.852, KilometersPerHour, Knot), 1.0); + assert_float_eq!(convert_test(3.6, KilometersPerHour, MetersPerSecond), 1.0); + assert_float_eq!(convert_test(0.3048, MetersPerSecond, FeetPerSecond), 1.0); + assert_float_eq!(convert_test(1.609344, KilometersPerHour, MilesPerHour), 1.0); + assert_float_eq!(convert_test(1.852, KilometersPerHour, Knot), 1.0); - assert_float_eq!(convert_test(274.15, Kelvin, Celsius), 1.0); - assert_float_eq!(convert_test(300.0, Kelvin, Fahrenheit), 80.33); - assert_float_eq!(convert_test(-272.15, Celsius, Kelvin), 1.0); - assert_float_eq!(convert_test(-15.0, Celsius, Fahrenheit), 5.0); - assert_float_eq!(convert_test(80.33, Fahrenheit, Kelvin), 300.0); - assert_float_eq!(convert_test(5.0, Fahrenheit, Celsius), -15.0); - } + assert_float_eq!(convert_test(274.15, Kelvin, Celsius), 1.0); + assert_float_eq!(convert_test(300.0, Kelvin, Fahrenheit), 80.33); + assert_float_eq!(convert_test(-272.15, Celsius, Kelvin), 1.0); + assert_float_eq!(convert_test(-15.0, Celsius, Fahrenheit), 5.0); + assert_float_eq!(convert_test(80.33, Fahrenheit, Kelvin), 300.0); + assert_float_eq!(convert_test(5.0, Fahrenheit, Celsius), -15.0); + } }