1// This may look like C code, but it is really -*- C++ -*- 2/* 3Copyright (C) 1988 Free Software Foundation 4 written by Doug Lea (dl@rocky.oswego.edu) 5 based on code by Marc Shapiro (shapiro@sor.inria.fr) 6 7This file is part of GNU CC. 8 9GNU CC is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY. No author or distributor 11accepts responsibility to anyone for the consequences of using it 12or for whether it serves any particular purpose or works at all, 13unless he says so in writing. Refer to the GNU CC General Public 14License for full details. 15 16Everyone is granted permission to copy, modify and redistribute 17GNU CC, but only under the conditions described in the 18GNU CC General Public License. A copy of this license is 19supposed to have been given to you along with GNU CC so you 20can know your rights and responsibilities. It should be in a 21file named COPYING. Among other things, the copyright notice 22and this notice must be preserved on all copies. 23*/ 24 25#ifdef __GNUG__ 26#pragma implementation 27#endif 28#include "<T>.RPlex.h" 29 30typedef <T>IChunk* _<T>IChunk_ptr; 31 32<T>RPlex:: <T>RPlex() 33{ 34 lo = fnc = 0; 35 csize = DEFAULT_INITIAL_CAPACITY; 36 <T>* data = new <T>[csize]; 37 set_cache(new <T>IChunk(data, lo, lo, fnc, lo+csize)); 38 hd = ch; 39 maxch = MIN_NCHUNKS; 40 lch = maxch / 2; 41 fch = lch + 1; 42 base = ch->base_index() - lch * csize; 43 chunks = new _<T>IChunk_ptr[maxch]; 44 chunks[lch] = ch; 45} 46 47<T>RPlex:: <T>RPlex(int chunksize) 48{ 49 if (chunksize == 0) error("invalid constructor specification"); 50 lo = fnc = 0; 51 if (chunksize > 0) 52 { 53 csize = chunksize; 54 <T>* data = new <T>[csize]; 55 set_cache(new <T>IChunk(data, lo, lo, fnc, csize+lo)); 56 hd = ch; 57 } 58 else 59 { 60 csize = -chunksize; 61 <T>* data = new <T>[csize]; 62 set_cache(new <T>IChunk(data, chunksize+lo, lo, fnc, fnc)); 63 hd = ch; 64 } 65 maxch = MIN_NCHUNKS; 66 lch = maxch / 2; 67 fch = lch + 1; 68 base = ch->base_index() - lch * csize; 69 chunks = new _<T>IChunk_ptr[maxch]; 70 chunks[lch] = ch; 71} 72 73 74<T>RPlex:: <T>RPlex(int l, int chunksize) 75{ 76 if (chunksize == 0) error("invalid constructor specification"); 77 lo = fnc = l; 78 if (chunksize > 0) 79 { 80 csize = chunksize; 81 <T>* data = new <T>[csize]; 82 set_cache(new <T>IChunk(data, lo, lo, fnc, lo+csize)); 83 hd = ch; 84 } 85 else 86 { 87 csize = -chunksize; 88 <T>* data = new <T>[csize]; 89 set_cache(new <T>IChunk(data, chunksize+lo, lo, fnc, fnc)); 90 hd = ch; 91 } 92 maxch = MIN_NCHUNKS; 93 lch = maxch / 2; 94 fch = lch + 1; 95 base = ch->base_index() - lch * csize; 96 chunks = new _<T>IChunk_ptr[maxch]; 97 chunks[lch] = ch; 98} 99 100void <T>RPlex::make_initial_chunks(int up) 101{ 102 int count = 0; 103 int need = fnc - lo; 104 hd = 0; 105 if (up) 106 { 107 int l = lo; 108 do 109 { 110 ++count; 111 int sz; 112 if (need >= csize) 113 sz = csize; 114 else 115 sz = need; 116 <T>* data = new <T> [csize]; 117 <T>IChunk* h = new <T>IChunk(data, l, l, l+sz, l+csize); 118 if (hd != 0) 119 h->link_to_next(hd); 120 else 121 hd = h; 122 l += sz; 123 need -= sz; 124 } while (need > 0); 125 } 126 else 127 { 128 int hi = fnc; 129 do 130 { 131 ++count; 132 int sz; 133 if (need >= csize) 134 sz = csize; 135 else 136 sz = need; 137 <T>* data = new <T> [csize]; 138 <T>IChunk* h = new <T>IChunk(data, hi-csize, hi-sz, hi, hi); 139 if (hd != 0) 140 h->link_to_next(hd); 141 hd = h; 142 hi -= sz; 143 need -= sz; 144 } while (need > 0); 145 } 146 set_cache((<T>IChunk*)hd); 147 148 maxch = MIN_NCHUNKS; 149 if (maxch < count * 2) 150 maxch = count * 2; 151 chunks = new _<T>IChunk_ptr[maxch]; 152 lch = maxch / 3; 153 fch = lch + count; 154 base = ch->base_index() - csize * lch; 155 int k = lch; 156 do 157 { 158 chunks[k++] = ch; 159 set_cache(ch->next()); 160 } while (ch != hd); 161} 162 163<T>RPlex:: <T>RPlex(int l, int hi, const <T&> initval, int chunksize) 164{ 165 lo = l; 166 fnc = hi + 1; 167 if (chunksize == 0) 168 { 169 csize = fnc - l; 170 make_initial_chunks(1); 171 } 172 else if (chunksize < 0) 173 { 174 csize = -chunksize; 175 make_initial_chunks(0); 176 } 177 else 178 { 179 csize = chunksize; 180 make_initial_chunks(1); 181 } 182 fill(initval); 183} 184 185<T>RPlex::<T>RPlex(const <T>RPlex& a) 186{ 187 lo = a.lo; 188 fnc = a.fnc; 189 csize = a.csize; 190 make_initial_chunks(); 191 for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i]; 192} 193 194void <T>RPlex::operator= (const <T>RPlex& a) 195{ 196 if (&a != this) 197 { 198 invalidate(); 199 lo = a.lo; 200 fnc = a.fnc; 201 csize = a.csize; 202 make_initial_chunks(); 203 for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i]; 204 } 205} 206 207 208void <T>RPlex::cache(const <T>* p) const 209{ 210 const <T>IChunk* old = ch; 211 const <T>IChunk* t = ch; 212 while (!t->actual_pointer(p)) 213 { 214 t = (t->next()); 215 if (t == old) index_error(); 216 } 217 set_cache(t); 218} 219 220int <T>RPlex::owns(Pix px) const 221{ 222 <T>* p = (<T>*)px; 223 const <T>IChunk* old = ch; 224 const <T>IChunk* t = ch; 225 while (!t->actual_pointer(p)) 226 { 227 t = (t->next()); 228 if (t == old) return 0; 229 } 230 set_cache(t); 231 return 1; 232} 233 234 235<T>* <T>RPlex::dosucc(const <T>* p) const 236{ 237 if (p == 0) return 0; 238 const <T>IChunk* old = ch; 239 const <T>IChunk* t = ch; 240 while (!t->actual_pointer(p)) 241 { 242 t = (t->next()); 243 if (t == old) return 0; 244 } 245 int i = t->index_of(p) + 1; 246 if (i >= fnc) return 0; 247 if (i >= t->fence_index()) t = (t->next()); 248 set_cache(t); 249 return t->pointer_to(i); 250} 251 252<T>* <T>RPlex::dopred(const <T>* p) const 253{ 254 if (p == 0) return 0; 255 const <T>IChunk* old = ch; 256 const <T>IChunk* t = ch; 257 while (!t->actual_pointer(p)) 258 { 259 t = (t->prev()); 260 if (t == old) return 0; 261 } 262 int i = t->index_of(p) - 1; 263 if (i < lo) return 0; 264 if (i < t->low_index()) t = (t->prev()); 265 set_cache(t); 266 return (t->pointer_to(i)); 267} 268 269int <T>RPlex::add_high(const <T&> elem) 270{ 271 <T>IChunk* t = tl(); 272 if (!t->can_grow_high()) 273 { 274 if (t-><T>IChunk::empty() && one_chunk()) 275 { 276 t->clear(fnc); 277 base = t->base_index() - lch * csize; 278 } 279 else 280 { 281 <T>* data = new <T> [csize]; 282 t = (new <T>IChunk(data, fnc, fnc, fnc,fnc+csize)); 283 t->link_to_prev(tl()); 284 if (fch == maxch) 285 { 286 maxch *= 2; 287 <T>IChunk** newch = new _<T>IChunk_ptr [maxch]; 288 bcopy(chunks, newch, fch * sizeof(_<T>IChunk_ptr)); 289 delete chunks; 290 chunks = newch; 291 } 292 chunks[fch++] = t; 293 } 294 } 295 *((t-><T>IChunk::grow_high())) = elem; 296 set_cache(t); 297 return fnc++; 298} 299 300int <T>RPlex::del_high () 301{ 302 if (empty()) empty_error(); 303 <T>IChunk* t = tl(); 304 if (t-><T>IChunk::empty()) // kill straggler first 305 { 306 <T>IChunk* pred = t->prev(); 307 del_chunk(t); 308 t = (pred); 309 --fch; 310 } 311 t-><T>IChunk::shrink_high(); 312 if (t-><T>IChunk::empty() && !one_chunk()) 313 { 314 <T>IChunk* pred = t->prev(); 315 del_chunk(t); 316 t = (pred); 317 --fch; 318 } 319 set_cache(t); 320 return --fnc - 1; 321} 322 323int <T>RPlex::add_low (const <T&> elem) 324{ 325 <T>IChunk* t = hd; 326 if (!t->can_grow_low()) 327 { 328 if (t-><T>IChunk::empty() && one_chunk()) 329 { 330 t->cleardown(lo); 331 base = t->base_index() - lch * csize; 332 } 333 else 334 { 335 <T>* data = new <T> [csize]; 336 hd = new <T>IChunk(data, lo-csize, lo, lo, lo); 337 hd->link_to_next(t); 338 t = ( hd); 339 if (lch == 0) 340 { 341 lch = maxch; 342 fch += maxch; 343 maxch *= 2; 344 <T>IChunk** newch = new _<T>IChunk_ptr [maxch]; 345 bcopy(chunks, &(newch[lch]), lch * sizeof(_<T>IChunk_ptr)); 346 delete chunks; 347 chunks = newch; 348 base = t->base_index() - (lch - 1) * csize; 349 } 350 chunks[--lch] = t; 351 } 352 } 353 *((t-><T>IChunk::grow_low())) = elem; 354 set_cache(t); 355 return --lo; 356} 357 358 359int <T>RPlex::del_low () 360{ 361 if (empty()) empty_error(); 362 <T>IChunk* t = hd; 363 if (t-><T>IChunk::empty()) 364 { 365 hd = t->next(); 366 del_chunk(t); 367 t = hd; 368 ++lch; 369 } 370 t-><T>IChunk::shrink_low(); 371 if (t-><T>IChunk::empty() && !one_chunk()) 372 { 373 hd = t->next(); 374 del_chunk(t); 375 t = hd; 376 ++lch; 377 } 378 set_cache(t); 379 return ++lo; 380} 381 382void <T>RPlex::append(const <T>RPlex& a) 383{ 384 for (int i = a.low(); i < a.fence(); a.next(i)) add_high(a[i]); 385} 386 387void <T>RPlex::prepend (const <T>RPlex& a) 388{ 389 for (int i = a.high(); i > a.ecnef(); a.prev(i)) add_low(a[i]); 390} 391 392void <T>RPlex::reverse() 393{ 394 <T> tmp; 395 int l = lo; 396 int h = fnc - 1; 397 <T>IChunk* loch = hd; 398 <T>IChunk* hich = tl(); 399 while (l < h) 400 { 401 <T>* lptr = loch->pointer_to(l); 402 <T>* hptr = hich->pointer_to(h); 403 tmp = *lptr; 404 *lptr = *hptr; 405 *hptr = tmp; 406 if (++l >= loch->fence_index()) loch = loch->next(); 407 if (--h < hich->low_index()) hich = hich->prev(); 408 } 409} 410 411void <T>RPlex::fill(const <T&> x) 412{ 413 for (int i = lo; i < fnc; ++i) (*this)[i] = x; 414} 415 416void <T>RPlex::fill(const <T&> x, int lo, int hi) 417{ 418 for (int i = lo; i <= hi; ++i) (*this)[i] = x; 419} 420 421 422void <T>RPlex::clear() 423{ 424 for (int i = lch + 1; i < fch; ++i) 425 del_chunk(chunks[i]); 426 fch = lch + 1; 427 set_cache(chunks[lch]); 428 ch-><T>IChunk::clear(lo); 429 fnc = lo; 430} 431 432int <T>RPlex::reset_low(int l) 433{ 434 int old = lo; 435 int diff = l - lo; 436 if (diff != 0) 437 { 438 lo += diff; 439 fnc += diff; 440 <T>IChunk* t = hd; 441 do 442 { 443 t->re_index(t->low_index() + diff); 444 t = t->next(); 445 } while (t != hd); 446 } 447 base = hd->base_index() - lch * csize; 448 return old; 449} 450 451 452int <T>RPlex::OK () const 453{ 454 int v = hd != 0 && ch != 0; // at least one chunk 455 456 v &= fnc == tl()->fence_index(); // last chunk fnc == plex fnc 457 v &= lo == hd-><T>IChunk::low_index(); // first lo == plex lo 458 459 v &= base == hd->base_index() - lch * csize; // base is correct; 460 v &= lch < fch; 461 v &= fch <= maxch; // within allocation; 462 463// loop for others: 464 465 int k = lch; // to cross-check nch 466 467 int found_ch = 0; // to make sure ch is in list; 468 const <T>IChunk* t = (hd); 469 for (;;) 470 { 471 v &= chunks[k++] == t; // each chunk is at proper index 472 if (t == ch) ++found_ch; 473 v &= t-><T>IChunk::OK(); // each chunk is OK 474 if (t == tl()) 475 break; 476 else // and has indices contiguous to succ 477 { 478 v &= t->top_index() == t->next()->base_index(); 479 if (t != hd) // internal chunks full 480 { 481 v &= !t->empty(); 482 v &= !t->can_grow_low(); 483 v &= !t->can_grow_high(); 484 } 485 t = t->next(); 486 } 487 } 488 v &= found_ch == 1; 489 v &= fch == k; 490 if (!v) error("invariant failure"); 491 return v; 492} 493