Hpl2:Resources:script modules:math

From Frictional Wiki
Jump to navigation Jump to search

Math Functions

The following block of code is a set of Math functions arranged by Apjjm. These functions were made using Improved Notepad++ HPS Support, and concequently would be viewed best with this plugin. Copy and paste the code below either into your .hps file or into some external file if using a Script Pre-Processer.

Code download

//Begin Math
//+ Constants
const float PI = 3.1415926535f;
const float HPI = PI * 0.5f;
const float PI2 = PI * 2.0f;
//-
//+ Sign Of
int sign(float &in x) { if(x==0.0f) return 0; return (x>0.0f)?1:-1; }
int sign(int &in x)   { if(x==0)    return 0; return (x>0)?1:-1; }
//-
//+ Abs
float abs(float &in x) { return (x>0.0f)?x:-x; }
int abs(int &in x)     { return (x>0)?x:-x; }
//-
//+ Approx
//Determines if two numbers are approximately equal (Differ by no more than epsilon)
bool approx(float &in x, float &in y, float &in epsilon) {
float delta = x-y; return ((delta>0?delta:-delta) <= (epsilon>0?epsilon:-epsilon)); }
//-
//+ Sqrt
//Prereq: Approx
//Returns the squareroot of x
const uint32 _SQRTITERATIONS=16; //Maximum number of iterations for sqrt computation
const float  _SQRTDELTA=0.00001f; //Margin of error allowable if complete before iteration ceiling
float sqrt(float &in x) {
  if(x<=0) return 0; //Early out - not valid input.
  uint32 i = 0; float o = x * 0.5f;
  while( i<_SQRTITERATIONS && !approx(o*o,x,_SQRTDELTA) && o != 0)
    { o = 0.5f * (o + x/o); i++; }
  return o;             }
//-
//+ Max/Min
//Max: Returns largest of two numbers
//Min: Returns smallest of two numbers
float max(float &in x, float &in y) { return x>y?x:y; }
int max(int &in x, int &in y) { return x>y?x:y; }
float min(float &in x, float &in y) { return x<y?x:y; }
int min(int &in x, int &in y) { return x<y?x:y; }
float clamp(float &in x, float &in upper, float &in lower) { return (x<lower?lower:(x<upper?x:upper)); }
int clamp(int &in x, int &in upper, int &in lower) { return (x<lower?lower:(x<upper?x:upper)); }
//-
//+ Factorial
uint32 fact(uint32 &in x) { if(x==0) return 1;
    uint32 y = x; for(uint32 i=x-1; i>0; i--) y*=i; return y; }
int fact(int &in x)       { if(x<=0) return 1;
    int y = x; for(int i=x-1; i>0; i--) y*=i; return y; }
//-
//+ Conversions
//Degrees to radians
float degtorad(float &in x) { return x * 0.0174532925f; }
//Radians to degrees
float radtodeg(float &in x) { return x * 57.2957795f; }
//-
//+ Trig Functions
//+ ..Helper
const float  _TRIGARCTANLIM=128.0f; //Value when x exceeds 90 is returned
const uint32 _TRIGITERATIONS=32; //Maximum number of iterations for sqrt computation
const float  _TRIGDELTA=0.00001f; //Smallest diff for trig vals
//Constrains X : -PI<X<PI
float trigClamp(float &in x) {
if(x> PI || x <-PI)
  { int t = x/PI2; return x-t*PI2; }
else return x;
}
//-
//+ ..Sin/Cos/Tan
//COSINE
float cos(float &in y) {
  float x = trigClamp(y);
  float t,s; t=1.0f; s = 1.0f; uint32 p=0;
  while( p<_TRIGITERATIONS)
   { p++; t = (-t * x * x) / ((2 * p - 1) * (2 * p)); s+=t; }
  return s;
}
//SINE
float sin(float &in y) {
  return cos(y-HPI);
}
//TAN (Tan(90 deg) Returns 0xFFFFFFFF [Use isInf()])
float tan(float &in y) {
  float x = trigClamp(y);
  float c = cos(x);
  if(c> -_TRIGDELTA/2 && c <_TRIGDELTA/2) return float(0xFFFFFFFF); //Return #+INF                                        
  return cos(x-HPI)/c;
}
//-
//+ ..ARC Sin/Cos/Tan [APPROX]
float arccos(float &in x) {
return trigClamp((-0.69813170079773212f * x * x - 0.87266462599716477f) * x + 1.5707963267948966f); }
float arcsin(float &in x) { return trigClamp(HPI-arccos(x)); }
float arctan(float &in x) {  if(x> _TRIGARCTANLIM) return HPI;
else if(x <-_TRIGARCTANLIM) return -HPI; else return trigClamp(HPI-arccos(x/sqrt(x*x+1.1f))); }
float arctan2(float &in x, float &in y) {
float c1 = HPI * 0.5f;    float c2 = 3.0f * c1; float abs_y = abs(y); float angle;    
if (x>= 0) { float r = (x - abs_y) / (x + abs_y);    angle = c1 - c1 * r;    }
else { float r = (x + abs_y) / (abs_y - x);    angle = c2 - c1 * r;    }    
return y<0?-angle:angle; }
//Can somebody actually get a good expansion to work here?
//-
//-
//+ Rounding
int floor(float &in x) { return int(x); }
int ceil(float &in x)  { int y = int(x); return (y==x?y:y+1); }
int round(float &in x) { int y = int(x); return (y+0.5f>x)?y:(y+1);}
//-
//End