Scopira 20080306

narray.h

00001 
00002 /*
00003  *  Copyright (c) 2002-2007    National Research Council
00004  *
00005  *  All rights reserved.
00006  *
00007  *  This material is confidential and proprietary information of
00008  *  National Research Council Canada ("Confidential Information").
00009  *  This Confidential Information may only be used and reproduced
00010  *  in accordance with the terms of the license agreement.
00011  *
00012  */
00013 
00014 #ifndef __INCLUDED_SCOPIRA_BASEKIT_NARRAY_H__
00015 #define __INCLUDED_SCOPIRA_BASEKIT_NARRAY_H__
00016 
00017 #include <iostream>
00018 #include <iomanip>
00019 
00020 #include <scopira/tool/platform.h>
00021 #include <scopira/tool/flow.h>
00022 #include <scopira/tool/traits.h>
00023 #include <scopira/tool/printflow.h>
00024 #include <scopira/tool/export.h>
00025 
00026 //
00027 // Super Fine N-dimensional data structures
00028 //
00029 // Has D = {1, 2, 3, 4) specializations
00030 // Will have a runtime dynamic narray with dynamic (basic_array)
00031 // based coords, perhaps
00032 //
00033 
00034 namespace scopira
00035 {
00040   namespace basekit
00041   {
00042     enum {
00043       x_axis_c = 0,
00044       y_axis_c = 1,
00045       z_axis_c = 2,
00046       t_axis_c = 3,
00047     };
00048 
00049     //template <class T, int DIM> class nslice;
00050     template <int DIM = 1> class nindex;
00051     template <> class nindex<1>;
00052     template <> class nindex<2>;
00053     template <> class nindex<3>;
00054     template <> class nindex<4>;
00055 
00062     template <int DIM> bool is_flat_stride(const nindex<DIM> &stride, const nindex<DIM> &size);
00063 
00069     class narray_delete_i
00070     {
00071       public:
00072         virtual ~narray_delete_i() { }
00081         virtual void narray_delete(void *mem, size_t len) = 0;
00082     };
00083 
00088     SCOPIRA_EXPORT extern narray_delete_i *null_narray_delete;
00094     SCOPIRA_EXPORT extern narray_delete_i *normal_narray_delete;
00095 
00096     template <class T, int DIM = 1> class narray;
00097 
00098     template <class T, int DIM = 1> class nslice;
00099     template <class T, int DIM = 1> class niterator;
00100 
00101     template <class T, int DIM = 1> class const_nslice;
00102     template <class T, int DIM = 1> class const_niterator;
00103 
00105     template <class E>
00106       inline void print_element(scopira::tool::oflow_i &o, E el);   // default uses <<
00108     template <>
00109       inline void print_element<long>(scopira::tool::oflow_i &o, long el);
00111     template <>
00112       inline void print_element<unsigned long>(scopira::tool::oflow_i &o, unsigned long el);
00114     template <>
00115       inline void print_element<int>(scopira::tool::oflow_i &o, int el);
00117     template <>
00118       inline void print_element<unsigned int>(scopira::tool::oflow_i &o, unsigned int el);
00120     template <>
00121       inline void print_element<short>(scopira::tool::oflow_i &o, short el);
00123     template <>
00124       inline void print_element<char>(scopira::tool::oflow_i &o, char el);
00126     template <>
00127       inline void print_element<double>(scopira::tool::oflow_i &o, double el);
00129     template <>
00130       inline void print_element<float>(scopira::tool::oflow_i &o, float el);
00131 
00133     template <class C>
00134       scopira::tool::oflow_i & print_vector_slice(scopira::tool::oflow_i &o, const const_nslice<C,1> &V);
00136     template <class C>
00137       scopira::tool::oflow_i & print_matrix_slice(scopira::tool::oflow_i &o, const const_nslice<C,2> &M);
00138 
00140     template <class C>
00141       std::ostream & print_vector_slice(std::ostream &o, const const_nslice<C,1> &V);
00143     template <class C>
00144       std::ostream & print_matrix_slice(std::ostream &o, const const_nslice<C,2> &M);
00145 
00146     //
00147     // In the future, a N-dimen base interface class could be put between
00148     // narray_o and object so that people can do dimen independant stuff?
00149     //class narray_i;
00150 
00151     template <class T, int DIM = 1> class narray_o;
00152 
00153     //
00154     // many type defs, for convieinence...
00155     //
00160     typedef narray<bool,1> boolvec_t;
00165     typedef narray<char,1> charvec_t;
00170     typedef narray<short,1> shortvec_t;
00175     typedef narray<int,1> intvec_t;
00180     typedef narray<float,1> floatvec_t;
00185     typedef narray<double,1> doublevec_t;
00186 
00191     typedef narray<bool,2> boolmatrix_t;
00196     typedef narray<char,2> charmatrix_t;
00201     typedef narray<short,2> shortmatrix_t;
00206     typedef narray<int,2> intmatrix_t;
00211     typedef narray<float,2> floatmatrix_t;
00216     typedef narray<double,2> doublematrix_t;
00217 
00222     typedef narray<bool,3> boolcube_t;
00227     typedef narray<char,3> charcube_t;
00232     typedef narray<short,3> shortcube_t;
00237     typedef narray<int,3> intcube_t;
00242     typedef narray<float,3> floatcube_t;
00247     typedef narray<double,3> doublecube_t;
00248 
00253     typedef narray<bool,4> boolquad_t;
00258     typedef narray<char,4> charquad_t;
00263     typedef narray<short,4> shortquad_t;
00268     typedef narray<int,4> intquad_t;
00273     typedef narray<float,4> floatquad_t;
00278     typedef narray<double,4> doublequad_t;
00279 
00284     typedef narray_o<bool,1> boolvec_o;
00289     typedef narray_o<char,1> charvec_o;
00294     typedef narray_o<short,1> shortvec_o;
00299     typedef narray_o<int,1> intvec_o;
00304     typedef narray_o<float,1> floatvec_o;
00309     typedef narray_o<double,1> doublevec_o;
00310 
00315     typedef narray_o<bool,2> boolmatrix_o;
00320     typedef narray_o<char,2> charmatrix_o;
00325     typedef narray_o<short,2> shortmatrix_o;
00330     typedef narray_o<int,2> intmatrix_o;
00335     typedef narray_o<float,2> floatmatrix_o;
00340     typedef narray_o<double,2> doublematrix_o;
00341 
00346     typedef narray_o<bool,3> boolcube_o;
00351     typedef narray_o<char,3> charcube_o;
00356     typedef narray_o<short,3> shortcube_o;
00361     typedef narray_o<int,3> intcube_o;
00366     typedef narray_o<float,3> floatcube_o;
00371     typedef narray_o<double,3> doublecube_o;
00372 
00377     typedef narray_o<bool,4> boolquad_o;
00382     typedef narray_o<char,4> charquad_o;
00387     typedef narray_o<short,4> shortquad_o;
00392     typedef narray_o<int,4> intquad_o;
00397     typedef narray_o<float,4> floatquad_o;
00402     typedef narray_o<double,4> doublequad_o;
00403   }
00404 }
00405 
00406 // NINDEX
00407 
00413 template <int DIM> class scopira::basekit::nindex : public scopira::tool::fixed_array<size_t, DIM>
00414 {
00415   private:
00416     typedef nindex<DIM> this_type;
00417 
00418   public:
00420     nindex(size_t val);
00422     nindex(void) { }
00423 
00425     bool operator < (const this_type &rhs) const;
00427     bool operator == (const this_type &rhs) const;
00429     size_t operator* (const this_type &rhs) const;
00430 
00432     size_t product(void) const;
00434     size_t offset(const this_type &c) const;
00436     this_type strides(void) const;
00438     static this_type steps(void);
00440     nindex<DIM-1> shrink(void) const;
00441 };
00442 
00448 template <>
00449 class scopira::basekit::nindex<1> : public scopira::tool::fixed_array<size_t, 1>
00450 {
00451   private:
00452     typedef scopira::tool::fixed_array<size_t, 1> parent_type;
00453     typedef nindex<1> this_type;
00454 
00455   public:
00457     nindex(size_t v=0) { dm_ary[0] = v; }
00459     void clear(size_t v = 0) { dm_ary[0] = v; }
00460 
00462     size_t product(void) const { return dm_ary[0]; }
00464     size_t offset(const this_type &c) const { return c.dm_ary[0]; }
00466     this_type strides(void) const { return this_type(1); }
00468     static this_type steps(void) { return this_type(0); }
00470     nindex<1> shrink(void) const { return nindex<1>(); } // gotta return somethin', and definatly not a 0-array
00471 
00473     bool operator < (const this_type &rhs) const { return dm_ary[0]<rhs.dm_ary[0]; }
00475     bool operator == (const this_type &rhs) const { return dm_ary[0]==rhs.dm_ary[0]; }
00477     size_t operator *(const this_type &rhs) const { return dm_ary[0]*rhs.dm_ary[0]; }
00479     const this_type & operator = (const this_type &rhs) { dm_ary[0] = rhs.dm_ary[0]; return *this; }
00480 
00482     size_t & x(void) { return dm_ary[0]; }
00484     size_t x(void) const { return dm_ary[0]; }
00485 
00487     void set(size_t _x) { dm_ary[0] = _x; }
00488 };
00489 
00495 template <>
00496 class scopira::basekit::nindex<2> : public scopira::tool::fixed_array<size_t, 2>
00497 {
00498   private:
00499     typedef scopira::tool::fixed_array<size_t, 2> parent_type;
00500     typedef nindex<2> this_type;
00501 
00502   public:
00504     nindex(size_t _x, size_t _y) { dm_ary[0] = _x; dm_ary[1] = _y; }
00506     nindex(size_t v=0) { clear(v); }
00508     void clear(size_t v = 0)
00509       { dm_ary[0] = v; dm_ary[1] = v; }
00510 
00512     size_t product(void) const { return dm_ary[0]*dm_ary[1]; }
00514     size_t offset(const this_type &c) const { return c.dm_ary[1]*dm_ary[0] + c.dm_ary[0]; }
00516     this_type strides(void) const { return this_type(1, dm_ary[0]); }
00518     static this_type steps(void) { return this_type(0,1); }
00520     nindex<1> shrink(void) const { return nindex<1>(dm_ary[0]); } // gotta return somethin'
00521 
00523     bool operator < (const this_type &rhs) const { return dm_ary[0]<rhs.dm_ary[0] && dm_ary[1]<rhs.dm_ary[1]; }
00525     bool operator == (const this_type &rhs) const { return dm_ary[0]==rhs.dm_ary[0] && dm_ary[1]==rhs.dm_ary[1]; }
00527     size_t operator *(const this_type &rhs) const { return dm_ary[0]*rhs.dm_ary[0] + dm_ary[1]*rhs.dm_ary[1]; }
00529     const this_type & operator = (const this_type &rhs) { dm_ary[0] = rhs.dm_ary[0]; dm_ary[1] = rhs.dm_ary[1]; return *this; }
00530 
00532     size_t & x(void) { return dm_ary[0]; }
00534     size_t x(void) const { return dm_ary[0]; }
00536     size_t & y(void) { return dm_ary[1]; }
00538     size_t y(void) const { return dm_ary[1]; }
00539 
00541     void set_xy(size_t _x, size_t _y) { dm_ary[0] = _x; dm_ary[1] = _y; }
00542 };
00543 
00549 template <>
00550 class scopira::basekit::nindex<3> : public scopira::tool::fixed_array<size_t, 3>
00551 {
00552   private:
00553     typedef scopira::tool::fixed_array<size_t, 3> parent_type;
00554     typedef nindex<3> this_type;
00555 
00556   public:
00558     SCOPIRA_EXPORT nindex(size_t _x, size_t _y, size_t _z=0);
00560     SCOPIRA_EXPORT nindex(size_t v=0);
00562     SCOPIRA_EXPORT nindex(const this_type &rhs);
00564     void clear(size_t v = 0)
00565       { dm_ary[0] = v; dm_ary[1] = v; dm_ary[2] = v; }
00566 
00568     size_t product(void) const { return dm_ary[0]*dm_ary[1]*dm_ary[2]; }
00570     size_t offset(const this_type &c) const { return c.dm_ary[2]*dm_ary[1]*dm_ary[0] + c.dm_ary[1]*dm_ary[0] + c.dm_ary[0]; }
00572     this_type strides(void) const { return this_type(1, dm_ary[0], dm_ary[0]*dm_ary[1]); }
00574     static this_type steps(void) { return this_type(0,1,2); }
00576     nindex<2> shrink(void) const { return nindex<2>(dm_ary[0], dm_ary[1]); } // gotta return somethin'
00577 
00579     bool operator < (const this_type &rhs) const { return dm_ary[0]<rhs.dm_ary[0] && dm_ary[1]<rhs.dm_ary[1] && dm_ary[2]<rhs.dm_ary[2]; }
00581     bool operator == (const this_type &rhs) const { return dm_ary[0]==rhs.dm_ary[0] && dm_ary[1]==rhs.dm_ary[1] && dm_ary[2]==rhs.dm_ary[2]; }
00583     size_t operator *(const this_type &rhs) const { return dm_ary[0]*rhs.dm_ary[0] + dm_ary[1]*rhs.dm_ary[1] + dm_ary[2]*rhs.dm_ary[2]; }
00585     const this_type & operator = (const this_type &rhs) { dm_ary[0] = rhs.dm_ary[0]; dm_ary[1] = rhs.dm_ary[1]; dm_ary[2] = rhs.dm_ary[2]; return *this; }
00586 
00588     size_t & x(void) { return dm_ary[0]; }
00590     size_t x(void) const { return dm_ary[0]; }
00592     size_t & y(void) { return dm_ary[1]; }
00594     size_t y(void) const { return dm_ary[1]; }
00596     size_t & z(void) { return dm_ary[2]; }
00598     size_t z(void) const { return dm_ary[2]; }
00599 };
00600 
00606 template <>
00607 class scopira::basekit::nindex<4> : public scopira::tool::fixed_array<size_t, 4>
00608 {
00609   private:
00610     typedef scopira::tool::fixed_array<size_t, 4> parent_type;
00611     typedef nindex<4> this_type;
00612 
00613   public:
00615     SCOPIRA_EXPORT nindex(size_t _x, size_t _y, size_t _z=0, size_t _t=0);
00617     SCOPIRA_EXPORT nindex(size_t v=0);
00619     SCOPIRA_EXPORT nindex(const this_type &rhs);
00621     void clear(size_t v = 0)
00622       { dm_ary[0] = v; dm_ary[1] = v; dm_ary[2] = v; dm_ary[3] = v; }
00623 
00625     size_t product(void) const { return dm_ary[0]*dm_ary[1]*dm_ary[2]*dm_ary[3]; }
00627     size_t offset(const this_type &c) const { return c.dm_ary[3]*dm_ary[2]*dm_ary[1]*dm_ary[0] + c.dm_ary[2]*dm_ary[1]*dm_ary[0] + c.dm_ary[1]*dm_ary[0] + c.dm_ary[0]; }
00629     this_type strides(void) const { return this_type(1, dm_ary[0], dm_ary[0]*dm_ary[1], dm_ary[0]*dm_ary[1]*dm_ary[2]); }
00631     static this_type steps(void) { return this_type(0,1,2,3); }
00633     nindex<3> shrink(void) const { return nindex<3>(dm_ary[0], dm_ary[1], dm_ary[2]); } // gotta return somethin'
00634 
00636     bool operator < (const this_type &rhs) const { return dm_ary[0]<rhs.dm_ary[0] && dm_ary[1]<rhs.dm_ary[1] && dm_ary[2]<rhs.dm_ary[2] && dm_ary[3]<rhs.dm_ary[3]; }
00638     bool operator == (const this_type &rhs) const { return dm_ary[0]==rhs.dm_ary[0] && dm_ary[1]==rhs.dm_ary[1] && dm_ary[2]==rhs.dm_ary[2] && dm_ary[3]==rhs.dm_ary[3]; }
00640     size_t operator *(const this_type &rhs) const { return dm_ary[0]*rhs.dm_ary[0] + dm_ary[1]*rhs.dm_ary[1] + dm_ary[2]*rhs.dm_ary[2] + dm_ary[3]*rhs.dm_ary[3]; }
00642     const this_type & operator = (const this_type &rhs) { dm_ary[0] = rhs.dm_ary[0]; dm_ary[1] = rhs.dm_ary[1]; dm_ary[2] = rhs.dm_ary[2]; dm_ary[3] = rhs.dm_ary[3]; return *this; }
00643 
00645     size_t & x(void) { return dm_ary[0]; }
00647     size_t x(void) const { return dm_ary[0]; }
00649     size_t & y(void) { return dm_ary[1]; }
00651     size_t y(void) const { return dm_ary[1]; }
00653     size_t & z(void) { return dm_ary[2]; }
00655     size_t z(void) const { return dm_ary[2]; }
00657     size_t & t(void) { return dm_ary[3]; }
00659     size_t t(void) const { return dm_ary[3]; }
00660 };
00661 
00662 template <int DIM>
00663 bool scopira::basekit::is_flat_stride(const nindex<DIM> &stride, const nindex<DIM> &size)
00664 {
00665   if (stride[0] != 1)
00666     return false;
00667   for (int x=1; x<stride.size(); ++x)
00668     if (stride[x] != size[x-1])
00669       return false;
00670   return true;
00671 }
00672 
00673 //
00674 //
00675 // nindex stuff
00676 //
00677 //
00678 
00679 template <int DIM> scopira::basekit::nindex<DIM>::nindex(size_t val)
00680 {
00681   for (typename this_type::iterator ii = scopira::tool::fixed_array<size_t,DIM>::begin(); ii != scopira::tool::fixed_array<size_t,DIM>::end(); ++ii)
00682     *ii = val;
00683 }
00684 
00685 template <int DIM>
00686 bool scopira::basekit::nindex<DIM>::operator < (const this_type &rhs) const
00687 {
00688   for (size_t i=0; i<scopira::tool::fixed_array<size_t,DIM>::size_c; ++i)
00689     if (scopira::tool::fixed_array<size_t,DIM>::get(i) >= rhs.get(i))
00690       return false;
00691   return true;
00692 }
00693 
00694 template <int DIM>
00695 bool scopira::basekit::nindex<DIM>::operator == (const this_type &rhs) const
00696 {
00697   for (size_t i=0; i<scopira::tool::fixed_array<size_t,DIM>::size_c; ++i)
00698     if (scopira::tool::fixed_array<size_t,DIM>::get(i) != rhs.get(i))
00699       return false;
00700   return true;
00701 }
00702 
00703 template <int DIM>
00704 size_t scopira::basekit::nindex<DIM>::operator * (const this_type &rhs) const
00705 {
00706   size_t ret = 0;
00707   for (size_t i=0; i<scopira::tool::fixed_array<size_t,DIM>::size_c; ++i)
00708     ret += (*this)[i] * rhs[i];
00709   return ret;
00710 }
00711 
00712 template <int DIM>
00713 size_t scopira::basekit::nindex<DIM>::product(void) const
00714 {
00715   size_t ret = 1;
00716   for (typename this_type::const_iterator ii=scopira::tool::fixed_array<size_t,DIM>::begin(); ii != scopira::tool::fixed_array<size_t,DIM>::end(); ++ii)
00717     ret *= *ii;
00718   return ret;
00719 }
00720 
00721 template <int DIM>
00722 size_t scopira::basekit::nindex<DIM>::offset(const this_type &c) const
00723 {
00724   size_t ret = 0, val = 1, i;
00725   for (i=0; i<scopira::tool::fixed_array<size_t,DIM>::size_c; ++i) {
00726     ret += c[i] * val;
00727     val *= scopira::tool::fixed_array<size_t,DIM>::get(i);
00728   }
00729   return ret;
00730 }
00731 
00732 template <int DIM>
00733 scopira::basekit::nindex<DIM> scopira::basekit::nindex<DIM>::strides(void) const
00734 {
00735   nindex<DIM> ret;
00736 
00737   ret[0] = 1;
00738   for (size_t i=1; i<scopira::tool::fixed_array<size_t,DIM>::size_c; ++i)
00739     ret[i] = ret[i-1] * (*this)[i];
00740 
00741   return ret;
00742 }
00743 
00744 template <int DIM>
00745 scopira::basekit::nindex<DIM> scopira::basekit::nindex<DIM>::steps(void)
00746 {
00747   nindex<DIM> ret;
00748 
00749   for (size_t i=0; i<scopira::tool::fixed_array<size_t,DIM>::size_c; ++i)
00750     ret[i] = i;
00751 
00752   return ret;
00753 }
00754 
00755 template <int DIM>
00756 scopira::basekit::nindex<DIM-1> scopira::basekit::nindex<DIM>::shrink(void) const
00757 {
00758   nindex<DIM-1> ret;
00759 
00760   for (size_t i=0; i<scopira::tool::fixed_array<size_t,DIM>::size_c-1; ++i)
00761     ret[i] = scopira::tool::fixed_array<size_t,DIM>::dm_ary[i];
00762   return ret;
00763 }
00764 
00765 // NARRAY
00766 
00787 template <class T, int DIM> class scopira::basekit::narray
00788 {
00789   private:
00790     typedef narray<T, DIM> this_type;
00791   public:
00793     typedef T data_type;
00795     typedef nindex<DIM> index_type;
00797     typedef T* iterator;
00799     typedef const T* const_iterator;
00800 
00801     // extra defines for STL-likeness
00802     typedef T value_type;
00803     typedef T* pointer;
00804     typedef T& reference;
00805     typedef const T& const_reference;
00806     typedef size_t size_type;
00807     typedef ptrdiff_t difference_type;
00808 
00809   private:
00810     T* dm_ary;              
00811     size_t dm_len;          
00812     index_type dm_size;     
00813     narray_delete_i * dm_direct;         
00814 
00815   public:
00817     narray(void);
00819     narray(const this_type &src);
00821     explicit narray(const index_type &sz);
00823     explicit narray(size_t width, size_t height);
00825     ~narray(void) { resize(nindex<DIM>(0)); }
00826 
00833     bool load(scopira::tool::itflow_i &in);
00840     void save(scopira::tool::otflow_i &out) const;
00841 
00843     const T * c_array(void) const { return dm_ary; }
00845     T * c_array(void) { return dm_ary; }
00846 
00848     iterator begin(void) { return c_array(); }
00850     iterator end(void) { return c_array()+size(); }
00852     const_iterator begin(void) const { return c_array(); }
00854     const_iterator end(void) const { return c_array()+size(); }
00855 
00857     bool empty(void) const { return dm_len == 0; }
00859     size_t size(void) const { return dm_len; }
00861     size_t width(void) const { return dm_size[0]; }
00863     size_t height(void) const { return dm_size[1]; }
00865     size_t depth(void) const { return dm_size[2]; }
00867     const index_type & dimen(void) const { return dm_size; }
00868 
00877     void resize(size_t len) { resize(nindex<1>(len)); }
00887     void resize(size_t neww, size_t newh) { resize(nindex<2>(neww, newh)); }
00898     void resize(size_t neww, size_t newh, size_t newd) { resize(nindex<3>(neww, newh, newd)); }
00906     void resize(const index_type &news);
00907 
00920     void resize_direct(index_type sz, T *direct_ary, scopira::basekit::narray_delete_i *delfunc = null_narray_delete);
00921 
00923     scopira::basekit::narray_delete_i * get_direct(void) const { return dm_direct; }
00924 
00925     //
00926     // Slicer Stuff (non-const)
00927     //
00928 
00930     template <int SIM>
00931       nslice<T,SIM> slicer(index_type base, nindex<SIM> dimen, nindex<SIM> direction);
00933     template <int SIM>
00934       nslice<T,SIM> slicer(index_type base, nindex<SIM> dimen);
00936     nslice<T,1> slicer(index_type base, size_t len, size_t direction = x_axis_c);
00937 
00945     nslice<T,1> diagonal_slice(void);
00946 
00947     // slice stuff
00948 
00950     nslice<T,DIM> all_slice(void);
00952     size_t size_rows(void) const { return dm_size[DIM-1]; }
00954     nslice<T,DIM-1> row_slice(size_t r);
00955 
00956     // specific slices
00957 
00958     // VECTOR
00959 
00961     nslice<T,1> xslice(size_t basex, size_t len)
00962       { return slicer(nindex<1>(basex), nindex<1>(len), nindex<1>(x_axis_c)); }
00963 
00964     // MATRIX
00965 
00967     nslice<T,1> xslice(size_t basex, size_t basey, size_t len)
00968       { return slicer(nindex<2>(basex, basey), nindex<1>(len), nindex<1>(x_axis_c)); }
00970     nslice<T,1> yslice(size_t basex, size_t basey, size_t len)
00971       { return slicer(nindex<2>(basex, basey), nindex<1>(len), nindex<1>(y_axis_c)); }
00973     nslice<T,2> xyslice(size_t basex, size_t basey, size_t width, size_t height)
00974       { return slicer(nindex<2>(basex, basey), nindex<2>(width, height)); }
00975 
00976     // N DIMENSIONAL
00977 
00979     nslice<T,1> xslice(index_type base, size_t len)
00980       { return slicer(base, nindex<1>(len), nindex<1>(x_axis_c)); }
00982     nslice<T,1> yslice(index_type base, size_t len)
00983       { return slicer(base, nindex<1>(len), nindex<1>(y_axis_c)); }
00985     nslice<T,1> zslice(index_type base, size_t len)
00986       { return slicer(base, nindex<1>(len), nindex<1>(z_axis_c)); }
00988     nslice<T,1> tslice(index_type base, size_t len)
00989       { return slicer(base, nindex<1>(len), nindex<1>(t_axis_c)); }
00990 
00992     nslice<T,2> xyslice(index_type base, size_t width, size_t height)
00993       { return slicer(base, nindex<2>(width, height)); }
00994 
00995     //
00996     // Slicer Stuff (const)
00997     //
00998 
01000     template <int SIM>
01001       const_nslice<T,SIM> slicer(index_type base, nindex<SIM> dimen,
01002           nindex<SIM> direction) const;
01004     template <int SIM>
01005       const_nslice<T,SIM> slicer(index_type base, nindex<SIM> dimen) const;
01007     const_nslice<T,1> slicer(index_type base, size_t len, size_t direction = x_axis_c) const;
01008 
01010     const_nslice<T,1> diagonal_slice(void) const;
01011 
01012     // slice stuff
01013 
01015     const_nslice<T,DIM> all_slice(void) const;
01017     //size_t size_rows(void) const { return dm_size[DIM-1]; }
01019     const_nslice<T,DIM-1> row_slice(size_t r) const;
01020 
01021     // specific slices
01022 
01023     // VECTOR
01024 
01026     const_nslice<T,1> xslice(size_t basex, size_t len) const
01027       { return slicer(nindex<1>(basex), nindex<1>(len), nindex<1>(x_axis_c)); }
01028 
01029     // MATRIX
01030 
01032     const_nslice<T,1> xslice(size_t basex, size_t basey, size_t len) const
01033       { return slicer(nindex<2>(basex, basey), nindex<1>(len), nindex<1>(x_axis_c)); }
01035     const_nslice<T,1> yslice(size_t basex, size_t basey, size_t len) const
01036       { return slicer(nindex<2>(basex, basey), nindex<1>(len), nindex<1>(y_axis_c)); }
01038     const_nslice<T,2> xyslice(size_t basex, size_t basey, size_t width, size_t height) const
01039       { return slicer(nindex<2>(basex, basey), nindex<2>(width, height)); }
01040 
01041     // N DIMENSIONAL
01042 
01044     const_nslice<T,1> xslice(index_type base, size_t len) const
01045       { return slicer(base, nindex<1>(len), nindex<1>(x_axis_c)); }
01047     const_nslice<T,1> yslice(index_type base, size_t len) const
01048       { return slicer(base, nindex<1>(len), nindex<1>(y_axis_c)); }
01050     const_nslice<T,1> zslice(index_type base, size_t len) const
01051       { return slicer(base, nindex<1>(len), nindex<1>(z_axis_c)); }
01053     const_nslice<T,1> tslice(index_type base, size_t len) const
01054       { return slicer(base, nindex<1>(len), nindex<1>(t_axis_c)); }
01055 
01057     const_nslice<T,2> xyslice(index_type base, size_t width, size_t height) const
01058       { return slicer(base, nindex<2>(width, height)); }
01059 
01060     //
01061     // end of slice stuff
01062     //
01063 
01065     void clear(void) { set_all(T()); }
01067     void set_all(T v);
01069     void copy(const this_type &at);
01071     void copy(const nslice<T,DIM> &at);
01073     void copy(const const_nslice<T,DIM> &at);
01075     void operator=(const this_type &at) { copy(at); }
01076 
01077     // *** nindex access ***
01078 
01080     T operator()(index_type c) const {
01081       assert("[narray element access out of bounds]" && c<dm_size );
01082       return dm_ary[dm_size.offset(c)];
01083     }
01085     T& operator()(index_type c) {
01086       assert("[narray element access out of bounds]" && c<dm_size );
01087       return dm_ary[dm_size.offset(c)];
01088     }
01090     void set(index_type c, T v) {
01091       assert("[narray element access out of bounds]" && c<dm_size );
01092       dm_ary[dm_size.offset(c)] = v;
01093     }
01095     T get(index_type c) const {
01096       assert("[narray element access out of bounds]" && c<dm_size );
01097       return dm_ary[dm_size.offset(c)];
01098     }
01099 
01100     // *** 1D vector like access ***
01101 
01103     const T operator[](size_t idx) const {
01104       assert("[narray element access out of bounds]" && (idx < dm_len) );
01105       return dm_ary[idx];
01106     }
01108     T& operator[](size_t idx) {
01109       assert("[narray element access out of bounds]" && (idx < dm_len) );
01110       return dm_ary[idx];
01111     }
01113     void set(size_t idx, T v) {
01114       assert("[narray element access out of bounds]" && (idx < dm_len) );
01115       dm_ary[idx] = v;
01116     }
01118     T get(size_t idx) const {
01119       assert("[narray element access out of bounds]" && (idx < dm_len) );
01120       return dm_ary[idx];
01121     }
01122 
01123     // *** 2D matrix like access ***
01124 
01134     const T operator()(size_t x, size_t y) const {
01135       assert("[narray element access out of bounds]" && (x<width()) && (y<height()) );
01136       return dm_ary[x+y*width()];
01137     }
01147     T& operator()(size_t x, size_t y) {
01148       assert("[narray element access out of bounds]" && (x<width()) && (y<height()) );
01149       return dm_ary[x+y*width()];
01150     }
01160     void set(size_t x, size_t y, T v) {
01161       assert("[narray element access out of bounds]" && (x<width()) && (y<height()) );
01162       dm_ary[x+y*width()] = v;
01163     }
01173     T get(size_t x, size_t y) const {
01174       assert("[narray element access out of bounds]" && (x<width()) && (y<height()));
01175       return dm_ary[x+y*width()];
01176     }
01177 
01178     // 3D
01179     
01190     T& operator()(size_t x, size_t y, size_t z) {
01191       assert("[narray element access out of bounds]" && (x<width()) && (y<height()) && (z<depth()));
01192       return dm_ary[x+y*width()+z*width()*height()];
01193     }
01204     void set(size_t x, size_t y, size_t z, T v) {
01205       assert("[narray element access out of bounds]" && (x<width()) && (y<height()) && (z<depth()));
01206       dm_ary[x+y*width()+z*width()*height()] = v;
01207     }
01218     T get(size_t x, size_t y, size_t z) const {
01219       assert("[narray element access out of bounds]" && (x<width()) && (y<height()) && (z<depth()));
01220       return dm_ary[x+y*width()+z*width()*height()];
01221     }
01222 };
01223 
01224 //
01225 // narray<T>
01226 //
01227 
01228 template <class T, int DIM>
01229 scopira::basekit::narray<T,DIM>::narray(void)
01230   : dm_ary(0), dm_len(0), dm_direct(0)
01231 {
01232 }
01233 
01234 template <class T, int DIM>
01235 scopira::basekit::narray<T,DIM>::narray(const this_type &src)
01236   : dm_ary(0), dm_len(0), dm_direct(0)
01237 {
01238   copy( src );
01239 }
01240 
01241 template <class T, int DIM>
01242 scopira::basekit::narray<T,DIM>::narray(const index_type &sz)
01243   : dm_ary(0), dm_len(0), dm_direct(0)
01244 {
01245   resize(sz);
01246 }
01247 
01248 template <class T, int DIM>
01249 scopira::basekit::narray<T,DIM>::narray(size_t width, size_t height)
01250   : dm_ary(0), dm_len(0), dm_direct(0)
01251 {
01252   resize(nindex<2>(width, height));
01253 }
01254 
01255 
01256 template <class T, int DIM>
01257 bool scopira::basekit::narray<T,DIM>::load(scopira::tool::itflow_i &in)
01258 {
01259   nindex<DIM> newsize;
01260   size_t j;
01261   int v;
01262   bool newver;
01263 
01264   if (!in.read_int(v))   // read TAG, possibly
01265     return false;
01266   if (v == -10 || v == -11) {
01267     newver = v == -11;
01268     // read new style
01269     if (!in.read_int(v))
01270       return false;
01271     assert(v == DIM);
01272     if (newver)
01273       for (j=0; j<DIM; ++j) {
01274         if (!in.read_size_t(newsize[j]))
01275           return false;
01276       }
01277     else
01278       for (j=0; j<DIM; ++j) {
01279         if (!in.read_int(v))
01280           return false;
01281         newsize[j] = v;
01282       }
01283 
01284     resize(newsize);
01285 
01286     if (!empty()) {
01287       if (!in.read_array(dm_ary, size()))
01288         return false;
01289 #ifdef PLATFORM_BYTESWAP
01290       // decode this thing
01291       scopira::tool::byte_swap_all(dm_ary, dm_ary + dm_len);
01292 #endif
01293     }
01294   } else {
01295     // read OLD STYLE, soon to be deprecated
01296     newsize[0] = v;
01297     iterator ii, endii;
01298 
01299     assert(v>=0);
01300     for (j=1; j<DIM; ++j) {
01301       if (!in.read_int(v))
01302         return false;
01303       assert(v>=0);
01304       newsize[j] = v;
01305     }
01306 
01307     resize(newsize);
01308 
01309     endii = end();
01310     for (ii=begin(); ii != endii; ++ii)
01311       if (!scopira::tool::flowtraits_g<data_type>::load(in, *ii))
01312         return false;
01313   }
01314   return true;
01315 }
01316 
01317 template <class T, int DIM>
01318 void scopira::basekit::narray<T,DIM>::save(scopira::tool::otflow_i &out) const
01319 {
01320   // this ONLY writes in NEW STYLE
01321   size_t j;
01322 
01323   out.write_int(-11);   // my TAG (-10 == int sizes... -11 size_t sizes)
01324   out.write_int(DIM);    // redudant, but whatever
01325   for (j=0; j<DIM; ++j)
01326     out.write_size_t(dm_size[j]);
01327   // write out payload
01328   if (!empty()) {
01329 #ifdef PLATFORM_BYTESWAP
01330     T *head, *tail;
01331     head = const_cast<T*>(dm_ary);   // ugly, but a must
01332     tail = const_cast<T*>(dm_ary + dm_len);
01333     scopira::tool::byte_swap_all(head, tail);
01334 #endif
01335     out.write_array(dm_ary, size());
01336 #ifdef PLATFORM_BYTESWAP
01337     // undo the swappage
01338     // I'd rather do this one extra time, then use a temporary (and thus twice the memory)
01339     scopira::tool::byte_swap_all(head, tail);
01340 #endif
01341   }
01342 }
01343 
01344 template <class T, int DIM>
01345   void scopira::basekit::narray<T,DIM>::resize(const index_type &news)
01346 {
01347   if (news == dm_size)
01348     return;
01349 
01350   if (dm_direct) {
01351     assert("[resize attempted on DIRECT mode narray]" && news.product() == 0);
01352     // call the handler to nuke this object, since we're in destruction mode
01353     dm_direct->narray_delete(dm_ary, dm_len);
01354     dm_direct = 0;
01355     dm_size = news;
01356     dm_ary = 0;
01357     dm_len = 0;
01358     return;
01359   }
01360 
01361   dm_size = news;
01362 
01363   if (dm_len > 0)
01364     delete []dm_ary;
01365   dm_len = dm_size.product();
01366   if (dm_len == 0)
01367     dm_ary = 0;
01368   else
01369     dm_ary = new T[dm_len];
01370 }
01371 
01372 template <class T, int DIM>
01373   void scopira::basekit::narray<T,DIM>::resize_direct(index_type sz, T *direct_ary, scopira::basekit::narray_delete_i *delfunc)
01374 {
01375   assert("[resize_direct may only be called on empty narrays]" && (dm_direct || empty()));
01376 
01377   if (dm_direct) {
01378     // nuke the previous version
01379     dm_direct->narray_delete(dm_ary, dm_len);
01380   }
01381 
01382   dm_size = sz;
01383   dm_len = dm_size.product();
01384   dm_direct = dm_len != 0 ? delfunc : 0;
01385   
01386   if (dm_direct) {
01387     assert(direct_ary);
01388     dm_ary = direct_ary;
01389     if (dm_direct == normal_narray_delete)    // special case
01390       dm_direct = 0;
01391   } else {
01392     // clearing operation (it doesnt matter what direct_ary is in this case)
01393     dm_ary = 0;
01394   }
01395 }
01396 
01397 template <class T, int DIM>
01398   template <int SIM>
01399 scopira::basekit::nslice<T,SIM> scopira::basekit::narray<T,DIM>::slicer(
01400     index_type base, nindex<SIM> dimen, nindex<SIM> direction)
01401 {
01402   nindex<DIM> size_strides = dm_size.strides();
01403   nindex<SIM> strides;
01404 
01405   for (size_t i=0; i<strides.size_c; ++i)
01406     strides[i] = size_strides[direction[i]];
01407 
01408   return nslice<T,SIM>(dm_ary, dm_size.offset(base), dimen, strides);
01409 }
01410 
01411 template <class T, int DIM>
01412   template <int SIM>
01413 scopira::basekit::nslice<T,SIM> scopira::basekit::narray<T,DIM>::slicer(
01414     index_type base, nindex<SIM> dimen)
01415 {
01416   return slicer(base, dimen, nindex<SIM>::steps());
01417 }
01418 
01419 template <class T, int DIM>
01420 scopira::basekit::nslice<T,1> scopira::basekit::narray<T,DIM>::slicer(index_type base, size_t len,
01421     size_t direction)
01422 {
01423   return slicer(base, nindex<1>(len), nindex<1>(direction));
01424 }
01425 
01426 template <class T, int DIM>
01427 scopira::basekit::nslice<T,1> scopira::basekit::narray<T,DIM>::diagonal_slice(void)
01428 {
01429   assert(DIM == 2 && "[called diagonal_slice() on a non-matrix]\n");
01430   assert(dm_size[0] == dm_size[1] && "[diagonal_slice() matrix must be square]\n");
01431   return nslice<T,1>(dm_ary, 0, dm_size[0], dm_size[0]+1);
01432 }
01433 
01434 template <class T, int DIM>
01435 scopira::basekit::nslice<T,DIM> scopira::basekit::narray<T,DIM>::all_slice(void)
01436 {
01437   return slicer(index_type(0), dm_size, nindex<DIM>::steps());
01438 }
01439 
01440 template <class T, int DIM>
01441 scopira::basekit::nslice<T,DIM-1> scopira::basekit::narray<T,DIM>::row_slice(size_t r)
01442 {
01443   index_type base(0);
01444   base[DIM-1] = r;
01445   return slicer(base, dm_size.shrink(), nindex<DIM-1>::steps());
01446 }
01447 
01448 template <class T, int DIM>
01449   template <int SIM>
01450 scopira::basekit::const_nslice<T,SIM> scopira::basekit::narray<T,DIM>::slicer(
01451     index_type base, nindex<SIM> dimen, nindex<SIM> direction) const
01452 {
01453   nindex<DIM> size_strides = dm_size.strides();
01454   nindex<SIM> strides;
01455 
01456   for (size_t i=0; i<strides.size_c; ++i)
01457     strides[i] = size_strides[direction[i]];
01458 
01459   return const_nslice<T,SIM>(dm_ary, dm_size.offset(base), dimen, strides);
01460 }
01461 
01462 template <class T, int DIM>
01463   template <int SIM>
01464 scopira::basekit::const_nslice<T,SIM> scopira::basekit::narray<T,DIM>::slicer(
01465     index_type base, nindex<SIM> dimen) const
01466 {
01467   return slicer(base, dimen, nindex<SIM>::steps());
01468 }
01469 
01470 template <class T, int DIM>
01471 scopira::basekit::const_nslice<T,1> scopira::basekit::narray<T,DIM>::slicer(index_type base, size_t len,
01472     size_t direction) const
01473 {
01474   return slicer(base, nindex<1>(len), nindex<1>(direction));
01475 }
01476 
01477 template <class T, int DIM>
01478 scopira::basekit::const_nslice<T,1> scopira::basekit::narray<T,DIM>::diagonal_slice(void) const
01479 {
01480   assert(DIM == 2 && "[called diagonal_slice() on a non-matrix]\n");
01481   assert(dm_size[0] == dm_size[1] && "[diagonal_slice() matrix must be square]\n");
01482   return const_nslice<T,1>(dm_ary, 0, dm_size[0], dm_size[0]+1);
01483 }
01484 
01485 template <class T, int DIM>
01486 scopira::basekit::const_nslice<T,DIM> scopira::basekit::narray<T,DIM>::all_slice(void) const
01487 {
01488   return slicer(index_type(0), dm_size, nindex<DIM>::steps());
01489 }
01490 
01491 template <class T, int DIM>
01492 scopira::basekit::const_nslice<T,DIM-1> scopira::basekit::narray<T,DIM>::row_slice(size_t r) const
01493 {
01494   index_type base(0);
01495   base[DIM-1] = r;
01496   return slicer(base, dm_size.shrink(), nindex<DIM-1>::steps());
01497 }
01498 
01499 template <class T, int DIM>
01500 void scopira::basekit::narray<T,DIM>::set_all(T v)
01501 {
01502   typedef typename this_type::iterator I;
01503   I ii, endii;
01504 
01505   endii = end();
01506   for (ii=begin(); ii != endii; ++ii)
01507     *ii = v;
01508 }
01509 
01510 template <class T, int DIM>
01511 void scopira::basekit::narray<T,DIM>::copy(const this_type &at)
01512 {
01513   typedef typename this_type::iterator I;
01514   typedef typename this_type::const_iterator J;
01515 
01516   resize(at.dimen());
01517 
01518   I ii, endii;
01519   J kk;
01520 
01521   endii = end();
01522   kk = at.begin();
01523 
01524   for (ii=begin(); ii != endii; ++ii, ++kk)
01525     *ii = *kk;
01526 }
01527 
01528 template <class T, int DIM>
01529 void scopira::basekit::narray<T,DIM>::copy(const nslice<T,DIM> &at)
01530 {
01531   typedef typename this_type::iterator I;
01532   typedef typename nslice<T,DIM>::const_iterator J;
01533 
01534   resize(at.dimen());
01535 
01536   I ii, endii;
01537   J kk;
01538 
01539   endii = end();
01540   kk = at.begin();
01541 
01542   for (ii=begin(); ii != endii; ++ii, ++kk)
01543     *ii = *kk;
01544 }
01545 
01546 template <class T, int DIM>
01547 void scopira::basekit::narray<T,DIM>::copy(const const_nslice<T,DIM> &at)
01548 {
01549   typedef typename this_type::iterator I;
01550   typedef typename const_nslice<T,DIM>::const_iterator J;
01551 
01552   resize(at.dimen());
01553 
01554   I ii, endii;
01555   J kk;
01556 
01557   endii = end();
01558   kk = at.begin();
01559 
01560   for (ii=begin(); ii != endii; ++ii, ++kk)
01561     *ii = *kk;
01562 }
01563 
01564 // NSLICE
01565 
01585 template <class T, int DIM> class scopira::basekit::nslice
01586 {
01587   private:
01588     typedef nslice<T, DIM> this_type;
01589     friend class scopira::basekit::const_nslice<T,DIM>;
01590   public:
01591     typedef T data_type;
01592     typedef nindex<DIM> index_type;
01593     typedef niterator<T, DIM> iterator;
01594     typedef niterator<T, DIM> const_iterator;
01595 
01596     // extra defines for STL-likeness
01597     typedef T value_type;
01598     typedef T* pointer;
01599     typedef T& reference;
01600     typedef const T& const_reference;
01601     typedef size_t size_type;
01602     typedef ptrdiff_t difference_type;
01603   private:
01604     T* dm_var;
01605     size_t dm_prime, dm_end_prime;
01606     // this is the size of each dimension
01607     index_type dm_size;
01608     // this is the striding factor
01609     // for each index, it contains the number of elements per-unit in that index
01610     // for example, dm_stride[0] is the number of elements per x (often 1)
01611     // for example, dm_stride[1] is the number of elements per y (often, this would be the width)
01612     // for example, dm_stride[2] is the number of elements per z (often, width()*height()
01613     index_type dm_stride;
01614   public:
01616     nslice(void);
01618     nslice(const this_type &rhs);
01620     nslice(narray<T,DIM> &rhs);
01622     nslice(narray<T,DIM> *rhs);
01624     nslice(T * _var, size_t _prime, index_type _size, index_type _stride);
01625 
01631     bool load(scopira::tool::itflow_i &in);
01637     void save(scopira::tool::otflow_i &out) const;
01638 
01646     T * c_array(void) const { assert(is_flat_stride()); return dm_var+dm_prime; }
01647 
01653     niterator<T, DIM> begin(void) const
01654       { return niterator<T,DIM>( dm_var+dm_prime, false, dm_size, dm_stride); }
01660     niterator<T, DIM> end(void) const
01661       { return niterator<T,DIM>( dm_var+dm_end_prime, true, dm_size, dm_stride); }
01662 
01664     bool is_null(void) const { return !dm_var; }
01666     void set_null(void) { dm_var = 0; }
01667 
01669     bool empty(void) const { return dm_prime == dm_end_prime; }
01671     size_t size(void) const { return dm_size.product(); }
01673     size_t width(void) const { return dm_size[0]; }
01675     size_t height(void) const { return dm_size[1]; }
01677     size_t depth(void) const { return dm_size[2]; }
01679     const index_type & dimen(void) const { return dm_size; }
01680 
01689     void resize(size_t len) { resize(nindex<1>(len)); }
01699     void resize(size_t neww, size_t newh) { resize(nindex<2>(neww, newh)); }
01710     void resize(size_t neww, size_t newh, size_t newd) { resize(nindex<3>(neww, newh, newd)); }
01718     void resize(const index_type &news);
01719 
01722     template <int SIM>
01723       nslice<T,SIM> slicer(index_type base, nindex<SIM> dimen,
01724           nindex<SIM> direction) const;
01726     template <int SIM>
01727       nslice<T,SIM> slicer(index_type base, nindex<SIM> dimen) const;
01729     nslice<T,1> slicer(index_type base, size_t len, size_t direction = 0) const;
01730 
01731     // slice stuff
01732 
01740     nslice<T,1> diagonal_slice(void);
01741 
01743     nslice<T,DIM> all_slice(void) const;
01745     size_t size_rows(void) const { return dm_size[DIM-1]; }
01747     nslice<T,DIM-1> row_slice(size_t r) const;
01748 
01749     // specific slices
01750 
01751     // VECTOR
01752 
01754     nslice<T,1> xslice(size_t basex, size_t len) const
01755       { return slicer(nindex<1>(basex), nindex<1>(len), nindex<1>(x_axis_c)); }
01756 
01757     // MATRIX
01758 
01760     nslice<T,1> xslice(size_t basex, size_t basey, size_t len) const
01761       { return slicer(nindex<2>(basex, basey), nindex<1>(len), nindex<1>(x_axis_c)); }
01763     nslice<T,1> yslice(size_t basex, size_t basey, size_t len) const
01764       { return slicer(nindex<2>(basex, basey), nindex<1>(len), nindex<1>(y_axis_c)); }
01766     nslice<T,2> xyslice(size_t basex, size_t basey, size_t width, size_t height) const
01767       { return slicer(nindex<2>(basex, basey), nindex<2>(width, height)); }
01768 
01769     // N DIMENSIONAL
01770 
01772     nslice<T,1> xslice(index_type base, size_t len) const
01773       { return slicer(base, nindex<1>(len), nindex<1>(x_axis_c)); }
01775     nslice<T,1> yslice(index_type base, size_t len) const
01776       { return slicer(base, nindex<1>(len), nindex<1>(y_axis_c)); }
01778     nslice<T,1> zslice(index_type base, size_t len) const
01779       { return slicer(base, nindex<1>(len), nindex<1>(z_axis_c)); }
01781     nslice<T,1> tslice(index_type base, size_t len) const
01782       { return slicer(base, nindex<1>(len), nindex<1>(t_axis_c)); }
01783 
01785     nslice<T,2> xyslice(index_type base, size_t width, size_t height) const
01786       { return slicer(base, nindex<2>(width, height)); }
01787 
01789     void clear(void) { set_all(0); }
01791     void set_all(T v) const;
01793     void copy(const narray<T,DIM> &at);
01795     void copy(const nslice<T,DIM> &at);
01797     void copy(const const_nslice<T,DIM> &at);
01798 
01800     T& operator()(index_type idx) const {
01801       assert("[nslice element access out of bounds]" && idx < dm_size && dm_var);
01802       return dm_var[dm_prime + (idx*dm_stride)];
01803     }
01804 
01805     // *** 1D vector like access ***
01806 
01808     T& operator[](size_t idx) const {
01809       assert("[nslice element access out of bounds]" &&  idx < dm_size[0] && DIM==1);
01810       return dm_var[dm_prime+idx*dm_stride[0]];
01811     }
01813     void set(size_t idx, T v) const {
01814       assert("[nslice element access out of bounds]" &&  idx < dm_size[0] && DIM==1);
01815       dm_var[dm_prime+idx*dm_stride[0]] = v;
01816     }
01818     T get(size_t idx) const {
01819       assert("[nslice element access out of bounds]" &&  idx < dm_size[0] && DIM==1);
01820       return dm_var[dm_prime+idx*dm_stride[0]];
01821     }
01822 
01823     // *** 2D matrix like access ***
01824 
01834     T& operator()(size_t x, size_t y) const {
01835       assert("[nslice element access out of bounds]" &&  (x<width()) && (y<height()) );
01836       return dm_var[dm_prime+x*dm_stride[0]+y*dm_stride[1]];
01837     }
01847     void set(size_t x, size_t y, T v) const {
01848       assert("[nslice element access out of bounds]" &&  (x<width()) && (y<height()) );
01849       dm_var[dm_prime+x*dm_stride[0]+y*dm_stride[1]] = v;
01850     }
01860     T get(size_t x, size_t y) const {
01861       assert("[nslice element access out of bounds]" &&  (x<width()) && (y<height()));
01862       return dm_var[dm_prime+x*dm_stride[0]+y*dm_stride[1]];
01863     }
01864 
01865     // 3D
01866 
01877     T& operator()(size_t x, size_t y, size_t z) const {
01878       assert("[nslice element access out of bounds]" &&  (x<width()) && (y<height()) && (z<depth()));
01879       return dm_var[dm_prime+x*dm_stride[0]+y*dm_stride[1]+z*dm_stride[2]];
01880     }
01891     void set(size_t x, size_t y, size_t z, T v) const {
01892       assert("[nslice element access out of bounds]" &&  (x<width()) && (y<height()) && (z<depth()));
01893       dm_var[dm_prime+x*dm_stride[0]+y*dm_stride[1]+z*dm_stride[2]] = v;
01894     }
01905     T get(size_t x, size_t y, size_t z) const {
01906       assert("[nslice element access out of bounds]" &&  (x<width()) && (y<height()) && (z<depth()));
01907       return dm_var[dm_prime+x*dm_stride[0]+y*dm_stride[1]+z*dm_stride[2]];
01908     }
01909 
01916     bool is_flat_stride(void) const { return scopira::basekit::is_flat_stride(dm_stride, dm_size); }
01917 };
01918 
01919 //
01920 //
01921 // nslice
01922 //
01923 //
01924 
01925 template <class T, int DIM>
01926 scopira::basekit::nslice<T,DIM>::nslice(void)
01927   : dm_var(0)
01928 {
01929 }
01930 
01931 template <class T, int DIM>
01932 scopira::basekit::nslice<T,DIM>::nslice(const this_type &rhs)
01933   : dm_var(rhs.dm_var), dm_prime(rhs.dm_prime), dm_end_prime(rhs.dm_end_prime),
01934     dm_size(rhs.dm_size), dm_stride(rhs.dm_stride)
01935 {
01936 }
01937 
01938 template <class T, int DIM>
01939 scopira::basekit::nslice<T,DIM>::nslice(narray<T,DIM> &rhs)
01940 {
01941   *this = rhs.all_slice();
01942 }
01943 
01944 template <class T, int DIM>
01945 scopira::basekit::nslice<T,DIM>::nslice(narray<T,DIM> *rhs)
01946 {
01947   *this = rhs->all_slice();
01948 }
01949 
01950 template <class T, int DIM>
01951 scopira::basekit::nslice<T,DIM>::nslice(T * _var, size_t _prime, index_type _size, index_type _stride)
01952   : dm_var(_var), dm_prime(_prime),
01953     dm_size(_size), dm_stride(_stride)
01954 {
01955   dm_end_prime = dm_prime + dm_stride[DIM-1]*dm_size[DIM-1];
01956 }
01957 
01958 template <class T, int DIM>
01959 bool scopira::basekit::nslice<T,DIM>::load(scopira::tool::itflow_i &in)
01960 {
01961   // this ONLY reads in NEW STYLE
01962   int i, j;
01963   size_t left;
01964 
01965   // read tag
01966   if (!in.read_int(i) || i != -11)
01967     return false;
01968 
01969   // read DIM
01970   if (!in.read_int(i) || i != DIM)
01971     return false;
01972   for (i=0; i<DIM; ++i)
01973     if (!in.read_size_t(left) || left != dm_size[i])
01974       return false;
01975 
01976   // check for super fast case when stride == 1
01977 #ifndef PLATFORM_BYTESWAP
01978   if (is_flat_stride()) {
01979     size_t sz = size();
01980     return in.read_array(c_array(), sz) == sz;
01981   }
01982 #endif
01983 
01984   // read in the payload
01985   scopira::tool::fixed_array<T, 1024*8> buf;
01986   const_iterator ii=begin(), endii=end();
01987   T *jj, *endjj;
01988 
01989   left = size();
01990   while (left>0) {
01991     if (left>buf.size())
01992       j = buf.size();
01993     else
01994       j = left;
01995     jj = buf.begin();
01996     endjj = jj + j;
01997 
01998     if (!in.read_array(jj, j))
01999       return false;
02000 #ifdef PLATFORM_BYTESWAP
02001     scopira::tool::byte_swap_all(jj, endjj);
02002 #endif
02003 
02004     for (; jj != endjj; ++jj, ++ii)
02005       *ii = *jj;
02006 
02007     left -= j;
02008   }
02009   return true;
02010 }
02011 
02012 template <class T, int DIM>
02013 void scopira::basekit::nslice<T,DIM>::save(scopira::tool::otflow_i &out) const
02014 {
02015   // this ONLY writes in NEW STYLE
02016   int j;
02017 
02018   out.write_int(-11);   // my TAG (-10 == int sizes... -11 size_t sizes)
02019   out.write_int(DIM);    // redudant, but whatever
02020   for (j=0; j<DIM; ++j)
02021     out.write_size_t(dm_size[j]);
02022   if (empty())
02023     return;
02024 
02025   // check for super fast case when stride == 1
02026 #ifndef PLATFORM_BYTESWAP
02027   if (is_flat_stride()) {
02028     out.write_array(c_array(), size());
02029     return;
02030   }
02031 #endif
02032 
02033   // write out payload
02034   scopira::tool::fixed_array<T, 1024*8> buf;
02035   const_iterator ii=begin(), endii=end();
02036   T *jj, *endjj;
02037 
02038   while (ii != endii) {
02039     for (jj=buf.begin(), endjj=buf.end(); jj != endjj && ii != endii; ++jj, ++ii)
02040       *jj = *ii;
02041 #ifdef PLATFORM_BYTESWAP
02042     scopira::tool::byte_swap_all(jj, endjj);
02043 #endif
02044     out.write_array(buf.begin(), (jj-buf.begin()));
02045   }
02046 }
02047 
02048 template <class T, int DIM>
02049 void scopira::basekit::nslice<T,DIM>::resize(const index_type &news)
02050 {
02051   dm_size = news;
02052   dm_end_prime = dm_prime + dm_stride[DIM-1]*dm_size[DIM-1];
02053 }
02054 
02055 template <class T, int DIM>
02056   template <int SIM>
02057 scopira::basekit::nslice<T,SIM> scopira::basekit::nslice<T,DIM>::slicer(
02058     index_type base, nindex<SIM> dimen, nindex<SIM> direction) const
02059 {
02060   nindex<SIM> strides;
02061 
02062   for (size_t i=0; i<strides.size_c; ++i)
02063     strides[i] = dm_stride[direction[i]];
02064 
02065   return nslice<T,SIM>(dm_var, dm_prime+(base*dm_stride), dimen, strides);
02066 }
02067 
02068 template <class T, int DIM>
02069   template <int SIM>
02070 scopira::basekit::nslice<T,SIM> scopira::basekit::nslice<T,DIM>::slicer(
02071     index_type base, nindex<SIM> dimen) const
02072 {
02073   return slicer(base, dimen, nindex<SIM>::steps());
02074 }
02075 
02076 template <class T, int DIM>
02077 scopira::basekit::nslice<T,1> scopira::basekit::nslice<T,DIM>::slicer(index_type base, size_t len,
02078     size_t direction) const
02079 {
02080   return slicer(base, nindex<1>(len), nindex<1>(direction));
02081 }
02082 
02083 template <class T, int DIM>
02084 scopira::basekit::nslice<T,1> scopira::basekit::nslice<T,DIM>::diagonal_slice(void)
02085 {
02086   assert(DIM == 2 && "[called diagonal_slice() on a non-matrix]\n");
02087   assert(dm_size[0] == dm_size[1] && "[diagonal_slice() matrix must be square]\n");
02088   return nslice<T,1>(dm_var, dm_prime, nindex<1>(dm_size[0]), nindex<1>(dm_stride[1]+1));
02089 }
02090 
02091 template <class T, int DIM>
02092 scopira::basekit::nslice<T,DIM> scopira::basekit::nslice<T,DIM>::all_slice(void) const
02093 {
02094   return slicer(index_type(0), dm_size, nindex<DIM>::steps());
02095 }
02096 
02097 template <class T, int DIM>
02098 scopira::basekit::nslice<T,DIM-1> scopira::basekit::nslice<T,DIM>::row_slice(size_t r) const
02099 {
02100   index_type base(0);
02101   base[DIM-1] = r;
02102   return slicer(base, dm_size.shrink(), nindex<DIM-1>::steps());
02103 }
02104 
02105 template <class T, int DIM>
02106 void scopira::basekit::nslice<T,DIM>::set_all(T v) const
02107 {
02108   typedef typename this_type::iterator I;
02109   I ii, endii;
02110 
02111   endii = end();
02112   for (ii=begin(); ii != endii; ++ii)
02113     *ii = v;
02114 }
02115 
02116 template <class T, int DIM>
02117 void scopira::basekit::nslice<T,DIM>::copy(const narray<T,DIM> &at)
02118 {
02119   typedef typename this_type::iterator I;
02120   typedef typename narray<T,DIM>::const_iterator J;
02121 
02122   resize(at.dimen());
02123 
02124   I ii, endii;
02125   J kk;
02126 
02127   endii = end();
02128   kk = at.begin();
02129 
02130   for (ii=begin(); ii != endii; ++ii, ++kk)
02131     *ii = *kk;
02132 }
02133 
02134 template <class T, int DIM>
02135 void scopira::basekit::nslice<T,DIM>::copy(const nslice<T,DIM> &at)
02136 {
02137   typedef typename this_type::iterator I;
02138   typedef typename nslice<T,DIM>::iterator J;
02139 
02140   resize(at.dimen());
02141 
02142   I ii, endii;
02143   J kk;
02144 
02145   endii = end();
02146   kk = at.begin();
02147 
02148   for (ii=begin(); ii != endii; ++ii, ++kk)
02149     *ii = *kk;
02150 }
02151 
02152 template <class T, int DIM>
02153 void scopira::basekit::nslice<T,DIM>::copy(const const_nslice<T,DIM> &at)
02154 {
02155   typedef typename this_type::iterator I;
02156   typedef typename const_nslice<T,DIM>::iterator J;
02157 
02158   resize(at.dimen());
02159 
02160   I ii, endii;
02161   J kk;
02162 
02163   endii = end();
02164   kk = at.begin();
02165 
02166   for (ii=begin(); ii != endii; ++ii, ++kk)
02167     *ii = *kk;
02168 }
02169 
02170 // *1niterator********************************************************************
02171 
02176 template <class T, int DIM>
02177 class scopira::basekit::niterator
02178 {
02179   public:
02181     typedef T data_type;
02182   private:
02183     typedef niterator<T, DIM> this_type;
02184     T *dm_ptr;
02185     nindex<DIM> dm_cur, dm_size, dm_stride;
02186   public:
02188     niterator(void);
02190     niterator(T *ptr, bool endptr, nindex<DIM> _size, nindex<DIM> _stride);
02191 
02193     T& operator *(void) { return *dm_ptr; }
02195     bool operator ==(const this_type &rhs) const { return dm_cur == rhs.dm_cur; }
02197     bool operator !=(const this_type &rhs) const { return !(dm_cur == rhs.dm_cur); }
02198 
02200     this_type operator++(void);
02202     this_type operator--(void);
02203 
02204     // for random iterators
02206     ptrdiff_t operator-(const this_type & rhs) const {
02207       assert(DIM == 1);
02208       return (dm_cur[0] - rhs.dm_cur[0]) / dm_stride[0]; }
02210     this_type  operator+(ptrdiff_t idx) const {
02211       assert(DIM == 1);
02212       this_type ret;
02213       ret.dm_ptr = dm_ptr + idx;
02214       ret.dm_cur[0] = dm_cur[0] + idx * dm_stride[0];
02215       ret.dm_size = dm_size;
02216       ret.dm_stride = dm_stride;
02217       return ret;
02218     }
02220     this_type  operator-(ptrdiff_t idx) const {
02221       assert(DIM == 1);
02222       this_type ret;
02223       ret.dm_ptr = dm_ptr - idx;
02224       ret.dm_cur[0] = dm_cur[0] - idx * dm_stride[0];
02225       ret.dm_size = dm_size;
02226       ret.dm_stride = dm_stride;
02227       return ret;
02228     }
02230     bool operator<(const this_type  &rhs) const {
02231       assert(DIM == 1);
02232       return dm_cur[0] < rhs.dm_cur[0]; }
02233 };
02234 
02235 template <class T, int DIM>
02236 scopira::basekit::niterator<T,DIM>::niterator(void)
02237 {
02238 }
02239 
02240 template <class T, int DIM>
02241 scopira::basekit::niterator<T,DIM>::niterator(T *ptr, bool endptr, nindex<DIM> _size, nindex<DIM> _stride)
02242   : dm_ptr(ptr), dm_cur(0), dm_size(_size), dm_stride(_stride)
02243 {
02244   if (endptr)
02245     dm_cur[DIM-1] = dm_size[DIM-1];
02246 }
02247 
02248 template <class T, int DIM>
02249 scopira::basekit::niterator<T,DIM> scopira::basekit::niterator<T, DIM>::operator++(void)
02250 {
02251   dm_ptr += dm_stride[0];
02252   ++dm_cur[0];
02253   for (size_t j=0; dm_cur[j] >= dm_size[j] && j+1<DIM; ++j) {
02254     // carry over the cur digits while doing some stride magic
02255     dm_ptr += -1 * dm_stride[j]*dm_cur[j] + dm_stride[j + 1];
02256     dm_cur[j] = 0;    // reset this digit
02257     ++dm_cur[j+1];    // carry over the next
02258   }
02259   return *this;
02260 }
02261 
02262 template <class T, int DIM>
02263 scopira::basekit::niterator<T,DIM> scopira::basekit::niterator<T, DIM>::operator--(void)
02264 {
02265   for (size_t j=0; j<DIM; ++j) {
02266     // decrement the current digit
02267     if (dm_cur[j] > 0) {
02268       // done... no need to borrow futher
02269       --dm_cur[j];
02270       dm_ptr -= dm_stride[j];
02271       return *this;
02272     }
02273     // dm_cur[j] == 0, so well need to borrow
02274     // carry over the cur digits while doing some stride magic
02275     dm_cur[j] = dm_size[j]-1;    // reset this digit
02276     dm_ptr += dm_stride[j]*dm_cur[j];
02277   }
02278   return *this;
02279 }
02280 
02281 
02282 // CONST_NSLICE
02283 
02293 template <class T, int DIM> class scopira::basekit::const_nslice
02294 {
02295   private:
02296     typedef const_nslice<T, DIM> this_type;
02297   public:
02298     typedef T data_type;
02299     typedef nindex<DIM> index_type;
02300     typedef const_niterator<T, DIM> iterator;
02301     typedef const_niterator<T, DIM> const_iterator;
02302 
02303     // extra defines for STL-likeness
02304     typedef T value_type;
02305     typedef T* pointer;
02306     typedef T& reference;
02307     typedef const T& const_reference;
02308     typedef size_t size_type;
02309     typedef ptrdiff_t difference_type;
02310   private:
02311     const T * dm_var;
02312     size_t dm_prime, dm_end_prime;
02313     index_type dm_size, dm_stride;
02314   public:
02316     const_nslice(void);
02318     const_nslice(const this_type &rhs);
02320     const_nslice(const narray<T,DIM> &rhs);
02322     const_nslice(const narray<T,DIM> *rhs);
02324     const_nslice(const T * _var, size_t _prime, index_type _size, index_type _stride);
02330     const_nslice(const nslice<T, DIM> &rhs);
02331 
02337     void save(scopira::tool::otflow_i &out) const;
02338 
02340     const T * c_array(void) const { assert(is_flat_stride()); return dm_var+dm_prime; }
02341 
02347     const_niterator<T, DIM> begin(void) const
02348       { return const_niterator<T,DIM>( dm_var+dm_prime, false, dm_size, dm_stride); }
02354     const_niterator<T, DIM> end(void) const
02355       { return const_niterator<T,DIM>( dm_var+dm_end_prime, true, dm_size, dm_stride); }
02356 
02358     bool is_null(void) const { return !dm_var; }
02360     void set_null(void) { dm_var = 0; }
02361 
02363     bool empty(void) const { return dm_prime == dm_end_prime; }
02365     size_t size(void) const { return dm_size.product(); }
02367     size_t width(void) const { return dm_size[0]; }
02369     size_t height(void) const { return dm_size[1]; }
02371     size_t depth(void) const { return dm_size[2]; }
02373     const index_type & dimen(void) const { return dm_size; }
02374 
02383     void resize(size_t len) { resize(nindex<1>(len)); }
02393     void resize(size_t neww, size_t newh) { resize(nindex<2>(neww, newh)); }
02404     void resize(size_t neww, size_t newh, size_t newd) { resize(nindex<3>(neww, newh, newd)); }
02412     void resize(const index_type &news);
02413 
02416     template <int SIM>
02417       const_nslice<T,SIM> slicer(index_type base, nindex<SIM> dimen,
02418           nindex<SIM> direction) const;
02420     template <int SIM>
02421       const_nslice<T,SIM> slicer(index_type base, nindex<SIM> dimen) const;
02423     const_nslice<T,1> slicer(index_type base, size_t len, size_t direction = 0) const;
02424 
02425     // slice stuff
02426 
02434     const_nslice<T,1> diagonal_slice(void);
02435 
02437     const_nslice<T,DIM> all_slice(void) const;
02439     size_t size_rows(void) const { return dm_size[DIM-1]; }
02441     const_nslice<T,DIM-1> row_slice(size_t r) const;
02442 
02443     // specific slices
02444 
02445     // VECTOR
02446 
02448     const_nslice<T,1> xslice(size_t basex, size_t len) const
02449       { return slicer(nindex<1>(basex), nindex<1>(len), nindex<1>(x_axis_c)); }
02450 
02451     // MATRIX
02452 
02454     const_nslice<T,1> xslice(size_t basex, size_t basey, size_t len) const
02455       { return slicer(nindex<2>(basex, basey), nindex<1>(len), nindex<1>(x_axis_c)); }
02457     const_nslice<T,1> yslice(size_t basex, size_t basey, size_t len) const
02458       { return slicer(nindex<2>(basex, basey), nindex<1>(len), nindex<1>(y_axis_c)); }
02460     const_nslice<T,2> xyslice(size_t basex, size_t basey, size_t width, size_t height) const
02461       { return slicer(nindex<2>(basex, basey), nindex<2>(width, height)); }
02462 
02463     // N DIMENSIONAL
02464 
02466     const_nslice<T,1> xslice(index_type base, size_t len) const
02467       { return slicer(base, nindex<1>(len), nindex<1>(x_axis_c)); }
02469     const_nslice<T,1> yslice(index_type base, size_t len) const
02470       { return slicer(base, nindex<1>(len), nindex<1>(y_axis_c)); }
02472     const_nslice<T,1> zslice(index_type base, size_t len) const
02473       { return slicer(base, nindex<1>(len), nindex<1>(z_axis_c)); }
02475     const_nslice<T,1> tslice(index_type base, size_t len) const
02476       { return slicer(base, nindex<1>(len), nindex<1>(t_axis_c)); }
02477 
02479     const_nslice<T,2> xyslice(index_type base, size_t width, size_t height) const
02480       { return slicer(base, nindex<2>(width, height)); }
02481 
02483     T operator()(index_type idx) const {
02484       assert("[const_nslice element access out of bounds]" && idx < dm_size && dm_var);
02485       return dm_var[dm_prime + (idx*dm_stride)];
02486     }
02487 
02488     // *** 1D vector like access ***
02489 
02491     T operator[](size_t idx) const {
02492       assert("[const_nslice element access out of bounds]" &&  idx < dm_size[0] && DIM==1);
02493       return dm_var[dm_prime+idx*dm_stride[0]];
02494     }
02496     T get(size_t idx) const {
02497       assert("[const_nslice element access out of bounds]" &&  idx < dm_size[0] && DIM==1);
02498       return dm_var[dm_prime+idx*dm_stride[0]];
02499     }
02500 
02501     // *** 2D matrix like access ***
02502 
02512     T operator()(size_t x, size_t y) const {
02513       assert("[const_nslice element access out of bounds]" &&  (x<width()) && (y<height()) );
02514       return dm_var[dm_prime+x*dm_stride[0]+y*dm_stride[1]];
02515     }
02525     T get(size_t x, size_t y) const {
02526       assert("[const_nslice element access out of bounds]" &&  (x<width()) && (y<height()) );
02527       return dm_var[dm_prime+x*dm_stride[0]+y*dm_stride[1]];
02528     }
02529 
02530     // 3D
02531 
02542     T& operator()(size_t x, size_t y, size_t z) const {
02543       assert("[nslice element access out of bounds]" &&  (x<width()) && (y<height()) && (z<depth()));
02544       return dm_var[dm_prime+x*dm_stride[0]+y*dm_stride[1]+z*dm_stride[2]];
02545     }
02556     T get(size_t x, size_t y, size_t z) const {
02557       assert("[nslice element access out of bounds]" &&  (x<width()) && (y<height()) && (z<depth()));
02558       return dm_var[dm_prime+x*dm_stride[0]+y*dm_stride[1]+z*dm_stride[2]];
02559     }
02560 
02567     bool is_flat_stride(void) const { return scopira::basekit::is_flat_stride(dm_stride, dm_size); }
02568 };
02569 
02570 //
02571 //
02572 // const_nslice
02573 //
02574 //
02575 
02576 template <class T, int DIM>
02577 scopira::basekit::const_nslice<T,DIM>::const_nslice(void)
02578   : dm_var(0)
02579 {
02580 }
02581 
02582 template <class T, int DIM>
02583 scopira::basekit::const_nslice<T,DIM>::const_nslice(const this_type &rhs)
02584   : dm_var(rhs.dm_var), dm_prime(rhs.dm_prime), dm_end_prime(rhs.dm_end_prime),
02585     dm_size(rhs.dm_size), dm_stride(rhs.dm_stride)
02586 {
02587 }
02588 
02589 template <class T, int DIM>
02590 scopira::basekit::const_nslice<T,1> scopira::basekit::const_nslice<T,DIM>::diagonal_slice(void)
02591 {
02592   assert(DIM == 2 && "[called diagonal_slice() on a non-matrix]\n");
02593   assert(dm_size[0] == dm_size[1] && "[diagonal_slice() matrix must be square]\n");
02594   return const_nslice<T,1>(dm_var, dm_prime, nindex<1>(dm_size[0]), nindex<1>(dm_stride[1]+1));
02595 }
02596 
02597 template <class T, int DIM>
02598 scopira::basekit::const_nslice<T,DIM>::const_nslice(const narray<T,DIM> &rhs)
02599 {
02600   *this = rhs.all_slice();
02601 }
02602 
02603 template <class T, int DIM>
02604 scopira::basekit::const_nslice<T,DIM>::const_nslice(const narray<T,DIM> *rhs)
02605 {
02606   *this = rhs->all_slice();
02607 }
02608 
02609 template <class T, int DIM>
02610 scopira::basekit::const_nslice<T,DIM>::const_nslice(const T * _var, size_t _prime, index_type _size, index_type _stride)
02611   : dm_var(_var), dm_prime(_prime),
02612     dm_size(_size), dm_stride(_stride)
02613 {
02614   dm_end_prime = dm_prime + dm_stride[DIM-1]*dm_size[DIM-1];
02615 }
02616 
02617 template <class T, int DIM>
02618 scopira::basekit::const_nslice<T,DIM>::const_nslice(const nslice<T, DIM> &rhs)
02619   : dm_var(rhs.dm_var), dm_prime(rhs.dm_prime), dm_end_prime(rhs.dm_end_prime),
02620     dm_size(rhs.dm_size), dm_stride(rhs.dm_stride)
02621 {
02622 }
02623 
02624 template <class T, int DIM>
02625 void scopira::basekit::const_nslice<T,DIM>::save(scopira::tool::otflow_i &out) const
02626 {
02627   // this ONLY writes in NEW STYLE
02628   int j;
02629 
02630   out.write_int(-11);   // my TAG (-10 == int sizes... -11 size_t sizes)
02631   out.write_int(DIM);    // redudant, but whatever
02632   for (j=0; j<DIM; ++j)
02633     out.write_size_t(dm_size[j]);
02634   if (empty())
02635     return;
02636 
02637   // check for super fast case when stride == 1
02638 #ifndef PLATFORM_BYTESWAP
02639   if (is_flat_stride()) {
02640     out.write_array(c_array(), size());
02641     return;
02642   }
02643 #endif
02644 
02645   // write out payload
02646   scopira::tool::fixed_array<T, 1024*8> buf;
02647   const_iterator ii=begin(), endii=end();
02648   T *jj, *endjj;
02649 
02650   while (ii != endii) {
02651     for (jj=buf.begin(), endjj=buf.end(); jj != endjj && ii != endii; ++jj, ++ii)
02652       *jj = *ii;
02653 #ifdef PLATFORM_BYTESWAP
02654     scopira::tool::byte_swap_all(jj, endjj);
02655 #endif
02656     out.write_array(buf.begin(), (jj-buf.begin()));
02657   }
02658 }
02659 
02660 template <class T, int DIM>
02661 void scopira::basekit::const_nslice<T,DIM>::resize(const index_type &news)
02662 {
02663   dm_size = news;
02664   dm_end_prime = dm_prime + dm_stride[DIM-1]*dm_size[DIM-1];
02665 }
02666 
02667 template <class T, int DIM>
02668   template <int SIM>
02669 scopira::basekit::const_nslice<T,SIM> scopira::basekit::const_nslice<T,DIM>::slicer(
02670     index_type base, nindex<SIM> dimen, nindex<SIM> direction) const
02671 {
02672   nindex<SIM> strides;
02673 
02674   for (size_t i=0; i<strides.size_c; ++i)
02675     strides[i] = dm_stride[direction[i]];
02676 
02677   return const_nslice<T,SIM>(dm_var, dm_prime+(base*dm_stride), dimen, strides);
02678 }
02679 
02680 template <class T, int DIM>
02681   template <int SIM>
02682 scopira::basekit::const_nslice<T,SIM> scopira::basekit::const_nslice<T,DIM>::slicer(
02683     index_type base, nindex<SIM> dimen) const
02684 {
02685   return slicer(base, dimen, nindex<SIM>::steps());
02686 }
02687 
02688 template <class T, int DIM>
02689 scopira::basekit::const_nslice<T,1> scopira::basekit::const_nslice<T,DIM>::slicer(index_type base, size_t len,
02690     size_t direction) const
02691 {
02692   return slicer(base, nindex<1>(len), nindex<1>(direction));
02693 }
02694 
02695 template <class T, int DIM>
02696 scopira::basekit::const_nslice<T,DIM> scopira::basekit::const_nslice<T,DIM>::all_slice(void) const
02697 {
02698   return slicer(index_type(0), dm_size, nindex<DIM>::steps());
02699 }
02700 
02701 template <class T, int DIM>
02702 scopira::basekit::const_nslice<T,DIM-1> scopira::basekit::const_nslice<T,DIM>::row_slice(size_t r) const
02703 {
02704   index_type base(0);
02705   base[DIM-1] = r;
02706   return slicer(base, dm_size.shrink(), nindex<DIM-1>::steps());
02707 }
02708 
02709 // *1const_niterator********************************************************************
02710 
02715 template <class T, int DIM>
02716 class scopira::basekit::const_niterator
02717 {
02718   public:
02720     typedef T data_type;
02721   private:
02722     typedef const_niterator<T, DIM> this_type;
02723     const T *dm_ptr;
02724     nindex<DIM> dm_cur, dm_size, dm_stride;
02725   public:
02727     const_niterator(void);
02729     const_niterator(const T *ptr, bool endptr, nindex<DIM> _size, nindex<DIM> _stride);
02730 
02732     const T& operator *(void) { return *dm_ptr; }
02734     bool operator ==(const this_type &rhs) const { return dm_cur == rhs.dm_cur; }
02736     bool operator !=(const this_type &rhs) const { return !(dm_cur == rhs.dm_cur); }
02737 
02739     void operator++(void);
02741     void operator--(void);
02742 
02743     // for random iterators
02745     ptrdiff_t operator-(const this_type & rhs) const {
02746       assert(DIM == 1);
02747       return (dm_cur[0] - rhs.dm_cur[0]) / dm_stride[0]; }
02749     this_type  operator+(ptrdiff_t idx) const {
02750       assert(DIM == 1);
02751       this_type ret;
02752       ret.dm_ptr = dm_ptr + idx;
02753       ret.dm_cur[0] = dm_cur[0] + idx * dm_stride[0];
02754       ret.dm_size = dm_size;
02755       ret.dm_stride = dm_stride;
02756       return ret;
02757     }
02759     this_type  operator-(ptrdiff_t idx) const {
02760       assert(DIM == 1);
02761       this_type ret;
02762       ret.dm_ptr = dm_ptr - idx;
02763       ret.dm_cur[0] = dm_cur[0] - idx * dm_stride[0];
02764       ret.dm_size = dm_size;
02765       ret.dm_stride = dm_stride;
02766       return ret;
02767     }
02769     bool operator<(const this_type  &rhs) const {
02770       assert(DIM == 1);
02771       return dm_cur[0] < rhs.dm_cur[0]; }
02772 };
02773 
02774 template <class T, int DIM>
02775 scopira::basekit::const_niterator<T,DIM>::const_niterator(void)
02776 {
02777 }
02778 
02779 template <class T, int DIM>
02780 scopira::basekit::const_niterator<T,DIM>::const_niterator(const T *ptr, bool endptr, nindex<DIM> _size, nindex<DIM> _stride)
02781   : dm_ptr(ptr), dm_cur(0), dm_size(_size), dm_stride(_stride)
02782 {
02783   if (endptr)
02784     dm_cur[DIM-1] = dm_size[DIM-1];
02785 }
02786 
02787 template <class T, int DIM>
02788 void scopira::basekit::const_niterator<T, DIM>::operator++(void)
02789 {
02790   dm_ptr += dm_stride[0];
02791   ++dm_cur[0];
02792   for (size_t j=0; dm_cur[j] >= dm_size[j] && j+1<DIM; ++j) {
02793     // carry over the cur digits while doing some stride magic
02794     dm_ptr += -1*dm_stride[j]*dm_cur[j] + dm_stride[j + 1];
02795     dm_cur[j] = 0;    // reset this digit
02796     ++dm_cur[j+1];    // carry over the next
02797   }
02798 }
02799 
02800 template <class T, int DIM>
02801 void scopira::basekit::const_niterator<T, DIM>::operator--(void)
02802 {
02803   for (size_t j=0; j<DIM; ++j) {
02804     // decrement the current digit
02805     if (dm_cur[j] > 0) {
02806       // done... no need to borrow futher
02807       --dm_cur[j];
02808       dm_ptr -= dm_stride[j];
02809       return;
02810     }
02811     // dm_cur[j] == 0, so well need to borrow
02812     // carry over the cur digits while doing some stride magic
02813     dm_cur[j] = dm_size[j]-1;    // reset this digit
02814     dm_ptr += dm_stride[j]*dm_cur[j];
02815   }
02816 }
02817 
02818 // *1narray_o*********************************************************************
02819 
02828 template <class T, int DIM> class scopira::basekit::narray_o : public scopira::basekit::narray<T,DIM>,
02829   public scopira::tool::object
02830 {
02831   private:
02832     typedef scopira::basekit::narray_o<T,DIM> this_type;
02833     typedef scopira::basekit::narray<T,DIM> narray_parent_type;
02834     typedef scopira::tool::object object_parent_type;
02835   public:
02836     // ctors
02837 
02839     narray_o(void) { }
02841     narray_o(const this_type &src)
02842       : narray_parent_type(src) { }
02844     narray_o(const narray_parent_type &src)
02845       : narray_parent_type(src) { }
02847     explicit narray_o(const nindex<DIM> &sz)
02848       : narray_parent_type(sz) { }
02850     explicit narray_o(size_t width, size_t height)
02851       : narray_parent_type(width, height) { }
02852 
02853     // object stuff
02854 
02855     virtual bool load(scopira::tool::iobjflow_i &in) { return narray_parent_type::load(in); }
02856     virtual void save(scopira::tool::oobjflow_i &out) const { narray_parent_type::save(out); }
02857 
02859     void operator=(const this_type &at) { copy(at); }
02860 };
02861 
02862 //
02863 //
02864 // misc funcs
02865 //
02866 //
02867 
02868 namespace std {
02874 template <typename T> struct iterator_traits<scopira::basekit::niterator<T,1> >
02875 {
02876   public:
02877     typedef std::random_access_iterator_tag iterator_category;
02878     typedef T value_type;
02879     typedef ptrdiff_t difference_type;
02880     typedef T* pointer;
02881     typedef T& reference;
02882 };
02883 }//namespace std
02884 
02885 template <class E>
02886   inline void scopira::basekit::print_element(scopira::tool::oflow_i &o, E el)
02887 {
02888   o << ' ' << el;
02889 }
02890 
02892 template <>
02893   inline void scopira::basekit::print_element<long>(scopira::tool::oflow_i &o, long el)
02894 {
02895   flow_printf(o, " %8ld", el);
02896 }
02897 
02899 template <>
02900   inline void scopira::basekit::print_element<unsigned long>(scopira::tool::oflow_i &o, unsigned long el)
02901 {
02902   flow_printf(o, " %8lu", el);
02903 }
02904 
02906 template <>
02907   inline void scopira::basekit::print_element<int>(scopira::tool::oflow_i &o, int el)
02908 {
02909   flow_printf(o, " %8d", el);
02910 }
02911 
02913 template <>
02914   inline void scopira::basekit::print_element<unsigned int>(scopira::tool::oflow_i &o, unsigned int el)
02915 {
02916   flow_printf(o, " %8u", el);
02917 }
02918 
02920 template <>
02921   inline void scopira::basekit::print_element<short>(scopira::tool::oflow_i &o, short el)
02922 {
02923   flow_printf(o, " %8d", el);
02924 }
02925 
02927 template <>
02928   inline void scopira::basekit::print_element<char>(scopira::tool::oflow_i &o, char el)
02929 {
02930   flow_printf(o, " %4d", el);
02931 }
02932 
02934 template <>
02935   inline void scopira::basekit::print_element<double>(scopira::tool::oflow_i &o, double el)
02936 {
02937   flow_printf(o, " %8.2f", el);
02938 }
02939 
02941 template <>
02942   inline void scopira::basekit::print_element<float>(scopira::tool::oflow_i &o, float el)
02943 {
02944   flow_printf(o, " %8.2f", el);
02945 }
02946 
02948 template <class C>
02949   scopira::tool::oflow_i & scopira::basekit::print_vector_slice
02950   (scopira::tool::oflow_i &o, const const_nslice<C,1> &V)
02951 {
02952   size_t i, mx;
02953 
02954   mx = V.size();
02955   o << "Vector, len=" << mx << ":";
02956   for (i=0; i<mx; i++) {
02957     if (i % 10 == 0)
02958       flow_printf(o, "\n %4d:", i);
02959     print_element(o, V[i]);
02960   }
02961 
02962   return o << '\n';
02963 }
02964 
02966 template <class C>
02967   scopira::tool::oflow_i & scopira::basekit::print_matrix_slice
02968   (scopira::tool::oflow_i &o, const const_nslice<C,2> &M)
02969 {
02970   size_t x, y, w, h;
02971 
02972   w = M.width();
02973   h = M.height();
02974 
02975   flow_printf(o, "Matrix, w=%d h=%d:\n       ", w, h);
02976   for (x=0; x<w; x++)
02977     flow_printf(o, " %7d:", x);
02978   o << '\n';
02979   for (y=0; y<h; y++) {
02980     flow_printf(o, " %4d: ", y);
02981     for (x=0; x<w; x++)
02982       print_element(o, M(x,y));
02983     o << '\n';
02984   }
02985   return o;
02986 }
02987 
02992 template <class T, int DIM> scopira::tool::oflow_i & operator << (scopira::tool::oflow_i &o,
02993     const scopira::basekit::const_nslice<T, DIM> &A)
02994 {
02995   size_t k, kmax;
02996   for (k=0, kmax=A.size_rows(); k<kmax; ++k) {
02997     o << "Sub Slice (depth=" << DIM << ") " << k << ":\n";
02998     o << A.row_slice(k) << '\n';
02999   }
03000 
03001   return o;
03002 }
03003 
03008 template <class T> inline scopira::tool::oflow_i & operator << (scopira::tool::oflow_i &o,
03009     const scopira::basekit::const_nslice<T, 1> &A)
03010 {
03011   return print_vector_slice(o, A);
03012 }
03013 
03018 template <class T> inline scopira::tool::oflow_i & operator << (scopira::tool::oflow_i &o,
03019     const scopira::basekit::const_nslice<T, 2> &A)
03020 {
03021   return print_matrix_slice(o, A);
03022 }
03023 
03028 template <class T, int DIM> inline scopira::tool::oflow_i & operator << (scopira::tool::oflow_i &o,
03029   const scopira::basekit::nslice<T, DIM> &A)
03030 {
03031   return o << scopira::basekit::const_nslice<T, DIM>(A);
03032 }
03033 
03038 template <class T, int DIM>
03039 inline
03040 scopira::tool::oflow_i & operator << (scopira::tool::oflow_i &o,
03041     const scopira::basekit::narray<T, DIM> &A)
03042 {
03043   return o << A.all_slice();
03044 }
03045 
03050 template <class T, int DIM>
03051 inline
03052 scopira::tool::oflow_i & operator << (scopira::tool::oflow_i &o,
03053     const scopira::basekit::narray_o<T, DIM> &A)
03054 {
03055   return o << A.all_slice();
03056 }
03057 
03062 template <int DIM>
03063 scopira::tool::oflow_i & operator << (scopira::tool::oflow_i &o,
03064     const scopira::basekit::nindex<DIM> &d)
03065 {
03066   o << '(' << d[0];
03067   for (size_t x=1; x<DIM; ++x)
03068     o << ',' << d[x];
03069   return o << ')';
03070 }
03071 
03073 template <class C>
03074   std::ostream & scopira::basekit::print_vector_slice(std::ostream &o, const const_nslice<C,1> &V)
03075 {
03076   size_t i, mx;
03077 
03078   mx = V.size();
03079   o << "Vector, len=" << mx << ":";
03080   for (i=0; i<mx; i++) {
03081     if (i % 5 == 0)
03082       o << "\n " << std::setw(4) << i << ":";
03083     o.width(8);
03084     o << std::setw(14) << V[i];
03085   }
03086 
03087   return o << '\n';
03088 }
03089 
03091 template <class C>
03092   std::ostream & scopira::basekit::print_matrix_slice
03093   (std::ostream &o, const const_nslice<C,2> &M)
03094 {
03095   size_t x, y, w, h;
03096 
03097   w = M.width();
03098   h = M.height();
03099 
03100   o << "Matrix, w=" << w << " h=" << h << ":\n     ";
03101   for (x=0; x<w; x++)
03102     o << std::setw(13) << x << ':';
03103   o << '\n';
03104   for (y=0; y<h; y++) {
03105     o << std::setw(4) << y << ':';
03106     for (x=0; x<w; x++)
03107       o << std::setw(14) << M(x,y);
03108     o << '\n';
03109   }
03110   return o;
03111 }
03112 
03117 template <class T, int DIM> std::ostream & operator << (std::ostream &o,
03118     const scopira::basekit::const_nslice<T, DIM> &A)
03119 {
03120   size_t k, kmax;
03121   for (k=0, kmax=A.size_rows(); k<kmax; ++k) {
03122     o << "Sub Slice (depth=" << DIM << ") " << k << ":\n";
03123     o << A.row_slice(k) << '\n';
03124   }
03125 
03126   return o;
03127 }
03128 
03133 template <class T> inline std::ostream & operator << (std::ostream &o,
03134     const scopira::basekit::const_nslice<T, 1> &A)
03135 {
03136   return print_vector_slice(o, A);
03137 }
03138 
03143 template <class T> inline std::ostream & operator << (std::ostream &o,
03144     const scopira::basekit::const_nslice<T, 2> &A)
03145 {
03146   return print_matrix_slice(o, A);
03147 }
03148 
03153 template <class T, int DIM> inline std::ostream & operator << (std::ostream &o,
03154   const scopira::basekit::nslice<T, DIM> &A)
03155 {
03156   return o << scopira::basekit::const_nslice<T, DIM>(A);
03157 }
03158 
03163 template <class T, int DIM>
03164 inline
03165 std::ostream & operator << (std::ostream &o,
03166     const scopira::basekit::narray<T, DIM> &A)
03167 {
03168   return o << A.all_slice();
03169 }
03170 
03175 template <class T, int DIM>
03176 inline
03177 std::ostream & operator << (std::ostream &o,
03178     const scopira::basekit::narray_o<T, DIM> &A)
03179 {
03180   return o << A.all_slice();
03181 }
03182 
03187 template <int DIM>
03188 std::ostream & operator << (std::ostream &o,
03189     const scopira::basekit::nindex<DIM> &d)
03190 {
03191   o << '(' << d[0];
03192   for (size_t x=1; x<DIM; ++x)
03193     o << ',' << d[x];
03194   return o << ')';
03195 }
03196 
03350 #endif
03351