Coverage Report

Created: 2025-03-09 06:52

/src/gmp-6.2.1/mpz/mul.c
Line
Count
Source
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
6.75M
{
39
6.75M
  mp_size_t usize;
40
6.75M
  mp_size_t vsize;
41
6.75M
  mp_size_t wsize;
42
6.75M
  mp_size_t sign_product;
43
6.75M
  mp_ptr up, vp;
44
6.75M
  mp_ptr wp;
45
6.75M
  mp_ptr free_me;
46
6.75M
  size_t free_me_size;
47
6.75M
  mp_limb_t cy_limb;
48
6.75M
  TMP_DECL;
49
50
6.75M
  usize = SIZ (u);
51
6.75M
  vsize = SIZ (v);
52
6.75M
  sign_product = usize ^ vsize;
53
6.75M
  usize = ABS (usize);
54
6.75M
  vsize = ABS (vsize);
55
56
6.75M
  if (usize < vsize)
57
650k
    {
58
650k
      MPZ_SRCPTR_SWAP (u, v);
59
650k
      MP_SIZE_T_SWAP (usize, vsize);
60
650k
    }
61
62
6.75M
  if (vsize == 0)
63
821
    {
64
821
      SIZ (w) = 0;
65
821
      return;
66
821
    }
67
68
6.75M
#if HAVE_NATIVE_mpn_mul_2
69
6.75M
  if (vsize <= 2)
70
4.42M
    {
71
4.42M
      wp = MPZ_REALLOC (w, usize+vsize);
72
4.42M
      if (vsize == 1)
73
4.41M
  cy_limb = mpn_mul_1 (wp, PTR (u), usize, PTR (v)[0]);
74
14.6k
      else
75
14.6k
  {
76
14.6k
    cy_limb = mpn_mul_2 (wp, PTR (u), usize, PTR (v));
77
14.6k
    usize++;
78
14.6k
  }
79
4.42M
      wp[usize] = cy_limb;
80
4.42M
      usize += (cy_limb != 0);
81
4.42M
      SIZ (w) = (sign_product >= 0 ? usize : -usize);
82
4.42M
      return;
83
4.42M
    }
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
2.33M
  TMP_MARK;
97
2.33M
  free_me = NULL;
98
2.33M
  up = PTR (u);
99
2.33M
  vp = PTR (v);
100
2.33M
  wp = PTR (w);
101
102
  /* Ensure W has space enough to store the result.  */
103
2.33M
  wsize = usize + vsize;
104
2.33M
  if (ALLOC (w) < wsize)
105
1.49M
    {
106
1.49M
      if (ALLOC (w) != 0)
107
1.49M
  {
108
1.49M
    if (wp == up || wp == vp)
109
1.48M
      {
110
1.48M
        free_me = wp;
111
1.48M
        free_me_size = ALLOC (w);
112
1.48M
      }
113
2.89k
    else
114
2.89k
      (*__gmp_free_func) (wp, (size_t) ALLOC (w) * GMP_LIMB_BYTES);
115
1.49M
  }
116
117
1.49M
      ALLOC (w) = wsize;
118
1.49M
      wp = __GMP_ALLOCATE_FUNC_LIMBS (wsize);
119
1.49M
      PTR (w) = wp;
120
1.49M
    }
121
838k
  else
122
838k
    {
123
      /* Make U and V not overlap with W.  */
124
838k
      if (wp == up)
125
15.4k
  {
126
    /* W and U are identical.  Allocate temporary space for U.  */
127
15.4k
    up = TMP_ALLOC_LIMBS (usize);
128
    /* Is V identical too?  Keep it identical with U.  */
129
15.4k
    if (wp == vp)
130
50
      vp = up;
131
    /* Copy to the temporary space.  */
132
15.4k
    MPN_COPY (up, wp, usize);
133
15.4k
  }
134
823k
      else if (wp == vp)
135
15.5k
  {
136
    /* W and V are identical.  Allocate temporary space for V.  */
137
15.5k
    vp = TMP_ALLOC_LIMBS (vsize);
138
    /* Copy to the temporary space.  */
139
15.5k
    MPN_COPY (vp, wp, vsize);
140
15.5k
  }
141
838k
    }
142
143
2.33M
  if (up == vp)
144
809k
    {
145
809k
      mpn_sqr (wp, up, usize);
146
809k
      cy_limb = wp[wsize - 1];
147
809k
    }
148
1.52M
  else
149
1.52M
    {
150
1.52M
      cy_limb = mpn_mul (wp, up, usize, vp, vsize);
151
1.52M
    }
152
153
2.33M
  wsize -= cy_limb == 0;
154
155
2.33M
  SIZ (w) = sign_product < 0 ? -wsize : wsize;
156
2.33M
  if (free_me != NULL)
157
1.48M
    (*__gmp_free_func) (free_me, free_me_size * GMP_LIMB_BYTES);
158
2.33M
  TMP_FREE;
159
2.33M
}