mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	gh-91117: Ensure integer mod and pow operations use cached small ints (GH-31843)
This commit is contained in:
		
							parent
							
								
									a8abb76af9
								
							
						
					
					
						commit
						8be8949116
					
				
					 3 changed files with 45 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -1024,6 +1024,48 @@ def test_small_ints_in_huge_calculation(self):
 | 
			
		|||
        self.assertIs(a + b, 1)
 | 
			
		||||
        self.assertIs(c - a, 1)
 | 
			
		||||
 | 
			
		||||
    @support.cpython_only
 | 
			
		||||
    def test_pow_uses_cached_small_ints(self):
 | 
			
		||||
        self.assertIs(pow(10, 3, 998), 2)
 | 
			
		||||
        self.assertIs(10 ** 3 % 998, 2)
 | 
			
		||||
        a, p, m = 10, 3, 998
 | 
			
		||||
        self.assertIs(a ** p % m, 2)
 | 
			
		||||
 | 
			
		||||
        self.assertIs(pow(2, 31, 2 ** 31 - 1), 1)
 | 
			
		||||
        self.assertIs(2 ** 31 % (2 ** 31 - 1), 1)
 | 
			
		||||
        a, p, m = 2, 31, 2 ** 31 - 1
 | 
			
		||||
        self.assertIs(a ** p % m, 1)
 | 
			
		||||
 | 
			
		||||
        self.assertIs(pow(2, 100, 2**100 - 3), 3)
 | 
			
		||||
        self.assertIs(2 ** 100 % (2 ** 100 - 3), 3)
 | 
			
		||||
        a, p, m = 2, 100, 2**100 - 3
 | 
			
		||||
        self.assertIs(a ** p % m, 3)
 | 
			
		||||
 | 
			
		||||
    @support.cpython_only
 | 
			
		||||
    def test_divmod_uses_cached_small_ints(self):
 | 
			
		||||
        big = 10 ** 100
 | 
			
		||||
 | 
			
		||||
        self.assertIs((big + 1) % big, 1)
 | 
			
		||||
        self.assertIs((big + 1) // big, 1)
 | 
			
		||||
        self.assertIs(big // (big // 2), 2)
 | 
			
		||||
        self.assertIs(big // (big // -4), -4)
 | 
			
		||||
 | 
			
		||||
        q, r = divmod(2 * big + 3, big)
 | 
			
		||||
        self.assertIs(q, 2)
 | 
			
		||||
        self.assertIs(r, 3)
 | 
			
		||||
 | 
			
		||||
        q, r = divmod(-4 * big + 100, big)
 | 
			
		||||
        self.assertIs(q, -4)
 | 
			
		||||
        self.assertIs(r, 100)
 | 
			
		||||
 | 
			
		||||
        q, r = divmod(3 * (-big) - 1, -big)
 | 
			
		||||
        self.assertIs(q, 3)
 | 
			
		||||
        self.assertIs(r, -1)
 | 
			
		||||
 | 
			
		||||
        q, r = divmod(3 * big - 1, -big)
 | 
			
		||||
        self.assertIs(q, -3)
 | 
			
		||||
        self.assertIs(r, -1)
 | 
			
		||||
 | 
			
		||||
    def test_small_ints(self):
 | 
			
		||||
        for i in range(-5, 257):
 | 
			
		||||
            self.assertIs(i, i + 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
Integer mod/remainder operations, including the three-argument form of :func:`pow`, now consistently return ints from the global small integer cache when applicable.
 | 
			
		||||
| 
						 | 
				
			
			@ -2679,6 +2679,7 @@ long_divrem(PyLongObject *a, PyLongObject *b,
 | 
			
		|||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        z = x_divrem(a, b, prem);
 | 
			
		||||
        *prem = maybe_small_long(*prem);
 | 
			
		||||
        if (z == NULL)
 | 
			
		||||
            return -1;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -2732,6 +2733,7 @@ long_rem(PyLongObject *a, PyLongObject *b, PyLongObject **prem)
 | 
			
		|||
    else {
 | 
			
		||||
        /* Slow path using divrem. */
 | 
			
		||||
        Py_XDECREF(x_divrem(a, b, prem));
 | 
			
		||||
        *prem = maybe_small_long(*prem);
 | 
			
		||||
        if (*prem == NULL)
 | 
			
		||||
            return -1;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue