MMALIB User Guide
MMALIB_int128_t.h
Go to the documentation of this file.
1 #ifndef COMMON_MMALIB_INT128_T_H_
2 #define COMMON_MMALIB_INT128_T_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 #ifdef __cplusplus
52 
53 /*******************************************************************************
54 *
55 * Definition and arithmetic for MMALIB_int128_t class
56 *
57 ******************************************************************************/
58 
59 // Define a 128-bit integer class to allow natural-c implementations of MMALIB
60 // 32-bit input/output functions to be templated. The class is implemented in
61 // a header file for easy sharing. All member functions, including constructors
62 // are declared inline for two reasons: (1) performance and (2) necessary for
63 // implementing the class in a multiple-inclusion header file.
64 
65 class MMALIB_int128_t
66 {
67 public:
68  int64_t hi;
69  int64_t lo;
70  MMALIB_int128_t(int64_t h, int64_t l); // constructor for both high and low specified
71  MMALIB_int128_t(int64_t l); // constructor for just low specified (sign extends to high)
72  MMALIB_int128_t(); // constructor for neither field specified
73  MMALIB_int128_t operator+ (const MMALIB_int128_t&) const; // operator +
74  MMALIB_int128_t operator>> (const int8_t&) const; // operator >>
75 };
76 
77 // define constructor
78 inline MMALIB_int128_t::MMALIB_int128_t(int64_t h, int64_t l)
79 {
80  hi = h;
81  lo = l;
82 }
83 
84 // define constructor
85 inline MMALIB_int128_t::MMALIB_int128_t(int64_t l)
86 {
87  // sign extend l
88  hi = (((uint64_t)l & 0x8000000000000000ULL) != 0LL)?(int64_t)0xffffffffffffffffULL:(int64_t)0x0000000000000000ULL;
89  lo = l;
90 }
91 
92 // define constructor
93 inline MMALIB_int128_t::MMALIB_int128_t()
94 {
95  hi = 0x0000000000000000LL;
96  lo = 0x0000000000000000LL;
97 }
98 
99 static inline void MMALIB_UTIL_shiftRight128(
100  uint64_t *rh , // result
101  uint64_t *rl ,
102  uint64_t ah , // operand
103  uint64_t al ,
104  int32_t sh , // shift amount
105  int32_t s ) // signed
106 {
107  uint64_t h ;
108  uint64_t l ;
109  int32_t i;
110 
111  h = ah ;
112  l = al ;
113  for(i = 0 ; i < sh ; i++ ) {
114  l = (uint64_t) __shift_right(l, (uint32_t)1) | (uint64_t) __shift_left(h, (uint32_t)63) ;
115  h = (uint64_t) __shift_right(h, (uint32_t)1) | ((s!=0)?(h&0x8000000000000000ULL):0ULL) ;
116  }
117 
118  *rh = h ;
119  *rl = l ;
120 }
121 
122 static inline void MMALIB_UTIL_Add128(
123  uint64_t *rh , // result
124  uint64_t *rl ,
125  uint64_t ah , // left operand
126  uint64_t al ,
127  uint64_t bh , // right operand
128  uint64_t bl )
129 {
130  // break up the operands into 4 32b chunks packed into 64b uints
131  uint64_t all ;
132  uint64_t alh ;
133  uint64_t ahl ;
134  uint64_t ahh ;
135  uint64_t bll ;
136  uint64_t blh ;
137  uint64_t bhl ;
138  uint64_t bhh ;
139  uint64_t s0 ;
140  uint64_t s1 ;
141  uint64_t s2 ;
142  uint64_t s3 ;
143  uint64_t sh ;
144  uint64_t sl ;
145 
146  all = (uint64_t) __shift_right(al, (uint32_t) 0) & 0x0ffffffffULL ;
147  alh = (uint64_t) __shift_right(al, (uint32_t)32) & 0x0ffffffffULL ;
148  ahl = (uint64_t) __shift_right(ah, (uint32_t) 0) & 0x0ffffffffULL ;
149  ahh = (uint64_t) __shift_right(ah, (uint32_t)32) & 0x0ffffffffULL ;
150 
151  bll = (uint64_t) __shift_right(bl, (uint32_t) 0) & 0x0ffffffffULL ;
152  blh = (uint64_t) __shift_right(bl, (uint32_t)32) & 0x0ffffffffULL ;
153  bhl = (uint64_t) __shift_right(bh, (uint32_t) 0) & 0x0ffffffffULL ;
154  bhh = (uint64_t) __shift_right(bh, (uint32_t)32) & 0x0ffffffffULL ;
155 
156  // the adds
157  s0 = all + bll ;
158  s1 = alh + blh + __shift_right(s0, (uint32_t)32) ;
159  s2 = ahl + bhl + __shift_right(s1, (uint32_t)32) ;
160  s3 = ahh + bhh + __shift_right(s2, (uint32_t)32) ;
161 
162  // pack the results
163  sl = (uint64_t) __shift_left(s1, (uint32_t)32) | (s0 & 0x0ffffffffULL) ;
164  sh = (uint64_t) __shift_left(s3, (uint32_t)32) | (s2 & 0x0ffffffffULL) ;
165 
166  *rl = sl ;
167  *rh = sh ;
168 }
169 
170 // define overloaded + (plus) operator
171 inline MMALIB_int128_t MMALIB_int128_t::operator+ (const MMALIB_int128_t& b) const
172 {
173  MMALIB_int128_t result;
174 
175  MMALIB_UTIL_Add128((uint64_t *)&(result.hi), (uint64_t *)&(result.lo), this->hi, this->lo, b.hi, b.lo);
176 
177  return result;
178 }
179 
180 // define overloaded >> (bit shift right) operator
181 inline MMALIB_int128_t MMALIB_int128_t::operator>> (const int8_t& shift) const
182 {
183  MMALIB_int128_t result;
184 
185  MMALIB_UTIL_shiftRight128((uint64_t *)&result.hi, (uint64_t *)&result.lo, this->hi, this->lo, (int32_t)shift, 1);
186  return result;
187 }
188 
189 #endif // cplusplus
190 
191 #endif // header