magick 0.1.0 → 0.1.2

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: e8d6e452deba31a7756fb5d9fbb58f11a5e6be0050c7fd66728f08235707a798
4
- data.tar.gz: 40fc7e21adc03fac84f439a41f25ad23e778ecc50e5a438ac27aeac791abed79
3
+ metadata.gz: 5ae8b9cd9f9526ea3adac12fd63ab30cd38895c035493a3f4866c83d25df015b
4
+ data.tar.gz: d60e88dbedd1c8d9c7bedf778beeefed2c3012678ce5022a741c02471ba76abd
5
5
  SHA512:
6
- metadata.gz: 3d13d4e771af6db5087d66ac1f8336411d3b00232d9abbfe790df6da8b454fb83ec5ecf6f238708b4ee72a23263fa8a62d6f26e2384f2febea8f16ee36b1bb92
7
- data.tar.gz: 219f308752938b16d27fd1b6c35832dff2e2e2054cf21fe37c086b683b24801a5c4948ea8295fddc295357657e6ed6c9b4aadd27bbf401e5e9483e9eada96a5d
6
+ metadata.gz: 9f033baf4e66b21b0c542d7f99ab95a717fb864acb48e5f51ba06e3c7eec9cd8e68f3d659272942fe4ffb487c618bb563e2b6c6765f4e016e196826cfd6cc45b
7
+ data.tar.gz: c967a3d6c062ee01b0f804cae609d8f281d4a33f66ba7449edaf2a08f8c505f52607090f769811c1db205745bf458bebdcd506cacfadc2f29b6295b3acf74bf9
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
@@ -1,9 +1,9 @@
1
1
  # maths
2
2
 
3
- # for addition, we'll just use Ruby
4
3
  module Magick
5
4
  module Maths
6
5
  class << self
6
+ # for addition, we'll just use Ruby
7
7
  def add = ->(x){ ->(y) { x + y }}
8
8
 
9
9
  def negate = ->(x) { -x }
@@ -11,11 +11,7 @@ module Magick
11
11
  def subtract = ->(x){ ->(y) { add.(x).(negate.(y)) }}
12
12
 
13
13
  def multiply
14
- ->(a){
15
- ->(b){
16
- power.(a).(b).(add)
17
- }
18
- }
14
+ power_2.(add)
19
15
  end
20
16
  alias :mult :multiply
21
17
 
@@ -30,6 +26,17 @@ module Magick
30
26
  end
31
27
  alias :div :divide
32
28
 
29
+ def div_to_f
30
+ ->(n){
31
+ ->(d){
32
+ # in order to get a float, we'll just
33
+ # use Ruby's `/` operator, and make sure
34
+ # at least one argument is cast to float.
35
+ n / d.to_f
36
+ }
37
+ }
38
+ end
39
+
33
40
  def mod
34
41
  Smullyan::Birds::Y.(->(f){
35
42
  ->(n){
@@ -41,11 +48,7 @@ module Magick
41
48
  end
42
49
 
43
50
  def exp
44
- ->(a){
45
- ->(b){
46
- power.(a).(b).(multiply)
47
- }
48
- }
51
+ power_2.(multiply)
49
52
  end
50
53
 
51
54
  def power
@@ -53,9 +56,9 @@ module Magick
53
56
  # operation. Powers of addition is equivalent
54
57
  # to multiplication; powers of multiplication
55
58
  # is equivalent to exponentiation
56
- ->(base) {
57
- ->(exponent) {
58
- ->(op) {
59
+ ->(op) {
60
+ ->(base) {
61
+ ->(exponent) {
59
62
  Smullyan::Birds::Y.(->(f) {
60
63
  ->(b) {
61
64
  ->(e) {
@@ -70,12 +73,87 @@ module Magick
70
73
  }
71
74
  end
72
75
 
76
+ # power, as written, will have a stack trace error if we try to
77
+ # do something like power.(mult).(2).(32)
78
+ # If we eliminate the recursion, we can avoid this, but it means we need
79
+ # to use some regular Ruby constructs (eg, `while`, instead of the Y combinator)
80
+ # The following is essentially how Stepanov & McJones define `power` in
81
+ # Elements of Programming
82
+ def power_accumulate_positive
83
+ ->(op){
84
+ ->(r){
85
+ ->(a){
86
+ ->(n){
87
+ while (true)
88
+ if n % 2 != 0
89
+ r = op.(r).(a)
90
+ return r if n == 1
91
+ end
92
+ a = op.(a).(a)
93
+ n = n/2
94
+ end
95
+ }
96
+ }
97
+ }
98
+ }
99
+ end
100
+
101
+ def power_accumulate
102
+ ->(op){
103
+ ->(r){
104
+ ->(n){
105
+ ->(a){
106
+ return r if n == 0
107
+ power_accumulate_positive.(op).(r).(n).(a)
108
+ }
109
+ }
110
+ }
111
+ }
112
+ end
113
+
114
+ def power_2
115
+ ->(op){
116
+ ->(b){
117
+ ->(e){
118
+ while (e % 2 == 0)
119
+ b = op.(b).(b)
120
+ e = e/2
121
+ end
122
+ e = e / 2
123
+ return b if e == 0
124
+ power_accumulate.(op).(b).(op.(b).(b)).(e)
125
+ }
126
+ }
127
+ }
128
+ end
129
+
73
130
  def average
74
131
  Smullyan::Birds::Phi.
75
- (Magick::Maths::divide).
132
+ (Magick::Maths::div_to_f).
76
133
  (Magick::Loops::sum).
77
134
  (Magick::Loops::length)
78
135
  end
136
+
137
+ def powers_of_two = exp.(2)
138
+
139
+ # x and y are pairs of ints
140
+ def fibonacci_matrix_multiply = ->(x){
141
+ ->(y){
142
+ [
143
+ x[0] * (y[1] + y[0]) +
144
+ x[1] * y[0],
145
+ x[0] * y[0] +
146
+ x[1] * y[1]
147
+ ]
148
+ }
149
+ }
150
+
151
+ def fibonacci
152
+ ->(n){
153
+ n == 0 ? 0 :
154
+ power_2.(fibonacci_matrix_multiply).([1,0]).(n)[0]
155
+ }
156
+ end
79
157
  end
80
158
  end
81
159
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Magick
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
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.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phil Crissman