From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../third_party/base/anglebase/base_export.h | 13 + .../base/anglebase/containers/mru_cache.h | 275 ++++++ .../common/third_party/base/anglebase/logging.h | 26 + .../src/common/third_party/base/anglebase/macros.h | 17 + .../third_party/base/anglebase/no_destructor.h | 106 ++ .../base/anglebase/numerics/checked_math.h | 384 ++++++++ .../base/anglebase/numerics/checked_math_impl.h | 641 ++++++++++++ .../base/anglebase/numerics/clamped_math.h | 270 +++++ .../base/anglebase/numerics/clamped_math_impl.h | 368 +++++++ .../base/anglebase/numerics/math_constants.h | 20 + .../third_party/base/anglebase/numerics/ranges.h | 39 + .../base/anglebase/numerics/safe_conversions.h | 403 ++++++++ .../anglebase/numerics/safe_conversions_arm_impl.h | 60 ++ .../anglebase/numerics/safe_conversions_impl.h | 893 +++++++++++++++++ .../base/anglebase/numerics/safe_math.h | 12 + .../base/anglebase/numerics/safe_math_arm_impl.h | 131 +++ .../anglebase/numerics/safe_math_clang_gcc_impl.h | 182 ++++ .../anglebase/numerics/safe_math_shared_impl.h | 227 +++++ .../src/common/third_party/base/anglebase/sha1.cc | 245 +++++ .../src/common/third_party/base/anglebase/sha1.h | 36 + .../third_party/base/anglebase/sys_byteorder.h | 49 + .../common/third_party/smhasher/src/PMurHash.cpp | 339 +++++++ .../src/common/third_party/smhasher/src/PMurHash.h | 57 ++ .../src/common/third_party/xxhash/xxhash.c | 1030 ++++++++++++++++++++ .../src/common/third_party/xxhash/xxhash.h | 341 +++++++ 25 files changed, 6164 insertions(+) create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/base_export.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/containers/mru_cache.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/logging.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/macros.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/no_destructor.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/checked_math.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/checked_math_impl.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/clamped_math.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/clamped_math_impl.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/math_constants.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/ranges.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/safe_conversions.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/safe_conversions_arm_impl.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/safe_math.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/safe_math_arm_impl.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/safe_math_clang_gcc_impl.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/safe_math_shared_impl.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/sha1.cc create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/sha1.h create mode 100644 gfx/angle/checkout/src/common/third_party/base/anglebase/sys_byteorder.h create mode 100644 gfx/angle/checkout/src/common/third_party/smhasher/src/PMurHash.cpp create mode 100644 gfx/angle/checkout/src/common/third_party/smhasher/src/PMurHash.h create mode 100644 gfx/angle/checkout/src/common/third_party/xxhash/xxhash.c create mode 100644 gfx/angle/checkout/src/common/third_party/xxhash/xxhash.h (limited to 'gfx/angle/checkout/src/common/third_party') diff --git a/gfx/angle/checkout/src/common/third_party/base/anglebase/base_export.h b/gfx/angle/checkout/src/common/third_party/base/anglebase/base_export.h new file mode 100644 index 0000000000..426047a992 --- /dev/null +++ b/gfx/angle/checkout/src/common/third_party/base/anglebase/base_export.h @@ -0,0 +1,13 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// base_export.h: Compatiblity hacks for importing Chromium's base/SHA1. + +#ifndef ANGLEBASE_BASE_EXPORT_H_ +#define ANGLEBASE_BASE_EXPORT_H_ + +#define ANGLEBASE_EXPORT + +#endif // ANGLEBASE_BASE_EXPORT_H_ diff --git a/gfx/angle/checkout/src/common/third_party/base/anglebase/containers/mru_cache.h b/gfx/angle/checkout/src/common/third_party/base/anglebase/containers/mru_cache.h new file mode 100644 index 0000000000..30b564aff6 --- /dev/null +++ b/gfx/angle/checkout/src/common/third_party/base/anglebase/containers/mru_cache.h @@ -0,0 +1,275 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file contains a template for a Most Recently Used cache that allows +// constant-time access to items using a key, but easy identification of the +// least-recently-used items for removal. Each key can only be associated with +// one payload item at a time. +// +// The key object will be stored twice, so it should support efficient copying. +// +// NOTE: While all operations are O(1), this code is written for +// legibility rather than optimality. If future profiling identifies this as +// a bottleneck, there is room for smaller values of 1 in the O(1). :] + +#ifndef ANGLEBASE_CONTAINERS_MRU_CACHE_H_ +#define ANGLEBASE_CONTAINERS_MRU_CACHE_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include "anglebase/logging.h" +#include "anglebase/macros.h" + +namespace angle +{ + +namespace base +{ + +// MRUCacheBase ---------------------------------------------------------------- + +// This template is used to standardize map type containers that can be used +// by MRUCacheBase. This level of indirection is necessary because of the way +// that template template params and default template params interact. +template +struct MRUCacheStandardMap +{ + typedef std::map Type; +}; + +// Base class for the MRU cache specializations defined below. +template class MapType = MRUCacheStandardMap> +class MRUCacheBase +{ + public: + // The payload of the list. This maintains a copy of the key so we can + // efficiently delete things given an element of the list. + typedef std::pair value_type; + + private: + typedef std::list PayloadList; + typedef + typename MapType::Type KeyIndex; + + public: + typedef typename PayloadList::size_type size_type; + + typedef typename PayloadList::iterator iterator; + typedef typename PayloadList::const_iterator const_iterator; + typedef typename PayloadList::reverse_iterator reverse_iterator; + typedef typename PayloadList::const_reverse_iterator const_reverse_iterator; + + enum + { + NO_AUTO_EVICT = 0 + }; + + // The max_size is the size at which the cache will prune its members to when + // a new item is inserted. If the caller wants to manager this itself (for + // example, maybe it has special work to do when something is evicted), it + // can pass NO_AUTO_EVICT to not restrict the cache size. + explicit MRUCacheBase(size_type max_size) : max_size_(max_size) {} + + virtual ~MRUCacheBase() {} + + size_type max_size() const { return max_size_; } + + // Inserts a payload item with the given key. If an existing item has + // the same key, it is removed prior to insertion. An iterator indicating the + // inserted item will be returned (this will always be the front of the list). + // + // The payload will be forwarded. + template + iterator Put(const KeyType &key, Payload &&payload) + { + // Remove any existing payload with that key. + typename KeyIndex::iterator index_iter = index_.find(key); + if (index_iter != index_.end()) + { + // Erase the reference to it. The index reference will be replaced in the + // code below. + Erase(index_iter->second); + } + else if (max_size_ != NO_AUTO_EVICT) + { + // New item is being inserted which might make it larger than the maximum + // size: kick the oldest thing out if necessary. + ShrinkToSize(max_size_ - 1); + } + + ordering_.emplace_front(key, std::forward(payload)); + index_.emplace(key, ordering_.begin()); + return ordering_.begin(); + } + + // Retrieves the contents of the given key, or end() if not found. This method + // has the side effect of moving the requested item to the front of the + // recency list. + iterator Get(const KeyType &key) + { + typename KeyIndex::iterator index_iter = index_.find(key); + if (index_iter == index_.end()) + return end(); + typename PayloadList::iterator iter = index_iter->second; + + // Move the touched item to the front of the recency ordering. + ordering_.splice(ordering_.begin(), ordering_, iter); + return ordering_.begin(); + } + + // Retrieves the payload associated with a given key and returns it via + // result without affecting the ordering (unlike Get). + iterator Peek(const KeyType &key) + { + typename KeyIndex::const_iterator index_iter = index_.find(key); + if (index_iter == index_.end()) + return end(); + return index_iter->second; + } + + const_iterator Peek(const KeyType &key) const + { + typename KeyIndex::const_iterator index_iter = index_.find(key); + if (index_iter == index_.end()) + return end(); + return index_iter->second; + } + + // Exchanges the contents of |this| by the contents of the |other|. + void Swap(MRUCacheBase &other) + { + ordering_.swap(other.ordering_); + index_.swap(other.index_); + std::swap(max_size_, other.max_size_); + } + + // Erases the item referenced by the given iterator. An iterator to the item + // following it will be returned. The iterator must be valid. + iterator Erase(iterator pos) + { + index_.erase(pos->first); + return ordering_.erase(pos); + } + + // MRUCache entries are often processed in reverse order, so we add this + // convenience function (not typically defined by STL containers). + reverse_iterator Erase(reverse_iterator pos) + { + // We have to actually give it the incremented iterator to delete, since + // the forward iterator that base() returns is actually one past the item + // being iterated over. + return reverse_iterator(Erase((++pos).base())); + } + + // Shrinks the cache so it only holds |new_size| items. If |new_size| is + // bigger or equal to the current number of items, this will do nothing. + void ShrinkToSize(size_type new_size) + { + for (size_type i = size(); i > new_size; i--) + Erase(rbegin()); + } + + // Deletes everything from the cache. + void Clear() + { + index_.clear(); + ordering_.clear(); + } + + // Returns the number of elements in the cache. + size_type size() const + { + // We don't use ordering_.size() for the return value because + // (as a linked list) it can be O(n). + DCHECK(index_.size() == ordering_.size()); + return index_.size(); + } + + // Allows iteration over the list. Forward iteration starts with the most + // recent item and works backwards. + // + // Note that since these iterators are actually iterators over a list, you + // can keep them as you insert or delete things (as long as you don't delete + // the one you are pointing to) and they will still be valid. + iterator begin() { return ordering_.begin(); } + const_iterator begin() const { return ordering_.begin(); } + iterator end() { return ordering_.end(); } + const_iterator end() const { return ordering_.end(); } + + reverse_iterator rbegin() { return ordering_.rbegin(); } + const_reverse_iterator rbegin() const { return ordering_.rbegin(); } + reverse_iterator rend() { return ordering_.rend(); } + const_reverse_iterator rend() const { return ordering_.rend(); } + + bool empty() const { return ordering_.empty(); } + + private: + PayloadList ordering_; + KeyIndex index_; + + size_type max_size_; + + DISALLOW_COPY_AND_ASSIGN(MRUCacheBase); +}; + +// MRUCache -------------------------------------------------------------------- + +// A container that does not do anything to free its data. Use this when storing +// value types (as opposed to pointers) in the list. +template > +class MRUCache : public MRUCacheBase +{ + private: + using ParentType = MRUCacheBase; + + public: + // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT. + explicit MRUCache(typename ParentType::size_type max_size) : ParentType(max_size) {} + virtual ~MRUCache() {} + + private: + DISALLOW_COPY_AND_ASSIGN(MRUCache); +}; + +// HashingMRUCache ------------------------------------------------------------ + +template +struct MRUCacheHashMap +{ + typedef std::unordered_map Type; +}; + +// This class is similar to MRUCache, except that it uses std::unordered_map as +// the map type instead of std::map. Note that your KeyType must be hashable to +// use this cache or you need to provide a hashing class. +template > +class HashingMRUCache : public MRUCacheBase +{ + private: + using ParentType = MRUCacheBase; + + public: + // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT. + explicit HashingMRUCache(typename ParentType::size_type max_size) : ParentType(max_size) {} + virtual ~HashingMRUCache() override {} + + private: + DISALLOW_COPY_AND_ASSIGN(HashingMRUCache); +}; + +} // namespace base + +} // namespace angle + +#endif // ANGLEBASE_CONTAINERS_MRU_CACHE_H_ diff --git a/gfx/angle/checkout/src/common/third_party/base/anglebase/logging.h b/gfx/angle/checkout/src/common/third_party/base/anglebase/logging.h new file mode 100644 index 0000000000..73f81e87f2 --- /dev/null +++ b/gfx/angle/checkout/src/common/third_party/base/anglebase/logging.h @@ -0,0 +1,26 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// logging.h: Compatiblity hacks for importing Chromium's base/numerics. + +#ifndef ANGLEBASE_LOGGING_H_ +#define ANGLEBASE_LOGGING_H_ + +#include "common/debug.h" + +#ifndef DCHECK +# define DCHECK(X) ASSERT(X) +#endif + +#ifndef CHECK +# define CHECK(X) ASSERT(X) +#endif + +// Unfortunately ANGLE relies on ASSERT being an empty statement, which these libs don't respect. +#ifndef NOTREACHED +# define NOTREACHED() ({ UNREACHABLE(); }) +#endif + +#endif // ANGLEBASE_LOGGING_H_ diff --git a/gfx/angle/checkout/src/common/third_party/base/anglebase/macros.h b/gfx/angle/checkout/src/common/third_party/base/anglebase/macros.h new file mode 100644 index 0000000000..06391784e4 --- /dev/null +++ b/gfx/angle/checkout/src/common/third_party/base/anglebase/macros.h @@ -0,0 +1,17 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// macros.h: Compatiblity hacks for importing Chromium's MRUCache. + +#ifndef ANGLEBASE_MACROS_H_ +#define ANGLEBASE_MACROS_H_ + +// A macro to disallow the copy constructor and operator= functions. +// This should be used in the private: declarations for a class. +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName &) = delete; \ + void operator=(const TypeName &) = delete + +#endif // ANGLEBASE_MACROS_H_ diff --git a/gfx/angle/checkout/src/common/third_party/base/anglebase/no_destructor.h b/gfx/angle/checkout/src/common/third_party/base/anglebase/no_destructor.h new file mode 100644 index 0000000000..5090dd9817 --- /dev/null +++ b/gfx/angle/checkout/src/common/third_party/base/anglebase/no_destructor.h @@ -0,0 +1,106 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ANGLEBASE_NO_DESTRUCTOR_H_ +#define ANGLEBASE_NO_DESTRUCTOR_H_ + +#include +#include + +namespace angle +{ + +namespace base +{ + +// A wrapper that makes it easy to create an object of type T with static +// storage duration that: +// - is only constructed on first access +// - never invokes the destructor +// in order to satisfy the styleguide ban on global constructors and +// destructors. +// +// Runtime constant example: +// const std::string& GetLineSeparator() { +// // Forwards to std::string(size_t, char, const Allocator&) constructor. +// static const base::NoDestructor s(5, '-'); +// return *s; +// } +// +// More complex initialization with a lambda: +// const std::string& GetSessionNonce() { +// static const base::NoDestructor nonce([] { +// std::string s(16); +// crypto::RandString(s.data(), s.size()); +// return s; +// }()); +// return *nonce; +// } +// +// NoDestructor stores the object inline, so it also avoids a pointer +// indirection and a malloc. Also note that since C++11 static local variable +// initialization is thread-safe and so is this pattern. Code should prefer to +// use NoDestructor over: +// - A function scoped static T* or T& that is dynamically initialized. +// - A global base::LazyInstance. +// +// Note that since the destructor is never run, this *will* leak memory if used +// as a stack or member variable. Furthermore, a NoDestructor should never +// have global scope as that may require a static initializer. +template +class NoDestructor +{ + public: + // Not constexpr; just write static constexpr T x = ...; if the value should + // be a constexpr. + template + explicit NoDestructor(Args &&... args) + { + new (storage_) T(std::forward(args)...); + } + + // Allows copy and move construction of the contained type, to allow + // construction from an initializer list, e.g. for std::vector. + explicit NoDestructor(const T &x) { new (storage_) T(x); } + explicit NoDestructor(T &&x) { new (storage_) T(std::move(x)); } + + NoDestructor(const NoDestructor &) = delete; + NoDestructor &operator=(const NoDestructor &) = delete; + + ~NoDestructor() = default; + + const T &operator*() const { return *get(); } + T &operator*() { return *get(); } + + const T *operator->() const { return get(); } + T *operator->() { return get(); } + + const T *get() const { return reinterpret_cast(storage_); } + T *get() { return reinterpret_cast(storage_); } + + private: + alignas(T) char storage_[sizeof(T)]; + +#if defined(LEAK_SANITIZER) + // TODO(https://crbug.com/812277): This is a hack to work around the fact + // that LSan doesn't seem to treat NoDestructor as a root for reachability + // analysis. This means that code like this: + // static base::NoDestructor> v({1, 2, 3}); + // is considered a leak. Using the standard leak sanitizer annotations to + // suppress leaks doesn't work: std::vector is implicitly constructed before + // calling the base::NoDestructor constructor. + // + // Unfortunately, I haven't been able to demonstrate this issue in simpler + // reproductions: until that's resolved, hold an explicit pointer to the + // placement-new'd object in leak sanitizer mode to help LSan realize that + // objects allocated by the contained type are still reachable. + T *storage_ptr_ = reinterpret_cast(storage_); +#endif // defined(LEAK_SANITIZER) +}; + +} // namespace base + +} // namespace angle + +#endif // ANGLEBASE_NO_DESTRUCTOR_H_ diff --git a/gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/checked_math.h b/gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/checked_math.h new file mode 100644 index 0000000000..18bceb7468 --- /dev/null +++ b/gfx/angle/checkout/src/common/third_party/base/anglebase/numerics/checked_math.h @@ -0,0 +1,384 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_NUMERICS_CHECKED_MATH_H_ +#define BASE_NUMERICS_CHECKED_MATH_H_ + +#include + +#include +#include + +#include "anglebase/numerics/checked_math_impl.h" + +namespace angle +{ +namespace base +{ +namespace internal +{ + +template +class CheckedNumeric +{ + static_assert(std::is_arithmetic::value, "CheckedNumeric: T must be a numeric type."); + + public: + template + friend class CheckedNumeric; + + using type = T; + + constexpr CheckedNumeric() = default; + + // Copy constructor. + template + constexpr CheckedNumeric(const CheckedNumeric &rhs) + : state_(rhs.state_.value(), rhs.IsValid()) + {} + + // This is not an explicit constructor because we implicitly upgrade regular + // numerics to CheckedNumerics to make them easier to use. + template + constexpr CheckedNumeric(Src value) // NOLINT(runtime/explicit) + : state_(value) + { + static_assert(std::is_arithmetic::value, "Argument must be numeric."); + } + + // This is not an explicit constructor because we want a seamless conversion + // from StrictNumeric types. + template + constexpr CheckedNumeric(StrictNumeric value) // NOLINT(runtime/explicit) + : state_(static_cast(value)) + {} + + // IsValid() - The public API to test if a CheckedNumeric is currently valid. + // A range checked destination type can be supplied using the Dst template + // parameter. + template + constexpr bool IsValid() const + { + return state_.is_valid() && IsValueInRangeForNumericType(state_.value()); + } + + // AssignIfValid(Dst) - Assigns the underlying value if it is currently valid + // and is within the range supported by the destination type. Returns true if + // successful and false otherwise. + template +#if defined(__clang__) || defined(__GNUC__) + __attribute__((warn_unused_result)) +#elif defined(_MSC_VER) + _Check_return_ +#endif + constexpr bool + AssignIfValid(Dst *result) const + { + return BASE_NUMERICS_LIKELY(IsValid()) + ? ((*result = static_cast(state_.value())), true) + : false; + } + + // ValueOrDie() - The primary accessor for the underlying value. If the + // current state is not valid it will CHECK and crash. + // A range checked destination type can be supplied using the Dst template + // parameter, which will trigger a CHECK if the value is not in bounds for + // the destination. + // The CHECK behavior can be overridden by supplying a handler as a + // template parameter, for test code, etc. However, the handler cannot access + // the underlying value, and it is not available through other means. + template + constexpr StrictNumeric ValueOrDie() const + { + return BASE_NUMERICS_LIKELY(IsValid()) ? static_cast(state_.value()) + : CheckHandler::template HandleFailure(); + } + + // ValueOrDefault(T default_value) - A convenience method that returns the + // current value if the state is valid, and the supplied default_value for + // any other state. + // A range checked destination type can be supplied using the Dst template + // parameter. WARNING: This function may fail to compile or CHECK at runtime + // if the supplied default_value is not within range of the destination type. + template + constexpr StrictNumeric ValueOrDefault(const Src default_value) const + { + return BASE_NUMERICS_LIKELY(IsValid()) ? static_cast(state_.value()) + : checked_cast(default_value); + } + + // Returns a checked numeric of the specified type, cast from the current + // CheckedNumeric. If the current state is invalid or the destination cannot + // represent the result then the returned CheckedNumeric will be invalid. + template + constexpr CheckedNumeric::type> Cast() const + { + return *this; + } + + // This friend method is available solely for providing more detailed logging + // in the tests. Do not implement it in production code, because the + // underlying values may change at any time. + template + friend U GetNumericValueForTest(const CheckedNumeric &src); + + // Prototypes for the supported arithmetic operator overloads. + template + constexpr CheckedNumeric &operator+=(const Src rhs); + template + constexpr CheckedNumeric &operator-=(const Src rhs); + template + constexpr CheckedNumeric &operator*=(const Src rhs); + template + constexpr CheckedNumeric &operator/=(const Src rhs); + template + constexpr CheckedNumeric &operator%=(const Src rhs); + template + constexpr CheckedNumeric &operator<<=(const Src rhs); + template + constexpr CheckedNumeric &operator>>=(const Src rhs); + template + constexpr CheckedNumeric &operator&=(const Src rhs); + template + constexpr CheckedNumeric &operator|=(const Src rhs); + template + constexpr CheckedNumeric &operator^=(const Src rhs); + + constexpr CheckedNumeric operator-() const + { + // Use an optimized code path for a known run-time variable. + if (!MustTreatAsConstexpr(state_.value()) && std::is_signed::value && + std::is_floating_point::value) + { + return FastRuntimeNegate(); + } + // The negation of two's complement int min is int min. + const bool is_valid = + IsValid() && (!std::is_signed::value || std::is_floating_point::value || + NegateWrapper(state_.value()) != std::numeric_limits::lowest()); + return CheckedNumeric(NegateWrapper(state_.value()), is_valid); + } + + constexpr CheckedNumeric operator~() const + { + return CheckedNumeric(InvertWrapper(state_.value()), + IsValid()); + } + + constexpr CheckedNumeric Abs() const + { + return !IsValueNegative(state_.value()) ? *this : -*this; + } + + template + constexpr CheckedNumeric::type> Max(const U rhs) const + { + return CheckMax(*this, rhs); + } + + template + constexpr CheckedNumeric::type> Min(const U rhs) const + { + return CheckMin(*this, rhs); + } + + // This function is available only for integral types. It returns an unsigned + // integer of the same width as the source type, containing the absolute value + // of the source, and properly handling signed min. + constexpr CheckedNumeric::type> UnsignedAbs() const + { + return CheckedNumeric::type>( + SafeUnsignedAbs(state_.value()), state_.is_valid()); + } + + constexpr CheckedNumeric &operator++() + { + *this += 1; + return *this; + } + + constexpr CheckedNumeric operator++(int) + { + CheckedNumeric value = *this; + *this += 1; + return value; + } + + constexpr CheckedNumeric &operator--() + { + *this -= 1; + return *this; + } + + constexpr CheckedNumeric operator--(int) + { + // TODO(pkasting): Consider std::exchange() once it's constexpr in C++20. + const CheckedNumeric value = *this; + *this -= 1; + return value; + } + + // These perform the actual math operations on the CheckedNumerics. + // Binary arithmetic operations. + template