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.
prev parent 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