1
0
Fork 0
mirror of https://github.com/perlbot/perlbuut synced 2025-06-08 09:35:40 -04:00
perlbuut/deps/Math/Farnsworth/Functions/StdMath.pm
2009-12-05 00:02:04 -05:00

453 lines
16 KiB
Perl

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;