@@ -3008,16 +3008,214 @@ decimal precision greater than the maximum supported precision. Therefore,
30083008compilation 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.. ::
0 commit comments