Author Topic: Question about quads  (Read 3089 times)

0 Members and 1 Guest are viewing this topic.

Arnold

  • Guest
Question about quads
« on: August 10, 2018, 06:55:02 AM »
Hi Charles,

by chance, I came across this strange behavior. I tried to print the quad numbers 1e16,1e17,1e18.
Code: [Select]
$ filename "quads.exe"
'use rtl32
'use rtl64

uses console

quad i=1e16
printl "1e16       = " i
i=10000000000000000
printl "as number  = " i
i=pow(10,16)
printl "pow(10,16) = " i
printl
i=1e17
printl "le17       = " i
i=100000000000000000
printl "as number  = " i
i=pow(10,17)
printl "pow(10,17) = " i
printl
i=1e18
printl "1e18       = " i
i=1000000000000000000
printl "as number  = " i
i=pow(10,18)
printl "pow(10,18) = " i
printl

printl "Enter ... " : waitkey

the output in 32-bit is (1e17 is strange):

1e16       = 10000000000000000
as number  = 10000000000000000
pow(10,16) = 10000000000000000

le17       = 1
as number  = 1
pow(10,17) = 1

1e18       = 1E+18
as number  = 1E+18
pow(10,18) = 1E+18


the output in 64-bit is (only pow(10,16) and pow(10,18) are correct):

1e16       = 1874919424
as number  = 1874919424
pow(10,16) = 10000000000000000

le17       = 1569325056
as number  = 1569325056
pow(10,17) = 1

1e18       = -1486618624
as number  = -1486618624
pow(10,18) = 1E+18

Is this a problem with my 64-bit machine or do I need some casting?

Roland

Charles Pegge

  • Guest
Re: Question about quads
« Reply #1 on: August 11, 2018, 04:10:40 AM »
Hi Roland,

In 32bit mode Quads are processed in the FPU, whereas in 64bit mode, they are processed directly by the CPU.

Quads are treated as 64bit signed integers. There is no unsigned option. So you will see overflows in 64bit mode.

There is a bug affecting the output of E17-sized numbers.  The lose their E component when converted to a number string. I will correct this misbehaviour in the next release.

In the longer term, I'm considering whether to switch all number i/o processing to MSVCRT. This would have the advantage of conforming to the C99 standard but entails the disadvantage of downgrading from extended precision to double precision. (This is a Microsoft issue). What do you think?

Arnold

  • Guest
Re: Question about quads
« Reply #2 on: August 11, 2018, 05:22:02 AM »
Hi Charles,

I have to admit that this goes far beyond my scope. Usually I do not need quad data types. But now that I am using Windows 10 64-bit, I am trying to better understand the differences between 32-bit and 64-bit numbers and whether it is possible to represent and print those numbers on 64-bit systems. I do not know if this will work with other programming languages ​​without extra routines.

Therefore, each of your approach is fine for me. I assume Mike and other forum members can judge this topic better than I do.

Roland

Charles Pegge

  • Guest
Re: Question about quads
« Reply #3 on: August 11, 2018, 05:33:50 PM »
You can try sprintf directly. It's quite easy to use with a converter term (quad, double ...)

Code: [Select]
'03:43 11/08/2018
'msvcrt val/str/format$ equivalent
'http://www.cplusplus.com/reference/cstdio/printf/
'nb: msvcrt downgrades extended precision to double.

  uses msvcrt 'or corewin
  char odata[64]
  sprintf(odata,"%g", double 1/3) '0.333333
  print odata
  sprintf(odata,"%lli", quad 9/5) '2
  print odata
« Last Edit: August 11, 2018, 05:48:12 PM by Charles Pegge »

Mike Lobanovsky

  • Guest
Re: Question about quads
« Reply #4 on: August 12, 2018, 01:47:40 AM »
Hi Roland and Charles,

My judgement is the closer we are to what most other people and languages do and have, the better. That's why I vote for 64-bit double precision calc that makes the results predictable and compatible with other general-purpose apps and libraries at all times. In my opinion, extended precision is a particular case of arbitrary precision calc and as such, it should resort to specialized libraries and instruments.

Regarding msvcrt vs. corewin, I'd still recommend working with the former in the user code. The corewin DLL is a kernel library and its binary interface and implementation are largely dependent on the exact OS build and version that the computer is currently running. It is primarily intended to build system-specific drivers (a.k.a. native applications). OTOH msvcrt.dll is nothing more than a mere user-mode proxy to the kernel-dependent API/ABI of corewin.dll. It is intended for making user-mode programs independent of the OS they are running under, and its ABI is guaranteed to remain unchanged for as long as the MS Windows OS'es are available.

Charles Pegge

  • Guest
Re: Question about quads
« Reply #5 on: August 13, 2018, 05:53:57 AM »
Hi Mike,

I use extended floats (80 bit) in my val() and str() algorithms. These values are passed directly on the FPU stack so there is no memory i/o and no loss of precision following a numeric expression, and no need for type conversion. The 80bit number contains a 64bit significand, so it represents both floats and quad-integers.

Apart from these advantages, it is very tempting to 'pass the buck' and adopt MSVCRT's scanf and printf to do the work for o2. It reduces the size of the run-time libraries by about 30% (about 60k of Assembler for RTL32 and RTL64), which I would no longer have to think about.


Arnold

  • Guest
Re: Question about quads
« Reply #6 on: August 13, 2018, 06:10:37 AM »
Hi Charles, Mike,

thank you for the link, example and the explanations. When I started to search in Internet for msvcrt.dll I found myself in a hell of different versions and derivations and opinions. But it seems that for MS Windows msvcrt.dll is delivered with every version since Win95.

I am not sure but it seems to me that the tinycc compiler tcc v 0.9.27 uses msvcrt.dll for output in MS Windows too. So I tried this little example (Ranges.c):
Code: [Select]
#include <stdio.h>
#include <math.h>

int main () {
   int c;
   printf("2^31-1 =  %lf\n", pow(2, 31)-1);
   printf("2^32-1 =  %lf\n", pow(2, 32)-1);
   printf("2^63-1 =  %lf\n", pow(2, 63)-1);
   printf("2^64-1 =  %lf\n", pow(2, 64)-1);

   printf("Enter: ... ");
   c=getchar();
   
   return(0);
}

Compiling with:
... >tcc -m32 Ranges.c
... >tcc -m64 Ranges.c

I will get the same output in Win32 and Win64:

2^31-1 =  2147483647.000000
2^32-1 =  4294967295.000000
2^63-1 =  9223372036854775800.000000
2^64-1 =  18446744073709552000.000000
Enter: ...

Using O2 I tried this (Ranges.o2bas):
Code: OxygenBasic
  1. $ filename "ranges.exe"
  2. 'use rtl32
  3. 'use rtl64
  4.  
  5. uses console
  6. uses msvcrt 'or corewin
  7.  
  8.    char odata[64]
  9.    sprintf(odata, "%lf", 2^31 -1)    '2147483647
  10.   printl "2^31-1 = " odata
  11.    sprintf(odata, "%lf", 2^32 -1)    '4294967295
  12.   printl "2^32-1 = " odata
  13.    sprintf(odata, "%lf", 2^63 -1)    '9223372036854775807
  14.   printl "2^63-1 = " odata
  15.    sprintf(odata, "%lf", 2^64 -1)    '18446744073709551615
  16.   printl "2^64-1 = " odata
  17.  
  18. printl "Enter: ... " : waitkey
  19.  

In Win32 I will get the same output as with tcc. But Win64 does simply not work. Could I do something better?

Roland



jack

  • Guest
Re: Question about quads
« Reply #7 on: August 13, 2018, 07:08:19 AM »
Hi Arnold
in your C code, try replacing the last two printf with
Code: [Select]
   printf("2^63-1 =  %Lf\n", powl(2, 63)-1L);
   printf("2^64-1 =  %Lf\n", powl(2, 64)-1L);
and see what it's output will be

edit:
it looks to me that your o2 code needs to specify the integer type in the expression 2^63 and 2^64
« Last Edit: August 13, 2018, 07:19:16 AM by jack »

Arnold

  • Guest
Re: Question about quads
« Reply #8 on: August 13, 2018, 07:59:45 AM »
Thank you, Jack. Using tcc there was no difference between %Lf and %lf; powl is not accepted with tcc. I have no experience with msvcrt.dll, but I think the result is only an approximation which is ok for me. I am only confused why I get the same result in O2 when running 32-bit, but in Win64 I only get zeros.

Charles Pegge

  • Guest
Re: Question about quads
« Reply #9 on: August 13, 2018, 09:32:24 AM »
Hi Roland,

There is something very strange going on.  In 64bit mode, MSVCRT produces a tiny value, whereas native o2 produces the expected result.

Code: [Select]
$filename "t.exe"
uses rtl64
uses corewin
char od[64]
double d=(2^63)-1
sprintf od,"%g", double (2^63)-1 : print od
sprintf od,"%g", double d : print od
print ( (2^63)-1 )

PS:
I've checked the Assembly code, and stack  16byte alignment, so there's nothing obvious wrong with the o2 call.
« Last Edit: August 13, 2018, 09:48:22 AM by Charles Pegge »

jack

  • Guest
Re: Question about quads
« Reply #10 on: August 13, 2018, 10:45:13 AM »
hello Charles Pegge
I may be shooting in the dark, could it be that o2 x64 expects the float result to be in st(0) instead of xmm0?

Mike Lobanovsky

  • Guest
Re: Question about quads
« Reply #11 on: August 13, 2018, 12:16:35 PM »
But it seems that for MS Windows msvcrt.dll is delivered with every version since Win95.

That says it all. FBSL has always relied on msvcrt.dll since its v1.0. Now, more than 15 years after v1.0, FBSL v3.5 can still run successfully on any Windows OS starting from Windows'95 OSR 2 (winsock control added to the system) up to Windows 10.

IMHO that beats flat all other considerations regarding bits and pieces of 80-bit calc and I/O that O2 and/or PB can offer. And it does reduce the runtimes of both BASIC compilers and interpreters by a few dozens kilobytes.

Charles Pegge

  • Guest
Re: Question about quads
« Reply #12 on: August 13, 2018, 12:43:22 PM »
Very close, Jack.

In fact, variadic parameters should be passed in the CPU registers, even when they are floats. A new discovery for me, anyway.

So this is the solution, and probably the best way to make use of sprintf

Code: [Select]
$filename "t.exe"
uses rtl64
uses corewin

function cformat(char*f, ...) as string
=======================================
  'restricted to one value only
  indexbase 1
  char od[64]
  #ifdef mode64bit
    sprintf od,f,param[2]
  #else
     sprintf od,f,param[2],param[3]
  #endif
  return od
end function
 
print cformat( "%g" , (2^63)-1 )
« Last Edit: August 13, 2018, 12:50:15 PM by Charles Pegge »

jack

  • Guest
Re: Question about quads
« Reply #13 on: August 13, 2018, 02:53:57 PM »
hello Charles Pegge
I hope that I don't come across as smart-a$$ :)
found this info on msdn
Quote
Varargs
11/03/2016
2 minutes to read
Contributors
Colin Robertson  Mike Jones  Mike B  Gordon Hogenson  Saisang Cai
If parameters are passed via varargs (for example, ellipsis arguments), then essentially the normal parameter passing applies including spilling the fifth and subsequent arguments. It is again the callee's responsibility to dump arguments that have their address taken. For floating-point values only, both the integer and the floating-point register will contain the float value in case the callee expects the value in the integer registers.
and
Quote
Parameter Passing
11/03/2016
2 minutes to read
Contributors
Colin Robertson  Mike Jones  Mike B  Gordon Hogenson  Saisang Cai
The first four integer arguments are passed in registers. Integer values are passed (in order left to right) in RCX, RDX, R8, and R9. Arguments five and higher are passed on the stack. All arguments are right-justified in registers. This is done so the callee can ignore the upper bits of the register if need be and can access only the portion of the register necessary.
Floating-point and double-precision arguments are passed in XMM0 - XMM3 (up to 4) with the integer slot (RCX, RDX, R8, and R9) that would normally be used for that cardinal slot being ignored (see example) and vice versa.
from that I gather that floats are passed to both xmm0 .. xmm3 and RCX, RDX, R8, and R9, I have not tested if this is actually true.

Charles Pegge

  • Guest
Re: Question about quads
« Reply #14 on: August 13, 2018, 05:01:55 PM »
Thanks, Jack.

It is not an elegant standard, and definitely not supportive of applications-level programming. Furthermore, the Microsoft 64bit differs in register usage from everyone else's 64bit calling convention.

o2 uses cdecl for all user-level internal 64bit calls, but maintains 16byte stack pointer alignment. This is how it should have been  :)