mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
261 lines
7.1 KiB
C++
261 lines
7.1 KiB
C++
/*
|
|
* Copyright (c) 2015, Intel Corporation
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* * Neither the name of Intel Corporation nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/** \file
|
|
* \brief Data types used to represent depth quantities.
|
|
*/
|
|
|
|
#ifndef DEPTH_H
|
|
#define DEPTH_H
|
|
|
|
#include "ue2common.h"
|
|
|
|
#ifdef DUMP_SUPPORT
|
|
#include <string>
|
|
#endif
|
|
|
|
#include <boost/functional/hash/hash_fwd.hpp>
|
|
|
|
namespace ue2 {
|
|
|
|
/**
|
|
* \brief Exception thrown if a depth operation overflows.
|
|
*/
|
|
struct DepthOverflowError {};
|
|
|
|
/**
|
|
* \brief Type used to represent depth information; value is either a count,
|
|
* or the special values "infinity" and "unreachable".
|
|
*/
|
|
class depth {
|
|
public:
|
|
depth() : val(val_unreachable) {}
|
|
|
|
depth(u32 v) : val(v) {
|
|
if (v > max_value()) {
|
|
DEBUG_PRINTF("depth %u too large to represent!\n", v);
|
|
throw DepthOverflowError();
|
|
}
|
|
}
|
|
|
|
static depth unreachable() {
|
|
depth d;
|
|
d.val = val_unreachable;
|
|
return d;
|
|
}
|
|
|
|
static depth infinity() {
|
|
depth d;
|
|
d.val = val_infinity;
|
|
return d;
|
|
}
|
|
|
|
/** \brief Returns the max finite value representable as a depth. */
|
|
static constexpr u32 max_value() { return val_infinity - 1; }
|
|
|
|
bool is_finite() const { return val < val_infinity; }
|
|
bool is_infinite() const { return val == val_infinity; }
|
|
bool is_unreachable() const { return val == val_unreachable; }
|
|
bool is_reachable() const { return !is_unreachable(); }
|
|
|
|
/** \brief Convert a finite depth to an integer. */
|
|
operator u32() const {
|
|
if (!is_finite()) {
|
|
throw DepthOverflowError();
|
|
}
|
|
return val;
|
|
}
|
|
|
|
bool operator<(const depth &d) const { return val < d.val; }
|
|
bool operator>(const depth &d) const { return val > d.val; }
|
|
bool operator<=(const depth &d) const { return val <= d.val; }
|
|
bool operator>=(const depth &d) const { return val >= d.val; }
|
|
bool operator==(const depth &d) const { return val == d.val; }
|
|
bool operator!=(const depth &d) const { return val != d.val; }
|
|
|
|
// The following comparison operators exist for use against integer types
|
|
// that are bigger than what we can safely convert to depth (such as those
|
|
// in extparam).
|
|
|
|
bool operator<(u64a d) const {
|
|
if (!is_finite()) {
|
|
return false;
|
|
}
|
|
return val < d;
|
|
}
|
|
bool operator<=(u64a d) const {
|
|
if (!is_finite()) {
|
|
return false;
|
|
}
|
|
return val <= d;
|
|
}
|
|
bool operator==(u64a d) const {
|
|
if (!is_finite()) {
|
|
return false;
|
|
}
|
|
return val == d;
|
|
}
|
|
bool operator>(u64a d) const { return !(*this <= d); }
|
|
bool operator>=(u64a d) const { return !(*this < d); }
|
|
bool operator!=(u64a d) const { return !(*this == d); }
|
|
|
|
depth operator+(const depth &d) const {
|
|
if (is_unreachable() || d.is_unreachable()) {
|
|
return unreachable();
|
|
}
|
|
if (is_infinite() || d.is_infinite()) {
|
|
return infinity();
|
|
}
|
|
|
|
u64a rv = val + d.val;
|
|
if (rv >= val_infinity) {
|
|
DEBUG_PRINTF("depth %llu too large to represent!\n", rv);
|
|
throw DepthOverflowError();
|
|
}
|
|
|
|
return depth((u32)rv);
|
|
}
|
|
|
|
depth &operator+=(const depth &d) {
|
|
depth rv = *this + d;
|
|
*this = rv;
|
|
return *this;
|
|
}
|
|
|
|
depth operator-(const depth &d) const {
|
|
if (!d.is_finite()) {
|
|
throw DepthOverflowError();
|
|
}
|
|
|
|
if (is_unreachable()) {
|
|
return unreachable();
|
|
}
|
|
if (is_infinite()) {
|
|
return infinity();
|
|
}
|
|
|
|
if (val < d.val) {
|
|
throw DepthOverflowError();
|
|
}
|
|
|
|
u32 rv = val - d.val;
|
|
return depth(rv);
|
|
}
|
|
|
|
depth &operator-=(const depth &d) {
|
|
depth rv = *this - d;
|
|
*this = rv;
|
|
return *this;
|
|
}
|
|
|
|
depth operator+(s32 d) const {
|
|
if (is_unreachable()) {
|
|
return unreachable();
|
|
}
|
|
if (is_infinite()) {
|
|
return infinity();
|
|
}
|
|
|
|
s64a rv = val + d;
|
|
if (rv < 0 || (u64a)rv >= val_infinity) {
|
|
DEBUG_PRINTF("depth %lld too large to represent!\n", rv);
|
|
throw DepthOverflowError();
|
|
}
|
|
|
|
return depth((u32)rv);
|
|
}
|
|
|
|
depth operator+=(s32 d) {
|
|
depth rv = *this + d;
|
|
*this = rv;
|
|
return *this;
|
|
}
|
|
|
|
#ifdef DUMP_SUPPORT
|
|
/** \brief Render as a string, useful for debugging. */
|
|
std::string str() const;
|
|
#endif
|
|
|
|
friend size_t hash_value(const depth &d) {
|
|
return d.val;
|
|
}
|
|
|
|
private:
|
|
static constexpr u32 val_infinity = (1u << 31) - 1;
|
|
static constexpr u32 val_unreachable = 1u << 31;
|
|
|
|
u32 val;
|
|
};
|
|
|
|
/**
|
|
* \brief Encapsulates a min/max pair.
|
|
*/
|
|
struct DepthMinMax {
|
|
depth min;
|
|
depth max;
|
|
|
|
DepthMinMax() : min(depth::infinity()), max(depth(0)) {}
|
|
DepthMinMax(const depth &mn, const depth &mx) : min(mn), max(mx) {}
|
|
|
|
bool operator<(const DepthMinMax &b) const {
|
|
if (min != b.min) {
|
|
return min < b.min;
|
|
}
|
|
return max < b.max;
|
|
}
|
|
|
|
bool operator==(const DepthMinMax &b) const {
|
|
return min == b.min && max == b.max;
|
|
}
|
|
|
|
bool operator!=(const DepthMinMax &b) const {
|
|
return !(*this == b);
|
|
}
|
|
|
|
#ifdef DUMP_SUPPORT
|
|
/** \brief Render as a string, useful for debugging. */
|
|
std::string str() const;
|
|
#endif
|
|
};
|
|
|
|
inline size_t hash_value(const DepthMinMax &d) {
|
|
size_t val = 0;
|
|
boost::hash_combine(val, d.min);
|
|
boost::hash_combine(val, d.max);
|
|
return val;
|
|
}
|
|
|
|
/**
|
|
* \brief Merge two DepthMinMax values together to produce their union.
|
|
*/
|
|
DepthMinMax unionDepthMinMax(const DepthMinMax &a, const DepthMinMax &b);
|
|
|
|
} // namespace ue2
|
|
|
|
#endif // DEPTH_H
|