2 /*+-----------------------------------------------------------------**
4 **-----------------------------------------------------------------**
6 **-----------------------------------------------------------------**
7 ** First version: 30/04/2008 **
8 **-----------------------------------------------------------------**
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 * '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' *
30 * Copyright (C) 2008 University Paris-Sud 11 and INRIA *
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 *
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. *
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. *
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> *
61 *****************************************************************************/
69 #include <osl/macros.h>
72 #include <osl/vector.h>
73 #include <osl/strings.h>
74 #include <osl/names.h>
75 #include <osl/relation.h>
78 /*+***************************************************************************
79 * Structure display function *
80 *****************************************************************************/
84 * osl_relation_sprint_type function:
85 * this function prints the textual type of an osl_relation_t structure into
86 * a string, according to the OpenScop specification, and returns that string.
87 * \param[in] relation The relation whose type has to be printed.
88 * \return A string containing the relation type.
91 char * osl_relation_sprint_type(osl_relation_p relation
) {
94 OSL_malloc(string
, char *, OSL_MAX_STRING
* sizeof(char));
97 if (relation
!= NULL
) {
98 switch (relation
->type
) {
100 snprintf(string
, OSL_MAX_STRING
, OSL_STRING_UNDEFINED
);
103 case OSL_TYPE_CONTEXT
: {
104 snprintf(string
, OSL_MAX_STRING
, OSL_STRING_CONTEXT
);
107 case OSL_TYPE_DOMAIN
: {
108 snprintf(string
, OSL_MAX_STRING
, OSL_STRING_DOMAIN
);
111 case OSL_TYPE_SCATTERING
: {
112 snprintf(string
, OSL_MAX_STRING
, OSL_STRING_SCATTERING
);
115 case OSL_TYPE_READ
: {
116 snprintf(string
, OSL_MAX_STRING
, OSL_STRING_READ
);
119 case OSL_TYPE_WRITE
: {
120 snprintf(string
, OSL_MAX_STRING
, OSL_STRING_WRITE
);
123 case OSL_TYPE_MAY_WRITE
: {
124 snprintf(string
, OSL_MAX_STRING
, OSL_STRING_MAY_WRITE
);
128 OSL_warning("unknown relation type, "
129 "replaced with "OSL_STRING_UNDEFINED
);
130 snprintf(string
, OSL_MAX_STRING
, OSL_STRING_UNDEFINED
);
140 * osl_relation_print_type function:
141 * this function displays the textual type of an osl_relation_t structure into
142 * a file (file, possibly stdout), according to the OpenScop specification.
143 * \param[in] file File where informations are printed.
144 * \param[in] relation The relation whose type has to be printed.
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
);
155 * osl_relation_idump function:
156 * this function displays a osl_relation_t structure (*relation) into a
157 * file (file, possibly stdout) in a way that trends to be understandable.
158 * It includes an indentation level (level) in order to work with others
160 * \param[in] file File where informations are printed.
161 * \param[in] relation The relation whose information has to be printed.
162 * \param[in] level Number of spaces before printing, for each line.
164 void osl_relation_idump(FILE * file
, osl_relation_p relation
, int level
) {
167 // Go to the right level.
168 for (j
= 0; j
< level
; j
++)
169 fprintf(file
, "|\t");
171 if (relation
!= NULL
) {
172 fprintf(file
, "+-- osl_relation_t (");
173 osl_relation_print_type(file
, relation
);
175 osl_int_dump_precision(file
, relation
->precision
);
176 fprintf(file
, ")\n");
179 fprintf(file
, "+-- NULL relation\n");
182 while (relation
!= NULL
) {
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
);
190 osl_int_dump_precision(file
, relation
->precision
);
191 fprintf(file
, ")\n");
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
);
204 // Display the relation.
205 for (i
= 0; i
< relation
->nb_rows
; i
++) {
206 for (j
= 0; j
<= level
; j
++)
207 fprintf(file
, "|\t");
211 for (j
= 0; j
< relation
->nb_columns
; j
++) {
212 osl_int_print(file
, relation
->precision
, relation
->m
[i
], j
);
216 fprintf(file
, "]\n");
219 relation
= relation
->next
;
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");
233 for (j
= 0; j
<= level
; j
++)
234 fprintf(file
, "|\t");
240 * osl_relation_dump function:
241 * this function prints the content of a osl_relation_t structure
242 * (*relation) into a file (file, possibly stdout).
243 * \param[in] file File where informations are printed.
244 * \param[in] relation The relation whose information have to be printed.
246 void osl_relation_dump(FILE * file
, osl_relation_p relation
) {
247 osl_relation_idump(file
, relation
, 0);
252 * osl_relation_expression_element function:
253 * this function returns a string containing the printing of a value (e.g.,
254 * an iterator with its coefficient or a constant).
255 * \param[in] val Address of the coefficient or constant value.
256 * \param[in] precision The precision of the value.
257 * \param[in,out] first Pointer to a boolean set to 1 if the current value
258 * is the first of an expresion, 0 otherwise (maybe
260 * \param[in] cst A boolean set to 1 if the value is a constant,
262 * \param[in] name String containing the name of the element.
263 * \return A string that contains the printing of a value.
266 char * osl_relation_expression_element(void * val
,
267 int precision
, int * first
,
268 int cst
, char * name
) {
269 char * temp
, * body
, * sval
;
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));
278 // statements for the 'normal' processing.
279 if (!osl_int_zero(precision
, val
, 0) && (!cst
)) {
280 if ((*first
) || osl_int_neg(precision
, val
, 0)) {
281 if (osl_int_one(precision
, val
, 0)) { // case 1
282 sprintf(sval
, "%s", name
);
285 if (osl_int_mone(precision
, val
, 0)) { // case -1
286 sprintf(sval
, "-%s", name
);
288 else { // default case
289 osl_int_sprint_txt(sval
, precision
, val
, 0);
290 sprintf(temp
, "*%s", name
);
297 if (osl_int_one(precision
, val
, 0)) {
298 sprintf(sval
, "+%s", name
);
302 osl_int_sprint_txt(temp
, precision
, val
, 0);
304 sprintf(temp
, "*%s", name
);
311 if ((osl_int_zero(precision
, val
, 0) && (*first
)) ||
312 (osl_int_neg(precision
, val
, 0)))
313 osl_int_sprint_txt(sval
, precision
, val
, 0);
314 if (osl_int_pos(precision
, val
, 0)) {
317 osl_int_sprint_txt(temp
, precision
, val
, 0);
321 osl_int_sprint_txt(sval
, precision
, val
, 0);
334 * osl_relation_strings function:
335 * this function creates a NULL-terminated array of strings from an
336 * osl_names_t structure in such a way that the ith string is the "name"
337 * corresponding to the ith column of the constraint matrix.
338 * \param[in] relation The relation for which we need an array of names.
339 * \param[in] names The set of names for each element.
340 * \return An array of strings with one string per constraint matrix column.
343 char ** osl_relation_strings(osl_relation_p relation
, osl_names_p names
) {
345 char temp
[OSL_MAX_STRING
];
346 int i
, offset
, array_id
;
348 if ((relation
== NULL
) || (names
== NULL
)) {
349 OSL_debug("no names or relation to build the name array");
353 OSL_malloc(strings
, char **, (relation
->nb_columns
+ 1)*sizeof(char *));
354 strings
[relation
->nb_columns
] = NULL
;
356 // 1. Equality/inequality marker.
357 OSL_strdup(strings
[0], "e/i");
360 // 2. Output dimensions.
361 if (osl_relation_is_access(relation
)) {
362 // The first output dimension is the array name.
363 array_id
= osl_relation_get_array_id(relation
);
364 OSL_strdup(strings
[offset
], "Arr");
365 // The other ones are the array dimensions [1]...[n]
366 for (i
= offset
+ 1; i
< relation
->nb_output_dims
+ offset
; i
++) {
367 sprintf(temp
, "[%d]", i
- 1);
368 OSL_strdup(strings
[i
], temp
);
372 if (relation
->type
== OSL_TYPE_SCATTERING
) {
373 for (i
= offset
; i
< relation
->nb_output_dims
+ offset
; i
++) {
374 OSL_strdup(strings
[i
], names
->scatt_dims
->string
[i
- offset
]);
378 for (i
= offset
; i
< relation
->nb_output_dims
+ offset
; i
++) {
379 OSL_strdup(strings
[i
], names
->iterators
->string
[i
- offset
]);
382 offset
+= relation
->nb_output_dims
;
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
;
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
;
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
;
400 OSL_strdup(strings
[offset
], "1");
407 * osl_relation_subexpression function:
408 * this function returns a string corresponding to an affine (sub-)expression
409 * stored at the "row"^th row of the relation pointed by "relation" between
410 * the start and stop columns. Optionally it may oppose the whole expression.
411 * \param[in] relation A set of linear expressions.
412 * \param[in] row The row corresponding to the expression.
413 * \param[in] start The first column for the expression (inclusive).
414 * \param[in] stop The last column for the expression (inclusive).
415 * \param[in] oppose Boolean set to 1 to negate the expression, 0 otherwise.
416 * \param[in] strings Array of textual names of the various elements.
417 * \return A string that contains the printing of an affine (sub-)expression.
420 char * osl_relation_subexpression(osl_relation_p relation
,
421 int row
, int start
, int stop
, int oppose
,
423 int i
, first
= 1, constant
;
427 OSL_malloc(sline
, char *, OSL_MAX_STRING
* sizeof(char));
430 // Create the expression. The constant is a special case.
431 for (i
= start
; i
<= stop
; i
++) {
433 osl_int_oppose(relation
->precision
,
434 relation
->m
[row
], i
, relation
->m
[row
], i
);
437 if (i
== relation
->nb_columns
- 1)
442 sval
= osl_relation_expression_element(
443 osl_int_address(relation
->precision
, relation
->m
[row
], i
),
444 relation
->precision
, &first
, constant
, strings
[i
]);
447 osl_int_oppose(relation
->precision
,
448 relation
->m
[row
], i
, relation
->m
[row
], i
);
459 * osl_relation_expression function:
460 * this function returns a string corresponding to an affine expression
461 * stored at the "row"^th row of the relation pointed by "relation".
462 * \param[in] relation A set of linear expressions.
463 * \param[in] row The row corresponding to the expression.
464 * \param[in] strings Array of textual names of the various elements.
465 * \return A string that contains the printing of an affine expression.
467 char * osl_relation_expression(osl_relation_p relation
,
468 int row
, char ** strings
) {
470 return osl_relation_subexpression(relation
, row
,
471 1, relation
->nb_columns
- 1, 0,
477 * osl_relation_is_simple_output function:
478 * this function returns 1 or -1 if a given constraint row of a relation
479 * corresponds to an output, 0 otherwise. We call a simple output an equality
480 * constraint where exactly one output coefficient is not 0 and is either
481 * 1 (in this case the function returns 1) or -1 (in this case the function
483 * \param[in] relation The relation to test for simple output.
484 * \param[in] row The row corresponding to the constraint to test.
485 * \return 1 or -1 if the row is a simple output, 0 otherwise.
488 int osl_relation_is_simple_output(osl_relation_p relation
, int row
) {
493 if ((relation
== NULL
) ||
494 (relation
->m
== NULL
) ||
495 (relation
->nb_output_dims
== 0))
498 if ((row
< 0) || (row
> relation
->nb_rows
))
499 OSL_error("the specified row does not exist in the relation");
501 // The constraint must be an equality.
502 if (!osl_int_zero(relation
->precision
, relation
->m
[row
], 0))
505 // Check the output part has one and only one non-zero +1 or -1 coefficient.
507 for (i
= 1; i
<= relation
->nb_output_dims
; i
++) {
508 if (!osl_int_zero(relation
->precision
, relation
->m
[row
], i
)) {
514 if (osl_int_one(relation
->precision
, relation
->m
[row
], i
))
516 else if (osl_int_mone(relation
->precision
, relation
->m
[row
], i
))
528 * osl_relation_sprint_comment function:
529 * this function prints into a string a comment corresponding to a constraint
530 * of a relation, according to its type, then it returns this string. This
531 * function does not check that printing the comment is possible (i.e., are
532 * there enough names ?), hence it is the responsibility of the user to ensure
533 * he/she can call this function safely.
534 * \param[in] relation The relation for which a comment has to be printed.
535 * \param[in] row The constrain row for which a comment has to be printed.
536 * \param[in] strings Array of textual names of the various elements.
537 * \param[in] arrays Array of textual identifiers of the arrays.
538 * \return A string which contains the comment for the row.
541 char * osl_relation_sprint_comment(osl_relation_p relation
, int row
,
542 char ** strings
, char ** arrays
) {
544 int high_water_mark
= OSL_MAX_STRING
;
545 char * string
= NULL
;
547 char buffer
[OSL_MAX_STRING
];
549 OSL_malloc(string
, char *, high_water_mark
* sizeof(char));
552 if ((relation
== NULL
) || (strings
== NULL
)) {
553 OSL_debug("no relation or names while asked to print a comment");
557 if ((sign
= osl_relation_is_simple_output(relation
, row
))) {
558 // First case : output == expression.
560 expression
= osl_relation_subexpression(relation
, row
,
561 1, relation
->nb_output_dims
,
564 snprintf(buffer
, OSL_MAX_STRING
, " ## %s", expression
);
565 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
568 // We don't print the right hand side if it's an array identifier.
569 if (!osl_relation_is_access(relation
) ||
570 osl_int_zero(relation
->precision
, relation
->m
[row
], 1)) {
571 expression
= osl_relation_subexpression(relation
, row
,
572 relation
->nb_output_dims
+ 1,
573 relation
->nb_columns
- 1,
576 snprintf(buffer
, OSL_MAX_STRING
, " == %s", expression
);
577 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
581 snprintf(buffer
, OSL_MAX_STRING
, " == %s",
582 arrays
[osl_relation_get_array_id(relation
) - 1]);
583 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
587 // Second case : general case.
589 expression
= osl_relation_expression(relation
, row
, strings
);
590 snprintf(buffer
, OSL_MAX_STRING
, " ## %s", expression
);
591 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
594 if (osl_int_zero(relation
->precision
, relation
->m
[row
], 0))
595 snprintf(buffer
, OSL_MAX_STRING
, " == 0");
597 snprintf(buffer
, OSL_MAX_STRING
, " >= 0");
598 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
606 * osl_relation_column_string function:
607 * this function returns an OpenScop comment string showing all column
608 * names. It is designed to nicely fit a constraint matrix that would be
609 * printed just below this line.
610 * \param[in] relation The relation related to the comment line to build.
611 * \param[in] strings Array of textual names of the various elements.
612 * \return A fancy comment string with all the dimension names.
615 char * osl_relation_column_string(osl_relation_p relation
, char ** strings
) {
617 int index_output_dims
;
618 int index_input_dims
;
619 int index_local_dims
;
620 int index_parameters
;
622 int space
, length
, left
, right
;
624 char temp
[OSL_MAX_STRING
];
626 OSL_malloc(scolumn
, char *, OSL_MAX_STRING
);
628 index_output_dims
= 1;
629 index_input_dims
= index_output_dims
+ relation
->nb_output_dims
;
630 index_local_dims
= index_input_dims
+ relation
->nb_input_dims
;
631 index_parameters
= index_local_dims
+ relation
->nb_local_dims
;
632 index_scalar
= index_parameters
+ relation
->nb_parameters
;
634 // 1. The comment part.
635 sprintf(scolumn
, "#");
636 for (j
= 0; j
< (OSL_FMT_LENGTH
- 1)/2 - 1; j
++)
637 strcat(scolumn
, " ");
640 while (strings
[i
] != NULL
) {
641 space
= OSL_FMT_LENGTH
;
642 length
= (space
> strlen(strings
[i
])) ? strlen(strings
[i
]) : space
;
643 right
= (space
- length
+ (OSL_FMT_LENGTH
% 2)) / 2;
644 left
= space
- length
- right
;
646 // 2. Spaces before the name
647 for (j
= 0; j
< left
; j
++)
648 strcat(scolumn
, " ");
650 // 3. The (abbreviated) name
651 for (j
= 0; j
< length
- 1; j
++) {
652 sprintf(temp
, "%c", strings
[i
][j
]);
653 strcat(scolumn
, temp
);
655 if (length
>= strlen(strings
[i
]))
656 sprintf(temp
, "%c", strings
[i
][j
]);
659 strcat(scolumn
, temp
);
661 // 4. Spaces after the name
662 for (j
= 0; j
< right
; j
++)
663 strcat(scolumn
, " ");
666 if ((i
== index_output_dims
) ||
667 (i
== index_input_dims
) ||
668 (i
== index_local_dims
) ||
669 (i
== index_parameters
) ||
671 strcat(scolumn
, "|");
673 strcat(scolumn
, " ");
675 strcat(scolumn
, "\n");
682 * osl_relation_names function:
683 * this function generates as set of names for all the dimensions
684 * involved in a given relation.
685 * \param[in] relation The relation we have to generate names for.
686 * \return A set of generated names for the input relation dimensions.
689 osl_names_p
osl_relation_names(osl_relation_p relation
) {
690 int nb_parameters
= OSL_UNDEFINED
;
691 int nb_iterators
= OSL_UNDEFINED
;
692 int nb_scattdims
= OSL_UNDEFINED
;
693 int nb_localdims
= OSL_UNDEFINED
;
694 int array_id
= OSL_UNDEFINED
;
696 osl_relation_get_attributes(relation
, &nb_parameters
, &nb_iterators
,
697 &nb_scattdims
, &nb_localdims
, &array_id
);
699 return osl_names_generate("P", nb_parameters
,
708 * osl_relation_nb_components function:
709 * this function returns the number of component in the union of relations
710 * provided as parameter.
711 * \param[in] relation The input union of relations.
712 * \return The number of components in the input union of relations.
714 int osl_relation_nb_components(osl_relation_p relation
) {
715 int nb_components
= 0;
717 while (relation
!= NULL
) {
719 relation
= relation
->next
;
722 return nb_components
;
727 * osl_relation_spprint_polylib function:
728 * this function pretty-prints the content of an osl_relation_t structure
729 * (*relation) into a string in the extended polylib format, and returns this
730 * string. This format is the same as OpenScop's, minus the type.
731 * \param[in] relation The relation whose information has to be printed.
732 * \param[in] names The names of the constraint columns for comments.
733 * \return A string containing the relation pretty-printing.
735 char * osl_relation_spprint_polylib(osl_relation_p relation
,
739 int generated_names
= 0;
740 int high_water_mark
= OSL_MAX_STRING
;
741 char * string
= NULL
;
742 char buffer
[OSL_MAX_STRING
];
743 char ** name_array
= NULL
;
747 if (relation
== NULL
)
748 return strdup("# NULL relation\n");
750 OSL_malloc(string
, char *, high_water_mark
* sizeof(char));
753 // Generates the names for the comments if necessary.
756 names
= osl_relation_names(relation
);
759 nb_parts
= osl_relation_nb_components(relation
);
762 snprintf(buffer
, OSL_MAX_STRING
, "# Union with %d parts\n%d\n",
764 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
767 // Print each part of the union.
768 for (part
= 1; part
<= nb_parts
; part
++) {
769 // Prepare the array of strings for comments.
770 name_array
= osl_relation_strings(relation
, names
);
773 snprintf(buffer
, OSL_MAX_STRING
, "# Union part No.%d\n", part
);
774 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
777 snprintf(buffer
, OSL_MAX_STRING
, "%d %d %d %d %d %d\n",
778 relation
->nb_rows
, relation
->nb_columns
,
779 relation
->nb_output_dims
, relation
->nb_input_dims
,
780 relation
->nb_local_dims
, relation
->nb_parameters
);
781 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
783 if (relation
->nb_rows
> 0) {
784 scolumn
= osl_relation_column_string(relation
, name_array
);
785 snprintf(buffer
, OSL_MAX_STRING
, "%s", scolumn
);
786 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
790 for (i
= 0; i
< relation
->nb_rows
; i
++) {
791 for (j
= 0; j
< relation
->nb_columns
; j
++) {
792 osl_int_sprint(buffer
, relation
->precision
, relation
->m
[i
], j
);
793 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
794 snprintf(buffer
, OSL_MAX_STRING
, " ");
795 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
798 if (name_array
!= NULL
) {
799 comment
= osl_relation_sprint_comment(relation
, i
, name_array
,
800 names
->arrays
->string
);
801 osl_util_safe_strcat(&string
, comment
, &high_water_mark
);
804 snprintf(buffer
, OSL_MAX_STRING
, "\n");
805 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
808 // Free the array of strings.
809 if (name_array
!= NULL
) {
810 for (i
= 0; i
< relation
->nb_columns
; i
++)
815 relation
= relation
->next
;
819 osl_names_free(names
);
826 * osl_relation_spprint function:
827 * this function pretty-prints the content of an osl_relation_t structure
828 * (*relation) into a string in the OpenScop format, and returns this string.
829 * \param[in] relation The relation whose information has to be printed.
830 * \param[in] names The names of the constraint columns for comments.
833 char * osl_relation_spprint(osl_relation_p relation
, osl_names_p names
) {
834 int high_water_mark
= OSL_MAX_STRING
;
835 char * string
= NULL
;
837 char buffer
[OSL_MAX_STRING
];
838 OSL_malloc(string
, char *, high_water_mark
* sizeof(char));
841 if (osl_relation_nb_components(relation
) > 0) {
842 temp
= osl_relation_sprint_type(relation
);
843 osl_util_safe_strcat(&string
, temp
, &high_water_mark
);
846 snprintf(buffer
, OSL_MAX_STRING
, "\n");
847 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
849 temp
= osl_relation_spprint_polylib(relation
, names
);
850 osl_util_safe_strcat(&string
, temp
, &high_water_mark
);
859 * osl_relation_pprint function:
860 * this function pretty-prints the content of an osl_relation_t structure
861 * (*relation) into a file (file, possibly stdout) in the OpenScop format.
862 * \param[in] file File where informations are printed.
863 * \param[in] relation The relation whose information has to be printed.
864 * \param[in] names The names of the constraint columns for comments.
866 void osl_relation_pprint(FILE * file
, osl_relation_p relation
,
868 char * string
= osl_relation_spprint(relation
, names
);
869 fprintf(file
, "%s", string
);
875 * osl_relation_print function:
876 * this function prints the content of an osl_relation_t structure
877 * (*relation) into a file (file, possibly stdout) in the OpenScop format.
878 * \param[in] file File where informations are printed.
879 * \param[in] relation The relation whose information has to be printed.
881 void osl_relation_print(FILE * file
, osl_relation_p relation
) {
883 osl_relation_pprint(file
, relation
, NULL
);
887 /*****************************************************************************
889 *****************************************************************************/
893 * osl_relation_read_type function:
894 * this function reads a textual relation type and returns its integer
896 * \param[in] file The input stream.
897 * \return The relation type.
900 int osl_relation_read_type(FILE * file
) {
902 osl_strings_p strings
;
904 strings
= osl_strings_read(file
);
905 if (osl_strings_size(strings
) > 1) {
906 OSL_warning("uninterpreted information (after the relation type)");
908 if (osl_strings_size(strings
) == 0)
909 OSL_error("no relation type");
911 if (!strcmp(strings
->string
[0], OSL_STRING_UNDEFINED
)) {
912 type
= OSL_UNDEFINED
;
916 if (!strcmp(strings
->string
[0], OSL_STRING_CONTEXT
)) {
917 type
= OSL_TYPE_CONTEXT
;
921 if (!strcmp(strings
->string
[0], OSL_STRING_DOMAIN
)) {
922 type
= OSL_TYPE_DOMAIN
;
926 if (!strcmp(strings
->string
[0], OSL_STRING_SCATTERING
)) {
927 type
= OSL_TYPE_SCATTERING
;
931 if (!strcmp(strings
->string
[0], OSL_STRING_READ
)) {
932 type
= OSL_TYPE_READ
;
936 if (!strcmp(strings
->string
[0], OSL_STRING_WRITE
)) {
937 type
= OSL_TYPE_WRITE
;
941 if (!strcmp(strings
->string
[0], OSL_STRING_MAY_WRITE
)) {
942 type
= OSL_TYPE_MAY_WRITE
;
946 OSL_error("relation type not supported");
949 osl_strings_free(strings
);
955 * osl_relation_pread function ("precision read"):
956 * this function reads a relation into a file (foo, posibly stdin) and
957 * returns a pointer this relation. The relation is set to the maximum
958 * available precision.
959 * \param[in] foo The input stream.
960 * \param[in] precision The precision of the relation elements.
961 * \return A pointer to the relation structure that has been read.
963 osl_relation_p
osl_relation_pread(FILE * foo
, int precision
) {
964 int i
, j
, k
, n
, read
= 0;
965 int nb_rows
, nb_columns
;
966 int nb_output_dims
, nb_input_dims
, nb_local_dims
, nb_parameters
;
967 int nb_union_parts
= 1;
968 int may_read_nb_union_parts
= 1;
969 int read_attributes
= 1;
972 char * c
, s
[OSL_MAX_STRING
], str
[OSL_MAX_STRING
], *tmp
;
973 osl_relation_p relation
, relation_union
= NULL
, previous
= NULL
;
975 type
= osl_relation_read_type(foo
);
977 // Read each part of the union (the number of parts may be updated inside)
978 for (k
= 0; k
< nb_union_parts
; k
++) {
979 // Read the number of union parts or the attributes of the union part
980 while (read_attributes
) {
983 // Read relation attributes.
984 c
= osl_util_skip_blank_and_comments(foo
, s
);
985 read
= sscanf(c
, " %d %d %d %d %d %d", &nb_rows
, &nb_columns
,
986 &nb_output_dims
, &nb_input_dims
,
987 &nb_local_dims
, &nb_parameters
);
989 if (((read
!= 1) && (read
!= 6)) ||
990 ((read
== 1) && (may_read_nb_union_parts
!= 1)))
991 OSL_error("not 1 or 6 integers on the first relation line");
994 // Only one number means a union and is the number of parts.
995 nb_union_parts
= nb_rows
;
996 if (nb_union_parts
< 1)
997 OSL_error("negative nb of union parts");
999 // Allow to read the properties of the first part of the union.
1000 read_attributes
= 1;
1003 may_read_nb_union_parts
= 0;
1006 // Allocate the union part and fill its properties.
1007 relation
= osl_relation_pmalloc(precision
, nb_rows
, nb_columns
);
1008 relation
->type
= type
;
1009 relation
->nb_output_dims
= nb_output_dims
;
1010 relation
->nb_input_dims
= nb_input_dims
;
1011 relation
->nb_local_dims
= nb_local_dims
;
1012 relation
->nb_parameters
= nb_parameters
;
1014 // Read the matrix of constraints.
1015 for (i
= 0; i
< relation
->nb_rows
; i
++) {
1016 c
= osl_util_skip_blank_and_comments(foo
, s
);
1018 OSL_error("not enough rows");
1020 for (j
= 0; j
< relation
->nb_columns
; j
++) {
1021 if (c
== NULL
|| *c
== '#' || *c
== '\n')
1022 OSL_error("not enough columns");
1023 if (sscanf(c
, "%s%n", str
, &n
) == 0)
1024 OSL_error("not enough rows");
1026 // TODO: remove this tmp (sread updates the pointer).
1028 osl_int_sread(&tmp
, precision
, relation
->m
[i
], j
);
1033 // Build the linked list of union parts.
1035 relation_union
= relation
;
1039 previous
->next
= relation
;
1042 previous
= relation
;
1043 read_attributes
= 1;
1046 return relation_union
;
1051 * osl_relation_read function:
1052 * this function is equivalent to osl_relation_pread() except that
1053 * the precision corresponds to the precision environment variable or
1054 * to the highest available precision if it is not defined.
1055 * \see{osl_relation_pread}
1057 osl_relation_p
osl_relation_read(FILE * foo
) {
1058 int precision
= osl_util_get_precision();
1059 return osl_relation_pread(foo
, precision
);
1063 /*+***************************************************************************
1064 * Memory allocation/deallocation function *
1065 *****************************************************************************/
1069 * osl_relation_pmalloc function:
1070 * (precision malloc) this function allocates the memory space for an
1071 * osl_relation_t structure and sets its fields with default values.
1072 * Then it returns a pointer to the allocated space.
1073 * \param[in] precision The precision of the constraint matrix.
1074 * \param[in] nb_rows The number of row of the relation to allocate.
1075 * \param[in] nb_columns The number of columns of the relation to allocate.
1076 * \return A pointer to an empty relation with fields set to default values
1077 * and a ready-to-use constraint matrix.
1079 osl_relation_p
osl_relation_pmalloc(int precision
,
1080 int nb_rows
, int nb_columns
) {
1081 osl_relation_p relation
;
1085 OSL_malloc(relation
, osl_relation_p
, sizeof(osl_relation_t
));
1086 relation
->type
= OSL_UNDEFINED
;
1087 relation
->nb_rows
= nb_rows
;
1088 relation
->nb_columns
= nb_columns
;
1089 relation
->nb_output_dims
= OSL_UNDEFINED
;
1090 relation
->nb_input_dims
= OSL_UNDEFINED
;
1091 relation
->nb_parameters
= OSL_UNDEFINED
;
1092 relation
->nb_local_dims
= OSL_UNDEFINED
;
1093 relation
->precision
= precision
;
1095 if ((nb_rows
== 0) || (nb_columns
== 0) ||
1096 (nb_rows
== OSL_UNDEFINED
) || (nb_columns
== OSL_UNDEFINED
)) {
1100 OSL_malloc(p
, void **, nb_rows
* sizeof(void *));
1101 OSL_malloc(q
, void *,
1102 nb_rows
* nb_columns
* osl_int_sizeof(precision
));
1104 for (i
= 0; i
< nb_rows
; i
++) {
1105 relation
->m
[i
] = osl_int_address(precision
, q
, i
* nb_columns
);
1106 for (j
= 0; j
< nb_columns
; j
++)
1107 osl_int_init_set_si(precision
, relation
->m
[i
], j
, 0);
1111 relation
->next
= NULL
;
1118 * osl_relation_malloc function:
1119 * this function is equivalent to osl_relation_pmalloc() except that
1120 * the precision corresponds to the precision environment variable or
1121 * to the highest available precision if it is not defined.
1122 * \see{osl_relation_pmalloc}
1124 osl_relation_p
osl_relation_malloc(int nb_rows
, int nb_columns
) {
1125 int precision
= osl_util_get_precision();
1126 return osl_relation_pmalloc(precision
, nb_rows
, nb_columns
);
1131 * osl_relation_free_inside function:
1132 * this function frees the allocated memory for the inside of a
1133 * osl_relation_t structure, i.e. only m.
1134 * \param[in] relation The pointer to the relation we want to free internals.
1136 void osl_relation_free_inside(osl_relation_p relation
) {
1140 if (relation
== NULL
)
1143 nb_elements
= relation
->nb_rows
* relation
->nb_columns
;
1145 if (nb_elements
> 0)
1148 for (i
= 0; i
< nb_elements
; i
++)
1149 osl_int_clear(relation
->precision
, p
, i
);
1151 if (relation
->m
!= NULL
) {
1152 if (nb_elements
> 0)
1153 free(relation
->m
[0]);
1160 * osl_relation_free function:
1161 * this function frees the allocated memory for an osl_relation_t
1163 * \param[in] relation The pointer to the relation we want to free.
1165 void osl_relation_free(osl_relation_p relation
) {
1168 if (relation
== NULL
)
1171 while (relation
!= NULL
) {
1172 tmp
= relation
->next
;
1173 osl_relation_free_inside(relation
);
1180 /*+***************************************************************************
1181 * Processing functions *
1182 *****************************************************************************/
1186 * osl_relation_nclone function:
1187 * this functions builds and returns a "hard copy" (not a pointer copy) of a
1188 * osl_relation_t data structure such that the clone is restricted to the
1189 * "n" first rows of the relation. This applies to all the parts in the case
1190 * of a relation union.
1191 * \param[in] relation The pointer to the relation we want to clone.
1192 * \param[in] n The number of row of the relation we want to clone (the
1193 * special value -1 means "all the rows").
1194 * \return A pointer to the clone of the relation union restricted to the
1195 * first n rows of constraint matrix for each part of the union.
1197 osl_relation_p
osl_relation_nclone(osl_relation_p relation
, int n
) {
1199 int first
= 1, all_rows
= 0;
1200 osl_relation_p clone
= NULL
, node
, previous
= NULL
;
1205 while (relation
!= NULL
) {
1207 n
= relation
->nb_rows
;
1209 if (n
> relation
->nb_rows
)
1210 OSL_error("not enough rows to clone in the relation");
1212 node
= osl_relation_pmalloc(relation
->precision
, n
, relation
->nb_columns
);
1213 node
->type
= relation
->type
;
1214 node
->nb_output_dims
= relation
->nb_output_dims
;
1215 node
->nb_input_dims
= relation
->nb_input_dims
;
1216 node
->nb_local_dims
= relation
->nb_local_dims
;
1217 node
->nb_parameters
= relation
->nb_parameters
;
1219 for (i
= 0; i
< n
; i
++)
1220 for (j
= 0; j
< relation
->nb_columns
; j
++)
1221 osl_int_assign(relation
->precision
, node
->m
[i
], j
, relation
->m
[i
], j
);
1229 previous
->next
= node
;
1230 previous
= previous
->next
;
1233 relation
= relation
->next
;
1241 * osl_relation_clone function:
1242 * this function builds and returns a "hard copy" (not a pointer copy) of an
1243 * osl_relation_t data structure (the full union of relation).
1244 * \param[in] relation The pointer to the relation we want to clone.
1245 * \return A pointer to the clone of the union of relations.
1247 osl_relation_p
osl_relation_clone(osl_relation_p relation
) {
1248 if (relation
== NULL
)
1251 return osl_relation_nclone(relation
, -1);
1256 * osl_relation_replace_vector function:
1257 * this function replaces the "row"^th row of a relation "relation" with the
1258 * vector "vector". It directly updates the relation union part pointed
1259 * by "relation" and this part only.
1260 * \param[in,out] relation The relation we want to replace a row.
1261 * \param[in] vector The vector that will replace a row of the relation.
1262 * \param[in] row The row of the relation to be replaced.
1264 void osl_relation_replace_vector(osl_relation_p relation
,
1265 osl_vector_p vector
, int row
) {
1268 if ((relation
== NULL
) || (vector
== NULL
) ||
1269 (relation
->precision
!= vector
->precision
) ||
1270 (relation
->nb_columns
!= vector
->size
) ||
1271 (row
>= relation
->nb_rows
) || (row
< 0))
1272 OSL_error("vector cannot replace relation row");
1274 for (i
= 0; i
< vector
->size
; i
++)
1275 osl_int_assign(relation
->precision
, relation
->m
[row
], i
, vector
->v
, i
);
1280 * osl_relation_add_vector function:
1281 * this function adds (meaning, +) a vector to the "row"^th row of a
1282 * relation "relation". It directly updates the relation union part pointed
1283 * by "relation" and this part only.
1284 * \param[in,out] relation The relation we want to add a vector to a row.
1285 * \param[in] vector The vector that will replace a row of the relation.
1286 * \param[in] row The row of the relation to add the vector.
1288 void osl_relation_add_vector(osl_relation_p relation
,
1289 osl_vector_p vector
, int row
) {
1292 if ((relation
== NULL
) || (vector
== NULL
) ||
1293 (relation
->precision
!= vector
->precision
) ||
1294 (relation
->nb_columns
!= vector
->size
) ||
1295 (row
>= relation
->nb_rows
) || (row
< 0))
1296 OSL_error("vector cannot be added to relation");
1298 if (osl_int_get_si(relation
->precision
, relation
->m
[row
], 0) == 0)
1299 osl_int_assign(relation
->precision
, relation
->m
[row
], 0, vector
->v
, 0);
1301 for (i
= 1; i
< vector
->size
; i
++)
1302 osl_int_add(relation
->precision
,
1303 relation
->m
[row
], i
, relation
->m
[row
], i
, vector
->v
, i
);
1308 * osl_relation_sub_vector function:
1309 * this function subtracts the vector "vector" to the "row"^th row of
1310 * a relation "relation. It directly updates the relation union part pointed
1311 * by "relation" and this part only.
1312 * \param[in,out] relation The relation where to subtract a vector to a row.
1313 * \param[in] vector The vector to subtract to a relation row.
1314 * \param[in] row The row of the relation to subtract the vector.
1316 void osl_relation_sub_vector(osl_relation_p relation
,
1317 osl_vector_p vector
, int row
) {
1320 if ((relation
== NULL
) || (vector
== NULL
) ||
1321 (relation
->precision
!= vector
->precision
) ||
1322 (relation
->nb_columns
!= vector
->size
) ||
1323 (row
>= relation
->nb_rows
) || (row
< 0))
1324 OSL_error("vector cannot be subtracted to row");
1326 if (osl_int_get_si(relation
->precision
, relation
->m
[row
], 0) == 0)
1327 osl_int_assign(relation
->precision
, relation
->m
[row
], 0, vector
->v
, 0);
1329 for (i
= 1; i
< vector
->size
; i
++)
1330 osl_int_sub(relation
->precision
,
1331 relation
->m
[row
], i
, relation
->m
[row
], i
, vector
->v
, i
);
1336 * osl_relation_insert_vector function:
1337 * this function inserts a new row corresponding to the vector "vector" to
1338 * the relation "relation" by inserting it at the "row"^th row of
1339 * "relation" (-1 is a shortcut to insert the vector after the constraints
1340 * of the relation). It directly updates the relation union part pointed
1341 * by "relation" and this part only. If "vector" (or "relation") is NULL,
1342 * the relation is left unmodified.
1343 * \param[in,out] relation The relation we want to extend.
1344 * \param[in] vector The vector that will be added relation.
1345 * \param[in] row The row where to insert the vector (-1 to
1346 * insert it after the relation constraints).
1348 void osl_relation_insert_vector(osl_relation_p relation
,
1349 osl_vector_p vector
, int row
) {
1350 osl_relation_p temp
;
1352 temp
= osl_relation_from_vector(vector
);
1353 osl_relation_insert_constraints(relation
, temp
, row
);
1354 osl_relation_free(temp
);
1359 * osl_relation_concat_vector function:
1360 * this function builds a new relation from one relation and a vector sent as
1361 * parameters. The new set of constraints is built as the concatenation
1362 * of the rows of the first part of the relation and of the vector
1363 * constraint. This means, there is no next field in the result.
1364 * \param[in] r The input relation.
1365 * \param[in] v The input vector.
1366 * \return A pointer to the relation resulting from the concatenation of
1367 * the constraints of the relation and of the vector.
1369 osl_relation_p
osl_relation_concat_vector(osl_relation_p relation
,
1370 osl_vector_p vector
) {
1371 osl_relation_p
new, temp
;
1373 temp
= osl_relation_from_vector(vector
);
1374 new = osl_relation_concat_constraints(relation
, temp
);
1375 osl_relation_free(temp
);
1381 * osl_relation_insert_blank_row function:
1382 * this function inserts a new row filled with zeros o an existing relation
1383 * union part (it only affects the first union part).
1384 * \param[in,out] relation The relation to add a row in.
1385 * \param[in] row The row where to insert the blank row.
1387 void osl_relation_insert_blank_row(osl_relation_p relation
, int row
) {
1388 osl_vector_p vector
;
1390 if (relation
!= NULL
) {
1391 vector
= osl_vector_pmalloc(relation
->precision
, relation
->nb_columns
);
1392 osl_relation_insert_vector(relation
, vector
, row
);
1393 osl_vector_free(vector
);
1399 * osl_relation_insert_blank_column function:
1400 * this function inserts a new column filled with zeros to an existing
1401 * relation union part (it only affects the first union part). WARNING:
1402 * this function does not update the relation attributes.
1403 * \param[in,out] relation The relation to add a column in.
1404 * \param[in] column The column where to insert the blank column.
1406 void osl_relation_insert_blank_column(osl_relation_p relation
, int column
) {
1409 osl_relation_p temp
;
1411 if (relation
== NULL
)
1414 if ((column
< 0) || (column
> relation
->nb_columns
))
1415 OSL_error("bad column number");
1417 // We use a temporary relation just to reuse existing functions. Cleaner.
1418 temp
= osl_relation_pmalloc(relation
->precision
,
1419 relation
->nb_rows
, relation
->nb_columns
+ 1);
1421 for (i
= 0; i
< relation
->nb_rows
; i
++) {
1422 for (j
= 0; j
< column
; j
++)
1423 osl_int_assign(relation
->precision
, temp
->m
[i
], j
, relation
->m
[i
], j
);
1425 for (j
= column
; j
< relation
->nb_columns
; j
++)
1426 osl_int_assign(relation
->precision
, temp
->m
[i
], j
+1, relation
->m
[i
], j
);
1429 osl_relation_free_inside(relation
);
1431 // Replace the inside of relation.
1432 relation
->nb_columns
= temp
->nb_columns
;
1433 relation
->m
= temp
->m
;
1435 // Free the temp "shell".
1441 * osl_relation_from_vector function:
1442 * this function converts a vector "vector" to a relation with a single row
1443 * and returns a pointer to that relation.
1444 * \param[in] vector The vector to convert to a relation.
1445 * \return A pointer to a relation resulting from the vector conversion.
1447 osl_relation_p
osl_relation_from_vector(osl_vector_p vector
) {
1448 osl_relation_p relation
;
1453 relation
= osl_relation_pmalloc(vector
->precision
, 1, vector
->size
);
1454 osl_relation_replace_vector(relation
, vector
, 0);
1460 * osl_relation_replace_constraints function:
1461 * this function replaces some rows of a relation "r1" with the rows of
1462 * the relation "r2". It begins at the "row"^th row of "r1". It directly
1463 * updates the relation union part pointed by "r1" and this part only.
1464 * \param[in,out] r1 The relation we want to change some rows.
1465 * \param[in] r2 The relation containing the new rows.
1466 * \param[in] row The first row of the relation r1 to be replaced.
1468 void osl_relation_replace_constraints(osl_relation_p r1
,
1469 osl_relation_p r2
, int row
) {
1472 if ((r1
== NULL
) || (r2
== NULL
) ||
1473 (r1
->precision
!= r2
->precision
) ||
1474 (r1
->nb_columns
!= r1
->nb_columns
) ||
1475 ((row
+ r2
->nb_rows
) > r1
->nb_rows
) || (row
< 0))
1476 OSL_error("relation rows could not be replaced");
1478 for (i
= 0; i
< r2
->nb_rows
; i
++)
1479 for (j
= 0; j
< r2
->nb_columns
; j
++)
1480 osl_int_assign(r1
->precision
, r1
->m
[i
+row
], j
, r2
->m
[i
], j
);
1485 * osl_relation_insert_constraints function:
1486 * this function inserts the rows of the relation "r2" to the relation
1487 * "r1", starting from the "row"^th row of "r1" (-1 is a
1488 * shortcut to insert the "r2" constraints after the constraints of r1).
1489 * It directly updates the relation union part pointed by "r1" and this
1490 * part only. If "r2" (or "r1") is NULL, the relation is left unmodified.
1491 * \param[in,out] r1 The relation we want to extend.
1492 * \param[in] r2 The relation to be inserted.
1493 * \param[in] row The row where to insert the constraints (-1 to
1494 * insert them after those of "r1").
1496 void osl_relation_insert_constraints(osl_relation_p r1
,
1497 osl_relation_p r2
, int row
) {
1499 osl_relation_p temp
;
1501 if ((r1
== NULL
) || (r2
== NULL
))
1507 if ((r1
->nb_columns
!= r2
->nb_columns
) ||
1508 (r1
->precision
!= r2
->precision
) ||
1509 (row
> r1
->nb_rows
) || (row
< 0))
1510 OSL_error("constraints cannot be inserted");
1512 // We use a temporary relation just to reuse existing functions. Cleaner.
1513 temp
= osl_relation_pmalloc(r1
->precision
,
1514 r1
->nb_rows
+ r2
->nb_rows
, r1
->nb_columns
);
1516 for (i
= 0; i
< row
; i
++)
1517 for (j
= 0; j
< r1
->nb_columns
; j
++)
1518 osl_int_assign(r1
->precision
, temp
->m
[i
], j
, r1
->m
[i
], j
);
1520 osl_relation_replace_constraints(temp
, r2
, row
);
1522 for (i
= row
+ r2
->nb_rows
; i
< r2
->nb_rows
+ r1
->nb_rows
; i
++)
1523 for (j
= 0; j
< r1
->nb_columns
; j
++)
1524 osl_int_assign(r1
->precision
, temp
->m
[i
], j
, r1
->m
[i
-r2
->nb_rows
], j
);
1526 osl_relation_free_inside(r1
);
1528 // Replace the inside of relation.
1529 r1
->nb_rows
= temp
->nb_rows
;
1532 // Free the temp "shell".
1538 * osl_relation_insert_columns function:
1539 * this function inserts new columns to an existing relation union part (it
1540 * only affects the first union part). The columns are copied out from the
1541 * matrix of an input relation which must have the convenient number of rows.
1542 * All columns of the input matrix are copied. WARNING: this function does not
1543 * update the relation attributes of the modified matrix.
1544 * \param[in,out] relation The relation to add columns in.
1545 * \param[in] insert The relation containing the columns to add.
1546 * \param[in] column The column where to insert the new columns.
1548 void osl_relation_insert_columns(osl_relation_p relation
,
1549 osl_relation_p insert
, int column
) {
1551 osl_relation_p temp
;
1553 if ((relation
== NULL
) || (insert
== NULL
))
1556 if ((relation
->precision
!= insert
->precision
) ||
1557 (relation
->nb_rows
!= insert
->nb_rows
) ||
1558 (column
< 0) || (column
> relation
->nb_columns
))
1559 OSL_error("columns cannot be inserted");
1561 // We use a temporary relation just to reuse existing functions. Cleaner.
1562 temp
= osl_relation_pmalloc(relation
->precision
, relation
->nb_rows
,
1563 relation
->nb_columns
+ insert
->nb_columns
);
1565 for (i
= 0; i
< relation
->nb_rows
; i
++) {
1566 for (j
= 0; j
< column
; j
++)
1567 osl_int_assign(relation
->precision
, temp
->m
[i
], j
, relation
->m
[i
], j
);
1569 for (j
= column
; j
< column
+ insert
->nb_columns
; j
++)
1570 osl_int_assign(relation
->precision
,
1571 temp
->m
[i
], j
, insert
->m
[i
], j
- column
);
1573 for (j
= column
+ insert
->nb_columns
;
1574 j
< insert
->nb_columns
+ relation
->nb_columns
; j
++)
1575 osl_int_assign(relation
->precision
,
1576 temp
->m
[i
], j
, relation
->m
[i
], j
- insert
->nb_columns
);
1579 osl_relation_free_inside(relation
);
1581 // Replace the inside of relation.
1582 relation
->nb_columns
= temp
->nb_columns
;
1583 relation
->m
= temp
->m
;
1585 // Free the temp "shell".
1591 * osl_relation_concat_constraints function:
1592 * this function builds a new relation from two relations sent as
1593 * parameters. The new set of constraints is built as the concatenation
1594 * of the rows of the first elements of the two relation unions r1 and r2.
1595 * This means, there is no next field in the result.
1596 * \param[in] r1 The first relation.
1597 * \param[in] r2 The second relation.
1598 * \return A pointer to the relation resulting from the concatenation of
1599 * the first elements of r1 and r2.
1601 osl_relation_p
osl_relation_concat_constraints(
1603 osl_relation_p r2
) {
1607 return osl_relation_clone(r2
);
1610 return osl_relation_clone(r1
);
1612 if (r1
->nb_columns
!= r2
->nb_columns
)
1613 OSL_error("incompatible sizes for concatenation");
1615 if (r1
->next
|| r2
->next
)
1616 OSL_warning("relation concatenation is done on the first elements "
1619 new = osl_relation_pmalloc(r1
->precision
,
1620 r1
->nb_rows
+ r2
->nb_rows
, r1
->nb_columns
);
1621 osl_relation_replace_constraints(new, r1
, 0);
1622 osl_relation_replace_constraints(new, r2
, r1
->nb_rows
);
1629 * osl_relation_equal function:
1630 * this function returns true if the two relations provided as parameters
1631 * are the same, false otherwise.
1632 * \param[in] r1 The first relation.
1633 * \param[in] r2 The second relation.
1634 * \return 1 if r1 and r2 are the same (content-wise), 0 otherwise.
1636 int osl_relation_equal(osl_relation_p r1
, osl_relation_p r2
) {
1639 while ((r1
!= NULL
) && (r2
!= NULL
)) {
1643 if ((r1
->type
!= r2
->type
) ||
1644 (r1
->precision
!= r2
->precision
) ||
1645 (r1
->nb_rows
!= r2
->nb_rows
) ||
1646 (r1
->nb_columns
!= r2
->nb_columns
) ||
1647 (r1
->nb_output_dims
!= r2
->nb_output_dims
) ||
1648 (r1
->nb_input_dims
!= r2
->nb_input_dims
) ||
1649 (r1
->nb_local_dims
!= r2
->nb_local_dims
) ||
1650 (r1
->nb_parameters
!= r2
->nb_parameters
))
1653 for (i
= 0; i
< r1
->nb_rows
; ++i
)
1654 for (j
= 0; j
< r1
->nb_columns
; ++j
)
1655 if (osl_int_ne(r1
->precision
, r1
->m
[i
], j
, r2
->m
[i
], j
))
1662 if (((r1
== NULL
) && (r2
!= NULL
)) || ((r1
!= NULL
) && (r2
== NULL
)))
1670 * osl_relation_check_attribute internal function:
1671 * This function checks whether an "actual" value is the same as an
1672 * "expected" value or not. If the expected value is set to
1673 * OSL_UNDEFINED, this function sets it to the "actual" value
1674 * and do not report a difference has been detected.
1675 * It returns 0 if a difference has been detected, 1 otherwise.
1676 * \param[in,out] expected Pointer to the expected value (the value is
1677 * modified if it was set to OSL_UNDEFINED).
1678 * \param[in] actual Value we want to check.
1679 * \return 0 if the values are not the same while the expected value was
1680 * not OSL_UNDEFINED, 1 otherwise.
1683 int osl_relation_check_attribute(int * expected
, int actual
) {
1684 if (*expected
!= OSL_UNDEFINED
) {
1685 if ((actual
!= OSL_UNDEFINED
) &&
1686 (actual
!= *expected
)) {
1687 OSL_warning("unexpected atribute");
1700 * osl_relation_check_nb_columns internal function:
1701 * This function checks that the number of columns of a relation
1702 * corresponds to some expected properties (setting an expected property to
1703 * OSL_UNDEFINED makes this function unable to detect a problem).
1704 * It returns 0 if the number of columns seems incorrect or 1 if no problem
1705 * has been detected.
1706 * \param[in] relation The relation we want to check the number of columns.
1707 * \param[in] expected_nb_output_dims Expected number of output dimensions.
1708 * \param[in] expected_nb_input_dims Expected number of input dimensions.
1709 * \param[in] expected_nb_parameters Expected number of parameters.
1710 * \return 0 if the number of columns seems incorrect, 1 otherwise.
1713 int osl_relation_check_nb_columns(osl_relation_p relation
,
1714 int expected_nb_output_dims
,
1715 int expected_nb_input_dims
,
1716 int expected_nb_parameters
) {
1717 int expected_nb_local_dims
, expected_nb_columns
;
1719 if ((expected_nb_output_dims
!= OSL_UNDEFINED
) &&
1720 (expected_nb_input_dims
!= OSL_UNDEFINED
) &&
1721 (expected_nb_parameters
!= OSL_UNDEFINED
)) {
1723 if (relation
->nb_local_dims
== OSL_UNDEFINED
)
1724 expected_nb_local_dims
= 0;
1726 expected_nb_local_dims
= relation
->nb_local_dims
;
1728 expected_nb_columns
= expected_nb_output_dims
+
1729 expected_nb_input_dims
+
1730 expected_nb_local_dims
+
1731 expected_nb_parameters
+
1734 if (expected_nb_columns
!= relation
->nb_columns
) {
1735 OSL_warning("unexpected number of columns");
1745 * osl_relation_integrity_check function:
1746 * this function checks that a relation is "well formed" according to some
1747 * expected properties (setting an expected value to OSL_UNDEFINED means
1748 * that we do not expect a specific value) and what the relation is supposed
1749 * to represent. It returns 0 if the check failed or 1 if no problem has been
1751 * \param[in] relation The relation we want to check.
1752 * \param[in] expected_type Semantics about this relation (domain, access...).
1753 * \param[in] expected_nb_output_dims Expected number of output dimensions.
1754 * \param[in] expected_nb_input_dims Expected number of input dimensions.
1755 * \param[in] expected_nb_parameters Expected number of parameters.
1756 * \return 0 if the integrity check fails, 1 otherwise.
1758 int osl_relation_integrity_check(osl_relation_p relation
,
1760 int expected_nb_output_dims
,
1761 int expected_nb_input_dims
,
1762 int expected_nb_parameters
) {
1765 // Check the NULL case.
1766 if (relation
== NULL
) {
1767 if ((expected_nb_output_dims
!= OSL_UNDEFINED
) ||
1768 (expected_nb_input_dims
!= OSL_UNDEFINED
) ||
1769 (expected_nb_parameters
!= OSL_UNDEFINED
)) {
1770 OSL_debug("NULL relation with some expected attibutes");
1778 if (((expected_type
!= OSL_TYPE_ACCESS
) &&
1779 (expected_type
!= relation
->type
)) ||
1780 ((expected_type
== OSL_TYPE_ACCESS
) &&
1781 (!osl_relation_is_access(relation
)))) {
1782 OSL_warning("wrong type");
1783 osl_relation_dump(stderr
, relation
);
1787 // Check that relations have no undefined atributes.
1788 if ((relation
->nb_output_dims
== OSL_UNDEFINED
) ||
1789 (relation
->nb_input_dims
== OSL_UNDEFINED
) ||
1790 (relation
->nb_local_dims
== OSL_UNDEFINED
) ||
1791 (relation
->nb_parameters
== OSL_UNDEFINED
)) {
1792 OSL_warning("all attributes should be defined");
1793 osl_relation_dump(stderr
, relation
);
1797 // Check that a context has actually 0 output dimensions.
1798 if ((relation
->type
== OSL_TYPE_CONTEXT
) &&
1799 (relation
->nb_output_dims
!= 0)) {
1800 OSL_warning("context without 0 as number of output dimensions");
1801 osl_relation_dump(stderr
, relation
);
1805 // Check that a domain or a context has actually 0 input dimensions.
1806 if (((relation
->type
== OSL_TYPE_DOMAIN
) ||
1807 (relation
->type
== OSL_TYPE_CONTEXT
)) &&
1808 (relation
->nb_input_dims
!= 0)) {
1809 OSL_warning("domain or context without 0 input dimensions");
1810 osl_relation_dump(stderr
, relation
);
1814 // Check properties according to expected values (and if expected values
1815 // are undefined, define them with the first relation part properties).
1816 if (!osl_relation_check_attribute(&expected_nb_output_dims
,
1817 relation
->nb_output_dims
) ||
1818 !osl_relation_check_attribute(&expected_nb_input_dims
,
1819 relation
->nb_input_dims
) ||
1820 !osl_relation_check_attribute(&expected_nb_parameters
,
1821 relation
->nb_parameters
)) {
1822 osl_relation_dump(stderr
, relation
);
1826 while (relation
!= NULL
) {
1828 // Attributes (except the number of local dimensions) should be the same
1829 // in all parts of the union.
1830 if ((expected_nb_output_dims
!= relation
->nb_output_dims
) ||
1831 (expected_nb_input_dims
!= relation
->nb_input_dims
) ||
1832 (expected_nb_parameters
!= relation
->nb_parameters
)) {
1833 OSL_warning("inconsistent attributes");
1834 osl_relation_dump(stderr
, relation
);
1838 // Check whether the number of columns is OK or not.
1839 if (!osl_relation_check_nb_columns(relation
,
1840 expected_nb_output_dims
,
1841 expected_nb_input_dims
,
1842 expected_nb_parameters
)) {
1843 osl_relation_dump(stderr
, relation
);
1847 // Check the first column. The first column of a relation part should be
1848 // made of 0 or 1 only.
1849 if ((relation
->nb_rows
> 0) && (relation
->nb_columns
> 0)) {
1850 for (i
= 0; i
< relation
->nb_rows
; i
++) {
1851 if (!osl_int_zero(relation
->precision
, relation
->m
[i
], 0) &&
1852 !osl_int_one(relation
->precision
, relation
->m
[i
], 0)) {
1853 OSL_warning("first column of a relation is not "
1854 "strictly made of 0 or 1");
1855 osl_relation_dump(stderr
, relation
);
1861 // Array accesses must provide the array identifier.
1862 if ((osl_relation_is_access(relation
)) &&
1863 (osl_relation_get_array_id(relation
) == OSL_UNDEFINED
)) {
1864 osl_relation_dump(stderr
, relation
);
1868 relation
= relation
->next
;
1876 * osl_relation_union function:
1877 * this function builds a new relation from two relations provided
1878 * as parameters. The new relation is built as an union of the
1879 * two relations: the list of constraint sets are linked together.
1880 * \param[in] r1 The first relation.
1881 * \param[in] r2 The second relation.
1882 * \return A new relation corresponding to the union of r1 and r2.
1884 osl_relation_p
osl_relation_union(osl_relation_p r1
,
1885 osl_relation_p r2
) {
1886 osl_relation_p copy1
, copy2
, tmp
;
1888 if ((r1
== NULL
) && (r2
== NULL
))
1891 copy1
= osl_relation_clone(r1
);
1892 copy2
= osl_relation_clone(r2
);
1894 if ((r1
!= NULL
) && (r2
== NULL
))
1897 if ((r1
== NULL
) && (r2
!= NULL
))
1901 while (tmp
->next
!= NULL
)
1910 * osl_relation_set_attributes function:
1911 * this functions sets the attributes of a relation provided as a
1912 * parameter. It updates the relation directly.
1913 * \param[in,out] relation The relation to set the attributes.
1914 * \param[in] nb_output_dims Number of output dimensions.
1915 * \param[in] nb_input_dims Number of input dimensions.
1916 * \param[in] nb_local_dims Number of local dimensions.
1917 * \param[in] nb_parameters Number of parameters.
1919 void osl_relation_set_attributes(osl_relation_p relation
,
1920 int nb_output_dims
, int nb_input_dims
,
1921 int nb_local_dims
, int nb_parameters
) {
1922 if (relation
!= NULL
) {
1923 relation
->nb_output_dims
= nb_output_dims
;
1924 relation
->nb_input_dims
= nb_input_dims
;
1925 relation
->nb_local_dims
= nb_local_dims
;
1926 relation
->nb_parameters
= nb_parameters
;
1932 * osl_relation_set_type function:
1933 * this function sets the type of each relation union part in the relation
1934 * to the one provided as parameter.
1935 * \param relation The relation to set the type.
1936 * \param type The type.
1938 void osl_relation_set_type(osl_relation_p relation
, int type
) {
1940 while (relation
!= NULL
) {
1941 relation
->type
= type
;
1942 relation
= relation
->next
;
1948 * osl_relation_get_array_id function:
1949 * this function returns the array identifier in a relation with access type
1950 * It returns OSL_UNDEFINED if it is not able to find it (in particular
1951 * if there are irregularities in the relation).
1952 * \param[in] relation The relation where to find an array identifier.
1953 * \return The array identifier in the relation or OSL_UNDEFINED.
1955 int osl_relation_get_array_id(osl_relation_p relation
) {
1958 int array_id
= OSL_UNDEFINED
;
1959 int reference_array_id
= OSL_UNDEFINED
;
1964 if (relation
== NULL
)
1965 return OSL_UNDEFINED
;
1967 if (!osl_relation_is_access(relation
)) {
1968 OSL_warning("asked for an array id of non-array relation");
1969 return OSL_UNDEFINED
;
1972 while (relation
!= NULL
) {
1973 precision
= relation
->precision
;
1975 // There should be room to store the array identifier.
1976 if ((relation
->nb_rows
< 1) ||
1977 (relation
->nb_columns
< 3)) {
1978 OSL_warning("no array identifier in an access function");
1979 return OSL_UNDEFINED
;
1982 // Array identifiers are m[i][#columns -1] / m[i][1], with i the only row
1983 // where m[i][1] is not 0.
1984 // - check there is exactly one row such that m[i][1] is not 0,
1985 // - check the whole ith row if full of 0 except m[i][1] and the id,
1986 // - check that (m[i][#columns -1] % m[i][1]) == 0,
1987 // - check that (-m[i][#columns -1] / m[i][1]) > 0.
1989 for (i
= 0; i
< relation
->nb_rows
; i
++) {
1990 if (!osl_int_zero(precision
, relation
->m
[i
], 1)) {
1995 if (nb_array_id
== 0) {
1996 OSL_warning("no array identifier in an access function");
1997 return OSL_UNDEFINED
;
1999 if (nb_array_id
> 1) {
2000 OSL_warning("several array identifiers in one access function");
2001 return OSL_UNDEFINED
;
2003 for (i
= 0; i
< relation
->nb_columns
- 1; i
++) {
2004 if ((i
!= 1) && !osl_int_zero(precision
, relation
->m
[row_id
], i
)) {
2005 OSL_warning("non integer array identifier");
2006 return OSL_UNDEFINED
;
2009 if (!osl_int_divisible(precision
,
2010 relation
->m
[row_id
], relation
->nb_columns
- 1,
2011 relation
->m
[row_id
], 1)) {
2012 OSL_warning("rational array identifier");
2013 return OSL_UNDEFINED
;
2015 array_id
= -osl_int_get_si(precision
,
2016 relation
->m
[row_id
],
2017 relation
->nb_columns
- 1);
2018 array_id
/= osl_int_get_si(precision
, relation
->m
[row_id
], 1);
2019 if (array_id
<= 0) {
2020 OSL_warning("negative or 0 identifier in access function");
2021 return OSL_UNDEFINED
;
2024 // Unions of accesses are allowed, but they should refer at the same array.
2026 reference_array_id
= array_id
;
2030 if (reference_array_id
!= array_id
) {
2031 OSL_warning("inconsistency of array identifiers in an "
2032 "union of access relations");
2033 return OSL_UNDEFINED
;
2037 relation
= relation
->next
;
2045 * osl_relation_is_access function:
2046 * this function returns 1 if the relation corresponds to an access relation,
2047 * whatever its precise type (read, write etc.), 0 otherwise.
2048 * \param relation The relation to check wheter it is an access relation or not.
2049 * \return 1 if the relation is an access relation, 0 otherwise.
2051 int osl_relation_is_access(osl_relation_p relation
) {
2053 if (relation
== NULL
)
2056 if ((relation
->type
== OSL_TYPE_ACCESS
) ||
2057 (relation
->type
== OSL_TYPE_READ
) ||
2058 (relation
->type
== OSL_TYPE_WRITE
) ||
2059 (relation
->type
== OSL_TYPE_MAY_WRITE
))
2067 * osl_relation_get_attributes function:
2068 * this function returns, through its parameters, the maximum values of the
2069 * relation attributes (nb_iterators, nb_parameters etc), depending on its
2070 * type. HOWEVER, it updates the parameter value iff the attribute is greater
2071 * than the input parameter value. Hence it may be used to get the
2072 * attributes as well as to find the maximum attributes for several relations.
2073 * The array identifier 0 is used when there is no array identifier (AND this
2074 * is OK), OSL_UNDEFINED is used to report it is impossible to provide the
2075 * property while it should. This function is not intended for checking, the
2076 * input relation should be correct.
2077 * \param[in] relation The relation to extract attribute values.
2078 * \param[in,out] nb_parameters Number of parameter attribute.
2079 * \param[in,out] nb_iterators Number of iterators attribute.
2080 * \param[in,out] nb_scattdims Number of scattering dimensions attribute.
2081 * \param[in,out] nb_localdims Number of local dimensions attribute.
2082 * \param[in,out] array_id Maximum array identifier attribute.
2084 void osl_relation_get_attributes(osl_relation_p relation
,
2085 int * nb_parameters
,
2091 int local_nb_parameters
= OSL_UNDEFINED
;
2092 int local_nb_iterators
= OSL_UNDEFINED
;
2093 int local_nb_scattdims
= OSL_UNDEFINED
;
2094 int local_nb_localdims
= OSL_UNDEFINED
;
2095 int local_array_id
= OSL_UNDEFINED
;
2097 while (relation
!= NULL
) {
2098 if (osl_relation_is_access(relation
))
2099 type
= OSL_TYPE_ACCESS
;
2101 type
= relation
->type
;
2103 // There is some redundancy but I believe the code is cleaner this way.
2105 case OSL_TYPE_CONTEXT
:
2106 local_nb_parameters
= relation
->nb_parameters
;
2107 local_nb_iterators
= 0;
2108 local_nb_scattdims
= 0;
2109 local_nb_localdims
= relation
->nb_local_dims
;
2113 case OSL_TYPE_DOMAIN
:
2114 local_nb_parameters
= relation
->nb_parameters
;
2115 local_nb_iterators
= relation
->nb_output_dims
;
2116 local_nb_scattdims
= 0;
2117 local_nb_localdims
= relation
->nb_local_dims
;
2121 case OSL_TYPE_SCATTERING
:
2122 local_nb_parameters
= relation
->nb_parameters
;
2123 local_nb_iterators
= relation
->nb_input_dims
;
2124 local_nb_scattdims
= relation
->nb_output_dims
;
2125 local_nb_localdims
= relation
->nb_local_dims
;
2129 case OSL_TYPE_ACCESS
:
2130 local_nb_parameters
= relation
->nb_parameters
;
2131 local_nb_iterators
= relation
->nb_input_dims
;
2132 local_nb_scattdims
= 0;
2133 local_nb_localdims
= relation
->nb_local_dims
;
2134 local_array_id
= osl_relation_get_array_id(relation
);
2139 *nb_parameters
= OSL_max(*nb_parameters
, local_nb_parameters
);
2140 *nb_iterators
= OSL_max(*nb_iterators
, local_nb_iterators
);
2141 *nb_scattdims
= OSL_max(*nb_scattdims
, local_nb_scattdims
);
2142 *nb_localdims
= OSL_max(*nb_localdims
, local_nb_localdims
);
2143 *array_id
= OSL_max(*array_id
, local_array_id
);
2144 relation
= relation
->next
;
2150 * osl_relation_extend_output function:
2151 * this function extends the number of output dimensions of a given relation. It
2152 * returns a copy of the input relation with a number of output dimensions
2153 * extended to "dim" for all its union components. The new output dimensions
2154 * are simply set equal to 0. The extended number of dimensions must be higher
2155 * than or equal to the original one (an error will be raised otherwise).
2156 * \param[in] relation The input relation to extend.
2157 * \param[in] dim The number of output dimension to reach.
2158 * \return A new relation: "relation" extended to "dim" output dims.
2160 osl_relation_p
osl_relation_extend_output(osl_relation_p relation
, int dim
) {
2164 osl_relation_p extended
= NULL
, node
, previous
= NULL
;
2166 while (relation
!= NULL
) {
2167 if (relation
->nb_output_dims
> dim
)
2168 OSL_error("Number of output dims is greater than required extension");
2169 offset
= dim
- relation
->nb_output_dims
;
2171 node
= osl_relation_pmalloc(relation
->precision
,
2172 relation
->nb_rows
+ offset
,
2173 relation
->nb_columns
+ offset
);
2175 node
->type
= relation
->type
;
2176 node
->nb_output_dims
= OSL_max(relation
->nb_output_dims
, dim
);
2177 node
->nb_input_dims
= relation
->nb_input_dims
;
2178 node
->nb_local_dims
= relation
->nb_local_dims
;
2179 node
->nb_parameters
= relation
->nb_parameters
;
2181 // Copy of the original relation with some 0 columns for the new dimensions
2182 // Note that we use the fact that the matrix is initialized with zeros.
2183 for (i
= 0; i
< relation
->nb_rows
; i
++) {
2184 for (j
= 0; j
<= relation
->nb_output_dims
; j
++)
2185 osl_int_assign(relation
->precision
, node
->m
[i
], j
, relation
->m
[i
], j
);
2187 for (j
= relation
->nb_output_dims
+ offset
+ 1;
2188 j
< relation
->nb_columns
+ offset
; j
++)
2189 osl_int_assign(relation
->precision
,
2190 node
->m
[i
], j
, relation
->m
[i
], j
- offset
);
2193 // New rows dedicated to the new dimensions
2194 for (i
= relation
->nb_rows
; i
< relation
->nb_rows
+ offset
; i
++) {
2195 for (j
= 0; j
< relation
->nb_columns
+ offset
; j
++) {
2196 if ((i
- relation
->nb_rows
) == (j
- relation
->nb_output_dims
- 1))
2197 osl_int_set_si(relation
->precision
, node
->m
[i
], j
, -1);
2207 previous
->next
= node
;
2208 previous
= previous
->next
;
2211 relation
= relation
->next
;