Coverage Report

Created: 2024-11-21 07:00

/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
1.42k
{
39
1.42k
  mp_size_t usize;
40
1.42k
  mp_size_t vsize;
41
1.42k
  mp_size_t wsize;
42
1.42k
  mp_size_t sign_product;
43
1.42k
  mp_ptr up, vp;
44
1.42k
  mp_ptr wp;
45
1.42k
  mp_ptr free_me;
46
1.42k
  size_t free_me_size;
47
1.42k
  mp_limb_t cy_limb;
48
1.42k
  TMP_DECL;
49
50
1.42k
  usize = SIZ (u);
51
1.42k
  vsize = SIZ (v);
52
1.42k
  sign_product = usize ^ vsize;
53
1.42k
  usize = ABS (usize);
54
1.42k
  vsize = ABS (vsize);
55
56
1.42k
  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.42k
  if (vsize == 0)
63
72
    {
64
72
      SIZ (w) = 0;
65
72
      return;
66
72
    }
67
68
1.35k
#if HAVE_NATIVE_mpn_mul_2
69
1.35k
  if (vsize <= 2)
70
187
    {
71
187
      wp = MPZ_REALLOC (w, usize+vsize);
72
187
      if (vsize == 1)
73
116
  cy_limb = mpn_mul_1 (wp, PTR (u), usize, PTR (v)[0]);
74
71
      else
75
71
  {
76
71
    cy_limb = mpn_mul_2 (wp, PTR (u), usize, PTR (v));
77
71
    usize++;
78
71
  }
79
187
      wp[usize] = cy_limb;
80
187
      usize += (cy_limb != 0);
81
187
      SIZ (w) = (sign_product >= 0 ? usize : -usize);
82
187
      return;
83
187
    }
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
1.16k
  TMP_MARK;
97
1.16k
  free_me = NULL;
98
1.16k
  up = PTR (u);
99
1.16k
  vp = PTR (v);
100
1.16k
  wp = PTR (w);
101
102
  /* Ensure W has space enough to store the result.  */
103
1.16k
  wsize = usize + vsize;
104
1.16k
  if (ALLOC (w) < wsize)
105
1.16k
    {
106
1.16k
      if (ALLOC (w) != 0)
107
387
  {
108
387
    if (wp == up || wp == vp)
109
387
      {
110
387
        free_me = wp;
111
387
        free_me_size = ALLOC (w);
112
387
      }
113
0
    else
114
0
      (*__gmp_free_func) (wp, (size_t) ALLOC (w) * GMP_LIMB_BYTES);
115
387
  }
116
117
1.16k
      ALLOC (w) = wsize;
118
1.16k
      wp = __GMP_ALLOCATE_FUNC_LIMBS (wsize);
119
1.16k
      PTR (w) = wp;
120
1.16k
    }
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
1.16k
  if (up == vp)
144
776
    {
145
776
      mpn_sqr (wp, up, usize);
146
776
      cy_limb = wp[wsize - 1];
147
776
    }
148
387
  else
149
387
    {
150
387
      cy_limb = mpn_mul (wp, up, usize, vp, vsize);
151
387
    }
152
153
1.16k
  wsize -= cy_limb == 0;
154
155
1.16k
  SIZ (w) = sign_product < 0 ? -wsize : wsize;
156
1.16k
  if (free_me != NULL)
157
387
    (*__gmp_free_func) (free_me, free_me_size * GMP_LIMB_BYTES);
158
1.16k
  TMP_FREE;
159
1.16k
}