comp.lang.ada
 help / color / mirror / Atom feed
* conversions between fixed-point types
@ 2009-09-18 21:35 Dirk Herrmann
  2009-09-18 22:42 ` Adam Beneschan
                   ` (2 more replies)
  0 siblings, 3 replies; 31+ messages in thread
From: Dirk Herrmann @ 2009-09-18 21:35 UTC (permalink / raw)


Hi,

I am currently trying to learn about Ada's fixed-point types, and there
are some points that I couldn't find any statement about, or which I
simply could not understand.

(Background: At my company there is a lot of code that makes heavy use
of fixed-point calculations in a proprietary language.  This language
offers special support for fixed-point arithmetics.  I am investigating
whether Ada would be a better choice, and thus the fixed-point handling
is important.  Note that the decision to use fixed-point arithmetics is
due to the fact that the target processors do not have a floating point
unit - and this will remain this way for some time.)

The first set of questions I have is about conversions between different
fixed-point types.

I realized that with GNAT for the following example types
    type FpA is delta 0.5 range -10.0 .. +10.0;
    for FpA'Small use 0.5;
    type FpB is delta 0.4 range -10.0 .. +10.0;
    for FpB'Small use 0.4;
conversions from FpA to FpB work as follows:

    FpA       FpB
    -1.5 ---> -1.2
    -1.0 ---> -0.8
    -0.5 ---> -0.4
    -0.0 ---> -0.0
    +0.5 ---> +0.4
    +1.0 ---> +0.8
    +1.5 ---> +1.2

That is, the conversion is performed similar to a truncation (always
choosing the closest value towards zero).  However, in principle there
are other possibilities how the conversion could be done:

               truncation  floor  ceiling  round
    -1.5 --->  -1.2        -1.6   -1.2     -1.6
    -1.0 --->  -0.8        -1.2   -0.8     -1.2
    -0.5 --->  -0.4        -0.8   -0.4     -0.4
     0.0 --->   0.0         0.0    0.0      0.0
    +0.5 --->  +0.4        +0.4   +0.8     +0.4
    +1.0 --->  +0.8        +0.8   +1.2     +1.2
    +1.5 --->  +1.2        +1.2   +1.6     +1.6

First question:

There does not seem to be any definite statement in the reference manual
of Ada 2005 about how exactly the conversion has to be performed.  All
of the above (and probably more options) seem to be legal, and GNAT just
chooses truncation.  Is that right, or have I already missed something?

I have not even found a statement that a compiler has to be consistent
with respect to the strategy it chooses.  It might be possible that for
different conversions within the same program different strategies are
chosen.  Regarding GNAT, I could not find any statement in the GNAT
documentation about whether GNAT will do it the same way throughout.

Second question:

Is there any way to control how the conversion is performed?  Maybe I
have missed something and the language itself offers some possibility?
Is there, for example, some attribute S'Round(X : some fixed point type)
  that rounds X to the nearest value of S?  I could not find anything
like that.

Or, if this is not the case, do any libraries exist that provide generic
conversion functions to achieve some or all of the "truncate", "floor",
"ceil" or "round" behaviours?  As I mentioned at the top of the mail,
any solutions that would require conversions between fixed-point and
floating-point to implement these conversions would probably not be
acceptable for our systems.

Thanks in advance,

Dirk Herrmann
(email address gladly given on request)



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-18 21:35 conversions between fixed-point types Dirk Herrmann
@ 2009-09-18 22:42 ` Adam Beneschan
  2009-09-19 12:41 ` Dirk Herrmann
  2009-09-20  8:22 ` sjw
  2 siblings, 0 replies; 31+ messages in thread
From: Adam Beneschan @ 2009-09-18 22:42 UTC (permalink / raw)


On Sep 18, 2:35 pm, Dirk Herrmann <fight_s...@invalid.invalid> wrote:
> Hi,
>
> I am currently trying to learn about Ada's fixed-point types, and there
> are some points that I couldn't find any statement about, or which I
> simply could not understand.
>
> (Background: At my company there is a lot of code that makes heavy use
> of fixed-point calculations in a proprietary language.  This language
> offers special support for fixed-point arithmetics.  I am investigating
> whether Ada would be a better choice, and thus the fixed-point handling
> is important.  Note that the decision to use fixed-point arithmetics is
> due to the fact that the target processors do not have a floating point
> unit - and this will remain this way for some time.)
>
> The first set of questions I have is about conversions between different
> fixed-point types.
>
> I realized that with GNAT for the following example types
>     type FpA is delta 0.5 range -10.0 .. +10.0;
>     for FpA'Small use 0.5;
>     type FpB is delta 0.4 range -10.0 .. +10.0;
>     for FpB'Small use 0.4;
> conversions from FpA to FpB work as follows:
>
>     FpA       FpB
>     -1.5 ---> -1.2
>     -1.0 ---> -0.8
>     -0.5 ---> -0.4
>     -0.0 ---> -0.0
>     +0.5 ---> +0.4
>     +1.0 ---> +0.8
>     +1.5 ---> +1.2
>
> That is, the conversion is performed similar to a truncation (always
> choosing the closest value towards zero).  However, in principle there
> are other possibilities how the conversion could be done:
>
>                truncation  floor  ceiling  round
>     -1.5 --->  -1.2        -1.6   -1.2     -1.6
>     -1.0 --->  -0.8        -1.2   -0.8     -1.2
>     -0.5 --->  -0.4        -0.8   -0.4     -0.4
>      0.0 --->   0.0         0.0    0.0      0.0
>     +0.5 --->  +0.4        +0.4   +0.8     +0.4
>     +1.0 --->  +0.8        +0.8   +1.2     +1.2
>     +1.5 --->  +1.2        +1.2   +1.6     +1.6
>
> First question:
>
> There does not seem to be any definite statement in the reference manual
> of Ada 2005 about how exactly the conversion has to be performed.  All
> of the above (and probably more options) seem to be legal, and GNAT just
> chooses truncation.  Is that right, or have I already missed something?

I think you're right, even if the implementation supports the Numerics
Annex (based on G.2.3(10,24)).

> I have not even found a statement that a compiler has to be consistent
> with respect to the strategy it chooses.  It might be possible that for
> different conversions within the same program different strategies are
> chosen.  Regarding GNAT, I could not find any statement in the GNAT
> documentation about whether GNAT will do it the same way throughout.
>
> Second question:
>
> Is there any way to control how the conversion is performed?  Maybe I
> have missed something and the language itself offers some possibility?
> Is there, for example, some attribute S'Round(X : some fixed point type)
>   that rounds X to the nearest value of S?  I could not find anything
> like that.
>
> Or, if this is not the case, do any libraries exist that provide generic
> conversion functions to achieve some or all of the "truncate", "floor",
> "ceil" or "round" behaviours?  As I mentioned at the top of the mail,
> any solutions that would require conversions between fixed-point and
> floating-point to implement these conversions would probably not be
> acceptable for our systems.

The following seems to work if you want to round:

   X : FpA;
   Y : FpB;

   Y := Integer (X / FpB'Small) * FpB'Small;

The conversion to Integer will round (4.6(33)).  I didn't check the
resulting code, but this shouldn't use any floating-point operations.

Unfortunately, I can't think of a good solution if you want to insist
(portably) on truncation, even though GNAT does this by default.
Floor and Ceiling probably require you to write a conditional that
behaves differently depending on whether X is < 0 or > 0, but on most
processors that is probably about as efficient as if support for this
existed in the language and the compiler generated the code itself.

                                    -- Adam



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-18 21:35 conversions between fixed-point types Dirk Herrmann
  2009-09-18 22:42 ` Adam Beneschan
@ 2009-09-19 12:41 ` Dirk Herrmann
  2009-09-19 14:48   ` John B. Matthews
  2009-09-19 18:38   ` tmoran
  2009-09-20  8:22 ` sjw
  2 siblings, 2 replies; 31+ messages in thread
From: Dirk Herrmann @ 2009-09-19 12:41 UTC (permalink / raw)


Dirk Herrmann wrote:

> I am currently trying to learn about Ada's fixed-point types, and there
> are some points that I couldn't find any statement about, or which I
> simply could not understand.

And, while experimenting and trying out Adam Beneschan's solution for
rounding (thanks for your answer, Alan) I got totally confused because
of the following code (I am using GNAT 4.3.4 with the following
command line options: gnatmake -f -gnatVa -gnata -gnatwadhl.o
-save-temps conversion.adb):  (For your convenience, I added the results
as comments within the code.)

    with Ada.Text_IO;

    procedure Conversion is

       package TIO renames Ada.Text_IO;
       package FIO is new Ada.Text_IO.Float_IO(Float);

       type FpA is delta 0.5 range -10.0 .. +10.0; for FpA'Small use 0.5;
       type FpB is delta 0.4 range -10.0 .. +10.0; for FpB'Small use 0.4;

       function MakeB(F: in Float) return FpB is
       begin
          return FpB(F);
       end MakeB;

       function MakeBFromA(F: in FpA) return FpB is
       begin
          return FpB(F);
       end MakeBFromA;

       function MakeBViaA(F: in Float) return FpB is
       begin
          return FpB(FpA(F));
       end MakeBViaA;

    begin

       FIO.Put(Float(FpA(-1.5))); TIO.Put(" ");             --> -1.50000E+00
       FIO.Put(Float(FpB(-1.5))); TIO.Put(" ");             --> -1.20000E+00
       FIO.Put(Float(FpB(Float(-1.5)))); TIO.Put(" ");      --> -1.20000E+00
       FIO.Put(Float(MakeB(-1.5))); TIO.Put(" ");           --> -1.60000E+00
       FIO.Put(Float(FpB(FpA(-1.5)))); TIO.Put(" ");        --> -1.20000E+00
       FIO.Put(Float(FpB(FpA(Float(-1.5))))); TIO.Put(" "); --> -1.20000E+00
       FIO.Put(Float(MakeBFromA(FpA(-1.5)))); TIO.Put(" "); --> -1.60000E+00
       FIO.Put(Float(MakeBViaA(-1.5))); TIO.Put(" ");       --> -1.60000E+00

    end Conversion;

Is this confusing behaviour allowed?  I will submit a bug report if some 
expert confirms it is a GNAT bug.

Thanks in advance,

Dirk Herrmann
(email address gladly given on request)



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-19 12:41 ` Dirk Herrmann
@ 2009-09-19 14:48   ` John B. Matthews
  2009-09-20  8:15     ` Dirk Herrmann
  2009-09-19 18:38   ` tmoran
  1 sibling, 1 reply; 31+ messages in thread
From: John B. Matthews @ 2009-09-19 14:48 UTC (permalink / raw)


In article <h92jie$q4g$1@news.albasani.net>,
 Dirk Herrmann <fight_spam@invalid.invalid> wrote:

> Dirk Herrmann wrote:
> 
> > I am currently trying to learn about Ada's fixed-point types, and 
> > there are some points that I couldn't find any statement about, or 
> > which I simply could not understand.
> 
> And, while experimenting and trying out Adam Beneschan's solution for 
> rounding (thanks for your answer, Alan) I got totally confused 
> because of the following code (I am using GNAT 4.3.4 with the 
> following command line options: gnatmake -f -gnatVa -gnata 
> -gnatwadhl.o -save-temps conversion.adb):
[...]
> Is this confusing behaviour allowed?  I will submit a bug report if 
> some expert confirms it is a GNAT bug.

I'm no expert, and I had some trouble following the conversions in your 
example. I tried a more direct test, and I don't see anything unusual; 
rounding appears consistent. Rounding away from zero is required for 
decimal fixed point types; but rounding toward zero is permitted for 
ordinary fixed point types such as FpA and FpB.

<code>
 with Ada.Text_IO;

 procedure Conversion is

    package TIO renames Ada.Text_IO;
    package FIO is new Ada.Text_IO.Float_IO(Float);

    type FpA is delta 0.5 range -10.0 .. +10.0; for FpA'Small use 0.5;
    type FpB is delta 0.4 range -10.0 .. +10.0; for FpB'Small use 0.4;
    
    package AIO is new Ada.Text_IO.Fixed_IO(FpA);
    package BIO is new Ada.Text_IO.Fixed_IO(FpB);
    
    V : Float := -2.0;

 begin

    while V < 0.0 loop
       FIO.Put(V, 1, 1, 0); TIO.Put(" ");
       AIO.Put(FpA(V)); TIO.Put(" ");
       BIO.Put(FpB(V)); TIO.New_Line;
       V := V + 0.1;
    end loop;

 end Conversion;
</code>

<console>
$ make run
Darwin: gcc 4.3.4
gnatmake conversion -cargs -O2 -bargs -shared -largs -dead_strip
gcc -c -O2 conversion.adb
gnatbind -shared -x conversion.ali
gnatlink conversion.ali -shared-libgcc -dead_strip
./conversion
-2.0  -2.0  -2.0
-1.9  -2.0  -2.0
-1.8  -2.0  -1.6
-1.7  -1.5  -1.6
-1.6  -1.5  -1.6
-1.5  -1.5  -1.6
-1.4  -1.5  -1.2
-1.3  -1.5  -1.2
-1.2  -1.0  -1.2
-1.1  -1.0  -1.2
-1.0  -1.0  -0.8
-0.9  -1.0  -0.8
-0.8  -1.0  -0.8
-0.7  -0.5  -0.8
-0.6  -0.5  -0.4
-0.5  -0.5  -0.4
-0.4  -0.5  -0.4
-0.3  -0.5  -0.4
-0.2   0.0   0.0
-0.1   0.0   0.0
</console>

-- 
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-19 12:41 ` Dirk Herrmann
  2009-09-19 14:48   ` John B. Matthews
@ 2009-09-19 18:38   ` tmoran
  1 sibling, 0 replies; 31+ messages in thread
From: tmoran @ 2009-09-19 18:38 UTC (permalink / raw)


> And, while experimenting and trying out Adam Beneschan's solution for
> rounding (thanks for your answer, Alan) I got totally confused because
> of the following code (I am using GNAT 4.3.4 with the following
> command line options: gnatmake -f -gnatVa -gnata -gnatwadhl.o
> -save-temps conversion.adb):  (For your convenience, I added the results
> as comments within the code.)

Using rather old versions of two compilers, I get:

  Gnat 3.15p   Janus 3.1.2a

-1.50000E+00  -1.50000E+00
-1.20000E+00  -1.60000E+00
-1.20000E+00  -1.60000E+00
-1.60000E+00  -1.60000E+00
-1.20000E+00  -1.60000E+00
-1.20000E+00  -1.60000E+00
-1.60000E+00  -1.60000E+00
-1.60000E+00  -1.60000E+00



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-19 14:48   ` John B. Matthews
@ 2009-09-20  8:15     ` Dirk Herrmann
  2009-09-20 14:22       ` Robert A Duff
                         ` (3 more replies)
  0 siblings, 4 replies; 31+ messages in thread
From: Dirk Herrmann @ 2009-09-20  8:15 UTC (permalink / raw)


Dirk Herrmann wrote:
>> And, while experimenting and trying out Adam Beneschan's solution for 
>> rounding (thanks for your answer, Alan) I got totally confused 
>> because of the following code (I am using GNAT 4.3.4 with the 
>> following command line options: gnatmake -f -gnatVa -gnata 
>> -gnatwadhl.o -save-temps conversion.adb):
> [...]
>> Is this confusing behaviour allowed?  I will submit a bug report if 
>> some expert confirms it is a GNAT bug.

John B. Matthews wrote:
> I'm no expert, and I had some trouble following the conversions in your 
> example.  [...]

Sorry, I should have given more details about why I am confused.

In particular I am disturbed by the fact that the following two lines produce 
different results with GNAT, as has been confirmed for GNAT 3.15p (thanks, 
tmoran):
       FIO.Put(Float(FpB(Float(-1.5)))); TIO.Put(" ");      --> -1.20000E+00
       FIO.Put(Float(MakeB(-1.5))); TIO.Put(" ");           --> -1.60000E+00
In the first line, the conversion to FpB is done from a Float value, which is 
a direct cast from -1.5.  In the second line, the conversion to FpB is also 
done from a Float value, but in this case -1.5 is passed as a Float argument 
to MakeB.  What I don't understand is, why it should make a difference whether 
I cast -1.5 to Float and then convert it to FpB compared to the situation 
where -1.5 is converted to a Float argument, which is then converted to FpB.

The same question arises for the following three lines:
       FIO.Put(Float(FpB(FpA(Float(-1.5))))); TIO.Put(" "); --> -1.20000E+00
       FIO.Put(Float(MakeBFromA(FpA(-1.5)))); TIO.Put(" "); --> -1.60000E+00
       FIO.Put(Float(MakeBViaA(-1.5))); TIO.Put(" ");       --> -1.60000E+00
Again, the difference lies in whether a sequence of casts is used compared to 
whether the very same value is passed as an argument.

Thanks for your help,

Dirk Herrmann
(email address gladly given on request)



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-18 21:35 conversions between fixed-point types Dirk Herrmann
  2009-09-18 22:42 ` Adam Beneschan
  2009-09-19 12:41 ` Dirk Herrmann
@ 2009-09-20  8:22 ` sjw
  2 siblings, 0 replies; 31+ messages in thread
From: sjw @ 2009-09-20  8:22 UTC (permalink / raw)


On Sep 18, 10:35 pm, Dirk Herrmann <fight_s...@invalid.invalid> wrote:

> I realized that with GNAT for the following example types
>     type FpA is delta 0.5 range -10.0 .. +10.0;
>     for FpA'Small use 0.5;
>     type FpB is delta 0.4 range -10.0 .. +10.0;
>     for FpB'Small use 0.4;
> conversions from FpA to FpB work as follows:
>
>     FpA       FpB
>     -1.5 ---> -1.2
>     -1.0 ---> -0.8
>     -0.5 ---> -0.4
>     -0.0 ---> -0.0
>     +0.5 ---> +0.4
>     +1.0 ---> +0.8
>     +1.5 ---> +1.2
>
> That is, the conversion is performed similar to a truncation (always
> choosing the closest value towards zero).

I don't see this; GNAT rounds ..

with Ada.Text_IO; use Ada.Text_IO;
procedure Fixed
is
   type FpA is delta 0.5 range -10.0 .. +10.0;
   for FpA'Small use 0.5;
   type FpB is delta 0.4 range -10.0 .. +10.0;
   for FpB'Small use 0.4;
   F : FpA'Base;
   G : FpB'Base;
begin
   F := -3.0;
   loop
      exit when F > 3.0;
      Put_Line
        (FpA'Image (F)
           & " "
           & FpB'Image (FpB (F))
           & " "
           & FpA'Image (FpA (FpB (F))));
      F := FpA'Succ (F);
   end loop;
   New_Line;
   G := -2.8;
   loop
      exit when G > 2.8;
      Put_Line
        (FpB'Image (G)
           & " "
           & FpA'Image (FpA (G))
           & " "
           & FpB'Image (FpB (FpA (G))));
      G := FpB'Succ (G);
   end loop;
end Fixed;

The output (Mac OS X, gcc-4.3.3 and GNAT-GPL-2009) is below, I've
noted the differences with ?'s:

-3.0 -3.2 -3.0      rounded away from 0
-2.5 -2.4 -2.5
-2.0 -2.0 -2.0
-1.5 -1.6 -1.5      " ?
-1.0 -1.2 -1.0      " ?
-0.5 -0.4 -0.5
 0.0  0.0  0.0
 0.5  0.4  0.5
 1.0  1.2  1.0      " ?
 1.5  1.6  1.5      " ?
 2.0  2.0  2.0
 2.5  2.4  2.5
 3.0  3.2  3.0      "

-2.8 -3.0 -3.2      " and final value /= initial value
-2.4 -2.5 -2.4      "
-2.0 -2.0 -2.0
-1.6 -1.5 -1.6
-1.2 -1.0 -1.2
-0.8 -1.0 -1.2      " "
-0.4 -0.5 -0.4      "
 0.0  0.0  0.0
 0.4  0.5  0.4
 0.8  1.0  1.2      " "
 1.2  1.0  1.2
 1.6  1.5  1.6
 2.0  2.0  2.0
 2.4  2.5  2.4      "
 2.8  3.0  3.2      " "



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-20  8:15     ` Dirk Herrmann
@ 2009-09-20 14:22       ` Robert A Duff
  2009-09-20 18:55         ` Dirk Herrmann
  2009-09-20 15:18       ` John B. Matthews
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 31+ messages in thread
From: Robert A Duff @ 2009-09-20 14:22 UTC (permalink / raw)


Dirk Herrmann <fight_spam@invalid.invalid> writes:

> In particular I am disturbed by the fact that the following two lines
> produce different results with GNAT, as has been confirmed for GNAT
> 3.15p (thanks, tmoran):

I don't know, but it might have something to do with the rules for
evaluating static expressions.  See RM-4.9.  You also need to look at
G.2.3.  I don't remember the exact rules for conversions of fixed
point, but I think they do allow some implementation freedom.
If you don't like that, then write code to make it do what
you want.  Or use compatible delta/small values.

Note that the rules for decimal fixed point are different.

By the way, you can say:

    for T'Small use T'Delta;

to avoid repeating yourself.

3.15p is very old.  It would be a good idea to upgrade to a more recent
version.

- Bob



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-20  8:15     ` Dirk Herrmann
  2009-09-20 14:22       ` Robert A Duff
@ 2009-09-20 15:18       ` John B. Matthews
  2009-09-20 19:13         ` Dirk Herrmann
  2009-09-20 20:09       ` tmoran
  2009-09-21 17:24       ` Jeffrey R. Carter
  3 siblings, 1 reply; 31+ messages in thread
From: John B. Matthews @ 2009-09-20 15:18 UTC (permalink / raw)


In article <h94obl$c7h$1@news.albasani.net>,
 Dirk Herrmann <fight_spam@invalid.invalid> wrote:

> Dirk Herrmann wrote:
> >> And, while experimenting and trying out Adam Beneschan's solution 
> >> for rounding (thanks for your answer, Alan) I got totally confused 
> >> because of the following code (I am using GNAT 4.3.4 with the 
> >> following command line options: gnatmake -f -gnatVa -gnata 
> >> -gnatwadhl.o -save-temps conversion.adb):
> > [...]
> >> Is this confusing behaviour allowed?  I will submit a bug report if 
> >> some expert confirms it is a GNAT bug.
> 
> John B. Matthews wrote:
> > I'm no expert, and I had some trouble following the conversions in 
> > your example.  [...]
> 
> Sorry, I should have given more details about why I am confused.

Not at all. My confusion arises from my own poor understanding of how to 
apply the rules to the various conversions.

> In particular I am disturbed by the fact that the following two lines produce 
> different results with GNAT, as has been confirmed for GNAT 3.15p (thanks, 
> tmoran):
>   FIO.Put(Float(FpB(Float(-1.5)))); TIO.Put(" ");      --> -1.20000E+00
>   FIO.Put(Float(MakeB(-1.5))); TIO.Put(" ");           --> -1.60000E+00
> In the first line, the conversion to FpB is done from a Float value, 
> which is a direct cast from -1.5.  In the second line, the conversion 
> to FpB is also done from a Float value, but in this case -1.5 is 
> passed as a Float argument to MakeB.  What I don't understand is, why 
> it should make a difference whether I cast -1.5 to Float and then 
> convert it to FpB compared to the situation where -1.5 is converted 
> to a Float argument, which is then converted to FpB.

I see what you mean. Here's my understanding: The Ada Reference Manual 
[1], section 3.6(32) on numeric type conversion refers to section G.2.1 
and G.2.3 for floating- and fixed-point arithmetic, respectively. The 
value -1.5 is exactly representable as type Float, but not as type FpB. 
The conversion to FpB is governed by G.2.3(10), so both -1.2 and -1.6 
are in the close result set. Because FpB is an ordinary fixed point 
type, rather than a decimal fixed point type, there's no requirement to 
prefer one element of the result set over another. The conversion back 
to Float is discussed in G.2.1(10). Because small is not a power of 
T'Machine_Radix, the result is implementation defined. I'm not sure if 
GNAT fully implements Annex G, and I may be overlooking something 
obvious.

From another perspective, I'm curious to know why the conversions are 
needed.

[1]<http://www.adaic.com/standards/05rm/html/RM-TTL.html>

[...]
-- 
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-20 14:22       ` Robert A Duff
@ 2009-09-20 18:55         ` Dirk Herrmann
  2009-09-20 20:34           ` Simon Clubley
                             ` (2 more replies)
  0 siblings, 3 replies; 31+ messages in thread
From: Dirk Herrmann @ 2009-09-20 18:55 UTC (permalink / raw)


Robert A Duff wrote:
> Dirk Herrmann <fight_spam@invalid.invalid> writes:
> 
>> In particular I am disturbed by the fact that the following two lines
>> produce different results with GNAT, as has been confirmed for GNAT
>> 3.15p (thanks, tmoran):
> 
> I don't know, but it might have something to do with the rules for
> evaluating static expressions.  See RM-4.9.  You also need to look at
> G.2.3.  I don't remember the exact rules for conversions of fixed
> point, but I think they do allow some implementation freedom.

Thanks Bob, I will look at those chapters.

> If you don't like that, then write code to make it do what
> you want.

As I said when I started this thread, I am currently investigating whether Ada 
could be a good replacement for the proprietary fixed-point oriented language 
used in our company.  And, convincing my colleagues would certainly not be 
easier with statements like "Ada can be used, but you have to implement all 
fixed-point stuff yourself".  Even more if you can not even rely on the fact 
that a compiler will behave the same way throughout.

> Or use compatible delta/small values.

Fortunately, most (but not all) of our fixed-point code uses powers of two for 
small.  But, even in that case you have to care about rounding when, for 
example, you are converting values from a small of 0.125 to a small of 0.5.

> By the way, you can say:
> 
>     for T'Small use T'Delta;
> 
> to avoid repeating yourself.

I have tried that, especially since the very same recommendation was given in 
the Barnes book "Ada 2005".  But, GNAT gives an error message.  It seems that 
the very moment you reference T'Delta the type T gets "frozen" such that  the 
"use" statement itself freezes T before it can modify it.  I don't know if 
this is what the authors of the reference manual had intended, but GNAT 
interprets it that way.

Thanks a lot for your help,
Dirk



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-20 15:18       ` John B. Matthews
@ 2009-09-20 19:13         ` Dirk Herrmann
  0 siblings, 0 replies; 31+ messages in thread
From: Dirk Herrmann @ 2009-09-20 19:13 UTC (permalink / raw)


John B. Matthews wrote:
> I see what you mean. Here's my understanding: The Ada Reference Manual 
> [1], section 3.6(32) on numeric type conversion refers to section G.2.1 
> and G.2.3 for floating- and fixed-point arithmetic, respectively. The 
> value -1.5 is exactly representable as type Float, but not as type FpB. 
> The conversion to FpB is governed by G.2.3(10), so both -1.2 and -1.6 
> are in the close result set. Because FpB is an ordinary fixed point 
> type, rather than a decimal fixed point type, there's no requirement to 
> prefer one element of the result set over another.

Thanks for your detailed analysis.  It confirms what I had suspected.  The bad 
thing seems to be that there is no easy approach to achieve a more specific 
behaviour.

> The conversion back 
> to Float is discussed in G.2.1(10). Because small is not a power of 
> T'Machine_Radix, the result is implementation defined. I'm not sure if 
> GNAT fully implements Annex G, and I may be overlooking something 
> obvious.

I see.  Probably the conversion back to float itself was not the problem, though.

> From another perspective, I'm curious to know why the conversions are 
> needed.

As I said, in my company we are using lots of fixed-point arithmetics.  Most 
of it is in powers of 2, but even then you have to care about rounding when 
converting between different fixed-point representations.

However, some data is represented with different resolutions.  For example, 
when you have some code that is executed cyclically every 100ms and delivers 
sensor sample values.  Then, a gradient of two sensor samples is 
(value2-value1)/dt.  Since dt is known to be 100ms, you can save a division 
operation if you choose a small of 100ms for dt.

At some point during the calculation, however, you will have to make the 
conversion from the world of types with "physical" representations (like, 
small of 100ms), to the world of binary representations.  This is the moment 
when conversions between smalls of 0.5 and 0.4 can be interesting.

Best regards,
Dirk



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-20  8:15     ` Dirk Herrmann
  2009-09-20 14:22       ` Robert A Duff
  2009-09-20 15:18       ` John B. Matthews
@ 2009-09-20 20:09       ` tmoran
  2009-09-21 17:24       ` Jeffrey R. Carter
  3 siblings, 0 replies; 31+ messages in thread
From: tmoran @ 2009-09-20 20:09 UTC (permalink / raw)


I ran on another old compiler, ObjectAda 7.2.2, and got:

  Gnat 3.15p   Janus 3.1.2a  ObjectAda 7.2.2

-1.50000E+00  -1.50000E+00   -1.50000E+00
-1.20000E+00  -1.60000E+00   -1.60000E+00
-1.20000E+00  -1.60000E+00   -1.60000E+00
-1.60000E+00  -1.60000E+00   -1.60000E+00
-1.20000E+00  -1.60000E+00   -1.60000E+00
-1.20000E+00  -1.60000E+00   -1.60000E+00
-1.60000E+00  -1.60000E+00   -1.20000E+00
-1.60000E+00  -1.60000E+00   -1.20000E+00

These were all Ada 95 compilers and I'm guessing the conformance
testing would have included fixed point handling, which would
suggest that any of the three different results would be legal.



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-20 18:55         ` Dirk Herrmann
@ 2009-09-20 20:34           ` Simon Clubley
  2009-09-23 20:46             ` Dirk Herrmann
  2009-09-27 19:22           ` sjw
  2009-09-28 18:37           ` Robert A Duff
  2 siblings, 1 reply; 31+ messages in thread
From: Simon Clubley @ 2009-09-20 20:34 UTC (permalink / raw)


On 2009-09-20, Dirk Herrmann <fight_spam@invalid.invalid> wrote:
>
> As I said when I started this thread, I am currently investigating whether
> Ada could be a good replacement for the proprietary fixed-point oriented
> language used in our company.
>

Are you allowed to tell us which language this is ?

I'm just curious.

Thanks,

Simon.

-- 
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980's technology to a 21st century world



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-20  8:15     ` Dirk Herrmann
                         ` (2 preceding siblings ...)
  2009-09-20 20:09       ` tmoran
@ 2009-09-21 17:24       ` Jeffrey R. Carter
  2009-09-23 20:57         ` Dirk Herrmann
  3 siblings, 1 reply; 31+ messages in thread
From: Jeffrey R. Carter @ 2009-09-21 17:24 UTC (permalink / raw)


Dirk Herrmann wrote:
> 
> In particular I am disturbed by the fact that the following two lines 
> produce different results with GNAT, as has been confirmed for GNAT 
> 3.15p (thanks, tmoran):
>       FIO.Put(Float(FpB(Float(-1.5)))); TIO.Put(" ");      --> -1.20000E+00
>       FIO.Put(Float(MakeB(-1.5))); TIO.Put(" ");           --> -1.60000E+00
> In the first line, the conversion to FpB is done from a Float value, 
> which is a direct cast from -1.5.  In the second line, the conversion to 
> FpB is also done from a Float value, but in this case -1.5 is passed as 
> a Float argument to MakeB.  What I don't understand is, why it should 
> make a difference whether I cast -1.5 to Float and then convert it to 
> FpB compared to the situation where -1.5 is converted to a Float 
> argument, which is then converted to FpB.

You are complicating matters with your functions and your conversions to and 
from Float. Since IIRC your target H/W doesn't support floating-point, you will 
be able to see what happens and formulate your questions better if you deal only 
with the fixed-point types and direct type conversions between them:

A : Fpa := -1.5;
B : Fpb := Fpb (A);
...
Ada.Text_IO.Put_Line (Fpb'Image (B) );

What you have called a "direct cast" is a type conversion. Also, it is never 
necessary to convert a real numeric literal to a real type. Your 1st line could 
be written as

FIO.Put (Float (Fpb (Float'(-1.5) ) ) );

With the apostrophe, this is a "qualified expression" and tells the compiler 
that the expression in the parentheses is of type Float. However, I suspect that

FIO.Put (Float (Fpb'(-1.5) ) );

is even better.

-- 
Jeff Carter
"It's all right, Taggart. Just a man and a horse being hung out there."
Blazing Saddles
34



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-20 20:34           ` Simon Clubley
@ 2009-09-23 20:46             ` Dirk Herrmann
  2009-09-27 17:15               ` Simon Clubley
  0 siblings, 1 reply; 31+ messages in thread
From: Dirk Herrmann @ 2009-09-23 20:46 UTC (permalink / raw)


Simon Clubley wrote:
> On 2009-09-20, Dirk Herrmann <fight_spam@invalid.invalid> wrote:
>> As I said when I started this thread, I am currently investigating whether
>> Ada could be a good replacement for the proprietary fixed-point oriented
>> language used in our company.
>>
> 
> Are you allowed to tell us which language this is ?

I'd rather not, sorry Simon: Currently I am doing this investigation 
completely in my spare time, I have no assignment to do this analysis and 
since our current language is a development of my company itself, I feel that 
I have to deal with this in a political way.

Best regards,
Dirk



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-21 17:24       ` Jeffrey R. Carter
@ 2009-09-23 20:57         ` Dirk Herrmann
  2009-09-23 22:28           ` Jeffrey R. Carter
  0 siblings, 1 reply; 31+ messages in thread
From: Dirk Herrmann @ 2009-09-23 20:57 UTC (permalink / raw)


Jeffrey R. Carter wrote:
> You are complicating matters with your functions and your conversions to 
> and from Float. Since IIRC your target H/W doesn't support 
> floating-point, you will be able to see what happens and formulate your 
> questions better if you deal only with the fixed-point types and direct 
> type conversions between them:

Thanks, Jeff, for the suggestions, I have tried them out.  I'd like to add 
that our target H/W does not have a floating point unit, but there certainly 
is a floating point library.

> What you have called a "direct cast" is a type conversion. Also, it is 
> never necessary to convert a real numeric literal to a real type. Your 
> 1st line could be written as
> 
> FIO.Put (Float (Fpb (Float'(-1.5) ) ) );
> 
> With the apostrophe, this is a "qualified expression" and tells the 
> compiler that the expression in the parentheses is of type Float. 
> However, I suspect that
> 
> FIO.Put (Float (Fpb'(-1.5) ) );
> 
> is even better.

FpB'Image(FpB'(-1.5))                evaluates to -1.2
FpB'Image(FpB(FpA'(-1.5)))           evaluates to -1.2
FpB'Image(MakeBFromA(FpA'(-1.5)))    evaluates to -1.6

Thus, even avoiding all floating point operations, the difference is still 
there.  It appears to be a question of whether the conversion from FpA to FpB 
or the conversion from Float to FpB is computed statically or dynamically.

Best regards,
Dirk



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-23 20:57         ` Dirk Herrmann
@ 2009-09-23 22:28           ` Jeffrey R. Carter
  2009-09-24  1:05             ` Adam Beneschan
  0 siblings, 1 reply; 31+ messages in thread
From: Jeffrey R. Carter @ 2009-09-23 22:28 UTC (permalink / raw)


Dirk Herrmann wrote:
> 
> FpB'Image(FpB'(-1.5))                evaluates to -1.2
> FpB'Image(FpB(FpA'(-1.5)))           evaluates to -1.2
> FpB'Image(MakeBFromA(FpA'(-1.5)))    evaluates to -1.6

There is no need to qualify these literals.

> Thus, even avoiding all floating point operations, the difference is 
> still there.  It appears to be a question of whether the conversion from 
> FpA to FpB or the conversion from Float to FpB is computed statically or 
> dynamically.

I presume you mean Fpa rather than Float.

Your last sentence may be what's happening. I don't know if that would be 
allowed or a compiler error. Any language lawyers want to comment?

-- 
Jeff Carter
"Go and boil your bottoms."
Monty Python & the Holy Grail
01



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-23 22:28           ` Jeffrey R. Carter
@ 2009-09-24  1:05             ` Adam Beneschan
  2009-09-24  3:57               ` Jeffrey R. Carter
                                 ` (2 more replies)
  0 siblings, 3 replies; 31+ messages in thread
From: Adam Beneschan @ 2009-09-24  1:05 UTC (permalink / raw)


On Sep 23, 3:28 pm, "Jeffrey R. Carter"
<spam.jrcarter....@spam.acm.org> wrote:
> Dirk Herrmann wrote:
>
> > FpB'Image(FpB'(-1.5))                evaluates to -1.2
> > FpB'Image(FpB(FpA'(-1.5)))           evaluates to -1.2
> > FpB'Image(MakeBFromA(FpA'(-1.5)))    evaluates to -1.6
>
> There is no need to qualify these literals.

In the second example, the qualification does make a difference,
semantically; it's the difference between a type conversion from a
fixed-point type to another fixed-point type, and a type conversion
from a universal_real to a fixed-point type.  It doesn't make a
difference in this particular case only because -1.5 is a model number
(machine number?) for an FpA.  But there's a definite difference
between FpB(0.7) and
FpB(FpA'(0.7)), if truncation is used instead of rounding.


> > Thus, even avoiding all floating point operations, the difference is
> > still there.  It appears to be a question of whether the conversion from
> > FpA to FpB or the conversion from Float to FpB is computed statically or
> > dynamically.
>
> I presume you mean Fpa rather than Float.
>
> Your last sentence may be what's happening. I don't know if that would be
> allowed or a compiler error. Any language lawyers want to comment?

The answer is curious (and I'm not sure if it's what the language
designers intended).  4.9(38) says, "For a real static expression that
is not part of a larger static expression ... the implementation shall
round or truncate the value (according to the Machine_Rounds attribute
of the expected type) to the nearest machine number of the expected
type...".  If FpB'Machine_Rounds is TRUE, this means that the result
will be rounded, both for static expressions and when computed at
runtime.  (Also, if a number that is halfway between two machine
numbers is rounded, the result is implementation-defined, but thanks
to AI95-268 there is now Implementation Advice that the rounding of
static expressions should be the same as it would be if computed at
runtime.)

If FpB'Machine_Rounds is FALSE, though, the situation is interesting.
4.9(38) requires that static expressions get *truncated* toward zero,
as I read it.  But there's no similar requirement for expressions
computed at runtime.  A.5.4(3) defines 'Machine_Rounds for a fixed-
point type as "Yields the value True if rounding is performed on
inexact results of every predefined operation that yields a result of
the type T; yields the value False otherwise."  It doesn't say that if
it's FALSE, then inexact results are truncated toward zero; it just
means that it might round or truncate.  It could be that some
predefined operations always round and others always truncate, or even
that the same predefined operation on different operands may sometimes
round upward and sometimes truncate (unlikely, but the language seems
to allow it).  Under this circumstance, it's possible that the type
conversion could produce different results at runtime than for a
static expression.

So I guess whether this is a GNAT bug or not depends on
FpB'Machine_Rounds.  If it's TRUE, the first two expressions are
computed incorrectly, but if it's FALSE, this seemingly anomalous
result is allowed.

Also, it's clear that static expressions need to round or truncate to
a multiple of the 'Small if they're not part of a larger static
expression.  But I'm not sure what this should do:

   FpA'Image (FpA (FpB' (-1.5)))

Here, FpB' (-1.5) *is* part of a larger static expression, so the rule
in 4.9(38) doesn't apply.  But I'm not sure just what does apply---is
the value of FpB'(-1.5) still assumed to be -1.5 (so that the type
conversion to FpA still results in -1.5), or should the type
conversion take place (which could result in -1.0 if truncation is
used for both type conversions), or is the result unspecified by the
language?

                                    -- Adam




^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-24  1:05             ` Adam Beneschan
@ 2009-09-24  3:57               ` Jeffrey R. Carter
  2009-09-25  8:47               ` Stuart
  2009-09-26 14:31               ` Dirk Herrmann
  2 siblings, 0 replies; 31+ messages in thread
From: Jeffrey R. Carter @ 2009-09-24  3:57 UTC (permalink / raw)


Adam Beneschan wrote:
> 
> In the second example, the qualification does make a difference,
> semantically; it's the difference between a type conversion from a
> fixed-point type to another fixed-point type, and a type conversion
> from a universal_real to a fixed-point type.

Oops. I know that. I even remember thinking that. Apparently it never got to my 
fingers.

-- 
Jeff Carter
"Go and boil your bottoms."
Monty Python & the Holy Grail
01



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-24  1:05             ` Adam Beneschan
  2009-09-24  3:57               ` Jeffrey R. Carter
@ 2009-09-25  8:47               ` Stuart
  2009-09-25 20:41                 ` sjw
  2009-09-26 14:43                 ` Dirk Herrmann
  2009-09-26 14:31               ` Dirk Herrmann
  2 siblings, 2 replies; 31+ messages in thread
From: Stuart @ 2009-09-25  8:47 UTC (permalink / raw)


"Adam Beneschan" <adam@irvine.com> wrote in message 
news:c8af7daf-9f00-4dbb-ad0d-9ca65e0a83d6@f18g2000prf.googlegroups.com...
> Dirk Herrmann wrote:
>
> > FpB'Image(FpB'(-1.5)) evaluates to -1.2
> > FpB'Image(FpB(FpA'(-1.5))) evaluates to -1.2
> > FpB'Image(MakeBFromA(FpA'(-1.5))) evaluates to -1.6

> The answer is curious (and I'm not sure if it's what the language
> designers intended).  4.9(38) says, ...
...
> If FpB'Machine_Rounds is FALSE, though, the situation is interesting.
> 4.9(38) requires that static expressions get *truncated* toward zero,
> as I read it.  But there's no similar requirement for expressions
> computed at runtime.

Having played with this on GNATPro 6.1.2 (to PC target) it does report 
FpB'Machine_Rounds as false.  It also rounds values like -1.59999 down to
-1.2 (which is a logical consequence).  Technically this is still within the 
error bounds declared for FpB (delta 0.4) so it is not "wrong" within the 
rules of the language definition.  But it is very counter-intuitive and is 
the sort of thing I find frustrating.

I also tested the problem on GreenHills AdaMULTI (4.2.3 to PowerPC target); 
this gave FpB'Machine_Rounds as true and gave the more intuitive results.

   -1.5         -> -1.6
   -1.40001 -> -1.6
   -1.4         -> -1.2

So although there does look to be a language "gotcha" here, it depends upon 
the compiler's choice of 'Machine_Rounds.

-- 
Stuart






^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-25  8:47               ` Stuart
@ 2009-09-25 20:41                 ` sjw
  2009-09-25 21:58                   ` Jeffrey R. Carter
  2009-09-28 13:40                   ` Stuart
  2009-09-26 14:43                 ` Dirk Herrmann
  1 sibling, 2 replies; 31+ messages in thread
From: sjw @ 2009-09-25 20:41 UTC (permalink / raw)


On Sep 25, 9:47 am, "Stuart" <stu...@0.0> wrote:
> "Adam Beneschan" <a...@irvine.com> wrote in message
>
> news:c8af7daf-9f00-4dbb-ad0d-9ca65e0a83d6@f18g2000prf.googlegroups.com...
>
>
>
> > Dirk Herrmann wrote:
>
> > > FpB'Image(FpB'(-1.5)) evaluates to -1.2
> > > FpB'Image(FpB(FpA'(-1.5))) evaluates to -1.2
> > > FpB'Image(MakeBFromA(FpA'(-1.5))) evaluates to -1.6
> > The answer is curious (and I'm not sure if it's what the language
> > designers intended).  4.9(38) says, ...
> ...
> > If FpB'Machine_Rounds is FALSE, though, the situation is interesting.
> > 4.9(38) requires that static expressions get *truncated* toward zero,
> > as I read it.  But there's no similar requirement for expressions
> > computed at runtime.
>
> Having played with this on GNATPro 6.1.2 (to PC target) it does report
> FpB'Machine_Rounds as false.  It also rounds values like -1.59999 down to
> -1.2 (which is a logical consequence).  Technically this is still within the
> error bounds declared for FpB (delta 0.4) so it is not "wrong" within the
> rules of the language definition.  But it is very counter-intuitive and is
> the sort of thing I find frustrating.
>
> I also tested the problem on GreenHills AdaMULTI (4.2.3 to PowerPC target);
> this gave FpB'Machine_Rounds as true and gave the more intuitive results.
>
>    -1.5         -> -1.6
>    -1.40001 -> -1.6
>    -1.4         -> -1.2
>
> So although there does look to be a language "gotcha" here, it depends upon
> the compiler's choice of 'Machine_Rounds.
>
> --
> Stuart

This is all very weird. Can I point you to my earlier post at
http://groups.google.com/group/comp.lang.ada/msg/f79a71b9abe7e287
which (unless I'm deluded) shows GNAT rounding away from zero for
dynamic values even though 'Machine_Rounds is False!! (and I get the
same results on Ubuntu 8.04 with GNAT GPL 2008.



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-25 20:41                 ` sjw
@ 2009-09-25 21:58                   ` Jeffrey R. Carter
  2009-09-28 13:40                   ` Stuart
  1 sibling, 0 replies; 31+ messages in thread
From: Jeffrey R. Carter @ 2009-09-25 21:58 UTC (permalink / raw)


sjw wrote:
>> "Adam Beneschan" <a...@irvine.com> wrote in message
>> news:c8af7daf-9f00-4dbb-ad0d-9ca65e0a83d6@f18g2000prf.googlegroups.com...
>>
>>> If FpB'Machine_Rounds is FALSE, though, the situation is interesting.
>>> 4.9(38) requires that static expressions get *truncated* toward zero,
>>> as I read it.  But there's no similar requirement for expressions
>>> computed at runtime.

> This is all very weird. Can I point you to my earlier post at
> http://groups.google.com/group/comp.lang.ada/msg/f79a71b9abe7e287
> which (unless I'm deluded) shows GNAT rounding away from zero for
> dynamic values even though 'Machine_Rounds is False!! (and I get the
> same results on Ubuntu 8.04 with GNAT GPL 2008.

I think Beneschan's quote about what the ARM requires when 'Machine_Rounds is 
False explains this. The compiler is truncating for static expressions as 
required, but not for dynamic expressions. Perhaps it's rounding, or perhaps 
taking the value furthest from zero, for dynamic expressions. The ARM doesn't 
seem to require a specific way of converting for dynamic expressions when 
'Machine_Rounds is False.

-- 
Jeff Carter
"You cheesy lot of second-hand electric donkey-bottom biters."
Monty Python & the Holy Grail
14



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-24  1:05             ` Adam Beneschan
  2009-09-24  3:57               ` Jeffrey R. Carter
  2009-09-25  8:47               ` Stuart
@ 2009-09-26 14:31               ` Dirk Herrmann
  2 siblings, 0 replies; 31+ messages in thread
From: Dirk Herrmann @ 2009-09-26 14:31 UTC (permalink / raw)


Adam Beneschan wrote:
> So I guess whether this is a GNAT bug or not depends on
> FpB'Machine_Rounds.  If it's TRUE, the first two expressions are
> computed incorrectly, but if it's FALSE, this seemingly anomalous
> result is allowed.

I checked that T'Machine_Rounds is FALSE for FpA and FpB.  Thus, according to 
your analysis the result should be OK with respect to the RM.

> Also, it's clear that static expressions need to round or truncate to
> a multiple of the 'Small if they're not part of a larger static
> expression.  But I'm not sure what this should do:
> 
>    FpA'Image (FpA (FpB' (-1.5)))
> 
> Here, FpB' (-1.5) *is* part of a larger static expression, so the rule
> in 4.9(38) doesn't apply.  But I'm not sure just what does apply---is
> the value of FpB'(-1.5) still assumed to be -1.5 (so that the type
> conversion to FpA still results in -1.5), or should the type
> conversion take place (which could result in -1.0 if truncation is
> used for both type conversions), or is the result unspecified by the
> language?

The following statement is made in the annotated RM (4.9(38.d/2)):
   {AI95-00100-01} Note that the only machine numbers values of a fixed point
   type are the multiples of the small, so a static conversion to a fixed-point
   type, or division by an integer, must do truncation to a multiple of small.
   It is not correct for the implementation to do all static calculations in
   infinite precision.
To me this makes it clear that conversions to a fixed point type within a 
larger static expression have to convert the value to a multiple of the small. 
  What surprises me is that it says "truncation" in contrast to 4.9(38) itself.

--
Dirk



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-25  8:47               ` Stuart
  2009-09-25 20:41                 ` sjw
@ 2009-09-26 14:43                 ` Dirk Herrmann
  2009-09-28 15:15                   ` Adam Beneschan
  1 sibling, 1 reply; 31+ messages in thread
From: Dirk Herrmann @ 2009-09-26 14:43 UTC (permalink / raw)


Stuart wrote:
> Having played with this on GNATPro 6.1.2 (to PC target) it does report 
> FpB'Machine_Rounds as false.  It also rounds values like -1.59999 down to
> -1.2 (which is a logical consequence).  Technically this is still within the 
> error bounds declared for FpB (delta 0.4) so it is not "wrong" within the 
> rules of the language definition.  But it is very counter-intuitive and is 
> the sort of thing I find frustrating.
> 
> I also tested the problem on GreenHills AdaMULTI (4.2.3 to PowerPC target); 
> this gave FpB'Machine_Rounds as true and gave the more intuitive results.
> 
>    -1.5         -> -1.6
>    -1.40001 -> -1.6
>    -1.4         -> -1.2
> 
> So although there does look to be a language "gotcha" here, it depends upon 
> the compiler's choice of 'Machine_Rounds.

Whom could I contact to figure out whether this is an omission in the language 
definition (which could then be fixed) or whether it is intentional?  I would 
also like to ask about another issue:

Dirk Herrmann wrote:
 > Robert A Duff wrote:
 >> By the way, you can say:
 >>
 >>     for T'Small use T'Delta;
 >>
 >> to avoid repeating yourself.
 >
 > I have tried that, especially since the very same recommendation was
 > given in the Barnes book "Ada 2005".  But, GNAT gives an error message.
 > It seems that the very moment you reference T'Delta the type T gets
 > "frozen" such that  the "use" statement itself freezes T before it can
 > modify it.  I don't know if this is what the authors of the reference
 > manual had intended, but GNAT interprets it that way.

--
Dirk



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-23 20:46             ` Dirk Herrmann
@ 2009-09-27 17:15               ` Simon Clubley
  0 siblings, 0 replies; 31+ messages in thread
From: Simon Clubley @ 2009-09-27 17:15 UTC (permalink / raw)


On 2009-09-23, Dirk Herrmann <fight_spam@invalid.invalid> wrote:
> Simon Clubley wrote:
>> 
>> Are you allowed to tell us which language this is ?
>
> I'd rather not, sorry Simon: Currently I am doing this investigation 
> completely in my spare time, I have no assignment to do this analysis and 
> since our current language is a development of my company itself, I feel that 
> I have to deal with this in a political way.
>

I understand. (I had not realised it was a language your company had
designed).

Thanks for having taken the time to reply.

Simon.

-- 
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980's technology to a 21st century world



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-20 18:55         ` Dirk Herrmann
  2009-09-20 20:34           ` Simon Clubley
@ 2009-09-27 19:22           ` sjw
  2009-09-28 20:18             ` Dirk Herrmann
  2009-09-28 18:37           ` Robert A Duff
  2 siblings, 1 reply; 31+ messages in thread
From: sjw @ 2009-09-27 19:22 UTC (permalink / raw)


On Sep 20, 7:55 pm, Dirk Herrmann <fight_s...@invalid.invalid> wrote:

> As I said when I started this thread, I am currently investigating whether Ada
> could be a good replacement for the proprietary fixed-point oriented language
> used in our company.  And, convincing my colleagues would certainly not be
> easier with statements like "Ada can be used, but you have to implement all
> fixed-point stuff yourself".  Even more if you can not even rely on the fact
> that a compiler will behave the same way throughout.

Is the target hardware standard? (eg, PPC without floating-point
support) If not, you're looking at a compiler port as well.

Even though GNAT/x86 seems to truncate on predefined operations and on
conversion from static values (though not, as far as I can tell, on
dynamic conversion between two types!), there seems no intrinsic
reason why a port to different hardware might not be made to round.

> Robert A Duff wrote:

> > By the way, you can say:
>
> >     for T'Small use T'Delta;
>
> > to avoid repeating yourself.
>
> I have tried that, especially since the very same recommendation was given in
> the Barnes book "Ada 2005".  But, GNAT gives an error message.  It seems that
> the very moment you reference T'Delta the type T gets "frozen" such that  the
> "use" statement itself freezes T before it can modify it.  I don't know if
> this is what the authors of the reference manual had intended, but GNAT
> interprets it that way.

The idiom used to the

T_Delta : constant := 0.4;
type T is delta T_Delta range -10.0 .. 10.0;
for T'Small use T_Delta;



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-25 20:41                 ` sjw
  2009-09-25 21:58                   ` Jeffrey R. Carter
@ 2009-09-28 13:40                   ` Stuart
  1 sibling, 0 replies; 31+ messages in thread
From: Stuart @ 2009-09-28 13:40 UTC (permalink / raw)



"sjw" <simon.j.wright@mac.com> wrote in message 
news:35adcbc7-dec6-45ae-bf80-1ebb7a058507@l35g2000vba.googlegroups.com...
> On Sep 25, 9:47 am, "Stuart" <stu...@0.0> wrote:
> "Adam Beneschan" <a...@irvine.com> wrote in message
..
> > Dirk Herrmann wrote:
DH> FpB'Image(FpB'(-1.5)) evaluates to -1.2
DH> FpB'Image(FpB(FpA'(-1.5))) evaluates to -1.2
DH> FpB'Image(MakeBFromA(FpA'(-1.5))) evaluates to -1.6

AB> The answer is curious (and I'm not sure if it's what the language
AB> designers intended). 4.9(38) says, ...
AB> ...
AB> If FpB'Machine_Rounds is FALSE, though, the situation is interesting.
AB> 4.9(38) requires that static expressions get *truncated* toward zero,
AB> as I read it. But there's no similar requirement for expressions
AB> computed at runtime.

S> Having played with this on GNATPro 6.1.2 (to PC target) it does report
S> FpB'Machine_Rounds as false. It also rounds values like -1.59999 down to
S> -1.2 (which is a logical consequence). Technically this is still within 
the
S> error bounds declared for FpB (delta 0.4) so it is not "wrong" within the
S> rules of the language definition. But it is very counter-intuitive and is
S> the sort of thing I find frustrating.
S>
S> I also tested the problem on GreenHills AdaMULTI (4.2.3 to PowerPC 
target);
S> this gave FpB'Machine_Rounds as true and gave the more intuitive results.
S>
S> -1.5 -> -1.6
S> -1.40001 -> -1.6
S> -1.4 -> -1.2
S>
S> So although there does look to be a language "gotcha" here, it depends 
upon
S> the compiler's choice of 'Machine_Rounds.

SW> This is all very weird. Can I point you to my earlier post at
SW> http://groups.google.com/group/comp.lang.ada/msg/f79a71b9abe7e287
SW> which (unless I'm deluded) shows GNAT rounding away from zero for
SW> dynamic values even though 'Machine_Rounds is False!! (and I get the
SW> same results on Ubuntu 8.04 with GNAT GPL 2008.

Sorry for any confusion Simon, I was stating my results for static values; 
for computed/dynamic conversions GNAT does round to nearest (so, away from 0 
for -1.5).
-- 
Stuart 





^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-26 14:43                 ` Dirk Herrmann
@ 2009-09-28 15:15                   ` Adam Beneschan
  0 siblings, 0 replies; 31+ messages in thread
From: Adam Beneschan @ 2009-09-28 15:15 UTC (permalink / raw)


On Sep 26, 7:43 am, Dirk Herrmann <fight_s...@invalid.invalid> wrote:

> Whom could I contact to figure out whether this is an omission in the language
> definition (which could then be fixed) or whether it is intentional?  I would
> also like to ask about another issue:
>
> Dirk Herrmann wrote:
>
>  > Robert A Duff wrote:
>  >> By the way, you can say:
>  >>
>  >>     for T'Small use T'Delta;
>  >>
>  >> to avoid repeating yourself.
>  >
>  > I have tried that, especially since the very same recommendation was
>  > given in the Barnes book "Ada 2005".  But, GNAT gives an error message.
>  > It seems that the very moment you reference T'Delta the type T gets
>  > "frozen" such that  the "use" statement itself freezes T before it can
>  > modify it.  I don't know if this is what the authors of the reference
>  > manual had intended, but GNAT interprets it that way.

Although at first glance it seems like you should be able to do this,
I don't think it's likely that the RM could make this work in the
general case.  The rules do say that the occurrence of T'Delta causes
freezing; I believe this is part of the rule that an expression causes
freezing (except for nonstatic expressions used in parameter or
component defaults and some other cases).  Here, T'Delta is a static
expression and thus requires T to be frozen.

If we were to make an exception that, say, a representation attribute
of T does not cause freezing if it occurs in another representation
clause for T, you could end up with some interesting situations:

   type Arr is array (1 .. 5) of Boolean;
   for A'Size use A'Component_Size * 8;
   for A'Component_Size use A'Size - 14;

and now the compiler has to figure out how to solve for two
variables.  I suppose it's possible to write RM rules in such a way as
to prevent things like this while allowing the 'Small/'Delta case, but
this either requires some pretty complex rules, or rules that just
spell out a number of special cases (such as saying "An expression
causes freezing except in the one particular clause FOR T'SMALL USE
T'DELTA).  Neither one is going to be appealing particularly for such
a small gain---it doesn't give programmers the ability to do anything
that couldn't be accomplished easily with just a tiny bit more
effort.

Bottom line: it isn't possible to make the language make everything
work that looks like it should work.  Ada is, after all, a Programming
Language and not a Mind-Reading Machine.

                                        -- Adam




^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-20 18:55         ` Dirk Herrmann
  2009-09-20 20:34           ` Simon Clubley
  2009-09-27 19:22           ` sjw
@ 2009-09-28 18:37           ` Robert A Duff
  2009-09-28 20:50             ` Dirk Herrmann
  2 siblings, 1 reply; 31+ messages in thread
From: Robert A Duff @ 2009-09-28 18:37 UTC (permalink / raw)


Dirk Herrmann <fight_spam@invalid.invalid> writes:

> Robert A Duff wrote:
>> Dirk Herrmann <fight_spam@invalid.invalid> writes:
> As I said when I started this thread, I am currently investigating
> whether Ada could be a good replacement for the proprietary fixed-point
> oriented language used in our company.  And, convincing my colleagues
> would certainly not be easier with statements like "Ada can be used, but
> you have to implement all fixed-point stuff yourself".

Well, yeah, but not "all fixed-point stuff" -- just conversions,
when the 'Smalls are incompatible.

Does it make sense in your context to avoid "odd-ball" smalls?
Note that the default 'Small is a power of 2.

>> By the way, you can say:
>>     for T'Small use T'Delta;
>> to avoid repeating yourself.
>
> I have tried that, especially since the very same recommendation was
> given in the Barnes book "Ada 2005".  But, GNAT gives an error message.

Oops.  You're right.  It's illegal by the freezing rules.
Sorry for the misinformation.

- Bob



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-27 19:22           ` sjw
@ 2009-09-28 20:18             ` Dirk Herrmann
  0 siblings, 0 replies; 31+ messages in thread
From: Dirk Herrmann @ 2009-09-28 20:18 UTC (permalink / raw)


sjw wrote:
> Is the target hardware standard?

Yes, it's an ARM core.

> T_Delta : constant := 0.4;
> type T is delta T_Delta range -10.0 .. 10.0;
> for T'Small use T_Delta;

:-)

However, what I don't like about this solution is, that you have to make 
T_Delta publically visible.  My point is not about anybody not knowing about 
T'Small - it's just that you can not control the use of the symbol T_Delta. 
Maybe later you want to rename it, or share the same constant between T1 and T2.

--
Dirk



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: conversions between fixed-point types
  2009-09-28 18:37           ` Robert A Duff
@ 2009-09-28 20:50             ` Dirk Herrmann
  0 siblings, 0 replies; 31+ messages in thread
From: Dirk Herrmann @ 2009-09-28 20:50 UTC (permalink / raw)


Robert A Duff wrote:
> Does it make sense in your context to avoid "odd-ball" smalls?
> Note that the default 'Small is a power of 2.

Actually, most of our code uses powers of two.  Still we have to think about 
rounding when, for example, we are converting values from a small of 0.125 to 
a small of 0.5.  But, Adam's suggestion seems to work fine:
    Y := Integer (X / FpB'Small) * FpB'Small;
The resulting x86 assembly code could be improved a little, but I have not 
checked the ARM code yet.

--
Dirk



^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2009-09-28 20:50 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-18 21:35 conversions between fixed-point types Dirk Herrmann
2009-09-18 22:42 ` Adam Beneschan
2009-09-19 12:41 ` Dirk Herrmann
2009-09-19 14:48   ` John B. Matthews
2009-09-20  8:15     ` Dirk Herrmann
2009-09-20 14:22       ` Robert A Duff
2009-09-20 18:55         ` Dirk Herrmann
2009-09-20 20:34           ` Simon Clubley
2009-09-23 20:46             ` Dirk Herrmann
2009-09-27 17:15               ` Simon Clubley
2009-09-27 19:22           ` sjw
2009-09-28 20:18             ` Dirk Herrmann
2009-09-28 18:37           ` Robert A Duff
2009-09-28 20:50             ` Dirk Herrmann
2009-09-20 15:18       ` John B. Matthews
2009-09-20 19:13         ` Dirk Herrmann
2009-09-20 20:09       ` tmoran
2009-09-21 17:24       ` Jeffrey R. Carter
2009-09-23 20:57         ` Dirk Herrmann
2009-09-23 22:28           ` Jeffrey R. Carter
2009-09-24  1:05             ` Adam Beneschan
2009-09-24  3:57               ` Jeffrey R. Carter
2009-09-25  8:47               ` Stuart
2009-09-25 20:41                 ` sjw
2009-09-25 21:58                   ` Jeffrey R. Carter
2009-09-28 13:40                   ` Stuart
2009-09-26 14:43                 ` Dirk Herrmann
2009-09-28 15:15                   ` Adam Beneschan
2009-09-26 14:31               ` Dirk Herrmann
2009-09-19 18:38   ` tmoran
2009-09-20  8:22 ` sjw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox