math.pp 101 KB

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