xor.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package lib
  5. import (
  6. "runtime"
  7. "unsafe"
  8. )
  9. const wordSize = int(unsafe.Sizeof(uintptr(0)))
  10. const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64"
  11. // fastXORBytes xors in bulk. It only works on architectures that
  12. // support unaligned read/writes.
  13. func fastXORBytes(dst, a, b []byte) int {
  14. n := len(a)
  15. if len(b) < n {
  16. n = len(b)
  17. }
  18. w := n / wordSize
  19. if w > 0 {
  20. dw := *(*[]uintptr)(unsafe.Pointer(&dst))
  21. aw := *(*[]uintptr)(unsafe.Pointer(&a))
  22. bw := *(*[]uintptr)(unsafe.Pointer(&b))
  23. for i := 0; i < w; i++ {
  24. dw[i] = aw[i] ^ bw[i]
  25. }
  26. }
  27. for i := (n - n%wordSize); i < n; i++ {
  28. dst[i] = a[i] ^ b[i]
  29. }
  30. return n
  31. }
  32. func safeXORBytes(dst, a, b []byte) int {
  33. n := len(a)
  34. if len(b) < n {
  35. n = len(b)
  36. }
  37. for i := 0; i < n; i++ {
  38. dst[i] = a[i] ^ b[i]
  39. }
  40. return n
  41. }
  42. // xorBytes xors the bytes in a and b. The destination is assumed to have enough
  43. // space. Returns the number of bytes xor'd.
  44. func xorBytes(dst, a, b []byte) int {
  45. if supportsUnaligned {
  46. return fastXORBytes(dst, a, b)
  47. } else {
  48. // TODO(hanwen): if (dst, a, b) have common alignment
  49. // we could still try fastXORBytes. It is not clear
  50. // how often this happens, and it's only worth it if
  51. // the block encryption itself is hardware
  52. // accelerated.
  53. return safeXORBytes(dst, a, b)
  54. }
  55. }
  56. // fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.)
  57. // The arguments are assumed to be of equal length.
  58. func fastXORWords(dst, a, b []byte) {
  59. dw := *(*[]uintptr)(unsafe.Pointer(&dst))
  60. aw := *(*[]uintptr)(unsafe.Pointer(&a))
  61. bw := *(*[]uintptr)(unsafe.Pointer(&b))
  62. n := len(b) / wordSize
  63. for i := 0; i < n; i++ {
  64. dw[i] = aw[i] ^ bw[i]
  65. }
  66. }
  67. func XorWords(dst, a, b []byte) {
  68. if supportsUnaligned {
  69. fastXORWords(dst, a, b)
  70. } else {
  71. safeXORBytes(dst, a, b)
  72. }
  73. }
  74. func Xor(a, dst []byte) {
  75. XorWords(dst, a, dst)
  76. }
  77. //make sure dst is all 0's when you call this
  78. func Xors(as [][]byte) []byte{
  79. dst := make([]byte, len(as[0]))
  80. for i := range as {
  81. XorWords(dst, dst, as[i])
  82. }
  83. return dst
  84. }
  85. func XorsDC(bsss [][][]byte) [][]byte {
  86. n := len(bsss)
  87. m := len(bsss[0])
  88. x := make([][]byte, n)
  89. for i, _ := range bsss {
  90. y := make([][]byte, m)
  91. x[i] = make([]byte, len(bsss[i][0]))
  92. for j := 0; j < m; j++ {
  93. y[j] = bsss[j][i]
  94. }
  95. x[i] = Xors(y)
  96. }
  97. return x
  98. }