8 | | Here is the code I propose: |
9 | | |
10 | | |
11 | | {{{#!python |
12 | | r""" |
13 | | sigma_gauss function (sum of divisors) applicable to a Gaussian integer. |
14 | | |
15 | | This function is an extension of the sigma function in number theory to Gaussian integers. |
16 | | |
17 | | |
18 | | INPUT: |
19 | | |
20 | | ''z'' -- GaussianInteger |
21 | | |
22 | | OUTPUT: |
23 | | |
24 | | ''sigma_gauss(z)'' -- GaussianInteger, the sum of the Gaussian integer divisors of z |
25 | | |
26 | | Caution: The Gaussian integer prime factors are only taken in the first quadrant, |
27 | | see why in the references below. |
28 | | |
29 | | EXAMPLES: |
30 | | |
31 | | The sum of the divisors of Gauss integers z = 2*I + 2, z = 3*I + 2, z = 13:: |
32 | | |
33 | | sage: sigma_gauss(2*I + 2) |
34 | | 5*I |
35 | | sage: sigma_gauss(3*I + 2) |
36 | | 3*I + 3 |
37 | | sage: sigma_gauss(5) |
38 | | 8*I + 4 |
39 | | |
40 | | AUTHORS: |
41 | | |
42 | | Paul Zimmermann and Jean-Luc Garambois (2019): initial version |
43 | | |
44 | | REFERENCES: |
45 | | |
46 | | [1] http://mathworld.wolfram.com/DivisorFunction.html |
47 | | Equivalent on the Mathematica software to DivisorSigma [1, z, GaussianIntegers -> True] |
48 | | [2] https://www.jstor.org/stable/2312472?seq=1 |
49 | | [3] https://encompass.eku.edu/etd/158/ |
50 | | """ |
51 | | # **************************************************************************** |
52 | | # Copyright (C) 2019 Jean-Luc Garambois <jlgarambois@gmail.com> |
53 | | # |
54 | | # This program is free software: you can redistribute it and/or modify |
55 | | # it under the terms of the GNU General Public License as published by |
56 | | # the Free Software Foundation, either version 2 of the License, or |
57 | | # (at your option) any later version. |
58 | | # https://www.gnu.org/licenses/ |
59 | | # **************************************************************************** |
60 | | |
61 | | from sage.functions.other import real, imag |
62 | | from sage.rings.number_field.order import GaussianIntegers |
63 | | |
64 | | R = GaussianIntegers() |
65 | | |
66 | | def sigma_gauss_aux (l): |
67 | | s = 1 |
68 | | e = 0 |
69 | | while e < len(l): |
70 | | p = l[e][0] |
71 | | k = l[e][1] |
72 | | s = s * (p**(k+1) - 1) / (p-1) |
73 | | e = e + 1 |
74 | | return R(s) |
75 | | |
76 | | def sigma_gauss(z): |
77 | | ll = list(R(z).factor()) |
78 | | l = [] |
79 | | i = 0 |
80 | | |
81 | | # **************************************************************************** |
82 | | # Gaussian prime factors must be selected in the first quadrant. |
83 | | # **************************************************************************** |
84 | | |
85 | | while i < len(ll): |
86 | | nz = ll[i][0] |
87 | | if real(nz) < 0 and imag(nz) < 0: |
88 | | nz = -nz |
89 | | if real(nz) < 0 and imag(nz) >= 0: |
90 | | nz = -I * nz |
91 | | if real(nz) >= 0 and imag(nz) < 0: |
92 | | nz = I * nz |
93 | | assert real(nz) >= 0 and imag(nz) >= 0 |
94 | | lz = [nz, ll[i][1]] |
95 | | l.append(lz) |
96 | | i = i + 1 |
97 | | r = 0 |
98 | | |
99 | | # **************************************************************************** |
100 | | # Be careful not to have the same factor twice after their selection |
101 | | # in the first quadrant and before applying the "sigma_gauss_aux" function. |
102 | | # **************************************************************************** |
103 | | |
104 | | while r < len(l) - 1: |
105 | | t = r + 1 |
106 | | while t < len(l): |
107 | | if l[r][0] == l[t][0]: |
108 | | l[r][1] = l[r][1] + l[t][1] |
109 | | del l[t] |
110 | | t = t - 1 |
111 | | t = t + 1 |
112 | | r= r + 1 |
113 | | for x, e in l: |
114 | | assert e != 0 |
115 | | return sigma_gauss_aux(l) |
116 | | }}} |