@@ -964,6 +964,105 @@ by a variable of type :ada:`T3_D3`, and assigning it to a variable of type
964964conversions because the underlying types for the fixed-point division operation
965965are universal fixed types.
966966
967+ .. admonition :: For further reading...
968+
969+ It's possible to implement custom :ada: `* ` and :ada: `/ ` operators for
970+ fixed-point types. However, those operators do **not ** override the
971+ corresponding operators for universal fixed-point types. For example:
972+
973+ .. code :: ada run_button project=Courses.Advanced_Ada.Data_Types.Types.Universal_Types.Fixed_Point_Custom_Multiplication
974+
975+ package Normalized_Fixed_Point_Types is
976+
977+ type TQ63 is
978+ delta 2.0 ** (-63)
979+ range -1.0 .. 1.0 - 2.0 ** (-63);
980+
981+ type TQ31 is
982+ delta 2.0 ** (-31)
983+ range -1.0 .. 1.0 - 2.0 ** (-31);
984+
985+ overriding
986+ -- ^^^^^^
987+ -- "+" operator is overriding!
988+ function "+" (L, R: TQ31)
989+ return TQ31;
990+
991+ not overriding
992+ -- ^^^^^^^^^^
993+ -- "*" operator is NOT overriding!
994+ function "*" (L, R: TQ31)
995+ return TQ31;
996+
997+ type TQ15 is
998+ delta 2.0 ** (-15)
999+ range -1.0 .. 1.0 - 2.0 ** (-15);
1000+
1001+ end Normalized_Fixed_Point_Types;
1002+
1003+ with Ada.Text_IO; use Ada.Text_IO;
1004+
1005+ package body Normalized_Fixed_Point_Types is
1006+
1007+ function "+" (L, R: TQ31)
1008+ return TQ31 is
1009+ begin
1010+ Put_Line ("Using the overriding ´+' operator");
1011+ return TQ31 (TQ63 (L) + TQ63 (R));
1012+ end "+";
1013+
1014+ function "*" (L, R: TQ31)
1015+ return TQ31 is
1016+ begin
1017+ Put_Line ("Using the non-overriding ´*' operator");
1018+ return TQ31 (TQ63 (L) * TQ63 (R));
1019+ end "*";
1020+
1021+ end Normalized_Fixed_Point_Types;
1022+
1023+ with Ada.Text_IO; use Ada.Text_IO;
1024+
1025+ with Normalized_Fixed_Point_Types;
1026+ use Normalized_Fixed_Point_Types;
1027+
1028+ procedure Show_Fixed_Multiplication is
1029+ Q31_A : TQ31 := 0.25;
1030+ Q31_B : TQ31 := 0.50;
1031+ Q15_A : TQ15 := 0.25;
1032+ Q15_B : TQ15 := 0.50;
1033+ begin
1034+ Q31_A := Q31_A * Q31_B;
1035+ Put_Line ("Q31_A = " & Q31_A'Image);
1036+
1037+ Q15_A := Q15_A * Q15_B;
1038+ Put_Line ("Q15_A = " & Q31_A'Image);
1039+
1040+ Q15_A := TQ15 (Q31_A) * Q15_B;
1041+ -- ^^^^^^^^^^^^
1042+ -- A conversion is required because of
1043+ -- the multiplication operator of
1044+ -- TQ15.
1045+ Put_Line ("Q31_A = " & Q31_A'Image);
1046+ end Show_Fixed_Multiplication;
1047+
1048+ In this example, we're declaring a custom multiplication operator for the
1049+ :ada: `TQ31 ` type. As we can see in the declaration, we specify that it's
1050+ :ada: `not overriding ` the :ada: `* ` operator. (Removing the :ada: `not `
1051+ keyword triggers a compilation error.) In contrast, for the :ada: `+ `
1052+ operator, we're indeed overriding the default :ada: `+ ` operator of the
1053+ :ada: `TQ31 ` type in the :ada: `Normalized_Fixed_Point_Types ` because the
1054+ addition operator is associate with its corresponding fixed-point type,
1055+ not with the universal fixed-point type. In the
1056+ :ada: `Q31_A := Q31_A * Q31_B ` statement, we see at runtime (through the
1057+ "Using the non-overriding ´*' operator" message) that the custom
1058+ multiplication is being used.
1059+
1060+ However, because of this custom :ada: `* ` operator, we cannot mix objects of
1061+ this type with objects of other fixed-point types in multiplication or
1062+ division operations. Therefore, for a statement such as
1063+ :ada: `Q15_A := Q31_A * Q15_B `, we have to convert :ada: `Q31_A ` to the
1064+ :ada: `TQ15 ` type before multiplying it by :ada: `Q15_B `.
1065+
9671066.. admonition :: In the Ada Reference Manual
9681067
9691068 - :arm22: `4.5.5 Multiplying Operators <4-5-5> `
0 commit comments