Made complex numbers work without rug

This commit is contained in:
bakk 2021-05-20 19:26:03 +02:00
parent 625c63470b
commit ee3082ad66
6 changed files with 80 additions and 65 deletions

View File

@ -175,8 +175,8 @@ fn eval_unary_expr(
let num = eval_expr(context, &expr, unit)?; let num = eval_expr(context, &expr, unit)?;
match op { match op {
TokenKind::Minus => Ok(KalkNum::new(-num.value, &num.unit)), TokenKind::Minus => Ok(num.mul(context, KalkNum::from(-1f64))),
TokenKind::Percent => Ok(KalkNum::new(num.value * 0.01, unit)), TokenKind::Percent => Ok(num.mul(context, KalkNum::from(0.01f64))),
TokenKind::Exclamation => Ok(KalkNum::new( TokenKind::Exclamation => Ok(KalkNum::new(
prelude::special_funcs::factorial(num.value), prelude::special_funcs::factorial(num.value),
unit, unit,

View File

@ -22,9 +22,7 @@ lazy_static! {
let mut m = HashMap::new(); let mut m = HashMap::new();
m.insert("3.141592", "π"); m.insert("3.141592", "π");
m.insert("2.718281", "e"); m.insert("2.718281", "e");
m.insert("6.283185", "tau");
m.insert("6.283185", "τ"); m.insert("6.283185", "τ");
m.insert("1.618033", "phi");
m.insert("1.618033", "ϕ"); m.insert("1.618033", "ϕ");
m.insert("1.414213", "√2"); m.insert("1.414213", "√2");
// Radian values for common angles // Radian values for common angles
@ -127,11 +125,32 @@ impl KalkNum {
} }
} }
pub fn to_string(&self) -> String {
let as_str = trim_number_string(&self.to_f64().to_string());
if self.imaginary_value != 0f64 {
let imaginary_as_str = trim_number_string(&self.imaginary_to_f64().to_string());
let sign = if self.imaginary_value < 0f64 {
"-"
} else {
"+"
};
format!("{} {} {}i", as_str, sign, imaginary_as_str)
} else {
as_str
}
}
pub fn to_string_big(&self) -> String { pub fn to_string_big(&self) -> String {
if self.imaginary_value == 0 { if self.imaginary_value == 0f64 {
self.value.to_string() self.value.to_string()
} else { } else {
let sign = if self.imaginary_value < 0 { "-" } else { "+" }; let sign = if self.imaginary_value < 0f64 {
"-"
} else {
"+"
};
format!( format!(
"{} {} {}", "{} {} {}",
self.value.to_string(), self.value.to_string(),
@ -141,6 +160,23 @@ impl KalkNum {
} }
} }
pub fn to_string_real(&self) -> String {
trim_number_string(&self.to_f64().to_string())
}
pub fn to_string_imaginary(&self, include_i: bool) -> String {
let value = trim_number_string(&self.imaginary_to_f64().to_string());
if include_i && value == "1" {
String::from("i")
} else if include_i && value == "-1" {
String::from("-i")
} else if include_i {
format!("{}i", value)
} else {
value
}
}
pub fn to_string_pretty(&self) -> String { pub fn to_string_pretty(&self) -> String {
let sci_notation_real = self.to_scientific_notation(ComplexNumberType::Real); let sci_notation_real = self.to_scientific_notation(ComplexNumberType::Real);
let result_str = if (-6..8).contains(&sci_notation_real.exponent) || self.value == 0f64 { let result_str = if (-6..8).contains(&sci_notation_real.exponent) || self.value == 0f64 {
@ -156,7 +192,7 @@ impl KalkNum {
{ {
self.to_string_imaginary(true) self.to_string_imaginary(true)
} else { } else {
format!("{} i", sci_notation_imaginary.to_string()) format!("{}", sci_notation_imaginary.to_string())
}; };
let mut output = result_str; let mut output = result_str;
@ -166,14 +202,22 @@ impl KalkNum {
if output == "0" { if output == "0" {
output = String::new(); output = String::new();
} }
// If there is a real value as well
if output.len() > 0 { if output.len() > 0 {
output.push_str(&format!( output.push_str(&format!(
" {} ", " {} {}",
if self.imaginary_value < 0 { "-" } else { "+" } if self.imaginary_value < 0f64 {
"-"
} else {
"+"
},
result_str_imaginary.trim_start_matches("-"),
)); ));
} } else {
output.push_str(&format!("{}", result_str_imaginary)); output.push_str(&format!("{}", result_str_imaginary));
} }
}
let unit = self.get_unit(); let unit = self.get_unit();
if unit != "" { if unit != "" {
@ -238,8 +282,10 @@ impl KalkNum {
pub(crate) fn mul(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum { pub(crate) fn mul(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs); let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
// (a + bi)(c + di) = ac + adi + bci + bdi²
KalkNum::new_with_imaginary( KalkNum::new_with_imaginary(
KalkNum::default().value, self.value.clone() * right.value.clone()
- self.imaginary_value.clone() * right.imaginary_value.clone(),
&right.unit, &right.unit,
self.value * right.imaginary_value + self.imaginary_value * right.value, self.value * right.imaginary_value + self.imaginary_value * right.value,
) )
@ -349,6 +395,17 @@ impl KalkNum {
} }
} }
fn trim_number_string(input: &str) -> String {
if input.contains(".") {
input
.trim_end_matches('0')
.trim_end_matches('.')
.to_string()
} else {
input.into()
}
}
fn calculate_unit( fn calculate_unit(
context: &mut crate::interpreter::Context, context: &mut crate::interpreter::Context,
left: &KalkNum, left: &KalkNum,

View File

@ -32,21 +32,18 @@ impl KalkNum {
self.value self.value
} }
#[wasm_bindgen(js_name = getImaginaryValue)]
pub fn imaginary_to_f64(&self) -> f64 {
self.imaginary_value
}
pub fn to_i32(&self) -> i32 { pub fn to_i32(&self) -> i32 {
self.value as i32 self.value as i32
} }
#[wasm_bindgen(js_name = toString)] #[wasm_bindgen(js_name = toString)]
pub fn to_string(&self) -> String { pub fn to_string_js(&self) -> String {
let string_value = self.value.to_string(); self.to_string()
if string_value.contains(".") {
string_value
.trim_end_matches('0')
.trim_end_matches('.')
.to_string()
} else {
string_value
}
} }
#[wasm_bindgen(js_name = toStringBig)] #[wasm_bindgen(js_name = toStringBig)]
@ -75,8 +72,11 @@ impl KalkNum {
} }
#[wasm_bindgen(js_name = toScientificNotation)] #[wasm_bindgen(js_name = toScientificNotation)]
pub fn to_scientific_notation_js(&self) -> ScientificNotation { pub fn to_scientific_notation_js(
self.to_scientific_notation() &self,
complex_number_type: ComplexNumberType,
) -> ScientificNotation {
self.to_scientific_notation(complex_number_type)
} }
#[wasm_bindgen(js_name = estimate)] #[wasm_bindgen(js_name = estimate)]

View File

@ -43,34 +43,6 @@ impl KalkNum {
self.value.to_i32_saturating().unwrap() self.value.to_i32_saturating().unwrap()
} }
pub fn to_string(&self) -> String {
let as_str = trim_number_string(&self.to_f64().to_string());
if self.imaginary_value != 0 {
let imaginary_as_str = trim_number_string(&self.imaginary_to_f64().to_string());
let sign = if self.imaginary_value < 0 { "-" } else { "+" };
format!("{} {} {}i", as_str, sign, imaginary_as_str)
} else {
as_str
}
}
pub fn to_string_real(&self) -> String {
trim_number_string(&self.to_f64().to_string())
}
pub fn to_string_imaginary(&self, include_i: bool) -> String {
let value = trim_number_string(&self.imaginary_to_f64().to_string());
if include_i && value == "1" {
String::from("i")
} else if include_i {
format!("{}i", value)
} else {
value
}
}
pub fn get_unit(&self) -> &str { pub fn get_unit(&self) -> &str {
&self.unit &self.unit
} }
@ -81,17 +53,6 @@ impl KalkNum {
} }
} }
fn trim_number_string(input: &str) -> String {
if input.contains(".") {
input
.trim_end_matches('0')
.trim_end_matches('.')
.to_string()
} else {
input.into()
}
}
impl From<f64> for KalkNum { impl From<f64> for KalkNum {
fn from(x: f64) -> Self { fn from(x: f64) -> Self {
KalkNum::new(Float::with_val(63, x), "") KalkNum::new(Float::with_val(63, x), "")

View File

@ -7,8 +7,6 @@ use std::env;
use std::fs::File; use std::fs::File;
use std::io::Read; use std::io::Read;
static DEFAULT_PRECISION: u32 = 53;
fn main() { fn main() {
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
let app = App::new("kalk") let app = App::new("kalk")

View File

@ -1,4 +1,3 @@
use crate::DEFAULT_PRECISION;
use ansi_term::Colour::Red; use ansi_term::Colour::Red;
use kalk::parser; use kalk::parser;