From: Gabriel Dos Reis Date: Sat, 15 Jul 2000 21:54:06 +0000 (+0000) Subject: valarray_array.h (__valarray_get_memory, [...]): New functions. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5b2ff385d530365adf4fab64266ac30bfe5d0311;p=gcc.git valarray_array.h (__valarray_get_memory, [...]): New functions. 2000-07-15 Gabriel Dos Reis * 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. From-SVN: r35055 --- diff --git a/libstdc++/ChangeLog b/libstdc++/ChangeLog index d09fc3d7b6f..04eac45b233 100644 --- a/libstdc++/ChangeLog +++ b/libstdc++/ChangeLog @@ -1,3 +1,34 @@ +2000-07-15 Gabriel Dos Reis + + * 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 * 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 index 00000000000..1a065b4efa8 --- /dev/null +++ b/libstdc++/std/cpp_type_traits.h @@ -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 + +#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 . 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 . +// +// -- Gaby (dosreis@cmla.ens-cachan.fr) 2000-03-06. +// + +extern "C++" { + template + struct __is_void + { + enum + { + _M_type = 0 + }; + }; + + template<> + struct __is_void + { + enum + { + _M_type = 1 + }; + }; + + // + // Integer types + // + template + 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 + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer + { + enum + { + _M_type = 1 + }; + }; + +# if 0 + template<> + struct __is_integer + { + enum + { + _M_type = 1 + }; + }; +# endif + + template<> + struct __is_integer + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer + { + enum + { + _M_type = 1 + }; + }; + +# if 0 + template<> + struct __is_integer + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer + { + enum + { + _M_type = 1 + }; + }; +# endif + + // + // Floating point types + // + template + struct __is_floating + { + enum + { + _M_type = 0 + }; + }; + + // three specializations (float, double and 'long double') + template<> + struct __is_floating + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_floating + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_floating + { + enum + { + _M_type = 1 + }; + }; + + // + // An arithmetic type is an integer type or a floating point type + // + template + 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 + 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 + struct __is_pod + { + enum + { + _M_type = __is_fundamental<_Tp>::_M_type + }; + }; +} // extern "C++" + +#endif //_CPP_BITS_CPP_TYPE_TRAITS_H + + + + + + + diff --git a/libstdc++/std/std_valarray.h b/libstdc++/std/std_valarray.h index 0e47c776950..d32412ce877 100644 --- a/libstdc++/std/std_valarray.h +++ b/libstdc++/std/std_valarray.h @@ -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 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 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 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 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 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 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(__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(__ga._M_index), + _Array<_Tp>(_M_data), _M_size); +} template 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 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 template 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 -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 inline valarray<_Tp>& @@ -472,14 +484,7 @@ template inline _Tp valarray<_Tp>::sum () const { - return accumulate (_M_data, _M_data + _M_size, _Tp ()); -} - -template -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 @@ -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 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 > 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 diff --git a/libstdc++/std/valarray_array.h b/libstdc++/std/valarray_array.h index a0b5818fd8b..eb66463708e 100644 --- a/libstdc++/std/valarray_array.h +++ b/libstdc++/std/valarray_array.h @@ -34,39 +34,205 @@ #include #include +#include extern "C++" { // // Helper functions on raw pointers // - -// fill plain array __a[<__n>] with __t -template -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 -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 -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 -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 + 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 v(n);' + template + 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 + 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 + 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 v(n, t). Also + // used in valarray<>::resize(). + template + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + struct _Array_copier + { + inline static void + _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b) + { while (__n--) *__b++ = *__a++; } + }; + + template + 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 + 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 @@ -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 + 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 + _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 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 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 inline @@ -174,11 +369,8 @@ inline _Array<_Tp>::_Array (const valarray<_Tp>& __v) template inline _Array<_Tp>::_Array (const _Tp* __restrict__ __b, size_t __s) - : _M_data (new _Tp[__s]) { __valarray_copy (__b, __s, _M_data); } - -template -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 inline _Tp* diff --git a/libstdc++/valarray.cc b/libstdc++/valarray.cc index 5e7fe0cf05f..5de4e929982 100644 --- a/libstdc++/valarray.cc +++ b/libstdc++/valarray.cc @@ -1,9 +1,5 @@ #include -// Some Explicit Instanciations. -template class multiplies; -template size_t accumulate(size_t*, size_t*, size_t, multiplies); - template void __valarray_fill(size_t* __restrict__, size_t, const size_t&); @@ -15,7 +11,19 @@ template valarray::~valarray(); template valarray::valarray(const valarray&); template size_t valarray::size() const; template size_t& valarray::operator[](size_t); -template size_t valarray::product() const; + + +inline size_t +__valarray_product(const valarray& __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& __t = const_cast&>(__a); + return __valarray_product(&__t[0], &__t[0] + __n); +} void __gslice_to_index(size_t __o, const valarray& __l, @@ -43,7 +51,7 @@ void __gslice_to_index(size_t __o, const valarray& __l, _Indexer::_Indexer(size_t __o, const valarray& __l, const valarray& __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); }