2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2010 Jan Nieuwenhuizen <janneke@gnu.org>
5 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 LilyPond is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 LilyPond is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
21 #include "duration.hh"
24 #include "lily-proto.hh"
26 #include "ly-smobs.icc"
29 Duration::compare (Duration
const &left
, Duration
const &right
)
31 return Rational::compare (left
.get_length (), right
.get_length ());
38 factor_
= Rational (1, 1);
41 Duration::Duration (int log
, int d
)
45 factor_
= Rational (1, 1);
48 Duration::Duration (Rational r
, bool scale
)
50 factor_
= Rational (1, 1);
59 /* we want to find the integer k for which 2q/p > 2^k >= q/p.
60 It's simple to check that k' = \floor \log q - \floor \log p
61 satisfies the left inequality and is within a factor of 2 of
62 satistying the right one. Therefore either k = k' or k = k'+1 */
66 int k
= intlog2 (q
) - intlog2 (p
);
67 if (shift_left(p
, k
) < q
)
70 assert (shift_left(p
, k
) >= q
&& shift_left(p
, (k
-1)) < q
);
72 /* If we were to write out log (p/q) in base 2, then the position of the
73 first non-zero bit (ie. k in our notation) would be the durlog
74 and the number of consecutive 1s after that bit would be the number of
76 p
= shift_left(p
, k
) - q
;
84 /* we only go up to 64th notes */
94 factor_
= r
/ get_length ();
99 Duration::compressed (Rational m
) const
107 Duration::get_length () const
109 Rational
mom (1 << abs (durlog_
));
112 mom
= Rational (1) / mom
;
114 Rational delta
= mom
;
115 for (int i
= 0; i
< dots_
; i
++)
117 delta
/= Rational (2);
121 return mom
* factor_
;
125 Duration::to_string () const
130 s
= "log = " + ::to_string (durlog_
);
132 s
= ::to_string (1 << durlog_
);
134 s
+= ::to_string ('.', dots_
);
135 if (factor_
!= Moment (Rational (1, 1)))
136 s
+= "*" + factor_
.to_string ();
140 IMPLEMENT_TYPE_P (Duration
, "ly:duration?");
143 Duration::mark_smob (SCM
)
148 IMPLEMENT_SIMPLE_SMOBS (Duration
);
150 Duration::print_smob (SCM s
, SCM port
, scm_print_state
*)
152 Duration
*r
= (Duration
*) SCM_CELL_WORD_1 (s
);
154 scm_puts ("#<Duration ", port
);
155 scm_display (ly_string2scm (r
->to_string ()), port
);
156 scm_puts (" >", port
);
162 Duration::equal_p (SCM a
, SCM b
)
164 Duration
*p
= (Duration
*) SCM_CELL_WORD_1 (a
);
165 Duration
*q
= (Duration
*) SCM_CELL_WORD_1 (b
);
167 bool eq
= p
->dots_
== q
->dots_
168 && p
->durlog_
== q
->durlog_
169 && p
->factor_
== q
->factor_
;
171 return eq
? SCM_BOOL_T
: SCM_BOOL_F
;
175 Duration::duration_log () const
181 Duration::dot_count () const