1########################################################################
2##
3## Copyright (C) 2003-2021 The Octave Project Developers
4##
5## See the file COPYRIGHT.md in the top-level directory of this
6## distribution or <https://octave.org/copyright/>.
7##
8## This file is part of Octave.
9##
10## Octave is free software: you can redistribute it and/or modify it
11## under the terms of the GNU General Public License as published by
12## the Free Software Foundation, either version 3 of the License, or
13## (at your option) any later version.
14##
15## Octave is distributed in the hope that it will be useful, but
16## WITHOUT ANY WARRANTY; without even the implied warranty of
17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18## GNU General Public License for more details.
19##
20## You should have received a copy of the GNU General Public License
21## along with Octave; see the file COPYING.  If not, see
22## <https://www.gnu.org/licenses/>.
23##
24########################################################################
25
26BEGIN {
27  declare_types = 0;
28  generate_ops = 0;
29  op_class = "";
30  sparse = 0;
31  ntypes = 0;
32  make_inclusive_header = 0;
33  make_header = 0;
34  make_source = 0;
35
36  if (build_file)
37    {
38      if (build_file == "mx-ops.h" || build_file == "smx-ops.h" || build_file == "vx-ops.h")
39        {
40          make_inclusive_header = 1;
41
42          print "// DO NOT EDIT -- generated by mk-ops.awk";
43          tmp = build_file;
44          prefix = substr (tmp, 1, index (tmp, "-")-1);
45          gsub (/[\.-]/, "_", tmp);
46          printf ("#if ! defined (octave_%s)\n", tmp);
47          printf ("#define octave_%s 1\n", tmp);
48          print "#include \"octave-config.h\"";
49        }
50      else
51        {
52          if (match (build_file, /\.h$/))
53            {
54              make_header = 1;
55
56              tmp = substr (build_file, 1, length (build_file)-2);
57            }
58          else if (match (build_file, /\.cc$/))
59            {
60              make_source = 1;
61
62              tmp = substr (build_file, 1, length (build_file)-3);
63            }
64
65          prefix = substr (tmp, 1, index (tmp, "-")-1);
66          tmp = substr (tmp, index (tmp, "-")+1);
67          lhs_arg = substr (tmp, 1, index (tmp, "-")-1);
68          rhs_arg = substr (tmp, index (tmp, "-")+1);
69        }
70    }
71}
72/^#/ {
73  if ($2 == "types")
74    declare_types = 1;
75  else if ($3 == "operators")
76    {
77      op_class = $2;
78      generate_ops = 1;
79      declare_types = 0;
80
81      if (op_class == "vector")
82        sparse = 0;
83      else if (op_class == "full-matrix")
84        sparse = 0;
85      else if (op_class == "sparse-matrix")
86        sparse = 1;
87      else
88        {
89          printf ("unrecognized object type: %s", op_class);
90          exit (1);
91        }
92    }
93  next;
94} {
95  if (declare_types)
96    {
97      ntypes++;
98
99      if (NF == 5 || NF == 6)
100        {
101          if (NF == 6)
102            core_type[ntypes] = $6;
103
104          fwd_decl_ok[ntypes] = $5 == "YES";
105          header[ntypes] = $4 == "NONE" ? "" : $4;
106          class[ntypes] = $3;
107          type[ntypes] = $2;
108          tag[ntypes] = $1;
109          rev_tag[$1] = ntypes;
110        }
111      else
112        printf ("skipping line %d: %s\n", NR, $0);
113    }
114  else if (generate_ops)
115    {
116      if (NF >= 4 || (sparse && NF >= 5))
117        {
118          n = 0;
119
120          result_tag_1 = $(++n);
121          if (sparse)
122            result_tag_2 = $(++n);
123          lhs_tag = $(++n);
124          rhs_tag = $(++n);
125          op_type = $(++n);
126
127          bin_ops = index (op_type, "B") != 0;
128          cmp_ops = index (op_type, "C") != 0;
129          eqne_ops = index (op_type, "E") != 0;
130          bool_ops = index (op_type, "L") != 0;
131
132          k = 0
133          while (NF > n)
134            bool_headers[k++] = $(++n);
135
136          cc_file = sprintf ("%s-%s-%s.cc", prefix, lhs_tag, rhs_tag);
137          h_file = sprintf ("%s-%s-%s.h", prefix, lhs_tag, rhs_tag);
138
139          if (list_cc_files)
140            {
141              printf (" liboctave/operators/%s", cc_file);
142              next;
143            }
144
145          if (list_h_files)
146            {
147              printf (" liboctave/operators/%s", h_file);
148              next;
149            }
150
151          if (make_inclusive_header)
152            {
153              printf ("#include \"%s\"\n", h_file);
154              next;
155            }
156
157          if (lhs_arg != lhs_tag || rhs_arg != rhs_tag)
158            next;
159
160          h_guard = sprintf ("octave_%s_%s_%s_h", prefix, lhs_tag, rhs_tag);
161
162          result_num_1 = rev_tag[result_tag_1];
163          if (sparse)
164            result_num_2 = rev_tag[result_tag_2];
165          lhs_num = rev_tag[lhs_tag];
166          rhs_num = rev_tag[rhs_tag];
167
168          result_type_1 = type[result_num_1];
169          if (sparse)
170            result_type_2 = type[result_num_2];
171          lhs_type = type[lhs_num];
172          rhs_type = type[rhs_num];
173
174          lhs_core_type = core_type[lhs_num];
175          rhs_core_type = core_type[rhs_num];
176
177          result_header_1 = header[result_num_1];
178          if (sparse)
179            result_header_2 = header[result_num_2];
180          lhs_header = header[lhs_num];
181          rhs_header = header[rhs_num];
182
183          lhs_class = class[lhs_num];
184          rhs_class = class[rhs_num];
185
186          if (make_header)
187            {
188              print "// DO NOT EDIT -- generated by mk-ops.awk";
189
190              printf ("#if ! defined (%s)\n", h_guard);
191              printf ("#define %s 1\n", h_guard);
192              print "#include \"octave-config.h\"";
193
194              if (result_header_1)
195                {
196                  if (result_fwd_decl_ok)
197                    printf ("class %s\n", result_type_1);
198                  else
199                    printf ("#include \"%s\"\n", result_header_1);
200                }
201
202              if (result_header_2 && ! (result_header_2 == result_header_1))
203                {
204                  if (result_fwd_decl_ok)
205                    printf ("class %s\n", result_type_2);
206                  else
207                    printf ("#include \"%s\"\n", result_header_2);
208                }
209
210              if (lhs_header && ! (lhs_header == result_header_1 || lhs_header == result_header_2))
211                {
212                  if (result_fwd_decl_ok)
213                    printf ("class %s\n", lhs_type);
214                  else
215                    printf ("#include \"%s\"\n", lhs_header);
216                }
217
218              if (rhs_header && ! (rhs_header == lhs_header || rhs_header == result_header_1 || rhs_header == result_header_2))
219                {
220                  if (result_fwd_decl_ok)
221                    printf ("class %s\n", rhs_type);
222                  else
223                    printf ("#include \"%s\"\n", rhs_header);
224                }
225
226              if (sparse)
227                {
228                  lhs_is_sparse = 0;
229                  rhs_is_sparse = 0;
230
231                  xlhs_tag = "NONE";
232                  xrhs_tag = "NONE";
233
234                  if (lhs_tag == "sbm")
235                    {
236                      lhs_is_sparse = 1;
237                      xlhs_tag = "b";
238                    }
239                  else if (lhs_tag == "scm")
240                    {
241                      lhs_is_sparse = 1;
242                      xlhs_tag = "cs";
243                    }
244                  else if (lhs_tag == "sm")
245                    {
246                      lhs_is_sparse = 1;
247                      xlhs_tag = "s";
248                    }
249                  else if (lhs_tag == "bm" || lhs_tag == "cm" || lhs_tag == "m")
250                    xlhs_tag = lhs_tag;
251
252                  if (rhs_tag == "sbm")
253                    {
254                      rhs_is_sparse = 1;
255                      xrhs_tag = "b";
256                    }
257                  else if (rhs_tag == "scm")
258                    {
259                      rhs_is_sparse = 1;
260                      xrhs_tag = "cs";
261                    }
262                  else if (rhs_tag == "sm")
263                    {
264                      rhs_is_sparse = 1;
265                      xrhs_tag = "s";
266                    }
267                  else if (rhs_tag == "bm" || rhs_tag == "cm" || rhs_tag == "m")
268                    xrhs_tag = rhs_tag;
269
270                  same_types = ((xlhs_tag == "b" && xrhs_tag == "bm") || (xlhs_tag == "cs" && xrhs_tag == "cm") || (xlhs_tag == "s" && xrhs_tag == "m") || (xlhs_tag == "bm" && xrhs_tag == "b") || (xlhs_tag == "cm" && xrhs_tag == "cs") || (xlhs_tag == "m" && xrhs_tag == "s"));
271
272                  if (! (same_types || (rhs_is_sparse && lhs_is_sparse) || xlhs_tag == "NONE" || xrhs_tag == "NONE"))
273                    {
274                      printf ("#include \"mx-%s-%s.h\"\n", xlhs_tag, xrhs_tag);
275                      printf ("#include \"mx-%s-%s.h\"\n", xrhs_tag, xlhs_tag);
276
277                      xxlhs_tag = xlhs_tag;
278                      xxrhs_tag = xrhs_tag;
279
280                      if (xxlhs_tag == "cs")
281                        xxlhs_tag = "cm";
282                      else if (xxlhs_tag == "s")
283                        xxlhs_tag = "m";
284                      else if (xxlhs_tag == "b")
285                        xxlhs_tag = "NONE";
286
287                      if (xxrhs_tag == "cs")
288                        xxrhs_tag = "cm";
289                      else if (xxrhs_tag == "s")
290                        xxrhs_tag = "m";
291                      else if (xxrhs_tag == "b")
292                        xxrhs_tag = "NONE";
293
294                      if (! (xxlhs_tag == "NONE" || xxrhs_tag == "NONE" || xxlhs_tag == xxrhs_tag))
295                        {
296                          printf ("#include \"mx-%s-%s.h\"\n", xxlhs_tag, xxrhs_tag);
297                          printf ("#include \"mx-%s-%s.h\"\n", xxrhs_tag, xxlhs_tag);
298                        }
299
300                      xxlhs_tag = xlhs_tag;
301                      xxrhs_tag = xrhs_tag;
302
303                      if (xxlhs_tag == "m")
304                        xxlhs_tag = "nda";
305                      else if (xxlhs_tag == "cm")
306                        xxlhs_tag = "cnda";
307                      else if (xxlhs_tag == "bm")
308                        xxlhs_tag = "NONE";
309
310                      if (xxrhs_tag == "m")
311                        xxrhs_tag = "nda";
312                      else if (xxrhs_tag == "cm")
313                        xxrhs_tag = "cnda";
314                      else if (xxrhs_tag == "bm")
315                        xxrhs_tag = "NONE";
316
317                      if (! (xxlhs_tag == "NONE" || xxrhs_tag == "NONE"))
318                        {
319                          printf ("#include \"mx-%s-%s.h\"\n", xxlhs_tag, xxrhs_tag);
320                          printf ("#include \"mx-%s-%s.h\"\n", xxrhs_tag, xxlhs_tag);
321                        }
322                    }
323
324                  printf ("#include \"Sparse-op-defs.h\"\n");
325                }
326
327              if (bin_ops)
328                emit_bin_op_decls(sparse, lhs_class, rhs_class,
329                                  result_type_1, result_type_2,
330                                  lhs_type, rhs_type);
331
332              if (cmp_ops)
333                emit_cmp_op_decls(sparse, lhs_class, rhs_class,
334                                  lhs_type, rhs_type);
335
336              if (eqne_ops)
337                emit_eqne_op_decls(sparse, lhs_class, rhs_class,
338                                   lhs_type, rhs_type);
339
340              if (bool_ops)
341                emit_bool_op_decls(sparse, lhs_class, rhs_class,
342                                   lhs_type, rhs_type);
343
344              print "#endif";
345
346              exit (0);
347            }
348          else if (make_source)
349            {
350              print "// DO NOT EDIT -- generated by mk-ops.awk";
351
352              print "#if defined (HAVE_CONFIG_H)";
353              print "#  include \"config.h\"";
354              print "#endif";
355
356              print "#include \"Array-util.h\"";
357
358              printf ("#include \"%s\"\n", h_file);
359
360              if (! sparse)
361                printf ("#include \"mx-op-defs.h\"\n");
362
363              for (i in bool_headers)
364                {
365                  printf ("#include \"%s\"\n", bool_headers[i]);
366                  delete bool_headers[i];
367                }
368
369              if (result_header_1)
370                printf ("#include \"%s\"\n", result_header_1);
371
372              if (result_header_2 && ! (result_header_2 == result_header_1))
373                printf ("#include \"%s\"\n", result_header_2);
374
375              if (lhs_header && ! (lhs_header == result_header_1 || lhs_header == result_header_2))
376                printf ("#include \"%s\"\n", lhs_header);
377
378              if (rhs_header && ! (rhs_header == lhs_header || rhs_header == result_header_1 || rhs_header == result_header_2))
379                printf ("#include \"%s\"\n", rhs_header);
380
381              if (bin_ops)
382                emit_bin_ops(sparse, lhs_class, rhs_class,
383                             result_type_1, result_type_2, lhs_type, rhs_type);
384
385              if (cmp_ops)
386                emit_cmp_ops(sparse, lhs_class, rhs_class, lhs_type, rhs_type);
387
388              if (eqne_ops)
389                emit_eqne_ops(sparse, lhs_class, rhs_class,
390                              lhs_type, rhs_type);
391
392              if (bool_ops)
393                emit_bool_ops(sparse, lhs_class, rhs_class,
394                              lhs_type, rhs_type);
395
396              exit (0);
397            }
398        }
399      else
400        printf ("skipping line %d: %s\n", NR, $0);
401    }
402}
403END {
404  if (make_inclusive_header)
405    print "#endif";
406}
407
408function emit_bin_op_decl (result_type, operator, lhs_type, rhs_type)
409{
410  if (operator != "")
411    printf ("  extern OCTAVE_API %s %s (const %s&, const %s&);\n",
412            result_type, operator, lhs_type, rhs_type);
413}
414
415function emit_bin_op_decls_1 (result_type, lhs_type, rhs_type,
416                              add_op, sub_op, mul_op, div_op)
417{
418  emit_bin_op_decl(result_type, add_op, lhs_type, rhs_type);
419  emit_bin_op_decl(result_type, sub_op, lhs_type, rhs_type);
420  emit_bin_op_decl(result_type, mul_op, lhs_type, rhs_type);
421  emit_bin_op_decl(result_type, div_op, lhs_type, rhs_type);
422}
423
424function emit_sparse_bin_op_decls (result_type_1, result_type_2,
425                                   lhs_type, rhs_type,
426                                   add_op, sub_op, mul_op, div_op)
427{
428  emit_bin_op_decl(result_type_1, add_op, lhs_type, rhs_type);
429  emit_bin_op_decl(result_type_1, sub_op, lhs_type, rhs_type);
430  emit_bin_op_decl(result_type_2, mul_op, lhs_type, rhs_type);
431  emit_bin_op_decl(result_type_2, div_op, lhs_type, rhs_type);
432}
433
434function emit_bin_op_decls (sparse, lhs_class, rhs_class,
435                            result_type_1, result_type_2,
436                            lhs_type, rhs_type)
437{
438  if (sparse)
439    {
440      if ((lhs_class == "SM" && rhs_class == "S") \
441          || (lhs_class == "S" && rhs_class == "SM"))
442        emit_sparse_bin_op_decls(result_type_1, result_type_2,
443                                 lhs_type, rhs_type,
444                                 "operator +", "operator -",
445                                 "operator *", "operator /");
446
447      else if ((lhs_class == "M" && rhs_class == "SM")    \
448               || (lhs_class == "SM" && rhs_class == "M") \
449               || (lhs_class == "SM" && rhs_class == "SM"))
450        emit_sparse_bin_op_decls(result_type_1, result_type_2,
451                                 lhs_type, rhs_type,
452                                 "operator +", "operator -",
453                                 "product", "quotient");
454    }
455  else
456    {
457      if ((lhs_class == "M" && rhs_class == "S") \
458          || (lhs_class == "ND" && rhs_class == "S") \
459          || (lhs_class == "S" \
460              && (rhs_class == "M" || rhs_class == "ND" || rhs_class == "V")) \
461          || (lhs_class == "V" && rhs_class == "S"))
462        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,
463                            "operator +", "operator -",
464                            "operator *", "operator /");
465
466      else if ((lhs_class == "M" && rhs_class == "M")      \
467               || (lhs_class == "ND" && rhs_class == "ND") \
468               || (lhs_class == "V" && rhs_class == "V"))
469        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,
470                            "operator +", "operator -",
471                            "product", "quotient");
472
473      else if ((lhs_class == "DM" && rhs_class == "M")  \
474          || (lhs_class == "M" && rhs_class == "DM"))
475        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,
476                            "operator +", "operator -", "operator *", "");
477
478      else if (lhs_class == "DM" && rhs_class == "DM")
479        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,
480                            "operator +", "operator -", "product", "");
481
482      else if (lhs_class == "DM" && rhs_class == "S")
483        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,
484                            "", "", "operator *", "operator /");
485
486      else if ((lhs_class == "M" && rhs_class == "PM") \
487               || (lhs_class == "PM" && rhs_class == "M") \
488               || (lhs_class == "S" && rhs_class == "DM"))
489        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,
490                            "", "", "operator *", "");
491    }
492}
493
494function emit_cmp_op_decls_1(result_type, lhs_type, rhs_type)
495{
496  emit_bin_op_decl(result_type, "mx_el_lt", lhs_type, rhs_type);
497  emit_bin_op_decl(result_type, "mx_el_le", lhs_type, rhs_type);
498  emit_bin_op_decl(result_type, "mx_el_ge", lhs_type, rhs_type);
499  emit_bin_op_decl(result_type, "mx_el_gt", lhs_type, rhs_type);
500  emit_bin_op_decl(result_type, "mx_el_eq", lhs_type, rhs_type);
501  emit_bin_op_decl(result_type, "mx_el_ne", lhs_type, rhs_type);
502}
503
504function emit_cmp_op_decls (sparse, lhs_class, rhs_class, lhs_type, rhs_type)
505{
506  if (sparse)
507    {
508      if ((lhs_class == "M" && rhs_class == "SM") \
509          || (lhs_class == "SM" && (rhs_class == "M" || rhs_class == "S" || rhs_class == "SM")) \
510          || (lhs_class == "S" && rhs_class == "SM"))
511        emit_cmp_op_decls_1("SparseBoolMatrix", lhs_type, rhs_type);
512    }
513  else
514    {
515      if ((lhs_class == "M" && rhs_class == "M") \
516          || (lhs_class == "M" && rhs_class == "S") \
517          || (lhs_class == "S" && rhs_class == "M"))
518        emit_cmp_op_decls_1("boolMatrix", lhs_type, rhs_type);
519      else if ((lhs_class == "ND" && rhs_class == "ND") \
520               || (lhs_class == "ND" && rhs_class == "S") \
521               || (lhs_class == "S" && rhs_class == "ND"))
522        emit_cmp_op_decls_1("boolNDArray", lhs_type, rhs_type);
523    }
524}
525
526function emit_eqne_op_decls_1(result_type, lhs_type, rhs_type)
527{
528  emit_bin_op_decl(result_type, "mx_el_eq", lhs_type, rhs_type);
529  emit_bin_op_decl(result_type, "mx_el_ne", lhs_type, rhs_type);
530}
531
532function emit_eqne_op_decls (sparse, lhs_class, rhs_class, lhs_type, rhs_type)
533{
534  if (sparse)
535    {
536      if ((lhs_class == "M" && rhs_class == "SM") \
537          || (lhs_class == "SM" && rhs_class == "M"))
538        emit_eqne_op_decls_1("SparseBoolMatrix", lhs_type, rhs_type);
539    }
540
541  ## No separate eqne ops for full-matrix or vector.
542}
543
544function emit_bool_op_decls_1 (result_type, lhs_type, rhs_type)
545{
546  emit_bin_op_decl(result_type, "mx_el_and", lhs_type, rhs_type);
547  emit_bin_op_decl(result_type, "mx_el_or", lhs_type, rhs_type);
548}
549
550function emit_bool_op_decls_2 (result_type, lhs_type, rhs_type)
551{
552  emit_bin_op_decl(result_type, "mx_el_not_and", lhs_type, rhs_type);
553  emit_bin_op_decl(result_type, "mx_el_not_or", lhs_type, rhs_type);
554}
555
556function emit_bool_op_decls_3 (result_type, lhs_type, rhs_type)
557{
558  emit_bin_op_decl(result_type, "mx_el_and_not", lhs_type, rhs_type);
559  emit_bin_op_decl(result_type, "mx_el_or_not", lhs_type, rhs_type);
560}
561
562function emit_bool_op_decls (sparse, lhs_class, rhs_class, lhs_type, rhs_type)
563{
564  if (sparse)
565    {
566      if ((lhs_class == "M" && rhs_class == "SM") \
567          || (lhs_class == "SM" && (rhs_class == "M" || rhs_class == "S" || rhs_class == "SM")) \
568          || (lhs_class == "S" && rhs_class == "SM"))
569        emit_bool_op_decls_1("SparseBoolMatrix", lhs_type, rhs_type);
570    }
571  else
572    {
573      if ((lhs_class == "M" && rhs_class == "M") \
574          || (lhs_class == "M" && rhs_class == "S") \
575          || (lhs_class == "S" && rhs_class == "M"))
576        emit_bool_op_decls_1("boolMatrix", lhs_type, rhs_type);
577      else if (lhs_class == "ND" && rhs_class == "S")
578        {
579          emit_bool_op_decls_1("boolNDArray", lhs_type, rhs_type);
580          emit_bool_op_decls_2("boolNDArray", lhs_type, rhs_type);
581        }
582      else if (lhs_class == "S" && rhs_class == "ND")
583        {
584          emit_bool_op_decls_1("boolNDArray", lhs_type, rhs_type);
585          emit_bool_op_decls_3("boolNDArray", lhs_type, rhs_type);
586        }
587      else if (lhs_class == "ND" && rhs_class == "ND")
588        {
589          emit_bool_op_decls_1("boolNDArray", lhs_type, rhs_type);
590          emit_bool_op_decls_2("boolNDArray", lhs_type, rhs_type);
591          emit_bool_op_decls_3("boolNDArray", lhs_type, rhs_type);
592        }
593    }
594}
595
596function emit_sparse_bin_ops (lhs_class, rhs_class, result_type_1,
597                              result_type_2, lhs_type, rhs_type)
598{
599  printf ("SPARSE_%s%s_BIN_OPS (%s, %s, %s, %s)\n",
600          lhs_class, rhs_class, result_type_1,
601          result_type_2, lhs_type, rhs_type);
602}
603
604function emit_dm_bin_ops (lhs_class, rhs_class, result_type_1,
605                          lhs_type, rhs_type)
606{
607  printf ("%s%s_BIN_OPS (%s, %s, %s)\n",
608          lhs_class, rhs_class, result_type_1, lhs_type, rhs_type);
609}
610
611function emit_mm_bin_op (result_t, op, lhs_t, rhs_t, fcn)
612{
613  printf ("\n" \
614          "%s\n" \
615          "%s (const %s& m1, const %s& m2)\n" \
616          "{\n" \
617          "  return do_mm_binary_op<%s::element_type, %s::element_type, %s::element_type> (m1, m2, %s, %s, %s, \"%s\");\n" \
618          "}\n",
619          result_t, op, lhs_t, rhs_t, result_t, lhs_t, rhs_t,
620          fcn, fcn, fcn, op);
621}
622
623function emit_mm_bin_ops (result_t, lhs_t, rhs_t)
624{
625  emit_mm_bin_op(result_t, "operator +", lhs_t, rhs_t, "mx_inline_add");
626  emit_mm_bin_op(result_t, "operator -", lhs_t, rhs_t, "mx_inline_sub");
627  emit_mm_bin_op(result_t, "product", lhs_t, rhs_t, "mx_inline_mul");
628  emit_mm_bin_op(result_t, "quotient", lhs_t, rhs_t, "mx_inline_div");
629}
630
631function emit_bin_ops (sparse, lhs_class, rhs_class,
632                       result_type_1, result_type_2, lhs_type, rhs_type)
633{
634  if (sparse)
635    emit_sparse_bin_ops(lhs_class, rhs_class, result_type_1,
636                        result_type_2, lhs_type, rhs_type);
637 else if ((lhs_class == "DM" && rhs_class == "M") \
638          || (lhs_class == "M" && rhs_class == "DM"))
639    emit_dm_bin_ops(lhs_class, rhs_class, result_type_1,
640                    lhs_type, rhs_type);
641  else if (lhs_class == "M" && rhs_class == "M")
642    emit_mm_bin_ops(result_type_1, lhs_type, rhs_type);
643  else
644    printf ("%s%s_BIN_OPS (%s, %s, %s)\n",
645            lhs_class, rhs_class, result_type_1, lhs_type, rhs_type);
646}
647
648function emit_cmp_ops (sparse, lhs_class, rhs_class, lhs_type, rhs_type)
649{
650  if (sparse)
651    printf ("SPARSE_%s%s_CMP_OPS (%s, %s)\n",
652            lhs_class, rhs_class, lhs_type, rhs_type);
653  else
654    printf ("%s%s_CMP_OPS (%s, %s)\n",
655            lhs_class, rhs_class, lhs_type, rhs_type);
656}
657
658function emit_eqne_ops (sparse, lhs_class, rhs_class, lhs_type, rhs_type)
659{
660  if (sparse)
661    printf ("SPARSE_%s%s_EQNE_OPS (%s, %s)\n",
662            lhs_class, rhs_class, lhs_type, rhs_type);
663
664  ## No separate eqne ops for full-matrix or vector.
665}
666
667function emit_bool_ops (sparse, lhs_class, rhs_class, lhs_type, rhs_type)
668{
669  if (sparse)
670    printf ("SPARSE_%s%s_BOOL_OPS (%s, %s)\n",
671            lhs_class, rhs_class, lhs_type, rhs_type);
672  else
673    printf ("%s%s_BOOL_OPS (%s, %s)\n",
674            lhs_class, rhs_class, lhs_type, rhs_type);
675}
676