Processing math: 100%
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

answered 1 year ago

dan_fulea gravatar image

If we start with an integer n>0 with known (or computable) factorization n=pPpr(p), for some finite set of primes P, each prime being one modulo 4, and corresponding powers function pr(p), then the algorithm to go straightforward to the result is as follows. Write each p as a product (a+ib)(aib) of two primes in R=Z[i], 0<ab. If p=2 the representation is (1+i)(1i), and the factors are associated. Else the two factors are different primes. Now from each pr(p) prime power factorization in Z we take the corresponding factorization in Z, (a+ib)r(p)(aib)r(p), and distribute it in all (r(p), p2) possibilities in two conjugated factors e(p),f(p) of same norm, pr(p)=e(p)f(p), e(p)=A+iB, f(p)=¯e(p)=AiB.

We obtain numerous factorizations e(p)f(p) , and writing e(p)=S+iT, f(p)=SiT the two numbers are relatively prime iff each choice pr(p)=e(p)f(p) has relatively prime factors e(p),f(p). So we have in essence only two choices for e(p), either (a+ib)r(p), or (a-ib)^r(p)$.

The algorithm is thus to start with an n, collect all prime powers, represent them as product of powers over Z[i], build for each p the factor e(p) in two ways for p2, compute e(p)=S+iT, then S2+T2=n. Among the many generated solutions only the half is needed in case there is a prime p2 in P, because the choices e(p)=S+iT, and e(p)=SiT, with e=ˉe lead to the same solution. So for the first prime p2 we make one choice.

def reps(n):
    """Searching for all different representations n = S² + T², where n > 0 is an integer
    """
    sols = []    # and we append solutions sol one by one when found
    first_prime, choices, R = True, [], GaussianIntegers()

    for p, mul in factor(n):
        if p == 2:
            choices.append( [(1 + i)^mul] )
        elif p % 4 != 1:
            return []            
        else:
            pp = R(p).factor()[0][0]    # first factor of p seen in ZZ[i]
            if first_prime:
                first_prime = False
                choices.append( [pp^mul] )
            else:
                choices.append( [pp^mul, pp.conjugate()^mul] )
    for choice in cartesian_product(choices):
        S, T = R(prod(choice))
        S, T = abs(S), abs(T)
        if S > T:    S, T = T, S
        sols.append((S, T))
    sols.sort()
    return sols

Then with the above code:

sage: N = 10^40 + 1
sage: reps(N)
[(1, 100000000000000000000),
 (19999999800000001, 99999998000000020000),
 (21175073018521651199, 97732370700092384320),
 (21194619068964748801, 97728133730883635680),
 (27288575518388109025, 96204644618527795624),
 (47041175529588244705, 88244704117552958824),
 (47058823529411764705, 88235294117647058824),
 (64675591816386108385, 76269704491365444424)]
sage: factor(N)
17 * 5070721 * 5882353 * 19721061166646717498359681

An other check:

sage: N = 2^90 + 1
sage: factor(N)
5^2 * 13 * 37 * 41 * 61 * 109 * 181 * 1321 * 54001 * 29247661
sage: factor(len(reps(N)))
2^9

And we have all 29 expected representation, the corresponding list of solutions is of course not shown. One more check:

sage: reps(5^20 * 13^20 * 17^20)
[(1120228314932443982452255202016, 2472109092323644501221860856287),
 (1222652640782476248129183940513, 2423087980638188359909730969616),
 (1808156181728664217638411829584, 2024056833293480968965675605087),
 (1891237057569836360342883758113, 1946652828318445656133130477184)]

sage: factor(1120228314932443982452255202016^2 + 2472109092323644501221860856287^2)
5^20 * 13^20 * 17^20