OSDN Git Service

2002-01-16 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / valarray_meta.h
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     //
46     // Implementing a loosened valarray return value is tricky.
47     // First we need to meet 26.3.1/3: we should not add more than
48     // two levels of template nesting. Therefore we resort to template
49     // template to "flatten" loosened return value types.
50     // At some point we use partial specialization to remove one level
51     // template nesting due to _Expr<>
52     //
53     
54
55     // This class is NOT defined. It doesn't need to.
56     template<typename _Tp1, typename _Tp2> class _Constant;
57
58     //
59     // Unary function application closure.
60     //
61     template<class _Dom> class _UnFunBase {
62     public:
63         typedef typename _Dom::value_type value_type;
64         typedef value_type _Vt;
65         
66         _UnFunBase (const _Dom& __e, _Vt __f(_Vt))
67                 : _M_expr(__e), _M_func(__f) {}
68         
69         _Vt operator[] (size_t __i) const { return _M_func(_M_expr[__i]); }
70         size_t size () const { return _M_expr.size(); }
71         
72     private:
73         const _Dom& _M_expr;
74         _Vt (*_M_func)(_Vt);
75     };
76
77     template<template<class, class> class _Meta, class _Dom>
78         class _UnFunClos;
79     
80     template<class _Dom>
81     struct _UnFunClos<_Expr,_Dom> : _UnFunBase<_Dom> {
82         typedef _UnFunBase<_Dom> _Base;
83         typedef typename _Base::value_type value_type;
84         
85         _UnFunClos (const _Dom& __e, value_type __f(value_type))
86                 : _Base (__e, __f) {}
87     };
88     
89     template<typename _Tp>
90     struct _UnFunClos<_ValArray,_Tp> : _UnFunBase<valarray<_Tp> > {
91         typedef _UnFunBase<valarray<_Tp> > _Base;
92         typedef typename _Base::value_type value_type;
93         
94         _UnFunClos (const valarray<_Tp>& __v, _Tp __f(_Tp))
95                 : _Base (__v, __f) {}
96     };
97
98     //
99     // Binary function application closure.
100     //
101     template<template<class, class> class _Meta1,
102         template<class, class> class Meta2,
103         class _Dom1, class _Dom2> class _BinFunClos;
104     
105     template<class _Dom1, class _Dom2> class _BinFunBase {
106     public:
107         typedef typename _Dom1::value_type value_type;
108         typedef value_type _Vt;
109
110         _BinFunBase (const _Dom1& __e1, const _Dom2& __e2,
111                       _Vt __f (_Vt, _Vt))
112                 : _M_expr1 (__e1), _M_expr2 (__e2), _M_func (__f) {}
113
114         value_type operator[] (size_t __i) const
115         { return _M_func (_M_expr1[__i], _M_expr2[__i]); }
116         size_t size () const { return _M_expr1.size (); }
117
118     private:
119         const _Dom1& _M_expr1;
120         const _Dom2& _M_expr2;
121         _Vt (*_M_func)(_Vt, _Vt);
122     };
123
124     template<class _Dom> class _BinFunBase1 {
125     public:
126         typedef typename _Dom::value_type value_type ;
127         typedef value_type _Vt;
128
129         _BinFunBase1 (const _Vt& __c, const _Dom& __e, _Vt __f(_Vt, _Vt))
130                 : _M_expr1 (__c), _M_expr2 (__e), _M_func (__f) {}
131
132         value_type operator[] (size_t __i) const
133         { return _M_func (_M_expr1, _M_expr2[__i]); }
134         size_t size () const { return _M_expr2.size (); }
135
136     private:
137         const _Vt& _M_expr1;
138         const _Dom& _M_expr2;
139         _Vt (*_M_func)(_Vt, _Vt);
140     };
141
142     template<class _Dom> class _BinFunBase2 {
143     public:
144         typedef typename _Dom::value_type value_type;
145         typedef value_type _Vt;
146
147         _BinFunBase2 (const _Dom& __e, const _Vt& __c, _Vt __f(_Vt, _Vt))
148                 : _M_expr1 (__e), _M_expr2 (__c), _M_func (__f) {}
149
150         value_type operator[] (size_t __i) const
151         { return _M_func (_M_expr1[__i], _M_expr2); }
152         size_t size () const { return _M_expr1.size (); }
153
154     private:
155         const _Dom& _M_expr1;
156         const _Vt& _M_expr2;
157         _Vt (*_M_func)(_Vt, _Vt);
158     };
159
160     template<class _Dom1, class _Dom2>
161     struct _BinFunClos<_Expr,_Expr,_Dom1,_Dom2> : _BinFunBase<_Dom1,_Dom2> {
162         typedef _BinFunBase<_Dom1,_Dom2> _Base;
163         typedef typename _Base::value_type value_type;
164         typedef value_type _Tp;
165
166         _BinFunClos (const _Dom1& __e1, const _Dom2& __e2,
167                      _Tp __f(_Tp, _Tp))
168                 : _Base (__e1, __e2, __f) {}
169     };
170
171     template<typename _Tp>
172     struct _BinFunClos<_ValArray,_ValArray,_Tp,_Tp>
173         : _BinFunBase<valarray<_Tp>, valarray<_Tp> > {
174         typedef _BinFunBase<valarray<_Tp>, valarray<_Tp> > _Base;
175         typedef _Tp value_type;
176
177         _BinFunClos (const valarray<_Tp>& __v, const valarray<_Tp>& __w,
178                      _Tp __f(_Tp, _Tp))
179                 : _Base (__v, __w, __f) {}
180     };
181     
182     template<class _Dom>
183     struct _BinFunClos<_Expr,_ValArray,_Dom,typename _Dom::value_type>
184         : _BinFunBase<_Dom,valarray<typename _Dom::value_type> > {
185         typedef typename _Dom::value_type _Tp;
186         typedef _BinFunBase<_Dom,valarray<_Tp> > _Base;
187         typedef _Tp value_type;
188
189         _BinFunClos (const _Dom& __e, const valarray<_Tp>& __v,
190                      _Tp __f(_Tp, _Tp))
191                 : _Base (__e, __v, __f) {}
192     };
193
194     template<class _Dom>
195     struct _BinFunClos<_ValArray,_Expr,typename _Dom::value_type,_Dom>
196         : _BinFunBase<valarray<typename _Dom::value_type>,_Dom> {
197         typedef typename _Dom::value_type _Tp;
198         typedef _BinFunBase<_Dom,valarray<_Tp> > _Base;
199         typedef _Tp value_type;
200
201         _BinFunClos (const valarray<_Tp>& __v, const _Dom& __e,
202                      _Tp __f(_Tp, _Tp))
203                 : _Base (__v, __e, __f) {}
204     };
205
206     template<class _Dom>
207     struct _BinFunClos<_Expr,_Constant,_Dom,typename _Dom::value_type>
208         : _BinFunBase2<_Dom> {
209         typedef typename _Dom::value_type _Tp;
210         typedef _Tp value_type;
211         typedef _BinFunBase2<_Dom> _Base;
212
213         _BinFunClos (const _Dom& __e, const _Tp& __t, _Tp __f (_Tp, _Tp))
214                 : _Base (__e, __t, __f) {}
215     };
216
217     template<class _Dom>
218     struct _BinFunClos<_Constant,_Expr,_Dom,typename _Dom::value_type>
219         : _BinFunBase1<_Dom> {
220         typedef typename _Dom::value_type _Tp;
221         typedef _Tp value_type;
222         typedef _BinFunBase1<_Dom> _Base;
223
224         _BinFunClos (const _Tp& __t, const _Dom& __e, _Tp __f (_Tp, _Tp))
225                 : _Base (__t, __e, __f) {}
226     };
227
228     template<typename _Tp>
229     struct _BinFunClos<_ValArray,_Constant,_Tp,_Tp>
230         : _BinFunBase2<valarray<_Tp> > {
231         typedef _BinFunBase2<valarray<_Tp> > _Base;
232         typedef _Tp value_type;
233
234         _BinFunClos (const valarray<_Tp>& __v, const _Tp& __t,
235                      _Tp __f(_Tp, _Tp))
236                 : _Base (__v, __t, __f) {}
237     };
238
239     template<typename _Tp>
240     struct _BinFunClos<_Constant,_ValArray,_Tp,_Tp>
241         : _BinFunBase1<valarray<_Tp> > {
242         typedef _BinFunBase1<valarray<_Tp> > _Base;
243         typedef _Tp value_type;
244
245         _BinFunClos (const _Tp& __t, const valarray<_Tp>& __v,
246                      _Tp __f (_Tp, _Tp))
247                 : _Base (__t, __v, __f) {}
248     };
249
250     //
251     // Apply function taking a value/const reference closure
252     //
253
254     template<typename _Dom, typename _Arg> class _FunBase {
255     public:
256         typedef typename _Dom::value_type value_type;
257
258         _FunBase (const _Dom& __e, value_type __f(_Arg))
259                 : _M_expr (__e), _M_func (__f) {}
260
261         value_type operator[] (size_t __i) const
262         { return _M_func (_M_expr[__i]); }
263         size_t size() const { return _M_expr.size ();}
264
265     private:
266         const _Dom& _M_expr;
267         value_type (*_M_func)(_Arg);
268     };
269
270     template<class _Dom>
271     struct _ValFunClos<_Expr,_Dom>
272         : _FunBase<_Dom, typename _Dom::value_type> {
273         typedef _FunBase<_Dom, typename _Dom::value_type> _Base;
274         typedef typename _Base::value_type value_type;
275         typedef value_type _Tp;
276     
277         _ValFunClos (const _Dom& __e, _Tp __f (_Tp)) : _Base (__e, __f) {}
278     };
279
280     template<typename _Tp>
281     struct _ValFunClos<_ValArray,_Tp>
282         : _FunBase<valarray<_Tp>, _Tp> {
283         typedef _FunBase<valarray<_Tp>, _Tp> _Base;
284         typedef _Tp value_type;
285
286         _ValFunClos (const valarray<_Tp>& __v, _Tp __f(_Tp))
287                 : _Base (__v, __f) {}
288     };
289
290     template<class _Dom>
291     struct _RefFunClos<_Expr,_Dom> :
292         _FunBase<_Dom, const typename _Dom::value_type&> {
293         typedef _FunBase<_Dom, const typename _Dom::value_type&> _Base;
294         typedef typename _Base::value_type value_type;
295         typedef value_type _Tp;
296
297         _RefFunClos (const _Dom& __e, _Tp __f (const _Tp&))
298                 : _Base (__e, __f) {}
299     };
300
301     template<typename _Tp>
302     struct _RefFunClos<_ValArray,_Tp>
303         : _FunBase<valarray<_Tp>, const _Tp&> {
304         typedef _FunBase<valarray<_Tp>, const _Tp&> _Base;
305         typedef _Tp value_type;
306         
307         _RefFunClos (const valarray<_Tp>& __v, _Tp __f(const _Tp&))
308                 : _Base (__v, __f) {}
309     };
310     
311     //
312     // Unary expression closure.
313     //
314
315     template<template<class> class _Oper, typename _Arg>
316     class _UnBase {
317     public:
318         typedef _Oper<typename _Arg::value_type> _Op;
319         typedef typename _Op::result_type value_type;
320
321         _UnBase (const _Arg& __e) : _M_expr(__e) {}
322         value_type operator[] (size_t) const;
323         size_t size () const { return _M_expr.size (); }
324
325     private:
326         const _Arg& _M_expr;
327     };
328
329     template<template<class> class _Oper, typename _Arg>
330     inline typename _UnBase<_Oper, _Arg>::value_type
331     _UnBase<_Oper, _Arg>::operator[] (size_t __i) const
332     { return _Op() (_M_expr[__i]); }
333     
334     template<template<class> class _Oper, class _Dom>
335     struct _UnClos<_Oper, _Expr, _Dom> :  _UnBase<_Oper, _Dom> {
336         typedef _Dom _Arg;
337         typedef _UnBase<_Oper, _Dom> _Base;
338         typedef typename _Base::value_type value_type;
339         
340         _UnClos (const _Arg& __e) : _Base(__e) {}
341     };
342
343     template<template<class> class _Oper, typename _Tp>
344     struct _UnClos<_Oper, _ValArray, _Tp> : _UnBase<_Oper, valarray<_Tp> > {
345         typedef valarray<_Tp> _Arg;
346         typedef _UnBase<_Oper, valarray<_Tp> > _Base;
347         typedef typename _Base::value_type value_type;
348
349         _UnClos (const _Arg& __e) : _Base(__e) {}
350     };
351
352
353     //
354     // Binary expression closure.
355     //
356
357     template<template<class> class _Oper,
358         typename _FirstArg, typename _SecondArg>
359     class _BinBase {
360     public:
361         typedef _Oper<typename _FirstArg::value_type> _Op;
362         typedef typename _Op::result_type value_type;
363
364         _BinBase (const _FirstArg& __e1, const _SecondArg& __e2)
365                 : _M_expr1 (__e1), _M_expr2 (__e2) {}
366         value_type operator[] (size_t) const;
367         size_t size () const { return _M_expr1.size (); }
368         
369     private:
370         const _FirstArg& _M_expr1;
371         const _SecondArg& _M_expr2;
372     };
373
374     template<template<class> class _Oper,
375         typename _FirstArg, typename _SecondArg>
376     inline typename _BinBase<_Oper,_FirstArg,_SecondArg>::value_type
377     _BinBase<_Oper,_FirstArg,_SecondArg>::operator[] (size_t __i) const
378     { return _Op() (_M_expr1[__i], _M_expr2[__i]); }
379
380
381     template<template<class> class _Oper, class _Clos>
382     class _BinBase2 {
383     public:
384         typedef typename _Clos::value_type _Vt;
385         typedef _Oper<_Vt> _Op;
386         typedef typename _Op::result_type value_type;
387
388         _BinBase2 (const _Clos& __e, const _Vt& __t)
389                 : _M_expr1 (__e), _M_expr2 (__t) {}
390         value_type operator[] (size_t) const;
391         size_t size () const { return _M_expr1.size (); }
392
393     private:
394         const _Clos& _M_expr1;
395         const _Vt& _M_expr2;
396     };
397
398     template<template<class> class _Oper, class _Clos>
399     inline typename _BinBase2<_Oper,_Clos>::value_type
400     _BinBase2<_Oper,_Clos>::operator[] (size_t __i) const
401     { return _Op() (_M_expr1[__i], _M_expr2); }
402
403
404     template<template<class> class _Oper, class _Clos>
405     class _BinBase1 {
406     public:
407         typedef typename _Clos::value_type _Vt;
408         typedef _Oper<_Vt> _Op;
409         typedef typename _Op::result_type value_type;
410
411         _BinBase1 (const _Vt& __t, const _Clos& __e)
412                 : _M_expr1 (__t), _M_expr2 (__e) {}
413         value_type operator[] (size_t) const;
414         size_t size () const { return _M_expr2.size (); }
415
416     private:
417         const _Vt& _M_expr1;
418         const _Clos& _M_expr2;
419     };
420
421     template<template<class> class _Oper, class _Clos>
422     inline typename
423     _BinBase1<_Oper,_Clos>::value_type
424     _BinBase1<_Oper,_Clos>:: operator[] (size_t __i) const
425     { return _Op() (_M_expr1, _M_expr2[__i]); }
426
427     
428     template<template<class> class _Oper, class _Dom1, class _Dom2>
429     struct  _BinClos<_Oper, _Expr, _Expr, _Dom1, _Dom2>
430         : _BinBase<_Oper,_Dom1,_Dom2> {
431         typedef _BinBase<_Oper,_Dom1,_Dom2> _Base;
432         typedef typename _Base::value_type value_type;
433         
434         _BinClos(const _Dom1& __e1, const _Dom2& __e2) : _Base(__e1, __e2) {}
435     };
436
437     template<template<class> class _Oper, typename _Tp>
438     struct _BinClos<_Oper,_ValArray,_ValArray,_Tp,_Tp>
439         : _BinBase<_Oper,valarray<_Tp>,valarray<_Tp> > {
440         typedef _BinBase<_Oper,valarray<_Tp>,valarray<_Tp> > _Base;
441         typedef _Tp value_type;
442
443         _BinClos (const valarray<_Tp>& __v, const valarray<_Tp>& __w)
444                 : _Base (__v, __w) {}
445     };
446
447     template<template<class> class _Oper, class _Dom>
448     struct  _BinClos<_Oper,_Expr,_ValArray,_Dom,typename _Dom::value_type>
449         : _BinBase<_Oper,_Dom,valarray<typename _Dom::value_type> > {
450         typedef typename _Dom::value_type _Tp;
451         typedef _BinBase<_Oper,_Dom,valarray<_Tp> > _Base;
452         typedef typename _Base::value_type value_type;
453
454         _BinClos(const _Dom& __e1, const valarray<_Tp>& __e2)
455                 : _Base (__e1, __e2) {}
456     };
457
458     template<template<class> class _Oper, class _Dom>
459     struct  _BinClos<_Oper,_ValArray,_Expr,typename _Dom::value_type,_Dom>
460         : _BinBase<_Oper,valarray<typename _Dom::value_type>,_Dom> {
461         typedef typename _Dom::value_type _Tp;
462         typedef _BinBase<_Oper,valarray<_Tp>,_Dom> _Base;
463         typedef typename _Base::value_type value_type;
464
465         _BinClos (const valarray<_Tp>& __e1, const _Dom& __e2)
466                 : _Base (__e1, __e2) {}
467     };
468
469     template<template<class> class _Oper, class _Dom>
470     struct _BinClos<_Oper,_Expr,_Constant,_Dom,typename _Dom::value_type>
471         : _BinBase2<_Oper,_Dom> {
472         typedef typename _Dom::value_type _Tp;
473         typedef _BinBase2<_Oper,_Dom> _Base;
474         typedef typename _Base::value_type value_type;
475
476         _BinClos (const _Dom& __e1, const _Tp& __e2) : _Base (__e1, __e2) {}
477     };
478
479     template<template<class> class _Oper, class _Dom>
480     struct _BinClos<_Oper,_Constant,_Expr,typename _Dom::value_type,_Dom>
481         : _BinBase1<_Oper,_Dom> {
482         typedef typename _Dom::value_type _Tp;
483         typedef _BinBase1<_Oper,_Dom> _Base;
484         typedef typename _Base::value_type value_type;
485
486         _BinClos (const _Tp& __e1, const _Dom& __e2) : _Base (__e1, __e2) {}
487     };
488     
489     template<template<class> class _Oper, typename _Tp>
490     struct _BinClos<_Oper,_ValArray,_Constant,_Tp,_Tp>
491         : _BinBase2<_Oper,valarray<_Tp> > {
492         typedef _BinBase2<_Oper,valarray<_Tp> > _Base;
493         typedef typename _Base::value_type value_type;
494
495         _BinClos (const valarray<_Tp>& __v, const _Tp& __t)
496                 : _Base (__v, __t) {}
497     };
498
499     template<template<class> class _Oper, typename _Tp>
500     struct _BinClos<_Oper,_Constant,_ValArray,_Tp,_Tp>
501         : _BinBase1<_Oper,valarray<_Tp> > {
502         typedef _BinBase1<_Oper,valarray<_Tp> > _Base;
503         typedef typename _Base::value_type value_type;
504
505         _BinClos (const _Tp& __t, const valarray<_Tp>& __v)
506                 : _Base (__t, __v) {}
507     };
508         
509
510     //
511     // slice_array closure.
512     //
513     template<typename _Dom>  class _SBase {
514     public:
515         typedef typename _Dom::value_type value_type;
516
517         _SBase (const _Dom& __e, const slice& __s)
518                 : _M_expr (__e), _M_slice (__s) {}
519         value_type operator[] (size_t __i) const
520         { return _M_expr[_M_slice.start () + __i * _M_slice.stride ()]; }
521         size_t size() const { return _M_slice.size (); }
522
523     private:
524         const _Dom& _M_expr;
525         const slice& _M_slice;
526     };
527
528     template<typename _Tp> class _SBase<_Array<_Tp> > {
529     public:
530         typedef _Tp value_type;
531
532         _SBase (_Array<_Tp> __a, const slice& __s)
533                 : _M_array (__a._M_data+__s.start()), _M_size (__s.size()),
534                   _M_stride (__s.stride()) {}
535         value_type operator[] (size_t __i) const
536         { return _M_array._M_data[__i * _M_stride]; }
537         size_t size() const { return _M_size; }
538
539     private:
540         const _Array<_Tp> _M_array;
541         const size_t _M_size;
542         const size_t _M_stride;
543     };
544
545     template<class _Dom> struct  _SClos<_Expr,_Dom> : _SBase<_Dom> {
546         typedef _SBase<_Dom> _Base;
547         typedef typename _Base::value_type value_type;
548         
549         _SClos (const _Dom& __e, const slice& __s) : _Base (__e, __s) {}
550     };
551
552     template<typename _Tp>
553     struct _SClos<_ValArray,_Tp> : _SBase<_Array<_Tp> > {
554         typedef  _SBase<_Array<_Tp> > _Base;
555         typedef _Tp value_type;
556
557         _SClos (_Array<_Tp> __a, const slice& __s) : _Base (__a, __s) {}
558     };
559
560     //
561     // gslice_array closure.
562     //
563     template<class _Dom> class _GBase {
564     public:
565         typedef typename _Dom::value_type value_type;
566         
567         _GBase (const _Dom& __e, const valarray<size_t>& __i)
568                 : _M_expr (__e), _M_index(__i) {}
569         value_type operator[] (size_t __i) const
570         { return _M_expr[_M_index[__i]]; }
571         size_t size () const { return _M_index.size(); }
572         
573     private:
574         const _Dom&      _M_expr;
575         const valarray<size_t>& _M_index;
576     };
577     
578     template<typename _Tp> class _GBase<_Array<_Tp> > {
579     public:
580         typedef _Tp value_type;
581         
582         _GBase (_Array<_Tp> __a, const valarray<size_t>& __i)
583                 : _M_array (__a), _M_index(__i) {}
584         value_type operator[] (size_t __i) const
585         { return _M_array._M_data[_M_index[__i]]; }
586         size_t size () const { return _M_index.size(); }
587         
588     private:
589         const _Array<_Tp>     _M_array;
590         const valarray<size_t>& _M_index;
591     };
592
593     template<class _Dom> struct _GClos<_Expr,_Dom> : _GBase<_Dom> {
594         typedef _GBase<_Dom> _Base;
595         typedef typename _Base::value_type value_type;
596
597         _GClos (const _Dom& __e, const valarray<size_t>& __i)
598                 : _Base (__e, __i) {}
599     };
600
601     template<typename _Tp>
602     struct _GClos<_ValArray,_Tp> : _GBase<_Array<_Tp> > {
603         typedef _GBase<_Array<_Tp> > _Base;
604         typedef typename _Base::value_type value_type;
605
606         _GClos (_Array<_Tp> __a, const valarray<size_t>& __i)
607                 : _Base (__a, __i) {}
608     };
609
610     //
611     // indirect_array closure
612     //
613
614     template<class _Dom> class _IBase {
615     public:
616         typedef typename _Dom::value_type value_type;
617
618         _IBase (const _Dom& __e, const valarray<size_t>& __i)
619                 : _M_expr (__e), _M_index (__i) {}
620         value_type operator[] (size_t __i) const
621         { return _M_expr[_M_index[__i]]; }
622         size_t size() const { return _M_index.size(); }
623         
624     private:
625         const _Dom&         _M_expr;
626         const valarray<size_t>& _M_index;
627     };
628
629     template<class _Dom> struct _IClos<_Expr,_Dom> : _IBase<_Dom> {
630         typedef _IBase<_Dom> _Base;
631         typedef typename _Base::value_type value_type;
632
633         _IClos (const _Dom& __e, const valarray<size_t>& __i)
634                 : _Base (__e, __i) {}
635     };
636
637     template<typename _Tp>
638     struct _IClos<_ValArray,_Tp>  : _IBase<valarray<_Tp> > {
639         typedef _IBase<valarray<_Tp> > _Base;
640         typedef _Tp value_type;
641
642         _IClos (const valarray<_Tp>& __a, const valarray<size_t>& __i)
643                 : _Base (__a, __i) {}
644     };
645
646     //
647     // class _Expr
648     //      
649     template<class _Clos, typename _Tp> class _Expr {
650     public:
651         typedef _Tp value_type;
652         
653         _Expr (const _Clos&);
654         
655         const _Clos& operator() () const;
656         
657         value_type operator[] (size_t) const;
658         valarray<value_type> operator[] (slice) const;
659         valarray<value_type> operator[] (const gslice&) const;
660         valarray<value_type> operator[] (const valarray<bool>&) const;
661         valarray<value_type> operator[] (const valarray<size_t>&) const;
662     
663         _Expr<_UnClos<_Unary_plus,std::_Expr,_Clos>, value_type>
664         operator+ () const;
665
666         _Expr<_UnClos<negate,std::_Expr,_Clos>, value_type>
667         operator- () const;
668
669         _Expr<_UnClos<_Bitwise_not,std::_Expr,_Clos>, value_type>
670         operator~ () const;
671
672         _Expr<_UnClos<logical_not,std::_Expr,_Clos>, bool>
673         operator! () const;
674
675         size_t size () const;
676         value_type sum () const;
677         
678         valarray<value_type> shift (int) const;
679         valarray<value_type> cshift (int) const;
680
681       value_type min() const;
682       value_type max() const;
683
684       valarray<value_type> apply(value_type (*) (const value_type&)) const;
685       valarray<value_type> apply(value_type (*) (value_type)) const;
686         
687     private:
688         const _Clos _M_closure;
689     };
690     
691     template<class _Clos, typename _Tp>
692     inline
693     _Expr<_Clos,_Tp>::_Expr (const _Clos& __c) : _M_closure(__c) {}
694     
695     template<class _Clos, typename _Tp>
696     inline const _Clos&
697     _Expr<_Clos,_Tp>::operator() () const
698     { return _M_closure; }
699
700     template<class _Clos, typename _Tp>
701     inline _Tp
702     _Expr<_Clos,_Tp>::operator[] (size_t __i) const
703     { return _M_closure[__i]; }
704
705     template<class _Clos, typename _Tp>
706     inline valarray<_Tp>
707     _Expr<_Clos,_Tp>::operator[] (slice __s) const
708     { return _M_closure[__s]; }
709     
710     template<class _Clos, typename _Tp>
711     inline valarray<_Tp>
712     _Expr<_Clos,_Tp>::operator[] (const gslice& __gs) const
713     { return _M_closure[__gs]; }
714     
715     template<class _Clos, typename _Tp>
716     inline valarray<_Tp>
717     _Expr<_Clos,_Tp>::operator[] (const valarray<bool>& __m) const
718     { return _M_closure[__m]; }
719     
720     template<class _Clos, typename _Tp>
721     inline valarray<_Tp>
722     _Expr<_Clos,_Tp>::operator[] (const valarray<size_t>& __i) const
723     { return _M_closure[__i]; }
724     
725     template<class _Clos, typename _Tp>
726     inline size_t
727     _Expr<_Clos,_Tp>::size () const  { return _M_closure.size (); }
728
729   template<class _Clos, typename _Tp>
730   inline valarray<_Tp>
731   _Expr<_Clos, _Tp>::shift(int __n) const
732   { return valarray<_Tp>(_M_closure).shift(__n); }
733
734   template<class _Clos, typename _Tp>
735   inline valarray<_Tp>
736   _Expr<_Clos, _Tp>::cshift(int __n) const
737   { return valarray<_Tp>(_M_closure).cshift(__n); }
738
739   template<class _Clos, typename _Tp>
740   inline valarray<_Tp>
741   _Expr<_Clos, _Tp>::apply(_Tp __f(const _Tp&)) const
742   { return valarray<_Tp>(_M_closure).apply(__f); }
743     
744   template<class _Clos, typename _Tp>
745   inline valarray<_Tp>
746   _Expr<_Clos, _Tp>::apply(_Tp __f(_Tp)) const
747   { return valarray<_Tp>(_M_closure).apply(__f); }
748
749     // XXX: replace this with a more robust summation algorithm.
750     template<class _Clos, typename _Tp>
751     inline _Tp
752     _Expr<_Clos,_Tp>::sum () const
753     {
754         size_t __n = _M_closure.size();
755         if (__n == 0) return _Tp();
756         else {
757             _Tp __s = _M_closure[--__n];
758             while (__n != 0) __s += _M_closure[--__n];
759             return __s;
760         }
761     }
762
763   template<class _Clos, typename _Tp>
764   inline _Tp
765   _Expr<_Clos, _Tp>::min() const
766   { return __valarray_min(_M_closure); }
767
768   template<class _Clos, typename _Tp>
769   inline _Tp
770   _Expr<_Clos, _Tp>::max() const
771   { return __valarray_max(_M_closure); }
772     
773     template<class _Dom, typename _Tp>
774     inline _Expr<_UnClos<logical_not,_Expr,_Dom>, bool>
775     _Expr<_Dom,_Tp>::operator! () const
776     {
777         typedef _UnClos<logical_not,std::_Expr,_Dom> _Closure;
778         return _Expr<_Closure,_Tp> (_Closure(this->_M_closure));
779     }
780
781 #define _DEFINE_EXPR_UNARY_OPERATOR(_Op, _Name)                         \
782 template<class _Dom, typename _Tp>                                      \
783 inline _Expr<_UnClos<_Name,std::_Expr,_Dom>,_Tp>                        \
784 _Expr<_Dom,_Tp>::operator _Op () const                                 \
785 {                                                                       \
786     typedef _UnClos<_Name,std::_Expr,_Dom> _Closure;                    \
787     return _Expr<_Closure,_Tp> (_Closure (this->_M_closure));           \
788 }
789
790     _DEFINE_EXPR_UNARY_OPERATOR(+, _Unary_plus)
791     _DEFINE_EXPR_UNARY_OPERATOR(-, negate)
792     _DEFINE_EXPR_UNARY_OPERATOR(~, _Bitwise_not)
793
794 #undef _DEFINE_EXPR_UNARY_OPERATOR
795
796
797 #define _DEFINE_EXPR_BINARY_OPERATOR(_Op, _Name)                        \
798 template<class _Dom1, class _Dom2>                                      \
799 inline _Expr<_BinClos<_Name,_Expr,_Expr,_Dom1,_Dom2>,                   \
800              typename _Name<typename _Dom1::value_type>::result_type>   \
801 operator _Op (const _Expr<_Dom1,typename _Dom1::value_type>& __v,      \
802               const _Expr<_Dom2,typename _Dom2::value_type>& __w)       \
803 {                                                                       \
804     typedef typename _Dom1::value_type _Arg;                            \
805     typedef typename _Name<_Arg>::result_type _Value;                   \
806     typedef _BinClos<_Name,_Expr,_Expr,_Dom1,_Dom2> _Closure;           \
807     return _Expr<_Closure,_Value> (_Closure (__v (), __w ()));          \
808 }                                                                       \
809                                                                         \
810 template<class _Dom>                                                    \
811 inline _Expr<_BinClos<_Name,_Expr,_Constant,_Dom,typename _Dom::value_type>, \
812              typename _Name<typename _Dom::value_type>::result_type>    \
813 operator _Op (const _Expr<_Dom,typename _Dom::value_type>& __v,        \
814               const typename _Dom::value_type& __t)                     \
815 {                                                                       \
816     typedef typename _Dom::value_type _Arg;                             \
817     typedef typename _Name<_Arg>::result_type _Value;                   \
818     typedef _BinClos<_Name,_Expr,_Constant,_Dom,_Arg> _Closure;         \
819     return _Expr<_Closure,_Value> (_Closure (__v (), __t));             \
820 }                                                                       \
821                                                                         \
822 template<class _Dom>                                                    \
823 inline _Expr<_BinClos<_Name,_Constant,_Expr,typename _Dom::value_type,_Dom>, \
824              typename _Name<typename _Dom::value_type>::result_type>    \
825 operator _Op (const typename _Dom::value_type& __t,                    \
826                const _Expr<_Dom,typename _Dom::value_type>& __v)        \
827 {                                                                       \
828     typedef typename _Dom::value_type _Arg;                             \
829     typedef typename _Name<_Arg>::result_type _Value;                   \
830     typedef _BinClos<_Name,_Constant,_Expr,_Arg,_Dom> _Closure;         \
831     return _Expr<_Closure,_Value> (_Closure (__t, __v ()));             \
832 }                                                                       \
833                                                                         \
834 template<class _Dom>                                                    \
835 inline _Expr<_BinClos<_Name,_Expr,_ValArray,_Dom,typename _Dom::value_type>, \
836              typename _Name<typename _Dom::value_type>::result_type>    \
837 operator _Op (const _Expr<_Dom,typename _Dom::value_type>& __e,        \
838                const valarray<typename _Dom::value_type>& __v)          \
839 {                                                                       \
840     typedef typename _Dom::value_type _Arg;                             \
841     typedef typename _Name<_Arg>::result_type _Value;                   \
842     typedef _BinClos<_Name,_Expr,_ValArray,_Dom,_Arg> _Closure;         \
843     return  _Expr<_Closure,_Value> (_Closure (__e (), __v));            \
844 }                                                                       \
845                                                                         \
846 template<class _Dom>                                                    \
847 inline _Expr<_BinClos<_Name,_ValArray,_Expr,typename _Dom::value_type,_Dom>, \
848              typename _Name<typename _Dom::value_type>::result_type>    \
849 operator _Op (const valarray<typename _Dom::value_type>& __v,          \
850                const _Expr<_Dom,typename _Dom::value_type>& __e)        \
851 {                                                                       \
852     typedef typename _Dom::value_type _Tp;                              \
853     typedef typename _Name<_Tp>::result_type _Value;                    \
854     typedef _BinClos<_Name,_ValArray,_Expr,_Tp,_Dom> _Closure;          \
855     return _Expr<_Closure,_Value> (_Closure (__v, __e ()));             \
856 }
857
858     _DEFINE_EXPR_BINARY_OPERATOR(+, plus)
859     _DEFINE_EXPR_BINARY_OPERATOR(-, minus)
860     _DEFINE_EXPR_BINARY_OPERATOR(*, multiplies)
861     _DEFINE_EXPR_BINARY_OPERATOR(/, divides)
862     _DEFINE_EXPR_BINARY_OPERATOR(%, modulus)
863     _DEFINE_EXPR_BINARY_OPERATOR(^, _Bitwise_xor)
864     _DEFINE_EXPR_BINARY_OPERATOR(&, _Bitwise_and)
865     _DEFINE_EXPR_BINARY_OPERATOR(|, _Bitwise_or)
866     _DEFINE_EXPR_BINARY_OPERATOR(<<, _Shift_left)
867     _DEFINE_EXPR_BINARY_OPERATOR(>>, _Shift_right)
868
869 #undef _DEFINE_EXPR_BINARY_OPERATOR
870     
871 #define _DEFINE_EXPR_RELATIONAL_OPERATOR(_Op, _Name)                    \
872 template<class _Dom1, class _Dom2>                                      \
873 inline _Expr<_BinClos<_Name,_Expr,_Expr,_Dom1,_Dom2>, bool>             \
874 operator _Op (const _Expr<_Dom1,typename _Dom1::value_type>& __v,      \
875               const _Expr<_Dom2,typename _Dom2::value_type>& __w)       \
876 {                                                                       \
877     typedef typename _Dom1::value_type _Arg;                            \
878     typedef _BinClos<_Name,_Expr,_Expr,_Dom1,_Dom2> _Closure;           \
879     return _Expr<_Closure,bool> (_Closure (__v (), __w ()));            \
880 }                                                                       \
881                                                                         \
882 template<class _Dom>                                                    \
883 inline _Expr<_BinClos<_Name,_Expr,_Constant,_Dom,typename _Dom::value_type>, \
884              bool>                                                      \
885 operator _Op (const _Expr<_Dom,typename _Dom::value_type>& __v,        \
886               const typename _Dom::value_type& __t)                     \
887 {                                                                       \
888     typedef typename _Dom::value_type _Arg;                             \
889     typedef _BinClos<_Name,_Expr,_Constant,_Dom,_Arg> _Closure;         \
890     return _Expr<_Closure,bool> (_Closure (__v (), __t));               \
891 }                                                                       \
892                                                                         \
893 template<class _Dom>                                                    \
894 inline _Expr<_BinClos<_Name,_Constant,_Expr,typename _Dom::value_type,_Dom>, \
895              bool>                                                      \
896 operator _Op (const typename _Dom::value_type& __t,                    \
897                const _Expr<_Dom,typename _Dom::value_type>& __v)        \
898 {                                                                       \
899     typedef typename _Dom::value_type _Arg;                             \
900     typedef _BinClos<_Name,_Constant,_Expr,_Arg,_Dom> _Closure;         \
901     return _Expr<_Closure,bool> (_Closure (__t, __v ()));               \
902 }                                                                       \
903                                                                         \
904 template<class _Dom>                                                    \
905 inline _Expr<_BinClos<_Name,_Expr,_ValArray,_Dom,typename _Dom::value_type>, \
906              bool>                                                      \
907 operator _Op (const _Expr<_Dom,typename _Dom::value_type>& __e,        \
908                const valarray<typename _Dom::value_type>& __v)          \
909 {                                                                       \
910     typedef typename _Dom::value_type _Tp;                              \
911     typedef _BinClos<_Name,_Expr,_ValArray,_Dom,_Tp> _Closure;          \
912     return  _Expr<_Closure,bool> (_Closure (__e (), __v));              \
913 }                                                                       \
914                                                                         \
915 template<class _Dom>                                                    \
916 inline _Expr<_BinClos<_Name,_ValArray,_Expr,typename _Dom::value_type,_Dom>, \
917              bool>                                                      \
918 operator _Op (const valarray<typename _Dom::value_type>& __v,          \
919                const _Expr<_Dom,typename _Dom::value_type>& __e)        \
920 {                                                                       \
921     typedef typename _Dom::value_type _Tp;                              \
922     typedef _BinClos<_Name,_ValArray,_Expr,_Tp,_Dom> _Closure;          \
923     return _Expr<_Closure,bool> (_Closure (__v, __e ()));               \
924 }
925
926     _DEFINE_EXPR_RELATIONAL_OPERATOR(&&, logical_and)
927     _DEFINE_EXPR_RELATIONAL_OPERATOR(||, logical_or)
928     _DEFINE_EXPR_RELATIONAL_OPERATOR(==, equal_to)
929     _DEFINE_EXPR_RELATIONAL_OPERATOR(!=, not_equal_to)
930     _DEFINE_EXPR_RELATIONAL_OPERATOR(<, less)
931     _DEFINE_EXPR_RELATIONAL_OPERATOR(>, greater)
932     _DEFINE_EXPR_RELATIONAL_OPERATOR(<=, less_equal)
933     _DEFINE_EXPR_RELATIONAL_OPERATOR(>=, greater_equal)
934
935 #undef _DEFINE_EXPR_RELATIONAL_OPERATOR
936
937
938
939 #define _DEFINE_EXPR_UNARY_FUNCTION(_Name)                              \
940 template<class _Dom>                                                    \
941 inline _Expr<_UnFunClos<_Expr,_Dom>,typename _Dom::value_type>          \
942 _Name(const _Expr<_Dom,typename _Dom::value_type>& __e)                 \
943 {                                                                       \
944     typedef typename _Dom::value_type _Tp;                              \
945     typedef _UnFunClos<_Expr,_Dom> _Closure;                            \
946     return _Expr<_Closure,_Tp>(_Closure(__e(), (_Tp(*)(_Tp))(&_Name))); \
947 }                                                                       \
948                                                                         \
949 template<typename _Tp>                                                  \
950 inline _Expr<_UnFunClos<_ValArray,_Tp>,_Tp>                             \
951 _Name(const valarray<_Tp>& __v)                                         \
952 {                                                                       \
953     typedef _UnFunClos<_ValArray,_Tp> _Closure;                         \
954     return _Expr<_Closure,_Tp> (_Closure (__v, (_Tp(*)(_Tp))(&_Name))); \
955 }
956
957
958     _DEFINE_EXPR_UNARY_FUNCTION(abs)
959     _DEFINE_EXPR_UNARY_FUNCTION(cos)
960     _DEFINE_EXPR_UNARY_FUNCTION(acos)
961     _DEFINE_EXPR_UNARY_FUNCTION(cosh)    
962     _DEFINE_EXPR_UNARY_FUNCTION(sin)
963     _DEFINE_EXPR_UNARY_FUNCTION(asin)
964     _DEFINE_EXPR_UNARY_FUNCTION(sinh)    
965     _DEFINE_EXPR_UNARY_FUNCTION(tan)
966     _DEFINE_EXPR_UNARY_FUNCTION(tanh)
967     _DEFINE_EXPR_UNARY_FUNCTION(atan)
968     _DEFINE_EXPR_UNARY_FUNCTION(exp)    
969     _DEFINE_EXPR_UNARY_FUNCTION(log)
970     _DEFINE_EXPR_UNARY_FUNCTION(log10)
971     _DEFINE_EXPR_UNARY_FUNCTION(sqrt)
972
973 #undef _DEFINE_EXPR_UNARY_FUNCTION
974
975
976 #define _DEFINE_EXPR_BINARY_FUNCTION(_Name)                             \
977 template<class _Dom1, class _Dom2>                                      \
978 inline _Expr<_BinFunClos<_Expr,_Expr,_Dom1,_Dom2>,typename _Dom1::value_type>\
979 _Name (const _Expr<_Dom1,typename _Dom1::value_type>& __e1,             \
980        const _Expr<_Dom2,typename _Dom2::value_type>& __e2)             \
981 {                                                                       \
982     typedef typename _Dom1::value_type _Tp;                             \
983     typedef _BinFunClos<_Expr,_Expr,_Dom1,_Dom2> _Closure;              \
984     return _Expr<_Closure,_Tp>                                          \
985         (_Closure (__e1 (), __e2 (), (_Tp(*)(_Tp, _Tp))(&_Name)));      \
986 }                                                                       \
987                                                                         \
988 template<class _Dom>                                                    \
989 inline _Expr<_BinFunClos<_Expr,_ValArray,_Dom,typename _Dom::value_type>, \
990              typename _Dom::value_type>                                 \
991 _Name (const _Expr<_Dom,typename _Dom::value_type>& __e,                \
992        const valarray<typename _Dom::value_type>& __v)                  \
993 {                                                                       \
994     typedef typename _Dom::value_type _Tp;                              \
995     typedef _BinFunClos<_Expr,_ValArray,_Dom,_Tp> _Closure;             \
996     return _Expr<_Closure,_Tp>                                          \
997         (_Closure (__e (), __v, (_Tp(*)(_Tp, _Tp))(&_Name)));           \
998 }                                                                       \
999                                                                         \
1000 template<class _Dom>                                                    \
1001 inline _Expr<_BinFunClos<_ValArray,_Expr,typename _Dom::value_type,_Dom>, \
1002              typename _Dom::value_type>                                 \
1003 _Name (const valarray<typename _Dom::valarray>& __v,                    \
1004        const _Expr<_Dom,typename _Dom::value_type>& __e)                \
1005 {                                                                       \
1006     typedef typename _Dom::value_type _Tp;                              \
1007     typedef _BinFunClos<_ValArray,_Expr,_Tp,_Dom> _Closure;             \
1008     return _Expr<_Closure,_Tp>                                          \
1009         (_Closure (__v, __e (), (_Tp(*)(_Tp, _Tp))(&_Name)));           \
1010 }                                                                       \
1011                                                                         \
1012 template<class _Dom>                                                    \
1013 inline _Expr<_BinFunClos<_Expr,_Constant,_Dom,typename _Dom::value_type>, \
1014              typename _Dom::value_type>                                 \
1015 _Name (const _Expr<_Dom, typename _Dom::value_type>& __e,               \
1016        const typename _Dom::value_type& __t)                            \
1017 {                                                                       \
1018     typedef typename _Dom::value_type _Tp;                              \
1019     typedef _BinFunClos<_Expr,_Constant,_Dom,_Tp> _Closure;             \
1020     return _Expr<_Closure,_Tp>                                          \
1021         (_Closure (__e (), __t, (_Tp(*)(_Tp, _Tp))(&_Name)));           \
1022 }                                                                       \
1023                                                                         \
1024 template<class _Dom>                                                    \
1025 inline _Expr<_BinFunClos<_Constant,_Expr,typename _Dom::value_type,_Dom>, \
1026              typename _Dom::value_type>                                 \
1027 _Name (const typename _Dom::value_type& __t,                            \
1028        const _Expr<_Dom,typename _Dom::value_type>& __e)                \
1029 {                                                                       \
1030     typedef typename _Dom::value_type _Tp;                              \
1031     typedef _BinFunClos<_Constant,_Expr,_Tp,_Dom> _Closure;             \
1032     return _Expr<_Closure,_Tp>                                          \
1033         (_Closure (__t, __e (), (_Tp(*)(_Tp, _Tp))(&_Name)));           \
1034 }                                                                       \
1035                                                                         \
1036 template<typename _Tp>                                                  \
1037 inline _Expr<_BinFunClos<_ValArray,_ValArray,_Tp,_Tp>, _Tp>             \
1038 _Name (const valarray<_Tp>& __v, const valarray<_Tp>& __w)              \
1039 {                                                                       \
1040     typedef _BinFunClos<_ValArray,_ValArray,_Tp,_Tp> _Closure;          \
1041     return _Expr<_Closure,_Tp>                                          \
1042         (_Closure (__v, __w, (_Tp(*)(_Tp,_Tp))(&_Name)));               \
1043 }                                                                       \
1044                                                                         \
1045 template<typename _Tp>                                                  \
1046 inline _Expr<_BinFunClos<_ValArray,_Constant,_Tp,_Tp>,_Tp>              \
1047 _Name (const valarray<_Tp>& __v, const _Tp& __t)                        \
1048 {                                                                       \
1049     typedef _BinFunClos<_ValArray,_Constant,_Tp,_Tp> _Closure;          \
1050     return _Expr<_Closure,_Tp>                                          \
1051         (_Closure (__v, __t, (_Tp(*)(_Tp,_Tp))(&_Name)));               \
1052 }                                                                       \
1053                                                                         \
1054 template<typename _Tp>                                                  \
1055 inline _Expr<_BinFunClos<_Constant,_ValArray,_Tp,_Tp>,_Tp>              \
1056 _Name (const _Tp& __t, const valarray<_Tp>& __v)                        \
1057 {                                                                       \
1058     typedef _BinFunClos<_Constant,_ValArray,_Tp,_Tp> _Closure;          \
1059     return _Expr<_Closure,_Tp>                                          \
1060         (_Closure (__t, __v, (_Tp(*)(_Tp,_Tp))(&_Name)));               \
1061 }
1062
1063 _DEFINE_EXPR_BINARY_FUNCTION(atan2)
1064 _DEFINE_EXPR_BINARY_FUNCTION(pow)
1065
1066 #undef _DEFINE_EXPR_BINARY_FUNCTION
1067
1068 } // std::
1069
1070
1071 #endif /* _CPP_VALARRAY_META_H */
1072
1073 // Local Variables:
1074 // mode:c++
1075 // End: