#ifndef NLTRANS_H
# define NLTRANS_H

# ifndef GPK_STD_H
#  include <gpk_std.h>
# endif
# ifndef M22V2_H
#  include "m22v2.h"
# endif
# ifndef T222_H
#  include "t222.h"
# endif
# ifndef LTRANS_H
#  include "ltrans.h"
# endif
// # include <iostream.h>
# ifndef NLINE_H
#  include "nline.h"
# endif
# ifndef LINE_H
#  include "line.h"
# endif
# ifndef TRANS_H
#  include "trans.h"
# endif


#define N_IMAGES 2

class nltransform : public transform	{
	tensor222 nl;
	matrix22 warp;
	vector2 shift;
	vector2 center;

	public:
	nltransform(C nltransform& a);
	~nltransform();
	nltransform();
	nltransform(C tensor222& n,
					C ltransform& t,
					C vector2& ctr);
	nltransform(C tensor222& n, C matrix22&w, C vector2& s, C vector2& ctr);
	nltransform(C vector2& init_and_ctr, C vector2& final_point,
				C matrix22& warp, C tensor222& n);
	nltransform& operator=(C nltransform& i);

	static nltransform identity(C vector2& center);
	void set_in_space(C vector_space *i);
	void set_out_space(C vector_space *o);

	BOOL ok() C;
	matrix22 Jacobian(C vector2& x) C;
	double Wronskian(C vector2& x) C	{return Jacobian(x).determinant();}
	friend nltransform inverse(C nltransform& x);	/* Approx inverse xform. */
	vector2 inverse(C vector2& x) C;	/* exact inverse of one point. */
	friend nltransform sqrt(C nltransform& x);
	vector2 operator()(C vector2&) C;
	nltransform operator()(C nltransform&) C;
	nltransform operator()(C ltransform&) C;
	nline operator()(C line&) C;
	nline operator()(C nline&) C;
	vector2 Shift() C	{return shift;}
	vector2 Center() C	{return center;}
	C matrix22& Warp() C	{return warp;}
	C tensor222& Nl() C	{return nl;}
	ltransform linearize() C;
	nltransform& recenter(C vector2& newcenter);
	// friend ostream& operator<<(ostream& s, C nltransform& t);
	};

nltransform operator*(C ltransform& a, C nltransform& b);
inline nltransform operator*(C nltransform& a, C ltransform& b)
	{return a(b);}
nltransform sqrt(C nltransform& x);
inline nltransform operator*(C nltransform& x, C nltransform& y)
	{return x(y);}
nltransform inverse(C nltransform& x);
// ostream& operator<<(ostream& s, C nltransform& t);

#endif
