github.com/lirm/aeron-go@v0.0.0-20230415210743-920325491dc4/aeron/util/bits.go (about) 1 /* 2 Copyright 2016 Stanislav Liberman 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package util 18 19 import ( 20 "fmt" 21 "unsafe" 22 ) 23 24 var i32 int32 25 var i64 int64 26 27 const ( 28 // CacheLineLength is a constant for the size of a CPU cache line 29 CacheLineLength int32 = 64 30 31 // SizeOfInt32 is a constant for the size of int32. Ha. Just for Clarity 32 SizeOfInt32 int32 = int32(unsafe.Sizeof(i32)) 33 34 // SizeOfInt64 is a constant for the size of int64 35 SizeOfInt64 int32 = int32(unsafe.Sizeof(i64)) 36 ) 37 38 // AlignInt32 will return a number rounded up to the alignment boundary 39 func AlignInt32(value, alignment int32) int32 { 40 return (value + (alignment - 1)) & ^(alignment - 1) 41 } 42 43 // NumberOfTrailingZeroes is HD recipe for determining the number of leading zeros on 32 bit integer 44 func NumberOfTrailingZeroes(value uint32) uint8 { 45 table := [32]uint8{ 46 0, 1, 2, 24, 3, 19, 6, 25, 47 22, 4, 20, 10, 16, 7, 12, 26, 48 31, 23, 18, 5, 21, 9, 15, 11, 49 30, 17, 8, 14, 29, 13, 28, 27} 50 51 if value == 0 { 52 return 32 53 } 54 55 value = (value & -value) * 0x04D7651F 56 57 return table[value>>27] 58 } 59 60 // FastMod3 is HD recipe for faster division by 3 for 32 bit integers 61 func FastMod3(value uint64) int32 { 62 63 table := [62]int32{0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 64 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 65 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 66 0, 1, 2, 0, 1, 2, 0, 1} 67 68 value = (value >> 16) + (value & 0xFFFF) // Max 0x1FFFE. 69 value = (value >> 8) + (value & 0x00FF) // Max 0x2FD. 70 value = (value >> 4) + (value & 0x000F) // Max 0x3D. 71 return table[value] 72 } 73 74 // IsPowerOfTwo checks that the argument number is a power of two 75 func IsPowerOfTwo(value int64) bool { 76 return value > 0 && ((value & (^value + 1)) == value) 77 } 78 79 // Memcpy will copy length bytes from pointer src to dest 80 //go:nocheckptr 81 func Memcpy(dest uintptr, src uintptr, length int32) { 82 var i int32 83 84 // batches of 8 85 i8 := length >> 3 86 for ; i < i8; i += 8 { 87 destPtr := unsafe.Pointer(dest + uintptr(i)) 88 srcPtr := unsafe.Pointer(src + uintptr(i)) 89 90 *(*uint64)(destPtr) = *(*uint64)(srcPtr) 91 } 92 93 // batches of 4 94 i4 := (length - i) >> 2 95 for ; i < i4; i += 4 { 96 destPtr := unsafe.Pointer(dest + uintptr(i)) 97 srcPtr := unsafe.Pointer(src + uintptr(i)) 98 99 *(*uint32)(destPtr) = *(*uint32)(srcPtr) 100 } 101 102 // remainder 103 for ; i < length; i++ { 104 destPtr := unsafe.Pointer(dest + uintptr(i)) 105 srcPtr := unsafe.Pointer(src + uintptr(i)) 106 107 *(*int8)(destPtr) = *(*int8)(srcPtr) 108 } 109 } 110 111 func MemPrint(ptr uintptr, len int) string { 112 var output string 113 114 for i := 0; i < len; i += 1 { 115 ptr := unsafe.Pointer(ptr + uintptr(i)) 116 output += fmt.Sprintf("%02x ", *(*int8)(ptr)) 117 } 118 119 return output 120 } 121 122 func Print(bytes []byte) { 123 for i, b := range bytes { 124 if i > 0 && i%16 == 0 && i%32 != 0 { 125 fmt.Print(" : ") 126 } 127 if i > 0 && i%32 == 0 { 128 fmt.Print("\n") 129 } 130 fmt.Printf("%02x ", b) 131 } 132 fmt.Print("\n") 133 }