Difference between revisions of "ESM Math Library"
imported>JustTim (fixed a bug in stage 21) |
imported>JustTim |
||
(37 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
This is a complete quest+function set-up. For a modular system, see [[:Category:Stage Functions|Stage Functions]] | |||
=== Welcome === | === Welcome === | ||
to the Stage Function Repository! The goal of the Repository is, to create a huge database of available functions all using the method described in the article [[Simulating_new_functions|Simulating new functions]]. | to the Stage Function Repository! The goal of the Repository is, to create a huge database of available functions all using the method described in the article [[Simulating_new_functions|Simulating new functions]]. | ||
If you've written such a function and you think it might be helpful to others, don't hesitate to contribute to this repository. | If you've written such a function and you think it might be helpful to others, don't hesitate to contribute to this repository. | ||
=== | === The easy way: Math Library ESM === | ||
The easiest way to use the functions shown in this article is by using [http://www.hazardx.com/details.php?file=68 this ESM Math Library]. To use it copy the ESM file to your oblivion data folder and select it as an additional master file when loading your mod with the Construction Set. By doing this all the necessary setup steps are already done for you. All you need to do to use a function is to call it. Examples of how to call each function are shown below in the "Usage" blocks of each stage function. | |||
Be aware that other users of your mod will need the Library too to run it. | |||
Download: [http://www.hazardx.com/details.php?file=68 ESM Math Library v1.0]. | |||
=== Do it yourself: Step by Step === | |||
To get this up and running follow there simple setup steps: | To get this up and running follow there simple setup steps: | ||
* Open any Plugin you wish or create a new one with the Construction Set | * Open any Plugin you wish or create a new one with the Construction Set | ||
Line 11: | Line 19: | ||
* Create a new stage in this quest for each function you want to use from this repository and copy all code from it's section in this article to the related Result Script textbox. Make sure to select the right stage number for the function. | * Create a new stage in this quest for each function you want to use from this repository and copy all code from it's section in this article to the related Result Script textbox. Make sure to select the right stage number for the function. | ||
* That's it! You should be able to use them now! | * That's it! You should be able to use them now! | ||
=== Note for Stage function writers === | |||
It's great to see so many contributions. Keep it up. | |||
However, please try to make things as clear as possible for users. This repository will be most useful to users who aren't that good at scripting themselves. It isn't safe to assume that every user is going to check through the code of a function before using it. | |||
At the least, each stage function should make clear what its inputs and outputs are. E.g. for trig functions this means specifying whether inputs/outputs are in degrees or radians. | |||
It also means making it clear (preferably outside the function code) when a certain function uses another one - e.g. Arccos calling Arcsin. Users should ideally not have to look through the code of each stage function to check whether it uses other stage functions. | |||
Making things clear shouldn't take long, and will be helpful to users. It's also no more than your code deserves :). | |||
=== Quest Script === | === Quest Script === | ||
Line 21: | Line 40: | ||
; Constants | ; Constants | ||
float pi | float pi | ||
float | float radToDeg | ||
float degToRad | |||
; Function In- and Output | ; Function In- and Output | ||
Line 33: | Line 53: | ||
;S5 FUNCTION sqrt | ;S5 FUNCTION sqrt | ||
float sqr | float sqr | ||
;S6 FUNCTION NormalizeAngle360 | |||
;S7 FUNCTION NormalizeAngle180 | |||
;S10 FUNCTION Hypotenuse | ;S10 FUNCTION Hypotenuse | ||
Line 53: | Line 77: | ||
float t5 | float t5 | ||
float t6 | float t6 | ||
;S17 FUNCTION SinCosTan 3 | |||
;float ang | |||
;float sin | |||
;float cos | |||
;float t2 | |||
;S20 FUNCTION Arcsine 1 | ;S20 FUNCTION Arcsine 1 | ||
Line 76: | Line 106: | ||
float tan | float tan | ||
;float ang | ;float ang | ||
;S40 FUNCTION NaturalLogarithm | |||
short LN_n | |||
;float t1 | |||
;float t2 | |||
;float t3 | |||
;float t5 | |||
;float t7 | |||
;float t9 | |||
;float t11 | |||
float t13 | |||
;S50 FUNCTION Exponentiation | |||
float base | |||
float exponent | |||
;float t1 | |||
;float t2 | |||
;float t3 | |||
float t4 | |||
;float t5 | |||
;float t6 | |||
;float t7 | |||
float t8 | |||
;float t9 | |||
float t10 | |||
;float t11 | |||
; Set constants first | ; Set constants first | ||
Line 81: | Line 137: | ||
if doOnce == 0 | if doOnce == 0 | ||
set pi to 3.1415927 | set pi to 3.1415927 | ||
set | set radToDeg to 180.0/pi ;always multiply to convert | ||
set degToRad to 1/radToDeg | |||
set fQuestDelayTime to 30 | set fQuestDelayTime to 30 | ||
Line 87: | Line 144: | ||
endif | endif | ||
End</pre> | End</pre> | ||
This Quest Script already contains everything needed for the following functions. | |||
=== Stage 5: Square Root === | === Stage 5: Square Root === | ||
Based on [[Square_Root|Square Root]] Article | Based on [[Square_Root|Square Root]] Article | ||
Code to include in FunctionQuestScript: | |||
<pre>;S5 FUNCTION sqrt | |||
float sqr</pre> | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float sqrt(float input) | <pre>;FUNCTION float sqrt(float input) | ||
if (f.fin1 <= 0) | if (f.fin1 <= 0) | ||
Line 102: | Line 167: | ||
set f.fout to f.sqr | set f.fout to f.sqr | ||
endif</pre> | endif</pre> | ||
Usage in another script: | |||
<pre>;CALL float sqrt(float input) | |||
set f.fin1 to myVarForInput | |||
setStage f 5 | |||
set myResult to f.fout</pre> | |||
=== Stage 6: Normalize Angle (0 till 360) === | |||
Takes an Angle and normalizes it to a range from 0 to 360 degrees. | |||
This is a functional loop! | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float NormalizeAngle360(float Angle) | |||
if (f.fin1 >= 0) && (f.fin1 <= 360) | |||
set f.fout to f.fin1 | |||
else | |||
if f.fin1 < 0 | |||
set f.fin1 to (f.fin1 + 360) | |||
else | |||
set f.fin1 to (f.fin1 - 360) | |||
endif | |||
;CALL float NormalizeAngle360(float angle) | |||
setStage f 6 | |||
endif</pre> | |||
Usage in another script: | |||
<pre>;CALL float NormalizeAngle360(float angle) | |||
set f.fin1 to myVarForAngle | |||
setStage f 6 | |||
set myResult to f.fout</pre> | |||
=== Stage 7: Normalize Angle (-180 till 180) === | |||
Takes an Angle and normalizes it to a range from -180 to 180 degrees. | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float NormalizeAngle180(float Angle) | |||
if (f.fin1 < 0) || (f.fin1 > 360) | |||
;CALL float NormalizeAngle360(float Angle) | |||
setStage f 6 | |||
else | |||
set f.fout to f.fin1 | |||
endif | |||
if f.fout > 180 | |||
set f.fout to (f.fout - 360) | |||
endif</pre> | |||
Usage in another script: | |||
<pre>;CALL float NormalizeAngle180(float angle) | |||
set f.fin1 to myVarForAngle | |||
setStage f 7 | |||
set myResult to f.fout</pre> | |||
=== Stage 10: Hypotenuse === | === Stage 10: Hypotenuse === | ||
Takes the length of both Cathesus in a right triangle as two floats.<br> | |||
Returns the length of the Hypotenuse as a float.<br> | |||
Code to include in FunctionQuestScript: | |||
<pre>;S10 FUNCTION Hypotenuse | |||
float n</pre> | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float Hypotenuse(float CathetusA, float CathetusB) | <pre>;FUNCTION float Hypotenuse(float CathetusA, float CathetusB) | ||
set f.n to ((f.fin1 * f.fin1) + (f.fin2 * f.fin2)) | set f.n to ((f.fin1 * f.fin1) + (f.fin2 * f.fin2)) | ||
; | ;CALL float sqrt(float input) | ||
set f.fin1 to f.n | set f.fin1 to f.n | ||
setStage f 5 | setStage f 5 | ||
;fout is already the result</pre> | ;fout is already the result</pre> | ||
Usage in another script: | |||
<pre>;CALL float Hypotenuse(float CathetusA, float CathetusB) | |||
set f.fin1 to myVarForCathetusA | |||
set f.fin2 to myVarForCathetusB | |||
setStage f 10 | |||
set myResult to f.fout</pre> | |||
=== Stage 15: Sin Cos Tan === | === Stage 15: Sin Cos Tan === | ||
Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | ||
Takes an angle in DEGREES.<br> | |||
Returns three floats: sin, cos and tan of the angle.<br> | |||
Code to include in FunctionQuestScript: | |||
<pre>;S15 FUNCTION SinCosTan | |||
float ang | |||
float sin | |||
float cos | |||
float exp</pre> | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float,float,float SinCosTan(float Angle) | <pre>;FUNCTION float,float,float SinCosTan(float Angle) | ||
;Taylor Series Variant 1 - script by Galerion | ;Taylor Series Variant 1 - script by Galerion | ||
;CALL float NormalizeAngle180(float Angle) | |||
setStage f 7 | |||
set f.ang to f.fout | |||
;approximate | ;approximate | ||
set f.ang to (f.ang | set f.ang to (f.ang*f.degToRad) | ||
set f.cos to 1 | set f.cos to 1 | ||
set f.exp to f.ang | set f.exp to f.ang | ||
Line 148: | Line 287: | ||
set f.fout to f.sin | set f.fout to f.sin | ||
if f.cos == 0 | |||
set f.cos to 0.0001 | |||
endif | |||
set f.fout2 to f.cos | set f.fout2 to f.cos | ||
set f.fout3 to (f.sin/f.cos) ;tan</pre> | set f.fout3 to (f.sin/f.cos) ;tan</pre> | ||
Usage in another script: | |||
<pre>;CALL float,float,float SinCosTan(float Angle) | |||
set f.fin1 to myVarForAngle | |||
setStage f 15 | |||
set myResultSin to f.fout | |||
set myResultCos to f.fout2 | |||
set myResultTan to f.fout3</pre> | |||
=== Stage 16: Sin Cos Tan 2 === | === Stage 16: Sin Cos Tan 2 === | ||
Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | ||
Takes an angle in DEGREES.<br> | |||
Returns three floats: sin, cos and tan of the angle.<br> | |||
Code to include in FunctionQuestScript: | |||
<pre>;S16 FUNCTION SinCodTan 2 | |||
float ang | |||
float sin | |||
float cos | |||
float t1 | |||
float t2 | |||
float t5 | |||
float t6</pre> | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float,float,float SinCosTan(float Angle) | <pre>;FUNCTION float,float,float SinCosTan(float Angle) | ||
;Taylor Series Variant 2 - script by JOG | ;Taylor Series Variant 2 - script by JOG | ||
;CALL float NormalizeAngle180(float Angle) | |||
setStage f 7 | |||
set f.ang to f.fout | |||
set f.t1 to (f.ang | set f.t1 to (f.ang*f.degToRad) | ||
set f.t2 to (f.t1*f.t1) | set f.t2 to (f.t1*f.t1) | ||
set f.t5 to (f.t2*f.t2*f.t1) | set f.t5 to (f.t2*f.t2*f.t1) | ||
Line 172: | Line 333: | ||
set f.fout to f.sin | set f.fout to f.sin | ||
if f.cos == 0 | |||
set f.cos to 0.0001 | |||
endif | |||
set f.fout2 to f.cos | set f.fout2 to f.cos | ||
set f.fout3 to f.sin/f.cos ;tan</pre> | set f.fout3 to f.sin/f.cos ;tan</pre> | ||
Usage in another script: | |||
<pre>;CALL float,float,float SinCosTan(float Angle) | |||
set f.fin1 to myVarForAngle | |||
setStage f 16 | |||
set myResultSin to f.fout | |||
set myResultCos to f.fout2 | |||
set myResultTan to f.fout3</pre> | |||
=== Stage 17: Sin Cos Tan 3 === | |||
Based on a posting by Galsiah in [http://www.elderscrolls.com/forums/index.php?showtopic=428015 THIS THREAD] | |||
Takes an angle in DEGREES.<br> | |||
Returns three floats: sin, cos and tan of the angle.<br> | |||
Code to include in FunctionQuestScript: | |||
<pre>;S17 FUNCTION SinCosTan 3 | |||
float ang | |||
float sin | |||
float cos | |||
float t2</pre> | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float,float,float SinCosTan(float Angle) | |||
;script by Galsiah | |||
;CALL float NormalizeAngle360(float Angle) | |||
setStage f 6 | |||
set f.ang to (f.fout*f.degToRad) | |||
set f.n to 1 | |||
if (f.ang > 4.7123) | |||
Set f.ang to (f.ang - 6.2832) | |||
elseif ( f.ang > 1.5708 ) | |||
Set f.ang to (f.ang - 3.1416) | |||
Set f.n to -1 | |||
endif | |||
set f.t2 to (f.ang * f.ang) | |||
set f.sin to (f.ang*(1 - (f.t2*(0.16605 - (0.00761*f.t2))))) | |||
set f.sin to (f.sin*f.n) | |||
set f.cos to (1 - (f.t2*(0.4967 - (0.03705*f.t2)))) | |||
set f.cos to (f.cos*f.n) | |||
set f.fout to f.sin | |||
set f.fout2 to f.cos | |||
;NB division is safe, since the above cos approximation cannot return 0. | |||
set f.fout3 to f.sin/f.cos ;tan</pre> | |||
Usage in another script: | |||
<pre>;CALL float,float,float SinCosTan(float Angle) | |||
set f.fin1 to myVarForAngle | |||
setStage f 17 | |||
set myResultSin to f.fout | |||
set myResultCos to f.fout2 | |||
set myResultTan to f.fout3</pre> | |||
=== Stage 20: Arcsine === | === Stage 20: Arcsine === | ||
Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | ||
Takes a float.<br> | |||
Returns the Arcsine in DEGREES as a float.<br> | |||
Code to include in FunctionQuestScript: | |||
<pre>;S20 FUNCTION Arcsine | |||
float sin | |||
float ang | |||
float n</pre> | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float Arcsine(float sin) | <pre>;FUNCTION float Arcsine(float sin) | ||
;Abramowitz/Stegun Approximation - script by JOG | ;Abramowitz/Stegun Approximation - script by JOG | ||
Line 188: | Line 421: | ||
set f.n to (f.ang+(f.n/f.ang))/2 | set f.n to (f.ang+(f.n/f.ang))/2 | ||
set f.fout to f. | set f.fout to f.radToDeg*(1.5707963 - f.n*(1.5707288 - 0.2121144*f.sin+0.0742610*f.sin*f.sin - 0.0187293*f.sin*f.sin*f.sin))</pre> | ||
Usage in another script: | |||
<pre>;CALL float Arcsine(float sin) | |||
set f.fin1 to myVarForSin | |||
setStage f 20 | |||
set myResult to f.fout</pre> | |||
=== Stage 21: Arcsine 2 === | === Stage 21: Arcsine 2 === | ||
Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | ||
Takes a float.<br> | |||
Returns the Arcsine in RADIANS as a float.<br> | |||
Code to include in FunctionQuestScript: | |||
<pre>;S21 FUNCTION Arcsine 2 | |||
float t3 | |||
float t5 | |||
float t7</pre> | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float Arcsine(float sin) | <pre>;FUNCTION float Arcsine(float sin) | ||
;Approximation by Taylor Series - script by DragoonWraith | ;Approximation by Taylor Series - script by DragoonWraith | ||
Line 201: | Line 451: | ||
set f.fout to (f.fin1 + (1/2)*(f.t3/3) + (3/8)*(f.t5/5) + (15/48)*(f.t7/7) )</pre> | set f.fout to (f.fin1 + (1/2)*(f.t3/3) + (3/8)*(f.t5/5) + (15/48)*(f.t7/7) )</pre> | ||
=== Stage 22: | Usage in another script: | ||
<pre>;CALL float Arcsine(float sin) | |||
set f.fin1 to myVarForSin | |||
setStage f 21 | |||
set myResult to f.fout</pre> | |||
=== Stage 22: Arccosine === | |||
Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | ||
Takes a float.<br> | |||
Returns the Arccosine in DEGREES as a float.<br> | |||
Implementation relies on Stage 20.<br> | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float Arccosine(float cos) | <pre>;FUNCTION float Arccosine(float cos) | ||
setStage f 20 ;Call Arcsine with same input | setStage f 20 ;Call Arcsine with same input (DEGREES version) | ||
set f.fout to ( | set f.fout to (90 - f.fout)</pre> | ||
Usage in another script: | |||
<pre>;CALL float Arccosine(float cos) | |||
set f.fin1 to myVarForCos | |||
setStage f 22 | |||
set myResult to f.fout</pre> | |||
=== Stage 23: Arccosine 2 === | === Stage 23: Arccosine 2 === | ||
Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | ||
Takes a float.<br> | |||
Returns the Arccosine in RADIANS as a float.<br> | |||
Implementation relies on Stage 21.<br> | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float Arccosine(float cos) | <pre>;FUNCTION float Arccosine(float cos) | ||
setStage f 21 ;Call Arcsine with same input | setStage f 21 ;Call Arcsine with same input (RADIANS version) | ||
set f.fout to ((f.pi / 2) - f.fout)</pre> | set f.fout to ((f.pi / 2) - f.fout)</pre> | ||
Usage in another script: | |||
<pre>;CALL float Arccosine(float cos) | |||
set f.fin1 to myVarForCos | |||
setStage f 23 | |||
set myResult to f.fout</pre> | |||
=== Stage 24: Arctan === | === Stage 24: Arctan === | ||
Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | Based on [[Trigonometry_Functions|Trigonometry Functions]] Article | ||
Takes a float.<br> | |||
Returns the Arctan in RADIANS as a float.<br> | |||
Code to include in FunctionQuestScript: | |||
<pre>;S24 FUNCTION Arctan | |||
float t3 | |||
float t5 | |||
float t7</pre> | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float Arctan(float tan) | <pre>;FUNCTION float Arctan(float tan) | ||
;Approximation by Taylor Series - script by DragoonWraith | ;Approximation by Taylor Series - script by DragoonWraith | ||
Line 224: | Line 515: | ||
set f.fout to (f.fin1 - (f.t3/3) + (f.t5/5) - (f.t7/7))</pre> | set f.fout to (f.fin1 - (f.t3/3) + (f.t5/5) - (f.t7/7))</pre> | ||
=== Stage 30: | Usage in another script: | ||
<pre>;FUNCTION float | <pre>;CALL float Arctan(float tan) | ||
set f.fin1 to myVarForTan | |||
setStage f 24 | |||
set myResult to f.fout</pre> | |||
=== Stage 30: getVectorAngle === | |||
Takes the X and Y dimension of a 2D Vector as two floats.<br> | |||
Returns the Angle of the Vector in DEGREES as a float.<br> | |||
Code to include in FunctionQuestScript: | |||
<pre>;S30 FUNCTION getVectorAngle | |||
float tan | |||
float ang</pre> | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float getVectorAngle(float x, float y) | |||
if f.fin1 == 0 | |||
set f.fin1 to 0.001 | |||
endif | |||
if f.fin2 == 0 | |||
set f.fin2 to 0.001 | |||
endif | |||
set f.tan to (f.fin1/f.fin2) | set f.tan to (f.fin1/f.fin2) | ||
Line 243: | Line 556: | ||
endif | endif | ||
;CALL float Arctan(float tan) | |||
set f.fin1 to f.tan | set f.fin1 to f.tan | ||
setStage f 24 | setStage f 24 | ||
if f.fout > (f.pi/2) | if f.fout > (f.pi/2) | ||
Line 251: | Line 565: | ||
set f.fout to (f.pi/ -2) | set f.fout to (f.pi/ -2) | ||
endif | endif | ||
set f.fout to ((f.fout*f. | set f.fout to ((f.fout*f.radToDeg) + f.ang)</pre> | ||
Usage in another script: | |||
<pre>;CALL float getVectorAngle(float x, float y) | |||
set f.fin1 to myVarForX | |||
set f.fin2 to myVarForY | |||
setStage f 30 | |||
set myResultAngle to f.fout</pre> | |||
=== Stage 40: Natural Logarithm === | |||
Takes an antilogarithm a (float) and returns the exponent b (float) to the base e(=2.71828...):<br> | |||
a=e^b --> b=LN(a)<br> | |||
<br> | |||
Serial approximation is described [http://www.convertit.com/Go/EducationPlanet/Reference/AMS55.ASP?Res=150&Page=68 here].<br> | |||
Code to include in FunctionQuestScript: | |||
<pre>;S40 FUNCTION NaturalLogarithm | |||
short LN_n | |||
float t1 | |||
float t2 | |||
float t3 | |||
float t5 | |||
float t7 | |||
float t9 | |||
float t11 | |||
float t13</pre> | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float LN(float input) | |||
if f.LN_n == 0 | |||
set f.LN_n to 1 | |||
endif | |||
if f.fin1 <= 0 | |||
set f.fout to 0 | |||
set f.LN_n to 0 | |||
elseif f.fin1 > 4 || f.fin1 < 0.25 | |||
;change values for better (slower processing) or worse accuracy (faster processing) | |||
;this configuration should provide an accuracy of at least 99.99% | |||
;LN(x) = n * LN( nthRoot(x) ) | |||
set f.LN_n to (f.LN_n * 2) | |||
setStage f 5 | |||
set f.fin1 to f.fout | |||
setStage f 40 | |||
else | |||
set f.t1 to ((f.fin1 - 1) / (f.fin1 + 1)) | |||
set f.t2 to (f.t1*f.t1) | |||
set f.t3 to (f.t1*f.t2) | |||
set f.t5 to (f.t3*f.t2) | |||
set f.t7 to (f.t5*f.t2) | |||
set f.t9 to (f.t7*f.t2) | |||
set f.t11 to (f.t9*f.t2) | |||
set f.t13 to (f.t11*f.t2) | |||
set f.fout to (2 * f.LN_n * (f.t1 + f.t3/3 + f.t5/5 + f.t7/7 + f.t9/9 + f.t11/11 + f.t13/13)) | |||
set f.LN_n to 0 | |||
endif</pre> | |||
Actually, there are two ways to increase accuracy. You can either use more terms or change the values above (nearer 1 increases accuracy, farther 1 decreases it).<br> | |||
Keep in mind, that this is only useful in the relation: firstValue = 1 / secondValue | |||
Usage in another script: | |||
<pre>;CALL float NaturalLogarithm(float x) | |||
set f.fin1 to xVar | |||
setStage f 40 | |||
set exponent to f.fout</pre> | |||
=== Stage 50: Exponentiation === | |||
Takes a base x (positive) and an exponent y and returns a=x^y (all floats).<br> | |||
Script uses Taylor-Series for exponential functions from [http://www.convertit.com/Go/EducationPlanet/Reference/AMS55.ASP?Res=150&Page=69 here]. | |||
Code to include in FunctionQuestScript: | |||
<pre>;S50 FUNCTION Exponentiation | |||
float base | |||
float exponent | |||
float t1 | |||
float t2 | |||
float t3 | |||
float t4 | |||
float t5 | |||
float t6 | |||
float t7 | |||
float t8 | |||
float t9 | |||
float t10 | |||
float t11</pre> | |||
Code for the Stage Result Script: | |||
<pre>;FUNCTION float Exponentiation(float base, float exponent) | |||
set f.base to f.fin1 | |||
set f.exponent to f.fin2 | |||
setStage f 40 | |||
;x^y = e^(LN(x) * y) , e=2.71828... | |||
set f.t1 to (f.fout*f.exponent) | |||
set f.t2 to (f.t1*f.t1) | |||
set f.t3 to (f.t2*f.t1) | |||
set f.t4 to (f.t3*f.t1) | |||
set f.t5 to (f.t4*f.t1) | |||
set f.t6 to (f.t5*f.t1) | |||
set f.t7 to (f.t6*f.t1) | |||
set f.t8 to (f.t7*f.t1) | |||
set f.t9 to (f.t8*f.t1) | |||
set f.t10 to (f.t9*f.t1) | |||
set f.t11 to (f.t10*f.t1) | |||
set f.fout to (1 + f.t1 + f.t2/2 + f.t3/6 + f.t4/24 + f.t5/120 + f.t6/720 + f.t7/5040 + f.t8/40320 + f.t9/362880 + f.t10/3628800 + f.t11/39916800) ;attend to write this in one line</pre> | |||
Actually, more terms won't increase accuracy any more, because Oblivion can't handle higher values. | |||
Usage in another script: | |||
<pre>;CALL float Exponentiation(float base, float exponent) | |||
set f.fin1 to base | |||
set f.fin2 to exponent | |||
setStage f 50 | |||
set result to f.fout</pre> | |||
[[Category: Useful Code]] | [[Category: Useful Code]] |
Latest revision as of 13:02, 17 April 2013
This is a complete quest+function set-up. For a modular system, see Stage Functions
Welcome[edit | edit source]
to the Stage Function Repository! The goal of the Repository is, to create a huge database of available functions all using the method described in the article Simulating new functions. If you've written such a function and you think it might be helpful to others, don't hesitate to contribute to this repository.
The easy way: Math Library ESM[edit | edit source]
The easiest way to use the functions shown in this article is by using this ESM Math Library. To use it copy the ESM file to your oblivion data folder and select it as an additional master file when loading your mod with the Construction Set. By doing this all the necessary setup steps are already done for you. All you need to do to use a function is to call it. Examples of how to call each function are shown below in the "Usage" blocks of each stage function. Be aware that other users of your mod will need the Library too to run it.
Download: ESM Math Library v1.0.
Do it yourself: Step by Step[edit | edit source]
To get this up and running follow there simple setup steps:
- Open any Plugin you wish or create a new one with the Construction Set
- Create a new Quest called "f" (yes, just the letter "f", nothing more)
- Activate the Checkbox "Allow repeated stages". (This is VERY important!!)
- Create a new Quest Script and copy the whole content of the "Quest Script" section from this article into this script. Don't forget to attach it to your f-Quest!
- Create a new stage in this quest for each function you want to use from this repository and copy all code from it's section in this article to the related Result Script textbox. Make sure to select the right stage number for the function.
- That's it! You should be able to use them now!
Note for Stage function writers[edit | edit source]
It's great to see so many contributions. Keep it up. However, please try to make things as clear as possible for users. This repository will be most useful to users who aren't that good at scripting themselves. It isn't safe to assume that every user is going to check through the code of a function before using it.
At the least, each stage function should make clear what its inputs and outputs are. E.g. for trig functions this means specifying whether inputs/outputs are in degrees or radians. It also means making it clear (preferably outside the function code) when a certain function uses another one - e.g. Arccos calling Arcsin. Users should ideally not have to look through the code of each stage function to check whether it uses other stage functions.
Making things clear shouldn't take long, and will be helpful to users. It's also no more than your code deserves :).
Quest Script[edit | edit source]
ScriptName FunctionQuestScript ; Internals short doOnce float fQuestDelayTime ; Constants float pi float radToDeg float degToRad ; Function In- and Output float fin1 float fin2 float fin3 float fout float fout2 float fout3 ;S5 FUNCTION sqrt float sqr ;S6 FUNCTION NormalizeAngle360 ;S7 FUNCTION NormalizeAngle180 ;S10 FUNCTION Hypotenuse ;float sqr float n ;S15 FUNCTION SinCosTan 1 float ang float sin float cos float tan float exp ;S16 FUNCTION SinCodTan 2 ;float ang ;float sin ;float cos float t1 float t2 float t5 float t6 ;S17 FUNCTION SinCosTan 3 ;float ang ;float sin ;float cos ;float t2 ;S20 FUNCTION Arcsine 1 ;float sin ;float ang ;float n ;S21 FUNCTION Arcsine 2 float t3 ;float t5 float t7 ;S22 FUNCTION Arccosine 1 ;S23 FUNCTION Arccosine 2 ;S24 FUNCTION Arctan ;float t3 ;float t5 ;float t7 ;S30 FUNCTION getAngle float tan ;float ang ;S40 FUNCTION NaturalLogarithm short LN_n ;float t1 ;float t2 ;float t3 ;float t5 ;float t7 ;float t9 ;float t11 float t13 ;S50 FUNCTION Exponentiation float base float exponent ;float t1 ;float t2 ;float t3 float t4 ;float t5 ;float t6 ;float t7 float t8 ;float t9 float t10 ;float t11 ; Set constants first Begin Gamemode if doOnce == 0 set pi to 3.1415927 set radToDeg to 180.0/pi ;always multiply to convert set degToRad to 1/radToDeg set fQuestDelayTime to 30 set doOnce to 1 endif End
This Quest Script already contains everything needed for the following functions.
Stage 5: Square Root[edit | edit source]
Based on Square Root Article
Code to include in FunctionQuestScript:
;S5 FUNCTION sqrt float sqr
Code for the Stage Result Script:
;FUNCTION float sqrt(float input) if (f.fin1 <= 0) set f.fout to 0 else set f.sqr to f.fin1/2 set f.sqr to (f.sqr+(f.fin1/f.sqr))/2 set f.sqr to (f.sqr+(f.fin1/f.sqr))/2 set f.sqr to (f.sqr+(f.fin1/f.sqr))/2 set f.sqr to (f.sqr+(f.fin1/f.sqr))/2 set f.sqr to (f.sqr+(f.fin1/f.sqr))/2 set f.fout to f.sqr endif
Usage in another script:
;CALL float sqrt(float input) set f.fin1 to myVarForInput setStage f 5 set myResult to f.fout
Stage 6: Normalize Angle (0 till 360)[edit | edit source]
Takes an Angle and normalizes it to a range from 0 to 360 degrees. This is a functional loop!
Code for the Stage Result Script:
;FUNCTION float NormalizeAngle360(float Angle) if (f.fin1 >= 0) && (f.fin1 <= 360) set f.fout to f.fin1 else if f.fin1 < 0 set f.fin1 to (f.fin1 + 360) else set f.fin1 to (f.fin1 - 360) endif ;CALL float NormalizeAngle360(float angle) setStage f 6 endif
Usage in another script:
;CALL float NormalizeAngle360(float angle) set f.fin1 to myVarForAngle setStage f 6 set myResult to f.fout
Stage 7: Normalize Angle (-180 till 180)[edit | edit source]
Takes an Angle and normalizes it to a range from -180 to 180 degrees.
Code for the Stage Result Script:
;FUNCTION float NormalizeAngle180(float Angle) if (f.fin1 < 0) || (f.fin1 > 360) ;CALL float NormalizeAngle360(float Angle) setStage f 6 else set f.fout to f.fin1 endif if f.fout > 180 set f.fout to (f.fout - 360) endif
Usage in another script:
;CALL float NormalizeAngle180(float angle) set f.fin1 to myVarForAngle setStage f 7 set myResult to f.fout
Stage 10: Hypotenuse[edit | edit source]
Takes the length of both Cathesus in a right triangle as two floats.
Returns the length of the Hypotenuse as a float.
Code to include in FunctionQuestScript:
;S10 FUNCTION Hypotenuse float n
Code for the Stage Result Script:
;FUNCTION float Hypotenuse(float CathetusA, float CathetusB) set f.n to ((f.fin1 * f.fin1) + (f.fin2 * f.fin2)) ;CALL float sqrt(float input) set f.fin1 to f.n setStage f 5 ;fout is already the result
Usage in another script:
;CALL float Hypotenuse(float CathetusA, float CathetusB) set f.fin1 to myVarForCathetusA set f.fin2 to myVarForCathetusB setStage f 10 set myResult to f.fout
Stage 15: Sin Cos Tan[edit | edit source]
Based on Trigonometry Functions Article
Takes an angle in DEGREES.
Returns three floats: sin, cos and tan of the angle.
Code to include in FunctionQuestScript:
;S15 FUNCTION SinCosTan float ang float sin float cos float exp
Code for the Stage Result Script:
;FUNCTION float,float,float SinCosTan(float Angle) ;Taylor Series Variant 1 - script by Galerion ;CALL float NormalizeAngle180(float Angle) setStage f 7 set f.ang to f.fout ;approximate set f.ang to (f.ang*f.degToRad) set f.cos to 1 set f.exp to f.ang set f.sin to f.exp set f.exp to (f.exp * f.ang) set f.cos to (f.cos - f.exp / 2) set f.exp to (f.exp * f.ang) set f.sin to (f.sin - f.exp / 6) set f.exp to (f.exp * f.ang) set f.cos to (f.cos + f.exp / 24) set f.exp to (f.exp * f.ang) set f.sin to (f.sin + f.exp / 120) set f.exp to (f.exp * f.ang) set f.cos to (f.cos - f.exp / 720) set f.exp to (f.exp * f.ang) set f.sin to (f.sin - f.exp / 5040) set f.exp to (f.exp * f.ang) set f.cos to (f.cos + f.exp / 40320) set f.exp to (f.exp * f.ang) set f.sin to (f.sin + f.exp / 362880) set f.fout to f.sin if f.cos == 0 set f.cos to 0.0001 endif set f.fout2 to f.cos set f.fout3 to (f.sin/f.cos) ;tan
Usage in another script:
;CALL float,float,float SinCosTan(float Angle) set f.fin1 to myVarForAngle setStage f 15 set myResultSin to f.fout set myResultCos to f.fout2 set myResultTan to f.fout3
Stage 16: Sin Cos Tan 2[edit | edit source]
Based on Trigonometry Functions Article
Takes an angle in DEGREES.
Returns three floats: sin, cos and tan of the angle.
Code to include in FunctionQuestScript:
;S16 FUNCTION SinCodTan 2 float ang float sin float cos float t1 float t2 float t5 float t6
Code for the Stage Result Script:
;FUNCTION float,float,float SinCosTan(float Angle) ;Taylor Series Variant 2 - script by JOG ;CALL float NormalizeAngle180(float Angle) setStage f 7 set f.ang to f.fout set f.t1 to (f.ang*f.degToRad) set f.t2 to (f.t1*f.t1) set f.t5 to (f.t2*f.t2*f.t1) set f.t6 to (f.t5*f.t1) set f.sin to (f.t1 - (f.t1*f.t2/6) + (f.t5/120) - (f.t5*f.t2/5040) + (f.t6*f.t2*f.t1/362880)) set f.cos to (1 - (f.t2/2) + (f.t2*f.t2/24) - (f.t6/720) + (f.t6*f.t2/40320)) set f.fout to f.sin if f.cos == 0 set f.cos to 0.0001 endif set f.fout2 to f.cos set f.fout3 to f.sin/f.cos ;tan
Usage in another script:
;CALL float,float,float SinCosTan(float Angle) set f.fin1 to myVarForAngle setStage f 16 set myResultSin to f.fout set myResultCos to f.fout2 set myResultTan to f.fout3
Stage 17: Sin Cos Tan 3[edit | edit source]
Based on a posting by Galsiah in THIS THREAD
Takes an angle in DEGREES.
Returns three floats: sin, cos and tan of the angle.
Code to include in FunctionQuestScript:
;S17 FUNCTION SinCosTan 3 float ang float sin float cos float t2
Code for the Stage Result Script:
;FUNCTION float,float,float SinCosTan(float Angle) ;script by Galsiah ;CALL float NormalizeAngle360(float Angle) setStage f 6 set f.ang to (f.fout*f.degToRad) set f.n to 1 if (f.ang > 4.7123) Set f.ang to (f.ang - 6.2832) elseif ( f.ang > 1.5708 ) Set f.ang to (f.ang - 3.1416) Set f.n to -1 endif set f.t2 to (f.ang * f.ang) set f.sin to (f.ang*(1 - (f.t2*(0.16605 - (0.00761*f.t2))))) set f.sin to (f.sin*f.n) set f.cos to (1 - (f.t2*(0.4967 - (0.03705*f.t2)))) set f.cos to (f.cos*f.n) set f.fout to f.sin set f.fout2 to f.cos ;NB division is safe, since the above cos approximation cannot return 0. set f.fout3 to f.sin/f.cos ;tan
Usage in another script:
;CALL float,float,float SinCosTan(float Angle) set f.fin1 to myVarForAngle setStage f 17 set myResultSin to f.fout set myResultCos to f.fout2 set myResultTan to f.fout3
Stage 20: Arcsine[edit | edit source]
Based on Trigonometry Functions Article
Takes a float.
Returns the Arcsine in DEGREES as a float.
Code to include in FunctionQuestScript:
;S20 FUNCTION Arcsine float sin float ang float n
Code for the Stage Result Script:
;FUNCTION float Arcsine(float sin) ;Abramowitz/Stegun Approximation - script by JOG set f.sin to f.fin1 set f.n to 1 - f.sin set f.ang to f.n/2 set f.ang to (f.ang+(f.n/f.ang))/2 set f.ang to (f.ang+(f.n/f.ang))/2 set f.ang to (f.ang+(f.n/f.ang))/2 set f.n to (f.ang+(f.n/f.ang))/2 set f.fout to f.radToDeg*(1.5707963 - f.n*(1.5707288 - 0.2121144*f.sin+0.0742610*f.sin*f.sin - 0.0187293*f.sin*f.sin*f.sin))
Usage in another script:
;CALL float Arcsine(float sin) set f.fin1 to myVarForSin setStage f 20 set myResult to f.fout
Stage 21: Arcsine 2[edit | edit source]
Based on Trigonometry Functions Article
Takes a float.
Returns the Arcsine in RADIANS as a float.
Code to include in FunctionQuestScript:
;S21 FUNCTION Arcsine 2 float t3 float t5 float t7
Code for the Stage Result Script:
;FUNCTION float Arcsine(float sin) ;Approximation by Taylor Series - script by DragoonWraith set f.t3 to (f.fin1 * f.fin1 * f.fin1) set f.t5 to (f.t3 * f.fin1 * f.fin1) set f.t7 to (f.t5 * f.fin1 * f.fin1) set f.fout to (f.fin1 + (1/2)*(f.t3/3) + (3/8)*(f.t5/5) + (15/48)*(f.t7/7) )
Usage in another script:
;CALL float Arcsine(float sin) set f.fin1 to myVarForSin setStage f 21 set myResult to f.fout
Stage 22: Arccosine[edit | edit source]
Based on Trigonometry Functions Article
Takes a float.
Returns the Arccosine in DEGREES as a float.
Implementation relies on Stage 20.
Code for the Stage Result Script:
;FUNCTION float Arccosine(float cos) setStage f 20 ;Call Arcsine with same input (DEGREES version) set f.fout to (90 - f.fout)
Usage in another script:
;CALL float Arccosine(float cos) set f.fin1 to myVarForCos setStage f 22 set myResult to f.fout
Stage 23: Arccosine 2[edit | edit source]
Based on Trigonometry Functions Article
Takes a float.
Returns the Arccosine in RADIANS as a float.
Implementation relies on Stage 21.
Code for the Stage Result Script:
;FUNCTION float Arccosine(float cos) setStage f 21 ;Call Arcsine with same input (RADIANS version) set f.fout to ((f.pi / 2) - f.fout)
Usage in another script:
;CALL float Arccosine(float cos) set f.fin1 to myVarForCos setStage f 23 set myResult to f.fout
Stage 24: Arctan[edit | edit source]
Based on Trigonometry Functions Article
Takes a float.
Returns the Arctan in RADIANS as a float.
Code to include in FunctionQuestScript:
;S24 FUNCTION Arctan float t3 float t5 float t7
Code for the Stage Result Script:
;FUNCTION float Arctan(float tan) ;Approximation by Taylor Series - script by DragoonWraith set f.t3 to (f.fin1 * f.fin1 * f.fin1) set f.t5 to (f.t3 * f.fin1 * f.fin1) set f.t7 to (f.t5 * f.fin1 * f.fin1) set f.fout to (f.fin1 - (f.t3/3) + (f.t5/5) - (f.t7/7))
Usage in another script:
;CALL float Arctan(float tan) set f.fin1 to myVarForTan setStage f 24 set myResult to f.fout
Stage 30: getVectorAngle[edit | edit source]
Takes the X and Y dimension of a 2D Vector as two floats.
Returns the Angle of the Vector in DEGREES as a float.
Code to include in FunctionQuestScript:
;S30 FUNCTION getVectorAngle float tan float ang
Code for the Stage Result Script:
;FUNCTION float getVectorAngle(float x, float y) if f.fin1 == 0 set f.fin1 to 0.001 endif if f.fin2 == 0 set f.fin2 to 0.001 endif set f.tan to (f.fin1/f.fin2) if f.tan >1 || f.tan < -1 set f.tan to (f.fin2/ -f.fin1) if f.fin1 >= 0 set f.ang to 90 else set f.ang to -90 endif else if f.fin2 >= 0 set f.ang to 0 else set f.ang to 180 endif endif ;CALL float Arctan(float tan) set f.fin1 to f.tan setStage f 24 if f.fout > (f.pi/2) set f.fout to (f.pi/2) elseif f.fout < (f.pi/ -2) set f.fout to (f.pi/ -2) endif set f.fout to ((f.fout*f.radToDeg) + f.ang)
Usage in another script:
;CALL float getVectorAngle(float x, float y) set f.fin1 to myVarForX set f.fin2 to myVarForY setStage f 30 set myResultAngle to f.fout
Stage 40: Natural Logarithm[edit | edit source]
Takes an antilogarithm a (float) and returns the exponent b (float) to the base e(=2.71828...):
a=e^b --> b=LN(a)
Serial approximation is described here.
Code to include in FunctionQuestScript:
;S40 FUNCTION NaturalLogarithm short LN_n float t1 float t2 float t3 float t5 float t7 float t9 float t11 float t13
Code for the Stage Result Script:
;FUNCTION float LN(float input) if f.LN_n == 0 set f.LN_n to 1 endif if f.fin1 <= 0 set f.fout to 0 set f.LN_n to 0 elseif f.fin1 > 4 || f.fin1 < 0.25 ;change values for better (slower processing) or worse accuracy (faster processing) ;this configuration should provide an accuracy of at least 99.99% ;LN(x) = n * LN( nthRoot(x) ) set f.LN_n to (f.LN_n * 2) setStage f 5 set f.fin1 to f.fout setStage f 40 else set f.t1 to ((f.fin1 - 1) / (f.fin1 + 1)) set f.t2 to (f.t1*f.t1) set f.t3 to (f.t1*f.t2) set f.t5 to (f.t3*f.t2) set f.t7 to (f.t5*f.t2) set f.t9 to (f.t7*f.t2) set f.t11 to (f.t9*f.t2) set f.t13 to (f.t11*f.t2) set f.fout to (2 * f.LN_n * (f.t1 + f.t3/3 + f.t5/5 + f.t7/7 + f.t9/9 + f.t11/11 + f.t13/13)) set f.LN_n to 0 endif
Actually, there are two ways to increase accuracy. You can either use more terms or change the values above (nearer 1 increases accuracy, farther 1 decreases it).
Keep in mind, that this is only useful in the relation: firstValue = 1 / secondValue
Usage in another script:
;CALL float NaturalLogarithm(float x) set f.fin1 to xVar setStage f 40 set exponent to f.fout
Stage 50: Exponentiation[edit | edit source]
Takes a base x (positive) and an exponent y and returns a=x^y (all floats).
Script uses Taylor-Series for exponential functions from here.
Code to include in FunctionQuestScript:
;S50 FUNCTION Exponentiation float base float exponent float t1 float t2 float t3 float t4 float t5 float t6 float t7 float t8 float t9 float t10 float t11
Code for the Stage Result Script:
;FUNCTION float Exponentiation(float base, float exponent) set f.base to f.fin1 set f.exponent to f.fin2 setStage f 40 ;x^y = e^(LN(x) * y) , e=2.71828... set f.t1 to (f.fout*f.exponent) set f.t2 to (f.t1*f.t1) set f.t3 to (f.t2*f.t1) set f.t4 to (f.t3*f.t1) set f.t5 to (f.t4*f.t1) set f.t6 to (f.t5*f.t1) set f.t7 to (f.t6*f.t1) set f.t8 to (f.t7*f.t1) set f.t9 to (f.t8*f.t1) set f.t10 to (f.t9*f.t1) set f.t11 to (f.t10*f.t1) set f.fout to (1 + f.t1 + f.t2/2 + f.t3/6 + f.t4/24 + f.t5/120 + f.t6/720 + f.t7/5040 + f.t8/40320 + f.t9/362880 + f.t10/3628800 + f.t11/39916800) ;attend to write this in one line
Actually, more terms won't increase accuracy any more, because Oblivion can't handle higher values.
Usage in another script:
;CALL float Exponentiation(float base, float exponent) set f.fin1 to base set f.fin2 to exponent setStage f 50 set result to f.fout