compiling irrational time signatures with \scaleDurations

2023-10-18 Thread Adrian Kleinlosen via LilyPond user discussion
Hello to all,


for quite some time now I've been trying to solve a problem concerning the
output of LilyPond code - unfortunately in vain. Maybe someone can help me
here?


About the "back story": I have written two algorithms in Python. First one,
with which I generate time signatures and metronome markings. I use
"normal" as well as irrational time signatures (like 7/23 or 5/12) and
metronome markings with up to three decimal places. The second algorithm
then converts the lists of time signatures and metronome markings into
LilyPond code.


The values of the individual functions of the code (attched) are calculated
as follows:


\scaleDurations = (notated note value * 6) / (note value * (metronome
marking * 1000)). Notated note value is the note value that is notated for
irrational note values (for example, 12th notes are commonly notated as 8th
notes, etc.); note value is the actual note value (e.g., 12th notes); and
the metronome marking has up to three decimal places. For a 7/23 measure
with a metronome marking of eight note = 62.375, if 23rd notes are notated
as 16th notes, this gives (16*6) / (23*(62.375*1000)).


\time = \scaleDurations * time signature


Now the output of the code works fine - but always only up to a certain
point. After a certain measure the output simply stops. I'm not sure now if
the problem is with my code or with Frescobaldi after all. (I am using
LilyPond version 2.24.2 in Frescobaldi 3.3.0 on a macOS Ventura 13.4.1).


Attached now is the code for a total of 24 such bars (once as a LilyPond
file and once as a text file). (I know, minimal examples are better in
principle, but in this case it would not make sense, because the output
stops after a couple of bars). Frescobaldi outputs the code correctly up to
the first note of the 4th bar, nothing more. An error message is not
generated.


How is it with you? Does the output work correctly or does it also break
off somewhere? I have already asked the same question in the German
LilyPond forum. A LilyPond user pointed out to me that the code seems to
work only in version 2.20.0, but not in any other version.


Thanks a lot for any help!


Kind regards,

Adrian Kleinlosen
\version "2.24.2"

musicone = {

%%% MEASURE : 1 %%%
\scaleDurations 49/50 {
\time 98/400    
\set Staff.timeSignatureFraction = #'(2 . 8)
\set baseMoment = #(ly:make-moment 49/50)

\textMark \markup {\left-column {\line { \smaller \general-align #Y #DOWN \note 
{8} #1 " = 61.213 " } } }

% The music will later be put here. For now, use the \repeat unfold expression
\repeat unfold 2 { c'8*8/8 }
|
}

\once \set Staff.whichBar = "|"

%%% MEASURE : 2 %%%
\scaleDurations 2/3 {
\time 18/141    
\set Staff.timeSignatureFraction = #'(9 . 47)
\set baseMoment = #(ly:make-moment 2/3)

% The music will later be put here. For now, use the \repeat unfold expression
\repeat unfold 9 { c'32*32/47 }
|
}

\once \set Staff.whichBar = "|"

%%% MEASURE : 3 %%%
\scaleDurations 35/38 {
\time 70/304    
\set Staff.timeSignatureFraction = #'(2 . 8)
\set baseMoment = #(ly:make-moment 35/38)

\textMark \markup {\left-column {\line { \smaller \general-align #Y #DOWN \note 
{8} #1 " = 65.073 " } } }

% The music will later be put here. For now, use the \repeat unfold expression
\repeat unfold 2 { c'8*8/8 }
|
}

\once \set Staff.whichBar = "|"

%%% MEASURE : 4 %%%
\scaleDurations 37/33 {
\time 296/1683    
\set Staff.timeSignatureFraction = #'(8 . 51)
\set baseMoment = #(ly:make-moment 37/33)

\textMark \markup {\left-column {\line { \smaller \general-align #Y #DOWN \note 
{8} #1 " = 67.176 " } } }

% The music will later be put here. For now, use the \repeat unfold expression
\repeat unfold 8 { c'64*64/51 }
|
}

\once \set Staff.whichBar = "|"

%%% MEASURE : 5 %%%
\scaleDurations 25/42 {
\time 100/504    
\set Staff.timeSignatureFraction = #'(4 . 12)
\set baseMoment = #(ly:make-moment 25/42)

% The music will later be put here. For now, use the \repeat unfold expression
\repeat unfold 4 { c'8*8/12 }
|
}

\once \set Staff.whichBar = "|"

%%% MEASURE : 6 %%%
\scaleDurations 15/13 {
\time 30/104    
\set Staff.timeSignatureFraction = #'(2 . 8)
\set baseMoment = #(ly:make-moment 15/13)

\textMark \markup {\left-column {\line { \smaller \general-align #Y #DOWN \note 
{8} #1 " = 52.0 " } } }

% The music will later be put here. For now, use the \repeat unfold expression
\repeat unfold 2 { c'8*8/8 }
|
}

\once \set Staff.whichBar = "|"

%%% MEASURE : 7 %%%
\scaleDurations 15/13 {
\time 30/104    
\set Staff.timeSignatureFraction = #'(2 . 8)
\set baseMoment = #(ly:make-moment 15/13)

% The music will later be put here. For now, use the \repeat unfold expression
\repeat unfold 2 { c'8*8/8 }
|
}

\once \set Staff.wh

Re: compiling irrational time signatures with \scaleDurations

2023-10-18 Thread Jean Abou Samra
Hi,

Here is a more minimal example illustrating your problem:

```
\version "2.24.2"

{
  \scaleDurations 1/2 c'1
  \scaleDurations 1/3 d'1
  \scaleDurations 1/5 e'1
  \scaleDurations 1/7 f'1
  \scaleDurations 1/11 g'1
  \scaleDurations 1/13 a'1
  \scaleDurations 1/17 b'1
  \scaleDurations 1/19 c''1
  \scaleDurations 1/23 d''1
  \scaleDurations 1/29 e''1
  \scaleDurations 1/31 f''1
  \scaleDurations 1/37 g''1
}
```

The underlying issue here is that you use lots of "complicated"
multipliers, with high denominators. LilyPond needs to represent
each point in time in an exact way, which it does using fractions.
However, because the denominators you use are sufficiently large
and have sufficiently few common prime factors, the denominator of
the fraction needed to represent a moment in your score gets huge.
In my example above, the product of primes up to 37 has the order
of magnitude of ten thousand billions, or two at the power 43.
Programs often use a fixed number of digits to represent integers,
for efficiency reasons. At some point, the computations overflow the
number of digits that is being used, and everything goes wrong.

You might call it a bug, but I'd rather speak of a limitation.
All programs that are written in languages such as C++ (internally
used in LilyPond) exhibit overflow issues when you feed them with
such huge integers.

So, unfortunately, I don't have a workaround to suggest other than
to use fractions with smaller denominators.

Jean


signature.asc
Description: This is a digitally signed message part


Re: compiling irrational time signatures with \scaleDurations

2023-10-18 Thread Vaughan McAlley
On Thu, 19 Oct 2023, 03:49 Jean Abou Samra,  wrote:

> Hi,
>
> Here is a more minimal example illustrating your problem:
>
> \version "2.24.2"
>
> {
>   \scaleDurations 1/2 c'1
>   \scaleDurations 1/3 d'1
>   \scaleDurations 1/5 e'1
>   \scaleDurations 1/7 f'1
>   \scaleDurations 1/11 g'1
>   \scaleDurations 1/13 a'1
>   \scaleDurations 1/17 b'1
>   \scaleDurations 1/19 c''1
>   \scaleDurations 1/23 d''1
>   \scaleDurations 1/29 e''1
>   \scaleDurations 1/31 f''1
>   \scaleDurations 1/37 g''1
> }
>
> The underlying issue here is that you use lots of "complicated"
> multipliers, with high denominators. LilyPond needs to represent each point
> in time in an exact way, which it does using fractions. However, because
> the denominators you use are sufficiently large and have sufficiently few
> common prime factors, the denominator of the fraction needed to represent a
> moment in your score gets huge. In my example above, the product of primes
> up to 37 has the order of magnitude of ten thousand billions, or two at the
> power 43. Programs often use a fixed number of digits to represent
> integers, for efficiency reasons. At some point, the computations overflow
> the number of digits that is being used, and everything goes wrong.
>
> You might call it a bug, but I'd rather speak of a limitation. All
> programs that are written in languages such as C++ (internally used in
> LilyPond) exhibit overflow issues when you feed them with such huge
> integers.
>
> So, unfortunately, I don't have a workaround to suggest other than to use
> fractions with smaller denominators.
>
> Jean
>
Would a function that turns a fraction into whatever number/100 work?

\scaleDurations \ratio 1/29 % or 1 29

Cheers,
Vaughan