Author Topic: Printing REAL10 values with the full range of decimal digits  (Read 12256 times)

Gunther

  • Member
  • *****
  • Posts: 3585
  • Forgive your enemies, but never forget their names
Re: Printing REAL10 values with the full range of decimal digits
« Reply #15 on: January 04, 2015, 02:17:36 AM »
Erol,

never mind. The new version, included in Real10ValC.zip works fine. I'll check the code and build process in detail tomorrow, because I've to finish my kernel-mode driver. It works now as expected, but I've to write the documentation, which is a lot of work to do.

Gunther
Get your facts first, and then you can distort them.

Vortex

  • Member
  • *****
  • Posts: 1994
Re: Printing REAL10 values with the full range of decimal digits
« Reply #16 on: January 04, 2015, 03:40:05 AM »
Hi Gunther,

No any problem. The internals of MinGW are very complicated and probably the A and B examples are missing something important.

Gunther

  • Member
  • *****
  • Posts: 3585
  • Forgive your enemies, but never forget their names
Re: Printing REAL10 values with the full range of decimal digits
« Reply #17 on: January 04, 2015, 04:30:02 AM »
Erol,

The internals of MinGW are very complicated and probably the A and B examples are missing something important.

that's my impression, too. But my idea should be practicable in both worlds (Win-32 and Win-64). By the way, what's the behavior of Pelle's C with long double values?

Gunther
Get your facts first, and then you can distort them.

jj2007

  • Member
  • *****
  • Posts: 9686
  • Assembler is fun ;-)
    • MasmBasic
Re: Printing REAL10 values with the full range of decimal digits
« Reply #18 on: January 04, 2015, 04:51:24 AM »
what's the behavior of Pelle's C with long double values?

  long double ld=1234567890.1234567890;
  printf("This is a long double: %.9f\n", ld);

  This is a long double: 1234567890.123456746

@Erol: What about a dll or static lib version for the ordinary mortals among us?

Vortex

  • Member
  • *****
  • Posts: 1994
Re: Printing REAL10 values with the full range of decimal digits
« Reply #19 on: January 04, 2015, 04:58:07 AM »
Hi Jochen,

Quote
@Erol: What about a dll or static lib version for the ordinary mortals among us?

As I mentioned above, the linking process managed by ld.exe is very complicated. We have to understand the relations between the MinGW libraries. For the moment, it's better to mimic some portions of the verbose logging. Not a perfect solution but it seems to work.

adeyblue

  • Member
  • **
  • Posts: 89
    • Airesoft
Re: Printing REAL10 values with the full range of decimal digits
« Reply #20 on: January 05, 2015, 02:11:55 PM »
Thanks to Vortex and Gunther diving the necessary command line, I've created some dlls for just the various __mingw_printf / scanf functions. It's pretty much just a matter of using a def to say what to export and adding in all those libraries to the linker. The f* versions aren't there, since the FILE struct is likely to be different for other compilers / versions of msvcrt, but you can just uncomment them from the def if you want them.

It seems to work from the quick test I gave it.

Gunther

  • Member
  • *****
  • Posts: 3585
  • Forgive your enemies, but never forget their names
Re: Printing REAL10 values with the full range of decimal digits
« Reply #21 on: January 06, 2015, 12:00:04 AM »
Hi adeyblue,

thank you for your distribution. I'll test it this evening. Could one integrate it into VS?

Gunther
Get your facts first, and then you can distort them.

adeyblue

  • Member
  • **
  • Posts: 89
    • Airesoft
Re: Printing REAL10 values with the full range of decimal digits
« Reply #22 on: January 06, 2015, 08:40:51 AM »
As far as you can call the functions, yes. You can't print long doubles directly using the C/C++ compiler since they're really only normal 64-bit doubles, but you can print them if you get them via other means (like below where its defined in hex).

MASM should be fine though.

Code: [Select]
void PrintIt(const char* p, ...)
{
va_list a;
va_start(a, p);
int ret = __mingw_vprintf(p, a);
va_end(a);
}

void test()
{
unsigned doub[4]; // 1234567890.123456789 in hex
doub[3] = 0;
doub[2] = 0x401d;
doub[1] = 0x932C05A4;
doub[0] = 0x3F35BA6E;
__m128 val = _mm_loadu_ps((float*)&doub[0]);
__mingw_printf("Value is %.9Lf\n", val);
PrintIt("Value is %.9Lf\n", val);
}

I'm trying to build the relevant bits from source, but the resulting dll is crash happy.

Gunther

  • Member
  • *****
  • Posts: 3585
  • Forgive your enemies, but never forget their names
Re: Printing REAL10 values with the full range of decimal digits
« Reply #23 on: January 06, 2015, 11:45:44 AM »
Hi adeyblue,

I'm trying to build the relevant bits from source, but the resulting dll is crash happy.

yes, entire topic is complicated, but your plan could be successful.

Gunther
Get your facts first, and then you can distort them.

jj2007

  • Member
  • *****
  • Posts: 9686
  • Assembler is fun ;-)
    • MasmBasic
Re: Printing REAL10 values with the full range of decimal digits
« Reply #24 on: January 07, 2015, 07:49:39 AM »
I'm trying to build the relevant bits from source, but the resulting dll is crash happy.

MS VC 2010 gave me "Cannot load the project due to a corrupt project file" (I've never seen a successful conversion, VS is such a crap :icon_redface:).

Can you build the DLL in 32-bit and post it here? I'd like to compare the results to my own code.

GoneFishing

  • Member
  • *****
  • Posts: 1071
  • Gone fishing
Re: Printing REAL10 values with the full range of decimal digits
« Reply #25 on: January 07, 2015, 08:30:47 AM »
The .vcproj file contains absolute paths "f:\dev-cpp\lib32;f:\dev-cpp\lib32\gcc\4.7.2\" which may not exist on you computer.
I've just downloaded the archive and found both 32 abd 64 bit dlls in "files" folder.

Gunther

  • Member
  • *****
  • Posts: 3585
  • Forgive your enemies, but never forget their names
Re: Printing REAL10 values with the full range of decimal digits
« Reply #26 on: January 07, 2015, 08:46:16 AM »
Hi vertograd,

The .vcproj file contains absolute paths "f:\dev-cpp\lib32;f:\dev-cpp\lib32\gcc\4.7.2\" which may not exist on you computer.
I've just downloaded the archive and found both 32 abd 64 bit dlls in "files" folder.

oh yes, these tricky project files. What about this: Writing a batch file and using the command line compiler? I hope that Microsoft provides it. That avoids the trouble.

Gunther
Get your facts first, and then you can distort them.

GoneFishing

  • Member
  • *****
  • Posts: 1071
  • Gone fishing
Re: Printing REAL10 values with the full range of decimal digits
« Reply #27 on: January 07, 2015, 08:51:52 AM »
Hi Gunther,
The command line for MS VS project can be terrific  :shock:
Once I started to write python script that parses .vcproj and converts it to  linux makefile (for opengl examples ) . The first part was done but the later is not yet finished .

jj2007

  • Member
  • *****
  • Posts: 9686
  • Assembler is fun ;-)
    • MasmBasic
Re: Printing REAL10 values with the full range of decimal digits
« Reply #28 on: January 07, 2015, 09:31:58 AM »
I've just downloaded the archive and found both 32 abd 64 bit dlls in "files" folder.

Oops, I was so busy trying to compile that I had not even looked into that folder. Thanks, adeyblue & vertograd :t

Here is a first test with the 32-bit DLL (left: MasmBasic Str$(), right: __mingw_sprintf). It seems that while you can specify more than 19 digits with sprintf(), their value is kind of doubtful:
Code: [Select]
digits    12345678901234567890    12345678901234567890
#1      0.1111111111111111111   0.1111111111111111111028290
#2      0.2222222222222222222   0.2222222222222222222056580
#3      0.3333333333333333333   0.3333333333333333333152633
#4      0.4444444444444444444   0.4444444444444444444113160
#5      0.5555555555555555555   0.5555555555555555555073688
#6      0.6666666666666666666   0.6666666666666666666305266
#7      0.7777777777777777777   0.7777777777777777777536844
#8      0.8888888888888888888   0.8888888888888888888768422
#9      1.000000000000000000    1.0000000000000000000000000
#10     1.111111111111111111    1.1111111111111111111231578
#11     1.222222222222222222    1.2222222222222222222463156

#86     9.555555555555555549    9.5555555555555555490021558
#87     9.666666666666666660    9.6666666666666666600168933
#88     9.777777777777777771    9.7777777777777777710316309
#89     9.888888888888888882    9.8888888888888888820463685
#90     9.999999999999999993    9.9999999999999999930611061
#91     10.11111111111111110    10.1111111111111111040758437
#92     10.22222222222222221    10.2222222222222222150905813
#93     10.33333333333333333    10.3333333333333333261053189
#94     10.44444444444444444    10.4444444444444444371200564
#95     10.55555555555555555    10.5555555555555555481347940
#96     10.66666666666666666    10.6666666666666666591495316
#97     10.77777777777777777    10.7777777777777777701642692
#98     10.88888888888888888    10.8888888888888888811790068
#99     10.99999999999999999    10.9999999999999999921937444
#100    11.11111111111111110    11.1111111111111111032084819

#996    110.6666666666666673    110.6666666666666673096708351
#997    110.7777777777777784    110.7777777777777784215529344
#998    110.8888888888888895    110.8888888888888895334350337
#999    111.0000000000000006    111.0000000000000006453171331
#1000   111.1111111111111118    111.1111111111111117571992324

Source:
include \masm32\MasmBasic\MasmBasic.inc      ; download
  SetGlobals MyR10:REAL10, Add01:REAL10=0.111111111111111111111, buffer[100]:BYTE
  Init
  Dll "\Masm32\bin\MingwPrintf32.dll"      ; adjust path if necessary
  Declare void __mingw_sprintf, C:?        ; ccall, vararg
  xor ecx, ecx
  Print "digits", Tb$, "  12345678901234567890", Tb$, "  12345678901234567890"
  .Repeat
      fld MyR10      ; load variable on FPU
      fld Add01      ; load modifier
      fadd           ; modify
      fstp MyR10     ; store back to memory
      .if ecx<11 || ecx>=85 && ecx<100 || ecx>=995
            __mingw_sprintf(addr buffer, "%1.25Lf", MyR10)
            Print Str$("\n#%i\t", ecx+1), Str$(MyR10), Tb$, addr buffer
      .elseif ecx==11 || ecx==100
            Print    ; insert a blank line
      .endif
      inc ecx
  .Until ecx>=1000
  Inkey CrLf$, "--- hit any key ---"
  Exit
end start


Source & exe attached, requires the latest MB version of 7 Jan.
« Last Edit: January 07, 2015, 10:36:50 AM by jj2007 »

adeyblue

  • Member
  • **
  • Posts: 89
    • Airesoft
Re: Printing REAL10 values with the full range of decimal digits
« Reply #29 on: January 07, 2015, 09:55:29 AM »
Yeah, you have to modify those absolute paths to point to your lib / lib\gcc\x.x.x\ directories if you want to create the dll. It was just about under the forum size limit without including the actual .o files (one which is 5MB by itself). The VC linker command line used is at the top of printf.c.

Anyhoo, I managed to compile it from source which has slightly minimized the size of the dll. I've attached what I ended up with. A static library and the dll are in the lib* directories. To build it GCC needs to be in your path, and you'll have to point the include and lib variables in source_code\build.cmd to point to your various MinGW include and lib dirs. It'll build 64 and 32-bit, optimized and debug versions of the code, provided you have the 64-bit MinGW and both sets of libs. I don't know what'll happen otherwise.

There's tons of warnings about -fpic not being necessary, primarily because I couldn't be bothered to figure out what it was needed for and what it wasn't. The static lib works with MinGW and VC2008 and above, it might not be compatible with any other CRT like Pelles due to the differences in FILE struct size. The dll should be usable by anything that can link to dlls.