• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // A test for BoundedRationals package.
18 
19 package com.android.calculator2;
20 
21 import com.hp.creals.CR;
22 import com.hp.creals.UnaryCRFunction;
23 
24 import junit.framework.AssertionFailedError;
25 import junit.framework.TestCase;
26 
27 import java.math.BigInteger;
28 
29 public class BRTest extends TestCase {
check(boolean x, String s)30     private static void check(boolean x, String s) {
31         if (!x) throw new AssertionFailedError(s);
32     }
33     final static int TEST_PREC = -100; // 100 bits to the right of
34                                        // binary point.
checkEq(BoundedRational x, CR y, String s)35     private static void checkEq(BoundedRational x, CR y, String s) {
36         check(x.CRValue().compareTo(y, TEST_PREC) == 0, s);
37     }
checkWeakEq(BoundedRational x, CR y, String s)38     private static void checkWeakEq(BoundedRational x, CR y, String s) {
39         if (x != null) checkEq(x, y, s);
40     }
41 
42     private final static UnaryCRFunction ASIN = UnaryCRFunction.asinFunction;
43     private final static UnaryCRFunction ACOS = UnaryCRFunction.acosFunction;
44     private final static UnaryCRFunction ATAN = UnaryCRFunction.atanFunction;
45     private final static UnaryCRFunction TAN = UnaryCRFunction.tanFunction;
46     private final static BoundedRational BR_0 = new BoundedRational(0);
47     private final static BoundedRational BR_M1 = new BoundedRational(-1);
48     private final static BoundedRational BR_2 = new BoundedRational(2);
49     private final static BoundedRational BR_M2 = new BoundedRational(-2);
50     private final static BoundedRational BR_15 = new BoundedRational(15);
51     private final static BoundedRational BR_390 = new BoundedRational(390);
52     private final static BoundedRational BR_M390 = new BoundedRational(-390);
53     private final static CR CR_1 = CR.valueOf(1);
54 
55     private final static CR RADIANS_PER_DEGREE = CR.PI.divide(CR.valueOf(180));
56     private final static CR DEGREES_PER_RADIAN = CR.valueOf(180).divide(CR.PI);
57     private final static CR LN10 = CR.valueOf(10).ln();
58 
toRadians(CR x)59     private static CR toRadians(CR x) {
60         return x.multiply(RADIANS_PER_DEGREE);
61     }
62 
fromRadians(CR x)63     private static CR fromRadians(CR x) {
64         return x.multiply(DEGREES_PER_RADIAN);
65     }
66 
67     // We assume that x is simple enough that we don't overflow bounds.
checkBR(BoundedRational x)68     private static void checkBR(BoundedRational x) {
69         check(x != null, "test data should not be null");
70         CR xAsCR = x.CRValue();
71         checkEq(BoundedRational.add(x, BoundedRational.ONE), xAsCR.add(CR_1),
72                 "add 1:" + x);
73         checkEq(BoundedRational.subtract(x, BoundedRational.MINUS_THIRTY),
74                 xAsCR.subtract(CR.valueOf(-30)), "sub -30:" + x);
75         checkEq(BoundedRational.multiply(x, BR_15),
76                 xAsCR.multiply(CR.valueOf(15)), "multiply 15:" + x);
77         checkEq(BoundedRational.divide(x, BR_15),
78                 xAsCR.divide(CR.valueOf(15)), "divide 15:" + x);
79         checkWeakEq(BoundedRational.sin(x), xAsCR.sin(), "sin:" + x);
80         checkWeakEq(BoundedRational.cos(x), xAsCR.cos(), "cos:" + x);
81         checkWeakEq(BoundedRational.tan(x), TAN.execute(xAsCR), "tan:" + x);
82         checkWeakEq(BoundedRational.degreeSin(x), toRadians(xAsCR).sin(),
83                 "degree sin:" + x);
84         checkWeakEq(BoundedRational.degreeCos(x), toRadians(xAsCR).cos(),
85                 "degree cos:" + x);
86         BigInteger big_x = BoundedRational.asBigInteger(x);
87         long long_x = (big_x == null? 0 : big_x.longValue());
88         try {
89             checkWeakEq(BoundedRational.degreeTan(x),
90                         TAN.execute(toRadians(xAsCR)), "degree tan:" + x);
91             check((long_x - 90) % 180 != 0, "missed undefined tan: " + x);
92         } catch (ArithmeticException ignored) {
93             check((long_x - 90) % 180 == 0, "exception on defined tan: " + x);
94         }
95         if (x.compareTo(BoundedRational.THIRTY) <= 0
96                 && x.compareTo(BoundedRational.MINUS_THIRTY) >= 0) {
97             checkWeakEq(BoundedRational.exp(x), xAsCR.exp(), "exp:" + x);
98             checkWeakEq(BoundedRational.pow(BR_15, x),
99                     CR.valueOf(15).ln().multiply(xAsCR).exp(),
100                     "pow(15,x):" + x);
101         }
102         if (x.compareTo(BoundedRational.ONE) <= 0
103                 && x.compareTo(BoundedRational.MINUS_ONE) >= 0) {
104             checkWeakEq(BoundedRational.asin(x), ASIN.execute(xAsCR),
105                         "asin:" + x);
106             checkWeakEq(BoundedRational.acos(x), ACOS.execute(xAsCR),
107                         "acos:" + x);
108             checkWeakEq(BoundedRational.degreeAsin(x),
109                         fromRadians(ASIN.execute(xAsCR)), "degree asin:" + x);
110             checkWeakEq(BoundedRational.degreeAcos(x),
111                         fromRadians(ACOS.execute(xAsCR)), "degree acos:" + x);
112         }
113         checkWeakEq(BoundedRational.atan(x), fromRadians(ATAN.execute(xAsCR)),
114                     "atan:" + x);
115         checkWeakEq(BoundedRational.degreeAtan(x),
116                     fromRadians(ATAN.execute(xAsCR)), "degree atan:" + x);
117         if (x.signum() > 0) {
118             checkWeakEq(BoundedRational.ln(x), xAsCR.ln(), "ln:" + x);
119             checkWeakEq(BoundedRational.log(x), xAsCR.ln().divide(LN10),
120                         "log:" + x);
121             checkWeakEq(BoundedRational.sqrt(x), xAsCR.sqrt(), "sqrt:" + x);
122             checkEq(BoundedRational.pow(x, BR_15),
123                     xAsCR.ln().multiply(CR.valueOf(15)).exp(),
124                     "pow(x,15):" + x);
125         }
126     }
127 
testBR()128     public void testBR() {
129         BoundedRational b = new BoundedRational(4,-6);
130         check(b.toString().equals("4/-6"), "toString(4/-6)");
131         check(b.toNiceString().equals("-2/3"),"toNiceString(4/-6)");
132         checkEq(BR_0, CR.valueOf(0), "0");
133         checkEq(BR_390, CR.valueOf(390), "390");
134         checkEq(BR_15, CR.valueOf(15), "15");
135         checkEq(BR_M390, CR.valueOf(-390), "-390");
136         checkEq(BR_M1, CR.valueOf(-1), "-1");
137         checkEq(BR_2, CR.valueOf(2), "2");
138         checkEq(BR_M2, CR.valueOf(-2), "-2");
139         check(BR_0.signum() == 0, "signum(0)");
140         check(BR_M1.signum() == -1, "signum(-1)");
141         check(BR_2.signum() == 1, "signum(2)");
142         check(BoundedRational.asBigInteger(BR_390).intValue() == 390, "390.asBigInteger()");
143         check(BoundedRational.asBigInteger(BoundedRational.HALF) == null, "1/2.asBigInteger()");
144         check(BoundedRational.asBigInteger(BoundedRational.MINUS_HALF) == null,
145                 "-1/2.asBigInteger()");
146         check(BoundedRational.asBigInteger(new BoundedRational(15, -5)).intValue() == -3,
147                 "-15/5.asBigInteger()");
148         check(BoundedRational.digitsRequired(BoundedRational.ZERO) == 0, "digitsRequired(0)");
149         check(BoundedRational.digitsRequired(BoundedRational.HALF) == 1, "digitsRequired(1/2)");
150         check(BoundedRational.digitsRequired(BoundedRational.MINUS_HALF) == 1,
151                 "digitsRequired(-1/2)");
152         check(BoundedRational.digitsRequired(new BoundedRational(1,-2)) == 1,
153                 "digitsRequired(1/-2)");
154         check(BoundedRational.fact(BoundedRational.ZERO).equals(BoundedRational.ONE), "0!");
155         check(BoundedRational.fact(BoundedRational.ONE).equals(BoundedRational.ONE), "1!");
156         check(BoundedRational.fact(BoundedRational.TWO).equals(BoundedRational.TWO), "2!");
157         check(BoundedRational.fact(BR_15).equals(new BoundedRational(1307674368000L)), "15!");
158         // We check values that include all interesting degree values.
159         BoundedRational r = BR_M390;
160         while (!r.equals(BR_390)) {
161             check(r != null, "loop counter overflowed!");
162             checkBR(r);
163             r = BoundedRational.add(r, BR_15);
164         }
165         checkBR(BoundedRational.HALF);
166         checkBR(BoundedRational.MINUS_HALF);
167         checkBR(BoundedRational.ONE);
168         checkBR(BoundedRational.MINUS_ONE);
169         checkBR(new BoundedRational(1000));
170         checkBR(new BoundedRational(100));
171         checkBR(new BoundedRational(4,9));
172         check(BoundedRational.sqrt(new BoundedRational(4,9)) != null,
173               "sqrt(4/9) is null");
174         checkBR(BoundedRational.negate(new BoundedRational(4,9)));
175         checkBR(new BoundedRational(5,9));
176         checkBR(new BoundedRational(5,10));
177         checkBR(new BoundedRational(5,10));
178         checkBR(new BoundedRational(4,13));
179         checkBR(new BoundedRational(36));
180         checkBR(BoundedRational.negate(new BoundedRational(36)));
181         check(BoundedRational.pow(null, BR_15) == null, "pow(null, 15)");
182     }
183 
testBRexceptions()184     public void testBRexceptions() {
185         try {
186             BoundedRational.ln(BR_M1);
187             check(false, "ln(-1)");
188         } catch (ArithmeticException ignored) {}
189         try {
190             BoundedRational.log(BR_M2);
191             check(false, "log(-2)");
192         } catch (ArithmeticException ignored) {}
193         try {
194             BoundedRational.sqrt(BR_M1);
195             check(false, "sqrt(-1)");
196         } catch (ArithmeticException ignored) {}
197         try {
198             BoundedRational.asin(BR_M2);
199             check(false, "asin(-2)");
200         } catch (ArithmeticException ignored) {}
201         try {
202             BoundedRational.degreeAcos(BR_2);
203             check(false, "degree acos(2)");
204         } catch (ArithmeticException ignored) {}
205     }
206 
testBROverflow()207     public void testBROverflow() {
208         BoundedRational sum = new BoundedRational(0);
209         long i;
210         for (i = 1; i < 1000; ++i) {
211              sum = BoundedRational.add(sum,
212                         BoundedRational.inverse(new BoundedRational(i)));
213              if (sum == null) break;
214         }
215         // Experimentally, this overflows at 139, which seems
216         // plausible based on the Wolfram Alpha result.
217         // This test is robust against minor changes in MAX_SIZE.
218         check(i > 100, "Harmonic series overflowed at " + i);
219         check(i < 1000, "Harmonic series didn't overflow");
220     }
221 }
222