mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
add SparseArray
This commit is contained in:
parent
1b76d5a31c
commit
9f198514ce
@ -53,6 +53,7 @@
|
|||||||
nonDeletor.h \
|
nonDeletor.h \
|
||||||
pta_double.h \
|
pta_double.h \
|
||||||
pta_float.h pta_int.h \
|
pta_float.h pta_int.h \
|
||||||
|
sparseArray.I sparseArray.h \
|
||||||
string_utils.I string_utils.N string_utils.h \
|
string_utils.I string_utils.N string_utils.h \
|
||||||
timedCycle.I timedCycle.h typedWritable.I \
|
timedCycle.I timedCycle.h typedWritable.I \
|
||||||
typedWritable.h typedWritableReferenceCount.I \
|
typedWritable.h typedWritableReferenceCount.I \
|
||||||
@ -94,6 +95,7 @@
|
|||||||
nonDeletor.cxx \
|
nonDeletor.cxx \
|
||||||
pta_double.cxx pta_float.cxx \
|
pta_double.cxx pta_float.cxx \
|
||||||
pta_int.cxx pta_ushort.cxx \
|
pta_int.cxx pta_ushort.cxx \
|
||||||
|
sparseArray.cxx \
|
||||||
string_utils.cxx timedCycle.cxx typedWritable.cxx \
|
string_utils.cxx timedCycle.cxx typedWritable.cxx \
|
||||||
typedWritableReferenceCount.cxx updateSeq.cxx \
|
typedWritableReferenceCount.cxx updateSeq.cxx \
|
||||||
uniqueIdAllocator.cxx \
|
uniqueIdAllocator.cxx \
|
||||||
@ -145,6 +147,7 @@
|
|||||||
nonDeletor.h \
|
nonDeletor.h \
|
||||||
pta_double.h \
|
pta_double.h \
|
||||||
pta_float.h pta_int.h pta_ushort.h \
|
pta_float.h pta_int.h pta_ushort.h \
|
||||||
|
sparseArray.I sparseArray.h \
|
||||||
string_utils.I \
|
string_utils.I \
|
||||||
string_utils.h timedCycle.I timedCycle.h typedWritable.I \
|
string_utils.h timedCycle.I timedCycle.h typedWritable.I \
|
||||||
typedWritable.h typedWritableReferenceCount.I \
|
typedWritable.h typedWritableReferenceCount.I \
|
||||||
|
@ -17,9 +17,31 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "bitArray.h"
|
#include "bitArray.h"
|
||||||
|
#include "sparseArray.h"
|
||||||
|
|
||||||
TypeHandle BitArray::_type_handle;
|
TypeHandle BitArray::_type_handle;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BitArray::Constructor (from SparseArray)
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
BitArray::
|
||||||
|
BitArray(const SparseArray &from) {
|
||||||
|
_highest_bits = 0;
|
||||||
|
|
||||||
|
int num_subranges = from.get_num_subranges();
|
||||||
|
for (int i = 0; i < num_subranges; ++i) {
|
||||||
|
int begin = from.get_subrange_begin(i);
|
||||||
|
int end = from.get_subrange_end(i);
|
||||||
|
set_range(begin, end - begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from.is_inverse()) {
|
||||||
|
invert_in_place();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: BitArray::is_zero
|
// Function: BitArray::is_zero
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -37,13 +59,148 @@ is_zero() const {
|
|||||||
// Start from the high end, since that's more likely to be nonzero.
|
// Start from the high end, since that's more likely to be nonzero.
|
||||||
Array::reverse_iterator ai;
|
Array::reverse_iterator ai;
|
||||||
for (ai = _array.rbegin(); ai != _array.rend(); ++ai) {
|
for (ai = _array.rbegin(); ai != _array.rend(); ++ai) {
|
||||||
if ((*ai) != 0) {
|
if (!(*ai).is_zero()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BitArray::is_all_on
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if the entire bitmask is one, false
|
||||||
|
// otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool BitArray::
|
||||||
|
is_all_on() const {
|
||||||
|
if (!_highest_bits) {
|
||||||
|
// If all the infinite highest bits are not set, certainly the
|
||||||
|
// bitmask is not all on.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array::reverse_iterator ai;
|
||||||
|
for (ai = _array.rbegin(); ai != _array.rend(); ++ai) {
|
||||||
|
if (!(*ai).is_all_on()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BitArray::has_any_of
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if any bit in the indicated range is
|
||||||
|
// set, false otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool BitArray::
|
||||||
|
has_any_of(int low_bit, int size) const {
|
||||||
|
if ((low_bit + size - 1) / num_bits_per_word >= get_num_words()) {
|
||||||
|
// This range touches the highest bits.
|
||||||
|
if (_highest_bits) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int w = low_bit / num_bits_per_word;
|
||||||
|
int b = low_bit % num_bits_per_word;
|
||||||
|
|
||||||
|
if (w >= get_num_words()) {
|
||||||
|
// This range is entirely among the highest bits.
|
||||||
|
return _highest_bits;
|
||||||
|
}
|
||||||
|
if (b + size <= num_bits_per_word) {
|
||||||
|
// The whole thing fits within one word of the array.
|
||||||
|
return get_word(w).has_any_of(b, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_high_bits = num_bits_per_word - b;
|
||||||
|
if (_array[w].has_any_of(b, num_high_bits)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
size -= num_high_bits;
|
||||||
|
++w;
|
||||||
|
|
||||||
|
while (size > 0) {
|
||||||
|
if (size <= num_bits_per_word) {
|
||||||
|
// The remainder fits within one word of the array.
|
||||||
|
return _array[w].has_any_of(0, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep going.
|
||||||
|
if (!_array[w].is_zero()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
size -= num_bits_per_word;
|
||||||
|
++w;
|
||||||
|
|
||||||
|
if (w >= get_num_words()) {
|
||||||
|
// Now we're up to the highest bits.
|
||||||
|
return _highest_bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BitArray::has_all_of
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if all bits in the indicated range are
|
||||||
|
// set, false otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool BitArray::
|
||||||
|
has_all_of(int low_bit, int size) const {
|
||||||
|
if ((low_bit + size - 1) / num_bits_per_word >= get_num_words()) {
|
||||||
|
// This range touches the highest bits.
|
||||||
|
if (!_highest_bits) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int w = low_bit / num_bits_per_word;
|
||||||
|
int b = low_bit % num_bits_per_word;
|
||||||
|
|
||||||
|
if (w >= get_num_words()) {
|
||||||
|
// This range is entirely among the highest bits.
|
||||||
|
return _highest_bits;
|
||||||
|
}
|
||||||
|
if (b + size <= num_bits_per_word) {
|
||||||
|
// The whole thing fits within one word of the array.
|
||||||
|
return get_word(w).has_all_of(b, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_high_bits = num_bits_per_word - b;
|
||||||
|
if (!_array[w].has_all_of(b, num_high_bits)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
size -= num_high_bits;
|
||||||
|
++w;
|
||||||
|
|
||||||
|
while (size > 0) {
|
||||||
|
if (size <= num_bits_per_word) {
|
||||||
|
// The remainder fits within one word of the array.
|
||||||
|
return _array[w].has_all_of(0, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep going.
|
||||||
|
if (!_array[w].is_all_on()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
size -= num_bits_per_word;
|
||||||
|
++w;
|
||||||
|
|
||||||
|
if (w >= get_num_words()) {
|
||||||
|
// Now we're up to the highest bits.
|
||||||
|
return _highest_bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: BitArray::set_range
|
// Function: BitArray::set_range
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
#include "checksumHashGenerator.h"
|
#include "checksumHashGenerator.h"
|
||||||
|
|
||||||
|
class SparseArray;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : BitArray
|
// Class : BitArray
|
||||||
// Description : A dynamic array with an unlimited number of bits.
|
// Description : A dynamic array with an unlimited number of bits.
|
||||||
@ -44,11 +46,11 @@ public:
|
|||||||
enum { num_bits_per_word = MaskType::num_bits };
|
enum { num_bits_per_word = MaskType::num_bits };
|
||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
|
|
||||||
INLINE BitArray();
|
INLINE BitArray();
|
||||||
INLINE BitArray(WordType init_value);
|
INLINE BitArray(WordType init_value);
|
||||||
INLINE BitArray(const BitArray ©);
|
INLINE BitArray(const BitArray ©);
|
||||||
INLINE BitArray &operator = (const BitArray ©);
|
INLINE BitArray &operator = (const BitArray ©);
|
||||||
|
BitArray(const SparseArray &from);
|
||||||
|
|
||||||
INLINE static BitArray all_on();
|
INLINE static BitArray all_on();
|
||||||
INLINE static BitArray all_off();
|
INLINE static BitArray all_off();
|
||||||
@ -69,9 +71,12 @@ PUBLISHED:
|
|||||||
INLINE void set_bit_to(int index, bool value);
|
INLINE void set_bit_to(int index, bool value);
|
||||||
INLINE bool get_highest_bits() const;
|
INLINE bool get_highest_bits() const;
|
||||||
bool is_zero() const;
|
bool is_zero() const;
|
||||||
|
bool is_all_on() const;
|
||||||
|
|
||||||
INLINE WordType extract(int low_bit, int size) const;
|
INLINE WordType extract(int low_bit, int size) const;
|
||||||
INLINE void store(WordType value, int low_bit, int size);
|
INLINE void store(WordType value, int low_bit, int size);
|
||||||
|
bool has_any_of(int low_bit, int size) const;
|
||||||
|
bool has_all_of(int low_bit, int size) const;
|
||||||
void set_range(int low_bit, int size);
|
void set_range(int low_bit, int size);
|
||||||
void clear_range(int low_bit, int size);
|
void clear_range(int low_bit, int size);
|
||||||
INLINE void set_range_to(bool value, int low_bit, int size);
|
INLINE void set_range_to(bool value, int low_bit, int size);
|
||||||
|
@ -273,6 +273,18 @@ is_zero() const {
|
|||||||
return (_word == 0);
|
return (_word == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BitMask::is_all_on
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if the entire bitmask is one, false
|
||||||
|
// otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
template<class WType, int nbits>
|
||||||
|
INLINE bool BitMask<WType, nbits>::
|
||||||
|
is_all_on() const {
|
||||||
|
return (~_word == 0);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: BitMask::extract
|
// Function: BitMask::extract
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -300,6 +312,32 @@ store(WordType value, int low_bit, int size) {
|
|||||||
_word = (_word & ~mask) | ((value << low_bit) & mask);
|
_word = (_word & ~mask) | ((value << low_bit) & mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BitMask::has_any_of
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if any bit in the indicated range is
|
||||||
|
// set, false otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
template<class WType, int nbits>
|
||||||
|
INLINE bool BitMask<WType, nbits>::
|
||||||
|
has_any_of(int low_bit, int size) const {
|
||||||
|
WordType mask = BitMask<WType, nbits>::range(low_bit, size)._word;
|
||||||
|
return (_word & mask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BitMask::has_all_of
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if all bits in the indicated range are
|
||||||
|
// set, false otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
template<class WType, int nbits>
|
||||||
|
INLINE bool BitMask<WType, nbits>::
|
||||||
|
has_all_of(int low_bit, int size) const {
|
||||||
|
WordType mask = BitMask<WType, nbits>::range(low_bit, size)._word;
|
||||||
|
return (_word & mask) == mask;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: BitMask::set_range
|
// Function: BitMask::set_range
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -64,9 +64,12 @@ PUBLISHED:
|
|||||||
INLINE void clear_bit(int index);
|
INLINE void clear_bit(int index);
|
||||||
INLINE void set_bit_to(int index, bool value);
|
INLINE void set_bit_to(int index, bool value);
|
||||||
INLINE bool is_zero() const;
|
INLINE bool is_zero() const;
|
||||||
|
INLINE bool is_all_on() const;
|
||||||
|
|
||||||
INLINE WordType extract(int low_bit, int size) const;
|
INLINE WordType extract(int low_bit, int size) const;
|
||||||
INLINE void store(WordType value, int low_bit, int size);
|
INLINE void store(WordType value, int low_bit, int size);
|
||||||
|
INLINE bool has_any_of(int low_bit, int size) const;
|
||||||
|
INLINE bool has_all_of(int low_bit, int size) const;
|
||||||
INLINE void set_range(int low_bit, int size);
|
INLINE void set_range(int low_bit, int size);
|
||||||
INLINE void clear_range(int low_bit, int size);
|
INLINE void clear_range(int low_bit, int size);
|
||||||
INLINE void set_range_to(bool value, int low_bit, int size);
|
INLINE void set_range_to(bool value, int low_bit, int size);
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "namable.h"
|
#include "namable.h"
|
||||||
#include "nodeCachedReferenceCount.h"
|
#include "nodeCachedReferenceCount.h"
|
||||||
#include "referenceCount.h"
|
#include "referenceCount.h"
|
||||||
|
#include "sparseArray.h"
|
||||||
#include "typedObject.h"
|
#include "typedObject.h"
|
||||||
#include "typedReferenceCount.h"
|
#include "typedReferenceCount.h"
|
||||||
#include "typedWritable.h"
|
#include "typedWritable.h"
|
||||||
@ -94,6 +95,7 @@ ConfigureFn(config_util) {
|
|||||||
Namable::init_type();
|
Namable::init_type();
|
||||||
NodeCachedReferenceCount::init_type();
|
NodeCachedReferenceCount::init_type();
|
||||||
ReferenceCount::init_type();
|
ReferenceCount::init_type();
|
||||||
|
SparseArray::init_type();
|
||||||
TypedObject::init_type();
|
TypedObject::init_type();
|
||||||
TypedReferenceCount::init_type();
|
TypedReferenceCount::init_type();
|
||||||
TypedWritable::init_type();
|
TypedWritable::init_type();
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "pta_float.cxx"
|
#include "pta_float.cxx"
|
||||||
#include "pta_int.cxx"
|
#include "pta_int.cxx"
|
||||||
#include "pta_ushort.cxx"
|
#include "pta_ushort.cxx"
|
||||||
|
#include "sparseArray.cxx"
|
||||||
#include "string_utils.cxx"
|
#include "string_utils.cxx"
|
||||||
#include "timedCycle.cxx"
|
#include "timedCycle.cxx"
|
||||||
#include "typedWritable.cxx"
|
#include "typedWritable.cxx"
|
||||||
|
578
panda/src/putil/sparseArray.I
Normal file
578
panda/src/putil/sparseArray.I
Normal file
@ -0,0 +1,578 @@
|
|||||||
|
// Filename: sparseArray.I
|
||||||
|
// Created by: drose (14Feb07)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the Panda 3d
|
||||||
|
// Software license. You should have received a copy of this license
|
||||||
|
// along with this source code; you will also find a current copy of
|
||||||
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||||
|
//
|
||||||
|
// To contact the maintainers of this program write to
|
||||||
|
// panda3d-general@lists.sourceforge.net .
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::Constructor
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray::
|
||||||
|
SparseArray() : _inverse(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::Copy Constructor
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray::
|
||||||
|
SparseArray(const SparseArray ©) :
|
||||||
|
_subranges(copy._subranges),
|
||||||
|
_inverse(copy._inverse)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::Copy Assignment Operator
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray &SparseArray::
|
||||||
|
operator = (const SparseArray ©) {
|
||||||
|
_subranges = copy._subranges;
|
||||||
|
_inverse = copy._inverse;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::Named all_on constructor
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Returns a SparseArray with an infinite array of bits,
|
||||||
|
// all on.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray SparseArray::
|
||||||
|
all_on() {
|
||||||
|
SparseArray result;
|
||||||
|
result._inverse = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::Named all_on constructor
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Returns a SparseArray whose bits are all off.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray SparseArray::
|
||||||
|
all_off() {
|
||||||
|
return SparseArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::Named lower_on constructor
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Returns a SparseArray whose lower on_bits bits are on.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray SparseArray::
|
||||||
|
lower_on(int on_bits) {
|
||||||
|
SparseArray result;
|
||||||
|
result.set_range(0, on_bits);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::Named bit constructor
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Returns a SparseArray with only the indicated bit on.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray SparseArray::
|
||||||
|
bit(int index) {
|
||||||
|
SparseArray result;
|
||||||
|
result.set_bit(index);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::Named range constructor
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Returns a SparseArray whose size bits, beginning at
|
||||||
|
// low_bit, are on.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray SparseArray::
|
||||||
|
range(int low_bit, int size) {
|
||||||
|
SparseArray result;
|
||||||
|
result.set_range(low_bit, size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::Destructor
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray::
|
||||||
|
~SparseArray() {
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::has_max_num_bits
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Returns true if there is a maximum number of bits
|
||||||
|
// that may be stored in this structure, false
|
||||||
|
// otherwise. If this returns true, the number may be
|
||||||
|
// queried in get_max_num_bits().
|
||||||
|
//
|
||||||
|
// This method always returns false. The SparseArray has
|
||||||
|
// no maximum number of bits. This method is defined so
|
||||||
|
// generic programming algorithms can use BitMask or
|
||||||
|
// SparseArray interchangeably.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool SparseArray::
|
||||||
|
has_max_num_bits() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::get_max_num_bits
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: If get_max_num_bits() returned true, this method may
|
||||||
|
// be called to return the maximum number of bits that
|
||||||
|
// may be stored in this structure. It is an error to
|
||||||
|
// call this if get_max_num_bits() return false.
|
||||||
|
//
|
||||||
|
// It is always an error to call this method. The
|
||||||
|
// SparseArray has no maximum number of bits. This method
|
||||||
|
// is defined so generic programming algorithms can use
|
||||||
|
// BitMask or SparseArray interchangeably.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE int SparseArray::
|
||||||
|
get_max_num_bits() {
|
||||||
|
nassertr(false, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::get_num_bits
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the current number of possibly different bits
|
||||||
|
// in this array. There are actually an infinite number
|
||||||
|
// of bits, but every bit higher than this bit will have
|
||||||
|
// the same value, either 0 or 1 (see
|
||||||
|
// get_highest_bits()).
|
||||||
|
//
|
||||||
|
// This number may grow and/or shrink automatically as
|
||||||
|
// needed.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE int SparseArray::
|
||||||
|
get_num_bits() const {
|
||||||
|
if (_subranges.empty()) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
Subranges::const_iterator si = _subranges.begin() + _subranges.size() - 1;
|
||||||
|
return (*si)._end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::get_bit
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if the nth bit is set, false if it is
|
||||||
|
// cleared. It is valid for n to increase beyond
|
||||||
|
// get_num_bits(), but the return value get_num_bits()
|
||||||
|
// will always be the same.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool SparseArray::
|
||||||
|
get_bit(int index) const {
|
||||||
|
return has_any_of(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::set_bit
|
||||||
|
// Access: Published
|
||||||
|
// Description: Sets the nth bit on. If n >= get_num_bits(), this
|
||||||
|
// automatically extends the array.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void SparseArray::
|
||||||
|
set_bit(int index) {
|
||||||
|
set_range(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::clear_bit
|
||||||
|
// Access: Published
|
||||||
|
// Description: Sets the nth bit off. If n >= get_num_bits(), this
|
||||||
|
// automatically extends the array.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void SparseArray::
|
||||||
|
clear_bit(int index) {
|
||||||
|
clear_range(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::set_bit_to
|
||||||
|
// Access: Published
|
||||||
|
// Description: Sets the nth bit either on or off, according to the
|
||||||
|
// indicated bool value.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void SparseArray::
|
||||||
|
set_bit_to(int index, bool value) {
|
||||||
|
if (value) {
|
||||||
|
set_bit(index);
|
||||||
|
} else {
|
||||||
|
clear_bit(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::get_highest_bits
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if the infinite set of bits beyond
|
||||||
|
// get_num_bits() are all on, or false of they are all
|
||||||
|
// off.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool SparseArray::
|
||||||
|
get_highest_bits() const {
|
||||||
|
return _inverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::is_zero
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if the entire bitmask is zero, false
|
||||||
|
// otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool SparseArray::
|
||||||
|
is_zero() const {
|
||||||
|
if (_inverse) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return _subranges.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::is_all_on
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if the entire bitmask is one, false
|
||||||
|
// otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool SparseArray::
|
||||||
|
is_all_on() const {
|
||||||
|
if (_inverse) {
|
||||||
|
return _subranges.empty();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::has_any_of
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if any bit in the indicated range is
|
||||||
|
// set, false otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool SparseArray::
|
||||||
|
has_any_of(int low_bit, int size) const {
|
||||||
|
if (_inverse) {
|
||||||
|
return !do_has_all(low_bit, low_bit + size);
|
||||||
|
} else {
|
||||||
|
return do_has_any(low_bit, low_bit + size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::has_all_of
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if all bits in the indicated range are
|
||||||
|
// set, false otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool SparseArray::
|
||||||
|
has_all_of(int low_bit, int size) const {
|
||||||
|
if (_inverse) {
|
||||||
|
return !do_has_any(low_bit, low_bit + size);
|
||||||
|
} else {
|
||||||
|
return do_has_all(low_bit, low_bit + size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::set_range
|
||||||
|
// Access: Published
|
||||||
|
// Description: Sets the indicated range of bits on.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void SparseArray::
|
||||||
|
set_range(int low_bit, int size) {
|
||||||
|
if (_inverse) {
|
||||||
|
return do_remove_range(low_bit, low_bit + size);
|
||||||
|
} else {
|
||||||
|
return do_add_range(low_bit, low_bit + size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::clear_range
|
||||||
|
// Access: Published
|
||||||
|
// Description: Sets the indicated range of bits off.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void SparseArray::
|
||||||
|
clear_range(int low_bit, int size) {
|
||||||
|
if (_inverse) {
|
||||||
|
return do_add_range(low_bit, low_bit + size);
|
||||||
|
} else {
|
||||||
|
return do_remove_range(low_bit, low_bit + size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::set_range_to
|
||||||
|
// Access: Published
|
||||||
|
// Description: Sets the indicated range of bits to either on or off.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void SparseArray::
|
||||||
|
set_range_to(bool value, int low_bit, int size) {
|
||||||
|
if (value) {
|
||||||
|
set_range(low_bit, size);
|
||||||
|
} else {
|
||||||
|
clear_range(low_bit, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::invert_in_place
|
||||||
|
// Access: Published
|
||||||
|
// Description: Inverts all the bits in the SparseArray. This is
|
||||||
|
// equivalent to array = ~array.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
invert_in_place() {
|
||||||
|
_inverse = !_inverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::clear
|
||||||
|
// Access: Published
|
||||||
|
// Description: Sets all the bits in the SparseArray off.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
clear() {
|
||||||
|
_subranges.clear();
|
||||||
|
_inverse = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator ==
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool SparseArray::
|
||||||
|
operator == (const SparseArray &other) const {
|
||||||
|
return compare_to(other) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator !=
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool SparseArray::
|
||||||
|
operator != (const SparseArray &other) const {
|
||||||
|
return compare_to(other) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator <
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if the unsigned integer which is
|
||||||
|
// represented by this SparseArray is less than that of the
|
||||||
|
// other one, false otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool SparseArray::
|
||||||
|
operator < (const SparseArray &other) const {
|
||||||
|
return compare_to(other) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator &
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray SparseArray::
|
||||||
|
operator & (const SparseArray &other) const {
|
||||||
|
SparseArray result(*this);
|
||||||
|
result &= other;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator |
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray SparseArray::
|
||||||
|
operator | (const SparseArray &other) const {
|
||||||
|
SparseArray result(*this);
|
||||||
|
result |= other;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator ^
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray SparseArray::
|
||||||
|
operator ^ (const SparseArray &other) const {
|
||||||
|
SparseArray result(*this);
|
||||||
|
result ^= other;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator ~
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray SparseArray::
|
||||||
|
operator ~ () const {
|
||||||
|
SparseArray result(*this);
|
||||||
|
result.invert_in_place();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator <<
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray SparseArray::
|
||||||
|
operator << (int shift) const {
|
||||||
|
SparseArray result(*this);
|
||||||
|
result <<= shift;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator >>
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray SparseArray::
|
||||||
|
operator >> (int shift) const {
|
||||||
|
SparseArray result(*this);
|
||||||
|
result >>= shift;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator <<=
|
||||||
|
// Access: Published
|
||||||
|
// Description: Logical left shift. Since negative bit positions
|
||||||
|
// have meaning in a SparseArray, real bit values are
|
||||||
|
// rotated in on the left (not necessarily zero).
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
operator <<= (int shift) {
|
||||||
|
do_shift(shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator >>=
|
||||||
|
// Access: Published
|
||||||
|
// Description: Logical right shift. The rightmost bits become
|
||||||
|
// negative, but are not lost; they will reappear into
|
||||||
|
// the zero position if the array is later left-shifted.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
operator >>= (int shift) {
|
||||||
|
do_shift(-shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::is_inverse
|
||||||
|
// Access: Published
|
||||||
|
// Description: If this is true, the SparseArray is actually defined
|
||||||
|
// as a list of subranges of integers that are *not* in
|
||||||
|
// the set. If this is false (the default), then the
|
||||||
|
// subranges define the integers that *are* in the set.
|
||||||
|
// This affects the interpretation of the values
|
||||||
|
// returned by iterating through get_num_subranges().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool SparseArray::
|
||||||
|
is_inverse() const {
|
||||||
|
return _inverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::get_num_subranges
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the number of separate subranges stored in
|
||||||
|
// the SparseArray. You can use this limit to iterate
|
||||||
|
// through the subranges, calling get_subrange_begin()
|
||||||
|
// and get_subrange_end() for each one.
|
||||||
|
//
|
||||||
|
// Also see is_inverse().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE int SparseArray::
|
||||||
|
get_num_subranges() const {
|
||||||
|
return _subranges.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::get_subrange_begin
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the first numeric element in the nth
|
||||||
|
// subrange.
|
||||||
|
//
|
||||||
|
// Also see is_inverse().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE int SparseArray::
|
||||||
|
get_subrange_begin(int n) const {
|
||||||
|
nassertr(n >= 0 && n < (int)_subranges.size(), 0);
|
||||||
|
return _subranges[n]._begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::get_subrange_end
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the last numeric element, plus one, in the
|
||||||
|
// nth subrange.
|
||||||
|
//
|
||||||
|
// Also see is_inverse().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE int SparseArray::
|
||||||
|
get_subrange_end(int n) const {
|
||||||
|
nassertr(n >= 0 && n < (int)_subranges.size(), 0);
|
||||||
|
return _subranges[n]._end;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::Subrange::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SparseArray::Subrange::
|
||||||
|
Subrange(int begin, int end) :
|
||||||
|
_begin(begin),
|
||||||
|
_end(end)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::Subrange::operator <
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool SparseArray::Subrange::
|
||||||
|
operator < (const SparseArray::Subrange &other) const {
|
||||||
|
// We compare the end values, rather than the begin values, to make
|
||||||
|
// lower_bound() sensibly return a possible intersection with the
|
||||||
|
// indicated Subrange.
|
||||||
|
return _end < other._end;
|
||||||
|
}
|
||||||
|
|
517
panda/src/putil/sparseArray.cxx
Normal file
517
panda/src/putil/sparseArray.cxx
Normal file
@ -0,0 +1,517 @@
|
|||||||
|
// Filename: sparseArray.cxx
|
||||||
|
// Created by: drose (14Feb07)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the Panda 3d
|
||||||
|
// Software license. You should have received a copy of this license
|
||||||
|
// along with this source code; you will also find a current copy of
|
||||||
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||||
|
//
|
||||||
|
// To contact the maintainers of this program write to
|
||||||
|
// panda3d-general@lists.sourceforge.net .
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "sparseArray.h"
|
||||||
|
#include "bitArray.h"
|
||||||
|
|
||||||
|
TypeHandle SparseArray::_type_handle;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::Constructor (from BitArray)
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
SparseArray::
|
||||||
|
SparseArray(const BitArray &from) {
|
||||||
|
bool empty_bit = from.get_highest_bits();
|
||||||
|
_inverse = empty_bit;
|
||||||
|
|
||||||
|
int begin = 0;
|
||||||
|
bool current_state = from.get_bit(0);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
// By including get_num_bits()--one more than the last bit--in this
|
||||||
|
// traversal, we guarantee that we will end on the empty_bit state
|
||||||
|
// (because the last bit we visit will be one of the highest_bits).
|
||||||
|
while (i <= from.get_num_bits()) {
|
||||||
|
if (from.get_bit(i) != current_state) {
|
||||||
|
// End of a run.
|
||||||
|
if (current_state != empty_bit) {
|
||||||
|
Subrange range(begin, i);
|
||||||
|
_subranges.push_back(range);
|
||||||
|
}
|
||||||
|
begin = i;
|
||||||
|
current_state = !current_state;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
nassertv(current_state == empty_bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::has_bits_in_common
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if this SparseArray has any "one" bits in
|
||||||
|
// common with the other one, false otherwise.
|
||||||
|
//
|
||||||
|
// This is equivalent to (array & other) != 0, but may
|
||||||
|
// be faster.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool SparseArray::
|
||||||
|
has_bits_in_common(const SparseArray &other) const {
|
||||||
|
if (_inverse && other._inverse) {
|
||||||
|
// Yup, in fact we have an infinite number of bits in common.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_inverse != other._inverse) {
|
||||||
|
// We'll handle this tricky case the lazy way.
|
||||||
|
return !(*this & other).is_zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actually, we'll handle this easy case the lazy way too. Maybe
|
||||||
|
// later we'll do this smarter.
|
||||||
|
return !(*this & other).is_zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::output
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
output(ostream &out) const {
|
||||||
|
out << "[ ";
|
||||||
|
if (_inverse) {
|
||||||
|
out << "all except: ";
|
||||||
|
}
|
||||||
|
Subranges::const_iterator si;
|
||||||
|
for (si = _subranges.begin(); si != _subranges.end(); ++si) {
|
||||||
|
if ((*si)._end == (*si)._begin + 1) {
|
||||||
|
// A single element.
|
||||||
|
out << (*si)._begin << ", ";
|
||||||
|
} else {
|
||||||
|
// A range of elements.
|
||||||
|
out << (*si)._begin << "-" << ((*si)._end - 1) << ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::compare_to
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns a number less than zero if this SparseArray
|
||||||
|
// sorts before the indicated other SparseArray, greater
|
||||||
|
// than zero if it sorts after, or 0 if they are
|
||||||
|
// equivalent. This is based on the same ordering
|
||||||
|
// defined by operator <.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int SparseArray::
|
||||||
|
compare_to(const SparseArray &other) const {
|
||||||
|
if (_inverse != other._inverse) {
|
||||||
|
return _inverse ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Subranges::const_reverse_iterator ai = _subranges.rbegin();
|
||||||
|
Subranges::const_reverse_iterator bi = other._subranges.rbegin();
|
||||||
|
|
||||||
|
while (ai != _subranges.rend() && bi != other._subranges.rend()) {
|
||||||
|
if ((*ai)._end < (*bi)._end) {
|
||||||
|
// B is higher.
|
||||||
|
return -1;
|
||||||
|
} else if ((*bi)._end < (*ai)._end) {
|
||||||
|
// A is higher.
|
||||||
|
return 1;
|
||||||
|
} else if ((*ai)._begin < (*bi)._begin) {
|
||||||
|
// A is higher.
|
||||||
|
return 1;
|
||||||
|
} else if ((*bi)._begin < (*ai)._begin) {
|
||||||
|
// B is higher.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
--ai;
|
||||||
|
--bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ai != _subranges.rend()) {
|
||||||
|
// A is higher.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (bi != other._subranges.rend()) {
|
||||||
|
// B is higher.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator &=
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
operator &= (const SparseArray &other) {
|
||||||
|
// We do this the slow and stupid way. This could be done much
|
||||||
|
// better with a little effort, but I'm not at all sure it's worth
|
||||||
|
// the effort. If you need fast boolean operations, you should
|
||||||
|
// probably be using a BitArray.
|
||||||
|
|
||||||
|
if (_inverse && other._inverse) {
|
||||||
|
do_union(other);
|
||||||
|
|
||||||
|
} else if (!_inverse && !other._inverse) {
|
||||||
|
do_intersection(other);
|
||||||
|
|
||||||
|
} else if (_inverse && !other._inverse) {
|
||||||
|
// a & b == b & a
|
||||||
|
(*this) = other & (*this);
|
||||||
|
|
||||||
|
} else if (!_inverse && other._inverse) {
|
||||||
|
do_intersection_neg(other);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// TODO.
|
||||||
|
nassertv(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator |=
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
operator |= (const SparseArray &other) {
|
||||||
|
// We do this the slow and stupid way. This could be done much
|
||||||
|
// better with a little effort, but I'm not at all sure it's worth
|
||||||
|
// the effort. If you need fast boolean operations, you should
|
||||||
|
// probably be using a BitArray.
|
||||||
|
|
||||||
|
if (_inverse && other._inverse) {
|
||||||
|
do_intersection(other);
|
||||||
|
|
||||||
|
} else if (!_inverse && !other._inverse) {
|
||||||
|
do_union(other);
|
||||||
|
|
||||||
|
} else if (_inverse && !other._inverse) {
|
||||||
|
do_intersection_neg(other);
|
||||||
|
|
||||||
|
} else if (!_inverse && other._inverse) {
|
||||||
|
// a | b == b | a
|
||||||
|
(*this) = other | (*this);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
nassertv(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::operator ^=
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
operator ^= (const SparseArray &other) {
|
||||||
|
// We do this the slow and stupid way. This could be done much
|
||||||
|
// better with a little effort, but I'm not at all sure it's worth
|
||||||
|
// the effort. If you need fast boolean operations, you should
|
||||||
|
// probably be using a BitArray.
|
||||||
|
|
||||||
|
(*this) = ((*this) | other) & ~((*this) & other);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::do_add_range
|
||||||
|
// Access: Private
|
||||||
|
// Description: Adds the consecutive range of integers beginning at
|
||||||
|
// begin, but not including end, to the array. If this
|
||||||
|
// range overlaps with another range already in the
|
||||||
|
// array, the result is the union.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
do_add_range(int begin, int end) {
|
||||||
|
if (begin >= end) {
|
||||||
|
// Empty range.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Subrange range(begin, end);
|
||||||
|
Subranges::iterator si = _subranges.lower_bound(range);
|
||||||
|
if (si == _subranges.end()) {
|
||||||
|
if (!_subranges.empty()) {
|
||||||
|
si = _subranges.begin() + _subranges.size() - 1;
|
||||||
|
if ((*si)._end >= begin) {
|
||||||
|
// The new range expands the last element of the array to the right.
|
||||||
|
(*si)._end = end;
|
||||||
|
// It might also expand it to the left; fall through.
|
||||||
|
} else {
|
||||||
|
// The new range is completely after the last element of the array.
|
||||||
|
_subranges.push_back(range);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// The new range is completely after the last element of the array.
|
||||||
|
_subranges.push_back(range);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nassertv((*si)._end >= end);
|
||||||
|
|
||||||
|
if ((*si)._begin > end) {
|
||||||
|
if (si != _subranges.begin()) {
|
||||||
|
Subranges::iterator si2 = si;
|
||||||
|
--si2;
|
||||||
|
if ((*si2)._end >= begin) {
|
||||||
|
// The new range expands an element within the array to the
|
||||||
|
// right (but does not intersect the next element).
|
||||||
|
(*si2)._end = end;
|
||||||
|
// It might also expand it to the left; fall through.
|
||||||
|
si = si2;
|
||||||
|
} else {
|
||||||
|
// The new range does not intersect any elements in the array.
|
||||||
|
_subranges.insert_unverified(si, range);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The new range does not intersect any elements in the array.
|
||||||
|
_subranges.insert_unverified(si, range);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the new range overlaps with any elements to the left.
|
||||||
|
while (si != _subranges.begin()) {
|
||||||
|
Subranges::iterator si2 = si;
|
||||||
|
--si2;
|
||||||
|
if ((*si2)._end >= begin) {
|
||||||
|
// The new range straddles two elements, so they get combined.
|
||||||
|
(*si2)._end = (*si)._end;
|
||||||
|
_subranges.erase(si);
|
||||||
|
}
|
||||||
|
si = si2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*si)._begin > begin) {
|
||||||
|
// The new range expands an element to the left.
|
||||||
|
(*si)._begin = begin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::do_remove_range
|
||||||
|
// Access: Private
|
||||||
|
// Description: Removes the consecutive range of integers beginning
|
||||||
|
// at begin, but not including end, from the array.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
do_remove_range(int begin, int end) {
|
||||||
|
if (begin >= end) {
|
||||||
|
// Empty range.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Subrange range(begin, end);
|
||||||
|
Subranges::iterator si = _subranges.lower_bound(range);
|
||||||
|
if (si == _subranges.end()) {
|
||||||
|
if (!_subranges.empty()) {
|
||||||
|
si = _subranges.begin() + _subranges.size() - 1;
|
||||||
|
if ((*si)._end >= begin) {
|
||||||
|
// The new range shortens the last element of the array on the right.
|
||||||
|
end = min(end, (*si)._begin);
|
||||||
|
(*si)._end = end;
|
||||||
|
// It might also shorten it on the left; fall through.
|
||||||
|
} else {
|
||||||
|
// The new range is completely after the last element of the array.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// The new range is completely after the last element of the array.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nassertv((*si)._end >= end);
|
||||||
|
|
||||||
|
if ((*si)._begin > end) {
|
||||||
|
if (si != _subranges.begin()) {
|
||||||
|
Subranges::iterator si2 = si;
|
||||||
|
--si2;
|
||||||
|
if ((*si2)._end >= begin) {
|
||||||
|
// The new range shortens an element within the array on the
|
||||||
|
// right (but does not intersect the next element).
|
||||||
|
end = min(end, (*si2)._begin);
|
||||||
|
(*si2)._end = end;
|
||||||
|
// It might also shorten it on the left; fall through.
|
||||||
|
si = si2;
|
||||||
|
} else {
|
||||||
|
// The new range does not intersect any elements in the array.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The new range does not intersect any elements in the array.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (end < (*si)._end) {
|
||||||
|
// We must split an element into two.
|
||||||
|
Subrange left_range((*si)._begin, begin);
|
||||||
|
(*si)._begin = end;
|
||||||
|
si = _subranges.insert_unverified(si, left_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the new range removes any elements to the left.
|
||||||
|
while (begin <= (*si)._begin) {
|
||||||
|
if (si == _subranges.begin()) {
|
||||||
|
_subranges.erase(si);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Subranges::iterator si2 = si;
|
||||||
|
--si2;
|
||||||
|
_subranges.erase(si);
|
||||||
|
si = si2;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*si)._end = min((*si)._end, begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::do_has_any
|
||||||
|
// Access: Private
|
||||||
|
// Description: Returns true if any of the consecutive range of
|
||||||
|
// integers beginning at begin, but not including end,
|
||||||
|
// appear in the array. Note that this will return
|
||||||
|
// false for an empty range.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool SparseArray::
|
||||||
|
do_has_any(int begin, int end) const {
|
||||||
|
if (begin >= end) {
|
||||||
|
// Empty range.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Subrange range(begin, end);
|
||||||
|
Subranges::const_iterator si = _subranges.lower_bound(range);
|
||||||
|
if (si != _subranges.end() && end > (*si)._begin) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (si != _subranges.begin()) {
|
||||||
|
--si;
|
||||||
|
if (begin < (*si)._end) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::do_has_all
|
||||||
|
// Access: Private
|
||||||
|
// Description: Returns true if all of the consecutive range of
|
||||||
|
// integers beginning at begin, but not including end,
|
||||||
|
// appear in the array. Note that this will return
|
||||||
|
// true for an empty range.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool SparseArray::
|
||||||
|
do_has_all(int begin, int end) const {
|
||||||
|
if (begin >= end) {
|
||||||
|
// Empty range.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Subrange range(begin, end);
|
||||||
|
Subranges::const_iterator si = _subranges.lower_bound(range);
|
||||||
|
if (si != _subranges.end() && begin >= (*si)._begin) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::do_intersection
|
||||||
|
// Access: Private
|
||||||
|
// Description: Removes from this array all of the elements that do
|
||||||
|
// not appear in the other one.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
do_intersection(const SparseArray &other) {
|
||||||
|
if (_subranges.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (other._subranges.empty()) {
|
||||||
|
_subranges.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int my_begin = (*_subranges.begin())._begin;
|
||||||
|
int other_begin = (*other._subranges.begin())._begin;
|
||||||
|
do_remove_range(my_begin, other_begin);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < other._subranges.size() - 1; ++i) {
|
||||||
|
do_remove_range(other._subranges[i]._end, other._subranges[i + 1]._begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
int my_end = (*(_subranges.begin() + _subranges.size() - 1))._end;
|
||||||
|
int other_end = (*(other._subranges.begin() + other._subranges.size() - 1))._end;
|
||||||
|
do_remove_range(other_end, my_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::do_union
|
||||||
|
// Access: Private
|
||||||
|
// Description: Adds to this array all of the elements that also
|
||||||
|
// appear in the other one.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
do_union(const SparseArray &other) {
|
||||||
|
Subranges::const_iterator si;
|
||||||
|
for (si = other._subranges.begin(); si != other._subranges.end(); ++si) {
|
||||||
|
do_add_range((*si)._begin, (*si)._end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::do_intersection_neg
|
||||||
|
// Access: Private
|
||||||
|
// Description: Removes from this array all of the elements that also
|
||||||
|
// appear in the other one.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
do_intersection_neg(const SparseArray &other) {
|
||||||
|
Subranges::const_iterator si;
|
||||||
|
for (si = other._subranges.begin(); si != other._subranges.end(); ++si) {
|
||||||
|
do_remove_range((*si)._begin, (*si)._end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SparseArray::do_shift
|
||||||
|
// Access: Private
|
||||||
|
// Description: Shifts all the elements in the array by the indicated
|
||||||
|
// amount.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void SparseArray::
|
||||||
|
do_shift(int offset) {
|
||||||
|
if (offset != 0) {
|
||||||
|
Subranges::iterator si;
|
||||||
|
for (si = _subranges.begin(); si != _subranges.end(); ++si) {
|
||||||
|
(*si)._begin += offset;
|
||||||
|
(*si)._end += offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
168
panda/src/putil/sparseArray.h
Normal file
168
panda/src/putil/sparseArray.h
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
// Filename: sparseArray.h
|
||||||
|
// Created by: drose (14Feb07)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the Panda 3d
|
||||||
|
// Software license. You should have received a copy of this license
|
||||||
|
// along with this source code; you will also find a current copy of
|
||||||
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||||
|
//
|
||||||
|
// To contact the maintainers of this program write to
|
||||||
|
// panda3d-general@lists.sourceforge.net .
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SPARSEARRAY_H
|
||||||
|
#define SPARSEARRAY_H
|
||||||
|
|
||||||
|
#include "pandabase.h"
|
||||||
|
#include "ordered_vector.h"
|
||||||
|
|
||||||
|
class BitArray;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Class : SparseArray
|
||||||
|
// Description : This class records a set of integers, where each
|
||||||
|
// integer is either present or not present in the set.
|
||||||
|
//
|
||||||
|
// It is similar in principle and in interface to a
|
||||||
|
// BitArray (which can be thought of as a set of
|
||||||
|
// integers, one integer corresponding to each different
|
||||||
|
// bit position), but the SparseArray is implemented as
|
||||||
|
// a list of min/max subrange lists, rather than as a
|
||||||
|
// bitmask.
|
||||||
|
//
|
||||||
|
// This makes it particularly efficient for storing sets
|
||||||
|
// which consist of large sections of consecutively
|
||||||
|
// included or consecutively excluded elements, with
|
||||||
|
// arbitrarily large integers, but particularly
|
||||||
|
// inefficient for doing boolean operations such as & or
|
||||||
|
// |.
|
||||||
|
//
|
||||||
|
// Also, unlike BitArray, the SparseArray can store
|
||||||
|
// negative integers.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
class EXPCL_PANDA SparseArray {
|
||||||
|
PUBLISHED:
|
||||||
|
INLINE SparseArray();
|
||||||
|
INLINE SparseArray(const SparseArray ©);
|
||||||
|
INLINE SparseArray &operator = (const SparseArray ©);
|
||||||
|
SparseArray(const BitArray &from);
|
||||||
|
|
||||||
|
INLINE static SparseArray all_on();
|
||||||
|
INLINE static SparseArray all_off();
|
||||||
|
INLINE static SparseArray lower_on(int on_bits);
|
||||||
|
INLINE static SparseArray bit(int index);
|
||||||
|
INLINE static SparseArray range(int low_bit, int size);
|
||||||
|
|
||||||
|
INLINE ~SparseArray();
|
||||||
|
|
||||||
|
INLINE static bool has_max_num_bits();
|
||||||
|
INLINE static int get_max_num_bits();
|
||||||
|
|
||||||
|
INLINE int get_num_bits() const;
|
||||||
|
INLINE bool get_bit(int index) const;
|
||||||
|
INLINE void set_bit(int index);
|
||||||
|
INLINE void clear_bit(int index);
|
||||||
|
INLINE void set_bit_to(int index, bool value);
|
||||||
|
INLINE bool get_highest_bits() const;
|
||||||
|
INLINE bool is_zero() const;
|
||||||
|
INLINE bool is_all_on() const;
|
||||||
|
|
||||||
|
INLINE bool has_any_of(int low_bit, int size) const;
|
||||||
|
INLINE bool has_all_of(int low_bit, int size) const;
|
||||||
|
INLINE void set_range(int low_bit, int size);
|
||||||
|
INLINE void clear_range(int low_bit, int size);
|
||||||
|
INLINE void set_range_to(bool value, int low_bit, int size);
|
||||||
|
|
||||||
|
INLINE void invert_in_place();
|
||||||
|
bool has_bits_in_common(const SparseArray &other) const;
|
||||||
|
INLINE void clear();
|
||||||
|
|
||||||
|
void output(ostream &out) const;
|
||||||
|
|
||||||
|
INLINE bool operator == (const SparseArray &other) const;
|
||||||
|
INLINE bool operator != (const SparseArray &other) const;
|
||||||
|
INLINE bool operator < (const SparseArray &other) const;
|
||||||
|
int compare_to(const SparseArray &other) const;
|
||||||
|
|
||||||
|
INLINE SparseArray
|
||||||
|
operator & (const SparseArray &other) const;
|
||||||
|
|
||||||
|
INLINE SparseArray
|
||||||
|
operator | (const SparseArray &other) const;
|
||||||
|
|
||||||
|
INLINE SparseArray
|
||||||
|
operator ^ (const SparseArray &other) const;
|
||||||
|
|
||||||
|
INLINE SparseArray
|
||||||
|
operator ~ () const;
|
||||||
|
|
||||||
|
INLINE SparseArray
|
||||||
|
operator << (int shift) const;
|
||||||
|
|
||||||
|
INLINE SparseArray
|
||||||
|
operator >> (int shift) const;
|
||||||
|
|
||||||
|
void operator &= (const SparseArray &other);
|
||||||
|
void operator |= (const SparseArray &other);
|
||||||
|
void operator ^= (const SparseArray &other);
|
||||||
|
INLINE void operator <<= (int shift);
|
||||||
|
INLINE void operator >>= (int shift);
|
||||||
|
|
||||||
|
INLINE bool is_inverse() const;
|
||||||
|
INLINE int get_num_subranges() const;
|
||||||
|
INLINE int get_subrange_begin(int n) const;
|
||||||
|
INLINE int get_subrange_end(int n) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void do_add_range(int begin, int end);
|
||||||
|
void do_remove_range(int begin, int end);
|
||||||
|
bool do_has_any(int begin, int end) const;
|
||||||
|
bool do_has_all(int begin, int end) const;
|
||||||
|
|
||||||
|
void do_intersection(const SparseArray &other);
|
||||||
|
void do_union(const SparseArray &other);
|
||||||
|
void do_intersection_neg(const SparseArray &other);
|
||||||
|
void do_shift(int offset);
|
||||||
|
|
||||||
|
// The SparseArray is implemented as a set of non-overlapping
|
||||||
|
// Subranges.
|
||||||
|
class Subrange {
|
||||||
|
public:
|
||||||
|
INLINE Subrange(int begin, int end);
|
||||||
|
INLINE bool operator < (const Subrange &other) const;
|
||||||
|
|
||||||
|
int _begin, _end;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef ov_set<Subrange> Subranges;
|
||||||
|
Subranges _subranges;
|
||||||
|
bool _inverse;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static TypeHandle get_class_type() {
|
||||||
|
return _type_handle;
|
||||||
|
}
|
||||||
|
static void init_type() {
|
||||||
|
register_type(_type_handle, "SparseArray");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static TypeHandle _type_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "sparseArray.I"
|
||||||
|
|
||||||
|
INLINE ostream &
|
||||||
|
operator << (ostream &out, const SparseArray &array) {
|
||||||
|
array.output(out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user