/** * Rotate the matrix through 90, 180 or 270 degrees * * @param Matrix $mA First matrix operand - required * @param int $extra Rotation degrees - default null = self::ROT_90 (counter clockwise) * * @return Matrix * * @throws \Chippyash\Matrix\Exceptions\TransformationException */ protected function doTransform(Matrix $mA, $extra = null) { if (is_null($extra)) { $extra = self::ROT_90; } else { if (!array_key_exists($extra, $this->rotationMatrices)) { throw new TransformationException('Rotation angle not supported'); } } //simple cases if ($mA->is('empty') || $mA->is('singleitem')) { return clone $mA; } $this->assertMatrixIsComplete($mA); return $this->rotate($mA, $this->rotationMatrices[$extra]); }
/** * Check that matrix is square * * @param \Chippyash\Matrix\Matrix $matrix * @param string $msg Optional message * @return $this * * @throws MatrixException */ protected function assertMatrixIsSquare(Matrix $matrix, $msg = 'Matrix is not square') { if (!$matrix->is('square')) { throw new MatrixException($msg); } return $this; }
/** * Check matrix is not empty * * @param \Chippyash\Matrix\Matrix $matrix * @param string $msg optional error message` * * @return $this * * @throws MatrixException */ protected function assertMatrixIsNotEmpty(Matrix $matrix, $msg = 'Matrix parameter is empty') { if ($matrix->is('empty')) { throw new MatrixException($msg); } return $this; }
/** * Does the matrix have this attribute * * @param Matrix $mA * @return boolean */ public function is(Matrix $mA) { //empty matrix is ok if ($mA->is('empty')) { return true; } $data = $mA->toArray(); //check we don't have empty/missing rows $tmp = array_keys($data); //to get past error_reporting E_STRICT for Travis $top = array_pop($tmp); if ($top >= count($data)) { $this->errRow = count($data); return false; } //check that each row has same number of columns $numcols = count($data[0]); $ret = true; $r = 0; array_walk($data, function ($value, $index, $matchCols) use(&$ret, &$r) { if ($ret && count($value) != $matchCols) { $ret = false; $r = $index; } }, $numcols); if (!$ret) { $this->errRow = $r + 1; } return $ret; }
/** * Set a matrix vertex, row or column vector * If row == 0 && col > 0, then set the column vector indicated by col * If col == 0 && row > 0, then set the row vector indicated by row * if row > 0 && col > 0, set the vertex * row == col == 0 is an error * * @param int $row * @param int $col * @param mixed|Matrix $data If setting a vector, supply the correct vector matrix * * @return Matrix * @throws VerticeOutOfBoundsException * @throws MatrixException */ public function set($row, $col, $data) { if ($row < 0 || $row > $this->rows()) { throw new VerticeOutOfBoundsException('row', $row); } if ($col < 0 || $col > $this->columns()) { throw new VerticeOutOfBoundsException('col', $col); } if ($row == 0 && $col == 0) { throw new VerticeOutOfBoundsException('row & col', 0); } if (($row == 0 || $col == 0) && !$data instanceof Matrix) { throw new MatrixException('$data for set method must be a matrix'); } if ($row == 0 && $col > 0) { if (!$data->is('columnvector')) { throw new MatrixException('$data for set method must be a column vector'); } $dArr = $data->toArray(); $col--; $nRows = $this->rows(); for ($n = 0; $n < $nRows; $n++) { $this->data[$n][$col] = $dArr[$n][0]; } return $this; } if ($col == 0 && $row > 0) { if (!$data->is('rowvector')) { throw new MatrixException('$data for set method must be a row vector'); } $dArr = $data->toArray(); $row--; $nCols = $this->columns(); for ($m = 0; $m < $nCols; $m++) { $this->data[$row][$m] = $dArr[0][$m]; } return $this; } $this->data[$row - 1][$col - 1] = $data; return $this; }
/** * Does the matrix have this attribute * * @param Matrix $mA * @return boolean */ public function is(Matrix $mA) { if (!$mA->is('square')) { return false; } $size = $mA->rows(); $data = $mA->toArray(); for ($row = 0; $row < $size; $row++) { for ($col = 0; $col < $size; $col++) { if ($row == $col) { if ($data[$row][$col] == 0) { return false; } } else { if ($data[$row][$col] != 0) { return false; } } } } return true; }
/** * Take a row slice from the matrix * * @param Matrix $mA First matrix operand - required * @param array $extra [int startRow, int numRows = 1] * * @return Matrix * * @throws MatrixException */ protected function doTransform(Matrix $mA, $extra = null) { if ($mA->is('empty')) { return new Matrix(array()); } /** @noinspection PhpInternalEntityUsedInspection */ $this->assertParameterIsArray($extra, 'Second operand is not an array'); if (empty($extra)) { throw new MatrixException('Second operand does not contain row indicator'); } $row = intval($extra[0]); $availableRows = $mA->rows(); if ($row < 1 || $row > $availableRows) { throw new MatrixException('Row indicator out of bounds'); } $numRows = isset($extra[1]) ? intval($extra[1]) : 1; if ($numRows < 1 || $numRows + $row - 1 > $availableRows) { throw new MatrixException('Numrows out of bounds'); } $this->assertMatrixIsComplete($mA); return $this->doTransformation($mA, $row, $numRows); }
/** * Take a row slice from the matrix * * @param Matrix $mA First matrix operand - required * @param array $extra [int startCol, int numCols = 1] * * @return Matrix * * @throws MatrixException */ protected function doTransform(Matrix $mA, $extra = null) { if ($mA->is('empty')) { return new Matrix(array()); } /** @noinspection PhpInternalEntityUsedInspection */ $this->assertParameterIsArray($extra, 'Second operand is not an array'); if (empty($extra)) { throw new MatrixException('Second operand does not contain col indicator'); } $col = intval($extra[0]); $availableCols = $mA->columns(); if ($col < 1 || $col > $availableCols) { throw new MatrixException('Col indicator out of bounds'); } $numCols = isset($extra[1]) ? intval($extra[1]) : 1; if ($numCols < 1 || $numCols + $col - 1 > $availableCols) { throw new MatrixException('Numcols out of bounds'); } $fT = new Transpose(); $fR = new Rowslice(); return $fT($fR($fT($mA), array($col, $numCols))); }
/** * Return cofactor matrix for a given vertice * * @param Matrix $mA First matrix operand - required * @param array $extra [int row, int col] * * @return Matrix * * @throws MatrixException */ protected function doTransform(Matrix $mA, $extra = null) { if ($mA->is('empty')) { return new Matrix([]); } /** @noinspection PhpInternalEntityUsedInspection */ $this->assertParameterIsArray($extra, 'Second operand is not an array'); if (count($extra) != 2) { throw new MatrixException('Second operand does not contain row and column'); } $row = intval($extra[0]); $col = intval($extra[1]); $size = $mA->rows(); if ($row < 1 || $row > $size) { throw new MatrixException('Row indicator out of bounds'); } if ($col < 1 || $col > $size) { throw new MatrixException('Col indicator out of bounds'); } $fC = new Colreduce(); $fR = new Rowreduce(); //R(C(mA)) return $fR($fC($mA, [$col]), [$row]); }
public function testConstructNonEmptyArrayGivesNonEmptyMatrix() { $this->object = new NumericMatrix(array(2)); $this->assertInstanceOf(self::NSUT, $this->object); $this->assertFalse($this->object->is('empty')); }
public function testIsMethodAcceptsAttributeInterfaceAsParameter() { $mA = new Matrix(array()); $attr = $this->getMock('\\Chippyash\\Matrix\\Interfaces\\AttributeInterface'); $attr->expects($this->once())->method('is')->will($this->returnValue(true)); $this->assertTrue($mA->is($attr)); }