You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

531 lines
22 KiB

  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. // FST property bits.
  19. #ifndef FST_PROPERTIES_H_
  20. #define FST_PROPERTIES_H_
  21. #include <sys/types.h>
  22. #include <cstddef>
  23. #include <cstdint>
  24. #include <vector>
  25. #include <fst/compat.h>
  26. #include <fst/log.h>
  27. #include <string_view>
  28. namespace fst {
  29. // The property bits here assert facts about an FST. If individual bits are
  30. // added, then the composite properties below, the property functions and
  31. // property names in properties.cc, and TestProperties() in test-properties.h
  32. // should be updated.
  33. // BINARY PROPERTIES
  34. //
  35. // For each property below, there is a single bit. If it is set, the property is
  36. // true. If it is not set, the property is false.
  37. // The Fst is an ExpandedFst.
  38. inline constexpr uint64_t kExpanded = 0x0000000000000001ULL;
  39. // The Fst is a MutableFst.
  40. inline constexpr uint64_t kMutable = 0x0000000000000002ULL;
  41. // An error was detected while constructing/using the FST.
  42. inline constexpr uint64_t kError = 0x0000000000000004ULL;
  43. // TRINARY PROPERTIES
  44. //
  45. // For each of these properties below there is a pair of property bits, one
  46. // positive and one negative. If the positive bit is set, the property is true.
  47. // If the negative bit is set, the property is false. If neither is set, the
  48. // property has unknown value. Both should never be simultaneously set. The
  49. // individual positive and negative bit pairs should be adjacent with the
  50. // positive bit at an odd and lower position.
  51. // ilabel == olabel for each arc.
  52. inline constexpr uint64_t kAcceptor = 0x0000000000010000ULL;
  53. // ilabel != olabel for some arc.
  54. inline constexpr uint64_t kNotAcceptor = 0x0000000000020000ULL;
  55. // ilabels unique leaving each state.
  56. inline constexpr uint64_t kIDeterministic = 0x0000000000040000ULL;
  57. // ilabels not unique leaving some state.
  58. inline constexpr uint64_t kNonIDeterministic = 0x0000000000080000ULL;
  59. // olabels unique leaving each state.
  60. inline constexpr uint64_t kODeterministic = 0x0000000000100000ULL;
  61. // olabels not unique leaving some state.
  62. inline constexpr uint64_t kNonODeterministic = 0x0000000000200000ULL;
  63. // FST has input/output epsilons.
  64. inline constexpr uint64_t kEpsilons = 0x0000000000400000ULL;
  65. // FST has no input/output epsilons.
  66. inline constexpr uint64_t kNoEpsilons = 0x0000000000800000ULL;
  67. // FST has input epsilons.
  68. inline constexpr uint64_t kIEpsilons = 0x0000000001000000ULL;
  69. // FST has no input epsilons.
  70. inline constexpr uint64_t kNoIEpsilons = 0x0000000002000000ULL;
  71. // FST has output epsilons.
  72. inline constexpr uint64_t kOEpsilons = 0x0000000004000000ULL;
  73. // FST has no output epsilons.
  74. inline constexpr uint64_t kNoOEpsilons = 0x0000000008000000ULL;
  75. // ilabels sorted wrt < for each state.
  76. inline constexpr uint64_t kILabelSorted = 0x0000000010000000ULL;
  77. // ilabels not sorted wrt < for some state.
  78. inline constexpr uint64_t kNotILabelSorted = 0x0000000020000000ULL;
  79. // olabels sorted wrt < for each state.
  80. inline constexpr uint64_t kOLabelSorted = 0x0000000040000000ULL;
  81. // olabels not sorted wrt < for some state.
  82. inline constexpr uint64_t kNotOLabelSorted = 0x0000000080000000ULL;
  83. // Non-trivial arc or final weights.
  84. inline constexpr uint64_t kWeighted = 0x0000000100000000ULL;
  85. // Only trivial arc and final weights.
  86. inline constexpr uint64_t kUnweighted = 0x0000000200000000ULL;
  87. // FST has cycles.
  88. inline constexpr uint64_t kCyclic = 0x0000000400000000ULL;
  89. // FST has no cycles.
  90. inline constexpr uint64_t kAcyclic = 0x0000000800000000ULL;
  91. // FST has cycles containing the initial state.
  92. inline constexpr uint64_t kInitialCyclic = 0x0000001000000000ULL;
  93. // FST has no cycles containing the initial state.
  94. inline constexpr uint64_t kInitialAcyclic = 0x0000002000000000ULL;
  95. // FST is topologically sorted.
  96. inline constexpr uint64_t kTopSorted = 0x0000004000000000ULL;
  97. // FST is not topologically sorted.
  98. inline constexpr uint64_t kNotTopSorted = 0x0000008000000000ULL;
  99. // All states reachable from the initial state.
  100. inline constexpr uint64_t kAccessible = 0x0000010000000000ULL;
  101. // Not all states reachable from the initial state.
  102. inline constexpr uint64_t kNotAccessible = 0x0000020000000000ULL;
  103. // All states can reach a final state.
  104. inline constexpr uint64_t kCoAccessible = 0x0000040000000000ULL;
  105. // Not all states can reach a final state.
  106. inline constexpr uint64_t kNotCoAccessible = 0x0000080000000000ULL;
  107. // If NumStates() > 0, then state 0 is initial, state NumStates() - 1 is final,
  108. // there is a transition from each non-final state i to state i + 1, and there
  109. // are no other transitions.
  110. inline constexpr uint64_t kString = 0x0000100000000000ULL;
  111. // Not a string FST.
  112. inline constexpr uint64_t kNotString = 0x0000200000000000ULL;
  113. // FST has at least one weighted cycle.
  114. inline constexpr uint64_t kWeightedCycles = 0x0000400000000000ULL;
  115. // FST has no weighted cycles. Any cycles that may be present are unweighted.
  116. inline constexpr uint64_t kUnweightedCycles = 0x0000800000000000ULL;
  117. // COMPOSITE PROPERTIES
  118. // Properties of an empty machine.
  119. inline constexpr uint64_t kNullProperties =
  120. kAcceptor | kIDeterministic | kODeterministic | kNoEpsilons | kNoIEpsilons |
  121. kNoOEpsilons | kILabelSorted | kOLabelSorted | kUnweighted | kAcyclic |
  122. kInitialAcyclic | kTopSorted | kAccessible | kCoAccessible | kString |
  123. kUnweightedCycles;
  124. // Properties of a string FST compiled into a string.
  125. inline constexpr uint64_t kCompiledStringProperties =
  126. kAcceptor | kString | kUnweighted | kIDeterministic | kODeterministic |
  127. kILabelSorted | kOLabelSorted | kAcyclic | kInitialAcyclic |
  128. kUnweightedCycles | kTopSorted | kAccessible | kCoAccessible;
  129. // Properties that are preserved when an FST is copied.
  130. inline constexpr uint64_t kCopyProperties =
  131. kError | kAcceptor | kNotAcceptor | kIDeterministic | kNonIDeterministic |
  132. kODeterministic | kNonODeterministic | kEpsilons | kNoEpsilons |
  133. kIEpsilons | kNoIEpsilons | kOEpsilons | kNoOEpsilons | kILabelSorted |
  134. kNotILabelSorted | kOLabelSorted | kNotOLabelSorted | kWeighted |
  135. kUnweighted | kCyclic | kAcyclic | kInitialCyclic | kInitialAcyclic |
  136. kTopSorted | kNotTopSorted | kAccessible | kNotAccessible | kCoAccessible |
  137. kNotCoAccessible | kString | kNotString | kWeightedCycles |
  138. kUnweightedCycles;
  139. // Properties that are intrinsic to the FST.
  140. inline constexpr uint64_t kIntrinsicProperties =
  141. kExpanded | kMutable | kAcceptor | kNotAcceptor | kIDeterministic |
  142. kNonIDeterministic | kODeterministic | kNonODeterministic | kEpsilons |
  143. kNoEpsilons | kIEpsilons | kNoIEpsilons | kOEpsilons | kNoOEpsilons |
  144. kILabelSorted | kNotILabelSorted | kOLabelSorted | kNotOLabelSorted |
  145. kWeighted | kUnweighted | kCyclic | kAcyclic | kInitialCyclic |
  146. kInitialAcyclic | kTopSorted | kNotTopSorted | kAccessible |
  147. kNotAccessible | kCoAccessible | kNotCoAccessible | kString | kNotString |
  148. kWeightedCycles | kUnweightedCycles;
  149. // Properties that are (potentially) extrinsic to the FST.
  150. inline constexpr uint64_t kExtrinsicProperties = kError;
  151. // Properties that are preserved when an FST start state is set.
  152. inline constexpr uint64_t kSetStartProperties =
  153. kExpanded | kMutable | kError | kAcceptor | kNotAcceptor | kIDeterministic |
  154. kNonIDeterministic | kODeterministic | kNonODeterministic | kEpsilons |
  155. kNoEpsilons | kIEpsilons | kNoIEpsilons | kOEpsilons | kNoOEpsilons |
  156. kILabelSorted | kNotILabelSorted | kOLabelSorted | kNotOLabelSorted |
  157. kWeighted | kUnweighted | kCyclic | kAcyclic | kTopSorted | kNotTopSorted |
  158. kCoAccessible | kNotCoAccessible | kWeightedCycles | kUnweightedCycles;
  159. // Properties that are preserved when an FST final weight is set.
  160. inline constexpr uint64_t kSetFinalProperties =
  161. kExpanded | kMutable | kError | kAcceptor | kNotAcceptor | kIDeterministic |
  162. kNonIDeterministic | kODeterministic | kNonODeterministic | kEpsilons |
  163. kNoEpsilons | kIEpsilons | kNoIEpsilons | kOEpsilons | kNoOEpsilons |
  164. kILabelSorted | kNotILabelSorted | kOLabelSorted | kNotOLabelSorted |
  165. kCyclic | kAcyclic | kInitialCyclic | kInitialAcyclic | kTopSorted |
  166. kNotTopSorted | kAccessible | kNotAccessible | kWeightedCycles |
  167. kUnweightedCycles;
  168. // Properties that are preserved when an FST state is added.
  169. inline constexpr uint64_t kAddStateProperties =
  170. kExpanded | kMutable | kError | kAcceptor | kNotAcceptor | kIDeterministic |
  171. kNonIDeterministic | kODeterministic | kNonODeterministic | kEpsilons |
  172. kNoEpsilons | kIEpsilons | kNoIEpsilons | kOEpsilons | kNoOEpsilons |
  173. kILabelSorted | kNotILabelSorted | kOLabelSorted | kNotOLabelSorted |
  174. kWeighted | kUnweighted | kCyclic | kAcyclic | kInitialCyclic |
  175. kInitialAcyclic | kTopSorted | kNotTopSorted | kNotAccessible |
  176. kNotCoAccessible | kNotString | kWeightedCycles | kUnweightedCycles;
  177. // Properties that are preserved when an FST arc is added.
  178. inline constexpr uint64_t kAddArcProperties =
  179. kExpanded | kMutable | kError | kNotAcceptor | kNonIDeterministic |
  180. kNonODeterministic | kEpsilons | kIEpsilons | kOEpsilons |
  181. kNotILabelSorted | kNotOLabelSorted | kWeighted | kCyclic | kInitialCyclic |
  182. kNotTopSorted | kAccessible | kCoAccessible | kWeightedCycles;
  183. // Properties that are preserved when an FST arc is set.
  184. inline constexpr uint64_t kSetArcProperties = kExpanded | kMutable | kError;
  185. // Properties that are preserved when FST states are deleted.
  186. inline constexpr uint64_t kDeleteStatesProperties =
  187. kExpanded | kMutable | kError | kAcceptor | kIDeterministic |
  188. kODeterministic | kNoEpsilons | kNoIEpsilons | kNoOEpsilons |
  189. kILabelSorted | kOLabelSorted | kUnweighted | kAcyclic | kInitialAcyclic |
  190. kTopSorted | kUnweightedCycles;
  191. // Properties that are preserved when FST arcs are deleted.
  192. inline constexpr uint64_t kDeleteArcsProperties =
  193. kExpanded | kMutable | kError | kAcceptor | kIDeterministic |
  194. kODeterministic | kNoEpsilons | kNoIEpsilons | kNoOEpsilons |
  195. kILabelSorted | kOLabelSorted | kUnweighted | kAcyclic | kInitialAcyclic |
  196. kTopSorted | kNotAccessible | kNotCoAccessible | kUnweightedCycles;
  197. // Properties that are preserved when an FST's states are reordered.
  198. inline constexpr uint64_t kStateSortProperties =
  199. kExpanded | kMutable | kError | kAcceptor | kNotAcceptor | kIDeterministic |
  200. kNonIDeterministic | kODeterministic | kNonODeterministic | kEpsilons |
  201. kNoEpsilons | kIEpsilons | kNoIEpsilons | kOEpsilons | kNoOEpsilons |
  202. kILabelSorted | kNotILabelSorted | kOLabelSorted | kNotOLabelSorted |
  203. kWeighted | kUnweighted | kCyclic | kAcyclic | kInitialCyclic |
  204. kInitialAcyclic | kAccessible | kNotAccessible | kCoAccessible |
  205. kNotCoAccessible | kWeightedCycles | kUnweightedCycles;
  206. // Properties that are preserved when an FST's arcs are reordered.
  207. inline constexpr uint64_t kArcSortProperties =
  208. kExpanded | kMutable | kError | kAcceptor | kNotAcceptor | kIDeterministic |
  209. kNonIDeterministic | kODeterministic | kNonODeterministic | kEpsilons |
  210. kNoEpsilons | kIEpsilons | kNoIEpsilons | kOEpsilons | kNoOEpsilons |
  211. kWeighted | kUnweighted | kCyclic | kAcyclic | kInitialCyclic |
  212. kInitialAcyclic | kTopSorted | kNotTopSorted | kAccessible |
  213. kNotAccessible | kCoAccessible | kNotCoAccessible | kString | kNotString |
  214. kWeightedCycles | kUnweightedCycles;
  215. // Properties that are preserved when an FST's input labels are changed.
  216. inline constexpr uint64_t kILabelInvariantProperties =
  217. kExpanded | kMutable | kError | kODeterministic | kNonODeterministic |
  218. kOEpsilons | kNoOEpsilons | kOLabelSorted | kNotOLabelSorted | kWeighted |
  219. kUnweighted | kCyclic | kAcyclic | kInitialCyclic | kInitialAcyclic |
  220. kTopSorted | kNotTopSorted | kAccessible | kNotAccessible | kCoAccessible |
  221. kNotCoAccessible | kString | kNotString | kWeightedCycles |
  222. kUnweightedCycles;
  223. // Properties that are preserved when an FST's output labels are changed.
  224. inline constexpr uint64_t kOLabelInvariantProperties =
  225. kExpanded | kMutable | kError | kIDeterministic | kNonIDeterministic |
  226. kIEpsilons | kNoIEpsilons | kILabelSorted | kNotILabelSorted | kWeighted |
  227. kUnweighted | kCyclic | kAcyclic | kInitialCyclic | kInitialAcyclic |
  228. kTopSorted | kNotTopSorted | kAccessible | kNotAccessible | kCoAccessible |
  229. kNotCoAccessible | kString | kNotString | kWeightedCycles |
  230. kUnweightedCycles;
  231. // Properties that are preserved when an FST's weights are changed. This
  232. // assumes that the set of states that are non-final is not changed.
  233. inline constexpr uint64_t kWeightInvariantProperties =
  234. kExpanded | kMutable | kError | kAcceptor | kNotAcceptor | kIDeterministic |
  235. kNonIDeterministic | kODeterministic | kNonODeterministic | kEpsilons |
  236. kNoEpsilons | kIEpsilons | kNoIEpsilons | kOEpsilons | kNoOEpsilons |
  237. kILabelSorted | kNotILabelSorted | kOLabelSorted | kNotOLabelSorted |
  238. kCyclic | kAcyclic | kInitialCyclic | kInitialAcyclic | kTopSorted |
  239. kNotTopSorted | kAccessible | kNotAccessible | kCoAccessible |
  240. kNotCoAccessible | kString | kNotString;
  241. // Properties that are preserved when a superfinal state is added and an FST's
  242. // final weights are directed to it via new transitions.
  243. inline constexpr uint64_t kAddSuperFinalProperties =
  244. kExpanded | kMutable | kError | kAcceptor | kNotAcceptor |
  245. kNonIDeterministic | kNonODeterministic | kEpsilons | kIEpsilons |
  246. kOEpsilons | kNotILabelSorted | kNotOLabelSorted | kWeighted | kUnweighted |
  247. kCyclic | kAcyclic | kInitialCyclic | kInitialAcyclic | kNotTopSorted |
  248. kNotAccessible | kCoAccessible | kNotCoAccessible | kNotString |
  249. kWeightedCycles | kUnweightedCycles;
  250. // Properties that are preserved when a superfinal state is removed and the
  251. // epsilon transitions directed to it are made final weights.
  252. inline constexpr uint64_t kRmSuperFinalProperties =
  253. kExpanded | kMutable | kError | kAcceptor | kNotAcceptor | kIDeterministic |
  254. kODeterministic | kNoEpsilons | kNoIEpsilons | kNoOEpsilons |
  255. kILabelSorted | kOLabelSorted | kWeighted | kUnweighted | kCyclic |
  256. kAcyclic | kInitialCyclic | kInitialAcyclic | kTopSorted | kAccessible |
  257. kCoAccessible | kNotCoAccessible | kString | kWeightedCycles |
  258. kUnweightedCycles;
  259. // All binary properties.
  260. inline constexpr uint64_t kBinaryProperties = 0x0000000000000007ULL;
  261. // All trinary properties.
  262. inline constexpr uint64_t kTrinaryProperties = 0x0000ffffffff0000ULL;
  263. // COMPUTED PROPERTIES
  264. // 1st bit of trinary properties.
  265. inline constexpr uint64_t kPosTrinaryProperties =
  266. kTrinaryProperties & 0x5555555555555555ULL;
  267. // 2nd bit of trinary properties.
  268. inline constexpr uint64_t kNegTrinaryProperties =
  269. kTrinaryProperties & 0xaaaaaaaaaaaaaaaaULL;
  270. // All properties.
  271. inline constexpr uint64_t kFstProperties =
  272. kBinaryProperties | kTrinaryProperties;
  273. // PROPERTY FUNCTIONS and STRING NAMES (defined in properties.cc).
  274. // Below are functions for getting property bit vectors when executing
  275. // mutation operations.
  276. inline uint64_t SetStartProperties(uint64_t inprops);
  277. template <typename Weight>
  278. uint64_t SetFinalProperties(uint64_t inprops, const Weight &old_weight,
  279. const Weight &new_weight);
  280. inline uint64_t AddStateProperties(uint64_t inprops);
  281. template <typename A>
  282. uint64_t AddArcProperties(uint64_t inprops, typename A::StateId s, const A &arc,
  283. const A *prev_arc);
  284. inline uint64_t DeleteStatesProperties(uint64_t inprops);
  285. inline uint64_t DeleteAllStatesProperties(uint64_t inprops,
  286. uint64_t staticProps);
  287. inline uint64_t DeleteArcsProperties(uint64_t inprops);
  288. uint64_t ClosureProperties(uint64_t inprops, bool star, bool delayed = false);
  289. uint64_t ComplementProperties(uint64_t inprops);
  290. uint64_t ComposeProperties(uint64_t inprops1, uint64_t inprops2);
  291. uint64_t ConcatProperties(uint64_t inprops1, uint64_t inprops2,
  292. bool delayed = false);
  293. uint64_t DeterminizeProperties(uint64_t inprops, bool has_subsequential_label,
  294. bool distinct_psubsequential_labels);
  295. uint64_t FactorWeightProperties(uint64_t inprops);
  296. uint64_t InvertProperties(uint64_t inprops);
  297. uint64_t ProjectProperties(uint64_t inprops, bool project_input);
  298. uint64_t RandGenProperties(uint64_t inprops, bool weighted);
  299. uint64_t RelabelProperties(uint64_t inprops);
  300. uint64_t ReplaceProperties(const std::vector<uint64_t> &inprops, size_t root,
  301. bool epsilon_on_call, bool epsilon_on_return,
  302. bool out_epsilon_on_call, bool out_epsilon_on_return,
  303. bool replace_transducer, bool no_empty_fst,
  304. bool all_ilabel_sorted, bool all_olabel_sorted,
  305. bool all_negative_or_dense);
  306. uint64_t ReverseProperties(uint64_t inprops, bool has_superinitial);
  307. uint64_t ReweightProperties(uint64_t inprops, bool added_start_epsilon);
  308. uint64_t RmEpsilonProperties(uint64_t inprops, bool delayed = false);
  309. uint64_t ShortestPathProperties(uint64_t props, bool tree = false);
  310. uint64_t SynchronizeProperties(uint64_t inprops);
  311. uint64_t UnionProperties(uint64_t inprops1, uint64_t inprops2,
  312. bool delayed = false);
  313. // Definitions of inlined functions.
  314. uint64_t SetStartProperties(uint64_t inprops) {
  315. auto outprops = inprops & kSetStartProperties;
  316. if (inprops & kAcyclic) {
  317. outprops |= kInitialAcyclic;
  318. }
  319. return outprops;
  320. }
  321. uint64_t AddStateProperties(uint64_t inprops) {
  322. return inprops & kAddStateProperties;
  323. }
  324. uint64_t DeleteStatesProperties(uint64_t inprops) {
  325. return inprops & kDeleteStatesProperties;
  326. }
  327. uint64_t DeleteAllStatesProperties(uint64_t inprops, uint64_t staticprops) {
  328. const auto outprops = inprops & kError;
  329. return outprops | kNullProperties | staticprops;
  330. }
  331. uint64_t DeleteArcsProperties(uint64_t inprops) {
  332. return inprops & kDeleteArcsProperties;
  333. }
  334. // Definitions of template functions.
  335. template <typename Weight>
  336. uint64_t SetFinalProperties(uint64_t inprops, const Weight &old_weight,
  337. const Weight &new_weight) {
  338. auto outprops = inprops;
  339. if (old_weight != Weight::Zero() && old_weight != Weight::One()) {
  340. outprops &= ~kWeighted;
  341. }
  342. if (new_weight != Weight::Zero() && new_weight != Weight::One()) {
  343. outprops |= kWeighted;
  344. outprops &= ~kUnweighted;
  345. }
  346. outprops &= kSetFinalProperties | kWeighted | kUnweighted;
  347. return outprops;
  348. }
  349. /// Gets the properties for the MutableFst::AddArc method.
  350. ///
  351. /// \param inprops the current properties of the FST
  352. /// \param s the ID of the state to which an arc is being added.
  353. /// \param arc the arc being added to the state with the specified ID
  354. /// \param prev_arc the previously-added (or "last") arc of state s, or nullptr
  355. // if s currently has no arcs.
  356. template <typename Arc>
  357. uint64_t AddArcProperties(uint64_t inprops, typename Arc::StateId s,
  358. const Arc &arc, const Arc *prev_arc) {
  359. using Weight = typename Arc::Weight;
  360. auto outprops = inprops;
  361. if (arc.ilabel != arc.olabel) {
  362. outprops |= kNotAcceptor;
  363. outprops &= ~kAcceptor;
  364. }
  365. if (arc.ilabel == 0) {
  366. outprops |= kIEpsilons;
  367. outprops &= ~kNoIEpsilons;
  368. if (arc.olabel == 0) {
  369. outprops |= kEpsilons;
  370. outprops &= ~kNoEpsilons;
  371. }
  372. }
  373. if (arc.olabel == 0) {
  374. outprops |= kOEpsilons;
  375. outprops &= ~kNoOEpsilons;
  376. }
  377. if (prev_arc) {
  378. if (prev_arc->ilabel > arc.ilabel) {
  379. outprops |= kNotILabelSorted;
  380. outprops &= ~kILabelSorted;
  381. }
  382. if (prev_arc->olabel > arc.olabel) {
  383. outprops |= kNotOLabelSorted;
  384. outprops &= ~kOLabelSorted;
  385. }
  386. }
  387. if (arc.weight != Weight::Zero() && arc.weight != Weight::One()) {
  388. outprops |= kWeighted;
  389. outprops &= ~kUnweighted;
  390. }
  391. if (arc.nextstate <= s) {
  392. outprops |= kNotTopSorted;
  393. outprops &= ~kTopSorted;
  394. }
  395. outprops &= kAddArcProperties | kAcceptor | kNoEpsilons | kNoIEpsilons |
  396. kNoOEpsilons | kILabelSorted | kOLabelSorted | kUnweighted |
  397. kTopSorted;
  398. if (outprops & kTopSorted) {
  399. outprops |= kAcyclic | kInitialAcyclic;
  400. }
  401. return outprops;
  402. }
  403. namespace internal {
  404. extern const std::string_view PropertyNames[];
  405. // For a binary property, the bit is always returned set. For a trinary (i.e.,
  406. // two-bit) property, both bits are returned set iff either corresponding input
  407. // bit is set.
  408. inline uint64_t KnownProperties(uint64_t props) {
  409. return kBinaryProperties | (props & kTrinaryProperties) |
  410. ((props & kPosTrinaryProperties) << 1) |
  411. ((props & kNegTrinaryProperties) >> 1);
  412. }
  413. // Tests compatibility between two sets of properties.
  414. inline bool CompatProperties(uint64_t props1, uint64_t props2) {
  415. const auto known_props1 = KnownProperties(props1);
  416. const auto known_props2 = KnownProperties(props2);
  417. const auto known_props = known_props1 & known_props2;
  418. const auto incompat_props = (props1 & known_props) ^ (props2 & known_props);
  419. if (incompat_props) {
  420. uint64_t prop = 1;
  421. for (int i = 0; i < 64; ++i, prop <<= 1) {
  422. if (prop & incompat_props) {
  423. LOG(ERROR) << "CompatProperties: Mismatch: "
  424. << internal::PropertyNames[i]
  425. << ": props1 = " << (props1 & prop ? "true" : "false")
  426. << ", props2 = " << (props2 & prop ? "true" : "false");
  427. }
  428. }
  429. return false;
  430. } else {
  431. return true;
  432. }
  433. }
  434. } // namespace internal
  435. } // namespace fst
  436. #endif // FST_PROPERTIES_H_