Skip to content

Commit c7332e9

Browse files
authored
RFC #17: remove the log2_int(n, need_pow2=True) function
2 parents 7667292 + a14959f commit c7332e9

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

text/0017-remove-log2-int.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
- Start Date: 2024-01-08
2+
- RFC PR: [amaranth-lang/rfcs#17](https://github.com/amaranth-lang/rfcs/pull/17)
3+
- Amaranth Issue: [amaranth-lang/amaranth#1025](https://github.com/amaranth-lang/amaranth/issues/1025)
4+
5+
# Remove `log2_int`
6+
7+
## Summary
8+
[summary]: #summary
9+
10+
Replace `log2_int` with two functions: `ceil_log2` and `exact_log2`.
11+
12+
## Motivation
13+
[motivation]: #motivation
14+
15+
`log2_int` is a helper function that was copied from Migen in the early days of Amaranth.
16+
17+
It behaves like so:
18+
19+
* `n` must be an integer, and a power-of-2 unless `need_pow2` is `False`;
20+
* if `n == 0`, it returns `0`;
21+
* if `n != 0`, it returns `(n - 1).bit_length()`.
22+
23+
#### Differences with `math.log2`
24+
25+
In practice, `log2_int` differs from `math.log2` in the following ways:
26+
27+
1. its implementation is restricted to integers only;
28+
2. if `need_pow2` is false, the result is rounded up to the nearest integer;
29+
3. it doesn't raise an exception for `n == 0`;
30+
4. if `need_pow2` is false, it doesn't raise an exception for `n < 0`.
31+
32+
#### Observations
33+
34+
* *1)* is a desirable property; coercing integers into floating-point numbers is fraught with peril, as the latter have limited precision.
35+
* *2)* has common use-cases in digital design, such as address decoders.
36+
* *3)* and *4)* are misleading at best. Despite being advertised as a logarithm, `log2_int` doesn't exclude 0 or negative integers from its domain.
37+
38+
## Guide-level explanation
39+
[guide-level-explanation]: #guide-level-explanation
40+
41+
Amaranth provides two log2 functions for integer arithmetic:
42+
43+
* `ceil_log2(n)`, where `n` is assumed to be any non-negative integer
44+
* `exact_log2(n)`, where `n` is assumed to be an integer power-of-2
45+
46+
For example:
47+
48+
```python3
49+
ceil_log2(8) # 3
50+
ceil_log2(5) # 3
51+
ceil_log2(4) # 2
52+
53+
exact_log2(8) # 3
54+
exact_log2(5) # raises a ValueError
55+
exact_log2(4) # 2
56+
```
57+
58+
## Reference-level explanation
59+
[reference-level-explanation]: #reference-level-explanation
60+
61+
Use of the `log2_int` function is deprecated.
62+
63+
A `ceil_log2(n)` function is added, that:
64+
65+
* returns the integer log2 of the smallest power-of-2 greater than or equal to `n`;
66+
* raises a `TypeError` if `n` is not an integer;
67+
* raises a `ValueError` if `n` is lesser than 0.
68+
69+
An `exact_log2(n)` function is added, that:
70+
71+
* returns the integer log2 of `n`;
72+
* raises a `TypeError` if `n` is not an integer;
73+
* raises a `ValueError` if `n` is not a power-of-two.
74+
75+
## Drawbacks
76+
[drawbacks]: #drawbacks
77+
78+
This is a breaking change.
79+
80+
## Rationale and alternatives
81+
[rationale-and-alternatives]: #rationale-and-alternatives
82+
83+
The following alternatives have been considered:
84+
85+
1. Do nothing. Callers of `log2_int` may still need to restrict its domain to positive integers.
86+
2. Restrict `log2_int` to positive integers. Downstream code relying on the previous behavior may silently break.
87+
3. Remove `log2_int`, and use `math.log2` as replacement:
88+
* `log2_int(n)` would be replaced with `math.log2(n)`
89+
* `log2_int(n, need_pow2=False)` would be replaced with `math.ceil(math.log2(n))`
90+
91+
Option *3)* will give incorrect results, as `n` is coerced from `int` to `float`:
92+
93+
```
94+
>>> log2_int((1 << 64) + 1, need_pow2=False)
95+
65
96+
>>> math.ceil(math.log2((1 << 64) + 1))
97+
64
98+
```
99+
100+
## Prior art
101+
[prior-art]: #prior-art
102+
103+
None.
104+
105+
## Unresolved questions
106+
[unresolved-questions]: #unresolved-questions
107+
108+
None.
109+
110+
## Future possibilities
111+
[future-possibilities]: #future-possibilities
112+
113+
None.
114+
115+
## Acknowledgements
116+
117+
[@wanda-phi] provided valuable feedback while this RFC was being drafted.
118+
119+
[@wanda-phi]: https://github.com/wanda-phi

0 commit comments

Comments
 (0)