### Author Topic: Large integers and floats  (Read 18073 times)

#### LiaoMi

• Member
• Posts: 948
##### Re: Large integers and floats
« Reply #45 on: August 27, 2021, 08:53:24 PM »
Hi nidud,

thanks  , what about multiplication and division? Are these features available?

#### nidud

• Member
• Posts: 2307
##### Re: Large integers and floats
« Reply #46 on: August 28, 2021, 02:52:37 AM »
The expression evaluator works up to 16 byte-sized values (unsigned, signed and floats). I've done some experiments using this for the operator directive but nothing is implemented yet.

#### JK

• Member
• Posts: 156
##### Re: Large integers and floats
« Reply #47 on: September 19, 2021, 06:00:25 PM »
Hi nidud,

while comparing real4 and real8 (.if (r4_1 == r4_2) ...    .if (r8_1 == r8_2) ...) works in 32 and 64 bit, it fails for real10. Likewise comparing a qword to an immediate value works in 64 bit but it fails in 32 bit ( .if (q == 255) ...). Comparing floats to immediate values is not possible at all (.if (r4 == 1.0) ...).

It would be extremely convenient to have all of these too (being able to compare a qword to an immediate value in 32 bit in first place) - any chance for an implementation?

Thanks

JK

#### jj2007

• Member
• Posts: 11768
• Assembler is fun ;-)
##### Re: Large integers and floats
« Reply #48 on: September 19, 2021, 08:31:01 PM »
Fcmp: the desired precision can be indicated as third argument: low, medium, high, top and xtra precision

In practice, there is no such thing as "equal" when comparing two REAL10 values

#### nidud

• Member
• Posts: 2307
##### Re: Large integers and floats
« Reply #49 on: September 20, 2021, 12:58:21 AM »
Note that the support for this is rather limited as it only support COMISS and COMISD.

while comparing real4 and real8 (.if (r4_1 == r4_2) ...    .if (r8_1 == r8_2) ...) works in 32 and 64 bit,

This didn't really work as it only compared the binary value (mov eax,r4_2 | cmp r4_1, eax). This is now added so now this works:

.if (r4_1 > r4_2)
*    movss xmm0, r4_1
*    comiss xmm0,  r4_2
*   jna @C0002

nop
.endif
.if (r8_1 > r8_2)
nop
.endif
.if (xmm0 > r4_2)
nop
.endif
.if (xmm0 > r8_2)
nop
.endif

Immediate values needs register and size.

option float: 4 ; default

.if (xmm0 > 4.0)
nop
.endif

option float: 8

.if (xmm0 > 8.0)
nop
.endif

#### nidud

• Member
• Posts: 2307
##### Re: Large integers and floats
« Reply #50 on: September 20, 2021, 04:23:44 AM »
Technically immediate floats are memory operands so they are now recursively parsed.

.if ( r8_1 > 8.0 && r8_1 < r8_2 ||
r4_1 > 4.0 && r4_1 < r4_2 ||
xmm1 > r8_1 && xmm0 > r4_1 )
nop
.endif

movsd   xmm0, qword ptr [ebp-10H]
comisd  xmm0, qword ptr [_F0000]
jbe     ?_001
movsd   xmm0, qword ptr [ebp-10H]
comisd  xmm0, qword ptr [ebp-18H]
jc      ?_003
?_001:  movss   xmm0, dword ptr [ebp-4H]
comiss  xmm0, dword ptr [_F0001]
jbe     ?_002
movss   xmm0, dword ptr [ebp-4H]
comiss  xmm0, dword ptr [ebp-8H]
jc      ?_003
?_002:  comisd  xmm1, qword ptr [ebp-10H]
jbe     ?_004
comiss  xmm0, dword ptr [ebp-4H]
jbe     ?_004
?_003:  nop

#### JK

• Member
• Posts: 156
##### Re: Large integers and floats
« Reply #51 on: September 20, 2021, 07:29:25 AM »
Many thanks nidud!

Quote
Technically immediate floats are memory operands

If all immediate numbers are memory operands, then you could implement a qword comparison in 32 bit as two dword comparisons. This (pseudo code) would test for equal:
Code: [Select]
`cmp dword ptr var, dword ptr [_F0000]jne ...cmp dword prt var[4], dword ptr [_F0000][4]jne ...`
one operand being a qword variable (of course it cannot be a register in 32 bit) and the other one an immediate value

JK

#### nidud

• Member
• Posts: 2307
##### Re: Large integers and floats
« Reply #52 on: September 20, 2021, 08:16:11 AM »
If all immediate numbers are memory operands, then you could implement a qword comparison in 32 bit as two dword comparisons.

Only floats are converted so a qword needs to be assigned.

local a:qword, b:qword

.if ( a > b )

.endif

.new t:qword = 0x4000000000000000

.if ( a < t )

.endif

There is however a problem with signed compare of qwords in 32-bit.

#### JK

• Member
• Posts: 156
##### Re: Large integers and floats
« Reply #53 on: September 30, 2021, 12:42:25 AM »
Converting and comparing floats:

I know comparing floats can be tricky, but given the code below both real8 (g_r8 vs. l_r8_1/l_r8_2) should be equal, because the "input" (17.6) is equal:
Code: [Select]
`option wstring:ONinclude windows.inc includelib kernel32.lib includelib user32.lib .datag_r4  real4  17.6g_r8  real8  17.6g_r10 real10 17.6.codestart proc ;***************************************************************************; main;***************************************************************************local l_r4 :real4local l_r8_1 :real8local l_r8_2 :real8local l_r10:real10  finit  fld  g_r4                                           ;get real4  fstp l_r8_1                                         ;save as real8  movss xmm0, g_r4                                    ;get real4  cvtss2sd xmm1, xmm0                                 ;convert to real8  movsD  l_r8_2, xmm1                                 ;save  .if (l_r8_1 == l_r8_2)                              ;is equal, which correct     MessageBoxW(0, "ok #1", "Test #1", 0)              .endif    .if (g_r8 == l_r8_2)                                ;should be equal, but isn´t     MessageBoxW(0, "ok #2", "Test #1", 0)               .endif    .if (g_r8 == l_r8_1)                                ;should be equal, but isn´t     MessageBoxW(0, "ok #3", "Test #1", 0)            .endif    invoke ExitProcess, 0  retstart endp  end start`The difference comes from the initialization, g_r8 is initialized with real8 precision, while only real4 precision (17.6) is given.

Ok - you could say: a real8 must be initialized with real8 precision, therefore i implicitly add trailing zeros, if not enough digits are given. But as you can see from the real4 to real8 conversion, both ways (FPU, xmm) don´t add zeros. The resulting numbers (l_r8_1 and l_r8_2) are equal (which is expected) but differ from g_r8 despite the fact, that all origin from exactly the same floating point number.

Is there a way to initialize g_r8 with real4 precision, so that the resulting value is equal to the value of a real4 to real8 conversion? Maybe something like:
Code: [Select]
`g_r8 real8 17.6r4`
where "r4" means: create a real4 number first then convert to real8 and then assign this value.

Thanks

JK

#### nidud

• Member
• Posts: 2307
##### Re: Large integers and floats
« Reply #54 on: September 30, 2021, 01:43:00 AM »
the numbers:

real4  = 0x418CCCCD
real8  = 0x403199999999999A
real10 = 0x40038CCCCCCCCCCCCCCD

convert real4 to 8:

movss xmm0,l_r4     ; <-- 418CCCCD
cvtss2sd xmm0,xmm0  ; --> 40319999A0000000

It's possible to size-up a float by using real hex notation:

value = 418CCCCDr
.data
g_r4 real4 value
g_r8 real8 value
...
movss xmm0,g_r4
cvtss2sd xmm0,xmm0
movsd l_r8,xmm0
.if ( l_r8 == g_r8 )
printf("l_r8 == g_r8\n")
.endif

https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

#### JK

• Member
• Posts: 156
##### Re: Large integers and floats
« Reply #55 on: September 30, 2021, 02:56:02 AM »
Thanks, so real hex notation is what i need, it indeed does what i want!

But how to get "418CCCCDr" from "17.6"? (i know it´s the memory representation of "17.6" in real4 format). This is, what "r4" (or whatever specifier) could do instead of having to do it (somehow) manually. You could even go one step further and add an option, which automatically makes an appropriate (according to the given precision) real hex out of a floating point number.
Code: [Select]
`g_r4    real4 17.6     (= 0x418CCCCD)g_r8_1 real8 17.6     (= 0x403199999999999A)g_r8_2 real8 17.6r4   (= 0x40319999A0000000  from 418CCCCDr)...g_r10  real10 17.6r4g_r10  real10 17.6123456789r8option size-up:ong_r8_1 real8 17.6    (= 0x40319999A0000000  from 418CCCCDr, size-up because only real4 precision is given)g_r8_2 real8 17.6123456789 (-> no size-up needed, because real8 precision is given)...g_r10  real10 17.6                (-> size-up, because only real4 precision is given)g_r10  real10 17.6123456789 (-> size-up, because only real8 precision is given)`

JK

#### nidud

• Member
• Posts: 2307
##### Re: Large integers and floats
« Reply #56 on: September 30, 2021, 03:38:59 AM »
It's difficult as it is and even more so with mixed size. The best method would probably be to compare the smallest size. Reduce all numbers to floats and maybe strip off the low byte as well.

movd eax,xmm0
and eax,0xFFFFFF00
movd xmm0,eax

Quote
But how to get "418CCCCDr" from "17.6"?

Something like this maybe:

r4 macro value
exitm<(value and 0FFFFFFFFE00000000000000000000000r)>
endm

.data
g_r4 real4 r4(17.6)
g_r8 real8 r4(17.6)

#### JK

• Member
• Posts: 156
##### Re: Large integers and floats
« Reply #57 on: October 01, 2021, 03:13:08 AM »
Yes- a macro would do. But in this case g_r4 real4 r4(17.6) is not equal to g_r4 real4 17.6, it is 17.599853 vs. 17.600000.

If i understand correctly, what you do here, then you try to mask out all mantissa bits exceeding real4 precision. But then the mask should be 32 + 7 (exponent difference = 7) bits "1" and the rest should be "0" (0FFFFFFFFFD000...) - which is closer (17.599998) but still not the same.

Loading both into the FPU results in 40038CCCCD0000000000 -> 17.600000.. vs. 40038CCCCC0000000000 -> 17.599998... It differs by one bit (the last one) set or not. Loading a real8 with a value of 17.6 results in 40038CCCCCCCCCCCD000, which explains the difference. So the basic idea (masking out) is good, but we also need some kind of rounding to make it correct.

The functionality must already be there (somewhere ) in ASMC, because just assigning 17.6 (converting a real16 back) to a real4 works correctly.

JK

#### nidud

• Member
• Posts: 2307
##### Re: Large integers and floats
« Reply #58 on: October 01, 2021, 03:55:10 AM »
Think the first suggestion is probably more reliable than this bit manipulation.

cmpfd proto :real4, :real8 {
cvtsd2ss xmm1,xmm1
comiss xmm0,xmm1
retm<(ZERO?)>
}

.data
g_r4 real4 17.6
g_r8 real8 17.6
...
.if cmpfd(g_r4, g_r8)

#### jj2007

• Member
• Posts: 11768
• Assembler is fun ;-)
##### Re: Large integers and floats
« Reply #59 on: October 01, 2021, 04:46:49 AM »