News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Small favour needed, test precision with sprintf.

Started by hutch--, September 05, 2018, 02:14:34 PM

Previous topic - Next topic

hutch--

I am testing the precision of the 64 bit MSVCRT version of sprintf. The default precision is 6 numbers after the decimal point but I have stretched it as far as I can get it on Win10 to about 11. I need the test done on Win7 64 or later to see if MSVCRT has remained the same over those OS versions. I would post the code but there are a number of things that have not been published yet.

This is the result I am getting on Win10 Professional.


    //////////////////////
    sprintf precision test
    \\\\\\\\\\\\\\\\\\\\\\

    Input  = 123456.1234567890123456
    Output = 123456.12345678901

    Press any key ....



Siekmanski

Win 8.1


    //////////////////////
    sprintf precision test
    \\\\\\\\\\\\\\\\\\\\\\

    Input  = 123456.1234567890123456
    Output = 123456.12345678901

    Press any key ....
Creative coders use backward thinking techniques as a strategy.

jj2007


Siekmanski

I tried to separate the integer and the fractional parts, but in 32 bit assembly the cvtpd2dq and cvtdq2pd instructions convert only 32 bit.
In 64 bit assembly 64 bits are converted.

At the moment I'm not able to run it in 64 bit assembly to test if we gain some resolution, probably not but....  :idea:
Maybe someone can test it in 64 bit assembly?


.data
align 16
Fabsmask   qword 7FFFFFFFFFFFFFFFh,7FFFFFFFFFFFFFFFh
float64bit real8 123456.1234567890123456
integer    real8 0.0
fraction   real8 0.0
szFloatNum db "%0.0f.%0.016f",0
szFloat64  db 64 dup (0)

.code
    movsd       xmm0,float64bit
    movsd       xmm2,xmm0
    cvtpd2dq    xmm1,xmm0     ; get rid of fractional part             
    cvtdq2pd    xmm1,xmm1     ; integer part
    subpd       xmm2,xmm1     ; subtract integer part from number to get fractional part
    andpd       xmm2,Fabsmask ; make fractional part absolute by removing sign bit
    movsd       integer,xmm1
    movsd       fraction,xmm2
   
    invoke      sprintf,addr szFloat64,addr szFloatNum,integer,fraction
    invoke      strlen,addr szFloat64
    lea         ecx,szFloat64
    movups      xmm0,[ecx+eax-16]
    movups      [ecx+eax-18],xmm0
    mov         byte ptr [ecx+eax-2],0

; print the szFloat64 string for the result.
; result with 32 bit assembly: 123456.1234567890060134
Creative coders use backward thinking techniques as a strategy.

hutch--

Marinus,

Like this ?

123456.1234567890060134
Press any key to continue...

I just plugged in your code into a 64 bit test piece, changed the 32 bit registers to 64 bit and used a 64 bit version of StrLen. Works fine.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include64\masm64rt.inc

    .data
      align 16
      Fabsmask   qword 7FFFFFFFFFFFFFFFh,7FFFFFFFFFFFFFFFh
      float64bit real8 123456.1234567890123456
      integer    real8 0.0
      fraction   real8 0.0
      szFloatNum db "%0.0f.%0.016f",0
      szFloat64  db 64 dup (0)

    .code

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

entry_point proc

    movsd       xmm0,float64bit
    movsd       xmm2,xmm0
    cvtpd2dq    xmm1,xmm0     ; get rid of fractional part             
    cvtdq2pd    xmm1,xmm1     ; integer part
    subpd       xmm2,xmm1     ; subtract integer part from number to get fractional part
    andpd       xmm2,Fabsmask ; make fractional part absolute by removing sign bit
    movsd       integer,xmm1
    movsd       fraction,xmm2
   
    invoke      vc_sprintf,addr szFloat64,addr szFloatNum,integer,fraction
    invoke      StrLen,addr szFloat64
    lea         rcx,szFloat64
    movups      xmm0,[rcx+rax-16]
    movups      [rcx+rax-18],xmm0
    mov         byte ptr [rcx+rax-2],0

    conout      ptr$(szFloat64),lf

    waitkey
    .exit

entry_point endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    end

nidud

#6
deleted

HSE


xx\simd3>asmc -c simd3.asm
Asmc Macro Assembler Version 2.28.04
Copyright (C) The Asmc Contributors. All Rights Reserved.

Assembling: simd3.asm

***********
ASCII build
***********

simd3.asm(47) : error A2070: invalid instruction operands

    "andpd       xmm2,Fabsmask ; make fractional part absolute by removing sign bit"

·······················································································································
xx\simd3>ml14 -c simd3.asm
Microsoft (R) Macro Assembler Version 14.00.23026.0
Copyright (C) Microsoft Corporation.  All rights reserved.

Assembling: simd3.asm

***********
ASCII build
***********

xx\simd3>link simd3.obj /subsystem:console
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.


xx\simd3>simd3
Hello Siemanski
123456.1234567890060134
Press any key to continue ...
Equations in Assembly: SmplMath

Siekmanski

Creative coders use backward thinking techniques as a strategy.

HSE

My previous post don't say it's 32bit, just showing AsmC error
Equations in Assembly: SmplMath

Siekmanski

Hi HSE,

maybe this works,

andpd       xmm2,oword ptr Fabsmask
or
andpd       xmm2,xmmword ptr Fabsmask
Creative coders use backward thinking techniques as a strategy.

avcaballero

My result executing marinus.exe:

123456.1234567890060134

HSE

Hi Siemanski!

Also work:

        Fabsmask   xmmword 7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFFh (idem oword)


But where is MASM compatibility?
Equations in Assembly: SmplMath

Siekmanski

QuoteBut where is MASM compatibility?

What do you mean exactly?
Creative coders use backward thinking techniques as a strategy.

aw27

I don't see any way of going there with SSE instructions.
Playing with FPU instructions we can obtain something like 123456.1234567890123444 which is closer.