Ternary.java Source code

Java tutorial

Introduction

Here is the source code for Ternary.java

Source

/*
 * @(#)Ternary.java   1.0 Mar 7, 2008
 *
 *   The MIT License
 *
 *   Copyright (c) 2008 Malachi de AElfweald <malachid@gmail.com>
 *
 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 *   of this software and associated documentation files (the "Software"), to deal
 *   in the Software without restriction, including without limitation the rights
 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *   copies of the Software, and to permit persons to whom the Software is
 *   furnished to do so, subject to the following conditions:
 *
 *   The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *   THE SOFTWARE.
 */
//package org.eoti.math.ternary;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.concurrent.CopyOnWriteArrayList;

public class Ternary extends Number implements Comparable<Ternary> {
    protected BigInteger biThree = BigInteger.valueOf(3);
    protected BigDecimal bdThree = new BigDecimal(biThree);
    protected CopyOnWriteArrayList<Trit> trits;

    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.format("java org.eoti.lang.Ternary number [[number]...]\n");
            System.exit(0);
        }

        for (String arg : args) {
            BigInteger toConvert = new BigInteger(arg);
            Ternary ternary = new Ternary(toConvert);
            System.out.format("\nDecimal:\t%s\nTernary:\t%s\n", toConvert, ternary);
        }
    }

    public Ternary(int toConvert) {
        this(BigInteger.valueOf(toConvert));
    }

    public Ternary(BigInteger toConvert) {
        this();
        int position = 0;
        BigInteger remaining = toConvert;
        BigInteger rounded, left;
        while (!remaining.equals(BigInteger.ZERO)) {
            rounded = ((new BigDecimal(remaining)).divide(bdThree, 0, BigDecimal.ROUND_HALF_UP)).toBigInteger();
            left = remaining.subtract(rounded.multiply(biThree));
            if (left.equals(BigInteger.ONE))
                setTrit(position++, Trit.POSITIVE);
            else if (left.equals(BigInteger.ZERO))
                setTrit(position++, Trit.NEUTRAL);
            else
                setTrit(position++, Trit.NEGATIVE);
            remaining = rounded;
        }
    }

    public Ternary() {
        super();
        trits = new CopyOnWriteArrayList<Trit>();
    }

    public Ternary(Ternary toClone) {
        this();
        trits.addAll(toClone.trits);
    }

    public Ternary abs() {
        if (signum() >= 0)
            return new Ternary(this);
        return invert(this);
    }

    public int tritLength() {
        for (int position = trits.size() - 1; position >= 0; position--) {
            if (!trits.get(position).equals(Trit.NEUTRAL))
                return position + 1;
        }

        return 0;
        //return trits.size();
    }

    public void clearTrit(int position) {
        setTrit(position, Trit.NEUTRAL);
    }

    public void setTrit(int position, Trit trit) {
        if (trits.size() <= position)
            ensureCapacity(position + 1);

        trits.set(position, trit);
    }

    public Trit getTrit(int position) {
        if (position < 0)
            return Trit.NEUTRAL;

        if (trits.size() <= position)
            ensureCapacity(position + 1);

        return trits.get(position);
    }

    public int signum() {
        return getTrit(tritLength() - 1).toInt();
    }

    public void ensureCapacity(int nTerts) {
        while (trits.size() < nTerts)
            trits.add(Trit.NEUTRAL);
    }

    public void trim() {
        while ((trits.size() > 0) && (trits.get(trits.size() - 1).isNeutral()))
            trits.remove(trits.size() - 1);
    }

    public void increment() {
        increment(0);
    }

    public void increment(int position) {
        Trit t = getTrit(position).rotateUp();
        setTrit(position, t);
        if (t.isNegative()) // carry
            increment(position + 1);
    }

    public void decrement() {
        decrement(0);
    }

    public void decrement(int position) {
        Trit t = getTrit(position).rotateDown();
        setTrit(position, t);
        if (t.isPositive()) // borrow
            decrement(position + 1);
    }

    public String toString() {
        if (trits.size() == 0)
            return Trit.NEUTRAL.toString();

        StringBuilder sb = new StringBuilder();
        for (Trit trit : trits)
            sb.append(trit);

        return sb.reverse().toString();
    }

    public int compareTo(Ternary t) {
        // shortcut if one is positive and the other negative
        int ourSig = signum();
        int theirSig = t.signum();
        if (ourSig > theirSig)
            return 1;
        if (theirSig > ourSig)
            return -1;

        // we're the same sign... who has more trits?
        int ourLength = tritLength();
        int theirLength = t.tritLength();
        if (ourLength > theirLength)
            return (ourSig > 0 ? 1 : -1);
        if (theirLength > ourLength)
            return (ourSig > 0 ? -1 : 1);

        // same sign, same length... guess we need to find first mismatch
        for (int position = ourLength - 1; position >= 0; position--) {
            int comparison = getTrit(position).compareTo(t.getTrit(position));
            if (comparison != 0)
                return comparison;
        }

        // guess we are identical
        return 0;
    }

    public boolean equals(Object obj) {
        if (obj == null)
            return false;
        return toString().equals(obj.toString());
    }

    public int hashCode() {
        return toString().hashCode();
    }

    public BigInteger toBigInteger() {
        BigInteger toRet = BigInteger.ZERO;
        BigInteger curr;
        for (int pos = 0; pos < trits.size(); pos++) {
            curr = (biThree.pow(pos)).multiply(BigInteger.valueOf(getTrit(pos).toInt()));
            toRet = toRet.add(curr);
        }

        return toRet;
    }

    public void shiftLeft() {
        shiftLeft(1);
    }

    public void shiftLeft(int num) {
        CopyOnWriteArrayList<Trit> newTrits = new CopyOnWriteArrayList<Trit>();
        for (int i = 0; i < num; i++)
            newTrits.add(Trit.NEUTRAL);

        newTrits.addAll(trits);
        trits = newTrits;
    }

    public void shiftRight() {
        shiftRight(1);
    }

    public void shiftRight(int num) {
        ensureCapacity(trits.size() + num);

        for (int i = 0; i < num; i++)
            trits.remove(0);
    }

    public byte byteValue() {
        return toBigInteger().byteValue();
    }

    public double doubleValue() {
        return toBigInteger().doubleValue();
    }

    public float floatValue() {
        return toBigInteger().floatValue();
    }

    public int intValue() {
        return toBigInteger().intValue();
    }

    public long longValue() {
        return toBigInteger().longValue();
    }

    public short shortValue() {
        return toBigInteger().shortValue();
    }

    /**
     * Add the specified addend to this augend
     *
     * @param addend to be added
     * @return ternary summation
     */
    public Ternary add(Ternary addend) {
        /**
         * Try to find a better way of doing this
         * using gate logic
         * and DON'T just use toBigInteger to do it
         */

        // make sure the LONGER one is on top
        if (tritLength() < addend.tritLength())
            return addend.add(this);

        Ternary summation = new Ternary(this);
        Ternary toCarry = new Ternary();
        for (int pos = 0; pos < trits.size(); pos++) {
            Trit a = summation.getTrit(pos);
            Trit b = addend.getTrit(pos);

            switch (a.state) {
            case Negative:
                summation.setTrit(pos, b.rotateDown());
                break;
            case Positive:
                summation.setTrit(pos, b.rotateUp());
                break;
            default:
                summation.setTrit(pos, b);
            }

            if (a.equals(b))
                toCarry.setTrit(pos + 1, a);
        }

        if (toCarry.tritLength() == 0)
            return summation;

        return summation.add(toCarry);
    }

    /**
     * Subtract the specified subtrahend from this minuend
     *
     * @param subtrahend to be subtracted
     * @return ternary difference
     */
    public Ternary subtract(Ternary subtrahend) {
        return add(invert(subtrahend));
    }

    public static Ternary invert(Ternary toInvert) {
        Ternary inverted = new Ternary();
        for (int i = 0; i < toInvert.trits.size(); i++)
            inverted.setTrit(i, toInvert.getTrit(i).invert());

        return inverted;
    }

    /**
     * Multiply this multiplicand by the specified multiplier
     *
     * @param multiplier to multiply by
     * @return ternary product
     */
    public Ternary multiply(Ternary multiplier) {
        /**
         * Try to find a better way of doing this
         * using gate logic
         * and DON'T just use toBigInteger to do it
         */

        // make sure the LONGER one is on top
        if (tritLength() < multiplier.tritLength())
            return multiplier.multiply(this);

        Ternary product = new Ternary();
        for (int posB = 0; posB < multiplier.trits.size(); posB++) {
            Ternary row = new Ternary();
            for (int posA = 0; posA < trits.size(); posA++) {
                Trit a = getTrit(posA);
                Trit b = multiplier.getTrit(posB);
                Trit c = a.equality(b);
                if (a.isNeutral() && b.isNeutral())
                    c = Trit.NEUTRAL;

                row.setTrit(posA + posB, c);
            }

            product = product.add(row);
        }
        return product;
    }

    /**
     * Divide this divided by the specified divisor
     *
     * @param divisor to divide by
     * @return ternary[] containing {quotient,remainder}
     */
    public Ternary[] divide(Ternary divisor) {
        /**
         * 6/3=2r0
         * 6=dividend
         * 3=divisor
         * 2=quotient
         * 0=remainder
         */

        Ternary dividend = new Ternary(this);

        Ternary quotient = new Ternary(0);
        Ternary remainder = new Ternary(0);

        int dividendSign = dividend.signum();
        if (dividendSign == 0)
            return new Ternary[] { quotient, remainder };

        int divisorSign = divisor.signum();
        if (divisorSign == 0)
            throw new ArithmeticException("Divide by Zero not currently supported.");

        if (dividendSign != divisorSign) {
            // if one or the other (not both) are negative, then the result will have a negative quotient
            Ternary tmp = null;
            Ternary[] results = null;
            if (dividendSign < 0) {
                tmp = new Ternary(dividend);
                tmp = invert(tmp);
                //results = tmp.divide(divisor);
                results = tmp.divide(divisor);
            } else {
                tmp = new Ternary(divisor);
                tmp = invert(tmp);
                //results = dividend.divide(tmp);
                results = dividend.divide(tmp);
            }
            quotient = invert(results[0]);
            remainder = dividend.subtract(quotient.multiply(divisor));
            return new Ternary[] { quotient, remainder };
        }

        // two positives or two negatives will be positive results
        if (dividendSign < 0) {
            dividend = invert(dividend);
            divisor = invert(divisor);
        }

        int position = dividend.tritLength() - 1;
        while (position >= 0) {
            remainder = (new Ternary(dividend)).subtract(quotient.multiply(divisor));
            remainder.shiftRight(position);

            int compare = remainder.compareTo(divisor);
            if (compare > 0) {
                quotient.increment();
            } else if (compare < 0) {
                if (position > 0)
                    quotient.shiftLeft(1);

                position--;
            } else {
                quotient.increment();
                position--;
            }
        }

        remainder = (new Ternary(dividend)).subtract(quotient.multiply(divisor));
        return new Ternary[] { quotient, remainder };
    }

    public Ternary sqrt() {
        return sqrt(this);
    }

    public static Ternary sqrt(Ternary number) {
        return sqrt(number, new Ternary(1));
    }

    protected static Ternary sqrt(Ternary number, Ternary guess) {
        // ((n/g) + g)/2: until same result twice in a row

        Ternary result = new Ternary(0);
        Ternary flipA = new Ternary(result);
        Ternary flipB = new Ternary(result);
        boolean first = true;
        while (result.compareTo(guess) != 0) {
            if (!first)
                guess = result;
            else
                first = false;

            result = (number.divide(guess))[0];
            result = result.add(guess);
            result = (result.divide(new Ternary(2)))[0];
            result.trim();

            // handle flip flops
            if (result.equals(flipB))
                return flipA;
            flipB = flipA;
            flipB.trim();
            flipA = result;
            flipA.trim();
        }

        return result;
    }
}

class Trit implements Comparable<Trit>, Comparator<Trit> {
    protected enum State {
        Negative(-1, '\u012B'), Neutral(0, '0'), Positive(1, '1');
        State(int intValue, char charValue) {
            this.intValue = intValue;
            this.charValue = charValue;
        }

        protected int intValue;
        protected char charValue;

        public int toInt() {
            return intValue;
        }

        public char toChar() {
            return charValue;
        }
    }

    // convenience access

    public static final Trit NEGATIVE = new Trit(State.Negative);
    public static final Trit NEUTRAL = new Trit(State.Neutral);
    public static final Trit POSITIVE = new Trit(State.Positive);

    protected State state;

    public Trit(State state) {
        this.state = state;
    }

    public Trit(Trit trit) {
        this.state = trit.state;
    }

    public boolean isNegative() {
        return state == State.Negative;
    }

    public boolean isNeutral() {
        return state == State.Neutral;
    }

    public boolean isPositive() {
        return state == State.Positive;
    }

    public Trit max(Trit other) {
        return toInt() >= other.toInt() ? this : other;
    }

    public Trit min(Trit other) {
        return toInt() <= other.toInt() ? this : other;
    }

    public Trit or(Trit other) {
        return max(other).clone();
    }

    public Trit and(Trit other) {
        return min(other).clone();
    }

    public Trit xor(Trit other) {
        if (isNegative() && other.isNegative())
            return NEGATIVE.clone();
        if (isNegative() && other.isPositive())
            return POSITIVE.clone();
        if (isPositive() && other.isNegative())
            return POSITIVE.clone();
        return NEUTRAL.clone();
    }

    public Trit nand(Trit other) {
        return not(and(other));
    }

    public Trit nor(Trit other) {
        return not(or(other));
    }

    public Trit nxor(Trit other) {
        return not(xor(other));
    }

    /**
     * Invert unary operation
     * ? becomes 1
     * 0 becomes 0
     * 1 becomes ?
     */
    public Trit invert() {
        return not();
    }

    public Trit not() {
        switch (state) {
        case Negative:
            return Trit.POSITIVE.clone();
        case Positive:
            return Trit.NEGATIVE.clone();
        default:
            return Trit.NEUTRAL.clone();
        }
    }

    public Trit not(Trit other) {
        return inequality(other);
    }

    public Trit inequality(Trit other) {
        Trit eq = equality(other);
        if (eq.isPositive())
            return NEGATIVE.clone();
        if (eq.isNegative())
            return POSITIVE.clone();
        return NEUTRAL.clone();
    }

    public Trit disjunction(Trit other) {
        return or(other);
    }

    public Trit conjunction(Trit other) {
        return and(other);
    }

    public Trit equality(Trit other) {
        if (state == other.state)
            return POSITIVE.clone();
        if (isNeutral())
            return NEUTRAL.clone();
        if (other.isNeutral())
            return NEUTRAL.clone();
        return NEGATIVE.clone();
    }

    public Trit implication(Trit other) {
        if (other.isNegative() && isNeutral())
            return NEUTRAL.clone();
        if (other.isNegative() && isPositive())
            return NEGATIVE.clone();
        if (other.isNeutral() && isPositive())
            return NEUTRAL.clone();
        return POSITIVE.clone();
    }

    public Trit alternation(Trit other) {
        return xor(other);
    }

    /**
     * ShiftUp unary operation
     * ? becomes 0
     * 0 becomes 1
     * 1 becomes 1
     */
    public Trit shiftUp() {
        return NEUTRAL.implication(this);
    }

    /**
     * ShiftDown unary operation
     * ? becomes ?
     * 0 becomes ?
     * 1 becomes 0
     */
    public Trit shiftDown() {
        return not(implication(NEUTRAL));
    }

    /**
     * RotateUp unary operation
     * ? becomes 0
     * 0 becomes 1
     * 1 becomes ?
     */
    public Trit rotateUp() {
        /**
         * Change to use gate logic?
         */
        switch (state) {
        case Negative:
            return NEUTRAL.clone();
        case Neutral:
            return POSITIVE.clone();
        default:
            return NEGATIVE.clone();
        }
    }

    /**
     * RotateDown unary operation
     * ? becomes 1
     * 0 becomes ?
     * 1 becomes 0
     */
    public Trit rotateDown() {
        /**
         * Change to use gate logic?
         */
        switch (state) {
        case Negative:
            return POSITIVE.clone();
        case Neutral:
            return NEGATIVE.clone();
        default:
            return NEUTRAL.clone();
        }
    }

    public String toString() {
        return "" + toChar();
    }

    public char toChar() {
        return state.toChar();
    }

    public int toInt() {
        return state.toInt();
    }

    public Trit clone() {
        return new Trit(state);
    }

    public boolean equals(Object obj) {
        if (obj == null)
            return false;
        if (!Trit.class.isAssignableFrom(obj.getClass()))
            return false;
        return (compareTo((Trit) obj) == State.Neutral.toInt());
    }

    public int compareTo(Trit obj) {
        return compare(this, obj);
    }

    public int compare(Trit t1, Trit t2) {
        if (t1.state.toInt() < t2.state.toInt())
            return State.Negative.toInt();

        if (t1.state.toInt() > t2.state.toInt())
            return State.Positive.toInt();

        return State.Neutral.toInt();
    }

    /**
     * Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those
     * provided by <code>java.util.Hashtable</code>.
     * <p/>
     * The general contract of <code>hashCode</code> is: <ul> <li>Whenever it is invoked on the same object more than once
     * during an execution of a Java application, the <tt>hashCode</tt> method must consistently return the same integer,
     * provided no information used in <tt>equals</tt> comparisons on the object is modified. This integer need not remain
     * consistent from one execution of an application to another execution of the same application. <li>If two objects are
     * equal according to the <tt>equals(Object)</tt> method, then calling the <code>hashCode</code> method on each of the
     * two objects must produce the same integer result. <li>It is <em>not</em> required that if two objects are unequal
     * according to the {@link Object#equals(Object)} method, then calling the <tt>hashCode</tt> method on each of the two
     * objects must produce distinct integer results.  However, the programmer should be aware that producing distinct
     * integer results for unequal objects may improve the performance of hashtables. </ul>
     * <p/>
     * As much as is reasonably practical, the hashCode method defined by class <tt>Object</tt> does return distinct
     * integers for distinct objects. (This is typically implemented by converting the internal address of the object into
     * an integer, but this implementation technique is not required by the Java<font size="-2"><sup>TM</sup></font>
     * programming language.)
     *
     * @return a hash code value for this object.
     *
     * @see Object#equals(Object)
     * @see java.util.Hashtable
     */
    @Override
    public int hashCode() {
        return toString().hashCode();
    }
}
/*
package org.eoti.math.ternary;
    
import junit.framework.TestCase;
import junit.framework.Test;
import junit.framework.TestSuite;
    
public class TernaryTest
   extends TestCase
{
   public TernaryTest(String name){super(name);}
    
   public static Test suite(){return new TestSuite(TernaryTest.class);}
    
   public void testInt()
   {
  int toTest = 13;
  assertEquals("Int", toTest, (new Ternary(toTest)).intValue());
   }
    
   public void testSignum()
   {
  assertEquals("Positive Signum", 1, (new Ternary(10)).signum());
  assertEquals("Neutral Signum", 0, (new Ternary(0)).signum());
  assertEquals("Negative Signum", -1, (new Ternary(-10)).signum());
   }
    
   public void testTritLength()
   {
  assertTrue("TritLength(13)", (new Ternary(13)).tritLength() == 3);
  assertTrue("TritLength(14)", (new Ternary(14)).tritLength() == 4);
   }
    
   public void testClearTrit()
   {
  Ternary tst = new Ternary(13);
  tst.clearTrit(1);
    
  Ternary expected = new Ternary(10);
    
  assertEquals("ClearTrit", expected, tst);
   }
    
   public void testSetTrit()
   {
  Ternary tst = new Ternary(10);
  tst.setTrit(1, Trit.POSITIVE);
    
  Ternary expected = new Ternary(13);
    
  assertEquals("SetTrit", expected, tst);
   }
    
   public void testIncrement()
   {
  Ternary tst = new Ternary(-1);
    
  tst.increment();
  assertEquals("Increment -1->0", 0, tst.intValue());
    
  tst.increment();
  assertEquals("Increment 0->1", 1, tst.intValue());
    
  tst.increment();
  assertEquals("Increment 1->2", 2, tst.intValue());
    
  tst.increment();
  assertEquals("Increment 2->3", 3, tst.intValue());
   }
    
   public void testDecrement()
   {
  Ternary tst = new Ternary(3);
    
  tst.decrement();
  assertEquals("Decrement 3->2", 2, tst.intValue());
    
  tst.decrement();
  assertEquals("Decrement 2->1", 1, tst.intValue());
    
  tst.decrement();
  assertEquals("Decrement 1->0", 0, tst.intValue());
    
  tst.decrement();
  assertEquals("Decrement 0->-1", -1, tst.intValue());
   }
    
   public void testShiftLeft()
   {
  Ternary tst = new Ternary(8); // +0-
  tst.shiftLeft();
  tst.trim();
    
  Ternary expected = new Ternary(24);// +0-0
  expected.trim();
    
  assertEquals("ShiftLeft", expected, tst);
   }
    
   public void testShiftRight()
   {
  Ternary tst = new Ternary(24);// +0-0
  tst.shiftRight();
  tst.trim();
    
  Ternary expected = new Ternary(8); // +0-
  expected.trim();
    
  assertEquals("ShiftRight", expected, tst);
   }
    
   public void testAdd()
   {
  assertEquals("Add PosPos", new Ternary(13), (new Ternary(10)).add(new Ternary(3)));
  assertEquals("Add PosNeg", new Ternary(7), (new Ternary(10)).add(new Ternary(-3)));
  assertEquals("Add NegNeg", new Ternary(-13), (new Ternary(-10)).add(new Ternary(-3)));
  assertEquals("Add NegPos", new Ternary(-7), (new Ternary(-10)).add(new Ternary(3)));
   }
    
   public void testSubtract()
   {
  assertEquals("Subtract PosPos", new Ternary(7), (new Ternary(10)).subtract(new Ternary(3)));
  assertEquals("Subtract PosNeg", new Ternary(13), (new Ternary(10)).subtract(new Ternary(-3)));
  assertEquals("Subtract NegNeg", new Ternary(-7), (new Ternary(-10)).subtract(new Ternary(-3)));
  assertEquals("Subtract NegPos", new Ternary(-13), (new Ternary(-10)).subtract(new Ternary(3)));
   }
    
   public void testMultiply()
   {
  assertEquals("Multiply PosPos", new Ternary(15), (new Ternary(5)).multiply(new Ternary(3)));
  assertEquals("Multiply PosNeg", new Ternary(-15), (new Ternary(5)).multiply(new Ternary(-3)));
  assertEquals("Multiply NegNeg", new Ternary(15), (new Ternary(-5)).multiply(new Ternary(-3)));
  assertEquals("Multiply NegPos", new Ternary(-15), (new Ternary(-5)).multiply(new Ternary(3)));
   }
    
   public void testDivide()
   {
  // 6/3=2r0; 6=dividend; 3=divisor; 2=quotient; 0=remainder
    
  Ternary dividend = new Ternary(7);
  Ternary divisor = new Ternary(2);
  Ternary expectedQuotient = new Ternary(3);
  Ternary expectedRemainder = new Ternary(1);
  Ternary[] results = dividend.divide(divisor);
  results[0].trim();
  results[1].trim();
  assertEquals("Divide(7/2) Quotient", expectedQuotient, results[0]);
  assertEquals("Divide(7/2) Remainder", expectedRemainder, results[1]);
    
  dividend = new Ternary(7);
  divisor = new Ternary(-2);
  expectedQuotient = new Ternary(-3);
  expectedRemainder = new Ternary(1);
  results = dividend.divide(divisor);
  results[0].trim();
  results[1].trim();
  assertEquals("Divide(7/-2) Quotient", expectedQuotient, results[0]);
  assertEquals("Divide(7/-2) Remainder", expectedRemainder, results[1]);
    
  dividend = new Ternary(-7);
  divisor = new Ternary(2);
  expectedQuotient = new Ternary(-3);
  expectedRemainder = new Ternary(-1);
  results = dividend.divide(divisor);
  results[0].trim();
  results[1].trim();
  assertEquals("Divide(-7/2) Quotient", expectedQuotient, results[0]);
  assertEquals("Divide(-7/2) Remainder", expectedRemainder, results[1]);
    
  dividend = new Ternary(-7);
  divisor = new Ternary(-2);
  expectedQuotient = new Ternary(3);
  expectedRemainder = new Ternary(1);
  results = dividend.divide(divisor);
  results[0].trim();
  results[1].trim();
  assertEquals("Divide(-7/-2) Quotient", expectedQuotient, results[0]);
  assertEquals("Divide(-7/-2) Remainder", expectedRemainder, results[1]);
    
  dividend = new Ternary(0);
  divisor = new Ternary(2);
  expectedQuotient = new Ternary(0);
  expectedRemainder = new Ternary(0);
  results = dividend.divide(divisor);
  results[0].trim();
  results[1].trim();
  assertEquals("Divide(0/2) Quotient", expectedQuotient, results[0]);
  assertEquals("Divide(0/2) Remainder", expectedRemainder, results[1]);
    
  try{
     dividend = new Ternary(2);
     divisor = new Ternary(0);
     results = dividend.divide(divisor);
     fail("Divide(2/0): Should have caused ArithmeticException");
  }catch(ArithmeticException ae){
     // good
  }
   }
    
   public void testSqrt()
   {
  if(true)
  {
     assertTrue("SKIPPING testSqrt", true);
     return;
  }
    
  assertEquals("SQRT", new Ternary(3), (new Ternary(15)).sqrt());
  assertEquals("SQRT", new Ternary(4), (new Ternary(16)).sqrt());
  assertEquals("SQRT", new Ternary(4), (new Ternary(17)).sqrt());
    
  assertEquals("SQRT", new Ternary(6), (new Ternary(48)).sqrt());
  assertEquals("SQRT", new Ternary(7), (new Ternary(49)).sqrt());
  assertEquals("SQRT", new Ternary(7), (new Ternary(50)).sqrt());
    
  assertEquals("SQRT", new Ternary(41), (new Ternary(1702)).sqrt());
  assertEquals("SQRT", new Ternary(41), (new Ternary(1703)).sqrt());
  assertEquals("SQRT", new Ternary(41), (new Ternary(1704)).sqrt());
    
  assertEquals("SQRT", new Ternary(10), (new Ternary(100)).sqrt());
   }
    
   public void testAbs()
   {
  assertEquals("SQRT", new Ternary(5), (new Ternary(5)).abs());
  assertEquals("SQRT", new Ternary(5), (new Ternary(-5)).abs());
  assertEquals("SQRT", new Ternary(0), (new Ternary(0)).abs());
   }
}
    
*/