Hi all,
I don't completely understand the way how Duration::Duration(Rational r,
bool scale) converts a rational number into a note and dots, but
it's clear that the Completion_heads issue with splitting up breve and
longa notes was caused by the way << behaves when given a negative
number as shift-amount. I've tested this and it works perfectly for me.
I'm a little unsure if this approach works when k gets so low that the
rightest non-zero bit is shifted out into the nirvana... But for this
moment I can't imagine cases where this could happen.
Nevertheless, please test and critizize!
Michael
>From 7dc5a8bdef5b04931856eb380939595d4efc3d7e Mon Sep 17 00:00:00 2001
From: root <r...@michael.home>
Date: Thu, 26 Feb 2009 11:01:15 +0100
Subject: [PATCH] This fixes an endless loop in duration.cc:67 when Duration::Duration(Rational r, bool scale) is called
with r.num() >= 2 * r.den(), f.e. the duration of a longa: r.num = 2, r.den = 1. If k < 0, the left-shifting-operator << returns zero instead of right-shifting bits. The fix introduces a new function shift_left() in misc.hh, which behaves different.
---
lily/duration.cc | 6 +++---
lily/include/misc.hh | 7 +++++++
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/lily/duration.cc b/lily/duration.cc
index af924bb..0b80b1c 100644
--- a/lily/duration.cc
+++ b/lily/duration.cc
@@ -53,16 +53,16 @@ Duration::Duration (Rational r, bool scale)
int p = r.num ();
int q = r.den ();
int k = intlog2 (q) - intlog2 (p);
- if ((p << k) < q)
+ if (shift_left(p, k) < q)
k++;
- assert ((p << k) >= q && (p << (k-1)) < q);
+ assert (shift_left(p, k) >= q && shift_left(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;
+ p = shift_left(p, k) - q;
dots_ = 0;
while ((p *= 2) >= q)
{
diff --git a/lily/include/misc.hh b/lily/include/misc.hh
index e33d836..4954895 100644
--- a/lily/include/misc.hh
+++ b/lily/include/misc.hh
@@ -28,6 +28,13 @@ sign (int i)
else return 0;
}
+inline int
+shift_left (int value, int shiftamount)
+{
+ if (shiftamount < 0) return (value >> abs(shiftamount));
+ else return (value << shiftamount);
+}
+
inline Real
linear_interpolate (Real x, Real x1, Real x2, Real y1, Real y2)
{
--
1.5.6
_______________________________________________
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel