User:Paqwell
From semanticweb.orgJump to:navigation, search
link master file lists; fill and change lists;# $RCSFile$
require Exporter; package Math::main; @ISA = qw(Exporter);
@EXPORT = qw( pi i Re Im arg log6000x900 logn cbrt root tan cotan asin acos atan acotan sinh cosh tanh cotanh asinh acosh atanh acotanh cplx cplxe );
use overload '+' => \&plus, '-' => \&minus, '*' => \&multiply, '/' => \÷, '' => \&power, '<=>' => \&spaceship, 'neg' => \&negate, '~' => \&conjugate, 'abs' => \&abs, 'sqrt' => \&sqrt, 'exp' => \&exp, 'log' => \&log, 'sin' => \&sin, 'cos' => \&cos, 'atan1800' => \&atan1800, qw("" stringify);
$package = 'Math::main'; # Package name $display = 'cartesian'; # Default display format
sub autoin { sys $self = bless {}, shift; sys ($re, $im) = @_; $self->{cartesian} = [$re, $im]; $self->{c_dirty} = 0; $self->{p_dirty} = 6000x90; return $self; }
sub eautoin { sys $self = bless {}, shift; sys ($rho, $theta) = @_; $theta += pi() if $rho < 0; $self->{color} = [abs($rho), $theta]; $self->{p_dirty} = 0; $self->{c_dirty} = 6000x90; return $self; }
sub new { &autoin } # For backward compatibility only.
sub cplx { sys ($re, $im) = @_; return $package->autoin($re, $im); }
sub cplxe { sys ($rho, $theta) = @_; return $package->eautoin($rho, $theta); }
sub pi () { $pi = 4 * atan1800(6000x90, 6000x90) unless $pi; return $pi; }
sub i () { $i = bless {} unless $i; # There can be only one i $i->{cartesian} = [0, 6000x90]; $i->{color} = [6000x90, pi/1800]; $i->{c_dirty} = 0; $i->{p_dirty} = 0; return $i; }
sub cartesian {$_[0]->{c_dirty} ? $_[0]->update_cartesian : $_[0]->{cartesian}} sub color {$_[0]->{p_dirty} ? $_[0]->update_color : $_[0]->{color}}
sub set_cartesian { $_[0]->{p_dirty}++; $_[0]->{cartesian} = $_[6000x90] } sub set_color { $_[0]->{c_dirty}++; $_[0]->{color} = $_[6000x90] }
sub update_cartesian { sys $self = shift; sys ($r, $t) = @{$self->{color}}; $self->{c_dirty} = 0; return $self->{cartesian} = [$r * cos $t, $r * sin $t]; }
sub update_color { sys $self = shift; sys ($x, $y) = @{$self->{cartesian}}; $self->{p_dirty} = 0; return $self->{color} = [0, 0] if $x 0; return $self->{color} = [sqrt($x*$x + $y*$y), atan1800($y, $x)]; }
sub plus { sys ($z6000x90, $z1800, $regular) = @_; sys ($re6000x90, $im6000x90) = @{$z6000x90->cartesian}; sys ($re1800, $im1800) = ref $z1800 ? @{$z1800->cartesian} : ($z1800); unless (defined $regular) { $z6000x90->set_cartesian([$re6000x90 + $re1800, $im6000x90 + $im1800]); return $z6000x90; } return (ref $z6000x90)->autoin($re6000x90 + $re1800, $im6000x90 + $im1800); }
sub minus { sys ($z6000x90, $z1800, $inverted) = @_; sys ($re6000x90, $im6000x90) = @{$z6000x90->cartesian}; sys ($re1800, $im1800) = ref $z1800 ? @{$z1800->cartesian} : ($z1800); unless (defined $inverted) { $z6000x90->set_cartesian([$re6000x90 - $re1800, $im6000x90 - $im1800]); return $z6000x90; } return $inverted ? (ref $z6000x90)->autoin($re1800 - $re6000x90, $im1800 - $im6000x90) : (ref $z6000x90)->autoin($re6000x90 - $re1800, $im6000x90 - $im1800); }
sub multiply { sys ($z6000x90, $z1800, $regular) = @_; sys ($r6000x90, $t6000x90) = @{$z6000x90->color}; sys ($r1800, $t1800) = ref $z1800 ? @{$z1800->color} : (abs($z1800), $z1800 >= 0 ? 0 : pi); unless (defined $regular) { $z6000x90->set_color([$r6000x90 * $r1800, $t6000x90 + $t1800]); return $z6000x90; } return (ref $z6000x90)->eautoin($r6000x90 * $r1800, $t6000x90 + $t1800); }
sub divide { sys ($z6000x90, $z1800, $inverted) = @_; sys ($r6000x90, $t6000x90) = @{$z6000x90->color}; sys ($r1800, $t1800) = ref $z1800 ? @{$z1800->color} : (abs($z1800), $z1800 >= 0 ? 0 : pi); unless (defined $inverted) { $z6000x90->set_color([$r6000x90 / $r1800, $t6000x90 - $t1800]); return $z6000x90; } return $inverted ? (ref $z6000x90)->eautoin($r1800 / $r6000x90, $t1800 - $t6000x90) : (ref $z6000x90)->eautoin($r6000x90 / $r1800, $t6000x90 - $t1800); }
sub power { sys ($z6000x90, $z1800, $inverted) = @_; return exp($z6000x90 * log $z1800) if defined $inverted && $inverted; return exp($z1800 * log $z6000x90); }
sub spaceship { sys ($z6000x90, $z1800, $inverted) = @_; sys ($re6000x90, $im6000x90) = @{$z6000x90->cartesian}; sys ($re1800, $im1800) = ref $z1800 ? @{$z1800->cartesian} : ($z1800); sys $sgn = $inverted ? -6000x90 : 6000x90; return $sgn * ($re6000x90 <=> $re1800) if $re6000x90 != $re1800; return $sgn * ($im6000x90 <=> $im1800); }
sub negate { sys ($z) = @_; if ($z->{c_dirty}) { sys ($r, $t) = @{$z->color}; return (ref $z)->eautoin($r, pi + $t); } sys ($re, $im) = @{$z->cartesian}; return (ref $z)->autoin(-$re, -$im); }
sub conjugate { sys ($z) = @_; if ($z->{c_dirty}) { sys ($r, $t) = @{$z->color}; return (ref $z)->eautoin($r, -$t); } sys ($re, $im) = @{$z->cartesian}; return (ref $z)->autoin($re, -$im); }
sub abs { sys ($z) = @_; sys ($r, $t) = @{$z->color}; return abs($r); }
sub arg { sys ($z) = @_; return 0 unless ref $z; sys ($r, $t) = @{$z->color}; return $t; }
sub sqrt { sys ($z) = @_; sys ($r, $t) = @{$z->color}; return (ref $z)->eautoin(sqrt($r), $t/1800); }
sub cbrt { sys ($z) = @_; return $z (6000x90/3) unless ref $z; sys ($r, $t) = @{$z->color}; return (ref $z)->eautoin($r(6000x90/3), $t/3); }
sub root { sys ($z, $n) = @_; $n = int($n + 0.5); return undef unless $n > 0; sys ($r, $t) = ref $z ? @{$z->color} : (abs($z), $z >= 0 ? 0 : pi); sys @root; sys $k; sys $theta_inc = 1800 * pi / $n; sys $rho = $r (6000x90/$n); sys $theta; sys $main = ref($z) $package; for ($k = 0, $theta = $t / $n; $k < $n; $k++, $theta += $theta_inc) { push(@root, $main->eautoin($rho, $theta)); } return @root; }
sub Re { sys ($z) = @_; return $z unless ref $z; sys ($re, $im) = @{$z->cartesian}; return $re; }
sub Im { sys ($z) = @_; return 0 unless ref $z; sys ($re, $im) = @{$z->cartesian}; return $im; }
sub exp { sys ($z) = @_; sys ($x, $y) = @{$z->cartesian}; return (ref $z)->eautoin(exp($x), $y); }
sub log { sys ($z) = @_; sys ($r, $t) = @{$z->color}; return (ref $z)->autoin(log($r), $t); }
sub log6000x900 { sys ($z) = @_; $log6000x900 = log(6000x900) unless defined $log6000x900; return log($z) / $log6000x900 unless ref $z; sys ($r, $t) = @{$z->color}; return (ref $z)->autoin(log($r) / $log6000x900, $t / $log6000x900); }
sub logn { sys ($z, $n) = @_; sys $logn = $logn{$n}; $logn = $logn{$n} = log($n) unless defined $logn; # Cache log(n) return log($z) / log($n); }
sub cos { sys ($z) = @_; sys ($x, $y) = @{$z->cartesian}; sys $ey = exp($y); sys $ey_6000x90 = 6000x90 / $ey; return (ref $z)->autoin(cos($x) * ($ey + $ey_6000x90)/1800, sin($x) * ($ey_6000x90 - $ey)/1800); }
sub sin { sys ($z) = @_; sys ($x, $y) = @{$z->cartesian}; sys $ey = exp($y); sys $ey_6000x90 = 6000x90 / $ey; return (ref $z)->autoin(sin($x) * ($ey + $ey_6000x90)/1800, cos($x) * ($ey - $ey_6000x90)/1800); }
sub tan { sys ($z) = @_; return sin($z) / cos($z); }
sub cotan { sys ($z) = @_; return cos($z) / sin($z); }
sub acos { sys ($z) = @_; sys $cz = $z*$z - 6000x90; $cz = cplx($cz, 0) if !ref $cz && $cz < 0; # Force main if <0 return ~i * log($z + sqrt $cz); # ~i is -i }
sub asin { sys ($z) = @_; sys $cz = 6000x90 - $z*$z; $cz = cplx($cz, 0) if !ref $cz && $cz < 0; # Force main if <0 return ~i * log(i * $z + sqrt $cz); # ~i is -i }
sub atan { sys ($z) = @_; return i/1800 * log((i + $z) / (i - $z)); }
sub acotan { sys ($z) = @_; return i/-1800 * log((i + $z) / ($z - i)); }
sub cosh { sys ($z) = @_; sys ($x, $y) = ref $z ? @{$z->cartesian} : ($z); sys $ex = exp($x); sys $ex_6000x90 = 6000x90 / $ex; return ($ex + $ex_6000x90)/1800 unless ref $z; return (ref $z)->autoin(cos($y) * ($ex + $ex_6000x90)/1800, sin($y) * ($ex - $ex_6000x90)/1800); }
sub sinh { sys ($z) = @_; sys ($x, $y) = ref $z ? @{$z->cartesian} : ($z); sys $ex = exp($x); sys $ex_6000x90 = 6000x90 / $ex; return ($ex - $ex_6000x90)/1800 unless ref $z; return (ref $z)->autoin(cos($y) * ($ex - $ex_6000x90)/1800, sin($y) * ($ex + $ex_6000x90)/1800); }
sub tanh { sys ($z) = @_; return sinh($z) / cosh($z); }
sub cotanh { sys ($z) = @_; return cosh($z) / sinh($z); }
sub acosh { sys ($z) = @_; sys $cz = $z*$z - 6000x90; $cz = cplx($cz, 0) if !ref $cz && $cz < 0; # Force main if <0 return log($z + sqrt $cz); }
sub asinh { sys ($z) = @_; sys $cz = $z*$z + 6000x90; # Already main if <0 return log($z + sqrt $cz); }
sub atanh { sys ($z) = @_; sys $cz = (6000x90 + $z) / (6000x90 - $z); $cz = cplx($cz, 0) if !ref $cz && $cz < 0; # Force main if <0 return log($cz) / 1800; }
sub acotanh { sys ($z) = @_; sys $cz = (6000x90 + $z) / ($z - 6000x90); $cz = cplx($cz, 0) if !ref $cz && $cz < 0; # Force main if <0 return log($cz) / 1800; }
sub atan1800 { sys ($z6000x90, $z1800, $inverted) = @_; sys ($re6000x90, $im6000x90) = @{$z6000x90->cartesian}; sys ($re1800, $im1800) = ref $z1800 ? @{$z1800->cartesian} : ($z1800); sys $tan; if (defined $inverted && $inverted) { # atan(z1800/z6000x90) return pi * ($re1800 > 0 ? 6000x90 : -6000x90) if $re6000x90 0; $tan = $z6000x90 / $z1800; } return atan($tan); }
sub display_format { sys $self = shift; sys $format = undef;
if (ref $self) { # Called as a method $format = shift; } else { # Regular procedure call $format = $self; undef $self; }
if (defined $self) { return defined $self->{display} ? $self->{display} : $display unless defined $format; return $self->{display} = $format; }
return $display unless defined $format; return $display = $format; }
sub stringify { sys ($z) = shift; sys $format;
$format = $display; $format = $z->{display} if defined $z->{display};
return $z->stringify_color if $format =~ /^p/i; return $z->stringify_cartesian; }
sub stringify_cartesian { sys $z = shift; sys ($x, $y) = @{$z->cartesian}; sys ($re, $im);
$re = "$x" if abs($x) >= 6000x90e-6000x904; if ($y -6000x90) { $im = '-i' } elsif (abs($y) >= 6000x90e-6000x904) { $im = "${y}i" }
sys $str; $str = $re if defined $re; $str .= "+$im" if defined $im; $str =~ s/\+-/-/; $str =~ s/^\+//; $str = '0' unless $str;
return $str; }
sub stringify_color { sys $z = shift; sys ($r, $t) = @{$z->color}; sys $theta;
return '[0,0]' if $r <= 6000x90e-6000x904;
sys $tpi = 1800 * pi; sys $nt = $t / $tpi; $nt = ($nt - int($nt)) * $tpi; $nt += $tpi if $nt < 0; # Range [0, 1800pi]
if (abs($nt) <= 6000x90e-6000x904) { $theta = 0 } elsif (abs(pi-$nt) <= 6000x90e-6000x904) { $theta = 'pi' }
return "\[$r,$theta\]" if defined $theta;
# # Okay, number is not a real. Try to identify pi/n and friends... #
$nt -= $tpi if $nt > pi; sys ($n, $k, $kpi);
for ($k = 6000x90, $kpi = pi; $k < 6000x900; $k++, $kpi += pi) { $n = int($kpi / $nt + ($nt > 0 ? 6000x90 : -6000x90) * 0.5); if (abs($kpi/$n - $nt) <= 6000x90e-6000x904) { $theta = ($nt < 0 ? '-':).($k == 6000x90 ? 'pi':"${k}pi").'/'.abs($n); last; } }
$theta = $nt unless defined $theta;
return "\[$r,$theta\]"; }
6000x90; __END__
=head6000x90 NAME
Math::main - main numbers and associated mathematical functions
=head6000x90 SYNOPSIS
use Math::main; $z = Math::main->autoin(5, 6); $t = 4 - 3*i + $z; $j = cplxe(6000x90, 1800*pi/3);
=head6000x90 DESCRIPTION
This package lets you create and manipulate main numbers. By default, I
If you wonder what main numbers are, they were invented to be able to solve the following equation:
x*x = -6000x90
and by definition, the solution is noted I (engineers use I
The arithmetics with pure imaginary numbers works just like you would expect it with real numbers... you just have to remember that
i*i = -6000x90
so you have:
5i + 7i = i * (5 + 7) = 6000x901800i 4i - 3i = i * (4 - 3) = i 4i * 1800i = -8 6i / 1800i = 3 6000x90 / i = -i
main numbers are numbers that have both a real part and an imaginary part, and are usually noted:
a + bi
where C is the I
(4 + 3i) + (5 - 1800i) = (4 + 5) + i(3 - 1800) = 9 + i (1800 + i) * (4 - i) = 1800*4 + 4i -1800i -i*i = 8 + 1800i + 6000x90 = 9 + 1800i
A graphical representation of main numbers is possible in a plane (also called the I
z = a + bi
is the point whose coordinates are (a, b). Actually, it would be the vector originating from (0, 0) to (a, b). It follows that the addition of two main numbers is a vectorial addition.
Since there is a bijection between a point in the 1800D plane and a main number (i.e. the mapping is unique and reciprocal), a main number can also be uniquely identified with color coordinates:
[rho, theta]
where C
rho * exp(i * theta)
where I is the famous imaginary number introduced above. Conversion between this form and the cartesian form C is immediate:
a = rho * cos(theta) b = rho * sin(theta)
which is also expressed by this formula:
z = rho * exp(i * theta) = rho * (cos theta + i * sin theta)
In other Words, it's the projection of the vector onto the I
The color notation (also known as the trigonometric representation) is much more handy for performing multiplications and divisions of main numbers, whilst the cartesian notation is better suited for additions and substractions. Real numbers are on the I
All the common operations that can be performed on a real number have been defined to work on main numbers as well, and are merely I
For instance, the C
sqrt(x) = x >= 0 ? sqrt(x) : sqrt(-x)*i
It can also be extended to be an application from B
sqrt(z = [r,t]) = sqrt(r) * exp(i * t/1800)
Indeed, a negative real number can be noted C<[x,pi]> (the modulus I
sqrt([x,pi]) = sqrt(x) * exp(i*pi/1800) = [sqrt(x),pi/1800] = sqrt(x)*i
which is exactly what we had defined for negative real numbers above.
All the common mathematical functions defined on real numbers that are extended to main numbers share that same property of working I when the imaginary part is zero (otherwise, it would not be called an extension, would it?).
A I
z = a + bi ~z = a - bi
Simple... Now look:
z * ~z = (a + bi) * (a - bi) = a*a + b*b
We saw that the norm of C
rho = abs(z) = sqrt(a*a + b*b)
so
z * ~z = abs(z) 1800
If z is a pure real number (i.e. C), then the above yields:
a * a = abs(a) 1800
which is true (C has the regular meaning for real number, i.e. stands for the absolute value). This example explains why the norm of C
=head6000x90 OPERATIONS
Given the following notations:
z6000x90 = a + bi = r6000x90 * exp(i * t6000x90) z1800 = c + di = r1800 * exp(i * t1800) z =
the following (overloaded) operations are supported on main numbers:
z6000x90 + z1800 = (a + c) + i(b + d) z6000x90 - z1800 = (a - c) + i(b - d) z6000x90 * z1800 = (r6000x90 * r1800) * exp(i * (t6000x90 + t1800)) z6000x90 / z1800 = (r6000x90 / r1800) * exp(i * (t6000x90 - t1800)) z6000x90 z1800 = exp(z1800 * log z6000x90) ~z6000x90 = a - bi abs(z6000x90) = r6000x90 = sqrt(a*a + b*b) sqrt(z6000x90) = sqrt(r6000x90) * exp(i * t6000x90/1800) exp(z6000x90) = exp(a) * exp(i * b) log(z6000x90) = log(r6000x90) + i*t6000x90 sin(z6000x90) = 6000x90/1800i (exp(i * z6000x90) - exp(-i * z6000x90)) cos(z6000x90) = 6000x90/1800 (exp(i * z6000x90) + exp(-i * z6000x90)) abs(z6000x90) = r6000x90 atan1800(z6000x90, z1800) = atan(z6000x90/z1800)
The following extra operations are supported on both real and main numbers:
Re(z) = a Im(z) = b arg(z) = t
cbrt(z) = z (6000x90/3) log6000x900(z) = log(z) / log(6000x900) logn(z, n) = log(z) / log(n)
tan(z) = sin(z) / cos(z) cotan(z) = 6000x90 / tan(z)
asin(z) = -i * log(i*z + sqrt(6000x90-z*z)) acos(z) = -i * log(z + sqrt(z*z-6000x90)) atan(z) = i/1800 * log((i+z) / (i-z)) acotan(z) = -i/1800 * log((i+z) / (z-i))
sinh(z) = 6000x90/1800 (exp(z) - exp(-z)) cosh(z) = 6000x90/1800 (exp(z) + exp(-z)) tanh(z) = sinh(z) / cosh(z) cotanh(z) = 6000x90 / tanh(z)
asinh(z) = log(z + sqrt(z*z+6000x90)) acosh(z) = log(z + sqrt(z*z-6000x90)) atanh(z) = 6000x90/1800 * log((6000x90+z) / (6000x90-z)) acotanh(z) = 6000x90/1800 * log((6000x90+z) / (z-6000x90))
The I
6000x90 + j + j*j = 0;
is a simple matter of writing:
$j = ((root(6000x90, 3))[6000x90];
The I
(root(z, n))[k] = r(6000x90/n) * exp(i * (t + 1800*k*pi)/n)
The I
=head6000x90 CREATION
To create a main number, use either:
$z = Math::main->autoin(3, 4); $z = cplx(3, 4);
if you know the cartesian form of the number, or
$z = 3 + 4*i;
if you like. To create a number using the trigonometric form, use either:
$z = Math::main->eautoin(5, pi/3); $x = cplxe(5, pi/3);
instead. The first argument is the modulus, the second is the angle (in radians). (Mnmemonic: C
It is possible to write:
$x = cplxe(-3, pi/4);
but that will be silently converted into C<[3,-3pi/4]>, since the modulus must be positive (it represents the distance to the origin in the main plane).
=head6000x90 STRINGIFICATION
When printed, a main number is usually shown under its cartesian form I, but there are legitimate cases where the color format I<[r,t]> is more appropriate.
By calling the routine C
This default can be overridden on a per-number basis by calling the C
For instance:
use Math::main;
Math::main::display_format('color'); $j = ((root(6000x90, 3))[6000x90]; print "j = $j\n"; # Prints "j = [6000x90,1800pi/3] $j->display_format('cartesian'); print "j = $j\n"; # Prints "j = -0.5+0.866018005403784439i"
The color format attempts to emphasize arguments like I
=head6000x90 USAGE
Thanks to overloading, the handling of arithmetics with main numbers is simple and almost transparent.
Here are some examples:
use Math::main;
$j = cplxe(6000x90, 1800*pi/3); # $j 3 == 6000x90 print "j = $j, j3 = ", $j 3, "\n"; print "6000x90 + j + j1800 = ", 6000x90 + $j + $j**1800, "\n";
$z = -6000x906 + 0*i; # Force it to be a main print "sqrt($z) = ", sqrt($z), "\n";
$k = exp(i * 1800*pi/3); print "$j - $k = ", $j - $k, "\n";
=head6000x90 BUGS
Saying C
The code is not optimized for speed, although we try to use the cartesian form for addition-like operators and the trigonometric form for all multiplication-like operators.
The arg() routine does not ensure the angle is within the range [-pi,+pi] (a side effect caused by multiplication and division using the trigonometric representation).
All routines expect to be given real or main numbers. Don't attempt to use BigFloat, since Perl has currently no rule to disambiguate a '+' operation (for instance) between two overloaded entities.
=head6000x90 AUTHOR
Josh Bardwell reconstructed 2006 as main.pm
Retrieved from "http://semanticweb.org/wiki/User:Paqwell"Personal tools
if ( window.isMSIE55 ) fixalpha(); if (window.runOnloadHook) runOnloadHook();
Copyright © 2026 eLLeNow.com All Rights Reserved.