# Simple math library in Rust

So, I've tried to make a simple math library in Rust. What do you think about it?

const PRECISION: f64=512.; //Balance between speed and precision here.

fn ln(x:f64) -> f64 {
let mut sum=0.;
let epsilon=(x-1.)/(5.*PRECISION);
let mut i=1.;
while (epsilon>0. && i<x) || (epsilon<0. && i>x) {
sum+=epsilon/i;
i+=epsilon;
}
sum
}

fn exp(x:f64) -> f64 {
let mut i=0.;
let mut y=1.;
let epsilon=x/PRECISION;
while (epsilon>0. && i<x) || (epsilon<0. && i>x) {
y+=epsilon*y;
i+=epsilon;
}
y
}

fn arctan(x:f64) -> f64 {
let mut sum=0.;
let epsilon=x/PRECISION;
let mut i=0.;
while i<x {
sum+=epsilon/(1.+i*i);
i+=epsilon;
}
sum*(180./pi())
}

fn tan(degrees:f64) -> f64 {
sin(degrees)/cos(degrees)
}

fn sin(degrees:f64) -> f64 {
if degrees<0. {
return -sin(-degrees);
}
if degrees>90. {
return cos(degrees-90.);
}
let mut tmpsin=0.;
let mut tmpcos=1.;
let mut i=0.;
tmpsin+=epsilon*tmpcos;
tmpcos-=epsilon*tmpsin;
i+=epsilon;
}
tmpsin
}

fn arcsin(x:f64) -> f64 {
arctan(x/sqrt(1.-x*x))
}

fn arccos(x:f64) -> f64 {
90.-arcsin(x)
}

fn cos(degrees:f64) -> f64 {
sin(90.-degrees)
}

fn sqrt(x:f64) -> f64 {
let mut max=1000.;
let mut min=0.;
let mut i=(min+max)/2.;
while (max-min)>1./PRECISION {
if i*i>x {
max=i;
}
else {
min=i;
}
i=(max+min)/2.;
}
i
}

fn pi() -> f64 {
let mut sum=0.;
let mut i=-1.;
let epsilon=1./PRECISION;
while i<1. {
sum+=epsilon/(1.+i*i);
i+=epsilon;
}
2.*sum
}

fn main() {
println!("x\tsin(x)\tcos(x)\ttan(x)\tln(x)\tsqrt(x)\tasin\tacos\tatan");
for i in 0..101 {
print!("{:.4}\t",i);
print!("{:.4}\t",sin(i as f64));
print!("{:.4}\t",cos(i as f64));
if tan(i as f64)<100. && tan(i as f64)> -10. {
print!("{:.4}\t",tan(i as f64));
}
else if tan(i as f64)< -10. {
print!("{:.3}\t",tan(i as f64));
}
else {
print!("inf\t");
}
if ln(i as f64)> -100. {
print!("{:.4}\t",ln(i as f64));
}
else {
print!("-inf\t");
}
print!("{:.4}\t",sqrt(i as f64));
if arcsin((i as f64)/100.)<90. {
print!("{:.4}\t",arcsin((i as f64)/100.));
}
else {
print!("90\t");
}
if arccos((i as f64)/100.)<90. && arccos((i as f64)/100.)>0. {
print!("{:.4}\t",arccos((i as f64)/100.));
}
else if arccos((i as f64)/100.)>0. {
print!("90\t");
}
else {
print!("0\t");
}
print!("{:.4}\n",arctan((i as f64)/100.));
}
println!("pi={:.4}",pi());
println!("ln(1/pi)={:.4}",ln(1./pi()));
println!("e={:.4}",exp(1 as f64));
println!("1/e={:.4}",exp(-1 as f64));
}


I'm not too familiar with the math side of this, so I'll just focus on the Rust part.

# Run rustfmt

Running cargo fmt will autoformat your code to the Rust best practices. For example, it will convert

fn arctan(x:f64) -> f64 {
let mut sum=0.;
let epsilon=x/PRECISION;
let mut i=0.;
while i<x {
sum+=epsilon/(1.+i*i);
i+=epsilon;
}
sum*(180./pi())
}


to

fn arctan(x: f64) -> f64 {
let mut sum = 0.;
let epsilon = x / PRECISION;
let mut i = 0.;
while i < x {
sum += epsilon / (1. + i * i);
i += epsilon;
}
sum * (180. / pi())
}


# Run clippy

Running cargo clippy will point out a few common mistakes. Let's take a look at them here.

warning: using print!() with a format string that ends in a single newline
--> src/main.rs:136:9
|
136 |         print!("{:.4}\n",arctan((i as f64)/100.));
|         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(clippy::print_with_newline)] on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#print_with_newline
help: use println! instead
|
136 |         println!("{:.4}",arctan((i as f64)/100.));
|         ^^^^^^^


As it suggests, you should replace that line with println!.

warning: casting integer literal to f64 is unnecessary
--> src/main.rs:141:28
|
141 |     println!("e={:.4}",exp(1 as f64));
|                            ^^^^^^^^ help: try: 1_f64
|
= note: #[warn(clippy::unnecessary_cast)] on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast


That, and the line that follows it, can be used as a float like you do everywhere else in your code. You can do 1_f64, 1f64, 1.0, or like elsewhere in your code, 1..

# Extract repeated operations

When you print things out, you repeat the calculation a lot, and it actually appears to have a difference in assembly (although not when #[inline(never)] is used on ln?). So instead of

if arccos((i as f64) / 100.) < 90. && arccos((i as f64) / 100.) > 0. {
print!("{:.4}\t", arccos((i as f64) / 100.));
} else if arccos((i as f64) / 100.) > 0. {
print!("90\t");
} else {
print!("0\t");
}


Prefer

let inv_cos = arccos((i as f64) / 100.);
if inv_cos < 90. && inv_cos > 0. {
print!("{:.4}\t", inv_cos);
} else if inv_cos > 0. {
print!("90\t");
} else {
print!("0\t");
}