MMALIB User Guide
MMALIB_utility.h
Go to the documentation of this file.
1 #ifndef COMMON_MMALIB_UTILITY_H_
2 #define COMMON_MMALIB_UTILITY_H_ 1
3 
4 /******************************************************************************/
8 /* Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  *
17  * Redistributions in binary form must reproduce the above copyright
18  * notice, this list of conditions and the following disclaimer in the
19  * documentation and/or other materials provided with the
20  * distribution.
21  *
22  * Neither the name of Texas Instruments Incorporated nor the names of
23  * its contributors may be used to endorse or promote products derived
24  * from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  *
38  ******************************************************************************/
39 
40 
41 /*******************************************************************************
42  *
43  * INCLUDES
44  *
45  ******************************************************************************/
46 
47 #include <float.h> // for max float, double values
48 #include <limits.h> // for min, max integer values
49 #include <math.h>
50 
51 #include "MMALIB_bufParams.h"
52 #include "MMALIB_types.h"
53 
54 #include "c71/MMALIB_utility.h"
55 #if MMALIB_DEBUGPRINT >= 1
56 #include "c71/MMALIB_debug.h"
57 #endif
58 
59 
60 /*******************************************************************************
61  *
62  * EXTERNAL VARIABLES
63  *
64  ******************************************************************************/
65 #ifdef __cplusplus
66 extern "C" {
67 #endif /* __cplusplus */
68 extern uint64_t beg_count; /* Begin cycle count for profiling */
69 extern uint64_t end_count; /* End cycle count for profiling */
70 extern uint64_t overhead; /* Cycle profiling overhead */
71 #ifdef __cplusplus
72 }
73 #endif /* __cplusplus */
74 
75 /*******************************************************************************
76  *
77  * Inline functions
78  *
79  ******************************************************************************/
80 
81 /*******************************************************************************
82  *
83  * Arithmetic with 128-bit signed integers
84  *
85  ******************************************************************************/
86 static inline void MMALIB_UTIL_mult(int64_t *ph, int64_t *pl, int64_t a, int64_t b);
87 
88 static inline void MMALIB_UTIL_mult(int64_t *ph , // result
89  int64_t *pl ,
90  int64_t a , // left operand
91  int64_t b // right operand
92  ){
93  //sum += A[k + m*K] * B[n + k*N];
94  *pl = a * b ;
95 
96  // sign extend the product
97  *ph = ((((uint64_t)*pl) & 0x8000000000000000ULL) != 0ULL)?(int64_t)0xffffffffffffffffULL:(int64_t)0ULL ;
98 }
99 
100 #ifdef __cplusplus
101 /*******************************************************************************
102  *
103  * We need special utility to do negation because range of values is from
104  * -2^(bit-width-1) to 2^(bit-width-1)-1. For example, with int16_t, the
105  * range is from -32768 to 32767 - that is, -0x8000 to 0x7FFF. Now, if we want
106  * to evaluate negation of -32768 and we try simply -(-32768) and store the
107  * result in int16_t, we would get -32768 itself. Instead, we want to get 32767.
108  *
109  ******************************************************************************/
110 
111 static inline int16_t MMALIB_UTIL_negate(int16_t a)
112 {
113  int16_t result;
114 
115  result = (a == -32768) ? 32767 : -a;
116  return result;
117 }
118 
119 static inline int32_t MMALIB_UTIL_negate(int32_t a)
120 {
121  int32_t result;
122 
123  result = (a == -2147483648) ? 2147483647 : -a;
124  return result;
125 }
126 
127 /*******************************************************************************
128  *
129  * Inline multiply with higher bit-width output type
130  *
131  ******************************************************************************/
132 
133 static inline uint32_t MMALIB_UTIL_mult(uint8_t a, uint8_t b)
134 {
135  return (uint16_t)a * (uint16_t)b;
136 }
137 
138 static inline int32_t MMALIB_UTIL_mult(int8_t a, int8_t b)
139 {
140  return (int16_t)a * (int16_t)b;
141 }
142 
143 static inline int32_t MMALIB_UTIL_mult(uint8_t a, int8_t b)
144 {
145  return (int16_t)a * (int16_t)b;
146 }
147 
148 static inline int32_t MMALIB_UTIL_mult(int8_t a, uint8_t b)
149 {
150  return (int16_t)a * (int16_t)b;
151 }
152 
153 static inline uint64_t MMALIB_UTIL_mult(uint16_t a, uint16_t b)
154 {
155  return (uint32_t)a * (uint32_t)b;
156 }
157 
158 static inline int64_t MMALIB_UTIL_mult(int16_t a, int16_t b)
159 {
160  return (int32_t)a * (int32_t)b;
161 }
162 
163 static inline int64_t MMALIB_UTIL_mult(uint16_t a, int16_t b)
164 {
165  return (int32_t)a * (int32_t)b;
166 }
167 
168 static inline int64_t MMALIB_UTIL_mult(int16_t a, uint16_t b)
169 {
170  return (int32_t)a * (int32_t)b;
171 }
172 
173 
174 static inline MMALIB_int128_t MMALIB_UTIL_mult(uint32_t a, uint32_t b)
175 {
176  MMALIB_int128_t result(0,0);
177 
178  result.lo = (int64_t)a * (int64_t)b ;
179  // sign extend the product
180  result.hi = (int64_t)0ULL ;
181 
182  return result;
183 }
184 
185 static inline MMALIB_int128_t MMALIB_UTIL_mult(int32_t a, int32_t b)
186 {
187  MMALIB_int128_t result(0,0);
188 
189  result.lo = (int64_t)a * (int64_t)b ;
190  // sign extend the product
191  result.hi = (((uint64_t)result.lo & 0x8000000000000000ULL) != 0LL)?(int64_t)0xffffffffffffffffULL:(int64_t)0ULL ;
192 
193  return result;
194 }
195 
196 static inline MMALIB_int128_t MMALIB_UTIL_mult(uint32_t a, int32_t b)
197 {
198  MMALIB_int128_t result(0,0);
199 
200  result.lo = (int64_t)a * (int64_t)b ;
201  // sign extend the product
202  result.hi = (((uint64_t)result.lo & 0x8000000000000000ULL) != 0LL)?(int64_t)0xffffffffffffffffULL:(int64_t)0ULL ;
203 
204  return result;
205 }
206 
207 static inline MMALIB_int128_t MMALIB_UTIL_mult(int32_t a, uint32_t b)
208 {
209  MMALIB_int128_t result(0,0);
210 
211  result.lo = (int64_t)a * (int64_t)b ;
212  // sign extend the product
213  result.hi = (((uint64_t)result.lo & 0x8000000000000000ULL) != 0LL)?(int64_t)0xffffffffffffffffULL:(int64_t)0ULL ;
214 
215  return result;
216 }
217 
218 /*******************************************************************************
219  *
220  * Inline shift, saturate and ReLU operation
221  *
222  ******************************************************************************/
223 
224 static inline void MMALIB_UTIL_shift_saturate_relu(int32_t x, uint8_t shift, int8_t *y)
225 {
226  int64_t xVal = x;
227 
228 //#if MMALIB_DEBUGPRINT
229 // printf("MMALIB_DEBUGPRINT MMALIB_UTIL_scale_shift_saturate_relu: scaledValue %ll xVal %d scale %d shift %d\n", scaledValue, xVal,scale, shift);
230 //#endif
231  if(shift > 0) {
232  xVal = __shift_right(xVal, (shift - 1)) + 1;
233  xVal = __shift_right(xVal, 1);
234  }
235 
236  if (xVal > 0x7F) {
237  *y = 0x7F;
238  } else if (xVal < 0) {
239  *y = 0;
240  } else {
241  *y = (int8_t)xVal;
242  }
243 
244  return;
245 }
246 
247 static inline void MMALIB_UTIL_shift_saturate_relu(int32_t x, uint8_t shift, uint8_t *y)
248 {
249  int64_t xVal = x;
250 //#if MMALIB_DEBUGPRINT
251 // printf("scaledValue %" PRId64 "\n", scaledValue);
252 // printf("MMALIB_DEBUGPRINT MMALIB_UTIL_scale_shift_saturate_relu: xVal %d scale %d shift %d\n", xVal,scale, shift);
253 //#endif
254  if(shift > 0) {
255  xVal = __shift_right(xVal, (shift - 1)) + 1;
256  xVal = __shift_right(xVal, 1);
257  }
258 
259  if (xVal > 0xFF) {
260  *y = 0xFF;
261  } else if (xVal < 0) {
262  *y = 0;
263  } else {
264  *y = (uint8_t)xVal;
265  }
266 
267  return;
268 }
269 
270 static inline void MMALIB_UTIL_shift_saturate_relu(int64_t x, uint8_t shift, int16_t *y)
271 {
272  int64_t xVal = x;
273 
274  if(shift > 0) {
275  xVal = __shift_right(xVal, (shift - 1)) + 1;
276  xVal = __shift_right(xVal, 1);
277  }
278 
279  if (xVal > 0x7FFF) {
280  *y = 0x7FFF;
281  } else if (xVal < 0x0000) {
282  *y = 0x0000;
283  } else {
284  *y = (int16_t)xVal;
285  }
286 
287  return;
288 }
289 
290 static inline void MMALIB_UTIL_shift_saturate_relu(int64_t x, uint8_t shift, uint16_t *y)
291 {
292  int64_t xVal = x;
293 
294  if(shift > 0) {
295  xVal = __shift_right(xVal, (shift - 1)) + 1;
296  xVal = __shift_right(xVal, 1);
297  }
298 
299 
300  if (xVal > 0xFFFF) {
301  *y = 0xFFFF;
302  } else if (xVal < 0x0000) {
303  *y = 0x0000;
304  } else {
305  *y = (uint16_t)xVal;
306  }
307 
308  return;
309 }
310 
311 static inline void MMALIB_UTIL_shift_saturate_relu(uint64_t x, uint8_t shift, uint16_t *y)
312 {
313  uint64_t xVal = x;
314 
315  uint32_t shift32_t = (uint32_t) shift;
316 
317  if (shift32_t > 0) {
318  xVal = (xVal >> (shift32_t - (uint32_t)1) ) + 1;
319  xVal = (xVal >> 1);
320  }
321 
322  if (xVal > 0xFFFF) {
323  *y = 0xFFFF;
324  } else {
325  *y = (uint16_t)xVal;
326  }
327 
328  return;
329 }
330 
331 /*******************************************************************************
332  *
333  * Inline saturate with ReLU operation
334  *
335  ******************************************************************************/
336 
337 static inline void MMALIB_UTIL_saturate_relu(int32_t x, int8_t *y)
338 {
339  if (x > 0x7F) {
340  *y = 0x7F;
341  } else if (x < 0) {
342  *y = 0;
343  } else {
344  *y = (int8_t)x;
345  }
346 
347  return;
348 }
349 
350 static inline void MMALIB_UTIL_saturate_relu(int32_t x, uint8_t *y)
351 {
352  if (x > 0xFF) {
353  *y = 0xFF;
354  } else if (x < 0) {
355  *y = 0;
356  } else {
357  *y = (uint8_t)x;
358  }
359 
360  return;
361 }
362 
363 static inline void MMALIB_UTIL_saturate_relu(uint32_t x, uint8_t *y)
364 {
365  if (x > 0xFF) {
366  *y = 0xFF;
367  } else {
368  *y = (uint8_t)x;
369  }
370 
371  return;
372 }
373 
374 static inline void MMALIB_UTIL_saturate_relu(int64_t x, int16_t *y)
375 {
376  if (x > 0x7FFF) {
377  *y = 0x7FFF;
378  } else if (x < 0x0000) {
379  *y = 0x0000;
380  } else {
381  *y = (int16_t)x;
382  }
383 
384  return;
385 }
386 
387 static inline void MMALIB_UTIL_saturate_relu(int64_t x, uint16_t *y)
388 {
389  if (x > 0xFFFF) {
390  *y = 0xFFFF;
391  } else if (x < 0x0000) {
392  *y = 0x0000;
393  } else {
394  *y = (uint16_t)x;
395  }
396 
397  return;
398 }
399 
400 static inline void MMALIB_UTIL_saturate_relu(uint64_t x, uint16_t *y)
401 {
402  if (x > 0xFFFF) {
403  *y = 0xFFFF;
404  } else {
405  *y = (uint16_t)x;
406  }
407 
408  return;
409 }
410 
411 static inline int32_t MMALIB_UTIL_saturate_relu(int64_t xh, int64_t xl)
412 {
413  int32_t retVal;
414  //printf("%s: xh = %" PRIx64 ", xl = %" PRIx64 "\n", __FUNCTION__, xh, xl);
415  // if negative
416  if(((uint64_t)xh & 0x8000000000000000ULL) != 0LL){
417  if( ((~(uint64_t)xh & 0xFFFFFFFFFFFFFFFFULL) != 0LL) || ((~(uint64_t)xl & 0xFFFFFFFF80000000ULL) != 0LL)){
418  retVal = ((int32_t)0x80000000U);
419  } else {
420  retVal = (int32_t)xl;
421  }
422  } else if (((uint64_t)xl & 0xFFFFFFFF80000000ULL) != 0LL){
423  //(xl > 0x000000007FFFFFFFLL){ // positive and saturated
424  retVal = ((int32_t)0x7FFFFFFFU);
425  } else {
426  retVal = (int32_t)xl;
427  }
428  return retVal;
429 }
430 
431 static inline int32_t MMALIB_UTIL_saturate_relu(MMALIB_int128_t x, int32_t *y)
432 {
433  return MMALIB_UTIL_saturate_relu(x.hi, int64_t(0));
434 }
435 
436 /*******************************************************************************
437  *
438  * Inline shift, round and ReLU operation
439  *
440  ******************************************************************************/
441 
442 template <typename dataType, typename returnType>
443 static inline returnType MMALIB_UTIL_shiftRoundAndReLU(dataType inVal, uint8_t shift){
444  returnType result;
445 
446  if(shift == 0){
447  // remove the rounding, which doesn't make sense with no shift but causes C code problems
448  MMALIB_UTIL_saturate_relu(inVal, &result);
449  } else {
450  // round and shift
451  // Method requires right shift of signed integers be an arithmetic shift, but right
452  // shift >> on signed integer types is implementation dependent on whether the shift is
453  // arithmetic or logical. There's no simple way in C to specify the shift type as arithmetic.
454  // Instead, we use the __shift_right intrinsic, which is defined to be arithmetic shift.
455  dataType temp;
456  temp = __shift_right(inVal, (shift - 1)) + 1;
457  temp = __shift_right(temp, 1);
458  MMALIB_UTIL_saturate_relu(temp, &result);
459  }
460 
461  return result;
462 }
463 
464 /*******************************************************************************
465  *
466  * Specialized shift and round operation for floating points
467  * Basically just returns input as it is
468  *
469  ******************************************************************************/
470 
471 template <>
472 inline uint8_t MMALIB_UTIL_shiftRoundAndReLU<int32_t, uint8_t>(int32_t inVal, uint8_t shift){
473  uint8_t result;
474 
475  if(shift == 0){
476  // remove the rounding, which doesn't make sense with no shift but causes C code problems
477  MMALIB_UTIL_saturate_relu(inVal, &result);
478  } else {
479  // round and shift
480  // Method requires right shift of signed integers be an arithmetic shift, but right
481  // shift >> on signed integer types is implementation dependent on whether the shift is
482  // arithmetic or logical. There's no simple way in C to specify the shift type as arithmetic.
483  // Instead, we use the __shift_right intrinsic, which is defined to be arithmetic shift.
484  int32_t temp;
485  temp = __shift_right( inVal, (shift - 1) ) + 1;
486  temp = __shift_right(temp, 1);
487  MMALIB_UTIL_saturate_relu(temp, &result);
488 
489  }
490 
491  return result;
492 }
493 
494 template <>
495 inline uint8_t MMALIB_UTIL_shiftRoundAndReLU<uint32_t, uint8_t>(uint32_t inVal, uint8_t shift){
496  uint8_t result;
497 
498  if(shift == 0){
499  // remove the rounding, which doesn't make sense with no shift but causes C code problems
500  MMALIB_UTIL_saturate_relu(inVal, &result);
501  } else {
502  uint32_t temp;
503  //Subtracting two unsigned values of the same size will result in an unsigned value.
504  //If the first operand is less than the second the result will be arithmetically in correct.
505  //But if the size of the unsigned types is less than that of an unsigned int, C/C++ will promote the types to
506  //signed int before subtracting resulting in an correct result. In either case,
507  //there is no indication of an error.
508  uint32_t shift32_t = (uint32_t) shift;
509  temp = (inVal >> (shift32_t - (uint32_t)1) ) + 1;
510  temp = temp >> 1;
511  MMALIB_UTIL_saturate_relu(temp, &result);
512  }
513 
514  return result;
515 }
516 
517 template <>
518 inline uint16_t MMALIB_UTIL_shiftRoundAndReLU<int64_t, uint16_t>(int64_t inVal, uint8_t shift){
519  uint16_t result;
520 
521  if(shift == 0){
522  // remove the rounding, which doesn't make sense with no shift but causes C code problems
523  MMALIB_UTIL_saturate_relu(inVal, &result);
524  } else {
525  // round and shift
526  // Method requires right shift of signed integers be an arithmetic shift, but right
527  // shift >> on signed integer types is implementation dependent on whether the shift is
528  // arithmetic or logical. There's no simple way in C to specify the shift type as arithmetic.
529  // Instead, we use the __shift_right intrinsic, which is defined to be arithmetic shift.
530  int64_t temp;
531  temp = __shift_right( inVal, (shift - 1) ) + 1;
532  temp = __shift_right(temp, 1);
533  MMALIB_UTIL_saturate_relu(temp, &result);
534  }
535 
536  return result;
537 }
538 
539 template <>
540 inline uint16_t MMALIB_UTIL_shiftRoundAndReLU<uint64_t, uint16_t>(uint64_t inVal, uint8_t shift){
541  uint16_t result=0;
542 
543  if(shift == 0){
544  // remove the rounding, which doesn't make sense with no shift but causes C code problems
545  MMALIB_UTIL_saturate_relu(inVal, &result);
546  } else {
547  uint64_t temp;
548  uint32_t shift32_t = (uint32_t) shift;
549  temp = (inVal >> (shift32_t - (uint32_t)1) ) + 1;
550  temp = (temp >> 1);
551  MMALIB_UTIL_saturate_relu(temp, &result);
552  }
553 
554  return result;
555 }
556 
557 template <>
558 inline int32_t MMALIB_UTIL_shiftRoundAndReLU<MMALIB_int128_t, int32_t>(MMALIB_int128_t inVal, uint8_t shift){
559  int32_t result;
560 
561  if(shift == 0){
562  // remove the rounding, which doesn't make sense with no shift but causes C code problems
563  result = MMALIB_UTIL_saturate_relu(inVal, &result);
564  } else {
565  // round and shift
566  //result = MMALIB_UTIL_saturate(((inVal >> ((uint8_t)(shift - 1))) + 1) >> 1);
567  MMALIB_int128_t temp;
568  // temp = inVal >> (shift - 1)
569  MMALIB_UTIL_shiftRight128((uint64_t *)&temp.hi, (uint64_t *)&temp.lo, inVal.hi, inVal.lo, (int32_t)(shift - 1), 1);
570  temp = temp + 1;
571  // temp = temp >> 1
572  MMALIB_UTIL_shiftRight128((uint64_t *)&temp.hi, (uint64_t *)&temp.lo, temp.hi, temp.lo, 1, 1);
573  MMALIB_UTIL_saturate_relu(temp, &result);
574  }
575 
576  return result;
577 }
578 
579 
580 /*******************************************************************************
581  *
582  * Inline saturate operation
583  *
584  ******************************************************************************/
585 
586 static inline int8_t MMALIB_UTIL_saturate(int32_t x)
587 {
588  int8_t retVal;
589  if (x > 0x7F) {
590  retVal = 0x7F;
591  } else if (x < -0x80) {
592  retVal = -0x80;
593  } else {
594  retVal = (int8_t)x;
595  }
596  return retVal;
597 }
598 
599 static inline uint8_t MMALIB_UTIL_saturate(uint32_t x)
600 {
601  uint8_t retVal;
602  if (x > 0xFF) {
603  retVal = 0xFF;
604  } else {
605  retVal = (uint8_t)x;
606  }
607  return retVal;
608 }
609 
610 static inline int16_t MMALIB_UTIL_saturate(int64_t x)
611 {
612  int16_t retVal;
613  if (x > 0x7FFF) {
614  retVal = 0x7FFF;
615  } else if (x < -0x8000) {
616  retVal = -0x8000;
617  } else {
618  retVal = (int16_t)x;
619  }
620  return retVal;
621 }
622 
623 static inline uint16_t MMALIB_UTIL_saturate(uint64_t x)
624 {
625  uint16_t retVal;
626  if (x > 0xFFFF) {
627  retVal = 0xFFFF;
628  } else {
629  retVal = (uint16_t)x;
630  }
631  return retVal;
632 }
633 
634 static inline int32_t MMALIB_UTIL_saturate(int64_t xh, int64_t xl)
635 {
636  int32_t retVal;
637  //printf("%s: xh = %" PRIx64 ", xl = %" PRIx64 "\n", __FUNCTION__, xh, xl);
638  // if negative
639  if(((uint64_t)xh & 0x8000000000000000ULL) != 0LL){
640  if( ((~(uint64_t)xh & 0xFFFFFFFFFFFFFFFFULL) != 0LL) || ((~(uint64_t)xl & 0xFFFFFFFF80000000ULL) != 0LL)){
641  retVal = ((int32_t)0x80000000U);
642  } else {
643  retVal = (int32_t)xl;
644  }
645  } else if (((uint64_t)xl & 0xFFFFFFFF80000000ULL) != 0LL){
646  //(xl > 0x000000007FFFFFFFLL){ // positive and saturated
647  retVal = ((int32_t)0x7FFFFFFFU);
648  } else {
649  retVal = (int32_t)xl;
650  }
651  return retVal;
652 }
653 
654 static inline int32_t MMALIB_UTIL_saturate(MMALIB_int128_t x)
655 {
656  return MMALIB_UTIL_saturate(x.hi, x.lo);
657 }
658 
659 /*******************************************************************************
660  *
661  * Inline shift and round operation
662  *
663  ******************************************************************************/
664 
665 template <typename dataType, typename returnType>
666 inline returnType MMALIB_UTIL_shiftAndRound(dataType inVal, uint8_t shift){
667  returnType result;
668 
669  if(shift == 0){
670  // remove the rounding, which doesn't make sense with no shift but causes C code problems
671  result = MMALIB_UTIL_saturate(inVal);
672  } else {
673  // round and shift
674  dataType temp;
675  temp = (__shift_right(inVal, (shift - 1)) + 1);
676  temp = __shift_right(temp , 1);
677  result = MMALIB_UTIL_saturate(temp);
678  }
679 
680  return result;
681 }
682 
683 /*******************************************************************************
684  *
685  * Specialized shift and round operation for floating points
686  * Basically just returns input as it is
687  *
688  ******************************************************************************/
689 template int8_t MMALIB_UTIL_shiftAndRound<int32_t, int8_t> (int32_t inVal, uint8_t shift);
690 template int16_t MMALIB_UTIL_shiftAndRound<int64_t, int16_t> (int64_t inVal, uint8_t shift);
691 
692 
693 template <>
694 inline uint8_t MMALIB_UTIL_shiftAndRound(uint32_t inVal, uint8_t shift){
695  uint8_t result;
696 
697  if(shift == 0){
698  // remove the rounding, which doesn't make sense with no shift but causes C code problems
699  result = MMALIB_UTIL_saturate(inVal);
700  } else {
701  // round and shift
702  uint32_t temp;
703  uint32_t shift32_t = (uint32_t) shift;
704  temp = (inVal >> (shift32_t - (uint32_t)1) ) + 1;
705  temp = (temp >> 1);
706  result = MMALIB_UTIL_saturate(temp);
707  }
708 
709  return result;
710 }
711 
712 template <>
713 inline uint16_t MMALIB_UTIL_shiftAndRound(uint64_t inVal, uint8_t shift){
714  uint16_t result;
715 
716  if(shift == 0){
717  // remove the rounding, which doesn't make sense with no shift but causes C code problems
718  result = MMALIB_UTIL_saturate(inVal);
719  } else {
720  // round and shift
721  uint64_t temp;
722  uint32_t shift32_t = (uint32_t) shift;
723  temp = (inVal >> (shift32_t - (uint32_t)1) ) + 1;
724  temp = (temp >> 1);
725  result = MMALIB_UTIL_saturate(temp);
726  }
727 
728  return result;
729 }
730 
731 // MISRA-C prohibits using >> on signed integers because it is implementation dependent on whether
732 // that shift is arithmetic or logical. However, for MMALIB_int128_t, this code implements the shift in software
733 // and ensures that it is arithmetic. To avoid the MISRA-C violation, we use the function version of the shift
734 // rather than the >> operator.
735 template <>
736 inline int32_t MMALIB_UTIL_shiftAndRound<MMALIB_int128_t, int32_t>(MMALIB_int128_t inVal, uint8_t shift){
737  int32_t result;
738 
739  if(shift == 0){
740  // remove the rounding, which doesn't make sense with no shift but causes C code problems
741  result = MMALIB_UTIL_saturate(inVal);
742  } else {
743  // round and shift
744  //result = MMALIB_UTIL_saturate(((inVal >> ((uint8_t)(shift - 1))) + 1) >> 1);
745  MMALIB_int128_t temp;
746  // temp = inVal >> (shift - 1)
747  MMALIB_UTIL_shiftRight128((uint64_t *)&temp.hi, (uint64_t *)&temp.lo, inVal.hi, inVal.lo, (int32_t)(shift - 1), 1);
748  temp = temp + 1;
749  // temp = temp >> 1
750  MMALIB_UTIL_shiftRight128((uint64_t *)&temp.hi, (uint64_t *)&temp.lo, temp.hi, temp.lo, 1, 1);
751  result = MMALIB_UTIL_saturate(temp);
752  }
753 
754  return result;
755 }
756 
757 
758 /*******************************************************************************
759  *
760  * Convert a double-precision floating point number to 16-bit integer
761  *
762  ******************************************************************************/
763 
764 template <typename returnType>
765 static inline returnType MMALIB_UTIL_typeConv_i64f_oxX(MMALIB_D64 x)
766 {
767  int64_t xLocal, maxValue;
768  returnType returnValue;
769 
770  /* Set maxValue to the maximumum possible value for the returnType */
771 
772  // original code
773  // maxValue = (1 << (sizeof(returnType)*8-2)) - 1;
774  // maxValue += (1 << (sizeof(returnType)*8-2));
775  maxValue = ((int64_t)( (uint32_t)1 << ((uint32_t)(sizeof(returnType)*8-2)))) - 1;
776  maxValue += (int64_t)( (uint32_t)1 << ((uint32_t)(sizeof(returnType)*8-2)));
777 
778  xLocal = (int64_t)floor(0.5 + x); /* Explicit rounding to integer */
779  if (xLocal >= maxValue) {
780  returnValue = (returnType)maxValue;
781  } else if (xLocal <= -maxValue-1) {
782  returnValue = (returnType)(-maxValue-1);
783  } else {
784  returnValue = (returnType)xLocal;
785  }
786  return returnValue;
787 }
788 
789 template int16_t MMALIB_UTIL_typeConv_i64f_oxX<int16_t>(MMALIB_D64 x);
790 template int32_t MMALIB_UTIL_typeConv_i64f_oxX<int32_t>(MMALIB_D64 x);
791 
792 
793 /*******************************************************************************
794  *
795  * Evaluate cos function, and apply appropriate scale factor
796  *
797  ******************************************************************************/
798 
799 template <typename returnType>
800 static returnType MMALIB_UTIL_cos_i64f_oxX(MMALIB_D64 x,
801  MMALIB_D64 scaleFactor)
802 {
803  return MMALIB_UTIL_typeConv_i64f_oxX<returnType>(scaleFactor*cos(x));
804 }
805 
806 template int16_t MMALIB_UTIL_cos_i64f_oxX<int16_t>(MMALIB_D64 x, MMALIB_D64 scaleFactor);
807 template int32_t MMALIB_UTIL_cos_i64f_oxX<int32_t>(MMALIB_D64 x, MMALIB_D64 scaleFactor);
808 
809 
810 /*******************************************************************************
811  *
812  * Evaluate sin function, and apply appropriate scale factor
813  *
814  ******************************************************************************/
815 
816 template <typename returnType>
817 static inline returnType MMALIB_UTIL_sin_i64f_oxX(MMALIB_D64 x,
818  MMALIB_D64 scaleFactor)
819 {
820  return MMALIB_UTIL_typeConv_i64f_oxX<returnType>(scaleFactor*sin(x));
821 }
822 
823 template int16_t MMALIB_UTIL_sin_i64f_oxX<int16_t>(MMALIB_D64 x, MMALIB_D64 scaleFactor);
824 template int32_t MMALIB_UTIL_sin_i64f_oxX<int32_t>(MMALIB_D64 x, MMALIB_D64 scaleFactor);
825 
826 
827 /*******************************************************************************
828  *
829  * ILUT
830  *
831  ******************************************************************************/
832 
833 // "base" template covers the 8-bit variants
834 template <typename dataType>
835 inline dataType MMALIB_UTIL_iLUT(dataType inVal, const void *pLutValues){
836  const dataType *iLUT = (const dataType*)pLutValues;
837  uint8_t mask = 0xffU;
838 
839  dataType result;
840  uint8_t index = (uint8_t)inVal & mask;
841  result = iLUT[index];
842 
843  return result;
844 }
845 
846 template <>
847 inline int16_t MMALIB_UTIL_iLUT<int16_t>(int16_t inVal, const void *pLutValues){
848  const int16_t *iLUT = (const int16_t*)pLutValues;
849  uint16_t mask = 0x00ff;
850 
851  int16_t result;
852  uint8_t index = (int16_t) ((uint16_t)inVal & mask);
853  result = iLUT[index];
854 
855  return result;
856 }
857 
858 template <>
859 inline uint16_t MMALIB_UTIL_iLUT<uint16_t>(uint16_t inVal, const void *pLutValues){
860  const uint16_t *iLUT = (const uint16_t*)pLutValues;
861  uint16_t mask = 0x00ff;
862 
863  uint16_t result;
864  uint8_t index = inVal & mask;
865  result = iLUT[index];
866 
867  return result;
868 }
869 
870 #endif // __cplusplus
871 
872 
873 // these may use some of the definitions above
874 #include "c7120/MMALIB_utility.h"
875 
876 #endif // headerfile
File to hold buffer parameter related info for MMALIB.
File to hold common structure, enums, macros and functions for MMALIB.
uint64_t end_count
static void MMALIB_UTIL_mult(int64_t *ph, int64_t *pl, int64_t a, int64_t b)
uint64_t overhead
uint64_t beg_count
double MMALIB_D64
Double precision floating point.
Definition: MMALIB_types.h:148