Switch from matrix to relation data structure
[openscop.git] / source / scop.c
bloba508ba1c3dfbe714e64a1da2c9897baacf4d4fdc
2 /*+-----------------------------------------------------------------**
3 ** OpenScop Library **
4 **-----------------------------------------------------------------**
5 ** scop.c **
6 **-----------------------------------------------------------------**
7 ** First version: 30/04/2008 **
8 **-----------------------------------------------------------------**
11 *****************************************************************************
12 * OpenScop: Structures and formats for polyhedral tools to talk together *
13 *****************************************************************************
14 * ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__, *
15 * / / / // // // // / / / // // / / // / /|,_, *
16 * / / / // // // // / / / // // / / // / / / /\ *
17 * |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/ \ *
18 * | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\ \ /\ *
19 * | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\ *
20 * | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \ \ *
21 * | P |n| l | = | s | t |=| = |d| = | = | = | | |=| o | | \# \ \ *
22 * | H | | y | | e | o | | = |l| | | = | | | | G | | \ \ \ *
23 * | I | | | | e | | | | | | | | | | | | | \ \ \ *
24 * | T | | | | | | | | | | | | | | | | | \ \ \ *
25 * | E | | | | | | | | | | | | | | | | | \ \ \ *
26 * | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | / \* \ \ *
27 * | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/ \ \ / *
28 * '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' *
29 * *
30 * Copyright (C) 2008 University Paris-Sud 11 and INRIA *
31 * *
32 * (3-clause BSD license) *
33 * Redistribution and use in source and binary forms, with or without *
34 * modification, are permitted provided that the following conditions *
35 * are met: *
36 * *
37 * 1. Redistributions of source code must retain the above copyright notice, *
38 * this list of conditions and the following disclaimer. *
39 * 2. Redistributions in binary form must reproduce the above copyright *
40 * notice, this list of conditions and the following disclaimer in the *
41 * documentation and/or other materials provided with the distribution. *
42 * 3. The name of the author may not be used to endorse or promote products *
43 * derived from this software without specific prior written permission. *
44 * *
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
46 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
47 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
48 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
49 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
50 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
51 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
52 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
55 * *
56 * OpenScop Library, a library to manipulate OpenScop formats and data *
57 * structures. Written by: *
58 * Cedric Bastoul <Cedric.Bastoul@u-psud.fr> and *
59 * Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr> *
60 * *
61 *****************************************************************************/
63 # include <stdlib.h>
64 # include <stdio.h>
65 # include <ctype.h>
66 # include <string.h>
67 # include <openscop/scop.h>
70 /*+***************************************************************************
71 * Structure display functions *
72 *****************************************************************************/
75 /**
76 * openscop_scop_print_structure function:
77 * Displays a openscop_scop_t structure (*scop) into a file (file, possibly
78 * stdout) in a way that trends to be understandable without falling in a deep
79 * depression or, for the lucky ones, getting a headache... It includes an
80 * indentation level (level) in order to work with others print_structure
81 * functions.
82 * \param file File where informations are printed.
83 * \param scop The scop whose information have to be printed.
84 * \param level Number of spaces before printing, for each line.
86 void
87 openscop_scop_print_structure(FILE * file, openscop_scop_p scop, int level)
89 int i, j;
91 if (scop != NULL)
93 // Go to the right level.
94 for (j = 0; j < level; j++)
95 fprintf(file, "|\t");
96 fprintf(file, "+-- openscop_scop_t\n");
98 // A blank line.
99 for (j = 0; j <= level+1; j++)
100 fprintf(file, "|\t");
101 fprintf(file, "\n");
103 // Print the language.
104 for (j = 0; j < level; j++)
105 fprintf(file, "|\t");
106 fprintf(file, "|\tLanguage: %s\n", scop->language);
108 // A blank line.
109 for (j = 0; j <= level+1; j++)
110 fprintf(file, "|\t");
111 fprintf(file, "\n");
113 // Print the context of the scop.
114 openscop_relation_print_structure(file, scop->context, level+1);
116 // Print the original parameter names.
117 for (i = 0; i <= level; i++)
118 fprintf(file, "|\t");
119 if (scop->nb_parameters > 0)
121 fprintf(file, "+-- Parameter strings:");
122 for (i = 0; i < scop->nb_parameters; i++)
123 fprintf(file, " %s", scop->parameters[i]);
124 fprintf(file, "\n");
126 else
127 fprintf(file, "+-- No parameter strings\n");
129 // A blank line.
130 for (j = 0; j <= level+1; j++)
131 fprintf(file, "|\t");
132 fprintf(file, "\n");
134 // Print the iterator names.
135 for (i = 0; i <= level; i++)
136 fprintf(file, "|\t");
137 if (scop->nb_iterators > 0)
139 fprintf(file, "+-- Iterator strings:");
140 for (i = 0; i < scop->nb_iterators; i++)
141 fprintf(file, " %s", scop->iterators[i]);
142 fprintf(file, "\n");
144 else
145 fprintf(file,"+-- No iterator string\n");
147 // A blank line.
148 for (j = 0; j <= level+1; j++)
149 fprintf(file, "|\t");
150 fprintf(file, "\n");
152 // Print the scattering dimension names.
153 for (i = 0; i <= level; i++)
154 fprintf(file, "|\t");
155 if (scop->nb_scattdims > 0)
157 fprintf(file, "+-- Scattering dimension strings:");
158 for (i = 0; i < scop->nb_scattdims; i++)
159 fprintf(file, " %s", scop->scattdims[i]);
160 fprintf(file, "\n");
162 else
163 fprintf(file, "+-- No scattering dimension string\n");
165 // A blank line.
166 for (j = 0; j <= level+1; j++)
167 fprintf(file, "|\t");
168 fprintf(file, "\n");
170 // Print the statements.
171 openscop_statement_print_structure(file, scop->statement, level+1);
173 else
175 // Go to the right level.
176 for (j = 0; j < level; j++)
177 fprintf(file, "|\t");
178 fprintf(file, "+-- NULL scop\n");
181 // The last line.
182 for (j = 0; j <= level; j++)
183 fprintf(file, "|\t");
184 fprintf(file, "\n");
189 * openscop_scop_print function:
190 * This function prints the content of a openscop_scop_t structure (*scop) into
191 * a file (file, possibly stdout).
192 * \param file File where informations are printed.
193 * \param scop The scop whose information have to be printed.
195 void
196 openscop_scop_print(FILE * file, openscop_scop_p scop)
198 openscop_scop_print_structure(file, scop, 0);
203 * openscop_scop_print_openscop function:
204 * This function prints the content of a openscop_scop_t structure (*scop)
205 * into a file (file, possibly stdout) in the OpenScop format.
206 * \param file File where informations are printed.
207 * \param scop The scop whose information have to be printed.
209 void
210 openscop_scop_print_openscop(FILE * file, openscop_scop_p scop)
212 int i;
213 int nb_arrays = 0;
214 char ** arrays = NULL;
216 // Extract array names information.
217 arrays = openscop_util_read_tag_arrays(scop->extensions, &nb_arrays);
219 if (0)
221 fprintf(file, "# \n");
222 fprintf(file, "# <| \n");
223 fprintf(file, "# A \n");
224 fprintf(file, "# /.\\ \n");
225 fprintf(file, "# <| [\"\"M# \n");
226 fprintf(file, "# A | # Clan McCloog Castle \n");
227 fprintf(file, "# /.\\ [\"\"M# [Generated by the OpenScop ");
228 fprintf(file, "Library %s %s bits]\n",OPENSCOP_RELEASE, OPENSCOP_VERSION);
229 fprintf(file, "# [\"\"M# | # U\"U#U \n");
230 fprintf(file, "# | # | # \\ .:/ \n");
231 fprintf(file, "# | # | #___| # \n");
232 fprintf(file, "# | \"--' .-\" \n");
233 fprintf(file, "# |\"-\"-\"-\"-\"-#-#-## \n");
234 fprintf(file, "# | # ## ###### \n");
235 fprintf(file, "# \\ .::::'/ \n");
236 fprintf(file, "# \\ ::::'/ \n");
237 fprintf(file, "# :8a| # # ## \n");
238 fprintf(file, "# ::88a ### \n");
239 fprintf(file, "# ::::888a 8a ##::. \n");
240 fprintf(file, "# ::::::888a88a[]:::: \n");
241 fprintf(file, "# :::::::::SUNDOGa8a::::. .. \n");
242 fprintf(file, "# :::::8::::888:Y8888:::::::::... \n");
243 fprintf(file, "#::':::88::::888::Y88a______________________________");
244 fprintf(file, "________________________\n");
245 fprintf(file, "#:: ::::88a::::88a:Y88a ");
246 fprintf(file, " __---__-- __\n");
247 fprintf(file, "#' .: ::Y88a:::::8a:Y88a ");
248 fprintf(file, "__----_-- -------_-__\n");
249 fprintf(file, "# :' ::::8P::::::::::88aa. _ _- -");
250 fprintf(file, "- --_ --- __ --- __--\n");
251 fprintf(file, "#.:: :::::::::::::::::::Y88as88a...s88aa.\n");
253 else
255 fprintf(file, "# [File generated by the OpenScop Library %s %s bits]\n",
256 OPENSCOP_RELEASE,OPENSCOP_VERSION);
259 fprintf(file, "\nOpenScop\n\n");
260 fprintf(file, "# =============================================== Global\n");
261 fprintf(file, "# Language\n");
262 fprintf(file, "%s\n\n", scop->language);
264 fprintf(file, "# Context\n");
265 openscop_relation_print_openscop(file, scop->context, OPENSCOP_TYPE_DOMAIN,
266 0, NULL,
267 scop->nb_parameters, scop->parameters,
268 nb_arrays, arrays);
269 fprintf(file, "\n");
271 if (scop->nb_parameters > 0)
273 fprintf(file, "# Parameter names are provided\n");
274 fprintf(file, "1\n");
275 fprintf(file, "# Parameter names\n");
276 for (i = 0; i < scop->nb_parameters; i++)
277 fprintf(file, "%s ", scop->parameters[i]);
278 fprintf(file, "\n\n");
280 else
282 fprintf(file, "# Parameter names are not provided\n");
283 fprintf(file, "0\n\n");
286 if (scop->nb_iterators > 0)
288 fprintf(file, "# Iterator names are provided\n");
289 fprintf(file, "1\n");
290 fprintf(file, "# Iterator names\n");
291 for (i = 0; i < scop->nb_iterators; i++)
292 fprintf(file, "%s ", scop->iterators[i]);
293 fprintf(file, "\n\n");
295 else
297 fprintf(file, "# Iterator names are not provided\n");
298 fprintf(file, "0\n\n");
301 if (scop->nb_scattdims > 0)
303 fprintf(file, "# Scattering dimension names are provided\n");
304 fprintf(file, "1\n");
305 fprintf(file, "# Scattering dimension names\n");
306 for (i = 0; i < scop->nb_scattdims; i++)
307 fprintf(file, "%s ", scop->scattdims[i]);
308 fprintf(file, "\n\n");
310 else
312 fprintf(file, "# Scattering dimension names are not provided\n");
313 fprintf(file, "0\n\n");
316 fprintf(file, "# Number of statements\n");
317 fprintf(file, "%d\n\n",openscop_statement_number(scop->statement));
319 openscop_statement_print_openscop(file, scop->statement,
320 scop->nb_parameters, scop->parameters,
321 nb_arrays, arrays);
323 fprintf(file, "# =============================================== Options\n");
324 if (scop->extensions)
326 if (scop->textual_extensions)
327 fprintf(file, "%s", (char *)scop->extensions);
328 else
329 openscop_extension_print(file, (openscop_extension_p)scop->extensions);
332 // Free array names
333 if (nb_arrays != 0)
335 for (i = 0; i < nb_arrays; i++)
336 free(arrays[i]);
337 free(arrays);
342 /*****************************************************************************
343 * Reading function *
344 *****************************************************************************/
347 static
348 void
349 openscop_scop_update_val(int * variable, int value)
351 if ((*variable == OPENSCOP_UNDEFINED) || (*variable == value))
352 *variable = value;
353 else
354 fprintf(stderr, "[OpenScop] Warning: number of iterators and "
355 "parameters inconsistency.\n");
358 static
359 void
360 openscop_scop_update_properties(openscop_relation_p relation,
361 int nb_output_dims, int nb_input_dims,
362 int nb_parameters)
364 if (relation != NULL)
366 openscop_scop_update_val(&(relation->nb_output_dims), nb_output_dims);
367 openscop_scop_update_val(&(relation->nb_input_dims), nb_input_dims);
368 openscop_scop_update_val(&(relation->nb_parameters), nb_parameters);
374 * openscop_scop_propagate_properties internal function:
375 * This function tries to propagate information in all relations through the
376 * whole openscop representation. For instance, the number of parameters can
377 * be found in the context as well as in any relation: if it is undefined in
378 * the relation, this function defines it, if it is different than the
379 * expected value, it reports an error. This function does the same for
380 * the number of output and input dimensions.
381 * \param scop The SCoP we want to propagate properties.
383 static
384 void
385 openscop_scop_propagate_properties(openscop_scop_p scop)
387 int i, nb_parameters;
388 openscop_statement_p statement;
389 openscop_relation_p relation;
390 openscop_relation_list_p list;
392 // Context part: get the number of parameters.
393 if ((scop->context != NULL) &&
394 (openscop_relation_is_matrix(scop->context)))
396 nb_parameters = scop->context->nb_columns - 2;
397 openscop_scop_update_properties(scop->context, 0, 0, nb_parameters);
399 else
400 return;
402 // For each statement:
403 statement = scop->statement;
404 while (statement != NULL)
406 // - Domain part,
407 relation = statement->domain;
408 if (openscop_relation_is_matrix(relation))
410 while (relation != NULL)
412 openscop_scop_update_properties(relation,
413 relation->nb_columns - nb_parameters - 2, 0, nb_parameters);
414 relation = relation->next;
418 // - Scattering part,
419 relation = statement->scattering;
420 if (openscop_relation_is_matrix(relation))
422 while (relation != NULL)
424 openscop_scop_update_properties(relation,
425 0, relation->nb_columns - nb_parameters - 2, nb_parameters);
426 relation = relation->next;
430 // - Access part.
431 for (i = 0; i < 2; i++)
433 if (i == 0)
434 list = statement->read;
435 else
436 list = statement->write;
438 while (list != NULL)
440 relation = list->elt;
441 if (openscop_relation_is_matrix(relation))
443 while (relation != NULL)
445 openscop_scop_update_properties(relation,
446 0, relation->nb_columns - nb_parameters - 2, nb_parameters);
447 relation = relation->next;
451 list = list->next;
455 statement = statement->next;
461 * openscop_scop_read function:
462 * This function reads a openscop_scop_t structure from an input stream
463 * (possibly stdin) corresponding to an OpenScop input file. If some relation
464 * properties (number of input/output/local dimensions and number of
465 * parameters) are undefined, it will define them according to the available
466 * information.
467 * \param file The input stream
469 openscop_scop_p
470 openscop_scop_read(FILE * file)
472 openscop_scop_p scop = NULL;
473 openscop_statement_p stmt = NULL;
474 openscop_statement_p prev = NULL;
475 int nb_statements;
476 int max;
477 char ** tmp;
478 int i;
480 if (file == NULL)
481 return NULL;
483 scop = openscop_scop_malloc();
485 // Backup the arrays of the program. Buffer is reajustable.
486 /*int nb_arr = OPENSCOP_MAX_STRING;
487 char ** arrays = (char **) malloc (sizeof(char *) * nb_arr);
488 for (i = 0; i < nb_arr; ++i)
489 arrays[i] = NULL;
493 // I. CONTEXT PART
496 // Ensure the file is a .scop.
497 tmp = openscop_util_read_strings(file, 1, &max);
498 if ((max == 0) || (strcmp(*tmp, "OpenScop")))
500 fprintf(stderr, "[OpenScop] Error: not an OpenScop file "
501 "(type \"%s\".\n", *tmp);
502 exit (1);
504 if (max > 1)
505 fprintf(stderr, "[OpenScop] Warning: uninterpreted information "
506 "(after file type).\n");
507 free(*tmp);
508 free(tmp);
510 // Read the language.
511 char ** language = openscop_util_read_strings(file, 1, &max);
512 if (max == 0)
514 fprintf(stderr, "[OpenScop] Error: no language (backend) specified.\n");
515 exit (1);
517 if (max > 1)
518 fprintf(stderr, "[OpenScop] Warning: uninterpreted information "
519 "(after language).\n");
520 scop->language = *language;
521 free(language);
523 // Read the context.
524 scop->context = openscop_relation_read(file);
525 scop->nb_parameters = scop->context->nb_columns - 2;
527 // Read the parameter names, if any.
528 if (openscop_util_read_int(file, NULL) > 0)
530 scop->parameters = openscop_util_read_strings(file,
531 scop->nb_parameters, &max);
532 if (max < scop->nb_parameters)
534 fprintf(stderr, "[OpenScop] Error: not enough parameter names.\n");
535 exit (1);
537 if (max > scop->nb_parameters)
538 fprintf(stderr, "[OpenScop] Warning: uninterpreted information "
539 "(after parameter names).\n");
541 else
542 scop->parameters = NULL;
544 // Read the iterator names, if any.
545 if (openscop_util_read_int(file, NULL) > 0)
546 scop->iterators = openscop_util_read_strings(file, -1,
547 &(scop->nb_iterators));
548 else
550 scop->nb_iterators = 0;
551 scop->iterators = NULL;
554 // Read the scattering dimension names, if any.
555 if (openscop_util_read_int(file, NULL) > 0)
556 scop->scattdims = openscop_util_read_strings(file, -1,
557 &(scop->nb_scattdims));
558 else
560 scop->nb_scattdims = 0;
561 scop->scattdims = NULL;
565 // II. STATEMENT PART
568 // Read the number of statements.
569 nb_statements = openscop_util_read_int(file, NULL);
571 for (i = 0; i < nb_statements; ++i)
573 // Read each statement.
574 stmt = openscop_statement_read(file);
575 if (scop->statement == NULL)
576 scop->statement = stmt;
577 else
578 prev->next = stmt;
579 prev = stmt;
583 // III. OPTION PART
586 // Read the remainder of the file, and store it in the extensions field.
587 scop->textual_extensions = 1;
588 scop->extensions = (void *)openscop_extension_read_string(file);
591 // VI. FINALIZE AND CHECK
593 openscop_scop_propagate_properties(scop);
595 if (!openscop_scop_integrity_check(scop))
596 fprintf(stderr, "[OpenScop] Warning: global integrity check failed.\n");
598 return scop;
602 /*+***************************************************************************
603 * Memory allocation/deallocation functions *
604 *****************************************************************************/
608 * openscop_scop_malloc function:
609 * This function allocates the memory space for a openscop_scop_t structure and
610 * sets its fields with default values. Then it returns a pointer to the
611 * allocated space.
612 * \return A pointer to an empty scop with fields set to default values.
614 openscop_scop_p
615 openscop_scop_malloc()
617 openscop_scop_p scop;
619 scop = (openscop_scop_p)malloc(sizeof(openscop_scop_t));
620 if (scop == NULL)
622 fprintf(stderr, "[OpenScop] Memory Overflow.\n");
623 exit(1);
626 scop->version = 1;
627 scop->textual_names = 1;
628 scop->textual_extensions = 1;
629 scop->language = NULL;
630 scop->context = NULL;
631 scop->nb_parameters = 0;
632 scop->nb_iterators = 0;
633 scop->nb_scattdims = 0;
634 scop->parameters = NULL;
635 scop->iterators = NULL;
636 scop->scattdims = NULL;
637 scop->statement = NULL;
638 scop->extensions = NULL;
639 scop->usr = NULL;
641 return scop;
646 * openscop_scop_free function:
647 * This function frees the allocated memory for a openscop_scop_t structure.
648 * \param scop The pointer to the scop we want to free.
650 void
651 openscop_scop_free(openscop_scop_p scop)
653 int i;
655 if (scop != NULL)
657 if (scop->language != NULL)
658 free(scop->language);
660 openscop_relation_free(scop->context);
662 if (scop->parameters != NULL)
664 for (i = 0; i < scop->nb_parameters; i++)
665 free(scop->parameters[i]);
666 free(scop->parameters);
669 if (scop->iterators != NULL)
671 for (i = 0; i < scop->nb_iterators; i++)
672 free(scop->iterators[i]);
673 free(scop->iterators);
676 if (scop->scattdims != NULL)
678 for (i = 0; i < scop->nb_scattdims; i++)
679 free(scop->scattdims[i]);
680 free(scop->scattdims);
683 openscop_statement_free(scop->statement);
685 if (scop->textual_extensions)
686 free(scop->extensions);
687 else
688 openscop_extension_free((openscop_extension_p)scop->extensions);
690 free(scop);
695 /*+***************************************************************************
696 * Processing functions *
697 *****************************************************************************/
701 * openscop_scop_copy function:
702 * This functions builds and returns a "hard copy" (not a pointer copy)
703 * of a openscop_statement_t data structure provided as parameter.
704 * Note that the usr field is not touched by this function.
705 * \param statement The pointer to the scop we want to copy.
706 * \return A pointer to the full copy of the scop provided as parameter.
708 openscop_scop_p
709 openscop_scop_copy(openscop_scop_p scop)
711 openscop_scop_p copy;
713 copy = openscop_scop_malloc();
714 copy->textual_names = scop->textual_names;
715 copy->textual_extensions = scop->textual_extensions;
716 copy->version = scop->version;
717 copy->language = strdup(scop->language);
718 copy->context = openscop_relation_copy(scop->context);
719 copy->nb_parameters = scop->nb_parameters;
720 copy->nb_iterators = scop->nb_iterators;
721 copy->nb_scattdims = scop->nb_scattdims;
722 copy->parameters = openscop_util_copy_strings(scop->parameters,
723 scop->nb_parameters);
724 copy->iterators = openscop_util_copy_strings(scop->iterators,
725 scop->nb_iterators);
726 copy->scattdims = openscop_util_copy_strings(scop->scattdims,
727 scop->nb_scattdims);
728 copy->statement = openscop_statement_copy(scop->statement);
730 if (scop->textual_extensions)
731 copy->extensions = strdup((char *)scop->extensions);
732 else
733 copy->extensions = openscop_extension_copy((openscop_extension_p)
734 scop->extensions);
736 return copy;
741 * openscop_scop_equal function:
742 * this function returns true if the two scops are the same, false
743 * otherwise (the usr field is not tested).
744 * \param s1 The first scop.
745 * \param s2 The second scop.
746 * \return 1 if s1 and s2 are the same (content-wise), 0 otherwise.
749 openscop_scop_equal(openscop_scop_p s1, openscop_scop_p s2)
751 int i;
753 if (s1->version != s2->version)
755 fprintf(stderr, "[OpenScop] info: versions are not the same.\n");
756 //return 0;
759 if (strcmp(s1->language, s2->language) != 0)
761 fprintf(stderr, "[OpenScop] info: languages are not the same.\n");
762 return 0;
765 if (!openscop_relation_equal(s1->context, s2->context))
767 fprintf(stderr, "[OpenScop] info: contexts are not the same.\n");
768 return 0;
771 if (s1->nb_parameters != s2->nb_parameters)
773 fprintf(stderr, "[OpenScop] info: #parameters are not the same.\n");
774 return 0;
777 if (s1->nb_iterators != s2->nb_iterators)
779 fprintf(stderr, "[OpenScop] info: #iterators are not the same.\n");
780 return 0;
783 if (s1->nb_scattdims != s2->nb_scattdims)
785 fprintf(stderr, "[OpenScop] info: #scattdims are not the same.\n");
786 return 0;
789 if (!openscop_statement_equal(s1->statement, s2->statement))
791 fprintf(stderr, "[OpenScop] info: statements are not the same.\n");
792 return 0;
795 if ((s1->textual_extensions != s2->textual_extensions) ||
796 (s1->textual_extensions && strcmp(s1->extensions, s2->extensions)) ||
797 (!s1->textual_extensions && !openscop_extension_equal(s1->extensions,
798 s2->extensions)))
800 fprintf(stderr, "[OpenScop] info: extensions are not the same.\n");
801 return 0;
804 for (i = 0; i < s1->nb_parameters; i++)
805 if (strcmp(s1->parameters[i], s2->parameters[i]) != 0)
807 fprintf(stderr, "[OpenScop] info: parameter names are not the same.\n");
808 return 0;
811 for (i = 0; i < s1->nb_iterators; i++)
812 if (strcmp(s1->iterators[i], s2->iterators[i]) != 0)
814 fprintf(stderr, "[OpenScop] info: iterator names are not the same.\n");
815 return 0;
818 for (i = 0; i < s1->nb_scattdims; i++)
819 if (strcmp(s1->scattdims[i], s2->scattdims[i]) != 0)
821 fprintf(stderr, "[OpenScop] info: scattdims names are not the same.\n");
822 return 0;
825 return 1;
830 * openscop_scop_integrity_check function:
831 * This function checks that a scop is "well formed". It returns 0 if the
832 * check failed or 1 if no problem has been detected.
833 * \param scop The scop we want to check.
834 * \return 0 if the integrity check fails, 1 otherwise.
837 openscop_scop_integrity_check(openscop_scop_p scop)
839 int expected_nb_parameters;
840 int nb_iterators, max_nb_iterators = 0;
841 int max_nb_scattdims = 0;
842 openscop_statement_p statement;
844 // Check the language.
845 if ((scop->language != NULL) &&
846 (!strcmp(scop->language, "caml") || !strcmp(scop->language, "Caml") ||
847 !strcmp(scop->language, "ocaml") || !strcmp(scop->language, "OCaml")))
848 fprintf(stderr, "[OpenScop] Alert: Caml ?! Are you sure ?! ;)\n");
850 // Check the context.
851 if (!openscop_relation_integrity_check(scop->context,
852 OPENSCOP_TYPE_CONTEXT,
853 0, 0, OPENSCOP_UNDEFINED))
854 return 0;
856 // Get the number of parameters.
857 if (scop->context != NULL)
859 if (openscop_relation_is_matrix(scop->context))
860 expected_nb_parameters = scop->context->nb_columns - 2;
861 else
862 expected_nb_parameters = scop->context->nb_parameters;
864 else
865 expected_nb_parameters = OPENSCOP_UNDEFINED;
867 if (!openscop_statement_integrity_check(scop->statement,
868 expected_nb_parameters))
869 return 0;
871 // Ensure we have enough names.
872 if (expected_nb_parameters == OPENSCOP_UNDEFINED)
873 expected_nb_parameters = 0;
875 statement = scop->statement;
876 while (statement != NULL)
878 if (statement->domain != NULL)
880 if (openscop_relation_is_matrix(statement->domain))
882 nb_iterators = statement->domain->nb_columns -
883 expected_nb_parameters - 2;
884 if (nb_iterators > max_nb_iterators)
885 max_nb_iterators = nb_iterators;
887 else
889 if (statement->domain->nb_output_dims > max_nb_iterators)
890 max_nb_iterators = statement->domain->nb_output_dims;
894 if (statement->scattering != NULL)
896 if (openscop_relation_is_matrix(statement->scattering))
898 if (statement->domain->nb_rows > max_nb_scattdims)
899 max_nb_scattdims = statement->scattering->nb_rows;
901 else
903 if (statement->scattering->nb_input_dims > max_nb_scattdims)
904 max_nb_scattdims = statement->scattering->nb_input_dims;
908 statement = statement->next;
911 if ((scop->nb_iterators > 0) &&
912 (scop->nb_iterators < max_nb_iterators))
914 fprintf(stderr, "[OpenScop] Warning: not enough iterator names.\n");
915 return 0;
918 if ((scop->nb_scattdims > 0) &&
919 (scop->nb_scattdims < max_nb_scattdims))
921 fprintf(stderr, "[OpenScop] Warning: not enough scattering "
922 "dimension names.\n");
923 return 0;
926 return 1;