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