package Math::Farnsworth::Functions::StdMath; use strict; use warnings; use Math::Pari; use Data::Dumper; use Math::Farnsworth::Value::Pari; use Math::Farnsworth::Value::Array; use Math::Farnsworth::Value::Lambda; use Math::Farnsworth::Value::Boolean; sub init { my $env = shift; my $array = new Math::Farnsworth::Value::Array([]); my $string = new Math::Farnsworth::Value::String(""); my $lambda = new Math::Farnsworth::Value::Lambda(); my $number = new Math::Farnsworth::Value::Pari(0); $env->{funcs}->addfunc("ln", [["in", undef, $number, 0]],\&log,$env); $env->eval("log{x isa 1} := {ln[x]/ln[10]}"); $env->{funcs}->addfunc("sin", [["in", undef, $number, 0]],\&sin,$env); $env->{funcs}->addfunc("cos", [["in", undef, $number, 0]],\&cos,$env); $env->{funcs}->addfunc("tan", [["in", undef, $number, 0]],\&tan,$env); $env->eval("csc{x isa 1} := {1/sin[x]}"); $env->eval("sec{x isa 1} := {1/cos[x]}"); $env->eval("cot{x isa 1} := {1/tan[x]}"); $env->eval("atan2{x isa 1,y isa 1} := {var s=x^2+y^2; var r=y+x i; -i * ln[r / sqrt[s]]}"); $env->{funcs}->addfunc("sinh", [["in", undef, $number, 0]],\&sinh,$env); $env->{funcs}->addfunc("cosh", [["in", undef, $number, 0]],\&cosh,$env); $env->{funcs}->addfunc("tanh", [["in", undef, $number, 0]],\&tanh,$env); $env->{funcs}->addfunc("arcsin", [["in", undef, $number, 0]],\&arcsin,$env); $env->{funcs}->addfunc("arccos", [["in", undef, $number, 0]],\&arccos,$env); $env->{funcs}->addfunc("arctan", [["in", undef, $number, 0]],\&arctan,$env); $env->{funcs}->addfunc("arcsinh", [["in", undef, $number, 0]],\&arcsinh,$env); $env->{funcs}->addfunc("arccosh", [["in", undef, $number, 0]],\&arccosh,$env); $env->{funcs}->addfunc("arctanh", [["in", undef, $number, 0]],\&arctanh,$env); $env->{funcs}->addfunc("asin", [["in", undef, $number, 0]],\&arcsin,$env); $env->{funcs}->addfunc("acos", [["in", undef, $number, 0]],\&arccos,$env); $env->{funcs}->addfunc("atan", [["in", undef, $number, 0]],\&arctan,$env); $env->{funcs}->addfunc("asinh", [["in", undef, $number, 0]],\&arcsinh,$env); $env->{funcs}->addfunc("acosh", [["in", undef, $number, 0]],\&arccosh,$env); $env->{funcs}->addfunc("atanh", [["in", undef, $number, 0]],\&arctanh,$env); $env->{funcs}->addfunc("abs", [["in", undef, undef, 0]],\&abs,$env); $env->{funcs}->addfunc("floor", [["in", undef, undef, 0]],\&floor,$env); $env->{funcs}->addfunc("ceil", [["in", undef, undef, 0]],\&ceil,$env); $env->{funcs}->addfunc("int", [["in", undef, undef, 0]],\&int,$env); $env->{funcs}->addfunc("rint", [["in", undef, undef, 0]],\&rint,$env); $env->eval("round{x, d isa 1} := {var m = x * 10 ** d; rint[m] * 10 ** -d+0.0};"); $env->{funcs}->addfunc("trunc", [["in", undef, undef, 0]],\&int,$env); $env->{funcs}->addfunc("numerator", [["in", undef, $number, 0]],\&numerator,$env); $env->{funcs}->addfunc("denominator", [["in", undef, $number, 0]],\&denominator,$env); $env->{funcs}->addfunc("real", [["in", undef, $number, 0]],\&real,$env); $env->{funcs}->addfunc("imag", [["in", undef, $number, 0]],\&imag,$env); $env->eval("imaginary{x isa 1} := imag[x]"); $env->{funcs}->addfunc("conj", [["in", undef, $number, 0]],\&conj,$env); $env->{funcs}->addfunc("norm", [["in", undef, $number, 0]],\&norm,$env); $env->{funcs}->addfunc("isprime", [["in", undef, $number, 0]],\&isprime,$env); $env->{funcs}->addfunc("prime", [["in", undef, $number, 0]],\&prime,$env); $env->{funcs}->addfunc("precprime", [["in", undef, $number, 0]],\&precprime,$env); $env->{funcs}->addfunc("nextprime", [["in", undef, $number, 0]],\&nextprime,$env); $env->{funcs}->addfunc("factor", [["in", undef, $number, 0]],\&factor,$env); $env->{funcs}->addfunc("randmax", [["in", undef, $number, 0]],\&randmax,$env); $env->{funcs}->addfunc("getrseed", [[]],\&getrseed,$env); $env->{funcs}->addfunc("setrseed", [[]],\&setrseed,$env); $env->eval("random{} := randmax[10**30]/10.0**30"); $env->eval("quad{a isa 1, b isa 1, c isa 1} := [(-b + sqrt[b^2 - 4 a c]) / 2a, (-b - sqrt[b^2 - 4 a c]) / 2a]"); $env->eval("quadratic{a, b, c} := quad[a,b,c]"); $env->{funcs}->addfunc("gcd", [["left", undef, $number, 0],["right", undef, $number, 0]],\&gcd,$env); $env->{funcs}->addfunc("lcm", [["left", undef, $number, 0],["right", undef, $number, 0]],\&lcm,$env); #these functions are simple enough to implement in farnsworth itself, so why not $env->{funcs}->addfunc("sqrt", [["in", undef, undef, 0]],\&sqrt,$env); #putting in like this to see if it brings better luck $env->eval("i := sqrt[-1]"); #since we have a better sqrt, use it to make a better i # $env->eval("sqrt{x} := {x ^ 0.5}"); $env->eval("exp{x isa 1} := {e ^ x}"); $env->eval("inv{x} := {1/x}"); $env->eval("recip{x} := {1/x}"); #$env->eval("_tohex{x isa 1} := { if(x < 16) { substrLen[\"0123456789abcdef\", x, 1] } else { _tohex[floor[x/16]] + _tohex[x%16] } }; tohex{x isa 1} := {\"0x\"+_tohex[x]}"); } sub sqrt { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too my $units = $input->getdimen(); $units = $units->mult(PARI '1/2'); #half them all! return Math::Farnsworth::Value::Pari->new(Math::Pari::sqrt($input->getpari()), $units); } sub sin { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::sin($input->getpari())); } sub cos { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::cos($input->getpari())); } sub tan { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::tan($input->getpari())); } sub arcsin { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::asin($input->getpari())); } sub arccos { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::acos($input->getpari())); } sub arctan { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::atan($input->getpari())); } sub sinh { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::sinh($input->getpari())); } sub cosh { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::cosh($input->getpari())); } sub tanh { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::tanh($input->getpari())); } sub arcsinh { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::asinh($input->getpari())); } sub arccosh { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::acosh($input->getpari())); } sub arctanh { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::atanh($input->getpari())); } sub abs { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::abs($input->getpari()), $input->getdimen()); } sub floor { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::floor($input->getpari()), $input->getdimen()); } sub ceil { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::ceil($input->getpari()), $input->getdimen()); } sub int { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too my $e = PARI '0'; my $r = Math::Farnsworth::Value::Pari->new(Math::Pari::truncate($input->getpari(),$e), $input->getdimen()); print Data::Dumper->Dump([$r], ["\$r"]); return $r; } sub numerator { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too #bug? should i make it pull the positive dimensions? return Math::Farnsworth::Value::Pari->new(Math::Pari::numerator($input->getpari())); } sub denominator { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too #bug? should i make it pull the negative dimensions? return Math::Farnsworth::Value::Pari->new(Math::Pari::denominator($input->getpari())); } sub real { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::real($input->getpari()), $input->getdimen()); } sub imag { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::imag($input->getpari()), $input->getdimen()); } sub conj { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::conj($input->getpari()), $input->getdimen()); } sub norm { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::norm($input->getpari()), $input->getdimen()); } sub isprime { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Boolean->new(Math::Pari::isprime($input->getpari())); } sub prime { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::prime($input->getpari())); } sub nextprime { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::nextprime($input->getpari())); } sub precprime { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::precprime($input->getpari())); } sub factor { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::factor($input->getpari())); } sub randmax { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::random($input->getpari())); } sub setrseed { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too my $oldseed = Math::Pari::getrand(); Math::Pari::setrand($input->getpari()); return Math::Farnsworth::Value::Pari->new($oldseed); } sub getrseed { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; return Math::Farnsworth::Value::Pari->new(Math::Pari::getrand()); } sub rint { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too #die "Argument to rint[] is not a numeric value" unless $input->isPARI(); my $e = PARI '0'; return Math::Farnsworth::Value::Pari->new(Math::Pari::round($input->getpari(), $e), $input->getdimen()); } sub gcd { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $left = $eval->{vars}->getvar("left"); #i should clean this up more too my $right = $eval->{vars}->getvar("right"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::gcd($left->getpari(), $right->getpari())); } sub lcm { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $left = $eval->{vars}->getvar("left"); #i should clean this up more too my $right = $eval->{vars}->getvar("right"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::lcm($left->getpari(), $right->getpari())); } sub log { #with an array we give the number of elements, with a string we give the length of the string my ($args, $eval, $branches)= @_; my $input = $eval->{vars}->getvar("in"); #i should clean this up more too return Math::Farnsworth::Value::Pari->new(Math::Pari::log($input->getpari())); } 1;