cvs: pear /Math_Matrix Matrix.php MatrixOp.php /Math_Matrix/examples ex_matrix.php

From: Date: Thu, 23 May 2002 09:43:51 +0000
Subject: cvs: pear /Math_Matrix Matrix.php MatrixOp.php /Math_Matrix/examples ex_matrix.php
Groups: php.pear.cvs 
Request: Send a blank email to pear-cvs+get-4047@lists.php.net to get a copy of this message
jmcastagnetto Thu May 23 05:43:51 2002 EDT Added files: /pear/Math_Matrix Matrix.php MatrixOp.php /pear/Math_Matrix/examples ex_matrix.php Log: Initial import. Still need to document methods and check consistency of code and example.

Index: pear/Math_Matrix/Matrix.php +++ pear/Math_Matrix/Matrix.php <?php // // +----------------------------------------------------------------------+ // | PHP version 4.0 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997-2001 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.02 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Authors: Jesus M. Castagnetto <jmcastagnetto@php.net> | // +----------------------------------------------------------------------+ // // Matrix definition and manipulation package // // $Id: Matrix.php,v 1.1 2002/05/23 09:43:50 jmcastagnetto Exp $ // require_once 'PEAR.php'; /** * Defines a matrix object, conceptualized as an array of arrays such that: * * <pre> * [0][0] [0][1] [0][2] ... [0][M]<br> * [1][0] [1][1] [1][2] ... [1][M]<br> * ...<br> * [N][0] [n][1] [n][2] ... [n][M]<br> * </pre> * * i.e. N rows, M colums * * Originally this class was part of NumPHP (Numeric PHP package) * * @author Jesus M. Castagnetto <jmcastagnetto@php.net> * @access public * @version 1.0 * @package Math_Matrix */ class Math_Matrix {/*{{{*/ // Properties /*{{{*/ /** * Contains the array of arrays defining the matrix * * @access private * @var array * @see getData() */ var $_data = null; /** * The number of rows in the matrix * * @access private * @var integer * @see getSize() */ var $_num_rows = null; /** * The number of columns in the matrix * * @access private * @var integer * @see getSize() */ var $_num_cols = null; /** * The smallest value of all matrix cells * * @access private * @var float * @see getMin() * @see getMinMax() */ var $_min = null; /** * The biggest value of all matrix cells * * @access private * @var float * @see getMax() * @see getMinMax() */ var $_max = null; /** * A flag indicating if the matrix is square * i.e. if $this->_num_cols == $this->_num_rows * * @access private * @var boolean * @see isSquare() */ var $_square = false; /*}}}*/ /** * Constructor for the matrix object * * @access public * @param array $data * @return object Math_Matrix * @see $_data * @see setData() */ function Math_Matrix ($data=null) {/*{{{*/ if (!is_null($data)) $this->setData($data); }/*}}}*/ /** * Validates the data and initializes all the internal variables. * * The validation is performed by by checking that * each row (first dimension in the array of arrays) * contains the same number of colums (e.g. arrays of the * same size) * * @access public * @param array $data array of arrays to create a matrix object * @return mixed true on success, a PEAR_Error object otherwise * * @see $_data * @see $_num_rows * @see $_num_cols * @see $_square * @see findMinMax() */ function setData($data) {/*{{{*/ $errorObj = PEAR::raiseError('Invalid data, cannot create/modify matrix'); if (!is_array($data) || !is_array($data[0])) return $errorObj; // check that we got a numeric bidimensional array // and that all rows are of the same size $nc = count($data[0]); $nr = count($data); for ($i=0; $i < $nr; $i++) { if (count($data[$i]) != $nc) return $errorObj; for ($j=0; $j < $nc; $j++) { if (!is_numeric($data[$i][$j])) return $errorObj; $tmp[] = $data[$i][$j]; } } $this->_num_rows = $nr; $this->_num_cols = $nc; $this->_square = ($nr == $nc); $this->_min = min($tmp); $this->_max = max($tmp); $this->_data = $data; return true; }/*}}}*/ function isEmpty() {/*{{{*/ return ( $this->_data == null ); }/*}}}*/ /** * Returns the an array with the number of rows and columns * in the matrix * * @access public * @return mixed an array of integers on success, a PEAR_Error object otherwise */ function getSize() { if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); else return array($this->_num_rows, $this->_num_cols); } function setElement($row, $col, $value) { if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); if ($row >= $this->_num_rows && $col >= $this->_num_cols) return PEAR::raiseError('Incorrect row and column values'); if (!is_numeric($value)) return PEAR::raiseError('Incorrect value, expecting a number'); $this->_data[$row][$col] = $value; return true; } function getElement($row, $col) { if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); if ($row >= $this->_num_rows && $col >= $this->_num_cols) return PEAR::raiseError('Incorrect row and column values'); return $this->_data[$row][$col]; } function getRow ($row) {/*{{{*/ if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); if ($row >= $this->_num_rows) return PEAR::raiseError('Incorrect row value'); return $this->_data[$row]; }/*}}}*/ function getCol ($col) {/*{{{*/ if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); if ($col >= $this->_num_cols) return PEAR::raiseError('Incorrect column value'); for ($i=0; $i < $this->_num_rows; $i++) $ret[$i] = $this->getElement($i,$col); return $ret; }/*}}}*/ function setRow ($row, $arr) {/*{{{*/ if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); if ($row >= $this->_num_rows) return PEAR::raiseError('Incorrect row value'); if (count($arr) != $this->_num_cols) return PEAR::raiseError('Incorrect size for matrix row'); for ($i=0; $i < $this->_num_cols; $i++) if (!is_numeric($arr[$i])) return PEAR::raiseError('Incorrect values, expecting numbers'); $this->_data[$row] = $arr; return true; }/*}}}*/ function setCol ($col, $arr) {/*{{{*/ if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); if ($col >= $this->_num_cols) return PEAR::raiseError('Incorrect column value'); if (count($arr) != $this->_num_cols) return PEAR::raiseError('Incorrect size for matrix column'); for ($i=0; $i < $this->_num_rows; $i++) { if (!is_numeric($arr[$i])) { return PEAR::raiseError('Incorrect values, expecting numbers'); } else { $err = $this->setElement($i, $col, $arr[$i]); if (PEAR::isError($err)) return $err; } } return true; }/*}}}*/ function getData () {/*{{{*/ if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); else return $this->_data; }/*}}}*/ function getMin () {/*{{{*/ if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); else return $this->_min; }/*}}}*/ function getMax () {/*{{{*/ if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); else return $this->_max; }/*}}}*/ function getMinMax () {/*{{{*/ if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); else return array ($this->_min, $this->_max); }/*}}}*/ function getValueIndex ($val) {/*{{{*/ if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); for ($i=0; $i < $this->_num_rows; $i++) for ($j=0; $j < $this->_num_cols; $j++) if ($this->_data[$i][$j] == $val) return array($i, $j); return false; }/*}}}*/ function getMinIndex () {/*{{{*/ if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); return $this->getValueIndex($this->_min); }/*}}}*/ function getMaxIndex () {/*{{{*/ if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); return $this->getValueIndex($this->_max); }/*}}}*/ function getMinMaxIndex () {/*{{{*/ if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); else return array_merge($this->getMinIndex(), $this->getMaxIndex()); }/*}}}*/ function isSquare () {/*{{{*/ if (is_null($this->_data)) return PEAR::raiseError('Matrix has not been populated'); else return $this->_square; }/*}}}*/ function toString ($format="%4s") {/*{{{*/ if (is_null($this->_data)) 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; }/*}}}*/ function toHTML() {/*{{{*/ if (is_null($this->_data)) 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"; }/*}}}*/ } // end of Math_Matrix class/*}}}*/ // vim: ts=4:sw=4:et: // vim6: fdl=1: ?> Index: pear/Math_Matrix/MatrixOp.php +++ pear/Math_Matrix/MatrixOp.php <?php // // +----------------------------------------------------------------------+ // | PHP version 4.0 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997-2001 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.02 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Authors: Jesus M. Castagnetto <jmcastagnetto@php.net> | // +----------------------------------------------------------------------+ // // Matrix manipulation class // // $Id: MatrixOp.php,v 1.1 2002/05/23 09:43:50 jmcastagnetto Exp $ // /** * Matrix operations class * A static class implementing methods to operate on Matrix objects. * * Originally this class was part of NumPHP (Numeric PHP package) * * @author Jesus M. Castagnetto <jmcastagnetto@php.net> * @access public * @version 1.0 * @package Math_Matrix */ class Math_MatrixOp {/*{{{*/ function &readFromFile ($filename) {/*{{{*/ if (!file_exists($filename) || !is_readable($filename)) return PEAR::raiseError('File cannot be opened for reading'); if (filesize($filename) == 0) return PEAR::raiseError('File is empty'); if (function_exists("file_get_contents")) $objser = file_get_contents($filename); else $objser = implode("",file($filename)); $obj = unserialize($objser); if (Math_MatrixOp::isMatrix($obj)) return $obj; else return PEAR::raiseError('File did not contain a Math_Matrix object'); }/*}}}*/ function writeToFile (&$matrix, $filename) {/*{{{*/ if (!Math_MatrixOp::isMatrix($matrix)) return PEAR::raiseError("Parameter must be a Math_Matrix object"); if ($matrix->isEmpty()) return PEAR::raiseError("Math_Matrix object is empty"); $objser = serialize($matrix); $fp = fopen($filename, "w"); if (!$fp) return PEAR::raiseError("Cannot write to file $filename"); fwrite($fp, $objser); fclose($fp); return true; }/*}}}*/ function isMatrix (&$matrix) {/*{{{*/ if (function_exists("is_a")) return is_a($matrix, "Math_Matrix"); else return (get_class($matrix) == "math_matrix"); }/*}}}*/ function &makeMatrix ($nrows, $ncols, $value) {/*{{{*/ for ($i=0; $i<$nrows; $i++) $m[$i] = explode(":",substr(str_repeat($value.":",$ncols),0,-1)); return new Math_Matrix($m); }/*}}}*/ function &makeOne ($nrows, $ncols) {/*{{{*/ return Math_MatrixOp::makeMatrix ($nrows, $ncols, 1); }/*}}}*/ function &makeZero ($nrows, $ncols) {/*{{{*/ return Math_MatrixOp::makeMatrix ($nrows, $ncols, 0); }/*}}}*/ function &makeUnit ($size) {/*{{{*/ for ($i=0; $i<=$size; $i++) for ($j=0; $j<=$size; $j++) $data[$i][$j] = (int) ($i == $j); return new Math_Matrix($data); }/*}}}*/ function &add (&$m1, &$m2) {/*{{{*/ if (!Math_MatrixOp::isMatrix($m1) || !Math_MatrixOp::isMatrix($m2)) return PEAR::raiseError("Parameters must be matrix objects"); if ($m1->getSize() != $m2->getSize()) return PEAR::raiseError("Matrices must have the same dimensions"); list($nr, $nc) = $m1->getSize(); for ($i=0; $i < $nr; $i++) for ($j=0; $j < $nc; $j++) $out[$i][$j] = $m1->getElement($i,$j) + $m2->getElement($i,$j); return new Math_Matrix($out); }/*}}}*/ function &sub (&$m1, &$m2) {/*{{{*/ if (!Math_MatrixOp::isMatrix($m1) || !Math_MatrixOp::isMatrix($m2)) return PEAR::raiseError("Parameters must be matrix objects"); if ($m1->getSize() != $m2->getSize()) return PEAR::raiseError("Matrices must have the same dimensions"); list($nr, $nc) = $m1->getSize(); for ($i=0; $i < $nr; $i++) for ($j=0; $j < $nc; $j++) $out[$i][$j] = $m1->getElement($i,$j) - $m2->getElement($i,$j); return new Math_Matrix($out); }/*}}}*/ function &scale (&$m1, $scale) {/*{{{*/ if (!Math_MatrixOp::isMatrix($m1) || !is_numeric($scale)) return PEAR::raiseError("Parameters must be a matrix object and a number"); list($nr, $nc) = $m1->getSize(); for ($i=0; $i < $nr; $i++) for ($j=0; $j < $nc; $j++) $out[$i][$j] = $scale * $m1->getElement($i,$j); return new Math_Matrix($out); }/*}}}*/ function &getSubMatrix (&$m1, $tlrow, $tlcol, $nrows, $ncols) {/*{{{*/ if (!Math_MatrixOp::isMatrix($m1) || !is_numeric($tlrow) || !is_numeric($tlcol) || !is_numeric($nrows) || !is_numeric($ncols)) return PEAR::raiseError("Parameters must be a matrix object and 4 numbers"); for ($i=0; $i < $nrows; $i++) for ($j=0; $j < $ncols; $j++) $data[$i][$j] = $m1->data[$i + $trow][$j + $tcol]; return new Math_Matrix($data); }/*}}}*/ function &transpose (&$m1) {/*{{{*/ if (!Math_MatrixOp::isMatrix($m1) || !$m1->isSquare()) return PEAR::raiseError("Parameter must be a square matrix object"); list($nr, $nc) = $m1->getSize(); for ($i=0; $i < $nc; $i++) $data[$i] = $m1->getCol($i); return new Math_Matrix($data); }/*}}}*/ function &swapRows ($m1, $row1, $row2) {/*{{{*/ if (!Math_MatrixOp::isMatrix($m1) || !is_int($row1) || !is_int($row2)) return PEAR::raiseError("Parameters must be a matrix and 2 row indices"); $r1 = $m1->getRow($row1); $m1->setRow($row1, $m1->getRow($row2)); $m1->setRow($row2, $r1); return $m1; }/*}}}*/ function &swapCols ($m1, $col1, $col2) {/*{{{*/ if (!Math_MatrixOp::isMatrix($m1) || !is_int($col1) || !is_int($col2)) return PEAR::raiseError("Parameters must be a square matrix and 2 col indices"); $r1 = $m1->getCol($col1); $m1->setCol($col1, $m1->getCol($col2)); $m1->setCol($col2, $r1); return $m1; }/*}}}*/ function &swapRowCol ($m1, $row, $col) {/*{{{*/ if (!Math_MatrixOp::isMatrix($m1) || !$m1->isSquare() || !is_int($row) || !is_int($col)) return PEAR::raiseError("Parameters must be a matrix, and a row and a column indices"); $c = $m1->getCol($col); $m1->setCol($col, $m1->getRow($row)); $m1->setRow($row, $c); return $m1; }/*}}}*/ } // end of class Math_MatrixOp/*}}}*/ // vim: ts=4:sw=4:et: // vim6: fdl=1: ?> Index: pear/Math_Matrix/examples/ex_matrix.php +++ pear/Math_Matrix/examples/ex_matrix.php <?php require_once "Matrix.php"; require_once "MatrixOp.php"; $dat = array( array(2,3,4), array(5,-1,3), array(-2,2,9), array(0,3,8) ); $dsq = array( array(2,3,4), array(-2,2,5), array(0,3,8) ); $m = new Math_Matrix($dat); list($nr, $nc) = $m->getSize(); echo "Matrix m\n"; echo "Min: ".$m->getMin()." , Max: ".$m->getMax()."\n"; echo "Rows: $nr , Columns: $nc\n"; echo "Element at (0,1) = ".$m->getElement(0,1)."\n"; list($er, $ec) = $m->getMinIndex(); echo "Min element is ($er,$ec) = ".$m->getMin()."\n"; list($er, $ec) = $m->getMaxIndex(); echo "Max element is ($er,$ec) = ".$m->getMax()."\n"; echo "toString()\n".$m->toString(); //echo "Printing table\n".$m->toHTML(); echo "writing m to file 'tmatrix.dat'\n"; Math_MatrixOp::writeToFile($m,"tmatrix.dat"); echo "...reading from file into temp:\n"; $temp = Math_MatrixOp::readFromFile("tmatrix.dat"); echo $temp->toString(); $sum = Math_MatrixOp::add($m, $temp); echo "m + temp:\n".$sum->toString(); $temp = Math_MatrixOp::scale ($temp, 0.834); echo "scale temp by 0.834\n".$temp->toString("%6.3f"); $sub = Math_MatrixOp::sub($m, $temp); echo "m - temp:\n".$sub->toString("%6.3f"); $msq = new Math_Matrix($dsq); echo "Matrix msq:\n".$msq->toString("%6.0f"); $transp = Math_MatrixOp::transpose($msq); if (PEAR::isError($transp)) echo $transp->getMessage()."\n"; else echo "transpose(msq):\n".$transp->toString("%6.0f"); $transp = Math_MatrixOp::swapRows($transp,0,1); echo "swap rows 0<->1\n".$transp->toString("%6.0f"); $transp = Math_MatrixOp::swapCols($transp,0,2); echo "swap cols 0<->2\n".$transp->toString("%6.0f"); $transp = Math_MatrixOp::swapRowCol($transp,0,1); echo "swap row<->col 0<->1\n".$transp->toString("%6.0f"); $d = Math_MatrixOp::makeMatrix(2,3,-2); echo "new matrix d (2 x 3), filled w/ -2\n".$d->toString(); $e = Math_MatrixOp::makeOne(3,2); echo "new matrix e (3 x 2), filled w/ 1\n".$e->toString(); $u = Math_MatrixOp::makeUnit(3); echo "new matrix u (unit matrix of size 4)\n".$u->toString(); ?>
« previous php.pear.cvs (#4047) next »