omega_h
Reliable mesh adaptation
Omega_h_int128.hpp
1 #ifndef OMEGA_H_INT128_HPP
2 #define OMEGA_H_INT128_HPP
3 
4 #include <cstdint>
5 #include <iosfwd>
6 #include <sstream>
7 
8 #include <Omega_h_macros.h>
9 
10 namespace Omega_h {
11 
12 struct Int128 {
13  std::int64_t high;
14  std::uint64_t low;
15  inline Int128() = default;
16  OMEGA_H_INLINE Int128(std::int64_t h, std::uint64_t l);
17  OMEGA_H_INLINE Int128(std::int64_t value);
18  inline Int128(Int128 const& rhs) = default;
19  inline Int128& operator=(const Int128&) = default;
20  double to_double(double unit) const;
21  void print(std::ostream& o) const;
22  static OMEGA_H_INLINE Int128 from_double(double value, double unit);
23  std::string to_string() {
24  std::ostringstream oss;
25  oss << "h: " << high << " l: " << low;
26  return oss.str();
27  }
28 };
29 
30 /*
31  We code our own int128 because we target GPUs and similar
32  systems where such a type is not guaranteed to exist.
33  TODO: wrap built-in types when they are available
34 */
35 
36 OMEGA_H_INLINE Int128::Int128(std::int64_t h, std::uint64_t l)
37  : high(h), low(l) {}
38 
39 OMEGA_H_INLINE Int128::Int128(std::int64_t value)
40  : Int128(std::int64_t(-1) * (value < 0), std::uint64_t(value)) {}
41 
42 OMEGA_H_INLINE Int128 Int128::from_double(double value, double unit) {
43  double normalized = value / unit;
44  return Int128(std::int64_t(normalized));
45 }
46 
47 /* we moved the actual operators out here to take
48  * their arguments by value, the CUDA compiler
49  * wouldn't match them otherwise when operating on
50  * two volatile Int128 variables.
51  */
52 
53 OMEGA_H_INLINE Int128 operator+(Int128 lhs, Int128 rhs) {
54  Int128 sum;
55  sum.high = lhs.high + rhs.high;
56  sum.low = lhs.low + rhs.low;
57  // check for overflow of low 64 bits, add carry to high
58  sum.high += (sum.low < lhs.low);
59  return sum;
60 }
61 
62 OMEGA_H_INLINE Int128 operator-(Int128 lhs, Int128 rhs) {
63  Int128 difference;
64  difference.high = lhs.high - rhs.high;
65  difference.low = lhs.low - rhs.low;
66  // check for underflow of low 64 bits, subtract carry from high
67  difference.high -= (difference.low > lhs.low);
68  return difference;
69 }
70 
71 OMEGA_H_INLINE Int128 operator-(Int128 x) { return Int128(0) - x; }
72 
73 OMEGA_H_INLINE Int128 operator>>(Int128 x, int expo) {
74  Int128 shifted;
75  shifted.low = (x.low >> expo) | (std::uint64_t(x.high) << (64 - expo));
76  shifted.high = x.high >> expo;
77  return shifted;
78 }
79 
80 OMEGA_H_INLINE bool operator==(Int128 lhs, Int128 rhs) {
81  return lhs.high == rhs.high && lhs.low == rhs.low;
82 }
83 
84 OMEGA_H_INLINE bool operator<(Int128 lhs, Int128 rhs) {
85  if (lhs.high != rhs.high) return lhs.high < rhs.high;
86  return lhs.low < rhs.low;
87 }
88 
89 } // namespace Omega_h
90 
91 #endif
Definition: amr_mpi_test.cpp:6
Definition: Omega_h_int128.hpp:12