|
2 | 2 |
|
3 | 3 | ## Introduction |
4 | 4 |
|
| 5 | +This function implements fast `Fixed` point `sin`, `cos` and `tan` functions. |
| 6 | +The ones that uses `Float` type (calling the Sinclair ROM) are much slower as FP Calculations |
| 7 | +are expensive. This variant is less precise but more suitable for games, for example. |
| 8 | + |
5 | 9 | `fSin` is the basis for the alternatives, since `COS(x)` can be calculated |
6 | | -from `SIN(x)` and `TAN(x)` from `COS(x)` and `SIN(x)`. |
| 10 | +from `SIN(x)` and `TAN(x)` as `SIN(x)` / `COS(x)`. |
| 11 | + |
| 12 | +!!! info "Note" |
| 13 | + This library is already bundled with Boriel BASIC.<br /> |
| 14 | + To use it just add `#include <fmath.bas>` |
| 15 | + at the beginning of your program. |
7 | 16 |
|
8 | 17 | The functions should be accurate to about 0.25%, and significantly faster. |
9 | 18 | If you need a lot of trig in your code, and it doesn't need to be pinpoint accuracy, these are good alternatives. |
10 | | -Note that they more or less acknowledge they are less accurate by returning values of type `Fixed` instead of type `Float`. |
11 | | -I did this because it should be fine for the actual accuracy returned, |
| 19 | +Note that they more or less acknowledge they are less accurate by returning values of type `Fixed` instead |
| 20 | +of type `Float`. |
| 21 | +It should be fine for the actual accuracy returned, |
12 | 22 | and `Fixed` numbers process faster and smaller than `Float` ones. |
13 | 23 |
|
14 | | -* Note that you need only include `fSin` if you only want Sines, but you need fSin to use `fCos` or `fTan`. |
| 24 | +* Note that you need only include `fSin` if you only want Sines, but you need `fSin` to use `fCos` or `fTan`. |
15 | 25 |
|
16 | 26 | * Note that these functions use degrees, not radians. |
17 | 27 |
|
18 | 28 | ## SINE Function |
19 | 29 |
|
20 | | -``` |
| 30 | +```vbnet |
21 | 31 | FUNCTION fSin(num as FIXED) as FIXED |
22 | | -DIM quad as byte |
23 | | -DIM est1,dif as uByte |
24 | | -
|
25 | | -'This change made now that MOD works with FIXED types. |
26 | | -'This is much faster than the repeated subtraction method for large angles (much > 360) |
27 | | -'while having some tiny rounding errors that should not significantly affect our results. |
28 | | -'Note that the result may be positive or negative still, and for SIN(360) might come out |
29 | | -'fractionally above 360 (which would cause issued) so the below code still is required. |
30 | | -
|
31 | | -IF num >= 360 THEN |
32 | | - num = num MOD 360 |
33 | | -ELSEIF num < 0 THEN |
34 | | - num = 360 - ABS(num) MOD 360 |
35 | | -END IF |
36 | | -
|
37 | | -IF num>180 then |
38 | | - quad=-1 |
39 | | - num=num-180 |
40 | | -ELSE |
41 | | - quad=1 |
42 | | -END IF |
43 | | -
|
44 | | -IF num>90 then num=180-num |
45 | | -
|
46 | | -num=num/2 |
47 | | -dif=num : rem Cast to byte loses decimal |
48 | | -num=num-dif : rem so this is just the decimal bit |
49 | | -
|
50 | | -
|
51 | | -est1=PEEK (@sinetable+dif) |
52 | | -dif=PEEK (@sinetable+dif+1)-est1 : REM this is just the difference to the next up number. |
53 | | -
|
54 | | -num=est1+(num*dif): REM base +interpolate to the next value. |
55 | | -
|
56 | | -return (num/255)*quad |
57 | | -
|
58 | | -
|
59 | | -sinetable: |
60 | | -asm |
61 | | -DEFB 000,009,018,027,035,044,053,062 |
62 | | -DEFB 070,079,087,096,104,112,120,127 |
63 | | -DEFB 135,143,150,157,164,171,177,183 |
64 | | -DEFB 190,195,201,206,211,216,221,225 |
65 | | -DEFB 229,233,236,240,243,245,247,249 |
66 | | -DEFB 251,253,254,254,255,255 |
67 | | -end asm |
| 32 | + DIM quad as byte |
| 33 | + DIM est1,dif as uByte |
| 34 | + |
| 35 | + 'This change made now that MOD works with FIXED types. |
| 36 | + 'This is much faster than the repeated subtraction method for large angles (much > 360) |
| 37 | + 'while having some tiny rounding errors that should not significantly affect our results. |
| 38 | + 'Note that the result may be positive or negative still, and for SIN(360) might come out |
| 39 | + 'fractionally above 360 (which would cause issued) so the below code still is required. |
| 40 | + |
| 41 | + IF num >= 360 THEN |
| 42 | + num = num MOD 360 |
| 43 | + ELSEIF num < 0 THEN |
| 44 | + num = 360 - ABS(num) MOD 360 |
| 45 | + END IF |
| 46 | + |
| 47 | + IF num > 180 then |
| 48 | + quad = -1 |
| 49 | + num = num - 180 |
| 50 | + ELSE |
| 51 | + quad = 1 |
| 52 | + END IF |
| 53 | + |
| 54 | + IF num > 90 THEN num = 180 - num |
| 55 | + |
| 56 | + num = num / 2 |
| 57 | + dif = num : REM Cast to byte loses decimal |
| 58 | + num = num - dif : REM so this is just the decimal bit |
| 59 | + |
| 60 | + est1 = PEEK(@sinetable + dif) |
| 61 | + dif = PEEK(@sinetable + dif + 1) - est1 : REM this is just the difference to the next up number. |
| 62 | + num = est1 + (num * dif) : REM base + interpolate to the next value. |
| 63 | + |
| 64 | + Return (num / 255) * quad |
| 65 | + |
| 66 | + sinetable: |
| 67 | + Asm |
| 68 | + DEFB 000,009,018,027,035,044,053,062 |
| 69 | + DEFB 070,079,087,096,104,112,120,127 |
| 70 | + DEFB 135,143,150,157,164,171,177,183 |
| 71 | + DEFB 190,195,201,206,211,216,221,225 |
| 72 | + DEFB 229,233,236,240,243,245,247,249 |
| 73 | + DEFB 251,253,254,254,255,255 |
| 74 | + End Asm |
68 | 75 | END FUNCTION |
69 | 76 | ``` |
70 | 77 |
|
71 | 78 | ## COSINE Function |
72 | 79 |
|
73 | | -``` |
| 80 | +```vbnet |
74 | 81 | FUNCTION fCos(num as FIXED) as FIXED |
75 | | - return fSin(90-num) |
| 82 | + Return fSin(90 - num) |
76 | 83 | END FUNCTION |
77 | 84 | ``` |
78 | 85 |
|
79 | 86 | ## TANGENT Function |
80 | 87 |
|
81 | | -``` |
| 88 | +```vbnet |
82 | 89 | FUNCTION fTan(num as FIXED) as FIXED |
83 | | - return fSin(num)/fSin(90-num) |
| 90 | + Return fSin(num) / fSin(90 - num) |
84 | 91 | END FUNCTION |
85 | 92 | ``` |
0 commit comments