magick 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4826f852b57d6f69bbf1d1d1c4671174e3b3d68dae520b5fd09f43a7c2ba2bac
4
- data.tar.gz: 0d56f6b3d4c9a6ec5fe45759695375700aacdedc28dcd9b1dccc23c06e9bff37
3
+ metadata.gz: b0239f6b8fc615275fa674559061c52c111913e971a49b3ab292630cca826b96
4
+ data.tar.gz: fa2a9c746508d7d10d89d883a84745509435e8ca2e931f8b862ef9a0409ec184
5
5
  SHA512:
6
- metadata.gz: ebe917fea532e9cd78d94e247120278f9f155cb857ff0daaea8f9538342a33fefff6e8a3c813180763845fd822efababcfaa0d70a0101d5b665becded5815a46
7
- data.tar.gz: 88573678ce6d983164280c784f14dd285f1136c0354cc1c40a3c92df1538637ea909b5f9ad4d1098a32eb067ec34a2b6a08a5058839d4d3a17aa0080115a09fb
6
+ metadata.gz: 16881788b5f302b8a6a06276351ec676e65cd97c21818347ce76910190e7068cce0cb52dc0338d28cbb1d5f747d64ab2129b3f71b19d482e917c00ae7497eeeb
7
+ data.tar.gz: 077b86c81e1e46d236fea5b4ed40492d9f646ae89da69c89987a5fdc1d0e7c6587b6c5a11a80a69e5b7797297ee5a12910537cb98278d5091ec38eee71172de2
data/lib/magick/loops.rb CHANGED
@@ -31,6 +31,7 @@ module Magick
31
31
  }
32
32
  end
33
33
 
34
+ # sum and length both assume they will be given a list
34
35
  def sum = fold.(Magick::Maths::add).(0)
35
36
 
36
37
  def length = fold.(->(acc) { ->(elem) { acc + 1 }}).(0)
data/lib/magick/maths.rb CHANGED
@@ -11,21 +11,30 @@ module Magick
11
11
  def subtract = ->(x){ ->(y) { add.(x).(negate.(y)) }}
12
12
 
13
13
  def multiply
14
- power.(add)
14
+ power_2.(add)
15
15
  end
16
16
  alias :mult :multiply
17
17
 
18
+ # See note on `mod`
18
19
  def divide
19
20
  Smullyan::Birds::Y.(->(f){
20
21
  ->(n){
21
22
  ->(d){
22
- n < d ? 0 : 1 + f.(n - d).(d)
23
+ n < d ? 0 : 1 + f.(subtract.(n).(d)).(d)
23
24
  }
24
25
  }
25
26
  })
26
27
  end
27
28
  alias :div :divide
28
29
 
30
+ def div
31
+ ->(n){
32
+ ->(d){
33
+ n/d
34
+ }
35
+ }
36
+ end
37
+
29
38
  def div_to_f
30
39
  ->(n){
31
40
  ->(d){
@@ -37,18 +46,23 @@ module Magick
37
46
  }
38
47
  end
39
48
 
49
+ # This implementation of mod _works_ but is mostly
50
+ # provided as a curiousity: ie, how could we implement
51
+ # modulus with the Y combinator and repeated subtraction?
52
+ # It isn't efficient, as you will find if you ever try, say,
53
+ # mod.(65536).(2)
40
54
  def mod
41
55
  Smullyan::Birds::Y.(->(f){
42
56
  ->(n){
43
57
  ->(d){
44
- n < d ? n : f.(n - d).(d)
58
+ n < d ? n : f.(subtract.(n).(d)).(d)
45
59
  }
46
60
  }
47
61
  })
48
62
  end
49
63
 
50
64
  def exp
51
- power.(multiply)
65
+ power_2.(multiply)
52
66
  end
53
67
 
54
68
  def power
@@ -63,8 +77,8 @@ module Magick
63
77
  ->(b) {
64
78
  ->(e) {
65
79
  e == 1 ? b :
66
- mod.(e).(2) == 0 ? f.(op.(b).(b)).(divide.(e).(2)) :
67
- op.(f.(op.(b).(b)).(divide.(e).(2))).(b)
80
+ mod.(e).(2) == 0 ? f.(op.(b).(b)).(div.(e).(2)) :
81
+ op.(f.(op.(b).(b)).(div.(e).(2))).(b)
68
82
  }
69
83
  }
70
84
  }).(base).(exponent)
@@ -73,6 +87,62 @@ module Magick
73
87
  }
74
88
  end
75
89
 
90
+ # power, as written, will have a stack trace error if we try to
91
+ # do something like power.(mult).(2).(32)
92
+ # If we eliminate the recursion, we can avoid this, but it means we need
93
+ # to use some regular Ruby constructs (eg, `while`, instead of the Y combinator)
94
+ # The following is essentially how Stepanov & McJones define `power` in
95
+ # Elements of Programming
96
+ def power_accumulate_positive
97
+ ->(op){
98
+ ->(r){
99
+ ->(a){
100
+ ->(n){
101
+ while (true)
102
+ if n % 2 != 0
103
+ r = op.(r).(a)
104
+ return r if n == 1
105
+ end
106
+ a = op.(a).(a)
107
+ n = div.(n).(2)
108
+ end
109
+ }
110
+ }
111
+ }
112
+ }
113
+ end
114
+
115
+ def power_accumulate
116
+ ->(op){
117
+ ->(r){
118
+ ->(n){
119
+ ->(a){
120
+ return r if n == 0
121
+ power_accumulate_positive.(op).(r).(n).(a)
122
+ }
123
+ }
124
+ }
125
+ }
126
+ end
127
+
128
+ def power_2
129
+ ->(op){
130
+ ->(b){
131
+ ->(e){
132
+ while (e % 2 == 0)
133
+ b = op.(b).(b)
134
+ e = e/2
135
+ end
136
+ e = e/2
137
+ return b if e == 0
138
+ power_accumulate.(op).(b).(op.(b).(b)).(e)
139
+ }
140
+ }
141
+ }
142
+ end
143
+
144
+ # average expects an array
145
+ # eg: average.([1,2,3]) => 2.0
76
146
  def average
77
147
  Smullyan::Birds::Phi.
78
148
  (Magick::Maths::div_to_f).
@@ -80,19 +150,24 @@ module Magick
80
150
  (Magick::Loops::length)
81
151
  end
82
152
 
83
- def powers_of_two = power.(multiply).(2)
153
+ def powers_of_two = exp.(2)
84
154
 
85
155
  # x and y are pairs of ints
86
156
  def fibonacci_matrix_multiply = ->(x){
87
157
  ->(y){
88
- [x[0] * (y[1] + y[0]) + x[1] * y[0], x[0] * y[0] + x[1] * y[1]]
158
+ [
159
+ x[0] * (y[1] + y[0]) +
160
+ x[1] * y[0],
161
+ x[0] * y[0] +
162
+ x[1] * y[1]
163
+ ]
89
164
  }
90
165
  }
91
166
 
92
167
  def fibonacci
93
168
  ->(n){
94
169
  n == 0 ? 0 :
95
- power.(fibonacci_matrix_multiply).([1,0]).(n)[0]
170
+ power_2.(fibonacci_matrix_multiply).([1,0]).(n)[0]
96
171
  }
97
172
  end
98
173
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Magick
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.3"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: magick
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phil Crissman