Coverage Report

Created: 2023-09-25 06:33

/src/gmp-6.2.1/mpz/mul.c
Line
Count
Source (jump to first uncovered line)
1
/* mpz_mul -- Multiply two integers.
2
3
Copyright 1991, 1993, 1994, 1996, 2000, 2001, 2005, 2009, 2011, 2012,
4
2015 Free Software Foundation, Inc.
5
6
This file is part of the GNU MP Library.
7
8
The GNU MP Library is free software; you can redistribute it and/or modify
9
it under the terms of either:
10
11
  * the GNU Lesser General Public License as published by the Free
12
    Software Foundation; either version 3 of the License, or (at your
13
    option) any later version.
14
15
or
16
17
  * the GNU General Public License as published by the Free Software
18
    Foundation; either version 2 of the License, or (at your option) any
19
    later version.
20
21
or both in parallel, as here.
22
23
The GNU MP Library is distributed in the hope that it will be useful, but
24
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
26
for more details.
27
28
You should have received copies of the GNU General Public License and the
29
GNU Lesser General Public License along with the GNU MP Library.  If not,
30
see https://www.gnu.org/licenses/.  */
31
32
#include <stdio.h> /* for NULL */
33
#include "gmp-impl.h"
34
35
36
void
37
mpz_mul (mpz_ptr w, mpz_srcptr u, mpz_srcptr v)
38
786
{
39
786
  mp_size_t usize;
40
786
  mp_size_t vsize;
41
786
  mp_size_t wsize;
42
786
  mp_size_t sign_product;
43
786
  mp_ptr up, vp;
44
786
  mp_ptr wp;
45
786
  mp_ptr free_me;
46
786
  size_t free_me_size;
47
786
  mp_limb_t cy_limb;
48
786
  TMP_DECL;
49
50
786
  usize = SIZ (u);
51
786
  vsize = SIZ (v);
52
786
  sign_product = usize ^ vsize;
53
786
  usize = ABS (usize);
54
786
  vsize = ABS (vsize);
55
56
786
  if (usize < vsize)
57
0
    {
58
0
      MPZ_SRCPTR_SWAP (u, v);
59
0
      MP_SIZE_T_SWAP (usize, vsize);
60
0
    }
61
62
786
  if (vsize == 0)
63
46
    {
64
46
      SIZ (w) = 0;
65
46
      return;
66
46
    }
67
68
740
#if HAVE_NATIVE_mpn_mul_2
69
740
  if (vsize <= 2)
70
164
    {
71
164
      wp = MPZ_REALLOC (w, usize+vsize);
72
164
      if (vsize == 1)
73
102
  cy_limb = mpn_mul_1 (wp, PTR (u), usize, PTR (v)[0]);
74
62
      else
75
62
  {
76
62
    cy_limb = mpn_mul_2 (wp, PTR (u), usize, PTR (v));
77
62
    usize++;
78
62
  }
79
164
      wp[usize] = cy_limb;
80
164
      usize += (cy_limb != 0);
81
164
      SIZ (w) = (sign_product >= 0 ? usize : -usize);
82
164
      return;
83
164
    }
84
#else
85
  if (vsize == 1)
86
    {
87
      wp = MPZ_REALLOC (w, usize+1);
88
      cy_limb = mpn_mul_1 (wp, PTR (u), usize, PTR (v)[0]);
89
      wp[usize] = cy_limb;
90
      usize += (cy_limb != 0);
91
      SIZ (w) = (sign_product >= 0 ? usize : -usize);
92
      return;
93
    }
94
#endif
95
96
576
  TMP_MARK;
97
576
  free_me = NULL;
98
576
  up = PTR (u);
99
576
  vp = PTR (v);
100
576
  wp = PTR (w);
101
102
  /* Ensure W has space enough to store the result.  */
103
576
  wsize = usize + vsize;
104
576
  if (ALLOC (w) < wsize)
105
576
    {
106
576
      if (ALLOC (w) != 0)
107
187
  {
108
187
    if (wp == up || wp == vp)
109
187
      {
110
187
        free_me = wp;
111
187
        free_me_size = ALLOC (w);
112
187
      }
113
0
    else
114
0
      (*__gmp_free_func) (wp, (size_t) ALLOC (w) * GMP_LIMB_BYTES);
115
187
  }
116
117
576
      ALLOC (w) = wsize;
118
576
      wp = __GMP_ALLOCATE_FUNC_LIMBS (wsize);
119
576
      PTR (w) = wp;
120
576
    }
121
0
  else
122
0
    {
123
      /* Make U and V not overlap with W.  */
124
0
      if (wp == up)
125
0
  {
126
    /* W and U are identical.  Allocate temporary space for U.  */
127
0
    up = TMP_ALLOC_LIMBS (usize);
128
    /* Is V identical too?  Keep it identical with U.  */
129
0
    if (wp == vp)
130
0
      vp = up;
131
    /* Copy to the temporary space.  */
132
0
    MPN_COPY (up, wp, usize);
133
0
  }
134
0
      else if (wp == vp)
135
0
  {
136
    /* W and V are identical.  Allocate temporary space for V.  */
137
0
    vp = TMP_ALLOC_LIMBS (vsize);
138
    /* Copy to the temporary space.  */
139
0
    MPN_COPY (vp, wp, vsize);
140
0
  }
141
0
    }
142
143
576
  if (up == vp)
144
389
    {
145
389
      mpn_sqr (wp, up, usize);
146
389
      cy_limb = wp[wsize - 1];
147
389
    }
148
187
  else
149
187
    {
150
187
      cy_limb = mpn_mul (wp, up, usize, vp, vsize);
151
187
    }
152
153
576
  wsize -= cy_limb == 0;
154
155
576
  SIZ (w) = sign_product < 0 ? -wsize : wsize;
156
576
  if (free_me != NULL)
157
187
    (*__gmp_free_func) (free_me, free_me_size * GMP_LIMB_BYTES);
158
576
  TMP_FREE;
159
576
}