Math.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986
  1. /******************************************************************************
  2. Floating Point Performance, Tested on Intel i7-3632QM 2.2 Ghz
  3. Operations Flt x Flt, have the same performance as Dbl x Dbl.
  4. However Flt x Dbl (mixed precision) are slower.
  5. Casting to the same types restores full performance: Flt x Flt(Dbl), without any cost for casting.
  6. Floating Point Precision:
  7. After 1 month of running an app:
  8. Flt time=60*60*24*30; (60s*60m*24h*30d = 2592000 seconds)
  9. At this value, 'time' + average frame time delta (1.0f/60) is the same as 'time'
  10. time+=1.0f/60; // does not modify 'time'
  11. /******************************************************************************/
  12. #include "stdafx.h"
  13. namespace EE{
  14. /******************************************************************************/
  15. const Half HalfZero=false, HalfOne=true;
  16. const Int PrimeNumbers[16]={2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};
  17. /******************************************************************************/
  18. Bool Special(C Flt &r) {UInt *d=(UInt*)&r; return (d[0]&0x7F800000)==0x7F800000 ;} // all exponent bits are on
  19. Bool Special(C Dbl &r) {UInt *d=(UInt*)&r; return (d[1]&0x7FF00000)==0x7FF00000 ;} // all exponent bits are on
  20. Bool NaN (C Flt &r) {UInt *d=(UInt*)&r; return Special(r) && (d[0]&0x7FFFFF );} // significand!=0
  21. Bool Inf (C Flt &r) {UInt *d=(UInt*)&r; return Special(r) && !(d[0]&0x7FFFFF );} // significand==0
  22. Bool NaN (C Dbl &r) {UInt *d=(UInt*)&r; return Special(r) && (d[1]&0x0FFFFF || d[0]);} // significand!=0
  23. Bool Inf (C Dbl &r) {UInt *d=(UInt*)&r; return Special(r) && !(d[1]&0x0FFFFF || d[0]);} // significand==0
  24. /******************************************************************************/
  25. Vec2 ScaleFactor(C Vec2 &vec) {return Vec2 (ScaleFactor(vec.x), ScaleFactor(vec.y));}
  26. VecD2 ScaleFactor(C VecD2 &vec) {return VecD2(ScaleFactor(vec.x), ScaleFactor(vec.y));}
  27. Vec ScaleFactor(C Vec &vec) {return Vec (ScaleFactor(vec.x), ScaleFactor(vec.y), ScaleFactor(vec.z));}
  28. VecD ScaleFactor(C VecD &vec) {return VecD (ScaleFactor(vec.x), ScaleFactor(vec.y), ScaleFactor(vec.z));}
  29. Vec4 ScaleFactor(C Vec4 &vec) {return Vec4 (ScaleFactor(vec.x), ScaleFactor(vec.y), ScaleFactor(vec.z), ScaleFactor(vec.w));}
  30. VecD4 ScaleFactor(C VecD4 &vec) {return VecD4(ScaleFactor(vec.x), ScaleFactor(vec.y), ScaleFactor(vec.z), ScaleFactor(vec.w));}
  31. Vec2 ScaleFactorR(C Vec2 &vec) {return Vec2 (ScaleFactorR(vec.x), ScaleFactorR(vec.y));}
  32. VecD2 ScaleFactorR(C VecD2 &vec) {return VecD2(ScaleFactorR(vec.x), ScaleFactorR(vec.y));}
  33. Vec ScaleFactorR(C Vec &vec) {return Vec (ScaleFactorR(vec.x), ScaleFactorR(vec.y), ScaleFactorR(vec.z));}
  34. VecD ScaleFactorR(C VecD &vec) {return VecD (ScaleFactorR(vec.x), ScaleFactorR(vec.y), ScaleFactorR(vec.z));}
  35. Vec4 ScaleFactorR(C Vec4 &vec) {return Vec4 (ScaleFactorR(vec.x), ScaleFactorR(vec.y), ScaleFactorR(vec.z), ScaleFactorR(vec.w));}
  36. VecD4 ScaleFactorR(C VecD4 &vec) {return VecD4(ScaleFactorR(vec.x), ScaleFactorR(vec.y), ScaleFactorR(vec.z), ScaleFactorR(vec.w));}
  37. /******************************************************************************/
  38. void MinMax(C Flt *f, Int elms, Flt &min, Flt &max)
  39. {
  40. if(elms)for(min=max=*f++; --elms; )
  41. {
  42. Flt r=*f++;
  43. if(r<min)min=r;else
  44. if(r>max)max=r;
  45. }
  46. }
  47. void MinMax(C Dbl *f, Int elms, Dbl &min, Dbl &max)
  48. {
  49. if(elms)for(min=max=*f++; --elms; )
  50. {
  51. Dbl r=*f++;
  52. if(r<min)min=r;else
  53. if(r>max)max=r;
  54. }
  55. }
  56. void MinMaxI(C Flt *f, Int elms, Int &min, Int &max)
  57. {
  58. if(elms)
  59. {
  60. Flt _min, _max;
  61. _min=_max=f[0];
  62. min= max= 0 ;
  63. for(Int i=1; i<elms; i++)
  64. {
  65. Flt r=f[i];
  66. if(r<_min){_min=r; min=i;}else
  67. if(r>_max){_max=r; max=i;}
  68. }
  69. }
  70. }
  71. void MinMaxI(C Dbl *f, Int elms, Int &min, Int &max)
  72. {
  73. if(elms)
  74. {
  75. Dbl _min, _max;
  76. _min=_max=f[0];
  77. min= max= 0 ;
  78. for(Int i=1; i<elms; i++)
  79. {
  80. Dbl r=f[i];
  81. if(r<_min){_min=r; min=i;}else
  82. if(r>_max){_max=r; max=i;}
  83. }
  84. }
  85. }
  86. /******************************************************************************/
  87. UInt SqrtI(UInt x, Int max_steps)
  88. {
  89. if(x<=1)return x;
  90. UInt y=1<<(BitHi(x)>>1); // approximate the sqrt
  91. REP(max_steps)
  92. {
  93. UInt prev=y;
  94. y=(y + x/y + 1)/2;
  95. if(prev==y)break; // if no change was made then stop
  96. }
  97. return y;
  98. }
  99. UInt SqrtI(UInt x)
  100. {
  101. UInt res=0, one=1<<30;
  102. for(; one>x; one>>=2);
  103. for(; one; )
  104. {
  105. if(x>=res+one)
  106. {
  107. x -=res+one;
  108. res+=one<<1;
  109. }
  110. res>>=1;
  111. one>>=2;
  112. }
  113. if(x>res)res++; // use rounding
  114. return res;
  115. }
  116. UInt SqrtI(ULong x)
  117. {
  118. ULong res=0, one=1ll<<62;
  119. for(; one>x; one>>=2);
  120. for(; one; )
  121. {
  122. if(x>=res+one)
  123. {
  124. x -=res+one;
  125. res+=one<<1;
  126. }
  127. res>>=1;
  128. one>>=2;
  129. }
  130. if(x>res)res++; // use rounding
  131. return res;
  132. }
  133. Int SqrtI(Int x) {return (x>0) ? SqrtI(UInt (x)) : 0;}
  134. Int SqrtI(Long x) {return (x>0) ? SqrtI(ULong(x)) : 0;}
  135. Flt Log(Flt x, Flt base) {return logf(x)/logf(base);}
  136. Dbl Log(Dbl x, Dbl base) {return log (x)/log (base);}
  137. Flt Pinch(Flt x, Flt pinch) {return x*pinch/(1+x*(pinch-1));}
  138. /******************************************************************************/
  139. // ROUNDING
  140. /******************************************************************************/
  141. Dbl TruncD(Dbl x)
  142. {
  143. Dbl trunc; modf(x, &trunc);
  144. return trunc;
  145. }
  146. /******************************************************************************/
  147. Flt SplitAlpha(Flt alpha, Int steps)
  148. {
  149. /* For 2 steps:
  150. apply regular alpha blending:
  151. alpha*src + (1-alpha)*dest = final
  152. apply regular alpha blending but two times in a row (now using unknown 'beta' instead of 'alpha'):
  153. beta*src + (1-beta)*(beta*src + (1-beta)*dest) = final
  154. now we want 'final' result to be the same in both cases:
  155. alpha*src + (1-alpha)*dest = beta*src + (1-beta)*(beta*src + (1-beta)*dest)
  156. alpha*src + dest - dest*alpha = beta*src + (1-beta)*(beta*src + dest - dest*beta)
  157. alpha*src + dest - dest*alpha = beta*src + beta*src + dest - dest*beta - beta*beta*src - dest*beta + dest*beta*beta
  158. alpha*src - dest*alpha = beta*src + beta*src - dest*beta - beta*beta*src - dest*beta + dest*beta*beta
  159. alpha*src - dest*alpha = beta*beta*(dest - src) + beta*2*(src - dest)
  160. alpha*src - dest*alpha = beta*beta*(dest - src) - beta*2*(dest - src)
  161. (alpha*src - dest*alpha)/(dest-src) = beta*beta - beta*2
  162. -alpha = beta*beta - beta*2 -> assumed dest=1, src=0
  163. beta*beta + (-2)*beta + alpha = 0
  164. delta = -2*-2 - 4*alpha*1
  165. return 1-Sqrt(4-4*alpha)*0.5
  166. return 1-2*Sqrt(1-alpha)*0.5;
  167. gives final result of: return 1-Sqrt(1-alpha);
  168. it was tested that for 3 steps: return 1-Cbrt(1-alpha); gives positive results
  169. So the final formula is: */
  170. return (steps>1) ? 1-Pow(1-alpha, 1.0f/steps) : alpha;
  171. }
  172. Flt VisibleOpacity(Flt density, Flt range) {return Pow(1-density, range);}
  173. Flt AccumulatedDensity(Flt density, Flt range) {return 1-Pow(1-density, range);}
  174. /******************************************************************************/
  175. // ANGLES
  176. /******************************************************************************/
  177. Vec2 Tan(C Vec2 &angle) {return Vec2(Tan(angle.x), Tan(angle.y));}
  178. void CosSin(Flt &cos, Flt &sin, Flt angle)
  179. {
  180. #if APPLE
  181. __sincosf(angle, &sin, &cos);
  182. #elif !WINDOWS
  183. sincosf(angle, &sin, &cos);
  184. #elif X64 || ARM
  185. sin=Sin(angle);
  186. cos=Cos(angle);
  187. #else
  188. _asm
  189. {
  190. mov edx, cos
  191. mov eax, sin
  192. fld angle
  193. fsincos
  194. fstp dword ptr[edx]
  195. fstp dword ptr[eax]
  196. }
  197. #endif
  198. }
  199. void CosSin(Dbl &cos, Dbl &sin, Dbl angle)
  200. {
  201. #if APPLE
  202. __sincos(angle, &sin, &cos);
  203. #elif !WINDOWS
  204. sincos(angle, &sin, &cos);
  205. #elif X64 || ARM
  206. sin=Sin(angle);
  207. cos=Cos(angle);
  208. #else
  209. _asm
  210. {
  211. mov edx, cos
  212. mov eax, sin
  213. fld angle
  214. fsincos
  215. fstp qword ptr[edx]
  216. fstp qword ptr[eax]
  217. }
  218. #endif
  219. }
  220. Flt Acos(Flt cos)
  221. {
  222. if(cos>= 1)return 0;
  223. if(cos<=-1)return PI;
  224. return acosf(cos);
  225. }
  226. Dbl Acos(Dbl cos)
  227. {
  228. if(cos>= 1)return 0;
  229. if(cos<=-1)return PID;
  230. return acos(cos);
  231. }
  232. Flt Asin(Flt sin)
  233. {
  234. if(sin>= 1)return PI_2;
  235. if(sin<=-1)return -PI_2;
  236. return asinf(sin);
  237. }
  238. Dbl Asin(Dbl sin)
  239. {
  240. if(sin>= 1)return PID_2;
  241. if(sin<=-1)return -PID_2;
  242. return asin(sin);
  243. }
  244. Flt ACosSin(Flt cos, Flt sin) // assumes "sin>=0"
  245. { // use Acos for angles 45..135 deg
  246. return (sin>=SQRT2_2) ? Acos(cos)
  247. : (cos>=0) ? Asin(sin) : PI-Asin(sin);
  248. }
  249. Dbl ACosSin(Dbl cos, Dbl sin) // assumes "sin>=0"
  250. { // use Acos for angles 45..135 deg
  251. return (sin>=SQRT2_2) ? Acos(cos)
  252. : (cos>=0) ? Asin(sin) : PID-Asin(sin);
  253. }
  254. Vec2 Atan(C Vec2 &tan) {return Vec2(Atan(tan.x), Atan(tan.y));}
  255. Flt AngleFast(Flt x, Flt y)
  256. {
  257. Flt r=Abs(x)+Abs(y);
  258. if(!r)return 0;
  259. return (y>=0) ? (1-x/r)*PI_2 : (x/r-1)*PI_2;
  260. }
  261. Flt AngleFast(C Vec2 &v)
  262. {
  263. Flt r=Abs(v.x)+Abs(v.y);
  264. if(!r)return 0;
  265. return (v.y>=0) ? (1-v.x/r)*PI_2 : (v.x/r-1)*PI_2;
  266. }
  267. Flt AngleFast(C Vec &v, C Vec &x, C Vec &y) {return AngleFast(Dot(v, x), Dot(v, y));}
  268. Flt Angle (C Vec &v, C Vec &x, C Vec &y) {return Angle (Dot(v, x), Dot(v, y));}
  269. /******************************************************************************/
  270. Flt AngleNormalize(Flt angle) {angle=AngleFull(angle); return (angle>PI ) ? angle-PI2 : angle;}
  271. Dbl AngleNormalize(Dbl angle) {angle=AngleFull(angle); return (angle>PID) ? angle-PID2 : angle;}
  272. /******************************************************************************/
  273. Flt CosBetween(C Vec2 &a, C Vec2 &b) {if(Flt l2=a.length2()*b.length2())return Dot(a, b)/SqrtFast(l2); return 0;}
  274. Dbl CosBetween(C VecD2 &a, C VecD2 &b) {if(Dbl l2=a.length2()*b.length2())return Dot(a, b)/SqrtFast(l2); return 0;}
  275. Flt CosBetween(C Vec &a, C Vec &b) {if(Flt l2=a.length2()*b.length2())return Dot(a, b)/SqrtFast(l2); return 0;}
  276. Dbl CosBetween(C VecD &a, C VecD &b) {if(Dbl l2=a.length2()*b.length2())return Dot(a, b)/SqrtFast(l2); return 0;}
  277. Flt SinBetween(C Vec2 &a, C Vec2 &b) {if(Flt l2=a.length2()*b.length2())return Cross(a, b)/ SqrtFast(l2); return 0;}
  278. Dbl SinBetween(C VecD2 &a, C VecD2 &b) {if(Dbl l2=a.length2()*b.length2())return Cross(a, b)/ SqrtFast(l2); return 0;}
  279. Flt AbsSinBetween(C Vec &a, C Vec &b) {if(Flt l2=a.length2()*b.length2())return SqrtFast(Cross(a, b).length2()/l2); return 0;}
  280. Dbl AbsSinBetween(C VecD &a, C VecD &b) {if(Dbl l2=a.length2()*b.length2())return SqrtFast(Cross(a, b).length2()/l2); return 0;}
  281. Flt AngleBetween (C Vec2 &a, C Vec2 &b) {return AngleDelta(Angle(a), Angle(b));}
  282. Dbl AngleBetween (C VecD2 &a, C VecD2 &b) {return AngleDelta(Angle(a), Angle(b));}
  283. Flt AbsAngleBetween (C Vec &a, C Vec &b) {return Angle (CosBetweenN(a, b), AbsSinBetweenN(a, b));} // we don't need to do any scaling because 'CosBetweenN' and 'AbsSinBetweenN' will have proportional lengths, and we use 'Angle' which doesn't require lengthts to be normalized
  284. Dbl AbsAngleBetween (C VecD &a, C VecD &b) {return Angle (CosBetweenN(a, b), AbsSinBetweenN(a, b));} // we don't need to do any scaling because 'CosBetweenN' and 'AbsSinBetweenN' will have proportional lengths, and we use 'Angle' which doesn't require lengthts to be normalized
  285. Flt AbsAngleBetweenN(C Vec &a, C Vec &b) {return ACosSin(CosBetweenN(a, b), AbsSinBetweenN(a, b));}
  286. Dbl AbsAngleBetweenN(C VecD &a, C VecD &b) {return ACosSin(CosBetweenN(a, b), AbsSinBetweenN(a, b));}
  287. Flt AngleBetween(C Vec &a, C Vec &b, C Vec &z) {Flt angle=AbsAngleBetween(a, b); if(Dot(Cross(a, b), z)<0)CHS(angle); return angle;}
  288. Dbl AngleBetween(C VecD &a, C VecD &b, C VecD &z) {Dbl angle=AbsAngleBetween(a, b); if(Dot(Cross(a, b), z)<0)CHS(angle); return angle;}
  289. /******************************************************************************/
  290. Vec DequantizeNormal(C Vec &n)
  291. {
  292. Flt z=CalcZ(n.xy);
  293. Vec dn(n.x, n.y, Lerp((n.z>=0) ? z : -z, n.z, n.xy.length())); // error 5232, errorNoNormalize 1583174
  294. //Vec dn(n.x, n.y, Lerp((n.z>=0) ? z : -z, n.z, CosSin(z))); // error 5232, errorNoNormalize 1583103
  295. //Vec dn(n.x, n.y, Lerp(n.z, (n.z>=0) ? z : -z, Sqr(z))); // error 5425, errorNoNormalize 1410261
  296. //Vec dn(n.x, n.y, Lerp((n.z>=0) ? z : -z, n.z, 1-Sqr(z))); // error 5425, errorNoNormalize 1410261
  297. //Vec dn(n.x, n.y, Lerp((n.z>=0) ? z : -z, n.z, n.xy.length2())); // error 5426, errorNoNormalize 1410402
  298. //Vec dn(n.x, n.y, Lerp(n.z, (n.z>=0) ? z : -z, z)); // error 7035, errorNoNormalize 1101598
  299. //Vec dn(n.x, n.y, Lerp((n.z>=0) ? z : -z, n.z, 1-z)); // error 7035, errorNoNormalize 1101598
  300. //Vec dn(n.x, n.y, Lerp((n.z>=0) ? z : -z, n.z, Sqr(1-z))); // error 10519, errorNoNormalize 793122
  301. //Vec dn(n.x, n.y, (n.z>=0) ? z : -z); // error 120477, errorNoNormalize 144597
  302. dn.normalize();
  303. return dn;
  304. }
  305. /******************************************************************************/
  306. // INTERPOLATION
  307. /******************************************************************************/
  308. #define TANGENT_FULL 0.817538f
  309. #define TANGENT 0.5f
  310. /******************************************************************************/
  311. Flt GetTangent ( Flt prev, Flt next) {return (next-prev)*TANGENT;}
  312. Vec2 GetTangent (C Vec2 &prev, C Vec2 &next) {return (next-prev)*TANGENT;}
  313. Vec GetTangent (C Vec &prev, C Vec &next) {return (next-prev)*TANGENT;}
  314. Vec4 GetTangent (C Vec4 &prev, C Vec4 &next) {return (next-prev)*TANGENT;}
  315. Vec2 GetTangentDir(C Vec2 &prev, C Vec2 &next) {return (next-prev)*Lerp(TANGENT, TANGENT_FULL, Sqr(AbsAngleBetween(prev, next)/PI));}
  316. Vec GetTangentDir(C Vec &prev, C Vec &next) {return (next-prev)*Lerp(TANGENT, TANGENT_FULL, Sqr(AbsAngleBetween(prev, next)/PI));}
  317. Flt GetTangent( Flt prev, Flt cur, Flt next) {return GetTangent (prev , next );}
  318. Vec2 GetTangent(C Vec2 &prev, C Vec2 &cur, C Vec2 &next) {return GetTangentDir(prev-cur, next-cur);}
  319. Vec GetTangent(C Vec &prev, C Vec &cur, C Vec &next) {return GetTangentDir(prev-cur, next-cur);}
  320. Vec4 GetTangent(C Vec4 &prev, C Vec4 &cur, C Vec4 &next) {return GetTangent (prev , next );}
  321. /******************************************************************************/
  322. VecB4 Lerp(C VecB4 &from, C VecB4 &to, Flt step)
  323. {
  324. Flt step1=1-step;
  325. return VecB4(Mid(RoundPos(from.x*step1 + to.x*step), 0, 255),
  326. Mid(RoundPos(from.y*step1 + to.y*step), 0, 255),
  327. Mid(RoundPos(from.z*step1 + to.z*step), 0, 255),
  328. Mid(RoundPos(from.w*step1 + to.w*step), 0, 255));
  329. }
  330. VecB4 Lerp(C VecB4 &a, C VecB4 &b, C VecB4 &c, C Vec &blend)
  331. {
  332. return VecB4(Mid(RoundPos(a.x*blend.x + b.x*blend.y + c.x*blend.z), 0, 255),
  333. Mid(RoundPos(a.y*blend.x + b.y*blend.y + c.y*blend.z), 0, 255),
  334. Mid(RoundPos(a.z*blend.x + b.z*blend.y + c.z*blend.z), 0, 255),
  335. Mid(RoundPos(a.w*blend.x + b.w*blend.y + c.w*blend.z), 0, 255));
  336. }
  337. /******************************************************************************/
  338. Flt LerpR(C Vec2 &from, C Vec2 &to, C Vec2 &value) {Int i=Abs(to-from).maxI(); return LerpR(from.c[i], to.c[i], value.c[i]);}
  339. Dbl LerpR(C VecD2 &from, C VecD2 &to, C VecD2 &value) {Int i=Abs(to-from).maxI(); return LerpR(from.c[i], to.c[i], value.c[i]);}
  340. Flt LerpR(C Vec &from, C Vec &to, C Vec &value) {Int i=Abs(to-from).maxI(); return LerpR(from.c[i], to.c[i], value.c[i]);}
  341. Dbl LerpR(C VecD &from, C VecD &to, C VecD &value) {Int i=Abs(to-from).maxI(); return LerpR(from.c[i], to.c[i], value.c[i]);}
  342. Flt LerpR(C Vec4 &from, C Vec4 &to, C Vec4 &value) {Int i=Abs(to-from).maxI(); return LerpR(from.c[i], to.c[i], value.c[i]);}
  343. Dbl LerpR(C VecD4 &from, C VecD4 &to, C VecD4 &value) {Int i=Abs(to-from).maxI(); return LerpR(from.c[i], to.c[i], value.c[i]);}
  344. /******************************************************************************/
  345. Flt LerpAngle(Flt from, Flt to, Flt step) {return step*AngleDelta(from, to)+from;}
  346. /******************************************************************************/
  347. void Lerp4Weights(Vec4 &weights, Flt step)
  348. {
  349. Flt s =step,
  350. s2=step*step,
  351. s3=step*step*step;
  352. weights.x=(( -TANGENT)*(s3+s ) + (2*TANGENT )*s2 );
  353. weights.y=(( 2-TANGENT)* s3 + ( TANGENT-3)*s2 + 1);
  354. //weights.z=((-2+TANGENT)* s3 - (2*TANGENT-3)*s2 + TANGENT*s ); don't calculate it manually, use the fact that the sum is always equal to 1, using Z component was the fastest version tested
  355. weights.w=( TANGENT *(s3-s2) );
  356. weights.z=1-weights.x-weights.y-weights.w;
  357. }
  358. /******************************************************************************/
  359. Flt Lerp4(Flt v0, Flt v1, Flt v2, Flt v3, Flt step)
  360. {
  361. Vec4 weights; Lerp4Weights(weights, step); return v0*weights.x + v1*weights.y + v2*weights.z + v3*weights.w;
  362. }
  363. Vec2 Lerp4(C Vec2 &v0, C Vec2 &v1, C Vec2 &v2, C Vec2 &v3, Flt step)
  364. {
  365. Vec4 weights; Lerp4Weights(weights, step); return v0*weights.x + v1*weights.y + v2*weights.z + v3*weights.w;
  366. }
  367. Vec Lerp4(C Vec &v0, C Vec &v1, C Vec &v2, C Vec &v3, Flt step)
  368. {
  369. Vec4 weights; Lerp4Weights(weights, step); return v0*weights.x + v1*weights.y + v2*weights.z + v3*weights.w;
  370. }
  371. Vec4 Lerp4(C Vec4 &v0, C Vec4 &v1, C Vec4 &v2, C Vec4 &v3, Flt step)
  372. {
  373. Vec4 weights; Lerp4Weights(weights, step); return v0*weights.x + v1*weights.y + v2*weights.z + v3*weights.w;
  374. }
  375. /******************************************************************************/
  376. Flt LerpTan(Flt from, Flt to, Flt step, Flt tan0, Flt tan1)
  377. {
  378. return step*step*step * ((from-to)* 2 + tan0 + tan1)
  379. + step*step * ((from-to)*-3 - 2*tan0 - tan1)
  380. + step * ( tan0 )
  381. + from;
  382. }
  383. Vec2 LerpTan(C Vec2 &from, C Vec2 &to, Flt step, C Vec2 &tan0, C Vec2 &tan1)
  384. {
  385. Flt s2=step*step,
  386. s3=step*step*step;
  387. return from
  388. + (from-to) * (2*s3 - 3*s2 )
  389. + tan0 * ( s3 - 2*s2 + step)
  390. + tan1 * ( s3 - s2 );
  391. }
  392. Vec LerpTan(C Vec &from, C Vec &to, Flt step, C Vec &tan0, C Vec &tan1)
  393. {
  394. Flt s2=step*step,
  395. s3=step*step*step;
  396. return from
  397. + (from-to) * (2*s3 - 3*s2 )
  398. + tan0 * ( s3 - 2*s2 + step)
  399. + tan1 * ( s3 - s2 );
  400. }
  401. Vec4 LerpTan(C Vec4 &from, C Vec4 &to, Flt step, C Vec4 &tan0, C Vec4 &tan1)
  402. {
  403. Flt s2=step*step,
  404. s3=step*step*step;
  405. return from
  406. + (from-to) * (2*s3 - 3*s2 )
  407. + tan0 * ( s3 - 2*s2 + step)
  408. + tan1 * ( s3 - s2 );
  409. }
  410. /******************************************************************************/
  411. // ADJUST VALUE
  412. /******************************************************************************/
  413. void AdjustValDir(Flt &value, Int dir, Flt dv)
  414. {
  415. if(dir) // adjust by direction
  416. {
  417. value+=dir*dv;
  418. Clamp(value, -1, 1);
  419. }else
  420. if(Int s=Sign(value)) // move towards zero
  421. {
  422. value-=s*dv;
  423. if(Sign(value)!=s)value=0;
  424. }
  425. }
  426. void AdjustValDir(Flt &value, Int dir, Flt change, Flt reset)
  427. {
  428. if(dir) // adjust by direction
  429. {
  430. value+=dir*change;
  431. Clamp(value, -1, 1);
  432. }else
  433. if(Int s=Sign(value)) // move towards zero
  434. {
  435. value-=s*reset;
  436. if(Sign(value)!=s)value=0;
  437. }
  438. }
  439. /******************************************************************************/
  440. void AdjustValBool(Flt &value, Bool on, Flt dv)
  441. {
  442. if(on)value+=dv; // increase
  443. else value-=dv; // decrease
  444. SAT(value); // saturate
  445. }
  446. void AdjustValBool(Flt &value, Bool on, Flt inc, Flt dec)
  447. {
  448. if(on)value+=inc; // increase
  449. else value-=dec; // decrease
  450. SAT(value); // saturate
  451. }
  452. /******************************************************************************/
  453. void AdjustValBoolSet(Flt &value, Bool on, Bool set, Flt dv ) {if(set)value=on;else AdjustValBool(value, on, dv );} // immediately set or smoothly adjust
  454. void AdjustValBoolSet(Flt &value, Bool on, Bool set, Flt inc, Flt dec) {if(set)value=on;else AdjustValBool(value, on, inc, dec);} // immediately set or smoothly adjust
  455. /******************************************************************************/
  456. void AdjustValTime(Flt &value, Flt target, Flt exponent, Flt dt) {value=Pow(exponent, dt)*(value-target)+target;} // smoothly adjust value to 'target' according to 'exponent' and 'time delta'
  457. void AdjustValTime(Dbl &value, Dbl target, Flt exponent, Flt dt) {value=Pow(exponent, dt)*(value-target)+target;} // smoothly adjust value to 'target' according to 'exponent' and 'time delta'
  458. void AdjustValTime(Vec2 &value, C Vec2 &target, Flt exponent, Flt dt) {value=Pow(exponent, dt)*(value-target)+target;} // smoothly adjust value to 'target' according to 'exponent' and 'time delta'
  459. void AdjustValTime(Vec &value, C Vec &target, Flt exponent, Flt dt) {value=Pow(exponent, dt)*(value-target)+target;} // smoothly adjust value to 'target' according to 'exponent' and 'time delta'
  460. void AdjustValTime(VecD &value, C VecD &target, Flt exponent, Flt dt) {value=Pow(exponent, dt)*(value-target)+target;} // smoothly adjust value to 'target' according to 'exponent' and 'time delta'
  461. /******************************************************************************/
  462. void AdjustValTarget(Flt &value, Flt target, Flt dv)
  463. {
  464. if(value>target){value-=dv; if(value<target)value=target;}else // move towards 'target' by increasing 'value' by 'dv'
  465. if(value<target){value+=dv; if(value>target)value=target;} // move towards 'target' by decreasing 'value' by 'dv'
  466. }
  467. void AdjustValTarget(Dbl &value, Dbl target, Dbl dv)
  468. {
  469. if(value>target){value-=dv; if(value<target)value=target;}else // move towards 'target' by increasing 'value' by 'dv'
  470. if(value<target){value+=dv; if(value>target)value=target;} // move towards 'target' by decreasing 'value' by 'dv'
  471. }
  472. void AdjustValTarget(Flt &value, Flt target, Flt inc, Flt dec)
  473. {
  474. if(value>target){value-=dec; if(value<target)value=target;}else // move towards 'target' by increasing 'value' by 'inc'
  475. if(value<target){value+=inc; if(value>target)value=target;} // move towards 'target' by decreasing 'value' by 'dec'
  476. }
  477. void AdjustValTarget(Vec2 &value, C Vec2 &target, Flt dv)
  478. {
  479. AdjustValTarget(value.x, target.x, dv);
  480. AdjustValTarget(value.y, target.y, dv);
  481. }
  482. void AdjustValTarget(Vec &value, C Vec &target, Flt dv)
  483. {
  484. AdjustValTarget(value.x, target.x, dv);
  485. AdjustValTarget(value.y, target.y, dv);
  486. AdjustValTarget(value.z, target.z, dv);
  487. }
  488. void AdjustValTarget(VecD &value, C VecD &target, Dbl dv)
  489. {
  490. AdjustValTarget(value.x, target.x, dv);
  491. AdjustValTarget(value.y, target.y, dv);
  492. AdjustValTarget(value.z, target.z, dv);
  493. }
  494. /******************************************************************************/
  495. // SMOOTH OFFSET
  496. /******************************************************************************/
  497. Flt SmoothOffset(Flt &offset, Flt max_length)
  498. {
  499. Flt ofs=offset; if(Flt length=Abs(ofs))
  500. {
  501. ofs=Sign(ofs);
  502. const Flt factor=1.0f/PI_2; // mul by this because we're operating on 'Sin' below, and for low values "Sin(x*PI_2)" is equal to "x*PI_2/PI_2" (tested via "Functions" tool)
  503. length*=factor;
  504. if(length>max_length){offset=ofs*(max_length/factor); length=max_length;}
  505. Flt frac=length/max_length;
  506. frac=Sin(frac*PI_2);
  507. ofs*=max_length*frac;
  508. }
  509. return ofs;
  510. }
  511. Vec2 SmoothOffset(Vec2 &offset, Flt max_length)
  512. {
  513. Vec2 ofs=offset; if(Flt length=ofs.normalize())
  514. {
  515. const Flt factor=1.0f/PI_2; // mul by this because we're operating on 'Sin' below, and for low values "Sin(x*PI_2)" is equal to "x*PI_2/PI_2" (tested via "Functions" tool)
  516. length*=factor;
  517. if(length>max_length){offset=ofs*(max_length/factor); length=max_length;}
  518. Flt frac=length/max_length;
  519. frac=Sin(frac*PI_2);
  520. ofs*=max_length*frac;
  521. }
  522. return ofs;
  523. }
  524. Vec SmoothOffset(Vec &offset, Flt max_length)
  525. {
  526. Vec ofs=offset; if(Flt length=ofs.normalize())
  527. {
  528. const Flt factor=1.0f/PI_2; // mul by this because we're operating on 'Sin' below, and for low values "Sin(x*PI_2)" is equal to "x*PI_2/PI_2" (tested via "Functions" tool)
  529. length*=factor;
  530. if(length>max_length){offset=ofs*(max_length/factor); length=max_length;}
  531. Flt frac=length/max_length;
  532. frac=Sin(frac*PI_2);
  533. ofs*=max_length*frac;
  534. }
  535. return ofs;
  536. }
  537. /******************************************************************************/
  538. // SMOOTH CURVES
  539. /******************************************************************************/
  540. Flt SmoothSqr(Flt x)
  541. {
  542. if(x<=0 )return 0;
  543. if(x>=1 )return 1;
  544. if(x<=0.5f)return 2*Sqr( x);
  545. return 1-2*Sqr(1-x); // 1-2*Sqr(1-x) -> 1-2*(1+x*x-2*x) -> 1 - 2 - 2*x*x + 4*x -> -2*x*x + 4*x - 1 (however this formula has more operations)
  546. }
  547. Flt SmoothCube(Flt x)
  548. {
  549. if(x<=0)return 0;
  550. if(x>=1)return 1;
  551. return _SmoothCube(x);
  552. }
  553. Flt SmoothCubeInv(Flt y)
  554. {
  555. if(y<=0)return 0;
  556. if(y>=1)return 1;
  557. return 0.5f-Sin(asinf(1-2*y)/3);
  558. }
  559. Flt SmoothCube2(Flt x)
  560. {
  561. if(x<=0 )return 0;
  562. if(x>=1 )return 1;
  563. if(x<=0.5f)return 4*Cube( x);
  564. return 1-4*Cube(1-x);
  565. }
  566. Flt _SmoothQuintic(Flt x)
  567. {
  568. return x*x*x*(x*(x*6-15)+10);
  569. }
  570. Flt SmoothSextic(Flt x)
  571. {
  572. if(x<=0)return 0;
  573. if(x>=1)return 1;
  574. x*=x;
  575. return (4.0f/9)*x*x*x - (17.0f/9)*x*x + (22.0f/9)*x;
  576. }
  577. Flt SmoothSin(Flt x)
  578. {
  579. if(x<=0)return 0;
  580. if(x>=1)return 1;
  581. return 0.5f-0.5f*Cos(x*PI);
  582. }
  583. Flt SmoothPow(Flt x, Flt pow)
  584. {
  585. if(x<=0 )return 0;
  586. if(x>=1 )return 1;
  587. if(x<=0.5f)return 0.5f*Pow( 2*x, pow);
  588. return 1-0.5f*Pow(2-2*x, pow);
  589. }
  590. Flt SmoothPinch(Flt x, Flt pinch)
  591. {
  592. if(x<=0 )return 0;
  593. if(x>=1 )return 1;
  594. if(x<=0.5f)return 0.5f*Pinch( 2*x, pinch);
  595. return 1-0.5f*Pinch(2-2*x, pinch);
  596. }
  597. /******************************************************************************/
  598. // SIGMOID
  599. /******************************************************************************/
  600. Flt gd(Flt x) {return Atan(sinhf(x));}
  601. Dbl gd(Dbl x) {return Atan(sinh (x));}
  602. Flt SigmoidExp (Flt x) {return 2/(1+expf(-x))-1;}
  603. Flt SigmoidDiv (Flt x) {return x/(1+x);}
  604. Flt SigmoidAtan (Flt x) {return Atan(PI_2*x)*2/PI;}
  605. Flt SigmoidSqrt (Flt x) {return x/SqrtFast(1+x*x);}
  606. Flt SigmoidSqrtInv(Flt y) {return y/SqrtFast(1-y*y);}
  607. Flt SigmoidGd (Flt x) {return (2/PI)*gd(PI_2*x);}
  608. Flt SigmoidTanh (Flt x) {return tanhf(x);}
  609. Flt SigmoidErf (Flt x) {return erff((SqrtFast(PI)/2)*x);}
  610. /******************************************************************************/
  611. // BLENDING
  612. /******************************************************************************/
  613. Flt BlendSqr(Flt x)
  614. {
  615. x*=x;
  616. return (x<1) ? 1-x : 0;
  617. }
  618. Flt BlendSmoothSqr(Flt x)
  619. {
  620. ABS(x);
  621. return (x<=0.5f) ? 1-2*Sqr( x)
  622. : (x< 1 ) ? 2*Sqr(1-x)
  623. : 0;
  624. }
  625. Flt BlendSmoothCube(Flt x) // !! avoid changing this formula, but if it's changed, then adjust 'BlendSmoothCubeSum' and 'BlendSmoothCubeSumHalf' !!
  626. {
  627. ABS(x);
  628. return (x<1) ? 1-(3-2*x)*x*x : 0;
  629. }
  630. Flt BlendSmoothSextic(Flt x)
  631. {
  632. x*=x;
  633. return (x<1) ? (-4.0f/9)*x*x*x + (17.0f/9)*x*x - (22.0f/9)*x + 1 : 0;
  634. }
  635. Flt BlendSmoothSin(Flt x)
  636. {
  637. ABS(x);
  638. return (x<1) ? Cos(x*PI)*0.5f+0.5f : 0;
  639. }
  640. /******************************************************************************/
  641. Flt Gaussian(Flt x)
  642. {
  643. return expf(-x*x);
  644. }
  645. /******************************************************************************/
  646. // EQUATIONS
  647. /******************************************************************************/
  648. Int Polynominal1(Flt a, Flt b, Flt &x ) {if(!a)return Polynominal0(b); x=-b/a; return 1;}
  649. Int Polynominal1(Dbl a, Dbl b, Dbl &x ) {if(!a)return Polynominal0(b); x=-b/a; return 1;}
  650. Int Polynominal2(Flt a, Flt b, Flt c, Flt &x0, Flt &x1)
  651. {
  652. if(!a)return Polynominal1(b, c, x0);
  653. Flt delta=b*b-4*a*c;
  654. if( delta<0)return 0; a+=a;
  655. if(!delta){x0= -b /a; return 1;} delta=Sqrt(delta);
  656. x0=(-b-delta)/a;
  657. x1=(-b+delta)/a; return 2;
  658. }
  659. Int Polynominal2(Dbl a, Dbl b, Dbl c, Dbl &x0, Dbl &x1)
  660. {
  661. if(!a)return Polynominal1(b, c, x0);
  662. Dbl delta=b*b-4*a*c;
  663. if( delta<0)return 0; a+=a;
  664. if(!delta){x0= -b /a; return 1;} delta=Sqrt(delta);
  665. x0=(-b-delta)/a;
  666. x1=(-b+delta)/a; return 2;
  667. }
  668. Int Polynominal3(Flt a, Flt b, Flt c, Flt d, Flt &x0, Flt &x1, Flt &x2)
  669. {
  670. if(!a)return Polynominal2(b, c, d, x0, x1);
  671. Flt f=c/a - b*b/(a*a*3),
  672. g=2*b*b*b/(a*a*a*27) - b*c/(a*a*3) + d/a,
  673. h=g*g/4 + f*f*f/27;
  674. if(h>0)
  675. {
  676. g/=-2;
  677. h =Sqrt(h);
  678. x0=Cbrt(g+h)+Cbrt(g-h) - b/(3*a);
  679. return 1;
  680. }else
  681. if(!f && !g && !h)
  682. {
  683. x0=x1=x2=-Cbrt(d/a);
  684. return 3;
  685. }else
  686. if(h<=0)
  687. {
  688. Flt i= g*g/4 - h,
  689. p=-b/(3*a),
  690. m, n; CosSin(m, n, Acos(-0.5f*g/Sqrt(i))/3);
  691. i=Pow(i, 1.0f/6); n*=SQRT3;
  692. x0=2*i* m +p;
  693. x1= -i*(m+n)+p;
  694. x2= -i*(m-n)+p;
  695. return 3;
  696. }
  697. return 0;
  698. }
  699. Int Polynominal3(Dbl a, Dbl b, Dbl c, Dbl d, Dbl &x0, Dbl &x1, Dbl &x2)
  700. {
  701. if(!a)return Polynominal2(b, c, d, x0, x1);
  702. Dbl f=c/a - b*b/(a*a*3),
  703. g=2*b*b*b/(a*a*a*27) - b*c/(a*a*3) + d/a,
  704. h=g*g/4 + f*f*f/27;
  705. if(h>0)
  706. {
  707. g/=-2;
  708. h =Sqrt(h);
  709. x0=Cbrt(g+h)+Cbrt(g-h) - b/(3*a);
  710. return 1;
  711. }else
  712. if(!f && !g && !h)
  713. {
  714. x0=x1=x2=-Cbrt(d/a);
  715. return 3;
  716. }else
  717. if(h<=0)
  718. {
  719. Dbl i= g*g/4 - h,
  720. p=-b/(3*a),
  721. m, n; CosSin(m, n, Acos(-0.5*g/Sqrt(i))/3);
  722. i=Pow(i, 1.0/6); n*=SQRT3;
  723. x0=2*i* m +p;
  724. x1= -i*(m+n)+p;
  725. x2= -i*(m-n)+p;
  726. return 3;
  727. }
  728. return 0;
  729. }
  730. /******************************************************************************/
  731. Int Solve(Flt a1, Flt a2, Flt b1, Flt b2, Flt c1, Flt c2, Flt &x, Flt &y)
  732. {
  733. // x*a1 + y*b1 = c1
  734. // x*a2 + y*b2 = c2
  735. // W = | a1 b1 | = a1*b2 - b1*a2, Wx = | c1 b1 | = c1*b2 - c2*b1, Wy = | a1 c1 | = a1*c2 - a2*c1
  736. // | a2 b2 | | c2 b2 | | a2 c2 |
  737. if(Flt W=a1*b2 - b1*a2)
  738. {
  739. Flt Wx=c1*b2 - c2*b1,
  740. Wy=a1*c2 - a2*c1;
  741. if(!Wx && !Wy)return -1;
  742. x=Wx/W;
  743. y=Wy/W;
  744. return 1;
  745. }
  746. return 0;
  747. }
  748. Int Solve(Dbl a1, Dbl a2, Dbl b1, Dbl b2, Dbl c1, Dbl c2, Dbl &x, Dbl &y)
  749. {
  750. // x*a1 + y*b1 = c1
  751. // x*a2 + y*b2 = c2
  752. // W = | a1 b1 | = a1*b2 - b1*a2, Wx = | c1 b1 | = c1*b2 - c2*b1, Wy = | a1 c1 | = a1*c2 - a2*c1
  753. // | a2 b2 | | c2 b2 | | a2 c2 |
  754. if(Dbl W=a1*b2 - b1*a2)
  755. {
  756. Dbl Wx=c1*b2 - c2*b1,
  757. Wy=a1*c2 - a2*c1;
  758. if(!Wx && !Wy)return -1;
  759. x=Wx/W;
  760. y=Wy/W;
  761. return 1;
  762. }
  763. return 0;
  764. }
  765. /******************************************************************************
  766. 64 BIT FLOAT - S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF (S-1 bit Sign, E-11 bit Exponent, F-52 bit Fraction)
  767. 32 BIT FLOAT - S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF (S-1 bit Sign, E- 8 bit Exponent, F-23 bit Fraction)
  768. 16 BIT FLOAT - S EEEEE FFFFFFFFFF (S-1 bit Sign, E- 5 bit Exponent, F-10 bit Fraction)
  769. 32:
  770. Exponent | Fraction Zero | Fraction Non-Zero | Equation
  771. 0 | +0 -0 | subnormal numbers | Pow(-1, sign) * Pow(2, -126) * 0.Fraction
  772. 1..254 | value | value | Pow(-1, sign) * Pow(2, exponent-127) * 1.Fraction
  773. 255 | +Inf -Inf | NaN |
  774. 16:
  775. Exponent | Fraction Zero | Fraction Non-Zero | Equation
  776. 0 | +0 -0 | subnormal numbers | Pow(-1, sign) * Pow(2, -14) * 0.Fraction
  777. 1..30 | value | value | Pow(-1, sign) * Pow(2, exponent-15) * 1.Fraction
  778. 31 | +Inf -Inf | NaN |
  779. /******************************************************************************/
  780. Half::operator Flt()C
  781. {
  782. UInt f;
  783. Int e=(data&0x7C00);
  784. if(e== 0)f=((data&0x8000)<<16);else
  785. if(e==0x7C00)f=((data&0x8000)<<16) | (0xFF <<23) | ((data&0x03FF)<<13);else
  786. f=((data&0x8000)<<16) | ((e+0x1C000)<<13) | ((data&0x03FF)<<13); // (127-15)<<10 = 0x1C000
  787. return (Flt&)f;
  788. }
  789. /*Half::Half(Bool b) {data=(b ? 15360 : 0);}
  790. Half::Half(Int i) : Half(Flt(i)) {}
  791. Half::Half(UInt i) : Half(Flt(i)) {}*/
  792. Half::Half(Flt f)
  793. {
  794. UInt u=(U32&)f;
  795. // Int e=((u>>23)&0xFF)+(15-127);
  796. // if(e<= 0)data= (u>>16)&0x8000;else
  797. // if(e> 31)data=((u>>16)&0x8000) | (31<<10) | ((u>>13)&0x03FF);else
  798. // data=((u>>16)&0x8000) | ( e<<10) | ((u>>13)&0x03FF);
  799. Int e =(u&0x7F800000);
  800. if( e<= 0x38000000)data= (u>>16)&0x8000;else
  801. if( e>= 0x47800000)data=((u>>16)&0x8000) | ( 31 <<10) | ((u>>13)&0x03FF);else
  802. data=((u>>16)&0x8000) | ((e-0x38000000)>>13) | ((u>>13)&0x03FF);
  803. }
  804. /******************************************************************************/
  805. void DecRealByBit(Flt &r)
  806. {
  807. UInt u =(U32&)r,
  808. f =(u&0x7FFFFF),
  809. exp =((u>>23)&0xFF);
  810. Bool sign=(u>>31);
  811. if( !sign)
  812. {
  813. f--;
  814. f&=0x7FFFFF;
  815. switch(f)
  816. {
  817. case 0x7FFFFF: if(exp)exp--;else{sign=true; /*exp=0;*/ f=1;} break; // -eps
  818. }
  819. }else
  820. if(exp<0xFF)
  821. {
  822. f++;
  823. f&=0x7FFFFF;
  824. if(!f)exp++;
  825. }
  826. (U32&)r=(sign<<31)|(exp<<23)|f;
  827. }
  828. void IncRealByBit(Flt &r)
  829. {
  830. UInt u =(U32&)r,
  831. f =(u&0x7FFFFF),
  832. exp =((u>>23)&0xFF);
  833. Bool sign=(u>>31);
  834. if( sign)
  835. {
  836. f--;
  837. f&=0x7FFFFF;
  838. switch(f)
  839. {
  840. case 0x7FFFFF: if(exp)exp--;else{sign=false; /*exp=0;*/ f=1;} break; // eps
  841. case 0x000000: if(!exp){sign=false; /*exp=0;*/ f=0;} break; // fix -0 -> 0
  842. }
  843. }else
  844. if(exp<0xFF)
  845. {
  846. f++;
  847. f&=0x7FFFFF;
  848. if(!f)exp++;
  849. }
  850. (U32&)r=(sign<<31)|(exp<<23)|f;
  851. }
  852. void DecRealByBit(Dbl &r)
  853. {
  854. ULong u =(U64&)r,
  855. f =(u&0xFFFFFFFFFFFFF),
  856. exp =((u>>52)&0x7FF),
  857. sign=(u>>63);
  858. if( !sign)
  859. {
  860. f--;
  861. f&=0xFFFFFFFFFFFFF;
  862. switch(f)
  863. {
  864. case 0xFFFFFFFFFFFFF: if(exp)exp--;else{sign=true; /*exp=0;*/ f=1;} break; // -eps
  865. }
  866. }else
  867. if(exp<0x7FF)
  868. {
  869. f++;
  870. f&=0xFFFFFFFFFFFFF;
  871. if(!f)exp++;
  872. }
  873. (U64&)r=(sign<<63)|(exp<<52)|f;
  874. }
  875. void IncRealByBit(Dbl &r)
  876. {
  877. ULong u =(U64&)r,
  878. f =(u&0xFFFFFFFFFFFFF),
  879. exp =((u>>52)&0x7FF),
  880. sign=(u>>63);
  881. if( sign)
  882. {
  883. f--;
  884. f&=0xFFFFFFFFFFFFF;
  885. switch(f)
  886. {
  887. case 0xFFFFFFFFFFFFF: if(exp)exp--;else{sign=false; /*exp=0;*/ f=1;} break; // eps
  888. case 0x0000000000000: if(!exp){sign=false; /*exp=0;*/ f=0;} break; // fix -0 -> 0
  889. }
  890. }else
  891. if(exp<0x7FF)
  892. {
  893. f++;
  894. f&=0xFFFFFFFFFFFFF;
  895. if(!f)exp++;
  896. }
  897. (U64&)r=(sign<<63)|(exp<<52)|f;
  898. }
  899. /******************************************************************************/
  900. // Standard Deviational Ellipse
  901. // http://resources.esri.com/help/9.3/arcgisengine/java/gp_toolref/spatial_statistics_tools/how_directional_distribution_colon_standard_deviational_ellipse_spatial_statistics_works.htm
  902. void AvgDirU(Vec2 &dir, C MemPtr<Vec2> &points)
  903. {
  904. Flt x2=0, y2=0, xy=0;
  905. REPA(points)
  906. {
  907. C Vec2 &p=points[i];
  908. x2+=Sqr(p.x);
  909. y2+=Sqr(p.y);
  910. xy+=p.x*p.y;
  911. }
  912. Flt a=x2-y2,
  913. c=2*xy,
  914. b=Dist(a, c);
  915. dir.set(a+b, c); // if we would normalize, then dir.x=cos, dir.y=sin
  916. }
  917. /*
  918. void AvgDirU(Vec &dir, C MemPtr<Vec > &points); // get average direction from array of points, points should be located around center Vec (0,0,0), direction is not normalized
  919. void AvgDirU(Vec &dir, C MemPtr<Vec> &points)
  920. {
  921. this is wrong
  922. Flt x2=0, y2=0, z2=0, xy=0, xz=0;
  923. REPA(points)
  924. {
  925. C Vec &p=points[i];
  926. x2+=Sqr(p.x);
  927. y2+=Sqr(p.y);
  928. z2+=Sqr(p.z);
  929. xy+=p.x*p.y;
  930. xz+=p.x*p.z;
  931. }
  932. Flt a=x2-y2,
  933. c=2*xy,
  934. b=Dist(a, c);
  935. dir.x=a+b; dir.y=c;
  936. dir.z=c;
  937. }*/
  938. /******************************************************************************
  939. void MathAssert()
  940. {
  941. DEBUG_ASSERT(FloorSpecial(0)==-1 && FloorSpecial(0.01f)==0 && FloorSpecial(0.5f)==0 && FloorSpecial(0.99f)==0 && FloorSpecial(1.0f)==0, "FloorSpecial");
  942. DEBUG_ASSERT( CeilSpecial(0)== 1 && CeilSpecial(0.01f)==1 && CeilSpecial(0.5f)==1 && CeilSpecial(0.99f)==1 && CeilSpecial(1.0f)==2, "CeilSpecial");
  943. }
  944. /******************************************************************************/
  945. }
  946. /******************************************************************************/