You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

401 lines
13 KiB

<HTML>
<HEAD>
<!-- Created by texi2html 1.56k from cln.texi on 5 May 2000 -->
<TITLE>CLN, a Class Library for Numbers - 3. Ordinary number types</TITLE>
</HEAD>
<BODY>
Go to the <A HREF="cln_1.html">first</A>, <A HREF="cln_2.html">previous</A>, <A HREF="cln_4.html">next</A>, <A HREF="cln_13.html">last</A> section, <A HREF="cln_toc.html">table of contents</A>.
<P><HR><P>
<H1><A NAME="SEC11" HREF="cln_toc.html#TOC11">3. Ordinary number types</A></H1>
<P>
CLN implements the following class hierarchy:
<PRE>
Number
cl_number
&#60;cl_number.h&#62;
|
|
Real or complex number
cl_N
&#60;cl_complex.h&#62;
|
|
Real number
cl_R
&#60;cl_real.h&#62;
|
+-------------------+-------------------+
| |
Rational number Floating-point number
cl_RA cl_F
&#60;cl_rational.h&#62; &#60;cl_float.h&#62;
| |
| +-------------+-------------+-------------+
Integer | | | |
cl_I Short-Float Single-Float Double-Float Long-Float
&#60;cl_integer.h&#62; cl_SF cl_FF cl_DF cl_LF
&#60;cl_sfloat.h&#62; &#60;cl_ffloat.h&#62; &#60;cl_dfloat.h&#62; &#60;cl_lfloat.h&#62;
</PRE>
<P>
<A NAME="IDX7"></A>
<A NAME="IDX8"></A>
The base class <CODE>cl_number</CODE> is an abstract base class.
It is not useful to declare a variable of this type except if you want
to completely disable compile-time type checking and use run-time type
checking instead.
<P>
<A NAME="IDX9"></A>
<A NAME="IDX10"></A>
<A NAME="IDX11"></A>
The class <CODE>cl_N</CODE> comprises real and complex numbers. There is
no special class for complex numbers since complex numbers with imaginary
part <CODE>0</CODE> are automatically converted to real numbers.
<P>
<A NAME="IDX12"></A>
The class <CODE>cl_R</CODE> comprises real numbers of different kinds. It is an
abstract class.
<P>
<A NAME="IDX13"></A>
<A NAME="IDX14"></A>
<A NAME="IDX15"></A>
The class <CODE>cl_RA</CODE> comprises exact real numbers: rational numbers, including
integers. There is no special class for non-integral rational numbers
since rational numbers with denominator <CODE>1</CODE> are automatically converted
to integers.
<P>
<A NAME="IDX16"></A>
The class <CODE>cl_F</CODE> implements floating-point approximations to real numbers.
It is an abstract class.
<H2><A NAME="SEC12" HREF="cln_toc.html#TOC12">3.1 Exact numbers</A></H2>
<P>
<A NAME="IDX17"></A>
<P>
Some numbers are represented as exact numbers: there is no loss of information
when such a number is converted from its mathematical value to its internal
representation. On exact numbers, the elementary operations (<CODE>+</CODE>,
<CODE>-</CODE>, <CODE>*</CODE>, <CODE>/</CODE>, comparisons, ...) compute the completely
correct result.
<P>
In CLN, the exact numbers are:
<UL>
<LI>
rational numbers (including integers),
<LI>
complex numbers whose real and imaginary parts are both rational numbers.
</UL>
<P>
Rational numbers are always normalized to the form
<CODE><VAR>numerator</VAR>/<VAR>denominator</VAR></CODE> where the numerator and denominator
are coprime integers and the denominator is positive. If the resulting
denominator is <CODE>1</CODE>, the rational number is converted to an integer.
<P>
Small integers (typically in the range <CODE>-2^30</CODE>...<CODE>2^30-1</CODE>,
for 32-bit machines) are especially efficient, because they consume no heap
allocation. Otherwise the distinction between these immediate integers
(called "fixnums") and heap allocated integers (called "bignums")
is completely transparent.
<H2><A NAME="SEC13" HREF="cln_toc.html#TOC13">3.2 Floating-point numbers</A></H2>
<P>
<A NAME="IDX18"></A>
<P>
Not all real numbers can be represented exactly. (There is an easy mathematical
proof for this: Only a countable set of numbers can be stored exactly in
a computer, even if one assumes that it has unlimited storage. But there
are uncountably many real numbers.) So some approximation is needed.
CLN implements ordinary floating-point numbers, with mantissa and exponent.
<P>
<A NAME="IDX19"></A>
The elementary operations (<CODE>+</CODE>, <CODE>-</CODE>, <CODE>*</CODE>, <CODE>/</CODE>, ...)
only return approximate results. For example, the value of the expression
<CODE>(cl_F) 0.3 + (cl_F) 0.4</CODE> prints as <SAMP>`0.70000005'</SAMP>, not as
<SAMP>`0.7'</SAMP>. Rounding errors like this one are inevitable when computing
with floating-point numbers.
<P>
Nevertheless, CLN rounds the floating-point results of the operations <CODE>+</CODE>,
<CODE>-</CODE>, <CODE>*</CODE>, <CODE>/</CODE>, <CODE>sqrt</CODE> according to the "round-to-even"
rule: It first computes the exact mathematical result and then returns the
floating-point number which is nearest to this. If two floating-point numbers
are equally distant from the ideal result, the one with a <CODE>0</CODE> in its least
significant mantissa bit is chosen.
<P>
Similarly, testing floating point numbers for equality <SAMP>`x == y'</SAMP>
is gambling with random errors. Better check for <SAMP>`abs(x - y) &#60; epsilon'</SAMP>
for some well-chosen <CODE>epsilon</CODE>.
<P>
Floating point numbers come in four flavors:
<UL>
<LI>
<A NAME="IDX20"></A>
Short floats, type <CODE>cl_SF</CODE>.
They have 1 sign bit, 8 exponent bits (including the exponent's sign),
and 17 mantissa bits (including the "hidden" bit).
They don't consume heap allocation.
<LI>
<A NAME="IDX21"></A>
Single floats, type <CODE>cl_FF</CODE>.
They have 1 sign bit, 8 exponent bits (including the exponent's sign),
and 24 mantissa bits (including the "hidden" bit).
In CLN, they are represented as IEEE single-precision floating point numbers.
This corresponds closely to the C/C++ type <SAMP>`float'</SAMP>.
<LI>
<A NAME="IDX22"></A>
Double floats, type <CODE>cl_DF</CODE>.
They have 1 sign bit, 11 exponent bits (including the exponent's sign),
and 53 mantissa bits (including the "hidden" bit).
In CLN, they are represented as IEEE double-precision floating point numbers.
This corresponds closely to the C/C++ type <SAMP>`double'</SAMP>.
<LI>
<A NAME="IDX23"></A>
Long floats, type <CODE>cl_LF</CODE>.
They have 1 sign bit, 32 exponent bits (including the exponent's sign),
and n mantissa bits (including the "hidden" bit), where n &#62;= 64.
The precision of a long float is unlimited, but once created, a long float
has a fixed precision. (No "lazy recomputation".)
</UL>
<P>
Of course, computations with long floats are more expensive than those
with smaller floating-point formats.
<P>
CLN does not implement features like NaNs, denormalized numbers and
gradual underflow. If the exponent range of some floating-point type
is too limited for your application, choose another floating-point type
with larger exponent range.
<P>
<A NAME="IDX24"></A>
As a user of CLN, you can forget about the differences between the
four floating-point types and just declare all your floating-point
variables as being of type <CODE>cl_F</CODE>. This has the advantage that
when you change the precision of some computation (say, from <CODE>cl_DF</CODE>
to <CODE>cl_LF</CODE>), you don't have to change the code, only the precision
of the initial values. Also, many transcendental functions have been
declared as returning a <CODE>cl_F</CODE> when the argument is a <CODE>cl_F</CODE>,
but such declarations are missing for the types <CODE>cl_SF</CODE>, <CODE>cl_FF</CODE>,
<CODE>cl_DF</CODE>, <CODE>cl_LF</CODE>. (Such declarations would be wrong if
the floating point contagion rule happened to change in the future.)
<H2><A NAME="SEC14" HREF="cln_toc.html#TOC14">3.3 Complex numbers</A></H2>
<P>
<A NAME="IDX25"></A>
<P>
Complex numbers, as implemented by the class <CODE>cl_N</CODE>, have a real
part and an imaginary part, both real numbers. A complex number whose
imaginary part is the exact number <CODE>0</CODE> is automatically converted
to a real number.
<P>
Complex numbers can arise from real numbers alone, for example
through application of <CODE>sqrt</CODE> or transcendental functions.
<H2><A NAME="SEC15" HREF="cln_toc.html#TOC15">3.4 Conversions</A></H2>
<P>
<A NAME="IDX26"></A>
<P>
Conversions from any class to any its superclasses ("base classes" in
C++ terminology) is done automatically.
<P>
Conversions from the C built-in types <SAMP>`long'</SAMP> and <SAMP>`unsigned long'</SAMP>
are provided for the classes <CODE>cl_I</CODE>, <CODE>cl_RA</CODE>, <CODE>cl_R</CODE>,
<CODE>cl_N</CODE> and <CODE>cl_number</CODE>.
<P>
Conversions from the C built-in types <SAMP>`int'</SAMP> and <SAMP>`unsigned int'</SAMP>
are provided for the classes <CODE>cl_I</CODE>, <CODE>cl_RA</CODE>, <CODE>cl_R</CODE>,
<CODE>cl_N</CODE> and <CODE>cl_number</CODE>. However, these conversions emphasize
efficiency. Their range is therefore limited:
<UL>
<LI>
The conversion from <SAMP>`int'</SAMP> works only if the argument is &#60; 2^29 and &#62; -2^29.
<LI>
The conversion from <SAMP>`unsigned int'</SAMP> works only if the argument is &#60; 2^29.
</UL>
<P>
In a declaration like <SAMP>`cl_I x = 10;'</SAMP> the C++ compiler is able to
do the conversion of <CODE>10</CODE> from <SAMP>`int'</SAMP> to <SAMP>`cl_I'</SAMP> at compile time
already. On the other hand, code like <SAMP>`cl_I x = 1000000000;'</SAMP> is
in error.
So, if you want to be sure that an <SAMP>`int'</SAMP> whose magnitude is not guaranteed
to be &#60; 2^29 is correctly converted to a <SAMP>`cl_I'</SAMP>, first convert it to a
<SAMP>`long'</SAMP>. Similarly, if a large <SAMP>`unsigned int'</SAMP> is to be converted to a
<SAMP>`cl_I'</SAMP>, first convert it to an <SAMP>`unsigned long'</SAMP>.
<P>
Conversions from the C built-in type <SAMP>`float'</SAMP> are provided for the classes
<CODE>cl_FF</CODE>, <CODE>cl_F</CODE>, <CODE>cl_R</CODE>, <CODE>cl_N</CODE> and <CODE>cl_number</CODE>.
<P>
Conversions from the C built-in type <SAMP>`double'</SAMP> are provided for the classes
<CODE>cl_DF</CODE>, <CODE>cl_F</CODE>, <CODE>cl_R</CODE>, <CODE>cl_N</CODE> and <CODE>cl_number</CODE>.
<P>
Conversions from <SAMP>`const char *'</SAMP> are provided for the classes
<CODE>cl_I</CODE>, <CODE>cl_RA</CODE>,
<CODE>cl_SF</CODE>, <CODE>cl_FF</CODE>, <CODE>cl_DF</CODE>, <CODE>cl_LF</CODE>, <CODE>cl_F</CODE>,
<CODE>cl_R</CODE>, <CODE>cl_N</CODE>.
The easiest way to specify a value which is outside of the range of the
C++ built-in types is therefore to specify it as a string, like this:
<A NAME="IDX27"></A>
<PRE>
cl_I order_of_rubiks_cube_group = "43252003274489856000";
</PRE>
<P>
Note that this conversion is done at runtime, not at compile-time.
<P>
Conversions from <CODE>cl_I</CODE> to the C built-in types <SAMP>`int'</SAMP>,
<SAMP>`unsigned int'</SAMP>, <SAMP>`long'</SAMP>, <SAMP>`unsigned long'</SAMP> are provided through
the functions
<DL COMPACT>
<DT><CODE>int cl_I_to_int (const cl_I&#38; x)</CODE>
<DD>
<A NAME="IDX28"></A>
<DT><CODE>unsigned int cl_I_to_uint (const cl_I&#38; x)</CODE>
<DD>
<A NAME="IDX29"></A>
<DT><CODE>long cl_I_to_long (const cl_I&#38; x)</CODE>
<DD>
<A NAME="IDX30"></A>
<DT><CODE>unsigned long cl_I_to_ulong (const cl_I&#38; x)</CODE>
<DD>
<A NAME="IDX31"></A>
Returns <CODE>x</CODE> as element of the C type <VAR>ctype</VAR>. If <CODE>x</CODE> is not
representable in the range of <VAR>ctype</VAR>, a runtime error occurs.
</DL>
<P>
Conversions from the classes <CODE>cl_I</CODE>, <CODE>cl_RA</CODE>,
<CODE>cl_SF</CODE>, <CODE>cl_FF</CODE>, <CODE>cl_DF</CODE>, <CODE>cl_LF</CODE>, <CODE>cl_F</CODE> and
<CODE>cl_R</CODE>
to the C built-in types <SAMP>`float'</SAMP> and <SAMP>`double'</SAMP> are provided through
the functions
<DL COMPACT>
<DT><CODE>float cl_float_approx (const <VAR>type</VAR>&#38; x)</CODE>
<DD>
<A NAME="IDX32"></A>
<DT><CODE>double cl_double_approx (const <VAR>type</VAR>&#38; x)</CODE>
<DD>
<A NAME="IDX33"></A>
Returns an approximation of <CODE>x</CODE> of C type <VAR>ctype</VAR>.
If <CODE>abs(x)</CODE> is too close to 0 (underflow), 0 is returned.
If <CODE>abs(x)</CODE> is too large (overflow), an IEEE infinity is returned.
</DL>
<P>
Conversions from any class to any of its subclasses ("derived classes" in
C++ terminology) are not provided. Instead, you can assert and check
that a value belongs to a certain subclass, and return it as element of that
class, using the <SAMP>`As'</SAMP> and <SAMP>`The'</SAMP> macros.
<A NAME="IDX34"></A>
<CODE>As(<VAR>type</VAR>)(<VAR>value</VAR>)</CODE> checks that <VAR>value</VAR> belongs to
<VAR>type</VAR> and returns it as such.
<A NAME="IDX35"></A>
<CODE>The(<VAR>type</VAR>)(<VAR>value</VAR>)</CODE> assumes that <VAR>value</VAR> belongs to
<VAR>type</VAR> and returns it as such. It is your responsibility to ensure
that this assumption is valid.
Example:
<PRE>
cl_I x = ...;
if (!(x &#62;= 0)) abort();
cl_I ten_x = The(cl_I)(expt(10,x)); // If x &#62;= 0, 10^x is an integer.
// In general, it would be a rational number.
</PRE>
<P><HR><P>
Go to the <A HREF="cln_1.html">first</A>, <A HREF="cln_2.html">previous</A>, <A HREF="cln_4.html">next</A>, <A HREF="cln_13.html">last</A> section, <A HREF="cln_toc.html">table of contents</A>.
</BODY>
</HTML>