FFTLIB User Guide
c7504/FFTLIB_utility.h
Go to the documentation of this file.
1 /******************************************************************************/
5 /* Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the
17  * distribution.
18  *
19  * Neither the name of Texas Instruments Incorporated nor the names of
20  * its contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  *
35  ******************************************************************************/
36 
37 #ifndef C7120_FFTLIB_UTILITY_H_
38 #define C7120_FFTLIB_UTILITY_H_ 1
39 
40 /*******************************************************************************
41  *
42  * INCLUDES
43  *
44  ******************************************************************************/
45 #include "../FFTLIB_types.h"
46 
47 
48 
49 /*******************************************************************************
50  *
51  * EXTERNAL VARIABLES
52  *
53  ******************************************************************************/
54 #ifdef __cplusplus
55 extern int64_t FFTLIB_CN_dynamicRangeMin;
56 extern int64_t FFTLIB_CN_dynamicRangeMax;
57 #endif // #ifdef __cplusplus
58 /*******************************************************************************
59  *
60  * Inline functions
61  *
62  ******************************************************************************/
63 
64 /**************************************************************************************
65  * debug print dynamic range update
66  **************************************************************************************/
67 
68 #ifdef __cplusplus
69 static inline void FFTLIB_CN_printUpdate(int32_t value, const char *string){
70  FFTLIB_DEBUGPRINTFN(2, "(%s) int32_t value is %d. min is %ld, max is %ld\n", string, value, FFTLIB_CN_dynamicRangeMin, FFTLIB_CN_dynamicRangeMax);
71 }
72 
73 static inline void FFTLIB_CN_printUpdate(int64_t value, const char *string){
74  FFTLIB_DEBUGPRINTFN(2, "(%s) int64_t value is %ld. min is %ld, max is %ld\n", string, value, FFTLIB_CN_dynamicRangeMin, FFTLIB_CN_dynamicRangeMax);
75 }
76 
77 static inline void FFTLIB_CN_printUpdate(uint32_t value, const char *string){
78  FFTLIB_DEBUGPRINTFN(2, "(%s) uint32_t value is %#010x. min is %#018lx, max is %#018lx\n", string, value, (uint64_t)FFTLIB_CN_dynamicRangeMin, (uint64_t)FFTLIB_CN_dynamicRangeMax);
79 }
80 
81 static inline void FFTLIB_CN_printUpdate(uint64_t value, const char *string){
82  FFTLIB_DEBUGPRINTFN(2, "(%s) uint64_t value is %#018lx. min is %#018lx, max is %#018lx\n", string, value, (uint64_t)FFTLIB_CN_dynamicRangeMin, (uint64_t)FFTLIB_CN_dynamicRangeMax);
83 }
84 #endif // __cplusplus
85 
86 
87 /**************************************************************************************
88  * update dynamic range
89  **************************************************************************************/
90 #ifdef __cplusplus
91 template <typename accumulateType>
92 static inline void FFTLIB_CN_updateDynamicRange(FFTLIB_enableDynamicRange_type enableDynamicRange, accumulateType value)
93 {
94  FFTLIB_CN_printUpdate(value, "before dynamic range update");
95  if( enableDynamicRange == FFTLIB_DYNAMIC_RANGE_DISABLE ){
96  // do nothing
97  } else {
98  if (((int64_t) value) > FFTLIB_CN_dynamicRangeMax) {
99  FFTLIB_CN_dynamicRangeMax = (int64_t) value;
100  }
101  if (((int64_t) value) < FFTLIB_CN_dynamicRangeMin) {
102  FFTLIB_CN_dynamicRangeMin = (int64_t) value;
103  }
104  }
105 
106  FFTLIB_CN_printUpdate(value, "after dynamic range update ");
107  return;
108 }
109 
110 template void FFTLIB_CN_updateDynamicRange(FFTLIB_enableDynamicRange_type enableDynamicRange, int32_t value);
111 template void FFTLIB_CN_updateDynamicRange(FFTLIB_enableDynamicRange_type enableDynamicRange, int64_t value);
112 template void FFTLIB_CN_updateDynamicRange(FFTLIB_enableDynamicRange_type enableDynamicRange, uint32_t value);
113 
114 // when accumulator uses an unsigned 64-bit data type
115 template <>
116 inline void FFTLIB_CN_updateDynamicRange(FFTLIB_enableDynamicRange_type enableDynamicRange, uint64_t value)
117 {
118  FFTLIB_CN_printUpdate(value, "before dynamic range update");
119  if( enableDynamicRange == FFTLIB_DYNAMIC_RANGE_DISABLE ){
120  // do nothing
121  } else {
122  int64_t signValue = value & 0x8000000000000000;
123  int64_t magValue = value & 0x7FFFFFFFFFFFFFFF;
124 
125  // logic for the max
126  int64_t signMax = FFTLIB_CN_dynamicRangeMax & 0x8000000000000000;
127  int64_t magMax = FFTLIB_CN_dynamicRangeMax & 0x7FFFFFFFFFFFFFFF;
128  if(signValue == signMax){
129  // a regular comparison on the magnitudes should work
130  if (magValue > magMax) {
131  //FFTLIB_CN_dynamicRangeMax = (int64_t) value;
132  FFTLIB_CN_dynamicRangeMax = signValue | magValue;
133  }
134  } else if (signValue < signMax) {
135  // value is positive (leading zero) and max is negative
136  //FFTLIB_CN_dynamicRangeMax = (int64_t) value;
137  FFTLIB_CN_dynamicRangeMax = signValue | magValue;
138  } else {
139  // max is positive and value is negative, so don't change the max
140  }
141 
142  // logic for the min
143  int64_t signMin = FFTLIB_CN_dynamicRangeMin & 0x8000000000000000;
144  int64_t magMin = FFTLIB_CN_dynamicRangeMin & 0x7FFFFFFFFFFFFFFF;
145  if(signValue == signMin){
146  // a regular comparison on the magnitudes should work
147  if (magValue < magMin) {
148  FFTLIB_CN_dynamicRangeMin = signValue | magValue;
149  }
150  } else if (signValue > signMin) {
151  // value is negative (leading one) and min is positive
152  FFTLIB_CN_dynamicRangeMin = signValue | magValue;
153  } else {
154  // value is positive and min is negative, so don't change the max
155  }
156 
157  }
158 
159  FFTLIB_CN_printUpdate(value, "after dynamic range update ");
160 
161  return;
162 }
163 #endif //#ifdef __cplusplus
164 
165 /*******************************************************************************
166  *
167  * Inline saturate with PSAT operation
168  *
169  ******************************************************************************/
170 #ifdef __cplusplus
171 
172 static inline void FFTLIB_UTIL_psat(int32_t x, int8_t minVal, int8_t maxVal, int8_t *y)
173 {
174  if (x < minVal) {
175  *y = minVal;
176  } else if (x > maxVal) {
177  *y = maxVal;
178  } else {
179  *y = (int8_t)x;
180  }
181 
182  return;
183 }
184 
185 static inline void FFTLIB_UTIL_psat(int32_t x, uint8_t minVal, uint8_t maxVal, uint8_t *y)
186 {
187  if (x < minVal) {
188  *y = minVal;
189  } else if (x > maxVal) {
190  *y = maxVal;
191  } else {
192  *y = (uint8_t)x;
193  }
194 
195  return;
196 }
197 
198 static inline void FFTLIB_UTIL_psat(uint32_t x, uint8_t minVal, uint8_t maxVal, uint8_t *y)
199 {
200  if (x < minVal) {
201  *y = minVal;
202  } else if (x > maxVal) {
203  *y = maxVal;
204  } else {
205  *y = (uint8_t)x;
206  }
207 
208  return;
209 }
210 
211 static inline void FFTLIB_UTIL_psat(int64_t x, int16_t minVal, int16_t maxVal, int16_t *y)
212 {
213  if (x < minVal) {
214  *y = minVal;
215  } else if (x > maxVal) {
216  *y = maxVal;
217  } else {
218  *y = (int16_t)x;
219  }
220 
221  return;
222 }
223 
224 static inline void FFTLIB_UTIL_psat(int64_t x, uint16_t minVal, uint16_t maxVal, uint16_t *y)
225 {
226  if (x < minVal) {
227  *y = minVal;
228  } else if (x > maxVal) {
229  *y = maxVal;
230  } else {
231  *y = (uint16_t)x;
232  }
233 
234  return;
235 }
236 
237 static inline void FFTLIB_UTIL_psat(uint64_t x, uint16_t minVal, uint16_t maxVal, uint16_t *y)
238 {
239  if (x < minVal) {
240  *y = minVal;
241  } else if (x > maxVal) {
242  *y = maxVal;
243  } else {
244  *y = (uint16_t)x;
245  }
246 
247  return;
248 }
249 
250 
251 /*******************************************************************************
252  *
253  * Inline shift, round and PSAT operation
254  *
255  ******************************************************************************/
256 
257 template <typename dataType, typename returnType>
258 static inline returnType FFTLIB_UTIL_shiftRoundAndPSAT(dataType inVal, uint8_t shift, returnType minVal, returnType maxVal){
259  returnType result;
260 
261  if(shift == 0){
262  // remove the rounding, which doesn't make sense with no shift but causes C code problems
263  FFTLIB_UTIL_psat(inVal, minVal, maxVal, &result);
264  } else {
265  // round and shift
266  // Method requires right shift of signed integers be an arithmetic shift, but right
267  // shift >> on signed integer types is implementation dependent on whether the shift is
268  // arithmetic or logical. There's no simple way in C to specify the shift type as arithmetic.
269  // Instead, we use the __shift_right intrinsic, which is defined to be arithmetic shift.
270  dataType temp;
271  temp = __shift_right(inVal, (shift - 1)) + 1;
272  temp = __shift_right(temp, 1);
273  FFTLIB_UTIL_psat(temp, minVal, maxVal, &result);
274  }
275 
276  return result;
277 }
278 
279 template int8_t FFTLIB_UTIL_shiftRoundAndPSAT<int32_t, int8_t> (int32_t inVal, uint8_t shift, int8_t minVal, int8_t maxVal);
280 template int16_t FFTLIB_UTIL_shiftRoundAndPSAT<int64_t, int16_t> (int64_t inVal, uint8_t shift, int16_t minVal, int16_t maxVal);
281 
282 template <>
283 inline uint8_t FFTLIB_UTIL_shiftRoundAndPSAT<int32_t, uint8_t>(int32_t inVal, uint8_t shift, uint8_t minVal, uint8_t maxVal){
284  uint8_t result;
285 
286  if(shift == 0){
287  // remove the rounding, which doesn't make sense with no shift but causes C code problems
288  FFTLIB_UTIL_psat(inVal, minVal, maxVal, &result);
289  } else {
290  // round and shift
291  // Method requires right shift of signed integers be an arithmetic shift, but right
292  // shift >> on signed integer types is implementation dependent on whether the shift is
293  // arithmetic or logical. There's no simple way in C to specify the shift type as arithmetic.
294  // Instead, we use the __shift_right intrinsic, which is defined to be arithmetic shift.
295  int32_t temp;
296  temp = __shift_right( inVal, (shift - 1) ) + 1;
297  temp = __shift_right(temp, 1);
298  FFTLIB_UTIL_psat(temp, minVal, maxVal, &result);
299 
300  }
301 
302  return result;
303 }
304 
305 template <>
306 inline uint8_t FFTLIB_UTIL_shiftRoundAndPSAT<uint32_t, uint8_t>(uint32_t inVal, uint8_t shift, uint8_t minVal, uint8_t maxVal){
307  uint8_t result;
308 
309  if(shift == 0){
310  // remove the rounding, which doesn't make sense with no shift but causes C code problems
311  FFTLIB_UTIL_psat(inVal, minVal, maxVal, &result);
312  } else {
313  uint32_t temp;
314  //Subtracting two unsigned values of the same size will result in an unsigned value.
315  //If the first operand is less than the second the result will be arithmetically in correct.
316  //But if the size of the unsigned types is less than that of an unsigned int, C/C++ will promote the types to
317  //signed int before subtracting resulting in an correct result. In either case,
318  //there is no indication of an error.
319  uint32_t shift32_t = (uint32_t) shift;
320  temp = (inVal >> (shift32_t - (uint32_t)1) ) + 1;
321  temp = temp >> 1;
322  FFTLIB_UTIL_psat(temp, minVal, maxVal, &result);
323  }
324 
325  return result;
326 }
327 
328 template <>
329 inline uint16_t FFTLIB_UTIL_shiftRoundAndPSAT<int64_t, uint16_t>(int64_t inVal, uint8_t shift, uint16_t minVal, uint16_t maxVal){
330  uint16_t result;
331 
332  if(shift == 0){
333  // remove the rounding, which doesn't make sense with no shift but causes C code problems
334  FFTLIB_UTIL_psat(inVal, minVal, maxVal, &result);
335  } else {
336  // round and shift
337  // Method requires right shift of signed integers be an arithmetic shift, but right
338  // shift >> on signed integer types is implementation dependent on whether the shift is
339  // arithmetic or logical. There's no simple way in C to specify the shift type as arithmetic.
340  // Instead, we use the __shift_right intrinsic, which is defined to be arithmetic shift.
341  int64_t temp;
342  temp = __shift_right( inVal, (shift - 1) ) + 1;
343  temp = __shift_right(temp, 1);
344  FFTLIB_UTIL_psat(temp, minVal, maxVal, &result);
345  }
346 
347  return result;
348 }
349 
350 template <>
351 inline uint16_t FFTLIB_UTIL_shiftRoundAndPSAT<uint64_t, uint16_t>(uint64_t inVal, uint8_t shift, uint16_t minVal, uint16_t maxVal){
352  uint16_t result;
353 
354  if(shift == 0){
355  // remove the rounding, which doesn't make sense with no shift but causes C code problems
356  FFTLIB_UTIL_psat(inVal, minVal, maxVal, &result);
357  } else {
358  uint64_t temp;
359  uint32_t shift32_t = (uint32_t) shift;
360  temp = (inVal >> (shift32_t - (uint32_t)1) ) + 1;
361  temp = (temp >> 1);
362  FFTLIB_UTIL_psat(temp, minVal, maxVal, &result);
363  }
364 
365  return result;
366 }
367 
368 /*******************************************************************************
369  *
370  * Inline scale, shift, saturate with PSAT operation
371  *
372  ******************************************************************************/
373 
374 
375 static inline void FFTLIB_UTIL_scaleShiftPsat(uint8_t scale, uint8_t shift, int32_t x, int8_t minVal, int8_t maxVal, int8_t *y)
376 {
377  int64_t xVal = x;
378  int64_t scaledValue = xVal*scale;
379 
380  if (shift > 0) {
381  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
382  xVal = __shift_right(xVal, 1);
383  } else {
384  xVal = scaledValue;
385  }
386 
387  if (xVal < minVal) {
388  *y = minVal;
389  } else if (xVal > maxVal) {
390  *y = maxVal;
391  } else {
392  *y = (int8_t)xVal;
393  }
394 
395  return;
396 }
397 
398 static inline void FFTLIB_UTIL_scaleShiftPsat(uint8_t scale, uint8_t shift, int32_t x, uint8_t minVal, uint8_t maxVal, uint8_t *y)
399 {
400  int64_t xVal = x;
401  int64_t scaledValue = xVal*scale;
402 
403  if (shift > 0) {
404  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
405  xVal = __shift_right(xVal, 1);
406  } else {
407  xVal = scaledValue;
408  }
409 
410  if (xVal < minVal) {
411  *y = minVal;
412  } else if (xVal > maxVal) {
413  *y = maxVal;
414  } else {
415  *y = (uint8_t)xVal;
416  }
417 
418  return;
419 }
420 
421 static inline void FFTLIB_UTIL_scaleShiftPsat(uint8_t scale, uint8_t shift, uint32_t x, uint8_t minVal, uint8_t maxVal, uint8_t *y)
422 {
423  uint64_t xVal = x;
424  uint64_t scaledValue = xVal*scale;
425 
426  uint32_t shift32_t = (uint32_t) shift;
427 
428  if (shift32_t > 0) {
429  xVal = (scaledValue >> (shift32_t - (uint32_t)1) ) + 1;
430  xVal = (xVal >> 1);
431  } else {
432  xVal = scaledValue;
433  }
434 
435  if (xVal < minVal) {
436  *y = minVal;
437  } else if (xVal > maxVal) {
438  *y = maxVal;
439  } else {
440  *y = (uint8_t)xVal;
441  }
442 
443  return;
444 }
445 
446 static inline void FFTLIB_UTIL_scaleShiftPsat(uint8_t scale, uint8_t shift, int64_t x, int16_t minVal, int16_t maxVal, int16_t *y)
447 {
448  int64_t xVal = x;
449  int64_t scaledValue = xVal*scale;
450 
451  if (shift > 0) {
452  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
453  xVal = __shift_right(xVal, 1);
454  } else {
455  xVal = scaledValue;
456  }
457 
458  if (xVal < minVal) {
459  *y = minVal;
460  } else if (xVal > maxVal) {
461  *y = maxVal;
462  } else {
463  *y = (int16_t)xVal;
464  }
465 
466  return;
467 }
468 
469 static inline void FFTLIB_UTIL_scaleShiftPsat(uint8_t scale, uint8_t shift, int64_t x, uint16_t minVal, uint16_t maxVal, uint16_t *y)
470 {
471  int64_t xVal = x;
472  int64_t scaledValue = xVal*scale;
473 
474  if (shift > 0) {
475  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
476  xVal = __shift_right(xVal, 1);
477  } else {
478  xVal = scaledValue;
479  }
480 
481  if (xVal < minVal) {
482  *y = minVal;
483  } else if (xVal > maxVal) {
484  *y = maxVal;
485  } else {
486  *y = (uint16_t)xVal;
487  }
488 
489  return;
490 }
491 
492 static inline void FFTLIB_UTIL_scaleShiftPsat(uint8_t scale, uint8_t shift, uint64_t x, uint16_t minVal, uint16_t maxVal, uint16_t *y)
493 {
494  uint64_t xVal = x;
495  uint64_t scaledValue = xVal*scale;
496 
497  uint32_t shift32_t = (uint32_t) shift;
498 
499  if (shift32_t > 0) {
500  xVal = (scaledValue >> (shift32_t - (uint32_t)1) ) + 1;
501  xVal = (xVal >> 1);
502  } else {
503  xVal = scaledValue;
504  }
505 
506  if (xVal < minVal) {
507  *y = minVal;
508  } else if (xVal > maxVal) {
509  *y = maxVal;
510  } else {
511  *y = (uint16_t)xVal;
512  }
513 
514  return;
515 }
516 
517 // scale int8_t
518 static inline void FFTLIB_UTIL_scaleShiftPsat(int8_t scale, uint8_t shift, int32_t x, int8_t minVal, int8_t maxVal, int8_t *y)
519 {
520  int64_t xVal = x;
521  int64_t scaledValue = xVal*scale;
522 
523  if (shift > 0) {
524  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
525  xVal = __shift_right(xVal, 1);
526  } else {
527  xVal = scaledValue;
528  }
529 
530  if (xVal < minVal) {
531  *y = minVal;
532  } else if (xVal > maxVal) {
533  *y = maxVal;
534  } else {
535  *y = (int8_t)xVal;
536  }
537 
538  return;
539 }
540 
541 static inline void FFTLIB_UTIL_scaleShiftPsat(int8_t scale, uint8_t shift, int32_t x, uint8_t minVal, uint8_t maxVal, uint8_t *y)
542 {
543  int64_t xVal = x;
544  int64_t scaledValue = xVal*scale;
545 
546  if (shift > 0) {
547  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
548  xVal = __shift_right(xVal, 1);
549  } else {
550  xVal = scaledValue;
551  }
552 
553  if (xVal < minVal) {
554  *y = minVal;
555  } else if (xVal > maxVal) {
556  *y = maxVal;
557  } else {
558  *y = (uint8_t)xVal;
559  }
560 
561  return;
562 }
563 
564 static inline void FFTLIB_UTIL_scaleShiftPsat(int8_t scale, uint8_t shift, uint32_t x, uint8_t minVal, uint8_t maxVal, uint8_t *y)
565 {
566  int64_t xVal = x;
567  int64_t scaledValue = xVal*scale;
568 
569 // uint32_t shift32_t = (uint32_t) shift;
570 //
571 // if (shift32_t > 0) {
572 // xVal = (scaledValue >> (shift32_t - (uint32_t)1) ) + 1;
573 // xVal = (xVal >> 1);
574 // } else {
575 // xVal = scaledValue;
576 // }
577  int32_t tmp;
578  if (shift > 0) {
579  tmp = __shift_right(scaledValue, (shift - 1)) + 1;
580  tmp = __shift_right(tmp, 1);
581  } else {
582  tmp = scaledValue;
583  }
584 
585  if (tmp < minVal) {
586  *y = minVal;
587  } else if (tmp > maxVal) {
588  *y = maxVal;
589  } else {
590  *y = (uint8_t)tmp;
591  }
592 
593  return;
594 }
595 
596 static inline void FFTLIB_UTIL_scaleShiftPsat(int8_t scale, uint8_t shift, int64_t x, int16_t minVal, int16_t maxVal, int16_t *y)
597 {
598  int64_t xVal = x;
599  int64_t scaledValue = xVal*scale;
600 
601  if (shift > 0) {
602  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
603  xVal = __shift_right(xVal, 1);
604  } else {
605  xVal = scaledValue;
606  }
607 
608  if (xVal < minVal) {
609  *y = minVal;
610  } else if (xVal > maxVal) {
611  *y = maxVal;
612  } else {
613  *y = (int16_t)xVal;
614  }
615 
616  return;
617 }
618 
619 static inline void FFTLIB_UTIL_scaleShiftPsat(int8_t scale, uint8_t shift, int64_t x, uint16_t minVal, uint16_t maxVal, uint16_t *y)
620 {
621  int64_t xVal = x;
622  int64_t scaledValue = xVal*scale;
623 
624  if (shift > 0) {
625  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
626  xVal = __shift_right(xVal, 1);
627  } else {
628  xVal = scaledValue;
629  }
630 
631  if (xVal < minVal) {
632  *y = minVal;
633  } else if (xVal > maxVal) {
634  *y = maxVal;
635  } else {
636  *y = (uint16_t)xVal;
637  }
638 
639  return;
640 }
641 
642 static inline void FFTLIB_UTIL_scaleShiftPsat(int8_t scale, uint8_t shift, uint64_t x, uint16_t minVal, uint16_t maxVal, uint16_t *y)
643 {
644  int64_t xVal = x;
645  int64_t scaledValue = xVal*scale;
646 
647 // uint32_t shift32_t = (uint32_t) shift;
648 //
649 // if (shift32_t > 0) {
650 // xVal = (scaledValue >> (shift32_t - (uint32_t)1) ) + 1;
651 // xVal = (xVal >> 1);
652 // } else {
653 // xVal = scaledValue;
654 // }
655 
656  int32_t tmp;
657  if (shift > 0) {
658  tmp = __shift_right(scaledValue, (shift - 1)) + 1;
659  tmp = __shift_right(tmp, 1);
660  } else {
661  tmp = scaledValue;
662  }
663 
664  if (tmp < minVal) {
665  *y = minVal;
666  } else if (tmp > maxVal) {
667  *y = maxVal;
668  } else {
669  *y = (uint16_t)tmp;
670  }
671 
672  return;
673 }
674 
675 
676 
677 /*******************************************************************************
678  *
679  * Inline scale, shift, round and PSAT operation
680  *
681  ******************************************************************************/
682 
683 template <typename dataType, typename dataTypeS, typename returnType>
684 static inline returnType FFTLIB_UTIL_scaleShiftRoundAndPSAT(dataType inVal, dataTypeS scale, uint8_t shift, returnType minVal, returnType maxVal){
685  returnType result;
686 
687  // round and shift
688  // Method requires right shift of signed integers be an arithmetic shift, but right
689  // shift >> on signed integer types is implementation dependent on whether the shift is
690  // arithmetic or logical. There's no simple way in C to specify the shift type as arithmetic.
691  // Instead, we use the __shift_right intrinsic, which is defined to be arithmetic shift.
692 
693  FFTLIB_UTIL_scaleShiftPsat(scale, shift, inVal, minVal, maxVal, &result);
694 
695  return result;
696 }
697 
698 template int8_t FFTLIB_UTIL_scaleShiftRoundAndPSAT<int32_t, uint8_t, int8_t> (int32_t inVal, uint8_t scale, uint8_t shift, int8_t minVal, int8_t maxVal);
699 template int16_t FFTLIB_UTIL_scaleShiftRoundAndPSAT<int64_t, uint8_t, int16_t> (int64_t inVal, uint8_t scale, uint8_t shift, int16_t minVal, int16_t maxVal);
700 template int8_t FFTLIB_UTIL_scaleShiftRoundAndPSAT<int32_t, int8_t, int8_t> (int32_t inVal, int8_t scale, uint8_t shift, int8_t minVal, int8_t maxVal);
701 template int16_t FFTLIB_UTIL_scaleShiftRoundAndPSAT<int64_t, int8_t, int16_t> (int64_t inVal, int8_t scale, uint8_t shift, int16_t minVal, int16_t maxVal);
702 
703 /*******************************************************************************
704  *
705  * Inline scale, shift saturate with ReLU operation
706  *
707  ******************************************************************************/
708 
709 static inline void FFTLIB_UTIL_scale_shift_saturate_relu(int32_t x, uint8_t scale, uint8_t shift, int8_t *y)
710 {
711  int64_t xVal = x;
712  int64_t scaledValue = xVal*scale;
713 
714 //#if FFTLIB_DEBUGPRINT
715 // printf("FFTLIB_DEBUGPRINT FFTLIB_UTIL_scale_shift_saturate_relu: scaledValue %ll xVal %d scale %d shift %d\n", scaledValue, xVal,scale, shift);
716 //#endif
717  if(shift > 0) {
718  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
719  xVal = __shift_right(xVal, 1);
720  } else {
721  xVal = scaledValue;
722  }
723 
724  if (xVal > 0x7F) {
725  *y = 0x7F;
726  } else if (xVal < 0) {
727  *y = 0;
728  } else {
729  *y = (int8_t)xVal;
730  }
731 
732  return;
733 }
734 
735 static inline void FFTLIB_UTIL_scale_shift_saturate_relu(int32_t x, uint8_t scale, uint8_t shift, uint8_t *y)
736 {
737  int64_t xVal = x;
738  int64_t scaledValue = xVal*scale;
739 //#if FFTLIB_DEBUGPRINT
740 // printf("scaledValue %" PRId64 "\n", scaledValue);
741 // printf("FFTLIB_DEBUGPRINT FFTLIB_UTIL_scale_shift_saturate_relu: xVal %d scale %d shift %d\n", xVal,scale, shift);
742 //#endif
743  if(shift > 0) {
744  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
745  xVal = __shift_right(xVal, 1);
746  } else {
747  xVal = scaledValue;
748  }
749 
750  if (xVal > 0xFF) {
751  *y = 0xFF;
752  } else if (xVal < 0) {
753  *y = 0;
754  } else {
755  *y = (uint8_t)xVal;
756  }
757 
758  return;
759 }
760 
761 static inline void FFTLIB_UTIL_scale_shift_saturate_relu(uint32_t x, uint8_t scale, uint8_t shift, uint8_t *y)
762 {
763  uint64_t xVal = x;
764  uint64_t scaledValue = xVal*scale;
765 
766  uint32_t shift32_t = (uint32_t) shift;
767 
768  if (shift32_t > 0) {
769  xVal = (scaledValue >> (shift32_t - (uint32_t)1) ) + 1;
770  xVal = (xVal >> 1);
771  } else {
772  xVal = scaledValue;
773  }
774 
775  if (xVal > 0xFF) {
776  *y = 0xFF;
777  } else {
778  *y = (uint8_t)xVal;
779  }
780 
781  return;
782 }
783 
784 static inline void FFTLIB_UTIL_scale_shift_saturate_relu(int64_t x, uint8_t scale, uint8_t shift, int16_t *y)
785 {
786  int64_t xVal = x;
787  int64_t scaledValue = xVal*scale;
788 
789  if(shift > 0) {
790  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
791  xVal = __shift_right(xVal, 1);
792  } else {
793  xVal = scaledValue;
794  }
795 
796 
797  if (xVal > 0x7FFF) {
798  *y = 0x7FFF;
799  } else if (xVal < 0x0000) {
800  *y = 0x0000;
801  } else {
802  *y = (int16_t)xVal;
803  }
804 
805  return;
806 }
807 
808 static inline void FFTLIB_UTIL_scale_shift_saturate_relu(int64_t x, uint8_t scale, uint8_t shift, uint16_t *y)
809 {
810  int64_t xVal = x;
811  int64_t scaledValue = xVal*scale;
812 
813  if(shift > 0) {
814  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
815  xVal = __shift_right(xVal, 1);
816  } else {
817  xVal = scaledValue;
818  }
819 
820 
821  if (xVal > 0xFFFF) {
822  *y = 0xFFFF;
823  } else if (xVal < 0x0000) {
824  *y = 0x0000;
825  } else {
826  *y = (uint16_t)xVal;
827  }
828 
829  return;
830 }
831 
832 static inline void FFTLIB_UTIL_scale_shift_saturate_relu(uint64_t x, uint8_t scale, uint8_t shift, uint16_t *y)
833 {
834  uint64_t xVal = x;
835  uint64_t scaledValue = xVal*scale;
836 
837  uint32_t shift32_t = (uint32_t) shift;
838 
839  if (shift32_t > 0) {
840  xVal = (scaledValue >> (shift32_t - (uint32_t)1) ) + 1;
841  xVal = (xVal >> 1);
842  } else {
843  xVal = scaledValue;
844  }
845 
846  if (xVal > 0xFFFF) {
847  *y = 0xFFFF;
848  } else {
849  *y = (uint16_t)xVal;
850  }
851 
852  return;
853 }
854 
855 //int8_t scale
856 static inline void FFTLIB_UTIL_scale_shift_saturate_relu(int32_t x, int8_t scale, uint8_t shift, int8_t *y)
857 {
858  int64_t xVal = x;
859  int64_t scaledValue = xVal*scale;
860 
861 //#if FFTLIB_DEBUGPRINT
862 // printf("FFTLIB_DEBUGPRINT FFTLIB_UTIL_scale_shift_saturate_relu: scaledValue %ll xVal %d scale %d shift %d\n", scaledValue, xVal,scale, shift);
863 //#endif
864  if(shift > 0) {
865  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
866  xVal = __shift_right(xVal, 1);
867  } else {
868  xVal = scaledValue;
869  }
870 
871  if (xVal > 0x7F) {
872  *y = 0x7F;
873  } else if (xVal < 0) {
874  *y = 0;
875  } else {
876  *y = (int8_t)xVal;
877  }
878 
879  return;
880 }
881 
882 static inline void FFTLIB_UTIL_scale_shift_saturate_relu(int32_t x, int8_t scale, uint8_t shift, uint8_t *y)
883 {
884  int64_t xVal = x;
885  int64_t scaledValue = xVal*scale;
886 //#if FFTLIB_DEBUGPRINT
887 // printf("scaledValue %" PRId64 "\n", scaledValue);
888 // printf("FFTLIB_DEBUGPRINT FFTLIB_UTIL_scale_shift_saturate_relu: xVal %d scale %d shift %d\n", xVal,scale, shift);
889 //#endif
890  if(shift > 0) {
891  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
892  xVal = __shift_right(xVal, 1);
893  } else {
894  xVal = scaledValue;
895  }
896 
897  if (xVal > 0xFF) {
898  *y = 0xFF;
899  } else if (xVal < 0) {
900  *y = 0;
901  } else {
902  *y = (uint8_t)xVal;
903  }
904 
905  return;
906 }
907 
908 static inline void FFTLIB_UTIL_scale_shift_saturate_relu(uint32_t x, int8_t scale, uint8_t shift, uint8_t *y)
909 {
910  int64_t xVal = x;
911  int64_t scaledValue = xVal*scale;
912 
913 // uint32_t shift32_t = (uint32_t) shift;
914 //
915 // if (shift32_t > 0) {
916 // xVal = (scaledValue >> (shift32_t - (uint32_t)1) ) + 1;
917 // xVal = (xVal >> 1);
918 // } else {
919 // xVal = scaledValue;
920 // }
921  int32_t tmp;
922  if(shift > 0) {
923  tmp = __shift_right(scaledValue, (shift - 1)) + 1;
924  tmp = __shift_right(tmp, 1);
925  } else {
926  tmp = scaledValue;
927  }
928 
929  if (tmp > 0xFF) {
930  *y = 0xFF;
931  } else {
932  *y = (uint8_t)tmp;
933  }
934 
935  return;
936 }
937 
938 static inline void FFTLIB_UTIL_scale_shift_saturate_relu(int64_t x, int8_t scale, uint8_t shift, int16_t *y)
939 {
940  int64_t xVal = x;
941  int64_t scaledValue = xVal*scale;
942 
943  if(shift > 0) {
944  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
945  xVal = __shift_right(xVal, 1);
946  } else {
947  xVal = scaledValue;
948  }
949 
950 
951  if (xVal > 0x7FFF) {
952  *y = 0x7FFF;
953  } else if (xVal < 0x0000) {
954  *y = 0x0000;
955  } else {
956  *y = (int16_t)xVal;
957  }
958 
959  return;
960 }
961 
962 static inline void FFTLIB_UTIL_scale_shift_saturate_relu(int64_t x, int8_t scale, uint8_t shift, uint16_t *y)
963 {
964  int64_t xVal = x;
965  int64_t scaledValue = xVal*scale;
966 
967  if(shift > 0) {
968  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
969  xVal = __shift_right(xVal, 1);
970  } else {
971  xVal = scaledValue;
972  }
973 
974 
975  if (xVal > 0xFFFF) {
976  *y = 0xFFFF;
977  } else if (xVal < 0x0000) {
978  *y = 0x0000;
979  } else {
980  *y = (uint16_t)xVal;
981  }
982 
983  return;
984 }
985 
986 static inline void FFTLIB_UTIL_scale_shift_saturate_relu(uint64_t x, int8_t scale, uint8_t shift, uint16_t *y)
987 {
988  int64_t xVal = x;
989  int64_t scaledValue = xVal*scale;
990 
991 // uint32_t shift32_t = (uint32_t) shift;
992 //
993 // if (shift32_t > 0) {
994 // xVal = (scaledValue >> (shift32_t - (uint32_t)1) ) + 1;
995 // xVal = (xVal >> 1);
996 // } else {
997 // xVal = scaledValue;
998 // }
999  int32_t tmp;
1000  if(shift > 0) {
1001  tmp = __shift_right(scaledValue, (shift - 1)) + 1;
1002  tmp = __shift_right(tmp, 1);
1003  } else {
1004  tmp = scaledValue;
1005  }
1006 
1007  if (tmp > 0xFFFF) {
1008  *y = 0xFFFF;
1009  } else {
1010  *y = (uint16_t)tmp;
1011  }
1012 
1013  return;
1014 }
1015 
1016 
1017 /*******************************************************************************
1018  *
1019  * Inline scale, shift, round and ReLU operation
1020  *
1021  ******************************************************************************/
1022 
1023 template <typename dataType, typename dataTypeS, typename returnType>
1024 static inline returnType FFTLIB_UTIL_scaleShiftRoundAndReLU(dataType inVal, dataTypeS scale, uint8_t shift){
1025  returnType result;
1026 //#if FFTLIB_DEBUGPRINT
1027 // printf("FFTLIB_DEBUGPRINT C: inVal %d scale %d shift %d\n", inVal,scale, shift);
1028 //#endif
1029  FFTLIB_UTIL_scale_shift_saturate_relu(inVal, scale, shift, &result);
1030 
1031 // if(shift == 0){
1032 // // remove the rounding, which doesn't make sense with no shift but causes C code problems
1033 // FFTLIB_UTIL_saturate_relu(inVal, &result);
1034 // } else {
1035 // // round and shift
1036 // // Method requires right shift of signed integers be an arithmetic shift, but right
1037 // // shift >> on signed integer types is implementation dependent on whether the shift is
1038 // // arithmetic or logical. There's no simple way in C to specify the shift type as arithmetic.
1039 // // Instead, we use the __shift_right intrinsic, which is defined to be arithmetic shift.
1040 // dataType temp;
1041 // temp = __shift_right(inVal, (shift - 1)) + 1;
1042 // temp = __shift_right(temp, 1);
1043 // FFTLIB_UTIL_saturate_relu(temp, &result);
1044 // }
1045 
1046  return result;
1047 }
1048 
1049 template int8_t FFTLIB_UTIL_scaleShiftRoundAndReLU<int32_t, uint8_t, int8_t> (int32_t inVal, uint8_t scale, uint8_t shift);
1050 template int16_t FFTLIB_UTIL_scaleShiftRoundAndReLU<int64_t, uint8_t, int16_t> (int64_t inVal, uint8_t scale, uint8_t shift);
1051 template int8_t FFTLIB_UTIL_scaleShiftRoundAndReLU<int32_t, int8_t, int8_t> (int32_t inVal, int8_t scale, uint8_t shift);
1052 template int16_t FFTLIB_UTIL_scaleShiftRoundAndReLU<int64_t, int8_t, int16_t> (int64_t inVal, int8_t scale, uint8_t shift);
1053 
1054 /*******************************************************************************
1055  *
1056  * Inline scale shift saturate operation
1057  *
1058  ******************************************************************************/
1059 
1060 static inline int8_t FFTLIB_UTIL_scaleShiftSaturate(int32_t x, uint8_t scale, uint8_t shift)
1061 {
1062  int8_t retVal;
1063  int64_t xVal = x;
1064  int64_t scaledValue = xVal*scale;
1065 
1066  if(shift > 0) {
1067  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
1068  xVal = __shift_right(xVal, 1);
1069  } else {
1070  xVal = scaledValue;
1071  }
1072 
1073  if (xVal > 0x7F) {
1074  retVal = 0x7F;
1075  } else if (xVal < -0x80) {
1076  retVal = -0x80;
1077  } else {
1078  retVal = (int8_t)xVal;
1079  }
1080  return retVal;
1081 }
1082 
1083 static inline uint8_t FFTLIB_UTIL_scaleShiftSaturate(uint32_t x, uint8_t scale, uint8_t shift)
1084 {
1085  uint8_t retVal;
1086  uint64_t xVal = x;
1087  uint64_t scaledValue = xVal*scale;
1088 
1089  uint32_t shift32_t = (uint32_t) shift;
1090 
1091  if (shift32_t > 0) {
1092  xVal = (scaledValue >> (shift32_t - (uint32_t)1) ) + 1;
1093  xVal = (xVal >> 1);
1094  } else {
1095  xVal = scaledValue;
1096  }
1097 
1098  if (xVal > 0xFF) {
1099  retVal = 0xFF;
1100  } else {
1101  retVal = (uint8_t)xVal;
1102  }
1103  return retVal;
1104 }
1105 
1106 static inline int16_t FFTLIB_UTIL_scaleShiftSaturate(int64_t x, uint8_t scale, uint8_t shift)
1107 {
1108  int16_t retVal;
1109  int64_t xVal = x;
1110  int64_t scaledValue = xVal*scale;
1111 
1112  if(shift > 0) {
1113  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
1114  xVal = __shift_right(xVal, 1);
1115  } else {
1116  xVal = scaledValue;
1117  }
1118 
1119  if (xVal > 0x7FFF) {
1120  retVal = 0x7FFF;
1121  } else if (xVal < -0x8000) {
1122  retVal = -0x8000;
1123  } else {
1124  retVal = (int16_t)xVal;
1125  }
1126  return retVal;
1127 }
1128 
1129 static inline uint16_t FFTLIB_UTIL_scaleShiftSaturate(uint64_t x, uint8_t scale, uint8_t shift)
1130 {
1131  uint16_t retVal;
1132  uint64_t xVal = x;
1133  uint64_t scaledValue = xVal*scale;
1134 
1135  uint32_t shift32_t = (uint32_t) shift;
1136 
1137  if (shift32_t > 0) {
1138  xVal = (scaledValue >> (shift32_t - (uint32_t)1) ) + 1;
1139  xVal = (xVal >> 1);
1140  } else {
1141  xVal = scaledValue;
1142  }
1143 
1144  if (xVal > 0xFFFF) {
1145  retVal = 0xFFFF;
1146  } else {
1147  retVal = (uint16_t)xVal;
1148  }
1149  return retVal;
1150 }
1151 
1152 /*static inline int32_t FFTLIB_UTIL_scaleShiftSaturate(int64_t xh, int64_t xl)
1153 {
1154  int32_t retVal;
1155  //printf("%s: xh = %" PRIx64 ", xl = %" PRIx64 "\n", __FUNCTION__, xh, xl);
1156  // if negative
1157  if(((uint64_t)xh & 0x8000000000000000ULL) != 0LL){
1158  if( ((~(uint64_t)xh & 0xFFFFFFFFFFFFFFFFULL) != 0LL) || ((~(uint64_t)xl & 0xFFFFFFFF80000000ULL) != 0LL)){
1159  retVal = ((int32_t)0x80000000U);
1160  } else {
1161  retVal = (int32_t)xl;
1162  }
1163  } else if (((uint64_t)xl & 0xFFFFFFFF80000000ULL) != 0LL){
1164  //(xl > 0x000000007FFFFFFFLL){ // positive and saturated
1165  retVal = ((int32_t)0x7FFFFFFFU);
1166  } else {
1167  retVal = (int32_t)xl;
1168  }
1169  return retVal;
1170 }
1171 
1172 static inline int32_t FFTLIB_UTIL_scaleShiftSaturate(FFTLIB_int128_t x)
1173 {
1174  return FFTLIB_UTIL_saturate(x.hi(), x.lo());
1175 }
1176 */
1177 
1178 //int8_t scale
1179 static inline int8_t FFTLIB_UTIL_scaleShiftSaturate(int32_t x, int8_t scale, uint8_t shift)
1180 {
1181  int8_t retVal;
1182  int64_t xVal = x;
1183  int64_t scaledValue = xVal*scale;
1184 
1185  if(shift > 0) {
1186  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
1187  xVal = __shift_right(xVal, 1);
1188  } else {
1189  xVal = scaledValue;
1190  }
1191 
1192  if (xVal > 0x7F) {
1193  retVal = 0x7F;
1194  } else if (xVal < -0x80) {
1195  retVal = -0x80;
1196  } else {
1197  retVal = (int8_t)xVal;
1198  }
1199  return retVal;
1200 }
1201 
1202 static inline uint8_t FFTLIB_UTIL_scaleShiftSaturate(uint32_t x, int8_t scale, uint8_t shift)
1203 {
1204  uint8_t retVal;
1205  int64_t xVal = x;
1206  int64_t scaledValue = xVal*scale;
1207 
1208 // uint32_t shift32_t = (uint32_t) shift;
1209 //
1210 // if (shift32_t > 0) {
1211 // xVal = (scaledValue >> (shift32_t - (uint32_t)1) ) + 1;
1212 // xVal = (xVal >> 1);
1213 // } else {
1214 // xVal = scaledValue;
1215 // }
1216  int32_t tmp;
1217  if(shift > 0) {
1218  tmp = __shift_right(scaledValue, (shift - 1)) + 1;
1219  tmp = __shift_right(tmp, 1);
1220  } else {
1221  tmp = scaledValue;
1222  }
1223 
1224  if (tmp > 0xFF) {
1225  retVal = 0xFF;
1226  } else {
1227  retVal = (uint8_t)tmp;
1228  }
1229  return retVal;
1230 }
1231 
1232 static inline int16_t FFTLIB_UTIL_scaleShiftSaturate(int64_t x, int8_t scale, uint8_t shift)
1233 {
1234  int16_t retVal;
1235  int64_t xVal = x;
1236  int64_t scaledValue = xVal*scale;
1237 
1238  if(shift > 0) {
1239  xVal = __shift_right(scaledValue, (shift - 1)) + 1;
1240  xVal = __shift_right(xVal, 1);
1241  } else {
1242  xVal = scaledValue;
1243  }
1244 
1245  if (xVal > 0x7FFF) {
1246  retVal = 0x7FFF;
1247  } else if (xVal < -0x8000) {
1248  retVal = -0x8000;
1249  } else {
1250  retVal = (int16_t)xVal;
1251  }
1252  return retVal;
1253 }
1254 
1255 static inline uint16_t FFTLIB_UTIL_scaleShiftSaturate(uint64_t x, int8_t scale, uint8_t shift)
1256 {
1257  uint16_t retVal;
1258  int64_t xVal = x;
1259  int64_t scaledValue = xVal*scale;
1260 
1261 // uint32_t shift32_t = (uint32_t) shift;
1262 //
1263 // if (shift32_t > 0) {
1264 // xVal = (scaledValue >> (shift32_t - (uint32_t)1) ) + 1;
1265 // xVal = (xVal >> 1);
1266 // } else {
1267 // xVal = scaledValue;
1268 // }
1269  int32_t tmp;
1270  if(shift > 0) {
1271  tmp = __shift_right(scaledValue, (shift - 1)) + 1;
1272  tmp = __shift_right(tmp, 1);
1273  } else {
1274  tmp = scaledValue;
1275  }
1276 
1277  if (tmp > 0xFFFF) {
1278  retVal = 0xFFFF;
1279  } else {
1280  retVal = (uint16_t)tmp;
1281  }
1282  return retVal;
1283 }
1284 
1285 /*******************************************************************************
1286  *
1287  * Inline shift and round operation
1288  *
1289  ******************************************************************************/
1290 
1291 template <typename dataType, typename dataTypeS, typename returnType>
1292 inline returnType FFTLIB_UTIL_scaleShiftAndRound(dataType inVal, dataTypeS scale, uint8_t shift){
1293  returnType result;
1294 
1295  result = FFTLIB_UTIL_scaleShiftSaturate(inVal, scale, shift);
1296 
1297  return result;
1298 }
1299 
1300 template int8_t FFTLIB_UTIL_scaleShiftAndRound<int32_t, uint8_t, int8_t> (int32_t inVal, uint8_t scale, uint8_t shift);
1301 template int16_t FFTLIB_UTIL_scaleShiftAndRound<int64_t, uint8_t, int16_t> (int64_t inVal, uint8_t scale, uint8_t shift);
1302 template int8_t FFTLIB_UTIL_scaleShiftAndRound<int32_t, int8_t, int8_t> (int32_t inVal, int8_t scale, uint8_t shift);
1303 template int16_t FFTLIB_UTIL_scaleShiftAndRound<int64_t, int8_t, int16_t> (int64_t inVal, int8_t scale, uint8_t shift);
1304 
1305 #endif //#ifdef __cplusplus
1306 /*******************************************************************************
1307  *
1308  * Assembly functions
1309  *
1310  ******************************************************************************/
1311 
1312 uint64_t FFTLIB_UTIL_mma_bist(void);
1313 
1314 
1315 /*******************************************************************************
1316  *
1317  * C++ function prototypes
1318  *
1319  ******************************************************************************/
1320 #ifdef __cplusplus
1321 // functions only implemented in C++. Could potentially develop a wrapper for C
1322 // linkage if necessary
1323 
1324 template <typename accumulateType>
1325 void FFTLIB_CN_initDynamicRange(FFTLIB_initDynamicRange_type initDynamicRange, accumulateType temp);
1326 
1327 #endif //__cplusplus
1328 
1329 
1330 /*******************************************************************************
1331  *
1332  * C function prototypes
1333  *
1334  ******************************************************************************/
1335 
1336 #ifdef __cplusplus
1337 extern "C" {
1338 #endif /* __cplusplus */
1339 
1340 // put C function prototypes here
1341 
1342 #ifdef __cplusplus
1343 }
1344 #endif /* __cplusplus */
1345 
1346 /*******************************************************************************
1347  *
1348  * Test code, removed by #if, left for future use.
1349  *
1350  ******************************************************************************/
1351 #if 0
1352 // int32_t quick tests
1354 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_DISABLE, (int32_t)0x1); // no change, new min & max
1355 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int32_t)0x1); // new min & max
1356 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int32_t)0x2); // new max
1357 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int32_t) -1); // new min
1358 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int32_t)0x7FFFFFFF); // new max, largest positive
1359 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int32_t)0x80000000); // new min, most negative
1360 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int32_t)0x2); // no change
1361 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int32_t) -1); // no change
1362 
1363 // uint32_t quick tests
1365 FFTLIB_DEBUGPRINTFN(2, "uint32_t test%s", "\n");
1366 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_DISABLE, (uint32_t)0x1); // no change, new min & max
1367 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (uint32_t)0x1); // new min & max
1368 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (uint32_t)0x2); // new max
1369 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (uint32_t)0x7FFFFFFF); // new max, half-way point
1370 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (uint32_t)0xFFFFFFFF); // new max, largest value
1371 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (uint32_t)0x0); // new min, minimum value
1372 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (uint32_t)0xbeef); // no change
1373 
1374 // int64_t quick tests
1376 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_DISABLE, (int64_t)0x1); // no change, new min & max
1377 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int64_t)0x1); // new min & max
1378 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int64_t)0x2); // new max
1379 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int64_t) -1); // new min
1380 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int64_t)0x7FFFFFFFFFFFFFFF); // new max, largest positive
1381 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int64_t)0x8000000000000000); // new min, most negative
1382 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int64_t)0x2); // no change
1383 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (int64_t) -1); // no change
1384 
1385 // uint64_t quick tests
1387 FFTLIB_DEBUGPRINTFN(2, "uint64_t test%s", "\n");
1388 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_DISABLE, (uint64_t)0x1); // no change, new min & max
1389 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (uint64_t)0x1); // new min & max
1390 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (uint64_t)0x2); // new max
1391 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (uint64_t)0x7FFFFFFFFFFFFFFF); // new max, largest positive
1392 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (uint64_t)0xFFFFFFFFFFFFFFFF); // new max, largest value
1393 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (uint64_t)0x0); // new min, minimum value
1394 FFTLIB_CN_updateDynamicRange(FFTLIB_DYNAMIC_RANGE_ENABLE, (uint64_t)0xdeadbeefbeefdead); // no change
1395 #endif // #if 0
1396 
1397 #endif /* C7120_FFTLIB_UTILITY_H_ */
#define FFTLIB_DEBUGPRINTFN(N, fmt,...)
Definition: FFTLIB_types.h:107
FFTLIB_enableDynamicRange_type_e
The enumeration of possible dynamic range enable settings.
@ FFTLIB_DYNAMIC_RANGE_DISABLE
Disable dynamic range computation.
@ FFTLIB_DYNAMIC_RANGE_ENABLE
Enable dynamic range computation.
FFTLIB_initDynamicRange_type_e
The enumeration of possible dynamic range reset options.
@ FFTLIB_DYNAMIC_RANGE_INIT
Reset dynamic range min/max at start of computation.
int64_t FFTLIB_CN_dynamicRangeMax
int64_t FFTLIB_CN_dynamicRangeMin
void FFTLIB_CN_initDynamicRange(FFTLIB_initDynamicRange_type initDynamicRange, accumulateType temp)
uint64_t FFTLIB_UTIL_mma_bist(void)