00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00037
#ifndef SMALLVECTOR
00038
#define SMALLVECTOR
00039
00040
#include <typeinfo>
00041
#include <algorithm>
00042
00043
#include "ArrayAllocatorTrivial.h"
00044
#include "general.h"
00045
00046
namespace PLearn {
00047
using namespace std;
00048
00049
00050
00051
00060
template <
class T,
unsigned SizeBits,
00061
class Allocator = ArrayAllocatorTrivial<T,SizeBits> >
00062 class SmallVector
00063 {
00064
public:
00066 typedef SmallVector<T,SizeBits> self_type;
00067 typedef Allocator
alloc_type;
00068
00069 typedef T
value_type;
00070 typedef size_t
size_type;
00071 typedef ptrdiff_t
difference_type;
00072
00073 typedef T*
iterator;
00074 typedef const T*
const_iterator;
00075
00076 typedef T*
pointer;
00077 typedef const T*
const_pointer;
00078 typedef T&
reference;
00079 typedef const T&
const_reference;
00080
00081
public:
00083
inline iterator begin();
00084
inline const_iterator begin() const;
00085 inline iterator end();
00086 inline const_iterator end() const;
00087
00088 public:
00090 inline reference operator[](size_type n);
00091 inline const_reference operator[](size_type n) const;
00092
00094 reference at(size_type n);
00095 const_reference at(size_type n) const;
00096
00097 inline reference front();
00098 inline const_reference front() const;
00099 inline reference back();
00100 inline const_reference back() const;
00101
00102 public:
00104 inline
SmallVector();
00105 inline SmallVector(size_type n, const T& val=T());
00106 ~SmallVector();
00107 SmallVector(const
self_type&);
00108 self_type& operator=(const self_type&);
00109
00111 template <class In>
00112 SmallVector(In first, In last) : i(0,0) {
00113
assign(first,last);
00114 }
00115
00116
template <
class In>
00117 void assign(In first, In last) {
00119
resize(last-first);
00120
iterator dest =
begin();
00121
while (first != last)
00122 *dest++ = *first++;
00123 }
00124
00125
inline void assign(size_type n,
const T& val);
00126
00127
public:
00129
void push_back(
const T& x);
00130
void pop_back();
00131
00132
public:
00134
00135
public:
00137 size_type
size() const;
00138 bool empty()
const {
00139
return size() == 0;
00140 }
00141 size_type max_size() {
00142
typename alloc_type::index_type dummy(
unsigned(-1),
unsigned(-1));
00143
return dummy.size;
00144 }
00145
void resize(size_type sz,
const T& val=T());
00146
void reserve(size_type n);
00147
00148
public:
00150
void swap(
SmallVector&);
00151
00153 static void allocator(alloc_type* the_alloc) {
00154 assert(the_alloc);
00155
alloc = the_alloc;
00156 }
00157 static alloc_type&
allocator() {
00158
return *
alloc;
00159 }
00160
00161
private:
00162
static alloc_type* alloc;
00163 typename alloc_type::index_type
i;
00164 };
00165
00167
00168
00169
template <
class T,
unsigned SizeBits,
class Allocator>
00170 inline unsigned int hashval(
const SmallVector<T,SizeBits,Allocator>& v)
00171 {
return hashbytes(const_cast<char*>(&v[0]),
sizeof(T)*size()); }
00172
00174
template <
class T,
unsigned SizeBits,
class Allocator>
00175
bool operator==(
const SmallVector<T,SizeBits,Allocator>& a,
00176
const SmallVector<T,SizeBits,Allocator>& b);
00177
00178
00179
00181
template <
class T,
unsigned SizeBits,
class Allocator>
00182 inline bool operator!=(
const SmallVector<T,SizeBits,Allocator>& x,
00183
const SmallVector<T,SizeBits,Allocator>& y) {
return !(
x==y); }
00184
00185
00187
00188
00190
template <
class T,
unsigned SizeBits>
00191
bool operator<(const SmallVector<T,SizeBits>&,
00192
const SmallVector<T,SizeBits>&);
00193
00194
00195
00196
00197
template <
class T,
unsigned SizeBits,
class Allocator = ArrayAllocatorTrivial<T,SizeBits> >
00198 Allocator*
SmallVector<T,SizeBits,Allocator>::alloc;
00199
00200
00201
00202
00203
00204
00205
template <
class T,
unsigned SizeBits,
class Allocator>
00206
typename SmallVector<T,SizeBits,Allocator>::iterator
00207 SmallVector<T,SizeBits,Allocator>::begin()
00208 {
00210
return allocator().toPointer(
i);
00211 }
00212
00213
00214
template <
class T,
unsigned SizeBits,
class Allocator>
00215
typename SmallVector<T,SizeBits,Allocator>::const_iterator
00216 SmallVector<T,SizeBits,Allocator>::begin()
const
00217
{
00219
return allocator().toPointer(
i);
00220 }
00221
00222
00223
template <
class T,
unsigned SizeBits,
class Allocator>
00224
typename SmallVector<T,SizeBits,Allocator>::iterator
00225 SmallVector<T,SizeBits,Allocator>::end()
00226 {
00227
return begin() +
size();
00228 }
00229
00230
00231
template <
class T,
unsigned SizeBits,
class Allocator>
00232
typename SmallVector<T,SizeBits,Allocator>::const_iterator
00233 SmallVector<T,SizeBits,Allocator>::end()
const
00234
{
00235
return begin() +
size();
00236 }
00237
00238
00239
00240
00241
00242
template <
class T,
unsigned SizeBits,
class Allocator>
00243
typename SmallVector<T,SizeBits,Allocator>::reference
00244 SmallVector<T,SizeBits,Allocator>::operator[](size_type n)
00245 {
00246
#ifdef BOUNDCHECK
00247
if (n >=
size())
00248
PLERROR(
"%s: out-of-range.",
typeid(*this).name());
00249
#endif
00250
return *(
begin()+n);
00251 }
00252
00253
00254
template <
class T,
unsigned SizeBits,
class Allocator>
00255
typename SmallVector<T,SizeBits,Allocator>::const_reference
00256 SmallVector<T,SizeBits,Allocator>::operator[](size_type n)
const
00257
{
00258
#ifdef BOUNDCHECK
00259
if (n >=
size())
00260
PLERROR(
"%s: out-of-range.",
typeid(*this).name());
00261
#endif
00262
return *(
begin()+n);
00263 }
00264
00265
00266
template <
class T,
unsigned SizeBits,
class Allocator>
00267
typename SmallVector<T,SizeBits,Allocator>::reference
00268 SmallVector<T,SizeBits,Allocator>::at(size_type n)
00269 {
00271
if (n >=
size())
00272
PLERROR(
"%s: out-of-range.",
typeid(*this).name());
00273
00274
return *(
begin()+n);
00275 }
00276
00277
00278
template <
class T,
unsigned SizeBits,
class Allocator>
00279
typename SmallVector<T,SizeBits,Allocator>::const_reference
00280 SmallVector<T,SizeBits,Allocator>::at(size_type n)
const
00281
{
00283
if (n >=
size())
00284
PLERROR(
"%s: out-of-range.",
typeid(*this).name());
00285
00286
return *(
begin()+n);
00287 }
00288
00289
00290
template <
class T,
unsigned SizeBits,
class Allocator>
00291
typename SmallVector<T,SizeBits,Allocator>::reference
00292 SmallVector<T,SizeBits,Allocator>::front()
00293 {
00294
if (
empty())
00295
PLERROR(
"%s: out-of-range.",
typeid(*this).name());
00296
00297
return *
begin();
00298 }
00299
00300
00301
template <
class T,
unsigned SizeBits,
class Allocator>
00302
typename SmallVector<T,SizeBits,Allocator>::const_reference
00303 SmallVector<T,SizeBits,Allocator>::front()
const
00304
{
00305
if (
empty())
00306
PLERROR(
"%s: out-of-range.",
typeid(*this).name());
00307
00308
return *
begin();
00309 }
00310
00311
00312
template <
class T,
unsigned SizeBits,
class Allocator>
00313
typename SmallVector<T,SizeBits,Allocator>::reference
00314 SmallVector<T,SizeBits,Allocator>::back()
00315 {
00316
if (
empty())
00317
PLERROR(
"%s: out-of-range.",
typeid(*this).name());
00318
00319
return *(
end()-1);
00320 }
00321
00322
00323
template <
class T,
unsigned SizeBits,
class Allocator>
00324
typename SmallVector<T,SizeBits,Allocator>::const_reference
00325 SmallVector<T,SizeBits,Allocator>::back()
const
00326
{
00327
if (
empty())
00328
PLERROR(
"%s: out-of-range.",
typeid(*this).name());
00329
00330
return *(
end()-1);
00331 }
00332
00333
00334
00335
00336
00337
template <
class T,
unsigned SizeBits,
class Allocator>
00338 void SmallVector<T,SizeBits,Allocator>::assign(size_type n,
const T& val)
00339 {
00340
if (n >
max_size())
00341
PLERROR(
"%s: out-of-range.",
typeid(*this).name());
00342
00343
resize(n);
00344
for (
size_type i=0; i<n; ++i)
00345 (*this)[i] =
val;
00346 }
00347
00348
00349
template <
class T,
unsigned SizeBits,
class Allocator>
00350 inline SmallVector<T,SizeBits,Allocator>::SmallVector()
00351 : i(0,0)
00352 { }
00353
00354
00355
template <
class T,
unsigned SizeBits,
class Allocator>
00356 inline SmallVector<T,SizeBits,Allocator>::SmallVector(size_type n,
const T& val)
00357 : i(0,0)
00358 {
00359 assign(n,
val);
00360 }
00361
00362
00363
template <
class T,
unsigned SizeBits,
class Allocator>
00364 SmallVector<T,SizeBits,Allocator>::SmallVector(
const self_type& other)
00365 : i(0)
00366 {
00367 assign(other.
begin(), other.
end());
00368 }
00369
00370
00371
template <
class T,
unsigned SizeBits,
class Allocator>
00372 SmallVector<T,SizeBits,Allocator>::~SmallVector()
00373 {
00374
allocator().deallocate(
i);
00375 }
00376
00377
00378
template <
class T,
unsigned SizeBits,
class Allocator>
00379
typename SmallVector<T,SizeBits,Allocator>::self_type&
00380 SmallVector<T,SizeBits,Allocator>::operator=(
const self_type& other)
00381 {
00382
if (
size() != other.
size()) {
00383
self_type tmp(other);
00384
swap(tmp);
00385 }
00386
else {
00387 assign(other.
begin(), other.
end());
00388 }
00389
return *
this;
00390 }
00391
00392
00393
00394
00395
00396
template <
class T,
unsigned SizeBits,
class Allocator>
00397 void SmallVector<T,SizeBits,Allocator>::push_back(
const T& x)
00398 {
00399
size_type s =
size();
00400
resize(s+1);
00401 (*this)[s] =
x;
00402 }
00403
00404
00405
template <
class T,
unsigned SizeBits,
class Allocator>
00406 void SmallVector<T,SizeBits,Allocator>::pop_back()
00407 {
00408
size_type s =
size();
00409
if (s == 0)
00410
PLERROR(
"%s: out-of-range.",
typeid(*this).name());
00411
resize(s-1);
00412 }
00413
00414
00415
00416
00417
00418
template <
class T,
unsigned SizeBits,
class Allocator>
00419
typename SmallVector<T,SizeBits,Allocator>::size_type
00420 SmallVector<T,SizeBits,Allocator>::size()
const
00421
{
00422
if (
i.isNull())
00423
return 0;
00424
else
00425
return i.size;
00426 }
00427
00428
00429
template <
class T,
unsigned SizeBits,
class Allocator>
00430 void SmallVector<T,SizeBits,Allocator>::resize(size_type sz,
const T& val)
00431 {
00432
if (sz >
max_size())
00433
PLERROR(
"%s: out-of-range.",
typeid(*this).name());
00434
00435
pointer newdata =
allocator().allocate(sz);
00436
typename alloc_type::index_type newi =
allocator().toIndex(newdata, sz);
00437
00439
pointer olddata =
allocator().toPointer(
i);
00440
size_type n = std::min(
int(sz),
int(
i.size));
00441
while (n--)
00442 *newdata++ = *olddata++;
00443
00445 n = std::max(0,
int(sz) -
int(
i.size));
00446
while (n--)
00447 *newdata++ =
val;
00448
00450
allocator().deallocate(
i);
00451
i = newi;
00452 }
00453
00454
00455
00456
template <
class T,
unsigned SizeBits,
class Allocator>
00457 void SmallVector<T,SizeBits,Allocator>::reserve(size_type n)
00458 {
00459
if (n >
max_size())
00460
PLERROR(
"%s: out-of-range.",
typeid(*this).name());
00461
00462 }
00463
00464
00465
00466
00467
00468
template <
class T,
unsigned SizeBits,
class Allocator>
00469 void SmallVector<T,SizeBits,Allocator>::swap(
SmallVector<T,SizeBits,Allocator>& other)
00470 {
00471 std::swap(
i,other.
i);
00472 }
00473
00474
00475
template <
class T,
unsigned SizeBits,
class Allocator>
00476 bool operator==(
const SmallVector<T,SizeBits,Allocator>& x,
00477
const SmallVector<T,SizeBits,Allocator>& y)
00478 {
00479
bool equal =
true;
00480
typename SmallVector<T,SizeBits,Allocator>::const_iterator
00481 xit=
x.begin(), xend=
x.end(), yit=y.
begin(), yend=y.
end();
00482
if (xend-xit != yend-yit)
00483
return false;
00484
for ( ; equal && xit != xend && yit != yend ; ++xit, ++yit)
00485 equal = (*xit == *yit);
00486
return equal;
00487 }
00488
00489
00490
template <
class T,
unsigned SizeBits,
class Allocator>
00491 bool operator<(const SmallVector<T,SizeBits,Allocator>&
x,
00492
const SmallVector<T,SizeBits,Allocator>& y)
00493 {
00494
return std::lexicographical_compare(
x.begin(),
x.end(),
00495 y.begin(), y.end());
00496 }
00497
00498 }
00499
00500
00501
#endif