/* -*- c-basic-offset: 3; mode: c++ -*-
 *
 * 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 Régis Clouard - 2003-04-01
 */

#include <math.h>
#include <pandore.h>
using namespace pandore;


/**
 * @file psqrt.cpp
 * Square root.
 */

template <typename T1, typename T2>
Errc PSqrt( const Imx3d<T1> &ims, Imx3d<T2> &imd ) {
   for (int b=0; b<ims.Bands();b++) {
      T1 *ps=ims.Vector(b);
      T2 *pd=imd.Vector(b);
      
      for (;ps<ims.Vector(b)+ims.VectorSize();ps++,pd++){   
	 *pd = (T2)sqrt((double)*ps);
      }
   }
   return SUCCESS;
}






/**
 * Graph (nodes).
 */
Errc PSqrt( const Graph2d &grs, Graph2d &grd ) {
   grd=grs;
   for (int i=0;i<grs.Size();i++)
      if ((grd[i]))
	 grd[i]->value=(Graph2d::ValueType)sqrt((double)grd[i]->value);
   
   return SUCCESS;
}

/**
 * Graph (nodes).
 */
Errc PSqrt( const Graph3d &grs, Graph3d &grd ) {
   grd=grs;
   for (int i=0;i<grs.Size();i++)
      if ((grd[i]))
	 grd[i]->value=(Graph3d::ValueType)sqrt((double)grd[i]->value);
   
   return SUCCESS;
}


#ifdef MAIN
#define	USAGE	"usage: %s [-m mask] [im_in|-] [im_out|-]"
#define	PARC	0
#define	FINC	1
#define	FOUTC	1
#define	MASK	1

int main( int argc, char *argv[] ) {
   Errc result;              // The result code of the execution.
   Pobject* mask;            // The region map.
   Pobject* objin[FINC+1];   // The input objects;
   Pobject* objs[FINC+1];    // The source objects masked.
   Pobject* objout[FOUTC+1]; // The output object.
   Pobject* objd[FOUTC+1];   // The result object of the execution.
   char* parv[PARC+1];       // The input parameters.

   ReadArgs(argc,argv,PARC,FINC,FOUTC,&mask,objin,objs,objout,objd,parv,USAGE,MASK);
   if (objs[0]->Type()==Po_Img2duc){
      Img2duc* const ims=(Img2duc*)objs[0];
      objd[0]=new Img2dsf(ims->Props());
      Img2dsf* const imd=(Img2dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Img2dsl){
      Img2dsl* const ims=(Img2dsl*)objs[0];
      objd[0]=new Img2dsf(ims->Props());
      Img2dsf* const imd=(Img2dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Img2dsf){
      Img2dsf* const ims=(Img2dsf*)objs[0];
      objd[0]=new Img2dsf(ims->Props());
      Img2dsf* const imd=(Img2dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Img3duc){
      Img3duc* const ims=(Img3duc*)objs[0];
      objd[0]=new Img3dsf(ims->Props());
      Img3dsf* const imd=(Img3dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Img3dsl){
      Img3dsl* const ims=(Img3dsl*)objs[0];
      objd[0]=new Img3dsf(ims->Props());
      Img3dsf* const imd=(Img3dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Img3dsf){
      Img3dsf* const ims=(Img3dsf*)objs[0];
      objd[0]=new Img3dsf(ims->Props());
      Img3dsf* const imd=(Img3dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Imc2duc){
      Imc2duc* const ims=(Imc2duc*)objs[0];
      objd[0]=new Imc2dsf(ims->Props());
      Imc2dsf* const imd=(Imc2dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Imc2dsl){
      Imc2dsl* const ims=(Imc2dsl*)objs[0];
      objd[0]=new Imc2dsf(ims->Props());
      Imc2dsf* const imd=(Imc2dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Imc2dsf){
      Imc2dsf* const ims=(Imc2dsf*)objs[0];
      objd[0]=new Imc2dsf(ims->Props());
      Imc2dsf* const imd=(Imc2dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Imc3duc){
      Imc3duc* const ims=(Imc3duc*)objs[0];
      objd[0]=new Imc3dsf(ims->Props());
      Imc3dsf* const imd=(Imc3dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Imc3dsl){
      Imc3dsl* const ims=(Imc3dsl*)objs[0];
      objd[0]=new Imc3dsf(ims->Props());
      Imc3dsf* const imd=(Imc3dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Imc3dsf){
      Imc3dsf* const ims=(Imc3dsf*)objs[0];
      objd[0]=new Imc3dsf(ims->Props());
      Imc3dsf* const imd=(Imc3dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Imx2duc){
      Imx2duc* const ims=(Imx2duc*)objs[0];
      objd[0]=new Imx2dsf(ims->Props());
      Imx2dsf* const imd=(Imx2dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Imx2dsl){
      Imx2dsl* const ims=(Imx2dsl*)objs[0];
      objd[0]=new Imx2dsf(ims->Props());
      Imx2dsf* const imd=(Imx2dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Imx2dsf){
      Imx2dsf* const ims=(Imx2dsf*)objs[0];
      objd[0]=new Imx2dsf(ims->Props());
      Imx2dsf* const imd=(Imx2dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Imx3duc){
      Imx3duc* const ims=(Imx3duc*)objs[0];
      objd[0]=new Imx3dsf(ims->Props());
      Imx3dsf* const imd=(Imx3dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Imx3dsl){
      Imx3dsl* const ims=(Imx3dsl*)objs[0];
      objd[0]=new Imx3dsf(ims->Props());
      Imx3dsf* const imd=(Imx3dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Imx3dsf){
      Imx3dsf* const ims=(Imx3dsf*)objs[0];
      objd[0]=new Imx3dsf(ims->Props());
      Imx3dsf* const imd=(Imx3dsf*)objd[0];
      
      result=PSqrt(*ims,*imd);
      goto end;
   }
   if (objs[0]->Type()==Po_Graph2d){
      Graph2d* const grs=(Graph2d*)objs[0];
      objd[0]=new Graph2d(grs->Props());
      Graph2d* const grd=(Graph2d*)objd[0];
      
      result=PSqrt(*grs,*grd);
      goto end;
   }
   if (objs[0]->Type()==Po_Graph3d){
      Graph3d* const grs=(Graph3d*)objs[0];
      objd[0]=new Graph3d(grs->Props());
      Graph3d* const grd=(Graph3d*)objd[0];
      
      result=PSqrt(*grs,*grd);
      goto end;
   }
  {
     PrintErrorFormat(objin,FINC);
     result = FAILURE;
  }	

end:
  if (result)
	WriteArgs(argc,argv,PARC,FINC,FOUTC,&mask,objin,objs,objout,objd,MASK);
  Exit(result);
  return 0;
}
#endif
