1 /* 2 This file is part of LilyPond, the GNU music typesetter. 3 4 Copyright (C) 1999--2020 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 20 #include "moment.hh" 21 22 /* TODO: add optional factor argument. */ 23 LY_DEFINE (ly_make_moment, "ly:make-moment", 24 1, 3, 0, (SCM m, SCM g, SCM gn, SCM gd), 25 "Create the moment with rational main timing @var{m}," 26 " and optional grace timing @var{g}.\n" 27 "\n" 28 "A @dfn{moment} is a point in musical time. It consists of" 29 " a pair of rationals (@var{m},@tie{}@var{g}), where @var{m} is" 30 " the timing for the main notes, and @var{g} the timing for" 31 " grace notes. In absence of grace notes, @var{g}@tie{}is zero.\n" 32 "\n" 33 "For compatibility reasons, it is possible to write two" 34 " numbers specifying numerator and denominator instead of" 35 " the rationals. These forms cannot be mixed, and the two-" 36 "argument form is disambiguated by the sign of the second" 37 " argument: if it is positive, it can only be a denominator" 38 " and not a grace timing." 39 ) 40 { 41 LY_ASSERT_TYPE (is_scm<Rational>, m, 1); 42 if (SCM_UNBNDP (g)) 43 return Moment (from_scm<Rational> (m)).smobbed_copy (); 44 45 if (SCM_UNBNDP (gn)) 46 { 47 LY_ASSERT_TYPE (is_scm<Rational>, g, 2); 48 if (scm_is_true (scm_positive_p (g))) 49 { 50 LY_ASSERT_TYPE (scm_is_integer, m, 1); 51 LY_ASSERT_TYPE (scm_is_integer, g, 2); 52 return Moment (Rational (scm_to_int64 (m), 53 scm_to_int64 (g))).smobbed_copy (); 54 } 55 return Moment (from_scm<Rational> (m), 56 from_scm<Rational> (g)).smobbed_copy (); 57 } 58 59 LY_ASSERT_TYPE (scm_is_integer, m, 1); 60 LY_ASSERT_TYPE (scm_is_integer, g, 2); 61 LY_ASSERT_TYPE (scm_is_integer, gn, 3); 62 I64 grace_num = scm_to_int64 (gn); 63 I64 grace_den = 1; 64 if (!SCM_UNBNDP (gd)) 65 { 66 LY_ASSERT_TYPE (scm_is_integer, gd, 4); 67 grace_den = scm_to_int64 (gd); 68 } 69 70 return Moment (Rational (scm_to_int64 (m), scm_to_int64 (g)), 71 Rational (grace_num, grace_den)).smobbed_copy (); 72 } 73 74 LY_DEFINE (ly_moment_sub, "ly:moment-sub", 75 2, 0, 0, (SCM a, SCM b), 76 "Subtract two moments.") 77 { 78 LY_ASSERT_SMOB (Moment, a, 1); 79 LY_ASSERT_SMOB (Moment, b, 2); 80 81 Moment *ma = unsmob<Moment> (a); 82 Moment *mb = unsmob<Moment> (b); 83 84 return (*ma - *mb).smobbed_copy (); 85 } 86 87 LY_DEFINE (ly_moment_add, "ly:moment-add", 88 2, 0, 0, (SCM a, SCM b), 89 "Add two moments.") 90 { 91 LY_ASSERT_SMOB (Moment, a, 1); 92 LY_ASSERT_SMOB (Moment, b, 2); 93 94 Moment *ma = unsmob<Moment> (a); 95 Moment *mb = unsmob<Moment> (b); 96 97 return (*ma + *mb).smobbed_copy (); 98 } 99 100 LY_DEFINE (ly_moment_mul, "ly:moment-mul", 101 2, 0, 0, (SCM a, SCM b), 102 "Multiply two moments.") 103 { 104 LY_ASSERT_SMOB (Moment, a, 1); 105 LY_ASSERT_SMOB (Moment, b, 2); // TODO: should be Rational 106 107 Moment *ma = unsmob<Moment> (a); 108 Moment *mb = unsmob<Moment> (b); 109 return (*ma * mb->main_part_).smobbed_copy (); 110 } 111 112 LY_DEFINE (ly_moment_div, "ly:moment-div", 113 2, 0, 0, (SCM a, SCM b), 114 "Divide two moments.") 115 { 116 LY_ASSERT_SMOB (Moment, a, 1); 117 LY_ASSERT_SMOB (Moment, b, 2); // TODO: should be Rational 118 119 Moment *ma = unsmob<Moment> (a); 120 Moment *mb = unsmob<Moment> (b); 121 122 return (*ma / mb->main_part_).smobbed_copy (); 123 } 124 125 LY_DEFINE (ly_moment_mod, "ly:moment-mod", 126 2, 0, 0, (SCM a, SCM b), 127 "Modulo of two moments.") 128 { 129 LY_ASSERT_SMOB (Moment, a, 1); 130 LY_ASSERT_SMOB (Moment, b, 2); // TODO: should be Rational 131 132 Moment *ma = unsmob<Moment> (a); 133 Moment *mb = unsmob<Moment> (b); 134 return (*ma % mb->main_part_).smobbed_copy (); 135 } 136 137 LY_DEFINE (ly_moment_grace, "ly:moment-grace", 138 1, 0, 0, (SCM mom), 139 "Extract grace timing as a rational number from @var{mom}.") 140 { 141 LY_ASSERT_SMOB (Moment, mom, 1); 142 143 return to_scm (unsmob<Moment> (mom)->grace_part_); 144 } 145 146 LY_DEFINE (ly_moment_grace_numerator, "ly:moment-grace-numerator", 147 1, 0, 0, (SCM mom), 148 "Extract numerator from grace timing.") 149 { 150 LY_ASSERT_SMOB (Moment, mom, 1); 151 152 Moment *ma = unsmob<Moment> (mom); 153 154 return to_scm (ma->grace_part_.numerator ()); 155 } 156 157 LY_DEFINE (ly_moment_grace_denominator, "ly:moment-grace-denominator", 158 1, 0, 0, (SCM mom), 159 "Extract denominator from grace timing.") 160 { 161 LY_ASSERT_SMOB (Moment, mom, 1); 162 Moment *ma = unsmob<Moment> (mom); 163 164 return to_scm (ma->grace_part_.denominator ()); 165 } 166 167 LY_DEFINE (ly_moment_main, "ly:moment-main", 168 1, 0, 0, (SCM mom), 169 "Extract main timing as a rational number from @var{mom}.") 170 { 171 LY_ASSERT_SMOB (Moment, mom, 1); 172 173 return to_scm (unsmob<Moment> (mom)->main_part_); 174 } 175 176 LY_DEFINE (ly_moment_main_numerator, "ly:moment-main-numerator", 177 1, 0, 0, (SCM mom), 178 "Extract numerator from main timing.") 179 { 180 LY_ASSERT_SMOB (Moment, mom, 1); 181 Moment *ma = unsmob<Moment> (mom); 182 183 return to_scm (ma->main_part_.numerator ()); 184 } 185 186 LY_DEFINE (ly_moment_main_denominator, "ly:moment-main-denominator", 187 1, 0, 0, (SCM mom), 188 "Extract denominator from main timing.") 189 { 190 LY_ASSERT_SMOB (Moment, mom, 1); 191 Moment *ma = unsmob<Moment> (mom); 192 193 return to_scm (ma->main_part_.denominator ()); 194 } 195 196 LY_DEFINE (ly_moment_less_p, "ly:moment<?", 197 2, 0, 0, (SCM a, SCM b), 198 "Compare two moments.") 199 { 200 LY_ASSERT_SMOB (Moment, a, 1); 201 LY_ASSERT_SMOB (Moment, b, 2); 202 203 Moment *ma = unsmob<Moment> (a); 204 Moment *mb = unsmob<Moment> (b); 205 206 return ly_bool2scm (*ma < *mb); 207 } 208 209