1 /*******************************************************************************
2 * Copyright 2016-2019 Intel Corporation.
3 *
4 * This software and the related documents are Intel copyrighted  materials,  and
5 * your use of  them is  governed by the  express license  under which  they were
6 * provided to you (License).  Unless the License provides otherwise, you may not
7 * use, modify, copy, publish, distribute,  disclose or transmit this software or
8 * the related documents without Intel's prior written permission.
9 *
10 * This software and the related documents  are provided as  is,  with no express
11 * or implied  warranties,  other  than those  that are  expressly stated  in the
12 * License.
13 *******************************************************************************/
14 
15 #if !defined( __IPP_IWPP_CORE__ )
16 #define __IPP_IWPP_CORE__
17 
18 #include "iw/iw_core.h"
19 
20 #include <string>
21 
22 // IW++ interface configuration switches
23 #ifndef IW_ENABLE_EXCEPTIONS
24 #define IW_ENABLE_EXCEPTIONS 1  // IW++ can return all errors by exceptions or by classic return codes.
25                                 // Note that some errors cannot be returned without exceptions and may be lost.
26 #endif
27 
28 
29 #if IW_ENABLE_EXCEPTIONS == 0
30 #define OWN_ERROR_THROW(IPP_STATUS)      return (IPP_STATUS);
31 #define OWN_ERROR_THROW_ONLY(IPP_STATUS) (void)(IPP_STATUS);
32 #else
33 #define OWN_ERROR_THROW(IPP_STATUS)      throw IwException(IPP_STATUS);
34 #define OWN_ERROR_THROW_ONLY(IPP_STATUS) OWN_ERROR_THROW(IPP_STATUS);
35 #endif
36 #define OWN_ERROR_CHECK_THROW_ONLY(IPP_STATUS)\
37 {\
38     if((IPP_STATUS) < 0)\
39     {\
40         OWN_ERROR_THROW_ONLY(IPP_STATUS)\
41     }\
42 }
43 #define OWN_ERROR_CHECK(IPP_STATUS)\
44 {\
45     if((IPP_STATUS) < 0)\
46     {\
47         OWN_ERROR_THROW(IPP_STATUS)\
48     }\
49 }
50 
51 // Common IW++ API declaration macro
52 #define IW_DECL_CPP(RET_TYPE) IW_INLINE RET_TYPE IPP_STDCALL
53 
54 // Base constructors set for auxiliary parameters
55 #define IW_BASE_PARAMS_CONSTRUCTORS(NAME, FUN)\
56     NAME(const ::NAME *pParams)\
57     {\
58         if(pParams)\
59             *((::NAME*)this) = *pParams;\
60         else\
61             FUN(this);\
62     }\
63     NAME(const ::NAME &params)\
64     {\
65         *((::NAME*)this) = params;\
66     }\
67     NAME(const ipp::IwDefault &)\
68     {\
69         FUN(this);\
70     }
71 
72 namespace ipp
73 {
74 
75 /* /////////////////////////////////////////////////////////////////////////////
76 //                   Base IW++ definitions
77 ///////////////////////////////////////////////////////////////////////////// */
78 
79 using ::IppStatus;
80 using ::IwSize;
81 
82 using ::Ipp8u;
83 using ::Ipp16u;
84 using ::Ipp32u;
85 using ::Ipp8s;
86 using ::Ipp16s;
87 using ::Ipp32s;
88 using ::Ipp32f;
89 using ::Ipp64s;
90 using ::Ipp64u;
91 using ::Ipp64f;
92 using ::Ipp16f;
93 
94 using ::IppDataType;
95 using ::ipp1u;
96 using ::ipp8u;
97 using ::ipp8uc;
98 using ::ipp8s;
99 using ::ipp8sc;
100 using ::ipp16u;
101 using ::ipp16uc;
102 using ::ipp16s;
103 using ::ipp16sc;
104 using ::ipp32u;
105 using ::ipp32uc;
106 using ::ipp32s;
107 using ::ipp32sc;
108 using ::ipp32f;
109 using ::ipp32fc;
110 using ::ipp64u;
111 using ::ipp64uc;
112 using ::ipp64s;
113 using ::ipp64sc;
114 using ::ipp64f;
115 using ::ipp64fc;
116 
117 // Class to initialize default objects
118 class IwDefault
119 {
120 public:
IwDefault()121     IwDefault() {}
122 };
123 
124 #if IW_ENABLE_EXCEPTIONS
125 // Stores an error code value for an exception thrown by the function
126 class IwException
127 {
128 public:
129     // Constructor with status assignment
IwException(IppStatus status)130     IwException(
131         IppStatus status    // IppStatus value
132     )
133     {
134         m_status = status;
135         m_string = iwGetStatusString(m_status);
136     }
137 
138     // Default destructor
~IwException()139     ~IwException() {}
140 
141     // IwException to IppStatus cast operator
operator IppStatus() const142     inline operator IppStatus() const { return m_status;}
143 
144     IppStatus   m_status;   // Stored IppStatus value
145     const char *m_string;   // Stored status string
146 };
147 #endif
148 
149 // This class sets Intel IPP optimizations for the current region and restores previous optimizations at the region end
150 class IwSetCpuFeaturesRegion
151 {
152 public:
153     // Default constructor. Saves current enabled CPU features.
IwSetCpuFeaturesRegion()154     IwSetCpuFeaturesRegion()
155     {
156         m_stored = ::ippGetEnabledCpuFeatures();
157     }
158 
159     // Saves current enabled CPU features and sets new features mask.
IwSetCpuFeaturesRegion(Ipp64u featuresMask)160     IwSetCpuFeaturesRegion(Ipp64u featuresMask)
161     {
162         m_stored = ::ippGetEnabledCpuFeatures();
163         Set(featuresMask);
164     }
165 
166     // Sets new features mask for the region.
Set(Ipp64u featuresMask)167     IppStatus Set(Ipp64u featuresMask)
168     {
169         return ::ippSetCpuFeatures(featuresMask);
170     }
171 
172     // Default destructor. Restores saved features mask.
~IwSetCpuFeaturesRegion()173     ~IwSetCpuFeaturesRegion()
174     {
175         ::ippSetCpuFeatures(m_stored);
176     }
177 
178 private:
179     Ipp64u m_stored;
180 };
181 
182 // Stores values for an array for array type casting
183 template<typename DST>
184 class IwValue
185 {
186 public:
187     // Default constructor. Sets array to zero
IwValue()188     IwValue()
189     {
190         SetValue<Ipp8u>(0);
191     }
192 
193     // Uniform template-based constructor. Sets channels to one value
194     template<typename SRC>
IwValue(SRC valUniform)195     IwValue(SRC valUniform)
196     {
197         SetValue<SRC>(valUniform);
198     }
199 
200     // 3 channels template-based constructor. Sets channels to individual values
201     template<typename SRC>
IwValue(SRC valC1,SRC valC2,SRC valC3)202     IwValue(SRC valC1, SRC valC2, SRC valC3)
203     {
204         SetValue<SRC>(valC1, valC2, valC3);
205     }
206 
207     // 4 channels template-based constructor. Sets channels to individual values
208     template<typename SRC>
IwValue(SRC valC1,SRC valC2,SRC valC3,SRC valC4)209     IwValue(SRC valC1, SRC valC2, SRC valC3, SRC valC4)
210     {
211         SetValue<SRC>(valC1, valC2, valC3, valC4);
212     }
213 
214     // Buffer template-based constructor. Sets values from a buffer of specific type
215     template<typename SRC>
IwValue(SRC * pBuffer,int channels)216     IwValue(SRC *pBuffer, int channels)
217     {
218         SetValue(pBuffer, channels);
219     }
220 
221     // Buffer parameter-based constructor. Sets values from a buffer of specific type
IwValue(void * pBuffer,IppDataType type,int channels)222     IwValue(void *pBuffer, IppDataType type, int channels)
223     {
224         SetValue(pBuffer, type, channels);
225     }
226 
227     // Uniform template setter. Sets channels to one value
228     template<typename SRC>
SetValue(SRC valUniform)229     void SetValue(SRC valUniform)
230     {
231         m_values = 1;
232         m_val[0] = m_val[1] = m_val[2] = m_val[3] = (DST)valUniform;
233     }
234 
235     // 3 channels template setter. Sets channels to individual values
236     template<typename SRC>
SetValue(SRC valC1,SRC valC2,SRC valC3)237     void SetValue(SRC valC1, SRC valC2, SRC valC3)
238     {
239         m_values = 3;
240         m_val[0] = (DST)valC1, m_val[1] = (DST)valC2, m_val[2] = (DST)valC3;
241     }
242 
243     // 4 channels template setter. Sets channels to individual values
244     template<typename SRC>
SetValue(SRC valC1,SRC valC2,SRC valC3,SRC valC4)245     void SetValue(SRC valC1, SRC valC2, SRC valC3, SRC valC4)
246     {
247         m_values = 4;
248         m_val[0] = (DST)valC1, m_val[1] = (DST)valC2, m_val[2] = (DST)valC3, m_val[3] = (DST)valC4;
249     }
250 
251     // Buffer template-based setter. Sets values from a buffer of specific type
252     template<typename SRC>
SetValue(SRC * pBuffer,int channels)253     void SetValue(SRC *pBuffer, int channels)
254     {
255         if(!pBuffer)
256             OWN_ERROR_THROW_ONLY(ippStsNullPtrErr);
257         if(channels > 4 || channels < 1)
258             OWN_ERROR_THROW_ONLY(ippStsNumChannelsErr);
259         m_values = channels;
260 
261         for(int i = 0; i < channels; i++)
262             m_val[i] = (DST)(pBuffer[i]);
263     }
264 
265     // Buffer parameter-based setter. Sets values from a buffer of specific type
SetValue(void * pBuffer,IppDataType type,int channels)266     void SetValue(void *pBuffer, IppDataType type, int channels)
267     {
268         switch(type)
269         {
270             case ipp8u:
271                 SetValue((Ipp8u*)pBuffer, channels);  break;
272             case ipp8s:
273                 SetValue((Ipp8s*)pBuffer, channels);  break;
274             case ipp16u:
275                 SetValue((Ipp16u*)pBuffer, channels); break;
276             case ipp16s:
277                 SetValue((Ipp16s*)pBuffer, channels); break;
278             case ipp32u:
279                 SetValue((Ipp32u*)pBuffer, channels); break;
280             case ipp32s:
281                 SetValue((Ipp32s*)pBuffer, channels); break;
282             case ipp32f:
283                 SetValue((Ipp32f*)pBuffer, channels); break;
284             case ipp64u:
285                 SetValue((Ipp64u*)pBuffer, channels); break;
286             case ipp64s:
287                 SetValue((Ipp64s*)pBuffer, channels); break;
288             case ipp64f:
289                 SetValue((Ipp64f*)pBuffer, channels); break;
290             default:
291                 OWN_ERROR_THROW_ONLY(ippStsDataTypeErr);
292         }
293     }
294 
295     // Returns number of initialized values
ValuesNum() const296     int ValuesNum() const { return m_values; }
297 
298     // IwValue to Ipp64f cast operator
operator DST() const299     inline operator       DST  () const { return ((DST*)m_val)[0];}
300 
301     // IwValue to Ipp64f* cast operator
operator DST*() const302     inline operator       DST* () const { return (DST*)m_val;}
303 
304     // IwValue to const Ipp64f* cast operator
operator const DST*() const305     inline operator const DST* () const { return (const DST*)m_val;}
306 
307     // Array subscript operator
operator [](int channel)308     inline DST& operator[](int channel)             { return (channel>=m_values)?m_val[m_values-1]:m_val[channel]; }
operator [](int channel) const309     inline const DST& operator[](int channel) const { return (channel>=m_values)?m_val[m_values-1]:m_val[channel]; }
310 
311     // Compares values
operator ==(const IwValue & rhs) const312     bool operator==(const IwValue& rhs) const
313     {
314         if((*this)[0] == rhs[0] && (*this)[1] == rhs[1] && (*this)[2] == rhs[2] && (*this)[3] == rhs[3])
315             return true;
316         else
317             return false;
318     }
operator !=(const IwValue & rhs) const319     bool operator!=(const IwValue& rhs) const
320     {
321         return !(*this==rhs);
322     }
323 
324 private:
325     int    m_values;  // Number of initialized values
326     DST    m_val[4];  // reserve 4 channels
327 };
328 
329 typedef IwValue<Ipp64f> IwValueFloat;
330 typedef IwValue<Ipp32s> IwValueInt;
331 
332 // Convert IppDataType to actual size in bytes
333 // Returns:
334 //      Size of IppDataType in bytes
iwTypeToSize(IppDataType type)335 IW_DECL_CPP(int) iwTypeToSize(
336     IppDataType type    // Data type
337 )
338 {
339     return ::iwTypeToSize(type);
340 }
341 
342 // Returns 1 if data type is of float type and 0 otherwise
343 // Returns:
344 //      Absolute value
iwTypeIsFloat(IppDataType type)345 IW_DECL_CPP(int) iwTypeIsFloat(
346     IppDataType type    // Data type
347 )
348 {
349     return ::iwTypeIsFloat(type);
350 }
351 
352 // Returns minimum possible value for specified data type
353 // Returns:
354 //      Minimum value
iwTypeGetMin(IppDataType type)355 IW_DECL_CPP(double) iwTypeGetMin(
356     IppDataType type    // Data type for min value
357 )
358 {
359     return ::iwTypeGetMin(type);
360 }
361 
362 // Returns maximum possible value for specified data type
363 // Returns:
364 //      Maximum value
iwTypeGetMax(IppDataType type)365 IW_DECL_CPP(double) iwTypeGetMax(
366     IppDataType type    // Data type for max value
367 )
368 {
369     return ::iwTypeGetMax(type);
370 }
371 
372 // Returns values range for specified data type
373 // Returns:
374 //      Range value
iwTypeGetRange(IppDataType type)375 IW_DECL_CPP(double) iwTypeGetRange(
376     IppDataType type    // Data type for range value
377 )
378 {
379     return ::iwTypeGetRange(type);
380 }
381 
382 // Cast double value to input type with rounding and saturation
383 // Returns:
384 //      Rounded and saturated value
iwValueSaturate(double val,IppDataType dstType)385 IW_DECL_CPP(double) iwValueSaturate(
386     double      val,    // Input value
387     IppDataType dstType // Data type for saturation range
388 )
389 {
390     return ::iwValueSaturate(val, dstType);
391 }
392 
393 // Converts relative value in range of [0,1] to the absolute value according to specified type
394 // Returns:
395 //      Absolute value
iwValueRelToAbs(double val,IppDataType type)396 IW_DECL_CPP(double) iwValueRelToAbs(
397     double      val,    // Relative value. From 0 to 1
398     IppDataType type    // Data type for the absolute range
399 )
400 {
401     return ::iwValueRelToAbs(val, type);
402 }
403 
404 /* /////////////////////////////////////////////////////////////////////////////
405 //                   IW with Threading Layer control
406 ///////////////////////////////////////////////////////////////////////////// */
407 
408 // This function sets number of threads for IW functions with parallel execution support
iwSetThreadsNum(int threads)409 IW_DECL_CPP(void) iwSetThreadsNum(
410     int threads     // Number of threads to use
411 )
412 {
413     ::iwSetThreadsNum(threads);
414 }
415 
416 // This function returns number of threads used by IW functions with parallel execution support
417 // Returns:
418 //      Number of threads or 0 if compiled without internal threading support
iwGetThreadsNum()419 IW_DECL_CPP(int)  iwGetThreadsNum()
420 {
421     return ::iwGetThreadsNum();
422 }
423 
424 // This function returns initial number of threads used by IW functions with parallel execution support
425 // Returns:
426 //      Default number of threads or 0 if compiled without internal threading support
iwGetThreadsNumDefault()427 IW_DECL_CPP(int)  iwGetThreadsNumDefault()
428 {
429     return ::iwGetThreadsNumDefault();
430 }
431 
432 
433 /* /////////////////////////////////////////////////////////////////////////////
434 //                   IwTls - TLS data storage interface
435 ///////////////////////////////////////////////////////////////////////////// */
436 
437 // Template-based TLS abstraction layer class.
438 // This is an extension of C IwTls structure with automatic objects destruction
439 template<class TYPE>
440 class IwTls: private ::IwTls
441 {
442 public:
443     // Default constructor
IwTls()444     IwTls()
445     {
446         IppStatus status = ::iwTls_Init(this, (IwTlsDestructor)(IwTls::TypeDestructor));
447         OWN_ERROR_CHECK_THROW_ONLY(status);
448     }
449 
450     // Default destructor
~IwTls()451     ~IwTls()
452     {
453         ::iwTls_Release(this);
454     }
455 
456     // Allocates object for current thread and returns pointer to it
Create()457     TYPE* Create()
458     {
459         TYPE *pData = new TYPE;
460         if(!pData)
461             return NULL;
462         IppStatus status = ::iwTls_Set(this, pData);
463         if(status < 0)
464         {
465             delete pData;
466             OWN_ERROR_CHECK_THROW_ONLY(status);
467             return NULL;
468         }
469         return pData;
470     }
471 
472     // Releases object for current thread
Release()473     void Release()
474     {
475         IppStatus status = ::iwTls_Set(this, NULL);
476         if(status < 0)
477             OWN_ERROR_CHECK_THROW_ONLY(status);
478     }
479 
480     // Releases objects for all threads
ReleaseAll()481     void ReleaseAll()
482     {
483         IppStatus status = ::iwTls_ReleaseData(this);
484         if(status < 0)
485             OWN_ERROR_CHECK_THROW_ONLY(status);
486     }
487 
488     // Returns pointer to object for current thread
Get() const489     TYPE* Get() const
490     {
491         return (TYPE*)::iwTls_Get(this);
492     }
493 
494 private:
495     // Object destructor
TypeDestructor(void * pData)496     static void IPP_STDCALL TypeDestructor(void *pData)
497     {
498         if(pData)
499             delete ((TYPE*)pData);
500     }
501 };
502 
503 /* /////////////////////////////////////////////////////////////////////////////
504 //                   IW version info
505 ///////////////////////////////////////////////////////////////////////////// */
506 
507 class IppVersion: private ::IwVersion
508 {
509 public:
IppVersion()510     IppVersion()
511     {
512         ::iwGetLibVersion(this);
513         if(!this->m_pIppVersion)
514             OWN_ERROR_THROW_ONLY(ippStsNullPtrErr);
515     }
516 
getMajor()517     int getMajor()
518     {
519         return this->m_pIppVersion->major;
520     }
521 
getMinor()522     int getMinor()
523     {
524         return this->m_pIppVersion->minor;
525     }
526 
getUpdate()527     int getUpdate()
528     {
529         return this->m_pIppVersion->majorBuild;
530     }
531 
getRevision()532     int getRevision()
533     {
534         return this->m_pIppVersion->build;
535     }
536 
getString()537     std::string getString()
538     {
539         return this->m_pIppVersion->Version;
540     }
541 
getLibraryName()542     std::string getLibraryName()
543     {
544         return this->m_pIppVersion->Name;
545     }
546 
getTargetCpu()547     std::string getTargetCpu()
548     {
549         return this->m_pIppVersion->targetCpu;
550     }
551 
getBuildDate()552     std::string getBuildDate()
553     {
554         return this->m_pIppVersion->BuildDate;
555     }
556 
getInfoString()557     std::string getInfoString()
558     {
559         return getLibraryName() + " " + getString() + ", " + getBuildDate();
560     }
561 };
562 
563 class IwVersion: private ::IwVersion
564 {
565 public:
IwVersion()566     IwVersion()
567     {
568         ::iwGetLibVersion(this);
569         if(!this->m_pIppVersion)
570             OWN_ERROR_THROW_ONLY(ippStsNullPtrErr);
571     }
572 
getMajor()573     int getMajor()
574     {
575         return this->m_major;
576     }
577 
getMinor()578     int getMinor()
579     {
580         return this->m_minor;
581     }
582 
getUpdate()583     int getUpdate()
584     {
585         return this->m_update;
586     }
587 
getString()588     std::string getString()
589     {
590         return this->m_versionStr;
591     }
592 
getInfoString()593     std::string getInfoString()
594     {
595         if(isReleaseBuild())
596             return getString() + ", release build";
597         else
598             return getString() + ", user build";
599     }
600 
isReleaseBuild()601     bool isReleaseBuild()
602     {
603         return !this->m_bUserBuild;
604     }
605 };
606 
607 }
608 
609 #endif
610