Moved insert_Perm_after to benode.c
[libfirm] / ir / be / mps.c
1 /**
2  * Author:      Daniel Grund
3  * Date:                02.06.2005
4  * Copyright:   (c) Universitaet Karlsruhe
5  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11 #include <stdarg.h>
12 #include <assert.h>
13 #include "mps.h"
14
15 /**
16  * These must comply to the enum cst_t in lpp.h
17  */
18 static char *mps_cst_encoding[4] = {"N", "E", "L", "G"};
19
20 /**
21  * Diffferent line styles which can be used in a mps file
22  */
23 typedef enum _mps_line_t {l_raw,
24                                                   l_ind_name, l_ind_objs, l_ind_rows, l_ind_cols, l_ind_rhs, l_ind_end,
25                                                   l_data_row, l_data_col1, l_data_col2, l_data_mst, l_marker} mps_line_t;
26
27 static void mps_write_line(FILE *out, style_t style, mps_line_t line_type, ...) {
28         va_list args;
29         char *fmt = "";
30
31         assert(style == s_mps_fixed || style == s_mps_free);
32         va_start(args, line_type);
33
34         if (style == s_mps_fixed) {
35                 /* white spaces are important! */
36                 switch (line_type) {
37                         case l_raw:                     fmt = "%s\n"; break;
38                         case l_ind_name:        fmt = "NAME          %s\n"; break;
39                         case l_ind_objs:        fmt = "OBJSENSE\n"; break;
40                         case l_ind_rows:        fmt = "ROWS\n"; break;
41                         case l_ind_cols:        fmt = "COLUMNS\n"; break;
42                         case l_ind_rhs:         fmt = "RHS\n"; break;
43                         case l_ind_end:         fmt = "ENDATA\n"; break;
44                         case l_data_row:        fmt = " %-2s %-8s\n"; break; /* Field 1-2 */
45                         case l_data_col1:       fmt = "    %-8s  %-8s  %12g\n"; break; /* Field 2-4 */
46                         case l_data_col2:       fmt = "    %-8s  %-8s  %12g   %-8s  %12g\n"; break; /* Field 2-6 */
47                         case l_data_mst:        fmt = "    %-8s            %12g\n"; break; /* Field 3-4 */
48                         case l_marker:          fmt = "    M%-7d  'MARKER'                 '%s'\n"; break; /* Field 2,3,5 */
49                         default: assert(0);
50                 }
51         } else {
52                 switch (line_type) {
53                         case l_raw:                     fmt = "%s\n"; break;
54                         case l_ind_name:        fmt = "NAME %s\n"; break;
55                         case l_ind_objs:        fmt = "OBJSENSE\n"; break;
56                         case l_ind_rows:        fmt = "ROWS\n"; break;
57                         case l_ind_cols:        fmt = "COLUMNS\n"; break;
58                         case l_ind_rhs:         fmt = "RHS\n"; break;
59                         case l_ind_end:         fmt = "ENDATA\n"; break;
60                         case l_data_row:        fmt = " %s\t%s\n"; break;
61                         case l_data_col1:       fmt = " %s\t%s\t%g\n"; break;
62                         case l_data_col2:       fmt = " %s\t%s\t%g\t%s\t%g\n"; break;
63                         case l_data_mst:        fmt = " %s\t%g\n"; break;
64                         case l_marker:          fmt = " M%d\t'MARKER'\t'%s'\n"; break;
65                         default: assert(0);
66                 }
67         }
68
69         vfprintf(out, fmt, args);
70         va_end(args);
71 }
72
73 static INLINE int mps_insert_markers(FILE *out, style_t style, var_t curr, var_t last, int marker_nr) {
74         assert(style == s_mps_fixed || style == s_mps_free);
75         if (last != curr) {
76                 /* print end-marker for last */
77                 if (last == binary)
78                         mps_write_line(out, style, l_marker, marker_nr++, "INTEND");
79
80                 /* print begin-marker for curr */
81                 if (curr == binary)
82                         mps_write_line(out, style, l_marker, marker_nr++, "INTORG");
83         }
84         return marker_nr;
85 }
86
87 void mps_write_mps(lpp_t *lpp, style_t style, FILE *out) {
88         int i, count, marker_nr = 0;
89         const name_t *curr;
90         const matrix_elem_t *elem, *before = NULL;
91         var_t last_type;
92         assert(style == s_mps_fixed || style == s_mps_free);
93
94         /* NAME */
95         mps_write_line(out, style, l_ind_name, lpp->name);
96
97         /* OBJSENSE */
98         if (lpp->opt_type == maximize) {
99                 mps_write_line(out, style, l_ind_objs);
100                 mps_write_line(out, style, l_raw, " MAX");
101         }
102
103         /* ROWS */
104         mps_write_line(out, style, l_ind_rows);
105         for(i=0; i<lpp->cst_next; ++i) {
106                 curr = lpp->csts[i];
107                 mps_write_line(out, style, l_data_row, mps_cst_encoding[curr->type.cst_type], curr->name);
108         }
109
110         /* COLUMNS */
111         mps_write_line(out, style, l_ind_cols);
112         last_type = invalid;
113         for(i=1; i<lpp->var_next; ++i) { /* column 0 is rhs */
114                 curr = lpp->vars[i];
115
116                 /* markers */
117                 marker_nr = mps_insert_markers(out, style, curr->type.var_type, last_type, marker_nr);
118                 last_type = curr->type.var_type;
119
120                 /* participation in constraints */
121                 count = 0;
122                 matrix_foreach_in_col(lpp->m, curr->nr, elem) {
123                         if (count == 0) {
124                                 before = elem;
125                                 count = 1;
126                         } else {
127                                 mps_write_line(out, style, l_data_col2, curr->name, lpp->csts[before->row]->name, (double)before->val, lpp->csts[elem->row]->name, (double)elem->val);
128                                 count = 0;
129                         }
130                 }
131                 if (count == 1)
132                         mps_write_line(out, style, l_data_col1, curr->name, lpp->csts[before->row]->name, (double)before->val);
133         }
134         mps_insert_markers(out, style, invalid, last_type, marker_nr); /* potential end-marker */
135
136         /* RHS */
137         mps_write_line(out, style, l_ind_rhs);
138         count = 0;
139         matrix_foreach_in_col(lpp->m, 0, elem) {
140                 if (count == 0) {
141                         before = elem;
142                         count = 1;
143                 } else {
144                         mps_write_line(out, style, l_data_col2, "rhs", lpp->csts[before->row]->name, (double)before->val, lpp->csts[elem->row]->name, (double)elem->val);
145                         count = 0;
146                 }
147         }
148         if (count == 1)
149                 mps_write_line(out, style, l_data_col1, "rhs", lpp->csts[before->row]->name, (double)before->val);
150
151         /* ENDATA */
152         mps_write_line(out, style, l_ind_end);
153 }
154
155 void mps_write_mst(lpp_t *lpp, style_t style, FILE *out) {
156         int i;
157         mps_write_line(out, style, l_ind_name, "");
158         for (i=0; i<lpp->var_next; ++i) {
159                 const name_t *var = lpp->vars[i];
160                 if (var->value_kind == value_start)
161                         mps_write_line(out, style, l_data_mst, var->name, (double)var->value);
162         }
163         mps_write_line(out, style, l_ind_end);
164 }