mirror of
https://github.com/PaddiM8/kalker.git
synced 2025-01-07 05:59:03 +01:00
Replaced f64 with rug::Float.
This commit is contained in:
parent
0d2d6df85b
commit
93321c3dac
70
Cargo.lock
generated
70
Cargo.lock
generated
@ -27,12 +27,29 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||
|
||||
[[package]]
|
||||
name = "az"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9bcd47d94aa4eb8c076b50fc61a75020789394ffb9bd74a180b3379130f6569"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
||||
|
||||
[[package]]
|
||||
name = "bigdecimal"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1374191e2dd25f9ae02e3aa95041ed5d747fc77b3c102b49fe2dd9a8117a6244"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
@ -112,6 +129,16 @@ dependencies = [
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gmp-mpfr-sys"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c04ccc68f16a0be7164b9de26e65aab8507596cc1969cec2e32fb1692b53b1b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
@ -123,7 +150,9 @@ name = "lek"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"bigdecimal",
|
||||
"phf",
|
||||
"rug",
|
||||
"rustyline",
|
||||
]
|
||||
|
||||
@ -161,6 +190,36 @@ dependencies = [
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.8.0"
|
||||
@ -303,6 +362,17 @@ dependencies = [
|
||||
"rust-argon2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rug"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6cfccfa888f22369385e0fc5f37a37fca05782fc653df5fe7de0934cbe66632"
|
||||
dependencies = [
|
||||
"az",
|
||||
"gmp-mpfr-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-argon2"
|
||||
version = "0.7.0"
|
||||
|
@ -14,3 +14,5 @@ panic = "abort"
|
||||
rustyline = "6.1.2"
|
||||
phf = { version = "0.8", features = ["macros"] }
|
||||
ansi_term = "0.12"
|
||||
bigdecimal = "0.1.2"
|
||||
rug = "1.9.0"
|
@ -2,21 +2,25 @@ use crate::ast::{compare_enums, Expr, Stmt, Unit};
|
||||
use crate::lexer::TokenKind;
|
||||
use crate::prelude;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
use rug::ops::Pow;
|
||||
use rug::Float;
|
||||
|
||||
pub struct Context<'a> {
|
||||
symbol_table: &'a mut SymbolTable,
|
||||
angle_unit: Unit,
|
||||
precision: u32,
|
||||
}
|
||||
|
||||
impl<'a> Context<'a> {
|
||||
pub fn new(angle_unit: Unit, symbol_table: &'a mut SymbolTable) -> Self {
|
||||
pub fn new(symbol_table: &'a mut SymbolTable, angle_unit: Unit, precision: u32) -> Self {
|
||||
Context {
|
||||
angle_unit: angle_unit.clone(),
|
||||
symbol_table,
|
||||
precision,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn interpret(&mut self, statements: Vec<Stmt>) -> Result<Option<f64>, String> {
|
||||
pub fn interpret(&mut self, statements: Vec<Stmt>) -> Result<Option<Float>, String> {
|
||||
for (i, stmt) in statements.iter().enumerate() {
|
||||
let value = eval_stmt(self, stmt);
|
||||
|
||||
@ -31,7 +35,7 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn eval_stmt(context: &mut Context, stmt: &Stmt) -> Result<f64, String> {
|
||||
fn eval_stmt(context: &mut Context, stmt: &Stmt) -> Result<Float, String> {
|
||||
match stmt {
|
||||
Stmt::VarDecl(identifier, _) => eval_var_decl_stmt(context, stmt, identifier),
|
||||
Stmt::FnDecl(_, _, _) => eval_fn_decl_stmt(context),
|
||||
@ -39,20 +43,24 @@ fn eval_stmt(context: &mut Context, stmt: &Stmt) -> Result<f64, String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn eval_var_decl_stmt(context: &mut Context, stmt: &Stmt, identifier: &str) -> Result<f64, String> {
|
||||
fn eval_var_decl_stmt(
|
||||
context: &mut Context,
|
||||
stmt: &Stmt,
|
||||
identifier: &str,
|
||||
) -> Result<Float, String> {
|
||||
context.symbol_table.insert(&identifier, stmt.clone());
|
||||
Ok(0f64)
|
||||
Ok(Float::with_val(context.precision, 1))
|
||||
}
|
||||
|
||||
fn eval_fn_decl_stmt(_: &mut Context) -> Result<f64, String> {
|
||||
Ok(0f64) // Nothing needs to happen here, since the parser will already have added the FnDecl's to the symbol table.
|
||||
fn eval_fn_decl_stmt(context: &mut Context) -> Result<Float, String> {
|
||||
Ok(Float::with_val(context.precision, 1)) // Nothing needs to happen here, since the parser will already have added the FnDecl's to the symbol table.
|
||||
}
|
||||
|
||||
fn eval_expr_stmt(context: &mut Context, expr: &Expr) -> Result<f64, String> {
|
||||
fn eval_expr_stmt(context: &mut Context, expr: &Expr) -> Result<Float, String> {
|
||||
eval_expr(context, &expr)
|
||||
}
|
||||
|
||||
fn eval_expr(context: &mut Context, expr: &Expr) -> Result<f64, String> {
|
||||
fn eval_expr(context: &mut Context, expr: &Expr) -> Result<Float, String> {
|
||||
match expr {
|
||||
Expr::Binary(left, op, right) => eval_binary_expr(context, &left, op, &right),
|
||||
Expr::Unary(op, expr) => eval_unary_expr(context, op, expr),
|
||||
@ -71,7 +79,7 @@ fn eval_binary_expr(
|
||||
left: &Expr,
|
||||
op: &TokenKind,
|
||||
right: &Expr,
|
||||
) -> Result<f64, String> {
|
||||
) -> Result<Float, String> {
|
||||
let left = eval_expr(context, &left)?;
|
||||
let right = eval_expr(context, &right)?;
|
||||
|
||||
@ -80,22 +88,25 @@ fn eval_binary_expr(
|
||||
TokenKind::Minus => left - right,
|
||||
TokenKind::Star => left * right,
|
||||
TokenKind::Slash => left / right,
|
||||
TokenKind::Power => left.powf(right),
|
||||
_ => 0f64,
|
||||
TokenKind::Power => left.pow(right),
|
||||
_ => Float::with_val(1, 1),
|
||||
})
|
||||
}
|
||||
|
||||
fn eval_unary_expr(context: &mut Context, op: &TokenKind, expr: &Expr) -> Result<f64, String> {
|
||||
fn eval_unary_expr(context: &mut Context, op: &TokenKind, expr: &Expr) -> Result<Float, String> {
|
||||
let expr_value = eval_expr(context, &expr)?.clone();
|
||||
|
||||
match op {
|
||||
TokenKind::Minus => Ok(-expr_value),
|
||||
TokenKind::Exclamation => Ok(prelude::special_funcs::factorial(expr_value as i32) as f64),
|
||||
TokenKind::Exclamation => Ok(Float::with_val(
|
||||
context.precision,
|
||||
prelude::special_funcs::factorial(expr_value),
|
||||
)),
|
||||
_ => Err(String::from("Invalid operator for unary expression.")),
|
||||
}
|
||||
}
|
||||
|
||||
fn eval_unit_expr(context: &mut Context, expr: &Expr, kind: &TokenKind) -> Result<f64, String> {
|
||||
fn eval_unit_expr(context: &mut Context, expr: &Expr, kind: &TokenKind) -> Result<Float, String> {
|
||||
let x = eval_expr(context, &expr);
|
||||
let unit = kind.to_unit()?;
|
||||
|
||||
@ -108,13 +119,15 @@ fn eval_unit_expr(context: &mut Context, expr: &Expr, kind: &TokenKind) -> Resul
|
||||
}
|
||||
}
|
||||
|
||||
match unit {
|
||||
/*match unit {
|
||||
Unit::Degrees => Ok(x?.to_radians()),
|
||||
Unit::Radians => Ok(x?.to_degrees()),
|
||||
}
|
||||
}*/
|
||||
|
||||
x
|
||||
}
|
||||
|
||||
fn eval_var_expr(context: &mut Context, identifier: &str) -> Result<f64, String> {
|
||||
fn eval_var_expr(context: &mut Context, identifier: &str) -> Result<Float, String> {
|
||||
// If there is a constant with this name, return a literal expression with its value
|
||||
if let Some(value) = prelude::CONSTANTS.get(identifier) {
|
||||
return eval_expr(context, &Expr::Literal(value.to_string()));
|
||||
@ -128,14 +141,14 @@ fn eval_var_expr(context: &mut Context, identifier: &str) -> Result<f64, String>
|
||||
}
|
||||
}
|
||||
|
||||
fn eval_literal_expr(_: &mut Context, value: &str) -> Result<f64, String> {
|
||||
match value.parse() {
|
||||
Ok(parsed_value) => Ok(parsed_value),
|
||||
fn eval_literal_expr(context: &mut Context, value: &str) -> Result<Float, String> {
|
||||
match Float::parse(value) {
|
||||
Ok(parsed_value) => Ok(Float::with_val(context.precision, parsed_value)),
|
||||
Err(_) => Err(format!("Invalid number literal: '{}'.", value)),
|
||||
}
|
||||
}
|
||||
|
||||
fn eval_group_expr(context: &mut Context, expr: &Expr) -> Result<f64, String> {
|
||||
fn eval_group_expr(context: &mut Context, expr: &Expr) -> Result<Float, String> {
|
||||
eval_expr(context, expr)
|
||||
}
|
||||
|
||||
@ -143,7 +156,7 @@ fn eval_fn_call_expr(
|
||||
context: &mut Context,
|
||||
identifier: &str,
|
||||
expressions: &Vec<Expr>,
|
||||
) -> Result<f64, String> {
|
||||
) -> Result<Float, String> {
|
||||
// Prelude
|
||||
let prelude_func = match expressions.len() {
|
||||
1 => {
|
||||
@ -164,7 +177,7 @@ fn eval_fn_call_expr(
|
||||
|
||||
// Special functions
|
||||
match identifier {
|
||||
"sum" => {
|
||||
"sum" | "Σ" => {
|
||||
// Make sure exactly 3 arguments were supplied.
|
||||
if expressions.len() != 3 {
|
||||
return Err(format!(
|
||||
@ -173,9 +186,9 @@ fn eval_fn_call_expr(
|
||||
));
|
||||
}
|
||||
|
||||
let start = eval_expr(context, &expressions[0])? as i32;
|
||||
let end = eval_expr(context, &expressions[1])? as i32;
|
||||
let mut sum = 0f64;
|
||||
let start = eval_expr(context, &expressions[0])?.to_f64() as i128;
|
||||
let end = eval_expr(context, &expressions[1])?.to_f64() as i128;
|
||||
let mut sum = Float::with_val(context.precision, 0);
|
||||
|
||||
for n in start..=end {
|
||||
let n_expr = Expr::Literal(String::from(n.to_string()));
|
||||
|
54
src/lexer.rs
54
src/lexer.rs
@ -51,7 +51,7 @@ impl<'a> Lexer<'a> {
|
||||
// If there isn't already an EOF token, add it.
|
||||
if let TokenKind::EOF = tokens.last().unwrap().kind {
|
||||
} else {
|
||||
tokens.push(lexer.build(TokenKind::EOF, ""));
|
||||
tokens.push(build(TokenKind::EOF, ""));
|
||||
}
|
||||
|
||||
tokens
|
||||
@ -64,7 +64,7 @@ impl<'a> Lexer<'a> {
|
||||
self.advance();
|
||||
|
||||
if self.is_at_end() {
|
||||
return self.build(TokenKind::EOF, "");
|
||||
return build(TokenKind::EOF, "");
|
||||
} else {
|
||||
c = self.peek();
|
||||
}
|
||||
@ -73,47 +73,47 @@ impl<'a> Lexer<'a> {
|
||||
let token = match c {
|
||||
'+' => {
|
||||
self.advance();
|
||||
self.build(TokenKind::Plus, "")
|
||||
build(TokenKind::Plus, "")
|
||||
}
|
||||
'-' => {
|
||||
self.advance();
|
||||
self.build(TokenKind::Minus, "")
|
||||
build(TokenKind::Minus, "")
|
||||
}
|
||||
'*' => {
|
||||
self.advance();
|
||||
self.build(TokenKind::Star, "")
|
||||
build(TokenKind::Star, "")
|
||||
}
|
||||
'/' => {
|
||||
self.advance();
|
||||
self.build(TokenKind::Slash, "")
|
||||
build(TokenKind::Slash, "")
|
||||
}
|
||||
'^' => {
|
||||
self.advance();
|
||||
self.build(TokenKind::Power, "")
|
||||
build(TokenKind::Power, "")
|
||||
}
|
||||
'(' => {
|
||||
self.advance();
|
||||
self.build(TokenKind::OpenParenthesis, "")
|
||||
build(TokenKind::OpenParenthesis, "")
|
||||
}
|
||||
')' => {
|
||||
self.advance();
|
||||
self.build(TokenKind::ClosedParenthesis, "")
|
||||
build(TokenKind::ClosedParenthesis, "")
|
||||
}
|
||||
'|' => {
|
||||
self.advance();
|
||||
self.build(TokenKind::Pipe, "")
|
||||
build(TokenKind::Pipe, "")
|
||||
}
|
||||
'=' => {
|
||||
self.advance();
|
||||
self.build(TokenKind::Equals, "")
|
||||
build(TokenKind::Equals, "")
|
||||
}
|
||||
'!' => {
|
||||
self.advance();
|
||||
self.build(TokenKind::Exclamation, "")
|
||||
build(TokenKind::Exclamation, "")
|
||||
}
|
||||
',' => {
|
||||
self.advance();
|
||||
self.build(TokenKind::Comma, "")
|
||||
build(TokenKind::Comma, "")
|
||||
}
|
||||
_ => {
|
||||
if c.is_digit(10) {
|
||||
@ -122,7 +122,7 @@ impl<'a> Lexer<'a> {
|
||||
self.next_identifier()
|
||||
} else {
|
||||
self.advance();
|
||||
self.build(TokenKind::Unknown, "")
|
||||
build(TokenKind::Unknown, "")
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -140,9 +140,9 @@ impl<'a> Lexer<'a> {
|
||||
}
|
||||
|
||||
if let Ok(value) = str::from_utf8(&self.source[start..end]) {
|
||||
self.build(TokenKind::Literal, value)
|
||||
build(TokenKind::Literal, value)
|
||||
} else {
|
||||
self.build(TokenKind::Unknown, "")
|
||||
build(TokenKind::Unknown, "")
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,16 +162,9 @@ impl<'a> Lexer<'a> {
|
||||
_ => TokenKind::Identifier,
|
||||
};
|
||||
|
||||
self.build(kind, value)
|
||||
build(kind, value)
|
||||
} else {
|
||||
self.build(TokenKind::Unknown, "")
|
||||
}
|
||||
}
|
||||
|
||||
fn build(&self, kind: TokenKind, value: &str) -> Token {
|
||||
Token {
|
||||
kind,
|
||||
value: value.to_string(),
|
||||
build(TokenKind::Unknown, "")
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,6 +181,13 @@ impl<'a> Lexer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_valid_identifier(c: char) -> bool {
|
||||
c.is_alphabetic() || c == '°' || c == '√' || c == '\'' || c == '¨'
|
||||
fn build(kind: TokenKind, value: &str) -> Token {
|
||||
Token {
|
||||
kind,
|
||||
value: value.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_valid_identifier(c: char) -> bool {
|
||||
c.is_alphabetic() || c == '°' || c == '√' || c == '\'' || c == '¨' || c == 'Σ'
|
||||
}
|
||||
|
10
src/main.rs
10
src/main.rs
@ -48,8 +48,14 @@ fn eval_repl(parser: &mut parser::Context, input: &str) {
|
||||
}
|
||||
|
||||
fn eval(parser: &mut parser::Context, input: &str) {
|
||||
match parser::parse(parser, input, get_angle_unit()) {
|
||||
Ok(Some(result)) => println!("{}", result),
|
||||
match parser::parse(parser, input, get_angle_unit(), 53) {
|
||||
Ok(Some(result)) => {
|
||||
if result.clone().fract() == 0 {
|
||||
println!("{}", result.to_integer().unwrap());
|
||||
} else {
|
||||
println!("{}", result);
|
||||
}
|
||||
}
|
||||
Ok(None) => print!(""),
|
||||
Err(err) => println!("{}", Red.paint(err)),
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use crate::{
|
||||
lexer::{Lexer, Token, TokenKind},
|
||||
symbol_table::SymbolTable,
|
||||
};
|
||||
use rug::Float;
|
||||
|
||||
pub struct Context {
|
||||
//angle_unit: Unit,
|
||||
@ -22,7 +23,12 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(context: &mut Context, input: &str, angle_unit: Unit) -> Result<Option<f64>, String> {
|
||||
pub fn parse(
|
||||
context: &mut Context,
|
||||
input: &str,
|
||||
angle_unit: Unit,
|
||||
precision: u32,
|
||||
) -> Result<Option<Float>, String> {
|
||||
context.tokens = Lexer::lex(input);
|
||||
context.pos = 0;
|
||||
|
||||
@ -30,7 +36,8 @@ pub fn parse(context: &mut Context, input: &str, angle_unit: Unit) -> Result<Opt
|
||||
while !is_at_end(context) {
|
||||
statements.push(parse_stmt(context)?);
|
||||
}
|
||||
let mut interpreter = interpreter::Context::new(angle_unit, &mut context.symbol_table);
|
||||
let mut interpreter =
|
||||
interpreter::Context::new(&mut context.symbol_table, angle_unit, precision);
|
||||
interpreter.interpret(statements)
|
||||
}
|
||||
|
||||
|
137
src/prelude.rs
137
src/prelude.rs
@ -1,3 +1,4 @@
|
||||
use rug::Float;
|
||||
use FuncType::*;
|
||||
|
||||
pub const CONSTANTS: phf::Map<&'static str, &'static str> = phf::phf_map! {
|
||||
@ -66,12 +67,12 @@ enum FuncType {
|
||||
}
|
||||
|
||||
// Unary functions
|
||||
pub struct UnaryFuncInfo(fn(f64) -> f64, FuncType);
|
||||
pub struct UnaryFuncInfo(fn(Float) -> Float, FuncType);
|
||||
|
||||
pub struct BinaryFuncInfo(fn(f64, f64) -> f64, FuncType);
|
||||
pub struct BinaryFuncInfo(fn(Float, Float) -> Float, FuncType);
|
||||
|
||||
impl UnaryFuncInfo {
|
||||
fn call(&self, x: f64, angle_unit: &Unit) -> f64 {
|
||||
fn call(&self, x: Float, angle_unit: &Unit) -> Float {
|
||||
let func = self.0;
|
||||
match self.1 {
|
||||
FuncType::Trig => func(from_angle_unit(x, angle_unit)),
|
||||
@ -82,7 +83,7 @@ impl UnaryFuncInfo {
|
||||
}
|
||||
|
||||
impl BinaryFuncInfo {
|
||||
fn call(&self, x: f64, y: f64, angle_unit: &Unit) -> f64 {
|
||||
fn call(&self, x: Float, y: Float, angle_unit: &Unit) -> Float {
|
||||
let func = self.0;
|
||||
match self.1 {
|
||||
FuncType::Trig => func(
|
||||
@ -95,7 +96,7 @@ impl BinaryFuncInfo {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call_unary_func(name: &str, x: f64, angle_unit: &Unit) -> Option<f64> {
|
||||
pub fn call_unary_func(name: &str, x: Float, angle_unit: &Unit) -> Option<Float> {
|
||||
if let Some(func_info) = UNARY_FUNCS.get(name) {
|
||||
Some(func_info.call(x, &angle_unit))
|
||||
} else {
|
||||
@ -103,7 +104,7 @@ pub fn call_unary_func(name: &str, x: f64, angle_unit: &Unit) -> Option<f64> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call_binary_func(name: &str, x: f64, y: f64, angle_unit: &Unit) -> Option<f64> {
|
||||
pub fn call_binary_func(name: &str, x: Float, y: Float, angle_unit: &Unit) -> Option<Float> {
|
||||
if let Some(func_info) = BINARY_FUNCS.get(name) {
|
||||
Some(func_info.call(x, y, angle_unit))
|
||||
} else {
|
||||
@ -111,188 +112,196 @@ pub fn call_binary_func(name: &str, x: f64, y: f64, angle_unit: &Unit) -> Option
|
||||
}
|
||||
}
|
||||
|
||||
fn to_angle_unit(x: f64, angle_unit: &Unit) -> f64 {
|
||||
fn to_angle_unit(x: Float, angle_unit: &Unit) -> Float {
|
||||
match angle_unit {
|
||||
Unit::Radians => x,
|
||||
Unit::Degrees => x.to_degrees(),
|
||||
Unit::Degrees => special_funcs::to_degrees(x),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_angle_unit(x: f64, angle_unit: &Unit) -> f64 {
|
||||
fn from_angle_unit(x: Float, angle_unit: &Unit) -> Float {
|
||||
match angle_unit {
|
||||
Unit::Radians => x,
|
||||
Unit::Degrees => x.to_radians(),
|
||||
Unit::Degrees => special_funcs::to_radians(x),
|
||||
}
|
||||
}
|
||||
|
||||
pub mod special_funcs {
|
||||
pub fn factorial(x: i32) -> i32 {
|
||||
let mut value = 1;
|
||||
for i in 1..=x {
|
||||
value *= i;
|
||||
}
|
||||
use rug::Float;
|
||||
|
||||
value
|
||||
pub fn factorial(x: Float) -> Float {
|
||||
((x + 1) as Float).gamma()
|
||||
}
|
||||
|
||||
pub fn to_degrees(x: Float) -> Float {
|
||||
Float::with_val(10, x.to_f64().to_degrees())
|
||||
}
|
||||
|
||||
pub fn to_radians(x: Float) -> Float {
|
||||
Float::with_val(10, x.to_f64().to_radians())
|
||||
}
|
||||
}
|
||||
|
||||
mod funcs {
|
||||
pub fn abs(x: f64) -> f64 {
|
||||
use rug::ops::Pow;
|
||||
use rug::Float;
|
||||
|
||||
pub fn abs(x: Float) -> Float {
|
||||
x.abs()
|
||||
}
|
||||
|
||||
pub fn acos(x: f64) -> f64 {
|
||||
pub fn acos(x: Float) -> Float {
|
||||
x.acos()
|
||||
}
|
||||
|
||||
pub fn acosh(x: f64) -> f64 {
|
||||
pub fn acosh(x: Float) -> Float {
|
||||
x.acosh()
|
||||
}
|
||||
|
||||
pub fn acot(x: f64) -> f64 {
|
||||
pub fn acot(x: Float) -> Float {
|
||||
(1f64 / x).atan()
|
||||
}
|
||||
pub fn acoth(x: f64) -> f64 {
|
||||
pub fn acoth(x: Float) -> Float {
|
||||
(1f64 / x).atanh()
|
||||
}
|
||||
|
||||
pub fn acosec(x: f64) -> f64 {
|
||||
pub fn acosec(x: Float) -> Float {
|
||||
(1f64 / x).asin()
|
||||
}
|
||||
|
||||
pub fn acosech(x: f64) -> f64 {
|
||||
pub fn acosech(x: Float) -> Float {
|
||||
(1f64 / x).asinh()
|
||||
}
|
||||
|
||||
pub fn asec(x: f64) -> f64 {
|
||||
pub fn asec(x: Float) -> Float {
|
||||
(1f64 / x).acos()
|
||||
}
|
||||
|
||||
pub fn asech(x: f64) -> f64 {
|
||||
pub fn asech(x: Float) -> Float {
|
||||
(1f64 / x).acosh()
|
||||
}
|
||||
|
||||
pub fn asin(x: f64) -> f64 {
|
||||
pub fn asin(x: Float) -> Float {
|
||||
x.asin()
|
||||
}
|
||||
|
||||
pub fn asinh(x: f64) -> f64 {
|
||||
pub fn asinh(x: Float) -> Float {
|
||||
x.asinh()
|
||||
}
|
||||
|
||||
pub fn atan(x: f64) -> f64 {
|
||||
pub fn atan(x: Float) -> Float {
|
||||
x.atan()
|
||||
}
|
||||
|
||||
pub fn atanh(x: f64) -> f64 {
|
||||
pub fn atanh(x: Float) -> Float {
|
||||
x.atanh()
|
||||
}
|
||||
|
||||
pub fn cbrt(x: f64) -> f64 {
|
||||
pub fn cbrt(x: Float) -> Float {
|
||||
x.cbrt()
|
||||
}
|
||||
|
||||
pub fn ceil(x: f64) -> f64 {
|
||||
pub fn ceil(x: Float) -> Float {
|
||||
x.ceil()
|
||||
}
|
||||
|
||||
pub fn cos(x: f64) -> f64 {
|
||||
pub fn cos(x: Float) -> Float {
|
||||
x.cos()
|
||||
}
|
||||
|
||||
pub fn cosh(x: f64) -> f64 {
|
||||
pub fn cosh(x: Float) -> Float {
|
||||
x.cos()
|
||||
}
|
||||
|
||||
pub fn cosec(x: f64) -> f64 {
|
||||
pub fn cosec(x: Float) -> Float {
|
||||
1f64 / x.sin()
|
||||
}
|
||||
|
||||
pub fn cosech(x: f64) -> f64 {
|
||||
pub fn cosech(x: Float) -> Float {
|
||||
1f64 / x.sinh()
|
||||
}
|
||||
|
||||
pub fn cot(x: f64) -> f64 {
|
||||
x.cos() / x.sin()
|
||||
pub fn cot(x: Float) -> Float {
|
||||
x.clone().cos() / x.sin()
|
||||
}
|
||||
|
||||
pub fn coth(x: f64) -> f64 {
|
||||
x.cosh() / x.sinh()
|
||||
pub fn coth(x: Float) -> Float {
|
||||
x.clone().cosh() / x.sinh()
|
||||
}
|
||||
|
||||
pub fn exp(x: f64) -> f64 {
|
||||
pub fn exp(x: Float) -> Float {
|
||||
x.exp()
|
||||
}
|
||||
|
||||
pub fn floor(x: f64) -> f64 {
|
||||
pub fn floor(x: Float) -> Float {
|
||||
x.floor()
|
||||
}
|
||||
|
||||
pub fn frac(x: f64) -> f64 {
|
||||
pub fn frac(x: Float) -> Float {
|
||||
x.fract()
|
||||
}
|
||||
|
||||
pub fn hyp(x: f64, y: f64) -> f64 {
|
||||
x.hypot(y)
|
||||
pub fn hyp(x: Float, y: Float) -> Float {
|
||||
x.hypot(&y)
|
||||
}
|
||||
|
||||
pub fn log(x: f64) -> f64 {
|
||||
x.log(10f64)
|
||||
pub fn log(x: Float) -> Float {
|
||||
x.log10()
|
||||
}
|
||||
|
||||
pub fn logx(x: f64, y: f64) -> f64 {
|
||||
x.log(y)
|
||||
pub fn logx(x: Float, y: Float) -> Float {
|
||||
x.log10() / y.log10()
|
||||
}
|
||||
|
||||
pub fn ln(x: f64) -> f64 {
|
||||
pub fn ln(x: Float) -> Float {
|
||||
x.ln()
|
||||
}
|
||||
|
||||
pub fn max(x: f64, y: f64) -> f64 {
|
||||
x.max(y)
|
||||
pub fn max(x: Float, y: Float) -> Float {
|
||||
x.max(&y)
|
||||
}
|
||||
|
||||
pub fn min(x: f64, y: f64) -> f64 {
|
||||
x.min(y)
|
||||
pub fn min(x: Float, y: Float) -> Float {
|
||||
x.min(&y)
|
||||
}
|
||||
|
||||
pub fn round(x: f64) -> f64 {
|
||||
pub fn round(x: Float) -> Float {
|
||||
x.round()
|
||||
}
|
||||
|
||||
pub fn sec(x: f64) -> f64 {
|
||||
pub fn sec(x: Float) -> Float {
|
||||
1f64 / x.cos()
|
||||
}
|
||||
|
||||
pub fn sech(x: f64) -> f64 {
|
||||
pub fn sech(x: Float) -> Float {
|
||||
1f64 / x.cosh()
|
||||
}
|
||||
|
||||
pub fn sin(x: f64) -> f64 {
|
||||
pub fn sin(x: Float) -> Float {
|
||||
x.sin()
|
||||
}
|
||||
|
||||
pub fn sinh(x: f64) -> f64 {
|
||||
pub fn sinh(x: Float) -> Float {
|
||||
x.sinh()
|
||||
}
|
||||
|
||||
pub fn sqrt(x: f64) -> f64 {
|
||||
pub fn sqrt(x: Float) -> Float {
|
||||
x.sqrt()
|
||||
}
|
||||
|
||||
pub fn nth_sqrt(x: f64, n: f64) -> f64 {
|
||||
x.powf(1f64 / n)
|
||||
pub fn nth_sqrt(x: Float, n: Float) -> Float {
|
||||
x.pow(Float::with_val(1, 1) / n)
|
||||
}
|
||||
|
||||
pub fn tan(x: f64) -> f64 {
|
||||
pub fn tan(x: Float) -> Float {
|
||||
x.tan()
|
||||
}
|
||||
|
||||
pub fn tanh(x: f64) -> f64 {
|
||||
pub fn tanh(x: Float) -> Float {
|
||||
x.tanh()
|
||||
}
|
||||
|
||||
pub fn trunc(x: f64) -> f64 {
|
||||
pub fn trunc(x: Float) -> Float {
|
||||
x.trunc()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user