/* -*- C++ -*- * cpp_sym_decl.C * @(#) Symmetry Code Generation for Variabous Typedecl * * Copyright (C) 1992 - 1999 by the Board of Trustees of * Leland Stanford Junior University. * * License to use, copy, modify, sell and/or distribute this software * and its documentation any purpose is hereby granted without royalty, * subject to the following terms and conditions: * * 1. The above copyright notice and this permission notice must * appear in all copies of the software and related documentation. * * 2. The name of Stanford University may not be used in advertising or * publicity pertaining to distribution of the software without the * specific, prior written permission of Stanford. * * 3. This software may not be called "Murphi" if it has been modified * in any way, without the specific prior written permission of David L. * Dill. * * 4. THE SOFTWARE IS PROVIDED "AS-IS" AND STANFORD MAKES NO * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, BY WAY OF EXAMPLE, * BUT NOT LIMITATION. STANFORD MAKES NO REPRESENTATIONS OR WARRANTIES * OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE * USE OF THE SOFTWARE WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS * TRADEMARKS OR OTHER RIGHTS. STANFORD SHALL NOT BE LIABLE FOR ANY * LIABILITY OR DAMAGES WITH RESPECT TO ANY CLAIM BY LICENSEE OR ANY * THIRD PARTY ON ACCOUNT OF, OR ARISING FROM THE LICENSE, OR ANY * SUBLICENSE OR USE OF THE SOFTWARE OR ANY SERVICE OR SUPPORT. * * LICENSEE shall indemnify, hold harmless and defend STANFORD and its * trustees, officers, employees, students and agents against any and all * claims arising out of the exercise of any rights under this Agreement, * including, without limiting the generality of the foregoing, against * any damages, losses or liabilities whatsoever with respect to death or * injury to person or damage to property arising from or out of the * possession, use, or operation of Software or Licensed Program(s) by * LICENSEE or its customers. * * Read the file "license" distributed with these sources, or call * Murphi without the -l switch for additional information. * */ /* * Original Author: C. Norris Ip * Symmetry extension to Rel2.6 * Created: 20 Dec 1993 * * Update: * * Denis Leroy and Norris Ip * Subject: removed useless run-time checking, * reduced Limit functions * Last modified: 18 June 1995 * */ #include "mu.h" /******************** Main procedure to generate symmetry code for typedecl ********************/ void typedecl::generate_all_symmetry_decl(symmetryclass& symmetry) { if (next != NULL) { next->generate_all_symmetry_decl(symmetry); } generate_permute_function(); generate_simple_canon_function(symmetry); generate_canonicalize_function(symmetry); generate_simple_limit_function(symmetry); generate_array_limit_function(symmetry); generate_limit_function(symmetry); generate_multisetlimit_function(symmetry); } /******************** generate scalarset list ********************/ charlist * enumtypedecl::generate_scalarset_list(charlist * sl) { return sl; } charlist * subrangetypedecl::generate_scalarset_list(charlist * sl) { return sl; } charlist * scalarsettypedecl::generate_scalarset_list(charlist * sl) { if (getsize() > 1 ) { if (sl==NULL) return new charlist("", this, NULL); else { for (charlist * sv=sl; sv!=NULL; sv=sv->next) if (sv->e==this) return sl; return new charlist("", this, sl); } } else return sl; } charlist * uniontypedecl::generate_scalarset_list(charlist * sl) { stelist * t; typedecl * d; bool notexist; charlist * sv; for(t=getunionmembers(); t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1 ) { if (sl==NULL) sl = new charlist("", d, NULL); else { notexist = TRUE; for (sv=sl; sv!=NULL; sv=sv->next) if (sv->e==d) notexist = FALSE; if (notexist) sl = new charlist("", d, sl); } } } return sl; } charlist * multisettypedecl::generate_scalarset_list(charlist * sl) { sl = elementtype->generate_scalarset_list(sl); return sl; } charlist * arraytypedecl::generate_scalarset_list(charlist * sl) { sl = elementtype->generate_scalarset_list(sl); sl = indextype->generate_scalarset_list(sl); return sl; } charlist * recordtypedecl::generate_scalarset_list(charlist * sl) { ste *f; for (f = fields; f != NULL; f = f->next) sl = f->getvalue()->gettype()->generate_scalarset_list(sl); return sl; } /******************** generate permute() for each typedecl ********************/ void enumtypedecl::generate_permute_function() { if (already_generated_permute_function) return; else already_generated_permute_function = TRUE; if (strcmp(mu_name,"mu_0_boolean")!=0) fprintf(codefile, "void %s::Permute(PermSet& Perm, int i) {};\n", mu_name); }; void subrangetypedecl::generate_permute_function() { if (already_generated_permute_function) return; else already_generated_permute_function = TRUE; fprintf(codefile, "void %s::Permute(PermSet& Perm, int i) {};\n", mu_name); }; void scalarsettypedecl::generate_permute_function() { if (already_generated_permute_function) return; else already_generated_permute_function = TRUE; if (!useless && getsize() > 1) fprintf(codefile, "void %s::Permute(PermSet& Perm, int i)\n" "{\n" " if (Perm.Presentation != PermSet::Explicit)\n" " Error.Error(\"Internal Error: Wrong Sequence of Normalization\");\n" " if (defined())\n" " value(Perm.perm_%s[Perm.in_%s[i]][value()-%d]); // value - base\n" "};\n", mu_name, mu_name, mu_name, left); else fprintf(codefile, "void %s::Permute(PermSet& Perm, int i) {}\n", mu_name); } void uniontypedecl::generate_permute_function() { if (already_generated_permute_function) return; else already_generated_permute_function = TRUE; if (useless) { fprintf(codefile, "void %s::Permute(PermSet& Perm, int i) {}\n", mu_name); } else { fprintf(codefile, "void %s::Permute(PermSet& Perm, int i)\n" "{\n" " if (Perm.Presentation != PermSet::Explicit)\n" " Error.Error(\"Internal Error: Wrong Sequence of Normalization\");\n" " if (defined()) {\n", mu_name); stelist * t; typedecl * d; int thisright = getsize(); int thisleft; for(t=unionmembers; t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); thisleft = thisright-d->getsize()+1; if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1 ) fprintf(codefile, " if ( ( value() >= %d ) && ( value() <= %d ) )\n" " value(Perm.perm_%s[Perm.in_%s[i]][value()-%d]+(%d)); // value - base\n", // thisleft, thisright, // fixing union permutation bug d->getleft(), d->getright(), d->generate_code(), d->generate_code(), // thisleft, thisleft - d->getleft() // fixing union permutation bug d->getleft(), 0 ); thisright= thisleft-1; } fprintf(codefile, " }\n" "}\n" ); } } void multisettypedecl::generate_permute_function() { if (already_generated_permute_function) return; else already_generated_permute_function = TRUE; elementtype->generate_permute_function(); fprintf(codefile, "void %s::Permute(PermSet& Perm, int i)\n" "{\n" " static PerThread< %s > temp_( %s( \"Permute_%s\",-1 ) );\n" " %s &temp = temp_.get();\n" " int j;\n" " for (j=0; j<%d; j++)\n" " array[j].Permute(Perm, i);\n", mu_name, // %s::Permute mu_name, mu_name, mu_name, // %s temp("Permute_%s"... mu_name, maximum_size // j-for ); fprintf(codefile,"};\n"); } void arraytypedecl::generate_permute_function() { if (already_generated_permute_function) return; else already_generated_permute_function = TRUE; elementtype->generate_permute_function(); fprintf(codefile, "void %s::Permute(PermSet& Perm, int i)\n" "{\n" " static PerThread< %s > temp_( %s(\"Permute_%s\",-1) );\n" " %s &temp = temp_.get();\n" " int j;\n" " for (j=0; j<%d; j++)\n" " array[j].Permute(Perm, i);\n", mu_name, // %s::Permute mu_name, mu_name, mu_name, mu_name, // %s temp("Permute_%s"... indextype->getsize() // j-for ); if ( indextype->gettypeclass() == typedecl::Scalarset && indextype->getsize() > 1) { if (elementtype->issimple()) fprintf(codefile, " temp = *this;\n" " for (j=%d; j<=%d; j++)\n" " (*this)[j].value(temp[Perm.revperm_%s[Perm.in_%s[i]][j-%d]].value());", indextype->getleft(), indextype->getright(), // j-for indextype->mu_name, indextype->mu_name, indextype->getleft() ); else fprintf(codefile, " temp = *this;\n" " for (j=%d; j<=%d; j++)\n" " (*this)[j] = temp[Perm.revperm_%s[Perm.in_%s[i]][j-%d]];", indextype->getleft(), indextype->getright(), // j-for indextype->mu_name, indextype->mu_name, indextype->getleft() ); } if ( indextype->gettypeclass() == typedecl::Union && ((uniontypedecl *)indextype)->IsUnionWithScalarset() ) { stelist * t; typedecl * d; for(t=((uniontypedecl *)indextype)->getunionmembers(); t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1 ) { if (elementtype->issimple()) fprintf(codefile, " temp = *this;\n" " for (j=%d; j<=%d; j++)\n" " (*this)[j].value(temp[Perm.revperm_%s[Perm.in_%s[i]][j-%d]].value());\n", d->getleft(), d->getright(), // j-for d->mu_name, d->mu_name, d->getleft() ); else fprintf(codefile, " temp = *this;\n" " for (j=%d; j<=%d; j++)\n" " (*this)[j] = temp[Perm.revperm_%s[Perm.in_%s[i]][j-%d]];\n", d->getleft(), d->getright(), // j-for d->mu_name, d->mu_name, d->getleft() ); } } } fprintf(codefile,"};\n"); } void recordtypedecl::generate_permute_function() { ste *f; if (already_generated_permute_function) return; else already_generated_permute_function = TRUE; for (f = fields; f != NULL; f = f->next) f->getvalue()->gettype()->generate_permute_function(); fprintf(codefile, "void %s::Permute(PermSet& Perm, int i)\n" "{\n", mu_name ); for (f = fields; f != NULL; f = f->next) if (f->getvalue()->gettype()->getstructure() != NoScalarset && f->getvalue()->gettype()->getstructure() != MultisetOfFree) fprintf(codefile, " %s.Permute(Perm,i);\n", f->getvalue()->generate_code() ); fprintf(codefile,"};\n"); } /******************** supporting procedure for arraytypedecl ********************/ void arraytypedecl::generate_simple_sort() { stelist * t; typedecl * d; int thisright; int thisleft; if (indextype->gettypeclass() == typedecl::Scalarset && indextype->getsize() > 1) generate_simple_sort(indextype->getsize(), indextype->mu_name, indextype->getleft()); else if (indextype->gettypeclass() == typedecl::Union && ((uniontypedecl *)indextype)->IsUnionWithScalarset()) { thisright = indextype->getsize()-1; for(t=((uniontypedecl *)indextype)->getunionmembers(); t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); thisleft = thisright-d->getsize()+1; if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1 ) // generate_simple_sort(d->getsize(), d->mu_name, thisleft); generate_simple_sort(d->getsize(), d->mu_name, d->getleft()); thisright= thisleft-1; } } } void arraytypedecl::generate_simple_sort(int size, char * name, int left) { // please make sure that i,j,k,z can be modified fprintf(codefile, " // sorting %s\n" " // only if there is more than 1 permutation in class\n" " if (Perm.MTO_class_%s())\n" " {\n" " for (i=0; i<%d; i++)\n" " for (j=0; j<%d; j++)\n" " pos_%s[i][j]=FALSE;\n" " count_%s = 0;\n", name, // sorting %s name, // MTO_class_%s size, size, name, // i-for j-for pos_%s name // count_%s ); if (elementtype->issimple()) { fprintf(codefile, " for (i=0; i<%d; i++)\n" " {\n" " for (j=0; j0)\n" " {\n" " for (k=count_%s; k>j; k--)\n" " {\n" " value[k].value(value[k-1].value());\n" " for (z=0; z<%d; z++)\n" " pos_%s[k][z] = pos_%s[k-1][z];\n" " }\n" " value[j].value((*this)[i+%d].value());\n" " for (z=0; z<%d; z++)\n" " pos_%s[j][z] = FALSE;\n" " pos_%s[j][i] = TRUE;\n" " count_%s++;\n" " break;\n" " }\n" " }\n", name, // count_%s size, // z-for name, name, // pos_%s pos_%s left, // array[i+%d] size, // z-for name, // pos_%s name, // pos_%s name // count_%s ); fprintf(codefile, " if (j==count_%s)\n" " {\n" " value[j].value((*this)[i+%d].value());\n" " for (z=0; z<%d; z++)\n" " pos_%s[j][z] = FALSE;\n" " pos_%s[j][i] = TRUE;\n" " count_%s++;\n" " }\n" " }\n" " }\n", name, // count_%s left, size, // z-for name, // pos_%s name, // pos_%s name // count_%s ); } else { fprintf(codefile, " for (i=0; i<%d; i++)\n" " {\n" " for (j=0; j0)\n" " {\n" " for (k=count_%s; k>j; k--)\n" " {\n" " value[k] = value[k-1];\n" " for (z=0; z<%d; z++)\n" " pos_%s[k][z] = pos_%s[k-1][z];\n" " }\n" " value[j] = (*this)[i+%d];\n" " for (z=0; z<%d; z++)\n" " pos_%s[j][z] = FALSE;\n" " pos_%s[j][i] = TRUE;\n" " count_%s++;\n" " break;\n" " }\n" " }\n", name, // count_%s size, // z-for name, name, // pos_%s pos_%s left, size, // z-for name, // pos_%s name, // pos_%s name // count_%s ); fprintf(codefile, " if (j==count_%s)\n" " {\n" " value[j] = (*this)[i+%d];\n" " for (z=0; z<%d; z++)\n" " pos_%s[j][z] = FALSE;\n" " pos_%s[j][i] = TRUE;\n" " count_%s++;\n" " }\n" " }\n" " }\n", name, // count_%s left, size, // z-for name, // pos_%s name, // pos_%s name // count_%s ); } } void arraytypedecl::generate_limit() { stelist * t; typedecl * d; if (indextype->gettypeclass() == typedecl::Scalarset && indextype->getsize() > 1) generate_limit(indextype->getsize(), indextype->mu_name); else if (indextype->gettypeclass() == typedecl::Union && ((uniontypedecl *)indextype)->IsUnionWithScalarset()) { for(t=((uniontypedecl *)indextype)->getunionmembers(); t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1 ) generate_limit(d->getsize(), d->mu_name); } } } void arraytypedecl::generate_limit(int size, char * name) { // please make sure that i,j,k can be modified fprintf(codefile, " // if there is more than 1 permutation in class\n" " if (Perm.MTO_class_%s() && count_%s>1)\n" " {\n" " // limit\n" " for (j=0; j<%d; j++) // class priority\n" " {\n" " for (i=0; ij\n" " || ( Perm.class_%s[k] == j && !goodset_%s[k] ) )\n" " Perm.class_%s[k]++;\n" " Perm.undefined_class_%s++;\n" " }\n" " }\n" " }\n" " }\n" " }\n", name, name, // if guard size, // j-for name, // count_%s size, name, // k-for goodset_%s size, // k-for name, name, // pos_%s, class_%s name, // goodset_%s name, // pos_%s size, // k-for name, name, // class_%s, goodset_%s size, // k-for name, // class_%s name, name, // class_%s, goodset_%s name, // class_%s name // undefined_class_%s ); } void arraytypedecl::generate_limit2(char * var, typedecl * e) { stelist * t; typedecl * d; if (indextype->gettypeclass() == typedecl::Scalarset && indextype->getsize() > 1) generate_limit2(indextype->getsize(), indextype->mu_name, var, indextype->getleft()); else if (indextype->gettypeclass() == typedecl::Union && ((uniontypedecl *)indextype)->IsUnionWithScalarset()) { for(t=((uniontypedecl *)indextype)->getunionmembers(); t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1 ) generate_limit2(d->getsize(), d->mu_name, var, d->getleft()); } } } void arraytypedecl::generate_limit2(int size, char * name, char * var, int left) { // please make sure that i,j,k can be modified fprintf(codefile, "\n" " // refinement -- check undefine\n" " // only if there is more than 1 permutation in class\n" " if (Perm.MTO_class_%s() && count_%s<%d)\n" " {\n" " exists = FALSE;\n" " split = FALSE;\n" " // if there exists both defined value and undefined value\n" " for (k=0; k<%d; k++) // step through class\n" " if ((*this)[k+%d]%s.isundefined())\n" " exists = TRUE;\n" " else\n" " split = TRUE;\n" " if (exists && split)\n" " {\n" " for (i=0; ii; j--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[j][k] = pos_%s[j-1][k];\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[i][k] && !goodset_%s[k])\n" " pos_%s[i][k] = FALSE;\n" " if (pos_%s[i+1][k] && goodset_%s[k])\n" " pos_%s[i+1][k] = FALSE; \n" " }\n" " count_%s++; i++;\n" " }\n" " }\n" " }\n" " }\n" " }\n", name, name, size, // if guard size, // k-for left, var, // (*this)[k+%d]%s name, // count_%s size, name, // k-for goodset_%s size, // k-for name, left, var, // pos_%s, [k+%d], %s.isundefined() name, // goodset_%s size, // k-for name, name, // pos_%s goodset_%s name, // count_%s size, // k-for name, name, // pos_%s, pos_%s size, // k-for name, name, // pos_%s, goodset_%s name, // pos_%s name, name, // class_%s, goodset_%s name, // pos_%s name // count_%s ); } // added by Uli int multisettypedecl::get_num_limit_locals(typedecl * e) { int ret, temp; ste * f; switch (e->gettypeclass()) { case typedecl::Scalarset: case typedecl::Enum: case typedecl::Range: case typedecl::Union: return 0; case typedecl::Record: ret = 0; for (f = e->getfields(); f != NULL; f = f->next) { temp = get_num_limit_locals(f->getvalue()->gettype()); if (ret < temp) ret = temp; } return ret; case typedecl::Array: return 1 + get_num_limit_locals(e->getelementtype()); default: abort(); } return 0; } int arraytypedecl::get_num_limit_locals(typedecl * e) { int ret, temp; ste * f; switch (e->gettypeclass()) { case typedecl::Scalarset: case typedecl::Enum: case typedecl::Range: case typedecl::Union: return 0; case typedecl::Record: ret = 0; for (f = e->getfields(); f != NULL; f = f->next) { temp = get_num_limit_locals(f->getvalue()->gettype()); if (ret < temp) ret = temp; } return ret; case typedecl::Array: return 1 + get_num_limit_locals(e->getelementtype()); default: abort(); } return 0; } void arraytypedecl::generate_limit_step1(int limit_strategy) { stelist * t; typedecl * d; if (indextype->gettypeclass() == typedecl::Scalarset && indextype->getsize() > 1) generate_limit_step2(indextype, "", elementtype,0,limit_strategy); else if (indextype->gettypeclass() == typedecl::Union && ((uniontypedecl *)indextype)->IsUnionWithScalarset()) { for(t=((uniontypedecl *)indextype)->getunionmembers(); t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1 ) generate_limit_step2(d, "", elementtype,0,limit_strategy); } } } void arraytypedecl::generate_limit_step2(typedecl * d, const char * var, typedecl * e, int local_num, int limit_strategy) { stelist * t; ste * f; typedecl * e2, * d2; // please check that scalarset of size 1 is handled by sort in the other routine if (e->gettypeclass() == typedecl::Scalarset && e->getsize() > 1) generate_limit_step3(d, var, e, limit_strategy, FALSE); else if (e->gettypeclass() == typedecl::Union && ((uniontypedecl *)e)->IsUnionWithScalarset()) { for(t=((uniontypedecl *)e)->getunionmembers(); t!= NULL; t=t->next) { d2 = (typedecl *)t->s->getvalue(); if (d2->gettypeclass() == typedecl::Scalarset && d2->getsize() > 1 ) generate_limit_step3(d, var, d2, limit_strategy, TRUE); } } else if (e->gettypeclass() == typedecl::Array) { e2 = e->getindextype(); switch (e2->gettypeclass()) { case typedecl::Scalarset: if (e2->getsize() == 1) generate_limit_step2(d, tsprintf("%s[mu_%s]",var,((scalarsettypedecl *)e2)->getidvalues()->getname()->getname()), e->getelementtype(), local_num, limit_strategy); break; case typedecl::Union: for(t=((uniontypedecl *)e2)->getunionmembers(); t!= NULL; t=t->next) { d2 = (typedecl *)t->s->getvalue(); switch (d2->gettypeclass()) { case typedecl::Enum: for (f = ((enumtypedecl *) d2)->getidvalues(); f!=NULL && type_equal( f->getvalue()->gettype(), d2); f = f->getnext()) generate_limit_step2(d, tsprintf("%s[mu_%s]",var,f->getname()->getname()), e->getelementtype(), local_num, limit_strategy); break; case typedecl::Range: fprintf(codefile, " // loop through elements of a array indexed by subrange(union)\n" " for (i%d = %d; i%d <= %d; i%d++)\n" " {\n", local_num, d2->getleft(), local_num, d2->getright(), local_num); generate_limit_step2(d, tsprintf("%s[i%d]",var,local_num), e->getelementtype(), local_num+1, limit_strategy); fprintf(codefile, " }\n"); break; default: abort(); } } case typedecl::Enum: for (f = ((enumtypedecl *)e2)->getidvalues(); f!=NULL && type_equal( f->getvalue()->gettype(), e2); f = f->getnext()) generate_limit_step2(d, tsprintf("%s[mu_%s]",var,f->getname()->getname()), e->getelementtype(), local_num, limit_strategy); break; case typedecl::Range: fprintf(codefile, " // loop through elements of a array indexed by subrange\n" " for (i%d = %d; i%d <= %d; i%d++)\n" " {\n", local_num, e2->getleft(), local_num, e2->getright(), local_num); generate_limit_step2(d, tsprintf("%s[i%d]",var,local_num), e->getelementtype(), local_num+1, limit_strategy); fprintf(codefile, " }\n"); break; default: abort(); } } else if (e->gettypeclass() == typedecl::Record) { for (f = e->getfields(); f != NULL; f = f->next) { generate_limit_step2(d, tsprintf("%s.mu_%s",var, f->getname()->getname()), f->getvalue()->gettype(), local_num, limit_strategy); } } } void arraytypedecl::generate_limit_step3(typedecl * d, const char * var, typedecl * e, int limit_strategy, bool isunion) { switch (limit_strategy) { case 3: if (e == d) generate_limit3(d->getsize(), d->mu_name, var, d->getleft()); break; case 4: if (e == d) generate_limit4(d->getsize(), d->mu_name, var, d->getleft(), isunion); break; case 5: if (e != d && e->getsize() > 1) generate_limit5(d->mu_name, d->getsize(), d->getleft(), var, e->mu_name, e->getsize(), e->getleft(), isunion); break; } } void arraytypedecl::generate_limit3(const char * var, typedecl * e) { stelist * t; typedecl * d; if (indextype->gettypeclass() == typedecl::Scalarset && indextype->getsize() > 1) generate_limit3(indextype, var, e); else if (indextype->gettypeclass() == typedecl::Union && ((uniontypedecl *)indextype)->IsUnionWithScalarset()) { for(t=((uniontypedecl *)indextype)->getunionmembers(); t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1 ) generate_limit3(d, var, e); } } } void arraytypedecl::generate_limit3(typedecl * d, const char * var, typedecl * e) { stelist * t; typedecl * d2; if (e == d) generate_limit3(d->getsize(), d->mu_name, var, d->getleft()); else if (e->gettypeclass() == typedecl::Union && ((uniontypedecl *)e)->IsUnionWithScalarset()) { for(t=((uniontypedecl *)e)->getunionmembers(); t!= NULL; t=t->next) { d2 = (typedecl *)t->s->getvalue(); if (d2 == d) generate_limit3(d->getsize(), d->mu_name, var, d2->getleft()); } } } void arraytypedecl::generate_limit3(int size, const char * name, const char * var, int left) { // please make sure that i,j,k can be modified fprintf(codefile, "\n" " // refinement -- check selfloop\n" " // only if there is more than 1 permutation in class\n" " if (Perm.MTO_class_%s() && count_%s<%d)\n" " {\n" " exists = FALSE;\n" " split = FALSE;\n" " // if there exists both self loop and non-self loop\n" " for (k=0; k<%d; k++) // step through class\n" " if ((*this)[k+%d]%s.isundefined()\n" " ||(*this)[k+%d]%s!=k+%d)\n" " exists = TRUE;\n" " else\n" " split = TRUE;\n" " if (exists && split)\n" " {\n" " for (i=0; ii; j--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[j][k] = pos_%s[j-1][k];\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[i][k] && !goodset_%s[k])\n" " pos_%s[i][k] = FALSE;\n" " if (pos_%s[i+1][k] && goodset_%s[k])\n" " pos_%s[i+1][k] = FALSE;\n" " }\n" " count_%s++; i++;\n" " }\n" " }\n" " }\n" " }\n" " }\n", name, name, size, // MTO_class count_%s<%d size, // k-for left, var, // (*this)[k]%s left, var, left, // (*this)[k]%s!=k+%d name, // count_%s size, name, // k-for goodset_%s size, // k-for name, // pos_%s left, var, // [i+%d]%s.isundefined() left, var, left, // [i+%d]%s== i+%d name, // goodset_%s size, // k-for name, name, // pos_%s goodset_%s name, // count_%s size, // k-for name, name, // pos_%s, pos_%s size, // k-for name, name, // pos_%s, goodset_%s name, // pos_%s name, name, // class_%s, goodset_%s name, // pos_%s name // count_%s ); } // void arraytypedecl::generate_limit4(int size, char * name, char * var, int left) // { // fprintf(codefile, // " // limit\n" // " // check priority in general\n" // " oldcount_%s = count_%s-1;\n" // " while (oldcount_%s != count_%s && count_%s<%d)\n" // " {\n" // " oldcount_%s = count_%s;\n" // " for (i=0; ii; j--)\n" // " for (k=0; k<%d; k++)\n" // " pos_%s[j][k] = pos_%s[j-1][k];\n" // " for (k=0; k<%d; k++)\n" // " {\n" // " if (pos_%s[i][k] && !goodset_%s[k])\n" // " pos_%s[i][k] = FALSE;\n" // " if (pos_%s[i+1][k] && goodset_%s[k])\n" // " pos_%s[i+1][k] = FALSE; \n" // " }\n" // " count_%s++;\n" // " }\n" // " }\n" // " }\n" // " }\n" // " }\n", // name, name, // oldcount_%s count_%s // name, name, name, size, // oldcount_%s count_%s count_%s<%d // name, name, // oldcount_%s count_%s // name, // count_%s // name, // count_%s // size, name, // k-for goodset_%s // size, // k-for // name, // pos_%s // left, var, // [i+%d]%s.isundefined() // left, var, left, // [i+%d]%s== i+%d // name, left, var, left, // pos_%s[j][array[k+%d]%s-%d] // name, // goodset_%s // // size, // k-for // name, name, // pos_%s goodset_%s // name, // count_%s // size, // k-for // name, name, // pos_%s, pos_%s // size, // k-for // // name, name, // pos_%s, goodset_%s // name, // pos_%s // name, name, // class_%s, goodset_%s // name, // pos_%s // name // count_%s // ); // } void arraytypedecl::generate_limit4(const char * var, typedecl * e) { stelist * t; typedecl * d; if (indextype->gettypeclass() == typedecl::Scalarset && indextype->getsize() > 1) generate_limit4(indextype, var, e); else if (indextype->gettypeclass() == typedecl::Union && ((uniontypedecl *)indextype)->IsUnionWithScalarset()) { for(t=((uniontypedecl *)indextype)->getunionmembers(); t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1 ) generate_limit4(d, var, e); } } } void arraytypedecl::generate_limit4(typedecl * d, const char * var, typedecl * e) { stelist * t; typedecl * d2; if (e->gettypeclass() == typedecl::Scalarset && e == d) generate_limit4(d->getsize(), d->mu_name, var, d->getleft(),FALSE); else if (e->gettypeclass() == typedecl::Union && ((uniontypedecl *)e)->IsUnionWithScalarset()) { for(t=((uniontypedecl *)e)->getunionmembers(); t!= NULL; t=t->next) { d2 = (typedecl *)t->s->getvalue(); if (d2 == d) fprintf(codefile, "\n" " // refinement -- graph structure for a single scalarset\n" " // as in array S1 of S1\n" " // only if there is more than 1 permutation in class\n" " if (Perm.MTO_class_%s() && count_%s<%d)\n" " {\n" " exists = FALSE;\n" " split = FALSE;\n" " for (k=0; k<%d; k++) // step through class\n" " if (!(*this)[k+%d]%s.isundefined()\n" " &&(*this)[k+%d]%s!=k+%d\n" " &&(*this)[k+%d]%s>=%d\n" " &&(*this)[k+%d]%s<=%d)\n" " exists = TRUE;\n" " if (exists)\n" " {\n" " for (i=0; i=%d\n" // extra checking " && (*this)[k+%d]%s<=%d\n" // extra checking " && pos_%s[j][(*this)[k+%d]%s-%d])\n" " {\n" " exists = TRUE;\n" " goodset_%s[k] = TRUE;\n" " }\n" " if (exists)\n" " {\n" " split=FALSE;\n" " for (k=0; k<%d; k++)\n" " if ( pos_%s[i][k] && !goodset_%s[k] ) \n" " split= TRUE;\n" " if (split)\n" " {\n" " for (j=count_%s; j>i; j--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[j][k] = pos_%s[j-1][k];\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[i][k] && !goodset_%s[k])\n" " pos_%s[i][k] = FALSE;\n" " if (pos_%s[i+1][k] && goodset_%s[k])\n" " pos_%s[i+1][k] = FALSE; \n" " }\n" " count_%s++;\n" " }\n" " }\n" " }\n" " }\n" " }\n" " }\n", d->mu_name, d->mu_name, d->getsize(), // MTO_class count_%s<%d d->getsize(), // k-for d->getleft(), var, // (*this)[k]%s d->getleft(), var, d->getleft(), // (*this)[k]%s==k+%d d->getleft(), var, d->getleft(), // (*this)[k]%s<%d d->getleft(), var, d->getright(), // (*this)[k]%s>%d d->mu_name, // count_%s d->mu_name, // count_%s d->getsize(), d->mu_name, // k-for goodset_%s d->getsize(), // k-for d->mu_name, // pos_%s d->getleft(), var, // [i+%d]%s.isundefined() d->getleft(), var, d->getleft(), // [i+%d]%s== i+%d d->getleft(), var, d->getleft(), // [i+%d]%s>=%d d->getleft(), var, d->getright(), // [i+%d]%s<=%d d->mu_name, d->getleft(), var, d->getleft(), // pos_%s[j][(*this)[k+%d]%s-%d] d->mu_name, // goodset_%s d->getsize(), // k-for d->mu_name, d->mu_name, // pos_%s goodset_%s d->mu_name, // count_%s d->getsize(), // k-for d->mu_name, d->mu_name, // pos_%s, pos_%s d->getsize(), // k-for d->mu_name, d->mu_name, // pos_%s, goodset_%s d->mu_name, // pos_%s d->mu_name, d->mu_name, // class_%s, goodset_%s d->mu_name, // pos_%s d->mu_name // count_%s ); } } } void arraytypedecl::generate_limit4(int size, const char * name, const char * var, int left, bool isunion) { if (isunion) fprintf(codefile, "\n" " // refinement -- graph structure for a single scalarset\n" " // as in array S1 of S1\n" " // only if there is more than 1 permutation in class\n" " if (Perm.MTO_class_%s() && count_%s<%d)\n" " {\n" " exists = FALSE;\n" " split = FALSE;\n" " for (k=0; k<%d; k++) // step through class\n" " if (!(*this)[k+%d]%s.isundefined()\n" " &&(*this)[k+%d]%s!=k+%d\n" " &&(*this)[k+%d]%s>=%d\n" " &&(*this)[k+%d]%s<=%d)\n" " exists = TRUE;\n" " if (exists)\n" " {\n" " for (i=0; i=%d\n" // extra checking " && (*this)[k+%d]%s<=%d\n" // extra checking " && pos_%s[j][(*this)[k+%d]%s-%d])\n" " {\n" " exists = TRUE;\n" " goodset_%s[k] = TRUE;\n" " }\n" " if (exists)\n" " {\n" " split=FALSE;\n" " for (k=0; k<%d; k++)\n" " if ( pos_%s[i][k] && !goodset_%s[k] ) \n" " split= TRUE;\n" " if (split)\n" " {\n" " for (j=count_%s; j>i; j--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[j][k] = pos_%s[j-1][k];\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[i][k] && !goodset_%s[k])\n" " pos_%s[i][k] = FALSE;\n" " if (pos_%s[i+1][k] && goodset_%s[k])\n" " pos_%s[i+1][k] = FALSE; \n" " }\n" " count_%s++;\n" " }\n" " }\n" " }\n" " }\n" " }\n" " }\n", name, name, size, // MTO_class count_%s<%d size, // k-for left, var, // (*this)[k]%s left, var, left, // (*this)[k]%s==k+%d left, var, left, // (*this)[k]%s<%d left, var, left+size-1, // (*this)[k]%s>%d name, // count_%s name, // count_%s size, name, // k-for goodset_%s size, // k-for name, // pos_%s left, var, // [i+%d]%s.isundefined() left, var, left, // [i+%d]%s== i+%d left, var, left, // [i+%d]%s>=%d left, var, left+size-1, // [i+%d]%s<=%d name, left, var, left, // pos_%s[j][(*this)[k+%d]%s-%d] name, // goodset_%s size, // k-for name, name, // pos_%s goodset_%s name, // count_%s size, // k-for name, name, // pos_%s, pos_%s size, // k-for name, name, // pos_%s, goodset_%s name, // pos_%s name, name, // class_%s, goodset_%s name, // pos_%s name // count_%s ); else fprintf(codefile, "\n" " // refinement -- graph structure for a single scalarset\n" " // as in array S1 of S1\n" " // only if there is more than 1 permutation in class\n" " if (Perm.MTO_class_%s() && count_%s<%d)\n" " {\n" " exists = FALSE;\n" " split = FALSE;\n" " // if there exists non-self/undefine loop\n" " for (k=0; k<%d; k++) // step through class\n" " if (!(*this)[k+%d]%s.isundefined()\n" " &&(*this)[k+%d]%s!=k+%d)\n" " exists = TRUE;\n" " if (exists)\n" " {\n" " for (i=0; ii; j--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[j][k] = pos_%s[j-1][k];\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[i][k] && !goodset_%s[k])\n" " pos_%s[i][k] = FALSE;\n" " if (pos_%s[i+1][k] && goodset_%s[k])\n" " pos_%s[i+1][k] = FALSE; \n" " }\n" " count_%s++;\n" " }\n" " }\n" " }\n" " }\n" " }\n" " }\n", name, name, size, // MTO_class count_%s<%d size, // k-for left, var, // (*this)[k]%s left, var, left, // (*this)[k]%s==k+%d name, // count_%s name, // count_%s size, name, // k-for goodset_%s size, // k-for name, // pos_%s left, var, // [i+%d]%s.isundefined() left, var, left, // [i+%d]%s== i+%d name, left, var, left, // pos_%s[j][(*this)[k+%d]%s-%d] name, // goodset_%s size, // k-for name, name, // pos_%s goodset_%s name, // count_%s size, // k-for name, name, // pos_%s, pos_%s size, // k-for name, name, // pos_%s, goodset_%s name, // pos_%s name, name, // class_%s, goodset_%s name, // pos_%s name // count_%s ); } void arraytypedecl::generate_limit5(const char * var, typedecl * e) { stelist * t; typedecl * d; if (indextype->gettypeclass() == typedecl::Scalarset && indextype->getsize() > 1) generate_limit5(indextype, var, e); else if (indextype->gettypeclass() == typedecl::Union && ((uniontypedecl *)indextype)->IsUnionWithScalarset() ) { for(t=((uniontypedecl *)indextype)->getunionmembers(); t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1) generate_limit5(d, var, e); } } } void arraytypedecl::generate_limit5(typedecl * d, const char * var, typedecl * e) { stelist * t; typedecl * d2; int thisright; int thisleft; if (e->gettypeclass() == typedecl::Scalarset && e!=d && e->getsize() > 1) generate_limit5(d->mu_name, d->getsize(), d->getleft(), var, e->mu_name, e->getsize(), e->getleft(),FALSE); else if (e->gettypeclass() == typedecl::Union) { thisright = e->getsize()-1; for(t=((uniontypedecl *)e)->getunionmembers(); t!= NULL; t=t->next) { d2 = (typedecl *)t->s->getvalue(); thisleft = thisright-d2->getsize()+1; if (d2->gettypeclass() == typedecl::Scalarset && d2->getsize() > 1 && d2!=d) fprintf(codefile, "\n" " // refinement -- graph structure for two scalarsets\n" " // as in array S1 of S2\n" " // only if there is more than 1 permutation in class\n" " if ( (Perm.MTO_class_%s() && count_%s<%d)\n" " || ( Perm.MTO_class_%s() && count_%s<%d) )\n" " {\n" " exists = FALSE;\n" " split = FALSE;\n" " for (k=0; k<%d; k++) // step through class\n" " if ((*this)[k+%d]%s.isundefined()\n" " ||(*this)[k+%d]%s<%d\n" " ||(*this)[k+%d]%s>%d)\n" " exists = TRUE;\n" " else\n" " split = TRUE;\n" " if (exists && split)\n" " {\n" " for (i=0; i=%d\n" // extra checking " && (*this)[k+%d]%s<=%d\n" // extra checking " && pos_%s[j][(*this)[k+%d]%s-%d])\n" " {\n" " exists = TRUE;\n" " goodset_%s[k] = TRUE;\n" " goodset_%s[(*this)[k+%d]%s-%d] = TRUE;\n" " }\n" " if (exists)\n" " {\n" " // set split for the array index type\n" " split=FALSE;\n" " for (k=0; k<%d; k++)\n" " if ( pos_%s[i][k] && !goodset_%s[k] )\n" " split= TRUE;\n" " if (split)\n" " {\n" " // move following pos entries down 1 step\n" " for (z=count_%s; z>i; z--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[z][k] = pos_%s[z-1][k];\n" " // split pos\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[i][k] && !goodset_%s[k])\n" " pos_%s[i][k] = FALSE;\n" " if (pos_%s[i+1][k] && goodset_%s[k])\n" " pos_%s[i+1][k] = FALSE;\n" " }\n" " count_%s++;\n" " }\n" " // set split for the element type\n" " split=FALSE;\n" " for (k=0; k<%d; k++)\n" " if ( pos_%s[j][k] && !goodset_%s[k] )\n" " split= TRUE;\n" " if (split)\n" " {\n" " // move following pos entries down 1 step\n" " for (z=count_%s; z>j; z--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[z][k] = pos_%s[z-1][k];\n" " // split pos\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[j][k] && !goodset_%s[k])\n" " pos_%s[j][k] = FALSE;\n" " if (pos_%s[j+1][k] && goodset_%s[k])\n" " pos_%s[j+1][k] = FALSE;\n" " }\n" " count_%s++;\n" " }\n" " }\n" " }\n" " }\n" " }\n", d->mu_name, d->mu_name, d->getsize(), // if guard1 d2->mu_name, d2->mu_name, d2->getsize(), // if guard2 d->getsize(), // k-for d->getleft(), var, // (*this)[k_%d]%s // d->getleft(), var, thisleft, // (*this)[k_%d]%s<%d // d->getleft(), var, thisright, // (*this)[k_%d]%s>%d d->getleft(), var, d2->getleft(), // (*this)[k_%d]%s<%d d->getleft(), var, d2->getright(), // (*this)[k_%d]%s>%d d->mu_name, // i-f d2->mu_name, // j-for d->getsize(), d->mu_name, // initialize goodset d2->getsize(), d2->mu_name, // initialize goodset d->getsize(), // scan array index d->mu_name, d->getleft(), var, // if condition // d->getleft(), var, thisleft, // (*this)[k_%d]%s<%d // d->getleft(), var, thisright, // (*this)[k_%d]%s>%d d->getleft(), var, d2->getleft(), // (*this)[k_%d]%s<%d d->getleft(), var, d2->getright(), // (*this)[k_%d]%s>%d d2->mu_name, d->getleft(), var, d2->getleft(), // if condition (cont) d->mu_name, d2->mu_name, d->getleft(), var, d2->getleft(), // set goodsets d->getsize(), // k-for -- split d->mu_name, d->mu_name, // if condition d->mu_name, d->getsize(), d->mu_name, d->mu_name, // move pos down 1 step d->getsize(), d->mu_name, d->mu_name, d->mu_name, // split pos d->mu_name, d->mu_name, d->mu_name, // split pos (cont) d->mu_name, // count_%s d2->getsize(), // k-for -- split d2->mu_name, d2->mu_name, // if condition d2->mu_name, d2->getsize(), d2->mu_name, d2->mu_name, // move pos down 1 step d2->getsize(), d2->mu_name, d2->mu_name, d2->mu_name, // split pos d2->mu_name, d2->mu_name, d2->mu_name, // split pos (cont) d2->mu_name // count_%s ); thisright= thisleft-1; } } } void arraytypedecl::generate_limit5(const char * name1, int size1, int left1, const char * var, const char * name2, int size2, int left2, bool isunion) { if (isunion) fprintf(codefile, "\n" " // refinement -- graph structure for two scalarsets\n" " // as in array S1 of S2\n" " // only if there is more than 1 permutation in class\n" " if ( (Perm.MTO_class_%s() && count_%s<%d)\n" " || ( Perm.MTO_class_%s() && count_%s<%d) )\n" " {\n" " exists = FALSE;\n" " split = FALSE;\n" " for (k=0; k<%d; k++) // step through class\n" " if ((*this)[k+%d]%s.isundefined()\n" " ||(*this)[k+%d]%s<%d\n" " ||(*this)[k+%d]%s>%d)\n" " exists = TRUE;\n" " else\n" " split = TRUE;\n" " if (exists && split)\n" " {\n" " for (i=0; i=%d\n" // extra checking " && (*this)[k+%d]%s<=%d\n" // extra checking " && pos_%s[j][(*this)[k+%d]%s-%d])\n" " {\n" " exists = TRUE;\n" " goodset_%s[k] = TRUE;\n" " goodset_%s[(*this)[k+%d]%s-%d] = TRUE;\n" " }\n" " if (exists)\n" " {\n" " // set split for the array index type\n" " split=FALSE;\n" " for (k=0; k<%d; k++)\n" " if ( pos_%s[i][k] && !goodset_%s[k] )\n" " split= TRUE;\n" " if (split)\n" " {\n" " // move following pos entries down 1 step\n" " for (z=count_%s; z>i; z--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[z][k] = pos_%s[z-1][k];\n" " // split pos\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[i][k] && !goodset_%s[k])\n" " pos_%s[i][k] = FALSE;\n" " if (pos_%s[i+1][k] && goodset_%s[k])\n" " pos_%s[i+1][k] = FALSE;\n" " }\n" " count_%s++;\n" " }\n" " // set split for the element type\n" " split=FALSE;\n" " for (k=0; k<%d; k++)\n" " if ( pos_%s[j][k] && !goodset_%s[k] )\n" " split= TRUE;\n" " if (split)\n" " {\n" " // move following pos entries down 1 step\n" " for (z=count_%s; z>j; z--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[z][k] = pos_%s[z-1][k];\n" " // split pos\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[j][k] && !goodset_%s[k])\n" " pos_%s[j][k] = FALSE;\n" " if (pos_%s[j+1][k] && goodset_%s[k])\n" " pos_%s[j+1][k] = FALSE;\n" " }\n" " count_%s++;\n" " }\n" " }\n" " }\n" " }\n" " }\n", name1, name1, size1, // if guard1 name2, name2, size2, // if guard2 size1, // k-for left1, var, // (*this)[k_%d]%s left1, var, left2, // (*this)[k_%d]%s<%d left1, var, left2+size2-1, // (*this)[k_%d]%s>%d name1, // i-f name2, // j-for size1, name1, // initialize goodset size2, name2, // initialize goodset size1, // scan array index name1, left1, var, // if condition left1, var, left2, // (*this)[k_%d]%s<%d left1, var, left2+size2-1, // (*this)[k_%d]%s>%d name2, left1, var, left2, // if condition (cont) name1, name2, left1, var, left2, // set goodsets size1, // k-for -- split name1, name1, // if condition name1, size1, name1, name1, // move pos down 1 step size1, name1, name1, name1, // split pos name1, name1, name1, // split pos (cont) name1, // count_%s size2, // k-for -- split name2, name2, // if condition name2, size2, name2, name2, // move pos down 1 step size2, name2, name2, name2, // split pos name2, name2, name2, // split pos (cont) name2 // count_%s ); else fprintf(codefile, "\n" " // refinement -- graph structure for two scalarsets\n" " // as in array S1 of S2\n" " // only if there is more than 1 permutation in class\n" " if ( (Perm.MTO_class_%s() && count_%s<%d)\n" " || ( Perm.MTO_class_%s() && count_%s<%d) )\n" " {\n" " exists = FALSE;\n" " split = FALSE;\n" " for (k=0; k<%d; k++) // step through class\n" " if ((*this)[k+%d]%s.isundefined())\n" " exists = TRUE;\n" " else\n" " split = TRUE;\n" " if (exists && split)\n" " {\n" " for (i=0; ii; z--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[z][k] = pos_%s[z-1][k];\n" " // split pos\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[i][k] && !goodset_%s[k])\n" " pos_%s[i][k] = FALSE;\n" " if (pos_%s[i+1][k] && goodset_%s[k])\n" " pos_%s[i+1][k] = FALSE;\n" " }\n" " count_%s++;\n" " }\n" " // set split for the element type\n" " split=FALSE;\n" " for (k=0; k<%d; k++)\n" " if ( pos_%s[j][k] && !goodset_%s[k] )\n" " split= TRUE;\n" " if (split)\n" " {\n" " // move following pos entries down 1 step\n" " for (z=count_%s; z>j; z--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[z][k] = pos_%s[z-1][k];\n" " // split pos\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[j][k] && !goodset_%s[k])\n" " pos_%s[j][k] = FALSE;\n" " if (pos_%s[j+1][k] && goodset_%s[k])\n" " pos_%s[j+1][k] = FALSE;\n" " }\n" " count_%s++;\n" " }\n" " }\n" " }\n" " }\n" " }\n", name1, name1, size1, // if guard1 name2, name2, size2, // if guard2 size1, // k-for left1, var, // (*this)[k_%d]%s name1, // i-f name2, // j-for size1, name1, // initialize goodset size2, name2, // initialize goodset size1, // scan array index name1, left1, var, // if condition name2, left1, var, left2, // if condition (cont) name1, name2, left1, var, left2, // set goodsets size1, // k-for -- split name1, name1, // if condition name1, size1, name1, name1, // move pos down 1 step size1, name1, name1, name1, // split pos name1, name1, name1, // split pos (cont) name1, // count_%s size2, // k-for -- split name2, name2, // if condition name2, size2, name2, name2, // move pos down 1 step size2, name2, name2, name2, // split pos name2, name2, name2, // split pos (cont) name2 // count_%s ); } void arraytypedecl::generate_range(int size, char * name) { fprintf(codefile, "\n" " // setup range for maping\n" " start = 0;\n" " for (j=0; j<=Perm.undefined_class_%s; j++) // class number\n" " {\n" " class_size = 0;\n" " for (k=0; k<%d; k++) // step through class[k]\n" " if (Perm.class_%s[k]==j)\n" " class_size++;\n" " for (k=0; k<%d; k++) // step through class[k]\n" " if (Perm.class_%s[k]==j)\n" " {\n" " size_%s[k] = class_size;\n" " start_%s[k] = start;\n" " }\n" " start+=class_size;\n" " }\n", name, // j-for size, // k-for name, // class_%s size, // k-for name, // class_%s name, // size_%s name // start_%s ); } void arraytypedecl::generate_canonicalize() { stelist * t; typedecl * d; int thisright; int thisleft; if (indextype->gettypeclass() == typedecl::Scalarset) generate_canonicalize(indextype->getsize(), indextype->mu_name, 0, indextype->getleft()); else if (indextype->gettypeclass() == typedecl::Union && ((uniontypedecl *)indextype)->IsUnionWithScalarset()) { thisright = indextype->getsize()-1; for(t=((uniontypedecl *)indextype)->getunionmembers(); t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); thisleft = thisright-d->getsize()+1; if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1 ) generate_canonicalize(d->getsize(), d->mu_name, thisleft, d->getleft()); thisright= thisleft-1; } } } void arraytypedecl::generate_canonicalize(int size, char * name, int left, int scalarsetleft) { fprintf(codefile, " if (Perm.MTO_class_%s())\n" " {\n", name ); generate_range(size, name); generate_slow_canonicalize(size, name, left, scalarsetleft); fprintf(codefile, " }\n" " else\n" " {\n" ); generate_fast_canonicalize(size, name, left, scalarsetleft); fprintf(codefile, " }\n" ); } void arraytypedecl::generate_slow_canonicalize(int size, char * name, int left, int scalarsetleft) { if (elementtype->issimple()) fprintf(codefile, "\n" " // canonicalize\n" " temp = *this;\n" " for (i=0; i<%d; i++)\n" " for (j=0; j<%d; j++)\n" " if (i >=start_%s[j] \n" " && i < start_%s[j] + size_%s[j])\n" " {\n" " array[i+%d].value(temp[j+%d].value());\n" " break;\n" " }\n", size, // i-for size, // j-for name, // start_%s name, name, // start_%s, size_%s left, scalarsetleft // array[i+%d], temp[j+%d] ); else fprintf(codefile, "\n" " // canonicalize\n" " temp = *this;\n" " for (i=0; i<%d; i++)\n" " for (j=0; j<%d; j++)\n" " if (i >=start_%s[j] \n" " && i < start_%s[j] + size_%s[j])\n" " {\n" " array[i+%d] = temp[j+%d];\n" " break;\n" " }\n", size, // i-for size, // j-for name, // start_%s name, name, // start_%s, size_%s left, scalarsetleft // array[i+%d], temp[j+%d] ); } void arraytypedecl::generate_fast_canonicalize(int size, char * name, int left, int scalarsetleft) { if (elementtype->gettypeclass() == typedecl::Record ||elementtype->gettypeclass() == typedecl::Array) fprintf(codefile, "\n" " // fast canonicalize\n" " temp = *this;\n" " for (j=0; j<%d; j++)\n" " array[Perm.class_%s[j]+%d] = temp[j+%d];\n", size, // j-for name, // class_%s left, scalarsetleft // array[i+%d], temp[j+%d] ); else fprintf(codefile, "\n" " // fast canonicalize\n" " temp = *this;\n" " for (j=0; j<%d; j++)\n" " array[Perm.class_%s[j]+%d].value(temp[j+%d].value());\n", size, // j-for name, left, scalarsetleft // class_%s array[i+%d], temp[j+%d] ); } void arraytypedecl::generate_while_guard(charlist * scalarsetlist) { charlist * sl; fprintf(codefile, " while_guard = FALSE;\n"); for (sl=scalarsetlist; sl!=NULL; sl = sl->next) fprintf(codefile, " while_guard = while_guard || (oldcount_%s!=count_%s);\n", sl->e->mu_name, sl->e->mu_name ); fprintf(codefile, " while_guard_temp = while_guard;\n"); fprintf(codefile, " while_guard = FALSE;\n"); for (sl=scalarsetlist; sl!=NULL; sl = sl->next) fprintf(codefile, " while_guard = while_guard || count_%s<%d;\n", sl->e->mu_name, sl->e->getsize() ); fprintf(codefile, " while_guard = while_guard && while_guard_temp;\n"); } void arraytypedecl::generate_while(charlist * scalarsetlist) { charlist * sl; fprintf(codefile, "\n" " // refinement -- checking priority in general\n"); // setup initial while guard fprintf(codefile, " while_guard = FALSE;\n"); for (sl=scalarsetlist; sl!=NULL; sl = sl->next) fprintf(codefile, " while_guard = while_guard || (Perm.MTO_class_%s() && count_%s<%d);\n", sl->e->mu_name, sl->e->mu_name, sl->e->getsize() ); fprintf(codefile, " while ( while_guard )\n" " {\n"); // setup oldcount for (sl=scalarsetlist; sl!=NULL; sl = sl->next) fprintf(codefile, " oldcount_%s = count_%s;\n", sl->e->mu_name, sl->e->mu_name ); } /******************** generate simple_canon() for each typedecl ********************/ void enumtypedecl::generate_simple_canon_function(symmetryclass& symmetry) { if (already_generated_simple_canon_function) return; else already_generated_simple_canon_function = TRUE; if (strcmp(mu_name,"mu_0_boolean")!=0) fprintf(codefile, "void %s::SimpleCanonicalize(PermSet& Perm) {};\n", mu_name); }; void subrangetypedecl::generate_simple_canon_function(symmetryclass& symmetry) { if (already_generated_simple_canon_function) return; else already_generated_simple_canon_function = TRUE; fprintf(codefile, "void %s::SimpleCanonicalize(PermSet& Perm) {};\n", mu_name); }; void multisettypedecl::generate_simple_canon_function(symmetryclass& symmetry) { if (already_generated_simple_canon_function) return; else already_generated_simple_canon_function = TRUE; elementtype->generate_simple_canon_function(symmetry); fprintf(codefile, "void %s::SimpleCanonicalize(PermSet& Perm)\n" "{ Error.Error(\"Internal: calling SimpleCanonicalize for a multiset.\\n\"); };\n", mu_name); } void arraytypedecl::generate_simple_canon_function(symmetryclass& symmetry) { if (already_generated_simple_canon_function) return; else already_generated_simple_canon_function = TRUE; elementtype->generate_simple_canon_function(symmetry); if (indextype->getstructure() != typedecl::ScalarsetVariable && elementtype->HasScalarsetVariable()) fprintf(codefile, "void %s::SimpleCanonicalize(PermSet& Perm)\n" "{\n" " for (int j=0; j<%d; j++)\n" " array[j].SimpleCanonicalize(Perm);\n" "}\n", mu_name, // %s::Canonicalize indextype->getsize() // j-for ); else fprintf(codefile, "void %s::SimpleCanonicalize(PermSet& Perm)\n" "{ Error.Error(\"Internal: Simple Canonicalization of Scalarset Array\\n\"); };\n", mu_name); } void recordtypedecl::generate_simple_canon_function(symmetryclass& symmetry) { ste *f; if (already_generated_simple_canon_function) return; else already_generated_simple_canon_function = TRUE; for (f = fields; f != NULL; f = f->next) f->getvalue()->gettype()->generate_simple_canon_function(symmetry); if (HasScalarsetVariable()) { fprintf(codefile, "void %s::SimpleCanonicalize(PermSet& Perm)\n" "{\n", mu_name ); for (f = fields; f != NULL; f = f->next) if (f->getvalue()->gettype()->HasScalarsetVariable()) fprintf(codefile, " %s.SimpleCanonicalize(Perm);\n", f->getvalue()->generate_code() ); fprintf(codefile, "};\n"); } else fprintf(codefile, "void %s::SimpleCanonicalize(PermSet& Perm)\n" "{ Error.Error(\"Internal: Simple Canonicalization of Record with no scalarset variable\\n\"); };\n", mu_name ); } void scalarsettypedecl::generate_simple_canon_function(symmetryclass& symmetry) { if (already_generated_simple_canon_function) return; else already_generated_simple_canon_function = TRUE; if (!useless && getsize() > 1) fprintf(codefile, "void %s::SimpleCanonicalize(PermSet& Perm)\n" "{\n" " int i, class_number;\n" " if (Perm.Presentation != PermSet::Simple)\n" " Error.Error(\"Internal Error: Wrong Sequence of Normalization\");\n" "\n" " if (defined())\n" " if (Perm.class_%s[value()-%d]==Perm.undefined_class_%s) // value - base\n" " {\n" " // it has not been mapped to any particular value\n" " for (i=0; i<%d; i++)\n" " if (Perm.class_%s[i] == Perm.undefined_class_%s && i!=value()-%d)\n" " Perm.class_%s[i]++;\n" " value(%d + Perm.undefined_class_%s++);\n" " }\n" " else \n" " {\n" " value(Perm.class_%s[value()-%d]+%d);\n" " }\n" "}\n", mu_name, // void %s::Canonicalize mu_name, left, mu_name, // class_%s, value-%d, undefined_class_%s getsize(), // i-for mu_name, mu_name, left, // class_%s, undefined_class_%s, value-%d mu_name, // class_%s left, mu_name, // %d + Perm.undefined_class_%s++ mu_name, left, left // class_%s[value-%d]+%d ); else fprintf(codefile, "void %s::SimpleCanonicalize(PermSet& Perm) {}\n", mu_name); } void uniontypedecl::generate_simple_canon_function(symmetryclass& symmetry) { if (already_generated_simple_canon_function) return; else already_generated_simple_canon_function = TRUE; if (useless) fprintf(codefile, "void %s::SimpleCanonicalize(PermSet& Perm) {}\n", mu_name); else { fprintf(codefile, "void %s::SimpleCanonicalize(PermSet& Perm)\n" "{\n" " int i, class_number;\n" " if (Perm.Presentation != PermSet::Simple)\n" " Error.Error(\"Internal Error: Wrong Sequence of Normalization\");\n" " if (defined()) {\n", mu_name); stelist * t; typedecl * d; int thisright = getsize(); int thisleft; for(t=unionmembers; t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); thisleft = thisright-d->getsize()+1; if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1) fprintf(codefile, " if ( ( value() >= %d ) && ( value() <= %d ) )\n" " {\n" " if (Perm.class_%s[value()-%d]==Perm.undefined_class_%s) // value - base\n" " {\n" " // it has not been mapped to any particular value\n" " for (i=0; i<%d; i++)\n" " if (Perm.class_%s[i] == Perm.undefined_class_%s && i!=value()-%d)\n" " Perm.class_%s[i]++;\n" " value(%d + Perm.undefined_class_%s++);\n" " }\n" " else \n" " {\n" " value(Perm.class_%s[value()-%d]+%d);\n" " }\n" " }\n", // thisleft, thisright, // if// fixing union permutation bug d->getleft(), d->getright(), // d->mu_name, thisleft, d->mu_name, // class_%s, value-%d, class_%s// fixing union permutation bug d->mu_name, d->getleft(), d->mu_name, d->getsize(), // i-for // d->mu_name, d->mu_name, thisleft, // class_%s, undefined_class_%s, vlaue -%d// fixing union permutation bug d->mu_name, d->mu_name, d->getleft(), // class_%s, undefined_class_%s, vlaue -%d d->mu_name, // class_%s // thisleft, d->mu_name, // %d + Perm.undefined_class_%s++// fixing union permutation bug d->getleft(), d->mu_name, // d->mu_name, thisleft, thisleft // class_%s[value-%d]+%d// fixing union permutation bug d->mu_name, d->getleft(), d->getleft() // class_%s[value-%d]+%d ); thisright = thisleft-1; } fprintf(codefile, " }\n" "}\n" ); } } void typedecl::generate_simple_canon_function(symmetryclass& symmetry) { Error.Error("Internal: typedecl::generate_simple_canon_function()"); }; /******************** generate canonicalize() for each typedecl ********************/ void enumtypedecl::generate_canonicalize_function(symmetryclass& symmetry) { if (already_generated_canonicalize_function) return; else already_generated_canonicalize_function = TRUE; if (strcmp(mu_name,"mu_0_boolean")!=0) fprintf(codefile, "void %s::Canonicalize(PermSet& Perm) {};\n", mu_name); }; void subrangetypedecl::generate_canonicalize_function(symmetryclass& symmetry) { if (already_generated_canonicalize_function) return; else already_generated_canonicalize_function = TRUE; fprintf(codefile, "void %s::Canonicalize(PermSet& Perm) {};\n", mu_name); }; void multisettypedecl::generate_canonicalize_function(symmetryclass& symmetry) { if (already_generated_canonicalize_function) return; else already_generated_canonicalize_function = TRUE; elementtype->generate_canonicalize_function(symmetry); fprintf(codefile, "void %s::Canonicalize(PermSet& Perm)\n" "{ Error.Error(\"You cannot use this symmetry algorithm with Multiset.\\n\"); };\n", mu_name); } void arraytypedecl::generate_canonicalize_function(symmetryclass& symmetry) { stelist * t; typedecl * d; if (already_generated_canonicalize_function) return; else already_generated_canonicalize_function = TRUE; elementtype->generate_canonicalize_function(symmetry); if (indextype->getstructure() != typedecl::ScalarsetVariable && ( elementtype->getstructure() == typedecl::ScalarsetArrayOfFree || elementtype->getstructure() == typedecl::MultisetOfFree ) ) { fprintf(codefile, "void %s::Canonicalize(PermSet& Perm)\n" "{\n" " for (int j=0; j<%d; j++)\n" " array[j].Canonicalize(Perm);\n" "}\n", mu_name, // %s::Canonicalize indextype->getsize() // j-for ); } else if (indextype->gettypeclass() == typedecl::Scalarset && elementtype->getstructure() == typedecl::NoScalarset && indextype->getsize() > 1 ) { fprintf(codefile, "void %s::Canonicalize(PermSet& Perm)\n" "{\n" " // indexes\n" " int i,j,k,z;\n" " // sorting\n" " int count_%s;\n" " int compare;\n" " static PerThread< std::vector< %s > > value_( std::vector< %s >( %d ) );\n" " std::vector< %s > &value = value_.get();\n" " // limit\n" " bool exists;\n" " bool split;\n" " bool goodset_%s[%d];\n" " bool pos_%s[%d][%d];\n" " // range mapping\n" " int start;\n" " int class_size;\n" " int size_%s[%d];\n" " int start_%s[%d];\n" " // canonicalization\n" " static PerThread< %s > temp_; %s &temp = temp_.get();\n", mu_name, // %s::Canonicalize indextype->mu_name, // count_%s elementtype->mu_name, elementtype->mu_name, indextype->getsize(), elementtype->mu_name, // %s value[%d] indextype->mu_name, indextype->getsize(), // bool goodset_%s[%d] indextype->mu_name, indextype->getsize(), indextype->getsize(), // pos indextype->mu_name, indextype->getsize(), // size_%s[%d] indextype->mu_name, indextype->getsize(), // start_%s[%d] mu_name, mu_name // static %s temp ); generate_simple_sort(); generate_limit(); generate_canonicalize(); fprintf(codefile, "}\n"); } else if (indextype->gettypeclass() == typedecl::Union && ((uniontypedecl *)indextype)->IsUnionWithScalarset() && elementtype->getstructure() == typedecl::NoScalarset) { fprintf(codefile, "void %s::Canonicalize(PermSet& Perm)\n" "{\n" " // indexes\n" " int i,j,k,z;\n" " // sorting\n" " static PerThread< std::vector< %s > > value_( std::vector< %s >( %d ) );\n" " std::vector< %s > &value = value_.get();\n" " int compare;\n" " // limit\n" " bool exists;\n" " bool split;\n" " // range mapping\n" " int start;\n" " int class_size;\n" " // canonicalization\n" " static PerThread< %s > temp_; %s &temp = temp_.get();\n", mu_name, // %s::Canonicalize elementtype->mu_name, elementtype->mu_name, indextype->getsize(), elementtype->mu_name, // %s value[%d] mu_name, mu_name // static %s temp ); for(t=((uniontypedecl *)indextype)->getunionmembers(); t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1 ) { fprintf(codefile, " int count_%s;\n" " bool pos_%s[%d][%d];\n" " bool goodset_%s[%d];\n" " int size_%s[%d];\n" " int start_%s[%d];\n", d->mu_name, d->mu_name, d->getsize(), d->getsize(), d->mu_name, d->getsize(), d->mu_name, d->getsize(), d->mu_name, d->getsize() ); } } generate_simple_sort(); generate_limit(); generate_canonicalize(); fprintf(codefile,"}\n"); } else fprintf(codefile, "void %s::Canonicalize(PermSet& Perm){};\n", mu_name); } void recordtypedecl::generate_canonicalize_function(symmetryclass& symmetry) { ste *f; if (already_generated_canonicalize_function) return; else already_generated_canonicalize_function = TRUE; for (f = fields; f != NULL; f = f->next) f->getvalue()->gettype()->generate_canonicalize_function(symmetry); // if (getstructure() == ScalarsetArrayOfFree) // { fprintf(codefile, "void %s::Canonicalize(PermSet& Perm)\n" "{\n", mu_name ); for (f = fields; f != NULL; f = f->next) if (f->getvalue()->gettype()->getstructure() == ScalarsetArrayOfFree) // if (f->getvalue()->gettype()->HasScalarsetArrayOfFree()) fprintf(codefile, " %s.Canonicalize(Perm);\n", f->getvalue()->generate_code() ); fprintf(codefile, "};\n"); // } // else // fprintf(codefile, // "void %s::Canonicalize(PermSet& Perm)\n" // "{\n" // " Error.Error(\"Calling canonicalize() for non simple scalarsettype.\");\n" // "}\n", // mu_name); } void scalarsettypedecl::generate_canonicalize_function(symmetryclass& symmetry) { if (already_generated_canonicalize_function) return; else already_generated_canonicalize_function = TRUE; fprintf(codefile, "void %s::Canonicalize(PermSet& Perm)\n" "{\n" " Error.Error(\"Calling canonicalize() for Scalarset.\");\n" "}\n", mu_name); } void uniontypedecl::generate_canonicalize_function(symmetryclass& symmetry) { if (already_generated_canonicalize_function) return; else already_generated_canonicalize_function = TRUE; fprintf(codefile, "void %s::Canonicalize(PermSet& Perm)\n" "{\n" " Error.Error(\"Calling canonicalize() for Scalarset.\");\n" "}\n", mu_name); } void typedecl::generate_canonicalize_function(symmetryclass& symmetry) { Error.Error("Internal: typedecl::generate_canonicalize_function()"); }; /******************** generate SimpleLimit() for each typedecl ********************/ void enumtypedecl::generate_simple_limit_function(symmetryclass& symmetry) { if (already_generated_simple_limit_function) return; else already_generated_simple_limit_function = TRUE; if (strcmp(mu_name,"mu_0_boolean")!=0) fprintf(codefile, "void %s::SimpleLimit(PermSet& Perm) {};\n", mu_name); }; void subrangetypedecl::generate_simple_limit_function(symmetryclass& symmetry) { if (already_generated_simple_limit_function) return; else already_generated_simple_limit_function = TRUE; fprintf(codefile, "void %s::SimpleLimit(PermSet& Perm) {};\n", mu_name); }; void multisettypedecl::generate_simple_limit_function(symmetryclass& symmetry) { if (already_generated_simple_limit_function) return; else already_generated_simple_limit_function = TRUE; elementtype->generate_simple_limit_function(symmetry); fprintf(codefile, "void %s::SimpleLimit(PermSet& Perm)\n" "{ Error.Error(\"You cannot use this symmetry algorithm with Multiset.\\n\"); };\n", mu_name); } void arraytypedecl::generate_simple_limit_function(symmetryclass& symmetry) { if (already_generated_simple_limit_function) return; else already_generated_simple_limit_function = TRUE; elementtype->generate_simple_limit_function(symmetry); if ( indextype->getstructure() != typedecl::ScalarsetVariable && elementtype->HasScalarsetVariable() ) { fprintf(codefile, "void %s::SimpleLimit(PermSet& Perm)\n" "{\n" " for (int j=0; j<%d; j++) {\n" " array[j].SimpleLimit(Perm);\n" " }\n" "}\n", mu_name, // %s::Limit indextype->getsize() // j-for ); } else fprintf(codefile, "void %s::SimpleLimit(PermSet& Perm){}\n", mu_name); } void recordtypedecl::generate_simple_limit_function(symmetryclass& symmetry) { ste *f; if (already_generated_simple_limit_function) return; else already_generated_simple_limit_function = TRUE; for (f = fields; f != NULL; f = f->next) f->getvalue()->gettype()->generate_simple_limit_function(symmetry); if (HasScalarsetVariable()) { fprintf(codefile, "void %s::SimpleLimit(PermSet& Perm)\n" "{\n", mu_name ); for (f = fields; f != NULL; f = f->next) if (f->getvalue()->gettype()->HasScalarsetVariable()) fprintf(codefile, " %s.SimpleLimit(Perm);\n", f->getvalue()->generate_code() ); fprintf(codefile,"};\n"); } else fprintf(codefile, "void %s::SimpleLimit(PermSet& Perm){}\n", mu_name); } void scalarsettypedecl::generate_simple_limit_function(symmetryclass& symmetry) { if (already_generated_simple_limit_function) return; else already_generated_simple_limit_function = TRUE; if (!useless && getsize() > 1) fprintf(codefile, "void %s::SimpleLimit(PermSet& Perm)\n" "{\n" " int i, class_number;\n" " if (Perm.Presentation != PermSet::Simple)\n" " Error.Error(\"Internal Error: Wrong Sequence of Normalization\");\n" "\n" " if (defined())\n" " if (Perm.class_%s[value()-%d]==Perm.undefined_class_%s) // value - base\n" " {\n" " // it has not been mapped to any particular value\n" " for (i=0; i<%d; i++)\n" " if (Perm.class_%s[i] == Perm.undefined_class_%s && i!=value()-%d)\n" " Perm.class_%s[i]++;\n" " Perm.undefined_class_%s++;\n" " }\n" "}\n", mu_name, // void %s::Canonicalize mu_name, left, mu_name, // class_%s, value-%d, undefined_class_%s getsize(), // i-for mu_name, mu_name, left, // class_%s, undefined_class_%s, value-%d mu_name, // class_%s mu_name // Perm.undefined_class_%s++ ); else fprintf(codefile, "void %s::SimpleLimit(PermSet& Perm) {}\n", mu_name); } void uniontypedecl::generate_simple_limit_function(symmetryclass& symmetry) { if (already_generated_simple_limit_function) return; else already_generated_simple_limit_function = TRUE; if (useless) { fprintf(codefile, "void %s::SimpleLimit(PermSet& Perm) {}\n", mu_name); } else { fprintf(codefile, "void %s::SimpleLimit(PermSet& Perm)\n" "{\n" " int i, class_number;\n" " if (Perm.Presentation != PermSet::Simple)\n" " Error.Error(\"Internal Error: Wrong Sequence of Normalization\");\n" " if (defined()) {\n", mu_name); stelist * t; typedecl * d; int thisright = getsize(); int thisleft; for(t=unionmembers; t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); thisleft = thisright-d->getsize()+1; if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1) fprintf(codefile, " if ( ( value() >= %d ) && ( value() <= %d ) )\n" " if (Perm.class_%s[value()-%d]==Perm.undefined_class_%s) // value - base\n" " {\n" " // it has not been mapped to any particular value\n" " for (i=0; i<%d; i++)\n" " if (Perm.class_%s[i] == Perm.undefined_class_%s && i!=value()-%d)\n" " Perm.class_%s[i]++;\n" " Perm.undefined_class_%s++;\n" " }\n", // thisleft, thisright, // if// fixing union permutation bug d->getleft(), d->getright(), // d->mu_name, thisleft, d->mu_name, // class_%s, value-%d, class_%s// fixing union permutation bug d->mu_name, d->getleft(), d->mu_name, // class_%s, value-%d, class_%s d->getsize(), // i-for // d->mu_name, d->mu_name, thisleft, // class_%s, undefined_class_%s, vlaue -%d// fixing union permutation bug d->mu_name, d->mu_name, d->getleft(), // class_%s, undefined_class_%s, vlaue -%d d->mu_name, // class_%s d->mu_name // Perm.undefined_class_%s++ ); thisright = thisleft-1; } fprintf(codefile, " }\n" "}\n" ); } } void typedecl::generate_simple_limit_function(symmetryclass& symmetry) { Error.Error("Internal: typedecl::generate_simple_limit_function()"); }; /******************** generate ArrayLimit() for each typedecl ********************/ void enumtypedecl::generate_array_limit_function(symmetryclass& symmetry) { if (already_generated_array_limit_function) return; else already_generated_array_limit_function = TRUE; if (strcmp(mu_name,"mu_0_boolean")!=0) fprintf(codefile, "void %s::ArrayLimit(PermSet& Perm) {};\n", mu_name); }; void subrangetypedecl::generate_array_limit_function(symmetryclass& symmetry) { if (already_generated_array_limit_function) return; else already_generated_array_limit_function = TRUE; fprintf(codefile, "void %s::ArrayLimit(PermSet& Perm) {};\n", mu_name); }; void multisettypedecl::generate_array_limit_function(symmetryclass& symmetry) { if (already_generated_array_limit_function) return; else already_generated_array_limit_function = TRUE; elementtype->generate_array_limit_function(symmetry); fprintf(codefile, "void %s::ArrayLimit(PermSet& Perm)\n" "{ Error.Error(\"You cannot use this symmetry algorithm with Multiset.\\n\"); };\n", mu_name); } void arraytypedecl::generate_array_limit_function(symmetryclass& symmetry) { stelist * t; typedecl * d; if (already_generated_array_limit_function) return; else already_generated_array_limit_function = TRUE; elementtype->generate_array_limit_function(symmetry); if ( indextype->getstructure() != typedecl::ScalarsetVariable && elementtype->HasScalarsetArrayOfFree() ) { fprintf(codefile, "void %s::ArrayLimit(PermSet& Perm)\n" "{\n" " for (int j=0; j<%d; j++)\n" " array[j].ArrayLimit(Perm);\n" "}\n", mu_name, // %s::Limit indextype->getsize() // j-for ); } // no matter what the element is, we will generate the procedure // whether this procedure will be call depends on the high level routine else if (indextype->gettypeclass() == typedecl::Scalarset && indextype->getsize() > 1 ) { fprintf(codefile, "void %s::ArrayLimit(PermSet& Perm)\n" "{\n" " // indexes\n" " int i,j,k,z;\n" " // sorting\n" " int count_%s;\n" " int compare;\n" " static PerThread< std::vector< %s > > value_( std::vector< %s >( %d ) );\n" " std::vector< %s > &value = value_.get();\n" " // limit\n" " bool exists;\n" " bool split;\n" " bool goodset_%s[%d];\n" " bool pos_%s[%d][%d];\n", mu_name, // %s::Limit indextype->mu_name, // count_%s elementtype->mu_name, elementtype->mu_name, indextype->getsize(), elementtype->mu_name, // %s value[%d] indextype->mu_name, indextype->getsize(), // bool goodset_%s[%d] indextype->mu_name, indextype->getsize(), indextype->getsize() // pos ); generate_simple_sort(); generate_limit(); fprintf(codefile, "}\n"); } // no matter what the element is, we will generate the procedure // whether this procedure will be call depends on the high level routine else if (indextype->gettypeclass() == typedecl::Union && ((uniontypedecl *)indextype)->IsUnionWithScalarset() ) { fprintf(codefile, "void %s::ArrayLimit(PermSet& Perm)\n" "{\n" " // indexes\n" " int i,j,k,z;\n" " // sorting\n" " int compare;\n" " static PerThread< std::vector< %s > > value_( std::vector< %s >( %d ) );\n" " std::vector< %s > &value = value_.get();\n" " // limit\n" " bool exists;\n" " bool split;\n", mu_name, // %s::Canonicalize elementtype->mu_name, elementtype->mu_name, indextype->getsize(), elementtype->mu_name // %s value[%d] ); for(t=((uniontypedecl *)indextype)->getunionmembers(); t!= NULL; t=t->next) { d = (typedecl *)t->s->getvalue(); if (d->gettypeclass() == typedecl::Scalarset && d->getsize() > 1 ) { fprintf(codefile, " int count_%s;\n" " bool pos_%s[%d][%d];\n" " bool goodset_%s[%d];\n", d->mu_name, d->mu_name, d->getsize(), d->getsize(), d->mu_name, d->getsize() ); } } generate_simple_sort(); generate_limit(); fprintf(codefile,"}\n"); } else fprintf(codefile, "void %s::ArrayLimit(PermSet& Perm) {}\n", mu_name); } void recordtypedecl::generate_array_limit_function(symmetryclass& symmetry) { ste *f; if (already_generated_array_limit_function) return; else already_generated_array_limit_function = TRUE; for (f = fields; f != NULL; f = f->next) f->getvalue()->gettype()->generate_array_limit_function(symmetry); if (HasScalarsetArrayOfFree()) { fprintf(codefile, "void %s::ArrayLimit(PermSet& Perm)\n" "{\n", mu_name ); for (f = fields; f != NULL; f = f->next) if (f->getvalue()->gettype()->HasScalarsetArrayOfFree()) fprintf(codefile, " %s.ArrayLimit(Perm);\n", f->getvalue()->generate_code() ); fprintf(codefile,"};\n"); } else fprintf(codefile, "void %s::ArrayLimit(PermSet& Perm){}\n", mu_name); } void scalarsettypedecl::generate_array_limit_function(symmetryclass& symmetry) { if (already_generated_array_limit_function) return; else already_generated_array_limit_function = TRUE; fprintf(codefile, "void %s::ArrayLimit(PermSet& Perm) {}\n", mu_name); } void uniontypedecl::generate_array_limit_function(symmetryclass& symmetry) { if (already_generated_array_limit_function) return; else already_generated_array_limit_function = TRUE; fprintf(codefile, "void %s::ArrayLimit(PermSet& Perm) {}\n", mu_name); } void typedecl::generate_array_limit_function(symmetryclass& symmetry) { Error.Error("Internal: typedecl::generate_array_limit_function()"); }; /******************** generate limit() for each typedecl ********************/ void enumtypedecl::generate_limit_function(symmetryclass& symmetry) { if (already_generated_limit_function) return; else already_generated_limit_function = TRUE; if (strcmp(mu_name,"mu_0_boolean")!=0) fprintf(codefile, "void %s::Limit(PermSet& Perm) {};\n", mu_name); }; void subrangetypedecl::generate_limit_function(symmetryclass& symmetry) { if (already_generated_limit_function) return; else already_generated_limit_function = TRUE; fprintf(codefile, "void %s::Limit(PermSet& Perm) {};\n", mu_name); }; void multisettypedecl::generate_limit_function(symmetryclass& symmetry) { if (already_generated_limit_function) return; else already_generated_limit_function = TRUE; elementtype->generate_limit_function(symmetry); fprintf(codefile, "void %s::Limit(PermSet& Perm)\n" "{ Error.Error(\"You cannot use this symmetry algorithm with Multiset.\\n\"); };\n", mu_name); } void arraytypedecl::generate_limit_function(symmetryclass& symmetry) { charlist * scalarsetlist; charlist * scalarsetvalue; charlist * sv; if (already_generated_limit_function) return; else already_generated_limit_function = TRUE; elementtype->generate_limit_function(symmetry); if ( indextype->getstructure() != typedecl::ScalarsetVariable && elementtype->HasScalarsetArrayOfS() ) { fprintf(codefile, "void %s::Limit(PermSet& Perm)\n" "{\n" " if (Perm.Presentation != PermSet::Simple)\n" " Error.Error(\"Internal Error: Wrong Sequence of Normalization\");\n" "\n" " for (int j=0; j<%d; j++) {\n" " array[j].Limit(Perm);\n" " }\n" "}\n", mu_name, // %s::Limit indextype->getsize() // j-for ); } else if (indextype->gettypeclass() == typedecl::Scalarset && elementtype->HasScalarsetVariable() && indextype->getsize() > 1 ) { fprintf(codefile, "void %s::Limit(PermSet& Perm)\n" "{\n" " // indexes\n" " int i,j,k,z;\n" " // while guard\n" " bool while_guard, while_guard_temp;\n" " // sorting\n" " static PerThread< std::vector< %s > > value_( std::vector< %s >( %d ) );\n" " std::vector< %s > &value = value_.get();\n" " // limit\n" " bool exists;\n" " bool split;\n", mu_name, // %s::Canonicalize elementtype->mu_name, elementtype->mu_name, indextype->getsize(), elementtype->mu_name // %s value[%d] ); // get a list for all scalarsets that may appear scalarsetlist = generate_scalarset_list(NULL); fprintf(codefile, " int i0"); for (int i = get_num_limit_locals(elementtype)-1; i>0; i--) fprintf(codefile,",i%d",i); fprintf(codefile, ";\n"); // declare for all scalarsets that may appear for (sv=scalarsetlist; sv!=NULL; sv = sv->next) fprintf(codefile, " int count_%s, oldcount_%s;\n" " bool pos_%s[%d][%d];\n" " bool goodset_%s[%d];\n", sv->e->mu_name, sv->e->mu_name, sv->e->mu_name, sv->e->getsize(), sv->e->getsize(), sv->e->mu_name, sv->e->getsize() ); // change to without simple sort // it has been done separately // you have to set it up for all scalarsets that may be reference // even though it may have only 1 permutation for (sv=scalarsetlist; sv!=NULL; sv = sv->next) fprintf(codefile, " // count_ corresponds to the number of equivalence class within the\n" " // scalarset value. If count_ == size of the scalarset, then a unique\n" " // permutation has been found.\n" "\n" " // pos_ is a relation on a equivalence class number and a scalarset value.\n" "\n" " // initializing pos array\n" " for (i=0; i<%d; i++)\n" " for (j=0; j<%d; j++)\n" " pos_%s[i][j]=FALSE;\n" " count_%s = 0;\n" " while (1)\n" " {\n" " exists = FALSE;\n" " for (i=0; i<%d; i++)\n" " if (Perm.class_%s[i] == count_%s)\n" " {\n" " pos_%s[count_%s][i]=TRUE;\n" " exists = TRUE;\n" " }\n" " if (exists) count_%s++;\n" " else break;\n" " }\n", sv->e->getsize(), sv->e->getsize(), sv->e->mu_name, // initialization sv->e->mu_name, // count_%s sv->e->getsize(), // i-for sv->e->mu_name, sv->e->mu_name, // if-guard sv->e->mu_name, sv->e->mu_name, // pos_%s[count%s] sv->e->mu_name // count_%s ); // refine according to the undefined scalarset value in the element // for (sv=scalarsetvalue; sv!=NULL; sv = sv->next) // generate_limit2(sv->string, sv->e); // refine according to selfreference of scalarset in the element // for (sv=scalarsetvalue; sv!=NULL; sv = sv->next) // generate_limit3(sv->string, sv->e); generate_limit_step1(3); // have to generate the while loop generate_while(scalarsetlist); // refine accordipng to directed graph of Array S1 of S1 // for (sv=scalarsetvalue; sv!=NULL; sv = sv->next) // generate_limit4(indextype, sv->string, sv->e); generate_limit_step1(4); // refine according to directed graph of Array S1 of S2 where S1 != S2 // for (sv=scalarsetvalue; sv!=NULL; sv = sv->next) generate_limit_step1(5); // set while guard generate_while_guard(scalarsetlist); // end while loop fprintf(codefile, " } // end while\n"); // enter result for (sv=scalarsetlist; sv!=NULL; sv = sv->next) fprintf(codefile, " // enter the result into class\n" " if (Perm.MTO_class_%s())\n" " {\n" " for (i=0; i<%d; i++)\n" " for (j=0; j<%d; j++)\n" " if (pos_%s[i][j])\n" " Perm.class_%s[j] = i;\n" " Perm.undefined_class_%s=0;\n" " for (j=0; j<%d; j++)\n" " if (Perm.class_%s[j]>Perm.undefined_class_%s)\n" " Perm.undefined_class_%s=Perm.class_%s[j];\n" " }\n", sv->e->mu_name, sv->e->getsize(), sv->e->getsize(), // i-for j-for sv->e->mu_name, // pos sv->e->mu_name, // class sv->e->mu_name, // undefined_class sv->e->getsize(), // i-for j-for sv->e->mu_name, sv->e->mu_name, // class_%s undefined_class_%s sv->e->mu_name, sv->e->mu_name // undefined_class_%s class_%s ); fprintf(codefile,"}\n"); } else if (indextype->gettypeclass() == typedecl::Union && ((uniontypedecl *)indextype)->IsUnionWithScalarset() && elementtype->HasScalarsetVariable() ) { fprintf(codefile, "void %s::Limit(PermSet& Perm)\n" "{\n" " // indexes\n" " int i,j,k,z;\n" " // while guard\n" " bool while_guard, while_guard_temp;\n" " // sorting\n" " static PerThread< std::vector< %s > > value_( std::vector< %s >( %d ) );\n" " std::vector< %s > &value = value_.get();\n" " // limit\n" " bool exists;\n" " bool split;\n", mu_name, // %s::Limit elementtype->mu_name, elementtype->mu_name, indextype->getsize(), elementtype->mu_name // %s value[%d] ); // get a list for all scalarsets that may appear scalarsetlist = generate_scalarset_list(NULL); fprintf(codefile, " int i0"); for (int i = get_num_limit_locals(elementtype)-1; i>0; i--) fprintf(codefile,",i%d",i); fprintf(codefile, ";\n"); // declare for all scalarsets that may appear for (sv=scalarsetlist; sv!=NULL; sv = sv->next) fprintf(codefile, " int count_%s, oldcount_%s;\n" " bool pos_%s[%d][%d];\n" " bool goodset_%s[%d];\n", sv->e->mu_name, sv->e->mu_name, sv->e->mu_name, sv->e->getsize(), sv->e->getsize(), sv->e->mu_name, sv->e->getsize() ); // change to without simple sort // you have to set it up for all scalarsets that may be reference // even though it may have only 1 permutation for (sv=scalarsetlist; sv!=NULL; sv = sv->next) fprintf(codefile, " // initializing pos array\n" " for (i=0; i<%d; i++)\n" " for (j=0; j<%d; j++)\n" " pos_%s[i][j]=FALSE;\n" " count_%s = 0;\n" " while (1)\n" " {\n" " exists = FALSE;\n" " for (i=0; i<%d; i++)\n" " if (Perm.class_%s[i] == count_%s)\n" " {\n" " pos_%s[count_%s][i]=TRUE;\n" " exists = TRUE;\n" " }\n" " if (exists) count_%s++;\n" " else break;\n" " }\n", sv->e->getsize(), sv->e->getsize(), sv->e->mu_name, // initialization sv->e->mu_name, // count_%s sv->e->getsize(), // i-for sv->e->mu_name, sv->e->mu_name, // if-guard sv->e->mu_name, sv->e->mu_name, // pos_%s[count%s] sv->e->mu_name // count_%s ); // sorting according to constants in the element // generate_simple_sort(); // refine according to the undefined scalarset value in the element // for (sv=scalarsetvalue; sv!=NULL; sv = sv->next) // generate_limit2(sv->string, sv->e); // refine according to selfreference of scalarset in the element // for (sv=scalarsetvalue; sv!=NULL; sv = sv->next) // generate_limit3(sv->string, sv->e); generate_limit_step1(3); // prepare while loop for further refinement generate_while(scalarsetlist); // refine according to direted graph of Array S1 of S1 // for (sv=scalarsetvalue; sv!=NULL; sv = sv->next) // generate_limit4(sv->string, sv->e); generate_limit_step1(4); // refine according to direted graph of Array S1 of S2 where S1 != S2 // for (sv=scalarsetvalue; sv!=NULL; sv = sv->next) // generate_limit5(sv->string, sv->e); generate_limit_step1(5); // set while guard generate_while_guard(scalarsetlist); // end while loop fprintf(codefile, " } // end while\n"); // enter result for (sv=scalarsetlist; sv!=NULL; sv = sv->next) fprintf(codefile, " // enter the result into class\n" " if (Perm.MTO_class_%s())\n" " {\n" " for (i=0; i<%d; i++)\n" " for (j=0; j<%d; j++)\n" " if (pos_%s[i][j])\n" " Perm.class_%s[j] = i;\n" " Perm.undefined_class_%s=0;\n" " for (j=0; j<%d; j++)\n" " if (Perm.class_%s[j]>Perm.undefined_class_%s)\n" " Perm.undefined_class_%s=Perm.class_%s[j];\n" " }\n", sv->e->mu_name, sv->e->getsize(), sv->e->getsize(), // i-for j-for sv->e->mu_name, // pos sv->e->mu_name, // class sv->e->mu_name, // undefined_class sv->e->getsize(), // i-for sv->e->mu_name, sv->e->mu_name, // class_%s undefined_class_%s sv->e->mu_name, sv->e->mu_name // undefined_class_%s class_%s ); fprintf(codefile,"}\n"); } else fprintf(codefile, "void %s::Limit(PermSet& Perm){}\n", mu_name); } void recordtypedecl::generate_limit_function(symmetryclass& symmetry) { ste *f; if (already_generated_limit_function) return; else already_generated_limit_function = TRUE; for (f = fields; f != NULL; f = f->next) f->getvalue()->gettype()->generate_limit_function(symmetry); fprintf(codefile, "void %s::Limit(PermSet& Perm)\n" "{\n", mu_name ); for (f = fields; f != NULL; f = f->next) if (f->getvalue()->gettype()->getstructure() != typedecl::NoScalarset && f->getvalue()->gettype()->getstructure() != typedecl::ScalarsetVariable && f->getvalue()->gettype()->getstructure() != typedecl::ScalarsetArrayOfFree && f->getvalue()->gettype()->getstructure() != typedecl::MultisetOfFree) fprintf(codefile, " %s.Limit(Perm);\n", f->getvalue()->generate_code() ); fprintf(codefile,"};\n"); } void scalarsettypedecl::generate_limit_function(symmetryclass& symmetry) { if (already_generated_limit_function) return; else already_generated_limit_function = TRUE; fprintf(codefile, "void %s::Limit(PermSet& Perm) {}\n", mu_name); } void uniontypedecl::generate_limit_function(symmetryclass& symmetry) { if (already_generated_limit_function) return; else already_generated_limit_function = TRUE; fprintf(codefile, "void %s::Limit(PermSet& Perm) {}\n", mu_name); } void typedecl::generate_limit_function(symmetryclass& symmetry) { Error.Error("Internal: typedecl::generate_limit_function()"); }; /******************** generate MultisetLimit() for each typedecl ********************/ void enumtypedecl::generate_multisetlimit_function(symmetryclass& symmetry) { if (already_generated_multisetlimit_function) return; else already_generated_multisetlimit_function = TRUE; if (strcmp(mu_name,"mu_0_boolean")!=0) fprintf(codefile, "void %s::MultisetLimit(PermSet& Perm)\n" "{ Error.Error(\"Internal: calling MultisetLimit for enum type.\\n\"); };\n", mu_name); }; void subrangetypedecl::generate_multisetlimit_function(symmetryclass& symmetry) { if (already_generated_multisetlimit_function) return; else already_generated_multisetlimit_function = TRUE; fprintf(codefile, "void %s::MultisetLimit(PermSet& Perm)\n" "{ Error.Error(\"Internal: calling MultisetLimit for subrange type.\\n\"); };\n", mu_name); }; void multisettypedecl::generate_multiset_simple_sort() { // similar to MultisetSort // but use CompareWeight instead of Compare, // ignoring the part of elements with scalarset fprintf(codefile, " PerThread< %s > temp_; %s &temp = temp_.get();\n" "\n" " // compact\n" " for (i = 0, j = 0; i < %d; i++)\n" " if (valid[i].value())\n" " {\n" " if (j!=i)\n" " array[j++] = array[i];\n" " else\n" " j++;\n" " }\n" " if (j != current_size) current_size = j;\n" " for (i = j; i < %d; i++)\n" " array[i].undefine();\n" " for (i = 0; i < j; i++)\n" " valid[i].value(TRUE);\n" " for (i = j; i < %d; i++)\n" " valid[i].value(FALSE);\n" "\n" " // bubble sort\n" " for (i = 0; i < current_size; i++)\n" " for (j = i+1; j < current_size; j++)\n" " if (CompareWeight(array[i],array[j])>0)\n" " {\n" " temp = array[i];\n" " array[i] = array[j];\n" " array[j] = temp;\n" " }\n", elementtype->generate_code(), elementtype->generate_code(), maximum_size, maximum_size, maximum_size ); fprintf(codefile, " // initializing pos array\n" " for (i=0; inext) fprintf(codefile, " while_guard = while_guard || (Perm.MTO_class_%s() && count_%s<%d);\n", sl->e->mu_name, sl->e->mu_name, sl->e->getsize() ); fprintf(codefile, " while ( while_guard )\n" " {\n" " oldcount_multisetindex = count_multisetindex;\n" ); // setup oldcount for (sl=scalarsetlist; sl!=NULL; sl = sl->next) fprintf(codefile, " oldcount_%s = count_%s;\n", sl->e->mu_name, sl->e->mu_name ); } void multisettypedecl::generate_multiset_while_guard(charlist * scalarsetlist) { charlist * sl; fprintf(codefile, " while_guard = oldcount_multisetindex!=count_multisetindex;\n"); for (sl=scalarsetlist; sl!=NULL; sl = sl->next) fprintf(codefile, " while_guard = while_guard || (oldcount_%s!=count_%s);\n", sl->e->mu_name, sl->e->mu_name ); fprintf(codefile, " while_guard_temp = while_guard;\n"); fprintf(codefile, " while_guard = (count_multisetindex < current_size);\n"); for (sl=scalarsetlist; sl!=NULL; sl = sl->next) fprintf(codefile, " while_guard = while_guard || count_%s<%d;\n", sl->e->mu_name, sl->e->getsize() ); fprintf(codefile, " while_guard = while_guard && while_guard_temp;\n"); } void multisettypedecl::generate_limit_step1(int limit_strategy) { generate_limit_step2("",elementtype,0,limit_strategy); } void multisettypedecl::generate_limit_step2(const char * var, typedecl * e, int local_num, int limit_strategy) { stelist * t; ste * f; typedecl * e2, * d2; // please check that scalarset of size 1 is handled by sort in the other routine if (e->gettypeclass() == typedecl::Scalarset && e->getsize() > 1) generate_limit_step3(var, e, limit_strategy, FALSE); else if (e->gettypeclass() == typedecl::Union && ((uniontypedecl *)e)->IsUnionWithScalarset()) { for(t=((uniontypedecl *)e)->getunionmembers(); t!= NULL; t=t->next) { d2 = (typedecl *)t->s->getvalue(); if (d2->gettypeclass() == typedecl::Scalarset && d2->getsize() > 1 ) generate_limit_step3(var, d2, limit_strategy, TRUE); } } else if (e->gettypeclass() == typedecl::Array) { e2 = e->getindextype(); switch (e2->gettypeclass()) { case typedecl::Scalarset: if (e2->getsize() == 1) generate_limit_step2(tsprintf("%s[mu_%s]",var,((scalarsettypedecl *)e2)->getidvalues()->getname()->getname()), e->getelementtype(), local_num, limit_strategy); break; case typedecl::Union: for(t=((uniontypedecl *)e2)->getunionmembers(); t!= NULL; t=t->next) { d2 = (typedecl *)t->s->getvalue(); switch (d2->gettypeclass()) { case typedecl::Enum: for (f = ((enumtypedecl *) d2)->getidvalues(); f!=NULL && type_equal( f->getvalue()->gettype(), d2); f = f->getnext()) generate_limit_step2(tsprintf("%s[mu_%s]",var,f->getname()->getname()), e->getelementtype(), local_num, limit_strategy); break; case typedecl::Range: fprintf(codefile, " // loop through elements of a array indexed by subrange(union)\n" " for (i%d = %d; i%d <= %d; i%d++)\n" " {\n", local_num, d2->getleft(), local_num, d2->getright(), local_num); generate_limit_step2(tsprintf("%s[i%d]",var,local_num), e->getelementtype(), local_num+1, limit_strategy); fprintf(codefile, " }\n"); break; default: abort(); } } case typedecl::Enum: for (f = ((enumtypedecl *)e2)->getidvalues(); f!=NULL && type_equal( f->getvalue()->gettype(), e2); f = f->getnext()) generate_limit_step2(tsprintf("%s[mu_%s]",var,f->getname()->getname()), e->getelementtype(), local_num, limit_strategy); break; case typedecl::Range: fprintf(codefile, " // loop through elements of a array indexed by subrange\n" " for (i%d = %d; i%d <= %d; i%d++)\n" " {\n", local_num, e2->getleft(), local_num, e2->getright(), local_num); generate_limit_step2(tsprintf("%s[i%d]",var,local_num), e->getelementtype(), local_num+1, limit_strategy); fprintf(codefile, " }\n"); break; default: abort(); } } else if (e->gettypeclass() == typedecl::Record) { for (f = e->getfields(); f != NULL; f = f->next) { generate_limit_step2(tsprintf("%s.mu_%s",var, f->getname()->getname()), f->getvalue()->gettype(), local_num, limit_strategy); } } } void multisettypedecl::generate_limit_step3(const char * var, typedecl * e, int limit_strategy, bool isunion) { if (limit_strategy == 5) generate_multiset_limit5(var, e->mu_name, e->getsize(), e->getleft(), isunion); } void multisettypedecl::generate_multiset_limit5(const char * var, typedecl * e) { stelist * t; typedecl * d2; int thisright; int thisleft; if (e->gettypeclass() == typedecl::Scalarset && e->getsize() > 1) generate_multiset_limit5(var,e->mu_name, e->getsize(), e->getleft(),FALSE); else if (e->gettypeclass() == typedecl::Union) { thisright = e->getsize()-1; for(t=((uniontypedecl *)e)->getunionmembers(); t!= NULL; t=t->next) { d2 = (typedecl *)t->s->getvalue(); thisleft = thisright-d2->getsize()+1; if (d2->gettypeclass() == typedecl::Scalarset && d2->getsize() > 1) fprintf(codefile, "\n" " // refinement -- graph structure for two scalarsets\n" " // as in array S1 of S2\n" " // only if there is more than 1 permutation in class\n" " if ( (count_multisetindex=%d\n" " && (*this)[k]%s<=%d)\n" " split = TRUE;\n" " if (split)\n" " {\n" " for (i=0; i=%d\n" // extra checking " && (*this)[k]%s<=%d\n" // extra checking " && pos_%s[j][(*this)[k]%s-%d])\n" " {\n" " exists = TRUE;\n" " goodset_multisetindex[k] = TRUE;\n" " goodset_%s[(*this)[k]%s-%d] = TRUE;\n" " }\n" " if (exists)\n" " {\n" " // set split for the array index type\n" " split=FALSE;\n" " for (k=0; ki; z--)\n" " for (k=0; kj; z--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[z][k] = pos_%s[z-1][k];\n" " // split pos\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[j][k] && !goodset_%s[k])\n" " pos_%s[j][k] = FALSE;\n" " if (pos_%s[j+1][k] && goodset_%s[k])\n" " pos_%s[j+1][k] = FALSE;\n" " }\n" " count_%s++;\n" " }\n" " }\n" " }\n" " }\n" " }\n", d2->mu_name, d2->mu_name, d2->getsize(), // if guard2 var, // (*this)[k]%s // var, thisleft, // (*this)[k]%s<%d // var, thisright, // (*this)[k]%s>%d var, d2->getleft(), // (*this)[k]%s<%d var, d2->getright(), // (*this)[k]%s>%d d2->mu_name, // j-for d2->getsize(), d2->mu_name, // initialize goodset var, // if condition // var, thisleft, // (*this)[k_%d]%s<%d // var, thisright, // (*this)[k_%d]%s>%d var, d2->getleft(), // (*this)[k]%s<%d var, d2->getright(), // (*this)[k]%s>%d d2->mu_name, var, d2->getleft(), // if condition (cont) d2->mu_name, var, d2->getleft(), // set goodsets d2->getsize(), // k-for -- split d2->mu_name, d2->mu_name, // if condition d2->mu_name, d2->getsize(), d2->mu_name, d2->mu_name, // move pos down 1 step d2->getsize(), d2->mu_name, d2->mu_name, d2->mu_name, // split pos d2->mu_name, d2->mu_name, d2->mu_name, // split pos (cont) d2->mu_name // count_%s ); thisright= thisleft-1; } } } void multisettypedecl::generate_multiset_limit5(const char *var, const char * name2, int size2, int left2, bool isunion) { if (isunion) fprintf(codefile, "\n" " // refinement -- graph structure for two scalarsets\n" " // as in array S1 of S2\n" " // only if there is more than 1 permutation in class\n" " if ( (count_multisetindex=%d\n" " && (*this)[k]%s<=%d)\n" " split = TRUE;\n" " if (split)\n" " {\n" " for (i=0; i=%d\n" // extra checking " && (*this)[k]%s<=%d\n" // extra checking " && pos_%s[j][(*this)[k]%s-%d])\n" " {\n" " exists = TRUE;\n" " goodset_multisetindex[k] = TRUE;\n" " goodset_%s[(*this)[k]%s-%d] = TRUE;\n" " }\n" " if (exists)\n" " {\n" " // set split for the array index type\n" " split=FALSE;\n" " for (k=0; ki; z--)\n" " for (k=0; kj; z--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[z][k] = pos_%s[z-1][k];\n" " // split pos\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[j][k] && !goodset_%s[k])\n" " pos_%s[j][k] = FALSE;\n" " if (pos_%s[j+1][k] && goodset_%s[k])\n" " pos_%s[j+1][k] = FALSE;\n" " }\n" " count_%s++;\n" " }\n" " }\n" " }\n" " }\n" " }\n", name2, name2, size2, // if guard2 var, // (*this)[k]%s var, left2, // (*this)[k]%s<%d var, left2+size2-1, // (*this)[k]%s>%d name2, // j-for size2, name2, // initialize goodset var, // if condition var, left2, // (*this)[k]%s<%d var, left2+size2-1, // (*this)[k]%s>%d name2, var, left2, // if condition (cont) name2, var, left2, // set goodsets size2, // k-for -- split name2, name2, // if condition name2, size2, name2, name2, // move pos down 1 step size2, name2, name2, name2, // split pos name2, name2, name2, // split pos (cont) name2 // count_%s ); else fprintf(codefile, "\n" " // refinement -- graph structure for two scalarsets\n" " // as in array S1 of S2\n" " if ( ( count_multisetindexi; z--)\n" " for (k=0; kj; z--)\n" " for (k=0; k<%d; k++)\n" " pos_%s[z][k] = pos_%s[z-1][k];\n" " // split pos\n" " for (k=0; k<%d; k++)\n" " {\n" " if (pos_%s[j][k] && !goodset_%s[k])\n" " pos_%s[j][k] = FALSE;\n" " if (pos_%s[j+1][k] && goodset_%s[k])\n" " pos_%s[j+1][k] = FALSE;\n" " }\n" " count_%s++;\n" " }\n" " }\n" " }\n" " }\n" " }\n", name2, name2, size2, // if guard2 var, // (*this)[k_%d]%s name2, // j-for size2, name2, // initialize goodset var, // if condition name2, var, left2, // if condition (cont) name2, var, left2, // set goodsets size2, // k-for -- split name2, name2, // if condition name2, size2, name2, name2, // move pos down 1 step size2, name2, name2, name2, // split pos name2, name2, name2, // split pos (cont) name2 // count_%s ); } void multisettypedecl::generate_multisetlimit_function(symmetryclass& symmetry) { charlist * scalarsetlist; charlist * scalarsetvalue; charlist * sv; if (already_generated_multisetlimit_function) return; else already_generated_multisetlimit_function = TRUE; elementtype->generate_multisetlimit_function(symmetry); if (!elementtype->HasScalarsetVariable()) fprintf(codefile, "void %s::MultisetLimit(PermSet& Perm)\n" "{ Error.Error(\"Internal: calling MultisetLimit for multiset type of scalarset-free elements.\\n\"); };\n", mu_name); else { fprintf(codefile, "void %s::MultisetLimit(PermSet& Perm)\n" "{\n" " // indexes\n" " int i,j,k,z;\n" " // while guard\n" " bool while_guard, while_guard_temp;\n" " // sorting\n" " static PerThread< std::vector< %s > > value_( std::vector< %s >( %d ) );\n" " std::vector< %s > &value = value_.get();\n" " // limit\n" " bool exists;\n" " bool split;\n", mu_name, // %s::Canonicalize elementtype->mu_name, elementtype->mu_name, maximum_size, elementtype->mu_name // %s value[%d] ); // get a list for all scalarsets that may appear scalarsetlist = generate_scalarset_list(NULL); // added by Uli fprintf(codefile, " int i0"); for (int i = get_num_limit_locals(elementtype)-1; i>0; i--) fprintf(codefile,",i%d",i); fprintf(codefile, ";\n"); // declare for all scalarsets that may appear for (sv=scalarsetlist; sv!=NULL; sv = sv->next) fprintf(codefile, " int count_%s, oldcount_%s;\n" " bool pos_%s[%d][%d];\n" " bool goodset_%s[%d];\n", sv->e->mu_name, sv->e->mu_name, sv->e->mu_name, sv->e->getsize(), sv->e->getsize(), sv->e->mu_name, sv->e->getsize() ); // declare for the indexes of the multiset fprintf(codefile, " int count_multisetindex, oldcount_multisetindex;\n" " bool pos_multisetindex[%d][%d];\n" " bool goodset_multisetindex[%d];\n", maximum_size, maximum_size, maximum_size ); generate_multiset_simple_sort(); fprintf(codefile, " if (current_size == 1)\n" " {\n" ); if (elementtype->HasScalarsetVariable()) fprintf(codefile, " array[0].SimpleLimit(Perm);\n" ); if (elementtype->HasScalarsetArrayOfFree()) fprintf(codefile, " array[0].ArrayLimit(Perm);\n" ); if (elementtype->HasScalarsetArrayOfS()) fprintf(codefile, " array[0].Limit(Perm);\n" ); fprintf(codefile, " }\n" " else\n" " {\n" "\n" ); for (sv=scalarsetlist; sv!=NULL; sv = sv->next) fprintf(codefile, " // initializing pos array\n" " for (i=0; i<%d; i++)\n" " for (j=0; j<%d; j++)\n" " pos_%s[i][j]=FALSE;\n" " count_%s = 0;\n" " while (1)\n" " {\n" " exists = FALSE;\n" " for (i=0; i<%d; i++)\n" " if (Perm.class_%s[i] == count_%s)\n" " {\n" " pos_%s[count_%s][i]=TRUE;\n" " exists = TRUE;\n" " }\n" " if (exists) count_%s++;\n" " else break;\n" " }\n", sv->e->getsize(), sv->e->getsize(), sv->e->mu_name, // initialization sv->e->mu_name, // count_%s sv->e->getsize(), // i-for sv->e->mu_name, sv->e->mu_name, // if-guard sv->e->mu_name, sv->e->mu_name, // pos_%s[count%s] sv->e->mu_name // count_%s ); // have to generate the while loop generate_multiset_while(scalarsetlist); // refine according to directed graph of Array S1 of S2 where S1 != S2 // for (sv=scalarsetvalue; sv!=NULL; sv = sv->next) // if (sv->e->getsize() > 1) // generate_multiset_limit5(sv->string, sv->e); generate_limit_step1(5); // set while guard generate_multiset_while_guard(scalarsetlist); // end while loop fprintf(codefile, " } // end while\n"); // enter result for (sv=scalarsetlist; sv!=NULL; sv = sv->next) fprintf(codefile, " // enter the result into class\n" " if (Perm.MTO_class_%s())\n" " {\n" " for (i=0; i<%d; i++)\n" " for (j=0; j<%d; j++)\n" " if (pos_%s[i][j])\n" " Perm.class_%s[j] = i;\n" " Perm.undefined_class_%s=0;\n" " for (j=0; j<%d; j++)\n" " if (Perm.class_%s[j]>Perm.undefined_class_%s)\n" " Perm.undefined_class_%s=Perm.class_%s[j];\n" " }\n", sv->e->mu_name, sv->e->getsize(), sv->e->getsize(), // i-for j-for sv->e->mu_name, // pos sv->e->mu_name, // class sv->e->mu_name, // undefined_class sv->e->getsize(), // i-for j-for sv->e->mu_name, sv->e->mu_name, // class_%s undefined_class_%s sv->e->mu_name, sv->e->mu_name // undefined_class_%s class_%s ); fprintf(codefile, " }\n" "}\n"); } } void arraytypedecl::generate_multisetlimit_function(symmetryclass& symmetry) { if (already_generated_multisetlimit_function) return; else already_generated_multisetlimit_function = TRUE; elementtype->generate_multisetlimit_function(symmetry); if ( indextype->getstructure() != typedecl::ScalarsetVariable && elementtype->HasMultisetOfScalarset() ) { fprintf(codefile, "void %s::MultisetLimit(PermSet& Perm)\n" "{\n" " for (int j=0; j<%d; j++) {\n" " array[j].MultisetLimit(Perm);\n" " }\n" "}\n", mu_name, // %s::Fast... indextype->getsize() // j-for ); } else fprintf(codefile, "void %s::MultisetLimit(PermSet& Perm)\n" "{ Error.Error(\"Internal: calling MultisetLimit for scalarset array.\\n\"); };\n", mu_name); }; void recordtypedecl::generate_multisetlimit_function(symmetryclass& symmetry) { if (already_generated_multisetlimit_function) return; else already_generated_multisetlimit_function = TRUE; ste *f; for (f = fields; f != NULL; f = f->next) f->getvalue()->gettype()->generate_limit_function(symmetry); fprintf(codefile, "void %s::MultisetLimit(PermSet& Perm)\n" "{\n", mu_name ); for (f = fields; f != NULL; f = f->next) if (f->getvalue()->gettype()->HasMultisetOfScalarset()) fprintf(codefile, " %s.MultisetLimit(Perm);\n", f->getvalue()->generate_code() ); fprintf(codefile,"};\n"); }; void scalarsettypedecl::generate_multisetlimit_function(symmetryclass& symmetry) { if (already_generated_multisetlimit_function) return; else already_generated_multisetlimit_function = TRUE; fprintf(codefile, "void %s::MultisetLimit(PermSet& Perm)\n" "{ Error.Error(\"Internal: calling MultisetLimit for scalarset type.\\n\"); };\n", mu_name); }; void uniontypedecl::generate_multisetlimit_function(symmetryclass& symmetry) { if (already_generated_multisetlimit_function) return; else already_generated_multisetlimit_function = TRUE; fprintf(codefile, "void %s::MultisetLimit(PermSet& Perm)\n" "{ Error.Error(\"Internal: calling MultisetLimit for union type.\\n\"); };\n", mu_name); }; void typedecl::generate_multisetlimit_function(symmetryclass& symmetry) { Error.Error("Internal: typedecl::generate_multisetlimit_function()"); }; /**************************************** * 20 Dec 93 Norris Ip: basic structures * 31 Jan 94 Norris Ip: Only generate useful scalarset/scalarsetunion functions * 16 Feb 94 Norris Ip: Break down arraytypedecl into a series of procedures * 23 Feb 94 Norris Ip: debuged limit, limit2, limit3, and limit4 expanding limit4 to more general case * 1 March 94 Norris Ip: added virtual void generate_simple_limit_function(symmetryclass& symmetry); virtual void generate_array_limit_function(symmetryclass& symmetry); ****** * Subject: Extension for {multiset, undefined value, general union} * 25 May 94 Norris Ip: change all scalarsetunion to union handled enum in union beta2.9S released * 14 July 95 Norris Ip: Tidying/removing old algorithm adding small memory algorithm for larger scalarsets ****************************************/ /******************** $Log: cpp_sym_decl.C,v $ Revision 1.2 1999/01/29 07:49:12 uli bugfixes Revision 1.4 1996/08/07 18:54:00 ip last bug fix on NextRule/SetNextEnabledRule has a bug; fixed this turn Revision 1.3 1996/08/07 00:59:13 ip Fixed bug on what_rule setting during guard evaluation; otherwise, bad diagnoistic message on undefine error on guard Revision 1.2 1996/08/06 23:57:39 ip fixed while code generation bug Revision 1.1 1996/08/06 23:56:55 ip Initial revision ********************/