scicom 0.2.0-java
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 +7 -0
- data/LICENSE.txt +674 -0
- data/README.md +66 -0
- data/README.md~ +290 -0
- data/Rakefile +51 -0
- data/config.rb +163 -0
- data/doc/PypeR.pdf +0 -0
- data/doc/Stat 133 Class Notes (Phil Spector).pdf +29905 -45
- data/doc/The R interface.docx +0 -0
- data/lib/JRubyR/as_mdarray.rb +60 -0
- data/lib/JRubyR/attributes.rb +74 -0
- data/lib/JRubyR/dataframe.rb +35 -0
- data/lib/JRubyR/environment.rb +60 -0
- data/lib/JRubyR/function.rb +61 -0
- data/lib/JRubyR/index.rb +278 -0
- data/lib/JRubyR/list.rb +56 -0
- data/lib/JRubyR/list_orig.rb +111 -0
- data/lib/JRubyR/logical_value.rb +56 -0
- data/lib/JRubyR/rbsexp.rb +386 -0
- data/lib/JRubyR/renjin.rb +431 -0
- data/lib/JRubyR/ruby_classes.rb +58 -0
- data/lib/JRubyR/sequence.rb +56 -0
- data/lib/JRubyR/vector.rb +493 -0
- data/lib/env.rb +12 -0
- data/lib/rinruby.rb +795 -0
- data/lib/scicom.rb +29 -0
- data/target/helper.jar +0 -0
- data/test/baseball.csv +1 -0
- data/test/env.rb +7 -0
- data/test/test_R_interface.rb +165 -0
- data/test/test_array.rb +191 -0
- data/test/test_attributes.rb +261 -0
- data/test/test_basic.rb +156 -0
- data/test/test_column-major.rb +114 -0
- data/test/test_complete.rb +49 -0
- data/test/test_creation.rb +299 -0
- data/test/test_dataframe.rb +248 -0
- data/test/test_distribution.rb +320 -0
- data/test/test_double_assign.rb +240 -0
- data/test/test_double_receive.rb +106 -0
- data/test/test_environment.rb +57 -0
- data/test/test_factor.rb +285 -0
- data/test/test_functions.rb +67 -0
- data/test/test_linear_model.rb +64 -0
- data/test/test_list.rb +220 -0
- data/test/test_matrix.rb +205 -0
- data/test/test_mdarray.rb +258 -0
- data/test/test_operators.rb +227 -0
- data/test/test_sequence.rb +63 -0
- data/test/test_subsetting.rb +67 -0
- data/test/test_tmp.rb +67 -0
- data/test/test_vector.rb +227 -0
- data/vendor/Renjin.pdf +0 -0
- data/vendor/renjin-script-engine-0.7.0-RC7-SNAPSHOT-jar-with-dependencies.jar +0 -0
- data/version.rb +2 -0
- metadata +196 -0
@@ -0,0 +1,431 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
##########################################################################################
|
4
|
+
# @author Rodrigo Botafogo
|
5
|
+
#
|
6
|
+
# Copyright © 2013 Rodrigo Botafogo. All Rights Reserved. Permission to use, copy, modify,
|
7
|
+
# and distribute this software and its documentation, without fee and without a signed
|
8
|
+
# licensing agreement, is hereby granted, provided that the above copyright notice, this
|
9
|
+
# paragraph and the following two paragraphs appear in all copies, modifications, and
|
10
|
+
# distributions.
|
11
|
+
#
|
12
|
+
# IN NO EVENT SHALL RODRIGO BOTAFOGO BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
|
13
|
+
# INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
|
14
|
+
# THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF RODRIGO BOTAFOGO HAS BEEN ADVISED OF THE
|
15
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
16
|
+
#
|
17
|
+
# RODRIGO BOTAFOGO SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
18
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
19
|
+
# SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
|
20
|
+
# RODRIGO BOTAFOGO HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
|
21
|
+
# OR MODIFICATIONS.
|
22
|
+
##########################################################################################
|
23
|
+
|
24
|
+
require 'java'
|
25
|
+
require 'securerandom'
|
26
|
+
|
27
|
+
require_relative 'rbsexp'
|
28
|
+
require_relative 'index'
|
29
|
+
|
30
|
+
|
31
|
+
#==========================================================================================
|
32
|
+
#
|
33
|
+
#==========================================================================================
|
34
|
+
|
35
|
+
class Renjin
|
36
|
+
include_package "javax.script"
|
37
|
+
include_package "org.renjin"
|
38
|
+
|
39
|
+
@stack = Array.new
|
40
|
+
|
41
|
+
class << self
|
42
|
+
attr_accessor :stack
|
43
|
+
end
|
44
|
+
|
45
|
+
#----------------------------------------------------------------------------------------
|
46
|
+
#
|
47
|
+
#----------------------------------------------------------------------------------------
|
48
|
+
|
49
|
+
attr_reader :engine
|
50
|
+
|
51
|
+
# Parse error
|
52
|
+
ParseError=Class.new(Exception)
|
53
|
+
|
54
|
+
#----------------------------------------------------------------------------------------
|
55
|
+
# R is invoked within a Ruby script (or the interactive "irb" prompt denoted >>) using:
|
56
|
+
#
|
57
|
+
# >> require "scicom"
|
58
|
+
#
|
59
|
+
# The previous statement reads the definition of the RinRuby class into the current Ruby
|
60
|
+
# interpreter and creates an instance of the RinRuby class named R. There is a second
|
61
|
+
# method for starting an instance of R which allows the user to use any name for the
|
62
|
+
# instance, in this case myr:
|
63
|
+
#
|
64
|
+
# >> require "scicom"
|
65
|
+
# >> myr = RinRuby.new
|
66
|
+
# >> myr.eval "rnorm(1)"
|
67
|
+
#
|
68
|
+
# Any number of independent instances of R can be created in this way.
|
69
|
+
#----------------------------------------------------------------------------------------
|
70
|
+
|
71
|
+
def initialize
|
72
|
+
|
73
|
+
@platform =
|
74
|
+
case RUBY_PLATFORM
|
75
|
+
when /mswin/ then 'windows'
|
76
|
+
when /mingw/ then 'windows'
|
77
|
+
when /bccwin/ then 'windows'
|
78
|
+
when /cygwin/ then 'windows-cygwin'
|
79
|
+
when /java/
|
80
|
+
require 'java' #:nodoc:
|
81
|
+
if java.lang.System.getProperty("os.name") =~ /[Ww]indows/
|
82
|
+
'windows-java'
|
83
|
+
else
|
84
|
+
'default-java'
|
85
|
+
end
|
86
|
+
else 'default'
|
87
|
+
end
|
88
|
+
|
89
|
+
factory = Java::JavaxScript.ScriptEngineManager.new()
|
90
|
+
@engine = factory.getEngineByName("Renjin")
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
#----------------------------------------------------------------------------------------
|
95
|
+
# Converts an MDArray shape or index onto an equivalent R shape or index
|
96
|
+
#----------------------------------------------------------------------------------------
|
97
|
+
|
98
|
+
def ri(shape)
|
99
|
+
|
100
|
+
rshape = shape.clone
|
101
|
+
|
102
|
+
if (rshape.size > 2)
|
103
|
+
rshape.reverse!
|
104
|
+
rshape[0], rshape[1] = rshape[1], rshape[0]
|
105
|
+
end
|
106
|
+
rshape.map{ |val| (val + 1) }
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
#----------------------------------------------------------------------------------------
|
111
|
+
#
|
112
|
+
#----------------------------------------------------------------------------------------
|
113
|
+
|
114
|
+
def nan?(x)
|
115
|
+
is__nan(x)
|
116
|
+
end
|
117
|
+
|
118
|
+
#----------------------------------------------------------------------------------------
|
119
|
+
# The integer constant used to designate elements or values that are
|
120
|
+
# missing in the statistical sense, or literally "Not Available".
|
121
|
+
# For integers (Fixnum) this is represented as the minimum integer from Java
|
122
|
+
# Integer.MIN_VALUE
|
123
|
+
#----------------------------------------------------------------------------------------
|
124
|
+
|
125
|
+
def na?(x)
|
126
|
+
R.is__na(x)
|
127
|
+
end
|
128
|
+
|
129
|
+
#----------------------------------------------------------------------------------------
|
130
|
+
#
|
131
|
+
#----------------------------------------------------------------------------------------
|
132
|
+
|
133
|
+
def finite?(x)
|
134
|
+
R.is__finite(x)
|
135
|
+
end
|
136
|
+
|
137
|
+
#----------------------------------------------------------------------------------------
|
138
|
+
#
|
139
|
+
#----------------------------------------------------------------------------------------
|
140
|
+
|
141
|
+
def method_missing(symbol, *args)
|
142
|
+
|
143
|
+
name = symbol.id2name
|
144
|
+
name.gsub!(/__/,".")
|
145
|
+
# Method 'rclass' is a substitute for R method 'class'. Needed, as 'class' is also
|
146
|
+
# a Ruby method on an object
|
147
|
+
name.gsub!("rclass", "class")
|
148
|
+
|
149
|
+
if name =~ /(.*)=$/
|
150
|
+
super if args.length != 1
|
151
|
+
ret = assign($1,args[0])
|
152
|
+
else
|
153
|
+
# super if args.length != 0
|
154
|
+
if (args.length == 0)
|
155
|
+
# is_var = false
|
156
|
+
# Try to see if name is a variable or a method.
|
157
|
+
ret = (eval("\"#{name}\" %in% ls()").gt)? eval("#{name}") : eval("#{name}()")
|
158
|
+
else
|
159
|
+
params = parse(*args)
|
160
|
+
# p "#{name}(#{params})"
|
161
|
+
ret = eval("#{name}(#{params})")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
ret
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
#----------------------------------------------------------------------------------------
|
170
|
+
# R built-in constants
|
171
|
+
#----------------------------------------------------------------------------------------
|
172
|
+
|
173
|
+
def pi
|
174
|
+
R.eval("pi")
|
175
|
+
end
|
176
|
+
|
177
|
+
def LETTERS
|
178
|
+
R.eval("LETTERS")
|
179
|
+
end
|
180
|
+
|
181
|
+
def letters
|
182
|
+
R.eval("letters")
|
183
|
+
end
|
184
|
+
|
185
|
+
def month__abb
|
186
|
+
R.eval("month.abb")
|
187
|
+
end
|
188
|
+
|
189
|
+
def month__name
|
190
|
+
R.eval("month.name")
|
191
|
+
end
|
192
|
+
|
193
|
+
def i(value)
|
194
|
+
R.eval("#{value}L")
|
195
|
+
end
|
196
|
+
|
197
|
+
def d(value)
|
198
|
+
R.eval("#{value}")
|
199
|
+
end
|
200
|
+
|
201
|
+
#----------------------------------------------------------------------------------------
|
202
|
+
#
|
203
|
+
#----------------------------------------------------------------------------------------
|
204
|
+
|
205
|
+
def eval(expression)
|
206
|
+
begin
|
207
|
+
ret = Renjin::RubySexp.build(@engine.eval(expression))
|
208
|
+
rescue Java::OrgRenjinEval::EvalException => e
|
209
|
+
p e.message
|
210
|
+
rescue Java::OrgRenjinParser::ParseException => e
|
211
|
+
p e.message
|
212
|
+
ensure
|
213
|
+
Renjin.stack.each do |sexp|
|
214
|
+
sexp.destroy
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
ret
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
#----------------------------------------------------------------------------------------
|
223
|
+
# Evaluates an expression but does not wrap the return in a RubySexp. Needed for
|
224
|
+
# intermediate evaluation done by internal methods. In principle, should not be
|
225
|
+
# called by users.
|
226
|
+
#----------------------------------------------------------------------------------------
|
227
|
+
|
228
|
+
def direct_eval(expression)
|
229
|
+
begin
|
230
|
+
ret = @engine.eval(expression)
|
231
|
+
rescue Java::OrgRenjinEval::EvalException => e
|
232
|
+
p e.message
|
233
|
+
ensure
|
234
|
+
=begin
|
235
|
+
Renjin.stack.each do |sexp|
|
236
|
+
sexp.destroy
|
237
|
+
end
|
238
|
+
=end
|
239
|
+
end
|
240
|
+
|
241
|
+
ret
|
242
|
+
|
243
|
+
end
|
244
|
+
|
245
|
+
#----------------------------------------------------------------------------------------
|
246
|
+
#
|
247
|
+
#----------------------------------------------------------------------------------------
|
248
|
+
|
249
|
+
def parse(*args)
|
250
|
+
|
251
|
+
params = Array.new
|
252
|
+
|
253
|
+
args.each do |arg|
|
254
|
+
if (arg.is_a? Numeric)
|
255
|
+
params << arg
|
256
|
+
elsif(arg.is_a? String)
|
257
|
+
params << "\"#{arg}\""
|
258
|
+
elsif (arg.is_a? Symbol)
|
259
|
+
var = eval("#{arg.to_s}")
|
260
|
+
params << var.r
|
261
|
+
elsif (arg.is_a? TrueClass)
|
262
|
+
params << "TRUE"
|
263
|
+
elsif (arg.is_a? FalseClass)
|
264
|
+
params << "FALSE"
|
265
|
+
elsif (arg == nil)
|
266
|
+
params << "NULL"
|
267
|
+
elsif (arg.is_a? NegRange)
|
268
|
+
final_value = (arg.exclude_end?)? (arg.end - 1) : arg.end
|
269
|
+
params << "-(#{arg.begin}:#{final_value})"
|
270
|
+
elsif (arg.is_a? Range)
|
271
|
+
final_value = (arg.exclude_end?)? (arg.end - 1) : arg.end
|
272
|
+
params << "(#{arg.begin}:#{final_value})"
|
273
|
+
elsif (arg.is_a? Hash)
|
274
|
+
arg.each_pair do |key, value|
|
275
|
+
params << "#{key.to_s} = #{parse(value)}"
|
276
|
+
end
|
277
|
+
elsif ((arg.is_a? Renjin::RubySexp) || (arg.is_a? Array) || (arg.is_a? MDArray))
|
278
|
+
params << arg.r
|
279
|
+
# elsif
|
280
|
+
# params << arg.inspect
|
281
|
+
else
|
282
|
+
raise "Unknown parameter type for R: #{arg}"
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|
286
|
+
|
287
|
+
params.join(",")
|
288
|
+
|
289
|
+
end
|
290
|
+
|
291
|
+
#----------------------------------------------------------------------------------------
|
292
|
+
# Data is copied from Ruby to R using the assign method or a short-hand equivalent. For
|
293
|
+
# example:
|
294
|
+
#
|
295
|
+
# >> names = ["Lisa","Teasha","Aaron","Thomas"]
|
296
|
+
# >> R.assign "people", names
|
297
|
+
# >> R.eval "sort(people)"
|
298
|
+
#
|
299
|
+
#produces the following :
|
300
|
+
#
|
301
|
+
# [1] "Aaron" "Lisa" "Teasha" "Thomas"
|
302
|
+
#
|
303
|
+
# The short-hand equivalent to the assign method is simply:
|
304
|
+
#
|
305
|
+
# >> R.people = names
|
306
|
+
#
|
307
|
+
# Some care is needed when using the short-hand of the assign method since the label
|
308
|
+
# (i.e., people in this case) must be a valid method name in Ruby. For example,
|
309
|
+
# R.copy.of.names = names will not work, but R.copy_of_names = names is permissible.
|
310
|
+
#
|
311
|
+
# The assign method supports Ruby variables of type Fixnum (i.e., integer), Bignum
|
312
|
+
# (i.e., integer), Float (i.e., double), String, and arrays of one of those three
|
313
|
+
# fundamental types. Note that Fixnum or Bignum values that exceed the capacity of R's
|
314
|
+
# integers are silently converted to doubles. Data in other formats must be coerced
|
315
|
+
# when copying to R.
|
316
|
+
#
|
317
|
+
# <b>Parameters that can be passed to the assign method:</b>
|
318
|
+
#
|
319
|
+
# * name: The name of the variable desired in R.
|
320
|
+
# * value: The value the R variable should have.
|
321
|
+
#
|
322
|
+
# The assign method is an alternative to the simplified method, with some additional
|
323
|
+
# flexibility. When using the simplified method, the parameters of name and value are
|
324
|
+
# automatically used, in other words:
|
325
|
+
#
|
326
|
+
# >> R.test = 144
|
327
|
+
#
|
328
|
+
# is the same as:
|
329
|
+
#
|
330
|
+
# >> R.assign("test",144)
|
331
|
+
#
|
332
|
+
# Of course it would be confusing to use the shorthand notation to assign a variable
|
333
|
+
# named eval, echo, or any other already defined function. RinRuby would assume you were
|
334
|
+
# calling the function, rather than trying to assign a variable.
|
335
|
+
#
|
336
|
+
# When assigning an array containing differing types of variables, RinRuby will follow
|
337
|
+
# R’s conversion conventions. An array that contains any Strings will result in a
|
338
|
+
# character vector in R. If the array does not contain any Strings, but it does contain
|
339
|
+
# a Float or a large integer (in absolute value), then the result will be a numeric
|
340
|
+
# vector of Doubles in R. If there are only integers that are suffciently small (in
|
341
|
+
# absolute value), then the result will be a numeric vector of integers in R.
|
342
|
+
#----------------------------------------------------------------------------------------
|
343
|
+
|
344
|
+
def assign(name, value)
|
345
|
+
|
346
|
+
original_value = value
|
347
|
+
|
348
|
+
if ((value.is_a? MDArray) || (value.is_a? RubySexp))
|
349
|
+
if (value.sexp != nil)
|
350
|
+
# MDArray already represented in R
|
351
|
+
value = value.sexp
|
352
|
+
else
|
353
|
+
value = build_vector(value)
|
354
|
+
end
|
355
|
+
elsif (value == nil)
|
356
|
+
value = NULL
|
357
|
+
end
|
358
|
+
|
359
|
+
@engine.put(name, value)
|
360
|
+
original_value
|
361
|
+
|
362
|
+
end
|
363
|
+
|
364
|
+
#----------------------------------------------------------------------------------------
|
365
|
+
#
|
366
|
+
#----------------------------------------------------------------------------------------
|
367
|
+
|
368
|
+
def pull(name)
|
369
|
+
eval(name)
|
370
|
+
end
|
371
|
+
|
372
|
+
#----------------------------------------------------------------------------------------
|
373
|
+
# function is either a function name alone represented by a ruby symbol or a hash
|
374
|
+
# with the function name and its arguments or indexes
|
375
|
+
# Ex:
|
376
|
+
# fassign(sexp, :rowname, "x1")
|
377
|
+
# fassign(sexp, {f: :rowname, index: [[1]]}, "x1")
|
378
|
+
# fassign(sexp, {f: :somefunc, params: "(2, 3, 4)"}, "x1")
|
379
|
+
#----------------------------------------------------------------------------------------
|
380
|
+
|
381
|
+
def fassign(sexp, function, value)
|
382
|
+
|
383
|
+
if (function.is_a? Hash)
|
384
|
+
index = function[:index]
|
385
|
+
params = function[:params]
|
386
|
+
function = function[:f]
|
387
|
+
if (index)
|
388
|
+
R.eval("#{function.to_s}(#{sexp.r})#{index} = #{value.r}")
|
389
|
+
else
|
390
|
+
end
|
391
|
+
else
|
392
|
+
R.eval("#{function.to_s}(#{sexp.r}) = #{value.r}")
|
393
|
+
end
|
394
|
+
|
395
|
+
end
|
396
|
+
|
397
|
+
#----------------------------------------------------------------------------------------
|
398
|
+
# Builds a Renjin vector from an MDArray. Should be private, but public for testing.
|
399
|
+
#----------------------------------------------------------------------------------------
|
400
|
+
|
401
|
+
def build_vector(array)
|
402
|
+
|
403
|
+
shape = array.shape
|
404
|
+
index = array.nc_array.getIndex()
|
405
|
+
# index = MDArray.index_factory(shape)
|
406
|
+
# representation of shape in R is different from shape in MDArray. Convert MDArray
|
407
|
+
# shape to R shape.
|
408
|
+
if (shape.size > 2)
|
409
|
+
shape.reverse!
|
410
|
+
shape[0], shape[1] = shape[1], shape[0]
|
411
|
+
end
|
412
|
+
# AttributeMap attributes = AttributeMap.builder().setDim(new IntVector(dim)).build();
|
413
|
+
attributes = Java::OrgRenjinSexp::AttributeMap.builder()
|
414
|
+
.setDim(Java::OrgRenjinSexp::IntArrayVector.new(*(shape))).build()
|
415
|
+
vector = Java::RbScicom::MDDoubleVector.new(array.nc_array, attributes, index,
|
416
|
+
index.stride)
|
417
|
+
|
418
|
+
end
|
419
|
+
|
420
|
+
|
421
|
+
end
|
422
|
+
|
423
|
+
# Create a new R interpreter
|
424
|
+
R = Renjin.new
|
425
|
+
NA = R.eval("NA")
|
426
|
+
NaN = R.eval("NaN")
|
427
|
+
Inf = R.eval("Inf")
|
428
|
+
MInf = R.eval("-Inf")
|
429
|
+
NULL = R.direct_eval("NULL")
|
430
|
+
# EPSILON = R.eval("EPSILON")
|
431
|
+
# NA_integer = R.eval("NA_integer")
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
##########################################################################################
|
4
|
+
# @author Rodrigo Botafogo
|
5
|
+
#
|
6
|
+
# Copyright © 2013 Rodrigo Botafogo. All Rights Reserved. Permission to use, copy, modify,
|
7
|
+
# and distribute this software and its documentation, without fee and without a signed
|
8
|
+
# licensing agreement, is hereby granted, provided that the above copyright notice, this
|
9
|
+
# paragraph and the following two paragraphs appear in all copies, modifications, and
|
10
|
+
# distributions.
|
11
|
+
#
|
12
|
+
# IN NO EVENT SHALL RODRIGO BOTAFOGO BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
|
13
|
+
# INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
|
14
|
+
# THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF RODRIGO BOTAFOGO HAS BEEN ADVISED OF THE
|
15
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
16
|
+
#
|
17
|
+
# RODRIGO BOTAFOGO SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
18
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
19
|
+
# SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
|
20
|
+
# RODRIGO BOTAFOGO HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
|
21
|
+
# OR MODIFICATIONS.
|
22
|
+
##########################################################################################
|
23
|
+
|
24
|
+
#==========================================================================================
|
25
|
+
#
|
26
|
+
#==========================================================================================
|
27
|
+
|
28
|
+
class Range
|
29
|
+
include Renjin::RBSexp
|
30
|
+
|
31
|
+
#----------------------------------------------------------------------------------------
|
32
|
+
# Defines unary minus operation for ranges
|
33
|
+
#----------------------------------------------------------------------------------------
|
34
|
+
|
35
|
+
def -@
|
36
|
+
NegRange.new(self.begin, self.end)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
#==========================================================================================
|
42
|
+
# Class NegRange exists to represent a negative range, e.g., -(1...10). Such a range is
|
43
|
+
# used to index vectors and means all elements but the ones in the given range. Class
|
44
|
+
# NegRange is parsed to become "-(1:10)" in R.
|
45
|
+
#==========================================================================================
|
46
|
+
|
47
|
+
class NegRange < Range
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
#==========================================================================================
|
52
|
+
#
|
53
|
+
#==========================================================================================
|
54
|
+
|
55
|
+
class Array
|
56
|
+
include Renjin::RBSexp
|
57
|
+
|
58
|
+
end
|