Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r80442 - sandbox/variadic_templates/sandbox/array_dyn
From: cppljevans_at_[hidden]
Date: 2012-09-08 06:57:16


Author: cppljevans
Date: 2012-09-08 06:57:15 EDT (Sat, 08 Sep 2012)
New Revision: 80442
URL: http://svn.boost.org/trac/boost/changeset/80442

Log:
Added reduce_axis header and test driver.
Slight mods to other changed files.

Added:
   sandbox/variadic_templates/sandbox/array_dyn/reduce_axis.cpp (contents, props changed)
   sandbox/variadic_templates/sandbox/array_dyn/reduce_axis.hpp (contents, props changed)
Text files modified:
   sandbox/variadic_templates/sandbox/array_dyn/array_dyn.hpp | 4 +
   sandbox/variadic_templates/sandbox/array_dyn/box_domain.hpp | 114 ++++++++++++++++++++++++++++++++++++---
   2 files changed, 109 insertions(+), 9 deletions(-)

Modified: sandbox/variadic_templates/sandbox/array_dyn/array_dyn.hpp
==============================================================================
--- sandbox/variadic_templates/sandbox/array_dyn/array_dyn.hpp (original)
+++ sandbox/variadic_templates/sandbox/array_dyn/array_dyn.hpp 2012-09-08 06:57:15 EDT (Sat, 08 Sep 2012)
@@ -34,7 +34,11 @@
       super_t::
     index_t
     ;
+ typedef
       std::vector<T>
+ data_t
+ ;
+ data_t
     my_data
     /**@brief
      * data in the array.

Modified: sandbox/variadic_templates/sandbox/array_dyn/box_domain.hpp
==============================================================================
--- sandbox/variadic_templates/sandbox/array_dyn/box_domain.hpp (original)
+++ sandbox/variadic_templates/sandbox/array_dyn/box_domain.hpp 2012-09-08 06:57:15 EDT (Sat, 08 Sep 2012)
@@ -54,20 +54,33 @@
       std::vector<index_t>
     strides_t
     ;
+ typedef
+ std::vector<index_t>
+ indices_t
+ ;
+ typedef
+ std::vector<index_t>
+ shape_t
+ ;
       strides_t
     my_strides
     /**@brief
      * The strides for each axis in a multidimensional array.
      */
     ;
- int const
+ dirs const
     my_dir
     /**@brief
- * Either 0 or 1.
- * If 1, then my_strides[i]/my_strides[i+1] > 0
+ * Either dir_fwd or dir_rev.
+ * If dir_rev, then my_strides[i]/my_strides[i+1] > 0
      * Otherwise, my_strides[i+1]/my_strides[i] > 0
      */
     ;
+
+ ~box_domain()
+ {
+ //std::cout<<__FILE__<<":"<<__LINE__<<"~box_domain"<<":this="<<(void*)this<<"\n";
+ }
       template
       < typename InpIter
       , typename OutIter
@@ -82,6 +95,7 @@
        * Helper function for init_strides( Sizes...)
        */
     {
+ //std::cout<<__FILE__<<":"<<__LINE__<<"box_domain:init_iter_strides"<<":this="<<(void*)this<<"\n";
         *strides=1;
         return
         std::partial_sum
@@ -141,6 +155,11 @@
         return result;
     }
     
+ dirs
+ dir()const
+ {
+ return dirs(my_dir);
+ }
       index_t
     rank()const
     {
@@ -150,7 +169,7 @@
       index_t
     stride(index_t Index)const
       /**@brief
- * size of Index-th axis.
+ * stride of Index-th axis.
        */
     {
         return my_strides[Index+my_dir];
@@ -158,6 +177,9 @@
     
       index_t
     size(index_t Index)const
+ /**@brief
+ * size of Index-th axis
+ */
     {
         index_t const greater=(my_dir+1)%2;
         return my_strides[Index+greater]/my_strides[Index+my_dir];
@@ -204,7 +226,7 @@
           );
     }
     
- std::vector<index_t>
+ indices_t
     indices_at_offset
       ( index_t offset
       )const
@@ -212,14 +234,14 @@
        * Inverse of offset_at_indices
        */
     {
- std::vector<index_t> indices(rank());
+ indices_t indices_v(rank());
         if(my_dir==dir_fwd)
         {
             indices_at_offset
             ( offset
             , my_strides.rbegin()+1
             , my_strides.rend()
- , indices.rbegin()
+ , indices_v.rbegin()
             );
         }
         else
@@ -228,10 +250,65 @@
             ( offset
             , my_strides.begin()+1
             , my_strides.end()
- , indices.begin()
+ , indices_v.begin()
             );
         }
- return indices;
+ return indices_v;
+ }
+
+ template
+ < typename StrideIter
+ , typename ShapeIter
+ >
+ static
+ void
+ iter_shape
+ ( StrideIter beg_stride
+ , StrideIter end_stride
+ , ShapeIter beg_shape
+ )
+ {
+ for(; beg_stride!=end_stride; ++beg_stride,++beg_shape)
+ {
+ *beg_shape=(*(beg_stride+1))/(*beg_stride);
+ }
+ }
+ shape_t
+ shape
+ (
+ )const
+ /**@brief
+ * Returns shape(i.e. lengths of axes).
+ */
+ {
+ shape_t shape_v(rank());
+ if(my_dir==dir_fwd)
+ {
+ iter_shape
+ ( my_strides.begin()
+ , my_strides.end()
+ , shape_v.begin()
+ );
+ }
+ else
+ {
+ typedef typename
+ strides_t::const_iterator
+ fwd_iter;
+ typedef
+ std::reverse_iterator<fwd_iter>
+ rev_iter;
+ rev_iter
+ rbeg(my_strides.end());
+ rev_iter
+ rend(my_strides.begin());
+ iter_shape
+ ( rbeg
+ , rend
+ , shape_v.rbegin()
+ );
+ }
+ return shape_v;
     }
     
   //[Template interface:
@@ -246,6 +323,25 @@
     , my_dir(a_dir)
     {
         init_strides( a_sizes);
+ #if 0
+ std::cout<<__FILE__<<":"<<__LINE__
+ <<":a_sizes="<<a_sizes
+ <<":my_strides="<<my_strides
+ <<"\n";
+ #endif
+ }
+
+ box_domain( box_domain const& a_self)
+ : my_strides( a_self.my_strides)
+ , my_dir(a_self.my_dir)
+ {
+ #if 0
+ std::cout<<__FILE__<<":"<<__LINE__
+ <<":my_strides="<<my_strides
+ <<":my_dir="<<my_strides
+ <<":this="<<(void*)this
+ <<"\n";
+ #endif
     }
     
       template

Added: sandbox/variadic_templates/sandbox/array_dyn/reduce_axis.cpp
==============================================================================
--- (empty file)
+++ sandbox/variadic_templates/sandbox/array_dyn/reduce_axis.cpp 2012-09-08 06:57:15 EDT (Sat, 08 Sep 2012)
@@ -0,0 +1,205 @@
+//Purpose:
+// Demo reducing along 1 axis of an array_dyn.
+//
+#include <boost/iostreams/utility/indent_scoped_ostreambuf.hpp>
+#include <vector>
+#include <algorithm>//for_each
+#include "reduce_axis.hpp"
+
+ template<typename Elem>
+ std::ostream&
+operator<<
+ ( std::ostream&sout
+ , std::vector<Elem>const&vec
+ )
+ {
+ sout<<"{ ";
+ for(unsigned i=0; i< vec.size(); ++i)
+ {
+ if(0<i)sout<<", ";
+ sout<<vec[i];
+ }
+ sout<<"}";
+ return sout;
+ }
+
+struct indent_scope
+{
+ indent_scope()
+ {
+ std::cout<<indent_buf_in;
+ }
+ ~indent_scope()
+ {
+ std::cout<<indent_buf_out;
+ }
+};
+
+ template
+ < typename Value
+ >
+struct reduce_add_one
+/**@brief
+ * add values.
+ */
+{
+ Value&
+ my_value
+ ;
+ reduce_add_one
+ ( Value&a_value
+ )
+ : my_value
+ ( a_value
+ )
+ {}
+ Value
+ operator()(Value operand)
+ {
+ my_value+=operand;
+ return my_value;
+ }
+};
+ template
+ < typename Value
+ >
+struct reduce_var_one
+/**@brief
+ * sum square of deviation from a mean.
+ */
+{
+ Value&
+ my_value
+ //result value
+ ;
+ Value const
+ my_mean
+ //the mean
+ ;
+ reduce_var_one
+ ( Value&a_value//sum of square of devitation from mean
+ , Value a_mean=0
+ )
+ : my_value
+ ( a_value
+ )
+ , my_mean
+ ( a_mean
+ )
+ {}
+ Value
+ operator()(Value operand)
+ {
+ Value
+ deviation=operand-my_mean;
+ my_value+=deviation*deviation;
+ return my_value;
+ }
+};
+struct reducer_variance
+{
+ template
+ < typename Iter
+ >
+ typename Iter::value_type
+ operator()
+ ( Iter beg
+ , Iter end
+ )const
+ /**@brief
+ * return value == variance of data in sample, *beg ... *(end-1).
+ */
+ {
+ typedef
+ typename Iter::value_type
+ val_t
+ ;
+ val_t
+ mean_v=0
+ ;
+ reduce_add_one<val_t>
+ reduce_add_v(mean_v)
+ ;
+ std::for_each
+ ( beg
+ , end
+ , reduce_add_v
+ );
+ auto
+ d=beg.distance(end);
+ mean_v=mean_v/d
+ //mean_v = mean of data in *beg ... *(end-1)
+ ;
+ val_t
+ var_v;
+ reduce_var_one<val_t>
+ reduce_var_v(var_v,mean_v)
+ ;
+ std::for_each
+ ( beg
+ , end
+ , reduce_var_v
+ );
+ var_v=var_v/d
+ //var_v = variance of data in *beg ... *(end-1)
+ ;
+ return var_v;
+ }
+};
+
+int main(void)
+{
+ ::boost::iostreams::indent_scoped_ostreambuf<> indent_cout(std::cout);
+ std::cout<<"*************************\n";
+ dirs const dir_op=dir_rev;
+ std::cout<<"dir_op="<<dir_op<<"\n";
+ typedef double val_t;
+ typedef array_dyn<val_t> array_t;
+ typedef array_t::index_t index_t;
+ std::vector<index_t> sample_shape({2,3,4});
+ std::cout<<"sample_shape="<<sample_shape<<"\n";
+ array_t sample_data(dir_op,sample_shape);
+ unsigned const sample_size=sample_data.my_data.size();
+ std::cout<<"my_data.size()="<<sample_size<<"\n";
+ unsigned const value0=1000;
+ for( unsigned i=0; i<sample_size; ++i)
+ {
+ sample_data.my_data[i]=value0+i;
+ }
+ unsigned const rank=sample_data.rank();
+ std::cout<<"rank="<<rank<<"\n";
+ std::cout<<"size()="<<sample_data.size()<<"\n";
+ for(unsigned i=0;i<rank;++i)
+ {
+ std::cout<<"stride("<<i<<")="<<sample_data.stride(i)<<"\n";
+ std::cout<<" size("<<i<<")="<<sample_data.size(i)<<"\n";
+ }
+ #if 1
+ std::cout<<"sample_data=\n";
+ std::cout<<sample_data<<".\n";
+ #endif
+ std::cout<<":reducer_variance for each axis:\n";
+ {
+ indent_scope is;
+ for(unsigned oper_axis=0; oper_axis<rank; ++oper_axis)
+ {
+ std::cout<<":oper_axis="<<oper_axis<<"\n";
+ {
+ indent_scope is;
+ array_t
+ arr_reduce
+ ( reduce_axis
+ < reducer_variance const&
+ >
+ ( reducer_variance()
+ , sample_data
+ , oper_axis
+ )
+ );
+ std::cout<<"arr_reduce=\n";
+ std::cout<<arr_reduce<<".\n";
+ }
+ }//exit for(mean_axis...)
+ }
+ return 0;
+}

Added: sandbox/variadic_templates/sandbox/array_dyn/reduce_axis.hpp
==============================================================================
--- (empty file)
+++ sandbox/variadic_templates/sandbox/array_dyn/reduce_axis.hpp 2012-09-08 06:57:15 EDT (Sat, 08 Sep 2012)
@@ -0,0 +1,174 @@
+#ifndef REDUCE_AXIS_HPP_INCLUDED
+#define REDUCE_AXIS_HPP_INCLUDED
+// (C) Copyright Larry Evans 2012.
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//====================================================================
+struct loop
+/**@brief
+ * loop variables for some axis in array.
+ */
+{
+ unsigned offset;//offset in array from start of axis
+ unsigned stride;//increment to offset
+ unsigned limit;//limit to offset
+ loop()
+ : offset(0)
+ , stride(0)
+ , limit(0)
+ {}
+};
+
+ template
+ < typename Iter
+ >
+struct iter_stride
+: Iter
+{
+ int const
+ my_stride
+ ;
+ int
+ stride()const
+ {
+ return my_stride;
+ }
+ iter_stride
+ ( Iter a_iter
+ , int a_stride=1
+ )
+ : Iter(a_iter)
+ , my_stride(a_stride)
+ {}
+ typedef
+ typename Iter::difference_type
+ difference_type
+ ;
+ difference_type
+ distance
+ ( iter_stride const& last
+ )
+ {
+ difference_type d=std::distance(*this,last);
+ d=d/my_stride;
+ return d;
+ }
+
+ Iter& operator++()
+ {
+ this->operator+=(my_stride);
+ return *this;
+ }
+};
+
+#include <cassert>
+#include "array_dyn.hpp"
+
+ template
+ < typename Reducer
+ , typename Value
+ >
+ array_dyn<Value>
+reduce_axis
+ ( Reducer a_reducer
+ , array_dyn<Value>const& a_source
+ , unsigned oper_axis=0
+ )
+ /**@brief
+ * Apply a_reducer to axis, oper_axis, of a_source,
+ * producing another array_dyn, a_target, where
+ * a_target.size(oper_axis)==1, and that single
+ * value is the result of the reduction on a_source.
+ * This does, essentially, what the apl reduce
+ * statement:
+ * operator(a_reducer)/[oper_axis] a_source
+ * would do, where operator(a_reducer) is the
+ * operation which a_reducer applies along the oper_axis.
+ * See:
+ * http://aplwiki.com/LearnApl/AplOperators#Reduce_and_scan
+ */
+{
+ assert(a_source.my_dir == dir_rev);
+ unsigned const rank=a_source.rank();
+ enum{outer,oper,inner};
+ std::vector<loop> loops(inner+1);
+ if(oper_axis==0)
+ {
+ loops[outer].stride=1;
+ loops[outer].limit =1;
+ }
+ else
+ {
+ loops[outer].stride=a_source.stride(oper_axis-1);
+ loops[outer].limit =a_source.size ();
+ }
+ loops[oper ].stride=a_source.stride(oper_axis);
+ loops[oper ].limit =a_source.size (oper_axis)*loops[oper].stride;
+ loops[inner].stride=a_source.stride(rank-1 );
+ loops[inner].limit =a_source.stride(oper_axis);
+ auto
+ shape_target=a_source.shape()
+ ;
+ shape_target[oper_axis]=1;
+ typedef
+ Value
+ val_t
+ ;
+ typedef
+ array_dyn<val_t>
+ array_t
+ ;
+ array_t
+ a_target(a_source.dir(),shape_target)
+ ;
+ unsigned offset_target=0;
+ for
+ ( loops[outer].offset = 0
+ ; loops[outer].offset < loops[outer].limit
+ ; loops[outer].offset+= loops[outer].stride
+ )
+ {
+ for
+ ( loops[inner].offset = 0
+ ; loops[inner].offset < loops[inner].limit
+ ; loops[inner].offset+= loops[inner].stride
+ , ++offset_target
+ )
+ {
+ unsigned const offset_in_out
+ = loops[outer].offset
+ + loops[inner].offset
+ ;
+ typedef typename
+ array_t::data_t::const_iterator
+ iter_base_t
+ ;
+ typedef
+ iter_stride<iter_base_t>
+ iter_t
+ ;
+ iter_t
+ beg_stride
+ ( a_source.my_data.begin()+offset_in_out
+ , loops[oper].stride
+ )
+ ;
+ iter_t
+ end_stride
+ ( a_source.my_data.begin()+offset_in_out
+ + loops[oper].limit
+ , loops[oper].stride
+ )
+ ;
+ val_t&oper_val=a_target.my_data[offset_target];
+ oper_val=a_reducer(beg_stride,end_stride);
+ }//exit for(oper...)
+ }//exit for(outer...)
+ return a_target;
+};
+
+#endif


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk