kmat 0.0.3

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 (55) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +3 -0
  3. data/.gitignore +15 -0
  4. data/CHANGELOG.md +15 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.md +675 -0
  7. data/README.md +224 -0
  8. data/Rakefile +26 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/ext/kmat/arith/binary.c +1121 -0
  12. data/ext/kmat/arith/logical.c +332 -0
  13. data/ext/kmat/arith/math.c +34 -0
  14. data/ext/kmat/arith/statistics.c +173 -0
  15. data/ext/kmat/arith/unary.c +165 -0
  16. data/ext/kmat/auto_collect.rb +118 -0
  17. data/ext/kmat/elementwise_function.rb +149 -0
  18. data/ext/kmat/extconf.rb +75 -0
  19. data/ext/kmat/id.txt +80 -0
  20. data/ext/kmat/id_sym.rb +40 -0
  21. data/ext/kmat/km_util.h +97 -0
  22. data/ext/kmat/kmat.h +96 -0
  23. data/ext/kmat/lapack_headers/blas.h +354 -0
  24. data/ext/kmat/lapack_headers/lapacke.h +19455 -0
  25. data/ext/kmat/lapack_headers/lapacke_config.h +119 -0
  26. data/ext/kmat/lapack_headers/lapacke_mangling.h +17 -0
  27. data/ext/kmat/lapack_headers/lapacke_utils.h +579 -0
  28. data/ext/kmat/linalg/dla.c +1629 -0
  29. data/ext/kmat/linalg/linalg.c +267 -0
  30. data/ext/kmat/linalg/norm.c +727 -0
  31. data/ext/kmat/linalg/vla.c +102 -0
  32. data/ext/kmat/linalg/working.c +240 -0
  33. data/ext/kmat/main.c +95 -0
  34. data/ext/kmat/smat/accessor.c +719 -0
  35. data/ext/kmat/smat/array.c +108 -0
  36. data/ext/kmat/smat/boxmuller.c +72 -0
  37. data/ext/kmat/smat/constructer.c +302 -0
  38. data/ext/kmat/smat/convert.c +375 -0
  39. data/ext/kmat/smat/elem.c +171 -0
  40. data/ext/kmat/smat/fund.c +702 -0
  41. data/ext/kmat/smat/share.c +427 -0
  42. data/ext/kmat/smat/smat.c +530 -0
  43. data/ext/kmat/smat/sort.c +1156 -0
  44. data/ext/kmat/sym.txt +34 -0
  45. data/kmat.gemspec +46 -0
  46. data/lib/kmat.rb +20 -0
  47. data/lib/kmat/accessor.rb +164 -0
  48. data/lib/kmat/arith.rb +189 -0
  49. data/lib/kmat/linalg.rb +279 -0
  50. data/lib/kmat/logical.rb +150 -0
  51. data/lib/kmat/misc.rb +122 -0
  52. data/lib/kmat/random.rb +106 -0
  53. data/lib/kmat/statistics.rb +98 -0
  54. data/lib/kmat/version.rb +3 -0
  55. metadata +156 -0
@@ -0,0 +1,165 @@
1
+ #include "../kmat.h"
2
+
3
+ static void
4
+ km_abs_func_d(double *ent, void *data)
5
+ {
6
+ *ent = fabs(*ent);
7
+ }
8
+ static void
9
+ km_abs_func_z(COMPLEX *ent, void *data)
10
+ {
11
+ *ent = cpack(cabs(*ent), 0.0);
12
+ }
13
+ static void
14
+ km_abs_func_i(int *ent, void *data)
15
+ {
16
+ *ent = ABS(*ent);
17
+ }
18
+ static void
19
+ km_abs_func_v(VALUE *ent, void *data)
20
+ {
21
+ *ent = rb_funcall(*ent, id_abs, 0);
22
+ }
23
+ VALUE
24
+ kmm_mat_abs_destl(VALUE self)
25
+ {
26
+ km_check_frozen(self);
27
+ SMAT *smat = km_mat2smat(self);
28
+ VT_SWITCH( smat->vtype,
29
+ km_smat_each_d(smat, km_abs_func_d, NULL);,
30
+ km_smat_each_z(smat, km_abs_func_z, NULL);,
31
+ km_smat_each_i(smat, km_abs_func_i, NULL);,
32
+ /* nothing to do */,
33
+ km_smat_each_v(smat, km_abs_func_v, NULL);
34
+ );
35
+ return self;
36
+ }
37
+ static void
38
+ km_cabs_func(double *dest, const COMPLEX *src, void *data)
39
+ {
40
+ *dest = cabs(*src);
41
+ }
42
+ VALUE
43
+ kmm_mat_abs(VALUE self)
44
+ {
45
+ SMAT *smat = km_mat2smat(self);
46
+ if ( smat->vtype == VT_COMPLEX ) {
47
+ VALUE ret = km_Mat(smat->m, smat->n, VT_DOUBLE);
48
+ km_smat_each2_dcz(km_mat2smat(ret), smat, km_cabs_func, NULL);
49
+ return ret;
50
+ } else {
51
+ return kmm_mat_abs_destl(rb_obj_dup(self));
52
+ }
53
+ }
54
+
55
+ static void
56
+ km_uminus_func_d(double *ent, void *data)
57
+ {
58
+ *ent = -(*ent);
59
+ }
60
+ static void
61
+ km_uminus_func_z(COMPLEX *ent, void *data)
62
+ {
63
+ *ent = -(*ent);
64
+ }
65
+ static void
66
+ km_uminus_func_i(int *ent, void *data)
67
+ {
68
+ *ent = -(*ent);
69
+ }
70
+ static void
71
+ km_uminus_func_v(VALUE *ent, void *data)
72
+ {
73
+ *ent = rb_funcall(*ent, id_op_uminus, 0);
74
+ }
75
+ VALUE
76
+ kmm_mat_uminus_destl(VALUE self)
77
+ {
78
+ km_check_frozen(self);
79
+ SMAT *smat = km_mat2smat(self);
80
+ VT_SWITCH( smat->vtype,
81
+ km_smat_each_d(smat, km_uminus_func_d, NULL);,
82
+ km_smat_each_z(smat, km_uminus_func_z, NULL);,
83
+ km_smat_each_i(smat, km_uminus_func_i, NULL);,
84
+ /* nothing to do */,
85
+ km_smat_each_v(smat, km_uminus_func_v, NULL);
86
+ );
87
+ return self;
88
+ }
89
+ // alias -@
90
+ VALUE
91
+ kmm_mat_uminus(VALUE self)
92
+ {
93
+ return kmm_mat_uminus_destl(rb_obj_dup(self));
94
+ }
95
+
96
+ static void
97
+ km_conj_func_z(COMPLEX *ent, void *data)
98
+ {
99
+ *ent = conj(*ent);
100
+ }
101
+ static void
102
+ km_conj_func_v(VALUE *ent, void *data)
103
+ {
104
+ *ent = rb_funcall(*ent, id_conj, 0);
105
+ }
106
+ // alias conjugate
107
+ VALUE
108
+ kmm_mat_conj_dest(VALUE self)
109
+ {
110
+ km_check_frozen(self);
111
+ SMAT *smat = km_mat2smat(self);
112
+ if ( smat->vtype == VT_COMPLEX ) {
113
+ km_smat_each_z(smat, km_conj_func_z, NULL);
114
+ } else if ( smat->vtype == VT_VALUE ) {
115
+ km_smat_each_v(smat, km_conj_func_v, NULL);
116
+ }
117
+ return self;
118
+ }
119
+
120
+ // trace
121
+ // alias tr
122
+ VALUE
123
+ kmm_mat_trace(VALUE self)
124
+ {
125
+ SMAT *smat = km_mat2smat(self);
126
+ int len = MIN(smat->m, smat->n);
127
+ if ( smat->vtype == VT_DOUBLE ) {
128
+ double ret = 0.0;
129
+ for ( int i=0; i<len; i++ ) {
130
+ ret += ENTITY(smat, d, i, i);
131
+ }
132
+ return rb_float_new(ret);
133
+ } else if ( smat->vtype == VT_COMPLEX ) {
134
+ COMPLEX ret = cpack(0.0, 0.0);
135
+ for ( int i=0; i<len; i++ ) {
136
+ ret += ENTITY(smat, z, i, i);
137
+ }
138
+ return km_c2v(ret);
139
+ } else if ( smat->vtype == VT_INT ) {
140
+ int ret = 0;
141
+ for ( int i=0; i<len; i++ ) {
142
+ ret += ENTITY(smat, i, i, i);
143
+ }
144
+ return INT2NUM(ret);
145
+ } else if ( smat->vtype == VT_BOOL ) {
146
+ bool ret = false;
147
+ for ( int i=0; i<len; i++ ) {
148
+ bool ent = ENTITY(smat, b, i, i);
149
+ ret = XOR(ret, ent);
150
+ }
151
+ return TF2V(ret);
152
+ } else if ( smat->vtype == VT_VALUE ) {
153
+ if ( len == 0 ) {
154
+ return INT2NUM(0);
155
+ } else {
156
+ VALUE ret = ENTITY(smat, v, 0, 0);
157
+ for ( int i=1; i<len; i++ ) {
158
+ ret = rb_funcall(ret, id_op_plus, 1, ENTITY(smat, v, i, i));
159
+ }
160
+ return ret;
161
+ }
162
+ } else {
163
+ rb_raise(km_eInternal, "unknown value type");
164
+ }
165
+ }
@@ -0,0 +1,118 @@
1
+
2
+ class MethodDefinition
3
+ def initialize(name_arg, comment)
4
+ comment = %r|//\s+(.*)|.match(comment)[1]
5
+ @als = /\Aalias (.+)/.match(comment)&.[](1)&.split(/[,\s]\s*/)
6
+ @meth = /\Akmm_/.match(name_arg)
7
+ return unless @meth
8
+ m = %r|\A(kmm_([^\(_]+)_([^\(]+))\((.+)\)\Z|.match(name_arg)
9
+ raise "unknown name_arg pattern `#{name_arg}' found" unless m
10
+ @funcname, @type, @name, arg = m[1], type_trans(m[2]), m[3], m[4]
11
+ if m = %r|(.+)_p\Z|.match(@name)
12
+ @name = m[1]+'?'
13
+ elsif m = %r|(.+)_dest\Z|.match(@name)
14
+ @name = m[1]
15
+ @dup_esc = true
16
+ elsif m = %r|(.+)_destl\Z|.match(@name)
17
+ @name = m[1]+'!'
18
+ end
19
+ if m = %r|(.+)_m2\Z|.match(@name)
20
+ @name = m[1]
21
+ @argc = -2
22
+ elsif m = %r|\Aint argc|.match(arg)
23
+ @argc = -1
24
+ else
25
+ @argc = arg.split(/,/).size-1
26
+ end
27
+ end
28
+ attr_reader :meth
29
+
30
+ def type_trans(t)
31
+ case t
32
+ when 'obj'
33
+ 'rb_cObject'
34
+ when 'mat'
35
+ 'km_cMat'
36
+ when 'Mat'
37
+ 'km_sMat'
38
+ when 'ary'
39
+ 'rb_cArray'
40
+ when 'MATH'
41
+ ['rb_mMath', 'rb_sMath']
42
+ when 'float'
43
+ 'rb_cFloat'
44
+ else
45
+ raise "unknown type `#{t}' found"
46
+ end
47
+ end
48
+
49
+ def to_s(join="\n\t")
50
+ ret = []
51
+ if @type.kind_of?(Array)
52
+ ret << %Q|rb_define_module_function(#{@type[0]}, "#{@name}", #{@funcname}, #{@argc});|
53
+ elsif %r|\A\_|.match(@name)
54
+ ret << %Q|rb_define_private_method(#{@type}, "#{@name}", #{@funcname}, #{@argc});|
55
+ elsif @dup_esc
56
+ ret << %Q|rb_define_method(#{@type}, "#{@name}!", #{@funcname}, #{@argc});|
57
+ ret << %Q|rb_funcall(km_cMat, id__define_dup_escaped_method, 1, rb_str_new_cstr("#{@name}"));|
58
+ else
59
+ ret << %Q|rb_define_method(#{@type}, "#{@name}", #{@funcname}, #{@argc});|
60
+ end
61
+ @als&.each do |a|
62
+ if @type.kind_of?(Array)
63
+ ret << %Q|rb_define_alias(#{@type[0]}, "#{a}", "#{@name}");|
64
+ ret << %Q|rb_define_alias(#{@type[1]}, "#{a}", "#{@name}");|
65
+ else
66
+ ret << %Q|rb_define_alias(#{@type}, "#{a}", "#{@name}");|
67
+ ret << %Q|rb_define_alias(#{@type}, "#{a}!", "#{@name}!");| if @dup_esc
68
+ end
69
+ end
70
+ ret.join(join)
71
+ end
72
+ end
73
+
74
+ defs, decs = [], []
75
+
76
+ # for all .c files
77
+ Dir.glob("#{__dir__}/**/*.c").each do |file|
78
+ # for lines that comment line (can be omitted), return type and modifier line, function name and argument line
79
+ File.read(file).gsub(%r|(//[^\n]+\n)?[^#/{}\n\s][^\n;]+\n[^#/{}\n\s][^\n;]+\n{\n|) do |m|
80
+ ary = m.split(/\n/)
81
+ # functions which name start with kmm_ are methods
82
+ if ary.size == 4
83
+ foo = MethodDefinition.new(ary[2], ary[0])
84
+ else
85
+ foo = MethodDefinition.new(ary[1], '// ')
86
+ end
87
+ defs << foo.to_s if foo.meth
88
+ # ignore static functions and static variables
89
+ unless /\Astatic/.match(ary[-3])
90
+ decs << "#{ary[-3]} #{ary[-2]};"
91
+ end
92
+ ''
93
+ end
94
+ end
95
+
96
+
97
+ File.open('./auto_collected.h', 'w') do |f|
98
+ decs.each do |dec|
99
+ f.puts dec
100
+ end
101
+ end
102
+
103
+ File.open('./method_definitions.c', 'w') do |f|
104
+ f.puts "static void\nkm_define_methods(void)\n{"
105
+ defs.each do |def_|
106
+ f.puts "\t#{def_}"
107
+ end
108
+ f.puts '}'
109
+ end
110
+
111
+ File.open('./global_variables.h', 'w') do |f|
112
+ flg = false
113
+ File.foreach("#{__dir__}/main.c") do |line|
114
+ flg = true if line == "// km_global_variables_begin\n"
115
+ f.puts "extern #{line}" if flg && !%r|\A// km_global_variables|.match(line) && !%r|\A\s*\n\Z|.match(line)
116
+ break if line == "// km_global_variables_end\n"
117
+ end
118
+ end
@@ -0,0 +1,149 @@
1
+ both = %w(sin cos tan asin acos atan sinh cosh tanh asinh acosh atanh exp log sqrt)
2
+ fonly = %w(exp2 expm1 log10 log1p log2 logb cbrt erf erfc lgamma tgamma ceil floor round trunc sign)
3
+ dz = %w(real imag arg)
4
+
5
+ File.open('elementwise_function.c', 'w') do |f|
6
+ f.puts 'static double sign(double x){ return ( x==0.0 ? 0.0 : ( x>0.0 ? 1.0 : ( x<0.0 ? -1.0 : x ))); }'
7
+
8
+ both.each do |func|
9
+ f.puts <<"EOS"
10
+ static void
11
+ km_#{func}_d(double *ent, void *null)
12
+ {
13
+ *ent = #{func}(*ent);
14
+ }
15
+ static void
16
+ km_#{func}_z(COMPLEX *ent, void *null)
17
+ {
18
+ *ent = c#{func}(*ent);
19
+ }
20
+ static void
21
+ km_#{func}_v(VALUE *ent, void *null)
22
+ {
23
+ *ent = rb_funcall(rb_mMath, id_#{func}, 1, *ent);
24
+ }
25
+ VALUE
26
+ kmm_mat_#{func}_dest(VALUE self)
27
+ {
28
+ km_check_frozen(self);
29
+ SMAT *smat = km_mat2smat(self);
30
+ if ( smat->vtype == VT_DOUBLE ) {
31
+ km_smat_each_d(smat, km_#{func}_d, NULL);
32
+ } else if ( smat->vtype == VT_COMPLEX ) {
33
+ km_smat_each_z(smat, km_#{func}_z, NULL);
34
+ } else if ( smat->vtype == VT_VALUE ) {
35
+ km_smat_each_v(smat, km_#{func}_v, NULL);
36
+ } else {
37
+ rb_raise(km_eVT, "the method is available only for float or complex matricies");
38
+ }
39
+ return self;
40
+ }
41
+ EOS
42
+ end
43
+
44
+ fonly.each do |func|
45
+ f.puts <<"EOS"
46
+ static void
47
+ km_#{func}_d(double *ent, void *null)
48
+ {
49
+ *ent = #{func}(*ent);
50
+ }
51
+ static void
52
+ km_#{func}_v(VALUE *ent, void *null)
53
+ {
54
+ *ent = rb_funcall(rb_mMath, id_#{func}, 1, *ent);
55
+ }
56
+ VALUE
57
+ kmm_mat_#{func}_dest(VALUE self)
58
+ {
59
+ km_check_frozen(self);
60
+ SMAT *smat = km_mat2smat(self);
61
+ if ( smat->vtype == VT_DOUBLE ) {
62
+ km_smat_each_d(smat, km_#{func}_d, NULL);
63
+ } else if ( smat->vtype == VT_VALUE ) {
64
+ km_smat_each_v(smat, km_#{func}_v, NULL);
65
+ } else {
66
+ rb_raise(km_eVT, "the method is available only for float matricies");
67
+ }
68
+ return self;
69
+ }
70
+ EOS
71
+ end
72
+ f.puts <<'EOS'
73
+ static VALUE
74
+ km_zmat_e_funcapp(VALUE self, void (*func)(COMPLEX *, void *))
75
+ {
76
+ km_check_frozen(self);
77
+ SMAT *smat = km_mat2smat(self);
78
+ if ( smat->vtype != VT_COMPLEX ) {
79
+ rb_raise(km_eVT, "the method is available only for complex matrcies");
80
+ }
81
+ km_smat_each_z(smat, func, NULL);
82
+ return self;
83
+ }
84
+ static VALUE
85
+ km_zdmat_e_funcapp(VALUE self, VALUE op, void (*func)(double *, const COMPLEX *, void *))
86
+ {
87
+ km_check_frozen(op);
88
+ SMAT *dest = km_mat2smat(op), *src = km_mat2smat(self);
89
+ if ( dest->vtype != VT_DOUBLE || src->vtype != VT_COMPLEX ) {
90
+ rb_raise(km_eVT, "self(operand) and argument(output) must be complex and float matrix, respectively");
91
+ }
92
+ CHECK_SAME_SIZE(dest, src);
93
+ km_smat_each2_dcz(dest, src, func, NULL);
94
+ return op;
95
+ }
96
+ EOS
97
+ dz.each do |func|
98
+ f.puts <<"EOS"
99
+ static void
100
+ km_#{func}_z(COMPLEX *ent, void *null)
101
+ {
102
+ *ent = cpack(c#{func}(*ent), 0.0);
103
+ }
104
+ static void
105
+ km_#{func}_dcz(double *dest, const COMPLEX *src, void *null)
106
+ {
107
+ *dest = c#{func}(*src);
108
+ }
109
+ VALUE
110
+ kmm_mat_#{func}_destl(int argc, VALUE *argv, VALUE self)
111
+ {
112
+ rb_check_arity(argc, 0, 1);
113
+ if ( argc == 0 ) {
114
+ return km_zmat_e_funcapp(self, km_#{func}_z);
115
+ } else {
116
+ return km_zdmat_e_funcapp(self, argv[0], km_#{func}_dcz);
117
+ }
118
+ }
119
+ VALUE
120
+ kmm_mat_#{func}(VALUE self)
121
+ {
122
+ SMAT *smat = km_mat2smat(self);
123
+ return km_zdmat_e_funcapp(self, km_Mat(smat->m, smat->n, VT_DOUBLE), km_#{func}_dcz);
124
+ }
125
+ EOS
126
+ end
127
+ end
128
+
129
+ File.open('elementwise_function.h', 'w') do |f|
130
+ (both+fonly).each do |func|
131
+ f.puts "VALUE kmm_mat_#{func}_dest(VALUE self);"
132
+ end
133
+ dz.each do |func|
134
+ f.puts "VALUE kmm_mat_#{func}_destl(int argc, VALUE *argv, VALUE self);"
135
+ f.puts "VALUE kmm_mat_#{func}(VALUE self);"
136
+ end
137
+ end
138
+ File.open('elementwise_function_definitions.c', 'w') do |f|
139
+ f.puts "static void\nkm_define_efs(void)\n{"
140
+ (both+fonly).each do |func|
141
+ f.puts %Q|\trb_define_method(km_cMat, "#{func}!", kmm_mat_#{func}_dest, 0);|
142
+ f.puts %Q|\trb_funcall(km_cMat, id__define_dup_escaped_method, 1, rb_str_new_cstr("#{func}"));|
143
+ end
144
+ dz.each do |func|
145
+ f.puts %Q|\trb_define_method(km_cMat, "#{func}!", kmm_mat_#{func}_destl, -1);|
146
+ f.puts %Q|\trb_define_method(km_cMat, "#{func}", kmm_mat_#{func}, 0);|
147
+ end
148
+ f.puts "}"
149
+ end
@@ -0,0 +1,75 @@
1
+ require "mkmf"
2
+ require 'fileutils'
3
+
4
+ if find_library("mkl_rt", nil, "/opt/intel/mkl/lib/intel64")
5
+ puts "It is set to use Intel MKL for BLAS/LAPACK functions."
6
+ mkl = true
7
+ elsif have_library("blas") && have_library("lapack")
8
+ puts "It is set to use BLAS/LAPACK."
9
+ mkl = false
10
+ else
11
+ puts "Intel MKL or BLAS/LAPACK is neaded to build this library."
12
+ exit
13
+ end
14
+
15
+ $CFLAGS = "$(cflags) -std=c11"
16
+ $CFLAGS += " -m64" if mkl
17
+
18
+ #$warnflags = "-Wall -Wextra -Wdeprecated-declarations -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wwrite-strings -Wmissing-noreturn -Wno-unused-parameter -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wunused-variable -Wno-maybe-uninitialized -Winit-self -Wshadow"
19
+ $warnflags = "-Wall -Wextra -Wdeprecated-declarations -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wwrite-strings -Wmissing-noreturn -Wno-unused-parameter -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wunused-variable -Winit-self -Wshadow -Wlogical-op -Wconversion"
20
+
21
+ $DLDFLAGS += " -Wl,-Bsymbolic -fPIC"
22
+ $DLDFLAGS += " -Wl,--no-as-needed" if mkl
23
+
24
+
25
+ # set .c files in subdirectories as source
26
+ $objs = Dir.glob("#{__dir__}/**/*.c").map do |file|
27
+ file[-1] = 'o'
28
+ obj = %r|#{__dir__}/(.+)|.match(file)[1]
29
+ if m = %r|(.+)/[^/]+|.match(obj)
30
+ FileUtils.mkdir_p(m[1]) unless FileTest.exist?(m[1])
31
+ end
32
+ obj
33
+ end
34
+
35
+ srcs = $objs.map do |file|
36
+ file = file.dup
37
+ file[-1] = 'c'
38
+ "$(srcdir)/#{file}"
39
+ end
40
+
41
+ create_makefile("kmat/kmat")
42
+
43
+ # change variables after Makefile created
44
+ File.open('./__Makefile__temp__', 'w') do |f|
45
+ File.foreach('Makefile') do |line|
46
+ if ARGV.include?('debug')
47
+ line.sub!(/^optflags.+/, 'optflags = -O0')
48
+ else
49
+ line.sub!(/^debugflags.+/, 'debugflags =')
50
+ end
51
+ f.puts line
52
+ end
53
+ end
54
+ File.unlink('./Makefile')
55
+ FileUtils.move('./__Makefile__temp__', './Makefile')
56
+
57
+ # add dependencies
58
+ File.open('./Makefile', 'a') do |f|
59
+ f.puts "true_srcs = #{srcs.join(' ')}"
60
+
61
+ # invoke auto_collect.rb
62
+ f.puts "auto_collected.h: auto_collect.rb $(true_srcs)"
63
+ f.puts "\truby $(srcdir)/auto_collect.rb"
64
+
65
+ # invoke id_sym.rb
66
+ f.puts "id_sym.c id_sym.h: id_sym.rb id.txt sym.txt"
67
+ f.puts "\truby $(srcdir)/id_sym.rb"
68
+
69
+ # invoke elementwise_functions.rb
70
+ f.puts "elementwise_function.h: elementwise_function.rb"
71
+ f.puts "\truby $(srcdir)/elementwise_function.rb"
72
+
73
+ f.puts '$(OBJS): auto_collected.h id_sym.h elementwise_function.h'
74
+ f.puts 'main.o: id_sym.c'
75
+ end