OSDN Git Service

2000-07-15 Gabriel Dos Reis <gdr@codesourcery.com>
authorgdr <gdr@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Jul 2000 21:54:06 +0000 (21:54 +0000)
committergdr <gdr@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Jul 2000 21:54:06 +0000 (21:54 +0000)
* std/valarray_array.h (__valarray_get_memory,
__valarray_get_storage, __valarray_release_storage): New
functions.
(_Array_default_ctor, _Array_init_ctor, _Array_copy_ctor,
_Array_copier): New traits classes.
(__valarray_default_construct): New function.  Implements valarray
default construction.
(__valarray_fill_construct): New function. Implements valarray
construction with initializer.
(__valarray_copy_construct): New function.  Implements valarray
copy construction.
(__valarray_destroy_elements): New function.
(__valarray_copy, __valarray_fill): Tweak.
(__valarray_sum, __valarray_product): New helper functions.
(_Array<>::free_data): Remove.
(_Array<>::_Array): Tweak.

* std/std_valarray.h (valarray<>::product): Remove.
(valarray<>::valarray): Use __valarray_get_storage.
(valarray<>::shift, valarray<>::cshift, valarray<>::resize):
Tweak.

* std/cpp_type_traits.h: New file.

* valarray.cc (multiplies<>, accumulate, valarray<>::product):
Remove explicit instantiation.
(__valarray_product): New function.
(_Indexer::_Indexer): Use.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@35055 138bc75d-0d04-0410-961f-82ee72b054a4

libstdc++/ChangeLog
libstdc++/std/cpp_type_traits.h [new file with mode: 0644]
libstdc++/std/std_valarray.h
libstdc++/std/valarray_array.h
libstdc++/valarray.cc

index d09fc3d..04eac45 100644 (file)
@@ -1,3 +1,34 @@
+2000-07-15  Gabriel Dos Reis  <gdr@codesourcery.com>
+
+       * std/valarray_array.h (__valarray_get_memory,
+       __valarray_get_storage, __valarray_release_storage): New
+       functions.
+       (_Array_default_ctor, _Array_init_ctor, _Array_copy_ctor,
+       _Array_copier): New traits classes.
+       (__valarray_default_construct): New function.  Implements valarray
+       default construction.
+       (__valarray_fill_construct): New function. Implements valarray
+       construction with initializer.
+       (__valarray_copy_construct): New function.  Implements valarray
+       copy construction.
+       (__valarray_destroy_elements): New function. 
+       (__valarray_copy, __valarray_fill): Tweak.
+       (__valarray_sum, __valarray_product): New helper functions.
+       (_Array<>::free_data): Remove.
+       (_Array<>::_Array): Tweak.
+
+       * std/std_valarray.h (valarray<>::product): Remove.
+       (valarray<>::valarray): Use __valarray_get_storage.
+       (valarray<>::shift, valarray<>::cshift, valarray<>::resize):
+       Tweak. 
+
+       * std/cpp_type_traits.h: New file.
+
+       * valarray.cc (multiplies<>, accumulate, valarray<>::product):
+       Remove explicit instantiation. 
+       (__valarray_product): New function.
+       (_Indexer::_Indexer): Use.
+
 2000-07-14  Jean-Francois Panisset <panisset@discreet.com>
        
        * std/bastring.h (basic_string<>::clear): Add function.
diff --git a/libstdc++/std/cpp_type_traits.h b/libstdc++/std/cpp_type_traits.h
new file mode 100644 (file)
index 0000000..1a065b4
--- /dev/null
@@ -0,0 +1,299 @@
+// The  -*- C++ -*- type traits classes for internal use in libstdc++
+
+// Copyright (C) 2000 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+// Written by Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
+
+#ifndef _CPP_BITS_CPP_TYPE_TRAITS_H
+#define _CPP_BITS_CPP_TYPE_TRAITS_H 1
+
+//
+// This file provides some compile-time information about various types.
+// These informations were designed, on purpose, to be constant-expressions
+// and not types as found in <stl/bits/type_traits.h>.  In particular, they
+// can be used in control structures and the optimizer, hopefully, will do
+// the obvious thing.
+//
+// Why integral expressions, and not functions nor types?
+// Firstly, these compile-time information entities are used as
+// template-arguments so function return values won't work.  We
+// need compile-time entities.  We're left with types and iintegral constant
+// expressions.
+// Secondly, from the point of view of ease of use, type-based compile-time
+// information is -not- *that* convenient.  One has to write lots of
+// overloaded functions and to hope that the compiler will select the right
+// one. As a net effect, the overall structure isn't very clear at first
+// glance.
+// Thirdly, partial ordering and overload resolution (of template functions)
+// is very costly in terms of compiler-resource.  It is a Good Thing to
+// keep these resource consumption as least as possible.  Please, direct
+// any comment to <dosreis@cmla.ens-cachan.fr>.
+//
+// -- Gaby (dosreis@cmla.ens-cachan.fr) 2000-03-06.
+//
+
+extern "C++" {
+  template<typename _Tp>
+  struct __is_void
+  {
+    enum
+    {
+      _M_type = 0
+    };
+  };
+  
+  template<>
+  struct __is_void<void>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+  //
+  // Integer types
+  //
+  template<typename _Tp>
+  struct __is_integer
+  {
+    enum
+    {
+      _M_type = 0
+    };
+  };
+  
+  // Thirteen specializations (yes there are eleven standard integer
+  // types; 'long long' and 'unsigned long long' are supported as
+  // extensions)
+  template<>
+  struct __is_integer<bool>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+  template<>
+  struct __is_integer<char>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+  template<>
+  struct __is_integer<signed char>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+  template<>
+  struct __is_integer<unsigned char>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+# if 0
+  template<>
+  struct __is_integer<wchar_t>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+# endif
+
+  template<>
+  struct __is_integer<short>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+  template<>
+  struct __is_integer<unsigned short>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+  template<>
+  struct __is_integer<int>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+  template<>
+  struct __is_integer<unsigned int>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+  template<>
+  struct __is_integer<long>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+  template<>
+  struct __is_integer<unsigned long>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+
+# if 0
+  template<>
+  struct __is_integer<long long>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+  template<>
+  struct __is_integer<unsigned long long>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+# endif
+
+  //
+  // Floating point types
+  //
+  template<typename _Tp>
+  struct __is_floating
+  {
+    enum
+    {
+      _M_type = 0
+    };
+  };
+  
+  // three specializations (float, double and 'long double')
+  template<>
+  struct __is_floating<float>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+  template<>
+  struct __is_floating<double>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+  template<>
+  struct __is_floating<long double>
+  {
+    enum
+    {
+      _M_type = 1
+    };
+  };
+  
+  //
+  // An arithmetic type is an integer type or a floating point type
+  //
+  template<typename _Tp>
+  struct __is_arithmetic
+  {
+    enum
+    {
+      _M_type = __is_integer<_Tp>::_M_type || __is_floating<_Tp>::_M_type
+    };
+  };
+  
+  //
+  // A fundamental type is `void' or and arithmetic type
+  //
+  template<typename _Tp>
+  struct __is_fundamental
+  {
+    enum
+    {
+      _M_type = __is_void<_Tp>::_M_type || __is_arithmetic<_Tp>::_M_type
+    };
+  };
+  
+  //
+  // For the immediate use, the following is a good approximation
+  //
+  template<typename _Tp>
+  struct __is_pod
+  {
+    enum
+    {
+      _M_type = __is_fundamental<_Tp>::_M_type
+    };
+  };
+} // extern "C++"
+
+#endif //_CPP_BITS_CPP_TYPE_TRAITS_H
+
+
+
+
+
+
+
index 0e47c77..d32412c 100644 (file)
@@ -212,10 +212,7 @@ public:
     _Tp    sum() const;        
     _Tp    min() const;        
     _Tp    max() const;        
-    
-    // FIXME: Extension
-    _Tp    product () const;
-
+  
     valarray<_Tp> shift (int) const;
     valarray<_Tp> cshift(int) const;
     _Expr<_ValFunClos<_ValArray,_Tp>,_Tp> apply(_Tp func(_Tp)) const;
@@ -285,54 +282,69 @@ inline valarray<_Tp>::valarray () : _M_size (0), _M_data (0) {}
 
 template<typename _Tp>
 inline valarray<_Tp>::valarray (size_t __n) 
-        : _M_size (__n), _M_data (new _Tp[__n]) {}
+  : _M_size (__n), _M_data(__valarray_get_storage<_Tp>(__n))
+{ __valarray_default_construct(_M_data, _M_data + __n); }
 
 template<typename _Tp>
 inline valarray<_Tp>::valarray (const _Tp& __t, size_t __n)
-        : _M_size (__n), _M_data (new _Tp[__n])
-{ __valarray_fill (_M_data, _M_size, __t); }
+  : _M_size (__n), _M_data(__valarray_get_storage<_Tp>(__n))
+{ __valarray_fill_construct(_M_data, _M_data + __n, __t); }
 
 template<typename _Tp>
 inline valarray<_Tp>::valarray (const _Tp* __restrict__ __pT, size_t __n)
-        : _M_size (__n), _M_data (new _Tp[__n])
-{ __valarray_copy (__pT, __n, _M_data); }
+        : _M_size (__n), _M_data(__valarray_get_storage<_Tp>(__n))
+{ __valarray_copy_construct(__pT, __pT + __n, _M_data); }
 
 template<typename _Tp>
 inline valarray<_Tp>::valarray (const valarray<_Tp>& __v)
-        : _M_size (__v._M_size), _M_data (new _Tp[__v._M_size])
-{ __valarray_copy (__v._M_data, _M_size, _M_data); }
+  : _M_size (__v._M_size), _M_data(__valarray_get_storage<_Tp>(__v._M_size))
+{ __valarray_copy_construct (__v._M_data, __v._M_data + _M_size, _M_data); }
 
 template<typename _Tp>
 inline valarray<_Tp>::valarray (const slice_array<_Tp>& __sa)
-        : _M_size (__sa._M_sz), _M_data (new _Tp[__sa._M_sz])
-{ __valarray_copy (__sa._M_array, __sa._M_sz, __sa._M_stride,
-                   _Array<_Tp>(_M_data)); }
+  : _M_size (__sa._M_sz), _M_data(__valarray_get_storage<_Tp>(__sa._M_sz))
+{
+  __valarray_copy_construct
+    (__sa._M_array, __sa._M_sz, __sa._M_stride, _Array<_Tp>(_M_data));
+}
 
 template<typename _Tp>
 inline valarray<_Tp>::valarray (const gslice_array<_Tp>& __ga)
-        : _M_size (__ga._M_index.size()), _M_data (new _Tp[_M_size])
-{ __valarray_copy (__ga._M_array, _Array<size_t>(__ga._M_index), 
-                   _Array<_Tp>(_M_data), _M_size); }
+  : _M_size (__ga._M_index.size()),
+    _M_data(__valarray_get_storage<_Tp>(_M_size))
+{
+  __valarray_copy_construct
+    (__ga._M_array, _Array<size_t>(__ga._M_index),
+     _Array<_Tp>(_M_data), _M_size);
+}
 
 template<typename _Tp>
 inline valarray<_Tp>::valarray (const mask_array<_Tp>& __ma)
-        : _M_size (__ma._M_sz), _M_data (new _Tp[__ma._M_sz])
-{ __valarray_copy (__ma._M_array, __ma._M_mask,
-                   _Array<_Tp>(_M_data), _M_size); }
+  : _M_size (__ma._M_sz), _M_data(__valarray_get_storage<_Tp>(__ma._M_sz))
+{
+  __valarray_copy_construct
+    (__ma._M_array, __ma._M_mask, _Array<_Tp>(_M_data), _M_size);
+}
 
 template<typename _Tp>
 inline valarray<_Tp>::valarray (const indirect_array<_Tp>& __ia)
-        : _M_size (__ia._M_sz), _M_data (new _Tp[__ia._M_sz])
-{ __valarray_copy (__ia._M_array, __ia._M_index, 
-                   _Array<_Tp>(_M_data), _M_size); }
+  : _M_size (__ia._M_sz), _M_data(__valarray_get_storage<_Tp>(__ia._M_size))
+{
+  __valarray_copy_construct
+    (__ia._M_array, __ia._M_index, _Array<_Tp>(_M_data), _M_size);
+}
 
 template<typename _Tp> template<class _Dom>
 inline valarray<_Tp>::valarray (const _Expr<_Dom, _Tp>& __e)
-        : _M_size (__e.size ()), _M_data (new _Tp[_M_size])
-{ __valarray_copy (__e, _M_size, _Array<_Tp>(_M_data)); }
+  : _M_size (__e.size ()), _M_data (__valarray_get_storage<_Tp>(_M_size))
+{ __valarray_copy_construct (__e, _M_size, _Array<_Tp>(_M_data)); }
 
 template<typename _Tp>
-inline valarray<_Tp>::~valarray () { delete[] _M_data; }
+inline valarray<_Tp>::~valarray ()
+{
+  __valarray_destroy_elements(_M_data, _M_data + _M_size);
+  __valarray_release_storage(_M_data);
+}
 
 template<typename _Tp>
 inline valarray<_Tp>&
@@ -472,14 +484,7 @@ template<class _Tp>
 inline _Tp
 valarray<_Tp>::sum () const
 {
-    return accumulate (_M_data, _M_data + _M_size, _Tp ());
-}
-
-template<typename _Tp>
-inline _Tp
-valarray<_Tp>::product () const
-{
-    return accumulate (_M_data, _M_data+_M_size, _Tp(1), multiplies<_Tp> ());
+  return __valarray_sum(_M_data, _M_data + _M_size);
 }
 
 template <class _Tp>
@@ -488,18 +493,18 @@ valarray<_Tp>::shift (int __n) const
 {
     _Tp* const __a = static_cast<_Tp*> (alloca (sizeof(_Tp) * _M_size));
     if (! __n)                          // __n == 0: no shift
-        __valarray_copy (_M_data, _M_size, __a);
+        __valarray_copy_construct (_M_data, _M_size, __a);
     else if (__n > 0) {                  // __n > 0: shift left
         if (__n > _M_size)
-            __valarray_fill(__a, __n, _Tp());
+            __valarray_default_construct(__a, __a + __n);
         else {
-            __valarray_copy (_M_data+__n, _M_size-__n, __a);
-            __valarray_fill (__a+_M_size-__n, __n, _Tp());
+            __valarray_copy_construct (_M_data+__n, _M_size-__n, __a);
+            __valarray_default_construct (__a+_M_size-__n, __a + _M_size);
         }
     }
     else {                             // __n < 0: shift right
-        __valarray_copy (_M_data, _M_size+__n, __a-__n);
-        __valarray_fill(__a, -__n, _Tp());
+      __valarray_copy_construct (_M_data, _M_data+_M_size+__n, __a-__n);
+        __valarray_default_construct(__a, __a-__n);
     }
     return valarray<_Tp> (__a, _M_size);
 }
@@ -509,15 +514,17 @@ inline valarray<_Tp>
 valarray<_Tp>::cshift (int __n) const
 {
     _Tp* const __a = static_cast<_Tp*> (alloca (sizeof(_Tp) * _M_size));
-    if (! __n)                          // __n == 0: no cshift
-        __valarray_copy(_M_data, _M_size, __a);
+    if (__n == 0)                          // __n == 0: no cshift
+      __valarray_copy_construct(_M_data, _M_data + _M_size, __a);
     else if (__n > 0) {                 // __n > 0: cshift left
-        __valarray_copy (_M_data, __n, __a + _M_size-__n);
-        __valarray_copy (_M_data + __n, _M_size-__n, __a);
+      __valarray_copy_construct (_M_data, _M_data + __n, __a + _M_size-__n);
+      __valarray_copy_construct (_M_data + __n, _M_data + _M_size, __a);
     }
     else {                            // __n < 0: cshift right
-        __valarray_copy (_M_data + _M_size + __n, -__n, __a);
-        __valarray_copy (_M_data, _M_size + __n, __a - __n);
+      __valarray_copy_construct
+        (_M_data + _M_size + __n, _M_data + _M_size, __a);
+        __valarray_copy_construct
+          (_M_data, _M_data + _M_size + __n, __a - __n);
     }
     return valarray<_Tp> (__a, _M_size);
 }
@@ -526,12 +533,15 @@ template <class _Tp>
 inline void
 valarray<_Tp>::resize (size_t __n, _Tp __c)
 {
-    if (_M_size != __n) {
-        delete[] _M_data;
-        _M_size = __n;
-        _M_data = new _Tp[_M_size];
-    }
-    __valarray_fill (_M_data, _M_size, __c);
+  // this is so to make valarray<valarray<T> > work
+  // even though it is not required by the standard.
+  __valarray_destroy_elements(_M_data, _M_data + _M_size);
+  if (_M_size != __n) {
+    __valarray_release_storage(_M_data);
+    _M_size = __n;
+    _M_data = __valarray_get_storage<_Tp>(__n);
+  }
+  __valarray_fill_construct (_M_data, _M_data + _M_size, __c);
 }
 
 template<typename _Tp>
index a0b5818..eb66463 100644 (file)
 
 #include <cstdlib>
 #include <cstring>
+#include <std/cpp_type_traits.h>
 
 extern "C++" {
 
 //
 // Helper functions on raw pointers
 //
-
-// fill plain array __a[<__n>] with __t
-template<typename _Tp>
-inline void
-__valarray_fill (_Tp* __restrict__ __a, size_t __n, const _Tp& __t)
-{ while (__n--) *__a++ = __t; }
-
-// fill strided array __a[<__n-1 : __s>] with __t
-template<typename _Tp>
-inline void
-__valarray_fill (_Tp* __restrict__ __a, size_t __n,
-                 size_t __s, const _Tp& __t)
-{ for (size_t __i=0; __i<__n; ++__i, __a+=__s) *__a = __t; }
-
-// fill indirect array __a[__i[<__n>]] with __i
-template<typename _Tp>
-inline void
-__valarray_fill(_Tp* __restrict__ __a, const size_t* __restrict__ __i,
-                size_t __n, const _Tp& __t)
-{ for (size_t __j=0; __j<__n; ++__j, ++__i) __a[*__i] = __t; }
-
-// copy plain array __a[<__n>] in __b[<__n>]
-template<typename _Tp>
-inline void
-__valarray_copy (const _Tp* __restrict__ __a, size_t __n,
-                 _Tp* __restrict__ __b)
-{ memcpy (__b, __a, __n * sizeof(_Tp)); }
+  
+  inline void*
+  __valarray_get_memory(size_t __n)
+  { return operator new(__n); }
+
+  template<typename _Tp>
+  inline _Tp*__restrict__
+  __valarray_get_storage(size_t __n)
+  {
+    return static_cast<_Tp*__restrict__>
+      (__valarray_get_memory(__n * sizeof(_Tp)));
+  }
+  
+  // Return memory to the system
+  inline void
+  __valarray_release_storage(void* __p)
+  { operator delete(__p); }
+
+  // Turn a raw-memory into an array of _Tp filled with _Tp()
+  // This is required in 'valarray<T> v(n);'
+  template<typename _Tp, bool>
+  struct _Array_default_ctor
+  {
+    // Please note that this isn't exception safe.  But
+    // valarrays aren't required to be exception safe.
+    inline static void
+    _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
+    { while (__b != __e) new(__b++) _Tp(); }
+  };
+
+  template<typename _Tp>
+  struct _Array_default_ctor<_Tp, true>
+  {
+    // For fundamental types, it suffices to say 'memset()'
+    inline static void
+    _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
+    { memset(__b, 0, (__e - __b)*sizeof(_Tp)); }
+  };
+
+  template<typename _Tp>
+  inline void
+  __valarray_default_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
+  {
+    _Array_default_ctor<_Tp, __is_fundamental<_Tp>::_M_type>::
+      _S_do_it(__b, __e);
+  }
+    
+  // Turn a raw-memory into an array of _Tp filled with __t
+  // This is the required in valarray<T> v(n, t).  Also
+  // used in valarray<>::resize().
+  template<typename _Tp, bool>
+  struct _Array_init_ctor
+  {
+    // Please note that this isn't exception safe.  But
+    // valarrays aren't required to be exception safe.
+    inline static void
+    _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e, const _Tp __t)
+    { while (__b != __e) new(__b++) _Tp(__t); }
+  };
+
+  template<typename _Tp>
+  struct _Array_init_ctor<_Tp, true>
+  {
+    inline static void
+    _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e,  const _Tp __t)
+    { while (__b != __e) *__b++ = __t; }
+  };
+
+  template<typename _Tp>
+  inline void
+  __valarray_fill_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e,
+                            const _Tp __t)
+  {
+    _Array_init_ctor<_Tp, __is_fundamental<_Tp>::_M_type>::
+      _S_do_it(__b, __e, __t);
+  }
+
+  //
+  // copy-construct raw array [__o, *) from plain array [__b, __e)
+  // We can't just say 'memcpy()'
+  //
+  template<typename _Tp, bool>
+  struct _Array_copy_ctor
+  {
+    // Please note that this isn't exception safe.  But
+    // valarrays aren't required to be exception safe.
+    inline static void
+    _S_do_it(const _Tp* __restrict__ __b, const _Tp* __restrict__ __e,
+             _Tp* __restrict__ __o)
+    { while (__b != __e) new(__o++) _Tp(*__b++); }
+  };
+
+  template<typename _Tp>
+  struct _Array_copy_ctor<_Tp, true>
+  {
+    inline static void
+    _S_do_it(const _Tp* __restrict__ __b, const _Tp* __restrict__ __e,
+             _Tp* __restrict__ __o)
+    { memcpy(__o, __b, (__e - __b)*sizeof(_Tp)); }
+  };
+
+  template<typename _Tp>
+  inline void
+  __valarray_copy_construct(const _Tp* __restrict__ __b,
+                            const _Tp* __restrict__ __e,
+                            _Tp* __restrict__ __o)
+  {
+    _Array_copy_ctor<_Tp, __is_fundamental<_Tp>::_M_type>::
+      _S_do_it(__b, __e, __o);
+  }
+
+  // copy-construct raw array [__o, *) from strided array __a[<__n : __s>]
+  template<typename _Tp>
+  inline void
+  __valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n,
+                             size_t __s, _Tp* __restrict__ __o)
+  {
+    if (__is_fundamental<_Tp>::_M_type)
+      while (__n--) { *__o++ = *__a; __a += __s; }
+    else
+      while (__n--) { new(__o++) _Tp(*__a);  __a += __s; }
+  }
+
+  // copy-construct raw array [__o, *) from indexed array __a[__i[<__n>]]
+  template<typename _Tp>
+  inline void
+  __valarray_copy_construct (const _Tp* __restrict__ __a,
+                             const size_t* __restrict__ __i,
+                             _Tp* __restrict__ __o, size_t __n)
+  {
+    if (__is_fundamental<_Tp>::_M_type)
+      while (__n--) *__o++ = __a[*__i++];
+    else
+      while (__n--) new (__o++) _Tp(__a[*__i++]);
+  }
+
+  // Do the necessary cleanup when we're done with arrays.
+  template<typename _Tp>
+  inline void
+  __valarray_destroy_elements(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
+  {
+    if (!__is_fundamental<_Tp>::_M_type)
+      while (__b != __e) { __b->~_Tp(); ++__b; }
+  }
+
+  
+  // fill plain array __a[<__n>] with __t
+  template<typename _Tp>
+  inline void
+  __valarray_fill (_Tp* __restrict__ __a, size_t __n, const _Tp& __t)
+  { while (__n--) *__a++ = __t; }
+  
+  // fill strided array __a[<__n-1 : __s>] with __t
+  template<typename _Tp>
+  inline void
+  __valarray_fill (_Tp* __restrict__ __a, size_t __n,
+                   size_t __s, const _Tp& __t)
+  { for (size_t __i=0; __i<__n; ++__i, __a+=__s) *__a = __t; }
+  
+  // fill indirect array __a[__i[<__n>]] with __i
+  template<typename _Tp>
+  inline void
+  __valarray_fill(_Tp* __restrict__ __a, const size_t* __restrict__ __i,
+                  size_t __n, const _Tp& __t)
+  { for (size_t __j=0; __j<__n; ++__j, ++__i) __a[*__i] = __t; }
+  
+  // copy plain array __a[<__n>] in __b[<__n>]
+  // For non-fundamental types, it is wrong to say 'memcpy()'
+  template<typename _Tp, bool>
+  struct _Array_copier
+  {
+    inline static void
+    _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b)
+    { while (__n--) *__b++ = *__a++; }      
+  };
+  
+  template<typename _Tp>
+  struct _Array_copier<_Tp, true>
+  {
+    inline static void
+    _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b)
+    { memcpy (__b, __a, __n * sizeof (_Tp)); }
+  };
+
+  template<typename _Tp>
+  inline void
+  __valarray_copy (const _Tp* __restrict__ __a, size_t __n,
+                   _Tp* __restrict__ __b)
+  {
+    _Array_copier<_Tp, __is_fundamental<_Tp>::_M_type>::
+      _S_do_it(__a, __n, __b);
+  }
 
 // copy strided array __a[<__n : __s>] in plain __b[<__n>]
 template<typename _Tp>
@@ -97,6 +263,34 @@ __valarray_copy (const _Tp* __restrict__ __a, size_t __n,
                  _Tp* __restrict__ __b, const size_t* __restrict__ __i)
 { for (size_t __j=0; __j<__n; ++__j, ++__a, ++__i) __b[*__i] = *__a; }
 
+  //
+  // Compute the sum of elements in range [__f, __l)
+  // This is a naive algorithm.  It suffers from cancelling.
+  // In the future try to specialize
+  // for _Tp = float, double, long double using a more accurate
+  // algorithm.
+  //
+  template<typename _Tp>
+  inline _Tp
+  __valarray_sum(const _Tp* __restrict__ __f, const _Tp* __restrict__ __l)
+  {
+    _Tp __r = _Tp();
+    while (__f != __l) __r = __r + *__f++;
+    return __r;
+  }
+
+  // Compute the product of all elements in range [__f, __l)
+  template<typename _Tp>
+  _Tp
+  __valarray_product(const _Tp* __restrict__ __f,
+                     const _Tp* __restrict__ __l)
+  {
+    _Tp __r = _Tp(1);
+    while (__f != __l) __r = __r * *__f++;
+    return __r;
+  }
+  
+
 //
 // Helper class _Array, first layer of valarray abstraction.
 // All operations on valarray should be forwarded to this class
@@ -110,7 +304,6 @@ template<typename _Tp> struct _Array {
     explicit _Array (const valarray<_Tp>&);
     _Array (const _Tp* __restrict__, size_t);
     
-    void free_data() const;
     _Tp* begin () const;
     
     _Tp* const __restrict__ _M_data;
@@ -161,7 +354,9 @@ __valarray_copy (_Array<_Tp> __a, size_t __n, _Array<_Tp> __b,
 
 template<typename _Tp>
 inline
-_Array<_Tp>::_Array (size_t __n) : _M_data (new _Tp[__n]) {}
+_Array<_Tp>::_Array (size_t __n)
+  : _M_data (__valarray_get_storage<_Tp>(__n))
+{ __valarray_default_construct(_M_data, _M_data + __n); }
 
 template<typename _Tp>
 inline
@@ -174,11 +369,8 @@ inline _Array<_Tp>::_Array (const valarray<_Tp>& __v)
 template<typename _Tp>
 inline
 _Array<_Tp>::_Array (const _Tp* __restrict__ __b, size_t __s) 
-        : _M_data (new _Tp[__s]) { __valarray_copy (__b, __s, _M_data); }
-
-template<typename _Tp>
-inline void
-_Array<_Tp>::free_data() const { delete[] _M_data; }
+  : _M_data (__valarray_get_storage<_Tp>(__s ))
+{ __valarray_copy_construct(__b, __s, _M_data); }
 
 template<typename _Tp>
 inline _Tp*
index 5e7fe0c..5de4e92 100644 (file)
@@ -1,9 +1,5 @@
 #include <std/std_valarray.h>
 
-// Some Explicit Instanciations.
-template class multiplies<size_t>;
-template size_t accumulate(size_t*, size_t*, size_t, multiplies<size_t>);
-
 template void
    __valarray_fill(size_t* __restrict__, size_t, const size_t&);
 
@@ -15,7 +11,19 @@ template valarray<size_t>::~valarray();
 template valarray<size_t>::valarray(const valarray<size_t>&);
 template size_t valarray<size_t>::size() const;
 template size_t& valarray<size_t>::operator[](size_t);
-template size_t valarray<size_t>::product() const;
+
+
+inline size_t
+__valarray_product(const valarray<size_t>& __a)
+{
+  // XXX: This ugly cast is necessary because
+  //      valarray::operator[]() const returns a VALUE!
+  //      Try to get the committee to correct that gross error.
+  typedef const size_t* __restrict__ _Tp;
+  const size_t __n = __a.size();
+  valarray<size_t>& __t = const_cast<valarray<size_t>&>(__a);
+  return __valarray_product(&__t[0], &__t[0] + __n);
+}
 
 
 void __gslice_to_index(size_t __o, const valarray<size_t>& __l,
@@ -43,7 +51,7 @@ void __gslice_to_index(size_t __o, const valarray<size_t>& __l,
 _Indexer::_Indexer(size_t __o, const valarray<size_t>& __l,
                    const valarray<size_t>& __s)
         : _M_count(1), _M_start(__o), _M_size(__l), _M_stride(__s),
-          _M_index(__l.size() ? __l.product() : 0)
+          _M_index(__l.size() ? __valarray_product(__l) : 0)
 { __gslice_to_index(__o, __l, __s, _M_index); }