rust 0.3 → 0.9
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 +4 -4
- data/bin/ruby-rust +3 -0
- data/lib/{rust-csv.rb → rust/core/csv.rb} +14 -4
- data/lib/rust/core/rust.rb +157 -0
- data/lib/rust/core/types/all.rb +4 -0
- data/lib/{rust-core.rb → rust/core/types/dataframe.rb} +183 -245
- data/lib/rust/core/types/datatype.rb +161 -0
- data/lib/rust/core/types/factor.rb +131 -0
- data/lib/rust/core/types/language.rb +166 -0
- data/lib/rust/core/types/list.rb +81 -0
- data/lib/rust/core/types/matrix.rb +132 -0
- data/lib/rust/core/types/s4class.rb +59 -0
- data/lib/rust/core/types/utils.rb +109 -0
- data/lib/rust/core.rb +7 -0
- data/lib/rust/models/all.rb +4 -0
- data/lib/rust/models/anova.rb +60 -0
- data/lib/rust/models/regression.rb +205 -0
- data/lib/rust/plots/all.rb +4 -0
- data/lib/rust/plots/basic-plots.rb +111 -0
- data/lib/{rust-plots.rb → rust/plots/core.rb} +64 -129
- data/lib/rust/plots/distribution-plots.rb +62 -0
- data/lib/rust/stats/all.rb +4 -0
- data/lib/{rust-basics.rb → rust/stats/correlation.rb} +11 -5
- data/lib/rust/stats/descriptive.rb +128 -0
- data/lib/{rust-effsize.rb → rust/stats/effsize.rb} +23 -21
- data/lib/rust/stats/probabilities.rb +248 -0
- data/lib/rust/stats/tests.rb +292 -0
- data/lib/rust.rb +4 -8
- metadata +31 -12
- data/lib/rust-calls.rb +0 -69
- data/lib/rust-descriptive.rb +0 -59
- data/lib/rust-tests.rb +0 -165
@@ -0,0 +1,131 @@
|
|
1
|
+
require_relative 'datatype'
|
2
|
+
|
3
|
+
module Rust
|
4
|
+
class Factor < RustDatatype
|
5
|
+
def self.can_pull?(type, klass)
|
6
|
+
return klass == "factor"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.pull_variable(variable, type, klass)
|
10
|
+
levels = Rust["levels(#{variable})"]
|
11
|
+
values = Rust["as.integer(#{variable})"]
|
12
|
+
|
13
|
+
return Factor.new(values, levels)
|
14
|
+
end
|
15
|
+
|
16
|
+
def load_in_r_as(variable_name)
|
17
|
+
Rust['tmp.levels'] = @levels.map { |v| v.to_s }
|
18
|
+
Rust['tmp.values'] = @values
|
19
|
+
|
20
|
+
Rust._eval("#{variable_name} <- factor(tmp.values, labels=tmp.levels)")
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(values, levels)
|
24
|
+
@levels = levels.map { |v| v.to_sym }
|
25
|
+
@values = values
|
26
|
+
end
|
27
|
+
|
28
|
+
def levels
|
29
|
+
@levels
|
30
|
+
end
|
31
|
+
|
32
|
+
def ==(other)
|
33
|
+
return false unless other.is_a?(Factor)
|
34
|
+
|
35
|
+
return @levels == other.levels && self.to_a == other.to_a
|
36
|
+
end
|
37
|
+
|
38
|
+
def [](i)
|
39
|
+
FactorValue.new(@values[i], @levels[@values[i] - 1])
|
40
|
+
end
|
41
|
+
|
42
|
+
def []=(i, value)
|
43
|
+
raise "The given value is outside the factor bounds" if value.is_a?(Integer) && (value < 1 || value > @levels.size)
|
44
|
+
|
45
|
+
if value.is_a?(FactorValue)
|
46
|
+
raise "Incompatible factor value, different levels used" unless @levels.include?(value.level) || @levels.index(value.level) + 1 == @value.value
|
47
|
+
value = value.value
|
48
|
+
end
|
49
|
+
|
50
|
+
if value.is_a?(String) || value.is_a?(Symbol)
|
51
|
+
value = value.to_sym
|
52
|
+
raise "Unsupported value #{value}; expected #{@levels.join(", ")}" unless @levels.include?(value)
|
53
|
+
|
54
|
+
value = @levels.index(value) + 1
|
55
|
+
end
|
56
|
+
|
57
|
+
@values[i] = value
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_a
|
61
|
+
@values.map { |v| FactorValue.new(v, @levels[v - 1]) }
|
62
|
+
end
|
63
|
+
|
64
|
+
def method_missing(method, *args, &block)
|
65
|
+
raise NoMethodError, "Undefined method #{method} for Factor" if method.to_s.end_with?("!") || method.end_with?("=")
|
66
|
+
|
67
|
+
self.to_a.method(method).call(*args, &block)
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_s
|
71
|
+
self.to_a.to_s
|
72
|
+
end
|
73
|
+
|
74
|
+
def inspect
|
75
|
+
self.to_a.inspect
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class FactorValue
|
80
|
+
def initialize(value, level)
|
81
|
+
@value = value
|
82
|
+
@level = level
|
83
|
+
end
|
84
|
+
|
85
|
+
def value
|
86
|
+
@value
|
87
|
+
end
|
88
|
+
|
89
|
+
def level
|
90
|
+
@level
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_i
|
94
|
+
@value
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_sym
|
98
|
+
@level
|
99
|
+
end
|
100
|
+
|
101
|
+
def to_R
|
102
|
+
self.to_i
|
103
|
+
end
|
104
|
+
|
105
|
+
def inspect
|
106
|
+
@level.inspect
|
107
|
+
end
|
108
|
+
|
109
|
+
def ==(other)
|
110
|
+
if other.is_a?(FactorValue)
|
111
|
+
@value == other.value && @level == other.level
|
112
|
+
elsif other.is_a?(Integer)
|
113
|
+
@value == other
|
114
|
+
elsif other.is_a?(Symbol)
|
115
|
+
@level == other
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def hash
|
120
|
+
@value.hash + @level.hash
|
121
|
+
end
|
122
|
+
|
123
|
+
def eql?(other)
|
124
|
+
return self == other
|
125
|
+
end
|
126
|
+
|
127
|
+
def method_missing(method, *args, &block)
|
128
|
+
@level.method(method).call(*args, &block)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require_relative 'datatype'
|
2
|
+
|
3
|
+
module Rust
|
4
|
+
class Formula < RustDatatype
|
5
|
+
def self.can_pull?(type, klass)
|
6
|
+
return klass == "formula" || (klass.is_a?(Array) && klass.include?("formula"))
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.pull_variable(variable, type, klass)
|
10
|
+
formula_elements = Rust._pull("as.character(#{variable})")
|
11
|
+
|
12
|
+
assert("The number of elements of a formula must be 2 or 3: #{formula_elements} given") { formula_elements.size > 1 && formula_elements.size < 4 }
|
13
|
+
if formula_elements.size == 2
|
14
|
+
return Formula.new(nil, formula_elements[1])
|
15
|
+
elsif formula_elements.size == 3
|
16
|
+
return Formula.new(formula_elements[2], formula_elements[1])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def load_in_r_as(variable_name)
|
21
|
+
Rust._eval("#{variable_name} <- #{self.left_part} ~ #{self.right_part}")
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :left_part
|
25
|
+
attr_reader :right_part
|
26
|
+
|
27
|
+
def initialize(left_part, right_part)
|
28
|
+
raise ArgumentError, "Expected string" if left_part && !left_part.is_a?(String)
|
29
|
+
raise ArgumentError, "Expected string" if !right_part.is_a?(String)
|
30
|
+
|
31
|
+
@left_part = left_part || ""
|
32
|
+
@right_part = right_part
|
33
|
+
end
|
34
|
+
|
35
|
+
def ==(oth)
|
36
|
+
return false unless oth.is_a?(Formula)
|
37
|
+
|
38
|
+
return @left_part == oth.left_part && @right_part == oth.right_part
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_R
|
42
|
+
return "#@left_part ~ #@right_part"
|
43
|
+
end
|
44
|
+
|
45
|
+
def inspect
|
46
|
+
return self.to_R.strip
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Call < RustDatatype
|
51
|
+
def self.can_pull?(type, klass)
|
52
|
+
return klass == "call"
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.pull_variable(variable, type, klass)
|
56
|
+
return Call.new(Rust["deparse(#{variable})"])
|
57
|
+
end
|
58
|
+
|
59
|
+
def load_in_r_as(variable_name)
|
60
|
+
Rust["call.str"] = @value
|
61
|
+
Rust._eval("#{variable_name} <- str2lang(call.str)")
|
62
|
+
end
|
63
|
+
|
64
|
+
def initialize(value)
|
65
|
+
@value = value
|
66
|
+
end
|
67
|
+
|
68
|
+
def value
|
69
|
+
@value
|
70
|
+
end
|
71
|
+
|
72
|
+
def inspect
|
73
|
+
@value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Environment < RustDatatype
|
78
|
+
def self.can_pull?(type, klass)
|
79
|
+
return type == "environment" && klass == "environment"
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.pull_variable(variable, type, klass)
|
83
|
+
warn "Exchanging R environments is not supported!"
|
84
|
+
return Environment.new
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.load_in_r_as(variable)
|
88
|
+
warn "Exchanging R environments is not supported!"
|
89
|
+
Rust._eval("#{variable} <- environment()")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class Function
|
94
|
+
attr_reader :name
|
95
|
+
attr_reader :arguments
|
96
|
+
attr_reader :options
|
97
|
+
|
98
|
+
def initialize(name)
|
99
|
+
@function = name
|
100
|
+
@arguments = Arguments.new
|
101
|
+
@options = Options.new
|
102
|
+
end
|
103
|
+
|
104
|
+
def options=(options)
|
105
|
+
raise TypeError, "Expected Options" unless options.is_a?(Options)
|
106
|
+
|
107
|
+
@options = options
|
108
|
+
end
|
109
|
+
|
110
|
+
def arguments=(arguments)
|
111
|
+
raise TypeError, "Expected Arguments" unless options.is_a?(Arguments)
|
112
|
+
|
113
|
+
@arguments = arguments
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_R
|
117
|
+
params = [@arguments.to_R, @options.to_R].select { |v| v != "" }.join(",")
|
118
|
+
return "#@function(#{params})"
|
119
|
+
end
|
120
|
+
|
121
|
+
def call
|
122
|
+
Rust._eval(self.to_R)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
class SimpleFormula
|
127
|
+
def initialize(dependent, independent)
|
128
|
+
@dependent = dependent
|
129
|
+
@independent = independent
|
130
|
+
end
|
131
|
+
|
132
|
+
def to_R
|
133
|
+
return "#@dependent ~ #@independent"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class Variable
|
138
|
+
def initialize(name)
|
139
|
+
@name = name
|
140
|
+
end
|
141
|
+
|
142
|
+
def to_R
|
143
|
+
@name
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class Arguments < Array
|
148
|
+
def to_R
|
149
|
+
return self.map { |v| v.to_R }.join(", ")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
class Options < Hash
|
154
|
+
def to_R
|
155
|
+
return self.map { |k, v| "#{k}=#{v.to_R}" }.join(", ")
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.from_hash(hash)
|
159
|
+
options = Options.new
|
160
|
+
hash.each do |key, value|
|
161
|
+
options[key.to_s] = value
|
162
|
+
end
|
163
|
+
return options
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require_relative 'datatype'
|
2
|
+
|
3
|
+
module Rust
|
4
|
+
class List < RustDatatype
|
5
|
+
def self.can_pull?(type, klass)
|
6
|
+
return type == "list"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.pull_variable(variable, type, klass)
|
10
|
+
return List.new(klass) if Rust._pull("length(#{variable})") == 0
|
11
|
+
|
12
|
+
names = [Rust["names(#{variable})"]].flatten
|
13
|
+
length = Rust["length(#{variable})"]
|
14
|
+
|
15
|
+
list = List.new(klass, names)
|
16
|
+
for i in 0...length
|
17
|
+
list[i] = Rust["#{variable}[[#{i + 1}]]"]
|
18
|
+
end
|
19
|
+
|
20
|
+
return list
|
21
|
+
end
|
22
|
+
|
23
|
+
def load_in_r_as(variable_name)
|
24
|
+
Rust._eval("#{variable_name} <- list()")
|
25
|
+
@data.each do |key, value|
|
26
|
+
Rust["#{variable_name}[[#{key + 1}]]"] = value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(klass, names = [])
|
31
|
+
@data = {}
|
32
|
+
@names = names
|
33
|
+
@klass = klass
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](key)
|
37
|
+
key = get_key(key)
|
38
|
+
|
39
|
+
return @data[key]
|
40
|
+
end
|
41
|
+
alias :| :[]
|
42
|
+
|
43
|
+
def []=(key, value)
|
44
|
+
key = get_key(key)
|
45
|
+
|
46
|
+
return @data[key] = value
|
47
|
+
end
|
48
|
+
|
49
|
+
def names
|
50
|
+
@names
|
51
|
+
end
|
52
|
+
|
53
|
+
def inspect
|
54
|
+
result = ""
|
55
|
+
values_inspected = @data.map { |k, v| [k, v.inspect.split("\n").map { |l| " " + l }.join("\n")] }.to_h
|
56
|
+
max_length = [values_inspected.map { |k, v| v.split("\n").map { |line| line.length }.max.to_i }.max.to_i, 100].min
|
57
|
+
|
58
|
+
@data.keys.each do |i|
|
59
|
+
result << "-" * max_length + "\n"
|
60
|
+
result << (@names[i] || "[[#{i}]]") + "\n"
|
61
|
+
result << values_inspected[i] + "\n"
|
62
|
+
end
|
63
|
+
result << "-" * max_length
|
64
|
+
|
65
|
+
return result
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
def get_key(key)
|
70
|
+
if key.is_a?(String)
|
71
|
+
new_key = @names.index(key)
|
72
|
+
raise ArgumentError, "Wrong key: #{key}" unless new_key
|
73
|
+
key = new_key
|
74
|
+
end
|
75
|
+
|
76
|
+
raise ArgumentError, "The key should be either a string or an integer" unless key.is_a?(Integer)
|
77
|
+
|
78
|
+
return key
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require_relative 'datatype'
|
2
|
+
|
3
|
+
module Rust
|
4
|
+
class Matrix < RustDatatype
|
5
|
+
def self.can_pull?(type, klass)
|
6
|
+
return klass.is_a?(Array) && klass.include?("matrix")
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.pull_variable(variable, type, klass)
|
10
|
+
if Rust._pull("length(#{variable})") == 1
|
11
|
+
core = ::Matrix[[Rust._pull("#{variable}[1]")]]
|
12
|
+
else
|
13
|
+
core = Rust._pull(variable)
|
14
|
+
end
|
15
|
+
row_names = [Rust["rownames(#{variable})"]].flatten
|
16
|
+
column_names = [Rust["colnames(#{variable})"]].flatten
|
17
|
+
|
18
|
+
row_names = nil if row_names.all? { |v| v == nil }
|
19
|
+
column_names = nil if column_names.all? { |v| v == nil }
|
20
|
+
|
21
|
+
Matrix.new(core, row_names, column_names)
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_in_r_as(variable_name)
|
25
|
+
matrix = ::Matrix[*@data]
|
26
|
+
|
27
|
+
Rust[variable_name] = matrix
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(data, row_names = nil, column_names = nil)
|
31
|
+
@data = data.clone
|
32
|
+
|
33
|
+
@row_names = row_names
|
34
|
+
@column_names = column_names
|
35
|
+
|
36
|
+
if @data.is_a?(::Matrix)
|
37
|
+
@data = @data.row_vectors.map { |v| v.to_a }
|
38
|
+
end
|
39
|
+
|
40
|
+
if self.flatten.size == 0
|
41
|
+
raise "Empty matrices are not allowed"
|
42
|
+
else
|
43
|
+
raise TypeError, "Expected array of array" unless @data.is_a?(Array) || @data[0].is_a?(Array)
|
44
|
+
raise TypeError, "Only numeric matrices are supported" unless self.flatten.all? { |e| e.is_a?(Numeric) }
|
45
|
+
raise "All the rows must have the same size" unless @data.map { |row| row.size }.uniq.size == 1
|
46
|
+
raise ArgumentError, "Expected row names #@row_names to match the number of rows in #{self.inspect}" if @row_names && @row_names.size != self.rows
|
47
|
+
raise ArgumentError, "Expected column names #@column_names to match the number of columns in #{self.inspect}" if @column_names && @column_names.size != self.cols
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def [](i, j)
|
52
|
+
i, j = indices(i, j)
|
53
|
+
|
54
|
+
return @data[i][j]
|
55
|
+
end
|
56
|
+
|
57
|
+
def rows
|
58
|
+
@data.size
|
59
|
+
end
|
60
|
+
|
61
|
+
def cols
|
62
|
+
@data[0].size
|
63
|
+
end
|
64
|
+
|
65
|
+
def flatten
|
66
|
+
return @data.flatten
|
67
|
+
end
|
68
|
+
|
69
|
+
def []=(i, j, value)
|
70
|
+
i, j = indices(i, j)
|
71
|
+
|
72
|
+
@data[i][j] = value
|
73
|
+
end
|
74
|
+
|
75
|
+
def inspect
|
76
|
+
row_names = @row_names || (0...self.rows).to_a.map { |v| v.to_s }
|
77
|
+
column_names = @column_names || (0...self.cols).to_a.map { |v| v.to_s }
|
78
|
+
|
79
|
+
separator = " | "
|
80
|
+
col_widths = column_names.map do |colname|
|
81
|
+
[
|
82
|
+
colname,
|
83
|
+
(
|
84
|
+
[colname ? colname.length : 1] +
|
85
|
+
@data.map {|r| r[column_names.index(colname)]}.map { |e| e.inspect.length }
|
86
|
+
).max
|
87
|
+
]
|
88
|
+
end.to_h
|
89
|
+
col_widths[:rowscol] = row_names.map { |rowname| rowname.length }.max + 3
|
90
|
+
|
91
|
+
result = ""
|
92
|
+
result << "-" * (col_widths.values.sum + ((col_widths.size - 1) * separator.length)) + "\n"
|
93
|
+
result << (" " * col_widths[:rowscol]) + column_names.map { |colname| (" " * (col_widths[colname] - colname.length)) + colname }.join(separator) + "\n"
|
94
|
+
result << "-" * (col_widths.values.sum + ((col_widths.size - 1) * separator.length)) + "\n"
|
95
|
+
|
96
|
+
@data.each_with_index do |row, i|
|
97
|
+
row_name = row_names[i]
|
98
|
+
row = column_names.zip(row)
|
99
|
+
|
100
|
+
index_part = "[" + (" " * (col_widths[:rowscol] - row_name.length - 3)) + "#{row_name}] "
|
101
|
+
row_part = row.map { |colname, value| (" " * (col_widths[colname] - value.inspect.length)) + value.inspect }.join(separator)
|
102
|
+
|
103
|
+
result << index_part + row_part + "\n"
|
104
|
+
end
|
105
|
+
|
106
|
+
result << "-" * (col_widths.values.sum + ((col_widths.size - 1) * separator.length))
|
107
|
+
|
108
|
+
return result
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
def indices(i, j)
|
113
|
+
if i.is_a?(String)
|
114
|
+
ri = @row_names.index(i)
|
115
|
+
raise ArgumentError, "Can not find row #{i}" unless ri
|
116
|
+
i = ri
|
117
|
+
end
|
118
|
+
|
119
|
+
if j.is_a?(String)
|
120
|
+
rj = @column_names.index(j)
|
121
|
+
raise ArgumentError, "Can not find column #{j}" unless rj
|
122
|
+
j = rj
|
123
|
+
end
|
124
|
+
|
125
|
+
raise ArgumentError, "Expected i and j to be both integers or strings" unless i.is_a?(Integer) && j.is_a?(Integer)
|
126
|
+
raise "Wrong i" unless i.between?(0, @data.size - 1)
|
127
|
+
raise "Wrong j" unless j.between?(0, @data[0].size - 1)
|
128
|
+
|
129
|
+
return [i, j]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require_relative 'datatype'
|
2
|
+
|
3
|
+
module Rust
|
4
|
+
class S4Class < RustDatatype
|
5
|
+
def self.can_pull?(type, klass)
|
6
|
+
return type == "S4"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.pull_variable(variable, type, klass)
|
10
|
+
slots = [Rust._pull("names(getSlots(\"#{klass}\"))")].flatten
|
11
|
+
|
12
|
+
return S4Class.new(variable, klass, slots)
|
13
|
+
end
|
14
|
+
|
15
|
+
def load_in_r_as(variable_name)
|
16
|
+
Rust._eval("#{variable_name} <- #{self.r_mirror}")
|
17
|
+
end
|
18
|
+
|
19
|
+
def r_hash
|
20
|
+
"immutable"
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(variable_name, klass, slots)
|
24
|
+
@klass = klass
|
25
|
+
@slots = slots
|
26
|
+
|
27
|
+
self.r_mirror_to(variable_name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def [](key)
|
31
|
+
raise ArgumentError, "Unknown slot `#{key}` for class `#@klass`" unless @slots.include?(key)
|
32
|
+
|
33
|
+
Rust.exclusive do
|
34
|
+
return Rust["#{self.r_mirror}@#{key}"]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
alias :| :[]
|
38
|
+
|
39
|
+
def []=(key, value)
|
40
|
+
raise ArgumentError, "Unknown slot `#{key}` for class `#@klass`" unless @slots.include?(key)
|
41
|
+
|
42
|
+
Rust.exclusive do
|
43
|
+
return Rust["#{self.r_mirror}@#{key}"] = value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def slots
|
48
|
+
@slots
|
49
|
+
end
|
50
|
+
|
51
|
+
def class_name
|
52
|
+
@klass
|
53
|
+
end
|
54
|
+
|
55
|
+
def inspect
|
56
|
+
return "<S4 instance of #@klass, with slots #@slots>"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require_relative 'datatype'
|
2
|
+
|
3
|
+
module Rust
|
4
|
+
class Sequence < RustDatatype
|
5
|
+
attr_reader :min
|
6
|
+
attr_reader :max
|
7
|
+
|
8
|
+
def self.can_pull?(type, klass)
|
9
|
+
return false
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(min, max, step=1)
|
13
|
+
@min = min
|
14
|
+
@max = max
|
15
|
+
@step = step
|
16
|
+
end
|
17
|
+
|
18
|
+
def step(step)
|
19
|
+
@step = step
|
20
|
+
end
|
21
|
+
|
22
|
+
def each
|
23
|
+
(@min..@max).step(@step) do |v|
|
24
|
+
yield v
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_a
|
29
|
+
result = []
|
30
|
+
self.each do |v|
|
31
|
+
result << v
|
32
|
+
end
|
33
|
+
return result
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_R
|
37
|
+
"seq(from=#@min, to=#@max, by=#@step)"
|
38
|
+
end
|
39
|
+
|
40
|
+
def load_in_r_as(variable_name)
|
41
|
+
Rust._eval("#{variable_name} <- #{self.to_R}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class MathArray < Array
|
46
|
+
def -(other)
|
47
|
+
raise ArgumentError, "Expected array or numeric" if !other.is_a?(::Array) && !other.is_a?(Numeric)
|
48
|
+
raise ArgumentError, "The two arrays must have the same size" if other.is_a?(::Array) && self.size != other.size
|
49
|
+
|
50
|
+
result = self.clone
|
51
|
+
other = [other] * self.size if other.is_a?(Numeric)
|
52
|
+
for i in 0...self.size
|
53
|
+
result[i] -= other[i]
|
54
|
+
end
|
55
|
+
|
56
|
+
return result
|
57
|
+
end
|
58
|
+
|
59
|
+
def *(other)
|
60
|
+
raise ArgumentError, "Expected array or numeric" if !other.is_a?(::Array) && !other.is_a?(Numeric)
|
61
|
+
raise ArgumentError, "The two arrays must have the same size" if other.is_a?(::Array) && self.size != other.size
|
62
|
+
|
63
|
+
result = self.clone
|
64
|
+
other = [other] * self.size if other.is_a?(Numeric)
|
65
|
+
for i in 0...self.size
|
66
|
+
result[i] *= other[i]
|
67
|
+
end
|
68
|
+
|
69
|
+
return result
|
70
|
+
end
|
71
|
+
|
72
|
+
def +(other)
|
73
|
+
raise ArgumentError, "Expected array or numeric" if !other.is_a?(::Array) && !other.is_a?(Numeric)
|
74
|
+
raise ArgumentError, "The two arrays must have the same size" if other.is_a?(::Array) && self.size != other.size
|
75
|
+
|
76
|
+
result = self.clone
|
77
|
+
other = [other] * self.size if other.is_a?(Numeric)
|
78
|
+
for i in 0...self.size
|
79
|
+
result[i] += other[i]
|
80
|
+
end
|
81
|
+
|
82
|
+
return result
|
83
|
+
end
|
84
|
+
|
85
|
+
def /(other) #/# <- this comment is just to recover the syntax highlighting bug in Kate
|
86
|
+
raise ArgumentError, "Expected array or numeric" if !other.is_a?(::Array) && !other.is_a?(Numeric)
|
87
|
+
raise ArgumentError, "The two arrays must have the same size" if other.is_a?(::Array) && self.size != other.size
|
88
|
+
|
89
|
+
result = self.clone
|
90
|
+
other = [other] * self.size if other.is_a?(Numeric)
|
91
|
+
for i in 0...self.size
|
92
|
+
result[i] /= other[i]
|
93
|
+
end
|
94
|
+
|
95
|
+
return result
|
96
|
+
end
|
97
|
+
|
98
|
+
def **(other)
|
99
|
+
raise ArgumentError, "Expected numeric" if !other.is_a?(Numeric)
|
100
|
+
|
101
|
+
result = self.clone
|
102
|
+
for i in 0...self.size
|
103
|
+
result[i] = result[i] ** other
|
104
|
+
end
|
105
|
+
|
106
|
+
return result
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/rust/core.rb
ADDED