gumath 0.2.0dev5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +61 -0
  3. data/Gemfile +5 -0
  4. data/History.md +0 -0
  5. data/README.md +5 -0
  6. data/Rakefile +105 -0
  7. data/ext/ruby_gumath/examples.c +126 -0
  8. data/ext/ruby_gumath/extconf.rb +97 -0
  9. data/ext/ruby_gumath/functions.c +106 -0
  10. data/ext/ruby_gumath/gufunc_object.c +79 -0
  11. data/ext/ruby_gumath/gufunc_object.h +55 -0
  12. data/ext/ruby_gumath/gumath/AUTHORS.txt +5 -0
  13. data/ext/ruby_gumath/gumath/INSTALL.txt +42 -0
  14. data/ext/ruby_gumath/gumath/LICENSE.txt +29 -0
  15. data/ext/ruby_gumath/gumath/MANIFEST.in +3 -0
  16. data/ext/ruby_gumath/gumath/Makefile.in +62 -0
  17. data/ext/ruby_gumath/gumath/README.rst +20 -0
  18. data/ext/ruby_gumath/gumath/config.guess +1530 -0
  19. data/ext/ruby_gumath/gumath/config.h.in +52 -0
  20. data/ext/ruby_gumath/gumath/config.sub +1782 -0
  21. data/ext/ruby_gumath/gumath/configure +5049 -0
  22. data/ext/ruby_gumath/gumath/configure.ac +167 -0
  23. data/ext/ruby_gumath/gumath/doc/_static/copybutton.js +66 -0
  24. data/ext/ruby_gumath/gumath/doc/conf.py +26 -0
  25. data/ext/ruby_gumath/gumath/doc/gumath/functions.rst +62 -0
  26. data/ext/ruby_gumath/gumath/doc/gumath/index.rst +26 -0
  27. data/ext/ruby_gumath/gumath/doc/index.rst +45 -0
  28. data/ext/ruby_gumath/gumath/doc/libgumath/data-structures.rst +130 -0
  29. data/ext/ruby_gumath/gumath/doc/libgumath/functions.rst +78 -0
  30. data/ext/ruby_gumath/gumath/doc/libgumath/index.rst +25 -0
  31. data/ext/ruby_gumath/gumath/doc/libgumath/kernels.rst +41 -0
  32. data/ext/ruby_gumath/gumath/doc/releases/index.rst +11 -0
  33. data/ext/ruby_gumath/gumath/install-sh +527 -0
  34. data/ext/ruby_gumath/gumath/libgumath/Makefile.in +170 -0
  35. data/ext/ruby_gumath/gumath/libgumath/Makefile.vc +160 -0
  36. data/ext/ruby_gumath/gumath/libgumath/apply.c +201 -0
  37. data/ext/ruby_gumath/gumath/libgumath/extending/bfloat16.c +130 -0
  38. data/ext/ruby_gumath/gumath/libgumath/extending/examples.c +176 -0
  39. data/ext/ruby_gumath/gumath/libgumath/extending/graph.c +393 -0
  40. data/ext/ruby_gumath/gumath/libgumath/extending/pdist.c +140 -0
  41. data/ext/ruby_gumath/gumath/libgumath/extending/quaternion.c +156 -0
  42. data/ext/ruby_gumath/gumath/libgumath/func.c +177 -0
  43. data/ext/ruby_gumath/gumath/libgumath/gumath.h +205 -0
  44. data/ext/ruby_gumath/gumath/libgumath/kernels/binary.c +547 -0
  45. data/ext/ruby_gumath/gumath/libgumath/kernels/unary.c +449 -0
  46. data/ext/ruby_gumath/gumath/libgumath/nploops.c +219 -0
  47. data/ext/ruby_gumath/gumath/libgumath/tbl.c +223 -0
  48. data/ext/ruby_gumath/gumath/libgumath/thread.c +175 -0
  49. data/ext/ruby_gumath/gumath/libgumath/xndloops.c +130 -0
  50. data/ext/ruby_gumath/gumath/python/extending.py +24 -0
  51. data/ext/ruby_gumath/gumath/python/gumath/__init__.py +74 -0
  52. data/ext/ruby_gumath/gumath/python/gumath/_gumath.c +577 -0
  53. data/ext/ruby_gumath/gumath/python/gumath/examples.c +93 -0
  54. data/ext/ruby_gumath/gumath/python/gumath/functions.c +77 -0
  55. data/ext/ruby_gumath/gumath/python/gumath/pygumath.h +95 -0
  56. data/ext/ruby_gumath/gumath/python/test_gumath.py +405 -0
  57. data/ext/ruby_gumath/gumath/setup.py +298 -0
  58. data/ext/ruby_gumath/gumath/vcbuild/INSTALL.txt +36 -0
  59. data/ext/ruby_gumath/gumath/vcbuild/vcbuild32.bat +21 -0
  60. data/ext/ruby_gumath/gumath/vcbuild/vcbuild64.bat +21 -0
  61. data/ext/ruby_gumath/gumath/vcbuild/vcclean.bat +10 -0
  62. data/ext/ruby_gumath/gumath/vcbuild/vcdistclean.bat +11 -0
  63. data/ext/ruby_gumath/include/gumath.h +205 -0
  64. data/ext/ruby_gumath/include/ruby_gumath.h +41 -0
  65. data/ext/ruby_gumath/lib/libgumath.a +0 -0
  66. data/ext/ruby_gumath/lib/libgumath.so +1 -0
  67. data/ext/ruby_gumath/lib/libgumath.so.0 +1 -0
  68. data/ext/ruby_gumath/lib/libgumath.so.0.2.0dev3 +0 -0
  69. data/ext/ruby_gumath/ruby_gumath.c +295 -0
  70. data/ext/ruby_gumath/ruby_gumath.h +41 -0
  71. data/ext/ruby_gumath/ruby_gumath_internal.h +45 -0
  72. data/ext/ruby_gumath/util.c +68 -0
  73. data/ext/ruby_gumath/util.h +48 -0
  74. data/gumath.gemspec +47 -0
  75. data/lib/gumath.rb +7 -0
  76. data/lib/gumath/version.rb +5 -0
  77. data/lib/ruby_gumath.so +0 -0
  78. metadata +206 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8a56c97c8de3fc82fc684c10a6a9910963c69214
4
+ data.tar.gz: f7e8e3053c3ff0d74c7b33dbd1e9668a892ffc70
5
+ SHA512:
6
+ metadata.gz: a33696aa82d1facedba27585e45b907cf287ba58407cd2856e127ded4e24529879f0cbf70b3ac1b931f661bbb7066fc1b461fede74b7b4602a463422c3c1ca1c
7
+ data.tar.gz: 21f198e731872448efde3548493c0bdd9c2f8e696aeca57786f130f812946da32c0f374e88bdaf17289d3691f5d7fa6c7c8a172bd0da2cb87b6ad5f9c85f23c3
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,61 @@
1
+ # Details
2
+
3
+ ## Functioning of libgumath
4
+
5
+ Gumath is a wrapper over libgumath. The docs for libgumath can be found [here](https://xnd.readthedocs.io/en/latest/libgumath/index.html).
6
+
7
+ It allows users to write [multiple dispatch](https://en.wikipedia.org/wiki/Multiple_dispatch) functions for XND containers.
8
+ Multiple dispatch can be thought of as the concept behind function overloading in
9
+ languages like C++. However the major difference is that the function call is made
10
+ according to the run time types of the arguments in case of multiple dispatch whereas
11
+ in overloading it is determined at compile-time and the types of arguments determine
12
+ the 'signature' of the function. [This answer](https://cs.stackexchange.com/questions/4660/difference-between-multimethods-and-overloading) sheds some light on the differences
13
+ between the two. Here's [another link](http://wiki.c2.com/?MultiMethods) on the same topic.
14
+
15
+ This functionality is absent in Ruby because in Ruby we don't care about the type of
16
+ the arguments of a function when calling it (aka duck typing).
17
+
18
+ Gumath functions (or 'kernels') are functions that can accept XND objects of multiple
19
+ data types and compute the result depending on what kind of data type is sent in. The
20
+ data type is known only at run time (like determining whether a container is of type
21
+ float32 or int etc.) and the same function can handle all sorts of data types.
22
+
23
+ Libgumath stores functions in a look-up table. Each Ruby module containing functions
24
+ should have its own look-up table. A prototype of adding gumath kernels to a Ruby module
25
+ `Gumath::Functions` can be found in the functions.c file in this repo.
26
+
27
+ An XND kernel has the following function signature:
28
+ ```
29
+ typedef int (* gm_xnd_kernel_t)(xnd_t stack[], ndt_context_t *ctx);
30
+ ```
31
+
32
+ ## Interfacing libgumath with Ruby
33
+
34
+ Unlike in Python, Ruby functions are not first-class objects and therefore we cannot create
35
+ a 'callable' object like we can in Python. Since libgumath kernels are run-time constructs
36
+ it is difficult to dynamically add these functions to a Ruby module at runtime since unlike
37
+ Ruby, C cannot generate new functions at run-time.
38
+
39
+ However, Ruby does have support for lambdas and we can store the function implementations
40
+ inside lambdas. These lambdas are stored in module variables that are of the same name
41
+ as the function name that they implement. When the user calls the lambda with the `call` method
42
+ or `.` syntax, the lambda will be passed the argument (after some conversion) and will
43
+ return the result given by the gumath kernel.
44
+
45
+ Another approach is to have a Hash of methods and their corresponding implementations
46
+ stored inside each module. Whenever a method is called on the module, it will routed to
47
+ the method_missing in the class, which will lookup the hash and call the appropriate
48
+ lambda. This seems like the better approach since the user no longer needs to know that
49
+ the functions that they're calling inside the module are in fact lambdas.
50
+
51
+ So each module that contains gumath methods should have a hash called `gumath_functions`
52
+ that stores function names as keys (as symbols) and the corresponding values as objects
53
+ of type `GufuncObject`. This `GufuncObject` will have a method `call` defined on it that
54
+ will be called by the `method_missing` when that object is called. The only extra overhead
55
+ will be that of a Hash lookup (O(1) time) and calling an Ruby method `call`.
56
+
57
+ ## Calling gumath kernels
58
+
59
+ Gumath kernels can be called by using the `gm_apply` function and passing a pointer to
60
+ the function along with its arguments. Its multi-threaded counterpart, `gm_apply_thread`
61
+ can also be used for this purpose.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ gem 'ndtypes', path: "/home/sameer/gitrepos/plures-ruby/ndtypes"
5
+ gem 'xnd', path: "/home/sameer/gitrepos/plures-ruby/xnd"
data/History.md ADDED
File without changes
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # Introduction
2
+
3
+ gumath is a library for computational kernels that target XND containers.
4
+
5
+
data/Rakefile ADDED
@@ -0,0 +1,105 @@
1
+ require 'rake'
2
+ require 'rake/extensiontask'
3
+ require 'rake/testtask'
4
+ require 'bundler/gem_tasks'
5
+ require 'fileutils'
6
+ require 'gumath/version.rb'
7
+
8
+ gemspec = eval(IO.read('gumath.gemspec'))
9
+
10
+ ext_name = "ruby_gumath"
11
+ Rake::ExtensionTask.new(ext_name, gemspec) do |ext|
12
+ ext.ext_dir = "ext/#{ext_name}"
13
+ ext.source_pattern = "**/*.{c,h}"
14
+ end
15
+
16
+ def run *cmd
17
+ sh(cmd.join(" "))
18
+ end
19
+
20
+ task :console do
21
+ cmd = ['irb', "-r './lib/gumath.rb'"]
22
+ run(*cmd)
23
+ end
24
+
25
+ task :pry do
26
+ cmd = ['pry', "-r './lib/gumath.rb'"]
27
+ run(*cmd)
28
+ end
29
+
30
+ Rake::TestTask.new(:test) do |t|
31
+ t.libs << "test"
32
+ t.libs << "lib"
33
+ t.test_files = FileList['test/**/test_*.rb']
34
+ end
35
+
36
+ BASEDIR = Pathname( __FILE__ ).dirname.relative_path_from( Pathname.pwd )
37
+ TESTDIR = BASEDIR + 'test'
38
+
39
+ VALGRIND_OPTIONS = [
40
+ "--tool=memcheck",
41
+ #"--leak-check=yes",
42
+ "--num-callers=15",
43
+ #"--error-limit=no",
44
+ "--partial-loads-ok=yes",
45
+ "--undef-value-errors=no" #,
46
+ #"--dsymutil=yes"
47
+ ]
48
+
49
+ VALGRIND_MEMORYFILL_OPTIONS = [
50
+ "--freelist-vol=100000000",
51
+ "--malloc-fill=6D",
52
+ "--free-fill=66 ",
53
+ ]
54
+
55
+ # partial-loads-ok and undef-value-errors necessary to ignore
56
+ # spurious (and eminently ignorable) warnings from the ruby
57
+ # interpreter
58
+
59
+ desc "Run specs under Valgrind."
60
+ task :valgrind => [ :compile ] do |task|
61
+ cmd = [ 'valgrind' ] + VALGRIND_OPTIONS
62
+ cmd += [" rake test "]
63
+ run( *cmd )
64
+ end
65
+
66
+ LEAKCHECK_CMD = [ 'ruby', '-Ilib:ext', "#{TESTDIR}/leakcheck.rb" ]
67
+
68
+ desc "Run leakcheck script."
69
+ task :leakcheck => [ :compile ] do |task|
70
+ cmd = [ 'valgrind' ] + VALGRIND_OPTIONS
71
+ cmd += LEAKCHECK_CMD
72
+ run( *cmd )
73
+ end
74
+
75
+ task :clobber do |task|
76
+ [
77
+ "ext/#{ext_name}/include",
78
+ "ext/#{ext_name}/share",
79
+ "ext/#{ext_name}/lib",
80
+ ].each do |f|
81
+ puts "deleting folder #{f}..."
82
+ FileUtils.rm_rf(f)
83
+ end
84
+
85
+ Dir.chdir("ext/#{ext_name}/gumath/libgumath/") do
86
+ system("make clean")
87
+ end
88
+ end
89
+
90
+ task :develop do
91
+ ext_gumath = "ext/ruby_gumath/gumath"
92
+ puts "deleting previously created #{ext_gumath} directory..."
93
+ FileUtils.rm_rf(ext_gumath)
94
+ Dir.mkdir(ext_gumath)
95
+
96
+ puts "cloning gumath repo into ext/ folder..."
97
+ system("git clone https://github.com/plures/gumath #{ext_gumath}")
98
+
99
+ Dir.chdir(ext_gumath) do
100
+ system("git checkout #{Gumath::COMMIT}")
101
+ end
102
+
103
+ puts "building gem with rake build..."
104
+ system("rake build")
105
+ end
@@ -0,0 +1,126 @@
1
+ /* BSD 3-Clause License
2
+ *
3
+ * Copyright (c) 2018, Quansight and Sameer Deshmukh
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright notice, this
10
+ * list of conditions and the following disclaimer.
11
+ *
12
+ * * Redistributions in binary form must reproduce the above copyright notice,
13
+ * this list of conditions and the following disclaimer in the documentation
14
+ * and/or other materials provided with the distribution.
15
+ *
16
+ * * Neither the name of the copyright holder nor the names of its
17
+ * contributors may be used to endorse or promote products derived from
18
+ * this software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ */
31
+ #include <ruby.h>
32
+ #include "ndtypes.h"
33
+ #include "ruby_ndtypes.h"
34
+ #include "gumath.h"
35
+ #include "gufunc_object.h"
36
+ #include "ruby_gumath.h"
37
+ #include "util.h"
38
+
39
+ /****************************************************************************/
40
+ /* Static globals */
41
+ /****************************************************************************/
42
+
43
+ /* Function table */
44
+ static gm_tbl_t *table = NULL;
45
+ static VALUE mGumath_Examples;
46
+ static int initialized = 0;
47
+
48
+ /****************************************************************************/
49
+ /* Singleton methods */
50
+ /****************************************************************************/
51
+ static VALUE
52
+ mGumath_Examples_s_method_missing(int argc, VALUE *argv, VALUE module)
53
+ {
54
+ VALUE method_name = argv[0];
55
+ VALUE method_hash = rb_ivar_get(module, GUMATH_FUNCTION_HASH);
56
+ VALUE gumath_method = rb_hash_aref(method_hash, method_name);
57
+ int is_present = RTEST(gumath_method);
58
+
59
+ if (is_present) {
60
+ rb_funcall2(gumath_method, rb_intern("call"), argc-1, &argv[1]);
61
+ }
62
+ else {
63
+ VALUE str = rb_funcall(method_name, rb_intern("to_s"), 0, NULL);
64
+ rb_raise(rb_eNoMethodError, "Method %s not present in this gumath module.",
65
+ StringValueCStr(str));
66
+ }
67
+ }
68
+
69
+ void
70
+ Init_gumath_examples(void)
71
+ {
72
+ NDT_STATIC_CONTEXT(ctx);
73
+
74
+ if (!initialized) {
75
+ if (!ndt_exists()) {
76
+ rb_raise(rb_eLoadError, "NDT is needed for making gumath work.");
77
+ }
78
+
79
+ if (!xnd_exists()) {
80
+ rb_raise(rb_eLoadError, "XND is needed for making gumath work.");
81
+ }
82
+
83
+ table = gm_tbl_new(&ctx);
84
+ if (table == NULL) {
85
+ seterr(&ctx);
86
+ raise_error();
87
+ }
88
+
89
+ /* load custom examples */
90
+ if (gm_init_example_kernels(table, &ctx) < 0) {
91
+ seterr(&ctx);
92
+ raise_error();
93
+ }
94
+
95
+ /* extending examples */
96
+ if (gm_init_graph_kernels(table, &ctx) < 0) {
97
+ seterr(&ctx);
98
+ raise_error();
99
+ }
100
+
101
+ #ifndef _MSC_VER
102
+ if (gm_init_quaternion_kernels(table, &ctx) < 0) {
103
+ seterr(&ctx);
104
+ raise_error();
105
+ }
106
+ #endif
107
+ if (gm_init_pdist_kernels(table, &ctx) < 0) {
108
+ seterr(&ctx);
109
+ raise_error();
110
+ }
111
+
112
+ initialized = 1;
113
+ }
114
+
115
+ mGumath_Examples = rb_define_module_under(cGumath, "Examples");
116
+ rb_ivar_set(mGumath_Examples, GUMATH_FUNCTION_HASH, rb_hash_new());
117
+
118
+ if (rb_gumath_add_functions(mGumath_Examples, table) < 0) {
119
+ mGumath_Examples = Qundef;
120
+ rb_raise(rb_eLoadError, "failed to load functions into Gumath::Examples module.");
121
+ }
122
+
123
+ /* Singleton methods */
124
+ rb_define_singleton_method(mGumath_Examples, "method_missing",
125
+ mGumath_Examples_s_method_missing, -1);
126
+ }
@@ -0,0 +1,97 @@
1
+ require 'mkmf'
2
+
3
+ def windows?
4
+ (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
5
+ end
6
+
7
+ def mac?
8
+ (/darwin/ =~ RUBY_PLATFORM) != nil
9
+ end
10
+
11
+ def unix?
12
+ !windows?
13
+ end
14
+
15
+ # ndtypes config
16
+
17
+ ndtypes_version = ">= 0.2.0dev5"
18
+ ndtypes_spec = Gem::Specification.find_by_name("ndtypes", ndtypes_version)
19
+ ndtypes_extdir = File.join(ndtypes_spec.gem_dir, 'ext', 'ruby_ndtypes')
20
+ ndtypes_includedir = File.join(ndtypes_extdir, 'include')
21
+ ndtypes_libdir = File.join(ndtypes_extdir, 'lib')
22
+
23
+ find_header("ruby_ndtypes.h", ndtypes_includedir)
24
+ raise "cannot find ruby_ndtypes.h in path #{ndtypes_includedir}." unless have_header("ruby_ndtypes.h")
25
+
26
+ find_header("ndtypes.h", ndtypes_includedir)
27
+ find_library("ndtypes", nil, ndtypes_libdir)
28
+
29
+ dir_config("ndtypes", [ndtypes_includedir], [ndtypes_libdir])
30
+
31
+ # xnd config
32
+
33
+ xnd_version = ">= 0.2.0dev5"
34
+ xnd_spec = Gem::Specification.find_by_name("xnd", xnd_version)
35
+ xnd_extdir = File.join(xnd_spec.gem_dir, 'ext', 'ruby_xnd')
36
+ xnd_includedir = File.join(xnd_extdir, 'include')
37
+ xnd_libdir = File.join(xnd_extdir, 'lib')
38
+
39
+ find_header("ruby_xnd.h", xnd_includedir)
40
+ raise "cannot find ruby_xnd.h in path #{xnd_includedir}." unless have_header("ruby_xnd.h")
41
+
42
+ find_header("xnd.h", xnd_includedir)
43
+ find_library("xnd", nil, xnd_libdir)
44
+
45
+ dir_config("xnd", [xnd_includedir], [xnd_libdir])
46
+
47
+ # gumath config
48
+
49
+ puts "compiling libgumath on your machine..."
50
+ Dir.chdir(File.join(File.dirname(__FILE__) + "/gumath")) do
51
+ if unix?
52
+ # ["libgumath", "libgumath/compat", "libgumath/serialize"].each do |f|
53
+ # Dir.chdir(f) do
54
+ # Dir.mkdir(".objs") unless Dir.exists? ".objs"
55
+ # end
56
+ # end
57
+ ENV['CFLAGS'] = " -I #{xnd_includedir} -I #{ndtypes_includedir} "
58
+ system("./configure --prefix=#{File.expand_path("../")} --with-docs=no ")
59
+ system("make")
60
+ system("make install")
61
+ elsif windows?
62
+ raise NotImplementedError, "need to specify build instructions for windows."
63
+ end
64
+ end
65
+
66
+ $INSTALLFILES = [
67
+ ["ruby_gumath.h", "$(archdir)"],
68
+ ["gumath.h", "$(archdir)"]
69
+ ]
70
+
71
+ binaries = File.expand_path(File.join(File.dirname(__FILE__) + "/lib/"))
72
+ headers = File.expand_path(File.join(File.dirname(__FILE__) + "/include/"))
73
+ $LOAD_PATH << File.expand_path(binaries)
74
+ append_ldflags("-Wl,-rpath #{binaries}")
75
+
76
+ find_library("gumath", nil, binaries)
77
+
78
+ find_header("gumath.h", headers)
79
+ have_header("gumath.h")
80
+
81
+ FileUtils.copy_file File.expand_path(File.join(File.dirname(__FILE__) +
82
+ "/ruby_gumath.h")),
83
+ "#{headers}/ruby_gumath.h"
84
+
85
+ dir_config("gumath", [headers], [binaries])
86
+
87
+ # for macOS
88
+ append_ldflags("-Wl,-rpath #{binaries}")
89
+
90
+ basenames = %w{util gufunc_object examples functions ruby_gumath}
91
+ $objs = basenames.map { |b| "#{b}.o" }
92
+ $srcs = basenames.map { |b| "#{b}.c" }
93
+
94
+ $CFLAGS += " -Wall -O0 -fPIC -g "
95
+ # FIXME: This is jugaad. Remove on deploy.
96
+ $libs += " -lndtypes -lxnd -lgumath "
97
+ create_makefile("ruby_gumath/ruby_gumath")
@@ -0,0 +1,106 @@
1
+ /* BSD 3-Clause License
2
+ *
3
+ * Copyright (c) 2018, Quansight and Sameer Deshmukh
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright notice, this
10
+ * list of conditions and the following disclaimer.
11
+ *
12
+ * * Redistributions in binary form must reproduce the above copyright notice,
13
+ * this list of conditions and the following disclaimer in the documentation
14
+ * and/or other materials provided with the distribution.
15
+ *
16
+ * * Neither the name of the copyright holder nor the names of its
17
+ * contributors may be used to endorse or promote products derived from
18
+ * this software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ */
31
+ #include "ruby_gumath_internal.h"
32
+
33
+ /****************************************************************************/
34
+ /* Static globals */
35
+ /****************************************************************************/
36
+
37
+ /* Function table */
38
+ static gm_tbl_t *table = NULL;
39
+ static VALUE mGumath_Functions;
40
+ static int initialized = 0;
41
+
42
+ /****************************************************************************/
43
+ /* Singleton methods */
44
+ /****************************************************************************/
45
+ static VALUE
46
+ mGumath_Functions_s_method_missing(int argc, VALUE *argv, VALUE module)
47
+ {
48
+ VALUE method_name = argv[0];
49
+ VALUE method_hash = rb_ivar_get(module, GUMATH_FUNCTION_HASH);
50
+ VALUE gumath_method = rb_hash_aref(method_hash, method_name);
51
+ int is_present = RTEST(gumath_method);
52
+
53
+ if (is_present) {
54
+ rb_funcall2(gumath_method, rb_intern("call"), argc-1, &argv[1]);
55
+ }
56
+ else {
57
+ VALUE str = rb_funcall(method_name, rb_intern("to_s"), 0, NULL);
58
+ rb_raise(rb_eNoMethodError, "Method %s not present in this gumath module.",
59
+ StringValueCStr(str));
60
+ }
61
+ }
62
+
63
+ void Init_gumath_functions(void)
64
+ {
65
+ /* Initialize gumath built-in function table. */
66
+ NDT_STATIC_CONTEXT(ctx);
67
+
68
+ if (!initialized) {
69
+ if (!xnd_exists()) {
70
+ rb_raise(rb_eLoadError, "XND is needed for making gumath work.");
71
+ }
72
+ if (!ndt_exists()) {
73
+ rb_raise(rb_eLoadError, "NDT is needed for maing gumath work.");
74
+ }
75
+
76
+ table = gm_tbl_new(&ctx);
77
+ if (table == NULL) {
78
+ rb_ndtypes_set_error(&ctx);
79
+ raise_error();
80
+ }
81
+
82
+ if (gm_init_unary_kernels(table, &ctx) < 0) {
83
+ rb_ndtypes_set_error(&ctx);
84
+ raise_error();
85
+ }
86
+
87
+ if (gm_init_binary_kernels(table, &ctx) < 0) {
88
+ rb_ndtypes_set_error(&ctx);
89
+ raise_error();
90
+ }
91
+
92
+ initialized = 1;
93
+ }
94
+
95
+ mGumath_Functions = rb_define_module_under(cGumath, "Functions");
96
+ rb_ivar_set(mGumath_Functions, GUMATH_FUNCTION_HASH, rb_hash_new());
97
+
98
+ if (rb_gumath_add_functions(mGumath_Functions, table) < 0) {
99
+ mGumath_Functions = Qundef;
100
+ rb_raise(rb_eLoadError, "failed to load functions into module Gumath::Functions.");
101
+ }
102
+
103
+ /* Singleton methods */
104
+ rb_define_singleton_method(mGumath_Functions, "method_missing",
105
+ mGumath_Functions_s_method_missing, -1);
106
+ }