rust 0.7 → 0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35c41ec98f5b286ef597096152249f19825a27bc33030e85ea196df8b778d3b1
4
- data.tar.gz: 48b2e61f707ebcd05fa5f593016c8c0fb4b9d1e58751dd5deae83715583bd978
3
+ metadata.gz: aaa404db11033ff42b529516ae4a3f3e252bdddf7677d082847ee06625144f8e
4
+ data.tar.gz: f72ebc2c95385b87a445f3fb8de3e517579b002e0606209903acd2327616befd
5
5
  SHA512:
6
- metadata.gz: b0cc1289721d52cd376e0a242c2be419ea511f03a0fdd42c4c7a1973cde24e8dfc467e9d355693f85632cccb98af6986777aa020b715db5f06aa88a63d154ea0
7
- data.tar.gz: 4c91c808773dcd04913a594cfcaa7956318908e6d590ebec1d9a04beef18986adc70a3c5e480c39bdc9f753b5edf920a1939208b8b530ccfc67124ac153a4804
6
+ metadata.gz: 00567c9b6216f7e9dc1a4135dbea263eecae2178273851c023980233531729313e15147e1bec8e9521df2d4fee15e2c4c8bf9bd4a0e2d1475f1d383339a17c21
7
+ data.tar.gz: 89800fff95be559e6f6bbbc05b6b5f5b52b7d59c54c61cd76ef679876ce5de0c08b405d88eadf0b254c95306ad98f38120e5960a92ce8358fca19ed6cc5c181d
data/bin/ruby-rust ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/ruby
2
+
3
+ system "irb -r \"rust\""
@@ -1,4 +1,5 @@
1
- require_relative 'rust-core'
1
+ require_relative '../core'
2
+ require 'csv'
2
3
 
3
4
  module Rust
4
5
  class CSV
@@ -0,0 +1,157 @@
1
+ require 'code-assertions'
2
+ require 'stringio'
3
+ require 'rinruby'
4
+
5
+ module Rust
6
+ CLIENT_MUTEX = Mutex.new
7
+ R_MUTEX = Mutex.new
8
+
9
+ R_ENGINE = RinRuby.new(echo: false)
10
+
11
+ private_constant :R_ENGINE
12
+ private_constant :R_MUTEX
13
+ private_constant :CLIENT_MUTEX
14
+
15
+ @@debugging = $RUST_DEBUG || false
16
+ @@in_client_mutex = false
17
+
18
+ def self.debug
19
+ @@debugging = true
20
+ end
21
+
22
+ def self.debug?
23
+ return @@debugging
24
+ end
25
+
26
+ def self.exclusive
27
+ result = nil
28
+ CLIENT_MUTEX.synchronize do
29
+ @@in_client_mutex = true
30
+ result = yield
31
+ @@in_client_mutex = false
32
+ end
33
+ return result
34
+ end
35
+
36
+ def self.[]=(variable, value)
37
+ if value.is_a?(RustDatatype)
38
+ value.load_in_r_as(variable.to_s)
39
+ elsif value.is_a?(String) || value.is_a?(Numeric) || value.is_a?(Array) || value.is_a?(::Matrix)
40
+ R_ENGINE.assign(variable, value)
41
+ else
42
+ raise "Trying to assign #{variable} with #{value.class}; expected RustDatatype, String, Numeric, or Array"
43
+ end
44
+
45
+ end
46
+
47
+ def self.[](variable)
48
+ return RustDatatype.pull_variable(variable)
49
+ end
50
+
51
+ def self._eval_big(r_command, return_warnings = false)
52
+ r_command = r_command.join("\n") if r_command.is_a?(Array)
53
+
54
+ self._rexec(r_command, return_warnings) do |cmd|
55
+ result = true
56
+ instructions = cmd.lines
57
+
58
+ while instructions.size > 0
59
+ current_command = ""
60
+
61
+ while (instructions.size > 0) && (current_command.length + instructions.first.length < 10000)
62
+ current_command << instructions.shift
63
+ end
64
+
65
+ result &= R_ENGINE.eval(current_command)
66
+ end
67
+
68
+ result
69
+ end
70
+ end
71
+
72
+ def self._pull(r_command, return_warnings = false)
73
+ self._rexec(r_command, return_warnings) { |cmd| R_ENGINE.pull(cmd) }
74
+ end
75
+
76
+ def self._eval(r_command, return_warnings = false)
77
+ self._rexec(r_command, return_warnings) { |cmd| R_ENGINE.eval(cmd) }
78
+ end
79
+
80
+ def self._rexec(r_command, return_warnings = false)
81
+ puts "Calling _rexec with command: #{r_command}" if @@debugging
82
+ R_MUTEX.synchronize do
83
+ assert("This command must be executed in an exclusive block") { @@in_client_mutex }
84
+
85
+ result = nil
86
+ begin
87
+ $stdout = StringIO.new
88
+ if return_warnings
89
+ R_ENGINE.echo(true, true)
90
+ else
91
+ R_ENGINE.echo(false, false)
92
+ end
93
+ result = yield(r_command)
94
+ ensure
95
+ R_ENGINE.echo(false, false)
96
+ warnings = $stdout.string
97
+ $stdout = STDOUT
98
+ end
99
+
100
+ if return_warnings
101
+ puts " Got #{warnings.size} warnings, with result #{result.inspect[0...100]}" if @@debugging
102
+ return result, warnings.lines.map { |w| w.strip.chomp }
103
+ else
104
+ puts " Result: #{result.inspect[0...100]}" if @@debugging
105
+ return result
106
+ end
107
+ end
108
+ end
109
+
110
+ def self.check_library(name)
111
+ self.exclusive do
112
+ result, _ = self._pull("require(\"#{name}\", character.only = TRUE)", true)
113
+ return result
114
+ end
115
+ end
116
+
117
+ def self.load_library(name)
118
+ self.exclusive do
119
+ self._eval("library(\"#{name}\", character.only = TRUE)")
120
+ end
121
+
122
+ return nil
123
+ end
124
+
125
+ def self.install_library(name)
126
+ self.exclusive do
127
+ self._eval("install.packages(\"#{name}\", dependencies = TRUE)")
128
+ end
129
+
130
+ return nil
131
+ end
132
+
133
+ def self.prerequisite(library)
134
+ self.install_library(library) unless self.check_library(library)
135
+ self.load_library(library)
136
+ end
137
+ end
138
+
139
+ module Rust::RBindings
140
+ def data_frame(*args)
141
+ Rust::DataFrame.new(*args)
142
+ end
143
+ end
144
+
145
+ module Rust::TestCases
146
+ def self.sample_dataframe(columns, size=100)
147
+ result = Rust::DataFrame.new(columns)
148
+ size.times do |i|
149
+ result << columns.map { |c| yield i, c }
150
+ end
151
+ return result
152
+ end
153
+ end
154
+
155
+ def bind_r!
156
+ include Rust::RBindings
157
+ end
@@ -0,0 +1,4 @@
1
+ self_path = File.expand_path(__FILE__)
2
+ Dir.glob(File.dirname(self_path) + "/*.rb").each do |lib|
3
+ require_relative lib unless lib == self_path
4
+ end
@@ -1,123 +1,20 @@
1
- require 'code-assertions'
2
- require 'stringio'
3
- require 'rinruby'
4
- require 'csv'
1
+ require_relative 'datatype'
5
2
 
6
3
  module Rust
7
- CLIENT_MUTEX = Mutex.new
8
- R_MUTEX = Mutex.new
9
-
10
- R_ENGINE = RinRuby.new(echo: false)
11
-
12
- private_constant :R_ENGINE
13
- private_constant :R_MUTEX
14
- private_constant :CLIENT_MUTEX
15
-
16
- @@debugging = false
17
- @@in_client_mutex = false
18
-
19
- def self.debug
20
- @@debugging = true
21
- end
22
-
23
- def self.exclusive
24
- result = nil
25
- CLIENT_MUTEX.synchronize do
26
- @@in_client_mutex = true
27
- result = yield
28
- @@in_client_mutex = false
29
- end
30
- return result
31
- end
32
-
33
- def self.[]=(variable, value)
34
- if value.is_a?(RustDatatype)
35
- value.load_in_r_as(variable.to_s)
36
- elsif value.is_a?(String) || value.is_a?(Numeric) || value.is_a?(Array)
37
- R_ENGINE.assign(variable, value)
38
- else
39
- raise "Given #{value.class}, expected RustDatatype, String, Numeric, or Array"
4
+ class DataFrame < RustDatatype
5
+ def self.can_pull?(type, klass)
6
+ return [klass].flatten.include?("data.frame")
40
7
  end
41
8
 
42
- end
43
-
44
- def self.[](variable, type=RustDatatype)
45
- return type.pull_variable(variable)
46
- end
47
-
48
- def self._eval_big(r_command, return_warnings = false)
49
- r_command = r_command.join("\n") if r_command.is_a?(Array)
50
-
51
- self._rexec(r_command, return_warnings) do |cmd|
52
- result = true
53
- instructions = cmd.lines
54
-
55
- while instructions.size > 0
56
- current_command = ""
57
-
58
- while (instructions.size > 0) && (current_command.length + instructions.first.length < 10000)
59
- current_command << instructions.shift
60
- end
61
-
62
- result &= R_ENGINE.eval(current_command)
63
- end
64
-
65
- result
66
- end
67
- end
68
-
69
- def self._pull(r_command, return_warnings = false)
70
- self._rexec(r_command, return_warnings) { |cmd| R_ENGINE.pull(cmd) }
71
- end
72
-
73
- def self._eval(r_command, return_warnings = false)
74
- self._rexec(r_command, return_warnings) { |cmd| R_ENGINE.eval(cmd) }
75
- end
76
-
77
- def self._rexec(r_command, return_warnings = false)
78
- puts "Calling _rexec with command: #{r_command}" if @@debugging
79
- R_MUTEX.synchronize do
80
- assert("This command must be executed in an exclusive block") { @@in_client_mutex }
81
-
82
- result = nil
83
- begin
84
- $stdout = StringIO.new
85
- if return_warnings
86
- R_ENGINE.echo(true, true)
87
- else
88
- R_ENGINE.echo(false, false)
89
- end
90
- result = yield(r_command)
91
- ensure
92
- R_ENGINE.echo(false, false)
93
- warnings = $stdout.string
94
- $stdout = STDOUT
95
- end
96
-
97
- if return_warnings
98
- return result, warnings.lines.map { |w| w.strip.chomp }
99
- else
100
- return result
101
- end
102
- end
103
- end
104
-
105
- class RustDatatype
106
- def self.pull_variable(variable)
107
- return Rust._pull(variable)
9
+ def self.pull_priority
10
+ 1
108
11
  end
109
12
 
110
- def load_in_r_as(r_instance, variable_name)
111
- raise "Not implemented"
112
- end
113
- end
114
-
115
- class DataFrame < RustDatatype
116
- def self.pull_variable(variable)
13
+ def self.pull_variable(variable, type, klass)
117
14
  hash = {}
118
- colnames = Rust._pull("colnames(#{variable})")
15
+ colnames = Rust["colnames(#{variable})"]
119
16
  colnames.each do |col|
120
- hash[col] = Rust._pull("#{variable}$#{col}")
17
+ hash[col] = Rust["#{variable}$\"#{col}\""]
121
18
  end
122
19
  return DataFrame.new(hash)
123
20
  end
@@ -373,6 +270,14 @@ module Rust
373
270
  row_index += 1
374
271
  end
375
272
 
273
+ self.column_names.each do |name|
274
+ column = self.column(name)
275
+
276
+ if column.is_a?(Factor)
277
+ command << "#{variable_name}[,#{name.to_R}] <- factor(#{variable_name}[,#{name.to_R}], labels=#{column.levels.to_R})"
278
+ end
279
+ end
280
+
376
281
  Rust._eval_big(command)
377
282
  end
378
283
 
@@ -586,82 +491,6 @@ module Rust
586
491
  end
587
492
  end
588
493
 
589
- class Matrix < RustDatatype
590
- def self.pull_variable(variable)
591
- return Rust._pull(variable)
592
- end
593
-
594
- def initialize(data)
595
- if data.flatten.size == 0
596
- raise "Empty matrices are not allowed"
597
- else
598
- raise TypeError, "Expected array of array" unless data.is_a?(Array) && data[0].is_a?(Array)
599
- raise TypeError, "Only numeric matrices are supported" unless data.all? { |row| row.all? { |e| e.is_a?(Numeric) } }
600
- raise "All the rows must have the same size" unless data.map { |row| row.size }.uniq.size == 1
601
- @data = data.clone
602
- end
603
- end
604
-
605
- def [](i, j)
606
- return @data[i][j]
607
- end
608
-
609
- def rows
610
- @data.size
611
- end
612
-
613
- def cols
614
- @data[0].size
615
- end
616
-
617
- def []=(i, j, value)
618
- raise "Wrong i" unless i.between?(0, @data.size - 1)
619
- raise "Wrong j" unless j.between?(0, @data[0].size - 1)
620
- @data[i][j] = value
621
- end
622
-
623
- def load_in_r_as(variable_name)
624
- Rust._eval("#{variable_name} <- matrix(c(#{@data.flatten.join(",")}), nrow=#{self.rows}, ncol=#{self.cols}, byrow=T)")
625
- end
626
- end
627
-
628
- class Sequence < RustDatatype
629
- attr_reader :min
630
- attr_reader :max
631
-
632
- def initialize(min, max, step=1)
633
- @min = min
634
- @max = max
635
- @step = step
636
- end
637
-
638
- def step(step)
639
- @step = step
640
- end
641
-
642
- def each
643
- (@min..@max).step(@step) do |v|
644
- yield v
645
- end
646
- end
647
-
648
- def to_a
649
- result = []
650
- self.each do |v|
651
- result << v
652
- end
653
- return result
654
- end
655
-
656
- def to_R
657
- "seq(from=#@min, to=#@max, by=#@step)"
658
- end
659
-
660
- def load_in_r_as(variable_name)
661
- Rust._eval("#{variable_name} <- #{self.to_R}")
662
- end
663
- end
664
-
665
494
  class DataFrameArray < Array
666
495
  def bind_all
667
496
  return nil if self.size == 0
@@ -689,151 +518,4 @@ module Rust
689
518
  return result
690
519
  end
691
520
  end
692
-
693
- class MathArray < Array
694
- def -(other)
695
- raise ArgumentError, "Expected array or numeric" if !other.is_a?(::Array) && !other.is_a?(Numeric)
696
- raise ArgumentError, "The two arrays must have the same size" if other.is_a?(::Array) && self.size != other.size
697
-
698
- result = self.clone
699
- other = [other] * self.size if other.is_a?(Numeric)
700
- for i in 0...self.size
701
- result[i] -= other[i]
702
- end
703
-
704
- return result
705
- end
706
-
707
- def *(other)
708
- raise ArgumentError, "Expected array or numeric" if !other.is_a?(::Array) && !other.is_a?(Numeric)
709
- raise ArgumentError, "The two arrays must have the same size" if other.is_a?(::Array) && self.size != other.size
710
-
711
- result = self.clone
712
- other = [other] * self.size if other.is_a?(Numeric)
713
- for i in 0...self.size
714
- result[i] *= other[i]
715
- end
716
-
717
- return result
718
- end
719
-
720
- def +(other)
721
- raise ArgumentError, "Expected array or numeric" if !other.is_a?(::Array) && !other.is_a?(Numeric)
722
- raise ArgumentError, "The two arrays must have the same size" if other.is_a?(::Array) && self.size != other.size
723
-
724
- result = self.clone
725
- other = [other] * self.size if other.is_a?(Numeric)
726
- for i in 0...self.size
727
- result[i] += other[i]
728
- end
729
-
730
- return result
731
- end
732
-
733
- def /(other) #To recover the syntax highlighting but in Kate: /
734
- raise ArgumentError, "Expected array or numeric" if !other.is_a?(::Array) && !other.is_a?(Numeric)
735
- raise ArgumentError, "The two arrays must have the same size" if other.is_a?(::Array) && self.size != other.size
736
-
737
- result = self.clone
738
- other = [other] * self.size if other.is_a?(Numeric)
739
- for i in 0...self.size
740
- result[i] /= other[i]
741
- end
742
-
743
- return result
744
- end
745
-
746
- def **(other)
747
- raise ArgumentError, "Expected numeric" if !other.is_a?(Numeric)
748
-
749
- result = self.clone
750
- for i in 0...self.size
751
- result[i] = result[i] ** other
752
- end
753
-
754
- return result
755
- end
756
- end
757
- end
758
-
759
- class TrueClass
760
- def to_R
761
- "TRUE"
762
- end
763
- end
764
-
765
- class FalseClass
766
- def to_R
767
- "FALSE"
768
- end
769
- end
770
-
771
- class Object
772
- def to_R
773
- raise TypeError, "Unsupported type for #{self.class}"
774
- end
775
- end
776
-
777
- class NilClass
778
- def to_R
779
- return "NULL"
780
- end
781
- end
782
-
783
- class Numeric
784
- def to_R
785
- self.inspect
786
- end
787
- end
788
-
789
- class Float
790
- def to_R
791
- return self.nan? ? "NA" : super
792
- end
793
- end
794
-
795
- class Array
796
- def to_R
797
- return "c(#{self.map { |e| e.to_R }.join(",")})"
798
- end
799
-
800
- def distribution
801
- result = {}
802
- self.each do |value|
803
- result[value] = result[value].to_i + 1
804
- end
805
- return result
806
- end
807
- end
808
-
809
- class String
810
- def to_R
811
- return self.inspect
812
- end
813
- end
814
-
815
- class Range
816
- def to_R
817
- [range.min, range.max].to_R
818
- end
819
- end
820
-
821
- module Rust::RBindings
822
- def data_frame(*args)
823
- Rust::DataFrame.new(*args)
824
- end
825
- end
826
-
827
- module Rust::TestCases
828
- def self.sample_dataframe(columns, size=100)
829
- result = Rust::DataFrame.new(columns)
830
- size.times do |i|
831
- result << columns.map { |c| yield i, c }
832
- end
833
- return result
834
- end
835
- end
836
-
837
- def bind_r!
838
- include Rust::RBindings
839
521
  end