[arrayfire] 282/408: FEAT/TEST/DOC: Adding wrap for CPU backend

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Mon Sep 21 19:12:14 UTC 2015


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to branch debian/sid
in repository arrayfire.

commit 7df4dcd55336081e7d4ee1e2abe11a1943bdd29a
Author: Pavan Yalamanchili <pavan at arrayfire.com>
Date:   Tue Aug 18 21:14:13 2015 -0400

    FEAT/TEST/DOC: Adding wrap for CPU backend
    
    - Added necessary tests and documentation
---
 docs/details/image.dox      |  16 +++-
 include/af/image.h          |  68 +++++++++++++++--
 include/arrayfire.h         |   3 +
 src/api/c/wrap.cpp          |  78 +++++++++++++++++++
 src/api/cpp/wrap.cpp        |  27 +++++++
 src/backend/cpu/unwrap.cpp  |   4 +-
 src/backend/cpu/wrap.cpp    | 122 ++++++++++++++++++++++++++++++
 src/backend/cpu/wrap.hpp    |  21 ++++++
 src/backend/cuda/wrap.cu    |  51 +++++++++++++
 src/backend/cuda/wrap.hpp   |  21 ++++++
 src/backend/opencl/wrap.cpp |  51 +++++++++++++
 src/backend/opencl/wrap.hpp |  22 ++++++
 test/wrap.cpp               | 178 ++++++++++++++++++++++++++++++++++++++++++++
 13 files changed, 648 insertions(+), 14 deletions(-)

diff --git a/docs/details/image.dox b/docs/details/image.dox
index ed0efae..ed07f03 100644
--- a/docs/details/image.dox
+++ b/docs/details/image.dox
@@ -678,15 +678,15 @@ The output array of this function will have \f$ S(x, y) \f$ values at their corr
 =======================================================================
 
 \defgroup image_func_unwrap unwrap
-\ingroup image_mod
+\ingroup image_mod_mat
 
-Generate image with image windows as columns
+Generate an array with image windows as columns
 
 unwrap takes in an input image along with the window sizes \p wx and \p
 wy, strides \p sx and \p sy, and padding \p px and \p py. This function then
 generates a matrix where each windows is an independent column.
 
-The number of columns in the output array are govenered by the number of
+The number of columns (rows if is_column is true) in the output array are govenered by the number of
 windows that can be fit along x and y directions. Padding is applied along all
 4 sides of the matrix with \p px defining the height of the padding along dim
 0 and \p py defining the width of the padding along dim 1.
@@ -769,5 +769,15 @@ unwrap(A, 3, 3, 3, 3, 2, 2) [9 9 1 1]
     0    12     0     0    27     0     0     0     0
    10    13     0    25    28     0     0     0     0
 \endcode
+
+
+=======================================================================
+
+\defgroup image_func_wrap wrap
+\ingroup image_mod_mat
+
+Wrap takes an unwrapped image (see \ref unwrap) and converts it back to an image.
+
+The inputs to this function should be the same as the inputs used to generate the unwrapped image.
 @}
 */
diff --git a/include/af/image.h b/include/af/image.h
index 6bdbfb4..7fbecc5 100644
--- a/include/af/image.h
+++ b/include/af/image.h
@@ -411,8 +411,8 @@ AFAPI array histEqual(const array& in, const array& hist);
 /**
    C++ Interface for generating gausian kernels
 
-   \param[in]  rows number of kernel rows
-   \param[in]  cols number of kernel columns
+   \param[in]  rows number of rows of the kernel
+   \param[in]  cols number of columns of the kernel
    \param[in]  sig_r (default 0) (calculated internally as 0.25 * rows + 0.75)
    \param[in]  sig_c (default 0) (calculated internally as 0.25 * cols + 0.75)
    \return     an array with values generated using gaussian function
@@ -476,7 +476,7 @@ AFAPI array dog(const array& in, const int radius1, const int radius2);
 /**
    C++ Interface wrapper for unwrap
 
-   \param[in]  in is the input array
+   \param[in]  in is the input image (or set of images)
    \param[in]  wx is the block window size along 0th-dimension between [1, input.dims[0] + px]
    \param[in]  wy is the block window size along 1st-dimension between [1, input.dims[1] + py]
    \param[in]  sx is the stride along 0th-dimension
@@ -484,7 +484,7 @@ AFAPI array dog(const array& in, const int radius1, const int radius2);
    \param[in]  px is the padding along 0th-dimension between [0, wx). Padding is applied both before and after.
    \param[in]  py is the padding along 1st-dimension between [0, wy). Padding is applied both before and after.
    \param[in]  is_column specifies the layout for the unwrapped patch. If is_column is false, the unrapped patch is laid out as a row.
-   \returns    an array with the image blocks as columns
+   \returns    an array with the image blocks as rows or columns
 
    \ingroup image_func_unwrap
 */
@@ -492,6 +492,29 @@ AFAPI array unwrap(const array& in, const dim_t wx, const dim_t wy,
                    const dim_t sx, const dim_t sy, const dim_t px=0, const dim_t py=0,
                    const bool is_column = true);
 
+/**
+   C++ Interface wrapper for wrap
+
+   \param[in]  in is the input image (or set of images)
+   \param[in]  ox is the 0th-dimension of output
+   \param[in]  oy is the ist-dimension of output
+   \param[in]  wx is the block window size along 0th-dimension between
+   \param[in]  wy is the block window size along 1st-dimension between
+   \param[in]  sx is the stride along 0th-dimension
+   \param[in]  sy is the stride along 1st-dimension
+   \param[in]  px is the padding used along 0th-dimension between [0, wx).
+   \param[in]  py is the padding used along 1st-dimension between [0, wy).
+   \param[in]  is_column specifies the layout for the unwrapped patch. If is_column is false, the rows are treated as patches
+   \returns    an array of images after converting rows or columns into image windows
+
+   \ingroup image_func_wrap
+*/
+AFAPI array wrap(const array& in,
+                 const dim_t ox, const dim_t oy,
+                 const dim_t wx, const dim_t wy,
+                 const dim_t sx, const dim_t sy,
+                 const dim_t px = 0, const dim_t py = 0,
+                 const bool is_column = true);
 
 /**
    C++ Interface wrapper for summed area tables
@@ -913,8 +936,8 @@ extern "C" {
        C Interface generating gaussian kernels
 
        \param[out] out is an array with values generated using gaussian function
-       \param[in]  rows number of kernel rows
-       \param[in]  cols number of kernel columns
+       \param[in]  rows number of rows of the gaussian kernel
+       \param[in]  cols number of columns of the gaussian kernel
        \param[in]  sigma_r (default 0) (calculated internally as 0.25 * rows + 0.75)
        \param[in]  sigma_c (default 0) (calculated internally as 0.25 * cols + 0.75)
        \return     \ref AF_SUCCESS if gaussian distribution values are generated successfully,
@@ -990,8 +1013,8 @@ extern "C" {
     /**
        C Interface wrapper for unwrap
 
-       \param[out] out is an array with image blocks as columns.
-       \param[in]  in is the input array
+       \param[out] out is an array with image blocks as rows or columns.
+       \param[in]  in is the input image (or set of images)
        \param[in]  wx is the block window size along 0th-dimension between [1, input.dims[0] + px]
        \param[in]  wy is the block window size along 1st-dimension between [1, input.dims[1] + py]
        \param[in]  sx is the stride along 0th-dimension
@@ -1009,6 +1032,35 @@ extern "C" {
                            const bool is_column);
 
     /**
+       C Interface wrapper for wrap
+
+       \param[out] out is an array after converting
+       \param[in]  in is the input array
+       \param[in]  ox is the 0th-dimension of \p out
+       \param[in]  oy is the ist-dimension of \p out
+       \param[in]  wx is the block window size along 0th-dimension between
+       \param[in]  wy is the block window size along 1st-dimension between
+       \param[in]  sx is the stride along 0th-dimension
+       \param[in]  sy is the stride along 1st-dimension
+       \param[in]  px is the padding used along 0th-dimension between [0, wx).
+       \param[in]  py is the padding used along 1st-dimension between [0, wy).
+       \param[in]  is_column specifies the layout for the unwrapped patch. If is_column is false, the rows are treated as the patches
+       \return     \ref AF_SUCCESS if the color transformation is successful,
+       otherwise an appropriate error code is returned.
+
+       \note The padding used in \ref af_unwrap is calculated from the provided parameters
+
+       \ingroup image_func_wrap
+    */
+    AFAPI af_err af_wrap(af_array *out,
+                         const af_array in,
+                         const dim_t ox, const dim_t oy,
+                         const dim_t wx, const dim_t wy,
+                         const dim_t sx, const dim_t sy,
+                         const dim_t px, const dim_t py,
+                         const bool is_column);
+
+    /**
        C Interface wrapper for summed area tables
 
        \param[out] out is the summed area table on input image(s)
diff --git a/include/arrayfire.h b/include/arrayfire.h
index 92c5cb1..c3d6022 100644
--- a/include/arrayfire.h
+++ b/include/arrayfire.h
@@ -138,6 +138,9 @@
      @defgroup connected_comps_mat Connected Components & Labeling
      regions
 
+     @defgroup image_mod_mat Wrapping and unwrapping image windows
+     wrap, unwrap, etc.
+
      @defgroup utility_mat Utility Functions
      loadImage, saveImage, gaussianKernel
    @}
diff --git a/src/api/c/wrap.cpp b/src/api/c/wrap.cpp
new file mode 100644
index 0000000..dc2b54b
--- /dev/null
+++ b/src/api/c/wrap.cpp
@@ -0,0 +1,78 @@
+/*******************************************************
+ * Copyright (c) 2015, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <af/image.h>
+#include <af/defines.h>
+#include <err_common.hpp>
+#include <handle.hpp>
+#include <backend.hpp>
+#include <ArrayInfo.hpp>
+#include <wrap.hpp>
+
+using af::dim4;
+using namespace detail;
+
+template<typename T>
+static inline af_array wrap(const af_array in,
+                            const dim_t ox, const dim_t oy,
+                            const dim_t wx, const dim_t wy,
+                            const dim_t sx, const dim_t sy,
+                            const dim_t px, const dim_t py,
+                            const bool is_column)
+{
+    return getHandle(wrap<T>(getArray<T>(in), ox, oy, wx, wy, sx, sy, px, py, is_column));
+}
+
+af_err af_wrap(af_array *out, const af_array in,
+               const dim_t ox, const dim_t oy,
+               const dim_t wx, const dim_t wy,
+               const dim_t sx, const dim_t sy,
+               const dim_t px, const dim_t py,
+               const bool is_column)
+{
+    try {
+        ArrayInfo info = getInfo(in);
+        af_dtype type = info.getType();
+        af::dim4 idims = info.dims();
+
+        ARG_ASSERT(2, wx > 0);
+        ARG_ASSERT(3, wx > 0);
+        ARG_ASSERT(4, sx > 0);
+        ARG_ASSERT(5, sy > 0);
+
+        dim_t nx = (ox + 2 * px - wx) / sx + 1;
+        dim_t ny = (oy + 2 * py - wy) / sy + 1;
+
+        dim_t patch_size  = is_column ? idims[0] : idims[1];
+        dim_t num_patches = is_column ? idims[1] : idims[0];
+
+        DIM_ASSERT(1, patch_size == wx * wy);
+        DIM_ASSERT(1, num_patches == nx * ny);
+
+        af_array output;
+
+        switch(type) {
+            case f32: output = wrap<float  >(in, ox, oy, wx, wy, sx, sy, px, py, is_column);  break;
+            case f64: output = wrap<double >(in, ox, oy, wx, wy, sx, sy, px, py, is_column);  break;
+            case c32: output = wrap<cfloat >(in, ox, oy, wx, wy, sx, sy, px, py, is_column);  break;
+            case c64: output = wrap<cdouble>(in, ox, oy, wx, wy, sx, sy, px, py, is_column);  break;
+            case s32: output = wrap<int    >(in, ox, oy, wx, wy, sx, sy, px, py, is_column);  break;
+            case u32: output = wrap<uint   >(in, ox, oy, wx, wy, sx, sy, px, py, is_column);  break;
+            case s64: output = wrap<intl   >(in, ox, oy, wx, wy, sx, sy, px, py, is_column);  break;
+            case u64: output = wrap<uintl  >(in, ox, oy, wx, wy, sx, sy, px, py, is_column);  break;
+            case u8:  output = wrap<uchar  >(in, ox, oy, wx, wy, sx, sy, px, py, is_column);  break;
+            case b8:  output = wrap<char   >(in, ox, oy, wx, wy, sx, sy, px, py, is_column);  break;
+            default:  TYPE_ERROR(1, type);
+        }
+        std::swap(*out,output);
+    }
+    CATCHALL;
+
+    return AF_SUCCESS;
+}
diff --git a/src/api/cpp/wrap.cpp b/src/api/cpp/wrap.cpp
new file mode 100644
index 0000000..ee95f84
--- /dev/null
+++ b/src/api/cpp/wrap.cpp
@@ -0,0 +1,27 @@
+/*******************************************************
+ * Copyright (c) 2015, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <af/array.h>
+#include <af/image.h>
+#include "error.hpp"
+
+namespace af
+{
+    array wrap(const array& in,
+               const dim_t ox, const dim_t oy,
+               const dim_t wx, const dim_t wy,
+               const dim_t sx, const dim_t sy,
+               const dim_t px, const dim_t py,
+               const bool is_column)
+    {
+        af_array out = 0;
+        AF_THROW(af_wrap(&out, in.get(), ox, oy, wx, wy, sx, sy, px, py, is_column));
+        return array(out);
+    }
+}
diff --git a/src/backend/cpu/unwrap.cpp b/src/backend/cpu/unwrap.cpp
index 25a8d32..466da2e 100644
--- a/src/backend/cpu/unwrap.cpp
+++ b/src/backend/cpu/unwrap.cpp
@@ -47,9 +47,7 @@ namespace cpu
                     dim_t spy = starty - py;
 
                     // Short cut condition ensuring all values within input dimensions
-                    bool cond = false;
-                    if(spx >= 0 && spx + wx < idims[0] && spy >= 0 && spy + wy < idims[1])
-                        cond = true;
+                    bool cond = (spx >= 0 && spx + wx < idims[0] && spy >= 0 && spy + wy < idims[1]);
 
                     for(dim_t y = 0; y < wy; y++) {
                         for(dim_t x = 0; x < wx; x++) {
diff --git a/src/backend/cpu/wrap.cpp b/src/backend/cpu/wrap.cpp
new file mode 100644
index 0000000..1ed9150
--- /dev/null
+++ b/src/backend/cpu/wrap.cpp
@@ -0,0 +1,122 @@
+/*******************************************************
+ * Copyright (c) 2015, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <Array.hpp>
+#include <wrap.hpp>
+#include <stdexcept>
+#include <err_cpu.hpp>
+#include <dispatch.hpp>
+#include <math.hpp>
+
+namespace cpu
+{
+
+    template<typename T, int d>
+    void wrap_dim(T *outPtr, const T *inPtr,
+                  const af::dim4 &odims, const af::dim4 &idims,
+                  const af::dim4 &ostrides, const af::dim4 &istrides,
+                  const dim_t wx, const dim_t wy,
+                  const dim_t sx, const dim_t sy,
+                  const dim_t px, const dim_t py)
+    {
+        dim_t nx = (odims[0] + 2 * px - wx) / sx + 1;
+
+        for(dim_t w = 0; w < idims[3]; w++) {
+            for(dim_t z = 0; z < idims[2]; z++) {
+
+                dim_t cIn  = w * istrides[3] + z * istrides[2];
+                dim_t cOut = w * ostrides[3] + z * ostrides[2];
+                const T* iptr_ = inPtr  + cIn;
+                T* optr= outPtr + cOut;
+
+                for(dim_t col = 0; col < idims[d]; col++) {
+                    // Offset output ptr
+                    const T* iptr = iptr_ + col * istrides[d];
+
+                    // Calculate input window index
+                    dim_t winy = (col / nx);
+                    dim_t winx = (col % nx);
+
+                    dim_t startx = winx * sx;
+                    dim_t starty = winy * sy;
+
+                    dim_t spx = startx - px;
+                    dim_t spy = starty - py;
+
+                    // Short cut condition ensuring all values within input dimensions
+                    bool cond = (spx >= 0 && spx + wx < odims[0] && spy >= 0 && spy + wy < odims[1]);
+
+                    for(dim_t y = 0; y < wy; y++) {
+                        for(dim_t x = 0; x < wx; x++) {
+                            dim_t xpad = spx + x;
+                            dim_t ypad = spy + y;
+
+                            dim_t iloc = (y * wx + x);
+                            if (d == 0) iloc *= istrides[1];
+
+                            if(cond || (xpad >= 0 && xpad < odims[0] && ypad >= 0 && ypad < odims[1])) {
+                                dim_t oloc = (ypad * ostrides[1] + xpad * ostrides[0]);
+                                // FIXME: When using threads, atomize this
+                                optr[oloc] += iptr[iloc];
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    template<typename T>
+    Array<T> wrap(const Array<T> &in,
+                  const dim_t ox, const dim_t oy,
+                  const dim_t wx, const dim_t wy,
+                  const dim_t sx, const dim_t sy,
+                  const dim_t px, const dim_t py,
+                  const bool is_column)
+    {
+        af::dim4 idims = in.dims();
+        af::dim4 odims(ox, oy, idims[2], idims[3]);
+        Array<T> out = createValueArray<T>(odims, scalar<T>(0));
+
+        const T *inPtr = in.get();
+        T *outPtr = out.get();
+
+        af::dim4 istrides = in.strides();
+        af::dim4 ostrides = out.strides();
+
+        if (is_column) {
+            wrap_dim<T, true >(outPtr, inPtr, odims, idims, ostrides, istrides, wx, wy, sx, sy, px, py);
+        } else {
+            wrap_dim<T, false>(outPtr, inPtr, odims, idims, ostrides, istrides, wx, wy, sx, sy, px, py);
+        }
+
+        return out;
+    }
+
+
+#define INSTANTIATE(T)                                          \
+    template Array<T> wrap<T> (const Array<T> &in,              \
+                               const dim_t ox, const dim_t oy,  \
+                               const dim_t wx, const dim_t wy,  \
+                               const dim_t sx, const dim_t sy,  \
+                               const dim_t px, const dim_t py,  \
+                               const bool is_column);
+
+
+    INSTANTIATE(float)
+    INSTANTIATE(double)
+    INSTANTIATE(cfloat)
+    INSTANTIATE(cdouble)
+    INSTANTIATE(int)
+    INSTANTIATE(uint)
+    INSTANTIATE(intl)
+    INSTANTIATE(uintl)
+    INSTANTIATE(uchar)
+    INSTANTIATE(char)
+}
diff --git a/src/backend/cpu/wrap.hpp b/src/backend/cpu/wrap.hpp
new file mode 100644
index 0000000..00263e7
--- /dev/null
+++ b/src/backend/cpu/wrap.hpp
@@ -0,0 +1,21 @@
+/*******************************************************
+ * Copyright (c) 2015, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <Array.hpp>
+
+namespace cpu
+{
+    template<typename T>
+    Array<T> wrap(const Array<T> &in,
+                  const dim_t ox, const dim_t oy,
+                  const dim_t wx, const dim_t wy,
+                  const dim_t sx, const dim_t sy,
+                  const dim_t px, const dim_t py,
+                  const bool is_column);
+}
diff --git a/src/backend/cuda/wrap.cu b/src/backend/cuda/wrap.cu
new file mode 100644
index 0000000..f7da711
--- /dev/null
+++ b/src/backend/cuda/wrap.cu
@@ -0,0 +1,51 @@
+/*******************************************************
+ * Copyright (c) 2015, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <Array.hpp>
+#include <wrap.hpp>
+#include <stdexcept>
+#include <err_cuda.hpp>
+#include <dispatch.hpp>
+#include <math.hpp>
+
+namespace cuda
+{
+
+    template<typename T>
+    Array<T> wrap(const Array<T> &in,
+                  const dim_t ox, const dim_t oy,
+                  const dim_t wx, const dim_t wy,
+                  const dim_t sx, const dim_t sy,
+                  const dim_t px, const dim_t py,
+                  const bool is_column)
+    {
+        CUDA_NOT_SUPPORTED();
+    }
+
+
+#define INSTANTIATE(T)                                          \
+    template Array<T> wrap<T> (const Array<T> &in,              \
+                               const dim_t ox, const dim_t oy,  \
+                               const dim_t wx, const dim_t wy,  \
+                               const dim_t sx, const dim_t sy,  \
+                               const dim_t px, const dim_t py,  \
+                               const bool is_column);
+
+
+    INSTANTIATE(float)
+    INSTANTIATE(double)
+    INSTANTIATE(cfloat)
+    INSTANTIATE(cdouble)
+    INSTANTIATE(int)
+    INSTANTIATE(uint)
+    INSTANTIATE(intl)
+    INSTANTIATE(uintl)
+    INSTANTIATE(uchar)
+    INSTANTIATE(char)
+}
diff --git a/src/backend/cuda/wrap.hpp b/src/backend/cuda/wrap.hpp
new file mode 100644
index 0000000..300b061
--- /dev/null
+++ b/src/backend/cuda/wrap.hpp
@@ -0,0 +1,21 @@
+/*******************************************************
+ * Copyright (c) 2015, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <Array.hpp>
+
+namespace cuda
+{
+    template<typename T>
+    Array<T> wrap(const Array<T> &in,
+                  const dim_t ox, const dim_t oy,
+                  const dim_t wx, const dim_t wy,
+                  const dim_t sx, const dim_t sy,
+                  const dim_t px, const dim_t py,
+                  const bool is_column);
+}
diff --git a/src/backend/opencl/wrap.cpp b/src/backend/opencl/wrap.cpp
new file mode 100644
index 0000000..240b4a6
--- /dev/null
+++ b/src/backend/opencl/wrap.cpp
@@ -0,0 +1,51 @@
+/*******************************************************
+ * Copyright (c) 2015, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <Array.hpp>
+#include <wrap.hpp>
+#include <stdexcept>
+#include <err_opencl.hpp>
+#include <dispatch.hpp>
+#include <math.hpp>
+
+namespace opencl
+{
+
+    template<typename T>
+    Array<T> wrap(const Array<T> &in,
+                  const dim_t ox, const dim_t oy,
+                  const dim_t wx, const dim_t wy,
+                  const dim_t sx, const dim_t sy,
+                  const dim_t px, const dim_t py,
+                  const bool is_column)
+    {
+        OPENCL_NOT_SUPPORTED();
+    }
+
+
+#define INSTANTIATE(T)                                          \
+    template Array<T> wrap<T> (const Array<T> &in,              \
+                               const dim_t ox, const dim_t oy,  \
+                               const dim_t wx, const dim_t wy,  \
+                               const dim_t sx, const dim_t sy,  \
+                               const dim_t px, const dim_t py,  \
+                               const bool is_column);
+
+
+    INSTANTIATE(float)
+    INSTANTIATE(double)
+    INSTANTIATE(cfloat)
+    INSTANTIATE(cdouble)
+    INSTANTIATE(int)
+    INSTANTIATE(uint)
+    INSTANTIATE(intl)
+    INSTANTIATE(uintl)
+    INSTANTIATE(uchar)
+    INSTANTIATE(char)
+}
diff --git a/src/backend/opencl/wrap.hpp b/src/backend/opencl/wrap.hpp
new file mode 100644
index 0000000..1be64f4
--- /dev/null
+++ b/src/backend/opencl/wrap.hpp
@@ -0,0 +1,22 @@
+/*******************************************************
+ * Copyright (c) 2015, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <Array.hpp>
+
+namespace opencl
+{
+    template<typename T>
+    Array<T> wrap(const Array<T> &in,
+                  const dim_t ox, const dim_t oy,
+                  const dim_t wx, const dim_t wy,
+                  const dim_t sx, const dim_t sy,
+                  const dim_t px, const dim_t py,
+                  const bool is_column);
+
+}
diff --git a/test/wrap.cpp b/test/wrap.cpp
new file mode 100644
index 0000000..3d5f735
--- /dev/null
+++ b/test/wrap.cpp
@@ -0,0 +1,178 @@
+/*******************************************************
+ * Copyright (c) 2014, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <gtest/gtest.h>
+#include <arrayfire.h>
+#include <af/dim4.hpp>
+#include <af/defines.h>
+#include <af/traits.hpp>
+#include <vector>
+#include <iostream>
+#include <complex>
+#include <string>
+#include <testHelpers.hpp>
+#include <algorithm>
+
+using std::vector;
+using std::string;
+using std::cout;
+using std::endl;
+using af::cfloat;
+using af::cdouble;
+
+template<typename T>
+class Wrap : public ::testing::Test
+{
+    public:
+        virtual void SetUp() {
+        }
+};
+
+// create a list of types to be tested
+typedef ::testing::Types<float, double, cfloat, cdouble, int, unsigned int, intl, uintl, char, unsigned char> TestTypes;
+
+// register the type list
+TYPED_TEST_CASE(Wrap, TestTypes);
+
+template<typename T>
+double get_val(T val)
+{
+    return val;
+}
+
+template<> double get_val<cfloat>(cfloat val)
+{
+    return abs(val);
+}
+
+template<> double get_val<cdouble>(cdouble val)
+{
+    return abs(val);
+}
+
+template<> double get_val<unsigned char>(unsigned char val)
+{
+    return ((int)(val)) % 256;
+}
+
+template<> double get_val<char>(char val)
+{
+    return (val != 0);
+}
+
+template<typename T>
+void wrapTest(const dim_t ix, const dim_t iy,
+              const dim_t wx, const dim_t wy,
+              const dim_t sx, const dim_t sy,
+              const dim_t px, const dim_t py)
+{
+    if (noDoubleTests<T>()) return;
+
+    const int nc = 1;
+
+    int lim = std::max((dim_t)2, (dim_t)(250) / (wx * wy));
+
+    af::dtype ty = (af::dtype)af::dtype_traits<T>::af_type;
+    af::array in = af::round(lim * af::randu(ix, iy, nc, f32)).as(ty);
+
+    std::vector<T> h_in(in.elements());
+    in.host(&h_in[0]);
+
+    std::vector<int> h_factor(ix * iy);
+
+    dim_t ny = (iy + 2 * py - wy) / sy + 1;
+    dim_t nx = (ix + 2 * px - wx) / sx + 1;
+
+    for (int idy = 0; idy < ny; idy++) {
+        int fy = idy * sy - py;
+        if (fy + wy < 0 || fy >= iy) continue;
+
+        for (int idx = 0; idx < nx; idx++) {
+            int fx = idx * sx - px;
+            if (fx + wx < 0 || fx >= ix) continue;
+
+            for (int ly = 0; ly < wy; ly++) {
+                if (fy + ly < 0 || fy + ly >= iy) continue;
+
+                for (int lx = 0; lx < wx; lx++) {
+                    if (fx + lx < 0 || fx + lx >= ix) continue;
+                    h_factor[(fy + ly) * ix + (fx + lx)]++;
+                }
+            }
+        }
+    }
+
+    af::array factor(ix, iy, &h_factor[0]);
+
+    for (int i = 0; i <= 1; i++)
+    {
+        bool cond = i == 0;
+        af::array in_dim = af::unwrap(in, wx, wy, sx, sy, px, py, cond);
+        af::array res_dim = af::wrap(in_dim, ix, iy, wx, wy, sx, sy, px, py, cond);
+
+        ASSERT_EQ(in.elements(), res_dim.elements());
+
+        std::vector<T> h_res(ix * iy);
+        res_dim.host(&h_res[0]);
+
+        for (int n = 0; n < nc; n++) {
+            T *iptr = &h_in[n * ix * iy];
+            T *rptr = &h_res[n * ix * iy];
+
+            for (int y = 0; y < iy; y++) {
+                for (int x = 0; x < ix; x++) {
+
+                    // FIXME: Use a better test
+                    T ival = iptr[y * ix + x];
+                    T rval = rptr[y * ix + x];
+                    int factor = h_factor[y * ix + x];
+
+                    if (abs(ival) == 0) continue;
+
+                    ASSERT_NEAR(get_val<T>(ival * factor), get_val<T>(rval), 1E-5)
+                        << "at " << x << "," << y << std::endl;
+                }
+            }
+
+        }
+    }
+}
+
+#define WRAP_INIT(desc, ix, iy, wx, wy, sx, sy, px,py)          \
+    TYPED_TEST(Wrap, desc)                                      \
+    {                                                           \
+        wrapTest<TypeParam>(ix, iy, wx, wy, sx, sy, px, py);    \
+    }
+
+    WRAP_INIT(Wrap00, 300, 100,  3,  3,  1,  1,  0,  0);
+    WRAP_INIT(Wrap01, 300, 100,  3,  3,  1,  1,  1,  1);
+    WRAP_INIT(Wrap03, 300, 100,  3,  3,  2,  2,  0,  0);
+    WRAP_INIT(Wrap04, 300, 100,  3,  3,  2,  2,  1,  1);
+    WRAP_INIT(Wrap05, 300, 100,  3,  3,  2,  2,  2,  2);
+    WRAP_INIT(Wrap06, 300, 100,  3,  3,  3,  3,  0,  0);
+    WRAP_INIT(Wrap07, 300, 100,  3,  3,  3,  3,  1,  1);
+    WRAP_INIT(Wrap08, 300, 100,  3,  3,  3,  3,  2,  2);
+    WRAP_INIT(Wrap09, 300, 100,  4,  4,  1,  1,  0,  0);
+    WRAP_INIT(Wrap13, 300, 100,  4,  4,  2,  2,  0,  0);
+    WRAP_INIT(Wrap14, 300, 100,  4,  4,  2,  2,  1,  1);
+    WRAP_INIT(Wrap15, 300, 100,  4,  4,  2,  2,  2,  2);
+    WRAP_INIT(Wrap16, 300, 100,  4,  4,  2,  2,  3,  3);
+    WRAP_INIT(Wrap17, 300, 100,  4,  4,  4,  4,  0,  0);
+    WRAP_INIT(Wrap18, 300, 100,  4,  4,  4,  4,  1,  1);
+    WRAP_INIT(Wrap19, 300, 100,  4,  4,  4,  4,  2,  2);
+    WRAP_INIT(Wrap27, 300, 100,  8,  8,  8,  8,  0,  0);
+    WRAP_INIT(Wrap28, 300, 100,  8,  8,  8,  8,  7,  7);
+    WRAP_INIT(Wrap31, 300, 100, 12, 12, 12, 12,  0,  0);
+    WRAP_INIT(Wrap32, 300, 100, 12, 12, 12, 12,  2,  2);
+    WRAP_INIT(Wrap35, 300, 100, 16, 16, 16, 16, 15, 15);
+    WRAP_INIT(Wrap36, 300, 100, 31, 31,  8,  8, 15, 15);
+    WRAP_INIT(Wrap39, 300, 100,  8, 12,  8, 12,  0,  0);
+    WRAP_INIT(Wrap40, 300, 100,  8, 12,  8, 12,  7, 11);
+    WRAP_INIT(Wrap43, 300, 100, 15, 10, 15, 10,  0,  0);
+    WRAP_INIT(Wrap44, 300, 100, 15, 10, 15, 10, 14,  9);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/arrayfire.git



More information about the debian-science-commits mailing list