math.pp 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {
  12. This unit is an equivalent to the Delphi math unit
  13. (with some improvements)
  14. What's to do:
  15. o a lot of function :), search for !!!!
  16. o some statistical functions
  17. o all financial functions
  18. o optimizations
  19. }
  20. unit math;
  21. interface
  22. {$MODE objfpc}
  23. uses
  24. sysutils;
  25. { Ranges of the IEEE floating point types, including denormals }
  26. {$ifdef FPC_HAS_TYPE_SINGLE}
  27. const
  28. MinSingle = 1.5e-45;
  29. MaxSingle = 3.4e+38;
  30. {$endif FPC_HAS_TYPE_SINGLE}
  31. {$ifdef FPC_HAS_TYPE_DOUBLE}
  32. const
  33. MinDouble = 5.0e-324;
  34. MaxDouble = 1.7e+308;
  35. {$endif FPC_HAS_TYPE_DOUBLE}
  36. {$ifdef FPC_HAS_TYPE_EXTENDED}
  37. const
  38. MinExtended = 3.4e-4932;
  39. MaxExtended = 1.1e+4932;
  40. {$endif FPC_HAS_TYPE_EXTENDED}
  41. {$ifdef FPC_HAS_TYPE_COMP}
  42. const
  43. MinComp = -9.223372036854775807e+18;
  44. MaxComp = 9.223372036854775807e+18;
  45. {$endif FPC_HAS_TYPE_COMP}
  46. { the original delphi functions use extended as argument, }
  47. { but I would prefer double, because 8 bytes is a very }
  48. { natural size for the processor }
  49. { WARNING : changing float type will }
  50. { break all assembler code PM }
  51. {$ifdef FPC_HAS_TYPE_FLOAT128}
  52. type
  53. float = float128;
  54. const
  55. MinFloat = MinFloat128;
  56. MaxFloat = MaxFloat128;
  57. {$else FPC_HAS_TYPE_FLOAT128}
  58. {$ifdef FPC_HAS_TYPE_EXTENDED}
  59. type
  60. float = extended;
  61. const
  62. MinFloat = MinExtended;
  63. MaxFloat = MaxExtended;
  64. {$else FPC_HAS_TYPE_EXTENDED}
  65. {$ifdef FPC_HAS_TYPE_DOUBLE}
  66. type
  67. float = double;
  68. const
  69. MinFloat = MinDouble;
  70. MaxFloat = MaxDouble;
  71. {$else FPC_HAS_TYPE_DOUBLE}
  72. {$ifdef FPC_HAS_TYPE_SINGLE}
  73. type
  74. float = single;
  75. const
  76. MinFloat = MinSingle;
  77. MaxFloat = MaxSingle;
  78. {$else FPC_HAS_TYPE_SINGLE}
  79. {$fatal At least one floating point type must be supported}
  80. {$endif FPC_HAS_TYPE_SINGLE}
  81. {$endif FPC_HAS_TYPE_DOUBLE}
  82. {$endif FPC_HAS_TYPE_EXTENDED}
  83. {$endif FPC_HAS_TYPE_FLOAT128}
  84. type
  85. PFloat = ^Float;
  86. PInteger = ^Integer;
  87. tpaymenttime = (ptendofperiod,ptstartofperiod);
  88. einvalidargument = class(ematherror);
  89. TValueRelationship = -1..1;
  90. const
  91. EqualsValue = 0;
  92. LessThanValue = Low(TValueRelationship);
  93. GreaterThanValue = High(TValueRelationship);
  94. {$ifopt R+}
  95. {$define RangeCheckWasOn}
  96. {$R-}
  97. {$endif opt R+}
  98. {$ifopt Q+}
  99. {$define OverflowCheckWasOn}
  100. {$Q-}
  101. {$endif opt Q+}
  102. {$ifdef CPUARM}
  103. { the ARM linux emulator doesn't like 0.0/0.0 }
  104. NaN = ln(-1.0);
  105. {$else CPUARM}
  106. NaN = 0.0/0.0;
  107. {$endif CPUARM}
  108. Infinity = 1.0/0.0;
  109. {$ifdef RangeCheckWasOn}
  110. {$R+}
  111. {$undef RangeCheckWasOn}
  112. {$endif}
  113. {$ifdef OverflowCheckWasOn}
  114. {$Q+}
  115. {$undef OverflowCheckWasOn}
  116. {$endif}
  117. { Min/max determination }
  118. function MinIntValue(const Data: array of Integer): Integer;
  119. function MaxIntValue(const Data: array of Integer): Integer;
  120. { Extra, not present in Delphi, but used frequently }
  121. function Min(a, b: Integer): Integer;
  122. function Max(a, b: Integer): Integer;
  123. function Min(a, b: Cardinal): Cardinal;
  124. function Max(a, b: Cardinal): Cardinal;
  125. function Min(a, b: Int64): Int64;
  126. function Max(a, b: Int64): Int64;
  127. {$ifdef FPC_HAS_TYPE_SINGLE}
  128. function Min(a, b: Single): Single;
  129. function Max(a, b: Single): Single;
  130. {$endif FPC_HAS_TYPE_SINGLE}
  131. {$ifdef FPC_HAS_TYPE_DOUBLE}
  132. function Min(a, b: Double): Double;
  133. function Max(a, b: Double): Double;
  134. {$endif FPC_HAS_TYPE_DOUBLE}
  135. {$ifdef FPC_HAS_TYPE_EXTENDED}
  136. function Min(a, b: Extended): Extended;
  137. function Max(a, b: Extended): Extended;
  138. {$endif FPC_HAS_TYPE_EXTENDED}
  139. function InRange(const AValue, AMin, AMax: Integer): Boolean;
  140. function InRange(const AValue, AMin, AMax: Int64): Boolean;
  141. {$ifdef FPC_HAS_TYPE_DOUBLE}
  142. function InRange(const AValue, AMin, AMax: Double): Boolean;
  143. {$endif FPC_HAS_TYPE_DOUBLE}
  144. function EnsureRange(const AValue, AMin, AMax: Integer): Integer;
  145. function EnsureRange(const AValue, AMin, AMax: Int64): Int64;
  146. {$ifdef FPC_HAS_TYPE_DOUBLE}
  147. function EnsureRange(const AValue, AMin, AMax: Double): Double;
  148. {$endif FPC_HAS_TYPE_DOUBLE}
  149. procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);
  150. // Sign functions
  151. Type
  152. TValueSign = -1..1;
  153. const
  154. NegativeValue = Low(TValueSign);
  155. ZeroValue = 0;
  156. PositiveValue = High(TValueSign);
  157. function Sign(const AValue: Integer): TValueSign;
  158. function Sign(const AValue: Int64): TValueSign;
  159. function Sign(const AValue: Double): TValueSign;
  160. function IsZero(const A: Single; Epsilon: Single): Boolean;
  161. function IsZero(const A: Single): Boolean;
  162. {$ifdef FPC_HAS_TYPE_DOUBLE}
  163. function IsZero(const A: Double; Epsilon: Double): Boolean;
  164. function IsZero(const A: Double): Boolean;
  165. {$endif FPC_HAS_TYPE_DOUBLE}
  166. {$ifdef FPC_HAS_TYPE_EXTENDED}
  167. function IsZero(const A: Extended; Epsilon: Extended): Boolean;
  168. function IsZero(const A: Extended): Boolean;
  169. {$endif FPC_HAS_TYPE_EXTENDED}
  170. function IsNan(const d : Double): Boolean;
  171. function IsInfinite(const d : Double): Boolean;
  172. {$ifdef FPC_HAS_TYPE_EXTENDED}
  173. function SameValue(const A, B: Extended): Boolean;
  174. {$endif}
  175. {$ifdef FPC_HAS_TYPE_DOUBLE}
  176. function SameValue(const A, B: Double): Boolean;
  177. {$endif}
  178. function SameValue(const A, B: Single): Boolean;
  179. {$ifdef FPC_HAS_TYPE_EXTENDED}
  180. function SameValue(const A, B: Extended; Epsilon: Extended): Boolean;
  181. {$endif}
  182. {$ifdef FPC_HAS_TYPE_DOUBLE}
  183. function SameValue(const A, B: Double; Epsilon: Double): Boolean;
  184. {$endif}
  185. function SameValue(const A, B: Single; Epsilon: Single): Boolean;
  186. { angle conversion }
  187. function degtorad(deg : float) : float;
  188. function radtodeg(rad : float) : float;
  189. function gradtorad(grad : float) : float;
  190. function radtograd(rad : float) : float;
  191. function degtograd(deg : float) : float;
  192. function gradtodeg(grad : float) : float;
  193. { one cycle are 2*Pi rad }
  194. function cycletorad(cycle : float) : float;
  195. function radtocycle(rad : float) : float;
  196. { trigoniometric functions }
  197. function tan(x : float) : float;
  198. function cotan(x : float) : float;
  199. procedure sincos(theta : float;var sinus,cosinus : float);
  200. { inverse functions }
  201. function arccos(x : float) : float;
  202. function arcsin(x : float) : float;
  203. { calculates arctan(y/x) and returns an angle in the correct quadrant }
  204. function arctan2(y,x : float) : float;
  205. { hyperbolic functions }
  206. function cosh(x : float) : float;
  207. function sinh(x : float) : float;
  208. function tanh(x : float) : float;
  209. { area functions }
  210. { delphi names: }
  211. function arccosh(x : float) : float;
  212. function arcsinh(x : float) : float;
  213. function arctanh(x : float) : float;
  214. { IMHO the function should be called as follows (FK) }
  215. function arcosh(x : float) : float;
  216. function arsinh(x : float) : float;
  217. function artanh(x : float) : float;
  218. { triangle functions }
  219. { returns the length of the hypotenuse of a right triangle }
  220. { if x and y are the other sides }
  221. function hypot(x,y : float) : float;
  222. { logarithm functions }
  223. function log10(x : float) : float;
  224. function log2(x : float) : float;
  225. function logn(n,x : float) : float;
  226. { returns natural logarithm of x+1 }
  227. function lnxp1(x : float) : float;
  228. { exponential functions }
  229. function power(base,exponent : float) : float;
  230. { base^exponent }
  231. function intpower(base : float;const exponent : Integer) : float;
  232. operator ** (bas,expo : float) e: float;
  233. operator ** (bas,expo : int64) i: int64;
  234. { number converting }
  235. { rounds x towards positive infinity }
  236. function ceil(x : float) : Integer;
  237. { rounds x towards negative infinity }
  238. function floor(x : float) : Integer;
  239. { misc. functions }
  240. { splits x into mantissa and exponent (to base 2) }
  241. procedure Frexp(X: float; var Mantissa: float; var Exponent: integer);
  242. { returns x*(2^p) }
  243. function ldexp(x : float; const p : Integer) : float;
  244. { statistical functions }
  245. function mean(const data : array of float) : float;
  246. function sum(const data : array of float) : float;
  247. function mean(const data : PFloat; Const N : longint) : float;
  248. function sum(const data : PFloat; Const N : Longint) : float;
  249. function sumofsquares(const data : array of float) : float;
  250. function sumofsquares(const data : PFloat; Const N : Integer) : float;
  251. { calculates the sum and the sum of squares of data }
  252. procedure sumsandsquares(const data : array of float;
  253. var sum,sumofsquares : float);
  254. procedure sumsandsquares(const data : PFloat; Const N : Integer;
  255. var sum,sumofsquares : float);
  256. function minvalue(const data : array of float) : float;
  257. function minvalue(const data : array of integer) : Integer;
  258. function minvalue(const data : PFloat; Const N : Integer) : float;
  259. function MinValue(const Data : PInteger; Const N : Integer): Integer;
  260. function maxvalue(const data : array of float) : float;
  261. function maxvalue(const data : array of integer) : Integer;
  262. function maxvalue(const data : PFloat; Const N : Integer) : float;
  263. function maxvalue(const data : PInteger; Const N : Integer) : Integer;
  264. { calculates the standard deviation }
  265. function stddev(const data : array of float) : float;
  266. function stddev(const data : PFloat; Const N : Integer) : float;
  267. { calculates the mean and stddev }
  268. procedure meanandstddev(const data : array of float;
  269. var mean,stddev : float);
  270. procedure meanandstddev(const data : PFloat;
  271. Const N : Longint;var mean,stddev : float);
  272. function variance(const data : array of float) : float;
  273. function totalvariance(const data : array of float) : float;
  274. function variance(const data : PFloat; Const N : Integer) : float;
  275. function totalvariance(const data : PFloat; Const N : Integer) : float;
  276. { returns random values with gaussian distribution }
  277. function randg(mean,stddev : float) : float;
  278. { I don't know what the following functions do: }
  279. function popnstddev(const data : array of float) : float;
  280. function popnstddev(const data : PFloat; Const N : Integer) : float;
  281. function popnvariance(const data : PFloat; Const N : Integer) : float;
  282. function popnvariance(const data : array of float) : float;
  283. procedure momentskewkurtosis(const data : array of float;
  284. var m1,m2,m3,m4,skew,kurtosis : float);
  285. procedure momentskewkurtosis(const data : PFloat; Const N : Integer;
  286. var m1,m2,m3,m4,skew,kurtosis : float);
  287. { geometrical function }
  288. { returns the euclidean L2 norm }
  289. function norm(const data : array of float) : float;
  290. function norm(const data : PFloat; Const N : Integer) : float;
  291. function ifthen(val:boolean;const iftrue:integer; const iffalse:integer= 0) :integer; {$ifdef MATHINLINE}inline; {$endif}
  292. function ifthen(val:boolean;const iftrue:int64 ; const iffalse:int64 = 0) :int64; {$ifdef MATHINLINE}inline; {$endif}
  293. function ifthen(val:boolean;const iftrue:double ; const iffalse:double =0.0):double; {$ifdef MATHINLINE}inline; {$endif}
  294. { include cpu specific stuff }
  295. {$i mathuh.inc}
  296. implementation
  297. { include cpu specific stuff }
  298. {$i mathu.inc}
  299. ResourceString
  300. SMathError = 'Math Error : %s';
  301. SInvalidArgument = 'Invalid argument';
  302. Procedure DoMathError(Const S : String);
  303. begin
  304. Raise EMathError.CreateFmt(SMathError,[S]);
  305. end;
  306. Procedure InvalidArgument;
  307. begin
  308. Raise EInvalidArgument.Create(SInvalidArgument);
  309. end;
  310. function Sign(const AValue: Integer): TValueSign;
  311. begin
  312. If Avalue<0 then
  313. Result:=NegativeValue
  314. else If Avalue>0 then
  315. Result:=PositiveValue
  316. else
  317. Result:=ZeroValue;
  318. end;
  319. function Sign(const AValue: Int64): TValueSign;
  320. begin
  321. If Avalue<0 then
  322. Result:=NegativeValue
  323. else If Avalue>0 then
  324. Result:=PositiveValue
  325. else
  326. Result:=ZeroValue;
  327. end;
  328. function Sign(const AValue: Double): TValueSign;
  329. begin
  330. If Avalue<0.0 then
  331. Result:=NegativeValue
  332. else If Avalue>0.0 then
  333. Result:=PositiveValue
  334. else
  335. Result:=ZeroValue;
  336. end;
  337. function degtorad(deg : float) : float;
  338. begin
  339. degtorad:=deg*(pi/180.0);
  340. end;
  341. function radtodeg(rad : float) : float;
  342. begin
  343. radtodeg:=rad*(180.0/pi);
  344. end;
  345. function gradtorad(grad : float) : float;
  346. begin
  347. gradtorad:=grad*(pi/200.0);
  348. end;
  349. function radtograd(rad : float) : float;
  350. begin
  351. radtograd:=rad*(200.0/pi);
  352. end;
  353. function degtograd(deg : float) : float;
  354. begin
  355. degtograd:=deg*(200.0/180.0);
  356. end;
  357. function gradtodeg(grad : float) : float;
  358. begin
  359. gradtodeg:=grad*(180.0/200.0);
  360. end;
  361. function cycletorad(cycle : float) : float;
  362. begin
  363. cycletorad:=(2*pi)*cycle;
  364. end;
  365. function radtocycle(rad : float) : float;
  366. begin
  367. { avoid division }
  368. radtocycle:=rad*(1/(2*pi));
  369. end;
  370. function tan(x : float) : float;
  371. begin
  372. Tan:=Sin(x)/Cos(x)
  373. end;
  374. function cotan(x : float) : float;
  375. begin
  376. cotan:=Cos(X)/Sin(X);
  377. end;
  378. procedure sincos(theta : float;var sinus,cosinus : float);
  379. begin
  380. sinus:=sin(theta);
  381. cosinus:=cos(theta);
  382. end;
  383. { ArcSin and ArcCos from Arjan van Dijk ([email protected]) }
  384. function arcsin(x : float) : float;
  385. begin
  386. if abs(x) > 1 then InvalidArgument
  387. else if abs(x) < 0.5 then
  388. arcsin := arctan(x/sqrt(1-sqr(x)))
  389. else
  390. arcsin := sign(x) * (pi*0.5 - arctan(sqrt(1 / sqr(x) - 1)));
  391. end;
  392. function Arccos(x : Float) : Float;
  393. begin
  394. arccos := pi*0.5 - arcsin(x);
  395. end;
  396. {$ifndef FPC_MATH_HAS_ARCTAN2}
  397. function arctan2(y,x : float) : float;
  398. begin
  399. if (x=0) then
  400. begin
  401. if y=0 then
  402. arctan2:=0.0
  403. else if y>0 then
  404. arctan2:=pi/2
  405. else if y<0 then
  406. arctan2:=-pi/2;
  407. end
  408. else
  409. ArcTan2:=ArcTan(y/x);
  410. if x<0.0 then
  411. ArcTan2:=ArcTan2+pi;
  412. if ArcTan2>pi then
  413. ArcTan2:=ArcTan2-2*pi;
  414. end;
  415. {$endif FPC_MATH_HAS_ARCTAN2}
  416. function cosh(x : float) : float;
  417. var
  418. temp : float;
  419. begin
  420. temp:=exp(x);
  421. cosh:=0.5*(temp+1.0/temp);
  422. end;
  423. function sinh(x : float) : float;
  424. var
  425. temp : float;
  426. begin
  427. temp:=exp(x);
  428. sinh:=0.5*(temp-1.0/temp);
  429. end;
  430. Const MaxTanh = 5678.22249441322; // Ln(MaxExtended)/2
  431. function tanh(x : float) : float;
  432. var Temp : float;
  433. begin
  434. if x>MaxTanh then exit(1.0)
  435. else if x<-MaxTanh then exit (-1.0);
  436. temp:=exp(-2*x);
  437. tanh:=(1-temp)/(1+temp)
  438. end;
  439. function arccosh(x : float) : float;
  440. begin
  441. arccosh:=arcosh(x);
  442. end;
  443. function arcsinh(x : float) : float;
  444. begin
  445. arcsinh:=arsinh(x);
  446. end;
  447. function arctanh(x : float) : float;
  448. begin
  449. if x>1 then InvalidArgument;
  450. arctanh:=artanh(x);
  451. end;
  452. function arcosh(x : float) : float;
  453. begin
  454. if x<1 then InvalidArgument;
  455. arcosh:=Ln(x+Sqrt(x*x-1));
  456. end;
  457. function arsinh(x : float) : float;
  458. begin
  459. arsinh:=Ln(x+Sqrt(1+x*x));
  460. end;
  461. function artanh(x : float) : float;
  462. begin
  463. If abs(x)>1 then InvalidArgument;
  464. artanh:=(Ln((1+x)/(1-x)))*0.5;
  465. end;
  466. function hypot(x,y : float) : float;
  467. begin
  468. hypot:=Sqrt(x*x+y*y)
  469. end;
  470. function log10(x : float) : float;
  471. begin
  472. log10:=ln(x)/ln(10);
  473. end;
  474. function log2(x : float) : float;
  475. begin
  476. log2:=ln(x)/ln(2)
  477. end;
  478. function logn(n,x : float) : float;
  479. begin
  480. if n<0 then InvalidArgument;
  481. logn:=ln(x)/ln(n);
  482. end;
  483. function lnxp1(x : float) : float;
  484. begin
  485. if x<-1 then
  486. InvalidArgument;
  487. lnxp1:=ln(1+x);
  488. end;
  489. function power(base,exponent : float) : float;
  490. begin
  491. if Exponent=0.0 then
  492. if base <> 0.0 then
  493. result:=1.0
  494. else
  495. InvalidArgument
  496. else if (base=0.0) and (exponent>0.0) then
  497. result:=0.0
  498. else if (abs(exponent)<=maxint) and (frac(exponent)=0.0) then
  499. result:=intpower(base,trunc(exponent))
  500. else if base>0.0 then
  501. result:=exp(exponent * ln (base))
  502. else
  503. InvalidArgument;
  504. end;
  505. function intpower(base : float;const exponent : Integer) : float;
  506. var
  507. i : longint;
  508. begin
  509. if (base = 0.0) and (exponent = 0) then
  510. InvalidArgument;
  511. i:=abs(exponent);
  512. intpower:=1.0;
  513. while i>0 do
  514. begin
  515. while (i and 1)=0 do
  516. begin
  517. i:=i shr 1;
  518. base:=sqr(base);
  519. end;
  520. i:=i-1;
  521. intpower:=intpower*base;
  522. end;
  523. if exponent<0 then
  524. intpower:=1.0/intpower;
  525. end;
  526. operator ** (bas,expo : float) e: float;
  527. begin
  528. e:=power(bas,expo);
  529. end;
  530. operator ** (bas,expo : int64) i: int64;
  531. begin
  532. i:=round(intpower(bas,expo));
  533. end;
  534. function ceil(x : float) : integer;
  535. begin
  536. Ceil:=Trunc(x);
  537. If Frac(x)>0 then
  538. Ceil:=Ceil+1;
  539. end;
  540. function floor(x : float) : integer;
  541. begin
  542. Floor:=Trunc(x);
  543. If Frac(x)<0 then
  544. Floor := Floor-1;
  545. end;
  546. procedure Frexp(X: float; var Mantissa: float; var Exponent: integer);
  547. begin
  548. Exponent :=0;
  549. if (abs(x)<0.5) then
  550. While (abs(x)<0.5) do
  551. begin
  552. x := x*2;
  553. Dec(Exponent);
  554. end
  555. else
  556. While (abs(x)>1) do
  557. begin
  558. x := x/2;
  559. Inc(Exponent);
  560. end;
  561. mantissa := x;
  562. end;
  563. function ldexp(x : float;const p : Integer) : float;
  564. begin
  565. ldexp:=x*intpower(2.0,p);
  566. end;
  567. function mean(const data : array of float) : float;
  568. begin
  569. Result:=Mean(@data[0],High(Data)+1);
  570. end;
  571. function mean(const data : PFloat; Const N : longint) : float;
  572. begin
  573. mean:=sum(Data,N);
  574. mean:=mean/N;
  575. end;
  576. function sum(const data : array of float) : float;
  577. begin
  578. Result:=Sum(@Data[0],High(Data)+1);
  579. end;
  580. function sum(const data : PFloat;Const N : longint) : float;
  581. var
  582. i : longint;
  583. begin
  584. sum:=0.0;
  585. for i:=0 to N-1 do
  586. sum:=sum+data[i];
  587. end;
  588. function sumofsquares(const data : array of float) : float;
  589. begin
  590. Result:=sumofsquares(@data[0],High(Data)+1);
  591. end;
  592. function sumofsquares(const data : PFloat; Const N : Integer) : float;
  593. var
  594. i : longint;
  595. begin
  596. sumofsquares:=0.0;
  597. for i:=0 to N-1 do
  598. sumofsquares:=sumofsquares+sqr(data[i]);
  599. end;
  600. procedure sumsandsquares(const data : array of float;
  601. var sum,sumofsquares : float);
  602. begin
  603. sumsandsquares (@Data[0],High(Data)+1,Sum,sumofsquares);
  604. end;
  605. procedure sumsandsquares(const data : PFloat; Const N : Integer;
  606. var sum,sumofsquares : float);
  607. var
  608. i : Integer;
  609. temp : float;
  610. begin
  611. sumofsquares:=0.0;
  612. sum:=0.0;
  613. for i:=0 to N-1 do
  614. begin
  615. temp:=data[i];
  616. sumofsquares:=sumofsquares+sqr(temp);
  617. sum:=sum+temp;
  618. end;
  619. end;
  620. function stddev(const data : array of float) : float;
  621. begin
  622. Result:=Stddev(@Data[0],High(Data)+1)
  623. end;
  624. function stddev(const data : PFloat; Const N : Integer) : float;
  625. begin
  626. StdDev:=Sqrt(Variance(Data,N));
  627. end;
  628. procedure meanandstddev(const data : array of float;
  629. var mean,stddev : float);
  630. begin
  631. Meanandstddev(@Data[0],High(Data)+1,Mean,stddev);
  632. end;
  633. procedure meanandstddev(const data : PFloat;
  634. Const N : Longint;var mean,stddev : float);
  635. Var I : longint;
  636. begin
  637. Mean:=0;
  638. StdDev:=0;
  639. For I:=0 to N-1 do
  640. begin
  641. Mean:=Mean+Data[i];
  642. StdDev:=StdDev+Sqr(Data[i]);
  643. end;
  644. Mean:=Mean/N;
  645. StdDev:=(StdDev-N*Sqr(Mean));
  646. If N>1 then
  647. StdDev:=Sqrt(Stddev/(N-1))
  648. else
  649. StdDev:=0;
  650. end;
  651. function variance(const data : array of float) : float;
  652. begin
  653. Variance:=Variance(@Data[0],High(Data)+1);
  654. end;
  655. function variance(const data : PFloat; Const N : Integer) : float;
  656. begin
  657. If N=1 then
  658. Result:=0
  659. else
  660. Result:=TotalVariance(Data,N)/(N-1);
  661. end;
  662. function totalvariance(const data : array of float) : float;
  663. begin
  664. Result:=TotalVariance(@Data[0],High(Data)+1);
  665. end;
  666. function totalvariance(const data : Pfloat;Const N : Integer) : float;
  667. var S,SS : Float;
  668. begin
  669. If N=1 then
  670. Result:=0
  671. else
  672. begin
  673. SumsAndSquares(Data,N,S,SS);
  674. Result := SS-Sqr(S)/N;
  675. end;
  676. end;
  677. function randg(mean,stddev : float) : float;
  678. Var U1,S2 : Float;
  679. begin
  680. repeat
  681. u1:= 2*random-1;
  682. S2:=Sqr(U1)+sqr(2*random-1);
  683. until s2<1;
  684. randg:=Sqrt(-2*ln(S2)/S2)*u1*stddev+Mean;
  685. end;
  686. function popnstddev(const data : array of float) : float;
  687. begin
  688. PopnStdDev:=Sqrt(PopnVariance(@Data[0],High(Data)+1));
  689. end;
  690. function popnstddev(const data : PFloat; Const N : Integer) : float;
  691. begin
  692. PopnStdDev:=Sqrt(PopnVariance(Data,N));
  693. end;
  694. function popnvariance(const data : array of float) : float;
  695. begin
  696. popnvariance:=popnvariance(@data[0],high(Data)+1);
  697. end;
  698. function popnvariance(const data : PFloat; Const N : Integer) : float;
  699. begin
  700. PopnVariance:=TotalVariance(Data,N)/N;
  701. end;
  702. procedure momentskewkurtosis(const data : array of float;
  703. var m1,m2,m3,m4,skew,kurtosis : float);
  704. begin
  705. momentskewkurtosis(@Data[0],High(Data)+1,m1,m2,m3,m4,skew,kurtosis);
  706. end;
  707. procedure momentskewkurtosis(const data : PFloat; Const N : Integer;
  708. var m1,m2,m3,m4,skew,kurtosis : float);
  709. Var S,SS,SC,SQ,invN,Acc,M1S,S2N,S3N,temp : Float;
  710. I : Longint;
  711. begin
  712. invN:=1.0/N;
  713. s:=0;
  714. ss:=0;
  715. sq:=0;
  716. sc:=0;
  717. for i:=0 to N-1 do
  718. begin
  719. temp:=Data[i]; { faster }
  720. S:=S+temp;
  721. acc:=temp*temp;
  722. ss:=ss+acc;
  723. Acc:=acc*temp;
  724. Sc:=sc+acc;
  725. acc:=acc*temp;
  726. sq:=sq+acc;
  727. end;
  728. M1:=s*invN;
  729. M1S:=M1*M1;
  730. S2N:=SS*invN;
  731. S3N:=SC*invN;
  732. M2:=S2N-M1S;
  733. M3:=S3N-(M1*3*S2N) + 2*M1S*M1;
  734. M4:=SQ*invN - (M1 * 4 * S3N) + (M1S*6*S2N-3*Sqr(M1S));
  735. Skew:=M3*power(M2,-3/2);
  736. Kurtosis:=M4 / Sqr(M2);
  737. end;
  738. function norm(const data : array of float) : float;
  739. begin
  740. norm:=Norm(@data[0],High(Data)+1);
  741. end;
  742. function norm(const data : PFloat; Const N : Integer) : float;
  743. begin
  744. norm:=sqrt(sumofsquares(data,N));
  745. end;
  746. function MinIntValue(const Data: array of Integer): Integer;
  747. var
  748. I: Integer;
  749. begin
  750. Result := Data[Low(Data)];
  751. For I := Succ(Low(Data)) To High(Data) Do
  752. If Data[I] < Result Then Result := Data[I];
  753. end;
  754. function MinValue(const Data: array of Integer): Integer;
  755. begin
  756. Result:=MinValue(Pinteger(@Data[0]),High(Data)+1)
  757. end;
  758. function MinValue(const Data: PInteger; Const N : Integer): Integer;
  759. var
  760. I: Integer;
  761. begin
  762. Result := Data[0];
  763. For I := 1 To N-1 do
  764. If Data[I] < Result Then Result := Data[I];
  765. end;
  766. function minvalue(const data : array of float) : float;
  767. begin
  768. Result:=minvalue(PFloat(@data[0]),High(Data)+1);
  769. end;
  770. function minvalue(const data : PFloat; Const N : Integer) : float;
  771. var
  772. i : longint;
  773. begin
  774. { get an initial value }
  775. minvalue:=data[0];
  776. for i:=1 to N-1 do
  777. if data[i]<minvalue then
  778. minvalue:=data[i];
  779. end;
  780. function MaxIntValue(const Data: array of Integer): Integer;
  781. var
  782. I: Integer;
  783. begin
  784. Result := Data[Low(Data)];
  785. For I := Succ(Low(Data)) To High(Data) Do
  786. If Data[I] > Result Then Result := Data[I];
  787. end;
  788. function maxvalue(const data : array of float) : float;
  789. begin
  790. Result:=maxvalue(PFloat(@data[0]),High(Data)+1);
  791. end;
  792. function maxvalue(const data : PFloat; Const N : Integer) : float;
  793. var
  794. i : longint;
  795. begin
  796. { get an initial value }
  797. maxvalue:=data[0];
  798. for i:=1 to N-1 do
  799. if data[i]>maxvalue then
  800. maxvalue:=data[i];
  801. end;
  802. function MaxValue(const Data: array of Integer): Integer;
  803. begin
  804. Result:=MaxValue(PInteger(@Data[0]),High(Data)+1)
  805. end;
  806. function maxvalue(const data : PInteger; Const N : Integer) : Integer;
  807. var
  808. i : longint;
  809. begin
  810. { get an initial value }
  811. maxvalue:=data[0];
  812. for i:=1 to N-1 do
  813. if data[i]>maxvalue then
  814. maxvalue:=data[i];
  815. end;
  816. function Min(a, b: Integer): Integer;
  817. begin
  818. if a < b then
  819. Result := a
  820. else
  821. Result := b;
  822. end;
  823. function Max(a, b: Integer): Integer;
  824. begin
  825. if a > b then
  826. Result := a
  827. else
  828. Result := b;
  829. end;
  830. function Min(a, b: Cardinal): Cardinal;
  831. begin
  832. if a < b then
  833. Result := a
  834. else
  835. Result := b;
  836. end;
  837. function Max(a, b: Cardinal): Cardinal;
  838. begin
  839. if a > b then
  840. Result := a
  841. else
  842. Result := b;
  843. end;
  844. function Min(a, b: Int64): Int64;
  845. begin
  846. if a < b then
  847. Result := a
  848. else
  849. Result := b;
  850. end;
  851. function Max(a, b: Int64): Int64;
  852. begin
  853. if a > b then
  854. Result := a
  855. else
  856. Result := b;
  857. end;
  858. {$ifdef FPC_HAS_TYPE_SINGLE}
  859. function Min(a, b: Single): Single;
  860. begin
  861. if a < b then
  862. Result := a
  863. else
  864. Result := b;
  865. end;
  866. function Max(a, b: Single): Single;
  867. begin
  868. if a > b then
  869. Result := a
  870. else
  871. Result := b;
  872. end;
  873. {$endif FPC_HAS_TYPE_SINGLE}
  874. {$ifdef FPC_HAS_TYPE_DOUBLE}
  875. function Min(a, b: Double): Double;
  876. begin
  877. if a < b then
  878. Result := a
  879. else
  880. Result := b;
  881. end;
  882. function Max(a, b: Double): Double;
  883. begin
  884. if a > b then
  885. Result := a
  886. else
  887. Result := b;
  888. end;
  889. {$endif FPC_HAS_TYPE_DOUBLE}
  890. {$ifdef FPC_HAS_TYPE_EXTENDED}
  891. function Min(a, b: Extended): Extended;
  892. begin
  893. if a < b then
  894. Result := a
  895. else
  896. Result := b;
  897. end;
  898. function Max(a, b: Extended): Extended;
  899. begin
  900. if a > b then
  901. Result := a
  902. else
  903. Result := b;
  904. end;
  905. {$endif FPC_HAS_TYPE_EXTENDED}
  906. function InRange(const AValue, AMin, AMax: Integer): Boolean;
  907. begin
  908. Result:=(AValue>=AMin) and (AValue<=AMax);
  909. end;
  910. function InRange(const AValue, AMin, AMax: Int64): Boolean;
  911. begin
  912. Result:=(AValue>=AMin) and (AValue<=AMax);
  913. end;
  914. {$ifdef FPC_HAS_TYPE_DOUBLE}
  915. function InRange(const AValue, AMin, AMax: Double): Boolean;
  916. begin
  917. Result:=(AValue>=AMin) and (AValue<=AMax);
  918. end;
  919. {$endif FPC_HAS_TYPE_DOUBLE}
  920. function EnsureRange(const AValue, AMin, AMax: Integer): Integer;
  921. begin
  922. Result:=AValue;
  923. If Result<AMin then
  924. Result:=AMin
  925. else if Result>AMax then
  926. Result:=AMax;
  927. end;
  928. function EnsureRange(const AValue, AMin, AMax: Int64): Int64;
  929. begin
  930. Result:=AValue;
  931. If Result<AMin then
  932. Result:=AMin
  933. else if Result>AMax then
  934. Result:=AMax;
  935. end;
  936. {$ifdef FPC_HAS_TYPE_DOUBLE}
  937. function EnsureRange(const AValue, AMin, AMax: Double): Double;
  938. begin
  939. Result:=AValue;
  940. If Result<AMin then
  941. Result:=AMin
  942. else if Result>AMax then
  943. Result:=AMax;
  944. end;
  945. {$endif FPC_HAS_TYPE_DOUBLE}
  946. Const
  947. EZeroResolution = 1E-16;
  948. DZeroResolution = 1E-12;
  949. SZeroResolution = 1E-4;
  950. function IsZero(const A: Single; Epsilon: Single): Boolean;
  951. begin
  952. if (Epsilon=0) then
  953. Epsilon:=SZeroResolution;
  954. Result:=Abs(A)<=Epsilon;
  955. end;
  956. function IsZero(const A: Single): Boolean;
  957. begin
  958. Result:=IsZero(A,single(SZeroResolution));
  959. end;
  960. {$ifdef FPC_HAS_TYPE_DOUBLE}
  961. function IsZero(const A: Double; Epsilon: Double): Boolean;
  962. begin
  963. if (Epsilon=0) then
  964. Epsilon:=DZeroResolution;
  965. Result:=Abs(A)<=Epsilon;
  966. end;
  967. function IsZero(const A: Double): Boolean;
  968. begin
  969. Result:=IsZero(A,DZeroResolution);
  970. end;
  971. {$endif FPC_HAS_TYPE_DOUBLE}
  972. {$ifdef FPC_HAS_TYPE_EXTENDED}
  973. function IsZero(const A: Extended; Epsilon: Extended): Boolean;
  974. begin
  975. if (Epsilon=0) then
  976. Epsilon:=EZeroResolution;
  977. Result:=Abs(A)<=Epsilon;
  978. end;
  979. function IsZero(const A: Extended): Boolean;
  980. begin
  981. Result:=IsZero(A,EZeroResolution);
  982. end;
  983. {$endif FPC_HAS_TYPE_EXTENDED}
  984. type
  985. TSplitDouble = packed record
  986. cards: Array[0..1] of cardinal;
  987. end;
  988. function IsNan(const d : Double): Boolean;
  989. var
  990. fraczero, expMaximal: boolean;
  991. begin
  992. {$if defined(FPC_BIG_ENDIAN) or (defined(CPUARM) and defined(FPUFPA))}
  993. expMaximal := ((TSplitDouble(d).cards[0] shr 20) and $7ff) = 2047;
  994. fraczero:= (TSplitDouble(d).cards[0] and $fffff = 0) and
  995. (TSplitDouble(d).cards[1] = 0);
  996. {$else FPC_BIG_ENDIAN}
  997. expMaximal := ((TSplitDouble(d).cards[1] shr 20) and $7ff) = 2047;
  998. fraczero := (TSplitDouble(d).cards[1] and $fffff = 0) and
  999. (TSplitDouble(d).cards[0] = 0);
  1000. {$endif FPC_BIG_ENDIAN}
  1001. Result:=expMaximal and not(fraczero);
  1002. end;
  1003. function IsInfinite(const d : Double): Boolean;
  1004. var
  1005. fraczero, expMaximal: boolean;
  1006. begin
  1007. {$if defined(FPC_BIG_ENDIAN) or (defined(CPUARM) and defined(FPUFPA))}
  1008. expMaximal := ((TSplitDouble(d).cards[0] shr 20) and $7ff) = 2047;
  1009. fraczero:= (TSplitDouble(d).cards[0] and $fffff = 0) and
  1010. (TSplitDouble(d).cards[1] = 0);
  1011. {$else FPC_BIG_ENDIAN}
  1012. expMaximal := ((TSplitDouble(d).cards[1] shr 20) and $7ff) = 2047;
  1013. fraczero := (TSplitDouble(d).cards[1] and $fffff = 0) and
  1014. (TSplitDouble(d).cards[0] = 0);
  1015. {$endif FPC_BIG_ENDIAN}
  1016. Result:=expMaximal and fraczero;
  1017. end;
  1018. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1019. function SameValue(const A, B: Extended; Epsilon: Extended): Boolean;
  1020. begin
  1021. if (Epsilon=0) then
  1022. Epsilon:=Max(Min(Abs(A),Abs(B))*EZeroResolution,EZeroResolution);
  1023. if (A>B) then
  1024. Result:=((A-B)<=Epsilon)
  1025. else
  1026. Result:=((B-A)<=Epsilon);
  1027. end;
  1028. function SameValue(const A, B: Extended): Boolean;
  1029. begin
  1030. Result:=SameValue(A,B,0);
  1031. end;
  1032. {$endif FPC_HAS_TYPE_EXTENDED}
  1033. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1034. function SameValue(const A, B: Double): Boolean;
  1035. begin
  1036. Result:=SameValue(A,B,0);
  1037. end;
  1038. function SameValue(const A, B: Double; Epsilon: Double): Boolean;
  1039. begin
  1040. if (Epsilon=0) then
  1041. Epsilon:=Max(Min(Abs(A),Abs(B))*DZeroResolution,DZeroResolution);
  1042. if (A>B) then
  1043. Result:=((A-B)<=Epsilon)
  1044. else
  1045. Result:=((B-A)<=Epsilon);
  1046. end;
  1047. {$endif FPC_HAS_TYPE_DOUBLE}
  1048. function SameValue(const A, B: Single): Boolean;
  1049. begin
  1050. Result:=SameValue(A,B,0);
  1051. end;
  1052. function SameValue(const A, B: Single; Epsilon: Single): Boolean;
  1053. begin
  1054. if (Epsilon=0) then
  1055. Epsilon:=Max(Min(Abs(A),Abs(B))*SZeroResolution,SZeroResolution);
  1056. if (A>B) then
  1057. Result:=((A-B)<=Epsilon)
  1058. else
  1059. Result:=((B-A)<=Epsilon);
  1060. end;
  1061. // Some CPUs probably allow a faster way of doing this in a single operation...
  1062. // There weshould define CPUDIVMOD in the header mathuh.inc and implement it using asm.
  1063. {$ifndef CPUDIVMOD}
  1064. procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);
  1065. begin
  1066. Result:=Dividend Div Divisor;
  1067. Remainder:=Dividend Mod Divisor;
  1068. end;
  1069. {$endif}
  1070. function ifthen(val:boolean;const iftrue:integer; const iffalse:integer= 0) :integer;
  1071. begin
  1072. if val then result:=iftrue else result:=iffalse;
  1073. end;
  1074. function ifthen(val:boolean;const iftrue:int64 ; const iffalse:int64 = 0) :int64;
  1075. begin
  1076. if val then result:=iftrue else result:=iffalse;
  1077. end;
  1078. function ifthen(val:boolean;const iftrue:double ; const iffalse:double =0.0):double;
  1079. begin
  1080. if val then result:=iftrue else result:=iffalse;
  1081. end;
  1082. end.