brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.5 KiB · 3ca17ff Raw
393 lines · python
1#!/usr/bin/env python2import random3import gmpapi4 5MAX_SLONG = "9223372036854775807"6MIN_SLONG = "-9223372036854775808"7MAX_ULONG = "18446744073709551615"8MAX_SINT = "2147483647"9MIN_SINT = "-2147483648"10MAX_UINT = "4294967295"11MAX_SSHORT = "32767"12MIN_SSHORT = "-32768"13MAX_USHORT = "65535"14 15 16def plus1(x):17    return str(int(x) + 1)18 19 20def minus1(x):21    return str(int(x) - 1)22 23 24def apply(fun, lst):25    return list(map(str, map(fun, lst)))26 27 28mzero_one = ["-0", "-1"]29zero_one = ["0", "1"]30mm_slong = [MAX_SLONG, MIN_SLONG]31mm_slong1 = [minus1(MAX_SLONG), plus1(MIN_SLONG)]32mm_ulong = [MAX_ULONG]33mm_ulong1 = [minus1(MAX_ULONG)]34mm_sint = [MAX_SINT, MIN_SINT]35mm_sint1 = [minus1(MAX_SINT), plus1(MIN_SINT)]36mm_uint = [MAX_UINT]37mm_uint1 = [minus1(MAX_UINT)]38mm_sshort = [MAX_SSHORT, MIN_SSHORT]39mm_sshort1 = [minus1(MAX_SSHORT), plus1(MIN_SSHORT)]40mm_ushort = [MAX_USHORT]41mm_ushort1 = [minus1(MAX_USHORT)]42mm_all = mm_slong + mm_ulong + mm_sint + mm_uint + mm_sshort + mm_ushort43zero_one_all = mzero_one + zero_one44 45mpz_std_list = zero_one_all + mm_all + apply(plus1, mm_all) + apply(minus1, mm_all)46si_std_list = (47    zero_one + mm_slong + mm_sint + mm_sshort + mm_slong1 + mm_sint1 + mm_sshort148)49ui_std_list = (50    zero_one + mm_ulong + mm_uint + mm_ushort + mm_ulong1 + mm_uint1 + mm_ushort151)52 53 54def gen_random_mpz(mindigits=1, maxdigits=100, allowneg=True):55    sign = random.choice(["", "-"])56    if not allowneg:57        sign = ""58    return sign + gen_digits(random.randint(mindigits, maxdigits))59 60 61def gen_random_si():62    si = gen_random_mpz(mindigits=1, maxdigits=19)63    while int(si) > int(MAX_SLONG) or int(si) < int(MIN_SLONG):64        si = gen_random_mpz(mindigits=1, maxdigits=19)65    return si66 67 68def gen_random_ui():69    ui = gen_random_mpz(mindigits=1, maxdigits=20, allowneg=False)70    while int(ui) > int(MAX_ULONG):71        ui = gen_random_mpz(mindigits=1, maxdigits=20, allowneg=False)72    return ui73 74 75def gen_digits(length):76    if length == 1:77        i = random.randint(1, 9)78    else:79        digits = [random.randint(1, 9)] + [80            random.randint(0, 9) for x in range(length - 1)81        ]82        digits = map(str, digits)83        i = "".join(digits)84    return str(i)85 86 87def gen_mpzs(mindigits=1, maxdigits=100, count=10):88    return [89        gen_random_mpz(mindigits=mindigits, maxdigits=maxdigits) for x in range(count)90    ]91 92 93default_count = 1094 95 96def gen_sis(count=default_count):97    return [gen_random_si() for x in range(count)]98 99 100def gen_uis(count=default_count):101    return [gen_random_ui() for x in range(count)]102 103 104def gen_small_mpzs(count=default_count):105    return gen_mpzs(mindigits=1, maxdigits=4, count=count)106 107 108def is_small_mpz(s):109    return len(s) >= 1 and len(s) <= 4110 111 112def gen_medium_mpzs(count=default_count):113    return gen_mpzs(mindigits=5, maxdigits=20, count=count)114 115 116def is_medium_mpz(s):117    return len(s) >= 5 and len(s) <= 20118 119 120def gen_large_mpzs(count=default_count):121    return gen_mpzs(mindigits=21, maxdigits=100, count=count)122 123 124def is_large_mpz(s):125    return len(s) >= 21126 127 128def gen_mpz_spread(count=default_count):129    return gen_small_mpzs(count) + gen_medium_mpzs(count) + gen_large_mpzs(count)130 131 132def gen_mpz_args(count=default_count):133    return mpz_std_list + gen_mpz_spread(count)134 135 136def gen_mpq_args(count=4):137    nums = zero_one + gen_mpz_spread(count)138    dens = ["1"] + gen_mpz_spread(count)139    return [n + "/" + d for n in nums for d in dens if int(d) != 0]140 141 142def gen_si_args():143    return si_std_list + gen_sis()144 145 146def gen_ui_args():147    return ui_std_list + gen_uis()148 149 150def gen_list_for_type(t, is_write_only):151    if (t == gmpapi.mpz_t or t == gmpapi.mpq_t) and is_write_only:152        return ["0"]153    elif t == gmpapi.mpz_t:154        return gen_mpz_args()155    elif t == gmpapi.ilong:156        return gen_si_args()157    elif t == gmpapi.ulong:158        return gen_ui_args()159    elif t == gmpapi.mpq_t:160        return gen_mpq_args()161    else:162        raise RuntimeError("Unknown type: {}".format(t))163 164 165def gen_args(api):166    if api.custom_test or api.name in custom:167        return custom[api.name](api)168    types = api.params169    if len(types) == 1:170        return [[a] for a in gen_list_for_type(types[0], api.is_write_only(0))]171    elif len(types) == 2:172        t1 = gen_list_for_type(types[0], api.is_write_only(0))173        t2 = gen_list_for_type(types[1], api.is_write_only(1))174        return [(a, b) for a in t1 for b in t2]175    elif len(types) == 3:176        t1 = gen_list_for_type(types[0], api.is_write_only(0))177        t2 = gen_list_for_type(types[1], api.is_write_only(1))178        t3 = gen_list_for_type(types[2], api.is_write_only(2))179        return [(a, b, c) for a in t1 for b in t2 for c in t3]180    elif len(types) == 4:181        t1 = gen_list_for_type(types[0], api.is_write_only(0))182        t2 = gen_list_for_type(types[1], api.is_write_only(1))183        t3 = gen_list_for_type(types[2], api.is_write_only(2))184        t4 = gen_list_for_type(types[3], api.is_write_only(3))185        return [(a, b, c, d) for a in t1 for b in t2 for c in t3 for d in t4]186    else:187        raise RuntimeError("Too many args: {}".format(len(types)))188 189 190###################################################################191#192# Fixup and massage random data for better test coverage193#194###################################################################195def mul_mpzs(a, b):196    return str(int(a) * int(b))197 198 199def mpz_divexact_data(args):200    # set n = n * d201    divisible = mul_mpzs(args[1], (args[2]))202    return [(args[0], divisible, args[2])]203 204 205def mpz_divisible_p_data(args):206    (n, d) = get_div_data(args[0], args[1], rate=1.0)207    return [(n, d), (args[0], args[1])]208 209 210def mpz_div3_data(args):211    q = args[0]212    (n, d) = get_div_data(args[1], args[2], rate=1.0)213    return [(q, n, d), (q, args[1], args[2])]214 215 216def mpz_pow_data(args, alwaysallowbase1=True):217    base = int(args[1])218    exp = int(args[2])219    # allow special numbers220    if base == 0 or exp == 0 or exp == 1:221        return [args]222    if base == 1 and alwaysallowbase1:223        return [args]224 225    # disallow too big numbers226    if base > 1000 or base < -1000:227        base = gen_random_mpz(maxdigits=3)228    if exp > 1000:229        exp = gen_random_mpz(maxdigits=3, allowneg=False)230 231    return [(args[0], str(base), str(exp))]232 233 234def mpz_mul_2exp_data(args):235    return mpz_pow_data(args, alwaysallowbase1=False)236 237 238def mpz_gcd_data(args):239    r = args[0]240    a = args[1]241    b = args[2]242    s_ = gen_small_mpzs(1)[0]243    m_ = gen_medium_mpzs(1)[0]244    l_ = gen_large_mpzs(1)[0]245 246    return [247        (r, a, b),248        (r, mul_mpzs(a, b), b),249        (r, mul_mpzs(a, s_), mul_mpzs(b, s_)),250        (r, mul_mpzs(a, m_), mul_mpzs(b, m_)),251        (r, mul_mpzs(a, l_), mul_mpzs(b, l_)),252    ]253 254 255def mpz_export_data(api):256    rop = ["0"]257    countp = ["0"]258    order = ["-1", "1"]259    size = ["1", "2", "4", "8"]260    endian = ["0"]261    nails = ["0"]262    ops = gen_mpz_args(1000) + gen_mpzs(count=100, mindigits=100, maxdigits=1000)263 264    args = []265    for r in rop:266        for c in countp:267            for o in order:268                for s in size:269                    for e in endian:270                        for n in nails:271                            for op in ops:272                                args.append((r, c, o, s, e, n, op))273    return args274 275 276def mpz_sizeinbase_data(api):277    bases = list(map(str, range(2, 37)))278    ops = gen_mpz_args(1000) + gen_mpzs(count=1000, mindigits=100, maxdigits=2000)279    return [(op, b) for op in ops for b in bases]280 281 282def get_str_data(ty):283    bases = list(range(2, 37)) + list(range(-2, -37, -1))284    bases = list(map(str, bases))285    if ty == gmpapi.mpz_t:286        ops = gen_mpz_args(1000)287    elif ty == gmpapi.mpq_t:288        ops = gen_mpq_args(20)289    else:290        raise RuntimeError("Unsupported get_str type: " + str(ty))291    return [("NULL", b, op) for b in bases for op in ops]292 293 294def mpz_get_str_data(api):295    return get_str_data(gmpapi.mpz_t)296 297 298def mpq_get_str_data(api):299    return get_str_data(gmpapi.mpq_t)300 301 302def mpq_set_str_data(api):303    args = gen_mpq_args(20) + gen_mpz_args()304    # zero does not match results exactly because the305    # results are not canonicalized first. We choose to306    # exclude zero from test results. The other option is307    # to canonicalize the results after parsing the strings.308    # Instead we exclude zero so that we can independently309    # test correctness of set_str and canonicalization310    nonzero = []311    for arg in args:312        if "/" in arg:313            pos = arg.find("/")314            if int(arg[:pos]) != 0:315                nonzero.append(arg)316        elif int(arg) != 0:317            nonzero.append(arg)318 319    return [("0", q, "10") for q in nonzero]320 321 322def get_div_data(n, d, rate=0.2):323    """Generate some inputs that are perfectly divisible"""324    if random.random() < rate:325        n = mul_mpzs(n, d)326    return (n, d)327 328 329def allow(name, args):330    if name not in blacklists:331        return True332    filters = blacklists[name]333    for (pos, disallow) in filters:334        if args[pos] in disallow:335            return False336    return True337 338 339def fixup_args(name, args):340    if name not in fixups:341        return [args]342    return fixups[name](args)343 344 345# list of values to be excluded for various api calls346# list format is (pos, [list of values to exclude])347blacklists = {348    "mpz_cdiv_q": [(2, ["0", "-0"])],349    "mpz_fdiv_q": [(2, ["0", "-0"])],350    "mpz_fdiv_r": [(2, ["0", "-0"])],351    "mpz_tdiv_q": [(2, ["0", "-0"])],352    "mpz_fdiv_q_ui": [(2, ["0", "-0"])],353    "mpz_divexact": [(2, ["0", "-0"])],354    "mpz_divisible_p": [(1, ["0", "-0"])],355    "mpz_divexact_ui": [(2, ["0", "-0"])],356    "mpq_set_ui": [(2, ["0", "-0"])],357}358 359fixups = {360    "mpz_divexact": mpz_divexact_data,361    "mpz_divisible_p": mpz_divisible_p_data,362    "mpz_cdiv_q": mpz_div3_data,363    "mpz_fdiv_q": mpz_div3_data,364    "mpz_fdiv_r": mpz_div3_data,365    "mpz_tdiv_q": mpz_div3_data,366    "mpz_fdiv_q_ui": mpz_div3_data,367    "mpz_divexact_ui": mpz_divexact_data,368    "mpz_pow_ui": mpz_pow_data,369    "mpz_gcd": mpz_gcd_data,370    "mpz_lcm": mpz_gcd_data,371    "mpz_mul_2exp": mpz_mul_2exp_data,372}373 374custom = {375    "mpz_export": mpz_export_data,376    "mpz_import": mpz_export_data,377    "mpz_sizeinbase": mpz_sizeinbase_data,378    "mpz_get_str": mpz_get_str_data,379    "mpq_set_str": mpq_set_str_data,380    "mpq_get_str": mpq_get_str_data,381}382 383if __name__ == "__main__":384    # apis = [gmpapi.get_api("mpq_set_str"),]385    apis = gmpapi.apis386    for api in apis:387        tests = gen_args(api)388        for args in tests:389            expanded_args = fixup_args(api.name, args)390            for args in expanded_args:391                if allow(api.name, args):392                    print("{}|{}".format(api.name, ",".join(args)))393