@@ -984,22 +984,22 @@ struct uint
984
984
985
985
using uint256 = uint <256 >;
986
986
987
- inline constexpr bool operator <(const uint256& x, const uint256& y) noexcept
988
- {
989
- auto xp = uint128{x[2 ], x[3 ]};
990
- auto yp = uint128{y[2 ], y[3 ]};
991
- if (xp == yp)
992
- {
993
- xp = uint128{x[0 ], x[1 ]};
994
- yp = uint128{y[0 ], y[1 ]};
995
- }
996
- return xp < yp;
997
- }
998
-
999
987
template <unsigned N>
1000
988
inline constexpr bool operator <(const uint <N>& x, const uint <N>& y) noexcept
1001
989
{
1002
- return subc (x, y).carry ;
990
+ if constexpr (N == 256 )
991
+ {
992
+ auto xp = uint128{x[2 ], x[3 ]};
993
+ auto yp = uint128{y[2 ], y[3 ]};
994
+ if (xp == yp)
995
+ {
996
+ xp = uint128{x[0 ], x[1 ]};
997
+ yp = uint128{y[0 ], y[1 ]};
998
+ }
999
+ return xp < yp;
1000
+ }
1001
+ else
1002
+ return subc (x, y).carry ;
1003
1003
}
1004
1004
1005
1005
template <unsigned N, typename T>
@@ -1092,109 +1092,103 @@ inline constexpr bool slt(const uint<N>& x, const uint<N>& y) noexcept
1092
1092
return ((x_neg ^ y_neg) != 0 ) ? x_neg : x < y;
1093
1093
}
1094
1094
1095
-
1096
- inline constexpr uint256 operator <<(const uint256& x, uint64_t shift) noexcept
1097
- {
1098
- if (INTX_UNLIKELY (shift >= uint256::num_bits))
1099
- return 0 ;
1100
-
1101
- constexpr auto num_bits = uint256::num_bits;
1102
- constexpr auto half_bits = num_bits / 2 ;
1103
-
1104
- const auto xlo = uint128{x[0 ], x[1 ]};
1105
-
1106
- if (shift < half_bits)
1107
- {
1108
- const auto lo = xlo << shift;
1109
-
1110
- const auto xhi = uint128{x[2 ], x[3 ]};
1111
-
1112
- // Find the part moved from lo to hi.
1113
- // The shift right here can be invalid:
1114
- // for shift == 0 => rshift == half_bits.
1115
- // Split it into 2 valid shifts by (rshift - 1) and 1.
1116
- const auto rshift = half_bits - shift;
1117
- const auto lo_overflow = (xlo >> (rshift - 1 )) >> 1 ;
1118
- const auto hi = (xhi << shift) | lo_overflow;
1119
- return {lo[0 ], lo[1 ], hi[0 ], hi[1 ]};
1120
- }
1121
-
1122
- const auto hi = xlo << (shift - half_bits);
1123
- return {0 , 0 , hi[0 ], hi[1 ]};
1124
- }
1125
-
1126
1095
template <unsigned N>
1127
1096
inline constexpr uint <N> operator <<(const uint <N>& x, uint64_t shift) noexcept
1128
1097
{
1129
- if (INTX_UNLIKELY ( shift >= uint <N>::num_bits))
1098
+ if (shift >= uint <N>::num_bits) [[unlikely]]
1130
1099
return 0 ;
1131
1100
1132
- constexpr auto word_bits = sizeof (uint64_t ) * 8 ;
1133
-
1134
- const auto s = shift % word_bits;
1135
- const auto skip = static_cast <size_t >(shift / word_bits);
1136
-
1137
- uint <N> r;
1138
- uint64_t carry = 0 ;
1139
- for (size_t i = 0 ; i < (uint <N>::num_words - skip); ++i)
1101
+ if constexpr (N == 256 )
1140
1102
{
1141
- r[i + skip] = (x[i] << s) | carry;
1142
- carry = (x[i] >> (word_bits - s - 1 )) >> 1 ;
1143
- }
1144
- return r;
1145
- }
1103
+ constexpr auto half_bits = uint <N>::num_bits / 2 ;
1146
1104
1105
+ const auto xlo = uint128{x[0 ], x[1 ]};
1147
1106
1148
- inline constexpr uint256 operator >>(const uint256& x, uint64_t shift) noexcept
1149
- {
1150
- if (INTX_UNLIKELY (shift >= uint256::num_bits))
1151
- return 0 ;
1152
-
1153
- constexpr auto num_bits = uint256::num_bits;
1154
- constexpr auto half_bits = num_bits / 2 ;
1155
-
1156
- const auto xhi = uint128{x[2 ], x[3 ]};
1107
+ if (shift < half_bits)
1108
+ {
1109
+ const auto lo = xlo << shift;
1110
+
1111
+ const auto xhi = uint128{x[2 ], x[3 ]};
1112
+
1113
+ // Find the part moved from lo to hi.
1114
+ // The shift right here can be invalid:
1115
+ // for shift == 0 => rshift == half_bits.
1116
+ // Split it into 2 valid shifts by (rshift - 1) and 1.
1117
+ const auto rshift = half_bits - shift;
1118
+ const auto lo_overflow = (xlo >> (rshift - 1 )) >> 1 ;
1119
+ const auto hi = (xhi << shift) | lo_overflow;
1120
+ return {lo[0 ], lo[1 ], hi[0 ], hi[1 ]};
1121
+ }
1157
1122
1158
- if (shift < half_bits)
1123
+ const auto hi = xlo << (shift - half_bits);
1124
+ return {0 , 0 , hi[0 ], hi[1 ]};
1125
+ }
1126
+ else
1159
1127
{
1160
- const auto hi = xhi >> shift ;
1128
+ constexpr auto word_bits = sizeof ( uint64_t ) * 8 ;
1161
1129
1162
- const auto xlo = uint128{x[0 ], x[1 ]};
1130
+ const auto s = shift % word_bits;
1131
+ const auto skip = static_cast <size_t >(shift / word_bits);
1163
1132
1164
- // Find the part moved from hi to lo.
1165
- // The shift left here can be invalid:
1166
- // for shift == 0 => lshift == half_bits.
1167
- // Split it into 2 valid shifts by (lshift - 1) and 1.
1168
- const auto lshift = half_bits - shift ;
1169
- const auto hi_overflow = (xhi << (lshift - 1 )) << 1 ;
1170
- const auto lo = (xlo >> shift) | hi_overflow;
1171
- return {lo[ 0 ], lo[ 1 ], hi[ 0 ], hi[ 1 ]} ;
1133
+ uint <N> r;
1134
+ uint64_t carry = 0 ;
1135
+ for ( size_t i = 0 ; i < ( uint <N>::num_words - skip); ++i)
1136
+ {
1137
+ r[i + skip] = (x[i] << s) | carry ;
1138
+ carry = (x[i] >> (word_bits - s - 1 )) >> 1 ;
1139
+ }
1140
+ return r ;
1172
1141
}
1173
-
1174
- const auto lo = xhi >> (shift - half_bits);
1175
- return {lo[0 ], lo[1 ], 0 , 0 };
1176
1142
}
1177
1143
1178
1144
template <unsigned N>
1179
1145
inline constexpr uint <N> operator >>(const uint <N>& x, uint64_t shift) noexcept
1180
1146
{
1181
- if (INTX_UNLIKELY ( shift >= uint <N>::num_bits))
1147
+ if (shift >= uint <N>::num_bits) [[unlikely]]
1182
1148
return 0 ;
1183
1149
1184
- constexpr auto num_words = uint <N>::num_words;
1185
- constexpr auto word_bits = sizeof (uint64_t ) * 8 ;
1150
+ if constexpr (N == 256 )
1151
+ {
1152
+ constexpr auto half_bits = uint <N>::num_bits / 2 ;
1186
1153
1187
- const auto s = shift % word_bits;
1188
- const auto skip = static_cast <size_t >(shift / word_bits);
1154
+ const auto xhi = uint128{x[2 ], x[3 ]};
1189
1155
1190
- uint <N> r;
1191
- uint64_t carry = 0 ;
1192
- for (size_t i = 0 ; i < (num_words - skip); ++i)
1156
+ if (shift < half_bits)
1157
+ {
1158
+ const auto hi = xhi >> shift;
1159
+
1160
+ const auto xlo = uint128{x[0 ], x[1 ]};
1161
+
1162
+ // Find the part moved from hi to lo.
1163
+ // The shift left here can be invalid:
1164
+ // for shift == 0 => lshift == half_bits.
1165
+ // Split it into 2 valid shifts by (lshift - 1) and 1.
1166
+ const auto lshift = half_bits - shift;
1167
+ const auto hi_overflow = (xhi << (lshift - 1 )) << 1 ;
1168
+ const auto lo = (xlo >> shift) | hi_overflow;
1169
+ return {lo[0 ], lo[1 ], hi[0 ], hi[1 ]};
1170
+ }
1171
+
1172
+ const auto lo = xhi >> (shift - half_bits);
1173
+ return {lo[0 ], lo[1 ], 0 , 0 };
1174
+ }
1175
+ else
1193
1176
{
1194
- r[num_words - 1 - i - skip] = (x[num_words - 1 - i] >> s) | carry;
1195
- carry = (x[num_words - 1 - i] << (word_bits - s - 1 )) << 1 ;
1177
+ constexpr auto num_words = uint <N>::num_words;
1178
+ constexpr auto word_bits = sizeof (uint64_t ) * 8 ;
1179
+
1180
+ const auto s = shift % word_bits;
1181
+ const auto skip = static_cast <size_t >(shift / word_bits);
1182
+
1183
+ uint <N> r;
1184
+ uint64_t carry = 0 ;
1185
+ for (size_t i = 0 ; i < (num_words - skip); ++i)
1186
+ {
1187
+ r[num_words - 1 - i - skip] = (x[num_words - 1 - i] >> s) | carry;
1188
+ carry = (x[num_words - 1 - i] << (word_bits - s - 1 )) << 1 ;
1189
+ }
1190
+ return r;
1196
1191
}
1197
- return r;
1198
1192
}
1199
1193
1200
1194
template <unsigned N>
0 commit comments