comp.lang.ada
 help / color / mirror / Atom feed
* Truncating a fixed-point value
@ 2010-07-09 19:06 Adam Beneschan
  2010-07-09 20:34 ` Simon Wright
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Adam Beneschan @ 2010-07-09 19:06 UTC (permalink / raw)


I must be suffering from an embarrassing mental block, because I'm
sure there's a simple solution, but I can't see what it is.

I have a value X of a fixed-point type, X >= 0.0, and I need to
compute Floor(X) as an Integer.  'Truncation and 'Floor aren't defined
for fixed-point types; the type conversion Integer(X) rounds; and
Integer(X-0.5) fails if X=0.0.

How do others do this?  Or do I have to resort to an IF statement (or
conditional expression in Ada 2012) to handle the different cases?

               -- Adam



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

* Re: Truncating a fixed-point value
  2010-07-09 19:06 Truncating a fixed-point value Adam Beneschan
@ 2010-07-09 20:34 ` Simon Wright
  2010-07-09 23:21   ` Adam Beneschan
  2010-07-09 20:39 ` Gene
  2010-07-09 22:58 ` Shark8
  2 siblings, 1 reply; 11+ messages in thread
From: Simon Wright @ 2010-07-09 20:34 UTC (permalink / raw)


Adam Beneschan <adam@irvine.com> writes:

> I must be suffering from an embarrassing mental block, because I'm
> sure there's a simple solution, but I can't see what it is.
>
> I have a value X of a fixed-point type, X >= 0.0, and I need to
> compute Floor(X) as an Integer.  'Truncation and 'Floor aren't defined
> for fixed-point types; the type conversion Integer(X) rounds; and
> Integer(X-0.5) fails if X=0.0.
>
> How do others do this?  Or do I have to resort to an IF statement (or
> conditional expression in Ada 2012) to handle the different cases?

Looks as though Integer(X+0.5)-1 might do the trick ..



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

* Re: Truncating a fixed-point value
  2010-07-09 19:06 Truncating a fixed-point value Adam Beneschan
  2010-07-09 20:34 ` Simon Wright
@ 2010-07-09 20:39 ` Gene
  2010-07-09 21:20   ` Jeffrey R. Carter
  2010-07-09 21:52   ` Adam Beneschan
  2010-07-09 22:58 ` Shark8
  2 siblings, 2 replies; 11+ messages in thread
From: Gene @ 2010-07-09 20:39 UTC (permalink / raw)


On Jul 9, 3:06 pm, Adam Beneschan <a...@irvine.com> wrote:
> I must be suffering from an embarrassing mental block, because I'm
> sure there's a simple solution, but I can't see what it is.
>
> I have a value X of a fixed-point type, X >= 0.0, and I need to
> compute Floor(X) as an Integer.  'Truncation and 'Floor aren't defined
> for fixed-point types; the type conversion Integer(X) rounds; and
> Integer(X-0.5) fails if X=0.0.
>
> How do others do this?  Or do I have to resort to an IF statement (or
> conditional expression in Ada 2012) to handle the different cases?
>
>                -- Adam

There is a prior discussion of this question:

http://coding.derkeiler.com/Archive/Ada/comp.lang.ada/2003-10/0729.html

The problem is that fixed point types don't have to include all the
integers.

An ugly approach is to convert to e.g. a long float, take the floor,
and convert back.  No doubt others will have something more elegant.



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

* Re: Truncating a fixed-point value
  2010-07-09 20:39 ` Gene
@ 2010-07-09 21:20   ` Jeffrey R. Carter
  2010-07-09 21:52   ` Adam Beneschan
  1 sibling, 0 replies; 11+ messages in thread
From: Jeffrey R. Carter @ 2010-07-09 21:20 UTC (permalink / raw)


On 07/09/2010 01:39 PM, Gene wrote:
>
> An ugly approach is to convert to e.g. a long float, take the floor,
> and convert back.  No doubt others will have something more elegant.

That's the approach I use, though, in the interest of portability, I declare my 
own floating-point type for the purpose:

function Floor (Value : in Fixed) return Integer is
    type Big is digits System.Max_Digits;
begin -- Floor
    return Integer (Big'Floor (Big (Value) ) );
end Floor;

-- 
Jeff Carter
"It's symbolic of his struggle against reality."
Monty Python's Life of Brian
78



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

* Re: Truncating a fixed-point value
  2010-07-09 20:39 ` Gene
  2010-07-09 21:20   ` Jeffrey R. Carter
@ 2010-07-09 21:52   ` Adam Beneschan
  2010-07-13 11:26     ` Jacob Sparre Andersen
  1 sibling, 1 reply; 11+ messages in thread
From: Adam Beneschan @ 2010-07-09 21:52 UTC (permalink / raw)


On Jul 9, 1:39 pm, Gene <gene.ress...@gmail.com> wrote:
> On Jul 9, 3:06 pm, Adam Beneschan <a...@irvine.com> wrote:
>
> > I must be suffering from an embarrassing mental block, because I'm
> > sure there's a simple solution, but I can't see what it is.
>
> > I have a value X of a fixed-point type, X >= 0.0, and I need to
> > compute Floor(X) as an Integer.  'Truncation and 'Floor aren't defined
> > for fixed-point types; the type conversion Integer(X) rounds; and
> > Integer(X-0.5) fails if X=0.0.
>
> > How do others do this?  Or do I have to resort to an IF statement (or
> > conditional expression in Ada 2012) to handle the different cases?
>
> >                -- Adam
>
> There is a prior discussion of this question:
>
> http://coding.derkeiler.com/Archive/Ada/comp.lang.ada/2003-10/0729.html

Thanks for the link.  I was aware of AI95-60 but I hadn't been aware
that the problem had been brought up again.


> The problem is that fixed point types don't have to include all the
> integers.

Ah, I see.  This is a problem because 'Truncation and 'Floor are
defined to return the same fixed-point type.  It seems to me that the
language could use a way to do the truncation (or floor) and return an
integer, without having to worry about an intermediate result of the
same fixed-point type (which might not be a possible value of the
type).  I think someone mentioned that in the thread, but mentioned
that it would probably have to be generic.


> An ugly approach is to convert to e.g. a long float, take the floor,
> and convert back.  No doubt others will have something more elegant.

That will probably work for my purpose; but in general, it's easy to
define a fixed-point number with a 'Small of 2**(-N) that has more
bits to the right of the binary point than are available in the
mantissa part of the floating-point.  If that's the case, this
approach will fail on certain values (probably M - (K * T'Small) for
integer M and suitably small integer K).  Since this situation lends
itself to really efficient code (basically just a bit shift), it's
kind of a shame that the language doesn't give you a good way to do
this.

                           -- Adam




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

* Re: Truncating a fixed-point value
  2010-07-09 19:06 Truncating a fixed-point value Adam Beneschan
  2010-07-09 20:34 ` Simon Wright
  2010-07-09 20:39 ` Gene
@ 2010-07-09 22:58 ` Shark8
  2 siblings, 0 replies; 11+ messages in thread
From: Shark8 @ 2010-07-09 22:58 UTC (permalink / raw)


On Jul 9, 1:06 pm, Adam Beneschan <a...@irvine.com> wrote:
> I must be suffering from an embarrassing mental block, because I'm
> sure there's a simple solution, but I can't see what it is.
>
> I have a value X of a fixed-point type, X >= 0.0, and I need to
> compute Floor(X) as an Integer.  'Truncation and 'Floor aren't defined
> for fixed-point types; the type conversion Integer(X) rounds; and
> Integer(X-0.5) fails if X=0.0.
>
> How do others do this?  Or do I have to resort to an IF statement (or
> conditional expression in Ada 2012) to handle the different cases?
>
>                -- Adam

I'd think that 1-Integer(X+0.5) would work... wouldn't it?



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

* Re: Truncating a fixed-point value
  2010-07-09 20:34 ` Simon Wright
@ 2010-07-09 23:21   ` Adam Beneschan
  2010-07-10  3:13     ` Gene
  2010-07-10  8:12     ` Simon Wright
  0 siblings, 2 replies; 11+ messages in thread
From: Adam Beneschan @ 2010-07-09 23:21 UTC (permalink / raw)


On Jul 9, 1:34 pm, Simon Wright <si...@pushface.org> wrote:
> Adam Beneschan <a...@irvine.com> writes:
> > I must be suffering from an embarrassing mental block, because I'm
> > sure there's a simple solution, but I can't see what it is.
>
> > I have a value X of a fixed-point type, X >= 0.0, and I need to
> > compute Floor(X) as an Integer.  'Truncation and 'Floor aren't defined
> > for fixed-point types; the type conversion Integer(X) rounds; and
> > Integer(X-0.5) fails if X=0.0.
>
> > How do others do this?  Or do I have to resort to an IF statement (or
> > conditional expression in Ada 2012) to handle the different cases?
>
> Looks as though Integer(X+0.5)-1 might do the trick ..

Yes, it looks like it, as long as X >= 0.0 and 0.5 is a model number
of the fixed-point type (I think I'm using the right term).  Those
conditions do hold for the code I need it for.  It isn't useful for
negative numbers---it yields -2 if X=-1.0, which is not useful whether
you want a truncation or a floor operation---but I did stipulate
nonnegative X in my original question.

                         -- Adam





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

* Re: Truncating a fixed-point value
  2010-07-09 23:21   ` Adam Beneschan
@ 2010-07-10  3:13     ` Gene
  2010-07-11 19:43       ` Gene
  2010-07-10  8:12     ` Simon Wright
  1 sibling, 1 reply; 11+ messages in thread
From: Gene @ 2010-07-10  3:13 UTC (permalink / raw)


On Jul 9, 7:21 pm, Adam Beneschan <a...@irvine.com> wrote:
> On Jul 9, 1:34 pm, Simon Wright <si...@pushface.org> wrote:
>
> > Adam Beneschan <a...@irvine.com> writes:
> > > I must be suffering from an embarrassing mental block, because I'm
> > > sure there's a simple solution, but I can't see what it is.
>
> > > I have a value X of a fixed-point type, X >= 0.0, and I need to
> > > compute Floor(X) as an Integer.  'Truncation and 'Floor aren't defined
> > > for fixed-point types; the type conversion Integer(X) rounds; and
> > > Integer(X-0.5) fails if X=0.0.
>
> > > How do others do this?  Or do I have to resort to an IF statement (or
> > > conditional expression in Ada 2012) to handle the different cases?
>
> > Looks as though Integer(X+0.5)-1 might do the trick ..
>
> Yes, it looks like it, as long as X >= 0.0 and 0.5 is a model number
> of the fixed-point type (I think I'm using the right term).  Those
> conditions do hold for the code I need it for.  It isn't useful for
> negative numbers---it yields -2 if X=-1.0, which is not useful whether
> you want a truncation or a floor operation---but I did stipulate
> nonnegative X in my original question.
>
>                          -- Adam

Shouldn't there be a way to convert a fixed point type to a
corresponding modular or integer type with one integer value per
floating point value, use rem to compute a floor, and convert back?




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

* Re: Truncating a fixed-point value
  2010-07-09 23:21   ` Adam Beneschan
  2010-07-10  3:13     ` Gene
@ 2010-07-10  8:12     ` Simon Wright
  1 sibling, 0 replies; 11+ messages in thread
From: Simon Wright @ 2010-07-10  8:12 UTC (permalink / raw)


Adam Beneschan <adam@irvine.com> writes:

> On Jul 9, 1:34 pm, Simon Wright <si...@pushface.org> wrote:
>> Adam Beneschan <a...@irvine.com> writes:
>> > I must be suffering from an embarrassing mental block, because I'm
>> > sure there's a simple solution, but I can't see what it is.
>>
>> > I have a value X of a fixed-point type, X >= 0.0, and I need to
>> > compute Floor(X) as an Integer.  'Truncation and 'Floor aren't defined
>> > for fixed-point types; the type conversion Integer(X) rounds; and
>> > Integer(X-0.5) fails if X=0.0.
>>
>> > How do others do this?  Or do I have to resort to an IF statement (or
>> > conditional expression in Ada 2012) to handle the different cases?
>>
>> Looks as though Integer(X+0.5)-1 might do the trick ..
>
> Yes, it looks like it, as long as X >= 0.0 and 0.5 is a model number
> of the fixed-point type (I think I'm using the right term).  Those
> conditions do hold for the code I need it for.  It isn't useful for
> negative numbers---it yields -2 if X=-1.0, which is not useful whether
> you want a truncation or a floor operation---but I did stipulate
> nonnegative X in my original question.

I hadn't considered the model number aspect, but nonnegative X is
indeed necessary for this solution!



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

* Re: Truncating a fixed-point value
  2010-07-10  3:13     ` Gene
@ 2010-07-11 19:43       ` Gene
  0 siblings, 0 replies; 11+ messages in thread
From: Gene @ 2010-07-11 19:43 UTC (permalink / raw)


On Jul 9, 11:13 pm, Gene <gene.ress...@gmail.com> wrote:
> On Jul 9, 7:21 pm, Adam Beneschan <a...@irvine.com> wrote:
>
>
>
>
>
> > On Jul 9, 1:34 pm, Simon Wright <si...@pushface.org> wrote:
>
> > > Adam Beneschan <a...@irvine.com> writes:
> > > > I must be suffering from an embarrassing mental block, because I'm
> > > > sure there's a simple solution, but I can't see what it is.
>
> > > > I have a value X of a fixed-point type, X >= 0.0, and I need to
> > > > compute Floor(X) as an Integer.  'Truncation and 'Floor aren't defined
> > > > for fixed-point types; the type conversion Integer(X) rounds; and
> > > > Integer(X-0.5) fails if X=0.0.
>
> > > > How do others do this?  Or do I have to resort to an IF statement (or
> > > > conditional expression in Ada 2012) to handle the different cases?
>
> > > Looks as though Integer(X+0.5)-1 might do the trick ..
>
> > Yes, it looks like it, as long as X >= 0.0 and 0.5 is a model number
> > of the fixed-point type (I think I'm using the right term).  Those
> > conditions do hold for the code I need it for.  It isn't useful for
> > negative numbers---it yields -2 if X=-1.0, which is not useful whether
> > you want a truncation or a floor operation---but I did stipulate
> > nonnegative X in my original question.
>
> >                          -- Adam
>
> Shouldn't there be a way to convert a fixed point type to a
> corresponding modular or integer type with one integer value per
> floating point value, use rem to compute a floor, and convert back?- Hide quoted text -

I'll try to answer my own question.  Here is an attempt that works for
a variety of fixed point types.  I'm no expert on fixed point. Perhaps
I've embedded some non-portable assumptions. With optimizations turned
up and range checks off, the Floor function inlines as the 3 (x86)
instructions you'd expect (subtract, "and" with mask, add) using GPL
2007.

with Ada.Text_IO; use Ada.Text_IO;

procedure FPF is

  type FP is delta 0.125 range -10.0 .. 50.0;

  function Floor(X : FP) return FP is
    Delta_Inv : constant := 1.0 / FP'Delta;
    type Bits is mod 2 ** 32;
    type FP_Bits is delta 1.0 range 0.0 .. (FP'Last - FP'First) *
Delta_Inv;
    Ordinal : constant Bits := Bits((X - FP'First) * Delta_Inv) and
not(Bits(Delta_Inv) - 1);
  begin
    return FP'Base(FP_Bits(Ordinal) * FP'Delta) + FP'First;
  end;

  X : FP := FP'First;
begin
  loop
    Put_Line(FP'Image(X) & " -> " & FP'Image(Floor(X)));
    exit when X = FP'Last;
    X := X + FP'Delta;
  end loop;
end;



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

* Re: Truncating a fixed-point value
  2010-07-09 21:52   ` Adam Beneschan
@ 2010-07-13 11:26     ` Jacob Sparre Andersen
  0 siblings, 0 replies; 11+ messages in thread
From: Jacob Sparre Andersen @ 2010-07-13 11:26 UTC (permalink / raw)


Adam Beneschan wrote:

> That will probably work for my purpose; but in general, it's easy to
> define a fixed-point number with a 'Small of 2**(-N) that has more
> bits to the right of the binary point than are available in the
> mantissa part of the floating-point.  If that's the case, this
> approach will fail on certain values (probably M - (K * T'Small) for
> integer M and suitably small integer K).  Since this situation lends
> itself to really efficient code (basically just a bit shift), it's
> kind of a shame that the language doesn't give you a good way to do
> this.

Isn't it possible to write a truncation function, which uses bit shift
when it is appropriate?  If the 'Small is statically known, there is a
fair chance that the compiler will remove the unused branch at
compile-time.

Jacob
-- 
"If we weren't at least occasionally surprised by the results,
 we might as well save ourselves the trouble of measuring :)"



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

end of thread, other threads:[~2010-07-13 11:26 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-07-09 19:06 Truncating a fixed-point value Adam Beneschan
2010-07-09 20:34 ` Simon Wright
2010-07-09 23:21   ` Adam Beneschan
2010-07-10  3:13     ` Gene
2010-07-11 19:43       ` Gene
2010-07-10  8:12     ` Simon Wright
2010-07-09 20:39 ` Gene
2010-07-09 21:20   ` Jeffrey R. Carter
2010-07-09 21:52   ` Adam Beneschan
2010-07-13 11:26     ` Jacob Sparre Andersen
2010-07-09 22:58 ` Shark8

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