Replaced f64 with rug::Float.

This commit is contained in:
PaddiM8 2020-06-04 14:46:45 +02:00
parent 0d2d6df85b
commit 93321c3dac
7 changed files with 229 additions and 122 deletions

70
Cargo.lock generated
View File

@ -27,12 +27,29 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]]
name = "az"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9bcd47d94aa4eb8c076b50fc61a75020789394ffb9bd74a180b3379130f6569"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.11.0" version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" 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]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.2.1" version = "1.2.1"
@ -112,6 +129,16 @@ dependencies = [
"wasi", "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]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@ -123,7 +150,9 @@ name = "lek"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ansi_term", "ansi_term",
"bigdecimal",
"phf", "phf",
"rug",
"rustyline", "rustyline",
] ]
@ -161,6 +190,36 @@ dependencies = [
"void", "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]] [[package]]
name = "phf" name = "phf"
version = "0.8.0" version = "0.8.0"
@ -303,6 +362,17 @@ dependencies = [
"rust-argon2", "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]] [[package]]
name = "rust-argon2" name = "rust-argon2"
version = "0.7.0" version = "0.7.0"

View File

@ -14,3 +14,5 @@ panic = "abort"
rustyline = "6.1.2" rustyline = "6.1.2"
phf = { version = "0.8", features = ["macros"] } phf = { version = "0.8", features = ["macros"] }
ansi_term = "0.12" ansi_term = "0.12"
bigdecimal = "0.1.2"
rug = "1.9.0"

View File

@ -2,21 +2,25 @@ use crate::ast::{compare_enums, Expr, Stmt, Unit};
use crate::lexer::TokenKind; use crate::lexer::TokenKind;
use crate::prelude; use crate::prelude;
use crate::symbol_table::SymbolTable; use crate::symbol_table::SymbolTable;
use rug::ops::Pow;
use rug::Float;
pub struct Context<'a> { pub struct Context<'a> {
symbol_table: &'a mut SymbolTable, symbol_table: &'a mut SymbolTable,
angle_unit: Unit, angle_unit: Unit,
precision: u32,
} }
impl<'a> Context<'a> { 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 { Context {
angle_unit: angle_unit.clone(), angle_unit: angle_unit.clone(),
symbol_table, 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() { for (i, stmt) in statements.iter().enumerate() {
let value = eval_stmt(self, stmt); 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 { match stmt {
Stmt::VarDecl(identifier, _) => eval_var_decl_stmt(context, stmt, identifier), Stmt::VarDecl(identifier, _) => eval_var_decl_stmt(context, stmt, identifier),
Stmt::FnDecl(_, _, _) => eval_fn_decl_stmt(context), 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()); 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> { fn eval_fn_decl_stmt(context: &mut Context) -> Result<Float, String> {
Ok(0f64) // Nothing needs to happen here, since the parser will already have added the FnDecl's to the symbol table. 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) 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 { match expr {
Expr::Binary(left, op, right) => eval_binary_expr(context, &left, op, &right), Expr::Binary(left, op, right) => eval_binary_expr(context, &left, op, &right),
Expr::Unary(op, expr) => eval_unary_expr(context, op, expr), Expr::Unary(op, expr) => eval_unary_expr(context, op, expr),
@ -71,7 +79,7 @@ fn eval_binary_expr(
left: &Expr, left: &Expr,
op: &TokenKind, op: &TokenKind,
right: &Expr, right: &Expr,
) -> Result<f64, String> { ) -> Result<Float, String> {
let left = eval_expr(context, &left)?; let left = eval_expr(context, &left)?;
let right = eval_expr(context, &right)?; let right = eval_expr(context, &right)?;
@ -80,22 +88,25 @@ fn eval_binary_expr(
TokenKind::Minus => left - right, TokenKind::Minus => left - right,
TokenKind::Star => left * right, TokenKind::Star => left * right,
TokenKind::Slash => left / right, TokenKind::Slash => left / right,
TokenKind::Power => left.powf(right), TokenKind::Power => left.pow(right),
_ => 0f64, _ => 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(); let expr_value = eval_expr(context, &expr)?.clone();
match op { match op {
TokenKind::Minus => Ok(-expr_value), 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.")), _ => 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 x = eval_expr(context, &expr);
let unit = kind.to_unit()?; 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::Degrees => Ok(x?.to_radians()),
Unit::Radians => Ok(x?.to_degrees()), 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 there is a constant with this name, return a literal expression with its value
if let Some(value) = prelude::CONSTANTS.get(identifier) { if let Some(value) = prelude::CONSTANTS.get(identifier) {
return eval_expr(context, &Expr::Literal(value.to_string())); 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> { fn eval_literal_expr(context: &mut Context, value: &str) -> Result<Float, String> {
match value.parse() { match Float::parse(value) {
Ok(parsed_value) => Ok(parsed_value), Ok(parsed_value) => Ok(Float::with_val(context.precision, parsed_value)),
Err(_) => Err(format!("Invalid number literal: '{}'.", 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) eval_expr(context, expr)
} }
@ -143,7 +156,7 @@ fn eval_fn_call_expr(
context: &mut Context, context: &mut Context,
identifier: &str, identifier: &str,
expressions: &Vec<Expr>, expressions: &Vec<Expr>,
) -> Result<f64, String> { ) -> Result<Float, String> {
// Prelude // Prelude
let prelude_func = match expressions.len() { let prelude_func = match expressions.len() {
1 => { 1 => {
@ -164,7 +177,7 @@ fn eval_fn_call_expr(
// Special functions // Special functions
match identifier { match identifier {
"sum" => { "sum" | "Σ" => {
// Make sure exactly 3 arguments were supplied. // Make sure exactly 3 arguments were supplied.
if expressions.len() != 3 { if expressions.len() != 3 {
return Err(format!( return Err(format!(
@ -173,9 +186,9 @@ fn eval_fn_call_expr(
)); ));
} }
let start = eval_expr(context, &expressions[0])? as i32; let start = eval_expr(context, &expressions[0])?.to_f64() as i128;
let end = eval_expr(context, &expressions[1])? as i32; let end = eval_expr(context, &expressions[1])?.to_f64() as i128;
let mut sum = 0f64; let mut sum = Float::with_val(context.precision, 0);
for n in start..=end { for n in start..=end {
let n_expr = Expr::Literal(String::from(n.to_string())); let n_expr = Expr::Literal(String::from(n.to_string()));

View File

@ -51,7 +51,7 @@ impl<'a> Lexer<'a> {
// If there isn't already an EOF token, add it. // If there isn't already an EOF token, add it.
if let TokenKind::EOF = tokens.last().unwrap().kind { if let TokenKind::EOF = tokens.last().unwrap().kind {
} else { } else {
tokens.push(lexer.build(TokenKind::EOF, "")); tokens.push(build(TokenKind::EOF, ""));
} }
tokens tokens
@ -64,7 +64,7 @@ impl<'a> Lexer<'a> {
self.advance(); self.advance();
if self.is_at_end() { if self.is_at_end() {
return self.build(TokenKind::EOF, ""); return build(TokenKind::EOF, "");
} else { } else {
c = self.peek(); c = self.peek();
} }
@ -73,47 +73,47 @@ impl<'a> Lexer<'a> {
let token = match c { let token = match c {
'+' => { '+' => {
self.advance(); self.advance();
self.build(TokenKind::Plus, "") build(TokenKind::Plus, "")
} }
'-' => { '-' => {
self.advance(); self.advance();
self.build(TokenKind::Minus, "") build(TokenKind::Minus, "")
} }
'*' => { '*' => {
self.advance(); self.advance();
self.build(TokenKind::Star, "") build(TokenKind::Star, "")
} }
'/' => { '/' => {
self.advance(); self.advance();
self.build(TokenKind::Slash, "") build(TokenKind::Slash, "")
} }
'^' => { '^' => {
self.advance(); self.advance();
self.build(TokenKind::Power, "") build(TokenKind::Power, "")
} }
'(' => { '(' => {
self.advance(); self.advance();
self.build(TokenKind::OpenParenthesis, "") build(TokenKind::OpenParenthesis, "")
} }
')' => { ')' => {
self.advance(); self.advance();
self.build(TokenKind::ClosedParenthesis, "") build(TokenKind::ClosedParenthesis, "")
} }
'|' => { '|' => {
self.advance(); self.advance();
self.build(TokenKind::Pipe, "") build(TokenKind::Pipe, "")
} }
'=' => { '=' => {
self.advance(); self.advance();
self.build(TokenKind::Equals, "") build(TokenKind::Equals, "")
} }
'!' => { '!' => {
self.advance(); self.advance();
self.build(TokenKind::Exclamation, "") build(TokenKind::Exclamation, "")
} }
',' => { ',' => {
self.advance(); self.advance();
self.build(TokenKind::Comma, "") build(TokenKind::Comma, "")
} }
_ => { _ => {
if c.is_digit(10) { if c.is_digit(10) {
@ -122,7 +122,7 @@ impl<'a> Lexer<'a> {
self.next_identifier() self.next_identifier()
} else { } else {
self.advance(); 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]) { if let Ok(value) = str::from_utf8(&self.source[start..end]) {
self.build(TokenKind::Literal, value) build(TokenKind::Literal, value)
} else { } else {
self.build(TokenKind::Unknown, "") build(TokenKind::Unknown, "")
} }
} }
@ -162,16 +162,9 @@ impl<'a> Lexer<'a> {
_ => TokenKind::Identifier, _ => TokenKind::Identifier,
}; };
self.build(kind, value) build(kind, value)
} else { } else {
self.build(TokenKind::Unknown, "") build(TokenKind::Unknown, "")
}
}
fn build(&self, kind: TokenKind, value: &str) -> Token {
Token {
kind,
value: value.to_string(),
} }
} }
@ -188,6 +181,13 @@ impl<'a> Lexer<'a> {
} }
} }
fn is_valid_identifier(c: char) -> bool { fn build(kind: TokenKind, value: &str) -> Token {
c.is_alphabetic() || c == '°' || c == '√' || c == '\'' || c == '¨' Token {
kind,
value: value.to_string(),
}
}
fn is_valid_identifier(c: char) -> bool {
c.is_alphabetic() || c == '°' || c == '√' || c == '\'' || c == '¨' || c == 'Σ'
} }

View File

@ -48,8 +48,14 @@ fn eval_repl(parser: &mut parser::Context, input: &str) {
} }
fn eval(parser: &mut parser::Context, input: &str) { fn eval(parser: &mut parser::Context, input: &str) {
match parser::parse(parser, input, get_angle_unit()) { match parser::parse(parser, input, get_angle_unit(), 53) {
Ok(Some(result)) => println!("{}", result), Ok(Some(result)) => {
if result.clone().fract() == 0 {
println!("{}", result.to_integer().unwrap());
} else {
println!("{}", result);
}
}
Ok(None) => print!(""), Ok(None) => print!(""),
Err(err) => println!("{}", Red.paint(err)), Err(err) => println!("{}", Red.paint(err)),
} }

View File

@ -4,6 +4,7 @@ use crate::{
lexer::{Lexer, Token, TokenKind}, lexer::{Lexer, Token, TokenKind},
symbol_table::SymbolTable, symbol_table::SymbolTable,
}; };
use rug::Float;
pub struct Context { pub struct Context {
//angle_unit: Unit, //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.tokens = Lexer::lex(input);
context.pos = 0; 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) { while !is_at_end(context) {
statements.push(parse_stmt(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) interpreter.interpret(statements)
} }

View File

@ -1,3 +1,4 @@
use rug::Float;
use FuncType::*; use FuncType::*;
pub const CONSTANTS: phf::Map<&'static str, &'static str> = phf::phf_map! { pub const CONSTANTS: phf::Map<&'static str, &'static str> = phf::phf_map! {
@ -66,12 +67,12 @@ enum FuncType {
} }
// Unary functions // 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 { impl UnaryFuncInfo {
fn call(&self, x: f64, angle_unit: &Unit) -> f64 { fn call(&self, x: Float, angle_unit: &Unit) -> Float {
let func = self.0; let func = self.0;
match self.1 { match self.1 {
FuncType::Trig => func(from_angle_unit(x, angle_unit)), FuncType::Trig => func(from_angle_unit(x, angle_unit)),
@ -82,7 +83,7 @@ impl UnaryFuncInfo {
} }
impl BinaryFuncInfo { 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; let func = self.0;
match self.1 { match self.1 {
FuncType::Trig => func( 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) { if let Some(func_info) = UNARY_FUNCS.get(name) {
Some(func_info.call(x, &angle_unit)) Some(func_info.call(x, &angle_unit))
} else { } 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) { if let Some(func_info) = BINARY_FUNCS.get(name) {
Some(func_info.call(x, y, angle_unit)) Some(func_info.call(x, y, angle_unit))
} else { } 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 { match angle_unit {
Unit::Radians => x, 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 { match angle_unit {
Unit::Radians => x, Unit::Radians => x,
Unit::Degrees => x.to_radians(), Unit::Degrees => special_funcs::to_radians(x),
} }
} }
pub mod special_funcs { pub mod special_funcs {
pub fn factorial(x: i32) -> i32 { use rug::Float;
let mut value = 1;
for i in 1..=x {
value *= i;
}
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 { mod funcs {
pub fn abs(x: f64) -> f64 { use rug::ops::Pow;
use rug::Float;
pub fn abs(x: Float) -> Float {
x.abs() x.abs()
} }
pub fn acos(x: f64) -> f64 { pub fn acos(x: Float) -> Float {
x.acos() x.acos()
} }
pub fn acosh(x: f64) -> f64 { pub fn acosh(x: Float) -> Float {
x.acosh() x.acosh()
} }
pub fn acot(x: f64) -> f64 { pub fn acot(x: Float) -> Float {
(1f64 / x).atan() (1f64 / x).atan()
} }
pub fn acoth(x: f64) -> f64 { pub fn acoth(x: Float) -> Float {
(1f64 / x).atanh() (1f64 / x).atanh()
} }
pub fn acosec(x: f64) -> f64 { pub fn acosec(x: Float) -> Float {
(1f64 / x).asin() (1f64 / x).asin()
} }
pub fn acosech(x: f64) -> f64 { pub fn acosech(x: Float) -> Float {
(1f64 / x).asinh() (1f64 / x).asinh()
} }
pub fn asec(x: f64) -> f64 { pub fn asec(x: Float) -> Float {
(1f64 / x).acos() (1f64 / x).acos()
} }
pub fn asech(x: f64) -> f64 { pub fn asech(x: Float) -> Float {
(1f64 / x).acosh() (1f64 / x).acosh()
} }
pub fn asin(x: f64) -> f64 { pub fn asin(x: Float) -> Float {
x.asin() x.asin()
} }
pub fn asinh(x: f64) -> f64 { pub fn asinh(x: Float) -> Float {
x.asinh() x.asinh()
} }
pub fn atan(x: f64) -> f64 { pub fn atan(x: Float) -> Float {
x.atan() x.atan()
} }
pub fn atanh(x: f64) -> f64 { pub fn atanh(x: Float) -> Float {
x.atanh() x.atanh()
} }
pub fn cbrt(x: f64) -> f64 { pub fn cbrt(x: Float) -> Float {
x.cbrt() x.cbrt()
} }
pub fn ceil(x: f64) -> f64 { pub fn ceil(x: Float) -> Float {
x.ceil() x.ceil()
} }
pub fn cos(x: f64) -> f64 { pub fn cos(x: Float) -> Float {
x.cos() x.cos()
} }
pub fn cosh(x: f64) -> f64 { pub fn cosh(x: Float) -> Float {
x.cos() x.cos()
} }
pub fn cosec(x: f64) -> f64 { pub fn cosec(x: Float) -> Float {
1f64 / x.sin() 1f64 / x.sin()
} }
pub fn cosech(x: f64) -> f64 { pub fn cosech(x: Float) -> Float {
1f64 / x.sinh() 1f64 / x.sinh()
} }
pub fn cot(x: f64) -> f64 { pub fn cot(x: Float) -> Float {
x.cos() / x.sin() x.clone().cos() / x.sin()
} }
pub fn coth(x: f64) -> f64 { pub fn coth(x: Float) -> Float {
x.cosh() / x.sinh() x.clone().cosh() / x.sinh()
} }
pub fn exp(x: f64) -> f64 { pub fn exp(x: Float) -> Float {
x.exp() x.exp()
} }
pub fn floor(x: f64) -> f64 { pub fn floor(x: Float) -> Float {
x.floor() x.floor()
} }
pub fn frac(x: f64) -> f64 { pub fn frac(x: Float) -> Float {
x.fract() x.fract()
} }
pub fn hyp(x: f64, y: f64) -> f64 { pub fn hyp(x: Float, y: Float) -> Float {
x.hypot(y) x.hypot(&y)
} }
pub fn log(x: f64) -> f64 { pub fn log(x: Float) -> Float {
x.log(10f64) x.log10()
} }
pub fn logx(x: f64, y: f64) -> f64 { pub fn logx(x: Float, y: Float) -> Float {
x.log(y) x.log10() / y.log10()
} }
pub fn ln(x: f64) -> f64 { pub fn ln(x: Float) -> Float {
x.ln() x.ln()
} }
pub fn max(x: f64, y: f64) -> f64 { pub fn max(x: Float, y: Float) -> Float {
x.max(y) x.max(&y)
} }
pub fn min(x: f64, y: f64) -> f64 { pub fn min(x: Float, y: Float) -> Float {
x.min(y) x.min(&y)
} }
pub fn round(x: f64) -> f64 { pub fn round(x: Float) -> Float {
x.round() x.round()
} }
pub fn sec(x: f64) -> f64 { pub fn sec(x: Float) -> Float {
1f64 / x.cos() 1f64 / x.cos()
} }
pub fn sech(x: f64) -> f64 { pub fn sech(x: Float) -> Float {
1f64 / x.cosh() 1f64 / x.cosh()
} }
pub fn sin(x: f64) -> f64 { pub fn sin(x: Float) -> Float {
x.sin() x.sin()
} }
pub fn sinh(x: f64) -> f64 { pub fn sinh(x: Float) -> Float {
x.sinh() x.sinh()
} }
pub fn sqrt(x: f64) -> f64 { pub fn sqrt(x: Float) -> Float {
x.sqrt() x.sqrt()
} }
pub fn nth_sqrt(x: f64, n: f64) -> f64 { pub fn nth_sqrt(x: Float, n: Float) -> Float {
x.powf(1f64 / n) x.pow(Float::with_val(1, 1) / n)
} }
pub fn tan(x: f64) -> f64 { pub fn tan(x: Float) -> Float {
x.tan() x.tan()
} }
pub fn tanh(x: f64) -> f64 { pub fn tanh(x: Float) -> Float {
x.tanh() x.tanh()
} }
pub fn trunc(x: f64) -> f64 { pub fn trunc(x: Float) -> Float {
x.trunc() x.trunc()
} }
} }