Statistical.php 133 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. if (!defined('PHPEXCEL_ROOT')) {
  8. /**
  9. * @ignore
  10. */
  11. define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
  12. require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
  13. }
  14. require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/trendClass.php';
  15. /** LOG_GAMMA_X_MAX_VALUE */
  16. define('LOG_GAMMA_X_MAX_VALUE', 2.55e305);
  17. /** XMININ */
  18. define('XMININ', 2.23e-308);
  19. /** EPS */
  20. define('EPS', 2.22e-16);
  21. /** SQRT2PI */
  22. define('SQRT2PI', 2.5066282746310005024157652848110452530069867406099);
  23. /**
  24. * PHPExcel_Calculation_Statistical
  25. *
  26. * Copyright (c) 2006 - 2015 PHPExcel
  27. *
  28. * This library is free software; you can redistribute it and/or
  29. * modify it under the terms of the GNU Lesser General Public
  30. * License as published by the Free Software Foundation; either
  31. * version 2.1 of the License, or (at your option) any later version.
  32. *
  33. * This library is distributed in the hope that it will be useful,
  34. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  35. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  36. * Lesser General Public License for more details.
  37. *
  38. * You should have received a copy of the GNU Lesser General Public
  39. * License along with this library; if not, write to the Free Software
  40. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  41. *
  42. * @category PHPExcel
  43. * @package PHPExcel_Calculation
  44. * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  45. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  46. * @version ##VERSION##, ##DATE##
  47. */
  48. class PHPExcel_Calculation_Statistical
  49. {
  50. private static function checkTrendArrays(&$array1, &$array2)
  51. {
  52. if (!is_array($array1)) {
  53. $array1 = array($array1);
  54. }
  55. if (!is_array($array2)) {
  56. $array2 = array($array2);
  57. }
  58. $array1 = PHPExcel_Calculation_Functions::flattenArray($array1);
  59. $array2 = PHPExcel_Calculation_Functions::flattenArray($array2);
  60. foreach ($array1 as $key => $value) {
  61. if ((is_bool($value)) || (is_string($value)) || (is_null($value))) {
  62. unset($array1[$key]);
  63. unset($array2[$key]);
  64. }
  65. }
  66. foreach ($array2 as $key => $value) {
  67. if ((is_bool($value)) || (is_string($value)) || (is_null($value))) {
  68. unset($array1[$key]);
  69. unset($array2[$key]);
  70. }
  71. }
  72. $array1 = array_merge($array1);
  73. $array2 = array_merge($array2);
  74. return true;
  75. }
  76. /**
  77. * Beta function.
  78. *
  79. * @author Jaco van Kooten
  80. *
  81. * @param p require p>0
  82. * @param q require q>0
  83. * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow
  84. */
  85. private static function beta($p, $q)
  86. {
  87. if ($p <= 0.0 || $q <= 0.0 || ($p + $q) > LOG_GAMMA_X_MAX_VALUE) {
  88. return 0.0;
  89. } else {
  90. return exp(self::logBeta($p, $q));
  91. }
  92. }
  93. /**
  94. * Incomplete beta function
  95. *
  96. * @author Jaco van Kooten
  97. * @author Paul Meagher
  98. *
  99. * The computation is based on formulas from Numerical Recipes, Chapter 6.4 (W.H. Press et al, 1992).
  100. * @param x require 0<=x<=1
  101. * @param p require p>0
  102. * @param q require q>0
  103. * @return 0 if x<0, p<=0, q<=0 or p+q>2.55E305 and 1 if x>1 to avoid errors and over/underflow
  104. */
  105. private static function incompleteBeta($x, $p, $q)
  106. {
  107. if ($x <= 0.0) {
  108. return 0.0;
  109. } elseif ($x >= 1.0) {
  110. return 1.0;
  111. } elseif (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) {
  112. return 0.0;
  113. }
  114. $beta_gam = exp((0 - self::logBeta($p, $q)) + $p * log($x) + $q * log(1.0 - $x));
  115. if ($x < ($p + 1.0) / ($p + $q + 2.0)) {
  116. return $beta_gam * self::betaFraction($x, $p, $q) / $p;
  117. } else {
  118. return 1.0 - ($beta_gam * self::betaFraction(1 - $x, $q, $p) / $q);
  119. }
  120. }
  121. // Function cache for logBeta function
  122. private static $logBetaCacheP = 0.0;
  123. private static $logBetaCacheQ = 0.0;
  124. private static $logBetaCacheResult = 0.0;
  125. /**
  126. * The natural logarithm of the beta function.
  127. *
  128. * @param p require p>0
  129. * @param q require q>0
  130. * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow
  131. * @author Jaco van Kooten
  132. */
  133. private static function logBeta($p, $q)
  134. {
  135. if ($p != self::$logBetaCacheP || $q != self::$logBetaCacheQ) {
  136. self::$logBetaCacheP = $p;
  137. self::$logBetaCacheQ = $q;
  138. if (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) {
  139. self::$logBetaCacheResult = 0.0;
  140. } else {
  141. self::$logBetaCacheResult = self::logGamma($p) + self::logGamma($q) - self::logGamma($p + $q);
  142. }
  143. }
  144. return self::$logBetaCacheResult;
  145. }
  146. /**
  147. * Evaluates of continued fraction part of incomplete beta function.
  148. * Based on an idea from Numerical Recipes (W.H. Press et al, 1992).
  149. * @author Jaco van Kooten
  150. */
  151. private static function betaFraction($x, $p, $q)
  152. {
  153. $c = 1.0;
  154. $sum_pq = $p + $q;
  155. $p_plus = $p + 1.0;
  156. $p_minus = $p - 1.0;
  157. $h = 1.0 - $sum_pq * $x / $p_plus;
  158. if (abs($h) < XMININ) {
  159. $h = XMININ;
  160. }
  161. $h = 1.0 / $h;
  162. $frac = $h;
  163. $m = 1;
  164. $delta = 0.0;
  165. while ($m <= MAX_ITERATIONS && abs($delta-1.0) > PRECISION) {
  166. $m2 = 2 * $m;
  167. // even index for d
  168. $d = $m * ($q - $m) * $x / ( ($p_minus + $m2) * ($p + $m2));
  169. $h = 1.0 + $d * $h;
  170. if (abs($h) < XMININ) {
  171. $h = XMININ;
  172. }
  173. $h = 1.0 / $h;
  174. $c = 1.0 + $d / $c;
  175. if (abs($c) < XMININ) {
  176. $c = XMININ;
  177. }
  178. $frac *= $h * $c;
  179. // odd index for d
  180. $d = -($p + $m) * ($sum_pq + $m) * $x / (($p + $m2) * ($p_plus + $m2));
  181. $h = 1.0 + $d * $h;
  182. if (abs($h) < XMININ) {
  183. $h = XMININ;
  184. }
  185. $h = 1.0 / $h;
  186. $c = 1.0 + $d / $c;
  187. if (abs($c) < XMININ) {
  188. $c = XMININ;
  189. }
  190. $delta = $h * $c;
  191. $frac *= $delta;
  192. ++$m;
  193. }
  194. return $frac;
  195. }
  196. /**
  197. * logGamma function
  198. *
  199. * @version 1.1
  200. * @author Jaco van Kooten
  201. *
  202. * Original author was Jaco van Kooten. Ported to PHP by Paul Meagher.
  203. *
  204. * The natural logarithm of the gamma function. <br />
  205. * Based on public domain NETLIB (Fortran) code by W. J. Cody and L. Stoltz <br />
  206. * Applied Mathematics Division <br />
  207. * Argonne National Laboratory <br />
  208. * Argonne, IL 60439 <br />
  209. * <p>
  210. * References:
  211. * <ol>
  212. * <li>W. J. Cody and K. E. Hillstrom, 'Chebyshev Approximations for the Natural
  213. * Logarithm of the Gamma Function,' Math. Comp. 21, 1967, pp. 198-203.</li>
  214. * <li>K. E. Hillstrom, ANL/AMD Program ANLC366S, DGAMMA/DLGAMA, May, 1969.</li>
  215. * <li>Hart, Et. Al., Computer Approximations, Wiley and sons, New York, 1968.</li>
  216. * </ol>
  217. * </p>
  218. * <p>
  219. * From the original documentation:
  220. * </p>
  221. * <p>
  222. * This routine calculates the LOG(GAMMA) function for a positive real argument X.
  223. * Computation is based on an algorithm outlined in references 1 and 2.
  224. * The program uses rational functions that theoretically approximate LOG(GAMMA)
  225. * to at least 18 significant decimal digits. The approximation for X > 12 is from
  226. * reference 3, while approximations for X < 12.0 are similar to those in reference
  227. * 1, but are unpublished. The accuracy achieved depends on the arithmetic system,
  228. * the compiler, the intrinsic functions, and proper selection of the
  229. * machine-dependent constants.
  230. * </p>
  231. * <p>
  232. * Error returns: <br />
  233. * The program returns the value XINF for X .LE. 0.0 or when overflow would occur.
  234. * The computation is believed to be free of underflow and overflow.
  235. * </p>
  236. * @return MAX_VALUE for x < 0.0 or when overflow would occur, i.e. x > 2.55E305
  237. */
  238. // Function cache for logGamma
  239. private static $logGammaCacheResult = 0.0;
  240. private static $logGammaCacheX = 0.0;
  241. private static function logGamma($x)
  242. {
  243. // Log Gamma related constants
  244. static $lg_d1 = -0.5772156649015328605195174;
  245. static $lg_d2 = 0.4227843350984671393993777;
  246. static $lg_d4 = 1.791759469228055000094023;
  247. static $lg_p1 = array(
  248. 4.945235359296727046734888,
  249. 201.8112620856775083915565,
  250. 2290.838373831346393026739,
  251. 11319.67205903380828685045,
  252. 28557.24635671635335736389,
  253. 38484.96228443793359990269,
  254. 26377.48787624195437963534,
  255. 7225.813979700288197698961
  256. );
  257. static $lg_p2 = array(
  258. 4.974607845568932035012064,
  259. 542.4138599891070494101986,
  260. 15506.93864978364947665077,
  261. 184793.2904445632425417223,
  262. 1088204.76946882876749847,
  263. 3338152.967987029735917223,
  264. 5106661.678927352456275255,
  265. 3074109.054850539556250927
  266. );
  267. static $lg_p4 = array(
  268. 14745.02166059939948905062,
  269. 2426813.369486704502836312,
  270. 121475557.4045093227939592,
  271. 2663432449.630976949898078,
  272. 29403789566.34553899906876,
  273. 170266573776.5398868392998,
  274. 492612579337.743088758812,
  275. 560625185622.3951465078242
  276. );
  277. static $lg_q1 = array(
  278. 67.48212550303777196073036,
  279. 1113.332393857199323513008,
  280. 7738.757056935398733233834,
  281. 27639.87074403340708898585,
  282. 54993.10206226157329794414,
  283. 61611.22180066002127833352,
  284. 36351.27591501940507276287,
  285. 8785.536302431013170870835
  286. );
  287. static $lg_q2 = array(
  288. 183.0328399370592604055942,
  289. 7765.049321445005871323047,
  290. 133190.3827966074194402448,
  291. 1136705.821321969608938755,
  292. 5267964.117437946917577538,
  293. 13467014.54311101692290052,
  294. 17827365.30353274213975932,
  295. 9533095.591844353613395747
  296. );
  297. static $lg_q4 = array(
  298. 2690.530175870899333379843,
  299. 639388.5654300092398984238,
  300. 41355999.30241388052042842,
  301. 1120872109.61614794137657,
  302. 14886137286.78813811542398,
  303. 101680358627.2438228077304,
  304. 341747634550.7377132798597,
  305. 446315818741.9713286462081
  306. );
  307. static $lg_c = array(
  308. -0.001910444077728,
  309. 8.4171387781295e-4,
  310. -5.952379913043012e-4,
  311. 7.93650793500350248e-4,
  312. -0.002777777777777681622553,
  313. 0.08333333333333333331554247,
  314. 0.0057083835261
  315. );
  316. // Rough estimate of the fourth root of logGamma_xBig
  317. static $lg_frtbig = 2.25e76;
  318. static $pnt68 = 0.6796875;
  319. if ($x == self::$logGammaCacheX) {
  320. return self::$logGammaCacheResult;
  321. }
  322. $y = $x;
  323. if ($y > 0.0 && $y <= LOG_GAMMA_X_MAX_VALUE) {
  324. if ($y <= EPS) {
  325. $res = -log(y);
  326. } elseif ($y <= 1.5) {
  327. // ---------------------
  328. // EPS .LT. X .LE. 1.5
  329. // ---------------------
  330. if ($y < $pnt68) {
  331. $corr = -log($y);
  332. $xm1 = $y;
  333. } else {
  334. $corr = 0.0;
  335. $xm1 = $y - 1.0;
  336. }
  337. if ($y <= 0.5 || $y >= $pnt68) {
  338. $xden = 1.0;
  339. $xnum = 0.0;
  340. for ($i = 0; $i < 8; ++$i) {
  341. $xnum = $xnum * $xm1 + $lg_p1[$i];
  342. $xden = $xden * $xm1 + $lg_q1[$i];
  343. }
  344. $res = $corr + $xm1 * ($lg_d1 + $xm1 * ($xnum / $xden));
  345. } else {
  346. $xm2 = $y - 1.0;
  347. $xden = 1.0;
  348. $xnum = 0.0;
  349. for ($i = 0; $i < 8; ++$i) {
  350. $xnum = $xnum * $xm2 + $lg_p2[$i];
  351. $xden = $xden * $xm2 + $lg_q2[$i];
  352. }
  353. $res = $corr + $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden));
  354. }
  355. } elseif ($y <= 4.0) {
  356. // ---------------------
  357. // 1.5 .LT. X .LE. 4.0
  358. // ---------------------
  359. $xm2 = $y - 2.0;
  360. $xden = 1.0;
  361. $xnum = 0.0;
  362. for ($i = 0; $i < 8; ++$i) {
  363. $xnum = $xnum * $xm2 + $lg_p2[$i];
  364. $xden = $xden * $xm2 + $lg_q2[$i];
  365. }
  366. $res = $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden));
  367. } elseif ($y <= 12.0) {
  368. // ----------------------
  369. // 4.0 .LT. X .LE. 12.0
  370. // ----------------------
  371. $xm4 = $y - 4.0;
  372. $xden = -1.0;
  373. $xnum = 0.0;
  374. for ($i = 0; $i < 8; ++$i) {
  375. $xnum = $xnum * $xm4 + $lg_p4[$i];
  376. $xden = $xden * $xm4 + $lg_q4[$i];
  377. }
  378. $res = $lg_d4 + $xm4 * ($xnum / $xden);
  379. } else {
  380. // ---------------------------------
  381. // Evaluate for argument .GE. 12.0
  382. // ---------------------------------
  383. $res = 0.0;
  384. if ($y <= $lg_frtbig) {
  385. $res = $lg_c[6];
  386. $ysq = $y * $y;
  387. for ($i = 0; $i < 6; ++$i) {
  388. $res = $res / $ysq + $lg_c[$i];
  389. }
  390. $res /= $y;
  391. $corr = log($y);
  392. $res = $res + log(SQRT2PI) - 0.5 * $corr;
  393. $res += $y * ($corr - 1.0);
  394. }
  395. }
  396. } else {
  397. // --------------------------
  398. // Return for bad arguments
  399. // --------------------------
  400. $res = MAX_VALUE;
  401. }
  402. // ------------------------------
  403. // Final adjustments and return
  404. // ------------------------------
  405. self::$logGammaCacheX = $x;
  406. self::$logGammaCacheResult = $res;
  407. return $res;
  408. }
  409. //
  410. // Private implementation of the incomplete Gamma function
  411. //
  412. private static function incompleteGamma($a, $x)
  413. {
  414. static $max = 32;
  415. $summer = 0;
  416. for ($n=0; $n<=$max; ++$n) {
  417. $divisor = $a;
  418. for ($i=1; $i<=$n; ++$i) {
  419. $divisor *= ($a + $i);
  420. }
  421. $summer += (pow($x, $n) / $divisor);
  422. }
  423. return pow($x, $a) * exp(0-$x) * $summer;
  424. }
  425. //
  426. // Private implementation of the Gamma function
  427. //
  428. private static function gamma($data)
  429. {
  430. if ($data == 0.0) {
  431. return 0;
  432. }
  433. static $p0 = 1.000000000190015;
  434. static $p = array(
  435. 1 => 76.18009172947146,
  436. 2 => -86.50532032941677,
  437. 3 => 24.01409824083091,
  438. 4 => -1.231739572450155,
  439. 5 => 1.208650973866179e-3,
  440. 6 => -5.395239384953e-6
  441. );
  442. $y = $x = $data;
  443. $tmp = $x + 5.5;
  444. $tmp -= ($x + 0.5) * log($tmp);
  445. $summer = $p0;
  446. for ($j=1; $j<=6; ++$j) {
  447. $summer += ($p[$j] / ++$y);
  448. }
  449. return exp(0 - $tmp + log(SQRT2PI * $summer / $x));
  450. }
  451. /***************************************************************************
  452. * inverse_ncdf.php
  453. * -------------------
  454. * begin : Friday, January 16, 2004
  455. * copyright : (C) 2004 Michael Nickerson
  456. * email : nickersonm@yahoo.com
  457. *
  458. ***************************************************************************/
  459. private static function inverseNcdf($p)
  460. {
  461. // Inverse ncdf approximation by Peter J. Acklam, implementation adapted to
  462. // PHP by Michael Nickerson, using Dr. Thomas Ziegler's C implementation as
  463. // a guide. http://home.online.no/~pjacklam/notes/invnorm/index.html
  464. // I have not checked the accuracy of this implementation. Be aware that PHP
  465. // will truncate the coeficcients to 14 digits.
  466. // You have permission to use and distribute this function freely for
  467. // whatever purpose you want, but please show common courtesy and give credit
  468. // where credit is due.
  469. // Input paramater is $p - probability - where 0 < p < 1.
  470. // Coefficients in rational approximations
  471. static $a = array(
  472. 1 => -3.969683028665376e+01,
  473. 2 => 2.209460984245205e+02,
  474. 3 => -2.759285104469687e+02,
  475. 4 => 1.383577518672690e+02,
  476. 5 => -3.066479806614716e+01,
  477. 6 => 2.506628277459239e+00
  478. );
  479. static $b = array(
  480. 1 => -5.447609879822406e+01,
  481. 2 => 1.615858368580409e+02,
  482. 3 => -1.556989798598866e+02,
  483. 4 => 6.680131188771972e+01,
  484. 5 => -1.328068155288572e+01
  485. );
  486. static $c = array(
  487. 1 => -7.784894002430293e-03,
  488. 2 => -3.223964580411365e-01,
  489. 3 => -2.400758277161838e+00,
  490. 4 => -2.549732539343734e+00,
  491. 5 => 4.374664141464968e+00,
  492. 6 => 2.938163982698783e+00
  493. );
  494. static $d = array(
  495. 1 => 7.784695709041462e-03,
  496. 2 => 3.224671290700398e-01,
  497. 3 => 2.445134137142996e+00,
  498. 4 => 3.754408661907416e+00
  499. );
  500. // Define lower and upper region break-points.
  501. $p_low = 0.02425; //Use lower region approx. below this
  502. $p_high = 1 - $p_low; //Use upper region approx. above this
  503. if (0 < $p && $p < $p_low) {
  504. // Rational approximation for lower region.
  505. $q = sqrt(-2 * log($p));
  506. return ((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) /
  507. (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1);
  508. } elseif ($p_low <= $p && $p <= $p_high) {
  509. // Rational approximation for central region.
  510. $q = $p - 0.5;
  511. $r = $q * $q;
  512. return ((((($a[1] * $r + $a[2]) * $r + $a[3]) * $r + $a[4]) * $r + $a[5]) * $r + $a[6]) * $q /
  513. ((((($b[1] * $r + $b[2]) * $r + $b[3]) * $r + $b[4]) * $r + $b[5]) * $r + 1);
  514. } elseif ($p_high < $p && $p < 1) {
  515. // Rational approximation for upper region.
  516. $q = sqrt(-2 * log(1 - $p));
  517. return -((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) /
  518. (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1);
  519. }
  520. // If 0 < p < 1, return a null value
  521. return PHPExcel_Calculation_Functions::NULL();
  522. }
  523. private static function inverseNcdf2($prob)
  524. {
  525. // Approximation of inverse standard normal CDF developed by
  526. // B. Moro, "The Full Monte," Risk 8(2), Feb 1995, 57-58.
  527. $a1 = 2.50662823884;
  528. $a2 = -18.61500062529;
  529. $a3 = 41.39119773534;
  530. $a4 = -25.44106049637;
  531. $b1 = -8.4735109309;
  532. $b2 = 23.08336743743;
  533. $b3 = -21.06224101826;
  534. $b4 = 3.13082909833;
  535. $c1 = 0.337475482272615;
  536. $c2 = 0.976169019091719;
  537. $c3 = 0.160797971491821;
  538. $c4 = 2.76438810333863E-02;
  539. $c5 = 3.8405729373609E-03;
  540. $c6 = 3.951896511919E-04;
  541. $c7 = 3.21767881768E-05;
  542. $c8 = 2.888167364E-07;
  543. $c9 = 3.960315187E-07;
  544. $y = $prob - 0.5;
  545. if (abs($y) < 0.42) {
  546. $z = ($y * $y);
  547. $z = $y * ((($a4 * $z + $a3) * $z + $a2) * $z + $a1) / (((($b4 * $z + $b3) * $z + $b2) * $z + $b1) * $z + 1);
  548. } else {
  549. if ($y > 0) {
  550. $z = log(-log(1 - $prob));
  551. } else {
  552. $z = log(-log($prob));
  553. }
  554. $z = $c1 + $z * ($c2 + $z * ($c3 + $z * ($c4 + $z * ($c5 + $z * ($c6 + $z * ($c7 + $z * ($c8 + $z * $c9)))))));
  555. if ($y < 0) {
  556. $z = -$z;
  557. }
  558. }
  559. return $z;
  560. } // function inverseNcdf2()
  561. private static function inverseNcdf3($p)
  562. {
  563. // ALGORITHM AS241 APPL. STATIST. (1988) VOL. 37, NO. 3.
  564. // Produces the normal deviate Z corresponding to a given lower
  565. // tail area of P; Z is accurate to about 1 part in 10**16.
  566. //
  567. // This is a PHP version of the original FORTRAN code that can
  568. // be found at http://lib.stat.cmu.edu/apstat/
  569. $split1 = 0.425;
  570. $split2 = 5;
  571. $const1 = 0.180625;
  572. $const2 = 1.6;
  573. // coefficients for p close to 0.5
  574. $a0 = 3.3871328727963666080;
  575. $a1 = 1.3314166789178437745E+2;
  576. $a2 = 1.9715909503065514427E+3;
  577. $a3 = 1.3731693765509461125E+4;
  578. $a4 = 4.5921953931549871457E+4;
  579. $a5 = 6.7265770927008700853E+4;
  580. $a6 = 3.3430575583588128105E+4;
  581. $a7 = 2.5090809287301226727E+3;
  582. $b1 = 4.2313330701600911252E+1;
  583. $b2 = 6.8718700749205790830E+2;
  584. $b3 = 5.3941960214247511077E+3;
  585. $b4 = 2.1213794301586595867E+4;
  586. $b5 = 3.9307895800092710610E+4;
  587. $b6 = 2.8729085735721942674E+4;
  588. $b7 = 5.2264952788528545610E+3;
  589. // coefficients for p not close to 0, 0.5 or 1.
  590. $c0 = 1.42343711074968357734;
  591. $c1 = 4.63033784615654529590;
  592. $c2 = 5.76949722146069140550;
  593. $c3 = 3.64784832476320460504;
  594. $c4 = 1.27045825245236838258;
  595. $c5 = 2.41780725177450611770E-1;
  596. $c6 = 2.27238449892691845833E-2;
  597. $c7 = 7.74545014278341407640E-4;
  598. $d1 = 2.05319162663775882187;
  599. $d2 = 1.67638483018380384940;
  600. $d3 = 6.89767334985100004550E-1;
  601. $d4 = 1.48103976427480074590E-1;
  602. $d5 = 1.51986665636164571966E-2;
  603. $d6 = 5.47593808499534494600E-4;
  604. $d7 = 1.05075007164441684324E-9;
  605. // coefficients for p near 0 or 1.
  606. $e0 = 6.65790464350110377720;
  607. $e1 = 5.46378491116411436990;
  608. $e2 = 1.78482653991729133580;
  609. $e3 = 2.96560571828504891230E-1;
  610. $e4 = 2.65321895265761230930E-2;
  611. $e5 = 1.24266094738807843860E-3;
  612. $e6 = 2.71155556874348757815E-5;
  613. $e7 = 2.01033439929228813265E-7;
  614. $f1 = 5.99832206555887937690E-1;
  615. $f2 = 1.36929880922735805310E-1;
  616. $f3 = 1.48753612908506148525E-2;
  617. $f4 = 7.86869131145613259100E-4;
  618. $f5 = 1.84631831751005468180E-5;
  619. $f6 = 1.42151175831644588870E-7;
  620. $f7 = 2.04426310338993978564E-15;
  621. $q = $p - 0.5;
  622. // computation for p close to 0.5
  623. if (abs($q) <= split1) {
  624. $R = $const1 - $q * $q;
  625. $z = $q * ((((((($a7 * $R + $a6) * $R + $a5) * $R + $a4) * $R + $a3) * $R + $a2) * $R + $a1) * $R + $a0) /
  626. ((((((($b7 * $R + $b6) * $R + $b5) * $R + $b4) * $R + $b3) * $R + $b2) * $R + $b1) * $R + 1);
  627. } else {
  628. if ($q < 0) {
  629. $R = $p;
  630. } else {
  631. $R = 1 - $p;
  632. }
  633. $R = pow(-log($R), 2);
  634. // computation for p not close to 0, 0.5 or 1.
  635. if ($R <= $split2) {
  636. $R = $R - $const2;
  637. $z = ((((((($c7 * $R + $c6) * $R + $c5) * $R + $c4) * $R + $c3) * $R + $c2) * $R + $c1) * $R + $c0) /
  638. ((((((($d7 * $R + $d6) * $R + $d5) * $R + $d4) * $R + $d3) * $R + $d2) * $R + $d1) * $R + 1);
  639. } else {
  640. // computation for p near 0 or 1.
  641. $R = $R - $split2;
  642. $z = ((((((($e7 * $R + $e6) * $R + $e5) * $R + $e4) * $R + $e3) * $R + $e2) * $R + $e1) * $R + $e0) /
  643. ((((((($f7 * $R + $f6) * $R + $f5) * $R + $f4) * $R + $f3) * $R + $f2) * $R + $f1) * $R + 1);
  644. }
  645. if ($q < 0) {
  646. $z = -$z;
  647. }
  648. }
  649. return $z;
  650. }
  651. /**
  652. * AVEDEV
  653. *
  654. * Returns the average of the absolute deviations of data points from their mean.
  655. * AVEDEV is a measure of the variability in a data set.
  656. *
  657. * Excel Function:
  658. * AVEDEV(value1[,value2[, ...]])
  659. *
  660. * @access public
  661. * @category Statistical Functions
  662. * @param mixed $arg,... Data values
  663. * @return float
  664. */
  665. public static function AVEDEV()
  666. {
  667. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  668. // Return value
  669. $returnValue = null;
  670. $aMean = self::AVERAGE($aArgs);
  671. if ($aMean != PHPExcel_Calculation_Functions::DIV0()) {
  672. $aCount = 0;
  673. foreach ($aArgs as $k => $arg) {
  674. if ((is_bool($arg)) &&
  675. ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
  676. $arg = (integer) $arg;
  677. }
  678. // Is it a numeric value?
  679. if ((is_numeric($arg)) && (!is_string($arg))) {
  680. if (is_null($returnValue)) {
  681. $returnValue = abs($arg - $aMean);
  682. } else {
  683. $returnValue += abs($arg - $aMean);
  684. }
  685. ++$aCount;
  686. }
  687. }
  688. // Return
  689. if ($aCount == 0) {
  690. return PHPExcel_Calculation_Functions::DIV0();
  691. }
  692. return $returnValue / $aCount;
  693. }
  694. return PHPExcel_Calculation_Functions::NaN();
  695. }
  696. /**
  697. * AVERAGE
  698. *
  699. * Returns the average (arithmetic mean) of the arguments
  700. *
  701. * Excel Function:
  702. * AVERAGE(value1[,value2[, ...]])
  703. *
  704. * @access public
  705. * @category Statistical Functions
  706. * @param mixed $arg,... Data values
  707. * @return float
  708. */
  709. public static function AVERAGE()
  710. {
  711. $returnValue = $aCount = 0;
  712. // Loop through arguments
  713. foreach (PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()) as $k => $arg) {
  714. if ((is_bool($arg)) &&
  715. ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
  716. $arg = (integer) $arg;
  717. }
  718. // Is it a numeric value?
  719. if ((is_numeric($arg)) && (!is_string($arg))) {
  720. if (is_null($returnValue)) {
  721. $returnValue = $arg;
  722. } else {
  723. $returnValue += $arg;
  724. }
  725. ++$aCount;
  726. }
  727. }
  728. // Return
  729. if ($aCount > 0) {
  730. return $returnValue / $aCount;
  731. } else {
  732. return PHPExcel_Calculation_Functions::DIV0();
  733. }
  734. }
  735. /**
  736. * AVERAGEA
  737. *
  738. * Returns the average of its arguments, including numbers, text, and logical values
  739. *
  740. * Excel Function:
  741. * AVERAGEA(value1[,value2[, ...]])
  742. *
  743. * @access public
  744. * @category Statistical Functions
  745. * @param mixed $arg,... Data values
  746. * @return float
  747. */
  748. public static function AVERAGEA()
  749. {
  750. $returnValue = null;
  751. $aCount = 0;
  752. // Loop through arguments
  753. foreach (PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()) as $k => $arg) {
  754. if ((is_bool($arg)) &&
  755. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  756. } else {
  757. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
  758. if (is_bool($arg)) {
  759. $arg = (integer) $arg;
  760. } elseif (is_string($arg)) {
  761. $arg = 0;
  762. }
  763. if (is_null($returnValue)) {
  764. $returnValue = $arg;
  765. } else {
  766. $returnValue += $arg;
  767. }
  768. ++$aCount;
  769. }
  770. }
  771. }
  772. if ($aCount > 0) {
  773. return $returnValue / $aCount;
  774. } else {
  775. return PHPExcel_Calculation_Functions::DIV0();
  776. }
  777. }
  778. /**
  779. * AVERAGEIF
  780. *
  781. * Returns the average value from a range of cells that contain numbers within the list of arguments
  782. *
  783. * Excel Function:
  784. * AVERAGEIF(value1[,value2[, ...]],condition)
  785. *
  786. * @access public
  787. * @category Mathematical and Trigonometric Functions
  788. * @param mixed $arg,... Data values
  789. * @param string $condition The criteria that defines which cells will be checked.
  790. * @param mixed[] $averageArgs Data values
  791. * @return float
  792. */
  793. public static function AVERAGEIF($aArgs, $condition, $averageArgs = array())
  794. {
  795. $returnValue = 0;
  796. $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
  797. $averageArgs = PHPExcel_Calculation_Functions::flattenArray($averageArgs);
  798. if (empty($averageArgs)) {
  799. $averageArgs = $aArgs;
  800. }
  801. $condition = PHPExcel_Calculation_Functions::ifCondition($condition);
  802. // Loop through arguments
  803. $aCount = 0;
  804. foreach ($aArgs as $key => $arg) {
  805. if (!is_numeric($arg)) {
  806. $arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
  807. }
  808. $testCondition = '='.$arg.$condition;
  809. if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
  810. if ((is_null($returnValue)) || ($arg > $returnValue)) {
  811. $returnValue += $arg;
  812. ++$aCount;
  813. }
  814. }
  815. }
  816. if ($aCount > 0) {
  817. return $returnValue / $aCount;
  818. }
  819. return PHPExcel_Calculation_Functions::DIV0();
  820. }
  821. /**
  822. * BETADIST
  823. *
  824. * Returns the beta distribution.
  825. *
  826. * @param float $value Value at which you want to evaluate the distribution
  827. * @param float $alpha Parameter to the distribution
  828. * @param float $beta Parameter to the distribution
  829. * @param boolean $cumulative
  830. * @return float
  831. *
  832. */
  833. public static function BETADIST($value, $alpha, $beta, $rMin = 0, $rMax = 1)
  834. {
  835. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  836. $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
  837. $beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta);
  838. $rMin = PHPExcel_Calculation_Functions::flattenSingleValue($rMin);
  839. $rMax = PHPExcel_Calculation_Functions::flattenSingleValue($rMax);
  840. if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) {
  841. if (($value < $rMin) || ($value > $rMax) || ($alpha <= 0) || ($beta <= 0) || ($rMin == $rMax)) {
  842. return PHPExcel_Calculation_Functions::NaN();
  843. }
  844. if ($rMin > $rMax) {
  845. $tmp = $rMin;
  846. $rMin = $rMax;
  847. $rMax = $tmp;
  848. }
  849. $value -= $rMin;
  850. $value /= ($rMax - $rMin);
  851. return self::incompleteBeta($value, $alpha, $beta);
  852. }
  853. return PHPExcel_Calculation_Functions::VALUE();
  854. }
  855. /**
  856. * BETAINV
  857. *
  858. * Returns the inverse of the beta distribution.
  859. *
  860. * @param float $probability Probability at which you want to evaluate the distribution
  861. * @param float $alpha Parameter to the distribution
  862. * @param float $beta Parameter to the distribution
  863. * @param float $rMin Minimum value
  864. * @param float $rMax Maximum value
  865. * @param boolean $cumulative
  866. * @return float
  867. *
  868. */
  869. public static function BETAINV($probability, $alpha, $beta, $rMin = 0, $rMax = 1)
  870. {
  871. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  872. $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
  873. $beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta);
  874. $rMin = PHPExcel_Calculation_Functions::flattenSingleValue($rMin);
  875. $rMax = PHPExcel_Calculation_Functions::flattenSingleValue($rMax);
  876. if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) {
  877. if (($alpha <= 0) || ($beta <= 0) || ($rMin == $rMax) || ($probability <= 0) || ($probability > 1)) {
  878. return PHPExcel_Calculation_Functions::NaN();
  879. }
  880. if ($rMin > $rMax) {
  881. $tmp = $rMin;
  882. $rMin = $rMax;
  883. $rMax = $tmp;
  884. }
  885. $a = 0;
  886. $b = 2;
  887. $i = 0;
  888. while ((($b - $a) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
  889. $guess = ($a + $b) / 2;
  890. $result = self::BETADIST($guess, $alpha, $beta);
  891. if (($result == $probability) || ($result == 0)) {
  892. $b = $a;
  893. } elseif ($result > $probability) {
  894. $b = $guess;
  895. } else {
  896. $a = $guess;
  897. }
  898. }
  899. if ($i == MAX_ITERATIONS) {
  900. return PHPExcel_Calculation_Functions::NA();
  901. }
  902. return round($rMin + $guess * ($rMax - $rMin), 12);
  903. }
  904. return PHPExcel_Calculation_Functions::VALUE();
  905. }
  906. /**
  907. * BINOMDIST
  908. *
  909. * Returns the individual term binomial distribution probability. Use BINOMDIST in problems with
  910. * a fixed number of tests or trials, when the outcomes of any trial are only success or failure,
  911. * when trials are independent, and when the probability of success is constant throughout the
  912. * experiment. For example, BINOMDIST can calculate the probability that two of the next three
  913. * babies born are male.
  914. *
  915. * @param float $value Number of successes in trials
  916. * @param float $trials Number of trials
  917. * @param float $probability Probability of success on each trial
  918. * @param boolean $cumulative
  919. * @return float
  920. *
  921. * @todo Cumulative distribution function
  922. *
  923. */
  924. public static function BINOMDIST($value, $trials, $probability, $cumulative)
  925. {
  926. $value = floor(PHPExcel_Calculation_Functions::flattenSingleValue($value));
  927. $trials = floor(PHPExcel_Calculation_Functions::flattenSingleValue($trials));
  928. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  929. if ((is_numeric($value)) && (is_numeric($trials)) && (is_numeric($probability))) {
  930. if (($value < 0) || ($value > $trials)) {
  931. return PHPExcel_Calculation_Functions::NaN();
  932. }
  933. if (($probability < 0) || ($probability > 1)) {
  934. return PHPExcel_Calculation_Functions::NaN();
  935. }
  936. if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
  937. if ($cumulative) {
  938. $summer = 0;
  939. for ($i = 0; $i <= $value; ++$i) {
  940. $summer += PHPExcel_Calculation_MathTrig::COMBIN($trials, $i) * pow($probability, $i) * pow(1 - $probability, $trials - $i);
  941. }
  942. return $summer;
  943. } else {
  944. return PHPExcel_Calculation_MathTrig::COMBIN($trials, $value) * pow($probability, $value) * pow(1 - $probability, $trials - $value) ;
  945. }
  946. }
  947. }
  948. return PHPExcel_Calculation_Functions::VALUE();
  949. }
  950. /**
  951. * CHIDIST
  952. *
  953. * Returns the one-tailed probability of the chi-squared distribution.
  954. *
  955. * @param float $value Value for the function
  956. * @param float $degrees degrees of freedom
  957. * @return float
  958. */
  959. public static function CHIDIST($value, $degrees)
  960. {
  961. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  962. $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees));
  963. if ((is_numeric($value)) && (is_numeric($degrees))) {
  964. if ($degrees < 1) {
  965. return PHPExcel_Calculation_Functions::NaN();
  966. }
  967. if ($value < 0) {
  968. if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) {
  969. return 1;
  970. }
  971. return PHPExcel_Calculation_Functions::NaN();
  972. }
  973. return 1 - (self::incompleteGamma($degrees/2, $value/2) / self::gamma($degrees/2));
  974. }
  975. return PHPExcel_Calculation_Functions::VALUE();
  976. }
  977. /**
  978. * CHIINV
  979. *
  980. * Returns the one-tailed probability of the chi-squared distribution.
  981. *
  982. * @param float $probability Probability for the function
  983. * @param float $degrees degrees of freedom
  984. * @return float
  985. */
  986. public static function CHIINV($probability, $degrees)
  987. {
  988. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  989. $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees));
  990. if ((is_numeric($probability)) && (is_numeric($degrees))) {
  991. $xLo = 100;
  992. $xHi = 0;
  993. $x = $xNew = 1;
  994. $dx = 1;
  995. $i = 0;
  996. while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
  997. // Apply Newton-Raphson step
  998. $result = self::CHIDIST($x, $degrees);
  999. $error = $result - $probability;
  1000. if ($error == 0.0) {
  1001. $dx = 0;
  1002. } elseif ($error < 0.0) {
  1003. $xLo = $x;
  1004. } else {
  1005. $xHi = $x;
  1006. }
  1007. // Avoid division by zero
  1008. if ($result != 0.0) {
  1009. $dx = $error / $result;
  1010. $xNew = $x - $dx;
  1011. }
  1012. // If the NR fails to converge (which for example may be the
  1013. // case if the initial guess is too rough) we apply a bisection
  1014. // step to determine a more narrow interval around the root.
  1015. if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) {
  1016. $xNew = ($xLo + $xHi) / 2;
  1017. $dx = $xNew - $x;
  1018. }
  1019. $x = $xNew;
  1020. }
  1021. if ($i == MAX_ITERATIONS) {
  1022. return PHPExcel_Calculation_Functions::NA();
  1023. }
  1024. return round($x, 12);
  1025. }
  1026. return PHPExcel_Calculation_Functions::VALUE();
  1027. }
  1028. /**
  1029. * CONFIDENCE
  1030. *
  1031. * Returns the confidence interval for a population mean
  1032. *
  1033. * @param float $alpha
  1034. * @param float $stdDev Standard Deviation
  1035. * @param float $size
  1036. * @return float
  1037. *
  1038. */
  1039. public static function CONFIDENCE($alpha, $stdDev, $size)
  1040. {
  1041. $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
  1042. $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
  1043. $size = floor(PHPExcel_Calculation_Functions::flattenSingleValue($size));
  1044. if ((is_numeric($alpha)) && (is_numeric($stdDev)) && (is_numeric($size))) {
  1045. if (($alpha <= 0) || ($alpha >= 1)) {
  1046. return PHPExcel_Calculation_Functions::NaN();
  1047. }
  1048. if (($stdDev <= 0) || ($size < 1)) {
  1049. return PHPExcel_Calculation_Functions::NaN();
  1050. }
  1051. return self::NORMSINV(1 - $alpha / 2) * $stdDev / sqrt($size);
  1052. }
  1053. return PHPExcel_Calculation_Functions::VALUE();
  1054. }
  1055. /**
  1056. * CORREL
  1057. *
  1058. * Returns covariance, the average of the products of deviations for each data point pair.
  1059. *
  1060. * @param array of mixed Data Series Y
  1061. * @param array of mixed Data Series X
  1062. * @return float
  1063. */
  1064. public static function CORREL($yValues, $xValues = null)
  1065. {
  1066. if ((is_null($xValues)) || (!is_array($yValues)) || (!is_array($xValues))) {
  1067. return PHPExcel_Calculation_Functions::VALUE();
  1068. }
  1069. if (!self::checkTrendArrays($yValues, $xValues)) {
  1070. return PHPExcel_Calculation_Functions::VALUE();
  1071. }
  1072. $yValueCount = count($yValues);
  1073. $xValueCount = count($xValues);
  1074. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  1075. return PHPExcel_Calculation_Functions::NA();
  1076. } elseif ($yValueCount == 1) {
  1077. return PHPExcel_Calculation_Functions::DIV0();
  1078. }
  1079. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  1080. return $bestFitLinear->getCorrelation();
  1081. }
  1082. /**
  1083. * COUNT
  1084. *
  1085. * Counts the number of cells that contain numbers within the list of arguments
  1086. *
  1087. * Excel Function:
  1088. * COUNT(value1[,value2[, ...]])
  1089. *
  1090. * @access public
  1091. * @category Statistical Functions
  1092. * @param mixed $arg,... Data values
  1093. * @return int
  1094. */
  1095. public static function COUNT()
  1096. {
  1097. $returnValue = 0;
  1098. // Loop through arguments
  1099. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  1100. foreach ($aArgs as $k => $arg) {
  1101. if ((is_bool($arg)) &&
  1102. ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
  1103. $arg = (integer) $arg;
  1104. }
  1105. // Is it a numeric value?
  1106. if ((is_numeric($arg)) && (!is_string($arg))) {
  1107. ++$returnValue;
  1108. }
  1109. }
  1110. return $returnValue;
  1111. }
  1112. /**
  1113. * COUNTA
  1114. *
  1115. * Counts the number of cells that are not empty within the list of arguments
  1116. *
  1117. * Excel Function:
  1118. * COUNTA(value1[,value2[, ...]])
  1119. *
  1120. * @access public
  1121. * @category Statistical Functions
  1122. * @param mixed $arg,... Data values
  1123. * @return int
  1124. */
  1125. public static function COUNTA()
  1126. {
  1127. $returnValue = 0;
  1128. // Loop through arguments
  1129. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  1130. foreach ($aArgs as $arg) {
  1131. // Is it a numeric, boolean or string value?
  1132. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
  1133. ++$returnValue;
  1134. }
  1135. }
  1136. return $returnValue;
  1137. }
  1138. /**
  1139. * COUNTBLANK
  1140. *
  1141. * Counts the number of empty cells within the list of arguments
  1142. *
  1143. * Excel Function:
  1144. * COUNTBLANK(value1[,value2[, ...]])
  1145. *
  1146. * @access public
  1147. * @category Statistical Functions
  1148. * @param mixed $arg,... Data values
  1149. * @return int
  1150. */
  1151. public static function COUNTBLANK()
  1152. {
  1153. $returnValue = 0;
  1154. // Loop through arguments
  1155. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  1156. foreach ($aArgs as $arg) {
  1157. // Is it a blank cell?
  1158. if ((is_null($arg)) || ((is_string($arg)) && ($arg == ''))) {
  1159. ++$returnValue;
  1160. }
  1161. }
  1162. return $returnValue;
  1163. }
  1164. /**
  1165. * COUNTIF
  1166. *
  1167. * Counts the number of cells that contain numbers within the list of arguments
  1168. *
  1169. * Excel Function:
  1170. * COUNTIF(value1[,value2[, ...]],condition)
  1171. *
  1172. * @access public
  1173. * @category Statistical Functions
  1174. * @param mixed $arg,... Data values
  1175. * @param string $condition The criteria that defines which cells will be counted.
  1176. * @return int
  1177. */
  1178. public static function COUNTIF($aArgs, $condition)
  1179. {
  1180. $returnValue = 0;
  1181. $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
  1182. $condition = PHPExcel_Calculation_Functions::ifCondition($condition);
  1183. // Loop through arguments
  1184. foreach ($aArgs as $arg) {
  1185. if (!is_numeric($arg)) {
  1186. $arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
  1187. }
  1188. $testCondition = '='.$arg.$condition;
  1189. if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
  1190. // Is it a value within our criteria
  1191. ++$returnValue;
  1192. }
  1193. }
  1194. return $returnValue;
  1195. }
  1196. /**
  1197. * COVAR
  1198. *
  1199. * Returns covariance, the average of the products of deviations for each data point pair.
  1200. *
  1201. * @param array of mixed Data Series Y
  1202. * @param array of mixed Data Series X
  1203. * @return float
  1204. */
  1205. public static function COVAR($yValues, $xValues)
  1206. {
  1207. if (!self::checkTrendArrays($yValues, $xValues)) {
  1208. return PHPExcel_Calculation_Functions::VALUE();
  1209. }
  1210. $yValueCount = count($yValues);
  1211. $xValueCount = count($xValues);
  1212. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  1213. return PHPExcel_Calculation_Functions::NA();
  1214. } elseif ($yValueCount == 1) {
  1215. return PHPExcel_Calculation_Functions::DIV0();
  1216. }
  1217. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  1218. return $bestFitLinear->getCovariance();
  1219. }
  1220. /**
  1221. * CRITBINOM
  1222. *
  1223. * Returns the smallest value for which the cumulative binomial distribution is greater
  1224. * than or equal to a criterion value
  1225. *
  1226. * See http://support.microsoft.com/kb/828117/ for details of the algorithm used
  1227. *
  1228. * @param float $trials number of Bernoulli trials
  1229. * @param float $probability probability of a success on each trial
  1230. * @param float $alpha criterion value
  1231. * @return int
  1232. *
  1233. * @todo Warning. This implementation differs from the algorithm detailed on the MS
  1234. * web site in that $CumPGuessMinus1 = $CumPGuess - 1 rather than $CumPGuess - $PGuess
  1235. * This eliminates a potential endless loop error, but may have an adverse affect on the
  1236. * accuracy of the function (although all my tests have so far returned correct results).
  1237. *
  1238. */
  1239. public static function CRITBINOM($trials, $probability, $alpha)
  1240. {
  1241. $trials = floor(PHPExcel_Calculation_Functions::flattenSingleValue($trials));
  1242. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  1243. $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
  1244. if ((is_numeric($trials)) && (is_numeric($probability)) && (is_numeric($alpha))) {
  1245. if ($trials < 0) {
  1246. return PHPExcel_Calculation_Functions::NaN();
  1247. } elseif (($probability < 0) || ($probability > 1)) {
  1248. return PHPExcel_Calculation_Functions::NaN();
  1249. } elseif (($alpha < 0) || ($alpha > 1)) {
  1250. return PHPExcel_Calculation_Functions::NaN();
  1251. } elseif ($alpha <= 0.5) {
  1252. $t = sqrt(log(1 / ($alpha * $alpha)));
  1253. $trialsApprox = 0 - ($t + (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t));
  1254. } else {
  1255. $t = sqrt(log(1 / pow(1 - $alpha, 2)));
  1256. $trialsApprox = $t - (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t);
  1257. }
  1258. $Guess = floor($trials * $probability + $trialsApprox * sqrt($trials * $probability * (1 - $probability)));
  1259. if ($Guess < 0) {
  1260. $Guess = 0;
  1261. } elseif ($Guess > $trials) {
  1262. $Guess = $trials;
  1263. }
  1264. $TotalUnscaledProbability = $UnscaledPGuess = $UnscaledCumPGuess = 0.0;
  1265. $EssentiallyZero = 10e-12;
  1266. $m = floor($trials * $probability);
  1267. ++$TotalUnscaledProbability;
  1268. if ($m == $Guess) {
  1269. ++$UnscaledPGuess;
  1270. }
  1271. if ($m <= $Guess) {
  1272. ++$UnscaledCumPGuess;
  1273. }
  1274. $PreviousValue = 1;
  1275. $Done = false;
  1276. $k = $m + 1;
  1277. while ((!$Done) && ($k <= $trials)) {
  1278. $CurrentValue = $PreviousValue * ($trials - $k + 1) * $probability / ($k * (1 - $probability));
  1279. $TotalUnscaledProbability += $CurrentValue;
  1280. if ($k == $Guess) {
  1281. $UnscaledPGuess += $CurrentValue;
  1282. }
  1283. if ($k <= $Guess) {
  1284. $UnscaledCumPGuess += $CurrentValue;
  1285. }
  1286. if ($CurrentValue <= $EssentiallyZero) {
  1287. $Done = true;
  1288. }
  1289. $PreviousValue = $CurrentValue;
  1290. ++$k;
  1291. }
  1292. $PreviousValue = 1;
  1293. $Done = false;
  1294. $k = $m - 1;
  1295. while ((!$Done) && ($k >= 0)) {
  1296. $CurrentValue = $PreviousValue * $k + 1 * (1 - $probability) / (($trials - $k) * $probability);
  1297. $TotalUnscaledProbability += $CurrentValue;
  1298. if ($k == $Guess) {
  1299. $UnscaledPGuess += $CurrentValue;
  1300. }
  1301. if ($k <= $Guess) {
  1302. $UnscaledCumPGuess += $CurrentValue;
  1303. }
  1304. if ($CurrentValue <= $EssentiallyZero) {
  1305. $Done = true;
  1306. }
  1307. $PreviousValue = $CurrentValue;
  1308. --$k;
  1309. }
  1310. $PGuess = $UnscaledPGuess / $TotalUnscaledProbability;
  1311. $CumPGuess = $UnscaledCumPGuess / $TotalUnscaledProbability;
  1312. // $CumPGuessMinus1 = $CumPGuess - $PGuess;
  1313. $CumPGuessMinus1 = $CumPGuess - 1;
  1314. while (true) {
  1315. if (($CumPGuessMinus1 < $alpha) && ($CumPGuess >= $alpha)) {
  1316. return $Guess;
  1317. } elseif (($CumPGuessMinus1 < $alpha) && ($CumPGuess < $alpha)) {
  1318. $PGuessPlus1 = $PGuess * ($trials - $Guess) * $probability / $Guess / (1 - $probability);
  1319. $CumPGuessMinus1 = $CumPGuess;
  1320. $CumPGuess = $CumPGuess + $PGuessPlus1;
  1321. $PGuess = $PGuessPlus1;
  1322. ++$Guess;
  1323. } elseif (($CumPGuessMinus1 >= $alpha) && ($CumPGuess >= $alpha)) {
  1324. $PGuessMinus1 = $PGuess * $Guess * (1 - $probability) / ($trials - $Guess + 1) / $probability;
  1325. $CumPGuess = $CumPGuessMinus1;
  1326. $CumPGuessMinus1 = $CumPGuessMinus1 - $PGuess;
  1327. $PGuess = $PGuessMinus1;
  1328. --$Guess;
  1329. }
  1330. }
  1331. }
  1332. return PHPExcel_Calculation_Functions::VALUE();
  1333. }
  1334. /**
  1335. * DEVSQ
  1336. *
  1337. * Returns the sum of squares of deviations of data points from their sample mean.
  1338. *
  1339. * Excel Function:
  1340. * DEVSQ(value1[,value2[, ...]])
  1341. *
  1342. * @access public
  1343. * @category Statistical Functions
  1344. * @param mixed $arg,... Data values
  1345. * @return float
  1346. */
  1347. public static function DEVSQ()
  1348. {
  1349. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  1350. // Return value
  1351. $returnValue = null;
  1352. $aMean = self::AVERAGE($aArgs);
  1353. if ($aMean != PHPExcel_Calculation_Functions::DIV0()) {
  1354. $aCount = -1;
  1355. foreach ($aArgs as $k => $arg) {
  1356. // Is it a numeric value?
  1357. if ((is_bool($arg)) &&
  1358. ((!PHPExcel_Calculation_Functions::isCellValue($k)) ||
  1359. (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
  1360. $arg = (integer) $arg;
  1361. }
  1362. if ((is_numeric($arg)) && (!is_string($arg))) {
  1363. if (is_null($returnValue)) {
  1364. $returnValue = pow(($arg - $aMean), 2);
  1365. } else {
  1366. $returnValue += pow(($arg - $aMean), 2);
  1367. }
  1368. ++$aCount;
  1369. }
  1370. }
  1371. // Return
  1372. if (is_null($returnValue)) {
  1373. return PHPExcel_Calculation_Functions::NaN();
  1374. } else {
  1375. return $returnValue;
  1376. }
  1377. }
  1378. return self::NA();
  1379. }
  1380. /**
  1381. * EXPONDIST
  1382. *
  1383. * Returns the exponential distribution. Use EXPONDIST to model the time between events,
  1384. * such as how long an automated bank teller takes to deliver cash. For example, you can
  1385. * use EXPONDIST to determine the probability that the process takes at most 1 minute.
  1386. *
  1387. * @param float $value Value of the function
  1388. * @param float $lambda The parameter value
  1389. * @param boolean $cumulative
  1390. * @return float
  1391. */
  1392. public static function EXPONDIST($value, $lambda, $cumulative)
  1393. {
  1394. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  1395. $lambda = PHPExcel_Calculation_Functions::flattenSingleValue($lambda);
  1396. $cumulative = PHPExcel_Calculation_Functions::flattenSingleValue($cumulative);
  1397. if ((is_numeric($value)) && (is_numeric($lambda))) {
  1398. if (($value < 0) || ($lambda < 0)) {
  1399. return PHPExcel_Calculation_Functions::NaN();
  1400. }
  1401. if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
  1402. if ($cumulative) {
  1403. return 1 - exp(0-$value*$lambda);
  1404. } else {
  1405. return $lambda * exp(0-$value*$lambda);
  1406. }
  1407. }
  1408. }
  1409. return PHPExcel_Calculation_Functions::VALUE();
  1410. }
  1411. /**
  1412. * FISHER
  1413. *
  1414. * Returns the Fisher transformation at x. This transformation produces a function that
  1415. * is normally distributed rather than skewed. Use this function to perform hypothesis
  1416. * testing on the correlation coefficient.
  1417. *
  1418. * @param float $value
  1419. * @return float
  1420. */
  1421. public static function FISHER($value)
  1422. {
  1423. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  1424. if (is_numeric($value)) {
  1425. if (($value <= -1) || ($value >= 1)) {
  1426. return PHPExcel_Calculation_Functions::NaN();
  1427. }
  1428. return 0.5 * log((1+$value)/(1-$value));
  1429. }
  1430. return PHPExcel_Calculation_Functions::VALUE();
  1431. }
  1432. /**
  1433. * FISHERINV
  1434. *
  1435. * Returns the inverse of the Fisher transformation. Use this transformation when
  1436. * analyzing correlations between ranges or arrays of data. If y = FISHER(x), then
  1437. * FISHERINV(y) = x.
  1438. *
  1439. * @param float $value
  1440. * @return float
  1441. */
  1442. public static function FISHERINV($value)
  1443. {
  1444. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  1445. if (is_numeric($value)) {
  1446. return (exp(2 * $value) - 1) / (exp(2 * $value) + 1);
  1447. }
  1448. return PHPExcel_Calculation_Functions::VALUE();
  1449. }
  1450. /**
  1451. * FORECAST
  1452. *
  1453. * Calculates, or predicts, a future value by using existing values. The predicted value is a y-value for a given x-value.
  1454. *
  1455. * @param float Value of X for which we want to find Y
  1456. * @param array of mixed Data Series Y
  1457. * @param array of mixed Data Series X
  1458. * @return float
  1459. */
  1460. public static function FORECAST($xValue, $yValues, $xValues)
  1461. {
  1462. $xValue = PHPExcel_Calculation_Functions::flattenSingleValue($xValue);
  1463. if (!is_numeric($xValue)) {
  1464. return PHPExcel_Calculation_Functions::VALUE();
  1465. } elseif (!self::checkTrendArrays($yValues, $xValues)) {
  1466. return PHPExcel_Calculation_Functions::VALUE();
  1467. }
  1468. $yValueCount = count($yValues);
  1469. $xValueCount = count($xValues);
  1470. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  1471. return PHPExcel_Calculation_Functions::NA();
  1472. } elseif ($yValueCount == 1) {
  1473. return PHPExcel_Calculation_Functions::DIV0();
  1474. }
  1475. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  1476. return $bestFitLinear->getValueOfYForX($xValue);
  1477. }
  1478. /**
  1479. * GAMMADIST
  1480. *
  1481. * Returns the gamma distribution.
  1482. *
  1483. * @param float $value Value at which you want to evaluate the distribution
  1484. * @param float $a Parameter to the distribution
  1485. * @param float $b Parameter to the distribution
  1486. * @param boolean $cumulative
  1487. * @return float
  1488. *
  1489. */
  1490. public static function GAMMADIST($value, $a, $b, $cumulative)
  1491. {
  1492. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  1493. $a = PHPExcel_Calculation_Functions::flattenSingleValue($a);
  1494. $b = PHPExcel_Calculation_Functions::flattenSingleValue($b);
  1495. if ((is_numeric($value)) && (is_numeric($a)) && (is_numeric($b))) {
  1496. if (($value < 0) || ($a <= 0) || ($b <= 0)) {
  1497. return PHPExcel_Calculation_Functions::NaN();
  1498. }
  1499. if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
  1500. if ($cumulative) {
  1501. return self::incompleteGamma($a, $value / $b) / self::gamma($a);
  1502. } else {
  1503. return (1 / (pow($b, $a) * self::gamma($a))) * pow($value, $a-1) * exp(0-($value / $b));
  1504. }
  1505. }
  1506. }
  1507. return PHPExcel_Calculation_Functions::VALUE();
  1508. }
  1509. /**
  1510. * GAMMAINV
  1511. *
  1512. * Returns the inverse of the beta distribution.
  1513. *
  1514. * @param float $probability Probability at which you want to evaluate the distribution
  1515. * @param float $alpha Parameter to the distribution
  1516. * @param float $beta Parameter to the distribution
  1517. * @return float
  1518. *
  1519. */
  1520. public static function GAMMAINV($probability, $alpha, $beta)
  1521. {
  1522. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  1523. $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
  1524. $beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta);
  1525. if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta))) {
  1526. if (($alpha <= 0) || ($beta <= 0) || ($probability < 0) || ($probability > 1)) {
  1527. return PHPExcel_Calculation_Functions::NaN();
  1528. }
  1529. $xLo = 0;
  1530. $xHi = $alpha * $beta * 5;
  1531. $x = $xNew = 1;
  1532. $error = $pdf = 0;
  1533. $dx = 1024;
  1534. $i = 0;
  1535. while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
  1536. // Apply Newton-Raphson step
  1537. $error = self::GAMMADIST($x, $alpha, $beta, true) - $probability;
  1538. if ($error < 0.0) {
  1539. $xLo = $x;
  1540. } else {
  1541. $xHi = $x;
  1542. }
  1543. $pdf = self::GAMMADIST($x, $alpha, $beta, false);
  1544. // Avoid division by zero
  1545. if ($pdf != 0.0) {
  1546. $dx = $error / $pdf;
  1547. $xNew = $x - $dx;
  1548. }
  1549. // If the NR fails to converge (which for example may be the
  1550. // case if the initial guess is too rough) we apply a bisection
  1551. // step to determine a more narrow interval around the root.
  1552. if (($xNew < $xLo) || ($xNew > $xHi) || ($pdf == 0.0)) {
  1553. $xNew = ($xLo + $xHi) / 2;
  1554. $dx = $xNew - $x;
  1555. }
  1556. $x = $xNew;
  1557. }
  1558. if ($i == MAX_ITERATIONS) {
  1559. return PHPExcel_Calculation_Functions::NA();
  1560. }
  1561. return $x;
  1562. }
  1563. return PHPExcel_Calculation_Functions::VALUE();
  1564. }
  1565. /**
  1566. * GAMMALN
  1567. *
  1568. * Returns the natural logarithm of the gamma function.
  1569. *
  1570. * @param float $value
  1571. * @return float
  1572. */
  1573. public static function GAMMALN($value)
  1574. {
  1575. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  1576. if (is_numeric($value)) {
  1577. if ($value <= 0) {
  1578. return PHPExcel_Calculation_Functions::NaN();
  1579. }
  1580. return log(self::gamma($value));
  1581. }
  1582. return PHPExcel_Calculation_Functions::VALUE();
  1583. }
  1584. /**
  1585. * GEOMEAN
  1586. *
  1587. * Returns the geometric mean of an array or range of positive data. For example, you
  1588. * can use GEOMEAN to calculate average growth rate given compound interest with
  1589. * variable rates.
  1590. *
  1591. * Excel Function:
  1592. * GEOMEAN(value1[,value2[, ...]])
  1593. *
  1594. * @access public
  1595. * @category Statistical Functions
  1596. * @param mixed $arg,... Data values
  1597. * @return float
  1598. */
  1599. public static function GEOMEAN()
  1600. {
  1601. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  1602. $aMean = PHPExcel_Calculation_MathTrig::PRODUCT($aArgs);
  1603. if (is_numeric($aMean) && ($aMean > 0)) {
  1604. $aCount = self::COUNT($aArgs) ;
  1605. if (self::MIN($aArgs) > 0) {
  1606. return pow($aMean, (1 / $aCount));
  1607. }
  1608. }
  1609. return PHPExcel_Calculation_Functions::NaN();
  1610. }
  1611. /**
  1612. * GROWTH
  1613. *
  1614. * Returns values along a predicted emponential trend
  1615. *
  1616. * @param array of mixed Data Series Y
  1617. * @param array of mixed Data Series X
  1618. * @param array of mixed Values of X for which we want to find Y
  1619. * @param boolean A logical value specifying whether to force the intersect to equal 0.
  1620. * @return array of float
  1621. */
  1622. public static function GROWTH($yValues, $xValues = array(), $newValues = array(), $const = true)
  1623. {
  1624. $yValues = PHPExcel_Calculation_Functions::flattenArray($yValues);
  1625. $xValues = PHPExcel_Calculation_Functions::flattenArray($xValues);
  1626. $newValues = PHPExcel_Calculation_Functions::flattenArray($newValues);
  1627. $const = (is_null($const)) ? true : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const);
  1628. $bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL, $yValues, $xValues, $const);
  1629. if (empty($newValues)) {
  1630. $newValues = $bestFitExponential->getXValues();
  1631. }
  1632. $returnArray = array();
  1633. foreach ($newValues as $xValue) {
  1634. $returnArray[0][] = $bestFitExponential->getValueOfYForX($xValue);
  1635. }
  1636. return $returnArray;
  1637. }
  1638. /**
  1639. * HARMEAN
  1640. *
  1641. * Returns the harmonic mean of a data set. The harmonic mean is the reciprocal of the
  1642. * arithmetic mean of reciprocals.
  1643. *
  1644. * Excel Function:
  1645. * HARMEAN(value1[,value2[, ...]])
  1646. *
  1647. * @access public
  1648. * @category Statistical Functions
  1649. * @param mixed $arg,... Data values
  1650. * @return float
  1651. */
  1652. public static function HARMEAN()
  1653. {
  1654. // Return value
  1655. $returnValue = PHPExcel_Calculation_Functions::NA();
  1656. // Loop through arguments
  1657. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  1658. if (self::MIN($aArgs) < 0) {
  1659. return PHPExcel_Calculation_Functions::NaN();
  1660. }
  1661. $aCount = 0;
  1662. foreach ($aArgs as $arg) {
  1663. // Is it a numeric value?
  1664. if ((is_numeric($arg)) && (!is_string($arg))) {
  1665. if ($arg <= 0) {
  1666. return PHPExcel_Calculation_Functions::NaN();
  1667. }
  1668. if (is_null($returnValue)) {
  1669. $returnValue = (1 / $arg);
  1670. } else {
  1671. $returnValue += (1 / $arg);
  1672. }
  1673. ++$aCount;
  1674. }
  1675. }
  1676. // Return
  1677. if ($aCount > 0) {
  1678. return 1 / ($returnValue / $aCount);
  1679. } else {
  1680. return $returnValue;
  1681. }
  1682. }
  1683. /**
  1684. * HYPGEOMDIST
  1685. *
  1686. * Returns the hypergeometric distribution. HYPGEOMDIST returns the probability of a given number of
  1687. * sample successes, given the sample size, population successes, and population size.
  1688. *
  1689. * @param float $sampleSuccesses Number of successes in the sample
  1690. * @param float $sampleNumber Size of the sample
  1691. * @param float $populationSuccesses Number of successes in the population
  1692. * @param float $populationNumber Population size
  1693. * @return float
  1694. *
  1695. */
  1696. public static function HYPGEOMDIST($sampleSuccesses, $sampleNumber, $populationSuccesses, $populationNumber)
  1697. {
  1698. $sampleSuccesses = floor(PHPExcel_Calculation_Functions::flattenSingleValue($sampleSuccesses));
  1699. $sampleNumber = floor(PHPExcel_Calculation_Functions::flattenSingleValue($sampleNumber));
  1700. $populationSuccesses = floor(PHPExcel_Calculation_Functions::flattenSingleValue($populationSuccesses));
  1701. $populationNumber = floor(PHPExcel_Calculation_Functions::flattenSingleValue($populationNumber));
  1702. if ((is_numeric($sampleSuccesses)) && (is_numeric($sampleNumber)) && (is_numeric($populationSuccesses)) && (is_numeric($populationNumber))) {
  1703. if (($sampleSuccesses < 0) || ($sampleSuccesses > $sampleNumber) || ($sampleSuccesses > $populationSuccesses)) {
  1704. return PHPExcel_Calculation_Functions::NaN();
  1705. }
  1706. if (($sampleNumber <= 0) || ($sampleNumber > $populationNumber)) {
  1707. return PHPExcel_Calculation_Functions::NaN();
  1708. }
  1709. if (($populationSuccesses <= 0) || ($populationSuccesses > $populationNumber)) {
  1710. return PHPExcel_Calculation_Functions::NaN();
  1711. }
  1712. return PHPExcel_Calculation_MathTrig::COMBIN($populationSuccesses, $sampleSuccesses) *
  1713. PHPExcel_Calculation_MathTrig::COMBIN($populationNumber - $populationSuccesses, $sampleNumber - $sampleSuccesses) /
  1714. PHPExcel_Calculation_MathTrig::COMBIN($populationNumber, $sampleNumber);
  1715. }
  1716. return PHPExcel_Calculation_Functions::VALUE();
  1717. }
  1718. /**
  1719. * INTERCEPT
  1720. *
  1721. * Calculates the point at which a line will intersect the y-axis by using existing x-values and y-values.
  1722. *
  1723. * @param array of mixed Data Series Y
  1724. * @param array of mixed Data Series X
  1725. * @return float
  1726. */
  1727. public static function INTERCEPT($yValues, $xValues)
  1728. {
  1729. if (!self::checkTrendArrays($yValues, $xValues)) {
  1730. return PHPExcel_Calculation_Functions::VALUE();
  1731. }
  1732. $yValueCount = count($yValues);
  1733. $xValueCount = count($xValues);
  1734. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  1735. return PHPExcel_Calculation_Functions::NA();
  1736. } elseif ($yValueCount == 1) {
  1737. return PHPExcel_Calculation_Functions::DIV0();
  1738. }
  1739. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  1740. return $bestFitLinear->getIntersect();
  1741. }
  1742. /**
  1743. * KURT
  1744. *
  1745. * Returns the kurtosis of a data set. Kurtosis characterizes the relative peakedness
  1746. * or flatness of a distribution compared with the normal distribution. Positive
  1747. * kurtosis indicates a relatively peaked distribution. Negative kurtosis indicates a
  1748. * relatively flat distribution.
  1749. *
  1750. * @param array Data Series
  1751. * @return float
  1752. */
  1753. public static function KURT()
  1754. {
  1755. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  1756. $mean = self::AVERAGE($aArgs);
  1757. $stdDev = self::STDEV($aArgs);
  1758. if ($stdDev > 0) {
  1759. $count = $summer = 0;
  1760. // Loop through arguments
  1761. foreach ($aArgs as $k => $arg) {
  1762. if ((is_bool($arg)) &&
  1763. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  1764. } else {
  1765. // Is it a numeric value?
  1766. if ((is_numeric($arg)) && (!is_string($arg))) {
  1767. $summer += pow((($arg - $mean) / $stdDev), 4);
  1768. ++$count;
  1769. }
  1770. }
  1771. }
  1772. // Return
  1773. if ($count > 3) {
  1774. return $summer * ($count * ($count+1) / (($count-1) * ($count-2) * ($count-3))) - (3 * pow($count-1, 2) / (($count-2) * ($count-3)));
  1775. }
  1776. }
  1777. return PHPExcel_Calculation_Functions::DIV0();
  1778. }
  1779. /**
  1780. * LARGE
  1781. *
  1782. * Returns the nth largest value in a data set. You can use this function to
  1783. * select a value based on its relative standing.
  1784. *
  1785. * Excel Function:
  1786. * LARGE(value1[,value2[, ...]],entry)
  1787. *
  1788. * @access public
  1789. * @category Statistical Functions
  1790. * @param mixed $arg,... Data values
  1791. * @param int $entry Position (ordered from the largest) in the array or range of data to return
  1792. * @return float
  1793. *
  1794. */
  1795. public static function LARGE()
  1796. {
  1797. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  1798. // Calculate
  1799. $entry = floor(array_pop($aArgs));
  1800. if ((is_numeric($entry)) && (!is_string($entry))) {
  1801. $mArgs = array();
  1802. foreach ($aArgs as $arg) {
  1803. // Is it a numeric value?
  1804. if ((is_numeric($arg)) && (!is_string($arg))) {
  1805. $mArgs[] = $arg;
  1806. }
  1807. }
  1808. $count = self::COUNT($mArgs);
  1809. $entry = floor(--$entry);
  1810. if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
  1811. return PHPExcel_Calculation_Functions::NaN();
  1812. }
  1813. rsort($mArgs);
  1814. return $mArgs[$entry];
  1815. }
  1816. return PHPExcel_Calculation_Functions::VALUE();
  1817. }
  1818. /**
  1819. * LINEST
  1820. *
  1821. * Calculates the statistics for a line by using the "least squares" method to calculate a straight line that best fits your data,
  1822. * and then returns an array that describes the line.
  1823. *
  1824. * @param array of mixed Data Series Y
  1825. * @param array of mixed Data Series X
  1826. * @param boolean A logical value specifying whether to force the intersect to equal 0.
  1827. * @param boolean A logical value specifying whether to return additional regression statistics.
  1828. * @return array
  1829. */
  1830. public static function LINEST($yValues, $xValues = null, $const = true, $stats = false)
  1831. {
  1832. $const = (is_null($const)) ? true : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const);
  1833. $stats = (is_null($stats)) ? false : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($stats);
  1834. if (is_null($xValues)) {
  1835. $xValues = range(1, count(PHPExcel_Calculation_Functions::flattenArray($yValues)));
  1836. }
  1837. if (!self::checkTrendArrays($yValues, $xValues)) {
  1838. return PHPExcel_Calculation_Functions::VALUE();
  1839. }
  1840. $yValueCount = count($yValues);
  1841. $xValueCount = count($xValues);
  1842. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  1843. return PHPExcel_Calculation_Functions::NA();
  1844. } elseif ($yValueCount == 1) {
  1845. return 0;
  1846. }
  1847. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues, $const);
  1848. if ($stats) {
  1849. return array(
  1850. array(
  1851. $bestFitLinear->getSlope(),
  1852. $bestFitLinear->getSlopeSE(),
  1853. $bestFitLinear->getGoodnessOfFit(),
  1854. $bestFitLinear->getF(),
  1855. $bestFitLinear->getSSRegression(),
  1856. ),
  1857. array(
  1858. $bestFitLinear->getIntersect(),
  1859. $bestFitLinear->getIntersectSE(),
  1860. $bestFitLinear->getStdevOfResiduals(),
  1861. $bestFitLinear->getDFResiduals(),
  1862. $bestFitLinear->getSSResiduals()
  1863. )
  1864. );
  1865. } else {
  1866. return array(
  1867. $bestFitLinear->getSlope(),
  1868. $bestFitLinear->getIntersect()
  1869. );
  1870. }
  1871. }
  1872. /**
  1873. * LOGEST
  1874. *
  1875. * Calculates an exponential curve that best fits the X and Y data series,
  1876. * and then returns an array that describes the line.
  1877. *
  1878. * @param array of mixed Data Series Y
  1879. * @param array of mixed Data Series X
  1880. * @param boolean A logical value specifying whether to force the intersect to equal 0.
  1881. * @param boolean A logical value specifying whether to return additional regression statistics.
  1882. * @return array
  1883. */
  1884. public static function LOGEST($yValues, $xValues = null, $const = true, $stats = false)
  1885. {
  1886. $const = (is_null($const)) ? true : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const);
  1887. $stats = (is_null($stats)) ? false : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($stats);
  1888. if (is_null($xValues)) {
  1889. $xValues = range(1, count(PHPExcel_Calculation_Functions::flattenArray($yValues)));
  1890. }
  1891. if (!self::checkTrendArrays($yValues, $xValues)) {
  1892. return PHPExcel_Calculation_Functions::VALUE();
  1893. }
  1894. $yValueCount = count($yValues);
  1895. $xValueCount = count($xValues);
  1896. foreach ($yValues as $value) {
  1897. if ($value <= 0.0) {
  1898. return PHPExcel_Calculation_Functions::NaN();
  1899. }
  1900. }
  1901. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  1902. return PHPExcel_Calculation_Functions::NA();
  1903. } elseif ($yValueCount == 1) {
  1904. return 1;
  1905. }
  1906. $bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL, $yValues, $xValues, $const);
  1907. if ($stats) {
  1908. return array(
  1909. array(
  1910. $bestFitExponential->getSlope(),
  1911. $bestFitExponential->getSlopeSE(),
  1912. $bestFitExponential->getGoodnessOfFit(),
  1913. $bestFitExponential->getF(),
  1914. $bestFitExponential->getSSRegression(),
  1915. ),
  1916. array(
  1917. $bestFitExponential->getIntersect(),
  1918. $bestFitExponential->getIntersectSE(),
  1919. $bestFitExponential->getStdevOfResiduals(),
  1920. $bestFitExponential->getDFResiduals(),
  1921. $bestFitExponential->getSSResiduals()
  1922. )
  1923. );
  1924. } else {
  1925. return array(
  1926. $bestFitExponential->getSlope(),
  1927. $bestFitExponential->getIntersect()
  1928. );
  1929. }
  1930. }
  1931. /**
  1932. * LOGINV
  1933. *
  1934. * Returns the inverse of the normal cumulative distribution
  1935. *
  1936. * @param float $probability
  1937. * @param float $mean
  1938. * @param float $stdDev
  1939. * @return float
  1940. *
  1941. * @todo Try implementing P J Acklam's refinement algorithm for greater
  1942. * accuracy if I can get my head round the mathematics
  1943. * (as described at) http://home.online.no/~pjacklam/notes/invnorm/
  1944. */
  1945. public static function LOGINV($probability, $mean, $stdDev)
  1946. {
  1947. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  1948. $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
  1949. $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
  1950. if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
  1951. if (($probability < 0) || ($probability > 1) || ($stdDev <= 0)) {
  1952. return PHPExcel_Calculation_Functions::NaN();
  1953. }
  1954. return exp($mean + $stdDev * self::NORMSINV($probability));
  1955. }
  1956. return PHPExcel_Calculation_Functions::VALUE();
  1957. }
  1958. /**
  1959. * LOGNORMDIST
  1960. *
  1961. * Returns the cumulative lognormal distribution of x, where ln(x) is normally distributed
  1962. * with parameters mean and standard_dev.
  1963. *
  1964. * @param float $value
  1965. * @param float $mean
  1966. * @param float $stdDev
  1967. * @return float
  1968. */
  1969. public static function LOGNORMDIST($value, $mean, $stdDev)
  1970. {
  1971. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  1972. $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
  1973. $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
  1974. if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
  1975. if (($value <= 0) || ($stdDev <= 0)) {
  1976. return PHPExcel_Calculation_Functions::NaN();
  1977. }
  1978. return self::NORMSDIST((log($value) - $mean) / $stdDev);
  1979. }
  1980. return PHPExcel_Calculation_Functions::VALUE();
  1981. }
  1982. /**
  1983. * MAX
  1984. *
  1985. * MAX returns the value of the element of the values passed that has the highest value,
  1986. * with negative numbers considered smaller than positive numbers.
  1987. *
  1988. * Excel Function:
  1989. * MAX(value1[,value2[, ...]])
  1990. *
  1991. * @access public
  1992. * @category Statistical Functions
  1993. * @param mixed $arg,... Data values
  1994. * @return float
  1995. */
  1996. public static function MAX()
  1997. {
  1998. $returnValue = null;
  1999. // Loop through arguments
  2000. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2001. foreach ($aArgs as $arg) {
  2002. // Is it a numeric value?
  2003. if ((is_numeric($arg)) && (!is_string($arg))) {
  2004. if ((is_null($returnValue)) || ($arg > $returnValue)) {
  2005. $returnValue = $arg;
  2006. }
  2007. }
  2008. }
  2009. if (is_null($returnValue)) {
  2010. return 0;
  2011. }
  2012. return $returnValue;
  2013. }
  2014. /**
  2015. * MAXA
  2016. *
  2017. * Returns the greatest value in a list of arguments, including numbers, text, and logical values
  2018. *
  2019. * Excel Function:
  2020. * MAXA(value1[,value2[, ...]])
  2021. *
  2022. * @access public
  2023. * @category Statistical Functions
  2024. * @param mixed $arg,... Data values
  2025. * @return float
  2026. */
  2027. public static function MAXA()
  2028. {
  2029. $returnValue = null;
  2030. // Loop through arguments
  2031. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2032. foreach ($aArgs as $arg) {
  2033. // Is it a numeric value?
  2034. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
  2035. if (is_bool($arg)) {
  2036. $arg = (integer) $arg;
  2037. } elseif (is_string($arg)) {
  2038. $arg = 0;
  2039. }
  2040. if ((is_null($returnValue)) || ($arg > $returnValue)) {
  2041. $returnValue = $arg;
  2042. }
  2043. }
  2044. }
  2045. if (is_null($returnValue)) {
  2046. return 0;
  2047. }
  2048. return $returnValue;
  2049. }
  2050. /**
  2051. * MAXIF
  2052. *
  2053. * Counts the maximum value within a range of cells that contain numbers within the list of arguments
  2054. *
  2055. * Excel Function:
  2056. * MAXIF(value1[,value2[, ...]],condition)
  2057. *
  2058. * @access public
  2059. * @category Mathematical and Trigonometric Functions
  2060. * @param mixed $arg,... Data values
  2061. * @param string $condition The criteria that defines which cells will be checked.
  2062. * @return float
  2063. */
  2064. public static function MAXIF($aArgs, $condition, $sumArgs = array())
  2065. {
  2066. $returnValue = null;
  2067. $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
  2068. $sumArgs = PHPExcel_Calculation_Functions::flattenArray($sumArgs);
  2069. if (empty($sumArgs)) {
  2070. $sumArgs = $aArgs;
  2071. }
  2072. $condition = PHPExcel_Calculation_Functions::ifCondition($condition);
  2073. // Loop through arguments
  2074. foreach ($aArgs as $key => $arg) {
  2075. if (!is_numeric($arg)) {
  2076. $arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
  2077. }
  2078. $testCondition = '='.$arg.$condition;
  2079. if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
  2080. if ((is_null($returnValue)) || ($arg > $returnValue)) {
  2081. $returnValue = $arg;
  2082. }
  2083. }
  2084. }
  2085. return $returnValue;
  2086. }
  2087. /**
  2088. * MEDIAN
  2089. *
  2090. * Returns the median of the given numbers. The median is the number in the middle of a set of numbers.
  2091. *
  2092. * Excel Function:
  2093. * MEDIAN(value1[,value2[, ...]])
  2094. *
  2095. * @access public
  2096. * @category Statistical Functions
  2097. * @param mixed $arg,... Data values
  2098. * @return float
  2099. */
  2100. public static function MEDIAN()
  2101. {
  2102. $returnValue = PHPExcel_Calculation_Functions::NaN();
  2103. $mArgs = array();
  2104. // Loop through arguments
  2105. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2106. foreach ($aArgs as $arg) {
  2107. // Is it a numeric value?
  2108. if ((is_numeric($arg)) && (!is_string($arg))) {
  2109. $mArgs[] = $arg;
  2110. }
  2111. }
  2112. $mValueCount = count($mArgs);
  2113. if ($mValueCount > 0) {
  2114. sort($mArgs, SORT_NUMERIC);
  2115. $mValueCount = $mValueCount / 2;
  2116. if ($mValueCount == floor($mValueCount)) {
  2117. $returnValue = ($mArgs[$mValueCount--] + $mArgs[$mValueCount]) / 2;
  2118. } else {
  2119. $mValueCount = floor($mValueCount);
  2120. $returnValue = $mArgs[$mValueCount];
  2121. }
  2122. }
  2123. return $returnValue;
  2124. }
  2125. /**
  2126. * MIN
  2127. *
  2128. * MIN returns the value of the element of the values passed that has the smallest value,
  2129. * with negative numbers considered smaller than positive numbers.
  2130. *
  2131. * Excel Function:
  2132. * MIN(value1[,value2[, ...]])
  2133. *
  2134. * @access public
  2135. * @category Statistical Functions
  2136. * @param mixed $arg,... Data values
  2137. * @return float
  2138. */
  2139. public static function MIN()
  2140. {
  2141. $returnValue = null;
  2142. // Loop through arguments
  2143. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2144. foreach ($aArgs as $arg) {
  2145. // Is it a numeric value?
  2146. if ((is_numeric($arg)) && (!is_string($arg))) {
  2147. if ((is_null($returnValue)) || ($arg < $returnValue)) {
  2148. $returnValue = $arg;
  2149. }
  2150. }
  2151. }
  2152. if (is_null($returnValue)) {
  2153. return 0;
  2154. }
  2155. return $returnValue;
  2156. }
  2157. /**
  2158. * MINA
  2159. *
  2160. * Returns the smallest value in a list of arguments, including numbers, text, and logical values
  2161. *
  2162. * Excel Function:
  2163. * MINA(value1[,value2[, ...]])
  2164. *
  2165. * @access public
  2166. * @category Statistical Functions
  2167. * @param mixed $arg,... Data values
  2168. * @return float
  2169. */
  2170. public static function MINA()
  2171. {
  2172. $returnValue = null;
  2173. // Loop through arguments
  2174. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2175. foreach ($aArgs as $arg) {
  2176. // Is it a numeric value?
  2177. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
  2178. if (is_bool($arg)) {
  2179. $arg = (integer) $arg;
  2180. } elseif (is_string($arg)) {
  2181. $arg = 0;
  2182. }
  2183. if ((is_null($returnValue)) || ($arg < $returnValue)) {
  2184. $returnValue = $arg;
  2185. }
  2186. }
  2187. }
  2188. if (is_null($returnValue)) {
  2189. return 0;
  2190. }
  2191. return $returnValue;
  2192. }
  2193. /**
  2194. * MINIF
  2195. *
  2196. * Returns the minimum value within a range of cells that contain numbers within the list of arguments
  2197. *
  2198. * Excel Function:
  2199. * MINIF(value1[,value2[, ...]],condition)
  2200. *
  2201. * @access public
  2202. * @category Mathematical and Trigonometric Functions
  2203. * @param mixed $arg,... Data values
  2204. * @param string $condition The criteria that defines which cells will be checked.
  2205. * @return float
  2206. */
  2207. public static function MINIF($aArgs, $condition, $sumArgs = array())
  2208. {
  2209. $returnValue = null;
  2210. $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
  2211. $sumArgs = PHPExcel_Calculation_Functions::flattenArray($sumArgs);
  2212. if (empty($sumArgs)) {
  2213. $sumArgs = $aArgs;
  2214. }
  2215. $condition = PHPExcel_Calculation_Functions::ifCondition($condition);
  2216. // Loop through arguments
  2217. foreach ($aArgs as $key => $arg) {
  2218. if (!is_numeric($arg)) {
  2219. $arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
  2220. }
  2221. $testCondition = '='.$arg.$condition;
  2222. if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
  2223. if ((is_null($returnValue)) || ($arg < $returnValue)) {
  2224. $returnValue = $arg;
  2225. }
  2226. }
  2227. }
  2228. return $returnValue;
  2229. }
  2230. //
  2231. // Special variant of array_count_values that isn't limited to strings and integers,
  2232. // but can work with floating point numbers as values
  2233. //
  2234. private static function modeCalc($data)
  2235. {
  2236. $frequencyArray = array();
  2237. foreach ($data as $datum) {
  2238. $found = false;
  2239. foreach ($frequencyArray as $key => $value) {
  2240. if ((string) $value['value'] == (string) $datum) {
  2241. ++$frequencyArray[$key]['frequency'];
  2242. $found = true;
  2243. break;
  2244. }
  2245. }
  2246. if (!$found) {
  2247. $frequencyArray[] = array(
  2248. 'value' => $datum,
  2249. 'frequency' => 1
  2250. );
  2251. }
  2252. }
  2253. foreach ($frequencyArray as $key => $value) {
  2254. $frequencyList[$key] = $value['frequency'];
  2255. $valueList[$key] = $value['value'];
  2256. }
  2257. array_multisort($frequencyList, SORT_DESC, $valueList, SORT_ASC, SORT_NUMERIC, $frequencyArray);
  2258. if ($frequencyArray[0]['frequency'] == 1) {
  2259. return PHPExcel_Calculation_Functions::NA();
  2260. }
  2261. return $frequencyArray[0]['value'];
  2262. }
  2263. /**
  2264. * MODE
  2265. *
  2266. * Returns the most frequently occurring, or repetitive, value in an array or range of data
  2267. *
  2268. * Excel Function:
  2269. * MODE(value1[,value2[, ...]])
  2270. *
  2271. * @access public
  2272. * @category Statistical Functions
  2273. * @param mixed $arg,... Data values
  2274. * @return float
  2275. */
  2276. public static function MODE()
  2277. {
  2278. $returnValue = PHPExcel_Calculation_Functions::NA();
  2279. // Loop through arguments
  2280. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2281. $mArgs = array();
  2282. foreach ($aArgs as $arg) {
  2283. // Is it a numeric value?
  2284. if ((is_numeric($arg)) && (!is_string($arg))) {
  2285. $mArgs[] = $arg;
  2286. }
  2287. }
  2288. if (!empty($mArgs)) {
  2289. return self::modeCalc($mArgs);
  2290. }
  2291. return $returnValue;
  2292. }
  2293. /**
  2294. * NEGBINOMDIST
  2295. *
  2296. * Returns the negative binomial distribution. NEGBINOMDIST returns the probability that
  2297. * there will be number_f failures before the number_s-th success, when the constant
  2298. * probability of a success is probability_s. This function is similar to the binomial
  2299. * distribution, except that the number of successes is fixed, and the number of trials is
  2300. * variable. Like the binomial, trials are assumed to be independent.
  2301. *
  2302. * @param float $failures Number of Failures
  2303. * @param float $successes Threshold number of Successes
  2304. * @param float $probability Probability of success on each trial
  2305. * @return float
  2306. *
  2307. */
  2308. public static function NEGBINOMDIST($failures, $successes, $probability)
  2309. {
  2310. $failures = floor(PHPExcel_Calculation_Functions::flattenSingleValue($failures));
  2311. $successes = floor(PHPExcel_Calculation_Functions::flattenSingleValue($successes));
  2312. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  2313. if ((is_numeric($failures)) && (is_numeric($successes)) && (is_numeric($probability))) {
  2314. if (($failures < 0) || ($successes < 1)) {
  2315. return PHPExcel_Calculation_Functions::NaN();
  2316. } elseif (($probability < 0) || ($probability > 1)) {
  2317. return PHPExcel_Calculation_Functions::NaN();
  2318. }
  2319. if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) {
  2320. if (($failures + $successes - 1) <= 0) {
  2321. return PHPExcel_Calculation_Functions::NaN();
  2322. }
  2323. }
  2324. return (PHPExcel_Calculation_MathTrig::COMBIN($failures + $successes - 1, $successes - 1)) * (pow($probability, $successes)) * (pow(1 - $probability, $failures));
  2325. }
  2326. return PHPExcel_Calculation_Functions::VALUE();
  2327. }
  2328. /**
  2329. * NORMDIST
  2330. *
  2331. * Returns the normal distribution for the specified mean and standard deviation. This
  2332. * function has a very wide range of applications in statistics, including hypothesis
  2333. * testing.
  2334. *
  2335. * @param float $value
  2336. * @param float $mean Mean Value
  2337. * @param float $stdDev Standard Deviation
  2338. * @param boolean $cumulative
  2339. * @return float
  2340. *
  2341. */
  2342. public static function NORMDIST($value, $mean, $stdDev, $cumulative)
  2343. {
  2344. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2345. $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
  2346. $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
  2347. if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
  2348. if ($stdDev < 0) {
  2349. return PHPExcel_Calculation_Functions::NaN();
  2350. }
  2351. if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
  2352. if ($cumulative) {
  2353. return 0.5 * (1 + PHPExcel_Calculation_Engineering::erfVal(($value - $mean) / ($stdDev * sqrt(2))));
  2354. } else {
  2355. return (1 / (SQRT2PI * $stdDev)) * exp(0 - (pow($value - $mean, 2) / (2 * ($stdDev * $stdDev))));
  2356. }
  2357. }
  2358. }
  2359. return PHPExcel_Calculation_Functions::VALUE();
  2360. }
  2361. /**
  2362. * NORMINV
  2363. *
  2364. * Returns the inverse of the normal cumulative distribution for the specified mean and standard deviation.
  2365. *
  2366. * @param float $value
  2367. * @param float $mean Mean Value
  2368. * @param float $stdDev Standard Deviation
  2369. * @return float
  2370. *
  2371. */
  2372. public static function NORMINV($probability, $mean, $stdDev)
  2373. {
  2374. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  2375. $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
  2376. $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
  2377. if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
  2378. if (($probability < 0) || ($probability > 1)) {
  2379. return PHPExcel_Calculation_Functions::NaN();
  2380. }
  2381. if ($stdDev < 0) {
  2382. return PHPExcel_Calculation_Functions::NaN();
  2383. }
  2384. return (self::inverseNcdf($probability) * $stdDev) + $mean;
  2385. }
  2386. return PHPExcel_Calculation_Functions::VALUE();
  2387. }
  2388. /**
  2389. * NORMSDIST
  2390. *
  2391. * Returns the standard normal cumulative distribution function. The distribution has
  2392. * a mean of 0 (zero) and a standard deviation of one. Use this function in place of a
  2393. * table of standard normal curve areas.
  2394. *
  2395. * @param float $value
  2396. * @return float
  2397. */
  2398. public static function NORMSDIST($value)
  2399. {
  2400. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2401. return self::NORMDIST($value, 0, 1, true);
  2402. }
  2403. /**
  2404. * NORMSINV
  2405. *
  2406. * Returns the inverse of the standard normal cumulative distribution
  2407. *
  2408. * @param float $value
  2409. * @return float
  2410. */
  2411. public static function NORMSINV($value)
  2412. {
  2413. return self::NORMINV($value, 0, 1);
  2414. }
  2415. /**
  2416. * PERCENTILE
  2417. *
  2418. * Returns the nth percentile of values in a range..
  2419. *
  2420. * Excel Function:
  2421. * PERCENTILE(value1[,value2[, ...]],entry)
  2422. *
  2423. * @access public
  2424. * @category Statistical Functions
  2425. * @param mixed $arg,... Data values
  2426. * @param float $entry Percentile value in the range 0..1, inclusive.
  2427. * @return float
  2428. */
  2429. public static function PERCENTILE()
  2430. {
  2431. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2432. // Calculate
  2433. $entry = array_pop($aArgs);
  2434. if ((is_numeric($entry)) && (!is_string($entry))) {
  2435. if (($entry < 0) || ($entry > 1)) {
  2436. return PHPExcel_Calculation_Functions::NaN();
  2437. }
  2438. $mArgs = array();
  2439. foreach ($aArgs as $arg) {
  2440. // Is it a numeric value?
  2441. if ((is_numeric($arg)) && (!is_string($arg))) {
  2442. $mArgs[] = $arg;
  2443. }
  2444. }
  2445. $mValueCount = count($mArgs);
  2446. if ($mValueCount > 0) {
  2447. sort($mArgs);
  2448. $count = self::COUNT($mArgs);
  2449. $index = $entry * ($count-1);
  2450. $iBase = floor($index);
  2451. if ($index == $iBase) {
  2452. return $mArgs[$index];
  2453. } else {
  2454. $iNext = $iBase + 1;
  2455. $iProportion = $index - $iBase;
  2456. return $mArgs[$iBase] + (($mArgs[$iNext] - $mArgs[$iBase]) * $iProportion) ;
  2457. }
  2458. }
  2459. }
  2460. return PHPExcel_Calculation_Functions::VALUE();
  2461. }
  2462. /**
  2463. * PERCENTRANK
  2464. *
  2465. * Returns the rank of a value in a data set as a percentage of the data set.
  2466. *
  2467. * @param array of number An array of, or a reference to, a list of numbers.
  2468. * @param number The number whose rank you want to find.
  2469. * @param number The number of significant digits for the returned percentage value.
  2470. * @return float
  2471. */
  2472. public static function PERCENTRANK($valueSet, $value, $significance = 3)
  2473. {
  2474. $valueSet = PHPExcel_Calculation_Functions::flattenArray($valueSet);
  2475. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2476. $significance = (is_null($significance)) ? 3 : (integer) PHPExcel_Calculation_Functions::flattenSingleValue($significance);
  2477. foreach ($valueSet as $key => $valueEntry) {
  2478. if (!is_numeric($valueEntry)) {
  2479. unset($valueSet[$key]);
  2480. }
  2481. }
  2482. sort($valueSet, SORT_NUMERIC);
  2483. $valueCount = count($valueSet);
  2484. if ($valueCount == 0) {
  2485. return PHPExcel_Calculation_Functions::NaN();
  2486. }
  2487. $valueAdjustor = $valueCount - 1;
  2488. if (($value < $valueSet[0]) || ($value > $valueSet[$valueAdjustor])) {
  2489. return PHPExcel_Calculation_Functions::NA();
  2490. }
  2491. $pos = array_search($value, $valueSet);
  2492. if ($pos === false) {
  2493. $pos = 0;
  2494. $testValue = $valueSet[0];
  2495. while ($testValue < $value) {
  2496. $testValue = $valueSet[++$pos];
  2497. }
  2498. --$pos;
  2499. $pos += (($value - $valueSet[$pos]) / ($testValue - $valueSet[$pos]));
  2500. }
  2501. return round($pos / $valueAdjustor, $significance);
  2502. }
  2503. /**
  2504. * PERMUT
  2505. *
  2506. * Returns the number of permutations for a given number of objects that can be
  2507. * selected from number objects. A permutation is any set or subset of objects or
  2508. * events where internal order is significant. Permutations are different from
  2509. * combinations, for which the internal order is not significant. Use this function
  2510. * for lottery-style probability calculations.
  2511. *
  2512. * @param int $numObjs Number of different objects
  2513. * @param int $numInSet Number of objects in each permutation
  2514. * @return int Number of permutations
  2515. */
  2516. public static function PERMUT($numObjs, $numInSet)
  2517. {
  2518. $numObjs = PHPExcel_Calculation_Functions::flattenSingleValue($numObjs);
  2519. $numInSet = PHPExcel_Calculation_Functions::flattenSingleValue($numInSet);
  2520. if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
  2521. $numInSet = floor($numInSet);
  2522. if ($numObjs < $numInSet) {
  2523. return PHPExcel_Calculation_Functions::NaN();
  2524. }
  2525. return round(PHPExcel_Calculation_MathTrig::FACT($numObjs) / PHPExcel_Calculation_MathTrig::FACT($numObjs - $numInSet));
  2526. }
  2527. return PHPExcel_Calculation_Functions::VALUE();
  2528. }
  2529. /**
  2530. * POISSON
  2531. *
  2532. * Returns the Poisson distribution. A common application of the Poisson distribution
  2533. * is predicting the number of events over a specific time, such as the number of
  2534. * cars arriving at a toll plaza in 1 minute.
  2535. *
  2536. * @param float $value
  2537. * @param float $mean Mean Value
  2538. * @param boolean $cumulative
  2539. * @return float
  2540. *
  2541. */
  2542. public static function POISSON($value, $mean, $cumulative)
  2543. {
  2544. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2545. $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
  2546. if ((is_numeric($value)) && (is_numeric($mean))) {
  2547. if (($value < 0) || ($mean <= 0)) {
  2548. return PHPExcel_Calculation_Functions::NaN();
  2549. }
  2550. if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
  2551. if ($cumulative) {
  2552. $summer = 0;
  2553. for ($i = 0; $i <= floor($value); ++$i) {
  2554. $summer += pow($mean, $i) / PHPExcel_Calculation_MathTrig::FACT($i);
  2555. }
  2556. return exp(0-$mean) * $summer;
  2557. } else {
  2558. return (exp(0-$mean) * pow($mean, $value)) / PHPExcel_Calculation_MathTrig::FACT($value);
  2559. }
  2560. }
  2561. }
  2562. return PHPExcel_Calculation_Functions::VALUE();
  2563. }
  2564. /**
  2565. * QUARTILE
  2566. *
  2567. * Returns the quartile of a data set.
  2568. *
  2569. * Excel Function:
  2570. * QUARTILE(value1[,value2[, ...]],entry)
  2571. *
  2572. * @access public
  2573. * @category Statistical Functions
  2574. * @param mixed $arg,... Data values
  2575. * @param int $entry Quartile value in the range 1..3, inclusive.
  2576. * @return float
  2577. */
  2578. public static function QUARTILE()
  2579. {
  2580. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2581. // Calculate
  2582. $entry = floor(array_pop($aArgs));
  2583. if ((is_numeric($entry)) && (!is_string($entry))) {
  2584. $entry /= 4;
  2585. if (($entry < 0) || ($entry > 1)) {
  2586. return PHPExcel_Calculation_Functions::NaN();
  2587. }
  2588. return self::PERCENTILE($aArgs, $entry);
  2589. }
  2590. return PHPExcel_Calculation_Functions::VALUE();
  2591. }
  2592. /**
  2593. * RANK
  2594. *
  2595. * Returns the rank of a number in a list of numbers.
  2596. *
  2597. * @param number The number whose rank you want to find.
  2598. * @param array of number An array of, or a reference to, a list of numbers.
  2599. * @param mixed Order to sort the values in the value set
  2600. * @return float
  2601. */
  2602. public static function RANK($value, $valueSet, $order = 0)
  2603. {
  2604. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2605. $valueSet = PHPExcel_Calculation_Functions::flattenArray($valueSet);
  2606. $order = (is_null($order)) ? 0 : (integer) PHPExcel_Calculation_Functions::flattenSingleValue($order);
  2607. foreach ($valueSet as $key => $valueEntry) {
  2608. if (!is_numeric($valueEntry)) {
  2609. unset($valueSet[$key]);
  2610. }
  2611. }
  2612. if ($order == 0) {
  2613. rsort($valueSet, SORT_NUMERIC);
  2614. } else {
  2615. sort($valueSet, SORT_NUMERIC);
  2616. }
  2617. $pos = array_search($value, $valueSet);
  2618. if ($pos === false) {
  2619. return PHPExcel_Calculation_Functions::NA();
  2620. }
  2621. return ++$pos;
  2622. }
  2623. /**
  2624. * RSQ
  2625. *
  2626. * Returns the square of the Pearson product moment correlation coefficient through data points in known_y's and known_x's.
  2627. *
  2628. * @param array of mixed Data Series Y
  2629. * @param array of mixed Data Series X
  2630. * @return float
  2631. */
  2632. public static function RSQ($yValues, $xValues)
  2633. {
  2634. if (!self::checkTrendArrays($yValues, $xValues)) {
  2635. return PHPExcel_Calculation_Functions::VALUE();
  2636. }
  2637. $yValueCount = count($yValues);
  2638. $xValueCount = count($xValues);
  2639. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  2640. return PHPExcel_Calculation_Functions::NA();
  2641. } elseif ($yValueCount == 1) {
  2642. return PHPExcel_Calculation_Functions::DIV0();
  2643. }
  2644. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  2645. return $bestFitLinear->getGoodnessOfFit();
  2646. }
  2647. /**
  2648. * SKEW
  2649. *
  2650. * Returns the skewness of a distribution. Skewness characterizes the degree of asymmetry
  2651. * of a distribution around its mean. Positive skewness indicates a distribution with an
  2652. * asymmetric tail extending toward more positive values. Negative skewness indicates a
  2653. * distribution with an asymmetric tail extending toward more negative values.
  2654. *
  2655. * @param array Data Series
  2656. * @return float
  2657. */
  2658. public static function SKEW()
  2659. {
  2660. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  2661. $mean = self::AVERAGE($aArgs);
  2662. $stdDev = self::STDEV($aArgs);
  2663. $count = $summer = 0;
  2664. // Loop through arguments
  2665. foreach ($aArgs as $k => $arg) {
  2666. if ((is_bool($arg)) &&
  2667. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  2668. } else {
  2669. // Is it a numeric value?
  2670. if ((is_numeric($arg)) && (!is_string($arg))) {
  2671. $summer += pow((($arg - $mean) / $stdDev), 3);
  2672. ++$count;
  2673. }
  2674. }
  2675. }
  2676. if ($count > 2) {
  2677. return $summer * ($count / (($count-1) * ($count-2)));
  2678. }
  2679. return PHPExcel_Calculation_Functions::DIV0();
  2680. }
  2681. /**
  2682. * SLOPE
  2683. *
  2684. * Returns the slope of the linear regression line through data points in known_y's and known_x's.
  2685. *
  2686. * @param array of mixed Data Series Y
  2687. * @param array of mixed Data Series X
  2688. * @return float
  2689. */
  2690. public static function SLOPE($yValues, $xValues)
  2691. {
  2692. if (!self::checkTrendArrays($yValues, $xValues)) {
  2693. return PHPExcel_Calculation_Functions::VALUE();
  2694. }
  2695. $yValueCount = count($yValues);
  2696. $xValueCount = count($xValues);
  2697. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  2698. return PHPExcel_Calculation_Functions::NA();
  2699. } elseif ($yValueCount == 1) {
  2700. return PHPExcel_Calculation_Functions::DIV0();
  2701. }
  2702. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  2703. return $bestFitLinear->getSlope();
  2704. }
  2705. /**
  2706. * SMALL
  2707. *
  2708. * Returns the nth smallest value in a data set. You can use this function to
  2709. * select a value based on its relative standing.
  2710. *
  2711. * Excel Function:
  2712. * SMALL(value1[,value2[, ...]],entry)
  2713. *
  2714. * @access public
  2715. * @category Statistical Functions
  2716. * @param mixed $arg,... Data values
  2717. * @param int $entry Position (ordered from the smallest) in the array or range of data to return
  2718. * @return float
  2719. */
  2720. public static function SMALL()
  2721. {
  2722. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2723. // Calculate
  2724. $entry = array_pop($aArgs);
  2725. if ((is_numeric($entry)) && (!is_string($entry))) {
  2726. $mArgs = array();
  2727. foreach ($aArgs as $arg) {
  2728. // Is it a numeric value?
  2729. if ((is_numeric($arg)) && (!is_string($arg))) {
  2730. $mArgs[] = $arg;
  2731. }
  2732. }
  2733. $count = self::COUNT($mArgs);
  2734. $entry = floor(--$entry);
  2735. if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
  2736. return PHPExcel_Calculation_Functions::NaN();
  2737. }
  2738. sort($mArgs);
  2739. return $mArgs[$entry];
  2740. }
  2741. return PHPExcel_Calculation_Functions::VALUE();
  2742. }
  2743. /**
  2744. * STANDARDIZE
  2745. *
  2746. * Returns a normalized value from a distribution characterized by mean and standard_dev.
  2747. *
  2748. * @param float $value Value to normalize
  2749. * @param float $mean Mean Value
  2750. * @param float $stdDev Standard Deviation
  2751. * @return float Standardized value
  2752. */
  2753. public static function STANDARDIZE($value, $mean, $stdDev)
  2754. {
  2755. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2756. $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
  2757. $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
  2758. if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
  2759. if ($stdDev <= 0) {
  2760. return PHPExcel_Calculation_Functions::NaN();
  2761. }
  2762. return ($value - $mean) / $stdDev ;
  2763. }
  2764. return PHPExcel_Calculation_Functions::VALUE();
  2765. }
  2766. /**
  2767. * STDEV
  2768. *
  2769. * Estimates standard deviation based on a sample. The standard deviation is a measure of how
  2770. * widely values are dispersed from the average value (the mean).
  2771. *
  2772. * Excel Function:
  2773. * STDEV(value1[,value2[, ...]])
  2774. *
  2775. * @access public
  2776. * @category Statistical Functions
  2777. * @param mixed $arg,... Data values
  2778. * @return float
  2779. */
  2780. public static function STDEV()
  2781. {
  2782. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  2783. // Return value
  2784. $returnValue = null;
  2785. $aMean = self::AVERAGE($aArgs);
  2786. if (!is_null($aMean)) {
  2787. $aCount = -1;
  2788. foreach ($aArgs as $k => $arg) {
  2789. if ((is_bool($arg)) &&
  2790. ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
  2791. $arg = (integer) $arg;
  2792. }
  2793. // Is it a numeric value?
  2794. if ((is_numeric($arg)) && (!is_string($arg))) {
  2795. if (is_null($returnValue)) {
  2796. $returnValue = pow(($arg - $aMean), 2);
  2797. } else {
  2798. $returnValue += pow(($arg - $aMean), 2);
  2799. }
  2800. ++$aCount;
  2801. }
  2802. }
  2803. // Return
  2804. if (($aCount > 0) && ($returnValue >= 0)) {
  2805. return sqrt($returnValue / $aCount);
  2806. }
  2807. }
  2808. return PHPExcel_Calculation_Functions::DIV0();
  2809. }
  2810. /**
  2811. * STDEVA
  2812. *
  2813. * Estimates standard deviation based on a sample, including numbers, text, and logical values
  2814. *
  2815. * Excel Function:
  2816. * STDEVA(value1[,value2[, ...]])
  2817. *
  2818. * @access public
  2819. * @category Statistical Functions
  2820. * @param mixed $arg,... Data values
  2821. * @return float
  2822. */
  2823. public static function STDEVA()
  2824. {
  2825. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  2826. $returnValue = null;
  2827. $aMean = self::AVERAGEA($aArgs);
  2828. if (!is_null($aMean)) {
  2829. $aCount = -1;
  2830. foreach ($aArgs as $k => $arg) {
  2831. if ((is_bool($arg)) &&
  2832. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  2833. } else {
  2834. // Is it a numeric value?
  2835. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
  2836. if (is_bool($arg)) {
  2837. $arg = (integer) $arg;
  2838. } elseif (is_string($arg)) {
  2839. $arg = 0;
  2840. }
  2841. if (is_null($returnValue)) {
  2842. $returnValue = pow(($arg - $aMean), 2);
  2843. } else {
  2844. $returnValue += pow(($arg - $aMean), 2);
  2845. }
  2846. ++$aCount;
  2847. }
  2848. }
  2849. }
  2850. if (($aCount > 0) && ($returnValue >= 0)) {
  2851. return sqrt($returnValue / $aCount);
  2852. }
  2853. }
  2854. return PHPExcel_Calculation_Functions::DIV0();
  2855. }
  2856. /**
  2857. * STDEVP
  2858. *
  2859. * Calculates standard deviation based on the entire population
  2860. *
  2861. * Excel Function:
  2862. * STDEVP(value1[,value2[, ...]])
  2863. *
  2864. * @access public
  2865. * @category Statistical Functions
  2866. * @param mixed $arg,... Data values
  2867. * @return float
  2868. */
  2869. public static function STDEVP()
  2870. {
  2871. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  2872. $returnValue = null;
  2873. $aMean = self::AVERAGE($aArgs);
  2874. if (!is_null($aMean)) {
  2875. $aCount = 0;
  2876. foreach ($aArgs as $k => $arg) {
  2877. if ((is_bool($arg)) &&
  2878. ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
  2879. $arg = (integer) $arg;
  2880. }
  2881. // Is it a numeric value?
  2882. if ((is_numeric($arg)) && (!is_string($arg))) {
  2883. if (is_null($returnValue)) {
  2884. $returnValue = pow(($arg - $aMean), 2);
  2885. } else {
  2886. $returnValue += pow(($arg - $aMean), 2);
  2887. }
  2888. ++$aCount;
  2889. }
  2890. }
  2891. if (($aCount > 0) && ($returnValue >= 0)) {
  2892. return sqrt($returnValue / $aCount);
  2893. }
  2894. }
  2895. return PHPExcel_Calculation_Functions::DIV0();
  2896. }
  2897. /**
  2898. * STDEVPA
  2899. *
  2900. * Calculates standard deviation based on the entire population, including numbers, text, and logical values
  2901. *
  2902. * Excel Function:
  2903. * STDEVPA(value1[,value2[, ...]])
  2904. *
  2905. * @access public
  2906. * @category Statistical Functions
  2907. * @param mixed $arg,... Data values
  2908. * @return float
  2909. */
  2910. public static function STDEVPA()
  2911. {
  2912. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  2913. $returnValue = null;
  2914. $aMean = self::AVERAGEA($aArgs);
  2915. if (!is_null($aMean)) {
  2916. $aCount = 0;
  2917. foreach ($aArgs as $k => $arg) {
  2918. if ((is_bool($arg)) &&
  2919. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  2920. } else {
  2921. // Is it a numeric value?
  2922. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
  2923. if (is_bool($arg)) {
  2924. $arg = (integer) $arg;
  2925. } elseif (is_string($arg)) {
  2926. $arg = 0;
  2927. }
  2928. if (is_null($returnValue)) {
  2929. $returnValue = pow(($arg - $aMean), 2);
  2930. } else {
  2931. $returnValue += pow(($arg - $aMean), 2);
  2932. }
  2933. ++$aCount;
  2934. }
  2935. }
  2936. }
  2937. if (($aCount > 0) && ($returnValue >= 0)) {
  2938. return sqrt($returnValue / $aCount);
  2939. }
  2940. }
  2941. return PHPExcel_Calculation_Functions::DIV0();
  2942. }
  2943. /**
  2944. * STEYX
  2945. *
  2946. * Returns the standard error of the predicted y-value for each x in the regression.
  2947. *
  2948. * @param array of mixed Data Series Y
  2949. * @param array of mixed Data Series X
  2950. * @return float
  2951. */
  2952. public static function STEYX($yValues, $xValues)
  2953. {
  2954. if (!self::checkTrendArrays($yValues, $xValues)) {
  2955. return PHPExcel_Calculation_Functions::VALUE();
  2956. }
  2957. $yValueCount = count($yValues);
  2958. $xValueCount = count($xValues);
  2959. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  2960. return PHPExcel_Calculation_Functions::NA();
  2961. } elseif ($yValueCount == 1) {
  2962. return PHPExcel_Calculation_Functions::DIV0();
  2963. }
  2964. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  2965. return $bestFitLinear->getStdevOfResiduals();
  2966. }
  2967. /**
  2968. * TDIST
  2969. *
  2970. * Returns the probability of Student's T distribution.
  2971. *
  2972. * @param float $value Value for the function
  2973. * @param float $degrees degrees of freedom
  2974. * @param float $tails number of tails (1 or 2)
  2975. * @return float
  2976. */
  2977. public static function TDIST($value, $degrees, $tails)
  2978. {
  2979. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2980. $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees));
  2981. $tails = floor(PHPExcel_Calculation_Functions::flattenSingleValue($tails));
  2982. if ((is_numeric($value)) && (is_numeric($degrees)) && (is_numeric($tails))) {
  2983. if (($value < 0) || ($degrees < 1) || ($tails < 1) || ($tails > 2)) {
  2984. return PHPExcel_Calculation_Functions::NaN();
  2985. }
  2986. // tdist, which finds the probability that corresponds to a given value
  2987. // of t with k degrees of freedom. This algorithm is translated from a
  2988. // pascal function on p81 of "Statistical Computing in Pascal" by D
  2989. // Cooke, A H Craven & G M Clark (1985: Edward Arnold (Pubs.) Ltd:
  2990. // London). The above Pascal algorithm is itself a translation of the
  2991. // fortran algoritm "AS 3" by B E Cooper of the Atlas Computer
  2992. // Laboratory as reported in (among other places) "Applied Statistics
  2993. // Algorithms", editied by P Griffiths and I D Hill (1985; Ellis
  2994. // Horwood Ltd.; W. Sussex, England).
  2995. $tterm = $degrees;
  2996. $ttheta = atan2($value, sqrt($tterm));
  2997. $tc = cos($ttheta);
  2998. $ts = sin($ttheta);
  2999. $tsum = 0;
  3000. if (($degrees % 2) == 1) {
  3001. $ti = 3;
  3002. $tterm = $tc;
  3003. } else {
  3004. $ti = 2;
  3005. $tterm = 1;
  3006. }
  3007. $tsum = $tterm;
  3008. while ($ti < $degrees) {
  3009. $tterm *= $tc * $tc * ($ti - 1) / $ti;
  3010. $tsum += $tterm;
  3011. $ti += 2;
  3012. }
  3013. $tsum *= $ts;
  3014. if (($degrees % 2) == 1) {
  3015. $tsum = M_2DIVPI * ($tsum + $ttheta);
  3016. }
  3017. $tValue = 0.5 * (1 + $tsum);
  3018. if ($tails == 1) {
  3019. return 1 - abs($tValue);
  3020. } else {
  3021. return 1 - abs((1 - $tValue) - $tValue);
  3022. }
  3023. }
  3024. return PHPExcel_Calculation_Functions::VALUE();
  3025. }
  3026. /**
  3027. * TINV
  3028. *
  3029. * Returns the one-tailed probability of the chi-squared distribution.
  3030. *
  3031. * @param float $probability Probability for the function
  3032. * @param float $degrees degrees of freedom
  3033. * @return float
  3034. */
  3035. public static function TINV($probability, $degrees)
  3036. {
  3037. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  3038. $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees));
  3039. if ((is_numeric($probability)) && (is_numeric($degrees))) {
  3040. $xLo = 100;
  3041. $xHi = 0;
  3042. $x = $xNew = 1;
  3043. $dx = 1;
  3044. $i = 0;
  3045. while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
  3046. // Apply Newton-Raphson step
  3047. $result = self::TDIST($x, $degrees, 2);
  3048. $error = $result - $probability;
  3049. if ($error == 0.0) {
  3050. $dx = 0;
  3051. } elseif ($error < 0.0) {
  3052. $xLo = $x;
  3053. } else {
  3054. $xHi = $x;
  3055. }
  3056. // Avoid division by zero
  3057. if ($result != 0.0) {
  3058. $dx = $error / $result;
  3059. $xNew = $x - $dx;
  3060. }
  3061. // If the NR fails to converge (which for example may be the
  3062. // case if the initial guess is too rough) we apply a bisection
  3063. // step to determine a more narrow interval around the root.
  3064. if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) {
  3065. $xNew = ($xLo + $xHi) / 2;
  3066. $dx = $xNew - $x;
  3067. }
  3068. $x = $xNew;
  3069. }
  3070. if ($i == MAX_ITERATIONS) {
  3071. return PHPExcel_Calculation_Functions::NA();
  3072. }
  3073. return round($x, 12);
  3074. }
  3075. return PHPExcel_Calculation_Functions::VALUE();
  3076. }
  3077. /**
  3078. * TREND
  3079. *
  3080. * Returns values along a linear trend
  3081. *
  3082. * @param array of mixed Data Series Y
  3083. * @param array of mixed Data Series X
  3084. * @param array of mixed Values of X for which we want to find Y
  3085. * @param boolean A logical value specifying whether to force the intersect to equal 0.
  3086. * @return array of float
  3087. */
  3088. public static function TREND($yValues, $xValues = array(), $newValues = array(), $const = true)
  3089. {
  3090. $yValues = PHPExcel_Calculation_Functions::flattenArray($yValues);
  3091. $xValues = PHPExcel_Calculation_Functions::flattenArray($xValues);
  3092. $newValues = PHPExcel_Calculation_Functions::flattenArray($newValues);
  3093. $const = (is_null($const)) ? true : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const);
  3094. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues, $const);
  3095. if (empty($newValues)) {
  3096. $newValues = $bestFitLinear->getXValues();
  3097. }
  3098. $returnArray = array();
  3099. foreach ($newValues as $xValue) {
  3100. $returnArray[0][] = $bestFitLinear->getValueOfYForX($xValue);
  3101. }
  3102. return $returnArray;
  3103. }
  3104. /**
  3105. * TRIMMEAN
  3106. *
  3107. * Returns the mean of the interior of a data set. TRIMMEAN calculates the mean
  3108. * taken by excluding a percentage of data points from the top and bottom tails
  3109. * of a data set.
  3110. *
  3111. * Excel Function:
  3112. * TRIMEAN(value1[,value2[, ...]], $discard)
  3113. *
  3114. * @access public
  3115. * @category Statistical Functions
  3116. * @param mixed $arg,... Data values
  3117. * @param float $discard Percentage to discard
  3118. * @return float
  3119. */
  3120. public static function TRIMMEAN()
  3121. {
  3122. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  3123. // Calculate
  3124. $percent = array_pop($aArgs);
  3125. if ((is_numeric($percent)) && (!is_string($percent))) {
  3126. if (($percent < 0) || ($percent > 1)) {
  3127. return PHPExcel_Calculation_Functions::NaN();
  3128. }
  3129. $mArgs = array();
  3130. foreach ($aArgs as $arg) {
  3131. // Is it a numeric value?
  3132. if ((is_numeric($arg)) && (!is_string($arg))) {
  3133. $mArgs[] = $arg;
  3134. }
  3135. }
  3136. $discard = floor(self::COUNT($mArgs) * $percent / 2);
  3137. sort($mArgs);
  3138. for ($i=0; $i < $discard; ++$i) {
  3139. array_pop($mArgs);
  3140. array_shift($mArgs);
  3141. }
  3142. return self::AVERAGE($mArgs);
  3143. }
  3144. return PHPExcel_Calculation_Functions::VALUE();
  3145. }
  3146. /**
  3147. * VARFunc
  3148. *
  3149. * Estimates variance based on a sample.
  3150. *
  3151. * Excel Function:
  3152. * VAR(value1[,value2[, ...]])
  3153. *
  3154. * @access public
  3155. * @category Statistical Functions
  3156. * @param mixed $arg,... Data values
  3157. * @return float
  3158. */
  3159. public static function VARFunc()
  3160. {
  3161. $returnValue = PHPExcel_Calculation_Functions::DIV0();
  3162. $summerA = $summerB = 0;
  3163. // Loop through arguments
  3164. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  3165. $aCount = 0;
  3166. foreach ($aArgs as $arg) {
  3167. if (is_bool($arg)) {
  3168. $arg = (integer) $arg;
  3169. }
  3170. // Is it a numeric value?
  3171. if ((is_numeric($arg)) && (!is_string($arg))) {
  3172. $summerA += ($arg * $arg);
  3173. $summerB += $arg;
  3174. ++$aCount;
  3175. }
  3176. }
  3177. if ($aCount > 1) {
  3178. $summerA *= $aCount;
  3179. $summerB *= $summerB;
  3180. $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
  3181. }
  3182. return $returnValue;
  3183. }
  3184. /**
  3185. * VARA
  3186. *
  3187. * Estimates variance based on a sample, including numbers, text, and logical values
  3188. *
  3189. * Excel Function:
  3190. * VARA(value1[,value2[, ...]])
  3191. *
  3192. * @access public
  3193. * @category Statistical Functions
  3194. * @param mixed $arg,... Data values
  3195. * @return float
  3196. */
  3197. public static function VARA()
  3198. {
  3199. $returnValue = PHPExcel_Calculation_Functions::DIV0();
  3200. $summerA = $summerB = 0;
  3201. // Loop through arguments
  3202. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  3203. $aCount = 0;
  3204. foreach ($aArgs as $k => $arg) {
  3205. if ((is_string($arg)) &&
  3206. (PHPExcel_Calculation_Functions::isValue($k))) {
  3207. return PHPExcel_Calculation_Functions::VALUE();
  3208. } elseif ((is_string($arg)) &&
  3209. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  3210. } else {
  3211. // Is it a numeric value?
  3212. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
  3213. if (is_bool($arg)) {
  3214. $arg = (integer) $arg;
  3215. } elseif (is_string($arg)) {
  3216. $arg = 0;
  3217. }
  3218. $summerA += ($arg * $arg);
  3219. $summerB += $arg;
  3220. ++$aCount;
  3221. }
  3222. }
  3223. }
  3224. if ($aCount > 1) {
  3225. $summerA *= $aCount;
  3226. $summerB *= $summerB;
  3227. $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
  3228. }
  3229. return $returnValue;
  3230. }
  3231. /**
  3232. * VARP
  3233. *
  3234. * Calculates variance based on the entire population
  3235. *
  3236. * Excel Function:
  3237. * VARP(value1[,value2[, ...]])
  3238. *
  3239. * @access public
  3240. * @category Statistical Functions
  3241. * @param mixed $arg,... Data values
  3242. * @return float
  3243. */
  3244. public static function VARP()
  3245. {
  3246. // Return value
  3247. $returnValue = PHPExcel_Calculation_Functions::DIV0();
  3248. $summerA = $summerB = 0;
  3249. // Loop through arguments
  3250. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  3251. $aCount = 0;
  3252. foreach ($aArgs as $arg) {
  3253. if (is_bool($arg)) {
  3254. $arg = (integer) $arg;
  3255. }
  3256. // Is it a numeric value?
  3257. if ((is_numeric($arg)) && (!is_string($arg))) {
  3258. $summerA += ($arg * $arg);
  3259. $summerB += $arg;
  3260. ++$aCount;
  3261. }
  3262. }
  3263. if ($aCount > 0) {
  3264. $summerA *= $aCount;
  3265. $summerB *= $summerB;
  3266. $returnValue = ($summerA - $summerB) / ($aCount * $aCount);
  3267. }
  3268. return $returnValue;
  3269. }
  3270. /**
  3271. * VARPA
  3272. *
  3273. * Calculates variance based on the entire population, including numbers, text, and logical values
  3274. *
  3275. * Excel Function:
  3276. * VARPA(value1[,value2[, ...]])
  3277. *
  3278. * @access public
  3279. * @category Statistical Functions
  3280. * @param mixed $arg,... Data values
  3281. * @return float
  3282. */
  3283. public static function VARPA()
  3284. {
  3285. $returnValue = PHPExcel_Calculation_Functions::DIV0();
  3286. $summerA = $summerB = 0;
  3287. // Loop through arguments
  3288. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  3289. $aCount = 0;
  3290. foreach ($aArgs as $k => $arg) {
  3291. if ((is_string($arg)) &&
  3292. (PHPExcel_Calculation_Functions::isValue($k))) {
  3293. return PHPExcel_Calculation_Functions::VALUE();
  3294. } elseif ((is_string($arg)) &&
  3295. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  3296. } else {
  3297. // Is it a numeric value?
  3298. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
  3299. if (is_bool($arg)) {
  3300. $arg = (integer) $arg;
  3301. } elseif (is_string($arg)) {
  3302. $arg = 0;
  3303. }
  3304. $summerA += ($arg * $arg);
  3305. $summerB += $arg;
  3306. ++$aCount;
  3307. }
  3308. }
  3309. }
  3310. if ($aCount > 0) {
  3311. $summerA *= $aCount;
  3312. $summerB *= $summerB;
  3313. $returnValue = ($summerA - $summerB) / ($aCount * $aCount);
  3314. }
  3315. return $returnValue;
  3316. }
  3317. /**
  3318. * WEIBULL
  3319. *
  3320. * Returns the Weibull distribution. Use this distribution in reliability
  3321. * analysis, such as calculating a device's mean time to failure.
  3322. *
  3323. * @param float $value
  3324. * @param float $alpha Alpha Parameter
  3325. * @param float $beta Beta Parameter
  3326. * @param boolean $cumulative
  3327. * @return float
  3328. *
  3329. */
  3330. public static function WEIBULL($value, $alpha, $beta, $cumulative)
  3331. {
  3332. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  3333. $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
  3334. $beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta);
  3335. if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta))) {
  3336. if (($value < 0) || ($alpha <= 0) || ($beta <= 0)) {
  3337. return PHPExcel_Calculation_Functions::NaN();
  3338. }
  3339. if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
  3340. if ($cumulative) {
  3341. return 1 - exp(0 - pow($value / $beta, $alpha));
  3342. } else {
  3343. return ($alpha / pow($beta, $alpha)) * pow($value, $alpha - 1) * exp(0 - pow($value / $beta, $alpha));
  3344. }
  3345. }
  3346. }
  3347. return PHPExcel_Calculation_Functions::VALUE();
  3348. }
  3349. /**
  3350. * ZTEST
  3351. *
  3352. * Returns the Weibull distribution. Use this distribution in reliability
  3353. * analysis, such as calculating a device's mean time to failure.
  3354. *
  3355. * @param float $dataSet
  3356. * @param float $m0 Alpha Parameter
  3357. * @param float $sigma Beta Parameter
  3358. * @param boolean $cumulative
  3359. * @return float
  3360. *
  3361. */
  3362. public static function ZTEST($dataSet, $m0, $sigma = null)
  3363. {
  3364. $dataSet = PHPExcel_Calculation_Functions::flattenArrayIndexed($dataSet);
  3365. $m0 = PHPExcel_Calculation_Functions::flattenSingleValue($m0);
  3366. $sigma = PHPExcel_Calculation_Functions::flattenSingleValue($sigma);
  3367. if (is_null($sigma)) {
  3368. $sigma = self::STDEV($dataSet);
  3369. }
  3370. $n = count($dataSet);
  3371. return 1 - self::NORMSDIST((self::AVERAGE($dataSet) - $m0) / ($sigma / SQRT($n)));
  3372. }
  3373. }