comp.lang.ada
 help / color / mirror / Atom feed
From: Syntax Issues <syntax.issues@gmail.com>
Subject: Re: Help with low level Ada
Date: Thu, 17 Mar 2011 12:30:02 -0700 (PDT)
Date: 2011-03-17T12:30:02-07:00	[thread overview]
Message-ID: <4506bb69-86ce-419f-af61-f573f311675a@j35g2000prb.googlegroups.com> (raw)
In-Reply-To: iltid5$nc8$1@tornado.tornevall.net

On Mar 17, 1:55 pm, Jeffrey Carter
<spam.jrcarter....@spam.not.acm.org> wrote:
> On 03/17/2011 07:31 AM, Syntax Issues wrote:
>
>
>
>
>
>
>
>
>
> > unsigned ColorNormalize (vec3_t rgb){
> >    unsigned        c;
> >    float           max;
> >    ...
> >    ((byte *)&c)[0] = rgb[0] * max;
> >    ((byte *)&c)[1] = rgb[1] * max;
> >    ((byte *)&c)[2] = rgb[2] * max;
> >    ((byte *)&c)[3] = 255;
> >    return c;
> > }
> > function Normalize
> >    (Red_Green_Blue : in Vector_Color)
> >    return Integer_Color
> >    is
> >    Result  : Integer_Color := 0;
> >    Maximum : Float_4       := 0.0;
> >    begin
> >            ...
> >            return
> >                    -- ???!!??!?!? Byte(Red_Green_Blue(1) * Maximum) +
> >                    -- ???!!??!?!? Byte(Red_Green_Blue(2) * Maximum) +
> >                    -- ???!!??!?!? Byte(Red_Green_Blue(3) * Maximum);
> >    end Normalize;
>
> First, I'd probably do something like
>
> type Color_ID is (Red, Blue, Green);
>
> subtype Natural_Float_4 is Float_4 range 0.0 .. Float_4'Last;
>
> type Vector_Color is array (Color_ID) of Natural_Float_4;
>
> so I can say Red_Green_Blue (Red). (I presume that the components of
> Vector_Color cannot be negative; better to make that clear in the code and
> enforced by the language.)
>
> One approach to this is
>
> type Byte is mod 2 ** 8;
>
> type Color_Bytes is record
>     Red    : Byte;
>     Green  : Byte;
>     Blue   : Byte;
>     Unused : Byte;
> end record;
> for Color_Bytes use
>     Red    at 0 range 0 .. 7;
>     Green  at 1 range 0 .. 7;
>     Blue   at 2 range 0 .. 7;
>     Unused at 3 range 0 .. 7;
> end record;
> for Color_Bytes'Size use Integer_Color'Size;
>
> You may need to change the representation clause to get the components in the
> right places.
>
> function Convert is new Ada.Unchecked_Conversion
>     (Source => Color_Bytes, Target => Integer_Color);
>
> Result := Color_Bytes'(Red    => Byte (Red_Green_Blue (Red)    * Maximum),
>                         Green  => Byte (Red_Green_Blue (Green)  * Maximum),
>                         Blue   => Byte (Red_Green_Blue (Blue)   * Maximum),
>                         Unused => Byte'Last);
>
> return Convert (Result);
>
> You missed out the assignment of 255 to the 4th byte.
>
> Another way is to use an array of 4 Bytes that you unchecked convert to the
> result type.
>
> Finally, if you use a modular type from package Interfaces you can shift the
> products into their correct positions and "or" them together. And you can always
> imitate that by multiplying by a power of 2 and adding them together:
>
> Result := Integer_Color (Red_Green_Blue (Red)    * Maximum) * 2 **  0 +
>            Integer_Color (Red_Green_Blue (Green)  * Maximum) * 2 **  8 +
>            Integer_Color (Red_Green_Blue (Blue)   * Maximum) * 2 ** 16 +
>            255 * 2 ** 24;
>
> The compiler will often replace these by shifts.
>
> > float AngleMod (float angle){
> >    return (360.0/65536) * ((int)(angle * (65536/360.0))&  65535);
> > }
> > function Mod_Angle
> >    (Angle : in Float_4)
> >    return Float_4
> >    is
> >    begin
> >            return (360.0 / 65536.0) * (Integer_4_Signed(Angle * (65536.0 /
> > 360.0)) ---???!?!?!&  65535);
> >    end Mod_Angle;
>
> Bitwise "and" is defined for all modular types. The only wrinkle is what happens
> if Angle is negative. If that's not allowed (see Natural_Float_4 above), then
> it's fairly easy:
>
> type Integer_4_Unsigned is mod Integer_4_Signed'Size;
>
> return (360.0 / 65536.0) *
>         Float_4 (Integer_4_Unsigned (Angle * (65536.0 / 360.0) ) and 65535);
>
> Otherwise, you need to do some unchecked converting between signed and modular
> types of the same size:
>
> function Convert is new Ada.Unchecked_Conversion
>     (Source => Integer_4_Signed, Target => Integer_4_Unsigned);
>
> return (360.0 / 65536.0) *
>         Float_4 (Convert (Integer_4_Signed (Angle * (65536.0 / 360.0) ) ) and
>                  65535);
>
> (I presume that Integer_4_Signed is 4 bytes from its name, so the result of
> "and"ing that with 65535 will always be non-negative. In that case, there's no
> need to convert back to signed before converting to Float_4.)
>
> > int NearestPowerOfTwo (int number, qboolean roundDown){
> >    int n = 1;
> >    if (number<= 0)
> >            return 1;
> >    while (n<  number)
> >            n<<= 1;
> >    if (roundDown){
> >            if (n>  number)
> >                    n>>= 1;
> >    }
> >    return n;
> > }
>
> Shift operations are defined for the modular types defined in package
> Interfaces. As mentioned above, the same effect can often be obtained with
> multiplication and division by powers of 2, and the compiler will often replace
> them with shifts:
>
> while N < Number loop
>     N := 2 * N;
> end loop;
>
> if Round_Down and N > Number then
>     N := N / 2;
> end if;
>
> You could also use the Log function from Ada.Numerics.Generic_Elementary_Functions:
>
> type Big is digits 15;
>
> package Math is new Ada.Numerics.Generic_Elementary_Functions
>     (Float_Type => Big);
>
> N := 2 ** Integer (Math.Log (Big (Number), 2.0) );
>
> if N < Number then
>     N := 2 * N;
> end if;
>
> if Round_Down and N > Number then
>     N := N / 2;
> end if;
>
> --
> Jeff Carter
> "We use a large, vibrating egg."
> Annie Hall
> 44

Excellent, I really appreciate the help.



      reply	other threads:[~2011-03-17 19:30 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-17 14:31 Help with low level Ada Syntax Issues
2011-03-17 17:46 ` Shark8
2011-03-17 17:59   ` Jeffrey Carter
2011-03-20  3:45     ` Shark8
2011-03-17 17:55 ` Jeffrey Carter
2011-03-17 19:30   ` Syntax Issues [this message]
replies disabled

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