Author: sebor
Date: Thu Jan 26 11:06:57 2006
New Revision: 372585
URL: http://svn.apache.org/viewcvs?rev=372585&view=rev
Log:
2006-01-26 Anton Pevtsov <[EMAIL PROTECTED]>
Martin Sebor <[EMAIL PROTECTED]>
* 25.transform.cpp: New test exercising lib.alg.transform.
Added:
incubator/stdcxx/trunk/tests/algorithms/25.transform.cpp (with props)
Added: incubator/stdcxx/trunk/tests/algorithms/25.transform.cpp
URL:
http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/algorithms/25.transform.cpp?rev=372585&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/algorithms/25.transform.cpp (added)
+++ incubator/stdcxx/trunk/tests/algorithms/25.transform.cpp Thu Jan 26
11:06:57 2006
@@ -0,0 +1,494 @@
+/***************************************************************************
+ *
+ * 25.transform.cpp - test exercising 25.2.3 [lib.alg.transform]
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave
+ * Software division. Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0. Unless required by
+ * applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License
+ * for the specific language governing permissions and limitations under
+ * the License.
+ *
+ **************************************************************************/
+
+#include <algorithm> // for transform
+#include <cstddef> // for size_t
+
+#include <alg_test.h>
+#include <driver.h> // for rw_test()
+
+
+_RWSTD_NAMESPACE (std) {
+
+// disable explicit instantiation for compilers (like MSVC)
+// that can't handle it
+#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
+
+template
+OutputIter<assign<base<> > >
+transform (InputIter<assign<base<> > >,
+ InputIter<assign<base<> > >,
+ OutputIter<assign<base<> > >,
+ func<assign<base<> > >);
+
+template
+OutputIter<assign<base<> > >
+transform (InputIter<assign<base<> > >,
+ InputIter<assign<base<> > >,
+ InputIter<assign<base<> > >,
+ OutputIter<assign<base<> > >,
+ binary_func<assign<base<> > >);
+
+#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
+
+} // namespace std
+
+/**************************************************************************/
+
+template <class T>
+struct incT
+{
+ // not a binary function
+ enum { binary = 0 };
+
+ // function name
+ static const char* name () { return "unary_function"; }
+
+ // dummy arguments to prevent the class from being default
+ // constructible or construtible by conversion from an int
+ incT (int /* dummy */, int /* dummy */) {
+ funcalls_ = 0;
+ }
+
+ // non-const in order to detect unwarranted assumptions
+ // in the algorithm(s)
+ T operator() (const T &x) /* non-const */ {
+ ++funcalls_;
+ T y (x);
+ y.val_ += 1;
+ return y;
+ }
+
+ static std::size_t funcalls_;
+};
+
+
+template <class T>
+struct plusT
+{
+ // binary function
+ enum { binary = 1 };
+
+ // function name
+ static const char* name () { return "binary_function"; }
+
+ // dummy arguments to prevent the class from being default
+ // constructible or construtible by conversion from an int
+ plusT (int, int) {
+ funcalls_ = 0;
+ }
+
+ // non-const in order to detect unwarranted assumptions
+ // in the algorithm(s)
+ T operator() (const T &a, const T &b) /* non-const */ {
+ ++funcalls_;
+ T x (a);
+ x.val_ = a.val_ + b.val_;
+ return x;
+ }
+
+ static std::size_t funcalls_;
+};
+
+template <class T> std::size_t incT<T>::funcalls_;
+template <class T> std::size_t plusT<T>::funcalls_;
+
+/**************************************************************************/
+
+/* extern */ int rw_opt_nloops = 32; // --nloops=#
+/* extern */ int rw_opt_no_unary_function; // --no-unary_function
+/* extern */ int rw_opt_no_binary_function; // --no-binary_function
+/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
+/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
+/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
+/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
+/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
+
+/**************************************************************************/
+
+template <class InputIterator, class Unused, class OutputIterator>
+OutputIterator
+invoke_transform (InputIterator first, InputIterator last,
+ Unused /* for compatibility with the overload below */,
+ OutputIterator dest, incT<X> fun)
+{
+ return std::transform (first, last, dest, fun);
+}
+
+template <class InputIterator1, class InputIterator2, class OutputIterator>
+OutputIterator
+invoke_transform (InputIterator1 first1, InputIterator1 last1,
+ InputIterator2 first2,
+ OutputIterator dest, plusT<X> fun)
+{
+ return std::transform (first1, last1, first2, dest, fun);
+}
+
+
+template <class T, class InputIterator1, class InputIterator2,
+ class OutputIterator, class Function>
+void test_transform (const T* ptr,
+ const InputIterator1 &it1,
+ const InputIterator2 &it2,
+ const OutputIterator &out,
+ const Function*,
+ int same_seq)
+{
+ static const char* const it1name = type_name (it1, ptr);
+ static const char* const it2name = type_name (it2, ptr);
+ static const char* const outname = type_name (out, ptr);
+ static const char* const algname = "transform";
+ static const char* const funname = Function::name ();
+ static const bool binary = Function::binary;
+
+ const std::size_t nloops = std::size_t (rw_opt_nloops);
+
+ rw_info (0, 0, 0,
+ "std::%s (%s, %2$s%{?}, %s%{;}, %s, %s)%{?}, %s%d == %s%{;}",
+ algname, it1name, binary, it2name, outname, funname,
+ same_seq, "first", same_seq, "dest");
+
+ // generate sequential values for each default constructed T
+ T::gen_ = gen_seq;
+
+ // make sure buf{1,2}[0] is dereferenceable even when (nloops == 0)
+ T* const buf1 = new T [nloops + 1];
+ T* const buf2 = new T [nloops + 1];
+ T* const buf3 = same_seq ? (same_seq == 1 ? buf1 : buf2) : new T [nloops];
+
+ const int start1_val = same_seq == 2 ? buf2 [0].val_ : buf1 [0].val_;
+ const int start2_val = same_seq == 2 ? buf1 [0].val_ : buf2 [0].val_;
+
+ for (std::size_t i = 0; i < nloops; ++i) {
+
+ T* const buf1_end = buf1 + i;
+ const T* const buf2_end = buf2 + i;
+ const T* const buf3_end = buf3 + i;
+
+ const InputIterator1 first1 = make_iter (buf1, buf1, buf1_end, it1);
+ const InputIterator1 last1 = make_iter (buf1_end, buf1, buf1_end,
it1);
+ const InputIterator2 first2 = make_iter (buf2, buf2, buf2_end, it2);
+ const OutputIterator dest = make_iter (buf3, buf3, buf3_end, out);
+
+ const Function fun (0, 0); // dummy arguments
+
+ // invoke the overload of std::transform() appropriate
+ // for this Function
+ const OutputIterator result =
+ invoke_transform (first1, last1, first2, dest, fun);
+
+ // check the returned iterator
+ bool success = result.cur_ == buf3_end;
+ rw_assert (success, 0, __LINE__,
+ "%zu. %s (%s, %2$s%{?}, %s%{;}, %s, %s)%{?}, "
+ "%s%d == %s%{;} : return val: "
+ "dest + %td, expected dest + %zu",
+ i, algname, it1name, binary, it2name, outname, funname,
+ same_seq, "first", same_seq, "dest",
+ result.cur_ - buf3, i);
+
+ if (!success)
+ break;
+
+ // check the transformation results
+ int exp_val = 0;
+ std::size_t j = 0;
+ for ( ; j < i; j++) {
+ if (0 == same_seq) {
+ exp_val = binary ?
+ start1_val + int (j) + start2_val + int (j)
+ : start1_val + int (j) + 1;
+ }
+ else {
+ exp_val = binary ?
+ start1_val + int (j)
+ + (start2_val + int (j)) * int (i - j)
+ : start1_val + int (i);
+ }
+
+ success = buf3 [j].val_ == exp_val;
+ if (!success)
+ break;
+ }
+
+ rw_assert (success, 0, __LINE__,
+ "%zu. %s (%s, %2$s%{?}, %s%{;}, %s, %s)%{?}, "
+ "%s%d == %s%{;} : error: incorrect value %d, "
+ "expected %d, position %zu",
+ i, algname, it1name, binary, it2name, outname, funname,
+ same_seq, "first", same_seq, "dest",
+ buf3 [j].val_, exp_val, j + 1);
+
+ if (!success)
+ break;
+
+ // check compexity, 25.2.3 p4
+ rw_assert (Function::funcalls_ == i, 0, __LINE__,
+ "%zu. %s (%s, %2$s%{?}, %s%{;}, %s, %s)%{?}, "
+ "%s%d == %s%{;} : complexity : %zu "
+ "applications of %5$s, expected %zu",
+ i, algname, it1name, binary, it2name, outname, funname,
+ same_seq, "first", same_seq, "dest",
+ Function::funcalls_, i);
+ }
+
+ delete[] buf1;
+ delete[] buf2;
+
+ if (0 == same_seq)
+ delete[] buf3;
+}
+
+/**************************************************************************/
+
+template <class T, class InputIterator1, class InputIterator2,
+ class OutputIterator, class Function>
+void gen_test (const T* ptr,
+ const InputIterator1 &it1,
+ const InputIterator2 &it2,
+ const OutputIterator &out,
+ const Function* pfun,
+ int tag1,
+ int tag2,
+ int tag3,
+ int same_seq)
+{
+ const InputIter<X> input_iter (0, 0, 0);
+ const OutputIter<T> output_iter (0, 0, 0);
+ const FwdIter<T> fwd_iter (0, 0, 0);
+ const BidirIter<T> bidir_iter (0, 0, 0);
+ const RandomAccessIter<X> rand_iter (0, 0, 0);
+
+ // tag1, tag2 and tag3 indicates that an iterator needs to be generated
+ // at the corresponding position by a recursive call to gen_test
+ // and other positions there the iterator will be used
+ // for all tags:
+ // 0 means that no iterator is needed here
+ // (maybe it was already generated or just not needed)
+ // 1 means that the iterator is needed at this position
+ // (first for tag1, second for tag2, etc)
+ // 2 means that the iterator is needed at this position and the
+ // same type of iterator should be used at third position
+
+ //////////////////////////////////////////////////////////////////
+ if (rw_opt_no_input_iter) {
+ if (1 == tag1 || 0 == tag1 && 1 == tag2)
+ rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
+ }
+ else {
+ if (1 == tag1) {
+ gen_test (ptr, input_iter, it2, out,
+ pfun, 0, tag2, tag3, same_seq);
+ }
+ else if (0 == tag1 && 1 == tag2) {
+ gen_test (ptr, it1, input_iter, out,
+ pfun, tag1, 0, tag3, same_seq);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////
+ if (rw_opt_no_fwd_iter) {
+ if (tag1 || !tag1 && tag2 || !tag1 && !tag2 && tag3)
+ rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
+ }
+ else {
+ if (1 == tag1) {
+ gen_test (ptr, fwd_iter, it2, out,
+ pfun, 0, tag2, tag3, same_seq);
+ }
+ else if (2 == tag1) {
+ gen_test (ptr, fwd_iter, it2, fwd_iter,
+ pfun, 0, tag2, 0, same_seq);
+ }
+ else if (0 == tag1 && 1 == tag2) {
+ gen_test (ptr, it1, fwd_iter, out,
+ pfun, tag1, 0, tag3, same_seq);
+ }
+ else if (0 == tag1 && 2 == tag2) {
+ gen_test (ptr, it1, fwd_iter, fwd_iter,
+ pfun, tag1, 0, 0, same_seq);
+ }
+ else if (0 == tag1 && 0 == tag2 && 1 == tag3) {
+ gen_test (ptr, it1, it2, fwd_iter,
+ pfun, tag1, tag2, 0, same_seq);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////
+ if (rw_opt_no_bidir_iter) {
+ if (tag1 || !tag1 && tag2 || !tag1 && !tag2 && tag3)
+ rw_note (0, __FILE__, __LINE__,
+ "BidirectionalIterator test disabled");
+ }
+ else {
+ if (1 == tag1) {
+ gen_test (ptr, bidir_iter, it2, out,
+ pfun, 0, tag2, tag3, same_seq);
+ }
+ else if (2 == tag1) {
+ gen_test (ptr, bidir_iter, it2, bidir_iter,
+ pfun, 0, tag2, 0, same_seq);
+ }
+ else if (0 == tag1 && 1 == tag2) {
+ gen_test (ptr, it1, bidir_iter, out,
+ pfun, tag1, 0, tag3, same_seq);
+ }
+ else if (0 == tag1 && 2 == tag2) {
+ gen_test (ptr, it1, bidir_iter, bidir_iter,
+ pfun, tag1, 0, 0, same_seq);
+ }
+ else if (0 == tag1 && 0 == tag2 && 1 == tag3) {
+ gen_test (ptr, it1, it2, bidir_iter,
+ pfun, tag1, tag2, 0, same_seq);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////
+ if (rw_opt_no_rnd_iter) {
+ if (tag1 || !tag1 && tag2 || !tag1 && !tag2 && tag3)
+ rw_note (0, __FILE__, __LINE__,
+ "RandomAccessIterator test disabled");
+ }
+ else {
+ if (1 == tag1) {
+ gen_test (ptr, rand_iter, it2, out,
+ pfun, 0, tag2, tag3, same_seq);
+ }
+ else if (2 == tag1) {
+ gen_test (ptr, rand_iter, it2, rand_iter,
+ pfun, 0, tag2, 0, same_seq);
+ }
+ else if (0 == tag1 && 1 == tag2) {
+ gen_test (ptr, it1, rand_iter, out,
+ pfun, tag1, 0, tag3, same_seq);
+ }
+ else if (0 == tag1 && 2 == tag2) {
+ gen_test (ptr, it1, rand_iter, rand_iter,
+ pfun, tag1, 0, 0, same_seq);
+ }
+ else if (0 == tag1 && 0 == tag2 && 1 == tag3) {
+ gen_test (ptr, it1, it2, rand_iter,
+ pfun, tag1, tag2, 0, same_seq);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////
+ if (rw_opt_no_output_iter) {
+ if (0 == tag1 && 0 == tag2 && 1 == tag3)
+ rw_note (0, __FILE__, __LINE__, "OutputIterator test disabled");
+ }
+ else {
+ if (0 == tag1 && 0 == tag2 && 1 == tag3) {
+ gen_test (ptr, it1, it2, output_iter,
+ pfun, tag1, tag2, 0, same_seq);
+ }
+ }
+
+ if (0 == tag1 && 0 == tag2 && 0 == tag3) {
+ test_transform (ptr, it1, it2, out, pfun, same_seq);
+ }
+}
+
+/**************************************************************************/
+
+static int
+run_test (int, char*[])
+{
+ const InputIter<X> input_iter (0, 0, 0);
+ const RandomAccessIter<X> rand_iter;
+ const X* const ptr = 0;
+
+ // test transform with a unary function
+ // according to 25.2.3 p5 'result may be equal to first'
+ // so it is neccessary to test this case separately
+ if (rw_opt_no_unary_function) {
+ rw_note (0, __FILE__, __LINE__,
+ "std::transform unary function test disabled");
+ }
+ else {
+ const incT<X>* const pfun = 0;
+
+ gen_test (ptr, input_iter, rand_iter, rand_iter,
+ pfun, 1, 0, 1, 0 /* result distinct from first */);
+
+ // test 25.2.3 p5 - result is equal to first
+ // set tag1 = 2 and tag3 = 0 to test all iterators at the first
+ // position and avoid generating iterators at the third pos
+ gen_test (ptr, input_iter, rand_iter, rand_iter,
+ pfun, 2, 0, 0, 1 /* result same as first */);
+ }
+
+ // test transform with a binary function
+ // according to 25.2.3 p5 'result may be equal to first1 or first2'
+ // so it is neccessary to test these cases separately
+ if (rw_opt_no_binary_function) {
+ rw_note (0, __FILE__, __LINE__,
+ "std::transform binary function test disabled");
+ }
+ else {
+ const plusT<X>* const pfun = 0;
+
+ gen_test (ptr, input_iter, rand_iter, rand_iter,
+ pfun, 1, 1, 1, 0 /* result distinct from first{1,2} */);
+
+ // test 25.2.3 p5 - result is equal to first2
+ // set tag2 = 2 and tag3 = 0 to test all iterators at the second
+ // position and avoid generating iterators at the third pos
+ gen_test (ptr, input_iter, rand_iter, rand_iter,
+ pfun, 1, 2, 0, 2 /* result same as first2 */);
+
+ // test 25.2.3 p5 - result is equal to first1
+ // set tag1 = 2 and tag3 = 0 to test all iterators at the first
+ // position and avoid generating iterators at the third pos
+ // set same_seq to 1 to indicate that first1 and dest should be
+ // the same iterators
+ gen_test (ptr, input_iter, rand_iter, rand_iter,
+ pfun, 2, 1, 0, 1 /* result same as first1 */);
+ }
+
+ return 0;
+}
+
+
+/**************************************************************************/
+
+int main (int argc, char *argv[])
+{
+ return rw_test (argc, argv, __FILE__,
+ "lib.alg.transform",
+ 0 /* no comment */, run_test,
+ "|-nloops#0 " // must be non-negative
+ "|-no-unary_function# "
+ "|-no-binary_function# "
+ "|-no-InputIterator# "
+ "|-no-OutputIterator# "
+ "|-no-ForwardIterator# "
+ "|-no-BidirectionalIterator# "
+ "|-no-RandomAccessIterator",
+ &rw_opt_nloops,
+ &rw_opt_no_unary_function,
+ &rw_opt_no_binary_function,
+ &rw_opt_no_input_iter,
+ &rw_opt_no_output_iter,
+ &rw_opt_no_fwd_iter,
+ &rw_opt_no_bidir_iter,
+ &rw_opt_no_rnd_iter);
+}
Propchange: incubator/stdcxx/trunk/tests/algorithms/25.transform.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/stdcxx/trunk/tests/algorithms/25.transform.cpp
------------------------------------------------------------------------------
svn:keywords = Id