aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/marisa-trie/marisa/grimoire/vector/pop-count.h
blob: 6d04cf831dc66cec611d331fa65b0c320f0560be (plain) (blame)
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
#pragma once
#ifndef MARISA_GRIMOIRE_VECTOR_POP_COUNT_H_
#define MARISA_GRIMOIRE_VECTOR_POP_COUNT_H_

#include "../intrin.h"

namespace marisa {
namespace grimoire {
namespace vector {

#if MARISA_WORD_SIZE == 64

class PopCount {
 public:
  explicit PopCount(UInt64 x) : value_() {
    x = (x & 0x5555555555555555ULL) + ((x & 0xAAAAAAAAAAAAAAAAULL) >> 1);
    x = (x & 0x3333333333333333ULL) + ((x & 0xCCCCCCCCCCCCCCCCULL) >> 2);
    x = (x & 0x0F0F0F0F0F0F0F0FULL) + ((x & 0xF0F0F0F0F0F0F0F0ULL) >> 4);
    x *= 0x0101010101010101ULL;
    value_ = x;
  }

  std::size_t lo8() const {
    return (std::size_t)(value_ & 0xFFU);
  }
  std::size_t lo16() const {
    return (std::size_t)((value_ >> 8) & 0xFFU);
  }
  std::size_t lo24() const {
    return (std::size_t)((value_ >> 16) & 0xFFU);
  }
  std::size_t lo32() const {
    return (std::size_t)((value_ >> 24) & 0xFFU);
  }
  std::size_t lo40() const {
    return (std::size_t)((value_ >> 32) & 0xFFU);
  }
  std::size_t lo48() const {
    return (std::size_t)((value_ >> 40) & 0xFFU);
  }
  std::size_t lo56() const {
    return (std::size_t)((value_ >> 48) & 0xFFU);
  }
  std::size_t lo64() const {
    return (std::size_t)((value_ >> 56) & 0xFFU);
  }

  static std::size_t count(UInt64 x) {
#if defined(MARISA_X64) && defined(MARISA_USE_POPCNT)
 #ifdef _MSC_VER
    return __popcnt64(x);
 #else  // _MSC_VER
    return _mm_popcnt_u64(x);
 #endif  // _MSC_VER
#else  // defined(MARISA_X64) && defined(MARISA_USE_POPCNT)
    return PopCount(x).lo64();
#endif  // defined(MARISA_X64) && defined(MARISA_USE_POPCNT)
  }

 private:
  UInt64 value_;
};

#else  // MARISA_WORD_SIZE == 64

class PopCount {
 public:
  explicit PopCount(UInt32 x) : value_() {
    x = (x & 0x55555555U) + ((x & 0xAAAAAAAAU) >> 1);
    x = (x & 0x33333333U) + ((x & 0xCCCCCCCCU) >> 2);
    x = (x & 0x0F0F0F0FU) + ((x & 0xF0F0F0F0U) >> 4);
    x *= 0x01010101U;
    value_ = x;
  }

  std::size_t lo8() const {
    return value_ & 0xFFU;
  }
  std::size_t lo16() const {
    return (value_ >> 8) & 0xFFU;
  }
  std::size_t lo24() const {
    return (value_ >> 16) & 0xFFU;
  }
  std::size_t lo32() const {
    return (value_ >> 24) & 0xFFU;
  }

  static std::size_t count(UInt32 x) {
#ifdef MARISA_USE_POPCNT
 #ifdef _MSC_VER
    return __popcnt(x);
 #else  // _MSC_VER
    return _mm_popcnt_u32(x);
 #endif  // _MSC_VER
#else  // MARISA_USE_POPCNT
    return PopCount(x).lo32();
#endif  // MARISA_USE_POPCNT
  }

 private:
  UInt32 value_;
};

#endif  // MARISA_WORD_SIZE == 64

}  // namespace vector
}  // namespace grimoire
}  // namespace marisa

#endif  // MARISA_GRIMOIRE_VECTOR_POP_COUNT_H_