math.pp 86 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2005 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. Using functions from AMath/DAMath libraries, which are covered by the
  13. following license:
  14. (C) Copyright 2009-2013 Wolfgang Ehrhardt
  15. This software is provided 'as-is', without any express or implied warranty.
  16. In no event will the authors be held liable for any damages arising from
  17. the use of this software.
  18. Permission is granted to anyone to use this software for any purpose,
  19. including commercial applications, and to alter it and redistribute it
  20. freely, subject to the following restrictions:
  21. 1. The origin of this software must not be misrepresented; you must not
  22. claim that you wrote the original software. If you use this software in
  23. a product, an acknowledgment in the product documentation would be
  24. appreciated but is not required.
  25. 2. Altered source versions must be plainly marked as such, and must not be
  26. misrepresented as being the original software.
  27. 3. This notice may not be removed or altered from any source distribution.
  28. ----------------------------------------------------------------------------}
  29. {
  30. This unit is an equivalent to the Delphi Math unit
  31. (with some improvements)
  32. What's to do:
  33. o some statistical functions
  34. o optimizations
  35. }
  36. {$MODE objfpc}
  37. {$inline on }
  38. {$GOTO on}
  39. unit Math;
  40. interface
  41. {$ifndef FPUNONE}
  42. uses
  43. sysutils;
  44. {$IFDEF FPDOC_MATH}
  45. Type
  46. Float = MaxFloatType;
  47. Const
  48. MinFloat = 0;
  49. MaxFloat = 0;
  50. {$ENDIF}
  51. { Ranges of the IEEE floating point types, including denormals }
  52. {$ifdef FPC_HAS_TYPE_SINGLE}
  53. const
  54. { values according to
  55. https://en.wikipedia.org/wiki/Single-precision_floating-point_format#Single-precision_examples
  56. }
  57. MinSingle = 1.1754943508e-38;
  58. MaxSingle = 3.4028234664e+38;
  59. {$endif FPC_HAS_TYPE_SINGLE}
  60. {$ifdef FPC_HAS_TYPE_DOUBLE}
  61. const
  62. { values according to
  63. https://en.wikipedia.org/wiki/Double-precision_floating-point_format#Double-precision_examples
  64. }
  65. MinDouble = 2.2250738585072014e-308;
  66. MaxDouble = 1.7976931348623157e+308;
  67. {$endif FPC_HAS_TYPE_DOUBLE}
  68. {$ifdef FPC_HAS_TYPE_EXTENDED}
  69. const
  70. MinExtended = 3.4e-4932;
  71. MaxExtended = 1.1e+4932;
  72. {$endif FPC_HAS_TYPE_EXTENDED}
  73. {$ifdef FPC_HAS_TYPE_COMP}
  74. const
  75. MinComp = -9.223372036854775807e+18;
  76. MaxComp = 9.223372036854775807e+18;
  77. {$endif FPC_HAS_TYPE_COMP}
  78. { the original delphi functions use extended as argument, }
  79. { but I would prefer double, because 8 bytes is a very }
  80. { natural size for the processor }
  81. { WARNING : changing float type will }
  82. { break all assembler code PM }
  83. {$if defined(FPC_HAS_TYPE_FLOAT128)}
  84. type
  85. Float = Float128;
  86. const
  87. MinFloat = MinFloat128;
  88. MaxFloat = MaxFloat128;
  89. {$elseif defined(FPC_HAS_TYPE_EXTENDED)}
  90. type
  91. Float = extended;
  92. const
  93. MinFloat = MinExtended;
  94. MaxFloat = MaxExtended;
  95. {$elseif defined(FPC_HAS_TYPE_DOUBLE)}
  96. type
  97. Float = double;
  98. const
  99. MinFloat = MinDouble;
  100. MaxFloat = MaxDouble;
  101. {$elseif defined(FPC_HAS_TYPE_SINGLE)}
  102. type
  103. Float = single;
  104. const
  105. MinFloat = MinSingle;
  106. MaxFloat = MaxSingle;
  107. {$else}
  108. {$fatal At least one floating point type must be supported}
  109. {$endif}
  110. type
  111. PFloat = ^Float;
  112. PInteger = ObjPas.PInteger;
  113. TPaymentTime = (ptEndOfPeriod,ptStartOfPeriod);
  114. EInvalidArgument = class(ematherror);
  115. TValueRelationship = -1..1;
  116. const
  117. EqualsValue = 0;
  118. LessThanValue = Low(TValueRelationship);
  119. GreaterThanValue = High(TValueRelationship);
  120. {$push}
  121. {$R-}
  122. {$Q-}
  123. NaN = 0.0/0.0;
  124. Infinity = 1.0/0.0;
  125. NegInfinity = -1.0/0.0;
  126. {$pop}
  127. {$IFDEF FPDOC_MATH}
  128. // This must be after the above defines.
  129. {$DEFINE FPC_HAS_TYPE_SINGLE}
  130. {$DEFINE FPC_HAS_TYPE_DOUBLE}
  131. {$DEFINE FPC_HAS_TYPE_EXTENDED}
  132. {$DEFINE FPC_HAS_TYPE_COMP}
  133. {$ENDIF}
  134. { Min/max determination }
  135. function MinIntValue(const Data: array of Integer): Integer;
  136. function MaxIntValue(const Data: array of Integer): Integer;
  137. { Extra, not present in Delphi, but used frequently }
  138. function Min(a, b: Integer): Integer;inline; overload;
  139. function Max(a, b: Integer): Integer;inline; overload;
  140. { this causes more trouble than it solves
  141. function Min(a, b: Cardinal): Cardinal; overload;
  142. function Max(a, b: Cardinal): Cardinal; overload;
  143. }
  144. function Min(a, b: Int64): Int64;inline; overload;
  145. function Max(a, b: Int64): Int64;inline; overload;
  146. function Min(a, b: QWord): QWord;inline; overload;
  147. function Max(a, b: QWord): QWord;inline; overload;
  148. {$ifdef FPC_HAS_TYPE_SINGLE}
  149. function Min(a, b: Single): Single;inline; overload;
  150. function Max(a, b: Single): Single;inline; overload;
  151. {$endif FPC_HAS_TYPE_SINGLE}
  152. {$ifdef FPC_HAS_TYPE_DOUBLE}
  153. function Min(a, b: Double): Double;inline; overload;
  154. function Max(a, b: Double): Double;inline; overload;
  155. {$endif FPC_HAS_TYPE_DOUBLE}
  156. {$ifdef FPC_HAS_TYPE_EXTENDED}
  157. function Min(a, b: Extended): Extended;inline; overload;
  158. function Max(a, b: Extended): Extended;inline; overload;
  159. {$endif FPC_HAS_TYPE_EXTENDED}
  160. function InRange(const AValue, AMin, AMax: Integer): Boolean;inline; overload;
  161. function InRange(const AValue, AMin, AMax: Int64): Boolean;inline; overload;
  162. {$ifdef FPC_HAS_TYPE_DOUBLE}
  163. function InRange(const AValue, AMin, AMax: Double): Boolean;inline; overload;
  164. {$endif FPC_HAS_TYPE_DOUBLE}
  165. function EnsureRange(const AValue, AMin, AMax: Integer): Integer;inline; overload;
  166. function EnsureRange(const AValue, AMin, AMax: Int64): Int64;inline; overload;
  167. {$ifdef FPC_HAS_TYPE_DOUBLE}
  168. function EnsureRange(const AValue, AMin, AMax: Double): Double;inline; overload;
  169. {$endif FPC_HAS_TYPE_DOUBLE}
  170. procedure DivMod(Dividend: LongInt; Divisor: Word; var Result, Remainder: Word);
  171. procedure DivMod(Dividend: LongInt; Divisor: Word; var Result, Remainder: SmallInt);
  172. procedure DivMod(Dividend: DWord; Divisor: DWord; var Result, Remainder: DWord);
  173. procedure DivMod(Dividend: LongInt; Divisor: LongInt; var Result, Remainder: LongInt);
  174. { Floating point modulo}
  175. {$ifdef FPC_HAS_TYPE_SINGLE}
  176. function FMod(const a, b: Single): Single;inline;overload;
  177. {$endif FPC_HAS_TYPE_SINGLE}
  178. {$ifdef FPC_HAS_TYPE_DOUBLE}
  179. function FMod(const a, b: Double): Double;inline;overload;
  180. {$endif FPC_HAS_TYPE_DOUBLE}
  181. {$ifdef FPC_HAS_TYPE_EXTENDED}
  182. function FMod(const a, b: Extended): Extended;inline;overload;
  183. {$endif FPC_HAS_TYPE_EXTENDED}
  184. operator mod(const a,b:float) c:float;inline;
  185. // Sign functions
  186. Type
  187. TValueSign = -1..1;
  188. const
  189. NegativeValue = Low(TValueSign);
  190. ZeroValue = 0;
  191. PositiveValue = High(TValueSign);
  192. function Sign(const AValue: Integer): TValueSign;inline; overload;
  193. function Sign(const AValue: Int64): TValueSign;inline; overload;
  194. {$ifdef FPC_HAS_TYPE_SINGLE}
  195. function Sign(const AValue: Single): TValueSign;inline; overload;
  196. {$endif}
  197. function Sign(const AValue: Double): TValueSign;inline; overload;
  198. {$ifdef FPC_HAS_TYPE_EXTENDED}
  199. function Sign(const AValue: Extended): TValueSign;inline; overload;
  200. {$endif}
  201. function IsZero(const A: Single; Epsilon: Single): Boolean; overload;
  202. function IsZero(const A: Single): Boolean;inline; overload;
  203. {$ifdef FPC_HAS_TYPE_DOUBLE}
  204. function IsZero(const A: Double; Epsilon: Double): Boolean; overload;
  205. function IsZero(const A: Double): Boolean;inline; overload;
  206. {$endif FPC_HAS_TYPE_DOUBLE}
  207. {$ifdef FPC_HAS_TYPE_EXTENDED}
  208. function IsZero(const A: Extended; Epsilon: Extended): Boolean; overload;
  209. function IsZero(const A: Extended): Boolean;inline; overload;
  210. {$endif FPC_HAS_TYPE_EXTENDED}
  211. function IsNan(const d : Single): Boolean; overload;
  212. {$ifdef FPC_HAS_TYPE_DOUBLE}
  213. function IsNan(const d : Double): Boolean; overload;
  214. {$endif FPC_HAS_TYPE_DOUBLE}
  215. {$ifdef FPC_HAS_TYPE_EXTENDED}
  216. function IsNan(const d : Extended): Boolean; overload;
  217. {$endif FPC_HAS_TYPE_EXTENDED}
  218. function IsInfinite(const d : Single): Boolean; overload;
  219. {$ifdef FPC_HAS_TYPE_DOUBLE}
  220. function IsInfinite(const d : Double): Boolean; overload;
  221. {$endif FPC_HAS_TYPE_DOUBLE}
  222. {$ifdef FPC_HAS_TYPE_EXTENDED}
  223. function IsInfinite(const d : Extended): Boolean; overload;
  224. {$endif FPC_HAS_TYPE_EXTENDED}
  225. {$ifdef FPC_HAS_TYPE_EXTENDED}
  226. function SameValue(const A, B: Extended): Boolean;inline; overload;
  227. {$endif}
  228. {$ifdef FPC_HAS_TYPE_DOUBLE}
  229. function SameValue(const A, B: Double): Boolean;inline; overload;
  230. {$endif}
  231. function SameValue(const A, B: Single): Boolean;inline; overload;
  232. {$ifdef FPC_HAS_TYPE_EXTENDED}
  233. function SameValue(const A, B: Extended; Epsilon: Extended): Boolean; overload;
  234. {$endif}
  235. {$ifdef FPC_HAS_TYPE_DOUBLE}
  236. function SameValue(const A, B: Double; Epsilon: Double): Boolean; overload;
  237. {$endif}
  238. function SameValue(const A, B: Single; Epsilon: Single): Boolean; overload;
  239. type
  240. TRoundToRange = -37..37;
  241. {$ifdef FPC_HAS_TYPE_DOUBLE}
  242. function RoundTo(const AValue: Double; const Digits: TRoundToRange): Double;
  243. {$endif}
  244. {$ifdef FPC_HAS_TYPE_EXTENDED}
  245. function RoundTo(const AVAlue: Extended; const Digits: TRoundToRange): Extended;
  246. {$endif}
  247. {$ifdef FPC_HAS_TYPE_SINGLE}
  248. function RoundTo(const AValue: Single; const Digits: TRoundToRange): Single;
  249. {$endif}
  250. {$ifdef FPC_HAS_TYPE_SINGLE}
  251. function SimpleRoundTo(const AValue: Single; const Digits: TRoundToRange = -2): Single;
  252. {$endif}
  253. {$ifdef FPC_HAS_TYPE_DOUBLE}
  254. function SimpleRoundTo(const AValue: Double; const Digits: TRoundToRange = -2): Double;
  255. {$endif}
  256. {$ifdef FPC_HAS_TYPE_EXTENDED}
  257. function SimpleRoundTo(const AValue: Extended; const Digits: TRoundToRange = -2): Extended;
  258. {$endif}
  259. { angle conversion }
  260. function DegToRad(deg : float) : float;inline;
  261. function RadToDeg(rad : float) : float;inline;
  262. function GradToRad(grad : float) : float;inline;
  263. function RadToGrad(rad : float) : float;inline;
  264. function DegToGrad(deg : float) : float;inline;
  265. function GradToDeg(grad : float) : float;inline;
  266. {$ifdef FPC_HAS_TYPE_SINGLE}
  267. function CycleToDeg(const Cycles: Single): Single;
  268. {$ENDIF}
  269. {$ifdef FPC_HAS_TYPE_DOUBLE}
  270. function CycleToDeg(const Cycles: Double): Double;
  271. {$ENDIF}
  272. {$ifdef FPC_HAS_TYPE_EXTENDED}
  273. function CycleToDeg(const Cycles: Extended): Extended;
  274. {$ENDIF}
  275. {$ifdef FPC_HAS_TYPE_SINGLE}
  276. function DegToCycle(const Degrees: Single): Single;
  277. {$ENDIF}
  278. {$ifdef FPC_HAS_TYPE_DOUBLE}
  279. function DegToCycle(const Degrees: Double): Double;
  280. {$ENDIF}
  281. {$ifdef FPC_HAS_TYPE_EXTENDED}
  282. function DegToCycle(const Degrees: Extended): Extended;
  283. {$ENDIF}
  284. {$ifdef FPC_HAS_TYPE_SINGLE}
  285. function CycleToGrad(const Cycles: Single): Single;
  286. {$ENDIF}
  287. {$ifdef FPC_HAS_TYPE_DOUBLE}
  288. function CycleToGrad(const Cycles: Double): Double;
  289. {$ENDIF}
  290. {$ifdef FPC_HAS_TYPE_EXTENDED}
  291. function CycleToGrad(const Cycles: Extended): Extended;
  292. {$ENDIF}
  293. {$ifdef FPC_HAS_TYPE_SINGLE}
  294. function GradToCycle(const Grads: Single): Single;
  295. {$ENDIF}
  296. {$ifdef FPC_HAS_TYPE_DOUBLE}
  297. function GradToCycle(const Grads: Double): Double;
  298. {$ENDIF}
  299. {$ifdef FPC_HAS_TYPE_EXTENDED}
  300. function GradToCycle(const Grads: Extended): Extended;
  301. {$ENDIF}
  302. {$ifdef FPC_HAS_TYPE_SINGLE}
  303. function CycleToRad(const Cycles: Single): Single;
  304. {$ENDIF}
  305. {$ifdef FPC_HAS_TYPE_DOUBLE}
  306. function CycleToRad(const Cycles: Double): Double;
  307. {$ENDIF}
  308. {$ifdef FPC_HAS_TYPE_EXTENDED}
  309. function CycleToRad(const Cycles: Extended): Extended;
  310. {$ENDIF}
  311. {$ifdef FPC_HAS_TYPE_SINGLE}
  312. function RadToCycle(const Rads: Single): Single;
  313. {$ENDIF}
  314. {$ifdef FPC_HAS_TYPE_DOUBLE}
  315. function RadToCycle(const Rads: Double): Double;
  316. {$ENDIF}
  317. {$ifdef FPC_HAS_TYPE_EXTENDED}
  318. function RadToCycle(const Rads: Extended): Extended;
  319. {$ENDIF}
  320. {$ifdef FPC_HAS_TYPE_SINGLE}
  321. Function DegNormalize(deg : single) : single; inline;
  322. {$ENDIF}
  323. {$ifdef FPC_HAS_TYPE_DOUBLE}
  324. Function DegNormalize(deg : double) : double; inline;
  325. {$ENDIF}
  326. {$ifdef FPC_HAS_TYPE_EXTENDED}
  327. Function DegNormalize(deg : extended) : extended; inline;
  328. {$ENDIF}
  329. { trigoniometric functions }
  330. function Tan(x : float) : float;
  331. function Cotan(x : float) : float;
  332. function Cot(x : float) : float; inline;
  333. {$ifdef FPC_HAS_TYPE_SINGLE}
  334. procedure SinCos(theta : single;out sinus,cosinus : single);
  335. {$endif}
  336. {$ifdef FPC_HAS_TYPE_DOUBLE}
  337. procedure SinCos(theta : double;out sinus,cosinus : double);
  338. {$endif}
  339. {$ifdef FPC_HAS_TYPE_EXTENDED}
  340. procedure SinCos(theta : extended;out sinus,cosinus : extended);
  341. {$endif}
  342. function Secant(x : float) : float; inline;
  343. function Cosecant(x : float) : float; inline;
  344. function Sec(x : float) : float; inline;
  345. function Csc(x : float) : float; inline;
  346. { inverse functions }
  347. function ArcCos(x : float) : float;
  348. function ArcSin(x : float) : float;
  349. { calculates arctan(y/x) and returns an angle in the correct quadrant }
  350. function ArcTan2(y,x : float) : float;
  351. { hyperbolic functions }
  352. function CosH(x : float) : float;
  353. function SinH(x : float) : float;
  354. function TanH(x : float) : float;
  355. { area functions }
  356. { delphi names: }
  357. function ArcCosH(x : float) : float;inline;
  358. function ArcSinH(x : float) : float;inline;
  359. function ArcTanH(x : float) : float;inline;
  360. { IMHO the function should be called as follows (FK) }
  361. function ArCosH(x : float) : float;
  362. function ArSinH(x : float) : float;
  363. function ArTanH(x : float) : float;
  364. { triangle functions }
  365. { returns the length of the hypotenuse of a right triangle }
  366. { if x and y are the other sides }
  367. function Hypot(x,y : float) : float;
  368. { logarithm functions }
  369. function Log10(x : float) : float;
  370. function Log2(x : float) : float;
  371. function LogN(n,x : float) : float;
  372. { returns natural logarithm of x+1, accurate for x values near zero }
  373. function LnXP1(x : float) : float;
  374. { exponential functions }
  375. function Power(base,exponent : float) : float;
  376. { base^exponent }
  377. function IntPower(base : float;exponent : longint) : float;
  378. operator ** (base,exponent : float) e: float; inline;
  379. operator ** (base,exponent : int64) res: int64;
  380. { number converting }
  381. { rounds x towards positive infinity }
  382. function Ceil(x : float) : Integer;
  383. function Ceil64(x: float): Int64;
  384. { rounds x towards negative infinity }
  385. function Floor(x : float) : Integer;
  386. function Floor64(x: float): Int64;
  387. { misc. functions }
  388. {$ifdef FPC_HAS_TYPE_SINGLE}
  389. { splits x into mantissa and exponent (to base 2) }
  390. procedure Frexp(X: single; out Mantissa: single; out Exponent: integer);
  391. { returns x*(2^p) }
  392. function Ldexp(X: single; p: Integer) : single;
  393. {$endif}
  394. {$ifdef FPC_HAS_TYPE_DOUBLE}
  395. procedure Frexp(X: double; out Mantissa: double; out Exponent: integer);
  396. function Ldexp(X: double; p: Integer) : double;
  397. {$endif}
  398. {$ifdef FPC_HAS_TYPE_EXTENDED}
  399. procedure Frexp(X: extended; out Mantissa: extended; out Exponent: integer);
  400. function Ldexp(X: extended; p: Integer) : extended;
  401. {$endif}
  402. { statistical functions }
  403. {$ifdef FPC_HAS_TYPE_SINGLE}
  404. function Mean(const data : array of Single) : float;
  405. function Sum(const data : array of Single) : float;inline;
  406. function Mean(const data : PSingle; Const N : longint) : float;
  407. function Sum(const data : PSingle; Const N : Longint) : float;
  408. {$endif FPC_HAS_TYPE_SINGLE}
  409. {$ifdef FPC_HAS_TYPE_DOUBLE}
  410. function Mean(const data : array of double) : float;inline;
  411. function Sum(const data : array of double) : float;inline;
  412. function Mean(const data : PDouble; Const N : longint) : float;
  413. function Sum(const data : PDouble; Const N : Longint) : float;
  414. {$endif FPC_HAS_TYPE_DOUBLE}
  415. {$ifdef FPC_HAS_TYPE_EXTENDED}
  416. function Mean(const data : array of Extended) : float;
  417. function Sum(const data : array of Extended) : float;inline;
  418. function Mean(const data : PExtended; Const N : longint) : float;
  419. function Sum(const data : PExtended; Const N : Longint) : float;
  420. {$endif FPC_HAS_TYPE_EXTENDED}
  421. function SumInt(const data : PInt64;Const N : longint) : Int64;
  422. function SumInt(const data : array of Int64) : Int64;inline;
  423. function Mean(const data : PInt64; const N : Longint):Float;
  424. function Mean(const data: array of Int64):Float;
  425. function SumInt(const data : PInteger; Const N : longint) : Int64;
  426. function SumInt(const data : array of Integer) : Int64;inline;
  427. function Mean(const data : PInteger; const N : Longint):Float;
  428. function Mean(const data: array of Integer):Float;
  429. {$ifdef FPC_HAS_TYPE_SINGLE}
  430. function SumOfSquares(const data : array of Single) : float;inline;
  431. function SumOfSquares(const data : PSingle; Const N : Integer) : float;
  432. { calculates the sum and the sum of squares of data }
  433. procedure SumsAndSquares(const data : array of Single;
  434. var sum,sumofsquares : float);inline;
  435. procedure SumsAndSquares(const data : PSingle; Const N : Integer;
  436. var sum,sumofsquares : float);
  437. {$endif FPC_HAS_TYPE_SINGLE}
  438. {$ifdef FPC_HAS_TYPE_DOUBLE}
  439. function SumOfSquares(const data : array of double) : float;
  440. function SumOfSquares(const data : PDouble; Const N : Integer) : float;
  441. { calculates the sum and the sum of squares of data }
  442. procedure SumsAndSquares(const data : array of Double;
  443. var sum,sumofsquares : float);inline;
  444. procedure SumsAndSquares(const data : PDouble; Const N : Integer;
  445. var sum,sumofsquares : float);
  446. {$endif FPC_HAS_TYPE_DOUBLE}
  447. {$ifdef FPC_HAS_TYPE_EXTENDED}
  448. function SumOfSquares(const data : array of Extended) : float;inline;
  449. function SumOfSquares(const data : PExtended; Const N : Integer) : float;
  450. { calculates the sum and the sum of squares of data }
  451. procedure SumsAndSquares(const data : array of Extended;
  452. var sum,sumofsquares : float);inline;
  453. procedure SumsAndSquares(const data : PExtended; Const N : Integer;
  454. var sum,sumofsquares : float);
  455. {$endif FPC_HAS_TYPE_EXTENDED}
  456. {$ifdef FPC_HAS_TYPE_SINGLE}
  457. function MinValue(const data : array of Single) : Single;inline;
  458. function MinValue(const data : PSingle; Const N : Integer) : Single;
  459. function MaxValue(const data : array of Single) : Single;inline;
  460. function MaxValue(const data : PSingle; Const N : Integer) : Single;
  461. {$endif FPC_HAS_TYPE_SINGLE}
  462. {$ifdef FPC_HAS_TYPE_DOUBLE}
  463. function MinValue(const data : array of Double) : Double;inline;
  464. function MinValue(const data : PDouble; Const N : Integer) : Double;
  465. function MaxValue(const data : array of Double) : Double;inline;
  466. function MaxValue(const data : PDouble; Const N : Integer) : Double;
  467. {$endif FPC_HAS_TYPE_DOUBLE}
  468. {$ifdef FPC_HAS_TYPE_EXTENDED}
  469. function MinValue(const data : array of Extended) : Extended;inline;
  470. function MinValue(const data : PExtended; Const N : Integer) : Extended;
  471. function MaxValue(const data : array of Extended) : Extended;inline;
  472. function MaxValue(const data : PExtended; Const N : Integer) : Extended;
  473. {$endif FPC_HAS_TYPE_EXTENDED}
  474. function MinValue(const data : array of integer) : Integer;inline;
  475. function MinValue(const Data : PInteger; Const N : Integer): Integer;
  476. function MaxValue(const data : array of integer) : Integer;inline;
  477. function MaxValue(const data : PInteger; Const N : Integer) : Integer;
  478. { returns random values with gaussian distribution }
  479. function RandG(mean,stddev : float) : float;
  480. function RandomRange(const aFrom, aTo: Integer): Integer;
  481. function RandomRange(const aFrom, aTo: Int64): Int64;
  482. {$ifdef FPC_HAS_TYPE_SINGLE}
  483. { calculates the standard deviation }
  484. function StdDev(const data : array of Single) : float;inline;
  485. function StdDev(const data : PSingle; Const N : Integer) : float;
  486. { calculates the mean and stddev }
  487. procedure MeanAndStdDev(const data : array of Single;
  488. var mean,stddev : float);inline;
  489. procedure MeanAndStdDev(const data : PSingle;
  490. Const N : Longint;var mean,stddev : float);
  491. function Variance(const data : array of Single) : float;inline;
  492. function TotalVariance(const data : array of Single) : float;inline;
  493. function Variance(const data : PSingle; Const N : Integer) : float;
  494. function TotalVariance(const data : PSingle; Const N : Integer) : float;
  495. { Population (aka uncorrected) variance and standard deviation }
  496. function PopnStdDev(const data : array of Single) : float;inline;
  497. function PopnStdDev(const data : PSingle; Const N : Integer) : float;
  498. function PopnVariance(const data : PSingle; Const N : Integer) : float;
  499. function PopnVariance(const data : array of Single) : float;inline;
  500. procedure MomentSkewKurtosis(const data : array of Single;
  501. out m1,m2,m3,m4,skew,kurtosis : float);inline;
  502. procedure MomentSkewKurtosis(const data : PSingle; Const N : Integer;
  503. out m1,m2,m3,m4,skew,kurtosis : float);
  504. { geometrical function }
  505. { returns the euclidean L2 norm }
  506. function Norm(const data : array of Single) : float;inline;
  507. function Norm(const data : PSingle; Const N : Integer) : float;
  508. {$endif FPC_HAS_TYPE_SINGLE}
  509. {$ifdef FPC_HAS_TYPE_DOUBLE}
  510. { calculates the standard deviation }
  511. function StdDev(const data : array of Double) : float;inline;
  512. function StdDev(const data : PDouble; Const N : Integer) : float;
  513. { calculates the mean and stddev }
  514. procedure MeanAndStdDev(const data : array of Double;
  515. var mean,stddev : float);inline;
  516. procedure MeanAndStdDev(const data : PDouble;
  517. Const N : Longint;var mean,stddev : float);
  518. function Variance(const data : array of Double) : float;inline;
  519. function TotalVariance(const data : array of Double) : float;inline;
  520. function Variance(const data : PDouble; Const N : Integer) : float;
  521. function TotalVariance(const data : PDouble; Const N : Integer) : float;
  522. { Population (aka uncorrected) variance and standard deviation }
  523. function PopnStdDev(const data : array of Double) : float;inline;
  524. function PopnStdDev(const data : PDouble; Const N : Integer) : float;
  525. function PopnVariance(const data : PDouble; Const N : Integer) : float;
  526. function PopnVariance(const data : array of Double) : float;inline;
  527. procedure MomentSkewKurtosis(const data : array of Double;
  528. out m1,m2,m3,m4,skew,kurtosis : float);inline;
  529. procedure MomentSkewKurtosis(const data : PDouble; Const N : Integer;
  530. out m1,m2,m3,m4,skew,kurtosis : float);
  531. { geometrical function }
  532. { returns the euclidean L2 norm }
  533. function Norm(const data : array of double) : float;inline;
  534. function Norm(const data : PDouble; Const N : Integer) : float;
  535. {$endif FPC_HAS_TYPE_DOUBLE}
  536. {$ifdef FPC_HAS_TYPE_EXTENDED}
  537. { calculates the standard deviation }
  538. function StdDev(const data : array of Extended) : float;inline;
  539. function StdDev(const data : PExtended; Const N : Integer) : float;
  540. { calculates the mean and stddev }
  541. procedure MeanAndStdDev(const data : array of Extended;
  542. var mean,stddev : float);inline;
  543. procedure MeanAndStdDev(const data : PExtended;
  544. Const N : Longint;var mean,stddev : float);
  545. function Variance(const data : array of Extended) : float;inline;
  546. function TotalVariance(const data : array of Extended) : float;inline;
  547. function Variance(const data : PExtended; Const N : Integer) : float;
  548. function TotalVariance(const data : PExtended; Const N : Integer) : float;
  549. { Population (aka uncorrected) variance and standard deviation }
  550. function PopnStdDev(const data : array of Extended) : float;inline;
  551. function PopnStdDev(const data : PExtended; Const N : Integer) : float;
  552. function PopnVariance(const data : PExtended; Const N : Integer) : float;
  553. function PopnVariance(const data : array of Extended) : float;inline;
  554. procedure MomentSkewKurtosis(const data : array of Extended;
  555. out m1,m2,m3,m4,skew,kurtosis : float);inline;
  556. procedure MomentSkewKurtosis(const data : PExtended; Const N : Integer;
  557. out m1,m2,m3,m4,skew,kurtosis : float);
  558. { geometrical function }
  559. { returns the euclidean L2 norm }
  560. function Norm(const data : array of Extended) : float;inline;
  561. function Norm(const data : PExtended; Const N : Integer) : float;
  562. {$endif FPC_HAS_TYPE_EXTENDED}
  563. { Financial functions }
  564. function FutureValue(ARate: Float; NPeriods: Integer;
  565. APayment, APresentValue: Float; APaymentTime: TPaymentTime): Float;
  566. function InterestRate(NPeriods: Integer; APayment, APresentValue, AFutureValue: Float;
  567. APaymentTime: TPaymentTime): Float;
  568. function NumberOfPeriods(ARate, APayment, APresentValue, AFutureValue: Float;
  569. APaymentTime: TPaymentTime): Float;
  570. function Payment(ARate: Float; NPeriods: Integer;
  571. APresentValue, AFutureValue: Float; APaymentTime: TPaymentTime): Float;
  572. function PresentValue(ARate: Float; NPeriods: Integer;
  573. APayment, AFutureValue: Float; APaymentTime: TPaymentTime): Float;
  574. { Misc functions }
  575. function IfThen(val:boolean;const iftrue:integer; const iffalse:integer= 0) :integer; inline; overload;
  576. function IfThen(val:boolean;const iftrue:int64 ; const iffalse:int64 = 0) :int64; inline; overload;
  577. function IfThen(val:boolean;const iftrue:double ; const iffalse:double =0.0):double; inline; overload;
  578. function CompareValue ( const A, B : Integer) : TValueRelationship; inline;
  579. function CompareValue ( const A, B : Int64) : TValueRelationship; inline;
  580. function CompareValue ( const A, B : QWord) : TValueRelationship; inline;
  581. {$ifdef FPC_HAS_TYPE_SINGLE}
  582. function CompareValue ( const A, B : Single; delta : Single = 0.0 ) : TValueRelationship; inline;
  583. {$endif}
  584. {$ifdef FPC_HAS_TYPE_DOUBLE}
  585. function CompareValue ( const A, B : Double; delta : Double = 0.0) : TValueRelationship; inline;
  586. {$endif}
  587. {$ifdef FPC_HAS_TYPE_EXTENDED}
  588. function CompareValue ( const A, B : Extended; delta : Extended = 0.0 ) : TValueRelationship; inline;
  589. {$endif}
  590. function RandomFrom(const AValues: array of Double): Double; overload;
  591. function RandomFrom(const AValues: array of Integer): Integer; overload;
  592. function RandomFrom(const AValues: array of Int64): Int64; overload;
  593. {$if FPC_FULLVERSION >=30101}
  594. generic function RandomFrom<T>(const AValues:array of T):T;
  595. {$endif}
  596. { cpu specific stuff }
  597. type
  598. TFPURoundingMode = system.TFPURoundingMode;
  599. TFPUPrecisionMode = system.TFPUPrecisionMode;
  600. TFPUException = system.TFPUException;
  601. TFPUExceptionMask = system.TFPUExceptionMask;
  602. function GetRoundMode: TFPURoundingMode;
  603. function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
  604. function GetPrecisionMode: TFPUPrecisionMode;
  605. function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;
  606. function GetExceptionMask: TFPUExceptionMask;
  607. function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
  608. procedure ClearExceptions(RaisePending: Boolean =true);
  609. implementation
  610. function copysign(x,y: float): float; forward; { returns abs(x)*sign(y) }
  611. { include cpu specific stuff }
  612. {$i mathu.inc}
  613. ResourceString
  614. SMathError = 'Math Error : %s';
  615. SInvalidArgument = 'Invalid argument';
  616. Procedure DoMathError(Const S : String);
  617. begin
  618. Raise EMathError.CreateFmt(SMathError,[S]);
  619. end;
  620. Procedure InvalidArgument;
  621. begin
  622. Raise EInvalidArgument.Create(SInvalidArgument);
  623. end;
  624. function Sign(const AValue: Integer): TValueSign;inline;
  625. begin
  626. result:=TValueSign(
  627. SarLongint(AValue,sizeof(AValue)*8-1) or { gives -1 for negative values, 0 otherwise }
  628. (longint(-AValue) shr (sizeof(AValue)*8-1)) { gives 1 for positive values, 0 otherwise }
  629. );
  630. end;
  631. function Sign(const AValue: Int64): TValueSign;inline;
  632. begin
  633. {$ifdef cpu64}
  634. result:=TValueSign(
  635. SarInt64(AValue,sizeof(AValue)*8-1) or
  636. (-AValue shr (sizeof(AValue)*8-1))
  637. );
  638. {$else cpu64}
  639. If Avalue<0 then
  640. Result:=NegativeValue
  641. else If Avalue>0 then
  642. Result:=PositiveValue
  643. else
  644. Result:=ZeroValue;
  645. {$endif}
  646. end;
  647. {$ifdef FPC_HAS_TYPE_SINGLE}
  648. function Sign(const AValue: Single): TValueSign;inline;
  649. begin
  650. Result:=ord(AValue>0.0)-ord(AValue<0.0);
  651. end;
  652. {$endif}
  653. function Sign(const AValue: Double): TValueSign;inline;
  654. begin
  655. Result:=ord(AValue>0.0)-ord(AValue<0.0);
  656. end;
  657. {$ifdef FPC_HAS_TYPE_EXTENDED}
  658. function Sign(const AValue: Extended): TValueSign;inline;
  659. begin
  660. Result:=ord(AValue>0.0)-ord(AValue<0.0);
  661. end;
  662. {$endif}
  663. function degtorad(deg : float) : float;inline;
  664. begin
  665. degtorad:=deg*(pi/180.0);
  666. end;
  667. function radtodeg(rad : float) : float;inline;
  668. begin
  669. radtodeg:=rad*(180.0/pi);
  670. end;
  671. function gradtorad(grad : float) : float;inline;
  672. begin
  673. gradtorad:=grad*(pi/200.0);
  674. end;
  675. function radtograd(rad : float) : float;inline;
  676. begin
  677. radtograd:=rad*(200.0/pi);
  678. end;
  679. function degtograd(deg : float) : float;inline;
  680. begin
  681. degtograd:=deg*(200.0/180.0);
  682. end;
  683. function gradtodeg(grad : float) : float;inline;
  684. begin
  685. gradtodeg:=grad*(180.0/200.0);
  686. end;
  687. {$ifdef FPC_HAS_TYPE_SINGLE}
  688. function CycleToDeg(const Cycles: Single): Single;
  689. begin
  690. CycleToDeg:=Cycles*360.0;
  691. end;
  692. {$ENDIF}
  693. {$ifdef FPC_HAS_TYPE_DOUBLE}
  694. function CycleToDeg(const Cycles: Double): Double;
  695. begin
  696. CycleToDeg:=Cycles*360.0;
  697. end;
  698. {$ENDIF}
  699. {$ifdef FPC_HAS_TYPE_EXTENDED}
  700. function CycleToDeg(const Cycles: Extended): Extended;
  701. begin
  702. CycleToDeg:=Cycles*360.0;
  703. end;
  704. {$ENDIF}
  705. {$ifdef FPC_HAS_TYPE_SINGLE}
  706. function DegToCycle(const Degrees: Single): Single;
  707. begin
  708. DegToCycle:=Degrees*(1/360.0);
  709. end;
  710. {$ENDIF}
  711. {$ifdef FPC_HAS_TYPE_DOUBLE}
  712. function DegToCycle(const Degrees: Double): Double;
  713. begin
  714. DegToCycle:=Degrees*(1/360.0);
  715. end;
  716. {$ENDIF}
  717. {$ifdef FPC_HAS_TYPE_EXTENDED}
  718. function DegToCycle(const Degrees: Extended): Extended;
  719. begin
  720. DegToCycle:=Degrees*(1/360.0);
  721. end;
  722. {$ENDIF}
  723. {$ifdef FPC_HAS_TYPE_SINGLE}
  724. function CycleToGrad(const Cycles: Single): Single;
  725. begin
  726. CycleToGrad:=Cycles*400.0;
  727. end;
  728. {$ENDIF}
  729. {$ifdef FPC_HAS_TYPE_DOUBLE}
  730. function CycleToGrad(const Cycles: Double): Double;
  731. begin
  732. CycleToGrad:=Cycles*400.0;
  733. end;
  734. {$ENDIF}
  735. {$ifdef FPC_HAS_TYPE_EXTENDED}
  736. function CycleToGrad(const Cycles: Extended): Extended;
  737. begin
  738. CycleToGrad:=Cycles*400.0;
  739. end;
  740. {$ENDIF}
  741. {$ifdef FPC_HAS_TYPE_SINGLE}
  742. function GradToCycle(const Grads: Single): Single;
  743. begin
  744. GradToCycle:=Grads*(1/400.0);
  745. end;
  746. {$ENDIF}
  747. {$ifdef FPC_HAS_TYPE_DOUBLE}
  748. function GradToCycle(const Grads: Double): Double;
  749. begin
  750. GradToCycle:=Grads*(1/400.0);
  751. end;
  752. {$ENDIF}
  753. {$ifdef FPC_HAS_TYPE_EXTENDED}
  754. function GradToCycle(const Grads: Extended): Extended;
  755. begin
  756. GradToCycle:=Grads*(1/400.0);
  757. end;
  758. {$ENDIF}
  759. {$ifdef FPC_HAS_TYPE_SINGLE}
  760. function CycleToRad(const Cycles: Single): Single;
  761. begin
  762. CycleToRad:=Cycles*2*pi;
  763. end;
  764. {$ENDIF}
  765. {$ifdef FPC_HAS_TYPE_DOUBLE}
  766. function CycleToRad(const Cycles: Double): Double;
  767. begin
  768. CycleToRad:=Cycles*2*pi;
  769. end;
  770. {$ENDIF}
  771. {$ifdef FPC_HAS_TYPE_EXTENDED}
  772. function CycleToRad(const Cycles: Extended): Extended;
  773. begin
  774. CycleToRad:=Cycles*2*pi;
  775. end;
  776. {$ENDIF}
  777. {$ifdef FPC_HAS_TYPE_SINGLE}
  778. function RadToCycle(const Rads: Single): Single;
  779. begin
  780. RadToCycle:=Rads*(1/(2*pi));
  781. end;
  782. {$ENDIF}
  783. {$ifdef FPC_HAS_TYPE_DOUBLE}
  784. function RadToCycle(const Rads: Double): Double;
  785. begin
  786. RadToCycle:=Rads*(1/(2*pi));
  787. end;
  788. {$ENDIF}
  789. {$ifdef FPC_HAS_TYPE_EXTENDED}
  790. function RadToCycle(const Rads: Extended): Extended;
  791. begin
  792. RadToCycle:=Rads*(1/(2*pi));
  793. end;
  794. {$ENDIF}
  795. {$ifdef FPC_HAS_TYPE_SINGLE}
  796. Function DegNormalize(deg : single) : single;
  797. begin
  798. Result:=Deg-Int(Deg/360)*360;
  799. If Result<0 then Result:=Result+360;
  800. end;
  801. {$ENDIF}
  802. {$ifdef FPC_HAS_TYPE_DOUBLE}
  803. Function DegNormalize(deg : double) : double; inline;
  804. begin
  805. Result:=Deg-Int(Deg/360)*360;
  806. If (Result<0) then Result:=Result+360;
  807. end;
  808. {$ENDIF}
  809. {$ifdef FPC_HAS_TYPE_EXTENDED}
  810. Function DegNormalize(deg : extended) : extended; inline;
  811. begin
  812. Result:=Deg-Int(Deg/360)*360;
  813. If Result<0 then Result:=Result+360;
  814. end;
  815. {$ENDIF}
  816. {$ifndef FPC_MATH_HAS_TAN}
  817. function tan(x : float) : float;
  818. var
  819. _sin,_cos : float;
  820. begin
  821. sincos(x,_sin,_cos);
  822. tan:=_sin/_cos;
  823. end;
  824. {$endif FPC_MATH_HAS_TAN}
  825. {$ifndef FPC_MATH_HAS_COTAN}
  826. function cotan(x : float) : float;
  827. var
  828. _sin,_cos : float;
  829. begin
  830. sincos(x,_sin,_cos);
  831. cotan:=_cos/_sin;
  832. end;
  833. {$endif FPC_MATH_HAS_COTAN}
  834. function cot(x : float) : float; inline;
  835. begin
  836. cot := cotan(x);
  837. end;
  838. {$ifndef FPC_MATH_HAS_SINCOS}
  839. {$ifdef FPC_HAS_TYPE_SINGLE}
  840. procedure sincos(theta : single;out sinus,cosinus : single);
  841. begin
  842. sinus:=sin(theta);
  843. cosinus:=cos(theta);
  844. end;
  845. {$endif}
  846. {$ifdef FPC_HAS_TYPE_DOUBLE}
  847. procedure sincos(theta : double;out sinus,cosinus : double);
  848. begin
  849. sinus:=sin(theta);
  850. cosinus:=cos(theta);
  851. end;
  852. {$endif}
  853. {$ifdef FPC_HAS_TYPE_EXTENDED}
  854. procedure sincos(theta : extended;out sinus,cosinus : extended);
  855. begin
  856. sinus:=sin(theta);
  857. cosinus:=cos(theta);
  858. end;
  859. {$endif}
  860. {$endif FPC_MATH_HAS_SINCOS}
  861. function secant(x : float) : float; inline;
  862. begin
  863. secant := 1 / cos(x);
  864. end;
  865. function cosecant(x : float) : float; inline;
  866. begin
  867. cosecant := 1 / sin(x);
  868. end;
  869. function sec(x : float) : float; inline;
  870. begin
  871. sec := secant(x);
  872. end;
  873. function csc(x : float) : float; inline;
  874. begin
  875. csc := cosecant(x);
  876. end;
  877. { arcsin and arccos functions from AMath library (C) Copyright 2009-2013 Wolfgang Ehrhardt }
  878. function arcsin(x : float) : float;
  879. begin
  880. arcsin:=arctan2(x,sqrt((1.0-x)*(1.0+x)));
  881. end;
  882. function Arccos(x : Float) : Float;
  883. begin
  884. if abs(x)=1.0 then
  885. if x<0.0 then
  886. arccos:=Pi
  887. else
  888. arccos:=0
  889. else
  890. arccos:=arctan2(sqrt((1.0-x)*(1.0+x)),x);
  891. end;
  892. {$ifndef FPC_MATH_HAS_ARCTAN2}
  893. function arctan2(y,x : float) : float;
  894. begin
  895. if x=0 then
  896. begin
  897. if y=0 then
  898. result:=0.0
  899. else if y>0 then
  900. result:=pi/2
  901. else
  902. result:=-pi/2;
  903. end
  904. else
  905. begin
  906. result:=ArcTan(y/x);
  907. if x<0 then
  908. if y<0 then
  909. result:=result-pi
  910. else
  911. result:=result+pi;
  912. end;
  913. end;
  914. {$endif FPC_MATH_HAS_ARCTAN2}
  915. function cosh(x : float) : float;
  916. var
  917. temp : float;
  918. begin
  919. temp:=exp(x);
  920. cosh:=0.5*(temp+1.0/temp);
  921. end;
  922. function sinh(x : float) : float;
  923. var
  924. temp : float;
  925. begin
  926. temp:=exp(x);
  927. { copysign ensures that sinh(-0.0)=-0.0 }
  928. sinh:=copysign(0.5*(temp-1.0/temp),x);
  929. end;
  930. function tanh(x : float) : float;
  931. var
  932. tmp:float;
  933. begin
  934. if x < 0 then begin
  935. tmp:=exp(2*x);
  936. result:=(tmp-1)/(1+tmp)
  937. end
  938. else begin
  939. tmp:=exp(-2*x);
  940. result:=(1-tmp)/(1+tmp)
  941. end;
  942. end;
  943. function arccosh(x : float) : float; inline;
  944. begin
  945. arccosh:=arcosh(x);
  946. end;
  947. function arcsinh(x : float) : float;inline;
  948. begin
  949. arcsinh:=arsinh(x);
  950. end;
  951. function arctanh(x : float) : float;inline;
  952. begin
  953. arctanh:=artanh(x);
  954. end;
  955. function arcosh(x : float) : float;
  956. begin
  957. { Provides accuracy about 4*eps near 1.0 }
  958. arcosh:=Ln(x+Sqrt((x-1.0)*(x+1.0)));
  959. end;
  960. function arsinh(x : float) : float;
  961. var
  962. z: float;
  963. begin
  964. z:=abs(x);
  965. z:=Ln(z+Sqrt(1+z*z));
  966. { copysign ensures that arsinh(-Inf)=-Inf and arsinh(-0.0)=-0.0 }
  967. arsinh:=copysign(z,x);
  968. end;
  969. function artanh(x : float) : float;
  970. begin
  971. artanh:=(lnxp1(x)-lnxp1(-x))*0.5;
  972. end;
  973. { hypot function from AMath library (C) Copyright 2009-2013 Wolfgang Ehrhardt }
  974. function hypot(x,y : float) : float;
  975. begin
  976. x:=abs(x);
  977. y:=abs(y);
  978. if (x>y) then
  979. hypot:=x*sqrt(1.0+sqr(y/x))
  980. else if (x>0.0) then
  981. hypot:=y*sqrt(1.0+sqr(x/y))
  982. else
  983. hypot:=y;
  984. end;
  985. function log10(x : float) : float;
  986. begin
  987. log10:=ln(x)*0.43429448190325182765; { 1/ln(10) }
  988. end;
  989. {$ifndef FPC_MATH_HAS_LOG2}
  990. function log2(x : float) : float;
  991. begin
  992. log2:=ln(x)*1.4426950408889634079; { 1/ln(2) }
  993. end;
  994. {$endif FPC_MATH_HAS_LOG2}
  995. function logn(n,x : float) : float;
  996. begin
  997. logn:=ln(x)/ln(n);
  998. end;
  999. { lnxp1 function from AMath library (C) Copyright 2009-2013 Wolfgang Ehrhardt }
  1000. function lnxp1(x : float) : float;
  1001. var
  1002. y: float;
  1003. begin
  1004. if (x>=4.0) then
  1005. lnxp1:=ln(1.0+x)
  1006. else
  1007. begin
  1008. y:=1.0+x;
  1009. if (y=1.0) then
  1010. lnxp1:=x
  1011. else
  1012. begin
  1013. lnxp1:=ln(y); { lnxp1(-1) = ln(0) = -Inf }
  1014. if y>0.0 then
  1015. lnxp1:=lnxp1+(x-(y-1.0))/y;
  1016. end;
  1017. end;
  1018. end;
  1019. function power(base,exponent : float) : float;
  1020. begin
  1021. if Exponent=0.0 then
  1022. result:=1.0
  1023. else if (base=0.0) and (exponent>0.0) then
  1024. result:=0.0
  1025. else if (abs(exponent)<=maxint) and (frac(exponent)=0.0) then
  1026. result:=intpower(base,trunc(exponent))
  1027. else
  1028. result:=exp(exponent * ln (base));
  1029. end;
  1030. function intpower(base : float;exponent : longint) : float;
  1031. begin
  1032. if exponent<0 then
  1033. begin
  1034. base:=1.0/base;
  1035. exponent:=-exponent;
  1036. end;
  1037. intpower:=1.0;
  1038. while exponent<>0 do
  1039. begin
  1040. if exponent and 1<>0 then
  1041. intpower:=intpower*base;
  1042. exponent:=exponent shr 1;
  1043. base:=sqr(base);
  1044. end;
  1045. end;
  1046. operator ** (base,exponent : float) e: float; inline;
  1047. begin
  1048. e:=power(base,exponent);
  1049. end;
  1050. operator ** (base,exponent : int64) res: int64;
  1051. begin
  1052. if exponent<0 then
  1053. begin
  1054. if base<=0 then
  1055. raise EInvalidArgument.Create('Non-positive base with negative exponent in **');
  1056. if base=1 then
  1057. res:=1
  1058. else
  1059. res:=0;
  1060. exit;
  1061. end;
  1062. res:=1;
  1063. while exponent<>0 do
  1064. begin
  1065. if exponent and 1<>0 then
  1066. res:=res*base;
  1067. exponent:=exponent shr 1;
  1068. base:=base*base;
  1069. end;
  1070. end;
  1071. function ceil(x : float) : integer;
  1072. begin
  1073. Result:=Trunc(x)+ord(Frac(x)>0);
  1074. end;
  1075. function ceil64(x: float): Int64;
  1076. begin
  1077. Result:=Trunc(x)+ord(Frac(x)>0);
  1078. end;
  1079. function floor(x : float) : integer;
  1080. begin
  1081. Result:=Trunc(x)-ord(Frac(x)<0);
  1082. end;
  1083. function floor64(x: float): Int64;
  1084. begin
  1085. Result:=Trunc(x)-ord(Frac(x)<0);
  1086. end;
  1087. // Correction for "rounding to nearest, ties to even".
  1088. // RoundToNearestTieToEven(QWE.RTYUIOP) = QWE + TieToEven(ER, TYUIOP <> 0).
  1089. function TieToEven(AB: cardinal; somethingAfter: boolean): cardinal;
  1090. begin
  1091. result := AB and 1;
  1092. if (result <> 0) and not somethingAfter then
  1093. result := AB shr 1;
  1094. end;
  1095. {$ifdef FPC_HAS_TYPE_SINGLE}
  1096. procedure Frexp(X: single; out Mantissa: single; out Exponent: integer);
  1097. var
  1098. M: uint32;
  1099. E, ExtraE: int32;
  1100. begin
  1101. Mantissa := X;
  1102. E := TSingleRec(X).Exp;
  1103. if (E > 0) and (E < 2 * TSingleRec.Bias + 1) then
  1104. begin
  1105. // Normal.
  1106. TSingleRec(Mantissa).Exp := TSingleRec.Bias - 1;
  1107. Exponent := E - (TSingleRec.Bias - 1);
  1108. exit;
  1109. end;
  1110. if E = 0 then
  1111. begin
  1112. M := TSingleRec(X).Frac;
  1113. if M <> 0 then
  1114. begin
  1115. // Subnormal.
  1116. ExtraE := 23 - BsrDWord(M);
  1117. TSingleRec(Mantissa).Frac := M shl ExtraE; // "and (1 shl 23 - 1)" required to remove starting 1, but .SetFrac already does it.
  1118. TSingleRec(Mantissa).Exp := TSingleRec.Bias - 1;
  1119. Exponent := -TSingleRec.Bias + 2 - ExtraE;
  1120. exit;
  1121. end;
  1122. end;
  1123. // ±0, ±Inf, NaN.
  1124. Exponent := 0;
  1125. end;
  1126. function Ldexp(X: single; p: integer): single;
  1127. var
  1128. M, E: uint32;
  1129. xp, sh: integer;
  1130. begin
  1131. E := TSingleRec(X).Exp;
  1132. if (E = 0) and (TSingleRec(X).Frac = 0) or (E = 2 * TSingleRec.Bias + 1) then
  1133. // ±0, ±Inf, NaN.
  1134. exit(X);
  1135. Frexp(X, result, xp);
  1136. inc(xp, p);
  1137. if (xp >= -TSingleRec.Bias + 2) and (xp <= TSingleRec.Bias + 1) then
  1138. // Normalized.
  1139. TSingleRec(result).Exp := xp + (TSingleRec.Bias - 1)
  1140. else if xp > TSingleRec.Bias + 1 then
  1141. begin
  1142. // Overflow.
  1143. TSingleRec(result).Exp := 2 * TSingleRec.Bias + 1;
  1144. TSingleRec(result).Frac := 0;
  1145. end else
  1146. begin
  1147. TSingleRec(result).Exp := 0;
  1148. if xp >= -TSingleRec.Bias + 2 - 23 then
  1149. begin
  1150. // Denormalized.
  1151. M := TSingleRec(result).Frac or uint32(1) shl 23;
  1152. sh := -TSingleRec.Bias + 1 - xp;
  1153. TSingleRec(result).Frac := M shr (sh + 1) + TieToEven(M shr sh and 3, M and (uint32(1) shl sh - 1) <> 0);
  1154. end else
  1155. // Underflow.
  1156. TSingleRec(result).Frac := 0;
  1157. end;
  1158. end;
  1159. {$endif}
  1160. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1161. procedure Frexp(X: double; out Mantissa: double; out Exponent: integer);
  1162. var
  1163. M: uint64;
  1164. E, ExtraE: int32;
  1165. begin
  1166. Mantissa := X;
  1167. E := TDoubleRec(X).Exp;
  1168. if (E > 0) and (E < 2 * TDoubleRec.Bias + 1) then
  1169. begin
  1170. // Normal.
  1171. TDoubleRec(Mantissa).Exp := TDoubleRec.Bias - 1;
  1172. Exponent := E - (TDoubleRec.Bias - 1);
  1173. exit;
  1174. end;
  1175. if E = 0 then
  1176. begin
  1177. M := TDoubleRec(X).Frac;
  1178. if M <> 0 then
  1179. begin
  1180. // Subnormal.
  1181. ExtraE := 52 - BsrQWord(M);
  1182. TDoubleRec(Mantissa).Frac := M shl ExtraE; // "and (1 shl 52 - 1)" required to remove starting 1, but .SetFrac already does it.
  1183. TDoubleRec(Mantissa).Exp := TDoubleRec.Bias - 1;
  1184. Exponent := -TDoubleRec.Bias + 2 - ExtraE;
  1185. exit;
  1186. end;
  1187. end;
  1188. // ±0, ±Inf, NaN.
  1189. Exponent := 0;
  1190. end;
  1191. function Ldexp(X: double; p: integer): double;
  1192. var
  1193. M: uint64;
  1194. E: uint32;
  1195. xp, sh: integer;
  1196. begin
  1197. E := TDoubleRec(X).Exp;
  1198. if (E = 0) and (TDoubleRec(X).Frac = 0) or (E = 2 * TDoubleRec.Bias + 1) then
  1199. // ±0, ±Inf, NaN.
  1200. exit(X);
  1201. Frexp(X, result, xp);
  1202. inc(xp, p);
  1203. if (xp >= -TDoubleRec.Bias + 2) and (xp <= TDoubleRec.Bias + 1) then
  1204. // Normalized.
  1205. TDoubleRec(result).Exp := xp + (TDoubleRec.Bias - 1)
  1206. else if xp > TDoubleRec.Bias + 1 then
  1207. begin
  1208. // Overflow.
  1209. TDoubleRec(result).Exp := 2 * TDoubleRec.Bias + 1;
  1210. TDoubleRec(result).Frac := 0;
  1211. end else
  1212. begin
  1213. TDoubleRec(result).Exp := 0;
  1214. if xp >= -TDoubleRec.Bias + 2 - 52 then
  1215. begin
  1216. // Denormalized.
  1217. M := TDoubleRec(result).Frac or uint64(1) shl 52;
  1218. sh := -TSingleRec.Bias + 1 - xp;
  1219. TDoubleRec(result).Frac := M shr (sh + 1) + TieToEven(M shr sh and 3, M and (uint64(1) shl sh - 1) <> 0);
  1220. end else
  1221. // Underflow.
  1222. TDoubleRec(result).Frac := 0;
  1223. end;
  1224. end;
  1225. {$endif}
  1226. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1227. procedure Frexp(X: extended; out Mantissa: extended; out Exponent: integer);
  1228. var
  1229. M: uint64;
  1230. E, ExtraE: int32;
  1231. begin
  1232. Mantissa := X;
  1233. E := TExtended80Rec(X).Exp;
  1234. if (E > 0) and (E < 2 * TExtended80Rec.Bias + 1) then
  1235. begin
  1236. // Normal.
  1237. TExtended80Rec(Mantissa).Exp := TExtended80Rec.Bias - 1;
  1238. Exponent := E - (TExtended80Rec.Bias - 1);
  1239. exit;
  1240. end;
  1241. if E = 0 then
  1242. begin
  1243. M := TExtended80Rec(X).Frac;
  1244. if M <> 0 then
  1245. begin
  1246. // Subnormal. Extended has explicit starting 1.
  1247. ExtraE := 63 - BsrQWord(M);
  1248. TExtended80Rec(Mantissa).Frac := M shl ExtraE;
  1249. TExtended80Rec(Mantissa).Exp := TExtended80Rec.Bias - 1;
  1250. Exponent := -TExtended80Rec.Bias + 2 - ExtraE;
  1251. exit;
  1252. end;
  1253. end;
  1254. // ±0, ±Inf, NaN.
  1255. Exponent := 0;
  1256. end;
  1257. function Ldexp(X: extended; p: integer): extended;
  1258. var
  1259. M: uint64;
  1260. E: uint32;
  1261. xp, sh: integer;
  1262. begin
  1263. E := TExtended80Rec(X).Exp;
  1264. if (E = 0) and (TExtended80Rec(X).Frac = 0) or (E = 2 * TExtended80Rec.Bias + 1) then
  1265. // ±0, ±Inf, NaN.
  1266. exit(X);
  1267. Frexp(X, result, xp);
  1268. inc(xp, p);
  1269. if (xp >= -TExtended80Rec.Bias + 2) and (xp <= TExtended80Rec.Bias + 1) then
  1270. // Normalized.
  1271. TExtended80Rec(result).Exp := xp + (TExtended80Rec.Bias - 1)
  1272. else if xp > TExtended80Rec.Bias + 1 then
  1273. begin
  1274. // Overflow.
  1275. TExtended80Rec(result).Exp := 2 * TExtended80Rec.Bias + 1;
  1276. TExtended80Rec(result).Frac := uint64(1) shl 63;
  1277. end
  1278. else if xp >= -TExtended80Rec.Bias + 2 - 63 then
  1279. begin
  1280. // Denormalized... usually.
  1281. // Mantissa of subnormal 'extended' (Exp = 0) must always start with 0.
  1282. // If the calculated mantissa starts with 1, extended instead becomes normalized with Exp = 1.
  1283. M := TExtended80Rec(result).Frac;
  1284. sh := -TExtended80Rec.Bias + 1 - xp;
  1285. M := M shr (sh + 1) + TieToEven(M shr sh and 3, M and (uint64(1) shl sh - 1) <> 0);
  1286. TExtended80Rec(result).Exp := M shr 63;
  1287. TExtended80Rec(result).Frac := M;
  1288. end else
  1289. begin
  1290. // Underflow.
  1291. TExtended80Rec(result).Exp := 0;
  1292. TExtended80Rec(result).Frac := 0;
  1293. end;
  1294. end;
  1295. {$endif}
  1296. const
  1297. { Cutoff for https://en.wikipedia.org/wiki/Pairwise_summation; sums of at least this many elements are split in two halves. }
  1298. RecursiveSumThreshold=12;
  1299. {$ifdef FPC_HAS_TYPE_SINGLE}
  1300. function mean(const data : array of Single) : float;
  1301. begin
  1302. Result:=Mean(PSingle(@data[0]),High(Data)+1);
  1303. end;
  1304. function mean(const data : PSingle; Const N : longint) : float;
  1305. begin
  1306. mean:=sum(Data,N);
  1307. mean:=mean/N;
  1308. end;
  1309. function sum(const data : array of Single) : float;inline;
  1310. begin
  1311. Result:=Sum(PSingle(@Data[0]),High(Data)+1);
  1312. end;
  1313. function sum(const data : PSingle;Const N : longint) : float;
  1314. var
  1315. i : SizeInt;
  1316. begin
  1317. if N>=RecursiveSumThreshold then
  1318. result:=sum(data,longword(N) div 2)+sum(data+longword(N) div 2,N-longword(N) div 2)
  1319. else
  1320. begin
  1321. result:=0;
  1322. for i:=0 to N-1 do
  1323. result:=result+data[i];
  1324. end;
  1325. end;
  1326. {$endif FPC_HAS_TYPE_SINGLE}
  1327. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1328. function mean(const data : array of Double) : float; inline;
  1329. begin
  1330. Result:=Mean(PDouble(@data[0]),High(Data)+1);
  1331. end;
  1332. function mean(const data : PDouble; Const N : longint) : float;
  1333. begin
  1334. mean:=sum(Data,N);
  1335. mean:=mean/N;
  1336. end;
  1337. function sum(const data : array of Double) : float; inline;
  1338. begin
  1339. Result:=Sum(PDouble(@Data[0]),High(Data)+1);
  1340. end;
  1341. function sum(const data : PDouble;Const N : longint) : float;
  1342. var
  1343. i : SizeInt;
  1344. begin
  1345. if N>=RecursiveSumThreshold then
  1346. result:=sum(data,longword(N) div 2)+sum(data+longword(N) div 2,N-longword(N) div 2)
  1347. else
  1348. begin
  1349. result:=0;
  1350. for i:=0 to N-1 do
  1351. result:=result+data[i];
  1352. end;
  1353. end;
  1354. {$endif FPC_HAS_TYPE_DOUBLE}
  1355. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1356. function mean(const data : array of Extended) : float;
  1357. begin
  1358. Result:=Mean(PExtended(@data[0]),High(Data)+1);
  1359. end;
  1360. function mean(const data : PExtended; Const N : longint) : float;
  1361. begin
  1362. mean:=sum(Data,N);
  1363. mean:=mean/N;
  1364. end;
  1365. function sum(const data : array of Extended) : float; inline;
  1366. begin
  1367. Result:=Sum(PExtended(@Data[0]),High(Data)+1);
  1368. end;
  1369. function sum(const data : PExtended;Const N : longint) : float;
  1370. var
  1371. i : SizeInt;
  1372. begin
  1373. if N>=RecursiveSumThreshold then
  1374. result:=sum(data,longword(N) div 2)+sum(data+longword(N) div 2,N-longword(N) div 2)
  1375. else
  1376. begin
  1377. result:=0;
  1378. for i:=0 to N-1 do
  1379. result:=result+data[i];
  1380. end;
  1381. end;
  1382. {$endif FPC_HAS_TYPE_EXTENDED}
  1383. function sumInt(const data : PInt64;Const N : longint) : Int64;
  1384. var
  1385. i : SizeInt;
  1386. begin
  1387. sumInt:=0;
  1388. for i:=0 to N-1 do
  1389. sumInt:=sumInt+data[i];
  1390. end;
  1391. function sumInt(const data : array of Int64) : Int64; inline;
  1392. begin
  1393. Result:=SumInt(PInt64(@Data[0]),High(Data)+1);
  1394. end;
  1395. function mean(const data : PInt64; const N : Longint):Float;
  1396. begin
  1397. mean:=sumInt(Data,N);
  1398. mean:=mean/N;
  1399. end;
  1400. function mean(const data: array of Int64):Float;
  1401. begin
  1402. mean:=mean(PInt64(@data[0]),High(Data)+1);
  1403. end;
  1404. function sumInt(const data : PInteger; Const N : longint) : Int64;
  1405. var
  1406. i : SizeInt;
  1407. begin
  1408. sumInt:=0;
  1409. for i:=0 to N-1 do
  1410. sumInt:=sumInt+data[i];
  1411. end;
  1412. function sumInt(const data : array of Integer) : Int64;inline;
  1413. begin
  1414. Result:=sumInt(PInteger(@Data[0]),High(Data)+1);
  1415. end;
  1416. function mean(const data : PInteger; const N : Longint):Float;
  1417. begin
  1418. mean:=sumInt(Data,N);
  1419. mean:=mean/N;
  1420. end;
  1421. function mean(const data: array of Integer):Float;
  1422. begin
  1423. mean:=mean(PInteger(@data[0]),High(Data)+1);
  1424. end;
  1425. {$ifdef FPC_HAS_TYPE_SINGLE}
  1426. function sumofsquares(const data : array of Single) : float; inline;
  1427. begin
  1428. Result:=sumofsquares(PSingle(@data[0]),High(Data)+1);
  1429. end;
  1430. function sumofsquares(const data : PSingle; Const N : Integer) : float;
  1431. var
  1432. i : SizeInt;
  1433. begin
  1434. if N>=RecursiveSumThreshold then
  1435. result:=sumofsquares(data,cardinal(N) div 2)+sumofsquares(data+cardinal(N) div 2,N-cardinal(N) div 2)
  1436. else
  1437. begin
  1438. result:=0;
  1439. for i:=0 to N-1 do
  1440. result:=result+sqr(data[i]);
  1441. end;
  1442. end;
  1443. procedure sumsandsquares(const data : array of Single;
  1444. var sum,sumofsquares : float); inline;
  1445. begin
  1446. sumsandsquares (PSingle(@Data[0]),High(Data)+1,Sum,sumofsquares);
  1447. end;
  1448. procedure sumsandsquares(const data : PSingle; Const N : Integer;
  1449. var sum,sumofsquares : float);
  1450. var
  1451. i : SizeInt;
  1452. temp,tsum,tsumofsquares,sum0,sumofsquares0,sum1,sumofsquares1 : float;
  1453. begin
  1454. if N>=RecursiveSumThreshold then
  1455. begin
  1456. sumsandsquares(data,cardinal(N) div 2,sum0,sumofsquares0);
  1457. sumsandsquares(data+cardinal(N) div 2,N-cardinal(N) div 2,sum1,sumofsquares1);
  1458. sum:=sum0+sum1;
  1459. sumofsquares:=sumofsquares0+sumofsquares1;
  1460. end
  1461. else
  1462. begin
  1463. tsum:=0;
  1464. tsumofsquares:=0;
  1465. for i:=0 to N-1 do
  1466. begin
  1467. temp:=data[i];
  1468. tsum:=tsum+temp;
  1469. tsumofsquares:=tsumofsquares+sqr(temp);
  1470. end;
  1471. sum:=tsum;
  1472. sumofsquares:=tsumofsquares;
  1473. end;
  1474. end;
  1475. {$endif FPC_HAS_TYPE_SINGLE}
  1476. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1477. function sumofsquares(const data : array of Double) : float; inline;
  1478. begin
  1479. Result:=sumofsquares(PDouble(@data[0]),High(Data)+1);
  1480. end;
  1481. function sumofsquares(const data : PDouble; Const N : Integer) : float;
  1482. var
  1483. i : SizeInt;
  1484. begin
  1485. if N>=RecursiveSumThreshold then
  1486. result:=sumofsquares(data,cardinal(N) div 2)+sumofsquares(data+cardinal(N) div 2,N-cardinal(N) div 2)
  1487. else
  1488. begin
  1489. result:=0;
  1490. for i:=0 to N-1 do
  1491. result:=result+sqr(data[i]);
  1492. end;
  1493. end;
  1494. procedure sumsandsquares(const data : array of Double;
  1495. var sum,sumofsquares : float);
  1496. begin
  1497. sumsandsquares (PDouble(@Data[0]),High(Data)+1,Sum,sumofsquares);
  1498. end;
  1499. procedure sumsandsquares(const data : PDouble; Const N : Integer;
  1500. var sum,sumofsquares : float);
  1501. var
  1502. i : SizeInt;
  1503. temp,tsum,tsumofsquares,sum0,sumofsquares0,sum1,sumofsquares1 : float;
  1504. begin
  1505. if N>=RecursiveSumThreshold then
  1506. begin
  1507. sumsandsquares(data,cardinal(N) div 2,sum0,sumofsquares0);
  1508. sumsandsquares(data+cardinal(N) div 2,N-cardinal(N) div 2,sum1,sumofsquares1);
  1509. sum:=sum0+sum1;
  1510. sumofsquares:=sumofsquares0+sumofsquares1;
  1511. end
  1512. else
  1513. begin
  1514. tsum:=0;
  1515. tsumofsquares:=0;
  1516. for i:=0 to N-1 do
  1517. begin
  1518. temp:=data[i];
  1519. tsum:=tsum+temp;
  1520. tsumofsquares:=tsumofsquares+sqr(temp);
  1521. end;
  1522. sum:=tsum;
  1523. sumofsquares:=tsumofsquares;
  1524. end;
  1525. end;
  1526. {$endif FPC_HAS_TYPE_DOUBLE}
  1527. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1528. function sumofsquares(const data : array of Extended) : float; inline;
  1529. begin
  1530. Result:=sumofsquares(PExtended(@data[0]),High(Data)+1);
  1531. end;
  1532. function sumofsquares(const data : PExtended; Const N : Integer) : float;
  1533. var
  1534. i : SizeInt;
  1535. begin
  1536. if N>=RecursiveSumThreshold then
  1537. result:=sumofsquares(data,cardinal(N) div 2)+sumofsquares(data+cardinal(N) div 2,N-cardinal(N) div 2)
  1538. else
  1539. begin
  1540. result:=0;
  1541. for i:=0 to N-1 do
  1542. result:=result+sqr(data[i]);
  1543. end;
  1544. end;
  1545. procedure sumsandsquares(const data : array of Extended;
  1546. var sum,sumofsquares : float); inline;
  1547. begin
  1548. sumsandsquares (PExtended(@Data[0]),High(Data)+1,Sum,sumofsquares);
  1549. end;
  1550. procedure sumsandsquares(const data : PExtended; Const N : Integer;
  1551. var sum,sumofsquares : float);
  1552. var
  1553. i : SizeInt;
  1554. temp,tsum,tsumofsquares,sum0,sumofsquares0,sum1,sumofsquares1 : float;
  1555. begin
  1556. if N>=RecursiveSumThreshold then
  1557. begin
  1558. sumsandsquares(data,cardinal(N) div 2,sum0,sumofsquares0);
  1559. sumsandsquares(data+cardinal(N) div 2,N-cardinal(N) div 2,sum1,sumofsquares1);
  1560. sum:=sum0+sum1;
  1561. sumofsquares:=sumofsquares0+sumofsquares1;
  1562. end
  1563. else
  1564. begin
  1565. tsum:=0;
  1566. tsumofsquares:=0;
  1567. for i:=0 to N-1 do
  1568. begin
  1569. temp:=data[i];
  1570. tsum:=tsum+temp;
  1571. tsumofsquares:=tsumofsquares+sqr(temp);
  1572. end;
  1573. sum:=tsum;
  1574. sumofsquares:=tsumofsquares;
  1575. end;
  1576. end;
  1577. {$endif FPC_HAS_TYPE_EXTENDED}
  1578. function randg(mean,stddev : float) : float;
  1579. Var U1,S2 : Float;
  1580. begin
  1581. repeat
  1582. u1:= 2*random-1;
  1583. S2:=Sqr(U1)+sqr(2*random-1);
  1584. until s2<1;
  1585. randg:=Sqrt(-2*ln(S2)/S2)*u1*stddev+Mean;
  1586. end;
  1587. function RandomRange(const aFrom, aTo: Integer): Integer;
  1588. begin
  1589. Result:=Random(Abs(aFrom-aTo))+Min(aTo,AFrom);
  1590. end;
  1591. function RandomRange(const aFrom, aTo: Int64): Int64;
  1592. begin
  1593. Result:=Random(Abs(aFrom-aTo))+Min(aTo,AFrom);
  1594. end;
  1595. {$ifdef FPC_HAS_TYPE_SINGLE}
  1596. procedure MeanAndTotalVariance
  1597. (const data: PSingle; N: LongInt; var mu, variance: float);
  1598. function CalcVariance(data: PSingle; N: SizeInt; mu: float): float;
  1599. var
  1600. i: SizeInt;
  1601. begin
  1602. if N>=RecursiveSumThreshold then
  1603. result:=CalcVariance(data,SizeUint(N) div 2,mu)+CalcVariance(data+SizeUint(N) div 2,N-SizeUint(N) div 2,mu)
  1604. else
  1605. begin
  1606. result:=0;
  1607. for i:=0 to N-1 do
  1608. result:=result+Sqr(data[i]-mu);
  1609. end;
  1610. end;
  1611. begin
  1612. mu := Mean( data, N );
  1613. variance := CalcVariance( data, N, mu );
  1614. end;
  1615. function stddev(const data : array of Single) : float; inline;
  1616. begin
  1617. Result:=Stddev(PSingle(@Data[0]),High(Data)+1);
  1618. end;
  1619. function stddev(const data : PSingle; Const N : Integer) : float;
  1620. begin
  1621. StdDev:=Sqrt(Variance(Data,N));
  1622. end;
  1623. procedure meanandstddev(const data : array of Single;
  1624. var mean,stddev : float); inline;
  1625. begin
  1626. Meanandstddev(PSingle(@Data[0]),High(Data)+1,Mean,stddev);
  1627. end;
  1628. procedure meanandstddev
  1629. ( const data: PSingle;
  1630. const N: Longint;
  1631. var mean,
  1632. stdDev: Float
  1633. );
  1634. var totalVariance: float;
  1635. begin
  1636. MeanAndTotalVariance( data, N, mean, totalVariance );
  1637. if N < 2 then stdDev := 0
  1638. else stdDev := Sqrt( totalVariance / ( N - 1 ) );
  1639. end;
  1640. function variance(const data : array of Single) : float; inline;
  1641. begin
  1642. Variance:=Variance(PSingle(@Data[0]),High(Data)+1);
  1643. end;
  1644. function variance(const data : PSingle; Const N : Integer) : float;
  1645. begin
  1646. If N=1 then
  1647. Result:=0
  1648. else
  1649. Result:=TotalVariance(Data,N)/(N-1);
  1650. end;
  1651. function totalvariance(const data : array of Single) : float; inline;
  1652. begin
  1653. Result:=TotalVariance(PSingle(@Data[0]),High(Data)+1);
  1654. end;
  1655. function totalvariance(const data : PSingle; const N : Integer) : float;
  1656. var mu: float;
  1657. begin
  1658. MeanAndTotalVariance( data, N, mu, result );
  1659. end;
  1660. function popnstddev(const data : array of Single) : float;
  1661. begin
  1662. PopnStdDev:=Sqrt(PopnVariance(PSingle(@Data[0]),High(Data)+1));
  1663. end;
  1664. function popnstddev(const data : PSingle; Const N : Integer) : float;
  1665. begin
  1666. PopnStdDev:=Sqrt(PopnVariance(Data,N));
  1667. end;
  1668. function popnvariance(const data : array of Single) : float; inline;
  1669. begin
  1670. popnvariance:=popnvariance(PSingle(@data[0]),high(Data)+1);
  1671. end;
  1672. function popnvariance(const data : PSingle; Const N : Integer) : float;
  1673. begin
  1674. PopnVariance:=TotalVariance(Data,N)/N;
  1675. end;
  1676. procedure momentskewkurtosis(const data : array of single;
  1677. out m1,m2,m3,m4,skew,kurtosis : float); inline;
  1678. begin
  1679. momentskewkurtosis(PSingle(@Data[0]),High(Data)+1,m1,m2,m3,m4,skew,kurtosis);
  1680. end;
  1681. type
  1682. TMoments2to4 = array[2 .. 4] of float;
  1683. procedure momentskewkurtosis(
  1684. const data: pSingle;
  1685. Const N: integer;
  1686. out m1: float;
  1687. out m2: float;
  1688. out m3: float;
  1689. out m4: float;
  1690. out skew: float;
  1691. out kurtosis: float
  1692. );
  1693. procedure CalcDevSums2to4(data: PSingle; N: SizeInt; m1: float; out m2to4: TMoments2to4);
  1694. var
  1695. tm2, tm3, tm4, dev, dev2: float;
  1696. i: SizeInt;
  1697. m2to4Part0, m2to4Part1: TMoments2to4;
  1698. begin
  1699. if N >= RecursiveSumThreshold then
  1700. begin
  1701. CalcDevSums2to4(data, SizeUint(N) div 2, m1, m2to4Part0);
  1702. CalcDevSums2to4(data + SizeUint(N) div 2, N - SizeUint(N) div 2, m1, m2to4Part1);
  1703. for i := Low(TMoments2to4) to High(TMoments2to4) do
  1704. m2to4[i] := m2to4Part0[i] + m2to4Part1[i];
  1705. end
  1706. else
  1707. begin
  1708. tm2 := 0;
  1709. tm3 := 0;
  1710. tm4 := 0;
  1711. for i := 0 to N - 1 do
  1712. begin
  1713. dev := data[i] - m1;
  1714. dev2 := sqr(dev);
  1715. tm2 := tm2 + dev2;
  1716. tm3 := tm3 + dev2 * dev;
  1717. tm4 := tm4 + sqr(dev2);
  1718. end;
  1719. m2to4[2] := tm2;
  1720. m2to4[3] := tm3;
  1721. m2to4[4] := tm4;
  1722. end;
  1723. end;
  1724. var
  1725. reciprocalN: float;
  1726. m2to4: TMoments2to4;
  1727. begin
  1728. m1 := 0;
  1729. reciprocalN := 1/N;
  1730. m1 := reciprocalN * sum(data, N);
  1731. CalcDevSums2to4(data, N, m1, m2to4);
  1732. m2 := reciprocalN * m2to4[2];
  1733. m3 := reciprocalN * m2to4[3];
  1734. m4 := reciprocalN * m2to4[4];
  1735. skew := m3 / (sqrt(m2)*m2);
  1736. kurtosis := m4 / (m2 * m2);
  1737. end;
  1738. function norm(const data : array of Single) : float; inline;
  1739. begin
  1740. norm:=Norm(PSingle(@data[0]),High(Data)+1);
  1741. end;
  1742. function norm(const data : PSingle; Const N : Integer) : float;
  1743. begin
  1744. norm:=sqrt(sumofsquares(data,N));
  1745. end;
  1746. {$endif FPC_HAS_TYPE_SINGLE}
  1747. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1748. procedure MeanAndTotalVariance
  1749. (const data: PDouble; N: LongInt; var mu, variance: float);
  1750. function CalcVariance(data: PDouble; N: SizeInt; mu: float): float;
  1751. var
  1752. i: SizeInt;
  1753. begin
  1754. if N>=RecursiveSumThreshold then
  1755. result:=CalcVariance(data,SizeUint(N) div 2,mu)+CalcVariance(data+SizeUint(N) div 2,N-SizeUint(N) div 2,mu)
  1756. else
  1757. begin
  1758. result:=0;
  1759. for i:=0 to N-1 do
  1760. result:=result+Sqr(data[i]-mu);
  1761. end;
  1762. end;
  1763. begin
  1764. mu := Mean( data, N );
  1765. variance := CalcVariance( data, N, mu );
  1766. end;
  1767. function stddev(const data : array of Double) : float; inline;
  1768. begin
  1769. Result:=Stddev(PDouble(@Data[0]),High(Data)+1)
  1770. end;
  1771. function stddev(const data : PDouble; Const N : Integer) : float;
  1772. begin
  1773. StdDev:=Sqrt(Variance(Data,N));
  1774. end;
  1775. procedure meanandstddev(const data : array of Double;
  1776. var mean,stddev : float);
  1777. begin
  1778. Meanandstddev(PDouble(@Data[0]),High(Data)+1,Mean,stddev);
  1779. end;
  1780. procedure meanandstddev
  1781. ( const data: PDouble;
  1782. const N: Longint;
  1783. var mean,
  1784. stdDev: Float
  1785. );
  1786. var totalVariance: float;
  1787. begin
  1788. MeanAndTotalVariance( data, N, mean, totalVariance );
  1789. if N < 2 then stdDev := 0
  1790. else stdDev := Sqrt( totalVariance / ( N - 1 ) );
  1791. end;
  1792. function variance(const data : array of Double) : float; inline;
  1793. begin
  1794. Variance:=Variance(PDouble(@Data[0]),High(Data)+1);
  1795. end;
  1796. function variance(const data : PDouble; Const N : Integer) : float;
  1797. begin
  1798. If N=1 then
  1799. Result:=0
  1800. else
  1801. Result:=TotalVariance(Data,N)/(N-1);
  1802. end;
  1803. function totalvariance(const data : array of Double) : float; inline;
  1804. begin
  1805. Result:=TotalVariance(PDouble(@Data[0]),High(Data)+1);
  1806. end;
  1807. function totalvariance(const data : PDouble; const N : Integer) : float;
  1808. var mu: float;
  1809. begin
  1810. MeanAndTotalVariance( data, N, mu, result );
  1811. end;
  1812. function popnstddev(const data : array of Double) : float;
  1813. begin
  1814. PopnStdDev:=Sqrt(PopnVariance(PDouble(@Data[0]),High(Data)+1));
  1815. end;
  1816. function popnstddev(const data : PDouble; Const N : Integer) : float;
  1817. begin
  1818. PopnStdDev:=Sqrt(PopnVariance(Data,N));
  1819. end;
  1820. function popnvariance(const data : array of Double) : float; inline;
  1821. begin
  1822. popnvariance:=popnvariance(PDouble(@data[0]),high(Data)+1);
  1823. end;
  1824. function popnvariance(const data : PDouble; Const N : Integer) : float;
  1825. begin
  1826. PopnVariance:=TotalVariance(Data,N)/N;
  1827. end;
  1828. procedure momentskewkurtosis(const data : array of Double;
  1829. out m1,m2,m3,m4,skew,kurtosis : float);
  1830. begin
  1831. momentskewkurtosis(PDouble(@Data[0]),High(Data)+1,m1,m2,m3,m4,skew,kurtosis);
  1832. end;
  1833. procedure momentskewkurtosis(
  1834. const data: pdouble;
  1835. Const N: integer;
  1836. out m1: float;
  1837. out m2: float;
  1838. out m3: float;
  1839. out m4: float;
  1840. out skew: float;
  1841. out kurtosis: float
  1842. );
  1843. procedure CalcDevSums2to4(data: PDouble; N: SizeInt; m1: float; out m2to4: TMoments2to4);
  1844. var
  1845. tm2, tm3, tm4, dev, dev2: float;
  1846. i: SizeInt;
  1847. m2to4Part0, m2to4Part1: TMoments2to4;
  1848. begin
  1849. if N >= RecursiveSumThreshold then
  1850. begin
  1851. CalcDevSums2to4(data, SizeUint(N) div 2, m1, m2to4Part0);
  1852. CalcDevSums2to4(data + SizeUint(N) div 2, N - SizeUint(N) div 2, m1, m2to4Part1);
  1853. for i := Low(TMoments2to4) to High(TMoments2to4) do
  1854. m2to4[i] := m2to4Part0[i] + m2to4Part1[i];
  1855. end
  1856. else
  1857. begin
  1858. tm2 := 0;
  1859. tm3 := 0;
  1860. tm4 := 0;
  1861. for i := 0 to N - 1 do
  1862. begin
  1863. dev := data[i] - m1;
  1864. dev2 := sqr(dev);
  1865. tm2 := tm2 + dev2;
  1866. tm3 := tm3 + dev2 * dev;
  1867. tm4 := tm4 + sqr(dev2);
  1868. end;
  1869. m2to4[2] := tm2;
  1870. m2to4[3] := tm3;
  1871. m2to4[4] := tm4;
  1872. end;
  1873. end;
  1874. var
  1875. reciprocalN: float;
  1876. m2to4: TMoments2to4;
  1877. begin
  1878. m1 := 0;
  1879. reciprocalN := 1/N;
  1880. m1 := reciprocalN * sum(data, N);
  1881. CalcDevSums2to4(data, N, m1, m2to4);
  1882. m2 := reciprocalN * m2to4[2];
  1883. m3 := reciprocalN * m2to4[3];
  1884. m4 := reciprocalN * m2to4[4];
  1885. skew := m3 / (sqrt(m2)*m2);
  1886. kurtosis := m4 / (m2 * m2);
  1887. end;
  1888. function norm(const data : array of Double) : float; inline;
  1889. begin
  1890. norm:=Norm(PDouble(@data[0]),High(Data)+1);
  1891. end;
  1892. function norm(const data : PDouble; Const N : Integer) : float;
  1893. begin
  1894. norm:=sqrt(sumofsquares(data,N));
  1895. end;
  1896. {$endif FPC_HAS_TYPE_DOUBLE}
  1897. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1898. procedure MeanAndTotalVariance
  1899. (const data: PExtended; N: LongInt; var mu, variance: float);
  1900. function CalcVariance(data: PExtended; N: SizeInt; mu: float): float;
  1901. var
  1902. i: SizeInt;
  1903. begin
  1904. if N>=RecursiveSumThreshold then
  1905. result:=CalcVariance(data,SizeUint(N) div 2,mu)+CalcVariance(data+SizeUint(N) div 2,N-SizeUint(N) div 2,mu)
  1906. else
  1907. begin
  1908. result:=0;
  1909. for i:=0 to N-1 do
  1910. result:=result+Sqr(data[i]-mu);
  1911. end;
  1912. end;
  1913. begin
  1914. mu := Mean( data, N );
  1915. variance := CalcVariance( data, N, mu );
  1916. end;
  1917. function stddev(const data : array of Extended) : float; inline;
  1918. begin
  1919. Result:=Stddev(PExtended(@Data[0]),High(Data)+1)
  1920. end;
  1921. function stddev(const data : PExtended; Const N : Integer) : float;
  1922. begin
  1923. StdDev:=Sqrt(Variance(Data,N));
  1924. end;
  1925. procedure meanandstddev(const data : array of Extended;
  1926. var mean,stddev : float); inline;
  1927. begin
  1928. Meanandstddev(PExtended(@Data[0]),High(Data)+1,Mean,stddev);
  1929. end;
  1930. procedure meanandstddev
  1931. ( const data: PExtended;
  1932. const N: Longint;
  1933. var mean,
  1934. stdDev: Float
  1935. );
  1936. var totalVariance: float;
  1937. begin
  1938. MeanAndTotalVariance( data, N, mean, totalVariance );
  1939. if N < 2 then stdDev := 0
  1940. else stdDev := Sqrt( totalVariance / ( N - 1 ) );
  1941. end;
  1942. function variance(const data : array of Extended) : float; inline;
  1943. begin
  1944. Variance:=Variance(PExtended(@Data[0]),High(Data)+1);
  1945. end;
  1946. function variance(const data : PExtended; Const N : Integer) : float;
  1947. begin
  1948. If N=1 then
  1949. Result:=0
  1950. else
  1951. Result:=TotalVariance(Data,N)/(N-1);
  1952. end;
  1953. function totalvariance(const data : array of Extended) : float; inline;
  1954. begin
  1955. Result:=TotalVariance(PExtended(@Data[0]),High(Data)+1);
  1956. end;
  1957. function totalvariance(const data : PExtended;Const N : Integer) : float;
  1958. var mu: float;
  1959. begin
  1960. MeanAndTotalVariance( data, N, mu, result );
  1961. end;
  1962. function popnstddev(const data : array of Extended) : float;
  1963. begin
  1964. PopnStdDev:=Sqrt(PopnVariance(PExtended(@Data[0]),High(Data)+1));
  1965. end;
  1966. function popnstddev(const data : PExtended; Const N : Integer) : float;
  1967. begin
  1968. PopnStdDev:=Sqrt(PopnVariance(Data,N));
  1969. end;
  1970. function popnvariance(const data : array of Extended) : float; inline;
  1971. begin
  1972. popnvariance:=popnvariance(PExtended(@data[0]),high(Data)+1);
  1973. end;
  1974. function popnvariance(const data : PExtended; Const N : Integer) : float;
  1975. begin
  1976. PopnVariance:=TotalVariance(Data,N)/N;
  1977. end;
  1978. procedure momentskewkurtosis(const data : array of Extended;
  1979. out m1,m2,m3,m4,skew,kurtosis : float); inline;
  1980. begin
  1981. momentskewkurtosis(PExtended(@Data[0]),High(Data)+1,m1,m2,m3,m4,skew,kurtosis);
  1982. end;
  1983. procedure momentskewkurtosis(
  1984. const data: pExtended;
  1985. Const N: Integer;
  1986. out m1: float;
  1987. out m2: float;
  1988. out m3: float;
  1989. out m4: float;
  1990. out skew: float;
  1991. out kurtosis: float
  1992. );
  1993. procedure CalcDevSums2to4(data: PExtended; N: SizeInt; m1: float; out m2to4: TMoments2to4);
  1994. var
  1995. tm2, tm3, tm4, dev, dev2: float;
  1996. i: SizeInt;
  1997. m2to4Part0, m2to4Part1: TMoments2to4;
  1998. begin
  1999. if N >= RecursiveSumThreshold then
  2000. begin
  2001. CalcDevSums2to4(data, SizeUint(N) div 2, m1, m2to4Part0);
  2002. CalcDevSums2to4(data + SizeUint(N) div 2, N - SizeUint(N) div 2, m1, m2to4Part1);
  2003. for i := Low(TMoments2to4) to High(TMoments2to4) do
  2004. m2to4[i] := m2to4Part0[i] + m2to4Part1[i];
  2005. end
  2006. else
  2007. begin
  2008. tm2 := 0;
  2009. tm3 := 0;
  2010. tm4 := 0;
  2011. for i := 0 to N - 1 do
  2012. begin
  2013. dev := data[i] - m1;
  2014. dev2 := sqr(dev);
  2015. tm2 := tm2 + dev2;
  2016. tm3 := tm3 + dev2 * dev;
  2017. tm4 := tm4 + sqr(dev2);
  2018. end;
  2019. m2to4[2] := tm2;
  2020. m2to4[3] := tm3;
  2021. m2to4[4] := tm4;
  2022. end;
  2023. end;
  2024. var
  2025. reciprocalN: float;
  2026. m2to4: TMoments2to4;
  2027. begin
  2028. m1 := 0;
  2029. reciprocalN := 1/N;
  2030. m1 := reciprocalN * sum(data, N);
  2031. CalcDevSums2to4(data, N, m1, m2to4);
  2032. m2 := reciprocalN * m2to4[2];
  2033. m3 := reciprocalN * m2to4[3];
  2034. m4 := reciprocalN * m2to4[4];
  2035. skew := m3 / (sqrt(m2)*m2);
  2036. kurtosis := m4 / (m2 * m2);
  2037. end;
  2038. function norm(const data : array of Extended) : float; inline;
  2039. begin
  2040. norm:=Norm(PExtended(@data[0]),High(Data)+1);
  2041. end;
  2042. function norm(const data : PExtended; Const N : Integer) : float;
  2043. begin
  2044. norm:=sqrt(sumofsquares(data,N));
  2045. end;
  2046. {$endif FPC_HAS_TYPE_EXTENDED}
  2047. function MinIntValue(const Data: array of Integer): Integer;
  2048. var
  2049. I: SizeInt;
  2050. begin
  2051. Result := Data[Low(Data)];
  2052. For I := Succ(Low(Data)) To High(Data) Do
  2053. If Data[I] < Result Then Result := Data[I];
  2054. end;
  2055. function MaxIntValue(const Data: array of Integer): Integer;
  2056. var
  2057. I: SizeInt;
  2058. begin
  2059. Result := Data[Low(Data)];
  2060. For I := Succ(Low(Data)) To High(Data) Do
  2061. If Data[I] > Result Then Result := Data[I];
  2062. end;
  2063. function MinValue(const Data: array of Integer): Integer; inline;
  2064. begin
  2065. Result:=MinValue(Pinteger(@Data[0]),High(Data)+1)
  2066. end;
  2067. function MinValue(const Data: PInteger; Const N : Integer): Integer;
  2068. var
  2069. I: SizeInt;
  2070. begin
  2071. Result := Data[0];
  2072. For I := 1 To N-1 do
  2073. If Data[I] < Result Then Result := Data[I];
  2074. end;
  2075. function MaxValue(const Data: array of Integer): Integer; inline;
  2076. begin
  2077. Result:=MaxValue(PInteger(@Data[0]),High(Data)+1)
  2078. end;
  2079. function maxvalue(const data : PInteger; Const N : Integer) : Integer;
  2080. var
  2081. i : SizeInt;
  2082. begin
  2083. { get an initial value }
  2084. maxvalue:=data[0];
  2085. for i:=1 to N-1 do
  2086. if data[i]>maxvalue then
  2087. maxvalue:=data[i];
  2088. end;
  2089. {$ifdef FPC_HAS_TYPE_SINGLE}
  2090. function minvalue(const data : array of Single) : Single; inline;
  2091. begin
  2092. Result:=minvalue(PSingle(@data[0]),High(Data)+1);
  2093. end;
  2094. function minvalue(const data : PSingle; Const N : Integer) : Single;
  2095. var
  2096. i : SizeInt;
  2097. begin
  2098. { get an initial value }
  2099. minvalue:=data[0];
  2100. for i:=1 to N-1 do
  2101. if data[i]<minvalue then
  2102. minvalue:=data[i];
  2103. end;
  2104. function maxvalue(const data : array of Single) : Single; inline;
  2105. begin
  2106. Result:=maxvalue(PSingle(@data[0]),High(Data)+1);
  2107. end;
  2108. function maxvalue(const data : PSingle; Const N : Integer) : Single;
  2109. var
  2110. i : SizeInt;
  2111. begin
  2112. { get an initial value }
  2113. maxvalue:=data[0];
  2114. for i:=1 to N-1 do
  2115. if data[i]>maxvalue then
  2116. maxvalue:=data[i];
  2117. end;
  2118. {$endif FPC_HAS_TYPE_SINGLE}
  2119. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2120. function minvalue(const data : array of Double) : Double; inline;
  2121. begin
  2122. Result:=minvalue(PDouble(@data[0]),High(Data)+1);
  2123. end;
  2124. function minvalue(const data : PDouble; Const N : Integer) : Double;
  2125. var
  2126. i : SizeInt;
  2127. begin
  2128. { get an initial value }
  2129. minvalue:=data[0];
  2130. for i:=1 to N-1 do
  2131. if data[i]<minvalue then
  2132. minvalue:=data[i];
  2133. end;
  2134. function maxvalue(const data : array of Double) : Double; inline;
  2135. begin
  2136. Result:=maxvalue(PDouble(@data[0]),High(Data)+1);
  2137. end;
  2138. function maxvalue(const data : PDouble; Const N : Integer) : Double;
  2139. var
  2140. i : SizeInt;
  2141. begin
  2142. { get an initial value }
  2143. maxvalue:=data[0];
  2144. for i:=1 to N-1 do
  2145. if data[i]>maxvalue then
  2146. maxvalue:=data[i];
  2147. end;
  2148. {$endif FPC_HAS_TYPE_DOUBLE}
  2149. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2150. function minvalue(const data : array of Extended) : Extended; inline;
  2151. begin
  2152. Result:=minvalue(PExtended(@data[0]),High(Data)+1);
  2153. end;
  2154. function minvalue(const data : PExtended; Const N : Integer) : Extended;
  2155. var
  2156. i : SizeInt;
  2157. begin
  2158. { get an initial value }
  2159. minvalue:=data[0];
  2160. for i:=1 to N-1 do
  2161. if data[i]<minvalue then
  2162. minvalue:=data[i];
  2163. end;
  2164. function maxvalue(const data : array of Extended) : Extended; inline;
  2165. begin
  2166. Result:=maxvalue(PExtended(@data[0]),High(Data)+1);
  2167. end;
  2168. function maxvalue(const data : PExtended; Const N : Integer) : Extended;
  2169. var
  2170. i : SizeInt;
  2171. begin
  2172. { get an initial value }
  2173. maxvalue:=data[0];
  2174. for i:=1 to N-1 do
  2175. if data[i]>maxvalue then
  2176. maxvalue:=data[i];
  2177. end;
  2178. {$endif FPC_HAS_TYPE_EXTENDED}
  2179. function Min(a, b: Integer): Integer;inline;
  2180. begin
  2181. if a < b then
  2182. Result := a
  2183. else
  2184. Result := b;
  2185. end;
  2186. function Max(a, b: Integer): Integer;inline;
  2187. begin
  2188. if a > b then
  2189. Result := a
  2190. else
  2191. Result := b;
  2192. end;
  2193. {
  2194. function Min(a, b: Cardinal): Cardinal;inline;
  2195. begin
  2196. if a < b then
  2197. Result := a
  2198. else
  2199. Result := b;
  2200. end;
  2201. function Max(a, b: Cardinal): Cardinal;inline;
  2202. begin
  2203. if a > b then
  2204. Result := a
  2205. else
  2206. Result := b;
  2207. end;
  2208. }
  2209. function Min(a, b: Int64): Int64;inline;
  2210. begin
  2211. if a < b then
  2212. Result := a
  2213. else
  2214. Result := b;
  2215. end;
  2216. function Max(a, b: Int64): Int64;inline;
  2217. begin
  2218. if a > b then
  2219. Result := a
  2220. else
  2221. Result := b;
  2222. end;
  2223. function Min(a, b: QWord): QWord; inline;
  2224. begin
  2225. if a < b then
  2226. Result := a
  2227. else
  2228. Result := b;
  2229. end;
  2230. function Max(a, b: QWord): Qword;inline;
  2231. begin
  2232. if a > b then
  2233. Result := a
  2234. else
  2235. Result := b;
  2236. end;
  2237. {$ifdef FPC_HAS_TYPE_SINGLE}
  2238. function Min(a, b: Single): Single;inline;
  2239. begin
  2240. if a < b then
  2241. Result := a
  2242. else
  2243. Result := b;
  2244. end;
  2245. function Max(a, b: Single): Single;inline;
  2246. begin
  2247. if a > b then
  2248. Result := a
  2249. else
  2250. Result := b;
  2251. end;
  2252. {$endif FPC_HAS_TYPE_SINGLE}
  2253. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2254. function Min(a, b: Double): Double;inline;
  2255. begin
  2256. if a < b then
  2257. Result := a
  2258. else
  2259. Result := b;
  2260. end;
  2261. function Max(a, b: Double): Double;inline;
  2262. begin
  2263. if a > b then
  2264. Result := a
  2265. else
  2266. Result := b;
  2267. end;
  2268. {$endif FPC_HAS_TYPE_DOUBLE}
  2269. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2270. function Min(a, b: Extended): Extended;inline;
  2271. begin
  2272. if a < b then
  2273. Result := a
  2274. else
  2275. Result := b;
  2276. end;
  2277. function Max(a, b: Extended): Extended;inline;
  2278. begin
  2279. if a > b then
  2280. Result := a
  2281. else
  2282. Result := b;
  2283. end;
  2284. {$endif FPC_HAS_TYPE_EXTENDED}
  2285. function InRange(const AValue, AMin, AMax: Integer): Boolean;inline;
  2286. begin
  2287. Result:=(AValue>=AMin) and (AValue<=AMax);
  2288. end;
  2289. function InRange(const AValue, AMin, AMax: Int64): Boolean;inline;
  2290. begin
  2291. Result:=(AValue>=AMin) and (AValue<=AMax);
  2292. end;
  2293. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2294. function InRange(const AValue, AMin, AMax: Double): Boolean;inline;
  2295. begin
  2296. Result:=(AValue>=AMin) and (AValue<=AMax);
  2297. end;
  2298. {$endif FPC_HAS_TYPE_DOUBLE}
  2299. function EnsureRange(const AValue, AMin, AMax: Integer): Integer;inline;
  2300. begin
  2301. Result:=AValue;
  2302. If Result<AMin then
  2303. Result:=AMin;
  2304. if Result>AMax then
  2305. Result:=AMax;
  2306. end;
  2307. function EnsureRange(const AValue, AMin, AMax: Int64): Int64;inline;
  2308. begin
  2309. Result:=AValue;
  2310. If Result<AMin then
  2311. Result:=AMin;
  2312. if Result>AMax then
  2313. Result:=AMax;
  2314. end;
  2315. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2316. function EnsureRange(const AValue, AMin, AMax: Double): Double;inline;
  2317. begin
  2318. Result:=AValue;
  2319. If Result<AMin then
  2320. Result:=AMin;
  2321. if Result>AMax then
  2322. Result:=AMax;
  2323. end;
  2324. {$endif FPC_HAS_TYPE_DOUBLE}
  2325. Const
  2326. EZeroResolution = Extended(1E-16);
  2327. DZeroResolution = Double(1E-12);
  2328. SZeroResolution = Single(1E-4);
  2329. function IsZero(const A: Single; Epsilon: Single): Boolean;
  2330. begin
  2331. if (Epsilon=0) then
  2332. Epsilon:=SZeroResolution;
  2333. Result:=Abs(A)<=Epsilon;
  2334. end;
  2335. function IsZero(const A: Single): Boolean;inline;
  2336. begin
  2337. Result:=IsZero(A,single(SZeroResolution));
  2338. end;
  2339. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2340. function IsZero(const A: Double; Epsilon: Double): Boolean;
  2341. begin
  2342. if (Epsilon=0) then
  2343. Epsilon:=DZeroResolution;
  2344. Result:=Abs(A)<=Epsilon;
  2345. end;
  2346. function IsZero(const A: Double): Boolean;inline;
  2347. begin
  2348. Result:=IsZero(A,DZeroResolution);
  2349. end;
  2350. {$endif FPC_HAS_TYPE_DOUBLE}
  2351. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2352. function IsZero(const A: Extended; Epsilon: Extended): Boolean;
  2353. begin
  2354. if (Epsilon=0) then
  2355. Epsilon:=EZeroResolution;
  2356. Result:=Abs(A)<=Epsilon;
  2357. end;
  2358. function IsZero(const A: Extended): Boolean;inline;
  2359. begin
  2360. Result:=IsZero(A,EZeroResolution);
  2361. end;
  2362. {$endif FPC_HAS_TYPE_EXTENDED}
  2363. type
  2364. TSplitDouble = packed record
  2365. cards: Array[0..1] of cardinal;
  2366. end;
  2367. TSplitExtended = packed record
  2368. cards: Array[0..1] of cardinal;
  2369. w: word;
  2370. end;
  2371. function IsNan(const d : Single): Boolean; overload;
  2372. begin
  2373. result:=(longword(d) and $7fffffff)>$7f800000;
  2374. end;
  2375. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2376. function IsNan(const d : Double): Boolean;
  2377. var
  2378. fraczero, expMaximal: boolean;
  2379. begin
  2380. {$if defined(FPC_BIG_ENDIAN) or defined(FPC_DOUBLE_HILO_SWAPPED)}
  2381. expMaximal := ((TSplitDouble(d).cards[0] shr 20) and $7ff) = 2047;
  2382. fraczero:= (TSplitDouble(d).cards[0] and $fffff = 0) and
  2383. (TSplitDouble(d).cards[1] = 0);
  2384. {$else FPC_BIG_ENDIAN}
  2385. expMaximal := ((TSplitDouble(d).cards[1] shr 20) and $7ff) = 2047;
  2386. fraczero := (TSplitDouble(d).cards[1] and $fffff = 0) and
  2387. (TSplitDouble(d).cards[0] = 0);
  2388. {$endif FPC_BIG_ENDIAN}
  2389. Result:=expMaximal and not(fraczero);
  2390. end;
  2391. {$endif FPC_HAS_TYPE_DOUBLE}
  2392. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2393. function IsNan(const d : Extended): Boolean; overload;
  2394. var
  2395. fraczero, expMaximal: boolean;
  2396. begin
  2397. {$ifdef FPC_BIG_ENDIAN}
  2398. {$error no support for big endian extended type yet}
  2399. {$else FPC_BIG_ENDIAN}
  2400. expMaximal := (TSplitExtended(d).w and $7fff) = 32767;
  2401. fraczero := (TSplitExtended(d).cards[0] = 0) and
  2402. ((TSplitExtended(d).cards[1] and $7fffffff) = 0);
  2403. {$endif FPC_BIG_ENDIAN}
  2404. Result:=expMaximal and not(fraczero);
  2405. end;
  2406. {$endif FPC_HAS_TYPE_EXTENDED}
  2407. function IsInfinite(const d : Single): Boolean; overload;
  2408. begin
  2409. result:=(longword(d) and $7fffffff)=$7f800000;
  2410. end;
  2411. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2412. function IsInfinite(const d : Double): Boolean; overload;
  2413. var
  2414. fraczero, expMaximal: boolean;
  2415. begin
  2416. {$if defined(FPC_BIG_ENDIAN) or defined(FPC_DOUBLE_HILO_SWAPPED)}
  2417. expMaximal := ((TSplitDouble(d).cards[0] shr 20) and $7ff) = 2047;
  2418. fraczero:= (TSplitDouble(d).cards[0] and $fffff = 0) and
  2419. (TSplitDouble(d).cards[1] = 0);
  2420. {$else FPC_BIG_ENDIAN}
  2421. expMaximal := ((TSplitDouble(d).cards[1] shr 20) and $7ff) = 2047;
  2422. fraczero := (TSplitDouble(d).cards[1] and $fffff = 0) and
  2423. (TSplitDouble(d).cards[0] = 0);
  2424. {$endif FPC_BIG_ENDIAN}
  2425. Result:=expMaximal and fraczero;
  2426. end;
  2427. {$endif FPC_HAS_TYPE_DOUBLE}
  2428. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2429. function IsInfinite(const d : Extended): Boolean; overload;
  2430. var
  2431. fraczero, expMaximal: boolean;
  2432. begin
  2433. {$ifdef FPC_BIG_ENDIAN}
  2434. {$error no support for big endian extended type yet}
  2435. {$else FPC_BIG_ENDIAN}
  2436. expMaximal := (TSplitExtended(d).w and $7fff) = 32767;
  2437. fraczero := (TSplitExtended(d).cards[0] = 0) and
  2438. ((TSplitExtended(d).cards[1] and $7fffffff) = 0);
  2439. {$endif FPC_BIG_ENDIAN}
  2440. Result:=expMaximal and fraczero;
  2441. end;
  2442. {$endif FPC_HAS_TYPE_EXTENDED}
  2443. function copysign(x,y: float): float;
  2444. begin
  2445. {$if defined(FPC_HAS_TYPE_FLOAT128)}
  2446. {$error copysign not yet implemented for float128}
  2447. {$elseif defined(FPC_HAS_TYPE_EXTENDED)}
  2448. TSplitExtended(x).w:=(TSplitExtended(x).w and $7fff) or (TSplitExtended(y).w and $8000);
  2449. {$elseif defined(FPC_HAS_TYPE_DOUBLE)}
  2450. {$if defined(FPC_BIG_ENDIAN) or defined(FPC_DOUBLE_HILO_SWAPPED)}
  2451. TSplitDouble(x).cards[0]:=(TSplitDouble(x).cards[0] and $7fffffff) or (TSplitDouble(y).cards[0] and longword($80000000));
  2452. {$else}
  2453. TSplitDouble(x).cards[1]:=(TSplitDouble(x).cards[1] and $7fffffff) or (TSplitDouble(y).cards[1] and longword($80000000));
  2454. {$endif}
  2455. {$else}
  2456. longword(x):=longword(x and $7fffffff) or (longword(y) and longword($80000000));
  2457. {$endif}
  2458. result:=x;
  2459. end;
  2460. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2461. function SameValue(const A, B: Extended; Epsilon: Extended): Boolean;
  2462. begin
  2463. if (Epsilon=0) then
  2464. Epsilon:=Max(Min(Abs(A),Abs(B))*EZeroResolution,EZeroResolution);
  2465. if (A>B) then
  2466. Result:=((A-B)<=Epsilon)
  2467. else
  2468. Result:=((B-A)<=Epsilon);
  2469. end;
  2470. function SameValue(const A, B: Extended): Boolean;inline;
  2471. begin
  2472. Result:=SameValue(A,B,0.0);
  2473. end;
  2474. {$endif FPC_HAS_TYPE_EXTENDED}
  2475. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2476. function SameValue(const A, B: Double): Boolean;inline;
  2477. begin
  2478. Result:=SameValue(A,B,0.0);
  2479. end;
  2480. function SameValue(const A, B: Double; Epsilon: Double): Boolean;
  2481. begin
  2482. if (Epsilon=0) then
  2483. Epsilon:=Max(Min(Abs(A),Abs(B))*DZeroResolution,DZeroResolution);
  2484. if (A>B) then
  2485. Result:=((A-B)<=Epsilon)
  2486. else
  2487. Result:=((B-A)<=Epsilon);
  2488. end;
  2489. {$endif FPC_HAS_TYPE_DOUBLE}
  2490. function SameValue(const A, B: Single): Boolean;inline;
  2491. begin
  2492. Result:=SameValue(A,B,0);
  2493. end;
  2494. function SameValue(const A, B: Single; Epsilon: Single): Boolean;
  2495. begin
  2496. if (Epsilon=0) then
  2497. Epsilon:=Max(Min(Abs(A),Abs(B))*SZeroResolution,SZeroResolution);
  2498. if (A>B) then
  2499. Result:=((A-B)<=Epsilon)
  2500. else
  2501. Result:=((B-A)<=Epsilon);
  2502. end;
  2503. // Some CPUs probably allow a faster way of doing this in a single operation...
  2504. // There weshould define FPC_MATH_HAS_CPUDIVMOD in the header mathuh.inc and implement it using asm.
  2505. {$ifndef FPC_MATH_HAS_DIVMOD}
  2506. procedure DivMod(Dividend: LongInt; Divisor: Word; var Result, Remainder: Word);
  2507. begin
  2508. if Dividend < 0 then
  2509. begin
  2510. { Use DivMod with >=0 dividend }
  2511. Dividend:=-Dividend;
  2512. { The documented behavior of Pascal's div/mod operators and DivMod
  2513. on negative dividends is to return Result closer to zero and
  2514. a negative Remainder. Which means that we can just negate both
  2515. Result and Remainder, and all it's Ok. }
  2516. Result:=-(Dividend Div Divisor);
  2517. Remainder:=-(Dividend+(Result*Divisor));
  2518. end
  2519. else
  2520. begin
  2521. Result:=Dividend Div Divisor;
  2522. Remainder:=Dividend-(Result*Divisor);
  2523. end;
  2524. end;
  2525. procedure DivMod(Dividend: LongInt; Divisor: Word; var Result, Remainder: SmallInt);
  2526. begin
  2527. if Dividend < 0 then
  2528. begin
  2529. { Use DivMod with >=0 dividend }
  2530. Dividend:=-Dividend;
  2531. { The documented behavior of Pascal's div/mod operators and DivMod
  2532. on negative dividends is to return Result closer to zero and
  2533. a negative Remainder. Which means that we can just negate both
  2534. Result and Remainder, and all it's Ok. }
  2535. Result:=-(Dividend Div Divisor);
  2536. Remainder:=-(Dividend+(Result*Divisor));
  2537. end
  2538. else
  2539. begin
  2540. Result:=Dividend Div Divisor;
  2541. Remainder:=Dividend-(Result*Divisor);
  2542. end;
  2543. end;
  2544. procedure DivMod(Dividend: DWord; Divisor: DWord; var Result, Remainder: DWord);
  2545. begin
  2546. Result:=Dividend Div Divisor;
  2547. Remainder:=Dividend-(Result*Divisor);
  2548. end;
  2549. procedure DivMod(Dividend: LongInt; Divisor: LongInt; var Result, Remainder: LongInt);
  2550. begin
  2551. if Dividend < 0 then
  2552. begin
  2553. { Use DivMod with >=0 dividend }
  2554. Dividend:=-Dividend;
  2555. { The documented behavior of Pascal's div/mod operators and DivMod
  2556. on negative dividends is to return Result closer to zero and
  2557. a negative Remainder. Which means that we can just negate both
  2558. Result and Remainder, and all it's Ok. }
  2559. Result:=-(Dividend Div Divisor);
  2560. Remainder:=-(Dividend+(Result*Divisor));
  2561. end
  2562. else
  2563. begin
  2564. Result:=Dividend Div Divisor;
  2565. Remainder:=Dividend-(Result*Divisor);
  2566. end;
  2567. end;
  2568. {$endif FPC_MATH_HAS_DIVMOD}
  2569. { Floating point modulo}
  2570. {$ifdef FPC_HAS_TYPE_SINGLE}
  2571. function FMod(const a, b: Single): Single;inline;overload;
  2572. begin
  2573. result:= a-b * Int(a/b);
  2574. end;
  2575. {$endif FPC_HAS_TYPE_SINGLE}
  2576. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2577. function FMod(const a, b: Double): Double;inline;overload;
  2578. begin
  2579. result:= a-b * Int(a/b);
  2580. end;
  2581. {$endif FPC_HAS_TYPE_DOUBLE}
  2582. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2583. function FMod(const a, b: Extended): Extended;inline;overload;
  2584. begin
  2585. result:= a-b * Int(a/b);
  2586. end;
  2587. {$endif FPC_HAS_TYPE_EXTENDED}
  2588. operator mod(const a,b:float) c:float;inline;
  2589. begin
  2590. c:= a-b * Int(a/b);
  2591. if SameValue(abs(c),abs(b)) then
  2592. c:=0.0;
  2593. end;
  2594. function ifthen(val:boolean;const iftrue:integer; const iffalse:integer= 0) :integer;
  2595. begin
  2596. if val then result:=iftrue else result:=iffalse;
  2597. end;
  2598. function ifthen(val:boolean;const iftrue:int64 ; const iffalse:int64 = 0) :int64;
  2599. begin
  2600. if val then result:=iftrue else result:=iffalse;
  2601. end;
  2602. function ifthen(val:boolean;const iftrue:double ; const iffalse:double =0.0):double;
  2603. begin
  2604. if val then result:=iftrue else result:=iffalse;
  2605. end;
  2606. // dilemma here. asm can do the two comparisons in one go?
  2607. // but pascal is portable and can be inlined. Ah well, we need purepascal's anyway:
  2608. function CompareValue(const A, B : Integer): TValueRelationship;
  2609. begin
  2610. result:=GreaterThanValue;
  2611. if a=b then
  2612. result:=EqualsValue
  2613. else
  2614. if a<b then
  2615. result:=LessThanValue;
  2616. end;
  2617. function CompareValue(const A, B: Int64): TValueRelationship;
  2618. begin
  2619. result:=GreaterThanValue;
  2620. if a=b then
  2621. result:=EqualsValue
  2622. else
  2623. if a<b then
  2624. result:=LessThanValue;
  2625. end;
  2626. function CompareValue(const A, B: QWord): TValueRelationship;
  2627. begin
  2628. result:=GreaterThanValue;
  2629. if a=b then
  2630. result:=EqualsValue
  2631. else
  2632. if a<b then
  2633. result:=LessThanValue;
  2634. end;
  2635. {$ifdef FPC_HAS_TYPE_SINGLE}
  2636. function CompareValue(const A, B: Single; delta: Single = 0.0): TValueRelationship;
  2637. begin
  2638. result:=GreaterThanValue;
  2639. if abs(a-b)<=delta then
  2640. result:=EqualsValue
  2641. else
  2642. if a<b then
  2643. result:=LessThanValue;
  2644. end;
  2645. {$endif}
  2646. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2647. function CompareValue(const A, B: Double; delta: Double = 0.0): TValueRelationship;
  2648. begin
  2649. result:=GreaterThanValue;
  2650. if abs(a-b)<=delta then
  2651. result:=EqualsValue
  2652. else
  2653. if a<b then
  2654. result:=LessThanValue;
  2655. end;
  2656. {$endif}
  2657. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2658. function CompareValue (const A, B: Extended; delta: Extended = 0.0): TValueRelationship;
  2659. begin
  2660. result:=GreaterThanValue;
  2661. if abs(a-b)<=delta then
  2662. result:=EqualsValue
  2663. else
  2664. if a<b then
  2665. result:=LessThanValue;
  2666. end;
  2667. {$endif}
  2668. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2669. function RoundTo(const AValue: Double; const Digits: TRoundToRange): Double;
  2670. var
  2671. RV : Double;
  2672. begin
  2673. RV:=IntPower(10,Digits);
  2674. Result:=Round(AValue/RV)*RV;
  2675. end;
  2676. {$endif}
  2677. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2678. function RoundTo(const AVAlue: Extended; const Digits: TRoundToRange): Extended;
  2679. var
  2680. RV : Extended;
  2681. begin
  2682. RV:=IntPower(10,Digits);
  2683. Result:=Round(AValue/RV)*RV;
  2684. end;
  2685. {$endif}
  2686. {$ifdef FPC_HAS_TYPE_SINGLE}
  2687. function RoundTo(const AValue: Single; const Digits: TRoundToRange): Single;
  2688. var
  2689. RV : Single;
  2690. begin
  2691. RV:=IntPower(10,Digits);
  2692. Result:=Round(AValue/RV)*RV;
  2693. end;
  2694. {$endif}
  2695. {$ifdef FPC_HAS_TYPE_SINGLE}
  2696. function SimpleRoundTo(const AValue: Single; const Digits: TRoundToRange = -2): Single;
  2697. var
  2698. RV : Single;
  2699. begin
  2700. RV := IntPower(10, -Digits);
  2701. if AValue < 0 then
  2702. Result := Int((AValue*RV) - 0.5)/RV
  2703. else
  2704. Result := Int((AValue*RV) + 0.5)/RV;
  2705. end;
  2706. {$endif}
  2707. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2708. function SimpleRoundTo(const AValue: Double; const Digits: TRoundToRange = -2): Double;
  2709. var
  2710. RV : Double;
  2711. begin
  2712. RV := IntPower(10, -Digits);
  2713. if AValue < 0 then
  2714. Result := Int((AValue*RV) - 0.5)/RV
  2715. else
  2716. Result := Int((AValue*RV) + 0.5)/RV;
  2717. end;
  2718. {$endif}
  2719. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2720. function SimpleRoundTo(const AValue: Extended; const Digits: TRoundToRange = -2): Extended;
  2721. var
  2722. RV : Extended;
  2723. begin
  2724. RV := IntPower(10, -Digits);
  2725. if AValue < 0 then
  2726. Result := Int((AValue*RV) - 0.5)/RV
  2727. else
  2728. Result := Int((AValue*RV) + 0.5)/RV;
  2729. end;
  2730. {$endif}
  2731. function RandomFrom(const AValues: array of Double): Double; overload;
  2732. begin
  2733. result:=AValues[random(High(AValues)+1)];
  2734. end;
  2735. function RandomFrom(const AValues: array of Integer): Integer; overload;
  2736. begin
  2737. result:=AValues[random(High(AValues)+1)];
  2738. end;
  2739. function RandomFrom(const AValues: array of Int64): Int64; overload;
  2740. begin
  2741. result:=AValues[random(High(AValues)+1)];
  2742. end;
  2743. {$if FPC_FULLVERSION >=30101}
  2744. generic function RandomFrom<T>(const AValues:array of T):T;
  2745. begin
  2746. result:=AValues[random(High(AValues)+1)];
  2747. end;
  2748. {$endif}
  2749. function FutureValue(ARate: Float; NPeriods: Integer;
  2750. APayment, APresentValue: Float; APaymentTime: TPaymentTime): Float;
  2751. var
  2752. q, qn, factor: Float;
  2753. begin
  2754. if ARate = 0 then
  2755. Result := -APresentValue - APayment * NPeriods
  2756. else begin
  2757. q := 1.0 + ARate;
  2758. qn := power(q, NPeriods);
  2759. factor := (qn - 1) / (q - 1);
  2760. if APaymentTime = ptStartOfPeriod then
  2761. factor := factor * q;
  2762. Result := -(APresentValue * qn + APayment*factor);
  2763. end;
  2764. end;
  2765. function InterestRate(NPeriods: Integer; APayment, APresentValue, AFutureValue: Float;
  2766. APaymentTime: TPaymentTime): Float;
  2767. { The interest rate cannot be calculated analytically. We solve the equation
  2768. numerically by means of the Newton method:
  2769. - guess value for the interest reate
  2770. - calculate at which interest rate the tangent of the curve fv(rate)
  2771. (straight line!) has the requested future vale.
  2772. - use this rate for the next iteration. }
  2773. const
  2774. DELTA = 0.001;
  2775. EPS = 1E-9; // required precision of interest rate (after typ. 6 iterations)
  2776. MAXIT = 20; // max iteration count to protect agains non-convergence
  2777. var
  2778. r1, r2, dr: Float;
  2779. fv1, fv2: Float;
  2780. iteration: Integer;
  2781. begin
  2782. iteration := 0;
  2783. r1 := 0.05; // inital guess
  2784. repeat
  2785. r2 := r1 + DELTA;
  2786. fv1 := FutureValue(r1, NPeriods, APayment, APresentValue, APaymentTime);
  2787. fv2 := FutureValue(r2, NPeriods, APayment, APresentValue, APaymentTime);
  2788. dr := (AFutureValue - fv1) / (fv2 - fv1) * delta; // tangent at fv(r)
  2789. r1 := r1 + dr; // next guess
  2790. inc(iteration);
  2791. until (abs(dr) < EPS) or (iteration >= MAXIT);
  2792. Result := r1;
  2793. end;
  2794. function NumberOfPeriods(ARate, APayment, APresentValue, AFutureValue: Float;
  2795. APaymentTime: TPaymentTime): Float;
  2796. { Solve the cash flow equation (1) for q^n and take the logarithm }
  2797. var
  2798. q, x1, x2: Float;
  2799. begin
  2800. if ARate = 0 then
  2801. Result := -(APresentValue + AFutureValue) / APayment
  2802. else begin
  2803. q := 1.0 + ARate;
  2804. if APaymentTime = ptStartOfPeriod then
  2805. APayment := APayment * q;
  2806. x1 := APayment - AFutureValue * ARate;
  2807. x2 := APayment + APresentValue * ARate;
  2808. if (x2 = 0) // we have to divide by x2
  2809. or (sign(x1) * sign(x2) < 0) // the argument of the log is negative
  2810. then
  2811. Result := Infinity
  2812. else begin
  2813. Result := ln(x1/x2) / ln(q);
  2814. end;
  2815. end;
  2816. end;
  2817. function Payment(ARate: Float; NPeriods: Integer;
  2818. APresentValue, AFutureValue: Float; APaymentTime: TPaymentTime): Float;
  2819. var
  2820. q, qn, factor: Float;
  2821. begin
  2822. if ARate = 0 then
  2823. Result := -(AFutureValue + APresentValue) / NPeriods
  2824. else begin
  2825. q := 1.0 + ARate;
  2826. qn := power(q, NPeriods);
  2827. factor := (qn - 1) / (q - 1);
  2828. if APaymentTime = ptStartOfPeriod then
  2829. factor := factor * q;
  2830. Result := -(AFutureValue + APresentValue * qn) / factor;
  2831. end;
  2832. end;
  2833. function PresentValue(ARate: Float; NPeriods: Integer;
  2834. APayment, AFutureValue: Float; APaymentTime: TPaymentTime): Float;
  2835. var
  2836. q, qn, factor: Float;
  2837. begin
  2838. if ARate = 0.0 then
  2839. Result := -AFutureValue - APayment * NPeriods
  2840. else begin
  2841. q := 1.0 + ARate;
  2842. qn := power(q, NPeriods);
  2843. factor := (qn - 1) / (q - 1);
  2844. if APaymentTime = ptStartOfPeriod then
  2845. factor := factor * q;
  2846. Result := -(AFutureValue + APayment*factor) / qn;
  2847. end;
  2848. end;
  2849. {$else}
  2850. implementation
  2851. {$endif FPUNONE}
  2852. end.