@@ -3320,16 +3320,52 @@ def _all_polys_mpolys():
33203320def test_factor_poly_mpoly ():
33213321 """Test that factor() is consistent across different poly/mpoly types."""
33223322
3323- def factor ( p ):
3324- coeff , factors = p . factor ()
3323+ def check ( p , coeff , factors ):
3324+ # Check all the types
33253325 lc = p .leading_coefficient ()
33263326 assert type (coeff ) is type (lc )
33273327 assert isinstance (factors , list )
33283328 assert all (isinstance (f , tuple ) for f in factors )
33293329 for fac , m in factors :
33303330 assert type (fac ) is type (p )
33313331 assert type (m ) is int
3332- return coeff , sorted (factors , key = lambda p : (p [1 ], str (p [0 ])))
3332+
3333+ # Check the actual factorisation!
3334+ res = coeff
3335+ for fac , m in factors :
3336+ res *= fac ** m
3337+ assert res == p
3338+
3339+ def sort (factors ):
3340+ def sort_key (p ):
3341+ fac , m = p
3342+ return (m , sorted (str (i ) for i in fac .coeffs ()))
3343+ return sorted (factors , key = sort_key )
3344+
3345+ def factor (p ):
3346+ coeff , factors = p .factor ()
3347+ check (p , coeff , factors )
3348+ return coeff , sort (factors )
3349+
3350+ def factor_sqf (p ):
3351+ coeff , factors = p .factor_squarefree ()
3352+ check (p , coeff , factors )
3353+ return coeff , sort (factors )
3354+
3355+ def sqrt (a ):
3356+ if type (x ) is flint .fq_default_poly :
3357+ try :
3358+ return S (a ).sqrt ()
3359+ except ValueError :
3360+ return None
3361+ elif characteristic != 0 :
3362+ # XXX: fmpz(0).sqrtmod crashes
3363+ try :
3364+ return flint .fmpz (- 1 ).sqrtmod (characteristic )
3365+ except ValueError :
3366+ return None
3367+ else :
3368+ return None
33333369
33343370 for P , S , [x , y ], is_field , characteristic in _all_polys_mpolys ():
33353371
@@ -3351,9 +3387,40 @@ def factor(p):
33513387 assert factor (x ) == (S (1 ), [(x , 1 )])
33523388 assert factor (- x ) == (S (- 1 ), [(x , 1 )])
33533389 assert factor (x ** 2 ) == (S (1 ), [(x , 2 )])
3354- assert factor (x * (x + 1 )) == (S (1 ), [(x , 1 ), (x + 1 , 1 )])
33553390 assert factor (2 * (x + 1 )) == (S (2 ), [(x + 1 , 1 )])
33563391
3392+ assert factor_sqf (0 * x ) == (S (0 ), [])
3393+ assert factor_sqf (0 * x + 1 ) == (S (1 ), [])
3394+ assert factor_sqf (0 * x + 3 ) == (S (3 ), [])
3395+ assert factor_sqf (- x ) == (S (- 1 ), [(x , 1 )])
3396+ assert factor_sqf (x ** 2 ) == (S (1 ), [(x , 2 )])
3397+ assert factor_sqf (2 * (x + 1 )) == (S (2 ), [(x + 1 , 1 )])
3398+
3399+ assert factor (x * (x + 1 )) == (S (1 ), [(x , 1 ), (x + 1 , 1 )])
3400+ if y is None :
3401+ assert factor_sqf (x * (x + 1 )) == (S (1 ), [(x ** 2 + x , 1 )])
3402+ else :
3403+ # mpoly types have a different squarefree factorisation because
3404+ # they handle trivial factors differently...
3405+ #
3406+ # Maybe it is worth making them consistent by absorbing the power
3407+ # of x into a factor of equal multiplicity.
3408+ assert factor_sqf (x * (x + 1 )) == (S (1 ), [(x , 1 ), (x + 1 , 1 )])
3409+
3410+ assert factor_sqf (x ** 2 * (x + 1 )) == (S (1 ), [(x + 1 , 1 ), (x , 2 )])
3411+
3412+ assert factor ((x - 1 )* (x + 1 )) == (S (1 ), sort ([(x - 1 , 1 ), (x + 1 , 1 )]))
3413+ assert factor_sqf ((x - 1 )* (x + 1 )) == (S (1 ), [(x ** 2 - 1 , 1 )])
3414+
3415+ p = 3 * (x - 1 )** 2 * (x + 1 )** 2 * (x ** 2 + 1 )** 3
3416+ assert factor_sqf (p ) == (S (3 ), [(x ** 2 - 1 , 2 ), (x ** 2 + 1 , 3 )])
3417+
3418+ i = sqrt (- 1 )
3419+ if i is not None :
3420+ assert factor (p ) == (S (3 ), sort ([(x + 1 , 2 ), (x - 1 , 2 ), (x + i , 3 ), (x - i , 3 )]))
3421+ else :
3422+ assert factor (p ) == (S (3 ), sort ([(x - 1 , 2 ), (x + 1 , 2 ), (x ** 2 + 1 , 3 )]))
3423+
33573424 if characteristic == 0 :
33583425 # primitive factors over Z for Z and Q.
33593426 assert factor (2 * x + 1 ) == (S (1 ), [(2 * x + 1 , 1 )])
@@ -3372,16 +3439,20 @@ def factor(p):
33723439 assert factor (x * y + 1 ) == (S (1 ), [(x * y + 1 , 1 )])
33733440 assert factor (x * y ) == (S (1 ), [(x , 1 ), (y , 1 )])
33743441
3442+ assert factor_sqf ((x * y + 1 )** 2 * (x * y - 1 )) == (S (1 ), [(x * y - 1 , 1 ), (x * y + 1 , 2 )])
3443+
3444+ p = 2 * x + y
33753445 if characteristic == 0 :
3376- assert factor (2 * x + y ) == (S (1 ), [(2 * x + y , 1 )])
3446+ assert factor (p ) == factor_sqf ( p ) == (S (1 ), [(p , 1 )])
33773447 else :
3378- assert factor (2 * x + y ) == (S (2 ), [(x + y / 2 , 1 )])
3448+ assert factor (p ) == factor_sqf ( p ) == (S (2 ), [(p / 2 , 1 )])
33793449
33803450 if is_field :
3451+ p = (2 * x + y )/ 7
33813452 if characteristic == 0 :
3382- assert factor (( 2 * x + y ) / 7 ) == (S (1 )/ 7 , [(2 * x + y , 1 )])
3453+ assert factor (p ) == factor_sqf ( p ) == (S (1 )/ 7 , [(7 * p , 1 )])
33833454 else :
3384- assert factor (( 2 * x + y ) / 7 ) == (S (2 )/ 7 , [(x + y / 2 , 1 )])
3455+ assert factor (p ) == factor_sqf ( p ) == (S (2 )/ 7 , [(7 * p / 2 , 1 )])
33853456
33863457
33873458def _all_matrices ():
0 commit comments