OpenScop
0.9.0
|
00001 00002 /*+-----------------------------------------------------------------** 00003 ** OpenScop Library ** 00004 **-----------------------------------------------------------------** 00005 ** relation.c ** 00006 **-----------------------------------------------------------------** 00007 ** First version: 30/04/2008 ** 00008 **-----------------------------------------------------------------** 00009 00010 00011 ***************************************************************************** 00012 * OpenScop: Structures and formats for polyhedral tools to talk together * 00013 ***************************************************************************** 00014 * ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__, * 00015 * / / / // // // // / / / // // / / // / /|,_, * 00016 * / / / // // // // / / / // // / / // / / / /\ * 00017 * |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/ \ * 00018 * | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\ \ /\ * 00019 * | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\ * 00020 * | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \ \ * 00021 * | P |n| l | = | s | t |=| = |d| = | = | = | | |=| o | | \# \ \ * 00022 * | H | | y | | e | o | | = |l| | | = | | | | G | | \ \ \ * 00023 * | I | | | | e | | | | | | | | | | | | | \ \ \ * 00024 * | T | | | | | | | | | | | | | | | | | \ \ \ * 00025 * | E | | | | | | | | | | | | | | | | | \ \ \ * 00026 * | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | / \* \ \ * 00027 * | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/ \ \ / * 00028 * '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' * 00029 * * 00030 * Copyright (C) 2008 University Paris-Sud 11 and INRIA * 00031 * * 00032 * (3-clause BSD license) * 00033 * Redistribution and use in source and binary forms, with or without * 00034 * modification, are permitted provided that the following conditions * 00035 * are met: * 00036 * * 00037 * 1. Redistributions of source code must retain the above copyright notice, * 00038 * this list of conditions and the following disclaimer. * 00039 * 2. Redistributions in binary form must reproduce the above copyright * 00040 * notice, this list of conditions and the following disclaimer in the * 00041 * documentation and/or other materials provided with the distribution. * 00042 * 3. The name of the author may not be used to endorse or promote products * 00043 * derived from this software without specific prior written permission. * 00044 * * 00045 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * 00046 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * 00047 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * 00048 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * 00049 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * 00050 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * 00051 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * 00052 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 00053 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * 00054 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 00055 * * 00056 * OpenScop Library, a library to manipulate OpenScop formats and data * 00057 * structures. Written by: * 00058 * Cedric Bastoul <Cedric.Bastoul@u-psud.fr> and * 00059 * Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr> * 00060 * * 00061 *****************************************************************************/ 00062 00063 00064 #include <stdlib.h> 00065 #include <stdio.h> 00066 #include <string.h> 00067 #include <ctype.h> 00068 00069 #include <osl/macros.h> 00070 #include <osl/int.h> 00071 #include <osl/util.h> 00072 #include <osl/vector.h> 00073 #include <osl/strings.h> 00074 #include <osl/names.h> 00075 #include <osl/relation.h> 00076 00077 00078 /*+*************************************************************************** 00079 * Structure display function * 00080 *****************************************************************************/ 00081 00082 00090 static 00091 char * osl_relation_sprint_type(osl_relation_p relation) { 00092 char * string = NULL; 00093 00094 OSL_malloc(string, char *, OSL_MAX_STRING * sizeof(char)); 00095 string[0] = '\0'; 00096 00097 if (relation != NULL) { 00098 switch (relation->type) { 00099 case OSL_UNDEFINED: { 00100 snprintf(string, OSL_MAX_STRING, OSL_STRING_UNDEFINED); 00101 break; 00102 } 00103 case OSL_TYPE_CONTEXT: { 00104 snprintf(string, OSL_MAX_STRING, OSL_STRING_CONTEXT); 00105 break; 00106 } 00107 case OSL_TYPE_DOMAIN: { 00108 snprintf(string, OSL_MAX_STRING, OSL_STRING_DOMAIN); 00109 break; 00110 } 00111 case OSL_TYPE_SCATTERING: { 00112 snprintf(string, OSL_MAX_STRING, OSL_STRING_SCATTERING); 00113 break; 00114 } 00115 case OSL_TYPE_READ: { 00116 snprintf(string, OSL_MAX_STRING, OSL_STRING_READ); 00117 break; 00118 } 00119 case OSL_TYPE_WRITE: { 00120 snprintf(string, OSL_MAX_STRING, OSL_STRING_WRITE); 00121 break; 00122 } 00123 case OSL_TYPE_MAY_WRITE: { 00124 snprintf(string, OSL_MAX_STRING, OSL_STRING_MAY_WRITE); 00125 break; 00126 } 00127 default: { 00128 OSL_warning("unknown relation type, " 00129 "replaced with "OSL_STRING_UNDEFINED); 00130 snprintf(string, OSL_MAX_STRING, OSL_STRING_UNDEFINED); 00131 } 00132 } 00133 } 00134 00135 return string; 00136 } 00137 00138 00146 static 00147 void osl_relation_print_type(FILE * file, osl_relation_p relation) { 00148 char * string = osl_relation_sprint_type(relation); 00149 fprintf(file, "%s", string); 00150 free(string); 00151 } 00152 00153 00164 void osl_relation_idump(FILE * file, osl_relation_p relation, int level) { 00165 int i, j, first = 1; 00166 00167 // Go to the right level. 00168 for (j = 0; j < level; j++) 00169 fprintf(file, "|\t"); 00170 00171 if (relation != NULL) { 00172 fprintf(file, "+-- osl_relation_t ("); 00173 osl_relation_print_type(file, relation); 00174 fprintf(file, ", "); 00175 osl_int_dump_precision(file, relation->precision); 00176 fprintf(file, ")\n"); 00177 } 00178 else { 00179 fprintf(file, "+-- NULL relation\n"); 00180 } 00181 00182 while (relation != NULL) { 00183 if (! first) { 00184 // Go to the right level. 00185 for (j = 0; j < level; j++) 00186 fprintf(file, "|\t"); 00187 fprintf(file, "| osl_relation_t ("); 00188 osl_relation_print_type(file, relation); 00189 fprintf(file, ", "); 00190 osl_int_dump_precision(file, relation->precision); 00191 fprintf(file, ")\n"); 00192 } 00193 else 00194 first = 0; 00195 00196 // A blank line 00197 for(j = 0; j <= level; j++) 00198 fprintf(file, "|\t"); 00199 fprintf(file, "%d %d %d %d %d %d\n", 00200 relation->nb_rows, relation->nb_columns, 00201 relation->nb_output_dims, relation->nb_input_dims, 00202 relation->nb_local_dims, relation->nb_parameters); 00203 00204 // Display the relation. 00205 for (i = 0; i < relation->nb_rows; i++) { 00206 for (j = 0; j <= level; j++) 00207 fprintf(file, "|\t"); 00208 00209 fprintf(file, "[ "); 00210 00211 for (j = 0; j < relation->nb_columns; j++) { 00212 osl_int_print(file, relation->precision, relation->m[i][j]); 00213 fprintf(file, " "); 00214 } 00215 00216 fprintf(file, "]\n"); 00217 } 00218 00219 relation = relation->next; 00220 00221 // Next line. 00222 if (relation != NULL) { 00223 for (j = 0; j <= level; j++) 00224 fprintf(file, "|\t"); 00225 fprintf(file, "|\n"); 00226 for (j = 0; j <= level; j++) 00227 fprintf(file, "|\t"); 00228 fprintf(file, "V\n"); 00229 } 00230 } 00231 00232 // The last line. 00233 for (j = 0; j <= level; j++) 00234 fprintf(file, "|\t"); 00235 fprintf(file, "\n"); 00236 } 00237 00238 00246 void osl_relation_dump(FILE * file, osl_relation_p relation) { 00247 osl_relation_idump(file, relation, 0); 00248 } 00249 00250 00265 static 00266 char * osl_relation_expression_element(osl_int_t val, 00267 int precision, int * first, 00268 int cst, char * name) { 00269 char * temp, * body, * sval; 00270 00271 OSL_malloc(temp, char *, OSL_MAX_STRING * sizeof(char)); 00272 OSL_malloc(body, char *, OSL_MAX_STRING * sizeof(char)); 00273 OSL_malloc(sval, char *, OSL_MAX_STRING * sizeof(char)); 00274 00275 body[0] = '\0'; 00276 sval[0] = '\0'; 00277 00278 // statements for the 'normal' processing. 00279 if (!osl_int_zero(precision, val) && (!cst)) { 00280 if ((*first) || osl_int_neg(precision, val)) { 00281 if (osl_int_one(precision, val)) { // case 1 00282 sprintf(sval, "%s", name); 00283 } 00284 else { 00285 if (osl_int_mone(precision, val)) { // case -1 00286 sprintf(sval, "-%s", name); 00287 } 00288 else { // default case 00289 osl_int_sprint_txt(sval, precision, val); 00290 sprintf(temp, "*%s", name); 00291 strcat(sval, temp); 00292 } 00293 } 00294 *first = 0; 00295 } 00296 else { 00297 if (osl_int_one(precision, val)) { 00298 sprintf(sval, "+%s", name); 00299 } 00300 else { 00301 sprintf(sval, "+"); 00302 osl_int_sprint_txt(temp, precision, val); 00303 strcat(sval, temp); 00304 sprintf(temp, "*%s", name); 00305 strcat(sval, temp); 00306 } 00307 } 00308 } 00309 else { 00310 if (cst) { 00311 if ((osl_int_zero(precision, val) && (*first)) || 00312 (osl_int_neg(precision, val))) 00313 osl_int_sprint_txt(sval, precision, val); 00314 if (osl_int_pos(precision, val)) { 00315 if (!(*first)) { 00316 sprintf(sval, "+"); 00317 osl_int_sprint_txt(temp, precision, val); 00318 strcat(sval, temp); 00319 } 00320 else { 00321 osl_int_sprint_txt(sval, precision, val); 00322 } 00323 } 00324 } 00325 } 00326 free(temp); 00327 free(body); 00328 00329 return(sval); 00330 } 00331 00332 00342 static 00343 char ** osl_relation_strings(osl_relation_p relation, osl_names_p names) { 00344 char ** strings; 00345 char temp[OSL_MAX_STRING]; 00346 int i, offset; 00347 00348 if ((relation == NULL) || (names == NULL)) { 00349 OSL_debug("no names or relation to build the name array"); 00350 return NULL; 00351 } 00352 00353 OSL_malloc(strings, char **, (relation->nb_columns + 1)*sizeof(char *)); 00354 strings[relation->nb_columns] = NULL; 00355 00356 // 1. Equality/inequality marker. 00357 OSL_strdup(strings[0], "e/i"); 00358 offset = 1; 00359 00360 // 2. Output dimensions. 00361 if (osl_relation_is_access(relation)) { 00362 // The first output dimension is the array name. 00363 OSL_strdup(strings[offset], "Arr"); 00364 // The other ones are the array dimensions [1]...[n] 00365 for (i = offset + 1; i < relation->nb_output_dims + offset; i++) { 00366 sprintf(temp, "[%d]", i - 1); 00367 OSL_strdup(strings[i], temp); 00368 } 00369 } 00370 else 00371 if ((relation->type == OSL_TYPE_DOMAIN) || 00372 (relation->type == OSL_TYPE_CONTEXT)) { 00373 for (i = offset; i < relation->nb_output_dims + offset; i++) { 00374 OSL_strdup(strings[i], names->iterators->string[i - offset]); 00375 } 00376 } 00377 else { 00378 for (i = offset; i < relation->nb_output_dims + offset; i++) { 00379 OSL_strdup(strings[i], names->scatt_dims->string[i - offset]); 00380 } 00381 } 00382 offset += relation->nb_output_dims; 00383 00384 // 3. Input dimensions. 00385 for (i = offset; i < relation->nb_input_dims + offset; i++) 00386 OSL_strdup(strings[i], names->iterators->string[i - offset]); 00387 offset += relation->nb_input_dims; 00388 00389 // 4. Local dimensions. 00390 for (i = offset; i < relation->nb_local_dims + offset; i++) 00391 OSL_strdup(strings[i], names->local_dims->string[i - offset]); 00392 offset += relation->nb_local_dims; 00393 00394 // 5. Parameters. 00395 for (i = offset; i < relation->nb_parameters + offset; i++) 00396 OSL_strdup(strings[i], names->parameters->string[i - offset]); 00397 offset += relation->nb_parameters; 00398 00399 // 6. Scalar. 00400 OSL_strdup(strings[offset], "1"); 00401 00402 return strings; 00403 } 00404 00405 00419 static 00420 char * osl_relation_subexpression(osl_relation_p relation, 00421 int row, int start, int stop, int oppose, 00422 char ** strings) { 00423 int i, first = 1, constant; 00424 char * sval; 00425 char * sline; 00426 00427 OSL_malloc(sline, char *, OSL_MAX_STRING * sizeof(char)); 00428 sline[0] = '\0'; 00429 00430 // Create the expression. The constant is a special case. 00431 for (i = start; i <= stop; i++) { 00432 if (oppose) { 00433 osl_int_oppose(relation->precision, 00434 &relation->m[row][i], relation->m[row][i]); 00435 } 00436 00437 if (i == relation->nb_columns - 1) 00438 constant = 1; 00439 else 00440 constant = 0; 00441 00442 sval = osl_relation_expression_element(relation->m[row][i], 00443 relation->precision, &first, constant, strings[i]); 00444 00445 if (oppose) { 00446 osl_int_oppose(relation->precision, 00447 &relation->m[row][i], relation->m[row][i]); 00448 } 00449 strcat(sline, sval); 00450 free(sval); 00451 } 00452 00453 return sline; 00454 } 00455 00456 00466 char * osl_relation_expression(osl_relation_p relation, 00467 int row, char ** strings) { 00468 00469 return osl_relation_subexpression(relation, row, 00470 1, relation->nb_columns - 1, 0, 00471 strings); 00472 } 00473 00474 00486 static 00487 int osl_relation_is_simple_output(osl_relation_p relation, int row) { 00488 int i; 00489 int first = 1; 00490 int sign = 0; 00491 00492 if ((relation == NULL) || 00493 (relation->m == NULL) || 00494 (relation->nb_output_dims == 0)) 00495 return 0; 00496 00497 if ((row < 0) || (row > relation->nb_rows)) 00498 OSL_error("the specified row does not exist in the relation"); 00499 00500 // The constraint must be an equality. 00501 if (!osl_int_zero(relation->precision, relation->m[row][0])) 00502 return 0; 00503 00504 // Check the output part has one and only one non-zero +1 or -1 coefficient. 00505 first = 1; 00506 for (i = 1; i <= relation->nb_output_dims; i++) { 00507 if (!osl_int_zero(relation->precision, relation->m[row][i])) { 00508 if (first) 00509 first = 0; 00510 else 00511 return 0; 00512 00513 if (osl_int_one(relation->precision, relation->m[row][i])) 00514 sign = 1; 00515 else if (osl_int_mone(relation->precision, relation->m[row][i])) 00516 sign = -1; 00517 else 00518 return 0; 00519 } 00520 } 00521 00522 return sign; 00523 } 00524 00525 00539 static 00540 char * osl_relation_sprint_comment(osl_relation_p relation, int row, 00541 char ** strings, char ** arrays) { 00542 int sign; 00543 int high_water_mark = OSL_MAX_STRING; 00544 char * string = NULL; 00545 char * expression; 00546 char buffer[OSL_MAX_STRING]; 00547 00548 OSL_malloc(string, char *, high_water_mark * sizeof(char)); 00549 string[0] = '\0'; 00550 00551 if ((relation == NULL) || (strings == NULL)) { 00552 OSL_debug("no relation or names while asked to print a comment"); 00553 return string; 00554 } 00555 00556 if ((sign = osl_relation_is_simple_output(relation, row))) { 00557 // First case : output == expression. 00558 00559 expression = osl_relation_subexpression(relation, row, 00560 1, relation->nb_output_dims, 00561 sign < 0, 00562 strings); 00563 snprintf(buffer, OSL_MAX_STRING, " ## %s", expression); 00564 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00565 free(expression); 00566 00567 // We don't print the right hand side if it's an array identifier. 00568 if (!osl_relation_is_access(relation) || 00569 osl_int_zero(relation->precision, relation->m[row][1])) { 00570 expression = osl_relation_subexpression(relation, row, 00571 relation->nb_output_dims + 1, 00572 relation->nb_columns - 1, 00573 sign > 0, 00574 strings); 00575 snprintf(buffer, OSL_MAX_STRING, " == %s", expression); 00576 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00577 free(expression); 00578 } 00579 else { 00580 snprintf(buffer, OSL_MAX_STRING, " == %s", 00581 arrays[osl_relation_get_array_id(relation) - 1]); 00582 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00583 } 00584 } 00585 else { 00586 // Second case : general case. 00587 00588 expression = osl_relation_expression(relation, row, strings); 00589 snprintf(buffer, OSL_MAX_STRING, " ## %s", expression); 00590 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00591 free(expression); 00592 00593 if (osl_int_zero(relation->precision, relation->m[row][0])) 00594 snprintf(buffer, OSL_MAX_STRING, " == 0"); 00595 else 00596 snprintf(buffer, OSL_MAX_STRING, " >= 0"); 00597 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00598 } 00599 00600 return string; 00601 } 00602 00603 00613 static 00614 char * osl_relation_column_string(osl_relation_p relation, char ** strings) { 00615 int i, j; 00616 int index_output_dims; 00617 int index_input_dims; 00618 int index_local_dims; 00619 int index_parameters; 00620 int index_scalar; 00621 int space, length, left, right; 00622 char * scolumn; 00623 char temp[OSL_MAX_STRING]; 00624 00625 OSL_malloc(scolumn, char *, OSL_MAX_STRING); 00626 00627 index_output_dims = 1; 00628 index_input_dims = index_output_dims + relation->nb_output_dims; 00629 index_local_dims = index_input_dims + relation->nb_input_dims; 00630 index_parameters = index_local_dims + relation->nb_local_dims; 00631 index_scalar = index_parameters + relation->nb_parameters; 00632 00633 // 1. The comment part. 00634 sprintf(scolumn, "#"); 00635 for (j = 0; j < (OSL_FMT_LENGTH - 1)/2 - 1; j++) 00636 strcat(scolumn, " "); 00637 00638 i = 0; 00639 while (strings[i] != NULL) { 00640 space = OSL_FMT_LENGTH; 00641 length = (space > (int)strlen(strings[i])) ? (int)strlen(strings[i]) : space; 00642 right = (space - length + (OSL_FMT_LENGTH % 2)) / 2; 00643 left = space - length - right; 00644 00645 // 2. Spaces before the name 00646 for (j = 0; j < left; j++) 00647 strcat(scolumn, " "); 00648 00649 // 3. The (abbreviated) name 00650 for (j = 0; j < length - 1; j++) { 00651 sprintf(temp, "%c", strings[i][j]); 00652 strcat(scolumn, temp); 00653 } 00654 if (length >= (int)strlen(strings[i])) 00655 sprintf(temp, "%c", strings[i][j]); 00656 else 00657 sprintf(temp, "."); 00658 strcat(scolumn, temp); 00659 00660 // 4. Spaces after the name 00661 for (j = 0; j < right; j++) 00662 strcat(scolumn, " "); 00663 00664 i++; 00665 if ((i == index_output_dims) || 00666 (i == index_input_dims) || 00667 (i == index_local_dims) || 00668 (i == index_parameters) || 00669 (i == index_scalar)) 00670 strcat(scolumn, "|"); 00671 else 00672 strcat(scolumn, " "); 00673 } 00674 strcat(scolumn, "\n"); 00675 00676 return scolumn; 00677 } 00678 00679 00689 static 00690 char * osl_relation_column_string_scoplib(osl_relation_p relation, 00691 char ** strings) { 00692 int i, j; 00693 int index_output_dims; 00694 int index_input_dims; 00695 int index_local_dims; 00696 int index_parameters; 00697 int index_scalar; 00698 int space, length, left, right; 00699 char * scolumn; 00700 char temp[OSL_MAX_STRING]; 00701 00702 OSL_malloc(scolumn, char *, OSL_MAX_STRING); 00703 00704 index_output_dims = 1; 00705 index_input_dims = index_output_dims + relation->nb_output_dims; 00706 index_local_dims = index_input_dims + relation->nb_input_dims; 00707 index_parameters = index_local_dims + relation->nb_local_dims; 00708 index_scalar = index_parameters + relation->nb_parameters; 00709 00710 // 1. The comment part. 00711 sprintf(scolumn, "#"); 00712 for (j = 0; j < (OSL_FMT_LENGTH - 1)/2 - 1; j++) 00713 strcat(scolumn, " "); 00714 00715 i = 0; 00716 while (strings[i] != NULL) { 00717 00718 if (i == 0 || 00719 (relation->type != OSL_TYPE_DOMAIN && i >= index_input_dims) || 00720 (relation->type == OSL_TYPE_DOMAIN && i <= index_output_dims) || 00721 i >= index_parameters) { 00722 space = OSL_FMT_LENGTH; 00723 length = (space > (int)strlen(strings[i])) ? (int)strlen(strings[i]) : space; 00724 right = (space - length + (OSL_FMT_LENGTH % 2)) / 2; 00725 left = space - length - right; 00726 00727 // 2. Spaces before the name 00728 for (j = 0; j < left; j++) 00729 strcat(scolumn, " "); 00730 00731 // 3. The (abbreviated) name 00732 for (j = 0; j < length - 1; j++) { 00733 sprintf(temp, "%c", strings[i][j]); 00734 strcat(scolumn, temp); 00735 } 00736 if (length >= (int)strlen(strings[i])) 00737 sprintf(temp, "%c", strings[i][j]); 00738 else 00739 sprintf(temp, "."); 00740 strcat(scolumn, temp); 00741 00742 // 4. Spaces after the name 00743 for (j = 0; j < right; j++) 00744 strcat(scolumn, " "); 00745 00746 if ((i == index_output_dims-1) || 00747 (i == index_input_dims-1) || 00748 (i == index_local_dims-1) || 00749 (i == index_parameters-1) || 00750 (i == index_scalar-1)) 00751 strcat(scolumn, "|"); 00752 else 00753 strcat(scolumn, " "); 00754 } 00755 00756 i++; 00757 } 00758 strcat(scolumn, "\n"); 00759 00760 return scolumn; 00761 } 00762 00763 00771 static 00772 osl_names_p osl_relation_names(osl_relation_p relation) { 00773 int nb_parameters = OSL_UNDEFINED; 00774 int nb_iterators = OSL_UNDEFINED; 00775 int nb_scattdims = OSL_UNDEFINED; 00776 int nb_localdims = OSL_UNDEFINED; 00777 int array_id = OSL_UNDEFINED; 00778 00779 osl_relation_get_attributes(relation, &nb_parameters, &nb_iterators, 00780 &nb_scattdims, &nb_localdims, &array_id); 00781 00782 return osl_names_generate("P", nb_parameters, 00783 "i", nb_iterators, 00784 "c", nb_scattdims, 00785 "l", nb_localdims, 00786 "A", array_id); 00787 } 00788 00789 00797 int osl_relation_nb_components(osl_relation_p relation) { 00798 int nb_components = 0; 00799 00800 while (relation != NULL) { 00801 nb_components++; 00802 relation = relation->next; 00803 } 00804 00805 return nb_components; 00806 } 00807 00808 00818 char * osl_relation_spprint_polylib(osl_relation_p relation, 00819 osl_names_p names) { 00820 int i, j; 00821 int part, nb_parts; 00822 int generated_names = 0; 00823 int high_water_mark = OSL_MAX_STRING; 00824 char * string = NULL; 00825 char buffer[OSL_MAX_STRING]; 00826 char ** name_array = NULL; 00827 char * scolumn; 00828 char * comment; 00829 00830 if (relation == NULL) 00831 return osl_util_strdup("# NULL relation\n"); 00832 00833 OSL_malloc(string, char *, high_water_mark * sizeof(char)); 00834 string[0] = '\0'; 00835 00836 // Generates the names for the comments if necessary. 00837 if (names == NULL) { 00838 generated_names = 1; 00839 names = osl_relation_names(relation); 00840 } 00841 00842 nb_parts = osl_relation_nb_components(relation); 00843 00844 if (nb_parts > 1) { 00845 snprintf(buffer, OSL_MAX_STRING, "# Union with %d parts\n%d\n", 00846 nb_parts, nb_parts); 00847 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00848 } 00849 00850 // Print each part of the union. 00851 for (part = 1; part <= nb_parts; part++) { 00852 // Prepare the array of strings for comments. 00853 name_array = osl_relation_strings(relation, names); 00854 00855 if (nb_parts > 1) { 00856 snprintf(buffer, OSL_MAX_STRING, "# Union part No.%d\n", part); 00857 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00858 } 00859 00860 snprintf(buffer, OSL_MAX_STRING, "%d %d %d %d %d %d\n", 00861 relation->nb_rows, relation->nb_columns, 00862 relation->nb_output_dims, relation->nb_input_dims, 00863 relation->nb_local_dims, relation->nb_parameters); 00864 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00865 00866 if (relation->nb_rows > 0) { 00867 scolumn = osl_relation_column_string(relation, name_array); 00868 snprintf(buffer, OSL_MAX_STRING, "%s", scolumn); 00869 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00870 free(scolumn); 00871 } 00872 00873 for (i = 0; i < relation->nb_rows; i++) { 00874 for (j = 0; j < relation->nb_columns; j++) { 00875 osl_int_sprint(buffer, relation->precision, relation->m[i][j]); 00876 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00877 snprintf(buffer, OSL_MAX_STRING, " "); 00878 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00879 } 00880 00881 if (name_array != NULL) { 00882 comment = osl_relation_sprint_comment(relation, i, name_array, 00883 names->arrays->string); 00884 osl_util_safe_strcat(&string, comment, &high_water_mark); 00885 free(comment); 00886 } 00887 snprintf(buffer, OSL_MAX_STRING, "\n"); 00888 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00889 } 00890 00891 // Free the array of strings. 00892 if (name_array != NULL) { 00893 for (i = 0; i < relation->nb_columns; i++) 00894 free(name_array[i]); 00895 free(name_array); 00896 } 00897 00898 relation = relation->next; 00899 } 00900 00901 if (generated_names) 00902 osl_names_free(names); 00903 00904 return string; 00905 } 00906 00907 00919 char * osl_relation_spprint_polylib_scoplib(osl_relation_p relation, 00920 osl_names_p names, 00921 int print_nth_part, 00922 int add_fakeiter) { 00923 int i, j; 00924 int part, nb_parts; 00925 int generated_names = 0; 00926 int is_access_array; 00927 int high_water_mark = OSL_MAX_STRING; 00928 int start_row; // for removing the first line in the access matrix 00929 int index_output_dims; 00930 int index_input_dims; 00931 int index_params; 00932 char * string = NULL; 00933 char buffer[OSL_MAX_STRING]; 00934 char ** name_array = NULL; 00935 char * scolumn; 00936 char * comment; 00937 00938 if (relation == NULL) 00939 return osl_util_strdup("# NULL relation\n"); 00940 00941 OSL_malloc(string, char *, high_water_mark * sizeof(char)); 00942 string[0] = '\0'; 00943 00944 // Generates the names for the comments if necessary. 00945 if (names == NULL) { 00946 generated_names = 1; 00947 names = osl_relation_names(relation); 00948 } 00949 00950 nb_parts = osl_relation_nb_components(relation); 00951 if (nb_parts > 1) { 00952 snprintf(buffer, OSL_MAX_STRING, "# Union with %d parts\n%d\n", 00953 nb_parts, nb_parts); 00954 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00955 } 00956 00957 is_access_array = (relation->type == OSL_TYPE_READ || 00958 relation->type == OSL_TYPE_WRITE ? 1 : 0); 00959 00960 // Print each part of the union. 00961 00962 for (part = 1; part <= nb_parts; part++) { 00963 00964 index_output_dims = 1; 00965 index_input_dims = index_output_dims + relation->nb_output_dims; 00966 index_params = index_input_dims + relation->nb_input_dims; 00967 00968 // Prepare the array of strings for comments. 00969 name_array = osl_relation_strings(relation, names); 00970 00971 if (nb_parts > 1) { 00972 snprintf(buffer, OSL_MAX_STRING, "# Union part No.%d\n", part); 00973 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00974 } 00975 00976 if (print_nth_part) { 00977 snprintf(buffer, OSL_MAX_STRING, "%d\n", part); 00978 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00979 } 00980 00981 // Don't print the array size for access array 00982 // (the total size is printed in osl_relation_list_pprint_access_array_scoplib) 00983 if (!is_access_array) { 00984 00985 // Print array size 00986 if (relation->type == OSL_TYPE_DOMAIN) { 00987 00988 if (add_fakeiter) { 00989 00990 snprintf(buffer, OSL_MAX_STRING, "%d %d\n", 00991 relation->nb_rows+1, relation->nb_columns - 00992 relation->nb_input_dims + 1); 00993 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00994 00995 // add the fakeiter line 00996 snprintf(buffer, OSL_MAX_STRING, " 0 "); 00997 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00998 snprintf(buffer, OSL_MAX_STRING, " 1 "); // fakeiter 00999 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01000 01001 for (i = 0 ; i < relation->nb_parameters ; i++) { 01002 snprintf(buffer, OSL_MAX_STRING, " 0 "); 01003 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01004 } 01005 01006 snprintf(buffer, OSL_MAX_STRING, " 0 ## fakeiter == 0\n"); 01007 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01008 01009 } else { 01010 snprintf(buffer, OSL_MAX_STRING, "%d %d\n", 01011 relation->nb_rows, relation->nb_columns - 01012 relation->nb_input_dims); 01013 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01014 } 01015 01016 } else { // SCATTERING 01017 01018 if (add_fakeiter) { 01019 snprintf(buffer, OSL_MAX_STRING, "%d %d\n", 01020 relation->nb_rows+2, relation->nb_columns - 01021 relation->nb_output_dims + 1); 01022 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01023 } else { 01024 snprintf(buffer, OSL_MAX_STRING, "%d %d\n", 01025 relation->nb_rows, relation->nb_columns - 01026 relation->nb_output_dims); 01027 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01028 } 01029 } 01030 01031 // Print column names in comment 01032 if (relation->nb_rows > 0) { 01033 scolumn = osl_relation_column_string_scoplib(relation, name_array); 01034 snprintf(buffer, OSL_MAX_STRING, "%s", scolumn); 01035 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01036 free(scolumn); 01037 } 01038 01039 start_row = 0; 01040 01041 } else { 01042 01043 if (relation->nb_rows == 1) // for non array variables 01044 start_row = 0; 01045 else // Remove the 'Arr' line 01046 start_row = 1; 01047 } 01048 01049 // Print the array 01050 for (i = start_row; i < relation->nb_rows; i++) { 01051 01052 // First column 01053 if (!is_access_array) { 01054 // array index name for scoplib 01055 osl_int_sprint(buffer, relation->precision, relation->m[i][0]); 01056 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01057 snprintf(buffer, OSL_MAX_STRING, " "); 01058 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01059 01060 } else { 01061 // The first column represents the array index name in openscop 01062 if (i == start_row) 01063 osl_int_sprint(buffer, relation->precision, 01064 relation->m[0][relation->nb_columns-1]); 01065 else 01066 snprintf(buffer, OSL_MAX_STRING, " 0 "); 01067 01068 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01069 snprintf(buffer, OSL_MAX_STRING, " "); 01070 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01071 } 01072 01073 // Rest of the array 01074 if (relation->type == OSL_TYPE_DOMAIN) { 01075 01076 for (j = 1; j < index_input_dims; j++) { 01077 osl_int_sprint(buffer, relation->precision, relation->m[i][j]); 01078 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01079 snprintf(buffer, OSL_MAX_STRING, " "); 01080 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01081 } 01082 01083 // Jmp input_dims 01084 for (j = index_params; j < relation->nb_columns; j++) { 01085 osl_int_sprint(buffer, relation->precision, relation->m[i][j]); 01086 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01087 snprintf(buffer, OSL_MAX_STRING, " "); 01088 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01089 } 01090 01091 } else { 01092 01093 // Jmp output_dims 01094 for (j = index_input_dims; j < index_params; j++) { 01095 if (is_access_array && relation->nb_rows == 1 && 01096 j == relation->nb_columns-1) { 01097 snprintf(buffer, OSL_MAX_STRING, " 0 "); 01098 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01099 } else { 01100 osl_int_sprint(buffer, relation->precision, relation->m[i][j]); 01101 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01102 snprintf(buffer, OSL_MAX_STRING, " "); 01103 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01104 } 01105 } 01106 01107 if (add_fakeiter) { 01108 snprintf(buffer, OSL_MAX_STRING, " 0 "); 01109 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01110 } 01111 01112 for (; j < relation->nb_columns; j++) { 01113 if (is_access_array && relation->nb_rows == 1 && 01114 j == relation->nb_columns-1) { 01115 snprintf(buffer, OSL_MAX_STRING, " 0 "); 01116 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01117 } else { 01118 osl_int_sprint(buffer, relation->precision, relation->m[i][j]); 01119 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01120 snprintf(buffer, OSL_MAX_STRING, " "); 01121 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01122 } 01123 } 01124 } 01125 01126 // equation in comment 01127 if (name_array != NULL) { 01128 comment = osl_relation_sprint_comment(relation, i, name_array, 01129 names->arrays->string); 01130 osl_util_safe_strcat(&string, comment, &high_water_mark); 01131 free(comment); 01132 snprintf(buffer, OSL_MAX_STRING, "\n"); 01133 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01134 } 01135 01136 // add the lines in the scattering if we need the fakeiter 01137 if (relation->nb_rows > 0 && add_fakeiter && 01138 relation->type == OSL_TYPE_SCATTERING) { 01139 01140 for (i = 0 ; i < 2 ; i++) { 01141 for (j = 0; j < relation->nb_columns; j++) { 01142 if (j == index_output_dims && i == 0) 01143 snprintf(buffer, OSL_MAX_STRING, " 1 "); // fakeiter 01144 else 01145 snprintf(buffer, OSL_MAX_STRING, " 0 "); 01146 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01147 } 01148 snprintf(buffer, OSL_MAX_STRING, "\n"); 01149 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01150 } 01151 } 01152 01153 } 01154 01155 // Free the array of strings. 01156 if (name_array != NULL) { 01157 for (i = 0; i < relation->nb_columns; i++) 01158 free(name_array[i]); 01159 free(name_array); 01160 } 01161 01162 relation = relation->next; 01163 } 01164 01165 if (generated_names) 01166 osl_names_free(names); 01167 01168 return string; 01169 } 01170 01171 01180 char * osl_relation_spprint(osl_relation_p relation, osl_names_p names) { 01181 int high_water_mark = OSL_MAX_STRING; 01182 char * string = NULL; 01183 char * temp; 01184 char buffer[OSL_MAX_STRING]; 01185 OSL_malloc(string, char *, high_water_mark * sizeof(char)); 01186 string[0] = '\0'; 01187 01188 if (osl_relation_nb_components(relation) > 0) { 01189 temp = osl_relation_sprint_type(relation); 01190 osl_util_safe_strcat(&string, temp, &high_water_mark); 01191 free(temp); 01192 01193 snprintf(buffer, OSL_MAX_STRING, "\n"); 01194 osl_util_safe_strcat(&string, buffer, &high_water_mark); 01195 01196 temp = osl_relation_spprint_polylib(relation, names); 01197 osl_util_safe_strcat(&string, temp, &high_water_mark); 01198 free(temp); 01199 } 01200 01201 return string; 01202 } 01203 01204 01215 char * osl_relation_spprint_scoplib(osl_relation_p relation, osl_names_p names, 01216 int print_nth_part, int add_fakeiter) { 01217 int high_water_mark = OSL_MAX_STRING; 01218 char * string = NULL; 01219 char * temp; 01220 OSL_malloc(string, char *, high_water_mark * sizeof(char)); 01221 string[0] = '\0'; 01222 01223 if (relation) { 01224 temp = osl_relation_spprint_polylib_scoplib(relation, names, 01225 print_nth_part, add_fakeiter); 01226 osl_util_safe_strcat(&string, temp, &high_water_mark); 01227 free(temp); 01228 } 01229 01230 return string; 01231 } 01232 01233 01242 void osl_relation_pprint(FILE * file, osl_relation_p relation, 01243 osl_names_p names) { 01244 char * string = osl_relation_spprint(relation, names); 01245 fprintf(file, "%s", string); 01246 free(string); 01247 } 01248 01249 01260 void osl_relation_pprint_scoplib(FILE * file, osl_relation_p relation, 01261 osl_names_p names, int print_nth_part, 01262 int add_fakeiter) { 01263 char * string = osl_relation_spprint_scoplib(relation, names, 01264 print_nth_part, add_fakeiter); 01265 fprintf(file, "%s", string); 01266 free(string); 01267 } 01268 01269 01277 char * osl_relation_sprint(osl_relation_p relation) { 01278 01279 return osl_relation_spprint(relation, NULL); 01280 } 01281 01282 01290 void osl_relation_print(FILE * file, osl_relation_p relation) { 01291 01292 osl_relation_pprint(file, relation, NULL); 01293 } 01294 01295 01296 /***************************************************************************** 01297 * Reading function * 01298 *****************************************************************************/ 01299 01300 01312 static 01313 int osl_relation_read_type(FILE * file, char ** str) { 01314 int type; 01315 osl_strings_p strings; 01316 01317 if ((file != NULL && str != NULL) || (file == NULL && str == NULL)) 01318 OSL_error("one and only one of the two parameters can be non-NULL"); 01319 01320 if (file != NULL) 01321 strings = osl_strings_read(file); 01322 else 01323 strings = osl_strings_sread(str); 01324 01325 if (osl_strings_size(strings) > 1) { 01326 OSL_warning("uninterpreted information (after the relation type)"); 01327 } 01328 if (osl_strings_size(strings) == 0) 01329 OSL_error("no relation type"); 01330 01331 if (!strcmp(strings->string[0], OSL_STRING_UNDEFINED)) { 01332 type = OSL_UNDEFINED; 01333 goto return_type; 01334 } 01335 01336 if (!strcmp(strings->string[0], OSL_STRING_CONTEXT)) { 01337 type = OSL_TYPE_CONTEXT; 01338 goto return_type; 01339 } 01340 01341 if (!strcmp(strings->string[0], OSL_STRING_DOMAIN)) { 01342 type = OSL_TYPE_DOMAIN; 01343 goto return_type; 01344 } 01345 01346 if (!strcmp(strings->string[0], OSL_STRING_SCATTERING)) { 01347 type = OSL_TYPE_SCATTERING; 01348 goto return_type; 01349 } 01350 01351 if (!strcmp(strings->string[0], OSL_STRING_READ)) { 01352 type = OSL_TYPE_READ; 01353 goto return_type; 01354 } 01355 01356 if (!strcmp(strings->string[0], OSL_STRING_WRITE)) { 01357 type = OSL_TYPE_WRITE; 01358 goto return_type; 01359 } 01360 01361 if (!strcmp(strings->string[0], OSL_STRING_MAY_WRITE)) { 01362 type = OSL_TYPE_MAY_WRITE; 01363 goto return_type; 01364 } 01365 01366 OSL_error("relation type not supported"); 01367 01368 return_type: 01369 osl_strings_free(strings); 01370 return type; 01371 } 01372 01373 01382 osl_relation_p osl_relation_pread(FILE * foo, int precision) { 01383 int i, j, k, n, read = 0; 01384 int nb_rows, nb_columns; 01385 int nb_output_dims, nb_input_dims, nb_local_dims, nb_parameters; 01386 int nb_union_parts = 1; 01387 int may_read_nb_union_parts = 1; 01388 int read_attributes = 1; 01389 int first = 1; 01390 int type; 01391 char * c, s[OSL_MAX_STRING], str[OSL_MAX_STRING], *tmp; 01392 osl_relation_p relation, relation_union = NULL, previous = NULL; 01393 01394 type = osl_relation_read_type(foo, NULL); 01395 01396 // Read each part of the union (the number of parts may be updated inside) 01397 for (k = 0; k < nb_union_parts; k++) { 01398 // Read the number of union parts or the attributes of the union part 01399 while (read_attributes) { 01400 read_attributes = 0; 01401 01402 // Read relation attributes. 01403 c = osl_util_skip_blank_and_comments(foo, s); 01404 read = sscanf(c, " %d %d %d %d %d %d", &nb_rows, &nb_columns, 01405 &nb_output_dims, &nb_input_dims, 01406 &nb_local_dims, &nb_parameters); 01407 01408 if (((read != 1) && (read != 6)) || 01409 ((read == 1) && (may_read_nb_union_parts != 1))) 01410 OSL_error("not 1 or 6 integers on the first relation line"); 01411 01412 if (read == 1) { 01413 // Only one number means a union and is the number of parts. 01414 nb_union_parts = nb_rows; 01415 if (nb_union_parts < 1) 01416 OSL_error("negative nb of union parts"); 01417 01418 // Allow to read the properties of the first part of the union. 01419 read_attributes = 1; 01420 } 01421 01422 may_read_nb_union_parts = 0; 01423 } 01424 01425 // Allocate the union part and fill its properties. 01426 relation = osl_relation_pmalloc(precision, nb_rows, nb_columns); 01427 relation->type = type; 01428 relation->nb_output_dims = nb_output_dims; 01429 relation->nb_input_dims = nb_input_dims; 01430 relation->nb_local_dims = nb_local_dims; 01431 relation->nb_parameters = nb_parameters; 01432 01433 // Read the matrix of constraints. 01434 for (i = 0; i < relation->nb_rows; i++) { 01435 c = osl_util_skip_blank_and_comments(foo, s); 01436 if (c == NULL) 01437 OSL_error("not enough rows"); 01438 01439 for (j = 0; j < relation->nb_columns; j++) { 01440 if (c == NULL || *c == '#' || *c == '\n') 01441 OSL_error("not enough columns"); 01442 if (sscanf(c, "%s%n", str, &n) == 0) 01443 OSL_error("not enough rows"); 01444 01445 // TODO: remove this tmp (sread updates the pointer). 01446 tmp = str; 01447 osl_int_sread(&tmp, precision, &relation->m[i][j]); 01448 c += n; 01449 } 01450 } 01451 01452 // Build the linked list of union parts. 01453 if (first == 1) { 01454 relation_union = relation; 01455 first = 0; 01456 } 01457 else { 01458 previous->next = relation; 01459 } 01460 01461 previous = relation; 01462 read_attributes = 1; 01463 } 01464 01465 return relation_union; 01466 } 01467 01468 01480 osl_relation_p osl_relation_psread(char ** input, int precision) { 01481 int i, j, k, n, read = 0; 01482 int nb_rows, nb_columns; 01483 int nb_output_dims, nb_input_dims, nb_local_dims, nb_parameters; 01484 int nb_union_parts = 1; 01485 int may_read_nb_union_parts = 1; 01486 int read_attributes = 1; 01487 int first = 1; 01488 int type; 01489 char str[OSL_MAX_STRING], *tmp; 01490 osl_relation_p relation, relation_union = NULL, previous = NULL; 01491 01492 type = osl_relation_read_type(NULL, input); 01493 01494 // Read each part of the union (the number of parts may be updated inside) 01495 for (k = 0; k < nb_union_parts; k++) { 01496 // Read the number of union parts or the attributes of the union part 01497 while (read_attributes) { 01498 read_attributes = 0; 01499 01500 // Read relation attributes. 01501 osl_util_sskip_blank_and_comments(input); 01502 01503 read = sscanf(*input, " %d %d %d %d %d %d%n", 01504 &nb_rows, &nb_columns, 01505 &nb_output_dims, &nb_input_dims, 01506 &nb_local_dims, &nb_parameters, &n); 01507 *input += n; 01508 01509 if (((read != 1) && (read != 6)) || 01510 ((read == 1) && (may_read_nb_union_parts != 1))) 01511 OSL_error("not 1 or 6 integers on the first relation line"); 01512 01513 if (read == 1) { 01514 // Only one number means a union and is the number of parts. 01515 nb_union_parts = nb_rows; 01516 if (nb_union_parts < 1) 01517 OSL_error("negative nb of union parts"); 01518 01519 // Allow to read the properties of the first part of the union. 01520 read_attributes = 1; 01521 } 01522 01523 may_read_nb_union_parts = 0; 01524 } 01525 01526 // Allocate the union part and fill its properties. 01527 relation = osl_relation_pmalloc(precision, nb_rows, nb_columns); 01528 relation->type = type; 01529 relation->nb_output_dims = nb_output_dims; 01530 relation->nb_input_dims = nb_input_dims; 01531 relation->nb_local_dims = nb_local_dims; 01532 relation->nb_parameters = nb_parameters; 01533 01534 // Read the matrix of constraints. 01535 for (i = 0; i < relation->nb_rows; i++) { 01536 osl_util_sskip_blank_and_comments(input); 01537 if (!(*input)) 01538 OSL_error("not enough rows"); 01539 01540 for (j = 0; j < relation->nb_columns; j++) { 01541 if (*input == NULL || **input == '#' || **input == '\n') 01542 OSL_error("not enough columns"); 01543 if (sscanf(*input, "%s%n", str, &n) == 0) 01544 OSL_error("not enough rows"); 01545 01546 // TODO: remove this tmp (sread updates the pointer). 01547 tmp = str; 01548 osl_int_sread(&tmp, precision, &relation->m[i][j]); 01549 *input += n; 01550 } 01551 } 01552 01553 // Build the linked list of union parts. 01554 if (first == 1) { 01555 relation_union = relation; 01556 first = 0; 01557 } 01558 else { 01559 previous->next = relation; 01560 } 01561 01562 previous = relation; 01563 read_attributes = 1; 01564 } 01565 01566 return relation_union; 01567 } 01568 01569 01577 osl_relation_p osl_relation_sread(char ** input) { 01578 int precision = osl_util_get_precision(); 01579 return osl_relation_psread(input, precision); 01580 } 01581 01582 01590 osl_relation_p osl_relation_read(FILE * foo) { 01591 int precision = osl_util_get_precision(); 01592 return osl_relation_pread(foo, precision); 01593 } 01594 01595 01596 /*+*************************************************************************** 01597 * Memory allocation/deallocation function * 01598 *****************************************************************************/ 01599 01600 01612 osl_relation_p osl_relation_pmalloc(int precision, 01613 int nb_rows, int nb_columns) { 01614 osl_relation_p relation; 01615 osl_int_t ** p, * q; 01616 int i, j; 01617 01618 if ((precision != OSL_PRECISION_SP) && 01619 (precision != OSL_PRECISION_DP) && 01620 (precision != OSL_PRECISION_MP)) 01621 OSL_error("unknown precision"); 01622 01623 if ((nb_rows < 0) || (nb_columns < 0)) 01624 OSL_error("negative sizes"); 01625 01626 OSL_malloc(relation, osl_relation_p, sizeof(osl_relation_t)); 01627 relation->type = OSL_UNDEFINED; 01628 relation->nb_rows = nb_rows; 01629 relation->nb_columns = nb_columns; 01630 relation->nb_output_dims = OSL_UNDEFINED; 01631 relation->nb_input_dims = OSL_UNDEFINED; 01632 relation->nb_parameters = OSL_UNDEFINED; 01633 relation->nb_local_dims = OSL_UNDEFINED; 01634 relation->precision = precision; 01635 01636 if ((nb_rows == 0) || (nb_columns == 0) || 01637 (nb_rows == OSL_UNDEFINED) || (nb_columns == OSL_UNDEFINED)) { 01638 relation->m = NULL; 01639 } 01640 else { 01641 OSL_malloc(p, osl_int_t**, nb_rows * sizeof(osl_int_t*)); 01642 OSL_malloc(q, osl_int_t*, nb_rows * nb_columns * sizeof(osl_int_t)); 01643 relation->m = p; 01644 for (i = 0; i < nb_rows; i++) { 01645 relation->m[i] = q + i * nb_columns ; 01646 for (j = 0; j < nb_columns; j++) 01647 osl_int_init_set_si(precision, &relation->m[i][j], 0); 01648 } 01649 } 01650 01651 relation->next = NULL; 01652 01653 return relation; 01654 } 01655 01656 01664 osl_relation_p osl_relation_malloc(int nb_rows, int nb_columns) { 01665 int precision = osl_util_get_precision(); 01666 return osl_relation_pmalloc(precision, nb_rows, nb_columns); 01667 } 01668 01669 01676 void osl_relation_free_inside(osl_relation_p relation) { 01677 int i, nb_elements; 01678 01679 if (relation == NULL) 01680 return; 01681 01682 nb_elements = relation->nb_rows * relation->nb_columns; 01683 01684 for (i = 0; i < nb_elements; i++) 01685 osl_int_clear(relation->precision, &relation->m[0][i]); 01686 01687 if (relation->m != NULL) { 01688 if (nb_elements > 0) 01689 free(relation->m[0]); 01690 free(relation->m); 01691 } 01692 } 01693 01694 01701 void osl_relation_free(osl_relation_p relation) { 01702 osl_relation_p tmp; 01703 01704 while (relation != NULL) { 01705 tmp = relation->next; 01706 osl_relation_free_inside(relation); 01707 free(relation); 01708 relation = tmp; 01709 } 01710 } 01711 01712 01713 /*+*************************************************************************** 01714 * Processing functions * 01715 *****************************************************************************/ 01716 01717 01728 osl_relation_p osl_relation_nclone(osl_relation_p relation, int n) { 01729 int i, j, k; 01730 int first = 1, nb_components, nb_parts; 01731 osl_relation_p clone = NULL, node, previous = NULL; 01732 01733 nb_components = osl_relation_nb_components(relation); 01734 nb_parts = (n == -1) ? nb_components : n; 01735 if (nb_components < nb_parts) 01736 OSL_error("not enough union parts to clone"); 01737 01738 for (k = 0; k < nb_parts; k++) { 01739 node = osl_relation_pmalloc(relation->precision, 01740 relation->nb_rows, relation->nb_columns); 01741 node->type = relation->type; 01742 node->nb_output_dims = relation->nb_output_dims; 01743 node->nb_input_dims = relation->nb_input_dims; 01744 node->nb_local_dims = relation->nb_local_dims; 01745 node->nb_parameters = relation->nb_parameters; 01746 01747 for (i = 0; i < relation->nb_rows; i++) 01748 for (j = 0; j < relation->nb_columns; j++) 01749 osl_int_assign(relation->precision, 01750 &node->m[i][j], relation->m[i][j]); 01751 01752 if (first) { 01753 first = 0; 01754 clone = node; 01755 previous = node; 01756 } 01757 else { 01758 previous->next = node; 01759 previous = previous->next; 01760 } 01761 01762 relation = relation->next; 01763 } 01764 01765 return clone; 01766 } 01767 01768 01781 osl_relation_p osl_relation_clone_nconstraints(osl_relation_p relation, 01782 int n) { 01783 int i, j; 01784 int first = 1, all_rows = 0; 01785 osl_relation_p clone = NULL, node, previous = NULL; 01786 01787 if (n == -1) 01788 all_rows = 1; 01789 01790 while (relation != NULL) { 01791 if (all_rows) 01792 n = relation->nb_rows; 01793 01794 if (n > relation->nb_rows) 01795 OSL_error("not enough rows to clone in the relation"); 01796 01797 node = osl_relation_pmalloc(relation->precision, n, relation->nb_columns); 01798 node->type = relation->type; 01799 node->nb_output_dims = relation->nb_output_dims; 01800 node->nb_input_dims = relation->nb_input_dims; 01801 node->nb_local_dims = relation->nb_local_dims; 01802 node->nb_parameters = relation->nb_parameters; 01803 01804 for (i = 0; i < n; i++) 01805 for (j = 0; j < relation->nb_columns; j++) 01806 osl_int_assign(relation->precision, 01807 &node->m[i][j], relation->m[i][j]); 01808 01809 if (first) { 01810 first = 0; 01811 clone = node; 01812 previous = node; 01813 } 01814 else { 01815 previous->next = node; 01816 previous = previous->next; 01817 } 01818 01819 relation = relation->next; 01820 } 01821 01822 return clone; 01823 } 01824 01825 01833 osl_relation_p osl_relation_clone(osl_relation_p relation) { 01834 if (relation == NULL) 01835 return NULL; 01836 01837 return osl_relation_nclone(relation, -1); 01838 } 01839 01840 01850 void osl_relation_add(osl_relation_p *r1, osl_relation_p r2) { 01851 while (*r1 != NULL) 01852 r1 = &((*r1)->next); 01853 01854 *r1 = r2; 01855 } 01856 01857 01867 osl_relation_p osl_relation_union(osl_relation_p r1, 01868 osl_relation_p r2) { 01869 osl_relation_p copy1, copy2; 01870 01871 if ((r1 == NULL) && (r2 == NULL)) 01872 return NULL; 01873 01874 copy1 = osl_relation_clone(r1); 01875 copy2 = osl_relation_clone(r2); 01876 osl_relation_add(©1, copy2); 01877 01878 return copy1; 01879 } 01880 01881 01891 void osl_relation_replace_vector(osl_relation_p relation, 01892 osl_vector_p vector, int row) { 01893 int i; 01894 01895 if ((relation == NULL) || (vector == NULL) || 01896 (relation->precision != vector->precision) || 01897 (relation->nb_columns != vector->size) || 01898 (row >= relation->nb_rows) || (row < 0)) 01899 OSL_error("vector cannot replace relation row"); 01900 01901 for (i = 0; i < vector->size; i++) 01902 osl_int_assign(relation->precision, &relation->m[row][i], vector->v[i]); 01903 } 01904 01905 01915 void osl_relation_add_vector(osl_relation_p relation, 01916 osl_vector_p vector, int row) { 01917 int i; 01918 01919 if ((relation == NULL) || (vector == NULL) || 01920 (relation->precision != vector->precision) || 01921 (relation->nb_columns != vector->size) || 01922 (row >= relation->nb_rows) || (row < 0)) 01923 OSL_error("vector cannot be added to relation"); 01924 01925 if (osl_int_get_si(relation->precision, relation->m[row][0]) == 0) 01926 osl_int_assign(relation->precision, &relation->m[row][0], vector->v[0]); 01927 01928 for (i = 1; i < vector->size; i++) 01929 osl_int_add(relation->precision, 01930 &relation->m[row][i], relation->m[row][i], vector->v[i]); 01931 } 01932 01933 01943 void osl_relation_sub_vector(osl_relation_p relation, 01944 osl_vector_p vector, int row) { 01945 int i; 01946 01947 if ((relation == NULL) || (vector == NULL) || 01948 (relation->precision != vector->precision) || 01949 (relation->nb_columns != vector->size) || 01950 (row >= relation->nb_rows) || (row < 0)) 01951 OSL_error("vector cannot be subtracted to row"); 01952 01953 if (osl_int_get_si(relation->precision, relation->m[row][0]) == 0) 01954 osl_int_assign(relation->precision, &relation->m[row][0], vector->v[0]); 01955 01956 for (i = 1; i < vector->size; i++) 01957 osl_int_sub(relation->precision, 01958 &relation->m[row][i], relation->m[row][i], vector->v[i]); 01959 } 01960 01961 01975 void osl_relation_insert_vector(osl_relation_p relation, 01976 osl_vector_p vector, int row) { 01977 osl_relation_p temp; 01978 01979 temp = osl_relation_from_vector(vector); 01980 osl_relation_insert_constraints(relation, temp, row); 01981 osl_relation_free(temp); 01982 } 01983 01984 01996 osl_relation_p osl_relation_concat_vector(osl_relation_p relation, 01997 osl_vector_p vector) { 01998 osl_relation_p new, temp; 01999 02000 temp = osl_relation_from_vector(vector); 02001 new = osl_relation_concat_constraints(relation, temp); 02002 osl_relation_free(temp); 02003 return new; 02004 } 02005 02006 02014 void osl_relation_insert_blank_row(osl_relation_p relation, int row) { 02015 osl_vector_p vector; 02016 02017 if (relation != NULL) { 02018 vector = osl_vector_pmalloc(relation->precision, relation->nb_columns); 02019 osl_relation_insert_vector(relation, vector, row); 02020 osl_vector_free(vector); 02021 } 02022 } 02023 02024 02033 void osl_relation_insert_blank_column(osl_relation_p relation, int column) { 02034 02035 int i, j; 02036 osl_relation_p temp; 02037 02038 if (relation == NULL) 02039 return; 02040 02041 if ((column < 0) || (column > relation->nb_columns)) 02042 OSL_error("bad column number"); 02043 02044 // We use a temporary relation just to reuse existing functions. Cleaner. 02045 temp = osl_relation_pmalloc(relation->precision, 02046 relation->nb_rows, relation->nb_columns + 1); 02047 02048 for (i = 0; i < relation->nb_rows; i++) { 02049 for (j = 0; j < column; j++) 02050 osl_int_assign(relation->precision, &temp->m[i][j], relation->m[i][j]); 02051 02052 for (j = column; j < relation->nb_columns; j++) 02053 osl_int_assign(relation->precision, &temp->m[i][j+1], relation->m[i][j]); 02054 } 02055 02056 osl_relation_free_inside(relation); 02057 02058 // Replace the inside of relation. 02059 relation->nb_columns = temp->nb_columns; 02060 relation->m = temp->m; 02061 02062 // Free the temp "shell". 02063 free(temp); 02064 } 02065 02066 02074 osl_relation_p osl_relation_from_vector(osl_vector_p vector) { 02075 osl_relation_p relation; 02076 02077 if (vector == NULL) 02078 return NULL; 02079 02080 relation = osl_relation_pmalloc(vector->precision, 1, vector->size); 02081 osl_relation_replace_vector(relation, vector, 0); 02082 return relation; 02083 } 02084 02085 02095 void osl_relation_replace_constraints(osl_relation_p r1, 02096 osl_relation_p r2, int row) { 02097 int i, j; 02098 02099 if ((r1 == NULL) || (r2 == NULL) || 02100 (r1->precision != r2->precision) || 02101 (r1->nb_columns != r1->nb_columns) || 02102 ((row + r2->nb_rows) > r1->nb_rows) || (row < 0)) 02103 OSL_error("relation rows could not be replaced"); 02104 02105 for (i = 0; i < r2->nb_rows; i++) 02106 for (j = 0; j < r2->nb_columns; j++) 02107 osl_int_assign(r1->precision, &r1->m[i+row][j], r2->m[i][j]); 02108 } 02109 02110 02123 void osl_relation_insert_constraints(osl_relation_p r1, 02124 osl_relation_p r2, int row) { 02125 int i, j; 02126 osl_relation_p temp; 02127 02128 if ((r1 == NULL) || (r2 == NULL)) 02129 return; 02130 02131 if (row == -1) 02132 row = r1->nb_rows; 02133 02134 if ((r1->nb_columns != r2->nb_columns) || 02135 (r1->precision != r2->precision) || 02136 (row > r1->nb_rows) || (row < 0)) 02137 OSL_error("constraints cannot be inserted"); 02138 02139 // We use a temporary relation just to reuse existing functions. Cleaner. 02140 temp = osl_relation_pmalloc(r1->precision, 02141 r1->nb_rows + r2->nb_rows, r1->nb_columns); 02142 02143 for (i = 0; i < row; i++) 02144 for (j = 0; j < r1->nb_columns; j++) 02145 osl_int_assign(r1->precision, &temp->m[i][j], r1->m[i][j]); 02146 02147 osl_relation_replace_constraints(temp, r2, row); 02148 02149 for (i = row + r2->nb_rows; i < r2->nb_rows + r1->nb_rows; i++) 02150 for (j = 0; j < r1->nb_columns; j++) 02151 osl_int_assign(r1->precision, &temp->m[i][j], r1->m[i-r2->nb_rows][j]); 02152 02153 osl_relation_free_inside(r1); 02154 02155 // Replace the inside of relation. 02156 r1->nb_rows = temp->nb_rows; 02157 r1->m = temp->m; 02158 02159 // Free the temp "shell". 02160 free(temp); 02161 } 02162 02163 02172 void osl_relation_swap_constraints(osl_relation_p relation, int c1, int c2) { 02173 int i; 02174 02175 if ((relation == NULL) || (c1 == c2)) 02176 return; 02177 02178 if ((c1 >= relation->nb_rows) || (c1 < 0) || 02179 (c2 >= relation->nb_rows) || (c2 < 0)) 02180 OSL_error("bad constraint rows"); 02181 02182 for (i = 0; i < relation->nb_columns; i++) 02183 osl_int_swap(relation->precision, 02184 &relation->m[c1][i], &relation->m[c2][i]); 02185 } 02186 02187 02195 void osl_relation_remove_row(osl_relation_p r, int row) { 02196 int i, j; 02197 osl_relation_p temp; 02198 02199 if (r == NULL) 02200 return; 02201 02202 if ((row < 0) || (row >= r->nb_rows)) 02203 OSL_error("bad row number"); 02204 02205 // We use a temporary relation just to reuse existing functions. Cleaner. 02206 temp = osl_relation_pmalloc(r->precision, 02207 r->nb_rows - 1, r->nb_columns); 02208 02209 for (i = 0; i < row; i++) 02210 for (j = 0; j < r->nb_columns; j++) 02211 osl_int_assign(r->precision, &temp->m[i][j], r->m[i][j]); 02212 02213 for (i = row + 1; i < r->nb_rows; i++) 02214 for (j = 0; j < r->nb_columns; j++) 02215 osl_int_assign(r->precision, &temp->m[i - 1][j], r->m[i][j]); 02216 02217 osl_relation_free_inside(r); 02218 02219 // Replace the inside of relation. 02220 r->nb_rows = temp->nb_rows; 02221 r->m = temp->m; 02222 02223 // Free the temp "shell". 02224 free(temp); 02225 } 02226 02227 02235 void osl_relation_remove_column(osl_relation_p r, int column) { 02236 int i, j; 02237 osl_relation_p temp; 02238 02239 if (r == NULL) 02240 return; 02241 02242 if ((column < 0) || (column >= r->nb_columns)) 02243 OSL_error("bad column number"); 02244 02245 // We use a temporary relation just to reuse existing functions. Cleaner. 02246 temp = osl_relation_pmalloc(r->precision, 02247 r->nb_rows, r->nb_columns - 1); 02248 02249 for (i = 0; i < r->nb_rows; i++) { 02250 for (j = 0; j < column; j++) 02251 osl_int_assign(r->precision, &temp->m[i][j], r->m[i][j]); 02252 02253 for (j = column + 1; j < r->nb_columns; j++) 02254 osl_int_assign(r->precision, &temp->m[i][j - 1], r->m[i][j]); 02255 } 02256 02257 osl_relation_free_inside(r); 02258 02259 // Replace the inside of relation. 02260 r->nb_columns = temp->nb_columns; 02261 r->m = temp->m; 02262 02263 // Free the temp "shell". 02264 free(temp); 02265 } 02266 02267 02279 void osl_relation_insert_columns(osl_relation_p relation, 02280 osl_relation_p insert, int column) { 02281 int i, j; 02282 osl_relation_p temp; 02283 02284 if ((relation == NULL) || (insert == NULL)) 02285 return; 02286 02287 if ((relation->precision != insert->precision) || 02288 (relation->nb_rows != insert->nb_rows) || 02289 (column < 0) || (column > relation->nb_columns)) 02290 OSL_error("columns cannot be inserted"); 02291 02292 // We use a temporary relation just to reuse existing functions. Cleaner. 02293 temp = osl_relation_pmalloc(relation->precision, relation->nb_rows, 02294 relation->nb_columns + insert->nb_columns); 02295 02296 for (i = 0; i < relation->nb_rows; i++) { 02297 for (j = 0; j < column; j++) 02298 osl_int_assign(relation->precision, &temp->m[i][j], relation->m[i][j]); 02299 02300 for (j = column; j < column + insert->nb_columns; j++) 02301 osl_int_assign(relation->precision, 02302 &temp->m[i][j], insert->m[i][j - column]); 02303 02304 for (j = column + insert->nb_columns; 02305 j < insert->nb_columns + relation->nb_columns; j++) 02306 osl_int_assign(relation->precision, 02307 &temp->m[i][j], relation->m[i][j - insert->nb_columns]); 02308 } 02309 02310 osl_relation_free_inside(relation); 02311 02312 // Replace the inside of relation. 02313 relation->nb_columns = temp->nb_columns; 02314 relation->m = temp->m; 02315 02316 // Free the temp "shell". 02317 free(temp); 02318 } 02319 02320 02332 osl_relation_p osl_relation_concat_constraints( 02333 osl_relation_p r1, 02334 osl_relation_p r2) { 02335 osl_relation_p new; 02336 02337 if (r1 == NULL) 02338 return osl_relation_clone(r2); 02339 02340 if (r2 == NULL) 02341 return osl_relation_clone(r1); 02342 02343 if (r1->nb_columns != r2->nb_columns) 02344 OSL_error("incompatible sizes for concatenation"); 02345 02346 if (r1->next || r2->next) 02347 OSL_warning("relation concatenation is done on the first elements " 02348 "of union only"); 02349 02350 new = osl_relation_pmalloc(r1->precision, 02351 r1->nb_rows + r2->nb_rows, r1->nb_columns); 02352 osl_relation_replace_constraints(new, r1, 0); 02353 osl_relation_replace_constraints(new, r2, r1->nb_rows); 02354 02355 return new; 02356 } 02357 02358 02368 int osl_relation_part_equal(osl_relation_p r1, osl_relation_p r2) { 02369 int i, j; 02370 02371 if (r1 == r2) 02372 return 1; 02373 02374 if (((r1 == NULL) && (r2 != NULL)) || 02375 ((r1 != NULL) && (r2 == NULL))) 02376 return 0; 02377 02378 if ((r1->type != r2->type) || 02379 (r1->precision != r2->precision) || 02380 (r1->nb_rows != r2->nb_rows) || 02381 (r1->nb_columns != r2->nb_columns) || 02382 (r1->nb_output_dims != r2->nb_output_dims) || 02383 (r1->nb_input_dims != r2->nb_input_dims) || 02384 (r1->nb_local_dims != r2->nb_local_dims) || 02385 (r1->nb_parameters != r2->nb_parameters)) 02386 return 0; 02387 02388 for (i = 0; i < r1->nb_rows; ++i) 02389 for (j = 0; j < r1->nb_columns; ++j) 02390 if (osl_int_ne(r1->precision, r1->m[i][j], r2->m[i][j])) 02391 return 0; 02392 02393 return 1; 02394 } 02395 02396 02405 int osl_relation_equal(osl_relation_p r1, osl_relation_p r2) { 02406 while ((r1 != NULL) && (r2 != NULL)) { 02407 if (!osl_relation_part_equal(r1, r2)) 02408 return 0; 02409 02410 r1 = r1->next; 02411 r2 = r2->next; 02412 } 02413 02414 if (((r1 == NULL) && (r2 != NULL)) || ((r1 != NULL) && (r2 == NULL))) 02415 return 0; 02416 02417 return 1; 02418 } 02419 02420 02434 static 02435 int osl_relation_check_attribute(int * expected, int actual) { 02436 if (*expected != OSL_UNDEFINED) { 02437 if ((actual != OSL_UNDEFINED) && 02438 (actual != *expected)) { 02439 OSL_warning("unexpected atribute"); 02440 return 0; 02441 } 02442 } 02443 else { 02444 *expected = actual; 02445 } 02446 02447 return 1; 02448 } 02449 02450 02464 static 02465 int osl_relation_check_nb_columns(osl_relation_p relation, 02466 int expected_nb_output_dims, 02467 int expected_nb_input_dims, 02468 int expected_nb_parameters) { 02469 int expected_nb_local_dims, expected_nb_columns; 02470 02471 if ((expected_nb_output_dims != OSL_UNDEFINED) && 02472 (expected_nb_input_dims != OSL_UNDEFINED) && 02473 (expected_nb_parameters != OSL_UNDEFINED)) { 02474 02475 if (relation->nb_local_dims == OSL_UNDEFINED) 02476 expected_nb_local_dims = 0; 02477 else 02478 expected_nb_local_dims = relation->nb_local_dims; 02479 02480 expected_nb_columns = expected_nb_output_dims + 02481 expected_nb_input_dims + 02482 expected_nb_local_dims + 02483 expected_nb_parameters + 02484 2; 02485 02486 if (expected_nb_columns != relation->nb_columns) { 02487 OSL_warning("unexpected number of columns"); 02488 return 0; 02489 } 02490 } 02491 02492 return 1; 02493 } 02494 02495 02510 int osl_relation_integrity_check(osl_relation_p relation, 02511 int expected_type, 02512 int expected_nb_output_dims, 02513 int expected_nb_input_dims, 02514 int expected_nb_parameters) { 02515 int i; 02516 02517 // Check the NULL case. 02518 if (relation == NULL) { 02519 if ((expected_nb_output_dims != OSL_UNDEFINED) || 02520 (expected_nb_input_dims != OSL_UNDEFINED) || 02521 (expected_nb_parameters != OSL_UNDEFINED)) { 02522 OSL_debug("NULL relation with some expected attibutes"); 02523 //return 0; 02524 } 02525 02526 return 1; 02527 } 02528 02529 // Check the type. 02530 if (((expected_type != OSL_TYPE_ACCESS) && 02531 (expected_type != relation->type)) || 02532 ((expected_type == OSL_TYPE_ACCESS) && 02533 (!osl_relation_is_access(relation)))) { 02534 OSL_warning("wrong type"); 02535 osl_relation_dump(stderr, relation); 02536 return 0; 02537 } 02538 02539 // Check that relations have no undefined atributes. 02540 if ((relation->nb_output_dims == OSL_UNDEFINED) || 02541 (relation->nb_input_dims == OSL_UNDEFINED) || 02542 (relation->nb_local_dims == OSL_UNDEFINED) || 02543 (relation->nb_parameters == OSL_UNDEFINED)) { 02544 OSL_warning("all attributes should be defined"); 02545 osl_relation_dump(stderr, relation); 02546 return 0; 02547 } 02548 02549 // Check that a context has actually 0 output dimensions. 02550 if ((relation->type == OSL_TYPE_CONTEXT) && 02551 (relation->nb_output_dims != 0)) { 02552 OSL_warning("context without 0 as number of output dimensions"); 02553 osl_relation_dump(stderr, relation); 02554 return 0; 02555 } 02556 02557 // Check that a domain or a context has actually 0 input dimensions. 02558 if (((relation->type == OSL_TYPE_DOMAIN) || 02559 (relation->type == OSL_TYPE_CONTEXT)) && 02560 (relation->nb_input_dims != 0)) { 02561 OSL_warning("domain or context without 0 input dimensions"); 02562 osl_relation_dump(stderr, relation); 02563 return 0; 02564 } 02565 02566 // Check properties according to expected values (and if expected values 02567 // are undefined, define them with the first relation part properties). 02568 if (!osl_relation_check_attribute(&expected_nb_output_dims, 02569 relation->nb_output_dims) || 02570 !osl_relation_check_attribute(&expected_nb_input_dims, 02571 relation->nb_input_dims) || 02572 !osl_relation_check_attribute(&expected_nb_parameters, 02573 relation->nb_parameters)) { 02574 osl_relation_dump(stderr, relation); 02575 return 0; 02576 } 02577 02578 while (relation != NULL) { 02579 02580 // Attributes (except the number of local dimensions) should be the same 02581 // in all parts of the union. 02582 if ((expected_nb_output_dims != relation->nb_output_dims) || 02583 (expected_nb_input_dims != relation->nb_input_dims) || 02584 (expected_nb_parameters != relation->nb_parameters)) { 02585 OSL_warning("inconsistent attributes"); 02586 osl_relation_dump(stderr, relation); 02587 return 0; 02588 } 02589 02590 // Check whether the number of columns is OK or not. 02591 if (!osl_relation_check_nb_columns(relation, 02592 expected_nb_output_dims, 02593 expected_nb_input_dims, 02594 expected_nb_parameters)) { 02595 osl_relation_dump(stderr, relation); 02596 return 0; 02597 } 02598 02599 // Check the first column. The first column of a relation part should be 02600 // made of 0 or 1 only. 02601 if ((relation->nb_rows > 0) && (relation->nb_columns > 0)) { 02602 for (i = 0; i < relation->nb_rows; i++) { 02603 if (!osl_int_zero(relation->precision, relation->m[i][0]) && 02604 !osl_int_one(relation->precision, relation->m[i][0])) { 02605 OSL_warning("first column of a relation is not " 02606 "strictly made of 0 or 1"); 02607 osl_relation_dump(stderr, relation); 02608 return 0; 02609 } 02610 } 02611 } 02612 02613 // Array accesses must provide the array identifier. 02614 if ((osl_relation_is_access(relation)) && 02615 (osl_relation_get_array_id(relation) == OSL_UNDEFINED)) { 02616 osl_relation_dump(stderr, relation); 02617 return 0; 02618 } 02619 02620 relation = relation->next; 02621 } 02622 02623 return 1; 02624 } 02625 02626 02637 void osl_relation_set_attributes_one(osl_relation_p relation, 02638 int nb_output_dims, int nb_input_dims, 02639 int nb_local_dims, int nb_parameters) { 02640 if (relation != NULL) { 02641 relation->nb_output_dims = nb_output_dims; 02642 relation->nb_input_dims = nb_input_dims; 02643 relation->nb_local_dims = nb_local_dims; 02644 relation->nb_parameters = nb_parameters; 02645 } 02646 } 02647 02648 02659 void osl_relation_set_attributes(osl_relation_p relation, 02660 int nb_output_dims, int nb_input_dims, 02661 int nb_local_dims, int nb_parameters) { 02662 while (relation != NULL) { 02663 osl_relation_set_attributes_one(relation, 02664 nb_output_dims, nb_input_dims, 02665 nb_local_dims, nb_parameters); 02666 relation = relation->next; 02667 } 02668 } 02669 02670 02678 void osl_relation_set_type(osl_relation_p relation, int type) { 02679 02680 while (relation != NULL) { 02681 relation->type = type; 02682 relation = relation->next; 02683 } 02684 } 02685 02686 02695 int osl_relation_get_array_id(osl_relation_p relation) { 02696 int i; 02697 int first = 1; 02698 int array_id = OSL_UNDEFINED; 02699 int reference_array_id = OSL_UNDEFINED; 02700 int nb_array_id; 02701 int row_id = 0; 02702 int precision; 02703 02704 if (relation == NULL) 02705 return OSL_UNDEFINED; 02706 02707 if (!osl_relation_is_access(relation)) { 02708 OSL_warning("asked for an array id of non-array relation"); 02709 return OSL_UNDEFINED; 02710 } 02711 02712 while (relation != NULL) { 02713 precision = relation->precision; 02714 02715 // There should be room to store the array identifier. 02716 if ((relation->nb_rows < 1) || 02717 (relation->nb_columns < 3)) { 02718 OSL_warning("no array identifier in an access function"); 02719 return OSL_UNDEFINED; 02720 } 02721 02722 // Array identifiers are m[i][#columns -1] / m[i][1], with i the only row 02723 // where m[i][1] is not 0. 02724 // - check there is exactly one row such that m[i][1] is not 0, 02725 // - check the whole ith row if full of 0 except m[i][1] and the id, 02726 // - check that (m[i][#columns -1] % m[i][1]) == 0, 02727 // - check that (-m[i][#columns -1] / m[i][1]) > 0. 02728 nb_array_id = 0; 02729 for (i = 0; i < relation->nb_rows; i++) { 02730 if (!osl_int_zero(precision, relation->m[i][1])) { 02731 nb_array_id ++; 02732 row_id = i; 02733 } 02734 } 02735 if (nb_array_id == 0) { 02736 OSL_warning("no array identifier in an access function"); 02737 return OSL_UNDEFINED; 02738 } 02739 if (nb_array_id > 1) { 02740 OSL_warning("several array identifiers in one access function"); 02741 return OSL_UNDEFINED; 02742 } 02743 for (i = 0; i < relation->nb_columns - 1; i++) { 02744 if ((i != 1) && !osl_int_zero(precision, relation->m[row_id][i])) { 02745 OSL_warning("non integer array identifier"); 02746 return OSL_UNDEFINED; 02747 } 02748 } 02749 if (!osl_int_divisible(precision, 02750 relation->m[row_id][relation->nb_columns - 1], 02751 relation->m[row_id][1])) { 02752 OSL_warning("rational array identifier"); 02753 return OSL_UNDEFINED; 02754 } 02755 array_id = -osl_int_get_si(precision, 02756 relation->m[row_id][relation->nb_columns - 1]); 02757 array_id /= osl_int_get_si(precision, relation->m[row_id][1]); 02758 if (array_id <= 0) { 02759 OSL_warning("negative or 0 identifier in access function"); 02760 return OSL_UNDEFINED; 02761 } 02762 02763 // Unions of accesses are allowed, but they should refer at the same array. 02764 if (first) { 02765 reference_array_id = array_id; 02766 first = 0; 02767 } 02768 else { 02769 if (reference_array_id != array_id) { 02770 OSL_warning("inconsistency of array identifiers in an " 02771 "union of access relations"); 02772 return OSL_UNDEFINED; 02773 } 02774 } 02775 02776 relation = relation->next; 02777 } 02778 02779 return array_id; 02780 } 02781 02782 02790 int osl_relation_is_access(osl_relation_p relation) { 02791 02792 if (relation == NULL) 02793 return 0; 02794 02795 if ((relation->type == OSL_TYPE_ACCESS) || 02796 (relation->type == OSL_TYPE_READ) || 02797 (relation->type == OSL_TYPE_WRITE) || 02798 (relation->type == OSL_TYPE_MAY_WRITE)) 02799 return 1; 02800 02801 return 0; 02802 } 02803 02804 02823 void osl_relation_get_attributes(osl_relation_p relation, 02824 int * nb_parameters, 02825 int * nb_iterators, 02826 int * nb_scattdims, 02827 int * nb_localdims, 02828 int * array_id) { 02829 int type; 02830 int local_nb_parameters = OSL_UNDEFINED; 02831 int local_nb_iterators = OSL_UNDEFINED; 02832 int local_nb_scattdims = OSL_UNDEFINED; 02833 int local_nb_localdims = OSL_UNDEFINED; 02834 int local_array_id = OSL_UNDEFINED; 02835 02836 while (relation != NULL) { 02837 if (osl_relation_is_access(relation)) 02838 type = OSL_TYPE_ACCESS; 02839 else 02840 type = relation->type; 02841 02842 // There is some redundancy but I believe the code is cleaner this way. 02843 switch (type) { 02844 case OSL_TYPE_CONTEXT: 02845 local_nb_parameters = relation->nb_parameters; 02846 local_nb_iterators = 0; 02847 local_nb_scattdims = 0; 02848 local_nb_localdims = relation->nb_local_dims; 02849 local_array_id = 0; 02850 break; 02851 02852 case OSL_TYPE_DOMAIN: 02853 local_nb_parameters = relation->nb_parameters; 02854 local_nb_iterators = relation->nb_output_dims; 02855 local_nb_scattdims = 0; 02856 local_nb_localdims = relation->nb_local_dims; 02857 local_array_id = 0; 02858 break; 02859 02860 case OSL_TYPE_SCATTERING: 02861 local_nb_parameters = relation->nb_parameters; 02862 local_nb_iterators = relation->nb_input_dims; 02863 local_nb_scattdims = relation->nb_output_dims; 02864 local_nb_localdims = relation->nb_local_dims; 02865 local_array_id = 0; 02866 break; 02867 02868 case OSL_TYPE_ACCESS: 02869 local_nb_parameters = relation->nb_parameters; 02870 local_nb_iterators = relation->nb_input_dims; 02871 local_nb_scattdims = 0; 02872 local_nb_localdims = relation->nb_local_dims; 02873 local_array_id = osl_relation_get_array_id(relation); 02874 break; 02875 02876 default: 02877 local_nb_parameters = relation->nb_parameters; 02878 local_nb_iterators = relation->nb_input_dims; 02879 local_nb_scattdims = relation->nb_output_dims; 02880 local_nb_localdims = relation->nb_local_dims; 02881 local_array_id = 0; 02882 } 02883 02884 // Update. 02885 *nb_parameters = OSL_max(*nb_parameters, local_nb_parameters); 02886 *nb_iterators = OSL_max(*nb_iterators, local_nb_iterators); 02887 *nb_scattdims = OSL_max(*nb_scattdims, local_nb_scattdims); 02888 *nb_localdims = OSL_max(*nb_localdims, local_nb_localdims); 02889 *array_id = OSL_max(*array_id, local_array_id); 02890 relation = relation->next; 02891 } 02892 } 02893 02894 02906 osl_relation_p osl_relation_extend_output(osl_relation_p relation, int dim) { 02907 int i, j; 02908 int first = 1; 02909 int offset; 02910 int precision = relation->precision; 02911 osl_relation_p extended = NULL, node, previous = NULL; 02912 02913 while (relation != NULL) { 02914 if (relation->nb_output_dims > dim) 02915 OSL_error("Number of output dims is greater than required extension"); 02916 offset = dim - relation->nb_output_dims; 02917 02918 node = osl_relation_pmalloc(precision, 02919 relation->nb_rows + offset, 02920 relation->nb_columns + offset); 02921 02922 node->type = relation->type; 02923 node->nb_output_dims = OSL_max(relation->nb_output_dims, dim); 02924 node->nb_input_dims = relation->nb_input_dims; 02925 node->nb_local_dims = relation->nb_local_dims; 02926 node->nb_parameters = relation->nb_parameters; 02927 02928 // Copy of the original relation with some 0 columns for the new dimensions 02929 // Note that we use the fact that the matrix is initialized with zeros. 02930 for (i = 0; i < relation->nb_rows; i++) { 02931 for (j = 0; j <= relation->nb_output_dims; j++) 02932 osl_int_assign(precision, &node->m[i][j], relation->m[i][j]); 02933 02934 for (j = relation->nb_output_dims + offset + 1; 02935 j < relation->nb_columns + offset; j++) 02936 osl_int_assign(precision, &node->m[i][j], relation->m[i][j - offset]); 02937 } 02938 02939 // New rows dedicated to the new dimensions 02940 for (i = relation->nb_rows; i < relation->nb_rows + offset; i++) { 02941 for (j = 0; j < relation->nb_columns + offset; j++) { 02942 if ((i - relation->nb_rows) == (j - relation->nb_output_dims - 1)) 02943 osl_int_set_si(precision, &node->m[i][j], -1); 02944 } 02945 } 02946 02947 if (first) { 02948 first = 0; 02949 extended = node; 02950 previous = node; 02951 } 02952 else { 02953 previous->next = node; 02954 previous = previous->next; 02955 } 02956 02957 relation = relation->next; 02958 } 02959 02960 return extended; 02961 } 02962 02963 02970 osl_interface_p osl_relation_interface() { 02971 osl_interface_p interface = osl_interface_malloc(); 02972 02973 OSL_strdup(interface->URI, OSL_URI_RELATION); 02974 interface->idump = (osl_idump_f)osl_relation_idump; 02975 interface->sprint = (osl_sprint_f)osl_relation_sprint; 02976 interface->sread = (osl_sread_f)osl_relation_sread; 02977 interface->malloc = (osl_malloc_f)osl_relation_malloc; 02978 interface->free = (osl_free_f)osl_relation_free; 02979 interface->clone = (osl_clone_f)osl_relation_clone; 02980 interface->equal = (osl_equal_f)osl_relation_equal; 02981 02982 return interface; 02983 }