At 14:35 07/10/1997 +1000, you wrote:
>Would anyone have an algorithm to do ArcSin of a value.
The standard algorithm is a polynomial Tchebichev approximation
which is obtain from an integral form.
Algorithm is finally a sum of (ai.X^n) and with 6 to 8 terms
you will reach a good precision. This is what it is used in
To do such calcul you will need:
- an algorithm to compute X^n
- an algorithm to convert binary number to "real" number
(exposant + mantissa)
- an algorithm to compute X*Y with real number
- another to add real number between themselve.
Unless you wish to spend a lot of time to write such a thing
with a PIC, I think the better is to use 'C' or 'BASIC' or 'PASCAL'
library for PIC.
Another idea would be to use a convertion table with only a few term
(perhaps 64 is enought) and then to compute a function which will
make an interpolation between 2 terms of the table. This will surely
be faster than polynomial approximation, but surely less precize.
The interpolation function will need some mathetical computation in
order to obtain something reliable, depending of researching precizion
perhaps a simple linear interpolation would be enough.
Finally, the algorithm will strongly depend of WHAT you want to do
with ArcSIN function ...
TONY NIXON 54964 wrote:
> Would anyone have an algorithm to do ArcSin of a value.
Here's an 8-bit one that uses a look up table plus first order
; The purpose of this routine is to take the arcsine of an
;8-bit number that ranges from 0 < x < 255/256. In other
;words, the input, x, is an unsigned fraction whose implicit
;divisor is 256.
; The output is in a conveniently awkward format of binary
;radians (brads?). The output corresponds to the range of zero
;to pi/2 for the normal arcsine function. Specifically, this
; arcsine(x) = real_arcsine(x/256) * 256 / (pi/2)
; where, real_arcsine returns the real arcsine of its argument
; The algorithm is a table look-up algorithm plus first order
;linear interpolation. The psuedo code is:
;unsigned char arcsine(unigned char x)
; unsigned char i;
; i = x >> 4;
; return(arcsin[i] + ((arcsin[i+1] - arcsin[i]) * (x & 0xf))/16);
; The accuracy is reasonable for x<150 or so. After that, the
;relatively steep arcsine severly deviates from a straight line
;approximation. The maximum error is around 5.
MOVWF temp ;Temporarily store the index
CALL arc_sine_table ;Get a2=asin( (x>>4) + 1)
MOVWF result ;Store temporarily in result
DECF temp,W ;Get the saved index
CALL arc_sine_table ;Get a1=asin( (x>>4) )
SUBWF result,W ;W=a2-a1, This is always
SUBWF result,F ;a1 = a1 - (a1-W) = W
As the comments say, the error is reasonably small for small
values of the input variable (uniquely named 'x'). If you want
to correct this, then the easiest thing to do is change the
last RETLW into another lookup table (note, what follows has
not been tested):
Then add code in the main routine that checks the
variable 'result_from_extended_table' to see if the
result is from the extended table. If the result was
obtained from the extended table, then the linear
interpolation doesn't need to be performed.
BTW, I've only verified that this routine works without
the extended look up table.
If your input is negative, then no problem. This is because:
y = arcsin(-x) = - arcsin(x)
In other words, for negative inputs change the sign of the
input variable, call the 'arcsin' routine, and then change
the sign of the result. However, be aware that there is not
any room in the 8-bit result for the sign bit. This could
be fixed many different ways. For example, you could shift the
result right one position and copy the sign to the MSB.
There are also arcsine identities that are useful for reducing
the domain, but they also require multiplication and division.
They would be useful as part of a higher order interpolation
algorithm. But this is beyond the scope of my time (right now).