home *** CD-ROM | disk | FTP | other *** search
- // This may look like C code, but it is really -*- C++ -*-
- /*
- Copyright (C) 1988 Free Software Foundation
- written by Doug Lea (dl@rocky.oswego.edu)
-
- This file is part of GNU CC.
-
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY. No author or distributor
- accepts responsibility to anyone for the consequences of using it
- or for whether it serves any particular purpose or works at all,
- unless he says so in writing. Refer to the GNU CC General Public
- License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- GNU CC, but only under the conditions described in the
- GNU CC General Public License. A copy of this license is
- supposed to have been given to you along with GNU CC so you
- can know your rights and responsibilities. It should be in a
- file named COPYING. Among other things, the copyright notice
- and this notice must be preserved on all copies.
- */
-
- #include <stream.h>
- #include "<T>Vec.h"
-
- // error handling
-
-
- void default_<T>Vec_error_handler(char* msg)
- {
- cerr << "Fatal <T>Vec error. " << msg << "\n";
- exit(1);
- }
-
- one_arg_error_handler_t <T>Vec_error_handler = default_<T>Vec_error_handler;
-
- one_arg_error_handler_t set_<T>Vec_error_handler(one_arg_error_handler_t f)
- {
- one_arg_error_handler_t old = <T>Vec_error_handler;
- <T>Vec_error_handler = f;
- return old;
- }
-
- void <T>Vec::error(const char* msg)
- {
- (*<T>Vec_error_handler)(msg);
- }
-
- void <T>Vec::range_error()
- {
- (*<T>Vec_error_handler)("Index out of range.");
- }
-
-
- // can't just realloc since there may be need for constructors/destructors
- void <T>Vec::resize(int newl)
- {
- <T>* news = new <T> [newl];
- <T>* p = news;
- int minl = len <? newl;
- <T>* top = &(s[minl]);
- <T>* t = s;
- while (t < top) *p++ = *t++;
- delete [len] s;
- s = news;
- len = newl;
- }
-
- <T>Vec concat(<T>Vec & a, <T>Vec & b)
- {
- int newl = a.len + b.len;
- <T>* news = new <T> [newl];
- <T>* p = news;
- <T>* top = &(a.s[a.len]);
- <T>* t = a.s;
- while (t < top) *p++ = *t++;
- top = &(b.s[b.len]);
- t = b.s;
- while (t < top) *p++ = *t++;
- return <T>Vec(newl, news);
- }
-
-
- <T>Vec combine(<T>Combiner f, <T>Vec& a, <T>Vec& b)
- {
- int newl = a.len <? b.len;
- <T>* news = new <T> [newl];
- <T>* p = news;
- <T>* top = &(a.s[newl]);
- <T>* t = a.s;
- <T>* u = b.s;
- while (t < top) *p++ = (*f)(*t++, *u++);
- return <T>Vec(newl, news);
- }
-
- <T> <T>Vec::reduce(<T>Combiner f, <T&> base)
- {
- <T> r = base;
- <T>* top = &(s[len]);
- <T>* t = s;
- while (t < top) r = (*f)(r, *t++);
- return r;
- }
-
- <T>Vec reverse(<T>Vec& a)
- {
- <T>* news = new <T> [a.len];
- if (a.len != 0)
- {
- <T>* lo = news;
- <T>* hi = &(news[a.len - 1]);
- while (lo < hi)
- {
- <T> tmp = *lo;
- *lo++ = *hi;
- *hi-- = tmp;
- }
- }
- return <T>Vec(a.len, news);
- }
-
- void <T>Vec::reverse()
- {
- if (len != 0)
- {
- <T>* lo = s;
- <T>* hi = &(s[len - 1]);
- while (lo < hi)
- {
- <T> tmp = *lo;
- *lo++ = *hi;
- *hi-- = tmp;
- }
- }
- }
-
- int <T>Vec::index(<T&> targ)
- {
- for (int i = 0; i < len; ++i) if (targ == s[i]) return i;
- return -1;
- }
-
- <T>Vec map(<T>Mapper f, <T>Vec& a)
- {
- <T>* news = new <T> [a.len];
- <T>* p = news;
- <T>* top = &(a.s[a.len]);
- <T>* t = a.s;
- while(t < top) *p++ = (*f)(*t++);
- return <T>Vec(a.len, news);
- }
-
- int operator == (<T>Vec& a, <T>Vec& b)
- {
- if (a.len != b.len)
- return 0;
- <T>* top = &(a.s[a.len]);
- <T>* t = a.s;
- <T>* u = b.s;
- while (t < top) if (*t++ != *u++) return 0;
- return 1;
- }
-
- void <T>Vec::fill(<T&> val, int from = 0, int n = -1)
- {
- int to;
- if (n < 0)
- to = len - 1;
- else
- to = from + n - 1;
- if ((unsigned)from > to)
- range_error();
- <T>* t = &(s[from]);
- <T>* top = &(s[to]);
- while (t <= top) *t++ = val;
- }
-
- <T>Vec <T>Vec::at(int from = 0, int n = -1)
- {
- int to;
- if (n < 0)
- {
- n = len - from;
- to = len - 1;
- }
- else
- to = from + n - 1;
- if ((unsigned)from > to)
- range_error();
- <T>* news = new <T> [n];
- <T>* p = news;
- <T>* t = &(s[from]);
- <T>* top = &(s[to]);
- while (t <= top) *p++ = *t++;
- return <T>Vec(n, news);
- }
-
- <T>Vec merge(<T>Vec & a, <T>Vec & b, <T>Comparator f)
- {
- int newl = a.len + b.len;
- <T>* news = new <T> [newl];
- <T>* p = news;
- <T>* topa = &(a.s[a.len]);
- <T>* as = a.s;
- <T>* topb = &(b.s[b.len]);
- <T>* bs = b.s;
-
- for (;;)
- {
- if (as >= topa)
- {
- while (bs < topb) *p++ = *bs++;
- break;
- }
- else if (bs >= topb)
- {
- while (as < topa) *p++ = *as++;
- break;
- }
- else if ((*f)(*as, *bs) <= 0)
- *p++ = *as++;
- else
- *p++ = *bs++;
- }
- return <T>Vec(newl, news);
- }
-
- /*
- * a lightly edited version of emacs-18.51 etc/qsort.c
- * The THRESHold below is the insertion sort threshold, and has been adjusted
- * for records of size 48 bytes.
- * The MTHREShold is where we stop finding a better median.
- */
-
-
- #define THRESH 4 /* threshold for insertion */
-
- #define MTHRESH 6 /* threshold for median */
-
- static <T>Comparator qcmp; /* the comparison routine */
-
- static void qst (<T>* base, <T>* max)
- {
- <T> *i, *j, *jj, *mid;
- <T> *tmp;
- int lo, hi;
-
- lo = max - base;
- do
- {
- mid = i = base + (lo >> 1);
- if (lo >= MTHRESH)
- {
- j = ((*qcmp) (*(jj = base), *i) > 0 ? jj : i);
- if ((*qcmp) (*j, *(tmp = max - 1)) > 0)
- {
- j = (j == jj ? i : jj); /* switch to first loser */
- if ((*qcmp) (*j, *tmp) < 0)
- j = tmp;
- }
- if (j != i)
- {
- <T> c = *i;
- *i++ = *j;
- *j++ = c;
- }
- }
- for (i = base, j = max - 1; ;)
- {
- while (i < mid && (*qcmp) (*i, *mid) <= 0)
- i += 1;
- while (j > mid)
- {
- if ((*qcmp) (*mid, *j) <= 0)
- {
- j -= 1;
- continue;
- }
- tmp = i + 1;
- if (i == mid)
- {
- mid = jj = j;
- }
- else
- {
- jj = j;
- j -= 1;
- }
- goto swap;
- }
- if (i == mid)
- {
- break;
- }
- else
- { /* i <-> mid, new mid is i */
- jj = mid;
- tmp = mid = i; /* value of i after swap */
- j -= 1;
- }
- swap:
- <T> c = *i;
- *i++ = *jj;
- *jj++ = c;
- i = tmp;
- }
- i = (j = mid) + 1;
- if ((lo = j - base) <= (hi = max - i))
- {
- if (lo >= THRESH)
- qst (base, j);
- base = i;
- lo = hi;
- }
- else
- {
- if (hi >= THRESH)
- qst (i, max);
- max = j;
- }
- }
- while (lo >= THRESH);
- }
-
- void <T>Vec::sort (<T>Comparator compar)
- {
- <T>* base = s;
- <T> *i, *j, *lo, *hi, *min;
-
- if (len <= 1) return;
- qcmp = compar;
-
- <T>* max = base + len;
-
- if (len >= THRESH)
- {
- qst (base, max);
- hi = base + THRESH;
- }
- else
- {
- hi = max;
- }
- for (j = lo = base; (lo += 1) < hi; )
- {
- if ((*qcmp) (*j, *lo) > 0)
- j = lo;
- }
- if (j != base)
- {
- <T> c = *j;
- *j++ = *base;
- *i = c;
- }
- for (min = base; (hi = min += 1) < max;)
- {
- while ( (*qcmp) (*(hi -= 1), *min) > 0);
- if ((hi += 1) != min)
- {
- for (lo = min + 1; --lo >= min;)
- {
- <T> c = *lo;
- for (i = j = lo; (j -= 1) >= hi; i = j)
- *i = *j;
- *i = c;
- }
- }
- }
- }
-
-
-