1132720Skan// The template and inlines for the -*- C++ -*- internal _Meta class.
2132720Skan
3169691Skan// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
4169691Skan// Free Software Foundation, Inc.
5132720Skan//
6132720Skan// This file is part of the GNU ISO C++ Library.  This library is free
7132720Skan// software; you can redistribute it and/or modify it under the
8132720Skan// terms of the GNU General Public License as published by the
9132720Skan// Free Software Foundation; either version 2, or (at your option)
10132720Skan// any later version.
11132720Skan
12132720Skan// This library is distributed in the hope that it will be useful,
13132720Skan// but WITHOUT ANY WARRANTY; without even the implied warranty of
14132720Skan// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15132720Skan// GNU General Public License for more details.
16132720Skan
17132720Skan// You should have received a copy of the GNU General Public License along
18132720Skan// with this library; see the file COPYING.  If not, write to the Free
19169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20132720Skan// USA.
21132720Skan
22132720Skan// As a special exception, you may use this file as part of a free software
23132720Skan// library without restriction.  Specifically, if other files instantiate
24132720Skan// templates or use macros or inline functions from this file, or you compile
25132720Skan// this file and link it with other files to produce an executable, this
26132720Skan// file does not by itself cause the resulting executable to be covered by
27132720Skan// the GNU General Public License.  This exception does not however
28132720Skan// invalidate any other reasons why the executable file might be covered by
29132720Skan// the GNU General Public License.
30132720Skan
31169691Skan/** @file valarray_before.h
32132720Skan *  This is an internal header file, included by other library headers.
33132720Skan *  You should not attempt to use it directly.
34132720Skan */
35132720Skan
36169691Skan// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@cmla.ens-cachan.fr>
37169691Skan
38132720Skan#ifndef _VALARRAY_BEFORE_H
39132720Skan#define _VALARRAY_BEFORE_H 1
40132720Skan
41132720Skan#pragma GCC system_header
42132720Skan
43132720Skan#include <bits/slice_array.h>
44132720Skan
45169691Skan_GLIBCXX_BEGIN_NAMESPACE(std)
46169691Skan
47132720Skan  //
48132720Skan  // Implementing a loosened valarray return value is tricky.
49132720Skan  // First we need to meet 26.3.1/3: we should not add more than
50132720Skan  // two levels of template nesting. Therefore we resort to template
51132720Skan  // template to "flatten" loosened return value types.
52132720Skan  // At some point we use partial specialization to remove one level
53132720Skan  // template nesting due to _Expr<>
54132720Skan  //
55132720Skan
56132720Skan  // This class is NOT defined. It doesn't need to.
57132720Skan  template<typename _Tp1, typename _Tp2> class _Constant;
58132720Skan
59132720Skan  // Implementations of unary functions applied to valarray<>s.
60132720Skan  // I use hard-coded object functions here instead of a generic
61132720Skan  // approach like pointers to function:
62132720Skan  //    1) correctness: some functions take references, others values.
63132720Skan  //       we can't deduce the correct type afterwards.
64132720Skan  //    2) efficiency -- object functions can be easily inlined
65132720Skan  //    3) be Koenig-lookup-friendly
66132720Skan
67132720Skan  struct __abs
68132720Skan  {
69132720Skan    template<typename _Tp>
70169691Skan      _Tp operator()(const _Tp& __t) const
71169691Skan      { return abs(__t); }
72132720Skan  };
73132720Skan
74132720Skan  struct __cos
75132720Skan  {
76132720Skan    template<typename _Tp>
77169691Skan      _Tp operator()(const _Tp& __t) const
78169691Skan      { return cos(__t); }
79132720Skan  };
80132720Skan
81132720Skan  struct __acos
82132720Skan  {
83132720Skan    template<typename _Tp>
84169691Skan      _Tp operator()(const _Tp& __t) const
85169691Skan      { return acos(__t); }
86132720Skan  };
87132720Skan
88132720Skan  struct __cosh
89132720Skan  {
90132720Skan    template<typename _Tp>
91169691Skan      _Tp operator()(const _Tp& __t) const
92169691Skan      { return cosh(__t); }
93132720Skan  };
94132720Skan
95132720Skan  struct __sin
96132720Skan  {
97132720Skan    template<typename _Tp>
98169691Skan      _Tp operator()(const _Tp& __t) const
99169691Skan      { return sin(__t); }
100132720Skan  };
101132720Skan
102132720Skan  struct __asin
103132720Skan  {
104132720Skan    template<typename _Tp>
105169691Skan      _Tp operator()(const _Tp& __t) const
106169691Skan      { return asin(__t); }
107132720Skan  };
108132720Skan
109132720Skan  struct __sinh
110132720Skan  {
111132720Skan    template<typename _Tp>
112169691Skan      _Tp operator()(const _Tp& __t) const
113169691Skan      { return sinh(__t); }
114132720Skan  };
115132720Skan
116132720Skan  struct __tan
117132720Skan  {
118132720Skan    template<typename _Tp>
119169691Skan      _Tp operator()(const _Tp& __t) const
120169691Skan      { return tan(__t); }
121132720Skan  };
122132720Skan
123132720Skan  struct __atan
124132720Skan  {
125132720Skan    template<typename _Tp>
126169691Skan      _Tp operator()(const _Tp& __t) const
127169691Skan      { return atan(__t); }
128132720Skan  };
129132720Skan
130132720Skan  struct __tanh
131132720Skan  {
132132720Skan    template<typename _Tp>
133169691Skan      _Tp operator()(const _Tp& __t) const
134169691Skan      { return tanh(__t); }
135132720Skan  };
136132720Skan
137132720Skan  struct __exp
138132720Skan  {
139132720Skan    template<typename _Tp>
140169691Skan      _Tp operator()(const _Tp& __t) const
141169691Skan      { return exp(__t); }
142132720Skan  };
143132720Skan
144132720Skan  struct __log
145132720Skan  {
146132720Skan    template<typename _Tp>
147169691Skan      _Tp operator()(const _Tp& __t) const
148169691Skan      { return log(__t); }
149132720Skan  };
150132720Skan
151132720Skan  struct __log10
152132720Skan  {
153132720Skan    template<typename _Tp>
154169691Skan      _Tp operator()(const _Tp& __t) const
155169691Skan      { return log10(__t); }
156132720Skan  };
157132720Skan
158132720Skan  struct __sqrt
159132720Skan  {
160132720Skan    template<typename _Tp>
161169691Skan      _Tp operator()(const _Tp& __t) const
162169691Skan      { return sqrt(__t); }
163132720Skan  };
164132720Skan
165132720Skan  // In the past, we used to tailor operator applications semantics
166132720Skan  // to the specialization of standard function objects (i.e. plus<>, etc.)
167132720Skan  // That is incorrect.  Therefore we provide our own surrogates.
168132720Skan
169132720Skan  struct __unary_plus
170132720Skan  {
171132720Skan    template<typename _Tp>
172169691Skan      _Tp operator()(const _Tp& __t) const
173169691Skan      { return +__t; }
174132720Skan  };
175132720Skan
176132720Skan  struct __negate
177132720Skan  {
178132720Skan    template<typename _Tp>
179169691Skan      _Tp operator()(const _Tp& __t) const
180169691Skan      { return -__t; }
181132720Skan  };
182132720Skan
183132720Skan  struct __bitwise_not
184132720Skan  {
185132720Skan    template<typename _Tp>
186169691Skan      _Tp operator()(const _Tp& __t) const
187169691Skan      { return ~__t; }
188132720Skan  };
189132720Skan
190132720Skan  struct __plus
191132720Skan  {
192132720Skan    template<typename _Tp>
193132720Skan      _Tp operator()(const _Tp& __x, const _Tp& __y) const
194132720Skan      { return __x + __y; }
195132720Skan  };
196132720Skan
197132720Skan  struct __minus
198132720Skan  {
199132720Skan    template<typename _Tp>
200132720Skan      _Tp operator()(const _Tp& __x, const _Tp& __y) const
201132720Skan      { return __x - __y; }
202132720Skan  };
203132720Skan
204132720Skan  struct __multiplies
205132720Skan  {
206132720Skan    template<typename _Tp>
207132720Skan      _Tp operator()(const _Tp& __x, const _Tp& __y) const
208132720Skan      { return __x * __y; }
209132720Skan  };
210132720Skan
211132720Skan  struct __divides
212132720Skan  {
213132720Skan    template<typename _Tp>
214132720Skan      _Tp operator()(const _Tp& __x, const _Tp& __y) const
215132720Skan      { return __x / __y; }
216132720Skan  };
217132720Skan
218132720Skan  struct __modulus
219132720Skan  {
220132720Skan    template<typename _Tp>
221132720Skan      _Tp operator()(const _Tp& __x, const _Tp& __y) const
222132720Skan      { return __x % __y; }
223132720Skan  };
224132720Skan
225132720Skan  struct __bitwise_xor
226132720Skan  {
227132720Skan    template<typename _Tp>
228132720Skan      _Tp operator()(const _Tp& __x, const _Tp& __y) const
229132720Skan      { return __x ^ __y; }
230132720Skan  };
231132720Skan
232132720Skan  struct __bitwise_and
233132720Skan  {
234132720Skan    template<typename _Tp>
235132720Skan      _Tp operator()(const _Tp& __x, const _Tp& __y) const
236132720Skan      { return __x & __y; }
237132720Skan  };
238132720Skan
239132720Skan  struct __bitwise_or
240132720Skan  {
241132720Skan    template<typename _Tp>
242132720Skan      _Tp operator()(const _Tp& __x, const _Tp& __y) const
243132720Skan      { return __x | __y; }
244132720Skan  };
245132720Skan
246132720Skan  struct __shift_left
247132720Skan  {
248132720Skan    template<typename _Tp>
249132720Skan      _Tp operator()(const _Tp& __x, const _Tp& __y) const
250132720Skan      { return __x << __y; }
251132720Skan  };
252132720Skan
253132720Skan  struct __shift_right
254132720Skan  {
255132720Skan    template<typename _Tp>
256132720Skan      _Tp operator()(const _Tp& __x, const _Tp& __y) const
257132720Skan      { return __x >> __y; }
258132720Skan  };
259132720Skan
260132720Skan  struct __logical_and
261132720Skan  {
262132720Skan    template<typename _Tp>
263132720Skan      bool operator()(const _Tp& __x, const _Tp& __y) const
264132720Skan      { return __x && __y; }
265132720Skan  };
266132720Skan
267132720Skan  struct __logical_or
268132720Skan  {
269132720Skan    template<typename _Tp>
270132720Skan      bool operator()(const _Tp& __x, const _Tp& __y) const
271132720Skan      { return __x || __y; }
272132720Skan  };
273132720Skan
274132720Skan  struct __logical_not
275132720Skan  {
276132720Skan    template<typename _Tp>
277132720Skan      bool operator()(const _Tp& __x) const { return !__x; }
278132720Skan  };
279132720Skan
280132720Skan  struct __equal_to
281132720Skan  {
282132720Skan    template<typename _Tp>
283132720Skan      bool operator()(const _Tp& __x, const _Tp& __y) const
284132720Skan      { return __x == __y; }
285132720Skan  };
286132720Skan
287132720Skan  struct __not_equal_to
288132720Skan  {
289132720Skan    template<typename _Tp>
290132720Skan      bool operator()(const _Tp& __x, const _Tp& __y) const
291132720Skan      { return __x != __y; }
292132720Skan  };
293132720Skan
294132720Skan  struct __less
295132720Skan  {
296132720Skan    template<typename _Tp>
297132720Skan      bool operator()(const _Tp& __x, const _Tp& __y) const
298132720Skan      { return __x < __y; }
299132720Skan  };
300132720Skan
301132720Skan  struct __greater
302132720Skan  {
303132720Skan    template<typename _Tp>
304132720Skan      bool operator()(const _Tp& __x, const _Tp& __y) const
305132720Skan      { return __x > __y; }
306132720Skan  };
307132720Skan
308132720Skan  struct __less_equal
309132720Skan  {
310132720Skan    template<typename _Tp>
311132720Skan      bool operator()(const _Tp& __x, const _Tp& __y) const
312132720Skan      { return __x <= __y; }
313132720Skan  };
314132720Skan
315132720Skan  struct __greater_equal
316132720Skan  {
317132720Skan    template<typename _Tp>
318132720Skan      bool operator()(const _Tp& __x, const _Tp& __y) const
319132720Skan      { return __x >= __y; }
320132720Skan  };
321132720Skan
322132720Skan  // The few binary functions we miss.
323132720Skan  struct __atan2
324132720Skan  {
325132720Skan    template<typename _Tp>
326132720Skan      _Tp operator()(const _Tp& __x, const _Tp& __y) const
327132720Skan      { return atan2(__x, __y); }
328132720Skan  };
329132720Skan
330132720Skan  struct __pow
331132720Skan  {
332132720Skan    template<typename _Tp>
333132720Skan      _Tp operator()(const _Tp& __x, const _Tp& __y) const
334132720Skan      { return pow(__x, __y); }
335132720Skan  };
336132720Skan
337132720Skan
338132720Skan  // We need these bits in order to recover the return type of
339132720Skan  // some functions/operators now that we're no longer using
340132720Skan  // function templates.
341132720Skan  template<typename, typename _Tp>
342132720Skan    struct __fun
343132720Skan    {
344132720Skan      typedef _Tp result_type;
345132720Skan    };
346132720Skan
347132720Skan  // several specializations for relational operators.
348132720Skan  template<typename _Tp>
349132720Skan    struct __fun<__logical_not, _Tp>
350132720Skan    {
351132720Skan      typedef bool result_type;
352132720Skan    };
353132720Skan
354132720Skan  template<typename _Tp>
355132720Skan    struct __fun<__logical_and, _Tp>
356132720Skan    {
357132720Skan      typedef bool result_type;
358132720Skan    };
359132720Skan
360132720Skan  template<typename _Tp>
361132720Skan    struct __fun<__logical_or, _Tp>
362132720Skan    {
363132720Skan      typedef bool result_type;
364132720Skan    };
365132720Skan
366132720Skan  template<typename _Tp>
367132720Skan    struct __fun<__less, _Tp>
368132720Skan    {
369132720Skan      typedef bool result_type;
370132720Skan    };
371132720Skan
372132720Skan  template<typename _Tp>
373132720Skan    struct __fun<__greater, _Tp>
374132720Skan    {
375132720Skan      typedef bool result_type;
376132720Skan    };
377132720Skan
378132720Skan  template<typename _Tp>
379132720Skan    struct __fun<__less_equal, _Tp>
380132720Skan    {
381132720Skan      typedef bool result_type;
382132720Skan    };
383132720Skan
384132720Skan  template<typename _Tp>
385132720Skan    struct __fun<__greater_equal, _Tp>
386132720Skan    {
387132720Skan      typedef bool result_type;
388132720Skan    };
389132720Skan
390132720Skan  template<typename _Tp>
391132720Skan    struct __fun<__equal_to, _Tp>
392132720Skan    {
393132720Skan      typedef bool result_type;
394132720Skan    };
395132720Skan
396132720Skan  template<typename _Tp>
397132720Skan    struct __fun<__not_equal_to, _Tp>
398132720Skan    {
399132720Skan      typedef bool result_type;
400132720Skan    };
401132720Skan
402169691Skan  //
403169691Skan  // Apply function taking a value/const reference closure
404169691Skan  //
405132720Skan
406132720Skan  template<typename _Dom, typename _Arg>
407132720Skan    class _FunBase
408132720Skan    {
409132720Skan    public:
410132720Skan      typedef typename _Dom::value_type value_type;
411132720Skan
412132720Skan      _FunBase(const _Dom& __e, value_type __f(_Arg))
413169691Skan      : _M_expr(__e), _M_func(__f) {}
414132720Skan
415132720Skan      value_type operator[](size_t __i) const
416132720Skan      { return _M_func (_M_expr[__i]); }
417132720Skan
418132720Skan      size_t size() const { return _M_expr.size ();}
419132720Skan
420132720Skan    private:
421169691Skan      const _Dom& _M_expr;
422169691Skan      value_type (*_M_func)(_Arg);
423132720Skan    };
424132720Skan
425132720Skan  template<class _Dom>
426132720Skan    struct _ValFunClos<_Expr,_Dom> : _FunBase<_Dom, typename _Dom::value_type>
427132720Skan    {
428132720Skan      typedef _FunBase<_Dom, typename _Dom::value_type> _Base;
429132720Skan      typedef typename _Base::value_type value_type;
430132720Skan      typedef value_type _Tp;
431132720Skan
432132720Skan      _ValFunClos(const _Dom& __e, _Tp __f(_Tp)) : _Base(__e, __f) {}
433132720Skan    };
434132720Skan
435132720Skan  template<typename _Tp>
436132720Skan    struct _ValFunClos<_ValArray,_Tp> : _FunBase<valarray<_Tp>, _Tp>
437132720Skan    {
438132720Skan      typedef _FunBase<valarray<_Tp>, _Tp> _Base;
439132720Skan      typedef _Tp value_type;
440132720Skan
441132720Skan      _ValFunClos(const valarray<_Tp>& __v, _Tp __f(_Tp)) : _Base(__v, __f) {}
442132720Skan    };
443132720Skan
444132720Skan  template<class _Dom>
445169691Skan    struct _RefFunClos<_Expr, _Dom>
446169691Skan    : _FunBase<_Dom, const typename _Dom::value_type&>
447132720Skan    {
448132720Skan      typedef _FunBase<_Dom, const typename _Dom::value_type&> _Base;
449132720Skan      typedef typename _Base::value_type value_type;
450132720Skan      typedef value_type _Tp;
451132720Skan
452132720Skan      _RefFunClos(const _Dom& __e, _Tp __f(const _Tp&))
453169691Skan      : _Base(__e, __f) {}
454132720Skan    };
455132720Skan
456132720Skan  template<typename _Tp>
457169691Skan    struct _RefFunClos<_ValArray, _Tp>
458169691Skan    : _FunBase<valarray<_Tp>, const _Tp&>
459132720Skan    {
460132720Skan      typedef _FunBase<valarray<_Tp>, const _Tp&> _Base;
461132720Skan      typedef _Tp value_type;
462132720Skan
463132720Skan      _RefFunClos(const valarray<_Tp>& __v, _Tp __f(const _Tp&))
464169691Skan      : _Base(__v, __f) {}
465132720Skan    };
466132720Skan
467132720Skan  //
468132720Skan  // Unary expression closure.
469132720Skan  //
470132720Skan
471132720Skan  template<class _Oper, class _Arg>
472132720Skan    class _UnBase
473132720Skan    {
474132720Skan    public:
475132720Skan      typedef typename _Arg::value_type _Vt;
476132720Skan      typedef typename __fun<_Oper, _Vt>::result_type value_type;
477132720Skan
478132720Skan      _UnBase(const _Arg& __e) : _M_expr(__e) {}
479132720Skan
480132720Skan      value_type operator[](size_t __i) const
481132720Skan      { return _Oper()(_M_expr[__i]); }
482132720Skan
483132720Skan      size_t size() const { return _M_expr.size(); }
484169691Skan
485132720Skan    private:
486132720Skan      const _Arg& _M_expr;
487132720Skan    };
488132720Skan
489132720Skan  template<class _Oper, class _Dom>
490169691Skan    struct _UnClos<_Oper, _Expr, _Dom>
491169691Skan    : _UnBase<_Oper, _Dom>
492132720Skan    {
493132720Skan      typedef _Dom _Arg;
494132720Skan      typedef _UnBase<_Oper, _Dom> _Base;
495132720Skan      typedef typename _Base::value_type value_type;
496132720Skan
497132720Skan      _UnClos(const _Arg& __e) : _Base(__e) {}
498132720Skan    };
499132720Skan
500132720Skan  template<class _Oper, typename _Tp>
501169691Skan    struct _UnClos<_Oper, _ValArray, _Tp>
502169691Skan    : _UnBase<_Oper, valarray<_Tp> >
503132720Skan    {
504132720Skan      typedef valarray<_Tp> _Arg;
505132720Skan      typedef _UnBase<_Oper, valarray<_Tp> > _Base;
506132720Skan      typedef typename _Base::value_type value_type;
507132720Skan
508132720Skan      _UnClos(const _Arg& __e) : _Base(__e) {}
509132720Skan    };
510132720Skan
511132720Skan
512132720Skan  //
513132720Skan  // Binary expression closure.
514132720Skan  //
515132720Skan
516132720Skan  template<class _Oper, class _FirstArg, class _SecondArg>
517132720Skan    class _BinBase
518132720Skan    {
519132720Skan    public:
520169691Skan      typedef typename _FirstArg::value_type _Vt;
521169691Skan      typedef typename __fun<_Oper, _Vt>::result_type value_type;
522132720Skan
523132720Skan      _BinBase(const _FirstArg& __e1, const _SecondArg& __e2)
524169691Skan      : _M_expr1(__e1), _M_expr2(__e2) {}
525132720Skan
526132720Skan      value_type operator[](size_t __i) const
527132720Skan      { return _Oper()(_M_expr1[__i], _M_expr2[__i]); }
528132720Skan
529132720Skan      size_t size() const { return _M_expr1.size(); }
530132720Skan
531132720Skan    private:
532132720Skan      const _FirstArg& _M_expr1;
533132720Skan      const _SecondArg& _M_expr2;
534132720Skan    };
535132720Skan
536132720Skan
537132720Skan  template<class _Oper, class _Clos>
538132720Skan    class _BinBase2
539132720Skan    {
540132720Skan    public:
541132720Skan      typedef typename _Clos::value_type _Vt;
542132720Skan      typedef typename __fun<_Oper, _Vt>::result_type value_type;
543132720Skan
544132720Skan      _BinBase2(const _Clos& __e, const _Vt& __t)
545169691Skan      : _M_expr1(__e), _M_expr2(__t) {}
546132720Skan
547132720Skan      value_type operator[](size_t __i) const
548132720Skan      { return _Oper()(_M_expr1[__i], _M_expr2); }
549132720Skan
550132720Skan      size_t size() const { return _M_expr1.size(); }
551132720Skan
552132720Skan    private:
553132720Skan      const _Clos& _M_expr1;
554132720Skan      const _Vt& _M_expr2;
555132720Skan    };
556132720Skan
557132720Skan  template<class _Oper, class _Clos>
558132720Skan    class _BinBase1
559132720Skan    {
560132720Skan    public:
561132720Skan      typedef typename _Clos::value_type _Vt;
562132720Skan      typedef typename __fun<_Oper, _Vt>::result_type value_type;
563132720Skan
564132720Skan      _BinBase1(const _Vt& __t, const _Clos& __e)
565169691Skan      : _M_expr1(__t), _M_expr2(__e) {}
566132720Skan
567132720Skan      value_type operator[](size_t __i) const
568132720Skan      { return _Oper()(_M_expr1, _M_expr2[__i]); }
569132720Skan
570132720Skan      size_t size() const { return _M_expr2.size(); }
571132720Skan
572132720Skan    private:
573132720Skan      const _Vt& _M_expr1;
574132720Skan      const _Clos& _M_expr2;
575132720Skan    };
576132720Skan
577132720Skan  template<class _Oper, class _Dom1, class _Dom2>
578132720Skan    struct _BinClos<_Oper, _Expr, _Expr, _Dom1, _Dom2>
579169691Skan    : _BinBase<_Oper, _Dom1, _Dom2>
580132720Skan    {
581169691Skan      typedef _BinBase<_Oper, _Dom1, _Dom2> _Base;
582132720Skan      typedef typename _Base::value_type value_type;
583132720Skan
584132720Skan      _BinClos(const _Dom1& __e1, const _Dom2& __e2) : _Base(__e1, __e2) {}
585132720Skan    };
586132720Skan
587132720Skan  template<class _Oper, typename _Tp>
588169691Skan    struct _BinClos<_Oper,_ValArray, _ValArray, _Tp, _Tp>
589169691Skan    : _BinBase<_Oper, valarray<_Tp>, valarray<_Tp> >
590132720Skan    {
591169691Skan      typedef _BinBase<_Oper, valarray<_Tp>, valarray<_Tp> > _Base;
592169691Skan      typedef typename _Base::value_type value_type;
593132720Skan
594132720Skan      _BinClos(const valarray<_Tp>& __v, const valarray<_Tp>& __w)
595169691Skan      : _Base(__v, __w) {}
596132720Skan    };
597132720Skan
598132720Skan  template<class _Oper, class _Dom>
599169691Skan    struct _BinClos<_Oper, _Expr, _ValArray, _Dom, typename _Dom::value_type>
600169691Skan    : _BinBase<_Oper, _Dom, valarray<typename _Dom::value_type> >
601132720Skan    {
602132720Skan      typedef typename _Dom::value_type _Tp;
603132720Skan      typedef _BinBase<_Oper,_Dom,valarray<_Tp> > _Base;
604132720Skan      typedef typename _Base::value_type value_type;
605132720Skan
606132720Skan      _BinClos(const _Dom& __e1, const valarray<_Tp>& __e2)
607169691Skan      : _Base(__e1, __e2) {}
608132720Skan    };
609132720Skan
610132720Skan  template<class _Oper, class _Dom>
611169691Skan    struct _BinClos<_Oper, _ValArray, _Expr, typename _Dom::value_type, _Dom>
612169691Skan    : _BinBase<_Oper, valarray<typename _Dom::value_type>,_Dom>
613132720Skan    {
614132720Skan      typedef typename _Dom::value_type _Tp;
615169691Skan      typedef _BinBase<_Oper, valarray<_Tp>, _Dom> _Base;
616132720Skan      typedef typename _Base::value_type value_type;
617132720Skan
618132720Skan      _BinClos(const valarray<_Tp>& __e1, const _Dom& __e2)
619169691Skan      : _Base(__e1, __e2) {}
620132720Skan    };
621132720Skan
622132720Skan  template<class _Oper, class _Dom>
623169691Skan    struct _BinClos<_Oper, _Expr, _Constant, _Dom, typename _Dom::value_type>
624169691Skan    : _BinBase2<_Oper, _Dom>
625132720Skan    {
626132720Skan      typedef typename _Dom::value_type _Tp;
627132720Skan      typedef _BinBase2<_Oper,_Dom> _Base;
628132720Skan      typedef typename _Base::value_type value_type;
629132720Skan
630132720Skan      _BinClos(const _Dom& __e1, const _Tp& __e2) : _Base(__e1, __e2) {}
631132720Skan    };
632132720Skan
633132720Skan  template<class _Oper, class _Dom>
634169691Skan    struct _BinClos<_Oper, _Constant, _Expr, typename _Dom::value_type, _Dom>
635169691Skan    : _BinBase1<_Oper, _Dom>
636132720Skan    {
637132720Skan      typedef typename _Dom::value_type _Tp;
638169691Skan      typedef _BinBase1<_Oper, _Dom> _Base;
639132720Skan      typedef typename _Base::value_type value_type;
640132720Skan
641132720Skan      _BinClos(const _Tp& __e1, const _Dom& __e2) : _Base(__e1, __e2) {}
642132720Skan    };
643132720Skan
644132720Skan  template<class _Oper, typename _Tp>
645169691Skan    struct _BinClos<_Oper, _ValArray, _Constant, _Tp, _Tp>
646169691Skan    : _BinBase2<_Oper, valarray<_Tp> >
647132720Skan    {
648132720Skan      typedef _BinBase2<_Oper,valarray<_Tp> > _Base;
649132720Skan      typedef typename _Base::value_type value_type;
650132720Skan
651132720Skan      _BinClos(const valarray<_Tp>& __v, const _Tp& __t) : _Base(__v, __t) {}
652132720Skan    };
653132720Skan
654132720Skan  template<class _Oper, typename _Tp>
655169691Skan    struct _BinClos<_Oper, _Constant, _ValArray, _Tp, _Tp>
656169691Skan    : _BinBase1<_Oper, valarray<_Tp> >
657132720Skan    {
658169691Skan      typedef _BinBase1<_Oper, valarray<_Tp> > _Base;
659132720Skan      typedef typename _Base::value_type value_type;
660132720Skan
661132720Skan      _BinClos(const _Tp& __t, const valarray<_Tp>& __v) : _Base(__t, __v) {}
662132720Skan    };
663132720Skan
664132720Skan    //
665132720Skan    // slice_array closure.
666132720Skan    //
667169691Skan  template<typename _Dom>
668169691Skan    class _SBase
669169691Skan    {
670132720Skan    public:
671169691Skan      typedef typename _Dom::value_type value_type;
672169691Skan
673169691Skan      _SBase (const _Dom& __e, const slice& __s)
674169691Skan      : _M_expr (__e), _M_slice (__s) {}
675169691Skan
676169691Skan      value_type
677169691Skan      operator[] (size_t __i) const
678169691Skan      { return _M_expr[_M_slice.start () + __i * _M_slice.stride ()]; }
679169691Skan
680169691Skan      size_t
681169691Skan      size() const
682169691Skan      { return _M_slice.size (); }
683132720Skan
684132720Skan    private:
685169691Skan      const _Dom& _M_expr;
686169691Skan      const slice& _M_slice;
687132720Skan    };
688132720Skan
689169691Skan  template<typename _Tp>
690169691Skan    class _SBase<_Array<_Tp> >
691169691Skan    {
692132720Skan    public:
693169691Skan      typedef _Tp value_type;
694169691Skan
695169691Skan      _SBase (_Array<_Tp> __a, const slice& __s)
696169691Skan      : _M_array (__a._M_data+__s.start()), _M_size (__s.size()),
697169691Skan	_M_stride (__s.stride()) {}
698169691Skan
699169691Skan      value_type
700169691Skan      operator[] (size_t __i) const
701169691Skan      { return _M_array._M_data[__i * _M_stride]; }
702169691Skan
703169691Skan      size_t
704169691Skan      size() const
705169691Skan      { return _M_size; }
706132720Skan
707132720Skan    private:
708169691Skan      const _Array<_Tp> _M_array;
709169691Skan      const size_t _M_size;
710169691Skan      const size_t _M_stride;
711132720Skan    };
712132720Skan
713169691Skan  template<class _Dom>
714169691Skan    struct _SClos<_Expr, _Dom>
715169691Skan    : _SBase<_Dom>
716169691Skan    {
717169691Skan      typedef _SBase<_Dom> _Base;
718169691Skan      typedef typename _Base::value_type value_type;
719169691Skan
720169691Skan      _SClos (const _Dom& __e, const slice& __s) : _Base (__e, __s) {}
721132720Skan    };
722132720Skan
723169691Skan  template<typename _Tp>
724169691Skan    struct _SClos<_ValArray, _Tp>
725169691Skan    : _SBase<_Array<_Tp> >
726169691Skan    {
727169691Skan      typedef  _SBase<_Array<_Tp> > _Base;
728169691Skan      typedef _Tp value_type;
729169691Skan
730169691Skan      _SClos (_Array<_Tp> __a, const slice& __s) : _Base (__a, __s) {}
731132720Skan    };
732132720Skan
733169691Skan_GLIBCXX_END_NAMESPACE
734132720Skan
735132720Skan#endif /* _CPP_VALARRAY_BEFORE_H */
736