@@ -2782,6 +2782,12 @@ def _all_mpolys():
2782
2782
def test_mpolys ():
2783
2783
for P , get_context , S , is_field in _all_mpolys ():
2784
2784
2785
+ # Division under modulo will raise a flint exception if something is not invertible, crashing the program. We
2786
+ # can't tell before what is invertible and what is not before hand so we always raise an exception, except for
2787
+ # fmpz_mpoly, that returns an bool noting if the division is exact or not.
2788
+ division_not_supported = P is not flint .fmpz_mpoly and not is_field
2789
+ characteristic_zero = not (P is flint .fmpz_mod_mpoly or P is flint .nmod_mpoly )
2790
+
2785
2791
ctx = get_context (nvars = 2 )
2786
2792
2787
2793
assert raises (lambda : get_context (nvars = 2 , ordering = "bad" ), TypeError )
@@ -3045,7 +3051,7 @@ def quick_poly():
3045
3051
assert raises (lambda : quick_poly ().imul (P (ctx = ctx1 )), IncompatibleContextError )
3046
3052
assert raises (lambda : quick_poly ().imul (None ), NotImplementedError )
3047
3053
3048
- if ( P is flint . fmpz_mod_mpoly or P is flint . nmod_mpoly ) and not ctx . is_prime () :
3054
+ if division_not_supported :
3049
3055
assert raises (lambda : quick_poly () // mpoly ({(1 , 1 ): 1 }), DomainError )
3050
3056
assert raises (lambda : quick_poly () % mpoly ({(1 , 1 ): 1 }), DomainError )
3051
3057
assert raises (lambda : divmod (quick_poly (), mpoly ({(1 , 1 ): 1 })), DomainError )
@@ -3056,9 +3062,6 @@ def quick_poly():
3056
3062
assert divmod (quick_poly (), mpoly ({(1 , 1 ): 1 })) \
3057
3063
== (mpoly ({(1 , 1 ): 4 }), mpoly ({(1 , 0 ): 3 , (0 , 1 ): 2 , (0 , 0 ): 1 }))
3058
3064
3059
- if (P is flint .fmpz_mod_mpoly or P is flint .nmod_mpoly ) and not ctx .is_prime ():
3060
- pass
3061
- else :
3062
3065
assert 1 / P (1 , ctx = ctx ) == P (1 , ctx = ctx )
3063
3066
assert quick_poly () / 1 == quick_poly ()
3064
3067
assert quick_poly () // 1 == quick_poly ()
@@ -3078,9 +3081,7 @@ def quick_poly():
3078
3081
3079
3082
f = mpoly ({(1 , 1 ): 4 , (0 , 0 ): 1 })
3080
3083
g = mpoly ({(0 , 1 ): 2 , (1 , 0 ): 2 })
3081
- if (P is flint .fmpz_mod_mpoly or P is flint .nmod_mpoly ) and not ctx .is_prime ():
3082
- pass
3083
- else :
3084
+ if not division_not_supported :
3084
3085
assert 1 // quick_poly () == P (ctx = ctx )
3085
3086
assert 1 % quick_poly () == P (1 , ctx = ctx )
3086
3087
assert divmod (1 , quick_poly ()) == (P (ctx = ctx ), P (1 , ctx = ctx ))
@@ -3089,43 +3090,44 @@ def quick_poly():
3089
3090
assert S (1 ) % quick_poly () == P (1 , ctx = ctx )
3090
3091
assert divmod (S (1 ), quick_poly ()) == (P (ctx = ctx ), P (1 , ctx = ctx ))
3091
3092
3092
- assert raises (lambda : quick_poly () / None , TypeError )
3093
- assert raises (lambda : quick_poly () // None , TypeError )
3094
- assert raises (lambda : quick_poly () % None , TypeError )
3095
- assert raises (lambda : divmod (quick_poly (), None ), TypeError )
3096
-
3097
- assert raises (lambda : None / quick_poly (), TypeError )
3098
- assert raises (lambda : None // quick_poly (), TypeError )
3099
- assert raises (lambda : None % quick_poly (), TypeError )
3100
- assert raises (lambda : divmod (None , quick_poly ()), TypeError )
3101
-
3102
- assert raises (lambda : quick_poly () / 0 , ZeroDivisionError )
3103
- assert raises (lambda : quick_poly () // 0 , ZeroDivisionError )
3104
- assert raises (lambda : quick_poly () % 0 , ZeroDivisionError )
3105
- assert raises (lambda : divmod (quick_poly (), 0 ), ZeroDivisionError )
3106
-
3107
- assert raises (lambda : 1 / P (ctx = ctx ), ZeroDivisionError )
3108
- assert raises (lambda : 1 // P (ctx = ctx ), ZeroDivisionError )
3109
- assert raises (lambda : 1 % P (ctx = ctx ), ZeroDivisionError )
3110
- assert raises (lambda : divmod (1 , P (ctx = ctx )), ZeroDivisionError )
3111
-
3112
- assert raises (lambda : quick_poly () / P (ctx = ctx ), ZeroDivisionError )
3113
- assert raises (lambda : quick_poly () // P (ctx = ctx ), ZeroDivisionError )
3114
- assert raises (lambda : quick_poly () % P (ctx = ctx ), ZeroDivisionError )
3115
- assert raises (lambda : divmod (quick_poly (), P (ctx = ctx )), ZeroDivisionError )
3116
-
3117
- assert raises (lambda : quick_poly () / P (1 , ctx = ctx1 ), IncompatibleContextError )
3118
- assert raises (lambda : quick_poly () // P (1 , ctx = ctx1 ), IncompatibleContextError )
3119
- assert raises (lambda : quick_poly () % P (1 , ctx = ctx1 ), IncompatibleContextError )
3120
- assert raises (lambda : divmod (quick_poly (), P (1 , ctx = ctx1 )), IncompatibleContextError )
3121
-
3122
3093
assert f * g / mpoly ({(0 , 1 ): 1 , (1 , 0 ): 1 }) \
3123
3094
== mpoly ({(1 , 1 ): 8 , (0 , 0 ): 2 })
3124
3095
3125
3096
if not is_field :
3126
3097
assert raises (lambda : 1 / quick_poly (), DomainError )
3127
3098
assert raises (lambda : quick_poly () / P (2 , ctx = ctx ), DomainError )
3128
3099
3100
+ # We prefer various other errors to the "division not supported" domain error so these are safe.
3101
+ assert raises (lambda : quick_poly () / None , TypeError )
3102
+ assert raises (lambda : quick_poly () // None , TypeError )
3103
+ assert raises (lambda : quick_poly () % None , TypeError )
3104
+ assert raises (lambda : divmod (quick_poly (), None ), TypeError )
3105
+
3106
+ assert raises (lambda : None / quick_poly (), TypeError )
3107
+ assert raises (lambda : None // quick_poly (), TypeError )
3108
+ assert raises (lambda : None % quick_poly (), TypeError )
3109
+ assert raises (lambda : divmod (None , quick_poly ()), TypeError )
3110
+
3111
+ assert raises (lambda : quick_poly () / 0 , ZeroDivisionError )
3112
+ assert raises (lambda : quick_poly () // 0 , ZeroDivisionError )
3113
+ assert raises (lambda : quick_poly () % 0 , ZeroDivisionError )
3114
+ assert raises (lambda : divmod (quick_poly (), 0 ), ZeroDivisionError )
3115
+
3116
+ assert raises (lambda : 1 / P (ctx = ctx ), ZeroDivisionError )
3117
+ assert raises (lambda : 1 // P (ctx = ctx ), ZeroDivisionError )
3118
+ assert raises (lambda : 1 % P (ctx = ctx ), ZeroDivisionError )
3119
+ assert raises (lambda : divmod (1 , P (ctx = ctx )), ZeroDivisionError )
3120
+
3121
+ assert raises (lambda : quick_poly () / P (ctx = ctx ), ZeroDivisionError )
3122
+ assert raises (lambda : quick_poly () // P (ctx = ctx ), ZeroDivisionError )
3123
+ assert raises (lambda : quick_poly () % P (ctx = ctx ), ZeroDivisionError )
3124
+ assert raises (lambda : divmod (quick_poly (), P (ctx = ctx )), ZeroDivisionError )
3125
+
3126
+ assert raises (lambda : quick_poly () / P (1 , ctx = ctx1 ), IncompatibleContextError )
3127
+ assert raises (lambda : quick_poly () // P (1 , ctx = ctx1 ), IncompatibleContextError )
3128
+ assert raises (lambda : quick_poly () % P (1 , ctx = ctx1 ), IncompatibleContextError )
3129
+ assert raises (lambda : divmod (quick_poly (), P (1 , ctx = ctx1 )), IncompatibleContextError )
3130
+
3129
3131
assert quick_poly () ** 0 == P (1 , ctx = ctx )
3130
3132
assert quick_poly () ** 1 == quick_poly ()
3131
3133
assert quick_poly () ** 2 == mpoly ({
@@ -3146,29 +3148,34 @@ def quick_poly():
3146
3148
# # XXX: Not sure what this should do in general:
3147
3149
assert raises (lambda : pow (P (1 , ctx = ctx ), 2 , 3 ), NotImplementedError )
3148
3150
3149
- if (P is not flint .fmpz_mod_mpoly and P is not flint .nmod_mpoly ) or f .context ().is_prime ():
3151
+ if division_not_supported :
3152
+ assert raises (lambda : (f * g ).gcd (f ), DomainError )
3153
+ else :
3150
3154
if is_field :
3151
3155
assert (f * g ).gcd (f ) == f / 4
3152
3156
else :
3153
3157
assert (f * g ).gcd (f ) == f
3154
3158
assert raises (lambda : quick_poly ().gcd (None ), TypeError )
3155
3159
assert raises (lambda : quick_poly ().gcd (P (ctx = ctx1 )), IncompatibleContextError )
3156
- else :
3157
- assert raises (lambda : (f * g ).gcd (f ), DomainError )
3158
3160
3159
- if P is flint .fmpz_mod_mpoly or P is flint .nmod_mpoly :
3160
- if is_field :
3161
- assert (f * g ).factor () == (S (8 ), [(mpoly ({(0 , 1 ): 1 , (1 , 0 ): 1 }), 1 ), (f / 4 , 1 )])
3161
+ if division_not_supported :
3162
+ # Factorisation not allowed over Z/nZ for n not prime.
3163
+ # Flint would abort so we raise an exception instead:
3164
+ assert raises (lambda : (f * g ).factor (), DomainError )
3165
+ elif characteristic_zero :
3166
+ # Primitive factors over Z for fmpz_mpoly and fmpq_mpoly
3167
+ assert (f * g ).factor () == (S (2 ), [(g / 2 , 1 ), (f , 1 )])
3168
+ elif is_field :
3169
+ # Monic polynomials over Z/pZ for nmod_mpoly and fmpz_mod_mpoly
3170
+ assert (f * g ).factor () == (S (8 ), [(g / 2 , 1 ), (f / 4 , 1 )])
3171
+
3172
+ if division_not_supported :
3173
+ assert raises (lambda : (f * g ).sqrt (), DomainError )
3162
3174
else :
3163
- assert (f * g ).factor () == (S (2 ), [(mpoly ({(0 , 1 ): 1 , (1 , 0 ): 1 }), 1 ), (f , 1 )])
3164
-
3165
- if (P is not flint .fmpz_mod_mpoly and P is not flint .nmod_mpoly ) or f .context ().is_prime ():
3166
3175
assert (f * f ).sqrt () == f
3167
3176
if P is flint .fmpz_mpoly :
3168
3177
assert (f * f ).sqrt (assume_perfect_square = True ) == f
3169
3178
assert raises (lambda : quick_poly ().sqrt (), ValueError )
3170
- else :
3171
- assert raises (lambda : (f * g ).sqrt (), DomainError )
3172
3179
3173
3180
p = quick_poly ()
3174
3181
assert p .derivative (0 ) == p .derivative ("x0" ) == mpoly ({(0 , 0 ): 3 , (1 , 2 ): 8 })
0 commit comments