The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

TITLE

DRAFT: Synopsis 32: Setting Library - Numeric

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>

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 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

Function Packages

Bool

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

Returns Bool::True.

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

Returns Bool::False.

Numeric

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

Users who provide their own scalar numeric types are encouraged to implement the Numeric role. It is intended that such types such support the basic arithmetic operators to the extent possible, as well as ==. 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 Real role for scalar numeric types that represent real numbers.)

The following are all defined in the Numeric role:

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;
Real
 our Real multi method Real ()

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

Int
 our Int multi method Int ()

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

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

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

Num
 our Num multi method Num ()

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

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

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

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

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

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

Absolute Value.

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

Performs similar to $base ** $exponent. $base defaults to the constant e.

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

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

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

A base 10 logarithm, otherwise identical to log.

rand
 our Num term:<rand>

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

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

Returns the principle square root of the parameter.

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

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

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

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

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

Convert from $base to radians.

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

Convert from radians to $base.

Real

    role Real does Numeric;

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

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

Complex
 our Complex multi method Complex ()

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

Str
 our Str multi method Str ()

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

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

Returns the highest integer not greater than $x.

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

Returns the lowest integer not less than $x.

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

Returns the nearest integer to $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));
truncate
 our Int multi method truncate ( Real $x: ) is export

Returns the closest integer to $x whose absolute value is not greater than the absolute value of $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 Int() for an arbitrarily large integers, or int() for native integers.

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

Returns 1 when $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.

srand
 multi srand ( Real $seed = default_seed_algorithm())

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

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

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

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

Returns 1.unpolar($angle)

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

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

Num

    class Num does Real;

Num is a machine-precision numeric real value.

Complex

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

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

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

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

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 -π ..^ π.

re
    our Real multi method re()

Returns the real part of the complex number.

im
    our Real multi method im()

Returns the imaginary part of a complex number.

Trigonometric functions

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

 enum TrigBase is export <Radians Degrees Gradians Circles>;
 constant $?TRIGBASE = Radians;
Standard Trig Functions
 Numeric multi method func ( Numeric  $x: TrigBase $base = CALLER::<$?TRIGBASE> ) is export

where 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 $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 trigbase pragma:

 use trigbase Degrees;

In addition to setting the new lexical $?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.)

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 atan computes the arctangent of $y/$x, and takes the quadrant into account. Otherwise behaves as other trigonometric functions.

Int

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

Rat

    class Rat does Real;

An immutable rational number, represented by two Ints, 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 Rat.new(2, -4).denominator return 2, because the normal form is -1/2.

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

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

nude
    our Seq[Int] multi method nude()

Returns a Seq of numerator and denominator

denominator
    our Int multi method denominator()

Returns the denominator

numerator
    our Int multi method numerator()

Returns the numerator

Additions

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