402N/A+/***************************************************************************
402N/A+ ***************************************************************************
402N/A+ * Licensed to the Apache Software Foundation (ASF) under one or more
402N/A+ * contributor license agreements. See the NOTICE file distributed
402N/A+ * with this work for additional information regarding copyright
402N/A+ * ownership. The ASF licenses this file to you under the Apache
402N/A+ * License, Version 2.0 (the "License"); you may not use this file
402N/A+ * except in compliance with the License. You may obtain a copy of
402N/A+ * Unless required by applicable law or agreed to in writing, software
402N/A+ * distributed under the License is distributed on an "AS IS" BASIS,
402N/A+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
402N/A+ * implied. See the License for the specific language governing
402N/A+ * permissions and limitations under the License.
402N/A+ * Copyright (C) 2007-2008 Rogue Wave Software, Inc.
402N/A+ ***************************************************************************
402N/A+ ***************************************************************************
402N/A+ * 2008-06-04 Travis Vitek <vitek@roguewave.com>
402N/A+ * loop body if the slice is reset but has one element.
402N/A+ * (gslice_array<>::operator*=): Ditto.
402N/A+ * (gslice_array<>::operator/=): Ditto.
402N/A+ * (gslice_array<>::operator+=): Ditto.
402N/A+ * (gslice_array<>::operator-=): Ditto.
402N/A+ * (gslice_array<>::operator%=): Ditto.
402N/A+ * (gslice_array<>::operator^=): Ditto.
402N/A+ * (gslice_array<>::operator&=): Ditto.
402N/A+ * (gslice_array<>::operator|=): Ditto.
402N/A+ * (gslice_array<>::operator<<=): Ditto.
402N/A+ * (gslice_array<>::operator>>=): Ditto.
402N/A+ * (valarray<>::ctor): Ditto.
402N/A+ * (valarray<>::operator=): Ditto.
402N/A+ * for slice computed assignment operators.
402N/A+ ***************************************************************************
402N/A+ **************************************************************************/
402N/A+#include <cstdlib> // for free(), strtod(), size_t
402N/A+#include <valarray> // for indirect_array, valarray
402N/A+/**************************************************************************/
402N/A+// returns an array of size elements of type T constructed from a string
402N/A+// of comma-separated values
402N/A+static std::valarray<std::size_t>
402N/A+make_array (const char *s)
402N/A+ std::size_t buf [256];
402N/A+ unsigned long val = std::strtoul (s, &end, 10);
402N/A+ RW_ASSERT ('\0' == *end || ',' == *end || '@' == *end);
402N/A+ buf [i++] = std::size_t (val);
402N/A+ const std::size_t n = buf [i-1];
402N/A+ for (std::size_t j = 0; j < (val - 1); ++j)
402N/A+ return std::valarray<std::size_t>(buf, i);
402N/A+/**************************************************************************/
402N/A+ void (std::gslice_array<std::size_t>::*op_assign)(const std::valarray<std::size_t>&) const,
402N/A+ const char *tname, // T's type name
402N/A+ const char *opname, // which assignment operator
402N/A+ int line, // test case line number
402N/A+ std::size_t start, // start index of slice
402N/A+ const char *length_str,// number of strides
402N/A+ const char *stride_str,// length of stride
402N/A+ const char *lhs_str, // original array
402N/A+ const char *rhs_str, // right hand side of assignment
402N/A+ const char *res_str) // result of assignment
402N/A+ // create an array of values from the string length_str
402N/A+ // representing the length array of the slice
402N/A+ const std::valarray<std::size_t> lengths (make_array (length_str));
402N/A+ // create an array of values from the string stride_str
402N/A+ // representing the stride array of the slice
402N/A+ const std::valarray<std::size_t> strides (make_array (stride_str));
402N/A+ // valarray(s)[gslice(start, length, stride)] op= rhs
402N/A+ const std::gslice gsl (start, lengths, strides);
402N/A+ // create an array of values from the string lhs_str
402N/A+ // representing the left-hand side array before slicing
402N/A+ /* const */ std::valarray<std::size_t> lhs_va (make_array (lhs_str));
402N/A+ // create an array of values from the string rhs_str
402N/A+ // representing the right-hand side argument of the assignment
402N/A+ const std::valarray<std::size_t> rhs_va (make_array (rhs_str));
402N/A+ // create an array of values from the string res_str
402N/A+ // representing the result of the assignment
402N/A+ const std::valarray<std::size_t> res_va (make_array (res_str));
402N/A+ // take a gslice of lhs_va, this is the lhs of the assignment
402N/A+ const std::gslice_array<std::size_t>& lhs_ga = lhs_va [gsl];
402N/A+ // format the name of the function call to be used in diagnostic
402N/A+ rw_asnprintf (&fname, &size,
402N/A+ "gslice_array<%s>(%s) %s std::valarray<%1$s>(%s)",
402N/A+ tname, lhs_str, opname, rhs_str);
402N/A+ // invoke the assignment operator through the member pointer
402N/A+ (lhs_ga.*op_assign)(rhs_va);
402N/A+ // verify the element values
402N/A+ if (!rw_assert (lhs_va [i] == res_va [i], 0, line,
402N/A+ "line %d. %s: element at index %zu == %zu, got %zu",
402N/A+ __LINE__, fname, i, res_va [i], lhs_va [i]))
402N/A+/**************************************************************************/
402N/A+#define OP(start, lengths, strides, lhs, rhs, res) \
402N/A+ test_op_assign ((T*)0, op, tname, opname, __LINE__, start, lengths, strides, lhs, rhs, res)
402N/A+void test_mul_assign (const T*, const char *tname, const char *opname)
402N/A+ rw_info (0, 0, __LINE__,
402N/A+ "std::gslice_array<%s>::operator%s (const std::valarray<%1$s>&)",
402N/A+ void (std::gslice_array<T>::*op)(const std::valarray<T>&) const =
402N/A+ &std::gslice_array<T>::operator*=;
402N/A+ // | | +- strides +- rhs
402N/A+ // | | | +- lhs | +- expect
402N/A+ OP (0, "", "", "1@4", "2", "1@4");
402N/A+ OP (0, "0", "1", "1@4", "2", "1@4");
402N/A+ OP (2, "0", "9", "1@4", "2", "1@4");
402N/A+ OP (3, "0", "2", "1@4", "7", "1@4");
402N/A+ OP (0, "1", "1", "1@4", "5", "5,1@3");
402N/A+ OP (2, "1", "1", "1@4", "5", "1,1,5,1");
402N/A+ OP (1, "2", "1", "1@4", "3,4", "1,3,4,1");
402N/A+ OP (1, "1", "2", "2@4", "2", "2,4,2,2");
402N/A+ OP (0, "2,1", "2,3", "2@4", "3,7", "6,2,14,2");
402N/A+ OP (1, "1,0", "2,3", "3@4", "3", "3,9,3,3");
402N/A+/**************************************************************************/
402N/A+void test_div_assign (const T*, const char *tname, const char *opname)
402N/A+ rw_info (0, 0, __LINE__,
402N/A+ "std::gslice_array<%s>::operator%s (const std::valarray<%1$s>&)",
402N/A+ void (std::gslice_array<T>::*op)(const std::valarray<T>&) const =
402N/A+ &std::gslice_array<T>::operator/=;
402N/A+ OP (0, "", "", "1@4", "2", "1@4");
402N/A+ OP (0, "0", "1", "1@4", "2", "1@4");
402N/A+ OP (2, "0", "9", "1@4", "2", "1@4");
402N/A+ OP (3, "0", "2", "1@4", "7", "1@4");
402N/A+ OP (0, "1", "1", "10@4", "5", "2,10@3");
402N/A+ OP (2, "1", "1", "12@4", "5", "12,12,2,12");
402N/A+ OP (1, "2", "1", "12@4", "3,4", "12,4,3,12");
402N/A+ OP (1, "1", "2", "6@4", "2", "6,3,6,6");
402N/A+ OP (0, "2,1", "2,3", "42@4", "3,7", "14,42,6,42");
402N/A+ OP (1, "1,0", "2,3", "3@4", "3", "3,1,3,3");
402N/A+/**************************************************************************/
402N/A+void test_mod_assign (const T*, const char *tname, const char *opname)
402N/A+ rw_info (0, 0, __LINE__,
402N/A+ "std::gslice_array<%s>::operator%s (const std::valarray<%1$s>&)",
402N/A+ void (std::gslice_array<T>::*op)(const std::valarray<T>&) const =
402N/A+ &std::gslice_array<T>::operator%=;
402N/A+ OP (0, "", "", "1@4", "2", "1@4");
402N/A+ OP (0, "0", "1", "1@4", "2", "1@4");
402N/A+ OP (2, "0", "9", "1@4", "2", "1@4");
402N/A+ OP (3, "0", "2", "1@4", "7", "1@4");
402N/A+ OP (0, "1", "1", "10@4", "5", "0,10@3");
402N/A+ OP (2, "1", "1", "12@4", "5", "12,12,2,12");
402N/A+ OP (1, "2", "1", "12@4", "3,4", "12,0,0,12");
402N/A+ OP (1, "1", "2", "7@4", "2", "7,1,7,7");
402N/A+ OP (0, "2,1", "2,3", "14@4", "3,7", "2,14,0,14");
402N/A+ OP (1, "1,0", "2,3", "3@4", "3", "3,0,3,3");
402N/A+/**************************************************************************/
402N/A+void test_add_assign (const T*, const char *tname, const char *opname)
402N/A+ rw_info (0, 0, __LINE__,
402N/A+ "std::valarray<%s>::operator%s (const std::valarray<%1$s>&)",
402N/A+ void (std::gslice_array<T>::*op)(const std::valarray<T>&) const =
402N/A+ &std::gslice_array<T>::operator+=;
402N/A+ OP (0, "", "", "1@4", "2", "1@4");
402N/A+ OP (0, "0", "1", "1@4", "2", "1@4");
402N/A+ OP (2, "0", "9", "1@4", "2", "1@4");
402N/A+ OP (3, "0", "2", "1@4", "7", "1@4");
402N/A+ OP (0, "1", "1", "1@4", "5", "6,1@3");
402N/A+ OP (2, "1", "1", "2@4", "5", "2,2,7,2");
402N/A+ OP (1, "2", "1", "3@4", "3,4", "3,6,7,3");
402N/A+ OP (1, "1", "2", "7@4", "2", "7,9,7,7");
402N/A+ OP (0, "2,1", "2,3", "1@4", "3,7", "4,1,8,1");
402N/A+ OP (1, "1,0", "2,3", "3@4", "3", "3,6,3,3");
402N/A+/**************************************************************************/
402N/A+void test_sub_assign (const T*, const char *tname, const char *opname)
402N/A+ rw_info (0, 0, __LINE__,
402N/A+ "std::gslice_array<%s>::operator%s (const std::valarray<%1$s>&)",
402N/A+ void (std::gslice_array<T>::*op)(const std::valarray<T>&) const =
402N/A+ &std::gslice_array<T>::operator-=;
402N/A+ OP (0, "", "", "1@4", "2", "1@4");
402N/A+ OP (0, "0", "1", "1@4", "2", "1@4");
402N/A+ OP (2, "0", "9", "1@4", "2", "1@4");
402N/A+ OP (3, "0", "2", "1@4", "7", "1@4");
402N/A+ OP (0, "1", "1", "9@4", "5", "4,9@3");
402N/A+ OP (2, "1", "1", "7@4", "5", "7,7,2,7");
402N/A+ OP (1, "2", "1", "3@4", "3,2", "3,0,1,3");
402N/A+ OP (1, "1", "2", "7@4", "2", "7,5,7,7");
402N/A+ OP (0, "2,1", "2,3", "7@4", "3,7", "4,7,0,7");
402N/A+ OP (1, "1,0", "2,3", "3@4", "3", "3,0,3,3");
402N/A+/**************************************************************************/
402N/A+void test_xor_assign (const T*, const char *tname, const char *opname)
402N/A+ rw_info (0, 0, __LINE__,
402N/A+ "std::gslice_array<%s>::operator%s (const std::valarray<%1$s>&)",
402N/A+ void (std::gslice_array<T>::*op)(const std::valarray<T>&) const =
402N/A+ &std::gslice_array<T>::operator^=;
402N/A+ OP (0, "", "", "1@4", "2", "1@4");
402N/A+ OP (0, "0", "1", "1@4", "2", "1@4");
402N/A+ OP (2, "0", "9", "1@4", "2", "1@4");
402N/A+ OP (3, "0", "2", "1@4", "7", "1@4");
402N/A+ OP (0, "1", "1", "9@4", "5", "12,9@3");
402N/A+ OP (2, "1", "1", "7@4", "5", "7,7,2,7");
402N/A+ OP (1, "2", "1", "3@4", "3,4", "3,0,7,3");
402N/A+ OP (1, "1", "2", "7@4", "2", "7,5,7,7");
402N/A+ OP (0, "2,1", "2,3", "7@4", "3,7", "4,7,0,7");
402N/A+ OP (1, "1,0", "2,3", "3@4", "3", "3,0,3,3");
402N/A+/**************************************************************************/
402N/A+void test_and_assign (const T*, const char *tname, const char *opname)
402N/A+ rw_info (0, 0, __LINE__,
402N/A+ "std::valarray<%s>::operator%s (const std::valarray<%1$s>&)",
402N/A+ void (std::gslice_array<T>::*op)(const std::valarray<T>&) const =
402N/A+ &std::gslice_array<T>::operator&=;
402N/A+ OP (0, "", "", "1@4", "2", "1@4");
402N/A+ OP (0, "0", "1", "1@4", "2", "1@4");
402N/A+ OP (2, "0", "9", "1@4", "2", "1@4");
402N/A+ OP (3, "0", "2", "1@4", "7", "1@4");
402N/A+ OP (0, "1", "1", "9@4", "5", "1,9@3");
402N/A+ OP (2, "1", "1", "7@4", "5", "7,7,5,7");
402N/A+ OP (1, "2", "1", "3@4", "3,4", "3,3,0,3");
402N/A+ OP (1, "1", "2", "7@4", "2", "7,2,7,7");
402N/A+ OP (0, "2,1", "2,3", "7@4", "3,2", "3,7,2,7");
402N/A+ OP (1, "1,0", "2,3", "3@4", "1", "3,1,3,3");
402N/A+/**************************************************************************/
402N/A+void test_or_assign (const T*, const char *tname, const char *opname)
402N/A+ rw_info (0, 0, __LINE__,
402N/A+ "std::gslice_array<%s>::operator%s (const std::valarray<%1$s>&)",
402N/A+ void (std::gslice_array<T>::*op)(const std::valarray<T>&) const =
402N/A+ &std::gslice_array<T>::operator|=;
402N/A+ OP (0, "", "", "1@4", "2", "1@4");
402N/A+ OP (0, "0", "1", "1@4", "2", "1@4");
402N/A+ OP (2, "0", "9", "1@4", "2", "1@4");
402N/A+ OP (3, "0", "2", "1@4", "7", "1@4");
402N/A+ OP (0, "1", "1", "9@4", "5", "13,9@3");
402N/A+ OP (2, "1", "1", "7@4", "5", "7,7,7,7");
402N/A+ OP (1, "2", "1", "3@4", "3,4", "3,3,7,3");
402N/A+ OP (1, "1", "2", "7@4", "2", "7,7,7,7");
402N/A+ OP (0, "2,1", "2,3", "4@4", "3,7", "7,4,7,4");
402N/A+ OP (1, "1,0", "2,3", "3@4", "4", "3,7,3,3");
402N/A+/**************************************************************************/
402N/A+void test_shl_assign (const T*, const char *tname, const char *opname)
402N/A+ rw_info (0, 0, __LINE__,
402N/A+ "std::gslice_array<%s>::operator%s (const std::valarray<%1$s>&)",
402N/A+ void (std::gslice_array<T>::*op)(const std::valarray<T>&) =
402N/A+ &std::gslice_array<T>::operator<<=;
402N/A+ OP (0, "", "", "1@4", "2", "1@4");
402N/A+ OP (0, "0", "1", "1@4", "2", "1@4");
402N/A+ OP (2, "0", "9", "1@4", "2", "1@4");
402N/A+ OP (3, "0", "2", "1@4", "7", "1@4");
402N/A+ OP (0, "1", "1", "1@4", "1", "2,1@3");
402N/A+ OP (2, "1", "1", "2@4", "1", "2,2,4,2");
402N/A+ OP (1, "2", "1", "1@4", "3,4", "1,4,8,1");
402N/A+ OP (1, "1", "2", "3@4", "2", "3,12,3,3");
402N/A+ OP (0, "2,1", "2,3", "1@4", "3,2", "8,1,4,1");
402N/A+ OP (1, "1,0", "2,3", "5@4", "3", "5,20,5,5");
402N/A+/**************************************************************************/
402N/A+void test_shr_assign (const T*, const char *tname, const char *opname)
402N/A+ rw_info (0, 0, __LINE__,
402N/A+ "std::gslice_array<%s>::operator%s (const std::valarray<%1$s>&)",
402N/A+ void (std::gslice_array<T>::*op)(const std::valarray<T>&) const =
402N/A+ &std::gslice_array<T>::operator>>=;
402N/A+ OP (0, "", "", "1@4", "2", "1@4");
402N/A+ OP (0, "0", "1", "1@4", "2", "1@4");
402N/A+ OP (2, "0", "9", "1@4", "2", "1@4");
402N/A+ OP (3, "0", "2", "1@4", "7", "1@4");
402N/A+ OP (0, "1", "1", "1@4", "1", "0,1@3");
402N/A+ OP (2, "1", "1", "2@4", "1", "2,2,1,2");
402N/A+ OP (1, "2", "1", "9@4", "3,4", "9,1,0,9");
402N/A+ OP (1, "1", "2", "9@4", "2", "9,2,9,9");
402N/A+ OP (0, "2,1", "2,3", "14@4", "3,2", "1,14,3,14");
402N/A+ OP (1, "1,0", "2,3", "5@4", "3", "5,0,5,5");
402N/A+/**************************************************************************/
402N/A+static int opt_assign [n_assign_ops];
402N/A+void test_op_assign (const T*, const char *tname)
402N/A+ const std::size_t nassigns = sizeof opt_assign / sizeof *opt_assign;
402N/A+ for (std::size_t i = 0; i != nassigns; ++i) {
402N/A+ if (0 < opt_assign [i]) {
402N/A+ for (std::size_t j = 0; j != nassigns; ++j) {
402N/A+ if (0 == opt_assign [j])
402N/A+ if (rw_note (0 <= opt_assign [inx_mul_assign], 0, __LINE__,
402N/A+ "tests of operator*= disabled"))
402N/A+ test_mul_assign ((const T*)0, tname, "*=");
402N/A+ if (rw_note (0 <= opt_assign [inx_div_assign], 0, __LINE__,
402N/A+ "tests of operator/= disabled"))
402N/A+ test_div_assign ((const T*)0, tname, "/=");
402N/A+ if (rw_note (0 <= opt_assign [inx_mod_assign], 0, __LINE__,
402N/A+ "tests of operator%= disabled"))
402N/A+ test_mod_assign ((const T*)0, tname, "%=");
402N/A+ if (rw_note (0 <= opt_assign [inx_add_assign], 0, __LINE__,
402N/A+ "tests of operator+= disabled"))
402N/A+ test_add_assign ((const T*)0, tname, "+=");
402N/A+ if (rw_note (0 <= opt_assign [inx_sub_assign], 0, __LINE__,
402N/A+ "tests of operator-= disabled"))
402N/A+ test_sub_assign ((const T*)0, tname, "-=");
402N/A+ if (rw_note (0 <= opt_assign [inx_xor_assign], 0, __LINE__,
402N/A+ "tests of operator^= disabled"))
402N/A+ test_xor_assign ((const T*)0, tname, "^=");
402N/A+ if (rw_note (0 <= opt_assign [inx_and_assign], 0, __LINE__,
402N/A+ "tests of operator&= disabled"))
402N/A+ test_and_assign ((const T*)0, tname, "&=");
402N/A+ if (rw_note (0 <= opt_assign [inx_or_assign], 0, __LINE__,
402N/A+ "tests of operator|= disabled"))
402N/A+ test_or_assign ((const T*)0, tname, "|=");
402N/A+ if (rw_note (0 <= opt_assign [inx_shl_assign], 0, __LINE__,
402N/A+ "tests of operator<<= disabled"))
402N/A+ test_shr_assign ((const T*)0, tname, "<<=");
402N/A+ if (rw_note (0 <= opt_assign [inx_shr_assign], 0, __LINE__,
402N/A+ "tests of operator>>= disabled"))
402N/A+ test_shr_assign ((const T*)0, tname, ">>=");
402N/A+/**************************************************************************/
402N/A+#define TEST(T) test_op_assign ((const T*)0, #T)
402N/A+//#if 0x04020100 >= _RWSTD_VER
402N/A+// // test fails to compile with stdcxx 4.2.1 and prior due to
402N/A+// rw_warn (0, 0, __LINE__,
402N/A+// "test of UserClass disabled in stdcxx 4.2.0 and prior "
402N/A+// "due to STDCXX-512");
402N/A+//#else // stdcxx >= 4.2.1
402N/A+//#endif // stdcxx version
402N/A+/**************************************************************************/
402N/A+int main (int argc, char *argv[])
402N/A+ return rw_test (argc, argv, __FILE__,
402N/A+ opt_assign + inx_mul_assign,
402N/A+ opt_assign + inx_div_assign,
402N/A+ opt_assign + inx_mod_assign,
402N/A+ opt_assign + inx_add_assign,
402N/A+ opt_assign + inx_sub_assign,
402N/A+ opt_assign + inx_xor_assign,
402N/A+ opt_assign + inx_and_assign,
402N/A+ opt_assign + inx_or_assign,
402N/A+ opt_assign + inx_shl_assign,
402N/A+ opt_assign + inx_shr_assign,
402N/A+ (void*)0 /* sentinel */);