diff options
Diffstat (limited to 'cloog-0.17.0/osl/source/relation.c')
-rw-r--r-- | cloog-0.17.0/osl/source/relation.c | 2179 |
1 files changed, 0 insertions, 2179 deletions
diff --git a/cloog-0.17.0/osl/source/relation.c b/cloog-0.17.0/osl/source/relation.c deleted file mode 100644 index a4b641a..0000000 --- a/cloog-0.17.0/osl/source/relation.c +++ /dev/null @@ -1,2179 +0,0 @@ - - /*+-----------------------------------------------------------------** - ** OpenScop Library ** - **-----------------------------------------------------------------** - ** relation.c ** - **-----------------------------------------------------------------** - ** First version: 30/04/2008 ** - **-----------------------------------------------------------------** - - - ***************************************************************************** - * OpenScop: Structures and formats for polyhedral tools to talk together * - ***************************************************************************** - * ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__, * - * / / / // // // // / / / // // / / // / /|,_, * - * / / / // // // // / / / // // / / // / / / /\ * - * |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/ \ * - * | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\ \ /\ * - * | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\ * - * | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \ \ * - * | P |n| l | = | s | t |=| = |d| = | = | = | | |=| o | | \# \ \ * - * | H | | y | | e | o | | = |l| | | = | | | | G | | \ \ \ * - * | I | | | | e | | | | | | | | | | | | | \ \ \ * - * | T | | | | | | | | | | | | | | | | | \ \ \ * - * | E | | | | | | | | | | | | | | | | | \ \ \ * - * | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | / \* \ \ * - * | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/ \ \ / * - * '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' * - * * - * Copyright (C) 2008 University Paris-Sud 11 and INRIA * - * * - * (3-clause BSD license) * - * Redistribution and use in source and binary forms, with or without * - * modification, are permitted provided that the following conditions * - * are met: * - * * - * 1. Redistributions of source code must retain the above copyright notice, * - * this list of conditions and the following disclaimer. * - * 2. Redistributions in binary form must reproduce the above copyright * - * notice, this list of conditions and the following disclaimer in the * - * documentation and/or other materials provided with the distribution. * - * 3. The name of the author may not be used to endorse or promote products * - * derived from this software without specific prior written permission. * - * * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * * - * OpenScop Library, a library to manipulate OpenScop formats and data * - * structures. Written by: * - * Cedric Bastoul <Cedric.Bastoul@u-psud.fr> and * - * Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr> * - * * - *****************************************************************************/ - - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> - -#include <osl/macros.h> -#include <osl/int.h> -#include <osl/util.h> -#include <osl/vector.h> -#include <osl/strings.h> -#include <osl/names.h> -#include <osl/relation.h> - - -/*+*************************************************************************** - * Structure display function * - *****************************************************************************/ - - -/** - * osl_relation_sprint_type function: - * this function prints the textual type of an osl_relation_t structure into - * a string, according to the OpenScop specification, and returns that string. - * \param[in] relation The relation whose type has to be printed. - * \return A string containing the relation type. - */ -static -char * osl_relation_sprint_type(osl_relation_p relation) { - char * string = NULL; - - OSL_malloc(string, char *, OSL_MAX_STRING * sizeof(char)); - string[0] = '\0'; - - if (relation != NULL) { - switch (relation->type) { - case OSL_UNDEFINED: { - snprintf(string, OSL_MAX_STRING, OSL_STRING_UNDEFINED); - break; - } - case OSL_TYPE_CONTEXT: { - snprintf(string, OSL_MAX_STRING, OSL_STRING_CONTEXT); - break; - } - case OSL_TYPE_DOMAIN: { - snprintf(string, OSL_MAX_STRING, OSL_STRING_DOMAIN); - break; - } - case OSL_TYPE_SCATTERING: { - snprintf(string, OSL_MAX_STRING, OSL_STRING_SCATTERING); - break; - } - case OSL_TYPE_READ: { - snprintf(string, OSL_MAX_STRING, OSL_STRING_READ); - break; - } - case OSL_TYPE_WRITE: { - snprintf(string, OSL_MAX_STRING, OSL_STRING_WRITE); - break; - } - case OSL_TYPE_MAY_WRITE: { - snprintf(string, OSL_MAX_STRING, OSL_STRING_MAY_WRITE); - break; - } - default: { - OSL_warning("unknown relation type, " - "replaced with "OSL_STRING_UNDEFINED); - snprintf(string, OSL_MAX_STRING, OSL_STRING_UNDEFINED); - } - } - } - - return string; -} - - -/** - * osl_relation_print_type function: - * this function displays the textual type of an osl_relation_t structure into - * a file (file, possibly stdout), according to the OpenScop specification. - * \param[in] file File where informations are printed. - * \param[in] relation The relation whose type has to be printed. - */ -static -void osl_relation_print_type(FILE * file, osl_relation_p relation) { - char * string = osl_relation_sprint_type(relation); - fprintf(file, "%s", string); - free(string); -} - - -/** - * osl_relation_idump function: - * this function displays a osl_relation_t structure (*relation) into a - * file (file, possibly stdout) in a way that trends to be understandable. - * It includes an indentation level (level) in order to work with others - * idump functions. - * \param[in] file File where informations are printed. - * \param[in] relation The relation whose information has to be printed. - * \param[in] level Number of spaces before printing, for each line. - */ -void osl_relation_idump(FILE * file, osl_relation_p relation, int level) { - int i, j, first = 1; - - // Go to the right level. - for (j = 0; j < level; j++) - fprintf(file, "|\t"); - - if (relation != NULL) { - fprintf(file, "+-- osl_relation_t ("); - osl_relation_print_type(file, relation); - fprintf(file, ", "); - osl_int_dump_precision(file, relation->precision); - fprintf(file, ")\n"); - } - else { - fprintf(file, "+-- NULL relation\n"); - } - - while (relation != NULL) { - if (! first) { - // Go to the right level. - for (j = 0; j < level; j++) - fprintf(file, "|\t"); - fprintf(file, "| osl_relation_t ("); - osl_relation_print_type(file, relation); - fprintf(file, ", "); - osl_int_dump_precision(file, relation->precision); - fprintf(file, ")\n"); - } - else - first = 0; - - // A blank line - for(j = 0; j <= level; j++) - fprintf(file, "|\t"); - fprintf(file, "%d %d %d %d %d %d\n", - relation->nb_rows, relation->nb_columns, - relation->nb_output_dims, relation->nb_input_dims, - relation->nb_local_dims, relation->nb_parameters); - - // Display the relation. - for (i = 0; i < relation->nb_rows; i++) { - for (j = 0; j <= level; j++) - fprintf(file, "|\t"); - - fprintf(file, "[ "); - - for (j = 0; j < relation->nb_columns; j++) { - osl_int_print(file, relation->precision, relation->m[i], j); - fprintf(file, " "); - } - - fprintf(file, "]\n"); - } - - relation = relation->next; - - // Next line. - if (relation != NULL) { - for (j = 0; j <= level; j++) - fprintf(file, "|\t"); - fprintf(file, "|\n"); - for (j = 0; j <= level; j++) - fprintf(file, "|\t"); - fprintf(file, "V\n"); - } - } - - // The last line. - for (j = 0; j <= level; j++) - fprintf(file, "|\t"); - fprintf(file, "\n"); -} - - -/** - * osl_relation_dump function: - * this function prints the content of a osl_relation_t structure - * (*relation) into a file (file, possibly stdout). - * \param[in] file File where informations are printed. - * \param[in] relation The relation whose information have to be printed. - */ -void osl_relation_dump(FILE * file, osl_relation_p relation) { - osl_relation_idump(file, relation, 0); -} - - -/** - * osl_relation_expression_element function: - * this function returns a string containing the printing of a value (e.g., - * an iterator with its coefficient or a constant). - * \param[in] val Address of the coefficient or constant value. - * \param[in] precision The precision of the value. - * \param[in,out] first Pointer to a boolean set to 1 if the current value - * is the first of an expresion, 0 otherwise (maybe - * updated). - * \param[in] cst A boolean set to 1 if the value is a constant, - * 0 otherwise. - * \param[in] name String containing the name of the element. - * \return A string that contains the printing of a value. - */ -static -char * osl_relation_expression_element(void * val, - int precision, int * first, - int cst, char * name) { - char * temp, * body, * sval; - - OSL_malloc(temp, char *, OSL_MAX_STRING * sizeof(char)); - OSL_malloc(body, char *, OSL_MAX_STRING * sizeof(char)); - OSL_malloc(sval, char *, OSL_MAX_STRING * sizeof(char)); - - body[0] = '\0'; - sval[0] = '\0'; - - // statements for the 'normal' processing. - if (!osl_int_zero(precision, val, 0) && (!cst)) { - if ((*first) || osl_int_neg(precision, val, 0)) { - if (osl_int_one(precision, val, 0)) { // case 1 - sprintf(sval, "%s", name); - } - else { - if (osl_int_mone(precision, val, 0)) { // case -1 - sprintf(sval, "-%s", name); - } - else { // default case - osl_int_sprint(sval, precision, val, 0); - sprintf(temp, "*%s", name); - strcat(sval, temp); - } - } - *first = 0; - } - else { - if (osl_int_one(precision, val, 0)) { - sprintf(sval, "+%s", name); - } - else { - sprintf(sval, "+"); - osl_int_sprint_txt(temp, precision, val, 0); - strcat(sval, temp); - sprintf(temp, "*%s", name); - strcat(sval, temp); - } - } - } - else { - if (cst) { - if ((osl_int_zero(precision, val, 0) && (*first)) || - (osl_int_neg(precision, val, 0))) - osl_int_sprint_txt(sval, precision, val, 0); - if (osl_int_pos(precision, val, 0)) { - if (!(*first)) { - sprintf(sval, "+"); - osl_int_sprint_txt(temp, precision, val, 0); - strcat(sval, temp); - } - else { - osl_int_sprint_txt(sval, precision, val, 0); - } - } - } - } - free(temp); - free(body); - - return(sval); -} - - -/** - * osl_relation_strings function: - * this function creates a NULL-terminated array of strings from an - * osl_names_t structure in such a way that the ith string is the "name" - * corresponding to the ith column of the constraint matrix. - * \param[in] relation The relation for which we need an array of names. - * \param[in] names The set of names for each element. - * \return An array of strings with one string per constraint matrix column. - */ -static -char ** osl_relation_strings(osl_relation_p relation, osl_names_p names) { - char ** strings; - char temp[OSL_MAX_STRING]; - int i, offset, array_id; - - if ((relation == NULL) || (names == NULL)) { - OSL_debug("no names or relation to build the name array"); - return NULL; - } - - OSL_malloc(strings, char **, (relation->nb_columns + 1)*sizeof(char *)); - strings[relation->nb_columns] = NULL; - - // 1. Equality/inequality marker. - OSL_strdup(strings[0], "e/i"); - offset = 1; - - // 2. Output dimensions. - if (osl_relation_is_access(relation)) { - // The first output dimension is the array name. - array_id = osl_relation_get_array_id(relation); - OSL_strdup(strings[offset], names->arrays->string[array_id - 1]); - // The other ones are the array dimensions [1]...[n] - for (i = offset + 1; i < relation->nb_output_dims + offset; i++) { - sprintf(temp, "[%d]", i - 1); - OSL_strdup(strings[i], temp); - } - } - else - if (relation->type == OSL_TYPE_SCATTERING) { - for (i = offset; i < relation->nb_output_dims + offset; i++) { - OSL_strdup(strings[i], names->scatt_dims->string[i - offset]); - } - } - else { - for (i = offset; i < relation->nb_output_dims + offset; i++) { - OSL_strdup(strings[i], names->iterators->string[i - offset]); - } - } - offset += relation->nb_output_dims; - - // 3. Input dimensions. - for (i = offset; i < relation->nb_input_dims + offset; i++) - OSL_strdup(strings[i], names->iterators->string[i - offset]); - offset += relation->nb_input_dims; - - // 4. Local dimensions. - for (i = offset; i < relation->nb_local_dims + offset; i++) - OSL_strdup(strings[i], names->local_dims->string[i - offset]); - offset += relation->nb_local_dims; - - // 5. Parameters. - for (i = offset; i < relation->nb_parameters + offset; i++) - OSL_strdup(strings[i], names->parameters->string[i - offset]); - offset += relation->nb_parameters; - - // 6. Scalar. - OSL_strdup(strings[offset], "1"); - - return strings; -} - - -/** - * osl_relation_subexpression function: - * this function returns a string corresponding to an affine (sub-)expression - * stored at the "row"^th row of the relation pointed by "relation" between - * the start and stop columns. Optionnaly it may oppose the whole expression. - * \param[in] relation A set of linear expressions. - * \param[in] row The row corresponding to the expression. - * \param[in] start The first column for the expression (inclusive). - * \param[in] stop The last column for the expression (inclusive). - * \param[in] oppose Boolean set to 1 to negate the expression, 0 otherwise. - * \param[in] strings Array of textual names of the various elements. - * \return A string that contains the printing of an affine (sub-)expression. - */ -static -char * osl_relation_subexpression(osl_relation_p relation, - int row, int start, int stop, int oppose, - char ** strings) { - int i, first = 1, constant; - char * sval; - char * sline; - - OSL_malloc(sline, char *, OSL_MAX_STRING * sizeof(char)); - sline[0] = '\0'; - - // Create the expression. The constant is a special case. - for (i = start; i <= stop; i++) { - if (oppose) { - osl_int_oppose(relation->precision, - relation->m[row], i, relation->m[row], i); - } - - if (i == relation->nb_columns - 1) - constant = 1; - else - constant = 0; - - sval = osl_relation_expression_element( - osl_int_address(relation->precision, relation->m[row], i), - relation->precision, &first, constant, strings[i]); - - if (oppose) { - osl_int_oppose(relation->precision, - relation->m[row], i, relation->m[row], i); - } - strcat(sline, sval); - free(sval); - } - - return sline; -} - - -/** - * osl_relation_expression function: - * this function returns a string corresponding to an affine expression - * stored at the "row"^th row of the relation pointed by "relation". - * \param[in] relation A set of linear expressions. - * \param[in] row The row corresponding to the expression. - * \param[in] strings Array of textual names of the various elements. - * \return A string that contains the printing of an affine expression. - */ -char * osl_relation_expression(osl_relation_p relation, - int row, char ** strings) { - - return osl_relation_subexpression(relation, row, - 1, relation->nb_columns - 1, 0, - strings); -} - - -/** - * osl_relation_is_simple_output function: - * this function returns 1 or -1 if a given constraint row of a relation - * corresponds to an output, 0 otherwise. We call a simple output an equality - * constraint where exactly one output coefficient is not 0 and is either - * 1 (in this case the function returns 1) or -1 (in this case the function - * returns -1). - * \param[in] relation The relation to test for simple output. - * \param[in] row The row corresponding to the constraint to test. - * \return 1 or -1 if the row is a simple output, 0 otherwise. - */ -static -int osl_relation_is_simple_output(osl_relation_p relation, int row) { - int i; - int first = 1; - int sign = 0; - - if ((relation == NULL) || - (relation->m == NULL) || - (relation->nb_output_dims == 0)) - return 0; - - if ((row < 0) || (row > relation->nb_rows)) - OSL_error("the specified row does not exist in the relation"); - - // The constraint must be an equality. - if (!osl_int_zero(relation->precision, relation->m[row], 0)) - return 0; - - // Check the output part has one and only one non-zero +1 or -1 coefficient. - first = 1; - for (i = 1; i <= relation->nb_output_dims; i++) { - if (!osl_int_zero(relation->precision, relation->m[row], i)) { - if (first) - first = 0; - else - return 0; - - if (osl_int_one(relation->precision, relation->m[row], i)) - sign = 1; - else if (osl_int_mone(relation->precision, relation->m[row], i)) - sign = -1; - else - return 0; - } - } - - return sign; -} - - -/** - * osl_relation_sprint_comment function: - * this function prints into a string a comment corresponding to a constraint - * of a relation, according to its type, then it returns this string. This - * function does not check that printing the comment is possible (i.e., are - * there enough names ?), hence it is the responsibility of the user to ensure - * he/she can call this function safely. - * \param[in] relation The relation for which a comment has to be printed. - * \param[in] row The constrain row for which a comment has to be printed. - * \param[in] strings Array of textual names of the various elements. - * \return A string which contains the comment for the row. - */ -static -char * osl_relation_sprint_comment(osl_relation_p relation, - int row, char ** strings) { - int sign; - int high_water_mark = OSL_MAX_STRING; - char * string = NULL; - char * expression; - char buffer[OSL_MAX_STRING]; - - OSL_malloc(string, char *, high_water_mark * sizeof(char)); - string[0] = '\0'; - - if ((relation == NULL) || (strings == NULL)) { - OSL_debug("no relation or names while asked to print a comment"); - return string; - } - - if ((sign = osl_relation_is_simple_output(relation, row))) { - // First case : output == expression. - - expression = osl_relation_subexpression(relation, row, - 1, relation->nb_output_dims, - sign < 0, - strings); - snprintf(buffer, OSL_MAX_STRING, " ## %s", expression); - osl_util_safe_strcat(&string, buffer, &high_water_mark); - free(expression); - - // We don't print the right hand side if it's an array identifier. - if (!osl_relation_is_access(relation) || - osl_int_zero(relation->precision, relation->m[row], 1)) { - expression = osl_relation_subexpression(relation, row, - relation->nb_output_dims + 1, - relation->nb_columns - 1, - sign > 0, - strings); - snprintf(buffer, OSL_MAX_STRING, " == %s", expression); - osl_util_safe_strcat(&string, buffer, &high_water_mark); - free(expression); - } - } - else { - // Second case : general case. - - expression = osl_relation_expression(relation, row, strings); - snprintf(buffer, OSL_MAX_STRING, " ## %s", expression); - osl_util_safe_strcat(&string, buffer, &high_water_mark); - free(expression); - - if (osl_int_zero(relation->precision, relation->m[row], 0)) - snprintf(buffer, OSL_MAX_STRING, " == 0"); - else - snprintf(buffer, OSL_MAX_STRING, " >= 0"); - osl_util_safe_strcat(&string, buffer, &high_water_mark); - } - - return string; -} - - -/** - * osl_relation_column_string function: - * this function returns an OpenScop comment string showing all column - * names. It is designed to nicely fit a constraint matrix that would be - * printed just below this line. - * \param[in] relation The relation related to the comment line to build. - * \param[in] strings Array of textual names of the various elements. - * \return A fancy comment string with all the dimension names. - */ -static -char * osl_relation_column_string(osl_relation_p relation, char ** strings) { - int i, j; - int index_output_dims; - int index_input_dims; - int index_local_dims; - int index_parameters; - int index_scalar; - int space, length, left, right; - char * scolumn; - char temp[OSL_MAX_STRING]; - - OSL_malloc(scolumn, char *, OSL_MAX_STRING); - - index_output_dims = 1; - index_input_dims = index_output_dims + relation->nb_output_dims; - index_local_dims = index_input_dims + relation->nb_input_dims; - index_parameters = index_local_dims + relation->nb_local_dims; - index_scalar = index_parameters + relation->nb_parameters; - - // 1. The comment part. - sprintf(scolumn, "#"); - for (j = 0; j < (OSL_FMT_LENGTH - 1)/2 - 1; j++) - strcat(scolumn, " "); - - i = 0; - while (strings[i] != NULL) { - space = OSL_FMT_LENGTH; - length = (space > strlen(strings[i])) ? strlen(strings[i]) : space; - right = (space - length + (OSL_FMT_LENGTH % 2)) / 2; - left = space - length - right; - - // 2. Spaces before the name - for (j = 0; j < left; j++) - strcat(scolumn, " "); - - // 3. The (abbreviated) name - for (j = 0; j < length - 1; j++) { - sprintf(temp, "%c", strings[i][j]); - strcat(scolumn, temp); - } - if (length >= strlen(strings[i])) - sprintf(temp, "%c", strings[i][j]); - else - sprintf(temp, "."); - strcat(scolumn, temp); - - // 4. Spaces after the name - for (j = 0; j < right; j++) - strcat(scolumn, " "); - - i++; - if ((i == index_output_dims) || - (i == index_input_dims) || - (i == index_local_dims) || - (i == index_parameters) || - (i == index_scalar)) - strcat(scolumn, "|"); - else - strcat(scolumn, " "); - } - strcat(scolumn, "\n"); - - return scolumn; -} - - -/** - * osl_relation_names function: - * this function generates as set of names for all the dimensions - * involved in a given relation. - * \param[in] relation The relation we have to generate names for. - * \return A set of generated names for the input relation dimensions. - */ -static -osl_names_p osl_relation_names(osl_relation_p relation) { - int nb_parameters = OSL_UNDEFINED; - int nb_iterators = OSL_UNDEFINED; - int nb_scattdims = OSL_UNDEFINED; - int nb_localdims = OSL_UNDEFINED; - int array_id = OSL_UNDEFINED; - - osl_relation_get_attributes(relation, &nb_parameters, &nb_iterators, - &nb_scattdims, &nb_localdims, &array_id); - - return osl_names_generate("P", nb_parameters, - "i", nb_iterators, - "c", nb_scattdims, - "l", nb_localdims, - "A", array_id); -} - - -/** - * osl_relation_nb_components function: - * this function returns the number of component in the union of relations - * provided as parameter. - * \param[in] relation The input union of relations. - * \return The number of components in the input union of relations. - */ -int osl_relation_nb_components(osl_relation_p relation) { - int nb_components = 0; - - while (relation != NULL) { - nb_components++; - relation = relation->next; - } - - return nb_components; -} - - -/** - * osl_relation_spprint_polylib function: - * this function pretty-prints the content of an osl_relation_t structure - * (*relation) into a string in the extended polylib format, and returns this - * string. This format is the same as OpenScop's, minus the type. - * \param[in] relation The relation whose information has to be printed. - * \param[in] names The names of the constraint columns for comments. - * \return A string containing the relation pretty-printing. - */ -char * osl_relation_spprint_polylib(osl_relation_p relation, - osl_names_p names) { - int i, j; - int part, nb_parts; - int generated_names = 0; - int high_water_mark = OSL_MAX_STRING; - char * string = NULL; - char buffer[OSL_MAX_STRING]; - char ** name_array = NULL; - char * scolumn; - char * comment; - - if (relation == NULL) - return strdup("# NULL relation\n"); - - OSL_malloc(string, char *, high_water_mark * sizeof(char)); - string[0] = '\0'; - - // Generates the names for the comments if necessary. - if (names == NULL) { - generated_names = 1; - names = osl_relation_names(relation); - } - - nb_parts = osl_relation_nb_components(relation); - - if (nb_parts > 1) { - snprintf(buffer, OSL_MAX_STRING, "# Union with %d parts\n%d\n", - nb_parts, nb_parts); - osl_util_safe_strcat(&string, buffer, &high_water_mark); - } - - // Print each part of the union. - for (part = 1; part <= nb_parts; part++) { - // Prepare the array of strings for comments. - name_array = osl_relation_strings(relation, names); - - if (nb_parts > 1) { - snprintf(buffer, OSL_MAX_STRING, "# Union part No.%d\n", part); - osl_util_safe_strcat(&string, buffer, &high_water_mark); - } - - snprintf(buffer, OSL_MAX_STRING, "%d %d %d %d %d %d\n", - relation->nb_rows, relation->nb_columns, - relation->nb_output_dims, relation->nb_input_dims, - relation->nb_local_dims, relation->nb_parameters); - osl_util_safe_strcat(&string, buffer, &high_water_mark); - - if (relation->nb_rows > 0) { - scolumn = osl_relation_column_string(relation, name_array); - snprintf(buffer, OSL_MAX_STRING, "%s", scolumn); - osl_util_safe_strcat(&string, buffer, &high_water_mark); - free(scolumn); - } - - for (i = 0; i < relation->nb_rows; i++) { - for (j = 0; j < relation->nb_columns; j++) { - osl_int_sprint(buffer, relation->precision, relation->m[i], j); - osl_util_safe_strcat(&string, buffer, &high_water_mark); - snprintf(buffer, OSL_MAX_STRING, " "); - osl_util_safe_strcat(&string, buffer, &high_water_mark); - } - - if (name_array != NULL) { - comment = osl_relation_sprint_comment(relation, i, name_array); - osl_util_safe_strcat(&string, comment, &high_water_mark); - free(comment); - } - snprintf(buffer, OSL_MAX_STRING, "\n"); - osl_util_safe_strcat(&string, buffer, &high_water_mark); - } - - // Free the array of strings. - if (name_array != NULL) { - for (i = 0; i < relation->nb_columns; i++) - free(name_array[i]); - free(name_array); - } - - relation = relation->next; - } - - if (generated_names) - osl_names_free(names); - - return string; -} - - -/** - * osl_relation_spprint function: - * this function pretty-prints the content of an osl_relation_t structure - * (*relation) into a string in the OpenScop format, and returns this string. - * \param[in] relation The relation whose information has to be printed. - * \param[in] names The names of the constraint columns for comments. - * \return A string - */ -char * osl_relation_spprint(osl_relation_p relation, osl_names_p names) { - int high_water_mark = OSL_MAX_STRING; - char * string = NULL; - char * temp; - char buffer[OSL_MAX_STRING]; - OSL_malloc(string, char *, high_water_mark * sizeof(char)); - string[0] = '\0'; - - if (osl_relation_nb_components(relation) > 0) { - temp = osl_relation_sprint_type(relation); - osl_util_safe_strcat(&string, temp, &high_water_mark); - free(temp); - - snprintf(buffer, OSL_MAX_STRING, "\n"); - osl_util_safe_strcat(&string, buffer, &high_water_mark); - - temp = osl_relation_spprint_polylib(relation, names); - osl_util_safe_strcat(&string, temp, &high_water_mark); - free(temp); - } - - return string; -} - - -/** - * osl_relation_pprint function: - * this function pretty-prints the content of an osl_relation_t structure - * (*relation) into a file (file, possibly stdout) in the OpenScop format. - * \param[in] file File where informations are printed. - * \param[in] relation The relation whose information has to be printed. - * \param[in] names The names of the constraint columns for comments. - */ -void osl_relation_pprint(FILE * file, osl_relation_p relation, - osl_names_p names) { - char * string = osl_relation_spprint(relation, names); - fprintf(file, "%s", string); - free(string); -} - - -/** - * osl_relation_print function: - * this function prints the content of an osl_relation_t structure - * (*relation) into a file (file, possibly stdout) in the OpenScop format. - * \param[in] file File where informations are printed. - * \param[in] relation The relation whose information has to be printed. - */ -void osl_relation_print(FILE * file, osl_relation_p relation) { - - osl_relation_pprint(file, relation, NULL); -} - - -/***************************************************************************** - * Reading function * - *****************************************************************************/ - - -/** - * osl_relation_read_type function: - * this function reads a textual relation type and returns its integer - * counterpart. - * \param[in] file The input stream. - * \return The relation type. - */ -static -int osl_relation_read_type(FILE * file) { - int type; - osl_strings_p strings; - - strings = osl_strings_read(file); - if (osl_strings_size(strings) > 1) { - OSL_warning("uninterpreted information (after the relation type)"); - } - if (osl_strings_size(strings) == 0) - OSL_error("no relation type"); - - if (!strcmp(strings->string[0], OSL_STRING_UNDEFINED)) { - type = OSL_UNDEFINED; - goto return_type; - } - - if (!strcmp(strings->string[0], OSL_STRING_CONTEXT)) { - type = OSL_TYPE_CONTEXT; - goto return_type; - } - - if (!strcmp(strings->string[0], OSL_STRING_DOMAIN)) { - type = OSL_TYPE_DOMAIN; - goto return_type; - } - - if (!strcmp(strings->string[0], OSL_STRING_SCATTERING)) { - type = OSL_TYPE_SCATTERING; - goto return_type; - } - - if (!strcmp(strings->string[0], OSL_STRING_READ)) { - type = OSL_TYPE_READ; - goto return_type; - } - - if (!strcmp(strings->string[0], OSL_STRING_WRITE)) { - type = OSL_TYPE_WRITE; - goto return_type; - } - - if (!strcmp(strings->string[0], OSL_STRING_MAY_WRITE)) { - type = OSL_TYPE_MAY_WRITE; - goto return_type; - } - - OSL_error("relation type not supported"); - -return_type: - osl_strings_free(strings); - return type; -} - - -/** - * osl_relation_pread function ("precision read"): - * this function reads a relation into a file (foo, posibly stdin) and - * returns a pointer this relation. The relation is set to the maximum - * available precision. - * \param[in] foo The input stream. - * \param[in] precision The precision of the relation elements. - * \return A pointer to the relation structure that has been read. - */ -osl_relation_p osl_relation_pread(FILE * foo, int precision) { - int i, j, k, n, read = 0; - int nb_rows, nb_columns; - int nb_output_dims, nb_input_dims, nb_local_dims, nb_parameters; - int nb_union_parts = 1; - int may_read_nb_union_parts = 1; - int read_attributes = 1; - int first = 1; - int type; - char * c, s[OSL_MAX_STRING], str[OSL_MAX_STRING], *tmp; - osl_relation_p relation, relation_union = NULL, previous = NULL; - - type = osl_relation_read_type(foo); - - // Read each part of the union (the number of parts may be updated inside) - for (k = 0; k < nb_union_parts; k++) { - // Read the number of union parts or the attributes of the union part - while (read_attributes) { - read_attributes = 0; - - // Read relation attributes. - c = osl_util_skip_blank_and_comments(foo, s); - read = sscanf(c, " %d %d %d %d %d %d", &nb_rows, &nb_columns, - &nb_output_dims, &nb_input_dims, - &nb_local_dims, &nb_parameters); - - if (((read != 1) && (read != 6)) || - ((read == 1) && (may_read_nb_union_parts != 1))) - OSL_error("not 1 or 6 integers on the first relation line"); - - if (read == 1) { - // Only one number means a union and is the number of parts. - nb_union_parts = nb_rows; - if (nb_union_parts < 1) - OSL_error("negative nb of union parts"); - - // Allow to read the properties of the first part of the union. - read_attributes = 1; - } - - may_read_nb_union_parts = 0; - } - - // Allocate the union part and fill its properties. - relation = osl_relation_pmalloc(precision, nb_rows, nb_columns); - relation->type = type; - relation->nb_output_dims = nb_output_dims; - relation->nb_input_dims = nb_input_dims; - relation->nb_local_dims = nb_local_dims; - relation->nb_parameters = nb_parameters; - - // Read the matrix of constraints. - for (i = 0; i < relation->nb_rows; i++) { - c = osl_util_skip_blank_and_comments(foo, s); - if (c == NULL) - OSL_error("not enough rows"); - - for (j = 0; j < relation->nb_columns; j++) { - if (c == NULL || *c == '#' || *c == '\n') - OSL_error("not enough columns"); - if (sscanf(c, "%s%n", str, &n) == 0) - OSL_error("not enough rows"); - - // TODO: remove this tmp (sread updates the pointer). - tmp = str; - osl_int_sread(&tmp, precision, relation->m[i], j); - c += n; - } - } - - // Build the linked list of union parts. - if (first == 1) { - relation_union = relation; - first = 0; - } - else { - previous->next = relation; - } - - previous = relation; - read_attributes = 1; - } - - return relation_union; -} - - -/** - * osl_relation_read function: - * this function is equivalent to osl_relation_pread() except that - * the precision corresponds to the precision environment variable or - * to the highest available precision if it is not defined. - * \see{osl_relation_pread} - */ -osl_relation_p osl_relation_read(FILE * foo) { - int precision = osl_util_get_precision(); - return osl_relation_pread(foo, precision); -} - - -/*+*************************************************************************** - * Memory allocation/deallocation function * - *****************************************************************************/ - - -/** - * osl_relation_pmalloc function: - * (precision malloc) this function allocates the memory space for an - * osl_relation_t structure and sets its fields with default values. - * Then it returns a pointer to the allocated space. - * \param[in] precision The precision of the constraint matrix. - * \param[in] nb_rows The number of row of the relation to allocate. - * \param[in] nb_columns The number of columns of the relation to allocate. - * \return A pointer to an empty relation with fields set to default values - * and a ready-to-use constraint matrix. - */ -osl_relation_p osl_relation_pmalloc(int precision, - int nb_rows, int nb_columns) { - osl_relation_p relation; - void ** p, * q; - int i, j; - - OSL_malloc(relation, osl_relation_p, sizeof(osl_relation_t)); - relation->type = OSL_UNDEFINED; - relation->nb_rows = nb_rows; - relation->nb_columns = nb_columns; - relation->nb_output_dims = OSL_UNDEFINED; - relation->nb_input_dims = OSL_UNDEFINED; - relation->nb_parameters = OSL_UNDEFINED; - relation->nb_local_dims = OSL_UNDEFINED; - relation->precision = precision; - - if ((nb_rows == 0) || (nb_columns == 0) || - (nb_rows == OSL_UNDEFINED) || (nb_columns == OSL_UNDEFINED)) { - relation->m = NULL; - } - else { - OSL_malloc(p, void **, nb_rows * sizeof(void *)); - OSL_malloc(q, void *, - nb_rows * nb_columns * osl_int_sizeof(precision)); - relation->m = p; - for (i = 0; i < nb_rows; i++) { - relation->m[i] = osl_int_address(precision, q, i * nb_columns); - for (j = 0; j < nb_columns; j++) - osl_int_init_set_si(precision, relation->m[i], j, 0); - } - } - - relation->next = NULL; - - return relation; -} - - -/** - * osl_relation_malloc function: - * this function is equivalent to osl_relation_pmalloc() except that - * the precision corresponds to the precision environment variable or - * to the highest available precision if it is not defined. - * \see{osl_relation_pmalloc} - */ -osl_relation_p osl_relation_malloc(int nb_rows, int nb_columns) { - int precision = osl_util_get_precision(); - return osl_relation_pmalloc(precision, nb_rows, nb_columns); -} - - -/** - * osl_relation_free_inside function: - * this function frees the allocated memory for the inside of a - * osl_relation_t structure, i.e. only m. - * \param[in] relation The pointer to the relation we want to free internals. - */ -void osl_relation_free_inside(osl_relation_p relation) { - int i, nb_elements; - void * p; - - if (relation == NULL) - return; - - nb_elements = relation->nb_rows * relation->nb_columns; - - if (nb_elements > 0) - p = relation->m[0]; - - for (i = 0; i < nb_elements; i++) - osl_int_clear(relation->precision, p, i); - - if (relation->m != NULL) { - if (nb_elements > 0) - free(relation->m[0]); - free(relation->m); - } -} - - -/** - * osl_relation_free function: - * this function frees the allocated memory for an osl_relation_t - * structure. - * \param[in] relation The pointer to the relation we want to free. - */ -void osl_relation_free(osl_relation_p relation) { - osl_relation_p tmp; - - if (relation == NULL) - return; - - while (relation != NULL) { - tmp = relation->next; - osl_relation_free_inside(relation); - free(relation); - relation = tmp; - } -} - - -/*+*************************************************************************** - * Processing functions * - *****************************************************************************/ - - -/** - * osl_relation_nclone function: - * this functions builds and returns a "hard copy" (not a pointer copy) of a - * osl_relation_t data structure such that the clone is restricted to the - * "n" first rows of the relation. This applies to all the parts in the case - * of a relation union. - * \param[in] relation The pointer to the relation we want to clone. - * \param[in] n The number of row of the relation we want to clone (the - * special value -1 means "all the rows"). - * \return A pointer to the clone of the relation union restricted to the - * first n rows of constraint matrix for each part of the union. - */ -osl_relation_p osl_relation_nclone(osl_relation_p relation, int n) { - int i, j; - int first = 1, all_rows = 0; - osl_relation_p clone = NULL, node, previous = NULL; - - if (n == -1) - all_rows = 1; - - while (relation != NULL) { - if (all_rows) - n = relation->nb_rows; - - if (n > relation->nb_rows) - OSL_error("not enough rows to clone in the relation"); - - node = osl_relation_pmalloc(relation->precision, n, relation->nb_columns); - node->type = relation->type; - node->nb_output_dims = relation->nb_output_dims; - node->nb_input_dims = relation->nb_input_dims; - node->nb_local_dims = relation->nb_local_dims; - node->nb_parameters = relation->nb_parameters; - - for (i = 0; i < n; i++) - for (j = 0; j < relation->nb_columns; j++) - osl_int_assign(relation->precision, node->m[i], j, relation->m[i], j); - - if (first) { - first = 0; - clone = node; - previous = node; - } - else { - previous->next = node; - previous = previous->next; - } - - relation = relation->next; - } - - return clone; -} - - -/** - * osl_relation_clone function: - * this function builds and returns a "hard copy" (not a pointer copy) of an - * osl_relation_t data structure (the full union of relation). - * \param[in] relation The pointer to the relation we want to clone. - * \return A pointer to the clone of the union of relations. - */ -osl_relation_p osl_relation_clone(osl_relation_p relation) { - if (relation == NULL) - return NULL; - - return osl_relation_nclone(relation, -1); -} - - -/** - * osl_relation_replace_vector function: - * this function replaces the "row"^th row of a relation "relation" with the - * vector "vector". It directly updates the relation union part pointed - * by "relation" and this part only. - * \param[in,out] relation The relation we want to replace a row. - * \param[in] vector The vector that will replace a row of the relation. - * \param[in] row The row of the relation to be replaced. - */ -void osl_relation_replace_vector(osl_relation_p relation, - osl_vector_p vector, int row) { - int i; - - if ((relation == NULL) || (vector == NULL) || - (relation->precision != vector->precision) || - (relation->nb_columns != vector->size) || - (row >= relation->nb_rows) || (row < 0)) - OSL_error("vector cannot replace relation row"); - - for (i = 0; i < vector->size; i++) - osl_int_assign(relation->precision, relation->m[row], i, vector->v, i); -} - - -/** - * osl_relation_add_vector function: - * this function adds (meaning, +) a vector to the "row"^th row of a - * relation "relation". It directly updates the relation union part pointed - * by "relation" and this part only. - * \param[in,out] relation The relation we want to add a vector to a row. - * \param[in] vector The vector that will replace a row of the relation. - * \param[in] row The row of the relation to add the vector. - */ -void osl_relation_add_vector(osl_relation_p relation, - osl_vector_p vector, int row) { - int i; - - if ((relation == NULL) || (vector == NULL) || - (relation->precision != vector->precision) || - (relation->nb_columns != vector->size) || - (row >= relation->nb_rows) || (row < 0)) - OSL_error("vector cannot be added to relation"); - - if (osl_int_get_si(relation->precision, relation->m[row], 0) == 0) - osl_int_assign(relation->precision, relation->m[row], 0, vector->v, 0); - - for (i = 1; i < vector->size; i++) - osl_int_add(relation->precision, - relation->m[row], i, relation->m[row], i, vector->v, i); -} - - -/** - * osl_relation_sub_vector function: - * this function subtracts the vector "vector" to the "row"^th row of - * a relation "relation. It directly updates the relation union part pointed - * by "relation" and this part only. - * \param[in,out] relation The relation where to subtract a vector to a row. - * \param[in] vector The vector to subtract to a relation row. - * \param[in] row The row of the relation to subtract the vector. - */ -void osl_relation_sub_vector(osl_relation_p relation, - osl_vector_p vector, int row) { - int i; - - if ((relation == NULL) || (vector == NULL) || - (relation->precision != vector->precision) || - (relation->nb_columns != vector->size) || - (row >= relation->nb_rows) || (row < 0)) - OSL_error("vector cannot be subtracted to row"); - - if (osl_int_get_si(relation->precision, relation->m[row], 0) == 0) - osl_int_assign(relation->precision, relation->m[row], 0, vector->v, 0); - - for (i = 1; i < vector->size; i++) - osl_int_sub(relation->precision, - relation->m[row], i, relation->m[row], i, vector->v, i); -} - - -/** - * osl_relation_insert_vector function: - * this function inserts a new row corresponding to the vector "vector" to - * the relation "relation" by inserting it at the "row"^th row. It directly - * updates the relation union part pointed by "relation" and this part only. - * If "vector" (or "relation") is NULL, the relation is left unmodified. - * \param[in,out] relation The relation we want to extend. - * \param[in] vector The vector that will be added relation. - * \param[in] row The row where to insert the vector. - */ -void osl_relation_insert_vector(osl_relation_p relation, - osl_vector_p vector, int row) { - osl_relation_p temp; - - temp = osl_relation_from_vector(vector); - osl_relation_insert_constraints(relation, temp, row); - osl_relation_free(temp); -} - - -/** - * osl_relation_insert_blank_row function: - * this function inserts a new row filled with zeros o an existing relation - * union part (it only affects the first union part). - * \param[in,out] relation The relation to add a row in. - * \param[in] row The row where to insert the blank row. - */ -void osl_relation_insert_blank_row(osl_relation_p relation, int row) { - osl_vector_p vector; - - if (relation != NULL) { - vector = osl_vector_pmalloc(relation->precision, relation->nb_columns); - osl_relation_insert_vector(relation, vector, row); - osl_vector_free(vector); - } -} - - -/** - * osl_relation_insert_blank_column function: - * this function inserts a new column filled with zeros to an existing - * relation union part (it only affects the first union part). WARNING: - * this function does not update the relation attributes. - * \param[in,out] relation The relation to add a column in. - * \param[in] column The column where to insert the blank column. - */ -void osl_relation_insert_blank_column(osl_relation_p relation, int column) { - - int i, j; - osl_relation_p temp; - - if (relation == NULL) - return; - - if ((column < 0) || (column > relation->nb_columns)) - OSL_error("bad column number"); - - // We use a temporary relation just to reuse existing functions. Cleaner. - temp = osl_relation_pmalloc(relation->precision, - relation->nb_rows, relation->nb_columns + 1); - - for (i = 0; i < relation->nb_rows; i++) { - for (j = 0; j < column; j++) - osl_int_assign(relation->precision, temp->m[i], j, relation->m[i], j); - - for (j = column; j < relation->nb_columns; j++) - osl_int_assign(relation->precision, temp->m[i], j+1, relation->m[i], j); - } - - osl_relation_free_inside(relation); - - // Replace the inside of relation. - relation->nb_columns = temp->nb_columns; - relation->m = temp->m; - - // Free the temp "shell". - free(temp); -} - - -/** - * osl_relation_from_vector function: - * this function converts a vector "vector" to a relation with a single row - * and returns a pointer to that relation. - * \param[in] vector The vector to convert to a relation. - * \return A pointer to a relation resulting from the vector conversion. - */ -osl_relation_p osl_relation_from_vector(osl_vector_p vector) { - osl_relation_p relation; - - if (vector == NULL) - return NULL; - - relation = osl_relation_pmalloc(vector->precision, 1, vector->size); - osl_relation_replace_vector(relation, vector, 0); - return relation; -} - - -/** - * osl_relation_replace_constraints function: - * this function replaces some rows of a relation "r1" with the rows of - * the relation "r2". It begins at the "row"^th row of "r1". It directly - * updates the relation union part pointed by "r1" and this part only. - * \param[in,out] r1 The relation we want to change some rows. - * \param[in] r2 The relation containing the new rows. - * \param[in] row The first row of the relation r1 to be replaced. - */ -void osl_relation_replace_constraints(osl_relation_p r1, - osl_relation_p r2, int row) { - int i, j; - - if ((r1 == NULL) || (r2 == NULL) || - (r1->precision != r2->precision) || - (r1->nb_columns != r1->nb_columns) || - ((row + r2->nb_rows) > r1->nb_rows) || (row < 0)) - OSL_error("relation rows could not be replaced"); - - for (i = 0; i < r2->nb_rows; i++) - for (j = 0; j < r2->nb_columns; j++) - osl_int_assign(r1->precision, r1->m[i+row], j, r2->m[i], j); -} - - -/** - * osl_relation_insert_constraints function: - * this function adds new rows corresponding to the relation "r1" to - * the relation "r2" by inserting it at the "row"^th row. It directly - * updates the relation union part pointed by "r1" and this part only. - * If "r2" (or "r1") is NULL, the relation is left unmodified. - * \param[in,out] r1 The relation we want to extend. - * \param[in] r2 The relation to be inserted. - * \param[in] row The row where to insert the relation - */ -void osl_relation_insert_constraints(osl_relation_p r1, - osl_relation_p r2, int row) { - int i, j; - osl_relation_p temp; - - if ((r1 == NULL) || (r2 == NULL)) - return; - - if ((r1->nb_columns != r2->nb_columns) || - (r1->precision != r2->precision) || - (row > r1->nb_rows) || (row < 0)) - OSL_error("constraints cannot be inserted"); - - // We use a temporary relation just to reuse existing functions. Cleaner. - temp = osl_relation_pmalloc(r1->precision, - r1->nb_rows + r2->nb_rows, r1->nb_columns); - - for (i = 0; i < row; i++) - for (j = 0; j < r1->nb_columns; j++) - osl_int_assign(r1->precision, temp->m[i], j, r1->m[i], j); - - osl_relation_replace_constraints(temp, r2, row); - - for (i = row + r2->nb_rows; i < r2->nb_rows + r1->nb_rows; i++) - for (j = 0; j < r1->nb_columns; j++) - osl_int_assign(r1->precision, temp->m[i], j, r1->m[i-r2->nb_rows], j); - - osl_relation_free_inside(r1); - - // Replace the inside of relation. - r1->nb_rows = temp->nb_rows; - r1->m = temp->m; - - // Free the temp "shell". - free(temp); -} - - -/** - * osl_relation_insert_columns function: - * this function inserts new columns to an existing relation union part (it - * only affects the first union part). The columns are copied out from the - * matrix of an input relation which must have the convenient number of rows. - * All columns of the input matrix are copied. WARNING: this function does not - * update the relation attributes of the modified matrix. - * \param[in,out] relation The relation to add columns in. - * \param[in] insert The relation containing the columns to add. - * \param[in] column The column where to insert the new columns. - */ -void osl_relation_insert_columns(osl_relation_p relation, - osl_relation_p insert, int column) { - int i, j; - osl_relation_p temp; - - if ((relation == NULL) || (insert == NULL)) - return; - - if ((relation->precision != insert->precision) || - (relation->nb_rows != insert->nb_rows) || - (column < 0) || (column > relation->nb_columns)) - OSL_error("columns cannot be inserted"); - - // We use a temporary relation just to reuse existing functions. Cleaner. - temp = osl_relation_pmalloc(relation->precision, relation->nb_rows, - relation->nb_columns + insert->nb_columns); - - for (i = 0; i < relation->nb_rows; i++) { - for (j = 0; j < column; j++) - osl_int_assign(relation->precision, temp->m[i], j, relation->m[i], j); - - for (j = column; j < column + insert->nb_columns; j++) - osl_int_assign(relation->precision, - temp->m[i], j, insert->m[i], j - column); - - for (j = column + insert->nb_columns; - j < insert->nb_columns + relation->nb_columns; j++) - osl_int_assign(relation->precision, - temp->m[i], j, relation->m[i], j - insert->nb_columns); - } - - osl_relation_free_inside(relation); - - // Replace the inside of relation. - relation->nb_columns = temp->nb_columns; - relation->m = temp->m; - - // Free the temp "shell". - free(temp); -} - - -/** - * osl_relation_concat_constraints function: - * this function builds a new relation from two relations sent as - * parameters. The new set of constraints is built as the concatenation - * of the rows of the first elements of the two relation unions r1 and r2. - * This means, there is no next field in the result. - * \param[in] r1 The first relation. - * \param[in] r2 The second relation. - * \return A pointer to the relation resulting from the concatenation of - * the first elements of r1 and r2. - */ -osl_relation_p osl_relation_concat_constraints( - osl_relation_p r1, - osl_relation_p r2) { - osl_relation_p new; - - if (r1 == NULL) - return osl_relation_clone(r2); - - if (r2 == NULL) - return osl_relation_clone(r1); - - if (r1->nb_columns != r2->nb_columns) - OSL_error("incompatible sizes for concatenation"); - - if (r1->next || r2->next) - OSL_warning("relation concatenation is done on the first elements " - "of union only"); - - new = osl_relation_pmalloc(r1->precision, - r1->nb_rows + r2->nb_rows, r1->nb_columns); - osl_relation_replace_constraints(new, r1, 0); - osl_relation_replace_constraints(new, r2, r1->nb_rows); - - return new; -} - - -/** - * osl_relation_equal function: - * this function returns true if the two relations provided as parameters - * are the same, false otherwise. - * \param[in] r1 The first relation. - * \param[in] r2 The second relation. - * \return 1 if r1 and r2 are the same (content-wise), 0 otherwise. - */ -int osl_relation_equal(osl_relation_p r1, osl_relation_p r2) { - int i, j; - - while ((r1 != NULL) && (r2 != NULL)) { - if (r1 == r2) - return 1; - - if ((r1->type != r2->type) || - (r1->precision != r2->precision) || - (r1->nb_rows != r2->nb_rows) || - (r1->nb_columns != r2->nb_columns) || - (r1->nb_output_dims != r2->nb_output_dims) || - (r1->nb_input_dims != r2->nb_input_dims) || - (r1->nb_local_dims != r2->nb_local_dims) || - (r1->nb_parameters != r2->nb_parameters)) - return 0; - - for (i = 0; i < r1->nb_rows; ++i) - for (j = 0; j < r1->nb_columns; ++j) - if (osl_int_ne(r1->precision, r1->m[i], j, r2->m[i], j)) - return 0; - - r1 = r1->next; - r2 = r2->next; - } - - if (((r1 == NULL) && (r2 != NULL)) || ((r1 != NULL) && (r2 == NULL))) - return 0; - - return 1; -} - - -/** - * osl_relation_check_attribute internal function: - * This function checks whether an "actual" value is the same as an - * "expected" value or not. If the expected value is set to - * OSL_UNDEFINED, this function sets it to the "actual" value - * and do not report a difference has been detected. - * It returns 0 if a difference has been detected, 1 otherwise. - * \param[in,out] expected Pointer to the expected value (the value is - * modified if it was set to OSL_UNDEFINED). - * \param[in] actual Value we want to check. - * \return 0 if the values are not the same while the expected value was - * not OSL_UNDEFINED, 1 otherwise. - */ -static -int osl_relation_check_attribute(int * expected, int actual) { - if (*expected != OSL_UNDEFINED) { - if ((actual != OSL_UNDEFINED) && - (actual != *expected)) { - OSL_warning("unexpected atribute"); - return 0; - } - } - else { - *expected = actual; - } - - return 1; -} - - -/** - * osl_relation_check_nb_columns internal function: - * This function checks that the number of columns of a relation - * corresponds to some expected properties (setting an expected property to - * OSL_UNDEFINED makes this function unable to detect a problem). - * It returns 0 if the number of columns seems incorrect or 1 if no problem - * has been detected. - * \param[in] relation The relation we want to check the number of columns. - * \param[in] expected_nb_output_dims Expected number of output dimensions. - * \param[in] expected_nb_input_dims Expected number of input dimensions. - * \param[in] expected_nb_parameters Expected number of parameters. - * \return 0 if the number of columns seems incorrect, 1 otherwise. - */ -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) { - int expected_nb_local_dims, expected_nb_columns; - - if ((expected_nb_output_dims != OSL_UNDEFINED) && - (expected_nb_input_dims != OSL_UNDEFINED) && - (expected_nb_parameters != OSL_UNDEFINED)) { - - if (relation->nb_local_dims == OSL_UNDEFINED) - expected_nb_local_dims = 0; - else - expected_nb_local_dims = relation->nb_local_dims; - - expected_nb_columns = expected_nb_output_dims + - expected_nb_input_dims + - expected_nb_local_dims + - expected_nb_parameters + - 2; - - if (expected_nb_columns != relation->nb_columns) { - OSL_warning("unexpected number of columns"); - return 0; - } - } - - return 1; -} - - -/** - * osl_relation_integrity_check function: - * this function checks that a relation is "well formed" according to some - * expected properties (setting an expected value to OSL_UNDEFINED means - * that we do not expect a specific value) and what the relation is supposed - * to represent. It returns 0 if the check failed or 1 if no problem has been - * detected. - * \param[in] relation The relation we want to check. - * \param[in] expected_type Semantics about this relation (domain, access...). - * \param[in] expected_nb_output_dims Expected number of output dimensions. - * \param[in] expected_nb_input_dims Expected number of input dimensions. - * \param[in] expected_nb_parameters Expected number of parameters. - * \return 0 if the integrity check fails, 1 otherwise. - */ -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) { - int i; - - // Check the NULL case. - if (relation == NULL) { - if ((expected_nb_output_dims != OSL_UNDEFINED) || - (expected_nb_input_dims != OSL_UNDEFINED) || - (expected_nb_parameters != OSL_UNDEFINED)) { - OSL_debug("NULL relation with some expected attibutes"); - //return 0; - } - - return 1; - } - - // Check the type. - if (((expected_type != OSL_TYPE_ACCESS) && - (expected_type != relation->type)) || - ((expected_type == OSL_TYPE_ACCESS) && - (!osl_relation_is_access(relation)))) { - OSL_warning("wrong type"); - osl_relation_dump(stderr, relation); - return 0; - } - - // Check that relations have no undefined atributes. - if ((relation->nb_output_dims == OSL_UNDEFINED) || - (relation->nb_input_dims == OSL_UNDEFINED) || - (relation->nb_local_dims == OSL_UNDEFINED) || - (relation->nb_parameters == OSL_UNDEFINED)) { - OSL_warning("all attributes should be defined"); - osl_relation_dump(stderr, relation); - return 0; - } - - // Check that a context has actually 0 output dimensions. - if ((relation->type == OSL_TYPE_CONTEXT) && - (relation->nb_output_dims != 0)) { - OSL_warning("context without 0 as number of output dimensions"); - osl_relation_dump(stderr, relation); - return 0; - } - - // Check that a domain or a context has actually 0 input dimensions. - if (((relation->type == OSL_TYPE_DOMAIN) || - (relation->type == OSL_TYPE_CONTEXT)) && - (relation->nb_input_dims != 0)) { - OSL_warning("domain or context without 0 input dimensions"); - osl_relation_dump(stderr, relation); - return 0; - } - - // Check properties according to expected values (and if expected values - // are undefined, define them with the first relation part properties). - if (!osl_relation_check_attribute(&expected_nb_output_dims, - relation->nb_output_dims) || - !osl_relation_check_attribute(&expected_nb_input_dims, - relation->nb_input_dims) || - !osl_relation_check_attribute(&expected_nb_parameters, - relation->nb_parameters)) { - osl_relation_dump(stderr, relation); - return 0; - } - - while (relation != NULL) { - - // Attributes (except the number of local dimensions) should be the same - // in all parts of the union. - if ((expected_nb_output_dims != relation->nb_output_dims) || - (expected_nb_input_dims != relation->nb_input_dims) || - (expected_nb_parameters != relation->nb_parameters)) { - OSL_warning("inconsistent attributes"); - osl_relation_dump(stderr, relation); - return 0; - } - - // Check whether the number of columns is OK or not. - if (!osl_relation_check_nb_columns(relation, - expected_nb_output_dims, - expected_nb_input_dims, - expected_nb_parameters)) { - osl_relation_dump(stderr, relation); - return 0; - } - - // Check the first column. The first column of a relation part should be - // made of 0 or 1 only. - if ((relation->nb_rows > 0) && (relation->nb_columns > 0)) { - for (i = 0; i < relation->nb_rows; i++) { - if (!osl_int_zero(relation->precision, relation->m[i], 0) && - !osl_int_one(relation->precision, relation->m[i], 0)) { - OSL_warning("first column of a relation is not " - "strictly made of 0 or 1"); - osl_relation_dump(stderr, relation); - return 0; - } - } - } - - // Array accesses must provide the array identifier. - if ((osl_relation_is_access(relation)) && - (osl_relation_get_array_id(relation) == OSL_UNDEFINED)) { - osl_relation_dump(stderr, relation); - return 0; - } - - relation = relation->next; - } - - return 1; -} - - -/** - * osl_relation_union function: - * this function builds a new relation from two relations provided - * as parameters. The new relation is built as an union of the - * two relations: the list of constraint sets are linked together. - * \param[in] r1 The first relation. - * \param[in] r2 The second relation. - * \return A new relation corresponding to the union of r1 and r2. - */ -osl_relation_p osl_relation_union(osl_relation_p r1, - osl_relation_p r2) { - osl_relation_p copy1, copy2, tmp; - - if ((r1 == NULL) && (r2 == NULL)) - return NULL; - - copy1 = osl_relation_clone(r1); - copy2 = osl_relation_clone(r2); - - if ((r1 != NULL) && (r2 == NULL)) - return copy1; - - if ((r1 == NULL) && (r2 != NULL)) - return copy2; - - tmp = copy1; - while (tmp->next != NULL) - tmp = tmp->next; - - tmp->next = copy2; - return copy1; -} - - -/** - * osl_relation_set_attributes function: - * this functions sets the attributes of a relation provided as a - * parameter. It updates the relation directly. - * \param[in,out] relation The relation to set the attributes. - * \param[in] nb_output_dims Number of output dimensions. - * \param[in] nb_input_dims Number of input dimensions. - * \param[in] nb_local_dims Number of local dimensions. - * \param[in] nb_parameters Number of parameters. - */ -void osl_relation_set_attributes(osl_relation_p relation, - int nb_output_dims, int nb_input_dims, - int nb_local_dims, int nb_parameters) { - if (relation != NULL) { - relation->nb_output_dims = nb_output_dims; - relation->nb_input_dims = nb_input_dims; - relation->nb_local_dims = nb_local_dims; - relation->nb_parameters = nb_parameters; - } -} - - -/** - * osl_relation_set_type function: - * this function sets the type of each relation union part in the relation - * to the one provided as parameter. - * \param relation The relation to set the type. - * \param type The type. - */ -void osl_relation_set_type(osl_relation_p relation, int type) { - - while (relation != NULL) { - relation->type = type; - relation = relation->next; - } -} - - -/** - * osl_relation_get_array_id function: - * this function returns the array identifier in a relation with access type - * It returns OSL_UNDEFINED if it is not able to find it (in particular - * if there are irregularities in the relation). - * \param[in] relation The relation where to find an array identifier. - * \return The array identifier in the relation or OSL_UNDEFINED. - */ -int osl_relation_get_array_id(osl_relation_p relation) { - int i; - int first = 1; - int array_id = OSL_UNDEFINED; - int reference_array_id = OSL_UNDEFINED; - int nb_array_id; - int row_id = 0; - int precision; - - if (relation == NULL) - return OSL_UNDEFINED; - - if (!osl_relation_is_access(relation)) { - OSL_warning("asked for an array id of non-array relation"); - return OSL_UNDEFINED; - } - - while (relation != NULL) { - precision = relation->precision; - - // There should be room to store the array identifier. - if ((relation->nb_rows < 1) || - (relation->nb_columns < 3)) { - OSL_warning("no array identifier in an access function"); - return OSL_UNDEFINED; - } - - // Array identifiers are m[i][#columns -1] / m[i][1], with i the only row - // where m[i][1] is not 0. - // - check there is exactly one row such that m[i][1] is not 0, - // - check the whole ith row if full of 0 except m[i][1] and the id, - // - check that (m[i][#columns -1] % m[i][1]) == 0, - // - check that (-m[i][#columns -1] / m[i][1]) > 0. - nb_array_id = 0; - for (i = 0; i < relation->nb_rows; i++) { - if (!osl_int_zero(precision, relation->m[i], 1)) { - nb_array_id ++; - row_id = i; - } - } - if (nb_array_id == 0) { - OSL_warning("no array identifier in an access function"); - return OSL_UNDEFINED; - } - if (nb_array_id > 1) { - OSL_warning("several array identifiers in one access function"); - return OSL_UNDEFINED; - } - for (i = 0; i < relation->nb_columns - 1; i++) { - if ((i != 1) && !osl_int_zero(precision, relation->m[row_id], i)) { - OSL_warning("non integer array identifier"); - return OSL_UNDEFINED; - } - } - if (!osl_int_divisible(precision, - relation->m[row_id], relation->nb_columns - 1, - relation->m[row_id], 1)) { - OSL_warning("rational array identifier"); - return OSL_UNDEFINED; - } - array_id = -osl_int_get_si(precision, - relation->m[row_id], - relation->nb_columns - 1); - array_id /= osl_int_get_si(precision, relation->m[row_id], 1); - if (array_id <= 0) { - OSL_warning("negative or 0 identifier in access function"); - return OSL_UNDEFINED; - } - - // Unions of accesses are allowed, but they should refer at the same array. - if (first) { - reference_array_id = array_id; - first = 0; - } - else { - if (reference_array_id != array_id) { - OSL_warning("inconsistency of array identifiers in an " - "union of access relations"); - return OSL_UNDEFINED; - } - } - - relation = relation->next; - } - - return array_id; -} - - -/** - * osl_relation_is_access function: - * this function returns 1 if the relation corresponds to an access relation, - * whatever its precise type (read, write etc.), 0 otherwise. - * \param relation The relation to check wheter it is an access relation or not. - * \return 1 if the relation is an access relation, 0 otherwise. - */ -int osl_relation_is_access(osl_relation_p relation) { - - if (relation == NULL) - return 0; - - if ((relation->type == OSL_TYPE_ACCESS) || - (relation->type == OSL_TYPE_READ) || - (relation->type == OSL_TYPE_WRITE) || - (relation->type == OSL_TYPE_MAY_WRITE)) - return 1; - - return 0; -} - - -/** - * osl_relation_get_attributes function: - * this function returns, through its parameters, the maximum values of the - * relation attributes (nb_iterators, nb_parameters etc), depending on its - * type. HOWEVER, it updates the parameter value iff the attribute is greater - * than the input parameter value. Hence it may be used to get the - * attributes as well as to find the maximum attributes for several relations. - * The array identifier 0 is used when there is no array identifier (AND this - * is OK), OSL_UNDEFINED is used to report it is impossible to provide the - * property while it should. This function is not intended for checking, the - * input relation should be correct. - * \param[in] relation The relation to extract attribute values. - * \param[in,out] nb_parameters Number of parameter attribute. - * \param[in,out] nb_iterators Number of iterators attribute. - * \param[in,out] nb_scattdims Number of scattering dimensions attribute. - * \param[in,out] nb_localdims Number of local dimensions attribute. - * \param[in,out] array_id Maximum array identifier attribute. - */ -void osl_relation_get_attributes(osl_relation_p relation, - int * nb_parameters, - int * nb_iterators, - int * nb_scattdims, - int * nb_localdims, - int * array_id) { - int type; - int local_nb_parameters = OSL_UNDEFINED; - int local_nb_iterators = OSL_UNDEFINED; - int local_nb_scattdims = OSL_UNDEFINED; - int local_nb_localdims = OSL_UNDEFINED; - int local_array_id = OSL_UNDEFINED; - - while (relation != NULL) { - if (osl_relation_is_access(relation)) - type = OSL_TYPE_ACCESS; - else - type = relation->type; - - // There is some redundancy but I believe the code is cleaner this way. - switch (type) { - case OSL_TYPE_CONTEXT: - local_nb_parameters = relation->nb_parameters; - local_nb_iterators = 0; - local_nb_scattdims = 0; - local_nb_localdims = relation->nb_local_dims; - local_array_id = 0; - break; - - case OSL_TYPE_DOMAIN: - local_nb_parameters = relation->nb_parameters; - local_nb_iterators = relation->nb_output_dims; - local_nb_scattdims = 0; - local_nb_localdims = relation->nb_local_dims; - local_array_id = 0; - break; - - case OSL_TYPE_SCATTERING: - local_nb_parameters = relation->nb_parameters; - local_nb_iterators = relation->nb_input_dims; - local_nb_scattdims = relation->nb_output_dims; - local_nb_localdims = relation->nb_local_dims; - local_array_id = 0; - break; - - case OSL_TYPE_ACCESS: - local_nb_parameters = relation->nb_parameters; - local_nb_iterators = relation->nb_input_dims; - local_nb_scattdims = 0; - local_nb_localdims = relation->nb_local_dims; - local_array_id = osl_relation_get_array_id(relation); - break; - } - - // Update. - *nb_parameters = OSL_max(*nb_parameters, local_nb_parameters); - *nb_iterators = OSL_max(*nb_iterators, local_nb_iterators); - *nb_scattdims = OSL_max(*nb_scattdims, local_nb_scattdims); - *nb_localdims = OSL_max(*nb_localdims, local_nb_localdims); - *array_id = OSL_max(*array_id, local_array_id); - relation = relation->next; - } -} - - -/** - * osl_relation_extend_output function: - * this function extends the number of output dimensions of a given relation. It - * returns a copy of the input relation with a number of output dimensions - * extended to "dim" for all its union components. The new output dimensions - * are simply set equal to 0. The extended number of dimensions must be higher - * than or equal to the original one (an error will be raised otherwise). - * \param[in] relation The input relation to extend. - * \param[in] dim The number of output dimension to reach. - * \return A new relation: "relation" extended to "dim" output dims. - */ -osl_relation_p osl_relation_extend_output(osl_relation_p relation, int dim) { - int i, j; - int first = 1; - int offset; - osl_relation_p extended = NULL, node, previous = NULL; - - while (relation != NULL) { - if (relation->nb_output_dims > dim) - OSL_error("Number of output dims is greater than required extension"); - offset = dim - relation->nb_output_dims; - - node = osl_relation_pmalloc(relation->precision, - relation->nb_rows + offset, - relation->nb_columns + offset); - - node->type = relation->type; - node->nb_output_dims = OSL_max(relation->nb_output_dims, dim); - node->nb_input_dims = relation->nb_input_dims; - node->nb_local_dims = relation->nb_local_dims; - node->nb_parameters = relation->nb_parameters; - - // Copy of the original relation with some 0 columns for the new dimensions - // Note that we use the fact that the matrix is initialized with zeros. - for (i = 0; i < relation->nb_rows; i++) { - for (j = 0; j <= relation->nb_output_dims; j++) - osl_int_assign(relation->precision, node->m[i], j, relation->m[i], j); - - for (j = relation->nb_output_dims + offset + 1; - j < relation->nb_columns + offset; j++) - osl_int_assign(relation->precision, - node->m[i], j, relation->m[i], j - offset); - } - - // New rows dedicated to the new dimensions - for (i = relation->nb_rows; i < relation->nb_rows + offset; i++) { - for (j = 0; j < relation->nb_columns + offset; j++) { - if ((i - relation->nb_rows) == (j - relation->nb_output_dims - 1)) - osl_int_set_si(relation->precision, node->m[i], j, -1); - } - } - - if (first) { - first = 0; - extended = node; - previous = node; - } - else { - previous->next = node; - previous = previous->next; - } - - relation = relation->next; - } - - return extended; -} - |