]> git.lyx.org Git - lyx.git/blobdiff - boost/boost/multi_array.hpp
Make the default format translatable, and load the cite formats in
[lyx.git] / boost / boost / multi_array.hpp
index a9481b9bc3134e7338f7aa98ec75a8d201769def..f459ce919314a38496b841d85fd82e67de5e3fe2 100644 (file)
@@ -1,3 +1,15 @@
+// Copyright 2002 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software 
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  Boost.MultiArray Library
+//  Authors: Ronald Garcia
+//           Jeremy Siek
+//           Andrew Lumsdaine
+//  See http://www.boost.org/libs/multi_array for documentation.
+
 #ifndef BOOST_MULTI_ARRAY_RG071801_HPP
 #define BOOST_MULTI_ARRAY_RG071801_HPP
 
@@ -14,6 +26,7 @@
 #include "boost/multi_array/multi_array_ref.hpp"
 #include "boost/multi_array/algorithm.hpp"
 #include "boost/array.hpp"
+#include "boost/mpl/if.hpp"
 #include "boost/type_traits.hpp"
 #include <algorithm>
 #include <cstddef>
 #include <numeric>
 #include <vector>
 
+
+
 namespace boost {
+  namespace detail {
+    namespace multi_array {
+
+      struct populate_index_ranges {
+        multi_array_types::index_range
+        // RG: underscore on extent_ to stifle strange MSVC warning.
+        operator()(multi_array_types::index base,
+                   multi_array_types::size_type extent_) {
+          return multi_array_types::index_range(base,base+extent_);
+        }
+      };
+
+#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+//
+// Compilers that don't support partial ordering may need help to
+// disambiguate multi_array's templated constructors.  Even vc6/7 are
+// capable of some limited SFINAE, so we take the most-general version
+// out of the overload set with disable_multi_array_impl.
+//
+template <typename T, std::size_t NumDims, typename TPtr>
+char is_multi_array_impl_help(const_multi_array_view<T,NumDims,TPtr>&);
+template <typename T, std::size_t NumDims, typename TPtr>
+char is_multi_array_impl_help(const_sub_array<T,NumDims,TPtr>&);
+template <typename T, std::size_t NumDims, typename TPtr>
+char is_multi_array_impl_help(const_multi_array_ref<T,NumDims,TPtr>&);
+
+char ( &is_multi_array_impl_help(...) )[2];
+
+template <class T>
+struct is_multi_array_impl
+{
+    static T x;
+    BOOST_STATIC_CONSTANT(bool, value = sizeof((is_multi_array_impl_help)(x)) == 1);
+
+  typedef mpl::bool_<value> type;
+};
+
+template <bool multi_array = false>
+struct disable_multi_array_impl_impl
+{
+    typedef int type;
+};
+
+template <>
+struct disable_multi_array_impl_impl<true>
+{
+    // forming a pointer to a reference triggers SFINAE
+    typedef int& type; 
+};
+
+
+template <class T>
+struct disable_multi_array_impl :
+  disable_multi_array_impl_impl<is_multi_array_impl<T>::value>
+{ };
+
+
+template <>
+struct disable_multi_array_impl<int>
+{
+  typedef int type;
+};
+
+
+#endif
+
+    } //namespace multi_array
+  } // namespace detail
 
 template<typename T, std::size_t NumDims,
   typename Allocator>
-class multi_array : 
+class multi_array :
   public multi_array_ref<T,NumDims>
 {
   typedef multi_array_ref<T,NumDims> super_type;
-public: 
+public:
   typedef typename super_type::value_type value_type;
   typedef typename super_type::reference reference;
   typedef typename super_type::const_reference const_reference;
   typedef typename super_type::iterator iterator;
   typedef typename super_type::const_iterator const_iterator;
-  typedef typename super_type::iter_base iter_base;
-  typedef typename super_type::const_iter_base const_iter_base;
   typedef typename super_type::reverse_iterator reverse_iterator;
   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
   typedef typename super_type::element element;
@@ -56,17 +137,31 @@ public:
     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
   };
 
+  explicit multi_array() :
+    super_type((T*)initial_base_,c_storage_order(),
+               /*index_bases=*/0, /*extents=*/0) {
+    allocate_space(); 
+  }
+
   template <class ExtentList>
-  explicit multi_array(ExtentList const& extents) :
+  explicit multi_array(
+      ExtentList const& extents
+#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+      , typename mpl::if_<
+      detail::multi_array::is_multi_array_impl<ExtentList>,
+      int&,int>::type* = 0
+#endif
+      ) :
     super_type((T*)initial_base_,extents) {
     boost::function_requires<
       detail::multi_array::CollectionConcept<ExtentList> >();
     allocate_space();
   }
 
+    
   template <class ExtentList>
   explicit multi_array(ExtentList const& extents,
-                      const general_storage_order<NumDims>& so) : 
+                       const general_storage_order<NumDims>& so) :
     super_type((T*)initial_base_,extents,so) {
     boost::function_requires<
       detail::multi_array::CollectionConcept<ExtentList> >();
@@ -75,8 +170,8 @@ public:
 
   template <class ExtentList>
   explicit multi_array(ExtentList const& extents,
-                      const general_storage_order<NumDims>& so,
-                      Allocator const& alloc) :
+                       const general_storage_order<NumDims>& so,
+                       Allocator const& alloc) :
     super_type((T*)initial_base_,extents,so), allocator_(alloc) {
     boost::function_requires<
       detail::multi_array::CollectionConcept<ExtentList> >();
@@ -85,7 +180,7 @@ public:
 
 
   explicit multi_array(const detail::multi_array
-                      ::extent_gen<NumDims>& ranges) :
+                       ::extent_gen<NumDims>& ranges) :
     super_type((T*)initial_base_,ranges) {
 
     allocate_space();
@@ -93,8 +188,8 @@ public:
 
 
   explicit multi_array(const detail::multi_array
-                      ::extent_gen<NumDims>& ranges,
-                      const general_storage_order<NumDims>& so) :
+                       ::extent_gen<NumDims>& ranges,
+                       const general_storage_order<NumDims>& so) :
     super_type((T*)initial_base_,ranges,so) {
 
     allocate_space();
@@ -102,9 +197,9 @@ public:
 
 
   explicit multi_array(const detail::multi_array
-                      ::extent_gen<NumDims>& ranges,
-                      const general_storage_order<NumDims>& so,
-                      Allocator const& alloc) :
+                       ::extent_gen<NumDims>& ranges,
+                       const general_storage_order<NumDims>& so,
+                       Allocator const& alloc) :
     super_type((T*)initial_base_,ranges,so), allocator_(alloc) {
 
     allocate_space();
@@ -113,28 +208,163 @@ public:
   multi_array(const multi_array& rhs) :
   super_type(rhs), allocator_(rhs.allocator_) {
     allocate_space();
-    boost::copy_n(rhs.base_,rhs.num_elements(),base_);
+    boost::detail::multi_array::copy_n(rhs.base_,rhs.num_elements(),base_);
+  }
+
+
+  //
+  // A multi_array is constructible from any multi_array_ref, subarray, or
+  // array_view object.  The following constructors ensure that.
+  //
+
+  // Due to limited support for partial template ordering, 
+  // MSVC 6&7 confuse the following with the most basic ExtentList 
+  // constructor.
+#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+  template <typename OPtr>
+  multi_array(const const_multi_array_ref<T,NumDims,OPtr>& rhs,
+              const general_storage_order<NumDims>& so = c_storage_order())
+    : super_type(0,so,rhs.index_bases(),rhs.shape()) 
+  {
+    allocate_space();
+    // Warning! storage order may change, hence the following copy technique.
+    std::copy(rhs.begin(),rhs.end(),this->begin());
   }
 
   template <typename OPtr>
   multi_array(const detail::multi_array::
-             const_sub_array<T,NumDims,OPtr>& rhs) :
-    super_type(rhs) {
+              const_sub_array<T,NumDims,OPtr>& rhs,
+              const general_storage_order<NumDims>& so = c_storage_order())
+    : super_type(0,so,rhs.index_bases(),rhs.shape()) 
+  {
     allocate_space();
-    std::copy(rhs.begin(),rhs.end(),begin());
+    std::copy(rhs.begin(),rhs.end(),this->begin());
   }
 
-  // For some reason, gcc 2.95.2 doesn't pick the above template
-  // member function when passed a subarray, so i was forced to
-  // duplicate the functionality here...
+
+  template <typename OPtr>
   multi_array(const detail::multi_array::
-             sub_array<T,NumDims>& rhs) :
-    super_type(rhs) {
+              const_multi_array_view<T,NumDims,OPtr>& rhs,
+              const general_storage_order<NumDims>& so = c_storage_order())
+    : super_type(0,so,rhs.index_bases(),rhs.shape()) 
+  {
     allocate_space();
-    std::copy(rhs.begin(),rhs.end(),begin());
+    std::copy(rhs.begin(),rhs.end(),this->begin());
   }
 
-  // Since assignment is a deep copy, multi_array_ref 
+#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+  // More limited support for MSVC
+
+
+  multi_array(const const_multi_array_ref<T,NumDims>& rhs)
+    : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) 
+  {
+    allocate_space();
+    // Warning! storage order may change, hence the following copy technique.
+    std::copy(rhs.begin(),rhs.end(),this->begin());
+  }
+
+  multi_array(const const_multi_array_ref<T,NumDims>& rhs,
+              const general_storage_order<NumDims>& so)
+    : super_type(0,so,rhs.index_bases(),rhs.shape()) 
+  {
+    allocate_space();
+    // Warning! storage order may change, hence the following copy technique.
+    std::copy(rhs.begin(),rhs.end(),this->begin());
+  }
+
+  multi_array(const detail::multi_array::
+              const_sub_array<T,NumDims>& rhs)
+    : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) 
+  {
+    allocate_space();
+    std::copy(rhs.begin(),rhs.end(),this->begin());
+  }
+
+  multi_array(const detail::multi_array::
+              const_sub_array<T,NumDims>& rhs,
+              const general_storage_order<NumDims>& so)
+    : super_type(0,so,rhs.index_bases(),rhs.shape()) 
+  {
+    allocate_space();
+    std::copy(rhs.begin(),rhs.end(),this->begin());
+  }
+
+
+  multi_array(const detail::multi_array::
+              const_multi_array_view<T,NumDims>& rhs)
+    : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) 
+  {
+    allocate_space();
+    std::copy(rhs.begin(),rhs.end(),this->begin());
+  }
+
+  multi_array(const detail::multi_array::
+              const_multi_array_view<T,NumDims>& rhs,
+              const general_storage_order<NumDims>& so)
+    : super_type(0,so,rhs.index_bases(),rhs.shape()) 
+  {
+    allocate_space();
+    std::copy(rhs.begin(),rhs.end(),this->begin());
+  }
+
+#endif // !BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+
+  // Thes constructors are necessary because of more exact template matches.
+  multi_array(const multi_array_ref<T,NumDims>& rhs)
+    : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) 
+  {
+    allocate_space();
+    // Warning! storage order may change, hence the following copy technique.
+    std::copy(rhs.begin(),rhs.end(),this->begin());
+  }
+
+  multi_array(const multi_array_ref<T,NumDims>& rhs,
+              const general_storage_order<NumDims>& so)
+    : super_type(0,so,rhs.index_bases(),rhs.shape()) 
+  {
+    allocate_space();
+    // Warning! storage order may change, hence the following copy technique.
+    std::copy(rhs.begin(),rhs.end(),this->begin());
+  }
+
+
+  multi_array(const detail::multi_array::
+              sub_array<T,NumDims>& rhs)
+    : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) 
+  {
+    allocate_space();
+    std::copy(rhs.begin(),rhs.end(),this->begin());
+  }
+
+  multi_array(const detail::multi_array::
+              sub_array<T,NumDims>& rhs,
+              const general_storage_order<NumDims>& so)
+    : super_type(0,so,rhs.index_bases(),rhs.shape()) 
+  {
+    allocate_space();
+    std::copy(rhs.begin(),rhs.end(),this->begin());
+  }
+
+
+  multi_array(const detail::multi_array::
+              multi_array_view<T,NumDims>& rhs)
+    : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) 
+  {
+    allocate_space();
+    std::copy(rhs.begin(),rhs.end(),this->begin());
+  }
+    
+  multi_array(const detail::multi_array::
+              multi_array_view<T,NumDims>& rhs,
+              const general_storage_order<NumDims>& so)
+    : super_type(0,so,rhs.index_bases(),rhs.shape()) 
+  {
+    allocate_space();
+    std::copy(rhs.begin(),rhs.end(),this->begin());
+  }
+    
+  // Since assignment is a deep copy, multi_array_ref
   // contains all the necessary code.
   template <typename ConstMultiArray>
   multi_array& operator=(const ConstMultiArray& other) {
@@ -150,6 +380,90 @@ public:
   }
 
 
+  template <typename ExtentList>
+  multi_array& resize(const ExtentList& extents) {
+    boost::function_requires<
+      detail::multi_array::CollectionConcept<ExtentList> >();
+
+    typedef detail::multi_array::extent_gen<NumDims> gen_type;
+    gen_type ranges;
+
+    for (int i=0; i != NumDims; ++i) {
+      typedef typename gen_type::range range_type;
+      ranges.ranges_[i] = range_type(0,extents[i]);
+    }
+    
+    return this->resize(ranges);
+  }
+
+
+
+  multi_array& resize(const detail::multi_array
+                      ::extent_gen<NumDims>& ranges) {
+
+
+    // build a multi_array with the specs given
+    multi_array new_array(ranges,this->storage_order());
+
+
+    // build a view of tmp with the minimum extents
+
+    // Get the minimum extents of the arrays.
+    boost::array<size_type,NumDims> min_extents;
+
+    const size_type& (*min)(const size_type&, const size_type&) =
+      std::min;
+    std::transform(new_array.extent_list_.begin(),new_array.extent_list_.end(),
+                   this->extent_list_.begin(),
+                   min_extents.begin(),
+                   min);
+
+
+    // typedef boost::array<index,NumDims> index_list;
+    // Build index_gen objects to create views with the same shape
+
+    // these need to be separate to handle non-zero index bases
+    typedef detail::multi_array::index_gen<NumDims,NumDims> index_gen;
+    index_gen old_idxes;
+    index_gen new_idxes;
+
+    std::transform(new_array.index_base_list_.begin(),
+                   new_array.index_base_list_.end(),
+                   min_extents.begin(),new_idxes.ranges_.begin(),
+                   detail::multi_array::populate_index_ranges());
+
+    std::transform(this->index_base_list_.begin(),
+                   this->index_base_list_.end(),
+                   min_extents.begin(),old_idxes.ranges_.begin(),
+                   detail::multi_array::populate_index_ranges());
+
+    // Build same-shape views of the two arrays
+    typename
+      multi_array::BOOST_NESTED_TEMPLATE array_view<NumDims>::type view_old = (*this)[old_idxes];
+    typename
+      multi_array::BOOST_NESTED_TEMPLATE array_view<NumDims>::type view_new = new_array[new_idxes];
+
+    // Set the right portion of the new array
+    view_new = view_old;
+
+    using std::swap;
+    // Swap the internals of these arrays.
+    swap(this->super_type::base_,new_array.super_type::base_);
+    swap(this->storage_,new_array.storage_);
+    swap(this->extent_list_,new_array.extent_list_);
+    swap(this->stride_list_,new_array.stride_list_);
+    swap(this->index_base_list_,new_array.index_base_list_);
+    swap(this->origin_offset_,new_array.origin_offset_);
+    swap(this->directional_offset_,new_array.directional_offset_);
+    swap(this->num_elements_,new_array.num_elements_);
+    swap(this->allocator_,new_array.allocator_);
+    swap(this->base_,new_array.base_);
+    swap(this->allocated_elements_,new_array.allocated_elements_);
+
+    return *this;
+  }
+
+
   ~multi_array() {
     deallocate_space();
   }
@@ -157,20 +471,20 @@ public:
 private:
   void allocate_space() {
     typename Allocator::const_pointer no_hint=0;
-    base_ = allocator_.allocate(super_type::num_elements(),no_hint);
-    super_type::set_base_ptr(base_);
-    allocated_elements_ = super_type::num_elements();
+    base_ = allocator_.allocate(this->num_elements(),no_hint);
+    this->set_base_ptr(base_);
+    allocated_elements_ = this->num_elements();
     std::uninitialized_fill_n(base_,allocated_elements_,T());
   }
 
   void deallocate_space() {
     if(base_) {
       for(T* i = base_; i != base_+allocated_elements_; ++i)
-       allocator_.destroy(i);
+        allocator_.destroy(i);
       allocator_.deallocate(base_,allocated_elements_);
     }
-  }    
-  
+  }
+
   typedef boost::array<size_type,NumDims> size_list;
   typedef boost::array<index,NumDims> index_list;