ERROR(msg);
assert false : msg;
    public void computeSteadyState()    {        // amount of data distributed to and collected by the split        // and join        //        int splitPushWeights[];        //        int joinPopWeights[];        //        int splitPopWeight, joinPushWeight;        Fraction childrenRates[] = new Fraction[nChildren];        Fraction splitRate = null;        Fraction joinRate = null;        // go through all children and calculate the rates at which        // they will be called w.r.t. the splitter.        // also, compute the rate of execution of the joiner        // (if it ever ends up being executed)        {            int nChild;            for (nChild = 0; nChild < nChildren; nChild++)                {                    StreamInterface child = children[nChild];                    assert child != null;                    // the rate at which the child should be executed                    Fraction childRate = null;                    // rates at which the splitter is producing the data                    // and the child is consuming it:                    int numOut = getSteadySplitFlow().getPushWeight(nChild);                    int numIn = child.getSteadyPop();                    // is the splitter actually producing any data?                    if (numOut != 0)                        {                            // if the slitter is producing data, the child better                            // be consuming it!                            assert numIn != 0;                            if (splitRate == null)                                {                                    // if I hadn't set the split rate yet, do it now                                    splitRate =                                        new Fraction(BigInteger.ONE, BigInteger.ONE);                                }                            // compute the rate at which the child should be executing                            // (relative to the splitter)                            childRate =                                new Fraction(numOut, numIn)                                .multiply(splitRate)                                .reduce();                            // if I still hadn't computed the rate at which the joiner                            // is executed, try to compute it:                            if (joinRate == null && child.getSteadyPush() != 0)                                {                                    // if the child is producing data, the joiner                                    // better be consuming it!                                    assert getSteadyJoinFlow().getPopWeight(nChild) != 0;                                    int childOut = child.getSteadyPush();                                    int joinIn = getSteadyJoinFlow().getPopWeight(nChild);                                    joinRate =                                        new Fraction(childOut, joinIn)                                        .multiply(childRate)                                        .reduce();                                }                        }                    childrenRates[nChild] = childRate;                    // Debugging:                    if (debugsplitjoin) {                        if (librarydebug) {                            System.err.print(splitjoin.getObject().getClass().getName());                        } else {                            System.err.print(((SIRStream)splitjoin.getObject()).getIdent());                        }                        System.err.println("[" + nChild + "].splitRate = " + childRate);                    }                    // End Debugging                }        }        // compute the rate of execution of the joiner w.r.t. children        // and make sure that everything will be executed at consistant        // rates (to avoid overflowing the buffers)        {            // if the splitter never needs to get executed (doesn't produce            // any data), the joiner rate should be set to ONE:            if (splitRate == null)                {                    // I better not have computed the join rate yet!                    assert joinRate == null;                    // okay, just set it to ONE/ONE                    joinRate = new Fraction(BigInteger.ONE, BigInteger.ONE);                }            int nChild;            for (nChild = 0; nChild < nChildren; nChild++)                {                    StreamInterface child = children[nChild];                    assert child != null;                    // get the child rate                    Fraction childRate = childrenRates[nChild];                    // compute the new childRate:                    Fraction newChildRate = null;                    {                        int childOut = child.getSteadyPush();                        int joinIn = getSteadyJoinFlow().getPopWeight(nChild);                        // does the child produce any data?                        if (childOut != 0)                            {                                // yes                                // the split better consume some data too!                                assert joinIn != 0;                                // compute the rate at which the child should execute                                // w.r.t. the splitter                                newChildRate =                                    new Fraction(joinIn, childOut)                                    .multiply(joinRate)                                    .reduce();                            }                        else                            {                                // no                                // the splitter better not consume any data either                                assert joinIn == 0;                            }                    }                    // if this is a new rate, put it in the array                    if (childRate == null)                        {                            // I better have the rate here, or the child                            // neither produces nor consumes any data!                            assert newChildRate != null;                            // set the rate                            childrenRates[nChild] = newChildRate;                            // Debugging:                            if (debugsplitjoin) {                                if (librarydebug) {                                    System.err.print(splitjoin.getObject().getClass().getName());                                } else {                                    System.err.print(((SIRStream)splitjoin.getObject()).getIdent());                                }                                System.err.println("[" + nChild + "].joinRate = " + childRate);                            }                            // End Debugging                        }                    // okay, if I have both rates, make sure that they agree!                    if (childRate != null && newChildRate != null)                        {                            if (!childRate.equals(newChildRate))                                {                                    String name = "" + splitjoin.getObject();                                    String msg = "ERROR:\n" +                                        "Two paths in the splitjoin \"" + name + "\" have different I/O rates.\n" +                                        "One path produces items at a rate of " + childRate + ", while another has a rate of " + newChildRate + ".\n" +                                         "Thus, the program cannot be executed without growing a buffer infinitely.\n" +                                        "Please check that the round-robin weights match the I/O rates of the\n" +                                        "child streams.\n";                                    // anonymous names aren't too helpful                                    if (name.startsWith("Anon") /* for library */ || name.startsWith("name=Anon") /* for compiler */ ) {                                        msg += "\n" +                                             "Note:  the name \"" + name + "\" indicates that this splitjoin is an\n" +                                            "anonymous wrapper in your program.  You can identify this wrapper by\n" +                                            "opening up the <filename>.java file and searching for this identifier,\n" +                                            "or by refactoring your program to give the splitjoin its own name.\n";                                    }                                    ERROR(msg);                                }                        }                }        }        // normalize all the rates to be integers        {            BigInteger multiplier;            if (joinRate != null)                {                    multiplier = joinRate.getDenominator();                }            else                {                    multiplier = BigInteger.ONE;                }            // find a factor to multiply all the fractional rates by            {                int index;                for (index = 0; index < nChildren; index++)                    {                        Fraction childRate = (Fraction) childrenRates[index];                        assert childRate != null;                        BigInteger rateDenom = childRate.getDenominator();                        assert rateDenom != null;                        BigInteger gcd = multiplier.gcd(rateDenom);                        multiplier = multiplier.multiply(rateDenom).divide(gcd);                    }            }            // multiply all the rates by this factor and set the rates for            // the children and splitter and joiner            {                if (splitRate != null)                    {                        splitRate = splitRate.multiply(multiplier);                        assert splitRate.getDenominator().equals(BigInteger.ONE);                        splitNumRounds = splitRate.getNumerator();                    }                else                    {                        splitNumRounds = BigInteger.ZERO;                    }                if (joinRate != null)                    {                        joinRate = joinRate.multiply(multiplier);                        assert joinRate.getDenominator().equals(BigInteger.ONE);                        joinNumRounds = joinRate.getNumerator();                    }                else                    {                        joinNumRounds = BigInteger.ZERO;                    }                // normalize the children's rates and store them in                // childrenNumExecs                {                    childrenNumExecs = new BigInteger[nChildren];                    int nChild;                    for (nChild = 0; nChild < nChildren; nChild++)                        {                            Fraction childRate = (Fraction) childrenRates[nChild];                            assert childRate != null;                            Fraction newChildRate =                                childRate.multiply(multiplier);                            assert newChildRate.getDenominator()                                .equals(BigInteger.ONE);                            // set the rate                            childrenNumExecs[nChild] =                                newChildRate.getNumerator();                            // Debugging:                            if (debugsplitjoin) {                                if (librarydebug) {                                    System.err.print(splitjoin.getObject().getClass().getName());                                } else {                                    System.err.print(((SIRStream)splitjoin.getObject()).getIdent());                                }                                System.err.println("[" + nChild + "] executions = " + childrenNumExecs[nChild]);                            }                            // End Debugging                            // make sure that the child executes a positive                            // number of times!                            assert childrenNumExecs[nChild].signum() == 1;                        }                }            }        }        // setup my variables that come for Stream:        {            int pop =                splitNumRounds.intValue()                * getSteadySplitFlow().getPopWeight();            int push =                joinNumRounds.intValue()                * getSteadyJoinFlow().getPushWeight();            setSteadyPeek(pop);            setSteadyPop(pop);            setSteadyPush(push);            // Debugging:            if (debugrates) {                if (librarydebug) {                    System.err.print(splitjoin.getObject().                                     getClass().getName());                } else {                    System.err.print(((SIRStream)splitjoin.getObject())                                     .getIdent());                 }                System.err.println(" steady state: push " + push + " pop " + pop);            }                                   // End Debugging        }    }