diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..57a50e6 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,40 @@ +# Contributing to ArrayFire + +## Reporting Issues + +We both value and encourage the community to provide feedback about using ArrayFire and the issues they are facing. +The more detailed the information, the easier it is for the developers to resolve the issue. + +Issues can span a variety of topics including: +- Feature requests +- Bug reports +- Build Issues +- Performance improvements +- New hardware / backend support + +We use the github [issue tracker](https://github.com/arrayfire/arrayfire-rb/issues?state=open) to track our issues. Technical issues can also be discussed on our [user forum](https://groups.google.com/forum/#!forum/arrayfire-users). + +## Contributing Code + +If you want to contribute code, we suggest you use the one of the following methods. + +- [Using Github](https://github.com/arrayfire/arrayfire-rb/wiki/Contribute-code-using-github) +- [Using Email](https://github.com/arrayfire/arrayfire-rb/wiki/Contribute-code-using-email) + +Key areas of code contributions include: +- [New features](https://github.com/arrayfire/arrayfire-rb/issues?q=is%3Aopen+is%3Aissue+label%3Afeature) +- [Bug fixes](https://github.com/arrayfire/arrayfire-rb/labels/bug) +- [Style changes](https://github.com/arrayfire/arrayfire-rb/labels/style) +- [Performance improvements](https://github.com/arrayfire/arrayfire-rb/labels/style) +- [New tests](https://github.com/arrayfire/arrayfire-rb/labels/test) +- New examples! + +## ArrayFire Based Projects + +You can also contribute to ArrayFire by helping out projects that use ArrayFire! For our part, in addition to the ArrayFire library we are also in the process of adding native bindings for numerous language. We currently support + +- [Java](https://github.com/arrayfire/arrayfire_java) +- [R](https://github.com/arrayfire/arrayfire_r) +- [Fortran](https://github.com/arrayfire/arrayfire_fortran) + +If you are experienced in any of these languages, you can help us improve these language bindings. If you prefer a different language that is not in the list, dive in and create a new repo! diff --git a/LICENSE b/LICENSE index bbc9e5a..b7b3701 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,6 @@ -Copyright (c) 2016, ArrayFire +BSD 3-Clause License + +Copyright (c) 2016-2017, Prasun Anand and ArrayFire All rights reserved. Redistribution and use in source and binary forms, with or without @@ -11,7 +13,7 @@ modification, are permitted provided that the following conditions are met: this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -* Neither the name of arrayfire-rb nor the names of its +* Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. @@ -25,4 +27,3 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/README.md b/README.md index 1b19ddf..a3ee453 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,45 @@ + + +ArrayFire is a general-purpose library that simplifies the process of developing +software that targets parallel and massively-parallel architectures including +CPUs, GPUs, and other hardware acceleration devices. + # Ruby wrapper for ArrayFire [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/arrayfire/arrayfire-ruby) Ruby bindings are a work in progress and are not production ready yet. -## Build from source +## Installation + ```sh git clone https://github.com/arrayfire/arrayfire-rb +cd arrayfire/ +gem install bundler bundle install rake compile ``` + +Run the tests using + +```sh +rake test +``` + +If you want to try out the code without installing: + +```sh +rake pry +``` + +To install: + +```sh +rake install +``` + +# LICENSE + +This software is distributed under the [BSD 3-Clause License](LICENSE). + +Copyright © 2017, Prasun Anand and ArrayFire diff --git a/Rakefile b/Rakefile index 08c84f8..a210642 100644 --- a/Rakefile +++ b/Rakefile @@ -1,5 +1,8 @@ +require "bundler/gem_tasks" require 'rake' require 'rake/extensiontask' +require "rake/testtask" +require "rdoc/task" Rake::ExtensionTask.new do |ext| ext.name = 'arrayfire' @@ -21,3 +24,16 @@ 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 diff --git a/arrayfire.gemspec b/arrayfire.gemspec index 2f0ec5f..21de1da 100644 --- a/arrayfire.gemspec +++ b/arrayfire.gemspec @@ -1,20 +1,37 @@ +# coding: utf-8 +$:.unshift File.expand_path("../lib", __FILE__) + +require 'arrayfire/version.rb' + +ArrayFire::DESCRIPTION = < 0' gem.add_development_dependency 'bundler', '~>1.6' - gem.add_development_dependency 'json' + gem.add_development_dependency 'json', '~> 0' gem.add_development_dependency 'pry', '~>0.10' gem.add_development_dependency 'rake', '~>10.3' gem.add_development_dependency 'rake-compiler', '~>0.8' gem.add_development_dependency 'rdoc', '~>4.0', '>=4.0.1' - gem.add_development_dependency 'rspec', '~>2.14' -end + gem.add_development_dependency "minitest", "~> 5.0" + + gem.add_development_dependency 'nmatrix', '~> 0.2.1' +end \ No newline at end of file diff --git a/examples/benchmarks/blas.rb b/examples/benchmarks/blas.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/benchmarks/cg.rb b/examples/benchmarks/cg.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/benchmarks/fft.rb b/examples/benchmarks/fft.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/benchmarks/pi.rb b/examples/benchmarks/pi.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/computer_vision/fast.rb b/examples/computer_vision/fast.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/computer_vision/harris.rb b/examples/computer_vision/harris.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/computer_vision/matching.rb b/examples/computer_vision/matching.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/computer_vision/susan.rb b/examples/computer_vision/susan.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/financial/black_scholes_options.rb b/examples/financial/black_scholes_options.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/financial/heston_model.rb b/examples/financial/heston_model.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/financial/monte_carlo_options.rb b/examples/financial/monte_carlo_options.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/getting_started/convolve.rb b/examples/getting_started/convolve.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/getting_started/integer.rb b/examples/getting_started/integer.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/getting_started/rainfall.rb b/examples/getting_started/rainfall.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/getting_started/vectorize.rb b/examples/getting_started/vectorize.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/helloworld/helloworld.rb b/examples/helloworld/helloworld.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/image_processing/adaptive_thresholding.rb b/examples/image_processing/adaptive_thresholding.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/image_processing/binary_thresholding.rb b/examples/image_processing/binary_thresholding.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/image_processing/brain_segmentation.rb b/examples/image_processing/brain_segmentation.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/image_processing/edge.rb b/examples/image_processing/edge.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/image_processing/filters.rb b/examples/image_processing/filters.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/image_processing/image_demo.rb b/examples/image_processing/image_demo.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/image_processing/image_editing.rb b/examples/image_processing/image_editing.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/image_processing/morphing.rb b/examples/image_processing/morphing.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/image_processing/optical_flow.rb b/examples/image_processing/optical_flow.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/image_processing/pyramids.rb b/examples/image_processing/pyramids.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/lin_algebra/cholesky.rb b/examples/lin_algebra/cholesky.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/lin_algebra/lu.rb b/examples/lin_algebra/lu.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/lin_algebra/qr.rb b/examples/lin_algebra/qr.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/lin_algebra/svd.rb b/examples/lin_algebra/svd.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/machine_learning/bagging.rb b/examples/machine_learning/bagging.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/machine_learning/deep_belief_net.rb b/examples/machine_learning/deep_belief_net.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/machine_learning/geneticalgorithm.rb b/examples/machine_learning/geneticalgorithm.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/machine_learning/kmeans.rb b/examples/machine_learning/kmeans.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/machine_learning/knn.rb b/examples/machine_learning/knn.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/machine_learning/logistic_regression.rb b/examples/machine_learning/logistic_regression.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/machine_learning/naive_bayes.rb b/examples/machine_learning/naive_bayes.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/machine_learning/neural_network.rb b/examples/machine_learning/neural_network.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/machine_learning/perceptron.rb b/examples/machine_learning/perceptron.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/machine_learning/rbm.rb b/examples/machine_learning/rbm.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/machine_learning/softmax_regression.rb b/examples/machine_learning/softmax_regression.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/pde/swe.rb b/examples/pde/swe.rb new file mode 100644 index 0000000..e69de29 diff --git a/examples/unified/basic.rb b/examples/unified/basic.rb new file mode 100644 index 0000000..e69de29 diff --git a/ext/mri/arrayfire.c b/ext/mri/arrayfire.c index 159102e..cc6508a 100644 --- a/ext/mri/arrayfire.c +++ b/ext/mri/arrayfire.c @@ -1,68 +1,680 @@ -// #include "ruby.h" - -#include "arrayfire.h" #include #include -#include "ruby_arrayfire.h" - VALUE ArrayFire = Qnil; VALUE Af_Array = Qnil; -VALUE Device = Qnil; +VALUE Algorithm = Qnil; +VALUE Backend = Qnil; VALUE Blas = Qnil; +VALUE Cuda = Qnil; +VALUE Data = Qnil; +VALUE Device = Qnil; +VALUE Index = Qnil; VALUE Lapack = Qnil; +VALUE OpenCL = Qnil; +VALUE Random = Qnil; +VALUE Sparse = Qnil; +VALUE Statistics = Qnil; +VALUE Util = Qnil; +extern "C++" { + VALUE cNMatrix; +} -typedef struct AF_STRUCT -{ - size_t dimension; // Method of storage (csc, dense, etc). - size_t array; -}afstruct; +// prototypes +void Init_arrayfire(); +void arf_handle_exception(af_err error_code); +const char* get_backend_name(af_backend backend); +const char* get_cl_device_name(afcl_device_type device); +const char* get_cl_platform_name(afcl_platform platform); +const char* get_random_engine_name(af_random_engine_type engine); + +af_backend arf_backend_type_from_rbsymbol(VALUE sym); +af_dtype arf_dtype_from_rbsymbol(VALUE sym); +af_mat_prop arf_mat_type_from_rbsymbol(VALUE sym); +af_moment_type arf_moment_type_from_rbsymbol(VALUE sym); +af_norm_type arf_norm_type_from_rbsymbol(VALUE sym); +af_random_engine_type arf_randome_engine_type_from_rbsymbol(VALUE sym); +af_source arf_source_from_rbsymbol(VALUE sym); -// prototypes -// void Init_arrayfire(); -static VALUE test1(VALUE self); -// VALUE method_arf_init(VALUE self, VALUE val); static VALUE arf_init(int argc, VALUE* argv, VALUE self); static VALUE arf_alloc(VALUE klass); static void arf_free(afstruct* af); -static VALUE dimension(VALUE self); -static VALUE array(VALUE self); -static VALUE get_info(VALUE self); +static VALUE arf_engine_alloc(VALUE klass); +static void arf_engine_free(afrandomenginestruct* afrandomengine); + +// Af_Array +static VALUE arf_create_array(int argc, VALUE* argv); +static VALUE arf_create_handle(int argc, VALUE* argv); +static VALUE arf_copy_array(VALUE self); +static VALUE arf_write_array(VALUE self); +static VALUE arf_get_data_ptr(VALUE self); +static VALUE arf_release_array(VALUE self); +static VALUE arf_retain_array(VALUE self); +static VALUE arf_get_data_ref_count(VALUE self); +static VALUE arf_eval(VALUE self); +static VALUE arf_eval_multiple(VALUE self); +static VALUE arf_set_manual_eval_flag(VALUE self, VALUE flag); +static VALUE arf_get_manual_eval_flag(VALUE self); +static VALUE arf_get_elements(VALUE self); +static VALUE arf_get_type(VALUE self); +static VALUE arf_get_dims(VALUE self); +static VALUE arf_get_numdims(VALUE self); +static VALUE arf_is_empty(VALUE self); +static VALUE arf_is_scalar(VALUE self); +static VALUE arf_is_row(VALUE self); +static VALUE arf_is_column(VALUE self); +static VALUE arf_is_vector(VALUE self); +static VALUE arf_is_complex(VALUE self); +static VALUE arf_is_real(VALUE self); +static VALUE arf_is_double(VALUE self); +static VALUE arf_is_single(VALUE self); +static VALUE arf_is_realfloating(VALUE self); +static VALUE arf_is_floating(VALUE self); +static VALUE arf_is_integer(VALUE self); +static VALUE arf_is_bool(VALUE self); +static VALUE arf_is_sparse(VALUE self); + +static VALUE arf_to_string(VALUE self); + +// Algorithm +static VALUE arf_sum(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_sum_nan(VALUE self, VALUE array_val, VALUE dim_val, VALUE nan_val); +static VALUE arf_product(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_product_nan(VALUE self, VALUE array_val, VALUE dim_val, VALUE nan_val); +static VALUE arf_min(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_max(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_all_true(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_any_true(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_count(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_sum_all(VALUE self, VALUE array_val); +static VALUE arf_sum_nan_all(VALUE self, VALUE array_val, VALUE nan_val); +static VALUE arf_product_all(VALUE self, VALUE array_val); +static VALUE arf_product_nan_all(VALUE self, VALUE array_val, VALUE nan_val); +static VALUE arf_min_all(VALUE self, VALUE array_val); +static VALUE arf_max_all(VALUE self, VALUE array_val); +static VALUE arf_all_true_all(VALUE self, VALUE array_val); +static VALUE arf_any_true_all(VALUE self, VALUE array_val); +static VALUE arf_count_all(VALUE self, VALUE array_val); +static VALUE arf_imin(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_imax(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_imin_all(VALUE self, VALUE array_val); +static VALUE arf_imax_all(VALUE self, VALUE array_val); +static VALUE arf_accum(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_scan(VALUE self); +static VALUE arf_scan_by_key(VALUE self); +static VALUE arf_where(VALUE self); +static VALUE arf_diff1(VALUE self); +static VALUE arf_diff2(VALUE self); +static VALUE arf_sort(VALUE self); +static VALUE arf_sort_index(VALUE self); +static VALUE arf_sort_by_key(VALUE self); +static VALUE arf_set_unique(VALUE self); +static VALUE arf_set_union(VALUE self); +static VALUE arf_set_intersect(VALUE self); + +// Backend +static VALUE arf_get_backend_count(VALUE self); +static VALUE arf_get_available_backends(VALUE self); +static VALUE arf_get_backend_id(VALUE self, VALUE array_val); +static VALUE arf_get_active_backend(VALUE self); +static VALUE arf_get_backend_device_id(VALUE self, VALUE array_val); +static VALUE arf_set_backend(VALUE self, VALUE backend_val); + +// BLAS +static VALUE arf_matmul(VALUE self, VALUE left_val, VALUE right_val, VALUE left_prop_val, VALUE right_prop_val); +static VALUE arf_dot(VALUE self, VALUE left_val, VALUE right_val, VALUE left_prop_val, VALUE right_prop_val); +static VALUE arf_transpose(VALUE self, VALUE input); +static VALUE arf_transpose_inplace(VALUE self, VALUE input); + +// CUDA +static VALUE arf_get_stream(VALUE self, VALUE id); +static VALUE arf_get_native_id(VALUE self, VALUE cuda_device_id); +static VALUE arf_set_native_id(VALUE self, VALUE native_id); + +// Device +static VALUE arf_info(VALUE self); +static VALUE arf_init2(VALUE self); +static VALUE arf_info_string(VALUE self, VALUE bool_val); +static VALUE arf_device_info(VALUE self, VALUE name_val, VALUE platform_val, VALUE toolkit_val, VALUE compute_val); +static VALUE arf_get_device_count(VALUE self); +static VALUE arf_get_dbl_support(VALUE self, VALUE device); +static VALUE arf_set_device(VALUE self, VALUE device); +static VALUE arf_get_device(VALUE self); +static VALUE arf_sync(VALUE self, VALUE device_val); +static VALUE arf_alloc_device(VALUE self); +static VALUE arf_free_device(VALUE self); +static VALUE arf_alloc_pinned(VALUE self); +static VALUE arf_free_pinned(VALUE self); +static VALUE arf_alloc_host(VALUE self); +static VALUE arf_free_host(VALUE self); +static VALUE arf_device_array(VALUE self); +static VALUE arf_device_mem_info(VALUE self); +static VALUE arf_print_mem_info(VALUE self, VALUE msg_val, VALUE device_id_val); +static void arf_device_gc(VALUE self); +static VALUE arf_set_mem_step_size(VALUE self, VALUE step_bytes); +static VALUE arf_get_mem_step_size(VALUE self); +static VALUE arf_lock_device_ptr(VALUE self, VALUE array_val); +static VALUE arf_unlock_device_ptr(VALUE self, VALUE array_val); +static VALUE arf_lock_array(VALUE self, VALUE array_val); +static VALUE arf_unlock_array(VALUE self, VALUE array_val); +static VALUE arf_is_locked_array(VALUE self, VALUE array_val); +static VALUE arf_get_device_ptr(VALUE self); + +// OpenCL +static VALUE arf_get_context(VALUE self); +static VALUE arf_get_queue(VALUE self); +static VALUE arf_get_device_id(VALUE self); +static VALUE arf_set_device_id(VALUE self); +static VALUE arf_add_device_context(VALUE self); +static VALUE arf_set_device_context(VALUE self); +static VALUE arf_delete_device_context(VALUE self); +static VALUE arf_get_device_type(VALUE self); +static VALUE arf_get_platform(VALUE self); + +// Data +static VALUE arf_constant(int argc, VALUE* argv); +static VALUE arf_constant_complex(VALUE self); +static VALUE arf_constant_long(int argc, VALUE* argv); +static VALUE arf_constant_ulong(int argc, VALUE* argv); +static VALUE arf_range(int argc, VALUE* argv); +static VALUE arf_iota(VALUE self); +static VALUE arf_identity(int argc, VALUE* argv); +static VALUE arf_diag_create(VALUE self, VALUE array_val, VALUE num_val); +static VALUE arf_diag_extract(VALUE self, VALUE array_val, VALUE num_val); +static VALUE arf_join(VALUE self, VALUE dim_val, VALUE first_array_val, VALUE second_array_val); +static VALUE arf_join_many(VALUE self); +static VALUE arf_tile(VALUE self, VALUE array_val, VALUE x_val, VALUE y_val, VALUE z_val, VALUE w_val); +static VALUE arf_reorder(VALUE self, VALUE array_val, VALUE x_val, VALUE y_val, VALUE z_val, VALUE w_val); +static VALUE arf_shift(VALUE self, VALUE array_val, VALUE x_val, VALUE y_val, VALUE z_val, VALUE w_val); +static VALUE arf_moddims(VALUE self); +static VALUE arf_flat(VALUE self, VALUE array_val); +static VALUE arf_flip(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_lower(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_upper(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_select(VALUE self, VALUE array_cond_val, VALUE array_a_val, VALUE array_b_val); +static VALUE arf_select_scalar_r(VALUE self, VALUE array_cond_val, VALUE array_a_val, VALUE b_val); +static VALUE arf_select_scalar_l(VALUE self, VALUE array_cond_val, VALUE a_val, VALUE array_b_val); +static VALUE arf_replace(VALUE self, VALUE array_input_val, VALUE array_cond_val, VALUE array_b_val); +static VALUE arf_replace_scalar(VALUE self, VALUE array_input_val, VALUE array_cond_val, VALUE b_val); + +// Index +static VALUE arf_index(VALUE self); +static VALUE arf_lookup(VALUE self); +static VALUE arf_assign_seq(VALUE self); +static VALUE arf_index_gen(VALUE self); +static VALUE arf_assign_gen(VALUE self); +static VALUE arf_create_indexers(VALUE self); +static VALUE arf_set_array_indexer(VALUE self); +static VALUE arf_set_seq_indexer(VALUE self); +static VALUE arf_set_seq_param_indexer(VALUE self); +static VALUE arf_release_indexers(VALUE self); + +// LAPACK +static VALUE arf_svd_func(VALUE self, VALUE u_val, VALUE s_val, VALUE vt_val, VALUE val); +static VALUE arf_svd_inplace_func(VALUE self, VALUE val); +static VALUE arf_lu_func(VALUE self, VALUE lower_val, VALUE upper_val, VALUE pivot_val, VALUE val); +static VALUE arf_lu_inplace_func(VALUE self); +static VALUE arf_qr_func(VALUE self, VALUE q_val, VALUE r_val, VALUE tau_val, VALUE val); +static VALUE arf_qr_inplace_func(VALUE self); +static VALUE arf_cholesky_func(VALUE self, VALUE output_val, VALUE val, VALUE is_upper_val); +static VALUE arf_cholesky_inplace_func(VALUE self); +static VALUE arf_solve(VALUE self, VALUE lhs_val, VALUE rhs_val); +static VALUE arf_solve_lu(VALUE self, VALUE lhs_val, VALUE rhs_val, VALUE piv_val); +static VALUE arf_inverse(VALUE self, VALUE val); +static VALUE arf_rank(VALUE self, VALUE val); +static VALUE arf_det(VALUE self, VALUE val); +static VALUE arf_norm(VALUE self, VALUE val); +static VALUE arf_is_lapack_available(VALUE self); + +// Random +static VALUE arf_create_random_engine(VALUE self, VALUE type_val, VALUE seed_val); +static VALUE arf_retain_random_engine(VALUE self, VALUE engine_val); +static VALUE arf_random_engine_set_type(VALUE self, VALUE engine_val, VALUE type_val); +static VALUE arf_random_engine_get_type(VALUE self, VALUE engine_val); +static VALUE arf_random_uniform(VALUE self, VALUE ndims_val, VALUE dim_val, VALUE engine_val); +static VALUE arf_random_normal(VALUE self, VALUE ndims_val, VALUE dim_val, VALUE engine_val); +static VALUE arf_random_engine_set_seed(VALUE self, VALUE engine_val ,VALUE seed_val); +static VALUE arf_get_default_random_engine(VALUE self); +static VALUE arf_set_default_random_engine_type(VALUE self, VALUE type_val); +static VALUE arf_random_engine_get_seed(VALUE self, VALUE engine_val); +static VALUE arf_release_random_engine(VALUE self, VALUE engine_val); +static VALUE arf_randu(VALUE self, VALUE ndims_val, VALUE dim_val); +static VALUE arf_randn(VALUE self, VALUE ndims_val, VALUE dim_val); +static VALUE arf_set_seed(VALUE self, VALUE seed); +static VALUE arf_get_seed(VALUE self); + +// Sparse +static VALUE arf_create_sparse_array(VALUE self, VALUE shape_array, VALUE values_array, VALUE rowIdx_val, VALUE colIdx_val, VALUE stype_val); +static VALUE arf_create_sparse_array_from_ptr(VALUE self); +static VALUE arf_create_sparse_array_from_dense(VALUE self, VALUE dense_val, VALUE stype_val); +static VALUE arf_sparse_convert_to(VALUE self, VALUE input_val, VALUE dest_storage_val); +static VALUE arf_sparse_to_dense(VALUE self, VALUE sparse_array); +static VALUE arf_sparse_get_info_func(VALUE self, VALUE values_val, VALUE rowIdx_val, VALUE colIdx_val, VALUE input_val); +static VALUE arf_sparse_get_values(VALUE self, VALUE input_val); +static VALUE arf_sparse_get_row_idx(VALUE self, VALUE input_val); +static VALUE arf_sparse_get_col_idx(VALUE self, VALUE input_val); +static VALUE arf_sparse_get_nnz(VALUE self, VALUE input_val); +static VALUE arf_sparse_get_storage(VALUE self, VALUE input_val); + +// Statistics +static VALUE arf_mean(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_mean_weighted(VALUE self, VALUE array_val, VALUE weighted_array_val, VALUE dim_val); +static VALUE arf_var(VALUE self, VALUE array_val, VALUE is_biased, VALUE dim_val); +static VALUE arf_var_weighted(VALUE self, VALUE array_val, VALUE weighted_array_val, VALUE dim_val); +static VALUE arf_stdev(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_cov(VALUE self, VALUE first_array_val, VALUE second_array_val, VALUE is_biased); +static VALUE arf_median(VALUE self, VALUE array_val, VALUE dim_val); +static VALUE arf_mean_all(VALUE self, VALUE array_val); +static VALUE arf_mean_all_weighted(VALUE self, VALUE array_val, VALUE weighted_array_val); +static VALUE arf_var_all(VALUE self, VALUE array_val, VALUE is_biased); +static VALUE arf_var_all_weighted(VALUE self, VALUE array_val, VALUE weighted_array_val); +static VALUE arf_stdev_all(VALUE self, VALUE array_val); +static VALUE arf_median_all(VALUE self, VALUE array_val); +static VALUE arf_corrcoef(VALUE self, VALUE first_array_val, VALUE second_array_val); + +// Util +static VALUE arf_print_array(VALUE self, VALUE input_val); +static VALUE arf_print_array_gen(VALUE self); +static VALUE arf_save_array(VALUE self, VALUE key_val, VALUE array_val, VALUE fn_val, VALUE append); +static VALUE arf_read_array_index(VALUE self); +static VALUE arf_read_array_key(VALUE self); +static VALUE arf_read_array_key_check(VALUE self); +static VALUE arf_array_to_string(VALUE self, VALUE exp_val, VALUE array_val, VALUE precision, VALUE transpose); +static VALUE arf_example_function(VALUE self); +static VALUE arf_get_version(VALUE self); +static VALUE arf_get_revision(VALUE self); +static VALUE arf_get_size_of(VALUE self, VALUE dtype_val); + +#define DECL_ELEMENTWISE_RUBY_ACCESSOR(name) static VALUE arf_ew_##name(VALUE left_val, VALUE right_val); +#define DECL_UNARY_RUBY_ACCESSOR(name) static VALUE arf_unary_##name(VALUE self); + +DECL_ELEMENTWISE_RUBY_ACCESSOR(add) +DECL_ELEMENTWISE_RUBY_ACCESSOR(subtract) +DECL_ELEMENTWISE_RUBY_ACCESSOR(multiply) +DECL_ELEMENTWISE_RUBY_ACCESSOR(divide) + +DECL_ELEMENTWISE_RUBY_ACCESSOR(eqeq) +DECL_ELEMENTWISE_RUBY_ACCESSOR(neq) +DECL_ELEMENTWISE_RUBY_ACCESSOR(leq) +DECL_ELEMENTWISE_RUBY_ACCESSOR(geq) +DECL_ELEMENTWISE_RUBY_ACCESSOR(lt) +DECL_ELEMENTWISE_RUBY_ACCESSOR(gt) + +DECL_UNARY_RUBY_ACCESSOR(sin) +DECL_UNARY_RUBY_ACCESSOR(cos) +DECL_UNARY_RUBY_ACCESSOR(tan) +DECL_UNARY_RUBY_ACCESSOR(asin) +DECL_UNARY_RUBY_ACCESSOR(acos) +DECL_UNARY_RUBY_ACCESSOR(atan) +DECL_UNARY_RUBY_ACCESSOR(sinh) +DECL_UNARY_RUBY_ACCESSOR(cosh) +DECL_UNARY_RUBY_ACCESSOR(tanh) +DECL_UNARY_RUBY_ACCESSOR(asinh) +DECL_UNARY_RUBY_ACCESSOR(acosh) +DECL_UNARY_RUBY_ACCESSOR(atanh) +DECL_UNARY_RUBY_ACCESSOR(exp) +DECL_UNARY_RUBY_ACCESSOR(log2) +DECL_UNARY_RUBY_ACCESSOR(log1p) +DECL_UNARY_RUBY_ACCESSOR(log10) +DECL_UNARY_RUBY_ACCESSOR(sqrt) +DECL_UNARY_RUBY_ACCESSOR(erf) +DECL_UNARY_RUBY_ACCESSOR(erfc) +DECL_UNARY_RUBY_ACCESSOR(cbrt) +DECL_UNARY_RUBY_ACCESSOR(lgamma) +DECL_UNARY_RUBY_ACCESSOR(tgamma) +DECL_UNARY_RUBY_ACCESSOR(floor) +DECL_UNARY_RUBY_ACCESSOR(ceil) + +/* + * Macro defines an element-wise accessor function for some operation. + * + * This is only responsible for the Ruby accessor! You still have to write the actual functions, obviously. + */ + +static VALUE arf_eqeq(VALUE left_val, VALUE right_val); +static VALUE arf_eqeq_approx(VALUE left_val, VALUE right_val); + +// Interfaces + +static VALUE arf_af_array_to_nmatrix(VALUE self); +extern VALUE arf_nmatrix_to_af_array_method(VALUE nmatrix); +afstruct* arf_nmatrix_to_af_array(VALUE nm); void Init_arrayfire() { ArrayFire = rb_define_module("ArrayFire"); - rb_define_method(ArrayFire, "test1", (METHOD)test1, 0); Af_Array = rb_define_class_under(ArrayFire, "Af_Array", rb_cObject); rb_define_alloc_func(Af_Array, arf_alloc); rb_define_method(Af_Array, "initialize", (METHOD)arf_init, -1); - rb_define_method(Af_Array, "dimension", (METHOD)dimension, 0); - rb_define_method(Af_Array, "array", (METHOD)array, 0); + rb_define_singleton_method(Af_Array, "create_array", (METHOD)arf_create_array, -1); + rb_define_singleton_method(Af_Array, "create_handle", (METHOD)arf_create_handle, -1); + rb_define_method(Af_Array, "copy_array", (METHOD)arf_copy_array, 0); + rb_define_method(Af_Array, "write_array", (METHOD)arf_write_array, 0); + rb_define_method(Af_Array, "get_data_ptr", (METHOD)arf_get_data_ptr, 0); + rb_define_method(Af_Array, "release_array", (METHOD)arf_release_array, 0); + rb_define_method(Af_Array, "retain_array", (METHOD)arf_retain_array, 0); + rb_define_method(Af_Array, "get_data_ref_count", (METHOD)arf_get_data_ref_count, 0); + rb_define_method(Af_Array, "eval", (METHOD)arf_eval, 0); + rb_define_method(Af_Array, "eval_multiple", (METHOD)arf_eval_multiple, 0); + rb_define_singleton_method(Af_Array, "set_manual_eval_flag", (METHOD)arf_set_manual_eval_flag, 1); + rb_define_singleton_method(Af_Array, "get_manual_eval_flag", (METHOD)arf_get_manual_eval_flag, 0); + rb_define_method(Af_Array, "get_elements", (METHOD)arf_get_elements, 0); + rb_define_method(Af_Array, "get_type", (METHOD)arf_get_type, 0); + rb_define_method(Af_Array, "get_dims", (METHOD)arf_get_dims, 0); + rb_define_method(Af_Array, "get_numdims", (METHOD)arf_get_numdims, 0); + rb_define_method(Af_Array, "is_empty", (METHOD)arf_is_empty, 0); + rb_define_method(Af_Array, "is_scalar", (METHOD)arf_is_scalar, 0); + rb_define_method(Af_Array, "is_row", (METHOD)arf_is_row, 0); + rb_define_method(Af_Array, "is_column", (METHOD)arf_is_column, 0); + rb_define_method(Af_Array, "is_vector", (METHOD)arf_is_vector, 0); + rb_define_method(Af_Array, "is_complex", (METHOD)arf_is_complex, 0); + rb_define_method(Af_Array, "is_real", (METHOD)arf_is_real, 0); + rb_define_method(Af_Array, "is_double", (METHOD)arf_is_double, 0); + rb_define_method(Af_Array, "is_single", (METHOD)arf_is_single, 0); + rb_define_method(Af_Array, "is_realfloating", (METHOD)arf_is_realfloating, 0); + rb_define_method(Af_Array, "is_floating", (METHOD)arf_is_floating, 0); + rb_define_method(Af_Array, "is_integer", (METHOD)arf_is_integer, 0); + rb_define_method(Af_Array, "is_bool", (METHOD)arf_is_bool, 0); + rb_define_method(Af_Array, "is_sparse", (METHOD)arf_is_sparse, 0); + + rb_define_method(Af_Array, "to_s", (METHOD)arf_to_string, 0); + + rb_define_alias(Af_Array, "ndims", "get_numdims"); + rb_define_alias(Af_Array, "dims", "get_dims"); + rb_define_alias(Af_Array, "to_cpu", "get_data_ptr"); + rb_define_alias(Af_Array, "elements", "get_data_ptr"); + + rb_define_method(Af_Array, "+",(METHOD)arf_ew_add,1); + rb_define_method(Af_Array, "-",(METHOD)arf_ew_subtract,1); + rb_define_method(Af_Array, "*",(METHOD)arf_ew_multiply,1); + rb_define_method(Af_Array, "/",(METHOD)arf_ew_divide,1); + rb_define_method(Af_Array, "==",(METHOD)arf_eqeq,1); + rb_define_method(Af_Array, "approx_equal",(METHOD)arf_eqeq_approx,1); + + rb_define_method(Af_Array, "=~",(METHOD)arf_ew_eqeq,1); + rb_define_method(Af_Array, "!~", (METHOD)arf_ew_neq, 1); + rb_define_method(Af_Array, "<=", (METHOD)arf_ew_leq, 1); + rb_define_method(Af_Array, ">=", (METHOD)arf_ew_geq, 1); + rb_define_method(Af_Array, "<", (METHOD)arf_ew_lt, 1); + rb_define_method(Af_Array, ">", (METHOD)arf_ew_gt, 1); + + rb_define_method(Af_Array, "sin", (METHOD)arf_unary_sin, 0); + rb_define_method(Af_Array, "cos", (METHOD)arf_unary_cos, 0); + rb_define_method(Af_Array, "tan", (METHOD)arf_unary_tan, 0); + rb_define_method(Af_Array, "asin", (METHOD)arf_unary_asin, 0); + rb_define_method(Af_Array, "acos", (METHOD)arf_unary_acos, 0); + rb_define_method(Af_Array, "atan", (METHOD)arf_unary_atan, 0); + rb_define_method(Af_Array, "sinh", (METHOD)arf_unary_sinh, 0); + rb_define_method(Af_Array, "cosh", (METHOD)arf_unary_cosh, 0); + rb_define_method(Af_Array, "tanh", (METHOD)arf_unary_tanh, 0); + rb_define_method(Af_Array, "asinh", (METHOD)arf_unary_asinh, 0); + rb_define_method(Af_Array, "acosh", (METHOD)arf_unary_acosh, 0); + rb_define_method(Af_Array, "atanh", (METHOD)arf_unary_atanh, 0); + rb_define_method(Af_Array, "exp", (METHOD)arf_unary_exp, 0); + rb_define_method(Af_Array, "log2", (METHOD)arf_unary_log2, 0); + rb_define_method(Af_Array, "log1p", (METHOD)arf_unary_log1p, 0); + rb_define_method(Af_Array, "log10", (METHOD)arf_unary_log10, 0); + rb_define_method(Af_Array, "sqrt", (METHOD)arf_unary_sqrt, 0); + rb_define_method(Af_Array, "erf", (METHOD)arf_unary_erf, 0); + rb_define_method(Af_Array, "erfc", (METHOD)arf_unary_erfc, 0); + rb_define_method(Af_Array, "cbrt", (METHOD)arf_unary_cbrt, 0); + rb_define_method(Af_Array, "lgamma", (METHOD)arf_unary_lgamma, 0); + rb_define_method(Af_Array, "tgamma", (METHOD)arf_unary_tgamma, 0); + rb_define_method(Af_Array, "floor", (METHOD)arf_unary_floor, 0); + rb_define_method(Af_Array, "ceil", (METHOD)arf_unary_ceil, 0); + + rb_define_method(Af_Array, "to_nmatrix", (METHOD)arf_af_array_to_nmatrix, 0); + + cNMatrix = rb_define_class("NMatrix", rb_cObject); + rb_define_method(cNMatrix, "to_af_array", (METHOD)arf_nmatrix_to_af_array_method, 0); + + Algorithm = rb_define_class_under(ArrayFire, "Algorithm", rb_cObject); + rb_define_singleton_method(Algorithm, "sum", (METHOD)arf_sum, 2); + rb_define_singleton_method(Algorithm, "sum_nan", (METHOD)arf_sum_nan, 3); + rb_define_singleton_method(Algorithm, "product", (METHOD)arf_product, 2); + rb_define_singleton_method(Algorithm, "product_nan", (METHOD)arf_product_nan, 3); + rb_define_singleton_method(Algorithm, "min", (METHOD)arf_min, 2); + rb_define_singleton_method(Algorithm, "max", (METHOD)arf_max, 2); + rb_define_singleton_method(Algorithm, "all_true", (METHOD)arf_all_true, 2); + rb_define_singleton_method(Algorithm, "any_true", (METHOD)arf_any_true, 2); + rb_define_singleton_method(Algorithm, "count", (METHOD)arf_count, 2); + rb_define_singleton_method(Algorithm, "sum_all", (METHOD)arf_sum_all, 1); + rb_define_singleton_method(Algorithm, "sum_nan_all", (METHOD)arf_sum_nan_all, 2); + rb_define_singleton_method(Algorithm, "product_all", (METHOD)arf_product_all, 1); + rb_define_singleton_method(Algorithm, "product_nan_all", (METHOD)arf_product_nan_all, 2); + rb_define_singleton_method(Algorithm, "min_all", (METHOD)arf_min_all, 1); + rb_define_singleton_method(Algorithm, "max_all", (METHOD)arf_max_all, 1); + rb_define_singleton_method(Algorithm, "all_true_all", (METHOD)arf_all_true_all, 1); + rb_define_singleton_method(Algorithm, "any_true_all", (METHOD)arf_any_true_all, 1); + rb_define_singleton_method(Algorithm, "count_all", (METHOD)arf_count_all, 1); + rb_define_singleton_method(Algorithm, "imin", (METHOD)arf_imin, 0); + rb_define_singleton_method(Algorithm, "imax", (METHOD)arf_imax, 0); + rb_define_singleton_method(Algorithm, "imin_all", (METHOD)arf_imin_all, 0); + rb_define_singleton_method(Algorithm, "imax_all", (METHOD)arf_imax_all, 0); + rb_define_singleton_method(Algorithm, "accum", (METHOD)arf_accum, 0); + rb_define_singleton_method(Algorithm, "scan", (METHOD)arf_scan, 0); + rb_define_singleton_method(Algorithm, "scan_by_key", (METHOD)arf_scan_by_key, 0); + rb_define_singleton_method(Algorithm, "where", (METHOD)arf_where, 0); + rb_define_singleton_method(Algorithm, "diff1", (METHOD)arf_diff1, 0); + rb_define_singleton_method(Algorithm, "diff2", (METHOD)arf_diff2, 0); + rb_define_singleton_method(Algorithm, "sort", (METHOD)arf_sort, 0); + rb_define_singleton_method(Algorithm, "sort_index", (METHOD)arf_sort_index, 0); + rb_define_singleton_method(Algorithm, "sort_by_key", (METHOD)arf_sort_by_key, 0); + rb_define_singleton_method(Algorithm, "set_unique", (METHOD)arf_set_unique, 0); + rb_define_singleton_method(Algorithm, "set_union", (METHOD)arf_set_union, 0); + rb_define_singleton_method(Algorithm, "set_intersect", (METHOD)arf_set_intersect, 0); + + Backend = rb_define_class_under(ArrayFire, "Backend", rb_cObject); + rb_define_singleton_method(Backend, "get_backend_count", (METHOD)arf_get_backend_count, 0); + rb_define_singleton_method(Backend, "get_available_backends", (METHOD)arf_get_available_backends, 0); + rb_define_singleton_method(Backend, "get_backend_id", (METHOD)arf_get_backend_id, 1); + rb_define_singleton_method(Backend, "get_active_backend", (METHOD)arf_get_active_backend, 0); + rb_define_singleton_method(Backend, "get_device_id", (METHOD)arf_get_backend_device_id, 1); + rb_define_singleton_method(Backend, "set_backend", (METHOD)arf_set_backend, 1); Device = rb_define_class_under(ArrayFire, "Device", rb_cObject); - rb_define_method(Device, "getInfo", (METHOD)get_info, 0); + rb_define_singleton_method(Device, "info", (METHOD)arf_info, 0); + rb_define_singleton_method(Device, "init", (METHOD)arf_init2, 0); + rb_define_singleton_method(Device, "info_string", (METHOD)arf_info_string, 1); + rb_define_singleton_method(Device, "device_info_func", (METHOD)arf_device_info, 4); + rb_define_singleton_method(Device, "get_device_count", (METHOD)arf_get_device_count, 0); + rb_define_singleton_method(Device, "get_dbl_support", (METHOD)arf_get_dbl_support, 1); + rb_define_singleton_method(Device, "set_device", (METHOD)arf_set_device, 1); + rb_define_singleton_method(Device, "get_device", (METHOD)arf_get_device, 0); + rb_define_singleton_method(Device, "sync", (METHOD)arf_sync, 1); + rb_define_singleton_method(Device, "alloc_device", (METHOD)arf_alloc_device, 0); + rb_define_singleton_method(Device, "free_device", (METHOD)arf_free_device, 0); + rb_define_singleton_method(Device, "alloc_pinned", (METHOD)arf_alloc_pinned, 0); + rb_define_singleton_method(Device, "free_pinned", (METHOD)arf_free_pinned, 0); + rb_define_singleton_method(Device, "alloc_host", (METHOD)arf_alloc_host, 0); + rb_define_singleton_method(Device, "free_host", (METHOD)arf_free_host, 0); + rb_define_singleton_method(Device, "device_array", (METHOD)arf_device_array, 0); + rb_define_singleton_method(Device, "device_mem_info", (METHOD)arf_device_mem_info, 0); + rb_define_singleton_method(Device, "print_mem_info", (METHOD)arf_print_mem_info, 2); + rb_define_singleton_method(Device, "device_gc", (METHOD)arf_device_gc, 0); + rb_define_singleton_method(Device, "set_mem_step_size", (METHOD)arf_set_mem_step_size, 1); + rb_define_singleton_method(Device, "get_mem_step_size", (METHOD)arf_get_mem_step_size, 0); + rb_define_singleton_method(Device, "lock_device_ptr", (METHOD)arf_lock_device_ptr, 1); + rb_define_singleton_method(Device, "unlock_device_ptr", (METHOD)arf_unlock_device_ptr, 1); + rb_define_singleton_method(Device, "lock_array", (METHOD)arf_lock_array, 1); + rb_define_singleton_method(Device, "unlock_array", (METHOD)arf_unlock_array, 1); + rb_define_singleton_method(Device, "is_locked_array", (METHOD)arf_is_locked_array, 1); + rb_define_singleton_method(Device, "get_device_ptr", (METHOD)arf_get_device_ptr, 0); Blas = rb_define_class_under(ArrayFire, "BLAS", rb_cObject); + rb_define_singleton_method(Blas, "matmul", (METHOD)arf_matmul, 4); + rb_define_singleton_method(Blas, "dot", (METHOD)arf_dot, 4); + rb_define_singleton_method(Blas, "transpose", (METHOD)arf_transpose, 1); + rb_define_singleton_method(Blas, "transpose_inplace", (METHOD)arf_transpose_inplace, 1); + + Cuda = rb_define_class_under(ArrayFire, "CUDA", rb_cObject); + rb_define_singleton_method(Cuda, "get_stream", (METHOD)arf_get_stream, 1); + rb_define_singleton_method(Cuda, "get_native_id", (METHOD)arf_get_native_id, 1); + rb_define_singleton_method(Cuda, "set_native_id", (METHOD)arf_set_native_id, 1); + + Index = rb_define_class_under(ArrayFire, "Index", rb_cObject); + rb_define_singleton_method(Index, "index", (METHOD)arf_index, 0); + rb_define_singleton_method(Index, "lookup", (METHOD)arf_lookup, 0); + rb_define_singleton_method(Index, "assign_seq", (METHOD)arf_assign_seq, 0); + rb_define_singleton_method(Index, "index_gen", (METHOD)arf_index_gen, 0); + rb_define_singleton_method(Index, "assign_gen", (METHOD)arf_assign_gen, 0); + rb_define_singleton_method(Index, "create_indexers", (METHOD)arf_create_indexers, 0); + rb_define_singleton_method(Index, "set_array_indexer", (METHOD)arf_set_array_indexer, 0); + rb_define_singleton_method(Index, "set_seq_indexer", (METHOD)arf_set_seq_indexer, 0); + rb_define_singleton_method(Index, "set_seq_param_indexer", (METHOD)arf_set_seq_param_indexer, 0); + rb_define_singleton_method(Index, "release_indexers", (METHOD)arf_release_indexers, 0); + + OpenCL = rb_define_class_under(ArrayFire, "OpenCL", rb_cObject); + rb_define_singleton_method(OpenCL, "get_context", (METHOD)arf_get_context, 0); + rb_define_singleton_method(OpenCL, "get_queue", (METHOD)arf_get_queue, 0); + rb_define_singleton_method(OpenCL, "get_device_id", (METHOD)arf_get_device_id, 0); + rb_define_singleton_method(OpenCL, "set_device_id", (METHOD)arf_set_device_id, 0); + rb_define_singleton_method(OpenCL, "add_device_context", (METHOD)arf_add_device_context, 0); + rb_define_singleton_method(OpenCL, "set_device_context", (METHOD)arf_set_device_context, 0); + rb_define_singleton_method(OpenCL, "delete_device_context", (METHOD)arf_delete_device_context, 0); + rb_define_singleton_method(OpenCL, "get_device_type", (METHOD)arf_get_device_type, 0); + rb_define_singleton_method(OpenCL, "get_platform", (METHOD)arf_get_platform, 0); + + Data = rb_define_class_under(ArrayFire, "Data", rb_cObject); + rb_define_singleton_method(Data, "constant", (METHOD)arf_constant, -1); + rb_define_singleton_method(Data, "constant_complex", (METHOD)arf_constant_complex, 0); + rb_define_singleton_method(Data, "constant_long", (METHOD)arf_constant_long, -1); + rb_define_singleton_method(Data, "constant_ulong", (METHOD)arf_constant_ulong, -1); + rb_define_singleton_method(Data, "range", (METHOD)arf_range, -1); + rb_define_singleton_method(Data, "iota", (METHOD)arf_iota, 0); + rb_define_singleton_method(Data, "identity", (METHOD)arf_identity, -1); + rb_define_singleton_method(Data, "diag_create", (METHOD)arf_diag_create, 2); + rb_define_singleton_method(Data, "diag_extract", (METHOD)arf_diag_extract, 2); + rb_define_singleton_method(Data, "join", (METHOD)arf_join, 3); + rb_define_singleton_method(Data, "join_many", (METHOD)arf_join_many, 0); + rb_define_singleton_method(Data, "tile", (METHOD)arf_tile, 5); + rb_define_singleton_method(Data, "reorder", (METHOD)arf_reorder, 5); + rb_define_singleton_method(Data, "shift", (METHOD)arf_shift, 5); + rb_define_singleton_method(Data, "moddims", (METHOD)arf_moddims, 0); + rb_define_singleton_method(Data, "flat", (METHOD)arf_flat, 1); + rb_define_singleton_method(Data, "flip", (METHOD)arf_flip, 2); + rb_define_singleton_method(Data, "lower", (METHOD)arf_lower, 2); + rb_define_singleton_method(Data, "upper", (METHOD)arf_upper, 2); + rb_define_singleton_method(Data, "select", (METHOD)arf_select, 3); + rb_define_singleton_method(Data, "select_scalar_r", (METHOD)arf_select_scalar_r, 3); + rb_define_singleton_method(Data, "select_scalar_l", (METHOD)arf_select_scalar_l, 3); + rb_define_singleton_method(Data, "replace", (METHOD)arf_replace, 3); + rb_define_singleton_method(Data, "replace_scalar", (METHOD)arf_replace_scalar, 3); Lapack = rb_define_class_under(ArrayFire, "LAPACK", rb_cObject); -} + rb_define_singleton_method(Lapack, "svd_func", (METHOD)arf_svd_func, 4); + rb_define_singleton_method(Lapack, "svd_inplace_func", (METHOD)arf_svd_inplace_func, 1); + rb_define_singleton_method(Lapack, "lu_func", (METHOD)arf_lu_func, 4); + rb_define_singleton_method(Lapack, "lu_inplace_func", (METHOD)arf_lu_inplace_func, 1); + rb_define_singleton_method(Lapack, "qr_func", (METHOD)arf_qr_func, 4); + rb_define_singleton_method(Lapack, "qr_inplace_func", (METHOD)arf_qr_inplace_func, 1); + rb_define_singleton_method(Lapack, "cholesky_func", (METHOD)arf_cholesky_func, 3); + rb_define_singleton_method(Lapack, "cholesky_inplace_func", (METHOD)arf_cholesky_inplace_func, 1); + rb_define_singleton_method(Lapack, "solve", (METHOD)arf_solve, 2); + rb_define_singleton_method(Lapack, "solve_lu", (METHOD)arf_solve_lu, 3); + rb_define_singleton_method(Lapack, "inverse", (METHOD)arf_inverse, 1); + rb_define_singleton_method(Lapack, "rank", (METHOD)arf_rank, 1); + rb_define_singleton_method(Lapack, "det", (METHOD)arf_det, 1); + rb_define_singleton_method(Lapack, "norm", (METHOD)arf_norm, 1); + rb_define_singleton_method(Lapack, "is_lapack_available", (METHOD)arf_is_lapack_available, 0); + + Random = rb_define_class_under(ArrayFire, "Random", rb_cObject); + rb_define_alloc_func(Random, arf_engine_alloc); + rb_define_singleton_method(Random, "create_random_engine", (METHOD)arf_create_random_engine, 2); + rb_define_singleton_method(Random, "retain_random_engine", (METHOD)arf_retain_random_engine, 1); + rb_define_singleton_method(Random, "random_engine_set_type", (METHOD)arf_random_engine_set_type, 2); + rb_define_singleton_method(Random, "random_engine_get_type", (METHOD)arf_random_engine_get_type, 1); + rb_define_singleton_method(Random, "random_uniform", (METHOD)arf_random_uniform, 3); + rb_define_singleton_method(Random, "random_normal", (METHOD)arf_random_normal, 3); + rb_define_singleton_method(Random, "random_engine_set_seed", (METHOD)arf_random_engine_set_seed, 2); + rb_define_singleton_method(Random, "get_default_random_engine", (METHOD)arf_get_default_random_engine, 0); + rb_define_singleton_method(Random, "set_default_random_engine_type", (METHOD)arf_set_default_random_engine_type, 1); + rb_define_singleton_method(Random, "random_engine_get_seed", (METHOD)arf_random_engine_get_seed, 1); + rb_define_singleton_method(Random, "release_random_engine", (METHOD)arf_release_random_engine, 1); + rb_define_singleton_method(Random, "randu", (METHOD)arf_randu, 2); + rb_define_singleton_method(Random, "randn", (METHOD)arf_randn, 2); + rb_define_singleton_method(Random, "set_seed", (METHOD)arf_set_seed, 1); + rb_define_singleton_method(Random, "get_seed", (METHOD)arf_get_seed, 0); + + Sparse = rb_define_class_under(ArrayFire, "Sparse", rb_cObject); + rb_define_singleton_method(Sparse, "create_sparse_array", (METHOD)arf_create_sparse_array, 5); + rb_define_singleton_method(Sparse, "create_sparse_array_from_ptr", (METHOD)arf_create_sparse_array_from_ptr, 0); + rb_define_singleton_method(Sparse, "create_sparse_array_from_dense", (METHOD)arf_create_sparse_array_from_dense, 2); + rb_define_singleton_method(Sparse, "sparse_convert_to", (METHOD)arf_sparse_convert_to, 2); + rb_define_singleton_method(Sparse, "sparse_to_dense", (METHOD)arf_sparse_to_dense, 1); + rb_define_singleton_method(Sparse, "sparse_get_info_func", (METHOD)arf_sparse_get_info_func, 4); + rb_define_singleton_method(Sparse, "sparse_get_values", (METHOD)arf_sparse_get_values, 1); + rb_define_singleton_method(Sparse, "sparse_get_row_idx", (METHOD)arf_sparse_get_row_idx, 1); + rb_define_singleton_method(Sparse, "sparse_get_col_idx", (METHOD)arf_sparse_get_col_idx, 1); + rb_define_singleton_method(Sparse, "sparse_get_nnz", (METHOD)arf_sparse_get_nnz, 1); + rb_define_singleton_method(Sparse, "sparse_get_storage", (METHOD)arf_sparse_get_storage, 1); + + Statistics = rb_define_class_under(ArrayFire, "Statistics", rb_cObject); + rb_define_singleton_method(Statistics, "mean", (METHOD)arf_mean, 2); + rb_define_singleton_method(Statistics, "mean_weighted", (METHOD)arf_mean_weighted, 3); + rb_define_singleton_method(Statistics, "var", (METHOD)arf_var, 3); + rb_define_singleton_method(Statistics, "var_weighted", (METHOD)arf_var_weighted, 3); + rb_define_singleton_method(Statistics, "stdev", (METHOD)arf_stdev, 2); + rb_define_singleton_method(Statistics, "cov", (METHOD)arf_cov, 3); + rb_define_singleton_method(Statistics, "median", (METHOD)arf_median, 2); + rb_define_singleton_method(Statistics, "mean_all", (METHOD)arf_mean_all, 1); + rb_define_singleton_method(Statistics, "mean_all_weighted", (METHOD)arf_mean_all_weighted, 2); + rb_define_singleton_method(Statistics, "var_all", (METHOD)arf_var_all, 2); + rb_define_singleton_method(Statistics, "var_all_weighted", (METHOD)arf_var_all_weighted, 2); + rb_define_singleton_method(Statistics, "stdev_all", (METHOD)arf_stdev_all, 1); + rb_define_singleton_method(Statistics, "median_all", (METHOD)arf_median_all, 1); + rb_define_singleton_method(Statistics, "corrcoef", (METHOD)arf_corrcoef, 2); + + Util = rb_define_class_under(ArrayFire, "Util", rb_cObject); + rb_define_singleton_method(Util, "print_array", (METHOD)arf_print_array, 1); + rb_define_singleton_method(Util, "print_array_gen", (METHOD)arf_print_array_gen, 0); + rb_define_singleton_method(Util, "save_array", (METHOD)arf_save_array, 4); + rb_define_singleton_method(Util, "read_array_index", (METHOD)arf_read_array_index, 0); + rb_define_singleton_method(Util, "read_array_key", (METHOD)arf_read_array_key, 0); + rb_define_singleton_method(Util, "read_array_key_check", (METHOD)arf_read_array_key_check, 0); + rb_define_singleton_method(Util, "array_to_string", (METHOD)arf_array_to_string, 4); + rb_define_singleton_method(Util, "example_function", (METHOD)arf_example_function, 0); + rb_define_singleton_method(Util, "get_version", (METHOD)arf_get_version, 0); + rb_define_singleton_method(Util, "get_revision", (METHOD)arf_get_revision, 0); + rb_define_singleton_method(Util, "get_size_of", (METHOD)arf_get_size_of, 1); -VALUE test1(VALUE self) { - VALUE x; - x = rb_str_new_cstr("Hello, world!"); - return x; } +/* + * call-seq: + * new(dimesnsion) -> Af_Array + * new(dims, dimesnsion, elements, data_type) -> Af_Array + * + * Create a new Af_Array. + * + */ + VALUE arf_init(int argc, VALUE* argv, VALUE self) { - afstruct* afarray; Data_Get_Struct(self, afstruct, afarray); - afarray->dimension = argv[0]; - afarray->array = argv[1]; + if(argc > 0){ + af_dtype dtype = (argc == 4) ? arf_dtype_from_rbsymbol(argv[3]) : f64; + + dim_t ndims = (dim_t)FIX2LONG(argv[0]); + dim_t* dimensions = ALLOC_N(dim_t, ndims); + dim_t count = 1; + for (dim_t index = 0; index < ndims; index++) { + dimensions[index] = (dim_t)FIX2LONG(RARRAY_AREF(argv[1], index)); + count *= dimensions[index]; + } + double* host_array = ALLOC_N(double, count); + for (dim_t index = 0; index < count; index++) { + host_array[index] = (double)NUM2DBL(RARRAY_AREF(argv[2], index)); + } + af_err flag = af_create_array(&afarray->carray, host_array, ndims, dimensions, dtype); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(afarray->carray); + } return self; } @@ -75,35 +687,108 @@ static VALUE arf_alloc(VALUE klass) return Data_Wrap_Struct(klass, NULL, arf_free, af); } +static VALUE arf_engine_alloc(VALUE klass) +{ + /* allocate */ + afrandomenginestruct* afrandomengine = ALLOC(afrandomenginestruct); + /* wrap */ + return Data_Wrap_Struct(klass, NULL, arf_engine_free, afrandomengine); +} static void arf_free(afstruct* af) { - free(af); + xfree(af); } -static VALUE dimension(VALUE self) +static void arf_engine_free(afrandomenginestruct* afrandomengine) { - afstruct * af; + xfree(afrandomengine); +} + - Data_Get_Struct(self, afstruct, af); +static VALUE arf_to_string(VALUE self){ + char* output; + afstruct* input; - return af->dimension; + Data_Get_Struct(self, afstruct, input); + const char* exp = ""; + af_array_to_string(&output, exp, input->carray, 3, false); + + return rb_str_new_cstr(output); } -static VALUE array(VALUE self) -{ - afstruct * af; +static VALUE arf_eqeq(VALUE left_val, VALUE right_val) { + afstruct* left; + afstruct* right; + afstruct* result = ALLOC(afstruct); + Data_Get_Struct(left_val, afstruct, left); + Data_Get_Struct(right_val, afstruct, right); + af_eq(&result->carray, left->carray, right->carray, true); - Data_Get_Struct(self, afstruct, af); + dim_t count; + af_get_elements(&count, result->carray); + bool* data = ALLOC_N(bool, count); + af_err flag = af_get_data_ptr(data, result->carray); - return af->array; + if(flag != AF_SUCCESS){ + rb_raise(rb_eArgError, "Something went wrong!"); + } + + for (dim_t index = 0; index < count; index++){ + if(!data[index]){ + return Qfalse; + } + } + return Qtrue; } -static VALUE get_info(VALUE self) -{ - VALUE x; - af_info(); - arf::matmul_benchmark(); - return x; +static VALUE arf_eqeq_approx(VALUE left_val, VALUE right_val) { + + afstruct* left; + afstruct* right; + + dim_t left_count; + dim_t right_count; + + Data_Get_Struct(left_val, afstruct, left); + Data_Get_Struct(right_val, afstruct, right); + + af_get_elements(&left_count, left->carray); + af_get_elements(&right_count, right->carray); + + if(left_count != right_count){return Qfalse;} + + double* left_arr = ALLOC_N(double, left_count); + af_get_data_ptr(left_arr, left->carray); + + double* right_arr = ALLOC_N(double, left_count); + af_get_data_ptr(right_arr, right->carray); + + for (dim_t index = 0; index < left_count; index++){ + double diff = left_arr[index] - right_arr[index]; + if(diff < 0){diff *= -1;} + if(diff > 1e-3){ + return Qfalse; + } + } + return Qtrue; } +#include "cmodules/array.c" +#include "cmodules/algorithm.c" +#include "cmodules/arith.c" +#include "cmodules/backend.c" +#include "cmodules/blas.c" +#include "cmodules/cuda.c" +#include "cmodules/data.c" +#include "cmodules/defines.c" +#include "cmodules/device.c" +#include "cmodules/index.c" +#include "cmodules/lapack.c" +#include "cmodules/opencl.c" +#include "cmodules/random.c" +#include "cmodules/sparse.c" +#include "cmodules/statistics.c" +#include "cmodules/util.c" + +#include "interfaces/nmatrix.c" diff --git a/ext/mri/cmodules/algorithm.c b/ext/mri/cmodules/algorithm.c new file mode 100644 index 0000000..73b783d --- /dev/null +++ b/ext/mri/cmodules/algorithm.c @@ -0,0 +1,286 @@ +static VALUE arf_sum(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_sum(&output->carray, input->carray, FIX2INT(dim_val)); + + return Data_Wrap_Struct(CLASS_OF(array_val), NULL, arf_free, output); +} + +static VALUE arf_sum_nan(VALUE self, VALUE array_val, VALUE dim_val, VALUE nan_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_sum_nan(&output->carray, input->carray, FIX2INT(dim_val), NUM2DBL(nan_val)); + + return Data_Wrap_Struct(CLASS_OF(array_val), NULL, arf_free, output); +} + +static VALUE arf_product(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_product(&output->carray, input->carray, FIX2INT(dim_val)); + + return Data_Wrap_Struct(CLASS_OF(array_val), NULL, arf_free, output); +} + +static VALUE arf_product_nan(VALUE self, VALUE array_val, VALUE dim_val, VALUE nan_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_product_nan(&output->carray, input->carray, FIX2INT(dim_val), NUM2DBL(nan_val)); + + return Data_Wrap_Struct(CLASS_OF(array_val), NULL, arf_free, output); +} + +static VALUE arf_min(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_min(&output->carray, input->carray, FIX2INT(dim_val)); + + return Data_Wrap_Struct(CLASS_OF(array_val), NULL, arf_free, output); +} + +static VALUE arf_max(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_max(&output->carray, input->carray, FIX2INT(dim_val)); + + return Data_Wrap_Struct(CLASS_OF(array_val), NULL, arf_free, output); +} + +static VALUE arf_all_true(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_all_true(&output->carray, input->carray, FIX2INT(dim_val)); + + return Data_Wrap_Struct(CLASS_OF(array_val), NULL, arf_free, output); +} + +static VALUE arf_any_true(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_any_true(&output->carray, input->carray, FIX2INT(dim_val)); + + return Data_Wrap_Struct(CLASS_OF(array_val), NULL, arf_free, output); +} + +static VALUE arf_count(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_count(&output->carray, input->carray, FIX2INT(dim_val)); + + return Data_Wrap_Struct(CLASS_OF(array_val), NULL, arf_free, output); +} + +static VALUE arf_sum_all(VALUE self, VALUE array_val){ + afstruct* input; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + + af_sum_all(&real_part, &imag_part, input->carray); + + return DBL2NUM(real_part); +} + +static VALUE arf_sum_nan_all(VALUE self, VALUE array_val, VALUE nan_val){ + afstruct* input; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + + af_sum_nan_all(&real_part, &imag_part, input->carray, NUM2DBL(nan_val)); + + return DBL2NUM(real_part); +} + +static VALUE arf_product_all(VALUE self, VALUE array_val){ + afstruct* input; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + + af_product_all(&real_part, &imag_part, input->carray); + + return DBL2NUM(real_part); +} + +static VALUE arf_product_nan_all(VALUE self, VALUE array_val, VALUE nan_val){ + afstruct* input; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + + af_product_nan_all(&real_part, &imag_part, input->carray, NUM2DBL(nan_val)); + + return DBL2NUM(real_part); +} + +static VALUE arf_min_all(VALUE self, VALUE array_val){ + afstruct* input; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + + af_min_all(&real_part, &imag_part, input->carray); + + return DBL2NUM(real_part); +} + +static VALUE arf_max_all(VALUE self, VALUE array_val){ + afstruct* input; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + + af_max_all(&real_part, &imag_part, input->carray); + + return DBL2NUM(real_part); +} + +static VALUE arf_all_true_all(VALUE self, VALUE array_val){ + afstruct* input; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + + af_all_true_all(&real_part, &imag_part, input->carray); + + return DBL2NUM(real_part); +} + +static VALUE arf_any_true_all(VALUE self, VALUE array_val){ + afstruct* input; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + + af_any_true_all(&real_part, &imag_part, input->carray); + + return DBL2NUM(real_part); +} + +static VALUE arf_count_all(VALUE self, VALUE array_val){ + afstruct* input; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + + af_count_all(&real_part, &imag_part, input->carray); + + return DBL2NUM(real_part); +} + +static VALUE arf_imin(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + afstruct* idx = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_imin(&output->carray, &idx->carray, input->carray, FIX2INT(dim_val)); + return Data_Wrap_Struct(CLASS_OF(array_val), NULL, arf_free, output); +} + +static VALUE arf_imax(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + afstruct* idx = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_imax(&output->carray, &idx->carray, input->carray, FIX2INT(dim_val)); + return Data_Wrap_Struct(CLASS_OF(array_val), NULL, arf_free, output); +} + +static VALUE arf_imin_all(VALUE self, VALUE array_val){ + afstruct* input; + double real_part, imag_part; + uint idx; + + Data_Get_Struct(array_val, afstruct, input); + + af_imin_all(&real_part, &imag_part, &idx, input->carray); + return DBL2NUM(real_part); +} + +static VALUE arf_imax_all(VALUE self, VALUE array_val){ + afstruct* input; + double real_part, imag_part; + uint idx; + + Data_Get_Struct(array_val, afstruct, input); + + af_imax_all(&real_part, &imag_part, &idx, input->carray); + return DBL2NUM(real_part); +} + +static VALUE arf_accum(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_accum(&output->carray, input->carray, FIX2INT(dim_val)); + + return Data_Wrap_Struct(CLASS_OF(array_val), NULL, arf_free, output); +} + +static VALUE arf_scan(VALUE self){ + return Qnil; +} +static VALUE arf_scan_by_key(VALUE self){ + return Qnil; +} +static VALUE arf_where(VALUE self){ + return Qnil; +} +static VALUE arf_diff1(VALUE self){ + return Qnil; +} +static VALUE arf_diff2(VALUE self){ + return Qnil; +} +static VALUE arf_sort(VALUE self){ + return Qnil; +} +static VALUE arf_sort_index(VALUE self){ + return Qnil; +} +static VALUE arf_sort_by_key(VALUE self){ + return Qnil; +} +static VALUE arf_set_unique(VALUE self){ + return Qnil; +} +static VALUE arf_set_union(VALUE self){ + return Qnil; +} +static VALUE arf_set_intersect(VALUE self){ + return Qnil; +} \ No newline at end of file diff --git a/ext/mri/cmodules/arith.c b/ext/mri/cmodules/arith.c new file mode 100644 index 0000000..fdbea23 --- /dev/null +++ b/ext/mri/cmodules/arith.c @@ -0,0 +1,60 @@ +#define DEF_ELEMENTWISE_RUBY_ACCESSOR(name, oper) \ +static VALUE arf_ew_##name(VALUE left_val, VALUE right_val) { \ + afstruct* left; \ + afstruct* right; \ + afstruct* result = ALLOC(afstruct); \ + Data_Get_Struct(left_val, afstruct, left); \ + Data_Get_Struct(right_val, afstruct, right); \ + af_err flag = af_##oper(&result->carray, left->carray, right->carray, true); \ + if (flag != AF_SUCCESS) arf_handle_exception(flag); \ + af_print_array(result->carray); \ + return Data_Wrap_Struct(CLASS_OF(left_val), NULL, arf_free, result); \ +} + +#define DEF_UNARY_RUBY_ACCESSOR(oper, name) \ +static VALUE arf_unary_##name(VALUE self) { \ + afstruct* obj; \ + afstruct* result = ALLOC(afstruct); \ + Data_Get_Struct(self, afstruct, obj); \ + af_err flag = af_##oper(&result->carray, obj->carray); \ + if (flag != AF_SUCCESS) arf_handle_exception(flag); \ + af_print_array(result->carray); \ + return Data_Wrap_Struct(CLASS_OF(self), NULL, arf_free, result); \ +} + +DEF_ELEMENTWISE_RUBY_ACCESSOR(add, add) +DEF_ELEMENTWISE_RUBY_ACCESSOR(subtract, sub) +DEF_ELEMENTWISE_RUBY_ACCESSOR(multiply, mul) +DEF_ELEMENTWISE_RUBY_ACCESSOR(divide, div) + +DEF_ELEMENTWISE_RUBY_ACCESSOR(eqeq, eq) +DEF_ELEMENTWISE_RUBY_ACCESSOR(neq, neq) +DEF_ELEMENTWISE_RUBY_ACCESSOR(leq, le) +DEF_ELEMENTWISE_RUBY_ACCESSOR(geq, ge) +DEF_ELEMENTWISE_RUBY_ACCESSOR(lt, lt) +DEF_ELEMENTWISE_RUBY_ACCESSOR(gt, gt) + +DEF_UNARY_RUBY_ACCESSOR(sin, sin) +DEF_UNARY_RUBY_ACCESSOR(cos, cos) +DEF_UNARY_RUBY_ACCESSOR(tan, tan) +DEF_UNARY_RUBY_ACCESSOR(asin, asin) +DEF_UNARY_RUBY_ACCESSOR(acos, acos) +DEF_UNARY_RUBY_ACCESSOR(atan, atan) +DEF_UNARY_RUBY_ACCESSOR(sinh, sinh) +DEF_UNARY_RUBY_ACCESSOR(cosh, cosh) +DEF_UNARY_RUBY_ACCESSOR(tanh, tanh) +DEF_UNARY_RUBY_ACCESSOR(asinh, asinh) +DEF_UNARY_RUBY_ACCESSOR(acosh, acosh) +DEF_UNARY_RUBY_ACCESSOR(atanh, atanh) +DEF_UNARY_RUBY_ACCESSOR(exp, exp) +DEF_UNARY_RUBY_ACCESSOR(log2, log2) +DEF_UNARY_RUBY_ACCESSOR(log1p, log1p) +DEF_UNARY_RUBY_ACCESSOR(log10, log10) +DEF_UNARY_RUBY_ACCESSOR(sqrt, sqrt) +DEF_UNARY_RUBY_ACCESSOR(erf, erf) +DEF_UNARY_RUBY_ACCESSOR(erfc, erfc) +DEF_UNARY_RUBY_ACCESSOR(cbrt, cbrt) +DEF_UNARY_RUBY_ACCESSOR(lgamma, lgamma) +DEF_UNARY_RUBY_ACCESSOR(tgamma, tgamma) +DEF_UNARY_RUBY_ACCESSOR(floor, floor) +DEF_UNARY_RUBY_ACCESSOR(ceil, ceil) diff --git a/ext/mri/cmodules/array.c b/ext/mri/cmodules/array.c new file mode 100644 index 0000000..cd5e4d9 --- /dev/null +++ b/ext/mri/cmodules/array.c @@ -0,0 +1,377 @@ +static VALUE arf_create_array(int argc, VALUE* argv){ + afstruct* afarray = ALLOC(afstruct); + dim_t ndims = (dim_t)FIX2LONG(argv[0]); + dim_t* dimensions = ALLOC_N(dim_t, ndims); + dim_t count = 1; + for (dim_t index = 0; index < ndims; index++) { + dimensions[index] = (dim_t)FIX2LONG(RARRAY_AREF(argv[1], index)); + count *= dimensions[index]; + } + double* host_array = ALLOC_N(double, count);; + for (dim_t index = 0; index < count; index++) { + host_array[index] = (double)NUM2DBL(RARRAY_AREF(argv[2], index)); + } + + af_err flag = af_create_array(&afarray->carray, host_array, ndims, dimensions, f32); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(afarray->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, afarray); +} + +static VALUE arf_create_handle(int argc, VALUE* argv){ + afstruct* afarray = ALLOC(afstruct); + dim_t ndims = (dim_t)FIX2LONG(argv[0]); + dim_t* dimensions = ALLOC_N(dim_t, ndims); + dim_t count = 1; + for (dim_t index = 0; index < ndims; index++) { + dimensions[index] = (dim_t)FIX2LONG(RARRAY_AREF(argv[1], index)); + count *= dimensions[index]; + } + double* host_array = ALLOC_N(double, count); + for (dim_t index = 0; index < count; index++) { + host_array[index] = (double)NUM2DBL(RARRAY_AREF(argv[2], index)); + } + + af_err flag = af_create_handle(&afarray->carray, ndims, dimensions, f32); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(afarray->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, afarray); +} + +static VALUE arf_copy_array(VALUE self){ + afstruct* array_val; + afstruct* result = ALLOC(afstruct); + + Data_Get_Struct(self, afstruct, array_val); + + af_err flag = af_copy_array(&result->carray, array_val->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(CLASS_OF(self), NULL, arf_free, result); +} + +static VALUE arf_write_array(VALUE self){ + return Qnil; +} + +static VALUE arf_get_data_ptr(VALUE self){ + afstruct* input; + dim_t count; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_get_elements(&count, input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + double* data = ALLOC_N(double, count); + + flag = af_get_data_ptr(data, input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + VALUE* array = ALLOC_N(VALUE, count); + for (dim_t index = 0; index < count; index++){ + array[index] = DBL2NUM(data[index]); + } + + return rb_ary_new4(count, array); +} + +static VALUE arf_release_array(VALUE self){ + afstruct* input; + Data_Get_Struct(self, afstruct, input); + af_err flag = af_release_array(input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qtrue; +} + +static VALUE arf_retain_array(VALUE self){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + Data_Get_Struct(self, afstruct, input); + af_err flag = af_retain_array(&output->carray, input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Data_Wrap_Struct(CLASS_OF(self), NULL, arf_free, output); +} + +static VALUE arf_get_data_ref_count(VALUE self){ + afstruct* input; + int use_count; + Data_Get_Struct(self, afstruct, input); + af_err flag = af_get_data_ref_count(&use_count, input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return INT2NUM(use_count); +} + +static VALUE arf_eval(VALUE self){ + afstruct* input; + Data_Get_Struct(self, afstruct, input); + af_err flag = af_eval(input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qtrue; +} + +static VALUE arf_eval_multiple(VALUE self){ + return Qnil; +} + +static VALUE arf_set_manual_eval_flag(VALUE self, VALUE flag){ + af_err code = af_set_manual_eval_flag(RTEST(flag)); + if (code != AF_SUCCESS) arf_handle_exception(code); + return Qtrue; +} + +static VALUE arf_get_manual_eval_flag(VALUE self){ + bool flag; + af_err code = af_get_manual_eval_flag(&flag); + if (code != AF_SUCCESS) arf_handle_exception(code); + return flag ? Qtrue : Qfalse; +} + +static VALUE arf_get_elements(VALUE self){ + afstruct* input; + + dim_t elems; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_get_elements(&elems, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return ULONG2NUM(elems); +} + +static VALUE arf_get_type(VALUE self){ + afstruct* input; + af_dtype type; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_get_type(&type, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Qnil; +} + +static VALUE arf_get_dims(VALUE self){ + afstruct* input; + Data_Get_Struct(self, afstruct, input); + + uint ndims; + + af_err flag = af_get_numdims(&ndims, input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + dim_t* dims = ALLOC_N(dim_t, ndims); + + flag = af_get_dims(&dims[0], &dims[1], &dims[2], &dims[3], input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + VALUE* array = ALLOC_N(VALUE, ndims); + for (dim_t index = 0; index < ndims; index++){ + array[index] = UINT2NUM(dims[index]); + } + + return rb_ary_new4(ndims, array); +} + +static VALUE arf_get_numdims(VALUE self){ + afstruct* input; + uint result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_get_numdims(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return UINT2NUM(result); +} + +static VALUE arf_is_empty(VALUE self){ + afstruct* input; + bool result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_is_empty(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} + +static VALUE arf_is_scalar(VALUE self){ + afstruct* input; + bool result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_is_scalar(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} + +static VALUE arf_is_row(VALUE self){ + afstruct* input; + bool result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_is_row(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} + +static VALUE arf_is_column(VALUE self){ + afstruct* input; + bool result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_is_column(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} + +static VALUE arf_is_vector(VALUE self){ + afstruct* input; + bool result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_is_vector(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} + +static VALUE arf_is_complex(VALUE self){ + afstruct* input; + bool result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_is_complex(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} + +static VALUE arf_is_real(VALUE self){ + afstruct* input; + bool result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_is_real(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} + +static VALUE arf_is_double(VALUE self){ + afstruct* input; + bool result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_is_double(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} + +static VALUE arf_is_single(VALUE self){ + afstruct* input; + bool result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_is_single(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} + +static VALUE arf_is_realfloating(VALUE self){ + afstruct* input; + bool result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_is_realfloating(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} + +static VALUE arf_is_floating(VALUE self){ + afstruct* input; + bool result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_is_floating(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} + +static VALUE arf_is_integer(VALUE self){ + afstruct* input; + bool result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_is_integer(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} + +static VALUE arf_is_bool(VALUE self){ + afstruct* input; + bool result; + + Data_Get_Struct(self, afstruct, input); + + af_err flag = af_is_bool(&result, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} + +static VALUE arf_is_sparse(VALUE self){ + afstruct* input; + bool result = false; + + Data_Get_Struct(self, afstruct, input); + + //FIXME + af_err flag = af_is_bool(&result, input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return result ? Qtrue : Qfalse; +} diff --git a/ext/mri/cmodules/backend.c b/ext/mri/cmodules/backend.c new file mode 100644 index 0000000..443f371 --- /dev/null +++ b/ext/mri/cmodules/backend.c @@ -0,0 +1,65 @@ +static VALUE arf_get_backend_count(VALUE self){ + uint num_backends; + + af_err flag = af_get_backend_count(&num_backends); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return UINT2NUM(num_backends); +} + +// int backends = af::getAvailableBackends(); +// bool cpu = backends & AF_BACKEND_CPU; +// bool cuda = backends & AF_BACKEND_CUDA; +// bool opencl = backends & AF_BACKEND_OPENCL; + +static VALUE arf_get_available_backends(VALUE self){ + int backends; + + af_err flag = af_get_available_backends(&backends); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return INT2NUM(backends); +} + +static VALUE arf_get_backend_id(VALUE self, VALUE array_val){ + afstruct* input; + Data_Get_Struct(array_val, afstruct, input); + af_backend backend; + + af_err flag = af_get_backend_id (&backend, input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + const char* backend_name = get_backend_name(backend); + return rb_str_new_cstr(backend_name); +} + +static VALUE arf_get_active_backend(VALUE self){ + af_backend backend; + + af_err flag = af_get_active_backend(&backend); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + const char* backend_name = get_backend_name(backend); + return rb_str_new_cstr(backend_name); +} + +static VALUE arf_get_backend_device_id(VALUE self, VALUE array_val){ + afstruct* input; + int device_id; + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_get_device_id(&device_id, input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return INT2NUM(device_id); +} + +static VALUE arf_set_backend(VALUE self, VALUE backend_val){ + af_backend backend = arf_backend_type_from_rbsymbol(backend_val); + + af_err flag = af_set_backend(backend); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Qtrue; +} diff --git a/ext/mri/cmodules/blas.c b/ext/mri/cmodules/blas.c new file mode 100644 index 0000000..19ec7d2 --- /dev/null +++ b/ext/mri/cmodules/blas.c @@ -0,0 +1,61 @@ +static VALUE arf_matmul(VALUE self, VALUE left_val, VALUE right_val, VALUE left_prop_val, VALUE right_prop_val){ + + afstruct* left; + afstruct* right; + afstruct* result = ALLOC(afstruct); + + Data_Get_Struct(left_val, afstruct, left); + Data_Get_Struct(right_val, afstruct, right); + + af_mat_prop left_mat_prop = arf_mat_type_from_rbsymbol(left_prop_val); + af_mat_prop right_mat_prop = arf_mat_type_from_rbsymbol(right_prop_val); + + af_err flag = af_matmul(&result->carray, left->carray, right->carray, left_mat_prop, right_mat_prop); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(CLASS_OF(left_val), NULL, arf_free, result); +} + +static VALUE arf_dot(VALUE self, VALUE left_val, VALUE right_val, VALUE left_prop_val, VALUE right_prop_val){ + afstruct* left; + afstruct* right; + afstruct* result = ALLOC(afstruct); + + Data_Get_Struct(left_val, afstruct, left); + Data_Get_Struct(right_val, afstruct, right); + + af_mat_prop left_mat_prop = arf_mat_type_from_rbsymbol(left_prop_val); + af_mat_prop right_mat_prop = arf_mat_type_from_rbsymbol(right_prop_val); + + af_err flag = af_dot(&result->carray, left->carray, right->carray, left_mat_prop, right_mat_prop); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(CLASS_OF(left_val), NULL, arf_free, result); +} + +static VALUE arf_transpose(VALUE self, VALUE input){ + afstruct* obj; + afstruct* result = ALLOC(afstruct); + + Data_Get_Struct(input, afstruct, obj); + + af_err flag = af_transpose(&result->carray, obj->carray, false); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(CLASS_OF(input), NULL, arf_free, result); +} + +static VALUE arf_transpose_inplace(VALUE self, VALUE input){ + afstruct* obj; + + Data_Get_Struct(input, afstruct, obj); + + af_err flag = af_transpose_inplace(obj->carray, false); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(CLASS_OF(input), NULL, arf_free, obj); +} diff --git a/ext/mri/cmodules/cuda.c b/ext/mri/cmodules/cuda.c new file mode 100644 index 0000000..0d6cf1b --- /dev/null +++ b/ext/mri/cmodules/cuda.c @@ -0,0 +1,18 @@ +static VALUE arf_get_stream(VALUE self, VALUE id){ + // cudaStream_t* stream; + // afcu_get_stream (stream, NUM2INT(id)); + return Qnil; +} + +static VALUE arf_get_native_id(VALUE self, VALUE cuda_device_id){ + int native_id; + af_err flag = afcu_get_native_id(&native_id, NUM2INT(cuda_device_id)); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return INT2NUM(native_id); +} + +static VALUE arf_set_native_id(VALUE self, VALUE native_id){ + af_err flag = afcu_set_native_id(native_id); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qtrue; +} diff --git a/ext/mri/cmodules/data.c b/ext/mri/cmodules/data.c new file mode 100644 index 0000000..9fafa37 --- /dev/null +++ b/ext/mri/cmodules/data.c @@ -0,0 +1,335 @@ +static VALUE arf_constant(int argc, VALUE* argv){ + afstruct* output = ALLOC(afstruct); + + dim_t ndims = (dim_t)FIX2LONG(argv[0]); + dim_t* dimensions = ALLOC_N(dim_t, ndims); + dim_t count = 1; + for (dim_t index = 0; index < ndims; index++) { + dimensions[index] = (dim_t)FIX2LONG(RARRAY_AREF(argv[1], index)); + count *= dimensions[index]; + } + double data = NUM2DBL(argv[2]); + + af_err flag = af_constant(&output->carray, data, 2, dimensions, f32); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_constant_complex(VALUE self){ + return Qnil; +} + +static VALUE arf_constant_long(int argc, VALUE* argv){ + afstruct* output = ALLOC(afstruct); + + dim_t ndims = (dim_t)FIX2LONG(argv[0]); + dim_t* dimensions = ALLOC_N(dim_t, ndims); + dim_t count = 1; + for (dim_t index = 0; index < ndims; index++) { + dimensions[index] = (dim_t)FIX2LONG(RARRAY_AREF(argv[1], index)); + count *= dimensions[index]; + } + long data = NUM2LONG(argv[2]); + + af_err flag = af_constant_long(&output->carray, data, 2, dimensions); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_constant_ulong(int argc, VALUE* argv){ + afstruct* output = ALLOC(afstruct); + + dim_t ndims = (dim_t)FIX2LONG(argv[0]); + dim_t* dimensions = ALLOC_N(dim_t, ndims); + dim_t count = 1; + for (dim_t index = 0; index < ndims; index++) { + dimensions[index] = (dim_t)FIX2LONG(RARRAY_AREF(argv[1], index)); + count *= dimensions[index]; + } + unsigned long data = NUM2LONG(argv[2]); + + af_err flag = af_constant_ulong(&output->carray, data, 2, dimensions); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_range(int argc, VALUE* argv){ + afstruct* output = ALLOC(afstruct); + + dim_t ndims = (dim_t)FIX2LONG(argv[0]); + dim_t* dimensions = ALLOC_N(dim_t, ndims); + dim_t count = 1; + for (dim_t index = 0; index < ndims; index++) { + dimensions[index] = (dim_t)FIX2LONG(RARRAY_AREF(argv[1], index)); + count *= dimensions[index]; + } + int seq_dim = NUM2INT(argv[2]); + af_err flag = af_range(&output->carray, ndims, dimensions, seq_dim, f32); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_iota(VALUE self){ + return Qnil; +} + +static VALUE arf_identity(int argc, VALUE* argv){ + afstruct* output = ALLOC(afstruct); + + dim_t ndims = (dim_t)FIX2LONG(argv[0]); + dim_t* dimensions = ALLOC_N(dim_t, ndims); + dim_t count = 1; + for (dim_t index = 0; index < ndims; index++) { + dimensions[index] = (dim_t)FIX2LONG(RARRAY_AREF(argv[1], index)); + count *= dimensions[index]; + } + + af_err flag = af_identity(&output->carray, ndims, dimensions, f32); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_diag_create(VALUE self, VALUE array_val, VALUE num_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_diag_create(&output->carray, input->carray, NUM2INT(num_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_diag_extract(VALUE self, VALUE array_val, VALUE num_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_diag_extract(&output->carray, input->carray, NUM2INT(num_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_join(VALUE self, VALUE dim_val, VALUE first_array_val, VALUE second_array_val){ + afstruct* first_array; + afstruct* second_array; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(first_array_val, afstruct, first_array); + Data_Get_Struct(second_array_val, afstruct, second_array); + + af_err flag = af_join(&output->carray, NUM2INT(dim_val), first_array->carray, second_array->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_join_many(VALUE self){ + return Qnil; +} + +static VALUE arf_tile(VALUE self, VALUE array_val, VALUE x_val, VALUE y_val, VALUE z_val, VALUE w_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_tile(&output->carray, input->carray, NUM2UINT(x_val), NUM2UINT(y_val), NUM2UINT(z_val), NUM2UINT(w_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_reorder(VALUE self, VALUE array_val, VALUE x_val, VALUE y_val, VALUE z_val, VALUE w_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_reorder(&output->carray, input->carray, NUM2UINT(x_val), NUM2UINT(y_val), NUM2UINT(z_val), NUM2UINT(w_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_shift(VALUE self, VALUE array_val, VALUE x_val, VALUE y_val, VALUE z_val, VALUE w_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_shift(&output->carray, input->carray, NUM2INT(x_val), NUM2INT(y_val), NUM2INT(z_val), NUM2INT(w_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_moddims(VALUE self){ + return Qnil; +} + +static VALUE arf_flat(VALUE self, VALUE array_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_flat(&output->carray, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_flip(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_flip(&output->carray, input->carray, NUM2UINT(dim_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_lower(VALUE self, VALUE array_val, VALUE is_unit_diag){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_lower(&output->carray, input->carray, RTEST(is_unit_diag)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_upper(VALUE self, VALUE array_val, VALUE is_unit_diag){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_upper(&output->carray, input->carray, RTEST(is_unit_diag)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_select(VALUE self, VALUE array_cond_val, VALUE array_a_val, VALUE array_b_val){ + afstruct* array_cond; + afstruct* array_a; + afstruct* array_b; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_cond_val, afstruct, array_cond); + Data_Get_Struct(array_a_val, afstruct, array_a); + Data_Get_Struct(array_b_val, afstruct, array_b); + + af_err flag = af_select(&output->carray, array_cond->carray, array_a->carray, array_b->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_select_scalar_r(VALUE self, VALUE array_cond_val, VALUE array_a_val, VALUE b_val){ + afstruct* array_cond; + afstruct* array_a; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_cond_val, afstruct, array_cond); + Data_Get_Struct(array_a_val, afstruct, array_a); + + af_err flag = af_select_scalar_r(&output->carray, array_cond->carray, array_a->carray, NUM2DBL(b_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_select_scalar_l(VALUE self, VALUE array_cond_val, VALUE a_val, VALUE array_b_val){ + afstruct* array_cond; + afstruct* array_b; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_cond_val, afstruct, array_cond); + Data_Get_Struct(array_b_val, afstruct, array_b); + + af_err flag = af_select_scalar_l(&output->carray, array_cond->carray, NUM2DBL(a_val), array_b->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_replace(VALUE self, VALUE array_input_val, VALUE array_cond_val, VALUE array_b_val){ + afstruct* input; + afstruct* array_cond; + afstruct* array_b; + + Data_Get_Struct(array_input_val, afstruct, input); + Data_Get_Struct(array_cond_val, afstruct, array_cond); + Data_Get_Struct(array_b_val, afstruct, array_b); + + af_err flag = af_replace(&input->carray, array_cond->carray, array_b->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Qtrue; +} + +static VALUE arf_replace_scalar(VALUE self, VALUE array_input_val, VALUE array_cond_val, VALUE b_val){ + afstruct* input; + afstruct* array_cond; + + Data_Get_Struct(array_input_val, afstruct, input); + Data_Get_Struct(array_cond_val, afstruct, array_cond); + + af_err flag = af_replace_scalar(&input->carray, array_cond->carray, NUM2DBL(b_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Qtrue; +} diff --git a/ext/mri/cmodules/defines.c b/ext/mri/cmodules/defines.c new file mode 100644 index 0000000..08674c3 --- /dev/null +++ b/ext/mri/cmodules/defines.c @@ -0,0 +1,233 @@ +const char* const DTYPE_NAMES[ARF_NUM_DTYPES] = { + "f32", + "c32", + "f64", + "c64", + "b8", + "s32", + "u32", + "u8", + "s64", + "u64", + "s16", + "u16" +}; + +const char* const SOURCE_NAMES[ARF_NUM_SOURCES] = { + "afDevice", ///< Device pointer + "afHost" ///< Host pointer +}; + +std::map MAT_PROPERTIES = { + {"AF_MAT_NONE", 0}, + {"AF_MAT_TRANS", 1}, + {"AF_MAT_CTRANS", 2}, + {"AF_MAT_CONJ", 4}, + {"AF_MAT_UPPER", 32}, + {"AF_MAT_LOWER", 64}, + {"AF_MAT_DIAG_UNIT", 128}, + {"AF_MAT_SYM", 512}, + {"AF_MAT_POSDEF", 1024}, + {"AF_MAT_ORTHOG", 2048}, + {"AF_MAT_TRI_DIAG", 4096}, + {"AF_MAT_BLOCK_DIAG", 8192} +}; + +const char* const NORM_TYPES[ARF_NUM_NORM_TYPES] = { + "AF_NORM_VECTOR_1", ///< treats the input as a vector and returns the sum of absolute values + "AF_NORM_VECTOR_INF", ///< treats the input as a vector and returns the max of absolute values + "AF_NORM_VECTOR_2", ///< treats the input as a vector and returns euclidean norm + "AF_NORM_VECTOR_P", ///< treats the input as a vector and returns the p-norm + "AF_NORM_MATRIX_1", ///< return the max of column sums + "AF_NORM_MATRIX_INF", ///< return the max of row sums + "AF_NORM_MATRIX_2", ///< returns the max singular value). Currently NOT SUPPORTED + "AF_NORM_MATRIX_L_PQ", ///< returns Lpq-norm + "AF_NORM_EUCLID" ///< The default. Same as AF_NORM_VECTOR_2 +}; + +std::map MOMENT_TYPES = { + {"AF_MOMENT_M00", 1}, + {"AF_MOMENT_M01", 2}, + {"AF_MOMENT_M10", 4}, + {"AF_MOMENT_M11", 8} + //AF_MOMENT_FIRST_ORDER = AF_MOMENT_M00 | AF_MOMENT_M01 | AF_MOMENT_M10 | AF_MOMENT_M11 +}; + +std::map BACKEND_TYPES = { + {"AF_BACKEND_DEFAULT" , 0}, ///< Default backend order: OpenCL -> CUDA -> CPU + {"AF_BACKEND_CPU" , 1}, ///< CPU a.k.a sequential algorithms + {"AF_BACKEND_CUDA" , 2}, ///< CUDA Compute Backend + {"AF_BACKEND_OPENCL" , 4} ///< OpenCL Compute Backend +}; + +std::map RANDOM_ENGINE_TYPES = { + {"AF_RANDOM_ENGINE_PHILOX_4X32_10" , 100}, //Philox variant with N = 4, W = 32 and Rounds = 10 + {"AF_RANDOM_ENGINE_THREEFRY_2X32_16" , 200}, //Threefry variant with N = 2, W = 32 and Rounds = 16 + {"AF_RANDOM_ENGINE_MERSENNE_GP11213" , 300}, //Mersenne variant with MEXP = 11213 + {"AF_RANDOM_ENGINE_PHILOX" , 100}, //Resolves to Philox 4x32_10 + {"AF_RANDOM_ENGINE_THREEFRY" , 200}, //Resolves to Threefry 2X32_16 + {"AF_RANDOM_ENGINE_MERSENNE" , 300}, //Resolves to Mersenne GP 11213 + {"AF_RANDOM_ENGINE_DEFAULT" , 100}, //Resolves to Philox +}; + +std::map ERROR_TYPES = { + {"AF_SUCCESS" , 0}, + {"AF_ERR_NO_MEM" , 101}, + {"AF_ERR_DRIVER" , 102}, + {"AF_ERR_RUNTIME" , 103}, + {"AF_ERR_INVALID_ARRAY" , 201}, + {"AF_ERR_ARG" , 202}, + {"AF_ERR_SIZE" , 203}, + {"AF_ERR_TYPE" , 204}, + {"AF_ERR_DIFF_TYPE" , 205}, + {"AF_ERR_BATCH" , 207}, + {"AF_ERR_DEVICE" , 208}, + {"AF_ERR_NOT_SUPPORTED" , 301}, + {"AF_ERR_NOT_CONFIGURED" , 302}, + {"AF_ERR_NONFREE" , 303}, + {"AF_ERR_NO_DBL" , 401}, + {"AF_ERR_NO_GFX" , 402}, + {"AF_ERR_LOAD_LIB" , 501}, + {"AF_ERR_LOAD_SYM" , 502}, + {"AF_ERR_ARR_BKND_MISMATCH" , 503}, + {"AF_ERR_INTERNAL" , 998}, + {"AF_ERR_UNKNOWN" , 999} +}; + +const char* const STORAGE_TYPES[ARF_NUM_STORAGE_TYPES] = { + "AF_STORAGE_DENSE", ///< Storage type is dense + "AF_STORAGE_CSR", ///< Storage type is CSR + "AF_STORAGE_CSC", ///< Storage type is CSC + "AF_STORAGE_COO", ///< Storage type is COO +}; + +void arf_handle_exception(af_err error_code){ + for(std::map::value_type& entry : ERROR_TYPES) { + if (error_code == entry.second) { + rb_raise(rb_eArgError, entry.first); + break; + } + } +} + +af_dtype arf_dtype_from_rbsymbol(VALUE sym) { + ID sym_id = SYM2ID(sym); + + for (size_t index = 0; index < ARF_NUM_DTYPES; ++index) { + if (sym_id == rb_intern(DTYPE_NAMES[index])) { + return static_cast(index); + } + } + + VALUE str = rb_any_to_s(sym); + rb_raise(rb_eArgError, "invalid data type symbol (:%s) specified", RSTRING_PTR(str)); +} + +af_source arf_source_from_rbsymbol(VALUE sym) { + ID sym_id = SYM2ID(sym); + + for (size_t index = 0; index < ARF_NUM_SOURCES; ++index) { + if (sym_id == rb_intern(SOURCE_NAMES[index])) { + return static_cast(index); + } + } + + VALUE str = rb_any_to_s(sym); + rb_raise(rb_eArgError, "invalid data type symbol (:%s) specified", RSTRING_PTR(str)); +} + +af_mat_prop arf_mat_type_from_rbsymbol(VALUE sym) { + ID sym_id = SYM2ID(sym); + + for(std::map::value_type& entry : MAT_PROPERTIES) { + if (sym_id == rb_intern(entry.first)) { + return static_cast(entry.second); + } + } + + VALUE str = rb_any_to_s(sym); + rb_raise(rb_eArgError, "invalid matrix type symbol (:%s) specified", RSTRING_PTR(str)); +} + +af_norm_type arf_norm_type_from_rbsymbol(VALUE sym) { + ID sym_id = SYM2ID(sym); + + for (size_t index = 0; index < ARF_NUM_NORM_TYPES; ++index) { + if (sym_id == rb_intern(NORM_TYPES[index])) { + return static_cast(index); + } + } + + VALUE str = rb_any_to_s(sym); + rb_raise(rb_eArgError, "invalid norm type symbol (:%s) specified", RSTRING_PTR(str)); +} + +af_moment_type arf_moment_type_from_rbsymbol(VALUE sym) { + ID sym_id = SYM2ID(sym); + + for(std::map::value_type& entry : MOMENT_TYPES) { + if (sym_id == rb_intern(entry.first)) { + return static_cast(entry.second); + } + } + + VALUE str = rb_any_to_s(sym); + rb_raise(rb_eArgError, "invalid moment type symbol (:%s) specified", RSTRING_PTR(str)); +} + +af_backend arf_backend_type_from_rbsymbol(VALUE sym) { + ID sym_id = SYM2ID(sym); + + for(std::map::value_type& entry : BACKEND_TYPES) { + if (sym_id == rb_intern(entry.first)) { + return static_cast(entry.second); + } + } + + VALUE str = rb_any_to_s(sym); + rb_raise(rb_eArgError, "invalid backend type symbol (:%s) specified", RSTRING_PTR(str)); +} + +af_random_engine_type arf_randome_engine_type_from_rbsymbol(VALUE sym) { + ID sym_id = SYM2ID(sym); + + for(std::map::value_type& entry : RANDOM_ENGINE_TYPES) { + if (sym_id == rb_intern(entry.first)) { + return static_cast(entry.second); + } + } + + VALUE str = rb_any_to_s(sym); + rb_raise(rb_eArgError, "invalid engine type symbol (:%s) specified", RSTRING_PTR(str)); +} + +af_storage arf_storage_type_from_rbsymbol(VALUE sym){ + ID sym_id = SYM2ID(sym); + + for (size_t index = 0; index < ARF_NUM_STORAGE_TYPES; ++index) { + if (sym_id == rb_intern(STORAGE_TYPES[index])) { + return static_cast(index); + } + } + + VALUE str = rb_any_to_s(sym); + rb_raise(rb_eArgError, "invalid storage type symbol (:%s) specified", RSTRING_PTR(str)); +} + +const char* get_backend_name(af_backend backend){ + for(std::map::value_type& entry : BACKEND_TYPES) { + if (backend == entry.second) { + return entry.first; + } + } + rb_raise(rb_eArgError, "Something went wrong!"); +} + +const char* get_random_engine_name(af_random_engine_type engine){ + for(std::map::value_type& entry : RANDOM_ENGINE_TYPES) { + if (engine == entry.second) { + return entry.first; + } + } + rb_raise(rb_eArgError, "Something went wrong!"); +} diff --git a/ext/mri/cmodules/device.c b/ext/mri/cmodules/device.c new file mode 100644 index 0000000..cad5699 --- /dev/null +++ b/ext/mri/cmodules/device.c @@ -0,0 +1,174 @@ +static VALUE arf_info(VALUE self){ + af_err flag = af_info(); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qtrue; +} + +static VALUE arf_init2(VALUE self){ + af_err flag = af_init(); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qtrue; +} + +static VALUE arf_info_string(VALUE self, VALUE bool_val){ + char* str; + af_err flag = af_info_string(&str, RTEST(bool_val)); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return rb_str_new_cstr(str); +} + +static VALUE arf_device_info(VALUE self, VALUE name_val, VALUE platform_val, VALUE toolkit_val, VALUE compute_val){ + char* d_name = ALLOC_N(char, sizeof(char) * 64); + char* d_platform = ALLOC_N(char, sizeof(char) * 10); + char* d_toolkit = ALLOC_N(char, sizeof(char) * 64); + char* d_compute = ALLOC_N(char, sizeof(char) * 10); + + af_err flag = af_device_info(d_name, d_platform, d_toolkit, d_compute); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + rb_str_cat2(name_val, d_name); + rb_str_cat2(platform_val, d_platform); + rb_str_cat2(toolkit_val, d_toolkit); + rb_str_cat2(compute_val, d_compute); + + return Qtrue; +} + +static VALUE arf_get_device_count(VALUE self){ + int num_of_devices; + af_err flag = af_get_device_count(&num_of_devices); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return INT2NUM(num_of_devices); +} + +static VALUE arf_get_dbl_support(VALUE self, VALUE device){ + bool available; + af_err flag = af_get_dbl_support(&available, NUM2INT(device)); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return available ? Qtrue : Qfalse; +} + +static VALUE arf_set_device(VALUE self, VALUE device){ + af_err flag = af_set_device(NUM2INT(device)); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qtrue; +} + +static VALUE arf_get_device(VALUE self){ + int device; + af_err flag = af_get_device(&device); + return INT2NUM(device); +} + +static VALUE arf_sync(VALUE self, VALUE device_val){ + af_err flag = af_sync(NUM2INT(device_val)); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qtrue; +} + +static VALUE arf_alloc_device(VALUE self){ + return Qnil; +} + +static VALUE arf_free_device(VALUE self){ + return Qnil; +} + +static VALUE arf_alloc_pinned(VALUE self){ + return Qnil; +} + +static VALUE arf_free_pinned(VALUE self){ + return Qnil; +} + +static VALUE arf_alloc_host(VALUE self){ + return Qnil; +} + +static VALUE arf_free_host(VALUE self){ + return Qnil; +} + +static VALUE arf_device_array(VALUE self){ + return Qnil; +} + +static VALUE arf_device_mem_info(VALUE self){ + size_t alloc_bytes, alloc_buffers, lock_bytes, lock_buffers; + af_err flag = af_device_mem_info( &alloc_bytes, &alloc_buffers, &lock_bytes, &lock_buffers); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + printf("Allocated Bytes: %d\nAllocated buffers: %d\nLock Bytes: %d\nLock Buffers: %d\n", + alloc_bytes, alloc_buffers, lock_bytes, lock_buffers); + return Qtrue; +} + +static VALUE arf_print_mem_info(VALUE self, VALUE msg_val, VALUE device_id_val){ + const char* msg = StringValuePtr(msg_val); + af_err flag = af_print_mem_info( msg, NUM2INT(device_id_val)); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qtrue; +} + +static void arf_device_gc(VALUE self){ + af_err flag = af_device_gc(); + if (flag != AF_SUCCESS) arf_handle_exception(flag); +} + +static VALUE arf_set_mem_step_size(VALUE self, VALUE step_bytes){ + af_err flag = af_set_mem_step_size(NUM2UINT(step_bytes)); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qtrue; +} + +static VALUE arf_get_mem_step_size(VALUE self){ + size_t step_bytes; + af_err flag = af_get_mem_step_size(&step_bytes); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return UINT2NUM(step_bytes); +} + +static VALUE arf_lock_device_ptr(VALUE self, VALUE array_val){ + afstruct* input; + Data_Get_Struct(array_val, afstruct, input); + af_err flag = af_lock_device_ptr(input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qtrue; +} + +static VALUE arf_unlock_device_ptr(VALUE self, VALUE array_val){ + afstruct* input; + Data_Get_Struct(array_val, afstruct, input); + af_err flag = af_unlock_device_ptr(input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qtrue; +} + +static VALUE arf_lock_array(VALUE self, VALUE array_val){ + afstruct* input; + Data_Get_Struct(array_val, afstruct, input); + af_err flag = af_lock_array(input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qtrue; +} + +static VALUE arf_unlock_array(VALUE self, VALUE array_val){ + afstruct* input; + Data_Get_Struct(array_val, afstruct, input); + af_err flag = af_unlock_array(input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qtrue; +} + +static VALUE arf_is_locked_array(VALUE self, VALUE array_val){ + bool res; + afstruct* input; + Data_Get_Struct(array_val, afstruct, input); + af_err flag = af_is_locked_array(&res, input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return res ? Qtrue : Qfalse; +} + +static VALUE arf_get_device_ptr(VALUE self){ + return Qnil; +} diff --git a/ext/mri/cmodules/index.c b/ext/mri/cmodules/index.c new file mode 100644 index 0000000..6c7896b --- /dev/null +++ b/ext/mri/cmodules/index.c @@ -0,0 +1,39 @@ +static VALUE arf_index(VALUE self){ + return Qnil; +} + +static VALUE arf_lookup(VALUE self){ + return Qnil; +} + +static VALUE arf_assign_seq(VALUE self){ + return Qnil; +} + +static VALUE arf_index_gen(VALUE self){ + return Qnil; +} + +static VALUE arf_assign_gen(VALUE self){ + return Qnil; +} + +static VALUE arf_create_indexers(VALUE self){ + return Qnil; +} + +static VALUE arf_set_array_indexer(VALUE self){ + return Qnil; +} + +static VALUE arf_set_seq_indexer(VALUE self){ + return Qnil; +} + +static VALUE arf_set_seq_param_indexer(VALUE self){ + return Qnil; +} + +static VALUE arf_release_indexers(VALUE self){ + return Qnil; +} diff --git a/ext/mri/cmodules/lapack.c b/ext/mri/cmodules/lapack.c new file mode 100644 index 0000000..55f100f --- /dev/null +++ b/ext/mri/cmodules/lapack.c @@ -0,0 +1,186 @@ +static VALUE arf_svd_func(VALUE self, VALUE u_val, VALUE s_val, VALUE vt_val, VALUE val){ + afstruct* input; + afstruct* u; + afstruct* s; + afstruct* vt; + + Data_Get_Struct(val, afstruct, input); + Data_Get_Struct(u_val, afstruct, u); + Data_Get_Struct(s_val, afstruct, s); + Data_Get_Struct(vt_val, afstruct, vt); + + af_err flag = af_svd(&u->carray, &s->carray, &vt->carray, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Qtrue; +} + +static VALUE arf_svd_inplace_func(VALUE self, VALUE val){ + afstruct* input; + afstruct* u = ALLOC(afstruct); + afstruct* s = ALLOC(afstruct); + afstruct* vt = ALLOC(afstruct); + + Data_Get_Struct(val, afstruct, input); + + af_err flag = af_svd_inplace(&u->carray, &s->carray, &vt->carray, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(CLASS_OF(val), NULL, arf_free, u); +} + +static VALUE arf_lu_func(VALUE self, VALUE lower_val, VALUE upper_val, VALUE pivot_val, VALUE val){ + afstruct* input; + afstruct* lower; + afstruct* upper; + afstruct* pivot; + + Data_Get_Struct(val, afstruct, input); + Data_Get_Struct(lower_val, afstruct, lower); + Data_Get_Struct(upper_val, afstruct, upper); + Data_Get_Struct(pivot_val, afstruct, pivot); + + af_lu(&lower->carray, &upper->carray, &pivot->carray, input->carray); + return Qtrue; +} + +static VALUE arf_lu_inplace_func(VALUE self){ + return Qnil; +} + +static VALUE arf_qr_func(VALUE self, VALUE q_val, VALUE r_val, VALUE tau_val, VALUE val){ + afstruct* input; + afstruct* q; + afstruct* r; + afstruct* tau; + + Data_Get_Struct(val, afstruct, input); + Data_Get_Struct(q_val, afstruct, q); + Data_Get_Struct(r_val, afstruct, r); + Data_Get_Struct(tau_val, afstruct, tau); + + af_err flag = af_qr(&q->carray, &r->carray, &tau->carray, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Qfalse; +} + +static VALUE arf_qr_inplace_func(VALUE self){ + return Qnil; +} + +static VALUE arf_cholesky_func(VALUE self, VALUE output_val, VALUE val, VALUE is_upper_val){ + afstruct* input; + afstruct* output; + int info; + + Data_Get_Struct(val, afstruct, input); + Data_Get_Struct(output_val, afstruct, output); + + af_err flag = af_cholesky(&output->carray, &info, input->carray, is_upper_val); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return INT2NUM(info); +} + +static VALUE arf_cholesky_inplace_func(VALUE self){ + return Qnil; +} + +static VALUE arf_solve(VALUE self, VALUE lhs_val, VALUE rhs_val){ + + afstruct* lhs; + afstruct* rhs; + afstruct* result = ALLOC(afstruct); + + Data_Get_Struct(lhs_val, afstruct, lhs); + Data_Get_Struct(rhs_val, afstruct, rhs); + + af_err flag = af_solve(&result->carray, lhs->carray, rhs->carray, AF_MAT_NONE); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(CLASS_OF(lhs_val), NULL, arf_free, result); +} + +static VALUE arf_solve_lu(VALUE self, VALUE lhs_val, VALUE rhs_val, VALUE piv_val){ + afstruct* lhs; + afstruct* rhs; + afstruct* piv; + afstruct* result = ALLOC(afstruct); + + Data_Get_Struct(lhs_val, afstruct, lhs); + Data_Get_Struct(rhs_val, afstruct, rhs); + Data_Get_Struct(piv_val, afstruct, piv); + + af_err flag = af_solve_lu(&result->carray, lhs->carray, piv->carray, rhs->carray, AF_MAT_NONE); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(CLASS_OF(lhs_val), NULL, arf_free, result); +} + +static VALUE arf_inverse(VALUE self, VALUE val){ + afstruct* matrix; + afstruct* result = ALLOC(afstruct); + + Data_Get_Struct(val, afstruct, matrix); + + af_err flag = af_inverse(&result->carray, matrix->carray, AF_MAT_NONE); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(CLASS_OF(val), NULL, arf_free, result); +} + +static VALUE arf_rank(VALUE self, VALUE val){ + afstruct* matrix; + uint rank; + + Data_Get_Struct(val, afstruct, matrix); + + af_err flag = af_rank(&rank, matrix->carray, 0.001); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return UINT2NUM(rank); +} + +static VALUE arf_det(VALUE self, VALUE val){ + afstruct* matrix; + double det_real, det_imag; + + Data_Get_Struct(val, afstruct, matrix); + + af_err flag = af_det(&det_real, &det_imag, matrix->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return DBL2NUM(det_real); +} + +static VALUE arf_norm(VALUE self, VALUE val){ + afstruct* matrix; + double norm; + double p = 0; + double q = 0; + Data_Get_Struct(val, afstruct, matrix); + af_err flag = af_norm(&norm, matrix->carray, AF_NORM_EUCLID, p, q); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return DBL2NUM(norm); +} + +static VALUE arf_is_lapack_available(VALUE self){ + bool output; + af_err flag = af_is_lapack_available(&output); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return output ? Qtrue : Qfalse; +} diff --git a/ext/mri/cmodules/opencl.c b/ext/mri/cmodules/opencl.c new file mode 100644 index 0000000..6b3e103 --- /dev/null +++ b/ext/mri/cmodules/opencl.c @@ -0,0 +1,83 @@ +std::map AFCL_DEVICE_TYPES = { + {"AFCL_DEVICE_TYPE_CPU", 0}, + {"CL_DEVICE_TYPE_CPU", 1}, + {"AFCL_DEVICE_TYPE_GPU", 2}, + {"CL_DEVICE_TYPE_GPU", 3}, + {"AFCL_DEVICE_TYPE_ACC", 4}, + {"CL_DEVICE_TYPE_ACCELERATOR", 5}, + {"AFCL_DEVICE_TYPE_UNKNOWN", -1} +}; + +std::map AFCL_PLATFORM_TYPES = { + {"AFCL_PLATFORM_AMD", 0}, + {"AFCL_PLATFORM_APPLE", 1}, + {"AFCL_PLATFORM_INTEL", 2}, + {"AFCL_PLATFORM_NVIDIA", 3}, + {"AFCL_PLATFORM_BEIGNET", 4}, + {"AFCL_PLATFORM_POCL", 5}, + {"AFCL_PLATFORM_UNKNOWN", -1} +}; + + +static VALUE arf_get_context(VALUE self){ + return Qnil; +} + +static VALUE arf_get_queue(VALUE self){ + return Qnil; +} + +static VALUE arf_get_device_id(VALUE self){ + cl_device_id id; + af_err flag = afcl_get_device_id(&id); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return Qnil; +} + +static VALUE arf_set_device_id(VALUE self){ + return Qnil; +} + +static VALUE arf_add_device_context(VALUE self){ + return Qnil; +} + +static VALUE arf_set_device_context(VALUE self){ + return Qnil; +} + +static VALUE arf_delete_device_context(VALUE self){ + return Qnil; +} + +static VALUE arf_get_device_type(VALUE self){ + afcl_device_type device; + af_err flag = afcl_get_device_type(&device); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return rb_str_new_cstr(get_cl_device_name(device)); +} + +static VALUE arf_get_platform(VALUE self){ + afcl_platform platform; + af_err flag = afcl_get_platform(&platform); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + return rb_str_new_cstr(get_cl_platform_name(platform)); +} + +const char* get_cl_device_name(afcl_device_type device){ + for(std::map::value_type& entry : AFCL_DEVICE_TYPES) { + if (device == entry.second) { + return entry.first; + } + } + rb_raise(rb_eArgError, "Couldn't detect device!"); +} + +const char* get_cl_platform_name(afcl_platform platform){ + for(std::map::value_type& entry : AFCL_PLATFORM_TYPES) { + if (platform == entry.second) { + return entry.first; + } + } + rb_raise(rb_eArgError, "Couldn't detect platform!"); +} diff --git a/ext/mri/cmodules/random.c b/ext/mri/cmodules/random.c new file mode 100644 index 0000000..033a7e8 --- /dev/null +++ b/ext/mri/cmodules/random.c @@ -0,0 +1,203 @@ +static VALUE arf_create_random_engine(VALUE self, VALUE type_val, VALUE seed_val){ + afrandomenginestruct* output = ALLOC(afrandomenginestruct); + af_random_engine_type rtype = arf_randome_engine_type_from_rbsymbol(type_val); + + af_err flag = af_create_random_engine(&output->cengine, AF_RANDOM_ENGINE_DEFAULT, NUM2ULL(seed_val) ) ; + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Random, NULL, arf_engine_free, output); +} + +static VALUE arf_retain_random_engine(VALUE self, VALUE engine_val){ + afrandomenginestruct* output = ALLOC(afrandomenginestruct); + afrandomenginestruct* engine; + + Data_Get_Struct(engine_val, afrandomenginestruct, engine); + + af_err flag = af_retain_random_engine ( &output->cengine, engine->cengine); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Random, NULL, arf_engine_free, output); +} + +static VALUE arf_random_engine_set_type(VALUE self, VALUE engine_val, VALUE type_val){ + af_random_engine_type rtype = arf_randome_engine_type_from_rbsymbol(type_val); + afrandomenginestruct* engine; + + Data_Get_Struct(engine_val, afrandomenginestruct, engine); + + af_err flag = af_random_engine_set_type(&engine->cengine, rtype); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Qtrue; +} + +static VALUE arf_random_engine_get_type(VALUE self, VALUE engine_val){ + af_random_engine_type rtype; + afrandomenginestruct* engine; + + Data_Get_Struct(engine_val, afrandomenginestruct, engine); + + af_err flag = af_random_engine_get_type(&rtype, engine->cengine); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + const char* rengine = get_random_engine_name(rtype); + return rb_str_new_cstr(rengine); +} + +static VALUE arf_random_uniform(VALUE self, VALUE ndims_val, VALUE dim_val, VALUE engine_val){ + afstruct* out_array = ALLOC(afstruct); + afrandomenginestruct* engine; + + Data_Get_Struct(engine_val, afrandomenginestruct, engine); + + dim_t ndims = (dim_t)FIX2LONG(ndims_val); + dim_t* dimensions = ALLOC_N(dim_t, ndims); + dim_t count = 1; + for (dim_t index = 0; index < ndims; index++) { + dimensions[index] = (dim_t)FIX2LONG(RARRAY_AREF(dim_val, index)); + count *= dimensions[index]; + } + + af_err flag = af_random_uniform(&out_array->carray, ndims, dimensions, f32, engine->cengine); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, out_array); +} + +static VALUE arf_random_normal(VALUE self, VALUE ndims_val, VALUE dim_val, VALUE engine_val){ + afstruct* out_array = ALLOC(afstruct); + afrandomenginestruct* engine; + + Data_Get_Struct(engine_val, afrandomenginestruct, engine); + + dim_t ndims = (dim_t)FIX2LONG(ndims_val); + dim_t* dimensions = ALLOC_N(dim_t, ndims); + dim_t count = 1; + for (dim_t index = 0; index < ndims; index++) { + dimensions[index] = (dim_t)FIX2LONG(RARRAY_AREF(dim_val, index)); + count *= dimensions[index]; + } + + af_err flag = af_random_uniform(&out_array->carray, ndims, dimensions, f32, engine->cengine); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, out_array); +} + +static VALUE arf_random_engine_set_seed(VALUE self, VALUE engine_val ,VALUE seed_val){ + afrandomenginestruct* engine; + + Data_Get_Struct(engine_val, afrandomenginestruct, engine); + + af_err flag = af_random_engine_set_seed (&engine->cengine, NUM2ULL(seed_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Random, NULL, arf_engine_free, engine); +} + +static VALUE arf_get_default_random_engine(VALUE self){ + afrandomenginestruct* output = ALLOC(afrandomenginestruct); + + af_err flag = af_get_default_random_engine(&output->cengine) ; + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Random, NULL, arf_engine_free, output); +} + +static VALUE arf_set_default_random_engine_type(VALUE self, VALUE type_val){ + af_random_engine_type rtype = arf_randome_engine_type_from_rbsymbol(type_val); + + af_err flag = af_set_default_random_engine_type(rtype); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Qtrue; +} + +static VALUE arf_random_engine_get_seed(VALUE self, VALUE engine_val){ + afrandomenginestruct* engine; + uintl seed; + + Data_Get_Struct(engine_val, afrandomenginestruct, engine); + + af_err flag = af_random_engine_get_seed(&seed, engine->cengine); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return ULL2NUM(seed); +} + +static VALUE arf_release_random_engine(VALUE self, VALUE engine_val){ + afrandomenginestruct* engine; + + Data_Get_Struct(engine_val, afrandomenginestruct, engine); + + af_err flag = af_release_random_engine(engine); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Qtrue; +} + +static VALUE arf_randu(VALUE self, VALUE ndims_val, VALUE dim_val){ + afstruct* out_array = ALLOC(afstruct); + + dim_t ndims = (dim_t)FIX2LONG(ndims_val); + dim_t* dimensions = ALLOC_N(dim_t, ndims); + dim_t count = 1; + for (dim_t index = 0; index < ndims; index++) { + dimensions[index] = (dim_t)FIX2LONG(RARRAY_AREF(dim_val, index)); + count *= dimensions[index]; + } + + af_err flag = af_randu(&out_array->carray, ndims, dimensions,f32); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, out_array); +} + +static VALUE arf_randn(VALUE self, VALUE ndims_val, VALUE dim_val){ + afstruct* out_array = ALLOC(afstruct); + + dim_t ndims = (dim_t)FIX2LONG(ndims_val); + dim_t* dimensions = ALLOC_N(dim_t, ndims); + dim_t count = 1; + for (dim_t index = 0; index < ndims; index++) { + dimensions[index] = (dim_t)FIX2LONG(RARRAY_AREF(dim_val, index)); + count *= dimensions[index]; + } + + af_err flag = af_randn(&out_array->carray, ndims, dimensions,f32); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, out_array); +} + +static VALUE arf_set_seed(VALUE self, VALUE seed){ + af_err flag = af_set_seed(NUM2ULL(seed)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Qtrue; +} + +static VALUE arf_get_seed(VALUE self){ + uintl seed; + + af_err flag = af_get_seed(&seed); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return ULL2NUM(seed); +} diff --git a/ext/mri/cmodules/sparse.c b/ext/mri/cmodules/sparse.c new file mode 100644 index 0000000..fcb80ea --- /dev/null +++ b/ext/mri/cmodules/sparse.c @@ -0,0 +1,154 @@ +static VALUE arf_create_sparse_array(VALUE self, VALUE shape_array, VALUE values_array, VALUE rowIdx_val, VALUE colIdx_val, VALUE stype_val){ + afstruct* output = ALLOC(afstruct); + afstruct* values; + afstruct* rowIdx; + afstruct* colIdx; + + Data_Get_Struct(values_array, afstruct, values); + Data_Get_Struct(rowIdx_val, afstruct, rowIdx); + Data_Get_Struct(colIdx_val, afstruct, colIdx); + + af_storage stype = arf_storage_type_from_rbsymbol(stype_val); + + dim_t nRows = (dim_t)FIX2LONG(RARRAY_AREF(shape_array, 0)); + dim_t nCols = (dim_t)FIX2LONG(RARRAY_AREF(shape_array, 1)); + + af_err flag = af_create_sparse_array(&output->carray, nRows, nCols, values->carray, rowIdx->carray, colIdx->carray, stype); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_create_sparse_array_from_ptr(VALUE self){ + return Qnil; +} + +static VALUE arf_create_sparse_array_from_dense(VALUE self, VALUE dense_val, VALUE stype_val){ + afstruct* output = ALLOC(afstruct); + afstruct* dense; + + Data_Get_Struct(dense_val, afstruct, dense); + + af_storage stype = arf_storage_type_from_rbsymbol(stype_val); + + af_err flag = af_create_sparse_array_from_dense(&output->carray, dense->carray, stype); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_sparse_convert_to(VALUE self, VALUE input_val, VALUE dest_storage_val){ + afstruct* output = ALLOC(afstruct); + afstruct* input; + + Data_Get_Struct(input_val, afstruct, input); + + af_storage dest_storage = arf_storage_type_from_rbsymbol(dest_storage_val); + + af_err flag = af_sparse_convert_to(&output->carray, input->carray, dest_storage); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_sparse_to_dense(VALUE self, VALUE sparse_array){ + afstruct* dense = ALLOC(afstruct); + afstruct* sparse; + + Data_Get_Struct(sparse_array, afstruct, sparse); + + af_err flag = af_sparse_to_dense(&dense->carray, sparse->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, dense); +} + +static VALUE arf_sparse_get_info_func(VALUE self, VALUE values_val, VALUE rowIdx_val, VALUE colIdx_val, VALUE input_val){ + afstruct* input; + afstruct* values; + afstruct* rowIdx; + afstruct* colIdx; + af_storage stype; + + Data_Get_Struct(input_val, afstruct, input); + Data_Get_Struct(values_val, afstruct, values); + Data_Get_Struct(rowIdx_val, afstruct, rowIdx); + Data_Get_Struct(colIdx_val, afstruct, colIdx); + + af_err flag = af_sparse_get_info( &values->carray, &rowIdx->carray, &colIdx->carray, &stype, input->carray ); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return rb_str_new_cstr(STORAGE_TYPES[stype]); +} + +static VALUE arf_sparse_get_values(VALUE self, VALUE input_val){ + afstruct* output = ALLOC(afstruct); + afstruct* input; + + Data_Get_Struct(input_val, afstruct, input); + + af_err flag = af_sparse_get_values(&output->carray, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_sparse_get_row_idx(VALUE self, VALUE input_val){ + afstruct* output = ALLOC(afstruct); + afstruct* input; + + Data_Get_Struct(input_val, afstruct, input); + + af_err flag = af_sparse_get_row_idx(&output->carray, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_sparse_get_col_idx(VALUE self, VALUE input_val){ + afstruct* output = ALLOC(afstruct); + afstruct* input; + + Data_Get_Struct(input_val, afstruct, input); + + af_err flag = af_sparse_get_col_idx(&output->carray, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_sparse_get_nnz(VALUE self, VALUE input_val){ + dim_t out; + afstruct* input; + + Data_Get_Struct(input_val, afstruct, input); + + af_err flag = af_sparse_get_nnz( &out, input); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return ULL2NUM(out); +} + +static VALUE arf_sparse_get_storage(VALUE self, VALUE input_val){ + afstruct* input; + Data_Get_Struct(input_val, afstruct, input); + + af_storage storage; + + af_err flag = af_sparse_get_storage(&storage , input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return rb_str_new_cstr(STORAGE_TYPES[storage]); +} diff --git a/ext/mri/cmodules/statistics.c b/ext/mri/cmodules/statistics.c new file mode 100644 index 0000000..937c3d0 --- /dev/null +++ b/ext/mri/cmodules/statistics.c @@ -0,0 +1,200 @@ +static VALUE arf_mean(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_mean(&output->carray, input->carray, NUM2UINT(dim_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_mean_weighted(VALUE self, VALUE array_val, VALUE weighted_array_val, VALUE dim_val){ + afstruct* input; + afstruct* weighted_array; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + Data_Get_Struct(weighted_array_val, afstruct, weighted_array); + + af_err flag = af_mean_weighted(&output->carray, input->carray, weighted_array->carray, NUM2UINT(dim_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_var(VALUE self, VALUE array_val, VALUE is_biased, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_var(&output->carray, input->carray, RTEST(is_biased), NUM2UINT(dim_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_var_weighted(VALUE self, VALUE array_val, VALUE weighted_array_val, VALUE dim_val){ + afstruct* input; + afstruct* weighted_array; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + Data_Get_Struct(weighted_array_val, afstruct, weighted_array); + + af_err flag = af_var_weighted(&output->carray, input->carray, weighted_array->carray, NUM2UINT(dim_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_stdev(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_stdev(&output->carray, input->carray, NUM2UINT(dim_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_cov(VALUE self, VALUE first_array_val, VALUE second_array_val, VALUE is_biased){ + afstruct* output = ALLOC(afstruct); + + afstruct* first_array; + afstruct* second_array; + + Data_Get_Struct(first_array_val, afstruct, first_array); + Data_Get_Struct(second_array_val, afstruct, second_array); + + af_err flag = af_cov(&output->carray, first_array->carray, second_array->carray, RTEST(is_biased)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_median(VALUE self, VALUE array_val, VALUE dim_val){ + afstruct* input; + afstruct* output = ALLOC(afstruct); + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_median(&output->carray, input->carray, NUM2UINT(dim_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + af_print_array(output->carray); + + return Data_Wrap_Struct(Af_Array, NULL, arf_free, output); +} + +static VALUE arf_mean_all(VALUE self, VALUE array_val){ + afstruct* input; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_mean_all(&real_part, &imag_part, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return DBL2NUM(real_part); +} + +static VALUE arf_mean_all_weighted(VALUE self, VALUE array_val, VALUE weighted_array_val){ + afstruct* input; + afstruct* weighted_array; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + Data_Get_Struct(weighted_array_val, afstruct, weighted_array); + + af_err flag = af_mean_all_weighted(&real_part, &imag_part, input->carray, weighted_array->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return DBL2NUM(real_part); +} + +static VALUE arf_var_all(VALUE self, VALUE array_val, VALUE is_biased){ + afstruct* input; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_var_all(&real_part, &imag_part, input->carray, RTEST(is_biased)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return DBL2NUM(real_part); +} + +static VALUE arf_var_all_weighted(VALUE self, VALUE array_val, VALUE weighted_array_val){ + afstruct* input; + afstruct* weighted_array; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + Data_Get_Struct(weighted_array_val, afstruct, weighted_array); + + af_err flag = af_var_all_weighted(&real_part, &imag_part, input->carray, weighted_array->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return DBL2NUM(real_part); +} + +static VALUE arf_stdev_all(VALUE self, VALUE array_val){ + afstruct* input; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_stdev_all(&real_part, &imag_part, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return DBL2NUM(real_part); +} + +static VALUE arf_median_all(VALUE self, VALUE array_val){ + afstruct* input; + double real_part, imag_part; + + Data_Get_Struct(array_val, afstruct, input); + + af_err flag = af_median_all(&real_part, &imag_part, input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return DBL2NUM(real_part); +} + +static VALUE arf_corrcoef(VALUE self, VALUE first_array_val, VALUE second_array_val){ + afstruct* first_array; + afstruct* second_array; + double real_part, imag_part; + + Data_Get_Struct(first_array_val, afstruct, first_array); + Data_Get_Struct(first_array_val, afstruct, second_array); + + af_err flag = af_corrcoef(&real_part, &imag_part, first_array->carray, second_array->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return DBL2NUM(real_part); +} diff --git a/ext/mri/cmodules/util.c b/ext/mri/cmodules/util.c new file mode 100644 index 0000000..5e4743d --- /dev/null +++ b/ext/mri/cmodules/util.c @@ -0,0 +1,90 @@ +static VALUE arf_print_array(VALUE self, VALUE input_val){ + afstruct* input; + + Data_Get_Struct(input_val, afstruct, input); + + af_err flag = af_print_array(input->carray); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return Qtrue; +} + +static VALUE arf_print_array_gen(VALUE self){ + return Qnil; +} + +static VALUE arf_save_array(VALUE self, VALUE key_val, VALUE array_val, VALUE fn_val, VALUE append){ + afstruct* input; + + Data_Get_Struct(array_val, afstruct, input); + const char* key = StringValueCStr(key_val); + const char* filename = StringValueCStr(fn_val); + int index; + + af_err flag = af_save_array (&index, key, input->carray, filename, RTEST(append)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return INT2NUM(index); +} + +static VALUE arf_read_array_index(VALUE self){ + return Qnil; +} + +static VALUE arf_read_array_key(VALUE self){ + return Qnil; +} + +static VALUE arf_read_array_key_check(VALUE self){ + return Qnil; +} + +static VALUE arf_array_to_string(VALUE self, VALUE exp_val, VALUE array_val, VALUE precision, VALUE transpose){ + char* output; + afstruct* input; + + Data_Get_Struct(array_val, afstruct, input); + const char* exp = StringValueCStr(exp_val); + + af_err flag = af_array_to_string(&output, exp, input->carray, NUM2INT(precision), RTEST(transpose)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return rb_str_new_cstr(output); +} + +static VALUE arf_example_function(VALUE self){ + return Qnil; +} + +static VALUE arf_get_version(VALUE self){ + int major, minor, patch; + + af_err flag = af_get_version(&major, &minor, &patch); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + VALUE hash = rb_hash_new(); + rb_hash_aset(hash, rb_str_new_cstr("major"), INT2NUM(major)); + rb_hash_aset(hash, rb_str_new_cstr("minor"), INT2NUM(minor)); + rb_hash_aset(hash, rb_str_new_cstr("patch"), INT2NUM(patch)); + + return hash; +} + +static VALUE arf_get_revision(VALUE self){ + const char* revision = af_get_revision(); + return rb_str_new_cstr(revision); +} + +static VALUE arf_get_size_of(VALUE self, VALUE dtype_val){ + size_t size; + + af_err flag = af_get_size_of(&size, arf_dtype_from_rbsymbol(dtype_val)); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return ULL2NUM(size); +} diff --git a/ext/mri/extconf.rb b/ext/mri/extconf.rb index 5f2937b..ff26e5c 100644 --- a/ext/mri/extconf.rb +++ b/ext/mri/extconf.rb @@ -2,7 +2,9 @@ extension_name = 'arrayfire' -dir_config(extension_name) +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_arrayfire.h' , '$(archdir)'], @@ -15,19 +17,36 @@ $CXXFLAGS = ["-Wall -Werror=return-type",$CXXFLAGS].join(" ") $CPPFLAGS = ["-Wall -Werror=return-type",$CPPFLAGS].join(" ") -dir_config('arrayfire', '/usr/local/include/', '/usr/local/lib/') -# $LOCAL_LIBS = LIBDIR = RbConfig::CONFIG['libdir'] INCLUDEDIR = RbConfig::CONFIG['includedir'] -HEADER_DIRS = [INCLUDEDIR, '/usr/local/include/', '/usr/local/include/af/'] +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('afcuda') +have_library('af') have_library('cusolver') have_library('cudart') have_library('cufft') have_library('cublas') +have_library('nmatrix') +have_header("nmatrix_config.h") +abort "Cannot locate NMatrix header files : nmatrix.h" unless find_header("nmatrix.h") basenames = %w{ruby_arrayfire} $objs = basenames.map { |b| "#{b}.o" } diff --git a/ext/mri/interfaces/nmatrix.c b/ext/mri/interfaces/nmatrix.c new file mode 100644 index 0000000..0b016dd --- /dev/null +++ b/ext/mri/interfaces/nmatrix.c @@ -0,0 +1,66 @@ +static VALUE arf_af_array_to_nmatrix(VALUE self) { + afstruct* input; + Data_Get_Struct(self, afstruct, input); + dim_t count; + uint ndims; + + af_err flag = af_get_numdims(&ndims, input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + dim_t* dims = ALLOC_N(dim_t, ndims); + + flag = af_get_dims(&dims[0], &dims[1], &dims[2], &dims[3], input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + size_t* shape = ALLOC_N(size_t, ndims); + for (dim_t index = 0; index < ndims; index++){ + shape[index] = (size_t)(dims[index]); + } + + flag = af_get_elements(&count, input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + double* elements = ALLOC_N(double, count); + + flag = af_get_data_ptr(elements, input->carray); + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return rb_nmatrix_dense_create(nm::FLOAT64, shape, ndims, elements, (int)count); +} + +extern VALUE arf_nmatrix_to_af_array_method(VALUE nmatrix) { + if (NM_DIM(nmatrix) > 4) { + rb_raise(rb_eStandardError, + "NMatrix must not have greater than 4 dimensions."); + } + + if (NM_DTYPE(nmatrix) == nm::FLOAT64) { + return Data_Wrap_Struct(Af_Array, NULL, arf_free, arf_nmatrix_to_af_array(nmatrix)); + } + else { + rb_raise(rb_eStandardError, + "NMatrix should be either :complex64, :complex128, :int32 or :float64 type."); + } + return Qnil; +} + + +afstruct* arf_nmatrix_to_af_array(VALUE nm) { + DENSE_STORAGE* nmat = NM_STORAGE_DENSE(nm); + afstruct* output = ALLOC(afstruct); + + if (nmat->dtype != nm::FLOAT64) { + rb_raise(rb_eStandardError, "requires dtype of :float64 to convert to an Af_Array"); + } + + dim_t* shape = ALLOC_N(dim_t, nmat->dim); + for (size_t index = 0; index < nmat->dim; index++){ + shape[index] = (size_t)(nmat->shape[index]); + } + + af_err flag = af_create_array(&output->carray, nmat->elements, nmat->dim, shape, f64); + + if (flag != AF_SUCCESS) arf_handle_exception(flag); + + return output; +} diff --git a/ext/mri/ruby_arrayfire.cpp b/ext/mri/ruby_arrayfire.cpp index a94666c..4b16065 100644 --- a/ext/mri/ruby_arrayfire.cpp +++ b/ext/mri/ruby_arrayfire.cpp @@ -2,8 +2,14 @@ #include // std::min #include #include +#include +#include #include #include +#include +#include "nmatrix.h" + + /* * Project Includes */ @@ -13,40 +19,7 @@ namespace arf { - // #include - using namespace af; -// create a small wrapper to benchmark - static array A; // populated before each timing - static void fn() - { - array B = matmul(A, A); // matrix multiply - B.eval(); // ensure evaluated - } - static void matmul_benchmark() - { - double peak = 0; - try { - int device = 0; - setDevice(device); - info(); - printf("Benchmark N-by-N matrix multiply\n"); - for (int n = 128; n <= 2048; n += 128) { - printf("%4d x %4d: ", n, n); - A = constant(1,n,n); - double time = timeit(fn); // time in seconds - double gflops = 2.0 * powf(n,3) / (time * 1e9); - if (gflops > peak) - peak = gflops; - printf(" %4.0f Gflops\n", gflops); - fflush(stdout); - } - } catch (af::exception& e) { - fprintf(stderr, "%s\n", e.what()); - throw; - } - printf(" ### peak %g GFLOPS\n", peak); - } } extern "C" { #include "arrayfire.c" -} \ No newline at end of file +} diff --git a/ext/mri/ruby_arrayfire.h b/ext/mri/ruby_arrayfire.h index 42b9e69..dc51ed5 100644 --- a/ext/mri/ruby_arrayfire.h +++ b/ext/mri/ruby_arrayfire.h @@ -2,6 +2,38 @@ #define RUBY_ARRAYFIRE_H #endif +typedef struct AF_STRUCT +{ + af_array carray; +}afstruct; + +typedef struct RANDOM_ENGINE_STRUCT +{ + af_random_engine cengine; +}afrandomenginestruct; + +#define ARF_NUM_DTYPES 12 +#define ARF_NUM_NORM_TYPES 9 +#define ARF_NUM_SOURCES 2 +#define ARF_NUM_STORAGE_TYPES 4 + +#ifndef HAVE_RB_ARRAY_CONST_PTR +static inline const VALUE * +rb_array_const_ptr(VALUE a) +{ + return FIX_CONST_VALUE_PTR((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ? + RARRAY(a)->as.ary : RARRAY(a)->as.heap.ptr); +} +#endif + +#ifndef RARRAY_CONST_PTR +# define RARRAY_CONST_PTR(a) rb_array_const_ptr(a) +#endif + +#ifndef RARRAY_AREF +# define RARRAY_AREF(a, i) (RARRAY_CONST_PTR(a)[i]) +#endif + /* * Functions */ @@ -9,20 +41,18 @@ #ifdef __cplusplus typedef VALUE (*METHOD)(...); //}; // end of namespace nm + +// Interfaces + #endif -#include -// #include + #ifdef __cplusplus extern "C" { #endif void Init_arrayfire(); - static void matmul_benchmark(); - // External API - #ifdef __cplusplus } #endif - diff --git a/lib/arrayfire/arrayfire.rb b/lib/arrayfire/arrayfire.rb index 967d23a..5e220d6 100644 --- a/lib/arrayfire/arrayfire.rb +++ b/lib/arrayfire/arrayfire.rb @@ -1 +1,4 @@ require_relative '../arrayfire.so' +require_relative 'lapack.rb' +require_relative 'device.rb' +require_relative 'sparse.rb' diff --git a/lib/arrayfire/device.rb b/lib/arrayfire/device.rb new file mode 100644 index 0000000..d2fea0c --- /dev/null +++ b/lib/arrayfire/device.rb @@ -0,0 +1,12 @@ +module ArrayFire + class Device + def self.device_info + d_name = "" + d_platform = "" + d_toolkit = "" + d_compute = "" + ArrayFire::Device.device_info_func(d_name, d_platform, d_toolkit, d_compute); + return d_name, d_platform, d_toolkit, d_compute + end + end +end diff --git a/lib/arrayfire/lapack.rb b/lib/arrayfire/lapack.rb new file mode 100644 index 0000000..f1ad88a --- /dev/null +++ b/lib/arrayfire/lapack.rb @@ -0,0 +1,36 @@ +module ArrayFire + class LAPACK + + def self.svd(af_array) + u = ArrayFire::Af_Array.new + s = ArrayFire::Af_Array.new + vt = ArrayFire::Af_Array.new + ArrayFire::LAPACK.svd_func(u, s, vt, af_array) + return u, s, vt + end + + def self.lu(af_array) + lower = ArrayFire::Af_Array.new + upper = ArrayFire::Af_Array.new + pivot = ArrayFire::Af_Array.new + ArrayFire::LAPACK.lu_func(lower, upper, pivot, af_array) + return lower, upper, pivot + end + + def self.qr(af_array) + q = ArrayFire::Af_Array.new + r = ArrayFire::Af_Array.new + tau = ArrayFire::Af_Array.new + ArrayFire::LAPACK.qr_func(q, r, tau, af_array) + return q, r, tau + end + + def self.cholesky(af_array, is_upper=true) + out = ArrayFire::Af_Array.new + info = ArrayFire::LAPACK.cholesky_func(out, af_array, is_upper) + return out, info + end + + end +end + diff --git a/lib/arrayfire/sparse.rb b/lib/arrayfire/sparse.rb new file mode 100644 index 0000000..439fe34 --- /dev/null +++ b/lib/arrayfire/sparse.rb @@ -0,0 +1,13 @@ +module ArrayFire + class Sparse + + def self.sparse_get_info(af_array) + values = ArrayFire::Af_Array.new + rowIdx = ArrayFire::Af_Array.new + colIdx = ArrayFire::Af_Array.new + stype = ArrayFire::Sparse.sparse_get_info_func(values, rowIdx, colIdx, af_array) + return values, rowIdx, colIdx, stype + end + + end +end diff --git a/lib/arrayfire/version.rb b/lib/arrayfire/version.rb new file mode 100644 index 0000000..3a6457a --- /dev/null +++ b/lib/arrayfire/version.rb @@ -0,0 +1,3 @@ +module ArrayFire + VERSION = '3.5.0' +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb deleted file mode 100644 index 273228a..0000000 --- a/spec/spec_helper.rb +++ /dev/null @@ -1 +0,0 @@ -require './lib/arrayfire' diff --git a/test/algorithm_test.rb b/test/algorithm_test.rb new file mode 100644 index 0000000..64d54a1 --- /dev/null +++ b/test/algorithm_test.rb @@ -0,0 +1,98 @@ +require 'test_helper' + +class ArrayFire::AlgorithmTest < Minitest::Test + + def setup + @input = ArrayFire::Af_Array.new 2, [3,3], [4, 1, 5, 6, -11, 9 , -22, 11, 1] + @input2 = ArrayFire::Af_Array.new 2, [3,3], [4, 1, 5, 6, -11, 9 , -22, 11, 0] + @inf_array = @input / @input2 + @nan_array = @inf_array / @inf_array + end + + def test_sum + sum_arr = ArrayFire::Af_Array.new 1, [3], [-12.0, 1.0, 15.0] + result = ArrayFire::Algorithm.sum(@input, 1) + assert_equal(sum_arr, result) + end + + def test_sum_nan + sum_nan_arr = ArrayFire::Af_Array.new 1, [3], [3.0, 3.0, 8.0] + result = ArrayFire::Algorithm.sum_nan(@nan_array, 1, 6) + assert_equal(sum_nan_arr, result) + end + + def test_product + product_arr = ArrayFire::Af_Array.new 1, [3], [-528.0, -121.0, 45.0] + result = ArrayFire::Algorithm.product(@input, 1) + assert_equal(product_arr, result) + end + + def test_product_nan + product_nan_arr = ArrayFire::Af_Array.new 1, [3], [1.0, 1.0, 6.0] + result = ArrayFire::Algorithm.product_nan(@nan_array, 1, 6) + assert_equal(product_nan_arr, result) + end + + def test_min + min_arr = ArrayFire::Af_Array.new 1, [3], [-22.0, -11.0, 1] + result = ArrayFire::Algorithm.min(@input, 1) + assert_equal(min_arr, result) + end + + def test_max + max_arr = ArrayFire::Af_Array.new 1, [3], [6.0, 11.0, 9.0] + result = ArrayFire::Algorithm.max(@input, 1) + assert_equal(max_arr, result) + end + + def test_all_true + all_true_arr = ArrayFire::Af_Array.new 1, [3], [1.0, 1.0, 1.0] + result = ArrayFire::Algorithm.all_true(@input, 1) + assert_equal(all_true_arr, result) + end + + def test_any_true + any_true_arr = ArrayFire::Af_Array.new 1, [3], [1.0, 1.0, 1.0] + result = ArrayFire::Algorithm.any_true(@input, 1) + assert_equal(any_true_arr, result) + end + + def test_count + count_arr = ArrayFire::Af_Array.new 1, [3], [3.0, 3.0, 3.0] + result = ArrayFire::Algorithm.count(@input, 1) + assert_equal(count_arr, result) + end + + def test_sum_all + assert_equal 4, ArrayFire::Algorithm.sum_all(@input) + end + + def test_sum_nan_all + assert_equal 18, ArrayFire::Algorithm.sum_nan_all(@nan_array, 10) + end + + def test_product_all + assert_equal 2874960.0, ArrayFire::Algorithm.product_all(@input) + end + + def test_product_nan_all + assert_equal 10, ArrayFire::Algorithm.product_nan_all(@nan_array, 10) + end + + def test_min_all + assert_equal -22, ArrayFire::Algorithm.min_all(@input) + end + + def test_max_all + assert_equal 11, ArrayFire::Algorithm.max_all(@input) + end + + def test_all_true_all + assert_equal 1, ArrayFire::Algorithm.all_true_all(@input) + end + + def test_any_true_all + assert_equal 1, ArrayFire::Algorithm.any_true_all(@input) + end + +end diff --git a/test/arith_test.rb b/test/arith_test.rb new file mode 100644 index 0000000..e511262 --- /dev/null +++ b/test/arith_test.rb @@ -0,0 +1,49 @@ +require 'test_helper' + +class ArrayFire::ArithTest < Minitest::Test + + def setup + @a = ArrayFire::Af_Array.new 2, [2,2],[1,2,3,4] + @b = ArrayFire::Af_Array.new 2, [2,2],[2,4,6,8] + @elements = [10, -11, 48, 21, 65, 0, 1, -7, 112] + @elements_h = [1, -1, 0, 1, 1, 0.4, -0.7, 1, 0.9] + @af_array = ArrayFire::Af_Array.new 2, [3,3], @elements + @af_array_h = ArrayFire::Af_Array.new 2, [3,3], @elements_h + end + + def test_addition + c = ArrayFire::Af_Array.new 2, [2,2],[3,6,9,12] + assert_equal c, @a + @b + end + + def test_subtraction + assert_equal @a, @b - @a + end + + def test_multiplication + c = ArrayFire::Af_Array.new 2, [2,2],[2,8,18,32] + assert_equal c, @b * @a + end + + def test_division + c = ArrayFire::Af_Array.new 2, [2,2],[2,2,2,2] + assert_equal c, @b / @a + end + + [:sin, :cos, :tan].each do |method| + define_method("test_#{method}") do + x = @elements.map{ |e| Math.send(method, e) } + res_arr = ArrayFire::Af_Array.new 2, [3,3], x + assert res_arr.approx_equal @af_array.send method + end + end + + [:sinh, :cosh, :tanh].each do |method| + define_method("test_#{method}") do + x = @elements_h.map{ |e| Math.send(method, e) } + res_arr = ArrayFire::Af_Array.new 2, [3,3], x + assert res_arr.approx_equal @af_array_h.send method + end + end + +end diff --git a/test/blas_test.rb b/test/blas_test.rb new file mode 100644 index 0000000..dfa7b91 --- /dev/null +++ b/test/blas_test.rb @@ -0,0 +1,27 @@ +require 'test_helper' + +class ArrayFire::BLASTest < Minitest::Test + + def setup + @matrix_left = ArrayFire::Af_Array.new 2, [2,2],[ 12, 21,-61, 48] + @matrix_right = ArrayFire::Af_Array.new 2, [2,2],[-15, 41, 30 , 7 ] + @vector_left = ArrayFire::Af_Array.new 2, [4,1],[-15, 41, 30 , 7 ] + @vector_right = ArrayFire::Af_Array.new 2, [4,1],[ 25, 141, 17 , 7 ] + end + + def test_matmul + result = ArrayFire::Af_Array.new 2, [2,2],[-2681.0, 1653.0, -67.0, 966.0] + assert_equal result, ArrayFire::BLAS.matmul(@matrix_left, @matrix_right, :AF_MAT_NONE, :AF_MAT_NONE) + end + + def test_dot + result = ArrayFire::Af_Array.new 1,[1],[5965.0] + assert_equal result, ArrayFire::BLAS.dot(@vector_left, @vector_right, :AF_MAT_NONE, :AF_MAT_NONE) + end + + def test_transpose + result = ArrayFire::Af_Array.new 2, [2,2], [12.0, -61.0, 21.0, 48.0] + assert_equal result, ArrayFire::BLAS.transpose(@matrix_left) + end + +end diff --git a/test/creation_test.rb b/test/creation_test.rb new file mode 100644 index 0000000..4162c2e --- /dev/null +++ b/test/creation_test.rb @@ -0,0 +1,21 @@ +require 'test_helper' + +class ArrayFire::Af_ArrayTest < Minitest::Test + + def setup + @i = ArrayFire::Af_Array.new 2, [2,2],[1,2,3,4] + end + + def test_ndims + assert_equal 2, @i.ndims + end + + def test_dims + assert_equal [2,2], @i.dims + end + + def test_elements + assert_equal [1, 2, 3, 4], @i.elements + end + +end diff --git a/test/data_test.rb b/test/data_test.rb new file mode 100644 index 0000000..cce8270 --- /dev/null +++ b/test/data_test.rb @@ -0,0 +1,145 @@ +require 'test_helper' + +class ArrayFire::DataTest < Minitest::Test + + def setup + @first = ArrayFire::Af_Array.new 2, [3,3], [4, 1, 5, 6, -11, 9 , -22, 11, 1] + @second = ArrayFire::Af_Array.new 2, [3,3], [-14, 27, 15, 6, -11, 9 , 22, 0, 61] + @diagonal = ArrayFire::Af_Array.new 1, [4,1], [1, 2, 3, 4] + @order_array = ArrayFire::Af_Array.new 2, [3,3], [1, 2, 3, 4, 5, 6 , 7, 8 , 9] + end + + def test_constant + result = ArrayFire::Af_Array.new 2, [3,3], [4, 4, 4, 4, 4, 4, 4, 4, 4] + assert_equal result, ArrayFire::Data.constant( 2, [3,3], 4 ); + end + + def test_constant_complex + # ArrayFire::Data.constant_complex + end + + def test_constant_long + result = ArrayFire::Af_Array.new 2, [3,3], [4, 4, 4, 4, 4, 4, 4, 4, 4] + assert_equal result, ArrayFire::Data.constant_long( 2, [3,3],4 ) + end + + def test_constant_ulong + result = ArrayFire::Af_Array.new 2, [3,3], [4, 4, 4, 4, 4, 4, 4, 4, 4] + assert_equal result, ArrayFire::Data.constant_ulong( 2, [3,3], 4 ) + end + + def test_range + result = ArrayFire::Af_Array.new 2, [4,4], [0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0] + assert_equal result, ArrayFire::Data.range( 2, [4,4], 1 ) + end + + def test_iota + # ArrayFire::Data.iota + end + + def test_identity + result = ArrayFire::Af_Array.new 2, [4,5], [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0] + assert_equal result, ArrayFire::Data.identity( 2, [4,5] ) + end + + def test_diag_create + result = ArrayFire::Af_Array.new 2, [4,4], [1.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 4.0] + assert_equal result, ArrayFire::Data.diag_create( @diagonal, 0 ) + end + + def test_diag_extract + diag_matrix = ArrayFire::Data.diag_create @diagonal, 0 + assert_equal @diagonal, ArrayFire::Data.diag_extract( diag_matrix, 0 ) + end + + def test_join + result = ArrayFire::Af_Array.new 2, [3, 6], [4.0, 1.0, 5.0, 6.0, -11.0, 9.0, -22.0, 11.0, 1.0, + -14.0, 27.0, 15.0, 6.0, -11.0, 9.0, 22.0,0.0, 61.0] + + assert_equal result, ArrayFire::Data.join(1, @first, @second) + end + + def test_join_many + # result = ArrayFire::Af_Array.new 2, [3, 6], [4.0, 1.0, 5.0, 6.0, -11.0, 9.0, -22.0, 11.0, 1.0, + # -14.0, 27.0, 15.0, 6.0, -11.0, 9.0, 22.0,0.0, 61.0] + + # assert_equal result, ArrayFire::Data.join_many(1, @first, @second) + end + + def test_tile + result = ArrayFire::Af_Array.new 2, [6,9], [1.0,2.0,3.0,1.0,2.0,3.0,4.0,5.0,6.0, + 4.0,5.0,6.0,7.0,8.0,9.0,7.0,8.0,9.0, + 1.0,2.0,3.0,1.0,2.0,3.0,4.0,5.0,6.0, + 4.0,5.0,6.0,7.0,8.0,9.0,7.0,8.0,9.0, + 1.0,2.0,3.0,1.0,2.0,3.0,4.0,5.0,6.0, + 4.0,5.0,6.0,7.0,8.0,9.0,7.0,8.0,9.0] + + assert_equal result.elements, ArrayFire::Data.tile( @order_array, 2, 3, 1, 1 ).elements + end + + def test_reorder + result = ArrayFire:: Af_Array.new 2, [3,3], [1.0, 4.0, 7.0, 2.0, 5.0, 8.0, 3.0, 6.0, 9.0] + assert_equal result, ArrayFire::Data.reorder( @order_array, 1, 0, 2, 3 ) + end + + def test_shift + first_shift = ArrayFire::Af_Array.new 2, [3,3], [3.0, 1.0, 2.0, 6.0, 4.0, 5.0, 9.0, 7.0, 8.0] + second_shift = ArrayFire::Af_Array.new 2, [3,3], [6.0, 4.0, 5.0, 9.0, 7.0, 8.0, 3.0, 1.0, 2.0] + assert_equal first_shift, ArrayFire::Data.shift( @order_array, 1, 0, 0, 0 ) + assert_equal second_shift, ArrayFire::Data.shift( @order_array, 1, 2, 0, 0 ) + end + + def test_moddims + # result = ArrayFire::Af_Array.new 2, [9,1], [4, 1, 5, 6, -11, 9 , -22, 11, 1] + # assert_equal result, ArrayFire::Data.moddims( @input, 2, [9,1] ) + end + + def test_flat + result = ArrayFire::Af_Array.new 1, [9], [4.0, 1.0, 5.0, 6.0, -11.0, 9.0, -22.0, 11.0, 1.0] + assert_equal result, ArrayFire::Data.flat(@first) + end + + def test_flip + result = ArrayFire::Af_Array.new 2, [3,3], [-22.0, 11.0, 1.0, 6.0, -11.0, 9.0, 4.0, 1.0, 5.0] + assert_equal result, ArrayFire::Data.flip(@first, 1) + end + + def test_lower + result = ArrayFire::Af_Array.new 2, [3,3], [4.0, 1.0, 5.0, 0.0, -11.0, 9.0, 0.0, 0.0, 1.0] + assert_equal result, ArrayFire::Data.lower(@first, false) + + #unit_diagonal + result = ArrayFire::Af_Array.new 2, [3,3], [1.0, 1.0, 5.0, 0.0, 1.0, 9.0, 0.0, 0.0, 1.0] + assert_equal result, ArrayFire::Data.lower(@first, true) + end + + def test_upper + result = ArrayFire::Af_Array.new 2, [3,3], [4.0, 0.0, 0.0, 6.0, -11.0, 0.0, -22.0, 11.0, 1.0] + assert_equal result, ArrayFire::Data.upper(@first, false) + + #unit_diagonal + result = ArrayFire::Af_Array.new 2, [3,3], [1.0, 0.0, 0.0, 6.0, 1.0, 0.0, -22.0, 11.0, 1.0] + assert_equal result, ArrayFire::Data.upper(@first, true) + end + + def test_select + # ArrayFire::Data.select + end + + def test_select_scalar_r + # ArrayFire::Data.select_scalar_r + end + + def test_select_scalar_l + # ArrayFire::Data.select_scalar_l + end + + def test_replace + # ArrayFire::Data.replace + end + + def test_replace_scalar + # ArrayFire::Data.replace_scalar + end + +end diff --git a/test/lapack_test.rb b/test/lapack_test.rb new file mode 100644 index 0000000..42c0e05 --- /dev/null +++ b/test/lapack_test.rb @@ -0,0 +1,86 @@ +require 'test_helper' + +class ArrayFire::LAPACKTest < Minitest::Test + + def setup + @array = ArrayFire::Af_Array.new 2, [2,2],[ 12, 21,-61, 48 ] + end + + def test_svd + matrix = ArrayFire::Af_Array.new 2, [4,2], [1,3,5,7,2,4,6,8] + u = ArrayFire::Af_Array.new 2, [4,4], [-0.1524, -0.3499, -0.5473, -0.7447, -0.8226, -0.4213, -0.0201, 0.3811, -0.3945, 0.2427, 0.6979, -0.5462, -0.3799, 0.8006, -0.4614, 0.0407] + s = ArrayFire::Af_Array.new 2, [2,1], [14.269095420837402, 0.6268] + v = ArrayFire::Af_Array.new 2, [2,2], [-0.6414, 0.7671, -0.7671, -0.6414] + svd_fac = ArrayFire::LAPACK.svd(matrix); + assert(u.approx_equal svd_fac[0]) + assert(s.approx_equal svd_fac[1]) + assert(v.approx_equal svd_fac[2]) + end + + def test_lu + matrix = ArrayFire::Af_Array.new 2, [3,3], [1,4,7,2,5,8,3,6,0] + l = ArrayFire::Af_Array.new 2, [3,3], [1.0, 0.1428, 0.5714, 0.0, 1.0, 0.4999, 0.0, 0.0, 1.0] + u = ArrayFire::Af_Array.new 2, [3,3], [7.0, 0.0, 0.0, 8.0, 0.8571, 0.0, 0.0, 3.0, 4.5000] + p = ArrayFire::Af_Array.new 2, [3,1], [0, 0, 0] + lu_fac = ArrayFire::LAPACK.lu(matrix); + assert(l.approx_equal lu_fac[0]) + assert(u.approx_equal lu_fac[1]) + assert(p.approx_equal lu_fac[2]) + end + + def test_qr + matrix = ArrayFire::Af_Array.new 2, [3,3], [12.0, -51.0, 4.0, 6.0, 167.0, -68.0, -4.0, 24.0, -41.0] + q = ArrayFire::Af_Array.new 2, [3,3], [-0.2283, 0.9705, -0.0761, -0.6189, -0.0843, 0.7809, 0.7515, 0.2254, 0.6199] + r = ArrayFire::Af_Array.new 2, [3,3], [-52.5452, 0.0, 0.0, 165.8952, -70.9068, 0.0, 27.3288, -31.5664, -23.015] + p = ArrayFire::Af_Array.new 2, [3,1], [1.2283, 1.5734, 0.0] + qr_fac = ArrayFire::LAPACK.qr matrix + assert(q.approx_equal qr_fac[0]) + assert(r.approx_equal qr_fac[1]) + assert(p.approx_equal qr_fac[2]) + end + + def test_cholesky + mat_upper = ArrayFire::Af_Array.new 2, [3,3], [1,0,0, 1,2,0, 1,2,6] + res_upper = ArrayFire::Af_Array.new 2, [3,3], [1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 2.0] + upper = ArrayFire::LAPACK.cholesky(mat_upper)[0] + assert_equal upper, res_upper + + mat_lower = ArrayFire::Af_Array.new 2, [3,3], [1,1,1, 0,2,2, 0,0,6] + res_lower = ArrayFire::Af_Array.new 2, [3,3], [1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 2.0] + lower = ArrayFire::LAPACK.cholesky(mat_lower, false)[0] + assert_equal lower, res_lower + end + + def test_solve + lhs = ArrayFire::Af_Array.new 2, [2,2], [3,1,1,2] + rhs = ArrayFire::Af_Array.new 2, [2,1], [9,8] + solution = ArrayFire::Af_Array.new 2, [2,1], [2,3] + assert_equal solution, ArrayFire::LAPACK.solve(lhs, rhs) + end + + def test_solve_lu + # TODO + end + + def test_inverse + result = ArrayFire::Af_Array.new 2, [2,2], [0.0258, -0.0113, 0.0328, 0.0064] + assert(result.approx_equal ArrayFire::LAPACK.inverse(@array)); + end + + def test_rank + assert_equal ArrayFire::LAPACK.rank(@array), 2; + end + + def test_det + assert_equal ArrayFire::LAPACK.det(@array), 1857.0; + end + + def test_norm + assert((ArrayFire::LAPACK.norm(@array) - 81.3019).abs < 0.001); + end + + def test_is_lapack_available + assert(ArrayFire::LAPACK.is_lapack_available); + end + +end diff --git a/test/statistics_test.rb b/test/statistics_test.rb new file mode 100644 index 0000000..42a8733 --- /dev/null +++ b/test/statistics_test.rb @@ -0,0 +1,72 @@ +require 'test_helper' + +class ArrayFire::StatisticsTest < Minitest::Test + + def setup + @array = ArrayFire::Af_Array.new 2, [3,3], [4, 3, 5, 6, -11, 9 , -22, 11, 1] + @weighted_array = ArrayFire::Af_Array.new 2, [3,3], [1, 2, 2, 0, -2, 2 , 1, 3, 1] + end + + def test_mean + result = ArrayFire::Af_Array.new 2, [3,1], [-4, 1, 5] + assert_equal result, ArrayFire::Statistics.mean(@array, 1) + end + + def test_mean_weighted + result = ArrayFire::Af_Array.new 2, [3,1], [-9.0, 20.333, 5.8] + assert result.approx_equal ArrayFire::Statistics.mean_weighted(@array, @weighted_array, 1) + end + + def test_var + result = ArrayFire::Af_Array.new 2, [3,1], [162.6667, 82.6667, 10.6667] + assert result.approx_equal ArrayFire::Statistics.var(@array, true, 1) + result = ArrayFire::Af_Array.new 2, [3,1], [244.0, 124.0, 16.0] + assert result.approx_equal ArrayFire::Statistics.var(@array, false, 1) + end + + def test_var_weighted + result = ArrayFire::Af_Array.new 2, [3,1], [169.0, -367.111, 8.960] + assert result.approx_equal ArrayFire::Statistics.var_weighted(@array, @weighted_array, 1) + end + + def test_stdev + result = ArrayFire::Af_Array.new 2, [3,1], [12.7540, 9.0921, 3.2659] + assert result.approx_equal ArrayFire::Statistics.stdev(@array, 1) + end + + def test_median + result = ArrayFire::Af_Array.new 2, [3,1], [4, 3, 5] + assert_equal result, ArrayFire::Statistics.median(@array, 1) + end + + def test_mean_all + assert_in_delta 0.667, ArrayFire::Statistics.mean_all(@array) + end + + def mean_all_weighted + assert_in_delta 7.20, ArrayFire::Statistics.mean_all_weighted(@array, @weighted_array) + end + + def test_var_all + assert_in_delta 98.8888, ArrayFire::Statistics.var_all(@array, true) + assert_in_delta 111.250, ArrayFire::Statistics.var_all(@array, false) + end + + def var_all_weighted + assert_in_delta 33.360, ArrayFire::Statistics.var_all_weighted(@array, @weighted_array) + end + + def stdev_all_weighted + assert_in_delta 9.9442, ArrayFire::Statistics.stdev_all(@array) + end + + def test_median_all + assert 4.0, ArrayFire::Statistics.median_all(@array) + end + + def test_corrcoef + array_second = ArrayFire::Af_Array.new 2, [3,3], [42, 1, -15, 52, -121, 9 , -22, 1, 7] + assert_equal 1.0, ArrayFire::Statistics.corrcoef(@array, array_second) + end + +end \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..8eae370 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,4 @@ +$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) +require 'arrayfire' + +require 'minitest/autorun'