120#ifndef OR_TOOLS_BASE_STRONG_INT_H_
121#define OR_TOOLS_BASE_STRONG_INT_H_
131#include <type_traits>
134#include "absl/meta/type_traits.h"
135#include "absl/strings/numbers.h"
136#include "absl/strings/str_cat.h"
137#include "absl/strings/str_format.h"
138#include "absl/strings/string_view.h"
139#include "absl/strings/substitute.h"
150struct NullStrongIntValidator {
178 template <
typename T,
typename U>
179 static constexpr bool ValidateInit(U ) {
183 template <
typename T>
184 static constexpr bool ValidateNegate(T ) {
188 template <
typename T>
189 static constexpr bool ValidateBitNot(T ) {
193 template <
typename T>
194 static constexpr bool ValidateAdd(T , T ) {
198 template <
typename T>
199 static constexpr bool ValidateSubtract(T , T ) {
203 template <
typename T,
typename U>
204 static constexpr bool ValidateMultiply(T , U ) {
208 template <
typename T,
typename U>
209 static constexpr bool ValidateDivide(T , U ) {
213 template <
typename T,
typename U>
214 static constexpr bool ValidateModulo(T , U ) {
218 template <
typename T>
219 static constexpr bool ValidateLeftShift(T , int64_t ) {
223 template <
typename T>
224 static constexpr bool ValidateRightShift(T , int64_t ) {
228 template <
typename T>
229 static constexpr bool ValidateBitAnd(T , T ) {
233 template <
typename T>
234 static constexpr bool ValidateBitOr(T , T ) {
238 template <
typename T>
239 static constexpr bool ValidateBitXor(T , T ) {
244template <
typename TagType,
typename NativeType,
245 typename ValidatorType = NullStrongIntValidator>
250struct IsStrongInt :
public std::false_type {};
252template <
typename... Ts>
253struct IsStrongInt<StrongInt<Ts...>> :
public std::true_type {};
257inline constexpr bool IsStrongIntV = IsStrongInt<T>::value;
264template <
typename TagType,
typename NativeType,
typename Val
idatorType>
267 typedef NativeType ValueType;
270 size_t operator()(
const StrongInt& x)
const {
271 return static_cast<size_t>(
x.value());
275 static constexpr absl::string_view TypeName() {
return TagType::TypeName(); }
278 constexpr StrongInt()
279 : value_((ValidatorType::template ValidateInit<ValueType>(NativeType()),
305 template <
typename ArgTagType,
typename ArgNativeType,
306 typename ArgValidatorType>
307 explicit constexpr StrongInt(
308 StrongInt<ArgTagType, ArgNativeType, ArgValidatorType> arg)
313 StrongIntConvert(arg, static_cast<StrongInt*>(nullptr)).value()) {}
318 class = std::enable_if_t<std::is_same_v<
319 decltype(
static_cast<ValueType
>(std::declval<T>())), ValueType>>>
320 explicit constexpr StrongInt(T init_value)
321 : value_((ValidatorType::template ValidateInit<ValueType>(init_value),
322 static_cast<ValueType>(init_value))) {}
327 constexpr ValueType value()
const {
return value_; }
331 template <
typename ValType>
332 constexpr ValType value()
const {
333 return static_cast<ValType
>(value_);
338 template <
typename T,
339 typename = absl::enable_if_t<absl::conjunction<
340 std::bool_constant<std::numeric_limits<T>::is_integer>,
341 std::is_convertible<ValueType, T>>::value>>
342 constexpr explicit operator T()
const {
347 static constexpr StrongInt Max() {
348 return StrongInt(std::numeric_limits<ValueType>::max());
350 static constexpr StrongInt Min() {
351 return StrongInt(std::numeric_limits<ValueType>::min());
355 bool operator!()
const {
return value_ == 0; }
356 StrongInt
operator+()
const {
return StrongInt(value_); }
358 ValidatorType::template ValidateNegate<ValueType>(value_);
359 return StrongInt(-value_);
361 StrongInt operator~()
const {
362 ValidatorType::template ValidateBitNot<ValueType>(value_);
363 return StrongInt(ValueType(~value_));
367 StrongInt& operator++() {
368 ValidatorType::template ValidateAdd<ValueType>(value_, ValueType(1));
372 StrongInt operator++(
int ) {
373 ValidatorType::template ValidateAdd<ValueType>(value_, ValueType(1));
374 StrongInt temp(*
this);
378 StrongInt& operator--() {
379 ValidatorType::template ValidateSubtract<ValueType>(value_, ValueType(1));
383 StrongInt operator--(
int ) {
384 ValidatorType::template ValidateSubtract<ValueType>(value_, ValueType(1));
385 StrongInt temp(*
this);
391 StrongInt& operator+=(StrongInt arg) {
392 ValidatorType::template ValidateAdd<ValueType>(value_, arg.value());
393 value_ += arg.value();
396 StrongInt& operator-=(StrongInt arg) {
397 ValidatorType::template ValidateSubtract<ValueType>(value_, arg.value());
398 value_ -= arg.value();
401 template <
typename ArgType,
402 std::enable_if_t<!IsStrongIntV<ArgType>>* =
nullptr>
403 StrongInt& operator*=(ArgType arg) {
404 ValidatorType::template ValidateMultiply<ValueType, ArgType>(value_, arg);
408 template <
typename ArgType,
409 std::enable_if_t<!IsStrongIntV<ArgType>>* =
nullptr>
410 StrongInt& operator/=(ArgType arg) {
411 ValidatorType::template ValidateDivide<ValueType, ArgType>(value_, arg);
415 template <
typename ArgType,
416 std::enable_if_t<!IsStrongIntV<ArgType>>* =
nullptr>
417 StrongInt& operator%=(ArgType arg) {
418 ValidatorType::template ValidateModulo<ValueType, ArgType>(value_, arg);
422 StrongInt& operator<<=(int64_t arg) {
423 ValidatorType::template ValidateLeftShift<ValueType>(value_, arg);
427 StrongInt& operator>>=(int64_t arg) {
428 ValidatorType::template ValidateRightShift<ValueType>(value_, arg);
432 StrongInt& operator&=(StrongInt arg) {
433 ValidatorType::template ValidateBitAnd<ValueType>(value_, arg.value());
434 value_ &= arg.value();
437 StrongInt& operator|=(StrongInt arg) {
438 ValidatorType::template ValidateBitOr<ValueType>(value_, arg.value());
439 value_ |= arg.value();
442 StrongInt& operator^=(StrongInt arg) {
443 ValidatorType::template ValidateBitXor<ValueType>(value_, arg.value());
444 value_ ^= arg.value();
448 template <
typename H>
450 return H::combine(std::move(h),
i.value_);
457 static_assert(std::numeric_limits<ValueType>::is_integer,
458 "invalid integer type for strong int");
472template <
typename Sink,
typename...
T>
474 using ValueType =
typename decltype(arg)::ValueType;
478 if constexpr (std::is_same_v<ValueType, int8_t>) {
479 absl::Format(&sink,
"%d", arg.value());
480 }
else if constexpr (std::is_same_v<ValueType, uint8_t>) {
481 absl::Format(&sink,
"%u", arg.value());
483 absl::Format(&sink,
"%v", arg.value());
487template <
typename TagType,
typename ValueType>
488static std::string IntParseError(absl::string_view text) {
489 return absl::Substitute(
"'$0' is not a valid $1 [min: $2, max: $3]", text,
491 std::numeric_limits<ValueType>::min(),
492 std::numeric_limits<ValueType>::max());
496template <
typename TagType,
typename ValueType,
typename Val
idatorType>
498 StrongInt<TagType, ValueType, ValidatorType>* out,
499 std::string* error) {
501 if constexpr (
sizeof(ValueType) >= 4) {
502 if (!absl::SimpleAtoi(text, &value)) {
503 *error = IntParseError<TagType, ValueType>(text);
508 int32_t larger_value;
509 if (!absl::SimpleAtoi(text, &larger_value) ||
510 larger_value > std::numeric_limits<ValueType>::max() ||
511 larger_value < std::numeric_limits<ValueType>::min()) {
512 *error = IntParseError<TagType, ValueType>(text);
516 value =
static_cast<ValueType
>(larger_value);
519 *out = StrongInt<TagType, ValueType, ValidatorType>(value);
523template <
typename TagType,
typename ValueType,
typename Val
idatorType>
525 const StrongInt<TagType, ValueType, ValidatorType>& val) {
526 return absl::StrCat(val.value());
530template <
typename TagType,
typename ValueType,
typename Val
idatorType>
532 StrongInt<TagType, ValueType, ValidatorType> arg) {
533 return os << arg.value();
538template <
typename TagType,
typename Val
idatorType>
540 StrongInt<TagType, int8_t, ValidatorType> arg) {
541 return os << static_cast<int>(arg.value());
546template <
typename TagType,
typename Val
idatorType>
548 StrongInt<TagType, uint8_t, ValidatorType> arg) {
549 return os << static_cast<unsigned int>(arg.value());
553#define STRONG_INT_VS_STRONG_INT_BINARY_OP(op, validator) \
554 template <typename TagType, typename ValueType, typename ValidatorType> \
555 constexpr StrongInt<TagType, ValueType, ValidatorType> operator op( \
556 StrongInt<TagType, ValueType, ValidatorType> lhs, \
557 StrongInt<TagType, ValueType, ValidatorType> rhs) { \
558 return ValidatorType::template validator<ValueType>(lhs.value(), \
560 StrongInt<TagType, ValueType, ValidatorType>( \
561 static_cast<ValueType>(lhs.value() op rhs.value())); \
568#undef STRONG_INT_VS_STRONG_INT_BINARY_OP
571#define STRONG_INT_VS_NUMERIC_BINARY_OP(op, validator) \
572 template <typename TagType, typename ValueType, typename ValidatorType, \
574 std::enable_if_t<!IsStrongIntV<NumType>>* = nullptr> \
575 constexpr StrongInt<TagType, ValueType, ValidatorType> operator op( \
576 StrongInt<TagType, ValueType, ValidatorType> lhs, NumType rhs) { \
577 return ValidatorType::template validator<ValueType>(lhs.value(), rhs), \
578 StrongInt<TagType, ValueType, ValidatorType>( \
579 static_cast<ValueType>(lhs.value() op rhs)); \
583#define NUMERIC_VS_STRONG_INT_BINARY_OP(op, validator) \
584 template <typename TagType, typename ValueType, typename ValidatorType, \
586 std::enable_if_t<!IsStrongIntV<NumType>>* = nullptr> \
587 constexpr StrongInt<TagType, ValueType, ValidatorType> operator op( \
588 NumType lhs, StrongInt<TagType, ValueType, ValidatorType> rhs) { \
589 return ValidatorType::template validator<ValueType>(rhs.value(), lhs), \
590 StrongInt<TagType, ValueType, ValidatorType>( \
591 static_cast<ValueType>(rhs.value() op lhs)); \
599#undef STRONG_INT_VS_NUMERIC_BINARY_OP
600#undef NUMERIC_VS_STRONG_INT_BINARY_OP
603#define STRONG_INT_COMPARISON_OP(op) \
604 template <typename TagType, typename ValueType, typename ValidatorType> \
605 constexpr bool operator op( \
606 StrongInt<TagType, ValueType, ValidatorType> lhs, \
607 StrongInt<TagType, ValueType, ValidatorType> rhs) { \
608 return lhs.value() op rhs.value(); \
616#undef STRONG_INT_COMPARISON_OP
620template <
typename IntType>
621class StrongIntRange {
624 class StrongIntRangeIterator {
626 using value_type = IntType;
627 using difference_type = IntType;
628 using reference =
const IntType&;
629 using pointer =
const IntType*;
630 using iterator_category = std::input_iterator_tag;
632 explicit StrongIntRangeIterator(IntType initial) : current_(initial) {}
633 bool operator!=(
const StrongIntRangeIterator& other)
const {
634 return current_ != other.current_;
636 bool operator==(
const StrongIntRangeIterator& other)
const {
637 return current_ == other.current_;
639 value_type
operator*()
const {
return current_; }
640 pointer operator->()
const {
return ¤t_; }
641 StrongIntRangeIterator& operator++() {
645 StrongIntRangeIterator operator++(
int) {
646 StrongIntRangeIterator old_iter = *
this;
656 explicit StrongIntRange(IntType end) : begin_(IntType(0)), end_(
end) {}
658 StrongIntRange(IntType begin, IntType end) : begin_(
begin), end_(
end) {}
659 StrongIntRangeIterator
begin()
const {
return begin_; }
660 StrongIntRangeIterator
end()
const {
return end_; }
663 const StrongIntRangeIterator begin_;
664 const StrongIntRangeIterator end_;
667template <
typename IntType>
668StrongIntRange<IntType> MakeStrongIntRange(IntType end) {
669 return StrongIntRange<IntType>(end);
672template <
typename IntType>
673StrongIntRange<IntType> MakeStrongIntRange(IntType begin, IntType end) {
674 return StrongIntRange<IntType>(begin, end);
683#define DEFINE_STRONG_INT_TYPE(type_name, value_type) \
684 struct type_name##_strong_int_tag_ { \
685 static constexpr absl::string_view TypeName() { return #type_name; } \
687 typedef ::util_intops::StrongInt<type_name##_strong_int_tag_, value_type, \
688 ::util_intops::NullStrongIntValidator> \
695template <
typename Tag,
typename Value,
typename Val
idator>
696struct hash<util_intops::StrongInt<Tag, Value, Validator>>
697 : ::util_intops::StrongInt<Tag, Value, Validator>::Hasher {};
699template <
typename TagType,
typename NativeType,
typename Val
idatorType>
700struct numeric_limits<
701 util_intops::StrongInt<TagType, NativeType, ValidatorType>> {
703 using StrongIntT = util_intops::StrongInt<TagType, NativeType, ValidatorType>;
707 static constexpr bool is_specialized =
true;
708 static constexpr bool is_signed = numeric_limits<NativeType>::is_signed;
709 static constexpr bool is_integer = numeric_limits<NativeType>::is_integer;
710 static constexpr bool is_exact = numeric_limits<NativeType>::is_exact;
711 static constexpr bool has_infinity = numeric_limits<NativeType>::has_infinity;
712 static constexpr bool has_quiet_NaN =
713 numeric_limits<NativeType>::has_quiet_NaN;
714 static constexpr bool has_signaling_NaN =
715 numeric_limits<NativeType>::has_signaling_NaN;
716 static constexpr float_denorm_style has_denorm =
717 numeric_limits<NativeType>::has_denorm;
718 static constexpr bool has_denorm_loss =
719 numeric_limits<NativeType>::has_denorm_loss;
720 static constexpr float_round_style round_style =
721 numeric_limits<NativeType>::round_style;
722 static constexpr bool is_iec559 = numeric_limits<NativeType>::is_iec559;
723 static constexpr bool is_bounded = numeric_limits<NativeType>::is_bounded;
724 static constexpr bool is_modulo = numeric_limits<NativeType>::is_modulo;
725 static constexpr int digits = numeric_limits<NativeType>::digits;
726 static constexpr int digits10 = numeric_limits<NativeType>::digits10;
727 static constexpr int max_digits10 = numeric_limits<NativeType>::max_digits10;
728 static constexpr int radix = numeric_limits<NativeType>::radix;
729 static constexpr int min_exponent = numeric_limits<NativeType>::min_exponent;
730 static constexpr int min_exponent10 =
731 numeric_limits<NativeType>::min_exponent10;
732 static constexpr int max_exponent = numeric_limits<NativeType>::max_exponent;
733 static constexpr int max_exponent10 =
734 numeric_limits<NativeType>::max_exponent10;
735 static constexpr bool traps = numeric_limits<NativeType>::traps;
736 static constexpr bool tinyness_before =
737 numeric_limits<NativeType>::tinyness_before;
740 static constexpr StrongIntT(min)() {
return StrongIntT(StrongIntT::Min()); }
741 static constexpr StrongIntT lowest() {
return StrongIntT(StrongIntT::Min()); }
742 static constexpr StrongIntT(max)() {
return StrongIntT(StrongIntT::Max()); }
743 static constexpr StrongIntT epsilon() {
return StrongIntT(); }
744 static constexpr StrongIntT round_error() {
return StrongIntT(); }
745 static constexpr StrongIntT infinity() {
return StrongIntT(); }
746 static constexpr StrongIntT quiet_NaN() {
return StrongIntT(); }
747 static constexpr StrongIntT signaling_NaN() {
return StrongIntT(); }
748 static constexpr StrongIntT denorm_min() {
return StrongIntT(); }
bool operator!=(const ProtoEnumIterator< E > &a, const ProtoEnumIterator< E > &b)
bool operator==(const ProtoEnumIterator< E > &a, const ProtoEnumIterator< E > &b)
void AbslStringify(Sink &sink, const AttrT attr_type)
H AbslHashValue(H h, std::shared_ptr< Variable > i)
dual_gradient T(y - `dual_solution`) class DiagonalTrustRegionProblemFromQp
LinearExpr operator*(LinearExpr lhs, double rhs)
LinearExpr operator-(LinearExpr lhs, const LinearExpr &rhs)
ClosedInterval::Iterator end(ClosedInterval interval)
LinearExpr operator+(LinearExpr lhs, const LinearExpr &rhs)
ClosedInterval::Iterator begin(ClosedInterval interval)
std::ostream & operator<<(std::ostream &out, const std::pair< First, Second > &p)
#define NUMERIC_VS_STRONG_INT_BINARY_OP(op, validator)
#define STRONG_INT_VS_STRONG_INT_BINARY_OP(op, validator)
#define STRONG_INT_COMPARISON_OP(op)
#define STRONG_INT_VS_NUMERIC_BINARY_OP(op, validator)