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

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# =================================================================== 

24 

25## NOTE: Do not import this module directly. Import these functions from Crypto.Util.number. 

26 

27__revision__ = "$Id$" 

28__all__ = ['ceil_shift', 'ceil_div', 'floor_div', 'exact_log2', 'exact_div'] 

29 

30import sys 

31if sys.version_info[0] == 2 and sys.version_info[1] == 1: 

32 from Crypto.Util.py21compat import * 

33 

34def ceil_shift(n, b): 

35 """Return ceil(n / 2**b) without performing any floating-point or division operations. 

36 

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__)) 

42 

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 

49 

50def ceil_div(a, b): 

51 """Return ceil(a / b) without performing any floating-point operations.""" 

52 

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__)) 

55 

56 (q, r) = divmod(a, b) 

57 if r: 

58 return q + 1 

59 else: 

60 return q 

61 

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__)) 

65 

66 (q, r) = divmod(a, b) 

67 return q 

68 

69def exact_log2(num): 

70 """Find and return an integer i >= 0 such that num == 2**i. 

71 

72 If no such integer exists, this function raises ValueError. 

73 """ 

74 

75 if not isinstance(num, int): 

76 raise TypeError("unsupported operand type: %r" % (type(num).__name__,)) 

77 

78 n = int(num) 

79 if n <= 0: 

80 raise ValueError("cannot compute logarithm of non-positive number") 

81 

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 

89 

90 assert num == (1 << i) 

91 return i 

92 

93def exact_div(p, d, allow_divzero=False): 

94 """Find and return an integer n such that p == n * d 

95 

96 If no such integer exists, this function raises ValueError. 

97 

98 Both operands must be integers. 

99 

100 If the second operand is zero, this function will raise ZeroDivisionError 

101 unless allow_divzero is true (default: False). 

102 """ 

103 

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__)) 

106 

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") 

115 

116 assert p == n * d 

117 return n 

118 

119# vim:set ts=4 sw=4 sts=4 expandtab: