• Welcome to Theos PowerBasic Museum 2017.

News:

Attachments are only available to registered users.
Please register using your full, real name.

Main Menu

Converting Text into FLoating Point Numbers in Assembler.

Started by Charles Pegge, June 27, 2007, 11:59:23 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Charles Pegge


Updated 28 June 2007 with "E+" notation, and now returns Error code

This does the same job as  number=VAL(numbertext) but about 2.5 times faster, (In Freebasic anyway)

It may look long and complicated but most of the opcodes used are very cheap in clock cycles. There is also a degree of parallel processing with the CPU doing things while the FPU crunches its numbers.

This supports extended precision floating point and E notation. Some tests are provided. It reads up to eighteen decimal digits, ignoring the rest, which should match the resolution of the x87 FPU.


'
' DVAL
' text to floating point number conversion in Assembler

' Charles E V Pegge
' 28 June 2007

' FreeBasic ver 0.16b
' using inline assembler.




function dval(byval p as byte ptr, byval le as long, byref v as double) as long
dim as long m10=10
dim as long m1e4=1e4
dim as long m1e8=1e8
dim as long tm1,tm2
dim as long sgg=0
dim as long sgx=0
'
asm
'======================'
xor eax,eax           ' clear eax
fldz                  ' load zero to fpu
mov ebx,[le]          ' length
mov ecx,[p]           ' text pointer
'======================'
a0:                    ' loop for reaching the sign or first digit
cmp ebx,0             ' is it zero or less?
jle a2                ' then terminate now with zero
mov al,[ecx]          ' first char
cmp al,44             ' is it
jl aa                 ' if less then .. aa treat as leading space
jz a2                 ' terminate now with zero
cmp al,45             ' is it '-' sign?
jnz a1                ' then
dec ebx               ' is it last char?
jle a2                ' then terminate now with zero
inc ecx               ' next char
mov dword ptr [sgg],1 ' set neg flag
jmp a1                ' procede to a1
'======================'
aa:                    ' skip space chars
dec ebx               ' down count chars to go
inc ecx               ' next char
jmp a0                ' loop back to a0
'======================'
a1:                    ' begin collecting digits
mov al,[ecx]          ' load next char
dec ebx               ' down count
jl a2                 ' no more digits so goto E section
inc ecx               ' ready next char
cmp al,46             ' is this a dot?
jz bb                 ' if so then goto decimals section
cmp al,48             ' check lower limit
jl a2                 ' below '0' char so goto E section
cmp al,57             ' check upper limit
jg a2                 ' above '9' so goto E section
fimul dword ptr [m10] ' premultiply the accummulator st
sub al,48             ' base to 0
mov [tm1],eax         ' store in temp
fiadd dword ptr [tm1] ' add from temp
jmp a1                ' repeat for next digit
'======================'
a2:                    ' relay to E section
mov esi,ecx           ' transfer index to esi
mov cl,al             ' transfer char to cl
jmp c2                ' go on to E section
'======================'
bb:                    ' decimal point
cmp ebx,0             ' is this the last char?
jle c2                ' then finish now
mov esi,ecx
xor edx,edx           ' clear edx
mov eax,1             ' set eax to 10
xor ecx,ecx           ' clear to act as char reg
xor edx,edx           ' while edx:eax is used as a digit multiplier
'======================'
xor edi,edi           ' zero the decimal places tally
b1:                    ' do loop
                       ' start of decimals loop
dec ebx               ' any more chars?
jl c1                 ' finish now
mov cl,[esi]          ' get next char
inc esi               ' ready for next char
cmp cl,48             ' range check lower
jl c1                 ' finish
cmp cl,57             ' range check upper
jg c1                 ' check for E numbers
cmp edi,18            ' limit of decimal places
jge b1                ' too many decimal places error so ignore rest
fimul dword ptr [m10] ' premultiply accummulator
mul dword ptr[m10]    ' multiply eax ready for next loop
inc edi               ' tally decimal places
cmp edi,9             ' is this 9 dps done ?
jnz b2                ' skip if not
mov [tm2],eax         ' move the multiplier to a second stage
mov eax,1             ' reset the multiplier
b2:                    ' continue
sub cl,48             ' base  to zero
mov [tm1],ecx         ' store to tm1
fiadd dword ptr [tm1] ' add from tm1
jmp b1                ' repeat for next digit
'======================'

'======================'
cc:                    '
c1:                    ' decimal place scaling
mov [tm1],eax         ' save eax to tm1
fidiv dword ptr [tm1] ' divide by this factor (up to 9 decimal places)
cmp dword ptr [tm2],0 ' is there a second stage?
jz c2                 ' skip if not
fidiv dword ptr [tm2] ' divide by this factor (up to 9 more decimal places)
'======================'
c2:                    ' inserted E number checking procedure here:
'======================'
ee:                    ' E & e numbers
cmp cl,&h45           ' is it E?
jz e1                 ' okay
cmp cl,&h65           ' is it e?
jz e1                 ' okay
jmp c3                ' else skip E numbers
'----------------------'
e1:                    ' ready to procede with E number
xor eax,eax           ' clear eax
mov ch,10             ' x10 multiplier
dec ebx               ' check if end
jl c3                 ' finish if at end
mov cl,[esi]          ' next char
inc esi               ' increment char pointer
cmp cl,43             ' is it a '+' sign?
jz e1a                ' then ignore and get next char
cmp cl,45             ' it it a '-' sign
jnz e2                ' skip if not
mov dword ptr [sgx],1 ' set negation flag
'----------------------'
e1a:                   ' get the next digit
dec ebx               ' check if at end
jl c3                 ' then finish now
mov cl,[esi]          ' get a digit
inc esi               ' increment char pointer
'----------------------'
e2:                    ' first digit is ready
cmp cl,48             ' is it less then 0?
jz e1a                ' ignore leading zeros, get next
jl c3                 ' then finish
cmp cl,57             ' is it greater than 9?
jg c3                 ' then finish
sub cl,48             ' base to zero
mov al,cl             ' move to accummulator
dec ebx               ' check at end
jl e3                 ' if so then procede to process
mov cl,[esi]          ' next digit
inc esi               ' next digit pointer
cmp cl,48             ' check below 0
jl e3                 ' if so then procede to process
cmp cl,57             ' check above 9
jg e3                 ' if so then procede to process
mul ch                ' multiply accum by 10
sub cl,48             ' base digit to zero
add al,cl             ' add it to accum
dec ebx               ' check if at end
jl e3                 ' then process
mov cl,[esi]          ' get the final digit
inc esi               ' ready for next xhar
cmp cl,48             ' is it below 0
jl e3                 ' then process
cmp cl,57             ' is it above 9
jg e3                 ' then process
mul ch                ' multiply accum by 10
sub cl,48             ' base digit to zero
add al,cl             ' add to accum
adc ah,0              ' carry thru to ah
'----------------------'
'                      ' ERROR CHECKS
'cmp eax,307           ' E too great
'jle ee1               '
'mov eax,1             ' error code: E out of range
'jmp xx                '
ee1:                   '
dec ebx               ' Excess E digits
jl e3                 '
mov cl,[esi]          '
inc esi
cmp cl,48             '
jl e3                 '
cmp cl,57             '
jg e3                 '
mov eax,2             ' error code: E overflow
jmp xx                '
'----------------------'
e3:                    ' E is now in binary form in eax
cmp dword ptr [sgx],1  ' is it negative
jz e4m                 ' if so then go to divider section
'----------------------'
e4:                    ' multiply by 10 for each E number
cmp eax,8             ' step of 10^8
jl e5                 ' try smaller step
fimul dword ptr [m1e8]'
sub eax,8             '
jmp e4                ' repeat
e5:                    '
cmp eax,4             ' step of 10^4
jl e6                 ' try smaller step
sub eax,4             '
fimul dword ptr [m1e4]'
jmp e5                ' repeat
e6:                    '
cmp eax,0             ' step of 10^1
jle c3                ' done
dec eax               '
fimul dword ptr [m10] '
jmp e6                ' repeat till ecx=0
'======================'

'======================'
e4m:                   ' divide by 10 for each negative E number
cmp eax,8             ' step of 10^8
jl e5m                ' try smaller step
fidiv dword ptr [m1e8]'
sub eax,8             '
jmp e4m               ' repeat
e5m:                   '
cmp eax,4             ' step of 10^4
jl e6m                ' try smaller step
sub eax,4             '
fidiv dword ptr [m1e4]'
jmp e5m               ' repeat
e6m:                   '
cmp eax,0             ' step of 10^1
jle c3                ' done
dec eax               '
fidiv dword ptr [m10] '
jmp e6m               ' repeat till ecx=0
'======================'

'======================'
c3:                    '
cmp dword ptr [sgg],1 ' check if sign '-'
jnz c4                ' skip if not.
fchs                  ' otherwise change the accummulator sign
'======================'
c4:                    '
mov eax,[v]           ' get pointer to result
fstp qword ptr [eax]  ' store the result and pop the FPU stack                  '
xor eax,eax           ' no error
'======================'
xx:
mov [function],eax    ' return error code
'======================'
end asm
end function

  '--------'
  '  TEST  '
  '--------'


dim as string s="-123456.6789e5"
dim v as double
dim erc as long

erc=dval( strptr(s),len(s),v )
print "input:  ";s
print "output: ";v
print
print "Error code: ";erc

  '-----------------'
  '  EXTREME TESTS  '
  '-----------------'
print
print "TESTS AND INTERPRETATIONS"
s=" 0":  dval( strptr(s),len(s),v ): print s;"    ",v
s=" ":   dval( strptr(s),len(s),v ): print s;"    ",v
s=" ,":  dval( strptr(s),len(s),v ): print s;"    ",v
s=" -":  dval( strptr(s),len(s),v ): print s;"    ",v
s=" .":  dval( strptr(s),len(s),v ): print s;"    ",v
s=" 0,1":dval( strptr(s),len(s),v ): print s;"    ",v
s=" 1,2":dval( strptr(s),len(s),v ): print s;"    ",v
s=" 0.1,2":dval( strptr(s),len(s),v ): print s;"    ",v
s=" !3":dval( strptr(s),len(s),v ): print s;"    ",v
s=" $3":dval( strptr(s),len(s),v ): print s;"    ",v
s=" $3$4":dval( strptr(s),len(s),v ): print s;"    ",v
s=" 3-4":dval( strptr(s),len(s),v ): print s;"    ",v
s=" 3.4":dval( strptr(s),len(s),v ): print s;"    ",v
s=" .000456":dval( strptr(s),len(s),v ): print s;"    ",v
s=" 3.4.5":dval( strptr(s),len(s),v ): print s;"    ",v
s=" 3e2":dval( strptr(s),len(s),v ): print s;"    ",v
s=" 3.4e2":dval( strptr(s),len(s),v ): print s;"    ",v
s=" -.4e2":dval( strptr(s),len(s),v ): print s;"    ",v
s=" .04e2":dval( strptr(s),len(s),v ): print s;"    ",v
s=" .04e-2":dval( strptr(s),len(s),v ): print s;"    ",v
s=" -.04e-2":dval( strptr(s),len(s),v ): print s;"    ",v
s=" -.0012345E-10":erc=dval( strptr(s),len(s),v ): print s;"    ",v
print
s=" .123456789012345678E-10":erc=dval( strptr(s),len(s),v ): print s;"    ",v
s=" 123456789012345678E+10":erc=dval( strptr(s),len(s),v ): print s;"    ",v
s=" 12345678.9012345678E100!?*":erc=dval( strptr(s),len(s),v ): print s;"    ",v
's=" 123456789012345678E999":erc=dval( strptr(s),len(s),v ): print s;"    ",v
s=" 123456.789012345678E000300":erc=dval( strptr(s),len(s),v ): print s;"    ",v
's=" 1234567890.12345678E300":erc=dval( strptr(s),len(s),v ): print s;"    ",v

print
print "Error Code: ";erc

  '-------------'
  ' SPEED TEST  '
  '-------------'

dim i as long
dim t as double
dim td as double
dim tv as double

t=timer
for i=1 to 100000
dval(strptr(s),len(s),v)
next
td=timer-t

t=timer
for i=1 to 100000
v=val(s)
next
tv=timer-t
print
print "for 100000 repeats: "
print "dval time:     ";td
print " val time:     ";tv
print
print "Speed factor:  ";tv/td



Charles Pegge

#1
Here is the PowerBasic equivalent.

However it performs equally as well as Powerbasic's VAL(). So as it stands, there is no advantage in using dval() in a PB program.



'
' DVAL
' text to floating point number conversion in Assembler

' Charles E V Pegge
' 28 June 2007

' PowerBasic  PBWin Ver 8x
' using inline assembler.

#COMPILE EXE
#DIM ALL
#REGISTER NONE


FUNCTION dval(BYVAL p AS BYTE PTR, BYVAL le AS LONG, BYREF v AS DOUBLE) AS LONG
DIM m10  AS LONG: m10=10
DIM m1e4 AS LONG: m1e4=1e4
DIM m1e8 AS LONG: m1e8=1e8
DIM tm1  AS LONG
DIM tm2  AS LONG
DIM sgg  AS LONG
DIM sgx  AS LONG
'

'======================'
!xor eax,eax           ' clear eax
!fldz                  ' load zero to fpu
!mov ebx,le            ' length
!mov ecx,p             ' text pointer
'======================'
a0:                    ' loop for reaching the sign or first digit
!cmp ebx,0             ' is it zero or less?
!jle a2                ' then terminate now with zero
!mov al,[ecx]          ' first char
!cmp al,44             ' is it
!jl aa                 ' if less then .. aa treat as leading space
!jz a2                 ' terminate now with zero
!cmp al,45             ' is it '-' sign?
!jnz a1                ' then
!dec ebx               ' is it last char?
!jle a2                ' then terminate now with zero
!inc ecx               ' next char
!mov dword ptr sgg,1   ' set neg flag
!jmp a1                ' procede to a1
'======================'
aa:                    ' skip space chars
!dec ebx               ' down count chars to go
!inc ecx               ' next char
!jmp a0                ' loop back to a0
'======================'
a1:                    ' begin collecting digits
!mov al,[ecx]          ' load next char
!dec ebx               ' down count
!jl a2                 ' no more digits so goto E section
!inc ecx               ' ready next char
!cmp al,46             ' is this a dot?
!jz bb                 ' if so then goto decimals section
!cmp al,48             ' check lower limit
!jl a2                 ' below '0' char so goto E section
!cmp al,57             ' check upper limit
!jg a2                 ' above '9' so goto E section
!fimul dword ptr m10   ' premultiply the accummulator st
!sub al,48             ' base to 0
!mov tm1,eax           ' store in temp
!fiadd dword ptr tm1   ' add from temp
!jmp a1                ' repeat for next digit
'======================'
a2:                    ' relay to E section
!mov esi,ecx           ' transfer index to esi
!mov cl,al             ' transfer char to cl
!jmp c2                ' go on to E section
'======================'
bb:                    ' decimal point
!cmp ebx,0             ' is this the last char?
!jle c2                ' then finish now
!mov esi,ecx
!xor edx,edx           ' clear edx
!mov eax,1             ' set eax to 10
!xor ecx,ecx           ' clear to act as char reg
!xor edx,edx           ' while edx:eax is used as a digit multiplier
'======================'
!xor edi,edi           ' zero the decimal places tally
b1:                    ' do loop
                       ' start of decimals loop
!dec ebx               ' any more chars?
!jl c1                 ' finish now
!mov cl,[esi]          ' get next char
!inc esi               ' ready for next char
!cmp cl,48             ' range check lower
!jl c1                 ' finish
!cmp cl,57             ' range check upper
!jg c1                 ' check for E numbers
!cmp edi,18            ' limit of decimal places
!jge b1                ' too many decimal places error so ignore rest
!fimul dword ptr m10   ' premultiply accummulator
!mul dword ptr m10     ' multiply eax ready for next loop
!inc edi               ' tally decimal places
!cmp edi,9             ' is this 9 dps done ?
!jnz b2                ' skip if not
!mov tm2,eax           ' move the multiplier to a second stage
!mov eax,1             ' reset the multiplier
b2:                    ' continue
!sub cl,48             ' base  to zero
!mov tm1,ecx           ' store to tm1
!fiadd dword ptr tm1   ' add from tm1
!jmp b1                ' repeat for next digit
'======================'

'======================'
cc:                    '
c1:                    ' decimal place scaling
!mov tm1,eax           ' save eax to tm1
!fidiv dword ptr tm1   ' divide by this factor (up to 9 decimal places)
!cmp dword ptr tm2,0   ' is there a second stage?
!jz c2                 ' skip if not
!fidiv dword ptr tm2   ' divide by this factor (up to 9 more decimal places)
'======================'
c2:                    ' inserted E number checking procedure here:
'======================'
ee:                    ' E & e numbers
!cmp cl,&h45           ' is it E?
!jz e1                 ' okay
!cmp cl,&h65           ' is it e?
!jz e1                 ' okay
!jmp c3                ' else skip E numbers
'----------------------'
e1:                    ' ready to procede with E number
!xor eax,eax           ' clear eax
!mov ch,10             ' x10 multiplier
!dec ebx               ' check if end
!jl c3                 ' finish if at end
!mov cl,[esi]          ' next char
!inc esi               ' increment char pointer
!cmp cl,43             ' is it a '+' sign?
!jz e1a                ' then ignore and get next char
!cmp cl,45             ' it it a '-' sign
!jnz e2                ' skip if not
!mov dword ptr sgx,1   ' set negation flag
'----------------------'
e1a:                   ' get the next digit
!dec ebx               ' check if at end
!jl c3                 ' then finish now
!mov cl,[esi]          ' get a digit
!inc esi               ' increment char pointer
'----------------------'
e2:                    ' first digit is ready
!cmp cl,48             ' is it less then 0?
!jz e1a                ' ignore leading zeros, get next
!jl c3                 ' then finish
!cmp cl,57             ' is it greater than 9?
!jg c3                 ' then finish
!sub cl,48             ' base to zero
!mov al,cl             ' move to accummulator
!dec ebx               ' check at end
!jl e3                 ' if so then procede to process
!mov cl,[esi]          ' next digit
!inc esi               ' next digit pointer
!cmp cl,48             ' check below 0
!jl e3                 ' if so then procede to process
!cmp cl,57             ' check above 9
!jg e3                 ' if so then procede to process
!mul ch                ' multiply accum by 10
!sub cl,48             ' base digit to zero
!add al,cl             ' add it to accum
!dec ebx               ' check if at end
!jl e3                 ' then process
!mov cl,[esi]          ' get the final digit
!inc esi               ' ready for next xhar
!cmp cl,48             ' is it below 0
!jl e3                 ' then process
!cmp cl,57             ' is it above 9
!jg e3                 ' then process
!mul ch                ' multiply accum by 10
!sub cl,48             ' base digit to zero
!add al,cl             ' add to accum
!adc ah,0              ' carry thru to ah
'----------------------'
'                      ' ERROR CHECKS
'cmp eax,307           ' E too great
'jle ee1               '
'mov eax,1             ' error code: E out of range
'jmp xx                '
ee1:                   '
!dec ebx               ' Excess E digits
!jl e3                 '
!mov cl,[esi]          '
!inc esi
!cmp cl,48             '
!jl e3                 '
!cmp cl,57             '
!jg e3                 '
!mov eax,2             ' error code: E overflow
!jmp xx                '
'----------------------'
e3:                    ' E is now in binary form in eax
!cmp dword ptr sgx,1   ' is it negative
!jz e4m                ' if so then go to divider section
'----------------------'
e4:                    ' multiply by 10 for each E number
!cmp eax,8             ' step of 10^8
!jl e5                 ' try smaller step
!fimul dword ptr m1e8  '
!sub eax,8             '
!jmp e4                ' repeat
e5:                    '
!cmp eax,4             ' step of 10^4
!jl e6                 ' try smaller step
!sub eax,4             '
!fimul dword ptr m1e4  '
!jmp e5                ' repeat
e6:                    '
!cmp eax,0             ' step of 10^1
!jle c3                ' done
!dec eax               '
!fimul dword ptr m10   '
!jmp e6                ' repeat till ecx=0
'======================'

'======================'
e4m:                   ' divide by 10 for each negative E number
!cmp eax,8             ' step of 10^8
!jl e5m                ' try smaller step
!fidiv dword ptr m1e8  '
!sub eax,8             '
!jmp e4m               ' repeat
e5m:                   '
!cmp eax,4             ' step of 10^4
!jl e6m                ' try smaller step
!sub eax,4             '
!fidiv dword ptr m1e4  '
!jmp e5m               ' repeat
e6m:                   '
!cmp eax,0             ' step of 10^1
!jle c3                ' done
!dec eax               '
!fidiv dword ptr m10   '
!jmp e6m               ' repeat till ecx=0
'======================'

'======================'
c3:                    '
!cmp dword ptr sgg,1   ' check if sign '-'
!jnz c4                ' skip if not.
!fchs                  ' otherwise change the accummulator sign
'======================'
c4:                    '
!mov eax,v             ' get pointer to result
!fstp qword ptr [eax]    ' store the result and pop the FPU stack                  '
!xor eax,eax           ' no error
'======================'
xx:
!mov function, eax     ' return error code
'======================'

END FUNCTION






  '--------'
  '  TEST  '
  '--------'

GLOBAL ps AS STRING

SUB sprint (s AS STRING)
ps=ps+s+$CR
END SUB

SUB tprint (s AS STRING,d AS STRING)
ps=ps+s+CHR$(8)+CHR$(9)+CHR$(9)+d+$CR
END SUB

FUNCTION PBMAIN() AS LONG


DIM s AS STRING: s="-123456.6789e5"
DIM v AS DOUBLE
DIM erc AS LONG

erc=dval( STRPTR(s),LEN(s),v )
sprint ("input:  "+s)
sprint ("output: "+STR$(v))
sprint ("")
sprint ("Error code: "+STR$(erc))

  '-----------------'
  '  EXTREME TESTS  '
  '-----------------'
sprint("")
sprint ("TESTS AND INTERPRETATIONS")
s=" 0":  dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" ":   dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" ,":  dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" -":  dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" .":  dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" 0,1":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" 1,2":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" 0.1,2":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" !3":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" $3":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" $3$4":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" 3-4":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" 3.4":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" .000456":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" 3.4.5":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" 3e2":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" 3.4e2":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" -.4e2":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" .04e2":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" .04e-2":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" -.04e-2":dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" -.0012345E-10":erc=dval( STRPTR(s),LEN(s),v ): tprint( s,STR$(v))
sprint("")
s=" .123456789012345678E-10":erc=dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" 123456789012345678E+10":erc=dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
s=" 12345678.9012345678E100!?*":erc=dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
's=" 123456789012345678E999":erc=dval( strptr(s),len(s),v ): tprint (s,str$(v))
s=" 123456.789012345678E000300":erc=dval( STRPTR(s),LEN(s),v ): tprint (s,STR$(v))
's=" 1234567890.12345678E300":erc=dval( strptr(s),len(s),v ): tprint (s,str$(v))

sprint("")
sprint ("Error Code: "+STR$(erc))

  '-------------'
  ' SPEED TEST  '
  '-------------'

DIM i AS LONG
DIM t AS DOUBLE
DIM td AS DOUBLE
DIM tv AS DOUBLE

t=TIMER
FOR i=1 TO 100000
dval(STRPTR(s),LEN(s),v)
NEXT
td=TIMER-t

t=TIMER
FOR i=1 TO 100000
v=VAL(s)
NEXT
tv=TIMER-t
sprint("")
sprint( "for 100000 repeats: ")
tprint( "dval time:",STR$(td))
tprint( " val time:",STR$(tv))
sprint("")
tprint( "Speed factor:",STR$(tv/td))

MSGBOX ps

ps=""

END FUNCTION