OpenScop  0.9.0
relation.c
Go to the documentation of this file.
1 
2  /*+-----------------------------------------------------------------**
3  ** OpenScop Library **
4  **-----------------------------------------------------------------**
5  ** relation.c **
6  **-----------------------------------------------------------------**
7  ** First version: 30/04/2008 **
8  **-----------------------------------------------------------------**
9 
10 
11  *****************************************************************************
12  * OpenScop: Structures and formats for polyhedral tools to talk together *
13  *****************************************************************************
14  * ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__, *
15  * / / / // // // // / / / // // / / // / /|,_, *
16  * / / / // // // // / / / // // / / // / / / /\ *
17  * |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/ \ *
18  * | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\ \ /\ *
19  * | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\ *
20  * | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \ \ *
21  * | P |n| l | = | s | t |=| = |d| = | = | = | | |=| o | | \# \ \ *
22  * | H | | y | | e | o | | = |l| | | = | | | | G | | \ \ \ *
23  * | I | | | | e | | | | | | | | | | | | | \ \ \ *
24  * | T | | | | | | | | | | | | | | | | | \ \ \ *
25  * | E | | | | | | | | | | | | | | | | | \ \ \ *
26  * | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | / \* \ \ *
27  * | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/ \ \ / *
28  * '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' *
29  * *
30  * Copyright (C) 2008 University Paris-Sud 11 and INRIA *
31  * *
32  * (3-clause BSD license) *
33  * Redistribution and use in source and binary forms, with or without *
34  * modification, are permitted provided that the following conditions *
35  * are met: *
36  * *
37  * 1. Redistributions of source code must retain the above copyright notice, *
38  * this list of conditions and the following disclaimer. *
39  * 2. Redistributions in binary form must reproduce the above copyright *
40  * notice, this list of conditions and the following disclaimer in the *
41  * documentation and/or other materials provided with the distribution. *
42  * 3. The name of the author may not be used to endorse or promote products *
43  * derived from this software without specific prior written permission. *
44  * *
45  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
46  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
47  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
48  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
49  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
50  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
51  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
52  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
53  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
54  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
55  * *
56  * OpenScop Library, a library to manipulate OpenScop formats and data *
57  * structures. Written by: *
58  * Cedric Bastoul <Cedric.Bastoul@u-psud.fr> and *
59  * Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr> *
60  * *
61  *****************************************************************************/
62 
63 
64 #include <stdlib.h>
65 #include <stdio.h>
66 #include <string.h>
67 #include <ctype.h>
68 
69 #include <osl/macros.h>
70 #include <osl/int.h>
71 #include <osl/util.h>
72 #include <osl/vector.h>
73 #include <osl/strings.h>
74 #include <osl/names.h>
75 #include <osl/relation.h>
76 
77 
78 /*+***************************************************************************
79  * Structure display function *
80  *****************************************************************************/
81 
82 
90 static
92  char * string = NULL;
93 
94  OSL_malloc(string, char *, OSL_MAX_STRING * sizeof(char));
95  string[0] = '\0';
96 
97  if (relation != NULL) {
98  switch (relation->type) {
99  case OSL_UNDEFINED: {
100  snprintf(string, OSL_MAX_STRING, OSL_STRING_UNDEFINED);
101  break;
102  }
103  case OSL_TYPE_CONTEXT: {
104  snprintf(string, OSL_MAX_STRING, OSL_STRING_CONTEXT);
105  break;
106  }
107  case OSL_TYPE_DOMAIN: {
108  snprintf(string, OSL_MAX_STRING, OSL_STRING_DOMAIN);
109  break;
110  }
111  case OSL_TYPE_SCATTERING: {
112  snprintf(string, OSL_MAX_STRING, OSL_STRING_SCATTERING);
113  break;
114  }
115  case OSL_TYPE_READ: {
116  snprintf(string, OSL_MAX_STRING, OSL_STRING_READ);
117  break;
118  }
119  case OSL_TYPE_WRITE: {
120  snprintf(string, OSL_MAX_STRING, OSL_STRING_WRITE);
121  break;
122  }
123  case OSL_TYPE_MAY_WRITE: {
124  snprintf(string, OSL_MAX_STRING, OSL_STRING_MAY_WRITE);
125  break;
126  }
127  default: {
128  OSL_warning("unknown relation type, "
129  "replaced with "OSL_STRING_UNDEFINED);
130  snprintf(string, OSL_MAX_STRING, OSL_STRING_UNDEFINED);
131  }
132  }
133  }
134 
135  return string;
136 }
137 
138 
146 static
147 void osl_relation_print_type(FILE * file, osl_relation_p relation) {
148  char * string = osl_relation_sprint_type(relation);
149  fprintf(file, "%s", string);
150  free(string);
151 }
152 
153 
164 void osl_relation_idump(FILE * file, osl_relation_p relation, int level) {
165  int i, j, first = 1;
166 
167  // Go to the right level.
168  for (j = 0; j < level; j++)
169  fprintf(file, "|\t");
170 
171  if (relation != NULL) {
172  fprintf(file, "+-- osl_relation_t (");
173  osl_relation_print_type(file, relation);
174  fprintf(file, ", ");
175  osl_int_dump_precision(file, relation->precision);
176  fprintf(file, ")\n");
177  }
178  else {
179  fprintf(file, "+-- NULL relation\n");
180  }
181 
182  while (relation != NULL) {
183  if (! first) {
184  // Go to the right level.
185  for (j = 0; j < level; j++)
186  fprintf(file, "|\t");
187  fprintf(file, "| osl_relation_t (");
188  osl_relation_print_type(file, relation);
189  fprintf(file, ", ");
190  osl_int_dump_precision(file, relation->precision);
191  fprintf(file, ")\n");
192  }
193  else
194  first = 0;
195 
196  // A blank line
197  for(j = 0; j <= level; j++)
198  fprintf(file, "|\t");
199  fprintf(file, "%d %d %d %d %d %d\n",
200  relation->nb_rows, relation->nb_columns,
201  relation->nb_output_dims, relation->nb_input_dims,
202  relation->nb_local_dims, relation->nb_parameters);
203 
204  // Display the relation.
205  for (i = 0; i < relation->nb_rows; i++) {
206  for (j = 0; j <= level; j++)
207  fprintf(file, "|\t");
208 
209  fprintf(file, "[ ");
210 
211  for (j = 0; j < relation->nb_columns; j++) {
212  osl_int_print(file, relation->precision, relation->m[i][j]);
213  fprintf(file, " ");
214  }
215 
216  fprintf(file, "]\n");
217  }
218 
219  relation = relation->next;
220 
221  // Next line.
222  if (relation != NULL) {
223  for (j = 0; j <= level; j++)
224  fprintf(file, "|\t");
225  fprintf(file, "|\n");
226  for (j = 0; j <= level; j++)
227  fprintf(file, "|\t");
228  fprintf(file, "V\n");
229  }
230  }
231 
232  // The last line.
233  for (j = 0; j <= level; j++)
234  fprintf(file, "|\t");
235  fprintf(file, "\n");
236 }
237 
238 
246 void osl_relation_dump(FILE * file, osl_relation_p relation) {
247  osl_relation_idump(file, relation, 0);
248 }
249 
250 
265 static
267  int precision, int * first,
268  int cst, char * name) {
269  char * temp, * body, * sval;
270 
271  OSL_malloc(temp, char *, OSL_MAX_STRING * sizeof(char));
272  OSL_malloc(body, char *, OSL_MAX_STRING * sizeof(char));
273  OSL_malloc(sval, char *, OSL_MAX_STRING * sizeof(char));
274 
275  body[0] = '\0';
276  sval[0] = '\0';
277 
278  // statements for the 'normal' processing.
279  if (!osl_int_zero(precision, val) && (!cst)) {
280  if ((*first) || osl_int_neg(precision, val)) {
281  if (osl_int_one(precision, val)) { // case 1
282  sprintf(sval, "%s", name);
283  }
284  else {
285  if (osl_int_mone(precision, val)) { // case -1
286  sprintf(sval, "-%s", name);
287  }
288  else { // default case
289  osl_int_sprint_txt(sval, precision, val);
290  sprintf(temp, "*%s", name);
291  strcat(sval, temp);
292  }
293  }
294  *first = 0;
295  }
296  else {
297  if (osl_int_one(precision, val)) {
298  sprintf(sval, "+%s", name);
299  }
300  else {
301  sprintf(sval, "+");
302  osl_int_sprint_txt(temp, precision, val);
303  strcat(sval, temp);
304  sprintf(temp, "*%s", name);
305  strcat(sval, temp);
306  }
307  }
308  }
309  else {
310  if (cst) {
311  if ((osl_int_zero(precision, val) && (*first)) ||
312  (osl_int_neg(precision, val)))
313  osl_int_sprint_txt(sval, precision, val);
314  if (osl_int_pos(precision, val)) {
315  if (!(*first)) {
316  sprintf(sval, "+");
317  osl_int_sprint_txt(temp, precision, val);
318  strcat(sval, temp);
319  }
320  else {
321  osl_int_sprint_txt(sval, precision, val);
322  }
323  }
324  }
325  }
326  free(temp);
327  free(body);
328 
329  return(sval);
330 }
331 
332 
342 static
344  char ** strings;
345  char temp[OSL_MAX_STRING];
346  int i, offset;
347 
348  if ((relation == NULL) || (names == NULL)) {
349  OSL_debug("no names or relation to build the name array");
350  return NULL;
351  }
352 
353  OSL_malloc(strings, char **, (relation->nb_columns + 1)*sizeof(char *));
354  strings[relation->nb_columns] = NULL;
355 
356  // 1. Equality/inequality marker.
357  OSL_strdup(strings[0], "e/i");
358  offset = 1;
359 
360  // 2. Output dimensions.
361  if (osl_relation_is_access(relation)) {
362  // The first output dimension is the array name.
363  OSL_strdup(strings[offset], "Arr");
364  // The other ones are the array dimensions [1]...[n]
365  for (i = offset + 1; i < relation->nb_output_dims + offset; i++) {
366  sprintf(temp, "[%d]", i - 1);
367  OSL_strdup(strings[i], temp);
368  }
369  }
370  else
371  if ((relation->type == OSL_TYPE_DOMAIN) ||
372  (relation->type == OSL_TYPE_CONTEXT)) {
373  for (i = offset; i < relation->nb_output_dims + offset; i++) {
374  OSL_strdup(strings[i], names->iterators->string[i - offset]);
375  }
376  }
377  else {
378  for (i = offset; i < relation->nb_output_dims + offset; i++) {
379  OSL_strdup(strings[i], names->scatt_dims->string[i - offset]);
380  }
381  }
382  offset += relation->nb_output_dims;
383 
384  // 3. Input dimensions.
385  for (i = offset; i < relation->nb_input_dims + offset; i++)
386  OSL_strdup(strings[i], names->iterators->string[i - offset]);
387  offset += relation->nb_input_dims;
388 
389  // 4. Local dimensions.
390  for (i = offset; i < relation->nb_local_dims + offset; i++)
391  OSL_strdup(strings[i], names->local_dims->string[i - offset]);
392  offset += relation->nb_local_dims;
393 
394  // 5. Parameters.
395  for (i = offset; i < relation->nb_parameters + offset; i++)
396  OSL_strdup(strings[i], names->parameters->string[i - offset]);
397  offset += relation->nb_parameters;
398 
399  // 6. Scalar.
400  OSL_strdup(strings[offset], "1");
401 
402  return strings;
403 }
404 
405 
419 static
421  int row, int start, int stop, int oppose,
422  char ** strings) {
423  int i, first = 1, constant;
424  char * sval;
425  char * sline;
426 
427  OSL_malloc(sline, char *, OSL_MAX_STRING * sizeof(char));
428  sline[0] = '\0';
429 
430  // Create the expression. The constant is a special case.
431  for (i = start; i <= stop; i++) {
432  if (oppose) {
433  osl_int_oppose(relation->precision,
434  &relation->m[row][i], relation->m[row][i]);
435  }
436 
437  if (i == relation->nb_columns - 1)
438  constant = 1;
439  else
440  constant = 0;
441 
442  sval = osl_relation_expression_element(relation->m[row][i],
443  relation->precision, &first, constant, strings[i]);
444 
445  if (oppose) {
446  osl_int_oppose(relation->precision,
447  &relation->m[row][i], relation->m[row][i]);
448  }
449  strcat(sline, sval);
450  free(sval);
451  }
452 
453  return sline;
454 }
455 
456 
467  int row, char ** strings) {
468 
469  return osl_relation_subexpression(relation, row,
470  1, relation->nb_columns - 1, 0,
471  strings);
472 }
473 
474 
486 static
488  int i;
489  int first = 1;
490  int sign = 0;
491 
492  if ((relation == NULL) ||
493  (relation->m == NULL) ||
494  (relation->nb_output_dims == 0))
495  return 0;
496 
497  if ((row < 0) || (row > relation->nb_rows))
498  OSL_error("the specified row does not exist in the relation");
499 
500  // The constraint must be an equality.
501  if (!osl_int_zero(relation->precision, relation->m[row][0]))
502  return 0;
503 
504  // Check the output part has one and only one non-zero +1 or -1 coefficient.
505  first = 1;
506  for (i = 1; i <= relation->nb_output_dims; i++) {
507  if (!osl_int_zero(relation->precision, relation->m[row][i])) {
508  if (first)
509  first = 0;
510  else
511  return 0;
512 
513  if (osl_int_one(relation->precision, relation->m[row][i]))
514  sign = 1;
515  else if (osl_int_mone(relation->precision, relation->m[row][i]))
516  sign = -1;
517  else
518  return 0;
519  }
520  }
521 
522  return sign;
523 }
524 
525 
539 static
541  char ** strings, char ** arrays) {
542  int sign;
543  int high_water_mark = OSL_MAX_STRING;
544  char * string = NULL;
545  char * expression;
546  char buffer[OSL_MAX_STRING];
547 
548  OSL_malloc(string, char *, high_water_mark * sizeof(char));
549  string[0] = '\0';
550 
551  if ((relation == NULL) || (strings == NULL)) {
552  OSL_debug("no relation or names while asked to print a comment");
553  return string;
554  }
555 
556  if ((sign = osl_relation_is_simple_output(relation, row))) {
557  // First case : output == expression.
558 
559  expression = osl_relation_subexpression(relation, row,
560  1, relation->nb_output_dims,
561  sign < 0,
562  strings);
563  snprintf(buffer, OSL_MAX_STRING, " ## %s", expression);
564  osl_util_safe_strcat(&string, buffer, &high_water_mark);
565  free(expression);
566 
567  // We don't print the right hand side if it's an array identifier.
568  if (!osl_relation_is_access(relation) ||
569  osl_int_zero(relation->precision, relation->m[row][1])) {
570  expression = osl_relation_subexpression(relation, row,
571  relation->nb_output_dims + 1,
572  relation->nb_columns - 1,
573  sign > 0,
574  strings);
575  snprintf(buffer, OSL_MAX_STRING, " == %s", expression);
576  osl_util_safe_strcat(&string, buffer, &high_water_mark);
577  free(expression);
578  }
579  else {
580  snprintf(buffer, OSL_MAX_STRING, " == %s",
581  arrays[osl_relation_get_array_id(relation) - 1]);
582  osl_util_safe_strcat(&string, buffer, &high_water_mark);
583  }
584  }
585  else {
586  // Second case : general case.
587 
588  expression = osl_relation_expression(relation, row, strings);
589  snprintf(buffer, OSL_MAX_STRING, " ## %s", expression);
590  osl_util_safe_strcat(&string, buffer, &high_water_mark);
591  free(expression);
592 
593  if (osl_int_zero(relation->precision, relation->m[row][0]))
594  snprintf(buffer, OSL_MAX_STRING, " == 0");
595  else
596  snprintf(buffer, OSL_MAX_STRING, " >= 0");
597  osl_util_safe_strcat(&string, buffer, &high_water_mark);
598  }
599 
600  return string;
601 }
602 
603 
613 static
614 char * osl_relation_column_string(osl_relation_p relation, char ** strings) {
615  int i, j;
616  int index_output_dims;
617  int index_input_dims;
618  int index_local_dims;
619  int index_parameters;
620  int index_scalar;
621  int space, length, left, right;
622  char * scolumn;
623  char temp[OSL_MAX_STRING];
624 
625  OSL_malloc(scolumn, char *, OSL_MAX_STRING);
626 
627  index_output_dims = 1;
628  index_input_dims = index_output_dims + relation->nb_output_dims;
629  index_local_dims = index_input_dims + relation->nb_input_dims;
630  index_parameters = index_local_dims + relation->nb_local_dims;
631  index_scalar = index_parameters + relation->nb_parameters;
632 
633  // 1. The comment part.
634  sprintf(scolumn, "#");
635  for (j = 0; j < (OSL_FMT_LENGTH - 1)/2 - 1; j++)
636  strcat(scolumn, " ");
637 
638  i = 0;
639  while (strings[i] != NULL) {
640  space = OSL_FMT_LENGTH;
641  length = (space > (int)strlen(strings[i])) ? (int)strlen(strings[i]) : space;
642  right = (space - length + (OSL_FMT_LENGTH % 2)) / 2;
643  left = space - length - right;
644 
645  // 2. Spaces before the name
646  for (j = 0; j < left; j++)
647  strcat(scolumn, " ");
648 
649  // 3. The (abbreviated) name
650  for (j = 0; j < length - 1; j++) {
651  sprintf(temp, "%c", strings[i][j]);
652  strcat(scolumn, temp);
653  }
654  if (length >= (int)strlen(strings[i]))
655  sprintf(temp, "%c", strings[i][j]);
656  else
657  sprintf(temp, ".");
658  strcat(scolumn, temp);
659 
660  // 4. Spaces after the name
661  for (j = 0; j < right; j++)
662  strcat(scolumn, " ");
663 
664  i++;
665  if ((i == index_output_dims) ||
666  (i == index_input_dims) ||
667  (i == index_local_dims) ||
668  (i == index_parameters) ||
669  (i == index_scalar))
670  strcat(scolumn, "|");
671  else
672  strcat(scolumn, " ");
673  }
674  strcat(scolumn, "\n");
675 
676  return scolumn;
677 }
678 
679 
689 static
691  char ** strings) {
692  int i, j;
693  int index_output_dims;
694  int index_input_dims;
695  int index_local_dims;
696  int index_parameters;
697  int index_scalar;
698  int space, length, left, right;
699  char * scolumn;
700  char temp[OSL_MAX_STRING];
701 
702  OSL_malloc(scolumn, char *, OSL_MAX_STRING);
703 
704  index_output_dims = 1;
705  index_input_dims = index_output_dims + relation->nb_output_dims;
706  index_local_dims = index_input_dims + relation->nb_input_dims;
707  index_parameters = index_local_dims + relation->nb_local_dims;
708  index_scalar = index_parameters + relation->nb_parameters;
709 
710  // 1. The comment part.
711  sprintf(scolumn, "#");
712  for (j = 0; j < (OSL_FMT_LENGTH - 1)/2 - 1; j++)
713  strcat(scolumn, " ");
714 
715  i = 0;
716  while (strings[i] != NULL) {
717 
718  if (i == 0 ||
719  (relation->type != OSL_TYPE_DOMAIN && i >= index_input_dims) ||
720  (relation->type == OSL_TYPE_DOMAIN && i <= index_output_dims) ||
721  i >= index_parameters) {
722  space = OSL_FMT_LENGTH;
723  length = (space > (int)strlen(strings[i])) ? (int)strlen(strings[i]) : space;
724  right = (space - length + (OSL_FMT_LENGTH % 2)) / 2;
725  left = space - length - right;
726 
727  // 2. Spaces before the name
728  for (j = 0; j < left; j++)
729  strcat(scolumn, " ");
730 
731  // 3. The (abbreviated) name
732  for (j = 0; j < length - 1; j++) {
733  sprintf(temp, "%c", strings[i][j]);
734  strcat(scolumn, temp);
735  }
736  if (length >= (int)strlen(strings[i]))
737  sprintf(temp, "%c", strings[i][j]);
738  else
739  sprintf(temp, ".");
740  strcat(scolumn, temp);
741 
742  // 4. Spaces after the name
743  for (j = 0; j < right; j++)
744  strcat(scolumn, " ");
745 
746  if ((i == index_output_dims-1) ||
747  (i == index_input_dims-1) ||
748  (i == index_local_dims-1) ||
749  (i == index_parameters-1) ||
750  (i == index_scalar-1))
751  strcat(scolumn, "|");
752  else
753  strcat(scolumn, " ");
754  }
755 
756  i++;
757  }
758  strcat(scolumn, "\n");
759 
760  return scolumn;
761 }
762 
763 
771 static
773  int nb_parameters = OSL_UNDEFINED;
774  int nb_iterators = OSL_UNDEFINED;
775  int nb_scattdims = OSL_UNDEFINED;
776  int nb_localdims = OSL_UNDEFINED;
777  int array_id = OSL_UNDEFINED;
778 
779  osl_relation_get_attributes(relation, &nb_parameters, &nb_iterators,
780  &nb_scattdims, &nb_localdims, &array_id);
781 
782  return osl_names_generate("P", nb_parameters,
783  "i", nb_iterators,
784  "c", nb_scattdims,
785  "l", nb_localdims,
786  "A", array_id);
787 }
788 
789 
798  int nb_components = 0;
799 
800  while (relation != NULL) {
801  nb_components++;
802  relation = relation->next;
803  }
804 
805  return nb_components;
806 }
807 
808 
819  osl_names_p names) {
820  int i, j;
821  int part, nb_parts;
822  int generated_names = 0;
823  int high_water_mark = OSL_MAX_STRING;
824  char * string = NULL;
825  char buffer[OSL_MAX_STRING];
826  char ** name_array = NULL;
827  char * scolumn;
828  char * comment;
829 
830  if (relation == NULL)
831  return osl_util_strdup("# NULL relation\n");
832 
833  OSL_malloc(string, char *, high_water_mark * sizeof(char));
834  string[0] = '\0';
835 
836  // Generates the names for the comments if necessary.
837  if (names == NULL) {
838  generated_names = 1;
839  names = osl_relation_names(relation);
840  }
841 
842  nb_parts = osl_relation_nb_components(relation);
843 
844  if (nb_parts > 1) {
845  snprintf(buffer, OSL_MAX_STRING, "# Union with %d parts\n%d\n",
846  nb_parts, nb_parts);
847  osl_util_safe_strcat(&string, buffer, &high_water_mark);
848  }
849 
850  // Print each part of the union.
851  for (part = 1; part <= nb_parts; part++) {
852  // Prepare the array of strings for comments.
853  name_array = osl_relation_strings(relation, names);
854 
855  if (nb_parts > 1) {
856  snprintf(buffer, OSL_MAX_STRING, "# Union part No.%d\n", part);
857  osl_util_safe_strcat(&string, buffer, &high_water_mark);
858  }
859 
860  snprintf(buffer, OSL_MAX_STRING, "%d %d %d %d %d %d\n",
861  relation->nb_rows, relation->nb_columns,
862  relation->nb_output_dims, relation->nb_input_dims,
863  relation->nb_local_dims, relation->nb_parameters);
864  osl_util_safe_strcat(&string, buffer, &high_water_mark);
865 
866  if (relation->nb_rows > 0) {
867  scolumn = osl_relation_column_string(relation, name_array);
868  snprintf(buffer, OSL_MAX_STRING, "%s", scolumn);
869  osl_util_safe_strcat(&string, buffer, &high_water_mark);
870  free(scolumn);
871  }
872 
873  for (i = 0; i < relation->nb_rows; i++) {
874  for (j = 0; j < relation->nb_columns; j++) {
875  osl_int_sprint(buffer, relation->precision, relation->m[i][j]);
876  osl_util_safe_strcat(&string, buffer, &high_water_mark);
877  snprintf(buffer, OSL_MAX_STRING, " ");
878  osl_util_safe_strcat(&string, buffer, &high_water_mark);
879  }
880 
881  if (name_array != NULL) {
882  comment = osl_relation_sprint_comment(relation, i, name_array,
883  names->arrays->string);
884  osl_util_safe_strcat(&string, comment, &high_water_mark);
885  free(comment);
886  }
887  snprintf(buffer, OSL_MAX_STRING, "\n");
888  osl_util_safe_strcat(&string, buffer, &high_water_mark);
889  }
890 
891  // Free the array of strings.
892  if (name_array != NULL) {
893  for (i = 0; i < relation->nb_columns; i++)
894  free(name_array[i]);
895  free(name_array);
896  }
897 
898  relation = relation->next;
899  }
900 
901  if (generated_names)
902  osl_names_free(names);
903 
904  return string;
905 }
906 
907 
920  osl_names_p names,
921  int print_nth_part,
922  int add_fakeiter) {
923  int i, j;
924  int part, nb_parts;
925  int generated_names = 0;
926  int is_access_array;
927  int high_water_mark = OSL_MAX_STRING;
928  int start_row; // for removing the first line in the access matrix
929  int index_output_dims;
930  int index_input_dims;
931  int index_params;
932  char * string = NULL;
933  char buffer[OSL_MAX_STRING];
934  char ** name_array = NULL;
935  char * scolumn;
936  char * comment;
937 
938  if (relation == NULL)
939  return osl_util_strdup("# NULL relation\n");
940 
941  OSL_malloc(string, char *, high_water_mark * sizeof(char));
942  string[0] = '\0';
943 
944  // Generates the names for the comments if necessary.
945  if (names == NULL) {
946  generated_names = 1;
947  names = osl_relation_names(relation);
948  }
949 
950  nb_parts = osl_relation_nb_components(relation);
951  if (nb_parts > 1) {
952  snprintf(buffer, OSL_MAX_STRING, "# Union with %d parts\n%d\n",
953  nb_parts, nb_parts);
954  osl_util_safe_strcat(&string, buffer, &high_water_mark);
955  }
956 
957  is_access_array = (relation->type == OSL_TYPE_READ ||
958  relation->type == OSL_TYPE_WRITE ? 1 : 0);
959 
960  // Print each part of the union.
961 
962  for (part = 1; part <= nb_parts; part++) {
963 
964  index_output_dims = 1;
965  index_input_dims = index_output_dims + relation->nb_output_dims;
966  index_params = index_input_dims + relation->nb_input_dims;
967 
968  // Prepare the array of strings for comments.
969  name_array = osl_relation_strings(relation, names);
970 
971  if (nb_parts > 1) {
972  snprintf(buffer, OSL_MAX_STRING, "# Union part No.%d\n", part);
973  osl_util_safe_strcat(&string, buffer, &high_water_mark);
974  }
975 
976  if (print_nth_part) {
977  snprintf(buffer, OSL_MAX_STRING, "%d\n", part);
978  osl_util_safe_strcat(&string, buffer, &high_water_mark);
979  }
980 
981  // Don't print the array size for access array
982  // (the total size is printed in osl_relation_list_pprint_access_array_scoplib)
983  if (!is_access_array) {
984 
985  // Print array size
986  if (relation->type == OSL_TYPE_DOMAIN) {
987 
988  if (add_fakeiter) {
989 
990  snprintf(buffer, OSL_MAX_STRING, "%d %d\n",
991  relation->nb_rows+1, relation->nb_columns -
992  relation->nb_input_dims + 1);
993  osl_util_safe_strcat(&string, buffer, &high_water_mark);
994 
995  // add the fakeiter line
996  snprintf(buffer, OSL_MAX_STRING, " 0 ");
997  osl_util_safe_strcat(&string, buffer, &high_water_mark);
998  snprintf(buffer, OSL_MAX_STRING, " 1 "); // fakeiter
999  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1000 
1001  for (i = 0 ; i < relation->nb_parameters ; i++) {
1002  snprintf(buffer, OSL_MAX_STRING, " 0 ");
1003  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1004  }
1005 
1006  snprintf(buffer, OSL_MAX_STRING, " 0 ## fakeiter == 0\n");
1007  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1008 
1009  } else {
1010  snprintf(buffer, OSL_MAX_STRING, "%d %d\n",
1011  relation->nb_rows, relation->nb_columns -
1012  relation->nb_input_dims);
1013  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1014  }
1015 
1016  } else { // SCATTERING
1017 
1018  if (add_fakeiter) {
1019  snprintf(buffer, OSL_MAX_STRING, "%d %d\n",
1020  relation->nb_rows+2, relation->nb_columns -
1021  relation->nb_output_dims + 1);
1022  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1023  } else {
1024  snprintf(buffer, OSL_MAX_STRING, "%d %d\n",
1025  relation->nb_rows, relation->nb_columns -
1026  relation->nb_output_dims);
1027  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1028  }
1029  }
1030 
1031  // Print column names in comment
1032  if (relation->nb_rows > 0) {
1033  scolumn = osl_relation_column_string_scoplib(relation, name_array);
1034  snprintf(buffer, OSL_MAX_STRING, "%s", scolumn);
1035  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1036  free(scolumn);
1037  }
1038 
1039  start_row = 0;
1040 
1041  } else {
1042 
1043  if (relation->nb_rows == 1) // for non array variables
1044  start_row = 0;
1045  else // Remove the 'Arr' line
1046  start_row = 1;
1047  }
1048 
1049  // Print the array
1050  for (i = start_row; i < relation->nb_rows; i++) {
1051 
1052  // First column
1053  if (!is_access_array) {
1054  // array index name for scoplib
1055  osl_int_sprint(buffer, relation->precision, relation->m[i][0]);
1056  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1057  snprintf(buffer, OSL_MAX_STRING, " ");
1058  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1059 
1060  } else {
1061  // The first column represents the array index name in openscop
1062  if (i == start_row)
1063  osl_int_sprint(buffer, relation->precision,
1064  relation->m[0][relation->nb_columns-1]);
1065  else
1066  snprintf(buffer, OSL_MAX_STRING, " 0 ");
1067 
1068  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1069  snprintf(buffer, OSL_MAX_STRING, " ");
1070  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1071  }
1072 
1073  // Rest of the array
1074  if (relation->type == OSL_TYPE_DOMAIN) {
1075 
1076  for (j = 1; j < index_input_dims; j++) {
1077  osl_int_sprint(buffer, relation->precision, relation->m[i][j]);
1078  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1079  snprintf(buffer, OSL_MAX_STRING, " ");
1080  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1081  }
1082 
1083  // Jmp input_dims
1084  for (j = index_params; j < relation->nb_columns; j++) {
1085  osl_int_sprint(buffer, relation->precision, relation->m[i][j]);
1086  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1087  snprintf(buffer, OSL_MAX_STRING, " ");
1088  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1089  }
1090 
1091  } else {
1092 
1093  // Jmp output_dims
1094  for (j = index_input_dims; j < index_params; j++) {
1095  if (is_access_array && relation->nb_rows == 1 &&
1096  j == relation->nb_columns-1) {
1097  snprintf(buffer, OSL_MAX_STRING, " 0 ");
1098  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1099  } else {
1100  osl_int_sprint(buffer, relation->precision, relation->m[i][j]);
1101  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1102  snprintf(buffer, OSL_MAX_STRING, " ");
1103  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1104  }
1105  }
1106 
1107  if (add_fakeiter) {
1108  snprintf(buffer, OSL_MAX_STRING, " 0 ");
1109  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1110  }
1111 
1112  for (; j < relation->nb_columns; j++) {
1113  if (is_access_array && relation->nb_rows == 1 &&
1114  j == relation->nb_columns-1) {
1115  snprintf(buffer, OSL_MAX_STRING, " 0 ");
1116  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1117  } else {
1118  osl_int_sprint(buffer, relation->precision, relation->m[i][j]);
1119  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1120  snprintf(buffer, OSL_MAX_STRING, " ");
1121  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1122  }
1123  }
1124  }
1125 
1126  // equation in comment
1127  if (name_array != NULL) {
1128  comment = osl_relation_sprint_comment(relation, i, name_array,
1129  names->arrays->string);
1130  osl_util_safe_strcat(&string, comment, &high_water_mark);
1131  free(comment);
1132  snprintf(buffer, OSL_MAX_STRING, "\n");
1133  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1134  }
1135 
1136  // add the lines in the scattering if we need the fakeiter
1137  if (relation->nb_rows > 0 && add_fakeiter &&
1138  relation->type == OSL_TYPE_SCATTERING) {
1139 
1140  for (i = 0 ; i < 2 ; i++) {
1141  for (j = 0; j < relation->nb_columns; j++) {
1142  if (j == index_output_dims && i == 0)
1143  snprintf(buffer, OSL_MAX_STRING, " 1 "); // fakeiter
1144  else
1145  snprintf(buffer, OSL_MAX_STRING, " 0 ");
1146  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1147  }
1148  snprintf(buffer, OSL_MAX_STRING, "\n");
1149  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1150  }
1151  }
1152 
1153  }
1154 
1155  // Free the array of strings.
1156  if (name_array != NULL) {
1157  for (i = 0; i < relation->nb_columns; i++)
1158  free(name_array[i]);
1159  free(name_array);
1160  }
1161 
1162  relation = relation->next;
1163  }
1164 
1165  if (generated_names)
1166  osl_names_free(names);
1167 
1168  return string;
1169 }
1170 
1171 
1181  int high_water_mark = OSL_MAX_STRING;
1182  char * string = NULL;
1183  char * temp;
1184  char buffer[OSL_MAX_STRING];
1185  OSL_malloc(string, char *, high_water_mark * sizeof(char));
1186  string[0] = '\0';
1187 
1188  if (osl_relation_nb_components(relation) > 0) {
1189  temp = osl_relation_sprint_type(relation);
1190  osl_util_safe_strcat(&string, temp, &high_water_mark);
1191  free(temp);
1192 
1193  snprintf(buffer, OSL_MAX_STRING, "\n");
1194  osl_util_safe_strcat(&string, buffer, &high_water_mark);
1195 
1196  temp = osl_relation_spprint_polylib(relation, names);
1197  osl_util_safe_strcat(&string, temp, &high_water_mark);
1198  free(temp);
1199  }
1200 
1201  return string;
1202 }
1203 
1204 
1216  int print_nth_part, int add_fakeiter) {
1217  int high_water_mark = OSL_MAX_STRING;
1218  char * string = NULL;
1219  char * temp;
1220  OSL_malloc(string, char *, high_water_mark * sizeof(char));
1221  string[0] = '\0';
1222 
1223  if (relation) {
1224  temp = osl_relation_spprint_polylib_scoplib(relation, names,
1225  print_nth_part, add_fakeiter);
1226  osl_util_safe_strcat(&string, temp, &high_water_mark);
1227  free(temp);
1228  }
1229 
1230  return string;
1231 }
1232 
1233 
1242 void osl_relation_pprint(FILE * file, osl_relation_p relation,
1243  osl_names_p names) {
1244  char * string = osl_relation_spprint(relation, names);
1245  fprintf(file, "%s", string);
1246  free(string);
1247 }
1248 
1249 
1260 void osl_relation_pprint_scoplib(FILE * file, osl_relation_p relation,
1261  osl_names_p names, int print_nth_part,
1262  int add_fakeiter) {
1263  char * string = osl_relation_spprint_scoplib(relation, names,
1264  print_nth_part, add_fakeiter);
1265  fprintf(file, "%s", string);
1266  free(string);
1267 }
1268 
1269 
1278 
1279  return osl_relation_spprint(relation, NULL);
1280 }
1281 
1282 
1290 void osl_relation_print(FILE * file, osl_relation_p relation) {
1291 
1292  osl_relation_pprint(file, relation, NULL);
1293 }
1294 
1295 
1296 /*****************************************************************************
1297  * Reading function *
1298  *****************************************************************************/
1299 
1300 
1312 static
1313 int osl_relation_read_type(FILE * file, char ** str) {
1314  int type;
1315  osl_strings_p strings;
1316 
1317  if ((file != NULL && str != NULL) || (file == NULL && str == NULL))
1318  OSL_error("one and only one of the two parameters can be non-NULL");
1319 
1320  if (file != NULL)
1321  strings = osl_strings_read(file);
1322  else
1323  strings = osl_strings_sread(str);
1324 
1325  if (osl_strings_size(strings) > 1) {
1326  OSL_warning("uninterpreted information (after the relation type)");
1327  }
1328  if (osl_strings_size(strings) == 0)
1329  OSL_error("no relation type");
1330 
1331  if (!strcmp(strings->string[0], OSL_STRING_UNDEFINED)) {
1332  type = OSL_UNDEFINED;
1333  goto return_type;
1334  }
1335 
1336  if (!strcmp(strings->string[0], OSL_STRING_CONTEXT)) {
1337  type = OSL_TYPE_CONTEXT;
1338  goto return_type;
1339  }
1340 
1341  if (!strcmp(strings->string[0], OSL_STRING_DOMAIN)) {
1342  type = OSL_TYPE_DOMAIN;
1343  goto return_type;
1344  }
1345 
1346  if (!strcmp(strings->string[0], OSL_STRING_SCATTERING)) {
1347  type = OSL_TYPE_SCATTERING;
1348  goto return_type;
1349  }
1350 
1351  if (!strcmp(strings->string[0], OSL_STRING_READ)) {
1352  type = OSL_TYPE_READ;
1353  goto return_type;
1354  }
1355 
1356  if (!strcmp(strings->string[0], OSL_STRING_WRITE)) {
1357  type = OSL_TYPE_WRITE;
1358  goto return_type;
1359  }
1360 
1361  if (!strcmp(strings->string[0], OSL_STRING_MAY_WRITE)) {
1362  type = OSL_TYPE_MAY_WRITE;
1363  goto return_type;
1364  }
1365 
1366  OSL_error("relation type not supported");
1367 
1368 return_type:
1369  osl_strings_free(strings);
1370  return type;
1371 }
1372 
1373 
1382 osl_relation_p osl_relation_pread(FILE * foo, int precision) {
1383  int i, j, k, n, read = 0;
1384  int nb_rows, nb_columns;
1385  int nb_output_dims, nb_input_dims, nb_local_dims, nb_parameters;
1386  int nb_union_parts = 1;
1387  int may_read_nb_union_parts = 1;
1388  int read_attributes = 1;
1389  int first = 1;
1390  int type;
1391  char * c, s[OSL_MAX_STRING], str[OSL_MAX_STRING], *tmp;
1392  osl_relation_p relation, relation_union = NULL, previous = NULL;
1393 
1394  type = osl_relation_read_type(foo, NULL);
1395 
1396  // Read each part of the union (the number of parts may be updated inside)
1397  for (k = 0; k < nb_union_parts; k++) {
1398  // Read the number of union parts or the attributes of the union part
1399  while (read_attributes) {
1400  read_attributes = 0;
1401 
1402  // Read relation attributes.
1404  read = sscanf(c, " %d %d %d %d %d %d", &nb_rows, &nb_columns,
1405  &nb_output_dims, &nb_input_dims,
1406  &nb_local_dims, &nb_parameters);
1407 
1408  if (((read != 1) && (read != 6)) ||
1409  ((read == 1) && (may_read_nb_union_parts != 1)))
1410  OSL_error("not 1 or 6 integers on the first relation line");
1411 
1412  if (read == 1) {
1413  // Only one number means a union and is the number of parts.
1414  nb_union_parts = nb_rows;
1415  if (nb_union_parts < 1)
1416  OSL_error("negative nb of union parts");
1417 
1418  // Allow to read the properties of the first part of the union.
1419  read_attributes = 1;
1420  }
1421 
1422  may_read_nb_union_parts = 0;
1423  }
1424 
1425  // Allocate the union part and fill its properties.
1426  relation = osl_relation_pmalloc(precision, nb_rows, nb_columns);
1427  relation->type = type;
1428  relation->nb_output_dims = nb_output_dims;
1429  relation->nb_input_dims = nb_input_dims;
1430  relation->nb_local_dims = nb_local_dims;
1431  relation->nb_parameters = nb_parameters;
1432 
1433  // Read the matrix of constraints.
1434  for (i = 0; i < relation->nb_rows; i++) {
1436  if (c == NULL)
1437  OSL_error("not enough rows");
1438 
1439  for (j = 0; j < relation->nb_columns; j++) {
1440  if (c == NULL || *c == '#' || *c == '\n')
1441  OSL_error("not enough columns");
1442  if (sscanf(c, "%s%n", str, &n) == 0)
1443  OSL_error("not enough rows");
1444 
1445  // TODO: remove this tmp (sread updates the pointer).
1446  tmp = str;
1447  osl_int_sread(&tmp, precision, &relation->m[i][j]);
1448  c += n;
1449  }
1450  }
1451 
1452  // Build the linked list of union parts.
1453  if (first == 1) {
1454  relation_union = relation;
1455  first = 0;
1456  }
1457  else {
1458  previous->next = relation;
1459  }
1460 
1461  previous = relation;
1462  read_attributes = 1;
1463  }
1464 
1465  return relation_union;
1466 }
1467 
1475 osl_relation_p osl_relation_psread(char ** input, int precision) {
1476  int type;
1477  osl_relation_p relation;
1478 
1479  type = osl_relation_read_type(NULL, input);
1480  relation = osl_relation_psread_polylib(input, precision);
1481  relation->type = type;
1482 
1483  return relation;
1484 }
1485 
1497 osl_relation_p osl_relation_psread_polylib(char ** input, int precision) {
1498  int i, j, k, n, read = 0;
1499  int nb_rows, nb_columns;
1500  int nb_output_dims, nb_input_dims, nb_local_dims, nb_parameters;
1501  int nb_union_parts = 1;
1502  int may_read_nb_union_parts = 1;
1503  int read_attributes = 1;
1504  int first = 1;
1505  char str[OSL_MAX_STRING], *tmp;
1506  osl_relation_p relation, relation_union = NULL, previous = NULL;
1507 
1508  // Read each part of the union (the number of parts may be updated inside)
1509  for (k = 0; k < nb_union_parts; k++) {
1510  // Read the number of union parts or the attributes of the union part
1511  while (read_attributes) {
1512  read_attributes = 0;
1513  // Read relation attributes.
1515  // make a copy of the first line
1516  tmp = *input;
1517  while ((*tmp != '\0') && (*tmp != '\n'))
1518  tmp++;
1519  strncpy(str, *input, sizeof(char) * (tmp-*input));
1520  str[(tmp-*input)] = '\0';
1521 
1522  read = sscanf(str, " %d %d %d %d %d %d",
1523  &nb_rows, &nb_columns,
1524  &nb_output_dims, &nb_input_dims,
1525  &nb_local_dims, &nb_parameters);
1526  *input = tmp;
1527 
1528  if (((read != 1) && (read != 6)) ||
1529  ((read == 1) && (may_read_nb_union_parts != 1)))
1530  OSL_error("not 1 or 6 integers on the first relation line");
1531 
1532  if (read == 1) {
1533  // Only one number means a union and is the number of parts.
1534  nb_union_parts = nb_rows;
1535  if (nb_union_parts < 1)
1536  OSL_error("negative nb of union parts");
1537 
1538  // Allow to read the properties of the first part of the union.
1539  read_attributes = 1;
1540  }
1541 
1542  may_read_nb_union_parts = 0;
1543  }
1544 
1545  // Allocate the union part and fill its properties.
1546  relation = osl_relation_pmalloc(precision, nb_rows, nb_columns);
1547  relation->nb_output_dims = nb_output_dims;
1548  relation->nb_input_dims = nb_input_dims;
1549  relation->nb_local_dims = nb_local_dims;
1550  relation->nb_parameters = nb_parameters;
1551 
1552  // Read the matrix of constraints.
1553  for (i = 0; i < relation->nb_rows; i++) {
1555  if (!(*input))
1556  OSL_error("not enough rows");
1557 
1558  for (j = 0; j < relation->nb_columns; j++) {
1559  if (*input == NULL || **input == '#' || **input == '\n')
1560  OSL_error("not enough columns");
1561  if (sscanf(*input, "%s%n", str, &n) == 0)
1562  OSL_error("not enough rows");
1563 
1564  // TODO: remove this tmp (sread updates the pointer).
1565  tmp = str;
1566  osl_int_sread(&tmp, precision, &relation->m[i][j]);
1567  *input += n;
1568  }
1569  }
1570 
1571  // Build the linked list of union parts.
1572  if (first == 1) {
1573  relation_union = relation;
1574  first = 0;
1575  }
1576  else {
1577  previous->next = relation;
1578  }
1579 
1580  previous = relation;
1581  read_attributes = 1;
1582  }
1583 
1584  return relation_union;
1585 }
1586 
1587 
1596  int precision = osl_util_get_precision();
1597  return osl_relation_psread(input, precision);
1598 }
1599 
1608  int precision = osl_util_get_precision();
1609  return osl_relation_psread_polylib(input, precision);
1610 }
1611 
1612 
1621  int precision = osl_util_get_precision();
1622  return osl_relation_pread(foo, precision);
1623 }
1624 
1625 
1626 /*+***************************************************************************
1627  * Memory allocation/deallocation function *
1628  *****************************************************************************/
1629 
1630 
1643  int nb_rows, int nb_columns) {
1644  osl_relation_p relation;
1645  osl_int_t ** p, * q;
1646  int i, j;
1647 
1648  if ((precision != OSL_PRECISION_SP) &&
1649  (precision != OSL_PRECISION_DP) &&
1650  (precision != OSL_PRECISION_MP))
1651  OSL_error("unknown precision");
1652 
1653  if ((nb_rows < 0) || (nb_columns < 0))
1654  OSL_error("negative sizes");
1655 
1656  OSL_malloc(relation, osl_relation_p, sizeof(osl_relation_t));
1657  relation->type = OSL_UNDEFINED;
1658  relation->nb_rows = nb_rows;
1659  relation->nb_columns = nb_columns;
1660  relation->nb_output_dims = OSL_UNDEFINED;
1661  relation->nb_input_dims = OSL_UNDEFINED;
1662  relation->nb_parameters = OSL_UNDEFINED;
1663  relation->nb_local_dims = OSL_UNDEFINED;
1664  relation->precision = precision;
1665 
1666  if ((nb_rows == 0) || (nb_columns == 0) ||
1667  (nb_rows == OSL_UNDEFINED) || (nb_columns == OSL_UNDEFINED)) {
1668  relation->m = NULL;
1669  }
1670  else {
1671  OSL_malloc(p, osl_int_t**, nb_rows * sizeof(osl_int_t*));
1672  OSL_malloc(q, osl_int_t*, nb_rows * nb_columns * sizeof(osl_int_t));
1673  relation->m = p;
1674  for (i = 0; i < nb_rows; i++) {
1675  relation->m[i] = q + i * nb_columns ;
1676  for (j = 0; j < nb_columns; j++)
1677  osl_int_init_set_si(precision, &relation->m[i][j], 0);
1678  }
1679  }
1680 
1681  relation->next = NULL;
1682 
1683  return relation;
1684 }
1685 
1686 
1694 osl_relation_p osl_relation_malloc(int nb_rows, int nb_columns) {
1695  int precision = osl_util_get_precision();
1696  return osl_relation_pmalloc(precision, nb_rows, nb_columns);
1697 }
1698 
1699 
1707  int i, nb_elements;
1708 
1709  if (relation == NULL)
1710  return;
1711 
1712  nb_elements = relation->nb_rows * relation->nb_columns;
1713 
1714  for (i = 0; i < nb_elements; i++)
1715  osl_int_clear(relation->precision, &relation->m[0][i]);
1716 
1717  if (relation->m != NULL) {
1718  if (nb_elements > 0)
1719  free(relation->m[0]);
1720  free(relation->m);
1721  }
1722 }
1723 
1724 
1732  osl_relation_p tmp;
1733 
1734  while (relation != NULL) {
1735  tmp = relation->next;
1736  osl_relation_free_inside(relation);
1737  free(relation);
1738  relation = tmp;
1739  }
1740 }
1741 
1742 
1743 /*+***************************************************************************
1744  * Processing functions *
1745  *****************************************************************************/
1746 
1747 
1759  int i, j, k;
1760  int first = 1, nb_components, nb_parts;
1761  osl_relation_p clone = NULL, node, previous = NULL;
1762 
1763  nb_components = osl_relation_nb_components(relation);
1764  nb_parts = (n == -1) ? nb_components : n;
1765  if (nb_components < nb_parts)
1766  OSL_error("not enough union parts to clone");
1767 
1768  for (k = 0; k < nb_parts; k++) {
1769  node = osl_relation_pmalloc(relation->precision,
1770  relation->nb_rows, relation->nb_columns);
1771  node->type = relation->type;
1772  node->nb_output_dims = relation->nb_output_dims;
1773  node->nb_input_dims = relation->nb_input_dims;
1774  node->nb_local_dims = relation->nb_local_dims;
1775  node->nb_parameters = relation->nb_parameters;
1776 
1777  for (i = 0; i < relation->nb_rows; i++)
1778  for (j = 0; j < relation->nb_columns; j++)
1779  osl_int_assign(relation->precision,
1780  &node->m[i][j], relation->m[i][j]);
1781 
1782  if (first) {
1783  first = 0;
1784  clone = node;
1785  previous = node;
1786  }
1787  else {
1788  previous->next = node;
1789  previous = previous->next;
1790  }
1791 
1792  relation = relation->next;
1793  }
1794 
1795  return clone;
1796 }
1797 
1798 
1812  int n) {
1813  int i, j;
1814  int first = 1, all_rows = 0;
1815  osl_relation_p clone = NULL, node, previous = NULL;
1816 
1817  if (n == -1)
1818  all_rows = 1;
1819 
1820  while (relation != NULL) {
1821  if (all_rows)
1822  n = relation->nb_rows;
1823 
1824  if (n > relation->nb_rows)
1825  OSL_error("not enough rows to clone in the relation");
1826 
1827  node = osl_relation_pmalloc(relation->precision, n, relation->nb_columns);
1828  node->type = relation->type;
1829  node->nb_output_dims = relation->nb_output_dims;
1830  node->nb_input_dims = relation->nb_input_dims;
1831  node->nb_local_dims = relation->nb_local_dims;
1832  node->nb_parameters = relation->nb_parameters;
1833 
1834  for (i = 0; i < n; i++)
1835  for (j = 0; j < relation->nb_columns; j++)
1836  osl_int_assign(relation->precision,
1837  &node->m[i][j], relation->m[i][j]);
1838 
1839  if (first) {
1840  first = 0;
1841  clone = node;
1842  previous = node;
1843  }
1844  else {
1845  previous->next = node;
1846  previous = previous->next;
1847  }
1848 
1849  relation = relation->next;
1850  }
1851 
1852  return clone;
1853 }
1854 
1855 
1864  if (relation == NULL)
1865  return NULL;
1866 
1867  return osl_relation_nclone(relation, -1);
1868 }
1869 
1870 
1881  while (*r1 != NULL)
1882  r1 = &((*r1)->next);
1883 
1884  *r1 = r2;
1885 }
1886 
1887 
1898  osl_relation_p r2) {
1899  osl_relation_p copy1, copy2;
1900 
1901  if ((r1 == NULL) && (r2 == NULL))
1902  return NULL;
1903 
1904  copy1 = osl_relation_clone(r1);
1905  copy2 = osl_relation_clone(r2);
1906  osl_relation_add(&copy1, copy2);
1907 
1908  return copy1;
1909 }
1910 
1911 
1922  osl_vector_p vector, int row) {
1923  int i;
1924 
1925  if ((relation == NULL) || (vector == NULL) ||
1926  (relation->precision != vector->precision) ||
1927  (relation->nb_columns != vector->size) ||
1928  (row >= relation->nb_rows) || (row < 0))
1929  OSL_error("vector cannot replace relation row");
1930 
1931  for (i = 0; i < vector->size; i++)
1932  osl_int_assign(relation->precision, &relation->m[row][i], vector->v[i]);
1933 }
1934 
1935 
1946  osl_vector_p vector, int row) {
1947  int i;
1948 
1949  if ((relation == NULL) || (vector == NULL) ||
1950  (relation->precision != vector->precision) ||
1951  (relation->nb_columns != vector->size) ||
1952  (row >= relation->nb_rows) || (row < 0))
1953  OSL_error("vector cannot be added to relation");
1954 
1955  if (osl_int_get_si(relation->precision, relation->m[row][0]) == 0)
1956  osl_int_assign(relation->precision, &relation->m[row][0], vector->v[0]);
1957 
1958  for (i = 1; i < vector->size; i++)
1959  osl_int_add(relation->precision,
1960  &relation->m[row][i], relation->m[row][i], vector->v[i]);
1961 }
1962 
1963 
1974  osl_vector_p vector, int row) {
1975  int i;
1976 
1977  if ((relation == NULL) || (vector == NULL) ||
1978  (relation->precision != vector->precision) ||
1979  (relation->nb_columns != vector->size) ||
1980  (row >= relation->nb_rows) || (row < 0))
1981  OSL_error("vector cannot be subtracted to row");
1982 
1983  if (osl_int_get_si(relation->precision, relation->m[row][0]) == 0)
1984  osl_int_assign(relation->precision, &relation->m[row][0], vector->v[0]);
1985 
1986  for (i = 1; i < vector->size; i++)
1987  osl_int_sub(relation->precision,
1988  &relation->m[row][i], relation->m[row][i], vector->v[i]);
1989 }
1990 
1991 
2006  osl_vector_p vector, int row) {
2007  osl_relation_p temp;
2008 
2009  temp = osl_relation_from_vector(vector);
2010  osl_relation_insert_constraints(relation, temp, row);
2011  osl_relation_free(temp);
2012 }
2013 
2014 
2027  osl_vector_p vector) {
2028  osl_relation_p new, temp;
2029 
2030  temp = osl_relation_from_vector(vector);
2031  new = osl_relation_concat_constraints(relation, temp);
2032  osl_relation_free(temp);
2033  return new;
2034 }
2035 
2036 
2045  osl_vector_p vector;
2046 
2047  if (relation != NULL) {
2048  vector = osl_vector_pmalloc(relation->precision, relation->nb_columns);
2049  osl_relation_insert_vector(relation, vector, row);
2050  osl_vector_free(vector);
2051  }
2052 }
2053 
2054 
2064 
2065  int i, j;
2066  osl_relation_p temp;
2067 
2068  if (relation == NULL)
2069  return;
2070 
2071  if ((column < 0) || (column > relation->nb_columns))
2072  OSL_error("bad column number");
2073 
2074  // We use a temporary relation just to reuse existing functions. Cleaner.
2075  temp = osl_relation_pmalloc(relation->precision,
2076  relation->nb_rows, relation->nb_columns + 1);
2077 
2078  for (i = 0; i < relation->nb_rows; i++) {
2079  for (j = 0; j < column; j++)
2080  osl_int_assign(relation->precision, &temp->m[i][j], relation->m[i][j]);
2081 
2082  for (j = column; j < relation->nb_columns; j++)
2083  osl_int_assign(relation->precision, &temp->m[i][j+1], relation->m[i][j]);
2084  }
2085 
2086  osl_relation_free_inside(relation);
2087 
2088  // Replace the inside of relation.
2089  relation->nb_columns = temp->nb_columns;
2090  relation->m = temp->m;
2091 
2092  // Free the temp "shell".
2093  free(temp);
2094 }
2095 
2096 
2105  osl_relation_p relation;
2106 
2107  if (vector == NULL)
2108  return NULL;
2109 
2110  relation = osl_relation_pmalloc(vector->precision, 1, vector->size);
2111  osl_relation_replace_vector(relation, vector, 0);
2112  return relation;
2113 }
2114 
2115 
2126  osl_relation_p r2, int row) {
2127  int i, j;
2128 
2129  if ((r1 == NULL) || (r2 == NULL) ||
2130  (r1->precision != r2->precision) ||
2131  (r1->nb_columns != r1->nb_columns) ||
2132  ((row + r2->nb_rows) > r1->nb_rows) || (row < 0))
2133  OSL_error("relation rows could not be replaced");
2134 
2135  for (i = 0; i < r2->nb_rows; i++)
2136  for (j = 0; j < r2->nb_columns; j++)
2137  osl_int_assign(r1->precision, &r1->m[i+row][j], r2->m[i][j]);
2138 }
2139 
2140 
2154  osl_relation_p r2, int row) {
2155  int i, j;
2156  osl_relation_p temp;
2157 
2158  if ((r1 == NULL) || (r2 == NULL))
2159  return;
2160 
2161  if (row == -1)
2162  row = r1->nb_rows;
2163 
2164  if ((r1->nb_columns != r2->nb_columns) ||
2165  (r1->precision != r2->precision) ||
2166  (row > r1->nb_rows) || (row < 0))
2167  OSL_error("constraints cannot be inserted");
2168 
2169  // We use a temporary relation just to reuse existing functions. Cleaner.
2170  temp = osl_relation_pmalloc(r1->precision,
2171  r1->nb_rows + r2->nb_rows, r1->nb_columns);
2172 
2173  for (i = 0; i < row; i++)
2174  for (j = 0; j < r1->nb_columns; j++)
2175  osl_int_assign(r1->precision, &temp->m[i][j], r1->m[i][j]);
2176 
2177  osl_relation_replace_constraints(temp, r2, row);
2178 
2179  for (i = row + r2->nb_rows; i < r2->nb_rows + r1->nb_rows; i++)
2180  for (j = 0; j < r1->nb_columns; j++)
2181  osl_int_assign(r1->precision, &temp->m[i][j], r1->m[i-r2->nb_rows][j]);
2182 
2184 
2185  // Replace the inside of relation.
2186  r1->nb_rows = temp->nb_rows;
2187  r1->m = temp->m;
2188 
2189  // Free the temp "shell".
2190  free(temp);
2191 }
2192 
2193 
2202 void osl_relation_swap_constraints(osl_relation_p relation, int c1, int c2) {
2203  int i;
2204 
2205  if ((relation == NULL) || (c1 == c2))
2206  return;
2207 
2208  if ((c1 >= relation->nb_rows) || (c1 < 0) ||
2209  (c2 >= relation->nb_rows) || (c2 < 0))
2210  OSL_error("bad constraint rows");
2211 
2212  for (i = 0; i < relation->nb_columns; i++)
2213  osl_int_swap(relation->precision,
2214  &relation->m[c1][i], &relation->m[c2][i]);
2215 }
2216 
2217 
2226  int i, j;
2227  osl_relation_p temp;
2228 
2229  if (r == NULL)
2230  return;
2231 
2232  if ((row < 0) || (row >= r->nb_rows))
2233  OSL_error("bad row number");
2234 
2235  // We use a temporary relation just to reuse existing functions. Cleaner.
2236  temp = osl_relation_pmalloc(r->precision,
2237  r->nb_rows - 1, r->nb_columns);
2238 
2239  for (i = 0; i < row; i++)
2240  for (j = 0; j < r->nb_columns; j++)
2241  osl_int_assign(r->precision, &temp->m[i][j], r->m[i][j]);
2242 
2243  for (i = row + 1; i < r->nb_rows; i++)
2244  for (j = 0; j < r->nb_columns; j++)
2245  osl_int_assign(r->precision, &temp->m[i - 1][j], r->m[i][j]);
2246 
2248 
2249  // Replace the inside of relation.
2250  r->nb_rows = temp->nb_rows;
2251  r->m = temp->m;
2252 
2253  // Free the temp "shell".
2254  free(temp);
2255 }
2256 
2257 
2266  int i, j;
2267  osl_relation_p temp;
2268 
2269  if (r == NULL)
2270  return;
2271 
2272  if ((column < 0) || (column >= r->nb_columns))
2273  OSL_error("bad column number");
2274 
2275  // We use a temporary relation just to reuse existing functions. Cleaner.
2276  temp = osl_relation_pmalloc(r->precision,
2277  r->nb_rows, r->nb_columns - 1);
2278 
2279  for (i = 0; i < r->nb_rows; i++) {
2280  for (j = 0; j < column; j++)
2281  osl_int_assign(r->precision, &temp->m[i][j], r->m[i][j]);
2282 
2283  for (j = column + 1; j < r->nb_columns; j++)
2284  osl_int_assign(r->precision, &temp->m[i][j - 1], r->m[i][j]);
2285  }
2286 
2288 
2289  // Replace the inside of relation.
2290  r->nb_columns = temp->nb_columns;
2291  r->m = temp->m;
2292 
2293  // Free the temp "shell".
2294  free(temp);
2295 }
2296 
2297 
2310  osl_relation_p insert, int column) {
2311  int i, j;
2312  osl_relation_p temp;
2313 
2314  if ((relation == NULL) || (insert == NULL))
2315  return;
2316 
2317  if ((relation->precision != insert->precision) ||
2318  (relation->nb_rows != insert->nb_rows) ||
2319  (column < 0) || (column > relation->nb_columns))
2320  OSL_error("columns cannot be inserted");
2321 
2322  // We use a temporary relation just to reuse existing functions. Cleaner.
2323  temp = osl_relation_pmalloc(relation->precision, relation->nb_rows,
2324  relation->nb_columns + insert->nb_columns);
2325 
2326  for (i = 0; i < relation->nb_rows; i++) {
2327  for (j = 0; j < column; j++)
2328  osl_int_assign(relation->precision, &temp->m[i][j], relation->m[i][j]);
2329 
2330  for (j = column; j < column + insert->nb_columns; j++)
2331  osl_int_assign(relation->precision,
2332  &temp->m[i][j], insert->m[i][j - column]);
2333 
2334  for (j = column + insert->nb_columns;
2335  j < insert->nb_columns + relation->nb_columns; j++)
2336  osl_int_assign(relation->precision,
2337  &temp->m[i][j], relation->m[i][j - insert->nb_columns]);
2338  }
2339 
2340  osl_relation_free_inside(relation);
2341 
2342  // Replace the inside of relation.
2343  relation->nb_columns = temp->nb_columns;
2344  relation->m = temp->m;
2345 
2346  // Free the temp "shell".
2347  free(temp);
2348 }
2349 
2350 
2363  osl_relation_p r1,
2364  osl_relation_p r2) {
2365  osl_relation_p new;
2366 
2367  if (r1 == NULL)
2368  return osl_relation_clone(r2);
2369 
2370  if (r2 == NULL)
2371  return osl_relation_clone(r1);
2372 
2373  if (r1->nb_columns != r2->nb_columns)
2374  OSL_error("incompatible sizes for concatenation");
2375 
2376  if (r1->next || r2->next)
2377  OSL_warning("relation concatenation is done on the first elements "
2378  "of union only");
2379 
2380  new = osl_relation_pmalloc(r1->precision,
2381  r1->nb_rows + r2->nb_rows, r1->nb_columns);
2384 
2385  return new;
2386 }
2387 
2388 
2399  int i, j;
2400 
2401  if (r1 == r2)
2402  return 1;
2403 
2404  if (((r1 == NULL) && (r2 != NULL)) ||
2405  ((r1 != NULL) && (r2 == NULL)))
2406  return 0;
2407 
2408  if ((r1->type != r2->type) ||
2409  (r1->precision != r2->precision) ||
2410  (r1->nb_rows != r2->nb_rows) ||
2411  (r1->nb_columns != r2->nb_columns) ||
2412  (r1->nb_output_dims != r2->nb_output_dims) ||
2413  (r1->nb_input_dims != r2->nb_input_dims) ||
2414  (r1->nb_local_dims != r2->nb_local_dims) ||
2415  (r1->nb_parameters != r2->nb_parameters))
2416  return 0;
2417 
2418  for (i = 0; i < r1->nb_rows; ++i)
2419  for (j = 0; j < r1->nb_columns; ++j)
2420  if (osl_int_ne(r1->precision, r1->m[i][j], r2->m[i][j]))
2421  return 0;
2422 
2423  return 1;
2424 }
2425 
2426 
2436  while ((r1 != NULL) && (r2 != NULL)) {
2437  if (!osl_relation_part_equal(r1, r2))
2438  return 0;
2439 
2440  r1 = r1->next;
2441  r2 = r2->next;
2442  }
2443 
2444  if (((r1 == NULL) && (r2 != NULL)) || ((r1 != NULL) && (r2 == NULL)))
2445  return 0;
2446 
2447  return 1;
2448 }
2449 
2450 
2464 static
2465 int osl_relation_check_attribute(int * expected, int actual) {
2466  if (*expected != OSL_UNDEFINED) {
2467  if ((actual != OSL_UNDEFINED) &&
2468  (actual != *expected)) {
2469  OSL_warning("unexpected atribute");
2470  return 0;
2471  }
2472  }
2473  else {
2474  *expected = actual;
2475  }
2476 
2477  return 1;
2478 }
2479 
2480 
2494 static
2496  int expected_nb_output_dims,
2497  int expected_nb_input_dims,
2498  int expected_nb_parameters) {
2499  int expected_nb_local_dims, expected_nb_columns;
2500 
2501  if ((expected_nb_output_dims != OSL_UNDEFINED) &&
2502  (expected_nb_input_dims != OSL_UNDEFINED) &&
2503  (expected_nb_parameters != OSL_UNDEFINED)) {
2504 
2505  if (relation->nb_local_dims == OSL_UNDEFINED)
2506  expected_nb_local_dims = 0;
2507  else
2508  expected_nb_local_dims = relation->nb_local_dims;
2509 
2510  expected_nb_columns = expected_nb_output_dims +
2511  expected_nb_input_dims +
2512  expected_nb_local_dims +
2513  expected_nb_parameters +
2514  2;
2515 
2516  if (expected_nb_columns != relation->nb_columns) {
2517  OSL_warning("unexpected number of columns");
2518  return 0;
2519  }
2520  }
2521 
2522  return 1;
2523 }
2524 
2525 
2541  int expected_type,
2542  int expected_nb_output_dims,
2543  int expected_nb_input_dims,
2544  int expected_nb_parameters) {
2545  int i;
2546 
2547  // Check the NULL case.
2548  if (relation == NULL) {
2549  if ((expected_nb_output_dims != OSL_UNDEFINED) ||
2550  (expected_nb_input_dims != OSL_UNDEFINED) ||
2551  (expected_nb_parameters != OSL_UNDEFINED)) {
2552  OSL_debug("NULL relation with some expected attibutes");
2553  //return 0;
2554  }
2555 
2556  return 1;
2557  }
2558 
2559  // Check the type.
2560  if (((expected_type != OSL_TYPE_ACCESS) &&
2561  (expected_type != relation->type)) ||
2562  ((expected_type == OSL_TYPE_ACCESS) &&
2563  (!osl_relation_is_access(relation)))) {
2564  OSL_warning("wrong type");
2565  osl_relation_dump(stderr, relation);
2566  return 0;
2567  }
2568 
2569  // Check that relations have no undefined atributes.
2570  if ((relation->nb_output_dims == OSL_UNDEFINED) ||
2571  (relation->nb_input_dims == OSL_UNDEFINED) ||
2572  (relation->nb_local_dims == OSL_UNDEFINED) ||
2573  (relation->nb_parameters == OSL_UNDEFINED)) {
2574  OSL_warning("all attributes should be defined");
2575  osl_relation_dump(stderr, relation);
2576  return 0;
2577  }
2578 
2579  // Check that a context has actually 0 output dimensions.
2580  if ((relation->type == OSL_TYPE_CONTEXT) &&
2581  (relation->nb_output_dims != 0)) {
2582  OSL_warning("context without 0 as number of output dimensions");
2583  osl_relation_dump(stderr, relation);
2584  return 0;
2585  }
2586 
2587  // Check that a domain or a context has actually 0 input dimensions.
2588  if (((relation->type == OSL_TYPE_DOMAIN) ||
2589  (relation->type == OSL_TYPE_CONTEXT)) &&
2590  (relation->nb_input_dims != 0)) {
2591  OSL_warning("domain or context without 0 input dimensions");
2592  osl_relation_dump(stderr, relation);
2593  return 0;
2594  }
2595 
2596  // Check properties according to expected values (and if expected values
2597  // are undefined, define them with the first relation part properties).
2598  if (!osl_relation_check_attribute(&expected_nb_output_dims,
2599  relation->nb_output_dims) ||
2600  !osl_relation_check_attribute(&expected_nb_input_dims,
2601  relation->nb_input_dims) ||
2602  !osl_relation_check_attribute(&expected_nb_parameters,
2603  relation->nb_parameters)) {
2604  osl_relation_dump(stderr, relation);
2605  return 0;
2606  }
2607 
2608  while (relation != NULL) {
2609 
2610  // Attributes (except the number of local dimensions) should be the same
2611  // in all parts of the union.
2612  if ((expected_nb_output_dims != relation->nb_output_dims) ||
2613  (expected_nb_input_dims != relation->nb_input_dims) ||
2614  (expected_nb_parameters != relation->nb_parameters)) {
2615  OSL_warning("inconsistent attributes");
2616  osl_relation_dump(stderr, relation);
2617  return 0;
2618  }
2619 
2620  // Check whether the number of columns is OK or not.
2621  if (!osl_relation_check_nb_columns(relation,
2622  expected_nb_output_dims,
2623  expected_nb_input_dims,
2624  expected_nb_parameters)) {
2625  osl_relation_dump(stderr, relation);
2626  return 0;
2627  }
2628 
2629  // Check the first column. The first column of a relation part should be
2630  // made of 0 or 1 only.
2631  if ((relation->nb_rows > 0) && (relation->nb_columns > 0)) {
2632  for (i = 0; i < relation->nb_rows; i++) {
2633  if (!osl_int_zero(relation->precision, relation->m[i][0]) &&
2634  !osl_int_one(relation->precision, relation->m[i][0])) {
2635  OSL_warning("first column of a relation is not "
2636  "strictly made of 0 or 1");
2637  osl_relation_dump(stderr, relation);
2638  return 0;
2639  }
2640  }
2641  }
2642 
2643  // Array accesses must provide the array identifier.
2644  if ((osl_relation_is_access(relation)) &&
2645  (osl_relation_get_array_id(relation) == OSL_UNDEFINED)) {
2646  osl_relation_dump(stderr, relation);
2647  return 0;
2648  }
2649 
2650  relation = relation->next;
2651  }
2652 
2653  return 1;
2654 }
2655 
2656 
2668  int nb_output_dims, int nb_input_dims,
2669  int nb_local_dims, int nb_parameters) {
2670  if (relation != NULL) {
2671  relation->nb_output_dims = nb_output_dims;
2672  relation->nb_input_dims = nb_input_dims;
2673  relation->nb_local_dims = nb_local_dims;
2674  relation->nb_parameters = nb_parameters;
2675  }
2676 }
2677 
2678 
2690  int nb_output_dims, int nb_input_dims,
2691  int nb_local_dims, int nb_parameters) {
2692  while (relation != NULL) {
2694  nb_output_dims, nb_input_dims,
2695  nb_local_dims, nb_parameters);
2696  relation = relation->next;
2697  }
2698 }
2699 
2700 
2708 void osl_relation_set_type(osl_relation_p relation, int type) {
2709 
2710  while (relation != NULL) {
2711  relation->type = type;
2712  relation = relation->next;
2713  }
2714 }
2715 
2716 
2726  int i;
2727  int first = 1;
2728  int array_id = OSL_UNDEFINED;
2729  int reference_array_id = OSL_UNDEFINED;
2730  int nb_array_id;
2731  int row_id = 0;
2732  int precision;
2733 
2734  if (relation == NULL)
2735  return OSL_UNDEFINED;
2736 
2737  if (!osl_relation_is_access(relation)) {
2738  OSL_warning("asked for an array id of non-array relation");
2739  return OSL_UNDEFINED;
2740  }
2741 
2742  while (relation != NULL) {
2743  precision = relation->precision;
2744 
2745  // There should be room to store the array identifier.
2746  if ((relation->nb_rows < 1) ||
2747  (relation->nb_columns < 3)) {
2748  OSL_warning("no array identifier in an access function");
2749  return OSL_UNDEFINED;
2750  }
2751 
2752  // Array identifiers are m[i][#columns -1] / m[i][1], with i the only row
2753  // where m[i][1] is not 0.
2754  // - check there is exactly one row such that m[i][1] is not 0,
2755  // - check the whole ith row if full of 0 except m[i][1] and the id,
2756  // - check that (m[i][#columns -1] % m[i][1]) == 0,
2757  // - check that (-m[i][#columns -1] / m[i][1]) > 0.
2758  nb_array_id = 0;
2759  for (i = 0; i < relation->nb_rows; i++) {
2760  if (!osl_int_zero(precision, relation->m[i][1])) {
2761  nb_array_id ++;
2762  row_id = i;
2763  }
2764  }
2765  if (nb_array_id == 0) {
2766  OSL_warning("no array identifier in an access function");
2767  return OSL_UNDEFINED;
2768  }
2769  if (nb_array_id > 1) {
2770  OSL_warning("several array identifiers in one access function");
2771  return OSL_UNDEFINED;
2772  }
2773  for (i = 0; i < relation->nb_columns - 1; i++) {
2774  if ((i != 1) && !osl_int_zero(precision, relation->m[row_id][i])) {
2775  OSL_warning("non integer array identifier");
2776  return OSL_UNDEFINED;
2777  }
2778  }
2779  if (!osl_int_divisible(precision,
2780  relation->m[row_id][relation->nb_columns - 1],
2781  relation->m[row_id][1])) {
2782  OSL_warning("rational array identifier");
2783  return OSL_UNDEFINED;
2784  }
2785  array_id = -osl_int_get_si(precision,
2786  relation->m[row_id][relation->nb_columns - 1]);
2787  array_id /= osl_int_get_si(precision, relation->m[row_id][1]);
2788  if (array_id <= 0) {
2789  OSL_warning("negative or 0 identifier in access function");
2790  return OSL_UNDEFINED;
2791  }
2792 
2793  // Unions of accesses are allowed, but they should refer at the same array.
2794  if (first) {
2795  reference_array_id = array_id;
2796  first = 0;
2797  }
2798  else {
2799  if (reference_array_id != array_id) {
2800  OSL_warning("inconsistency of array identifiers in an "
2801  "union of access relations");
2802  return OSL_UNDEFINED;
2803  }
2804  }
2805 
2806  relation = relation->next;
2807  }
2808 
2809  return array_id;
2810 }
2811 
2812 
2821 
2822  if (relation == NULL)
2823  return 0;
2824 
2825  if ((relation->type == OSL_TYPE_ACCESS) ||
2826  (relation->type == OSL_TYPE_READ) ||
2827  (relation->type == OSL_TYPE_WRITE) ||
2828  (relation->type == OSL_TYPE_MAY_WRITE))
2829  return 1;
2830 
2831  return 0;
2832 }
2833 
2834 
2854  int * nb_parameters,
2855  int * nb_iterators,
2856  int * nb_scattdims,
2857  int * nb_localdims,
2858  int * array_id) {
2859  int type;
2860  int local_nb_parameters = OSL_UNDEFINED;
2861  int local_nb_iterators = OSL_UNDEFINED;
2862  int local_nb_scattdims = OSL_UNDEFINED;
2863  int local_nb_localdims = OSL_UNDEFINED;
2864  int local_array_id = OSL_UNDEFINED;
2865 
2866  while (relation != NULL) {
2867  if (osl_relation_is_access(relation))
2868  type = OSL_TYPE_ACCESS;
2869  else
2870  type = relation->type;
2871 
2872  // There is some redundancy but I believe the code is cleaner this way.
2873  switch (type) {
2874  case OSL_TYPE_CONTEXT:
2875  local_nb_parameters = relation->nb_parameters;
2876  local_nb_iterators = 0;
2877  local_nb_scattdims = 0;
2878  local_nb_localdims = relation->nb_local_dims;
2879  local_array_id = 0;
2880  break;
2881 
2882  case OSL_TYPE_DOMAIN:
2883  local_nb_parameters = relation->nb_parameters;
2884  local_nb_iterators = relation->nb_output_dims;
2885  local_nb_scattdims = 0;
2886  local_nb_localdims = relation->nb_local_dims;
2887  local_array_id = 0;
2888  break;
2889 
2890  case OSL_TYPE_SCATTERING:
2891  local_nb_parameters = relation->nb_parameters;
2892  local_nb_iterators = relation->nb_input_dims;
2893  local_nb_scattdims = relation->nb_output_dims;
2894  local_nb_localdims = relation->nb_local_dims;
2895  local_array_id = 0;
2896  break;
2897 
2898  case OSL_TYPE_ACCESS:
2899  local_nb_parameters = relation->nb_parameters;
2900  local_nb_iterators = relation->nb_input_dims;
2901  local_nb_scattdims = 0;
2902  local_nb_localdims = relation->nb_local_dims;
2903  local_array_id = osl_relation_get_array_id(relation);
2904  break;
2905 
2906  default:
2907  local_nb_parameters = relation->nb_parameters;
2908  local_nb_iterators = relation->nb_input_dims;
2909  local_nb_scattdims = relation->nb_output_dims;
2910  local_nb_localdims = relation->nb_local_dims;
2911  local_array_id = 0;
2912  }
2913 
2914  // Update.
2915  *nb_parameters = OSL_max(*nb_parameters, local_nb_parameters);
2916  *nb_iterators = OSL_max(*nb_iterators, local_nb_iterators);
2917  *nb_scattdims = OSL_max(*nb_scattdims, local_nb_scattdims);
2918  *nb_localdims = OSL_max(*nb_localdims, local_nb_localdims);
2919  *array_id = OSL_max(*array_id, local_array_id);
2920  relation = relation->next;
2921  }
2922 }
2923 
2924 
2937  int i, j;
2938  int first = 1;
2939  int offset;
2940  int precision = relation->precision;
2941  osl_relation_p extended = NULL, node, previous = NULL;
2942 
2943  while (relation != NULL) {
2944  if (relation->nb_output_dims > dim)
2945  OSL_error("Number of output dims is greater than required extension");
2946  offset = dim - relation->nb_output_dims;
2947 
2948  node = osl_relation_pmalloc(precision,
2949  relation->nb_rows + offset,
2950  relation->nb_columns + offset);
2951 
2952  node->type = relation->type;
2953  node->nb_output_dims = OSL_max(relation->nb_output_dims, dim);
2954  node->nb_input_dims = relation->nb_input_dims;
2955  node->nb_local_dims = relation->nb_local_dims;
2956  node->nb_parameters = relation->nb_parameters;
2957 
2958  // Copy of the original relation with some 0 columns for the new dimensions
2959  // Note that we use the fact that the matrix is initialized with zeros.
2960  for (i = 0; i < relation->nb_rows; i++) {
2961  for (j = 0; j <= relation->nb_output_dims; j++)
2962  osl_int_assign(precision, &node->m[i][j], relation->m[i][j]);
2963 
2964  for (j = relation->nb_output_dims + offset + 1;
2965  j < relation->nb_columns + offset; j++)
2966  osl_int_assign(precision, &node->m[i][j], relation->m[i][j - offset]);
2967  }
2968 
2969  // New rows dedicated to the new dimensions
2970  for (i = relation->nb_rows; i < relation->nb_rows + offset; i++) {
2971  for (j = 0; j < relation->nb_columns + offset; j++) {
2972  if ((i - relation->nb_rows) == (j - relation->nb_output_dims - 1))
2973  osl_int_set_si(precision, &node->m[i][j], -1);
2974  }
2975  }
2976 
2977  if (first) {
2978  first = 0;
2979  extended = node;
2980  previous = node;
2981  }
2982  else {
2983  previous->next = node;
2984  previous = previous->next;
2985  }
2986 
2987  relation = relation->next;
2988  }
2989 
2990  return extended;
2991 }
2992 
2993 
3001  osl_interface_p interface = osl_interface_malloc();
3002 
3003  OSL_strdup(interface->URI, OSL_URI_RELATION);
3004  interface->idump = (osl_idump_f)osl_relation_idump;
3005  interface->sprint = (osl_sprint_f)osl_relation_sprint;
3006  interface->sread = (osl_sread_f)osl_relation_sread;
3007  interface->malloc = (osl_malloc_f)osl_relation_malloc;
3008  interface->free = (osl_free_f)osl_relation_free;
3009  interface->clone = (osl_clone_f)osl_relation_clone;
3010  interface->equal = (osl_equal_f)osl_relation_equal;
3011 
3012  return interface;
3013 }
3014 
3015 
3022 void osl_relation_set_precision(int const precision, osl_relation_p r) {
3023  while (r != NULL) {
3024  if (precision != r->precision) {
3025  size_t i;
3026  size_t j;
3027  for (i = 0; i < (size_t)r->nb_rows; ++i) {
3028  for (j = 0; j < (size_t)r->nb_columns; ++j) {
3029  osl_int_set_precision(r->precision, precision, &r->m[i][j]);
3030  }
3031  }
3032  r->precision = precision;
3033  }
3034  r = r->next;
3035  }
3036 }
3037 
3038 
3047  if (a != NULL && b != NULL && a->precision != b->precision) {
3048  if (a->precision == OSL_PRECISION_MP || b->precision == OSL_PRECISION_MP) {
3049  osl_relation_set_precision(OSL_PRECISION_MP, a);
3050  osl_relation_set_precision(OSL_PRECISION_MP, b);
3051  }
3052  else if (a->precision == OSL_PRECISION_DP || b->precision == OSL_PRECISION_DP) {
3053  osl_relation_set_precision(OSL_PRECISION_DP, a);
3054  osl_relation_set_precision(OSL_PRECISION_DP, b);
3055  }
3056  }
3057 }
int osl_int_get_si(int precision, osl_const_int_t value)
Get the value in a int.
Definition: int.c:236
char * osl_relation_spprint(osl_relation_p relation, osl_names_p names)
Definition: relation.c:1180
void osl_relation_free(osl_relation_p relation)
Definition: relation.c:1731
osl_names_p osl_names_generate(char *parameter_prefix, int nb_parameters, char *iterator_prefix, int nb_iterators, char *scatt_dim_prefix, int nb_scatt_dims, char *local_dim_prefix, int nb_local_dims, char *array_prefix, int nb_arrays)
Definition: names.c:206
char * osl_relation_expression(osl_relation_p relation, int row, char **strings)
Definition: relation.c:466
osl_relation_p osl_relation_clone_nconstraints(osl_relation_p relation, int n)
Definition: relation.c:1811
osl_relation_p osl_relation_pmalloc(int precision, int nb_rows, int nb_columns)
Definition: relation.c:1642
int osl_int_one(int precision, osl_const_int_t value)
value == 1
Definition: int.c:1224
void *(* osl_clone_f)(void *)
Definition: interface.h:80
void osl_int_oppose(int precision, osl_int_const_p variable, osl_const_int_t value)
variable = - value
Definition: int.c:981
int size
Definition: vector.h:86
int osl_int_divisible(int precision, osl_const_int_t val1, osl_const_int_t val2)
(val1 % val2) == 0
Definition: int.c:1275
static char * osl_relation_sprint_type(osl_relation_p relation)
Definition: relation.c:91
char ** string
Definition: strings.h:82
char * osl_relation_spprint_polylib_scoplib(osl_relation_p relation, osl_names_p names, int print_nth_part, int add_fakeiter)
Definition: relation.c:919
void osl_relation_free_inside(osl_relation_p relation)
Definition: relation.c:1706
struct osl_relation * next
Definition: relation.h:117
osl_relation_p osl_relation_union(osl_relation_p r1, osl_relation_p r2)
Definition: relation.c:1897
void osl_int_swap(int precision, osl_int_const_p var1, osl_int_const_p var2)
Swap the osl ints.
Definition: int.c:343
osl_interface_p osl_interface_malloc()
Definition: interface.c:212
static char * osl_relation_column_string_scoplib(osl_relation_p relation, char **strings)
Definition: relation.c:690
int nb_columns
Definition: relation.h:108
int osl_int_mone(int precision, osl_const_int_t value)
value == -1
Definition: int.c:1249
void osl_vector_free(osl_vector_p vector)
Definition: vector.c:197
char * osl_relation_sprint(osl_relation_p relation)
Definition: relation.c:1277
int precision
Definition: vector.h:85
int nb_local_dims
Definition: relation.h:111
void osl_int_sread(char **string, int precision, osl_int_const_p i)
sread for osl int
Definition: int.c:539
int osl_int_neg(int precision, osl_const_int_t value)
value < 0
Definition: int.c:1174
char * osl_relation_spprint_polylib(osl_relation_p relation, osl_names_p names)
Definition: relation.c:818
void osl_relation_print(FILE *file, osl_relation_p relation)
Definition: relation.c:1290
static void osl_relation_print_type(FILE *file, osl_relation_p relation)
Definition: relation.c:147
int osl_int_ne(int precision, osl_const_int_t val1, osl_const_int_t val2)
val1 != val2
Definition: int.c:1138
void osl_int_sub(int precision, osl_int_const_p variable, osl_const_int_t val1, osl_const_int_t val2)
variable = val1 - val2
Definition: int.c:685
void osl_relation_insert_constraints(osl_relation_p r1, osl_relation_p r2, int row)
Definition: relation.c:2153
int nb_parameters
Definition: relation.h:113
int nb_output_dims
Definition: relation.h:109
static char * osl_relation_column_string(osl_relation_p relation, char **strings)
Definition: relation.c:614
char * osl_util_strdup(char const *str)
String duplicate.
Definition: util.c:504
void osl_relation_set_attributes_one(osl_relation_p relation, int nb_output_dims, int nb_input_dims, int nb_local_dims, int nb_parameters)
Definition: relation.c:2667
osl_strings_p iterators
Definition: names.h:83
static char * osl_relation_sprint_comment(osl_relation_p relation, int row, char **strings, char **arrays)
Definition: relation.c:540
void *(* osl_sread_f)(char **)
Definition: interface.h:77
void osl_int_clear(int precision, osl_int_const_p variable)
variable = 0 // including cleaning for GMP
Definition: int.c:382
void osl_relation_pprint(FILE *file, osl_relation_p relation, osl_names_p names)
Definition: relation.c:1242
Definition: int.h:79
osl_strings_p osl_strings_sread(char **input)
Definition: strings.c:194
osl_int_t ** m
Definition: relation.h:114
int osl_relation_get_array_id(osl_relation_p relation)
Definition: relation.c:2725
void osl_int_set_precision(int const precision, int const new_precision, osl_int_p i)
Change the precision of the osl_int.
Definition: int.c:1306
void osl_relation_dump(FILE *file, osl_relation_p relation)
Definition: relation.c:246
osl_strings_p local_dims
Definition: names.h:85
int osl_relation_is_access(osl_relation_p relation)
Definition: relation.c:2820
void osl_util_safe_strcat(char **dst, char *src, int *hwm)
Definition: util.c:483
int osl_relation_equal(osl_relation_p r1, osl_relation_p r2)
Definition: relation.c:2435
void osl_relation_idump(FILE *file, osl_relation_p relation, int level)
Definition: relation.c:164
static int osl_relation_is_simple_output(osl_relation_p relation, int row)
Definition: relation.c:487
void osl_int_init_set_si(int precision, osl_int_const_p variable, int i)
variable = i // including initialization for GMP
Definition: int.c:314
static char * osl_relation_subexpression(osl_relation_p relation, int row, int start, int stop, int oppose, char **strings)
Definition: relation.c:420
void osl_relation_insert_blank_column(osl_relation_p relation, int column)
Definition: relation.c:2063
int nb_input_dims
Definition: relation.h:110
int osl_util_get_precision()
Definition: util.c:518
void osl_int_print(FILE *file, int precision, osl_const_int_t value)
Definition: int.c:423
int precision
Definition: relation.h:106
osl_strings_p osl_strings_read(FILE *file)
Definition: strings.c:259
void osl_relation_replace_constraints(osl_relation_p r1, osl_relation_p r2, int row)
Definition: relation.c:2125
osl_vector_p osl_vector_pmalloc(int precision, int size)
Definition: vector.c:157
void osl_relation_pprint_scoplib(FILE *file, osl_relation_p relation, osl_names_p names, int print_nth_part, int add_fakeiter)
Definition: relation.c:1260
void osl_relation_sub_vector(osl_relation_p relation, osl_vector_p vector, int row)
Definition: relation.c:1973
size_t osl_strings_size(osl_const_strings_const_p strings)
Definition: strings.c:413
void osl_util_sskip_blank_and_comments(char **str)
Definition: util.c:113
void(* osl_idump_f)(FILE *, void *, int)
Definition: interface.h:75
void osl_relation_replace_vector(osl_relation_p relation, osl_vector_p vector, int row)
Definition: relation.c:1921
char * osl_relation_spprint_scoplib(osl_relation_p relation, osl_names_p names, int print_nth_part, int add_fakeiter)
Definition: relation.c:1215
osl_relation_p osl_relation_read(FILE *foo)
Definition: relation.c:1620
void osl_relation_set_type(osl_relation_p relation, int type)
Definition: relation.c:2708
void osl_relation_get_attributes(osl_relation_p relation, int *nb_parameters, int *nb_iterators, int *nb_scattdims, int *nb_localdims, int *array_id)
Definition: relation.c:2853
static int osl_relation_read_type(FILE *file, char **str)
Definition: relation.c:1313
void osl_names_free(osl_names_p names)
Definition: names.c:172
void osl_relation_insert_blank_row(osl_relation_p relation, int row)
Definition: relation.c:2044
osl_strings_p arrays
Definition: names.h:86
static int osl_relation_check_nb_columns(osl_relation_p relation, int expected_nb_output_dims, int expected_nb_input_dims, int expected_nb_parameters)
Definition: relation.c:2495
void osl_int_set_si(int precision, osl_int_const_p variable, int i)
variable = i
Definition: int.c:208
int osl_relation_integrity_check(osl_relation_p relation, int expected_type, int expected_nb_output_dims, int expected_nb_input_dims, int expected_nb_parameters)
Definition: relation.c:2540
void osl_relation_insert_columns(osl_relation_p relation, osl_relation_p insert, int column)
Definition: relation.c:2309
void osl_int_sprint_txt(char *string, int precision, osl_const_int_t value)
Definition: int.c:471
char *(* osl_sprint_f)(void *)
Definition: interface.h:76
osl_relation_p osl_relation_sread(char **input)
Definition: relation.c:1595
char * osl_util_skip_blank_and_comments(FILE *file, char *str)
Definition: util.c:91
osl_int_t * v
Definition: vector.h:87
void osl_int_add(int precision, osl_int_const_p variable, osl_const_int_t val1, osl_const_int_t val2)
variable = val1 + val2
Definition: int.c:581
osl_relation_p osl_relation_sread_polylib(char **input)
Definition: relation.c:1607
void osl_relation_add(osl_relation_p *r1, osl_relation_p r2)
Definition: relation.c:1880
osl_relation_p osl_relation_clone(osl_relation_p relation)
Definition: relation.c:1863
void osl_relation_remove_column(osl_relation_p r, int column)
Definition: relation.c:2265
int osl_relation_nb_components(osl_relation_p relation)
Definition: relation.c:797
void osl_relation_add_vector(osl_relation_p relation, osl_vector_p vector, int row)
Definition: relation.c:1945
osl_relation_p osl_relation_malloc(int nb_rows, int nb_columns)
Definition: relation.c:1694
osl_relation_p osl_relation_nclone(osl_relation_p relation, int n)
Definition: relation.c:1758
void *(* osl_malloc_f)()
Definition: interface.h:78
static char * osl_relation_expression_element(osl_int_t val, int precision, int *first, int cst, char *name)
Definition: relation.c:266
osl_relation_p osl_relation_concat_constraints(osl_relation_p r1, osl_relation_p r2)
Definition: relation.c:2362
osl_strings_p scatt_dims
Definition: names.h:84
void osl_relation_remove_row(osl_relation_p r, int row)
Definition: relation.c:2225
static int osl_relation_check_attribute(int *expected, int actual)
Definition: relation.c:2465
void osl_relation_swap_constraints(osl_relation_p relation, int c1, int c2)
Definition: relation.c:2202
void osl_strings_free(osl_strings_p strings)
Definition: strings.c:299
osl_strings_p parameters
Definition: names.h:82
int(* osl_equal_f)(void *, void *)
Definition: interface.h:81
void osl_relation_insert_vector(osl_relation_p relation, osl_vector_p vector, int row)
Definition: relation.c:2005
void osl_relation_set_precision(int const precision, osl_relation_p r)
Definition: relation.c:3022
osl_relation_p osl_relation_psread_polylib(char **input, int precision)
Definition: relation.c:1497
void osl_int_sprint(char *string, int precision, osl_const_int_t value)
Definition: int.c:439
static char ** osl_relation_strings(osl_relation_p relation, osl_names_p names)
Definition: relation.c:343
void osl_relation_set_attributes(osl_relation_p relation, int nb_output_dims, int nb_input_dims, int nb_local_dims, int nb_parameters)
Definition: relation.c:2689
void osl_int_assign(int precision, osl_int_const_p variable, osl_const_int_t value)
variable = value
Definition: int.c:179
osl_relation_p osl_relation_psread(char **input, int precision)
Definition: relation.c:1475
int osl_relation_part_equal(osl_relation_p r1, osl_relation_p r2)
Definition: relation.c:2398
osl_relation_p osl_relation_from_vector(osl_vector_p vector)
Definition: relation.c:2104
int osl_int_zero(int precision, osl_const_int_t value)
value == 0
Definition: int.c:1199
osl_relation_p osl_relation_extend_output(osl_relation_p relation, int dim)
Definition: relation.c:2936
osl_relation_p osl_relation_pread(FILE *foo, int precision)
Definition: relation.c:1382
int osl_int_pos(int precision, osl_const_int_t value)
value > 0
Definition: int.c:1149
osl_interface_p osl_relation_interface()
Definition: relation.c:3000
osl_relation_p osl_relation_concat_vector(osl_relation_p relation, osl_vector_p vector)
Definition: relation.c:2026
void osl_relation_set_same_precision(osl_relation_p a, osl_relation_p b)
Definition: relation.c:3046
void osl_int_dump_precision(FILE *file, int precision)
Definition: int.c:113
static osl_names_p osl_relation_names(osl_relation_p relation)
Definition: relation.c:772
void(* osl_free_f)(void *)
Definition: interface.h:79