From: fred Date: Wed, 19 Mar 1997 00:45:23 +0000 (+0000) Subject: lilypond-0.0.43 X-Git-Tag: release/1.5.59~6196 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=55364f5fb07b258c341ea5caa91f5f57788eb2bf;p=lilypond.git lilypond-0.0.43 --- diff --git a/flower/choleski.cc b/flower/choleski.cc new file mode 100644 index 0000000000..1d64f949ac --- /dev/null +++ b/flower/choleski.cc @@ -0,0 +1,91 @@ +#include "choleski.hh" +const Real EPS = 1e-7; // so sue me. Hard coded + +Vector +Choleski_decomposition::solve(Vector rhs)const +{ + int n= rhs.dim(); + assert(n == L.dim()); + Vector y(n); + + // forward substitution + for (int i=0; i < n; i++) { + Real sum(0.0); + for (int j=0; j < i; j++) + sum += y(j) * L(i,j); + y(i) = (rhs(i) - sum)/L(i,i); + } + for (int i=0; i < n; i++) + y(i) /= D(i); + + // backward subst + Vector &x(rhs); // using input as return val. + for (int i=n-1; i >= 0; i--) { + Real sum(0.0); + for (int j=i+1; j < n; j++) + sum += L(j,i)*x(j); + x(i) = (y(i) - sum)/L(i,i); + } + return x; +} + +/* + Standard matrix algorithm. + */ + +Choleski_decomposition::Choleski_decomposition(Matrix P) + : L(P.dim()), D(P.dim()) +{ + int n = P.dim(); + assert((P-P.transposed()).norm()/P.norm() < EPS); + + L.unit(); + for (int k= 0; k < n; k++) { + for (int j = 0; j < k; j++){ + Real sum(0.0); + for (int l=0; l < j; l++) + sum += L(k,l)*L(j,l)*D(l); + L(k,j) = (P(k,j) - sum)/D(j); + } + Real sum=0.0; + + for (int l=0; l < k; l++) + sum += sqr(L(k,l))*D(l); + Real d = P(k,k) - sum; + D(k) = d; + } + +#ifdef NDEBUG + assert((original()-P).norm() / P.norm() < EPS); +#endif +} + +Matrix +Choleski_decomposition::original() const +{ + Matrix T(L.dim()); + T.set_diag(D); + return L*T*L.transposed(); +} + +Matrix +Choleski_decomposition::inverse() const +{ + int n=L.dim(); + Matrix invm(n); + Vector e_i(n); + for (int i = 0; i < n; i++) { + e_i.set_unit(i); + Vector inv(solve(e_i)); + for (int j = 0 ; j +#include + +#include "data-file.hh" + +void +Data_file::gobble_white() +{ + char c; + + while ((c=data_get()) == ' ' ||c == '\t') + if (eof()) + break; + + data_unget(c); +} + +String +Data_file::get_word() +{// should handle escape seq's + String s; + + while (1) + { + char c = data_get(); + + if (isspace(c) || eof()) + { + data_unget(c); + break; + } + + + if (c == '\"') + { + rawmode= true; + + while ((c = data_get()) != '\"') + if (eof()) + error("EOF in a string"); + else + s += c; + + + rawmode= false; + } + else + s += c; + } + + return s; +} + +/** get a char + Only class member who uses text_file::get + */ +char +Data_file::data_get() { + char c = get(); + if (!rawmode && c == '#') // gobble comment + { + while ((c = get()) != '\n' && !eof()) + ; + return '\n'; + } + + return c; +} + +/// read line, gobble '\n' +String Data_file::get_line() +{ + char c; + String s; + + while ((c = data_get()) != '\n' && !eof()) + s += c; + return s; +} + +/// gobble stuff before first entry on a line. +void +Data_file::gobble_leading_white() +{ + // eat blank lines. + while (!eof()) { + char c = data_get(); + if (!isspace(c)) { + data_unget(c); + break; + } + } +} + + diff --git a/flower/dstream.cc b/flower/dstream.cc new file mode 100644 index 0000000000..05ee3e6958 --- /dev/null +++ b/flower/dstream.cc @@ -0,0 +1,161 @@ + + +#include +#include "assoc.hh" +#include "dstream.hh" +#include "scalar.hh" +#include "text-db.hh" +#include "string-convert.hh" + +/// indent of each level +const INDTAB = 2; + +/* + should use Regexp library. + */ +static String +strip_pretty(String pretty_str) +{ + int i = pretty_str.index_i('('); + if (i>=0) + pretty_str = pretty_str.left_str(i); + + int l = pretty_str.index_last_i(' '); // strip until last ' ' + if (l>=0) + pretty_str = pretty_str.nomid_str(0,l+1); + return pretty_str; +} + +static String +strip_member(String pret) +{ + int l=pret.index_last_i(':')-1; + if (l>=0) + pret = pret.left_str(l ); + return pret; +} + +Dstream& +Dstream::identify_as(String name) +{ + if (!os) + return *this; + + String mem(strip_pretty(name)); + String cl(strip_member(mem)); + String idx = cl; + + if (silent->elt_query(mem)) + idx = mem; + else if (silent->elt_query(cl)) + idx = cl; + else { + (*silent)[idx] = false; + } + local_silence = (*silent)[idx]; + if (classname != idx && !local_silence) { + classname=idx; + if (!(*silent)["Dstream"]) + *os << "[" << classname << ":]"; // messy. + } + return *this; +} + +bool +Dstream::silence(String s) +{ + if (!silent->elt_query(s)) + return false; + return (*silent)[s]; +} + +/** Output a string via the Dstream. This is the only output + interface. It delegates all conversion to String class. */ +Dstream & +Dstream::operator<<(String s) +{ + output(s); + return *this; +} + +Dstream & +Dstream::operator<<(void const *v_l) +{ + output(String_convert::pointer_str(v_l)); + return *this; +} + +Dstream & +Dstream::operator<<(char const *ch_l) +{ + output(ch_l); + return *this; +} + +void +Dstream::output(String s) +{ + if (local_silence|| !os) + return ; + + for (char const *cp = s ; *cp; cp++) + switch(*cp) { + case '{': + case '[': + case '(': indentlvl += INDTAB; + *os << *cp; + break; + + case ')': + case ']': + case '}': + indentlvl -= INDTAB; + *os << *cp ; + + assert (indentlvl>=0) ; + break; + + case '\n': + *os << '\n' << String (' ', indentlvl) << flush; + break; + default: + *os << *cp; + break; + } + return ; +} + + +Dstream::Dstream(ostream *r, char const * cfg_nm ) +{ + os = r; + silent = new Assoc; + indentlvl = 0; + if (!os) + return; + + char const * fn =cfg_nm ? cfg_nm : ".dstreamrc"; + { + ifstream ifs(fn); // can't open + if (!ifs) + return; + } + + Text_db cfg(fn); + while (! cfg.eof()){ + Text_record r( cfg++); + if (r.size() != 2) { + r.message("not enough fields in Dstream init."); + continue; + } + (*silent)[r[0]] = (bool)(int)(Scalar(r[1])); + } + +} + + +Dstream::~Dstream() +{ + delete silent; + assert(!indentlvl) ; +} diff --git a/flower/flower-version.cc b/flower/flower-version.cc new file mode 100644 index 0000000000..fd37845588 --- /dev/null +++ b/flower/flower-version.cc @@ -0,0 +1,16 @@ +#include "version.hh" // urg +#include + +static char *s = "FlowerLib " MAJOR_VERSION "." MINOR_VERSION "." PATCH_LEVEL MY_PATCH_LEVEL " #%d"; + +static const int build= +#include ".build" +; + +char const * +flower_version_sz() +{ + static char v[1024]; + sprintf(v, s, build); + return v; +} diff --git a/flower/include/assoc-iter.hh b/flower/include/assoc-iter.hh new file mode 100644 index 0000000000..34b88df22d --- /dev/null +++ b/flower/include/assoc-iter.hh @@ -0,0 +1,39 @@ +/* + associter.hh -- part of flowerlib + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef ASSOCITER_HH +#define ASSOCITER_HH + +#include "assoc.hh" + +/// an iterator for the #Assoc# class +template +struct Assoc_iter { + int i; + Assoc &assoc_; + /// we don't want to be bothered by const correctness + Assoc_iter(const Assoc &a) : + assoc_((Assoc &)a) + { + i= next(0); + } + int next(int j) { + while (j < assoc_.arr.size() && assoc_.arr[j].free) + j++; + return j; + } + bool ok() const { + return i < assoc_.arr.size(); + } + void OK()const { + assert(!ok() || !assoc_.arr[i].free); + } + void operator++(int) { i++; i = next(i); } + K key() { return assoc_.arr[i].key; } + V &val() { return assoc_.arr[i].val; } +}; + +#endif diff --git a/flower/include/assoc.hh b/flower/include/assoc.hh new file mode 100644 index 0000000000..bf22881d90 --- /dev/null +++ b/flower/include/assoc.hh @@ -0,0 +1,78 @@ +#ifndef ASSOC_HH +#define ASSOC_HH + +#include "varray.hh" +#include + +/** + A helper for Assoc + */ +template +struct Assoc_ent_ { + bool free; + K key; + V val; +}; + + +/** mindblowingly stupid Associative array implementation. + Hungarian: map + */ +template +struct Assoc { + Array< Assoc_ent_ > arr; + + /* ************** */ + + int find(K key) const { + for (int i = 0; i < arr.size(); i++) { + if (!arr[i].free && key == arr[i].key) + return i; + } + return -1; + } + int find_creat(K key) { + int free = -1; + for (int i = 0; i < arr.size(); i++) { + if (key == arr[i].key) { + return i; + } else if (arr[i].free ) { + free = i; + } + } + if (free >= 0){ + arr[free].free = false; + arr[free].key = key; + return free; + } + + Assoc_ent_ ae; + ae.free = false; + ae.key = key; + arr.push(ae); + return arr.size() -1; + } +public: + bool elt_query(K key) const { + return find(key) >= 0; + } + void del(K key) { + assert(elt_query(key)); + int i= find(key); + arr[i].free = true; + } + void + add(K key, V val) { + int i = find_creat(key); + arr[i].val = val; + } + V& operator[](K key) { + return arr[find_creat(key)].val; + } + V const & operator[](K key) const { + assert(elt_query(key)); + return arr[find(key)].val; + } +}; + +#endif diff --git a/flower/include/choleski.hh b/flower/include/choleski.hh new file mode 100644 index 0000000000..f5e9fb4f5a --- /dev/null +++ b/flower/include/choleski.hh @@ -0,0 +1,46 @@ +#ifndef CHOLESKI_HH +#define CHOLESKI_HH + +#include "matrix.hh" + +/** + Choleski decomposition of a matrix + structure for using the LU decomposition of a positive definite matrix. + + #P# is split into + + LD transpose(L) + */ +struct Choleski_decomposition { + + /// lower triangle of Choleski decomposition + Matrix L; + + /// diagonal + Vector D; + + /** Create decomposition of P. + PRE + P needs to be symmetric positive definite + */ + + Choleski_decomposition(Matrix P); + + /** + solve Px = rhs + */ + Vector solve(Vector rhs) const; + + Vector operator * (Vector rhs) const { return solve (rhs); } + /** + return the inverse of the matrix P. + */ + Matrix inverse() const; + /** + return P, calc'ed from L and D + */ + Matrix original() const; + + +}; +#endif diff --git a/flower/include/compare.hh b/flower/include/compare.hh new file mode 100644 index 0000000000..203ba014e7 --- /dev/null +++ b/flower/include/compare.hh @@ -0,0 +1,55 @@ +/* + flowerlib + + (c) 1996 Han-Wen Nienhuys + */ +#ifndef COMPARE_HH +#define COMPARE_HH + +#define one_operator(type, function, op) \ +inline bool \ +operator op (type t1, type t2) {\ + return function(t1, t2) op 0;\ +}\ + +#define gpp_minmax_operator(type, op, opp) \ +inline type \ +operator op(type t1, type t2)\ +{\ + return (t1 opp t2) ? t1 : t2;\ +}\ + + +#if defined (__GNUG__) && ! defined (__STRICT_ANSI__) +#define gpp_minmax(type, prefix)\ + prefix gpp_minmax_operator(type, ?, >) +#else +#define gpp_minmax(type, prefix) +#endif + +/** handy notations for a signed comparison. + make the operators{<,<=,==,>=,>} and the MAX and MIN of two. + Please fill a & in the type argument if necessary. + */ +#define template_instantiate_compare(type, function, prefix) \ +prefix one_operator(type, function, >)\ +prefix one_operator(type, function, >=)\ +prefix one_operator(type, function, ==)\ +prefix one_operator(type, function, !=)\ +prefix one_operator(type, function, <)\ +prefix one_operator(type, function, <=)\ +gpp_minmax(type, prefix)\ +prefix inline type max(type t1, type t2) { return (t1 > t2 )? t1 : t2; }\ +prefix inline type min(type t1, type t2) { return (t1 < t2 )? t1 : t2; }\ + \ +prefix bool operator<(type t1, type t2) /* stupid fix to allow ; */ + + + +#define instantiate_compare(type, func) template_instantiate_compare(type,func, ) + + + +#endif + diff --git a/flower/include/cursor.hh b/flower/include/cursor.hh new file mode 100644 index 0000000000..af2e251a08 --- /dev/null +++ b/flower/include/cursor.hh @@ -0,0 +1,113 @@ +// cursor.hh + +#ifndef __CURSOR_HH +#define __CURSOR_HH + +#include "link.hh" +template class List; + +/** iterator to List. + add and insert extend the list + items are always stored as copies in List, but: + List : copies of String stored + List : copies of String* stored! + + the operations add and insert actually delegate the work to List class. + */ +template +class Cursor +{ + public: + /** create cursor, set at top. The const part isn't true, actually, #list# + surely isn't const, but I get tired of the warning messages. */ + Cursor( const List& list, Link* pointer = 0 ); + + Cursor( const Cursor& cursor ); + + T& thing(); + + /// return current T + T& operator *() { return thing(); } + operator T() { return thing(); } + Cursor operator =( const Cursor& c ); + + /// make cursor with #no# items back + Cursor operator -( int no) const; + + /// make cursor with #no# items further + Cursor operator +( int no) const; + int operator -(Cursor op) const; + Cursor operator -=(int); + Cursor operator +=(int); + + /// return current and move one down + Cursor operator ++( int ); + + /// return current and move one up + Cursor operator --( int ); + + /// point to link? + bool ok(); + + /// ++ items left? + bool forward(); + + /// -- items left? + bool backward(); + + /** put (copy) after me in List. + analogously to editor. ok() interpreted as at end + of line. + + PRE: !ok, POST: added to bottom() + + PRE: ok, POST: added after me + + cursor points to same object, cursor.next() is newly added + object. + */ + void add( T const & thing ); + + /** put (copy) before me in List. + analogously to editor. ok() interpreted as at begin of + line. + + PRE: !ok, POST: add to top() + + PRE: ok, POST: add before me + + cursor points to same object, cursor.previous() + is newly inserted object. + */ + + void insert( T const & thing ); + /// + void backspace(); + + /// + void del(); + + /// access the list this came from + List& list() const ; + Link* pointer(); + static int compare(Cursor a,Cursorb) { return a-b; } +private: + List& list_; + Link* pointer_; +}; + + +/* + comparisons. + */ +#include "compare.hh" + + +template_instantiate_compare(Cursor, Cursor::compare, template); + +#include "pcursor.hh" +#include "list.hh" +#include "cursor.inl" +#include "iterate.hh" + +#endif // CURSOR_HH diff --git a/flower/include/cursor.tcc b/flower/include/cursor.tcc new file mode 100644 index 0000000000..3be73fe5d2 --- /dev/null +++ b/flower/include/cursor.tcc @@ -0,0 +1,109 @@ +#ifndef CURSOR_CC +#define CURSOR_CC + +#include "cursor.hh" +#include + +template + void +Cursor::backspace() +{ + Cursor c(*this); + if ( c.ok() ) + c--; + list_.remove( *this ); +} + +template + void +Cursor::del() +{ + Cursor c(*this); + if ( c.ok() ) + c++; + list_.remove( *this ); + *this = c; +} + + +template +Cursor +Cursor::operator -=( int j ) +{ + while (j--) + (*this)--; + return *this; +} +template +Cursor +Cursor::operator +=( int j ) +{ + while (j++) + (*this)++; + return *this; +} + +template +Cursor +Cursor::operator +( int i ) const +{ + Cursor r = *this; + + if (i<0) + return r -(-i); + + while (i--) + r++; + + return r; +} + +template +Cursor +Cursor::operator -( int i ) const +{ + Cursor r = *this; + if (i<0) + return r +(-i); + + while (i--) + r--; + + return r; +} +/* + warning: can't use Cursor::operator == (Cursor), + since it uses Cursor::operator-(Cursor) + */ +template +int +Cursor::operator-(Cursor rhs) const +{ + assert(rhs.list == list); + int dif = 0; + + // search from *this on further up (positive difference) + Cursor c(*this); + while (c.ok() && c.pointer_ != rhs.pointer_) { + c--; + dif++; + } + + if (c.ok()) + goto gotcha; // so, sue me. + + // search in direction of bottom. (negative diff) + dif =0; + c=*this; + while (c.ok() && c.pointer_ !=rhs.pointer_) { + dif --; + c++; + } + assert(c.ok()); + +gotcha: + assert((*this - dif).pointer_ == c.pointer_); + return dif; +} + +#endif diff --git a/flower/include/data-file.hh b/flower/include/data-file.hh new file mode 100644 index 0000000000..dae9e56347 --- /dev/null +++ b/flower/include/data-file.hh @@ -0,0 +1,59 @@ +/* + data-file.hh -- declare Data_file + + source file of the LilyPond music typesetter + + (c) 1997 Han-Wen Nienhuys +*/ + + +#ifndef DATAFILE_HH +#define DATAFILE_HH + +#include "text-stream.hh" + +/// read a data file +class Data_file : private Text_stream +{ + + public: + bool rawmode; + + Text_stream::line; + Text_stream::eof; + Text_stream::get_name; + + char data_get(); + void data_unget(char c) { + unget(c); + } + + /// read line, eat #\n# + String get_line(); + + /// read a word till next space, leave space. Also does quotes + String get_word(); + + /// gobble horizontal white stuff. + void gobble_white(); + + /// gobble empty stuff before first field. + void gobble_leading_white(); + Data_file(String s) : Text_stream(s) { + //*mlog << "(" << s << flush; + rawmode= false; + } + + ~Data_file() { + // *mlog << ")"< +struct Assoc; + +/** debug stream. + a class for providing debug output of nested structures, + with indents according to \{\}()[]. + + One can turn on and off specific messages using the Assoc silent. + This can be done automatically: + + #define DEBUG dstream_.identify_as(__PRETTY_FUNCTION__) + + DEBUG << "a message\n"; + + Init for the class names which should be silent can be given in a rc file. + + */ +class Dstream +{ + ostream *os; + int indentlvl; + bool local_silence; + String classname; + void output(String s); + Assoc *silent; +public: + + bool silence(String); + + /** + if rcfile == 0, then do not read any rc file. + */ + + Dstream(ostream *r, char const * rcfile); + virtual ~Dstream(); + Dstream &identify_as(String s); + + Dstream &operator << (String s); + /** + Output memory locations. + */ + Dstream &operator << (void const *); + Dstream &operator << (char const *); +}; +#endif + diff --git a/flower/include/fproto.hh b/flower/include/fproto.hh new file mode 100644 index 0000000000..c2fc98399c --- /dev/null +++ b/flower/include/fproto.hh @@ -0,0 +1,54 @@ +/* + fproto.hh -- typenames in flowerlib + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef FPROTO_HH +#define FPROTO_HH + + +char const * flower_version_sz(); + +// what the F*** is "int" ? +// depreciate int, long, etc., use i32, i64, remember: linux-16/linux-64 ? +/// (i32) +typedef int i32; +/// (i64) +typedef long long I64; + +template struct Array; +template struct sstack; +template struct Assoc; +template struct List; +template struct PointerList; +template struct IPointerList; +template struct Cursor; +template struct PCursor; +template struct Link; +template struct Handle; +template struct Interval_t; +template struct PQueue; + +#include "real.hh" + +typedef Interval_t Interval; + +struct Choleski_decomposition; + +struct Long_option_init; +struct Getopt_long; +struct Matrix; +struct String_data; +struct String_handle; +struct String_convert; +struct String; +struct virtual_smat; +struct Vector ; +struct Text_stream; +struct Data_file; +struct Text_db; +struct Scalar; +typedef unsigned char Byte; +#endif // FPROTO_HH + diff --git a/flower/include/handle.hh b/flower/include/handle.hh new file mode 100644 index 0000000000..26328bd26b --- /dev/null +++ b/flower/include/handle.hh @@ -0,0 +1,58 @@ +#ifndef HANDLE_HH +#define HANDLE_HH + +/// reference counting handle +template +class Handle { + T *obj; + int *refs; + + /// let go of ref. Delete if necessary + void down() { + if (!(*refs--)) { + delete obj; + delete refs; + } + obj = 0; + refs = 0; + } + /// point to new object. + void up(T *t, int *r) { + if (!r) { + refs = new int; + *refs = 1; + } else { + refs =r; + *refs++; + } + obj = t; + } + /// POST: *refs == 1 + void copy() { + if(*refs != 1){ + T * newobj = new T(*obj ); + down(); + up(newobj); + } + } + Handle(Handle const &src) { + up(src.obj, src.refs); + } + Handle(T & o) { + up (&o); + } + void operator=(Handle const& src) { + if (this == &src) + return; + down(); + up(src.o, src.refs); + } + operator T const &() { + return *obj; + } + operator T&() { + copy(); + return *obj; + } +} +#endif diff --git a/flower/include/interval.hh b/flower/include/interval.hh new file mode 100644 index 0000000000..aae16381db --- /dev/null +++ b/flower/include/interval.hh @@ -0,0 +1,125 @@ +/* + interval.hh -- part of flowerlib + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef INTERVAL_HH +#define INTERVAL_HH + +#include +#include "fproto.hh" +#include "real.hh" + + +/** a T interval. + this represents the closed interval [left,right]. + No invariants. T must be a totally ordered ring + */ +template +struct Interval_t { + T left, right; + + /* ************** */ + + T center() { return (left + right) / T(2);} + void translate(T t) { + left += t; + right += t; + } + T& idx(int j) { + if (j==-1) + return left; + else if (j==1) + return right; + else + assert(false); + return left; + } + T& operator[](int j) { + return idx(j); + } + T operator[](int j) const { + return ((Interval_t *)this)->idx(j); + } + T &max() { return right;} + T max()const { return right;} + T min()const{ return left; } + T &min(){ return left; } + /** + PRE + *this and h are comparable + */ + void unite(Interval_t h); + void intersect(Interval_t h); + + T length() const; + void set_empty() ; + bool empty() const { return left > right; } + Interval_t() { + set_empty(); + } + Interval_t(T m, T M) { + left =m; + right = M; + } + Interval_t &operator += (T r) { + left += r; + right +=r; + return *this; + } + String str() const; + bool elt_q(T r); +}; + + +/** + inclusion ordering. Crash if not comparable. + */ +template +int Interval__compare(const Interval_t&,Interval_t const&); + +/* + INLINE + */ + +#include "compare.hh" + +template_instantiate_compare(Interval_t&, Interval__compare, template); + + +template +inline Interval_t +intersection(Interval_t a, Interval_t const&b) +{ + a.intersect(b); + return a; + +} + + +template +inline +Interval_t operator +(T a,Interval_t i ) +{ + i += a; + return i; +} + +template +inline +Interval_t operator +(Interval_t i,T a ){ + return a+i; +} + +typedef Interval_t Interval; + + +#define Interval__instantiate(T) template struct Interval_t;\ + template int Interval__compare(const Interval_t&,Interval_t const&) + + +#endif // INTERVAL_HH + + + diff --git a/flower/include/interval.tcc b/flower/include/interval.tcc new file mode 100644 index 0000000000..6e7b0b1279 --- /dev/null +++ b/flower/include/interval.tcc @@ -0,0 +1,106 @@ +#include +#include +#include "interval.hh" +#include "string.hh" + + +template +int +_Interval__compare(const Interval_t&a,Interval_t const&b) +{ + if (a.left == b.left && a.right == b.right) + return 0; + + if (a.left <= b.left && a.right >= b.right) + return 1; + + if (a.left >= b.left && a.right <= b.right) + return -1; + + return -2; +} + + +template +int +Interval__compare(const Interval_t&a,Interval_t const&b) +{ + int i = _Interval__compare(a,b); + if (i < -1) + assert(false); + return i; +} + +#ifdef AIX +const Real INFTY = 1e8; // ARGh. AIX sucks +#else +const Real INFTY = HUGE_VAL; +#endif + +template +void +Interval_t::set_empty() +{ + left = INFTY; + right = -INFTY; +} + +template +T +Interval_t::length() const { + assert(right >= left); + return right-left; +} + +template +void +Interval_t::unite(Interval_t h) +{ + if (h.leftright) + right = h.right; +} + +/** + smallest Interval which includes *this and #h# + */ + +template +void +Interval_t::intersect(Interval_t h) +{ +#if defined (__GNUG__) && ! defined (__STRICT_ANSI__) + left = h.left >? left; + right = h.right +Interval_t +intersect(Interval_t x, Interval_t const &y) +{ + x.intersect(y); + return x; +} + +template +String +Interval_t::str() const +{ + if (empty()) + return "[empty]"; + String s("["); + + return s + left + "," + right +"]"; +} + +template +bool +Interval_t::elt_q(T r) +{ + return r >= left && r <= right; +} diff --git a/flower/include/iterate.hh b/flower/include/iterate.hh new file mode 100644 index 0000000000..1e924f0790 --- /dev/null +++ b/flower/include/iterate.hh @@ -0,0 +1,22 @@ +/* + iterate.hh -- define some list macros + + source file of the flowerlib + + (c) 1997 Han-Wen Nienhuys +*/ + + +#ifndef ITERATE_HH +#define ITERATE_HH + + + +#define iterator(set) typeof((set).top()) +#define iterator_bot(set) typeof((set).bottom()) + +// should use top() +#define iter_top(set,var) iterator(set) var(set) +#define iter_bot(set,var) iterator(set) var(set.bottom()) + +#endif // ITERATE_HH diff --git a/flower/include/lgetopt.hh b/flower/include/lgetopt.hh new file mode 100644 index 0000000000..22f45d2adb --- /dev/null +++ b/flower/include/lgetopt.hh @@ -0,0 +1,94 @@ +#ifndef LGETOPT_HH +#define LGETOPT_HH + +#include + + +class ostream; + +/** + a struct this for initialising the commandline options. + */ +struct Long_option_init { + bool take_arg; + char const * longname; + char shortname; + + ostream &printon(ostream &errorout); +}; + + +/** C++ for version of long_getopt. For processing GNU style command + line arguments. No pointer (return values, arguments) contents are + copied. */ +class Getopt_long { +public: + /** errorcodes: no error, argument expected, no argument expected, + unknown option, illegal argument (eg. int expected). */ + enum Errorcod { E_NOERROR = 0, E_ARGEXPECT, E_NOARGEXPECT, E_UNKNOWNOPTION, + E_ILLEGALARG } ; + + +private: + + /// the option info. + Long_option_init *the_opts; + int table_len; + + /// if doing short option, argv[optind][optindind] is processed next. + int optindind; + + /// the option found + Long_option_init *beet; + + /// get ready for processing next error. + bool next(); + Long_option_init *parselong(); + Long_option_init *parseshort(); + + ostream *errorout; + + /// report an error and abort + void report(Errorcod c); +public: + + /// argument. Set to 0 if not present + char* optarg; + + /// current error status + Errorcod error; + + /// return an integer (with err. detect) + long intarg(); + /// argv[optind] will be processed next. + int optind; + + /// the arguments + char **argv; + + /// the arg. count + int argc; + + /* *************** */ + + /** + What to do with errors. + report messages on #*os#, and abort. + if #os# is null, then do not report nor abort, just set #error# + */ + + void seterror(ostream *os); + + /// construct: pass arguments and option info. + Getopt_long(int c, char **v, Long_option_init *lo); + + /** get the next option. + @return pointer to next option found. + 0 if error occurred, or next argument is no option. + */ + Long_option_init *operator()(); + + char *current_arg(); + char * get_next_arg(); +}; +#endif diff --git a/flower/include/libc-extension.hh b/flower/include/libc-extension.hh new file mode 100644 index 0000000000..96f3df00e1 --- /dev/null +++ b/flower/include/libc-extension.hh @@ -0,0 +1,33 @@ +/* + libc-extension.hh -- declare some string.h extensions + + source file of the flowerlib + + (c) 1997 Han-Wen Nienhuys +*/ + + +#ifndef LIBC_EXTENSION_HH +#define LIBC_EXTENSION_HH +#include "fproto.hh" +#include "config.hh" + +char* strnlwr( char* start_l ,int n); +char* strnupr( char* start_l, int n); + +#if !HAVE_MEMMEM // GNU extension. +char *memmem(Byte const * haystack, int haystack_len, + Byte const *needle, int needle_len); +#endif HAVE_MEMMEM + +#if !HAVE_SNPRINTF // GNU extension. +int snprintf (char *str, size_t n, + char const *format, ... ); +#endif + + +Byte *memrchr(Byte const * p, int n, char c); +Byte *strrev( Byte* byte_l, int length_i ); + + +#endif // LIBC_EXTENSION_HH diff --git a/flower/include/link.hh b/flower/include/link.hh new file mode 100644 index 0000000000..22fcec4e71 --- /dev/null +++ b/flower/include/link.hh @@ -0,0 +1,38 @@ +// link.hh + +#ifndef __LINK_HH +#define __LINK_HH +template +class List; + + +/// class for List +template +class Link +{ +// friend class Cursor; +public: + Link( T const & thing ); + + Link* previous(); + Link* next(); + + /// put new Link item after me in list + void add( T const & thing ); + /// put new Link item before me in list + void insert( T const & thing ); + void remove(List &l); + + T& thing(); + void OK() const; +private: + Link( Link* previous, Link* next, T const & thing ); + + T thing_; + Link* previous_; + Link* next_; +}; + +#include "link.inl" + +#endif // __LINK_HH // diff --git a/flower/include/list.hh b/flower/include/list.hh new file mode 100644 index 0000000000..fbb79e6edf --- /dev/null +++ b/flower/include/list.hh @@ -0,0 +1,98 @@ +#ifndef __LIST_HH +#define __LIST_HH + +class ostream; +template class Cursor; +template class Link; + +/** all-purpose doubly linked list. + + List can be seen as all items written down on paper, + from top to bottom + + class Cursor is used to extend List + + items are always stored as copies in List, but: + #List# : copies of #String# stored + #List# : copies of #String*# stored! + (do not use, use \Ref{PointerList} ## instead.) + + {\bf note:} + retrieving "invalid" cursors, i.e. + #top()/bottom()# from empty list, #find()# without success, + results in a nonvalid Cursor ( #!ok()# ) + + + INVARIANTEN! +*/ + +template +class List +{ + public: + List(List const&src); + + /// construct empty list + List(); + virtual ~List(); + + int size() const; + + Cursor bottom() const; // const sucks. + Cursor top() const; + + void OK() const; // check list + + protected: + friend class Cursor; + friend class Link; + + void concatenate(List const &s); + + /** make *this empty. + + POST: + size == 0 + + WARNING: + contents lost, and not deleted. + */ + void set_empty(); + + void add( T const & thing, Cursor &after_me ); + + /// put thing before #before_me# + void insert( T const & thing, Cursor &before_me ); + + /** Remove link pointed to by me. Destructor of contents called + (nop for pointers) + + POST + none; + + + WARNING: do not use #me# after calling + */ + void remove( Cursor me ); + + + /* ************** */ + + int size_; + Link* top_; + Link* bottom_; +}; + +#include "list.inl" +#include "cursor.hh" + +// instantiate a template: explicit instantiation. +#define L_instantiate(a) template class List; template class Cursor; \ + template class Link + + +#endif // __LIST_HH // + + + + diff --git a/flower/include/list.tcc b/flower/include/list.tcc new file mode 100644 index 0000000000..bd3a16b0c6 --- /dev/null +++ b/flower/include/list.tcc @@ -0,0 +1,112 @@ +#ifndef LIST_CC +#define LIST_CC + +#include "list.hh" + +template +List::List(List const&src) +{ + set_empty(); + // probably el stupido + for (Cursor c(src); c.ok(); c++) + bottom().add(c); +} + +template +void +List::OK() const +{ + int i = size_; + Link *lp = top_; + while (i--) { + assert(lp); + lp->OK(); + lp = lp->next(); + } + assert(!lp); + i = size_; + lp = bottom_; + while (i--) { + assert(lp); + lp->OK(); + lp = lp->previous(); + } + assert(!lp); +} + + +template +List::~List() +{ + Cursor c(*this); + while (c.ok()) + c.del(); +} + +/** + + add after after_me. + + Procedure: + \begin{itemize} + \item if #after_me# is #ok()#, add after #after_me#, else + \item if list !empty simply add to bottom, else + \item list is empty: create first \Ref{Link} and initialize + #bottom_# and #top_#. + \end{itemize} +*/ +template +void +List::add( T const & thing, Cursor &after_me ) +{ + if (!size_) { // not much choice if list is empty + bottom_ = top_ = new Link( thing ); + if (!after_me.ok()) + after_me = bottom(); + } else { // add at aprioprate place + if (!after_me.ok()) + after_me = bottom(); + Link *p =after_me.pointer(); + p->add(thing); + if (p == bottom_) // adjust bottom_ if necessary. + bottom_ = p->next(); + } + + size_++; +} + +template +void +List::insert( T const & thing, Cursor &before_me ) +{ + if (!size_) { + bottom_ = top_ = new Link( thing ); + if (!before_me.ok()) + before_me = top(); + + } else { + if (!before_me.ok()) + before_me = top(); + + Link *p = before_me.pointer() ; + + p->insert(thing); + if (p == top_) + top_ = p->previous(); + } + + size_++; +} + + +template +void +List::concatenate(List const&s) +{ + Cursor b(bottom()); + for (Cursor c(s); c.ok(); c++) { + b.add(c); + b++; + } +} +#endif diff --git a/flower/include/matrix.hh b/flower/include/matrix.hh new file mode 100644 index 0000000000..e4f447041b --- /dev/null +++ b/flower/include/matrix.hh @@ -0,0 +1,135 @@ +#ifndef MATRIX_HH +#define MATRIX_HH + + +#include "vsmat.hh" +#include "vector.hh" + +/** a Real matrix. This is a class for a nonsquare block of #Real#s. The + implementation of sparse matrices is done in the appropriate #smat# + class. Matrix only does the mathematical actions (adding, + multiplying, etc.) + + + TODO + implement ref counting? */ + + +class Matrix { + virtual_smat *dat; + +public: + void OK() const { dat->OK(); } + int cols() const { return dat->cols(); } + int rows() const { return dat->rows(); } + + /** return the size of a matrix. + PRE + the matrix needs to be square. + */ + int dim() const; + + // Matrix() { dat = 0; } + ~Matrix() { delete dat; } + + /// set entries to r + void fill(Real r); + + /// set diagonal to d + void set_diag(Real d); + + void set_diag(Vector d); + /// set unit matrix + void unit() { set_diag(1.0); } + + void operator+=(Matrix const &m); + void operator-=(Matrix const &m); + void operator*=(Real a); + void operator/=(Real a) { (*this) *= 1/a; } + + /** add a row. + add a row to the matrix before row k + + PRE + v.dim() == cols() + 0 <= k <= rows() + */ + void insert_row(Vector v,int k); + /** . + delete a row from this matrix. + + PRE + 0 <= k < rows(); + */ + void delete_row(int k) { dat->delete_row(k); } + void delete_column(int k) { dat->delete_column(k); } + + /** + square n matrix, initialised to null + */ + Matrix(int n); + + /** + n x m matrix, init to 0 + */ + Matrix(int n, int m); + Matrix(Matrix const &m); + + /// dyadic product: v * w.transpose + Matrix(Vector v, Vector w); + void operator=(Matrix const &m); + + /// access an element + Real operator()(int i,int j) const { return dat->elem(i,j); } + + /// access an element + Real &operator()(int i, int j) { return dat->elem(i,j); } + + /// Matrix multiply with vec (from right) + Vector operator *(Vector const &v) const; + + /// set this to m1*m2. + void set_product(Matrix const &m1, Matrix const &m2); + + + Vector left_multiply(Vector const &) const; + + Matrix operator-() const; + + /// transpose this. + void transpose(); + + /// return a transposed copy. + Matrix transposed() const ; + + Real norm() const; + /** swap. + PRE + 0 <= c1,c2 < cols() + */ + void swap_columns(int c1, int c2); + + /** swap. + PRE + 0 <= c1,c2 < rows() + */ + void swap_rows(int c1, int c2); + + + Vector row(int ) const; + Vector col(int) const; + + operator String() const; + void print() const; +}; + +inline Vector +operator *(Vector &v, Matrix const & m) { return m.left_multiply(v); } +Matrix operator *(Matrix const & m1,Matrix const &m2); +Matrix operator /(Matrix const &m1,Real a); +inline Matrix operator -(Matrix m1,const Matrix m2) +{ + m1 -= m2; + return m1; +} +#endif diff --git a/flower/include/path.hh b/flower/include/path.hh new file mode 100644 index 0000000000..bc4d9f3776 --- /dev/null +++ b/flower/include/path.hh @@ -0,0 +1,32 @@ +#ifndef PATH_HH +#define PATH_HH +#include "string.hh" +#include "varray.hh" + + +/** searching directory for file. + + Abstraction of PATH variable. An interface for searching input files. + Search a number of dirs for a file. + + Should use kpathsea? + +*/ + +class File_path : private Array +{ +public: + /// locate a file in the search path + String find(String nm); + + /// construct using prefix. Normally argv[0]. + File_path(String); + + /// add to end of path. + Array::push; + void add(String str) { push(str); } +}; +/// split path into its components +void split_path(String path, String &drive, String &dirs, String &filebase, String &extension); + +#endif diff --git a/flower/include/pcursor.hh b/flower/include/pcursor.hh new file mode 100644 index 0000000000..37512d553b --- /dev/null +++ b/flower/include/pcursor.hh @@ -0,0 +1,68 @@ +/* + pcursor.hh -- part of flowerlib + + (c) 1996 Han-Wen Nienhuys&Jan Nieuwenhuizen +*/ + +#ifndef PCURSOR_HH +#define PCURSOR_HH + +#include "plist.hh" +#include "cursor.hh" + +/** cursor to go with PointerList. + don't create PointerList's. + This cursor is just an interface class for Cursor. It takes care of the + appropriate type casts + */ +template +class PCursor : private Cursor { + friend class IPointerList; + + /// delete contents + void junk(); +public: + Cursor::ok; + Cursor::del; + Cursor::backspace; + T remove_p() { + T p = ptr(); + Cursor::del(); + return p; + } + T remove_prev_p() { + assert( ok() ); + (*this)--; + return remove_p(); + } + + PointerList &list() { return (PointerList&)Cursor::list(); } + PCursor operator++(int) { return Cursor::operator++(0);} + PCursor operator--(int) { return Cursor::operator--(0); } + PCursor operator+=(int i) { return Cursor::operator+=(i);} + PCursor operator-=(int i) { return Cursor::operator-=(i); } + PCursor operator -(int no) const { return Cursor::operator-(no);} + int operator -(PCursor op) const { return Cursor::operator-(op);} + PCursor operator +( int no) const {return Cursor::operator+(no);} PCursor(const PointerList & l) : Cursor (l) {} + + PCursor( const Cursor& cursor ) : Cursor(cursor) { } + void* vptr() const { return *((Cursor &) *this); } + + // should return T& ? + T ptr() const { return (T) vptr(); } + T operator ->() const { return ptr(); } + operator T() { return ptr(); } + T operator *() { return ptr(); } + void add(T const & p ) { Cursor::add((void*) p); } + void insert(T const & p ) { Cursor::insert((void*) p);} + static int compare(PCursor a,PCursorb) { + return Cursor::compare(a,b); + } +}; + + + +#include "compare.hh" +template_instantiate_compare(PCursor, PCursor::compare, template); + +#endif diff --git a/flower/include/pcursor.tcc b/flower/include/pcursor.tcc new file mode 100644 index 0000000000..ffb01bcfe8 --- /dev/null +++ b/flower/include/pcursor.tcc @@ -0,0 +1,16 @@ +#include "pcursor.hh" + +template +void +PCursor::junk() +{ +#if !defined(NDEBUG) && defined(PARANOID) + list().OK(); +#endif + + delete ptr(); +#if !defined(NDEBUG)&&defined(PARANOID) + thing() = 0; + list().OK(); +#endif +} diff --git a/flower/include/plist.hh b/flower/include/plist.hh new file mode 100644 index 0000000000..f9af4c693b --- /dev/null +++ b/flower/include/plist.hh @@ -0,0 +1,72 @@ +/* + list.hh -- part of flowerlib + + (c) 1996 Han-Wen Nienhuys & Jan Nieuwenhuizen +*/ + +#ifndef PLIST_HH +#define PLIST_HH + +#include "list.hh" + +/** + A list of pointers. + + Use for list of pointers, e.g. PointerList. + This class does no deletion of the pointers, but it knows how to + copy itself (shallow copy). We could have derived it from List, + but this design saves a lot of code dup; for all PointerLists in the + program only one parent List is instantiated. + */ +template +class PointerList : public List +{ + public: + PCursor top() const{ + return PCursor (List::top()); + } + PCursor bottom() const { + return PCursor (List::bottom()); + } + PCursor find(T) const; + void concatenate(PointerList const &s) { List::concatenate(s); } + PointerList() {} +}; + +/** PointerList which deletes pointers given to it. + NOTE: + + The copy constructor doesn't do what you'd want: + Since T might have a virtual ctor, we don't try to do a + + new T(*cursor) + + You have to copy this yourself, or use the macro PointerList__copy + + */ +template +class IPointerList : public PointerList { +public: + IPointerList(IPointerList const &) { set_empty(); } + IPointerList() { } + ~IPointerList(); +}; + +#define IPointerList__copy(T, to, from, op) \ + for (PCursor _pc_(from); _pc_.ok(); _pc_++)\ + to.bottom().add(_pc_->op)\ + \ + + +template +void PL_copy(IPointerList &dst,IPointerList const&src); + + +#define PL_instantiate(a) template class PointerList; \ + template class PCursor; +#define IPL_instantiate(a) PL_instantiate(a); \ + template class IPointerList + +#include "plist.inl" + +#endif diff --git a/flower/include/plist.tcc b/flower/include/plist.tcc new file mode 100644 index 0000000000..ac9daedf71 --- /dev/null +++ b/flower/include/plist.tcc @@ -0,0 +1,21 @@ +#include "plist.hh" + +template +IPointerList::~IPointerList() +{ + PCursor c( *this ); + while (c.ok()) { + delete c.remove_p(); + } +} + +template +PCursor +PointerList::find(T what ) const +{ + PCursor i(*this); + for (; i.ok(); i++) + if (i.ptr() == what) + break; + return i; +} diff --git a/flower/include/pqueue.hh b/flower/include/pqueue.hh new file mode 100644 index 0000000000..c8dfe1bea6 --- /dev/null +++ b/flower/include/pqueue.hh @@ -0,0 +1,72 @@ +/* + pqueue.hh -- declare + + source file of the LilyPond music typesetter + + (c) 1997 Han-Wen Nienhuys +*/ + + +#ifndef PQUEUE_HH +#define PQUEUE_HH + +#include "varray.hh" + +/** + Stupid Prioq. Should use Lists and STL. + Smallest is put at the front. + +Actually, this sux. Should use a template struct PQuee_ent + */ + +template +struct PQueue +{ + Array value_arr_; + Array indices_arr_; + void OK() const + { + + assert(value_arr_.size() == indices_arr_.size()); + } + + void enter(V v, I idx) { + int j=0; + for (; j < value_arr_.size(); j++) + if (indices_arr_[j] > idx) + break; + + insert(j,v,idx); + + } + int size() { return value_arr_.size(); } + V front_val() { return value_arr_[0]; } + I front_idx() { return indices_arr_[0]; } + void del(int i) + { + value_arr_.del(i); + indices_arr_.del(i); + } + int size() const + { + OK(); + return value_arr_.size(); + } + + + void insert(int j, V v, I idx) + { + value_arr_.insert(v, j); + indices_arr_.insert(idx, j); + } + + + + V get() { + V retval = front_val(); + del(0); + return retval; + } + +}; +#endif // PQUEUE_HH diff --git a/flower/include/rational.hh b/flower/include/rational.hh new file mode 100644 index 0000000000..30fa2cb6d6 --- /dev/null +++ b/flower/include/rational.hh @@ -0,0 +1 @@ +#include diff --git a/flower/include/real.hh b/flower/include/real.hh new file mode 100644 index 0000000000..0533af2111 --- /dev/null +++ b/flower/include/real.hh @@ -0,0 +1,16 @@ +#ifndef REAL_HH +#define REAL_HH + + +#include +#include +#include + +typedef double Real; + +inline Real +distance(Real x,Real y) +{ + return abs(x-y); +} +#endif diff --git a/flower/include/scalar.hh b/flower/include/scalar.hh new file mode 100644 index 0000000000..08897ce50c --- /dev/null +++ b/flower/include/scalar.hh @@ -0,0 +1,34 @@ +/* + scalar.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef SCALAR_HH +#define SCALAR_HH +#include "string.hh" +#include "real.hh" + +/// Perl -like scalar type. +struct Scalar : public String { + + Scalar(Real r) : String(r) {} + Scalar(int i) : String(i) {} + Scalar(char c) : String(c) {} + Scalar(char const *c) : String(c) {} + Scalar(String s ):String(s) {} + Scalar(Rational ); + operator Rational(); + Scalar() {} + bool isnum(); + operator Real(); + operator int(); + + /** perl -like string to bool conversion. + */ + operator bool() const; + +}; + +#endif // SCALAR_HH + diff --git a/flower/include/smat.hh b/flower/include/smat.hh new file mode 100644 index 0000000000..05bdac464b --- /dev/null +++ b/flower/include/smat.hh @@ -0,0 +1,93 @@ +#ifndef SMAT_HH +#define SMAT_HH +#include "varray.hh" +#include "vsmat.hh" +#include "real.hh" +/// simplest matrix storage. refer to its baseclass for the doco. +class Full_storage : public virtual_smat +{ + /// height, width + int h,w; + /// maxima. + int maxh, maxw; + + /// the storage + Real** els; + void + init() { + els=0; + h=w=maxh=maxw=0; + + } + + bool valid(int i, int j) const { + return (i>=0 && i < h) + && (j < w && j >=0); + } + + + void resize_rows(int); + void resize_cols(int); + +public: + virtual int rows() const { + return h; + } + virtual int cols() const { + return w; + } + + + virtual void set_size(int i, int j) + { + resize(i,j); //this could be more efficient. + } + + virtual void set_size(int i) { + set_size(i,i); + } + virtual void resize(int i, int j); + virtual void resize(int i) { + resize(i,i); + } + + virtual Real& elem(int i,int j) { + assert(valid(i,j)); + return els[i][j]; + } + virtual Real const & elem(int i, int j) const { + assert(valid(i,j)); + return els[i][j]; + } + virtual Array row(int i) const; + virtual Array column(int j) const; + + Full_storage() { + init(); + } + Full_storage(int i, int j) { + init(); + set_size(i,j); + } + Full_storage(Full_storage&); + Full_storage(int i) { + init(); + set_size(i); + } + void OK() const; + void operator=(Full_storage const &); + + virtual void insert_row(int k); + virtual void delete_row(int k); + virtual void delete_column(int k); + + + ~Full_storage(); + virtual bool mult_ok(int i, int j)const; + virtual void mult_next(int &i, int &j) const ; + virtual bool trans_ok(int i, int j) const; + virtual void trans_next(int &i, int &j) const; + virtual virtual_smat * clone(); +}; + +#endif diff --git a/flower/include/string-convert.hh b/flower/include/string-convert.hh new file mode 100644 index 0000000000..9eb9869653 --- /dev/null +++ b/flower/include/string-convert.hh @@ -0,0 +1,45 @@ +/* + PROJECT: FlowerSoft C++ library + FILE : string-convert.hh + +*/ + +#ifndef STRING_CONVERT_HH +#define STRING_CONVERT_HH + +/* + ///a class which only has functions. +//#define functor class // cute. docxx fucks up +*/ + +/** + The functor String_convert handles all conversions to/from String (some + time, anyway). + The class is quite empty from data view. + */ +class String_convert { + static int hex2bin_i( String hex_str, String& bin_str_r ); + static int hex2nibble_i( Byte byte ); + static Byte nibble2hex_byte( Byte byte ); +public: + static String bin2dec_str( String bin_str ); + static String bin2hex_str( String bin_str ); + static String dec2bin_str( String str ); + static int bin2_i( String str ); + static String char_str(char c, int n); + static int dec2_i( String dec_str ); + static double dec2_f( String dec_str ); + static String double_str(double f, char const* fmt=0); + static int hex2_i( String str ); + static unsigned hex2_u( String str ); + static String hex2bin_str( String str ); + static String int_str(int i, char const *fmt=0 ); + static String i2hex_str( int i, int length_i, char ch ); + static String u2hex_str( unsigned u, int length_i, char ch ); + static String i2dec_str( int i, int length_i, char ch ); + static String rational_str(Rational); + static String pointer_str(void const *); + static String i64_str(I64, char const * fmt = 0); +}; + +#endif // __STRING_CONVERT_HH // diff --git a/flower/include/string-data.hh b/flower/include/string-data.hh new file mode 100644 index 0000000000..ecd7159074 --- /dev/null +++ b/flower/include/string-data.hh @@ -0,0 +1,95 @@ +/* + string-data.hh -- declare String_data + + source file of the LilyPond music typesetter + + (c) 1997 Han-Wen Nienhuys +*/ + + +#ifndef STRINGDATA_HH +#define STRINGDATA_HH + + +/**Internal String struct. + the data itself. Handles simple tasks (resizing, resetting) + */ +class String_data { + // GNU malloc: storage overhead is 8 bytes anyway. + +friend class String_handle; + int maxlen; // maxlen is arraysize-1 + + int length_i_; + Byte* data_byte_p_; + int references; + + /// init to "" + String_data(); + + /// init from src. Conservative allocation. + String_data(String_data const &src); + + ~String_data(); + + /** POST: maxlen >= j. + @param j, maximum stringlength_i_. + contents thrown away. + */ + void setmax(int j); + + /** POST: maxlen >= j. + @param j, maximum stringlength_i_. + contents are kept if it grows. + */ + void remax(int j); + + /// check if writeable. + void OKW(); + + /// check state. + void OK(); + + /// reduce memory usage. + void tighten(); + + // assignment. + void set( Byte const* byte_c_l, int length_i ); + + void set( char const* ch_c_l ); + + /// concatenation. + void append( Byte const* byte_c_l, int length_i ); + + void operator += ( char const* ch_c_l ); + + char const* ch_c_l() const; + + char* ch_l(); + + Byte const* byte_c_l() const; + + // idem, non const + Byte* byte_l(); + + void trunc(int j); + + /** access element. not really safe. Can alter length_i_ without + #String_data# knowing it. */ + Byte &operator [](int j); + Byte operator [](int j) const; + bool is_binary_bo()const; +}; + + + +#ifdef STRING_UTILS_INLINED +#ifndef INLINE +#define INLINE inline +#endif +#include "string-data.inl" + +#endif + + +#endif // STRING_DATA_HH diff --git a/flower/include/string-handle.hh b/flower/include/string-handle.hh new file mode 100644 index 0000000000..5b7a12f648 --- /dev/null +++ b/flower/include/string-handle.hh @@ -0,0 +1,70 @@ +/* + string-handle.hh -- declare String_handle + + source file of the LilyPond music typesetter + + (c) 1997 Han-Wen Nienhuys +*/ + + +#ifndef STRINGHANDLE_HH +#define STRINGHANDLE_HH +#include "fproto.hh" + + +/** + Reference counting for strings. + + handles ref. counting, and provides a very thin interface using + Byte * + + */ +class String_handle { + String_data* data; + + /// decrease ref count. Named kind of like a Tanenbaum semafore + void down(); + + /// increase ref count + void up(String_data *d); + + /** make sure data has only one reference. + POST: data->references == 1 + */ + void copy(); + +public: + String_handle(); + ~String_handle(); + String_handle(String_handle const & src); + + Byte const* byte_c_l() const; + char const* ch_c_l() const; + Byte* byte_l(); + char* ch_l(); + bool is_binary_bo()const; + void operator =(String_handle const &src); + void operator += (char const *s); + Byte operator[](int j) const; + + /** Access elements. WARNING: NOT SAFE + don't use this for loops. Use byte_c_l() + */ + Byte &operator[](int j); + void append( Byte const* byte_c_l, int length_i ); + void set( Byte const* byte_c_l, int length_i ); + void operator = (char const *p); + void trunc(int j); + int length_i() const; +}; + +#ifdef STRING_UTILS_INLINED +#ifndef INLINE +#define INLINE inline +#endif +#include "string-handle.inl" +/* we should be resetting INLINE. oh well. */ +#endif + + +#endif // STRINGHANDLE_HH diff --git a/flower/include/string.hh b/flower/include/string.hh new file mode 100644 index 0000000000..8270e01e08 --- /dev/null +++ b/flower/include/string.hh @@ -0,0 +1,193 @@ +/* + + FILE : string.hh -- declare String + + Rehacked by HWN 3/nov/95 + removed String & 's + introduced Class String_handle + */ + +#ifndef STRING_HH +#define STRING_HH + + +#include +#include +#include + +#include "string-handle.hh" + +/** + + Intuitive string class. provides +\begin{itemize} +\item + ref counting through #String_handle# +\item + conversion from bool, int, double, char* , char. +\item + to be moved to String_convert: + conversion to int, upcase, downcase + +\item + printable. + +\item + indexing (index_i, index_any_i, last_index_i) + +\item + cutting (left_str, right_str, mid_str) + +\item + concat (+=, +) + +\item + signed comparison (<, >, ==, etc) + +\item + No operator[] is provided, since this would be enormously slow. If needed, + convert to char const* . +\end{itemize} + +*/ +class String +{ +protected: + String_handle strh_; + + bool null_terminated(); + +public: + + /** init to empty string. This is needed because other + constructors are provided.*/ + String() { } + String(Rational); + + /// String s = "abc"; + String( char const* source ); + String( Byte const* byte_c_l, int length_i ); + + /// "ccccc" + String( char c, int n = 1 ); + + String( int i , char const *fmt=0); + String ( double f , char const* fmt =0); + /// 'true' or 'false' + String(bool ); + + /// return a "new"-ed copy of contents + Byte* copy_byte_p() const; // return a "new"-ed copy of contents + + char const* ch_c_l() const; + Byte const* byte_c_l() const; + char* ch_l(); + Byte* byte_l(); + + /// deprecated; use ch_c_l() + operator char const* () const { return ch_c_l(); } + + String &operator =( String const & source ); + + /// concatenate s + void operator += (char const* s) { strh_ += s; } + void operator += (String s); + + void append(String); + void prepend(String); + + char operator []( int n ) const { return strh_[n]; } + + /// return n leftmost chars + String left_str( int n ) const; + + /// return n rightmost chars + String right_str( int n ) const; + + /// return uppercase of *this + String upper_str() const; + + /// return lowercase of *this + String lower_str() const; + + /// return the "esrever" of *this + String reversed_str() const; + + + /// return a piece starting at index_i (first char = index_i 0), length n + String mid_str(int index_i, int n ) const; + + /// cut out a middle piece, return remainder + String nomid_str(int index_i, int n ) const; + + /// signed comparison, analogous to memcmp; + static int compare_i(String const & s1,const String& s2); + + /// index of rightmost c + int index_last_i( char c) const; + + /// index of rightmost element of string + int index_last_i( char const* string ) const; + + int index_i(char c ) const; + int index_i(String ) const; + int index_any_i(String ) const; + + void to_upper(); + void to_lower(); + /// provide Stream output + void print_on(ostream& os) const; + + /// the length of the string + int length_i() const; + + // ***** depreciated + int len() const { + return length_i(); + } + + /// convert to an integer + int value_i() const; + + /// convert to a double + double value_f() const; +}; + +#include "compare.hh" + +instantiate_compare(String const &, String::compare_i); + +// because char const* also has an operator ==, this is for safety: +inline bool operator==(String s1, char const* s2){ + return s1 == String(s2); +} +inline bool operator==(char const* s1, String s2) +{ + return String(s1)==s2; +} +inline bool operator!=(String s1, char const* s2 ) { + return s1!=String(s2); +} +inline bool operator!=(char const* s1,String s2) { + return String(s2) !=s1; +} + + +inline String +operator + (String s1, String s2) +{ + s1 += s2; + return s1; +} + +inline ostream & +operator << ( ostream& os, String d ) +{ + d.print_on(os); + return os; +} + + +// String quoteString(String message, String quote); + +#endif diff --git a/flower/include/text-db.hh b/flower/include/text-db.hh new file mode 100644 index 0000000000..3535a84f8f --- /dev/null +++ b/flower/include/text-db.hh @@ -0,0 +1,55 @@ +#ifndef TEXTDB_HH +#define TEXTDB_HH + +#include "data-file.hh" + +/**a "const" Array. Contents can't be changed. do "#" comments, read quote enclosed fields */ + +class Text_record : Array +{ + int line_no; + String filename; + +public: + Text_record() { } // needed because of other ctor + + /// report an error in this line. + message(String s) { + cerr << '\n'<< filename << ": "<< line_no << s << "\n"; + } + String operator[](int j) { + return Array::operator[](j); + } + + Text_record(Array s, String fn, int j) : Array(s) { + filename = fn; line_no = j; + } + Array::size; +}; + +/** abstraction for a datafile. + add a subrec/fieldsep/record separator + */ + +class Text_db : private Data_file +{ + void gobble_leading_white(); +public: + /// get a line with records + Text_record get_record(); + + Text_db(String fn):Data_file(fn) { } + Data_file::error; + bool eof(); + + /// get next line. + Text_record operator++(int) { + return get_record(); + } + /// are we done yet? + operator bool() { + return !eof(); + } +}; + +#endif diff --git a/flower/include/text-stream.hh b/flower/include/text-stream.hh new file mode 100644 index 0000000000..437f8698c7 --- /dev/null +++ b/flower/include/text-stream.hh @@ -0,0 +1,74 @@ + +#ifndef TEXTSTR_HH +#define TEXTSTR_HH + +#include +#include +#include "string.hh" +#include "varray.hh" + +/** + line counting input stream. + a stream for textfiles. linecounting. Thin interface getchar and + ungetchar. (ungetc is unlimited) + + should protect get and unget against improper use +*/ + + +class Text_stream +{ + int line_no; + + // could just have used streams. + FILE *f; + Array pushback; + String name; + + public: + Text_stream(String fn); + String get_name() { return name; } + bool eof() { + return feof(f); + } + bool eol() { + return (peek() == '\n'); + } + char peek() { + char c = get(); + unget(c); + return c; + } + int line(){ + return line_no; + } + + char get() { + char c; + + if (pushback.empty()) + c = getc(f); + else + c = pushback.pop(); + + if (c =='\n') + line_no++; + return c; + } + void unget(char c) { + if (c =='\n') + line_no--; + pushback.push(c); + } + ~Text_stream (){ + if (!eof()) + cerr <<__FUNCTION__<< ": closing unended file"; + + fclose(f); + } + + /// GNU format message. + void message(String s); +}; + +#endif diff --git a/flower/include/unionfind.hh b/flower/include/unionfind.hh new file mode 100644 index 0000000000..fbaa51e731 --- /dev/null +++ b/flower/include/unionfind.hh @@ -0,0 +1,25 @@ +#ifndef UNIONFIND_HH +#define UNIONFIND_HH +#include "varray.hh" + +/* + which points of a graph are connected?. + Union find, a standard algorithm: + + Union_find represents an undirected graph of N points. You can + connect two points using #connect()#. #find(i)# finds a uniquely + determined representant of the equivalence class of points + connected to #i#. + + */ +struct Union_find { + void connect(int i, int j); + int find(int i); + bool equiv(int i, int j) { return find(i) == find(j); } + Union_find(int sz); + +private: + Array classes; + +}; +#endif diff --git a/flower/include/varray.hh b/flower/include/varray.hh new file mode 100644 index 0000000000..b7400bb501 --- /dev/null +++ b/flower/include/varray.hh @@ -0,0 +1,186 @@ +/* + (c) Han-Wen Nienhuys 1995,96 + + Distributed under GNU GPL +*/ + +#ifndef ARRAY_H +#define ARRAY_H +#include + +/// copy a bare (C-)array from #src# to #dest# sized #count# +template +inline void arrcpy(T*dest, T*src, int count) { + for (int i=0; i < count ; i++) + *dest++ = *src++; +} + + +/** + Scaleable array/stack template, for a type T with default constructor. + + + This template implements a scaleable vector. With (or without) range + checking. It may be flaky for objects with complicated con- and + destructors. The type T should have a default constructor. It is + best suited for simple types, such as int, double or String, it + provides a paranoidly safe replacement for the new T[int] construct. + + It uses stack terminology, (push, pop, top), and can be used as a stack. + + + */ +template +class Array { +protected: + /// maximum length of array. + int max; + + /// the data itself + T *thearray; + + /// stretch or shrink array. + void remax(int newmax) { + T* newarr = new T[newmax]; + size_ = (newmax < size_) ? newmax : size_; + arrcpy(newarr, thearray, size_); + + delete[] thearray; + thearray = newarr; + max = newmax; + } + int size_; + +public: + /// check invariants + void OK() const { + assert(max >= size_ && size_ >=0); + if (max) assert(thearray); + } + /** report the size_. + @see {setsize_} + */ + int size() const { return size_; } + + /// POST: size() == 0 + void clear() { size_ = 0; } + + Array() { thearray = 0; max =0; size_ =0; } + + + /** set the size_ to #s#. + POST: size() == s. + Warning: contents are unspecified */ + void set_size(int s) { + if (s >= max) remax(s); + size_ = s; + } + + ~Array() { delete[] thearray; } + + /// return a "new"ed copy of array + T* copy_array() const { + T* Tarray = new T[size_]; + arrcpy(Tarray, thearray, size_); + return Tarray; + } + // depracated + operator T* () const { + return copy_array(); + } + void operator=(Array const & src) { + set_size (src.size_); + arrcpy(thearray,src.thearray, size_); + } + Array(Array const & src) { + thearray = src.copy_array(); + max = size_ = src.size_; + } + + /// tighten array size_. + void precompute () { remax(size_); } + + /// this makes Array behave like an array + T &operator[] (const int i) const { + assert(i >=0&&i=0 && j<= size_); + set_size(size_+1); + for (int i=size_-1; i > j; i--) + thearray[i] = thearray[i-1]; + thearray[j] = k; + } + void del(int i) { + assert(i >=0&& i < size_); + arrcpy(thearray+i, thearray+i+1, size_-i-1); + size_--; + } + // quicksort. + void sort (int (*compare)( T const&,T const&), + int lower = -1, int upper = -1 ) { + if (lower < 0) { + lower = 0 ; + upper = size()-1; + } + if (lower >= upper) + return; + swap(lower, (lower+upper)/2); + int last = lower; + for (int i= lower +1; i <= upper; i++) + if (compare(thearray[i], thearray[lower]) < 0 ) + swap( ++last,i); + swap(lower, last); + sort(compare, lower, last-1); + sort(compare, last+1, upper); + } + void concat(Array const &src) { + int s = size_; + set_size(size_ + src.size_); + arrcpy(thearray+s,src.thearray, src.size_); + } + Array subvec(int lower, int upper) { + assert(lower >= 0 && lower <=upper&& upper <= size_); + Array r; + int s =upper-lower; + r.set_size(s); + arrcpy(r.thearray, thearray + lower, s); + return r; + } +}; + +#endif diff --git a/flower/include/vector.hh b/flower/include/vector.hh new file mode 100644 index 0000000000..323d03db88 --- /dev/null +++ b/flower/include/vector.hh @@ -0,0 +1,111 @@ +#ifndef VECTOR_HH +#define VECTOR_HH + +#include +#include "real.hh" +#include "varray.hh" + +class Dstream; +class String; +void set_matrix_debug(Dstream&ds); + +/** a row of numbers. + a vector. Storage is handled in Array, Vector only does the mathematics. + */ +class Vector { + Array dat; +public: + void OK() const { dat.OK();} + int dim() const { return dat.size(); } + Vector() { } + Vector(Array d ); + Vector(Vector const &n); + Vector(int n) { + dat.set_size(n); + fill(0); + } + void insert(Real v, int i) { + dat.insert(v,i); + } + void del(int i) { dat.del(i); } + operator String() const; + void fill(Real r) { + for (int i=0; i < dim(); i++) + dat[i] =r; + } + + void operator +=(Vector v) { + assert(v.dim() == dim()); + for (int i=0; i < dim(); i++) + dat[i] += v.dat[i]; + } + + void operator /=(Real a) { + (*this) *= 1/a; + } + + void operator *=(Real a) { + for (int i=0; i < dim(); i++) + dat[i] *= a; + } + + void operator -=(Vector v) { + assert(v.dim() == dim()); + for (int i=0; i < dim(); i++) + dat[i] -= v(i); + } + + Real &operator()(int i) { return dat[i]; } + Real operator()(int i) const { return dat[i]; } + Real elem(int i) { return dat[i]; } + Real operator *(Vector v) const { + Real ip=0; + assert(v.dim() == dim()); + for (int i=0; i < dim(); i++) + ip += dat[i] *v(i); + return ip; + } + Vector operator-() const; + Real norm() { + return sqrt(norm_sq() ); + } + Real norm_sq() { + return ((*this) * (*this)); + } + operator Array () { return dat; } + void print() const; + /// set to j-th element of unit-base + void set_unit(int j) ; +}; + +inline Vector +operator+(Vector a, Vector const &b) { + a += b; + return a; +} + +inline Vector +operator-(Vector a, Vector const &b) { + a -= b; + return a; +} + +inline Vector +operator*(Vector v, Real a) { + v *= a; + return v; +} + +inline Vector +operator*( Real a,Vector v) { + v *= a; + return v; +} + +inline Vector +operator/(Vector v,Real a) { + v *= 1/a; + return v; +} + +#endif diff --git a/flower/include/vsmat.hh b/flower/include/vsmat.hh new file mode 100644 index 0000000000..b9dcdadecb --- /dev/null +++ b/flower/include/vsmat.hh @@ -0,0 +1,141 @@ +#ifndef VSMAT_HH +#define VSMAT_HH +#include "varray.hh" +#include "real.hh" +/** base class for interface with matrix storageclasses. There are no + iterators for matrixclasses, since matrices are (like arrays) + explicitly int-indexed. + + Iteration is provided by *_next, *_ok, which update and check both + index variables simultaneously. + + TODO + determine type of product matrix. + +*/ +class virtual_smat { + + +public: + /// check invariants + virtual void OK() const=0; + + /// height of matrix + virtual int rows() const = 0; + + /// width of matrix + virtual int cols() const = 0; + + + /** set the size. contents lost. + PRE + i >=0, j>=0 + */ + virtual void set_size(int i, int j) = 0; + + /**set the size to square dimen. contents lost + PRE + i>=0 + */ + virtual void set_size(int i) = 0; + /**set the size to i. + + keep contents. If enlarged contents unspecified + + PRE + i>=0, j>=0 + + */ + virtual void resize(int i, int j) = 0; + + /** + set the size to square dimen. contents kept + Keep contents. If enlarged contents are unspecified + + PRE + i>=0 + */ + virtual void resize(int i) = 0; + + + /** + access an element. + + Generate an errormessage, if this happens + in the 0-part of a sparse matrix. + */ + + virtual Real& elem(int i,int j) = 0; + + /// access a element, no modify + virtual Real const & elem(int i, int j) const = 0; + +#if 1 + virtual Array row(int i) const = 0; + virtual Array column(int j) const = 0; +#endif + + + /** + add a row to the matrix before row k. Contents + of added row are unspecified + + 0 <= k <= rows() + */ + virtual void insert_row(int k)=0; + + + /** + delete a row from this matrix. + + PRE + 0 <= k < rows(); + */ + virtual void delete_row(int k)=0; + virtual void delete_column(int k)=0; + virtual ~virtual_smat() { } + virtual virtual_smat *clone()=0; + + + + /** + at end of matrix?. when doing loop + + for(i=0; i + */ +#include +#include +#include +#include "lgetopt.hh" + +long +Getopt_long::intarg() +{ + long l; + if (sscanf(optarg, "%ld", &l) != 1) + report(E_ILLEGALARG); + + return l; +} + +Long_option_init * +Getopt_long::parselong() +{ + char const *optnm = argv[optind] + 2 ; + assert(*optnm); + + char *endopt = strchr(optnm, '='); + int searchlen = (endopt) ? endopt - optnm : strlen(optnm); + + beet=0; + for (int i=0; i< table_len; i++) { + char const *ln = the_opts[i].longname; + + if (ln && !strncmp(ln, optnm, searchlen)) { + beet = the_opts+i; + break; + } + } + + if (!beet) { + report(E_UNKNOWNOPTION); + return 0; + } + optind++; + optindind = 0; + + + if (beet->take_arg) { + if (endopt) + optarg = endopt +1; // a '=' + else { + optarg = argv[optind]; + optind++; + } + if (!optarg) + report(E_ARGEXPECT); + + } else { + optarg = 0; + if (endopt) + report(E_NOARGEXPECT); + } + + return beet; +} + + +ostream & +Long_option_init::printon(ostream &errorout) +{ + if (shortname) + errorout <<"-" << shortname; + if (shortname && longname) + errorout << ", "; + if (longname) + errorout << "`--" << longname << "'"; + return errorout; +} + +// report an error, GNU style. +void +Getopt_long::report(Errorcod c) +{ + error = c; + if (!errorout) + return; + + *errorout << argv[0] << ": "; + switch (c) { + case E_ARGEXPECT: + *errorout<< "option "; + beet->printon(*errorout); + *errorout << "requires an argument"<longname << "' does not allow an argument"<printon(*errorout); + *errorout << '\n'; + default: + assert(false); + } + exit(2); +} + +Long_option_init * +Getopt_long::parseshort() +{ + char c=argv[optind][optindind]; + beet=0; + assert(c); + + for (int i=0; i < table_len; i++) + if (the_opts[i].shortname == c) { + beet = the_opts+i; + break; + } + + if (!beet){ + report(E_UNKNOWNOPTION); + return 0; + } + + optindind++; + if (!beet->take_arg){ + optarg = 0; + return beet; + } + optarg = argv[optind] + optindind; + + optind ++; + optindind = 0; + + if (!optarg[0]) { + optarg = argv[optind]; + optind ++; + } + if (!optarg) { + report(E_ARGEXPECT); + } + + return beet; +} + +Long_option_init * +Getopt_long::operator()() { + if (!next()) + return 0; + + if (optindind) + return parseshort(); + + if (argv[optind][0] != '-') + return 0; + + if (argv[optind][1] == '-') {// what to do with "command -- bla" + return parselong(); + } else { + optindind = 1; + return parseshort(); + } +} + +Getopt_long::Getopt_long(int c, char **v, Long_option_init *lo) +{ + the_opts = lo; + errorout = &cerr; + argv = v; + argc = c; + optind = 1; + optindind = 0; + + // reached end of option table? + int i; + for (i = 0; the_opts[i].longname ||the_opts[i].shortname; i++) + ; + table_len = i; +} + +bool +Getopt_long::next() +{ + + error = E_NOERROR; + while (optind < argc && !argv[optind][optindind]) { + optind++; + optindind = 0; + } + return (optind < argc); +} + +char * +Getopt_long::current_arg() +{ + if (optind >= argc) + return 0; + char * a = argv[optind]; + return a + optindind; +} + +char * +Getopt_long::get_next_arg() +{ + char * a = current_arg(); + if ( a) { + optind ++; + optindind = 0; + } + return a; +} diff --git a/flower/libc-extension.cc b/flower/libc-extension.cc new file mode 100644 index 0000000000..6e9a9b77a6 --- /dev/null +++ b/flower/libc-extension.cc @@ -0,0 +1,112 @@ +/* + libc-extension.cc -- compensate for lacking libc functions. + + + source file of the flowerlib + + (c) 1997 Han-Wen Nienhuys +*/ +#include +#include +#include +#include "libc-extension.hh" + + +char* +strnlwr( char* start_l ,int n) +{ + char * p = start_l + n; + while ( --p >= start_l) { + *p = tolower( *p ); /* a macro on some compilers */ + } + return start_l; +} + +char* +strnupr( char* start_l, int n) +{ + char * p = start_l + n; + while ( --p >= start_l) { + *p = toupper( *p ); /* a macro on some compilers */ + } + return start_l; +} + +#if !HAVE_MEMMEM + +/** locate a substring. #memmem# finds the first occurrence of + #needle# in #haystack# + */ + +char * +memmem(Byte const * haystack, int haystack_len, + Byte const *needle,int needle_len) +{ + Byte const * end_haystack = haystack + haystack_len - needle_len; + Byte const * end_needle = needle + needle_len ; + + /* Ahhh ... Some minimal lowlevel stuff. This *is* nice; Varation + is the spice of life */ + while (haystack < end_haystack) { + Byte const *subneedle_l = needle; + Byte const *subhaystack_l = haystack; + while (subneedle_l < end_needle) { + if (*subneedle_l++ != *subhaystack_l++) + goto next; // yeah. I should be prosecuted. + } + + // completed the needle. Gotcha. + return (char*) haystack; + next: + haystack++; + } + return 0; +} +#endif + +Byte * +memrchr(Byte const * p, int n, char c) +{ + const Byte * q = p+n; + while (q > p) { + if (*--q == c) + return (Byte*)q; + } + return 0; +} + + +template +inline void +my_swap(T &t1, T &t2, T &tmp) +{ + tmp = t1; + t1 = t2; + t2 = tmp; +} + +Byte* +strrev( Byte* byte_l, int length_i ) +{ + Byte tmp_byte; + + Byte* left_l = byte_l; + Byte* right_l = byte_l + length_i; + + while ( right_l > left_l ) { + my_swap(*right_l-- , *left_l++ , tmp_byte); + } + return byte_l; +} + +#if ! HAVE_SNPRINTF +int snprintf ( char *str, size_t, + char const *format, ... ) +{ + va_list ap; + va_start(ap, format); + int i = vsprintf(str, format, ap); + va_end(ap); + return i; +} +#endif diff --git a/flower/matdebug.cc b/flower/matdebug.cc new file mode 100644 index 0000000000..bcc2843bca --- /dev/null +++ b/flower/matdebug.cc @@ -0,0 +1,63 @@ +#include "dstream.hh" +#include "matrix.hh" + +static Dstream *dout = 0; + +/** + Set the debugging output. Will not delete/swallow argument. + */ +void set_matrix_debug(Dstream&ds) +{ + dout = &ds; +} + +Matrix::operator String() const +{ + String s; +#ifndef NPRINT + s="matrix {\n"; + for (int i=0; i< rows(); i++){ + for (int j = 0; j < cols(); j++) { + s+= String(dat->elem(i,j), "%6f "); + } + s+="\n"; + } + s+="}\n"; +#endif + return s; +} + + +void +Matrix::print() const +{ +#ifndef NPRINT + if (!dout) + return; + *dout << *this; +#endif +} + +Vector::operator String() const +{ + String s; +#ifndef NPRINT + s="vector ["; + for (int i=0; i < dim(); i++) { + s += String(dat[i], "%6f") + String(' '); + } + s+="]"; +#endif + return s; +} + + +void +Vector::print() const +{ +#ifndef NDEBUG + if (!dout) + return; + *dout << *this<<'\n'; +#endif +} diff --git a/flower/matrix.cc b/flower/matrix.cc new file mode 100644 index 0000000000..9d229c0ae1 --- /dev/null +++ b/flower/matrix.cc @@ -0,0 +1,240 @@ +#include "matrix.hh" + +Real +Matrix::norm() const +{ + Real r =0.0; + for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j)) + r += sqr(dat->elem(i,j)); + return sqrt(r); +} + +void +Matrix::fill(Real r) +{ + for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j)) + dat->elem(i,j)=r; +} + +void +Matrix::set_diag(Real r) +{ + for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j)) + dat->elem(i,j)=(i==j) ? r: 0.0; +} + +void +Matrix::set_diag(Vector d) +{ + for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j)) + dat->elem(i,j)=(i==j) ? d(i): 0.0; +} + +void +Matrix::operator+=(Matrix const &m) +{ + assert(m.cols() == cols()); + assert(m.rows() == rows()); + for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j)) + dat->elem(i,j) += m(i,j); +} + +void +Matrix::operator-=(Matrix const &m) +{ + assert(m.cols() == cols()); + assert(m.rows() == rows()); + for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j)) + dat->elem(i,j) -= m(i,j); +} + + +void +Matrix::operator*=(Real a) +{ + for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j)) + dat->elem(i,j) *= a; +} + +void +Matrix::operator=(Matrix const &m) +{ + if (&m == this) + return ; + delete dat; + dat = m.dat->clone(); +} + +Matrix::Matrix(Matrix const &m) +{ + m.OK(); + + dat = m.dat->clone(); +} + + +Matrix::Matrix(int n, int m) +{ + dat = virtual_smat::get_full(n,m); + fill(0); +} + +Matrix::Matrix(int n) +{ + dat = virtual_smat::get_full(n,n); + fill(0); +} + +Matrix::Matrix(Vector v, Vector w) +{ + dat = virtual_smat::get_full(v.dim(), w.dim()); + for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j)) + dat->elem(i,j)=v(i)*w(j); +} + + +Vector +Matrix::row(int k) const +{ + int n=cols(); + + + Vector v(n); + for(int i=0; i < n; i++) + v(i)=dat->elem(k,i); + + return v; +} + +Vector +Matrix::col(int k) const +{ + int n=rows(); + Vector v(n); + for(int i=0; i < n; i++) + v(i)=dat->elem(i,k); + return v; +} + +Vector +Matrix::left_multiply(Vector const & v) const +{ + Vector dest(v.dim()); + assert(dat->cols()==v.dim()); + for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j)) + dest(i)+= dat->elem(j,i)*v(j); + return dest; +} + +Vector +Matrix::operator *(Vector const & v) const +{ + Vector dest(rows()); + assert(dat->cols()==v.dim()); + for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j)) + dest(i)+= dat->elem(i,j)*v(j); + return dest; +} + +Matrix +operator /(Matrix const& m1,Real a) +{ + Matrix m(m1); + m /= a; + return m; +} + +void +Matrix::transpose() // delegate to storage? +{ + for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j)) { + if (i >= j) + continue; + Real r=dat->elem(i,j); + dat->elem(i,j) = dat->elem(j,i); + dat->elem(j,i)=r; + } +} + +Matrix +Matrix::operator-() const +{ + OK(); + Matrix m(*this); + m*=-1.0; + return m; +} + +Matrix +Matrix::transposed() const +{ + Matrix m(*this); + m.transpose(); + return m; +} + + +/* should do something smarter: bandmatrix * bandmatrix is also banded matrix. */ +Matrix +operator *(Matrix const &m1, Matrix const &m2) +{ + Matrix result(m1.rows(), m2.cols()); + result.set_product(m1,m2); + return result; +} + +void +Matrix::set_product(Matrix const &m1, Matrix const &m2) +{ + assert(m1.cols()==m2.rows()); + assert(cols()==m2.cols() && rows()==m1.rows()); + + for (int i=0, j=0; dat->mult_ok(i,j); + dat->mult_next(i,j)) { + Real r=0.0; + for (int k = 0; k < m1.cols(); k++) + r += m1(i,k)*m2(k,j); + dat->elem(i,j)=r; + } +} + +void +Matrix::insert_row(Vector v, int k) +{ + assert(v.dim()==cols()); + dat->insert_row(k); + for (int j=0; j < cols(); j++) + dat->elem(k,j)=v(j); +} + + +void +Matrix::swap_columns(int c1, int c2) +{ + assert(c1>=0&& c1 < cols()&&c2 < cols() && c2 >=0); + for (int i=0; i< rows(); i++) { + Real r=dat->elem(i,c1); + dat->elem(i,c1) = dat->elem(i,c2); + dat->elem(i,c2)=r; + } +} + +void +Matrix::swap_rows(int c1, int c2) +{ + assert(c1>=0&& c1 < rows()&&c2 < rows() && c2 >=0); + for (int i=0; i< cols(); i++) { + Real r=dat->elem(c1,i); + dat->elem(c1,i) = dat->elem(c2,i); + dat->elem(c2,i)=r; + } +} + + +int +Matrix::dim() const +{ + assert(cols() == rows()); + return rows(); +} + diff --git a/flower/path.cc b/flower/path.cc new file mode 100644 index 0000000000..c79962f00f --- /dev/null +++ b/flower/path.cc @@ -0,0 +1,77 @@ +/* + path.cc - manipulation of paths and filenames. +*/ +#include +#include "path.hh" + +#ifndef PATHSEP +#define PATHSEP '/' +#endif + +/** + @param path the original full filename + @return 4 components of the path. They can be empty +*/ +void +split_path(String path, + String &drive, String &dirs, String &filebase, String &extension) +{ + // peel off components, one by one. + int di = path.index_i(':'); + if (di >= 0) + { + drive = path.left_str(di + 1); + path = path.right_str(path.len() - di -1); + } + else + drive = ""; + + di = path.index_last_i(PATHSEP); + if (di >=0) + { + dirs = path.left_str(di + 1); + path = path.right_str(path.len()-di -1); + } + else + dirs = ""; + + di = path.index_last_i('.'); + if (di >= 0) + { + filebase = path.left_str(di); + extension =path.right_str(path.len()-di); + } + else + { + extension = ""; + filebase = path; + } +} + +File_path::File_path(String pref) +{ + add("."); + add(pref); +} + + +/** find a file. + It will search in the current dir, in the construction-arg, and + in any other added path, in this order. + */ +String +File_path::find(String nm) +{ + for (int i=0; i < size(); i++) { + String path = (*this)[i]; + path+= "/"+nm; + + + FILE *f = fopen(path, "r"); // ugh! + if (f) { + fclose(f); + return path; + } + } + return ""; +} diff --git a/flower/scalar.cc b/flower/scalar.cc new file mode 100644 index 0000000000..5edd9e997f --- /dev/null +++ b/flower/scalar.cc @@ -0,0 +1,57 @@ +#include +#include +#include "scalar.hh" + +Scalar::Scalar(Rational r) + :String(r) +{ + +} + +Scalar::operator Rational() +{ + int p = index_i('/'); + if (p == -1) + return int(*this); + + String s2 = right_str(len()-p-1); + String s1 = left_str(p); + + return Rational(s1.value_i(), s2.value_i()); +} + +bool +Scalar::isnum() +{ + int conv = false; + if (len()) { + long l =0; + conv = sscanf(strh_.ch_c_l(), "%ld", &l); + } + return len() && conv; +} + +Scalar::operator Real() +{ + assert (isnum()); + return value_f(); +} + +Scalar::operator int() +{ + assert (isnum()); + return value_i(); +} + + +Scalar::operator bool() const +{ + if (!len()) + return false; + if (*this == "0") + return false; + String u (*this); + if ( u.upper_str() == "FALSE") + return false; + return true; +} diff --git a/flower/smat.cc b/flower/smat.cc new file mode 100644 index 0000000000..dcc61ce44e --- /dev/null +++ b/flower/smat.cc @@ -0,0 +1,181 @@ +#include "smat.hh" + +void +Full_storage::operator=(Full_storage const &fs) +{ + resize(fs.h, fs.w); + OK(); + fs.OK(); + for (int i=0; i= h && maxw >= w); + assert(h >= 0 && w >= 0); + assert(els||!maxh); +#endif +} +void +Full_storage::resize_cols(int newh) +{ + if (newh <= maxh) { + h=newh; + return; + } + + Real ** newa=new Real*[newh]; + int j=0; + for (; j < h; j++) + newa[j] = els[j]; + for (; j < newh; j++) + newa[j] = new Real[maxw]; + delete[] els; + els=newa; + + h = maxh = newh; +} + +void +Full_storage::resize_rows(int neww) +{ + if (neww <= maxw) { + w=neww; + return; + } + for (int i=0; i < maxh ; i++) { + Real* newa = new Real[neww]; + for (int k=0; k < w; k++) + newa[k] = els[i][k]; + + delete[] els[i]; + els[i] = newa; + } + w = maxw = neww; +} + +Full_storage::~Full_storage() { + for (int i=0; i < maxh; i++) + delete [] els[i]; + delete[] els; +} + +void +Full_storage::resize(int rows, int cols) +{ + OK(); + resize_cols(rows); + resize_rows(cols); + +} + + +bool +Full_storage::mult_ok(int i, int j) const +{ + return valid(i,j); +} + +bool +Full_storage::trans_ok(int i, int j) const +{ + return valid(i,j); +} + + +void +Full_storage::trans_next(int &i, int &j) const +{ + assert(trans_ok(i,j)); + i++; + if (i >= h) { + i=0; + j ++; + } +} + +void +Full_storage::mult_next(int &i, int &j) const +{ + assert(mult_ok(i,j)); + j++; + if (j >= w) { + j=0; + i++; + } +} + +void +Full_storage::delete_column(int k) +{ + assert(0 <= k &&k k ; i--) + for (int j=0; j +Full_storage::row(int n) const +{ + Array r; + for (int j = 0; j < w; j++) + r.push(els[n][j]); + return r; +} + +Array +Full_storage::column(int n) const +{ + + Array r; + for (int i = 0; i +#include +#include "libc-extension.hh" +#include "string.hh" +#include "string-convert.hh" + +/** + a safe length for stringconversion buffers + + worst case would be %f printing HUGE (or 1/HUGE), which is approx + 2e318, this number would have approx 318 zero's in its string. + + Should enlarge buff dynamically. + @see + man 3 snprintf + */ +static const int STRING_BUFFER_LEN=1024; + +String +String_convert::bin2hex_str( String bin_str ) +{ + String str; + Byte const* byte_c_l = bin_str.byte_c_l(); + for ( int i = 0; i < bin_str.length_i(); i++ ) { + str += (char)nibble2hex_byte( *byte_c_l >> 4 ); + str += (char)nibble2hex_byte( *byte_c_l++ ); + } + return str; +} + +int +String_convert::bin2_i( String bin_str ) +{ + assert( bin_str.length_i() <= 4 ); + + int result_i = 0; + for ( int i = 0; i < bin_str.length_i(); i++ ) { + result_i <<= 8; + result_i += (Byte)bin_str[ i ]; + } + return result_i; +} + +// breendet imp from String +int +String_convert::dec2_i( String dec_str ) +{ + if ( !dec_str.length_i() ) + return 0; + + long l = 0; + int conv = sscanf( dec_str.ch_c_l(), "%ld", &l ); + assert( conv ); + + return (int)l; +} + +String +String_convert::i64_str( I64 i64, char const* fmt) +{ + char buffer[STRING_BUFFER_LEN]; + snprintf(buffer, STRING_BUFFER_LEN, + (fmt ? fmt : "%Ld"), i64 ); // assume radix 10 + return String(buffer); + +} +// breendet imp from String +double +String_convert::dec2_f( String dec_str ) +{ + if ( !dec_str.length_i() ) + return 0; + double d = 0; + int conv = sscanf( dec_str.ch_c_l(), "%lf", &d ); + assert( conv ); + return d; +} + +int +String_convert::hex2bin_i( String hex_str, String& bin_str_r ) +{ + if ( hex_str.length_i() % 2 ) + hex_str = "0" + hex_str; + + bin_str_r = ""; + Byte const* byte_c_l= hex_str.byte_c_l(); + int i = 0; + while ( i < hex_str.length_i() ) { + int high_i = hex2nibble_i( *byte_c_l++ ); + int low_i = hex2nibble_i( *byte_c_l++ ); + if ( high_i < 0 || low_i < 0 ) + return 1; // illegal char + bin_str_r += String( (char)( high_i << 4 | low_i ), 1 ); + i += 2; + } + return 0; +} + +String +String_convert::hex2bin_str( String hex_str ) +{ + String str; +// silly, asserts should alway be "on"! +// assert( !hex2bin_i( hex_str, str ) ); + int error_i = hex2bin_i( hex_str, str ); + assert( !error_i ); + return str; +} + +int +String_convert::hex2nibble_i( Byte byte ) +{ + if ( byte >= '0' && byte <= '9' ) + return byte - '0'; + if ( byte >= 'A' && byte <= 'F' ) + return byte - 'A' + 10; + if ( byte >= 'a' && byte <= 'f') + return byte - 'a' + 10; + return -1; +} + +// stupido. Should use int_str() +String +String_convert::i2dec_str( int i, int length_i, char ch ) +{ + char fill_ch = ch; + if ( fill_ch) + fill_ch = '0'; + + // ugh + String dec_str( i ); + + // ugh + return String( fill_ch, length_i - dec_str.length_i() ) + dec_str; +} + + +// stupido. Should use int_str() +String +String_convert::u2hex_str( unsigned u, int length_i, char fill_ch ) +{ + String str; + if ( !u ) + str = "0"; + +#if 1 // both go... + while ( u ) { + str = String( (char)( ( u % 16 )["0123456789abcdef"] ) ) + str; + u /= 16; + } +#else + str += int_str( u, "%x" ); +#endif + + str = String( fill_ch, length_i - str.length_i() ) + str; + while ( ( str.length_i() > length_i ) && ( str[ 0 ] == 'f' ) ) + str = str.mid_str( 2, INT_MAX ); + + return str; +} + +String +String_convert::i2hex_str( int i, int length_i, char fill_ch ) +{ + return u2hex_str( (unsigned)i, length_i, fill_ch ); +} + +Byte +String_convert::nibble2hex_byte( Byte byte ) +{ + if ( ( byte & 0x0f ) <= 9 ) + return ( byte & 0x0f ) + '0'; + else + return ( byte & 0x0f ) - 10 + 'a'; +} +/** + Convert an integer to a string + + @param + #fmt# is a printf style format, default assumes "%d" as format. + */ +String +String_convert::int_str(int i, char const* fmt) +{ + char buffer[STRING_BUFFER_LEN]; + snprintf(buffer, STRING_BUFFER_LEN, + (fmt ? fmt : "%d"), i ); // assume radix 10 + return String(buffer); +} + +/** + Convert a double to a string. + + @param #fmt# is a printf style format, default assumes "%lf" as format + */ +String +String_convert::double_str(double f, char const* fmt) +{ + char buf[STRING_BUFFER_LEN]; + + snprintf(buf, STRING_BUFFER_LEN, fmt ? fmt : "%f", f); + return buf; +} + +/** + Make a string from a single character. + + @param + #n# is a repetition count, default value is 1 + */ +String +String_convert::char_str(char c, int n) +{ + n = n >= 0 ? n : 0; + char* ch_p = new char[ n ]; + memset( ch_p, c, n ); + String s((Byte*)ch_p, n); + delete ch_p; + return s; +} + +String +String_convert::rational_str(Rational r) +{ + char * n = Itoa(r.numerator()); // LEAK???? + + String s = n; + if (r.denominator() != 1) { + char * d = Itoa(r.denominator()); + s += String( '/' ) + String(d); + //delete d; + } +/* delete n; + */ + return s; +} + +String +String_convert::pointer_str(void const *l) +{ + I64 i64 = (I64)l; + return String_convert::i64_str(i64, "0x%0Lx"); +} diff --git a/flower/string.cc b/flower/string.cc new file mode 100644 index 0000000000..3eaa5c1b09 --- /dev/null +++ b/flower/string.cc @@ -0,0 +1,365 @@ +/* + + string.cc - implement String + + (c) 1997 Han-Wen Nienhuys & Jan Nieuwenhuizen + + */ + +#include +#include + +#include +#include + +#include "string.hh" +#include "libc-extension.hh" +#include "string-convert.hh" + +#ifdef STRING_DEBUG +void* mymemmove( void* dest, void const* src, size_t n ); +#define memmove mymemmove +#endif + +// return array, alloced with new. +Byte* +String::copy_byte_p() const +{ + Byte const* src = strh_.byte_c_l(); + Byte* dest = new Byte[strh_.length_i() + 1]; + memcpy( dest, src, strh_.length_i() + 1 ); + return dest; +} +void +String::print_on(ostream& os) const +{ + if (!strh_.is_binary_bo()) + os << ch_c_l(); + else + for ( int i = 0; i < length_i(); i++ ) + os << (Byte)(*this)[ i ]; +} + +/* + copying, constructing. + */ +String& +String::operator = (String const&source ) +{ + strh_ = source.strh_; + return *this; +} + + +String::String(Rational r) +{ + *this = String_convert::rational_str(r); +} + +String::String (double f, char const* fmt) +{ + *this= String_convert::double_str(f,fmt); +} + +String::String( char c, int n ) +{ + *this = String_convert::char_str (c,n); +} + +/** + @see + String_convert::int_str + */ +String::String(int i, char const * format ) +{ + *this = String_convert::int_str(i,format); +} + +String::String (bool b) +{ + *this = (char const* ) (b ? "true" : "false"); +} + +String::String( char const* source ) +{ + assert(source); + strh_ = source; +} + +String::String( Byte const* byte_l, int length_i ) +{ + strh_.set( byte_l, length_i ); +} + +void +String::append(String s) +{ + strh_.append( s.byte_c_l(), s.length_i() ); +} +void +String::operator +=(String s) +{ + append(s); +} + +void +String::prepend(String s) +{ + s += *this; + *this = s; +} + +int +String::length_i() const +{ + return strh_.length_i(); +} + +Byte const* +String::byte_c_l() const +{ + return strh_.byte_c_l(); +} + +char const* +String::ch_c_l() const +{ + return strh_.ch_c_l(); +} + +Byte* +String::byte_l() +{ + return strh_.byte_l(); +} + +char* +String::ch_l() +{ + return strh_.ch_l(); +} + +/** + Do a signed comparison, analogous to memcmp; + */ +int +String::compare_i(String const& s1, String const& s2 ) +{ + Byte const* p1 = s1.byte_c_l(); + Byte const* p2 = s2.byte_c_l(); + if ( p1 == p2 ) + return 0; + + int i1 = s1.length_i(); + int i2 = s2.length_i(); + + int result= memcmp( p1, p2, i1 = 0 ) { + index_i += next_i; + next_i = right_str( length_i() - index_i - length ).index_i( string ); + } + return index_i; +} + +/** find a character. + + @return + the index of the leftmost character #c# (0 <= return < length_i()), + or -1 if not found. + + ? should return length_i()?, as in string.left_str(index_i(delimiter)) +*/ +int +String::index_i(char c ) const +{ + char const* me = strh_.ch_c_l(); + char const* p = (char const *) memchr( me,c, length_i()); + if ( p ) + return p - me; + return -1; +} + +/** + find the substring. + + @return + index of leftmost occurrence of #searchfor# + */ +int +String::index_i( String searchfor ) const +{ + char const* me = strh_.ch_c_l(); + char const* p = (char const *) memmem( + me, length_i(), searchfor.ch_c_l(), searchfor.length_i()); + + if ( p ) + return p - me; + else + return -1; +} + +/** find chars of a set. + + @return + the index of the leftmost occurance of an element of #set# + */ +int +String::index_any_i( String set ) const +{ + int n = length_i(); + if ( !n ) + return -1; + + void const * me_l = (void const *) strh_.ch_c_l(); + for (int i=0; i < set.length_i(); i++) { + char * found=(char*) memchr(me_l, set[i], n ); + if (found) { + return found - me_l; + } + } + return -1; +} + +String +String::left_str( int n ) const +{ + if (n >= length_i()) + return *this; + + String retval; + if (n < 1) + return retval; + + retval = *this; + retval.strh_.trunc(n); + return retval; +} + +String +String::right_str( int n ) const +{ + if (n > length_i()) + return *this; + + if ( n < 1) + return ""; + + return String( strh_.byte_c_l() + length_i() - n, n ); +} + + +String +String::nomid_str( int index_i, int n ) const +{ + if ( index_i < 0 ) { + n += index_i; + index_i = 0; + } + if ( n <= 0) + return *this; + + return + left_str( index_i ) + + right_str( length_i() - index_i - n ) ; +} + +/* + proposal: change to "cut()" + */ +String +String::mid_str( int index_i, int n ) const +{ + if (index_i <0) { + n += index_i; + index_i=0; + } + + if ( !length_i() || ( index_i < 0 ) || ( index_i >= length_i() ) || ( n < 1 ) ) + return String(); + + if ( ( n > length_i() ) || ( index_i + n > length_i() ) ) + n = length_i() - index_i; + + return String( byte_c_l() + index_i, n ); +} + +String +String::upper_str() const +{ + String str = *this; + str.to_upper(); + return str; +} +void +String::to_upper() +{ + char *s = (char*)strh_.byte_l(); + strnupr( s ,length_i()); +} + +void +String::to_lower() +{ + char* s = strh_.ch_l(); + strnlwr(s,length_i()); +} + + +String +String::lower_str() const +{ + String str = *this; + str.to_lower(); + return str; +} +String +String::reversed_str() const +{ + String str = *this; + strrev( str.byte_l(), str.length_i() ); + return str; +} + +int +String::value_i() const +{ + return String_convert::dec2_i( *this ); +} + +double +String::value_f() const +{ + return String_convert::dec2_f( *this ); +} + + diff --git a/flower/stringtest.cc b/flower/stringtest.cc new file mode 100644 index 0000000000..0bbde77c99 --- /dev/null +++ b/flower/stringtest.cc @@ -0,0 +1,118 @@ +#ifdef STRING_TEST +/* + stupid test program to verify stringlib + stringtest.cc + */ +#include +#include "string.hh" +#include "varray.hh" +#include "string-convert.hh" + +void +ctors() +{ + cout << "constructors"< a; + a.push("abcd"); + a.push("zxy"); + a.push("abc"); + a.push(""); + a.sort(String::compare_i); + cout << "compares: "< +*/ + +#ifdef STRING_DEBUG +#include +#include +void* +mymemmove( void* dest, void const* src, size_t n ) +{ + return memcpy( dest, src, n ); // wohltempererit: 69006 +} +#define memmove mymemmove +#endif + +#ifdef STRING_UTILS_INLINED +#undef STRING_UTILS_INLINED +#endif + +#ifdef INLINE +#undef INLINE +#endif + +#define INLINE + +#include "string-handle.hh" +#include "string-data.hh" +#include "string-data.inl" +#include "string-handle.inl" diff --git a/flower/text-db.cc b/flower/text-db.cc new file mode 100644 index 0000000000..ebfc992ff2 --- /dev/null +++ b/flower/text-db.cc @@ -0,0 +1,48 @@ +#include "text-db.hh" +bool +Text_db::eof() +{ + Data_file::gobble_leading_white(); + return Data_file::eof(); +} + +void +Text_db::gobble_leading_white() +{ + while (1) { + Data_file::gobble_leading_white(); + if (eof()) + return ; + char c; + if ((c = data_get()) !='\n'){ + data_unget (c); + return ; + } + } +} + + +Text_record +Text_db::get_record() +{ + while (1) { + String s; + Array fields; + assert(!eof()); + + while ((s = get_word()) != "") + { + fields.push(s); + gobble_white(); + } + + + if (get_line() != "") + assert(false); + + assert (fields.size()); + return Text_record(fields, get_name(), line()); + } +} + + diff --git a/flower/text-stream.cc b/flower/text-stream.cc new file mode 100644 index 0000000000..a2d3e4b119 --- /dev/null +++ b/flower/text-stream.cc @@ -0,0 +1,31 @@ +#include "text-stream.hh" + +Text_stream::Text_stream(String fn) +{ + ios::sync_with_stdio(); + if (fn == "") + { + name = ""; + f = stdin; + } + + else + { + name = fn; + f = fopen(fn, "r"); + } + + if (!f) { + cerr <<__FUNCTION__<< ": can't open `" << fn << "'\n"; + exit(1); + } + + line_no = 1; + } + +void +Text_stream::message(String s) +{ + cerr << "\n"< d) + : dat(d) +{ + +} +Vector::Vector(Vector const &n) + : dat(n.dat) +{ +} + +Vector +Vector::operator-() const +{ + Vector v(*this); + v*=-1; + return v; +} + +void +Vector::set_unit(int j) +{ + fill(0.0); + dat[j] = 1.0; +}