rlsm 1.0.0 → 1.1.0

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.
@@ -1,24 +1,19 @@
1
1
  = rlsm
2
+ rlsm stands for *R*egular *L*anguages and *S*yntactic *M*onoids.
2
3
 
3
- http://www.github.com/asmodis/rlsm
4
+ Source is availible from
5
+ http://github.com/asmodis/rlsm
6
+
7
+ RDoc-Documentation is availible from
8
+ http://rlsm.rubyforge.org
4
9
 
5
10
  == DESCRIPTION:
6
11
 
7
12
  This is a ruby implementation of three concepts:
8
- - Deterministic Finite Automata (DFA)
13
+ - Deterministic Finite Automata
9
14
  - Regular Expressions (in the sense of theoretical computer sience)
10
- - Monoids (an algebraic construct)
11
-
12
-
13
- == FEATURES/PROBLEMS:
14
-
15
- It is possible to convert
16
- Monoid -> DFA
17
- DFA -> RegExp
18
- RegExp -> DFA
19
- DFA -> Monoid
15
+ - Monoids
20
16
 
21
- Also it is possible to ask a monoid for some properties.
22
17
 
23
18
  == SYNOPSIS:
24
19
 
@@ -29,24 +24,16 @@ Also it is possible to ask a monoid for some properties.
29
24
  m.isomorph_to?(m) # => true
30
25
  m.commutative? # => false
31
26
 
32
- == REQUIREMENTS:
33
-
34
- Depends on
35
- - sqlite3-ruby
36
-
37
27
  == INSTALL:
38
28
 
39
- Hopefully a
40
-
41
- sudo gem install rlsm
29
+ gem install rlsm
42
30
 
43
- is sufficent.
44
31
 
45
32
  == LICENSE:
46
33
 
47
34
  (The MIT License)
48
35
 
49
- Copyright (c) 2008 Gunther Diemant <g.diemant@gmx.net>
36
+ Copyright (c) 2009 Gunther Diemant <g.diemant@gmx.net>
50
37
 
51
38
  Permission is hereby granted, free of charge, to any person obtaining
52
39
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -1,12 +1,84 @@
1
1
  # -*- ruby -*-
2
2
 
3
- require 'rubygems'
4
- require 'hoe'
5
- require './lib/rlsm.rb'
3
+ require File.join(File.dirname(__FILE__), 'lib', 'rlsm')
6
4
 
7
- Hoe.new('rlsm', RLSM::VERSION) do |p|
8
- #p.rubyforge_name = 'rlsm' # if different than lowercase project name
9
- p.developer('asmodis', 'g.diemant@gmx.net')
5
+ task :build_ext do
6
+ Dir.chdir File.join(File.dirname(__FILE__), 'ext') do
7
+ Dir.foreach('.') do |extension|
8
+ Dir.chdir extension do
9
+ if File.exists? 'extconf.rb'
10
+ ruby 'extconf.rb'
11
+ sh "make"
12
+ end
13
+ end
14
+ end
15
+ end
10
16
  end
11
17
 
12
- # vim: syntax=Ruby
18
+ task :test => :build_ext do
19
+ Dir.chdir File.join(File.dirname(__FILE__), 'test') do
20
+ Dir.glob("test_*").each do |file|
21
+ ruby file
22
+ end
23
+ end
24
+ end
25
+
26
+ task :create_manifest do
27
+ Dir.chdir(File.dirname(__FILE__)) do
28
+ File.open("Manifest", 'w') do |manifest|
29
+ FileList['lib/**/*.rb', 'ext/**/*.c','ext/**/*.rb', 'test/**/*'].to_a.each do |file|
30
+ manifest.puts file
31
+ end
32
+
33
+ manifest.puts "Rakefile"
34
+ manifest.puts "README"
35
+ end
36
+ end
37
+ end
38
+
39
+ task :create_gemspec => :create_manifest do
40
+ Dir.chdir(File.dirname(__FILE__)) do
41
+ readme = File.open("README")
42
+ manifest = File.open("Manifest")
43
+ filelist = "[" + manifest.to_a.map { |line| "'#{line.chomp}'" }.join(", ") + "]"
44
+ manifest.close
45
+
46
+ readme_string = '<<DESCRIPTION' + "\n" + readme.to_a.join + "\nDESCRIPTION"
47
+ readme.close
48
+
49
+ File.open(".gemspec", 'w') do |gemspec|
50
+ gemspec.puts <<GEMSPEC
51
+ # -*- ruby -*-
52
+
53
+ require "rake"
54
+
55
+ Gem::Specification.new do |s|
56
+ s.author = "Gunther Diemant"
57
+ s.email = "g.diemant@gmx.net"
58
+ s.homepage = "http://github.com/asmodis/rlsm"
59
+ s.rubyforge_project = 'rlsm'
60
+
61
+ s.name = 'rlsm'
62
+ s.version = '#{RLSM::VERSION}'
63
+ s.add_development_dependency('minitest')
64
+ s.add_development_dependency('thoughtbot-shoulda')
65
+ s.summary = "Library for investigating regular languages and syntactic monoids."
66
+ s.description = #{readme_string}
67
+
68
+ s.files = #{filelist}
69
+ s.test_files = FileList['test/test_*.rb']
70
+ s.extensions = FileList['ext/**/extconf.rb']
71
+
72
+ s.has_rdoc = true
73
+ s.extra_rdoc_files = ['README']
74
+ s.rdoc_options << '--main' << 'README'
75
+ end
76
+ GEMSPEC
77
+ end
78
+ end
79
+ end
80
+
81
+ task :create_gem => :create_gemspec do
82
+ sh "gem build .gemspec"
83
+ sh "mv *.gem gem/"
84
+ end
@@ -0,0 +1,137 @@
1
+ #include <ruby.h>
2
+
3
+ static int
4
+ c_subset_next(int* sub, int n, int k) {
5
+ int i = k - 1;
6
+
7
+ while(i >= 0 && sub[i] == n-k+i) { i--; }
8
+
9
+ if (i < 0)
10
+ return -1;
11
+
12
+ int j;
13
+ int sub_i = sub[i];
14
+ for (j=i; j < k; ++j) {
15
+ sub[j] = sub_i + 1 + j - i;
16
+ }
17
+
18
+ return 0;
19
+ }
20
+
21
+ static int
22
+ c_next_perm(int* perm, int n) {
23
+ int i = n-2;
24
+ while (i >= -1 && perm[i+1] < perm[i]) { i--; }
25
+ if ( i < 0 ) { return -1; }
26
+
27
+ int j = n-1;
28
+ while ( perm[j] < perm[i] ) { j--; }
29
+
30
+ int temp = perm[i];
31
+ perm[i] = perm[j];
32
+ perm[j] = temp;
33
+
34
+ int* tmp = (int*) ALLOCA_N(int, n);
35
+
36
+ int k;
37
+ for (k=0; k < n; ++k) { tmp[k] = perm[k]; }
38
+
39
+ for (k = i+1; k < n; ++k) {
40
+ perm[k] = tmp[n+i-k];
41
+ }
42
+
43
+ return 0;
44
+ }
45
+
46
+ static VALUE
47
+ ary2ruby(int* subset, int k, VALUE ary) {
48
+ VALUE result = rb_ary_new2(k);
49
+ int i;
50
+
51
+ for (i=0; i < k; ++i) {
52
+ rb_ary_store(result, i, RARRAY(ary)->ptr[subset[i]]);
53
+ }
54
+
55
+ return result;
56
+ }
57
+
58
+ static VALUE
59
+ powerset(VALUE self) {
60
+ int k;
61
+ int n = RARRAY(self)->len;
62
+ if (!rb_block_given_p()) {
63
+ VALUE result = rb_ary_new();
64
+ for (k=0; k <= n; ++k) {
65
+ int i,res;
66
+ int* subset = ALLOCA_N(int, k);
67
+ for (i=0; i < k; ++i) { subset[i] = i; }
68
+
69
+ while(1) {
70
+ rb_ary_push(result, ary2ruby(subset,k,self));
71
+ res = c_subset_next(subset, n, k);
72
+ if (res == -1)
73
+ break;
74
+ }
75
+ }
76
+ return result;
77
+ }
78
+ else {
79
+ for (k=0; k <= n; ++k) {
80
+ int i,res;
81
+ int* subset = ALLOCA_N(int, k);
82
+ for (i=0; i < k; ++i) { subset[i] = i; }
83
+
84
+ while(1) {
85
+ rb_yield(ary2ruby(subset,k,self));
86
+ res = c_subset_next(subset, n, k);
87
+ if (res == -1)
88
+ break;
89
+ }
90
+ }
91
+
92
+ return Qnil;
93
+ }
94
+ }
95
+
96
+ static VALUE
97
+ permutations(VALUE self) {
98
+ int res;
99
+ int n = RARRAY(self)->len;
100
+ int* perm = (int*) ALLOCA_N(int, n);
101
+ int t;
102
+ for (t=0; t < n; ++t) { perm[t] = t; }
103
+
104
+ if (rb_block_given_p()) {
105
+ while(1) {
106
+ rb_yield(ary2ruby(perm, n, self));
107
+ res = c_next_perm(perm, n);
108
+ if (res == -1)
109
+ break;
110
+ }
111
+ }
112
+ else {
113
+ VALUE result = rb_ary_new();
114
+ while(1) {
115
+ rb_ary_push(result,ary2ruby(perm, n, self));
116
+ res = c_next_perm(perm, n);
117
+ if (res == -1)
118
+ break;
119
+ }
120
+
121
+ return result;
122
+ }
123
+
124
+ return Qnil;
125
+ }
126
+
127
+ #ifdef __cplusplus
128
+ extern "C" {
129
+ #endif
130
+ void Init_array_cext() {
131
+ VALUE ary = rb_const_get(rb_cObject, rb_intern("Array"));
132
+ rb_define_method(ary, "powerset", (VALUE(*)(ANYARGS))powerset, 0);
133
+ rb_define_method(ary, "permutations", (VALUE(*)(ANYARGS))permutations, 0);
134
+ }
135
+ #ifdef __cplusplus
136
+ }
137
+ #endif
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile('array_cext')
@@ -0,0 +1,57 @@
1
+ #include <ruby.h>
2
+
3
+
4
+ static VALUE
5
+ non_associative_triple(VALUE self) {
6
+ VALUE table = rb_iv_get(self, "@table");
7
+ VALUE max = NUM2INT(rb_iv_get(self, "@order"));
8
+ VALUE base = rb_iv_get(self, "@elements");
9
+
10
+ int i,j,k;
11
+ for (i=0; i < max; ++i) {
12
+ for (j=0; j < max; ++j) {
13
+ for (k=0; k < max; ++k) {
14
+ int ij,jk, i_jk, ij_k;
15
+ ij = NUM2INT(RARRAY(table)->ptr[max*i + j]);
16
+ jk = NUM2INT(RARRAY(table)->ptr[max*j + k]);
17
+ i_jk = NUM2INT(RARRAY(table)->ptr[max*i + jk]);
18
+ ij_k = NUM2INT(RARRAY(table)->ptr[max*ij + k]);
19
+ if (ij_k != i_jk) {
20
+ return (rb_ary_new3(3,RARRAY(base)->ptr[i],RARRAY(base)->ptr[j],RARRAY(base)->ptr[k]));
21
+ }
22
+ }
23
+ }
24
+ }
25
+
26
+ return (Qnil);
27
+ }
28
+
29
+ static VALUE
30
+ is_commutative(VALUE self) {
31
+ VALUE table = rb_iv_get(self, "@table");
32
+ VALUE max = NUM2INT(rb_iv_get(self, "@order"));
33
+
34
+ int i,j;
35
+ for (i=0; i < max; ++i) {
36
+ for (j=0; j < max; ++j) {
37
+ if (NUM2INT(RARRAY(table)->ptr[max*i + j]) != NUM2INT(RARRAY(table)->ptr[max*j + i]))
38
+ return (Qfalse);
39
+ }
40
+ }
41
+
42
+ return (Qtrue);
43
+ }
44
+
45
+ #ifdef __cplusplus
46
+ extern "C" {
47
+ #endif
48
+ void Init_binop_cext() {
49
+ VALUE rlsm = rb_define_module("RLSM");
50
+ VALUE binop = rb_define_class_under(rlsm, "BinaryOperation", rb_cObject);
51
+
52
+ rb_define_private_method(binop, "is_commutative", (VALUE(*)(ANYARGS))is_commutative, 0);
53
+ rb_define_private_method(binop, "non_associative_triple", (VALUE(*)(ANYARGS))non_associative_triple, 0);
54
+ }
55
+ #ifdef __cplusplus
56
+ }
57
+ #endif
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile('binop_cext')
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile('monoid_cext')
@@ -0,0 +1,330 @@
1
+ #include <ruby.h>
2
+
3
+ typedef int bool;
4
+
5
+ static int
6
+ mi_index(VALUE ary, int index) {
7
+ int i;
8
+ for (i=0; i < RARRAY(ary)->len; ++i) {
9
+ if (NUM2INT(RARRAY(ary)->ptr[i]) == index) { return i; }
10
+ }
11
+
12
+ return -1;
13
+ }
14
+
15
+ static int*
16
+ mi_new_ary(int length, int val) {
17
+ int* result = (int*) calloc(length, sizeof(int));
18
+ int i;
19
+ for (i=0; i < length; ++i) { result[i] = val; }
20
+
21
+ return result;
22
+ }
23
+
24
+ static VALUE mi_ary2rb(const int* ary, int length) {
25
+ VALUE result = rb_ary_new2(length);
26
+ int i;
27
+ for (i=0; i < length; ++i) { rb_ary_store(result, i, INT2NUM(ary[i])); }
28
+
29
+ return result;
30
+ }
31
+
32
+ static int*
33
+ mi_helper_init_table(VALUE diagonal, int order) {
34
+ int* result = (int*) calloc(order*order, sizeof(int));
35
+
36
+ int i;
37
+ for (i = 0; i < order*order; ++i) {
38
+ if (i < order)
39
+ result[i] = i;
40
+ else if (i % order == 0)
41
+ result[i] = i / order;
42
+ else if (i % order == i / order)
43
+ result[i] = NUM2INT(RARRAY(diagonal)->ptr[i / order]);
44
+ else
45
+ result[i] = 0;
46
+ }
47
+
48
+ return result;
49
+ }
50
+
51
+ static bool
52
+ mi_is_perm_stable(VALUE diagonal, VALUE perm) {
53
+ int i;
54
+ for (i=0; i < RARRAY(diagonal)->len; ++i) {
55
+ int a = NUM2INT(RARRAY(diagonal)->ptr[i]);
56
+ int b = NUM2INT(RARRAY(perm)->ptr[NUM2INT(RARRAY(diagonal)->ptr[mi_index(perm, i)])]);
57
+
58
+ if ( a != b)
59
+ return 0;
60
+ }
61
+
62
+ return 1;
63
+ }
64
+
65
+ static bool
66
+ mi_is_invertable(VALUE diag, int index) {
67
+ int i, pot = NUM2INT(RARRAY(diag)->ptr[index]);
68
+
69
+ for (i=0; i < RARRAY(diag)->len; ++i) {
70
+ if (pot == 0) { return 1; }
71
+ pot = NUM2INT(RARRAY(diag)->ptr[pot]);
72
+ }
73
+
74
+ return 0;
75
+ }
76
+
77
+ static VALUE
78
+ mi_helper_select_perms(VALUE diagonal, VALUE perms, int order) {
79
+ VALUE result = rb_ary_new();
80
+ VALUE perm;
81
+ int i;
82
+ for (i=0; i < RARRAY(perms)->len; ++i) {
83
+ perm = RARRAY(perms)->ptr[i];
84
+ if (mi_is_perm_stable(diagonal, perm))
85
+ rb_ary_push(result, perm);
86
+ }
87
+
88
+ return result;
89
+ }
90
+
91
+ static int*
92
+ mi_helper_rc_restrictions(VALUE diagonal, int order) {
93
+ int* result = (int*) calloc(order, sizeof(int));
94
+ result[0] = 1;
95
+
96
+ int i;
97
+ for (i=1; i < order; ++i) {
98
+ result[i] = 1;
99
+ if (NUM2INT(RARRAY(diagonal)->ptr[i]) == i)
100
+ result[i] *= 2; /* idempotent */
101
+ if (mi_is_invertable(diagonal, i))
102
+ result[i] *= 3; /* invertible */
103
+ }
104
+
105
+ return result;
106
+ }
107
+
108
+ static bool
109
+ mi_is_diagonal_valid(int* diagonal, int ord, VALUE perms) {
110
+ int i,j;
111
+ VALUE perm;
112
+ for (i=0; i < RARRAY(perms)->len; ++i) {
113
+ perm = RARRAY(perms)->ptr[i];
114
+
115
+ for (j=0; j < ord; ++j) {
116
+ int ii, pdii;
117
+ ii = mi_index(perm, j);
118
+ if (diagonal[ii] == -1) { break; }
119
+
120
+ pdii = NUM2INT(RARRAY(perm)->ptr[diagonal[ii]]);
121
+ if (diagonal[j] < pdii) { break; }
122
+ if (diagonal[j] > pdii) { return 0; }
123
+ }
124
+ }
125
+
126
+ return 1;
127
+ }
128
+
129
+
130
+ static bool
131
+ mi_is_associative(const int* table, int order) {
132
+ int x1,x2,x3;
133
+ for (x1=1; x1 < order; ++x1) {
134
+ for (x2=1; x2 < order; ++x2) {
135
+ for (x3=1; x3 < order; ++x3) {
136
+ int x1x2, x2x3, x1_x2x3, x1x2_x3;
137
+
138
+ x1x2 = table[order*x1 + x2];
139
+ if (x1x2 == -1) { break; }
140
+
141
+ x2x3 = table[order*x2 + x3];
142
+ if (x2x3 == -1) { break; }
143
+
144
+ x1x2_x3 = table[order*x1x2 + x3];
145
+ if (x1x2_x3 == -1) { break; }
146
+
147
+ x1_x2x3 = table[order*x1 + x2x3];
148
+ if (x1_x2x3 == -1) { break; }
149
+
150
+ if (x1_x2x3 != x1x2_x3)
151
+ return 0;
152
+ }
153
+ }
154
+ }
155
+
156
+ return 1;
157
+ }
158
+
159
+ static bool
160
+ mi_is_iso_antiiso(const int* table, int order, VALUE perms) {
161
+ int p,i;
162
+ int max_index = order*order;
163
+ VALUE perm;
164
+
165
+ for (p = 0; p < RARRAY(perms)->len; ++p) {
166
+ int smaller_iso = 0, smaller_aiso = 0;
167
+ perm = RARRAY(perms)->ptr[p];
168
+ for (i = order+1; i < max_index; ++i) {
169
+ int ix1, ix2, ti, tii, taii, ptii, ptaii;
170
+ ix1 = mi_index(perm, i / order);
171
+ ix2 = mi_index(perm, i % order);
172
+
173
+ ti = table[i];
174
+ tii = table[order*ix1 + ix2];
175
+ taii = table[order*ix2 + ix1];
176
+
177
+ if (ti == -1 || tii == -1 || taii == -1 )
178
+ break;
179
+
180
+ ptii = NUM2INT(RARRAY(perm)->ptr[tii]);
181
+ ptaii = NUM2INT(RARRAY(perm)->ptr[taii]);
182
+
183
+ if (ti < ptii)
184
+ smaller_iso = 1;
185
+
186
+ if (ti < ptaii)
187
+ smaller_aiso = 1;
188
+
189
+ if (smaller_iso == 1 && smaller_aiso == 1)
190
+ break;
191
+
192
+ if ((smaller_iso == 0 && ti > ptii) || (smaller_aiso == 0 && ti > ptaii))
193
+ return 0;
194
+ }
195
+ }
196
+
197
+ return 1;
198
+ }
199
+
200
+ static bool
201
+ mi_is_rc_rest_satisfied(const int* table, int order, const int* rc_rest) {
202
+ int i,j,k;
203
+ for (i=1; i < order; ++i) {
204
+ if (rc_rest[i] != 1) {
205
+ if (rc_rest[i] % 2 == 0) {
206
+ for (j=1; j < order; ++j) {
207
+ if (table[order*i + j] == 0 || table[order*j + i] == 0)
208
+ return 0;
209
+ }
210
+ }
211
+
212
+ if (rc_rest[i] % 3 == 0) {
213
+ for (j=0; j < order; ++j) {
214
+ for (k=j+1; k < order; ++k) {
215
+ if (table[order*i + j] != -1 && table[order*i + j] == table[order*i + k] )
216
+ return 0;
217
+ if (table[order*j + i] != -1 && table[order*j + i] == table[order*k + i])
218
+ return 0;
219
+
220
+ }
221
+ }
222
+ }
223
+ }
224
+ }
225
+
226
+ return 1;
227
+ }
228
+
229
+ static bool
230
+ mi_table_valid(const int* table, int order, const int* rc_rest, VALUE perms) {
231
+ if (!mi_is_rc_rest_satisfied(table, order, rc_rest))
232
+ return 0;
233
+
234
+ if (!mi_is_associative(table, order))
235
+ return 0;
236
+
237
+ if (!mi_is_iso_antiiso(table, order, perms))
238
+ return 0;
239
+
240
+ return 1;
241
+ }
242
+
243
+
244
+ static VALUE
245
+ each_diagonal(VALUE self, VALUE rorder, VALUE perms) {
246
+ rb_need_block();
247
+
248
+ int order = NUM2INT(rorder);
249
+ int* diagonal = mi_new_ary(order, 0);
250
+ rb_yield(mi_ary2rb(diagonal, order));
251
+
252
+ int index = order - 1;
253
+ while(1) {
254
+ diagonal[index]++;
255
+ if (diagonal[index] >= order) {
256
+ if (index == 1) { return; } /* finished */
257
+ diagonal[index] = -1;
258
+ index--;
259
+ }
260
+ else if (mi_is_diagonal_valid(diagonal, order, perms)) {
261
+ if (index == order -1)
262
+ rb_yield(mi_ary2rb(diagonal, order));
263
+ else
264
+ index++;
265
+ }
266
+ }
267
+
268
+ return Qnil;
269
+ }
270
+
271
+ static VALUE
272
+ e_w_diagonal(VALUE self, VALUE diagonal, VALUE perms) {
273
+ int order = RARRAY(diagonal)->len, t_order = order*order;
274
+ int* table = mi_helper_init_table(diagonal, order);
275
+ VALUE rperms = mi_helper_select_perms(diagonal, perms, order);
276
+ int* rc_rest = mi_helper_rc_restrictions(diagonal, order);
277
+
278
+ if (mi_table_valid(table, order, rc_rest, rperms)) { rb_yield(mi_ary2rb(table, t_order)); }
279
+
280
+ int index = t_order - 2;
281
+ while (1) {
282
+ table[index]++;
283
+ if (table[index] >= order) {
284
+ if (index <= order + 2) { return; } /* finished */
285
+ table[index] = -1;
286
+ index--;
287
+ /* skip diagonal and first column */
288
+ if ((index % order == index / order) || (index % order == 0))
289
+ index--;
290
+ }
291
+ else if (mi_table_valid(table, order, rc_rest, rperms)) {
292
+ if (index == t_order - 2)
293
+ rb_yield(mi_ary2rb(table, t_order));
294
+ else {
295
+ index++;
296
+ /* skip diagonal and first column */
297
+ if ((index % order == index / order) || (index % order == 0))
298
+ index++;
299
+ }
300
+ }
301
+ }
302
+
303
+ return Qnil;
304
+ }
305
+
306
+ static VALUE
307
+ e_pos(VALUE self, VALUE table, VALUE rorder) {
308
+ int i, order = NUM2INT(rorder);
309
+ for(i=0; i < order; ++i) {
310
+ if (NUM2INT(RARRAY(table)->ptr[i]) != i || NUM2INT(RARRAY(table)->ptr[order*i]) != i) {
311
+ rb_raise(rb_const_get(rb_cObject, rb_intern("MonoidError")), "Neutral element isn't in first row.");
312
+ }
313
+ }
314
+
315
+ return Qnil;
316
+ }
317
+
318
+ #ifdef __cplusplus
319
+ extern "C" {
320
+ #endif
321
+ void Init_monoid_cext() {
322
+ VALUE rlsm = rb_define_module("RLSM");
323
+ VALUE monoid = rb_define_class_under(rlsm, "Monoid", rb_cObject);
324
+ rb_define_singleton_method(monoid, "each_diagonal", (VALUE(*)(ANYARGS))each_diagonal, 2);
325
+ rb_define_singleton_method(monoid, "each_with_diagonal", (VALUE(*)(ANYARGS))e_w_diagonal, 2);
326
+ rb_define_singleton_method(monoid, "enforce_identity_position", (VALUE(*)(ANYARGS))e_pos, 2);
327
+ }
328
+ #ifdef __cplusplus
329
+ }
330
+ #endif