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)?;
match op {
TokenKind::Minus => Ok(KalkNum::new(-num.value, &num.unit)),
TokenKind::Percent => Ok(KalkNum::new(num.value * 0.01, unit)),
TokenKind::Minus => Ok(num.mul(context, KalkNum::from(-1f64))),
TokenKind::Percent => Ok(num.mul(context, KalkNum::from(0.01f64))),
TokenKind::Exclamation => Ok(KalkNum::new(
prelude::special_funcs::factorial(num.value),
unit,

View File

@ -22,9 +22,7 @@ lazy_static! {
let mut m = HashMap::new();
m.insert("3.141592", "π");
m.insert("2.718281", "e");
m.insert("6.283185", "tau");
m.insert("6.283185", "τ");
m.insert("1.618033", "phi");
m.insert("1.618033", "ϕ");
m.insert("1.414213", "√2");
// 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 {
if self.imaginary_value == 0 {
if self.imaginary_value == 0f64 {
self.value.to_string()
} else {
let sign = if self.imaginary_value < 0 { "-" } else { "+" };
let sign = if self.imaginary_value < 0f64 {
"-"
} else {
"+"
};
format!(
"{} {} {}",
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 {
let sci_notation_real = self.to_scientific_notation(ComplexNumberType::Real);
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)
} else {
format!("{} i", sci_notation_imaginary.to_string())
format!("{}", sci_notation_imaginary.to_string())
};
let mut output = result_str;
@ -166,13 +202,21 @@ impl KalkNum {
if output == "0" {
output = String::new();
}
// If there is a real value as well
if output.len() > 0 {
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();
@ -238,8 +282,10 @@ impl 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);
// (a + bi)(c + di) = ac + adi + bci + bdi²
KalkNum::new_with_imaginary(
KalkNum::default().value,
self.value.clone() * right.value.clone()
- self.imaginary_value.clone() * right.imaginary_value.clone(),
&right.unit,
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(
context: &mut crate::interpreter::Context,
left: &KalkNum,

View File

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

View File

@ -43,34 +43,6 @@ impl KalkNum {
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 {
&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 {
fn from(x: f64) -> Self {
KalkNum::new(Float::with_val(63, x), "")

View File

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

View File

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