@@ -30,34 +30,40 @@ namespace util {
3030namespace bit_util {
3131
3232inline uint64_t SafeLoadUpTo8Bytes (const uint8_t * bytes, int num_bytes) {
33- // This will not be correct on big-endian architectures.
34- #if !ARROW_LITTLE_ENDIAN
35- ARROW_DCHECK (false );
36- #endif
3733 ARROW_DCHECK (num_bytes >= 0 && num_bytes <= 8 );
3834 if (num_bytes == 8 ) {
3935 return util::SafeLoad (reinterpret_cast <const uint64_t *>(bytes));
4036 } else {
4137 uint64_t word = 0 ;
38+ #if ARROW_LITTLE_ENDIAN
4239 for (int i = 0 ; i < num_bytes; ++i) {
4340 word |= static_cast <uint64_t >(bytes[i]) << (8 * i);
4441 }
42+ #else
43+ // Big-endian: most significant byte first
44+ for (int i = 0 ; i < num_bytes; ++i) {
45+ word |= static_cast <uint64_t >(bytes[i]) << (8 * (num_bytes - 1 - i));
46+ }
47+ #endif
4548 return word;
4649 }
4750}
4851
4952inline void SafeStoreUpTo8Bytes (uint8_t * bytes, int num_bytes, uint64_t value) {
50- // This will not be correct on big-endian architectures.
51- #if !ARROW_LITTLE_ENDIAN
52- ARROW_DCHECK (false );
53- #endif
5453 ARROW_DCHECK (num_bytes >= 0 && num_bytes <= 8 );
5554 if (num_bytes == 8 ) {
5655 util::SafeStore (reinterpret_cast <uint64_t *>(bytes), value);
5756 } else {
57+ #if ARROW_LITTLE_ENDIAN
5858 for (int i = 0 ; i < num_bytes; ++i) {
5959 bytes[i] = static_cast <uint8_t >(value >> (8 * i));
6060 }
61+ #else
62+ // Big-endian: most significant byte first
63+ for (int i = 0 ; i < num_bytes; ++i) {
64+ bytes[i] = static_cast <uint8_t >(value >> (8 * (num_bytes - 1 - i)));
65+ }
66+ #endif
6167 }
6268}
6369
@@ -118,7 +124,22 @@ void bits_to_indexes_internal(int64_t hardware_flags, const int num_bits,
118124 // Optionally process the last partial word with masking out bits outside range
119125 if (tail) {
120126 const uint8_t * bits_tail = bits + (num_bits - tail) / 8 ;
127+ #if ARROW_LITTLE_ENDIAN
121128 uint64_t word = SafeLoadUpTo8Bytes (bits_tail, (tail + 7 ) / 8 );
129+ #else
130+ int tail_bytes = (tail + 7 ) / 8 ;
131+ uint64_t word;
132+ if (tail_bytes == 8 ) {
133+ word = util::SafeLoad (reinterpret_cast <const uint64_t *>(bits_tail));
134+ } else {
135+ // For bit manipulation, always load into least significant bits
136+ // to ensure compatibility with CountTrailingZeros on Big-endian systems
137+ word = 0 ;
138+ for (int i = 0 ; i < tail_bytes; ++i) {
139+ word |= static_cast <uint64_t >(bits_tail[i]) << (8 * i);
140+ }
141+ }
142+ #endif
122143 if (bit_to_search == 0 ) {
123144 word = ~word;
124145 }
@@ -299,7 +320,21 @@ void bytes_to_bits(int64_t hardware_flags, const int num_bits, const uint8_t* by
299320 }
300321 int tail = num_bits % unroll;
301322 if (tail) {
302- uint64_t bytes_next = SafeLoadUpTo8Bytes (bytes + num_bits - tail, tail);
323+ uint64_t bytes_next;
324+ #if ARROW_LITTLE_ENDIAN
325+ bytes_next = SafeLoadUpTo8Bytes (bytes + num_bits - tail, tail);
326+ #else
327+ if (tail == 8 ) {
328+ bytes_next = util::SafeLoad (reinterpret_cast <const uint64_t *>(bytes + num_bits - tail));
329+ } else {
330+ // On Big-endian systems, for bytes_to_bits, load all tail bytes in little-endian order
331+ // to ensure compatibility with subsequent bit operations
332+ bytes_next = 0 ;
333+ for (int i = 0 ; i < tail; ++i) {
334+ bytes_next |= static_cast <uint64_t >((bytes + num_bits - tail)[i]) << (8 * i);
335+ }
336+ }
337+ #endif
303338 bytes_next &= 0x0101010101010101ULL ;
304339 bytes_next |= (bytes_next >> 7 ); // Pairs of adjacent output bits in individual bytes
305340 bytes_next |= (bytes_next >> 14 ); // 4 adjacent output bits in individual bytes
0 commit comments