
Expression Evaluator
-
- Addict
- Posts: 1648
- Joined: Mon Sep 20, 2004 3:52 pm
- Contact:
-
- Addict
- Posts: 1648
- Joined: Mon Sep 20, 2004 3:52 pm
- Contact:
-
- Addict
- Posts: 1648
- Joined: Mon Sep 20, 2004 3:52 pm
- Contact:
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

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

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.
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
;-------------------
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
-
- Addict
- Posts: 1648
- Joined: Mon Sep 20, 2004 3:52 pm
- Contact:
Another update with a lot of thanks to Flype
I never knew what those .BYTE, .LONG etc... structures were for
Now I know
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



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
-
- Enthusiast
- Posts: 731
- Joined: Wed Apr 21, 2004 7:12 pm
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...
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...
...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 ^_^
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
Well, that's how I look at it, anyway. Hopefully some ASM expert will drop by and correct me ^_^
seems correct xombie
much easier to use (when understood) than to explain
@killswitch, look at this snippets :

much easier to use (when understood) than to explain

@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$
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
-
- Enthusiast
- Posts: 731
- Joined: Wed Apr 21, 2004 7:12 pm
-
- Addict
- Posts: 1648
- Joined: Mon Sep 20, 2004 3:52 pm
- Contact:
-
- Enthusiast
- Posts: 731
- Joined: Wed Apr 21, 2004 7:12 pm
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
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
~I see one problem with your reasoning: the fact is thats not a chicken~