148 lines
5.5 KiB
C
148 lines
5.5 KiB
C
|
/*******************************************************************************************[Vec.h]
|
||
|
MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
|
||
|
|
||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||
|
associated documentation files (the "Software"), to deal in the Software without restriction,
|
||
|
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||
|
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||
|
furnished to do so, subject to the following conditions:
|
||
|
|
||
|
The above copyright notice and this permission notice shall be included in all copies or
|
||
|
substantial portions of the Software.
|
||
|
|
||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||
|
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||
|
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
**************************************************************************************************/
|
||
|
|
||
|
#ifndef BoxedVec_h
|
||
|
#define BoxedVec_h
|
||
|
|
||
|
#include <cstdlib>
|
||
|
#include <cassert>
|
||
|
#include <new>
|
||
|
|
||
|
//=================================================================================================
|
||
|
// Automatically resizable arrays
|
||
|
//
|
||
|
// NOTE! Don't use this vector on datatypes that cannot be re-located in memory (with realloc)
|
||
|
|
||
|
template<class T>
|
||
|
class bvec {
|
||
|
|
||
|
static inline int imin(int x, int y) {
|
||
|
int mask = (x-y) >> (sizeof(int)*8-1);
|
||
|
return (x&mask) + (y&(~mask)); }
|
||
|
|
||
|
static inline int imax(int x, int y) {
|
||
|
int mask = (y-x) >> (sizeof(int)*8-1);
|
||
|
return (x&mask) + (y&(~mask)); }
|
||
|
|
||
|
struct Vec_t {
|
||
|
int sz;
|
||
|
int cap;
|
||
|
T data[0];
|
||
|
|
||
|
static Vec_t* alloc(Vec_t* x, int size){
|
||
|
x = (Vec_t*)realloc((void*)x, sizeof(Vec_t) + sizeof(T)*size);
|
||
|
x->cap = size;
|
||
|
return x;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
Vec_t* ref;
|
||
|
|
||
|
static const int init_size = 2;
|
||
|
static int nextSize (int current) { return (current * 3 + 1) >> 1; }
|
||
|
static int fitSize (int needed) { int x; for (x = init_size; needed > x; x = nextSize(x)); return x; }
|
||
|
|
||
|
void fill (int size) {
|
||
|
assert(ref != NULL);
|
||
|
for (T* i = ref->data; i < ref->data + size; i++)
|
||
|
new (i) T();
|
||
|
}
|
||
|
|
||
|
void fill (int size, const T& pad) {
|
||
|
assert(ref != NULL);
|
||
|
for (T* i = ref->data; i < ref->data + size; i++)
|
||
|
new (i) T(pad);
|
||
|
}
|
||
|
|
||
|
// Don't allow copying (error prone):
|
||
|
altvec<T>& operator = (altvec<T>& other) { assert(0); }
|
||
|
altvec (altvec<T>& other) { assert(0); }
|
||
|
|
||
|
public:
|
||
|
void clear (bool dealloc = false) {
|
||
|
if (ref != NULL){
|
||
|
for (int i = 0; i < ref->sz; i++)
|
||
|
(*ref).data[i].~T();
|
||
|
|
||
|
if (dealloc) {
|
||
|
free(ref); ref = NULL;
|
||
|
}else
|
||
|
ref->sz = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Constructors:
|
||
|
altvec(void) : ref (NULL) { }
|
||
|
altvec(int size) : ref (Vec_t::alloc(NULL, fitSize(size))) { fill(size); ref->sz = size; }
|
||
|
altvec(int size, const T& pad) : ref (Vec_t::alloc(NULL, fitSize(size))) { fill(size, pad); ref->sz = size; }
|
||
|
~altvec(void) { clear(true); }
|
||
|
|
||
|
// Ownership of underlying array:
|
||
|
operator T* (void) { return ref->data; } // (unsafe but convenient)
|
||
|
operator const T* (void) const { return ref->data; }
|
||
|
|
||
|
// Size operations:
|
||
|
int size (void) const { return ref != NULL ? ref->sz : 0; }
|
||
|
|
||
|
void pop (void) { assert(ref != NULL && ref->sz > 0); int last = --ref->sz; ref->data[last].~T(); }
|
||
|
void push (const T& elem) {
|
||
|
int size = ref != NULL ? ref->sz : 0;
|
||
|
int cap = ref != NULL ? ref->cap : 0;
|
||
|
if (size == cap){
|
||
|
cap = cap != 0 ? nextSize(cap) : init_size;
|
||
|
ref = Vec_t::alloc(ref, cap);
|
||
|
}
|
||
|
//new (&ref->data[size]) T(elem);
|
||
|
ref->data[size] = elem;
|
||
|
ref->sz = size+1;
|
||
|
}
|
||
|
|
||
|
void push () {
|
||
|
int size = ref != NULL ? ref->sz : 0;
|
||
|
int cap = ref != NULL ? ref->cap : 0;
|
||
|
if (size == cap){
|
||
|
cap = cap != 0 ? nextSize(cap) : init_size;
|
||
|
ref = Vec_t::alloc(ref, cap);
|
||
|
}
|
||
|
new (&ref->data[size]) T();
|
||
|
ref->sz = size+1;
|
||
|
}
|
||
|
|
||
|
void shrink (int nelems) { for (int i = 0; i < nelems; i++) pop(); }
|
||
|
void shrink_(int nelems) { for (int i = 0; i < nelems; i++) pop(); }
|
||
|
void growTo (int size) { while (this->size() < size) push(); }
|
||
|
void growTo (int size, const T& pad) { while (this->size() < size) push(pad); }
|
||
|
void capacity (int size) { growTo(size); }
|
||
|
|
||
|
const T& last (void) const { return ref->data[ref->sz-1]; }
|
||
|
T& last (void) { return ref->data[ref->sz-1]; }
|
||
|
|
||
|
// Vector interface:
|
||
|
const T& operator [] (int index) const { return ref->data[index]; }
|
||
|
T& operator [] (int index) { return ref->data[index]; }
|
||
|
|
||
|
void copyTo(altvec<T>& copy) const { copy.clear(); for (int i = 0; i < size(); i++) copy.push(ref->data[i]); }
|
||
|
void moveTo(altvec<T>& dest) { dest.clear(true); dest.ref = ref; ref = NULL; }
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
#endif
|