LCOV - code coverage report
Current view: top level - ecm - spv.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 38 38 100.0 %
Date: 2022-03-21 11:19:20 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /* spv.c - "small prime vector" functions for arithmetic on vectors of
       2             :    residues modulo a single small prime
       3             : 
       4             : Copyright 2005, 2006, 2007, 2008, 2009 Dave Newman, Jason Papadopoulos,
       5             : Brian Gladman, Alexander Kruppa, Paul Zimmermann.
       6             : 
       7             : The SP Library is free software; you can redistribute it and/or modify
       8             : it under the terms of the GNU Lesser General Public License as published by
       9             : the Free Software Foundation; either version 3 of the License, or (at your
      10             : option) any later version.
      11             : 
      12             : The SP Library is distributed in the hope that it will be useful, but
      13             : WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      14             : or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
      15             : License for more details.
      16             : 
      17             : You should have received a copy of the GNU Lesser General Public License
      18             : along with the SP Library; see the file COPYING.LIB.  If not, write to
      19             : the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
      20             : MA 02110-1301, USA. */
      21             : 
      22             : #include "config.h"
      23             : #include <string.h> /* for memset */
      24             : #include "sp.h"
      25             : #ifdef USE_VALGRIND
      26             : #include <valgrind/memcheck.h>
      27             : #endif
      28             : #include "ecm-impl.h"
      29             : 
      30             : /* Routines for vectors of integers modulo r common small prime
      31             :  * 
      32             :  * These are low-overhead routines that don't do memory allocation,
      33             :  * other than for temporary variables. Unless otherwise specified, any
      34             :  * of the input pointers can be equal. */
      35             : 
      36             : #ifdef WANT_ASSERT
      37             : int
      38             : spv_verify (spv_t x, spv_size_t len, const sp_t m)
      39             : {
      40             :   spv_size_t i;
      41             : #ifdef USE_VALGRIND
      42             :   if (len > 0)
      43             :     {
      44             :       if (VALGRIND_CHECK_MEM_IS_DEFINED(x, len * sizeof(sp_t)) != 0)
      45             :         return 0;
      46             :     }
      47             : #endif
      48             :   for (i = 0; i < len; i++)
      49             :     {
      50             :       if (x[i] >= m)
      51             :         return 0;
      52             :     }
      53             :   
      54             :   return 1;
      55             : }
      56             : #endif
      57             : 
      58             : /* r = x */
      59             : void
      60     5895776 : spv_set (spv_t r, spv_t x, spv_size_t len)
      61             : {
      62             : #ifdef HAVE_MEMMOVE  
      63             :   /* memmove doesn't rely on the assertion below */
      64     5895776 :   memmove (r, x, len * sizeof (sp_t));
      65             : #else
      66             :   spv_size_t i;
      67             : 
      68             :   ASSERT (r >= x + len || x >= r);
      69             : 
      70             :   for (i = 0; i < len; i++)
      71             :     r[i] = x[i];
      72             : #endif
      73     5895776 : }
      74             : 
      75             : /* r[0 ... len - 1] = x[len - 1 ... 0]  */
      76             : void
      77        7695 : spv_rev (spv_t r, spv_t x, spv_size_t len)
      78             : {
      79             :   spv_size_t i;
      80             :   
      81             :   ASSERT (r >= x + len || x >= r + len);
      82             : 
      83    23749383 :   for (i = 0; i < len; i++)
      84    23741688 :     r[i] = x[len - 1 - i];
      85        7695 : }
      86             : 
      87             : /* r = [y, y, ... ] */
      88             : void
      89      549593 : spv_set_sp (spv_t r, sp_t y, spv_size_t len)
      90             : {
      91             :   spv_size_t i;
      92             : 
      93    94867710 :   for (i = 0; i < len; i++)
      94    94318117 :     r[i] = y;
      95      549593 : }
      96             : 
      97             : void
      98     1447032 : spv_set_zero (spv_t r, spv_size_t len)
      99             : {
     100     1447032 :   memset (r, 0, len * sizeof (sp_t));
     101     1447032 : }
     102             : 
     103             : /* r = x + y */
     104             : void
     105        2623 : spv_add (spv_t r, spv_t x, spv_t y, spv_size_t len, sp_t m)
     106             : {
     107             :   spv_size_t i;
     108             :   
     109             :   ASSERT (r >= x + len || x >= r);
     110             :   ASSERT (r >= y + len || y >= r);
     111             :   
     112    49719103 :   for (i = 0; i < len; i++)
     113    49716480 :     r[i] = sp_add (x[i], y[i], m);
     114        2623 : }
     115             : 
     116             : /* r = [-x[0], -x[1], ... ] */
     117             : void
     118        6515 : spv_neg (spv_t r, spv_t x, spv_size_t len, sp_t m)
     119             : {
     120             :   spv_size_t i;
     121             : 
     122    16026739 :   for (i = 0; i < len; i++)
     123    16020224 :     r[i] = sp_sub (0, x[i], m);
     124        6515 : }
     125             : 
     126             : /* Pointwise multiplication
     127             :  * r = [x[0] * y[0], x[1] * y[1], ... ] */
     128             : void
     129     1453040 : spv_pwmul (spv_t r, spv_t x, spv_t y, spv_size_t len, sp_t m, sp_t d)
     130             : {
     131     1453040 :   spv_size_t i = 0;
     132             :   
     133             :   ASSERT (r >= x + len || x >= r);
     134             :   ASSERT (r >= y + len || y >= r);
     135             : 
     136             : #if (defined(__GNUC__) || defined(__ICL)) && \
     137             :         defined(__i386__) && defined(HAVE_SSE2)
     138             : 
     139             :   asm volatile (
     140             :        "movd %6, %%xmm6            \n\t"
     141             :        "pshufd $0x44, %%xmm6, %%xmm5  \n\t"
     142             :        "pshufd $0, %%xmm6, %%xmm6  \n\t"
     143             :        "movd %7, %%xmm7            \n\t"
     144             :        "pshufd $0, %%xmm7, %%xmm7  \n\t"
     145             : 
     146             :        "0:                         \n\t"
     147             :        "movdqa (%1,%4,4), %%xmm0   \n\t"
     148             :        "movdqa (%2,%4,4), %%xmm2   \n\t"
     149             :        "pshufd $0x31, %%xmm0, %%xmm1\n\t"
     150             :        "pshufd $0x31, %%xmm2, %%xmm3\n\t"
     151             :        "pmuludq %%xmm2, %%xmm0     \n\t"
     152             :        "pmuludq %%xmm3, %%xmm1     \n\t"
     153             : 
     154             :        "movdqa %%xmm0, %%xmm2      \n\t"
     155             :        "movdqa %%xmm1, %%xmm3      \n\t"
     156             :        "psrlq $" STRING((2*SP_NUMB_BITS - W_TYPE_SIZE)) ", %%xmm2  \n\t"
     157             :        "pmuludq %%xmm7, %%xmm2     \n\t"
     158             :        "psrlq $" STRING((2*SP_NUMB_BITS - W_TYPE_SIZE)) ", %%xmm3  \n\t"
     159             :        "pmuludq %%xmm7, %%xmm3     \n\t"
     160             : 
     161             : #if SP_NUMB_BITS < W_TYPE_SIZE - 1
     162             :        "psrlq $33, %%xmm2          \n\t"
     163             :        "pmuludq %%xmm6, %%xmm2     \n\t"
     164             :        "psrlq $33, %%xmm3          \n\t"
     165             :        "pmuludq %%xmm6, %%xmm3     \n\t"
     166             :        "psubq %%xmm2, %%xmm0       \n\t"
     167             :        "psubq %%xmm3, %%xmm1       \n\t"
     168             : #else
     169             :        "pshufd $0xf5, %%xmm2, %%xmm2 \n\t"
     170             :        "pmuludq %%xmm6, %%xmm2     \n\t"
     171             :        "pshufd $0xf5, %%xmm3, %%xmm3 \n\t"
     172             :        "pmuludq %%xmm6, %%xmm3     \n\t"
     173             :        "psubq %%xmm2, %%xmm0       \n\t"
     174             :        "psubq %%xmm3, %%xmm1       \n\t"
     175             : 
     176             :        "psubq %%xmm5, %%xmm0       \n\t"
     177             :        "psubq %%xmm5, %%xmm1       \n\t"
     178             :        "pshufd $0xf5, %%xmm0, %%xmm2 \n\t"
     179             :        "pshufd $0xf5, %%xmm1, %%xmm3 \n\t"
     180             :        "pand %%xmm5, %%xmm2        \n\t"
     181             :        "pand %%xmm5, %%xmm3        \n\t"
     182             :        "paddq %%xmm2, %%xmm0       \n\t"
     183             :        "paddq %%xmm3, %%xmm1       \n\t"
     184             : #endif
     185             :        "pshufd $0x8, %%xmm0, %%xmm0 \n\t"
     186             :        "pshufd $0x8, %%xmm1, %%xmm1 \n\t"
     187             :        "punpckldq %%xmm1, %%xmm0   \n\t"
     188             :        "psubd %%xmm6, %%xmm0       \n\t"
     189             : 
     190             :        "pxor %%xmm1, %%xmm1        \n\t"
     191             :        "pcmpgtd %%xmm0, %%xmm1     \n\t"
     192             :        "pand %%xmm6, %%xmm1        \n\t"
     193             :        "paddd %%xmm1, %%xmm0       \n\t"
     194             :        "movdqa %%xmm0, (%3,%4,4)   \n\t"
     195             : 
     196             :        "addl $4, %4                \n\t"  /* INC */
     197             :        "cmpl %5, %4                \n\t"
     198             :        "jne 0b                     \n\t"
     199             : 
     200             :        :"=r"(i)
     201             :        :"r"(x), "r"(y), "r"(r), "0"(i), 
     202             :         "g"(len & (spv_size_t)(~3)), "g"(m), "g"(d)
     203             :        :"%xmm0", "%xmm1", "%xmm2", "%xmm3",
     204             :         "%xmm5", "%xmm6", "%xmm7", "cc", "memory");
     205             : #elif defined( _MSC_VER ) && defined( SSE2)
     206             :     __asm
     207             :     {   push        esi
     208             :         push        edi
     209             :         mov         edi, x
     210             :         mov         esi, y
     211             :         mov         edx, r
     212             :         xor         ecx, ecx
     213             :         mov         eax, len
     214             :         and         eax, ~3
     215             : 
     216             :         movd        xmm6, m
     217             :         pshufd      xmm5, xmm6, 0x44
     218             :         pshufd      xmm6, xmm6, 0
     219             :         movd        xmm7, d
     220             :         pshufd      xmm7, xmm7, 0
     221             : 
     222             :     L0: movdqa      xmm0, [edi+ecx*4]
     223             :         movdqa      xmm2, [esi+ecx*4]
     224             :         pshufd      xmm1, xmm0, 0x31
     225             :         pshufd      xmm3, xmm2, 0x31
     226             :         pmuludq     xmm0, xmm2
     227             :         pmuludq     xmm1, xmm3
     228             : 
     229             :         movdqa      xmm2, xmm0
     230             :         movdqa      xmm3, xmm1
     231             :         psrlq       xmm2, 2*SP_NUMB_BITS - W_TYPE_SIZE
     232             :         pmuludq     xmm2, xmm7
     233             :         psrlq       xmm3, 2*SP_NUMB_BITS - W_TYPE_SIZE
     234             :         pmuludq     xmm3, xmm7
     235             : 
     236             : #if SP_NUMB_BITS < W_TYPE_SIZE - 1
     237             :         psrlq       xmm2, 33
     238             :         pmuludq     xmm2, xmm6
     239             :         psrlq       xmm3, 33
     240             :         pmuludq     xmm3, xmm6
     241             :         psubq       xmm0, xmm2
     242             :         psubq       xmm1, xmm3
     243             : #else
     244             :         pshufd      xmm2, xmm2, 0xf5
     245             :         pmuludq     xmm2, xmm6
     246             :         pshufd      xmm3, xmm3, 0xf5
     247             :         pmuludq     xmm3, xmm6
     248             :         psubq       xmm0, xmm2
     249             :         psubq       xmm1, xmm3
     250             : 
     251             :         psubq       xmm0, xmm5
     252             :         psubq       xmm1, xmm5
     253             :         pshufd      xmm2, xmm0, 0xf5
     254             :         pshufd      xmm3, xmm1, 0xf5
     255             :         pand        xmm2, xmm5
     256             :         pand        xmm3, xmm5
     257             :         paddq       xmm0, xmm2
     258             :         paddq       xmm1, xmm3
     259             : #endif
     260             :         pshufd      xmm0, xmm0, 0x8
     261             :         pshufd      xmm1, xmm1, 0x8
     262             :         punpckldq   xmm0, xmm1
     263             :         psubd       xmm0, xmm6
     264             : 
     265             :         pxor        xmm1, xmm1
     266             :         pcmpgtd     xmm1, xmm0
     267             :         pand        xmm1, xmm6
     268             :         paddd       xmm0, xmm1
     269             :         movdqa      [edx+ecx*4], xmm0
     270             : 
     271             :         add         ecx, 4
     272             :         cmp         eax, ecx
     273             :         jne         L0
     274             :         mov         i, ecx
     275             :         pop         edi
     276             :         pop         esi
     277             :     }
     278             : #endif
     279             : 
     280   837068320 :   for (; i < len; i++)
     281   835615280 :     r[i] = sp_mul (x[i], y[i], m, d);
     282     1453040 : }
     283             : 
     284             : /* dst = src * y */
     285             : void
     286    22893072 : spv_mul_sp (spv_t r, spv_t x, sp_t c, spv_size_t len, sp_t m, sp_t d)
     287             : {
     288    22893072 :   spv_size_t i = 0;
     289             :   
     290             :   ASSERT (r >= x + len || x >= r);
     291             :   
     292             : #if (defined(__GNUC__) || defined(__ICL)) && \
     293             :         defined(__i386__) && defined(HAVE_SSE2)
     294             : 
     295             :   asm volatile (
     296             :        "movd %2, %%xmm4            \n\t"
     297             :        "pshufd $0, %%xmm4, %%xmm4  \n\t"
     298             :        "movd %6, %%xmm6            \n\t"
     299             :        "pshufd $0x44, %%xmm6, %%xmm5  \n\t"
     300             :        "pshufd $0, %%xmm6, %%xmm6  \n\t"
     301             :        "movd %7, %%xmm7            \n\t"
     302             :        "pshufd $0, %%xmm7, %%xmm7  \n\t"
     303             : 
     304             :        "0:                         \n\t"
     305             :        "movdqa (%1,%4,4), %%xmm0   \n\t"
     306             :        "pshufd $0x31, %%xmm0, %%xmm1\n\t"
     307             :        "pshufd $0x31, %%xmm4, %%xmm3\n\t"
     308             :        "pmuludq %%xmm4, %%xmm0     \n\t"
     309             :        "pmuludq %%xmm3, %%xmm1     \n\t"
     310             : 
     311             :        "movdqa %%xmm0, %%xmm2      \n\t"
     312             :        "movdqa %%xmm1, %%xmm3      \n\t"
     313             :        "psrlq $" STRING((2*SP_NUMB_BITS - W_TYPE_SIZE)) ", %%xmm2  \n\t"
     314             :        "pmuludq %%xmm7, %%xmm2     \n\t"
     315             :        "psrlq $" STRING((2*SP_NUMB_BITS - W_TYPE_SIZE)) ", %%xmm3  \n\t"
     316             :        "pmuludq %%xmm7, %%xmm3     \n\t"
     317             : 
     318             : #if SP_NUMB_BITS < W_TYPE_SIZE - 1
     319             :        "psrlq $33, %%xmm2          \n\t"
     320             :        "pmuludq %%xmm6, %%xmm2     \n\t"
     321             :        "psrlq $33, %%xmm3          \n\t"
     322             :        "pmuludq %%xmm6, %%xmm3     \n\t"
     323             :        "psubq %%xmm2, %%xmm0       \n\t"
     324             :        "psubq %%xmm3, %%xmm1       \n\t"
     325             : #else
     326             :        "pshufd $0xf5, %%xmm2, %%xmm2 \n\t"
     327             :        "pmuludq %%xmm6, %%xmm2     \n\t"
     328             :        "pshufd $0xf5, %%xmm3, %%xmm3 \n\t"
     329             :        "pmuludq %%xmm6, %%xmm3     \n\t"
     330             :        "psubq %%xmm2, %%xmm0       \n\t"
     331             :        "psubq %%xmm3, %%xmm1       \n\t"
     332             : 
     333             :        "psubq %%xmm5, %%xmm0       \n\t"
     334             :        "psubq %%xmm5, %%xmm1       \n\t"
     335             :        "pshufd $0xf5, %%xmm0, %%xmm2 \n\t"
     336             :        "pshufd $0xf5, %%xmm1, %%xmm3 \n\t"
     337             :        "pand %%xmm5, %%xmm2        \n\t"
     338             :        "pand %%xmm5, %%xmm3        \n\t"
     339             :        "paddq %%xmm2, %%xmm0       \n\t"
     340             :        "paddq %%xmm3, %%xmm1       \n\t"
     341             : #endif
     342             :        "pshufd $0x8, %%xmm0, %%xmm0 \n\t"
     343             :        "pshufd $0x8, %%xmm1, %%xmm1 \n\t"
     344             :        "punpckldq %%xmm1, %%xmm0   \n\t"
     345             :        "psubd %%xmm6, %%xmm0       \n\t"
     346             : 
     347             :        "pxor %%xmm1, %%xmm1        \n\t"
     348             :        "pcmpgtd %%xmm0, %%xmm1     \n\t"
     349             :        "pand %%xmm6, %%xmm1        \n\t"
     350             :        "paddd %%xmm1, %%xmm0       \n\t"
     351             :        "movdqa %%xmm0, (%3,%4,4)   \n\t"
     352             : 
     353             :        "addl $4, %4                \n\t"  /* INC */
     354             :        "cmpl %5, %4                \n\t"
     355             :        "jne 0b                     \n\t"
     356             : 
     357             :        :"=r"(i)
     358             :        :"r"(x), "g"(c), "r"(r), "0"(i), 
     359             :         "g"(len & (spv_size_t)(~3)), "g"(m), "g"(d)
     360             :        :"%xmm0", "%xmm1", "%xmm2", "%xmm3",
     361             :         "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory");
     362             : #elif defined( _MSC_VER ) && defined( SSE2) 
     363             :     __asm
     364             :     {   push        esi
     365             :         push        edi
     366             :         xor         ecx, ecx
     367             :         mov         edi, x
     368             :         mov         esi, c
     369             :         mov         edx, r
     370             :         mov         eax, len
     371             :         and         eax, ~3
     372             : 
     373             :         movd        xmm4, esi
     374             :         pshufd      xmm4, xmm4, 0
     375             :         movd        xmm6, m
     376             :         pshufd      xmm5, xmm6, 0x44
     377             :         pshufd      xmm6, xmm6, 0
     378             :         movd        xmm7, d
     379             :         pshufd      xmm7, xmm7, 0
     380             : 
     381             :     L0: movdqa      xmm0, [edi+ecx*4]
     382             :         pshufd      xmm1, xmm0, 0x31
     383             :         pshufd      xmm3, xmm4, 0x31
     384             :         pmuludq     xmm0, xmm4
     385             :         pmuludq     xmm1, xmm3
     386             : 
     387             :         movdqa      xmm2, xmm0
     388             :         movdqa      xmm3, xmm1
     389             :         psrlq       xmm2, 2*SP_NUMB_BITS - W_TYPE_SIZE
     390             :         pmuludq     xmm2, xmm7
     391             :         psrlq       xmm3, 2*SP_NUMB_BITS - W_TYPE_SIZE
     392             :         pmuludq     xmm3, xmm7
     393             : 
     394             : #if SP_NUMB_BITS < W_TYPE_SIZE - 1
     395             :         psrlq       xmm2, 33
     396             :         pmuludq     xmm2, xmm6
     397             :         psrlq       xmm3, 33
     398             :         pmuludq     xmm3, xmm6
     399             :         psubq       xmm0, xmm2
     400             :         psubq       xmm1, xmm3
     401             : #else
     402             :         pshufd      xmm2, xmm2, 0xf5
     403             :         pmuludq     xmm2, xmm6
     404             :         pshufd      xmm3, xmm3, 0xf5
     405             :         pmuludq     xmm3, xmm6
     406             :         psubq       xmm0, xmm2
     407             :         psubq       xmm1, xmm3
     408             : 
     409             :         psubq       xmm0, xmm5
     410             :         psubq       xmm1, xmm5
     411             :         pshufd      xmm2, xmm0, 0xf5
     412             :         pshufd      xmm3, xmm1, 0xf5
     413             :         pand        xmm2, xmm5
     414             :         pand        xmm3, xmm5
     415             :         paddq       xmm0, xmm2
     416             :         paddq       xmm1, xmm3
     417             : #endif
     418             :         pshufd      xmm0, xmm0, 0x8
     419             :         pshufd      xmm1, xmm1, 0x8
     420             :         punpckldq   xmm0, xmm1
     421             :         psubd       xmm0, xmm6
     422             : 
     423             :         pxor        xmm1, xmm1
     424             :         pcmpgtd     xmm1, xmm0
     425             :         pand        xmm1, xmm6
     426             :         paddd       xmm0, xmm1
     427             :         movdqa      [edx+ecx*4], xmm0
     428             : 
     429             :         add         ecx, 4
     430             :         cmp         eax, ecx
     431             :         jne         L0
     432             :         mov         i, ecx
     433             :         pop         edi
     434             :         pop         esi
     435             :     }
     436             : #endif
     437             : 
     438  3634381864 :   for (; i < len; i++)
     439  3611488792 :     r[i] = sp_mul (x[i], c, m, d);
     440    22893072 : }
     441             : 
     442             : void
     443          24 : spv_random (spv_t x, spv_size_t len, sp_t m)
     444             : {
     445             :   spv_size_t i;
     446          24 :   mpn_random ((mp_ptr) x, len);
     447             :   
     448     6291480 :   for (i = 0; i < len; i++)
     449    15725866 :     while (x[i] >= m)
     450     9434410 :       x[i] -= m;
     451          24 : }

Generated by: LCOV version 1.14