News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Ascii to DWORD replacement

Started by hutch--, January 25, 2013, 01:58:28 PM

Previous topic - Next topic

jj2007

Intel(R) Celeron(R) M CPU        420  @ 1.60GHz (SSE3)

680     cycles for 10 * atodwJJ
3967    cycles for 10 * a2dw

682     cycles for 10 * atodwJJ
3860    cycles for 10 * a2dw


A factor five, not bad ;-)

frktons

Quote
testing 1:      1        ok
testing -1:     -1       ok
testing 123:    123      ok
testing 123456789:      123456789        ok
testing 1234567890:     source too long
testing -9876x54321:    x is an invalid character
testing -987.654321:    . is an invalid character
testing -987654321:     -987654321       ok
testing -9876543210:    source too long
testing -987654h:       h is an invalid character
48      bytes for atodw
11      bytes for Dec2Dword
6       bytes for Dec2Dword2
62      bytes for atodwJJ

Intel(R) Pentium(R) 4 CPU 3.20GHz (SSE3)
++++++++++++++++++++
269     cycles for 10 * Dec2Dword
1921    cycles for 10 * atodwJJ
7708    cycles for 10 * a2dw

269     cycles for 10 * Dec2Dword
1911    cycles for 10 * atodwJJ
7478    cycles for 10 * a2dw

266     cycles for 10 * Dec2Dword
1949    cycles for 10 * atodwJJ
7799    cycles for 10 * a2dw

266     cycles for 10 * Dec2Dword
1919    cycles for 10 * atodwJJ
7819    cycles for 10 * a2dw

270     cycles for 10 * Dec2Dword
1926    cycles for 10 * atodwJJ
7735    cycles for 10 * a2dw
There are only two days a year when you can't do anything: one is called yesterday, the other is called tomorrow, so today is the right day to love, believe, do and, above all, live.

Dalai Lama

FORTRANS

Hi,

#1 factor of ~6.4
#2 factor of ~5.3
#3 factor of ~5.9

Regards,

Steve N.

testing 1: 1 ok
testing -1: -1 ok
testing 123: 123 ok
testing 123456789: 123456789 ok
testing 1234567890: source too long
testing -9876x54321: x is an invalid character
testing -987.654321: . is an invalid character
testing -987654321: -987654321 ok
testing -9876543210: source too long
testing -987654h: h is an invalid character
48 bytes for atodw
11 bytes for Dec2Dword
6 bytes for Dec2Dword2
62 bytes for atodwJJ

pre-P4 (SSE1)
loop overhead is approx. 28/10 cycles


107 cycles for 10 * Dec2Dword
781 cycles for 10 * atodwJJ
4991 cycles for 10 * a2dw

107 cycles for 10 * Dec2Dword
781 cycles for 10 * atodwJJ
4992 cycles for 10 * a2dw

107 cycles for 10 * Dec2Dword
781 cycles for 10 * atodwJJ
4992 cycles for 10 * a2dw

107 cycles for 10 * Dec2Dword
781 cycles for 10 * atodwJJ
4994 cycles for 10 * a2dw

107 cycles for 10 * Dec2Dword
781 cycles for 10 * atodwJJ
4996 cycles for 10 * a2dw


--- ok --- testing 1: 1 ok
testing -1: -1 ok
testing 123: 123 ok
testing 123456789: 123456789 ok
testing 1234567890: source too long
testing -9876x54321: x is an invalid character
testing -987.654321: . is an invalid character
testing -987654321: -987654321 ok
testing -9876543210: source too long
testing -987654h: h is an invalid character
48 bytes for atodw
11 bytes for Dec2Dword
6 bytes for Dec2Dword2
62 bytes for atodwJJ

pre-P4++++++++++++++++++++
164 cycles for 10 * Dec2Dword
1285 cycles for 10 * atodwJJ
6793 cycles for 10 * a2dw

163 cycles for 10 * Dec2Dword
1277 cycles for 10 * atodwJJ
6908 cycles for 10 * a2dw

162 cycles for 10 * Dec2Dword
1276 cycles for 10 * atodwJJ
6784 cycles for 10 * a2dw

162 cycles for 10 * Dec2Dword
1277 cycles for 10 * atodwJJ
6797 cycles for 10 * a2dw

161 cycles for 10 * Dec2Dword
1272 cycles for 10 * atodwJJ
6791 cycles for 10 * a2dw


--- ok --- testing 1: 1 ok
testing -1: -1 ok
testing 123: 123 ok
testing 123456789: 123456789 ok
testing 1234567890: source too long
testing -9876x54321: x is an invalid character
testing -987.654321: . is an invalid character
testing -987654321: -987654321 ok
testing -9876543210: source too long
testing -987654h: h is an invalid character
48 bytes for atodw
11 bytes for Dec2Dword
6 bytes for Dec2Dword2
62 bytes for atodwJJ

Intel(R) Pentium(R) M processor 1.70GHz (SSE2)
loop overhead is approx. 17/10 cycles


63 cycles for 10 * Dec2Dword
682 cycles for 10 * atodwJJ
4038 cycles for 10 * a2dw

63 cycles for 10 * Dec2Dword
683 cycles for 10 * atodwJJ
4037 cycles for 10 * a2dw

63 cycles for 10 * Dec2Dword
690 cycles for 10 * atodwJJ
4093 cycles for 10 * a2dw

64 cycles for 10 * Dec2Dword
684 cycles for 10 * atodwJJ
3935 cycles for 10 * a2dw

63 cycles for 10 * Dec2Dword
690 cycles for 10 * atodwJJ
4016 cycles for 10 * a2dw


--- ok ---

dedndave

it would be nice if we were also testing "atou", posted by Hutch
and "a2dwDave", posted by me   :P

http://masm32.com/board/index.php?topic=1357.msg13648#msg13648
http://masm32.com/board/index.php?topic=1357.msg13646#msg13646

i ran a simple test of these 2, and "atou" is ~12 cycles faster than "a2dwDave" (4294967295)
but, a2dwDave handles signed/unsigned, and is UNICODE aware

    atou: 52bytes
a2dwDave: 43bytes
    atou: 64 64 64 63 63
a2dwDave: 75 75 75 75 75

hutch--

Dave,

At the going rate the code in "atou" is probably what I will end up using, I have a very fast version by Lingo as well and either of these will work as an exact drop in replacement for Iczelion's old algo. It part of the old rule that you never ever ever change the functionality of a published function as it breaks many folks code. I have versions that do both signed and unsigned but they are not drop in replacements for the old proc.

jj2007

atou is certainly fast, but... no negative numbers, no error check ::)

testing a2dwDave, 1:      1
testing -1:     -1
testing 123:    123
testing 123456789:      123456789
testing 1234567890:     1234567890
testing -9876x54321:    -1293319729
testing -987.654321:    -1278719729
testing -987654321:     -987654321
testing -9876543210:    -1286608618
testing -987654h:       -9876596

Intel(R) Celeron(R) M CPU        420  @ 1.60GHz (SSE3)
loop overhead is approx. 17/10 cycles


322     cycles for 10 * atou
516     cycles for 10 * a2dwDave
677     cycles for 10 * atodwJJ
3991    cycles for 10 * a2dw

322     cycles for 10 * atou
517     cycles for 10 * a2dwDave
677     cycles for 10 * atodwJJ
4026    cycles for 10 * a2dw

321     cycles for 10 * atou
515     cycles for 10 * a2dwDave
677     cycles for 10 * atodwJJ
4005    cycles for 10 * a2dw

323     cycles for 10 * atou
515     cycles for 10 * a2dwDave
677     cycles for 10 * atodwJJ
4035    cycles for 10 * a2dw

321     cycles for 10 * atou
515     cycles for 10 * a2dwDave
677     cycles for 10 * atodwJJ
4034    cycles for 10 * a2dw

dedndave

i understand, Hutch - no prob
i just saw how easy it was to add that support - lol
i guess i could take out the sign check and it would fit in there
UNICODE support would not affect any pre-existing software

prescott w/htt
Intel(R) Pentium(R) 4 CPU 3.00GHz (SSE3)
loop overhead is approx. 29/10 cycles

559     cycles for 10 * atou
742     cycles for 10 * a2dwDave
1291    cycles for 10 * atodwJJ
4607    cycles for 10 * a2dw

559     cycles for 10 * atou
774     cycles for 10 * a2dwDave
1421    cycles for 10 * atodwJJ
5146    cycles for 10 * a2dw

559     cycles for 10 * atou
843     cycles for 10 * a2dwDave
1227    cycles for 10 * atodwJJ
4560    cycles for 10 * a2dw

563     cycles for 10 * atou
834     cycles for 10 * a2dwDave
1407    cycles for 10 * atodwJJ
5041    cycles for 10 * a2dw

563     cycles for 10 * atou
789     cycles for 10 * a2dwDave
1231    cycles for 10 * atodwJJ
4651    cycles for 10 * a2dw

jj2007

Quote from: hutch-- on January 27, 2013, 06:45:53 AM...exact drop in replacement for Iczelion's old algo. It part of the old rule that you never ever ever change the functionality of a published function as it breaks many folks code.

Masmlib.chm:
Quoteatodw

atodw proc uses edi esi String:PTR BYTE

Description
atodw converts a decimal string to dword.

Note that the parameter String is an address of DWORD size.

Parameter
1. String The address of the decimal string to convert

Return Value
The DWORD value is returned in eax.

The algo I posted does exactly what the documentation says. In addition, it has two new features:

a) error checking:
   print src, ":", 9
   invoke atodwJJ, src
   .if Sign?
      print "source too long", 13, 10
   .else
      add edx, "0"
      .if !Zero?
         push edx
         print esp,  " is an invalid character", 13, 10
         pop edx
      .else
         print str$(eax), 9, " ok", 13, 10
      .endif
   .endif


b) it reads negative numbers correctly, where the old algo would silently produce an error, a behaviour that is not documented in masmlib.chm

How that can break existing code remains a mystery for a poor noob like me ;)

(besides, lazy as I am, Val and MovVal offer better value for money :icon_mrgreen:)

hutch--

 :biggrin:

Unsigned DWORDs don't have negative numbers. While I have nothing against multi-purpose functions, I am of the view that existing functions should never suffer from "function creep" as it ends up being the source of broken code.

jj2007

Quote from: hutch-- on January 27, 2013, 05:21:58 PM
Unsigned DWORDs don't have negative numbers.

.if Instr("decimal string", "unsigned")
   Print "you are right"
.else
   Print "RTFM (i.e. \Masm32\help\Masmlib.chm)"
.endif
;)

(strange that a phrase search for "undocumented non-feature" gives only 18 hits ::))

MichaelW

It seems to me that "decimal string" specifies a string of decimal digits, and "signed decimal string" specifies a string of decimal digits with a sign. And there is nothing in the atodw source to deal with a sign.

Well Microsoft, here's another nice mess you've gotten us into.

jj2007

#26
Quote from: MichaelW on January 27, 2013, 07:36:54 PM
It seems to me that "decimal string" specifies a string of decimal digits, and "signed decimal string" specifies a string of decimal digits with a sign.

Michael,

Show me one example on the World Wide Web where the absence of the word "signed" implies that the conversion is unsigned.

Or one HLL that converts "-123" to 253123

Or one example of code that gets broken because it relies on invoke atodw, chr$("-123") returning
253123

But this is stuff for one of the endless religious debates on whether or eax, eax destroys a precious register or not, so I better pull out here :lol:

testing :       0 is an invalid character
testing 0:      0        ok
testing 1:      1        ok
testing -1:     -1       ok
testing 123:    123      ok
testing +123:   123      ok
testing          +123:  123      ok
testing 123456789:      123456789        ok
testing 1234567890:     1234567890       ok
testing 9876543210:     source too long
testing -9876x54321:    x is an invalid character
testing -987.654321:    . is an invalid character
testing -987654321:     -987654321       ok
testing -9876543210:    source too long
testing -987654h:       h is an invalid character
80      bytes for atodwJJ

Intel(R) Celeron(R) M CPU        420  @ 1.60GHz (SSE3)
loop overhead is approx. 17/10 cycles


324     cycles for 10 * atou
519     cycles for 10 * a2dwDave
699     cycles for 10 * atodwJJ
3930    cycles for 10 * a2dw

323     cycles for 10 * atou
518     cycles for 10 * a2dwDave
698     cycles for 10 * atodwJJ
3970    cycles for 10 * a2dw


EDIT: Attached code renamed to "Asc2DwSafe". Actually, since it's still more than a factor five faster than the current Masm32 a2dw, it should correctly be named Asc2DwSafeAndFast ;-)

hutch--

Have a look at Iczelion's old algo and you will see that it does not test for sign, it is a DWORD algo and that means unsigned. Now I am sure you could add all sorts of functionality to any algo you like, check the registry for a valid registration number, use a lookup table to test if the string is in EBCDIC format but the original request was for a drop in replacement for Iczelion's old algo, not a redesign full of stuff that the old algo did not have.

dedndave

well - the question is - does it break existing code
certainly, when we went from v10 to v11, several functions were updated to allow unicode support
the behaviour of many things changed - the "drop-in" functionality rule was bent all to hell

personally, this is a function that i rarely use
i can see using it for user input, primarily
which means that, before i pass a string to the function,
i have to do a lot of pre-parsing to ensure the user doesn't think "xyzzy" is a number
i have to test or limit the number of digits and, in some cases, the format of the string

i might also use a function like this to convert text file info
i think the same rules would apply

at least, that's if i am writing a real-world app
if i am writing a trivial, the rules can be loser   :P

hutch--

The catch is with this view that it justifies function creep where my own view is if you want a function with extra functionality, you write a new one. As far as UNICODE support, I have tended to write 2 functions, one ASCII, the other UNICODE and switch between them based on the equate. This allows better code for each than switching between them.

Rather than a pseudo philosophical debate I was hoping that someone had a faster one than "atou" or Lingo's faster one, the only reason why I have not used Lingo's algo is it does an untidy exit with a JMP that messes up the call/ret pairing and through testing interferes with the following code.

There are basically two ideas of library design being applied here, I see library modules as components where the alternative is trying to build objects, the difference between assembler programming and high level languages.  :P