Blame view

tools/openfst-1.6.7/include/fst/pair-weight.h 4.3 KB
8dcb6dfcb   Yannick Estève   first commit
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  // See www.openfst.org for extensive documentation on this weighted
  // finite-state transducer library.
  //
  // Pair weight templated base class for weight classes that contain two weights
  // (e.g. Product, Lexicographic).
  
  #ifndef FST_PAIR_WEIGHT_H_
  #define FST_PAIR_WEIGHT_H_
  
  #include <climits>
  #include <stack>
  #include <string>
  #include <utility>
  
  #include <fst/flags.h>
  #include <fst/log.h>
  
  #include <fst/weight.h>
  
  
  namespace fst {
  
  template <class W1, class W2>
  class PairWeight {
   public:
    using ReverseWeight =
        PairWeight<typename W1::ReverseWeight, typename W2::ReverseWeight>;
  
    PairWeight() {}
  
    PairWeight(const PairWeight &weight)
        : value1_(weight.value1_), value2_(weight.value2_) {}
  
    PairWeight(W1 w1, W2 w2) : value1_(std::move(w1)), value2_(std::move(w2)) {}
  
    static const PairWeight<W1, W2> &Zero() {
      static const PairWeight zero(W1::Zero(), W2::Zero());
      return zero;
    }
  
    static const PairWeight<W1, W2> &One() {
      static const PairWeight one(W1::One(), W2::One());
      return one;
    }
  
    static const PairWeight<W1, W2> &NoWeight() {
      static const PairWeight no_weight(W1::NoWeight(), W2::NoWeight());
      return no_weight;
    }
  
    std::istream &Read(std::istream &strm) {
      value1_.Read(strm);
      return value2_.Read(strm);
    }
  
    std::ostream &Write(std::ostream &strm) const {
      value1_.Write(strm);
      return value2_.Write(strm);
    }
  
    PairWeight<W1, W2> &operator=(const PairWeight<W1, W2> &weight) {
      value1_ = weight.Value1();
      value2_ = weight.Value2();
      return *this;
    }
  
    bool Member() const { return value1_.Member() && value2_.Member(); }
  
    size_t Hash() const {
      const auto h1 = value1_.Hash();
      const auto h2 = value2_.Hash();
      static constexpr int lshift = 5;
      static constexpr int rshift = CHAR_BIT * sizeof(size_t) - 5;
      return h1 << lshift ^ h1 >> rshift ^ h2;
    }
  
    PairWeight<W1, W2> Quantize(float delta = kDelta) const {
      return PairWeight<W1, W2>(value1_.Quantize(delta), value2_.Quantize(delta));
    }
  
    ReverseWeight Reverse() const {
      return ReverseWeight(value1_.Reverse(), value2_.Reverse());
    }
  
    const W1 &Value1() const { return value1_; }
  
    const W2 &Value2() const { return value2_; }
  
    void SetValue1(const W1 &weight) { value1_ = weight; }
  
    void SetValue2(const W2 &weight) { value2_ = weight; }
  
   private:
    W1 value1_;
    W2 value2_;
  };
  
  template <class W1, class W2>
  inline bool operator==(const PairWeight<W1, W2> &w1,
                         const PairWeight<W1, W2> &w2) {
    return w1.Value1() == w2.Value1() && w1.Value2() == w2.Value2();
  }
  
  template <class W1, class W2>
  inline bool operator!=(const PairWeight<W1, W2> &w1,
                         const PairWeight<W1, W2> &w2) {
    return w1.Value1() != w2.Value1() || w1.Value2() != w2.Value2();
  }
  
  template <class W1, class W2>
  inline bool ApproxEqual(const PairWeight<W1, W2> &w1,
                          const PairWeight<W1, W2> &w2, float delta = kDelta) {
    return ApproxEqual(w1.Value1(), w2.Value1(), delta) &&
           ApproxEqual(w1.Value2(), w2.Value2(), delta);
  }
  
  template <class W1, class W2>
  inline std::ostream &operator<<(std::ostream &strm,
                                  const PairWeight<W1, W2> &weight) {
    CompositeWeightWriter writer(strm);
    writer.WriteBegin();
    writer.WriteElement(weight.Value1());
    writer.WriteElement(weight.Value2());
    writer.WriteEnd();
    return strm;
  }
  
  template <class W1, class W2>
  inline std::istream &operator>>(std::istream &strm,
                                  PairWeight<W1, W2> &weight) {
    CompositeWeightReader reader(strm);
    reader.ReadBegin();
    W1 w1;
    reader.ReadElement(&w1);
    weight.SetValue1(w1);
    W2 w2;
    reader.ReadElement(&w2, true);
    weight.SetValue2(w2);
    reader.ReadEnd();
    return strm;
  }
  
  // This function object returns weights by calling the underlying generators
  // and forming a pair. This is intended primarily for testing.
  template <class W1, class W2>
  class WeightGenerate<PairWeight<W1, W2>> {
   public:
    using Weight = PairWeight<W1, W2>;
    using Generate1 = WeightGenerate<W1>;
    using Generate2 = WeightGenerate<W2>;
  
    explicit WeightGenerate(bool allow_zero = true)
        : generate1_(allow_zero), generate2_(allow_zero) {}
  
    Weight operator()() const { return Weight(generate1_(), generate2_()); }
  
   private:
    Generate1 generate1_;
    Generate2 generate2_;
  };
  
  }  // namespace fst
  
  #endif  // FST_PAIR_WEIGHT_H_