Removed code duplication in kalk_num

This commit is contained in:
= 2021-05-20 11:03:53 +02:00
parent d21202a446
commit 869708b454
6 changed files with 137 additions and 235 deletions

View File

@ -1,6 +1,10 @@
#[cfg(feature = "rug")] #[cfg(feature = "rug")]
pub mod with_rug; pub mod with_rug;
#[cfg(feature = "rug")] #[cfg(feature = "rug")]
use rug::ops::Pow;
#[cfg(feature = "rug")]
use rug::Float;
#[cfg(feature = "rug")]
pub use with_rug::*; pub use with_rug::*;
#[cfg(not(feature = "rug"))] #[cfg(not(feature = "rug"))]
@ -8,6 +12,7 @@ pub mod regular;
#[cfg(not(feature = "rug"))] #[cfg(not(feature = "rug"))]
pub use regular::*; pub use regular::*;
use crate::ast::Expr;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use std::collections::HashMap; use std::collections::HashMap;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
@ -44,11 +49,29 @@ lazy_static! {
} }
#[wasm_bindgen] #[wasm_bindgen]
impl KalkNum { #[derive(Clone)]
#[cfg(not(feature = "rug"))] pub struct ScientificNotation {
#[wasm_bindgen(js_name = estimate)] pub negative: bool,
pub fn estimate_js(&self) -> Option<String> { pub(crate) digits: String,
self.estimate() pub exponent: i32,
}
#[wasm_bindgen]
impl ScientificNotation {
#[wasm_bindgen(js_name = toString)]
pub fn to_string(&self) -> String {
let sign = if self.negative { "-" } else { "" };
let mut digits_and_mul = if self.digits == "1" {
String::new()
} else {
format!("{}*", &self.digits)
};
if self.digits.len() > 1 {
digits_and_mul.insert(1usize, '.');
}
format!("{}{}10^{}", sign, digits_and_mul, self.exponent - 1)
} }
} }
@ -73,7 +96,67 @@ impl KalkNum {
} }
} }
// Get an estimate of what the number is, eg. 3.141592 => π pub fn to_string_big(&self) -> String {
self.value.to_string()
}
pub fn is_too_big(&self) -> bool {
self.value.is_infinite()
}
pub fn to_string_with_unit(&self) -> String {
format!("{} {}", self.to_string(), self.unit)
}
pub fn has_unit(&self) -> bool {
self.unit.len() > 0
}
pub(crate) fn convert_to_unit(
&self,
context: &mut crate::interpreter::Context,
to_unit: &str,
) -> Option<KalkNum> {
let result = crate::interpreter::convert_unit(
context,
&Expr::Literal(self.to_f64()),
&self.unit,
to_unit,
);
if let Ok(num) = result {
Some(num)
} else {
None
}
}
pub(crate) fn add(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value + right.value, &right.unit)
}
pub(crate) fn sub(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value - right.value, &right.unit)
}
pub(crate) fn mul(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value * right.value, &right.unit)
}
pub(crate) fn div(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value / right.value, &right.unit)
}
pub(crate) fn rem(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value % right.value, &right.unit)
}
/// Get an estimate of what the number is, eg. 3.141592 => π
pub fn estimate(&self) -> Option<String> { pub fn estimate(&self) -> Option<String> {
let fract = self.value.clone().fract().abs(); let fract = self.value.clone().fract().abs();
let integer = self.value.clone().trunc(); let integer = self.value.clone().trunc();
@ -167,6 +250,18 @@ impl KalkNum {
} }
} }
fn calculate_unit(
context: &mut crate::interpreter::Context,
left: &KalkNum,
right: KalkNum,
) -> Option<KalkNum> {
if left.has_unit() && right.has_unit() {
right.convert_to_unit(context, &left.unit)
} else {
Some(KalkNum::new(right.value, &left.unit))
}
}
fn trim_zeroes(input: &str) -> String { fn trim_zeroes(input: &str) -> String {
if input.contains(".") { if input.contains(".") {
input input
@ -178,6 +273,24 @@ fn trim_zeroes(input: &str) -> String {
} }
} }
impl Into<String> for ScientificNotation {
fn into(self) -> String {
self.to_string()
}
}
impl Into<String> for KalkNum {
fn into(self) -> String {
self.to_string()
}
}
impl Into<f64> for KalkNum {
fn into(self) -> f64 {
self.to_f64()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::kalk_num::KalkNum; use crate::kalk_num::KalkNum;

View File

@ -1,4 +1,4 @@
use crate::ast::Expr; use crate::kalk_num::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen] #[wasm_bindgen]
@ -8,33 +8,6 @@ pub struct KalkNum {
pub(crate) unit: String, pub(crate) unit: String,
} }
#[wasm_bindgen]
#[derive(Clone)]
pub struct ScientificNotation {
pub negative: bool,
pub(crate) digits: String,
pub exponent: i32,
}
#[wasm_bindgen]
impl ScientificNotation {
#[wasm_bindgen(js_name = toString)]
pub fn to_string(&self) -> String {
let sign = if self.negative { "-" } else { "" };
let mut digits_and_mul = if self.digits == "1" {
String::new()
} else {
format!("{}*", &self.digits)
};
if self.digits.len() > 1 {
digits_and_mul.insert(1usize, '.');
}
format!("{}{}10^{}", sign, digits_and_mul, self.exponent - 1)
}
}
#[wasm_bindgen] #[wasm_bindgen]
impl KalkNum { impl KalkNum {
pub fn new(value: f64, unit: &str) -> Self { pub fn new(value: f64, unit: &str) -> Self {
@ -67,18 +40,23 @@ impl KalkNum {
} }
#[wasm_bindgen(js_name = toStringBig)] #[wasm_bindgen(js_name = toStringBig)]
pub fn to_string_big(&self) -> String { pub fn to_string_big_js(&self) -> String {
self.value.to_string() self.to_string_big()
} }
#[wasm_bindgen(js_name = isTooBig)] #[wasm_bindgen(js_name = isTooBig)]
pub fn is_too_big(&self) -> bool { pub fn is_too_big_js(&self) -> bool {
self.value.is_infinite() self.is_too_big()
} }
#[wasm_bindgen(js_name = toStringWithUnit)] #[wasm_bindgen(js_name = toStringWithUnit)]
pub fn to_string_with_unit(&self) -> String { pub fn to_string_with_unit_js(&self) -> String {
format!("{} {}", self.to_string(), self.unit) self.to_string_with_unit()
}
#[wasm_bindgen(js_name = hasUnit)]
pub fn has_unit_js(&self) -> bool {
self.has_unit()
} }
#[wasm_bindgen(js_name = getUnit)] #[wasm_bindgen(js_name = getUnit)]
@ -86,58 +64,14 @@ impl KalkNum {
self.unit.clone() self.unit.clone()
} }
#[wasm_bindgen(js_name = hasUnit)]
pub fn has_unit(&self) -> bool {
self.unit.len() > 0
}
#[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) -> ScientificNotation {
self.to_scientific_notation() self.to_scientific_notation()
} }
pub(crate) fn convert_to_unit( #[wasm_bindgen(js_name = estimate)]
&self, pub fn estimate_js(&self) -> Option<String> {
context: &mut crate::interpreter::Context, self.estimate()
to_unit: &str,
) -> Option<KalkNum> {
let result = crate::interpreter::convert_unit(
context,
&Expr::Literal(self.value),
&self.unit,
to_unit,
);
if let Ok(num) = result {
Some(num)
} else {
None
}
}
pub(crate) fn add(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value + right.value, &right.unit)
}
pub(crate) fn sub(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value - right.value, &right.unit)
}
pub(crate) fn mul(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value * right.value, &right.unit)
}
pub(crate) fn div(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value / right.value, &right.unit)
}
pub(crate) fn rem(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value % right.value, &right.unit)
} }
pub(crate) fn pow(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum { pub(crate) fn pow(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
@ -146,36 +80,6 @@ impl KalkNum {
} }
} }
fn calculate_unit(
context: &mut crate::interpreter::Context,
left: &KalkNum,
right: KalkNum,
) -> Option<KalkNum> {
if left.has_unit() && right.has_unit() {
right.convert_to_unit(context, &left.unit)
} else {
Some(KalkNum::new(right.value, &left.unit))
}
}
impl Into<String> for ScientificNotation {
fn into(self) -> String {
self.to_string()
}
}
impl Into<String> for KalkNum {
fn into(self) -> String {
self.to_string()
}
}
impl Into<f64> for KalkNum {
fn into(self) -> f64 {
self.value
}
}
impl From<f64> for KalkNum { impl From<f64> for KalkNum {
fn from(x: f64) -> Self { fn from(x: f64) -> Self {
KalkNum::new(x, "") KalkNum::new(x, "")

View File

@ -1,6 +1,4 @@
use crate::ast::Expr; use crate::kalk_num::*;
use rug::ops::Pow;
use rug::Float;
impl Default for KalkNum { impl Default for KalkNum {
fn default() -> Self { fn default() -> Self {
@ -14,29 +12,6 @@ pub struct KalkNum {
pub(crate) unit: String, pub(crate) unit: String,
} }
pub struct ScientificNotation {
pub negative: bool,
pub digits: String,
pub exponent: i32,
}
impl ScientificNotation {
pub fn to_string(&self) -> String {
let sign = if self.negative { "-" } else { "" };
let mut digits_and_mul = if self.digits == "1" {
String::new()
} else {
format!("{}*", &self.digits)
};
if self.digits.len() > 1 {
digits_and_mul.insert(1usize, '.');
}
format!("{}{}10^{}", sign, digits_and_mul, self.exponent - 1)
}
}
impl KalkNum { impl KalkNum {
pub fn new(value: Float, unit: &str) -> Self { pub fn new(value: Float, unit: &str) -> Self {
Self { Self {
@ -66,106 +41,16 @@ impl KalkNum {
} }
} }
pub fn to_string_big(&self) -> String {
self.value.to_string()
}
pub fn is_too_big(&self) -> bool {
self.value.is_infinite()
}
pub fn to_string_with_unit(&self) -> String {
format!("{} {}", self.to_string(), self.unit)
}
pub fn get_unit(&self) -> &str { pub fn get_unit(&self) -> &str {
&self.unit &self.unit
} }
pub fn has_unit(&self) -> bool { pub(crate) fn pow(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
self.unit.len() > 0
}
pub fn convert_to_unit(
&self,
context: &mut crate::interpreter::Context,
to_unit: &str,
) -> Option<KalkNum> {
let result = crate::interpreter::convert_unit(
context,
&Expr::Literal(self.value.to_f64()),
&self.unit,
to_unit,
);
if let Ok(num) = result {
Some(num)
} else {
None
}
}
pub fn add(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value + right.value, &right.unit)
}
pub fn sub(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value - right.value, &right.unit)
}
pub fn mul(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value * right.value, &right.unit)
}
pub fn div(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value / right.value, &right.unit)
}
pub fn rem(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value % right.value, &right.unit)
}
pub fn pow(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);
KalkNum::new(self.value.pow(right.value), &right.unit) KalkNum::new(self.value.pow(right.value), &right.unit)
} }
} }
fn calculate_unit(
context: &mut crate::interpreter::Context,
left: &KalkNum,
right: KalkNum,
) -> Option<KalkNum> {
if left.has_unit() && right.has_unit() {
right.convert_to_unit(context, &left.unit)
} else {
Some(KalkNum::new(right.value, &left.unit))
}
}
impl Into<String> for ScientificNotation {
fn into(self) -> String {
self.to_string()
}
}
impl Into<f64> for KalkNum {
fn into(self) -> f64 {
self.to_f64()
}
}
impl Into<String> for KalkNum {
fn into(self) -> String {
self.to_string()
}
}
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), "")

0
kalk/src/test_helpers.rs Normal file → Executable file
View File

0
kalk_mobile/android/gradlew vendored Normal file → Executable file
View File

View File

@ -1,6 +1,6 @@
{ {
"name": "@paddim8/kalk-component", "name": "@paddim8/kalk-component",
"version": "1.0.16", "version": "1.0.17",
"description": "A Svelte component for kalk, a calculator that supports user-defined functions and variables.", "description": "A Svelte component for kalk, a calculator that supports user-defined functions and variables.",
"svelte": "src/main.ts", "svelte": "src/main.ts",
"main": "public/build/bundle.js", "main": "public/build/bundle.js",