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
@@ -0,0 +1,167 @@
1
+
2
+ AC_PREREQ([2.67])
3
+ AC_INIT(gumath, 0.2.0dev3, skrah@bytereef.org, gumath, https://github.com/plures/)
4
+ AC_CONFIG_HEADER(config.h)
5
+ AC_CONFIG_FILES([Makefile libgumath/Makefile])
6
+
7
+ # System and machine type (only used for Darwin):
8
+ AC_MSG_CHECKING(system as reported by uname -s)
9
+ ac_sys_system=`uname -s`
10
+ AC_MSG_RESULT($ac_sys_system)
11
+
12
+ LIBSTATIC=libgumath.a
13
+ case $ac_sys_system in
14
+ darwin*|Darwin*)
15
+ LIBRARY_PATH="DYLD_LIBRARY_PATH"
16
+ LIBNAME="libgumath.dylib"
17
+ LIBSONAME="libgumath.0.dylib"
18
+ LIBSHARED="libgumath.0.2.0dev3.dylib"
19
+ CONFIGURE_LDFLAGS="-dynamiclib -install_name @rpath/$LIBSONAME -undefined dynamic_lookup -compatibility_version 0.2 -current_version 0.2.0"
20
+ ;;
21
+ *)
22
+ LIBRARY_PATH="LD_LIBRARY_PATH"
23
+ LIBNAME="libgumath.so"
24
+ LIBSONAME="libgumath.so.0"
25
+ LIBSHARED="libgumath.so.0.2.0dev3"
26
+ CONFIGURE_LDFLAGS="-shared -Wl,-soname,$LIBSONAME"
27
+ ;;
28
+ esac
29
+
30
+ AC_SUBST(LIBSTATIC)
31
+ AC_SUBST(LIBRARY_PATH)
32
+ AC_SUBST(LIBNAME)
33
+ AC_SUBST(LIBSONAME)
34
+ AC_SUBST(LIBSHARED)
35
+
36
+
37
+ # Apparently purely informational for this particular build:
38
+ AC_CANONICAL_HOST
39
+ AC_SUBST(build)
40
+ AC_SUBST(host)
41
+
42
+ # Language and compiler:
43
+ AC_LANG_C
44
+ saved_cflags=$CFLAGS
45
+ AC_PROG_CC
46
+ CFLAGS=$saved_cflags
47
+
48
+ # ar and ranlib:
49
+ AC_CHECK_TOOL(AR, ar, ar)
50
+ AC_PROG_RANLIB
51
+ AC_SUBST(RANLIB)
52
+
53
+
54
+ # Checks for header files:
55
+ AC_HEADER_STDC
56
+ AC_CHECK_HEADER([pthread.h],
57
+ [AC_DEFINE([HAVE_PTHREAD_H], 1, [Define to 1 if you have the <pthread.h> header file.])],
58
+ [])
59
+
60
+ # Install program:
61
+ AC_PROG_INSTALL
62
+ AC_SUBST(INSTALL)
63
+
64
+ # Add an explicit include directory.
65
+ AC_MSG_CHECKING(for --with-includes)
66
+ AC_ARG_WITH(includes,
67
+ AS_HELP_STRING([--with-includes="/usr/local/include"],
68
+ [absolute path to an include directory]),
69
+ [],
70
+ [with_includes="none"])
71
+
72
+ AC_MSG_RESULT($with_includes)
73
+
74
+ if test "$with_includes" = "none"; then
75
+ CONFIGURE_INCLUDES=../ndtypes/libndtypes
76
+ CONFIGURE_INCLUDES_TEST=../../ndtypes/libndtypes
77
+ else
78
+ CONFIGURE_INCLUDES=$with_includes
79
+ CONFIGURE_INCLUDES_TEST=$with_includes
80
+ fi
81
+
82
+ AC_SUBST(CONFIGURE_INCLUDES)
83
+ AC_SUBST(CONFIGURE_INCLUDES_TEST)
84
+
85
+ # Add an explicit library path.
86
+ AC_MSG_CHECKING(for --with-libs)
87
+ AC_ARG_WITH(libs,
88
+ AS_HELP_STRING([--with-libs="/usr/local/lib"],
89
+ [absolute path to a library directory]),
90
+ [],
91
+ [with_libs="none"])
92
+
93
+ AC_MSG_RESULT($with_libs)
94
+
95
+ if test "$with_libs" = "none"; then
96
+ CONFIGURE_LIBS=../ndtypes/libndtypes
97
+ CONFIGURE_LIBS_TEST=../../ndtypes/libndtypes
98
+ else
99
+ CONFIGURE_LIBS=$with_libs
100
+ CONFIGURE_LIBS_TEST=$with_libs
101
+ fi
102
+
103
+ AC_SUBST(CONFIGURE_LIBS)
104
+ AC_SUBST(CONFIGURE_LIBS_TEST)
105
+
106
+ # Without documentation:
107
+ AC_MSG_CHECKING([for --with-docs])
108
+ AC_ARG_WITH([docs],
109
+ AS_HELP_STRING([--with-docs], [install documentation - enabled by default]),,
110
+ with_docs=yes)
111
+ AC_MSG_RESULT([$with_docs])
112
+ if test "$with_docs" = yes; then
113
+ NDT_INSTALL_DOCS="install_docs"
114
+ else
115
+ NDT_INSTALL_DOCS=""
116
+ fi
117
+
118
+ AC_SUBST(NDT_INSTALL_DOCS)
119
+
120
+ # Compiler dependent settings:
121
+ GM_WARN=
122
+ GM_OPT="-O2"
123
+ case $CC in
124
+ *gcc*)
125
+ GM_WARN="-Wall -Wextra -std=c11 -pedantic"
126
+ GM_OPT="-O3"
127
+ ;;
128
+ *icc*)
129
+ AR=xiar
130
+ GM_WARN="-Wall"
131
+ GM_OPT="-O3"
132
+ ;;
133
+ *clang*)
134
+ GM_WARN="-Wall -Wextra -std=c11 -pedantic"
135
+ GM_OPT="-O3"
136
+ ;;
137
+ esac
138
+
139
+
140
+
141
+ # Substitute variables and generate output:
142
+ if test -z "$LD"; then
143
+ LD="$CC"
144
+ fi
145
+ AC_SUBST(LD)
146
+ AC_SUBST(AR)
147
+ AC_SUBST(GM_WARN)
148
+ AC_SUBST(GM_OPT)
149
+
150
+
151
+ if test -z "$CFLAGS"; then
152
+ CONFIGURE_CFLAGS="$GM_INCLUDE $GM_WARN $GM_CONFIG $GM_OPT"
153
+ else
154
+ CONFIGURE_CFLAGS="$GM_INCLUDE $GM_WARN $GM_CONFIG $GM_OPT $CFLAGS"
155
+ fi
156
+
157
+ if test -z "$LDFLAGS"; then
158
+ CONFIGURE_LDFLAGS="$GM_LINK $CONFIGURE_LDFLAGS"
159
+ else
160
+ CONFIGURE_LDFLAGS="$GM_LINK $CONFIGURE_LDFLAGS $LDFLAGS"
161
+ fi
162
+
163
+ AC_SUBST(CONFIGURE_CFLAGS)
164
+ AC_SUBST(CONFIGURE_LDFLAGS)
165
+
166
+ AC_OUTPUT
167
+
@@ -0,0 +1,66 @@
1
+ // Copyright 2014 PSF. Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
2
+ // File originates from the cpython source found in Doc/tools/sphinxext/static/copybutton.js
3
+
4
+ $(document).ready(function() {
5
+ /* Add a [>>>] button on the top-right corner of code samples to hide
6
+ * the >>> and ... prompts and the output and thus make the code
7
+ * copyable. */
8
+ var div = $('.highlight-py .highlight,' +
9
+ '.highlight-default .highlight,' +
10
+ '.highlight-py3 .highlight')
11
+ var pre = div.find('pre');
12
+
13
+ // get the styles from the current theme
14
+ pre.parent().parent().css('position', 'relative');
15
+ var hide_text = 'Hide the prompts and output';
16
+ var show_text = 'Show the prompts and output';
17
+ var border_width = pre.css('border-top-width');
18
+ var border_style = pre.css('border-top-style');
19
+ var border_color = pre.css('border-top-color');
20
+ var button_styles = {
21
+ 'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0',
22
+ 'border-color': border_color, 'border-style': border_style,
23
+ 'border-width': border_width, 'color': border_color, 'text-size': '75%',
24
+ 'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em',
25
+ 'border-radius': '0 3px 0 0'
26
+ }
27
+
28
+ // create and add the button to all the code blocks that contain >>>
29
+ div.each(function(index) {
30
+ var jthis = $(this);
31
+ if (jthis.find('.gp').length > 0) {
32
+ var button = $('<span class="copybutton">&gt;&gt;&gt;</span>');
33
+ button.css(button_styles)
34
+ button.attr('title', hide_text);
35
+ button.data('hidden', 'false');
36
+ jthis.prepend(button);
37
+ }
38
+ // tracebacks (.gt) contain bare text elements that need to be
39
+ // wrapped in a span to work with .nextUntil() (see later)
40
+ jthis.find('pre:has(.gt)').contents().filter(function() {
41
+ return ((this.nodeType == 3) && (this.data.trim().length > 0));
42
+ }).wrap('<span>');
43
+ });
44
+
45
+ // define the behavior of the button when it's clicked
46
+ $('.copybutton').click(function(e){
47
+ e.preventDefault();
48
+ var button = $(this);
49
+ if (button.data('hidden') === 'false') {
50
+ // hide the code output
51
+ button.parent().find('.go, .gp, .gt').hide();
52
+ button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden');
53
+ button.css('text-decoration', 'line-through');
54
+ button.attr('title', show_text);
55
+ button.data('hidden', 'true');
56
+ } else {
57
+ // show the code output
58
+ button.parent().find('.go, .gp, .gt').show();
59
+ button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible');
60
+ button.css('text-decoration', 'none');
61
+ button.attr('title', hide_text);
62
+ button.data('hidden', 'false');
63
+ }
64
+ });
65
+ });
66
+
@@ -0,0 +1,26 @@
1
+ import sys, os, docutils
2
+
3
+
4
+ extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.doctest']
5
+
6
+ source_suffix = '.rst'
7
+ master_doc = 'index'
8
+ project = 'gumath'
9
+ copyright = '2017-2018, Plures Project'
10
+ version = 'v0.2.0dev3'
11
+ release = 'v0.2.0dev3'
12
+ exclude_patterns = ['doc', 'build']
13
+ pygments_style = 'sphinx'
14
+ html_static_path = ['_static']
15
+
16
+ primary_domain = 'py'
17
+ add_function_parentheses = False
18
+
19
+
20
+ def setup(app):
21
+ app.add_crossref_type('topic', 'topic', 'single: %s',
22
+ docutils.nodes.strong)
23
+ app.add_javascript("copybutton.js")
24
+
25
+
26
+
@@ -0,0 +1,62 @@
1
+ .. meta::
2
+ :robots: index,follow
3
+ :description: xnd container
4
+ :keywords: xnd, types, examples
5
+
6
+ .. sectionauthor:: Stefan Krah <skrah at bytereef.org>
7
+
8
+
9
+ Builtin functions
10
+ =================
11
+
12
+ The gumath.functions module wraps the builtin libgumath kernels and serves
13
+ as an example of a modular namespace.
14
+
15
+
16
+ All builtin functions
17
+ ---------------------
18
+
19
+ .. doctest::
20
+
21
+ >>> from gumath import functions as fn
22
+ >>> dir(fn)
23
+ ['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'add', 'asin', 'asinh', 'atan', 'atanh', 'cbrt', 'ceil', 'copy', 'cos', 'cosh', 'divide', 'erf', 'erfc', 'exp', 'exp2', 'expm1', 'fabs', 'floor', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'logb', 'multiply', 'nearbyint', 'round', 'sin', 'sinh', 'sqrt', 'subtract', 'tan', 'tanh', 'tgamma', 'trunc']
24
+
25
+
26
+ Unary functions
27
+ ---------------
28
+
29
+ .. doctest::
30
+
31
+ >>> from xnd import xnd
32
+ >>> x = xnd([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
33
+ >>> fn.log(x)
34
+ xnd([[0.0, 0.6931471805599453, 1.0986122886681098], [1.3862943611198906, 1.6094379124341003, 1.791759469228055]],
35
+ type='2 * 3 * float64')
36
+
37
+ On an array with a *float64* dtype, *log* works as expected.
38
+
39
+
40
+ .. doctest::
41
+
42
+ >>> x = xnd([[1, 2, 3], [4, 5, 6]])
43
+ >>> x.type
44
+ ndt("2 * 3 * int64")
45
+ >>> fn.log(x)
46
+ Traceback (most recent call last):
47
+ File "<stdin>", line 1, in <module>
48
+ RuntimeError: invalid dtype
49
+
50
+ This function call would require an implicit inexact conversion from *int64* to
51
+ *float64*. All builtin libgumath kernels only allow exact conversions, so the
52
+ example fails.
53
+
54
+
55
+ .. doctest::
56
+
57
+ >>> x = xnd([[1, 2, 3], [4, 5, 6]], dtype="int32")
58
+ >>> fn.log(x)
59
+ xnd([[0.0, 0.6931471805599453, 1.0986122886681098], [1.3862943611198906, 1.6094379124341003, 1.791759469228055]],
60
+ type='2 * 3 * float64')
61
+
62
+ *int32* to *float64* conversions are exact, so the call succeeds.
@@ -0,0 +1,26 @@
1
+ .. meta::
2
+ :robots: index, follow
3
+ :description: gumath documentation
4
+ :keywords: kernels, dispatch, Python
5
+
6
+ .. sectionauthor:: Stefan Krah <skrah at bytereef.org>
7
+
8
+
9
+ gumath
10
+ ------
11
+
12
+ The gumath Python module provides the infrastructure for managing and
13
+ dispatching libgumath kernels. Kernels target xnd containers from the
14
+ xnd Python module.
15
+
16
+ gumath supports modular namespaces. Typically, a namespace is implemented
17
+ as one Python module that uses gumath for calling kernels.
18
+
19
+ The xndtools project automates generating kernels and creating namespace
20
+ modules.
21
+
22
+
23
+ .. toctree::
24
+ :maxdepth: 1
25
+
26
+ functions.rst
@@ -0,0 +1,45 @@
1
+ .. meta::
2
+ :robots: index, follow
3
+ :description: gumath documentation
4
+ :keywords: libgumath, gumath, C, Python, array computing
5
+
6
+ .. sectionauthor:: Stefan Krah <skrah at bytereef.org>
7
+
8
+
9
+ gumath
10
+ ======
11
+
12
+ Gumath is a package for extensible dispatch of computational kernels that
13
+ target xnd containers. Kernels can be added at runtime, which allows the
14
+ use of JIT compilers.
15
+
16
+
17
+ Libgumath
18
+ ---------
19
+
20
+ C library.
21
+
22
+ .. toctree::
23
+ :maxdepth: 1
24
+
25
+ libgumath/index.rst
26
+
27
+
28
+ Gumath
29
+ ------
30
+
31
+ Python module.
32
+
33
+ .. toctree::
34
+ :maxdepth: 1
35
+
36
+ gumath/index.rst
37
+
38
+
39
+ Releases
40
+ --------
41
+
42
+ .. toctree::
43
+ :maxdepth: 1
44
+
45
+ releases/index.rst
@@ -0,0 +1,130 @@
1
+ .. meta::
2
+ :robots: index,follow
3
+ :description: libndtypes documentation
4
+
5
+ .. sectionauthor:: Stefan Krah <skrah at bytereef.org>
6
+
7
+
8
+ Data structures
9
+ ===============
10
+
11
+ libgumath is a lightweight library for managing and dispatching computational
12
+ kernels that target XND containers.
13
+
14
+ Functions are multimethods in a lookup table. Typically, applications that
15
+ use libgumath should create a new lookup table for each namespace. For example,
16
+ Python modules generally should have a module-specific lookup table.
17
+
18
+
19
+ Kernel signatures
20
+ -----------------
21
+
22
+ .. topic:: kernels
23
+
24
+ .. code-block:: c
25
+
26
+ typedef int (* gm_xnd_kernel_t)(xnd_t stack[], ndt_context_t *ctx);
27
+
28
+ The signature of an *xnd* kernel. *stack* contains incoming and outgoing
29
+ arguments. In case of an error, kernels are expected to set a context error
30
+ message and return *-1*.
31
+
32
+ In case of success, the return value is *0*.
33
+
34
+
35
+ .. code-block:: c
36
+
37
+ typedef int (* gm_strided_kernel_t)(char **args, intptr_t *dimensions, intptr_t *steps, void *data);
38
+
39
+ The signature of a NumPy compatible kernel. These signatures are for
40
+ applications that want to use existing NumPy compatible kernels on XND
41
+ containers.
42
+
43
+ XND containers are automatically converted to a temporary ndarray before
44
+ kernel application.
45
+
46
+
47
+ Kernel set
48
+ ----------
49
+
50
+ .. code-block:: c
51
+
52
+ /* Collection of specialized kernels for a single function signature. */
53
+ typedef struct {
54
+ ndt_t *sig;
55
+ const ndt_constraint_t *constraint;
56
+
57
+ /* Xnd signatures */
58
+ gm_xnd_kernel_t C; /* dispatch ensures c-contiguous */
59
+ gm_xnd_kernel_t Fortran; /* dispatch ensures f-contiguous */
60
+ gm_xnd_kernel_t Xnd; /* selected if non-contiguous or both C and Fortran are NULL */
61
+
62
+ /* NumPy signature */
63
+ gm_strided_kernel_t Strided;
64
+ } gm_kernel_set_t;
65
+
66
+ A kernel set contains the function signature, an optional constraint function,
67
+ and up to four specialized kernels, each of which may be *NULL*.
68
+
69
+ The dispatch calls the kernels in the following order of preference:
70
+
71
+ If the inner dimensions of the incoming arguments are C-contiguous, the *C*
72
+ kernel is called first. In case of *Fortran* inner dimensions, *Fortran*
73
+ is called first.
74
+
75
+ If an *Xnd* kernel is present, it is called next, then the *Strided* kernel.
76
+
77
+
78
+ Kernel set initialization
79
+ -------------------------
80
+
81
+ .. topic:: kernel set initialization
82
+
83
+ .. code-block:: c
84
+
85
+ typedef struct {
86
+ const char *name;
87
+ const char *sig;
88
+ const ndt_constraint_t *constraint;
89
+
90
+ gm_xnd_kernel_t C;
91
+ gm_xnd_kernel_t Fortran;
92
+ gm_xnd_kernel_t Xnd;
93
+ gm_strided_kernel_t Strided;
94
+ } gm_kernel_init_t;
95
+
96
+ int gm_add_kernel(gm_tbl_t *tbl, const gm_kernel_init_t *kernel, ndt_context_t *ctx);
97
+
98
+ The *gm_kernel_init_t* is used for initializing a kernel set. Usually, a C
99
+ translation unit contains an array of hundreds of *gm_kernel_init_t* structs
100
+ together with a function that initializes a specific lookup table.
101
+
102
+
103
+ Multimethod struct
104
+ ------------------
105
+
106
+ .. topic:: kernel set initialization
107
+
108
+ .. code-block:: c
109
+
110
+ /* Multimethod with associated kernels */
111
+ typedef struct gm_func gm_func_t;
112
+ typedef const gm_kernel_set_t *(*gm_typecheck_t)(ndt_apply_spec_t *spec,
113
+ const gm_func_t *f, const ndt_t *in[], int nin, ndt_context_t *ctx);
114
+ struct gm_func {
115
+ char *name;
116
+ gm_typecheck_t typecheck; /* Experimental optimized type-checking, may be NULL. */
117
+ int nkernels;
118
+ gm_kernel_set_t kernels[GM_MAX_KERNELS];
119
+ };
120
+
121
+ This is the multimethod struct for a given function name. Each multimethod has
122
+ a *nkernels* associated kernel sets with unique type signatures.
123
+
124
+ If *typecheck* is *NULL*, the generic libndtypes multimethod dispatch is used
125
+ to locate the kernel. This is an O(N) operation, whose search time is negligible
126
+ for large array operations.
127
+
128
+ The *typecheck* field can be set to an optimized lookup function that has
129
+ internal knowledge of kernel set locations. The only restriction to the
130
+ function is that it must behave exactly as the generic libndtypes typecheck.