# math for DCT, by Shiar

# 1.10.4 200410282330 - trig functions from basic menu
# 1.10.3 200410152245 - rnd, atan, pi
#                     - trigonometry functions seperated
# 1.10.2 200410132050 - probability functions: comb, perm, rdz
# 1.10.1 200410112340 - adds menu items via addmenu() call
# 1.09.2 200410112050 - functions don't handle stack themselves,
#                       but behave like real functions
# 1.09.1 200410022255 - moved from 1.9 main

#todo: check for errors, eg division by zero

use strict;
use warnings;
use utf8;

%action = (
	%action,

	'+'    => [2, sub { $_[1] + $_[0] }], # addition
	'-'    => [2, sub { $_[1] - $_[0] }], # substraction
	'*'    => [2, sub { $_[1] * $_[0] }], # multiplication
	'/'    => [2, sub { $_[1] / $_[0] }], # division
	'mod'  => [2, sub { $_[1] % $_[0] }], # modulo

	'inv'  => [1, sub { 1 / $_[0] }], # 1/x
	'sqrt' => [1, sub { sqrt $_[0] }], # square root
	'sq'   => [1, sub { $_[0] * $_[0] }], # squared
	'^'    => [2, sub { $_[1] ** $_[0] }], # exponentiation
	'xroot'=> [2, sub { $_[1] ** (1/$_[0]) }], # x-root of y

	# logarithmic
	'log'  => [1, sub { log($_[0]) / log(10) }], # logarithm
	'alog' => [1, sub { 10 ** $_[0] }], # 10^x
	'ln'   => [1, sub { log $_[0] }], # natural logaritm
	'lnp1' => [1, sub { log($_[0] + 1) }], # ln(x+1)
	'exp'  => [1, sub { exp $_[0] }], # e^x
	'expm' => [1, sub { exp($_[0]) - 1 }], # exp(x)-1

	# binary
	'and'  => [2, sub { $_[1] & $_[0] }], # bitwise and
	'or'   => [2, sub { $_[1] | $_[0] }], # bitwise or
	'xor'  => [2, sub { $_[1] ^ $_[0] }], # bitwise xor
	'not'  => [2, sub { ~$_[0] }], # bitwise not
	'sl'   => [1, sub { $_[0] * 2 }], # shift left
	'sr'   => [1, sub { $_[0] / 2 }], # shift right

	# unclassified
	'%'    => [2, sub { $_[0] / $_[1] }], # percentage
#	'%ch'  => [2, sub { $val{i} = 100*(shift(@_)-$val{i})/$val{i} }], # percentage change
#	'%t'   => [2, sub { $val{i} = 100*$val{i}/shift(@_) }], # percentage total

	'abs'  => [1, sub { abs $_[0] }], # absolute
	'sign' => [1, sub { $_[0] <=> 0 }], # sign
	'ip'   => [1, sub { int $_[0] }], # integer part
	'fp'   => [1, sub { $_[0] - int $_[0] }], # fractional part

	'rnd'  => [1, sub { sprintf "%.0f", $_[0] }], # round
#	'trnc' => [1, sub { local $_ = 10**$_[0]; $val{i} = int($val{i}*$_)/$_ }], # truncate
	'floor'=> [1, sub { int $_[0] }], # floor
	'ceil' => [1, sub { int $_[0]+.9999 }], # ceil

	'min'  => [2, sub { $_[1]<$_[0] ? $_[1] : $_[0] }], # minimum
	'max'  => [2, sub { $_[1]>$_[0] ? $_[1] : $_[0] }], # maximum

	# number base
	'dec'  => [-1, sub { $::set{base} = 10; () }], # decimal
	'bin'  => [-1, sub { $::set{base} = 2; () }], # binary
	'oct'  => [-1, sub { $::set{base} = 8; () }], # octal
	'hex'  => [-1, sub { $::set{base} = 16; () }], # hexadecimal
	'base' => [1, sub { $::set{base} = $_[0]; () }], # alphanumerical

	# probability
	'comb' => [2, sub {
		my $res = 1;
		$res *= $_ for $_[1]-$_[0]+1..$_[1];  # (n-r+1)..(n-2)(n-1)n
		$res /= $_ for 2..$_[0];  # / r!
		$res;  # n!/(r!(n-r)!)
	}], # combinations
	'perm' => [2, sub {
		my $res = 1;
		$res *= $_ for $_[1]-$_[0]+1..$_[1];  # (n-r+1)..(n-2)(n-1)n
		$res;  # n!/(n-r)!
	}], # permutations
	'!'    => [1, sub { my $res = $_[0]; $res *= $_ for 2..$res-1; $res }], # factor
	'rand' => [0, sub { rand }], # random value <1
	'rdz'  => [1, sub { srand $_[0]; () }], # seed randomizer
#	'ndist'=> [3], # normal distribution
#	'utpn' => [3], # normal distribution
#	'utpt' => [1], # student-t distribution
#	'utpc' => [2], # chi-square (χ²) distribution
#	'utpf' => [3], # F distribution
); # newaction

addmenu(["main", 0], "math",
	[qw(basic sq sqrt ^ xroot log alog ln exp)],
#	[qw(vector)],
#	[qw(matrix)],
#	[qw(list)],
#	[qw(hyperbolic sinh cosh tanh asinh acosh atanh expm lnp1)],
	[qw(real % %ch %t min max mod abs sign mant xpon ip fp rnd trnc floor ceil r>d d>r)],
	[qw(base dec bin oct hex),
		[qw(logic and or xor not)],
		[qw(bit rl sl asr sr rr)],
#		[qw(byte rlb slb srb rrb)],
	], # base
	[qw(probability comb perm ! rand rdz)], # utpc utpf utpn utpt ndist)],
#	[qw(fft)],
#	[qw(complex)],
#	[qw(constants)],
) if defined &addmenu; # addmenu

return {
	author  => "Shiar",
	title   => "basic math",
	version => "1.10.4",
};

