math.pp 101 KB

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