我试图说明输入位如何影响四步旋转散列中的输出位。哈希函数如下所示:
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
uint32_t rotating_hash(uint32_t state, uint32_t input)
{
uint32_t hash = state;
uint8_t *p = (uint8_t*)&input;
// mix ; combine
hash ^= *(p++);
hash += rot(hash, 4) ^ *(p++);
hash += rot(hash, 4) ^ *(p++);
hash += rot(hash, 4) ^ *p;
return hash;
}
其中,为简单起见,我假设加法中的位只影响它们已经存在的相同位置。实际函数不是那么重要,但它是一个过程,其中一步的每一位都会影响它下面的两位
我计算一个级别的位会影响它们之下的位,如下所示:
library(tibble)
library(dplyr)
library(magrittr)
rot_hash_positions <- function(bit) {
operation_1 <- bit
operation_2 <- outer(operation_1, c(4, 0, -28), FUN = '+') %>% as.vector() %>% { . %% 32 }
operation_3 <- outer(operation_2, c(4, 0, -28), FUN = '+') %>% as.vector() %>% { . %% 32 }
operation_4 <- outer(operation_3, c(4, 0, -28), FUN = '+') %>% as.vector() %>% { . %% 32 }
rbind(tibble(bit = bit, operation = 1, positions = operation_1),
tibble(bit = bit, operation = 2, positions = operation_2),
tibble(bit = bit, operation = 3, positions = operation_3),
tibble(bit = bit, operation = 4, positions = operation_4))
}
bit_movement <- do.call(rbind, lapply(0:31, rot_hash_positions))
,结果如下:
> bit_movement %>% filter(bit == 0)
# A tibble: 10 x 3
bit operation positions
<int> <dbl> <dbl>
1 0 1 0
2 0 2 4
3 0 2 0
4 0 3 8
5 0 3 4
6 0 3 0
7 0 4 12
8 0 4 8
9 0 4 4
10 0 4 0
该函数计算旋转操作的两个值,但模数32成为一个位置,我使用unique()
摆脱了重复。
现在我想绘制这个。到目前为止,我的尝试看起来像这样:
library(ggplot2)
plot_bitmovement <- function(bit_movement, highlight_bits) {
ggplot(bit_movement, aes(
y = positions,
x = operation,
group = factor(bit, levels = 1:32)
)) +
geom_line(colour = "gray") +
geom_point(colour = "gray") +
geom_line(data = highlight_bits, colour = "black") +
geom_point(data = highlight_bits, colour = "black") +
coord_flip() +
scale_y_reverse(breaks = 0:31, labels = 1:32) +
scale_x_reverse() +
theme_minimal() +
theme(
legend.position = "none"
) + ylab("Bit-position") + xlab("Operation")
}
我突出显示图中的第一个或最后一个字节:
bit_movement <- do.call(rbind, lapply(0:31, rot_hash_positions))
plot_bitmovement(bit_movement, bit_movement %>% filter(bit < 8))
last_byte <- tibble(bit = 0:7, operation = 4, positions = 0:7)
plot_bitmovement(bit_movement, last_byte)
在这种情况下,最后一个字节不太有趣,但是我需要可视化其他一些哈希函数以及它变得更有趣。
现在我的问题是这样的:当我使用geom_line()
绘制位移动时,我不会从一个y轴水平到下一个水平线获得线段,但是除了第一步之外的所有水平线段都是一级到下一级。我想要的只是从一个级别到下一个级别的段。我不完全确定如何做到这一点。
我认为geom_linesegment
是要走的路,在这种情况下,我需要将我的bit_movement
数据框修改为具有我想要的线段的起点和终点位置的东西,但我不确定如何以优雅的方式做到这一点。由于我需要绘制几个相似的数字,我宁愿不必过多地对数据操作进行硬连接。
有什么建议吗?
答案 0 :(得分:0)
我想出了这个主意。我不确定它有多优雅,所以我仍然喜欢它的评论。
library(purrr)
get_steps <- function(bm, step) {
op1 <- bm %>%
filter(operation == !!(step-1)) %>%
mutate(x = operation, y = positions) %>%
select(bit, x, y)
op2 <- bm %>%
filter(operation == !!step) %>%
mutate(xend = operation, yend = positions) %>%
select(bit, xend, yend)
inner_join(op1, op2, by = "bit")
}
plot_bitmovement <- function(bit_movement, highlight_bits) {
bm_segs <- map(2:4, ~ get_steps(bit_movement, .x)) %>% bind_rows()
hl_segs <- map(2:4, ~ get_steps(highlight_bits, .x)) %>% bind_rows()
ggplot(bm_segs, aes(
x = x,
y = y,
xend = xend,
yend = yend)
) +
geom_segment(colour = "grey") +
geom_point(colour = "grey") +
geom_point(aes(x = xend, y = yend), colour = "grey") +
geom_segment(data = hl_segs, colour = "black") +
geom_point(data = hl_segs, colour = "black") +
geom_point(aes(x = xend, y = yend), data = hl_segs, colour = "black") +
coord_flip() +
scale_y_reverse(breaks = 0:31, labels = 1:32) +
scale_x_reverse() +
theme_minimal() +
theme(
legend.position = "none"
) + ylab("Bit-position") + xlab("Operation")
}
bit_movement <- do.call(rbind, lapply(0:31, rot_hash_positions))
plot_bitmovement(bit_movement, bit_movement %>% filter(bit < 8))
更新:不,这也不太正确。现在我看到的动作比我应该多,因为我将所有位置合并到一个级别以下。不过,这是rot_hash_positions
中的一个错误,所以我会自己给它一个。