OpenScop  0.9.1
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 **, ((size_t)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  size_t 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  size_t 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  size_t 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  size_t 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  size_t 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 row
1516  size_t row_size = 0;
1517  tmp = *input;
1518  while ((*tmp != '\0') && (*tmp != '\n')) {
1519  tmp++;
1520  row_size += 1;
1521  }
1522  strncpy(str, *input, sizeof(char) * row_size);
1523  str[(tmp-*input)] = '\0';
1524 
1525  read = sscanf(str, " %d %d %d %d %d %d",
1526  &nb_rows, &nb_columns,
1527  &nb_output_dims, &nb_input_dims,
1528  &nb_local_dims, &nb_parameters);
1529  *input = tmp;
1530 
1531  if (((read != 1) && (read != 6)) ||
1532  ((read == 1) && (may_read_nb_union_parts != 1)))
1533  OSL_error("not 1 or 6 integers on the first relation line");
1534 
1535  if (read == 1) {
1536  // Only one number means a union and is the number of parts.
1537  nb_union_parts = nb_rows;
1538  if (nb_union_parts < 1)
1539  OSL_error("negative nb of union parts");
1540 
1541  // Allow to read the properties of the first part of the union.
1542  read_attributes = 1;
1543  }
1544 
1545  may_read_nb_union_parts = 0;
1546  }
1547 
1548  // Allocate the union part and fill its properties.
1549  relation = osl_relation_pmalloc(precision, nb_rows, nb_columns);
1550  relation->nb_output_dims = nb_output_dims;
1551  relation->nb_input_dims = nb_input_dims;
1552  relation->nb_local_dims = nb_local_dims;
1553  relation->nb_parameters = nb_parameters;
1554 
1555  // Read the matrix of constraints.
1556  for (i = 0; i < relation->nb_rows; i++) {
1558  if (!(*input))
1559  OSL_error("not enough rows");
1560 
1561  for (j = 0; j < relation->nb_columns; j++) {
1562  if (*input == NULL || **input == '#' || **input == '\n')
1563  OSL_error("not enough columns");
1564  if (sscanf(*input, "%s%n", str, &n) == 0)
1565  OSL_error("not enough rows");
1566 
1567  // TODO: remove this tmp (sread updates the pointer).
1568  tmp = str;
1569  osl_int_sread(&tmp, precision, &relation->m[i][j]);
1570  *input += n;
1571  }
1572  }
1573 
1574  // Build the linked list of union parts.
1575  if (first == 1) {
1576  relation_union = relation;
1577  first = 0;
1578  }
1579  else {
1580  previous->next = relation;
1581  }
1582 
1583  previous = relation;
1584  read_attributes = 1;
1585  }
1586 
1587  return relation_union;
1588 }
1589 
1590 
1599  int precision = osl_util_get_precision();
1600  return osl_relation_psread(input, precision);
1601 }
1602 
1611  int precision = osl_util_get_precision();
1612  return osl_relation_psread_polylib(input, precision);
1613 }
1614 
1615 
1624  int precision = osl_util_get_precision();
1625  return osl_relation_pread(foo, precision);
1626 }
1627 
1628 
1629 /*+***************************************************************************
1630  * Memory allocation/deallocation function *
1631  *****************************************************************************/
1632 
1633 
1646  int nb_rows, int nb_columns) {
1647  osl_relation_p relation;
1648  osl_int_t ** p, * q;
1649  int i, j;
1650 
1651  if ((precision != OSL_PRECISION_SP) &&
1652  (precision != OSL_PRECISION_DP) &&
1653  (precision != OSL_PRECISION_MP))
1654  OSL_error("unknown precision");
1655 
1656  if ((nb_rows < 0) || (nb_columns < 0))
1657  OSL_error("negative sizes");
1658 
1659  OSL_malloc(relation, osl_relation_p, sizeof(osl_relation_t));
1660  relation->type = OSL_UNDEFINED;
1661  relation->nb_rows = nb_rows;
1662  relation->nb_columns = nb_columns;
1663  relation->nb_output_dims = OSL_UNDEFINED;
1664  relation->nb_input_dims = OSL_UNDEFINED;
1665  relation->nb_parameters = OSL_UNDEFINED;
1666  relation->nb_local_dims = OSL_UNDEFINED;
1667  relation->precision = precision;
1668 
1669  if ((nb_rows == 0) || (nb_columns == 0) ||
1670  (nb_rows == OSL_UNDEFINED) || (nb_columns == OSL_UNDEFINED)) {
1671  relation->m = NULL;
1672  }
1673  else {
1674  OSL_malloc(p, osl_int_t**, (size_t)nb_rows * sizeof(osl_int_t*));
1675  OSL_malloc(q, osl_int_t*, (size_t)nb_rows * (size_t)nb_columns * sizeof(osl_int_t));
1676  relation->m = p;
1677  for (i = 0; i < nb_rows; i++) {
1678  relation->m[i] = q + i * nb_columns ;
1679  for (j = 0; j < nb_columns; j++)
1680  osl_int_init_set_si(precision, &relation->m[i][j], 0);
1681  }
1682  }
1683 
1684  relation->next = NULL;
1685 
1686  return relation;
1687 }
1688 
1689 
1697 osl_relation_p osl_relation_malloc(int nb_rows, int nb_columns) {
1698  int precision = osl_util_get_precision();
1699  return osl_relation_pmalloc(precision, nb_rows, nb_columns);
1700 }
1701 
1702 
1710  int i, nb_elements;
1711 
1712  if (relation == NULL)
1713  return;
1714 
1715  nb_elements = relation->nb_rows * relation->nb_columns;
1716 
1717  for (i = 0; i < nb_elements; i++)
1718  osl_int_clear(relation->precision, &relation->m[0][i]);
1719 
1720  if (relation->m != NULL) {
1721  if (nb_elements > 0)
1722  free(relation->m[0]);
1723  free(relation->m);
1724  }
1725 }
1726 
1727 
1735  osl_relation_p tmp;
1736 
1737  while (relation != NULL) {
1738  tmp = relation->next;
1739  osl_relation_free_inside(relation);
1740  free(relation);
1741  relation = tmp;
1742  }
1743 }
1744 
1745 
1746 /*+***************************************************************************
1747  * Processing functions *
1748  *****************************************************************************/
1749 
1750 
1762  int i, j, k;
1763  int first = 1, nb_components, nb_parts;
1764  osl_relation_p clone = NULL, node, previous = NULL;
1765 
1766  nb_components = osl_relation_nb_components(relation);
1767  nb_parts = (n == -1) ? nb_components : n;
1768  if (nb_components < nb_parts)
1769  OSL_error("not enough union parts to clone");
1770 
1771  for (k = 0; k < nb_parts; k++) {
1772  node = osl_relation_pmalloc(relation->precision,
1773  relation->nb_rows, relation->nb_columns);
1774  node->type = relation->type;
1775  node->nb_output_dims = relation->nb_output_dims;
1776  node->nb_input_dims = relation->nb_input_dims;
1777  node->nb_local_dims = relation->nb_local_dims;
1778  node->nb_parameters = relation->nb_parameters;
1779 
1780  for (i = 0; i < relation->nb_rows; i++)
1781  for (j = 0; j < relation->nb_columns; j++)
1782  osl_int_assign(relation->precision,
1783  &node->m[i][j], relation->m[i][j]);
1784 
1785  if (first) {
1786  first = 0;
1787  clone = node;
1788  previous = node;
1789  }
1790  else {
1791  previous->next = node;
1792  previous = previous->next;
1793  }
1794 
1795  relation = relation->next;
1796  }
1797 
1798  return clone;
1799 }
1800 
1801 
1815  int n) {
1816  int i, j;
1817  int first = 1, all_rows = 0;
1818  osl_relation_p clone = NULL, node, previous = NULL;
1819 
1820  if (n == -1)
1821  all_rows = 1;
1822 
1823  while (relation != NULL) {
1824  if (all_rows)
1825  n = relation->nb_rows;
1826 
1827  if (n > relation->nb_rows)
1828  OSL_error("not enough rows to clone in the relation");
1829 
1830  node = osl_relation_pmalloc(relation->precision, n, relation->nb_columns);
1831  node->type = relation->type;
1832  node->nb_output_dims = relation->nb_output_dims;
1833  node->nb_input_dims = relation->nb_input_dims;
1834  node->nb_local_dims = relation->nb_local_dims;
1835  node->nb_parameters = relation->nb_parameters;
1836 
1837  for (i = 0; i < n; i++)
1838  for (j = 0; j < relation->nb_columns; j++)
1839  osl_int_assign(relation->precision,
1840  &node->m[i][j], relation->m[i][j]);
1841 
1842  if (first) {
1843  first = 0;
1844  clone = node;
1845  previous = node;
1846  }
1847  else {
1848  previous->next = node;
1849  previous = previous->next;
1850  }
1851 
1852  relation = relation->next;
1853  }
1854 
1855  return clone;
1856 }
1857 
1858 
1867  if (relation == NULL)
1868  return NULL;
1869 
1870  return osl_relation_nclone(relation, -1);
1871 }
1872 
1873 
1884  while (*r1 != NULL)
1885  r1 = &((*r1)->next);
1886 
1887  *r1 = r2;
1888 }
1889 
1890 
1901  osl_relation_p r2) {
1902  osl_relation_p copy1, copy2;
1903 
1904  if ((r1 == NULL) && (r2 == NULL))
1905  return NULL;
1906 
1907  copy1 = osl_relation_clone(r1);
1908  copy2 = osl_relation_clone(r2);
1909  osl_relation_add(&copy1, copy2);
1910 
1911  return copy1;
1912 }
1913 
1914 
1925  osl_vector_p vector, int row) {
1926  int i;
1927 
1928  if ((relation == NULL) || (vector == NULL) ||
1929  (relation->precision != vector->precision) ||
1930  (relation->nb_columns != vector->size) ||
1931  (row >= relation->nb_rows) || (row < 0))
1932  OSL_error("vector cannot replace relation row");
1933 
1934  for (i = 0; i < vector->size; i++)
1935  osl_int_assign(relation->precision, &relation->m[row][i], vector->v[i]);
1936 }
1937 
1938 
1949  osl_vector_p vector, int row) {
1950  int i;
1951 
1952  if ((relation == NULL) || (vector == NULL) ||
1953  (relation->precision != vector->precision) ||
1954  (relation->nb_columns != vector->size) ||
1955  (row >= relation->nb_rows) || (row < 0))
1956  OSL_error("vector cannot be added to relation");
1957 
1958  if (osl_int_get_si(relation->precision, relation->m[row][0]) == 0)
1959  osl_int_assign(relation->precision, &relation->m[row][0], vector->v[0]);
1960 
1961  for (i = 1; i < vector->size; i++)
1962  osl_int_add(relation->precision,
1963  &relation->m[row][i], relation->m[row][i], vector->v[i]);
1964 }
1965 
1966 
1977  osl_vector_p vector, int row) {
1978  int i;
1979 
1980  if ((relation == NULL) || (vector == NULL) ||
1981  (relation->precision != vector->precision) ||
1982  (relation->nb_columns != vector->size) ||
1983  (row >= relation->nb_rows) || (row < 0))
1984  OSL_error("vector cannot be subtracted to row");
1985 
1986  if (osl_int_get_si(relation->precision, relation->m[row][0]) == 0)
1987  osl_int_assign(relation->precision, &relation->m[row][0], vector->v[0]);
1988 
1989  for (i = 1; i < vector->size; i++)
1990  osl_int_sub(relation->precision,
1991  &relation->m[row][i], relation->m[row][i], vector->v[i]);
1992 }
1993 
1994 
2009  osl_vector_p vector, int row) {
2010  osl_relation_p temp;
2011 
2012  temp = osl_relation_from_vector(vector);
2013  osl_relation_insert_constraints(relation, temp, row);
2014  osl_relation_free(temp);
2015 }
2016 
2017 
2030  osl_vector_p vector) {
2031  osl_relation_p new, temp;
2032 
2033  temp = osl_relation_from_vector(vector);
2034  new = osl_relation_concat_constraints(relation, temp);
2035  osl_relation_free(temp);
2036  return new;
2037 }
2038 
2039 
2048  osl_vector_p vector;
2049 
2050  if (relation != NULL) {
2051  vector = osl_vector_pmalloc(relation->precision, relation->nb_columns);
2052  osl_relation_insert_vector(relation, vector, row);
2053  osl_vector_free(vector);
2054  }
2055 }
2056 
2057 
2067 
2068  int i, j;
2069  osl_relation_p temp;
2070 
2071  if (relation == NULL)
2072  return;
2073 
2074  if ((column < 0) || (column > relation->nb_columns))
2075  OSL_error("bad column number");
2076 
2077  // We use a temporary relation just to reuse existing functions. Cleaner.
2078  temp = osl_relation_pmalloc(relation->precision,
2079  relation->nb_rows, relation->nb_columns + 1);
2080 
2081  for (i = 0; i < relation->nb_rows; i++) {
2082  for (j = 0; j < column; j++)
2083  osl_int_assign(relation->precision, &temp->m[i][j], relation->m[i][j]);
2084 
2085  for (j = column; j < relation->nb_columns; j++)
2086  osl_int_assign(relation->precision, &temp->m[i][j+1], relation->m[i][j]);
2087  }
2088 
2089  osl_relation_free_inside(relation);
2090 
2091  // Replace the inside of relation.
2092  relation->nb_columns = temp->nb_columns;
2093  relation->m = temp->m;
2094 
2095  // Free the temp "shell".
2096  free(temp);
2097 }
2098 
2099 
2108  osl_relation_p relation;
2109 
2110  if (vector == NULL)
2111  return NULL;
2112 
2113  relation = osl_relation_pmalloc(vector->precision, 1, vector->size);
2114  osl_relation_replace_vector(relation, vector, 0);
2115  return relation;
2116 }
2117 
2118 
2129  osl_relation_p r2, int row) {
2130  int i, j;
2131 
2132  if ((r1 == NULL) || (r2 == NULL) ||
2133  (r1->precision != r2->precision) ||
2134  (r1->nb_columns != r2->nb_columns) ||
2135  ((row + r2->nb_rows) > r1->nb_rows) || (row < 0))
2136  OSL_error("relation rows could not be replaced");
2137 
2138  for (i = 0; i < r2->nb_rows; i++)
2139  for (j = 0; j < r2->nb_columns; j++)
2140  osl_int_assign(r1->precision, &r1->m[i+row][j], r2->m[i][j]);
2141 }
2142 
2143 
2157  osl_relation_p r2, int row) {
2158  int i, j;
2159  osl_relation_p temp;
2160 
2161  if ((r1 == NULL) || (r2 == NULL))
2162  return;
2163 
2164  if (row == -1)
2165  row = r1->nb_rows;
2166 
2167  if ((r1->nb_columns != r2->nb_columns) ||
2168  (r1->precision != r2->precision) ||
2169  (row > r1->nb_rows) || (row < 0))
2170  OSL_error("constraints cannot be inserted");
2171 
2172  // We use a temporary relation just to reuse existing functions. Cleaner.
2173  temp = osl_relation_pmalloc(r1->precision,
2174  r1->nb_rows + r2->nb_rows, r1->nb_columns);
2175 
2176  for (i = 0; i < row; i++)
2177  for (j = 0; j < r1->nb_columns; j++)
2178  osl_int_assign(r1->precision, &temp->m[i][j], r1->m[i][j]);
2179 
2180  osl_relation_replace_constraints(temp, r2, row);
2181 
2182  for (i = row + r2->nb_rows; i < r2->nb_rows + r1->nb_rows; i++)
2183  for (j = 0; j < r1->nb_columns; j++)
2184  osl_int_assign(r1->precision, &temp->m[i][j], r1->m[i-r2->nb_rows][j]);
2185 
2187 
2188  // Replace the inside of relation.
2189  r1->nb_rows = temp->nb_rows;
2190  r1->m = temp->m;
2191 
2192  // Free the temp "shell".
2193  free(temp);
2194 }
2195 
2196 
2205 void osl_relation_swap_constraints(osl_relation_p relation, int c1, int c2) {
2206  int i;
2207 
2208  if ((relation == NULL) || (c1 == c2))
2209  return;
2210 
2211  if ((c1 >= relation->nb_rows) || (c1 < 0) ||
2212  (c2 >= relation->nb_rows) || (c2 < 0))
2213  OSL_error("bad constraint rows");
2214 
2215  for (i = 0; i < relation->nb_columns; i++)
2216  osl_int_swap(relation->precision,
2217  &relation->m[c1][i], &relation->m[c2][i]);
2218 }
2219 
2220 
2229  int i, j;
2230  osl_relation_p temp;
2231 
2232  if (r == NULL)
2233  return;
2234 
2235  if ((row < 0) || (row >= r->nb_rows))
2236  OSL_error("bad row number");
2237 
2238  // We use a temporary relation just to reuse existing functions. Cleaner.
2239  temp = osl_relation_pmalloc(r->precision,
2240  r->nb_rows - 1, r->nb_columns);
2241 
2242  for (i = 0; i < row; i++)
2243  for (j = 0; j < r->nb_columns; j++)
2244  osl_int_assign(r->precision, &temp->m[i][j], r->m[i][j]);
2245 
2246  for (i = row + 1; i < r->nb_rows; i++)
2247  for (j = 0; j < r->nb_columns; j++)
2248  osl_int_assign(r->precision, &temp->m[i - 1][j], r->m[i][j]);
2249 
2251 
2252  // Replace the inside of relation.
2253  r->nb_rows = temp->nb_rows;
2254  r->m = temp->m;
2255 
2256  // Free the temp "shell".
2257  free(temp);
2258 }
2259 
2260 
2269  int i, j;
2270  osl_relation_p temp;
2271 
2272  if (r == NULL)
2273  return;
2274 
2275  if ((column < 0) || (column >= r->nb_columns))
2276  OSL_error("bad column number");
2277 
2278  // We use a temporary relation just to reuse existing functions. Cleaner.
2279  temp = osl_relation_pmalloc(r->precision,
2280  r->nb_rows, r->nb_columns - 1);
2281 
2282  for (i = 0; i < r->nb_rows; i++) {
2283  for (j = 0; j < column; j++)
2284  osl_int_assign(r->precision, &temp->m[i][j], r->m[i][j]);
2285 
2286  for (j = column + 1; j < r->nb_columns; j++)
2287  osl_int_assign(r->precision, &temp->m[i][j - 1], r->m[i][j]);
2288  }
2289 
2291 
2292  // Replace the inside of relation.
2293  r->nb_columns = temp->nb_columns;
2294  r->m = temp->m;
2295 
2296  // Free the temp "shell".
2297  free(temp);
2298 }
2299 
2300 
2313  osl_relation_p insert, int column) {
2314  int i, j;
2315  osl_relation_p temp;
2316 
2317  if ((relation == NULL) || (insert == NULL))
2318  return;
2319 
2320  if ((relation->precision != insert->precision) ||
2321  (relation->nb_rows != insert->nb_rows) ||
2322  (column < 0) || (column > relation->nb_columns))
2323  OSL_error("columns cannot be inserted");
2324 
2325  // We use a temporary relation just to reuse existing functions. Cleaner.
2326  temp = osl_relation_pmalloc(relation->precision, relation->nb_rows,
2327  relation->nb_columns + insert->nb_columns);
2328 
2329  for (i = 0; i < relation->nb_rows; i++) {
2330  for (j = 0; j < column; j++)
2331  osl_int_assign(relation->precision, &temp->m[i][j], relation->m[i][j]);
2332 
2333  for (j = column; j < column + insert->nb_columns; j++)
2334  osl_int_assign(relation->precision,
2335  &temp->m[i][j], insert->m[i][j - column]);
2336 
2337  for (j = column + insert->nb_columns;
2338  j < insert->nb_columns + relation->nb_columns; j++)
2339  osl_int_assign(relation->precision,
2340  &temp->m[i][j], relation->m[i][j - insert->nb_columns]);
2341  }
2342 
2343  osl_relation_free_inside(relation);
2344 
2345  // Replace the inside of relation.
2346  relation->nb_columns = temp->nb_columns;
2347  relation->m = temp->m;
2348 
2349  // Free the temp "shell".
2350  free(temp);
2351 }
2352 
2353 
2366  osl_relation_p r1,
2367  osl_relation_p r2) {
2368  osl_relation_p new;
2369 
2370  if (r1 == NULL)
2371  return osl_relation_clone(r2);
2372 
2373  if (r2 == NULL)
2374  return osl_relation_clone(r1);
2375 
2376  if (r1->nb_columns != r2->nb_columns)
2377  OSL_error("incompatible sizes for concatenation");
2378 
2379  if (r1->next || r2->next)
2380  OSL_warning("relation concatenation is done on the first elements "
2381  "of union only");
2382 
2383  new = osl_relation_pmalloc(r1->precision,
2384  r1->nb_rows + r2->nb_rows, r1->nb_columns);
2387 
2388  return new;
2389 }
2390 
2391 
2402  int i, j;
2403 
2404  if (r1 == r2)
2405  return 1;
2406 
2407  if (((r1 == NULL) && (r2 != NULL)) ||
2408  ((r1 != NULL) && (r2 == NULL)))
2409  return 0;
2410 
2411  if ((r1->type != r2->type) ||
2412  (r1->precision != r2->precision) ||
2413  (r1->nb_rows != r2->nb_rows) ||
2414  (r1->nb_columns != r2->nb_columns) ||
2415  (r1->nb_output_dims != r2->nb_output_dims) ||
2416  (r1->nb_input_dims != r2->nb_input_dims) ||
2417  (r1->nb_local_dims != r2->nb_local_dims) ||
2418  (r1->nb_parameters != r2->nb_parameters))
2419  return 0;
2420 
2421  for (i = 0; i < r1->nb_rows; ++i)
2422  for (j = 0; j < r1->nb_columns; ++j)
2423  if (osl_int_ne(r1->precision, r1->m[i][j], r2->m[i][j]))
2424  return 0;
2425 
2426  return 1;
2427 }
2428 
2429 
2439  while ((r1 != NULL) && (r2 != NULL)) {
2440  if (!osl_relation_part_equal(r1, r2))
2441  return 0;
2442 
2443  r1 = r1->next;
2444  r2 = r2->next;
2445  }
2446 
2447  if (((r1 == NULL) && (r2 != NULL)) || ((r1 != NULL) && (r2 == NULL)))
2448  return 0;
2449 
2450  return 1;
2451 }
2452 
2453 
2467 static
2468 int osl_relation_check_attribute(int * expected, int actual) {
2469  if (*expected != OSL_UNDEFINED) {
2470  if ((actual != OSL_UNDEFINED) &&
2471  (actual != *expected)) {
2472  OSL_warning("unexpected atribute");
2473  return 0;
2474  }
2475  }
2476  else {
2477  *expected = actual;
2478  }
2479 
2480  return 1;
2481 }
2482 
2483 
2497 static
2499  int expected_nb_output_dims,
2500  int expected_nb_input_dims,
2501  int expected_nb_parameters) {
2502  int expected_nb_local_dims, expected_nb_columns;
2503 
2504  if ((expected_nb_output_dims != OSL_UNDEFINED) &&
2505  (expected_nb_input_dims != OSL_UNDEFINED) &&
2506  (expected_nb_parameters != OSL_UNDEFINED)) {
2507 
2508  if (relation->nb_local_dims == OSL_UNDEFINED)
2509  expected_nb_local_dims = 0;
2510  else
2511  expected_nb_local_dims = relation->nb_local_dims;
2512 
2513  expected_nb_columns = expected_nb_output_dims +
2514  expected_nb_input_dims +
2515  expected_nb_local_dims +
2516  expected_nb_parameters +
2517  2;
2518 
2519  if (expected_nb_columns != relation->nb_columns) {
2520  OSL_warning("unexpected number of columns");
2521  return 0;
2522  }
2523  }
2524 
2525  return 1;
2526 }
2527 
2528 
2544  int expected_type,
2545  int expected_nb_output_dims,
2546  int expected_nb_input_dims,
2547  int expected_nb_parameters) {
2548  int i;
2549 
2550  // Check the NULL case.
2551  if (relation == NULL) {
2552  if ((expected_nb_output_dims != OSL_UNDEFINED) ||
2553  (expected_nb_input_dims != OSL_UNDEFINED) ||
2554  (expected_nb_parameters != OSL_UNDEFINED)) {
2555  OSL_debug("NULL relation with some expected attibutes");
2556  //return 0;
2557  }
2558 
2559  return 1;
2560  }
2561 
2562  // Check the type.
2563  if (((expected_type != OSL_TYPE_ACCESS) &&
2564  (expected_type != relation->type)) ||
2565  ((expected_type == OSL_TYPE_ACCESS) &&
2566  (!osl_relation_is_access(relation)))) {
2567  OSL_warning("wrong type");
2568  osl_relation_dump(stderr, relation);
2569  return 0;
2570  }
2571 
2572  // Check that relations have no undefined atributes.
2573  if ((relation->nb_output_dims == OSL_UNDEFINED) ||
2574  (relation->nb_input_dims == OSL_UNDEFINED) ||
2575  (relation->nb_local_dims == OSL_UNDEFINED) ||
2576  (relation->nb_parameters == OSL_UNDEFINED)) {
2577  OSL_warning("all attributes should be defined");
2578  osl_relation_dump(stderr, relation);
2579  return 0;
2580  }
2581 
2582  // Check that a context has actually 0 output dimensions.
2583  if ((relation->type == OSL_TYPE_CONTEXT) &&
2584  (relation->nb_output_dims != 0)) {
2585  OSL_warning("context without 0 as number of output dimensions");
2586  osl_relation_dump(stderr, relation);
2587  return 0;
2588  }
2589 
2590  // Check that a domain or a context has actually 0 input dimensions.
2591  if (((relation->type == OSL_TYPE_DOMAIN) ||
2592  (relation->type == OSL_TYPE_CONTEXT)) &&
2593  (relation->nb_input_dims != 0)) {
2594  OSL_warning("domain or context without 0 input dimensions");
2595  osl_relation_dump(stderr, relation);
2596  return 0;
2597  }
2598 
2599  // Check properties according to expected values (and if expected values
2600  // are undefined, define them with the first relation part properties).
2601  if (!osl_relation_check_attribute(&expected_nb_output_dims,
2602  relation->nb_output_dims) ||
2603  !osl_relation_check_attribute(&expected_nb_input_dims,
2604  relation->nb_input_dims) ||
2605  !osl_relation_check_attribute(&expected_nb_parameters,
2606  relation->nb_parameters)) {
2607  osl_relation_dump(stderr, relation);
2608  return 0;
2609  }
2610 
2611  while (relation != NULL) {
2612 
2613  // Attributes (except the number of local dimensions) should be the same
2614  // in all parts of the union.
2615  if ((expected_nb_output_dims != relation->nb_output_dims) ||
2616  (expected_nb_input_dims != relation->nb_input_dims) ||
2617  (expected_nb_parameters != relation->nb_parameters)) {
2618  OSL_warning("inconsistent attributes");
2619  osl_relation_dump(stderr, relation);
2620  return 0;
2621  }
2622 
2623  // Check whether the number of columns is OK or not.
2624  if (!osl_relation_check_nb_columns(relation,
2625  expected_nb_output_dims,
2626  expected_nb_input_dims,
2627  expected_nb_parameters)) {
2628  osl_relation_dump(stderr, relation);
2629  return 0;
2630  }
2631 
2632  // Check the first column. The first column of a relation part should be
2633  // made of 0 or 1 only.
2634  if ((relation->nb_rows > 0) && (relation->nb_columns > 0)) {
2635  for (i = 0; i < relation->nb_rows; i++) {
2636  if (!osl_int_zero(relation->precision, relation->m[i][0]) &&
2637  !osl_int_one(relation->precision, relation->m[i][0])) {
2638  OSL_warning("first column of a relation is not "
2639  "strictly made of 0 or 1");
2640  osl_relation_dump(stderr, relation);
2641  return 0;
2642  }
2643  }
2644  }
2645 
2646  // Array accesses must provide the array identifier.
2647  if ((osl_relation_is_access(relation)) &&
2648  (osl_relation_get_array_id(relation) == OSL_UNDEFINED)) {
2649  osl_relation_dump(stderr, relation);
2650  return 0;
2651  }
2652 
2653  relation = relation->next;
2654  }
2655 
2656  return 1;
2657 }
2658 
2659 
2671  int nb_output_dims, int nb_input_dims,
2672  int nb_local_dims, int nb_parameters) {
2673  if (relation != NULL) {
2674  relation->nb_output_dims = nb_output_dims;
2675  relation->nb_input_dims = nb_input_dims;
2676  relation->nb_local_dims = nb_local_dims;
2677  relation->nb_parameters = nb_parameters;
2678  }
2679 }
2680 
2681 
2693  int nb_output_dims, int nb_input_dims,
2694  int nb_local_dims, int nb_parameters) {
2695  while (relation != NULL) {
2697  nb_output_dims, nb_input_dims,
2698  nb_local_dims, nb_parameters);
2699  relation = relation->next;
2700  }
2701 }
2702 
2703 
2711 void osl_relation_set_type(osl_relation_p relation, int type) {
2712 
2713  while (relation != NULL) {
2714  relation->type = type;
2715  relation = relation->next;
2716  }
2717 }
2718 
2719 
2729  int i;
2730  int first = 1;
2731  int array_id = OSL_UNDEFINED;
2732  int reference_array_id = OSL_UNDEFINED;
2733  int nb_array_id;
2734  int row_id = 0;
2735  int precision;
2736 
2737  if (relation == NULL)
2738  return OSL_UNDEFINED;
2739 
2740  if (!osl_relation_is_access(relation)) {
2741  OSL_warning("asked for an array id of non-array relation");
2742  return OSL_UNDEFINED;
2743  }
2744 
2745  while (relation != NULL) {
2746  precision = relation->precision;
2747 
2748  // There should be room to store the array identifier.
2749  if ((relation->nb_rows < 1) ||
2750  (relation->nb_columns < 3)) {
2751  OSL_warning("no array identifier in an access function");
2752  return OSL_UNDEFINED;
2753  }
2754 
2755  // Array identifiers are m[i][#columns -1] / m[i][1], with i the only row
2756  // where m[i][1] is not 0.
2757  // - check there is exactly one row such that m[i][1] is not 0,
2758  // - check the whole ith row if full of 0 except m[i][1] and the id,
2759  // - check that (m[i][#columns -1] % m[i][1]) == 0,
2760  // - check that (-m[i][#columns -1] / m[i][1]) > 0.
2761  nb_array_id = 0;
2762  for (i = 0; i < relation->nb_rows; i++) {
2763  if (!osl_int_zero(precision, relation->m[i][1])) {
2764  nb_array_id ++;
2765  row_id = i;
2766  }
2767  }
2768  if (nb_array_id == 0) {
2769  OSL_warning("no array identifier in an access function");
2770  return OSL_UNDEFINED;
2771  }
2772  if (nb_array_id > 1) {
2773  OSL_warning("several array identifiers in one access function");
2774  return OSL_UNDEFINED;
2775  }
2776  for (i = 0; i < relation->nb_columns - 1; i++) {
2777  if ((i != 1) && !osl_int_zero(precision, relation->m[row_id][i])) {
2778  OSL_warning("non integer array identifier");
2779  return OSL_UNDEFINED;
2780  }
2781  }
2782  if (!osl_int_divisible(precision,
2783  relation->m[row_id][relation->nb_columns - 1],
2784  relation->m[row_id][1])) {
2785  OSL_warning("rational array identifier");
2786  return OSL_UNDEFINED;
2787  }
2788  array_id = -osl_int_get_si(precision,
2789  relation->m[row_id][relation->nb_columns - 1]);
2790  array_id /= osl_int_get_si(precision, relation->m[row_id][1]);
2791  if (array_id <= 0) {
2792  OSL_warning("negative or 0 identifier in access function");
2793  return OSL_UNDEFINED;
2794  }
2795 
2796  // Unions of accesses are allowed, but they should refer at the same array.
2797  if (first) {
2798  reference_array_id = array_id;
2799  first = 0;
2800  }
2801  else {
2802  if (reference_array_id != array_id) {
2803  OSL_warning("inconsistency of array identifiers in an "
2804  "union of access relations");
2805  return OSL_UNDEFINED;
2806  }
2807  }
2808 
2809  relation = relation->next;
2810  }
2811 
2812  return array_id;
2813 }
2814 
2815 
2824 
2825  if (relation == NULL)
2826  return 0;
2827 
2828  if ((relation->type == OSL_TYPE_ACCESS) ||
2829  (relation->type == OSL_TYPE_READ) ||
2830  (relation->type == OSL_TYPE_WRITE) ||
2831  (relation->type == OSL_TYPE_MAY_WRITE))
2832  return 1;
2833 
2834  return 0;
2835 }
2836 
2837 
2857  int * nb_parameters,
2858  int * nb_iterators,
2859  int * nb_scattdims,
2860  int * nb_localdims,
2861  int * array_id) {
2862  int type;
2863  int local_nb_parameters = OSL_UNDEFINED;
2864  int local_nb_iterators = OSL_UNDEFINED;
2865  int local_nb_scattdims = OSL_UNDEFINED;
2866  int local_nb_localdims = OSL_UNDEFINED;
2867  int local_array_id = OSL_UNDEFINED;
2868 
2869  while (relation != NULL) {
2870  if (osl_relation_is_access(relation))
2871  type = OSL_TYPE_ACCESS;
2872  else
2873  type = relation->type;
2874 
2875  // There is some redundancy but I believe the code is cleaner this way.
2876  switch (type) {
2877  case OSL_TYPE_CONTEXT:
2878  local_nb_parameters = relation->nb_parameters;
2879  local_nb_iterators = 0;
2880  local_nb_scattdims = 0;
2881  local_nb_localdims = relation->nb_local_dims;
2882  local_array_id = 0;
2883  break;
2884 
2885  case OSL_TYPE_DOMAIN:
2886  local_nb_parameters = relation->nb_parameters;
2887  local_nb_iterators = relation->nb_output_dims;
2888  local_nb_scattdims = 0;
2889  local_nb_localdims = relation->nb_local_dims;
2890  local_array_id = 0;
2891  break;
2892 
2893  case OSL_TYPE_SCATTERING:
2894  local_nb_parameters = relation->nb_parameters;
2895  local_nb_iterators = relation->nb_input_dims;
2896  local_nb_scattdims = relation->nb_output_dims;
2897  local_nb_localdims = relation->nb_local_dims;
2898  local_array_id = 0;
2899  break;
2900 
2901  case OSL_TYPE_ACCESS:
2902  local_nb_parameters = relation->nb_parameters;
2903  local_nb_iterators = relation->nb_input_dims;
2904  local_nb_scattdims = 0;
2905  local_nb_localdims = relation->nb_local_dims;
2906  local_array_id = osl_relation_get_array_id(relation);
2907  break;
2908 
2909  default:
2910  local_nb_parameters = relation->nb_parameters;
2911  local_nb_iterators = relation->nb_input_dims;
2912  local_nb_scattdims = relation->nb_output_dims;
2913  local_nb_localdims = relation->nb_local_dims;
2914  local_array_id = 0;
2915  }
2916 
2917  // Update.
2918  *nb_parameters = OSL_max(*nb_parameters, local_nb_parameters);
2919  *nb_iterators = OSL_max(*nb_iterators, local_nb_iterators);
2920  *nb_scattdims = OSL_max(*nb_scattdims, local_nb_scattdims);
2921  *nb_localdims = OSL_max(*nb_localdims, local_nb_localdims);
2922  *array_id = OSL_max(*array_id, local_array_id);
2923  relation = relation->next;
2924  }
2925 }
2926 
2927 
2940  int i, j;
2941  int first = 1;
2942  int offset;
2943  int precision = relation->precision;
2944  osl_relation_p extended = NULL, node, previous = NULL;
2945 
2946  while (relation != NULL) {
2947  if (relation->nb_output_dims > dim)
2948  OSL_error("Number of output dims is greater than required extension");
2949  offset = dim - relation->nb_output_dims;
2950 
2951  node = osl_relation_pmalloc(precision,
2952  relation->nb_rows + offset,
2953  relation->nb_columns + offset);
2954 
2955  node->type = relation->type;
2956  node->nb_output_dims = OSL_max(relation->nb_output_dims, dim);
2957  node->nb_input_dims = relation->nb_input_dims;
2958  node->nb_local_dims = relation->nb_local_dims;
2959  node->nb_parameters = relation->nb_parameters;
2960 
2961  // Copy of the original relation with some 0 columns for the new dimensions
2962  // Note that we use the fact that the matrix is initialized with zeros.
2963  for (i = 0; i < relation->nb_rows; i++) {
2964  for (j = 0; j <= relation->nb_output_dims; j++)
2965  osl_int_assign(precision, &node->m[i][j], relation->m[i][j]);
2966 
2967  for (j = relation->nb_output_dims + offset + 1;
2968  j < relation->nb_columns + offset; j++)
2969  osl_int_assign(precision, &node->m[i][j], relation->m[i][j - offset]);
2970  }
2971 
2972  // New rows dedicated to the new dimensions
2973  for (i = relation->nb_rows; i < relation->nb_rows + offset; i++) {
2974  for (j = 0; j < relation->nb_columns + offset; j++) {
2975  if ((i - relation->nb_rows) == (j - relation->nb_output_dims - 1))
2976  osl_int_set_si(precision, &node->m[i][j], -1);
2977  }
2978  }
2979 
2980  if (first) {
2981  first = 0;
2982  extended = node;
2983  previous = node;
2984  }
2985  else {
2986  previous->next = node;
2987  previous = previous->next;
2988  }
2989 
2990  relation = relation->next;
2991  }
2992 
2993  return extended;
2994 }
2995 
2996 
3004  osl_interface_p interface = osl_interface_malloc();
3005 
3006  OSL_strdup(interface->URI, OSL_URI_RELATION);
3007  interface->idump = (osl_idump_f)osl_relation_idump;
3008  interface->sprint = (osl_sprint_f)osl_relation_sprint;
3009  interface->sread = (osl_sread_f)osl_relation_sread;
3010  interface->malloc = (osl_malloc_f)osl_relation_malloc;
3011  interface->free = (osl_free_f)osl_relation_free;
3012  interface->clone = (osl_clone_f)osl_relation_clone;
3013  interface->equal = (osl_equal_f)osl_relation_equal;
3014 
3015  return interface;
3016 }
3017 
3018 
3025 void osl_relation_set_precision(int const precision, osl_relation_p r) {
3026  while (r != NULL) {
3027  if (precision != r->precision) {
3028  size_t i;
3029  size_t j;
3030  for (i = 0; i < (size_t)r->nb_rows; ++i) {
3031  for (j = 0; j < (size_t)r->nb_columns; ++j) {
3032  osl_int_set_precision(r->precision, precision, &r->m[i][j]);
3033  }
3034  }
3035  r->precision = precision;
3036  }
3037  r = r->next;
3038  }
3039 }
3040 
3041 
3050  if (a != NULL && b != NULL && a->precision != b->precision) {
3054  }
3055  else if (a->precision == OSL_PRECISION_DP || b->precision == OSL_PRECISION_DP) {
3058  }
3059  }
3060 }
3061 
3071  osl_relation_p part) {
3072  osl_relation_p relation, previous;
3073 
3074  if (relation_list == NULL || *relation_list == NULL || part == NULL) {
3075  return;
3076  }
3077 
3078  if (*relation_list == part) {
3079  *relation_list = (*relation_list)->next;
3080  return;
3081  }
3082 
3083  previous = *relation_list;
3084  for (relation = (*relation_list)->next; relation != NULL;
3085  relation = relation->next) {
3086  if (relation == part) {
3087  previous->next = relation->next;
3088  relation->next = NULL;
3089  osl_relation_free(relation);
3090  return;
3091  }
3092  previous = relation;
3093  }
3094 }
3095 
int osl_int_divisible(int precision, osl_const_int_t val1, osl_const_int_t val2)
(val1 % val2) == 0
Definition: int.c:1399
void *(* osl_clone_f)(void *)
Definition: interface.h:80
void osl_int_print(FILE *file, int precision, osl_const_int_t value)
Definition: int.c:423
void osl_relation_print(FILE *file, osl_relation_p relation)
Definition: relation.c:1290
#define OSL_error(msg)
Definition: macros.h:149
void *(* osl_sread_f)(char **)
Definition: interface.h:77
#define OSL_TYPE_DOMAIN
Definition: macros.h:101
void osl_int_dump_precision(FILE *file, int precision)
Definition: int.c:113
#define OSL_warning(msg)
Definition: macros.h:144
osl_relation_p osl_relation_clone_nconstraints(osl_relation_p relation, int n)
Definition: relation.c:1814
int osl_int_get_si(int precision, osl_const_int_t value)
Get the value in a int.
Definition: int.c:236
void osl_int_swap(int precision, osl_int_const_p var1, osl_int_const_p var2)
Swap the osl ints.
Definition: int.c:343
#define OSL_STRING_MAY_WRITE
Definition: macros.h:121
osl_interface_p osl_relation_interface(void)
Definition: relation.c:3003
osl_strings_p scatt_dims
Definition: names.h:84
void osl_relation_free_inside(osl_relation_p relation)
Definition: relation.c:1709
osl_relation_p osl_relation_extend_output(osl_relation_p relation, int dim)
Definition: relation.c:2939
void(* osl_idump_f)(FILE *, void *, int)
Definition: interface.h:75
osl_strings_p parameters
Definition: names.h:82
int size
Definition: vector.h:86
void osl_int_set_si(int precision, osl_int_const_p variable, int i)
variable = i
Definition: int.c:208
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
int nb_output_dims
Definition: relation.h:109
char ** string
Definition: strings.h:82
int precision
Definition: vector.h:85
static char * osl_relation_sprint_type(osl_relation_p relation)
Definition: relation.c:91
int osl_int_one(int precision, osl_const_int_t value)
value == 1
Definition: int.c:1348
osl_interface_p osl_interface_malloc(void)
Definition: interface.c:212
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
int nb_parameters
Definition: relation.h:113
int osl_relation_get_array_id(osl_relation_p relation)
Definition: relation.c:2728
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
int nb_columns
Definition: relation.h:108
void osl_relation_free(osl_relation_p relation)
Definition: relation.c:1734
void osl_relation_idump(FILE *file, osl_relation_p relation, int level)
Definition: relation.c:164
int nb_input_dims
Definition: relation.h:110
osl_int_t ** m
Definition: relation.h:114
void osl_util_safe_strcat(char **dst, char *src, size_t *hwm)
Definition: util.c:482
char *(* osl_sprint_f)(void *)
Definition: interface.h:76
#define OSL_TYPE_READ
Definition: macros.h:104
void osl_int_sprint(char *string, int precision, osl_const_int_t value)
Definition: int.c:439
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
static char * osl_relation_column_string(osl_relation_p relation, char **strings)
Definition: relation.c:614
#define OSL_debug(msg)
Definition: macros.h:133
static char * osl_relation_sprint_comment(osl_relation_p relation, int row, char **strings, char **arrays)
Definition: relation.c:540
Definition: int.h:81
osl_relation_p osl_relation_read(FILE *foo)
Definition: relation.c:1623
void osl_relation_insert_constraints(osl_relation_p r1, osl_relation_p r2, int row)
Definition: relation.c:2156
static int osl_relation_read_type(FILE *file, char **str)
Definition: relation.c:1313
void osl_relation_pprint(FILE *file, osl_relation_p relation, osl_names_p names)
Definition: relation.c:1242
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:1430
#define OSL_TYPE_CONTEXT
Definition: macros.h:100
#define OSL_strdup(destination, source)
Definition: macros.h:169
int osl_int_ne(int precision, osl_const_int_t val1, osl_const_int_t val2)
val1 != val2
Definition: int.c:1171
void *(* osl_malloc_f)(void)
Definition: interface.h:78
osl_vector_p osl_vector_pmalloc(int precision, int size)
Definition: vector.c:157
osl_relation_p osl_relation_union(osl_relation_p r1, osl_relation_p r2)
Definition: relation.c:1900
#define OSL_TYPE_MAY_WRITE
Definition: macros.h:106
#define OSL_STRING_CONTEXT
Definition: macros.h:116
static char * osl_relation_column_string_scoplib(osl_relation_p relation, char **strings)
Definition: relation.c:690
static int osl_relation_is_simple_output(osl_relation_p relation, int row)
Definition: relation.c:487
#define OSL_STRING_WRITE
Definition: macros.h:120
void osl_relation_insert_blank_column(osl_relation_p relation, int column)
Definition: relation.c:2066
osl_relation_p osl_relation_sread(char **input)
Definition: relation.c:1598
char * osl_util_strdup(char const *str)
String duplicate.
Definition: util.c:503
char * osl_relation_sprint(osl_relation_p relation)
Definition: relation.c:1277
int(* osl_equal_f)(void *, void *)
Definition: interface.h:81
void osl_relation_dump(FILE *file, osl_relation_p relation)
Definition: relation.c:246
osl_relation_p osl_relation_clone(osl_relation_p relation)
Definition: relation.c:1866
char * osl_relation_spprint_scoplib(osl_relation_p relation, osl_names_p names, int print_nth_part, int add_fakeiter)
Definition: relation.c:1215
int osl_relation_equal(osl_relation_p r1, osl_relation_p r2)
Definition: relation.c:2438
char * osl_relation_spprint_polylib(osl_relation_p relation, osl_names_p names)
Definition: relation.c:818
static void osl_relation_print_type(FILE *file, osl_relation_p relation)
Definition: relation.c:147
osl_relation_p osl_relation_malloc(int nb_rows, int nb_columns)
Definition: relation.c:1697
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_int_sprint_txt(char *string, int precision, osl_const_int_t value)
Definition: int.c:471
void osl_relation_remove_row(osl_relation_p r, int row)
Definition: relation.c:2228
#define OSL_PRECISION_SP
Definition: macros.h:78
osl_strings_p osl_strings_read(FILE *file)
Definition: strings.c:260
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:2543
void osl_int_oppose(int precision, osl_int_const_p variable, osl_const_int_t value)
variable = - value
Definition: int.c:1014
void osl_relation_swap_constraints(osl_relation_p relation, int c1, int c2)
Definition: relation.c:2205
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
void osl_relation_insert_columns(osl_relation_p relation, osl_relation_p insert, int column)
Definition: relation.c:2312
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:2670
void osl_relation_set_precision(int const precision, osl_relation_p r)
Definition: relation.c:3025
#define OSL_STRING_DOMAIN
Definition: macros.h:117
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:2047
#define OSL_STRING_SCATTERING
Definition: macros.h:118
#define OSL_max(x, y)
Definition: macros.h:181
osl_relation_p osl_relation_sread_polylib(char **input)
Definition: relation.c:1610
#define OSL_MAX_STRING
Definition: macros.h:94
void osl_strings_free(osl_strings_p strings)
Definition: strings.c:300
void osl_relation_add(osl_relation_p *r1, osl_relation_p r2)
Definition: relation.c:1883
void(* osl_free_f)(void *)
Definition: interface.h:79
osl_int_t * v
Definition: vector.h:87
#define OSL_URI_RELATION
Definition: relation.h:77
int osl_int_mone(int precision, osl_const_int_t value)
value == -1
Definition: int.c:1373
int osl_relation_is_access(osl_relation_p relation)
Definition: relation.c:2823
int osl_relation_nb_components(osl_relation_p relation)
Definition: relation.c:797
#define OSL_STRING_READ
Definition: macros.h:119
void osl_int_sread(char **string, int precision, osl_int_const_p i)
sread for osl int
Definition: int.c:539
void osl_util_sskip_blank_and_comments(char **str)
Definition: util.c:113
#define OSL_TYPE_WRITE
Definition: macros.h:105
void osl_relation_set_same_precision(osl_relation_p a, osl_relation_p b)
Definition: relation.c:3049
#define OSL_STRING_UNDEFINED
Definition: macros.h:115
void osl_relation_replace_constraints(osl_relation_p r1, osl_relation_p r2, int row)
Definition: relation.c:2128
osl_strings_p iterators
Definition: names.h:83
void osl_relation_sub_vector(osl_relation_p relation, osl_vector_p vector, int row)
Definition: relation.c:1976
size_t osl_strings_size(osl_const_strings_const_p strings)
Definition: strings.c:414
#define OSL_TYPE_ACCESS
Definition: macros.h:103
char * osl_relation_spprint(osl_relation_p relation, osl_names_p names)
Definition: relation.c:1180
void osl_relation_replace_vector(osl_relation_p relation, osl_vector_p vector, int row)
Definition: relation.c:1924
void osl_relation_insert_vector(osl_relation_p relation, osl_vector_p vector, int row)
Definition: relation.c:2008
osl_strings_p arrays
Definition: names.h:86
int nb_local_dims
Definition: relation.h:111
void osl_relation_set_type(osl_relation_p relation, int type)
Definition: relation.c:2711
osl_relation_p osl_relation_psread_polylib(char **input, int precision)
Definition: relation.c:1497
static char ** osl_relation_strings(osl_relation_p relation, osl_names_p names)
Definition: relation.c:343
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:2856
osl_relation_p osl_relation_psread(char **input, int precision)
Definition: relation.c:1475
osl_relation_p osl_relation_concat_constraints(osl_relation_p r1, osl_relation_p r2)
Definition: relation.c:2365
int osl_relation_part_equal(osl_relation_p r1, osl_relation_p r2)
Definition: relation.c:2401
static int osl_relation_check_attribute(int *expected, int actual)
Definition: relation.c:2468
int osl_int_neg(int precision, osl_const_int_t value)
value < 0
Definition: int.c:1298
#define OSL_PRECISION_MP
Definition: macros.h:80
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:2498
int precision
Definition: relation.h:106
osl_strings_p osl_strings_sread(char **input)
Definition: strings.c:195
osl_relation_p osl_relation_pmalloc(int precision, int nb_rows, int nb_columns)
Definition: relation.c:1645
int osl_int_pos(int precision, osl_const_int_t value)
value > 0
Definition: int.c:1273
osl_relation_p osl_relation_from_vector(osl_vector_p vector)
Definition: relation.c:2107
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
#define OSL_PRECISION_DP
Definition: macros.h:79
int osl_util_get_precision(void)
Definition: util.c:517
#define OSL_UNDEFINED
Definition: macros.h:93
osl_relation_p osl_relation_pread(FILE *foo, int precision)
Definition: relation.c:1382
void osl_relation_remove_part(osl_relation_p *relation_list, osl_relation_p part)
Definition: relation.c:3070
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:2692
osl_relation_p osl_relation_concat_vector(osl_relation_p relation, osl_vector_p vector)
Definition: relation.c:2029
void osl_int_clear(int precision, osl_int_const_p variable)
variable = 0 // including cleaning for GMP
Definition: int.c:382
osl_strings_p local_dims
Definition: names.h:85
#define OSL_FMT_LENGTH
Definition: macros.h:85
static osl_names_p osl_relation_names(osl_relation_p relation)
Definition: relation.c:772
void osl_int_assign(int precision, osl_int_const_p variable, osl_const_int_t value)
variable = value
Definition: int.c:179
char * osl_util_skip_blank_and_comments(FILE *file, char *str)
Definition: util.c:91
struct osl_relation * next
Definition: relation.h:117
void osl_relation_remove_column(osl_relation_p r, int column)
Definition: relation.c:2268
void osl_relation_add_vector(osl_relation_p relation, osl_vector_p vector, int row)
Definition: relation.c:1948
char * osl_relation_expression(osl_relation_p relation, int row, char **strings)
Definition: relation.c:466
int osl_int_zero(int precision, osl_const_int_t value)
value == 0
Definition: int.c:1323
osl_relation_p osl_relation_nclone(osl_relation_p relation, int n)
Definition: relation.c:1761
void osl_vector_free(osl_vector_p vector)
Definition: vector.c:197
#define OSL_TYPE_SCATTERING
Definition: macros.h:102
static char * osl_relation_expression_element(osl_int_t val, int precision, int *first, int cst, char *name)
Definition: relation.c:266
#define OSL_malloc(ptr, type, size)
Definition: macros.h:157