comp.lang.ada
 help / color / mirror / Atom feed
* Why no 'Floor for fixed point types
@ 2003-10-23 20:09 Duncan Sands
  2003-10-23 22:06 ` Robert I. Eachus
                   ` (2 more replies)
  0 siblings, 3 replies; 22+ messages in thread
From: Duncan Sands @ 2003-10-23 20:09 UTC (permalink / raw)
  To: comp.lang.ada

I think the subject says it all.  Just curious.

Duncan.



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

* Re: Why no 'Floor for fixed point types
  2003-10-23 20:09 Why no 'Floor for fixed point types Duncan Sands
@ 2003-10-23 22:06 ` Robert I. Eachus
  2003-10-24 16:00   ` Stephen Leake
  2003-10-23 23:10 ` Martin Dowie
  2003-10-24 21:46 ` Nick Roberts
  2 siblings, 1 reply; 22+ messages in thread
From: Robert I. Eachus @ 2003-10-23 22:06 UTC (permalink / raw)


Duncan Sands wrote:
> I think the subject says it all.  Just curious.

For floating-point types, integer values are either model numbers or in 
a range limited by two integer model numbers.  (Or are IEEE infinities 
or NANs.)

But for fixed-point types, there may be few integer values that can be 
represented.  A typical example might be:

type Radians is delta Pi/1000 range -Pi..Pi;
for Radians'small use Pi/1000;

where the only integer value of the type is zero.

For type Radians what should Radians'Floor return? It doesn't make much 
sense for it to return a value that is approximately an integer, 
especially since Radians'Floor(Radians'Floor(X)) = Randians'Floor(X) 
could return false.  It might be nice to have a type conversion to 
Integer that truncated instead of rounding, but that is a different 
question.
-- 
                                            Robert I. Eachus

"Quality is the Buddha. Quality is scientific reality. Quality is the 
goal of Art. It remains to work these concepts into a practical, 
down-to-earth context, and for this there is nothing more practical or 
down-to-earth than what I have been talking about all along...the repair 
of an old motorcycle."  -- from Zen and the Art of Motorcycle 
Maintenance by Robert Pirsig




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

* Re: Why no 'Floor for fixed point types
  2003-10-23 20:09 Why no 'Floor for fixed point types Duncan Sands
  2003-10-23 22:06 ` Robert I. Eachus
@ 2003-10-23 23:10 ` Martin Dowie
  2003-10-24 21:46 ` Nick Roberts
  2 siblings, 0 replies; 22+ messages in thread
From: Martin Dowie @ 2003-10-23 23:10 UTC (permalink / raw)


"Duncan Sands" <baldrick@free.fr> wrote in message
news:mailman.194.1066939697.25614.comp.lang.ada@ada-france.org...
> I think the subject says it all.  Just curious.

It only makes sense to convert to a float then to an integer - what
if there is no fixed point value that has the same magnitude as an
integer value? It is annoying though, when in 'real life' you don't
really care about the middle conversion, e.g.

My_Int := My_Int_Type (My_Float_Type'Floor (My_Fixed_Type'(1.5)));

My_Int should be 1.

I've just been throew this one myself and if you think long
and hard you will see the logic :-)





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

* Re: Why no 'Floor for fixed point types
  2003-10-23 22:06 ` Robert I. Eachus
@ 2003-10-24 16:00   ` Stephen Leake
  2003-10-24 18:13     ` Duncan Sands
  0 siblings, 1 reply; 22+ messages in thread
From: Stephen Leake @ 2003-10-24 16:00 UTC (permalink / raw)


"Robert I. Eachus" <rieachus@comcast.net> writes:

> type Radians is delta Pi/1000 range -Pi..Pi;
> for Radians'small use Pi/1000;
> 
> where the only integer value of the type is zero.
> 
> For type Radians what should Radians'Floor return? 

An Integer, that is the truncated value.

Hmm, I guess it needs to be generic, so you can specify which integer
type to use for the result. 

-- 
-- Stephe



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

* Re: Why no 'Floor for fixed point types
  2003-10-24 16:00   ` Stephen Leake
@ 2003-10-24 18:13     ` Duncan Sands
  0 siblings, 0 replies; 22+ messages in thread
From: Duncan Sands @ 2003-10-24 18:13 UTC (permalink / raw)
  To: Stephen Leake, comp.lang.ada

On Friday 24 October 2003 18:00, Stephen Leake wrote:
> "Robert I. Eachus" <rieachus@comcast.net> writes:
> > type Radians is delta Pi/1000 range -Pi..Pi;
> > for Radians'small use Pi/1000;
> >
> > where the only integer value of the type is zero.
> >
> > For type Radians what should Radians'Floor return?
>
> An Integer, that is the truncated value.
>
> Hmm, I guess it needs to be generic, so you can specify which integer
> type to use for the result.

Though given the amazing rules for multiplication of different fixed point
types (result type determined by the context), I doubt that would stop
a determined language designer...

Thanks for your comments,

Duncan.



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

* Re: Why no 'Floor for fixed point types
  2003-10-23 20:09 Why no 'Floor for fixed point types Duncan Sands
  2003-10-23 22:06 ` Robert I. Eachus
  2003-10-23 23:10 ` Martin Dowie
@ 2003-10-24 21:46 ` Nick Roberts
  2003-10-25  4:29   ` Robert I. Eachus
  2 siblings, 1 reply; 22+ messages in thread
From: Nick Roberts @ 2003-10-24 21:46 UTC (permalink / raw)


Duncan Sands wrote:

> I think the subject says it all.  Just curious.
> 
> Duncan.

For a fixed point type Tf -- assuming it has a delta which is less than 1 
-- you can write:

    Scale: constant := 1/Tf'Small;

    type Ti is range Tf'First*Scale .. Tf'Last*Scale;

    function Scaled_Floor (X: in Tf) return Ti is
    begin
       return Ti(X*Scale) - Ti(X*Scale) mod Ti(Scale);
    end;

The basic idea is that with fixed point types, a 'floor' function will 
inevitably need to be scaled, and the integer type it returns needs to be 
customised to the fixed point type (its range and delta) and the chosen 
scale. I've shown a scale of 1/Tf'Small, but the chances are that the scale 
you will require in a certain situation will be different (it might be unity).

A little more information about your specific problem would enable us to 
give a more detailed diagnosis.

-- 
Nick Roberts




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

* Re: Why no 'Floor for fixed point types
  2003-10-24 21:46 ` Nick Roberts
@ 2003-10-25  4:29   ` Robert I. Eachus
  2003-10-25 20:42     ` Nick Roberts
  0 siblings, 1 reply; 22+ messages in thread
From: Robert I. Eachus @ 2003-10-25  4:29 UTC (permalink / raw)


Nick Roberts wrote:

> For a fixed point type Tf -- assuming it has a delta which is less than 
> 1 -- you can write:
> 
>    Scale: constant := 1/Tf'Small;
> 
>    type Ti is range Tf'First*Scale .. Tf'Last*Scale;
> 
>    function Scaled_Floor (X: in Tf) return Ti is
>    begin
>       return Ti(X*Scale) - Ti(X*Scale) mod Ti(Scale);
>    end;
> 
> The basic idea is that with fixed point types, a 'floor' function will 
> inevitably need to be scaled, and the integer type it returns needs to 
> be customised to the fixed point type (its range and delta) and the 
> chosen scale. I've shown a scale of 1/Tf'Small, but the chances are that 
> the scale you will require in a certain situation will be different (it 
> might be unity).

Ignore this.  To quote RM 3.5.9(8): "The set of values of a fixed point 
type comprise the integral multiples of a number called the small of the 
type."  So the effect of all the code above can be better accomplished by:

   function Mantissa(X: in Tf) return Ti is
   begin return Ti(X/Tf'Small); end Mantissa;

-- Technically you could use the constant named Scale above, but there
-- are some potential rounding issues.  Writing it this way allows the
-- compiler to convert the division to a multiplication that gives the
-- same result, if it can.

-- Of course, any decent compiler should be able to recognize this
-- special case and do nothing.  If your compiler doesn't recognize this
-- you could rewrite Mantissa as an instance of Unchecked_Conversion.



-- 
                                                     Robert I. Eachus

"Quality is the Buddha. Quality is scientific reality. Quality is the 
goal of Art. It remains to work these concepts into a practical, 
down-to-earth context, and for this there is nothing more practical or 
down-to-earth than what I have been talking about all along...the repair 
of an old motorcycle."  -- from Zen and the Art of Motorcycle 
Maintenance by Robert Pirsig




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

* Re: Why no 'Floor for fixed point types
  2003-10-25  4:29   ` Robert I. Eachus
@ 2003-10-25 20:42     ` Nick Roberts
  2003-10-25 22:40       ` Robert I. Eachus
  2003-10-27 18:49       ` Randy Brukardt
  0 siblings, 2 replies; 22+ messages in thread
From: Nick Roberts @ 2003-10-25 20:42 UTC (permalink / raw)


Robert I. Eachus wrote:

> ...
> Ignore this.  To quote RM 3.5.9(8): "The set of values of a fixed point 
> type comprise the integral multiples of a number called the small of the 
> type."  So the effect of all the code above can be better accomplished by:
> 
>   function Mantissa(X: in Tf) return Ti is
>   begin return Ti(X/Tf'Small); end Mantissa;

No, Robert. Wrong! This function fails to do the 'floor' part of the 
calculation. The name 'Mantissa' is misleading, since the result will not 
be the mantissa (the decimal digits to the left of the decimal point) 
unless Tf'Small happens to be 1.0 (and I did explicitly exclude this case).

> -- Technically you could use the constant named Scale above, but there
> -- are some potential rounding issues.  Writing it this way allows the
> -- compiler to convert the division to a multiplication that gives the
> -- same result, if it can.

For a conforming compiler, there should be no rounding issues in the case 
Scale=1/Tf'Small, the division is a static expression (which should be 
calculated precisely at compile time), and I would expect the 
multiplications to be eliminated. For other scales, of course there will be 
rounding issues, which must be dealt with; this was rather the point I was 
trying to emphasise.

> -- Of course, any decent compiler should be able to recognize this
> -- special case and do nothing.  If your compiler doesn't recognize this
> -- you could rewrite Mantissa as an instance of Unchecked_Conversion.

Yuk! I would suggest you either put up with the redundant operation or get 
a new compiler.

Maybe an example would help.

Suppose we have a temperature in variable Temp, of type Temperature (in 
degrees celsius):

    type Temperature is delta 0.2 range -15.0 .. 90.0;

    Temp: Temperature := Read_Sensor(...);

Now suppose we have a subsystem that can display two decimal digits 
(perhaps on a 7-segment LED display), and we can use the following 
procedure to do it:

    type Two_Decimal_Digits is range 00..99;

    procedure Display (Digits: in Two_Decimal_Digits);

What we need to be able to do is to convert the fixed point type 
Temperature into the integer type Two_Decimal_Digits. It might be in the 
specification that the figure displayed should be the mantissa of the value 
in Temp; this implies a 'floor' function (rounding down to the nearest 
whole degree celsius).

Having declared:

    Scale: constant := 1/Temperature'Small;

    type Scaled_Temperature is
       range Temperature'First*Scale .. Temperature'Last*Scale;

    function Scaled_Floor (X: in Temperature) return Scaled_Temperature is
       subtype ST is Scaled_Temperature;
    begin
       return ST(X*Scale) - ST(X*Scale) mod ST(Scale);
    end;

    function Mantissa (T: in Temperature) return Two_Decimal_Digits is
    begin
       return Two_Decimal_Digits(Scaled_Floor(T)/Scaled_Temperature(Scale));
    end;

we can now conveniently write:

    Display( Mantissa(Temp) );

In general, the sequence of events in the calculation will be: scale the 
value; convert it to an integer; calculate the scaled floor (using integer 
arithmetic); rescale the result as required. In my example, the 
Scaled_Floor function scales the value, and the Mantissa function unscales 
it again. I hope this clarifies things a bit.

-- 
Nick Roberts




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

* Re: Why no 'Floor for fixed point types
  2003-10-25 20:42     ` Nick Roberts
@ 2003-10-25 22:40       ` Robert I. Eachus
  2003-10-27 18:59         ` Randy Brukardt
  2003-10-28 18:10         ` Nick Roberts
  2003-10-27 18:49       ` Randy Brukardt
  1 sibling, 2 replies; 22+ messages in thread
From: Robert I. Eachus @ 2003-10-25 22:40 UTC (permalink / raw)


Nick Roberts wrote:
>I said:
>> Ignore this.  To quote RM 3.5.9(8): "The set of values of a fixed 
>> point type comprise the integral multiples of a number called the 
>> small of the type."  So the effect of all the code above can be better 
>> accomplished by:
>>
>>   function Mantissa(X: in Tf) return Ti is
>>   begin return Ti(X/Tf'Small); end Mantissa;
> 
> 
> No, Robert. Wrong! This function fails to do the 'floor' part of the 
> calculation. The name 'Mantissa' is misleading, since the result will 
> not be the mantissa (the decimal digits to the left of the decimal 
> point) unless Tf'Small happens to be 1.0 (and I did explicitly exclude 
> this case).

First, the mantissa is not "the decimal digits to the left of the 
decimal point."  For a number written in scaled notation: 1.2345E6 it is 
the part of the number before the exponent.  Since in your program you 
are attempting to remove the scaling from a fixed-point type, the name 
Mantissa seemed appropriate.  Change it if you wish.

But you didn't pay attention above.  The compiler allows you to think 
about fixed-point types as if they are real (non-integer) values.  But 
they are not implemented that way.  Any compiler that uses 
floating-point arithmetic to do fixed-point computations has a lot of 
bugs in it.   They just havent been found yet.  (And I think it was ACVC 
1.4 that added a lot of tests which found such bugs.)

Fixed point values are represented as integers.  Their "actual" value is 
the integer times a scale factor 'Small.  If you divide a fixed point 
number by its 'Small, you get an integer.  Doing the arithmetic right 
can be tricky in theory, but most compilers are smart enough to 
recognize that all they need to do is nothing.  That was why I advised 
you to write it that way--compilers are sensitive to that special case:

>> -- Of course, any decent compiler should be able to recognize this
>> -- special case and do nothing.  If your compiler doesn't recognize this
>> -- you could rewrite Mantissa as an instance of Unchecked_Conversion.

> Yuk! I would suggest you either put up with the redundant operation or 
> get a new compiler.

I assume that the Yuk! was about the reference to Unchecked_Conversion. 
  But I think you didn't understand why it was there.  I was not 
encouraging anyone to write that way, but to use 'Small in an idiom the 
compiler should recognize.  I only mentioned the Unchecked_Conversion 
possibility to help people recognize what is going on in this function: 
  NOTHING.  It is a notation to tell the compiler to switch from 
treating the value as having fixed-point type, and to instead look at 
the value as an integer.

> Maybe an example would help.

Okay.

> Suppose we have a temperature in variable Temp, of type Temperature (in 
> degrees celsius):
> 
>    type Temperature is delta 0.2 range -15.0 .. 90.0;
> 
>    Temp: Temperature := Read_Sensor(...);
> 
> Now suppose we have a subsystem that can display two decimal digits 
> (perhaps on a 7-segment LED display), and we can use the following 
> procedure to do it:
> 
>    type Two_Decimal_Digits is range 00..99;
> 
>    procedure Display (Digits: in Two_Decimal_Digits);
> 
> What we need to be able to do is to convert the fixed point type 
> Temperature into the integer type Two_Decimal_Digits. It might be in the 
> specification that the figure displayed should be the mantissa of the 
> value in Temp; this implies a 'floor' function (rounding down to the 
> nearest whole degree celsius).
> 
> Having declared:
> 
>    Scale: constant := 1/Temperature'Small;
> 
>    
>       range Temperature'First*Scale .. Temperature'Last*Scale;

At this point the compiler will give you an error message.  Let's say we 
  fix it:

        type Scaled_Temperature is
                  range Integer(Temperature'First/Temperature'Small)
                       ..Integer(Temperature'Last/Temperature'Small);

>    function Scaled_Floor (X: in Temperature) return Scaled_Temperature is
>       subtype ST is Scaled_Temperature;
>    begin
>       return ST(X*Scale) - ST(X*Scale) mod ST(Scale);
>    end;

...Now I understand the problem you think you are solving with this 
code.  With the fix above so it compiles, for lots of values of 
Temperature'Small you will end up dividing by zero.  With other values 
of Temperature'Small you will have overflows.  So the range where your 
method works is fairly small.  For this particular problem though,

     Integer(Float'Floor(Float(X)));

Should do what you want.  (Or what you should want, or something like that.)

-- 
                                                     Robert I. Eachus

"Quality is the Buddha. Quality is scientific reality. Quality is the 
goal of Art. It remains to work these concepts into a practical, 
down-to-earth context, and for this there is nothing more practical or 
down-to-earth than what I have been talking about all along...the repair 
of an old motorcycle."  -- from Zen and the Art of Motorcycle 
Maintenance by Robert Pirsig




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

* Re: Why no 'Floor for fixed point types
  2003-10-25 20:42     ` Nick Roberts
  2003-10-25 22:40       ` Robert I. Eachus
@ 2003-10-27 18:49       ` Randy Brukardt
  2003-10-28 18:32         ` Nick Roberts
  1 sibling, 1 reply; 22+ messages in thread
From: Randy Brukardt @ 2003-10-27 18:49 UTC (permalink / raw)


"Nick Roberts" <nick.roberts@acm.org> wrote in message
news:bnen7p$vjo06$1@ID-25716.news.uni-berlin.de...
> For a conforming compiler, there should be no rounding issues in the case
> Scale=1/Tf'Small, the division is a static expression (which should be
> calculated precisely at compile time), and I would expect the
> multiplications to be eliminated.

Not true if Tf is a generic formal type (and this is a common way to
implement such code). Moreover, if you use a code-sharing compiler such as
Janus/Ada, it won't be calculated at compile-time, either.

                   Randy.






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

* Re: Why no 'Floor for fixed point types
  2003-10-25 22:40       ` Robert I. Eachus
@ 2003-10-27 18:59         ` Randy Brukardt
  2003-10-28  1:19           ` Robert I. Eachus
  2003-10-28 18:10         ` Nick Roberts
  1 sibling, 1 reply; 22+ messages in thread
From: Randy Brukardt @ 2003-10-27 18:59 UTC (permalink / raw)


"Robert I. Eachus" <rieachus@comcast.net> wrote in message
news:3F9AFB67.5080401@comcast.net...
> But you didn't pay attention above.  The compiler allows you to think
> about fixed-point types as if they are real (non-integer) values.  But
> they are not implemented that way.  Any compiler that uses
> floating-point arithmetic to do fixed-point computations has a lot of
> bugs in it.   They just havent been found yet.  (And I think it was ACVC
> 1.4 that added a lot of tests which found such bugs.)

As usual with blanket statements, this is wrong. Janus/Ada in fact does use
floating-point arithmetic to implement fixed point in some cases (especially
the mixed multiply). We did the error analysis on these operations, and they
are fine - they'll get the right answer in all cases that Ada 95 requires
that. (There are some cases where no technique will get the "right" answer
as defined in Ada 83, and those of course we might get wrong for some bit
patterns. Many Ada 83 compilers simply avoided the issue by restricting
'Small to powers of two, which of course is trivial to get right. And rather
restrictive.) Since, in a generic, you don't know the 'Smalls involved, and
you don't know the magatude of the values, there isn't much else to do
except use the highest precision math that you have available. As with
everything, it depends on how you use it.

                        Randy.

                   Randy.






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

* Re: Why no 'Floor for fixed point types
  2003-10-27 18:59         ` Randy Brukardt
@ 2003-10-28  1:19           ` Robert I. Eachus
  2003-10-28 18:23             ` Nick Roberts
  0 siblings, 1 reply; 22+ messages in thread
From: Robert I. Eachus @ 2003-10-28  1:19 UTC (permalink / raw)


Randy Brukardt wrote:
> "Robert I. Eachus" <rieachus@comcast.net> wrote in message
> news:3F9AFB67.5080401@comcast.net...
> 
>>But you didn't pay attention above.  The compiler allows you to think
>>about fixed-point types as if they are real (non-integer) values.  But
>>they are not implemented that way.  Any compiler that uses
>>floating-point arithmetic to do fixed-point computations has a lot of
>>bugs in it.   They just havent been found yet.  (And I think it was ACVC
>>1.4 that added a lot of tests which found such bugs.) 
> 
> As usual with blanket statements, this is wrong. Janus/Ada in fact does use
> floating-point arithmetic to implement fixed point in some cases (especially
> the mixed multiply). We did the error analysis on these operations, and they
> are fine - they'll get the right answer in all cases that Ada 95 requires
> that. (There are some cases where no technique will get the "right" answer
> as defined in Ada 83, and those of course we might get wrong for some bit
> patterns. Many Ada 83 compilers simply avoided the issue by restricting
> 'Small to powers of two, which of course is trivial to get right. And rather
> restrictive.) Since, in a generic, you don't know the 'Smalls involved, and
> you don't know the magatude of the values, there isn't much else to do
> except use the highest precision math that you have available. As with
> everything, it depends on how you use it.

Actually, I think you are agreeing with me.  Trying to test even a small 
subset of all possible reasonable values of 'Small and fixed-point 
numbers just isn't reasonably possible without trillions of machines 
crunching for millions of years.   So your compiler probably has 
millions of errors in the low order bit that are just not practical to 
find, and of no real interest to anyone anyway.  From experience with 
fixed-point, the tough cases are of the form A := Fixed(B*C); where B 
and C are of two other types than Fixed, and there is no easy 
representation of Fixed'Small/(B_type'Small * C_type'Small).

In practice those cases are of little or no interest to anyone.  If your 
compiler correctly implements A := A * I; where I is an Integer, or A := 
B + C; where all three are of the same fixed-point type, then I and most 
other fixed-point users won't care about those painful cases.  Other 
than, of course, to note that they exist so that we can avoid them.

If you do use the three type multiplication operator, you should check 
whether it is an easy or hard case, and avoid the hard cases.  (Any 
conversion where the target type is the same as one of the multiplicand 
types counts as easy, since it can be done with a single division.)

I'm not trying to scare anyone here.  In fact one of the differences 
between Ada 83 and Ada 95 is that the error bounds on the hard cases 
were changed to make them easier to implement.  The hard cases do come 
up, and for example, one of the harder parts of the Euro conversion was 
to specify rules and error bounds for some of these three type 
conversions.  (Say from Marks to Kronar, using today's market rates for 
Marks to Euros and Euros to Kronar.)

-- 
                                           Robert I. Eachus

"Quality is the Buddha. Quality is scientific reality. Quality is the 
goal of Art. It remains to work these concepts into a practical, 
down-to-earth context, and for this there is nothing more practical or 
down-to-earth than what I have been talking about all along...the repair 
of an old motorcycle."  -- from Zen and the Art of Motorcycle 
Maintenance by Robert Pirsig




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

* Re: Why no 'Floor for fixed point types
  2003-10-25 22:40       ` Robert I. Eachus
  2003-10-27 18:59         ` Randy Brukardt
@ 2003-10-28 18:10         ` Nick Roberts
  1 sibling, 0 replies; 22+ messages in thread
From: Nick Roberts @ 2003-10-28 18:10 UTC (permalink / raw)


Robert I. Eachus wrote:

>> No, Robert. Wrong! This function fails to do the 'floor' part of the 
>> calculation. The name 'Mantissa' is misleading, since the result will 
>> not be the mantissa (the decimal digits to the left of the decimal 
>> point) unless Tf'Small happens to be 1.0 (and I did explicitly exclude 
>> this case).
> 
> First, the mantissa is not "the decimal digits to the left of the 
> decimal point."  For a number written in scaled notation: 1.2345E6 it is 
> the part of the number before the exponent.  Since in your program you 
> are attempting to remove the scaling from a fixed-point type, the name 
> Mantissa seemed appropriate.  Change it if you wish.

I'm sorry, you're right about the mantissa. In fact, in your example, I 
think the mantissa would strictly be 0.12345, and the exponent 7, but I 
wouldn't mind being set straight on this point.

> But you didn't pay attention above.  The compiler allows you to think 
> about fixed-point types as if they are real (non-integer) values.  But 
> they are not implemented that way.  Any compiler that uses 
> floating-point arithmetic to do fixed-point computations has a lot of 
> bugs in it.   They just havent been found yet.  (And I think it was ACVC 
> 1.4 that added a lot of tests which found such bugs.) Fixed point values
 > are represented as integers.

I understand that fixed point types are intended to be represented as 
integers, and that most Ada implementations do so. I also thought the idea 
was that the Ada 95 standard was framed to permit other representations. I 
have heard that on some machines it makes sense to use the native 
floating-point representation (because the machine has sufficient support 
for operations on this representation).

When you say 'bugs', I guess you mean 'inaccuracies'. I would honestly 
appreciate you saying a bit more on this subject (it is quite important to 
me, as a compiler writer!).

I'm also not really sure as to the point you really making, Robert, so -- 
at the risk of trying your patience -- I'd appreciate any clarification you 
can make.

> Their "actual" value is 
> the integer times a scale factor 'Small.  If you divide a fixed point 
> number by its 'Small, you get an integer.  Doing the arithmetic right 
> can be tricky in theory, but most compilers are smart enough to 
> recognize that all they need to do is nothing.  That was why I advised 
> you to write it that way--compilers are sensitive to that special case:

Well, from the point of view of the compiler I am writing, I would be 
grateful for more information on the tricky bits.

>>> -- Of course, any decent compiler should be able to recognize this
>>> -- special case and do nothing.  If your compiler doesn't recognize this
>>> -- you could rewrite Mantissa as an instance of Unchecked_Conversion.
> 
>> Yuk! I would suggest you either put up with the redundant operation or 
>> get a new compiler.
> 
> I assume that the Yuk! was about the reference to Unchecked_Conversion. 

Yes it was. Surely it is possible that there will be differences between 
the underlying integer an implementation uses for a fixed point type, and 
an apparently equivalent integer type. For example, the implementation may 
offset the value in the former. What works for one implementation is likely 
to be non-portable, and could suddenly fail in many other circumstances too.

>  But I think you didn't understand why it was there.  I was not 
> encouraging anyone to write that way, but to use 'Small in an idiom the 
> compiler should recognize.  I only mentioned the Unchecked_Conversion 
> possibility to help people recognize what is going on in this function: 
>  NOTHING.  It is a notation to tell the compiler to switch from treating 
> the value as having fixed-point type, and to instead look at the value 
> as an integer.

Okay, I understand that, and that is part of what I was trying to achieve 
with the Scaled_Floor I suggested.

The other part of what I was trying to achieve with this function was the 
'floor' part, where the value is rounded down to the nearest 1/Tf'Small. I 
was suggesting this second part should be done using integer arithmetic 
(after conversion). Are you saying that this part should be done using 
fixed-point arithmetic? (I think you might be right.)

>> Having declared:
>>
>>    Scale: constant := 1/Temperature'Small;
>>
>>       type Scaled_Temperature is
>>          range Temperature'First*Scale .. Temperature'Last*Scale;
> 
> 
> At this point the compiler will give you an error message.  Let's say we 
>  fix it:
> 
>        type Scaled_Temperature is
>                  range Integer(Temperature'First/Temperature'Small)
>                       ..Integer(Temperature'Last/Temperature'Small);

Oops! Well spotted. Possibly this mistake suggests that Scaled_Temperature 
should be a fixed point type, rather than an integer type (with delta 1.0). 
Do you agree?

>>    function Scaled_Floor (X: in Temperature) return Scaled_Temperature is
>>       subtype ST is Scaled_Temperature;
>>    begin
>>       return ST(X*Scale) - ST(X*Scale) mod ST(Scale);
>>    end;
> 
> ...Now I understand the problem you think you are solving with this 
> code.  With the fix above so it compiles, for lots of values of 
> Temperature'Small you will end up dividing by zero.

Is that so? Could you please illustrate. Remember, I did specifically say 
that Tf'Delta is less than 1.

> With other values 
> of Temperature'Small you will have overflows.  So the range where your 
> method works is fairly small.

Again, I'd appreciate more information about this.

 > For this particular problem though,
> 
>     Integer(Float'Floor(Float(X)));
> 
> Should do what you want.

But this begs the original question of this thread, doesn't it? Why doesn't 
Ada 95 provide the Floor attribute for fixed point types? I admit I never 
really answered this question, and it's a fair one, isn't it?

Also, is the above formulation (which I think we can assume really would 
convert the value to a floating-point representation, and then use some 
kind of iterative approximation scheme to compute the floor value, and then 
convert to Integer) reasonably efficient?

> (Or what you should want, or something like that.)

Hehe. Of course, the trick is always to know what you need, rather than 
what you want.

-- 
Nick Roberts




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

* Re: Why no 'Floor for fixed point types
  2003-10-28  1:19           ` Robert I. Eachus
@ 2003-10-28 18:23             ` Nick Roberts
  2003-10-28 18:34               ` Stephane Richard
  2003-10-29 19:26               ` Randy Brukardt
  0 siblings, 2 replies; 22+ messages in thread
From: Nick Roberts @ 2003-10-28 18:23 UTC (permalink / raw)


Robert I. Eachus wrote:

> ...  Trying to test even a small 
> subset of all possible reasonable values of 'Small and fixed-point 
> numbers just isn't reasonably possible without trillions of machines 
> crunching for millions of years.   So your compiler probably has 
> millions of errors in the low order bit that are just not practical to 
> find, and of no real interest to anyone anyway.

So possibly a question we should ask is "If nobody cares, does it count as 
an error (or bug)?" I admit, there might be a few Intel customers who'd 
like to know the answer to that one. :-)

> From experience with 
> fixed-point, the tough cases are of the form A := Fixed(B*C); where B 
> and C are of two other types than Fixed, and there is no easy 
> representation of Fixed'Small/(B_type'Small * C_type'Small).

What do you mean when you say these are tough cases? The RM95 essentially 
says that the result is either of the representable values (of the type 
Fixed here) which bound the precise result.

> In practice those cases are of little or no interest to anyone.  If your 
> compiler correctly implements A := A * I; where I is an Integer, or A := 
> B + C; where all three are of the same fixed-point type, then I and most 
> other fixed-point users won't care about those painful cases.  Other 
> than, of course, to note that they exist so that we can avoid them.

But why are the cases you refer to painful? Do they really need to be avoided?

I can certainly see that if a calculation causes a missile to hit someone's 
house (instead of the next door embassy), it might be quite painful for the 
occupants of the house. Are you saying that these cases are capable of 
being sources of nasty accidents, or are you saying that they are merely an 
academic curiosity, of no possible practical consequence? (And I realise 
this may be a slightly unfair question.)

> If you do use the three type multiplication operator, you should check 
> whether it is an easy or hard case, and avoid the hard cases.  (Any 
> conversion where the target type is the same as one of the multiplicand 
> types counts as easy, since it can be done with a single division.)

Would you please provide an example, to illustrate this point.

> I'm not trying to scare anyone here.  In fact one of the differences 
> between Ada 83 and Ada 95 is that the error bounds on the hard cases 
> were changed to make them easier to implement.  The hard cases do come 
> up, and for example, one of the harder parts of the Euro conversion was 
> to specify rules and error bounds for some of these three type 
> conversions.  (Say from Marks to Kronar, using today's market rates for 
> Marks to Euros and Euros to Kronar.)

I seem to dimly recall you mentioning this before, Robert. Was it in 
comp.lang.ada? I would like to review it on Google, if possible.

-- 
Nick Roberts




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

* Re: Why no 'Floor for fixed point types
  2003-10-27 18:49       ` Randy Brukardt
@ 2003-10-28 18:32         ` Nick Roberts
  2003-10-29 19:29           ` Randy Brukardt
  0 siblings, 1 reply; 22+ messages in thread
From: Nick Roberts @ 2003-10-28 18:32 UTC (permalink / raw)


Randy Brukardt wrote:

> "Nick Roberts" <nick.roberts@acm.org> wrote in message
> news:bnen7p$vjo06$1@ID-25716.news.uni-berlin.de...
> 
>>For a conforming compiler, there should be no rounding issues in the case
>>Scale=1/Tf'Small, the division is a static expression (which should be
>>calculated precisely at compile time), and I would expect the
>>multiplications to be eliminated.
> 
> 
> Not true if Tf is a generic formal type (and this is a common way to
> implement such code). Moreover, if you use a code-sharing compiler such as
> Janus/Ada, it won't be calculated at compile-time, either.

Hmmmm, nasty. Is this (the non-staticness of things in generics) something 
that is likely to be addressed in the next revision, Randy? Do you think 
fixed point types should have a Floor attribute?

-- 
Nick Roberts




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

* Re: Why no 'Floor for fixed point types
  2003-10-28 18:23             ` Nick Roberts
@ 2003-10-28 18:34               ` Stephane Richard
  2003-10-29 19:26               ` Randy Brukardt
  1 sibling, 0 replies; 22+ messages in thread
From: Stephane Richard @ 2003-10-28 18:34 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3265 bytes --]

In the worlds of our common savior <- .oO( Yeah Right!!! ) Bill
Gates...hehehe....if nobody cares, it's a bug...if everyone cares, it's a
feature..;-)

-- 
St�phane Richard
"Ada World" Webmaster
http://www.adaworld.com


"Nick Roberts" <nick.roberts@acm.org> wrote in message
news:bnmc74$137bsk$1@ID-25716.news.uni-berlin.de...
> Robert I. Eachus wrote:
>
> > ...  Trying to test even a small
> > subset of all possible reasonable values of 'Small and fixed-point
> > numbers just isn't reasonably possible without trillions of machines
> > crunching for millions of years.   So your compiler probably has
> > millions of errors in the low order bit that are just not practical to
> > find, and of no real interest to anyone anyway.
>
> So possibly a question we should ask is "If nobody cares, does it count as
> an error (or bug)?" I admit, there might be a few Intel customers who'd
> like to know the answer to that one. :-)
>
> > From experience with
> > fixed-point, the tough cases are of the form A := Fixed(B*C); where B
> > and C are of two other types than Fixed, and there is no easy
> > representation of Fixed'Small/(B_type'Small * C_type'Small).
>
> What do you mean when you say these are tough cases? The RM95 essentially
> says that the result is either of the representable values (of the type
> Fixed here) which bound the precise result.
>
> > In practice those cases are of little or no interest to anyone.  If your
> > compiler correctly implements A := A * I; where I is an Integer, or A :=
> > B + C; where all three are of the same fixed-point type, then I and most
> > other fixed-point users won't care about those painful cases.  Other
> > than, of course, to note that they exist so that we can avoid them.
>
> But why are the cases you refer to painful? Do they really need to be
avoided?
>
> I can certainly see that if a calculation causes a missile to hit
someone's
> house (instead of the next door embassy), it might be quite painful for
the
> occupants of the house. Are you saying that these cases are capable of
> being sources of nasty accidents, or are you saying that they are merely
an
> academic curiosity, of no possible practical consequence? (And I realise
> this may be a slightly unfair question.)
>
> > If you do use the three type multiplication operator, you should check
> > whether it is an easy or hard case, and avoid the hard cases.  (Any
> > conversion where the target type is the same as one of the multiplicand
> > types counts as easy, since it can be done with a single division.)
>
> Would you please provide an example, to illustrate this point.
>
> > I'm not trying to scare anyone here.  In fact one of the differences
> > between Ada 83 and Ada 95 is that the error bounds on the hard cases
> > were changed to make them easier to implement.  The hard cases do come
> > up, and for example, one of the harder parts of the Euro conversion was
> > to specify rules and error bounds for some of these three type
> > conversions.  (Say from Marks to Kronar, using today's market rates for
> > Marks to Euros and Euros to Kronar.)
>
> I seem to dimly recall you mentioning this before, Robert. Was it in
> comp.lang.ada? I would like to review it on Google, if possible.
>
> -- 
> Nick Roberts
>





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

* Re: Why no 'Floor for fixed point types
  2003-10-28 18:23             ` Nick Roberts
  2003-10-28 18:34               ` Stephane Richard
@ 2003-10-29 19:26               ` Randy Brukardt
  2003-10-30  4:55                 ` Robert I. Eachus
  1 sibling, 1 reply; 22+ messages in thread
From: Randy Brukardt @ 2003-10-29 19:26 UTC (permalink / raw)


"Nick Roberts" <nick.roberts@acm.org> wrote in message
news:bnmc74$137bsk$1@ID-25716.news.uni-berlin.de...
> Robert I. Eachus wrote:
>
> > ...  Trying to test even a small
> > subset of all possible reasonable values of 'Small and fixed-point
> > numbers just isn't reasonably possible without trillions of machines
> > crunching for millions of years.   So your compiler probably has
> > millions of errors in the low order bit that are just not practical to
> > find, and of no real interest to anyone anyway.
>
> So possibly a question we should ask is "If nobody cares, does it count as
> an error (or bug)?" I admit, there might be a few Intel customers who'd
> like to know the answer to that one. :-)

This is wrong (which was my original point). Ada requires such results to be
members of the "close result set", which is implementation-defined. Thus,
the only way for there to be actual "errors" or "bugs" in these result is if
we've defined that set incorrectly (implementation-defined stuff is supposed
to be documented). Of course, if it is proved that we've done that wrong,
it's highly unlikely that we'd change the compiler; just the documentation.
So in practice it means that such results have whatever accuracy the
compiler writer can easily support.

> > From experience with
> > fixed-point, the tough cases are of the form A := Fixed(B*C); where B
> > and C are of two other types than Fixed, and there is no easy
> > representation of Fixed'Small/(B_type'Small * C_type'Small).
>
> What do you mean when you say these are tough cases? The RM95 essentially
> says that the result is either of the representable values (of the type
> Fixed here) which bound the precise result.

Read G.2.3 to see what the RM says about the accuracy of fixed point. In
particular, read about the 'perfect result set' and the 'close result set'.
If you care about accuracy, you need to avoid operations which only require
a result in the 'close result set', because those are cases that the
compiler is allowed to be inaccurate.

                    Randy.






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

* Re: Why no 'Floor for fixed point types
  2003-10-28 18:32         ` Nick Roberts
@ 2003-10-29 19:29           ` Randy Brukardt
  2003-10-30 23:41             ` Nick Roberts
  0 siblings, 1 reply; 22+ messages in thread
From: Randy Brukardt @ 2003-10-29 19:29 UTC (permalink / raw)


"Nick Roberts" <nick.roberts@acm.org> wrote in message
news:bnmcoj$12vsv7$1@ID-25716.news.uni-berlin.de...
> > Not true if Tf is a generic formal type (and this is a common way to
> > implement such code). Moreover, if you use a code-sharing compiler such
as
> > Janus/Ada, it won't be calculated at compile-time, either.
>
> Hmmmm, nasty. Is this (the non-staticness of things in generics) something
> that is likely to be addressed in the next revision, Randy?

I hope not, or I'll be out of the compiler business. (Redoing all of the
generic support in Janus/Ada is out of the question.)

> Do you think fixed point types should have a Floor attribute?

The original answer to this showed that for some fixed point types, it
wouldn't be possible to implement it accurately. Thus, it is much better to
show what you are doing via a conversion to an appropriate float type.
Hopefully the compiler can note the easy cases and eliminate the float
operations.

                    Randy.






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

* Re: Why no 'Floor for fixed point types
  2003-10-29 19:26               ` Randy Brukardt
@ 2003-10-30  4:55                 ` Robert I. Eachus
  0 siblings, 0 replies; 22+ messages in thread
From: Robert I. Eachus @ 2003-10-30  4:55 UTC (permalink / raw)


Randy Brukardt wrote:

 > Read G.2.3 to see what the RM says about the accuracy of fixed point.
 > In particular, read about the 'perfect result set' and the 'close
 > result set'. If you care about accuracy, you need to avoid operations
 > which only require a result in the 'close result set', because those
 > are cases that the compiler is allowed to be inaccurate.

Actually, there are cases that are allowed to use the close result set
that no compiler goes out of their way to get inaccurate results on. 
But whether you limit yourself to the perfect result set, or are willing 
to accept some well-behaved cases in the close result set.  My real 
point is that there are some pathological cases which no one cares 
about, and I doubt that any compiler does a perfect job of documenting.

But that is fine with me.  As I said, if you care, you check and for the 
compiler vendors to try and understand what code the compiler will 
generate in 2**93 cases (assuming only three 31-bit 'Smalls) is not 
something that I would want any compiler vendor to waste time on.

In any case, the wierd/pathological whatever term you want to use cases 
are just not that usual.  In the usual cases 1.0/fixed_type'Small is an 
integer for all three operands and A'Small/(B'Small * C'Small) is an 
integer as well.

Of course, I am one of those nasty people who goes around doing things 
like measuring angles in microradians--and declaring a fixed point type 
with a 'Small to match.  Technically, as declared 'Small is a rational 
number (2*Pi/1_000_000.0) since Ada.Numerics.Pi is only declared to 50 
decimal places...

But since 'Small is static, it is usally easy to see if the compiler did 
a good job of eliminating common factors to simplify the job. 
Incidently back in Ada 83 days Paul Hilfinger and I went round and 
around on when 2*actual precision or 3*actual precision was needed.  I 
have implementation notes somewhere and Paul actually published a couple 
of papers.  These are the calculations that the Ada 95 rules allow to be 
done using the close result set, and I think you can see that there are 
a few (as I said very pathological) cases where getting even close is 
difficult.

I even have a program lying around with painful test cases.  I never 
distributed it, because I was afraid it would end up in the ACVC/ACATS 
test.  Remember the reason I was interested in these cases were entirely 
from a computational perspective.  And if I don't care if compilers do 
them well, I don't see why anyone else should.  (In one case I used two 
different power series expansions for Pi that agree to several thousand 
decimal places.  And yes, they are written as universal integer 
expressions, so the compiler has to expand them exactly at compile time. 
    I always thought it was funny when new computers would be used to 
compute a million digits of Pi or so.  In Ada those programs are so fast 
they start printing the answer immediately. ;-)

-- 
                                         Robert I. Eachus

"Quality is the Buddha. Quality is scientific reality. Quality is the
goal of Art. It remains to work these concepts into a practical,
down-to-earth context, and for this there is nothing more practical or
down-to-earth than what I have been talking about all along...the repair
of an old motorcycle."  -- from Zen and the Art of Motorcycle
Maintenance by Robert Pirsig




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

* Re: Why no 'Floor for fixed point types
  2003-10-29 19:29           ` Randy Brukardt
@ 2003-10-30 23:41             ` Nick Roberts
  2003-10-31 22:25               ` Randy Brukardt
  0 siblings, 1 reply; 22+ messages in thread
From: Nick Roberts @ 2003-10-30 23:41 UTC (permalink / raw)


Randy Brukardt wrote:

>>Do you think fixed point types should have a Floor attribute?
> 
> The original answer to this showed that for some fixed point types, it
> wouldn't be possible to implement it accurately. Thus, it is much better to
> show what you are doing via a conversion to an appropriate float type.
> Hopefully the compiler can note the easy cases and eliminate the float
> operations.

To my mind, I would not expect this form of optimisation in any compiler.

Would it not be reasonable to provide 'Floor for fixed-point types which 
fulfil certain conditions?

For example, it might be required that the delta be less than 1.0 (and that 
the range includes at least one integer). Alternatively, it might be 
required that the delta is precisely 1.0 (with conditions on the range).

These conditions might be imposed statically (erroneous) or dynamically 
(raising an exception). I suppose the dynamic option would fit easier with 
the possibility of the fixed point type being a generic formal.

After all, if Float'Floor(Float(X)) is going to produce a silly result 
(without itself raising Constraint_Error), what's wrong with 
Some_Fixed'Floor(X) raising Constraint_Error? Surely that would actually be 
better?

-- 
Nick Roberts




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

* Re: Why no 'Floor for fixed point types
  2003-10-30 23:41             ` Nick Roberts
@ 2003-10-31 22:25               ` Randy Brukardt
  2003-11-06  2:41                 ` Nick Roberts
  0 siblings, 1 reply; 22+ messages in thread
From: Randy Brukardt @ 2003-10-31 22:25 UTC (permalink / raw)


"Nick Roberts" <nick.roberts@acm.org> wrote in message
news:bns7j9$15h0a9$1@ID-25716.news.uni-berlin.de...
> Randy Brukardt wrote:
>
> >>Do you think fixed point types should have a Floor attribute?
> >
> > The original answer to this showed that for some fixed point types, it
> > wouldn't be possible to implement it accurately. Thus, it is much better
to
> > show what you are doing via a conversion to an appropriate float type.
> > Hopefully the compiler can note the easy cases and eliminate the float
> > operations.
>
> To my mind, I would not expect this form of optimisation in any compiler.

Why not? If a coding style is common, compiler writers will go out their way
to optimize it. Particularly if there are customers who care. It's the same
reason that we don't need Float => Integer rounding attributes -- compilers
can and should optimize the case of the attribute surrounded by the type
conversion.

> Would it not be reasonable to provide 'Floor for fixed-point types which
> fulfil certain conditions?
>
> For example, it might be required that the delta be less than 1.0 (and
that
> the range includes at least one integer). Alternatively, it might be
> required that the delta is precisely 1.0 (with conditions on the range).

To make sense, the 'Small (the delta is irrelevant) would have to be 1/<some
integer>. The default powers of 2 and 10 would work, but not Eachus's
PI/2000.

> These conditions might be imposed statically (erroneous) or dynamically
> (raising an exception). I suppose the dynamic option would fit easier with
> the possibility of the fixed point type being a generic formal.

Yes, it couldn't be a legality check - that would be a "generic contract
model violation". Typically, that's how otherwise good ideas get shot down -
by someone saying "contract model violation".

And it would be weird for this to be a dynamic check. The problem, after
all, is one of accuracy, not that the operation doesn't make sense
mathematically. If 'floor worked like the mixed multiply, it would OK, but
that seems like overkill for a minor problem.

> After all, if Float'Floor(Float(X)) is going to produce a silly result
> (without itself raising Constraint_Error), what's wrong with
> Some_Fixed'Floor(X) raising Constraint_Error? Surely that would actually
be
> better?

But Float'Floor(Float(X)) *will* produce a reasonable result. The problem is
that it may not be possible to represent that result as a value of
Some_Fixed (if the type doesn't have integer values). Producing one of the
"nearby" model numbers [the normal handling of accuracy issues] wouldn't
make sense for this function (if you ask for an integer value, getting
3.14159 would be surprising).

                 Randy.







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

* Re: Why no 'Floor for fixed point types
  2003-10-31 22:25               ` Randy Brukardt
@ 2003-11-06  2:41                 ` Nick Roberts
  0 siblings, 0 replies; 22+ messages in thread
From: Nick Roberts @ 2003-11-06  2:41 UTC (permalink / raw)


Randy Brukardt wrote:

>>>>Do you think fixed point types should have a Floor attribute?
>>>
>>>The original answer to this showed that for some fixed point types,
 >>>it wouldn't be possible to implement it accurately. Thus, it is much
 >>>better to show what you are doing via a conversion to an appropriate
 >>>float type. Hopefully the compiler can note the easy cases and
 >>>eliminate the float operations.
>>
>>To my mind, I would not expect this form of optimisation in any compiler.
> 
> Why not? If a coding style is common, compiler writers will go out
 > their way to optimize it. Particularly if there are customers who
 > care. It's the same reason that we don't need Float => Integer rounding
 > attributes -- compilers can and should optimize the case of the
 > attribute surrounded by the type conversion.

I've never seen or heard of it. But I don't know how broad my experience is 
of these things. I don't doubt that it /could/ be done.

>>Would it not be reasonable to provide 'Floor for fixed-point types which
>>fulfil certain conditions?
>>
>>For example, it might be required that the delta be less than 1.0 (and
>>that the range includes at least one integer). Alternatively, it might
 >>be required that the delta is precisely 1.0 (with conditions on the
 >>range).
> 
> To make sense, the 'Small (the delta is irrelevant) would have to be
 > 1/<some integer>. The default powers of 2 and 10 would work, but not
 > Eachus's PI/2000.

Actually, I think, to really make sense, both 'Delta and 'Small would have 
to be exactly 1.0, and the range ought to be required to be non-null and of 
two integral values not equal to each other.

>>These conditions might be imposed statically (erroneous) or dynamically
>>(raising an exception). I suppose the dynamic option would fit easier with
>>the possibility of the fixed point type being a generic formal.
> 
> Yes, it couldn't be a legality check - that would be a "generic contract
> model violation". Typically, that's how otherwise good ideas get shot down -
> by someone saying "contract model violation".
> 
> And it would be weird for this to be a dynamic check. The problem, after
> all, is one of accuracy, not that the operation doesn't make sense
> mathematically. If 'floor worked like the mixed multiply, it would OK, but
> that seems like overkill for a minor problem.

I think I agree with you here.

>>After all, if Float'Floor(Float(X)) is going to produce a silly result
>>(without itself raising Constraint_Error), what's wrong with
>>Some_Fixed'Floor(X) raising Constraint_Error? Surely that would actually
>>be better?
> 
> But Float'Floor(Float(X)) *will* produce a reasonable result. The problem
 > is that it may not be possible to represent that result as a value of
> Some_Fixed (if the type doesn't have integer values).

I disagree that the result would be reasonable. If we had:

    type Measured_Weight is delta 0.02 range 0.20 .. 0.80;
    W: Measured_Weight;

then of course Float'Floor(Float(W)) would be certain to produce 0.0 
regardless of the (valid) value of W. In these kinds of case, it just 
doesn't make sense to find the floor of W at all. Trying to do so would 
indicate a programming error, and it would be better for it to produce an 
error (preferably at compile time, but better an error when executed than 
just blithely carrying on).

 > Producing one of the "nearby" model numbers [the normal handling of
 > accuracy issues] wouldn't make sense for this function (if you ask
 > for an integer value, getting 3.14159 would be surprising).

I agree!

Perhaps in the case of the above example the programmer may have meant (or 
would have decided, having thought harder) to have found 
Float'Floor(Float(W)*1000) and displayed the resulting three digits (maybe 
on a 7-segment display). This thought suggests to me that you are 
essentially right, Randy. To my mind, it makes sense to convert to Float if 
one is then going to scale by some orders of magnitude before calculating a 
floor.

I don't think it is likely to be a (sensible) requirement for a compiler to 
optimise an expression such as Integer(Float'Floor(Float(W)*1000)) to 
eliminate the actual conversion to (and from) a floating point 
representation in these kinds of cases, because I doubt that they would be 
at all speed-critical.

I'm not really sure of all the practical uses of calculating the floor of a 
number. Can you think of any realistic situation where the speed of a 
Integer(Float'Floor(Float(...)) expression would be that important?

In fact, could the same be said of Integer(Float'Rounding(...)) expressions?

-- 
Nick Roberts




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

end of thread, other threads:[~2003-11-06  2:41 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-10-23 20:09 Why no 'Floor for fixed point types Duncan Sands
2003-10-23 22:06 ` Robert I. Eachus
2003-10-24 16:00   ` Stephen Leake
2003-10-24 18:13     ` Duncan Sands
2003-10-23 23:10 ` Martin Dowie
2003-10-24 21:46 ` Nick Roberts
2003-10-25  4:29   ` Robert I. Eachus
2003-10-25 20:42     ` Nick Roberts
2003-10-25 22:40       ` Robert I. Eachus
2003-10-27 18:59         ` Randy Brukardt
2003-10-28  1:19           ` Robert I. Eachus
2003-10-28 18:23             ` Nick Roberts
2003-10-28 18:34               ` Stephane Richard
2003-10-29 19:26               ` Randy Brukardt
2003-10-30  4:55                 ` Robert I. Eachus
2003-10-28 18:10         ` Nick Roberts
2003-10-27 18:49       ` Randy Brukardt
2003-10-28 18:32         ` Nick Roberts
2003-10-29 19:29           ` Randy Brukardt
2003-10-30 23:41             ` Nick Roberts
2003-10-31 22:25               ` Randy Brukardt
2003-11-06  2:41                 ` Nick Roberts

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