Overview

Packages

  • JAMA
  • None
  • PHP
  • PHPExcel
    • CachedObjectStorage
    • Calculation
    • Cell
    • Chart
      • Renderer
    • Reader
      • Excel2007
      • Excel5
    • RichText
    • Settings
    • Shared
      • Escher
      • OLE
      • Trend
      • ZipArchive
    • Style
    • Worksheet
      • Drawing
    • Writer
      • 2007
      • CSV
      • Excel2007
      • Excel5
      • HTML
      • PDF

Classes

  • CholeskyDecomposition
  • Dao
  • DateTime
  • DateTimeZone
  • DOMNode
  • EigenvalueDecomposition
  • Elemento
  • Historial
  • Irradiacion
  • Latitud
  • MotorPhp
  • Panel
  • PclZip
  • Periodo
  • PHPExcel
  • PHPExcel_Autoloader
  • PHPExcel_Best_Fit
  • PHPExcel_CachedObjectStorage_APC
  • PHPExcel_CachedObjectStorage_CacheBase
  • PHPExcel_CachedObjectStorage_DiscISAM
  • PHPExcel_CachedObjectStorage_Igbinary
  • PHPExcel_CachedObjectStorage_Memcache
  • PHPExcel_CachedObjectStorage_Memory
  • PHPExcel_CachedObjectStorage_MemoryGZip
  • PHPExcel_CachedObjectStorage_MemorySerialized
  • PHPExcel_CachedObjectStorage_PHPTemp
  • PHPExcel_CachedObjectStorage_SQLite
  • PHPExcel_CachedObjectStorage_SQLite3
  • PHPExcel_CachedObjectStorage_Wincache
  • PHPExcel_CachedObjectStorageFactory
  • PHPExcel_CalcEngine_CyclicReferenceStack
  • PHPExcel_CalcEngine_Logger
  • PHPExcel_Calculation
  • PHPExcel_Calculation_Database
  • PHPExcel_Calculation_DateTime
  • PHPExcel_Calculation_Engineering
  • PHPExcel_Calculation_ExceptionHandler
  • PHPExcel_Calculation_Financial
  • PHPExcel_Calculation_FormulaParser
  • PHPExcel_Calculation_FormulaToken
  • PHPExcel_Calculation_Function
  • PHPExcel_Calculation_Functions
  • PHPExcel_Calculation_Logical
  • PHPExcel_Calculation_LookupRef
  • PHPExcel_Calculation_MathTrig
  • PHPExcel_Calculation_Statistical
  • PHPExcel_Calculation_TextData
  • PHPExcel_Calculation_Token_Stack
  • PHPExcel_Cell
  • PHPExcel_Cell_AdvancedValueBinder
  • PHPExcel_Cell_DataType
  • PHPExcel_Cell_DataValidation
  • PHPExcel_Cell_DefaultValueBinder
  • PHPExcel_Cell_Hyperlink
  • PHPExcel_Chart
  • PHPExcel_Chart_DataSeries
  • PHPExcel_Chart_DataSeriesValues
  • PHPExcel_Chart_Layout
  • PHPExcel_Chart_Legend
  • PHPExcel_Chart_PlotArea
  • PHPExcel_Chart_Renderer_jpgraph
  • PHPExcel_Chart_Title
  • PHPExcel_Comment
  • PHPExcel_DocumentProperties
  • PHPExcel_DocumentSecurity
  • PHPExcel_Exponential_Best_Fit
  • PHPExcel_HashTable
  • PHPExcel_IOFactory
  • PHPExcel_Linear_Best_Fit
  • PHPExcel_Logarithmic_Best_Fit
  • PHPExcel_NamedRange
  • PHPExcel_Polynomial_Best_Fit
  • PHPExcel_Power_Best_Fit
  • PHPExcel_Reader_Abstract
  • PHPExcel_Reader_CSV
  • PHPExcel_Reader_DefaultReadFilter
  • PHPExcel_Reader_Excel2003XML
  • PHPExcel_Reader_Excel2007
  • PHPExcel_Reader_Excel2007_Chart
  • PHPExcel_Reader_Excel2007_Theme
  • PHPExcel_Reader_Excel5
  • PHPExcel_Reader_Excel5_Escher
  • PHPExcel_Reader_Excel5_MD5
  • PHPExcel_Reader_Excel5_RC4
  • PHPExcel_Reader_Gnumeric
  • PHPExcel_Reader_HTML
  • PHPExcel_Reader_OOCalc
  • PHPExcel_Reader_SYLK
  • PHPExcel_ReferenceHelper
  • PHPExcel_RichText
  • PHPExcel_RichText_Run
  • PHPExcel_RichText_TextElement
  • PHPExcel_Settings
  • PHPExcel_Shared_CodePage
  • PHPExcel_Shared_Date
  • PHPExcel_Shared_Drawing
  • PHPExcel_Shared_Escher
  • PHPExcel_Shared_Escher_DgContainer
  • PHPExcel_Shared_Escher_DgContainer_SpgrContainer
  • PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer
  • PHPExcel_Shared_Escher_DggContainer
  • PHPExcel_Shared_Escher_DggContainer_BstoreContainer
  • PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE
  • PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip
  • PHPExcel_Shared_Excel5
  • PHPExcel_Shared_File
  • PHPExcel_Shared_Font
  • PHPExcel_Shared_JAMA_LUDecomposition
  • PHPExcel_Shared_JAMA_Matrix
  • PHPExcel_Shared_JAMA_QRDecomposition
  • PHPExcel_Shared_OLE
  • PHPExcel_Shared_OLE_ChainedBlockStream
  • PHPExcel_Shared_OLE_PPS
  • PHPExcel_Shared_OLE_PPS_File
  • PHPExcel_Shared_OLE_PPS_Root
  • PHPExcel_Shared_OLERead
  • PHPExcel_Shared_PasswordHasher
  • PHPExcel_Shared_String
  • PHPExcel_Shared_TimeZone
  • PHPExcel_Shared_XMLWriter
  • PHPExcel_Shared_ZipArchive
  • PHPExcel_Shared_ZipStreamWrapper
  • PHPExcel_Style
  • PHPExcel_Style_Alignment
  • PHPExcel_Style_Border
  • PHPExcel_Style_Borders
  • PHPExcel_Style_Color
  • PHPExcel_Style_Conditional
  • PHPExcel_Style_Fill
  • PHPExcel_Style_Font
  • PHPExcel_Style_NumberFormat
  • PHPExcel_Style_Protection
  • PHPExcel_Style_Supervisor
  • PHPExcel_Worksheet
  • PHPExcel_Worksheet_AutoFilter
  • PHPExcel_Worksheet_AutoFilter_Column
  • PHPExcel_Worksheet_AutoFilter_Column_Rule
  • PHPExcel_Worksheet_BaseDrawing
  • PHPExcel_Worksheet_CellIterator
  • PHPExcel_Worksheet_ColumnDimension
  • PHPExcel_Worksheet_Drawing
  • PHPExcel_Worksheet_Drawing_Shadow
  • PHPExcel_Worksheet_HeaderFooter
  • PHPExcel_Worksheet_HeaderFooterDrawing
  • PHPExcel_Worksheet_MemoryDrawing
  • PHPExcel_Worksheet_PageMargins
  • PHPExcel_Worksheet_PageSetup
  • PHPExcel_Worksheet_Protection
  • PHPExcel_Worksheet_Row
  • PHPExcel_Worksheet_RowDimension
  • PHPExcel_Worksheet_RowIterator
  • PHPExcel_Worksheet_SheetView
  • PHPExcel_WorksheetIterator
  • PHPExcel_Writer_Abstract
  • PHPExcel_Writer_CSV
  • PHPExcel_Writer_Excel2007
  • PHPExcel_Writer_Excel2007_Chart
  • PHPExcel_Writer_Excel2007_Comments
  • PHPExcel_Writer_Excel2007_ContentTypes
  • PHPExcel_Writer_Excel2007_DocProps
  • PHPExcel_Writer_Excel2007_Drawing
  • PHPExcel_Writer_Excel2007_Rels
  • PHPExcel_Writer_Excel2007_RelsRibbon
  • PHPExcel_Writer_Excel2007_RelsVBA
  • PHPExcel_Writer_Excel2007_StringTable
  • PHPExcel_Writer_Excel2007_Style
  • PHPExcel_Writer_Excel2007_Theme
  • PHPExcel_Writer_Excel2007_Workbook
  • PHPExcel_Writer_Excel2007_Worksheet
  • PHPExcel_Writer_Excel2007_WriterPart
  • PHPExcel_Writer_Excel5
  • PHPExcel_Writer_Excel5_BIFFwriter
  • PHPExcel_Writer_Excel5_Escher
  • PHPExcel_Writer_Excel5_Font
  • PHPExcel_Writer_Excel5_Parser
  • PHPExcel_Writer_Excel5_Workbook
  • PHPExcel_Writer_Excel5_Worksheet
  • PHPExcel_Writer_Excel5_Xf
  • PHPExcel_Writer_HTML
  • PHPExcel_Writer_PDF
  • PHPExcel_Writer_PDF_Core
  • PHPExcel_Writer_PDF_DomPDF
  • PHPExcel_Writer_PDF_mPDF
  • PHPExcel_Writer_PDF_tcPDF
  • Provincia
  • Radiacion
  • SingularValueDecomposition
  • Sistema
  • trendClass
  • xajax
  • xajaxArgumentManager
  • xajaxCallableObject
  • xajaxCallableObjectPlugin
  • xajaxControl
  • xajaxControlContainer
  • xajaxCustomRequest
  • xajaxCustomResponse
  • xajaxEvent
  • xajaxEventPlugin
  • xajaxFunctionPlugin
  • xajaxIncludeClientScriptPlugin
  • xajaxLanguageManager
  • xajaxPlugin
  • xajaxPluginManager
  • xajaxRequest
  • xajaxRequestPlugin
  • xajaxResponse
  • xajaxResponseManager
  • xajaxResponsePlugin
  • xajaxScriptPlugin
  • xajaxUserFunction
  • XMLWriter

Interfaces

  • DateTimeInterface
  • Iterator
  • PHPExcel_CachedObjectStorage_ICache
  • PHPExcel_Cell_IValueBinder
  • PHPExcel_IComparable
  • PHPExcel_Reader_IReader
  • PHPExcel_Reader_IReadFilter
  • PHPExcel_RichText_ITextElement
  • PHPExcel_Writer_IWriter
  • Throwable
  • Traversable

Exceptions

  • Exception
  • PHPExcel_Calculation_Exception
  • PHPExcel_Chart_Exception
  • PHPExcel_Exception
  • PHPExcel_Reader_Exception
  • PHPExcel_Writer_Exception

Functions

  • acosh
  • agregar_elemento
  • asinh
  • atanh
  • borrar_elementos
  • borrar_gdm_ab
  • borrar_irradiacion
  • borrar_latitud
  • borrar_panel
  • borrar_periodo
  • borrar_pmp_min_pmp_max
  • borrar_radiacion
  • borrar_resumen
  • borrar_sistema
  • borrar_sombra
  • gdm_ab
  • grabar_resumen
  • historial
  • hypo
  • irradiacion
  • JAMAError
  • latitud
  • limpiar_historial
  • login
  • mb_str_replace
  • mostrar_energia_total_ch
  • mostrar_panel_md_th
  • mostrar_panel_th
  • mostrar_radiacion_md_th
  • mostrar_radiacion_th
  • mostrar_resumen_th
  • panel
  • PclZipUtilCopyBlock
  • PclZipUtilOptionText
  • PclZipUtilPathInclusion
  • PclZipUtilPathReduction
  • PclZipUtilRename
  • PclZipUtilTranslateWinPath
  • periodo
  • pmp_min_pmp_max
  • preparar_panel
  • preparar_radiacion
  • preparar_radiacion_media
  • radiacion
  • resumen
  • sistema
  • sombra
  • xajaxCompressFile
  • xajaxErrorHandler
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  • Download
  1: <?php
  2: /**
  3:  *  @package JAMA
  4:  *
  5:  *  Class to obtain eigenvalues and eigenvectors of a real matrix.
  6:  *
  7:  *  If A is symmetric, then A = V*D*V' where the eigenvalue matrix D
  8:  *  is diagonal and the eigenvector matrix V is orthogonal (i.e.
  9:  *  A = V.times(D.times(V.transpose())) and V.times(V.transpose())
 10:  *  equals the identity matrix).
 11:  *
 12:  *  If A is not symmetric, then the eigenvalue matrix D is block diagonal
 13:  *  with the real eigenvalues in 1-by-1 blocks and any complex eigenvalues,
 14:  *  lambda + i*mu, in 2-by-2 blocks, [lambda, mu; -mu, lambda].  The
 15:  *  columns of V represent the eigenvectors in the sense that A*V = V*D,
 16:  *  i.e. A.times(V) equals V.times(D).  The matrix V may be badly
 17:  *  conditioned, or even singular, so the validity of the equation
 18:  *  A = V*D*inverse(V) depends upon V.cond().
 19:  *
 20:  *  @author  Paul Meagher
 21:  *  @license PHP v3.0
 22:  *  @version 1.1
 23:  */
 24: class EigenvalueDecomposition {
 25: 
 26:     /**
 27:      *  Row and column dimension (square matrix).
 28:      *  @var int
 29:      */
 30:     private $n;
 31: 
 32:     /**
 33:      *  Internal symmetry flag.
 34:      *  @var int
 35:      */
 36:     private $issymmetric;
 37: 
 38:     /**
 39:      *  Arrays for internal storage of eigenvalues.
 40:      *  @var array
 41:      */
 42:     private $d = array();
 43:     private $e = array();
 44: 
 45:     /**
 46:      *  Array for internal storage of eigenvectors.
 47:      *  @var array
 48:      */
 49:     private $V = array();
 50: 
 51:     /**
 52:     *   Array for internal storage of nonsymmetric Hessenberg form.
 53:     *   @var array
 54:     */
 55:     private $H = array();
 56: 
 57:     /**
 58:     *   Working storage for nonsymmetric algorithm.
 59:     *   @var array
 60:     */
 61:     private $ort;
 62: 
 63:     /**
 64:     *   Used for complex scalar division.
 65:     *   @var float
 66:     */
 67:     private $cdivr;
 68:     private $cdivi;
 69: 
 70: 
 71:     /**
 72:      *  Symmetric Householder reduction to tridiagonal form.
 73:      *
 74:      *  @access private
 75:      */
 76:     private function tred2 () {
 77:         //  This is derived from the Algol procedures tred2 by
 78:         //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
 79:         //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
 80:         //  Fortran subroutine in EISPACK.
 81:         $this->d = $this->V[$this->n-1];
 82:         // Householder reduction to tridiagonal form.
 83:         for ($i = $this->n-1; $i > 0; --$i) {
 84:             $i_ = $i -1;
 85:             // Scale to avoid under/overflow.
 86:             $h = $scale = 0.0;
 87:             $scale += array_sum(array_map(abs, $this->d));
 88:             if ($scale == 0.0) {
 89:                 $this->e[$i] = $this->d[$i_];
 90:                 $this->d = array_slice($this->V[$i_], 0, $i_);
 91:                 for ($j = 0; $j < $i; ++$j) {
 92:                     $this->V[$j][$i] = $this->V[$i][$j] = 0.0;
 93:                 }
 94:             } else {
 95:                 // Generate Householder vector.
 96:                 for ($k = 0; $k < $i; ++$k) {
 97:                     $this->d[$k] /= $scale;
 98:                     $h += pow($this->d[$k], 2);
 99:                 }
100:                 $f = $this->d[$i_];
101:                 $g = sqrt($h);
102:                 if ($f > 0) {
103:                     $g = -$g;
104:                 }
105:                 $this->e[$i] = $scale * $g;
106:                 $h = $h - $f * $g;
107:                 $this->d[$i_] = $f - $g;
108:                 for ($j = 0; $j < $i; ++$j) {
109:                     $this->e[$j] = 0.0;
110:                 }
111:                 // Apply similarity transformation to remaining columns.
112:                 for ($j = 0; $j < $i; ++$j) {
113:                     $f = $this->d[$j];
114:                     $this->V[$j][$i] = $f;
115:                     $g = $this->e[$j] + $this->V[$j][$j] * $f;
116:                     for ($k = $j+1; $k <= $i_; ++$k) {
117:                         $g += $this->V[$k][$j] * $this->d[$k];
118:                         $this->e[$k] += $this->V[$k][$j] * $f;
119:                     }
120:                     $this->e[$j] = $g;
121:                 }
122:                 $f = 0.0;
123:                 for ($j = 0; $j < $i; ++$j) {
124:                     $this->e[$j] /= $h;
125:                     $f += $this->e[$j] * $this->d[$j];
126:                 }
127:                 $hh = $f / (2 * $h);
128:                 for ($j=0; $j < $i; ++$j) {
129:                     $this->e[$j] -= $hh * $this->d[$j];
130:                 }
131:                 for ($j = 0; $j < $i; ++$j) {
132:                     $f = $this->d[$j];
133:                     $g = $this->e[$j];
134:                     for ($k = $j; $k <= $i_; ++$k) {
135:                         $this->V[$k][$j] -= ($f * $this->e[$k] + $g * $this->d[$k]);
136:                     }
137:                     $this->d[$j] = $this->V[$i-1][$j];
138:                     $this->V[$i][$j] = 0.0;
139:                 }
140:             }
141:             $this->d[$i] = $h;
142:         }
143: 
144:         // Accumulate transformations.
145:         for ($i = 0; $i < $this->n-1; ++$i) {
146:             $this->V[$this->n-1][$i] = $this->V[$i][$i];
147:             $this->V[$i][$i] = 1.0;
148:             $h = $this->d[$i+1];
149:             if ($h != 0.0) {
150:                 for ($k = 0; $k <= $i; ++$k) {
151:                     $this->d[$k] = $this->V[$k][$i+1] / $h;
152:                 }
153:                 for ($j = 0; $j <= $i; ++$j) {
154:                     $g = 0.0;
155:                     for ($k = 0; $k <= $i; ++$k) {
156:                         $g += $this->V[$k][$i+1] * $this->V[$k][$j];
157:                     }
158:                     for ($k = 0; $k <= $i; ++$k) {
159:                         $this->V[$k][$j] -= $g * $this->d[$k];
160:                     }
161:                 }
162:             }
163:             for ($k = 0; $k <= $i; ++$k) {
164:                 $this->V[$k][$i+1] = 0.0;
165:             }
166:         }
167: 
168:         $this->d = $this->V[$this->n-1];
169:         $this->V[$this->n-1] = array_fill(0, $j, 0.0);
170:         $this->V[$this->n-1][$this->n-1] = 1.0;
171:         $this->e[0] = 0.0;
172:     }
173: 
174: 
175:     /**
176:      *  Symmetric tridiagonal QL algorithm.
177:      *
178:      *  This is derived from the Algol procedures tql2, by
179:      *  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
180:      *  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
181:      *  Fortran subroutine in EISPACK.
182:      *
183:      *  @access private
184:      */
185:     private function tql2() {
186:         for ($i = 1; $i < $this->n; ++$i) {
187:             $this->e[$i-1] = $this->e[$i];
188:         }
189:         $this->e[$this->n-1] = 0.0;
190:         $f = 0.0;
191:         $tst1 = 0.0;
192:         $eps  = pow(2.0,-52.0);
193: 
194:         for ($l = 0; $l < $this->n; ++$l) {
195:             // Find small subdiagonal element
196:             $tst1 = max($tst1, abs($this->d[$l]) + abs($this->e[$l]));
197:             $m = $l;
198:             while ($m < $this->n) {
199:                 if (abs($this->e[$m]) <= $eps * $tst1)
200:                     break;
201:                 ++$m;
202:             }
203:             // If m == l, $this->d[l] is an eigenvalue,
204:             // otherwise, iterate.
205:             if ($m > $l) {
206:                 $iter = 0;
207:                 do {
208:                     // Could check iteration count here.
209:                     $iter += 1;
210:                     // Compute implicit shift
211:                     $g = $this->d[$l];
212:                     $p = ($this->d[$l+1] - $g) / (2.0 * $this->e[$l]);
213:                     $r = hypo($p, 1.0);
214:                     if ($p < 0)
215:                         $r *= -1;
216:                     $this->d[$l] = $this->e[$l] / ($p + $r);
217:                     $this->d[$l+1] = $this->e[$l] * ($p + $r);
218:                     $dl1 = $this->d[$l+1];
219:                     $h = $g - $this->d[$l];
220:                     for ($i = $l + 2; $i < $this->n; ++$i)
221:                         $this->d[$i] -= $h;
222:                     $f += $h;
223:                     // Implicit QL transformation.
224:                     $p = $this->d[$m];
225:                     $c = 1.0;
226:                     $c2 = $c3 = $c;
227:                     $el1 = $this->e[$l + 1];
228:                     $s = $s2 = 0.0;
229:                     for ($i = $m-1; $i >= $l; --$i) {
230:                         $c3 = $c2;
231:                         $c2 = $c;
232:                         $s2 = $s;
233:                         $g  = $c * $this->e[$i];
234:                         $h  = $c * $p;
235:                         $r  = hypo($p, $this->e[$i]);
236:                         $this->e[$i+1] = $s * $r;
237:                         $s = $this->e[$i] / $r;
238:                         $c = $p / $r;
239:                         $p = $c * $this->d[$i] - $s * $g;
240:                         $this->d[$i+1] = $h + $s * ($c * $g + $s * $this->d[$i]);
241:                         // Accumulate transformation.
242:                         for ($k = 0; $k < $this->n; ++$k) {
243:                             $h = $this->V[$k][$i+1];
244:                             $this->V[$k][$i+1] = $s * $this->V[$k][$i] + $c * $h;
245:                             $this->V[$k][$i] = $c * $this->V[$k][$i] - $s * $h;
246:                         }
247:                     }
248:                     $p = -$s * $s2 * $c3 * $el1 * $this->e[$l] / $dl1;
249:                     $this->e[$l] = $s * $p;
250:                     $this->d[$l] = $c * $p;
251:                 // Check for convergence.
252:                 } while (abs($this->e[$l]) > $eps * $tst1);
253:             }
254:             $this->d[$l] = $this->d[$l] + $f;
255:             $this->e[$l] = 0.0;
256:         }
257: 
258:         // Sort eigenvalues and corresponding vectors.
259:         for ($i = 0; $i < $this->n - 1; ++$i) {
260:             $k = $i;
261:             $p = $this->d[$i];
262:             for ($j = $i+1; $j < $this->n; ++$j) {
263:                 if ($this->d[$j] < $p) {
264:                     $k = $j;
265:                     $p = $this->d[$j];
266:                 }
267:             }
268:             if ($k != $i) {
269:                 $this->d[$k] = $this->d[$i];
270:                 $this->d[$i] = $p;
271:                 for ($j = 0; $j < $this->n; ++$j) {
272:                     $p = $this->V[$j][$i];
273:                     $this->V[$j][$i] = $this->V[$j][$k];
274:                     $this->V[$j][$k] = $p;
275:                 }
276:             }
277:         }
278:     }
279: 
280: 
281:     /**
282:      *  Nonsymmetric reduction to Hessenberg form.
283:      *
284:      *  This is derived from the Algol procedures orthes and ortran,
285:      *  by Martin and Wilkinson, Handbook for Auto. Comp.,
286:      *  Vol.ii-Linear Algebra, and the corresponding
287:      *  Fortran subroutines in EISPACK.
288:      *
289:      *  @access private
290:      */
291:     private function orthes () {
292:         $low  = 0;
293:         $high = $this->n-1;
294: 
295:         for ($m = $low+1; $m <= $high-1; ++$m) {
296:             // Scale column.
297:             $scale = 0.0;
298:             for ($i = $m; $i <= $high; ++$i) {
299:                 $scale = $scale + abs($this->H[$i][$m-1]);
300:             }
301:             if ($scale != 0.0) {
302:                 // Compute Householder transformation.
303:                 $h = 0.0;
304:                 for ($i = $high; $i >= $m; --$i) {
305:                     $this->ort[$i] = $this->H[$i][$m-1] / $scale;
306:                     $h += $this->ort[$i] * $this->ort[$i];
307:                 }
308:                 $g = sqrt($h);
309:                 if ($this->ort[$m] > 0) {
310:                     $g *= -1;
311:                 }
312:                 $h -= $this->ort[$m] * $g;
313:                 $this->ort[$m] -= $g;
314:                 // Apply Householder similarity transformation
315:                 // H = (I -u * u' / h) * H * (I -u * u') / h)
316:                 for ($j = $m; $j < $this->n; ++$j) {
317:                     $f = 0.0;
318:                     for ($i = $high; $i >= $m; --$i) {
319:                         $f += $this->ort[$i] * $this->H[$i][$j];
320:                     }
321:                     $f /= $h;
322:                     for ($i = $m; $i <= $high; ++$i) {
323:                         $this->H[$i][$j] -= $f * $this->ort[$i];
324:                     }
325:                 }
326:                 for ($i = 0; $i <= $high; ++$i) {
327:                     $f = 0.0;
328:                     for ($j = $high; $j >= $m; --$j) {
329:                         $f += $this->ort[$j] * $this->H[$i][$j];
330:                     }
331:                     $f = $f / $h;
332:                     for ($j = $m; $j <= $high; ++$j) {
333:                         $this->H[$i][$j] -= $f * $this->ort[$j];
334:                     }
335:                 }
336:                 $this->ort[$m] = $scale * $this->ort[$m];
337:                 $this->H[$m][$m-1] = $scale * $g;
338:             }
339:         }
340: 
341:         // Accumulate transformations (Algol's ortran).
342:         for ($i = 0; $i < $this->n; ++$i) {
343:             for ($j = 0; $j < $this->n; ++$j) {
344:                 $this->V[$i][$j] = ($i == $j ? 1.0 : 0.0);
345:             }
346:         }
347:         for ($m = $high-1; $m >= $low+1; --$m) {
348:             if ($this->H[$m][$m-1] != 0.0) {
349:                 for ($i = $m+1; $i <= $high; ++$i) {
350:                     $this->ort[$i] = $this->H[$i][$m-1];
351:                 }
352:                 for ($j = $m; $j <= $high; ++$j) {
353:                     $g = 0.0;
354:                     for ($i = $m; $i <= $high; ++$i) {
355:                         $g += $this->ort[$i] * $this->V[$i][$j];
356:                     }
357:                     // Double division avoids possible underflow
358:                     $g = ($g / $this->ort[$m]) / $this->H[$m][$m-1];
359:                     for ($i = $m; $i <= $high; ++$i) {
360:                         $this->V[$i][$j] += $g * $this->ort[$i];
361:                     }
362:                 }
363:             }
364:         }
365:     }
366: 
367: 
368:     /**
369:      *  Performs complex division.
370:      *
371:      *  @access private
372:      */
373:     private function cdiv($xr, $xi, $yr, $yi) {
374:         if (abs($yr) > abs($yi)) {
375:             $r = $yi / $yr;
376:             $d = $yr + $r * $yi;
377:             $this->cdivr = ($xr + $r * $xi) / $d;
378:             $this->cdivi = ($xi - $r * $xr) / $d;
379:         } else {
380:             $r = $yr / $yi;
381:             $d = $yi + $r * $yr;
382:             $this->cdivr = ($r * $xr + $xi) / $d;
383:             $this->cdivi = ($r * $xi - $xr) / $d;
384:         }
385:     }
386: 
387: 
388:     /**
389:      *  Nonsymmetric reduction from Hessenberg to real Schur form.
390:      *
391:      *  Code is derived from the Algol procedure hqr2,
392:      *  by Martin and Wilkinson, Handbook for Auto. Comp.,
393:      *  Vol.ii-Linear Algebra, and the corresponding
394:      *  Fortran subroutine in EISPACK.
395:      *
396:      *  @access private
397:      */
398:     private function hqr2 () {
399:         //  Initialize
400:         $nn = $this->n;
401:         $n  = $nn - 1;
402:         $low = 0;
403:         $high = $nn - 1;
404:         $eps = pow(2.0, -52.0);
405:         $exshift = 0.0;
406:         $p = $q = $r = $s = $z = 0;
407:         // Store roots isolated by balanc and compute matrix norm
408:         $norm = 0.0;
409: 
410:         for ($i = 0; $i < $nn; ++$i) {
411:             if (($i < $low) OR ($i > $high)) {
412:                 $this->d[$i] = $this->H[$i][$i];
413:                 $this->e[$i] = 0.0;
414:             }
415:             for ($j = max($i-1, 0); $j < $nn; ++$j) {
416:                 $norm = $norm + abs($this->H[$i][$j]);
417:             }
418:         }
419: 
420:         // Outer loop over eigenvalue index
421:         $iter = 0;
422:         while ($n >= $low) {
423:             // Look for single small sub-diagonal element
424:             $l = $n;
425:             while ($l > $low) {
426:                 $s = abs($this->H[$l-1][$l-1]) + abs($this->H[$l][$l]);
427:                 if ($s == 0.0) {
428:                     $s = $norm;
429:                 }
430:                 if (abs($this->H[$l][$l-1]) < $eps * $s) {
431:                     break;
432:                 }
433:                 --$l;
434:             }
435:             // Check for convergence
436:             // One root found
437:             if ($l == $n) {
438:                 $this->H[$n][$n] = $this->H[$n][$n] + $exshift;
439:                 $this->d[$n] = $this->H[$n][$n];
440:                 $this->e[$n] = 0.0;
441:                 --$n;
442:                 $iter = 0;
443:             // Two roots found
444:             } else if ($l == $n-1) {
445:                 $w = $this->H[$n][$n-1] * $this->H[$n-1][$n];
446:                 $p = ($this->H[$n-1][$n-1] - $this->H[$n][$n]) / 2.0;
447:                 $q = $p * $p + $w;
448:                 $z = sqrt(abs($q));
449:                 $this->H[$n][$n] = $this->H[$n][$n] + $exshift;
450:                 $this->H[$n-1][$n-1] = $this->H[$n-1][$n-1] + $exshift;
451:                 $x = $this->H[$n][$n];
452:                 // Real pair
453:                 if ($q >= 0) {
454:                     if ($p >= 0) {
455:                         $z = $p + $z;
456:                     } else {
457:                         $z = $p - $z;
458:                     }
459:                     $this->d[$n-1] = $x + $z;
460:                     $this->d[$n] = $this->d[$n-1];
461:                     if ($z != 0.0) {
462:                         $this->d[$n] = $x - $w / $z;
463:                     }
464:                     $this->e[$n-1] = 0.0;
465:                     $this->e[$n] = 0.0;
466:                     $x = $this->H[$n][$n-1];
467:                     $s = abs($x) + abs($z);
468:                     $p = $x / $s;
469:                     $q = $z / $s;
470:                     $r = sqrt($p * $p + $q * $q);
471:                     $p = $p / $r;
472:                     $q = $q / $r;
473:                     // Row modification
474:                     for ($j = $n-1; $j < $nn; ++$j) {
475:                         $z = $this->H[$n-1][$j];
476:                         $this->H[$n-1][$j] = $q * $z + $p * $this->H[$n][$j];
477:                         $this->H[$n][$j] = $q * $this->H[$n][$j] - $p * $z;
478:                     }
479:                     // Column modification
480:                     for ($i = 0; $i <= n; ++$i) {
481:                         $z = $this->H[$i][$n-1];
482:                         $this->H[$i][$n-1] = $q * $z + $p * $this->H[$i][$n];
483:                         $this->H[$i][$n] = $q * $this->H[$i][$n] - $p * $z;
484:                     }
485:                     // Accumulate transformations
486:                     for ($i = $low; $i <= $high; ++$i) {
487:                         $z = $this->V[$i][$n-1];
488:                         $this->V[$i][$n-1] = $q * $z + $p * $this->V[$i][$n];
489:                         $this->V[$i][$n] = $q * $this->V[$i][$n] - $p * $z;
490:                     }
491:                 // Complex pair
492:                 } else {
493:                     $this->d[$n-1] = $x + $p;
494:                     $this->d[$n] = $x + $p;
495:                     $this->e[$n-1] = $z;
496:                     $this->e[$n] = -$z;
497:                 }
498:                 $n = $n - 2;
499:                 $iter = 0;
500:             // No convergence yet
501:             } else {
502:                 // Form shift
503:                 $x = $this->H[$n][$n];
504:                 $y = 0.0;
505:                 $w = 0.0;
506:                 if ($l < $n) {
507:                     $y = $this->H[$n-1][$n-1];
508:                     $w = $this->H[$n][$n-1] * $this->H[$n-1][$n];
509:                 }
510:                 // Wilkinson's original ad hoc shift
511:                 if ($iter == 10) {
512:                     $exshift += $x;
513:                     for ($i = $low; $i <= $n; ++$i) {
514:                         $this->H[$i][$i] -= $x;
515:                     }
516:                     $s = abs($this->H[$n][$n-1]) + abs($this->H[$n-1][$n-2]);
517:                     $x = $y = 0.75 * $s;
518:                     $w = -0.4375 * $s * $s;
519:                 }
520:                 // MATLAB's new ad hoc shift
521:                 if ($iter == 30) {
522:                     $s = ($y - $x) / 2.0;
523:                     $s = $s * $s + $w;
524:                     if ($s > 0) {
525:                         $s = sqrt($s);
526:                         if ($y < $x) {
527:                             $s = -$s;
528:                         }
529:                         $s = $x - $w / (($y - $x) / 2.0 + $s);
530:                         for ($i = $low; $i <= $n; ++$i) {
531:                             $this->H[$i][$i] -= $s;
532:                         }
533:                         $exshift += $s;
534:                         $x = $y = $w = 0.964;
535:                     }
536:                 }
537:                 // Could check iteration count here.
538:                 $iter = $iter + 1;
539:                 // Look for two consecutive small sub-diagonal elements
540:                 $m = $n - 2;
541:                 while ($m >= $l) {
542:                     $z = $this->H[$m][$m];
543:                     $r = $x - $z;
544:                     $s = $y - $z;
545:                     $p = ($r * $s - $w) / $this->H[$m+1][$m] + $this->H[$m][$m+1];
546:                     $q = $this->H[$m+1][$m+1] - $z - $r - $s;
547:                     $r = $this->H[$m+2][$m+1];
548:                     $s = abs($p) + abs($q) + abs($r);
549:                     $p = $p / $s;
550:                     $q = $q / $s;
551:                     $r = $r / $s;
552:                     if ($m == $l) {
553:                         break;
554:                     }
555:                     if (abs($this->H[$m][$m-1]) * (abs($q) + abs($r)) <
556:                         $eps * (abs($p) * (abs($this->H[$m-1][$m-1]) + abs($z) + abs($this->H[$m+1][$m+1])))) {
557:                         break;
558:                     }
559:                     --$m;
560:                 }
561:                 for ($i = $m + 2; $i <= $n; ++$i) {
562:                     $this->H[$i][$i-2] = 0.0;
563:                     if ($i > $m+2) {
564:                         $this->H[$i][$i-3] = 0.0;
565:                     }
566:                 }
567:                 // Double QR step involving rows l:n and columns m:n
568:                 for ($k = $m; $k <= $n-1; ++$k) {
569:                     $notlast = ($k != $n-1);
570:                     if ($k != $m) {
571:                         $p = $this->H[$k][$k-1];
572:                         $q = $this->H[$k+1][$k-1];
573:                         $r = ($notlast ? $this->H[$k+2][$k-1] : 0.0);
574:                         $x = abs($p) + abs($q) + abs($r);
575:                         if ($x != 0.0) {
576:                             $p = $p / $x;
577:                             $q = $q / $x;
578:                             $r = $r / $x;
579:                         }
580:                     }
581:                     if ($x == 0.0) {
582:                         break;
583:                     }
584:                     $s = sqrt($p * $p + $q * $q + $r * $r);
585:                     if ($p < 0) {
586:                         $s = -$s;
587:                     }
588:                     if ($s != 0) {
589:                         if ($k != $m) {
590:                             $this->H[$k][$k-1] = -$s * $x;
591:                         } elseif ($l != $m) {
592:                             $this->H[$k][$k-1] = -$this->H[$k][$k-1];
593:                         }
594:                         $p = $p + $s;
595:                         $x = $p / $s;
596:                         $y = $q / $s;
597:                         $z = $r / $s;
598:                         $q = $q / $p;
599:                         $r = $r / $p;
600:                         // Row modification
601:                         for ($j = $k; $j < $nn; ++$j) {
602:                             $p = $this->H[$k][$j] + $q * $this->H[$k+1][$j];
603:                             if ($notlast) {
604:                                 $p = $p + $r * $this->H[$k+2][$j];
605:                                 $this->H[$k+2][$j] = $this->H[$k+2][$j] - $p * $z;
606:                             }
607:                             $this->H[$k][$j] = $this->H[$k][$j] - $p * $x;
608:                             $this->H[$k+1][$j] = $this->H[$k+1][$j] - $p * $y;
609:                         }
610:                         // Column modification
611:                         for ($i = 0; $i <= min($n, $k+3); ++$i) {
612:                             $p = $x * $this->H[$i][$k] + $y * $this->H[$i][$k+1];
613:                             if ($notlast) {
614:                                 $p = $p + $z * $this->H[$i][$k+2];
615:                                 $this->H[$i][$k+2] = $this->H[$i][$k+2] - $p * $r;
616:                             }
617:                             $this->H[$i][$k] = $this->H[$i][$k] - $p;
618:                             $this->H[$i][$k+1] = $this->H[$i][$k+1] - $p * $q;
619:                         }
620:                         // Accumulate transformations
621:                         for ($i = $low; $i <= $high; ++$i) {
622:                             $p = $x * $this->V[$i][$k] + $y * $this->V[$i][$k+1];
623:                             if ($notlast) {
624:                                 $p = $p + $z * $this->V[$i][$k+2];
625:                                 $this->V[$i][$k+2] = $this->V[$i][$k+2] - $p * $r;
626:                             }
627:                             $this->V[$i][$k] = $this->V[$i][$k] - $p;
628:                             $this->V[$i][$k+1] = $this->V[$i][$k+1] - $p * $q;
629:                         }
630:                     }  // ($s != 0)
631:                 }  // k loop
632:             }  // check convergence
633:         }  // while ($n >= $low)
634: 
635:         // Backsubstitute to find vectors of upper triangular form
636:         if ($norm == 0.0) {
637:             return;
638:         }
639: 
640:         for ($n = $nn-1; $n >= 0; --$n) {
641:             $p = $this->d[$n];
642:             $q = $this->e[$n];
643:             // Real vector
644:             if ($q == 0) {
645:                 $l = $n;
646:                 $this->H[$n][$n] = 1.0;
647:                 for ($i = $n-1; $i >= 0; --$i) {
648:                     $w = $this->H[$i][$i] - $p;
649:                     $r = 0.0;
650:                     for ($j = $l; $j <= $n; ++$j) {
651:                         $r = $r + $this->H[$i][$j] * $this->H[$j][$n];
652:                     }
653:                     if ($this->e[$i] < 0.0) {
654:                         $z = $w;
655:                         $s = $r;
656:                     } else {
657:                         $l = $i;
658:                         if ($this->e[$i] == 0.0) {
659:                             if ($w != 0.0) {
660:                                 $this->H[$i][$n] = -$r / $w;
661:                             } else {
662:                                 $this->H[$i][$n] = -$r / ($eps * $norm);
663:                             }
664:                         // Solve real equations
665:                         } else {
666:                             $x = $this->H[$i][$i+1];
667:                             $y = $this->H[$i+1][$i];
668:                             $q = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i];
669:                             $t = ($x * $s - $z * $r) / $q;
670:                             $this->H[$i][$n] = $t;
671:                             if (abs($x) > abs($z)) {
672:                                 $this->H[$i+1][$n] = (-$r - $w * $t) / $x;
673:                             } else {
674:                                 $this->H[$i+1][$n] = (-$s - $y * $t) / $z;
675:                             }
676:                         }
677:                         // Overflow control
678:                         $t = abs($this->H[$i][$n]);
679:                         if (($eps * $t) * $t > 1) {
680:                             for ($j = $i; $j <= $n; ++$j) {
681:                                 $this->H[$j][$n] = $this->H[$j][$n] / $t;
682:                             }
683:                         }
684:                     }
685:                 }
686:             // Complex vector
687:             } else if ($q < 0) {
688:                 $l = $n-1;
689:                 // Last vector component imaginary so matrix is triangular
690:                 if (abs($this->H[$n][$n-1]) > abs($this->H[$n-1][$n])) {
691:                     $this->H[$n-1][$n-1] = $q / $this->H[$n][$n-1];
692:                     $this->H[$n-1][$n] = -($this->H[$n][$n] - $p) / $this->H[$n][$n-1];
693:                 } else {
694:                     $this->cdiv(0.0, -$this->H[$n-1][$n], $this->H[$n-1][$n-1] - $p, $q);
695:                     $this->H[$n-1][$n-1] = $this->cdivr;
696:                     $this->H[$n-1][$n]   = $this->cdivi;
697:                 }
698:                 $this->H[$n][$n-1] = 0.0;
699:                 $this->H[$n][$n] = 1.0;
700:                 for ($i = $n-2; $i >= 0; --$i) {
701:                     // double ra,sa,vr,vi;
702:                     $ra = 0.0;
703:                     $sa = 0.0;
704:                     for ($j = $l; $j <= $n; ++$j) {
705:                         $ra = $ra + $this->H[$i][$j] * $this->H[$j][$n-1];
706:                         $sa = $sa + $this->H[$i][$j] * $this->H[$j][$n];
707:                     }
708:                     $w = $this->H[$i][$i] - $p;
709:                     if ($this->e[$i] < 0.0) {
710:                         $z = $w;
711:                         $r = $ra;
712:                         $s = $sa;
713:                     } else {
714:                         $l = $i;
715:                         if ($this->e[$i] == 0) {
716:                             $this->cdiv(-$ra, -$sa, $w, $q);
717:                             $this->H[$i][$n-1] = $this->cdivr;
718:                             $this->H[$i][$n]   = $this->cdivi;
719:                         } else {
720:                             // Solve complex equations
721:                             $x = $this->H[$i][$i+1];
722:                             $y = $this->H[$i+1][$i];
723:                             $vr = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i] - $q * $q;
724:                             $vi = ($this->d[$i] - $p) * 2.0 * $q;
725:                             if ($vr == 0.0 & $vi == 0.0) {
726:                                 $vr = $eps * $norm * (abs($w) + abs($q) + abs($x) + abs($y) + abs($z));
727:                             }
728:                             $this->cdiv($x * $r - $z * $ra + $q * $sa, $x * $s - $z * $sa - $q * $ra, $vr, $vi);
729:                             $this->H[$i][$n-1] = $this->cdivr;
730:                             $this->H[$i][$n]   = $this->cdivi;
731:                             if (abs($x) > (abs($z) + abs($q))) {
732:                                 $this->H[$i+1][$n-1] = (-$ra - $w * $this->H[$i][$n-1] + $q * $this->H[$i][$n]) / $x;
733:                                 $this->H[$i+1][$n] = (-$sa - $w * $this->H[$i][$n] - $q * $this->H[$i][$n-1]) / $x;
734:                             } else {
735:                                 $this->cdiv(-$r - $y * $this->H[$i][$n-1], -$s - $y * $this->H[$i][$n], $z, $q);
736:                                 $this->H[$i+1][$n-1] = $this->cdivr;
737:                                 $this->H[$i+1][$n]   = $this->cdivi;
738:                             }
739:                         }
740:                         // Overflow control
741:                         $t = max(abs($this->H[$i][$n-1]),abs($this->H[$i][$n]));
742:                         if (($eps * $t) * $t > 1) {
743:                             for ($j = $i; $j <= $n; ++$j) {
744:                                 $this->H[$j][$n-1] = $this->H[$j][$n-1] / $t;
745:                                 $this->H[$j][$n]   = $this->H[$j][$n] / $t;
746:                             }
747:                         }
748:                     } // end else
749:                 } // end for
750:             } // end else for complex case
751:         } // end for
752: 
753:         // Vectors of isolated roots
754:         for ($i = 0; $i < $nn; ++$i) {
755:             if ($i < $low | $i > $high) {
756:                 for ($j = $i; $j < $nn; ++$j) {
757:                     $this->V[$i][$j] = $this->H[$i][$j];
758:                 }
759:             }
760:         }
761: 
762:         // Back transformation to get eigenvectors of original matrix
763:         for ($j = $nn-1; $j >= $low; --$j) {
764:             for ($i = $low; $i <= $high; ++$i) {
765:                 $z = 0.0;
766:                 for ($k = $low; $k <= min($j,$high); ++$k) {
767:                     $z = $z + $this->V[$i][$k] * $this->H[$k][$j];
768:                 }
769:                 $this->V[$i][$j] = $z;
770:             }
771:         }
772:     } // end hqr2
773: 
774: 
775:     /**
776:      *  Constructor: Check for symmetry, then construct the eigenvalue decomposition
777:      *
778:      *  @access public
779:      *  @param A  Square matrix
780:      *  @return Structure to access D and V.
781:      */
782:     public function __construct($Arg) {
783:         $this->A = $Arg->getArray();
784:         $this->n = $Arg->getColumnDimension();
785: 
786:         $issymmetric = true;
787:         for ($j = 0; ($j < $this->n) & $issymmetric; ++$j) {
788:             for ($i = 0; ($i < $this->n) & $issymmetric; ++$i) {
789:                 $issymmetric = ($this->A[$i][$j] == $this->A[$j][$i]);
790:             }
791:         }
792: 
793:         if ($issymmetric) {
794:             $this->V = $this->A;
795:             // Tridiagonalize.
796:             $this->tred2();
797:             // Diagonalize.
798:             $this->tql2();
799:         } else {
800:             $this->H = $this->A;
801:             $this->ort = array();
802:             // Reduce to Hessenberg form.
803:             $this->orthes();
804:             // Reduce Hessenberg to real Schur form.
805:             $this->hqr2();
806:         }
807:     }
808: 
809: 
810:     /**
811:      *  Return the eigenvector matrix
812:      *
813:      *  @access public
814:      *  @return V
815:      */
816:     public function getV() {
817:         return new Matrix($this->V, $this->n, $this->n);
818:     }
819: 
820: 
821:     /**
822:      *  Return the real parts of the eigenvalues
823:      *
824:      *  @access public
825:      *  @return real(diag(D))
826:      */
827:     public function getRealEigenvalues() {
828:         return $this->d;
829:     }
830: 
831: 
832:     /**
833:      *  Return the imaginary parts of the eigenvalues
834:      *
835:      *  @access public
836:      *  @return imag(diag(D))
837:      */
838:     public function getImagEigenvalues() {
839:         return $this->e;
840:     }
841: 
842: 
843:     /**
844:      *  Return the block diagonal eigenvalue matrix
845:      *
846:      *  @access public
847:      *  @return D
848:      */
849:     public function getD() {
850:         for ($i = 0; $i < $this->n; ++$i) {
851:             $D[$i] = array_fill(0, $this->n, 0.0);
852:             $D[$i][$i] = $this->d[$i];
853:             if ($this->e[$i] == 0) {
854:                 continue;
855:             }
856:             $o = ($this->e[$i] > 0) ? $i + 1 : $i - 1;
857:             $D[$i][$o] = $this->e[$i];
858:         }
859:         return new Matrix($D);
860:     }
861: 
862: }   //  class EigenvalueDecomposition
863: 
Autene API documentation generated by ApiGen