mirror of
https://github.com/perlbot/perlbuut
synced 2025-06-08 11:25:40 -04:00
453 lines
16 KiB
Perl
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;
|