* Fixed point constants issue @ 2010-09-13 17:27 Vinzent Hoefler 2010-09-13 18:04 ` Dmitry A. Kazakov 0 siblings, 1 reply; 30+ messages in thread From: Vinzent Hoefler @ 2010-09-13 17:27 UTC (permalink / raw) Is this a GNAT bug or am I just stupid? Suppose we have a fixed point type (with a rather large delta): -- 8< -- with Ada.Text_IO; use Ada.Text_IO; procedure Fixed_Point is FEET_PER_METER : constant := 0.3048; HEIGHT : constant := 10; -- Feet type Altitude is delta (2.0**15 / 50_000.0) range 0.0 .. 50_000.0; TEN_FEET_1 : constant := HEIGHT * FEET_PER_METER; TEN_FEET_2 : constant Altitude := HEIGHT * FEET_PER_METER; TEN_FEET_3 : constant Altitude := TEN_FEET_1; TEN_FEET_4 : constant Altitude := Altitude (HEIGHT * FEET_PER_METER); begin Put_Line ("10 feet ~" & Altitude'Image (TEN_FEET_1) & " m."); Put_Line ("10 feet ~" & Altitude'Image (TEN_FEET_2) & " m."); Put_Line ("10 feet ~" & Altitude'Image (TEN_FEET_3) & " m."); Put_Line ("10 feet ~" & Altitude'Image (TEN_FEET_4) & " m."); end Fixed_Point; -- 8< -- Now let's run the test: 10 feet ~ 3.0 m. 10 feet ~ 0.0 m. <--- *oops*!? 10 feet ~ 3.0 m. 10 feet ~ 3.0 m. I can see what's going on in case of TEN_FEET_2 ("FEET_PER_METER" equals zero after the obviously happening type conversion to Altitude), but I sure wouldn't expect such a behavior from an Ada compiler, especially not when TEN_FEET_4 gives the expected result again[1]. To add to the confusion, the target compiler actually even does it the "right" (or rather: expected) way; but after reading all the relevant paragraphs in the ARM again and again, I still do not know if GNAT does it wrong here, or if we just entered one of the few dark corners in the Ada language. Can anyone shed some light on this? This has driven us crazy for weeks now. Vinzent. [1] Of course, "Altitude'(HEIGHT * FEET_PER_METER)" yields "0.0" again. At least this is consistent with my understanding so far. -- There is no signature. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-13 17:27 Fixed point constants issue Vinzent Hoefler @ 2010-09-13 18:04 ` Dmitry A. Kazakov 2010-09-13 18:25 ` Vinzent Hoefler 2010-09-14 19:44 ` Keith Thompson 0 siblings, 2 replies; 30+ messages in thread From: Dmitry A. Kazakov @ 2010-09-13 18:04 UTC (permalink / raw) On Mon, 13 Sep 2010 19:27:30 +0200, Vinzent Hoefler wrote: > Is this a GNAT bug or am I just stupid? > > Suppose we have a fixed point type (with a rather large delta): > > -- 8< -- > with Ada.Text_IO; use Ada.Text_IO; > > procedure Fixed_Point > is > FEET_PER_METER : constant := 0.3048; > HEIGHT : constant := 10; -- Feet > > type Altitude is delta (2.0**15 / 50_000.0) range 0.0 .. 50_000.0; [...] > Can anyone shed some light on this? This has driven us crazy for weeks now. > > [1] Of course, "Altitude'(HEIGHT * FEET_PER_METER)" yields "0.0" again. > At least this is consistent with my understanding so far. Hmm, what did you expect? 0.3048 (FEET_PER_METER) is 0 when Altitude. That is because 2.0**15/50_000.0=0.65536 > 0.3048. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-13 18:04 ` Dmitry A. Kazakov @ 2010-09-13 18:25 ` Vinzent Hoefler 2010-09-13 19:05 ` Niklas Holsti 2010-09-13 20:32 ` Dmitry A. Kazakov 2010-09-14 19:44 ` Keith Thompson 1 sibling, 2 replies; 30+ messages in thread From: Vinzent Hoefler @ 2010-09-13 18:25 UTC (permalink / raw) On Mon, 13 Sep 2010 20:04:32 +0200, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote: > On Mon, 13 Sep 2010 19:27:30 +0200, Vinzent Hoefler wrote: > >> Is this a GNAT bug or am I just stupid? >> >> Suppose we have a fixed point type (with a rather large delta): >> >> -- 8< -- >> with Ada.Text_IO; use Ada.Text_IO; >> >> procedure Fixed_Point >> is >> FEET_PER_METER : constant := 0.3048; >> HEIGHT : constant := 10; -- Feet >> >> type Altitude is delta (2.0**15 / 50_000.0) range 0.0 .. 50_000.0; > > [...] >> Can anyone shed some light on this? This has driven us crazy for weeks >> now. >> >> [1] Of course, "Altitude'(HEIGHT * FEET_PER_METER)" yields "0.0" again. >> At least this is consistent with my understanding so far. > > Hmm, what did you expect? 0.3048 (FEET_PER_METER) is 0 when Altitude. > That is because 2.0**15/50_000.0=0.65536 > 0.3048. Yes, of course. Still, it's not quite intuitive why TEN_FEET_1 : constant := HEIGHT * FEET_PER_METER; TEN_FEET_2 : constant Altitude := HEIGHT * FEET_PER_METER; just because a type is given in the second case. I would expect the compiler to evaluate the expression "HEIGHT * FEET_PER_METER" _before_ converting it to the appropriate fixed point type. And, obviously it does this that when evaluating TEN_FEET_4 : constant Altitude := Altitude (HEIGHT * FEET_PER_METER); In our opinion, this type conversion on the right hand side shouldn't be necessary, yet it is (with GNAT). Vinzent. -- There is no signature. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-13 18:25 ` Vinzent Hoefler @ 2010-09-13 19:05 ` Niklas Holsti 2010-09-13 20:35 ` Vinzent Hoefler 2010-09-13 20:35 ` Jeffrey Carter 2010-09-13 20:32 ` Dmitry A. Kazakov 1 sibling, 2 replies; 30+ messages in thread From: Niklas Holsti @ 2010-09-13 19:05 UTC (permalink / raw) Vinzent Hoefler wrote: > On Mon, 13 Sep 2010 20:04:32 +0200, Dmitry A. Kazakov > <mailbox@dmitry-kazakov.de> wrote: > >> On Mon, 13 Sep 2010 19:27:30 +0200, Vinzent Hoefler wrote: >> >>> Is this a GNAT bug or am I just stupid? >>> >>> Suppose we have a fixed point type (with a rather large delta): >>> >>> -- 8< -- >>> with Ada.Text_IO; use Ada.Text_IO; >>> >>> procedure Fixed_Point >>> is >>> FEET_PER_METER : constant := 0.3048; >>> HEIGHT : constant := 10; -- Feet >>> >>> type Altitude is delta (2.0**15 / 50_000.0) range 0.0 .. 50_000.0; >> >> [...] >>> Can anyone shed some light on this? This has driven us crazy for >>> weeks now. >>> >>> [1] Of course, "Altitude'(HEIGHT * FEET_PER_METER)" yields "0.0" again. >>> At least this is consistent with my understanding so far. >> >> Hmm, what did you expect? 0.3048 (FEET_PER_METER) is 0 when Altitude. >> That is because 2.0**15/50_000.0=0.65536 > 0.3048. > > Yes, of course. Still, it's not quite intuitive why > > TEN_FEET_1 : constant := HEIGHT * FEET_PER_METER; > TEN_FEET_2 : constant Altitude := HEIGHT * FEET_PER_METER; > > just because a type is given in the second case. I think these cases are clear from the language rules: The declaration of TEN_FEET_1 is a named-number declaration, so the expression is evaluated using the "root" multiplication operator "*" (Left : root_integer; Right : root_real) return root_real, which is done at compile-time and exactly (with unlimited precision). > I would expect the compiler to evaluate the expression > "HEIGHT * FEET_PER_METER" [for TEN_FEET_2] _before_ > converting it to the appropriate fixed point type. The declaration of TEN_FEET_2 is an object declaration with type Altitude, therefore the right-hand-side expression is expected to be of type Altitude and so the "*" will be resolved to the Altitude multiplication operator "*" (Left, Right : Altitude) return Altitude, with result zero. I agree that this is a bit nasty and counter-intuitive. Perhaps the compiler should warn that the conversion of the universal_real number 0.3048 to Altitude is seriously inexact, but then, what is "seriously"? > And, obviously it does this that when evaluating > > TEN_FEET_4 : constant Altitude := Altitude (HEIGHT * FEET_PER_METER); Here the right-hand side expression is a type conversion, in fact a value conversion, and so the operand HEIGHT * FEET_PER_METER is expected to be of any numeric type. At first sight the multiplication could be resolved to the root "*" or to the Altitude "*", which would thus be ambiguous. However, RM 8.6(29) says that the ambiguity is resolved by using the root "*", giving the more precise result. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-13 19:05 ` Niklas Holsti @ 2010-09-13 20:35 ` Vinzent Hoefler 2010-09-13 20:35 ` Jeffrey Carter 1 sibling, 0 replies; 30+ messages in thread From: Vinzent Hoefler @ 2010-09-13 20:35 UTC (permalink / raw) On Mon, 13 Sep 2010 21:05:58 +0200, Niklas Holsti <niklas.holsti@tidorum.invalid> wrote: > Vinzent Hoefler wrote: > > > I would expect the compiler to evaluate the expression > > "HEIGHT * FEET_PER_METER" [for TEN_FEET_2] _before_ > > converting it to the appropriate fixed point type. > > The declaration of TEN_FEET_2 is an object declaration with type > Altitude, therefore the right-hand-side expression is expected to be of > type Altitude and so the "*" will be resolved to the Altitude > multiplication operator "*" (Left, Right : Altitude) return Altitude, > with result zero. That's what I suspected. So, although the result is seriously wrong compared to the mathematical result of the given static expression, the compiler is still correct? :( > I agree that this is a bit nasty and counter-intuitive. Perhaps the > compiler should warn that the conversion of the universal_real number > 0.3048 to Altitude is seriously inexact, but then, what is "seriously"? Well, GNAT warns with a "static fixed-point value is not a multiple of Small", but this one is quite useless, because that warning is issued for virtually every expression in the example, so it's hard to identify the real problematic cases. >> And, obviously it does this that when evaluating >> TEN_FEET_4 : constant Altitude := Altitude (HEIGHT * FEET_PER_METER); > > Here the right-hand side expression is a type conversion, in fact a > value conversion, and so the operand HEIGHT * FEET_PER_METER is expected > to be of any numeric type. At first sight the multiplication could be > resolved to the root "*" or to the Altitude "*", which would thus be > ambiguous. However, RM 8.6(29) says that the ambiguity is resolved by > using the root "*", giving the more precise result. Right. That was the part of the ARM I didn't read. Obviously I was too focused on the fixed point arithmetic model in Annex G 2.3. So, it's the other compiler that does it wrong (according to my colleague, only GNAT gives the "wrong" results)? I may run a short test tomorrow to confirm that this is really the case. There isn't any paragraph in the ARM that would allow the compiler to arbitrarily choose any of both interpretations, is there? Vinzent. -- There is no signature. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-13 19:05 ` Niklas Holsti 2010-09-13 20:35 ` Vinzent Hoefler @ 2010-09-13 20:35 ` Jeffrey Carter 2010-09-13 21:06 ` Vinzent Hoefler ` (2 more replies) 1 sibling, 3 replies; 30+ messages in thread From: Jeffrey Carter @ 2010-09-13 20:35 UTC (permalink / raw) On 09/13/2010 12:05 PM, Niklas Holsti wrote: > > The declaration of TEN_FEET_1 is a named-number declaration, so the > expression is evaluated using the "root" multiplication operator "*" > (Left : root_integer; Right : root_real) return root_real, which is done > at compile-time and exactly (with unlimited precision). Right. > > I would expect the compiler to evaluate the expression > > "HEIGHT * FEET_PER_METER" [for TEN_FEET_2] _before_ > > converting it to the appropriate fixed point type. > > The declaration of TEN_FEET_2 is an object declaration with type > Altitude, therefore the right-hand-side expression is expected to be of > type Altitude and so the "*" will be resolved to the Altitude > multiplication operator "*" (Left, Right : Altitude) return Altitude, > with result zero. More likely, function "*" (Left : in Integer; Right : in Altitude) return Altitude; [ARM 4.5.5(14)]. Feet_Per_Meter will be converted to Altitude before calling this function, resulting in a value of 0.0. Note that this changed between Ada 83 and Ada 95. In Ada 83, the expression is evaluated exactly at compile time using universal_real, just as for the named number. In Ada 95, this was changed to use the "*" function defined for Altitude. If the target compiler gives 3.0 as the value, then perhaps it is an Ada-83 compiler. There is a further wrinkle with the Ada 95 (and current Ada) rule. If "*" has not been overridden, this is a static expression and is evaluated at compile time. If "*" has been overridden, then this is not a static expression and it will be evaluated at run time. -- Jeff Carter "Mr. President, we must not allow a mine-shaft gap!" Dr. Strangelove 33 --- news://freenews.netfront.net/ - complaints: news@netfront.net --- ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-13 20:35 ` Jeffrey Carter @ 2010-09-13 21:06 ` Vinzent Hoefler 2010-09-14 5:39 ` Niklas Holsti 2010-09-24 14:43 ` Markus Schöpflin 2 siblings, 0 replies; 30+ messages in thread From: Vinzent Hoefler @ 2010-09-13 21:06 UTC (permalink / raw) On Mon, 13 Sep 2010 22:35:46 +0200, Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> wrote: > If the target compiler gives 3.0 as the value, then perhaps it is an > Ada-83 compiler. I thought of that, too, but consider it unlikely. We use quite a lot of Ada95 features in the meantime and it still compiles. It also says "Ada95" in the documentation. Vinzent. -- There is no signature. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-13 20:35 ` Jeffrey Carter 2010-09-13 21:06 ` Vinzent Hoefler @ 2010-09-14 5:39 ` Niklas Holsti 2010-09-24 14:43 ` Markus Schöpflin 2 siblings, 0 replies; 30+ messages in thread From: Niklas Holsti @ 2010-09-14 5:39 UTC (permalink / raw) Jeffrey Carter wrote: > On 09/13/2010 12:05 PM, Niklas Holsti wrote: >> >> The declaration of TEN_FEET_2 is an object declaration with type >> Altitude, therefore the right-hand-side expression is expected to be of >> type Altitude and so the "*" will be resolved to the Altitude >> multiplication operator "*" (Left, Right : Altitude) return Altitude, >> with result zero. > > More likely, > > function "*" (Left : in Integer; Right : in Altitude) return Altitude; Yes, my typo, sorry. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-13 20:35 ` Jeffrey Carter 2010-09-13 21:06 ` Vinzent Hoefler 2010-09-14 5:39 ` Niklas Holsti @ 2010-09-24 14:43 ` Markus Schöpflin 2010-09-24 20:05 ` Vinzent Hoefler 2010-09-24 21:38 ` Jeffrey Carter 2 siblings, 2 replies; 30+ messages in thread From: Markus Schöpflin @ 2010-09-24 14:43 UTC (permalink / raw) Forgive me for resurrecting an old thread, but when trying to understand the issue, I came up with more questions... Am 13.09.2010 22:35, schrieb Jeffrey Carter: > Note that this changed between Ada 83 and Ada 95. In Ada 83, the expression > is evaluated exactly at compile time using universal_real, just as for the > named number. In Ada 95, this was changed to use the "*" function defined > for Altitude. Are you sure about that? Because I compiled and ran the following program with an Ada 83 compiler (DEC Ada) and I got a different result. Note that I modified the delta to 0.5 to avoid any issues resulting from delta /= small. ---%<--- with TEXT_IO; use TEXT_IO; procedure FIXED_POINT is type ALTITUDE is delta 0.5 range 0.0 .. 50_000.0; package ALTITUDE_IO is new FIXED_IO (ALTITUDE); FEET_PER_METER : constant := 0.3048; HEIGHT : constant := 10; -- Feet TEN_FEET_1 : constant := HEIGHT * FEET_PER_METER; TEN_FEET_2 : constant ALTITUDE := HEIGHT * FEET_PER_METER; begin ALTITUDE_IO.PUT (TEN_FEET_1); NEW_LINE; -- gives 3.0 ALTITUDE_IO.PUT (TEN_FEET_2); NEW_LINE; -- gives 5.0 (*) end FIXED_POINT; --->%--- (*) This certainly looks like FEET_PER_METER is converted to ALTITUDE before doing the multiplication. Another question regarding the implicit conversion from universal_real to ALTITUDE: Does ARM83-3.5.6 apply here? And what does this mean: "If the universal_real value is a safe number, the implicit conversion delivers the corresponding value; if it belongs to the range of safe numbers but is not a safe number, then the converted value can be any value within the range defined by the safe numbers next above and below the universal_real value." Is the compiler free to convert FEET_PER_METER to either 0.0 or 0.5? Regards, Markus ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-24 14:43 ` Markus Schöpflin @ 2010-09-24 20:05 ` Vinzent Hoefler 2010-09-24 21:38 ` Jeffrey Carter 1 sibling, 0 replies; 30+ messages in thread From: Vinzent Hoefler @ 2010-09-24 20:05 UTC (permalink / raw) On Fri, 24 Sep 2010 16:43:29 +0200, Markus Schöpflin <no@spam.spam> wrote: > TEN_FEET_1 : constant := HEIGHT * FEET_PER_METER; > TEN_FEET_2 : constant ALTITUDE := HEIGHT * FEET_PER_METER; > begin > ALTITUDE_IO.PUT (TEN_FEET_1); NEW_LINE; -- gives 3.0 > ALTITUDE_IO.PUT (TEN_FEET_2); NEW_LINE; -- gives 5.0 (*) > end FIXED_POINT; > --->%--- > > (*) This certainly looks like FEET_PER_METER is converted to ALTITUDE > before doing the multiplication. Now that's interesting. Let me re-iterate: We have an Ada95 compiler behaving as expected (although not necessarily intuitive) (GNAT), an Ada95 compiler behaving like what's supposed to be an Ada83 difference (GreenHills, to finally reveal the name), and now an Ada83 compiler behaving as if it were an Ada95 compiler. At least according to what I understood so far... seriously, I'm no less confused than I was before. > Another question regarding the implicit conversion from universal_real > to ALTITUDE: Does ARM83-3.5.6 apply here? And what does this mean: "If > the universal_real value is a safe number, the implicit conversion > delivers the corresponding value; if it belongs to the range of safe > numbers but is not a safe number, then the converted value can be any > value within the range defined by the safe numbers next above and below > the universal_real value." Is the compiler free to convert > FEET_PER_METER to either 0.0 or 0.5? This would by my understanding, Ada95 puts it in different terms, but basically the compiler seems to be allowed to choose any of both choices. But IANALL (although today a call from my co-worker started with "Ada Support there?" *g*). Vinzent. -- There is no signature. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-24 14:43 ` Markus Schöpflin 2010-09-24 20:05 ` Vinzent Hoefler @ 2010-09-24 21:38 ` Jeffrey Carter 2010-09-24 22:42 ` Vinzent Hoefler 2010-09-27 17:58 ` Adam Beneschan 1 sibling, 2 replies; 30+ messages in thread From: Jeffrey Carter @ 2010-09-24 21:38 UTC (permalink / raw) On 09/24/2010 07:43 AM, Markus Schöpflin wrote: > > Are you sure about that? Because I compiled and ran the following > program with an Ada 83 compiler (DEC Ada) and I got a different result. > Note that I modified the delta to 0.5 to avoid any issues resulting from > delta /= small. > > ---%<--- > with TEXT_IO; use TEXT_IO; > > procedure FIXED_POINT > is > type ALTITUDE is delta 0.5 range 0.0 .. 50_000.0; > > package ALTITUDE_IO is new FIXED_IO (ALTITUDE); > > FEET_PER_METER : constant := 0.3048; > HEIGHT : constant := 10; -- Feet > > TEN_FEET_1 : constant := HEIGHT * FEET_PER_METER; > TEN_FEET_2 : constant ALTITUDE := HEIGHT * FEET_PER_METER; > begin > ALTITUDE_IO.PUT (TEN_FEET_1); NEW_LINE; -- gives 3.0 > ALTITUDE_IO.PUT (TEN_FEET_2); NEW_LINE; -- gives 5.0 (*) > end FIXED_POINT; > --->%--- > > (*) This certainly looks like FEET_PER_METER is converted to ALTITUDE > before doing the multiplication. That is interesting. I learned Ada 83 in 1984; I was explicitly taught that static universal (sub)expressions were evaluated exactly by the compiler, using universal operations. For example, I was taught that in Pi : constant := 3.14159; X : Float; ... Reduce : loop exit Reduce when X < Pi / 2; X := X - Pi / 2; end loop Reduce; both occurrences of "Pi / 2" would be evaluated exactly by the compiler. Perhaps I was taught wrong. -- Jeff Carter "We use a large, vibrating egg." Annie Hall 44 ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-24 21:38 ` Jeffrey Carter @ 2010-09-24 22:42 ` Vinzent Hoefler 2010-09-25 0:16 ` Jeffrey Carter 2010-09-27 17:58 ` Adam Beneschan 1 sibling, 1 reply; 30+ messages in thread From: Vinzent Hoefler @ 2010-09-24 22:42 UTC (permalink / raw) On Fri, 24 Sep 2010 23:38:11 +0200, Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> wrote: > That is interesting. I learned Ada 83 in 1984; I was explicitly taught > that static universal (sub)expressions were evaluated exactly by the > compiler, using universal operations. 3.5.9 says: Multiplication and division of fixed point values deliver results of a fixed point type with an arbitrarily fine accuracy [...] which is referred to [...] as /universal_fixed/. And then 4.5.8 (referenced by 3.5.9) seems quite clear about that: The bounds on a real value resulting from a predefined operation are defined by the three following steps: (1) A model interval of the appropriate type or subtype is associated with the value of each operand. (2) A new interval is formed by applying the (exact) mathematical operation to operands from the model intervals produced in step (1). [...] Vinzent. -- There is no signature. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-24 22:42 ` Vinzent Hoefler @ 2010-09-25 0:16 ` Jeffrey Carter 2010-09-27 10:33 ` Markus Schöpflin 0 siblings, 1 reply; 30+ messages in thread From: Jeffrey Carter @ 2010-09-25 0:16 UTC (permalink / raw) On 09/24/2010 03:42 PM, Vinzent Hoefler wrote: > > 3.5.9 says: > > Multiplication and division of fixed point values deliver results of a > fixed point type with > an arbitrarily fine accuracy [...] which is referred to [...] as > /universal_fixed/. Yes. But these are not fixed-point values. One is universal_integer and the other is universal_real. The question is whether "*" is the one defined for universal_real or for the fixed-point type. In the latter case, the universal_real value would be converted to the fixed-point type before calling "*". ARM83 4.10 says that static, universal expressions are evaluated exactly. The question seems to be whether the expression is universal. ARM83 4.4 seems to be the place to look for that, but I'm not sure which it requires. -- Jeff Carter "We use a large, vibrating egg." Annie Hall 44 ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-25 0:16 ` Jeffrey Carter @ 2010-09-27 10:33 ` Markus Schöpflin 2010-09-27 18:57 ` Jeffrey Carter 0 siblings, 1 reply; 30+ messages in thread From: Markus Schöpflin @ 2010-09-27 10:33 UTC (permalink / raw) Am 25.09.2010 02:16, schrieb Jeffrey Carter: > On 09/24/2010 03:42 PM, Vinzent Hoefler wrote: >> >> 3.5.9 says: >> >> Multiplication and division of fixed point values deliver results of a >> fixed point type with >> an arbitrarily fine accuracy [...] which is referred to [...] as >> /universal_fixed/. > > Yes. But these are not fixed-point values. One is universal_integer and the > other is universal_real. The question is whether "*" is the one defined for > universal_real or for the fixed-point type. In the latter case, the > universal_real value would be converted to the fixed-point type before > calling "*". > > ARM83 4.10 says that static, universal expressions are evaluated exactly. > The question seems to be whether the expression is universal. ARM83 4.4 > seems to be the place to look for that, but I'm not sure which it requires. We have three different overloads for "*" to consider. One is universal_integer * universal_real -> universal_real [4.10] The next is INTEGER * ALTITUDE -> ALTITUDE [4.5.5] The third is ALTITUDE * ALTITUDE -> ALTITUDE [4.5.5] I think the key to the answer is in ARM83 4.6: "Apart from the explicit type conversions, the only allowed form of type conversion is the implicit conversion of a value of the type universal_integer or universal_real into another numeric type. An implicit conversion of an operand of type universal_integer to another integer type, or of an operand of type universal_real to another real type, can only be applied if the operand is either a numeric literal, a named number, or an attribute; such an operand is called a convertible universal operand in this section. An implicit conversion of a convertible universal operand is applied if and only if the innermost complete context (see 8.7) determines a unique (numeric) target type for the implicit conversion, and there is no legal interpretation of this context without this conversion." There is no conversion from universal_integer to ALTITUDE, therefore the third overload cannot be chosen. The implicit conversion from universal_real to ALTITUDE is only done when the operand is either a numeric literal, a named number, or an attribute. This rules out the first overload. Therefore we have only the second overload left which is chosen because of an implicit conversion from universal_integer to INTEGER and from universal_real to ALTITUDE. And the different results we're seeing are due to [3.5.6] which, if I understand the text correctly, allows the result of the conversion from FEET_PER_METER to be either 0 or 0.5. Can someone confirm this reasoning? Markus ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-27 10:33 ` Markus Schöpflin @ 2010-09-27 18:57 ` Jeffrey Carter 2010-09-28 8:16 ` Markus Schöpflin 0 siblings, 1 reply; 30+ messages in thread From: Jeffrey Carter @ 2010-09-27 18:57 UTC (permalink / raw) On 09/27/2010 03:33 AM, Markus Schöpflin wrote: > > The implicit conversion from universal_real to ALTITUDE is only done > when the operand is either a numeric literal, a named number, or an > attribute. This rules out the first overload. I don't follow this. -- Jeff Carter "Sir Lancelot saves Sir Gallahad from almost certain temptation." Monty Python & the Holy Grail 69 ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-27 18:57 ` Jeffrey Carter @ 2010-09-28 8:16 ` Markus Schöpflin 2010-09-28 17:28 ` Jeffrey Carter 0 siblings, 1 reply; 30+ messages in thread From: Markus Schöpflin @ 2010-09-28 8:16 UTC (permalink / raw) Am 27.09.2010 20:57, schrieb Jeffrey Carter: > On 09/27/2010 03:33 AM, Markus Schöpflin wrote: >> >> The implicit conversion from universal_real to ALTITUDE is only done >> when the operand is either a numeric literal, a named number, or an >> attribute. This rules out the first overload. > > I don't follow this. Could you please elaborate? To quote ARM83 4.6 again: "An implicit conversion of an operand of type [...] universal_real to another real type, can only be applied if the operand is either a numeric literal, a named number, or an attribute; [...]" So an implicit conversion will never be applied to the result of universal_integer * universal_real, as the operand of the conversion is an expression. But an implicit conversion to ALTITUDE would be needed for universal_integer * universal_real -> universal_real to be used. On the other hand, the line "TEN_FEET_3 : constant Altitude := TEN_FEET_1;" from the original example does use an implicit conversion, precisely because TEN_FEET_1 is a named number of type universal_real. Or am I completely off track here? Markus ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-28 8:16 ` Markus Schöpflin @ 2010-09-28 17:28 ` Jeffrey Carter 2010-10-05 6:27 ` Randy Brukardt 0 siblings, 1 reply; 30+ messages in thread From: Jeffrey Carter @ 2010-09-28 17:28 UTC (permalink / raw) On 09/28/2010 01:16 AM, Markus Schöpflin wrote: > > To quote ARM83 4.6 again: "An implicit conversion of an operand of type > [...] universal_real to another real type, can only be applied if the > operand is either a numeric literal, a named number, or an attribute; > [...]" > > So an implicit conversion will never be applied to the result of > universal_integer * universal_real, as the operand of the conversion is > an expression. But an implicit conversion to ALTITUDE would be needed > for universal_integer * universal_real -> universal_real to be used. Having read the section, I see what you're saying now. I was unclear because of the use of "operand"; I thought it referred to an operand of "*", but it refers to the operand of the implicit type conversion. This does seem to indicate that function "*" (Left : Integer; Right : Altitude) return Altitude; is used in this case, and what I was taught is incorrect. It would be nice to hear from someone who implemented an Ada-83 compiler. We know you're out there. -- Jeff Carter "People called Romanes, they go the house?" Monty Python's Life of Brian 79 ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-28 17:28 ` Jeffrey Carter @ 2010-10-05 6:27 ` Randy Brukardt 2010-10-05 18:40 ` Jeffrey Carter 0 siblings, 1 reply; 30+ messages in thread From: Randy Brukardt @ 2010-10-05 6:27 UTC (permalink / raw) "Jeffrey Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message news:i7t9el$95r$1@tornado.tornevall.net... ... > It would be nice to hear from someone who implemented an Ada-83 compiler. > We know you're out there. I don't remember for certain, but my recollection is that Ada 83 always implicitly converts the leaves of an expression tree; that is operations on universal types are only used for named numbers, operands of type conversions and the like. I don't think Ada 95 changed this significantly (the way the rules are presented was changed a lot, but that's not particularly important). I remember hearing the exact evaluation saw as well, but I don't think it was ever true other than in very limited cases. Randy (who did write an Ada 83 compiler). ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-10-05 6:27 ` Randy Brukardt @ 2010-10-05 18:40 ` Jeffrey Carter 0 siblings, 0 replies; 30+ messages in thread From: Jeffrey Carter @ 2010-10-05 18:40 UTC (permalink / raw) On 10/04/2010 11:27 PM, Randy Brukardt wrote: > "Jeffrey Carter"<spam.jrcarter.not@spam.not.acm.org> wrote in message > news:i7t9el$95r$1@tornado.tornevall.net... > ... >> It would be nice to hear from someone who implemented an Ada-83 compiler. >> We know you're out there. > > Randy (who did write an Ada 83 compiler). I know. I used it. -- Jeff Carter "English bed-wetting types." Monty Python & the Holy Grail 15 ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-24 21:38 ` Jeffrey Carter 2010-09-24 22:42 ` Vinzent Hoefler @ 2010-09-27 17:58 ` Adam Beneschan 1 sibling, 0 replies; 30+ messages in thread From: Adam Beneschan @ 2010-09-27 17:58 UTC (permalink / raw) On Sep 24, 2:38 pm, Jeffrey Carter <spam.jrcarter....@spam.not.acm.org> wrote: > On 09/24/2010 07:43 AM, Markus Schöpflin wrote: > > > > > > > > > Are you sure about that? Because I compiled and ran the following > > program with an Ada 83 compiler (DEC Ada) and I got a different result. > > Note that I modified the delta to 0.5 to avoid any issues resulting from > > delta /= small. > > > ---%<--- > > with TEXT_IO; use TEXT_IO; > > > procedure FIXED_POINT > > is > > type ALTITUDE is delta 0.5 range 0.0 .. 50_000.0; > > > package ALTITUDE_IO is new FIXED_IO (ALTITUDE); > > > FEET_PER_METER : constant := 0.3048; > > HEIGHT : constant := 10; -- Feet > > > TEN_FEET_1 : constant := HEIGHT * FEET_PER_METER; > > TEN_FEET_2 : constant ALTITUDE := HEIGHT * FEET_PER_METER; > > begin > > ALTITUDE_IO.PUT (TEN_FEET_1); NEW_LINE; -- gives 3.0 > > ALTITUDE_IO.PUT (TEN_FEET_2); NEW_LINE; -- gives 5.0 (*) > > end FIXED_POINT; > > --->%--- > > > (*) This certainly looks like FEET_PER_METER is converted to ALTITUDE > > before doing the multiplication. > > That is interesting. I learned Ada 83 in 1984; I was explicitly taught that > static universal (sub)expressions were evaluated exactly by the compiler, using > universal operations. For example, I was taught that in > > Pi : constant := 3.14159; > > X : Float; > ... > Reduce : loop > exit Reduce when X < Pi / 2; > > X := X - Pi / 2; > end loop Reduce; > > both occurrences of "Pi / 2" would be evaluated exactly by the compiler. Perhaps > I was taught wrong. Hmmm... in looking into this, I bumped into AI83-165 which would make it appear that the use of Pi/2 in both occurrences is illegal. But maybe that AI got superseded by some other AI. I don't know. -- Adam ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-13 18:25 ` Vinzent Hoefler 2010-09-13 19:05 ` Niklas Holsti @ 2010-09-13 20:32 ` Dmitry A. Kazakov 2010-09-13 21:08 ` Vinzent Hoefler 1 sibling, 1 reply; 30+ messages in thread From: Dmitry A. Kazakov @ 2010-09-13 20:32 UTC (permalink / raw) On Mon, 13 Sep 2010 20:25:43 +0200, Vinzent Hoefler wrote: > On Mon, 13 Sep 2010 20:04:32 +0200, Dmitry A. Kazakov > <mailbox@dmitry-kazakov.de> wrote: > >> On Mon, 13 Sep 2010 19:27:30 +0200, Vinzent Hoefler wrote: >> >>> Is this a GNAT bug or am I just stupid? >>> >>> Suppose we have a fixed point type (with a rather large delta): >>> >>> -- 8< -- >>> with Ada.Text_IO; use Ada.Text_IO; >>> >>> procedure Fixed_Point >>> is >>> FEET_PER_METER : constant := 0.3048; >>> HEIGHT : constant := 10; -- Feet >>> >>> type Altitude is delta (2.0**15 / 50_000.0) range 0.0 .. 50_000.0; >> >> [...] >>> Can anyone shed some light on this? This has driven us crazy for weeks >>> now. >>> >>> [1] Of course, "Altitude'(HEIGHT * FEET_PER_METER)" yields "0.0" again. >>> At least this is consistent with my understanding so far. >> >> Hmm, what did you expect? 0.3048 (FEET_PER_METER) is 0 when Altitude. >> That is because 2.0**15/50_000.0=0.65536 > 0.3048. > > Yes, of course. Still, it's not quite intuitive why > > TEN_FEET_1 : constant := HEIGHT * FEET_PER_METER; > TEN_FEET_2 : constant Altitude := HEIGHT * FEET_PER_METER; > > just because a type is given in the second case. Different types, different behavior. > I would expect the compiler to evaluate the expression "HEIGHT * > FEET_PER_METER" _before_ converting it to the appropriate fixed point type. Why? "*" is defined on Altitude. You should rather wonder why the result is different for TEN_FEET_4. Multiplication is inexact taking rounding this or that way you get different results. > And, obviously it does this that when evaluating > > TEN_FEET_4 : constant Altitude := Altitude (HEIGHT * FEET_PER_METER); Well, it does not, because here another type is involved. But what about: X : constant Altitude := 0.3048; -- The result is 0 Does it wonder you? You should consider fixed point values intervals. So 0 is actually something like [0, 0.65536[. When multiplied to 10 it becomes [0, 6.5536[. That thing has 10 intervals of 0.65536 width in it. "0"=[0, 0.65536[ and "3"=[3.048, 3.70336[ are just two of them. The choice is more or less arbitrary. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-13 20:32 ` Dmitry A. Kazakov @ 2010-09-13 21:08 ` Vinzent Hoefler 2010-09-14 6:54 ` J-P. Rosen 2010-09-14 7:47 ` Dmitry A. Kazakov 0 siblings, 2 replies; 30+ messages in thread From: Vinzent Hoefler @ 2010-09-13 21:08 UTC (permalink / raw) On Mon, 13 Sep 2010 22:32:05 +0200, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote: > On Mon, 13 Sep 2010 20:25:43 +0200, Vinzent Hoefler wrote: > >> Yes, of course. Still, it's not quite intuitive why >> >> TEN_FEET_1 : constant := HEIGHT * FEET_PER_METER; >> TEN_FEET_2 : constant Altitude := HEIGHT * FEET_PER_METER; >> >> just because a type is given in the second case. > > Different types, different behavior. Well well. So this subtle difference between using a named number and a typed constant (where the actual type *may* be a fixed point type) has lead to quite not so subtle constraint errors. >> I would expect the compiler to evaluate the expression "HEIGHT * >> FEET_PER_METER" _before_ converting it to the appropriate fixed point >> type. > > Why? "*" is defined on Altitude. You should rather wonder why the result > is different for TEN_FEET_4. I did wonder. :) I did a lot of different things trying to understand the issue to my satisfaction. We now know how to get around it, but knowing a workaround and actually understanding it are two different things. > Multiplication is inexact taking rounding this or that way you get > different results. Yes, honestly I just wasn't really expecting that the compiler would actually choose the multiplication operator of the fixed point type in something that looks like a static expression. >> And, obviously it does this that when evaluating >> >> TEN_FEET_4 : constant Altitude := Altitude (HEIGHT * FEET_PER_METER); > > Well, it does not, because here another type is involved. Yes. So, the expression HEIGHT * FEET_PER_METER in the one case is evaluated by using the result type's multiplication operator and if the conversion is present, it is not, giving the more precise result. That's still a bit crazy, IMHO. > But what about: > > X : constant Altitude := 0.3048; -- The result is 0 > > Does it wonder you? No. That behavior is crystal-clear and expected. It's having to add all those conversions just to make sure the values come out as expected that's disturbing me a bit. It is something I wouldn't expect from Ada. As you can probably imagine, there are a lot more packages with appropriate constants involved than in this shortened test case. And a lot of those constants are used for fixed point values with totally different ranges and deltas. So the actual problems do not show immediately. Vinzent. -- There is no signature. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-13 21:08 ` Vinzent Hoefler @ 2010-09-14 6:54 ` J-P. Rosen 2010-09-14 18:28 ` Vinzent Hoefler 2010-09-14 7:47 ` Dmitry A. Kazakov 1 sibling, 1 reply; 30+ messages in thread From: J-P. Rosen @ 2010-09-14 6:54 UTC (permalink / raw) Le 13/09/2010 23:08, Vinzent Hoefler a écrit : >>> And, obviously it does this that when evaluating >>> >>> TEN_FEET_4 : constant Altitude := Altitude (HEIGHT * FEET_PER_METER); >> >> Well, it does not, because here another type is involved. > > Yes. So, the expression HEIGHT * FEET_PER_METER in the one case is > evaluated by using the result type's multiplication operator and if the > conversion is present, it is not, giving the more precise result. > > That's still a bit crazy, IMHO. > Every language with overloading has to decide whether resolution goes from the outside to the inside, or the other way round. In the case of Ada, it is the "enclosing context" that determines the type of what's in it. If the enclosing context is a type conversion, it tells nothing about the expected type of its argument, hence the fall back to universal types. If the enclosing context is typed, it determines the type of the "*" operator. -- --------------------------------------------------------- J-P. Rosen (rosen@adalog.fr) Visit Adalog's web site at http://www.adalog.fr ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-14 6:54 ` J-P. Rosen @ 2010-09-14 18:28 ` Vinzent Hoefler 0 siblings, 0 replies; 30+ messages in thread From: Vinzent Hoefler @ 2010-09-14 18:28 UTC (permalink / raw) On Tue, 14 Sep 2010 08:54:20 +0200, J-P. Rosen <rosen@adalog.fr> wrote: > Every language with overloading has to decide whether resolution goes > from the outside to the inside, or the other way round. In the case of > Ada, it is the "enclosing context" that determines the type of what's in > it. If the enclosing context is a type conversion, it tells nothing > about the expected type of its argument, hence the fall back to > universal types. If the enclosing context is typed, it determines the > type of the "*" operator. I understand that. What I don't understand is that two different compilers do seem to handle it differently. Actually, I just wanted to know which one does it wrong. ;) Now, to make matters worse: ARM 3.5(9): "[...] the evaluation of the range evaluates these simple_expressions in an arbitrary order, and converts them to the type of the range." which I read as "_first_ evaluate and _then_ convert". But this only applies to the dynamic case, right? Then: ARM 3.5(5): "For a subtype_indication containing a range_constraint, [...], the type of the range shall resolve to that of the type determined by the subtype_mark of the subtype_indication. For a range of a given type, the simple_expressions of the range (likewise, the simple_expressions of the equivalent range for a range_attribute_reference) are expected to be of the type of the range." Which is quite specific and seems to happen here. Yet, this is not the end: ARM 3.5.9(3) defines a fixed point definition to have a "real_range_specification", which according to ARM 3.5.7(5) "is expected to be of any real type; the types need not be the same". Now, I suspect that in type Fixed_1 is delta 0.5 range 0.0 .. 50.0 * 0.1; subtype Fixed_2 is Fixed_1 range 0.0 .. 50.0 * 0.1; (where "One_Tenth" shall be a non-static function). Fixed_1 and Fixed_4 have a range of 0.0 .. 5.0 then, whilst Fixed_2's range suddenly is 0.0 .. 0.0 again, right? Vinzent. -- There is no signature. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-13 21:08 ` Vinzent Hoefler 2010-09-14 6:54 ` J-P. Rosen @ 2010-09-14 7:47 ` Dmitry A. Kazakov 2010-09-14 17:42 ` Vinzent Hoefler 1 sibling, 1 reply; 30+ messages in thread From: Dmitry A. Kazakov @ 2010-09-14 7:47 UTC (permalink / raw) On Mon, 13 Sep 2010 23:08:08 +0200, Vinzent Hoefler wrote: > On Mon, 13 Sep 2010 22:32:05 +0200, Dmitry A. Kazakov > <mailbox@dmitry-kazakov.de> wrote: > >> On Mon, 13 Sep 2010 20:25:43 +0200, Vinzent Hoefler wrote: >> >>> Yes, of course. Still, it's not quite intuitive why >>> >>> TEN_FEET_1 : constant := HEIGHT * FEET_PER_METER; >>> TEN_FEET_2 : constant Altitude := HEIGHT * FEET_PER_METER; >>> >>> just because a type is given in the second case. >> >> Different types, different behavior. > > Well well. So this subtle difference between using a named number and a > typed constant (where the actual type *may* be a fixed point type) has > lead to quite not so subtle constraint errors. Yes, because multiplication you have in mind is not the one effectively implemented for fixed point types. Fixed-point operations are exact, but inaccurate in terms of real numbers. You seem to expect them inexact, but accurate. >> Multiplication is inexact taking rounding this or that way you get >> different results. > > Yes, honestly I just wasn't really expecting that the compiler would > actually choose the multiplication operator of the fixed point type in > something that looks like a static expression. If there were a way to disallow predefined multiplication, but there is no one, AFAIK. And you have this same problem with all other operations. Consider 0.4+0.4 is it 0 or 0.65536? > Yes. So, the expression HEIGHT * FEET_PER_METER in the one case is > evaluated by using the result type's multiplication operator and if the > conversion is present, it is not, giving the more precise result. > > That's still a bit crazy, IMHO. No, fixed point multiplication was intentionally defined that way. > It's having to add all those conversions just to make sure the values come > out as expected that's disturbing me a bit. It is something I wouldn't > expect from Ada. Well, I don't disagree, but the part of the problem is a non-intended use. It is difficult to say how the compiler could detect that. In your use case, the only solution I see were literals made intervals rather than universal numbers. That would statically detect that HEIGHT * FEET_PER_METER has the width greater than Small and warn about implicit conversion to Altitude possibly raising Precision_Loss_Error. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-14 7:47 ` Dmitry A. Kazakov @ 2010-09-14 17:42 ` Vinzent Hoefler 2010-09-15 8:35 ` Dmitry A. Kazakov 0 siblings, 1 reply; 30+ messages in thread From: Vinzent Hoefler @ 2010-09-14 17:42 UTC (permalink / raw) On Tue, 14 Sep 2010 09:47:03 +0200, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote: > Well, I don't disagree, but the part of the problem is a non-intended > use. Well, the actually intended use was to create a range constrained subtype from an existing full-range fixed point type: -- 8< -- snip -- type BASE_TYPE is delta 1.0 / 64.0 range 0.0 .. 1.0; for BASE_TYPE'Small use 1.0 / 128.0; UPPER_BOUND_1 : constant := 51.0 * 0.01; UPPER_BOUND_2 : constant BASE_TYPE := 51.0 * 0.01; UPPER_BOUND_3 : constant BASE_TYPE := BASE_TYPE (51.0 * 0.01); subtype SUB1_TYPE is BASE_TYPE range 0.0 .. UPPER_BOUND_1; subtype SUB2_TYPE is BASE_TYPE range 0.0 .. UPPER_BOUND_2; subtype SUB3_TYPE is BASE_TYPE range 0.0 .. UPPER_BOUND_3; -- 8< -- snip -- (Further details of the test procedure omitted to save space.) The numbers are arbitrarily chosen and in the real code we weren't using constants, but rather the raw expression like in "range 0.0 .. SOME_CONSTANT * SOME_OTHER_CONSTANT" (but that doesn't actually matter, the issue remains the same, if not to say totally consistent). Now, interestingly, the resulting ranges of the subtypes seem to be compiler-dependent: -- 8< -- snip -- ~/project/fixed_point_issue> build fixed_point.bld Registering Ada Sources Compiling /home/hoefler/project/fixed_point_issue/fixed_point.adb because "fixed_point.o" doesn't exist Linking fixed_point Translating symbols for fixed_point Done ~/project/fixed_point_issue> simppc -ada fixed_point BASE_TYPE: 0.00000000000000 .. 1.00000000000000 SUB1_TYPE: 0.00000000000000 .. 0.50781250000000 SUB2_TYPE: 0.00000000000000 .. 0.50781250000000 SUB3_TYPE: 0.00000000000000 .. 0.50781250000000 ~/project/fixed_point_issue> gnatmake -f fixed_point gnatgcc -c fixed_point.adb gnatbind -x fixed_point.ali gnatlink fixed_point.ali ~/project/fixed_point_issue> ./fixed_point BASE_TYPE: 0.00000000000000 .. 0.99218750000000 SUB1_TYPE: 0.00000000000000 .. 0.50781250000000 SUB2_TYPE: 0.00000000000000 .. 0.39843750000000 SUB3_TYPE: 0.00000000000000 .. 0.50781250000000 -- 8< -- After all it really looks like the target compiler actually uses an Ada83 mode(l) here, although the code definitely is Ada95, and also both compilers claim to be Ada95 compilers. > It is difficult to say how the compiler could detect that. Well, it did. By raising Constraint_Error for an assignment of a value within the supposed range of the subtype. The virtues of unit testing. Fortunately, it wasn't the other way around. Vinzent. -- There is no signature. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-14 17:42 ` Vinzent Hoefler @ 2010-09-15 8:35 ` Dmitry A. Kazakov 2010-09-15 17:24 ` Vinzent Hoefler 0 siblings, 1 reply; 30+ messages in thread From: Dmitry A. Kazakov @ 2010-09-15 8:35 UTC (permalink / raw) On Tue, 14 Sep 2010 19:42:52 +0200, Vinzent Hoefler wrote: > On Tue, 14 Sep 2010 09:47:03 +0200, Dmitry A. Kazakov > <mailbox@dmitry-kazakov.de> wrote: > >> Well, I don't disagree, but the part of the problem is a non-intended >> use. > > Well, the actually intended use was to create a range constrained subtype > from an existing full-range fixed point type: > > -- 8< -- snip -- > type BASE_TYPE is delta 1.0 / 64.0 range 0.0 .. 1.0; > for BASE_TYPE'Small use 1.0 / 128.0; But use suggests rather: type Base_Type is delta 0.01 digits 3 range 0.0..1.0; or type Base_Type is delta 0.01 digits 3 range -1.0..1.0; -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-15 8:35 ` Dmitry A. Kazakov @ 2010-09-15 17:24 ` Vinzent Hoefler 2010-09-15 20:11 ` Dmitry A. Kazakov 0 siblings, 1 reply; 30+ messages in thread From: Vinzent Hoefler @ 2010-09-15 17:24 UTC (permalink / raw) On Wed, 15 Sep 2010 10:35:22 +0200, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote: > On Tue, 14 Sep 2010 19:42:52 +0200, Vinzent Hoefler wrote: > >> -- 8< -- snip -- >> type BASE_TYPE is delta 1.0 / 64.0 range 0.0 .. 1.0; >> for BASE_TYPE'Small use 1.0 / 128.0; > > But use suggests rather: > > type Base_Type is delta 0.01 digits 3 range 0.0..1.0; > > or > > type Base_Type is delta 0.01 digits 3 range -1.0..1.0; No. These are bus-protocol types (read: hardware types) where MSB values, bit sizes and (valid) range are given, so we definitely want to make sure that the compiler uses the correct representation. Thus, a "simple" digits constraint is ruled out here. Usually such a type definition looks similar to that: type Foo is delta 1.638_400 / 2**13 range -0.819_200 .. 0.819_200; for Foo'Small use 1.638_400 / 2**13; for Foo'Size use 13; For reading from the bus we use the (full-range) base type and checking its range before assigning it to the appropriate object of the constrained subtype. Vinzent. -- There is no signature. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-15 17:24 ` Vinzent Hoefler @ 2010-09-15 20:11 ` Dmitry A. Kazakov 0 siblings, 0 replies; 30+ messages in thread From: Dmitry A. Kazakov @ 2010-09-15 20:11 UTC (permalink / raw) On Wed, 15 Sep 2010 19:24:23 +0200, Vinzent Hoefler wrote: > On Wed, 15 Sep 2010 10:35:22 +0200, Dmitry A. Kazakov > <mailbox@dmitry-kazakov.de> wrote: > >> On Tue, 14 Sep 2010 19:42:52 +0200, Vinzent Hoefler wrote: >> >>> -- 8< -- snip -- >>> type BASE_TYPE is delta 1.0 / 64.0 range 0.0 .. 1.0; >>> for BASE_TYPE'Small use 1.0 / 128.0; >> >> But use suggests rather: >> >> type Base_Type is delta 0.01 digits 3 range 0.0..1.0; >> >> or >> >> type Base_Type is delta 0.01 digits 3 range -1.0..1.0; > > No. These are bus-protocol types (read: hardware types) where MSB values, > bit sizes and (valid) range are given, so we definitely want to make sure that the > compile uses the correct representation. OK, I would never do it this way. In similar cases I use a modular or integer type. Which is converted to a floating point or fixed point type suitable for further computations or processing. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: Fixed point constants issue 2010-09-13 18:04 ` Dmitry A. Kazakov 2010-09-13 18:25 ` Vinzent Hoefler @ 2010-09-14 19:44 ` Keith Thompson 1 sibling, 0 replies; 30+ messages in thread From: Keith Thompson @ 2010-09-14 19:44 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes: > On Mon, 13 Sep 2010 19:27:30 +0200, Vinzent Hoefler wrote: >> Is this a GNAT bug or am I just stupid? >> >> Suppose we have a fixed point type (with a rather large delta): >> >> -- 8< -- >> with Ada.Text_IO; use Ada.Text_IO; >> >> procedure Fixed_Point >> is >> FEET_PER_METER : constant := 0.3048; >> HEIGHT : constant := 10; -- Feet >> >> type Altitude is delta (2.0**15 / 50_000.0) range 0.0 .. 50_000.0; > > [...] >> Can anyone shed some light on this? This has driven us crazy for weeks now. >> >> [1] Of course, "Altitude'(HEIGHT * FEET_PER_METER)" yields "0.0" again. >> At least this is consistent with my understanding so far. > > Hmm, what did you expect? 0.3048 (FEET_PER_METER) is 0 when Altitude. That > is because 2.0**15/50_000.0=0.65536 > 0.3048. Close, but actually it's because 2.0**15/50_000.0=0.65536 > 0.5. Altitude'Delta = 0.65536. Altitude'Small = 0.5. If you want the 'Small to be the same as the 'Delta, you have to specify it (or use a power of 2.0). -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Nokia "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" ^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2010-10-05 18:40 UTC | newest] Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2010-09-13 17:27 Fixed point constants issue Vinzent Hoefler 2010-09-13 18:04 ` Dmitry A. Kazakov 2010-09-13 18:25 ` Vinzent Hoefler 2010-09-13 19:05 ` Niklas Holsti 2010-09-13 20:35 ` Vinzent Hoefler 2010-09-13 20:35 ` Jeffrey Carter 2010-09-13 21:06 ` Vinzent Hoefler 2010-09-14 5:39 ` Niklas Holsti 2010-09-24 14:43 ` Markus Schöpflin 2010-09-24 20:05 ` Vinzent Hoefler 2010-09-24 21:38 ` Jeffrey Carter 2010-09-24 22:42 ` Vinzent Hoefler 2010-09-25 0:16 ` Jeffrey Carter 2010-09-27 10:33 ` Markus Schöpflin 2010-09-27 18:57 ` Jeffrey Carter 2010-09-28 8:16 ` Markus Schöpflin 2010-09-28 17:28 ` Jeffrey Carter 2010-10-05 6:27 ` Randy Brukardt 2010-10-05 18:40 ` Jeffrey Carter 2010-09-27 17:58 ` Adam Beneschan 2010-09-13 20:32 ` Dmitry A. Kazakov 2010-09-13 21:08 ` Vinzent Hoefler 2010-09-14 6:54 ` J-P. Rosen 2010-09-14 18:28 ` Vinzent Hoefler 2010-09-14 7:47 ` Dmitry A. Kazakov 2010-09-14 17:42 ` Vinzent Hoefler 2010-09-15 8:35 ` Dmitry A. Kazakov 2010-09-15 17:24 ` Vinzent Hoefler 2010-09-15 20:11 ` Dmitry A. Kazakov 2010-09-14 19:44 ` Keith Thompson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox