OpenScop  0.9.0
scop.c
Go to the documentation of this file.
00001 
00002     /*+-----------------------------------------------------------------**
00003      **                       OpenScop Library                          **
00004      **-----------------------------------------------------------------**
00005      **                            scop.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 # include <stdlib.h>
00064 # include <stdio.h>
00065 # include <ctype.h>
00066 # include <string.h>
00067 
00068 #include <osl/macros.h>
00069 #include <osl/util.h>
00070 #include <osl/extensions/arrays.h>
00071 #include <osl/extensions/textual.h>
00072 #include <osl/strings.h>
00073 #include <osl/relation.h>
00074 #include <osl/interface.h>
00075 #include <osl/generic.h>
00076 #include <osl/statement.h>
00077 #include <osl/scop.h>
00078 
00079 
00080 /*+***************************************************************************
00081  *                         Structure display functions                       *
00082  *****************************************************************************/
00083 
00084 
00095 void osl_scop_idump(FILE * file, osl_scop_p scop, int level) {
00096   int j, first = 1;
00097 
00098   // Go to the right level.
00099   for (j = 0; j < level; j++)
00100     fprintf(file, "|\t");
00101 
00102   if (scop != NULL)
00103     fprintf(file, "+-- osl_scop_t\n");
00104   else
00105     fprintf(file, "+-- NULL scop\n");
00106 
00107   while (scop != NULL) {
00108     if (!first) {
00109       // Go to the right level.
00110       for (j = 0; j < level; j++)
00111         fprintf(file, "|\t");
00112       fprintf(file, "|   osl_scop_t\n");
00113     }
00114     else
00115       first = 0;
00116 
00117     // A blank line.
00118     for (j = 0; j <= level+1; j++)
00119       fprintf(file, "|\t");
00120     fprintf(file, "\n");
00121 
00122     // Print the version.
00123     for (j = 0; j < level; j++)
00124       fprintf(file, "|\t");
00125     fprintf(file, "|\tVersion: %d\n", scop->version);
00126 
00127     // A blank line.
00128     for (j = 0; j <= level+1; j++)
00129       fprintf(file, "|\t");
00130     fprintf(file, "\n");
00131 
00132     // Print the language.
00133     for (j = 0; j < level; j++)
00134       fprintf(file, "|\t");
00135     fprintf(file, "|\tLanguage: %s\n", scop->language);
00136 
00137     // A blank line.
00138     for (j = 0; j <= level+1; j++)
00139       fprintf(file, "|\t");
00140     fprintf(file, "\n");
00141 
00142     // Print the context of the scop.
00143     osl_relation_idump(file, scop->context, level+1);
00144 
00145     // Print the parameters.
00146     osl_generic_idump(file, scop->parameters, level+1);
00147 
00148     // Print the statements.
00149     osl_statement_idump(file, scop->statement, level+1);
00150 
00151     // Print the registered extension interfaces.
00152     osl_interface_idump(file, scop->registry, level+1);
00153 
00154     // Print the extensions.
00155     osl_generic_idump(file, scop->extension, level+1);
00156 
00157     scop = scop->next;
00158 
00159     // Next line.
00160     if (scop != NULL) {
00161       for (j = 0; j <= level; j++)
00162         fprintf(file, "|\t");
00163       fprintf(file, "V\n");
00164     }
00165   }
00166 
00167   // The last line.
00168   for (j = 0; j <= level; j++)
00169     fprintf(file, "|\t");
00170   fprintf(file, "\n");
00171 }
00172 
00173 
00181 void osl_scop_dump(FILE * file, osl_scop_p scop) {
00182   osl_scop_idump(file, scop, 0);
00183 }
00184 
00185 
00193 osl_names_p osl_scop_names(osl_scop_p scop) {
00194   int nb_parameters = OSL_UNDEFINED;
00195   int nb_iterators  = OSL_UNDEFINED;
00196   int nb_scattdims  = OSL_UNDEFINED;
00197   int nb_localdims  = OSL_UNDEFINED;
00198   int array_id      = OSL_UNDEFINED;
00199 
00200   osl_scop_get_attributes(scop, &nb_parameters, &nb_iterators,
00201                           &nb_scattdims,  &nb_localdims, &array_id);
00202   
00203   return osl_names_generate("P", nb_parameters,
00204                             "i", nb_iterators,
00205                             "c", nb_scattdims,
00206                             "l", nb_localdims,
00207                             "A", array_id);
00208 }
00209 
00210 
00218 void osl_scop_print(FILE * file, osl_scop_p scop) {
00219   int parameters_backedup = 0;
00220   int arrays_backedup = 0;
00221   osl_strings_p parameters_backup = NULL;
00222   osl_strings_p arrays_backup = NULL;
00223   osl_names_p names;
00224   osl_arrays_p arrays;
00225 
00226   if (scop == NULL) {
00227     fprintf(file, "# NULL scop\n");
00228     return;
00229   }
00230   else {
00231     fprintf(file, "# [File generated by the OpenScop Library %s]\n",
00232             OSL_RELEASE);
00233   }
00234 
00235   if (osl_scop_integrity_check(scop) == 0)
00236     OSL_warning("OpenScop integrity check failed. Something may go wrong.");
00237   
00238   // Generate the names for the various dimensions.
00239   names = osl_scop_names(scop);
00240 
00241   while (scop != NULL) {
00242     // If possible, replace parameter names with scop parameter names.
00243     if (osl_generic_has_URI(scop->parameters, OSL_URI_STRINGS)) {
00244       parameters_backedup = 1;
00245       parameters_backup = names->parameters;
00246       names->parameters = scop->parameters->data;
00247     }
00248 
00249     // If possible, replace array names with arrays extension names.
00250     arrays = osl_generic_lookup(scop->extension, OSL_URI_ARRAYS);
00251     if (arrays != NULL) {
00252       arrays_backedup = 1;
00253       arrays_backup = names->arrays;
00254       names->arrays = osl_arrays_to_strings(arrays);
00255     }
00256 
00257     fprintf(file, "\n<"OSL_URI_SCOP">\n\n");
00258     fprintf(file, "# =============================================== "
00259                   "Global\n");
00260     fprintf(file, "# Language\n");
00261     fprintf(file, "%s\n\n", scop->language);
00262 
00263     fprintf(file, "# Context\n");
00264     osl_relation_pprint(file, scop->context, names);
00265     fprintf(file, "\n");
00266 
00267     osl_util_print_provided(file,
00268         osl_generic_has_URI(scop->parameters, OSL_URI_STRINGS),
00269         "Parameters are");
00270     osl_generic_print(file, scop->parameters);
00271 
00272     fprintf(file, "\n# Number of statements\n");
00273     fprintf(file, "%d\n\n",osl_statement_number(scop->statement));
00274 
00275     osl_statement_pprint(file, scop->statement, names);
00276 
00277     if (scop->extension) {
00278       fprintf(file, "# =============================================== "
00279                     "Extensions\n");
00280       osl_generic_print(file, scop->extension);
00281     }
00282     fprintf(file, "\n</"OSL_URI_SCOP">\n\n");
00283     
00284     // If necessary, switch back parameter names.
00285     if (parameters_backedup) {
00286       parameters_backedup = 0;
00287       names->parameters = parameters_backup;
00288     }
00289 
00290     // If necessary, switch back array names.
00291     if (arrays_backedup) {
00292       arrays_backedup = 0;
00293       osl_strings_free(names->arrays);
00294       names->arrays = arrays_backup;
00295     }
00296 
00297     scop = scop->next;
00298   }
00299 
00300   osl_names_free(names);
00301 }
00302 
00303 
00311 void osl_scop_print_scoplib(FILE * file, osl_scop_p scop) {
00312   int parameters_backedup = 0;
00313   int arrays_backedup = 0;
00314   osl_strings_p parameters_backup = NULL;
00315   osl_strings_p arrays_backup = NULL;
00316   osl_names_p names;
00317   osl_arrays_p arrays;
00318 
00319   if (scop == NULL) {
00320     fprintf(file, "# NULL scop\n");
00321     return;
00322   }
00323   else {
00324     fprintf(file, "# [File generated by the OpenScop Library %s]\n"
00325                   "# [SCoPLib format]\n",
00326                   OSL_RELEASE);
00327   }
00328 
00329   if (osl_scop_check_compatible_scoplib(scop) == 0) {
00330     OSL_error("SCoP integrity check failed. Something may go wrong.");
00331     exit(1);
00332   }
00333   
00334   // Generate the names for the various dimensions.
00335   names = osl_scop_names(scop);
00336 
00337   while (scop != NULL) {
00338     // If possible, replace parameter names with scop parameter names.
00339     if (osl_generic_has_URI(scop->parameters, OSL_URI_STRINGS)) {
00340       parameters_backedup = 1;
00341       parameters_backup = names->parameters;
00342       names->parameters = scop->parameters->data;
00343     }
00344 
00345     // If possible, replace array names with arrays extension names.
00346     arrays = osl_generic_lookup(scop->extension, OSL_URI_ARRAYS);
00347     if (arrays != NULL) {
00348       arrays_backedup = 1;
00349       arrays_backup = names->arrays;
00350       names->arrays = osl_arrays_to_strings(arrays);
00351     }
00352 
00353     fprintf(file, "\nSCoP\n\n");
00354     fprintf(file, "# =============================================== "
00355                   "Global\n");
00356     fprintf(file, "# Language\n");
00357     fprintf(file, "%s\n\n", scop->language);
00358 
00359     fprintf(file, "# Context\n");
00360 
00361     osl_relation_pprint_scoplib(file, scop->context, names, 0, 0);
00362     fprintf(file, "\n");
00363 
00364     osl_util_print_provided(file,
00365         osl_generic_has_URI(scop->parameters, OSL_URI_STRINGS),
00366         "Parameters are");
00367         
00368     if (scop->parameters) {
00369       fprintf(file, "# Parameter names\n");
00370       osl_strings_print(file, scop->parameters->data);
00371     }
00372 
00373     fprintf(file, "\n# Number of statements\n");
00374     fprintf(file, "%d\n\n",osl_statement_number(scop->statement));
00375 
00376     osl_statement_pprint_scoplib(file, scop->statement, names);
00377 
00378     if (scop->extension) {
00379       fprintf(file, "# =============================================== "
00380                     "Options\n");
00381       osl_generic_print_options_scoplib(file, scop->extension);
00382     }
00383     
00384     // If necessary, switch back parameter names.
00385     if (parameters_backedup) {
00386       parameters_backedup = 0;
00387       names->parameters = parameters_backup;
00388     }
00389 
00390     // If necessary, switch back array names.
00391     if (arrays_backedup) {
00392       arrays_backedup = 0;
00393       osl_strings_free(names->arrays);
00394       names->arrays = arrays_backup;
00395     }
00396 
00397     scop = scop->next;
00398   }
00399 
00400   osl_names_free(names);
00401 }
00402 
00403 
00404 /*****************************************************************************
00405  *                               Reading function                            *
00406  *****************************************************************************/
00407 
00408 
00421 osl_scop_p osl_scop_pread(FILE * file, osl_interface_p registry,
00422                           int precision) {
00423   osl_scop_p list = NULL, current = NULL, scop;
00424   osl_statement_p stmt = NULL;
00425   osl_statement_p prev = NULL;
00426   osl_strings_p language;
00427   int nb_statements;
00428   char * tmp;
00429   int first = 1;
00430   int i;
00431 
00432   if (file == NULL)
00433     return NULL;
00434 
00435   while(1) {
00436     //
00437     // I. START TAG
00438     //
00439     tmp = osl_util_read_uptotag(file, NULL, OSL_URI_SCOP);
00440     if (tmp == NULL) {
00441       OSL_debug("no more scop in the file");
00442       break;
00443     }
00444     else {
00445       free(tmp);
00446     }
00447 
00448     scop = osl_scop_malloc();
00449     scop->registry = osl_interface_clone(registry);
00450 
00451     //
00452     // II. CONTEXT PART
00453     //
00454 
00455     // Read the language.
00456     language = osl_strings_read(file);
00457     if (osl_strings_size(language) == 0)
00458       OSL_error("no language (backend) specified");
00459 
00460     if (osl_strings_size(language) > 1)
00461       OSL_warning("uninterpreted information (after language)");
00462 
00463     if (language != NULL) {
00464       OSL_strdup(scop->language, language->string[0]);
00465       osl_strings_free(language);
00466     }
00467 
00468     // Read the context domain.
00469     scop->context = osl_relation_pread(file, precision);
00470 
00471     // Read the parameters.
00472     if (osl_util_read_int(file, NULL) > 0)
00473       scop->parameters = osl_generic_read_one(file, scop->registry);
00474 
00475     //
00476     // III. STATEMENT PART
00477     //
00478 
00479     // Read the number of statements.
00480     nb_statements = osl_util_read_int(file, NULL);
00481 
00482     for (i = 0; i < nb_statements; i++) {
00483       // Read each statement.
00484       stmt = osl_statement_pread(file, scop->registry, precision);
00485       if (scop->statement == NULL)
00486         scop->statement = stmt;
00487       else
00488         prev->next = stmt;
00489       prev = stmt;
00490     }
00491 
00492     //
00493     // IV. EXTENSION PART (TO THE END TAG)
00494     //
00495 
00496     // Read up the end tag (if any), and store extensions.
00497     scop->extension = osl_generic_read(file, scop->registry);
00498 
00499     // Add the new scop to the list.
00500     if (first) {
00501       list = scop;
00502       first = 0;
00503     }
00504     else {
00505       current->next = scop;
00506     }
00507     current = scop;    
00508   }
00509   
00510   if (!osl_scop_integrity_check(list))
00511     OSL_warning("scop integrity check failed");
00512 
00513   return list;
00514 }
00515 
00516 
00525 osl_scop_p osl_scop_read(FILE * foo) {
00526   int precision = osl_util_get_precision();
00527   osl_interface_p registry = osl_interface_get_default_registry();
00528   osl_scop_p scop = osl_scop_pread(foo, registry, precision);
00529 
00530   osl_interface_free(registry);
00531   return scop;
00532 }
00533 
00534 
00535 /*+***************************************************************************
00536  *                   Memory allocation/deallocation functions                *
00537  *****************************************************************************/
00538 
00539 
00547 osl_scop_p osl_scop_malloc() {
00548   osl_scop_p scop;
00549 
00550   OSL_malloc(scop, osl_scop_p, sizeof(osl_scop_t));
00551   scop->version        = 1;
00552   scop->language       = NULL;
00553   scop->context        = NULL;
00554   scop->parameters     = NULL;
00555   scop->statement      = NULL;
00556   scop->registry       = NULL;
00557   scop->extension      = NULL;
00558   scop->usr            = NULL;
00559   scop->next           = NULL;
00560 
00561   return scop;
00562 }
00563 
00564 
00570 void osl_scop_free(osl_scop_p scop) {
00571   osl_scop_p tmp;
00572   
00573   while (scop != NULL) {
00574     if (scop->language != NULL)
00575       free(scop->language);
00576     osl_generic_free(scop->parameters);
00577     osl_relation_free(scop->context);
00578     osl_statement_free(scop->statement);
00579     osl_interface_free(scop->registry);
00580     osl_generic_free(scop->extension);
00581 
00582     tmp = scop->next;
00583     free(scop);
00584     scop = tmp;
00585   }
00586 }
00587 
00588 
00589 /*+***************************************************************************
00590  *                            Processing functions                           *
00591  *****************************************************************************/
00592 
00593 
00601 void osl_scop_add(osl_scop_p * location, osl_scop_p scop) {
00602   while (*location != NULL)
00603     location = &((*location)->next);
00604 
00605   *location = scop;
00606 }
00607 
00608 
00616 size_t osl_scop_number(osl_scop_p scop) {
00617   size_t number = 0;
00618 
00619   while (scop != NULL) {
00620     number++;
00621     scop = scop->next;
00622   }
00623   return number;
00624 }
00625 
00626 
00635 osl_scop_p osl_scop_clone(osl_scop_p scop) {
00636   osl_scop_p clone = NULL, node, previous = NULL;
00637   int first = 1;
00638   
00639   while (scop != NULL) {
00640     node                 = osl_scop_malloc();
00641     node->version        = scop->version;
00642     if (scop->language != NULL)
00643       OSL_strdup(node->language, scop->language);
00644     node->context        = osl_relation_clone(scop->context);
00645     node->parameters     = osl_generic_clone(scop->parameters);
00646     node->statement      = osl_statement_clone(scop->statement);
00647     node->registry       = osl_interface_clone(scop->registry);
00648     node->extension      = osl_generic_clone(scop->extension);
00649     
00650     if (first) {
00651       first = 0;
00652       clone = node;
00653       previous = node;
00654     }
00655     else {
00656       previous->next = node;
00657       previous = previous->next;
00658     }
00659 
00660     scop = scop->next;
00661   }
00662 
00663   return clone;
00664 }
00665 
00666 
00675 int osl_scop_equal(osl_scop_p s1, osl_scop_p s2) {
00676 
00677   while ((s1 != NULL) && (s2 != NULL)) {
00678     if (s1 == s2)
00679       return 1;
00680 
00681     if (s1->version != s2->version) {
00682       OSL_info("versions are not the same"); 
00683       return 0;
00684     }
00685 
00686     if (strcmp(s1->language, s2->language) != 0) {
00687       OSL_info("languages are not the same"); 
00688       return 0;
00689     }
00690 
00691     if (!osl_relation_equal(s1->context, s2->context)) {
00692       OSL_info("contexts are not the same"); 
00693       return 0;
00694     }
00695 
00696     if (!osl_generic_equal(s1->parameters, s2->parameters)) {
00697       OSL_info("parameters are not the same"); 
00698       return 0;
00699     }
00700 
00701     if (!osl_statement_equal(s1->statement, s2->statement)) {
00702       OSL_info("statements are not the same"); 
00703       return 0;
00704     }
00705 
00706     if (!osl_interface_equal(s1->registry, s2->registry)) {
00707       OSL_info("registries are not the same"); 
00708       return 0;
00709     }
00710 
00711     if (!osl_generic_equal(s1->extension, s2->extension)) {
00712       OSL_info("extensions are not the same"); 
00713       return 0;
00714     }
00715 
00716     s1 = s1->next;
00717     s2 = s2->next;
00718   }
00719   
00720   if (((s1 == NULL) && (s2 != NULL)) || ((s1 != NULL) && (s2 == NULL)))
00721     return 0;
00722 
00723   return 1;
00724 }
00725 
00726 
00734 int osl_scop_integrity_check(osl_scop_p scop) {
00735   int expected_nb_parameters;
00736 
00737 
00738   while (scop != NULL) {
00739     // Check the language.
00740     if ((scop->language != NULL) &&
00741         (!strcmp(scop->language, "caml")  || !strcmp(scop->language, "Caml") ||
00742          !strcmp(scop->language, "ocaml") || !strcmp(scop->language, "OCaml")))
00743       fprintf(stderr, "[OpenScop] Alert: What ?! Caml ?! Are you sure ?!?!\n");
00744 
00745     // Check the context.
00746     if (!osl_relation_integrity_check(scop->context,
00747                                       OSL_TYPE_CONTEXT,
00748                                       OSL_UNDEFINED,
00749                                       OSL_UNDEFINED,
00750                                       OSL_UNDEFINED))
00751       return 0;
00752 
00753     // Get the number of parameters.
00754     if (scop->context != NULL) 
00755       expected_nb_parameters = scop->context->nb_parameters;
00756     else
00757       expected_nb_parameters = OSL_UNDEFINED;
00758     
00759     // TODO : check the number of parameter strings.
00760 
00761     if (!osl_statement_integrity_check(scop->statement,
00762                                        expected_nb_parameters))
00763       return 0;
00764 
00765     scop = scop->next;
00766   }
00767 
00768   return 1;
00769 }
00770 
00771 
00779 int osl_scop_check_compatible_scoplib(osl_scop_p scop) {
00780   
00781   if (!osl_scop_integrity_check(scop))
00782     return 0;
00783   if (scop->next != NULL)
00784     return 0;
00785   if (scop == NULL || scop->statement == NULL)
00786     return 1;
00787   
00788   osl_relation_p domain;
00789   osl_statement_p statement;
00790   osl_relation_p scattering;
00791   int precision = scop->statement->scattering->precision;
00792   int i, j;
00793   
00794   statement = scop->statement;
00795   while (statement != NULL) {
00796     scattering = statement->scattering;
00797     
00798     if (scattering->nb_local_dims != 0) {
00799       OSL_error("Local dims in scattering matrix");
00800       return 0;
00801     }
00802     
00803     domain = statement->domain;
00804     while (domain != NULL) {
00805       if (domain->nb_local_dims != 0) {
00806         OSL_error("Local dims in domain matrix");
00807         return 0;
00808       }
00809       domain = domain->next;
00810     }
00811     
00812     // Check if there is only the -Identity in the output_dims
00813     // and the lines MUST be in the right order
00814     for (i = 0 ; i < scattering->nb_rows ; i++) {
00815       for (j = 0 ; j < scattering->nb_output_dims ; j++) {
00816         if (i == j) { // -1
00817           if (!osl_int_mone(precision, scattering->m[i][j+1])) {
00818             OSL_error("Wrong -Identity");
00819             return 0;
00820           }
00821         } else { // 0
00822           if (!osl_int_zero(precision, scattering->m[i][j+1])) {
00823             OSL_error("Wrong -Identity");
00824             return 0;
00825           }
00826         }
00827       }
00828     }
00829     
00830     statement = statement->next;
00831   }
00832 
00833   return 1;
00834 }
00835 
00836 
00843 int osl_scop_get_nb_parameters(osl_scop_p scop) {
00844 
00845   if (scop->context == NULL) {
00846     OSL_debug("no context domain, assuming 0 parameters");
00847     return 0;
00848   }
00849   else {
00850     return scop->context->nb_parameters;
00851   }
00852 }
00853 
00854 
00864 void osl_scop_register_extension(osl_scop_p scop, osl_interface_p interface) {
00865   osl_generic_p textual, new;
00866   char * extension_string;
00867 
00868   if ((interface != NULL) && (scop != NULL)) {
00869     osl_interface_add(&scop->registry, interface);
00870 
00871     textual = osl_generic_lookup(scop->extension, interface->URI);
00872     if (textual != NULL) {
00873       extension_string = ((osl_textual_p)textual->data)->textual;
00874       new = osl_generic_sread(&extension_string, interface);
00875       osl_generic_add(&scop->extension, new);
00876     }
00877   }
00878 }
00879 
00880 
00899 void osl_scop_get_attributes(osl_scop_p scop,
00900                              int * nb_parameters,
00901                              int * nb_iterators,
00902                              int * nb_scattdims,
00903                              int * nb_localdims,
00904                              int * array_id) {
00905   int local_nb_parameters = OSL_UNDEFINED;
00906   int local_nb_iterators  = OSL_UNDEFINED;
00907   int local_nb_scattdims  = OSL_UNDEFINED;
00908   int local_nb_localdims  = OSL_UNDEFINED;
00909   int local_array_id      = OSL_UNDEFINED;
00910 
00911   while (scop != NULL) {
00912     osl_relation_get_attributes(scop->context,
00913                                 &local_nb_parameters,
00914                                 &local_nb_iterators,
00915                                 &local_nb_scattdims,
00916                                 &local_nb_localdims,
00917                                 &local_array_id);
00918 
00919     osl_statement_get_attributes(scop->statement,
00920                                 &local_nb_parameters,
00921                                 &local_nb_iterators,
00922                                 &local_nb_scattdims,
00923                                 &local_nb_localdims,
00924                                 &local_array_id);
00925     // Update.
00926     *nb_parameters = OSL_max(*nb_parameters, local_nb_parameters);
00927     *nb_iterators  = OSL_max(*nb_iterators,  local_nb_iterators);
00928     *nb_scattdims  = OSL_max(*nb_scattdims,  local_nb_scattdims);
00929     *nb_localdims  = OSL_max(*nb_localdims,  local_nb_localdims);
00930     *array_id      = OSL_max(*array_id,      local_array_id);
00931     scop = scop->next;
00932   }
00933 }
00934 
00935 
00943 void osl_scop_normalize_scattering(osl_scop_p scop) {
00944   int max_scattering_dims = 0;
00945   osl_statement_p statement;
00946   osl_relation_p extended;
00947 
00948   if ((scop != NULL) && (scop->statement != NULL)) {
00949     // Get the max number of scattering dimensions.
00950     statement = scop->statement;
00951     while (statement != NULL) {
00952       if (statement->scattering != NULL) {
00953         max_scattering_dims = OSL_max(max_scattering_dims,
00954                                       statement->scattering->nb_output_dims);
00955       }
00956       statement = statement->next;
00957     }
00958 
00959     // Normalize.
00960     statement = scop->statement;
00961     while (statement != NULL) {
00962       if (statement->scattering != NULL) {
00963         extended = osl_relation_extend_output(statement->scattering,
00964                                               max_scattering_dims);
00965         osl_relation_free(statement->scattering);
00966         statement->scattering = extended;
00967       }
00968       statement = statement->next;
00969     }
00970   }
00971 }
00972