1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
Copyright (C) 2009 William Hart
Copyright (C) 2018 Daniel Schultz
Copyright (C) 2023 Fredrik Johansson
This file is part of FLINT.
FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version. See <https://www.gnu.org/licenses/>.
*/
#include "gmpcompat.h"
#include "ulong_extras.h"
#include "fmpz.h"
void
fmpz_pow_ui(fmpz_t f, const fmpz_t g, ulong exp)
{
fmpz c1;
if (exp == WORD(0))
{
fmpz_one(f);
return;
}
c1 = *g;
if (!COEFF_IS_MPZ(c1)) /* g is small */
{
ulong u1 = FLINT_ABS(c1);
ulong bits = FLINT_BIT_COUNT(u1);
if (u1 <= UWORD(1))
{
fmpz_set_ui(f, u1);
}
else if (exp * bits <= SMALL_FMPZ_BITCOUNT_MAX)
{
fmpz_set_ui(f, n_pow(u1, exp));
}
else
{
mpz_ptr mf = _fmpz_promote_val(f);
flint_mpz_set_ui(mf, u1);
flint_mpz_pow_ui(mf, mf, exp);
_fmpz_demote_val(f); /* may actually fit into a small after all */
}
if ((c1 < WORD(0)) && (exp & 1)) /* sign is -ve if exp odd and g -ve */
fmpz_neg(f, f);
}
else
{
mpz_ptr mf = _fmpz_promote_val(f);
flint_mpz_pow_ui(mf, COEFF_TO_PTR(c1), exp);
/* no need to demote as it can't get smaller */
}
}
int fmpz_pow_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t e)
{
int e_sgn = fmpz_sgn(e);
if (e_sgn < 0)
{
flint_throw(FLINT_ERROR, "Negative exponent in fmpz_pow_fmpz");
}
else if (e_sgn == 0)
{
fmpz_one(a);
}
else if (fmpz_is_zero(b))
{
fmpz_zero(a);
}
else if (fmpz_is_pm1(b))
{
fmpz_set_si(a, fmpz_is_one(b) || fmpz_is_even(e) ? 1 : -1);
}
else
{
if (!fmpz_fits_si(e))
return 0;
fmpz_pow_ui(a, b, fmpz_get_si(e));
}
return 1;
}
void
fmpz_ui_pow_ui(fmpz_t x, ulong b, ulong e)
{
if (e <= 1)
{
fmpz_set_ui(x, e == 0 ? 1 : b);
}
else if (e == 2)
{
ulong t[2];
umul_ppmm(t[1], t[0], b, b);
fmpz_set_uiui(x, t[1], t[0]);
}
else if (b <= 1)
{
fmpz_set_ui(x, b);
}
else
{
ulong bits = FLINT_BIT_COUNT(b);
if (e * bits <= FLINT_BITS)
{
fmpz_set_ui(x, n_pow(b, e));
}
else
{
mpz_ptr z = _fmpz_promote(x);
flint_mpz_set_ui(z, b);
flint_mpz_pow_ui(z, z, e);
_fmpz_demote_val(x);
}
}
}