#ifndef M22_H
# define M22_H
#include <gpk_std.h>
#include <stdio.h>
#ifdef __cplusplus
# include <iostream>
  using namespace std;

#ifndef V2_H
# include "v2.h"
#endif

extern "C"	{
#endif
#include <math.h>



typedef struct	{double d[2][2]; BOOL ok;} m22;

void m22constr(m22 *p);
BOOL m22is_square(m22 a);
BOOL m22badmat(m22 a);
double m22max(m22 a);
double m22trace(m22 a);
double m22norm_2(m22 a);
double m22norm(m22 a);
m22 m22add(m22 a, m22 b);
m22 m22sub(m22 a, m22 b);
m22 m22mult(m22 a, m22 b);
m22 m22smult(m22 a, double sb);
m22 m22transpose(m22 b);
m22 m22inverse(m22 a, double *pd);
m22 m22sqrt(m22 a);
m22 m22zero();
m22 m22identity();
void m22print(FILE *fp, m22 a);

#ifdef __cplusplus
}	/* extern "C" */

class matrix22 {
	double d[2][2];

	public:
	C vector_space *in, *out;
	matrix22 ns() C {return matrix22(d[0][0], d[0][1], d[1][0], d[1][1]);}

	public:
	double operator()(int i, int j) C	{return d[i][j];}
	matrix22();
	matrix22(C matrix22& a);
	matrix22(C m22& a);
	matrix22(double a00, double a01, double a10, double a11);
	matrix22(double a00, double a01, double a10, double a11,
				C vector_space *i, C vector_space *o);
	matrix22& operator=(C matrix22& a);

	BOOL badmat() C	{return !vector_space::vsok(in)
						|| !vector_space::vsok(out);}
	BOOL ok() C	{return !badmat();}
	BOOL is_square() C	{return TRUE;}

	static matrix22 identity();
	static matrix22 rotation(double);
	double e_val(int i) C;
	double norm() C	{return sqrt(norm_2());}
	double norm_2() C;
	double max() C;
	double trace() C	{return d[0][0] + d[1][1];}
	double determinant()	C;
	matrix22& operator+=(C matrix22& a);
	matrix22& operator-=(C matrix22& a);
	};

matrix22 sqrt(C matrix22& a);
matrix22 operator-(C matrix22& a, C matrix22& b);
matrix22 operator-(C matrix22& a);
matrix22 operator*(C matrix22& a, C matrix22& b);
matrix22 transpose(C matrix22& b);
matrix22 inverse(C matrix22& a, double *pd=0);
matrix22 operator+(C matrix22& a, C matrix22& b);
matrix22 operator*(C matrix22& b, double a);
/* matrix22 operator*(double a, C matrix22& b); */
ostream& operator<<(ostream& s, C matrix22& b);


inline matrix22 operator*(double a, C matrix22& b)
		{return b*a;}
#endif

#endif
