Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
creation and elementwise operation and basic setup
- Loading branch information
1 parent
007a627
commit 974ce86
Showing
20 changed files
with
436 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
source 'https://rubygems.org' | ||
gemspec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
|
||
require "bundler/gem_tasks" | ||
require 'rake' | ||
require 'rake/extensiontask' | ||
require "rake/testtask" | ||
require "rdoc/task" | ||
|
||
Rake::ExtensionTask.new do |ext| | ||
ext.name = 'nmatrix' | ||
ext.ext_dir = 'ext/' | ||
ext.lib_dir = 'lib/' | ||
ext.source_pattern = '**/*.{c,cpp, h}' | ||
end | ||
|
||
task :console do | ||
cmd = ['irb', "-r './lib/nmatrix.rb'"] | ||
run(*cmd) | ||
end | ||
|
||
task :pry do | ||
cmd = ['pry', "-r './lib/nmatrix.rb'"] | ||
run(*cmd) | ||
end | ||
|
||
def run(*cmd) | ||
sh(cmd.join(' ')) | ||
end | ||
|
||
RDoc::Task.new do |rdoc| | ||
rdoc.main = "README.md" | ||
rdoc.rdoc_files.include(%w{README.md LICENSE CONTRIBUTING.md lib ext}) | ||
end | ||
|
||
Rake::TestTask.new(:test) do |t| | ||
t.libs << "test" | ||
t.libs << "lib" | ||
t.test_files = FileList['test/**/*_test.rb'] | ||
end | ||
|
||
task :default => :test |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
require_relative 'mkmf.rb' | ||
|
||
extension_name = 'nmatrix' | ||
|
||
nmatrix_path = Gem::Specification.find_all_by_name('nmatrix').compact | ||
abort "Cannot locate NMatrix installation" unless nmatrix_path | ||
nmatrix_header_dir = File.join(nmatrix_path[0].require_path) | ||
|
||
$INSTALLFILES = [ | ||
['ruby_nmatrix.h' , '$(archdir)'], | ||
# ['ruby_nmatrix.hpp' , '$(archdir)'], | ||
['nmatrix_config.h', '$(archdir)'], | ||
] | ||
|
||
$DEBUG = true | ||
$CFLAGS = ["-Wall -Werror=return-type",$CFLAGS].join(" ") | ||
$CXXFLAGS = ["-Wall -Werror=return-type",$CXXFLAGS].join(" ") | ||
$CPPFLAGS = ["-Wall -Werror=return-type",$CPPFLAGS].join(" ") | ||
|
||
|
||
LIBDIR = RbConfig::CONFIG['libdir'] | ||
INCLUDEDIR = RbConfig::CONFIG['includedir'] | ||
|
||
HEADER_DIRS = [ | ||
'/opt/local/include', | ||
'/usr/local/include', | ||
INCLUDEDIR, | ||
'/usr/include', | ||
nmatrix_header_dir | ||
] | ||
|
||
LIB_DIRS = [ | ||
'/opt/local/lib', | ||
'/usr/local/lib', | ||
LIBDIR, | ||
'/usr/lib', | ||
nmatrix_header_dir | ||
] | ||
|
||
dir_config(extension_name, HEADER_DIRS, LIB_DIRS) | ||
|
||
# have_library('af') | ||
|
||
basenames = %w{ruby_nmatrix} | ||
$objs = basenames.map { |b| "#{b}.o" } | ||
$srcs = basenames.map { |b| "#{b}.cpp" } | ||
|
||
create_conf_h("nmatrix_config.h") | ||
create_makefile(extension_name) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
require "mkmf" | ||
|
||
if RUBY_VERSION < '1.9' | ||
raise NotImplementedError, "Sorry, you need at least Ruby 1.9!" | ||
end | ||
|
||
# Function derived from NArray's extconf.rb. | ||
def create_conf_h(file) #:nodoc: | ||
print "creating #{file}\n" | ||
File.open(file, 'w') do |hfile| | ||
header_guard = file.upcase.sub(/\s|\./, '_') | ||
|
||
hfile.puts "#ifndef #{header_guard}" | ||
hfile.puts "#define #{header_guard}" | ||
hfile.puts | ||
|
||
# FIXME: Find a better way to do this: | ||
hfile.puts "#define RUBY_2 1" if RUBY_VERSION >= '2.0' | ||
|
||
for line in $defs | ||
line =~ /^-D(.*)/ | ||
hfile.printf "#define %s 1\n", $1 | ||
end | ||
|
||
hfile.puts | ||
hfile.puts "#endif" | ||
end | ||
end | ||
|
||
def find_newer_gplusplus #:nodoc: | ||
print "checking for apparent GNU g++ binary with C++0x/C++11 support... " | ||
[9,8,7,6,5,4,3].each do |minor| | ||
ver = "4.#{minor}" | ||
gpp = "g++-#{ver}" | ||
result = `which #{gpp}` | ||
next if result.empty? | ||
CONFIG['CXX'] = gpp | ||
puts ver | ||
return CONFIG['CXX'] | ||
end | ||
false | ||
end | ||
|
||
def gplusplus_version | ||
cxxvar = proc { |n| `#{CONFIG['CXX']} -E -dM - <#{File::NULL} | grep #{n}`.chomp.split(' ')[2] } | ||
major = cxxvar.call('__GNUC__') | ||
minor = cxxvar.call('__GNUC_MINOR__') | ||
patch = cxxvar.call('__GNUC_PATCHLEVEL__') | ||
|
||
raise("unable to determine g++ version (match to get version was nil)") if major.nil? || minor.nil? || patch.nil? | ||
|
||
"#{major}.#{minor}.#{patch}" | ||
end | ||
|
||
|
||
if /cygwin|mingw/ =~ RUBY_PLATFORM | ||
CONFIG["DLDFLAGS"] << " --output-lib libnmatrix.a" | ||
end | ||
|
||
# Fix compiler pairing | ||
if CONFIG['CC'] == 'clang' && CONFIG['CXX'] != 'clang++' | ||
puts "WARNING: CONFIG['CXX'] is not 'clang++' even though CONFIG['CC'] is 'clang'.", | ||
"WARNING: Force to use clang++ together with clang." | ||
|
||
CONFIG['CXX'] = 'clang++' | ||
end | ||
|
||
if CONFIG['CXX'] == 'clang++' | ||
$CXX_STANDARD = 'c++11' | ||
else | ||
version = gplusplus_version | ||
if version < '4.3.0' && CONFIG['CXX'] == 'g++' # see if we can find a newer G++, unless it's been overridden by user | ||
if !find_newer_gplusplus | ||
raise("You need a version of g++ which supports -std=c++0x or -std=c++11. If you're on a Mac and using Homebrew, we recommend using mac-brew-gcc.sh to install a more recent g++.") | ||
end | ||
version = gplusplus_version | ||
end | ||
|
||
if version < '4.7.0' | ||
$CXX_STANDARD = 'c++0x' | ||
else | ||
$CXX_STANDARD = 'c++11' | ||
end | ||
puts "using C++ standard... #{$CXX_STANDARD}" | ||
puts "g++ reports version... " + `#{CONFIG['CXX']} --version|head -n 1|cut -f 3 -d " "` | ||
end | ||
|
||
# For release, these next two should both be changed to -O3. | ||
$CFLAGS += " -O3 " | ||
#$CFLAGS += " -static -O0 -g " | ||
$CXXFLAGS += " -O3 -std=#{$CXX_STANDARD} " #-fmax-errors=10 -save-temps | ||
#$CXXFLAGS += " -static -O0 -g -std=#{$CXX_STANDARD} " | ||
|
||
CONFIG['warnflags'].gsub!('-Wshorten-64-to-32', '') # doesn't work except in Mac-patched gcc (4.2) | ||
CONFIG['warnflags'].gsub!('-Wdeclaration-after-statement', '') | ||
CONFIG['warnflags'].gsub!('-Wimplicit-function-declaration', '') | ||
|
||
have_func("rb_array_const_ptr", "ruby.h") | ||
have_macro("FIX_CONST_VALUE_PTR", "ruby.h") | ||
have_macro("RARRAY_CONST_PTR", "ruby.h") | ||
have_macro("RARRAY_AREF", "ruby.h") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
#include "ruby.h" | ||
#include "stdio.h" | ||
|
||
typedef struct NMATRIX_STRUCT | ||
{ | ||
size_t ndims; | ||
size_t count; | ||
size_t* shape; | ||
double* elements; | ||
}nmatrix; | ||
|
||
VALUE NMatrix = Qnil; | ||
|
||
void Init_nmatrix(); | ||
VALUE nmatrix_init(int argc, VALUE* argv, VALUE self); | ||
VALUE nm_get_elements(VALUE self); | ||
VALUE nm_get_shape(VALUE self); | ||
VALUE nm_alloc(VALUE klass); | ||
void nm_free(nmatrix* mat); | ||
|
||
VALUE nm_add(VALUE self, VALUE another); | ||
|
||
#define DECL_ELEMENTWISE_RUBY_ACCESSOR(name) VALUE nm_##name(VALUE self, VALUE another); | ||
|
||
DECL_ELEMENTWISE_RUBY_ACCESSOR(subtract) | ||
DECL_ELEMENTWISE_RUBY_ACCESSOR(multiply) | ||
DECL_ELEMENTWISE_RUBY_ACCESSOR(divide) | ||
|
||
|
||
void Init_nmatrix() { | ||
NMatrix = rb_define_class("NMatrix", rb_cObject); | ||
|
||
rb_define_alloc_func(NMatrix, nm_alloc); | ||
rb_define_method(NMatrix, "initialize", nmatrix_init, -1); | ||
rb_define_method(NMatrix, "shape", nm_get_shape, 0); | ||
rb_define_method(NMatrix, "elements", nm_get_elements, 0); | ||
|
||
rb_define_method(NMatrix, "+", nm_add, 1); | ||
rb_define_method(NMatrix, "-", nm_subtract, 1); | ||
rb_define_method(NMatrix, "*", nm_multiply,1); | ||
rb_define_method(NMatrix, "/", nm_divide,1); | ||
} | ||
|
||
|
||
VALUE nmatrix_init(int argc, VALUE* argv, VALUE self){ | ||
nmatrix* mat; | ||
Data_Get_Struct(self, nmatrix, mat); | ||
|
||
if(argc > 0){ | ||
mat->ndims = 2; | ||
mat->count = 1; | ||
mat->shape = ALLOC_N(size_t, mat->ndims); | ||
for (size_t index = 0; index < mat->ndims; index++) { | ||
mat->shape[index] = (size_t)FIX2LONG(RARRAY_AREF(argv[0], index)); | ||
mat->count *= mat->shape[index]; | ||
} | ||
mat->elements = ALLOC_N(double, mat->count); | ||
for (size_t index = 0; index < mat->count; index++) { | ||
mat->elements[index] = (double)NUM2DBL(RARRAY_AREF(argv[1], index)); | ||
} | ||
} | ||
|
||
return self; | ||
} | ||
|
||
VALUE nm_alloc(VALUE klass) | ||
{ | ||
nmatrix* mat = ALLOC(nmatrix); | ||
|
||
return Data_Wrap_Struct(klass, NULL, nm_free, mat); | ||
} | ||
|
||
void nm_free(nmatrix* mat){ | ||
xfree(mat); | ||
} | ||
|
||
VALUE nm_get_elements(VALUE self){ | ||
nmatrix* input; | ||
|
||
Data_Get_Struct(self, nmatrix, input); | ||
|
||
VALUE* array = ALLOC_N(VALUE, input->count); | ||
for (size_t index = 0; index < input->count; index++){ | ||
array[index] = DBL2NUM(input->elements[index]); | ||
} | ||
|
||
return rb_ary_new4(input->count, array); | ||
} | ||
|
||
VALUE nm_get_shape(VALUE self){ | ||
nmatrix* input; | ||
|
||
Data_Get_Struct(self, nmatrix, input); | ||
|
||
VALUE* array = ALLOC_N(VALUE, input->ndims); | ||
for (size_t index = 0; index < input->ndims; index++){ | ||
array[index] = LONG2NUM(input->shape[index]); | ||
} | ||
|
||
return rb_ary_new4(input->ndims, array); | ||
} | ||
|
||
VALUE nm_add(VALUE self, VALUE another){ | ||
nmatrix* left; | ||
nmatrix* right; | ||
Data_Get_Struct(self, nmatrix, left); | ||
Data_Get_Struct(another, nmatrix, right); | ||
|
||
nmatrix* result = ALLOC(nmatrix); | ||
result->count = left->count; | ||
result->ndims = left->ndims; | ||
result->shape = ALLOC_N(size_t, result->ndims); | ||
|
||
for(size_t index = 0; index < result->ndims; index++){ | ||
result->shape[index] = left->shape[index]; | ||
} | ||
|
||
result->elements = ALLOC_N(double, result->count); | ||
for(size_t index = 0; index < left->count; index++){ | ||
result->elements[index] = left->elements[index] + right->elements[index]; | ||
} | ||
|
||
return Data_Wrap_Struct(NMatrix, NULL, nm_free, result); | ||
} | ||
|
||
#define DEF_ELEMENTWISE_RUBY_ACCESSOR(name, oper) \ | ||
VALUE nm_##name(VALUE self, VALUE another){ \ | ||
nmatrix* left; \ | ||
nmatrix* right; \ | ||
Data_Get_Struct(self, nmatrix, left); \ | ||
Data_Get_Struct(another, nmatrix, right); \ | ||
\ | ||
nmatrix* result = ALLOC(nmatrix); \ | ||
result->count = left->count; \ | ||
result->ndims = left->ndims; \ | ||
result->shape = ALLOC_N(size_t, result->ndims); \ | ||
\ | ||
for(size_t index = 0; index < result->ndims; index++){ \ | ||
result->shape[index] = left->shape[index]; \ | ||
} \ | ||
\ | ||
result->elements = ALLOC_N(double, result->count); \ | ||
for(size_t index = 0; index < left->count; index++){ \ | ||
result->elements[index] = (left->elements[index]) oper (right->elements[index]); \ | ||
} \ | ||
\ | ||
return Data_Wrap_Struct(NMatrix, NULL, nm_free, result); \ | ||
} | ||
|
||
DEF_ELEMENTWISE_RUBY_ACCESSOR(subtract, -) | ||
DEF_ELEMENTWISE_RUBY_ACCESSOR(multiply, *) | ||
DEF_ELEMENTWISE_RUBY_ACCESSOR(divide, /) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
require 'nmatrix/nmatrix.rb' | ||
require 'nmatrix.so' |
Empty file.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
class NMatrix | ||
|
||
# attr_reader :shape, :elements | ||
|
||
# def initialize shape, elements | ||
# @shape = shape | ||
# @elements = elements | ||
# end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
class NMatrix | ||
module VERSION #:nodoc: | ||
MAJOR = 0 | ||
MINOR = 0 | ||
TINY = 1 | ||
STRING = [MAJOR, MINOR, TINY].compact.join(".") | ||
end | ||
end |
Oops, something went wrong.