Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/Crypto/Util/_number_new.py: 62%
52 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 07:03 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 07:03 +0000
1# -*- coding: ascii -*-
2#
3# Util/_number_new.py : utility functions
4#
5# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
6#
7# ===================================================================
8# The contents of this file are dedicated to the public domain. To
9# the extent that dedication to the public domain is not available,
10# everyone is granted a worldwide, perpetual, royalty-free,
11# non-exclusive license to exercise all rights associated with the
12# contents of this file for any purpose whatsoever.
13# No rights are reserved.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22# SOFTWARE.
23# ===================================================================
25## NOTE: Do not import this module directly. Import these functions from Crypto.Util.number.
27__revision__ = "$Id$"
28__all__ = ['ceil_shift', 'ceil_div', 'floor_div', 'exact_log2', 'exact_div']
30import sys
31if sys.version_info[0] == 2 and sys.version_info[1] == 1:
32 from Crypto.Util.py21compat import *
34def ceil_shift(n, b):
35 """Return ceil(n / 2**b) without performing any floating-point or division operations.
37 This is done by right-shifting n by b bits and incrementing the result by 1
38 if any '1' bits were shifted out.
39 """
40 if not isinstance(n, int) or not isinstance(b, int):
41 raise TypeError("unsupported operand type(s): %r and %r" % (type(n).__name__, type(b).__name__))
43 assert n >= 0 and b >= 0 # I haven't tested or even thought about negative values
44 mask = (1 << b) - 1
45 if n & mask:
46 return (n >> b) + 1
47 else:
48 return n >> b
50def ceil_div(a, b):
51 """Return ceil(a / b) without performing any floating-point operations."""
53 if not isinstance(a, int) or not isinstance(b, int):
54 raise TypeError("unsupported operand type(s): %r and %r" % (type(a).__name__, type(b).__name__))
56 (q, r) = divmod(a, b)
57 if r:
58 return q + 1
59 else:
60 return q
62def floor_div(a, b):
63 if not isinstance(a, int) or not isinstance(b, int):
64 raise TypeError("unsupported operand type(s): %r and %r" % (type(a).__name__, type(b).__name__))
66 (q, r) = divmod(a, b)
67 return q
69def exact_log2(num):
70 """Find and return an integer i >= 0 such that num == 2**i.
72 If no such integer exists, this function raises ValueError.
73 """
75 if not isinstance(num, int):
76 raise TypeError("unsupported operand type: %r" % (type(num).__name__,))
78 n = int(num)
79 if n <= 0:
80 raise ValueError("cannot compute logarithm of non-positive number")
82 i = 0
83 while n != 0:
84 if (n & 1) and n != 1:
85 raise ValueError("No solution could be found")
86 i += 1
87 n >>= 1
88 i -= 1
90 assert num == (1 << i)
91 return i
93def exact_div(p, d, allow_divzero=False):
94 """Find and return an integer n such that p == n * d
96 If no such integer exists, this function raises ValueError.
98 Both operands must be integers.
100 If the second operand is zero, this function will raise ZeroDivisionError
101 unless allow_divzero is true (default: False).
102 """
104 if not isinstance(p, int) or not isinstance(d, int):
105 raise TypeError("unsupported operand type(s): %r and %r" % (type(p).__name__, type(d).__name__))
107 if d == 0 and allow_divzero:
108 n = 0
109 if p != n * d:
110 raise ValueError("No solution could be found")
111 else:
112 (n, r) = divmod(p, d)
113 if r != 0:
114 raise ValueError("No solution could be found")
116 assert p == n * d
117 return n
119# vim:set ts=4 sw=4 sts=4 expandtab: