PASM math
Bobb Fwed
Posts: 1,119
This has had to come have up before, but I couldn't find a whole lot with the search...
I am looking for common math uses in PASM. I have found some algorithms, but there has to be better ones out there. I found propeller.wikispaces.com/MATH as well, but the functions are HUGE!
Here is what I found for multiplying:
problem: only 16 bit inputs, but fast
Here is mine:
problem: much slower especially when multiplying two large numbers
I also have one that works as a signed multiplier.
Here is the divider I found:
problem: it can't divide (for example) 350/100 ... unless a whole number is returned, the output is unexpected
And finally...
Square root I found:
and power I made:
problem: slow and dependent on [noparse][[/noparse]slow] multiply for large numbers
I'm a function-oriented-man so I have formatted these so the inputs are always par1, par2, etc. and the output is always in ret_val. It may make it slightly slower, but portability is very handy.
It seems there should be a collection of PASM math "functions" lying around somewhere. Any input?
I am looking for common math uses in PASM. I have found some algorithms, but there has to be better ones out there. I found propeller.wikispaces.com/MATH as well, but the functions are HUGE!
Here is what I found for multiplying:
problem: only 16 bit inputs, but fast
'----- MULTIPLY -------------------------------- ' par1 * par2 ' 16-bit max input, 32-bit results multiply2 SHL par1, #16 ' get multiplicand into x[noparse][[/noparse]31..16] MOV midx, #16 ' ready for 16 multiplier bits SHR par2, #1 WC ' get initial multiplier bit into c :loop IF_C ADD par2, par1 WC ' conditionally add multiplicand into product RCR par2, #1 WC ' get next multiplier bit into c. ' while shift product DJNZ midx, #:loop ' loop until done MOV ret_val, par2 ' return product multiply2_ret RET
Here is mine:
problem: much slower especially when multiplying two large numbers
'----- MULTIPLY -------------------------------- ' par1 * par2 ' 32-bit in/out ... slower than multiply2 multiply MOV ret_val, #0 CMP par1, #0 WZ ' if multiplyer of 0 return 0 IF_Z JMP #multiplyend CMP par2, #0 WZ ' if multiplyer of 0 return 0 IF_Z JMP #multiplyend CMP par1, par2 WZ, WC IF_Z_OR_NC JMP #:skip MOV accum, par1 ' these commands help speed up process by reducing number of loops MOV par1, par2 MOV par2, accum :skip MOV midx, par2 :loop ADD ret_val, par1 DJNZ midx, #:loop multiplyend multiply_ret RET
I also have one that works as a signed multiplier.
Here is the divider I found:
problem: it can't divide (for example) 350/100 ... unless a whole number is returned, the output is unexpected
'----- DIVIDE ---------------------------------- ' par1 / par2 divide SHL par2, #15 ' get divisor into y[noparse][[/noparse]30..15] MOV midx, #16 ' ready for 16 quotient bits :loop CMPSUB par1, par2 WC ' if y =< x then subtract it, set C RCL par1, #1 ' rotate c into quotient, shift dividend DJNZ midx, #:loop ' loop until done MOV ret_val, par1 ' move to return divide_ret RET
And finally...
Square root I found:
'----- SQUARE ROOT ----------------------------- ' sqrt(par1) root MOV accum, #0 ' reset accumulator MOV par2, #0 ' reset root MOV midx, #16 ' ready for 16 root bits :loop SHL par1, #1 WC ' rotate top two bits of y RCL accum, #1 ' ..into accumulator SHL par1, #1 WC RCL accum, #1 SHL par2, #2 ' determine next bit of root OR par2, #1 CMPSUB accum, par2 WC SHR par2, #2 RCL par2, #1 DJNZ midx, #:loop ' loop until done MOV ret_val, par2 ' move to return root_ret RET
and power I made:
problem: slow and dependent on [noparse][[/noparse]slow] multiply for large numbers
'----- POWER ----------------------------------- ' par1^par2 -- par1 to-the-power-of par2 pow CMP par2, #0 WZ ' if power of 0 return 1 IF_Z MOV ret_val, #1 IF_Z JMP #powend CMP par2, #1 WZ ' if power of 1 return par1 IF_Z MOV ret_val, par1 IF_Z JMP #powend MOV accum, par1 ' make copy MOV m2idx, par2 ' repeat par2 times SUB m2idx, #1 MOV ret_val, par1 :loop MOV par1, ret_val ' use results in next use MOV par2, accum CALL #multiply DJNZ m2idx, #:loop powend pow_ret RET
I'm a function-oriented-man so I have formatted these so the inputs are always par1, par2, etc. and the output is always in ret_val. It may make it slightly slower, but portability is very handy.
It seems there should be a collection of PASM math "functions" lying around somewhere. Any input?
Comments
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
The Spin interpreter contains some functions that are sort of small but well, a bit slow. If you look at the FFT source (referenced in that page) there are some other routines. they are faster but also longer. You cannot have everything.
btw: I wrote that page , most of the routines, BCD, binary and FFT, I'm missing some good fixed point ones. Suggestions are always welcome, pieces of code too.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
http://www.amazon.com/Math-Toolkit-Real-Time-Programming-Crenshaw/dp/1929629095/ref=sr_1_1?ie=UTF8&s=books&qid=1234243646&sr=1-1
Jack