1// The template and inlines for the -*- C++ -*- internal _Meta class.
2
3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
4// Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16
17// You should have received a copy of the GNU General Public License along
18// with this library; see the file COPYING.  If not, write to the Free
19// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20// USA.
21
22// As a special exception, you may use this file as part of a free software
23// library without restriction.  Specifically, if other files instantiate
24// templates or use macros or inline functions from this file, or you compile
25// this file and link it with other files to produce an executable, this
26// file does not by itself cause the resulting executable to be covered by
27// the GNU General Public License.  This exception does not however
28// invalidate any other reasons why the executable file might be covered by
29// the GNU General Public License.
30
31/** @file valarray_before.h
32 *  This is an internal header file, included by other library headers.
33 *  You should not attempt to use it directly.
34 */
35
36// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@cmla.ens-cachan.fr>
37
38#ifndef _VALARRAY_BEFORE_H
39#define _VALARRAY_BEFORE_H 1
40
41#pragma GCC system_header
42
43#include <bits/slice_array.h>
44
45_GLIBCXX_BEGIN_NAMESPACE(std)
46
47  //
48  // Implementing a loosened valarray return value is tricky.
49  // First we need to meet 26.3.1/3: we should not add more than
50  // two levels of template nesting. Therefore we resort to template
51  // template to "flatten" loosened return value types.
52  // At some point we use partial specialization to remove one level
53  // template nesting due to _Expr<>
54  //
55
56  // This class is NOT defined. It doesn't need to.
57  template<typename _Tp1, typename _Tp2> class _Constant;
58
59  // Implementations of unary functions applied to valarray<>s.
60  // I use hard-coded object functions here instead of a generic
61  // approach like pointers to function:
62  //    1) correctness: some functions take references, others values.
63  //       we can't deduce the correct type afterwards.
64  //    2) efficiency -- object functions can be easily inlined
65  //    3) be Koenig-lookup-friendly
66
67  struct __abs
68  {
69    template<typename _Tp>
70      _Tp operator()(const _Tp& __t) const
71      { return abs(__t); }
72  };
73
74  struct __cos
75  {
76    template<typename _Tp>
77      _Tp operator()(const _Tp& __t) const
78      { return cos(__t); }
79  };
80
81  struct __acos
82  {
83    template<typename _Tp>
84      _Tp operator()(const _Tp& __t) const
85      { return acos(__t); }
86  };
87
88  struct __cosh
89  {
90    template<typename _Tp>
91      _Tp operator()(const _Tp& __t) const
92      { return cosh(__t); }
93  };
94
95  struct __sin
96  {
97    template<typename _Tp>
98      _Tp operator()(const _Tp& __t) const
99      { return sin(__t); }
100  };
101
102  struct __asin
103  {
104    template<typename _Tp>
105      _Tp operator()(const _Tp& __t) const
106      { return asin(__t); }
107  };
108
109  struct __sinh
110  {
111    template<typename _Tp>
112      _Tp operator()(const _Tp& __t) const
113      { return sinh(__t); }
114  };
115
116  struct __tan
117  {
118    template<typename _Tp>
119      _Tp operator()(const _Tp& __t) const
120      { return tan(__t); }
121  };
122
123  struct __atan
124  {
125    template<typename _Tp>
126      _Tp operator()(const _Tp& __t) const
127      { return atan(__t); }
128  };
129
130  struct __tanh
131  {
132    template<typename _Tp>
133      _Tp operator()(const _Tp& __t) const
134      { return tanh(__t); }
135  };
136
137  struct __exp
138  {
139    template<typename _Tp>
140      _Tp operator()(const _Tp& __t) const
141      { return exp(__t); }
142  };
143
144  struct __log
145  {
146    template<typename _Tp>
147      _Tp operator()(const _Tp& __t) const
148      { return log(__t); }
149  };
150
151  struct __log10
152  {
153    template<typename _Tp>
154      _Tp operator()(const _Tp& __t) const
155      { return log10(__t); }
156  };
157
158  struct __sqrt
159  {
160    template<typename _Tp>
161      _Tp operator()(const _Tp& __t) const
162      { return sqrt(__t); }
163  };
164
165  // In the past, we used to tailor operator applications semantics
166  // to the specialization of standard function objects (i.e. plus<>, etc.)
167  // That is incorrect.  Therefore we provide our own surrogates.
168
169  struct __unary_plus
170  {
171    template<typename _Tp>
172      _Tp operator()(const _Tp& __t) const
173      { return +__t; }
174  };
175
176  struct __negate
177  {
178    template<typename _Tp>
179      _Tp operator()(const _Tp& __t) const
180      { return -__t; }
181  };
182
183  struct __bitwise_not
184  {
185    template<typename _Tp>
186      _Tp operator()(const _Tp& __t) const
187      { return ~__t; }
188  };
189
190  struct __plus
191  {
192    template<typename _Tp>
193      _Tp operator()(const _Tp& __x, const _Tp& __y) const
194      { return __x + __y; }
195  };
196
197  struct __minus
198  {
199    template<typename _Tp>
200      _Tp operator()(const _Tp& __x, const _Tp& __y) const
201      { return __x - __y; }
202  };
203
204  struct __multiplies
205  {
206    template<typename _Tp>
207      _Tp operator()(const _Tp& __x, const _Tp& __y) const
208      { return __x * __y; }
209  };
210
211  struct __divides
212  {
213    template<typename _Tp>
214      _Tp operator()(const _Tp& __x, const _Tp& __y) const
215      { return __x / __y; }
216  };
217
218  struct __modulus
219  {
220    template<typename _Tp>
221      _Tp operator()(const _Tp& __x, const _Tp& __y) const
222      { return __x % __y; }
223  };
224
225  struct __bitwise_xor
226  {
227    template<typename _Tp>
228      _Tp operator()(const _Tp& __x, const _Tp& __y) const
229      { return __x ^ __y; }
230  };
231
232  struct __bitwise_and
233  {
234    template<typename _Tp>
235      _Tp operator()(const _Tp& __x, const _Tp& __y) const
236      { return __x & __y; }
237  };
238
239  struct __bitwise_or
240  {
241    template<typename _Tp>
242      _Tp operator()(const _Tp& __x, const _Tp& __y) const
243      { return __x | __y; }
244  };
245
246  struct __shift_left
247  {
248    template<typename _Tp>
249      _Tp operator()(const _Tp& __x, const _Tp& __y) const
250      { return __x << __y; }
251  };
252
253  struct __shift_right
254  {
255    template<typename _Tp>
256      _Tp operator()(const _Tp& __x, const _Tp& __y) const
257      { return __x >> __y; }
258  };
259
260  struct __logical_and
261  {
262    template<typename _Tp>
263      bool operator()(const _Tp& __x, const _Tp& __y) const
264      { return __x && __y; }
265  };
266
267  struct __logical_or
268  {
269    template<typename _Tp>
270      bool operator()(const _Tp& __x, const _Tp& __y) const
271      { return __x || __y; }
272  };
273
274  struct __logical_not
275  {
276    template<typename _Tp>
277      bool operator()(const _Tp& __x) const { return !__x; }
278  };
279
280  struct __equal_to
281  {
282    template<typename _Tp>
283      bool operator()(const _Tp& __x, const _Tp& __y) const
284      { return __x == __y; }
285  };
286
287  struct __not_equal_to
288  {
289    template<typename _Tp>
290      bool operator()(const _Tp& __x, const _Tp& __y) const
291      { return __x != __y; }
292  };
293
294  struct __less
295  {
296    template<typename _Tp>
297      bool operator()(const _Tp& __x, const _Tp& __y) const
298      { return __x < __y; }
299  };
300
301  struct __greater
302  {
303    template<typename _Tp>
304      bool operator()(const _Tp& __x, const _Tp& __y) const
305      { return __x > __y; }
306  };
307
308  struct __less_equal
309  {
310    template<typename _Tp>
311      bool operator()(const _Tp& __x, const _Tp& __y) const
312      { return __x <= __y; }
313  };
314
315  struct __greater_equal
316  {
317    template<typename _Tp>
318      bool operator()(const _Tp& __x, const _Tp& __y) const
319      { return __x >= __y; }
320  };
321
322  // The few binary functions we miss.
323  struct __atan2
324  {
325    template<typename _Tp>
326      _Tp operator()(const _Tp& __x, const _Tp& __y) const
327      { return atan2(__x, __y); }
328  };
329
330  struct __pow
331  {
332    template<typename _Tp>
333      _Tp operator()(const _Tp& __x, const _Tp& __y) const
334      { return pow(__x, __y); }
335  };
336
337
338  // We need these bits in order to recover the return type of
339  // some functions/operators now that we're no longer using
340  // function templates.
341  template<typename, typename _Tp>
342    struct __fun
343    {
344      typedef _Tp result_type;
345    };
346
347  // several specializations for relational operators.
348  template<typename _Tp>
349    struct __fun<__logical_not, _Tp>
350    {
351      typedef bool result_type;
352    };
353
354  template<typename _Tp>
355    struct __fun<__logical_and, _Tp>
356    {
357      typedef bool result_type;
358    };
359
360  template<typename _Tp>
361    struct __fun<__logical_or, _Tp>
362    {
363      typedef bool result_type;
364    };
365
366  template<typename _Tp>
367    struct __fun<__less, _Tp>
368    {
369      typedef bool result_type;
370    };
371
372  template<typename _Tp>
373    struct __fun<__greater, _Tp>
374    {
375      typedef bool result_type;
376    };
377
378  template<typename _Tp>
379    struct __fun<__less_equal, _Tp>
380    {
381      typedef bool result_type;
382    };
383
384  template<typename _Tp>
385    struct __fun<__greater_equal, _Tp>
386    {
387      typedef bool result_type;
388    };
389
390  template<typename _Tp>
391    struct __fun<__equal_to, _Tp>
392    {
393      typedef bool result_type;
394    };
395
396  template<typename _Tp>
397    struct __fun<__not_equal_to, _Tp>
398    {
399      typedef bool result_type;
400    };
401
402  //
403  // Apply function taking a value/const reference closure
404  //
405
406  template<typename _Dom, typename _Arg>
407    class _FunBase
408    {
409    public:
410      typedef typename _Dom::value_type value_type;
411
412      _FunBase(const _Dom& __e, value_type __f(_Arg))
413      : _M_expr(__e), _M_func(__f) {}
414
415      value_type operator[](size_t __i) const
416      { return _M_func (_M_expr[__i]); }
417
418      size_t size() const { return _M_expr.size ();}
419
420    private:
421      const _Dom& _M_expr;
422      value_type (*_M_func)(_Arg);
423    };
424
425  template<class _Dom>
426    struct _ValFunClos<_Expr,_Dom> : _FunBase<_Dom, typename _Dom::value_type>
427    {
428      typedef _FunBase<_Dom, typename _Dom::value_type> _Base;
429      typedef typename _Base::value_type value_type;
430      typedef value_type _Tp;
431
432      _ValFunClos(const _Dom& __e, _Tp __f(_Tp)) : _Base(__e, __f) {}
433    };
434
435  template<typename _Tp>
436    struct _ValFunClos<_ValArray,_Tp> : _FunBase<valarray<_Tp>, _Tp>
437    {
438      typedef _FunBase<valarray<_Tp>, _Tp> _Base;
439      typedef _Tp value_type;
440
441      _ValFunClos(const valarray<_Tp>& __v, _Tp __f(_Tp)) : _Base(__v, __f) {}
442    };
443
444  template<class _Dom>
445    struct _RefFunClos<_Expr, _Dom>
446    : _FunBase<_Dom, const typename _Dom::value_type&>
447    {
448      typedef _FunBase<_Dom, const typename _Dom::value_type&> _Base;
449      typedef typename _Base::value_type value_type;
450      typedef value_type _Tp;
451
452      _RefFunClos(const _Dom& __e, _Tp __f(const _Tp&))
453      : _Base(__e, __f) {}
454    };
455
456  template<typename _Tp>
457    struct _RefFunClos<_ValArray, _Tp>
458    : _FunBase<valarray<_Tp>, const _Tp&>
459    {
460      typedef _FunBase<valarray<_Tp>, const _Tp&> _Base;
461      typedef _Tp value_type;
462
463      _RefFunClos(const valarray<_Tp>& __v, _Tp __f(const _Tp&))
464      : _Base(__v, __f) {}
465    };
466
467  //
468  // Unary expression closure.
469  //
470
471  template<class _Oper, class _Arg>
472    class _UnBase
473    {
474    public:
475      typedef typename _Arg::value_type _Vt;
476      typedef typename __fun<_Oper, _Vt>::result_type value_type;
477
478      _UnBase(const _Arg& __e) : _M_expr(__e) {}
479
480      value_type operator[](size_t __i) const
481      { return _Oper()(_M_expr[__i]); }
482
483      size_t size() const { return _M_expr.size(); }
484
485    private:
486      const _Arg& _M_expr;
487    };
488
489  template<class _Oper, class _Dom>
490    struct _UnClos<_Oper, _Expr, _Dom>
491    : _UnBase<_Oper, _Dom>
492    {
493      typedef _Dom _Arg;
494      typedef _UnBase<_Oper, _Dom> _Base;
495      typedef typename _Base::value_type value_type;
496
497      _UnClos(const _Arg& __e) : _Base(__e) {}
498    };
499
500  template<class _Oper, typename _Tp>
501    struct _UnClos<_Oper, _ValArray, _Tp>
502    : _UnBase<_Oper, valarray<_Tp> >
503    {
504      typedef valarray<_Tp> _Arg;
505      typedef _UnBase<_Oper, valarray<_Tp> > _Base;
506      typedef typename _Base::value_type value_type;
507
508      _UnClos(const _Arg& __e) : _Base(__e) {}
509    };
510
511
512  //
513  // Binary expression closure.
514  //
515
516  template<class _Oper, class _FirstArg, class _SecondArg>
517    class _BinBase
518    {
519    public:
520      typedef typename _FirstArg::value_type _Vt;
521      typedef typename __fun<_Oper, _Vt>::result_type value_type;
522
523      _BinBase(const _FirstArg& __e1, const _SecondArg& __e2)
524      : _M_expr1(__e1), _M_expr2(__e2) {}
525
526      value_type operator[](size_t __i) const
527      { return _Oper()(_M_expr1[__i], _M_expr2[__i]); }
528
529      size_t size() const { return _M_expr1.size(); }
530
531    private:
532      const _FirstArg& _M_expr1;
533      const _SecondArg& _M_expr2;
534    };
535
536
537  template<class _Oper, class _Clos>
538    class _BinBase2
539    {
540    public:
541      typedef typename _Clos::value_type _Vt;
542      typedef typename __fun<_Oper, _Vt>::result_type value_type;
543
544      _BinBase2(const _Clos& __e, const _Vt& __t)
545      : _M_expr1(__e), _M_expr2(__t) {}
546
547      value_type operator[](size_t __i) const
548      { return _Oper()(_M_expr1[__i], _M_expr2); }
549
550      size_t size() const { return _M_expr1.size(); }
551
552    private:
553      const _Clos& _M_expr1;
554      const _Vt& _M_expr2;
555    };
556
557  template<class _Oper, class _Clos>
558    class _BinBase1
559    {
560    public:
561      typedef typename _Clos::value_type _Vt;
562      typedef typename __fun<_Oper, _Vt>::result_type value_type;
563
564      _BinBase1(const _Vt& __t, const _Clos& __e)
565      : _M_expr1(__t), _M_expr2(__e) {}
566
567      value_type operator[](size_t __i) const
568      { return _Oper()(_M_expr1, _M_expr2[__i]); }
569
570      size_t size() const { return _M_expr2.size(); }
571
572    private:
573      const _Vt& _M_expr1;
574      const _Clos& _M_expr2;
575    };
576
577  template<class _Oper, class _Dom1, class _Dom2>
578    struct _BinClos<_Oper, _Expr, _Expr, _Dom1, _Dom2>
579    : _BinBase<_Oper, _Dom1, _Dom2>
580    {
581      typedef _BinBase<_Oper, _Dom1, _Dom2> _Base;
582      typedef typename _Base::value_type value_type;
583
584      _BinClos(const _Dom1& __e1, const _Dom2& __e2) : _Base(__e1, __e2) {}
585    };
586
587  template<class _Oper, typename _Tp>
588    struct _BinClos<_Oper,_ValArray, _ValArray, _Tp, _Tp>
589    : _BinBase<_Oper, valarray<_Tp>, valarray<_Tp> >
590    {
591      typedef _BinBase<_Oper, valarray<_Tp>, valarray<_Tp> > _Base;
592      typedef typename _Base::value_type value_type;
593
594      _BinClos(const valarray<_Tp>& __v, const valarray<_Tp>& __w)
595      : _Base(__v, __w) {}
596    };
597
598  template<class _Oper, class _Dom>
599    struct _BinClos<_Oper, _Expr, _ValArray, _Dom, typename _Dom::value_type>
600    : _BinBase<_Oper, _Dom, valarray<typename _Dom::value_type> >
601    {
602      typedef typename _Dom::value_type _Tp;
603      typedef _BinBase<_Oper,_Dom,valarray<_Tp> > _Base;
604      typedef typename _Base::value_type value_type;
605
606      _BinClos(const _Dom& __e1, const valarray<_Tp>& __e2)
607      : _Base(__e1, __e2) {}
608    };
609
610  template<class _Oper, class _Dom>
611    struct _BinClos<_Oper, _ValArray, _Expr, typename _Dom::value_type, _Dom>
612    : _BinBase<_Oper, valarray<typename _Dom::value_type>,_Dom>
613    {
614      typedef typename _Dom::value_type _Tp;
615      typedef _BinBase<_Oper, valarray<_Tp>, _Dom> _Base;
616      typedef typename _Base::value_type value_type;
617
618      _BinClos(const valarray<_Tp>& __e1, const _Dom& __e2)
619      : _Base(__e1, __e2) {}
620    };
621
622  template<class _Oper, class _Dom>
623    struct _BinClos<_Oper, _Expr, _Constant, _Dom, typename _Dom::value_type>
624    : _BinBase2<_Oper, _Dom>
625    {
626      typedef typename _Dom::value_type _Tp;
627      typedef _BinBase2<_Oper,_Dom> _Base;
628      typedef typename _Base::value_type value_type;
629
630      _BinClos(const _Dom& __e1, const _Tp& __e2) : _Base(__e1, __e2) {}
631    };
632
633  template<class _Oper, class _Dom>
634    struct _BinClos<_Oper, _Constant, _Expr, typename _Dom::value_type, _Dom>
635    : _BinBase1<_Oper, _Dom>
636    {
637      typedef typename _Dom::value_type _Tp;
638      typedef _BinBase1<_Oper, _Dom> _Base;
639      typedef typename _Base::value_type value_type;
640
641      _BinClos(const _Tp& __e1, const _Dom& __e2) : _Base(__e1, __e2) {}
642    };
643
644  template<class _Oper, typename _Tp>
645    struct _BinClos<_Oper, _ValArray, _Constant, _Tp, _Tp>
646    : _BinBase2<_Oper, valarray<_Tp> >
647    {
648      typedef _BinBase2<_Oper,valarray<_Tp> > _Base;
649      typedef typename _Base::value_type value_type;
650
651      _BinClos(const valarray<_Tp>& __v, const _Tp& __t) : _Base(__v, __t) {}
652    };
653
654  template<class _Oper, typename _Tp>
655    struct _BinClos<_Oper, _Constant, _ValArray, _Tp, _Tp>
656    : _BinBase1<_Oper, valarray<_Tp> >
657    {
658      typedef _BinBase1<_Oper, valarray<_Tp> > _Base;
659      typedef typename _Base::value_type value_type;
660
661      _BinClos(const _Tp& __t, const valarray<_Tp>& __v) : _Base(__t, __v) {}
662    };
663
664    //
665    // slice_array closure.
666    //
667  template<typename _Dom>
668    class _SBase
669    {
670    public:
671      typedef typename _Dom::value_type value_type;
672
673      _SBase (const _Dom& __e, const slice& __s)
674      : _M_expr (__e), _M_slice (__s) {}
675
676      value_type
677      operator[] (size_t __i) const
678      { return _M_expr[_M_slice.start () + __i * _M_slice.stride ()]; }
679
680      size_t
681      size() const
682      { return _M_slice.size (); }
683
684    private:
685      const _Dom& _M_expr;
686      const slice& _M_slice;
687    };
688
689  template<typename _Tp>
690    class _SBase<_Array<_Tp> >
691    {
692    public:
693      typedef _Tp value_type;
694
695      _SBase (_Array<_Tp> __a, const slice& __s)
696      : _M_array (__a._M_data+__s.start()), _M_size (__s.size()),
697	_M_stride (__s.stride()) {}
698
699      value_type
700      operator[] (size_t __i) const
701      { return _M_array._M_data[__i * _M_stride]; }
702
703      size_t
704      size() const
705      { return _M_size; }
706
707    private:
708      const _Array<_Tp> _M_array;
709      const size_t _M_size;
710      const size_t _M_stride;
711    };
712
713  template<class _Dom>
714    struct _SClos<_Expr, _Dom>
715    : _SBase<_Dom>
716    {
717      typedef _SBase<_Dom> _Base;
718      typedef typename _Base::value_type value_type;
719
720      _SClos (const _Dom& __e, const slice& __s) : _Base (__e, __s) {}
721    };
722
723  template<typename _Tp>
724    struct _SClos<_ValArray, _Tp>
725    : _SBase<_Array<_Tp> >
726    {
727      typedef  _SBase<_Array<_Tp> > _Base;
728      typedef _Tp value_type;
729
730      _SClos (_Array<_Tp> __a, const slice& __s) : _Base (__a, __s) {}
731    };
732
733_GLIBCXX_END_NAMESPACE
734
735#endif /* _CPP_VALARRAY_BEFORE_H */
736