develooper Front page | perl.perl6.internals | Postings from February 2002

Initial bignum pdd

Thread Next
From:
Alex Gough
Date:
February 21, 2002 19:09
Subject:
Initial bignum pdd
Message ID:
Pine.OSF.4.44.0202220306001.25764-100000@ermine.ox.ac.uk
This is a slightly confused first attempt at a pdd.  I'll start to add
extra details over the next couple of days.

Is 8 the right number?  And can someone who knows how fix the ones in
the repository to have more meaningful file names?

Alex Gough
#################################################
=head1 TITLE

PDD 8 - Big Numbers

=head1 VERSION

$Id$

=head2 CURRENT

    Maintainer: Alex Gough (alex@earth.li)
    Class: Informational
    PDD Number: 8
    Version: $Id$
    Status: Being finished
    Last Modified: $Id$
    PDD Format: 1
    Language: English

=head2 HISTORY

=over 4

=item version 1

The first version is more a description of the state of the art than a
plan for the future.  The author believes this is akin to learning how
to crawl before trying to run.  Leaving the ground is considered Right
Out with attempts being left as an exercise for the interested reader.

=back

=head1 CHANGES

=over 4

=item Version 1.0

None. First version

=back

=head1 ABSTRACT

This document describes the big number library, the functionality it
provides and some internal details of interest to people making use of
the library.  Some of the areas in which the big number library meet
with the rest of parrot are also discussed.

=head1 DESCRIPTION

The big number library attempts to provide a standard decimal
arithmetic and a range of unlimited precision numeric types to parrot.

=head2 Why decimal arithmetic?

There are benifits in using the big number library to provide both
values of effectively unlimited precision and a defined arithmetic,
complete with rounding and exceptional conditions, for values which
are otherwise easily represented using standard low-level types.  Both
require the same range of operations but differ in the environment
under which those operations occur.  The effort required to produce a
library which implements a decimal arithmetic is not much greater than
that needed to provide a base-2 big number library.  It is true that
some trade-off in both space and speed is made but given the nature of
dynamic languages, this should not present too great a burden.

=head2 Numeric types provided

The bignumber library provides the following data types to parrot:

=over 4

=item Big integers (BigInt)

Whole numbers with no limits on their size.

=item Big floats (BigNum)

Numbers with decimal fractional parts, again with no limit on size.

=item Big floats with fixed fractional parts

Numbers with a fixed maximum number of digits in their fractional
part, again with no limit on size.

=back

The library implements these different forms of number using the same
internal representation, and differentiates between them only when
performing rounding operations.  A number has the following abstract
form:

 [ sign, string of digits, exponent ]

If sign is zero, the number is positive, if equal to one, the number is
negative.  The number has the value

 sign, string of digits * 10 ** exponent

A big integer must always have a non-negative exponent, a big float
may have any exponent and a float with a fixed fractional part will
have an exponent greater than a given (negative) number.  These limits
are not attatched to a numeric value, but instead are enforced by
giving any operation involving the numbers a I<context>.

In general, parrot functions will not need to care about what the
bignum objects are or do, they should merely be used as arguments to
big number functions, the objects will be managed by parrot's garbage
collection in a simillar manner to strings.

=head2 Context

All operations occur within a defined context.  This tells the
operations how they should be treating their arguments, what sort of
rounding to perform and what to do if information is lost through
rounding.

The context provides the environment in which an operation occurs,
in particular the following options are available:

=over 4

=item precision

A positive I<precision> indicates that big floats are to be used,
these cannot have more than I<precision> digits in their coefficient
before or after any operation.  Arguments to operations with more than
I<precision> digits will be truncated and rounded appropriately and
results of operations will not have more than I<precision> digits in
their coefficients, with any extra digits accumulated during the
calculation of the operation being truncated and rounded as required.

A I<precision> of zero indicates that integer operations are to be
performed.  Arguments to operations are rounded so that they have no
fractional part, and the result of all operations will be rounded to
be integers.

A negative value of I<precision> indicates that a fixed number of
fractional digits are to be provided, with arguments and results being
truncated after those digits.

With non-positive values of I<precision> the total number of digits in
the coefficient is limited only by available memory.

=item rounding

The rounding part of the context defines the rounding algorithm which
is to be applied when truncating digits from a number's coefficient.
The available rounding forms are outlined below.

=item lost_digits

If the I<lost_digits> part of the context is true (non-zero) an
exception will be raised (and dispatched as any other parrot level
exception) if arguments to operations are rounded and lose significant
digits in the process.  This exception may be either a warning, or a
fatal error, as decided by the language running at the time.

=item flags

The I<flags> part of the context carries information about the result
of an operation.  If a I<lost_digits> condition would have been
triggered but was not because I<lost_digits> was false, this is
recorded in the flags.  The flags will also record if the result of an
operation has been rounded, or is imprecise.

=back

It is therefore the current I<context> which determines which numeric
type is being considered during a particular operation, this makes it
easy to upgrade from one numeric form to another, and also allows for
considerable code-reuse within the library.

=head2 Rounding

The rounding part of the context defines the rounding algoritm to be
used, the following are provided (examples assume a precision of 5):

=over 4

=item Round down

Any unwanted digits are simply truncated from the coefficient.

 [0, 1234567, 10] => [0, 12345, 12]

=item Round half up

The first lost digit is examined, if this is in the range 0-4, the
coefficient is truncated directly, if in the range 5-9, one is added
to the final digit of the coefficient.  If this leads to a coefficient
with more than I<precision> digits, the final trailing zero is
removed.

 [0, 1234567, 10] => [0, 12346, 12]
 [0, 1234549, 10] => [0, 12345, 12]
 [0, 9999950, 10] => [0, 10000, 13]

=item Round half even

The first lost digit is examined, if it lies in the range 0-4, the
coefficient is truncated directly, if in the range 6-9, the
coefficient is rounded up.  If the first lost digit is equal to 5, and
the remaining lost digits in the coefficient are non-zero, the number
is also rounded up.  If the lost digits are equal to exactly half, the
number is rounded up if the least significant retained digit is odd,
and rounded down if it is even.

=back

=head2 Operations

The following operations are provided by the library, they function
exactly as those described in the Standard Decimal Arithmetic (SDA)
(see references below) with some extension to cope with integer and
fixed fractional part numbers.  Only the deviations are outlined here.

In all cases, the sequence of rounding and promotion to zero outlined
by the SDA are followed, even where the context implies integer
operations.

=over 4

=item Addition, Subtraction

=item Multiplication

=item Division

Under integer conditions, division is halted once the first fractional
digit is calculated, with the result then being rounded to an integer
and returned.  Under fixed-fraction conditions, one more digit than
needed is calculated, with the coefficient then being rounded and
returned.

If a floating point value is required, or if inexact division by a
very small number is attempted, it may be wise to follow big float
arithmetic to limit the number of digits returned.  It is safe to
chose a precision at least as big the largest number of digits
of either argument to the division function.

=item Integer division, Remainder

For both integer and fixed-fraction numbers, the result returned by
the remainder function will be an integer or fixed-fraction number.
The result of integer division will be an integer.

=item Rounding

=item Plus / Minus

=item Comparison

Comparision returns a big number which is equal to 1, 0 or -1.  An
alternative form which returns an INTVAL is also provided.

=item Rescale

=item Power

=back

=head2 Conversion to and from strings

A one to one conversion between the abstract representation above and
a string is provided by the library, and acts as defined by the
standard decimal arithmetic.  Other conversation operations may also
be implemented, and these may not provide one to one mapping.

A pedantic error checking conversion is available within the library,
but only works with native strings.  Versions which work with parrot
strings will also be provided, although in a seperate file to the rest
of the library (they will share a common private header file).

=head1 IMPLEMENTATION

Functions are provided with implement the arithmetic, conversion,
creation and destruction of big numbers by dealing with otherwise
opaque big number objects.

=head2 Big number representation

A big number is represented by the following structure, this is
capable of being allocated, tracked and destroyed by the parrot
garbage collection system.

 typedef struct {
     BN_NIB* buffer;   /* string of nibbles */
     UINTVAL nibs;     /* nibs allocated, in sizeof(BN_NIB) */
     UINTVAL flags;    /* May store, say +Inf */
     INTVAL digits;    /* digits used */
     int sign;         /* sign of number, 0=> positive, zero, 1 => negative */
     INTVAL expn;      /* exponent of number */
 } parrot_bignum_t;

Within the library, individual decimal digits can be accessed using
macros, outside the library, access must be made via exported
functions.  BN_NIB is likely to be a UINTVAL, but this is not
essential.  The I<flags> member of the structure may be used in future
to indicate that a number is, say, +Inf.

=head2 Context

 typedef struct {
     INTVAL precision;     /* number of digits to retain */
     BN_ROUNDING rounding; /* rounding type to perform */
     int lost_digits;      /* 0 => round, 1 => raise exception */
     UINTVAL flags;        /* records possible errors */
 } BN_CONTEXT;

BN_ROUNDING is an enumeration of ROUND_HALF_UP, ROUND_DOWN and
ROUND_HALF_EVEN.

It is expected that language level types implement big floats using a
global floating point context which is tagged onto an interpreter
structure (and can thus be modified by called the right opcodes).
That big integers and fixed-fraction number are provided by creating a
context with an appropriate precision whenever a call into the library
is made.

=head2 Tests

The Standard Decimal Arithmetic provides a collection of tests for
both its base and extended behaviour.  Initially it is hoped that this
library can pass all base tests, with extended tests to be included at
a later date as it is extended to cope with values such as +Inf.

=head1 ATTACHMENTS

=head1 FOOTNOTES

=head1 REFERENCES

IBM's Standard Decimal Arithmetic, with tests
http://www2.hursley.ibm.com/decimal/

Perl's Math::Big* modules.


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About