ruby-sfst 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -0
- data/COPYING +280 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +54 -0
- data/README.md +1 -1
- data/Rakefile +9 -18
- data/bin/console +7 -0
- data/bin/setup +6 -0
- data/ext/sfst/alphabet.cc +879 -0
- data/ext/sfst/alphabet.h +302 -0
- data/ext/sfst/basic.cc +85 -0
- data/ext/{sfst_machine → sfst}/basic.h +7 -4
- data/ext/sfst/compact.cc +629 -0
- data/ext/sfst/compact.h +100 -0
- data/ext/sfst/determinise.cc +279 -0
- data/ext/{sfst_machine → sfst}/extconf.rb +2 -1
- data/ext/sfst/fst.cc +1150 -0
- data/ext/sfst/fst.h +374 -0
- data/ext/sfst/hopcroft.cc +681 -0
- data/ext/sfst/interface.cc +1921 -0
- data/ext/sfst/interface.h +171 -0
- data/ext/sfst/make-compact.cc +323 -0
- data/ext/{sfst_machine → sfst}/make-compact.h +15 -13
- data/ext/sfst/mem.h +80 -0
- data/ext/sfst/operators.cc +1273 -0
- data/ext/{sfst_machine → sfst}/sfst_machine.cc +89 -78
- data/ext/sfst/sgi.h +72 -0
- data/ext/sfst/utf8.cc +149 -0
- data/ext/{sfst_machine → sfst}/utf8.h +7 -4
- data/lib/sfst.rb +2 -1
- data/lib/sfst/version.rb +1 -1
- data/ruby-sfst.gemspec +23 -23
- metadata +107 -35
- data/ext/sfst_machine/alphabet.cc +0 -812
- data/ext/sfst_machine/alphabet.h +0 -273
- data/ext/sfst_machine/basic.cc +0 -84
- data/ext/sfst_machine/compact.cc +0 -616
- data/ext/sfst_machine/compact.h +0 -98
- data/ext/sfst_machine/determinise.cc +0 -303
- data/ext/sfst_machine/fst.cc +0 -1000
- data/ext/sfst_machine/fst.h +0 -369
- data/ext/sfst_machine/interface.cc +0 -1842
- data/ext/sfst_machine/interface.h +0 -93
- data/ext/sfst_machine/make-compact.cc +0 -327
- data/ext/sfst_machine/mem.h +0 -74
- data/ext/sfst_machine/operators.cc +0 -1131
- data/ext/sfst_machine/sgi.h +0 -44
- data/ext/sfst_machine/utf8.cc +0 -146
- data/test/test_sfst.fst +0 -3
- data/test/test_sfst.rb +0 -114
@@ -0,0 +1,171 @@
|
|
1
|
+
/*******************************************************************/
|
2
|
+
/* */
|
3
|
+
/* FILE interface.h */
|
4
|
+
/* MODULE interface */
|
5
|
+
/* PROGRAM SFST */
|
6
|
+
/* AUTHOR Helmut Schmid, IMS, University of Stuttgart */
|
7
|
+
/* */
|
8
|
+
/*******************************************************************/
|
9
|
+
|
10
|
+
#ifndef _INTERFACE_H_
|
11
|
+
#define _INTERFACE_H_
|
12
|
+
|
13
|
+
#include "utf8.h"
|
14
|
+
#include "fst.h"
|
15
|
+
|
16
|
+
using std::set;
|
17
|
+
using std::cerr;
|
18
|
+
|
19
|
+
namespace SFST {
|
20
|
+
|
21
|
+
void error( const char *message );
|
22
|
+
void error2( const char *message, char *input );
|
23
|
+
|
24
|
+
typedef enum {twol_left, twol_right, twol_both} Twol_Type;
|
25
|
+
|
26
|
+
typedef enum {repl_left, repl_right, repl_up, my_repl_down, repl_down} Repl_Type;
|
27
|
+
|
28
|
+
typedef struct range_t {
|
29
|
+
Character character;
|
30
|
+
struct range_t *next;
|
31
|
+
} Range;
|
32
|
+
|
33
|
+
typedef struct ranges_t {
|
34
|
+
Range *range;
|
35
|
+
struct ranges_t *next;
|
36
|
+
} Ranges;
|
37
|
+
|
38
|
+
|
39
|
+
typedef struct contexts_t {
|
40
|
+
Transducer *left, *right;
|
41
|
+
struct contexts_t *next;
|
42
|
+
} Contexts;
|
43
|
+
|
44
|
+
|
45
|
+
/***************** class Interface *******************************/
|
46
|
+
|
47
|
+
class Interface {
|
48
|
+
|
49
|
+
private:
|
50
|
+
struct ltstr {
|
51
|
+
bool operator()(const char* s1, const char* s2) const
|
52
|
+
{ return strcmp(s1, s2) < 0; }
|
53
|
+
};
|
54
|
+
|
55
|
+
typedef set<char*, ltstr> RVarSet;
|
56
|
+
|
57
|
+
typedef map<char*, Transducer*, ltstr> VarMap;
|
58
|
+
typedef map<char*, Range*, ltstr> SVarMap;
|
59
|
+
|
60
|
+
Range *copy_values( const Range *r );
|
61
|
+
Transducer *one_label_transducer( Label l );
|
62
|
+
void add_pi_transitions( Transducer *t, Node *node, Alphabet &alph );
|
63
|
+
Transducer *pi_machine( Alphabet &alph );
|
64
|
+
Transducer *empty_string_transducer( void );
|
65
|
+
Transducer *cp( Range *lower_range, Range *upper_range );
|
66
|
+
Transducer *anti_cp( Range *lower_range, Range *upper_range );
|
67
|
+
Transducer *twol_right_rule( Transducer *lc, Range *lower_range,
|
68
|
+
Range *upper_range, Transducer *rc);
|
69
|
+
Transducer *twol_left_rule( Transducer *lc, Range *lower_range,
|
70
|
+
Range *upper_range, Transducer *rc );
|
71
|
+
Transducer *restriction_transducer( Transducer *l1, Transducer *l2,
|
72
|
+
Character marker );
|
73
|
+
Transducer *marker_transducer( Transducer *t, Contexts *c,
|
74
|
+
Character &marker );
|
75
|
+
Transducer *center_transducer( Transducer *t, Transducer *pi,
|
76
|
+
Transducer *mt );
|
77
|
+
Transducer *context_transducer( Transducer *t, Transducer *pi,
|
78
|
+
Transducer *mt, Contexts *c );
|
79
|
+
Transducer *insert_boundary_transducer( Character leftm, Character rightm,
|
80
|
+
Alphabet &alph );
|
81
|
+
Transducer *remove_boundary_transducer( Character leftm, Character rightm,
|
82
|
+
Alphabet &alph );
|
83
|
+
Transducer *constrain_boundary_transducer( Character leftm, Character rm,
|
84
|
+
Alphabet &alph );
|
85
|
+
Transducer *extended_left_transducer( Transducer *t, Character m1,
|
86
|
+
Character m2, Alphabet& );
|
87
|
+
Transducer *left_context( Transducer *t, Character m1, Character m2, Alphabet& );
|
88
|
+
Transducer *right_context( Transducer *t, Character m1, Character m2, Alphabet& );
|
89
|
+
Transducer *make_optional( Transducer *t, Repl_Type type );
|
90
|
+
Transducer *replace_transducer( Transducer *ct, Character lm,
|
91
|
+
Character rm, Repl_Type type );
|
92
|
+
|
93
|
+
Transducer *result_transducer( Transducer *l1, Transducer *l2,
|
94
|
+
Twol_Type type, Character marker );
|
95
|
+
|
96
|
+
VarMap VM;
|
97
|
+
SVarMap SVM;
|
98
|
+
RVarSet RS;
|
99
|
+
RVarSet RSS;
|
100
|
+
|
101
|
+
public:
|
102
|
+
bool Verbose;
|
103
|
+
bool Alphabet_Defined;
|
104
|
+
bool LexiconComments;
|
105
|
+
Alphabet TheAlphabet;
|
106
|
+
|
107
|
+
Interface( bool utf8=false, bool verbose=false ) :
|
108
|
+
Verbose(verbose), Alphabet_Defined(false), LexiconComments(false)
|
109
|
+
{
|
110
|
+
TheAlphabet.utf8 = utf8;
|
111
|
+
}
|
112
|
+
|
113
|
+
void allow_lexicon_comments() { LexiconComments = true; }
|
114
|
+
|
115
|
+
Transducer *new_transducer( Range*, Range* );
|
116
|
+
Transducer *read_words( char *filename );
|
117
|
+
Transducer *read_transducer( char *filename );
|
118
|
+
Transducer *var_value( char *name );
|
119
|
+
Transducer *rvar_value( char *name );
|
120
|
+
Range *svar_value( char *name );
|
121
|
+
Range *complement_range( Range* );
|
122
|
+
Range *rsvar_value( char *name );
|
123
|
+
Character character_code( unsigned int uc );
|
124
|
+
Character symbol_code( char *s );
|
125
|
+
|
126
|
+
bool in_range( unsigned int c, Range *r );
|
127
|
+
Transducer *make_transducer( Range *r1, Range *r2 );
|
128
|
+
|
129
|
+
Range *add_value( Character, Range*);
|
130
|
+
|
131
|
+
Range *add_var_values( char *name, Range*);
|
132
|
+
Range *add_values( unsigned int, unsigned int, Range*);
|
133
|
+
Range *append_values( Range *r2, Range *r );
|
134
|
+
void add_alphabet( Transducer* );
|
135
|
+
|
136
|
+
// These functions delete their argument automata
|
137
|
+
|
138
|
+
void def_alphabet( Transducer *a );
|
139
|
+
bool def_var( char *name, Transducer *a );
|
140
|
+
bool def_rvar( char *name, Transducer *a );
|
141
|
+
bool def_svar( char *name, Range *r );
|
142
|
+
Transducer *explode( Transducer *a );
|
143
|
+
Transducer *catenate( Transducer *a1, Transducer *a2 );
|
144
|
+
Transducer *disjunction( Transducer *a1, Transducer *a2 );
|
145
|
+
Transducer *conjunction( Transducer *a1, Transducer *a2 );
|
146
|
+
Transducer *subtraction( Transducer *a1, Transducer *a2 );
|
147
|
+
Transducer *composition( Transducer *a1, Transducer *a2 );
|
148
|
+
Transducer *restriction( Transducer *a, Twol_Type type, Contexts *c, int );
|
149
|
+
Transducer *replace( Transducer *a, Repl_Type type, bool optional );
|
150
|
+
Transducer *replace_in_context( Transducer *a, Repl_Type type,
|
151
|
+
Contexts *c, bool optional );
|
152
|
+
Transducer *negation( Transducer *a );
|
153
|
+
Transducer *upper_level( Transducer *a );
|
154
|
+
Transducer *lower_level( Transducer *a );
|
155
|
+
Transducer *minimise( Transducer *a );
|
156
|
+
Transducer *switch_levels( Transducer *a );
|
157
|
+
Transducer *repetition( Transducer *a );
|
158
|
+
Transducer *repetition2( Transducer *a );
|
159
|
+
Transducer *optional( Transducer *a );
|
160
|
+
Transducer *make_rule( Transducer *lc, Range *r1, Twol_Type type,
|
161
|
+
Range *r2, Transducer *rc );
|
162
|
+
Transducer *freely_insert( Transducer *a, Character lc, Character uc );
|
163
|
+
Transducer *make_mapping( Ranges*, Ranges* );
|
164
|
+
Ranges *add_range( Range*, Ranges* );
|
165
|
+
Contexts *make_context( Transducer *l, Transducer *r );
|
166
|
+
Contexts *add_context( Contexts *nc, Contexts *c );
|
167
|
+
Transducer *result( Transducer*, bool );
|
168
|
+
void write_to_file( Transducer*, char *filename);
|
169
|
+
};
|
170
|
+
}
|
171
|
+
#endif
|
@@ -0,0 +1,323 @@
|
|
1
|
+
/*******************************************************************/
|
2
|
+
/* */
|
3
|
+
/* FILE make-compact.C */
|
4
|
+
/* MODULE make-compact */
|
5
|
+
/* PROGRAM SFST */
|
6
|
+
/* AUTHOR Helmut Schmid, IMS, University of Stuttgart */
|
7
|
+
/* */
|
8
|
+
/* PURPOSE Code needed for generating compact automata */
|
9
|
+
/* */
|
10
|
+
/*******************************************************************/
|
11
|
+
|
12
|
+
#include <math.h>
|
13
|
+
|
14
|
+
#include "make-compact.h"
|
15
|
+
|
16
|
+
namespace SFST {
|
17
|
+
|
18
|
+
class ARC {
|
19
|
+
public:
|
20
|
+
int cv;
|
21
|
+
Label label;
|
22
|
+
unsigned int target_node;
|
23
|
+
|
24
|
+
bool operator< ( const ARC a ) const {
|
25
|
+
return cv < a.cv;
|
26
|
+
};
|
27
|
+
};
|
28
|
+
|
29
|
+
typedef map<Label, size_t, Label::label_cmp> LabelNumber;
|
30
|
+
|
31
|
+
|
32
|
+
/*******************************************************************/
|
33
|
+
/* */
|
34
|
+
/* MakeCompactTransducer::sort */
|
35
|
+
/* */
|
36
|
+
/*******************************************************************/
|
37
|
+
|
38
|
+
void MakeCompactTransducer::sort( Level level )
|
39
|
+
|
40
|
+
{
|
41
|
+
for( unsigned int n=0; n<number_of_nodes; n++) {
|
42
|
+
unsigned int from=first_arc[n];
|
43
|
+
unsigned int to=first_arc[n+1];
|
44
|
+
int l=to-from;
|
45
|
+
|
46
|
+
// copy the arcs to a temporary table
|
47
|
+
ARC *arc=new ARC[l];
|
48
|
+
for( unsigned int i=from; i<to; i++) {
|
49
|
+
arc[i-from].cv = (int)label[i].get_char(level);
|
50
|
+
// make sure that epsilon arcs are stored at the beginning
|
51
|
+
// even if epsilon is not 0
|
52
|
+
if (arc[i-from].cv == (int)Label::epsilon)
|
53
|
+
arc[i-from].cv = -1;
|
54
|
+
arc[i-from].label = label[i];
|
55
|
+
arc[i-from].target_node = target_node[i];
|
56
|
+
}
|
57
|
+
|
58
|
+
// sort the table
|
59
|
+
std::sort( arc, arc+l );
|
60
|
+
|
61
|
+
// copy the arcs back to the original table
|
62
|
+
for( unsigned int i=from; i<to; i++) {
|
63
|
+
label[i] = arc[i-from].label;
|
64
|
+
target_node[i] = arc[i-from].target_node;
|
65
|
+
}
|
66
|
+
|
67
|
+
delete[] arc;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
|
72
|
+
/*******************************************************************/
|
73
|
+
/* */
|
74
|
+
/* MakeCompactTransducer::count_arcs */
|
75
|
+
/* */
|
76
|
+
/*******************************************************************/
|
77
|
+
|
78
|
+
void MakeCompactTransducer::count_arcs( Node *node, VType vmark )
|
79
|
+
{
|
80
|
+
if (!node->was_visited( vmark )) {
|
81
|
+
unsigned n = (unsigned)node->index;
|
82
|
+
finalp[n] = node->is_final();
|
83
|
+
first_arc[n] = 0;
|
84
|
+
Arcs *arcs=node->arcs();
|
85
|
+
for( ArcsIter p(arcs); p; p++ ) {
|
86
|
+
Arc *arc=p;
|
87
|
+
first_arc[n]++;
|
88
|
+
count_arcs(arc->target_node(), vmark);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
|
94
|
+
/*******************************************************************/
|
95
|
+
/* */
|
96
|
+
/* MakeCompactTransducer::store_arcs */
|
97
|
+
/* */
|
98
|
+
/*******************************************************************/
|
99
|
+
|
100
|
+
void MakeCompactTransducer::store_arcs( Node *node, VType vmark )
|
101
|
+
{
|
102
|
+
if (!node->was_visited( vmark )) {
|
103
|
+
unsigned int n=first_arc[node->index];
|
104
|
+
Arcs *arcs=node->arcs();
|
105
|
+
for( ArcsIter p(arcs); p; p++ ) {
|
106
|
+
Arc *arc=p;
|
107
|
+
label[n] = arc->label();
|
108
|
+
target_node[n++] = (unsigned)arc->target_node()->index;
|
109
|
+
store_arcs(arc->target_node(), vmark);
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
|
115
|
+
/*******************************************************************/
|
116
|
+
/* */
|
117
|
+
/* MakeCompactTransducer::MakeCompactTransducer */
|
118
|
+
/* */
|
119
|
+
/*******************************************************************/
|
120
|
+
|
121
|
+
MakeCompactTransducer::MakeCompactTransducer( Transducer &a, Level l )
|
122
|
+
|
123
|
+
{
|
124
|
+
if (a.is_infinitely_ambiguous()) {
|
125
|
+
std::cerr << "Error: resulting transducer contains an infinite loop!\n";
|
126
|
+
exit(1);
|
127
|
+
}
|
128
|
+
|
129
|
+
number_of_nodes = (unsigned)a.nodeindexing().first;
|
130
|
+
alphabet.copy(a.alphabet);
|
131
|
+
|
132
|
+
// memory allocation
|
133
|
+
finalp = new char[number_of_nodes];
|
134
|
+
first_arc = new unsigned int[number_of_nodes+1];
|
135
|
+
|
136
|
+
// count the number of outgoing arcs for each node
|
137
|
+
// and store them in first_arc[]
|
138
|
+
a.incr_vmark();
|
139
|
+
count_arcs( a.root_node(), a.vmark );
|
140
|
+
for( int n=number_of_nodes; n>0; n-- )
|
141
|
+
first_arc[n] = first_arc[n-1];
|
142
|
+
first_arc[0] = 0;
|
143
|
+
for( unsigned int n=0; n<number_of_nodes; n++ )
|
144
|
+
first_arc[n+1] += first_arc[n];
|
145
|
+
number_of_arcs = first_arc[number_of_nodes];
|
146
|
+
|
147
|
+
// memory allocation
|
148
|
+
label = new Label[number_of_arcs];
|
149
|
+
target_node = new unsigned int[number_of_arcs];
|
150
|
+
|
151
|
+
// store the arcs
|
152
|
+
a.incr_vmark();
|
153
|
+
store_arcs( a.root_node(), a.vmark );
|
154
|
+
|
155
|
+
// sort the arcs
|
156
|
+
sort( l );
|
157
|
+
}
|
158
|
+
|
159
|
+
|
160
|
+
/*******************************************************************/
|
161
|
+
/* */
|
162
|
+
/* MakeCompactTransducer::store_finalp */
|
163
|
+
/* */
|
164
|
+
/*******************************************************************/
|
165
|
+
|
166
|
+
void MakeCompactTransducer::store_finalp( FILE *file )
|
167
|
+
|
168
|
+
{
|
169
|
+
int k=0;
|
170
|
+
unsigned char n=0;
|
171
|
+
|
172
|
+
for( size_t i=0; i<number_of_nodes; i++ ) {
|
173
|
+
n = (unsigned char)(n << 1);
|
174
|
+
if (finalp[i])
|
175
|
+
n |= 1;
|
176
|
+
if (++k == 8) {
|
177
|
+
fputc(n, file);
|
178
|
+
n = 0;
|
179
|
+
k = 0;
|
180
|
+
}
|
181
|
+
}
|
182
|
+
if (k > 0) {
|
183
|
+
n = (unsigned char)(n << (8-k));
|
184
|
+
fputc(n, file);
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
|
189
|
+
/*******************************************************************/
|
190
|
+
/* */
|
191
|
+
/* MakeCompactTransducer::store_first_arcs */
|
192
|
+
/* */
|
193
|
+
/* The data is encoded with the minimal number of bits needed. */
|
194
|
+
/* */
|
195
|
+
/*******************************************************************/
|
196
|
+
|
197
|
+
void MakeCompactTransducer::store_first_arcs( FILE *file )
|
198
|
+
|
199
|
+
{
|
200
|
+
int k=0;
|
201
|
+
unsigned int n=0;
|
202
|
+
// compute number of bits required for storing each item
|
203
|
+
int bits=(int)ceil(log(number_of_arcs+1)/log(2));
|
204
|
+
|
205
|
+
for( size_t i=0; i<=number_of_nodes; i++ ) {
|
206
|
+
unsigned int m=first_arc[i];
|
207
|
+
m <<= (sizeof(n)*8) - bits;
|
208
|
+
m >>= k;
|
209
|
+
n = n | m;
|
210
|
+
k += bits;
|
211
|
+
if (k >= (int)sizeof(n)*8) {
|
212
|
+
fwrite(&n, sizeof(n), 1, file);
|
213
|
+
k -= (int)sizeof(n) * 8;
|
214
|
+
n = first_arc[i];
|
215
|
+
if (k == 0)
|
216
|
+
n = 0;
|
217
|
+
else
|
218
|
+
n = first_arc[i] << (sizeof(n) * 8 - k);
|
219
|
+
}
|
220
|
+
}
|
221
|
+
if (k > 0)
|
222
|
+
fwrite(&n, sizeof(n), 1, file);
|
223
|
+
}
|
224
|
+
|
225
|
+
|
226
|
+
/*******************************************************************/
|
227
|
+
/* */
|
228
|
+
/* MakeCompactTransducer::store_target_nodes */
|
229
|
+
/* */
|
230
|
+
/*******************************************************************/
|
231
|
+
|
232
|
+
void MakeCompactTransducer::store_target_nodes( FILE *file )
|
233
|
+
|
234
|
+
{
|
235
|
+
int k=0;
|
236
|
+
unsigned int n=0;
|
237
|
+
int bits=(int)ceil(log(number_of_nodes)/log(2));
|
238
|
+
|
239
|
+
for( size_t i=0; i<number_of_arcs; i++ ) {
|
240
|
+
unsigned int m=target_node[i];
|
241
|
+
m <<= (sizeof(n)*8) - bits;
|
242
|
+
m >>= k;
|
243
|
+
n = n | m;
|
244
|
+
k += bits;
|
245
|
+
if (k >= (int)sizeof(n)*8) {
|
246
|
+
fwrite(&n, sizeof(n), 1, file);
|
247
|
+
k -= (int)sizeof(n)*8;
|
248
|
+
if (k == 0)
|
249
|
+
n = 0;
|
250
|
+
else
|
251
|
+
n = target_node[i] << (sizeof(n) * 8 - k);
|
252
|
+
}
|
253
|
+
}
|
254
|
+
if (k > 0)
|
255
|
+
fwrite(&n, sizeof(n), 1, file);
|
256
|
+
}
|
257
|
+
|
258
|
+
|
259
|
+
/*******************************************************************/
|
260
|
+
/* */
|
261
|
+
/* MakeCompactTransducer::store_labels */
|
262
|
+
/* */
|
263
|
+
/*******************************************************************/
|
264
|
+
|
265
|
+
void MakeCompactTransducer::store_labels( FILE *file )
|
266
|
+
|
267
|
+
{
|
268
|
+
size_t N=0;
|
269
|
+
LabelNumber LNum;
|
270
|
+
for( Alphabet::const_iterator it=alphabet.begin();
|
271
|
+
it != alphabet.end(); it++ )
|
272
|
+
{
|
273
|
+
Label l=*it;
|
274
|
+
LNum[l] = N++;
|
275
|
+
}
|
276
|
+
|
277
|
+
int k=0;
|
278
|
+
unsigned int n=0;
|
279
|
+
int bits=(int)ceil(log((double)alphabet.size())/log(2));
|
280
|
+
|
281
|
+
for( size_t i=0; i<number_of_arcs; i++ ) {
|
282
|
+
unsigned int l = (unsigned)LNum[label[i]];
|
283
|
+
unsigned int m=l;
|
284
|
+
m <<= (sizeof(n)*8) - bits;
|
285
|
+
m >>= k;
|
286
|
+
n = n | m;
|
287
|
+
k += bits;
|
288
|
+
if (k >= (int)sizeof(n)*8) {
|
289
|
+
fwrite(&n, sizeof(n), 1, file);
|
290
|
+
k -= (int)sizeof(n)*8;
|
291
|
+
if (k == 0)
|
292
|
+
n = 0;
|
293
|
+
else
|
294
|
+
n = l << (sizeof(n) * 8 - k);
|
295
|
+
}
|
296
|
+
}
|
297
|
+
if (k > 0)
|
298
|
+
fwrite(&n, sizeof(n), 1, file);
|
299
|
+
}
|
300
|
+
|
301
|
+
|
302
|
+
/*******************************************************************/
|
303
|
+
/* */
|
304
|
+
/* MakeCompactTransducer::store */
|
305
|
+
/* */
|
306
|
+
/*******************************************************************/
|
307
|
+
|
308
|
+
void MakeCompactTransducer::store( FILE *file )
|
309
|
+
|
310
|
+
{
|
311
|
+
fputc('c',file);
|
312
|
+
alphabet.store(file);
|
313
|
+
fwrite(&number_of_nodes, sizeof(number_of_nodes), 1, file);
|
314
|
+
fwrite(&number_of_arcs, sizeof(number_of_arcs), 1, file);
|
315
|
+
store_finalp(file);
|
316
|
+
store_first_arcs(file);
|
317
|
+
store_labels(file);
|
318
|
+
store_target_nodes(file);
|
319
|
+
if (ferror(file))
|
320
|
+
throw "Error encountered while writing transducer to file\n";
|
321
|
+
}
|
322
|
+
|
323
|
+
}
|