#ifndef BOT_ATYPE_LTYPE_RTYPE_OPNAME
#define BOT_ATYPE_LTYPE_RTYPE_OPNAME
IA_BinaryOperationsTable<ATYPE,
	IA_BaseImage<IA_Point<int>, LTYPE>,
	IA_BaseImage<IA_Point<int>, RTYPE> >
	*IA_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl;

void IA_fill_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl();

#endif // BOT_ATYPE_LTYPE_RTYPE_OPNAME
ATYPE OP ( const IA_Image<IA_Point<int>, LTYPE> &lhs,
		const IA_Image<IA_Point<int>, RTYPE> &rhs)
{
    if (lhs.domain() != rhs.domain()) {
	 ATYPE	rval;
	ia_throw(Image_DomainMismatch_Exception(__FILE__,__LINE__));
	return rval;
    }

    if (!IA_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl)
	IA_fill_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl();

    ATYPE(*f)( IA_BaseImage<IA_Point<int>, LTYPE> &,
		IA_BaseImage<IA_Point<int>, RTYPE> &);
    f = IA_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl->lookup_operation
	(lhs.type(), rhs.type());
    IA_BaseImage<IA_Point<int>,LTYPE>	&basel = *IA_FBI<IA_Point<int>,IA_Point<int>, LTYPE,LTYPE,LTYPE>
	    ::extract_baseptr(lhs);
    IA_BaseImage<IA_Point<int>,LTYPE>	&baser = *IA_FBI<IA_Point<int>,IA_Point<int>, LTYPE,LTYPE,LTYPE>
	    ::extract_baseptr(rhs);
    return 	 f(basel,baser);
}

//
//
//

static ATYPE vec_vec_bo_OPNAME(IA_BaseImage<IA_Point<int>, LTYPE> &lhs_,
	IA_BaseImage<IA_Point<int>, RTYPE> &rhs_)
{
    const IA_Set<IA_Point<int> > domain = lhs_.domain();
    const unsigned sz = domain.card();
    ATYPE *const vec = new ATYPE[sz];

    {
	ATYPE *ds = vec;
	IA_VectorI<IA_Point<int>, LTYPE> *lhs
		= (IA_VectorI<IA_Point<int>, LTYPE> *)&lhs_;
	const LTYPE *ls = lhs->vec;
	IA_VectorI<IA_Point<int>, RTYPE> *rhs
		= (IA_VectorI<IA_Point<int>, RTYPE> *)&rhs_;
	const RTYPE *rs = rhs->vec;
	for (unsigned i=0; i<sz; i++) {
	    if (!( (*ls) SUBOP (*rs) ))
		return 0;
	    ls++;
	    rs++;
	}
    }
    return 1;
}

#ifndef vec_scalar_ATYPE_LTYPE_RTYPE_OPNAME
#define vec_scalar_ATYPE_LTYPE_RTYPE_OPNAME
static ATYPE vec_scalar_bo_OPNAME(IA_BaseImage<IA_Point<int>, LTYPE> &lhs_,
	IA_BaseImage<IA_Point<int>, RTYPE> &rhs_)
{
    const IA_Set<IA_Point<int> > domain = lhs_.domain();
    const unsigned sz = domain.card();
    ATYPE *const vec = new ATYPE[sz];

    {
	ATYPE *ds = vec;
	IA_VectorI<IA_Point<int>, LTYPE> *lhs
		= (IA_VectorI<IA_Point<int>, LTYPE> *)&lhs_;
	const LTYPE *ls = lhs->vec;
	IA_ConstI<IA_Point<int>, RTYPE> *rhs
		= (IA_ConstI<IA_Point<int>, RTYPE> *)&rhs_;
	for (unsigned i=0; i<sz; i++) {
	    if (!( (*ls) SUBOP (rhs->value) ))
		return 0;
	    ls++;
	}
    }
    return 1;
}
#endif // vec_scalar_ATYPE_LTYPE_RTYPE_OPNAME

static ATYPE vec_iter_bo_OPNAME(IA_BaseImage<IA_Point<int>, LTYPE> &lhs_,
	IA_BaseImage<IA_Point<int>, RTYPE> &rhs_)
{
    const IA_Set<IA_Point<int> > domain = lhs_.domain();
    const unsigned sz = domain.card();
    ATYPE *const vec = new ATYPE[sz];

    {
	ATYPE *ds = vec;
	IA_VectorI<IA_Point<int>, LTYPE> *lhs
		= (IA_VectorI<IA_Point<int>, LTYPE> *)&lhs_;
	const LTYPE *ls = lhs->vec;
	RTYPE rtmp;
	IA_BaseIVIter<IA_Point<int>, RTYPE>	*riter = rhs_.value_iterator();
	for (unsigned i=0; i<sz; i++) {
	    riter->next(rtmp);
	    if (!( (*ls) SUBOP (rtmp) ))
		return 0;
	    ls++;
	}
	delete riter;
    }
    return 1;
}

#ifndef scalar_vec_ATYPE_LTYPE_RTYPE_OPNAME
#define scalar_vec_ATYPE_LTYPE_RTYPE_OPNAME
static ATYPE scalar_vec_bo_OPNAME(IA_BaseImage<IA_Point<int>, LTYPE> &lhs_,
	IA_BaseImage<IA_Point<int>, RTYPE> &rhs_)
{
    const IA_Set<IA_Point<int> > domain = lhs_.domain();
    const unsigned sz = domain.card();
    ATYPE *const vec = new ATYPE[sz];

    {
	ATYPE *ds = vec;
	IA_ConstI<IA_Point<int>, LTYPE> *lhs
		= (IA_ConstI<IA_Point<int>, LTYPE> *)&lhs_;
	IA_VectorI<IA_Point<int>, RTYPE> *rhs
		= (IA_VectorI<IA_Point<int>, RTYPE> *)&rhs_;
	const RTYPE *rs = rhs->vec;
	for (unsigned i=0; i<sz; i++) {
	    if (!( (lhs->value) SUBOP (*rs) ))
		return 0;
	    rs++;
	}
    }
    return 1;
}
#endif // scalar_vec_ATYPE_LTYPE_RTYPE_OPNAME

#ifndef scalar_scalar_ATYPE_LTYPE_RTYPE_OPNAME
#define scalar_scalar_ATYPE_LTYPE_RTYPE_OPNAME
static ATYPE scalar_scalar_bo_OPNAME(IA_BaseImage<IA_Point<int>, LTYPE> &lhs_,
	IA_BaseImage<IA_Point<int>, RTYPE> &rhs_)
{
    const IA_Set<IA_Point<int> > domain = lhs_.domain();
	IA_ConstI<IA_Point<int>, LTYPE> *lhs
		= (IA_ConstI<IA_Point<int>, LTYPE> *)&lhs_;
	IA_ConstI<IA_Point<int>, RTYPE> *rhs
		= (IA_ConstI<IA_Point<int>, RTYPE> *)&rhs_;
    ATYPE	aval = ( lhs->value SUBOP rhs->value );
    return aval;
}
#endif // scalar_scalar_ATYPE_LTYPE_RTYPE_OPNAME

#ifndef scalar_iter_ATYPE_LTYPE_RTYPE_OPNAME
#define scalar_iter_ATYPE_LTYPE_RTYPE_OPNAME
static ATYPE scalar_iter_bo_OPNAME(IA_BaseImage<IA_Point<int>, LTYPE> &lhs_,
	IA_BaseImage<IA_Point<int>, RTYPE> &rhs_)
{
    const IA_Set<IA_Point<int> > domain = lhs_.domain();
    const unsigned sz = domain.card();
    ATYPE *const vec = new ATYPE[sz];

    {
	ATYPE *ds = vec;
	IA_ConstI<IA_Point<int>, LTYPE> *lhs
		= (IA_ConstI<IA_Point<int>, LTYPE> *)&lhs_;
	RTYPE rtmp;
	IA_BaseIVIter<IA_Point<int>, RTYPE>	*riter = rhs_.value_iterator();
	for (unsigned i=0; i<sz; i++) {
	    riter->next(rtmp);
	    if (!( (lhs->value) SUBOP (rtmp) ))
		return 0;
	}
	delete riter;
    }
    return 1;
}
#endif // scalar_iter_ATYPE_LTYPE_RTYPE_OPNAME

static ATYPE iter_vec_bo_OPNAME(IA_BaseImage<IA_Point<int>, LTYPE> &lhs_,
	IA_BaseImage<IA_Point<int>, RTYPE> &rhs_)
{
    const IA_Set<IA_Point<int> > domain = lhs_.domain();
    const unsigned sz = domain.card();
    ATYPE *const vec = new ATYPE[sz];

    {
	ATYPE *ds = vec;
	LTYPE ltmp;
	IA_BaseIVIter<IA_Point<int>, LTYPE>	*liter = lhs_.value_iterator();
	IA_VectorI<IA_Point<int>, RTYPE> *rhs
		= (IA_VectorI<IA_Point<int>, RTYPE> *)&rhs_;
	const RTYPE *rs = rhs->vec;
	for (unsigned i=0; i<sz; i++) {
	    liter->next(ltmp);
	    if (!( (ltmp) SUBOP (*rs) ))
		return 0;
	    rs++;
	}
	delete liter;
    }
    return 1;
}

#ifndef iter_scalar_ATYPE_LTYPE_RTYPE_OPNAME
#define iter_scalar_ATYPE_LTYPE_RTYPE_OPNAME
static ATYPE iter_scalar_bo_OPNAME(IA_BaseImage<IA_Point<int>, LTYPE> &lhs_,
	IA_BaseImage<IA_Point<int>, RTYPE> &rhs_)
{
    const IA_Set<IA_Point<int> > domain = lhs_.domain();
    const unsigned sz = domain.card();
    ATYPE *const vec = new ATYPE[sz];

    {
	ATYPE *ds = vec;
	LTYPE ltmp;
	IA_BaseIVIter<IA_Point<int>, LTYPE>	*liter = lhs_.value_iterator();
	IA_ConstI<IA_Point<int>, RTYPE> *rhs
		= (IA_ConstI<IA_Point<int>, RTYPE> *)&rhs_;
	for (unsigned i=0; i<sz; i++) {
	    liter->next(ltmp);
	    if (!( (ltmp) SUBOP (rhs->value) ))
		return 0;
	}
	delete liter;
    }
    return 1;
}
#endif // iter_scalar_ATYPE_LTYPE_RTYPE_OPNAME

static ATYPE iter_iter_bo_OPNAME(IA_BaseImage<IA_Point<int>, LTYPE> &lhs_,
	IA_BaseImage<IA_Point<int>, RTYPE> &rhs_)
{
    const IA_Set<IA_Point<int> > domain = lhs_.domain();
    const unsigned sz = domain.card();
    ATYPE *const vec = new ATYPE[sz];

    {
	ATYPE *ds = vec;
	LTYPE ltmp;
	IA_BaseIVIter<IA_Point<int>, LTYPE>	*liter = lhs_.value_iterator();
	RTYPE rtmp;
	IA_BaseIVIter<IA_Point<int>, RTYPE>	*riter = rhs_.value_iterator();
	for (unsigned i=0; i<sz; i++) {
	    liter->next(ltmp);
	    riter->next(rtmp);
	    if (!( (ltmp) SUBOP (rtmp) ))
		return 0;
	}
	delete liter;
	delete riter;
    }
    return 1;
}

#ifndef FILL_BOT_ATYPE_LTYPE_RTYPE_OPNAME
#define FILL_BOT_ATYPE_LTYPE_RTYPE_OPNAME
void IA_fill_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl()
{
    if (IA_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl)
	return;

    IA_BinaryOperationsTable<ATYPE,
	IA_BaseImage<IA_Point<int>, LTYPE>,
	IA_BaseImage<IA_Point<int>, RTYPE> >::function f;
    f = iter_iter_bo_OPNAME;

    IA_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl = new IA_BinaryOperationsTable<ATYPE,
	IA_BaseImage<IA_Point<int>, LTYPE>,
	IA_BaseImage<IA_Point<int>, RTYPE> >(iter_iter_bo_OPNAME);
    IA_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl->add_operation
	(IA_VectorI<IA_Point<int>, LTYPE>::s_type(),
	 IA_VectorI<IA_Point<int>, RTYPE>::s_type(),
	 vec_vec_bo_OPNAME);
    IA_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl->add_operation
	(IA_VectorI<IA_Point<int>, LTYPE>::s_type(),
	 IA_ConstI<IA_Point<int>, RTYPE>::s_type(),
	 vec_scalar_bo_OPNAME);
    IA_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl->add_operation
	(IA_VectorI<IA_Point<int>, LTYPE>::s_type(),
	 0,
	 vec_iter_bo_OPNAME);

    IA_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl->add_operation
	(IA_ConstI<IA_Point<int>, LTYPE>::s_type(),
	 IA_VectorI<IA_Point<int>, RTYPE>::s_type(),
	 scalar_vec_bo_OPNAME);
    IA_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl->add_operation
	(IA_ConstI<IA_Point<int>, LTYPE>::s_type(),
	 IA_ConstI<IA_Point<int>, RTYPE>::s_type(),
	 scalar_scalar_bo_OPNAME);
    IA_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl->add_operation
	(IA_ConstI<IA_Point<int>, LTYPE>::s_type(),
	 0,
	 scalar_iter_bo_OPNAME);

    IA_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl->add_operation
	(0,
	 IA_VectorI<IA_Point<int>, RTYPE>::s_type(),
	 iter_vec_bo_OPNAME);
    IA_Image_IP_ATYPE_LTYPE_RTYPE_OPNAME_tbl->add_operation
	(0,
	 IA_ConstI<IA_Point<int>, RTYPE>::s_type(),
	 iter_scalar_bo_OPNAME);

}
#endif // BOT_ATYPE_LTYPE_RTYPE_OPNAME
