Page 3 of 4

Posted: Tue Mar 07, 2006 8:14 pm
by dracflamloc
normal floats are enough since the main purpose of this scripting language is for games or general apps, not engineering calculators ;)

Posted: Wed Mar 08, 2006 1:45 am
by Xombie
Updated to fix the problem with "-10". I hadn't added in support for negative numbers yet but they should be in now.

Still tossing around ideas for optimizations.

Posted: Wed Mar 08, 2006 2:35 am
by dracflamloc
Awesome

Posted: Wed Mar 08, 2006 6:16 pm
by dracflamloc
Wow thats fast and it seems to work great once I strip out the function part of your code. Still a bit on the slow side. Maybe I'll strip out the string concatenation and see hwo it goes

Posted: Thu Mar 09, 2006 6:49 pm
by Xombie
Here's a new version that should be pretty quick. I stripped out functions and string handling so it's pretty basic. I also completely rewrote the actual solving part. Completely different logic there :)

I compared it against Trond's latest code in some speed tests of 100,000 items.

"100+1" - 156ms on mine, 344ms on Trond's
"100.000000-1*6+7.9/8.334" - 813ms on mine, 1141ms on Trond's

Much faster compared to my old code. I'll see if I can squeeze out any other optimizations. I may be able to do something with the code that handles paranthesis and some other stuff.

http://www.seijin.net/Storage/xSolve/xSolve-Basic.pb

Let me know if something is broken. And take care :)

Posted: Thu Mar 09, 2006 7:14 pm
by Flype
Great work.

I always think that an eval command should be a built-in Purebasic feature.

maybe you can optimize a little by using structured pointer than using Peek/Poke.

Code: Select all

;-------------------

var = 123
Debug var

;-------------------

PokeL(@var,456)
Debug PeekL(@var)
Debug var

;-------------------

*ptr.LONG = @var

*ptr\l = 789
Debug *ptr\l
Debug var

;-------------------

Posted: Thu Mar 09, 2006 7:53 pm
by dracflamloc
As long as its cross-platform =)

Awesome Xombie I'll have to try it out in my scripting language tonight!

Posted: Thu Mar 09, 2006 11:40 pm
by Xombie
Another update with a lot of thanks to Flype :) I never knew what those .BYTE, .LONG etc... structures were for :D Now I know 8)

This time I'm getting 125ms for 100,000 iterations of "100+1" and 765ms for 100,000 iterations of "100.000000-1*6+7.9/8.334"

Something like 7 times my first expression evaluator. Not too shabby.

http://www.seijin.net/Storage/xSolve/xSolve-Basic.pb

Posted: Thu Mar 09, 2006 11:57 pm
by Killswitch
I really don't follow Flypes code - what's going on there?

Posted: Fri Mar 10, 2006 12:59 am
by Xombie
I've just uploaded another update. This one completely removes the xEvaluate() procedure in favor of handing paranthesis inside of the xs_Solve() procedure itself. Removes some overhead and speeds up processing of basic expressions (by a good bit) and expressions containing paranthesis (by a LOT).

Tests on 100,000 iterations of three different expressions...

"100+1" ... now takes about 94ms
"100.000000-1*6+7.9/8.334" ... still takes 765ms
"100.00 * (2 + (9-10) * 8) / 2" ... takes about 685-700ms

So the first case drops a good 30ms and the third case actually drops down about 284-269ms (it was 969ms previously).

http://www.seijin.net/Storage/xSolve/xSolve-Basic.pb

Isn't it amazing how big a speed difference you can make if you seriously work at speeding something up? And it's not always a matter of trying to tweak existing code. More and more often I find that I have to look at something in a completely different way to get it working right.

@Killswitch

I had to think about it a little bit but from what I can tell is this... Every variable has an address in memory. Bytes, Words, Longs, etc... all have a 4 byte address. The BYTE, WORD, LONG, FLOAT are structures using up 1, 2, 4, 4 bytes of memory respectively since they only contain .b, .w, .l, .f as members.

*ptr.LONG is creating a pointer to a LONG structure (4 bytes in memory) and is assigning *ptr to the address of 'var' (a long variable). So now *ptr is the address of the 'var' variable. The '\l' structure item is at offset 0 in the LONG structure.

Now if you look at the assembly output...

Code: Select all

; *ptr.LONG = @var 
  LEA    eax,[v_var]
  MOV    dword [p_ptr],eax
; 
; *ptr\l = 789 
  MOV    ebp,dword [p_ptr]
  MOV    dword [ebp],789

You'll see that first the address of 'var' is stored in *ptr. That's why it uses LEA rather than MOV. That's storing the address of 'var' in the eax register and then setting that as the value for *ptr.

Next, it takes the address from *ptr and stores that in the ebp register. That fourth command then stores the value 789 into the memory stored in register ebp. If it was...

Code: Select all

MOV ebp, 789
...it would just store 789 in ebp. Instead, it effectively says, "At address *ptr is the number 789. If I look at that address again, I want to see the LONG number 789". Using this is a shortcut at peek'ing/poke'ing memory addresses.

Well, that's how I look at it, anyway. Hopefully some ASM expert will drop by and correct me ^_^

Posted: Fri Mar 10, 2006 1:14 am
by Flype
seems correct xombie :wink:
much easier to use (when understood) than to explain :D

@killswitch, look at this snippets :

Code: Select all

string$ = "hello i'm a purebasic string !"

Debug "StructuredPointer method"

*pointer.CHARACTER = @string$

While *pointer\c
  Debug Chr(*pointer\c)
  *pointer + 1
Wend

Debug "PeekC() method"

*pointer = @string$

While PeekC(*pointer)
  Debug Chr(PeekC(*pointer))
  *pointer + 1
Wend

Code: Select all

Procedure test( *a.LONG, *b.BYTE, *c.WORD )
  *a\l = 123456789
  *b\b = 127
  *c\w = 32000
EndProcedure

test( @arg1.l, @arg2.b, @arg3.w )

Debug arg1
Debug arg2
Debug arg3

Code: Select all

Procedure LowerCase( *hString.CHARACTER )
  
  While *hString\c
    Select *hString\c
      Case 65 To 90 : *hString\c + 32
    EndSelect
    *hString + 1
  Wend
  
EndProcedure
Procedure UpperCase( *hString.CHARACTER )
  
  While *hString\c
    Select *hString\c
      Case 97 To 122 : *hString\c - 32
    EndSelect
    *hString + 1
  Wend
  
EndProcedure

hello$ = "Hello i'm a PureBasic string !"

LowerCase(@hello$) : Debug hello$
UpperCase(@hello$) : Debug hello$

Posted: Fri Mar 10, 2006 11:23 am
by Killswitch
Thanks for the examples, they've been a big help :). I couldn't run the snippets with the CHARACTER structures - is that a PB 4.0 feature (as I'm sticking with 3.94 until 4.0 final).

Posted: Fri Mar 10, 2006 12:13 pm
by Flype
yes it is.

( just replace CHARACTER by BYTE, and \c by \b :wink: )

Posted: Fri Mar 10, 2006 5:09 pm
by dracflamloc
Wow this is lightning. Great stuff.

It really improved the speed of the language quite a bit. I gotta optimize my logic code now so dracscript will be nice and fast =)

Posted: Mon Mar 13, 2006 7:07 pm
by Killswitch
This thread was the bane of my existance for many, many a night. I just had to make my code faster. I've completely rewritten my InfixToPostfix and SolvePostfix procedures and they can now do 100+1 a hundred times in about 580-591 milliseconds. It's not as fast as some of the other examples here but hey, it's almost 3 times as fast as my original code.

I've also hooked up my PostfixToASM procedure, which is why there's a couple of legacy procedures in there which it requires to work.

DOWNLOAD