// Emacs: -*- C++ -*-

//
//	Copyright 1993, Center for Computer Vision and Visualization,
//	University of Florida.  All rights reserved.
//


//
// $Log: closure.c,v $
// Revision 1.18.1.2  1995/01/13  19:37:42  thoth
// CoreImage has been re-merged with Image.  All special stuff should be
// friends of FBI now.
//
// Revision 1.18.1.1  1994/12/28  17:51:25  thoth
// restriction and extension are now ROFs.
// New ClosureNbh class.
// removed some debugging cruft.
//
// Revision 1.18  1994/09/16  14:59:10  thoth
// fix Xeroxing error that prevented instantiation of continuous images.
//
// Revision 1.17  1994/08/22  15:25:39  thoth
// DOS-inspired name rework
//
// Revision 1.16  1994/07/25  17:26:39  thoth
// Name sanitization
//
// Revision 1.15  1994/05/27  15:33:06  thoth
// fix of typo.
//
// Revision 1.14  1994/04/26  18:21:33  thoth
// composition between UDIs and RGB functions for pseudocolor map.
//
// Revision 1.13  1994/04/15  13:18:55  thoth
// instantiate the convolutions and reductions.  Remove gratuitous composes.
//
// Revision 1.12  1994/03/30  13:58:52  thoth
// new generic convolutions and generic neighborhood reductions.
//
// Revision 1.11  1994/03/15  14:23:43  thoth
// Add constructor that assumes the White Hole.
//
// Revision 1.10  1994/03/14  15:57:33  thoth
// ValueSet has been replaced by container class Set.
//
// Revision 1.9  1994/03/02  13:58:50  jnw
// Added RGB instantiations
//
// Revision 1.8  1994/02/26  16:03:27  thoth
// New 3-argument spatial composition functions.  Allow destination
// pointsets to be specified.
//
// Revision 1.7  1994/01/31  15:51:47  thoth
// removed cruft.
// chi_contains is only good for Discrete images.
// value-value closures are now available.
// we can instantiate things (like chi_contains) that only make sense on
// discrete images.
// Neighborhoods now exist.
// the double-double FDI composition was not being instantiated.
//
// Revision 1.6  1994/01/07  15:10:00  thoth
// Image class is now CoreImage and named image types are
// Image<P,T>.
//
// Revision 1.5  1993/12/29  17:17:12  thoth
// New FunctionI type.
// new chi_contains function.
//
// Revision 1.4  1993/11/17  18:30:27  thoth
// We now instantiate templates too.
// translated is now translate.
// extensivep is now extensive.
// ComplexDI is instantiated.
// DoubleDI is commented out.
//
// Revision 1.3  1993/10/05  19:34:25  thoth
// Move to new Closure naming convention.
// Eliminated unnecessary Continuous Images.
//
// Revision 1.2  1993/09/27  15:54:08  thoth
// xlated is now translated.
//
// Revision 1.1  1993/09/15  12:58:07  thoth
// Initial revision
//


#include <complex.h>
#include "Image.h"
#include "ImageIter.h"

#include "BitDI.h"
#include "UcharDI.h"
#include "IntDI.h"
#include "FloatDI.h"
#include "CplxDI.h"
#include "RGBDI.h"
#include "DDTempl.h"

#include "Nbh.h"

#include "ClosureNbh.h"


#define INSTANTIATE(P,T) \
{ \
    P	*points=0; \
    T	*vals=0; \
    IA_ClosureI<P,T>	*zero=0; \
    IA_Set<T>	vs; \
    IA_Set<P >		ps; \
    IA_Array<T>		ar; \
    IA_Image<P,T>	i1; \
    IA_Image<P,T>	i2(i1), i3(ps, vals[0]), i4(ps, (T*)0, 0, 0), \
	i5(ps, vals, 0), i6(*zero), \
	i7(ps, (T(*)(const P&))0), i8(ps, (T(*)(P))0); \
    int	j; \
 \
    i1 = i2; \
    i1 = vals[0]; \
    vals[0] = i2(points[0]); \
    i2[points[0]] = vals[0]; \
 \
/*    i1.restrict(IA_Set<IA_Point<int> >()); \
    i1 = i1.restrict(IA_Set<IA_Point<double> >()); \
    i1 = i1.restrict(vs);  */\
    restrict(i1,IA_Set<IA_Point<int> >()); \
    i1 = restrict(i1,IA_Set<IA_Point<double> >()); \
    i1 = value_restrict(i1,vs); \
/*    i1 = i1.extend(i2); */ \
    i1 = extend(i1,i2); \
    i1 = i1.translate(points[0]); \
    ps = i1.domain(); \
    vs = i1.range(); \
    ar = i1.value_array(); \
    j = i1.card(); \
    j = i1.extensive(); \
    vals[0] = i1.reduce((T(*)(const T&, const T&))0, 0); \
    vals[0] = i1.reduce((T(*)(T, T))0, 0); \
 \
    i1.restrict_assign(i2); \
 \
     cout << i1; \
 \
    IA_IVIter<P,T>	viter1; \
    IA_IVIter<P,T>	viter2(viter1), viter3(i1); \
    viter1 = viter2; \
    viter1 = i1; \
    i1 = viter1.domain(); \
    while (viter1(vals[0])) \
	; \
    viter1.reset(); \
 \
    IA_IPIter<P,T>	piter1; \
    IA_IPIter<P,T>	piter2(piter1), piter3(i1); \
    piter1 = piter2; \
    piter1 = i1; \
    i1 = piter1.domain(); \
    while (piter1(points[0],vals[0])) \
	; \
    piter1.reset(); \
 \
    i1 = compose(i1, *(IA_Closure<P,P>*)0); \
    i1 = compose(i1, (P (*)(const P&))0); \
    i1 = compose(i1, *(IA_Closure<P,P>*)0, ps); \
    i1 = compose(i1, (P (*)(const P&))0, ps); \
    i1 = compose((T (*)(T))0, i1); \
    i1 = compose(*(IA_Closure<T,T>*)0, i1); \
    i1 = compose(*(IA_Closure<T,T>*)0, i1, (T*)0); \
 \
}

#define INST_TEMPL(T) \
{ \
    IA_Set<IA_Point<int> >	ps; \
    IA_Point<int>	p; \
    IA_Image<IA_Point<int>, T>	img; \
    IA_DDTemplate<IA_Image<IA_Point<int>, T> > templ1(ps, img); \
    IA_DDTemplate<IA_Image<IA_Point<int>, T> > templ2(2, img); \
    /*IA_DDTemplate<IA_Image<IA_Point<int>, T> > templ3(img);*/ \
    IA_DDTemplate<IA_Image<IA_Point<int>, T> > templ4(ps, 0); \
    IA_DDTemplate<IA_Image<IA_Point<int>, T> > templ5(*(IA_ClosureDT<IA_Image<IA_Point<int>, T> >*)0); \
 \
    img = templ1(p); \
    ps = templ1.domain(); \
    templ1.type(); \
    generic_product(img, templ1, ps, \
		    (T(*)(T,T))0, (T(*)(T,T))0, (T)0, (T)0); \
    generic_product(img, templ1, ps, \
		    (T(*)(T,T))0, (T(*)(T*,unsigned))0, (T)0); \
    generic_product(img, templ1, ps, \
		    (T(*)(T,T))0, (T(*)(T*,unsigned))0); \
    generic_product(templ1, img, ps, \
		    (T(*)(T,T))0, (T(*)(T,T))0, (T)0, (T)0); \
    generic_product(templ1, img, ps, \
		    (T(*)(T,T))0, (T(*)(T*,unsigned))0, (T)0); \
    generic_product(templ1, img, ps, \
		    (T(*)(T,T))0, (T(*)(T*,unsigned))0); \
}

typedef IA_Image<IA_Point<int>,IA_Bit>	BDI;
typedef	IA_Image<IA_Point<int>,u_char>	UDI;
typedef	IA_Image<IA_Point<int>,int>	IDI;
typedef	IA_Image<IA_Point<int>,float>	FDI;
typedef	IA_Image<IA_Point<int>,complex>	CDI;
typedef	IA_Image<IA_Point<int>,IA_RGB>	RGBDI;

#define INSTANTIATE_D(T) \
{ \
    IA_Image<IA_Point<int>, T>	i1; \
    IA_Set<T>		vs; \
    chi_contains(i1, vs); \
    transpose(i1); \
}

#define INSTANTIATE_NBH(T) \
	do { \
	neighborhood_reduction(IA_Image<IA_Point<int>, T>(), n1, \
			       IA_Set<IA_Point<int> >(), \
			       (T(*)(T, T))0, \
			       T());  \
	neighborhood_reduction(IA_Image<IA_Point<int>, T>(), n1, \
			       IA_Set<IA_Point<int> >(), \
			       T(), \
			       (T(*)(T*, unsigned))0);  \
	neighborhood_reduction(IA_Image<IA_Point<int>, T>(), n1, \
			       IA_Set<IA_Point<int> >(), \
			       (T(*)(T*, unsigned))0);  \
	neighborhood_reduction(n1, IA_Image<IA_Point<int>, T>(), \
			       IA_Set<IA_Point<int> >(), \
			       (T(*)(T, T))0, \
			       T()); \
	neighborhood_reduction(n1, IA_Image<IA_Point<int>, T>(), \
			       IA_Set<IA_Point<int> >(), \
			       T(), \
			       (T(*)(T*, unsigned))0); \
	neighborhood_reduction(n1, IA_Image<IA_Point<int>, T>(), \
			       IA_Set<IA_Point<int> >(), \
			       (T(*)(T*, unsigned))0); \
			       } while (0)


class spam_nbh : public IA_ClosureNbh<IA_Point<int>, IA_Point<int> > {
public:
    spam_nbh() :IA_ClosureNbh<IA_Point<int>, IA_Point<int> >
	( IA_Set<IA_Point<int> >()) { }

    IA_Set<IA_Point<int> > operator() (const IA_Point<int> &) const { return IA_Set<IA_Point<int> >(); }
    IA::Type type() const { return 0; }
    ostream& print_this(ostream &o) const { return o; }

    IA_ClosureNbh<IA_Point<int>, IA_Point<int> > *
	clone_self() const { return new spam_nbh(*this); }
};

typedef IA_Point<int> IP;
typedef IA_Point<double> FP;
typedef IA_Set<IP> IPS;

void crap ()
{
#if 1
    INSTANTIATE(IP, IA_Bit);
    INSTANTIATE(IP, unsigned char);
    INSTANTIATE(IP, int);
    INSTANTIATE(IP, float);
    //INSTANTIATE(IP, double);
    INSTANTIATE(IP, complex);
    INSTANTIATE(IP, IA_RGB);
    INSTANTIATE(FP, float);
    //INSTANTIATE(IA_Point<double>, double);
    //INSTANTIATE(IA_Point<double>, complex);

    INSTANTIATE_D(IA_Bit);
    INSTANTIATE_D(unsigned char);
    INSTANTIATE_D(int);
    INSTANTIATE_D(float);
  //INSTANTIATE_D(double);
    INSTANTIATE_D(complex);
    INSTANTIATE_D(IA_RGB);
#endif

#if 1
    INST_TEMPL(IA_Bit);
    INST_TEMPL(u_char);
    INST_TEMPL(int);
    INST_TEMPL(float);
#endif
    INST_TEMPL(complex);
    // INST_TEMPL(RGBDI);

#if 1
    {
	IA_Neighborhood<IA_Point<int>,IA_Point<int> >
		n1(2,IA_Set<IA_Point<int> >()),
		n2(n1),
		n3(spam_nbh());
	n1 = n2;
	IA_Neighborhood<IA_Point<int>,IA_Point<int> >
#if 0
	    // for a good time with CFront, uncomment this line.
	    //  kaBOOM!
		n4((IA_Set<IP >(*)(IP ))0),
#endif
		n4(IA_Set<IA_Point<int> >(),(IPS(*)(IP))0),
		n5(IA_Set<IA_Point<int> >(),(IPS(*)(const IP&))0);
	n1 = n2;
	n1(IA_Point<int>());
	n1.domain();
	n2.type();
#if 1
	INSTANTIATE_NBH(IA_Bit);
	INSTANTIATE_NBH(u_char);
	INSTANTIATE_NBH(int);
	INSTANTIATE_NBH(float);
	INSTANTIATE_NBH(complex);
#endif
    }


    compose((double(*)(double))0, IA_Image<IA_Point<int>,float>());
    compose((double(*)(double))0, IA_Image<IA_Point<int>,float>());
    compose((IA_RGB(*)(u_char))0, IA_Image<IA_Point<int>,u_char>(), (IA_RGB*)0);
#endif
}



int main()
{
  cout << "Hello, world.\n";
  crap();
}
