From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,e0423f8984d47f76 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2003-10-08 19:36:24 PST Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!logbridge.uoregon.edu!nntp-server.caltech.edu!attla2!ip.att.net!attbi_feed3!attbi.com!rwcrnsc53.POSTED!not-for-mail From: "Jeff C," Newsgroups: comp.lang.ada References: Subject: Re: Problems converting Float to Integer efficiently X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2800.1158 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 Message-ID: NNTP-Posting-Host: 66.31.4.164 X-Complaints-To: abuse@comcast.net X-Trace: rwcrnsc53 1065666983 66.31.4.164 (Thu, 09 Oct 2003 02:36:23 GMT) NNTP-Posting-Date: Thu, 09 Oct 2003 02:36:23 GMT Organization: Comcast Online Date: Thu, 09 Oct 2003 02:36:23 GMT Xref: archiver1.google.com comp.lang.ada:512 Date: 2003-10-09T02:36:23+00:00 List-Id: "Dr. Adrian Wrigley" wrote in message news:KD1hb.8538$RU4.82065@newsfep4-glfd.server.ntli.net... > Hi all! > > I have been having problems getting decent code out of GNAT 3.15p (Intel architecture) > > All I want to do is get the integer part of a Float variable (without checks). > I don't want rounding to nearest like I get with "Integer (Y)" > > In C, a function to do this might look like: > int x (float y) { return y; } > > Which generates code like: > pushl %ebp > movl %esp,%ebp > subl $12,%esp > flds 8(%ebp) > fnstcw -4(%ebp) > movl -4(%ebp),%edx > movb $12,%dh > movl %edx,-12(%ebp) > fldcw -12(%ebp) > fistpl -12(%ebp) > movl -12(%ebp),%eax > fldcw -4(%ebp) > movl %ebp,%esp > popl %ebp > ret > > In Ada you could try something like: > > pragma Suppress (All_Checks); > function X (A : Float) return Integer is > begin > return Integer (Float'Floor (A)); > end X; > > which generates twice as much code, and a call to system__fat_flt__fat_float__floor > I have also seen "Integer (A - 0.5)" used, but the core of the code for this is still *much* more > verbose than the core of the C function. > > No matter what I try, I get *at least* twice as much code to execute out of the Ada. > My application is generating indexes for a multi-dimensional array structure from > floating point values. If I get a major performance penalty from Ada (>20%), I will be tempted > to code this in C or assembly :( Could I get the right code in my application using > a Machine Operation in an pragama Inlined function? > > This should be so simple! What is the expression for getting the right code? > Shouldn't there be an attribute to an integer out of a float, rounding up/down/nearest/etc?? > -- > Adrian Wrigley, Cambridge, UK > Kind of yucky, although the C version that wants rounding ends up being a little ugly and calling a builtin to do a round...It does seem to be a shame that the compiler does not do something better here. If you can use a more up to date gcc (a 3.X series) and have a pentium 4 (maybe ok on III) then you can try this little thing I made contents of a file called truncate.ads function truncate(y : in float) return Integer; pragma inline(truncate); contents of a file called truncate.adb with Machine_Code; use Machine_Code; function truncate(y : in float) return Integer is temp : integer; begin Asm ("cvttss2si %1, %0",inputs => float'asm_input("m", y), Outputs => integer'asm_output("=r",temp)); return temp; end truncate; and a little test driver with Text_IO; with Truncate; procedure TestX is I : Integer; begin I := Truncate(100.8); Text_IO.Put_Line(Integer'image(I)); end TestX; This prints 100 when it runs...Beyond that I can not promise anything :) In terms of the code, it looks like gcc -S -O2 -gnatp -fomit-frame-pointer truncate.adb C:\msys\1.0\home\jcreem>type truncate.s .file "truncate.adb" .globl _truncate_E .data _truncate_E: .byte 0 .text .p2align 4,,15 .globl __ada_truncate .def __ada_truncate; .scl 2; .type 32; .endef __ada_truncate: /APP cvttss2si 4(%esp), %eax /NO_APP ret Or in other words, it is a single instruction. I can confirm that when compiled with -O2 -gnatn it does indeed inline this and you essentially end up with the single instruction.