1// The template and inlines for the -*- C++ -*- internal _Meta class.
2
3// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library.  This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 2, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License along
17// with this library; see the file COPYING.  If not, write to the Free
18// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19// USA.
20
21// As a special exception, you may use this file as part of a free software
22// library without restriction.  Specifically, if other files instantiate
23// templates or use macros or inline functions from this file, or you compile
24// this file and link it with other files to produce an executable, this
25// file does not by itself cause the resulting executable to be covered by
26// the GNU General Public License.  This exception does not however
27// invalidate any other reasons why the executable file might be covered by
28// the GNU General Public License.
29
30// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@cmla.ens-cachan.fr>
31
32/** @file valarray_meta.h
33 *  This is an internal header file, included by other library headers.
34 *  You should not attempt to use it directly.
35 */
36
37#ifndef _CPP_VALARRAY_META_H
38#define _CPP_VALARRAY_META_H 1
39
40#pragma GCC system_header
41
42namespace std
43{
44  //
45  // Implementing a loosened valarray return value is tricky.
46  // First we need to meet 26.3.1/3: we should not add more than
47  // two levels of template nesting. Therefore we resort to template
48  // template to "flatten" loosened return value types.
49  // At some point we use partial specialization to remove one level
50  // template nesting due to _Expr<>
51  //
52
53  // This class is NOT defined. It doesn't need to.
54  template<typename _Tp1, typename _Tp2> class _Constant;
55
56  // Implementations of unary functions applied to valarray<>s.
57  // I use hard-coded object functions here instead of a generic
58  // approach like pointers to function:
59  //    1) correctness: some functions take references, others values.
60  //       we can't deduce the correct type afterwards.
61  //    2) efficiency -- object functions can be easily inlined
62  //    3) be Koenig-lookup-friendly
63
64  struct __abs
65  {
66    template<typename _Tp>
67      _Tp operator()(const _Tp& __t) const { return abs(__t); }
68  };
69
70  struct __cos
71  {
72    template<typename _Tp>
73      _Tp operator()(const _Tp& __t) const { return cos(__t); }
74  };
75
76  struct __acos
77  {
78    template<typename _Tp>
79      _Tp operator()(const _Tp& __t) const { return acos(__t); }
80  };
81
82  struct __cosh
83  {
84    template<typename _Tp>
85      _Tp operator()(const _Tp& __t) const { return cosh(__t); }
86  };
87
88  struct __sin
89  {
90    template<typename _Tp>
91      _Tp operator()(const _Tp& __t) const { return sin(__t); }
92  };
93
94  struct __asin
95  {
96    template<typename _Tp>
97      _Tp operator()(const _Tp& __t) const { return asin(__t); }
98  };
99
100  struct __sinh
101  {
102    template<typename _Tp>
103      _Tp operator()(const _Tp& __t) const { return sinh(__t); }
104  };
105
106  struct __tan
107  {
108    template<typename _Tp>
109      _Tp operator()(const _Tp& __t) const { return tan(__t); }
110  };
111
112  struct __atan
113  {
114    template<typename _Tp>
115      _Tp operator()(const _Tp& __t) const { return atan(__t); }
116  };
117
118  struct __tanh
119  {
120    template<typename _Tp>
121      _Tp operator()(const _Tp& __t) const { return tanh(__t); }
122  };
123
124  struct __exp
125  {
126    template<typename _Tp>
127      _Tp operator()(const _Tp& __t) const { return exp(__t); }
128  };
129
130  struct __log
131  {
132    template<typename _Tp>
133      _Tp operator()(const _Tp& __t) const { return log(__t); }
134  };
135
136  struct __log10
137  {
138    template<typename _Tp>
139      _Tp operator()(const _Tp& __t) const { return log10(__t); }
140  };
141
142  struct __sqrt
143  {
144    template<typename _Tp>
145      _Tp operator()(const _Tp& __t) const { return sqrt(__t); }
146  };
147
148  // In the past, we used to tailor operator applications semantics
149  // to the specialization of standard function objects (i.e. plus<>, etc.)
150  // That is incorrect.  Therefore we provide our own surrogates.
151
152  struct __unary_plus
153  {
154    template<typename _Tp>
155      _Tp operator()(const _Tp& __t) const { return +__t; }
156  };
157
158  struct __negate
159  {
160    template<typename _Tp>
161      _Tp operator()(const _Tp& __t) const { return -__t; }
162  };
163
164  struct __bitwise_not
165  {
166    template<typename _Tp>
167      _Tp operator()(const _Tp& __t) const { return ~__t; }
168  };
169
170  struct __plus
171  {
172    template<typename _Tp>
173      _Tp operator()(const _Tp& __x, const _Tp& __y) const
174      { return __x + __y; }
175  };
176
177  struct __minus
178  {
179    template<typename _Tp>
180      _Tp operator()(const _Tp& __x, const _Tp& __y) const
181      { return __x - __y; }
182  };
183
184  struct __multiplies
185  {
186    template<typename _Tp>
187      _Tp operator()(const _Tp& __x, const _Tp& __y) const
188      { return __x * __y; }
189  };
190
191  struct __divides
192  {
193    template<typename _Tp>
194      _Tp operator()(const _Tp& __x, const _Tp& __y) const
195      { return __x / __y; }
196  };
197
198  struct __modulus
199  {
200    template<typename _Tp>
201      _Tp operator()(const _Tp& __x, const _Tp& __y) const
202      { return __x % __y; }
203  };
204
205  struct __bitwise_xor
206  {
207    template<typename _Tp>
208      _Tp operator()(const _Tp& __x, const _Tp& __y) const
209      { return __x ^ __y; }
210  };
211
212  struct __bitwise_and
213  {
214    template<typename _Tp>
215      _Tp operator()(const _Tp& __x, const _Tp& __y) const
216      { return __x & __y; }
217  };
218
219  struct __bitwise_or
220  {
221    template<typename _Tp>
222      _Tp operator()(const _Tp& __x, const _Tp& __y) const
223      { return __x | __y; }
224  };
225
226  struct __shift_left
227  {
228    template<typename _Tp>
229      _Tp operator()(const _Tp& __x, const _Tp& __y) const
230      { return __x << __y; }
231  };
232
233  struct __shift_right
234  {
235    template<typename _Tp>
236      _Tp operator()(const _Tp& __x, const _Tp& __y) const
237      { return __x >> __y; }
238  };
239
240  struct __logical_and
241  {
242    template<typename _Tp>
243      bool operator()(const _Tp& __x, const _Tp& __y) const
244      { return __x && __y; }
245  };
246
247  struct __logical_or
248  {
249    template<typename _Tp>
250      bool operator()(const _Tp& __x, const _Tp& __y) const
251      { return __x || __y; }
252  };
253
254  struct __logical_not
255  {
256    template<typename _Tp>
257      bool operator()(const _Tp& __x) const { return !__x; }
258  };
259
260  struct __equal_to
261  {
262    template<typename _Tp>
263      bool operator()(const _Tp& __x, const _Tp& __y) const
264      { return __x == __y; }
265  };
266
267  struct __not_equal_to
268  {
269    template<typename _Tp>
270      bool operator()(const _Tp& __x, const _Tp& __y) const
271      { return __x != __y; }
272  };
273
274  struct __less
275  {
276    template<typename _Tp>
277      bool operator()(const _Tp& __x, const _Tp& __y) const
278      { return __x < __y; }
279  };
280
281  struct __greater
282  {
283    template<typename _Tp>
284      bool operator()(const _Tp& __x, const _Tp& __y) const
285      { return __x > __y; }
286  };
287
288  struct __less_equal
289  {
290    template<typename _Tp>
291      bool operator()(const _Tp& __x, const _Tp& __y) const
292      { return __x <= __y; }
293  };
294
295  struct __greater_equal
296  {
297    template<typename _Tp>
298      bool operator()(const _Tp& __x, const _Tp& __y) const
299      { return __x >= __y; }
300  };
301
302  // The few binary functions we miss.
303  struct __atan2
304  {
305    template<typename _Tp>
306      _Tp operator()(const _Tp& __x, const _Tp& __y) const
307      { return atan2(__x, __y); }
308  };
309
310  struct __pow
311  {
312    template<typename _Tp>
313      _Tp operator()(const _Tp& __x, const _Tp& __y) const
314      { return pow(__x, __y); }
315  };
316
317
318  // We need these bits in order to recover the return type of
319  // some functions/operators now that we're no longer using
320  // function templates.
321  template<typename, typename _Tp>
322    struct __fun
323    {
324      typedef _Tp result_type;
325    };
326
327  // several specializations for relational operators.
328  template<typename _Tp>
329    struct __fun<__logical_not, _Tp>
330    {
331      typedef bool result_type;
332    };
333
334  template<typename _Tp>
335    struct __fun<__logical_and, _Tp>
336    {
337      typedef bool result_type;
338    };
339
340  template<typename _Tp>
341    struct __fun<__logical_or, _Tp>
342    {
343      typedef bool result_type;
344    };
345
346  template<typename _Tp>
347    struct __fun<__less, _Tp>
348    {
349      typedef bool result_type;
350    };
351
352  template<typename _Tp>
353    struct __fun<__greater, _Tp>
354    {
355      typedef bool result_type;
356    };
357
358  template<typename _Tp>
359    struct __fun<__less_equal, _Tp>
360    {
361      typedef bool result_type;
362    };
363
364  template<typename _Tp>
365    struct __fun<__greater_equal, _Tp>
366    {
367      typedef bool result_type;
368    };
369
370  template<typename _Tp>
371    struct __fun<__equal_to, _Tp>
372    {
373      typedef bool result_type;
374    };
375
376  template<typename _Tp>
377    struct __fun<__not_equal_to, _Tp>
378    {
379      typedef bool result_type;
380    };
381
382    //
383    // Apply function taking a value/const reference closure
384    //
385
386  template<typename _Dom, typename _Arg>
387    class _FunBase
388    {
389    public:
390      typedef typename _Dom::value_type value_type;
391
392      _FunBase(const _Dom& __e, value_type __f(_Arg))
393	: _M_expr(__e), _M_func(__f) {}
394
395      value_type operator[](size_t __i) const
396      { return _M_func (_M_expr[__i]); }
397
398      size_t size() const { return _M_expr.size ();}
399
400    private:
401        const _Dom& _M_expr;
402        value_type (*_M_func)(_Arg);
403    };
404
405  template<class _Dom>
406    struct _ValFunClos<_Expr,_Dom> : _FunBase<_Dom, typename _Dom::value_type>
407    {
408      typedef _FunBase<_Dom, typename _Dom::value_type> _Base;
409      typedef typename _Base::value_type value_type;
410      typedef value_type _Tp;
411
412      _ValFunClos(const _Dom& __e, _Tp __f(_Tp)) : _Base(__e, __f) {}
413    };
414
415  template<typename _Tp>
416    struct _ValFunClos<_ValArray,_Tp> : _FunBase<valarray<_Tp>, _Tp>
417    {
418      typedef _FunBase<valarray<_Tp>, _Tp> _Base;
419      typedef _Tp value_type;
420
421      _ValFunClos(const valarray<_Tp>& __v, _Tp __f(_Tp)) : _Base(__v, __f) {}
422    };
423
424  template<class _Dom>
425    struct _RefFunClos<_Expr,_Dom> :
426        _FunBase<_Dom, const typename _Dom::value_type&>
427    {
428      typedef _FunBase<_Dom, const typename _Dom::value_type&> _Base;
429      typedef typename _Base::value_type value_type;
430      typedef value_type _Tp;
431
432      _RefFunClos(const _Dom& __e, _Tp __f(const _Tp&))
433	: _Base(__e, __f) {}
434    };
435
436  template<typename _Tp>
437    struct _RefFunClos<_ValArray,_Tp> : _FunBase<valarray<_Tp>, const _Tp&>
438    {
439      typedef _FunBase<valarray<_Tp>, const _Tp&> _Base;
440      typedef _Tp value_type;
441
442      _RefFunClos(const valarray<_Tp>& __v, _Tp __f(const _Tp&))
443	: _Base(__v, __f) {}
444    };
445
446  //
447  // Unary expression closure.
448  //
449
450  template<class _Oper, class _Arg>
451    class _UnBase
452    {
453    public:
454      typedef typename _Arg::value_type _Vt;
455      typedef typename __fun<_Oper, _Vt>::result_type value_type;
456
457      _UnBase(const _Arg& __e) : _M_expr(__e) {}
458
459      value_type operator[](size_t __i) const
460      { return _Oper()(_M_expr[__i]); }
461
462      size_t size() const { return _M_expr.size(); }
463
464    private:
465      const _Arg& _M_expr;
466    };
467
468  template<class _Oper, class _Dom>
469    struct _UnClos<_Oper, _Expr, _Dom> :  _UnBase<_Oper, _Dom>
470    {
471      typedef _Dom _Arg;
472      typedef _UnBase<_Oper, _Dom> _Base;
473      typedef typename _Base::value_type value_type;
474
475      _UnClos(const _Arg& __e) : _Base(__e) {}
476    };
477
478  template<class _Oper, typename _Tp>
479    struct _UnClos<_Oper, _ValArray, _Tp> : _UnBase<_Oper, valarray<_Tp> >
480    {
481      typedef valarray<_Tp> _Arg;
482      typedef _UnBase<_Oper, valarray<_Tp> > _Base;
483      typedef typename _Base::value_type value_type;
484
485      _UnClos(const _Arg& __e) : _Base(__e) {}
486    };
487
488
489  //
490  // Binary expression closure.
491  //
492
493  template<class _Oper, class _FirstArg, class _SecondArg>
494    class _BinBase
495    {
496    public:
497        typedef typename _FirstArg::value_type _Vt;
498        typedef typename __fun<_Oper, _Vt>::result_type value_type;
499
500      _BinBase(const _FirstArg& __e1, const _SecondArg& __e2)
501	: _M_expr1(__e1), _M_expr2(__e2) {}
502
503      value_type operator[](size_t __i) const
504      { return _Oper()(_M_expr1[__i], _M_expr2[__i]); }
505
506      size_t size() const { return _M_expr1.size(); }
507
508    private:
509      const _FirstArg& _M_expr1;
510      const _SecondArg& _M_expr2;
511    };
512
513
514  template<class _Oper, class _Clos>
515    class _BinBase2
516    {
517    public:
518      typedef typename _Clos::value_type _Vt;
519      typedef typename __fun<_Oper, _Vt>::result_type value_type;
520
521      _BinBase2(const _Clos& __e, const _Vt& __t)
522	: _M_expr1(__e), _M_expr2(__t) {}
523
524      value_type operator[](size_t __i) const
525      { return _Oper()(_M_expr1[__i], _M_expr2); }
526
527      size_t size() const { return _M_expr1.size(); }
528
529    private:
530      const _Clos& _M_expr1;
531      const _Vt& _M_expr2;
532    };
533
534  template<class _Oper, class _Clos>
535    class _BinBase1
536    {
537    public:
538      typedef typename _Clos::value_type _Vt;
539      typedef typename __fun<_Oper, _Vt>::result_type value_type;
540
541      _BinBase1(const _Vt& __t, const _Clos& __e)
542	: _M_expr1(__t), _M_expr2(__e) {}
543
544      value_type operator[](size_t __i) const
545      { return _Oper()(_M_expr1, _M_expr2[__i]); }
546
547      size_t size() const { return _M_expr2.size(); }
548
549    private:
550      const _Vt& _M_expr1;
551      const _Clos& _M_expr2;
552    };
553
554  template<class _Oper, class _Dom1, class _Dom2>
555    struct _BinClos<_Oper, _Expr, _Expr, _Dom1, _Dom2>
556        : _BinBase<_Oper,_Dom1,_Dom2>
557    {
558      typedef _BinBase<_Oper,_Dom1,_Dom2> _Base;
559      typedef typename _Base::value_type value_type;
560
561      _BinClos(const _Dom1& __e1, const _Dom2& __e2) : _Base(__e1, __e2) {}
562    };
563
564  template<class _Oper, typename _Tp>
565    struct _BinClos<_Oper,_ValArray,_ValArray,_Tp,_Tp>
566      : _BinBase<_Oper,valarray<_Tp>,valarray<_Tp> >
567    {
568      typedef _BinBase<_Oper,valarray<_Tp>,valarray<_Tp> > _Base;
569      typedef _Tp value_type;
570
571      _BinClos(const valarray<_Tp>& __v, const valarray<_Tp>& __w)
572	: _Base(__v, __w) {}
573    };
574
575  template<class _Oper, class _Dom>
576    struct _BinClos<_Oper,_Expr,_ValArray,_Dom,typename _Dom::value_type>
577      : _BinBase<_Oper,_Dom,valarray<typename _Dom::value_type> >
578    {
579      typedef typename _Dom::value_type _Tp;
580      typedef _BinBase<_Oper,_Dom,valarray<_Tp> > _Base;
581      typedef typename _Base::value_type value_type;
582
583      _BinClos(const _Dom& __e1, const valarray<_Tp>& __e2)
584	: _Base(__e1, __e2) {}
585    };
586
587  template<class _Oper, class _Dom>
588    struct  _BinClos<_Oper,_ValArray,_Expr,typename _Dom::value_type,_Dom>
589      : _BinBase<_Oper,valarray<typename _Dom::value_type>,_Dom>
590    {
591      typedef typename _Dom::value_type _Tp;
592      typedef _BinBase<_Oper,valarray<_Tp>,_Dom> _Base;
593      typedef typename _Base::value_type value_type;
594
595      _BinClos(const valarray<_Tp>& __e1, const _Dom& __e2)
596	: _Base(__e1, __e2) {}
597    };
598
599  template<class _Oper, class _Dom>
600    struct _BinClos<_Oper,_Expr,_Constant,_Dom,typename _Dom::value_type>
601      : _BinBase2<_Oper,_Dom>
602    {
603      typedef typename _Dom::value_type _Tp;
604      typedef _BinBase2<_Oper,_Dom> _Base;
605      typedef typename _Base::value_type value_type;
606
607      _BinClos(const _Dom& __e1, const _Tp& __e2) : _Base(__e1, __e2) {}
608    };
609
610  template<class _Oper, class _Dom>
611    struct _BinClos<_Oper,_Constant,_Expr,typename _Dom::value_type,_Dom>
612      : _BinBase1<_Oper,_Dom>
613    {
614      typedef typename _Dom::value_type _Tp;
615      typedef _BinBase1<_Oper,_Dom> _Base;
616      typedef typename _Base::value_type value_type;
617
618      _BinClos(const _Tp& __e1, const _Dom& __e2) : _Base(__e1, __e2) {}
619    };
620
621  template<class _Oper, typename _Tp>
622    struct _BinClos<_Oper,_ValArray,_Constant,_Tp,_Tp>
623      : _BinBase2<_Oper,valarray<_Tp> >
624    {
625      typedef _BinBase2<_Oper,valarray<_Tp> > _Base;
626      typedef typename _Base::value_type value_type;
627
628      _BinClos(const valarray<_Tp>& __v, const _Tp& __t) : _Base(__v, __t) {}
629    };
630
631  template<class _Oper, typename _Tp>
632    struct _BinClos<_Oper,_Constant,_ValArray,_Tp,_Tp>
633      : _BinBase1<_Oper,valarray<_Tp> >
634    {
635      typedef _BinBase1<_Oper,valarray<_Tp> > _Base;
636      typedef typename _Base::value_type value_type;
637
638      _BinClos(const _Tp& __t, const valarray<_Tp>& __v) : _Base(__t, __v) {}
639    };
640
641
642    //
643    // slice_array closure.
644    //
645    template<typename _Dom>  class _SBase {
646    public:
647        typedef typename _Dom::value_type value_type;
648
649        _SBase (const _Dom& __e, const slice& __s)
650                : _M_expr (__e), _M_slice (__s) {}
651        value_type operator[] (size_t __i) const
652        { return _M_expr[_M_slice.start () + __i * _M_slice.stride ()]; }
653        size_t size() const { return _M_slice.size (); }
654
655    private:
656        const _Dom& _M_expr;
657        const slice& _M_slice;
658    };
659
660    template<typename _Tp> class _SBase<_Array<_Tp> > {
661    public:
662        typedef _Tp value_type;
663
664        _SBase (_Array<_Tp> __a, const slice& __s)
665                : _M_array (__a._M_data+__s.start()), _M_size (__s.size()),
666                  _M_stride (__s.stride()) {}
667        value_type operator[] (size_t __i) const
668        { return _M_array._M_data[__i * _M_stride]; }
669        size_t size() const { return _M_size; }
670
671    private:
672        const _Array<_Tp> _M_array;
673        const size_t _M_size;
674        const size_t _M_stride;
675    };
676
677    template<class _Dom> struct  _SClos<_Expr,_Dom> : _SBase<_Dom> {
678        typedef _SBase<_Dom> _Base;
679        typedef typename _Base::value_type value_type;
680
681        _SClos (const _Dom& __e, const slice& __s) : _Base (__e, __s) {}
682    };
683
684    template<typename _Tp>
685    struct _SClos<_ValArray,_Tp> : _SBase<_Array<_Tp> > {
686        typedef  _SBase<_Array<_Tp> > _Base;
687        typedef _Tp value_type;
688
689        _SClos (_Array<_Tp> __a, const slice& __s) : _Base (__a, __s) {}
690    };
691
692    //
693    // gslice_array closure.
694    //
695    template<class _Dom> class _GBase {
696    public:
697        typedef typename _Dom::value_type value_type;
698
699        _GBase (const _Dom& __e, const valarray<size_t>& __i)
700                : _M_expr (__e), _M_index(__i) {}
701        value_type operator[] (size_t __i) const
702        { return _M_expr[_M_index[__i]]; }
703        size_t size () const { return _M_index.size(); }
704
705    private:
706        const _Dom&	 _M_expr;
707        const valarray<size_t>& _M_index;
708    };
709
710    template<typename _Tp> class _GBase<_Array<_Tp> > {
711    public:
712        typedef _Tp value_type;
713
714        _GBase (_Array<_Tp> __a, const valarray<size_t>& __i)
715                : _M_array (__a), _M_index(__i) {}
716        value_type operator[] (size_t __i) const
717        { return _M_array._M_data[_M_index[__i]]; }
718        size_t size () const { return _M_index.size(); }
719
720    private:
721        const _Array<_Tp>     _M_array;
722        const valarray<size_t>& _M_index;
723    };
724
725    template<class _Dom> struct _GClos<_Expr,_Dom> : _GBase<_Dom> {
726        typedef _GBase<_Dom> _Base;
727        typedef typename _Base::value_type value_type;
728
729        _GClos (const _Dom& __e, const valarray<size_t>& __i)
730                : _Base (__e, __i) {}
731    };
732
733    template<typename _Tp>
734    struct _GClos<_ValArray,_Tp> : _GBase<_Array<_Tp> > {
735        typedef _GBase<_Array<_Tp> > _Base;
736        typedef typename _Base::value_type value_type;
737
738        _GClos (_Array<_Tp> __a, const valarray<size_t>& __i)
739                : _Base (__a, __i) {}
740    };
741
742    //
743    // indirect_array closure
744    //
745
746    template<class _Dom> class _IBase {
747    public:
748        typedef typename _Dom::value_type value_type;
749
750        _IBase (const _Dom& __e, const valarray<size_t>& __i)
751                : _M_expr (__e), _M_index (__i) {}
752        value_type operator[] (size_t __i) const
753        { return _M_expr[_M_index[__i]]; }
754        size_t size() const { return _M_index.size(); }
755
756    private:
757        const _Dom& 	    _M_expr;
758        const valarray<size_t>& _M_index;
759    };
760
761    template<class _Dom> struct _IClos<_Expr,_Dom> : _IBase<_Dom> {
762        typedef _IBase<_Dom> _Base;
763        typedef typename _Base::value_type value_type;
764
765        _IClos (const _Dom& __e, const valarray<size_t>& __i)
766                : _Base (__e, __i) {}
767    };
768
769    template<typename _Tp>
770    struct _IClos<_ValArray,_Tp>  : _IBase<valarray<_Tp> > {
771        typedef _IBase<valarray<_Tp> > _Base;
772        typedef _Tp value_type;
773
774        _IClos (const valarray<_Tp>& __a, const valarray<size_t>& __i)
775                : _Base (__a, __i) {}
776    };
777
778  //
779  // class _Expr
780  //
781  template<class _Clos, typename _Tp>
782    class _Expr
783    {
784    public:
785      typedef _Tp value_type;
786
787      _Expr(const _Clos&);
788
789      const _Clos& operator()() const;
790
791      value_type operator[](size_t) const;
792      valarray<value_type> operator[](slice) const;
793      valarray<value_type> operator[](const gslice&) const;
794      valarray<value_type> operator[](const valarray<bool>&) const;
795      valarray<value_type> operator[](const valarray<size_t>&) const;
796
797      _Expr<_UnClos<__unary_plus,std::_Expr,_Clos>, value_type>
798        operator+() const;
799
800      _Expr<_UnClos<__negate,std::_Expr,_Clos>, value_type>
801        operator-() const;
802
803      _Expr<_UnClos<__bitwise_not,std::_Expr,_Clos>, value_type>
804        operator~() const;
805
806      _Expr<_UnClos<__logical_not,std::_Expr,_Clos>, bool>
807        operator!() const;
808
809      size_t size() const;
810      value_type sum() const;
811
812      valarray<value_type> shift(int) const;
813      valarray<value_type> cshift(int) const;
814
815      value_type min() const;
816      value_type max() const;
817
818      valarray<value_type> apply(value_type (*)(const value_type&)) const;
819      valarray<value_type> apply(value_type (*)(value_type)) const;
820
821    private:
822      const _Clos _M_closure;
823    };
824
825  template<class _Clos, typename _Tp>
826    inline
827    _Expr<_Clos,_Tp>::_Expr(const _Clos& __c) : _M_closure(__c) {}
828
829  template<class _Clos, typename _Tp>
830    inline const _Clos&
831    _Expr<_Clos,_Tp>::operator()() const
832    { return _M_closure; }
833
834  template<class _Clos, typename _Tp>
835    inline _Tp
836    _Expr<_Clos,_Tp>::operator[](size_t __i) const
837    { return _M_closure[__i]; }
838
839  template<class _Clos, typename _Tp>
840    inline valarray<_Tp>
841    _Expr<_Clos,_Tp>::operator[](slice __s) const
842    { return _M_closure[__s]; }
843
844  template<class _Clos, typename _Tp>
845    inline valarray<_Tp>
846    _Expr<_Clos,_Tp>::operator[](const gslice& __gs) const
847    { return _M_closure[__gs]; }
848
849  template<class _Clos, typename _Tp>
850    inline valarray<_Tp>
851    _Expr<_Clos,_Tp>::operator[](const valarray<bool>& __m) const
852    { return _M_closure[__m]; }
853
854  template<class _Clos, typename _Tp>
855    inline valarray<_Tp>
856    _Expr<_Clos,_Tp>::operator[](const valarray<size_t>& __i) const
857    { return _M_closure[__i]; }
858
859  template<class _Clos, typename _Tp>
860    inline size_t
861    _Expr<_Clos,_Tp>::size() const  { return _M_closure.size (); }
862
863  template<class _Clos, typename _Tp>
864    inline valarray<_Tp>
865    _Expr<_Clos, _Tp>::shift(int __n) const
866    { return valarray<_Tp>(_M_closure).shift(__n); }
867
868  template<class _Clos, typename _Tp>
869    inline valarray<_Tp>
870    _Expr<_Clos, _Tp>::cshift(int __n) const
871    { return valarray<_Tp>(_M_closure).cshift(__n); }
872
873  template<class _Clos, typename _Tp>
874    inline valarray<_Tp>
875    _Expr<_Clos, _Tp>::apply(_Tp __f(const _Tp&)) const
876    { return valarray<_Tp>(_M_closure).apply(__f); }
877
878  template<class _Clos, typename _Tp>
879    inline valarray<_Tp>
880    _Expr<_Clos, _Tp>::apply(_Tp __f(_Tp)) const
881    { return valarray<_Tp>(_M_closure).apply(__f); }
882
883  // XXX: replace this with a more robust summation algorithm.
884  template<class _Clos, typename _Tp>
885    inline _Tp
886    _Expr<_Clos,_Tp>::sum() const
887    {
888      size_t __n = _M_closure.size();
889      if (__n == 0)
890	return _Tp();
891      else
892	{
893	  _Tp __s = _M_closure[--__n];
894	  while (__n != 0)
895	    __s += _M_closure[--__n];
896	  return __s;
897        }
898    }
899
900  template<class _Clos, typename _Tp>
901    inline _Tp
902    _Expr<_Clos, _Tp>::min() const
903    { return __valarray_min(_M_closure); }
904
905  template<class _Clos, typename _Tp>
906    inline _Tp
907    _Expr<_Clos, _Tp>::max() const
908    { return __valarray_max(_M_closure); }
909
910  template<class _Dom, typename _Tp>
911    inline _Expr<_UnClos<__logical_not,_Expr,_Dom>, bool>
912    _Expr<_Dom,_Tp>::operator!() const
913    {
914      typedef _UnClos<__logical_not,std::_Expr,_Dom> _Closure;
915      return _Expr<_Closure,_Tp>(_Closure(this->_M_closure));
916    }
917
918#define _DEFINE_EXPR_UNARY_OPERATOR(_Op, _Name)                           \
919  template<class _Dom, typename _Tp>                                      \
920    inline _Expr<_UnClos<_Name,std::_Expr,_Dom>,_Tp>                      \
921    _Expr<_Dom,_Tp>::operator _Op() const                                 \
922    {                                                                     \
923      typedef _UnClos<_Name,std::_Expr,_Dom> _Closure;                    \
924      return _Expr<_Closure,_Tp>(_Closure(this->_M_closure));             \
925    }
926
927    _DEFINE_EXPR_UNARY_OPERATOR(+, __unary_plus)
928    _DEFINE_EXPR_UNARY_OPERATOR(-, __negate)
929    _DEFINE_EXPR_UNARY_OPERATOR(~, __bitwise_not)
930
931#undef _DEFINE_EXPR_UNARY_OPERATOR
932
933
934#define _DEFINE_EXPR_BINARY_OPERATOR(_Op, _Name)                        \
935  template<class _Dom1, class _Dom2>					\
936  inline _Expr<_BinClos<_Name,_Expr,_Expr,_Dom1,_Dom2>,                 \
937         typename __fun<_Name, typename _Dom1::value_type>::result_type>\
938  operator _Op(const _Expr<_Dom1,typename _Dom1::value_type>& __v,      \
939	       const _Expr<_Dom2,typename _Dom2::value_type>& __w)      \
940  {                                                                     \
941    typedef typename _Dom1::value_type _Arg;                            \
942    typedef typename __fun<_Name, _Arg>::result_type _Value;            \
943    typedef _BinClos<_Name,_Expr,_Expr,_Dom1,_Dom2> _Closure;           \
944    return _Expr<_Closure,_Value>(_Closure(__v(), __w()));              \
945  }                                                                     \
946                                                                        \
947template<class _Dom>                                                    \
948inline _Expr<_BinClos<_Name,_Expr,_Constant,_Dom,typename _Dom::value_type>,\
949             typename __fun<_Name, typename _Dom::value_type>::result_type>\
950operator _Op(const _Expr<_Dom,typename _Dom::value_type>& __v,          \
951             const typename _Dom::value_type& __t)                      \
952{                                                                       \
953  typedef typename _Dom::value_type _Arg;                               \
954  typedef typename __fun<_Name, _Arg>::result_type _Value;              \
955  typedef _BinClos<_Name,_Expr,_Constant,_Dom,_Arg> _Closure;           \
956  return _Expr<_Closure,_Value>(_Closure(__v(), __t));                  \
957}                                                                       \
958                                                                        \
959template<class _Dom>                                                    \
960inline _Expr<_BinClos<_Name,_Constant,_Expr,typename _Dom::value_type,_Dom>,\
961             typename __fun<_Name, typename _Dom::value_type>::result_type>\
962operator _Op(const typename _Dom::value_type& __t,                      \
963             const _Expr<_Dom,typename _Dom::value_type>& __v)          \
964{                                                                       \
965  typedef typename _Dom::value_type _Arg;                               \
966  typedef typename __fun<_Name, _Arg>::result_type _Value;              \
967  typedef _BinClos<_Name,_Constant,_Expr,_Arg,_Dom> _Closure;           \
968  return _Expr<_Closure,_Value>(_Closure(__t, __v()));                  \
969}                                                                       \
970                                                                        \
971template<class _Dom>                                                    \
972inline _Expr<_BinClos<_Name,_Expr,_ValArray,_Dom,typename _Dom::value_type>,\
973             typename __fun<_Name, typename _Dom::value_type>::result_type>\
974operator _Op(const _Expr<_Dom,typename _Dom::value_type>& __e,          \
975             const valarray<typename _Dom::value_type>& __v)            \
976{                                                                       \
977  typedef typename _Dom::value_type _Arg;                               \
978  typedef typename __fun<_Name, _Arg>::result_type _Value;              \
979  typedef _BinClos<_Name,_Expr,_ValArray,_Dom,_Arg> _Closure;           \
980  return  _Expr<_Closure,_Value>(_Closure(__e(), __v));                 \
981}                                                                       \
982                                                                        \
983template<class _Dom>                                                    \
984inline _Expr<_BinClos<_Name,_ValArray,_Expr,typename _Dom::value_type,_Dom>,\
985             typename __fun<_Name, typename _Dom::value_type>::result_type>\
986operator _Op(const valarray<typename _Dom::value_type>& __v,            \
987             const _Expr<_Dom,typename _Dom::value_type>& __e)          \
988{                                                                       \
989  typedef typename _Dom::value_type _Tp;                                \
990  typedef typename __fun<_Name, _Tp>::result_type _Value;               \
991  typedef _BinClos<_Name,_ValArray,_Expr,_Tp,_Dom> _Closure;            \
992  return _Expr<_Closure,_Value> (_Closure (__v, __e ()));               \
993}
994
995    _DEFINE_EXPR_BINARY_OPERATOR(+, __plus)
996    _DEFINE_EXPR_BINARY_OPERATOR(-, __minus)
997    _DEFINE_EXPR_BINARY_OPERATOR(*, __multiplies)
998    _DEFINE_EXPR_BINARY_OPERATOR(/, __divides)
999    _DEFINE_EXPR_BINARY_OPERATOR(%, __modulus)
1000    _DEFINE_EXPR_BINARY_OPERATOR(^, __bitwise_xor)
1001    _DEFINE_EXPR_BINARY_OPERATOR(&, __bitwise_and)
1002    _DEFINE_EXPR_BINARY_OPERATOR(|, __bitwise_or)
1003    _DEFINE_EXPR_BINARY_OPERATOR(<<, __shift_left)
1004    _DEFINE_EXPR_BINARY_OPERATOR(>>, __shift_right)
1005    _DEFINE_EXPR_BINARY_OPERATOR(&&, __logical_and)
1006    _DEFINE_EXPR_BINARY_OPERATOR(||, __logical_or)
1007    _DEFINE_EXPR_BINARY_OPERATOR(==, __equal_to)
1008    _DEFINE_EXPR_BINARY_OPERATOR(!=, __not_equal_to)
1009    _DEFINE_EXPR_BINARY_OPERATOR(<, __less)
1010    _DEFINE_EXPR_BINARY_OPERATOR(>, __greater)
1011    _DEFINE_EXPR_BINARY_OPERATOR(<=, __less_equal)
1012    _DEFINE_EXPR_BINARY_OPERATOR(>=, __greater_equal)
1013
1014#undef _DEFINE_EXPR_BINARY_OPERATOR
1015
1016#define _DEFINE_EXPR_UNARY_FUNCTION(_Name)                               \
1017  template<class _Dom>                                                   \
1018    inline _Expr<_UnClos<__##_Name,_Expr,_Dom>,typename _Dom::value_type>\
1019    _Name(const _Expr<_Dom,typename _Dom::value_type>& __e)              \
1020    {                                                                    \
1021      typedef typename _Dom::value_type _Tp;                             \
1022      typedef _UnClos<__##_Name,_Expr,_Dom> _Closure;                    \
1023      return _Expr<_Closure,_Tp>(_Closure(__e()));                       \
1024    }                                                                    \
1025                                                                         \
1026  template<typename _Tp>                                                 \
1027    inline _Expr<_UnClos<__##_Name,_ValArray,_Tp>,_Tp>                   \
1028    _Name(const valarray<_Tp>& __v)                                      \
1029    {                                                                    \
1030      typedef _UnClos<__##_Name,_ValArray,_Tp> _Closure;                 \
1031      return _Expr<_Closure,_Tp>(_Closure(__v));                         \
1032    }
1033
1034    _DEFINE_EXPR_UNARY_FUNCTION(abs)
1035    _DEFINE_EXPR_UNARY_FUNCTION(cos)
1036    _DEFINE_EXPR_UNARY_FUNCTION(acos)
1037    _DEFINE_EXPR_UNARY_FUNCTION(cosh)
1038    _DEFINE_EXPR_UNARY_FUNCTION(sin)
1039    _DEFINE_EXPR_UNARY_FUNCTION(asin)
1040    _DEFINE_EXPR_UNARY_FUNCTION(sinh)
1041    _DEFINE_EXPR_UNARY_FUNCTION(tan)
1042    _DEFINE_EXPR_UNARY_FUNCTION(tanh)
1043    _DEFINE_EXPR_UNARY_FUNCTION(atan)
1044    _DEFINE_EXPR_UNARY_FUNCTION(exp)
1045    _DEFINE_EXPR_UNARY_FUNCTION(log)
1046    _DEFINE_EXPR_UNARY_FUNCTION(log10)
1047    _DEFINE_EXPR_UNARY_FUNCTION(sqrt)
1048
1049#undef _DEFINE_EXPR_UNARY_FUNCTION
1050
1051#define _DEFINE_EXPR_BINARY_FUNCTION(_Fun)                             \
1052  template<class _Dom1, class _Dom2>                                   \
1053    inline _Expr<_BinClos<__##_Fun,_Expr,_Expr,_Dom1,_Dom2>,           \
1054		 typename _Dom1::value_type>                           \
1055    _Fun(const _Expr<_Dom1,typename _Dom1::value_type>& __e1,          \
1056	  const _Expr<_Dom2,typename _Dom2::value_type>& __e2)         \
1057    {                                                                  \
1058      typedef typename _Dom1::value_type _Tp;                          \
1059      typedef _BinClos<__##_Fun,_Expr,_Expr,_Dom1,_Dom2> _Closure;     \
1060      return _Expr<_Closure,_Tp>(_Closure(__e1(), __e2()));            \
1061    }                                                                  \
1062                                                                       \
1063  template<class _Dom>                                                 \
1064    inline _Expr<_BinClos<__##_Fun, _Expr, _ValArray, _Dom,            \
1065			  typename _Dom::value_type>,                  \
1066		 typename _Dom::value_type>                            \
1067    _Fun(const _Expr<_Dom,typename _Dom::value_type>& __e,             \
1068	 const valarray<typename _Dom::value_type>& __v)               \
1069    {                                                                  \
1070      typedef typename _Dom::value_type _Tp;                           \
1071      typedef _BinClos<__##_Fun, _Expr, _ValArray, _Dom, _Tp> _Closure;\
1072      return _Expr<_Closure,_Tp>(_Closure(__e(), __v));                \
1073    }                                                                  \
1074                                                                       \
1075  template<class _Dom>                                                 \
1076    inline _Expr<_BinClos<__##_Fun, _ValArray, _Expr,                  \
1077			  typename _Dom::value_type,_Dom>,             \
1078		 typename _Dom::value_type>                            \
1079    _Fun(const valarray<typename _Dom::valarray>& __v,                 \
1080	 const _Expr<_Dom,typename _Dom::value_type>& __e)             \
1081    {                                                                  \
1082      typedef typename _Dom::value_type _Tp;                           \
1083      typedef _BinClos<__##_Fun,_ValArray,_Expr,_Tp,_Dom> _Closure;    \
1084      return _Expr<_Closure,_Tp>(_Closure(__v, __e()));                \
1085    }                                                                  \
1086                                                                       \
1087  template<class _Dom>                                                 \
1088    inline _Expr<_BinClos<__##_Fun,_Expr,_Constant,_Dom,               \
1089			  typename _Dom::value_type>,                  \
1090		 typename _Dom::value_type>                            \
1091    _Fun(const _Expr<_Dom, typename _Dom::value_type>& __e,            \
1092	 const typename _Dom::value_type& __t)                         \
1093    {                                                                  \
1094      typedef typename _Dom::value_type _Tp;                           \
1095      typedef _BinClos<__##_Fun,_Expr,_Constant,_Dom,_Tp> _Closure;    \
1096      return _Expr<_Closure,_Tp>(_Closure(__e(), __t));                \
1097    }                                                                  \
1098                                                                       \
1099  template<class _Dom>                                                 \
1100    inline _Expr<_BinClos<__##_Fun,_Constant,_Expr,                    \
1101			  typename _Dom::value_type,_Dom>,             \
1102		 typename _Dom::value_type>                            \
1103    _Fun(const typename _Dom::value_type& __t,                         \
1104	 const _Expr<_Dom,typename _Dom::value_type>& __e)             \
1105    {                                                                  \
1106      typedef typename _Dom::value_type _Tp;                           \
1107      typedef _BinClos<__##_Fun, _Constant,_Expr,_Tp,_Dom> _Closure;   \
1108      return _Expr<_Closure,_Tp>(_Closure(__t, __e()));                \
1109    }                                                                  \
1110                                                                       \
1111  template<typename _Tp>                                               \
1112    inline _Expr<_BinClos<__##_Fun,_ValArray,_ValArray,_Tp,_Tp>, _Tp>  \
1113    _Fun(const valarray<_Tp>& __v, const valarray<_Tp>& __w)           \
1114    {                                                                  \
1115      typedef _BinClos<__##_Fun,_ValArray,_ValArray,_Tp,_Tp> _Closure; \
1116      return _Expr<_Closure,_Tp>(_Closure(__v, __w));                  \
1117    }                                                                  \
1118                                                                       \
1119  template<typename _Tp>                                               \
1120    inline _Expr<_BinClos<__##_Fun,_ValArray,_Constant,_Tp,_Tp>,_Tp>   \
1121    _Fun(const valarray<_Tp>& __v, const _Tp& __t)                     \
1122    {                                                                  \
1123      typedef _BinClos<__##_Fun,_ValArray,_Constant,_Tp,_Tp> _Closure; \
1124      return _Expr<_Closure,_Tp>(_Closure(__v, __t));                  \
1125    }                                                                  \
1126								       \
1127  template<typename _Tp>                                               \
1128    inline _Expr<_BinClos<__##_Fun,_Constant,_ValArray,_Tp,_Tp>,_Tp>   \
1129    _Fun(const _Tp& __t, const valarray<_Tp>& __v)                     \
1130    {                                                                  \
1131      typedef _BinClos<__##_Fun,_Constant,_ValArray,_Tp,_Tp> _Closure; \
1132      return _Expr<_Closure,_Tp>(_Closure(__t, __v));                  \
1133    }
1134
1135_DEFINE_EXPR_BINARY_FUNCTION(atan2)
1136_DEFINE_EXPR_BINARY_FUNCTION(pow)
1137
1138#undef _DEFINE_EXPR_BINARY_FUNCTION
1139
1140} // std::
1141
1142
1143#endif /* _CPP_VALARRAY_META_H */
1144
1145// Local Variables:
1146// mode:c++
1147// End:
1148