matrix.php
来自「视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.」· PHP 代码 · 共 1,490 行 · 第 1/4 页
PHP
1,490 行
if (PEAR::isError($det)) { return $det; } $norm = $this->norm(); if (PEAR::isError($norm)) { return $norm; } if ($norm == 0) { return PEAR::raiseError('Undefined normalized determinant, euclidean norm is zero'); } return abs($det / $norm); }/*}}}*/ /** * Returns the index of the row with the maximum value under column of the element e[i][i] * * @access protected * @return an integer */ function _maxElementIndex($r) {/*{{{*/ $max = 0; $idx = -1; list($nr, $nc) = $this->getSize(); $arr = array(); for ($i=$r; $i<$nr; $i++) { $val = abs($this->_data[$i][$r]); if ($val > $max) { $max = $val; $idx = $i; } } if ($idx == -1) { $idx = $r; } return $idx; }/*}}}*/ /** * Inverts a matrix using Gauss-Jordan elimination with partial pivoting * * @access public * @return mixed the value of the matrix determinant on success, PEAR_Error otherwise * @see scaleRow() */ function invert() { if ($this->isEmpty()) { return PEAR::raiseError('Matrix has not been populated'); } if (!$this->isSquare()) { return PEAR::raiseError('Determinant undefined for non-square matrices'); } $norm = $this->norm(); $sign = 1; $det = 1.0; // work on a copy to be safe $m = $this->clone(); list($nr, $nc) = $m->getSize(); // Unit matrix to use as target $q = Math_Matrix::makeUnit($nr); for ($i=0; $i<$nr; $i++) { $ridx = $this->_maxElementIndex($i); if ($i != $ridx) { $sign = -$sign; $e = $m->swapRows($i, $ridx); if (PEAR::isError($e)) { return $e; } $e = $q->swapRows($i, $ridx); if (PEAR::isError($e)) { return $e; } } $pelement = $m->getElement($i, $i); if (PEAR::isError($pelement)) { return $pelement; } if ($pelement == 0) { return PEAR::raiseError('Cannot continue inversion, pivoting element is zero'); } $det *= $pelement; if ((abs($det)/$norm) < $this->_epsilon) { return PEAR::raiseError('Probable singular or ill-conditioned matrix, normalized determinant = ' .(abs($det)/$norm)); } $e = $m->scaleRow($i, 1/$pelement); if (PEAR::isError($e)) { return $e; } $e = $q->scaleRow($i, 1/$pelement); if (PEAR::isError($e)) { return $e; } // zero all column elements execpt for the current one $tpelement = $m->getElement($i, $i); for ($j=0; $j<$nr; $j++) { if ($j == $i) { continue; } $factor = $m->getElement($j, $i) / $tpelement; for ($k=0; $k<$nc; $k++) { $vm = $m->getElement($j, $k) - $factor * $m->getElement($i, $k); $vq = $q->getElement($j, $k) - $factor * $q->getElement($i, $k); $m->setElement($j, $k, $vm); $q->setElement($j, $k, $vq); } } // for debugging /* echo "COLUMN: $i\n"; echo $m->toString()."\n"; echo $q->toString()."\n"; */ } $data = $q->getData(); /* // for debugging echo $m->toString()."\n"; echo $q->toString()."\n"; */ unset($m); unset($q); $e = $this->setData($data); if (PEAR::isError($e)) { return $e; } if ($sign < 0) { $det = -$det; } $this->_det = $det; return $det; } /** * Returns a submatrix from the position (row, col), with nrows and ncols * * @access public * @return object Math_Matrix on success, PEAR_Error otherwise */ function &getSubMatrix ($row, $col, $nrows, $ncols) {/*{{{*/ if (!is_numeric($row) || !is_numeric($col) || !is_numeric($nrows) || !is_numeric($ncols)) { return PEAR::raiseError('Parameters must be a initial row and column, and number of rows and columns in submatrix'); } list($nr, $nc) = $this->getSize(); if ($rows + $nrows > $nr) { return PEAR::raiseError('Rows in submatrix more than in original matrix'); } if ($cols + $ncols > $nr) { return PEAR::raiseError('Columns in submatrix more than in original matrix'); } $data = array(); for ($i=0; $i < $nrows; $i++) { for ($j=0; $j < $ncols; $j++) { $data[$i][$j] = $this->getElement($i + $row, $j + $col); } } return new Math_Matrix($data); }/*}}}*/ /** * Returns a simple string representation of the matrix * * @param optional string $format a sprintf() format used to print the matrix elements (default = '%6.2f') * @return mixed a string on success, PEAR_Error otherwise */ function toString ($format='%6.2f') {/*{{{*/ if ($this->isEmpty()) { return PEAR::raiseError('Matrix has not been populated'); } $out = ""; for ($i=0; $i < $this->_num_rows; $i++) { for ($j=0; $j < $this->_num_cols; $j++) { $out .= sprintf($format, $this->_data[$i][$j]); } $out .= "\n"; } return $out; }/*}}}*/ /** * Returns an HTML table representation of the matrix elements * * @access public * @return a string on success, PEAR_Error otherwise */ function toHTML() {/*{{{*/ if ($this->isEmpty()) { return PEAR::raiseError('Matrix has not been populated'); } $out = "<table border>\n\t<caption align=\"top\"><b>Matrix</b>"; $out .= "</caption>\n\t<tr align=\"center\">\n\t\t<th>"; $out .= $this->_num_rows."x".$this->_num_cols."</th>"; for ($i=0; $i < $this->_num_cols; $i++) { $out .= "<th>".$i."</th>"; } $out .= "\n\t</tr>\n"; for ($i=0; $i < $this->_num_rows; $i++) { $out .= "\t<tr align=\"center\">\n\t\t<th>".$i."</th>"; for ($j=0; $j < $this->_num_cols; $j++) { $out .= "<td bgcolor=\"#ffffdd\">".$this->_data[$i][$j]."</td>"; } $out .= "\n\t</tr>"; } return $out."\n</table>\n"; }/*}}}*/ // Binary operations /** * Adds a matrix to this one * * @param object Math_Matrix $m1 * @return mixed TRUE on success, PEAR_Error otherwise * @see getSize() * @see getElement() * @see setData() */ function add ($m1) {/*{{{*/ if (!Math_Matrix::isMatrix($m1)) { return PEAR::raiseError("Parameter must be a Math_Matrix object"); } if ($this->getSize() != $m1->getSize()) { return PEAR::raiseError("Matrices must have the same dimensions"); } list($nr, $nc) = $m1->getSize(); $data = array(); for ($i=0; $i < $nr; $i++) { for ($j=0; $j < $nc; $j++) { $el1 = $m1->getElement($i,$j); if (PEAR::isError($el1)) { return $el1; } $el = $this->getElement($i,$j); if (PEAR::isError($el)) { return $el; } $data[$i][$j] = $el + $el1; } } if (!empty($data)) { return $this->setData($data); } else { return PEAR::raiseError('Undefined error'); } }/*}}}*/ /** * Substracts a matrix from this one * * @param object Math_Matrix $m1 * @return mixed TRUE on success, PEAR_Error otherwise * @see getSize() * @see getElement() * @see setData() */ function sub (&$m1) {/*{{{*/ if (!Math_Matrix::isMatrix($m1)) { return PEAR::raiseError("Parameter must be a Math_Matrix object"); } if ($this->getSize() != $m1->getSize()) { return PEAR::raiseError("Matrices must have the same dimensions"); } list($nr, $nc) = $m1->getSize(); $data = array(); for ($i=0; $i < $nr; $i++) { for ($j=0; $j < $nc; $j++) { $el1 = $m1->getElement($i,$j); if (PEAR::isError($el1)) { return $el1; } $el = $this->getElement($i,$j); if (PEAR::isError($el)) { return $el; } $data[$i][$j] = $el - $el1; } } if (!empty($data)) { return $this->setData($data); } else { return PEAR::raiseError('Undefined error'); } }/*}}}*/ /** * Scales the matrix by a given factor * * @param numeric $scale the scaling factor * @return mixed TRUE on success, PEAR_Error otherwise * @see getSize() * @see getElement() * @see setData() */ function scale ($scale) {/*{{{*/ if (!is_numeric($scale)) { return PEAR::raiseError("Parameter must be a number"); } list($nr, $nc) = $this->getSize(); $data = array(); for ($i=0; $i < $nr; $i++) { for ($j=0; $j < $nc; $j++) { $data[$i][$j] = $scale * $this->getElement($i,$j); } } if (!empty($data)) { return $this->setData($data); } else { return PEAR::raiseError('Undefined error'); } }/*}}}*/ /** * Multiplies (scales) a row by the given factor * * @access public * @param integer $row the row index * @param numeric $factor the scaling factor * @return mixed TRUE on success, a PEAR_Error otherwise * @see invert() */ function scaleRow($row, $factor) {/*{{{*/ if ($this->isEmpty()) { return PEAR::raiseError('Uninitialized Math_Matrix object'); } if (!is_integer($row) || !is_numeric($factor)) { return PEAR::raiseError('Row index must be an integer, and factor a valid number'); } if ($row >= $this->_num_rows) { return PEAR::raiseError('Row index out of bounds'); } $r = $this->getRow($row); if (PEAR::isError($r)) { return $r; } $nr = count($r); for ($i=0; $i<$nr; $i++) { $r[$i] *= $factor; } return $this->setRow($row, $r); }/*}}}*/ /** * Multiplies a matrix by this one * * @param object Math_Matrix $m1 * @return mixed TRUE on success, PEAR_Error otherwise * @see getSize() * @see getRow() * @see getCol() * @see setData() */ function multiply(&$m1) {/*{{{*/ $epsilon = 1E-10; if (!Math_Matrix::isMatrix($m1)) { return PEAR::raiseError ('Wrong parameter, expected a Math_Matrix object'); } list($nr, $nc) = $this->getSize(); list($nr1, $nc1) = $m1->getSize(); if ($nc1 != $nr) { return PEAR::raiseError('Incompatible sizes columns in matrix must be the same as rows in parameter matrix'); } $data = array(); for ($i=0; $i < $nr; $i++) { for ($j=0; $j < $nc1; $j++) { $data[$i][$j] = 0; for ($k=0; $k < $nc; $k++) { $data[$i][$j] += $this->getElement($i,$k) * $m1->getElement($k, $j); } // take care of some round-off errors if ($data[$i][$j] <= $epsilon) { $data[$i][$j] = 0.0; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?