Pages

Wednesday, September 19, 2012

AdaTutor - Advanced Topics (2)

More Attributes

Ada provides many attributes, all described in Annex K
of the Ada 95 RM. The
most important ones that we haven't yet discussed are these:

For any real type or subtype (floating or fixed), 'Small and
'Large are the smallest and largest positive model numbers. Thus
Float'Small is the difference between zero and the next larger number in
type Float. Also, for any floating point (sub)type, 'Model_Epsilon
is the difference between one and the next larger number. (In Ada 83,
'Model_Epsilon is simply called 'Epsilon.) We'll use
'Epsilon in an Ada 83 generic function in a moment.

For a floating point (sub)type, 'Digits returns the value given for
digits in the declaration, and for a fixed point (sub)type, 'Delta
returns the value given for delta in the declaration. These
attributes may not seem too useful, because the programmer already knows what
he or she wrote in the declarations. However, they're useful in generic
packages and subprograms. For example, if the generic part says type
Dummy is delta <>;, the body can use Dummy'Delta.

Ada 95 has 'Max and 'Min, both of which take two scalar
parameters. For example, if we have I : Integer := 1; and
J : Integer := 2;, then Integer'Max(I, J) is 2.

For any discrete (sub)type, 'Width gives the maximum length that the
attribute 'Image can produce. Boolean'Width is 5 because
“False” has length 5. With our earlier definition of
Rainbow_Color, Rainbow_Color'Width is 6. For versions of Ada using
16-bit Integers, Integer'Width is also 6, the length of
&lduqo;-32768”.

'Count is used with the name of a task entry. It returns the
number of calls presently queued on the entry. 'Terminated is of
type Boolean. It's used with a task name, and tells if the task is
terminated.

Ada 95 has a package Ada.Numerics.Generic_Elementary_Functions containing a
square root (Sqrt) function, but Ada 83 doesn't have this package. As an
exercise, let's write a generic Ada 83 function to compute the square root for
any floating point type, using Newton-Raphson iteration.

Let's suppose that G is our guess of the square root of X. If our guess is
correct, then X/G equals G. If our guess is too low, then X/G is larger than
G, and if our guess is too high, then X/G is smaller than G. The Newton-
-Raphson method simply says that our next guess is the average of G and X/G
(one of which is too high, and the other of which is too low). For example, if
we want to compute the square root of 9.0 and our first guess is 9.0,
successive guesses are 5.0, 3.4, 3.02352941, 3.00009155, 3.00000000. Note that
convergence is very rapid.

However, the problem in writing a program like this is knowing when to stop
the iteration. We'll use the Ada 83 attribute 'Epsilon (called
'Model_Epsilon in Ada 95). Since G*G/X should be 1.0, we'll quit
when the absolute value of the difference between G*G/X and 1.0 is less than or
equal to 3.0 times Epsilon. Recall that Dummy'Epsilon is the
difference between 1.0 and the next higher number for type Dummy. If we
use 1.0 times Epsilon, the loop might never terminate, and if we use 10.0 times
Epsilon, we might not get full precision. So we'll use 3.0 times
Epsilon. Here's our function:

We tested our Sqrt with an implementation of Ada 83 having types Float,
Long_Float, and Long_Long_Float. The last gives at least 33 decimal digits of
precision. Sqrt was instantiated for all three floating point types, as was
Float_IO to display the results. When tested with the three types, all
displayed digits of the answers were correct.