math.pp 100 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029
  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. exit(huge_single*huge_single);
  1092. temp:=exp(x);
  1093. {$push}
  1094. {$safefpuexceptions on}
  1095. cosh:=0.5*(temp+1.0/temp);
  1096. {$pop}
  1097. end;
  1098. {$ENDIF}
  1099. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1100. function cosh(x : Double) : Double;
  1101. var
  1102. temp : ValReal;
  1103. begin
  1104. if (x>7.10475860073943942030E+0002) or (x<-7.10475860073943942030E+0002) then
  1105. exit(huge_double*huge_double);
  1106. temp:=exp(x);
  1107. {$push}
  1108. {$safefpuexceptions on}
  1109. cosh:=0.5*(temp+1.0/temp);
  1110. {$pop}
  1111. end;
  1112. {$ENDIF}
  1113. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1114. function cosh(x : Extended) : Extended;
  1115. var
  1116. temp : ValReal;
  1117. begin
  1118. temp:=exp(x);
  1119. cosh:=0.5*(temp+1.0/temp);
  1120. end;
  1121. {$ENDIF}
  1122. {$ifdef FPC_HAS_TYPE_SINGLE}
  1123. function sinh(x : Single) : Single;
  1124. var
  1125. temp : ValReal;
  1126. begin
  1127. if x>8.94159862326326216608E+0001 then
  1128. exit(huge_single*huge_single);
  1129. if x<-8.94159862326326216608E+0001 then
  1130. exit(-(huge_single*huge_single));
  1131. temp:=exp(x);
  1132. { gives better behavior around zero, and in particular ensures that sinh(-0.0)=-0.0 }
  1133. if temp=1 then
  1134. exit(x);
  1135. {$push}
  1136. {$safefpuexceptions on}
  1137. sinh:=0.5*(temp-1.0/temp);
  1138. {$pop}
  1139. end;
  1140. {$ENDIF}
  1141. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1142. function sinh(x : Double) : Double;
  1143. var
  1144. temp : ValReal;
  1145. begin
  1146. if x>7.10475860073943942030E+0002 then
  1147. exit(huge_double*huge_double);
  1148. if x<-7.10475860073943942030E+0002 then
  1149. exit(-(huge_double*huge_double));
  1150. temp:=exp(x);
  1151. if temp=1 then
  1152. exit(x);
  1153. {$push}
  1154. {$safefpuexceptions on}
  1155. sinh:=0.5*(temp-1.0/temp);
  1156. {$pop}
  1157. end;
  1158. {$ENDIF}
  1159. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1160. function sinh(x : Extended) : Extended;
  1161. var
  1162. temp : ValReal;
  1163. begin
  1164. temp:=exp(x);
  1165. if temp=1 then
  1166. exit(x);
  1167. sinh:=0.5*(temp-1.0/temp);
  1168. end;
  1169. {$ENDIF}
  1170. {$ifdef FPC_HAS_TYPE_SINGLE}
  1171. function tanh(x : Single) : Single;
  1172. var
  1173. tmp:ValReal;
  1174. begin
  1175. if x < 0 then begin
  1176. tmp:=exp(2*x);
  1177. if tmp=1 then
  1178. exit(x);
  1179. {$push}
  1180. {$safefpuexceptions on}
  1181. result:=(tmp-1)/(1+tmp)
  1182. {$pop}
  1183. end
  1184. else begin
  1185. tmp:=exp(-2*x);
  1186. if tmp=1 then
  1187. exit(x);
  1188. {$push}
  1189. {$safefpuexceptions on}
  1190. result:=(1-tmp)/(1+tmp)
  1191. {$pop}
  1192. end;
  1193. end;
  1194. {$ENDIF}
  1195. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1196. function tanh(x : Double) : Double;
  1197. var
  1198. tmp:ValReal;
  1199. begin
  1200. if x < 0 then begin
  1201. tmp:=exp(2*x);
  1202. if tmp=1 then
  1203. exit(x);
  1204. {$push}
  1205. {$safefpuexceptions on}
  1206. result:=(tmp-1)/(1+tmp)
  1207. {$pop}
  1208. end
  1209. else 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_EXTENDED}
  1221. function tanh(x : Extended) : Extended;
  1222. var
  1223. tmp:Extended;
  1224. begin
  1225. if x < 0 then begin
  1226. tmp:=exp(2*x);
  1227. if tmp=1 then
  1228. exit(x);
  1229. result:=(tmp-1)/(1+tmp)
  1230. end
  1231. else begin
  1232. tmp:=exp(-2*x);
  1233. if tmp=1 then
  1234. exit(x);
  1235. result:=(1-tmp)/(1+tmp)
  1236. end;
  1237. end;
  1238. {$ENDIF}
  1239. {$ifdef FPC_HAS_TYPE_SINGLE}
  1240. function SecH(const X: Single): Single;
  1241. var
  1242. Ex: ValReal;
  1243. begin
  1244. //https://en.wikipedia.org/wiki/Hyperbolic_functions#Definitions
  1245. //SecH = 2 / (e^X + e^-X)
  1246. Ex:=Exp(X);
  1247. {$push}
  1248. {$safefpuexceptions on}
  1249. SecH:=2/(Ex+1/Ex);
  1250. {$pop}
  1251. end;
  1252. {$ENDIF}
  1253. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1254. function SecH(const X: Double): Double;
  1255. var
  1256. Ex: ValReal;
  1257. begin
  1258. Ex:=Exp(X);
  1259. {$push}
  1260. {$safefpuexceptions on}
  1261. SecH:=2/(Ex+1/Ex);
  1262. {$pop}
  1263. end;
  1264. {$ENDIF}
  1265. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1266. function SecH(const X: Extended): Extended;
  1267. var
  1268. Ex: ValReal;
  1269. begin
  1270. Ex:=Exp(X);
  1271. SecH:=2/(Ex+1/Ex);
  1272. end;
  1273. {$ENDIF}
  1274. {$ifdef FPC_HAS_TYPE_SINGLE}
  1275. function CscH(const X: Single): Single;
  1276. var
  1277. Ex: ValReal;
  1278. begin
  1279. //CscH = 2 / (e^X - e^-X)
  1280. Ex:=Exp(X);
  1281. {$push}
  1282. {$safefpuexceptions on}
  1283. CscH:=2/(Ex-1/Ex);
  1284. {$pop}
  1285. end;
  1286. {$ENDIF}
  1287. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1288. function CscH(const X: Double): Double;
  1289. var
  1290. Ex: ValReal;
  1291. begin
  1292. Ex:=Exp(X);
  1293. {$push}
  1294. {$safefpuexceptions on}
  1295. CscH:=2/(Ex-1/Ex);
  1296. {$pop}
  1297. end;
  1298. {$ENDIF}
  1299. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1300. function CscH(const X: Extended): Extended;
  1301. var
  1302. Ex: ValReal;
  1303. begin
  1304. Ex:=Exp(X);
  1305. CscH:=2/(Ex-1/Ex);
  1306. end;
  1307. {$ENDIF}
  1308. {$ifdef FPC_HAS_TYPE_SINGLE}
  1309. function CotH(const X: Single): Single;
  1310. var
  1311. e2: ValReal;
  1312. begin
  1313. if x < 0 then begin
  1314. e2:=exp(2*x);
  1315. if e2=1 then
  1316. exit(1/x);
  1317. {$push}
  1318. {$safefpuexceptions on}
  1319. result:=(1+e2)/(e2-1)
  1320. {$pop}
  1321. end
  1322. else begin
  1323. e2:=exp(-2*x);
  1324. if e2=1 then
  1325. exit(1/x);
  1326. {$push}
  1327. {$safefpuexceptions on}
  1328. result:=(1+e2)/(1-e2)
  1329. {$pop}
  1330. end;
  1331. end;
  1332. {$ENDIF}
  1333. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1334. function CotH(const X: Double): Double;
  1335. var
  1336. e2: ValReal;
  1337. begin
  1338. if x < 0 then begin
  1339. e2:=exp(2*x);
  1340. if e2=1 then
  1341. exit(1/x);
  1342. {$push}
  1343. {$safefpuexceptions on}
  1344. result:=(1+e2)/(e2-1)
  1345. {$pop}
  1346. end
  1347. else begin
  1348. e2:=exp(-2*x);
  1349. if e2=1 then
  1350. exit(1/x);
  1351. {$push}
  1352. {$safefpuexceptions on}
  1353. result:=(1+e2)/(1-e2)
  1354. {$pop}
  1355. end;
  1356. end;
  1357. {$ENDIF}
  1358. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1359. function CotH(const X: Extended): Extended;
  1360. var
  1361. e2: ValReal;
  1362. begin
  1363. if x < 0 then begin
  1364. e2:=exp(2*x);
  1365. if e2=1 then
  1366. exit(1/x);
  1367. result:=(1+e2)/(e2-1)
  1368. end
  1369. else begin
  1370. e2:=exp(-2*x);
  1371. if e2=1 then
  1372. exit(1/x);
  1373. result:=(1+e2)/(1-e2)
  1374. end;
  1375. end;
  1376. {$ENDIF}
  1377. function arccosh(x : float) : float; inline;
  1378. begin
  1379. arccosh:=arcosh(x);
  1380. end;
  1381. function arcsinh(x : float) : float;inline;
  1382. begin
  1383. arcsinh:=arsinh(x);
  1384. end;
  1385. function arctanh(x : float) : float;inline;
  1386. begin
  1387. arctanh:=artanh(x);
  1388. end;
  1389. function arcosh(x : float) : float;
  1390. begin
  1391. { Provides accuracy about 4*eps near 1.0 }
  1392. arcosh:=Ln(x+Sqrt((x-1.0)*(x+1.0)));
  1393. end;
  1394. function arsinh(x : float) : float;
  1395. var
  1396. z: float;
  1397. begin
  1398. z:=abs(x);
  1399. z:=Ln(z+Sqrt(1+z*z));
  1400. { copysign ensures that arsinh(-Inf)=-Inf and arsinh(-0.0)=-0.0 }
  1401. arsinh:=copysign(z,x);
  1402. end;
  1403. function artanh(x : float) : float;
  1404. begin
  1405. artanh:=(lnxp1(x)-lnxp1(-x))*0.5;
  1406. end;
  1407. {$ifdef FPC_HAS_TYPE_SINGLE}
  1408. function ArcSec(X: Single): Single;
  1409. begin
  1410. ArcSec:=ArcCos(1/X);
  1411. end;
  1412. {$ENDIF}
  1413. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1414. function ArcSec(X: Double): Double;
  1415. begin
  1416. ArcSec:=ArcCos(1/X);
  1417. end;
  1418. {$ENDIF}
  1419. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1420. function ArcSec(X: Extended): Extended;
  1421. begin
  1422. ArcSec:=ArcCos(1/X);
  1423. end;
  1424. {$ENDIF}
  1425. {$ifdef FPC_HAS_TYPE_SINGLE}
  1426. function ArcCsc(X: Single): Single;
  1427. begin
  1428. ArcCsc:=ArcSin(1/X);
  1429. end;
  1430. {$ENDIF}
  1431. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1432. function ArcCsc(X: Double): Double;
  1433. begin
  1434. ArcCsc:=ArcSin(1/X);
  1435. end;
  1436. {$ENDIF}
  1437. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1438. function ArcCsc(X: Extended): Extended;
  1439. begin
  1440. ArcCsc:=ArcSin(1/X);
  1441. end;
  1442. {$ENDIF}
  1443. {$ifdef FPC_HAS_TYPE_SINGLE}
  1444. function ArcCot(X: Single): Single;
  1445. begin
  1446. if x=0 then
  1447. ArcCot:=0.5*pi
  1448. else
  1449. ArcCot:=ArcTan(1/X);
  1450. end;
  1451. {$ENDIF}
  1452. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1453. function ArcCot(X: Double): Double;
  1454. begin
  1455. begin
  1456. if x=0 then
  1457. ArcCot:=0.5*pi
  1458. else
  1459. ArcCot:=ArcTan(1/X);
  1460. end;
  1461. end;
  1462. {$ENDIF}
  1463. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1464. function ArcCot(X: Extended): Extended;
  1465. begin
  1466. begin
  1467. if x=0 then
  1468. ArcCot:=0.5*pi
  1469. else
  1470. ArcCot:=ArcTan(1/X);
  1471. end;
  1472. end;
  1473. {$ENDIF}
  1474. {$ifdef FPC_HAS_TYPE_SINGLE}
  1475. function ArcSecH(X : Single): Single;
  1476. begin
  1477. ArcSecH:=ln((1+(sqrt(1.0-sqr(X))))/X); //replacing division inside ln() by subtracting 2 ln()'s seems to be slower
  1478. end;
  1479. {$ENDIF}
  1480. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1481. function ArcSecH(X : Double): Double;
  1482. begin
  1483. ArcSecH:=ln((1+(sqrt(1.0-sqr(X))))/X);
  1484. end;
  1485. {$ENDIF}
  1486. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1487. function ArcSecH(X : Extended): Extended;
  1488. begin
  1489. ArcSecH:=ln((1+(sqrt(1.0-sqr(X))))/X);
  1490. end;
  1491. {$ENDIF}
  1492. {$ifdef FPC_HAS_TYPE_SINGLE}
  1493. function ArcCscH(X: Single): Single;
  1494. begin
  1495. ArcCscH:=ln((1.0/X)+sqrt(1.0/(sqr(x))+1.0));
  1496. end;
  1497. {$ENDIF}
  1498. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1499. function ArcCscH(X: Double): Double;
  1500. begin
  1501. ArcCscH:=ln((1.0/X)+sqrt(1.0/(sqr(x))+1.0));
  1502. end;
  1503. {$ENDIF}
  1504. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1505. function ArcCscH(X: Extended): Extended;
  1506. begin
  1507. ArcCscH:=ln((1.0/X)+sqrt(1.0/(sqr(x))+1.0));
  1508. end;
  1509. {$ENDIF}
  1510. {$ifdef FPC_HAS_TYPE_SINGLE}
  1511. function ArcCotH(X: Single): Single;
  1512. begin
  1513. ArcCotH:=0.5*ln((x + 1.0)/(x - 1.0));
  1514. end;
  1515. {$ENDIF}
  1516. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1517. function ArcCotH(X: Double): Double;
  1518. begin
  1519. ArcCotH:=0.5*ln((x + 1.0)/(x - 1.0));
  1520. end;
  1521. {$ENDIF}
  1522. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1523. function ArcCotH(X: Extended): Extended;
  1524. begin
  1525. ArcCotH:=0.5*ln((x + 1.0)/(x - 1.0));
  1526. end;
  1527. {$ENDIF}
  1528. { hypot function from AMath library (C) Copyright 2009-2013 Wolfgang Ehrhardt }
  1529. function hypot(x,y : float) : float;
  1530. begin
  1531. x:=abs(x);
  1532. y:=abs(y);
  1533. if (x>y) then
  1534. hypot:=x*sqrt(1.0+sqr(y/x))
  1535. else if (x>0.0) then
  1536. hypot:=y*sqrt(1.0+sqr(x/y))
  1537. else
  1538. hypot:=y;
  1539. end;
  1540. function log10(x : float) : float;
  1541. begin
  1542. log10:=ln(x)*0.43429448190325182765; { 1/ln(10) }
  1543. end;
  1544. {$ifndef FPC_MATH_HAS_LOG2}
  1545. function log2(x : float) : float;
  1546. begin
  1547. log2:=ln(x)*1.4426950408889634079; { 1/ln(2) }
  1548. end;
  1549. {$endif FPC_MATH_HAS_LOG2}
  1550. function logn(n,x : float) : float;
  1551. begin
  1552. logn:=ln(x)/ln(n);
  1553. end;
  1554. { lnxp1 function from AMath library (C) Copyright 2009-2013 Wolfgang Ehrhardt }
  1555. function lnxp1(x : float) : float;
  1556. var
  1557. y: float;
  1558. begin
  1559. if (x>=4.0) then
  1560. lnxp1:=ln(1.0+x)
  1561. else
  1562. begin
  1563. y:=1.0+x;
  1564. if (y=1.0) then
  1565. lnxp1:=x
  1566. else
  1567. begin
  1568. lnxp1:=ln(y); { lnxp1(-1) = ln(0) = -Inf }
  1569. if y>0.0 then
  1570. lnxp1:=lnxp1+(x-(y-1.0))/y;
  1571. end;
  1572. end;
  1573. end;
  1574. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1575. { Ref: Boost, expm1.hpp }
  1576. function PolyEval(x: double; const a: array of double): double;
  1577. var
  1578. i : sizeint;
  1579. begin
  1580. result:=a[High(a)];
  1581. for i:=High(a)-1 downto 0 do result:=result*x+a[i];
  1582. end;
  1583. function ExpM1(x : double) : double;
  1584. const
  1585. P: array[0..5] of double = (
  1586. -2.8127670288085937500E-2,
  1587. +5.1278186299064532072E-1,
  1588. -6.3100290693501981387E-2,
  1589. +1.1638457975729295593E-2,
  1590. -5.2143390687520998431E-4,
  1591. +2.1491399776965686808E-5);
  1592. Q: array[0..5] of double = (
  1593. +1.0000000000000000000,
  1594. -4.5442309511354755935E-1,
  1595. +9.0850389570911710413E-2,
  1596. -1.0088963629815501238E-2,
  1597. +6.3003407478692265934E-4,
  1598. -1.7976570003654402936E-5);
  1599. var
  1600. a : double;
  1601. begin
  1602. a:=abs(x);
  1603. if a>0.5 then
  1604. result:=exp(x)-1.0
  1605. else if a<3e-16 then
  1606. result:=x
  1607. else
  1608. result:=x*double(0.10281276702880859e1)+x*(PolyEval(x,P)/PolyEval(x,Q));
  1609. end;
  1610. {$endif}
  1611. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1612. function PolyEval(x: extended; const a: array of extended): extended;
  1613. var
  1614. i : sizeint;
  1615. begin
  1616. result:=a[High(a)];
  1617. for i:=High(a)-1 downto 0 do result:=result*x+a[i];
  1618. end;
  1619. function ExpM1(x : extended) : extended;
  1620. const
  1621. P: array[0..9] of extended = (
  1622. -0.28127670288085937499999999999999999854e-1,
  1623. +0.51278156911210477556524452177540792214e0,
  1624. -0.63263178520747096729500254678819588223e-1,
  1625. +0.14703285606874250425508446801230572252e-1,
  1626. -0.8675686051689527802425310407898459386e-3,
  1627. +0.88126359618291165384647080266133492399e-4,
  1628. -0.25963087867706310844432390015463138953e-5,
  1629. +0.14226691087800461778631773363204081194e-6,
  1630. -0.15995603306536496772374181066765665596e-8,
  1631. +0.45261820069007790520447958280473183582e-10);
  1632. Q: array[0..10] of extended = (
  1633. +1,
  1634. -0.45441264709074310514348137469214538853e0,
  1635. +0.96827131936192217313133611655555298106e-1,
  1636. -0.12745248725908178612540554584374876219e-1,
  1637. +0.11473613871583259821612766907781095472e-2,
  1638. -0.73704168477258911962046591907690764416e-4,
  1639. +0.34087499397791555759285503797256103259e-5,
  1640. -0.11114024704296196166272091230695179724e-6,
  1641. +0.23987051614110848595909588343223896577e-8,
  1642. -0.29477341859111589208776402638429026517e-10,
  1643. +0.13222065991022301420255904060628100924e-12);
  1644. var
  1645. a : extended;
  1646. begin
  1647. a:=abs(x);
  1648. if a>0.5 then
  1649. result:=exp(x)-1
  1650. else if a<2e-19 then
  1651. result:=x
  1652. else
  1653. result:=x*extended(0.10281276702880859375e1)+x*(PolyEval(x,P)/PolyEval(x,Q));
  1654. end;
  1655. {$endif}
  1656. function power(base,exponent : float) : float;
  1657. begin
  1658. if Exponent=0.0 then
  1659. result:=1.0
  1660. else if (base=0.0) and (exponent>0.0) then
  1661. result:=0.0
  1662. else if (frac(exponent)=0.0) and (abs(exponent)<=maxint) then
  1663. result:=intpower(base,trunc(exponent))
  1664. else
  1665. result:=exp(exponent * ln (base));
  1666. end;
  1667. function intpower(base : float;exponent : longint) : float;
  1668. begin
  1669. if exponent<0 then
  1670. begin
  1671. base:=1.0/base;
  1672. exponent:=-exponent;
  1673. end;
  1674. intpower:=1.0;
  1675. while exponent<>0 do
  1676. begin
  1677. if exponent and 1<>0 then
  1678. intpower:=intpower*base;
  1679. exponent:=exponent shr 1;
  1680. base:=sqr(base);
  1681. end;
  1682. end;
  1683. operator ** (base,exponent : float) e: float; inline;
  1684. begin
  1685. e:=power(base,exponent);
  1686. end;
  1687. operator ** (base,exponent : int64) res: int64;
  1688. begin
  1689. if exponent<0 then
  1690. begin
  1691. if base<=0 then
  1692. raise EInvalidArgument.Create('Non-positive base with negative exponent in **');
  1693. if base=1 then
  1694. res:=1
  1695. else
  1696. res:=0;
  1697. exit;
  1698. end;
  1699. res:=1;
  1700. while exponent<>0 do
  1701. begin
  1702. if exponent and 1<>0 then
  1703. res:=res*base;
  1704. exponent:=exponent shr 1;
  1705. base:=base*base;
  1706. end;
  1707. end;
  1708. function ceil(x : float) : integer;
  1709. begin
  1710. Result:=Trunc(x)+ord(Frac(x)>0);
  1711. end;
  1712. function ceil64(x: float): Int64;
  1713. begin
  1714. Result:=Trunc(x)+ord(Frac(x)>0);
  1715. end;
  1716. function floor(x : float) : integer;
  1717. begin
  1718. Result:=Trunc(x)-ord(Frac(x)<0);
  1719. end;
  1720. function floor64(x: float): Int64;
  1721. begin
  1722. Result:=Trunc(x)-ord(Frac(x)<0);
  1723. end;
  1724. // Correction for "rounding to nearest, ties to even".
  1725. // RoundToNearestTieToEven(QWE.RTYUIOP) = QWE + TieToEven(ER, TYUIOP <> 0).
  1726. function TieToEven(AB: cardinal; somethingAfter: boolean): cardinal;
  1727. begin
  1728. result := AB and 1;
  1729. if (result <> 0) and not somethingAfter then
  1730. result := AB shr 1;
  1731. end;
  1732. {$ifdef FPC_HAS_TYPE_SINGLE}
  1733. procedure Frexp(X: single; out Mantissa: single; out Exponent: integer);
  1734. var
  1735. M: uint32;
  1736. E, ExtraE: int32;
  1737. begin
  1738. Mantissa := X;
  1739. E := TSingleRec(X).Exp;
  1740. if (E > 0) and (E < 2 * TSingleRec.Bias + 1) then
  1741. begin
  1742. // Normal.
  1743. TSingleRec(Mantissa).Exp := TSingleRec.Bias - 1;
  1744. Exponent := E - (TSingleRec.Bias - 1);
  1745. exit;
  1746. end;
  1747. if E = 0 then
  1748. begin
  1749. M := TSingleRec(X).Frac;
  1750. if M <> 0 then
  1751. begin
  1752. // Subnormal.
  1753. ExtraE := 23 - BsrDWord(M);
  1754. TSingleRec(Mantissa).Frac := M shl ExtraE; // "and (1 shl 23 - 1)" required to remove starting 1, but .SetFrac already does it.
  1755. TSingleRec(Mantissa).Exp := TSingleRec.Bias - 1;
  1756. Exponent := -TSingleRec.Bias + 2 - ExtraE;
  1757. exit;
  1758. end;
  1759. end;
  1760. // ±0, ±Inf, NaN.
  1761. Exponent := 0;
  1762. end;
  1763. function Ldexp(X: single; p: integer): single;
  1764. var
  1765. M, E: uint32;
  1766. xp, sh: integer;
  1767. begin
  1768. E := TSingleRec(X).Exp;
  1769. if (E = 0) and (TSingleRec(X).Frac = 0) or (E = 2 * TSingleRec.Bias + 1) then
  1770. // ±0, ±Inf, NaN.
  1771. exit(X);
  1772. Frexp(X, result, xp);
  1773. inc(xp, p);
  1774. if (xp >= -TSingleRec.Bias + 2) and (xp <= TSingleRec.Bias + 1) then
  1775. // Normalized.
  1776. TSingleRec(result).Exp := xp + (TSingleRec.Bias - 1)
  1777. else if xp > TSingleRec.Bias + 1 then
  1778. begin
  1779. // Overflow.
  1780. TSingleRec(result).Exp := 2 * TSingleRec.Bias + 1;
  1781. TSingleRec(result).Frac := 0;
  1782. end else
  1783. begin
  1784. TSingleRec(result).Exp := 0;
  1785. if xp >= -TSingleRec.Bias + 2 - 23 then
  1786. begin
  1787. // Denormalized.
  1788. M := TSingleRec(result).Frac or uint32(1) shl 23;
  1789. sh := -TSingleRec.Bias + 1 - xp;
  1790. TSingleRec(result).Frac := M shr (sh + 1) + TieToEven(M shr sh and 3, M and (uint32(1) shl sh - 1) <> 0);
  1791. end else
  1792. // Underflow.
  1793. TSingleRec(result).Frac := 0;
  1794. end;
  1795. end;
  1796. {$endif}
  1797. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1798. procedure Frexp(X: double; out Mantissa: double; out Exponent: integer);
  1799. var
  1800. M: uint64;
  1801. E, ExtraE: int32;
  1802. begin
  1803. Mantissa := X;
  1804. E := TDoubleRec(X).Exp;
  1805. if (E > 0) and (E < 2 * TDoubleRec.Bias + 1) then
  1806. begin
  1807. // Normal.
  1808. TDoubleRec(Mantissa).Exp := TDoubleRec.Bias - 1;
  1809. Exponent := E - (TDoubleRec.Bias - 1);
  1810. exit;
  1811. end;
  1812. if E = 0 then
  1813. begin
  1814. M := TDoubleRec(X).Frac;
  1815. if M <> 0 then
  1816. begin
  1817. // Subnormal.
  1818. ExtraE := 52 - BsrQWord(M);
  1819. TDoubleRec(Mantissa).Frac := M shl ExtraE; // "and (1 shl 52 - 1)" required to remove starting 1, but .SetFrac already does it.
  1820. TDoubleRec(Mantissa).Exp := TDoubleRec.Bias - 1;
  1821. Exponent := -TDoubleRec.Bias + 2 - ExtraE;
  1822. exit;
  1823. end;
  1824. end;
  1825. // ±0, ±Inf, NaN.
  1826. Exponent := 0;
  1827. end;
  1828. function Ldexp(X: double; p: integer): double;
  1829. var
  1830. M: uint64;
  1831. E: uint32;
  1832. xp, sh: integer;
  1833. begin
  1834. E := TDoubleRec(X).Exp;
  1835. if (E = 0) and (TDoubleRec(X).Frac = 0) or (E = 2 * TDoubleRec.Bias + 1) then
  1836. // ±0, ±Inf, NaN.
  1837. exit(X);
  1838. Frexp(X, result, xp);
  1839. inc(xp, p);
  1840. if (xp >= -TDoubleRec.Bias + 2) and (xp <= TDoubleRec.Bias + 1) then
  1841. // Normalized.
  1842. TDoubleRec(result).Exp := xp + (TDoubleRec.Bias - 1)
  1843. else if xp > TDoubleRec.Bias + 1 then
  1844. begin
  1845. // Overflow.
  1846. TDoubleRec(result).Exp := 2 * TDoubleRec.Bias + 1;
  1847. TDoubleRec(result).Frac := 0;
  1848. end else
  1849. begin
  1850. TDoubleRec(result).Exp := 0;
  1851. if xp >= -TDoubleRec.Bias + 2 - 52 then
  1852. begin
  1853. // Denormalized.
  1854. M := TDoubleRec(result).Frac or uint64(1) shl 52;
  1855. sh := -TSingleRec.Bias + 1 - xp;
  1856. TDoubleRec(result).Frac := M shr (sh + 1) + TieToEven(M shr sh and 3, M and (uint64(1) shl sh - 1) <> 0);
  1857. end else
  1858. // Underflow.
  1859. TDoubleRec(result).Frac := 0;
  1860. end;
  1861. end;
  1862. {$endif}
  1863. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1864. procedure Frexp(X: extended; out Mantissa: extended; out Exponent: integer);
  1865. var
  1866. M: uint64;
  1867. E, ExtraE: int32;
  1868. begin
  1869. Mantissa := X;
  1870. E := TExtended80Rec(X).Exp;
  1871. if (E > 0) and (E < 2 * TExtended80Rec.Bias + 1) then
  1872. begin
  1873. // Normal.
  1874. TExtended80Rec(Mantissa).Exp := TExtended80Rec.Bias - 1;
  1875. Exponent := E - (TExtended80Rec.Bias - 1);
  1876. exit;
  1877. end;
  1878. if E = 0 then
  1879. begin
  1880. M := TExtended80Rec(X).Frac;
  1881. if M <> 0 then
  1882. begin
  1883. // Subnormal. Extended has explicit starting 1.
  1884. ExtraE := 63 - BsrQWord(M);
  1885. TExtended80Rec(Mantissa).Frac := M shl ExtraE;
  1886. TExtended80Rec(Mantissa).Exp := TExtended80Rec.Bias - 1;
  1887. Exponent := -TExtended80Rec.Bias + 2 - ExtraE;
  1888. exit;
  1889. end;
  1890. end;
  1891. // ±0, ±Inf, NaN.
  1892. Exponent := 0;
  1893. end;
  1894. function Ldexp(X: extended; p: integer): extended;
  1895. var
  1896. M: uint64;
  1897. E: uint32;
  1898. xp, sh: integer;
  1899. begin
  1900. E := TExtended80Rec(X).Exp;
  1901. if (E = 0) and (TExtended80Rec(X).Frac = 0) or (E = 2 * TExtended80Rec.Bias + 1) then
  1902. // ±0, ±Inf, NaN.
  1903. exit(X);
  1904. Frexp(X, result, xp);
  1905. inc(xp, p);
  1906. if (xp >= -TExtended80Rec.Bias + 2) and (xp <= TExtended80Rec.Bias + 1) then
  1907. // Normalized.
  1908. TExtended80Rec(result).Exp := xp + (TExtended80Rec.Bias - 1)
  1909. else if xp > TExtended80Rec.Bias + 1 then
  1910. begin
  1911. // Overflow.
  1912. TExtended80Rec(result).Exp := 2 * TExtended80Rec.Bias + 1;
  1913. TExtended80Rec(result).Frac := uint64(1) shl 63;
  1914. end
  1915. else if xp >= -TExtended80Rec.Bias + 2 - 63 then
  1916. begin
  1917. // Denormalized... usually.
  1918. // Mantissa of subnormal 'extended' (Exp = 0) must always start with 0.
  1919. // If the calculated mantissa starts with 1, extended instead becomes normalized with Exp = 1.
  1920. M := TExtended80Rec(result).Frac;
  1921. sh := -TExtended80Rec.Bias + 1 - xp;
  1922. M := M shr (sh + 1) + TieToEven(M shr sh and 3, M and (uint64(1) shl sh - 1) <> 0);
  1923. TExtended80Rec(result).Exp := M shr 63;
  1924. TExtended80Rec(result).Frac := M;
  1925. end else
  1926. begin
  1927. // Underflow.
  1928. TExtended80Rec(result).Exp := 0;
  1929. TExtended80Rec(result).Frac := 0;
  1930. end;
  1931. end;
  1932. {$endif}
  1933. const
  1934. { Cutoff for https://en.wikipedia.org/wiki/Pairwise_summation; sums of at least this many elements are split in two halves. }
  1935. RecursiveSumThreshold=12;
  1936. {$ifdef FPC_HAS_TYPE_SINGLE}
  1937. function mean(const data : array of Single) : float;
  1938. begin
  1939. Result:=Mean(PSingle(@data[0]),High(Data)+1);
  1940. end;
  1941. function mean(const data : PSingle; Const N : longint) : float;
  1942. begin
  1943. mean:=sum(Data,N);
  1944. mean:=mean/N;
  1945. end;
  1946. function sum(const data : array of Single) : float;inline;
  1947. begin
  1948. Result:=Sum(PSingle(@Data[0]),High(Data)+1);
  1949. end;
  1950. function sum(const data : PSingle;Const N : longint) : float;
  1951. var
  1952. i : SizeInt;
  1953. begin
  1954. if N>=RecursiveSumThreshold then
  1955. result:=sum(data,longword(N) div 2)+sum(data+longword(N) div 2,N-longword(N) div 2)
  1956. else
  1957. begin
  1958. result:=0;
  1959. for i:=0 to N-1 do
  1960. result:=result+data[i];
  1961. end;
  1962. end;
  1963. {$endif FPC_HAS_TYPE_SINGLE}
  1964. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1965. function mean(const data : array of Double) : float; inline;
  1966. begin
  1967. Result:=Mean(PDouble(@data[0]),High(Data)+1);
  1968. end;
  1969. function mean(const data : PDouble; Const N : longint) : float;
  1970. begin
  1971. mean:=sum(Data,N);
  1972. mean:=mean/N;
  1973. end;
  1974. function sum(const data : array of Double) : float; inline;
  1975. begin
  1976. Result:=Sum(PDouble(@Data[0]),High(Data)+1);
  1977. end;
  1978. function sum(const data : PDouble;Const N : longint) : float;
  1979. var
  1980. i : SizeInt;
  1981. begin
  1982. if N>=RecursiveSumThreshold then
  1983. result:=sum(data,longword(N) div 2)+sum(data+longword(N) div 2,N-longword(N) div 2)
  1984. else
  1985. begin
  1986. result:=0;
  1987. for i:=0 to N-1 do
  1988. result:=result+data[i];
  1989. end;
  1990. end;
  1991. {$endif FPC_HAS_TYPE_DOUBLE}
  1992. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1993. function mean(const data : array of Extended) : float;
  1994. begin
  1995. Result:=Mean(PExtended(@data[0]),High(Data)+1);
  1996. end;
  1997. function mean(const data : PExtended; Const N : longint) : float;
  1998. begin
  1999. mean:=sum(Data,N);
  2000. mean:=mean/N;
  2001. end;
  2002. function sum(const data : array of Extended) : float; inline;
  2003. begin
  2004. Result:=Sum(PExtended(@Data[0]),High(Data)+1);
  2005. end;
  2006. function sum(const data : PExtended;Const N : longint) : float;
  2007. var
  2008. i : SizeInt;
  2009. begin
  2010. if N>=RecursiveSumThreshold then
  2011. result:=sum(data,longword(N) div 2)+sum(data+longword(N) div 2,N-longword(N) div 2)
  2012. else
  2013. begin
  2014. result:=0;
  2015. for i:=0 to N-1 do
  2016. result:=result+data[i];
  2017. end;
  2018. end;
  2019. {$endif FPC_HAS_TYPE_EXTENDED}
  2020. function sumInt(const data : PInt64;Const N : longint) : Int64;
  2021. var
  2022. i : SizeInt;
  2023. begin
  2024. sumInt:=0;
  2025. for i:=0 to N-1 do
  2026. sumInt:=sumInt+data[i];
  2027. end;
  2028. function sumInt(const data : array of Int64) : Int64; inline;
  2029. begin
  2030. Result:=SumInt(PInt64(@Data[0]),High(Data)+1);
  2031. end;
  2032. function mean(const data : PInt64; const N : Longint):Float;
  2033. begin
  2034. mean:=sumInt(Data,N);
  2035. mean:=mean/N;
  2036. end;
  2037. function mean(const data: array of Int64):Float;
  2038. begin
  2039. mean:=mean(PInt64(@data[0]),High(Data)+1);
  2040. end;
  2041. function sumInt(const data : PInteger; Const N : longint) : Int64;
  2042. var
  2043. i : SizeInt;
  2044. begin
  2045. sumInt:=0;
  2046. for i:=0 to N-1 do
  2047. sumInt:=sumInt+data[i];
  2048. end;
  2049. function sumInt(const data : array of Integer) : Int64;inline;
  2050. begin
  2051. Result:=sumInt(PInteger(@Data[0]),High(Data)+1);
  2052. end;
  2053. function mean(const data : PInteger; const N : Longint):Float;
  2054. begin
  2055. mean:=sumInt(Data,N);
  2056. mean:=mean/N;
  2057. end;
  2058. function mean(const data: array of Integer):Float;
  2059. begin
  2060. mean:=mean(PInteger(@data[0]),High(Data)+1);
  2061. end;
  2062. {$ifdef FPC_HAS_TYPE_SINGLE}
  2063. function sumofsquares(const data : array of Single) : float; inline;
  2064. begin
  2065. Result:=sumofsquares(PSingle(@data[0]),High(Data)+1);
  2066. end;
  2067. function sumofsquares(const data : PSingle; Const N : Integer) : float;
  2068. var
  2069. i : SizeInt;
  2070. begin
  2071. if N>=RecursiveSumThreshold then
  2072. result:=sumofsquares(data,cardinal(N) div 2)+sumofsquares(data+cardinal(N) div 2,N-cardinal(N) div 2)
  2073. else
  2074. begin
  2075. result:=0;
  2076. for i:=0 to N-1 do
  2077. result:=result+sqr(data[i]);
  2078. end;
  2079. end;
  2080. procedure sumsandsquares(const data : array of Single;
  2081. var sum,sumofsquares : float); inline;
  2082. begin
  2083. sumsandsquares (PSingle(@Data[0]),High(Data)+1,Sum,sumofsquares);
  2084. end;
  2085. procedure sumsandsquares(const data : PSingle; Const N : Integer;
  2086. var sum,sumofsquares : float);
  2087. var
  2088. i : SizeInt;
  2089. temp,tsum,tsumofsquares,sum0,sumofsquares0,sum1,sumofsquares1 : float;
  2090. begin
  2091. if N>=RecursiveSumThreshold then
  2092. begin
  2093. sumsandsquares(data,cardinal(N) div 2,sum0,sumofsquares0);
  2094. sumsandsquares(data+cardinal(N) div 2,N-cardinal(N) div 2,sum1,sumofsquares1);
  2095. sum:=sum0+sum1;
  2096. sumofsquares:=sumofsquares0+sumofsquares1;
  2097. end
  2098. else
  2099. begin
  2100. tsum:=0;
  2101. tsumofsquares:=0;
  2102. for i:=0 to N-1 do
  2103. begin
  2104. temp:=data[i];
  2105. tsum:=tsum+temp;
  2106. tsumofsquares:=tsumofsquares+sqr(temp);
  2107. end;
  2108. sum:=tsum;
  2109. sumofsquares:=tsumofsquares;
  2110. end;
  2111. end;
  2112. {$endif FPC_HAS_TYPE_SINGLE}
  2113. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2114. function sumofsquares(const data : array of Double) : float; inline;
  2115. begin
  2116. Result:=sumofsquares(PDouble(@data[0]),High(Data)+1);
  2117. end;
  2118. function sumofsquares(const data : PDouble; Const N : Integer) : float;
  2119. var
  2120. i : SizeInt;
  2121. begin
  2122. if N>=RecursiveSumThreshold then
  2123. result:=sumofsquares(data,cardinal(N) div 2)+sumofsquares(data+cardinal(N) div 2,N-cardinal(N) div 2)
  2124. else
  2125. begin
  2126. result:=0;
  2127. for i:=0 to N-1 do
  2128. result:=result+sqr(data[i]);
  2129. end;
  2130. end;
  2131. procedure sumsandsquares(const data : array of Double;
  2132. var sum,sumofsquares : float); inline;
  2133. begin
  2134. sumsandsquares (PDouble(@Data[0]),High(Data)+1,Sum,sumofsquares);
  2135. end;
  2136. procedure sumsandsquares(const data : PDouble; Const N : Integer;
  2137. var sum,sumofsquares : float);
  2138. var
  2139. i : SizeInt;
  2140. temp,tsum,tsumofsquares,sum0,sumofsquares0,sum1,sumofsquares1 : float;
  2141. begin
  2142. if N>=RecursiveSumThreshold then
  2143. begin
  2144. sumsandsquares(data,cardinal(N) div 2,sum0,sumofsquares0);
  2145. sumsandsquares(data+cardinal(N) div 2,N-cardinal(N) div 2,sum1,sumofsquares1);
  2146. sum:=sum0+sum1;
  2147. sumofsquares:=sumofsquares0+sumofsquares1;
  2148. end
  2149. else
  2150. begin
  2151. tsum:=0;
  2152. tsumofsquares:=0;
  2153. for i:=0 to N-1 do
  2154. begin
  2155. temp:=data[i];
  2156. tsum:=tsum+temp;
  2157. tsumofsquares:=tsumofsquares+sqr(temp);
  2158. end;
  2159. sum:=tsum;
  2160. sumofsquares:=tsumofsquares;
  2161. end;
  2162. end;
  2163. {$endif FPC_HAS_TYPE_DOUBLE}
  2164. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2165. function sumofsquares(const data : array of Extended) : float; inline;
  2166. begin
  2167. Result:=sumofsquares(PExtended(@data[0]),High(Data)+1);
  2168. end;
  2169. function sumofsquares(const data : PExtended; Const N : Integer) : float;
  2170. var
  2171. i : SizeInt;
  2172. begin
  2173. if N>=RecursiveSumThreshold then
  2174. result:=sumofsquares(data,cardinal(N) div 2)+sumofsquares(data+cardinal(N) div 2,N-cardinal(N) div 2)
  2175. else
  2176. begin
  2177. result:=0;
  2178. for i:=0 to N-1 do
  2179. result:=result+sqr(data[i]);
  2180. end;
  2181. end;
  2182. procedure sumsandsquares(const data : array of Extended;
  2183. var sum,sumofsquares : float); inline;
  2184. begin
  2185. sumsandsquares (PExtended(@Data[0]),High(Data)+1,Sum,sumofsquares);
  2186. end;
  2187. procedure sumsandsquares(const data : PExtended; Const N : Integer;
  2188. var sum,sumofsquares : float);
  2189. var
  2190. i : SizeInt;
  2191. temp,tsum,tsumofsquares,sum0,sumofsquares0,sum1,sumofsquares1 : float;
  2192. begin
  2193. if N>=RecursiveSumThreshold then
  2194. begin
  2195. sumsandsquares(data,cardinal(N) div 2,sum0,sumofsquares0);
  2196. sumsandsquares(data+cardinal(N) div 2,N-cardinal(N) div 2,sum1,sumofsquares1);
  2197. sum:=sum0+sum1;
  2198. sumofsquares:=sumofsquares0+sumofsquares1;
  2199. end
  2200. else
  2201. begin
  2202. tsum:=0;
  2203. tsumofsquares:=0;
  2204. for i:=0 to N-1 do
  2205. begin
  2206. temp:=data[i];
  2207. tsum:=tsum+temp;
  2208. tsumofsquares:=tsumofsquares+sqr(temp);
  2209. end;
  2210. sum:=tsum;
  2211. sumofsquares:=tsumofsquares;
  2212. end;
  2213. end;
  2214. {$endif FPC_HAS_TYPE_EXTENDED}
  2215. function randg(mean,stddev : float) : float;
  2216. Var U1,S2 : Float;
  2217. begin
  2218. repeat
  2219. u1:= 2*random-1;
  2220. S2:=Sqr(U1)+sqr(2*random-1);
  2221. until s2<1;
  2222. randg:=Sqrt(-2*ln(S2)/S2)*u1*stddev+Mean;
  2223. end;
  2224. function RandomRange(const aFrom, aTo: Integer): Integer;
  2225. begin
  2226. Result:=Random(Abs(aFrom-aTo))+Min(aTo,AFrom);
  2227. end;
  2228. function RandomRange(const aFrom, aTo: Int64): Int64;
  2229. begin
  2230. Result:=Random(Abs(aFrom-aTo))+Min(aTo,AFrom);
  2231. end;
  2232. {$ifdef FPC_HAS_TYPE_SINGLE}
  2233. procedure MeanAndTotalVariance
  2234. (const data: PSingle; N: LongInt; var mu, variance: float);
  2235. function CalcVariance(data: PSingle; N: SizeInt; mu: float): float;
  2236. var
  2237. i: SizeInt;
  2238. begin
  2239. if N>=RecursiveSumThreshold then
  2240. result:=CalcVariance(data,SizeUint(N) div 2,mu)+CalcVariance(data+SizeUint(N) div 2,N-SizeUint(N) div 2,mu)
  2241. else
  2242. begin
  2243. result:=0;
  2244. for i:=0 to N-1 do
  2245. result:=result+Sqr(data[i]-mu);
  2246. end;
  2247. end;
  2248. begin
  2249. mu := Mean( data, N );
  2250. variance := CalcVariance( data, N, mu );
  2251. end;
  2252. function stddev(const data : array of Single) : float; inline;
  2253. begin
  2254. Result:=Stddev(PSingle(@Data[0]),High(Data)+1);
  2255. end;
  2256. function stddev(const data : PSingle; Const N : Integer) : float;
  2257. begin
  2258. StdDev:=Sqrt(Variance(Data,N));
  2259. end;
  2260. procedure meanandstddev(const data : array of Single;
  2261. var mean,stddev : float); inline;
  2262. begin
  2263. Meanandstddev(PSingle(@Data[0]),High(Data)+1,Mean,stddev);
  2264. end;
  2265. procedure meanandstddev
  2266. ( const data: PSingle;
  2267. const N: Longint;
  2268. var mean,
  2269. stdDev: Float
  2270. );
  2271. var totalVariance: float;
  2272. begin
  2273. MeanAndTotalVariance( data, N, mean, totalVariance );
  2274. if N < 2 then stdDev := 0
  2275. else stdDev := Sqrt( totalVariance / ( N - 1 ) );
  2276. end;
  2277. function variance(const data : array of Single) : float; inline;
  2278. begin
  2279. Variance:=Variance(PSingle(@Data[0]),High(Data)+1);
  2280. end;
  2281. function variance(const data : PSingle; Const N : Integer) : float;
  2282. begin
  2283. If N=1 then
  2284. Result:=0
  2285. else
  2286. Result:=TotalVariance(Data,N)/(N-1);
  2287. end;
  2288. function totalvariance(const data : array of Single) : float; inline;
  2289. begin
  2290. Result:=TotalVariance(PSingle(@Data[0]),High(Data)+1);
  2291. end;
  2292. function totalvariance(const data : PSingle; const N : Integer) : float;
  2293. var mu: float;
  2294. begin
  2295. MeanAndTotalVariance( data, N, mu, result );
  2296. end;
  2297. function popnstddev(const data : array of Single) : float;
  2298. begin
  2299. PopnStdDev:=Sqrt(PopnVariance(PSingle(@Data[0]),High(Data)+1));
  2300. end;
  2301. function popnstddev(const data : PSingle; Const N : Integer) : float;
  2302. begin
  2303. PopnStdDev:=Sqrt(PopnVariance(Data,N));
  2304. end;
  2305. function popnvariance(const data : array of Single) : float; inline;
  2306. begin
  2307. popnvariance:=popnvariance(PSingle(@data[0]),high(Data)+1);
  2308. end;
  2309. function popnvariance(const data : PSingle; Const N : Integer) : float;
  2310. begin
  2311. PopnVariance:=TotalVariance(Data,N)/N;
  2312. end;
  2313. procedure momentskewkurtosis(const data : array of single;
  2314. out m1,m2,m3,m4,skew,kurtosis : float); inline;
  2315. begin
  2316. momentskewkurtosis(PSingle(@Data[0]),High(Data)+1,m1,m2,m3,m4,skew,kurtosis);
  2317. end;
  2318. type
  2319. TMoments2to4 = array[2 .. 4] of float;
  2320. procedure momentskewkurtosis(
  2321. const data: pSingle;
  2322. Const N: integer;
  2323. out m1: float;
  2324. out m2: float;
  2325. out m3: float;
  2326. out m4: float;
  2327. out skew: float;
  2328. out kurtosis: float
  2329. );
  2330. procedure CalcDevSums2to4(data: PSingle; N: SizeInt; m1: float; out m2to4: TMoments2to4);
  2331. var
  2332. tm2, tm3, tm4, dev, dev2: float;
  2333. i: SizeInt;
  2334. m2to4Part0, m2to4Part1: TMoments2to4;
  2335. begin
  2336. if N >= RecursiveSumThreshold then
  2337. begin
  2338. CalcDevSums2to4(data, SizeUint(N) div 2, m1, m2to4Part0);
  2339. CalcDevSums2to4(data + SizeUint(N) div 2, N - SizeUint(N) div 2, m1, m2to4Part1);
  2340. for i := Low(TMoments2to4) to High(TMoments2to4) do
  2341. m2to4[i] := m2to4Part0[i] + m2to4Part1[i];
  2342. end
  2343. else
  2344. begin
  2345. tm2 := 0;
  2346. tm3 := 0;
  2347. tm4 := 0;
  2348. for i := 0 to N - 1 do
  2349. begin
  2350. dev := data[i] - m1;
  2351. dev2 := sqr(dev);
  2352. tm2 := tm2 + dev2;
  2353. tm3 := tm3 + dev2 * dev;
  2354. tm4 := tm4 + sqr(dev2);
  2355. end;
  2356. m2to4[2] := tm2;
  2357. m2to4[3] := tm3;
  2358. m2to4[4] := tm4;
  2359. end;
  2360. end;
  2361. var
  2362. reciprocalN: float;
  2363. m2to4: TMoments2to4;
  2364. begin
  2365. m1 := 0;
  2366. reciprocalN := 1/N;
  2367. m1 := reciprocalN * sum(data, N);
  2368. CalcDevSums2to4(data, N, m1, m2to4);
  2369. m2 := reciprocalN * m2to4[2];
  2370. m3 := reciprocalN * m2to4[3];
  2371. m4 := reciprocalN * m2to4[4];
  2372. skew := m3 / (sqrt(m2)*m2);
  2373. kurtosis := m4 / (m2 * m2);
  2374. end;
  2375. function norm(const data : array of Single) : float; inline;
  2376. begin
  2377. norm:=Norm(PSingle(@data[0]),High(Data)+1);
  2378. end;
  2379. function norm(const data : PSingle; Const N : Integer) : float;
  2380. begin
  2381. norm:=sqrt(sumofsquares(data,N));
  2382. end;
  2383. {$endif FPC_HAS_TYPE_SINGLE}
  2384. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2385. procedure MeanAndTotalVariance
  2386. (const data: PDouble; N: LongInt; var mu, variance: float);
  2387. function CalcVariance(data: PDouble; N: SizeInt; mu: float): float;
  2388. var
  2389. i: SizeInt;
  2390. begin
  2391. if N>=RecursiveSumThreshold then
  2392. result:=CalcVariance(data,SizeUint(N) div 2,mu)+CalcVariance(data+SizeUint(N) div 2,N-SizeUint(N) div 2,mu)
  2393. else
  2394. begin
  2395. result:=0;
  2396. for i:=0 to N-1 do
  2397. result:=result+Sqr(data[i]-mu);
  2398. end;
  2399. end;
  2400. begin
  2401. mu := Mean( data, N );
  2402. variance := CalcVariance( data, N, mu );
  2403. end;
  2404. function stddev(const data : array of Double) : float; inline;
  2405. begin
  2406. Result:=Stddev(PDouble(@Data[0]),High(Data)+1)
  2407. end;
  2408. function stddev(const data : PDouble; Const N : Integer) : float;
  2409. begin
  2410. StdDev:=Sqrt(Variance(Data,N));
  2411. end;
  2412. procedure meanandstddev(const data : array of Double;
  2413. var mean,stddev : float);
  2414. begin
  2415. Meanandstddev(PDouble(@Data[0]),High(Data)+1,Mean,stddev);
  2416. end;
  2417. procedure meanandstddev
  2418. ( const data: PDouble;
  2419. const N: Longint;
  2420. var mean,
  2421. stdDev: Float
  2422. );
  2423. var totalVariance: float;
  2424. begin
  2425. MeanAndTotalVariance( data, N, mean, totalVariance );
  2426. if N < 2 then stdDev := 0
  2427. else stdDev := Sqrt( totalVariance / ( N - 1 ) );
  2428. end;
  2429. function variance(const data : array of Double) : float; inline;
  2430. begin
  2431. Variance:=Variance(PDouble(@Data[0]),High(Data)+1);
  2432. end;
  2433. function variance(const data : PDouble; Const N : Integer) : float;
  2434. begin
  2435. If N=1 then
  2436. Result:=0
  2437. else
  2438. Result:=TotalVariance(Data,N)/(N-1);
  2439. end;
  2440. function totalvariance(const data : array of Double) : float; inline;
  2441. begin
  2442. Result:=TotalVariance(PDouble(@Data[0]),High(Data)+1);
  2443. end;
  2444. function totalvariance(const data : PDouble; const N : Integer) : float;
  2445. var mu: float;
  2446. begin
  2447. MeanAndTotalVariance( data, N, mu, result );
  2448. end;
  2449. function popnstddev(const data : array of Double) : float;
  2450. begin
  2451. PopnStdDev:=Sqrt(PopnVariance(PDouble(@Data[0]),High(Data)+1));
  2452. end;
  2453. function popnstddev(const data : PDouble; Const N : Integer) : float;
  2454. begin
  2455. PopnStdDev:=Sqrt(PopnVariance(Data,N));
  2456. end;
  2457. function popnvariance(const data : array of Double) : float; inline;
  2458. begin
  2459. popnvariance:=popnvariance(PDouble(@data[0]),high(Data)+1);
  2460. end;
  2461. function popnvariance(const data : PDouble; Const N : Integer) : float;
  2462. begin
  2463. PopnVariance:=TotalVariance(Data,N)/N;
  2464. end;
  2465. procedure momentskewkurtosis(const data : array of Double;
  2466. out m1,m2,m3,m4,skew,kurtosis : float);
  2467. begin
  2468. momentskewkurtosis(PDouble(@Data[0]),High(Data)+1,m1,m2,m3,m4,skew,kurtosis);
  2469. end;
  2470. procedure momentskewkurtosis(
  2471. const data: pdouble;
  2472. Const N: integer;
  2473. out m1: float;
  2474. out m2: float;
  2475. out m3: float;
  2476. out m4: float;
  2477. out skew: float;
  2478. out kurtosis: float
  2479. );
  2480. procedure CalcDevSums2to4(data: PDouble; N: SizeInt; m1: float; out m2to4: TMoments2to4);
  2481. var
  2482. tm2, tm3, tm4, dev, dev2: float;
  2483. i: SizeInt;
  2484. m2to4Part0, m2to4Part1: TMoments2to4;
  2485. begin
  2486. if N >= RecursiveSumThreshold then
  2487. begin
  2488. CalcDevSums2to4(data, SizeUint(N) div 2, m1, m2to4Part0);
  2489. CalcDevSums2to4(data + SizeUint(N) div 2, N - SizeUint(N) div 2, m1, m2to4Part1);
  2490. for i := Low(TMoments2to4) to High(TMoments2to4) do
  2491. m2to4[i] := m2to4Part0[i] + m2to4Part1[i];
  2492. end
  2493. else
  2494. begin
  2495. tm2 := 0;
  2496. tm3 := 0;
  2497. tm4 := 0;
  2498. for i := 0 to N - 1 do
  2499. begin
  2500. dev := data[i] - m1;
  2501. dev2 := sqr(dev);
  2502. tm2 := tm2 + dev2;
  2503. tm3 := tm3 + dev2 * dev;
  2504. tm4 := tm4 + sqr(dev2);
  2505. end;
  2506. m2to4[2] := tm2;
  2507. m2to4[3] := tm3;
  2508. m2to4[4] := tm4;
  2509. end;
  2510. end;
  2511. var
  2512. reciprocalN: float;
  2513. m2to4: TMoments2to4;
  2514. begin
  2515. m1 := 0;
  2516. reciprocalN := 1/N;
  2517. m1 := reciprocalN * sum(data, N);
  2518. CalcDevSums2to4(data, N, m1, m2to4);
  2519. m2 := reciprocalN * m2to4[2];
  2520. m3 := reciprocalN * m2to4[3];
  2521. m4 := reciprocalN * m2to4[4];
  2522. skew := m3 / (sqrt(m2)*m2);
  2523. kurtosis := m4 / (m2 * m2);
  2524. end;
  2525. function norm(const data : array of Double) : float; inline;
  2526. begin
  2527. norm:=Norm(PDouble(@data[0]),High(Data)+1);
  2528. end;
  2529. function norm(const data : PDouble; Const N : Integer) : float;
  2530. begin
  2531. norm:=sqrt(sumofsquares(data,N));
  2532. end;
  2533. {$endif FPC_HAS_TYPE_DOUBLE}
  2534. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2535. procedure MeanAndTotalVariance
  2536. (const data: PExtended; N: LongInt; var mu, variance: float);
  2537. function CalcVariance(data: PExtended; N: SizeInt; mu: float): float;
  2538. var
  2539. i: SizeInt;
  2540. begin
  2541. if N>=RecursiveSumThreshold then
  2542. result:=CalcVariance(data,SizeUint(N) div 2,mu)+CalcVariance(data+SizeUint(N) div 2,N-SizeUint(N) div 2,mu)
  2543. else
  2544. begin
  2545. result:=0;
  2546. for i:=0 to N-1 do
  2547. result:=result+Sqr(data[i]-mu);
  2548. end;
  2549. end;
  2550. begin
  2551. mu := Mean( data, N );
  2552. variance := CalcVariance( data, N, mu );
  2553. end;
  2554. function stddev(const data : array of Extended) : float; inline;
  2555. begin
  2556. Result:=Stddev(PExtended(@Data[0]),High(Data)+1)
  2557. end;
  2558. function stddev(const data : PExtended; Const N : Integer) : float;
  2559. begin
  2560. StdDev:=Sqrt(Variance(Data,N));
  2561. end;
  2562. procedure meanandstddev(const data : array of Extended;
  2563. var mean,stddev : float); inline;
  2564. begin
  2565. Meanandstddev(PExtended(@Data[0]),High(Data)+1,Mean,stddev);
  2566. end;
  2567. procedure meanandstddev
  2568. ( const data: PExtended;
  2569. const N: Longint;
  2570. var mean,
  2571. stdDev: Float
  2572. );
  2573. var totalVariance: float;
  2574. begin
  2575. MeanAndTotalVariance( data, N, mean, totalVariance );
  2576. if N < 2 then stdDev := 0
  2577. else stdDev := Sqrt( totalVariance / ( N - 1 ) );
  2578. end;
  2579. function variance(const data : array of Extended) : float; inline;
  2580. begin
  2581. Variance:=Variance(PExtended(@Data[0]),High(Data)+1);
  2582. end;
  2583. function variance(const data : PExtended; Const N : Integer) : float;
  2584. begin
  2585. If N=1 then
  2586. Result:=0
  2587. else
  2588. Result:=TotalVariance(Data,N)/(N-1);
  2589. end;
  2590. function totalvariance(const data : array of Extended) : float; inline;
  2591. begin
  2592. Result:=TotalVariance(PExtended(@Data[0]),High(Data)+1);
  2593. end;
  2594. function totalvariance(const data : PExtended;Const N : Integer) : float;
  2595. var mu: float;
  2596. begin
  2597. MeanAndTotalVariance( data, N, mu, result );
  2598. end;
  2599. function popnstddev(const data : array of Extended) : float;
  2600. begin
  2601. PopnStdDev:=Sqrt(PopnVariance(PExtended(@Data[0]),High(Data)+1));
  2602. end;
  2603. function popnstddev(const data : PExtended; Const N : Integer) : float;
  2604. begin
  2605. PopnStdDev:=Sqrt(PopnVariance(Data,N));
  2606. end;
  2607. function popnvariance(const data : array of Extended) : float; inline;
  2608. begin
  2609. popnvariance:=popnvariance(PExtended(@data[0]),high(Data)+1);
  2610. end;
  2611. function popnvariance(const data : PExtended; Const N : Integer) : float;
  2612. begin
  2613. PopnVariance:=TotalVariance(Data,N)/N;
  2614. end;
  2615. procedure momentskewkurtosis(const data : array of Extended;
  2616. out m1,m2,m3,m4,skew,kurtosis : float); inline;
  2617. begin
  2618. momentskewkurtosis(PExtended(@Data[0]),High(Data)+1,m1,m2,m3,m4,skew,kurtosis);
  2619. end;
  2620. procedure momentskewkurtosis(
  2621. const data: pExtended;
  2622. Const N: Integer;
  2623. out m1: float;
  2624. out m2: float;
  2625. out m3: float;
  2626. out m4: float;
  2627. out skew: float;
  2628. out kurtosis: float
  2629. );
  2630. procedure CalcDevSums2to4(data: PExtended; N: SizeInt; m1: float; out m2to4: TMoments2to4);
  2631. var
  2632. tm2, tm3, tm4, dev, dev2: float;
  2633. i: SizeInt;
  2634. m2to4Part0, m2to4Part1: TMoments2to4;
  2635. begin
  2636. if N >= RecursiveSumThreshold then
  2637. begin
  2638. CalcDevSums2to4(data, SizeUint(N) div 2, m1, m2to4Part0);
  2639. CalcDevSums2to4(data + SizeUint(N) div 2, N - SizeUint(N) div 2, m1, m2to4Part1);
  2640. for i := Low(TMoments2to4) to High(TMoments2to4) do
  2641. m2to4[i] := m2to4Part0[i] + m2to4Part1[i];
  2642. end
  2643. else
  2644. begin
  2645. tm2 := 0;
  2646. tm3 := 0;
  2647. tm4 := 0;
  2648. for i := 0 to N - 1 do
  2649. begin
  2650. dev := data[i] - m1;
  2651. dev2 := sqr(dev);
  2652. tm2 := tm2 + dev2;
  2653. tm3 := tm3 + dev2 * dev;
  2654. tm4 := tm4 + sqr(dev2);
  2655. end;
  2656. m2to4[2] := tm2;
  2657. m2to4[3] := tm3;
  2658. m2to4[4] := tm4;
  2659. end;
  2660. end;
  2661. var
  2662. reciprocalN: float;
  2663. m2to4: TMoments2to4;
  2664. begin
  2665. m1 := 0;
  2666. reciprocalN := 1/N;
  2667. m1 := reciprocalN * sum(data, N);
  2668. CalcDevSums2to4(data, N, m1, m2to4);
  2669. m2 := reciprocalN * m2to4[2];
  2670. m3 := reciprocalN * m2to4[3];
  2671. m4 := reciprocalN * m2to4[4];
  2672. skew := m3 / (sqrt(m2)*m2);
  2673. kurtosis := m4 / (m2 * m2);
  2674. end;
  2675. function norm(const data : array of Extended) : float; inline;
  2676. begin
  2677. norm:=Norm(PExtended(@data[0]),High(Data)+1);
  2678. end;
  2679. function norm(const data : PExtended; Const N : Integer) : float;
  2680. begin
  2681. norm:=sqrt(sumofsquares(data,N));
  2682. end;
  2683. {$endif FPC_HAS_TYPE_EXTENDED}
  2684. function MinIntValue(const Data: array of Integer): Integer;
  2685. var
  2686. I: SizeInt;
  2687. begin
  2688. Result := Data[Low(Data)];
  2689. For I := Succ(Low(Data)) To High(Data) Do
  2690. If Data[I] < Result Then Result := Data[I];
  2691. end;
  2692. function MaxIntValue(const Data: array of Integer): Integer;
  2693. var
  2694. I: SizeInt;
  2695. begin
  2696. Result := Data[Low(Data)];
  2697. For I := Succ(Low(Data)) To High(Data) Do
  2698. If Data[I] > Result Then Result := Data[I];
  2699. end;
  2700. function MinValue(const Data: array of Integer): Integer; inline;
  2701. begin
  2702. Result:=MinValue(Pinteger(@Data[0]),High(Data)+1)
  2703. end;
  2704. function MinValue(const Data: PInteger; Const N : Integer): Integer;
  2705. var
  2706. I: SizeInt;
  2707. begin
  2708. Result := Data[0];
  2709. For I := 1 To N-1 do
  2710. If Data[I] < Result Then Result := Data[I];
  2711. end;
  2712. function MaxValue(const Data: array of Integer): Integer; inline;
  2713. begin
  2714. Result:=MaxValue(PInteger(@Data[0]),High(Data)+1)
  2715. end;
  2716. function maxvalue(const data : PInteger; Const N : Integer) : Integer;
  2717. var
  2718. i : SizeInt;
  2719. begin
  2720. { get an initial value }
  2721. maxvalue:=data[0];
  2722. for i:=1 to N-1 do
  2723. if data[i]>maxvalue then
  2724. maxvalue:=data[i];
  2725. end;
  2726. {$ifdef FPC_HAS_TYPE_SINGLE}
  2727. function minvalue(const data : array of Single) : Single; inline;
  2728. begin
  2729. Result:=minvalue(PSingle(@data[0]),High(Data)+1);
  2730. end;
  2731. function minvalue(const data : PSingle; Const N : Integer) : Single;
  2732. var
  2733. i : SizeInt;
  2734. begin
  2735. { get an initial value }
  2736. minvalue:=data[0];
  2737. for i:=1 to N-1 do
  2738. if data[i]<minvalue then
  2739. minvalue:=data[i];
  2740. end;
  2741. function maxvalue(const data : array of Single) : Single; inline;
  2742. begin
  2743. Result:=maxvalue(PSingle(@data[0]),High(Data)+1);
  2744. end;
  2745. function maxvalue(const data : PSingle; Const N : Integer) : Single;
  2746. var
  2747. i : SizeInt;
  2748. begin
  2749. { get an initial value }
  2750. maxvalue:=data[0];
  2751. for i:=1 to N-1 do
  2752. if data[i]>maxvalue then
  2753. maxvalue:=data[i];
  2754. end;
  2755. {$endif FPC_HAS_TYPE_SINGLE}
  2756. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2757. function minvalue(const data : array of Double) : Double; inline;
  2758. begin
  2759. Result:=minvalue(PDouble(@data[0]),High(Data)+1);
  2760. end;
  2761. function minvalue(const data : PDouble; Const N : Integer) : Double;
  2762. var
  2763. i : SizeInt;
  2764. begin
  2765. { get an initial value }
  2766. minvalue:=data[0];
  2767. for i:=1 to N-1 do
  2768. if data[i]<minvalue then
  2769. minvalue:=data[i];
  2770. end;
  2771. function maxvalue(const data : array of Double) : Double; inline;
  2772. begin
  2773. Result:=maxvalue(PDouble(@data[0]),High(Data)+1);
  2774. end;
  2775. function maxvalue(const data : PDouble; Const N : Integer) : Double;
  2776. var
  2777. i : SizeInt;
  2778. begin
  2779. { get an initial value }
  2780. maxvalue:=data[0];
  2781. for i:=1 to N-1 do
  2782. if data[i]>maxvalue then
  2783. maxvalue:=data[i];
  2784. end;
  2785. {$endif FPC_HAS_TYPE_DOUBLE}
  2786. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2787. function minvalue(const data : array of Extended) : Extended; inline;
  2788. begin
  2789. Result:=minvalue(PExtended(@data[0]),High(Data)+1);
  2790. end;
  2791. function minvalue(const data : PExtended; Const N : Integer) : Extended;
  2792. var
  2793. i : SizeInt;
  2794. begin
  2795. { get an initial value }
  2796. minvalue:=data[0];
  2797. for i:=1 to N-1 do
  2798. if data[i]<minvalue then
  2799. minvalue:=data[i];
  2800. end;
  2801. function maxvalue(const data : array of Extended) : Extended; inline;
  2802. begin
  2803. Result:=maxvalue(PExtended(@data[0]),High(Data)+1);
  2804. end;
  2805. function maxvalue(const data : PExtended; Const N : Integer) : Extended;
  2806. var
  2807. i : SizeInt;
  2808. begin
  2809. { get an initial value }
  2810. maxvalue:=data[0];
  2811. for i:=1 to N-1 do
  2812. if data[i]>maxvalue then
  2813. maxvalue:=data[i];
  2814. end;
  2815. {$endif FPC_HAS_TYPE_EXTENDED}
  2816. function Min(a, b: Integer): Integer;inline;
  2817. begin
  2818. if a < b then
  2819. Result := a
  2820. else
  2821. Result := b;
  2822. end;
  2823. function Max(a, b: Integer): Integer;inline;
  2824. begin
  2825. if a > b then
  2826. Result := a
  2827. else
  2828. Result := b;
  2829. end;
  2830. {
  2831. function Min(a, b: Cardinal): Cardinal;inline;
  2832. begin
  2833. if a < b then
  2834. Result := a
  2835. else
  2836. Result := b;
  2837. end;
  2838. function Max(a, b: Cardinal): Cardinal;inline;
  2839. begin
  2840. if a > b then
  2841. Result := a
  2842. else
  2843. Result := b;
  2844. end;
  2845. }
  2846. function Min(a, b: Int64): Int64;inline;
  2847. begin
  2848. if a < b then
  2849. Result := a
  2850. else
  2851. Result := b;
  2852. end;
  2853. function Max(a, b: Int64): Int64;inline;
  2854. begin
  2855. if a > b then
  2856. Result := a
  2857. else
  2858. Result := b;
  2859. end;
  2860. function Min(a, b: QWord): QWord; inline;
  2861. begin
  2862. if a < b then
  2863. Result := a
  2864. else
  2865. Result := b;
  2866. end;
  2867. function Max(a, b: QWord): Qword;inline;
  2868. begin
  2869. if a > b then
  2870. Result := a
  2871. else
  2872. Result := b;
  2873. end;
  2874. {$ifdef FPC_HAS_TYPE_SINGLE}
  2875. function Min(a, b: Single): Single;inline;
  2876. begin
  2877. if a < b then
  2878. Result := a
  2879. else
  2880. Result := b;
  2881. end;
  2882. function Max(a, b: Single): Single;inline;
  2883. begin
  2884. if a > b then
  2885. Result := a
  2886. else
  2887. Result := b;
  2888. end;
  2889. {$endif FPC_HAS_TYPE_SINGLE}
  2890. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2891. function Min(a, b: Double): Double;inline;
  2892. begin
  2893. if a < b then
  2894. Result := a
  2895. else
  2896. Result := b;
  2897. end;
  2898. function Max(a, b: Double): Double;inline;
  2899. begin
  2900. if a > b then
  2901. Result := a
  2902. else
  2903. Result := b;
  2904. end;
  2905. {$endif FPC_HAS_TYPE_DOUBLE}
  2906. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2907. function Min(a, b: Extended): Extended;inline;
  2908. begin
  2909. if a < b then
  2910. Result := a
  2911. else
  2912. Result := b;
  2913. end;
  2914. function Max(a, b: Extended): Extended;inline;
  2915. begin
  2916. if a > b then
  2917. Result := a
  2918. else
  2919. Result := b;
  2920. end;
  2921. {$endif FPC_HAS_TYPE_EXTENDED}
  2922. function InRange(const AValue, AMin, AMax: Integer): Boolean;inline;
  2923. begin
  2924. Result:=(AValue>=AMin) and (AValue<=AMax);
  2925. end;
  2926. function InRange(const AValue, AMin, AMax: Int64): Boolean;inline;
  2927. begin
  2928. Result:=(AValue>=AMin) and (AValue<=AMax);
  2929. end;
  2930. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2931. function InRange(const AValue, AMin, AMax: Double): Boolean;inline;
  2932. begin
  2933. Result:=(AValue>=AMin) and (AValue<=AMax);
  2934. end;
  2935. {$endif FPC_HAS_TYPE_DOUBLE}
  2936. function EnsureRange(const AValue, AMin, AMax: Integer): Integer;inline;
  2937. begin
  2938. Result:=AValue;
  2939. If Result<AMin then
  2940. Result:=AMin;
  2941. if Result>AMax then
  2942. Result:=AMax;
  2943. end;
  2944. function EnsureRange(const AValue, AMin, AMax: Int64): Int64;inline;
  2945. begin
  2946. Result:=AValue;
  2947. If Result<AMin then
  2948. Result:=AMin;
  2949. if Result>AMax then
  2950. Result:=AMax;
  2951. end;
  2952. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2953. function EnsureRange(const AValue, AMin, AMax: Double): Double;inline;
  2954. begin
  2955. Result:=AValue;
  2956. If Result<AMin then
  2957. Result:=AMin;
  2958. if Result>AMax then
  2959. Result:=AMax;
  2960. end;
  2961. {$endif FPC_HAS_TYPE_DOUBLE}
  2962. Const
  2963. EZeroResolution = Extended(1E-16);
  2964. DZeroResolution = Double(1E-12);
  2965. SZeroResolution = Single(1E-4);
  2966. function IsZero(const A: Single; Epsilon: Single): Boolean;
  2967. begin
  2968. if (Epsilon=0) then
  2969. Epsilon:=SZeroResolution;
  2970. Result:=Abs(A)<=Epsilon;
  2971. end;
  2972. function IsZero(const A: Single): Boolean;inline;
  2973. begin
  2974. Result:=IsZero(A,single(SZeroResolution));
  2975. end;
  2976. {$ifdef FPC_HAS_TYPE_DOUBLE}
  2977. function IsZero(const A: Double; Epsilon: Double): Boolean;
  2978. begin
  2979. if (Epsilon=0) then
  2980. Epsilon:=DZeroResolution;
  2981. Result:=Abs(A)<=Epsilon;
  2982. end;
  2983. function IsZero(const A: Double): Boolean;inline;
  2984. begin
  2985. Result:=IsZero(A,DZeroResolution);
  2986. end;
  2987. {$endif FPC_HAS_TYPE_DOUBLE}
  2988. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2989. function IsZero(const A: Extended; Epsilon: Extended): Boolean;
  2990. begin
  2991. if (Epsilon=0) then
  2992. Epsilon:=EZeroResolution;
  2993. Result:=Abs(A)<=Epsilon;
  2994. end;
  2995. function IsZero(const A: Extended): Boolean;inline;
  2996. begin
  2997. Result:=IsZero(A,EZeroResolution);
  2998. end;
  2999. {$endif FPC_HAS_TYPE_EXTENDED}
  3000. type
  3001. TSplitDouble = packed record
  3002. cards: Array[0..1] of cardinal;
  3003. end;
  3004. TSplitExtended = packed record
  3005. cards: Array[0..1] of cardinal;
  3006. w: word;
  3007. end;
  3008. function IsNan(const d : Single): Boolean; overload;
  3009. begin
  3010. result:=(longword(d) and $7fffffff)>$7f800000;
  3011. end;
  3012. {$ifdef FPC_HAS_TYPE_DOUBLE}
  3013. function IsNan(const d : Double): Boolean;
  3014. var
  3015. fraczero, expMaximal: boolean;
  3016. begin
  3017. {$if defined(FPC_BIG_ENDIAN) or defined(FPC_DOUBLE_HILO_SWAPPED)}
  3018. expMaximal := ((TSplitDouble(d).cards[0] shr 20) and $7ff) = 2047;
  3019. fraczero:= (TSplitDouble(d).cards[0] and $fffff = 0) and
  3020. (TSplitDouble(d).cards[1] = 0);
  3021. {$else FPC_BIG_ENDIAN}
  3022. expMaximal := ((TSplitDouble(d).cards[1] shr 20) and $7ff) = 2047;
  3023. fraczero := (TSplitDouble(d).cards[1] and $fffff = 0) and
  3024. (TSplitDouble(d).cards[0] = 0);
  3025. {$endif FPC_BIG_ENDIAN}
  3026. Result:=expMaximal and not(fraczero);
  3027. end;
  3028. {$endif FPC_HAS_TYPE_DOUBLE}
  3029. {$ifdef FPC_HAS_TYPE_EXTENDED}
  3030. function IsNan(const d : Extended): Boolean; overload;
  3031. var
  3032. fraczero, expMaximal: boolean;
  3033. begin
  3034. {$ifdef FPC_BIG_ENDIAN}
  3035. {$error no support for big endian extended type yet}
  3036. {$else FPC_BIG_ENDIAN}
  3037. expMaximal := (TSplitExtended(d).w and $7fff) = 32767;
  3038. fraczero := (TSplitExtended(d).cards[0] = 0) and
  3039. ((TSplitExtended(d).cards[1] and $7fffffff) = 0);
  3040. {$endif FPC_BIG_ENDIAN}
  3041. Result:=expMaximal and not(fraczero);
  3042. end;
  3043. {$endif FPC_HAS_TYPE_EXTENDED}
  3044. function IsInfinite(const d : Single): Boolean; overload;
  3045. begin
  3046. result:=(longword(d) and $7fffffff)=$7f800000;
  3047. end;
  3048. {$ifdef FPC_HAS_TYPE_DOUBLE}
  3049. function IsInfinite(const d : Double): Boolean; overload;
  3050. var
  3051. fraczero, expMaximal: boolean;
  3052. begin
  3053. {$if defined(FPC_BIG_ENDIAN) or defined(FPC_DOUBLE_HILO_SWAPPED)}
  3054. expMaximal := ((TSplitDouble(d).cards[0] shr 20) and $7ff) = 2047;
  3055. fraczero:= (TSplitDouble(d).cards[0] and $fffff = 0) and
  3056. (TSplitDouble(d).cards[1] = 0);
  3057. {$else FPC_BIG_ENDIAN}
  3058. expMaximal := ((TSplitDouble(d).cards[1] shr 20) and $7ff) = 2047;
  3059. fraczero := (TSplitDouble(d).cards[1] and $fffff = 0) and
  3060. (TSplitDouble(d).cards[0] = 0);
  3061. {$endif FPC_BIG_ENDIAN}
  3062. Result:=expMaximal and fraczero;
  3063. end;
  3064. {$endif FPC_HAS_TYPE_DOUBLE}
  3065. {$ifdef FPC_HAS_TYPE_EXTENDED}
  3066. function IsInfinite(const d : Extended): Boolean; overload;
  3067. var
  3068. fraczero, expMaximal: boolean;
  3069. begin
  3070. {$ifdef FPC_BIG_ENDIAN}
  3071. {$error no support for big endian extended type yet}
  3072. {$else FPC_BIG_ENDIAN}
  3073. expMaximal := (TSplitExtended(d).w and $7fff) = 32767;
  3074. fraczero := (TSplitExtended(d).cards[0] = 0) and
  3075. ((TSplitExtended(d).cards[1] and $7fffffff) = 0);
  3076. {$endif FPC_BIG_ENDIAN}
  3077. Result:=expMaximal and fraczero;
  3078. end;
  3079. {$endif FPC_HAS_TYPE_EXTENDED}
  3080. function copysign(x,y: float): float;
  3081. begin
  3082. {$if defined(FPC_HAS_TYPE_FLOAT128)}
  3083. {$error copysign not yet implemented for float128}
  3084. {$elseif defined(FPC_HAS_TYPE_EXTENDED)}
  3085. TSplitExtended(x).w:=(TSplitExtended(x).w and $7fff) or (TSplitExtended(y).w and $8000);
  3086. {$elseif defined(FPC_HAS_TYPE_DOUBLE)}
  3087. {$if defined(FPC_BIG_ENDIAN) or defined(FPC_DOUBLE_HILO_SWAPPED)}
  3088. TSplitDouble(x).cards[0]:=(TSplitDouble(x).cards[0] and $7fffffff) or (TSplitDouble(y).cards[0] and longword($80000000));
  3089. {$else}
  3090. TSplitDouble(x).cards[1]:=(TSplitDouble(x).cards[1] and $7fffffff) or (TSplitDouble(y).cards[1] and longword($80000000));
  3091. {$endif}
  3092. {$else}
  3093. longword(x):=longword(x and $7fffffff) or (longword(y) and longword($80000000));
  3094. {$endif}
  3095. result:=x;
  3096. end;
  3097. {$ifdef FPC_HAS_TYPE_EXTENDED}
  3098. function SameValue(const A, B: Extended; Epsilon: Extended): Boolean;
  3099. begin
  3100. if (Epsilon=0) then
  3101. Epsilon:=Max(Min(Abs(A),Abs(B))*EZeroResolution,EZeroResolution);
  3102. if (A>B) then
  3103. Result:=((A-B)<=Epsilon)
  3104. else
  3105. Result:=((B-A)<=Epsilon);
  3106. end;
  3107. function SameValue(const A, B: Extended): Boolean;inline;
  3108. begin
  3109. Result:=SameValue(A,B,0.0);
  3110. end;
  3111. {$endif FPC_HAS_TYPE_EXTENDED}
  3112. {$ifdef FPC_HAS_TYPE_DOUBLE}
  3113. function SameValue(const A, B: Double): Boolean;inline;
  3114. begin
  3115. Result:=SameValue(A,B,0.0);
  3116. end;
  3117. function SameValue(const A, B: Double; Epsilon: Double): Boolean;
  3118. begin
  3119. if (Epsilon=0) then
  3120. Epsilon:=Max(Min(Abs(A),Abs(B))*DZeroResolution,DZeroResolution);
  3121. if (A>B) then
  3122. Result:=((A-B)<=Epsilon)
  3123. else
  3124. Result:=((B-A)<=Epsilon);
  3125. end;
  3126. {$endif FPC_HAS_TYPE_DOUBLE}
  3127. function SameValue(const A, B: Single): Boolean;inline;
  3128. begin
  3129. Result:=SameValue(A,B,0);
  3130. end;
  3131. function SameValue(const A, B: Single; Epsilon: Single): Boolean;
  3132. begin
  3133. if (Epsilon=0) then
  3134. Epsilon:=Max(Min(Abs(A),Abs(B))*SZeroResolution,SZeroResolution);
  3135. if (A>B) then
  3136. Result:=((A-B)<=Epsilon)
  3137. else
  3138. Result:=((B-A)<=Epsilon);
  3139. end;
  3140. // Some CPUs probably allow a faster way of doing this in a single operation...
  3141. // There weshould define FPC_MATH_HAS_CPUDIVMOD in the header mathuh.inc and implement it using asm.
  3142. {$ifndef FPC_MATH_HAS_DIVMOD}
  3143. procedure DivMod(Dividend: LongInt; Divisor: Word; var Result, Remainder: Word);
  3144. begin
  3145. if Dividend < 0 then
  3146. begin
  3147. { Use DivMod with >=0 dividend }
  3148. Dividend:=-Dividend;
  3149. { The documented behavior of Pascal's div/mod operators and DivMod
  3150. on negative dividends is to return Result closer to zero and
  3151. a negative Remainder. Which means that we can just negate both
  3152. Result and Remainder, and all it's Ok. }
  3153. Result:=-(Dividend Div Divisor);
  3154. Remainder:=-(Dividend+(Result*Divisor));
  3155. end
  3156. else
  3157. begin
  3158. Result:=Dividend Div Divisor;
  3159. Remainder:=Dividend-(Result*Divisor);
  3160. end;
  3161. end;
  3162. procedure DivMod(Dividend: LongInt; Divisor: Word; var Result, Remainder: SmallInt);
  3163. begin
  3164. if Dividend < 0 then
  3165. begin
  3166. { Use DivMod with >=0 dividend }
  3167. Dividend:=-Dividend;
  3168. { The documented behavior of Pascal's div/mod operators and DivMod
  3169. on negative dividends is to return Result closer to zero and
  3170. a negative Remainder. Which means that we can just negate both
  3171. Result and Remainder, and all it's Ok. }
  3172. Result:=-(Dividend Div Divisor);
  3173. Remainder:=-(Dividend+(Result*Divisor));
  3174. end
  3175. else
  3176. begin
  3177. Result:=Dividend Div Divisor;
  3178. Remainder:=Dividend-(Result*Divisor);
  3179. end;
  3180. end;
  3181. procedure DivMod(Dividend: DWord; Divisor: DWord; var Result, Remainder: DWord);
  3182. begin
  3183. Result:=Dividend Div Divisor;
  3184. Remainder:=Dividend-(Result*Divisor);
  3185. end;
  3186. procedure DivMod(Dividend: LongInt; Divisor: LongInt; var Result, Remainder: LongInt);
  3187. begin
  3188. if Dividend < 0 then
  3189. begin
  3190. { Use DivMod with >=0 dividend }
  3191. Dividend:=-Dividend;
  3192. { The documented behavior of Pascal's div/mod operators and DivMod
  3193. on negative dividends is to return Result closer to zero and
  3194. a negative Remainder. Which means that we can just negate both
  3195. Result and Remainder, and all it's Ok. }
  3196. Result:=-(Dividend Div Divisor);
  3197. Remainder:=-(Dividend+(Result*Divisor));
  3198. end
  3199. else
  3200. begin
  3201. Result:=Dividend Div Divisor;
  3202. Remainder:=Dividend-(Result*Divisor);
  3203. end;
  3204. end;
  3205. {$endif FPC_MATH_HAS_DIVMOD}
  3206. { Floating point modulo}
  3207. {$ifdef FPC_HAS_TYPE_SINGLE}
  3208. function FMod(const a, b: Single): Single;inline;overload;
  3209. begin
  3210. result:= a-b * Int(a/b);
  3211. end;
  3212. {$endif FPC_HAS_TYPE_SINGLE}
  3213. {$ifdef FPC_HAS_TYPE_DOUBLE}
  3214. function FMod(const a, b: Double): Double;inline;overload;
  3215. begin
  3216. result:= a-b * Int(a/b);
  3217. end;
  3218. {$endif FPC_HAS_TYPE_DOUBLE}
  3219. {$ifdef FPC_HAS_TYPE_EXTENDED}
  3220. function FMod(const a, b: Extended): Extended;inline;overload;
  3221. begin
  3222. result:= a-b * Int(a/b);
  3223. end;
  3224. {$endif FPC_HAS_TYPE_EXTENDED}
  3225. operator mod(const a,b:float) c:float;inline;
  3226. begin
  3227. c:= a-b * Int(a/b);
  3228. if SameValue(abs(c),abs(b)) then
  3229. c:=0.0;
  3230. end;
  3231. function ifthen(val:boolean;const iftrue:integer; const iffalse:integer= 0) :integer;
  3232. begin
  3233. if val then result:=iftrue else result:=iffalse;
  3234. end;
  3235. function ifthen(val:boolean;const iftrue:int64 ; const iffalse:int64 = 0) :int64;
  3236. begin
  3237. if val then result:=iftrue else result:=iffalse;
  3238. end;
  3239. function ifthen(val:boolean;const iftrue:double ; const iffalse:double =0.0):double;
  3240. begin
  3241. if val then result:=iftrue else result:=iffalse;
  3242. end;
  3243. // dilemma here. asm can do the two comparisons in one go?
  3244. // but pascal is portable and can be inlined. Ah well, we need purepascal's anyway:
  3245. function CompareValue(const A, B : Integer): TValueRelationship;
  3246. begin
  3247. result:=GreaterThanValue;
  3248. if a=b then
  3249. result:=EqualsValue
  3250. else
  3251. if a<b then
  3252. result:=LessThanValue;
  3253. end;
  3254. function CompareValue(const A, B: Int64): TValueRelationship;
  3255. begin
  3256. result:=GreaterThanValue;
  3257. if a=b then
  3258. result:=EqualsValue
  3259. else
  3260. if a<b then
  3261. result:=LessThanValue;
  3262. end;
  3263. function CompareValue(const A, B: QWord): TValueRelationship;
  3264. begin
  3265. result:=GreaterThanValue;
  3266. if a=b then
  3267. result:=EqualsValue
  3268. else
  3269. if a<b then
  3270. result:=LessThanValue;
  3271. end;
  3272. {$ifdef FPC_HAS_TYPE_SINGLE}
  3273. function CompareValue(const A, B: Single; delta: Single = 0.0): TValueRelationship;
  3274. begin
  3275. result:=GreaterThanValue;
  3276. if abs(a-b)<=delta then
  3277. result:=EqualsValue
  3278. else
  3279. if a<b then
  3280. result:=LessThanValue;
  3281. end;
  3282. {$endif}
  3283. {$ifdef FPC_HAS_TYPE_DOUBLE}
  3284. function CompareValue(const A, B: Double; delta: Double = 0.0): TValueRelationship;
  3285. begin
  3286. result:=GreaterThanValue;
  3287. if abs(a-b)<=delta then
  3288. result:=EqualsValue
  3289. else
  3290. if a<b then
  3291. result:=LessThanValue;
  3292. end;
  3293. {$endif}
  3294. {$ifdef FPC_HAS_TYPE_EXTENDED}
  3295. function CompareValue (const A, B: Extended; delta: Extended = 0.0): TValueRelationship;
  3296. begin
  3297. result:=GreaterThanValue;
  3298. if abs(a-b)<=delta then
  3299. result:=EqualsValue
  3300. else
  3301. if a<b then
  3302. result:=LessThanValue;
  3303. end;
  3304. {$endif}
  3305. {$ifdef FPC_HAS_TYPE_DOUBLE}
  3306. function RoundTo(const AValue: Double; const Digits: TRoundToRange): Double;
  3307. var
  3308. RV : Double;
  3309. begin
  3310. RV:=IntPower(10,Digits);
  3311. Result:=Round(AValue/RV)*RV;
  3312. end;
  3313. {$endif}
  3314. {$ifdef FPC_HAS_TYPE_EXTENDED}
  3315. function RoundTo(const AVAlue: Extended; const Digits: TRoundToRange): Extended;
  3316. var
  3317. RV : Extended;
  3318. begin
  3319. RV:=IntPower(10,Digits);
  3320. Result:=Round(AValue/RV)*RV;
  3321. end;
  3322. {$endif}
  3323. {$ifdef FPC_HAS_TYPE_SINGLE}
  3324. function RoundTo(const AValue: Single; const Digits: TRoundToRange): Single;
  3325. var
  3326. RV : Single;
  3327. begin
  3328. RV:=IntPower(10,Digits);
  3329. Result:=Round(AValue/RV)*RV;
  3330. end;
  3331. {$endif}
  3332. {$ifdef FPC_HAS_TYPE_SINGLE}
  3333. function SimpleRoundTo(const AValue: Single; const Digits: TRoundToRange = -2): Single;
  3334. var
  3335. RV : Single;
  3336. begin
  3337. RV := IntPower(10, -Digits);
  3338. if AValue < 0 then
  3339. Result := Int((AValue*RV) - 0.5)/RV
  3340. else
  3341. Result := Int((AValue*RV) + 0.5)/RV;
  3342. end;
  3343. {$endif}
  3344. {$ifdef FPC_HAS_TYPE_DOUBLE}
  3345. function SimpleRoundTo(const AValue: Double; const Digits: TRoundToRange = -2): Double;
  3346. var
  3347. RV : Double;
  3348. begin
  3349. RV := IntPower(10, -Digits);
  3350. if AValue < 0 then
  3351. Result := Int((AValue*RV) - 0.5)/RV
  3352. else
  3353. Result := Int((AValue*RV) + 0.5)/RV;
  3354. end;
  3355. {$endif}
  3356. {$ifdef FPC_HAS_TYPE_EXTENDED}
  3357. function SimpleRoundTo(const AValue: Extended; const Digits: TRoundToRange = -2): Extended;
  3358. var
  3359. RV : Extended;
  3360. begin
  3361. RV := IntPower(10, -Digits);
  3362. if AValue < 0 then
  3363. Result := Int((AValue*RV) - 0.5)/RV
  3364. else
  3365. Result := Int((AValue*RV) + 0.5)/RV;
  3366. end;
  3367. {$endif}
  3368. function RandomFrom(const AValues: array of Double): Double; overload;
  3369. begin
  3370. result:=AValues[random(High(AValues)+1)];
  3371. end;
  3372. function RandomFrom(const AValues: array of Integer): Integer; overload;
  3373. begin
  3374. result:=AValues[random(High(AValues)+1)];
  3375. end;
  3376. function RandomFrom(const AValues: array of Int64): Int64; overload;
  3377. begin
  3378. result:=AValues[random(High(AValues)+1)];
  3379. end;
  3380. {$if FPC_FULLVERSION >=30101}
  3381. generic function RandomFrom<T>(const AValues:array of T):T;
  3382. begin
  3383. result:=AValues[random(High(AValues)+1)];
  3384. end;
  3385. {$endif}
  3386. function FutureValue(ARate: Float; NPeriods: Integer;
  3387. APayment, APresentValue: Float; APaymentTime: TPaymentTime): Float;
  3388. var
  3389. q, qn, factor: Float;
  3390. begin
  3391. if ARate = 0 then
  3392. Result := -APresentValue - APayment * NPeriods
  3393. else begin
  3394. q := 1.0 + ARate;
  3395. qn := power(q, NPeriods);
  3396. factor := (qn - 1) / (q - 1);
  3397. if APaymentTime = ptStartOfPeriod then
  3398. factor := factor * q;
  3399. Result := -(APresentValue * qn + APayment*factor);
  3400. end;
  3401. end;
  3402. function InterestRate(NPeriods: Integer; APayment, APresentValue, AFutureValue: Float;
  3403. APaymentTime: TPaymentTime): Float;
  3404. { The interest rate cannot be calculated analytically. We solve the equation
  3405. numerically by means of the Newton method:
  3406. - guess value for the interest reate
  3407. - calculate at which interest rate the tangent of the curve fv(rate)
  3408. (straight line!) has the requested future vale.
  3409. - use this rate for the next iteration. }
  3410. const
  3411. DELTA = 0.001;
  3412. EPS = 1E-9; // required precision of interest rate (after typ. 6 iterations)
  3413. MAXIT = 20; // max iteration count to protect agains non-convergence
  3414. var
  3415. r1, r2, dr: Float;
  3416. fv1, fv2: Float;
  3417. iteration: Integer;
  3418. begin
  3419. iteration := 0;
  3420. r1 := 0.05; // inital guess
  3421. repeat
  3422. r2 := r1 + DELTA;
  3423. fv1 := FutureValue(r1, NPeriods, APayment, APresentValue, APaymentTime);
  3424. fv2 := FutureValue(r2, NPeriods, APayment, APresentValue, APaymentTime);
  3425. dr := (AFutureValue - fv1) / (fv2 - fv1) * delta; // tangent at fv(r)
  3426. r1 := r1 + dr; // next guess
  3427. inc(iteration);
  3428. until (abs(dr) < EPS) or (iteration >= MAXIT);
  3429. Result := r1;
  3430. end;
  3431. function NumberOfPeriods(ARate, APayment, APresentValue, AFutureValue: Float;
  3432. APaymentTime: TPaymentTime): Float;
  3433. { Solve the cash flow equation (1) for q^n and take the logarithm }
  3434. var
  3435. q, x1, x2: Float;
  3436. begin
  3437. if ARate = 0 then
  3438. Result := -(APresentValue + AFutureValue) / APayment
  3439. else begin
  3440. q := 1.0 + ARate;
  3441. if APaymentTime = ptStartOfPeriod then
  3442. APayment := APayment * q;
  3443. x1 := APayment - AFutureValue * ARate;
  3444. x2 := APayment + APresentValue * ARate;
  3445. if (x2 = 0) // we have to divide by x2
  3446. or (sign(x1) * sign(x2) < 0) // the argument of the log is negative
  3447. then
  3448. Result := Infinity
  3449. else begin
  3450. Result := ln(x1/x2) / ln(q);
  3451. end;
  3452. end;
  3453. end;
  3454. function Payment(ARate: Float; NPeriods: Integer;
  3455. APresentValue, AFutureValue: Float; APaymentTime: TPaymentTime): Float;
  3456. var
  3457. q, qn, factor: Float;
  3458. begin
  3459. if ARate = 0 then
  3460. Result := -(AFutureValue + APresentValue) / NPeriods
  3461. else begin
  3462. q := 1.0 + ARate;
  3463. qn := power(q, NPeriods);
  3464. factor := (qn - 1) / (q - 1);
  3465. if APaymentTime = ptStartOfPeriod then
  3466. factor := factor * q;
  3467. Result := -(AFutureValue + APresentValue * qn) / factor;
  3468. end;
  3469. end;
  3470. function PresentValue(ARate: Float; NPeriods: Integer;
  3471. APayment, AFutureValue: Float; APaymentTime: TPaymentTime): Float;
  3472. var
  3473. q, qn, factor: Float;
  3474. begin
  3475. if ARate = 0.0 then
  3476. Result := -AFutureValue - APayment * NPeriods
  3477. else begin
  3478. q := 1.0 + ARate;
  3479. qn := power(q, NPeriods);
  3480. factor := (qn - 1) / (q - 1);
  3481. if APaymentTime = ptStartOfPeriod then
  3482. factor := factor * q;
  3483. Result := -(AFutureValue + APayment*factor) / qn;
  3484. end;
  3485. end;
  3486. {$else}
  3487. implementation
  3488. {$endif FPUNONE}
  3489. end.