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 + -
显示快捷键?