]> git.donarmstrong.com Git - lilypond.git/blob - scm/lily-library.scm
Doc-it: chapter 1 completed
[lilypond.git] / scm / lily-library.scm
1 ;;;; This file is part of LilyPond, the GNU music typesetter.
2 ;;;;
3 ;;;; Copyright (C) 1998--2012 Jan Nieuwenhuizen <janneke@gnu.org>
4 ;;;; Han-Wen Nienhuys <hanwen@xs4all.nl>
5 ;;;;
6 ;;;; LilyPond is free software: you can redistribute it and/or modify
7 ;;;; it under the terms of the GNU General Public License as published by
8 ;;;; the Free Software Foundation, either version 3 of the License, or
9 ;;;; (at your option) any later version.
10 ;;;;
11 ;;;; LilyPond is distributed in the hope that it will be useful,
12 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ;;;; GNU General Public License for more details.
15 ;;;;
16 ;;;; You should have received a copy of the GNU General Public License
17 ;;;; along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18
19 ;; for take, drop, take-while, list-index, and find-tail:
20 (use-modules (srfi srfi-1))
21
22 ;; for define-safe-public when byte-compiling using Guile V2
23 (use-modules (scm safe-utility-defs))
24
25 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
26 ;; constants.
27
28 (define-public X 0)
29 (define-public Y 1)
30 (define-safe-public START -1)
31 (define-safe-public STOP 1)
32 (define-public LEFT -1)
33 (define-public RIGHT 1)
34 (define-public UP 1)
35 (define-public DOWN -1)
36 (define-public CENTER 0)
37
38 (define-safe-public DOUBLE-FLAT-QTS -4)
39 (define-safe-public THREE-Q-FLAT-QTS -3)
40 (define-safe-public FLAT-QTS -2)
41 (define-safe-public SEMI-FLAT-QTS -1)
42 (define-safe-public NATURAL-QTS 0)
43 (define-safe-public SEMI-SHARP-QTS 1)
44 (define-safe-public SHARP-QTS 2)
45 (define-safe-public THREE-Q-SHARP-QTS 3)
46 (define-safe-public DOUBLE-SHARP-QTS 4)
47 (define-safe-public SEMI-TONE-QTS 2)
48
49 (define-safe-public DOUBLE-FLAT  -1)
50 (define-safe-public THREE-Q-FLAT -3/4)
51 (define-safe-public FLAT -1/2)
52 (define-safe-public SEMI-FLAT -1/4)
53 (define-safe-public NATURAL 0)
54 (define-safe-public SEMI-SHARP 1/4)
55 (define-safe-public SHARP 1/2)
56 (define-safe-public THREE-Q-SHARP 3/4)
57 (define-safe-public DOUBLE-SHARP 1)
58 (define-safe-public SEMI-TONE 1/2)
59
60 (define-safe-public INFINITY-INT 1000000)
61
62 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
63 ;; moments
64
65 (define-public ZERO-MOMENT (ly:make-moment 0 1))
66
67 (define-public (moment-min a b)
68   (if (ly:moment<? a b) a b))
69
70 (define-public (moment<=? a b)
71   (or (equal? a b)
72       (ly:moment<? a b)))
73
74 (define-public (fraction->moment fraction)
75   (if (null? fraction)
76       ZERO-MOMENT
77       (ly:make-moment (car fraction) (cdr fraction))))
78
79 (define-public (moment->fraction moment)
80   (cons (ly:moment-main-numerator moment)
81         (ly:moment-main-denominator moment)))
82
83 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
84 ;; durations
85
86 (define-public (duration-log-factor lognum)
87   "Given a logarithmic duration number, return the length of the duration,
88 as a number of whole notes."
89   (or (and (exact? lognum) (integer? lognum))
90       (scm-error 'wrong-type-arg "duration-log-factor" "Not an integer: ~S" (list lognum) #f))
91   (if (<= lognum 0)
92       (ash 1 (- lognum))
93       (/ (ash 1 lognum))))
94
95 (define-public (duration-dot-factor dotcount)
96   "Given a count of the dots used to extend a musical duration, return
97 the numeric factor by which they increase the duration."
98   (or (and (exact? dotcount) (integer? dotcount) (>= dotcount 0))
99       (scm-error 'wrong-type-arg "duration-dot-factor" "Not a count: ~S" (list dotcount) #f))
100   (- 2 (/ (ash 1 dotcount))))
101
102 (define-public (duration-length dur)
103   "Return the overall length of a duration, as a number of whole
104 notes.  (Not to be confused with ly:duration-length, which returns a
105 less-useful moment object.)"
106   (ly:moment-main (ly:duration-length dur)))
107
108 (define-public (duration-visual dur)
109   "Given a duration object, return the visual part of the duration (base
110 note length and dot count), in the form of a duration object with
111 non-visual scale factor 1."
112   (ly:make-duration (ly:duration-log dur) (ly:duration-dot-count dur) 1))
113
114 (define-public (duration-visual-length dur)
115   "Given a duration object, return the length of the visual part of the
116 duration (base note length and dot count), as a number of whole notes."
117   (duration-length (duration-visual dur)))
118
119 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
120 ;; arithmetic
121 (define-public (average x . lst)
122   (/ (+ x (apply + lst)) (1+ (length lst))))
123
124 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
125 ;; parser <-> output hooks.
126
127 (define-public (collect-bookpart-for-book parser book-part)
128   "Toplevel book-part handler."
129   (define (add-bookpart book-part)
130     (ly:parser-define!
131      parser 'toplevel-bookparts
132      (cons book-part (ly:parser-lookup parser 'toplevel-bookparts))))
133   ;; If toplevel scores have been found before this \bookpart,
134   ;; add them first to a dedicated bookpart
135   (if (pair? (ly:parser-lookup parser 'toplevel-scores))
136       (begin
137         (add-bookpart (ly:make-book-part
138                        (ly:parser-lookup parser 'toplevel-scores)))
139         (ly:parser-define! parser 'toplevel-scores (list))))
140   (add-bookpart book-part))
141
142 (define-public (collect-scores-for-book parser score)
143   (ly:parser-define!
144    parser 'toplevel-scores
145    (cons score (ly:parser-lookup parser 'toplevel-scores))))
146
147 (define-public (collect-music-aux score-handler parser music)
148   (define (music-property symbol)
149     (ly:music-property music symbol #f))
150   (cond ((music-property 'page-marker)
151          ;; a page marker: set page break/turn permissions or label
152          (let ((label (music-property 'page-label)))
153            (if (symbol? label)
154                (score-handler (ly:make-page-label-marker label))))
155          (for-each (lambda (symbol)
156                      (let ((permission (music-property symbol)))
157                        (if (symbol? permission)
158                            (score-handler
159                             (ly:make-page-permission-marker symbol
160                                                             (if (eq? 'forbid permission)
161                                                                 '()
162                                                                 permission))))))
163                    '(line-break-permission page-break-permission
164                                            page-turn-permission)))
165         ((not (music-property 'void))
166          ;; a regular music expression: make a score with this music
167          ;; void music is discarded
168          (score-handler (scorify-music music parser)))))
169
170 (define-public (collect-music-for-book parser music)
171   "Top-level music handler."
172   (collect-music-aux (lambda (score)
173                        (collect-scores-for-book parser score))
174                      parser
175                      music))
176
177 (define-public (collect-book-music-for-book parser book music)
178   "Book music handler."
179   (collect-music-aux (lambda (score)
180                        (ly:book-add-score! book score))
181                      parser
182                      music))
183
184 (define-public (scorify-music music parser)
185   "Preprocess @var{music}."
186   (ly:make-score
187    (fold (lambda (f m) (f m parser))
188          music
189          toplevel-music-functions)))
190
191 (define (get-current-filename parser book)
192   "return any suffix value for output filename allowing for settings by
193 calls to bookOutputName function"
194   (or (paper-variable parser book 'output-filename)
195       (ly:parser-output-name parser)))
196
197 (define (get-current-suffix parser book)
198   "return any suffix value for output filename allowing for settings by calls to
199 bookoutput function"
200   (let ((book-output-suffix (paper-variable parser book 'output-suffix)))
201     (if (not (string? book-output-suffix))
202         (ly:parser-lookup parser 'output-suffix)
203         book-output-suffix)))
204
205 (define-public current-outfile-name #f)  ; for use by regression tests
206
207 (define (get-outfile-name parser book)
208   "return current filename for generating backend output files"
209   ;; user can now override the base file name, so we have to use
210   ;; the file-name concatenated with any potential output-suffix value
211   ;; as the key to out internal a-list
212   (let* ((base-name (get-current-filename parser book))
213          (output-suffix (get-current-suffix parser book))
214          (alist-key (format #f "~a~a" base-name output-suffix))
215          (counter-alist (ly:parser-lookup parser 'counter-alist))
216          (output-count (assoc-get alist-key counter-alist 0))
217          (result base-name))
218     ;; Allow all ASCII alphanumerics, including accents
219     (if (string? output-suffix)
220         (set! result
221               (format #f "~a-~a"
222                       result
223                       (string-regexp-substitute
224                        "[^-[:alnum:]]"
225                        "_"
226                        output-suffix))))
227
228     ;; assoc-get call will always have returned a number
229     (if (> output-count 0)
230         (set! result (format #f "~a-~a" result output-count)))
231
232     (ly:parser-define!
233      parser 'counter-alist
234      (assoc-set! counter-alist alist-key (1+ output-count)))
235     (set! current-outfile-name result)
236     result))
237
238 (define (print-book-with parser book process-procedure)
239   (let* ((paper (ly:parser-lookup parser '$defaultpaper))
240          (layout (ly:parser-lookup parser '$defaultlayout))
241          (outfile-name (get-outfile-name parser book)))
242     (process-procedure book paper layout outfile-name)))
243
244 (define-public (print-book-with-defaults parser book)
245   (print-book-with parser book ly:book-process))
246
247 (define-public (print-book-with-defaults-as-systems parser book)
248   (print-book-with parser book ly:book-process-to-systems))
249
250 ;; Add a score to the current bookpart, book or toplevel
251 (define-public (add-score parser score)
252   (cond
253    ((ly:parser-lookup parser '$current-bookpart)
254     ((ly:parser-lookup parser 'bookpart-score-handler)
255      (ly:parser-lookup parser '$current-bookpart) score))
256    ((ly:parser-lookup parser '$current-book)
257     ((ly:parser-lookup parser 'book-score-handler)
258      (ly:parser-lookup parser '$current-book) score))
259    (else
260     ((ly:parser-lookup parser 'toplevel-score-handler) parser score))))
261
262 (define-public paper-variable
263   (let
264       ((get-papers
265         (lambda (parser book)
266           (append (if (and book (ly:output-def? (ly:book-paper book)))
267                       (list (ly:book-paper book))
268                       '())
269                   (ly:parser-lookup parser '$papers)
270                   (list (ly:parser-lookup parser '$defaultpaper))))))
271     (make-procedure-with-setter
272      (lambda (parser book symbol)
273        (any (lambda (p) (ly:output-def-lookup p symbol #f))
274             (get-papers parser book)))
275      (lambda (parser book symbol value)
276        (ly:output-def-set-variable!
277         (car (get-papers parser book))
278         symbol value)))))
279
280 (define-public (add-text parser text)
281   (add-score parser (list text)))
282
283 (define-public (add-music parser music)
284   (collect-music-aux (lambda (score)
285                        (add-score parser score))
286                      parser
287                      music))
288
289 (define-public (context-mod-from-music parser music)
290   (let ((warn #t) (mods (ly:make-context-mod)))
291     (let loop ((m music))
292       (if (music-is-of-type? m 'layout-instruction-event)
293           (let ((symbol (ly:music-property m 'symbol)))
294             (ly:add-context-mod
295              mods
296              (case (ly:music-property m 'name)
297                ((PropertySet)
298                 (list 'assign
299                       symbol
300                       (ly:music-property m 'value)))
301                ((PropertyUnset)
302                 (list 'unset symbol))
303                ((OverrideProperty)
304                 (cons* 'push
305                        symbol
306                        (ly:music-property m 'grob-value)
307                        (cond
308                         ((ly:music-property m 'grob-property #f) => list)
309                         (else
310                          (ly:music-property m 'grob-property-path)))))
311                ((RevertProperty)
312                 (cons* 'pop
313                        symbol
314                        (cond
315                         ((ly:music-property m 'grob-property #f) => list)
316                         (else
317                          (ly:music-property m 'grob-property-path))))))))
318           (case (ly:music-property m 'name)
319             ((ApplyContext)
320              (ly:add-context-mod mods
321                                  (list 'apply
322                                        (ly:music-property m 'procedure))))
323             ((ContextSpeccedMusic)
324              (loop (ly:music-property m 'element)))
325             (else
326              (let ((callback (ly:music-property m 'elements-callback)))
327                (if (procedure? callback)
328                    (for-each loop (callback m))
329                    (if (and warn (ly:duration? (ly:music-property m 'duration)))
330                        (begin
331                          (ly:music-warning
332                           music
333                           (_ "Music unsuitable for context-mod"))
334                          (set! warn #f)))))))))
335     mods))
336
337 (define-public (context-defs-from-music parser output-def music)
338   (let ((warn #t))
339     (let loop ((m music) (mods #f))
340       ;; The parser turns all sets, overrides etc into something
341       ;; wrapped in ContextSpeccedMusic.  If we ever get a set,
342       ;; override etc that is not wrapped in ContextSpeccedMusic, the
343       ;; user has created it in Scheme himself without providing the
344       ;; required wrapping.  In that case, using #f in the place of a
345       ;; context modification results in a reasonably recognizable
346       ;; error.
347       (if (music-is-of-type? m 'layout-instruction-event)
348           (ly:add-context-mod
349            mods
350            (case (ly:music-property m 'name)
351              ((PropertySet)
352               (list 'assign
353                     (ly:music-property m 'symbol)
354                     (ly:music-property m 'value)))
355              ((PropertyUnset)
356               (list 'unset
357                     (ly:music-property m 'symbol)))
358              ((OverrideProperty)
359               (cons* 'push
360                      (ly:music-property m 'symbol)
361                      (ly:music-property m 'grob-value)
362                      (cond
363                       ((ly:music-property m 'grob-property #f) => list)
364                       (else
365                        (ly:music-property m 'grob-property-path)))))
366              ((RevertProperty)
367               (cons* 'pop
368                      (ly:music-property m 'symbol)
369                      (cond
370                       ((ly:music-property m 'grob-property #f) => list)
371                       (else
372                        (ly:music-property m 'grob-property-path)))))))
373           (case (ly:music-property m 'name)
374             ((ApplyContext)
375              (ly:add-context-mod mods
376                                  (list 'apply
377                                        (ly:music-property m 'procedure))))
378             ((ContextSpeccedMusic)
379              ;; Use let* here to let defs catch up with modifications
380              ;; to the context defs made in the recursion
381              (let* ((mods (loop (ly:music-property m 'element)
382                                 (ly:make-context-mod)))
383                     (defs (ly:output-find-context-def
384                            output-def (ly:music-property m 'context-type))))
385                (if (null? defs)
386                    (ly:music-warning
387                     music
388                     (ly:format (_ "Cannot find context-def \\~a")
389                                (ly:music-property m 'context-type)))
390                    (for-each
391                     (lambda (entry)
392                       (ly:output-def-set-variable!
393                        output-def (car entry)
394                        (ly:context-def-modify (cdr entry) mods)))
395                     defs))))
396             (else
397              (let ((callback (ly:music-property m 'elements-callback)))
398                (if (procedure? callback)
399                    (fold loop mods (callback m))
400                    (if (and warn (ly:duration? (ly:music-property m 'duration)))
401                        (begin
402                          (ly:music-warning
403                           music
404                           (_ "Music unsuitable for output-def"))
405                          (set! warn #f))))))))
406       mods)))
407
408
409 ;;;;;;;;;;;;;;;;
410 ;; alist
411
412 (define-public assoc-get ly:assoc-get)
413
414 (define-public chain-assoc-get ly:chain-assoc-get)
415
416 (define-public (uniqued-alist alist acc)
417   (if (null? alist) acc
418       (if (assoc (caar alist) acc)
419           (uniqued-alist (cdr alist) acc)
420           (uniqued-alist (cdr alist) (cons (car alist) acc)))))
421
422 (define-public (alist<? x y)
423   (string<? (symbol->string (car x))
424             (symbol->string (car y))))
425
426 (define (map-alist-vals func list)
427   "map FUNC over the vals of LIST, leaving the keys."
428   (if (null?  list)
429       '()
430       (cons (cons  (caar list) (func (cdar list)))
431             (map-alist-vals func (cdr list)))))
432
433 (define (map-alist-keys func list)
434   "map FUNC over the keys of an alist LIST, leaving the vals."
435   (if (null?  list)
436       '()
437       (cons (cons (func (caar list)) (cdar list))
438             (map-alist-keys func (cdr list)))))
439
440 (define-public (first-member members lst)
441   "Return first successful member (of member) from @var{members} in
442 @var{lst}."
443   (any (lambda (m) (member m lst)) members))
444
445 (define-public (first-assoc keys lst)
446   "Return first successful assoc of key from @var{keys} in @var{lst}."
447   (any (lambda (k) (assoc k lst)) keys))
448
449 (define-public (flatten-alist alist)
450   (if (null? alist)
451       '()
452       (cons (caar alist)
453             (cons (cdar alist)
454                   (flatten-alist (cdr alist))))))
455
456 (define-public (map-selected-alist-keys function keys alist)
457   "Return @var{alist} with @var{function} applied to all of the values
458 in list @var{keys}.
459
460 For example:
461 @example
462 @code{guile> (map-selected-alist-keys - '(a b) '((a . 1) (b . -2) (c . 3) (d . 4)))}
463 @code{((a . -1) (b . 2) (c . 3) (d . 4)}
464 @end example"
465   (define (map-selected-alist-keys-helper key alist)
466     (map
467      (lambda (pair)
468        (if (equal? key (car pair))
469            (cons key (function (cdr pair)))
470            pair))
471      alist))
472   (fold map-selected-alist-keys-helper alist keys))
473
474 ;;;;;;;;;;;;;;;;
475 ;; vector
476
477 (define-public (vector-for-each proc vec)
478   (do
479       ((i 0 (1+ i)))
480       ((>= i (vector-length vec)) vec)
481     (vector-set! vec i (proc (vector-ref vec i)))))
482
483 ;;;;;;;;;;;;;;;;
484 ;; hash
485
486 (define-public (hash-table->alist t)
487   (hash-fold acons '() t))
488
489 ;; todo: code dup with C++.
490 (define-safe-public (alist->hash-table lst)
491   "Convert alist to table"
492   (let ((m (make-hash-table (length lst))))
493     (for-each (lambda (k-v) (hashq-set! m (car k-v) (cdr k-v))) lst)
494     m))
495
496 ;;;;;;;;;;;;;;;;
497 ;; list
498
499 (define (functional-or . rest)
500   (any identity rest))
501
502 (define (functional-and . rest)
503   (every identity rest))
504
505 (define (split-list lst n)
506   "Split LST in N equal sized parts"
507
508   (define (helper todo acc-vector k)
509     (if (null? todo)
510         acc-vector
511         (begin
512           (if (< k 0)
513               (set! k (+ n k)))
514
515           (vector-set! acc-vector k (cons (car todo) (vector-ref acc-vector k)))
516           (helper (cdr todo) acc-vector (1- k)))))
517
518   (helper lst (make-vector n '()) (1- n)))
519
520 (define (list-element-index lst x)
521   (list-index (lambda (m) (equal? m x)) lst))
522
523 (define-public (count-list lst)
524   "Given @var{lst} as @code{(E1 E2 .. )}, return
525 @code{((E1 . 1) (E2 . 2) ... )}."
526   (map cons lst (iota (length lst) 1)))
527
528 (define-public (list-join lst intermediate)
529   "Put @var{intermediate} between all elts of @var{lst}."
530
531   (fold-right
532    (lambda (elem prev)
533      (if (pair? prev)
534          (cons  elem (cons intermediate prev))
535          (list elem)))
536    '() lst))
537
538 (define-public (filtered-map proc lst)
539   (filter
540    (lambda (x) x)
541    (map proc lst)))
542
543 (define-public (flatten-list x)
544   "Unnest list."
545   (let loop ((x x) (tail '()))
546     (cond ((list? x) (fold-right loop tail x))
547           ((not (pair? x)) (cons x tail))
548           (else (loop (car x) (loop (cdr x) tail))))))
549
550 (define (list-minus a b)
551   "Return list of elements in A that are not in B."
552   (lset-difference eq? a b))
553
554 (define-public (uniq-list lst)
555   "Uniq @var{lst}, assuming that it is sorted.  Uses @code{equal?}
556 for comparisons."
557
558   (reverse!
559    (fold (lambda (x acc)
560            (if (null? acc)
561                (list x)
562                (if (equal? x (car acc))
563                    acc
564                    (cons x acc))))
565          '() lst) '()))
566
567 (define (split-at-predicate pred lst)
568   "Split LST into two lists at the first element that returns #f for
569   (PRED previous_element element).  Return the two parts as a pair.
570   Example: (split-at-predicate < '(1 2 3 2 1)) ==> ((1 2 3) . (2 1))"
571   (let ((i (and (pair? lst)
572                 (list-index (lambda (x y) (not (pred x y)))
573                             lst
574                             (cdr lst)))))
575     (if i
576         (call-with-values
577             (lambda () (split-at lst (1+ i)))
578           cons)
579         (list lst))))
580
581 (define-public (split-list-by-separator lst pred)
582   "Split @var{lst} at each element that satisfies @var{pred}, and return
583 the parts (with the separators removed) as a list of lists.  For example,
584 executing @samp{(split-list-by-separator '(a 0 b c 1 d) number?)} returns
585 @samp{((a) (b c) (d))}."
586   (call-with-values (lambda () (break pred lst))
587     (lambda (head tail)
588       (cons head
589             (if (null? tail)
590                 tail
591                 (split-list-by-separator (cdr tail) pred))))))
592
593 (define-public (offset-add a b)
594   (cons (+ (car a) (car b))
595         (+ (cdr a) (cdr b))))
596
597 (define-public (offset-flip-y o)
598   (cons (car o) (- (cdr o))))
599
600 (define-public (offset-scale o scale)
601   (cons (* (car o) scale)
602         (* (cdr o) scale)))
603
604 (define-public (ly:list->offsets accum coords)
605   (if (null? coords)
606       accum
607       (cons (cons (car coords) (cadr coords))
608             (ly:list->offsets accum (cddr coords)))))
609
610 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
611 ;; intervals
612
613 (define-public empty-interval '(+inf.0 . -inf.0))
614
615 (define-public (symmetric-interval expr)
616   (cons (- expr) expr))
617
618 (define-public (interval-length x)
619   "Length of the number-pair @var{x}, if an interval."
620   (max 0 (- (cdr x) (car x))))
621
622 (define-public (ordered-cons a b)
623   (cons (min a b)
624         (max a b)))
625
626 (define-public (interval-bound interval dir)
627   ((if (= dir RIGHT) cdr car) interval))
628
629 (define-public (interval-index interval dir)
630   "Interpolate @var{interval} between between left (@var{dir}=-1) and
631 right (@var{dir}=+1)."
632
633   (* (+  (interval-start interval) (interval-end interval)
634          (* dir (- (interval-end interval) (interval-start interval))))
635      0.5))
636
637 (define-public (interval-center x)
638   "Center the number-pair @var{x}, if an interval."
639   (if (interval-empty? x)
640       0.0
641       (/ (+ (car x) (cdr x)) 2)))
642
643 (define-public interval-start car)
644
645 (define-public interval-end cdr)
646
647 (define (other-axis a)
648   (remainder (+ a 1) 2))
649
650 (define-public (interval-scale iv factor)
651   (cons (* (car iv) factor)
652         (* (cdr iv) factor)))
653
654 (define-public (interval-widen iv amount)
655   (cons (- (car iv) amount)
656         (+ (cdr iv) amount)))
657
658 (define-public (interval-empty? iv)
659   (> (car iv) (cdr iv)))
660
661 (define-public (interval-union i1 i2)
662   (cons
663    (min (car i1) (car i2))
664    (max (cdr i1) (cdr i2))))
665
666 (define-public (interval-intersection i1 i2)
667   (cons
668    (max (car i1) (car i2))
669    (min (cdr i1) (cdr i2))))
670
671 (define-public (interval-sane? i)
672   (not (or  (nan? (car i))
673             (inf? (car i))
674             (nan? (cdr i))
675             (inf? (cdr i))
676             (> (car i) (cdr i)))))
677
678 (define-public (add-point interval p)
679   (cons (min (interval-start interval) p)
680         (max (interval-end interval) p)))
681
682 (define-public (reverse-interval iv)
683   (cons (cdr iv) (car iv)))
684
685 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
686 ;; coordinates
687
688 (define coord-x car)
689 (define coord-y cdr)
690
691 (define (coord-operation operator operand coordinate)
692   (if (pair? operand)
693       (cons (operator (coord-x operand) (coord-x coordinate))
694             (operator (coord-y operand) (coord-y coordinate)))
695       (cons (operator operand (coord-x coordinate))
696             (operator operand (coord-y coordinate)))))
697
698 (define (coord-apply function coordinate)
699   (if (pair? function)
700       (cons
701        ((coord-x function) (coord-x coordinate))
702        ((coord-y function) (coord-y coordinate)))
703       (cons
704        (function (coord-x coordinate))
705        (function (coord-y coordinate)))))
706
707 (define-public (coord-translate coordinate amount)
708   (coord-operation + amount coordinate))
709
710 (define-public (coord-scale coordinate amount)
711   (coord-operation * amount coordinate))
712
713 (define-public (coord-rotate coordinate degrees-in-radians)
714   (let*
715       ((coordinate
716         (cons
717          (exact->inexact (coord-x coordinate))
718          (exact->inexact (coord-y coordinate))))
719        (radius
720         (sqrt
721          (+ (* (coord-x coordinate) (coord-x coordinate))
722             (* (coord-y coordinate) (coord-y coordinate)))))
723        (angle (angle-0-2pi (atan (coord-y coordinate) (coord-x coordinate)))))
724     (cons
725      (* radius (cos (+ angle degrees-in-radians)))
726      (* radius (sin (+ angle degrees-in-radians))))))
727
728 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
729 ;; trig
730
731 (define-public PI (* 4 (atan 1)))
732
733 (define-public TWO-PI (* 2 PI))
734
735 (define-public PI-OVER-TWO (/ PI 2))
736
737 (define-public THREE-PI-OVER-TWO (* 3 PI-OVER-TWO))
738
739 (define-public (cyclic-base-value value cycle)
740   "Take @var{value} and modulo-maps it between 0 and base @var{cycle}."
741   (if (< value 0)
742       (cyclic-base-value (+ value cycle) cycle)
743       (if (>= value cycle)
744           (cyclic-base-value (- value cycle) cycle)
745           value)))
746
747 (define-public (angle-0-2pi angle)
748   "Take @var{angle} (in radians) and maps it between 0 and 2pi."
749   (cyclic-base-value angle TWO-PI))
750
751 (define-public (angle-0-360 angle)
752   "Take @var{angle} (in degrees) and maps it between 0 and 360 degrees."
753   (cyclic-base-value angle 360.0))
754
755 (define-public PI-OVER-180  (/ PI 180))
756
757 (define-public (degrees->radians angle-degrees)
758   "Convert the given angle from degrees to radians."
759   (* angle-degrees PI-OVER-180))
760
761 (define-public (ellipse-radius x-radius y-radius angle)
762   (/
763    (* x-radius y-radius)
764    (sqrt
765     (+ (* (expt y-radius 2)
766           (* (cos angle) (cos angle)))
767        (* (expt x-radius 2)
768           (* (sin angle) (sin angle)))))))
769
770 (define-public (polar->rectangular radius angle-in-degrees)
771   "Return polar coordinates (@var{radius}, @var{angle-in-degrees})
772 as rectangular coordinates @ode{(x-length . y-length)}."
773
774   (let ((complex (make-polar
775                   radius
776                   (degrees->radians angle-in-degrees))))
777     (cons
778      (real-part complex)
779      (imag-part complex))))
780
781 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
782 ;; string
783
784 (define-public (string-endswith s suffix)
785   (equal? suffix (substring s
786                             (max 0 (- (string-length s) (string-length suffix)))
787                             (string-length s))))
788
789 (define-public (string-startswith s prefix)
790   (equal? prefix (substring s 0 (min (string-length s) (string-length prefix)))))
791
792 (define-public (string-encode-integer i)
793   (cond
794    ((= i  0) "o")
795    ((< i 0)   (string-append "n" (string-encode-integer (- i))))
796    (else (string-append
797           (make-string 1 (integer->char (+ 65 (modulo i 26))))
798           (string-encode-integer (quotient i 26))))))
799
800 (define (number->octal-string x)
801   (let* ((n (inexact->exact x))
802          (n64 (quotient n 64))
803          (n8 (quotient (- n (* n64 64)) 8)))
804     (string-append
805      (number->string n64)
806      (number->string n8)
807      (number->string (remainder (- n (+ (* n64 64) (* n8 8))) 8)))))
808
809 (define-public (ly:inexact->string x radix)
810   (let ((n (inexact->exact x)))
811     (number->string n radix)))
812
813 (define-public (ly:number-pair->string c)
814   (string-append (ly:number->string (car c)) " "
815                  (ly:number->string (cdr c))))
816
817 (define-public (dir-basename file . rest)
818   "Strip suffixes in @var{rest}, but leave directory component for
819 @var{file}."
820   (define (inverse-basename x y) (basename y x))
821   (simple-format #f "~a/~a" (dirname file)
822                  (fold inverse-basename file rest)))
823
824 (define-public (write-me message x)
825   "Return @var{x}.  Display @var{message} and write @var{x}.
826 Handy for debugging, possibly turned off."
827   (display message) (write x) (newline) x)
828 ;;  x)
829
830 (define-public (stderr string . rest)
831   (apply format (cons (current-error-port) (cons string rest)))
832   (force-output (current-error-port)))
833
834 (define-public (debugf string . rest)
835   (if #f
836       (apply stderr (cons string rest))))
837
838 (define (index-cell cell dir)
839   (if (equal? dir 1)
840       (cdr cell)
841       (car cell)))
842
843 (define (cons-map f x)
844   "map F to contents of X"
845   (cons (f (car x)) (f (cdr x))))
846
847 (define-public (list-insert-separator lst between)
848   "Create new list, inserting @var{between} between elements of @var{lst}."
849   (define (conc x y )
850     (if (eq? y #f)
851         (list x)
852         (cons x  (cons between y))))
853   (fold-right conc #f lst))
854
855 (define-public (string-regexp-substitute a b str)
856   (regexp-substitute/global #f a str 'pre b 'post))
857
858 (define (regexp-split str regex)
859   (define matches '())
860   (define end-of-prev-match 0)
861   (define (notice match)
862
863     (set! matches (cons (substring (match:string match)
864                                    end-of-prev-match
865                                    (match:start match))
866                         matches))
867     (set! end-of-prev-match (match:end match)))
868
869   (regexp-substitute/global #f regex str notice 'post)
870
871   (if (< end-of-prev-match (string-length str))
872       (set!
873        matches
874        (cons (substring str end-of-prev-match (string-length str)) matches)))
875
876   (reverse matches))
877
878 ;;;;;;;;;;;;;;;;
879 ;; other
880
881 (define (sign x)
882   (if (= x 0)
883       0
884       (if (< x 0) -1 1)))
885
886 (define-public (binary-search start end getter target-val)
887   (_i "Find the index between @var{start} and @var{end} (an integer)
888 which produces the closest match to @var{target-val} if
889 applied to function @var{getter}.")
890   (if (<= end start)
891       start
892       (let* ((compare (quotient (+ start end) 2))
893              (get-val (getter compare)))
894         (cond
895          ((< target-val get-val)
896           (set! end (1- compare)))
897          ((< get-val target-val)
898           (set! start (1+ compare))))
899         (binary-search start end getter target-val))))
900
901 (define-public (car< a b)
902   (< (car a) (car b)))
903
904 (define-public (car<= a b)
905   (<= (car a) (car b)))
906
907 (define-public (symbol<? lst r)
908   (string<? (symbol->string lst) (symbol->string r)))
909
910 (define-public (symbol-key<? lst r)
911   (string<? (symbol->string (car lst)) (symbol->string (car r))))
912
913 (define-public (eval-carefully symbol module . default)
914   "Check whether all symbols in expr @var{symbol} are reachable
915 in module @var{module}.  In that case evaluate, otherwise
916 print a warning and set an optional @var{default}."
917   (let* ((unavailable? (lambda (sym)
918                          (not (module-defined? module sym))))
919          (sym-unavailable
920           (filter
921            unavailable?
922            (filter symbol? (flatten-list symbol)))))
923     (if (null? sym-unavailable)
924         (eval symbol module)
925         (let* ((def (and (pair? default) (car default))))
926           (ly:programming-error
927            "cannot evaluate ~S in module ~S, setting to ~S"
928            (object->string symbol)
929            (object->string module)
930            (object->string def))
931           def))))
932
933 ;;
934 ;; don't confuse users with #<procedure .. > syntax.
935 ;;
936 (define-public (scm->string val)
937   (if (and (procedure? val)
938            (symbol? (procedure-name val)))
939       (symbol->string (procedure-name val))
940       (string-append
941        (if (self-evaluating? val)
942            (if (string? val)
943                "\""
944                "")
945            "'")
946        (call-with-output-string (lambda (port) (display val port)))
947        (if (string? val)
948            "\""
949            ""))))
950
951 (define-public (!= lst r)
952   (not (= lst r)))
953
954 (define-public lily-unit->bigpoint-factor
955   (cond
956    ((equal? (ly:unit) "mm") (/ 72.0 25.4))
957    ((equal? (ly:unit) "pt") (/ 72.0 72.27))
958    (else (ly:error (_ "unknown unit: ~S") (ly:unit)))))
959
960 (define-public lily-unit->mm-factor
961   (* 25.4 (/ lily-unit->bigpoint-factor 72)))
962
963 ;;; FONT may be font smob, or pango font string...
964 (define-public (font-name-style font)
965   (if (string? font)
966       (string-downcase font)
967       (let* ((font-name (ly:font-name font))
968              (full-name (if font-name font-name (ly:font-file-name font))))
969         (string-downcase full-name))))
970
971 (define-public (modified-font-metric-font-scaling font)
972   (let* ((designsize (ly:font-design-size font))
973          (magnification (* (ly:font-magnification font)))
974          (scaling (* magnification designsize)))
975     (debugf "scaling:~S\n" scaling)
976     (debugf "magnification:~S\n" magnification)
977     (debugf "design:~S\n" designsize)
978     scaling))
979
980 (define-public (version-not-seen-message input-file-name)
981   (ly:warning-located
982    (ly:format "~a:1" input-file-name)
983    (_ "no \\version statement found, please add~afor future compatibility")
984    (format #f "\n\n\\version ~s\n\n" (lilypond-version))))