Apologies for OT, but this might be of interest.

>From our preprint [1].

> We got plausible algorithm and strong numerical evidence
that integers of the form $n=(x^D+a_{D-2}x^{D-2}+\cdots a_0)
(y^D+b_{D-2}y^{D-2}+\cdots b_0)$ with $x,y$ of the same size
and $C=\max\{a_i,b_i\}$ and $a_i \ge 0,b_i \ge 0$ can be factored in
$O(\mathrm{polynomial}(C \log(n)))$. A special case for $D>1$ is
$n=(x^D+1)(y^D+1)$ We tested thousands of testcases without failure.

1. Is this correct?
2. Is this known?
3. Can it be improved?

Example session:

Kx.<x,y>=QQ[]

B=2**400;f1=x^4+5*x^2+1;f2=y^4+14*y^2+2;x0,y0=[randint(B,2*B) for _ in
(1,2)];n=f1(x0,0)*f2(0,y0)
%time ss=guninski_fg(n,f1,f2,L=None,allsols=False,prot=1) #Wall time: 71.5 ms
print("log(sol,2)=",RR(ss[0]).log(2)) #log(sol,2)= 1602.01840756461

[1] 
https://www.researchgate.net/publication/395877507_On_factoring_integers_of_the_form_n_x_D_1y_D_1_and_n_x_D_a_D-2_x_D-2_a_0_y_D_b_D-2_y_D-2_b_0_with_x_y_of_the_same_size

-- 
You received this message because you are subscribed to the Google Groups 
"sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/sage-devel/CAGUWgD8ja0byswRDTOK21oiLz5qnT_3qzj%3D99Q8rcBkRMg%2BFsA%40mail.gmail.com.
"""

Code for the paper: 

On factoring integers of the form $n=(x^D+1)(y^D+1)$ and 
$n=(x^D+a_{D-2}x^{D-2}++ a_0) (y^D+b_{D-2}y^{D-2}+ b_0)$ with $x,y$ of the same 
size

https://www.researchgate.net/publication/395877507_On_factoring_integers_of_the_form_n_x_D_1y_D_1_and_n_x_D_a_D-2_x_D-2_a_0_y_D_b_D-2_y_D-2_b_0_with_x_y_of_the_same_size



"""

def guninski_fg(n,f,g,L=None,prot=False,allsols=False):
        """
        n: integer to be factor, L:  bound

        f=x^D+O(x^(D-2)),g=y^D+O(y^D-1), x ~ y <=> 
floor(log(x_0))=floor(log(y_0))
        n=f(x_0)*g(y_0)

        C is maximum coefficient of f,g and it must be small for efficiency

        the coefficient a_i of f and b_i of g must be nonnegative

        complexity including failure:  O(C log_2(n)  univariate polynomial 
factorizations over the integres)
        returns list of factors of n or empty on failure

        usage:

        Kx.<x,y>=QQ[]
        
        B=2**400;f1=x^4+5*x^2+1;f2=y^4+14*y^2+2;x0,y0=[randint(B,2*B) for _ in 
(1,2)];n=f1(x0,0)*f2(0,y0)
        %time ss=guninski_fg(n,f1,f2,L=None,allsols=False,prot=1)
        print("log(sol,2)=",RR(ss[0]).log(2))

        author:  Georgi Guninski Wed Sep 24 02:55:02 PM UTC 2025
        """
        sols=[]
        X,Y=f.parent().gens()
        KX=QQ[str(X)]
        D=f.degree()
        assert D==g.degree(),"g.degree() != f.degree()"
        assert f.coefficient({X:D-1})==0,"X^(D-1) != 0"
        assert g.coefficient({Y:D-1})==0,"Y^(D-1) != 0"
        C=max([i for i,j in f])
        C=max([C]+[i for i,j in g])
        if L is None:  L=floor(C*log(n,2))
        if prot:  print("L=",L," log_2(L)",floor(log(L,2)))
        F=f*g-n
        t=floor(AA(n)**(1/QQ(D)))
        for r_0 in range(L):
                Y1=(t-r_0)/X
                F2=F.subs({Y:Y1})
                F2=KX(numerator(F2))
                ro=F2.roots(multiplicities=False)
                ro=[ZZ(i) for i in ro if denominator(i)==1]
                sol=[gcd(f(i,0),n)%n for i in ro if gcd(f(i,0),n)%n>1]
                if not sol:  continue
                if prot:  print("Solution at 
ro=",r_0,"log_2(g)=",[floor(RR(i).log(2)) for i in sol])
                sols += sol
                sols=list(set(sorted(sols)))
                if not allsols:  break
        return sols

def getpolydm2(D,C,X,D2=2):
        # for guninski_factor_fg
        return X**D+sum(X**i * randint(0,C) for i in range(D-D2+1))

def benchmark_fg(lim,D=3,BC=10,B=2**200,D2=2):
        bad=0
        badss=0
        Kx.<x,y>=QQ[]
        i0=0
        badl=[]
        while i0 < lim:
                f1=getpolydm2(D,BC,x,D2=D2)
                f2=getpolydm2(D,BC,y,D2=D2)
                x0=randint(B,4*B)
                y0=randint(B,4*B)
                #print(f1,f2)
                p1=f1(x0,y0)
                p2=f2(x0,y0)
                #if gcd(p1,p2) != 1:  continue
                i0 += 1
                n=p1*p2
                ss=guninski_fg(n,f1,f2,L=None,allsols=False,prot=True)
                goo=any([gcd(i,n)%n for i in ss if gcd(n,i)%n>1])
                
                if not goo:  
                        bad += 1
                        badl += [(n,D,f1,f2,x0,y0)]
                if not ss:  badss += 1
                print(i0,'bad=',bad,badss,goo)
                
        return bad,badl

Reply via email to