# Copyright (C) 2014 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

upper_bound_int_pow2 = 31
upper_bound_int_pow2_neg = 32
upper_bound_long_pow2 = 63
upper_bound_long_pow2_neg = 64
upper_bound_constant = 100
all_tests = [
    ({'@INT@': 'int', '@SUFFIX@':''},
     [('CheckDiv', 'idiv_by_pow2_', [2**i for i in range(upper_bound_int_pow2)]),
      ('CheckDiv', 'idiv_by_pow2_neg_', [-2**i for i in range(upper_bound_int_pow2_neg)]),
      ('CheckDiv', 'idiv_by_constant_', [i for i in range(1, upper_bound_constant)]),
      ('CheckDiv', 'idiv_by_constant_neg_', [-i for i in range(1, upper_bound_constant)]),
      ('CheckRem', 'irem_by_pow2_', [2**i for i in range(upper_bound_int_pow2)]),
      ('CheckRem', 'irem_by_pow2_neg_', [-2**i for i in range(upper_bound_int_pow2_neg)]),
      ('CheckRem', 'irem_by_constant_', [i for i in range(1, upper_bound_constant)]),
      ('CheckRem', 'irem_by_constant_neg_', [-i for i in range(1, upper_bound_constant)])]),
    ({'@INT@': 'long', '@SUFFIX@': 'l'},
     [('CheckDiv', 'ldiv_by_pow2_', [2**i for i in range(upper_bound_long_pow2)]),
      ('CheckDiv', 'ldiv_by_pow2_neg_', [-2**i for i in range(upper_bound_long_pow2_neg)]),
      ('CheckDiv', 'ldiv_by_constant_', [i for i in range(1, upper_bound_constant)]),
      ('CheckDiv', 'ldiv_by_constant_neg_', [-i for i in range(1, upper_bound_constant)]),
      ('CheckRem', 'lrem_by_pow2_', [2**i for i in range(upper_bound_long_pow2)]),
      ('CheckRem', 'lrem_by_pow2_neg_', [-2**i for i in range(upper_bound_long_pow2_neg)]),
      ('CheckRem', 'lrem_by_constant_', [i for i in range(1, upper_bound_constant)]),
      ('CheckRem', 'lrem_by_constant_neg_', [-i for i in range(1, upper_bound_constant)])])
]

def subst_vars(variables, text):
    '''Substitute variables in text.'''
    for key, value in variables.items():
        text = text.replace(str(key), str(value))
    return text

# Generate all the function bodies (in decls) and all the function calls (in calls).
decls, calls = '', {}
for default_vars, tests in all_tests:
    local_vars = default_vars.copy()
    int_type = local_vars['@INT@']
    for checker, name, values in tests:
        local_vars['@CHECKER@'] = checker
        for i, value in enumerate(values):
            local_vars['@NAME@'] = name + str(i)
            local_vars['@VALUE@'] = value
            local_vars['@OP@'] = '/' if 'div' in name else '%'

            # Function body.
            decls += subst_vars(local_vars, '''
    public static @INT@ @NAME@(@INT@ x) {return x @OP@ @VALUE@@SUFFIX@;}''')

            # Function call and test.
            calls[int_type] = calls.get(int_type, '') + subst_vars(local_vars, '''
        @INT@@CHECKER@("@NAME@", @NAME@(x), x, @VALUE@@SUFFIX@);''')

# Generate the checkers.
checkers = ''
local_vars = {}
for int_type in ('int', 'long'):
    local_vars['@INT@'] = int_type
    for op, op_name in (('/', 'Div'), ('%', 'Rem')):
        local_vars['@OP@'] = op
        local_vars['@OP_NAME@'] = op_name
        checkers += subst_vars(local_vars, '''
    public static void @INT@Check@OP_NAME@(String desc, @INT@ result, @INT@ dividend, @INT@ divisor) {
        @INT@ correct_result = dividend @OP@ divisor;
        if (result != correct_result) {
            reportError(desc + "(" + dividend + ") == " + result +
                        " should be " + correct_result);
        }
    }''')


code = \
'''/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

public class Main {
    public static int num_errors = 0;

    public static void reportError(String message) {
        if (num_errors == 10) {
            System.out.println("Omitting other error messages...");
        } else if (num_errors < 10) {
            System.out.println(message);
        }
        num_errors += 1;
    }
%s
%s

    public static void intCheckAll(int x) {%s
    }

    public static void longCheckAll(long x) {%s
    }

    public static void main(String[] args) {
      int i;
      long l;

      System.out.println("Begin");

      System.out.println("Int: checking some equally spaced dividends...");
      for (i = -1000; i < 1000; i += 300) {
          intCheckAll(i);
          intCheckAll(-i);
      }

      System.out.println("Int: checking small dividends...");
      for (i = 1; i < 100; i += 1) {
          intCheckAll(i);
          intCheckAll(-i);
      }

      System.out.println("Int: checking big dividends...");
      for (i = 0; i < 100; i += 1) {
          intCheckAll(Integer.MAX_VALUE - i);
          intCheckAll(Integer.MIN_VALUE + i);
      }

      System.out.println("Long: checking some equally spaced dividends...");
      for (l = 0l; l < 1000000000000l; l += 300000000000l) {
          longCheckAll(l);
          longCheckAll(-l);
      }

      System.out.println("Long: checking small dividends...");
      for (l = 1l; l < 100l; l += 1l) {
          longCheckAll(l);
          longCheckAll(-l);
      }

      System.out.println("Long: checking big dividends...");
      for (l = 0l; l < 100l; l += 1l) {
          longCheckAll(Long.MAX_VALUE - l);
          longCheckAll(Long.MIN_VALUE + l);
      }

      System.out.println("End");
    }
}
''' % (checkers, decls, calls['int'], calls['long'])

with open('src/Main.java', 'w') as f:
    f.write(code)
