=encoding utf8

=head1 TITLE

DRAFT: Synopsis 32: Setting Library - Numeric

=head1 AUTHORS

    Rod Adams <rod@rodadams.net>
    Larry Wall <larry@wall.org>
    Aaron Sherman <ajs@ajs.com>
    Mark Stosberg <mark@summersault.com>
    Carl Mäsak <cmasak@gmail.com>
    Moritz Lenz <moritz@faui2k3.org>
    Tim Nelson <wayland@wayland.id.au>

=head1 VERSION

    Created: 19 Mar 2009 extracted from S29-functions.pod

    Last Modified: 16 July 2010
    Version: 10

The document is a draft.

If you read the HTML version, it is generated from the Pod in the specs
repository under
L<https://github.com/perl6/specs/blob/master/S32-setting-library/Numeric.pod>
so edit it there in the git repository if you would like to make changes.

This documents Bit, Int, Numeric, Rat, Complex, and Bool.

XXX So where are Bit, Int, and Rat

=head1 Function Packages

=head2 Bool

=over 4

=item succ

 our Bool multi method succ ( Bool $b: ) is export

Returns C<Bool::True>.

=item pred

 our Bool multi method pred ( Bool $b: ) is export

Returns C<Bool::False>.

=back

=head2 Numeric

C<Numeric> is a role for everything that's a scalar number. So C<Num>, C<Int>,
C<Rat>, C<Complex> and other numeric types do that role. However it is an
abstract interface, so C<$number.WHAT> will never return C<Numeric>. 

Users who provide their own scalar numeric types are encouraged to implement the
C<Numeric> role.  It is intended that such types such support the basic arithmetic
operators to the extent possible, as well as C<==>.  In addition, it is hoped that
comparison operators will at least return consistent results, even if there is no
sensible mathemtical ordering of your type.  That allows functions like sort to 
not choke and die if they are handed a value of your type.  (See also the C<Real>
role for scalar numeric types that represent real numbers.)

The following are all defined in the C<Numeric> role:

C<Numeric> provides some constants in addition to the basic
mathematical functions.

    constant pi is export = 3.14159_26535_89793_23846_26433_83279_50288;
    constant e  is export = 2.71828_18284_59045_23536_02874_71352_66249;
    constant i  is export = 1i;

=over

=item Real

 our Real multi method Real ()

If this C<Numeric> is equivalent to a C<Real>, return that C<Real>.  
(For instance, if this number is a C<Complex> with a zero imaginary part.)  
Fail otherwise.

=item Int

 our Int multi method Int ()

If this C<Numeric> is equivalent to a C<Real>, return the equivalent of
calling C<truncate> on that C<Real> to get an C<Int>. 

=item Rat

 our Rat multi method Rat ( Real $epsilon = 1.0e-6 )

If this C<Numeric> is equivalent to a C<Real>, return a C<Rat> which is
within C<$epsilon> of that C<Real>'s value.

=item Num

 our Num multi method Num ()

If this C<Numeric> is equivalent to a C<Real>, return that C<Real> as a C<Num>
as accurately as is possible.

=item succ

 our Numeric multi method succ ( Numeric $x: ) is export
 our Int     multi method succ ( Int $x: )     is export

Returns the successor of C<$x>. This method is used by C<< prefix:<++> >> and
C<< postfix:<++> >> to increment the value in a container.

=item pred

 our Numeric multi method pred ( Numeric $x: ) is export
 our Int     multi method pred ( Int $x:     ) is export

Returns the predecessor of C<$x>. This method is used by C<< prefix:<--> >>
and C<< postfix:<--> >> to decrement the value in a container.

=item abs

 our Numeric multi method abs ( Numeric $x: ) is export

Absolute Value.

=item exp

 our Numeric multi method exp ( Numeric $exponent: Numeric :$base = Num::e ) is export

Performs similar to C<$base ** $exponent>. C<$base> defaults to the
constant I<e>.

=item log

 our Numeric multi method log ( Numeric $x: Numeric $base = Num::e ) is export

Logarithm of base C<$base>, default Natural. Calling with C<$x == 0> is an
error.

=item log10

 our Numeric multi method log10 (Numeric $x:) is export

A base C<10> logarithm, otherwise identical to C<log>.

=item rand

 our Num term:<rand>

Pseudo random number in range C<< 0 ..^ 1 >>.  That is, C<0> is
theoretically possible, while C<1> is not.  Note that there is no
unary C<rand> function in Perl 6, but there is a C<rand> method.  
For picking a random integer you probably want
to use something like C<(1..6).pick> instead.

=item sqrt

 our Numeric multi method sqrt ( Numeric $x: ) is export

Returns the principle square root of the parameter.

=item roots

  method roots (Numeric $x: Int $n ) is export

Returns a list of all C<$n>th (complex) roots of C<$x>. Returns C<NaN> if
C<< $n <= 0 >>, itself if C<$n == 0>,  and is free to return a single C<NaN>
if C<$x> is C<NaN> or C<Inf>, or in case of complex numbers if one of the
components is.

=item i

 our Complex multi postfix:<i> ( Numeric $x )

Returns a complex number representing the parameter multiplied by the imaginary
unit C<i>.  Note that there is no C<.i> method.  To follow a variable name
with the postfix, it's necessary to use a backslash or parentheses:

    $land\i
    ($land)i

=item to-radians

 our Numeric multi method to-radians ( Numeric $x: TrigBase $base ) is export

Convert from C<$base> to radians.

=item from-radians

 our Numeric multi method from-radians ( Numeric $x: TrigBase $base ) is export

Convert from radians to C<$base>.

=back


=head2 Real

    role Real does Numeric;

C<Real>, like C<Numeric>, is an abstract role that represents the interface of
a real scalar number (i.e. neither C<Complex> nor vector-like). For example
C<Num>, C<Int>, C<Bool> and C<Rat> implement the C<Real> role.

Users who provide their own scalar real numeric types are encouraged to implement the
C<Real> role.  Because real numbers are strictly-totally-ordered and
C<Real> types try to emulate that property, it is desirable that any two
C<Real> types be mutally compatible, even if they are not aware of each other.  The
current proposal requires you to define a C<Bridge> method in your C<Real> type, which
converts your type into a neutral C<Real> type by restating it in terms of the fundamental
Perl 6 types and calling C<Bridge> on them.  This then makes the default C<Real> methods
and operators all work with your C<Real> type.  While the name of this method may changed,
it is hoped that something like this will remain in the spec.

=over

=item Complex

 our Complex multi method Complex ()

Returns a C<Complex> whose real part is this C<Real> and whose imaginary part is 0.

=item Str

 our Str multi method Str ()

Returns the C<Real> as a C<Str>.  All built-in C<Real> types format it as a decimal 
number, so for example, the C<Rat> C<5/4> is returned as C<"1.2">.

=item floor

 our Int multi method floor ( Real $x: ) is export

Returns the highest integer not greater than C<$x>.

=item ceiling

 our Int multi method ceiling ( Real $x: ) is export

Returns the lowest integer not less than C<$x>.

=item round

 our Int multi method round ( Real $x: $scale = 1) is export

Returns the nearest integer to C<$x>.  The algorithm is:

    floor($x / $scale + 0.5) * $scale

(Other rounding algorithms will be given extended names beginning with "round".)

Functions that round to a particular precision may easily be created with
currying:

    constant &roundcents ::= &round.assuming(:scale(1/100));

=item truncate

 our Int multi method truncate ( Real $x: ) is export

Returns the closest integer to C<$x> whose absolute value is not greater
than the absolute value of C<$x>.  (In other words, just chuck any
fractional part.)  This is the default rounding function used by
implicit integer conversions.

You may also truncate using explicit integer casts, either C<Int()> for
an arbitrarily large integers, or C<int()> for native integers.

=item sign

 our Int multi method sign ( Real $x: ) is export

Returns 1 when C<$x> is greater than 0, -1 when it is less than 0, 0 when it
is equal to 0, or undefined when the value passed is undefined.

=item srand

 multi srand ( Real $seed = default_seed_algorithm())

Seed the generator C<rand> uses. C<$seed> defaults to some combination
of various platform dependent characteristics to yield a non-deterministic seed.
Note that you get one C<srand()> for free when you start a Perl program, so
you I<must> call C<srand()> yourself if you wish to specify a deterministic seed
(or if you wish to be differently nondeterministic).

=item rand

 our Num multi method rand (Real $x:) is export

Pseudo random number in range C<< 0 ..^ $x >>.  That is, C<0> is
theoretically possible, while C<$x> is not.  For picking a random integer
you probably want to use something like C<(1..6).pick> instead.

=item cis

    our Complex multi method cis (Real $angle:) is export

Returns 1.unpolar($angle)

=item unpolar

    our Complex multi method unpolar (Real $mag: Real $angle) is export

Returns a complex number specified in polar coordinates.  Angle is in radians.


=back

=head2 Num

    class Num does Real;

C<Num> is a machine-precision numeric real value.

=head2 Complex

C<Complex> is an immutable type. Each C<Complex> object stores two numbers,
the real and imaginary part. For all practical purposes a C<Complex> with
a C<NaN> in real or imaginary part may be considered a C<NaN> itself (and
C<(NaN + 1i) ~~ NaN> is C<True>).

Coercion of a C<Complex> to any C<Real> returns the real part (coerced, if
necessary) if the imaginary part is 0, and fails otherwise. Comparison
between a C<Real> number and a C<Complex> must be smart enough not to coerce
the C<Complex> to a real number blindly.

=over 4

=item new

    our Complex multi method new(Real $re, Real $im)

Constructs a C<Complex> number from real and imaginary part. This is the
method form of C<$re + ($im)i>.

=item polar

    our Seq multi method polar (Complex $nim:) is export

Returns (magnitude, angle) corresponding to the complex number.
The magnitude is non-negative, and the angle in the range C<-π ..^ π>.

=item re

    our Real multi method re()

Returns the real part of the complex number.

=item im

    our Real multi method im()

Returns the imaginary part of a complex number.

=back

=head2 Trigonometric functions

The following are also defined in C<Numeric>.  The trig functions
depend on the current (lexically scoped) trig base:

 enum TrigBase is export <Radians Degrees Gradians Circles>;
 constant $?TRIGBASE = Radians;

=over 4

=item I<Standard Trig Functions>

 Numeric multi method func ( Numeric  $x: TrigBase $base = CALLER::<$?TRIGBASE> ) is export

where I<func> is one of:
sin, cos, tan, asin, acos, atan, sec, cosec, cotan, asec, acosec,
acotan, sinh, cosh, tanh, asinh, acosh, atanh, sech, cosech, cotanh,
asech, acosech, acotanh.

Performs the various trigonometric functions.

Option C<$base> is used to declare how you measure your angles.
Given the value of an arc representing a single full revolution.

 $base       Subdivisions of circle
 ----        ----------------------
 Radians     2*pi
 Degrees     360
 Gradians    400
 Circles     1

To change the base within your own lexical scope, it suffices to redefine the
compiler constant with the C<trigbase> pragma:

 use trigbase Degrees;

In addition to setting the new lexical C<$?TRIGBASE>, this also
curries a new set of functions into the current lexical scope that
assume the new base.  (Note that methods calls cannot be curried, so
methods must still look up the caller's trigbase.  The optimizer may,
of course, optimize these into fast function calls.)

=item atan2

 our Real multi method atan2 ( Real $y: Real $x = 1, TrigBase $base = CALLER::<$?TRIGBASE> )
 our Real multi atan2 ( Real $y, Real $x = 1, TrigBase $base = CALLER::<$?TRIGBASE> )

This second form of C<atan> computes the arctangent of C<$y/$x>, and takes
the quadrant into account. Otherwise behaves as other trigonometric functions.

=back

=head2 Int

An C<Int> is an immutable, integral number of arbitrary size.

=head2 Rat

    class Rat does Real;

An immutable rational number, represented by two C<Int>s, a numerator and
a denominator. All interface methods return values as if the numerator and
denominator were stored in a normal form: both numerator and denominator are
minimal in their magnitude, and the denominator is positive. So
C<Rat.new(2, -4).denominator> return C<2>, because the normal form is C<-1/2>.

=over

=item new

    multi method new(Int $num, Int $denom)

Constructs a C<Rat> object from the numerator and denominator.
Fails if C<$denom == 0>.

=item nude

    our Seq[Int] multi method nude()

Returns a C<Seq> of numerator and denominator

=item denominator

    our Int multi method denominator()

Returns the denominator

=item numerator

    our Int multi method numerator()

Returns the numerator

=back


=head1 Additions

Please post errors and feedback to perl6-language.  If you are making
a general laundry list, please separate messages by topic.

=for vim:set expandtab sw=4: