t-fat.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:9k
源码类别:

数学计算

开发平台:

Unix_Linux

  1. /* Test fat binary setups.
  2. Copyright 2003 Free Software Foundation, Inc.
  3. This file is part of the GNU MP Library.
  4. The GNU MP Library is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or (at your
  7. option) any later version.
  8. The GNU MP Library is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  11. License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include "gmp.h"
  18. #include "gmp-impl.h"
  19. #include "longlong.h"
  20. #include "tests.h"
  21. /* In this program we're aiming to pick up certain subtle problems that
  22.    might creep into a fat binary.
  23.    1. We want to ensure the application entry point routines like
  24.       __gmpn_add_n dispatch to the correct field of __gmpn_cpuvec.
  25.       Note that these routines are not exercised as a side effect of other
  26.       tests (eg. the mpz routines).  Internally the fields of __gmpn_cpuvec
  27.       are used directly, so we need to write test code explicitly calling
  28.       the mpn functions, like an application will have.
  29.    2. We want to ensure the initial __gmpn_cpuvec data has the initializer
  30.       function pointers in the correct fields, and that those initializer
  31.       functions dispatch to their correct corresponding field once
  32.       initialization has been done.
  33.       Only one of the initializer routines executes in a normal program,
  34.       since that routine sets all the pointers to actual mpn functions.  We
  35.       forcibly reset __gmpn_cpuvec so we can run each.
  36.    In both cases for the above, the data put through the functions is
  37.    nothing special, just enough to verify that for instance an add_n is
  38.    really doing an add_n and has not for instance mistakenly gone to sub_n
  39.    or something.
  40.    The loop around each test will exercise the initializer routine on the
  41.    first iteration, and the dispatcher routine on the second.
  42.    If the dispatcher and/or initializer routines are generated mechanically
  43.    via macros (eg. mpn/x86/fat/fat_entry.asm) then there shouldn't be too
  44.    much risk of them going wrong, provided the structure layout is correctly
  45.    expressed.  But if they're in C then it's good to guard against typos in
  46.    what is rather repetitive code.  The initializer data for __gmpn_cpuvec
  47.    in fat.c is always done by hand and is likewise a bit repetitive.  */
  48. /* dummies when not a fat binary */
  49. #if ! WANT_FAT_BINARY
  50. struct cpuvec_t {
  51.   int  initialized;
  52. };
  53. struct cpuvec_t __gmpn_cpuvec;
  54. #define ITERATE_FAT_THRESHOLDS()  do { } while (0)
  55. #endif
  56. /* saved from program startup */
  57. struct cpuvec_t  initial_cpuvec;
  58. void
  59. check_functions (void)
  60. {
  61.   mp_limb_t  wp[2], xp[2], yp[2], r;
  62.   int  i;
  63.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  64.   for (i = 0; i < 2; i++)
  65.     {
  66.       xp[0] = 123;
  67.       yp[0] = 456;
  68.       mpn_add_n (wp, xp, yp, (mp_size_t) 1);
  69.       ASSERT_ALWAYS (wp[0] == 579);
  70.     }
  71.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  72.   for (i = 0; i < 2; i++)
  73.     {
  74.       xp[0] = 123;
  75.       wp[0] = 456;
  76.       r = mpn_addmul_1 (wp, xp, (mp_size_t) 1, CNST_LIMB(2));
  77.       ASSERT_ALWAYS (wp[0] == 702);
  78.       ASSERT_ALWAYS (r == 0);
  79.     }
  80. #if HAVE_NATIVE_mpn_copyd
  81.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  82.   for (i = 0; i < 2; i++)
  83.     {
  84.       xp[0] = 123;
  85.       xp[1] = 456;
  86.       mpn_copyd (xp+1, xp, (mp_size_t) 1);
  87.       ASSERT_ALWAYS (xp[1] == 123);
  88.     }
  89. #endif
  90. #if HAVE_NATIVE_mpn_copyi
  91.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  92.   for (i = 0; i < 2; i++)
  93.     {
  94.       xp[0] = 123;
  95.       xp[1] = 456;
  96.       mpn_copyi (xp, xp+1, (mp_size_t) 1);
  97.       ASSERT_ALWAYS (xp[0] == 456);
  98.     }
  99. #endif
  100.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  101.   for (i = 0; i < 2; i++)
  102.     {
  103.       xp[0] = 1605;
  104.       mpn_divexact_1 (wp, xp, (mp_size_t) 1, CNST_LIMB(5));
  105.       ASSERT_ALWAYS (wp[0] == 321);
  106.     }
  107.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  108.   for (i = 0; i < 2; i++)
  109.     {
  110.       xp[0] = 1296;
  111.       r = mpn_divexact_by3c (wp, xp, (mp_size_t) 1, CNST_LIMB(0));
  112.       ASSERT_ALWAYS (wp[0] == 432);
  113.       ASSERT_ALWAYS (r == 0);
  114.     }
  115.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  116.   for (i = 0; i < 2; i++)
  117.     {
  118.       xp[0] = 287;
  119.       r = mpn_divrem_1 (wp, (mp_size_t) 1, xp, (mp_size_t) 1, CNST_LIMB(7));
  120.       ASSERT_ALWAYS (wp[1] == 41);
  121.       ASSERT_ALWAYS (wp[0] == 0);
  122.       ASSERT_ALWAYS (r == 0);
  123.     }
  124.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  125.   for (i = 0; i < 2; i++)
  126.     {
  127.       xp[0] = 12;
  128.       r = mpn_gcd_1 (xp, (mp_size_t) 1, CNST_LIMB(9));
  129.       ASSERT_ALWAYS (r == 3);
  130.     }
  131.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  132.   for (i = 0; i < 2; i++)
  133.     {
  134.       xp[0] = 0x1001;
  135.       mpn_lshift (wp, xp, (mp_size_t) 1, 1);
  136.       ASSERT_ALWAYS (wp[0] == 0x2002);
  137.     }
  138.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  139.   for (i = 0; i < 2; i++)
  140.     {
  141.       xp[0] = 14;
  142.       r = mpn_mod_1 (xp, (mp_size_t) 1, CNST_LIMB(4));
  143.       ASSERT_ALWAYS (r == 2);
  144.     }
  145. #if (GMP_NUMB_BITS % 4) == 0
  146.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  147.   for (i = 0; i < 2; i++)
  148.     {
  149.       int  bits = (GMP_NUMB_BITS / 4) * 3;
  150.       mp_limb_t  mod = (CNST_LIMB(1) << bits) - 1;
  151.       mp_limb_t  want = GMP_NUMB_MAX % mod;
  152.       xp[0] = GMP_NUMB_MAX;
  153.       r = mpn_mod_34lsub1 (xp, (mp_size_t) 1);
  154.       ASSERT_ALWAYS (r % mod == want);
  155.     }
  156. #endif
  157.   /*   DECL_modexact_1c_odd ((*modexact_1c_odd)); */
  158.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  159.   for (i = 0; i < 2; i++)
  160.     {
  161.       xp[0] = 14;
  162.       r = mpn_mul_1 (wp, xp, (mp_size_t) 1, CNST_LIMB(4));
  163.       ASSERT_ALWAYS (wp[0] == 56);
  164.       ASSERT_ALWAYS (r == 0);
  165.     }
  166.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  167.   for (i = 0; i < 2; i++)
  168.     {
  169.       xp[0] = 5;
  170.       yp[0] = 7;
  171.       mpn_mul_basecase (wp, xp, (mp_size_t) 1, yp, (mp_size_t) 1);
  172.       ASSERT_ALWAYS (wp[0] == 35);
  173.       ASSERT_ALWAYS (wp[1] == 0);
  174.     }
  175. #if HAVE_NATIVE_mpn_preinv_divrem_1 && GMP_NAIL_BITS == 0
  176.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  177.   for (i = 0; i < 2; i++)
  178.     {
  179.       xp[0] = 0x101;
  180.       r = mpn_preinv_divrem_1 (wp, (mp_size_t) 1, xp, (mp_size_t) 1,
  181.                                GMP_LIMB_HIGHBIT,
  182.                                refmpn_invert_limb (GMP_LIMB_HIGHBIT), 0);
  183.       ASSERT_ALWAYS (wp[0] == 0x202);
  184.       ASSERT_ALWAYS (wp[1] == 0);
  185.       ASSERT_ALWAYS (r == 0);
  186.     }
  187. #endif
  188. #if GMP_NAIL_BITS == 0
  189.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  190.   for (i = 0; i < 2; i++)
  191.     {
  192.       xp[0] = GMP_LIMB_HIGHBIT+123;
  193.       r = mpn_preinv_mod_1 (xp, (mp_size_t) 1, GMP_LIMB_HIGHBIT,
  194.                             refmpn_invert_limb (GMP_LIMB_HIGHBIT));
  195.       ASSERT_ALWAYS (r == 123);
  196.     }
  197. #endif
  198.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  199.   for (i = 0; i < 2; i++)
  200.     {
  201.       xp[0] = 0x8008;
  202.       mpn_rshift (wp, xp, (mp_size_t) 1, 1);
  203.       ASSERT_ALWAYS (wp[0] == 0x4004);
  204.     }
  205.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  206.   for (i = 0; i < 2; i++)
  207.     {
  208.       xp[0] = 5;
  209.       mpn_sqr_basecase (wp, xp, (mp_size_t) 1);
  210.       ASSERT_ALWAYS (wp[0] == 25);
  211.       ASSERT_ALWAYS (wp[1] == 0);
  212.     }
  213.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  214.   for (i = 0; i < 2; i++)
  215.     {
  216.       xp[0] = 999;
  217.       yp[0] = 666;
  218.       mpn_sub_n (wp, xp, yp, (mp_size_t) 1);
  219.       ASSERT_ALWAYS (wp[0] == 333);
  220.     }
  221.   memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));
  222.   for (i = 0; i < 2; i++)
  223.     {
  224.       xp[0] = 123;
  225.       wp[0] = 456;
  226.       r = mpn_submul_1 (wp, xp, (mp_size_t) 1, CNST_LIMB(2));
  227.       ASSERT_ALWAYS (wp[0] == 210);
  228.       ASSERT_ALWAYS (r == 0);
  229.     }
  230. }
  231. /* Expect the first use of a each fat threshold to invoke the necessary
  232.    initialization.  */
  233. void
  234. check_thresholds (void)
  235. {
  236. #define ITERATE(name,field)                                             
  237.   do {                                                                  
  238.     memcpy (&__gmpn_cpuvec, &initial_cpuvec, sizeof (__gmpn_cpuvec));   
  239.     ASSERT_ALWAYS (name != 0);                                          
  240.     ASSERT_ALWAYS (name == __gmpn_cpuvec.field);                        
  241.     ASSERT_ALWAYS (__gmpn_cpuvec.initialized);                          
  242.   } while (0)
  243.   ITERATE_FAT_THRESHOLDS ();
  244. }
  245. int
  246. main (void)
  247. {
  248.   memcpy (&initial_cpuvec, &__gmpn_cpuvec, sizeof (__gmpn_cpuvec));
  249.   tests_start ();
  250.   check_functions ();
  251.   check_thresholds ();
  252.   tests_end ();
  253.   exit (0);
  254. }