Home | History | Annotate | Download | only in src
      1 /* Binary relations.
      2 
      3    Copyright (C) 2002, 2004-2005, 2009-2012 Free Software Foundation,
      4    Inc.
      5 
      6    This file is part of Bison, the GNU Compiler Compiler.
      7 
      8    This program is free software: you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation, either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     20 
     21 #include <config.h>
     22 #include "system.h"
     23 
     24 #include <bitsetv.h>
     25 
     26 #include "getargs.h"
     27 #include "relation.h"
     28 
     29 void
     30 relation_print (relation r, relation_node size, FILE *out)
     31 {
     32   relation_node i;
     33   relation_node j;
     34 
     35   for (i = 0; i < size; ++i)
     36     {
     37       fprintf (out, "%3lu: ", (unsigned long int) i);
     38       if (r[i])
     39 	for (j = 0; r[i][j] != END_NODE; ++j)
     40 	  fprintf (out, "%3lu ", (unsigned long int) r[i][j]);
     41       fputc ('\n', out);
     42     }
     43   fputc ('\n', out);
     44 }
     45 
     46 
     47 /*---------------------------------------------------------------.
     48 | digraph & traverse.                                            |
     49 |                                                                |
     50 | The following variables are used as common storage between the |
     51 | two.                                                           |
     52 `---------------------------------------------------------------*/
     53 
     54 static relation R;
     55 static relation_nodes INDEX;
     56 static relation_nodes VERTICES;
     57 static relation_node top;
     58 static relation_node infinity;
     59 static bitsetv F;
     60 
     61 static void
     62 traverse (relation_node i)
     63 {
     64   relation_node j;
     65   relation_node height;
     66 
     67   VERTICES[++top] = i;
     68   INDEX[i] = height = top;
     69 
     70   if (R[i])
     71     for (j = 0; R[i][j] != END_NODE; ++j)
     72       {
     73 	if (INDEX[R[i][j]] == 0)
     74 	  traverse (R[i][j]);
     75 
     76 	if (INDEX[i] > INDEX[R[i][j]])
     77 	  INDEX[i] = INDEX[R[i][j]];
     78 
     79 	bitset_or (F[i], F[i], F[R[i][j]]);
     80       }
     81 
     82   if (INDEX[i] == height)
     83     for (;;)
     84       {
     85 	j = VERTICES[top--];
     86 	INDEX[j] = infinity;
     87 
     88 	if (i == j)
     89 	  break;
     90 
     91 	bitset_copy (F[j], F[i]);
     92       }
     93 }
     94 
     95 
     96 void
     97 relation_digraph (relation r, relation_node size, bitsetv *function)
     98 {
     99   relation_node i;
    100 
    101   infinity = size + 2;
    102   INDEX = xcalloc (size + 1, sizeof *INDEX);
    103   VERTICES = xnmalloc (size + 1, sizeof *VERTICES);
    104   top = 0;
    105 
    106   R = r;
    107   F = *function;
    108 
    109   for (i = 0; i < size; i++)
    110     if (INDEX[i] == 0 && R[i])
    111       traverse (i);
    112 
    113   free (INDEX);
    114   free (VERTICES);
    115 
    116   *function = F;
    117 }
    118 
    119 
    120 /*-------------------------------------------.
    121 | Destructively transpose R_ARG, of size N.  |
    122 `-------------------------------------------*/
    123 
    124 void
    125 relation_transpose (relation *R_arg, relation_node n)
    126 {
    127   relation r = *R_arg;
    128   /* The result. */
    129   relation new_R = xnmalloc (n, sizeof *new_R);
    130   /* END_R[I] -- next entry of NEW_R[I]. */
    131   relation end_R = xnmalloc (n, sizeof *end_R);
    132   /* NEDGES[I] -- total size of NEW_R[I]. */
    133   size_t *nedges = xcalloc (n, sizeof *nedges);
    134   relation_node i;
    135   relation_node j;
    136 
    137   if (trace_flag & trace_sets)
    138     {
    139       fputs ("relation_transpose: input\n", stderr);
    140       relation_print (r, n, stderr);
    141     }
    142 
    143   /* Count. */
    144   for (i = 0; i < n; i++)
    145     if (r[i])
    146       for (j = 0; r[i][j] != END_NODE; ++j)
    147 	++nedges[r[i][j]];
    148 
    149   /* Allocate. */
    150   for (i = 0; i < n; i++)
    151     {
    152       relation_node *sp = NULL;
    153       if (nedges[i] > 0)
    154 	{
    155 	  sp = xnmalloc (nedges[i] + 1, sizeof *sp);
    156 	  sp[nedges[i]] = END_NODE;
    157 	}
    158       new_R[i] = sp;
    159       end_R[i] = sp;
    160     }
    161 
    162   /* Store. */
    163   for (i = 0; i < n; i++)
    164     if (r[i])
    165       for (j = 0; r[i][j] != END_NODE; ++j)
    166 	*end_R[r[i][j]]++ = i;
    167 
    168   free (nedges);
    169   free (end_R);
    170 
    171   /* Free the input: it is replaced with the result. */
    172   for (i = 0; i < n; i++)
    173     free (r[i]);
    174   free (r);
    175 
    176   if (trace_flag & trace_sets)
    177     {
    178       fputs ("relation_transpose: output\n", stderr);
    179       relation_print (new_R, n, stderr);
    180     }
    181 
    182   *R_arg = new_R;
    183 }
    184