rsl 0.0.1

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.
data/CHANGELOG ADDED
@@ -0,0 +1,6 @@
1
+ CHANGELOG
2
+
3
+ == 0.0.1
4
+
5
+ * Initial release.
6
+ * Simple least squares fit
data/README ADDED
@@ -0,0 +1,11 @@
1
+ == Ruby Scientific Library
2
+
3
+ Native Ruby scientific/numeric programs, available for use in any application.
4
+
5
+ For more information see http://www.sbrew.com/rsl
6
+
7
+ RSL is distributed under the Ruby License.
8
+
9
+ == WARNING
10
+
11
+ This is alpha-quality software. It is still very young.
data/Rakefile ADDED
@@ -0,0 +1,198 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/contrib/rubyforgepublisher'
8
+
9
+ $:.unshift(File.dirname(__FILE__) + "/lib")
10
+ require 'rsl'
11
+
12
+ PKG_NAME = 'rsl'
13
+ PKG_VERSION = Rsl::VERSION
14
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
15
+
16
+ RELEASE_NAME = "REL #{PKG_VERSION}"
17
+
18
+ RUBY_FORGE_PROJECT = "rsl"
19
+ RUBY_FORGE_USER = "timbreitkreutz"
20
+
21
+ desc "Default Task"
22
+ task :default => [ :clean, :test ]
23
+
24
+ desc "Clean images generated by tests"
25
+ task :clean do
26
+ rm FileList['test/output/*.png']
27
+ rm_rf 'pkg'
28
+ rm_rf 'doc'
29
+ end
30
+
31
+ # Run the unit tests
32
+ Rake::TestTask.new { |t|
33
+ t.libs << "test"
34
+ t.pattern = 'test/*_test.rb'
35
+ t.verbose = true
36
+ }
37
+
38
+
39
+ # Genereate the RDoc documentation
40
+ Rake::RDocTask.new { |rdoc|
41
+ rdoc.rdoc_dir = 'doc'
42
+ rdoc.title = "RSL -- Ruby Scientific Library"
43
+ # rdoc.options << '--line-numbers --inline-source --main README --accessor adv_attr_accessor=M'
44
+ rdoc.template = "#{ENV['template']}.rb" if ENV['template']
45
+ rdoc.rdoc_files.include('README', 'CHANGELOG')
46
+ rdoc.rdoc_files.include('lib/rsl.rb')
47
+ rdoc.rdoc_files.include('lib/rsl/*.rb')
48
+ }
49
+
50
+
51
+ # Create compressed packages
52
+ spec = Gem::Specification.new do |s|
53
+ s.platform = Gem::Platform::RUBY
54
+ s.name = PKG_NAME
55
+ s.summary = "A native Ruby Scientific/Numerical library."
56
+ s.description = %q{Find and contribute numeric/scientific programs in native Ruby.}
57
+ s.version = PKG_VERSION
58
+
59
+ s.author = "Tim Breitkreutz"
60
+ s.email = "tim@sbrew.com"
61
+ s.rubyforge_project = RUBY_FORGE_PROJECT
62
+ s.homepage = "http://www.sbrew.com/rsl"
63
+
64
+ s.has_rdoc = true
65
+ s.requirements << 'none'
66
+ s.require_path = 'lib'
67
+ s.autorequire = 'rsl'
68
+
69
+ s.files = [ "Rakefile", "README", "CHANGELOG" ]
70
+ s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
71
+ s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
72
+ end
73
+
74
+ Rake::GemPackageTask.new(spec) do |p|
75
+ p.gem_spec = spec
76
+ p.need_tar = true
77
+ p.need_zip = true
78
+ end
79
+
80
+ desc "Publish the API documentation"
81
+ task :pgem => [:package] do
82
+ Rake::SshFilePublisher.new("tim@sbrew.com", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
83
+ end
84
+
85
+ desc "Publish the release files to RubyForge."
86
+ task :release => [:package] do
87
+ files = ["gem", "tgz", "zip"].map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
88
+
89
+ if RUBY_FORGE_PROJECT then
90
+ require 'net/http'
91
+ require 'open-uri'
92
+
93
+ project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
94
+ project_data = open(project_uri) { |data| data.read }
95
+ group_id = project_data[/[?&]group_id=(\d+)/, 1]
96
+ raise "Couldn't get group id" unless group_id
97
+
98
+ # This echos password to shell which is a bit sucky
99
+ if ENV["RUBY_FORGE_PASSWORD"]
100
+ password = ENV["RUBY_FORGE_PASSWORD"]
101
+ else
102
+ print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
103
+ password = STDIN.gets.chomp
104
+ end
105
+
106
+ login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
107
+ data = [
108
+ "login=1",
109
+ "form_loginname=#{RUBY_FORGE_USER}",
110
+ "form_pw=#{password}"
111
+ ].join("&")
112
+ http.post("/account/login.php", data)
113
+ end
114
+
115
+ cookie = login_response["set-cookie"]
116
+ raise "Login failed" unless cookie
117
+ headers = { "Cookie" => cookie }
118
+
119
+ release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
120
+ release_data = open(release_uri, headers) { |data| data.read }
121
+ package_id = release_data[/[?&]package_id=(\d+)/, 1]
122
+ raise "Couldn't get package id" unless package_id
123
+
124
+ first_file = true
125
+ release_id = ""
126
+
127
+ files.each do |filename|
128
+ basename = File.basename(filename)
129
+ file_ext = File.extname(filename)
130
+ file_data = File.open(filename, "rb") { |file| file.read }
131
+
132
+ puts "Releasing #{basename}..."
133
+
134
+ release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
135
+ release_date = Time.now.strftime("%Y-%m-%d %H:%M")
136
+ type_map = {
137
+ ".zip" => "3000",
138
+ ".tgz" => "3110",
139
+ ".gz" => "3110",
140
+ ".gem" => "1400"
141
+ }; type_map.default = "9999"
142
+ type = type_map[file_ext]
143
+ boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
144
+
145
+ query_hash = if first_file then
146
+ {
147
+ "group_id" => group_id,
148
+ "package_id" => package_id,
149
+ "release_name" => RELEASE_NAME,
150
+ "release_date" => release_date,
151
+ "type_id" => type,
152
+ "processor_id" => "8000", # Any
153
+ "release_notes" => "",
154
+ "release_changes" => "",
155
+ "preformatted" => "1",
156
+ "submit" => "1"
157
+ }
158
+ else
159
+ {
160
+ "group_id" => group_id,
161
+ "release_id" => release_id,
162
+ "package_id" => package_id,
163
+ "step2" => "1",
164
+ "type_id" => type,
165
+ "processor_id" => "8000", # Any
166
+ "submit" => "Add This File"
167
+ }
168
+ end
169
+
170
+ query = "?" + query_hash.map do |(name, value)|
171
+ [name, URI.encode(value)].join("=")
172
+ end.join("&")
173
+
174
+ data = [
175
+ "--" + boundary,
176
+ "Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
177
+ "Content-Type: application/octet-stream",
178
+ "Content-Transfer-Encoding: binary",
179
+ "", file_data, ""
180
+ ].join("\x0D\x0A")
181
+
182
+ release_headers = headers.merge(
183
+ "Content-Type" => "multipart/form-data; boundary=#{boundary}"
184
+ )
185
+
186
+ target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
187
+ http.post(target + query, data, release_headers)
188
+ end
189
+
190
+ if first_file then
191
+ release_id = release_response.body[/release_id=(\d+)/, 1]
192
+ raise("Couldn't get release id") unless release_id
193
+ end
194
+
195
+ first_file = false
196
+ end
197
+ end
198
+ end
data/lib/rsl/base.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Rsl
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,43 @@
1
+
2
+
3
+ module Rsl
4
+ # Linear fit--least squares regression
5
+ # Fits the data in xes and ys to Y = b + a X
6
+ # returns (a, b)
7
+ def Rsl.least_squares_fit( xes, ys )
8
+ raise "input vectors must not be nil" if xes == nil || ys == nil
9
+ raise "input vectors must be larger" if xes.size < 3 || ys.size < 3
10
+ raise "input vectors must be of equal size" if xes.size != ys.size
11
+
12
+ run_x = 0.0
13
+ run_y = 0.0
14
+
15
+ count = 1.0
16
+
17
+ xes.to_a.each { |x|
18
+ raise "X vector contains a nil" if x == nil
19
+ run_x += ( x - run_x ) / count
20
+ count += 1.0
21
+ }
22
+ count = 1.0
23
+ ys.to_a.each { |y|
24
+ raise "Y vector contains a nil" if y == nil
25
+ run_y += ( ( y ) - run_y ) / count
26
+ count += 1.0
27
+ }
28
+
29
+ dx2, dxdy = 0.0, 0.0
30
+
31
+ (1..xes.size).each do |count|
32
+ dx = xes[count-1] - run_x
33
+ dy = ( ys[count-1] ) - run_y
34
+ dx2 += ( dx * dx - dx2 ) / count.to_f
35
+ dxdy += ( dx * dy - dxdy ) / count.to_f
36
+ end
37
+
38
+ b = dxdy / dx2 if dx2 != 0.0
39
+ a = run_y - run_x * b
40
+
41
+ return a, b
42
+ end
43
+ end
data/lib/rsl.rb ADDED
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + '/rsl/base'
2
+ require File.dirname(__FILE__) + '/rsl/least_squares_fit'
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'rsl'
5
+ require 'matrix'
6
+ require 'mathn'
7
+
8
+ class LinearFitTest < Test::Unit::TestCase
9
+
10
+ def test_fit
11
+ a, b = Rsl.least_squares_fit([1, 2, 3], [10, 11, 12 ])
12
+ assert_equal(sprintf("%.2f", a), "9.00")
13
+ assert_equal(sprintf("%.2f", b), "1.00")
14
+
15
+ a, b = Rsl.least_squares_fit([1, 2, 3], [10, 10.5, 12 ])
16
+ assert_equal(sprintf("%.2f", a), "8.83")
17
+ assert_equal(sprintf("%.2f", b), "1.00")
18
+
19
+ a, b = Rsl.least_squares_fit([1, 2, 3, 8, 11, 22], [10, 10.5, 12, 12.55, 13.55, 15.01 ])
20
+ assert_equal(sprintf("%.2f", a), "10.53")
21
+ assert_equal(sprintf("%.2f", b), "0.22")
22
+
23
+ # Some simple boundaries, zeros and negative inputs
24
+
25
+ a, b = Rsl.least_squares_fit([1, 0, 3, 8, 11, 22], [10, 10.5, 12, 12.55, 13.55, 15.01 ])
26
+ assert_equal(sprintf("%.2f", a), "10.65")
27
+ assert_equal(sprintf("%.2f", b), "0.22")
28
+
29
+ a, b = Rsl.least_squares_fit([1, 8, 3, 8, 11, 22], [10, 0, 12, 12.55, 13.55, 15.01 ])
30
+ assert_equal(sprintf("%.2f", a), "8.33")
31
+ assert_equal(sprintf("%.2f", b), "0.25")
32
+
33
+ a, b = Rsl.least_squares_fit([-100, 8, 3, 8, 11, 22], [10, 0, -12, 12.55, 13.55, 15.01 ])
34
+ assert_equal(sprintf("%.2f", a), "6.41")
35
+ assert_equal(sprintf("%.2f", b), "-0.01")
36
+ end
37
+
38
+ def test_nil_vector
39
+ assert_raise(RuntimeError) { a, b = Rsl.least_squares_fit(nil, nil) }
40
+ end
41
+
42
+ def test_nil_member
43
+ assert_raise(RuntimeError) { a, b = Rsl.least_squares_fit([nil, 1, 2, 3], [2, 3, 4, 5]) }
44
+ end
45
+
46
+ def test_wrong_length
47
+ assert_raise(RuntimeError) { a, b = Rsl.least_squares_fit([9, 1, 2, 3], [2, 3, 4, 5, 5]) }
48
+ end
49
+
50
+ def test_too_short
51
+ assert_raise(RuntimeError) { a, b = Rsl.least_squares_fit([9], [2]) }
52
+ assert_raise(RuntimeError) { a, b = Rsl.least_squares_fit([nil], [nil]) }
53
+ assert_raise(RuntimeError) { a, b = Rsl.least_squares_fit([2,2], [3,3]) }
54
+ end
55
+
56
+ def test_vectors
57
+ x = Vector[1, 2, 3]
58
+ y = Vector[10, 11, 12]
59
+ a, b = Rsl.least_squares_fit(x, y)
60
+ assert_equal(sprintf("%.2f", a), "9.00")
61
+ assert_equal(sprintf("%.2f", b), "1.00")
62
+ end
63
+ end
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: rsl
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2006-03-30 00:00:00 -07:00
8
+ summary: A native Ruby Scientific/Numerical library.
9
+ require_paths:
10
+ - lib
11
+ email: tim@sbrew.com
12
+ homepage: http://www.sbrew.com/rsl
13
+ rubyforge_project: rsl
14
+ description: Find and contribute numeric/scientific programs in native Ruby.
15
+ autorequire: rsl
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ authors:
29
+ - Tim Breitkreutz
30
+ files:
31
+ - Rakefile
32
+ - README
33
+ - CHANGELOG
34
+ - lib/rsl
35
+ - lib/rsl.rb
36
+ - lib/rsl/base.rb
37
+ - lib/rsl/least_squares_fit.rb
38
+ - test/least_squares_test.rb
39
+ test_files: []
40
+
41
+ rdoc_options: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ executables: []
46
+
47
+ extensions: []
48
+
49
+ requirements:
50
+ - none
51
+ dependencies: []
52
+