Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2021-10

Currency * Double

3 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

LacaK
Hi ,
what data type is result of multiplication of: (Currency * Double) on
Win64 (and on Win32)?
   c:=1115;
   d:=100000000;
   writeln(Round(c*d)); // gives -72967440737

I suppose that Currency*Double is Currency (on Win64) and result overflows MaxCurrency ...?
(but then how FPC determines result data type?; On Win32 there is result Extended?)

TIA
-Laco.

Reply by email

Virgo Pärna
to LacaK
LacaK wrote 6 lines
Hi , what data type is result of multiplication of: (Currency * Double) on Win64 (and on Win32)?   c:=1115;   d:=100000000;   writeln(Round(c*d)); // gives -72967440737

32 bit version gives always 111500000000 as a result (and floating point math should always have extended precision intermeiate there) . But even with double intermediate result on 64 bit versions there should not be any problems. 1.1150000000000000E+011 is well in range of that type.

Virgo Pärna

Reply by email

LacaK
to Virgo Pärna
Show quoted text 12 lines
> Hi , > what data type is result of multiplication of: (Currency * Double) on > Win64 (and on Win32)? >   c:=1115; >   d:=100000000; >   writeln(Round(c*d)); // gives -72967440737 32 bit version gives always 111500000000 as a result (and floating point math should always have extended precision intermeiate there) . But even with double intermediate result on 64 bit versions there should not be any problems. 1.1150000000000000E+011 is well in range of that type.

Let's look at disassembly on Win32:
--------------------------------------------------------- (FPU here uses "st registers" 80 bits wide)

test_curr_int64.lpr:77            c1:=1115; 00401EFC a178a14200               mov    0x42a178,%eax 00401F01 a320204300               mov    %eax,0x432020 00401F06 a17ca14200               mov    0x42a17c,%eax 00401F0B a324204300               mov    %eax,0x432024 test_curr_int64.lpr:78            d:=100000000; 00401F10 a180a14200               mov    0x42a180,%eax 00401F15 a330204300               mov    %eax,0x432030 00401F1A a184a14200               mov    0x42a184,%eax 00401F1F a334204300               mov    %eax,0x432034 test_curr_int64.lpr:79            i1:=Round(c1*d); 00401F24 dd0530204300             fldl   0x432030                 // st0:=100000000
00401F2A dc0d08a14200             fmull  0x42a108                 // st0:=1000000000000
00401F30 df2d20204300             fildll 0x432020                 // st0:=11150000, st1:=1000000000000
00401F36 dec9                     fmulp  %st,%st(1)               // st0:=1.115e+019
00401F38 df2d28a04200             fildll 0x42a028                 // st0:=10000, st1:=1.115e+019
00401F3E def9                     fdivrp %st,%st(1)               // st0:=1115000000000000
00401F40 df2d28a04200             fildll 0x42a028                 // st0:=10000, st1:=1115000000000000
00401F46 def9                     fdivrp %st,%st(1)               // st0:=111500000000
00401F48 df7df8                   fistpll -0x8(%ebp) 00401F4B 9b                       fwait 00401F4C 8b45f8                   mov    -0x8(%ebp),%eax 00401F4F a340204300               mov    %eax,0x432040 00401F54 8b45fc                   mov    -0x4(%ebp),%eax 00401F57 a344204300               mov    %eax,0x432044

And now on Win64:
---------------------------
test_curr_int64.lpr:77                    c1:=1115; 0000000100001EAC 48c70569410400b022aa00   movq
$0xaa22b0,0x44169(%rip)        # 0x100046020 test_curr_int64.lpr:78                    d:=100000000; 0000000100001EB7 488b05f2f20200           mov 0x2f2f2(%rip),%rax        # 0x1000311b0 <_$TEST_CURR_INT64$_Ld16>
0000000100001EBE 4889056b410400           mov %rax,0x4416b(%rip)        # 0x100046030
test_curr_int64.lpr:79                    i1:=Round(c1*d); 0000000100001EC5 f20f100563410400         movsd 0x44163(%rip),%xmm0        // 100000000
0000000100001ECD f20f590553f20200         mulsd 0x2f253(%rip),%xmm0        // 1000000000000 0000000100001ED5 f2480f2dc8               cvtsd2si %xmm0,%rcx               // 1000000000000 0000000100001EDA 488b053f410400           mov 0x4413f(%rip),%rax         // 11150000
0000000100001EE1 480fafc8                 imul %rax,%rcx                  // -7296744073709551616 <---OVERFLOW HERE 0000000100001EE5 48b84b598638d6c56d34     movabs $0x346dc5d63886594b,%rax 0000000100001EEF 48f7e9                   imul   %rcx 0000000100001EF2 48c1fa0b                 sar    $0xb,%rdx 0000000100001EF6 48c1e93f                 shr    $0x3f,%rcx 0000000100001EFA 4801ca                   add    %rcx,%rdx 0000000100001EFD 4889d1                   mov    %rdx,%rcx 0000000100001F00 e8fb110000               callq  0x100003100 <SYSTEM_$$_ROUND$CURRENCY$$INT64>
0000000100001F05 48890534410400           mov %rax,0x44134(%rip)        # 0x100046040

If I understand correctly multipllication "imul" is performed as multiplication of two currency values (int64)
(11150000 * 1000000000000 = 1115 * 10^16) which is over Max Int64 ... So on Win64 there is currency (int64) intermediate ...

L.

Reply by email