1: <?php
2: /**
3: * PHPExcel
4: *
5: * Copyright (c) 2006 - 2014 PHPExcel
6: *
7: * This library is free software; you can redistribute it and/or
8: * modify it under the terms of the GNU Lesser General Public
9: * License as published by the Free Software Foundation; either
10: * version 2.1 of the License, or (at your option) any later version.
11: *
12: * This library is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: * Lesser General Public License for more details.
16: *
17: * You should have received a copy of the GNU Lesser General Public
18: * License along with this library; if not, write to the Free Software
19: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20: *
21: * @category PHPExcel
22: * @package PHPExcel_Shared_Trend
23: * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
24: * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
25: * @version 1.8.0, 2014-03-02
26: */
27:
28:
29: require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/linearBestFitClass.php';
30: require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/logarithmicBestFitClass.php';
31: require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/exponentialBestFitClass.php';
32: require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/powerBestFitClass.php';
33: require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/polynomialBestFitClass.php';
34:
35:
36: /**
37: * PHPExcel_trendClass
38: *
39: * @category PHPExcel
40: * @package PHPExcel_Shared_Trend
41: * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
42: */
43: class trendClass
44: {
45: const TREND_LINEAR = 'Linear';
46: const TREND_LOGARITHMIC = 'Logarithmic';
47: const TREND_EXPONENTIAL = 'Exponential';
48: const TREND_POWER = 'Power';
49: const TREND_POLYNOMIAL_2 = 'Polynomial_2';
50: const TREND_POLYNOMIAL_3 = 'Polynomial_3';
51: const TREND_POLYNOMIAL_4 = 'Polynomial_4';
52: const TREND_POLYNOMIAL_5 = 'Polynomial_5';
53: const TREND_POLYNOMIAL_6 = 'Polynomial_6';
54: const TREND_BEST_FIT = 'Bestfit';
55: const TREND_BEST_FIT_NO_POLY = 'Bestfit_no_Polynomials';
56:
57: /**
58: * Names of the best-fit trend analysis methods
59: *
60: * @var string[]
61: **/
62: private static $_trendTypes = array( self::TREND_LINEAR,
63: self::TREND_LOGARITHMIC,
64: self::TREND_EXPONENTIAL,
65: self::TREND_POWER
66: );
67: /**
68: * Names of the best-fit trend polynomial orders
69: *
70: * @var string[]
71: **/
72: private static $_trendTypePolyOrders = array( self::TREND_POLYNOMIAL_2,
73: self::TREND_POLYNOMIAL_3,
74: self::TREND_POLYNOMIAL_4,
75: self::TREND_POLYNOMIAL_5,
76: self::TREND_POLYNOMIAL_6
77: );
78:
79: /**
80: * Cached results for each method when trying to identify which provides the best fit
81: *
82: * @var PHPExcel_Best_Fit[]
83: **/
84: private static $_trendCache = array();
85:
86:
87: public static function calculate($trendType=self::TREND_BEST_FIT, $yValues, $xValues=array(), $const=True) {
88: // Calculate number of points in each dataset
89: $nY = count($yValues);
90: $nX = count($xValues);
91:
92: // Define X Values if necessary
93: if ($nX == 0) {
94: $xValues = range(1,$nY);
95: $nX = $nY;
96: } elseif ($nY != $nX) {
97: // Ensure both arrays of points are the same size
98: trigger_error("trend(): Number of elements in coordinate arrays do not match.", E_USER_ERROR);
99: }
100:
101: $key = md5($trendType.$const.serialize($yValues).serialize($xValues));
102: // Determine which trend method has been requested
103: switch ($trendType) {
104: // Instantiate and return the class for the requested trend method
105: case self::TREND_LINEAR :
106: case self::TREND_LOGARITHMIC :
107: case self::TREND_EXPONENTIAL :
108: case self::TREND_POWER :
109: if (!isset(self::$_trendCache[$key])) {
110: $className = 'PHPExcel_'.$trendType.'_Best_Fit';
111: self::$_trendCache[$key] = new $className($yValues,$xValues,$const);
112: }
113: return self::$_trendCache[$key];
114: break;
115: case self::TREND_POLYNOMIAL_2 :
116: case self::TREND_POLYNOMIAL_3 :
117: case self::TREND_POLYNOMIAL_4 :
118: case self::TREND_POLYNOMIAL_5 :
119: case self::TREND_POLYNOMIAL_6 :
120: if (!isset(self::$_trendCache[$key])) {
121: $order = substr($trendType,-1);
122: self::$_trendCache[$key] = new PHPExcel_Polynomial_Best_Fit($order,$yValues,$xValues,$const);
123: }
124: return self::$_trendCache[$key];
125: break;
126: case self::TREND_BEST_FIT :
127: case self::TREND_BEST_FIT_NO_POLY :
128: // If the request is to determine the best fit regression, then we test each trend line in turn
129: // Start by generating an instance of each available trend method
130: foreach(self::$_trendTypes as $trendMethod) {
131: $className = 'PHPExcel_'.$trendMethod.'BestFit';
132: $bestFit[$trendMethod] = new $className($yValues,$xValues,$const);
133: $bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit();
134: }
135: if ($trendType != self::TREND_BEST_FIT_NO_POLY) {
136: foreach(self::$_trendTypePolyOrders as $trendMethod) {
137: $order = substr($trendMethod,-1);
138: $bestFit[$trendMethod] = new PHPExcel_Polynomial_Best_Fit($order,$yValues,$xValues,$const);
139: if ($bestFit[$trendMethod]->getError()) {
140: unset($bestFit[$trendMethod]);
141: } else {
142: $bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit();
143: }
144: }
145: }
146: // Determine which of our trend lines is the best fit, and then we return the instance of that trend class
147: arsort($bestFitValue);
148: $bestFitType = key($bestFitValue);
149: return $bestFit[$bestFitType];
150: break;
151: default :
152: return false;
153: }
154: } // function calculate()
155:
156: } // class trendClass