X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fduration.cc;h=755679fd71cf2d84469e69062efd4b7dabd71be9;hb=5b4b0d6e9a197e8f9eb085b7c2ad78b8be3e5cfc;hp=cc44db4def30e2b34e4309be643ca6d4bbd79be5;hpb=c0270765c0df9cceda34a6584f7da324eed5fc2a;p=lilypond.git diff --git a/lily/duration.cc b/lily/duration.cc index cc44db4def..755679fd71 100644 --- a/lily/duration.cc +++ b/lily/duration.cc @@ -1,41 +1,87 @@ /* - duration.cc -- implement Duration, Plet, + duration.cc -- implement Duration source file of the LilyPond music typesetter - (c) 1997--2000 Jan Nieuwenhuizen - Han-Wen Nienhuys - + (c) 1997--2008 Jan Nieuwenhuizen + Han-Wen Nienhuys */ -#include - -#include "lily-proto.hh" -#include "string.hh" -#include "moment.hh" #include "duration.hh" -#include "ly-smobs.icc" +#include "misc.hh" +#include "lily-proto.hh" +#include "ly-smobs.icc" int Duration::compare (Duration const &left, Duration const &right) { - return Rational::compare (left.length_mom (), right.length_mom ()); + return Rational::compare (left.get_length (), right.get_length ()); } Duration::Duration () { - durlog_i_ = 0; - dots_i_ = 0; - factor_ = Moment (1,1); + durlog_ = 0; + dots_ = 0; + factor_ = Rational (1, 1); } -Duration::Duration (int l, int d) +Duration::Duration (int log, int d) { - durlog_i_ = l; - dots_i_ = d; - factor_ = Moment (1,1); + durlog_ = log; + dots_ = d; + factor_ = Rational (1, 1); +} + +Duration::Duration (Rational r, bool scale) +{ + factor_ = Rational (1, 1); + + if (r.num () == 0.0) + { + durlog_ = 0; + dots_ = 0; + } + else + { + /* we want to find the integer k for which 2q/p > 2^k >= q/p. + It's simple to check that k' = \floor \log q - \floor \log p + satisfies the left inequality and is within a factor of 2 of + satistying the right one. Therefore either k = k' or k = k'+1 */ + + int p = r.num (); + int q = r.den (); + int k = intlog2 (q) - intlog2 (p); + if ((p << k) < q) + k++; + + assert ((p << k) >= q && (p << (k-1)) < q); + + /* If we were to write out log (p/q) in base 2, then the position of the + first non-zero bit (ie. k in our notation) would be the durlog + and the number of consecutive 1s after that bit would be the number of + dots */ + p = (p << k) - q; + dots_ = 0; + while ((p *= 2) >= q) + { + p -= q; + dots_++; + } + + /* we only go up to 64th notes */ + if (k > 6) + { + durlog_ = 6; + dots_ = 0; + } + else + durlog_ = k; + + if (scale || k > 6) + factor_ = r / get_length (); + } } Duration @@ -47,120 +93,81 @@ Duration::compressed (Rational m) const } Rational -Duration::length_mom () const +Duration::get_length () const { - Rational mom (1 << abs (durlog_i_)); + Rational mom (1 << abs (durlog_)); - if (durlog_i_> 0) - mom = Moment (1)/mom; + if (durlog_ > 0) + mom = Rational (1) / mom; Rational delta = mom; - - for (int d = dots_i_; d; d--) + for (int i = 0; i < dots_; i++) { - delta /= Moment (2); + delta /= Rational (2); mom += delta; } return mom * factor_; } +string +Duration::to_string () const +{ + string s; + if (durlog_ < 0) + s = "log = " + ::to_string (durlog_); + else + s = ::to_string (1 << durlog_); -String -Duration::str () const -{ - String s = to_str (durlog_i_) + to_str ('.', dots_i_); - if (factor_ != Moment (1,1)) - { - s += "*" + factor_.str (); - } + s += ::to_string ('.', dots_); + if (factor_ != Moment (Rational (1, 1))) + s += "*" + factor_.to_string (); return s; } - -IMPLEMENT_TYPE_P(Duration, "duration?"); -IMPLEMENT_UNSMOB(Duration, duration); +IMPLEMENT_TYPE_P (Duration, "ly:duration?"); SCM -Duration::mark_smob (SCM ) +Duration::mark_smob (SCM) { return SCM_EOL; } -IMPLEMENT_SIMPLE_SMOBS(Duration); - - +IMPLEMENT_SIMPLE_SMOBS (Duration); int Duration::print_smob (SCM s, SCM port, scm_print_state *) { - Duration *r = (Duration *) gh_cdr (s); - + Duration *r = (Duration *) SCM_CELL_WORD_1 (s); + scm_puts ("#str().ch_C()), port); + scm_display (ly_string2scm (r->to_string ()), port); scm_puts (" >", port); - + return 1; } SCM -Duration::equal_p (SCM a , SCM b) +Duration::equal_p (SCM a, SCM b) { - Duration *p = (Duration *) gh_cdr (a); - Duration *q = (Duration *) gh_cdr (b); + Duration *p = (Duration *) SCM_CELL_WORD_1 (a); + Duration *q = (Duration *) SCM_CELL_WORD_1 (b); - bool eq = p->dots_i_ == q->dots_i_ - && p->durlog_i_ == q->durlog_i_ + bool eq = p->dots_ == q->dots_ + && p->durlog_ == q->durlog_ && p->factor_ == q->factor_; return eq ? SCM_BOOL_T : SCM_BOOL_F; } - -MAKE_SCHEME_CALLBACK(Duration, less_p, 2); -SCM -Duration::less_p (SCM p1, SCM p2) -{ - Duration *a = unsmob_duration (p1); - Duration *b = unsmob_duration (p2); - - if (compare(*a, *b) < 0 ) - return SCM_BOOL_T; - else - return SCM_BOOL_F; -} - - -static SCM -make_duration (SCM l, SCM d) -{ - Duration p( gh_scm2int (l), gh_scm2int (d)); - return p.smobbed_copy (); -} - -static void -add_funcs() -{ - scm_make_gsubr ("make-duration", 2, 0, 0, (Scheme_function_unknown)make_duration); -} - -ADD_SCM_INIT_FUNC(duration, add_funcs); - -SCM -Duration::smobbed_copy ()const -{ - Duration * p = new Duration (*this); - return p->smobbed_self (); -} int Duration::duration_log () const { - return durlog_i_; + return durlog_; } int Duration::dot_count () const { - return dots_i_; + return dots_; } -