--- /dev/null
+#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<n; j++)
+ invm(i,j) = inv(j);
+ }
+
+#ifdef NDEBUG
+ Matrix I1(n), I2(original());
+ I1.unit();
+ assert((I1-original()*invm).norm()/original.norm() < EPS);
+#endif
+
+ return invm;
+}
--- /dev/null
+#include <fstream.h>
+#include <ctype.h>
+
+#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;
+ }
+ }
+}
+
+
--- /dev/null
+
+
+#include <fstream.h>
+#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<String,bool>;
+ 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) ;
+}
--- /dev/null
+#include "version.hh" // urg
+#include <stdio.h>
+
+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;
+}
--- /dev/null
+/*
+ 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<class K, class V>
+struct Assoc_iter {
+ int i;
+ Assoc<K,V> &assoc_;
+ /// we don't want to be bothered by const correctness
+ Assoc_iter(const Assoc<K,V> &a) :
+ assoc_((Assoc<K,V> &)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
--- /dev/null
+#ifndef ASSOC_HH
+#define ASSOC_HH
+
+#include "varray.hh"
+#include <assert.h>
+
+/**
+ A helper for Assoc
+ */
+template<class K, class V>
+struct Assoc_ent_ {
+ bool free;
+ K key;
+ V val;
+};
+
+
+/** mindblowingly stupid Associative array implementation.
+ Hungarian: map
+ */
+template<class K, class V>
+struct Assoc {
+ Array< Assoc_ent_<K,V> > 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_<K,V> 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
--- /dev/null
+#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
--- /dev/null
+/*
+ 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, <?, <)\
+ 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
+
--- /dev/null
+// cursor.hh
+
+#ifndef __CURSOR_HH
+#define __CURSOR_HH
+
+#include "link.hh"
+template<class T> class List;
+
+/** iterator to List.
+ add and insert extend the list
+ items are always stored as copies in List, but:
+ List<String> : copies of String stored
+ List<String*> : copies of String* stored!
+
+ the operations add and insert actually delegate the work to List class.
+ */
+template<class T>
+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<T>& list, Link<T>* pointer = 0 );
+
+ Cursor( const Cursor<T>& cursor );
+
+ T& thing();
+
+ /// return current T
+ T& operator *() { return thing(); }
+ operator T() { return thing(); }
+ Cursor<T> operator =( const Cursor<T>& c );
+
+ /// make cursor with #no# items back
+ Cursor<T> operator -( int no) const;
+
+ /// make cursor with #no# items further
+ Cursor<T> operator +( int no) const;
+ int operator -(Cursor<T> op) const;
+ Cursor<T> operator -=(int);
+ Cursor<T> operator +=(int);
+
+ /// return current and move one down
+ Cursor<T> operator ++( int );
+
+ /// return current and move one up
+ Cursor<T> 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<T>& list() const ;
+ Link<T>* pointer();
+ static int compare(Cursor<T> a,Cursor<T>b) { return a-b; }
+private:
+ List<T>& list_;
+ Link<T>* pointer_;
+};
+
+
+/*
+ comparisons.
+ */
+#include "compare.hh"
+
+
+template_instantiate_compare(Cursor<T>, Cursor<T>::compare, template<class T>);
+
+#include "pcursor.hh"
+#include "list.hh"
+#include "cursor.inl"
+#include "iterate.hh"
+
+#endif // CURSOR_HH
--- /dev/null
+#ifndef CURSOR_CC
+#define CURSOR_CC
+
+#include "cursor.hh"
+#include <assert.h>
+
+template<class T>
+ void
+Cursor<T>::backspace()
+{
+ Cursor<T> c(*this);
+ if ( c.ok() )
+ c--;
+ list_.remove( *this );
+}
+
+template<class T>
+ void
+Cursor<T>::del()
+{
+ Cursor<T> c(*this);
+ if ( c.ok() )
+ c++;
+ list_.remove( *this );
+ *this = c;
+}
+
+
+template<class T>
+Cursor<T>
+Cursor<T>::operator -=( int j )
+{
+ while (j--)
+ (*this)--;
+ return *this;
+}
+template<class T>
+Cursor<T>
+Cursor<T>::operator +=( int j )
+{
+ while (j++)
+ (*this)++;
+ return *this;
+}
+
+template<class T>
+Cursor<T>
+Cursor<T>::operator +( int i ) const
+{
+ Cursor<T> r = *this;
+
+ if (i<0)
+ return r -(-i);
+
+ while (i--)
+ r++;
+
+ return r;
+}
+
+template<class T>
+Cursor<T>
+Cursor<T>::operator -( int i ) const
+{
+ Cursor<T> 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<class T>
+int
+Cursor<T>::operator-(Cursor<T> rhs) const
+{
+ assert(rhs.list == list);
+ int dif = 0;
+
+ // search from *this on further up (positive difference)
+ Cursor<T> 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
--- /dev/null
+/*
+ data-file.hh -- declare Data_file
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#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 << ")"<<flush;
+ }
+
+ warning(String s) {
+ message("warning: " + s);
+ }
+ error(String s){
+ message(s);
+ exit(1);
+ }
+};
+#endif // DATAFILE_HH
--- /dev/null
+
+#ifndef DSTREAM_HH
+#define DSTREAM_HH
+
+#include "string.hh"
+
+const char eol= '\n';
+
+template<class K,class V>
+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<String, bool> *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
+
--- /dev/null
+/*
+ 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<class T> struct Array;
+template<class T> struct sstack;
+template<class T,class K> struct Assoc;
+template<class T> struct List;
+template<class T> struct PointerList;
+template<class T> struct IPointerList;
+template<class T> struct Cursor;
+template<class T> struct PCursor;
+template<class T> struct Link;
+template<class T> struct Handle;
+template<class T> struct Interval_t;
+template<class T,class Q> struct PQueue;
+
+#include "real.hh"
+
+typedef Interval_t<Real> 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
+
--- /dev/null
+#ifndef HANDLE_HH
+#define HANDLE_HH
+
+/// reference counting handle
+template<class T>
+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
--- /dev/null
+/*
+ interval.hh -- part of flowerlib
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef INTERVAL_HH
+#define INTERVAL_HH
+
+#include <assert.h>
+#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<class T>
+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<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<T> h);
+ void intersect(Interval_t<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<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<class T>
+int Interval__compare(const Interval_t<T>&,Interval_t<T> const&);
+
+/*
+ INLINE
+ */
+
+#include "compare.hh"
+
+template_instantiate_compare(Interval_t<T>&, Interval__compare, template<class T>);
+
+
+template<class T>
+inline Interval_t<T>
+intersection(Interval_t<T> a, Interval_t<T> const&b)
+{
+ a.intersect(b);
+ return a;
+
+}
+
+
+template<class T>
+inline
+Interval_t<T> operator +(T a,Interval_t<T> i )
+{
+ i += a;
+ return i;
+}
+
+template<class T>
+inline
+Interval_t<T> operator +(Interval_t<T> i,T a ){
+ return a+i;
+}
+
+typedef Interval_t<Real> Interval;
+
+
+#define Interval__instantiate(T) template struct Interval_t<T>;\
+ template int Interval__compare(const Interval_t<T>&,Interval_t<T> const&)
+
+
+#endif // INTERVAL_HH
+
+
+
--- /dev/null
+#include <assert.h>
+#include <math.h>
+#include "interval.hh"
+#include "string.hh"
+
+
+template<class T>
+int
+_Interval__compare(const Interval_t<T>&a,Interval_t<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<class T>
+int
+Interval__compare(const Interval_t<T>&a,Interval_t<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<class T>
+void
+Interval_t<T>::set_empty()
+{
+ left = INFTY;
+ right = -INFTY;
+}
+
+template<class T>
+T
+Interval_t<T>::length() const {
+ assert(right >= left);
+ return right-left;
+}
+
+template<class T>
+void
+Interval_t<T>::unite(Interval_t<T> h)
+{
+ if (h.left<left)
+ left = h.left;
+ if (h.right>right)
+ right = h.right;
+}
+
+/**
+ smallest Interval which includes *this and #h#
+ */
+
+template<class T>
+void
+Interval_t<T>::intersect(Interval_t<T> h)
+{
+#if defined (__GNUG__) && ! defined (__STRICT_ANSI__)
+ left = h.left >? left;
+ right = h.right <?right;
+#else
+ left = max(h.left, left);
+ right = min(h.right, right);
+#endif
+}
+
+template<class T>
+Interval_t<T>
+intersect(Interval_t<T> x, Interval_t<T> const &y)
+{
+ x.intersect(y);
+ return x;
+}
+
+template<class T>
+String
+Interval_t<T>::str() const
+{
+ if (empty())
+ return "[empty]";
+ String s("[");
+
+ return s + left + "," + right +"]";
+}
+
+template<class T>
+bool
+Interval_t<T>::elt_q(T r)
+{
+ return r >= left && r <= right;
+}
--- /dev/null
+/*
+ iterate.hh -- define some list macros
+
+ source file of the flowerlib
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#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
--- /dev/null
+#ifndef LGETOPT_HH
+#define LGETOPT_HH
+
+#include <string.h>
+
+
+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
--- /dev/null
+/*
+ libc-extension.hh -- declare some string.h extensions
+
+ source file of the flowerlib
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#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
--- /dev/null
+// link.hh
+
+#ifndef __LINK_HH
+#define __LINK_HH
+template<class T>
+class List;
+
+
+/// class for List
+template<class T>
+class Link
+{
+// friend class Cursor<T>;
+public:
+ Link( T const & thing );
+
+ Link<T>* previous();
+ Link<T>* 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<T> &l);
+
+ T& thing();
+ void OK() const;
+private:
+ Link( Link<T>* previous, Link<T>* next, T const & thing );
+
+ T thing_;
+ Link<T>* previous_;
+ Link<T>* next_;
+};
+
+#include "link.inl"
+
+#endif // __LINK_HH //
--- /dev/null
+#ifndef __LIST_HH
+#define __LIST_HH
+
+class ostream;
+template<class T> class Cursor;
+template<class T> 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<String># : copies of #String# stored
+ #List<String*># : copies of #String*# stored!
+ (do not use, use \Ref{PointerList} #<String*># 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 T>
+class List
+{
+ public:
+ List(List const&src);
+
+ /// construct empty list
+ List();
+ virtual ~List();
+
+ int size() const;
+
+ Cursor<T> bottom() const; // const sucks.
+ Cursor<T> top() const;
+
+ void OK() const; // check list
+
+ protected:
+ friend class Cursor<T>;
+ friend class Link<T>;
+
+ void concatenate(List<T> const &s);
+
+ /** make *this empty.
+
+ POST:
+ size == 0
+
+ WARNING:
+ contents lost, and not deleted.
+ */
+ void set_empty();
+
+ void add( T const & thing, Cursor<T> &after_me );
+
+ /// put thing before #before_me#
+ void insert( T const & thing, Cursor<T> &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<T> me );
+
+
+ /* ************** */
+
+ int size_;
+ Link<T>* top_;
+ Link<T>* bottom_;
+};
+
+#include "list.inl"
+#include "cursor.hh"
+
+// instantiate a template: explicit instantiation.
+#define L_instantiate(a) template class List<a>; template class Cursor<a>; \
+ template class Link<a>
+
+
+#endif // __LIST_HH //
+
+
+
+
--- /dev/null
+#ifndef LIST_CC
+#define LIST_CC
+
+#include "list.hh"
+
+template<class T>
+List<T>::List(List const&src)
+{
+ set_empty();
+ // probably el stupido
+ for (Cursor<T> c(src); c.ok(); c++)
+ bottom().add(c);
+}
+
+template<class T>
+void
+List<T>::OK() const
+{
+ int i = size_;
+ Link<T> *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<class T>
+List<T>::~List()
+{
+ Cursor<T> 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<class T>
+void
+List<T>::add( T const & thing, Cursor<T> &after_me )
+{
+ if (!size_) { // not much choice if list is empty
+ bottom_ = top_ = new Link<T>( thing );
+ if (!after_me.ok())
+ after_me = bottom();
+ } else { // add at aprioprate place
+ if (!after_me.ok())
+ after_me = bottom();
+ Link<T> *p =after_me.pointer();
+ p->add(thing);
+ if (p == bottom_) // adjust bottom_ if necessary.
+ bottom_ = p->next();
+ }
+
+ size_++;
+}
+
+template<class T>
+void
+List<T>::insert( T const & thing, Cursor<T> &before_me )
+{
+ if (!size_) {
+ bottom_ = top_ = new Link<T>( thing );
+ if (!before_me.ok())
+ before_me = top();
+
+ } else {
+ if (!before_me.ok())
+ before_me = top();
+
+ Link<T> *p = before_me.pointer() ;
+
+ p->insert(thing);
+ if (p == top_)
+ top_ = p->previous();
+ }
+
+ size_++;
+}
+
+
+template<class T>
+void
+List<T>::concatenate(List<T> const&s)
+{
+ Cursor<T> b(bottom());
+ for (Cursor<T> c(s); c.ok(); c++) {
+ b.add(c);
+ b++;
+ }
+}
+#endif
--- /dev/null
+#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
--- /dev/null
+#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<String>
+{
+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<String>::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
--- /dev/null
+/*
+ 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<void*>'s.
+ This cursor is just an interface class for Cursor. It takes care of the
+ appropriate type casts
+ */
+template<class T>
+class PCursor : private Cursor<void *> {
+ friend class IPointerList<T>;
+
+ /// delete contents
+ void junk();
+public:
+ Cursor<void*>::ok;
+ Cursor<void*>::del;
+ Cursor<void*>::backspace;
+ T remove_p() {
+ T p = ptr();
+ Cursor<void*>::del();
+ return p;
+ }
+ T remove_prev_p() {
+ assert( ok() );
+ (*this)--;
+ return remove_p();
+ }
+
+ PointerList<T> &list() { return (PointerList<T>&)Cursor<void*>::list(); }
+ PCursor<T> operator++(int) { return Cursor<void*>::operator++(0);}
+ PCursor<T> operator--(int) { return Cursor<void*>::operator--(0); }
+ PCursor<T> operator+=(int i) { return Cursor<void*>::operator+=(i);}
+ PCursor<T> operator-=(int i) { return Cursor<void*>::operator-=(i); }
+ PCursor<T> operator -(int no) const { return Cursor<void*>::operator-(no);}
+ int operator -(PCursor<T> op) const { return Cursor<void*>::operator-(op);}
+ PCursor<T> operator +( int no) const {return Cursor<void*>::operator+(no);} PCursor(const PointerList<T> & l) : Cursor<void*> (l) {}
+
+ PCursor( const Cursor<void*>& cursor ) : Cursor<void*>(cursor) { }
+ void* vptr() const { return *((Cursor<void*> &) *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<void*>::add((void*) p); }
+ void insert(T const & p ) { Cursor<void*>::insert((void*) p);}
+ static int compare(PCursor<T> a,PCursor<T>b) {
+ return Cursor<void*>::compare(a,b);
+ }
+};
+
+
+
+#include "compare.hh"
+template_instantiate_compare(PCursor<T>, PCursor<T>::compare, template<class T>);
+
+#endif
--- /dev/null
+#include "pcursor.hh"
+
+template<class T>
+void
+PCursor<T>::junk()
+{
+#if !defined(NDEBUG) && defined(PARANOID)
+ list().OK();
+#endif
+
+ delete ptr();
+#if !defined(NDEBUG)&&defined(PARANOID)
+ thing() = 0;
+ list().OK();
+#endif
+}
--- /dev/null
+/*
+ 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<AbstractType*>.
+ This class does no deletion of the pointers, but it knows how to
+ copy itself (shallow copy). We could have derived it from List<T>,
+ but this design saves a lot of code dup; for all PointerLists in the
+ program only one parent List<void*> is instantiated.
+ */
+template<class T>
+class PointerList : public List<void *>
+{
+ public:
+ PCursor<T> top() const{
+ return PCursor<T> (List<void*>::top());
+ }
+ PCursor<T> bottom() const {
+ return PCursor<T> (List<void*>::bottom());
+ }
+ PCursor<T> find(T) const;
+ void concatenate(PointerList<T> const &s) { List<void*>::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 T>
+class IPointerList : public PointerList<T> {
+public:
+ IPointerList(IPointerList const &) { set_empty(); }
+ IPointerList() { }
+ ~IPointerList();
+};
+
+#define IPointerList__copy(T, to, from, op) \
+ for (PCursor<T> _pc_(from); _pc_.ok(); _pc_++)\
+ to.bottom().add(_pc_->op)\
+ \
+
+
+template<class T>
+void PL_copy(IPointerList<T*> &dst,IPointerList<T*> const&src);
+
+
+#define PL_instantiate(a) template class PointerList<a*>; \
+ template class PCursor<a*>;
+#define IPL_instantiate(a) PL_instantiate(a); \
+ template class IPointerList<a*>
+
+#include "plist.inl"
+
+#endif
--- /dev/null
+#include "plist.hh"
+
+template<class T>
+IPointerList<T>::~IPointerList()
+{
+ PCursor<T> c( *this );
+ while (c.ok()) {
+ delete c.remove_p();
+ }
+}
+
+template<class T>
+PCursor<T>
+PointerList<T>::find(T what ) const
+{
+ PCursor<T> i(*this);
+ for (; i.ok(); i++)
+ if (i.ptr() == what)
+ break;
+ return i;
+}
--- /dev/null
+/*
+ pqueue.hh -- declare
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#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<V,I>
+ */
+
+template<class V, class I>
+struct PQueue
+{
+ Array<V> value_arr_;
+ Array<I> 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
--- /dev/null
+#include <Rational.h>
--- /dev/null
+#ifndef REAL_HH
+#define REAL_HH
+
+
+#include <builtin.h>
+#include <minmax.h>
+#include <math.h>
+
+typedef double Real;
+
+inline Real
+distance(Real x,Real y)
+{
+ return abs(x-y);
+}
+#endif
--- /dev/null
+/*
+ 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
+
--- /dev/null
+#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<Real> row(int i) const;
+ virtual Array<Real> 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
--- /dev/null
+/*
+ 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 //
--- /dev/null
+/*
+ string-data.hh -- declare String_data
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#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
--- /dev/null
+/*
+ string-handle.hh -- declare String_handle
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#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
--- /dev/null
+/*
+
+ 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 <string.h>
+#include <iostream.h>
+#include <Rational.h>
+
+#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
--- /dev/null
+#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<String>
+{
+ 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<String>::operator[](j);
+ }
+
+ Text_record(Array<String> s, String fn, int j) : Array<String>(s) {
+ filename = fn; line_no = j;
+ }
+ Array<String>::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
--- /dev/null
+
+#ifndef TEXTSTR_HH
+#define TEXTSTR_HH
+
+#include <stdio.h>
+#include <ctype.h>
+#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<char> 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
--- /dev/null
+#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<int> classes;
+
+};
+#endif
--- /dev/null
+/*
+ (c) Han-Wen Nienhuys 1995,96
+
+ Distributed under GNU GPL
+*/
+
+#ifndef ARRAY_H
+#define ARRAY_H
+#include <assert.h>
+
+/// copy a bare (C-)array from #src# to #dest# sized #count#
+template<class T>
+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 T>
+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<size_);
+ return ((T*)thearray)[i];
+ }
+
+ /// add to the end of array
+ void push(T x) {
+ if (size_ == max)
+ remax(2*max + 1);
+
+ // T::operator=(T &) is called here. Safe to use with automatic
+ // vars
+ thearray[size_++] = x;
+ }
+ /// remove and return last entry
+ T pop() {
+ assert(!empty());
+ T l = top(0);
+ set_size(size()-1);
+ return l;
+ }
+ /// access last entry
+ T& top(int j=0) {
+ return (*this)[size_-j-1];
+ }
+ /// return last entry
+ T top (int j=0) const {
+ return (*this)[size_-j-1];
+ }
+
+
+ void swap (int i,int j) {
+ T t((*this)[i]);
+ (*this)[i]=(*this)[j];
+ (*this)[j]=t;
+ }
+ bool empty() { return !size_; }
+ void insert(T k, int j) {
+ assert(j >=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<T> const &src) {
+ int s = size_;
+ set_size(size_ + src.size_);
+ arrcpy(thearray+s,src.thearray, src.size_);
+ }
+ Array<T> subvec(int lower, int upper) {
+ assert(lower >= 0 && lower <=upper&& upper <= size_);
+ Array<T> r;
+ int s =upper-lower;
+ r.set_size(s);
+ arrcpy(r.thearray, thearray + lower, s);
+ return r;
+ }
+};
+
+#endif
--- /dev/null
+#ifndef VECTOR_HH
+#define VECTOR_HH
+
+#include <math.h>
+#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<Real> dat;
+public:
+ void OK() const { dat.OK();}
+ int dim() const { return dat.size(); }
+ Vector() { }
+ Vector(Array<Real> 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<Real> () { 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
--- /dev/null
+#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<Real> row(int i) const = 0;
+ virtual Array<Real> 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<h; i++)
+ for(j=0; j<w; j++)
+ ..
+
+ */
+ virtual bool mult_ok(int i, int j) const=0;
+
+ /**
+ walk through matrix (regular multiply).
+ get next j for row i, or get next row i and reset j.
+ this will make sparse matrix implementation easy.
+
+ PRE
+ mult_ok(i,j)
+ */
+ virtual void mult_next(int &i, int &j) const = 0;
+
+/**
+ valid matrix entry. return false if at end of row
+ */
+ virtual bool trans_ok(int i, int j) const=0;
+
+ /**
+ walk through matrix (transposed multiply).
+ Get next i (for column j)
+
+ PRE
+ ver_ok(i,j)
+ */
+
+ virtual void trans_next(int &i, int &j) const = 0;
+ /// generate a "Full_storage" matrix
+ static virtual_smat *get_full(int n, int m);
+
+};
+
+
+#endif
--- /dev/null
+/*
+ process command line, GNU style.
+
+ this is (Copyleft) 1996, Han-Wen Nienhuys, <hanwen@stack.nl>
+ */
+#include <stdio.h>
+#include <iostream.h>
+#include <assert.h>
+#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"<<endl;
+ break;
+ case E_NOARGEXPECT:
+ *errorout << "option `--" <<
+ beet->longname << "' does not allow an argument"<<endl;
+ break;
+
+ case E_UNKNOWNOPTION:
+ *errorout << "unrecognized option ";
+ if (optindind)
+ *errorout << "-" << argv[optind][optindind] << endl;
+ else
+ *errorout << argv[optind] << endl;
+
+ break;
+ case E_ILLEGALARG:
+ *errorout << "illegal argument `" << optarg << "\'to option ";
+ beet->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;
+}
--- /dev/null
+/*
+ libc-extension.cc -- compensate for lacking libc functions.
+
+
+ source file of the flowerlib
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#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<class T>
+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
--- /dev/null
+#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
+}
--- /dev/null
+#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();
+}
+
--- /dev/null
+/*
+ path.cc - manipulation of paths and filenames.
+*/
+#include <stdio.h>
+#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 "";
+}
--- /dev/null
+#include <assert.h>
+#include <stdio.h>
+#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;
+}
--- /dev/null
+#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; i++)
+ for (int j=0; j<w; j++)
+ els[i][j]= fs.els[i][j];
+}
+
+void
+Full_storage::OK() const
+{
+#ifndef NDEBUG
+ // static Real dummy;
+ assert(maxh >= 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<w);
+ for (int i=0; i< h ; i++)
+ for (int j=k+1; j <w; j++)
+ els[i][j-1]=els[i][j];
+ w--;
+}
+void
+Full_storage::delete_row(int k)
+{
+ assert(0 <= k &&k<h);
+ for (int i=k+1; i < h ; i++)
+ for (int j=0; j < w; j++)
+ els[i-1][j]=els[i][j];
+ h--;
+}
+
+
+void
+Full_storage::insert_row(int k)
+{
+ assert(0 <= k&& k <=h);
+ resize_cols(h+1);
+ for (int i=h-1; i > k ; i--)
+ for (int j=0; j <w; j++)
+ els[i][j]=els[i-1][j];
+
+}
+
+
+Array<Real>
+Full_storage::row(int n) const
+{
+ Array<Real> r;
+ for (int j = 0; j < w; j++)
+ r.push(els[n][j]);
+ return r;
+}
+
+Array<Real>
+Full_storage::column(int n) const
+{
+
+ Array<Real> r;
+ for (int i = 0; i<h; i++)
+ r.push(els[i][n]);
+ return r;
+}
+
+
+Full_storage::Full_storage(Full_storage&s)
+{
+ init();
+ (*this) = s;
+}
+virtual_smat*
+Full_storage::clone()
+{
+ return new Full_storage(*this);
+}
+
+
+virtual_smat *
+virtual_smat::get_full(int n, int m)
+{
+ return new Full_storage(n,m);
+}
--- /dev/null
+/*
+ PROJECT: FlowerSoft C++ library
+ FILE : string-convert.cc
+
+--*/
+
+
+#include <assert.h>
+#include <limits.h>
+#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");
+}
--- /dev/null
+/*
+
+ string.cc - implement String
+
+ (c) 1997 Han-Wen Nienhuys & Jan Nieuwenhuizen
+
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <assert.h>
+#include <string.h>
+
+#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 ];
+}
+\f
+/*
+ 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 );
+}
+\f
+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 <? i2 );
+ return result ? result : i1-i2;
+}
+
+\f
+int
+String::index_last_i( char const c ) const
+{
+ if ( !length_i() )
+ return -1;
+
+ char const* me = strh_.ch_c_l();
+ char const* p = memrchr(me, length_i(), c );
+ if ( p )
+ return p - me;
+ return -1;
+}
+
+int
+String::index_last_i( char const* string ) const // UGK!
+{
+ assert(false); // broken
+ int length = strlen( string ); // ugrh
+ if ( !length_i() || !length )
+ return -1;
+
+ int next_i = index_i( string );
+ if ( next_i == -1 )
+ return -1;
+
+ int index_i = 0;
+ while( next_i >= 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;
+}
+\f
+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 );
+}
+\f
+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 );
+}
+
+
--- /dev/null
+#ifdef STRING_TEST
+/*
+ stupid test program to verify stringlib
+ stringtest.cc
+ */
+#include <iostream.h>
+#include "string.hh"
+#include "varray.hh"
+#include "string-convert.hh"
+
+void
+ctors()
+{
+ cout << "constructors"<<endl;
+
+ String str( "hai" );
+ String def;
+ String fromi(10);
+ String fromc('c');
+ String fromf(1.32e-2, "%g");
+
+ cout << str << endl;
+ cout << def << endl;
+ cout << fromi<< endl;
+ cout << fromc<< endl;
+ cout << fromf<< endl;
+}
+
+void
+cmp()
+{
+ Array<String> a;
+ a.push("abcd");
+ a.push("zxy");
+ a.push("abc");
+ a.push("");
+ a.sort(String::compare_i);
+ cout << "compares: "<<endl;
+ for (int i=0; i < a.size(); i++)
+ cout << a[i] << endl;
+}
+
+
+void
+searching()
+{
+ String hay = "foobarbazblub";
+
+ char c = 'b';
+ String cstr =c;
+ String set = "bar";
+ cout << "hay = \"" << hay << "\" len="<< hay.length_i()<<endl;
+ cout << "index_i('"<< c<<"') " << c << "= " << hay.index_i(c) <<endl;
+ cout << "last_index_i('"<< c<<"') " << c << "= " << hay.index_last_i(c) <<endl;
+// cout << "last index of cstr " << c << ": " << hay.index_last_i(cstr) <<endl;
+// cout << "index_last_i(\""<<set<<"\"): " << hay.index_last_i(set) <<endl;
+ cout << "index_i(\""<<set<<"\"): " << hay.index_i(set) <<endl;
+ cout << "index_any(\"" << set << "\"): " << cstr << ": " << hay.index_any_i(cstr) <<endl;
+
+
+
+}
+
+
+void
+kutenpeer()
+{
+ String str( "hai" );
+ for (int i=-1; i < str.length_i()+2; i++) {
+ cout<<" left_str(" << i<<"): " << str.left_str( i ) << endl;
+ cout<<" right_str( "<<i<<"): " << str.right_str( i ) << endl;
+ }
+ str = "blonde haren";
+ cout << str<<endl;
+ cout << "mid(2,6)="<<str.mid_str(2,3)<<endl;
+ cout << "nomid(2,6)="<<str.nomid_str(2,3)<<endl;
+}
+
+int
+main()
+{
+ ctors();
+ cmp();
+ searching();
+ kutenpeer();
+ String str( "hai" );
+ cout << str << endl;
+ cout << "left" << endl;
+ str += " daar";
+ cout << str << endl;
+
+ str = String( "Hallo" ) + " daaR" + '!';
+ cout << str << endl;
+
+ cout << "up: " << str.upper_str() << " down: " << str.lower_str()<<endl;
+
+ if ( str == String( "" ) )
+ cout << str << " is empty" << endl;
+ else
+ cout << str << " is not empty"<<endl;
+
+
+ String fn = "";
+ if ( fn == "" )
+ cout << fn << " is empty" << endl;
+ else
+ assert(false);
+
+ fn = "";
+ fn += "";
+ delete fn.copy_byte_p();
+ delete str.copy_byte_p();
+
+ cout << String_convert::bin2hex_str( String( (char)0xff ) ) << endl;
+}
+
+#endif STRING_TEST
+
--- /dev/null
+/*
+ stringutil.cc -- generate non-inline members.
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#ifdef STRING_DEBUG
+#include <sys/types.h>
+#include <memory.h>
+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"
--- /dev/null
+#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<String> 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());
+ }
+}
+
+
--- /dev/null
+#include "text-stream.hh"
+
+Text_stream::Text_stream(String fn)
+{
+ ios::sync_with_stdio();
+ if (fn == "")
+ {
+ name = "<STDIN>";
+ 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"<<get_name() << ": " << line()<<": "<<s<<endl;
+}
+
--- /dev/null
+#include "unionfind.hh"
+/*
+ see a book on data structures
+ */
+
+Union_find::Union_find(int n)
+{
+ classes.set_size(n);
+
+ for (int i=0; i < n; i++) {
+ classes[i] = i;
+ }
+}
+
+int
+Union_find::find(int i)
+{
+ int rep = i;
+ while (classes[rep] != rep)
+ rep = classes[rep];
+ while (classes[i] != rep) {
+ int next =classes[i];
+ classes[i] = rep;
+ i = next;
+ }
+ return rep;
+}
+
+void
+Union_find::connect(int i, int j)
+{
+ i = find(i);
+ j = find(j);
+ classes[i] = j;
+}
--- /dev/null
+#include "vector.hh"
+Vector::Vector(Array<Real> 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;
+}