#if !defined(__MIMASINTERNALIMAGEFUNC)
#   error "Do not include this file directly."
#endif
#if !defined(__MIMASEXTERNALIMAGEFUNC)
#   error "Do not include this file directly."
#endif
#if !defined(__MIMASFUNCTIONOBJECT)
#   error "Do not include this file directly."
#endif

namespace mimas {

/** @addtogroup arrayOp
    @{ */
///
template<
  typename T, typename T1Ptr, typename T2Ptr
>
image< T > __MIMASEXTERNALIMAGEFUNC( const const_image_ref< T, T1Ptr > &a,
                                     const const_image_ref< T, T2Ptr > &b )
{
  return image_func< T >( a, b, __MIMASFUNCTIONOBJECT< T >() );
}

///
template<
  typename T, typename TPtr
>
image< T > __MIMASEXTERNALIMAGEFUNC( const const_image_ref< T, TPtr > &a,
                                     const T &b )
{
  return image_func< T >( a, std::bind2nd( __MIMASFUNCTIONOBJECT< T >(), b ) );
}

///
template<
  typename T, typename TPtr
>
image< T > __MIMASEXTERNALIMAGEFUNC( const T &a,
                                     const const_image_ref< T, TPtr > &b )
{
  return image_func< T >( b, std::bind1st( __MIMASFUNCTIONOBJECT< T >(), a ) );
}

///
template<
  typename T, typename TPtr
>
image_ref< T > &__MIMASINTERNALIMAGEFUNC( image_ref< T > &a,
                                          const const_image_ref< T, TPtr > &b )
{
  return image_apply( a, a, b,
                      _multi_help2< T, T, T, __MIMASFUNCTIONOBJECT< T > >
                      ( __MIMASFUNCTIONOBJECT< T >() ) );
}

///
template<
  typename T
>
image_ref< T > &__MIMASINTERNALIMAGEFUNC( image_ref< T > &a,
                                          const T &b )
{
  return image_apply( a, a,
                      _multi_help1< T, T,
                          std::binder2nd< __MIMASFUNCTIONOBJECT< T > > >
                      ( std::bind2nd( __MIMASFUNCTIONOBJECT< T >(), b ) ) );
}

///@}

};

#undef __MIMASINTERNALIMAGEFUNC
#undef __MIMASEXTERNALIMAGEFUNC
#undef __MIMASFUNCTIONOBJECT