Need an inline PASM function
RS_Jim
Posts: 1,764
Can I get one of you PASM experts to create an inline function out of this equation?
`
{to clarify: x is the Var that changes each pass}
result=(x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;}
`
all of the inputs and outputs are integers with the largest being 3300 and the smallest 0. Out min is 0 and out max is 200 in min lowest is 0 highest is 3300. X is automatically constrained by the environment and will never fall outside the the in_min and in_Max.
Thanks in advance.
Jim
Edit: added some clarification
Comments
I'm not a PASM expert, but do dabble a bit.
It sounds like you want to constrain an input between 0..3300 and scale it to 0..200.
In a timing test of both passing a variable to the method the first ran in 3.64us, the inline PASM version in 3.36us. If you need it to go faster you can install the PASM in the top part of the interpreter so you don't have the overhead of loading it every time.
Update: I tried the technique of installing the PASM code in the interpreter cog. It still requires a Spin interface, and is faster than native Spin, but not quite as fast as the inline version of the code.
Forget all that -- this is fastest (by 2x) since you're doing a simple mx equation.
The value for sca is 200 / 3300 * (2^32)
It's even faster (by 2x again) if your input value doesn't need to be constrained.
Thanks jon,
I have to think about about this for a while. What I see you doing is letting the compiler do some of the calculations on the numbers and only calculating on the fly the changing var.
Jim
@RS_Jim : It's worth mentioning here that @JonnyMac is using the standard PNut / PropTool Spin2 interpreter. If you use a different compiler or interpreter your results will vary -- for example, in flexspin the inline PASM is actually slower than the regular method, because flexspin is compiling the code to PASM anyway. Even in flexspin the SCA operator method that Jon posted seems to be the fastest approach, so that's probably the best way to go.
@ersmith,
Thanks for the input Eric. Yes I work in Linux and use only flexprop. I will see what happens when I use Jon's method.
Jim
What Eric didn't mention: On FlexSpin, you generally want to use the ASM/ENDASM style inline assembly rather than ORG/END. The former is processable by the optimizer and can thus be inlined...
You can go even faster if you use a somewhat lower precision approximation that can run on the fast multiplier
or with slightly different rounding:
Why, then, would you ask for PASM when you're using a tool that already outputs PASM?
I just simplified the expression. From your description, it would have been:
Internally, the sca instruction is identical to what Ada suggested. The constant used in that version represents 200/3300 but for 32 bits (Ada is using 16, which is probably fine for such a small output range).
Well, flexspin can very rarely choose MUL(S) over QMUL, so explicitly spelling things like that out in ASM is actual helpful. (In particular, both sides of a multiply need to either be a small constant, a word/byte sized variable or a zerox/signx sub-expression for flexspin to generate a MUL or MULS)