Coverage Report

Created: 2024-11-25 06:27

/src/gmp/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
1.72k
{
39
1.72k
  mp_size_t usize;
40
1.72k
  mp_size_t vsize;
41
1.72k
  mp_size_t wsize;
42
1.72k
  mp_size_t sign_product;
43
1.72k
  mp_ptr up, vp;
44
1.72k
  mp_ptr wp;
45
1.72k
  mp_ptr free_me;
46
1.72k
  size_t free_me_size;
47
1.72k
  mp_limb_t cy_limb;
48
1.72k
  TMP_DECL;
49
50
1.72k
  usize = SIZ (u);
51
1.72k
  vsize = SIZ (v);
52
1.72k
  sign_product = usize ^ vsize;
53
1.72k
  usize = ABS (usize);
54
1.72k
  vsize = ABS (vsize);
55
56
1.72k
  if (usize < vsize)
57
0
    {
58
0
      MPZ_SRCPTR_SWAP (u, v);
59
0
      MP_SIZE_T_SWAP (usize, vsize);
60
0
    }
61
62
1.72k
  if (vsize == 0)
63
9
    {
64
9
      SIZ (w) = 0;
65
9
      return;
66
9
    }
67
68
#if HAVE_NATIVE_mpn_mul_2
69
  if (vsize <= 2)
70
    {
71
      wp = MPZ_REALLOC (w, usize+vsize);
72
      if (vsize == 1)
73
  cy_limb = mpn_mul_1 (wp, PTR (u), usize, PTR (v)[0]);
74
      else
75
  {
76
    cy_limb = mpn_mul_2 (wp, PTR (u), usize, PTR (v));
77
    usize++;
78
  }
79
      wp[usize] = cy_limb;
80
      usize += (cy_limb != 0);
81
      SIZ (w) = (sign_product >= 0 ? usize : -usize);
82
      return;
83
    }
84
#else
85
1.71k
  if (vsize == 1)
86
186
    {
87
186
      wp = MPZ_REALLOC (w, usize+1);
88
186
      cy_limb = mpn_mul_1 (wp, PTR (u), usize, PTR (v)[0]);
89
186
      wp[usize] = cy_limb;
90
186
      usize += (cy_limb != 0);
91
186
      SIZ (w) = (sign_product >= 0 ? usize : -usize);
92
186
      return;
93
186
    }
94
1.52k
#endif
95
96
1.52k
  TMP_MARK;
97
1.52k
  free_me = NULL;
98
1.52k
  up = PTR (u);
99
1.52k
  vp = PTR (v);
100
1.52k
  wp = PTR (w);
101
102
  /* Ensure W has space enough to store the result.  */
103
1.52k
  wsize = usize + vsize;
104
1.52k
  if (ALLOC (w) < wsize)
105
1.52k
    {
106
1.52k
      if (ALLOC (w) != 0)
107
480
  {
108
480
    if (wp == up || wp == vp)
109
480
      {
110
480
        free_me = wp;
111
480
        free_me_size = ALLOC (w);
112
480
      }
113
0
    else
114
0
      (*__gmp_free_func) (wp, (size_t) ALLOC (w) * GMP_LIMB_BYTES);
115
480
  }
116
117
1.52k
      ALLOC (w) = wsize;
118
1.52k
      wp = __GMP_ALLOCATE_FUNC_LIMBS (wsize);
119
1.52k
      PTR (w) = wp;
120
1.52k
    }
121
1
  else
122
1
    {
123
      /* Make U and V not overlap with W.  */
124
1
      if (wp == up)
125
1
  {
126
    /* W and U are identical.  Allocate temporary space for U.  */
127
1
    up = TMP_ALLOC_LIMBS (usize);
128
    /* Is V identical too?  Keep it identical with U.  */
129
1
    if (wp == vp)
130
0
      vp = up;
131
    /* Copy to the temporary space.  */
132
1
    MPN_COPY (up, wp, usize);
133
1
  }
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
1
    }
142
143
1.52k
  if (up == vp)
144
1.04k
    {
145
1.04k
      mpn_sqr (wp, up, usize);
146
1.04k
      cy_limb = wp[wsize - 1];
147
1.04k
    }
148
481
  else
149
481
    {
150
481
      cy_limb = mpn_mul (wp, up, usize, vp, vsize);
151
481
    }
152
153
1.52k
  wsize -= cy_limb == 0;
154
155
1.52k
  SIZ (w) = sign_product < 0 ? -wsize : wsize;
156
1.52k
  if (free_me != NULL)
157
480
    (*__gmp_free_func) (free_me, free_me_size * GMP_LIMB_BYTES);
158
1.52k
  TMP_FREE;
159
1.52k
}