Floats

Starting with version 4.5, &GAP; has built-in support for floating-point numbers in machine format, and allows package to implement arbitrary-precision floating-point arithmetic in a uniform manner. For now, one such package, `Float` exists, and is based on the arbitrary-precision routines in `mpfr`.

A word of caution: &GAP; deals primarily with algebraic objects, which can be represented exactly in a computer. Numerical imprecision means that floating-point numbers do not form a ring in the strict &GAP; sense, because addition is in general not associative ((1.0e-100+1.0)-1.0 is not the same as 1.0e-100+(1.0-1.0), in the default precision setting).

Most algorithms in &GAP; which require ring elements will therefore not be applicable to floating-point elements. In some cases, such a notion would not even make any sense (what is the greatest common divisor of two floating-point numbers?)

A sample run

Floating-point numbers can be input into &GAP; in the standard floating-point notation:

gap> 3.14; 3.14 gap> last^2/6; 1.64327 gap> h := 6.62606896e-34; 6.62607e-34 gap> pi := 4*Atan(1.0); 3.14159 gap> hbar := h/(2*pi); 1.05457e-34

Floating-point numbers can also be created using Float, from strings or rational numbers; and can be converted back using String,Rat,Int.

&GAP; allows rational and floating-point numbers to be mixed in the elementary operations +,-,*,/. However, floating-point numbers and rational numbers may not be compared. Conversions are performed using the creator Float:

gap> Float("3.1416"); 3.1416 gap> Float(355/113); 3.14159 gap> Rat(last); 355/113 gap> Rat(0.33333); 1/3 gap> Int(1.e10); 10000000000 gap> Int(1.e20); 100000000000000000000 gap> Int(1.e30); 1000000000000000019884624838656
Methods

Floating-point numbers may be directly input, as in any usual mathematical software or language; with the exception that every floating-point number must contain a decimal digit. Therefore .1, .1e1, -.999 etc. are all valid &GAP; inputs.

Floating-point numbers so entered in &GAP; are stored as strings. They are converted to floating-point when they are first used. This means that, if the floating-point precision is increased, the constants are reevaluated to fit the new format.

Floating-point numbers may be followed by an underscore, as in 1._. This means that they are to be immediately converted to the current floating-point format. The underscore may be followed by a single letter, which specifies which format/precision to use. By default, &GAP; has a single floating-point handler, with fixed (53 bits) precision, and its format specifier is 'l' as in 1._l. Higher-precision floating-point computations is available via external packages; `float` for example.

A record, , contains all relevant constants for the current floating-point format; see its documentation for details. Typical fields are FLOAT.MANT_DIG=53, the constant FLOAT.VIEW_DIG=6 specifying the number of digits to view, and FLOAT.PI for the constant \pi. The constants have the same name as their C counterparts, except for the missing initial DBL_ or M_.

Floating-point numbers may be created using the single function , which accepts as arguments rational, string, or floating-point numbers. Floating-point numbers may also be created, in any floating-point representation, using as in NewFloat(IsIEEE754FloatRep,355/113), by supplying the category filter of the desired new floating-point number; or using as in NewFloat(1.0,355/113), by supplying a sample floating-point number.

Floating-point numbers may also be converted to other &GAP; formats using the usual commands , , .

Exact conversion to and from floating-point format may be done using external representations. The "external representation" of a floating-point number x is a pair [m,e] of integers, such that x=m*2^(1+e-LogInt(m,2)). Conversion to and from external representation is performed as usual using and : gap> ExtRepOfObj(3.14); [ 7070651414971679, 2 ] gap> ObjByExtRep(IEEE754FloatsFamily,last); 3.14

Computations with floating-point numbers never raise any error. Division by zero is allowed, and produces a signed infinity. Illegal operations, such as 0./0., produce NaN's (not-a-number); this is the only floating-point number x such that not EqFloat(x+0.0,x).

The IEEE754 standard requires NaN to be non-equal to itself. On the other hand, &GAP; requires every object to be equal to itself. To respect the IEEE754 standard, the function should be used instead of =.

The category a floating-point belongs to can be checked using the filters , , , , .

Comparisons between floating-point numbers and rationals are explicitly forbidden. The rationale is that objects belonging to different families should in general not be comparable in &GAP;. Floating-point numbers are also approximations of real numbers, and don't follow the same rules; consider for example, using the default &GAP; implementation of floating-point numbers, gap> 1.0/3.0 = Float(1/3); true gap> (1.0/3.0)^5 = Float((1/3)^5); false

<#Include Label="FLOAT_UNARY"> <#Include Label="Float">

High-precision-specific methods

&GAP; provides a mechanism for packages to implement new floating-point numerical interfaces. The following describes that mechanism, actual examples of packages are documented separately.

A package must create a record with fields (all optional) creator a function converting strings to floating-point; eager a character allowing immediate conversion to floating-point; objbyextrep a function creating a floating-point number out of a list [mantissa,exponent]; filter a filter for the new floating-point objects; constants a record containing numerical constants, such as MANT_DIG, MAX, MIN, NAN.

The package must install methods Int, Rat, String for its objects, and creators NewFloat(filter,IsRat), NewFloat(IsString).

It must then install methods for all arithmetic and numerical operations: PLUS, Exp, ...

The user chooses that implementation by calling with the record as argument, and with an optional second argument requesting a precision in binary digits.

Complex arithmetic

Complex arithmetic may be implemented in packages, and is present in `float`. Complex numbers are treated as usual numbers; they may be input with an extra "i" as in -0.5+0.866i.

Methods should then be implemented for Norm, RealPart, ImaginaryPart, ComplexConjugate, ...

Interval-specific methods

Interval arithmetic may also be implemented in packages. Intervals are in fact efficient implementations of sets of real numbers. The only non-trivial issue is how they should be compared. The standard EQ tests if the intervals are equal; however, it is usually more useful to know if intervals overlap, or are disjoint, or are contained in each other. The methods provided by the package should include Sup,Inf,Mid,DiameterOfInterval,Overlaps,IsSubset,IsDisjoint.

Note the usual convention that intervals are compared as in [a,b]\le[c,d] if and only if a\le c and b\le d.