xref: /openbsd-src/gnu/lib/libstdc++/libstdc++/include/bits/valarray_meta.h (revision 03a78d155d6fff5698289342b62759a75b20d130)
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 
42 namespace 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>
operator__abs67       _Tp operator()(const _Tp& __t) const { return abs(__t); }
68   };
69 
70   struct __cos
71   {
72     template<typename _Tp>
operator__cos73       _Tp operator()(const _Tp& __t) const { return cos(__t); }
74   };
75 
76   struct __acos
77   {
78     template<typename _Tp>
operator__acos79       _Tp operator()(const _Tp& __t) const { return acos(__t); }
80   };
81 
82   struct __cosh
83   {
84     template<typename _Tp>
operator__cosh85       _Tp operator()(const _Tp& __t) const { return cosh(__t); }
86   };
87 
88   struct __sin
89   {
90     template<typename _Tp>
operator__sin91       _Tp operator()(const _Tp& __t) const { return sin(__t); }
92   };
93 
94   struct __asin
95   {
96     template<typename _Tp>
operator__asin97       _Tp operator()(const _Tp& __t) const { return asin(__t); }
98   };
99 
100   struct __sinh
101   {
102     template<typename _Tp>
operator__sinh103       _Tp operator()(const _Tp& __t) const { return sinh(__t); }
104   };
105 
106   struct __tan
107   {
108     template<typename _Tp>
operator__tan109       _Tp operator()(const _Tp& __t) const { return tan(__t); }
110   };
111 
112   struct __atan
113   {
114     template<typename _Tp>
operator__atan115       _Tp operator()(const _Tp& __t) const { return atan(__t); }
116   };
117 
118   struct __tanh
119   {
120     template<typename _Tp>
operator__tanh121       _Tp operator()(const _Tp& __t) const { return tanh(__t); }
122   };
123 
124   struct __exp
125   {
126     template<typename _Tp>
operator__exp127       _Tp operator()(const _Tp& __t) const { return exp(__t); }
128   };
129 
130   struct __log
131   {
132     template<typename _Tp>
operator__log133       _Tp operator()(const _Tp& __t) const { return log(__t); }
134   };
135 
136   struct __log10
137   {
138     template<typename _Tp>
operator__log10139       _Tp operator()(const _Tp& __t) const { return log10(__t); }
140   };
141 
142   struct __sqrt
143   {
144     template<typename _Tp>
operator__sqrt145       _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>
operator__unary_plus155       _Tp operator()(const _Tp& __t) const { return +__t; }
156   };
157 
158   struct __negate
159   {
160     template<typename _Tp>
operator__negate161       _Tp operator()(const _Tp& __t) const { return -__t; }
162   };
163 
164   struct __bitwise_not
165   {
166     template<typename _Tp>
operator__bitwise_not167       _Tp operator()(const _Tp& __t) const { return ~__t; }
168   };
169 
170   struct __plus
171   {
172     template<typename _Tp>
operator__plus173       _Tp operator()(const _Tp& __x, const _Tp& __y) const
174       { return __x + __y; }
175   };
176 
177   struct __minus
178   {
179     template<typename _Tp>
operator__minus180       _Tp operator()(const _Tp& __x, const _Tp& __y) const
181       { return __x - __y; }
182   };
183 
184   struct __multiplies
185   {
186     template<typename _Tp>
operator__multiplies187       _Tp operator()(const _Tp& __x, const _Tp& __y) const
188       { return __x * __y; }
189   };
190 
191   struct __divides
192   {
193     template<typename _Tp>
operator__divides194       _Tp operator()(const _Tp& __x, const _Tp& __y) const
195       { return __x / __y; }
196   };
197 
198   struct __modulus
199   {
200     template<typename _Tp>
operator__modulus201       _Tp operator()(const _Tp& __x, const _Tp& __y) const
202       { return __x % __y; }
203   };
204 
205   struct __bitwise_xor
206   {
207     template<typename _Tp>
operator__bitwise_xor208       _Tp operator()(const _Tp& __x, const _Tp& __y) const
209       { return __x ^ __y; }
210   };
211 
212   struct __bitwise_and
213   {
214     template<typename _Tp>
operator__bitwise_and215       _Tp operator()(const _Tp& __x, const _Tp& __y) const
216       { return __x & __y; }
217   };
218 
219   struct __bitwise_or
220   {
221     template<typename _Tp>
operator__bitwise_or222       _Tp operator()(const _Tp& __x, const _Tp& __y) const
223       { return __x | __y; }
224   };
225 
226   struct __shift_left
227   {
228     template<typename _Tp>
operator__shift_left229       _Tp operator()(const _Tp& __x, const _Tp& __y) const
230       { return __x << __y; }
231   };
232 
233   struct __shift_right
234   {
235     template<typename _Tp>
operator__shift_right236       _Tp operator()(const _Tp& __x, const _Tp& __y) const
237       { return __x >> __y; }
238   };
239 
240   struct __logical_and
241   {
242     template<typename _Tp>
operator__logical_and243       bool operator()(const _Tp& __x, const _Tp& __y) const
244       { return __x && __y; }
245   };
246 
247   struct __logical_or
248   {
249     template<typename _Tp>
operator__logical_or250       bool operator()(const _Tp& __x, const _Tp& __y) const
251       { return __x || __y; }
252   };
253 
254   struct __logical_not
255   {
256     template<typename _Tp>
operator__logical_not257       bool operator()(const _Tp& __x) const { return !__x; }
258   };
259 
260   struct __equal_to
261   {
262     template<typename _Tp>
operator__equal_to263       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>
operator__not_equal_to270       bool operator()(const _Tp& __x, const _Tp& __y) const
271       { return __x != __y; }
272   };
273 
274   struct __less
275   {
276     template<typename _Tp>
operator__less277       bool operator()(const _Tp& __x, const _Tp& __y) const
278       { return __x < __y; }
279   };
280 
281   struct __greater
282   {
283     template<typename _Tp>
operator__greater284       bool operator()(const _Tp& __x, const _Tp& __y) const
285       { return __x > __y; }
286   };
287 
288   struct __less_equal
289   {
290     template<typename _Tp>
operator__less_equal291       bool operator()(const _Tp& __x, const _Tp& __y) const
292       { return __x <= __y; }
293   };
294 
295   struct __greater_equal
296   {
297     template<typename _Tp>
operator__greater_equal298       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>
operator__atan2306       _Tp operator()(const _Tp& __x, const _Tp& __y) const
307       { return atan2(__x, __y); }
308   };
309 
310   struct __pow
311   {
312     template<typename _Tp>
operator__pow313       _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                                                                         \
947 template<class _Dom>                                                    \
948 inline _Expr<_BinClos<_Name,_Expr,_Constant,_Dom,typename _Dom::value_type>,\
949              typename __fun<_Name, typename _Dom::value_type>::result_type>\
950 operator _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                                                                         \
959 template<class _Dom>                                                    \
960 inline _Expr<_BinClos<_Name,_Constant,_Expr,typename _Dom::value_type,_Dom>,\
961              typename __fun<_Name, typename _Dom::value_type>::result_type>\
962 operator _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                                                                         \
971 template<class _Dom>                                                    \
972 inline _Expr<_BinClos<_Name,_Expr,_ValArray,_Dom,typename _Dom::value_type>,\
973              typename __fun<_Name, typename _Dom::value_type>::result_type>\
974 operator _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                                                                         \
983 template<class _Dom>                                                    \
984 inline _Expr<_BinClos<_Name,_ValArray,_Expr,typename _Dom::value_type,_Dom>,\
985              typename __fun<_Name, typename _Dom::value_type>::result_type>\
986 operator _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