1f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// sparse-power-weight.h
2f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
3f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Licensed under the Apache License, Version 2.0 (the "License");
4f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// you may not use this file except in compliance with the License.
5f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// You may obtain a copy of the License at
6f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
7f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     http://www.apache.org/licenses/LICENSE-2.0
8f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
9f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Unless required by applicable law or agreed to in writing, software
10f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// distributed under the License is distributed on an "AS IS" BASIS,
11f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// See the License for the specific language governing permissions and
13f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// limitations under the License.
14f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
15f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Copyright 2005-2010 Google, Inc.
16f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Author: krr@google.com (Kasturi Rangan Raghavan)
17f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Inspiration: allauzen@google.com (Cyril Allauzen)
18f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
19f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// \file
20f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Cartesian power weight semiring operation definitions.
21f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Uses SparseTupleWeight as underlying representation.
22f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
23f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#ifndef FST_LIB_SPARSE_POWER_WEIGHT_H__
24f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define FST_LIB_SPARSE_POWER_WEIGHT_H__
25f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
26f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include<string>
27f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
28f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/sparse-tuple-weight.h>
29f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/weight.h>
30f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
31f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
32f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace fst {
33f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
34f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Below SparseTupleWeight*Mapper are used in conjunction with
35f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// SparseTupleWeightMap to compute the respective semiring operations
36f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class W, class K>
37f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct SparseTupleWeightPlusMapper {
38f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  W Map(const K& k, const W& v1, const W& v2) const {
39f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return Plus(v1, v2);
40f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
41f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
42f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
43f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class W, class K>
44f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct SparseTupleWeightTimesMapper {
45f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  W Map(const K& k, const W& v1, const W& v2) const {
46f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return Times(v1, v2);
47f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
48f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
49f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
50f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class W, class K>
51f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct SparseTupleWeightDivideMapper {
52f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparseTupleWeightDivideMapper(DivideType divide_type) {
53f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    divide_type_ = divide_type;
54f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
55f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  W Map(const K& k, const W& v1, const W& v2) const {
56f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return Divide(v1, v2, divide_type_);
57f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
58f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  DivideType divide_type_;
59f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
60f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
61f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class W, class K>
62f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct SparseTupleWeightApproxMapper {
63f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparseTupleWeightApproxMapper(float delta) { delta_ = delta; }
64f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  W Map(const K& k, const W& v1, const W& v2) const {
65f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return ApproxEqual(v1, v2, delta_) ? W::One() : W::Zero();
66f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
67f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  float delta_;
68f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
69f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
70f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Sparse cartesian power semiring: W ^ n
71f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Forms:
72f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  - a left semimodule when W is a left semiring,
73f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  - a right semimodule when W is a right semiring,
74f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  - a bisemimodule when W is a semiring,
75f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//    the free semimodule of rank n over W
76f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// The Times operation is overloaded to provide the
77f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// left and right scalar products.
78f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// K is the key value type. kNoKey(-1) is reserved for internal use
79f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, class K = int>
80f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass SparsePowerWeight : public SparseTupleWeight<W, K> {
81f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
82f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using SparseTupleWeight<W, K>::Zero;
83f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using SparseTupleWeight<W, K>::One;
84f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using SparseTupleWeight<W, K>::NoWeight;
85f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using SparseTupleWeight<W, K>::Quantize;
86f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using SparseTupleWeight<W, K>::Reverse;
87f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
88f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef SparsePowerWeight<typename W::ReverseWeight, K> ReverseWeight;
89f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
90f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparsePowerWeight() {}
91f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
92f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparsePowerWeight(const SparseTupleWeight<W, K> &w) :
93f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    SparseTupleWeight<W, K>(w) { }
94f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
95f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  template <class Iterator>
96f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparsePowerWeight(Iterator begin, Iterator end) :
97f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    SparseTupleWeight<W, K>(begin, end) { }
98f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
99f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparsePowerWeight(const K &key, const W &w) :
100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    SparseTupleWeight<W, K>(key, w) { }
101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const SparsePowerWeight<W, K> &Zero() {
103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static const SparsePowerWeight<W, K> zero(SparseTupleWeight<W, K>::Zero());
104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return zero;
105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const SparsePowerWeight<W, K> &One() {
108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static const SparsePowerWeight<W, K> one(SparseTupleWeight<W, K>::One());
109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return one;
110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const SparsePowerWeight<W, K> &NoWeight() {
113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static const SparsePowerWeight<W, K> no_weight(
114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        SparseTupleWeight<W, K>::NoWeight());
115f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return no_weight;
116f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
117f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
118f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Overide this: Overwrite the Type method to reflect the key type
119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // if using non-default key type.
120f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const string &Type() {
121f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static string type;
122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if(type.empty()) {
123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      type = W::Type() + "_^n";
124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if(sizeof(K) != sizeof(uint32)) {
125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        string size;
126f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        Int64ToStr(8 * sizeof(K), &size);
127f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        type += "_" + size;
128f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
129f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return type;
131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static uint64 Properties() {
134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    uint64 props = W::Properties();
135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return props & (kLeftSemiring | kRightSemiring |
136f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                    kCommutative | kIdempotent);
137f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
138f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
139f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparsePowerWeight<W, K> Quantize(float delta = kDelta) const {
140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SparseTupleWeight<W, K>::Quantize(delta);
141f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
142f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
143f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ReverseWeight Reverse() const {
144f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SparseTupleWeight<W, K>::Reverse();
145f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
146f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
147f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
148f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Semimodule plus operation
149f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, class K>
150f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline SparsePowerWeight<W, K> Plus(const SparsePowerWeight<W, K> &w1,
151f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                    const SparsePowerWeight<W, K> &w2) {
152f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparsePowerWeight<W, K> ret;
153f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparseTupleWeightPlusMapper<W, K> operator_mapper;
154f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparseTupleWeightMap(&ret, w1, w2, operator_mapper);
155f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return ret;
156f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
157f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
158f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Semimodule times operation
159f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, class K>
160f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline SparsePowerWeight<W, K> Times(const SparsePowerWeight<W, K> &w1,
161f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                     const SparsePowerWeight<W, K> &w2) {
162f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparsePowerWeight<W, K> ret;
163f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparseTupleWeightTimesMapper<W, K> operator_mapper;
164f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparseTupleWeightMap(&ret, w1, w2, operator_mapper);
165f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return ret;
166f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
167f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
168f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Semimodule divide operation
169f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, class K>
170f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline SparsePowerWeight<W, K> Divide(const SparsePowerWeight<W, K> &w1,
171f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                      const SparsePowerWeight<W, K> &w2,
172f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                      DivideType type = DIVIDE_ANY) {
173f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparsePowerWeight<W, K> ret;
174f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparseTupleWeightDivideMapper<W, K> operator_mapper(type);
175f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparseTupleWeightMap(&ret, w1, w2, operator_mapper);
176f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return ret;
177f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
178f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
179f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Semimodule dot product
180f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, class K>
181f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline const W& DotProduct(const SparsePowerWeight<W, K> &w1,
182f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                    const SparsePowerWeight<W, K> &w2) {
183f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const SparsePowerWeight<W, K>& product = Times(w1, w2);
184f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  W ret(W::Zero());
185f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  for (SparseTupleWeightIterator<W, K> it(product); !it.Done(); it.Next()) {
186f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ret = Plus(ret, it.Value().second);
187f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
188f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return ret;
189f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
190f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
191f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, class K>
192f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline bool ApproxEqual(const SparsePowerWeight<W, K> &w1,
193f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                        const SparsePowerWeight<W, K> &w2,
194f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                        float delta = kDelta) {
195f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparseTupleWeight<W, K> ret;
196f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparseTupleWeightApproxMapper<W, K> operator_mapper(kDelta);
197f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparseTupleWeightMap(&ret, w1, w2, operator_mapper);
198f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return ret == SparsePowerWeight<W, K>::One();
199f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
200f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
201f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, class K>
202f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline SparsePowerWeight<W, K> Times(const W &k,
203f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                     const SparsePowerWeight<W, K> &w2) {
204f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparsePowerWeight<W, K> w1(k);
205f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Times(w1, w2);
206f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
207f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
208f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, class K>
209f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline SparsePowerWeight<W, K> Times(const SparsePowerWeight<W, K> &w1,
210f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                     const W &k) {
211f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparsePowerWeight<W, K> w2(k);
212f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Times(w1, w2);
213f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
214f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
215f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, class K>
216f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline SparsePowerWeight<W, K> Divide(const SparsePowerWeight<W, K> &w1,
217f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                      const W &k,
218f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                      DivideType divide_type = DIVIDE_ANY) {
219f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SparsePowerWeight<W, K> w2(k);
220f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Divide(w1, w2, divide_type);
221f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
222f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
223f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}  // namespace fst
224f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
225f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#endif  // FST_LIB_SPARSE_POWER_WEIGHT_H__
226