MATHLIB User Guide
MATHLIB_utility.h
Go to the documentation of this file.
1 #ifndef COMMON_MATHLIB_UTILITY_H_
2 #define COMMON_MATHLIB_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 "MATHLIB_bufParams.h"
52 #include "MATHLIB_types.h"
53 
54 #include "c71/MATHLIB_utility.h"
55 #if MATHLIB_DEBUGPRINT >= 1
56 #include "c71/MATHLIB_debug.h"
57 #endif
58 
59 #include "c7120/MATHLIB_utility.h"
60 
61 /*******************************************************************************
62  *
63  * EXTERNAL VARIABLES
64  *
65  ******************************************************************************/
66 #ifdef __cplusplus
67 extern "C" {
68 #endif /* __cplusplus */
69 extern uint64_t beg_count; /* Begin cycle count for profiling */
70 extern uint64_t end_count; /* End cycle count for profiling */
71 extern uint64_t overhead; /* Cycle profiling overhead */
72 #ifdef __cplusplus
73 }
74 #endif /* __cplusplus */
75 
76 /*******************************************************************************
77  *
78  * Inline functions
79  *
80  ******************************************************************************/
81 
82 /*******************************************************************************
83  *
84  * Arithmetic with 128-bit signed integers
85  *
86  ******************************************************************************/
87 static inline void MATHLIB_UTIL_mult(int64_t *ph, int64_t *pl, int64_t a, int64_t b);
88 
89 static inline void MATHLIB_UTIL_mult(int64_t *ph , // result
90  int64_t *pl ,
91  int64_t a , // left operand
92  int64_t b // right operand
93  ){
94  //sum += A[k + m*K] * B[n + k*N];
95  *pl = a * b ;
96 
97  // sign extend the product
98  *ph = ((((uint64_t)*pl) & 0x8000000000000000ULL) != 0ULL)?(int64_t)0xffffffffffffffffULL:(int64_t)0ULL ;
99 }
100 
101 
102 #ifdef __cplusplus
103 
104 /*******************************************************************************
105 *
106 * Definition and arithmetic for MATHLIB_int128_t class
107 *
108 ******************************************************************************/
109 
110 // Define a 128-bit integer class to allow natural-c implementations of MATHLIB
111 // 32-bit input/output functions to be templated. The class is implemented in
112 // a header file for easy sharing. All member functions, including constructors
113 // are declared inline for two reasons: (1) performance and (2) necessary for
114 // implementing the class in a multiple-inclusion header file.
115 
116 class MATHLIB_int128_t
117 {
118 public:
119  int64_t hi;
120  int64_t lo;
121  MATHLIB_int128_t(int64_t h, int64_t l); // constructor for both high and low specified
122  MATHLIB_int128_t(int64_t l); // constructor for just low specified (sign extends to high)
123  MATHLIB_int128_t(); // constructor for neither field specified
124  MATHLIB_int128_t operator+ (const MATHLIB_int128_t&) const; // operator +
125  MATHLIB_int128_t operator>> (const int8_t&) const; // operator >>
126 };
127 
128 // define constructor
129 inline MATHLIB_int128_t::MATHLIB_int128_t(int64_t h, int64_t l)
130 {
131  hi = h;
132  lo = l;
133 }
134 
135 // define constructor
136 inline MATHLIB_int128_t::MATHLIB_int128_t(int64_t l)
137 {
138  // sign extend l
139  hi = (((uint64_t)l & 0x8000000000000000ULL) != 0LL)?(int64_t)0xffffffffffffffffULL:(int64_t)0x0000000000000000ULL;
140  lo = l;
141 }
142 
143 // define constructor
144 inline MATHLIB_int128_t::MATHLIB_int128_t()
145 {
146  hi = 0x0000000000000000LL;
147  lo = 0x0000000000000000LL;
148 }
149 
150 static inline void MATHLIB_UTIL_shiftRight128(
151  uint64_t *rh , // result
152  uint64_t *rl ,
153  uint64_t ah , // operand
154  uint64_t al ,
155  int32_t sh , // shift amount
156  int32_t s ) // signed
157 {
158  uint64_t h ;
159  uint64_t l ;
160  int32_t i;
161 
162  h = ah ;
163  l = al ;
164  for(i = 0 ; i < sh ; i++ ) {
165  l = __shift_right(l, (uint32_t)1) | __shift_left(h, (uint32_t)63) ;
166  h = __shift_right(h, (uint32_t)1) | ((s!=0)?(h&0x8000000000000000ULL):0ULL) ;
167  }
168 
169  *rh = h ;
170  *rl = l ;
171 }
172 
173 static inline void MATHLIB_UTIL_Add128(
174  uint64_t *rh , // result
175  uint64_t *rl ,
176  uint64_t ah , // left operand
177  uint64_t al ,
178  uint64_t bh , // right operand
179  uint64_t bl )
180 {
181  // break up the operands into 4 32b chunks packed into 64b uints
182  uint64_t all ;
183  uint64_t alh ;
184  uint64_t ahl ;
185  uint64_t ahh ;
186  uint64_t bll ;
187  uint64_t blh ;
188  uint64_t bhl ;
189  uint64_t bhh ;
190  uint64_t s0 ;
191  uint64_t s1 ;
192  uint64_t s2 ;
193  uint64_t s3 ;
194  uint64_t sh ;
195  uint64_t sl ;
196 
197  all = __shift_right(al, (uint32_t) 0) & 0x0ffffffffULL ;
198  alh = __shift_right(al, (uint32_t)32) & 0x0ffffffffULL ;
199  ahl = __shift_right(ah, (uint32_t) 0) & 0x0ffffffffULL ;
200  ahh = __shift_right(ah, (uint32_t)32) & 0x0ffffffffULL ;
201 
202  bll = __shift_right(bl, (uint32_t) 0) & 0x0ffffffffULL ;
203  blh = __shift_right(bl, (uint32_t)32) & 0x0ffffffffULL ;
204  bhl = __shift_right(bh, (uint32_t) 0) & 0x0ffffffffULL ;
205  bhh = __shift_right(bh, (uint32_t)32) & 0x0ffffffffULL ;
206 
207  // the adds
208  s0 = all + bll ;
209  s1 = alh + blh + __shift_right(s0, (uint32_t)32) ;
210  s2 = ahl + bhl + __shift_right(s1, (uint32_t)32) ;
211  s3 = ahh + bhh + __shift_right(s2, (uint32_t)32) ;
212 
213  // pack the results
214  sl = __shift_left(s1, (uint32_t)32) | (s0 & 0x0ffffffffULL) ;
215  sh = __shift_left(s3, (uint32_t)32) | (s2 & 0x0ffffffffULL) ;
216 
217  *rl = sl ;
218  *rh = sh ;
219 }
220 
221 // define overloaded + (plus) operator
222 inline MATHLIB_int128_t MATHLIB_int128_t::operator+ (const MATHLIB_int128_t& b) const
223 {
224  MATHLIB_int128_t result;
225 
226  MATHLIB_UTIL_Add128((uint64_t *)&(result.hi), (uint64_t *)&(result.lo), this->hi, this->lo, b.hi, b.lo);
227 
228  return result;
229 }
230 
231 // define overloaded >> (bit shift right) operator
232 inline MATHLIB_int128_t MATHLIB_int128_t::operator>> (const int8_t& shift) const
233 {
234  MATHLIB_int128_t result;
235 
236  MATHLIB_UTIL_shiftRight128((uint64_t *)&result.hi, (uint64_t *)&result.lo, this->hi, this->lo, (int32_t)shift, 1);
237  return result;
238 }
239 
240 /*******************************************************************************
241  *
242  * We need special utility to do negation because range of values is from
243  * -2^(bit-width-1) to 2^(bit-width-1)-1. For example, with int16_t, the
244  * range is from -32768 to 32767 - that is, -0x8000 to 0x7FFF. Now, if we want
245  * to evaluate negation of -32768 and we try simply -(-32768) and store the
246  * result in int16_t, we would get -32768 itself. Instead, we want to get 32767.
247  *
248  ******************************************************************************/
249 
250 static inline int16_t MATHLIB_UTIL_negate(int16_t a)
251 {
252  int16_t result;
253 
254  result = (a == -32768) ? 32767 : -a;
255  return result;
256 }
257 
258 static inline int32_t MATHLIB_UTIL_negate(int32_t a)
259 {
260  int32_t result;
261 
262  result = (a == -2147483648) ? 2147483647 : -a;
263  return result;
264 }
265 
266 /*******************************************************************************
267  *
268  * Inline multiply with higher bit-width output type
269  *
270  ******************************************************************************/
271 
272 static inline int32_t MATHLIB_UTIL_mult(int8_t a, int8_t b)
273 {
274  return (int16_t)a * (int16_t)b;
275 }
276 
277 static inline int32_t MATHLIB_UTIL_mult(uint8_t a, int8_t b)
278 {
279  return (int16_t)a * (int16_t)b;
280 }
281 
282 
283 static inline int64_t MATHLIB_UTIL_mult(int16_t a, int16_t b)
284 {
285  return (int32_t)a * (int32_t)b;
286 }
287 
288 static inline int64_t MATHLIB_UTIL_mult(uint16_t a, int16_t b)
289 {
290  return (int32_t)a * (int32_t)b;
291 }
292 
293 static inline MATHLIB_int128_t MATHLIB_UTIL_mult(int32_t a, int32_t b)
294 {
295  MATHLIB_int128_t result(0,0);
296 
297  result.lo = (int64_t)a * (int64_t)b ;
298  // sign extend the product
299  result.hi = (((uint64_t)result.lo & 0x8000000000000000ULL) != 0LL)?(int64_t)0xffffffffffffffffULL:(int64_t)0ULL ;
300 
301  return result;
302 }
303 
304 /*******************************************************************************
305  *
306  * Inline saturate with ReLU operation
307  *
308  ******************************************************************************/
309 
310 static inline void MATHLIB_UTIL_saturate_relu(int32_t x, int8_t *y)
311 {
312  if (x > 0x7F) {
313  *y = 0x7F;
314  } else if (x < 0) {
315  *y = 0;
316  } else {
317  *y = (int8_t)x;
318  }
319 
320  return;
321 }
322 
323 static inline void MATHLIB_UTIL_saturate_relu(int32_t x, uint8_t *y)
324 {
325  if (x > 0xFF) {
326  *y = 0xFF;
327  } else if (x < 0) {
328  *y = 0;
329  } else {
330  *y = (uint8_t)x;
331  }
332 
333  return;
334 }
335 
336 static inline void MATHLIB_UTIL_saturate_relu(uint32_t x, uint8_t *y)
337 {
338  if (x > 0xFF) {
339  *y = 0xFF;
340  } else {
341  *y = (uint8_t)x;
342  }
343 
344  return;
345 }
346 
347 static inline void MATHLIB_UTIL_saturate_relu(int64_t x, int16_t *y)
348 {
349  if (x > 0x7FFF) {
350  *y = 0x7FFF;
351  } else if (x < 0x0000) {
352  *y = 0x0000;
353  } else {
354  *y = (int16_t)x;
355  }
356 
357  return;
358 }
359 
360 static inline void MATHLIB_UTIL_saturate_relu(int64_t x, uint16_t *y)
361 {
362  if (x > 0xFFFF) {
363  *y = 0xFFFF;
364  } else if (x < 0x0000) {
365  *y = 0x0000;
366  } else {
367  *y = (uint16_t)x;
368  }
369 
370  return;
371 }
372 
373 static inline void MATHLIB_UTIL_saturate_relu(uint64_t x, uint16_t *y)
374 {
375  if (x > 0xFFFF) {
376  *y = 0xFFFF;
377  } else {
378  *y = (uint16_t)x;
379  }
380 
381  return;
382 }
383 
384 /*******************************************************************************
385  *
386  * Inline shift, round and ReLU operation
387  *
388  ******************************************************************************/
389 
390 template <typename dataType, typename returnType>
391 static inline returnType MATHLIB_UTIL_shiftRoundAndReLU(dataType inVal, uint8_t shift){
392  returnType result;
393 
394  if(shift == 0){
395  // remove the rounding, which doesn't make sense with no shift but causes C code problems
396  MATHLIB_UTIL_saturate_relu(inVal, &result);
397  } else {
398  // round and shift
399  // Method requires right shift of signed integers be an arithmetic shift, but right
400  // shift >> on signed integer types is implementation dependent on whether the shift is
401  // arithmetic or logical. There's no simple way in C to specify the shift type as arithmetic.
402  // Instead, we use the __shift_right intrinsic, which is defined to be arithmetic shift.
403  dataType temp;
404  temp = __shift_right(inVal, (shift - 1)) + 1;
405  temp = __shift_right(temp, 1);
406  MATHLIB_UTIL_saturate_relu(temp, &result);
407  }
408 
409  return result;
410 }
411 
412 template int8_t MATHLIB_UTIL_shiftRoundAndReLU<int32_t, int8_t> (int32_t inVal, uint8_t shift);
413 template int16_t MATHLIB_UTIL_shiftRoundAndReLU<int64_t, int16_t> (int64_t inVal, uint8_t shift);
414 // added for unsigned C matrix values inside MMA
415 //template uint8_t MATHLIB_UTIL_shiftRoundAndReLU<uint32_t, uint8_t> (uint32_t inVal, uint8_t shift);
416 //template uint16_t MATHLIB_UTIL_shiftRoundAndReLU<uint64_t, uint16_t> (uint64_t inVal, uint8_t shift);
417 
418 template <>
419 inline uint8_t MATHLIB_UTIL_shiftRoundAndReLU<int32_t, uint8_t>(int32_t inVal, uint8_t shift){
420  uint8_t result;
421 
422  if(shift == 0){
423  // remove the rounding, which doesn't make sense with no shift but causes C code problems
424  MATHLIB_UTIL_saturate_relu(inVal, &result);
425  } else {
426  // round and shift
427  // Method requires right shift of signed integers be an arithmetic shift, but right
428  // shift >> on signed integer types is implementation dependent on whether the shift is
429  // arithmetic or logical. There's no simple way in C to specify the shift type as arithmetic.
430  // Instead, we use the __shift_right intrinsic, which is defined to be arithmetic shift.
431  int32_t temp;
432  temp = __shift_right( inVal, (shift - 1) ) + 1;
433  temp = __shift_right(temp, 1);
434  MATHLIB_UTIL_saturate_relu(temp, &result);
435 
436  }
437 
438  return result;
439 }
440 
441 template <>
442 inline uint8_t MATHLIB_UTIL_shiftRoundAndReLU<uint32_t, uint8_t>(uint32_t inVal, uint8_t shift){
443  uint8_t result;
444 
445  if(shift == 0){
446  // remove the rounding, which doesn't make sense with no shift but causes C code problems
447  MATHLIB_UTIL_saturate_relu(inVal, &result);
448  } else {
449  uint32_t temp;
450  //Subtracting two unsigned values of the same size will result in an unsigned value.
451  //If the first operand is less than the second the result will be arithmetically in correct.
452  //But if the size of the unsigned types is less than that of an unsigned int, C/C++ will promote the types to
453  //signed int before subtracting resulting in an correct result. In either case,
454  //there is no indication of an error.
455  uint32_t shift32_t = (uint32_t) shift;
456  temp = (inVal >> (shift32_t - (uint32_t)1) ) + 1;
457  temp = temp >> 1;
458  MATHLIB_UTIL_saturate_relu(temp, &result);
459  }
460 
461  return result;
462 }
463 
464 template <>
465 inline uint16_t MATHLIB_UTIL_shiftRoundAndReLU<int64_t, uint16_t>(int64_t inVal, uint8_t shift){
466  uint16_t result;
467 
468  if(shift == 0){
469  // remove the rounding, which doesn't make sense with no shift but causes C code problems
470  MATHLIB_UTIL_saturate_relu(inVal, &result);
471  } else {
472  // round and shift
473  // Method requires right shift of signed integers be an arithmetic shift, but right
474  // shift >> on signed integer types is implementation dependent on whether the shift is
475  // arithmetic or logical. There's no simple way in C to specify the shift type as arithmetic.
476  // Instead, we use the __shift_right intrinsic, which is defined to be arithmetic shift.
477  int64_t temp;
478  temp = __shift_right( inVal, (shift - 1) ) + 1;
479  temp = __shift_right(temp, 1);
480  MATHLIB_UTIL_saturate_relu(temp, &result);
481  }
482 
483  return result;
484 }
485 
486 template <>
487 inline uint16_t MATHLIB_UTIL_shiftRoundAndReLU<uint64_t, uint16_t>(uint64_t inVal, uint8_t shift){
488  uint16_t result;
489 
490  if(shift == 0){
491  // remove the rounding, which doesn't make sense with no shift but causes C code problems
492  MATHLIB_UTIL_saturate_relu(inVal, &result);
493  } else {
494  uint64_t temp;
495  uint32_t shift32_t = (uint32_t) shift;
496  temp = (inVal >> (shift32_t - (uint32_t)1) ) + 1;
497  temp = (temp >> 1);
498  MATHLIB_UTIL_saturate_relu(temp, &result);
499  }
500 
501  return result;
502 }
503 
504 
505 /*******************************************************************************
506  *
507  * Inline saturate operation
508  *
509  ******************************************************************************/
510 
511 static inline int8_t MATHLIB_UTIL_saturate(int32_t x)
512 {
513  int8_t retVal;
514  if (x > 0x7F) {
515  retVal = 0x7F;
516  } else if (x < -0x80) {
517  retVal = -0x80;
518  } else {
519  retVal = (int8_t)x;
520  }
521  return retVal;
522 }
523 
524 static inline uint8_t MATHLIB_UTIL_saturate(uint32_t x)
525 {
526  uint8_t retVal;
527  if (x > 0xFF) {
528  retVal = 0xFF;
529  } else {
530  retVal = (uint8_t)x;
531  }
532  return retVal;
533 }
534 
535 static inline int16_t MATHLIB_UTIL_saturate(int64_t x)
536 {
537  int16_t retVal;
538  if (x > 0x7FFF) {
539  retVal = 0x7FFF;
540  } else if (x < -0x8000) {
541  retVal = -0x8000;
542  } else {
543  retVal = (int16_t)x;
544  }
545  return retVal;
546 }
547 
548 static inline uint16_t MATHLIB_UTIL_saturate(uint64_t x)
549 {
550  uint16_t retVal;
551  if (x > 0xFFFF) {
552  retVal = 0xFFFF;
553  } else {
554  retVal = (uint16_t)x;
555  }
556  return retVal;
557 }
558 
559 static inline int32_t MATHLIB_UTIL_saturate(int64_t xh, int64_t xl)
560 {
561  int32_t retVal;
562  //printf("%s: xh = %" PRIx64 ", xl = %" PRIx64 "\n", __FUNCTION__, xh, xl);
563  // if negative
564  if(((uint64_t)xh & 0x8000000000000000ULL) != 0LL){
565  if( ((~(uint64_t)xh & 0xFFFFFFFFFFFFFFFFULL) != 0LL) || ((~(uint64_t)xl & 0xFFFFFFFF80000000ULL) != 0LL)){
566  retVal = ((int32_t)0x80000000U);
567  } else {
568  retVal = (int32_t)xl;
569  }
570  } else if (((uint64_t)xl & 0xFFFFFFFF80000000ULL) != 0LL){
571  //(xl > 0x000000007FFFFFFFLL){ // positive and saturated
572  retVal = ((int32_t)0x7FFFFFFFU);
573  } else {
574  retVal = (int32_t)xl;
575  }
576  return retVal;
577 }
578 
579 static inline int32_t MATHLIB_UTIL_saturate(MATHLIB_int128_t x)
580 {
581  return MATHLIB_UTIL_saturate(x.hi, x.lo);
582 }
583 
584 /*******************************************************************************
585  *
586  * Inline shift and round operation
587  *
588  ******************************************************************************/
589 
590 template <typename dataType, typename returnType>
591 inline returnType MATHLIB_UTIL_shiftAndRound(dataType inVal, uint8_t shift){
592  returnType result;
593 
594  if(shift == 0){
595  // remove the rounding, which doesn't make sense with no shift but causes C code problems
596  result = MATHLIB_UTIL_saturate(inVal);
597  } else {
598  // round and shift
599  dataType temp;
600  temp = (__shift_right(inVal, (shift - 1)) + 1);
601  temp = __shift_right(temp , 1);
602  result = MATHLIB_UTIL_saturate(temp);
603  }
604 
605  return result;
606 }
607 
608 template int8_t MATHLIB_UTIL_shiftAndRound<int32_t, int8_t> (int32_t inVal, uint8_t shift);
609 template int16_t MATHLIB_UTIL_shiftAndRound<int64_t, int16_t> (int64_t inVal, uint8_t shift);
610 
611 
612 template <>
613 inline uint8_t MATHLIB_UTIL_shiftAndRound(uint32_t inVal, uint8_t shift){
614  uint8_t result;
615 
616  if(shift == 0){
617  // remove the rounding, which doesn't make sense with no shift but causes C code problems
618  result = MATHLIB_UTIL_saturate(inVal);
619  } else {
620  // round and shift
621  uint32_t temp;
622  uint32_t shift32_t = (uint32_t) shift;
623  temp = (inVal >> (shift32_t - (uint32_t)1) ) + 1;
624  temp = (temp >> 1);
625  result = MATHLIB_UTIL_saturate(temp);
626  }
627 
628  return result;
629 }
630 
631 template <>
632 inline uint16_t MATHLIB_UTIL_shiftAndRound(uint64_t inVal, uint8_t shift){
633  uint16_t result;
634 
635  if(shift == 0){
636  // remove the rounding, which doesn't make sense with no shift but causes C code problems
637  result = MATHLIB_UTIL_saturate(inVal);
638  } else {
639  // round and shift
640  uint64_t temp;
641  uint32_t shift32_t = (uint32_t) shift;
642  temp = (inVal >> (shift32_t - (uint32_t)1) ) + 1;
643  temp = (temp >> 1);
644  result = MATHLIB_UTIL_saturate(temp);
645  }
646 
647  return result;
648 }
649 
650 // MISRA-C prohibits using >> on signed integers because it is implementation dependent on whether
651 // that shift is arithmetic or logical. However, for MATHLIB_int128_t, this code implements the shift in software
652 // and ensures that it is arithmetic. To avoid the MISRA-C violation, we use the function version of the shift
653 // rather than the >> operator.
654 template <>
655 inline int32_t MATHLIB_UTIL_shiftAndRound<MATHLIB_int128_t, int32_t>(MATHLIB_int128_t inVal, uint8_t shift){
656  int32_t result;
657 
658  if(shift == 0){
659  // remove the rounding, which doesn't make sense with no shift but causes C code problems
660  result = MATHLIB_UTIL_saturate(inVal);
661  } else {
662  // round and shift
663  //result = MATHLIB_UTIL_saturate(((inVal >> ((uint8_t)(shift - 1))) + 1) >> 1);
664  MATHLIB_int128_t temp;
665  // temp = inVal >> (shift - 1)
666  MATHLIB_UTIL_shiftRight128((uint64_t *)&temp.hi, (uint64_t *)&temp.lo, inVal.hi, inVal.lo, (int32_t)(shift - 1), 1);
667  temp = temp + 1;
668  // temp = temp >> 1
669  MATHLIB_UTIL_shiftRight128((uint64_t *)&temp.hi, (uint64_t *)&temp.lo, temp.hi, temp.lo, 1, 1);
670  result = MATHLIB_UTIL_saturate(temp);
671  }
672 
673  return result;
674 }
675 
676 
677 /*******************************************************************************
678  *
679  * Convert a double-precision floating point number to 16-bit integer
680  *
681  ******************************************************************************/
682 
683 template <typename returnType>
684 static inline returnType MATHLIB_UTIL_typeConv_i64f_oxX(MATHLIB_D64 x)
685 {
686  int64_t xLocal, maxValue;
687  returnType returnValue;
688 
689  /* Set maxValue to the maximumum possible value for the returnType */
690 
691  // original code
692  // maxValue = (1 << (sizeof(returnType)*8-2)) - 1;
693  // maxValue += (1 << (sizeof(returnType)*8-2));
694  maxValue = ((int64_t)( (uint32_t)1 << ((uint32_t)(sizeof(returnType)*8-2)))) - 1;
695  maxValue += (int64_t)( (uint32_t)1 << ((uint32_t)(sizeof(returnType)*8-2)));
696 
697  xLocal = (int64_t)floor(0.5 + x); /* Explicit rounding to integer */
698  if (xLocal >= maxValue) {
699  returnValue = (returnType)maxValue;
700  } else if (xLocal <= -maxValue-1) {
701  returnValue = (returnType)(-maxValue-1);
702  } else {
703  returnValue = (returnType)xLocal;
704  }
705  return returnValue;
706 }
707 
708 template int16_t MATHLIB_UTIL_typeConv_i64f_oxX<int16_t>(MATHLIB_D64 x);
709 template int32_t MATHLIB_UTIL_typeConv_i64f_oxX<int32_t>(MATHLIB_D64 x);
710 
711 /*******************************************************************************
712  *
713  * Evaluate cos function, and apply appropriate scale factor
714  *
715  ******************************************************************************/
716 template <typename returnType>
717 static returnType MATHLIB_UTIL_cos_i64f_oxX(MATHLIB_D64 x,
718  MATHLIB_D64 scaleFactor)
719 {
720  return MATHLIB_UTIL_typeConv_i64f_oxX<returnType>(scaleFactor*cos(x));
721 }
722 
723 template int16_t MATHLIB_UTIL_cos_i64f_oxX<int16_t>(MATHLIB_D64 x, MATHLIB_D64 scaleFactor);
724 template int32_t MATHLIB_UTIL_cos_i64f_oxX<int32_t>(MATHLIB_D64 x, MATHLIB_D64 scaleFactor);
725 /*******************************************************************************
726  *
727  * Evaluate sin function, and apply appropriate scale factor
728  *
729  ******************************************************************************/
730 template <typename returnType>
731 static inline returnType MATHLIB_UTIL_sin_i64f_oxX(MATHLIB_D64 x,
732  MATHLIB_D64 scaleFactor)
733 {
734  return MATHLIB_UTIL_typeConv_i64f_oxX<returnType>(scaleFactor*sin(x));
735 }
736 
737 template int16_t MATHLIB_UTIL_sin_i64f_oxX<int16_t>(MATHLIB_D64 x, MATHLIB_D64 scaleFactor);
738 template int32_t MATHLIB_UTIL_sin_i64f_oxX<int32_t>(MATHLIB_D64 x, MATHLIB_D64 scaleFactor);
739 
740 #endif
741 
742 #endif
uint64_t overhead
double MATHLIB_D64
Double precision floating point.
uint64_t beg_count
uint64_t end_count
File to hold common structure, enums, macros and functions for MATHLIB.
static void MATHLIB_UTIL_mult(int64_t *ph, int64_t *pl, int64_t a, int64_t b)