1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
pub fn ones(n: u16) -> u128 {
    0_u128.wrapping_sub(1) >> (128 - n)
}

pub fn parse_int(s: &str) -> Result<u128, core::num::ParseIntError> {
    let mut chars = s.chars();

    if chars.next() == Some('0') {
        if chars.next() == Some('x') {
            let res = chars.collect::<String>();
            return u128::from_str_radix(&res, 16);
        } else if chars.next().is_some() {
            panic!("other bases not supported");
        }
    }

    let signed: i128 = s.parse()?;

    Ok(signed as _)
}

pub fn reverse(mut x: u128, n: u16) -> u128 {
    match n {
        1 => x & 1,
        2 => ((x >> 1) & 1) + ((x << 1) & 2),
        3..=4 => {
            x = ((x >> 2) & 3) + ((x << 2) & 0xc);
            x = ((x >> 1) & 5) + ((x << 1) & 0xa);
            x >> (4 - n)
        }
        5..=8 => {
            x = ((x >> 4) & 0x0f) + ((x << 4) & 0xf0);
            x = ((x >> 2) & 0x33) + ((x << 2) & 0xcc);
            x = ((x >> 1) & 0x55) + ((x << 1) & 0xaa);
            x >> (8 - n)
        }
        9..=16 => {
            x = ((x >> 8) & 0x00ff) + ((x << 8) & 0xff00);
            x = ((x >> 4) & 0x0f0f) + ((x << 4) & 0xf0f0);
            x = ((x >> 2) & 0x3333) + ((x << 2) & 0xcccc);
            x = ((x >> 1) & 0x5555) + ((x << 1) & 0xaaaa);
            x >> (16 - n)
        }
        17..=32 => {
            x = ((x >> 16) & 0x0000ffff) + ((x << 16) & 0xffff0000);
            x = ((x >> 8) & 0x00ff00ff) + ((x << 8) & 0xff00ff00);
            x = ((x >> 4) & 0x0f0f0f0f) + ((x << 4) & 0xf0f0f0f0);
            x = ((x >> 2) & 0x33333333) + ((x << 2) & 0xcccccccc);
            x = ((x >> 1) & 0x55555555) + ((x << 1) & 0xaaaaaaaa);
            x >> (32 - n)
        }
        33..=64 => {
            x = ((x >> 32) & 0x00000000ffffffff) + ((x << 32) & 0xffffffff00000000);
            x = ((x >> 16) & 0x0000ffff0000ffff) + ((x << 16) & 0xffff0000ffff0000);
            x = ((x >> 8) & 0x00ff00ff00ff00ff) + ((x << 8) & 0xff00ff00ff00ff00);
            x = ((x >> 4) & 0x0f0f0f0f0f0f0f0f) + ((x << 4) & 0xf0f0f0f0f0f0f0f0);
            x = ((x >> 2) & 0x3333333333333333) + ((x << 2) & 0xcccccccccccccccc);
            x = ((x >> 1) & 0x5555555555555555) + ((x << 1) & 0xaaaaaaaaaaaaaaaa);
            x >> (64 - n)
        }
        65..=128 => {
            let hi = reverse(x, 64) << (n - 64);
            let lo = reverse(x >> 64, n - 64);
            lo | hi
        }
        _ => panic!("Bitwidth must be less than 128!"),
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn reverse_one_bit() {
        assert_eq!(0, reverse(0, 1));
        assert_eq!(1, reverse(1, 1));
    }

    #[test]
    fn reverse_two_bits() {
        assert_eq!(0b00, reverse(0b00, 2));
        assert_eq!(0b10, reverse(0b01, 2));
        assert_eq!(0b01, reverse(0b10, 2));
        assert_eq!(0b11, reverse(0b11, 2));
    }

    #[test]
    fn reverse_three_bits() {
        assert_eq!(0b000, reverse(0b000, 3));
        assert_eq!(0b100, reverse(0b001, 3));
        assert_eq!(0b010, reverse(0b010, 3));
        assert_eq!(0b110, reverse(0b011, 3));
        assert_eq!(0b001, reverse(0b100, 3));
        assert_eq!(0b101, reverse(0b101, 3));
        assert_eq!(0b011, reverse(0b110, 3));
        assert_eq!(0b111, reverse(0b111, 3));
    }

    #[test]
    fn reverse_four_bits() {
        assert_eq!(0b0000, reverse(0b0000, 4));
        assert_eq!(0b1000, reverse(0b0001, 4));
        assert_eq!(0b0100, reverse(0b0010, 4));
        assert_eq!(0b1100, reverse(0b0011, 4));
        assert_eq!(0b0010, reverse(0b0100, 4));
        assert_eq!(0b1010, reverse(0b0101, 4));
        assert_eq!(0b0110, reverse(0b0110, 4));
        assert_eq!(0b1110, reverse(0b0111, 4));
        assert_eq!(0b0001, reverse(0b1000, 4));
        assert_eq!(0b1001, reverse(0b1001, 4));
        assert_eq!(0b0101, reverse(0b1010, 4));
        assert_eq!(0b1101, reverse(0b1011, 4));
        assert_eq!(0b0011, reverse(0b1100, 4));
        assert_eq!(0b1011, reverse(0b1101, 4));
        assert_eq!(0b0111, reverse(0b1110, 4));
        assert_eq!(0b1111, reverse(0b1111, 4));
    }

    #[test]
    fn reverse_five_bits() {
        assert_eq!(0b10101, reverse(0b10101, 5));
        assert_eq!(0b10100, reverse(0b00101, 5));
        assert_eq!(0b00101, reverse(0b10100, 5));
        assert_eq!(0b10001, reverse(0b10001, 5));
        assert_eq!(0b11101, reverse(0b10111, 5));
        assert_eq!(0b10111, reverse(0b11101, 5));
    }

    #[test]
    fn reverse_six_bits() {
        assert_eq!(0b010101, reverse(0b101010, 6));
        assert_eq!(0b010100, reverse(0b001010, 6));
        assert_eq!(0b000101, reverse(0b101000, 6));
        assert_eq!(0b100010, reverse(0b010001, 6));
        assert_eq!(0b111010, reverse(0b010111, 6));
        assert_eq!(0b101110, reverse(0b011101, 6));
    }

    #[test]
    fn reverse_seven_bits() {
        assert_eq!(0b0010101, reverse(0b1010100, 7));
        assert_eq!(0b0010100, reverse(0b0010100, 7));
        assert_eq!(0b1000101, reverse(0b1010001, 7));
        assert_eq!(0b1100010, reverse(0b0100011, 7));
        assert_eq!(0b1110100, reverse(0b0010111, 7));
        assert_eq!(0b1011100, reverse(0b0011101, 7));
    }

    #[test]
    fn reverse_eight_bits() {
        assert_eq!(0b00010101, reverse(0b10101000, 8));
        assert_eq!(0b10010100, reverse(0b00101001, 8));
        assert_eq!(0b01000101, reverse(0b10100010, 8));
        assert_eq!(0b11100010, reverse(0b01000111, 8));
        assert_eq!(0b01110100, reverse(0b00101110, 8));
        assert_eq!(0b11011100, reverse(0b00111011, 8));
    }

    #[test]
    fn reverse_nine_bits() {
        assert_eq!(0b000101011, reverse(0b110101000, 9));
        assert_eq!(0b100101001, reverse(0b100101001, 9));
        assert_eq!(0b010001011, reverse(0b110100010, 9));
        assert_eq!(0b111000101, reverse(0b101000111, 9));
        assert_eq!(0b011101001, reverse(0b100101110, 9));
        assert_eq!(0b110111001, reverse(0b100111011, 9));
    }

    #[test]
    fn reverse_sixteen_bits() {
        assert_eq!(0b1000010101110101, reverse(0b1010111010100001, 16));
        assert_eq!(0b1010010100110101, reverse(0b1010110010100101, 16));
        assert_eq!(0b1001000101110101, reverse(0b1010111010001001, 16));
        assert_eq!(0b1011100010110101, reverse(0b1010110100011101, 16));
        assert_eq!(0b1001110100110101, reverse(0b1010110010111001, 16));
        assert_eq!(0b1011011100110101, reverse(0b1010110011101101, 16));
    }

    #[test]
    fn reverse_seventeen_bits() {
        assert_eq!(0b10100010101110101, reverse(0b10101110101000101, 17));
        assert_eq!(0b10010010100110101, reverse(0b10101100101001001, 17));
        assert_eq!(0b10101000101110101, reverse(0b10101110100010101, 17));
        assert_eq!(0b10011100010110101, reverse(0b10101101000111001, 17));
        assert_eq!(0b10101110100110101, reverse(0b10101100101110101, 17));
        assert_eq!(0b10011011100110101, reverse(0b10101100111011001, 17));
    }

    #[test]
    fn reverse_thirty_two_bits() {
        assert_eq!(
            0b01000101011101011000010101110101,
            reverse(0b10101110101000011010111010100010, 32)
        );
        assert_eq!(
            0b10100101001101011010010100110101,
            reverse(0b10101100101001011010110010100101, 32)
        );
        assert_eq!(
            0b01010001011101011001000101110101,
            reverse(0b10101110100010011010111010001010, 32)
        );
        assert_eq!(
            0b10111000101101011011100010110101,
            reverse(0b10101101000111011010110100011101, 32)
        );
        assert_eq!(
            0b01011101001101011001110100110101,
            reverse(0b10101100101110011010110010111010, 32)
        );
        assert_eq!(
            0b10110111001101011011011100110101,
            reverse(0b10101100111011011010110011101101, 32)
        );
    }

    #[test]
    fn reverse_thirty_three_bits() {
        assert_eq!(
            0b101000101011101011000010101110101,
            reverse(0b101011101010000110101110101000101, 33)
        );
        assert_eq!(
            0b010100101001101011010010100110101,
            reverse(0b101011001010010110101100101001010, 33)
        );
        assert_eq!(
            0b101010001011101011001000101110101,
            reverse(0b101011101000100110101110100010101, 33)
        );
        assert_eq!(
            0b010111000101101011011100010110101,
            reverse(0b101011010001110110101101000111010, 33)
        );
        assert_eq!(
            0b101011101001101011001110100110101,
            reverse(0b101011001011100110101100101110101, 33)
        );
        assert_eq!(
            0b010110111001101011011011100110101,
            reverse(0b101011001110110110101100111011010, 33)
        );
    }

    #[test]
    fn reverse_sixty_four_bits() {
        assert_eq!(0xf0f0f0f0f0f0f0f0, reverse(0x0f0f0f0f0f0f0f0f, 64));
        assert_eq!(0x3535353535353535, reverse(0xacacacacacacacac, 64));
    }

    #[test]
    fn reverse_sixty_five_bits() {
        assert_eq!(0x10000000000000000, reverse(1, 65));
        assert_eq!(0x1f0f0f0f0f0f0f0f0, reverse(0x01e1e1e1e1e1e1e1f, 65));
    }

    #[test]
    fn reverse_one_hundred_twenty_eight_bits() {
        assert_eq!(0x80000000000000000000000000000000, reverse(1, 128));
        assert_eq!(
            0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0,
            reverse(0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f, 128)
        );
        assert_eq!(
            0x35353535353535353535353535353535,
            reverse(0xacacacacacacacacacacacacacacacac, 128)
        );
    }

    #[test]
    fn parse_int_dec() {
        assert_eq!(Ok(42), parse_int("42"));
    }

    #[test]
    fn parse_int_hex() {
        assert_eq!(Ok(42), parse_int("0x2a"));
    }
}