/******************************************************************************
* Misc_lib.h - header file for the misc. library.			      *
* This header is also the interface header to the world.		      *
*******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                 *
*******************************************************************************
* Written by Gershon Elber, Oct. 94.					      *
******************************************************************************/

#ifndef MISC_LIB_H
#define MISC_LIB_H

#include <stdio.h>
#ifdef __WINCE__
#   include <memory.h>
#endif
#include "irit_sm.h"

typedef enum {
    MISC_ERR_MALLOC_FAILED,
    MISC_ERR_UNKNOWN_CONFIG,

    MISC_ERR_UNDEFINE_ERR
} MiscFatalErrorType;

typedef enum {
    IC_BOOLEAN_TYPE = 1,
    IC_INTEGER_TYPE = 2,
    IC_REAL_TYPE = 3,
    IC_STRING_TYPE = 4
} IrtCfgDataType;

typedef enum {
    IRIT_IMAGE_UNKNOWN_TYPE,
    IRIT_IMAGE_RLE_TYPE,
    IRIT_IMAGE_PPM3_TYPE,
    IRIT_IMAGE_PPM6_TYPE,
    IRIT_IMAGE_PNG_TYPE
} IrtImgImageType;

typedef struct IritConfigStruct {
    char *VarName;
    char *SomeInfo;
    VoidPtr VarData;
    IrtCfgDataType VarType;
} IritConfigStruct;

typedef struct IrtImgPixelStruct {
    ByteType r, g, b;
} IrtImgPixelStruct;

typedef struct IrtImgRGBAPxlStruct {
    ByteType r, g, b, a;
} IrtImgRGBAPxlStruct;

typedef float IrtImgRealClrType;
typedef struct IrtImgRealPxlStruct {
    IrtImgRealClrType r, g, b, a;
} IrtImgRealPxlStruct;

typedef struct IritPriorQue {
    struct IritPriorQue *Right, *Left; /* Pointers to two sons of this node. */
    VoidPtr Data;			     /* Pointers to the data itself. */
} IritPriorQue;

typedef struct IritHashElementStruct {
    struct IritHashElementStruct *Pnext;
    VoidPtr Data;
    RealType Key;
} IritHashElementStruct;

typedef struct IritHashTableStruct {
    RealType MinKeyVal, MaxKeyVal, DKey, KeyEps;
    IritHashElementStruct **Vec;
    int VecSize;
} IritHashTableStruct;

typedef int (*IritPQCompFuncType)(VoidPtr, VoidPtr);/* Comparison functions. */
typedef int (*IritHashCmpFuncType)(VoidPtr Data1, VoidPtr Data2);
typedef void IritLevenEvalFuncType(RealType *CurPoint,
				   RealType ModelParams[],
				   RealType *YPointer,
				   RealType YdParams[]);
typedef void IritLevenNumerProtectionFuncType(RealType InternalModelParams[]);
typedef int IritLevenIsModelValidFuncType(RealType InternalModelParams[]);
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

/* Basic dynamic memory allocation routines: */
#ifdef DEBUG_IRIT_MALLOC
VoidPtr IritMalloc(unsigned Size, char *ObjType, char *FileName, int LineNum);
#define IritMalloc(x)	IritMalloc((x), #x, __FILE__, __LINE__)
void IritFree(VoidPtr p);
#define IritFree(x)	{ IritFree(x); x = NULL; }
void IritTestAllDynMemory(void);
void IritInitTestDynMemory(void);
void IritInitTestDynMemory2(int DebugMalloc,
			    int DebugSearchPtr,
			    int DebugSearchPtrAbort);
void IritCheckMarkDynMemory(RealType *Start);
void IritDebugMallocSearchPtr(VoidPtr p, int Abort);
#else
#define IritMalloc(Size)	malloc(Size)
#define IritFree(Ptr)		free(Ptr)
#endif /* DEBUG_IRIT_MALLOC */
VoidPtr IritRealloc(VoidPtr p, unsigned OldSize, unsigned NewSize);

/* Prototype of the configuration routines: */
void IritConfig(char *PrgmName, IritConfigStruct *SetUp, int NumVar);
void IritConfigPrint(IritConfigStruct *SetUp, int NumVar);

/* Get command line arguments. */
#ifdef USE_VARARGS
int GAGetArgs(int va_alist, ...);
#else
int GAGetArgs(int argc, ...);
#endif /* USE_VARARGS */
char *GAStringErrMsg(int Error, char *OutStr);
void GAPrintErrMsg(int Error);
char *GAStringHowTo(char *CtrlStr, char *OutStr);
void GAPrintHowTo(char *CtrlStr);

/* Generic 4x4 matrix routines. */
void MatGenUnitMat(MatrixType Mat);
int MatIsUnitMatrix(MatrixType Mat, RealType Eps);
void MatGenMatTrans(RealType Tx, RealType Ty, RealType Tz, MatrixType Mat);
void MatGenMatUnifScale(RealType Scale, MatrixType Mat);
void MatGenMatScale(RealType Sx, RealType Sy, RealType Sz, MatrixType Mat);
void MatGenMatRotX1(RealType Teta, MatrixType Mat);
void MatGenMatRotX(RealType CosTeta, RealType SinTeta, MatrixType Mat);
void MatGenMatRotY1(RealType Teta, MatrixType Mat);
void MatGenMatRotY(RealType CosTeta, RealType SinTeta, MatrixType Mat);
void MatGenMatRotZ1(RealType Teta, MatrixType Mat);
void MatGenMatRotZ(RealType CosTeta, RealType SinTeta, MatrixType Mat);

void MatMultTwo4by4(MatrixType MatRes, MatrixType Mat1, MatrixType Mat2);
void MatAddTwo4by4(MatrixType MatRes, MatrixType Mat1, MatrixType Mat2);
void MatSubTwo4by4(MatrixType MatRes, MatrixType Mat1, MatrixType Mat2);
void MatScale4by4(MatrixType MatRes, MatrixType Mat, RealType *Scale);

void MatMultVecby4by4(VectorType VecRes, VectorType Vec, MatrixType Mat);
void MatMultPtby4by4(PointType PtRes, PointType Pt, MatrixType Mat);
void MatMultWVecby4by4(RealType VRes[4], RealType Vec[4], MatrixType Mat);

RealType MatDeterminantMatrix(MatrixType Mat);
int MatInverseMatrix(MatrixType M, MatrixType InvM);
void MatTranspMatrix(MatrixType M, MatrixType TranspM);
RealType MatScaleFactorMatrix(MatrixType M);
void MatRotateFactorMatrix(MatrixType M, MatrixType RotMat);
void MatTranslateFactorMatrix(MatrixType M, VectorType Trans);

/* QR matrix factorization. */
int IritQRFactorization(RealType *A, int n, int m, RealType *Q, RealType *R);
int IritSolveUpperDiagMatrix(RealType *A, int n, RealType *b, RealType *x);
int IritSolveLowerDiagMatrix(RealType *A, int n, RealType *b, RealType *x);
int IritQRUnderdetermined(RealType *A, RealType *x, RealType *b, int m, int n);

/* Gauss Jordan matrix solver and Levenberg Marquardt local minimum finder. */
int IritGaussJordan(RealType *A, RealType *B, unsigned N, unsigned M);
RealType IritLevenMarMin(RealType **x,
			 RealType y[],
			 RealType Sigma[],
			 unsigned NumberOfDataElements,
			 RealType ModelParams[],
			 IritLevenEvalFuncType *ShapeFunc,
			 IritLevenNumerProtectionFuncType *ProtectionFunc,
			 IritLevenIsModelValidFuncType *ModelValidatorFunc,
			 unsigned NumberOfModelParams,
			 RealType Tolerance);
RealType IritLevenMarMinSig1(RealType **XVals,
			     RealType YVals[],
			     unsigned NumberOfDataElements,
			     RealType ModelParams[],
			     IritLevenEvalFuncType *ShapeFunc,
			     IritLevenNumerProtectionFuncType *ProtectionFunc,
			     IritLevenIsModelValidFuncType *ModelValidatorFunc,
			     unsigned NumberOfMedelParams,
			     RealType Tolerance);
unsigned int IritLevenMarSetMaxIterations(unsigned NewVal);

/* An implementation of a priority queue. */
void IritPQInit(IritPriorQue **PQ);
int IritPQEmpty(IritPriorQue *PQ);
void IritPQCompFunc(IritPQCompFuncType NewCompFunc);
VoidPtr IritPQFirst(IritPriorQue **PQ, int Delete);
VoidPtr IritPQInsert(IritPriorQue **PQ, VoidPtr NewItem);
VoidPtr IritPQDelete(IritPriorQue **PQ, VoidPtr NewItem);
VoidPtr IritPQFind(IritPriorQue *PQ, VoidPtr OldItem);
VoidPtr IritPQNext(IritPriorQue *PQ, VoidPtr CmpItem, VoidPtr BiggerThan);
int IritPQSize(IritPriorQue *PQ);
void IritPQPrint(IritPriorQue *PQ, void (*PrintFunc)(VoidPtr));
void IritPQFree(IritPriorQue *PQ, int FreeItems);
void IritPQFreeFunc(IritPriorQue *PQ, void (*FreeFunc)(VoidPtr));

/* An implementation of a hashing table. */
IritHashTableStruct *IritHashTableCreate(RealType MinKeyVal,
					 RealType MaxKeyVal,
					 RealType KeyEps,
					 int VecSize);
int IritHashTableInsert(IritHashTableStruct *IHT,
			VoidPtr Data,
			IritHashCmpFuncType HashCmpFunc,
			RealType Key,
			int RplcSame);
VoidPtr IritHashTableFind(IritHashTableStruct *IHT,
			  VoidPtr Data,
			  IritHashCmpFuncType HashCmpFunc,
			  RealType Key);
int IritHashTableRemove(IritHashTableStruct *IHT,
			VoidPtr Data,
			IritHashCmpFuncType HashCmpFunc,
			RealType Key);
void IritHashTableFree(IritHashTableStruct *IHT);

/* Read/Write of images. */
IrtImgPixelStruct *IrtImgReadImage(char *ImageFileName, int *MaxX, int *MaxY);
IrtImgPixelStruct *IrtImgReadImage2(char *ImageFileName, int *MaxX, int *MaxY);
void IrtImgReadClrCache(void);
IrtImgImageType IrtImgWriteSetType(char *Image);
int IrtImgWriteOpenFile(char **argv,
			char *FName,
			int Alpha,
			int XSize,
			int YSize);
void IrtImgWritePutLine(ByteType *Alpha, IrtImgPixelStruct *Pixels);
void IrtImgWriteCloseFile(void);
IrtImgPixelStruct *IrtImgFlipXYImage(IrtImgPixelStruct *Img,
				     int MaxX,
				     int MaxY);
int IrtImgParsePTextureString(char *PTexture,
			      char *FName,
			      RealType *Scale,
			      int *Flip);

/* Searching routines. */
VoidPtr IritSearch2DInit(RealType XMin,
			 RealType XMax,
			 RealType YMin,
			 RealType YMax,
			 RealType Tol,
			 int DataSize);
void IritSearch2DFree(VoidPtr S2D);
void IritSearch2DInsertElem(VoidPtr S2D,
			    RealType XKey,
			    RealType YKey,
			    VoidPtr Data);
int IritSearch2DFindElem(VoidPtr S2D,
			 RealType XKey,
			 RealType YKey,
			 VoidPtr Data);

/* Set cover related routines. */
VoidPtr IritRLNew(void);
void IritRLAdd(VoidPtr RLC, RealType l, RealType r, int attr);
int *IritRLFindCyclicCover(VoidPtr RLC, RealType Tol);
void IritRLDelete(VoidPtr RLC);
int IritRLSetGaurdiansNumber(int g);

/* XGeneral routine - compatibility between Unix and Win95/WinNT/OS2/etc. */
char *IritStrdup(char *s);
void IritSleep(int MiliSeconds);
void IritRandomInit(long Seed);
RealType IritRandom(RealType Min, RealType Max);
RealType IritCPUTime(int Reset);
char *IritRealTimeDate(void);
RealType IritApproxStrStrMatch(char *Str1, char *Str2, int IgnoreCase);

#ifndef AMIGA
void movmem(VoidPtr Src, VoidPtr Dest, int Len);
#endif /* AMIGA */
char *searchpath(char *Name);

#ifdef STRICMP
int strnicmp(char *s1, char *s2, int n);
int stricmp(char *s1, char *s2);
#else
#if !(defined(__WINNT__) || defined(__WINCE__) || defined(OS2GCC) || defined(AMIGA) || defined(__CYGWIN__))
#   define strnicmp(s1, s2, n) strncasecmp((s1), (s2), (n))
#   define stricmp(s1, s2)     strcasecmp((s1), (s2))
#endif /* !(__WINNT__ || __WINCE__|| OS2GCC || AMIGA) */
#ifdef __WINCE__
#   ifdef strnicmp
#       undef strnicmp
#       undef stricmp
#   endif /* strnicmp */
#   define strnicmp(s1, s2, n) _strnicmp((s1), (s2), (n))
#   define stricmp(s1, s2)     _stricmp((s1), (s2))
#endif /* __WINCE__ */
#endif /* STRICMP */


#ifdef STRSTR
char *strstr(char *s, char *Pattern);
#endif /* STRSTR */

#ifdef GETCWD
char *getcwd(char *s, int Len);
#endif /* GETCWD */

/* Error handling. */

void MiscFatalError(MiscFatalErrorType ErrID);
char *MiscDescribeError(MiscFatalErrorType ErrorNum);

void IritFatalError(char *Msg);
void IritWarningError(char *Msg);

#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

#endif /* MISC_LIB_H */
