• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

Does O2 has an integer function ?

Started by Chris Chancellor, May 07, 2018, 12:56:32 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Chris Chancellor

Hello Charles


In PB they have an Integer function

which Convert a numeric expression to an integer

y = INT(numeric_expression)

see http://www.manmrk.net/tutorials/basic/PowerBASIC/pbcc6/int_function.html


so in O2,  can we have something like

   
        Long  Tmpnum ,   Tmpnum2
         Tmpnum = 405
        Tmpnum = INT(Tmpnum / 16)

         Tmpnum2  = INT( Tmpnum\16 )

   


   is this syntaxly correct ?    as i'm using Long for  Tmpnum and  Tmpnum2

Chris Chancellor

i have compiled the below code


' IntegerFun.o2bas 

$ filename "IntegerFun.exe"
use rtl64
use corewin


Long  Tmpnum ,   Tmpnum2
         Tmpnum = 405
        Tmpnum = INT(Tmpnum / 16)

         Tmpnum2  = INT( Tmpnum\16 )

print "  Tmpnum " + Tmpnum  + chr(13,10)  + "  Tmpnum2  " + Tmpnum2



the results are  Tmpnum = 25   and Tmpnum2 = 1

which means that the  INT function in O2 is the same as in PB  ?
am i right here ?



Charles Pegge

Hi Chris,

O2 does not have an int() function, like PB's but you won't need one anyway if your variables are integers, and the division is an integer div '\'

For any numeric types, including singles and doubles, we have trunc() and round()

Mike Lobanovsky

Hi Charles,

What data type do trunc() and round() return? (NB: PB's ROUND() does "banker's", not arithmetic, rounding!)

floor() and ceil() can be imported from msvcrt.dll.

Quote from: Charles Pegge on May 07, 2018, 07:18:49 AM... you won't need one anyway if your variables are integers, and the division is an integer div '\'

Will -0.1 \ 1 return -1 as PB's INT() does?
Mike
(3.6GHz Intel Core i5 w/ 16GB RAM, 2 x GTX 650Ti w/ 2GB VRAM, Windows 7 Ultimate Sp1)

Charles Pegge

#4
Hi Mike,

O2 has core floor() and ceil() too. All of these functions are implemented as FPU macros, and their result is held on the fpu stack (80bit floats) until assigned to a variable. This also applies to whole expressions involving floats, or float division.

-0.1\1 produces -0 :)

Mike Lobanovsky

Quote from: Charles Pegge on May 07, 2018, 12:58:35 PMAll of these functions are implemented as FPU macros, and their result is held on the fpu stack (80bit floats) until assigned to a variable.

So, Oxygen's trunc(), round(), floor() and ceil() will automatically match the data type of the variable they are assigned to and thus won't need additional casts?

Quote-0.1\1 produces -0 :)

Sweet! Let's then leave the PB-like INT() and ROUND() (and a hellofalot of other) functional peculiarity re-implementations as a home exercise for whoever is going to be the first one to come up with the PB compatibility layer. :)
Mike
(3.6GHz Intel Core i5 w/ 16GB RAM, 2 x GTX 650Ti w/ 2GB VRAM, Windows 7 Ultimate Sp1)

Charles Pegge

These anomalies probably go back to a time when there was a software emulation of the FPU, for those early PCs without this expensive luxury chip (8087) .

Digressing a little further, O2 also supports float infinities, and expressions like float a= 1 / 0 are legit.

If a contains infinity then you will get an accurate 90 degrees from deg atn a

Chris Chancellor

Thanxx Charles

so any division by zero will give infinity ?  and the program won't  GPF    (global protection fault)?

this is a welcome feature for O2


Mike Lobanovsky

Quote from: Charles Pegge on May 07, 2018, 02:11:55 PM... O2 also supports float infinities, and expressions like float a= 1 / 0 are legit.

This is cool because it makes O2 compatible with GCC. 8)
Mike
(3.6GHz Intel Core i5 w/ 16GB RAM, 2 x GTX 650Ti w/ 2GB VRAM, Windows 7 Ultimate Sp1)

Charles Pegge

#9
Chris,

I've just checked:

You can still crash the program with an integer division by zero on an integer:

int i=1\0

A normal division will not crash, but produces a large negative number!

int i=1/0

Only floats have a bit representation for infinity, and handle it correctly, mathematically speaking.

single f=1\0
double f=1\0


single f=1/0
double f=1/0




Mike,

Does GCC support extended precision?

Mike Lobanovsky

Charles,

Yes, MinGW GCC can support long double/extended precision/80-bit/REAL10 format in calc and formatted output on 32 bits via the compiler command line option -mpc80. Otherwise, it defaults to double and also automatically reduces the long double declarations throughout the code to ordinary 64-bit double pretty much like MS VC would.

On 64 bits, MinGW GCC uses SSE instead.

Under MinGW GCC,  (float|double)+|-1.0 / 0 result in +|-INF, respectively, but (int)+|-1 / 0 throw a "division by 0" exception. That's why I noted Oxygen's compatibility with GCC. :)
Mike
(3.6GHz Intel Core i5 w/ 16GB RAM, 2 x GTX 650Ti w/ 2GB VRAM, Windows 7 Ultimate Sp1)

Brian Alvarez

Charles, do you mean the compiler will do automatic rounding of float integers when storing a float in an integer variable?
If so, that means I can create an int function for the cases when the programmer tries to store an integer value in a DOUBLE
or SINGLE variable, right?

Charles Pegge

#12
Thanks for the GCC info, Mike.

In 64bit extern mode, O2 is obliged to use SSE registers when passing floats directly, but all its float computations are done in the FPU. It is still possible to pass extended types byref


Hi Brian,

When a float variable or expression is assigned to an integer, it will be rounded up or down. This is not the same as PB's INT() function, which seems to be equivalent to our FLOOR()

http://www.manmrk.net/tutorials/basic/PowerBASIC/pbcc6/int_function.html

Johan Klassen

I did a test using gcc 7.3 on Windows 10 x64, tested both gcc 32-bit and gcc 64-bit with -mpc80 and without - the result were the same for the respective compiler

//
//  test.c
// 
//
#include <stdio.h>

int main()
{
union ldb{
unsigned short m[8];
long double ld;
};
typedef union ldb ldbl;

ldbl x;
x.ld=3.1415926535897932384626433832795L;

printf("%24.19Lf\n",x.ld);

printf("%X\n",x.m[0]);
printf("%X\n",x.m[1]);
printf("%X\n",x.m[2]);
printf("%X\n",x.m[3]);
printf("%X\n",x.m[4]);
return 0;
}

gcc 32-bit
gcc test.c -o test
output

-88796093704934495000000000000000000000000000.0000000000000000000
C235
2168
DAA2
C90F
4000

same result with gcc -mpc80 test.c -o test
the result using 64-bit gcc both with and without -mpc80  were

   0.0000000000000000000
C235
2168
DAA2
C90F
4000

as can be seen from the output, gcc correctly assigns the long double literal of pi to the variable but fails to print it, however if compiled with -D__USE_MINGW_ANSI_STDIO=1 then it prints the value as expected.

Mike Lobanovsky

#14
Hi Johan,

Thanks for the feedback. It inspired my own investigation with newer builds of MinGW GCC as my regular tool has always been, and still is, TDM GCC 4.3.3 because:

  • among the 64-bit capable GCC compilers, it produces the smallest and fastest executables (up to 2 times smaller and 45% faster) as compared to many later builds I tested my apps against;
  • unlike vanilla MinGW, TDM doesn't pull in too much alien Linuxoid stuff and it fits in seamlessly in the Code::Blocks environment that I'm using, as a faithful Windozer, instead of prehistoric console and batch/make file rudiments of the DOS era.
Here are my findings based on the latest available TDM GCC 5.1.0. I hope they will be useful to public at large because I failed to find all this information elsewhere on the net.

  • -mpc80 has never been intended for use under 64 bits, as is clearly stated twice in the gcc.info help file, therefore it is useless to test it in the 64-bit mode.
  • Moreover, -mpc80 has never even worked under Windows (at least within the 4.3.3 to 5.1.0 span) though it has not been stressed  – I'd say, quite expectedly for a piece of Linux SW – anywhere in the documentation. Thus, older versions like 4.3.3 didn't offer any alternatives at all to control the range of FPU precision other than 32-/64-bit floats.
  • Again, even if it would work, it would not be compatible with msvcrt.dll that TDM GCC (and I suppose, vanilla MinGW too) is linked against on default. msvcrt.dll's doesn't even offer a formatted input/output type specifier for anything wider than a double. Therefore, it isn't reasonable even to try to print an EXT or long double via msvcrt.dll, only to get the funny snake
    Quote-88796093704934495000000000000000000000000000.0000000000000000000
    crawling all around.
  • Both MS VC and GCC are general-purpose compilers, and there are no ordinary real world phenomena that would potentially require calculation in long-double or even EXT quantities. Arbitrary precision math calc can be done using specialized libraries only when really needed, and it is highly unlikely that NASA or DoD would rely in their multi-billion dollars worth projects on something so prosaic as MS VC, to say nothing of such a ridiculous thing as the restrictive and, at the same time, irresponsible GNU GPL(icense).
  • Luckily, later versions including 5.1.0 introduced an alternative option -mlong-double-NN which, much to my surprise and in contrast with the usual Linuxoid practices of irresponsible "as-is"-iness and "absolutely-no-warranty-whatsoever"-ness, does work under Windows and enables us to control, via the NN part of the option, the bitness of FPU calc results stored in GCC's long double variables.
  • In many cases, the below compilations throw quite a number of formatting and type mismatch warnings yet complete successfully regardless.
    Under 64 bits,

    • -mlong-double-64 makes a long double 8 bytes long and thus equal to a VC (long) double compatible with msvcrt.dll:
      Quotesize of long double = 8
      value = 3.1415926535897931000
      It however crashes __USE_MINGW_ANSI_STDIO (see  further below for criticism of this yet one more Linuxoid cheat/hack/"crutch");
    • -mlong-double-80 makes the long double 16 bytes long with only 80 bits (10 bytes) used for the actual presentation of an EXT precision floating-point quantity. It breaks GCC's compatibility with msvcrt.dll:
      Quotesize of long double = 16
      value = 0.0000000000000000000
      but makes it compatible with the __USE_MINGW_ANSI_STDIO hack:
      Quotesize of long double = 16
      value = 3.1415926535897932385
      Note the rounding-up at the 19th decimal place. Also note that there isn't a way to utilize the remaining 6 bytes of storage; a literal value overflows and refuses to compile at a little larger than approx. +1.18973e4932L (this matches well with PB's own 80-bit EXT upper range of approx. +1.2*10^4932 as per the PB manual), or yields GCC's typical +/-INF when overflown as a calculation result. Such behavior is a valid indication that calc indeed takes place in the Intel FPU's 80-bit wide context.
    • -mlong-double-128 is effectively equal to __float128 and moves the whole stuff to SSE.
  • Under 32 bits,

    • -mlong-double-64 works the same as it does under 64 bits;
    • -mlong-double-80 makes the long double 12 bytes long with only 80 bits (10 bytes) used for the actual presentation of an EXT precision floating-point quantity. It breaks GCC's compatibility with msvcrt.dll:
      Quotesize of long double = 12
      value = -88796093704934495000000000000000000000000000.0000000000000000000
      but makes it compatible with the __USE_MINGW_ANSI_STDIO hack.
  • Regarding __USE_MINGW_ANSI_STDIO, it is a dirty hack which links in statically GCC's own re-implementations of formatted input/output functions (printf, sprintf et al.) that introduce Linuxoid format specifiers for long doubles and overrun the respective calls to msvcrt.dll's native procedures. Overall, they

    • waste 2 to 6 extra bytes of memory space for every 80-bit literal or variable quantity – persistent or temporary;
    • make GCC's long double-aware executables significantly fatter than their GCC-emulated 8-byte (long) double/VC original counterparts; (22KB vs. 6KB minimum for 4.3.3, 35KB vs. 12KB minimum for 5.1.0)
    • litter extra space as defined by excessive precision digits with meaningless random noise, e.g.
      Quote3.141592653589793238512808959406
      for %.30Lf as opposed to MS VC's clear and concise
      Quote3.141592653589793100000000000000
      for a 64-bit (long) double;
    • sometimes crash GCC executables where msvcrt.dll would gracefully yield zero-filled output.

________________________________________________

Bottom line, as half baked and clumsy under Windows as much of Linuxoid "multiplatform" software usually is. ;)
Mike
(3.6GHz Intel Core i5 w/ 16GB RAM, 2 x GTX 650Ti w/ 2GB VRAM, Windows 7 Ultimate Sp1)