1 ///////////////////////////////////////////////////////////////////////////////
2 //                                                                           //
3 // The Template Matrix/Vector Library for C++ was created by Mike Jarvis     //
4 // Copyright (C) 1998 - 2016                                                 //
5 // All rights reserved                                                       //
6 //                                                                           //
7 // The project is hosted at https://code.google.com/p/tmv-cpp/               //
8 // where you can find the current version and current documention.           //
9 //                                                                           //
10 // For concerns or problems with the software, Mike may be contacted at      //
11 // mike_jarvis17 [at] gmail.                                                 //
12 //                                                                           //
13 // This software is licensed under a FreeBSD license.  The file              //
14 // TMV_LICENSE should have bee included with this distribution.              //
15 // It not, you can get a copy from https://code.google.com/p/tmv-cpp/.       //
16 //                                                                           //
17 // Essentially, you can use this software however you want provided that     //
18 // you include the TMV_LICENSE file in any distribution that uses it.        //
19 //                                                                           //
20 ///////////////////////////////////////////////////////////////////////////////
21 
22 
23 #ifndef TMV_SmallVectorArithFunc_H
24 #define TMV_SmallVectorArithFunc_H
25 
26 #define CT std::complex<T>
27 
28 namespace tmv {
29 
30     template <typename T1, typename T2>
31     struct OKTypeHelper { enum { ok=true }; };
32     template <typename T>
33     struct OKTypeHelper<CT,T> { enum { ok=false }; };
34 
35     template <typename T1, typename T2, typename T3>
36     struct OKTypeHelper2 { enum { ok=true }; };
37     template <typename T>
38     struct OKTypeHelper2<T,CT,T> { enum { ok=false }; };
39     template <typename T>
40     struct OKTypeHelper2<CT,T,T> { enum { ok=false }; };
41     template <typename T>
42     struct OKTypeHelper2<CT,CT,T> { enum { ok=false }; };
43 
44 #define OKTypes(T1,T2) (OKTypeHelper<T1,T2>::ok)
45 #define OKTypes2(T1,T2,T3) (OKTypeHelper2<T1,T2,T3>::ok)
46 
47 
48     // v *= x
49     template <ptrdiff_t N, typename T, typename Tv, bool ok>
50     struct MultXVHelper
51     { MultXVHelper(const T, Tv*) {} };
52     template <ptrdiff_t N, typename T, typename Tv>
53     struct MultXVHelper<N,T,Tv,true>
54     {
55         MultXVHelper(const T x, Tv* v)
56         { for(ptrdiff_t i=0;i<N;++i) v[i] *= x; }
57     };
58     template <ptrdiff_t N, typename T, typename Tv>
59     inline void MultXV(const T x, Tv* v)
60     { MultXVHelper<N,T,Tv,OKTypes(T,Tv)>(x,v); }
61 
62     // v2 = x * v1
63     template <ptrdiff_t N, typename T, typename T1, typename T2, bool ok>
64     struct MultXVHelper2
65     { MultXVHelper2(const T, const T1*, T2*) {} };
66     template <ptrdiff_t N, typename T, typename T1, typename T2>
67     struct MultXVHelper2<N,T,T1,T2,true>
68     {
69         MultXVHelper2(const T x, const T1* v1, T2* v2)
70         { for(ptrdiff_t i=0;i<N;++i) v2[i] = x * v1[i]; }
71     };
72     template <ptrdiff_t N, typename T, typename T1, typename T2>
73     inline void MultXV( const T x, const T1* v1, T2* v2)
74     { MultXVHelper2<N,T,T1,T2,OKTypes2(T,T1,T2)>(x,v1,v2); }
75 
76     // v2 += x * v1
77     template <ptrdiff_t N, typename T1, typename T2, bool ok>
78     struct AddVV_1Helper
79     { AddVV_1Helper(const T1*, T2*) {} };
80     template <ptrdiff_t N, typename T1, typename T2>
81     struct AddVV_1Helper<N,T1,T2,true>
82     {
83         inline AddVV_1Helper(const T1* v1, T2* v2)
84         { for(ptrdiff_t i=0;i<N;++i) v2[i] += v1[i]; }
85     };
86     template <ptrdiff_t N, typename T1, typename T2>
87     inline void AddVV_1(const T1* v1, T2* v2)
88     { AddVV_1Helper<N,T1,T2,OKTypes(T1,T2)>(v1,v2); }
89 
90     template <ptrdiff_t N, typename T1, typename T2, bool ok>
91     struct AddVV_m1Helper
92     { AddVV_m1Helper(const T1*, T2*) {} };
93     template <ptrdiff_t N, typename T1, typename T2>
94     struct AddVV_m1Helper<N,T1,T2,true>
95     {
96         inline AddVV_m1Helper(const T1* v1, T2* v2)
97         { for(ptrdiff_t i=0;i<N;++i) v2[i] -= v1[i]; }
98     };
99     template <ptrdiff_t N, typename T1, typename T2>
100     inline void AddVV_m1(const T1* v1, T2* v2)
101     { AddVV_m1Helper<N,T1,T2,OKTypes(T1,T2)>(v1,v2); }
102 
103     template <ptrdiff_t N, typename T, typename T1, typename T2, bool ok>
104     struct AddVVHelper
105     { AddVVHelper(const T, const T1*, T2*) {} };
106     template <ptrdiff_t N, typename T, typename T1, typename T2>
107     struct AddVVHelper<N,T,T1,T2,true>
108     {
109         inline AddVVHelper(const T x, const T1* v1, T2* v2)
110         { for(ptrdiff_t i=0;i<N;++i) v2[i] += x*v1[i]; }
111     };
112     template <ptrdiff_t N, typename T, typename T1, typename T2>
113     inline void AddVV(const T x, const T1* v1, T2* v2)
114     { AddVVHelper<N,T,T1,T2,OKTypes2(T,T1,T2)>(x,v1,v2); }
115 
116     // v3 = x1 * v1 + x2 * v2
117     template <ptrdiff_t N, typename T1, typename T2, typename T3>
118     inline void AddVV_1_1(const T1* v1, const T2* v2, T3* v3)
119     { SmallVectorCopy<N>(v1,v3); AddVV_1<N>(v2,v3); }
120     template <ptrdiff_t N, typename T1, typename T2, typename T3>
121     inline void AddVV_1_m1(const T1* v1, const T2* v2, T3* v3)
122     { SmallVectorCopy<N>(v1,v3); AddVV_m1<N>(v2,v3); }
123     template <ptrdiff_t N, typename T, typename T1, typename T2, typename T3>
124     inline void AddVV_1_x(const T1* v1, const T x2, const T2* v2, T3* v3)
125     { MultXV<N>(x2,v2,v3); AddVV_1<N>(v1,v3); }
126     template <ptrdiff_t N, typename T, typename T1, typename T2, typename T3>
127     inline void AddVV_x_1(const T x1, const T1* v1, const T2* v2, T3* v3)
128     { MultXV<N>(x1,v1,v3); AddVV_1<N>(v2,v3); }
129     template <ptrdiff_t N, typename T, typename T1, typename T2, typename T3>
130     inline void AddVV_x_m1(const T x1, const T1* v1, const T2* v2, T3* v3)
131     { MultXV<N>(x1,v1,v3); AddVV_m1<N>(v2,v3); }
132     template <ptrdiff_t N, typename T, typename T1, typename T2, typename T3>
133     inline void AddVV(const T x1, const T1* v1, const T x2, const T2* v2, T3* v3)
134     { MultXV<N>(x1,v1,v3); AddVV<N>(x2,v2,v3); }
135 
136     // v1 * v2 (dot product)
137     template <typename T1, typename T2>
138     struct ProdType { typedef T1 Tprod; };
139     template <typename T>
140     struct ProdType<T,std::complex<T> > { typedef std::complex<T> Tprod; };
141 #define ProductType(T1,T2) typename ProdType<T1,T2>::Tprod
142 
143     template <ptrdiff_t N, typename T, typename T1, typename T2>
144     struct MultVVHelper
145     {
146         inline MultVVHelper(T& res, const T1* v1, const T2* v2)
147         { for(ptrdiff_t i=0;i<N;++i) res += v1[i]*v2[i]; }
148     };
149     template <ptrdiff_t N, typename T1, typename T2>
150     inline ProductType(T1,T2) MultVV(const T1* v1, const T2* v2)
151     {
152         ProductType(T1,T2) res(0);
153         MultVVHelper<N,ProductType(T1,T2),T1,T2>(res,v1,v2);
154         return res;
155     }
156 #undef ProductType
157 
158     template <typename T, typename T1, typename T2, typename T3, ptrdiff_t N, int A1, int A2, int A3>
159     inline void ElemMultVV(
160         const T alpha, const SmallVector<T1,N,A1>& v1,
161         const SmallVector<T2,N,A2>& v2, SmallVector<T3,N,A3>& v3)
162     {
163         if (alpha == T(1))
164             for(ptrdiff_t i=0;i<N;++i) v3.ref(i) = v1.cref(i) * v2.cref(i);
165         else
166             for(ptrdiff_t i=0;i<N;++i) v3.ref(i) = alpha * v1.cref(i) * v2.cref(i);
167     }
168     template <typename T, typename T1, typename T2, ptrdiff_t N, int A1, int A2, int A3>
169     inline void ElemMultVV(
170         const CT , const SmallVector<T1,N,A1>& ,
171         const SmallVector<T2,N,A2>& , SmallVector<T,N,A3>& )
172     { TMVAssert(TMV_FALSE); }
173 
174 
175     template <typename T, typename T1, typename T2, typename T3, ptrdiff_t N, int A1, int A2, int A3>
176     inline void AddElemMultVV(
177         const T alpha, const SmallVector<T1,N,A1>& v1,
178         const SmallVector<T2,N,A2>& v2, SmallVector<T3,N,A3>& v3)
179     {
180         if (alpha == T(1))
181             for(ptrdiff_t i=0;i<N;++i) v3.ref(i) += v1.cref(i) * v2.cref(i);
182         else if (alpha == T(-1))
183             for(ptrdiff_t i=0;i<N;++i) v3.ref(i) -= v1.cref(i) * v2.cref(i);
184         else
185             for(ptrdiff_t i=0;i<N;++i) v3.ref(i) += alpha * v1.cref(i) * v2.cref(i);
186     }
187     template <typename T, typename T1, typename T2, ptrdiff_t N, int A1, int A2, int A3>
188     inline void AddElemMultVV(
189         const CT , const SmallVector<T1,N,A1>& ,
190         const SmallVector<T2,N,A2>& , SmallVector<T,N,A3>& )
191     { TMVAssert(TMV_FALSE); }
192 
193 #undef OKTypes
194 #undef OKTypes2
195 
196 } // namespace tmv
197 
198 #undef CT
199 
200 #endif
201