1# Copyright (C) 2014 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15upper_bound_int_pow2 = 31
16upper_bound_int_pow2_neg = 32
17upper_bound_long_pow2 = 63
18upper_bound_long_pow2_neg = 64
19upper_bound_constant = 100
20all_tests = [
21    ({'@INT@': 'int', '@SUFFIX@':''},
22     [('CheckDiv', 'idiv_by_pow2_', [2**i for i in range(upper_bound_int_pow2)]),
23      ('CheckDiv', 'idiv_by_pow2_neg_', [-2**i for i in range(upper_bound_int_pow2_neg)]),
24      ('CheckDiv', 'idiv_by_constant_', [i for i in range(1, upper_bound_constant)]),
25      ('CheckDiv', 'idiv_by_constant_neg_', [-i for i in range(1, upper_bound_constant)]),
26      ('CheckRem', 'irem_by_pow2_', [2**i for i in range(upper_bound_int_pow2)]),
27      ('CheckRem', 'irem_by_pow2_neg_', [-2**i for i in range(upper_bound_int_pow2_neg)]),
28      ('CheckRem', 'irem_by_constant_', [i for i in range(1, upper_bound_constant)]),
29      ('CheckRem', 'irem_by_constant_neg_', [-i for i in range(1, upper_bound_constant)])]),
30    ({'@INT@': 'long', '@SUFFIX@': 'l'},
31     [('CheckDiv', 'ldiv_by_pow2_', [2**i for i in range(upper_bound_long_pow2)]),
32      ('CheckDiv', 'ldiv_by_pow2_neg_', [-2**i for i in range(upper_bound_long_pow2_neg)]),
33      ('CheckDiv', 'ldiv_by_constant_', [i for i in range(1, upper_bound_constant)]),
34      ('CheckDiv', 'ldiv_by_constant_neg_', [-i for i in range(1, upper_bound_constant)]),
35      ('CheckRem', 'lrem_by_pow2_', [2**i for i in range(upper_bound_long_pow2)]),
36      ('CheckRem', 'lrem_by_pow2_neg_', [-2**i for i in range(upper_bound_long_pow2_neg)]),
37      ('CheckRem', 'lrem_by_constant_', [i for i in range(1, upper_bound_constant)]),
38      ('CheckRem', 'lrem_by_constant_neg_', [-i for i in range(1, upper_bound_constant)])])
39]
40
41def subst_vars(variables, text):
42    '''Substitute variables in text.'''
43    for key, value in variables.items():
44        text = text.replace(str(key), str(value))
45    return text
46
47# Generate all the function bodies (in decls) and all the function calls (in calls).
48decls, calls = '', {}
49for default_vars, tests in all_tests:
50    local_vars = default_vars.copy()
51    int_type = local_vars['@INT@']
52    for checker, name, values in tests:
53        local_vars['@CHECKER@'] = checker
54        for i, value in enumerate(values):
55            local_vars['@NAME@'] = name + str(i)
56            local_vars['@VALUE@'] = value
57            local_vars['@OP@'] = '/' if 'div' in name else '%'
58
59            # Function body.
60            decls += subst_vars(local_vars, '''
61    public static @INT@ @NAME@(@INT@ x) {return x @OP@ @VALUE@@SUFFIX@;}''')
62
63            # Function call and test.
64            calls[int_type] = calls.get(int_type, '') + subst_vars(local_vars, '''
65        @INT@@CHECKER@("@NAME@", @NAME@(x), x, @VALUE@@SUFFIX@);''')
66
67# Generate the checkers.
68checkers = ''
69local_vars = {}
70for int_type in ('int', 'long'):
71    local_vars['@INT@'] = int_type
72    for op, op_name in (('/', 'Div'), ('%', 'Rem')):
73        local_vars['@OP@'] = op
74        local_vars['@OP_NAME@'] = op_name
75        checkers += subst_vars(local_vars, '''
76    public static void @INT@Check@OP_NAME@(String desc, @INT@ result, @INT@ dividend, @INT@ divisor) {
77        @INT@ correct_result = dividend @OP@ divisor;
78        if (result != correct_result) {
79            reportError(desc + "(" + dividend + ") == " + result +
80                        " should be " + correct_result);
81        }
82    }''')
83
84
85code = \
86'''/*
87 * Copyright (C) 2014 The Android Open Source Project
88 *
89 * Licensed under the Apache License, Version 2.0 (the "License");
90 * you may not use this file except in compliance with the License.
91 * You may obtain a copy of the License at
92 *
93 *      http://www.apache.org/licenses/LICENSE-2.0
94 *
95 * Unless required by applicable law or agreed to in writing, software
96 * distributed under the License is distributed on an "AS IS" BASIS,
97 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
98 * See the License for the specific language governing permissions and
99 * limitations under the License.
100 */
101
102public class Main {
103    public static int num_errors = 0;
104
105    public static void reportError(String message) {
106        if (num_errors == 10) {
107            System.out.println("Omitting other error messages...");
108        } else if (num_errors < 10) {
109            System.out.println(message);
110        }
111        num_errors += 1;
112    }
113%s
114%s
115
116    public static void intCheckAll(int x) {%s
117    }
118
119    public static void longCheckAll(long x) {%s
120    }
121
122    public static void main(String[] args) {
123      int i;
124      long l;
125
126      System.out.println("Begin");
127
128      System.out.println("Int: checking some equally spaced dividends...");
129      for (i = -1000; i < 1000; i += 300) {
130          intCheckAll(i);
131          intCheckAll(-i);
132      }
133
134      System.out.println("Int: checking small dividends...");
135      for (i = 1; i < 100; i += 1) {
136          intCheckAll(i);
137          intCheckAll(-i);
138      }
139
140      System.out.println("Int: checking big dividends...");
141      for (i = 0; i < 100; i += 1) {
142          intCheckAll(Integer.MAX_VALUE - i);
143          intCheckAll(Integer.MIN_VALUE + i);
144      }
145
146      System.out.println("Long: checking some equally spaced dividends...");
147      for (l = 0l; l < 1000000000000l; l += 300000000000l) {
148          longCheckAll(l);
149          longCheckAll(-l);
150      }
151
152      System.out.println("Long: checking small dividends...");
153      for (l = 1l; l < 100l; l += 1l) {
154          longCheckAll(l);
155          longCheckAll(-l);
156      }
157
158      System.out.println("Long: checking big dividends...");
159      for (l = 0l; l < 100l; l += 1l) {
160          longCheckAll(Long.MAX_VALUE - l);
161          longCheckAll(Long.MIN_VALUE + l);
162      }
163
164      System.out.println("End");
165    }
166}
167''' % (checkers, decls, calls['int'], calls['long'])
168
169with open('src/Main.java', 'w') as f:
170    f.write(code)
171