Line | Count | Source (jump to first uncovered line) |
1 | | /* mpz_setbit -- set a specified bit. |
2 | | |
3 | | Copyright 1991, 1993-1995, 1997, 1999, 2001, 2002, 2012 Free Software |
4 | | 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 "gmp-impl.h" |
33 | | |
34 | | void |
35 | | mpz_setbit (mpz_ptr d, mp_bitcnt_t bit_idx) |
36 | 0 | { |
37 | 0 | mp_size_t dsize = SIZ (d); |
38 | 0 | mp_ptr dp = PTR (d); |
39 | 0 | mp_size_t limb_idx; |
40 | 0 | mp_limb_t mask; |
41 | |
|
42 | 0 | limb_idx = bit_idx / GMP_NUMB_BITS; |
43 | 0 | mask = CNST_LIMB(1) << (bit_idx % GMP_NUMB_BITS); |
44 | 0 | if (dsize >= 0) |
45 | 0 | { |
46 | 0 | if (limb_idx < dsize) |
47 | 0 | { |
48 | 0 | dp[limb_idx] |= mask; |
49 | 0 | } |
50 | 0 | else |
51 | 0 | { |
52 | | /* Ugh. The bit should be set outside of the end of the |
53 | | number. We have to increase the size of the number. */ |
54 | 0 | dp = MPZ_REALLOC (d, limb_idx + 1); |
55 | 0 | SIZ (d) = limb_idx + 1; |
56 | 0 | MPN_ZERO (dp + dsize, limb_idx - dsize); |
57 | 0 | dp[limb_idx] = mask; |
58 | 0 | } |
59 | 0 | } |
60 | 0 | else |
61 | 0 | { |
62 | | /* Simulate two's complement arithmetic, i.e. simulate |
63 | | 1. Set OP = ~(OP - 1) [with infinitely many leading ones]. |
64 | | 2. Set the bit. |
65 | | 3. Set OP = ~OP + 1. */ |
66 | |
|
67 | 0 | dsize = -dsize; |
68 | |
|
69 | 0 | if (limb_idx < dsize) |
70 | 0 | { |
71 | 0 | mp_size_t zero_bound; |
72 | | /* No index upper bound on this loop, we're sure there's a non-zero limb |
73 | | sooner or later. */ |
74 | 0 | zero_bound = 0; |
75 | 0 | while (dp[zero_bound] == 0) |
76 | 0 | zero_bound++; |
77 | |
|
78 | 0 | if (limb_idx > zero_bound) |
79 | 0 | { |
80 | 0 | mp_limb_t dlimb; |
81 | 0 | dlimb = dp[limb_idx] & ~mask; |
82 | 0 | dp[limb_idx] = dlimb; |
83 | |
|
84 | 0 | if (UNLIKELY ((dlimb == 0) + limb_idx == dsize)) /* dsize == limb_idx + 1 */ |
85 | 0 | { |
86 | | /* high limb became zero, must normalize */ |
87 | 0 | MPN_NORMALIZE (dp, limb_idx); |
88 | 0 | SIZ (d) = -limb_idx; |
89 | 0 | } |
90 | 0 | } |
91 | 0 | else if (limb_idx == zero_bound) |
92 | 0 | { |
93 | 0 | dp[limb_idx] = ((dp[limb_idx] - 1) & ~mask) + 1; |
94 | 0 | ASSERT (dp[limb_idx] != 0); |
95 | 0 | } |
96 | 0 | else |
97 | 0 | { |
98 | 0 | MPN_DECR_U (dp + limb_idx, dsize - limb_idx, mask); |
99 | 0 | dsize -= dp[dsize - 1] == 0; |
100 | 0 | SIZ (d) = -dsize; |
101 | 0 | } |
102 | 0 | } |
103 | 0 | } |
104 | 0 | } |