diff --git a/src/api/c/rank.cpp b/src/api/c/rank.cpp index c1eeb737d4..197d2c8974 100644 --- a/src/api/c/rank.cpp +++ b/src/api/c/rank.cpp @@ -17,6 +17,7 @@ #include #include #include +#include using af::dim4; using namespace detail; @@ -24,21 +25,24 @@ using namespace detail; template static inline uint rank(const af_array in, double tol) { + typedef typename af::dtype_traits::base_type BT; Array In = getArray(in); - Array r = createEmptyArray(dim4()); + Array R = createEmptyArray(dim4()); - // Scoping to get rid of q and t as they are not necessary + // Scoping to get rid of q, r and t as they are not necessary { Array q = createEmptyArray(dim4()); + Array r = createEmptyArray(dim4()); Array t = createEmptyArray(dim4()); qr(q, r, t, In); + + R = abs(r); } - Array val = createValueArray(r.dims(), scalar(tol)); - Array gt = logicOp(r, val, val.dims()); + Array val = createValueArray(R.dims(), scalar(tol)); + Array gt = logicOp(R, val, val.dims()); Array at = reduce(gt, 1); - return reduce_all(at); } diff --git a/src/api/c/unary.cpp b/src/api/c/unary.cpp index f1e86ffaba..2b8cc1d4b6 100644 --- a/src/api/c/unary.cpp +++ b/src/api/c/unary.cpp @@ -113,7 +113,7 @@ af_err af_not(af_array *out, const af_array in) in_info.ndims(), in_info.dims().get(), in_info.getType())); - AF_CHECK(af_neq(out, in, tmp, false)); + AF_CHECK(af_eq(out, in, tmp, false)); AF_CHECK(af_release_array(tmp)); } CATCHALL; diff --git a/src/api/cpp/array.cpp b/src/api/cpp/array.cpp index 036db4930a..ba46f6385c 100644 --- a/src/api/cpp/array.cpp +++ b/src/api/cpp/array.cpp @@ -919,8 +919,7 @@ namespace af { af_array lhs = this->get(); af_array out; - array cst = constant(0, this->dims(), this->type()); - AF_THROW(af_eq(&out, cst.get(), lhs, gforGet())); + AF_THROW(af_not(&out, lhs)); return array(out); } diff --git a/src/backend/cpu/random.cpp b/src/backend/cpu/random.cpp index 03fabb37d4..4c91b96fb1 100644 --- a/src/backend/cpu/random.cpp +++ b/src/backend/cpu/random.cpp @@ -86,11 +86,14 @@ Array randn(const af::dim4 &dims) if (my_seed != gen_seed) { gen = nrand(generator); + my_seed = gen_seed; } Array outArray = createEmptyArray(dims); T *outPtr = outArray.get(); - generate(outPtr, outPtr + outArray.elements(), gen); + for (int i = 0; i < (int)outArray.elements(); i++) { + outPtr[i] = gen(); + } return outArray; } @@ -107,6 +110,7 @@ Array randu(const af::dim4 &dims) if (my_seed != gen_seed) { gen = urand(generator); + my_seed = gen_seed; } Array outArray = createEmptyArray(dims); @@ -152,6 +156,7 @@ Array randu(const af::dim4 &dims) if (my_seed != gen_seed) { gen = urand(generator); + my_seed = gen_seed; } Array outArray = createEmptyArray(dims); diff --git a/src/backend/opencl/kernel/random.cl b/src/backend/opencl/kernel/random.cl index 5debf5259b..d6d0f1fa06 100644 --- a/src/backend/opencl/kernel/random.cl +++ b/src/backend/opencl/kernel/random.cl @@ -241,8 +241,13 @@ void generate(T *one, T *two, threefry2_ctr_t *c, threefry2_key_t k) T u1 = result(r.v[0]); T u2 = result(r.v[1]); - T R = sqrt(-2*log(u1)); - T Theta = 2 * PI_VAL * u2; +#if defined(IS_APPLE) // Because Apple is.. "special" + T R = sqrt((T)(-2.0) * log10(u1) * (T)log10_val); +#else + T R = sqrt((T)(-2.0) * log(u1)); +#endif + + T Theta = 2 * (T)PI_VAL * u2; *one = R * sin(Theta); *two = R * cos(Theta); diff --git a/src/backend/opencl/kernel/random.hpp b/src/backend/opencl/kernel/random.hpp index a903e39a01..f951797e97 100644 --- a/src/backend/opencl/kernel/random.hpp +++ b/src/backend/opencl/kernel/random.hpp @@ -106,6 +106,10 @@ namespace opencl std::ostringstream options; options << " -D T=" << dtype_traits::getName() << " -D repeat="<< REPEAT +#if defined(OS_MAC) // Because apple is "special" + << " -D IS_APPLE" + << " -D log10_val=" << std::log(10.0) +#endif << " -D " << random_name().name(); if (std::is_same::value) { diff --git a/test/fft.cpp b/test/fft.cpp index 8a25c1fe76..c2e5fcbe1f 100644 --- a/test/fft.cpp +++ b/test/fft.cpp @@ -81,7 +81,7 @@ TEST(ifft2, Invalid_Array) af::dim4 dims(100,1,1,1); ASSERT_EQ(AF_SUCCESS, af_create_array(&inArray, &(in.front()), - dims.ndims(), dims.get(), (af_dtype) af::dtype_traits::af_type)); + dims.ndims(), dims.get(), (af_dtype) af::dtype_traits::af_type)); ASSERT_EQ(AF_ERR_SIZE, af_ifft2(&outArray, inArray, 0.01, 0, 0)); ASSERT_EQ(AF_SUCCESS, af_release_array(inArray)); @@ -98,7 +98,7 @@ TEST(ifft3, Invalid_Array) af::dim4 dims(10,10,1,1); ASSERT_EQ(AF_SUCCESS, af_create_array(&inArray, &(in.front()), - dims.ndims(), dims.get(), (af_dtype) af::dtype_traits::af_type)); + dims.ndims(), dims.get(), (af_dtype) af::dtype_traits::af_type)); ASSERT_EQ(AF_ERR_SIZE, af_ifft3(&outArray, inArray, 0.01, 0, 0, 0)); ASSERT_EQ(AF_SUCCESS, af_release_array(inArray)); diff --git a/test/math.cpp b/test/math.cpp index e5dbe76194..007054b7c3 100644 --- a/test/math.cpp +++ b/test/math.cpp @@ -105,3 +105,18 @@ MATH_TESTS_DOUBLE(log2) MATH_TESTS_LIMITS(double, double, abs, dbl_err, -10, 10) MATH_TESTS_LIMITS(double, double, ceil, dbl_err, -10, 10) MATH_TESTS_LIMITS(double, double, floor, dbl_err, -10, 10) + +TEST(MathTests, Not) +{ + af::array a = af::randu(5, 5, b8); + af::array b = !a; + char *ha = a.host(); + char *hb = b.host(); + + for(int i = 0; i < a.elements(); i++) { + ASSERT_EQ(ha[i] ^ hb[i], true); + } + + delete[] ha; + delete[] hb; +} diff --git a/test/random.cpp b/test/random.cpp index 5d4f46c255..4ca5126b2a 100644 --- a/test/random.cpp +++ b/test/random.cpp @@ -151,6 +151,8 @@ void testSetSeed(const uintl seed0, const uintl seed1, bool is_norm = false) if (noDoubleTests()) return; + uintl orig_seed = af::getSeed(); + const int num = 1024 * 1024; af::dtype ty = (af::dtype)af::dtype_traits::af_type; @@ -162,23 +164,32 @@ void testSetSeed(const uintl seed0, const uintl seed1, bool is_norm = false) af::setSeed(seed0); af::array in2 = is_norm ? af::randn(num, ty) : af::randu(num, ty); + af::array in3 = is_norm ? af::randn(num, ty) : af::randu(num, ty); std::vector h_in0(num); std::vector h_in1(num); std::vector h_in2(num); + std::vector h_in3(num); in0.host((void *)&h_in0[0]); in1.host((void *)&h_in1[0]); in2.host((void *)&h_in2[0]); + in3.host((void *)&h_in3[0]); for (int i = 0; i < num; i++) { // Verify if same seed produces same arrays ASSERT_EQ(h_in0[i], h_in2[i]); - // Verify different arrays don't clash at same location + // Verify different arrays created with different seeds differ // b8 and u9 can clash because they generate a small set of values if (ty != b8 && ty != u8) ASSERT_NE(h_in0[i], h_in1[i]); + + // Verify different arrays created one after the other with same seed differ + // b8 and u9 can clash because they generate a small set of values + if (ty != b8 && ty != u8) ASSERT_NE(h_in2[i], h_in3[i]); } + + af::setSeed(orig_seed); // Reset the seed } TYPED_TEST(Random, setSeed) @@ -188,7 +199,7 @@ TYPED_TEST(Random, setSeed) TYPED_TEST(Random_norm, setSeed) { - testSetSeed(456, 789, false); + testSetSeed(456, 789, true); } template @@ -196,6 +207,8 @@ void testGetSeed(const uintl seed0, const uintl seed1) { if (noDoubleTests()) return; + uintl orig_seed = af::getSeed(); + const int num = 1024; af::dtype ty = (af::dtype)af::dtype_traits::af_type; @@ -210,6 +223,8 @@ void testGetSeed(const uintl seed0, const uintl seed1) af::setSeed(seed0); af::array in2 = af::randu(num, ty); ASSERT_EQ(af::getSeed(), seed0); + + af::setSeed(orig_seed); // Reset the seed } TYPED_TEST(Random, getSeed) diff --git a/test/rank_dense.cpp b/test/rank_dense.cpp new file mode 100644 index 0000000000..3ecf49784c --- /dev/null +++ b/test/rank_dense.cpp @@ -0,0 +1,88 @@ +/******************************************************* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; +using std::string; +using std::cout; +using std::endl; +using af::cfloat; +using af::cdouble; + +template +class Rank : public ::testing::Test +{ +}; + +typedef ::testing::Types TestTypes; +TYPED_TEST_CASE(Rank, TestTypes); + +template +void rankSmall() +{ + if (noDoubleTests()) return; + + T ha[] = {1, 4, 7, 2, 5, 8, 3, 6, 20}; + af::array a(3, 3, ha); + + ASSERT_EQ(3, (int)af::rank(a)); +} + +template +void rankBig(const int num) +{ + if (noDoubleTests()) return; + af::dtype dt = (af::dtype)af::dtype_traits::af_type; + af::array a = af::randu(num, num, dt); + ASSERT_EQ(num, (int)af::rank(a)); + + af::array b = af::randu(num, num/2, dt); + ASSERT_EQ(num/2, (int)af::rank(b)); + ASSERT_EQ(num/2, (int)af::rank(transpose(b))); +} + +template +void rankLow(const int num) +{ + if (noDoubleTests()) return; + af::dtype dt = (af::dtype)af::dtype_traits::af_type; + + af::array a = af::randu(3 * num, num, dt); + af::array b = af::randu(3 * num, num, dt); + af::array c = a + 0.2 * b; + af::array in = join(1, a, b, c); + + // The last third is just a linear combination of first and second thirds + ASSERT_EQ(2 * num, (int)af::rank(in)); +} + +TYPED_TEST(Rank, small) +{ + rankSmall(); +} + +TYPED_TEST(Rank, big) +{ + rankBig(1024); +} + +TYPED_TEST(Rank, low) +{ + rankBig(512); +}