Coverage Report

Created: 2024-11-25 06:31

/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
987
{
39
987
  mp_size_t usize;
40
987
  mp_size_t vsize;
41
987
  mp_size_t wsize;
42
987
  mp_size_t sign_product;
43
987
  mp_ptr up, vp;
44
987
  mp_ptr wp;
45
987
  mp_ptr free_me;
46
987
  size_t free_me_size;
47
987
  mp_limb_t cy_limb;
48
987
  TMP_DECL;
49
50
987
  usize = SIZ (u);
51
987
  vsize = SIZ (v);
52
987
  sign_product = usize ^ vsize;
53
987
  usize = ABS (usize);
54
987
  vsize = ABS (vsize);
55
56
987
  if (usize < vsize)
57
0
    {
58
0
      MPZ_SRCPTR_SWAP (u, v);
59
0
      MP_SIZE_T_SWAP (usize, vsize);
60
0
    }
61
62
987
  if (vsize == 0)
63
11
    {
64
11
      SIZ (w) = 0;
65
11
      return;
66
11
    }
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
976
  if (vsize == 1)
86
243
    {
87
243
      wp = MPZ_REALLOC (w, usize+1);
88
243
      cy_limb = mpn_mul_1 (wp, PTR (u), usize, PTR (v)[0]);
89
243
      wp[usize] = cy_limb;
90
243
      usize += (cy_limb != 0);
91
243
      SIZ (w) = (sign_product >= 0 ? usize : -usize);
92
243
      return;
93
243
    }
94
733
#endif
95
96
733
  TMP_MARK;
97
733
  free_me = NULL;
98
733
  up = PTR (u);
99
733
  vp = PTR (v);
100
733
  wp = PTR (w);
101
102
  /* Ensure W has space enough to store the result.  */
103
733
  wsize = usize + vsize;
104
733
  if (ALLOC (w) < wsize)
105
732
    {
106
732
      if (ALLOC (w) != 0)
107
209
  {
108
209
    if (wp == up || wp == vp)
109
209
      {
110
209
        free_me = wp;
111
209
        free_me_size = ALLOC (w);
112
209
      }
113
0
    else
114
0
      (*__gmp_free_func) (wp, (size_t) ALLOC (w) * GMP_LIMB_BYTES);
115
209
  }
116
117
732
      ALLOC (w) = wsize;
118
732
      wp = __GMP_ALLOCATE_FUNC_LIMBS (wsize);
119
732
      PTR (w) = wp;
120
732
    }
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
733
  if (up == vp)
144
523
    {
145
523
      mpn_sqr (wp, up, usize);
146
523
      cy_limb = wp[wsize - 1];
147
523
    }
148
210
  else
149
210
    {
150
210
      cy_limb = mpn_mul (wp, up, usize, vp, vsize);
151
210
    }
152
153
733
  wsize -= cy_limb == 0;
154
155
733
  SIZ (w) = sign_product < 0 ? -wsize : wsize;
156
733
  if (free_me != NULL)
157
209
    (*__gmp_free_func) (free_me, free_me_size * GMP_LIMB_BYTES);
158
733
  TMP_FREE;
159
733
}