FST  openfst-1.8.2
OpenFst Library
weight_test.cc
Go to the documentation of this file.
1 // Copyright 2005-2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the 'License');
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an 'AS IS' BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // See www.openfst.org for extensive documentation on this weighted
16 // finite-state transducer library.
17 //
18 // Regression test for FST weights.
19 
20 #include <cstdint>
21 
22 #include <fst/flags.h>
23 #include <fst/log.h>
24 #include <fst/expectation-weight.h>
25 #include <fst/float-weight.h>
27 #include <fst/power-weight.h>
28 #include <fst/product-weight.h>
29 #include <fst/set-weight.h>
30 #include <fst/signed-log-weight.h>
32 #include <fst/string-weight.h>
33 #include <fst/union-weight.h>
34 #include <fst/test/weight-tester.h>
35 
36 DEFINE_uint64(seed, 403, "random seed");
37 DEFINE_int32(repeat, 10000, "number of test repetitions");
38 
39 namespace {
40 
41 using fst::Adder;
43 using fst::GALLIC;
44 using fst::GallicWeight;
46 using fst::LogWeight;
47 using fst::LogWeightTpl;
48 using fst::MinMaxWeight;
50 using fst::NaturalLess;
51 using fst::PowerWeight;
52 using fst::ProductWeight;
53 using fst::RealWeight;
54 using fst::RealWeightTpl;
55 using fst::SET_BOOLEAN;
58 using fst::SetWeight;
62 using fst::STRING_RIGHT;
63 using fst::StringWeight;
66 using fst::UnionWeight;
67 using fst::WeightConvert;
69 using fst::WeightTester;
70 
71 template <class T>
72 void TestTemplatedWeights(uint64_t seed, int repeat) {
73  WeightGenerate<TropicalWeightTpl<T>> tropical_generate(seed);
74  WeightTester<TropicalWeightTpl<T>> tropical_tester(tropical_generate);
75  tropical_tester.Test(repeat);
76 
77  WeightGenerate<LogWeightTpl<T>> log_generate(seed);
78  WeightTester<LogWeightTpl<T>> log_tester(log_generate);
79  log_tester.Test(repeat);
80 
81  WeightGenerate<RealWeightTpl<T>> real_generate(seed);
82  WeightTester<RealWeightTpl<T>> real_tester(real_generate);
83  real_tester.Test(repeat);
84 
85  WeightGenerate<MinMaxWeightTpl<T>> minmax_generate(seed, true);
86  WeightTester<MinMaxWeightTpl<T>> minmax_tester(minmax_generate);
87  minmax_tester.Test(repeat);
88 
89  WeightGenerate<SignedLogWeightTpl<T>> signedlog_generate(seed, true);
90  WeightTester<SignedLogWeightTpl<T>> signedlog_tester(signedlog_generate);
91  signedlog_tester.Test(repeat);
92 }
93 
94 template <class Weight>
95 void TestAdder(int n) {
96  Weight sum = Weight::Zero();
97  Adder<Weight> adder;
98  for (int i = 0; i < n; ++i) {
99  sum = Plus(sum, Weight::One());
100  adder.Add(Weight::One());
101  }
102  CHECK(ApproxEqual(sum, adder.Sum()));
103 }
104 
105 template <class Weight>
106 void TestSignedAdder(int n) {
107  Weight sum = Weight::Zero();
108  Adder<Weight> adder;
109  const Weight minus_one = Minus(Weight::Zero(), Weight::One());
110  for (int i = 0; i < n; ++i) {
111  if (i < n / 4 || i > 3 * n / 4) {
112  sum = Plus(sum, Weight::One());
113  adder.Add(Weight::One());
114  } else {
115  sum = Minus(sum, Weight::One());
116  adder.Add(minus_one);
117  }
118  }
119  CHECK(ApproxEqual(sum, adder.Sum()));
120 }
121 
122 template <typename Weight1, typename Weight2>
123 void TestWeightConversion(Weight1 w1) {
124  // Tests round-trp conversion.
125  const WeightConvert<Weight2, Weight1> to_w1_;
126  const WeightConvert<Weight1, Weight2> to_w2_;
127  Weight2 w2 = to_w2_(w1);
128  Weight1 nw1 = to_w1_(w2);
129  CHECK_EQ(w1, nw1);
130 }
131 
132 template <typename FromWeight, typename ToWeight>
133 void TestWeightCopy(FromWeight w) {
134  // Test copy constructor.
135  const ToWeight to_copied(w);
136  const FromWeight roundtrip_copied(to_copied);
137  CHECK_EQ(w, roundtrip_copied);
138 
139  // Test copy assign.
140  ToWeight to_copy_assigned;
141  to_copy_assigned = w;
142  CHECK_EQ(to_copied, to_copy_assigned);
143 
144  FromWeight roundtrip_copy_assigned;
145  roundtrip_copy_assigned = to_copy_assigned;
146  CHECK_EQ(w, roundtrip_copy_assigned);
147 }
148 
149 template <typename FromWeight, typename ToWeight>
150 void TestWeightMove(FromWeight w) {
151  // Assume FromWeight -> FromWeight copy works.
152  const FromWeight orig(w);
153  ToWeight to_moved(std::move(w));
154  const FromWeight roundtrip_moved(std::move(to_moved));
155  CHECK_EQ(orig, roundtrip_moved);
156 
157  // Test move assign.
158  w = orig;
159  ToWeight to_move_assigned;
160  to_move_assigned = std::move(w);
161  FromWeight roundtrip_move_assigned;
162  roundtrip_move_assigned = std::move(to_move_assigned);
163  CHECK_EQ(orig, roundtrip_move_assigned);
164 }
165 
166 template <class Weight>
167 void TestImplicitConversion() {
168  // Only test a few of the operations; assumes they are implemented with the
169  // same pattern.
170  CHECK(Weight(2.0f) == 2.0f);
171  CHECK(Weight(2.0) == 2.0);
172  CHECK(2.0f == Weight(2.0f));
173  CHECK(2.0 == Weight(2.0));
174 
175  CHECK_EQ(Weight::Zero(), Times(Weight::Zero(), 3.0f));
176  CHECK_EQ(Weight::Zero(), Times(Weight::Zero(), 3.0));
177  CHECK_EQ(Weight::Zero(), Times(3.0, Weight::Zero()));
178 
179  CHECK_EQ(Weight(3.0), Plus(Weight::Zero(), 3.0f));
180  CHECK_EQ(Weight(3.0), Plus(Weight::Zero(), 3.0));
181  CHECK_EQ(Weight(3.0), Plus(3.0, Weight::Zero()));
182 }
183 
184 void TestPowerWeightGetSetValue() {
185  PowerWeight<LogWeight, 3> w;
186  // LogWeight has unspecified initial value, so don't check it.
187  w.SetValue(0, LogWeight(2));
188  w.SetValue(1, LogWeight(3));
189  CHECK_EQ(LogWeight(2), w.Value(0));
190  CHECK_EQ(LogWeight(3), w.Value(1));
191 }
192 
193 void TestSparsePowerWeightGetSetValue() {
194  const LogWeight default_value(17);
195  SparsePowerWeight<LogWeight> w;
196  w.SetDefaultValue(default_value);
197 
198  // All gets should be the default.
199  CHECK_EQ(default_value, w.Value(0));
200  CHECK_EQ(default_value, w.Value(100));
201 
202  // First set should fill first_.
203  w.SetValue(10, LogWeight(10));
204  CHECK_EQ(LogWeight(10), w.Value(10));
205  w.SetValue(10, LogWeight(20));
206  CHECK_EQ(LogWeight(20), w.Value(10));
207 
208  // Add a smaller index.
209  w.SetValue(5, LogWeight(5));
210  CHECK_EQ(LogWeight(5), w.Value(5));
211  CHECK_EQ(LogWeight(20), w.Value(10));
212 
213  // Add some larger indices.
214  w.SetValue(30, LogWeight(30));
215  CHECK_EQ(LogWeight(5), w.Value(5));
216  CHECK_EQ(LogWeight(20), w.Value(10));
217  CHECK_EQ(LogWeight(30), w.Value(30));
218 
219  w.SetValue(29, LogWeight(29));
220  CHECK_EQ(LogWeight(5), w.Value(5));
221  CHECK_EQ(LogWeight(20), w.Value(10));
222  CHECK_EQ(LogWeight(29), w.Value(29));
223  CHECK_EQ(LogWeight(30), w.Value(30));
224 
225  w.SetValue(31, LogWeight(31));
226  CHECK_EQ(LogWeight(5), w.Value(5));
227  CHECK_EQ(LogWeight(20), w.Value(10));
228  CHECK_EQ(LogWeight(29), w.Value(29));
229  CHECK_EQ(LogWeight(30), w.Value(30));
230  CHECK_EQ(LogWeight(31), w.Value(31));
231 
232  // Replace a value.
233  w.SetValue(30, LogWeight(60));
234  CHECK_EQ(LogWeight(60), w.Value(30));
235 
236  // Replace a value with the default.
237  CHECK_EQ(5, w.Size());
238  w.SetValue(30, default_value);
239  CHECK_EQ(default_value, w.Value(30));
240  CHECK_EQ(4, w.Size());
241 
242  // Replace lowest index by the default value.
243  w.SetValue(5, default_value);
244  CHECK_EQ(default_value, w.Value(5));
245  CHECK_EQ(3, w.Size());
246 
247  // Clear out everything.
248  w.SetValue(31, default_value);
249  w.SetValue(29, default_value);
250  w.SetValue(10, default_value);
251  CHECK_EQ(0, w.Size());
252 
253  CHECK_EQ(default_value, w.Value(5));
254  CHECK_EQ(default_value, w.Value(10));
255  CHECK_EQ(default_value, w.Value(29));
256  CHECK_EQ(default_value, w.Value(30));
257  CHECK_EQ(default_value, w.Value(31));
258 }
259 
260 // If this test fails, it is possible that x == x will not
261 // hold for FloatWeight, breaking NaturalLess and probably more.
262 // To trigger these failures, use g++ -O -m32 -mno-sse.
263 template <class T>
264 bool FloatEqualityIsReflexive(T m) {
265  // The idea here is that x is spilled to memory, but
266  // y remains in an 80-bit register with extra precision,
267  // causing it to compare unequal to x.
268  volatile T x = 1.111;
269  x *= m;
270 
271  T y = 1.111;
272  y *= m;
273 
274  return x == y;
275 }
276 
277 void TestFloatEqualityIsReflexive() {
278  // Use a volatile test_value to avoid excessive inlining / optimization
279  // breaking what we're trying to test.
280  volatile double test_value = 1.1;
281  CHECK(FloatEqualityIsReflexive(static_cast<float>(test_value)));
282  CHECK(FloatEqualityIsReflexive(test_value));
283 }
284 
285 } // namespace
286 
287 int main(int argc, char **argv) {
288  std::set_new_handler(FailedNewHandler);
289  SET_FLAGS(argv[0], &argc, &argv, true);
290 
291  TestTemplatedWeights<float>(FST_FLAGS_seed,
292  FST_FLAGS_repeat);
293  TestTemplatedWeights<double>(FST_FLAGS_seed,
294  FST_FLAGS_repeat);
295  SetFlag(&FST_FLAGS_fst_weight_parentheses, "()");
296  TestTemplatedWeights<float>(FST_FLAGS_seed,
297  FST_FLAGS_repeat);
298  TestTemplatedWeights<double>(FST_FLAGS_seed,
299  FST_FLAGS_repeat);
300  SetFlag(&FST_FLAGS_fst_weight_parentheses, "");
301 
302  // Makes sure type names for templated weights are consistent.
303  CHECK_EQ(TropicalWeight::Type(), "tropical");
304  CHECK(TropicalWeightTpl<double>::Type() != TropicalWeightTpl<float>::Type());
305  CHECK_EQ(LogWeight::Type(), "log");
306  CHECK(LogWeightTpl<double>::Type() != LogWeightTpl<float>::Type());
307  CHECK_EQ(RealWeight::Type(), "real");
308  CHECK(RealWeightTpl<double>::Type() != RealWeightTpl<float>::Type());
309  TropicalWeightTpl<double> w(2.0);
310  TropicalWeight tw(2.0);
311  CHECK_EQ(w.Value(), tw.Value());
312 
313  TestAdder<TropicalWeight>(1000);
314  TestAdder<LogWeight>(1000);
315  TestAdder<RealWeight>(1000);
316  TestSignedAdder<SignedLogWeight>(1000);
317 
318  TestImplicitConversion<TropicalWeight>();
319  TestImplicitConversion<LogWeight>();
320  TestImplicitConversion<RealWeight>();
321  TestImplicitConversion<MinMaxWeight>();
322 
323  TestWeightConversion<TropicalWeight, LogWeight>(2.0);
324 
325  using LeftStringWeight = StringWeight<int>;
326  WeightGenerate<LeftStringWeight> left_string_generate(
327  FST_FLAGS_seed);
328  WeightTester<LeftStringWeight> left_string_tester(left_string_generate);
329  left_string_tester.Test(FST_FLAGS_repeat);
330 
331  using RightStringWeight = StringWeight<int, STRING_RIGHT>;
332  WeightGenerate<RightStringWeight> right_string_generate(
333  FST_FLAGS_seed);
334  WeightTester<RightStringWeight> right_string_tester(right_string_generate);
335  right_string_tester.Test(FST_FLAGS_repeat);
336 
337  // STRING_RESTRICT not tested since it requires equal strings,
338  // so would fail.
339 
340  using IUSetWeight = SetWeight<int, SET_INTERSECT_UNION>;
341  WeightGenerate<IUSetWeight> iu_set_generate(FST_FLAGS_seed);
342  WeightTester<IUSetWeight> iu_set_tester(iu_set_generate);
343  iu_set_tester.Test(FST_FLAGS_repeat);
344 
345  using UISetWeight = SetWeight<int, SET_UNION_INTERSECT>;
346  WeightGenerate<UISetWeight> ui_set_generate(FST_FLAGS_seed);
347  WeightTester<UISetWeight> ui_set_tester(ui_set_generate);
348  ui_set_tester.Test(FST_FLAGS_repeat);
349 
350  // SET_INTERSECT_UNION_RESTRICT not tested since it requires equal sets,
351  // so would fail.
352 
353  using BoolSetWeight = SetWeight<int, SET_BOOLEAN>;
354  WeightGenerate<BoolSetWeight> bool_set_generate(FST_FLAGS_seed);
355  WeightTester<BoolSetWeight> bool_set_tester(bool_set_generate);
356  bool_set_tester.Test(FST_FLAGS_repeat);
357 
358  TestWeightConversion<IUSetWeight, UISetWeight>(iu_set_generate());
359 
360  TestWeightCopy<IUSetWeight, UISetWeight>(iu_set_generate());
361  TestWeightCopy<IUSetWeight, BoolSetWeight>(iu_set_generate());
362  TestWeightCopy<UISetWeight, IUSetWeight>(ui_set_generate());
363  TestWeightCopy<UISetWeight, BoolSetWeight>(ui_set_generate());
364  TestWeightCopy<BoolSetWeight, IUSetWeight>(bool_set_generate());
365  TestWeightCopy<BoolSetWeight, UISetWeight>(bool_set_generate());
366 
367  TestWeightMove<IUSetWeight, UISetWeight>(iu_set_generate());
368  TestWeightMove<IUSetWeight, BoolSetWeight>(iu_set_generate());
369  TestWeightMove<UISetWeight, IUSetWeight>(ui_set_generate());
370  TestWeightMove<UISetWeight, BoolSetWeight>(ui_set_generate());
371  TestWeightMove<BoolSetWeight, IUSetWeight>(bool_set_generate());
372  TestWeightMove<BoolSetWeight, UISetWeight>(bool_set_generate());
373 
374  // COMPOSITE WEIGHTS AND TESTERS - DEFINITIONS
375 
376  using TropicalGallicWeight = GallicWeight<int, TropicalWeight>;
377  WeightGenerate<TropicalGallicWeight> tropical_gallic_generate(
378  FST_FLAGS_seed, true);
379  WeightTester<TropicalGallicWeight> tropical_gallic_tester(
380  tropical_gallic_generate);
381 
382  using TropicalGenGallicWeight = GallicWeight<int, TropicalWeight, GALLIC>;
383  WeightGenerate<TropicalGenGallicWeight> tropical_gen_gallic_generate(
384  FST_FLAGS_seed, false);
385  WeightTester<TropicalGenGallicWeight> tropical_gen_gallic_tester(
386  tropical_gen_gallic_generate);
387 
388  using TropicalProductWeight = ProductWeight<TropicalWeight, TropicalWeight>;
389  WeightGenerate<TropicalProductWeight> tropical_product_generate(
390  FST_FLAGS_seed);
391  WeightTester<TropicalProductWeight> tropical_product_tester(
392  tropical_product_generate);
393 
394  using TropicalLexicographicWeight =
395  LexicographicWeight<TropicalWeight, TropicalWeight>;
396  WeightGenerate<TropicalLexicographicWeight> tropical_lexicographic_generate(
397  FST_FLAGS_seed);
398  WeightTester<TropicalLexicographicWeight> tropical_lexicographic_tester(
399  tropical_lexicographic_generate);
400 
401  using TropicalCubeWeight = PowerWeight<TropicalWeight, 3>;
402  WeightGenerate<TropicalCubeWeight> tropical_cube_generate(
403  FST_FLAGS_seed);
404  WeightTester<TropicalCubeWeight> tropical_cube_tester(tropical_cube_generate);
405 
406  using FirstNestedProductWeight =
407  ProductWeight<TropicalProductWeight, TropicalWeight>;
408  WeightGenerate<FirstNestedProductWeight> first_nested_product_generate(
409  FST_FLAGS_seed);
410  WeightTester<FirstNestedProductWeight> first_nested_product_tester(
411  first_nested_product_generate);
412 
413  using SecondNestedProductWeight =
414  ProductWeight<TropicalWeight, TropicalProductWeight>;
415  WeightGenerate<SecondNestedProductWeight> second_nested_product_generate(
416  FST_FLAGS_seed);
417  WeightTester<SecondNestedProductWeight> second_nested_product_tester(
418  second_nested_product_generate);
419 
420  using NestedProductCubeWeight = PowerWeight<FirstNestedProductWeight, 3>;
421  WeightGenerate<NestedProductCubeWeight> nested_product_cube_generate(
422  FST_FLAGS_seed);
423  WeightTester<NestedProductCubeWeight> nested_product_cube_tester(
424  nested_product_cube_generate);
425 
426  using SparseNestedProductCubeWeight =
427  SparsePowerWeight<NestedProductCubeWeight, size_t>;
428  WeightGenerate<SparseNestedProductCubeWeight>
429  sparse_nested_product_cube_generate(FST_FLAGS_seed);
430  WeightTester<SparseNestedProductCubeWeight> sparse_nested_product_cube_tester(
431  sparse_nested_product_cube_generate);
432 
433  using LogSparsePowerWeight = SparsePowerWeight<LogWeight, size_t>;
434  WeightGenerate<LogSparsePowerWeight> log_sparse_power_generate(
435  FST_FLAGS_seed);
436  WeightTester<LogSparsePowerWeight> log_sparse_power_tester(
437  log_sparse_power_generate);
438 
439  using LogLogExpectationWeight = ExpectationWeight<LogWeight, LogWeight>;
440  WeightGenerate<LogLogExpectationWeight> log_log_expectation_generate(
441  FST_FLAGS_seed);
442  WeightTester<LogLogExpectationWeight> log_log_expectation_tester(
443  log_log_expectation_generate);
444 
445  using RealRealExpectationWeight = ExpectationWeight<RealWeight, RealWeight>;
446  WeightGenerate<RealRealExpectationWeight> real_real_expectation_generate(
447  FST_FLAGS_seed);
448  WeightTester<RealRealExpectationWeight> real_real_expectation_tester(
449  real_real_expectation_generate);
450 
451  using LogLogSparseExpectationWeight =
452  ExpectationWeight<LogWeight, LogSparsePowerWeight>;
453  WeightGenerate<LogLogSparseExpectationWeight>
454  log_log_sparse_expectation_generate(FST_FLAGS_seed);
455  WeightTester<LogLogSparseExpectationWeight> log_log_sparse_expectation_tester(
456  log_log_sparse_expectation_generate);
457 
458  struct UnionWeightOptions {
459  using Compare = NaturalLess<TropicalWeight>;
460 
461  struct Merge {
462  TropicalWeight operator()(const TropicalWeight &w1,
463  const TropicalWeight &w2) const {
464  return w1;
465  }
466  };
467 
468  using ReverseOptions = UnionWeightOptions;
469  };
470 
471  using TropicalUnionWeight = UnionWeight<TropicalWeight, UnionWeightOptions>;
472  WeightGenerate<TropicalUnionWeight> tropical_union_generate(
473  FST_FLAGS_seed);
474  WeightTester<TropicalUnionWeight> tropical_union_tester(
475  tropical_union_generate);
476 
477  // COMPOSITE WEIGHTS AND TESTERS - TESTING
478 
479  // Tests composite weight I/O with parentheses.
480  SetFlag(&FST_FLAGS_fst_weight_parentheses, "()");
481 
482  // Unnested composite.
483  tropical_gallic_tester.Test(FST_FLAGS_repeat);
484  tropical_gen_gallic_tester.Test(FST_FLAGS_repeat);
485  tropical_product_tester.Test(FST_FLAGS_repeat);
486  tropical_lexicographic_tester.Test(FST_FLAGS_repeat);
487  tropical_cube_tester.Test(FST_FLAGS_repeat);
488  log_sparse_power_tester.Test(FST_FLAGS_repeat);
489  log_log_expectation_tester.Test(FST_FLAGS_repeat);
490  real_real_expectation_tester.Test(FST_FLAGS_repeat);
491  tropical_union_tester.Test(FST_FLAGS_repeat);
492 
493  // Nested composite.
494  first_nested_product_tester.Test(FST_FLAGS_repeat);
495  second_nested_product_tester.Test(5);
496  nested_product_cube_tester.Test(FST_FLAGS_repeat);
497  sparse_nested_product_cube_tester.Test(FST_FLAGS_repeat);
498  log_log_sparse_expectation_tester.Test(FST_FLAGS_repeat);
499 
500  // ... and tests composite weight I/O without parentheses.
501  SetFlag(&FST_FLAGS_fst_weight_parentheses, "");
502 
503  // Unnested composite.
504  tropical_gallic_tester.Test(FST_FLAGS_repeat);
505  tropical_product_tester.Test(FST_FLAGS_repeat);
506  tropical_lexicographic_tester.Test(FST_FLAGS_repeat);
507  tropical_cube_tester.Test(FST_FLAGS_repeat);
508  log_sparse_power_tester.Test(FST_FLAGS_repeat);
509  log_log_expectation_tester.Test(FST_FLAGS_repeat);
510  tropical_union_tester.Test(FST_FLAGS_repeat);
511 
512  // Nested composite.
513  second_nested_product_tester.Test(FST_FLAGS_repeat);
514  log_log_sparse_expectation_tester.Test(FST_FLAGS_repeat);
515 
516  TestPowerWeightGetSetValue();
517  TestSparsePowerWeightGetSetValue();
518 
519  TestFloatEqualityIsReflexive();
520 
521  return 0;
522 }
RealWeightTpl< float > RealWeight
Definition: float-weight.h:708
ErrorWeight Plus(const ErrorWeight &, const ErrorWeight &)
Definition: error-weight.h:60
DEFINE_int32(repeat, 10000,"number of test repetitions")
ErrorWeight Times(const ErrorWeight &, const ErrorWeight &)
Definition: error-weight.h:63
int main(int argc, char **argv)
Definition: weight_test.cc:287
void FailedNewHandler()
Definition: compat.cc:26
#define SET_FLAGS(usage, argc, argv, rmflags)
Definition: flags.h:224
LogWeightTpl< float > LogWeight
Definition: float-weight.h:465
TropicalWeightTpl< float > TropicalWeight
Definition: float-weight.h:264
MinMaxWeightTpl< float > MinMaxWeight
Definition: float-weight.h:908
#define CHECK_EQ(x, y)
Definition: log.h:62
LogWeightTpl< T > Minus(const LogWeightTpl< T > &w1, const LogWeightTpl< T > &w2)
Definition: float-weight.h:539
DEFINE_uint64(seed, 403,"random seed")
void SetFlag(Type *flag, Value value)
Definition: flags.h:220
#define CHECK(x)
Definition: log.h:61
SignedLogWeightTpl< float > SignedLogWeight
bool ApproxEqual(const ErrorWeight &, const ErrorWeight &, float)
Definition: error-weight.h:57