You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
5.2 KiB
182 lines
5.2 KiB
// Simple vectors.
|
|
|
|
#ifndef _CL_SV_H
|
|
#define _CL_SV_H
|
|
|
|
#include "cln/object.h"
|
|
#include "cln/V.h"
|
|
#include "cln/abort.h"
|
|
#include <cstdlib>
|
|
|
|
namespace cln {
|
|
|
|
// A simple vector has the same operations as a vector, but it can store
|
|
// _only_ cl_gcobject's.
|
|
// This class is here because the general vectors always need a function
|
|
// call for getting/setting the element of a vector. Our main application
|
|
// of the general vectors are the bit vectors, needed for implementing
|
|
// polynomials over modular integer rings. I don't want that polynomials
|
|
// over other rings (in particular cl_I) be penalized by the mere existence
|
|
// of polynomials over modular integer rings.
|
|
|
|
// When the vectors were implemented like this:
|
|
//
|
|
// cl_GV<cl_I> --> cl_GV<cl_RA> --> cl_GV<cl_R> --> cl_GV<cl_N>
|
|
//
|
|
// a bit/byte-vector (of integers with limited range) could actually be
|
|
// treated correctly by all the functions which manipulate vectors of cl_N.
|
|
// This is not crucial, however. Here, we'll have disjoint sets
|
|
//
|
|
// cl_SV<cl_I> --> cl_SV<cl_RA> --> cl_SV<cl_R> --> cl_SV<cl_N>
|
|
//
|
|
// cl_GV<cl_I>
|
|
//
|
|
// i.e. the functions which manipulate a (simple!) vector of cl_N cannot
|
|
// deal with a bit/byte-vector.
|
|
// (This is the same issue as UPGRADED-ARRAY-ELEMENT-TYPE in Common Lisp.)
|
|
|
|
template <class T> class cl_SV_inner;
|
|
|
|
template <class T>
|
|
class cl_SV_inner {
|
|
protected:
|
|
uintC len; // number of elements
|
|
private:
|
|
// T data[]; // the elements
|
|
T * data() { return (T *) (this+1); }
|
|
const T * data() const { return (const T *) (this+1); }
|
|
public:
|
|
uintC length () const { return len; } // number of elements
|
|
const T & operator[] (unsigned long index) const
|
|
{
|
|
#ifndef CL_SV_NO_RANGECHECKS
|
|
if (!(index < length())) cl_abort();
|
|
#endif
|
|
return data()[index];
|
|
}
|
|
T & operator[] (unsigned long index)
|
|
{
|
|
#ifndef CL_SV_NO_RANGECHECKS
|
|
if (!(index < length())) cl_abort();
|
|
#endif
|
|
return data()[index];
|
|
}
|
|
// New ANSI C++ compilers also want the following.
|
|
const T & operator[] (unsigned int index) const
|
|
{ return operator[]((unsigned long)index); }
|
|
T & operator[] (unsigned int index)
|
|
{ return operator[]((unsigned long)index); }
|
|
const T & operator[] (long index) const
|
|
{ return operator[]((unsigned long)index); }
|
|
T & operator[] (long index)
|
|
{ return operator[]((unsigned long)index); }
|
|
const T & operator[] (int index) const
|
|
{ return operator[]((unsigned long)index); }
|
|
T & operator[] (int index)
|
|
{ return operator[]((unsigned long)index); }
|
|
public: /* ugh */
|
|
// Constructor.
|
|
cl_SV_inner (uintC l) : len (l) {}
|
|
public:
|
|
// Destructor.
|
|
~cl_SV_inner ();
|
|
// Ability to place an object at a given address.
|
|
void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
|
|
private:
|
|
// No default constructor, copy constructor, assignment operator, new.
|
|
cl_SV_inner ();
|
|
cl_SV_inner (const cl_SV_inner&);
|
|
cl_SV_inner& operator= (const cl_SV_inner&);
|
|
void* operator new (size_t size);
|
|
};
|
|
|
|
// All member functions are inline.
|
|
|
|
template <class T>
|
|
inline cl_SV_inner<T>::~cl_SV_inner ()
|
|
{
|
|
uintC i = len;
|
|
while (i > 0) {
|
|
i--;
|
|
data()[i].~T();
|
|
}
|
|
}
|
|
|
|
|
|
// In memory, a simple vector looks like this:
|
|
|
|
template <class T>
|
|
struct cl_heap_SV : cl_heap {
|
|
cl_SV_inner<T> v;
|
|
// here room for the elements
|
|
};
|
|
|
|
template <class T, class BASE>
|
|
struct cl_SV : public BASE {
|
|
public:
|
|
// Length.
|
|
uintC length () const
|
|
{
|
|
return ((const cl_heap_SV<T> *) this->pointer)->v.length();
|
|
}
|
|
// Reference. Forbid modification of `const cl_SV&' arguments.
|
|
const T & operator[] (unsigned long index) const
|
|
{
|
|
return ((const cl_heap_SV<T> *) this->pointer)->v[index];
|
|
}
|
|
T & operator[] (unsigned long index)
|
|
{
|
|
return ((cl_heap_SV<T> *) this->pointer)->v[index];
|
|
}
|
|
// New ANSI C++ compilers also want the following.
|
|
const T & operator[] (unsigned int index) const
|
|
{ return operator[]((unsigned long)index); }
|
|
T & operator[] (unsigned int index)
|
|
{ return operator[]((unsigned long)index); }
|
|
const T & operator[] (long index) const
|
|
{ return operator[]((unsigned long)index); }
|
|
T & operator[] (long index)
|
|
{ return operator[]((unsigned long)index); }
|
|
const T & operator[] (int index) const
|
|
{ return operator[]((unsigned long)index); }
|
|
T & operator[] (int index)
|
|
{ return operator[]((unsigned long)index); }
|
|
// Constructors.
|
|
cl_SV (const cl_SV&);
|
|
// Assignment operators.
|
|
cl_SV& operator= (const cl_SV&);
|
|
// Private pointer manipulations.
|
|
cl_SV (cl_heap_SV<T>* p) : BASE ((cl_private_thing)p) {}
|
|
cl_SV (cl_private_thing p) : BASE (p) {}
|
|
protected:
|
|
// Forbid use of default constructor.
|
|
cl_SV ();
|
|
};
|
|
#define CL_SV(T,BASE) cl_SV<T,BASE>
|
|
// Define copy constructor.
|
|
template <class T, class BASE>
|
|
_CL_DEFINE_COPY_CONSTRUCTOR2(CL_SV(T,BASE),cl_SV,BASE)
|
|
// Define assignment operator.
|
|
template <class T, class BASE>
|
|
CL_DEFINE_ASSIGNMENT_OPERATOR(CL_SV(T,BASE),CL_SV(T,BASE))
|
|
#undef CL_SV
|
|
|
|
// The "generic" simple vector type.
|
|
|
|
typedef cl_heap_SV<cl_gcobject> cl_heap_SV_any;
|
|
typedef cl_SV<cl_gcobject,cl_V_any> cl_SV_any;
|
|
|
|
// Copy a simple vector.
|
|
extern const cl_SV_any copy (const cl_SV_any&);
|
|
|
|
|
|
// Hack section.
|
|
|
|
// Conversions to subtypes without checking:
|
|
#define The(type) *(const type *) & cl_identity
|
|
// This inline function is for type checking purposes only.
|
|
inline const cl_SV_any& cl_identity (const cl_SV_any& x) { return x; }
|
|
|
|
} // namespace cln
|
|
|
|
#endif /* _CL_SV_H */
|