tonal-tools 1.0.4 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f6ae36a205038f24fa661fa8a7ede3bb360e2c5241b980cfb356f394d06f92c0
4
- data.tar.gz: d86932650896d5e8e765ff3de65b78b1bdeca2db70e9c2b7a0a57ca6ae763bb3
3
+ metadata.gz: 540d38c024465fdb45af2fbaada5a4fc020857ca03fc9c9e56f6152462e5d38e
4
+ data.tar.gz: 58637a5d53fe59d3a5feab46e587b3ae08c4d8d837aa3410b5b21d684f90fc12
5
5
  SHA512:
6
- metadata.gz: b2eff196352f633616155a0730abd04ff134b6157dbf9a34234d3fb59f12d659431509d6f8f462f326a80fc25e5ad97496f6b866c45961592ebe9826d20066c0
7
- data.tar.gz: 1ccd7aecfb974180d56909535c43cce03cb4cb872b3991264b594c38eb23a496ad83139123586b4999ff5274193ef82f78f9a234f088855c5853108bbfb9fbea
6
+ metadata.gz: d3e97921221dc86faeeae926b23af4c7ed22da2d2c26bc1377493d6442cb9dcafaa2ab60ee430b5b804e550fbfaa6e4c19c8b2379c2941b1d4407f7000649845
7
+ data.tar.gz: e5850e74a54e375834e7b578e2438146907a6a9107e6b95e72366a531f92cdab734f4d273ac8be48877d0c19ca36940dc2acf9eb3f4ded6baadf4b46eb21c54d
@@ -5,54 +5,61 @@ class Prime
5
5
  # @param lower bound
6
6
  # @param upper bound
7
7
  #
8
- def self.within(lower, upper)
9
- self.each(upper).reject{|p| p < lower}
10
- end
8
+ def self.within(lower=0, upper) = self.each(upper).reject{|p| p < lower}
11
9
  end
12
10
 
13
11
  class Numeric
12
+ # @return [Numeric] translated modularly
13
+ # @example
14
+ # Math::PI.modulo_translate(-3, 3) => -2.858407346410207
15
+ # @param lower the lower bound of the modulo range
16
+ # @param upper the upper bound of the modulo range
17
+ #
18
+ def modulo_translate(lower=0, upper)
19
+ range = (upper - lower) == 0 ? 1 : upper - lower
20
+ (self - lower) % range + lower
21
+ end
22
+
14
23
  # @return [Array] a tuple of self offset positively/negatively
15
24
  # @example
16
25
  # Math::PI.plus_minus(3)
17
26
  # => [6.141592653589793, 0.14159265358979312]
18
27
  # @param offset plus and minus distance from self
19
28
  #
20
- def plus_minus(offset)
21
- [self + offset, self - offset]
22
- end
29
+ def plus_minus(offset) = [self + offset, self - offset]
30
+ alias :min_plus :plus_minus
31
+
32
+ # @return [Array] a tuple of self divided and multiplied by factor
33
+ # @example
34
+ # Math::PI.div_times(3) => [1.0471975511965976, 9.42477796076938]
35
+ # @param [Numeric]
36
+ #
37
+ def div_times(factor) = [self / factor, self * factor]
23
38
 
24
39
  # @return [Tonal::ReducedRatio] the octave reduced ratio of self
25
40
  # @example
26
41
  # (2**(1.0/12)).ratio => (4771397596969315/4503599627370496)
27
42
  #
28
- def to_ratio(reduced: true, equave: 2/1r)
29
- reduced ? Tonal::ReducedRatio.new(self, equave: equave) : Tonal::Ratio.new(self, equave: equave)
30
- end
43
+ def to_ratio(reduced: true, equave: 2/1r) = reduced ? Tonal::ReducedRatio.new(self, equave: equave) : Tonal::Ratio.new(self, equave: equave)
31
44
  alias :ratio :to_ratio
32
45
 
33
46
  # @return [Float], the degrees on a circle of self
34
47
  # @example
35
48
  # (2**(6.0/12)).period_degrees => 180.0
36
49
  #
37
- def period_degrees
38
- self.ratio.period_degrees
39
- end
50
+ def period_degrees = self.ratio.period_degrees
40
51
 
41
52
  # @return [Tonal::Log] the log of self to the given base
42
53
  # @example
43
54
  # (3/2r).log(10) => 0.17609125905568124
44
55
  #
45
- def log(base)
46
- Tonal::Log.new(logarithmand: self, base: base)
47
- end
56
+ def log(base) = Tonal::Log.new(logarithmand: self, base: base)
48
57
 
49
58
  # @return [Tonal::Log2] the log2 of self
50
59
  # @example
51
60
  # (3/2r).log2 => 0.5849625007211562
52
61
  #
53
- def log2
54
- Tonal::Log2.new(logarithmand: self)
55
- end
62
+ def log2 = Tonal::Log2.new(logarithmand: self)
56
63
  alias :to_log2 :log2
57
64
  alias :span :log2
58
65
 
@@ -60,31 +67,23 @@ class Numeric
60
67
  # @example
61
68
  # 700.0.cents => 700.0
62
69
  #
63
- def cents
64
- Tonal::Cents.new(cents: self)
65
- end
70
+ def cents = Tonal::Cents.new(cents: self)
66
71
 
67
72
  # @return [Tonal::Cents] of self interpreted as a cents quantity
68
73
  # @example
69
74
  # 700.0.¢ => 700.0
70
75
  #
71
- def ¢
72
- cents
73
- end
76
+ def ¢ = cents
74
77
 
75
78
  # @return [Tonal::Cents] of self interpreted as a ratio
76
79
  # @example
77
80
  # (3/2r).to_cents => 701.96
78
81
  #
79
- def to_cents
80
- self.log2.to_cents
81
- end
82
+ def to_cents = self.log2.to_cents
82
83
 
83
84
  # @return [Tonal::Hertz] of self
84
85
  #
85
- def hz
86
- Tonal::Hertz.new(self)
87
- end
86
+ def hz = Tonal::Hertz.new(self)
88
87
  alias :to_hz :hz
89
88
 
90
89
  # @return [Step] the step of self in the given modulo
@@ -92,133 +91,89 @@ class Numeric
92
91
  # (5/4r).step(12) => 4\12
93
92
  # @param modulo
94
93
  #
95
- def step(modulo=12)
96
- to_log2.step(modulo)
97
- end
94
+ def step(modulo=12) = to_log2.step(modulo)
98
95
 
99
96
  # @return [Float] the log product complexity of self
100
97
  # @example
101
- # (3/2r).tenney_height => 2.584962500721156
98
+ # (3/2r).benedetti_height => 6
102
99
  #
103
- def benedetti_height
104
- self.ratio.benedetti_height
105
- end
100
+ def benedetti_height = self.ratio.benedetti_height
106
101
  alias :product_complexity :benedetti_height
107
102
 
108
103
  # @return [Integer] the product complexity of self
109
104
  # @example
110
- # (3/2r).benedetti_height => 6
105
+ # (3/2r).tenney_height => 2.584962500721156
111
106
  #
112
- def tenney_height
113
- self.ratio.tenney_height
114
- end
107
+ def tenney_height = self.ratio.tenney_height
115
108
  alias :log_product_complexity :tenney_height
116
109
 
117
110
  # @return [Integer] the Weil height
118
111
  # @example
119
112
  # (3/2r).weil_height => 3
120
113
  #
121
- def weil_height
122
- self.ratio.weil_height
123
- end
114
+ def weil_height = self.ratio.weil_height
124
115
 
125
116
  # @return [Tonal::Log2] the log of Weil height
126
117
  # @example
127
118
  # (3/2r).log_weil_height => 1.5849625007211563
128
119
  #
129
- def log_weil_height
130
- self.ratio.log_weil_height
131
- end
120
+ def log_weil_height = self.ratio.log_weil_height
132
121
 
133
122
  # @return [Integer] the Wilson height
134
123
  # @example (14/9r).wilson_height => 13
135
124
  #
136
- def wilson_height(reduced: true, equave: 2/1r, prime_rejects: [2])
137
- self.ratio(reduced: reduced, equave: equave).wilson_height(prime_rejects: prime_rejects)
138
- end
125
+ def wilson_height(reduced: true, equave: 2/1r, prime_rejects: [2]) = self.ratio(reduced: reduced, equave: equave).wilson_height(prime_rejects: prime_rejects)
139
126
 
140
127
  # @return [Float] the cents difference between self and its step in the given modulo
141
128
  # @example
142
129
  # (3/2r).efficiency(12) => -1.955000865387433
143
130
  # @param modulo
144
131
  #
145
- def efficiency(modulo)
146
- (Tonal::Cents::CENT_SCALE * step(modulo).step / modulo.to_f) - to_cents
147
- end
132
+ def efficiency(modulo) = (Tonal::Cents::CENT_SCALE * step(modulo).step / modulo.to_f) - to_cents
148
133
 
149
134
  # @return [Interval] beween self (upper) and ratio (lower)
150
135
  # @example
151
136
  # (133).interval_with(3/2r) => 133/96 (133/128 / 3/2)
152
137
  # @param ratio
153
138
  #
154
- def interval_with(ratio)
155
- Tonal::Interval.new(self.ratio, ratio)
156
- end
139
+ def interval_with(ratio) = Tonal::Interval.new(self.ratio, ratio)
157
140
 
158
141
  # @return [Vector], self represented as a prime vector
159
142
  # @example
160
143
  # (3/2r).prime_vector => Vector[-1, 1]
161
144
  #
162
- def prime_vector
163
- self.ratio.prime_vector
164
- end
145
+ def prime_vector = self.ratio.prime_vector
165
146
  alias :monzo :prime_vector
166
147
 
167
148
  # @return [Array], self decomposed into its prime factors
168
149
  # @example
169
150
  # (31/30r).prime_divisions => [[[31, 1]], [[2, 1], [3, 1], [5, 1]]]
170
151
  #
171
- def prime_divisions
172
- self.ratio.prime_divisions
173
- end
152
+ def prime_divisions = self.ratio.prime_divisions
174
153
 
175
154
  # @return [Integer] the maximum prime factor of self
176
155
  # @example
177
156
  # (31/30r).max_prime => 31
178
157
  #
179
- def max_prime
180
- prime_divisions.flatten(1).map(&:first).max
181
- end
158
+ def max_prime = prime_divisions.flatten(1).map(&:first).max
182
159
 
183
160
  # @return [Integer] the minimum prime factor of self
184
161
  # @example
185
162
  # (31/30r).min_prime => 2
186
163
  #
187
- def min_prime
188
- prime_divisions.flatten(1).map(&:first).min
189
- end
190
-
191
- # @return [Integer] the product complexity of self
192
- # @example
193
- # (3/2r).benedetti_height => 6
194
- #
195
- def benedetti_height
196
- numerator * denominator
197
- end
198
-
199
- # @return [Float] the log product complexity of self
200
- # @example
201
- # (3/2r).tenney_height => 2.584962500721156
202
- #
203
- def tenney_height
204
- Tonal::Log2.new(logarithmand: benedetti_height)
205
- end
164
+ def min_prime = prime_divisions.flatten(1).map(&:first).min
206
165
 
207
166
  # @return [Tonal::ReducedRatio], the Ernst Levy negative of self
208
167
  # @example
209
168
  # (7/4r).negative => (12/7)
210
169
  #
211
- def negative
212
- self.ratio.negative
213
- end
170
+ def negative = self.ratio.negative
214
171
 
215
172
  # @return [Tonal::ReducedRatio], the ratio rotated on the given axis, default 1/1
216
173
  # @example
217
174
  # (3/2r).mirror => (4/3)
218
175
  #
219
- def mirror(axis=1/1r)
220
- self.ratio.mirror(axis)
221
- end
176
+ def mirror(axis=1/1r) = self.ratio.mirror(axis)
222
177
  end
223
178
 
224
179
  class Rational
@@ -226,34 +181,26 @@ class Rational
226
181
  # @example
227
182
  # (3/2r).to_vector => Vector[3, 2]
228
183
  #
229
- def to_vector
230
- Vector[self.numerator, self.denominator]
231
- end
184
+ def to_vector = Vector[self.numerator, self.denominator]
232
185
  alias :vector :to_vector
233
186
 
234
187
  # @return [Array], self decomposed into its prime factors
235
188
  # @example
236
189
  # (31/30r).prime_divisions => [[[31, 1]], [[2, 1], [3, 1], [5, 1]]]
237
190
  #
238
- def prime_divisions
239
- self.ratio.prime_divisions
240
- end
191
+ def prime_divisions = self.ratio.prime_divisions
241
192
 
242
193
  # @return [Integer] the maximum prime factor of self
243
194
  # @example
244
195
  # (31/30r).max_prime => 31
245
196
  #
246
- def max_prime
247
- self.ratio.max_prime
248
- end
197
+ def max_prime = self.ratio.max_prime
249
198
 
250
199
  # @return [Integer] the minimum prime factor of self
251
200
  # @example
252
201
  # (31/30r).min_prime => 2
253
202
  #
254
- def min_prime
255
- self.ratio.min_prime
256
- end
203
+ def min_prime = self.ratio.min_prime
257
204
  end
258
205
 
259
206
  class Integer
@@ -263,34 +210,26 @@ class Integer
263
210
  # @example
264
211
  # 72.max_prime => 3
265
212
  #
266
- def max_prime
267
- self.prime_division.map(&:first).max
268
- end
213
+ def max_prime = self.prime_division.map(&:first).max
269
214
 
270
215
  # @return [Integer] the minimum prime factor of self
271
216
  # @example
272
217
  # 72.min_prime => 2
273
218
  #
274
- def min_prime
275
- self.prime_division.map(&:first).min
276
- end
219
+ def min_prime = self.prime_division.map(&:first).min
277
220
 
278
221
  # @return [Integer] the factorial of self
279
222
  # @example
280
223
  # 5.factorial => 120
281
224
  #
282
- def factorial
283
- (2..self).reduce(1, :*)
284
- end
225
+ def factorial = (2..self).reduce(1, :*)
285
226
 
286
227
  # @return [Boolean] if self is coprime with i
287
228
  # @example
288
229
  # 25.coprime?(7) => true
289
230
  # 25.coprime?(5) => false
290
231
  #
291
- def coprime?(i)
292
- self.gcd(i) == 1
293
- end
232
+ def coprime?(i) = self.gcd(i) == 1
294
233
 
295
234
  # @return [Array] list of integers that are coprime with self, up to the value of self
296
235
  # @example
@@ -308,9 +247,7 @@ class Integer
308
247
  # @example
309
248
  # 10.phi => 4
310
249
  #
311
- def phi
312
- coprimes.count
313
- end
250
+ def phi = coprimes.count
314
251
  alias :totient :phi
315
252
 
316
253
  # @return [Array] of integers that are n-smooth with self
@@ -358,43 +295,33 @@ class Array
358
295
  # @param min_size
359
296
  # @param value
360
297
  #
361
- def rpad(min_size, value = nil)
362
- self.dup.rpad!(min_size, value)
363
- end
298
+ def rpad(min_size, value = nil) = self.dup.rpad!(min_size, value)
364
299
 
365
300
  # @return [Vector] self converted to a vector
366
301
  # @example
367
302
  # [3,2].to_vector => Vector[3, 2]
368
303
  #
369
- def to_vector
370
- Vector[*self]
371
- end
304
+ def to_vector = Vector[*self]
372
305
  alias :vector :to_vector
373
306
 
374
307
  # @return [Integer] least common multiple of integer elements of self
375
308
  # @example
376
309
  # [3, 2, 7].lcm => 42
377
310
  #
378
- def lcm
379
- self.reduce(1, :lcm)
380
- end
311
+ def lcm = self.reduce(1, :lcm)
381
312
 
382
313
  # @return [Array] of numerators of elements of self
383
314
  # @example
384
315
  # [3/2r, 5/4r].numerators => [3, 5]
385
316
  #
386
- def numerators
387
- self.map(&:numerator)
388
- end
317
+ def numerators = self.map(&:numerator)
389
318
  alias :antecedents :numerators
390
319
 
391
320
  # @return [Array] of denominators of elements of self
392
321
  # @example
393
322
  # [Tonal::Ratio.new(3,2), Tonal::Ratio.new(5,4)].denominators => [2, 4]
394
323
  #
395
- def denominators
396
- self.map(&:denominator)
397
- end
324
+ def denominators = self.map(&:denominator)
398
325
  alias :consequents :denominators
399
326
 
400
327
  # @return [Array] an array of normalized ratios
@@ -410,25 +337,57 @@ class Array
410
337
  # @example
411
338
  # [3/2r, 4/3r].to_cents => [701.96, 498.04]
412
339
  #
413
- def to_cents
414
- self.map{|r| r.to_cents}
415
- end
340
+ def to_cents = self.map{|r| r.to_cents}
416
341
  alias :cents :to_cents
417
342
 
418
343
  # @return [Float] the mean of the elements of self
419
344
  # @example
420
345
  # [1, 2].mean => 1.5
421
346
  #
422
- def mean
423
- self.sum / self.count.to_f
424
- end
347
+ def mean = self.sum / self.count.to_f
425
348
 
426
349
  # @return [Tonal::ReducedRatio] ratio reconstructed from the result of a prime factor decomposition
427
350
  # @example
428
351
  # [[[3, 1]], [[2, 1]]].ratio_from_prime_divisions => (3/2)
429
352
  #
430
- def ratio_from_prime_divisions
431
- Tonal::Ratio.new(Prime.int_from_prime_division(self.first), Prime.int_from_prime_division(self.last))
353
+ def ratio_from_prime_divisions = Tonal::Ratio.new(Prime.int_from_prime_division(self.first), Prime.int_from_prime_division(self.last))
354
+
355
+ # @return [Array] translated by value
356
+ # @example
357
+ # [0.24184760813024642, 0.49344034900361244, 0.07231824070126536].translate(-0.07231824070126536) = [0.16952936742898106, 0.4211221083023471, 0.0]
358
+ # @param value [Numeric] the value that is translating self
359
+ #
360
+ def translate(value) = self.map{|e| e + value}
361
+
362
+
363
+ # @return [Array] rescaled by new minimum and new maximum
364
+ # @example
365
+ # [0.47943068514319154, 0.7161083818132802, 0.19855867360591783].rescale(0,3)
366
+ # => [1.6280871600341376, 3.0, 0.0]
367
+ # @param new_min
368
+ # @param new_max
369
+ #
370
+ def rescale(new_min=0, new_max)
371
+ old_min = min
372
+ old_max = max
373
+
374
+ self.map do |x|
375
+ new_min + ((x - old_min) * (new_max - new_min)) / (old_max - old_min)
376
+ end
377
+ end
378
+
379
+ # @return [Array] translated modularly
380
+ # @example
381
+ # [-6.617469071022061, 4.755369851099594, 7.588140911919945, -6.49706614430203].modulo_translate(-3, 5)
382
+ # => [2.382530928977939, 4.755369851099594, -1.411859088080055, 2.50293385569797]
383
+ # @param lower the lower bound of the modulo range
384
+ # @param upper the upper bound of the modulo range
385
+ #
386
+ def modulo_translate(lower=0, upper)
387
+ range = upper - lower + 1
388
+ map do |value|
389
+ (value - lower) % range + lower
390
+ end
432
391
  end
433
392
  end
434
393
 
@@ -439,9 +398,7 @@ class Vector
439
398
  # @param reduced
440
399
  # @param equave
441
400
  #
442
- def to_ratio(reduced: true, equave: 2/1r)
443
- reduced ? Tonal::ReducedRatio.new(*self, equave: equave) : Tonal::Ratio.new(*self, equave: equave)
444
- end
401
+ def to_ratio(reduced: true, equave: 2/1r) = reduced ? Tonal::ReducedRatio.new(*self, equave: equave) : Tonal::Ratio.new(*self, equave: equave)
445
402
  alias :ratio :to_ratio
446
403
  end
447
404
 
@@ -451,9 +408,7 @@ module Math
451
408
  # Math.factorial(10) => 3628800
452
409
  # @param limit
453
410
  #
454
- def self.factorial(limit)
455
- (2..limit).reduce(1, :*)
456
- end
411
+ def self.factorial(limit) = (2..limit).reduce(1, :*)
457
412
 
458
413
  PHI = (1 + 5**(1.0/2))/2
459
414
  end
data/lib/tonal/ratio.rb CHANGED
@@ -456,6 +456,7 @@ class Tonal::Ratio
456
456
  ratio = ratio.ratio
457
457
  [self - ratio, self + ratio]
458
458
  end
459
+ alias :min_plus :plus_minus
459
460
 
460
461
  # @return [Cents] cent difference between self and other ratio
461
462
  # @example
@@ -482,6 +483,7 @@ class Tonal::Ratio
482
483
  def inspect
483
484
  "(#{antecedent}/#{consequent})"
484
485
  end
486
+ alias :to_s :inspect
485
487
 
486
488
  def +(rhs)
487
489
  operate(rhs, :+)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tonal-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jose Hales-Garcia
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-22 00:00:00.000000000 Z
11
+ date: 2024-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: yaml
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '1.0'
103
+ version: '1.1'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '1.0'
110
+ version: '1.1'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rspec
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -174,7 +174,8 @@ homepage: https://mtonal.github.io/tools/
174
174
  licenses:
175
175
  - MIT
176
176
  metadata:
177
- source_code_uri: https://github.com/mTonal/tools
177
+ source_code_uri: https://github.com/mTonal/tools/
178
+ documentation_uri: https://mtonal.github.io/tools/
178
179
  post_install_message:
179
180
  rdoc_options: []
180
181
  require_paths:
@@ -190,7 +191,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
191
  - !ruby/object:Gem::Version
191
192
  version: '3.1'
192
193
  requirements: []
193
- rubygems_version: 3.5.1
194
+ rubygems_version: 3.5.4
194
195
  signing_key:
195
196
  specification_version: 4
196
197
  summary: Tonal tools