musicality 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +47 -0
  8. data/Rakefile +65 -0
  9. data/bin/midify +78 -0
  10. data/examples/hip.rb +32 -0
  11. data/examples/missed_connection.rb +26 -0
  12. data/examples/song1.rb +33 -0
  13. data/examples/song2.rb +32 -0
  14. data/lib/musicality/errors.rb +9 -0
  15. data/lib/musicality/notation/conversion/change_conversion.rb +19 -0
  16. data/lib/musicality/notation/conversion/measure_note_map.rb +40 -0
  17. data/lib/musicality/notation/conversion/measured_score_conversion.rb +70 -0
  18. data/lib/musicality/notation/conversion/measured_score_converter.rb +95 -0
  19. data/lib/musicality/notation/conversion/note_time_converter.rb +68 -0
  20. data/lib/musicality/notation/conversion/tempo_conversion.rb +25 -0
  21. data/lib/musicality/notation/conversion/unmeasured_score_conversion.rb +47 -0
  22. data/lib/musicality/notation/conversion/unmeasured_score_converter.rb +64 -0
  23. data/lib/musicality/notation/model/articulations.rb +13 -0
  24. data/lib/musicality/notation/model/change.rb +62 -0
  25. data/lib/musicality/notation/model/dynamics.rb +12 -0
  26. data/lib/musicality/notation/model/link.rb +73 -0
  27. data/lib/musicality/notation/model/meter.rb +54 -0
  28. data/lib/musicality/notation/model/meters.rb +9 -0
  29. data/lib/musicality/notation/model/note.rb +120 -0
  30. data/lib/musicality/notation/model/part.rb +54 -0
  31. data/lib/musicality/notation/model/pitch.rb +163 -0
  32. data/lib/musicality/notation/model/pitches.rb +21 -0
  33. data/lib/musicality/notation/model/program.rb +53 -0
  34. data/lib/musicality/notation/model/score.rb +132 -0
  35. data/lib/musicality/notation/packing/change_packing.rb +46 -0
  36. data/lib/musicality/notation/packing/part_packing.rb +31 -0
  37. data/lib/musicality/notation/packing/program_packing.rb +16 -0
  38. data/lib/musicality/notation/packing/score_packing.rb +108 -0
  39. data/lib/musicality/notation/parsing/articulation_parsing.rb +264 -0
  40. data/lib/musicality/notation/parsing/articulation_parsing.treetop +59 -0
  41. data/lib/musicality/notation/parsing/convenience_methods.rb +74 -0
  42. data/lib/musicality/notation/parsing/duration_nodes.rb +21 -0
  43. data/lib/musicality/notation/parsing/duration_parsing.rb +205 -0
  44. data/lib/musicality/notation/parsing/duration_parsing.treetop +25 -0
  45. data/lib/musicality/notation/parsing/link_nodes.rb +35 -0
  46. data/lib/musicality/notation/parsing/link_parsing.rb +270 -0
  47. data/lib/musicality/notation/parsing/link_parsing.treetop +33 -0
  48. data/lib/musicality/notation/parsing/meter_parsing.rb +190 -0
  49. data/lib/musicality/notation/parsing/meter_parsing.treetop +29 -0
  50. data/lib/musicality/notation/parsing/note_node.rb +40 -0
  51. data/lib/musicality/notation/parsing/note_parsing.rb +229 -0
  52. data/lib/musicality/notation/parsing/note_parsing.treetop +28 -0
  53. data/lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.rb +289 -0
  54. data/lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.treetop +29 -0
  55. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb +64 -0
  56. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.treetop +17 -0
  57. data/lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.rb +86 -0
  58. data/lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.treetop +20 -0
  59. data/lib/musicality/notation/parsing/numbers/positive_float_parsing.rb +503 -0
  60. data/lib/musicality/notation/parsing/numbers/positive_float_parsing.treetop +33 -0
  61. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.rb +95 -0
  62. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.treetop +19 -0
  63. data/lib/musicality/notation/parsing/numbers/positive_rational_parsing.rb +84 -0
  64. data/lib/musicality/notation/parsing/numbers/positive_rational_parsing.treetop +19 -0
  65. data/lib/musicality/notation/parsing/parseable.rb +30 -0
  66. data/lib/musicality/notation/parsing/pitch_node.rb +23 -0
  67. data/lib/musicality/notation/parsing/pitch_parsing.rb +448 -0
  68. data/lib/musicality/notation/parsing/pitch_parsing.treetop +52 -0
  69. data/lib/musicality/notation/parsing/segment_parsing.rb +141 -0
  70. data/lib/musicality/notation/parsing/segment_parsing.treetop +23 -0
  71. data/lib/musicality/notation/util/interpolation.rb +16 -0
  72. data/lib/musicality/notation/util/piecewise_function.rb +122 -0
  73. data/lib/musicality/notation/util/value_computer.rb +170 -0
  74. data/lib/musicality/performance/conversion/glissando_converter.rb +34 -0
  75. data/lib/musicality/performance/conversion/note_sequence_extractor.rb +98 -0
  76. data/lib/musicality/performance/conversion/portamento_converter.rb +24 -0
  77. data/lib/musicality/performance/conversion/score_collator.rb +126 -0
  78. data/lib/musicality/performance/midi/midi_events.rb +34 -0
  79. data/lib/musicality/performance/midi/midi_util.rb +31 -0
  80. data/lib/musicality/performance/midi/part_sequencer.rb +123 -0
  81. data/lib/musicality/performance/midi/score_sequencer.rb +45 -0
  82. data/lib/musicality/performance/model/note_attacks.rb +19 -0
  83. data/lib/musicality/performance/model/note_sequence.rb +111 -0
  84. data/lib/musicality/performance/util/note_linker.rb +28 -0
  85. data/lib/musicality/performance/util/optimization.rb +31 -0
  86. data/lib/musicality/validatable.rb +38 -0
  87. data/lib/musicality/version.rb +3 -0
  88. data/lib/musicality.rb +81 -0
  89. data/musicality.gemspec +30 -0
  90. data/spec/musicality_spec.rb +7 -0
  91. data/spec/notation/conversion/change_conversion_spec.rb +40 -0
  92. data/spec/notation/conversion/measure_note_map_spec.rb +73 -0
  93. data/spec/notation/conversion/measured_score_conversion_spec.rb +141 -0
  94. data/spec/notation/conversion/measured_score_converter_spec.rb +329 -0
  95. data/spec/notation/conversion/note_time_converter_spec.rb +81 -0
  96. data/spec/notation/conversion/tempo_conversion_spec.rb +40 -0
  97. data/spec/notation/conversion/unmeasured_score_conversion_spec.rb +71 -0
  98. data/spec/notation/conversion/unmeasured_score_converter_spec.rb +116 -0
  99. data/spec/notation/model/change_spec.rb +90 -0
  100. data/spec/notation/model/link_spec.rb +83 -0
  101. data/spec/notation/model/meter_spec.rb +97 -0
  102. data/spec/notation/model/note_spec.rb +183 -0
  103. data/spec/notation/model/part_spec.rb +69 -0
  104. data/spec/notation/model/pitch_spec.rb +180 -0
  105. data/spec/notation/model/program_spec.rb +50 -0
  106. data/spec/notation/model/score_spec.rb +211 -0
  107. data/spec/notation/packing/change_packing_spec.rb +153 -0
  108. data/spec/notation/packing/part_packing_spec.rb +66 -0
  109. data/spec/notation/packing/program_packing_spec.rb +33 -0
  110. data/spec/notation/packing/score_packing_spec.rb +301 -0
  111. data/spec/notation/parsing/articulation_parsing_spec.rb +23 -0
  112. data/spec/notation/parsing/convenience_methods_spec.rb +99 -0
  113. data/spec/notation/parsing/duration_nodes_spec.rb +83 -0
  114. data/spec/notation/parsing/duration_parsing_spec.rb +70 -0
  115. data/spec/notation/parsing/link_nodes_spec.rb +30 -0
  116. data/spec/notation/parsing/link_parsing_spec.rb +13 -0
  117. data/spec/notation/parsing/meter_parsing_spec.rb +23 -0
  118. data/spec/notation/parsing/note_node_spec.rb +87 -0
  119. data/spec/notation/parsing/note_parsing_spec.rb +46 -0
  120. data/spec/notation/parsing/numbers/nonnegative_float_spec.rb +28 -0
  121. data/spec/notation/parsing/numbers/nonnegative_integer_spec.rb +11 -0
  122. data/spec/notation/parsing/numbers/nonnegative_rational_spec.rb +11 -0
  123. data/spec/notation/parsing/numbers/positive_float_spec.rb +28 -0
  124. data/spec/notation/parsing/numbers/positive_integer_spec.rb +28 -0
  125. data/spec/notation/parsing/numbers/positive_rational_spec.rb +28 -0
  126. data/spec/notation/parsing/pitch_node_spec.rb +38 -0
  127. data/spec/notation/parsing/pitch_parsing_spec.rb +14 -0
  128. data/spec/notation/parsing/segment_parsing_spec.rb +27 -0
  129. data/spec/notation/util/value_computer_spec.rb +146 -0
  130. data/spec/performance/conversion/glissando_converter_spec.rb +93 -0
  131. data/spec/performance/conversion/note_sequence_extractor_spec.rb +230 -0
  132. data/spec/performance/conversion/portamento_converter_spec.rb +91 -0
  133. data/spec/performance/conversion/score_collator_spec.rb +183 -0
  134. data/spec/performance/midi/midi_util_spec.rb +110 -0
  135. data/spec/performance/midi/part_sequencer_spec.rb +40 -0
  136. data/spec/performance/midi/score_sequencer_spec.rb +50 -0
  137. data/spec/performance/model/note_sequence_spec.rb +147 -0
  138. data/spec/performance/util/note_linker_spec.rb +68 -0
  139. data/spec/performance/util/optimization_spec.rb +73 -0
  140. data/spec/spec_helper.rb +43 -0
  141. metadata +323 -0
@@ -0,0 +1,289 @@
1
+ # Autogenerated from a Treetop grammar. Edits may be lost.
2
+
3
+
4
+ module Musicality
5
+ module Parsing
6
+
7
+ module NonnegativeFloat
8
+ include Treetop::Runtime
9
+
10
+ def root
11
+ @root ||= :nonnegative_float
12
+ end
13
+
14
+ module NonnegativeFloat0
15
+ def to_f
16
+ text_value.to_f
17
+ end
18
+
19
+ alias :to_num :to_f
20
+ end
21
+
22
+ def _nt_nonnegative_float
23
+ start_index = index
24
+ if node_cache[:nonnegative_float].has_key?(index)
25
+ cached = node_cache[:nonnegative_float][index]
26
+ if cached
27
+ node_cache[:nonnegative_float][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
28
+ @index = cached.interval.end
29
+ end
30
+ return cached
31
+ end
32
+
33
+ i0 = index
34
+ r1 = _nt_float1
35
+ if r1
36
+ r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
37
+ r0 = r1
38
+ r0.extend(NonnegativeFloat0)
39
+ else
40
+ r2 = _nt_float2
41
+ if r2
42
+ r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
43
+ r0 = r2
44
+ r0.extend(NonnegativeFloat0)
45
+ else
46
+ @index = i0
47
+ r0 = nil
48
+ end
49
+ end
50
+
51
+ node_cache[:nonnegative_float][start_index] = r0
52
+
53
+ r0
54
+ end
55
+
56
+ module Float10
57
+ def exponent
58
+ elements[1]
59
+ end
60
+ end
61
+
62
+ def _nt_float1
63
+ start_index = index
64
+ if node_cache[:float1].has_key?(index)
65
+ cached = node_cache[:float1][index]
66
+ if cached
67
+ node_cache[:float1][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
68
+ @index = cached.interval.end
69
+ end
70
+ return cached
71
+ end
72
+
73
+ i0, s0 = index, []
74
+ s1, i1 = [], index
75
+ loop do
76
+ if has_terminal?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index)
77
+ r2 = true
78
+ @index += 1
79
+ else
80
+ terminal_parse_failure('[0-9]')
81
+ r2 = nil
82
+ end
83
+ if r2
84
+ s1 << r2
85
+ else
86
+ break
87
+ end
88
+ end
89
+ if s1.empty?
90
+ @index = i1
91
+ r1 = nil
92
+ else
93
+ r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
94
+ end
95
+ s0 << r1
96
+ if r1
97
+ r3 = _nt_exponent
98
+ s0 << r3
99
+ end
100
+ if s0.last
101
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
102
+ r0.extend(Float10)
103
+ else
104
+ @index = i0
105
+ r0 = nil
106
+ end
107
+
108
+ node_cache[:float1][start_index] = r0
109
+
110
+ r0
111
+ end
112
+
113
+ module Float20
114
+ end
115
+
116
+ def _nt_float2
117
+ start_index = index
118
+ if node_cache[:float2].has_key?(index)
119
+ cached = node_cache[:float2][index]
120
+ if cached
121
+ node_cache[:float2][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
122
+ @index = cached.interval.end
123
+ end
124
+ return cached
125
+ end
126
+
127
+ i0, s0 = index, []
128
+ s1, i1 = [], index
129
+ loop do
130
+ if has_terminal?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index)
131
+ r2 = true
132
+ @index += 1
133
+ else
134
+ terminal_parse_failure('[0-9]')
135
+ r2 = nil
136
+ end
137
+ if r2
138
+ s1 << r2
139
+ else
140
+ break
141
+ end
142
+ end
143
+ if s1.empty?
144
+ @index = i1
145
+ r1 = nil
146
+ else
147
+ r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
148
+ end
149
+ s0 << r1
150
+ if r1
151
+ if has_terminal?(@regexps[gr = '\A[.]'] ||= Regexp.new(gr), :regexp, index)
152
+ r3 = true
153
+ @index += 1
154
+ else
155
+ terminal_parse_failure('[.]')
156
+ r3 = nil
157
+ end
158
+ s0 << r3
159
+ if r3
160
+ s4, i4 = [], index
161
+ loop do
162
+ if has_terminal?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index)
163
+ r5 = true
164
+ @index += 1
165
+ else
166
+ terminal_parse_failure('[0-9]')
167
+ r5 = nil
168
+ end
169
+ if r5
170
+ s4 << r5
171
+ else
172
+ break
173
+ end
174
+ end
175
+ if s4.empty?
176
+ @index = i4
177
+ r4 = nil
178
+ else
179
+ r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
180
+ end
181
+ s0 << r4
182
+ if r4
183
+ r7 = _nt_exponent
184
+ if r7
185
+ r6 = r7
186
+ else
187
+ r6 = instantiate_node(SyntaxNode,input, index...index)
188
+ end
189
+ s0 << r6
190
+ end
191
+ end
192
+ end
193
+ if s0.last
194
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
195
+ r0.extend(Float20)
196
+ else
197
+ @index = i0
198
+ r0 = nil
199
+ end
200
+
201
+ node_cache[:float2][start_index] = r0
202
+
203
+ r0
204
+ end
205
+
206
+ module Exponent0
207
+ end
208
+
209
+ def _nt_exponent
210
+ start_index = index
211
+ if node_cache[:exponent].has_key?(index)
212
+ cached = node_cache[:exponent][index]
213
+ if cached
214
+ node_cache[:exponent][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
215
+ @index = cached.interval.end
216
+ end
217
+ return cached
218
+ end
219
+
220
+ i0, s0 = index, []
221
+ if (match_len = has_terminal?("e", false, index))
222
+ r1 = true
223
+ @index += match_len
224
+ else
225
+ terminal_parse_failure("e")
226
+ r1 = nil
227
+ end
228
+ s0 << r1
229
+ if r1
230
+ if has_terminal?(@regexps[gr = '\A[+-]'] ||= Regexp.new(gr), :regexp, index)
231
+ r3 = true
232
+ @index += 1
233
+ else
234
+ terminal_parse_failure('[+-]')
235
+ r3 = nil
236
+ end
237
+ if r3
238
+ r2 = r3
239
+ else
240
+ r2 = instantiate_node(SyntaxNode,input, index...index)
241
+ end
242
+ s0 << r2
243
+ if r2
244
+ s4, i4 = [], index
245
+ loop do
246
+ if has_terminal?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index)
247
+ r5 = true
248
+ @index += 1
249
+ else
250
+ terminal_parse_failure('[0-9]')
251
+ r5 = nil
252
+ end
253
+ if r5
254
+ s4 << r5
255
+ else
256
+ break
257
+ end
258
+ end
259
+ if s4.empty?
260
+ @index = i4
261
+ r4 = nil
262
+ else
263
+ r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
264
+ end
265
+ s0 << r4
266
+ end
267
+ end
268
+ if s0.last
269
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
270
+ r0.extend(Exponent0)
271
+ else
272
+ @index = i0
273
+ r0 = nil
274
+ end
275
+
276
+ node_cache[:exponent][start_index] = r0
277
+
278
+ r0
279
+ end
280
+
281
+ end
282
+
283
+ class NonnegativeFloatParser < Treetop::Runtime::CompiledParser
284
+ include NonnegativeFloat
285
+ end
286
+
287
+
288
+ end
289
+ end
@@ -0,0 +1,29 @@
1
+ module Musicality
2
+ module Parsing
3
+
4
+ grammar NonnegativeFloat
5
+ rule nonnegative_float
6
+ (float1 / float2) {
7
+ def to_f
8
+ text_value.to_f
9
+ end
10
+
11
+ alias :to_num :to_f
12
+ }
13
+ end
14
+
15
+ rule float1
16
+ [0-9]+ exponent
17
+ end
18
+
19
+ rule float2
20
+ [0-9]+ [.] [0-9]+ exponent?
21
+ end
22
+
23
+ rule exponent
24
+ "e" [+-]? [0-9]+
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,64 @@
1
+ # Autogenerated from a Treetop grammar. Edits may be lost.
2
+
3
+
4
+ module Musicality
5
+ module Parsing
6
+
7
+ module NonnegativeInteger
8
+ include Treetop::Runtime
9
+
10
+ def root
11
+ @root ||= :nonnegative_integer
12
+ end
13
+
14
+ module NonnegativeInteger0
15
+ def to_i
16
+ text_value.to_i
17
+ end
18
+
19
+ alias :to_num :to_i
20
+ end
21
+
22
+ def _nt_nonnegative_integer
23
+ start_index = index
24
+ if node_cache[:nonnegative_integer].has_key?(index)
25
+ cached = node_cache[:nonnegative_integer][index]
26
+ if cached
27
+ node_cache[:nonnegative_integer][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
28
+ @index = cached.interval.end
29
+ end
30
+ return cached
31
+ end
32
+
33
+ s0, i0 = [], index
34
+ loop do
35
+ if has_terminal?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index)
36
+ r1 = true
37
+ @index += 1
38
+ else
39
+ terminal_parse_failure('[0-9]')
40
+ r1 = nil
41
+ end
42
+ if r1
43
+ s0 << r1
44
+ else
45
+ break
46
+ end
47
+ end
48
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
49
+ r0.extend(NonnegativeInteger0)
50
+
51
+ node_cache[:nonnegative_integer][start_index] = r0
52
+
53
+ r0
54
+ end
55
+
56
+ end
57
+
58
+ class NonnegativeIntegerParser < Treetop::Runtime::CompiledParser
59
+ include NonnegativeInteger
60
+ end
61
+
62
+
63
+ end
64
+ end
@@ -0,0 +1,17 @@
1
+ module Musicality
2
+ module Parsing
3
+
4
+ grammar NonnegativeInteger
5
+ rule nonnegative_integer
6
+ [0-9]* {
7
+ def to_i
8
+ text_value.to_i
9
+ end
10
+
11
+ alias :to_num :to_i
12
+ }
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,86 @@
1
+ # Autogenerated from a Treetop grammar. Edits may be lost.
2
+
3
+
4
+ module Musicality
5
+ module Parsing
6
+
7
+ module NonnegativeRational
8
+ include Treetop::Runtime
9
+
10
+ def root
11
+ @root ||= :nonnegative_rational
12
+ end
13
+
14
+ include NonnegativeInteger
15
+
16
+ include PositiveInteger
17
+
18
+ module NonnegativeRational0
19
+ def nonnegative_integer
20
+ elements[0]
21
+ end
22
+
23
+ def positive_integer
24
+ elements[2]
25
+ end
26
+ end
27
+
28
+ module NonnegativeRational1
29
+ def to_r
30
+ text_value.to_r
31
+ end
32
+
33
+ alias :to_num :to_r
34
+ end
35
+
36
+ def _nt_nonnegative_rational
37
+ start_index = index
38
+ if node_cache[:nonnegative_rational].has_key?(index)
39
+ cached = node_cache[:nonnegative_rational][index]
40
+ if cached
41
+ node_cache[:nonnegative_rational][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
42
+ @index = cached.interval.end
43
+ end
44
+ return cached
45
+ end
46
+
47
+ i0, s0 = index, []
48
+ r1 = _nt_nonnegative_integer
49
+ s0 << r1
50
+ if r1
51
+ if (match_len = has_terminal?("/", false, index))
52
+ r2 = true
53
+ @index += match_len
54
+ else
55
+ terminal_parse_failure("/")
56
+ r2 = nil
57
+ end
58
+ s0 << r2
59
+ if r2
60
+ r3 = _nt_positive_integer
61
+ s0 << r3
62
+ end
63
+ end
64
+ if s0.last
65
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
66
+ r0.extend(NonnegativeRational0)
67
+ r0.extend(NonnegativeRational1)
68
+ else
69
+ @index = i0
70
+ r0 = nil
71
+ end
72
+
73
+ node_cache[:nonnegative_rational][start_index] = r0
74
+
75
+ r0
76
+ end
77
+
78
+ end
79
+
80
+ class NonnegativeRationalParser < Treetop::Runtime::CompiledParser
81
+ include NonnegativeRational
82
+ end
83
+
84
+
85
+ end
86
+ end
@@ -0,0 +1,20 @@
1
+ module Musicality
2
+ module Parsing
3
+
4
+ grammar NonnegativeRational
5
+ include NonnegativeInteger
6
+ include PositiveInteger
7
+
8
+ rule nonnegative_rational
9
+ nonnegative_integer "/" positive_integer {
10
+ def to_r
11
+ text_value.to_r
12
+ end
13
+
14
+ alias :to_num :to_r
15
+ }
16
+ end
17
+ end
18
+
19
+ end
20
+ end