/***************************************************************************
 *   Copyright (C) 2007 by Honorius Galmeanu                               *
 *   honorius_galmeanu@yahoo.com                                           *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 *                                                                         *
 *   Copyright: See COPYING file that comes with this distribution         *
 *                                                                         *
 ***************************************************************************/

#ifndef __IDCOMMON_H__
#define __IDCOMMON_H__

#define	ALLOC(type,n) (type *) malloc (n * sizeof (type))
#define	TRACE(format...) { \
	printf ("---(%s:%d) ", __FILE__, __LINE__); \
	printf (format); \
	printf ("\n"); }

#define INFO(lvl,format...) \
	if (lvl <= g_dbgLevel) printf (format)


#define MINVAL 1E-14
#define MINVAL2 1E-9
#define IS_ZERO(x) (x < MINVAL && x > -MINVAL)
#define IS_ZERO2(x) (x < MINVAL2 && x > -MINVAL2)
#define IS_CONST(x,C) (x-C < MINVAL && C-x < MINVAL)
#define IS_CONST2(x,C) (x-C < MINVAL2 && C-x < MINVAL2)


#define	PARAM_VIEW_STATE	0x01
#define	PARAM_DECREASE_C	0x02
#define	PARAM_RESTORE_C		0x04
#define PARAM_PRECALCULATE	0x08
#define PARAM_BUG_FIND		0x10


template <class T> inline void swap (T& x, T& y) { T t = x; x = y; y = t; }

template <class T> inline T min (T& x, T& y) { return x < y ? x : y; }


template <class T>
struct x_vector
{
	T *	e;
public:
	const int length;
public:
	x_vector (void);
	x_vector (int l);
	~x_vector (void);

	int store (FILE * file);
	int restore (FILE * file);

	void ensure (int l);

	T& operator[] (int idx);
};


template <class T>
struct x_line
{
	T * e;

	int length;
	int size;
public:
	x_line (int size_ = 10);
	~x_line (void);

	inline const int& len (void) { return length; } 

	void expand (int l = 1);
	void ensure (int l);

	void add (T& t);
	void remove (int pos);

	void print (char * string = NULL);

	T& operator[] (int idx);
};


template <class T>
struct x_matrix
{
	T ** e;

	int length;
	int size;
public:
	x_matrix (int size_ = 10);
	~x_matrix (void);

	inline int len (void) { return length; }

	void expand (int l = 1);
	void ensure (int l);
	void remove (int pos);

	void print (void);

	T * operator[] (int idx);
};


template <class T>
struct x_product
{
	static void dot_ll (/* in */ x_line<T>& l1, /* in */ x_line<T>& l2, /* out */ T& out);
	static void cross_ll (/* in */ x_line<T>& l1, /* in */ x_line<T>& l2, /* out */ x_matrix<T>& out);
	static void mul_ml (/* in */ x_matrix<T>& m, /* in */ x_line<T>& l, /* out */ x_line<T>& out);
	static void mul_lm (/* in */ x_line<T>& l, /* in */ x_matrix<T>& m, /* out */ x_line<T>& out);
	static void mul_mm (/* in */ x_matrix<T>& m1, /* in */ x_matrix<T>& m2, /* out */ x_matrix<T>& out);
};


struct x_elem
{
	enum TYPE { ZERO, UNBOUNDED, BOUNDED };

	int 		idx;
	double 		lambda;
	x_elem::TYPE	type;

	inline int operator> (x_elem& v) { return idx > v.idx; }
	inline int operator< (x_elem& v) { return idx < v.idx; }
	inline int operator== (x_elem& v) { return idx == v.idx; }
};


// lightsvm format
struct x_svm_node
{
	int idx;	// index
	float val;	// value

};

struct x_svm_problem
{
	int n;				// nr. patterns
	float * y;			// labels
	struct x_svm_node ** x;		// links to patterns
	struct x_svm_node * x_all;	// patterns

	x_svm_problem (void);
	~x_svm_problem (void);
};

struct x_svm_param
{
	int	kernel_type;
	double	sigma;		// RBF kernel sigma parameter
	double	C;		// SVM cost parameter

	int 	saveEvery;	// saves context every n'th state 
	char * 	restoreFrom;	// initial context restored from given state
	char * 	saveTo;		// prefix for stored state name
	int	info;		// additional processing on restored sessions
	double	newC;		// for -dc c option

	char *	input_file;	// input patterns file name
	char * 	test_file;	// test patterns

	int	firstLabel;	// first class label, -1 if not defined
	int	secondLabel;	// second class label, -1 if not defined
	int	cross_k;	// k-fold cross validation, this is k
	int	cross_test;	// use this set (of all k) for test; goes from [0, cross_k)

	x_svm_param (void); 
	~x_svm_param (void);
};

class x_svm_kernel
{
	enum { LINEAR, RBF, LAST };	// kernel types

	const struct x_svm_node * const * x;
	double * x_square;

	const int kernel_type;
	const double sigma;

	double (x_svm_kernel::*kernel_function) (int i, int j) const;
	double (x_svm_kernel::*kernel_extended) (const x_svm_node * px, const x_svm_node * py) const;

protected:
	static double dot (const x_svm_node * px, const x_svm_node * py);
	double kernel_linear (int i, int j) const;
	double kernel_linear_ext (const x_svm_node * px, const x_svm_node * py) const;
	double kernel_rbf (int i, int j) const;
	double kernel_rbf_ext (const x_svm_node * px, const x_svm_node * py) const;

public:
	inline double K (int i, int j) { return (this->*kernel_function) (i, j); }
	inline double K_ext (const x_svm_node * px, const x_svm_node * py) { return (this->*kernel_extended) (px, py); }

	x_svm_kernel (int l, const struct x_svm_node * const * x_, const x_svm_param& param);
	~x_svm_kernel (void);
};


#endif // __IDCOMMON_H__
