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