001    package ps1.test;
002    
003    import ps1.*;
004    
005    import junit.framework.TestCase;
006    
007    /**
008     * This class contains a set of test cases that can be used to test the
009     * implementation of the RatNum class.
010     * <p>
011     * RatNum is implemented for you, so it should already pass all the tests in
012     * this suite. This test is provided to give you (1) examples of using the
013     * RatNum class, albeit in the context of a test driver and (2) an example of a
014     * test suite.
015     * <p>
016     */
017    public final class RatNumTest extends TestCase {
018    
019        // Naming convention used throughout class: spell out number in
020        // variable as its constructive form. Unary minus is notated with
021        // the prefix "neg", and the solidus ("/") is notated with an 'I'
022        // character. Thus, "1 + 2/3" becomes "one_plus_two_I_three".
023    
024        // some simple base RatNums
025        private RatNum zero = new RatNum(0);
026    
027        private RatNum one = new RatNum(1);
028    
029        private RatNum negOne = new RatNum(-1);
030    
031        private RatNum two = new RatNum(2);
032    
033        private RatNum three = new RatNum(3);
034    
035        private RatNum one_I_two = new RatNum(1, 2);
036    
037        private RatNum one_I_three = new RatNum(1, 3);
038    
039        private RatNum one_I_four = new RatNum(1, 4);
040    
041        private RatNum two_I_three = new RatNum(2, 3);
042    
043        private RatNum three_I_four = new RatNum(3, 4);
044    
045        private RatNum negOne_I_two = new RatNum(-1, 2);
046    
047        // improper fraction
048        private RatNum three_I_two = new RatNum(3, 2);
049    
050        // NaNs
051        private RatNum one_I_zero = new RatNum(1, 0);
052    
053        private RatNum negOne_I_zero = new RatNum(-1, 0);
054    
055        private RatNum hundred_I_zero = new RatNum(100, 0);
056    
057        /**
058         * ratnums: Set of varied ratnums (includes NaNs) set is { 0, 1, -1, 2, 1/2,
059         * 3/2, 1/0, -1/0, 100/0 }
060         */
061        private RatNum[] ratNums = new RatNum[] { zero, one, negOne, two,
062                one_I_two, negOne_I_two, three_I_two,
063                /* NaNs */one_I_zero, negOne_I_zero, hundred_I_zero };
064    
065        /**
066         * ratnans: Set of varied NaNs set is { 1/0, -1/0, 100/0 }
067         */
068        private RatNum[] ratNaNs = new RatNum[] { one_I_zero, negOne_I_zero,
069                hundred_I_zero };
070    
071        /**
072         * ratNonNaNs: Set of varied non-NaN ratNums set is ratNums - ratNaNs
073         */
074        private RatNum[] ratNonNaNs = new RatNum[] { zero, one, negOne, two,
075                one_I_two, three_I_two };
076    
077        /**
078         * This constructor is provided for junit's use.
079         */
080        public RatNumTest(String name) {
081            super(name);
082        }
083    
084        /**
085         * Asserts that rep is equal to RatNum.toString. This method depends on the
086         * implementation of RatNum's "toString" and "equals" methods. Therefore,
087         * one should verify (test) those methods before using this method is in
088         * tests.
089         */
090        private void eq(RatNum ratNum, String rep) {
091            assertEquals(rep, ratNum.toString());
092        }
093    
094        // The actual test cases are below.
095        //
096        // The order of the test cases is important for producing useful
097        // output. If a test uses a method of RatNum, it should test that
098        // method before hand. For example, suppose one of the test cases
099        // for "negate" is:
100        //
101        // "(new RatNum(1)).negate().equals(new RatNum(-1))"
102        //
103        // In this case, the test case relies on RatNum's "equals" method
104        // in addition to "negate"; therefore, one should test "equals"
105        // before "negate". Otherwise, it will be unclear if failing the
106        // "negate" test is due "negate" having a bug or "equals" having a
107        // bug. (Furthermore, the test depends on RatNum's constructor,
108        // so it should also be tested beforehand.)
109        //
110        // In general, it is best to have as few dependences in your test
111        // cases as possible. Doing so, will reduce the number of methods
112        // that could cause a test case to fail, making it easier to find
113        // the faulty method. In practice, one will usually need to
114        // depend on a few core methods such as the constructors and
115        // "equals" methods. Also, some of the test cases below depend on
116        // the "toString" method because it made the cases easier to write.
117        //
118        // As a secondary concern to above, if one has access to the
119        // source code of a class (as under glass box testing) one should
120        // order tests such that a method is tested after all the methods
121        // it depends on are tested. For example, in RatNum, the "sub"
122        // method calls the "negate" method; therefore, one should test
123        // "negate" before "sub". Following this methodology will make it
124        // more clear that one should fix bugs in "negate" before looking
125        // at the results of "sub" test because, "sub" could be correctly
126        // written and the "sub" test case fails only be "negate" is
127        // broken.
128        //
129        // If one does not have access to the source code (as is the case
130        // of RatTermTest and RatPolyTest, because you are proving the
131        // implementations), one can still take an educated guess as to
132        // which methods depend on other methods, but don't worry about
133        // getting it perfect.
134    
135        // First, we test the constructors in isolation of (without
136        // depending on) all other RatNum methods.
137        //
138        // Unfortunately, without using any of RatNum's methods, all we
139        // can do is call the constructors and ensure that "checkRep"
140        // passes. While this is useful, it does not catch many types of
141        // errors. For example, the constructor could always return a
142        // RatNum, r, where r.numer = 1 and r.denom = 1. Being a valid
143        // RatNum, r would pass "checkRep" but would be the wrong RatNum
144        // in most cases.
145        //
146        // Given that we are unable to fully test the constructors, when
147        // any other test case fails, it could be due to an error in the
148        // constructor instead of an error in method the test case is
149        // testing.
150        //
151        // If RatNum had public fields, this problem would not exist,
152        // because we could check if the fields were set to the correct
153        // values. This problem is really a case of a more general
154        // problem of being unable to test private fields and methods of
155        // classes. For example, we are also unable to test the gcd
156        // method because it is private. Solutions to this general
157        // problem include:
158        //
159        // (1) Make the private fields and methods public. (For example,
160        // make numer, denom, and gcd public.) This in not done in
161        // general because private fields have many benefits as will
162        // be discussed in class.
163        //
164        // (2) Move the test suite code into RatNum and, thus, it would
165        // have access to private memebers. (Maybe as a static inner
166        // class [Don't worry if you don't know what this means yet.])
167        // This is not done in general because it clutters the class
168        // being tested, making it harder to understand.
169        //
170        // In practice, while testing, you may find it necessary to do (1)
171        // or (2) temporarily with a test case that accesses private
172        // fields or methods to track down a bug. But after finding the
173        // bug, remember to revert your code back. Also for future
174        // problem sets where you will be writing your own test suites,
175        // make sure that your test suite runs correctly without (1) or
176        // (2) being true.
177    
178        // (Note, all of these objects were already constructed above as
179        // fields of this class (RatNumTest); thus, one could argue that
180        // this test case is redundant. We included this test case anyhow
181        // to give you an example of such a test case and because the
182        // implementation of this class could change eliminating the
183        // fields above.)
184        public void testOneArgConstructor() {
185            new RatNum(0);
186            new RatNum(1);
187            new RatNum(-1);
188            new RatNum(2);
189            new RatNum(3);
190        }
191    
192        public void testTwoArgConstructor() {
193            new RatNum(1, 2);
194            new RatNum(1, 3);
195            new RatNum(1, 4);
196            new RatNum(2, 3);
197            new RatNum(3, 4);
198    
199            new RatNum(-1, 2);
200    
201            // improper fraction
202            new RatNum(3, 2);
203    
204            // NaNs
205            new RatNum(1, 0);
206            new RatNum(-1, 0);
207            new RatNum(100, 0);
208        }
209    
210        // Next, we test isNaN because it can be tested in isolation from
211        // everything except the constructors. (All instance method tests
212        // will depend on a constructor.)
213        public void testIsNaN() {
214            for (int i = 0; i < ratNaNs.length; i++) {
215                assertTrue(ratNaNs[i].isNaN());
216            }
217            for (int i = 0; i < ratNonNaNs.length; i++) {
218                assertFalse(ratNonNaNs[i].isNaN());
219            }
220        }
221    
222        // Next, we test isPos and isNeg because we can easily test these
223        // methods without depending on any other methods (except the
224        // constructors).
225        private void assertPos(RatNum n) {
226            assertTrue(n.isPositive());
227            assertFalse(n.isNegative());
228        }
229    
230        private void assertNeg(RatNum n) {
231            assertTrue(n.isNegative());
232            assertFalse(n.isPositive());
233        }
234    
235        public void testIsPosAndIsNeg() {
236            assertFalse(zero.isPositive());
237            assertFalse(zero.isNegative());
238    
239            assertPos(one);
240            assertNeg(negOne);
241            assertPos(two);
242            assertPos(three);
243    
244            assertPos(one_I_two);
245            assertPos(one_I_three);
246            assertPos(one_I_four);
247            assertPos(two_I_three);
248            assertPos(three_I_four);
249    
250            assertNeg(negOne_I_two);
251    
252            assertPos(three_I_two);
253    
254            assertPos(one_I_zero);
255            assertPos(negOne_I_zero); // non-intuitive; see spec
256            assertPos(hundred_I_zero);
257        }
258    
259        // Next, we test doubleValue because the test does not require any
260        // other RatNum methods (other than constructors).
261    
262        // asserts that two double's are within .0000001 of one another.
263        // It is often impossible to assert that doubles are exactly equal
264        // because of the idiosyncrasies of Java's floating point math.
265        private void approxEq(double d1, double d2) {
266            assertTrue(Math.abs(d1 - d2) < .0000001);
267        }
268    
269        public void testDoubleValue() {
270            approxEq(zero.doubleValue(), 0.0);
271            approxEq(one.doubleValue(), 1.0);
272            approxEq(negOne.doubleValue(), -1.0);
273            approxEq(two.doubleValue(), 2.0);
274            approxEq(one_I_two.doubleValue(), 0.5);
275            approxEq(two_I_three.doubleValue(), 2. / 3.);
276            approxEq(three_I_four.doubleValue(), 0.75);
277    
278            // cannot test that one_I_zero.doubleValue() approxEq Double.NaN,
279            // because it WON'T!!! Instead, construct corresponding
280            // instance of Double and use .equals(..) method
281            assertTrue((new Double(Double.NaN)).equals(new Double(one_I_zero
282                    .doubleValue())));
283    
284            // use left-shift operator "<<" to create integer for 2^30
285            RatNum one_I_twoToThirty = new RatNum(1, (1 << 30));
286            double quiteSmall = 1. / Math.pow(2, 30);
287            approxEq(one_I_twoToThirty.doubleValue(), quiteSmall);
288        }
289    
290        public void testFloatValue() {
291            approxEq(zero.floatValue(), 0.0);
292            approxEq(one.floatValue(), 1.0);
293            approxEq(negOne.floatValue(), -1.0);
294            approxEq(two.floatValue(), 2.0);
295            approxEq(one_I_two.floatValue(), 0.5);
296            approxEq(two_I_three.floatValue(), 2. / 3.);
297            approxEq(three_I_four.floatValue(), 0.75);
298    
299            // cannot test that one_I_zero.doubleValue() approxEq Float.NaN,
300            // because it WON'T!!! Instead, construct corresponding
301            // instance of Float and use .equals(..) method
302            assertTrue((new Float(Float.NaN)).equals(new Float(one_I_zero
303                    .floatValue())));
304    
305            // use left-shift operator "<<" to create integer for 2^30
306            RatNum one_I_twoToThirty = new RatNum(1, (1 << 30));
307            double quiteSmall = 1. / Math.pow(2, 30);
308            approxEq(one_I_twoToThirty.floatValue(), quiteSmall);
309        }
310    
311        public void testIntValue() {
312            assertTrue("0 should round to 0", zero.intValue() == 0);
313            assertTrue("1 should round to 1", one.intValue() == 1);
314            assertTrue("-1 should round to -1", negOne.intValue() == -1);
315            assertTrue("1/2 should round to 1", one_I_two.intValue() == 1);
316            assertTrue("2/3 should round to 1", two_I_three.intValue() == 1);
317            assertTrue("3/4 should round to 1", three_I_four.intValue() == 1);
318            assertTrue("-1/2 should round to -1",
319                    one_I_two.negate().intValue() == -1);
320            assertTrue("-2/3 should round to -1",
321                    two_I_three.negate().intValue() == -1);
322            assertTrue("-3/4 should round to -1",
323                    three_I_four.negate().intValue() == -1);
324    
325            // large numbers
326            assertTrue("MAX_VALUE should round to MAX_VALUE", new RatNum(
327                    Integer.MAX_VALUE).intValue() == Integer.MAX_VALUE);
328            assertTrue("MIN_VALUE should round to MIN_VALUE", new RatNum(
329                    Integer.MIN_VALUE).intValue() == Integer.MIN_VALUE);
330            assertTrue("MAX_VALUE/2 should round to (MAX_VALUE/2)+1", new RatNum(
331                    Integer.MAX_VALUE, 2).intValue() == (Integer.MAX_VALUE / 2) + 1);
332            assertTrue("MIN_VALUE/2 should round to (MIN_VALUE/2)", new RatNum(
333                    Integer.MIN_VALUE, 2).intValue() == (Integer.MIN_VALUE / 2));
334            assertTrue("MAX_VALUE/MAX_VALUE should round to 1", new RatNum(
335                    Integer.MAX_VALUE, Integer.MAX_VALUE).intValue() == 1);
336            assertTrue("MIN_VALUE/MIN_VALUE should round to 1", new RatNum(
337                    Integer.MIN_VALUE, Integer.MIN_VALUE).intValue() == 1);
338    
339            assertTrue("(MAX_VALUE-1)/MAX_VALUE should round to 1", new RatNum(
340                    Integer.MAX_VALUE - 1, Integer.MAX_VALUE).intValue() == 1);
341            assertTrue("1/MAX_VALUE should round to 0", new RatNum(1,
342                    Integer.MAX_VALUE).intValue() == 0);
343            if (false) {
344                // Note that these tests fail because our RatNum implementation
345                // can't represent the fractions in question. Can you think of
346                // a tweak to the representation invariant which would allow us
347                // to represent these values?
348                assertTrue("(MIN_VALUE+1)/MIN_VALUE should round to 1", new RatNum(
349                        Integer.MIN_VALUE + 1, Integer.MIN_VALUE).intValue() == 1);
350    
351                assertTrue("1/MIN_VALUE should round to 0", new RatNum(1,
352                        Integer.MIN_VALUE).intValue() == 0);
353            }
354        }
355    
356        // Next, we test the equals method because that can be tested in
357        // isolation from everything except the constructor and maybe
358        // isNaN, which we just tested.
359        // Additionally, this method will be very useful for testing other
360        // methods.
361    
362        /**
363         * This test check is equals is reflexive. In other words that x.equals(x)
364         * is always true.
365         */
366        public void testEqualsReflexive() {
367            for (int i = 0; i < ratNums.length; i++) {
368                assertTrue(ratNums[i].equals(ratNums[i]));
369            }
370        }
371    
372        public void testEquals() {
373    
374            // Some simple cases.
375            assertTrue(one.equals(one));
376            assertTrue(one.add(one).equals(two));
377            // including negitives:
378            assertTrue(negOne.equals(negOne));
379    
380            // Some simple cases where the objects are different but
381            // repersent the same rational number. That is, x != y but
382            // x.equals(y).
383            assertTrue((new RatNum(1, 1)).equals(new RatNum(1, 1)));
384            assertTrue((new RatNum(1, 2)).equals(new RatNum(1, 2)));
385    
386            // Check that equals works on fractions that were not
387            // constructed in reduced form.
388            assertTrue(one.equals(new RatNum(2, 2)));
389            assertTrue((new RatNum(2, 2)).equals(one));
390            // including negitives:
391            assertTrue(negOne.equals(new RatNum(-9, 9)));
392            assertTrue((new RatNum(-9, 9)).equals(negOne));
393            // including double negitives:
394            assertTrue(one_I_two.equals(new RatNum(-13, -26)));
395            assertTrue((new RatNum(-13, -26)).equals(one_I_two));
396    
397            // Check that all NaN's are equals to one another.
398            assertTrue(one_I_zero.equals(one_I_zero));
399            assertTrue(one_I_zero.equals(negOne_I_zero));
400            assertTrue(one_I_zero.equals(hundred_I_zero));
401    
402            // Some simple cases checking for false positives.
403            assertFalse(one.equals(zero));
404            assertFalse(zero.equals(one));
405            assertFalse(one.equals(two));
406            assertFalse(two.equals(one));
407    
408            // Check that equals does not neglect sign.
409            assertFalse(one.equals(negOne));
410            assertFalse(negOne.equals(one));
411    
412            // Check that equals does not return false positives on
413            // fractions.
414            assertFalse(one.equals(one_I_two));
415            assertFalse(one_I_two.equals(one));
416            assertFalse(one.equals(three_I_two));
417            assertFalse(three_I_two.equals(one));
418        }
419    
420        // Now that we have verified equals, we will use it in the
421        // rest or our tests.
422    
423        // Next, we test the toString and valueOf methods because we can test
424        // them isolation of everything except the constructor and equals,
425        // and they will be useful methods to aid with testing other
426        // methods. (In some cases, it is easier to use valueOf("1/2") than
427        // new RatNum(1, 2) as you will see below.)
428    
429        // Note that "eq" calls "toString" on its first argument.
430        public void testToStringSimple() {
431            eq(zero, "0");
432    
433            eq(one, "1");
434    
435            RatNum four = new RatNum(4);
436            eq(four, "4");
437    
438            eq(negOne, "-1");
439    
440            RatNum negFive = new RatNum(-5);
441            eq(negFive, "-5");
442    
443            RatNum negZero = new RatNum(-0);
444            eq(negZero, "0");
445        }
446    
447        public void testToStringFractions() {
448            RatNum one_I_two = new RatNum(1, 2);
449            eq(one_I_two, "1/2");
450    
451            RatNum three_I_two = new RatNum(3, 2);
452            eq(three_I_two, "3/2");
453    
454            RatNum negOne_I_thirteen = new RatNum(-1, 13);
455            eq(negOne_I_thirteen, "-1/13");
456    
457            RatNum fiftyThree_I_seven = new RatNum(53, 7);
458            eq(fiftyThree_I_seven, "53/7");
459        }
460    
461        public void testToStringNaN() {
462            RatNum one_I_zero = new RatNum(1, 0);
463            eq(one_I_zero, "NaN");
464    
465            RatNum two_I_zero = new RatNum(2, 0);
466            eq(two_I_zero, "NaN");
467    
468            RatNum negOne_I_zero = new RatNum(-1, 0);
469            eq(negOne_I_zero, "NaN");
470    
471            RatNum zero_I_zero = new RatNum(0, 0);
472            eq(zero_I_zero, "NaN");
473    
474            RatNum negHundred_I_zero = new RatNum(-100, 0);
475            eq(negHundred_I_zero, "NaN");
476    
477            RatNum two_I_one = new RatNum(2, 1);
478            eq(two_I_one, "2");
479    
480            RatNum zero_I_one = new RatNum(0, 1);
481            eq(zero_I_one, "0");
482    
483            RatNum negOne_I_negTwo = new RatNum(-1, -2);
484            eq(negOne_I_negTwo, "1/2");
485    
486            RatNum two_I_four = new RatNum(2, 4);
487            eq(two_I_four, "1/2");
488    
489            RatNum six_I_four = new RatNum(6, 4);
490            eq(six_I_four, "3/2");
491    
492            RatNum twentySeven_I_thirteen = new RatNum(27, 13);
493            eq(twentySeven_I_thirteen, "27/13");
494    
495            RatNum negHundred_I_negHundred = new RatNum(-100, -100);
496            eq(negHundred_I_negHundred, "1");
497        }
498    
499        // helper function, "decode-and-check"
500        private void decChk(String s, RatNum expected) {
501            RatNum.valueOf(s).equals(expected);
502        }
503    
504        // Note that decChk calls valueOf.
505        public void testValueOf() {
506            decChk("0", zero);
507    
508            decChk("1", one);
509            decChk("1/1", one);
510            decChk("2/2", one);
511            decChk("-1/-1", one);
512    
513            decChk("-1", negOne);
514            decChk("1/-1", negOne);
515            decChk("-3/3", negOne);
516    
517            decChk("2", two);
518            decChk("2/1", two);
519            decChk("-4/-2", two);
520    
521            decChk("1/2", one_I_two);
522            decChk("2/4", one_I_two);
523    
524            decChk("3/2", three_I_two);
525            decChk("-6/-4", three_I_two);
526    
527            decChk("NaN", one_I_zero);
528            decChk("NaN", negOne_I_zero);
529        }
530    
531        // Next, we test the arithmetic operations.
532        //
533        // We test them in our best guess of increasing difficultly and
534        // likelihood of having depend on a previous method. (For
535        // example, add could use sub as a subroutine.
536        //
537        // Note that our tests depend on toString and
538        // equals, which we have already tested.
539    
540        public void testNegate() {
541            eq(zero.negate(), "0");
542            eq(one.negate(), "-1");
543            eq(negOne.negate(), "1");
544            eq(two.negate(), "-2");
545            eq(three.negate(), "-3");
546    
547            eq(one_I_two.negate(), "-1/2");
548            eq(one_I_three.negate(), "-1/3");
549            eq(one_I_four.negate(), "-1/4");
550            eq(two_I_three.negate(), "-2/3");
551            eq(three_I_four.negate(), "-3/4");
552    
553            eq(three_I_two.negate(), "-3/2");
554    
555            eq(one_I_zero.negate(), "NaN");
556            eq(negOne_I_zero.negate(), "NaN");
557            eq(hundred_I_zero.negate(), "NaN");
558        }
559    
560        public void testAddSimple() {
561            eq(zero.add(zero), "0");
562            eq(zero.add(one), "1");
563            eq(one.add(zero), "1");
564            eq(one.add(one), "2");
565            eq(one.add(negOne), "0");
566            eq(one.add(two), "3");
567            eq(two.add(two), "4");
568        }
569    
570        public void testAddComplex() {
571            eq(one_I_two.add(zero), "1/2");
572            eq(one_I_two.add(one), "3/2");
573            eq(one_I_two.add(one_I_two), "1");
574            eq(one_I_two.add(one_I_three), "5/6");
575            eq(one_I_two.add(negOne), "-1/2");
576            eq(one_I_two.add(two), "5/2");
577            eq(one_I_two.add(two_I_three), "7/6");
578            eq(one_I_two.add(three_I_four), "5/4");
579    
580            eq(one_I_three.add(zero), "1/3");
581            eq(one_I_three.add(two_I_three), "1");
582            eq(one_I_three.add(three_I_four), "13/12");
583        }
584    
585        public void testAddImproper() {
586            eq(three_I_two.add(one_I_two), "2");
587            eq(three_I_two.add(one_I_three), "11/6");
588            eq(three_I_four.add(three_I_four), "3/2");
589    
590            eq(three_I_two.add(three_I_two), "3");
591        }
592    
593        public void testAddOnNaN() {
594            // each test case (addend, augend) drawn from the set
595            // ratNums x ratNaNs
596    
597            for (int i = 0; i < ratNums.length; i++) {
598                for (int j = 0; j < ratNaNs.length; j++) {
599                    eq(ratNums[i].add(ratNaNs[j]), "NaN");
600                    eq(ratNaNs[j].add(ratNums[i]), "NaN");
601                }
602            }
603    
604        }
605    
606        public void testAddTransitively() {
607            eq(one.add(one).add(one), "3");
608            eq(one.add(one.add(one)), "3");
609            eq(zero.add(zero).add(zero), "0");
610            eq(zero.add(zero.add(zero)), "0");
611            eq(one.add(two).add(three), "6");
612            eq(one.add(two.add(three)), "6");
613    
614            eq(one_I_three.add(one_I_three).add(one_I_three), "1");
615            eq(one_I_three.add(one_I_three.add(one_I_three)), "1");
616    
617            eq(one_I_zero.add(one_I_zero).add(one_I_zero), "NaN");
618            eq(one_I_zero.add(one_I_zero.add(one_I_zero)), "NaN");
619    
620            eq(one_I_two.add(one_I_three).add(one_I_four), "13/12");
621            eq(one_I_two.add(one_I_three.add(one_I_four)), "13/12");
622        }
623    
624        public void testSubSimple() {
625            eq(zero.sub(one), "-1");
626            eq(zero.sub(zero), "0");
627            eq(one.sub(zero), "1");
628            eq(one.sub(one), "0");
629            eq(two.sub(one), "1");
630            eq(one.sub(negOne), "2");
631            eq(one.sub(two), "-1");
632            eq(one.sub(three), "-2");
633        }
634    
635        public void testSubComplex() {
636            eq(one.sub(one_I_two), "1/2");
637            eq(one_I_two.sub(one), "-1/2");
638            eq(one_I_two.sub(zero), "1/2");
639            eq(one_I_two.sub(two_I_three), "-1/6");
640            eq(one_I_two.sub(three_I_four), "-1/4");
641        }
642    
643        public void testSubImproper() {
644            eq(three_I_two.sub(one_I_two), "1");
645            eq(three_I_two.sub(one_I_three), "7/6");
646        }
647    
648        public void testSubOnNaN() {
649            // analogous to testAddOnNaN()
650    
651            for (int i = 0; i < ratNums.length; i++) {
652                for (int j = 0; j < ratNaNs.length; j++) {
653                    eq(ratNums[i].sub(ratNaNs[j]), "NaN");
654                    eq(ratNaNs[j].sub(ratNums[i]), "NaN");
655                }
656            }
657        }
658    
659        public void testSubTransitively() {
660            // subtraction is not transitive; testing that operation is
661            // correct when *applied transitivitely*, not that it obeys
662            // the transitive property
663    
664            eq(one.sub(one).sub(one), "-1");
665            eq(one.sub(one.sub(one)), "1");
666            eq(zero.sub(zero).sub(zero), "0");
667            eq(zero.sub(zero.sub(zero)), "0");
668            eq(one.sub(two).sub(three), "-4");
669            eq(one.sub(two.sub(three)), "2");
670    
671            eq(one_I_three.sub(one_I_three).sub(one_I_three), "-1/3");
672            eq(one_I_three.sub(one_I_three.sub(one_I_three)), "1/3");
673    
674            eq(one_I_zero.sub(one_I_zero).sub(one_I_zero), "NaN");
675            eq(one_I_zero.sub(one_I_zero.sub(one_I_zero)), "NaN");
676    
677            eq(one_I_two.sub(one_I_three).sub(one_I_four), "-1/12");
678            eq(one_I_two.sub(one_I_three.sub(one_I_four)), "5/12");
679        }
680    
681        public void testMulProperties() {
682            // zero property
683            for (int i = 0; i < ratNonNaNs.length; i++) {
684                eq(zero.mul(ratNonNaNs[i]), "0");
685                eq(ratNonNaNs[i].mul(zero), "0");
686            }
687    
688            // one property
689            for (int i = 0; i < ratNonNaNs.length; i++) {
690                eq(one.mul(ratNonNaNs[i]), ratNonNaNs[i].toString());
691                eq(ratNonNaNs[i].mul(one), ratNonNaNs[i].toString());
692            }
693    
694            // negOne property
695            for (int i = 0; i < ratNonNaNs.length; i++) {
696                eq(negOne.mul(ratNonNaNs[i]), ratNonNaNs[i].negate().toString());
697                eq(ratNonNaNs[i].mul(negOne), ratNonNaNs[i].negate().toString());
698            }
699        }
700    
701        public void testMulSimple() {
702            eq(two.mul(two), "4");
703            eq(two.mul(three), "6");
704            eq(three.mul(two), "6");
705        }
706    
707        public void testMulComplex() {
708            eq(one_I_two.mul(two), "1");
709            eq(two.mul(one_I_two), "1");
710            eq(one_I_two.mul(one_I_two), "1/4");
711            eq(one_I_two.mul(one_I_three), "1/6");
712            eq(one_I_three.mul(one_I_two), "1/6");
713        }
714    
715        public void testMulImproper() {
716            eq(three_I_two.mul(one_I_two), "3/4");
717            eq(three_I_two.mul(one_I_three), "1/2");
718            eq(three_I_two.mul(three_I_four), "9/8");
719            eq(three_I_two.mul(three_I_two), "9/4");
720        }
721    
722        public void testMulOnNaN() {
723            // analogous to testAddOnNaN()
724    
725            for (int i = 0; i < ratNums.length; i++) {
726                for (int j = 0; j < ratNaNs.length; j++) {
727                    eq(ratNums[i].mul(ratNaNs[j]), "NaN");
728                    eq(ratNaNs[j].mul(ratNums[i]), "NaN");
729                }
730            }
731        }
732    
733        public void testMulTransitively() {
734            eq(one.mul(one).mul(one), "1");
735            eq(one.mul(one.mul(one)), "1");
736            eq(zero.mul(zero).mul(zero), "0");
737            eq(zero.mul(zero.mul(zero)), "0");
738            eq(one.mul(two).mul(three), "6");
739            eq(one.mul(two.mul(three)), "6");
740    
741            eq(one_I_three.mul(one_I_three).mul(one_I_three), "1/27");
742            eq(one_I_three.mul(one_I_three.mul(one_I_three)), "1/27");
743    
744            eq(one_I_zero.mul(one_I_zero).mul(one_I_zero), "NaN");
745            eq(one_I_zero.mul(one_I_zero.mul(one_I_zero)), "NaN");
746    
747            eq(one_I_two.mul(one_I_three).mul(one_I_four), "1/24");
748            eq(one_I_two.mul(one_I_three.mul(one_I_four)), "1/24");
749        }
750    
751        public void testDivSimple() {
752            eq(zero.div(zero), "NaN");
753            eq(zero.div(one), "0");
754            eq(one.div(zero), "NaN");
755            eq(one.div(one), "1");
756            eq(one.div(negOne), "-1");
757            eq(one.div(two), "1/2");
758            eq(two.div(two), "1");
759        }
760    
761        public void testDivComplex() {
762            eq(one_I_two.div(zero), "NaN");
763            eq(one_I_two.div(one), "1/2");
764            eq(one_I_two.div(one_I_two), "1");
765            eq(one_I_two.div(one_I_three), "3/2");
766            eq(one_I_two.div(negOne), "-1/2");
767            eq(one_I_two.div(two), "1/4");
768            eq(one_I_two.div(two_I_three), "3/4");
769            eq(one_I_two.div(three_I_four), "2/3");
770    
771            eq(one_I_three.div(zero), "NaN");
772            eq(one_I_three.div(two_I_three), "1/2");
773            eq(one_I_three.div(three_I_four), "4/9");
774        }
775    
776        public void testDivImproper() {
777            eq(three_I_two.div(one_I_two), "3");
778            eq(three_I_two.div(one_I_three), "9/2");
779            eq(three_I_two.div(three_I_two), "1");
780        }
781    
782        public void testDivOnNaN() {
783            // each test case (addend, augend) drawn from the set
784            // ratNums x ratNaNs
785    
786            for (int i = 0; i < ratNums.length; i++) {
787                for (int j = 0; j < ratNaNs.length; j++) {
788                    eq(ratNums[i].div(ratNaNs[j]), "NaN");
789                    eq(ratNaNs[j].div(ratNums[i]), "NaN");
790                }
791            }
792    
793        }
794    
795        public void testDivTransitively() {
796            // (same note as in testSubTransitively re: transitivity property)
797    
798            eq(one.div(one).div(one), "1");
799            eq(one.div(one.div(one)), "1");
800            eq(zero.div(zero).div(zero), "NaN");
801            eq(zero.div(zero.div(zero)), "NaN");
802            eq(one.div(two).div(three), "1/6");
803            eq(one.div(two.div(three)), "3/2");
804    
805            eq(one_I_three.div(one_I_three).div(one_I_three), "3");
806            eq(one_I_three.div(one_I_three.div(one_I_three)), "1/3");
807    
808            eq(one_I_zero.div(one_I_zero).div(one_I_zero), "NaN");
809            eq(one_I_zero.div(one_I_zero.div(one_I_zero)), "NaN");
810    
811            eq(one_I_two.div(one_I_three).div(one_I_four), "6");
812            eq(one_I_two.div(one_I_three.div(one_I_four)), "3/8");
813    
814        }
815    
816        // Finally, we test compare. We do so last, because compare may
817        // depend on sub, isNaN, and/or equals, so we want to test those
818        // methods first.
819    
820        private void assertGreater(RatNum larger, RatNum smaller) {
821            assertTrue(larger.compareTo(smaller) > 0);
822            assertTrue(smaller.compareTo(larger) < 0);
823        }
824    
825        public void testCompareToReflexive() {
826            // reflexivitiy: x.compare(x) == 0.
827            for (int i = 0; i < ratNums.length; i++) {
828                assertTrue(ratNums[i].equals(ratNums[i]));
829            }
830        }
831    
832        public void testCompareToNonFract() {
833            assertGreater(one, zero);
834            assertGreater(one, negOne);
835            assertGreater(two, one);
836            assertGreater(two, zero);
837            assertGreater(zero, negOne);
838        }
839    
840        public void testCompareToFract() {
841            assertGreater(one, one_I_two);
842            assertGreater(two, one_I_three);
843            assertGreater(one, two_I_three);
844            assertGreater(two, two_I_three);
845            assertGreater(one_I_two, zero);
846            assertGreater(one_I_two, negOne);
847            assertGreater(one_I_two, negOne_I_two);
848            assertGreater(zero, negOne_I_two);
849        }
850    
851        public void testCompareToNaNs() {
852            for (int i = 0; i < ratNaNs.length; i++) {
853                for (int j = 0; j < ratNaNs.length; j++) {
854                    assertTrue(ratNaNs[i].equals(ratNaNs[j]));
855                }
856                for (int j = 0; j < ratNonNaNs.length; j++) {
857                    assertGreater(ratNaNs[i], ratNonNaNs[j]);
858                }
859            }
860        }
861    
862    }