/* -*- mode: c++; c-basic-offset: 3 -*-
 *
 * PANDORE (PANTHEON Project)
 *
 * GREYC IMAGE
 * 6 Boulevard Maréchal Juin
 * F-14050 Caen Cedex France
 *
 * This file is free software. You can use it, distribute it
 * and/or modify it. However, the entire risk to the quality
 * and performance of this program is with you.
 *
 * Please email any bugs, comments, and/or additions to this file to:
 * pandore@greyc.ensicaen.fr
 * http://www.greyc.ensicaen.fr/EquipeImage/Pandore/
 */

/**
 * @author Jean-Baptiste Hoock - 2005-07-26 
 */

/**
 * @file wutils.cpp
 *
 * wedgewindow: creation of the two halves of a C^inf compactly supported 
 *              window 
 * wedgewindow: creer deux fenetres en utilisant un fenetrage de Meyer
 */ 

#ifndef UTILS_CC
#define UTILS_CC

#include <pandore.h>
using namespace pandore;

#include <math.h>

#define LEFT	1
#define RIGHT	2
#define mat(a, i, j) (*(a + (m*(j)+i))) 
#define MOD(a, b) ((a) - (int)floor((Double)a/(Double)b)*(b))
#define SIGN(a) ((a) >= 0.0 ? 1 : -1)
#define PI M_PI 

/*
 * Modulo function.
 */
int mod(int a, int b) {
   int r;
   
   if(a<0)
      r = b + a + (a/b)*b;
   else
      r = a - (a/b)*b;
   
   //printf("%d %d %d\n",a,b,r);
   return(r);	
}

/*
 * Sign of a number : return 1 if x > 0 else -1
 */
int sign(Float x) {
   return x>0 ? 1 : -1;
}

/*
 * This function returns the next power of two.
 */
int nextpow2(Double num){
   Double f;
   int exp;
	
   f = frexp(fabs(num), &exp);
	
   if(f && f == 0.5)
      exp = exp-1;
   return exp;
}

/**
 * Get the max abs value of a vector.
 * Inputs :
 * 	x : The vector of floats.
 * 	n : The length of the vector.
 */
Float maxabs(Float* x,int n) {
   Float curmax = MINFLOAT;
   int i;
	
   for(i = 0; i < n; i++)
      curmax = fabs(x[i]) > curmax ? fabs(x[i]):curmax;
   return curmax;
} 

/**
 * norm 
 * This function gives the norm of a vector.
 * x    : The vector.
 * size : The size of the vector.
 */
Float norm(Float* x, int size) {
   int i;
   Float nrm;
   for( i = 1,nrm = 0; i <= size; i++)
      nrm+=x[i]*x[i];
   return (Float)sqrt(nrm);
}

/**
 * Make a copy of src into dst
 */
template<typename U,typename V>
void copy(U * dst,V * src,int width) {
   int i;
   for( i = 0 ; i < width ; i++)
      dst[i] = (U)src[i];
}

/**
 * Make a copy of src into dst
 */
template<typename U,typename V>
void sumvectors(U * src,V * dst,int width) {
   int i;
   for( i = 0 ; i < width ; i++)
      dst[i] += (U)src[i];
}


/**
 * We check some conditions on the image.
 */
template<typename U>
Errc Check(Imx3d<U> & ims) {
   if (MIN(ims.Width(),ims.Height()) == 0) {
      std::cerr<<"Incorrect width or height "<<std::endl;
      Exit(FAILURE);
   }
   if ((1<<nextpow2(ims.Width()) != (int)ims.Width()) || (1<<nextpow2(ims.Height()) !=(int)ims.Height())) {
      std::cerr<<"Incorrect width or height format: must be a power of 2 (e.g. try to pad with zeros)."<<std::endl;
      Exit(FAILURE);
   }
   return SUCCESS;
}

/*
 * Check two images
 */
template<typename U,typename V>
Errc Check(Imx3d<U> &ims,Imx3d<V> &imd) {
   Check(ims);
   Check(imd);
   return SUCCESS;
}

#endif
