1+ import operator
12from six import print_
3+ from functools import reduce
4+ import operator
25try :
36 import unittest2 as unittest
47except ImportError :
@@ -22,11 +25,6 @@ def test_numbertheory():
2225 # p = modular_exp(2, -2, 3)
2326 # p = square_root_mod_prime(2, 3)
2427
25- print_ ("Testing gcd..." )
26- assert gcd (3 * 5 * 7 , 3 * 5 * 11 , 3 * 5 * 13 ) == 3 * 5
27- assert gcd ([3 * 5 * 7 , 3 * 5 * 11 , 3 * 5 * 13 ]) == 3 * 5
28- assert gcd (3 ) == 3
29-
3028 print_ ("Testing lcm..." )
3129 assert lcm (3 , 5 * 3 , 7 * 3 ) == 3 * 5 * 7
3230 assert lcm ([3 , 5 * 3 , 7 * 3 ]) == 3 * 5 * 7
@@ -95,7 +93,7 @@ def st_primes(draw, *args, **kwargs):
9593 kwargs ["min_value" ] = 1
9694 prime = draw (st .sampled_from (smallprimes ) |
9795 st .integers (* args , ** kwargs )
98- .filter (lambda x : is_prime ( x ) ))
96+ .filter (is_prime ))
9997 return prime
10098
10199
@@ -107,6 +105,65 @@ def st_num_square_prime(draw):
107105 return sq , prime
108106
109107
108+ @st .composite
109+ def st_comp_with_com_fac (draw ):
110+ """
111+ Strategy that returns lists of numbers, all having a common factor.
112+ """
113+ primes = draw (st .lists (st_primes (max_value = 2 ** 512 ), min_size = 1 ,
114+ max_size = 10 ))
115+ # select random prime(s) that will make the common factor of composites
116+ com_fac_primes = draw (st .lists (st .sampled_from (primes ),
117+ min_size = 1 , max_size = 20 ))
118+ com_fac = reduce (operator .mul , com_fac_primes , 1 )
119+
120+ # select at most 20 lists (returned numbers),
121+ # each having at most 30 primes (factors) including none (then the number
122+ # will be 1)
123+ comp_primes = draw (
124+ st .integers (min_value = 1 , max_value = 20 ).
125+ flatmap (lambda n : st .lists (st .lists (st .sampled_from (primes ),
126+ max_size = 30 ),
127+ min_size = 1 , max_size = n )))
128+
129+ return [reduce (operator .mul , nums , 1 ) * com_fac for nums in comp_primes ]
130+
131+
132+ @st .composite
133+ def st_comp_no_com_fac (draw ):
134+ """
135+ Strategy that returns lists of numbers that don't have a common factor.
136+ """
137+ primes = draw (st .lists (st_primes (max_value = 2 ** 512 ),
138+ min_size = 2 , max_size = 10 , unique = True ))
139+ # first select the primes that will create the uncommon factor
140+ # between returned numbers
141+ uncom_fac_primes = draw (st .lists (
142+ st .sampled_from (primes ),
143+ min_size = 1 , max_size = len (primes )- 1 , unique = True ))
144+ uncom_fac = reduce (operator .mul , uncom_fac_primes , 1 )
145+
146+ # then build composites from leftover primes
147+ leftover_primes = [i for i in primes if i not in uncom_fac_primes ]
148+
149+ assert leftover_primes
150+ assert uncom_fac_primes
151+
152+ # select at most 20 lists, each having at most 30 primes
153+ # selected from the leftover_primes list
154+ number_primes = draw (
155+ st .integers (min_value = 1 , max_value = 20 ).
156+ flatmap (lambda n : st .lists (st .lists (st .sampled_from (leftover_primes ),
157+ max_size = 30 ),
158+ min_size = 1 , max_size = n )))
159+
160+ numbers = [reduce (operator .mul , nums , 1 ) for nums in number_primes ]
161+
162+ insert_at = draw (st .integers (min_value = 0 , max_value = len (numbers )))
163+ numbers .insert (insert_at , uncom_fac )
164+ return numbers
165+
166+
110167HYP_SETTINGS = {}
111168if HC_PRESENT :
112169 HYP_SETTINGS ['suppress_health_check' ]= [HealthCheck .filter_too_much ,
@@ -116,6 +173,39 @@ def st_num_square_prime(draw):
116173
117174
118175class TestNumbertheory (unittest .TestCase ):
176+ def test_gcd (self ):
177+ assert gcd (3 * 5 * 7 , 3 * 5 * 11 , 3 * 5 * 13 ) == 3 * 5
178+ assert gcd ([3 * 5 * 7 , 3 * 5 * 11 , 3 * 5 * 13 ]) == 3 * 5
179+ assert gcd (3 ) == 3
180+
181+ @unittest .skipUnless (HC_PRESENT ,
182+ "Hypothesis 2.0.0 can't be made tolerant of hard to "
183+ "meet requirements (like `is_prime()`)" )
184+ @settings (** HYP_SETTINGS )
185+ @given (st_comp_with_com_fac ())
186+ def test_gcd_with_com_factor (self , numbers ):
187+ n = gcd (numbers )
188+ assert 1 in numbers or n != 1
189+ for i in numbers :
190+ assert i % n == 0
191+
192+ @unittest .skipUnless (HC_PRESENT ,
193+ "Hypothesis 2.0.0 can't be made tolerant of hard to "
194+ "meet requirements (like `is_prime()`)" )
195+ @settings (** HYP_SETTINGS )
196+ @given (st_comp_no_com_fac ())
197+ def test_gcd_with_uncom_factor (self , numbers ):
198+ n = gcd (numbers )
199+ assert n == 1
200+
201+ @given (st .lists (st .integers (min_value = 1 , max_value = 2 ** 8192 ),
202+ min_size = 1 , max_size = 20 ))
203+ def test_gcd_with_random_numbers (self , numbers ):
204+ n = gcd (numbers )
205+ for i in numbers :
206+ # check that at least it's a divider
207+ assert i % n == 0
208+
119209 @unittest .skipUnless (HC_PRESENT ,
120210 "Hypothesis 2.0.0 can't be made tolerant of hard to "
121211 "meet requirements (like `is_prime()`)" )
0 commit comments