BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdldfp_uint128.h
Go to the documentation of this file.
1/// @file bdldfp_uint128.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdldfp_uint128.h -*-C++-*-
8#ifndef INCLUDED_BDLDFP_UINT128
9#define INCLUDED_BDLDFP_UINT128
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdldfp_uint128 bdldfp_uint128
15/// @brief Provide a representation of a 128-bit `int` for bitwise operations.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdldfp
19/// @{
20/// @addtogroup bdldfp_uint128
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdldfp_uint128-purpose"> Purpose</a>
25/// * <a href="#bdldfp_uint128-classes"> Classes </a>
26/// * <a href="#bdldfp_uint128-description"> Description </a>
27/// * <a href="#bdldfp_uint128-usage"> Usage </a>
28/// * <a href="#bdldfp_uint128-example-1-representing-a-128-bit-pattern-for-ipv6"> Example 1: Representing a 128 bit pattern for IPv6 </a>
29/// * <a href="#bdldfp_uint128-example-2-checking-a-128-bit-ipv6-network-mask"> Example 2: Checking a 128-bit IPv6 Network Mask </a>
30///
31/// # Purpose {#bdldfp_uint128-purpose}
32/// Provide a representation of a 128-bit `int` for bitwise operations.
33///
34/// # Classes {#bdldfp_uint128-classes}
35///
36/// - bdldfp::Uint128: A representation of a 128-bit unsigned integer
37///
38/// @see bsl::bitset
39///
40/// # Description {#bdldfp_uint128-description}
41/// This component provides a value-semantic type,
42/// `bdldfp::Uint128`, that is used to represent a 128-bit unsigned integer
43/// having host-native byte order. This component also provides a set of useful
44/// bitwise manipulation operators for this type.
45///
46/// ## Usage {#bdldfp_uint128-usage}
47///
48///
49/// This section illustrates intended use of this component.
50///
51/// ### Example 1: Representing a 128 bit pattern for IPv6 {#bdldfp_uint128-example-1-representing-a-128-bit-pattern-for-ipv6}
52///
53///
54/// Starting in 1996, the world's TCP/IP infrastructure started the move to a
55/// 128-bit addressing scheme, IPv6. IPv4 had a useful quality in that it could
56/// be represented by a single 32-bit machine word for internal routing
57/// purposes. With IPv6, the need arises to manipulate 128-bit values
58/// representing IPv6 addresses for similar routing purposes.
59///
60/// Suppose we need to write a function that needs to take 128-bit addresses
61/// indicating downstream routers in our network.
62///
63/// First, we forward declare the "addRouter" function that takes an IPv6
64/// address indicating a router, and an IPv6 network address (a partial IP
65/// address, with trailing 0's) that the router covers:
66/// @code
67/// void addRouter(bdldfp::Uint128 router, bdldfp::Uint128 network);
68/// @endcode
69/// Now we create a function that loads a set of networks and routers:
70/// @code
71/// void setupNetwork()
72/// {
73/// bdldfp::Uint128 network;
74/// network.setHigh(0x4242000042420000L);
75/// network.setLow(0x0);
76///
77/// bdldfp::Uint128 router(0x000012345678ABCDL, 0xDCBA000087654321L);
78/// @endcode
79/// Finally we invoke addRouter, on our network and router.
80/// @code
81/// addRouter(router, network);
82/// }
83/// @endcode
84/// Notice that Uint128 values can be created from high/low pairs.
85///
86/// ### Example 2: Checking a 128-bit IPv6 Network Mask {#bdldfp_uint128-example-2-checking-a-128-bit-ipv6-network-mask}
87///
88///
89/// In networks, checking a network mask is a fundamental operation. A 128-bit
90/// mask can be used to indicate if an address is in a network, and where in the
91/// network an address is.
92///
93/// Suppose we need to decide if an address is within a network, and extract the
94/// sub-address from the IPv6 address.
95///
96/// First, we define a function that checks a passed IPv6 address and indicates
97/// the sub-address, and network membership:
98/// @code
99/// bool checkNetworkAddress(bdldfp::Uint128 *subAddress,
100/// bdldfp::Uint128 network,
101/// int maskLength
102/// bdldfp::Uint128 address)
103/// {
104/// @endcode
105/// Then, we compute a net mask for the specified `maskLength`:
106/// @code
107/// bdldfp::Uint128 netMask;
108/// for (int i = 0; i < maskLength; ++i) {
109/// netMask |= 1;
110/// if (i != maskLength - 1) {
111/// netMask <<= 1;
112/// }
113/// }
114/// @endcode
115/// Notice that it is possible to shift `Uint128` values as if they were a
116/// native type. Meaning that it is possible to shift a `Uint128` by 64-bits,
117/// or more, in single operation, because `Uint128` functions just like a
118/// built-in 128-bit integer type would.
119///
120/// Next, we calculate whether the passed address is within the network:
121/// @code
122/// bool inNetwork = network == (address & ~netMask);
123/// @endcode
124/// Then, we compute the subAddress, if the address is in the network:
125/// @code
126/// if (inNetwork) {
127/// *subAddress = address & netMask;
128/// }
129/// @endcode
130/// Now, we return whether the address is in the network, and close the
131/// function:
132/// @code
133/// return inNetwork
134/// }
135/// @endcode
136/// Finally, we call `checkNetworkAddress` on a test network and address:
137/// @code
138/// bdldfp::Uint128 subAddress;
139/// assert(checkNetworkAddress(
140/// &subAddress,
141/// bdldfp::Uint128(0xABCD424200001234L,0x22FF12345678L),
142/// bdldfp::Uint128(0xABCD424200001234L,0x22FF00000000L),
143/// 32); // The network has a 32-bit internal address mask.
144/// assert(subAddress == 0x12345678L);
145/// @endcode
146/// Notice that primitive 64-bit words can be promoted to 128-bit addresses.
147/// @}
148/** @} */
149/** @} */
150
151/** @addtogroup bdl
152 * @{
153 */
154/** @addtogroup bdldfp
155 * @{
156 */
157/** @addtogroup bdldfp_uint128
158 * @{
159 */
160
161#include <bsls_types.h>
162#include <bsls_platform.h>
163
164
165namespace bdldfp {
166
167 // =============
168 // class Uint128
169 // =============
170
171/// This value-semantic type represents a 128-bit integer, with host machine
172/// byte order.
173///
174/// See @ref bdldfp_uint128
175class Uint128 {
176
177 private:
178 // DATA
179
180 // The high and low values are laid out in an architecture dependent
181 // fashion to facilitate a native-endian layout. This class is expected to
182 // have standard layout.
183
184 #ifdef BSLS_PLATFORM_IS_BIG_ENDIAN
185 bsls::Types::Uint64 d_high;
187 #elif defined(BSLS_PLATFORM_IS_LITTLE_ENDIAN)
189 bsls::Types::Uint64 d_high;
190 #else
191 #error Only big or little endian is supported.
192 #endif
193
194 public:
195 // CREATORS
196
197 /// Create an Uint128 object having the value `0`
198 Uint128();
199
200 /// Create an `Uint128` object having the 128-bit integer bit pattern of
201 /// the value of the specified `initialValue`.
202 Uint128(bsls::Types::Uint64 initialValue); // IMPLICIT
203
204 /// Create an `Uint128` object having the 128-bit pattern specified by
205 /// `initialHigh..initialLow`
206 Uint128(bsls::Types::Uint64 initialHigh, bsls::Types::Uint64 initialLow);
207
208 ~Uint128() = default;
209 // Destroy this object.
210
211 // MANIPULATORS
212 Uint128& operator=(const Uint128& rhs) = default;
213 // Assign to this object the value of the specified 'rhs' object, and
214 // return a reference providing modifiable access to this object.
215
216 /// Set the value of this object to the value of a the bitwise or
217 /// between this 128 bit integer and the specified `rhs` value, and
218 /// return a reference providing mofifiable access to this object.
219 Uint128& operator|=(const Uint128& rhs);
220
221 /// Set the value of this object to the value of a the bitwise and
222 /// between this 128 bit integer and the specified `rhs` value, and
223 /// return a reference providing mofifiable access to this object.
224 Uint128& operator&=(const Uint128& rhs);
225
226 /// Set the value of this object to the value of a the bitwise xor
227 /// between this 128 bit integer and the specified `rhs` value, and
228 /// return a reference providing mofifiable access to this object.
229 Uint128& operator^=(const Uint128& rhs);
230
231 /// Set the value of this object to the value of a bitwise right shift
232 /// of this 128 bit integer shifted by the specified `rhs` value, and
233 /// return a reference providing mofifiable access to this object. The
234 /// behavior is undefined unless `0 <= rhs < 128`.
235 Uint128& operator>>=(int rhs);
236
237 /// Set the value of this object to the value of a bitwise left shift of
238 /// this 128 bit integer shifted by the specified `rhs` value, and
239 /// return a reference providing mofifiable access to this object. The
240 /// behavior is undefined unless `0 <= rhs < 128`.
241 Uint128& operator<<=(int rhs);
242
243 /// Set the high order bits of this integer to the specified `value`.
244 void setHigh(bsls::Types::Uint64 value);
245
246 /// Set the low order bits of this integer to the specified `value`.
247 void setLow(bsls::Types::Uint64 value);
248
249 // ACCESSORS
250
251 /// Return the high order bits of this integer.
253
254 /// Return the low order bits of this integer.
255 bsls::Types::Uint64 low() const;
256};
257
258// FREE OPERATORS
259
260/// Return `true` if the specified `lhs` and the specified `rhs` objects
261/// have the same value, and `false` otherwise. Two `Uint128` objects have
262/// the same value if both of their `low` and `high` attributes are the
263/// same.
264bool operator==(const Uint128& lhs, const Uint128& rhs);
265
266/// Return `true` if the specified `lhs` and the specified `rhs` objects do
267/// not have the same value, and `false` otherwise. Two `Uint128` objects
268/// do not have the same value if either of their `low` and `high`
269/// attributes are not the same.
270bool operator!=(const Uint128& lhs, const Uint128& rhs);
271
272/// Return an Uint128 object having the value of a the bitwise or between
273/// the specified `lhs` and the specified `rhs` value.
275
276/// Return an Uint128 object having the value of a the bitwise and between
277/// the specified `lhs` and the specified `rhs` value.
279
280/// Return an Uint128 object having the value of a the bitwise xor between
281/// the specified `lhs` and the specified `rhs` value.
283
284/// Return an `Uint128` value equal to the value of a bitwise left shift of
285/// the specified `lhs` 128-bit integer shifted by the specified `rhs`
286/// value. The behavior is undefined unless `0 <= rhs < 128`.
288
289/// Return an `Uint128` value equal to the value of a bitwise right shift of
290/// the specified `lhs` 128-bit integer shifted by the specified `rhs`
291/// value. The behavior is undefined unless `0 <= rhs < 128`.
293
294/// Return an `Uint128` value equal to the bitwise ones compliment of the
295/// specified `value`.
297
298// ============================================================================
299// INLINE FUNCTION DEFINITIONS
300// ============================================================================
301
302 // -------------
303 // class Uint128
304 // -------------
305
306// CREATORS
307inline
309{
310 d_low = 0;
311 d_high = 0;
312}
313
314inline
316{
317 d_high = 0;
318 d_low = initialValue;
319}
320
321inline
323 bsls::Types::Uint64 initialLow)
324{
325 d_high = initialHigh;
326 d_low = initialLow;
327}
328
329// MANIPULATORS
330inline
332{
333 d_high |= rhs.d_high;
334 d_low |= rhs.d_low;
335
336 return *this;
337}
338
339inline
341{
342 d_high &= rhs.d_high;
343 d_low &= rhs.d_low;
344
345 return *this;
346}
347
348inline
350{
351 d_high ^= rhs.d_high;
352 d_low ^= rhs.d_low;
353
354 return *this;
355}
356
357inline
359{
360 if (rhs == 0) {
361 return *this; // RETURN
362 }
363
364 if (rhs < 64) {
365 d_low >>= rhs;
366 d_low |= d_high << (64 - rhs);
367 d_high >>= rhs;
368 }
369 else {
370 d_low = d_high >> (rhs - 64);
371 d_high = 0;
372 }
373
374 return *this;
375}
376
377inline
379{
380 if (rhs == 0) {
381 return *this; // RETURN
382 }
383
384 if (rhs < 64) {
385 d_high <<= rhs;
386 d_high |= d_low >> (64 - rhs);
387 d_low <<= rhs;
388 }
389 else {
390 d_high = d_low << (rhs - 64);
391 d_low = 0;
392 }
393
394 return *this;
395}
396
397inline
399{
400 d_high = value;
401}
402
403inline
405{
406 d_low = value;
407}
408
409// ACCESSORS
410inline
412{
413 return d_high;
414}
415
416inline
418{
419 return d_low;
420}
421
422
423} // close package namespace
424
425// FREE OPERATORS
426inline
427bool bdldfp::operator==(const bdldfp::Uint128& lhs,
428 const bdldfp::Uint128& rhs)
429{
430 return lhs.high() == rhs.high() && lhs.low() == rhs.low();
431}
432
433inline
434bool bdldfp::operator!=(const bdldfp::Uint128& lhs,
435 const bdldfp::Uint128& rhs)
436{
437 return lhs.high() != rhs.high() || lhs.low() != rhs.low();
438}
439
440inline
442 const bdldfp::Uint128& rhs)
443{
444 return lhs |= rhs;
445}
446
447inline
449 const bdldfp::Uint128& rhs)
450{
451 return lhs &= rhs;
452}
453
454inline
456 const bdldfp::Uint128& rhs )
457{
458 return lhs ^= rhs;
459}
460
461inline
463{
464 return lhs <<= rhs;
465}
466
467inline
469{
470 return lhs >>= rhs;
471}
472
473inline
475{
476 value.setHigh(~value.high());
477 value.setLow( ~value.low());
478
479 return value;
480}
481
482
483#endif
484
485// ----------------------------------------------------------------------------
486// Copyright 2014 Bloomberg Finance L.P.
487//
488// Licensed under the Apache License, Version 2.0 (the "License");
489// you may not use this file except in compliance with the License.
490// You may obtain a copy of the License at
491//
492// http://www.apache.org/licenses/LICENSE-2.0
493//
494// Unless required by applicable law or agreed to in writing, software
495// distributed under the License is distributed on an "AS IS" BASIS,
496// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
497// See the License for the specific language governing permissions and
498// limitations under the License.
499// ----------------------------- END-OF-FILE ----------------------------------
500
501/** @} */
502/** @} */
503/** @} */
Definition bdldfp_uint128.h:175
void setLow(bsls::Types::Uint64 value)
Set the low order bits of this integer to the specified value.
Definition bdldfp_uint128.h:404
Uint128 & operator<<=(int rhs)
Definition bdldfp_uint128.h:378
void setHigh(bsls::Types::Uint64 value)
Set the high order bits of this integer to the specified value.
Definition bdldfp_uint128.h:398
Uint128 & operator|=(const Uint128 &rhs)
Definition bdldfp_uint128.h:331
~Uint128()=default
Uint128()
Create an Uint128 object having the value 0
Definition bdldfp_uint128.h:308
Uint128 & operator^=(const Uint128 &rhs)
Definition bdldfp_uint128.h:349
Uint128 & operator>>=(int rhs)
Definition bdldfp_uint128.h:358
Uint128 & operator=(const Uint128 &rhs)=default
bsls::Types::Uint64 high() const
Return the high order bits of this integer.
Definition bdldfp_uint128.h:411
bsls::Types::Uint64 low() const
Return the low order bits of this integer.
Definition bdldfp_uint128.h:417
Uint128 & operator&=(const Uint128 &rhs)
Definition bdldfp_uint128.h:340
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdldfp_decimal.h:712
bsl::basic_istream< CHARTYPE, TRAITS > & operator>>(bsl::basic_istream< CHARTYPE, TRAITS > &stream, Decimal32 &object)
bsl::basic_ostream< CHARTYPE, TRAITS > & operator<<(bsl::basic_ostream< CHARTYPE, TRAITS > &stream, Decimal32 object)
bool operator!=(Decimal32 lhs, Decimal32 rhs)
Uint128 operator~(Uint128 value)
Uint128 operator|(Uint128 lhs, const Uint128 &rhs)
Uint128 operator^(Uint128 lhs, const Uint128 &rhs)
Uint128 operator&(Uint128 lhs, const Uint128 &rhs)
bool operator==(Decimal32 lhs, Decimal32 rhs)
unsigned long long Uint64
Definition bsls_types.h:137