rserve-client 0.1.9 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/History.txt +9 -1
- data/Manifest.txt +7 -0
- data/README.txt +8 -7
- data/benchmark/benchmark.rb +113 -0
- data/benchmark/comparison_2010_06_07.xls +0 -0
- data/benchmark/comparison_2010_06_07_using_pack.xls +0 -0
- data/benchmark/plot.rb +69 -0
- data/examples/hello_world.rb +1 -1
- data/lib/rserve.rb +2 -1
- data/lib/rserve/connection.rb +75 -14
- data/lib/rserve/protocol.rb +22 -1
- data/lib/rserve/rexp.rb +138 -74
- data/lib/rserve/rexp/double.rb +9 -2
- data/lib/rserve/session.rb +29 -0
- data/spec/rserve_connection_on_unix_spec.rb +37 -0
- data/spec/rserve_connection_spec.rb +22 -16
- data/spec/rserve_protocol_spec.rb +5 -0
- data/spec/rserve_rexp_to_ruby_spec.rb +3 -0
- data/spec/rserve_rexpfactory_spec.rb +4 -1
- data/spec/rserve_rlist_spec.rb +3 -0
- data/spec/rserve_session_spec.rb +27 -0
- data/spec/rserve_spec.rb +3 -0
- metadata +15 -6
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/History.txt
CHANGED
@@ -1,5 +1,13 @@
|
|
1
|
-
=== 0.
|
1
|
+
=== 0.2.0 / 2010-06-15
|
2
|
+
* Session implemented.
|
3
|
+
* Retrieve auth information from server first responde. TODO: Implement authentification
|
4
|
+
* Rserve::Protocol get_int and get_long uses pack. Spec for test compatibility for old method
|
5
|
+
* Added benchmark, comparing Rserve with RinRuby and RsRuby
|
6
|
+
* Windows Support:
|
7
|
+
* On windows, any new connection closes the previous. Rserve on Windows can't process parallel connections
|
8
|
+
* All Specification works on Windows
|
2
9
|
|
10
|
+
=== 0.1.9 / 2010-06-04
|
3
11
|
* Documentation:
|
4
12
|
* Added commentaries on examples/regression.txt
|
5
13
|
* Examples.txt on main directory renamed to Introduction.txt
|
data/Manifest.txt
CHANGED
@@ -4,6 +4,10 @@ Introduction.txt
|
|
4
4
|
Manifest.txt
|
5
5
|
README.txt
|
6
6
|
Rakefile
|
7
|
+
benchmark/benchmark.rb
|
8
|
+
benchmark/comparison_2010_06_07.xls
|
9
|
+
benchmark/comparison_2010_06_07_using_pack.xls
|
10
|
+
benchmark/plot.rb
|
7
11
|
data/gettysburg.txt
|
8
12
|
examples/gettysburg.rb
|
9
13
|
examples/hello_world.rb
|
@@ -36,9 +40,11 @@ lib/rserve/rexp/vector.rb
|
|
36
40
|
lib/rserve/rexp/wrapper.rb
|
37
41
|
lib/rserve/rfactor.rb
|
38
42
|
lib/rserve/rlist.rb
|
43
|
+
lib/rserve/session.rb
|
39
44
|
lib/rserve/talk.rb
|
40
45
|
lib/rserve/withattributes.rb
|
41
46
|
lib/rserve/withnames.rb
|
47
|
+
spec/rserve_connection_on_unix_spec.rb
|
42
48
|
spec/rserve_connection_spec.rb
|
43
49
|
spec/rserve_double_spec.rb
|
44
50
|
spec/rserve_genericvector_spec.rb
|
@@ -52,6 +58,7 @@ spec/rserve_rexp_wrapper_spec.rb
|
|
52
58
|
spec/rserve_rexpfactory_spec.rb
|
53
59
|
spec/rserve_rfactor_spec.rb
|
54
60
|
spec/rserve_rlist_spec.rb
|
61
|
+
spec/rserve_session_spec.rb
|
55
62
|
spec/rserve_spec.rb
|
56
63
|
spec/rserve_talk_spec.rb
|
57
64
|
spec/rserve_withnames_spec.rb
|
data/README.txt
CHANGED
@@ -16,10 +16,11 @@ Follows closely the new Java client API, but maintains all Ruby conventions when
|
|
16
16
|
* Requires Rserve installed on the server machine. On debian / ubuntu, you should use <tt>sudo apt-get install r-cran-rserve</tt>
|
17
17
|
Pros:
|
18
18
|
* Work with Ruby 1.8, 1.9 and JRuby 1.5.
|
19
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
*
|
19
|
+
* Work on Windows. Rserve limitations on that plataform applies (single connection, crash on parse errors)
|
20
|
+
* Retrieve and assign various R's datatypes: integer, doubles, chars, logical vectors, lists and raw data.
|
21
|
+
* Session allows to process data asynchronously. You start a command, detach the process and retrieve result later. You can marshall the session, store on file or database and use it when you need it.
|
22
|
+
* Ruby API follows closely the Java API, so any change on the server API could be adopted without much problem
|
23
|
+
* Fast: 5-10 times faster than RinRuby.
|
23
24
|
* Easy management of differences between R and Ruby, or "You can have your cake and eat it, too!"
|
24
25
|
* From R side: The evaluation of expression retrieves REXP object, with a lot of information from original variables on R. You can construct your REXP objects and <tt>assign</tt> them to variables on R fast using binary TCP/IP port or send complex expression without lost of time using <tt>void_eval</tt>
|
25
26
|
* Between R and Ruby: Every REXP object implements methods to convert to specific Ruby type: as_integers, as_doubles, as_strings
|
@@ -38,16 +39,17 @@ Cons:
|
|
38
39
|
* Work with Ruby 1.8, 1.9 and JRuby 1.5
|
39
40
|
* All API tested
|
40
41
|
* Cons:
|
41
|
-
* VERY SLOW
|
42
|
+
* VERY SLOW on assignation
|
42
43
|
* Very limited datatypes: Only vector and Matrix
|
43
44
|
* RSRuby
|
44
45
|
* C Extension for Ruby, linked to R's shared library
|
45
46
|
* Pros:
|
46
|
-
*
|
47
|
+
* Blazing speed! 5-10 times faster than Rserve and 100-1000 than RinRuby.
|
47
48
|
* Seamless integration with ruby. Every method and object is treated like a Ruby one
|
48
49
|
* Cons:
|
49
50
|
* Transformation between R and Ruby types aren't trivial
|
50
51
|
* Dependent on operating system, Ruby implementation and R version
|
52
|
+
* Ocassionaly crash
|
51
53
|
* Not available for alternative implementations of Ruby (JRuby, IronRuby and Rubinius)
|
52
54
|
|
53
55
|
|
@@ -55,7 +57,6 @@ Cons:
|
|
55
57
|
|
56
58
|
Implements
|
57
59
|
|
58
|
-
* Sessions
|
59
60
|
* Authentification
|
60
61
|
* Original test
|
61
62
|
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# Compares rserve, rinruby and rsruby
|
2
|
+
# in retrieval and assign of information
|
3
|
+
$:.unshift(File.dirname(__FILE__)+"/../lib")
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'rserve'
|
7
|
+
require 'rinruby'
|
8
|
+
begin
|
9
|
+
require 'rsruby'
|
10
|
+
rs=RSRuby.instance
|
11
|
+
rescue LoadError
|
12
|
+
rs=nil
|
13
|
+
end
|
14
|
+
require 'benchmark'
|
15
|
+
data_size=30000
|
16
|
+
tries=50
|
17
|
+
con=Rserve::Connection.new
|
18
|
+
R.eval("1",false)
|
19
|
+
data=data_size.times.map {rand()}
|
20
|
+
data_integer=data_size.times.map {rand(100)}
|
21
|
+
Benchmark.bm(30) do |x|
|
22
|
+
x.report("assign '1' rinruby") {
|
23
|
+
tries.times {
|
24
|
+
R.a=1
|
25
|
+
}
|
26
|
+
}
|
27
|
+
x.report("assign '1' rserve") {
|
28
|
+
con.assign("a", 1)
|
29
|
+
}
|
30
|
+
if rs
|
31
|
+
x.report("assign '1' rsruby") {
|
32
|
+
rs.assign('a',1)
|
33
|
+
}
|
34
|
+
end
|
35
|
+
x.report("assign double(#{data_size}) rinruby") {
|
36
|
+
tries.times {
|
37
|
+
R.a=data
|
38
|
+
}
|
39
|
+
}
|
40
|
+
x.report("assign double(#{data_size}) rserve") {
|
41
|
+
con.assign("a", data)
|
42
|
+
}
|
43
|
+
if rs
|
44
|
+
x.report("assign double(#{data_size}) rsruby") {
|
45
|
+
rs.assign("a", data)
|
46
|
+
}
|
47
|
+
end
|
48
|
+
x.report("void_eval rinruby") {
|
49
|
+
tries.times {
|
50
|
+
R.eval("1",false)
|
51
|
+
}
|
52
|
+
}
|
53
|
+
x.report("void_eval rserve") {
|
54
|
+
tries.times {
|
55
|
+
con.void_eval("1")
|
56
|
+
}
|
57
|
+
}
|
58
|
+
if rs
|
59
|
+
x.report("void_eval rsruby") {
|
60
|
+
tries.times {
|
61
|
+
rs.eval("1")
|
62
|
+
}
|
63
|
+
}
|
64
|
+
end
|
65
|
+
# Assign data
|
66
|
+
R.a=1
|
67
|
+
con.assign('a',1)
|
68
|
+
if rs
|
69
|
+
rs.assign('a',1)
|
70
|
+
end
|
71
|
+
x.report("get '1' rinruby") {
|
72
|
+
tries.times {
|
73
|
+
R.pull('a')
|
74
|
+
}
|
75
|
+
}
|
76
|
+
x.report("get '1' rserve") {
|
77
|
+
tries.times {
|
78
|
+
con.eval('a').to_ruby
|
79
|
+
}
|
80
|
+
}
|
81
|
+
if rs
|
82
|
+
x.report("get '1' rsruby") {
|
83
|
+
tries.times {
|
84
|
+
rs.a
|
85
|
+
}
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
R.a=data
|
90
|
+
con.assign('a',data)
|
91
|
+
if rs
|
92
|
+
rs.assign('a',data)
|
93
|
+
end
|
94
|
+
x.report("get double(#{data_size}) rinruby") {
|
95
|
+
tries.times {
|
96
|
+
R.pull('a')
|
97
|
+
}
|
98
|
+
}
|
99
|
+
x.report("get double(#{data_size}) rserve") {
|
100
|
+
tries.times {
|
101
|
+
con.eval('a').to_ruby
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
if rs
|
106
|
+
x.report("get double(#{data_size}) rsruby") {
|
107
|
+
tries.times {
|
108
|
+
rs.a
|
109
|
+
}
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
Binary file
|
Binary file
|
data/benchmark/plot.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Creates a graph with multiple size assignment and retrieval
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rserve'
|
5
|
+
require 'rinruby'
|
6
|
+
require 'benchmark'
|
7
|
+
require 'statsample'
|
8
|
+
require 'rsruby'
|
9
|
+
|
10
|
+
max=45
|
11
|
+
R.eval("1")
|
12
|
+
rs=RSRuby.instance
|
13
|
+
con=Rserve::Connection.new
|
14
|
+
rserve_assign = []
|
15
|
+
rserve_retrieve = []
|
16
|
+
rinruby_assign = []
|
17
|
+
rinruby_retrieve = []
|
18
|
+
rs_assign=[]
|
19
|
+
rs_retrieve=[]
|
20
|
+
|
21
|
+
max.times.map {|x|
|
22
|
+
puts "Rserve #{x}"
|
23
|
+
start=Time.new.to_f
|
24
|
+
con.assign('a',(x*100+1).times.map {rand})
|
25
|
+
a=Time.new.to_f-start
|
26
|
+
|
27
|
+
start=Time.new.to_f
|
28
|
+
|
29
|
+
con.eval('a').to_f
|
30
|
+
|
31
|
+
b=Time.new.to_f-start
|
32
|
+
|
33
|
+
rserve_assign.push(a)
|
34
|
+
rserve_retrieve.push(b)
|
35
|
+
}
|
36
|
+
max.times.map {|x|
|
37
|
+
|
38
|
+
puts "Rinruby #{x}"
|
39
|
+
start=Time.new.to_f
|
40
|
+
R.assign("a", (x*100+1).times.map {rand})
|
41
|
+
a=Time.new.to_f-start
|
42
|
+
start=Time.new.to_f
|
43
|
+
R.pull('a')
|
44
|
+
b=Time.new.to_f-start
|
45
|
+
rinruby_assign.push(a)
|
46
|
+
rinruby_retrieve.push(b)
|
47
|
+
}
|
48
|
+
|
49
|
+
|
50
|
+
max.times.map {|x|
|
51
|
+
puts "RsRuby #{x}"
|
52
|
+
start=Time.new.to_f
|
53
|
+
rs.assign('a',(x*100+1).times.map {rand})
|
54
|
+
a=Time.new.to_f-start
|
55
|
+
|
56
|
+
start=Time.new.to_f
|
57
|
+
|
58
|
+
rs.a.to_f
|
59
|
+
|
60
|
+
b=Time.new.to_f-start
|
61
|
+
|
62
|
+
rs_assign.push(a)
|
63
|
+
rs_retrieve.push(b)
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
ds_assign={'times'=>(1..max).map {|v| v*100+1}.to_scale,'rserve assign'=> rserve_assign.to_scale, 'rserve retrieve'=>rserve_retrieve.to_scale, 'rinruby assign'=>rinruby_assign.to_scale, 'rinruby retrieve'=>rinruby_retrieve.to_scale, 'rs_assign'=>rs_assign.to_scale, 'rs_retrieve'=>rs_retrieve.to_scale}.to_dataset
|
68
|
+
ds_assign.fields=['times','rs_assign','rserve_assign','rinruby_assign','rs_retrieve','rserve_retrieve','rinruby_retrieve']
|
69
|
+
Statsample::Excel.write(ds_assign,'comparison.xls')
|
data/examples/hello_world.rb
CHANGED
data/lib/rserve.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'socket'
|
2
2
|
|
3
3
|
module Rserve
|
4
|
-
VERSION = '0.
|
4
|
+
VERSION = '0.2.0'
|
5
5
|
end
|
6
6
|
|
7
7
|
|
@@ -14,6 +14,7 @@ require 'rserve/packet'
|
|
14
14
|
require 'rserve/talk'
|
15
15
|
require 'rserve/rexp'
|
16
16
|
require 'rserve/engine'
|
17
|
+
require 'rserve/session'
|
17
18
|
require 'rserve/connection'
|
18
19
|
require 'rserve/rlist'
|
19
20
|
require 'rserve/rfactor'
|
data/lib/rserve/connection.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
require 'rbconfig'
|
1
2
|
module Rserve
|
2
3
|
class Connection < Rserve::Engine
|
4
|
+
@@connected_object=nil
|
3
5
|
include Rserve::Protocol
|
4
6
|
|
5
7
|
# :section: Exceptions
|
@@ -27,6 +29,7 @@ module Rserve
|
|
27
29
|
attr_reader :rt
|
28
30
|
attr_reader :s
|
29
31
|
attr_reader :port
|
32
|
+
attr_reader :session
|
30
33
|
attr_writer :transfer_charset
|
31
34
|
attr_reader :rsrv_version
|
32
35
|
attr_writer :persistent
|
@@ -40,10 +43,13 @@ module Rserve
|
|
40
43
|
@hostname = opts.delete(:hostname) || "127.0.0.1"
|
41
44
|
@port_number = opts.delete(:port_number) || 6311
|
42
45
|
@max_tries = opts.delete(:max_tries) || 5
|
46
|
+
@session = opts.delete(:session) || nil
|
43
47
|
@tries = 0
|
44
48
|
@connected=false
|
45
|
-
|
46
|
-
|
49
|
+
if (!@session.nil?)
|
50
|
+
@hostname=@session.host
|
51
|
+
@port_number=@session.port
|
52
|
+
end
|
47
53
|
begin
|
48
54
|
#puts "Tryin to connect..."
|
49
55
|
connect
|
@@ -72,22 +78,49 @@ module Rserve
|
|
72
78
|
end
|
73
79
|
end
|
74
80
|
def connect
|
75
|
-
|
81
|
+
# On windows, Rserve doesn't allows concurrent connections.
|
82
|
+
# So, we must close the last open connection first
|
83
|
+
if RbConfig::CONFIG['arch']=~/mswin/ and !@@connected_object.nil?
|
84
|
+
@@connected_object.close
|
85
|
+
end
|
86
|
+
|
76
87
|
close if @connected
|
88
|
+
|
77
89
|
@s = TCPSocket::new(@hostname, @port_number)
|
78
90
|
@rt=Rserve::Talk.new(@s)
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
91
|
+
if @session.nil?
|
92
|
+
#puts "Connected"
|
93
|
+
# Accept first input
|
94
|
+
input=@s.recv(32).unpack("a4a4a4a4a4a4a4a4")
|
95
|
+
raise IncorrectServer,"Handshake failed: Rsrv signature expected, but received [#{input[0]}]" unless input[0]=="Rsrv"
|
96
|
+
@rsrv_version=input[1].to_i
|
97
|
+
raise IncorrectServerVersion, "Handshake failed: The server uses more recent protocol than this client." if @rsrv_version>103
|
98
|
+
@protocol=input[2]
|
99
|
+
raise IncorrectProtocol, "Handshake failed: unsupported transfer protocol #{@protocol}, I talk only QAP1." if @protocol!="QAP1"
|
100
|
+
(3..7).each do |i|
|
101
|
+
attr=input[i]
|
102
|
+
if (attr=="ARpt")
|
103
|
+
if (!auth_req) # this method is only fallback when no other was specified
|
104
|
+
auth_req=true
|
105
|
+
auth_type=AT_plain
|
106
|
+
end
|
107
|
+
end
|
108
|
+
if (attr=="ARuc")
|
109
|
+
auth_req=true
|
110
|
+
authType=AT_crypt
|
111
|
+
end
|
112
|
+
if (attr[0]=='K')
|
113
|
+
key=attr[1,3]
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
else # we have a session to take care of
|
118
|
+
@s.write(@session.key.pack("C*"))
|
119
|
+
@rsrv_version=session.rsrv_version
|
120
|
+
end
|
88
121
|
@connected=true
|
122
|
+
@@connected_object=self
|
89
123
|
@last_error="OK"
|
90
|
-
|
91
124
|
end
|
92
125
|
def connected?
|
93
126
|
@connected
|
@@ -99,6 +132,7 @@ module Rserve
|
|
99
132
|
end
|
100
133
|
raise "Can't close socket" unless @s.closed?
|
101
134
|
@connected=false
|
135
|
+
@@connected_object=nil
|
102
136
|
true
|
103
137
|
end
|
104
138
|
def get_server_version
|
@@ -119,6 +153,20 @@ module Rserve
|
|
119
153
|
end
|
120
154
|
|
121
155
|
|
156
|
+
def void_eval_detach(cmd)
|
157
|
+
raise NotConnected if !connected? or rt.nil?
|
158
|
+
rp=rt.request(:cmd=>Rserve::Protocol::CMD_detachedVoidEval,:cont=>cmd+"\n")
|
159
|
+
if rp.nil? or !rp.ok?
|
160
|
+
raise EvalError.new(rp), "detached void eval failed : #{rp.to_s}"
|
161
|
+
else
|
162
|
+
s=Rserve::Session.new(self,rp)
|
163
|
+
close
|
164
|
+
s
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
|
122
170
|
# evaluates the given command and retrieves the result
|
123
171
|
# * @param cmd command/expression string
|
124
172
|
# * @return R-xpression or <code>null</code> if an error occured */
|
@@ -233,6 +281,19 @@ module Rserve
|
|
233
281
|
raise "Shutdown failed"
|
234
282
|
end
|
235
283
|
end
|
236
|
-
|
284
|
+
# detaches the session and closes the connection (requires Rserve 0.4+).
|
285
|
+
# The session can be only resumed by calling RSession.attach
|
286
|
+
|
287
|
+
def detach
|
288
|
+
raise NotConnected if !connected? or rt.nil?
|
289
|
+
rp=rt.request(:cmd=>Rserve::Protocol::CMD_detachSession)
|
290
|
+
if !rp.nil? and rp.ok?
|
291
|
+
s=Rserve::Session.new(self,rp)
|
292
|
+
close
|
293
|
+
s
|
294
|
+
else
|
295
|
+
raise "Cannot detach"
|
296
|
+
end
|
297
|
+
end
|
237
298
|
end
|
238
299
|
end
|
data/lib/rserve/protocol.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'rbconfig'
|
1
2
|
module Rserve
|
2
3
|
#
|
3
4
|
# This module encapsulates methods and constants related to QAP1 protocol used by Rserv. Follows almost exactly the interface on RTalk class
|
@@ -7,6 +8,15 @@ module Rserve
|
|
7
8
|
# Policy: No other class should know about the internal of protocol!
|
8
9
|
# See Rtalk class on Java version.
|
9
10
|
module Protocol
|
11
|
+
# Arch dependent Long Nil value
|
12
|
+
case Config::CONFIG['arch']
|
13
|
+
when 'i686-linux'
|
14
|
+
LONG_NA=9221120237041092514 # :nodoc:
|
15
|
+
when /mswin/
|
16
|
+
LONG_NA=9221120237041092514 # :nodoc:
|
17
|
+
else
|
18
|
+
LONG_NA=9218868437227407266 # :nodoc:
|
19
|
+
end
|
10
20
|
# Defines from Rsrv.h
|
11
21
|
CMD_RESP=0x010000 # all responses have this flag set
|
12
22
|
RESP_OK=(CMD_RESP|0x0001) # command succeeded; returned parameters depend on the command issued
|
@@ -162,7 +172,9 @@ module Rserve
|
|
162
172
|
# make sure that the buffer is big enough
|
163
173
|
|
164
174
|
def get_int(buf, o)
|
165
|
-
|
175
|
+
buf[o,4].pack("C*").unpack("l")[0]
|
176
|
+
end
|
177
|
+
def get_int_original(buf,o) # :nodoc:
|
166
178
|
v=((buf[o]&255)|((buf[o+1]&255)<<8)|((buf[o+2]&255)<<16)|((buf[o+3]&255)<<24))
|
167
179
|
v >= MAX_LONG_SIGNED ? v-MAX_LONG_UNSIGNED : v
|
168
180
|
end
|
@@ -187,12 +199,20 @@ module Rserve
|
|
187
199
|
# @param o offset (8 bytes will be used)
|
188
200
|
# @return long value */
|
189
201
|
def get_long(buf, o)
|
202
|
+
buf[o,8].pack("CCCCCCCC").unpack("Q")[0]
|
203
|
+
end
|
204
|
+
def get_long_original(buf,o) #:nodoc:
|
190
205
|
low=(get_int(buf,o))&0xffffffff;
|
191
206
|
hi=(get_int(buf,o+4))&0xffffffff;
|
192
207
|
hi<<=32; hi|=low;
|
193
208
|
hi
|
194
209
|
end
|
210
|
+
|
195
211
|
def longBitsToDouble(bits)
|
212
|
+
(bits==LONG_NA) ? Rserve::REXP::Double::NA : [bits].pack("Q").unpack("d")[0]
|
213
|
+
end
|
214
|
+
# Complete version of longBitsToDouble, as Java documentation established
|
215
|
+
def longBitsToDouble_old(bits) # :nodoc:
|
196
216
|
s = ((bits >> 63) == 0) ? 1 : -1;
|
197
217
|
e = ((bits >> 52) & 0x7ff)
|
198
218
|
m = (e == 0) ?
|
@@ -200,6 +220,7 @@ module Rserve
|
|
200
220
|
(bits & 0xfffffffffffff) | 0x10000000000000;
|
201
221
|
s*m*2**(e-1075)
|
202
222
|
end
|
223
|
+
|
203
224
|
def doubleToRawLongBits(double)
|
204
225
|
[double].pack("d").unpack("Q")[0]
|
205
226
|
end
|
data/lib/rserve/rexp.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Rserve
|
2
|
-
# Basic class representing an object of any type in R. Each type in R in represented by a specific subclass.
|
3
|
-
#
|
4
|
-
# This class defines basic accessor methods (<tt>as</tt><i>XXX</i>), type check methods (<tt>is</tt><i>XXX</i>), gives access to attributes ({@link #getAttribute}, {@link #hasAttribute}) as well as several convenience methods. If a given method is not applicable to a particular type, it will throw the {@link MismatchException} exception.
|
2
|
+
# Basic class representing an object of any type in R. Each type in R in represented by a specific subclass.
|
5
3
|
#
|
4
|
+
# This class defines basic accessor methods (<tt>as</tt>_<i>xxx</i>), type check methods (<i>XXX</i><tt>?</tt>), gives access to attributes (REXP.get_attribute, REXP.has_attribute?) as well as several convenience methods. If a given method is not applicable to a particular type, it will throw the MismatchException exception.
|
5
|
+
#
|
6
6
|
# This root class will throw on any accessor call and returns <code>false</code> for all type methods. This allows subclasses to override accessor and type methods selectively.
|
7
7
|
#
|
8
8
|
class REXP
|
@@ -16,181 +16,232 @@ module Rserve
|
|
16
16
|
# specifies how many items of a vector or list will be displayed in {@link #toDebugString}
|
17
17
|
MaxDebugItems = 32
|
18
18
|
# :section: type checks
|
19
|
-
|
20
|
-
#
|
21
|
-
|
19
|
+
|
20
|
+
# check whether the <code>REXP</code> object is a character vector (string).
|
21
|
+
#
|
22
|
+
# @return [boolean] <code>true</code> if the receiver is a character vector, <code>false</code> otherwise
|
22
23
|
def string?
|
23
24
|
false
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
|
-
|
27
|
+
# check whether the <code>REXP</code> object is a numeric vector.
|
28
|
+
#
|
29
|
+
# @return [boolean] <code>true</code> if the receiver is a numeric vector, <code>false</code> otherwise
|
28
30
|
|
29
31
|
def numeric?
|
30
32
|
false
|
31
33
|
end
|
32
|
-
# check whether the <code>REXP</code> object is an integer vector
|
33
|
-
#
|
34
|
+
# check whether the <code>REXP</code> object is an integer vector.
|
35
|
+
#
|
36
|
+
# @return [boolean] <code>true</code> if the receiver is an integer vector, <code>false</code> otherwise
|
34
37
|
def integer?
|
35
38
|
false
|
36
39
|
end
|
37
|
-
# check whether the <code>REXP</code> object is NULL
|
38
|
-
#
|
40
|
+
# check whether the <code>REXP</code> object is NULL.
|
41
|
+
#
|
42
|
+
# @return [boolean] <code>true</code> if the receiver is NULL, <code>false</code> otherwise
|
39
43
|
def null?
|
40
44
|
false
|
41
45
|
end
|
42
|
-
|
43
|
-
#
|
46
|
+
|
47
|
+
# check whether the <code>REXP</code> object is a factor.
|
48
|
+
#
|
49
|
+
# @return [boolean] <code>true</code> if the receiver is a factor, <code>false</code> otherwise
|
44
50
|
def factor?
|
45
51
|
false
|
46
52
|
end
|
47
|
-
|
48
|
-
#
|
53
|
+
|
54
|
+
# check whether the <code>REXP</code> object is a list (either generic vector or a pairlist - i.e. REXP.asList() will succeed).
|
55
|
+
#
|
56
|
+
# @return [boolean] <code>true</code> if the receiver is a generic vector or a pair-list, <code>false</code> otherwise
|
49
57
|
def list?
|
50
58
|
false
|
51
59
|
end
|
52
|
-
# check whether the <code>REXP</code> object is a pair-list
|
53
|
-
#
|
60
|
+
# check whether the <code>REXP</code> object is a pair-list.
|
61
|
+
#
|
62
|
+
# @return [boolean] <code>true</code> if the receiver is a pair-list, <code>false</code> otherwise
|
54
63
|
def pair_list?
|
55
64
|
false
|
56
65
|
end
|
57
|
-
# check whether the <code>REXP</code> object is a logical vector
|
58
|
-
#
|
66
|
+
# check whether the <code>REXP</code> object is a logical vector.
|
67
|
+
#
|
68
|
+
# @return [boolean] <code>true</code> if the receiver is a logical vector, <code>false</code> otherwise */
|
59
69
|
def logical?
|
60
70
|
false
|
61
71
|
end
|
62
|
-
#
|
63
|
-
#
|
72
|
+
# check whether the <code>REXP</code> object is an environment.
|
73
|
+
#
|
74
|
+
# @return [boolean] <code>true</code> if the receiver is an environment, <code>false</code> otherwise
|
64
75
|
def environment?
|
65
76
|
false
|
66
77
|
end
|
67
|
-
# check whether the <code>REXP</code> object is a language object
|
68
|
-
#
|
78
|
+
# check whether the <code>REXP</code> object is a language object.
|
79
|
+
#
|
80
|
+
# @return [boolean] <code>true</code> if the receiver is a language object, <code>false</code> otherwise
|
69
81
|
def language?
|
70
82
|
false
|
71
83
|
end
|
72
|
-
# check whether the <code>REXP</code> object is an expression vector
|
73
|
-
#
|
84
|
+
# check whether the <code>REXP</code> object is an expression vector.
|
85
|
+
#
|
86
|
+
# @return [boolean] <code>true</code> if the receiver is an expression vector, <code>false</code> otherwise
|
74
87
|
def expression?
|
75
88
|
false
|
76
89
|
end
|
77
|
-
# check whether the <code>REXP</code> object is a symbol
|
78
|
-
#
|
90
|
+
# check whether the <code>REXP</code> object is a symbol.
|
91
|
+
#
|
92
|
+
# @return [boolean] <code>true</code> if the receiver is a symbol, <code>false</code> otherwise
|
79
93
|
def symbol?
|
80
94
|
false
|
81
95
|
end
|
82
|
-
# check whether the <code>REXP</code> object is a vector
|
83
|
-
#
|
96
|
+
# check whether the <code>REXP</code> object is a vector.
|
97
|
+
#
|
98
|
+
# @return [boolean] <code>true</code> if the receiver is a vector, <code>false</code> otherwise
|
84
99
|
def vector?
|
85
100
|
false
|
86
101
|
end
|
87
102
|
# check whether the <code>REXP</code> object is a raw vector
|
88
|
-
# @return <code>true</code> if the receiver is a raw vector, <code>false</code> otherwise
|
103
|
+
# @return [boolean] <code>true</code> if the receiver is a raw vector, <code>false</code> otherwise
|
89
104
|
def raw?
|
90
105
|
false
|
91
106
|
end
|
92
107
|
# check whether the <code>REXP</code> object is a complex vector
|
93
|
-
# @return <code>true</code> if the receiver is a complex vector, <code>false</code> otherwise
|
108
|
+
# @return [boolean] <code>true</code> if the receiver is a complex vector, <code>false</code> otherwise
|
94
109
|
def complex?
|
95
110
|
false
|
96
111
|
end
|
97
112
|
# check whether the <code>REXP</code> object is a recursive obejct
|
98
|
-
# @return <code>true</code> if the receiver is a recursive object, <code>false</code> otherwise
|
113
|
+
# @return [boolean] <code>true</code> if the receiver is a recursive object, <code>false</code> otherwise
|
99
114
|
def recursive?
|
100
115
|
false
|
101
116
|
end
|
102
117
|
# check whether the <code>REXP</code> object is a reference to an R object
|
103
|
-
# @return <code>true</code> if the receiver is a reference, <code>false</code> otherwise
|
118
|
+
# @return [boolean] <code>true</code> if the receiver is a reference, <code>false</code> otherwise
|
104
119
|
def reference?
|
105
120
|
false
|
106
121
|
end
|
107
122
|
|
108
123
|
# :section: basic accessor methods
|
109
|
-
|
124
|
+
|
125
|
+
# returns the contents as an array of Strings (if supported by the represented object).
|
126
|
+
#
|
127
|
+
# @return [Array]
|
110
128
|
def as_strings
|
111
129
|
raise MismatchException, "String"
|
112
130
|
end
|
113
131
|
# returns the contents as an array of integers (if supported by the represented object)
|
132
|
+
#
|
133
|
+
# @return [Array]
|
114
134
|
|
115
135
|
def as_integers
|
116
136
|
raise MismatchException, "int"
|
117
137
|
end
|
118
138
|
|
119
|
-
# returns the contents as an array of
|
139
|
+
# returns the contents as an array of floats (C double precision) (if supported by the represented object).
|
140
|
+
#
|
141
|
+
# @return [Array]
|
142
|
+
|
120
143
|
def as_doubles
|
121
144
|
raise MismatchException,"double"
|
122
145
|
end
|
123
146
|
|
124
|
-
# On Ruby, Float are stored in double precision
|
147
|
+
# On Ruby, Float are stored in double precision.
|
148
|
+
#
|
149
|
+
# @return [Array]
|
125
150
|
def as_floats
|
126
151
|
as_doubles
|
127
152
|
end
|
128
153
|
|
129
|
-
# returns the contents as an array of bytes (if supported by the represented object)
|
154
|
+
# returns the contents as an array of bytes (if supported by the represented object).
|
155
|
+
#
|
156
|
+
# @return [Array]
|
157
|
+
|
130
158
|
def as_bytes
|
131
159
|
raise MismatchException , "byte"
|
132
160
|
end
|
133
161
|
# returns the contents as a (named) list (if supported by the represented object)
|
162
|
+
#
|
163
|
+
# @return [Array]
|
134
164
|
def as_list
|
135
165
|
raise MismatchException,"list"
|
136
166
|
end
|
137
|
-
# returns the contents as a factor (if supported by the represented object)
|
167
|
+
# returns the contents as a factor (if supported by the represented object).
|
168
|
+
#
|
169
|
+
# @return [RFactor]
|
138
170
|
def as_factor
|
139
171
|
raise MismatchException,"factor"
|
140
172
|
end
|
141
173
|
|
142
|
-
# returns the length of a vector object. Note that we use R semantics here, i.e. a matrix will have a length of <i>m * n</i> since it is represented by a single vector (see
|
143
|
-
#
|
144
|
-
#
|
174
|
+
# returns the length of a vector object. Note that we use R semantics here, i.e. a matrix will have a length of <i>m * n</i> since it is represented by a single vector (see REXP.dim) for retrieving matrix and multidimentional-array dimensions).
|
175
|
+
#
|
176
|
+
# @return [Integer] length (number of elements) in a vector object.
|
145
177
|
def length
|
146
178
|
raise MismatchException, "vector"
|
147
179
|
end
|
148
180
|
|
149
|
-
# returns a boolean vector of the same length as this vector with <code>true</code> for NA values and <code>false</code> for any other values
|
150
|
-
#
|
151
|
-
#
|
181
|
+
# returns a boolean vector of the same length as this vector with <code>true</code> for NA values and <code>false</code> for any other values.
|
182
|
+
#
|
183
|
+
# @return [boolean] a boolean vector of the same length as this vector with <code>true</code> for NA values and <code>false</code> for any other values.
|
184
|
+
#
|
152
185
|
def na?
|
153
186
|
raise MismatchException, "vector"
|
154
187
|
end
|
155
188
|
|
156
189
|
# :section: convenience accessor methods
|
190
|
+
|
191
|
+
|
157
192
|
# convenience method corresponding to <code>as_integer()[0]</code>
|
158
|
-
#
|
193
|
+
#
|
194
|
+
# @return [Integer] first entry returned by as_integers()
|
159
195
|
def as_integer
|
160
196
|
as_integers[0]
|
161
197
|
end
|
198
|
+
# Alias for as_integer().
|
199
|
+
#
|
200
|
+
# @return [Integer]
|
201
|
+
|
162
202
|
def to_i
|
163
203
|
as_integers[0]
|
164
204
|
end
|
165
|
-
# convenience method corresponding to <code>
|
166
|
-
#
|
205
|
+
# convenience method corresponding to <code>as_floats[0]</code>.
|
206
|
+
#
|
207
|
+
# @return [Float] first entry returned by as_doubles()
|
167
208
|
def as_double
|
168
209
|
as_doubles[0]
|
169
210
|
end
|
211
|
+
# Alias for as_double()
|
212
|
+
#
|
213
|
+
# @return [Float]
|
170
214
|
def as_float
|
171
215
|
as_double
|
172
216
|
end
|
217
|
+
# Alias for as_float()
|
218
|
+
#
|
219
|
+
# @return [Float]
|
173
220
|
def to_f
|
174
221
|
as_double
|
175
222
|
end
|
176
|
-
# convenience method corresponding to <code>
|
177
|
-
#
|
223
|
+
# convenience method corresponding to <code>as_strings[0]</code>.
|
224
|
+
#
|
225
|
+
# @return [String] first entry returned by REXP.as_strings
|
178
226
|
def as_string
|
179
227
|
as_strings[0]
|
180
228
|
end
|
181
|
-
# // methods common to all REXPs
|
182
229
|
|
183
|
-
#
|
184
|
-
|
185
|
-
#
|
230
|
+
# :section: methods common to all REXPs
|
231
|
+
|
232
|
+
# Retrieve an attribute of the given name from this object.
|
233
|
+
#
|
234
|
+
# @param [String] attribute name.
|
235
|
+
# @return [Rlist, nil] attribute value or <code>nil</code> if the attribute does not exist
|
186
236
|
|
187
237
|
def get_attribute(name)
|
188
238
|
has_attribute?(name) ? @attr.as_list[name] : nil
|
189
239
|
end
|
190
240
|
|
191
|
-
# checks whether this
|
192
|
-
#
|
193
|
-
#
|
241
|
+
# checks whether this object has a given attribute.
|
242
|
+
#
|
243
|
+
# @param [String] attribute name.
|
244
|
+
# @return [boolean] <code>true</code> if the attribute exists, <code>false</code> otherwise
|
194
245
|
def has_attribute? (name)
|
195
246
|
!@attr.nil? and @attr.list? and !@attr.as_list[name].nil?
|
196
247
|
end
|
@@ -198,8 +249,9 @@ module Rserve
|
|
198
249
|
|
199
250
|
# :section: helper methods common to all REXPs
|
200
251
|
|
201
|
-
#
|
202
|
-
#
|
252
|
+
# Returns dimensions of the object (as determined by the REXP::dim() attribute).
|
253
|
+
#
|
254
|
+
# @return [Array] an array of integers with corresponding dimensions or <code>nil</code> if the object has no dimension attribute
|
203
255
|
def dim
|
204
256
|
begin
|
205
257
|
return has_attribute?("dim") ? @attr.as_list['dim'].as_integers : nil;
|
@@ -209,9 +261,10 @@ module Rserve
|
|
209
261
|
nil
|
210
262
|
end
|
211
263
|
|
212
|
-
# determines whether this object inherits from a given class in the same fashion as the <code>inherits()</code> function in R does (i.e. ignoring S4 inheritance)
|
213
|
-
#
|
214
|
-
# @
|
264
|
+
# determines whether this object inherits from a given class in the same fashion as the <code>inherits()</code> function in R does (i.e. ignoring S4 inheritance).
|
265
|
+
#
|
266
|
+
# @param [String] klass class name.
|
267
|
+
# @return [boolean] <code>true</code> if this object is of the class <code>klass</code>, <code>false</code> otherwise.
|
215
268
|
def inherits?(klass)
|
216
269
|
return false if (!has_attribute? "class")
|
217
270
|
begin
|
@@ -226,20 +279,23 @@ module Rserve
|
|
226
279
|
|
227
280
|
|
228
281
|
|
229
|
-
# returns representation that it useful for debugging (e.g. it includes attributes and may include vector values
|
230
|
-
#
|
282
|
+
# returns representation that it useful for debugging (e.g. it includes attributes and may include vector values)
|
283
|
+
#
|
284
|
+
# @return [String] extended description of the obejct -- it may include vector values
|
231
285
|
def to_debug_string
|
232
286
|
(!@attr.nil?) ? (("<"+@attr.to_debug_string()+">")+to_s()) : to_s
|
233
287
|
end
|
234
288
|
|
235
289
|
|
236
|
-
|
290
|
+
# :section: complex convenience methods
|
291
|
+
|
292
|
+
|
237
293
|
# returns the content of the REXP as a ruby matrix of doubles (2D-array: m[rows][cols]). You could use Matrix.rows(result) to create
|
238
294
|
# a ruby matrix.
|
239
295
|
# Matrix(c.eval("matrix(c(1,2,3,4,5,6),2,3)").as_double_matrix());</code>
|
240
296
|
#
|
241
|
-
# @return 2D array of doubles in the form double[rows][cols] or <code>
|
242
|
-
def as_double_matrix
|
297
|
+
# @return [Array] 2D array of doubles in the form double[rows][cols] or <code>nil</code> if the contents is no 2-dimensional matrix of doubles
|
298
|
+
def as_double_matrix
|
243
299
|
ct = as_doubles()
|
244
300
|
dim = get_attribute "dim"
|
245
301
|
raise MismatchException, "matrix (dim attribute missing)" if dim.nil?
|
@@ -252,12 +308,16 @@ module Rserve
|
|
252
308
|
# we need to copy everything, since we create 2d array from 1d array
|
253
309
|
#r=m.times.map {|i| n.times.map {|j| ct[j*n+i]}}
|
254
310
|
end
|
255
|
-
# Returns a standard library's matrix
|
311
|
+
# Returns a standard library's matrix.
|
312
|
+
#
|
313
|
+
# @return [Matrix]
|
256
314
|
def as_matrix
|
257
315
|
require 'matrix'
|
258
316
|
Matrix.rows(as_double_matrix)
|
259
317
|
end
|
260
318
|
# Returns the content of the REXP as a serie of nested arrays of X dimensions
|
319
|
+
#
|
320
|
+
# @return [Array]
|
261
321
|
def as_nested_array
|
262
322
|
ct=as_doubles
|
263
323
|
dim = get_attribute "dim"
|
@@ -267,7 +327,7 @@ module Rserve
|
|
267
327
|
split_array(ct,ds)
|
268
328
|
end
|
269
329
|
|
270
|
-
def split_array(ar, dims)
|
330
|
+
def split_array(ar, dims) # :nodoc:
|
271
331
|
# puts "#{ar} - #{dims}"
|
272
332
|
if dims.size==1
|
273
333
|
raise "Improper size ar:#{ar} , dims=#{dims[0]}" if ar.size!=dims[0]
|
@@ -296,10 +356,10 @@ module Rserve
|
|
296
356
|
|
297
357
|
# :section: tools
|
298
358
|
|
299
|
-
# creates a data frame object from a list object using integer row names
|
300
|
-
#
|
301
|
-
# * @
|
302
|
-
#
|
359
|
+
# creates a data frame object from a list object using integer row names.
|
360
|
+
#
|
361
|
+
# * @param [Rlist] a (named) list of vectors (REXP::Vector subclasses), each element corresponds to a column and all elements must have the same length.
|
362
|
+
# * @return [GenericVector] a data frame object representation.
|
303
363
|
def self.create_data_frame(l)
|
304
364
|
raise(MismatchException, "data frame (must have dim>0)") if l.nil? or l.size<1
|
305
365
|
raise MismatchException, "data frame (contents must be vectors)" if (!(l[0].is_a? REXP::Vector))
|
@@ -321,7 +381,8 @@ module Rserve
|
|
321
381
|
# If R object has attributes, the Ruby object is extended with Rserve::WithAttributes.
|
322
382
|
# If R object is names, the Ruby object is extended with Rserve::WithNames and
|
323
383
|
# their elements can be accessed with [] using numbers and literals.
|
324
|
-
#
|
384
|
+
#
|
385
|
+
# @return [Object] Ruby object.
|
325
386
|
def to_ruby
|
326
387
|
#pp self
|
327
388
|
v=to_ruby_internal
|
@@ -346,6 +407,9 @@ module Rserve
|
|
346
407
|
|
347
408
|
v
|
348
409
|
end
|
410
|
+
# Return the bare-bone representation of REXP as a Ruby Object.
|
411
|
+
# Called by REXP.to_ruby, so shouldn't be used directly by developers.
|
412
|
+
#
|
349
413
|
def to_ruby_internal
|
350
414
|
raise "You should implement to_ruby_internal for #{self.class}"
|
351
415
|
end
|
data/lib/rserve/rexp/double.rb
CHANGED
@@ -7,6 +7,8 @@ module Rserve
|
|
7
7
|
case Config::CONFIG['arch']
|
8
8
|
when 'i686-linux'
|
9
9
|
NA = 269653970229425383598692395468593241088322026492507901905402939417320933254485890939796955099302180188971623023005661539310855695935759376615857567599472873400528811349204333736152257830107446553333670133666606746438802800063353690283455789426038632208916715592554825644961573453826957827246636338344317943808
|
10
|
+
when /mswin/
|
11
|
+
NA = 269653970229425383598692395468593241088322026492507901905402939417320933254485890939796955099302180188971623023005661539310855695935759376615857567599472873400528811349204333736152257830107446553333670133666606746438802800063353690283455789426038632208916715592554825644961573453826957827246636338344317943808
|
10
12
|
else
|
11
13
|
NA = 0x100000000007a2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
12
14
|
end
|
@@ -42,8 +44,13 @@ module Rserve
|
|
42
44
|
end
|
43
45
|
|
44
46
|
def na?(value=nil)
|
45
|
-
|
46
|
-
@payload.map {|v| v
|
47
|
+
#if value.nil?
|
48
|
+
# @payload.map {|v| v.respond_to? :nan and v.nan?}
|
49
|
+
#else
|
50
|
+
# value.respond_to? :nan? and value.nan?
|
51
|
+
#end
|
52
|
+
return value.to_i == NA unless value.nil?
|
53
|
+
@payload.map {|v| v.to_i==NA}
|
47
54
|
end
|
48
55
|
def to_debug_string
|
49
56
|
t=super
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Rserve
|
2
|
+
class Session
|
3
|
+
# serial version UID should only change if method signatures change
|
4
|
+
# significantly enough that previous versions cannot be used with
|
5
|
+
# current versions
|
6
|
+
include Rserve::Protocol
|
7
|
+
UID=-7048099825974875604
|
8
|
+
attr_reader :host
|
9
|
+
attr_reader :port
|
10
|
+
attr_reader :key
|
11
|
+
attr_reader :attach_packet
|
12
|
+
attr_reader :rsrv_version
|
13
|
+
def initialize(con,packet)
|
14
|
+
@host=con.hostname
|
15
|
+
@rsrv_version=con.rsrv_version
|
16
|
+
ct=packet.cont
|
17
|
+
if ct.nil? or ct.length!=32+3*4
|
18
|
+
raise "Invalid response to session detach request."
|
19
|
+
end
|
20
|
+
@port=get_int(ct,4)
|
21
|
+
@key=ct[12,32]
|
22
|
+
end
|
23
|
+
def attach
|
24
|
+
c=Rserve::Connection.new(:session=>self)
|
25
|
+
@attach_packet=c.rt.request(:cmd=>-1,:cont=>[])
|
26
|
+
c
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.dirname(__FILE__)+"/spec_helper.rb"
|
2
|
+
require 'rbconfig'
|
3
|
+
describe "Rserve::Connection on unix" do
|
4
|
+
before do
|
5
|
+
@r=Rserve::Connection.new
|
6
|
+
end
|
7
|
+
if RbConfig::CONFIG['arch']!~/mswin/
|
8
|
+
it "method eval_void should raise an error with an incorrect expression" do
|
9
|
+
lambda {@r.void_eval("x<-")}.should raise_exception(Rserve::Connection::EvalError) {|e| e.request_packet.stat.should==2}
|
10
|
+
lambda {@r.void_eval("as.stt(c(1))")}.should raise_exception(Rserve::Connection::EvalError) {|e|
|
11
|
+
e.request_packet.stat.should==127}
|
12
|
+
end
|
13
|
+
it "method eval should raise an error with an incorrect expression" do
|
14
|
+
lambda {@r.eval("x<-")}.should raise_exception(Rserve::Connection::EvalError) {|e| e.request_packet.stat.should==2}
|
15
|
+
lambda {@r.eval("as.stt(c(1))")}.should raise_exception(Rserve::Connection::EvalError) {|e|
|
16
|
+
e.request_packet.stat.should==127}
|
17
|
+
end
|
18
|
+
it "should raise ServerNotAvailable if started another instance on another port" do
|
19
|
+
lambda {Rserve::Connection.new(:port_number=>6700)}.should raise_exception(Rserve::Connection::ServerNotAvailable)
|
20
|
+
end
|
21
|
+
it "should create different session on *nix" do
|
22
|
+
s=Rserve::Connection.new
|
23
|
+
@r.assign("a", 1)
|
24
|
+
s.assign("a",2)
|
25
|
+
@r.eval('a').to_i.should==1
|
26
|
+
s.eval('a').to_i.should==2
|
27
|
+
s.close
|
28
|
+
end
|
29
|
+
else
|
30
|
+
it "shouldn't crash server with an incorrect expression as Windows version does"
|
31
|
+
it "shouldn't raise ServerNotAvailable if started another instance on another port as Windows version does"
|
32
|
+
it "shouldn create a different session. On Windows, every new connection closes previously open session"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
|
@@ -10,9 +10,6 @@ describe Rserve::Connection do
|
|
10
10
|
@r.last_error.should=="OK"
|
11
11
|
@r.rt.should be_instance_of(Rserve::Talk)
|
12
12
|
end
|
13
|
-
it "should raise ServerNotAvailable if started another instance on another port" do
|
14
|
-
lambda {Rserve::Connection.new(:port_number=>6700)}.should raise_exception(Rserve::Connection::ServerNotAvailable)
|
15
|
-
end
|
16
13
|
it "should quit correctly" do
|
17
14
|
@r.should be_connected
|
18
15
|
@r.close.should be_true
|
@@ -35,24 +32,31 @@ describe Rserve::Connection do
|
|
35
32
|
it "method eval_void should return true with correct expression" do
|
36
33
|
@r.void_eval("x<-1").should be_true
|
37
34
|
end
|
38
|
-
|
39
|
-
lambda {@r.void_eval("x<-")}.should raise_exception(Rserve::Connection::EvalError) {|e| e.request_packet.stat.should==2}
|
40
|
-
lambda {@r.void_eval("as.stt(c(1))")}.should raise_exception(Rserve::Connection::EvalError) {|e|
|
41
|
-
e.request_packet.stat.should==127}
|
42
|
-
end
|
43
|
-
|
35
|
+
|
44
36
|
it "method eval should return a simple object" do
|
45
37
|
la=@r.eval("TRUE")
|
46
38
|
la.should be_instance_of(Rserve::REXP::Logical)
|
47
39
|
la.true?.should==[true]
|
48
40
|
end
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
41
|
+
it "should eval_void_detach correctly" do
|
42
|
+
s=@r.void_eval_detach("x<-c(TRUE,FALSE)")
|
43
|
+
@r.should_not be_connected
|
44
|
+
s.should be_instance_of(Rserve::Session)
|
45
|
+
s.host.should==@r.hostname
|
46
|
+
s.key.size.should==32
|
47
|
+
end
|
48
|
+
it "should detach correctly" do
|
49
|
+
x=rand(100)
|
50
|
+
@r.void_eval("x<-#{x}")
|
51
|
+
s=@r.detach
|
52
|
+
@r.should_not be_connected
|
53
|
+
s.should be_instance_of(Rserve::Session)
|
54
|
+
s.host.should==@r.hostname
|
55
|
+
s.key.size.should==32
|
56
|
+
r=s.attach
|
57
|
+
r.eval("x").to_ruby==x
|
54
58
|
end
|
55
|
-
|
59
|
+
|
56
60
|
it "should eval_void and eval correctly" do
|
57
61
|
@r.void_eval("x<-c(TRUE,FALSE)").should be_true
|
58
62
|
la=@r.eval("x")
|
@@ -68,8 +72,10 @@ describe Rserve::Connection do
|
|
68
72
|
describe "assign using REXPs" do
|
69
73
|
before do
|
70
74
|
@r=Rserve::Connection.new
|
71
|
-
|
72
75
|
end
|
76
|
+
after do
|
77
|
+
@r.close
|
78
|
+
end
|
73
79
|
it "should assign double" do
|
74
80
|
rexp=Rserve::REXP::Double.new([1.5,-1.5])
|
75
81
|
@r.assign("x", rexp)
|
@@ -44,6 +44,7 @@ describe Rserve::Protocol do
|
|
44
44
|
buffer=[0xFF,0x78,0x56,0x34,0x12]
|
45
45
|
expected=0x12345678
|
46
46
|
@t.get_int(buffer,1).should==expected
|
47
|
+
@t.get_int(buffer,1).should==@t.get_int_original(buffer,1)
|
47
48
|
|
48
49
|
# Version with errors
|
49
50
|
|
@@ -51,6 +52,9 @@ describe Rserve::Protocol do
|
|
51
52
|
expected=0x12345678
|
52
53
|
@t.get_int(buffer,1).should==expected
|
53
54
|
end
|
55
|
+
|
56
|
+
|
57
|
+
|
54
58
|
it "get_len method should return correct length from a header" do
|
55
59
|
cmd=Rserve::Protocol::CMD_login
|
56
60
|
len=0x12345678
|
@@ -61,6 +65,7 @@ describe Rserve::Protocol do
|
|
61
65
|
buffer=[0xFF,0x78,0x56,0x34,0x12,0x78,0x56,0x34,0x12]
|
62
66
|
expected=0x1234567812345678
|
63
67
|
@t.get_long(buffer,1).should==expected
|
68
|
+
@t.get_long(buffer,1).should==@t.get_long_original(buffer,1)
|
64
69
|
|
65
70
|
end
|
66
71
|
it "set_long method should set correct long(32 bits) for a given buffer" do
|
@@ -7,7 +7,9 @@ describe Rserve::Protocol::REXPFactory do
|
|
7
7
|
before do
|
8
8
|
@r=Rserve::Connection.new
|
9
9
|
end
|
10
|
-
|
10
|
+
after do
|
11
|
+
@r.close
|
12
|
+
end
|
11
13
|
it "should process null" do
|
12
14
|
la=@r.eval("NULL")
|
13
15
|
la.should be_instance_of(Rserve::REXP::Null)
|
@@ -29,6 +31,7 @@ describe Rserve::Protocol::REXPFactory do
|
|
29
31
|
end
|
30
32
|
it "should process logical vectors with NA" do
|
31
33
|
la=@r.eval("c(TRUE,NA)")
|
34
|
+
|
32
35
|
la.should be_instance_of(Rserve::REXP::Logical)
|
33
36
|
la.na?.should==[false,true]
|
34
37
|
end
|
data/spec/rserve_rlist_spec.rb
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.dirname(__FILE__)+"/spec_helper.rb"
|
2
|
+
describe Rserve::Session do
|
3
|
+
before do
|
4
|
+
@r=Rserve::Connection.new
|
5
|
+
end
|
6
|
+
it "should resume an detached session with void_eval_detach" do
|
7
|
+
x2=10+rand(12)
|
8
|
+
s=@r.void_eval_detach("x<-1:#{x2}")
|
9
|
+
r=Rserve::Connection.new
|
10
|
+
r.void_eval("x<-1")
|
11
|
+
r.eval("x").to_ruby.should==1
|
12
|
+
s.should be_instance_of(Rserve::Session)
|
13
|
+
r2=s.attach
|
14
|
+
r2.eval("x").to_ruby.should==(1..x2).to_a
|
15
|
+
end
|
16
|
+
it "should resume an detached session with detach" do
|
17
|
+
x2=10+rand(12)
|
18
|
+
@r.void_eval("x<-1:#{x2}")
|
19
|
+
s=@r.detach
|
20
|
+
r=Rserve::Connection.new
|
21
|
+
r.void_eval("x<-1")
|
22
|
+
r.eval("x").to_ruby.should==1
|
23
|
+
s.should be_instance_of(Rserve::Session)
|
24
|
+
r2=s.attach
|
25
|
+
r2.eval("x").to_ruby.should==(1..x2).to_a
|
26
|
+
end
|
27
|
+
end
|
data/spec/rserve_spec.rb
CHANGED
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Claudio Bustos
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
rpP0jjs0
|
36
36
|
-----END CERTIFICATE-----
|
37
37
|
|
38
|
-
date: 2010-06-
|
38
|
+
date: 2010-06-16 00:00:00 -04:00
|
39
39
|
default_executable:
|
40
40
|
dependencies:
|
41
41
|
- !ruby/object:Gem::Dependency
|
@@ -62,8 +62,8 @@ dependencies:
|
|
62
62
|
segments:
|
63
63
|
- 2
|
64
64
|
- 6
|
65
|
-
-
|
66
|
-
version: 2.6.
|
65
|
+
- 1
|
66
|
+
version: 2.6.1
|
67
67
|
type: :development
|
68
68
|
version_requirements: *id002
|
69
69
|
description: |-
|
@@ -88,6 +88,10 @@ files:
|
|
88
88
|
- Manifest.txt
|
89
89
|
- README.txt
|
90
90
|
- Rakefile
|
91
|
+
- benchmark/benchmark.rb
|
92
|
+
- benchmark/comparison_2010_06_07.xls
|
93
|
+
- benchmark/comparison_2010_06_07_using_pack.xls
|
94
|
+
- benchmark/plot.rb
|
91
95
|
- data/gettysburg.txt
|
92
96
|
- examples/gettysburg.rb
|
93
97
|
- examples/hello_world.rb
|
@@ -120,9 +124,11 @@ files:
|
|
120
124
|
- lib/rserve/rexp/wrapper.rb
|
121
125
|
- lib/rserve/rfactor.rb
|
122
126
|
- lib/rserve/rlist.rb
|
127
|
+
- lib/rserve/session.rb
|
123
128
|
- lib/rserve/talk.rb
|
124
129
|
- lib/rserve/withattributes.rb
|
125
130
|
- lib/rserve/withnames.rb
|
131
|
+
- spec/rserve_connection_on_unix_spec.rb
|
126
132
|
- spec/rserve_connection_spec.rb
|
127
133
|
- spec/rserve_double_spec.rb
|
128
134
|
- spec/rserve_genericvector_spec.rb
|
@@ -136,6 +142,7 @@ files:
|
|
136
142
|
- spec/rserve_rexpfactory_spec.rb
|
137
143
|
- spec/rserve_rfactor_spec.rb
|
138
144
|
- spec/rserve_rlist_spec.rb
|
145
|
+
- spec/rserve_session_spec.rb
|
139
146
|
- spec/rserve_spec.rb
|
140
147
|
- spec/rserve_talk_spec.rb
|
141
148
|
- spec/rserve_withnames_spec.rb
|
@@ -181,11 +188,13 @@ test_files:
|
|
181
188
|
- spec/rserve_double_spec.rb
|
182
189
|
- spec/rserve_withnames_spec.rb
|
183
190
|
- spec/rserve_packet_spec.rb
|
191
|
+
- spec/rserve_connection_on_unix_spec.rb
|
184
192
|
- spec/rserve_rexpfactory_spec.rb
|
185
193
|
- spec/rserve_rexp_spec.rb
|
186
194
|
- spec/rserve_integer_spec.rb
|
187
195
|
- spec/rserve_spec.rb
|
188
196
|
- spec/rserve_protocol_spec.rb
|
189
197
|
- spec/rserve_genericvector_spec.rb
|
198
|
+
- spec/rserve_session_spec.rb
|
190
199
|
- spec/rserve_logical_spec.rb
|
191
200
|
- spec/rserve_talk_spec.rb
|
metadata.gz.sig
CHANGED
Binary file
|