t-fat.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:9k
- /* Test fat binary setups.
- Copyright 2003 Free Software Foundation, Inc.
- This file is part of the GNU MP Library.
- The GNU MP Library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 3 of the License, or (at your
- option) any later version.
- The GNU MP Library is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
- You should have received a copy of the GNU Lesser General Public License
- along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "gmp.h"
- #include "gmp-impl.h"
- #include "longlong.h"
- #include "tests.h"
- /* In this program we're aiming to pick up certain subtle problems that
- might creep into a fat binary.
- 1. We want to ensure the application entry point routines like
- __gmpn_add_n dispatch to the correct field of __gmpn_cpuvec.
- Note that these routines are not exercised as a side effect of other
- tests (eg. the mpz routines). Internally the fields of __gmpn_cpuvec
- are used directly, so we need to write test code explicitly calling
- the mpn functions, like an application will have.
- 2. We want to ensure the initial __gmpn_cpuvec data has the initializer
- function pointers in the correct fields, and that those initializer
- functions dispatch to their correct corresponding field once
- initialization has been done.
- Only one of the initializer routines executes in a normal program,
- since that routine sets all the pointers to actual mpn functions. We
- forcibly reset __gmpn_cpuvec so we can run each.
- In both cases for the above, the data put through the functions is
- nothing special, just enough to verify that for instance an add_n is
- really doing an add_n and has not for instance mistakenly gone to sub_n
- or something.
- The loop around each test will exercise the initializer routine on the
- first iteration, and the dispatcher routine on the second.
- If the dispatcher and/or initializer routines are generated mechanically
- via macros (eg. mpn/x86/fat/fat_entry.asm) then there shouldn't be too
- much risk of them going wrong, provided the structure layout is correctly
- expressed. But if they're in C then it's good to guard against typos in
- what is rather repetitive code. The initializer data for __gmpn_cpuvec
- in fat.c is always done by hand and is likewise a bit repetitive. */
- /* dummies when not a fat binary */
- #if ! WANT_FAT_BINARY
- struct cpuvec_t {
- int initialized;
- };
- struct cpuvec_t __gmpn_cpuvec;
- #define ITERATE_FAT_THRESHOLDS() do { } while (0)
- #endif
- /* saved from program startup */
- struct cpuvec_t initial_cpuvec;
- void
- check_functions (void)
- {
- mp_limb_t wp[2], xp[2], yp[2], r;
- int i;
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 123;
- yp[0] = 456;
- mpn_add_n (wp, xp, yp, (mp_size_t) 1);
- ASSERT_ALWAYS (wp[0] == 579);
- }
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 123;
- wp[0] = 456;
- r = mpn_addmul_1 (wp, xp, (mp_size_t) 1, CNST_LIMB(2));
- ASSERT_ALWAYS (wp[0] == 702);
- ASSERT_ALWAYS (r == 0);
- }
- #if HAVE_NATIVE_mpn_copyd
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 123;
- xp[1] = 456;
- mpn_copyd (xp+1, xp, (mp_size_t) 1);
- ASSERT_ALWAYS (xp[1] == 123);
- }
- #endif
- #if HAVE_NATIVE_mpn_copyi
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 123;
- xp[1] = 456;
- mpn_copyi (xp, xp+1, (mp_size_t) 1);
- ASSERT_ALWAYS (xp[0] == 456);
- }
- #endif
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 1605;
- mpn_divexact_1 (wp, xp, (mp_size_t) 1, CNST_LIMB(5));
- ASSERT_ALWAYS (wp[0] == 321);
- }
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 1296;
- r = mpn_divexact_by3c (wp, xp, (mp_size_t) 1, CNST_LIMB(0));
- ASSERT_ALWAYS (wp[0] == 432);
- ASSERT_ALWAYS (r == 0);
- }
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 287;
- r = mpn_divrem_1 (wp, (mp_size_t) 1, xp, (mp_size_t) 1, CNST_LIMB(7));
- ASSERT_ALWAYS (wp[1] == 41);
- ASSERT_ALWAYS (wp[0] == 0);
- ASSERT_ALWAYS (r == 0);
- }
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 12;
- r = mpn_gcd_1 (xp, (mp_size_t) 1, CNST_LIMB(9));
- ASSERT_ALWAYS (r == 3);
- }
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 0x1001;
- mpn_lshift (wp, xp, (mp_size_t) 1, 1);
- ASSERT_ALWAYS (wp[0] == 0x2002);
- }
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 14;
- r = mpn_mod_1 (xp, (mp_size_t) 1, CNST_LIMB(4));
- ASSERT_ALWAYS (r == 2);
- }
- #if (GMP_NUMB_BITS % 4) == 0
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- int bits = (GMP_NUMB_BITS / 4) * 3;
- mp_limb_t mod = (CNST_LIMB(1) << bits) - 1;
- mp_limb_t want = GMP_NUMB_MAX % mod;
- xp[0] = GMP_NUMB_MAX;
- r = mpn_mod_34lsub1 (xp, (mp_size_t) 1);
- ASSERT_ALWAYS (r % mod == want);
- }
- #endif
- /* DECL_modexact_1c_odd ((*modexact_1c_odd)); */
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 14;
- r = mpn_mul_1 (wp, xp, (mp_size_t) 1, CNST_LIMB(4));
- ASSERT_ALWAYS (wp[0] == 56);
- ASSERT_ALWAYS (r == 0);
- }
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 5;
- yp[0] = 7;
- mpn_mul_basecase (wp, xp, (mp_size_t) 1, yp, (mp_size_t) 1);
- ASSERT_ALWAYS (wp[0] == 35);
- ASSERT_ALWAYS (wp[1] == 0);
- }
- #if HAVE_NATIVE_mpn_preinv_divrem_1 && GMP_NAIL_BITS == 0
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 0x101;
- r = mpn_preinv_divrem_1 (wp, (mp_size_t) 1, xp, (mp_size_t) 1,
- GMP_LIMB_HIGHBIT,
- refmpn_invert_limb (GMP_LIMB_HIGHBIT), 0);
- ASSERT_ALWAYS (wp[0] == 0x202);
- ASSERT_ALWAYS (wp[1] == 0);
- ASSERT_ALWAYS (r == 0);
- }
- #endif
- #if GMP_NAIL_BITS == 0
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = GMP_LIMB_HIGHBIT+123;
- r = mpn_preinv_mod_1 (xp, (mp_size_t) 1, GMP_LIMB_HIGHBIT,
- refmpn_invert_limb (GMP_LIMB_HIGHBIT));
- ASSERT_ALWAYS (r == 123);
- }
- #endif
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 0x8008;
- mpn_rshift (wp, xp, (mp_size_t) 1, 1);
- ASSERT_ALWAYS (wp[0] == 0x4004);
- }
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 5;
- mpn_sqr_basecase (wp, xp, (mp_size_t) 1);
- ASSERT_ALWAYS (wp[0] == 25);
- ASSERT_ALWAYS (wp[1] == 0);
- }
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 999;
- yp[0] = 666;
- mpn_sub_n (wp, xp, yp, (mp_size_t) 1);
- ASSERT_ALWAYS (wp[0] == 333);
- }
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- for (i = 0; i < 2; i++)
- {
- xp[0] = 123;
- wp[0] = 456;
- r = mpn_submul_1 (wp, xp, (mp_size_t) 1, CNST_LIMB(2));
- ASSERT_ALWAYS (wp[0] == 210);
- ASSERT_ALWAYS (r == 0);
- }
- }
- /* Expect the first use of a each fat threshold to invoke the necessary
- initialization. */
- void
- check_thresholds (void)
- {
- #define ITERATE(name,field)
- do {
- memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
- ASSERT_ALWAYS (name != 0);
- ASSERT_ALWAYS (name == __gmpn_cpuvec.field);
- ASSERT_ALWAYS (__gmpn_cpuvec.initialized);
- } while (0)
- ITERATE_FAT_THRESHOLDS ();
- }
- int
- main (void)
- {
- memcpy (&initial_cpuvec, &__gmpn_cpuvec, sizeof (__gmpn_cpuvec));
- tests_start ();
- check_functions ();
- check_thresholds ();
- tests_end ();
- exit (0);
- }