Line data Source code
1 : ///////////////////////////////////////////////////////////////////////////
2 : // Inastemp - Berenger Bramas MPCDF - 2016
3 : // Under MIT Licence, please you must read the LICENCE file.
4 : ///////////////////////////////////////////////////////////////////////////
5 : #ifndef INAVECFLOPS_HPP
6 : #define INAVECFLOPS_HPP
7 :
8 : #include <type_traits>
9 :
10 : #include "Common/InaUtils.hpp"
11 :
12 : class InaVecFLOPSStats {
13 : size_t mulop;
14 : size_t divop;
15 : size_t addop;
16 : size_t subop;
17 : size_t rsqrt;
18 : size_t sqrt;
19 :
20 : public:
21 : InaVecFLOPSStats()
22 42 : : mulop(0), divop(0), addop(0),
23 42 : subop(0), rsqrt(0), sqrt(0){
24 : }
25 :
26 : void incMulOp(const size_t inNbEvents = 1){
27 828 : mulop += inNbEvents;
28 : }
29 : void incDivOp(const size_t inNbEvents = 1){
30 154 : divop += inNbEvents;
31 : }
32 : void incAddOp(const size_t inNbEvents = 1){
33 5604 : addop += inNbEvents;
34 : }
35 : void incSubOp(const size_t inNbEvents = 1){
36 350 : subop += inNbEvents;
37 : }
38 : void incRsqrt(const size_t inNbEvents = 1){
39 28 : rsqrt += inNbEvents;
40 : }
41 : void incSqrt(const size_t inNbEvents = 1){
42 28 : sqrt += inNbEvents;
43 : }
44 :
45 : size_t getMulOp() const {
46 : return mulop;
47 : }
48 : size_t getDivOp() const {
49 : return divop;
50 : }
51 : size_t getAddOp() const {
52 : return addop;
53 : }
54 : size_t getSubOp() const {
55 : return subop;
56 : }
57 : size_t getRsqrt() const {
58 : return rsqrt;
59 : }
60 : size_t getSqrt() const {
61 : return sqrt;
62 : }
63 : };
64 :
65 :
66 : /**
67 : * This class defines the interface that each vector
68 : * type must provide.
69 : * It is not made to be use as an abstract data type
70 : * by having for example a pointer on InaVecFLOPS.
71 : * It simply help to implement each type.
72 : */
73 : template < class VecType >
74 : class InaVecFLOPS : public VecType {
75 : static InaVecFLOPSStats FlopsStats;
76 :
77 : public:
78 : static const InaVecFLOPSStats& GetFlopsStats(){
79 : return FlopsStats;
80 : }
81 :
82 : static void ResetFlopsStats(){
83 70 : FlopsStats = InaVecFLOPSStats();
84 : }
85 :
86 : using Parent = VecType;
87 : using VecRawType = typename VecType::VecRawType;
88 : using MaskType = typename VecType::MaskType;
89 : using RealType = typename VecType::RealType;
90 : static const int Alignement= VecType::Alignement;
91 : static const bool IsOfFixedSize = VecType::IsOfFixedSize;
92 :
93 : using VecType::GetVecLength;
94 :
95 19556 : using VecType::VecType;
96 :
97 : using VecType::IsRealFma;
98 :
99 702 : inline InaVecFLOPS(){}
100 : inline InaVecFLOPS(const InaVecFLOPS&) = default;
101 : inline InaVecFLOPS& operator = (const InaVecFLOPS&) = default;
102 :
103 6300 : inline InaVecFLOPS(const VecType& inVec) : Parent(inVec){};
104 : inline InaVecFLOPS& operator = (const VecType& inVec){
105 14 : this->Parent::operator=(inVec);
106 : return *this;
107 : }
108 :
109 : inline InaVecFLOPS(const std::initializer_list<RealType> lst)
110 164 : : Parent(lst.begin()){
111 : }
112 :
113 : /** Load and store */
114 :
115 : inline /*not explicit*/ InaVecFLOPS(const VecRawType inVec)
116 1682 : : Parent(inVec){
117 : }
118 :
119 : inline VecType& operator=(const VecRawType inVec){
120 : this->Parent::operator =(inVec);
121 : return *this;
122 : }
123 :
124 : //! Convert inValue into a VecType by duplicating it and
125 : //! setting all the values of the array equal to inValue
126 : //! @code VecType[0:last-val-idx] = inValue
127 : inline VecType setFromRawType(const VecRawType inValue) const {
128 : return Parent::setFromRawType(inValue);
129 : }
130 :
131 : inline explicit operator VecRawType() const{
132 : return this->Parent::operator VecRawType();
133 : }
134 :
135 : inline VecRawType getVec() const{
136 : return Parent::getVec();
137 : }
138 :
139 : // inline /*not explicit*/ InaVecFLOPS(const RealType inVal)
140 : // : Parent(inVal){
141 : // }
142 :
143 : // inline VecType& operator=(const RealType inVal){
144 : // this->Parent::operator =(inVal);
145 : // return *this;
146 : // }
147 :
148 : inline void setFromScalar(const RealType inVal){
149 : this->Parent::setFromScalar(inVal);
150 : }
151 :
152 : // Constructor from vec
153 : inline explicit InaVecFLOPS(const RealType ptr[])
154 11524 : : Parent(ptr){
155 : }
156 :
157 : //! Convert values from inArray into a VecType
158 : //! inArray might not be aligned
159 : //! @code idx in [0:last-val-idx] => VecType[idx] = inArray[idx]
160 : inline VecType& setFromArray(const RealType ptr[]){
161 1184 : Parent::setFromArray(ptr);
162 : return *this;
163 : }
164 :
165 : //! Convert values from inArray into a VecType
166 : //! inArray must be aligned
167 : //! @code idx in [0:last-val-idx] => VecType[idx] = inArray[idx]
168 : inline VecType& setFromAlignedArray(const RealType ptr[]){
169 264 : Parent::setFromAlignedArray(ptr);
170 : return *this;
171 : }
172 :
173 : //! Convert values at position inIndirection from inArray into a VecType
174 : //! inArray might not be aligned
175 : //! @code idx in [0:last-val-idx] => VecType[idx] = inArray[inIndirection[idx]]
176 : inline VecType& setFromIndirectArray(const RealType values[], const int inIndirection[]) {
177 156 : Parent::setFromIndirectArray(values, inIndirection);
178 : return *this;
179 : }
180 :
181 : //! Convert values at position inIndirection from inArray into a VecType
182 : //! inArray might not be aligned
183 : //! @code idx in [0:last-val-idx] => VecType[idx] = inArray[inIndirection1[idx]*inLeadingDimension
184 : //! @code + inIndirection2[idx]]
185 : inline VecType& setFromIndirect2DArray(const RealType inArray[], const int inIndirection1[],
186 : const int inLeadingDimension, const int inIndirection2[]){
187 120 : Parent::setFromIndirect2DArray(inArray, inIndirection1, inLeadingDimension, inIndirection2);
188 : return *this;
189 : }
190 :
191 : //! inArray
192 : //! @code idx in [0:last-val-idx] => outArray[idx] = inVec[idx]
193 : inline void storeInArray(RealType ptr[]) const {
194 46872 : Parent::storeInArray(ptr);
195 : }
196 :
197 : //! inArray might must be aligned
198 : //! @code idx in [0:last-val-idx] => outArray[idx] = inVec[idx]
199 : inline void storeInAlignedArray(RealType ptr[]) const {
200 12944 : Parent::storeInAlignedArray(ptr);
201 : }
202 :
203 : // Acce to individual values
204 : //! Return the value at position inIdx in inVec
205 : //! @code return inVec[inIdx]
206 : inline RealType at(const int index) const {
207 67984 : return Parent::at(index);
208 : }
209 :
210 : // Horizontal operation
211 : //! Sum all the values from inVec
212 : //! @code return inVec[0] + ... + inVec[last-val-idx]
213 : inline RealType horizontalSum() const {
214 9724 : FlopsStats.incAddOp(size_t(GetVecLength())-1);
215 9724 : return Parent::horizontalSum();
216 : }
217 :
218 : //! Multiply all the values from inVec
219 : //! @code return inVec[0] * ... * inVec[last-val-idx]
220 : inline RealType horizontalMul() const {
221 156 : FlopsStats.incMulOp(size_t(GetVecLength())-1);
222 156 : return Parent::horizontalMul();
223 : }
224 :
225 : //! Return the smallest value in the vector
226 : inline RealType minInVec() const {
227 392 : return Parent::minInVec();
228 : }
229 :
230 : //! Return the greatest value in the vector
231 : inline RealType maxInVec() const {
232 392 : return Parent::maxInVec();
233 : }
234 :
235 : //! Apply Sqrt to all values from inVec
236 : //! @code idx in [0:last-val-idx] => resVec[idx] = Sqrt(inVec[idx])
237 : inline VecType sqrt() const {
238 56 : FlopsStats.incSqrt((1)*size_t(GetVecLength()));
239 64 : return Parent::sqrt();
240 : }
241 :
242 : //! Apply exponential to all values from inVec
243 : //! @code idx in [0:last-val-idx] => resVec[idx] = Exp(inVec[idx])
244 56 : inline VecType exp() const {
245 112 : FlopsStats.incAddOp((1+5)*size_t(GetVecLength()));
246 112 : FlopsStats.incMulOp((1+1+5)*size_t(GetVecLength()));
247 112 : FlopsStats.incSubOp((1+1)*size_t(GetVecLength()));
248 : if(std::is_same<double,typename VecType::RealType>::value){
249 56 : FlopsStats.incAddOp((3)*size_t(GetVecLength()));
250 56 : FlopsStats.incMulOp((3)*size_t(GetVecLength()));
251 : }
252 88 : return Parent::exp();
253 : }
254 :
255 : //! Apply exponential to all values from inVec with low accuracy
256 : //! @code idx in [0:last-val-idx] => resVec[idx] = ExpLowExp(inVec[idx])
257 28 : inline VecType expLowAcc() const {
258 56 : FlopsStats.incAddOp((1+2)*size_t(GetVecLength()));
259 56 : FlopsStats.incMulOp((1+1+2)*size_t(GetVecLength()));
260 56 : FlopsStats.incSubOp((1+1)*size_t(GetVecLength()));
261 : if(std::is_same<double,typename VecType::RealType>::value){
262 28 : FlopsStats.incAddOp((1)*size_t(GetVecLength()));
263 28 : FlopsStats.incMulOp((1)*size_t(GetVecLength()));
264 : }
265 50 : return Parent::expLowAcc();
266 : }
267 :
268 : //! Apply 1/Sqrt to all values from inVec
269 : //! @code idx in [0:last-val-idx] => resVec[idx] = 1/Sqrt(inVec[idx])
270 : inline VecType rsqrt() const {
271 56 : FlopsStats.incRsqrt((1)*size_t(GetVecLength()));
272 64 : return Parent::rsqrt();
273 : }
274 :
275 : //! Return the abs value of inVec
276 : //! @code idx in [0:last-val-idx] => resVec[idx] = abs(inVec[idx])
277 : inline VecType abs() const {
278 192 : return Parent::abs();
279 : }
280 :
281 : //! Convert inVal in integer and then to real
282 : //! @code idx in [0:last-val-idx] => floor(inVal[idx])
283 : inline VecType floor() const {
284 260 : return Parent::floor();
285 : }
286 :
287 : //! Return 1 or -1 for each value in inVec
288 : //! @code idx in [0:last-val-idx] => resVec[idx] = (inVec[idx]<0?-1:1)
289 : inline VecType signOf() const {
290 320 : return Parent::signOf();
291 : }
292 :
293 : //! Return 1 if positive or zero, else 0 for each value
294 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec[idx]>=0?1:0
295 : inline VecType isPositive() const {
296 320 : return Parent::isPositive();
297 : }
298 :
299 : //! Return 1 if negative or zero, else 0 for each value
300 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec[idx]<=0?1:0
301 : inline VecType isNegative() const {
302 320 : return Parent::isNegative();
303 : }
304 :
305 : //! Return 1 if positive, else 0 for each value
306 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec[idx]>0?1:0
307 : inline VecType isPositiveStrict() const {
308 320 : return Parent::isPositiveStrict();
309 : }
310 :
311 : //! Return 1 if negative, else 0 for each value
312 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec[idx]<0?1:0
313 : inline VecType isNegativeStrict() const {
314 320 : return Parent::isNegativeStrict();
315 : }
316 :
317 : //! Return 1 if equal to, else 0 for each value
318 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec[idx]==0?1:0
319 : inline VecType isZero() const {
320 192 : return Parent::isZero();
321 : }
322 :
323 : //! Return 1 if not equal to, else 0 for each value
324 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec[idx]!=0?1:0
325 : inline VecType isNotZero() const {
326 192 : return Parent::isNotZero();
327 : }
328 :
329 : //! Return ~0 if positive or zero, else 0 for each value
330 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec[idx]>=0?~0:0
331 : inline MaskType isPositiveMask() const {
332 280 : return Parent::isPositiveMask();
333 : }
334 :
335 : //! Return ~0 if negative or zero, else 0 for each value
336 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec[idx]<=0?~0:0
337 : inline MaskType isNegativeMask() const {
338 280 : return Parent::isNegativeMask();
339 : }
340 :
341 : //! Return ~0 if positive, else 0 for each value
342 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec[idx]>0?~0:0
343 : inline MaskType isPositiveStrictMask() const {
344 280 : return Parent::isPositiveStrictMask();
345 : }
346 :
347 : //! Return ~0 if negative, else 0 for each value
348 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec[idx]<0?~0:0
349 : inline MaskType isNegativeStrictMask() const {
350 280 : return Parent::isNegativeStrictMask();
351 : }
352 :
353 : //! Return ~0 if equal to, else 0 for each value
354 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec[idx]==0?~0:0
355 : inline MaskType isZeroMask() const {
356 168 : return Parent::isZeroMask();
357 : }
358 :
359 : //! Return ~0 if not equal to, else 0 for each value
360 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec[idx]!=0?~0:0
361 : inline MaskType isNotZeroMask() const {
362 168 : return Parent::isNotZeroMask();
363 : }
364 :
365 : // Static basic methods
366 : //! Return a vector where all values are 1
367 : //! @code VecType[0:last-val-idx] = 1
368 : //! Might be implemtented as ScalarToSimd(1)
369 : inline static VecType GetZero() {
370 24 : return Parent::GetZero();
371 : }
372 :
373 : //! Return a vector where all values are 0
374 : //! @code VecType[0:last-val-idx] = 0
375 : //! Might be implemtented as ScalarToSimd(0)
376 : inline static VecType GetOne() {
377 24 : return Parent::GetOne();
378 : }
379 :
380 : //! Return the minimum value between inVec1 and inVec2
381 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]<=inVec2[idx]?inVec1[idx]:inVec2[idx]
382 : inline static VecType Min(const VecType& inVec1, const VecType& inVec2) {
383 156 : return Parent::Min(inVec1, inVec2);
384 : }
385 :
386 : //! Return the maximum value between inVec1 and inVec2
387 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]>=inVec2[idx]?inVec1[idx]:inVec2[idx]
388 : inline static VecType Max(const VecType& inVec1, const VecType& inVec2) {
389 156 : return Parent::Max(inVec1, inVec2);
390 : }
391 :
392 : //! Return 1 if inVec1 <= inVec2, else 0 for each value
393 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]<=inVec2[idx]?1:0
394 : inline static VecType IsLowerOrEqual(const VecType& inVec1, const VecType& inVec2) {
395 208 : return Parent::IsLowerOrEqual(inVec1, inVec2);
396 : }
397 :
398 : //! Return 1 if inVec1 < inVec2, else 0 for each value
399 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]<inVec2[idx]?1:0
400 : inline static VecType IsLower(const VecType& inVec1, const VecType& inVec2) {
401 208 : return Parent::IsLower(inVec1, inVec2);
402 : }
403 :
404 : //! Return 1 if inVec1 >= inVec2, else 0 for each value
405 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]>=inVec2[idx]?1:0
406 : inline static VecType IsGreaterOrEqual(const VecType& inVec1, const VecType& inVec2) {
407 208 : return Parent::IsGreaterOrEqual(inVec1, inVec2);
408 : }
409 :
410 : //! Return 1 if inVec1 > inVec2, else 0 for each value
411 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]>inVec2[idx]?1:0
412 : inline static VecType IsGreater(const VecType& inVec1, const VecType& inVec2) {
413 208 : return Parent::IsGreater(inVec1, inVec2);
414 : }
415 :
416 : //! Return 1 if inVec1 == inVec2, else 0 for each value
417 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]==inVec2[idx]?1:0
418 : inline static VecType IsEqual(const VecType& inVec1, const VecType& inVec2) {
419 208 : return Parent::IsEqual(inVec1, inVec2);
420 : }
421 :
422 : //! Return 1 if inVec1 == inVec2, else 0 for each value
423 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]!=inVec2[idx]?1:0
424 : inline static VecType IsNotEqual(const VecType& inVec1, const VecType& inVec2) {
425 208 : return Parent::IsNotEqual(inVec1, inVec2);
426 : }
427 :
428 : //! Return ~0 if inVec1 <= inVec2, else 0 for each value
429 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]<=inVec2[idx]?~0:0
430 : inline static MaskType IsLowerOrEqualMask(const VecType& inVec1, const VecType& inVec2) {
431 176 : return Parent::IsLowerOrEqualMask(inVec1, inVec2);
432 : }
433 :
434 : //! Return ~0 if inVec1 < inVec2, else 0 for each value
435 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]<inVec2[idx]?~0:0
436 : inline static MaskType IsLowerMask(const VecType& inVec1, const VecType& inVec2) {
437 176 : return Parent::IsLowerMask(inVec1, inVec2);
438 : }
439 :
440 : //! Return ~0 if inVec1 >= inVec2, else 0 for each value
441 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]>=inVec2[idx]?~0:0
442 : inline static MaskType IsGreaterOrEqualMask(const VecType& inVec1, const VecType& inVec2) {
443 176 : return Parent::IsGreaterOrEqualMask(inVec1, inVec2);
444 : }
445 :
446 : //! Return ~0 if inVec1 > inVec2, else 0 for each value
447 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]>inVec2[idx]?~0:0
448 : inline static MaskType IsGreaterMask(const VecType& inVec1, const VecType& inVec2) {
449 176 : return Parent::IsGreaterMask(inVec1, inVec2);
450 : }
451 :
452 : //! Return ~0 if inVec1 == inVec2, else 0 for each value
453 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]==inVec2[idx]?~0:0
454 : inline static MaskType IsEqualMask(const VecType& inVec1, const VecType& inVec2) {
455 176 : return Parent::IsEqualMask(inVec1, inVec2);
456 : }
457 :
458 : //! Return ~0 if inVec1 == inVec2, else 0 for each value
459 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]!=inVec2[idx]?~0:0
460 : inline static MaskType IsNotEqualMask(const VecType& inVec1, const VecType& inVec2) {
461 176 : return Parent::IsNotEqualMask(inVec1, inVec2);
462 : }
463 :
464 : /** Bits operations */
465 : //! Return inVec1 AND inVec2, for each value
466 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]&inVec2[idx]
467 : inline static VecType BitsAnd(const VecType& inVec1, const VecType& inVec2) {
468 156 : return Parent::BitsAnd(inVec1, inVec2);
469 : }
470 :
471 : //! Return NOT inVec1 AND inVec2, for each value
472 : //! @code idx in [0:last-val-idx] => resVec[idx] = (~inVec1[idx])&inVec2[idx]
473 : inline static VecType BitsNotAnd(const VecType& inVec1, const VecType& inVec2) {
474 208 : return Parent::BitsNotAnd(inVec1, inVec2);
475 : }
476 :
477 : //! Return inVec1 OR inVec2, for each value
478 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx]|inVec2[idx]
479 : inline static VecType BitsOr(const VecType& inVec1, const VecType& inVec2) {
480 156 : return Parent::BitsOr(inVec1, inVec2);
481 : }
482 :
483 : //! Return inVec1 XOR inVec2, for each value
484 : //! @code idx in [0:last-val-idx] => resVec[idx] = inVec1[idx] ^ inVec2[idx]
485 : inline static VecType BitsXor(const VecType& inVec1, const VecType& inVec2) {
486 156 : return Parent::BitsXor(inVec1, inVec2);
487 : }
488 :
489 : //! Return the name identifier of the vectorizer
490 : inline static const char* GetName() {
491 : return Parent::GetName();
492 : }
493 :
494 : //! The method cannot be because the return type is unknown
495 : inline static typename InaIfElse< VecType >::ThenClass If(const MaskType& inTest) {
496 : return Parent::If(inTest);
497 : }
498 :
499 : //! This is a ternary if/else test
500 : //! It can be implemented as : return (inMask & inIfTrue) | (~inMask & inIfFalse)
501 : //! @code idx in [0:last-val-idx] => resVec[idx] = inMask ? inIfTrue[idx] : inIfFalse[idx]
502 : inline static VecType IfElse(const MaskType& inMask, const VecType& inIfTrue, const VecType& inIfFalse) {
503 : return Parent::IfElse(inMask, inIfTrue, inIfFalse);
504 : }
505 :
506 : //! This is a ternary if/else test with 0 as else case
507 : //! It can be implemented as : return (inMask & inIfTrue)
508 : //! @code idx in [0:last-val-idx] => resVec[idx] = inMask ? inIfTrue[idx] : 0
509 : inline static VecType IfTrue(const MaskType& inMask, const VecType& inIfTrue) {
510 5200 : return Parent::IfTrue(inMask, inIfTrue);
511 : }
512 :
513 : //! This is a ternary if/else test with 0 as if case
514 : //! It can be implemented as : return (!inMask & inIfFalse)
515 : //! @code idx in [0:last-val-idx] => resVec[idx] = inMask ? 0 : inIfFalse[idx]
516 : inline static VecType IfFalse(const MaskType& inMask, const VecType& inIfFalse) {
517 : return Parent::IfFalse(inMask, inIfFalse);
518 : }
519 :
520 : // Inner operators
521 : inline VecType& operator+=(const VecType& inVec){
522 308 : FlopsStats.incAddOp(size_t(GetVecLength()));
523 292 : this->Parent::operator +=(inVec);
524 : return *this;
525 : }
526 :
527 : inline VecType& operator-=(const VecType& inVec){
528 252 : FlopsStats.incSubOp(size_t(GetVecLength()));
529 236 : this->Parent::operator -=(inVec);
530 : return *this;
531 : }
532 :
533 : inline VecType& operator/=(const VecType& inVec){
534 140 : FlopsStats.incDivOp(size_t(GetVecLength()));
535 132 : this->Parent::operator /=(inVec);
536 : return *this;
537 : }
538 :
539 : inline VecType& operator*=(const VecType& inVec){
540 252 : FlopsStats.incMulOp(size_t(GetVecLength()));
541 236 : this->Parent::operator *=(inVec);
542 : return *this;
543 : }
544 :
545 :
546 168 : inline VecType pow(size_t power) const{
547 336 : FlopsStats.incMulOp(InaUtils::FastPowNbMul(power)*size_t(GetVecLength()));
548 384 : return this->Parent::pow(power);
549 : }
550 :
551 :
552 : template <class VecType2>
553 : friend InaVecFLOPS<VecType2> operator+(const InaVecFLOPS<VecType2>& inVec1, const InaVecFLOPS<VecType2>& inVec2);
554 :
555 : template <class VecType2>
556 : friend InaVecFLOPS<VecType2> operator-(const InaVecFLOPS<VecType2>& inVec1, const InaVecFLOPS<VecType2>& inVec2);
557 :
558 : template <class VecType2>
559 : friend InaVecFLOPS<VecType2> operator/(const InaVecFLOPS<VecType2>& inVec1, const InaVecFLOPS<VecType2>& inVec2);
560 :
561 : template <class VecType2>
562 : friend InaVecFLOPS<VecType2> operator*(const InaVecFLOPS<VecType2>& inVec1, const InaVecFLOPS<VecType2>& inVec2);
563 :
564 :
565 : // Multiple sum
566 : template <class ... Args>
567 16 : inline static void MultiHorizontalSum(RealType sumRes[], Args ...args){
568 644 : const size_t nbVecs = sizeof...(args);
569 1172 : FlopsStats.incAddOp((size_t(GetVecLength())-1)*nbVecs);
570 644 : Parent::MultiHorizontalSum(sumRes, args...);
571 16 : }
572 :
573 : inline static VecType Fma(const VecType& inValAdd, const VecType& inValMul1, const VecType& inValMul2){
574 336 : FlopsStats.incAddOp(size_t(GetVecLength()));
575 336 : FlopsStats.incMulOp(size_t(GetVecLength()));
576 312 : return Parent::Fma(inValAdd, inValMul1, inValMul2);
577 : }
578 : };
579 :
580 : // Bits operators
581 : template <class VecType>
582 : inline InaVecFLOPS<VecType> operator&(const InaVecFLOPS<VecType>& inVec1, const InaVecFLOPS<VecType>& inVec2){
583 : return InaVecFLOPS<VecType>::BitsAnd(inVec1, inVec2);
584 : }
585 :
586 : template <class VecType>
587 : inline InaVecFLOPS<VecType> operator|(const InaVecFLOPS<VecType>& inVec1, const InaVecFLOPS<VecType>& inVec2){
588 : return InaVecFLOPS<VecType>::BitsOr(inVec1, inVec2);
589 : }
590 :
591 : template <class VecType>
592 : inline InaVecFLOPS<VecType> operator^(const InaVecFLOPS<VecType>& inVec1, const InaVecFLOPS<VecType>& inVec2){
593 : return InaVecFLOPS<VecType>::BitsXor(inVec1, inVec2);
594 : }
595 :
596 : // Dual operators
597 : template <class VecType>
598 : inline InaVecFLOPS<VecType> operator+(const InaVecFLOPS<VecType>& inVec1, const InaVecFLOPS<VecType>& inVec2){
599 294 : InaVecFLOPS<VecType>::FlopsStats.incAddOp(size_t(InaVecFLOPS<VecType>::GetVecLength()));
600 396 : return static_cast<const VecType&>(inVec1) + static_cast<const VecType&>(inVec2);
601 : }
602 :
603 : template <class VecType>
604 : inline InaVecFLOPS<VecType> operator-(const InaVecFLOPS<VecType>& inVec1, const InaVecFLOPS<VecType>& inVec2){
605 294 : InaVecFLOPS<VecType>::FlopsStats.incSubOp(size_t(InaVecFLOPS<VecType>::GetVecLength()));
606 396 : return static_cast<const VecType&>(inVec1) - static_cast<const VecType&>(inVec2);
607 : }
608 :
609 : template <class VecType>
610 : inline InaVecFLOPS<VecType> operator/(const InaVecFLOPS<VecType>& inVec1, const InaVecFLOPS<VecType>& inVec2){
611 182 : InaVecFLOPS<VecType>::FlopsStats.incDivOp(size_t(InaVecFLOPS<VecType>::GetVecLength()));
612 252 : return static_cast<const VecType&>(inVec1) / static_cast<const VecType&>(inVec2);
613 : }
614 :
615 : template <class VecType>
616 : inline InaVecFLOPS<VecType> operator*(const InaVecFLOPS<VecType>& inVec1, const InaVecFLOPS<VecType>& inVec2){
617 350 : InaVecFLOPS<VecType>::FlopsStats.incMulOp(size_t(InaVecFLOPS<VecType>::GetVecLength()));
618 468 : return static_cast<const VecType&>(inVec1) * static_cast<const VecType&>(inVec2);
619 : }
620 :
621 : // Tests and comparions
622 : template <class VecType>
623 : inline typename InaVecFLOPS<VecType>::MaskType operator<(const InaVecFLOPS<VecType>& inVec1, const InaVecFLOPS<VecType>& inVec2){
624 : return InaVecFLOPS<VecType>::IsLowerMask(inVec1,inVec2);
625 : }
626 :
627 : template <class VecType>
628 : inline typename InaVecFLOPS<VecType>::MaskType operator<=(const InaVecFLOPS<VecType>& inVec1, const InaVecFLOPS<VecType>& inVec2){
629 : return InaVecFLOPS<VecType>::IsLowerOrEqualMask(inVec1,inVec2);
630 : }
631 :
632 : template <class VecType>
633 : inline typename InaVecFLOPS<VecType>::MaskType operator>(const InaVecFLOPS<VecType>& inVec1, const InaVecFLOPS<VecType>& inVec2){
634 : return InaVecFLOPS<VecType>::IsGreaterMask(inVec1,inVec2);
635 : }
636 :
637 : template <class VecType>
638 : inline typename InaVecFLOPS<VecType>::MaskType operator>=(const InaVecFLOPS<VecType>& inVec1, const InaVecFLOPS<VecType>& inVec2){
639 : return InaVecFLOPS<VecType>::IsGreaterOrEqualMask(inVec1,inVec2);
640 : }
641 :
642 : template <class VecType>
643 : inline typename InaVecFLOPS<VecType>::MaskType operator==(const InaVecFLOPS<VecType>& inVec1, const InaVecFLOPS<VecType>& inVec2){
644 : return InaVecFLOPS<VecType>::IsEqualMask(inVec1,inVec2);
645 : }
646 :
647 : template <class VecType>
648 : inline typename InaVecFLOPS<VecType>::MaskType operator!=(const InaVecFLOPS<VecType>& inVec1, const InaVecFLOPS<VecType>& inVec2){
649 : return InaVecFLOPS<VecType>::IsNotEqualMask(inVec1,inVec2);
650 : }
651 :
652 :
653 : template < class VecType >
654 42 : InaVecFLOPSStats InaVecFLOPS<VecType>::FlopsStats;
655 :
656 : #endif // INAVECFLOPS_HPP
|