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