gumath 0.2.0dev5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.