From 42760f5db93014a878f17f05538464326683d354 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 22 Sep 1999 11:22:30 +0200 Subject: [PATCH] release: 1.2.10 --- CHANGES | 17 + Documentation/topdocs/AUTHORS.texi | 2 + TODO | 9 +- VERSION | 4 +- flower/choleski.cc | 209 -------- flower/full-storage.cc | 168 ------- flower/include/choleski.hh | 52 -- flower/include/full-storage.hh | 171 ------- flower/include/matrix-storage.hh | 153 ------ flower/include/matrix.hh | 159 ------ flower/include/scalar.hh | 6 - flower/include/vector.hh | 117 ----- flower/matrix-debug.cc | 64 --- flower/matrix.cc | 299 ----------- flower/scalar.cc | 9 - flower/vector.cc | 35 -- input/bugs/auto-melismas.ly | 17 - input/bugs/hara.ly | 88 ---- input/bugs/l.ly | 13 - input/bugs/p.ly | 239 +++++++++ input/bugs/utremi_old.ly | 262 ---------- input/test/hara-kiri.ly | 32 +- lily/axis-group-element.cc | 1 + lily/bar-script-engraver.cc | 2 +- lily/break-algorithm.cc | 10 +- lily/col-info.cc | 70 --- lily/column-x-positions.cc | 9 - lily/gourlay-breaking.cc | 2 +- lily/graphical-element.cc | 13 +- lily/hara-kiri-vertical-group-spanner.cc | 9 +- lily/include/column-x-positions.hh | 1 - lily/include/graphical-element.hh | 2 +- lily/include/ineq-constrained-qp.hh | 91 ---- lily/include/line-spacer.hh | 1 - lily/include/qlp.hh | 44 -- lily/include/qlpsolve.hh | 95 ---- lily/include/rhythmic-head.hh | 2 +- lily/include/spring-spacer.hh | 99 ---- lily/include/staff-symbol-referencer.hh | 2 +- lily/ineq-constrained-qp.cc | 294 ----------- lily/mixed-qp.cc | 82 --- lily/note-column.cc | 2 +- lily/note-head.cc | 12 +- lily/{p-col.cc => paper-column.cc} | 0 lily/qlpsolve.cc | 169 ------- lily/rest.cc | 2 +- lily/rhythmic-head.cc | 8 +- lily/spring-spacer.cc | 432 ---------------- lily/staff-side.cc | 13 +- lily/staff-symbol-referencer.cc | 7 +- lily/stem.cc | 8 +- lily/tie.cc | 13 +- lily/volta-spanner.cc | 12 +- lily/word-wrap.cc | 2 +- make/out/lilypond.lsm | 8 +- make/out/lilypond.spec | 4 +- midi2ly/mudela-staff.cc | 45 +- scripts/abc2ly.py | 612 +++++++++++++++++------ 58 files changed, 835 insertions(+), 3468 deletions(-) delete mode 100644 flower/choleski.cc delete mode 100644 flower/full-storage.cc delete mode 100644 flower/include/choleski.hh delete mode 100644 flower/include/full-storage.hh delete mode 100644 flower/include/matrix-storage.hh delete mode 100644 flower/include/matrix.hh delete mode 100644 flower/include/vector.hh delete mode 100644 flower/matrix-debug.cc delete mode 100644 flower/matrix.cc delete mode 100644 flower/vector.cc delete mode 100644 input/bugs/auto-melismas.ly delete mode 100644 input/bugs/hara.ly delete mode 100644 input/bugs/l.ly create mode 100644 input/bugs/p.ly delete mode 100644 input/bugs/utremi_old.ly delete mode 100644 lily/col-info.cc delete mode 100644 lily/include/ineq-constrained-qp.hh delete mode 100644 lily/include/qlp.hh delete mode 100644 lily/include/qlpsolve.hh delete mode 100644 lily/include/spring-spacer.hh delete mode 100644 lily/ineq-constrained-qp.cc delete mode 100644 lily/mixed-qp.cc rename lily/{p-col.cc => paper-column.cc} (100%) delete mode 100644 lily/qlpsolve.cc delete mode 100644 lily/spring-spacer.cc diff --git a/CHANGES b/CHANGES index dde6aac485..4bccc170a1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,11 +1,28 @@ +pl 9.rrr1 + - abc2ly bug fixes and extensions + - volta spanner given height to avoid collisions + pl 9.jcn2 - 2.95 fixes - input/test/different-time-signatures.ly (wasn't this in refman?) +pl 9.hwn1 + - fixes for mi2mu + - bf: staff-side with empty parent. + - bf: +Hara_kiri_vertical_group_spanner::do_substitute_element_pointer has to +call Axis_group_spanner::do_substitute_element_pointer. Fixes +harakiri & barline problem. + - junk: Spring_spacer, Ineq_constrained_qp, Mixed_qp, +Active_constraints, Inactive_iter, Matrix, Vector, +Choleski_decomposition, Full_storage + + pl 9.jcn1 - included last Localisation.texi - set-lily: de catalog too +******* pl 8.hwn1 - Erwin Dieterich: german translation. - dependency helper funcs simplified. diff --git a/Documentation/topdocs/AUTHORS.texi b/Documentation/topdocs/AUTHORS.texi index c0eaec3cb0..017ea1722b 100644 --- a/Documentation/topdocs/AUTHORS.texi +++ b/Documentation/topdocs/AUTHORS.texi @@ -56,6 +56,8 @@ list is alphabetically ordered. parts of Documentation/Vocab*, started internationalization stuff @item @email{glenprideaux@@iname.com, Glen Prideaux}, minor bug fix to script used to generate doc++ documentation +@item @email{Roy.Rankin@@alcatel.com.au, Roy R. Rankin}, + major extension, fixes to abc2ly, lilypond bug fixes @item @email{daboys@@austin.rr.com, Jeffrey B. Reed}, Windows-NT support. @item Shay Rojanski diff --git a/TODO b/TODO index b6461b75e1..694d39e90e 100644 --- a/TODO +++ b/TODO @@ -10,8 +10,8 @@ Grep -i for TODO, FIXME and ugh/ugr/urg. .* TODO . * use Rhythmic_head::position_i () for all Staff_referenced -. * sleur.ly. * rerun profile -. * mmrests +. * Depracate Wordwrap +. * rerun profile . * Break_req handling is silly (break_forbid () + \break fucks up.) . * script engraver . * HaraKiriStaffContext removes bar lines and doesn't remove @@ -65,8 +65,9 @@ the mensural music notation. bar line fully drawn across the staves and after that keep to the ChoirStaff bar line types in the rest of the scores -- autoBeamMelisma: if I explicitly beam notes in a staff with auto beaming disabled I -would like to have these beams also to be melismatic. +- autoBeamMelisma: if I explicitly beam notes in a staff with auto +beaming disabled I would like to have these beams also to be +melismatic. . * make all Feta (including dynamics) available to the user in textual scripts. Examples: "D.S. al \coda", "\mf espress.". diff --git a/VERSION b/VERSION index e126e9c088..41c1aa8efa 100644 --- a/VERSION +++ b/VERSION @@ -1,8 +1,8 @@ PACKAGE_NAME=LilyPond MAJOR_VERSION=1 MINOR_VERSION=2 -PATCH_LEVEL=9 -MY_PATCH_LEVEL=jcn2 +PATCH_LEVEL=10 +MY_PATCH_LEVEL= # use the above to send patches: MY_PATCH_LEVEL is always empty for a # released version. diff --git a/flower/choleski.cc b/flower/choleski.cc deleted file mode 100644 index ae40c45613..0000000000 --- a/flower/choleski.cc +++ /dev/null @@ -1,209 +0,0 @@ -/* - choleski.cc -- implement Choleski_decomposition - - source file of the Flower Library - - (c) 1997--1999 Han-Wen Nienhuys -*/ - -#include "choleski.hh" -const Real EPS = 1e-7; // so sue me. Hard coded - -// for testing new Matrix_storage. -//#define PARANOID - -void -Choleski_decomposition::full_matrix_solve (Vector &out, Vector const &rhs) const -{ - int n= rhs.dim(); - assert (n == L.dim()); - Vector y; - y.set_dim (n); - out.set_dim (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 (out); // 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); - } -} - -void -Choleski_decomposition::band_matrix_solve (Vector &out, Vector const &rhs) const -{ - int n= rhs.dim(); - int b = L.band_i(); - assert (n == L.dim()); - - out.set_dim (n); - - Vector y; - y.set_dim (n); - - // forward substitution - for (int i=0; i < n; i++) - { - Real sum (0.0); - for (int j= 0 >? i - b; 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 (out); // using input as return val. - for (int i=n-1; i >= 0; i--) - { - Real sum (0.0); - for (int j=i+1; j <= i + b&&j < n ; j++) - sum += L(j,i)*x (j); - x (i) = (y (i) - sum)/L(i,i); - } -} - -void -Choleski_decomposition::solve (Vector &x, Vector const &rhs) const -{ - if (band_b_) - { - band_matrix_solve (x,rhs); - } - else - full_matrix_solve (x,rhs); -} - -Vector -Choleski_decomposition::solve (Vector rhs) const -{ - Vector r; - solve (r, rhs); - return r; -} - -void -Choleski_decomposition::full_matrix_decompose (Matrix const & P) -{ - - int n = P.dim(); - 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; - } - -} - -void -Choleski_decomposition::band_matrix_decompose (Matrix const &P) -{ - int n = P.dim(); - int b = P.band_i(); - L.unit(); - - for (int i= 0; i < n; i++) - { - for (int j = 0 >? i - b; j < i; j++) - { - Real sum (0.0); - for (int l=0 >? i - b; l < j; l++) - sum += L(i,l)*L(j,l)*D(l); - L(i,j) = (P(i,j) - sum)/D(j); - } - Real sum=0.0; - - for (int l=0 >? i - b; l < i; l++) - sum += sqr (L(i,l))*D(l); - Real d = P(i,i) - sum; - D(i) = d; - } - L.set_band(); - band_b_ = true; -} - - - - -/* - Standard matrix algorithm. - */ - -Choleski_decomposition::Choleski_decomposition (Matrix const & P) - : L(P.dim()), D(P.dim ()) -{ -#ifdef PARANOID - assert ((P-P.transposed()).norm ()/P.norm () < EPS); -#endif - band_b_ = false; - - int b = P.calc_band_i (); - - if (b <= P.dim ()/2) - band_matrix_decompose (P); - else - full_matrix_decompose (P); - -#ifdef PARANOID - 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); - Vector inv (n); - for (int i = 0; i < n; i++) - { - e_i.set_unit (i); - solve (inv, e_i); - for (int j = 0 ; j -*/ - -#include "full-storage.hh" - - -void -Full_storage::operator=(Full_storage const &fs) -{ - resize (fs.height_i_, fs.width_i_); - OK(); - fs.OK(); - for (int i=0; i= height_i_ && max_width_i_ >= width_i_); - assert (height_i_ >= 0 && width_i_ >= 0); - assert (els_p_p_||!max_height_i_); -#endif -} - - - - -Full_storage::~Full_storage() -{ - for (int i=0; i < max_height_i_; i++) - delete [] els_p_p_[i]; - delete[] els_p_p_; -} - -void -Full_storage::resize (int rows, int cols) -{ - OK(); - resize_cols (rows); - resize_rows (cols); - band_i_ = rows >? cols; -} - -void -Full_storage::delete_column (int k) -{ - assert (0 <= k &&k k ; i--) - for (int j=0; j -Full_storage::row (int n) const -{ - Array r; - for (int j = 0; j < cols(); j++) - r.push (elem (n,j)); - return r; -} - -Array -Full_storage::column (int n) const -{ - Array r; - for (int i = 0; i < rows(); i++) - r.push (elem (i,n)); - return r; -} - -void -Full_storage::set_size (int rows, int cols) -{ - resize (rows,cols); -} - -void -Full_storage::set_size (int rows) -{ - - resize (rows); -} - - - -void -Full_storage::resize_cols (int newh) -{ - if (newh <= max_height_i_) - { - height_i_=newh; - return; - } - - Real ** newa=new Real*[newh]; - int j=0; - for (; j < height_i_; j++) - newa[j] = els_p_p_[j]; - for (; j < newh; j++) - newa[j] = new Real[max_width_i_]; - delete[] els_p_p_; - els_p_p_=newa; - - height_i_ = max_height_i_ = newh; -} - - - -void -Full_storage::resize_rows (int neww) -{ - if (neww <= max_width_i_) - { - width_i_=neww; - return; - } - for (int i=0; i < max_height_i_ ; i++) - { - Real* newa = new Real[neww]; - for (int k=0; k < width_i_; k++) - newa[k] = els_p_p_[i][k]; - - delete[] els_p_p_[i]; - els_p_p_[i] = newa; - } - width_i_ = max_width_i_ = neww; -} - -#ifdef INLINE -#undef INLINE -#endif -#define INLINE - - -#include "full-storage.icc" diff --git a/flower/include/choleski.hh b/flower/include/choleski.hh deleted file mode 100644 index c6db243ba8..0000000000 --- a/flower/include/choleski.hh +++ /dev/null @@ -1,52 +0,0 @@ -#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; - - bool band_b_; - - /// diagonal - Vector D; - - /** Create decomposition of P. - PRE - P needs to be symmetric positive definite - */ - - Choleski_decomposition (Matrix const &P); - - /** - solve Px = rhs - */ - Vector solve (Vector rhs) const; - void solve (Vector &dest, Vector const &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; -private: - void full_matrix_solve (Vector &,Vector const&) const; - void band_matrix_solve (Vector &, Vector const&) const; - void full_matrix_decompose (Matrix const & P); - void band_matrix_decompose (Matrix const &P); - -}; -#endif diff --git a/flower/include/full-storage.hh b/flower/include/full-storage.hh deleted file mode 100644 index d666953d6f..0000000000 --- a/flower/include/full-storage.hh +++ /dev/null @@ -1,171 +0,0 @@ -/* - full-storage.hh -- declare Full_storage - - source file of the Flower Library - - (c) 1997--1999 Han-Wen Nienhuys -*/ - - -#ifndef FULL_STORAGE_HH -#define FULL_STORAGE_HH - -#include "array.hh" -#include "real.hh" - -#ifndef INLINE -#define INLINE inline -#endif - -/// simplest matrix storage. refer to its baseclass for the doco. -class Full_storage -{ - /// height, width - int height_i_; - int width_i_; - /// maxima. - int max_height_i_; - int max_width_i_; - - /// the storage - Real** els_p_p_; - - INLINE void init() ; - - INLINE bool valid (int i, int j) const ; - - void resize_rows (int); - void resize_cols (int); - -public: - int band_i_; // ugh - - /// check invariants - void OK() const; - - /// height of matrix - INLINE int rows() const; - - /// width of matrix - INLINE int cols() const; - - /// size if square - INLINE int dim() const; - - /** set the size. contents lost. - PRE - i >=0, j>=0 - */ - void set_size (int rows, int cols) ; - - - /**set the size to square dimen. contents lost - PRE - i>=0 - */ - void set_size (int i) ; - /**set the size to i. - - keep contents. If enlarged contents unspecified - - PRE - i>=0, j>=0 - - */ - void resize (int rows, int cols); - - /** - set the size to square dimen. contents kept - Keep contents. If enlarged contents are unspecified - - PRE - i>=0 - */ - void resize (int i); - - - /** - access an element. - - Generate an errormessage, if this happens - in the 0-part of a sparse matrix. - */ - - INLINE Real& elem (int i,int j); - - /// access a element, no modify - INLINE Real elem (int i, int j) const; - - Array row (int i) const ; - Array column (int j) const; - - - /** - add a row to the matrix before row k. Contents - of added row are unspecified - - 0 <= k <= rows() - */ - void insert_row (int k); - - - /** - delete a row from this matrix. - - PRE - 0 <= k < rows(); - */ - void delete_row (int k); - void delete_column (int k); - - - - /** - at end of matrix?. when doing loop - - for (i=0; i -*/ - - -#ifndef MATRIX_STORAGE_HH -#define MATRIX_STORAGE_HH - -#include "array.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 Matrix_storage { - - -public: - /// check invariants - void OK() const; - - /// height of matrix - int rows() const; - - /// width of matrix - int cols() const; - - /// size if square - int dim() const; - - /** set the size. contents lost. - PRE - i >=0, j>=0 - */ - void set_size (int rows, int cols) ; - - - /**set the size to square dimen. contents lost - PRE - i>=0 - */ - void set_size (int i) ; - /**set the size to i. - - keep contents. If enlarged contents unspecified - - PRE - i>=0, j>=0 - - */ - void resize (int rows, int cols); - - /** - set the size to square dimen. contents kept - Keep contents. If enlarged contents are unspecified - - PRE - i>=0 - */ - void resize (int i); - - - /** - access an element. - - Generate an errormessage, if this happens - in the 0-part of a sparse matrix. - */ - - Real& elem (int i,int j); - - /// access a element, no modify - Real elem (int i, int j) const; - - Array row (int i) const ; - Array column (int j) const; - - - /** - add a row to the matrix before row k. Contents - of added row are unspecified - - 0 <= k <= rows() - */ - void insert_row (int k); - - - /** - delete a row from this matrix. - - PRE - 0 <= k < rows(); - */ - void delete_row (int k); - void delete_column (int k); - ~Matrix_storage() { } - - - /** - at end of matrix?. when doing loop - - for (i=0; i -*/ - - -#ifndef MATRIX_HH -#define MATRIX_HH - -#include "full-storage.hh" -#include "vector.hh" -#include "offset.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 { - friend Matrix operator *(Matrix const &m1, Matrix const &m2); - -protected: - Full_storage *dat_; - void set (Matrix_storage*); -public: - void OK() const { dat_->OK(); } - void set_band (); - int calc_band_i () const; - 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; - - /** - the band size of the matrix. - @ret - - 0 <= band_i() <= dim - */ - int band_i() const; - - /// 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; - - String str () const; - void print() const; - ~Matrix (); -}; - -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; -} -inline Matrix operator +(Matrix m1,const Matrix m2) -{ - m1 += m2; - return m1; -} -#endif diff --git a/flower/include/scalar.hh b/flower/include/scalar.hh index e76841b561..b389277bc3 100644 --- a/flower/include/scalar.hh +++ b/flower/include/scalar.hh @@ -35,12 +35,6 @@ struct Scalar : public String int to_i () const; Real to_f () const; - /* - urg, these are bit silly; perhaps should make "Print_string" class - (derive from Scalar?) - */ - Scalar (Vector const &v); - Scalar (Matrix const &m); /** perl -like string to bool conversion. */ diff --git a/flower/include/vector.hh b/flower/include/vector.hh deleted file mode 100644 index b4eeb97597..0000000000 --- a/flower/include/vector.hh +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef VECTOR_HH -#define VECTOR_HH - -#include -#include "real.hh" -#include "array.hh" - -class Dstream; -class String; - -/** a row of numbers. - a vector. Storage is handled in Array, Vector only does the mathematics. - */ -class Vector { - Array dat; -public: - void OK() const { dat.OK();} - int dim() const { return dat.size (); } - void fill (Real r) { - for (int i=0; i < dim(); i++) - dat[i] =r; - } - - Vector() { } - Vector (Array d); - Vector (Vector const &n); - - Real &operator()(int i) { return dat[i]; } - Real operator()(int i) const { return dat[i]; } - Real elem (int i) { return dat[i]; } - Vector (int n) { - dat.set_size (n); - fill (0); - } - void set_dim (int i) - { - dat.set_size (i); - } - - void insert (Real v, int i) { - dat.insert (v,i); - } - void del (int i) { dat.del (i); } - - String str () const; - - void operator +=(Vector v) { - assert (v.dim() == dim ()); - for (int i=0; i < dim(); i++) - dat[i] += v.dat[i]; - } - - void operator -=(Vector v) { - assert (v.dim() == dim ()); - for (int i=0; i < dim(); i++) - dat[i] -= v (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; - } - void operator *=(Real a) { - for (int i=0; i < dim(); i++) - dat[i] *= a; - } - void operator /=(Real a) { - (*this) *= 1/a; - } - Vector operator-() const; - Real norm_sq() { - return ((*this) * (*this)); - } - Real norm() { - return sqrt (norm_sq()); - } - operator Array() { return dat; } - Array const &to_array()const { return dat; } - void print() const; - /// set to j-th element of unit-base - void set_unit (int j) ; -}; - -inline Vector -operator+(Vector a, Vector const &b) { - a += b; - return a; -} - -inline Vector -operator-(Vector a, Vector const &b) { - a -= b; - return a; -} - -inline Vector -operator*(Vector v, Real a) { - v *= a; - return v; -} - -inline Vector -operator*(Real a,Vector v) { - v *= a; - return v; -} - -inline Vector -operator/(Vector v,Real a) { - v *= 1/a; - return v; -} - -#endif diff --git a/flower/matrix-debug.cc b/flower/matrix-debug.cc deleted file mode 100644 index 323962e2c2..0000000000 --- a/flower/matrix-debug.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* - matrix-debug.cc -- implement Matrix print routines - - source file of the Flower Library - - (c) 1997--1999 Han-Wen Nienhuys -*/ - - -#include "flower-debug.hh" -#include "matrix.hh" - -String -Matrix::str () const -{ - String s; -#ifndef NPRINT - Full_storage const * stor_c_l = dat_; - s = String ("matrix {"); - for (int i=0; i< rows(); i++) - { - for (int j = 0; j < cols(); j++) - { - s+= to_str (stor_c_l->elem (i,j), "%6f "); - } - s+="\n"; - } - s+="}\n"; -#endif - return s; -} - - -void -Matrix::print () const -{ -#ifndef NPRINT - fdebug << *this; -#endif -} - -String -Vector::str () const -{ - String s; -#ifndef NPRINT - s = String ("vector (") + to_str (dim ()) + ") ["; - for (int i=0; i < dim(); i++) - { - s += to_str (dat[i], "%6f") + to_str (' '); - } - s += "]\n"; -#endif - return s; -} - - -void -Vector::print() const -{ -#ifndef NDEBUG - fdebug << *this << '\n'; -#endif -} diff --git a/flower/matrix.cc b/flower/matrix.cc deleted file mode 100644 index b671238ac5..0000000000 --- a/flower/matrix.cc +++ /dev/null @@ -1,299 +0,0 @@ -/* - matrix.cc -- implement Matrix - - source file of the Flower Library - - (c) 1997--1999 Han-Wen Nienhuys -*/ - -#include "matrix.hh" -#include "full-storage.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_ = new Full_storage (*m.dat_); -} - - -int -Matrix::band_i () const -{ - return dat_->band_i_; -} - -void -Matrix::set_band () -{ - dat_->band_i_ = calc_band_i (); -} - -int -Matrix::calc_band_i() const -{ - int starty = dim(); - while (starty >= 0) - { - for (int i = starty, j = 0; i < dim(); i++, j++) - if (dat_->elem (i,j)) - goto gotcha; - for (int i=0, j = starty; j < dim(); i++,j++) - if (dat_->elem (i,j)) - goto gotcha; - starty --; - } - gotcha: - return starty; -} - -Matrix::Matrix (Matrix const &m) -{ - dat_ = new Full_storage (*m.dat_); -} - - -Matrix::Matrix (int n, int m) -{ - dat_ = new Full_storage(n,m); - fill (0); -} - - -Matrix::Matrix (int n) -{ - dat_= new Full_storage (n,n); - fill (0); -} - -Matrix::Matrix (Vector v, Vector w) -{ - int n = v.dim(); - int m = w.dim (); - dat_= new Full_storage (n,m); - for (int i=0; i < n; i++) - for (int j=0; j < m ; 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; -} - -/* - ugh. Only works for square matrices. - */ -void -Matrix::transpose() -{ - 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; -} - -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; i < rows (); i++) - for (int j=0; j < cols (); j++) - { - Real r=0.0; - for (int k = 0 >? i - m1.band_i () >? j - m2.band_i (); - k < m1.cols(); k++) - { - r += m1(i,k)*m2(k,j); - } - dat_->elem (i,j)=r; - } -} - -void -Matrix::insert_row (Vector v, int k) -{ - int c = cols(); - assert (v.dim()==cols ()); - dat_->insert_row (k); - for (int j=0; j < c; j++) - dat_->elem (k,j)=v (j); -} - - -void -Matrix::swap_columns (int c1, int c2) -{ - assert (c1>=0&& c1 < cols()&&c2 < cols () && c2 >=0); - int r = rows(); - for (int i=0; i< r; 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); - int c = cols(); - for (int i=0; i< c; 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(); -} - -Matrix::~Matrix () -{ - delete dat_; -} diff --git a/flower/scalar.cc b/flower/scalar.cc index 951f50359d..476b6485bd 100644 --- a/flower/scalar.cc +++ b/flower/scalar.cc @@ -10,7 +10,6 @@ #include #include "scalar.hh" #include "rational.hh" -#include "matrix.hh" Scalar::Scalar (Rational r) { @@ -105,12 +104,4 @@ Scalar::to_bool () const return true; } -Scalar::Scalar(Matrix const &m) -{ - *this = m.str (); -} -Scalar::Scalar (Vector const &v) -{ - *this = v.str (); -} diff --git a/flower/vector.cc b/flower/vector.cc deleted file mode 100644 index e4eb654d69..0000000000 --- a/flower/vector.cc +++ /dev/null @@ -1,35 +0,0 @@ -/* - vector.cc -- implement Vector - - source file of the Flower Library - - (c) 1996-98 Han-Wen Nienhuys - - */ - -#include "vector.hh" - -Vector::Vector (Array 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; -} diff --git a/input/bugs/auto-melismas.ly b/input/bugs/auto-melismas.ly deleted file mode 100644 index bafa169559..0000000000 --- a/input/bugs/auto-melismas.ly +++ /dev/null @@ -1,17 +0,0 @@ -\score{ - \addlyrics - \context Staff { - \notes\relative c''{ c () d r e f } - \notes\relative c''{ c ~ c r c c } - } - { - \context Lyrics \lyrics { foo __ bar baz } - \context Lyrics \lyrics { foo __ bar baz } - } - \paper{ - \translator{ - \VoiceContext - automaticMelismas=1; - } - } -} diff --git a/input/bugs/hara.ly b/input/bugs/hara.ly deleted file mode 100644 index 85ff14adf8..0000000000 --- a/input/bugs/hara.ly +++ /dev/null @@ -1,88 +0,0 @@ - - -The following example shows 2 bugs with HaraKiriStaffContext. - -The first bug is that when the second staff disappears, the instr -string in the margin "2" is still printed, and surprisingly appears -above staff 1. - -The second and more serious bug is that when staff 2 reappears, -the bar separators are no longer being printed for that staff. - -Regards, -Roy Rankin - -\header { - composer = "Music: Trad."; - crossRefNumber = "4"; - title = "HaraKiri Bugs"; -} -voice1 = \notes { -\property Staff.instrument = "Part1" -\property Staff.instr = "1" -\property Staff.timeSignatureStyle="C" - \time 4/4; \key c; - e''4. e''8 e''4 r4 | e''4 d''4 - c''2 | - e''4 d''4 c''2 ( | - e''2 c''2 ~ | - ) c''1 \bar "|."; \break - e''4. e''8 e''4 r4 | e''4 d''4 - c''2 | - e''4 d''4 c''2 ( | - e''2 c''2 ~ | - ) c''1 \bar "|."; \break - e''4. e''8 e''4 r4 | e''4 d''4 - c''2 | - e''4 d''4 c''2 ( | - e''2 c''2 ~ | - ) c''1 \bar "|."; \break - e''4. e''8 e''4 r4 | e''4 d''4 - c''2 | - e''4 d''4 c''2 ( | - e''2 c''2 ~ | - ) c''1 \bar "|."; -} -voice2 = \notes { -\property Staff.instrument = "Part2" -\property Staff.instr = "2" -\property Staff.timeSignatureStyle="C" - \time 4/4; \key c; - e''4. e''8 e''4 r4 | e''4 d''4 - c''2 | - e''4 d''4 c''2 ( | - e''2 c''2 ~ | - ) c''1 \bar "|."; -s1 * 10 - e''4. e''8 e''4 r4 | e''4 d''4 - c''2 | - e''4 d''4 c''2 ( | - e''2 c''2 ~ | - ) c''1 \bar "|."; -} -\score{ - \notes < - - \context Staff="1" - { - \$voice1 - } - \context Staff="2" - { - \$voice2 - } - - > - \paper - { - \translator - { - \HaraKiriStaffContext - \consists Staff_margin_engraver; - } - } - \midi {} -} - - - diff --git a/input/bugs/l.ly b/input/bugs/l.ly deleted file mode 100644 index f042e73068..0000000000 --- a/input/bugs/l.ly +++ /dev/null @@ -1,13 +0,0 @@ -\score { - \notes { - \repeat volta 5 { - c' c' c' c' - } - \alternative { - {d' d' d' d'} - {e' e' e' e'} - } - f' - } - } - diff --git a/input/bugs/p.ly b/input/bugs/p.ly new file mode 100644 index 0000000000..fb5acbf510 --- /dev/null +++ b/input/bugs/p.ly @@ -0,0 +1,239 @@ +\header { + filename = "praeludium-fuga-E.ly"; + title = "praeludium and fuga in E-major"; + opus = "BWV 566"; + composer = "Johann Sebastian Bach (1685-1750)"; + enteredby = "JCN"; + copyright = "public domain"; +} +%{ + description + + Praeludium 3 bar excerpt, + 2nd fuga transposed subject -- 4 bar excerpt. + We try to imitate the Griepenkerl/Keller edition which + gives the best approximation to Bach's original layout + +%} +%{ + Tested Features: + purpose of this file is testing: + * real-life collisions + * multi-voice input --- splitting? + * organ staff... +%} + +\version "1.2.0"; + + + +praeludium_commands = \notes { + \time 4/4; + \key e; +} + +praeludium_right = \notes { + \$praeludium_commands + \clef violin; + + % 13 -- how to type -- where to split -- this more neatly? + \context Staff < + \context Voice = I \relative c'' { \stemup r4 dis4 e4. e8 ~ | + \shifton e4 [d8 fis8] \shiftoff gis4 ~ [gis8 fis16 e ] | + fis4 ~ [fis8 e16 dis] e4 r8 e8 } + \context Voice = III \relative c'' { \stemup \shifton r4 bis cis \shiftoff cis | + a' ~ [a16 gis a b] \shifton dis,4 cis ~ | + [cis8 dis16 ais] bis4 cis r8 b } + \context Voice = IV \relative c'' { + + %\stemup + %{ + this is a diversion from the Griepenkerl/Keller + edition; a hack to avoid collisions + %} + \stemdown + \shifton s4 gis } + + \context Voice = II \relative c' { \stemdown +% \shifton % idem + + r4 fis \shiftoff gis gis | + a4. cis8 gis2 | + fis4 gis gis r8 e8 } + > | + % 16 +} + +praeludium_left = \notes \relative c { + \$praeludium_commands + \clef bass; + + % 13 + \context Staff < + \context VoiceTwo { r4 } + \context VoiceOne { \stemup s4 dis' cis cis ~ | + [cis8 a d cis] [bis gis] cis4 | + dis2 cis4 r8 cis } + \context VoiceOne { \stemup bis2 } + \context VoiceThree { \stemup \shifton r4 gis ~ [gis8 gis] ~ \stemdown \shiftoff gis4 | + a4. fis8 gis4. a8 ~ | + a4 gis4 gis r8 gis } +% { \stemup \shifton s4 fis4 e} +% a quick hack to avoid some collisons + \context VoiceFour { \stemdown \shifton s4 fis4 e} + \context VoiceTwo { \stemdown s4 dis4 cis4 } + > | + %16 +} + +praeludium_pedal = \notes \relative c{ + \$praeludium_commands + \clef bass; + + %13 + r4 fis,4-\ltoe e4.-\lheel e'8-\rheel | + fis4.-\rtoe fis8-\rtoe fis4-\rtoe [e8-\ltoe a-\rtoe] | + dis,4-\ltoe gis-\rtoe [cis,8-\ltoe b!-\lheel ais-\rtoe gis-\ltoe] | + %16 +} + + +fugaII_commands = \notes{ + \time3/4; + \key e; % E-major +} + +fugaII_right = \notes \relative c'' { + \$fugaII_commands + \clef violin; + + %15 + \context Staff < + \context Voice = VA { \stemup [b8 fis8] b4 } + \context Voice = VB { \stemdown fis2 } + > + + % Wadieuw + \context Staff \notes\relative c''< + \context Voice=one { + \property Voice.horizontalNoteShift=0 + \property Voice.verticalDirection=1 + e4 + } + \context Voice=two { + \property Voice.verticalDirection=1 + \property Voice.horizontalNoteShift=1 + cis + } + \context Voice=three { + \property Voice.horizontalNoteShift=2 + \property Voice.verticalDirection=1 + ais + } + \context Voice=four { + \property Voice.verticalDirection=-1 + \property Voice.horizontalNoteShift=-1 + fis + } + > + + %16 + \context Staff < + \context VoiceOne { dis2 dis4 | + cis2 cis4 | + b4. [cis8 dis e] } + \context VoiceThree { \stemup \shifton [b8 fis] b2 ~ | + [b8 a!16 gis] a2 ~ | + a4 gis2 } + \context VoiceTwo { \stemdown fis2. ~ | + fis ~ | + fis4 e2 } + > | + %19 +} + +fugaII_left = \notes { + \$fugaII_commands + \clef bass; + + %15 + \context Staff < + \context VoiceTwo { \stemdown b2 \stemup ais4 | + b2 b4 } + \context VoiceTwo { \stemdown s2 e4 | + fis2 fis4 } + > + \stemdown cis2 e4 | + b4. b8 b4 | + %19 +} + +fugaII_pedal = \notes \relative c { + \$fugaII_commands + \clef bass; + + %15 + dis4.-\ltoe e8-\rtoe cis4 | + b4.-\lheel [cis8-\ltoe dis8-\rtoe e8-\rheel] | + fis4.-\rtoe [e8-\rheel dis8-\rtoe cis8-\ltoe] | + dis4-\rtoe e4-\rheel e,4-\ltoe | + %19 +} + +breakmusic = \notes { + %\time4/4; + r1 +} + + +% these should be two separate scores... +\score{ + \context Score < + \context PianoStaff < + \context Staff = treble { + \praeludium_right \breakmusic \fugaII_right } + \context Staff = bass { + \praeludium_left \breakmusic \fugaII_left } + > + \context Staff = pedal { + \praeludium_pedal \breakmusic \fugaII_pedal } + > + + \paper { + \translator { + \VoiceContext + \name "VoiceOne"; + verticalDirection = "1"; + } + \translator { + \VoiceContext + \name "VoiceTwo"; + verticalDirection = "-1"; + } + \translator { + \VoiceContext + \name "VoiceThree"; + verticalDirection = "1"; + horizontalNoteShift = "1"; + } + \translator { + \VoiceContext + \name "VoiceFour"; + verticalDirection = "-1"; + horizontalNoteShift = "1"; + } + \translator { + \StaffContext + + \accepts VoiceFour; + \accepts VoiceThree; + \accepts VoiceTwo; + \accepts VoiceOne; + } + \translator { \OrchestralScoreContext } +castingalgorithm = \Wordwrap; + } + + \midi { + \tempo 4 =96; } +} diff --git a/input/bugs/utremi_old.ly b/input/bugs/utremi_old.ly deleted file mode 100644 index 60a62403fa..0000000000 --- a/input/bugs/utremi_old.ly +++ /dev/null @@ -1,262 +0,0 @@ -\header { -filename = "utremi.ly"; -enteredby = "Christian Mondrup"; -%composer = "Thomas Ravenscroft"; -opus = "Thomas Ravenscroft"; -%opus = "Pammelia, 1609, no. 31"; -arranger = "Pammelia, 1609, no. 31"; -title = "Vt, re, me, fa, sol, la, sol, fa, re, vt"; -tagline = "Typeset with GNU LilyPond by Christian Mondrup. Non-commercial copying welcome."; -} - -papersize = "letter" - -\include "paper16.ly" -%\include "a4.ly" - -lyricsOne = \lyrics { - ""\breve ""8 - "Vt,"\breve re, me, fa, sol, la, "" - sol, la, fa, me, re, vt. -} - -lyricsTwo = \lyrics { - "" "" - Hey downe downe hey downe downe downe downe hey down - hey down "" down down a. - My heart of gold as true as steele - as I me leant "" vn -- to the bowres. - but if my La -- dy loue me well, - Lord so Ro -- bin bowres, -} - -lyricsThree = \lyrics { - "" "" "" "" "" "" "" "" "" "" "" "" - heaue and hoe Rum -- be -- lo, hey tro -- lo tro -- ly lo, - hey tro -- ly trol -- ly hey tro -- ly trol -- ly - hey tro -- ly trol -- ly hey trol -- "" ly trol -- ly lo. - My La -- dies gone to Can -- ter -- bu -- ry - S. Tho -- mas be her boote. - Shee met with Kate of Malms -- "" bu -- ry, - why weepst thou ma -- ple -} - -lyricsFour = \lyrics { - "" - roote: - O sleepst thou or wakst thon Ies -- se -- ry, Cooke, - the rost it burnes, turne round turne round "" a -- bout "" - turne round "" a -- bout, "" - turne round "" a -- bout, "" turne round. "" - O Fri -- er how fares thy ban -- de -- low ban -- de -- low - Fri -- er, how fares thy San -- de -- low, San -- de -- low. -} - -global = \notes { - \key c; - %\time 4/2; - %\time 17/8; - \time 33/16; - \clef "tenor"; -} - -dummyBeat = \notes { - \property Staff.defaultBarType = "||" - \property Staff.barAlways = "1" - s16 - \property Staff.barAlways = "0" - \property Staff.defaultBarType = "|" -} - -incipOne = \notes\relative c' { - g\breve - \dummyBeat - \bar ""; -} - -incipTwo = \notes\relative c'' { - \property Voice.noteHeadStyle = "diamond" - g1. - \property Voice.noteHeadStyle = "" - f2 - \dummyBeat - \bar ""; -} - -incipThree = \notes\relative c' { - \property Voice.noteHeadStyle = "harmonic" - \property Voice.tupletVisibility = 0 - \times 2/3 { d4. e8 d4 } \times 2/3 { b4. a8 g4 } - \times 2/3 { b4. c8 b4 } \times 2/3 { b4. a8 g4 } - \dummyBeat - \property Voice.tupletVisibility = 3 - \bar ""; -} - -incipFour = \notes\relative c' { - \property Voice.noteHeadStyle = "diamond" - %\property Voice.restStyle = "mensural" - b1 r1 - \dummyBeat - \bar ""; -} - -partOne = \notes\relative c' { - %\property Score.currentBarNumber = "1" - \property Voice.noteHeadStyle = "" - %\property Staff.barNumberScriptPadding = 1 - g1 ~ | g | a ~ | a | bes ~ | bes | c ~ | c | d ~ | d | e ~ | e | - r | r | - e ~ | e | d ~ | d | c ~ | c | bes ~ | bes | a ~ | a | g ~ | g - \bar "|."; -} - -partTwo = \notes\relative c'' { - \property Voice.noteHeadStyle = "" - g2. f4 | e2 d | c4. b8 a4 g | f2 e | - d g ~ | g4 a g2 | c,1 | r2 c | - g'2. a4 | b2 g | c c | c c | - b4 c d2 ~ | d4 d b g | c1 | r2 c | - g g | d2. e4 | f2 e | c1 | - g'2. g4 | g2 g | c,1 ~ | c | r | r - \bar "|."; -} - -partThree = \notes\relative c' { - \property Voice.noteHeadStyle = "" - \times 2/3 { d4. e8 d4 } \times 2/3 {b4. a8 g4 } | - \times 2/3 { b4. c8 b4 } \times 2/3 { b4. a8 g4 } - c2 c4 c | c2 c | - d2 d4 d | d2 d | e2. f4 | e2 d4 c | - b2 g ~ | g4 f e d | c1 | r2 c | - g'2. g4 | g2 g | c,2. c4 | c c c'2 | - bes g | bes bes | a1 | r2 e' | - d d | g g | a2. g4 | fis e d2 | - g g | d2. c4 - \bar "|."; -} - -partFour = \notes\relative c' { - \property Voice.noteHeadStyle = "" - b1^\fermata | r2 g' | e e4 e | a2. g4 | - fis2 e4 d | g1 | g2 g | g g | - g g | g g ~ | g4 f e d | c2 d ~ | - d4 c b a | g2 g' ~ | g4 f e d | c2 g' ~ | - g r | \times 2/3 { r1 d2 } \times 2/3 { a'2 a g } | - \times 2/3 { e1 f2 } \times 2/3 { g2. g4 g2 } - \times 2/3 { d2. d4 e2 } \times 2/3 { f2. f4 e2 } - \times 2/3 { d1 c2 } \times 2/3 { b2. a4 g2 } - \times 2/3 { d'2. d4 d2 } - \bar "|."; -} - -partOneStaff = < - \context Staff = vocal1 < - \property Staff.clefStyle = "fullSizeChanges" - \property Staff.instrument = "\large{1.}" - %\property Staff.instr = "" - \notes { - \global - \property Staff.timeSignatureStyle = "old4/4" - \incipOne - \clef "G_8"; - \property Staff.timeSignatureStyle = "C2/2" - \time 4/4; - \partOne - } - {\context Lyrics = lyrOne \lyricsOne } - > -> - -partTwoStaff = < - \context Staff = vocal2 < - \property Staff.clefStyle = "fullSizeChanges" - \property Staff.instrument = "\large{2.}" - %\property Staff.instr = "" - %\property Voice.automaticMelismata = "1" - \addlyrics - \notes { - \global - \property Staff.timeSignatureStyle = "old4/4" - \incipTwo - \clef "G_8"; - \property Staff.timeSignatureStyle = "C2/2" - \time 4/4; - \partTwo - } - {\context Lyrics = lyrTwo \lyricsTwo } - > -> - - -partThreeStaff = < - \context Staff = vocal3 < - \property Staff.clefStyle = "fullSizeChanges" - \property Staff.instrument = "\large{3.}" - %\property Staff.instr = "" - %\property Voice.automaticMelismata = "1" - \addlyrics - \notes { - \context Voice = vthree - \property Voice.tupletDirection = \up - \global - \property Staff.timeSignatureStyle = "old4/4" - \incipThree - \clef "G_8"; - \property Staff.timeSignatureStyle = "C2/2" - \time 4/4; - \partThree - } - {\context Lyrics = lyrThree \lyricsThree } - > -> - -partFourStaff = < - \context Staff = vocal4 < - \property Staff.clefStyle = "fullSizeChanges" - \property Staff.timeSignatureStyle = "C2/2" - \property Staff.barNumberDirection = \up - \property Staff.instrument = "\large{4.}" - \property Staff.instr = "" - %\property Voice.automaticMelismata = "1" - \addlyrics - \notes { - \context Voice = vfour - \property Voice.tupletDirection = \up - \global - %\property Staff.instrument = "\large{4.}" - %\property Staff.instr = "" - \property Staff.timeSignatureStyle = "old4/4" - \incipFour - \clef "G_8"; - \property Staff.timeSignatureStyle = "C2/2" - \time 4/4; - \partFour - } - {\context Lyrics = lyrFour \lyricsFour} - > -> - -\score { - \context StaffGroup < - \partFourStaff - \partThreeStaff - \partTwoStaff - \partOneStaff - > - %\paper {\translator {\BarNumberingStaffContext } } - \paper { - indent = 0.\mm; - linewidth = 17.0\cm; - textheight = 27.0\cm; - gourlay_maxmeasures=6.0; - \translator { \StaffContext - \consists "Staff_margin_engraver"; } - %\translator { \ScoreContext - % minVerticalAlign = 1.5*\staffheight; } - } - %\midi { - % output = "utremi.mid"; - % \tempo 2 = 80; - %} -} diff --git a/input/test/hara-kiri.ly b/input/test/hara-kiri.ly index 6d22d559b4..46e7a59981 100644 --- a/input/test/hara-kiri.ly +++ b/input/test/hara-kiri.ly @@ -7,24 +7,24 @@ toeter_i = \notes\relative c <{ \context Voice = upper { \stemup s1*6 } \context Voice = together { - c'''4 c c c \break + c'''4^"toet I" c c c d d d d \break - R1 \break + R1 \context Voice = upper { e4 e e e \break } - f f f f \break + f f f f g g g g }> toeter_ii = \notes \relative c \context Voice = together { - c''4 c c c \break - d d d d \break - R1 \break + c''4^"toet II" c c c + d d d d + R1 \context Voice = lower { \stemdown - e4 e e e \break + e4 e e e } - f f f f \break + f f f f g g g g } @@ -37,14 +37,14 @@ zager = \context Staff = zager \notes \relative c'' { \clef treble; \property Staff.instrument = "Zager" \property Staff.instr = "Zag." - c4 d e f \break + c4^"zag" d e f \property Staff.instr = "Zag. \& Zog." - f e d c \break - c d e f \break + f e d c + c d e f \property Staff.instr = "Zag." \stemup - f e d c \break - c d e f \break + f e d c + c d e f f e d c } @@ -52,14 +52,14 @@ zoger = \context Staff = zoger \notes \relative c'' { \clef treble; \property Staff.instrument = "Zoger" \property Staff.instr = "Zog." - c4 d e f \break + c4^"zog" d e f \skip 1*2; \translator Staff=zager \stemdown c2 g2 - a4 b c d \break + a4 b c d \skip 1*1; } @@ -78,7 +78,7 @@ zagers = \context GrandStaff < > > \paper{ - linewidth = 40.0\mm; + linewidth = 80.0\mm; \translator { \HaraKiriStaffContext } %uh? \translator { \OrchestralScoreContext } diff --git a/lily/axis-group-element.cc b/lily/axis-group-element.cc index 1fa40edda0..a0ea8abb99 100644 --- a/lily/axis-group-element.cc +++ b/lily/axis-group-element.cc @@ -35,6 +35,7 @@ Axis_group_element::get_children () { Link_array childs; Link_array elems = elem_l_arr (); + elems.concat (extra_elems_ ); for (int i=0; i < elems.size (); i++) { diff --git a/lily/bar-script-engraver.cc b/lily/bar-script-engraver.cc index 53721f811f..f5bfcacd91 100644 --- a/lily/bar-script-engraver.cc +++ b/lily/bar-script-engraver.cc @@ -59,7 +59,7 @@ Bar_script_engraver::do_acknowledge_element (Item *i) /* How do we make sure that staff_side_p_ has a dependency from - someone else? We can't use i for that, so we use some other element. + someone else? We can't use I for that, so we use some other element. */ // staff_side_p_->set_elt_property (dangling_scm_sym, SCM_BOOL_T) get_staff_info ().command_pcol_l ()->add_dependency (staff_side_p_); diff --git a/lily/break-algorithm.cc b/lily/break-algorithm.cc index 32450301f8..51486412c9 100644 --- a/lily/break-algorithm.cc +++ b/lily/break-algorithm.cc @@ -9,14 +9,12 @@ #include "score-column.hh" #include "break.hh" #include "paper-def.hh" -#include "spring-spacer.hh" #include "debug.hh" #include "line-of-score.hh" #include "paper-score.hh" #include "paper-column.hh" #include "cpu-timer.hh" #include "command-request.hh" -#include "spring-spacer.hh" #include "simple-spacer.hh" @@ -62,13 +60,7 @@ Break_algorithm::find_breaks () const Line_spacer* Break_algorithm::generate_spacing_problem (Line_of_cols curline, Interval line) const { - Real r = pscore_l_->paper_l_->get_var ("simple_spacing_solver"); - - Line_spacer * sp = 0; - if (r) - sp = new Simple_spacer; - else - sp = new Spring_spacer; + Line_spacer * sp = new Simple_spacer; sp->default_space_f_ = pscore_l_->paper_l_->get_var ("loose_column_distance"); diff --git a/lily/col-info.cc b/lily/col-info.cc deleted file mode 100644 index 2ebfd15d4f..0000000000 --- a/lily/col-info.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* - col-info.cc -- implement Column_info - - source file of the GNU LilyPond music typesetter - - (c) 1997--1999 Han-Wen Nienhuys -*/ - -#include "paper-column.hh" -#include "col-info.hh" -#include "debug.hh" - -void -Column_info::print() const -{ -#ifndef NPRINT - DOUT << "column { "; - if (fixed_b()) - DOUT << "fixed at " << fixed_position() << ", "; - assert (pcol_l_); - DOUT << width_.str(); - Direction d = LEFT; - do { - for (int i=0; i < rods_[d].size (); i++) - rods_[d][i].print (); - } while (flip (&d) != LEFT); - - DOUT <<"}\n"; -#endif -} - -Column_info::Column_info (Paper_column *col_l, Real const *fixed_C) -{ - if (fixed_C) - fixpos_p_.set_l (fixed_C); - pcol_l_ = col_l; - width_ = pcol_l_->extent(X_AXIS); - if (width_.empty_b()) - width_ = Interval(0,0); -} - - -Column_info::Column_info() -{ - pcol_l_ =0; -} - -bool -Column_info::fixed_b () const -{ - return fixpos_p_.get_C(); -} - -Real -Column_info::fixed_position () const -{ - return *fixpos_p_; -} - -int -Column_info::rank_i () const -{ - return pcol_l_->rank_i (); -} - -void -Spacer_rod::print ()const -{ - DOUT << "Other " << other_idx_ << "dist = " << distance_f_ << '\n'; -} diff --git a/lily/column-x-positions.cc b/lily/column-x-positions.cc index 988cf4f054..15fc02faae 100644 --- a/lily/column-x-positions.cc +++ b/lily/column-x-positions.cc @@ -9,7 +9,6 @@ #include "column-x-positions.hh" #include "real.hh" #include "debug.hh" -#include "vector.hh" #include "line-spacer.hh" Column_x_positions::Column_x_positions() @@ -36,8 +35,6 @@ Column_x_positions::print() const #ifndef NPRINT DOUT << "energy : " << energy_f_ << '\n'; DOUT << "line of " << config_.size() << " cols\n"; - Vector v (config_); - DOUT << v; #endif } @@ -49,12 +46,6 @@ Column_x_positions::OK() const #endif } -void -Column_x_positions::set_stupid_solution(Vector v) -{ - energy_f_ = infinity_f; - config_ = v; -} void Column_x_positions::stupid_solution() diff --git a/lily/gourlay-breaking.cc b/lily/gourlay-breaking.cc index de9da6836d..562d06391e 100644 --- a/lily/gourlay-breaking.cc +++ b/lily/gourlay-breaking.cc @@ -8,11 +8,11 @@ #include "gourlay-breaking.hh" #include "column-x-positions.hh" -#include "spring-spacer.hh" #include "debug.hh" #include "paper-column.hh" #include "paper-score.hh" #include "paper-def.hh" +#include "line-spacer.hh" #include "killing-cons.tcc" diff --git a/lily/graphical-element.cc b/lily/graphical-element.cc index ca2cec9137..d0e55a553d 100644 --- a/lily/graphical-element.cc +++ b/lily/graphical-element.cc @@ -71,17 +71,12 @@ Graphical_element::set_empty (bool b, Axis a1, Axis a2) } /** - Return true if empty in either direction. + Return true if empty in both A1 direction and A2 dir. */ bool -Graphical_element::empty_b (Axis a1, Axis a2) +Graphical_element::empty_b (Axis a) { - bool b = false; - if (a1 != NO_AXES) - b = b || dim_cache_[a1]->empty_b (); - if (a2 != NO_AXES) - b = b || dim_cache_[a2]->empty_b (); - return b; + return dim_cache_[a]->empty_b (); } Interval @@ -104,8 +99,6 @@ Graphical_element::do_print () const #endif } - - void Graphical_element::invalidate_cache (Axis a) { diff --git a/lily/hara-kiri-vertical-group-spanner.cc b/lily/hara-kiri-vertical-group-spanner.cc index 1c05020ec3..4b09a5d8a7 100644 --- a/lily/hara-kiri-vertical-group-spanner.cc +++ b/lily/hara-kiri-vertical-group-spanner.cc @@ -33,8 +33,12 @@ Hara_kiri_group_spanner::do_post_processing () Link_array childs = get_children (); for (int i = 0; i < childs.size (); i++) { - childs[i]->set_elt_property (transparent_scm_sym, SCM_BOOL_T); - childs[i]->set_empty (true, X_AXIS, Y_AXIS); + Score_element* s = childs[i]; + + if ( line_l () != s->line_l ()) + programming_error ("Killing other children too"); + s->set_elt_property (transparent_scm_sym, SCM_BOOL_T); + s->set_empty (true, X_AXIS, Y_AXIS); } set_empty (true); @@ -43,6 +47,7 @@ Hara_kiri_group_spanner::do_post_processing () void Hara_kiri_group_spanner::do_substitute_element_pointer (Score_element*o, Score_element*n) { + Axis_group_spanner::do_substitute_element_pointer (o,n); if (Item *it = dynamic_cast (o)) interesting_items_.substitute (it, dynamic_cast (n)); } diff --git a/lily/include/column-x-positions.hh b/lily/include/column-x-positions.hh index 254ae882a7..2807eca851 100644 --- a/lily/include/column-x-positions.hh +++ b/lily/include/column-x-positions.hh @@ -27,7 +27,6 @@ struct Column_x_positions { /** generate a solution with no regard to idealspacings or constraints. should always work */ void stupid_solution(); - void set_stupid_solution (Vector); Column_x_positions(); void add_paper_column (Paper_column*c); void print() const; diff --git a/lily/include/graphical-element.hh b/lily/include/graphical-element.hh index 41c9e0994c..eeb2582688 100644 --- a/lily/include/graphical-element.hh +++ b/lily/include/graphical-element.hh @@ -33,7 +33,7 @@ public: Set empty in direction a1 and a2. If an argument is NO_AXES, it is ignored. */ void set_empty (bool b, Axis a1 = NO_AXES, Axis a2 = NO_AXES); - bool empty_b (Axis a1 = NO_AXES, Axis a2 = NO_AXES); + bool empty_b (Axis a1); Graphical_element (); Graphical_element (Graphical_element const&); virtual ~Graphical_element (); diff --git a/lily/include/ineq-constrained-qp.hh b/lily/include/ineq-constrained-qp.hh deleted file mode 100644 index 247f2a7688..0000000000 --- a/lily/include/ineq-constrained-qp.hh +++ /dev/null @@ -1,91 +0,0 @@ -/* - ineq-constrained-qp.hh -- declare Ineq_constrained_qp - - source file of the GNU LilyPond music typesetter - - (c) 1997--1999 Han-Wen Nienhuys -*/ - - -#ifndef INEQ_CONSTRAINED_QP_HH -#define INEQ_CONSTRAINED_QP_HH - - - -#include "matrix.hh" - -/** inequality constrained quadratic program - - It takes the form of - - optimise for x : x*quad_ *x + lin_* x + const_term_ - - subject to for all i: cons_[i] * x >= consrhs_[i] - - - @usage: - instantiate Ineq_constrained_qp. - - Modify quad_, lin_ and const_term_ directly. Use - add_inequality_cons () to add constraints. Call solve () with a - feasible solution - - - */ -class Ineq_constrained_qp { - friend class Active_constraints; - - Array cons_; - Array consrhs_; -public: - Matrix quad_; - Vector lin_; - Real const_term_; - - - /** - use a KKT method to assert optimality of sol - */ - void assert_solution (Vector sol) const; - /// solve the problem using a projected gradient method - Vector constraint_solve (Vector) const; - /** - Solve it. First try it the easy way. - */ - Vector solve (Vector start) const; - - /** - @return the number of variables in the problem - */ - int dim() const; - - /** - add a constraint - - - c*vars >= r - - PRE - c.dim() == dim (); - - */ - void add_inequality_cons (Vector c, double r); - - /** set up matrices to go with the problem. */ - Ineq_constrained_qp (int novars); - - /** - evaluate the quadratic function for input #v# - */ - Real eval (Vector v); - - void eliminate_var (int idx, Real value); - void OK() const; - void print() const; - -}; - -// ugh -const Real EPS=1e-7; - -#endif // INEQ_CONSTRAINED_QP_HH diff --git a/lily/include/line-spacer.hh b/lily/include/line-spacer.hh index ee51de4770..49bdd56e4f 100644 --- a/lily/include/line-spacer.hh +++ b/lily/include/line-spacer.hh @@ -11,7 +11,6 @@ #define LINE_SPACER_HH #include "lily-proto.hh" #include "array.hh" -#include "vector.hh" #include "interval.hh" /** diff --git a/lily/include/qlp.hh b/lily/include/qlp.hh deleted file mode 100644 index af7513e5d0..0000000000 --- a/lily/include/qlp.hh +++ /dev/null @@ -1,44 +0,0 @@ -/* - qlp.hh -- declare Ineq_constrained_qp, Mixed_qp - - source file of the GNU LilyPond music typesetter - - (c) 1997--1999 Han-Wen Nienhuys -*/ - -#ifndef QLP_HH -#define QLP_HH - -#include "ineq-constrained-qp.hh" - -/** - Quadratic programming with mixed linear constraints. - problem definition of a quadratic optimisation problem with linear - inequality and equality constraints - - - x^T QUAD x /2 + b^T x -*/ -class Mixed_qp :public Ineq_constrained_qp { - Array eq_cons; - Array eq_consrhs; -public: - Mixed_qp (int n); - void OK() const; - void print() const; - - Vector solve (Vector start) const; - void add_fixed_var (int i , Real value); - - - /** - add a constraint, - - c*vars == r - - PRE - c.dim()==dim (); - */ - void add_equality_cons (Vector c, double r); -}; -#endif diff --git a/lily/include/qlpsolve.hh b/lily/include/qlpsolve.hh deleted file mode 100644 index 9a342527ee..0000000000 --- a/lily/include/qlpsolve.hh +++ /dev/null @@ -1,95 +0,0 @@ -/* - qlpsolve.hh -- declare Active_constraints, Inactive_iter - - source file of the GNU LilyPond music typesetter - - (c) 1997--1999 Han-Wen Nienhuys -*/ - - -#ifndef QLPSOLVE_HH -#define QLPSOLVE_HH - -#include "matrix.hh" - - -/** - This class represents the set of active (binding) constraints - which can be active while the QLP algorithm is in a feasible - point. The active constraints are numbered. - If the constraints are of the form - - A^T*x >= b - - then the binding constraints are those where the >= is equality. - - */ - -class Active_constraints { - friend class Inactive_iter; - - - Matrix A,H; - Array active; - Array inactive; // actually this is a set, not an array. - Ineq_constrained_qp const *opt; - -public: - - /** This counts the number of errors the algorithms makes. The - optimum search should be abandoned if it becomes too high. */ - int degenerate_count_i_; - String status() const; - - Vector vec (int k) const { return opt->cons_[k]; } - Real rhs (int k) const { return opt->consrhs_[k]; } - - - /** drop constraint. drop constraint k from the active set. k is the index of the - constraint in #active# - - */ - void drop_constraint (int k); - - - /** add constraint j. - add constraint j to the active set j is the index of the - constraint in #inactive# - */ - void add_constraint (int j); - - /// exchange in and out. - void exchange (int in, int out) { add_constraint (in); drop_constraint (out); } - - - Vector find_active_optimum (Vector g); - - /// get lagrange multipliers. - Vector get_lagrange (Vector v); - - Active_constraints (Ineq_constrained_qp const *op); - /** construct: no constraints active, n vars. Put the equalities - into the constraints. */ - - /// check invariants - void OK(); -}; - - -/** - loop through the inactive constraints. - */ -class Inactive_iter { - int j; - Active_constraints const* ac; -public: - Inactive_iter (Active_constraints const &c) { ac=&c; j=0; } - int idx() const { return j; } - void operator ++(int) { j++; } - int constraint_id() const { return ac->inactive[j]; } - Vector vec() const { return ac->vec (constraint_id ()); } - Real rhs() const { return ac->rhs (constraint_id ()); } - bool ok() const { return j < ac->inactive.size (); } -}; - -#endif // QLPSOLVE_HH diff --git a/lily/include/rhythmic-head.hh b/lily/include/rhythmic-head.hh index e516b2cdc5..7f792787db 100644 --- a/lily/include/rhythmic-head.hh +++ b/lily/include/rhythmic-head.hh @@ -26,7 +26,7 @@ public: Rhythmic_head (); int dots_i ()const; - virtual int position_i () const; + virtual Real position_f () const; protected: virtual void do_post_processing (); virtual void do_pre_processing (); diff --git a/lily/include/spring-spacer.hh b/lily/include/spring-spacer.hh deleted file mode 100644 index 7359f6a1a6..0000000000 --- a/lily/include/spring-spacer.hh +++ /dev/null @@ -1,99 +0,0 @@ -/* - spring-spacer.hh -- declare Spring_spacer - - source file of the GNU LilyPond music typesetter - - (c) 1997--1999 Han-Wen Nienhuys -*/ - - -#ifndef SPRING_SPACER_HH -#define SPRING_SPACER_HH - -#include "line-spacer.hh" -#include "cons.hh" -#include "col-info.hh" -#include "column-x-positions.hh" -#include "moment.hh" - - - -/** - Determine positions of columns connected by springs and held apart by rods. - - - Generate a spacing which - \begin{itemize} - \item - Satisfies spacing constraints (notes can't be printed through each other) - \item - Looks good, ie tries to conform to an ideal spacing as much as possible. - \end{itemize} - - This is converted by regarding idealspacing as "springs" attached - to columns. The equilibrium of one spring is the ideal - distance. The columns have a size, this imposes "hard" constraints - on the distances. This transforms the problem into a quadratic - programming problem with linear constraints. - - The quality is given by the total potential energy in the - springs. The lower the energy, the better the configuration. - - - TODO: too complicated. Revise. - Use force iso. energy. Also optimise for uniform density -*/ - -class Spring_spacer : public Line_spacer { - friend class Durations_iter; -private: - // can't copy me. - Spring_spacer (Spring_spacer const&s); - Cons *ideal_p_list_; - Array cols_; - Real indent_f_; - - /// the index of #c# in #cols# - int col_id (Paper_column const *c) const; - - /// generate an (nonoptimal) solution - Vector find_initial_solution() const; - - /// does #this# contain the column #w#? - bool contains_b (Paper_column const *w); - - /// make the energy function - void make_matrices (Matrix &quad, Vector &lin,Real&) const; - - - /// generate the LP constraints - void make_constraints (Mixed_qp& lp) const; - - - void handle_loose_cols(); - bool try_initial_solution_and_tell (Vector&)const; - Vector try_initial_solution() const; - - void set_fixed_cols (Mixed_qp&) const; - - Score_column* scol_l (int); - void connect (int i,int j, Real,Real); - Real calculate_energy_f (Vector) const; -public: - static Line_spacer *constructor(); - Real energy_normalisation_f_; - Spring_spacer (); - virtual ~Spring_spacer (); - virtual void solve (Column_x_positions*) const; - virtual void lower_bound_solution (Column_x_positions*) const; - virtual void add_columns (Link_array); - void add_column (Paper_column *, bool, Real); - - virtual Vector default_solution() const; - virtual bool check_constraints (Vector v) const; - virtual void OK() const; - virtual void print() const; - virtual void prepare(); -}; - -#endif // SPRING_SPACER_HH diff --git a/lily/include/staff-symbol-referencer.hh b/lily/include/staff-symbol-referencer.hh index c64381c8d5..f768269c5b 100644 --- a/lily/include/staff-symbol-referencer.hh +++ b/lily/include/staff-symbol-referencer.hh @@ -30,7 +30,7 @@ public: int lines_i () const; virtual void do_substitute_element_pointer (Score_element*,Score_element*); - virtual int position_i () const; + virtual Real position_f () const; }; #endif /* STAFF_SYM_REFERENCER_HH */ diff --git a/lily/ineq-constrained-qp.cc b/lily/ineq-constrained-qp.cc deleted file mode 100644 index 563199c938..0000000000 --- a/lily/ineq-constrained-qp.cc +++ /dev/null @@ -1,294 +0,0 @@ -/* - ineq-constrained-qp.cc -- implement Ineq_constrained_qp - - source file of the GNU LilyPond music typesetter - - (c) 1996, 1997--1999 Han-Wen Nienhuys -*/ -#include "ineq-constrained-qp.hh" -#include "qlpsolve.hh" -#include "debug.hh" -#include "choleski.hh" -#include "main.hh" - -/* - May be this also should go into a library - */ - -const int MAXITER=100; // qlpsolve.hh - -const int MAXDEGEN=5; - -/* - assume x (idx) == value, and adjust constraints, lin and quad accordingly - - TODO: add const_term - */ -void -Ineq_constrained_qp::eliminate_var (int idx, Real value) -{ - Vector row (quad_.row (idx)); - row*= value; - - quad_.delete_row (idx); - - quad_.delete_column (idx); - - lin_.del (idx); - row.del (idx); - lin_ +=row ; - - for (int i=0; i < cons_.size(); i++) - { - consrhs_[i] -= cons_[i](idx) *value; - cons_[i].del (idx); - } -} - -void -Ineq_constrained_qp::add_inequality_cons (Vector c, double r) -{ - cons_.push (c); - consrhs_.push (r); -} - -Ineq_constrained_qp::Ineq_constrained_qp (int novars): - quad_ (novars), - lin_ (novars), - const_term_ (0.0) -{ -} - -void -Ineq_constrained_qp::OK() const -{ -#if !defined (NDEBUG) && defined (PARANOID) - assert (cons_.size() == consrhs_.size ()); - Matrix Qdif= quad_ - quad_.transposed(); - assert (Qdif.norm()/quad_.norm () < EPS); -#endif -} - - -Real -Ineq_constrained_qp::eval (Vector v) -{ - return v * quad_ * v + lin_ * v + const_term_; -} - - -int -min_elt_index (Vector v) -{ - Real m=infinity_f; - int idx=-1; - for (int i = 0; i < v.dim(); i++) - { - if (v (i) < m) - { - idx = i; - m = v (i); - } - assert (v (i) <= infinity_f); - } - return idx; -} - - -/**the numerical solving. Mordecai Avriel, Nonlinear Programming: analysis and methods (1976) - Prentice Hall. - - Section 13.3 - - This is a "projected gradient" algorithm. Starting from a point x - the next point is found in a direction determined by projecting - the gradient onto the active constraints. (well, not really the - gradient. The optimal solution obeying the active constraints is - tried. This is why H = Q^-1 in initialisation)) - - - */ -Vector -Ineq_constrained_qp::constraint_solve (Vector start) const -{ - if (!dim()) - return Vector (0); - - Active_constraints act (this); - act.OK(); - - - Vector x (start); - Vector gradient=quad_*x+lin_; - - - // Real fvalue = x*quad_*x/2 + lin*x + const_term;// it's no use. - Vector last_gradient (gradient); - int iterations=0; - - while (iterations++ < MAXITER && act.degenerate_count_i_ < MAXDEGEN) - { - if (experimental_features_global_b) - assert_solution (x); - - Vector direction= - act.find_active_optimum (gradient); - - DOUT << "gradient "<< gradient<< "\ndirection " << direction<< '\n'; - - if (direction.norm() > EPS) - { - DOUT << act.status() << '\n'; - - Real unbounded_alfa = 1.0; - Real minalf = unbounded_alfa; - - Inactive_iter minidx (act); - - - /* - we know the optimum on this "hyperplane". Check if we - bump into the edges of the simplex - */ - - for (Inactive_iter ia (act); ia.ok(); ia++) - { - Real dot = ia.vec() * direction; - Real mindot = (experimental_features_global_b) - ? -EPS - : 0; - - if (dot >= mindot) - continue; - - - Real numerator = ia.rhs () - ia.vec()*x; - if (numerator >= 0) - { - if (numerator > EPS) - { - warning (_f ("Ineq_constrained_qp::solve (): Constraint off by %f", numerator)); - act.degenerate_count_i_ ++; - } - minalf = -numerator; - minidx = ia; - break; - } - - Real alfa = numerator / dot; - - - if (minalf > alfa) - { - minidx = ia; - minalf = alfa; - } - } - - Real optimal_step = minalf; - - Vector deltax = direction * optimal_step; - x += deltax; - gradient += optimal_step * (quad_ * deltax); - - DOUT << "step = " << optimal_step << " (|dx| = " << - to_str (deltax.norm()) << ")\n"; - - if (minalf < unbounded_alfa) - { - /* bumped into an edge. try again, in smaller space. */ - act.add_constraint (minidx.idx()); - DOUT << "adding cons "<< minidx.idx () << '\n'; - continue; - } - /*ASSERT: we are at the optimal solution for this "plane"*/ - } - - Vector lagrange_mult=act.get_lagrange (gradient); - int m= min_elt_index (lagrange_mult); - - if (m>=0 && lagrange_mult (m) > 0) - { - break; // optimal sol. - } - else if (m<0) - { - Real n =gradient.norm(); - if (n >= EPS) - { - programming_error ("Huh? Gradient should be zero "); - act.degenerate_count_i_ ++; - } - else if (n <0) - { - programming_error ("Huh? Norm should be positive"); - act.degenerate_count_i_++; - } - break; - } - - DOUT << "dropping cons " << m << '\n'; - act.drop_constraint (m); - } - if (iterations >= MAXITER) - WARN << _ ("Didn't converge!") << '\n'; - if (act.degenerate_count_i_ >= MAXDEGEN) - WARN << _ ("too much degeneracy") << '\n'; - DOUT << ": found " << x << " in " << iterations <<" iterations\n"; - assert_solution (x); - return x; -} - - -Vector -Ineq_constrained_qp::solve (Vector start) const -{ - /* no hassle if no constraints*/ - if (! cons_.size()) - { - Choleski_decomposition chol (quad_); - return - chol.solve (lin_); - } - else - { - return constraint_solve (start); - } -} - -int -Ineq_constrained_qp::dim () const -{ - return lin_.dim(); -} - - - - -void -Ineq_constrained_qp::assert_solution (Vector sol) const -{ - bool sol_b=true; - - for (int i=0; sol_b && i < cons_.size(); i++) - { - Real R=cons_[i] * sol- consrhs_[i]; - if (R> -EPS) - sol_b = false; - } -} - -void -Ineq_constrained_qp::print() const -{ -#ifndef NPRINT - DOUT << "Ineq_constrained_qp { " << '\n'; - DOUT << "Quad " << quad_; - DOUT << "lin " << lin_ << '\n' - << "const " << const_term_<< '\n'; - for (int i=0; i < cons_.size(); i++) - { - DOUT << "constraint["<= " << consrhs_[i]; - DOUT << '\n'; - } - DOUT << "}\n"; -#endif -} diff --git a/lily/mixed-qp.cc b/lily/mixed-qp.cc deleted file mode 100644 index 25946d444f..0000000000 --- a/lily/mixed-qp.cc +++ /dev/null @@ -1,82 +0,0 @@ -/* - qlp.cc -- implement Mixed_qp - - source file of the GNU LilyPond music typesetter - - (c) 1997--1999 Han-Wen Nienhuys -*/ - -#include "debug.hh" -#include "qlp.hh" - - -void -Mixed_qp::add_equality_cons (Vector , double) -{ - assert (false); -} - -void -Mixed_qp::add_fixed_var (int i, Real r) -{ - eq_cons.push (i); - eq_consrhs.push (r); -} - - -/** - eliminate appropriate variables, until we have a Ineq_constrained_qp - then solve that. - - PRE - cons should be ascending - */ -Vector -Mixed_qp::solve (Vector start) const -{ - if (!dim()) - return Vector (0); - - print(); - Ineq_constrained_qp pure (*this); - - for (int i= eq_cons.size()-1; i>=0; i--) - { - pure.eliminate_var (eq_cons[i], eq_consrhs[i]); - start.del (eq_cons[i]); - } - Vector sol = pure.solve (start); - for (int i= 0; i < eq_cons.size(); i++) - { - sol.insert (eq_consrhs[i],eq_cons[i]); - } - return sol; -} - - -Mixed_qp::Mixed_qp (int n) - : Ineq_constrained_qp (n) -{ -} - -void -Mixed_qp::OK() const -{ -#ifndef NDEBUG - Ineq_constrained_qp::OK(); - assert (eq_consrhs.size() == eq_cons.size ()); -#endif -} - -void -Mixed_qp::print() const -{ -#ifndef NPRINT - Ineq_constrained_qp::print(); - for (int i=0; i < eq_cons.size(); i++) - { - DOUT << "eq cons "<position_i (); + int j = int (head_l_arr_[i]->position_f ()); iv.unite (Slice (j,j)); } return iv; diff --git a/lily/note-head.cc b/lily/note-head.cc index 8ea7cb460d..3c13d1ae1c 100644 --- a/lily/note-head.cc +++ b/lily/note-head.cc @@ -33,7 +33,7 @@ Note_head::do_pre_processing () if (balltype_i_ > 2) balltype_i_ = 2; if (dots_l_) // move into Rhythmic_head? - dots_l_->position_i_ = position_i (); + dots_l_->position_i_ = int (position_f ()); } @@ -41,7 +41,7 @@ Note_head::do_pre_processing () int Note_head::compare (Note_head *const &a, Note_head * const &b) { - return a->position_i () - b->position_i (); + return sign(a->position_f () - b->position_f ()); } /** @@ -61,9 +61,9 @@ Note_head::do_brew_molecule_p() const Real inter_f = staff_line_leading_f ()/2; int sz = lines_i ()-1; - int streepjes_i = abs (position_i ()) < sz + int streepjes_i = abs (position_f ()) < sz ? 0 - : (abs(position_i ()) - sz) /2; + : (abs(position_f ()) - sz) /2; String type; @@ -79,7 +79,7 @@ Note_head::do_brew_molecule_p() const if (streepjes_i) { - Direction dir = (Direction)sign (position_i ()); + Direction dir = (Direction)sign (position_f ()); Interval hd = out->dim_[X_AXIS]; Real hw = hd.length ()/4; @@ -87,7 +87,7 @@ Note_head::do_brew_molecule_p() const = lookup_l ()->ledger_line (Interval (hd[LEFT] - hw, hd[RIGHT] + hw)); - int parity = abs(position_i ()) % 2; + int parity = abs(int (position_f ())) % 2; for (int i=0; i < streepjes_i; i++) { diff --git a/lily/p-col.cc b/lily/paper-column.cc similarity index 100% rename from lily/p-col.cc rename to lily/paper-column.cc diff --git a/lily/qlpsolve.cc b/lily/qlpsolve.cc deleted file mode 100644 index 3d64b37792..0000000000 --- a/lily/qlpsolve.cc +++ /dev/null @@ -1,169 +0,0 @@ -/* - qlpsolve.cc -- implement Active_constraints, Inactive_iter - - source file of the GNU LilyPond music typesetter - - (c) 1996, 1997--1999 Han-Wen Nienhuys - - TODO: - try fixed point arithmetic, to speed up lily. - */ - -#include "ineq-constrained-qp.hh" -#include "qlpsolve.hh" -#include "debug.hh" -#include "choleski.hh" - -const Real TOL=1e-1; // roughly 1/30 mm - -String -Active_constraints::status() const -{ - String s ("Active|Inactive ["); - for (int i=0; i< active.size(); i++) - { - s += to_str (active[i]) + " "; - } - - s+="| "; - for (int i=0; i< inactive.size(); i++) - { - s += to_str (inactive[i]) + " "; - } - s+="]"; - - return s; -} - -void -Active_constraints::OK() -{ -#ifndef NDEBUG - H.OK(); - A.OK(); - assert (active.size() +inactive.size () == opt->cons_.size ()); - assert (H.dim() == opt->dim ()); - assert (active.size() == A.rows ()); - Array allcons; - - for (int i=0; i < opt->cons_.size(); i++) - allcons.push (0); - for (int i=0; i < active.size(); i++) - { - int j = active[i]; - allcons[j]++; - } - for (int i=0; i < inactive.size(); i++) - { - int j = inactive[i]; - allcons[j]++; - } - for (int i=0; i < allcons.size(); i++) - assert (allcons[i] == 1); -#endif -} - -Vector -Active_constraints::get_lagrange (Vector gradient) -{ - return (A*gradient); -} - -void -Active_constraints::add_constraint (int k) -{ - // add indices - int cidx=inactive[k]; - - Vector a (opt->cons_[cidx]); - // update of matrices - Vector Ha = H*a; - Real aHa = a*Ha; - Vector addrow (Ha.dim()); - bool degenerate = (abs (aHa) < EPS); - - if (degenerate) - { - warning (String ("Active_constraints::add ():") - + _("degenerate constraints")); - DOUT << "Ha = " << Ha.str () << '\n'; - /* - a != 0, so if Ha = O(EPS), then - Ha * aH / aHa = O(EPS^2/EPS) - - if H*a == 0, the constraints are dependent. - */ - degenerate_count_i_ ++; - } - if (!degenerate) - { - active.push (cidx); - inactive.swap (k,inactive.size()-1); - inactive.pop(); - - H -= Matrix (Ha/aHa , Ha); - - addrow=Ha; - addrow /= aHa; - A -= Matrix (A*a, addrow); - A.insert_row (addrow,A.rows()); - } -} - -void -Active_constraints::drop_constraint (int k) -{ - int q=active.size()-1; - - - Vector a (A.row (q)); - if (a.norm() > EPS) - { - // drop indices - inactive.push (active[k]); - active.swap (k,q); - A.swap_rows (k,q); - active.pop(); - /* - - */ - Real aqa = a*opt->quad_*a; - Matrix aaq (a,a/aqa); - H += aaq; - A -= A*opt->quad_*aaq; - - A.delete_row (q); - }else { - degenerate_count_i_ ++; - warning (String ("Active_constraints::drop ():") - + _("degenerate constraints")); - } -} - - -Active_constraints::Active_constraints (Ineq_constrained_qp const *op) - : A(0,op->dim()), - H(op->dim()), - opt (op) -{ - for (int i=0; i < op->cons_.size(); i++) - inactive.push (i); - Choleski_decomposition chol (op->quad_); - - /* - ugh. - */ - H=chol.inverse(); - OK(); - - degenerate_count_i_ = 0; -} - -/** Find the optimum which is in the planes generated by the active - constraints. - */ -Vector -Active_constraints::find_active_optimum (Vector g) -{ - return H*g; -} diff --git a/lily/rest.cc b/lily/rest.cc index af38a2b0d3..daa9ceb5dd 100644 --- a/lily/rest.cc +++ b/lily/rest.cc @@ -46,7 +46,7 @@ Rest::do_brew_molecule_p () const bool ledger_b =false; if (balltype_i_ == 0 || balltype_i_ == 1) - ledger_b = abs(position_i () - (2* balltype_i_ - 1)) > lines_i (); + ledger_b = abs(position_f () - (2* balltype_i_ - 1)) > lines_i (); diff --git a/lily/rhythmic-head.cc b/lily/rhythmic-head.cc index 00f6cb1df4..61ae70ffac 100644 --- a/lily/rhythmic-head.cc +++ b/lily/rhythmic-head.cc @@ -30,7 +30,7 @@ Rhythmic_head::do_post_processing () { if (dots_l_) { - dots_l_->position_i_ = position_i (); + dots_l_->position_i_ = int (position_f ()); } } @@ -41,10 +41,10 @@ Rhythmic_head::do_pre_processing () position_i_ = 0; } -int -Rhythmic_head::position_i () const +Real +Rhythmic_head::position_f () const { - return position_i_ + Staff_symbol_referencer::position_i (); + return position_i_ + Staff_symbol_referencer::position_f (); } diff --git a/lily/spring-spacer.cc b/lily/spring-spacer.cc deleted file mode 100644 index 45dcb76a8e..0000000000 --- a/lily/spring-spacer.cc +++ /dev/null @@ -1,432 +0,0 @@ -/* - spring-spacer.cc -- implement Spring_spacer - - source file of the GNU LilyPond music typesetter - - (c) 1996--1999 Han-Wen Nienhuys -*/ - - -#include -#include -#include "killing-cons.tcc" -#include "spring-spacer.hh" -#include "paper-column.hh" -#include "debug.hh" -#include "dimensions.hh" -#include "qlp.hh" -#include "unionfind.hh" -#include "idealspacing.hh" -#include "pointer.tcc" -#include "score-column.hh" -#include "paper-def.hh" -#include "column-x-positions.hh" -#include "main.hh" - -Vector -Spring_spacer::default_solution() const -{ - return try_initial_solution(); -} - -Score_column* -Spring_spacer::scol_l (int i) -{ - return dynamic_cast(cols_[i].pcol_l_); -} - -const Real COLFUDGE=1e-3; -template class P; // ugh. - -bool -Spring_spacer::contains_b (Paper_column const *w) -{ - for (int i=0; i< cols_.size(); i++) - if (cols_[i].pcol_l_ == w) - return true; - return false; -} - - -void -Spring_spacer::OK() const -{ -#ifndef NDEBUG - for (int i = 1; i < cols_.size(); i++) - assert (cols_[i].rank_i_ > cols_[i-1].rank_i_); -#endif -} - -/** - Make sure no unconnected columns happen. - */ -void -Spring_spacer::handle_loose_cols() -{ - Union_find connected (cols_.size()); - Array fixed; - - for (Cons *i = ideal_p_list_; i; i = i->next_) - { - connected.connect (i->car_->cols_drul_[LEFT],i->car_->cols_drul_[RIGHT]); - } - for (int i = 0; i < cols_.size(); i++) - if (cols_[i].fixed_b()) - fixed.push (i); - for (int i=1; i < fixed.size(); i++) - connected.connect (fixed[i-1], fixed[i]); - - /* - If columns do not have spacing information set, we need to supply our own. - */ - Real d = default_space_f_; - for (int i = cols_.size(); i--;) - { - if (! connected.equiv (fixed[0], i)) - { - connected.connect (i-1, i); - connect (i-1, i, d, 1.0); - } - } -} - -bool -Spring_spacer::check_constraints (Vector v) const -{ - int dim=v.dim(); - assert (dim == cols_.size()); - DOUT << "checking " << v; - for (int i=0; i < dim; i++) - { - if (cols_[i].fixed_b() && - abs (cols_[i].fixed_position() - v (i)) > COLFUDGE) - { - DOUT << "Fixpos broken\n"; - return false; - } - Array const &rods (cols_[i].rods_[RIGHT]); - for (int j =0; j < rods.size (); j++) - { - int other =rods[j].other_idx_; - Real diff =v (other) - v (i) ; - if (COLFUDGE +diff < rods[j].distance_f_) - { - DOUT << "i, other_i: " << i << " " << other << '\n'; - DOUT << "dist, minimal = " << diff << " " - << rods[j].distance_f_ << '\n'; - return false; - } - } - - } - return true; -} - -/** try to generate a solution which obeys the min - distances and fixed positions - */ -Vector -Spring_spacer::try_initial_solution() const -{ - Vector v; - if (!try_initial_solution_and_tell (v)) - { - warning (_ ("I'm too fat; call Oprah")); - } - return v; - -} - -bool -Spring_spacer::try_initial_solution_and_tell (Vector &v) const -{ - int dim=cols_.size(); - bool succeeded = true; - Vector initsol (dim); - - assert (cols_[0].fixed_b ()); - DOUT << "fixpos 0 " << cols_[0].fixed_position (); - for (int i=0; i < dim; i++) - { - Real min_x = i ? initsol (i-1) : cols_[0].fixed_position (); - Array const &sr_arr(cols_[i].rods_[LEFT]); - for (int j=0; j < sr_arr.size (); j++) - { - min_x = min_x >? (initsol (sr_arr[j].other_idx_) + sr_arr[j].distance_f_); - } - initsol (i) = min_x; - - if (cols_[i].fixed_b()) - { - initsol (i)=cols_[i].fixed_position(); - if (initsol (i) < min_x ) - { - DOUT << "failing: init, min : " << initsol (i) << " " << min_x << '\n'; - initsol (i) = min_x; - succeeded = false; - } - } - } - v = initsol; - - DOUT << "tried and told solution: " << v; - if (!succeeded) - DOUT << "(failed)\n"; - return succeeded; -} - - - -// generate the matrices -void -Spring_spacer::make_matrices (Matrix &quad, Vector &lin, Real &c) const -{ - quad.fill (0); - lin.fill (0); - c = 0; - - for (Cons *p =ideal_p_list_; p; p = p->next_) - { - Idealspacing *i = p->car_; - int l = i->cols_drul_[LEFT]; - int r = i->cols_drul_[RIGHT]; - - quad (r,r) += i->hooke_f_; - quad (r,l) -= i->hooke_f_; - quad (l,r) -= i->hooke_f_; - quad (l,l) += i->hooke_f_; - - lin (r) -= i->space_f_*i->hooke_f_; - lin (l) += i->space_f_*i->hooke_f_; - - c += sqr (i->space_f_); - } - - if (quad.dim() > 10) - quad.set_band(); - - -} - -void -Spring_spacer::set_fixed_cols (Mixed_qp &qp) const -{ - for (int j=0; j < cols_.size(); j++) - if (cols_[j].fixed_b()) - qp.add_fixed_var (j,cols_[j].fixed_position()); -} - -// put the constraints into the LP problem -void -Spring_spacer::make_constraints (Mixed_qp& lp) const -{ - int dim=cols_.size(); - - for (int j=0; j < dim -1; j++) - { - Array const&rod_arr (cols_[j].rods_[RIGHT]); - for (int i = 0; i < rod_arr.size (); i++) - { - Vector c1(dim); - c1(rod_arr[i].other_idx_)=1.0 ; - c1(j)=-1.0 ; - - lp.add_inequality_cons (c1, rod_arr[i].distance_f_); - } - } -} - - -Real -Spring_spacer::calculate_energy_f (Vector solution) const -{ - Real e = 0.0; - for (Cons*p =ideal_p_list_; p; p = p->next_) - { - Idealspacing * i = p->car_; - e += i->energy_f(solution(i->cols_drul_[RIGHT]) - solution(i->cols_drul_[LEFT])); - } - - return e; -} -void -Spring_spacer::lower_bound_solution (Column_x_positions*positions) const -{ - Mixed_qp lp (cols_.size()); - make_matrices (lp.quad_,lp.lin_, lp.const_term_); - set_fixed_cols (lp); - - Vector start (cols_.size()); - start.fill (0.0); - Vector solution_vec (lp.solve (start)); - for (int i=0; i < solution_vec.dim (); i++) - solution_vec(i) += indent_f_; - - DOUT << "Lower bound sol: " << solution_vec; - positions->energy_f_ = calculate_energy_f (solution_vec); - positions->config_ = solution_vec; - positions->satisfies_constraints_b_ = check_constraints (solution_vec); -} - -Spring_spacer::Spring_spacer () -{ - ideal_p_list_ =0; - energy_normalisation_f_ = 1.0; -} - -void -Spring_spacer::solve (Column_x_positions*positions) const -{ - Vector solution_try; - - bool constraint_satisfaction = try_initial_solution_and_tell (solution_try); - if (constraint_satisfaction) - { - Mixed_qp lp (cols_.size()); - make_matrices (lp.quad_,lp.lin_, lp.const_term_); - make_constraints (lp); - set_fixed_cols (lp); - - - Vector solution_vec (lp.solve (solution_try)); - for (int i=0; i < solution_vec.dim (); i++) - solution_vec(i) += indent_f_; - - - positions->satisfies_constraints_b_ = check_constraints (solution_vec); - if (!positions->satisfies_constraints_b_) - { - warning (_("Solution doesn't satisfy constraints")); - } - - positions->energy_f_ = calculate_energy_f (solution_vec); - positions->config_ = solution_vec; - } - else - { - positions->set_stupid_solution (solution_try); - } - -} - -/** - add one column to the problem. - - TODO: ugh merge with add_columns. -*/ -void -Spring_spacer::add_column (Paper_column *col, bool fixed, Real fixpos) -{ - Column_info c (col,(fixed)? &fixpos : 0); - int this_rank = cols_.size(); - c.rank_i_ = this_rank; - - for (int i=0; i < col->minimal_dists_arr_drul_[LEFT].size (); i++) - { - Column_rod &cr = col->minimal_dists_arr_drul_[LEFT][i]; - int left_idx = cr.other_l_->rank_i () - cols_[0].pcol_l_->rank_i (); - if (left_idx < 0) - continue; - - if (cols_[left_idx].pcol_l_ != cr.other_l_) - continue; - - Spacer_rod l_rod; - l_rod.distance_f_ = cr.distance_f_; - l_rod.other_idx_ = left_idx; - c.rods_[LEFT].push (l_rod); - - Spacer_rod r_rod; - r_rod.distance_f_ = cr.distance_f_; - r_rod.other_idx_ = this_rank; - cols_[left_idx].rods_[RIGHT].push (r_rod); - } - - for (int i=0; i < col->spring_arr_drul_[LEFT].size (); i++) - { - Column_spring &cr = col->spring_arr_drul_[LEFT][i]; - int idx = cr.other_l_->rank_i () - cols_[0].pcol_l_->rank_i (); - if (idx < 0) - continue; - - if (cols_[idx].pcol_l_ != cr.other_l_) - continue; - connect (idx, this_rank, cr.distance_f_, cr.strength_f_); - } - - cols_.push (c); -} - - -void -Spring_spacer::add_columns (Link_array cols) -{ - energy_normalisation_f_ = sqr (line_len_f_); - add_column (cols[0], true, 0.0); - for (int i=1; i< cols.size ()-1; i++) - add_column (cols[i],false,0.0); - - if (line_len_f_ > 0) - add_column (cols.top (), true, line_len_f_); - else - add_column (cols.top (), false, 0); -} - - - -void -Spring_spacer::print() const -{ -#ifndef NPRINT - for (int i=0; i < cols_.size(); i++) - { - DOUT << "col " << i << " "; - cols_[i].print(); - } - - for (Cons *p =ideal_p_list_; p; p = p->next_) - { - p->car_->print(); - } -#endif -} - - -void -Spring_spacer::connect (int i, int j, Real d, Real h) -{ - if (d > 100 CM) - { - programming_error( _f ("Improbable distance: %f point, setting to 10 mm", d)); - d = 1 CM; - } - if(d < 0) - { - programming_error (_ ("Negative distance, setting to 10 mm")); - d = 10 MM; - } - - assert(h >=0); - - Idealspacing * s = new Idealspacing; - - s->cols_drul_[LEFT] = i ; - s->cols_drul_[RIGHT] = j; - s->space_f_ = d; - s->hooke_f_ = h; - - ideal_p_list_ = new Killing_cons (s, ideal_p_list_); -} - -void -Spring_spacer::prepare() -{ - handle_loose_cols(); - print(); -} - - -Spring_spacer::~Spring_spacer() -{ - delete ideal_p_list_; -} diff --git a/lily/staff-side.cc b/lily/staff-side.cc index b0cefd1e1b..bd4d062a98 100644 --- a/lily/staff-side.cc +++ b/lily/staff-side.cc @@ -72,6 +72,17 @@ Staff_side_element::position_self () to_position_l_->get_elt_property (transparent_scm_sym) != SCM_BOOL_F) return; + Axis other = Axis ((axis_ + 1) % NO_AXES); + if (parent_l (axis_)->empty_b (axis_) + &&parent_l (axis_)->empty_b (other)) // guh + { + warning (_("No support; erasing script")); + to_position_l_->set_empty (X_AXIS,Y_AXIS); + to_position_l_->set_elt_property (transparent_scm_sym, SCM_BOOL_T); + set_empty (X_AXIS, Y_AXIS); + return ; + } + Interval dim; Graphical_element *common = 0; if (support_l_arr_.size ()) @@ -102,8 +113,6 @@ Staff_side_element::position_self () : Interval(0,0); Real off = relative_coordinate (common, axis_); - - SCM pad = remove_elt_property (padding_scm_sym); if (pad != SCM_BOOL_F) diff --git a/lily/staff-symbol-referencer.cc b/lily/staff-symbol-referencer.cc index aad498bce3..813d8a8b17 100644 --- a/lily/staff-symbol-referencer.cc +++ b/lily/staff-symbol-referencer.cc @@ -52,9 +52,8 @@ Staff_symbol_referencer::staff_line_leading_f () const return (staff_sym_l_) ? staff_sym_l_->staff_line_leading_f_ : paper_l ()->get_realvar (interline_scm_sym); } - -int -Staff_symbol_referencer::position_i () const +Real +Staff_symbol_referencer::position_f () const { if (!staff_sym_l_ ) return 0; @@ -62,5 +61,5 @@ Staff_symbol_referencer::position_i () const Graphical_element * c = common_refpoint (staff_sym_l_, Y_AXIS); Real y = relative_coordinate (c, Y_AXIS) - staff_sym_l_->relative_coordinate (c, Y_AXIS); - return int (2.0 * y / staff_line_leading_f ()); + return 2.0 * y / staff_line_leading_f (); } diff --git a/lily/stem.cc b/lily/stem.cc index 15e9fa7ecc..f6f18abbbf 100644 --- a/lily/stem.cc +++ b/lily/stem.cc @@ -57,7 +57,7 @@ Stem::head_positions () const Interval_t r; for (int i =0; i < head_l_arr_.size (); i++) { - int p = head_l_arr_[i]->position_i (); + int p = (int)head_l_arr_[i]->position_f (); r[BIGGER] = r[BIGGER] >? p; r[SMALLER] = r[SMALLER] set_elt_property (extremal_scm_sym, SCM_BOOL_T); int parity=1; - int lastpos = beginhead->position_i (); + int lastpos = int (beginhead->position_f ()); for (int i=1; i < head_l_arr_.size (); i ++) { - int dy =abs (lastpos- head_l_arr_[i]->position_i ()); + int dy =abs (lastpos- (int)head_l_arr_[i]->position_f ()); if (dy <= 1) { @@ -242,7 +242,7 @@ Stem::set_noteheads () } else parity = 1; - lastpos = head_l_arr_[i]->position_i (); + lastpos = int (head_l_arr_[i]->position_f ()); } } diff --git a/lily/tie.cc b/lily/tie.cc index eeaf89fa98..bdc3089f64 100644 --- a/lily/tie.cc +++ b/lily/tie.cc @@ -37,8 +37,8 @@ Tie::Tie() Direction Tie::get_default_dir () const { - int m = (head_l_drul_[LEFT]->position_i () - + head_l_drul_[RIGHT]->position_i ()) /2; + int m = int (head_l_drul_[LEFT]->position_f () + + head_l_drul_[RIGHT]->position_f ()) /2; /* If dir is not determined: inverse of stem: down @@ -151,11 +151,12 @@ Tie::do_post_processing() for smal slurs */ - int ypos_i = head_l_drul_[LEFT] ? head_l_drul_[LEFT]->position_i () - : head_l_drul_[RIGHT]->position_i (); - - Real y_f = internote_f * ypos_i; + Real ypos = head_l_drul_[LEFT] ? head_l_drul_[LEFT]->position_f () + : head_l_drul_[RIGHT]->position_f (); + Real y_f = internote_f * ypos; + int ypos_i = int (ypos); + Real dx_f = extent (X_AXIS).length () + dx_f_drul_[RIGHT] - dx_f_drul_[LEFT]; if (dx_f < paper_l ()->get_var ("tie_staffspace_length")) { diff --git a/lily/volta-spanner.cc b/lily/volta-spanner.cc index a227d07d7c..5ebadf0d08 100644 --- a/lily/volta-spanner.cc +++ b/lily/volta-spanner.cc @@ -87,10 +87,16 @@ Interval Volta_spanner::do_height () const { /* - in most cases, it's a lot better not no have height... + Originally the following comment existed here + "in most cases, it's a lot better not no have height...", + but problems existed with collision between volta spanner + and above staff or lyrics for multi-staff music, so the proper + height is now being returned. Additional space should still + be added elsewhere so lyrics from above staff do not sit on + volta spanner. (Roy R. Rankin) */ - Interval i; - return i; + Real h = paper_l()->get_var ("volta_spanner_height") * 2.; + return Interval (0., h); } void diff --git a/lily/word-wrap.cc b/lily/word-wrap.cc index 7091b65980..cf6a95e9fe 100644 --- a/lily/word-wrap.cc +++ b/lily/word-wrap.cc @@ -11,7 +11,7 @@ #include "paper-score.hh" #include "debug.hh" #include "paper-column.hh" -#include "spring-spacer.hh" +#include "line-spacer.hh" /** El stupido. Add a measure until we're past the optimum. diff --git a/make/out/lilypond.lsm b/make/out/lilypond.lsm index c60cc02d01..c1752e04d1 100644 --- a/make/out/lilypond.lsm +++ b/make/out/lilypond.lsm @@ -1,7 +1,7 @@ Begin3 Title: LilyPond -Version: 1.2.9 -Entered-date: 20SEP99 +Version: 1.2.10 +Entered-date: 22SEP99 Description: LilyPond is a music typesetter. It produces beautiful sheet music using a high level description file as input. LilyPond is part of @@ -11,8 +11,8 @@ Author: hanwen@cs.uu.nl (Han-Wen Nienhuys) janneke@gnu.org (Jan Nieuwenhuizen) Maintained-by: hanwen@stack.nl (Han-Wen Nienhuys) Primary-site: sunsite.unc.edu /pub/Linux/apps/sound/convert - 1000k lilypond-1.2.9.tar.gz + 1000k lilypond-1.2.10.tar.gz Original-site: ftp.cs.uu.nl /pub/GNU/LilyPond/development/ - 1000k lilypond-1.2.9.tar.gz + 1000k lilypond-1.2.10.tar.gz Copying-policy: GPL End diff --git a/make/out/lilypond.spec b/make/out/lilypond.spec index 2f2d909550..d1b5af05b9 100644 --- a/make/out/lilypond.spec +++ b/make/out/lilypond.spec @@ -1,9 +1,9 @@ Name: lilypond -Version: 1.2.9 +Version: 1.2.10 Release: 1 Copyright: GPL Group: Applications/Publishing -Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.2.9.tar.gz +Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.2.10.tar.gz Summary: A program for printing sheet music. URL: http://www.cs.uu.nl/~hanwen/lilypond Packager: Han-Wen Nienhuys diff --git a/midi2ly/mudela-staff.cc b/midi2ly/mudela-staff.cc index edba0e1bc4..6440d180b9 100644 --- a/midi2ly/mudela-staff.cc +++ b/midi2ly/mudela-staff.cc @@ -72,22 +72,26 @@ Mudela_staff::eat_voice (Cons_list& items) for (Cons *cp = i; cp && cp->car_->at_mom () == mom; cp = cp->next_) now_items.push (i->car_); - Mudela_item * which = 0; Mudela_note * last_note = dynamic_cast (voice_p->last_item_l_); + Link_array candidates; - for (int i=0; !which && last_note && i < now_items.size (); i++) + for (int i=0; last_note && i < now_items.size (); i++) { Mudela_note * now_note = dynamic_cast (now_items[i]); if (now_note && last_note->channel_i_ != now_note->channel_i_) - which = now_note; + candidates.push (now_note); + } + + if (candidates.size()) + { + now_items = candidates; } -#if 0 - // use pitch difference for determining which item to pick. - if (!which) + Mudela_item * which = 0; + if (now_items.size () > 1) { int mindiff = 100000; // ugh - for (int i=0; !which && last_note && i < now_items.size (); i++) + for (int i=0; last_note && i < now_items.size (); i++) { Mudela_note *nt = dynamic_cast (now_items[i]); if (!nt) @@ -104,28 +108,25 @@ Mudela_staff::eat_voice (Cons_list& items) { which =0; } - } -#endif - - if (!which && now_items.size ()) + else if (now_items.size () == 1) which = now_items[0]; - - - if (!which) + if (which) + { + while ((*pp)->car_ != which) + pp = &(*pp)->next_; + + mom += (*pp)->car_->duration_mom (); + Cons* c = items.remove_cons (pp); + voice_p->add_item (c->car_); + delete c; + } + else { pp = &(*pp)->next_; continue; } - - while ((*pp)->car_ != which) - pp = &(*pp)->next_; - - mom += (*pp)->car_->duration_mom (); - Cons* c = items.remove_cons (pp); - voice_p->add_item (c->car_); - delete c; } } diff --git a/scripts/abc2ly.py b/scripts/abc2ly.py index 7b075e727e..2fb57404e6 100644 --- a/scripts/abc2ly.py +++ b/scripts/abc2ly.py @@ -7,13 +7,45 @@ # (not finished.) # ABC standard v1.6: http://www.gre.ac.uk/~c.walshaw/abc2mtex/abc.txt # - - +# Enhancements (Roy R. Rankin) +# +# Header section moved to top of lilypond file +# handle treble, treble-8, alto, and bass clef +# Handle voices (V: headers) with clef and part names, multiple voices +# Handle w: lyrics with multiple verses +# Handle key mode names for minor, major, phrygian, ionian, locrian, aeolian, +# mixolydian, lydian, dorian +# Handle part names from V: header +# Tuplets handling fixed up +# Lines starting with |: not discarded as header lines +# Multiple T: and C: header entries handled +# Accidental maintained until next bar check +# Silent rests supported +# articulations fermata, upbow, downbow, ltoe, accent, tenuto supported +# Chord strings([-^]"string") can contain a '#' +# Header fields enclosed by [] in notes string processed +# W: words output after tune as abc2ps does it (they failed before) +# +# Limitations +# +# Multiple tunes in single file not supported +# Blank T: header lines should write score and open a new score +# Not all header fields supported +# Beaming not preserved between ABC and lilypond +# ABC line breaks are ignored +# Block comments generate error and are ignored +# Postscript commands are ignored +# lyrics not resynchronized by line breaks (lyrics must fully match notes) +# ??? + + + + program_name = 'abc2ly' version = '@TOPLEVEL_VERSION@' if version == '@' + 'TOPLEVEL_VERSION' + '@': - version = '1.2.6' # uGUHGUHGHGUGH - + version = '1.2.9' # uGUHGUHGHGUGH + import __main__ import getopt import sys @@ -22,65 +54,103 @@ import string import os - +UNDEF = 255 +state = UNDEF voice_idx_dict = {} header = {} lyrics = [] +slyrics = [] voices = [] +state_list = [] current_voice_idx = -1 current_lyric_idx = -1 - -def select_voice (name): - if not voice_idx_dict.has_key (name): - voices.append ('') - voice_idx_dict[name] = len (voices) -1 - __main__.current_voice_idx = voice_idx_dict[name] - -# assert 0 -# current_voice_idx >= 0 - +lyric_idx = -1 +part_names = 0 default_len = 8 global_key = [0] * 7 # UGH names = ["One", "Two", "Three"] DIGITS='0123456789' HSPACE=' \t' -def gcd (a, b): - while a % b: - a,b = b, a % b - return b - -class Rational: - def __init__ (self, n, d = 1): - self.num = n - self.den = d - - def simplify (self): - g = gcd (self.num, self.den) - self.num = self.num / g - self.den = self.den /g - if self.den < 0: - self.den = - self.den - self.num = - self.num - - def __sub__ (self, other): - pass +def check_clef(s): + if not s: + return '' + if re.match('^treble', s): + s = s[6:] + if re.match ('^-8', s): + s = s[2:] + state.base_octave = -2 + voices_append("\\clef \"G_8\";\n") + else: + state.base_octave = 0 + voices_append("\\clef treble;\n") + elif re.match('^alto', s): + s = s[4:] + state.base_octave = -1 + voices_append ("\\clef alto;\n" ) + elif re.match('^bass',s ): + s = s[4:] + state.base_octave = -2 + voices_append ("\\clef bass;\n" ) + return s + +def select_voice (name, rol): + if not voice_idx_dict.has_key (name): + state_list.append(Parser_state()) + voices.append ('') + slyrics.append ([]) + voice_idx_dict[name] = len (voices) -1 + __main__.current_voice_idx = voice_idx_dict[name] + __main__.state = state_list[current_voice_idx] + while rol != '': + m = re.match ('^([^ \t=]*)=(.*)$', rol) # find keywork + if m: + keyword = m.group(1) + rol = m.group (2) + a = re.match ('^("[^"]*"|[^ \t]*) *(.*)$', rol) + if a: + value = a.group (1) + rol = a.group ( 2) + if keyword == 'clef': + check_clef(value) + elif keyword == "name": + value = re.sub ('\\\\','\\\\\\\\', value) + voices_append ("\\property Staff.instrument = %s\n" % value ) + __main__.part_names = 1 + elif keyword == "sname" or keyword == "snm": + voices_append ("\\property Staff.instr = %s\n" % value ) + + else: + break + + return def dump_header (outf,hdr): - outf.write ('\\header {') + outf.write ('\\header {\n') ks = hdr.keys () ks.sort () for k in ks: - outf.write ('\n%s = "%s";\n'% (k,hdr[k])) + outf.write ('\t%s = "%s";\n'% (k,hdr[k])) outf.write ('}') def dump_lyrics (outf): - for i in range (len (lyrics)): - outf.write ("\nverse%s = \\lyrics {" % names [i]) - outf.write ("\n" + lyrics [i]) - outf.write ("\n}") + if (len(lyrics)): + outf.write("\n\\score\n{\n \\context Lyrics\n <\n") + for i in range (len (lyrics)): + outf.write ( lyrics [i]) + outf.write ("\n") + outf.write(" >\n \\paper{}\n}\n") + +def dump_slyrics (outf): + ks = voice_idx_dict.keys() + ks.sort () + for k in ks: + for i in range (len(slyrics[voice_idx_dict[k]])): + outf.write ("\nwords%sV%d = \\lyrics {" % (k, i)) + outf.write ("\n" + slyrics [voice_idx_dict[k]][i]) + outf.write ("\n}") def dump_voices (outf): ks = voice_idx_dict.keys() @@ -98,19 +168,30 @@ def dump_score (outf): ks = voice_idx_dict.keys (); ks.sort () for k in ks: - outf.write ("\n \\context Staff=\"%s\" \\$voice%s " % (k,k))# ugh - for i in range (len (lyrics)): - j = i - if j >= len (voices): - j = len (voices) - 1 - outf.write ("\n \\context Lyrics=\"%s\" \\addlyrics \\$voice%s \\$verse%s " % - (names [i], names [j], names [i])) + if k == 'default' and len (voice_idx_dict) > 1: + break + if len ( slyrics [voice_idx_dict[k]] ): + outf.write ("\n \\addlyrics") + outf.write ("\n\t\\context Staff=\"%s\"\n\t{\n" %k ) + if k != 'default': + outf.write ("\t \\$voicedefault\n") + outf.write ("\t \\$voice%s " % k) + outf.write ("\n\t}\n") + if len ( slyrics [voice_idx_dict[k]] ): + outf.write ("\n\t\\context Lyrics=\"%s\" \n\t<\t" % k) + for i in range (len(slyrics[voice_idx_dict[k]])): + outf.write("\n\t { \\$words%sV%d }" % ( k, i) ) + outf.write ( "\n\t>\n" ) outf.write ("\n >") - dump_header (outf ,header) - outf.write (r""" -\paper {} -\midi {} -}""") + outf.write ("\n\t\\paper {\n") + if part_names: + outf.write ("\t \\translator \n\t {\n") + outf.write ("\t\t\\StaffContext\n") + outf.write ("\t\t\\consists Staff_margin_engraver;\n") + outf.write ("\t }\n") + outf.write ("\t}\n\t\\midi {}\n}\n") + + def set_default_length (s): m = re.search ('1/([0-9]+)', s) @@ -123,9 +204,9 @@ def set_default_len_from_time_sig (s): n = string.atoi (m.group (1)) d = string.atoi (m.group (2)) if (n * 1.0 )/(d * 1.0) < 0.75: - default_len = 16 + __main__.default_len = 16 else: - default_len = 8 + __main__.default_len = 8 def gulp_file(f): try: @@ -201,7 +282,64 @@ def quart_above_pitch (tup): return (n,a) +key_lookup = { # abc to lilypond key mode names + 'm' : 'minor', + 'min' : 'minor', + 'maj' : 'major', + 'phr' : 'phrygian', + 'ion' : 'ionian', + 'loc' : 'locrian', + 'aeo' : 'aeolian', + 'mix' : 'mixolydian', + 'lyd' : 'lydian', + 'dor' : 'dorian' +} +def lily_key (k): + k = string.lower (k) + key = k[0] + k = k[1:] + if k and k[0] == '#': + key = key + 'is' + k = k[1:] + elif k and k[0] == 'b': + key = key + 'es' + k = k[1:] + if not k: + return(key) + + type = k[0:3] + if key_lookup.has_key(type): + return("%s \\%s" % ( key, key_lookup[type])) + sys.stderr.write("Unknown key type %s ignored\n" % type) + return key + +def shift_key (note, acc , shift): + s = semitone_pitch((note, acc)) + s = (s + shift + 12) % 12 + if s <= 4: + n = s / 2 + a = s % 2 + else: + n = (s + 1) / 2 + a = (s + 1) % 2 + if a: + n = n + 1 + a = -1 + return (n,a) + +key_shift = { # semitone shifts for key mode names + 'm' : 3, + 'min' : 3, + 'maj' : 0, + 'phr' : -4, + 'ion' : 0, + 'loc' : 1, + 'aeo' : 3, + 'mix' : 5, + 'lyd' : -5, + 'dor' : -2 +} def compute_key (k): k = string.lower (k) intkey = (ord (k[0]) - ord('a') + 5) % 7 @@ -214,7 +352,9 @@ def compute_key (k): elif k and k[0] == '#': intkeyacc = 1 k = k[1:] - + k = k[0:3] + if k and key_shift.has_key(k): + (intkey, intkeyacc) = shift_key(intkey, intkeyacc, key_shift[k]) keytup = (intkey, intkeyacc) sharp_key_seq = sharp_keys () @@ -237,7 +377,6 @@ def compute_key (k): key_table = [0] * 7 for a in accseq: key_table[a] = key_table[a] + accsign - return key_table @@ -253,10 +392,10 @@ tup_lookup = { def try_parse_tuplet_begin (str, state): - if re.match ('\([0-9]', str): + if re.match ('\([2-9]', str): dig = str[1] str = str[2:] - state.parsing_tuplet = 1 + state.parsing_tuplet = string.atoi (dig[0]) voices_append ("\\times %s {" % tup_lookup[dig]) return str @@ -264,9 +403,6 @@ def try_parse_tuplet_begin (str, state): def try_parse_group_end (str, state): if str and str[0] in HSPACE: str = str[1:] - if state.parsing_tuplet: - state.parsing_tuplet = 0 - voices_append ("}") return str def header_append (key, a): @@ -275,89 +411,159 @@ def header_append (key, a): s = header[key] + "\n" header [key] = s + a -def stuff_append (stuff, idx, a): - if not stuff: - stuff.append ('') - - v = stuff[idx] - - #wordwrap +def wordwrap(a, v): linelen = len (v) - string.rfind(v, '\n') if linelen + len (a) > 80: v = v + '\n' - v = v + a + ' ' - stuff [idx] = v + return v + a + ' ' + +def stuff_append (stuff, idx, a): + if not stuff: + stuff.append (a) + else: + stuff [idx] = wordwrap(a, stuff[idx]) def voices_append(a): if current_voice_idx < 0: - select_voice ('default') + select_voice ('default', '') stuff_append (voices, current_voice_idx, a) def lyrics_append(a): + a = re.sub ( '#', '\\#', a) # latex does not like naked #'s + a = re.sub ( '"', '\\"', a) # latex does not like naked "'s + a = '\t{ \\lyrics "' + a + '" }\n' stuff_append (lyrics, current_lyric_idx, a) +# break lyrics to words and put "'s around words containing numbers and '"'s +def fix_lyric(str): + ret = '' + + while str != '': + m = re.match('[ \t]*([^ \t]*)[ \t]*(.*$)', str) + if m: + word = m.group(1) + str = m.group(2) + word = re.sub('"', '\\"', word) # escape " + if re.match('.*[0-9"]', word): + word = re.sub('_', ' ', word) # _ causes probs inside "" + ret = ret + '\"' + word + '\" ' + else: + ret = ret + word + ' ' + else: + return (ret) + return (ret) + +def slyrics_append(a): + a = re.sub ( '_', ' _ ', a) # _ to ' _ ' + a = re.sub ( '-', '- ', a) # split words with - + a = re.sub ( '\\\\- ', '-', a) # unless \- + a = re.sub ( '~', '_', a) # ~ to space('_') + a = re.sub ( '\*', '_ ', a) # * to to space + a = re.sub ( '#', '\\#', a) # latex does not like naked #'s + if re.match('.*[0-9"]', a): # put numbers and " into quoted string + a = fix_lyric(a) + a = re.sub ( '$', ' ', a) # insure space between lines + __main__.lyric_idx = lyric_idx + 1 + if len(slyrics[current_voice_idx]) <= lyric_idx: + slyrics[current_voice_idx].append(a) + else: + v = slyrics[current_voice_idx][lyric_idx] + slyrics[current_voice_idx][lyric_idx] = wordwrap(a, slyrics[current_voice_idx][lyric_idx]) + -def try_parse_header_line (ln): - m = re.match ('^(.): *(.*)$', ln) +def try_parse_header_line (ln, state): + m = re.match ('^([A-Za-z]): *(.*)$', ln) if m: g =m.group (1) a = m.group (2) - a = re.sub ('"', '\\"', a) - if g == 'T': - header['title'] = a - if g == 'M': + if g == 'T': #title + a = re.sub('[ \t]*$','', a) #strip trailing blanks + if header.has_key('title'): + if a: + header['title'] = header['title'] + '\\\\\\\\' + a + else: + header['title'] = a + if g == 'M': # Meter if a == 'C': + if not state.common_time: + state.common_time = 1 + voices_append ("\\property Staff.timeSignatureStyle=\"C\"\n") a = '4/4' + if a == 'C|': + if not state.common_time: + state.common_time = 1 + voices_append ("\\property Staff.timeSignatureStyle=\"C\"\n") + a = '2/2' # global_voice_stuff.append ('\\time %s;' % a) set_default_len_from_time_sig (a) voices_append ('\\time %s;' % a) - if g == 'K': - __main__.global_key =compute_key (a)# ugh. - voices_append ('\\key %s;' % a) - - if g == 'O': + state.next_bar = '' + if g == 'K': # KEY + a = check_clef(a) + if a: + __main__.global_key =compute_key (a)# ugh. + m = re.match ('^([^ \t]*) *(.*)$', a) # seperate clef info + if m: + voices_append ('\\key %s;' % lily_key(m.group(1))) + check_clef(m.group(2)) + else: + voices_append ('\\key %s;' % lily_key(a)) + if g == 'O': # Origin header ['origin'] = a - if g == 'X': + if g == 'X': # Reference Number header ['crossRefNumber'] = a - if g == 'A': + if g == 'A': # Area header ['area'] = a - if g == 'H': + if g == 'H': # History header_append ('history', a) - if g == 'B': + if g == 'B': # Book header ['book'] = a - if g == 'C': - header ['composer'] = a + if g == 'C': # Composer + if header.has_key('composer'): + if a: + header['composer'] = header['composer'] + '\\\\\\\\' + a + else: + header['composer'] = a if g == 'S': header ['subtitle'] = a - if g == 'L': + if g == 'L': # Default note length set_default_length (ln) - if g == 'V': - a = re.sub (' .*$', '', a) - select_voice (a) - if g == 'W': - if not len (a): - lyrics.append ('') - else: - lyrics_append (a); + if g == 'V': # Voice + voice = re.sub (' .*$', '', a) + rest = re.sub ('^[^ \t]* *', '', a) + if state.next_bar: + voices_append(state.next_bar) + state.next_bar = '' + select_voice (voice, rest) + if g == 'W': # Words + lyrics_append(a); + if g == 'w': # vocals + slyrics_append (a); return '' return ln -def pitch_to_mudela_name (name, acc): +# we use in this order specified accidental, active accidental for bar, +# active accidental for key +def pitch_to_mudela_name (name, acc, bar_acc, key): s = '' - if acc < 0: + if acc == UNDEF: + acc = bar_acc + if acc == UNDEF: + acc = key + if acc == -1: s = 'es' - acc = -acc - elif acc > 0: - s = 'is' - + elif acc == 1: + s = 'is' + if name > 4: name = name -7 - return chr (name + ord('c')) + s * acc + return(chr (name + ord('c')) + s) + def octave_to_mudela_quotes (o): o = o + 2 @@ -394,10 +600,15 @@ def duration_to_mudela_duration (multiply_tup, defaultlen, dots): class Parser_state: def __init__ (self): + self.in_acc = {} self.next_articulation = '' + self.next_bar = '' self.next_dots = 0 self.next_den = 1 self.parsing_tuplet = 0 + self.plus_chord = 0 + self.base_octave = 0 + self.common_time = 0 @@ -424,19 +635,18 @@ def parse_duration (str, parser_state): current_dots = parser_state.next_dots parser_state.next_dots = 0 - - while str[0] == ' ': - str = str [1:] - - while str[0] == '>': - str = str [1:] - current_dots = current_dots + 1; - parser_state.next_den = parser_state.next_den * 2 - - while str[0] == '<': - str = str [1:] - den = den * 2 - parser_state.next_dots = parser_state.next_dots + 1 + if re.match ('[ \t]*[<>]', str): + while str[0] in HSPACE: + str = str[1:] + while str[0] == '>': + str = str [1:] + current_dots = current_dots + 1; + parser_state.next_den = parser_state.next_den * 2 + + while str[0] == '<': + str = str [1:] + den = den * 2 + parser_state.next_dots = parser_state.next_dots + 1 @@ -453,30 +663,54 @@ def parse_duration (str, parser_state): def try_parse_rest (str, parser_state): - if not str or str[0] <> 'z': + if not str or str[0] <> 'z' and str[0] <> 'x': return str + __main__.lyric_idx = -1 + + if parser_state.next_bar: + voices_append(parser_state.next_bar) + parser_state.next_bar = '' + + if str[0] == 'z': + rest = 'r' + else: + rest = 's' str = str[1:] (str, num,den,d) = parse_duration (str, parser_state) - voices_append ('r%s' % duration_to_mudela_duration ((num,den), default_len, d)) + voices_append ('%s%s' % (rest, duration_to_mudela_duration ((num,den), default_len, d))) + if parser_state.next_articulation: + voices_append (parser_state.next_articulation) + parser_state.next_articulation = '' return str +artic_tbl = { + '.' : '-.', + 'T' : '^\\trill', + 'H' : '^\\fermata', + 'u' : '^\\upbow', + 'K' : '^\\ltoe', + 'k' : '^\\accent', + 'M' : '^\\tenuto', + '~' : '^"~" ', + 'J' : '', # ignore slide + 'R' : '', # ignore roll + 'v' : '^\\downbow' +} + def try_parse_articulation (str, state): - if str[:1] =='.': - state.next_articulation = state.next_articulation + '-.' - str = str[1:] + while str and artic_tbl.has_key(str[:1]): + state.next_articulation = state.next_articulation + artic_tbl[str[:1]] + if not artic_tbl[str[:1]]: + sys.stderr.write("Warning: ignoring %s\n" % str[:1] ) - if str[:1] =='~': - state.next_articulation = state.next_articulation + '-\\trill' - str = str[1:] - - if str[:1] =='H': - state.next_articulation = state.next_articulation + '-\\fermata' str = str[1:] + + # s7m2 input doesnt care about spaces if re.match('[ \t]*\(', str): str = string.lstrip (str) @@ -489,6 +723,29 @@ def try_parse_articulation (str, state): return str +# +# remember accidental for rest of bar +# +def set_bar_acc(note, octave, acc, state): + if acc == UNDEF: + return + n_oct = note + octave * 7 + state.in_acc[n_oct] = acc + +# get accidental set in this bar or UNDEF if not set +def get_bar_acc(note, octave, state): + n_oct = note + octave * 7 + if state.in_acc.has_key(n_oct): + return(state.in_acc[n_oct]) + else: + return(UNDEF) + +def clear_bar_acc(state): + for k in state.in_acc.keys(): + del state.in_acc[k] + + + # WAT IS ABC EEN ONTZETTENDE PROGRAMMEERPOEP ! def try_parse_note (str, parser_state): mud = '' @@ -498,7 +755,7 @@ def try_parse_note (str, parser_state): return str articulation ='' - acc = 0 + acc = UNDEF if str[0] in '^=_': c = str[0] str = str[1:] @@ -509,10 +766,10 @@ def try_parse_note (str, parser_state): if c == '_': acc = -1 - octave = 0; + octave = parser_state.base_octave if str[0] in "ABCDEFG": str = string.lower (str[0]) + str[1:] - octave = -1 + octave = octave - 1 notename = 0 @@ -522,6 +779,13 @@ def try_parse_note (str, parser_state): else: return str # failed; not a note! + + __main__.lyric_idx = -1 + + if parser_state.next_bar: + voices_append(parser_state.next_bar) + parser_state.next_bar = '' + while str[0] == ',': octave = octave - 1 str = str[1:] @@ -543,15 +807,29 @@ def try_parse_note (str, parser_state): if slur_end: voices_append ('%s' % ')' *slur_end ) - voices_append ("%s%s%s" % - (pitch_to_mudela_name (notename, acc + global_key[notename]), - octave_to_mudela_quotes (octave), + + bar_acc = get_bar_acc(notename, octave, parser_state) + pit = pitch_to_mudela_name(notename, acc, bar_acc, global_key[notename]) + oct = octave_to_mudela_quotes (octave) + if acc != UNDEF and (acc == global_key[notename] or acc == bar_acc): + mod='!' + else: + mod = '' + voices_append ("%s%s%s%s" % + (pit, oct, mod, duration_to_mudela_duration ((num,den), default_len, current_dots))) + + set_bar_acc(notename, octave, acc, parser_state) if parser_state.next_articulation: articulation = articulation + parser_state.next_articulation parser_state.next_articulation = '' voices_append (articulation) + + if parser_state.parsing_tuplet: + parser_state.parsing_tuplet = parser_state.parsing_tuplet - 1 + if not parser_state.parsing_tuplet: + voices_append ("}") if slur_begin: voices_append ('%s' % '(' * slur_begin ) @@ -575,8 +853,8 @@ def try_parse_guitar_chord (str, state): if str: str = str[1:] - - state.next_articulation = "-\"%s\"" % gc + gc = re.sub('#', '\\#', gc) # escape '#'s + state.next_articulation = ("-\"%s\"" % gc) + state.next_articulation return str def try_parse_escape (str): @@ -586,7 +864,6 @@ def try_parse_escape (str): str = str[1:] if str[:1] =='K': key_table = compute_key () - return str # @@ -627,14 +904,17 @@ def try_parse_bar (str,state): break if str[:1] == '|': - bs = '|\n' + state.next_bar = '|\n' str = str[1:] + clear_bar_acc(state) - if bs <> None: + if bs <> None or state.next_bar != '': if state.parsing_tuplet: state.parsing_tuplet =0 voices_append ('} ') + if bs <> None: + clear_bar_acc(state) voices_append (bs) return str @@ -645,11 +925,36 @@ def try_parse_tie (str): voices_append (' ~ ') return str -def try_parse_chord_delims (str): +def bracket_escape (str, state): + m = re.match ( '^([^\]]*)] *(.*)$', str) + if m: + cmd = m.group (1) + str = m.group (2) + try_parse_header_line (cmd, state) + return str + +def try_parse_chord_delims (str, state): if str[:1] =='[': str = str[1:] + if re.match('[A-Z]:', str): # bracket escape + return bracket_escape(str, state) + if state.next_bar: + voices_append(state.next_bar) + state.next_bar = '' voices_append ('<') + if str[:1] == '+': + str = str[1:] + if state.plus_chord: + voices_append ('>') + state.plus_chord = 0 + else: + if state.next_bar: + voices_append(state.next_bar) + state.next_bar = '' + voices_append ('<') + state.plus_chord = 1 + ch = '' if str[:1] ==']': str = str[1:] @@ -665,8 +970,11 @@ def try_parse_chord_delims (str): voices_append (ch) return str -def try_parse_grace_delims (str): +def try_parse_grace_delims (str, state): if str[:1] =='{': + if state.next_bar: + voices_append(state.next_bar) + state.next_bar = '' str = str[1:] voices_append ('\\grace { ') @@ -682,10 +990,11 @@ def parse_file (fn): f = open (fn) ls = f.readlines () - state = Parser_state () + select_voice('default', '') lineno = 0 sys.stderr.write ("Line ... ") sys.stderr.flush () + __main__.state = state_list[current_voice_idx] for ln in ls: lineno = lineno + 1 @@ -693,22 +1002,21 @@ def parse_file (fn): if not (lineno % happy_count): sys.stderr.write ('[%d]'% lineno) sys.stderr.flush () - if re.match ('^[\t ]*(%.*)?$', ln): - continue - m = re.match ('^(.*?)%(.*)$',ln) + m = re.match ('^([^%]*)%(.*)$',ln) # add comments to current voice if m: - voices_append ('%% %s\n' % m.group(2)) + if m.group(2): + voices_append ('%% %s\n' % m.group(2)) ln = m.group (1) orig_ln = ln - ln = try_parse_header_line (ln) + ln = try_parse_header_line (ln, state) # Try nibbling characters off until the line doesn't change. prev_ln = '' while ln != prev_ln: prev_ln = ln - ln = try_parse_chord_delims (ln) + ln = try_parse_chord_delims (ln, state) ln = try_parse_rest (ln, state) ln = try_parse_articulation (ln,state) ln = try_parse_note (ln, state) @@ -718,7 +1026,7 @@ def parse_file (fn): ln = try_parse_guitar_chord (ln, state) ln = try_parse_tuplet_begin (ln, state) ln = try_parse_group_end (ln, state) - ln = try_parse_grace_delims (ln) + ln = try_parse_grace_delims (ln, state) ln = junk_space (ln) if ln: @@ -784,8 +1092,10 @@ for f in files: outf = open (out_filename, 'w') # dump_global (outf) - dump_lyrics (outf) + dump_header (outf ,header) + dump_slyrics (outf) dump_voices (outf) dump_score (outf) + dump_lyrics (outf) sys.stderr.write ('\n') -- 2.39.5