Skip to content

Commit e1a42d1

Browse files
authored
Merge pull request #1276 from gusthoff/content/advanced_ada/new_content/numerics/fixed_point_types/20250822
Adding section on fixed-point types
2 parents 518b5f7 + 2117082 commit e1a42d1

File tree

3 files changed

+208
-63
lines changed

3 files changed

+208
-63
lines changed

content/courses/advanced-ada/parts/data_types/numeric_attributes.rst

Lines changed: 2 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,8 @@ indicating whether a feature is available or not in the target architecture:
12861286
end Show_Boolean_Attributes;
12871287

12881288

1289+
.. _Adv_Ada_Fixed_Point_Type_Small_Delta_Attributes:
1290+
12891291
Attribute: :ada:`Small` and :ada:`Delta`
12901292
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12911293

@@ -1295,63 +1297,6 @@ type :ada:`T` is equal to the :ada:`Delta` of that type |mdash| i.e.
12951297
:ada:`T'Small = T'Delta`. Let's discuss each attribute and how they distinguish
12961298
from each other.
12971299

1298-
The :ada:`Delta` attribute returns the value of the :ada:`delta` that was
1299-
used in the type definition. For example, if we declare
1300-
:ada:`type T3_D3 is delta 10.0 ** (-3) digits D`, then the value of
1301-
:ada:`T3_D3'Delta` is the :ada:`10.0 ** (-3)` that we used in the type
1302-
definition.
1303-
1304-
The :ada:`Small` attribute returns the "small" of a type, i.e. the smallest
1305-
value used in the machine representation of the type. The *small* must be at
1306-
least equal to or smaller than the *delta* |mdash| in other words, it must
1307-
conform to the :ada:`T'Small <= T'Delta` rule.
1308-
1309-
.. admonition:: For further reading...
1310-
1311-
The :ada:`Small` and the :ada:`Delta` need not actually be small numbers.
1312-
They can be arbitrarily large. For instance, they could be 1.0, or 1000.0.
1313-
Consider the following example:
1314-
1315-
.. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Numerics.Fixed_Point_Types.Large_Small_Attribute
1316-
1317-
package Fixed_Point_Defs is
1318-
S : constant := 32;
1319-
Exp : constant := 128;
1320-
D : constant := 2.0 ** (-S + Exp + 1);
1321-
1322-
type Fixed is delta D
1323-
range -1.0 * 2.0 ** Exp ..
1324-
1.0 * 2.0 ** Exp - D;
1325-
1326-
pragma Assert (Fixed'Size = S);
1327-
end Fixed_Point_Defs;
1328-
1329-
with Fixed_Point_Defs; use Fixed_Point_Defs;
1330-
with Ada.Text_IO; use Ada.Text_IO;
1331-
1332-
procedure Show_Fixed_Type_Info is
1333-
begin
1334-
Put_Line ("Size : "
1335-
& Fixed'Size'Image);
1336-
Put_Line ("Small : "
1337-
& Fixed'Small'Image);
1338-
Put_Line ("Delta : "
1339-
& Fixed'Delta'Image);
1340-
Put_Line ("First : "
1341-
& Fixed'First'Image);
1342-
Put_Line ("Last : "
1343-
& Fixed'Last'Image);
1344-
end Show_Fixed_Type_Info;
1345-
1346-
In this example, the *small* of the :ada:`Fixed` type is actually quite
1347-
large: 1.58456325028528675\ :sup:`29`. (Also, the first and the last values
1348-
are large: -340,282,366,920,938,463,463,374,607,431,768,211,456.0 and
1349-
340,282,366,762,482,138,434,845,932,244,680,310,784.0, or approximately
1350-
-3.4028\ :sup:`38` and 3.4028\ :sup:`38`.)
1351-
1352-
In this case, if we assign 1 or 1,000 to a variable :ada:`F` of this type,
1353-
the actual value stored in :ada:`F` is zero. Feel free to try this out!
1354-
13551300
When we declare an ordinary fixed-point data type, we must specify the *delta*.
13561301
Specifying the *small*, however, is optional:
13571302

content/courses/advanced-ada/parts/data_types/numerics.rst

Lines changed: 204 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3008,16 +3008,214 @@ decimal precision greater than the maximum supported precision. Therefore,
30083008
compilation fails for this example.
30093009

30103010

3011-
.. ::
3011+
.. _Adv_Ada_Fixed_Point_Types:
3012+
3013+
Fixed-point types
3014+
-----------------
3015+
3016+
We already discussed :ref:`fixed-point types <Intro_Ada_Fixed_Point_Types>` in
3017+
the Introduction to Ada course. Roughly speaking, fixed-point types can be
3018+
thought as a way to mimic operations that look like floating-point types, but
3019+
use discrete numeric types *in the background*. This has a big advantage for
3020+
the implementation of certain numeric algorithms, as developers can use
3021+
operations that look familiar because they resemble the ones they use with
3022+
floating-point types.
3023+
3024+
.. admonition:: In other languages
3025+
3026+
In many programming languages such as C, there's no built-in support for
3027+
fixed-point types. This forces developers that need fixed-point types to
3028+
circumvent this absence with sometimes cumbersome alternative. They could,
3029+
for example, use integer types and introduce additional operations to match
3030+
fixed-point operations. Alternatively, frameworks or non-portable,
3031+
compiler-specific extensions might be used in some cases. In contrast, the
3032+
fact that Ada has built-in support for fixed-point types means that using
3033+
these types is both portable and doesn't require extra efforts to
3034+
circumvent limitations |mdash| such as the ones that originate from using
3035+
integer types to emulate fixed-point operations.
3036+
3037+
As mentioned in the Introduction to Ada course course, fixed-point types
3038+
are classified in
3039+
decimal fixed-point types and
3040+
ordinary (binary).
3041+
3042+
.. todo::
3043+
3044+
Add link to sections above once available.
3045+
3046+
Decimal fixed-point types are based on powers of ten and have the following
3047+
syntax:
3048+
3049+
.. code-block:: ada
3050+
3051+
type <type-name> is
3052+
delta <delta-value> digits <digits-value>;
3053+
3054+
Decimal fixed-point types are useful, for example, in many financial
3055+
applications, where round-off errors from arithmetic operations are considered
3056+
unacceptable.
3057+
3058+
Ordinary fixed-point types are based on powers of two (in their hardware
3059+
implementation) and have the following syntax:
3060+
3061+
.. code-block:: ada
3062+
3063+
type <type-name> is
3064+
delta <delta-value>
3065+
range <lower-bound> .. <upper-bound>;
3066+
3067+
Ordinary fixed-point types can be found for example in some implementations for
3068+
digital signal processing.
3069+
3070+
In the next sections, we discuss further details about these specific types.
3071+
Next in this section, we introduce the concept of *small* and *delta* of
3072+
fixed-point types, which are common for both kinds of fixed-point types.
3073+
3074+
3075+
.. _Adv_Ada_Fixed_Point_Types_Small_Delta:
3076+
3077+
Small and delta
3078+
~~~~~~~~~~~~~~~
3079+
3080+
The *small* and the *delta* of a fixed-point type indicate the numeric
3081+
precision of that type. Let's discuss these concepts and how they differ
3082+
from each other.
3083+
3084+
The *delta* corresponds to the value used for the :ada:`delta` in the type
3085+
definition. For example, if we declare
3086+
:ada:`type T3_D3 is delta 10.0 ** (-3) digits D`, then the *delta* is equal to
3087+
the 10.0\ :sup:`-3` that we used in the type definition.
3088+
3089+
The *small* of a type :ada:`T` is the smallest positive value used in the
3090+
machine representation of the type. In other words, while the *delta* is
3091+
primarily a user-selected value that (ideally) fits the requirements of the
3092+
implementation, the *small* indicates how that *delta* is represented on the
3093+
target machine.
3094+
3095+
The *small* must be at least equal to or smaller than the *delta*. In many
3096+
cases, however, the *small* of a type :ada:`T` is equal to the *delta* of that
3097+
type. In addition, note that these values aren't necessarily small numbers
3098+
|mdash| in fact, they could be quite large.
3099+
3100+
We can use the :ada:`T'Small` and :ada:`T'Delta` attributes to retrieve the
3101+
actual values of the *small* and *delta* of a fixed-point type :ada:`T`. (We
3102+
discuss more details about these attributes
3103+
:ref:`in another chapter <Adv_Ada_Fixed_Point_Type_Small_Delta_Attributes>`.)
3104+
For example:
3105+
3106+
.. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Numerics.Fixed_Point_Types.Fixed_Small_Delta
3107+
3108+
with Ada.Text_IO; use Ada.Text_IO;
3109+
3110+
procedure Show_Fixed_Small_Delta is
3111+
3112+
type Ordinary_Fixed_Point is
3113+
delta 0.25
3114+
range -2.0 .. 2.0;
3115+
3116+
begin
3117+
Put_Line ("Ordinary_Fixed_Point'Small: "
3118+
& Ordinary_Fixed_Point'Small'Image);
3119+
Put_Line ("Ordinary_Fixed_Point'Delta: "
3120+
& Ordinary_Fixed_Point'Delta'Image);
3121+
Put_Line ("Ordinary_Fixed_Point'Size: "
3122+
& Ordinary_Fixed_Point'Size'Image);
3123+
end Show_Fixed_Small_Delta;
3124+
3125+
In this example, we see the values for the compiler-selected *small* and the
3126+
*delta* of type :ada:`Ordinary_Fixed_Point`. (Both are 0.25.)
3127+
3128+
When we declare a fixed-point data type, we must specify the *delta*. In
3129+
contrast, providing a *small* in the type declaration is optional.
3130+
3131+
When the *small* isn't specified, it is automatically selected by the compiler.
3132+
In this case, the actual value of the *small* is an implementation-defined
3133+
power of ten for decimal fixed-point types and a power of two for ordinary
3134+
fixed-point types. Again, the selected value always follows the rule that the
3135+
*small* must be smaller or equal to the delta. For example:
3136+
3137+
.. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Numerics.Fixed_Point_Types.Fixed_Small_Delta
3138+
3139+
with Ada.Text_IO; use Ada.Text_IO;
3140+
3141+
procedure Show_Fixed_Small_Delta is
3142+
3143+
type Ordinary_Fixed_Point is
3144+
delta 0.2
3145+
range -2.0 .. 2.0;
3146+
3147+
begin
3148+
Put_Line ("Ordinary_Fixed_Point'Small: "
3149+
& Ordinary_Fixed_Point'Small'Image);
3150+
Put_Line ("Ordinary_Fixed_Point'Delta: "
3151+
& Ordinary_Fixed_Point'Delta'Image);
3152+
Put_Line ("Ordinary_Fixed_Point'Size: "
3153+
& Ordinary_Fixed_Point'Size'Image);
3154+
end Show_Fixed_Small_Delta;
3155+
3156+
In this example, the *delta* that we specifed for :ada:`Ordinary_Fixed_Point`
3157+
is 0.2, while the compiler-selected *small* is 2.0\ :sup:`-3`.
3158+
3159+
If we want to specify the *small*, we can use the :ada:`Small` aspect. (we'll
3160+
see this aspect again later on.)
3161+
3162+
.. todo::
3163+
3164+
Add link to subsection on :ada:`Small` aspect once available.
3165+
3166+
However, we can only do so for ordinary fixed-point types: for decimal
3167+
fixed-point types, the *small* is automatically selected by the compiler, and
3168+
it's always equal to the *delta*.
3169+
3170+
.. admonition:: For further reading...
3171+
3172+
As we've mentioned, the small and the delta need not actually be small
3173+
numbers.
3174+
They can be arbitrarily large. For instance, they could be 1.0, or 1000.0.
3175+
Consider the following example:
3176+
3177+
.. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Numerics.Fixed_Point_Types.Large_Small_Attribute
3178+
3179+
package Fixed_Point_Defs is
3180+
S : constant := 32;
3181+
Exp : constant := 128;
3182+
D : constant := 2.0 ** (-S + Exp + 1);
3183+
3184+
type Fixed is delta D
3185+
range -1.0 * 2.0 ** Exp ..
3186+
1.0 * 2.0 ** Exp - D;
3187+
3188+
pragma Assert (Fixed'Size = S);
3189+
end Fixed_Point_Defs;
3190+
3191+
with Fixed_Point_Defs; use Fixed_Point_Defs;
3192+
with Ada.Text_IO; use Ada.Text_IO;
3193+
3194+
procedure Show_Fixed_Type_Info is
3195+
begin
3196+
Put_Line ("Size : "
3197+
& Fixed'Size'Image);
3198+
Put_Line ("Small : "
3199+
& Fixed'Small'Image);
3200+
Put_Line ("Delta : "
3201+
& Fixed'Delta'Image);
3202+
Put_Line ("First : "
3203+
& Fixed'First'Image);
3204+
Put_Line ("Last : "
3205+
& Fixed'Last'Image);
3206+
end Show_Fixed_Type_Info;
3207+
3208+
In this example, the *small* of the :ada:`Fixed` type is actually quite
3209+
large: 1.58456325028528675\ :sup:`29`. (Also, the first and the last values
3210+
are large: -340,282,366,920,938,463,463,374,607,431,768,211,456.0 and
3211+
340,282,366,762,482,138,434,845,932,244,680,310,784.0, or approximately
3212+
-3.4028\ :sup:`38` and 3.4028\ :sup:`38`.)
30123213

3013-
.. _Adv_Ada_Fixed_Point_Types:
3214+
In this case, if we assign 1 or 1,000 to a variable :ada:`F` of this type,
3215+
the actual value stored in :ada:`F` is zero. Feel free to try this out!
30143216

3015-
Fixed-point types
3016-
-----------------
30173217

3018-
.. todo::
30193218

3020-
Complete section!
30213219

30223220

30233221
.. ::

content/courses/intro-to-ada/chapters/fixed_point_types.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.. _Intro_Ada_Fixed_Point_Types:
2+
13
Fixed-point types
24
=================
35

0 commit comments

Comments
 (0)