[arrayfire] 360/408: FEAT: Adding support for linear assignment in C API
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Mon Sep 21 19:12:30 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 aa8bc95f331f4913ead66fe2046140ac8644fdbb
Author: Pavan Yalamanchili <pavan at arrayfire.com>
Date: Wed Aug 26 11:44:39 2015 -0400
FEAT: Adding support for linear assignment in C API
---
src/api/c/assign.cpp | 75 +++++++++++++++++++-------
test/assign.cpp | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 202 insertions(+), 19 deletions(-)
diff --git a/src/api/c/assign.cpp b/src/api/c/assign.cpp
index 00dcc05..7d5e651 100644
--- a/src/api/c/assign.cpp
+++ b/src/api/c/assign.cpp
@@ -19,6 +19,7 @@
#include <copy.hpp>
#include <assign.hpp>
#include <math.hpp>
+#include <tile.hpp>
using namespace detail;
using std::vector;
@@ -49,13 +50,21 @@ void assign(Array<Tout> &out, const unsigned &ndims, const af_seq *index, const
is_vector &= oDims[i] == 1;
}
- if (is_vector && in_.isVector()) {
- if (oDims.elements() != (dim_t)in_.elements()) {
+ is_vector &= in_.isVector() || in_.isScalar();
+
+ for (dim_t i = ndims; i < (int)in_.ndims(); i++) {
+ oDims[i] = 1;
+ }
+
+
+ if (is_vector) {
+ if (oDims.elements() != (dim_t)in_.elements() &&
+ in_.elements() != 1) {
AF_ERROR("Size mismatch between input and output", AF_ERR_SIZE);
}
// If both out and in are vectors of equal elements, reshape in to out dims
- Array<Tin> in = modDims(in_, oDims);
+ Array<Tin> in = in_.elements() == 1 ? tile(in_, oDims) : modDims(in_, oDims);
Array<Tout> dst = createSubArray<Tout>(out, index_, false);
copyArray<Tin , Tout>(dst, in);
@@ -112,6 +121,15 @@ af_err af_assign_seq(af_array *out,
ARG_ASSERT(1, (ndims>0));
ARG_ASSERT(3, (rhs!=0));
+
+ if (ndims == 1 && ndims != (dim_t)getInfo(lhs).ndims()) {
+ af_array tmp;
+ AF_CHECK(af_flat(&tmp, lhs));
+ AF_CHECK(af_assign_seq(out, tmp, ndims, index, rhs));
+ AF_CHECK(af_release_array(tmp));
+ return AF_SUCCESS;
+ }
+
for(dim_t i=0; i<(dim_t)ndims; ++i) {
ARG_ASSERT(2, (index[i].step>=0));
}
@@ -200,18 +218,6 @@ af_err af_assign_gen(af_array *out,
ARG_ASSERT(1, (lhs!=0));
ARG_ASSERT(4, (rhs!=0));
- if (*out != lhs) {
- int count = 0;
- AF_CHECK(af_get_data_ref_count(&count, lhs));
- if (count > 1) {
- AF_CHECK(af_copy_array(&output, lhs));
- } else {
- AF_CHECK(af_retain_array(&output, lhs));
- }
- } else {
- output = lhs;
- }
-
ArrayInfo lInfo = getInfo(lhs);
ArrayInfo rInfo = getInfo(rhs);
dim4 lhsDims = lInfo.dims();
@@ -219,11 +225,33 @@ af_err af_assign_gen(af_array *out,
af_dtype lhsType= lInfo.getType();
af_dtype rhsType= rInfo.getType();
+ ARG_ASSERT(2, (ndims == 1) || (ndims == (dim_t)lInfo.ndims()));
+
+ if (ndims == 1 && ndims != (dim_t)lInfo.ndims()) {
+ af_array tmp;
+ AF_CHECK(af_flat(&tmp, lhs));
+ AF_CHECK(af_assign_gen(out, tmp, ndims, indexs, rhs_));
+ AF_CHECK(af_release_array(tmp));
+ return AF_SUCCESS;
+ }
+
ARG_ASSERT(1, (lhsType==rhsType));
ARG_ASSERT(3, (rhsDims.ndims()>0));
ARG_ASSERT(1, (lhsDims.ndims()>=rhsDims.ndims()));
ARG_ASSERT(2, (lhsDims.ndims()>=ndims));
+ if (*out != lhs) {
+ int count = 0;
+ AF_CHECK(af_get_data_ref_count(&count, lhs));
+ if (count > 1) {
+ AF_CHECK(af_copy_array(&output, lhs));
+ } else {
+ AF_CHECK(af_retain_array(&output, lhs));
+ }
+ } else {
+ output = lhs;
+ }
+
dim4 oDims = toDims(seqs, lhsDims);
// if af_array are indexs along any
// particular dimension, set the length of
@@ -234,20 +262,29 @@ af_err af_assign_gen(af_array *out,
}
}
+ for (dim_t i = ndims; i < (dim_t)lInfo.ndims(); i++) {
+ oDims[i] = 1;
+ }
+
bool is_vector = true;
for (int i = 0; is_vector && i < oDims.ndims() - 1; i++) {
is_vector &= oDims[i] == 1;
}
//TODO: Move logic out of this
- is_vector &= rInfo.isVector();
+ is_vector &= rInfo.isVector() || rInfo.isScalar();
if (is_vector) {
- if (oDims.elements() != (dim_t)rInfo.elements()) {
+ if (oDims.elements() != (dim_t)rInfo.elements() &&
+ rInfo.elements() != 1) {
AF_ERROR("Size mismatch between input and output", AF_ERR_SIZE);
}
- // If both out and rhs are vectors of equal elements, reshape rhs to out dims
- AF_CHECK(af_moddims(&rhs, rhs_, oDims.ndims(), oDims.get()));
+ if (rInfo.elements() == 1) {
+ AF_CHECK(af_tile(&rhs, rhs_, oDims[0], oDims[1], oDims[2], oDims[3]));
+ } else {
+ // If both out and rhs are vectors of equal elements, reshape rhs to out dims
+ AF_CHECK(af_moddims(&rhs, rhs_, oDims.ndims(), oDims.get()));
+ }
} else {
for (int i = 0; i < 4; i++) {
if (oDims[i] != rhsDims[i]) {
diff --git a/test/assign.cpp b/test/assign.cpp
index aa92079..3abe1b4 100644
--- a/test/assign.cpp
+++ b/test/assign.cpp
@@ -830,3 +830,149 @@ TEST(Assign, Copy)
delete[] h_a;
delete[] h_b;
}
+
+TEST(Asssign, LinearCPP)
+{
+ using af::array;
+ const int nx = 5;
+ const int ny = 4;
+ const float val = 3;
+
+ const int st = nx - 2;
+ const int en = nx * (ny - 1);
+
+ array a = af::randu(nx, ny);
+ array a_copy = a;
+ af::index idx = af::seq(st, en);
+ a(idx) = 3;
+
+ std::vector<float> ha(nx * ny);
+ std::vector<float> ha_copy(nx * ny);
+
+ a.host(&ha[0]);
+ a_copy.host(&ha_copy[0]);
+
+ for (int i = 0; i < nx * ny; i++) {
+ if (i < st || i > en)
+ ASSERT_EQ(ha[i], ha_copy[i]) << "at " << i;
+ else
+ ASSERT_EQ(ha[i], val) << "at " << i;
+ }
+}
+
+TEST(Asssign, LinearAssignSeq)
+{
+ using af::array;
+ const int nx = 5;
+ const int ny = 4;
+ const float val = 3;
+ const array rhs = af::constant(val, 1, 1);
+
+ const int st = nx - 2;
+ const int en = nx * (ny - 1);
+
+ array a = af::randu(nx, ny);
+ af::index idx = af::seq(st, en);
+
+ af_array in_arr = a.get();
+ af_index_t ii = idx.get();
+ af_array rhs_arr = rhs.get();
+ af_array out_arr;
+
+ ASSERT_EQ(AF_SUCCESS,
+ af_assign_seq(&out_arr, in_arr, 1, &ii.idx.seq, rhs_arr));
+
+ af::array out(out_arr);
+
+
+ std::vector<float> hout(nx * ny);
+ std::vector<float> ha(nx * ny);
+
+ a.host(&ha[0]);
+ out.host(&hout[0]);
+
+ for (int i = 0; i < nx * ny; i++) {
+ if (i < st || i > en)
+ ASSERT_EQ(hout[i], ha[i]) << "at " << i;
+ else
+ ASSERT_EQ(hout[i], val) << "at " << i;
+ }
+}
+
+TEST(Asssign, LinearAssignGenSeq)
+{
+ using af::array;
+ const int nx = 5;
+ const int ny = 4;
+ const float val = 3;
+ const array rhs = af::constant(val, 1, 1);
+
+ const int st = nx - 2;
+ const int en = nx * (ny - 1);
+
+ array a = af::randu(nx, ny);
+ af::index idx = af::seq(st, en);
+
+ af_array in_arr = a.get();
+ af_index_t ii = idx.get();
+ af_array rhs_arr = rhs.get();
+ af_array out_arr;
+
+ ASSERT_EQ(AF_SUCCESS,
+ af_assign_gen(&out_arr, in_arr, 1, &ii, rhs_arr));
+
+ af::array out(out_arr);
+
+
+ std::vector<float> hout(nx * ny);
+ std::vector<float> ha(nx * ny);
+
+ a.host(&ha[0]);
+ out.host(&hout[0]);
+
+ for (int i = 0; i < nx * ny; i++) {
+ if (i < st || i > en)
+ ASSERT_EQ(hout[i], ha[i]) << "at " << i;
+ else
+ ASSERT_EQ(hout[i], val) << "at " << i;
+ }
+}
+
+TEST(Asssign, LinearAssignGenArr)
+{
+ using af::array;
+ const int nx = 5;
+ const int ny = 4;
+ const float val = 3;
+ const array rhs = af::constant(val, 1, 1);
+
+ const int st = nx - 2;
+ const int en = nx * (ny - 1);
+
+ array a = af::randu(nx, ny);
+ af::index idx = af::array(af::seq(st, en));
+
+ af_array in_arr = a.get();
+ af_index_t ii = idx.get();
+ af_array rhs_arr = rhs.get();
+ af_array out_arr;
+
+ ASSERT_EQ(AF_SUCCESS,
+ af_assign_gen(&out_arr, in_arr, 1, &ii, rhs_arr));
+
+ af::array out(out_arr);
+
+
+ std::vector<float> hout(nx * ny);
+ std::vector<float> ha(nx * ny);
+
+ a.host(&ha[0]);
+ out.host(&hout[0]);
+
+ for (int i = 0; i < nx * ny; i++) {
+ if (i < st || i > en)
+ ASSERT_EQ(hout[i], ha[i]) << "at " << i;
+ else
+ ASSERT_EQ(hout[i], val) << "at " << i;
+ }
+}
--
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