

#include <pw/core/matrix.hpp>
#include <pw/core/vector.hpp>
#include <pw/core/serialize.hpp>

#include <pw/core/debug.hpp>

#include <iostream>
#include <sstream>


int main(int argc,char **argv) {

    using namespace pw;

    matrix2x2f m22; m22.zero();


    m22(0,0) = 1; m22(0,1) = 2;
    m22(1,0) = 3; m22(1,1) = 4;

	vector2f v2;
	v2[0] = 1; v2[1] = 3;

	vector2f v3( { 1.f,2.f } );


	auto m22_inv = m22.inverse();
	auto m22_id = m22_inv * m22;

	auto v2_t = m22_id * v2;
	auto v3_t = m22_id * v3;

	auto v2_f = m22 * v2;
	auto v2_b = m22_inv * v2_f;

    vector2_<float> r_m22 = m22.row(0).transposed();
    vector2_<float> c_m22 = m22.column(1);

    auto r_m22_h = r_m22.homogenous();

    debug::d() << "offset(0,1) col-major " << m22.offset(0,1);
    debug::d() << "det " << m22.determinant();

	std::cout << "m22 " << pw::serialize::matrix(m22) << std::endl;
	std::cout << "m22-1 " << pw::serialize::matrix(m22_inv) << std::endl;
	std::cout << "m22-i " << pw::serialize::matrix(m22_id) << std::endl;
	std::cout << "v22_t " << pw::serialize::matrix(v2_t) << std::endl;
	std::cout << "v3_t " << pw::serialize::matrix(v3_t) << std::endl;


	std::cout << "v2_f " << pw::serialize::matrix(v2_f) << std::endl;
	std::cout << "v2_b " << pw::serialize::matrix(v2_b) << std::endl;

	std::cout << "v2_b.norm " << v2_b.norm() << std::endl;

//	v2_b.normalize();
	std::cout << "v2_b.normalized " << pw::serialize::matrix(v2_b.normalized()) << std::endl;

//	std::cout << "v2_b~v3_t " << rad_to_deg(vector2f::angle_between(v2,v3)) << std::endl;






//    vector2f v2 = m22.slice<2,1>(0,0);
//    m22.set_slice<2,1>(v2,0,0);

//    v2 *= 2;
//    v2 += 1;

//    m22 *= 3;

//    m22.determinant();

//    debug::d() << sizeof(v2);

//    auto m22_i = m22.inverse();



#if 0

    pw::matrix4x4d m;

    m.set_identity();

    std::cout << "m = " << pw::serialize::matrix(m) << std::endl;

    std::cout << "row_stride() : " << m.row_stride() << std::endl;
    std::cout << "col_stride() : " << m.col_stride() << std::endl;
    std::cout << "rows()       : " << m.rows() << std::endl;
    std::cout << "cols()       : " << m.cols() << std::endl;
    std::cout << "data()       : " << m.data() << std::endl;
    std::cout << "data()[0]    : " << m.data()[0] << std::endl;
    std::cout << "at(0,0)      : " << m.at(0,0) << std::endl;
    std::cout << "determinant(): " << m.determinant() << std::endl;


    pw::matrix4x4d mi = m.get_inverse();

    std::cout << "mi.at(0,0)   : " << mi.at(0,0) << std::endl;


    pw::matrix4x4d mscale = m * 4.2;


    std::cout << "mscale = " << pw::serialize::matrix(mscale) << std::endl;


    pw::matrix4x4d a;

    for (int r = 0; r < m.rows(); r++) {
        for (int c = 0; c < m.cols(); c++) {
            a.at(r,c) = r * m.cols() + c;
        }
    }
    std::cout << "a = " << pw::serialize::matrix(a) << std::endl;

    pw::matrix4x4d r = a * mscale;

    std::cout << "a * mscale = " << pw::serialize::matrix(r) << std::endl;


    return 0;

#endif
}
