<?php
namespace NumbersPHP\Tests;

use NumbersPHP\Matrix;

/**
 * Generated by PHPUnit_SkeletonGenerator 1.2.0 on 2013-02-25 at 11:22:01.
 */
class MatrixTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var Matrix
     */
    protected $object;

    /**
     * Sets up the fixture, for example, opens a network connection.
     * This method is called before a test is executed.
     */
    protected function setUp()
    {
        $this->object = new Matrix;
    }

    /**
     * Tears down the fixture, for example, closes a network connection.
     * This method is called after a test is executed.
     */
    protected function tearDown()
    {
    }

    /**
     * @covers NumbersPHP\Matrix::isSquare
     */
    public function testIsSquare()
    {
        $this->assertTrue(\NumbersPHP\Matrix::isSquare(array(array(1, 2), array(3, 4))));
        $this->assertFalse(\NumbersPHP\Matrix::isSquare(array(array(1, 2, 3), array(4, 5, 6))));
    }

    /**
     * @covers NumbersPHP\Matrix::addition
     */
    public function testAddition()
    {
        $a = array(array(0, 1, 2),
            array(3, 4, 5));
        $b = array(array( 6,  7,  8),
            array( 9, 10, 11));
        $c = array(array( 6,  8, 10),
            array(12, 14, 16));
        $this->assertEquals($c, \NumbersPHP\Matrix::addition($a, $b));
    }

    /**
     * @covers NumbersPHP\Matrix::scalar
     */
    public function testScalar()
    {
        $a = array(array(0, 1, 2),
            array(3, 4, 5));
        $b = 5;
        $c = array(array( 0,  5, 10),
            array(15, 20, 25));
        $this->assertEquals($c, \NumbersPHP\Matrix::scalar($a, $b));
    }

    /**
     * @covers NumbersPHP\Matrix::transpose
     */
    public function testTranspose()
    {
        $a = array(array(0, 1, 2),
            array(3, 4, 5));
        $b = array(array(0, 3),
            array(1, 4),
            array(2, 5));
        $this->assertEquals($b, \NumbersPHP\Matrix::transpose($a));
    }

    /**
     * @covers NumbersPHP\Matrix::identity
     */
    public function testIdentity()
    {
        $a = array(array(1, 0, 0),
            array(0, 1, 0),
            array(0, 0, 1));
        $this->assertEquals($a, \NumbersPHP\Matrix::identity(3));
    }

    /**
     * @covers NumbersPHP\Matrix::dotproduct
     */
    public function testDotproduct()
    {
        $this->assertEquals(28, \NumbersPHP\Matrix::dotproduct(array(0, 1, 2, 3), array(-1, 2, 4, 6)));
    }

    /**
     * @covers NumbersPHP\Matrix::multiply
     */
    public function testMultiply()
    {
        $a = array(array(0, 1, 2),
            array(3, 4, 5));
        $b = array(array(0, 3),
            array(1, 4),
            array(2, 5));
        $c = array(array( 5, 14),
            array(14, 50));
        $this->assertEquals($c, \NumbersPHP\Matrix::multiply($a, $b));

        $a = array(array(0, 1, 2),
            array(3, 4, 5));
        $b = array(array(0),
            array(1),
            array(2));
        $c = array(array( 5),
            array(14));
        $this->assertEquals($c, \NumbersPHP\Matrix::multiply($a, $b));
    }



    /**
     * @covers NumbersPHP\Matrix::determinant
     */
    public function testDeterminant()
    {
        $a = array(array(1));
        $this->assertEquals(1, \NumbersPHP\Matrix::determinant($a));

        $b = array(array(2, 3),
            array(6, 7));
        $this->assertEquals(-4, \NumbersPHP\Matrix::determinant($b));

        $c = array(array(0, 1, 2),
            array(3, 4, 5),
            array(6, 7, 8));
        $this->assertEquals(0, \NumbersPHP\Matrix::determinant($c));
    }

    /**
     * @covers NumbersPHP\Matrix::determinant
     * @expectedException \Exception
     */
    public function testDeterminantException()
    {
        \NumbersPHP\Matrix::determinant(
            array(array( 3, -7,  8,  9, -6),
            array( 0,  2, -5,  7,  3),
            array( 0,  0,  1,  5,  0),
            array( 0,  0,  0, -2,  0))
        );
    }

    /**
     * @covers NumbersPHP\Matrix::lupDecomposition
     */
    public function testLupDecomposition()
    {
        $a = array(array( 1,  0,  0,  2),
            array( 2, -2,  0,  5),
            array( 1, -2, -2,  3),
            array( 5, -3, -5,  2));
        $b = array(array( 1,  0,  0,  2),
            array( 1, -2,  0,  5),
            array( 1, -2,  0,  3),
            array( 1, -3, -5,  0));
        $lupA = \NumbersPHP\Matrix::lupDecomposition($a);
        $this->assertEquals(
            \NumbersPHP\Matrix::multiply($lupA[2], $a),
            \NumbersPHP\Matrix::multiply($lupA[0], $lupA[1])
        );

        $lupB = \NumbersPHP\Matrix::lupDecomposition($b);
        $this->assertEquals(
            \NumbersPHP\Matrix::multiply($lupB[2], $b),
            \NumbersPHP\Matrix::multiply($lupB[0], $lupB[1])
        );
    }

    /**
     * @covers NumbersPHP\Matrix::lupDecomposition
     * @expectedException \Exception
     */
    public function testLupDecompositionException()
    {
        \NumbersPHP\Matrix::lupDecomposition(array(array(1, 2, 3), array(4, 5, 6)));
    }

    /**
     * @covers NumbersPHP\Matrix::rotate
     */
    public function testRotate()
    {
        $a = \NumbersPHP\Matrix::rotate(array(array(0), array(1)), 90, 'clockwise');
        $this->assertTrue(
            \NumbersPHP\Basic::numbersEqual($a[0][0], 1) &&
            \NumbersPHP\Basic::numbersEqual($a[1][0], 0)
        );
    }

    /**
     * @covers NumbersPHP\Matrix::rotate
     * @expectedException \Exception
     */
    public function testRotateException()
    {
        \NumbersPHP\Matrix::rotate(array(array(0), array(1), array(2)), 90, 'clockwise');
    }

    /**
     * @covers NumbersPHP\Matrix::scale
     */
    public function testScale()
    {
        $this->assertEquals(
            array(array(20), array(25)),
            \NumbersPHP\Matrix::scale(array(array(2), array(5)), 10, 5)
        );
    }

    /**
     * @covers NumbersPHP\Matrix::scale
     * @expectedException \Exception
     */
    public function testScaleException()
    {
        \NumbersPHP\Matrix::scale(array(array(0), array(1), array(2)), 10, 5);
    }

    /**
     * @covers NumbersPHP\Matrix::shear
     */
    public function testShear()
    {
        $this->assertEquals(
            array(array(52), array(5)),
            \NumbersPHP\Matrix::shear(array(array(2), array(5)), 10, 'xaxis')
        );

        $this->assertEquals(
            array(array(2), array(25)),
            \NumbersPHP\Matrix::shear(array(array(2), array(5)), 10, 'yaxis')
        );
    }

    /**
     * @covers NumbersPHP\Matrix::shear
     * @expectedException \Exception
     */
    public function testShearException()
    {
        \NumbersPHP\Matrix::shear(array(array(0), array(1), array(2)), 10, 'yaxis');
    }

    /**
     * @covers NumbersPHP\Matrix::affine
     */
    public function testAffine()
    {
        $this->assertEquals(array(array(12), array(15)), \NumbersPHP\Matrix::affine(array(array(2), array(5)), 10, 10));
    }

    /**
     * @covers NumbersPHP\Matrix::affine
     * @expectedException \Exception
     */
    public function testAffineException()
    {
        \NumbersPHP\Matrix::affine(array(array(0), array(1), array(2)), 10, 10);
    }

    /**
     * @covers NumbersPHP\Matrix::rowScale
     */
    public function testRowScale()
    {
        $a = array(array( 0,  1,  2),
            array( 3, -1,  5),
            array( 1,  2,  5));
        $b = array(array( 0,  0,  0),
            array( 3, -1,  5),
            array( 1,  2,  5));
        $c = array(array(  0,   1,   2),
            array( -6,   2, -10),
            array(  1,   2,   5));
        $this->assertEquals($b, \NumbersPHP\Matrix::rowScale($a, 0, 0));

        $this->assertEquals($c, \NumbersPHP\Matrix::rowScale($a, 1, -2));

        $this->assertEquals($a, \NumbersPHP\Matrix::rowScale($a, 1, 1));
    }

    /**
     * @covers NumbersPHP\Matrix::rowSwitch
     */
    public function testRowSwitch()
    {
        $a = array(array( 0,  1,  2),
            array( 3, -1,  5),
            array( 1,  2,  5));
        $b = array(array( 3, -1,  5),
            array( 0,  1,  2),
            array( 1,  2,  5));
        $this->assertEquals($b, \NumbersPHP\Matrix::rowSwitch($a, 0, 1));
    }

    /**
     * @covers NumbersPHP\Matrix::rowAddMultiple
     */
    public function testRowAddMultiple()
    {
        $a = array(array( 0,  1,  2),
            array( 3, -1,  5),
            array( 1,  2,  5));
        $b = array(array(0, 1, 2),
            array(3, 1, 9),
            array(1, 2, 5));
        $this->assertEquals($b, \NumbersPHP\Matrix::rowAddMultiple($a, 0, 1, 2));
    }
}
