I am supposed to write two procedures for calculating the Sine and the Cosine of a given angle but the problem is that the code should be compatible with 8087 math-coprocessor and 8087 does not have the FSIN/FCOS FPU instructions. I know a lot of trigonometric functions and identities and I just figured I would calculate the cosine and the sine of an angle usin the below formulas:

1+Tan^2(a) = 1/Cos^2(a)
1+Cot^2(a) = 1/Sin^2(a)

The problem is that since we are calculating the exponent, the base number would result in a positive number even if it is negative but in the second quadrant of the unit circle for example, only the sine of the angle can be positive and Cosine/Tangent and cotangent should be negative.

Could anybody help with these formulas or provide some other that solely work on Tan and Cosine/Sine?
Posted on 2006-12-03 04:01:18 by XCHG
Use maclaurin series!



Angles are in radian.
Posted on 2006-12-03 06:08:53 by roticv
Considering the computational complexity of the above series, I'd recommend using a LUT with spline interpolation of 4 or more points. LUT size 1024 or 4096 floats.
Posted on 2006-12-03 08:15:57 by Ultrano
you can make some predictions
for example, if the angle is between 1-25 degree, use (1-(x^x)/2) for cosine (ofcourse x should be radian)
Posted on 2006-12-03 10:42:02 by Dite
Posted on 2006-12-03 13:19:46 by ti_mo_n
Continue using the fptan function.

However, you must remember that on the 8087, the angle must not exceed pi/4 radians (45 degrees). Therefore, before you can start with your correct formulas,
a) you must determine the quadrant of the angle which you use to set the sign of the result,
b) determine in which half of the quadrant the angle is located in order to decide which of the sine or cosine you will compute,
c) determine the correct angle within the pi/4 range to use.

After computing the appropriate sine or cosine, you adjust the sign according to the quadrant of the angle.

Example: sin(108 degrees)
Quadrant: 2nd where the sine is positive
Section of quadrant: 1st half where the tangent is > 1. You will thus have to compute the cosine.
Correct angle: 90-(180-108)=18 degrees

sin(108 degrees) = cos(18 degrees)

Similarly, you could work out
sin(170 degrees) = sin(10 degrees)
sin(195 degrees) = -sin(15 degrees)
sin(300 degrees) = -cos(30 degrees)

With your knowledge of trigonometry, just make a list with paper & pencil of the 8 ranges of the circle, which equation to use for the sine and cosine in each region, how to adjust the required computing angle, and then write your algo accordingly.

Also remember that the fptan instruction needs the angle in radians.

Have fun

Posted on 2006-12-03 20:59:37 by Raymond

That would be slow even if it worked. I mean, you need a really fast Internet connection to use that as a math coprocessor.

Posted on 2006-12-04 02:09:24 by Maverick
rotfl :lol:
Posted on 2006-12-04 08:23:22 by ti_mo_n

    This is ground that has been plowed before.  Your best bet is the incremental Taylor series (ITS) with a look up table (LUT).  Once you make a LUT table of sines, you also have a LUT of cosines.  This is because the sine lags the cosine by 90 degrees.  Furthermore the cos is the derivative of the sine and vice versa with a change of sign.  This makes it easy to implement the ITS and it converges fast.  Forget about the tan in this case.  The following links show you how it is done.  Ratch

Posted on 2006-12-04 15:26:10 by Ratch
He's telling you that you can use the SAME table for sine and for cosine, as long as you're aware that they're 90 degrees out of phase.
For TAN, you can implement 'rise over run' algorithm...
If you need further help with this or other trigonometry, just ask :)
Posted on 2006-12-06 06:56:17 by Homer
Thank you so much guys. As for trigonometry, I'm not saying that I'm good with it but I can do a lot things with it and really use it but the whole 8087 FPU is giving me a headache.

You guys have provided so many information and links that might take me over a week to read thoroughly. I just wanted to say thank you and that I'll post back here as soon as I write the algorithm.
Posted on 2006-12-07 07:55:46 by XCHG
Just use GOOGLE and WINSOCK.

Connect to google.com on port 80

GET /search?hl=en&q=sin%28X%29&btnG=Google+Search HTTP/1.1
Accept: */*
Referer: http://www.google.com/
Accept-Language: en-us
Host: www.google.com
Connection: Keep-Alive

Replace the X in the first line with the radian value

You'll get a lot of useless data in but just parse it for this.
<img src=/images/calc_img.gif></td><td>&nbsp;</td><td nowrap><font size=+1><b>sin(X) = -0.544021111</b>
So basically
strSearch db 'calc_img.gif'
strSearch2 db '= '
strSearch3 db '</b>'
_format db '%s',0
mov eax, ;"calc"
mov ebx, ;"_img"
mov ecx, ;".gif"
mov esi,Recv_Buffer ;;;make sure it's zeroed out before filling  it
inc esi
test ,-1 ;;;buffer should be zero padded
jz .fail
cmp eax,
jne .loop
cmp ebx,
jne .loop
cmp ecx,
jne .loop
;;;now find the equal sign+space "= "
mov ax,word
inc esi
cmp word,-1
jz .fail
cmp word,ax
jne .loop2
;;;now null the end of the answer
mov edi,esi
mov eax,
inc edi
cmp ,-1
jz .fail
cmp ,eax
jne .loop3
mov byte,0
;;;out put your result
push esi
push _format
call ;;;msvcrt.dll

MATH FORMULAS ARE FOR NERDS!!!!!!!!!! All the cool kids use GOOGLE.

Posted on 2006-12-08 01:30:22 by r22
Posted on 2006-12-08 03:19:18 by Homer
Haha r22, you're insane - I love it ^_^

Shouldn't be too hard hacking something together using either raw winsock or wininet... if you're into that kinda thing. Great to see yet another way of nullifying fast processors ^_^
Posted on 2006-12-08 04:25:53 by f0dder
I examined a lot of right triangles in differnet quadrants of the unit circle and saw that the sine of an angle in the upper semi circle of the unit circle is always positive and in the lower semi circle always negative. So all I had to do was to compare the angle with PI.

The below code is written in MASM in a quick and dirty fashion and leaves the sine of the __Angle parameter in ST(0) as an extended precision value. __Angle should be in range 0 to 359 degrees.

Posted on 2007-01-01 01:24:59 by XCHG
1- I guess that you did not read my post about the limitations of the 8087 for the fptan instruction if you are still aiming for that platform.
2- Whether it's the 8087 or latest FPU, trig functions require angle parameters to be expressed in radians. You definitely won't get correct results with angles in degrees.
3- You don't have to store any value of "pi" in memory to load it on the FPU. That constant is hard coded in the FPU and you can load it with the "fldpi" instruction.
4- Although you seem to be keeping track of the content of FPU registers (which is an excellent practice), you are disregarding your own data. i.e.
FDIVP  ST(1) , ST(0)        ; ST(0) = 1/ST(0) = Sine
By that time, the st(1) was empty!!!!! :shock: :sad:

leaves the sine of the __Angle parameter in ST(0) as an extended precision value.

Even if your code was correct, that statement would be totally wrong. Because you are using a single-precision value in your computation (the value of pi you put on the stack), the result CANNOT have a precision any better than single-precision.

If you had studied the following tutorial, it may have prevented some of the above mistakes:


Posted on 2007-01-01 20:41:11 by Raymond

1- I did read your post about FPU limitations on 8086 machines and this is, as I stated, just a quick and dirty shot at writing such procedure. Clearly, the code is not compatible with 8086 because of the DWORD MOV instructions.

2- I don?t know why think I am not aware of that fact. I just said that the angle should be in the range 0?359 degrees. Can?t we drive at the maximum speed of 100 kilometers per hour if our car?s speedometer is based on miles? Of course we should just convert those values.

3- I really don?t know why I did that. I think for some reason I thought the FPU equivalent of doing such thing could be slower and when I compared, mine loaded with 17 clock cycles more than the ?FLDPI? FPU instruction. I should definitely change that.

4- Oh no; at that step, prior the execution of the ?FDIVP? FPU instruction, ST(1) is +1.0 which I loaded after loading the value of PI into the stack but *after* the execution of this instruction, yes, the content of the ST(0) is divided by ST(1) and ST(0) is popped and replaced by ST(1).

Am I really not using extended precision? Isn?t that a REAL10 PI value that I am loading into the stack and then the FPU? I just stored the hard-coded PI value in the PFU into the stack as an extended precision value and it gives the same result!

Oh and about the ?SimplyFPU? tutorial, oh yeah I read it every time I want to code PFU-related programs. That?s a must for me. Thank you and also thanks for your comments and the time you put on looking at the code. I appreciate it.

Posted on 2007-01-03 00:06:01 by XCHG