#!/usr/bin/env python import ctypes from os import system C_SRC = """ #include <stdlib.h> #include <stdint.h> int64_t cdiv(int64_t a, int64_t b) { return a/b; } int64_t cmod(int64_t a, int64_t b) { return a%b; } #define LOOPY_CALL_WITH_INTEGER_TYPES(MACRO_NAME) \ MACRO_NAME(int8, char) \ MACRO_NAME(int16, short) \ MACRO_NAME(int32, int) \ MACRO_NAME(int64, long long) #define LOOPY_DEFINE_FLOOR_DIV(SUFFIX, TYPE) \ TYPE loopy_floor_div_##SUFFIX(TYPE a, TYPE b) \ { \ if ((a<0) != (b<0)) \ a = a - (b + (b<0) - (b>=0)); \ return a/b; \ } LOOPY_CALL_WITH_INTEGER_TYPES(LOOPY_DEFINE_FLOOR_DIV) #undef LOOPY_DEFINE_FLOOR_DIV #define LOOPY_DEFINE_FLOOR_DIV_POS_B(SUFFIX, TYPE) \ TYPE loopy_floor_div_pos_b_##SUFFIX(TYPE a, TYPE b) \ { \ if (a<0) \ a = a - (b-1); \ return a/b; \ } LOOPY_CALL_WITH_INTEGER_TYPES(LOOPY_DEFINE_FLOOR_DIV_POS_B) #undef LOOPY_DEFINE_FLOOR_DIV_POS_B #define LOOPY_DEFINE_MOD_POS_B(SUFFIX, TYPE) \ TYPE loopy_mod_pos_b_##SUFFIX(TYPE a, TYPE b) \ { \ TYPE result = a%b; \ if (result < 0) \ result += b; \ return result; \ } LOOPY_CALL_WITH_INTEGER_TYPES(LOOPY_DEFINE_MOD_POS_B) #undef LOOPY_DEFINE_MOD_POS_B #define LOOPY_DEFINE_MOD(SUFFIX, TYPE) \ TYPE loopy_mod_##SUFFIX(TYPE a, TYPE b) \ { \ TYPE result = a%b; \ if (result < 0 && b > 0) \ result += b; \ if (result > 0 && b < 0) \ result = result + b; \ return result; \ } LOOPY_CALL_WITH_INTEGER_TYPES(LOOPY_DEFINE_MOD) #undef LOOPY_DEFINE_MOD """ def main(): with open("int-experiments.c", "w") as outf: outf.write(C_SRC) system("gcc -Wall -shared int-experiments.c -o int-experiments.so") int_exp = ctypes.CDLL("int-experiments.so") for func in [ int_exp.cdiv, int_exp.cmod, int_exp.loopy_floor_div_int64, int_exp.loopy_floor_div_pos_b_int64, int_exp.loopy_mod_pos_b_int64, int_exp.loopy_mod_int64, ]: func.argtypes = [ctypes.c_longlong, ctypes.c_longlong] func.restype = ctypes.c_longlong cmod = int_exp.cmod int_floor_div = int_exp.loopy_floor_div_int64 int_floor_div_pos_b = int_exp.loopy_floor_div_pos_b_int64 int_mod_pos_b = int_exp.loopy_mod_pos_b_int64 int_mod = int_exp.loopy_mod_int64 m = 50 for a in range(-m, m): for b in range(1, m): cresult = int_floor_div_pos_b(a, b) presult = a // b assert cresult == presult if cresult != presult: print(a, b, cresult, presult) for a in range(-m, m): for b in range(-m, m): if b == 0: continue cresult = int_floor_div(a, b) presult = a // b assert cresult == presult if cresult != presult: print(a, b, cresult, presult) for a in range(-m, m): for b in range(1, m): cresult = int_mod_pos_b(a, b) presult = a % b assert cresult == presult for a in range(-m, m): for b in range(-m, m): if b == 0: continue cresult = int_mod(a, b) presult = a % b assert cresult == presult if cresult != presult: print(a, b, cresult, presult) # print(int_mod(552, -918), 552 % -918) print(cmod(23, -11), 23 % -11) if __name__ == "__main__": main()