see5-installer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.rubocop.yml +11 -0
  4. data/CHANGELOG.md +5 -0
  5. data/Gemfile +10 -0
  6. data/README.md +29 -0
  7. data/Rakefile +12 -0
  8. data/ext/c5.0/Makefile +86 -0
  9. data/ext/c5.0/attwinnow.c +394 -0
  10. data/ext/c5.0/c50.c +330 -0
  11. data/ext/c5.0/classify.c +700 -0
  12. data/ext/c5.0/confmat.c +195 -0
  13. data/ext/c5.0/construct.c +853 -0
  14. data/ext/c5.0/contin.c +613 -0
  15. data/ext/c5.0/defns.i +788 -0
  16. data/ext/c5.0/discr.c +307 -0
  17. data/ext/c5.0/extern.i +170 -0
  18. data/ext/c5.0/formrules.c +720 -0
  19. data/ext/c5.0/formtree.c +1158 -0
  20. data/ext/c5.0/getdata.c +521 -0
  21. data/ext/c5.0/getnames.c +733 -0
  22. data/ext/c5.0/global.c +211 -0
  23. data/ext/c5.0/gpl.txt +674 -0
  24. data/ext/c5.0/implicitatt.c +1112 -0
  25. data/ext/c5.0/info.c +146 -0
  26. data/ext/c5.0/mcost.c +138 -0
  27. data/ext/c5.0/modelfiles.c +952 -0
  28. data/ext/c5.0/p-thresh.c +313 -0
  29. data/ext/c5.0/prune.c +1069 -0
  30. data/ext/c5.0/report.c +345 -0
  31. data/ext/c5.0/rules.c +579 -0
  32. data/ext/c5.0/ruletree.c +398 -0
  33. data/ext/c5.0/siftrules.c +1285 -0
  34. data/ext/c5.0/sort.c +156 -0
  35. data/ext/c5.0/subset.c +599 -0
  36. data/ext/c5.0/text.i +223 -0
  37. data/ext/c5.0/trees.c +740 -0
  38. data/ext/c5.0/update.c +129 -0
  39. data/ext/c5.0/utility.c +1146 -0
  40. data/ext/c5.0/xval +150 -0
  41. data/ext/c5.0/xval.c +402 -0
  42. data/ext/gritbot/Makefile +98 -0
  43. data/ext/gritbot/check.c +1110 -0
  44. data/ext/gritbot/cluster.c +342 -0
  45. data/ext/gritbot/common.c +1269 -0
  46. data/ext/gritbot/continatt.c +412 -0
  47. data/ext/gritbot/defns.i +623 -0
  48. data/ext/gritbot/discratt.c +459 -0
  49. data/ext/gritbot/extern.i +101 -0
  50. data/ext/gritbot/getdata.c +329 -0
  51. data/ext/gritbot/getnames.c +573 -0
  52. data/ext/gritbot/global.c +104 -0
  53. data/ext/gritbot/gpl.txt +674 -0
  54. data/ext/gritbot/gritbot.c +295 -0
  55. data/ext/gritbot/implicitatt.c +1108 -0
  56. data/ext/gritbot/inspect.c +794 -0
  57. data/ext/gritbot/modelfiles.c +687 -0
  58. data/ext/gritbot/outlier.c +415 -0
  59. data/ext/gritbot/sort.c +130 -0
  60. data/ext/gritbot/text.i +159 -0
  61. data/ext/gritbot/update.c +126 -0
  62. data/ext/gritbot/utility.c +1029 -0
  63. data/ext/see5-installer/extconf.rb +25 -0
  64. data/lib/see5/installer.rb +10 -0
  65. data/lib/see5/installer/version.rb +7 -0
  66. data/see5-installer.gemspec +30 -0
  67. metadata +115 -0
@@ -0,0 +1,159 @@
1
+ /*************************************************************************/
2
+ /* */
3
+ /* Copyright 2010 Rulequest Research Pty Ltd. */
4
+ /* */
5
+ /* This file is part of GritBot GPL Edition, a single-threaded version */
6
+ /* of GritBot release 2.01. */
7
+ /* */
8
+ /* GritBot GPL Edition is free software: you can redistribute it */
9
+ /* and/or modify it under the terms of the GNU General Public License */
10
+ /* as published by the Free Software Foundation, either version 3 of */
11
+ /* the License, or (at your option) any later version. */
12
+ /* */
13
+ /* GritBot GPL Edition is distributed in the hope that it will be */
14
+ /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
15
+ /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
16
+ /* GNU General Public License for more details. */
17
+ /* */
18
+ /* You should have received a copy of the GNU General Public License */
19
+ /* (gpl.txt) along with GritBot GPL Edition. If not, see */
20
+ /* */
21
+ /* <http://www.gnu.org/licenses/>. */
22
+ /* */
23
+ /*************************************************************************/
24
+
25
+
26
+
27
+ /*************************************************************************/
28
+ /* */
29
+ /* Text strings for UTF-8 internationalization */
30
+ /* ------------------------------------------- */
31
+ /* */
32
+ /*************************************************************************/
33
+
34
+
35
+ /* General stuff */
36
+
37
+
38
+ #ifdef UTF8
39
+ #define CharWidth(S) UTF8CharWidth(S)
40
+ #else
41
+ #define CharWidth(S) (int) strlen(S)
42
+ #endif
43
+
44
+ /* Strings etc */
45
+
46
+ #define T_GritBot "GritBot"
47
+ #define F_Release(n) "Release " n
48
+
49
+ #define T_Options "Options"
50
+ #define F_Application "\tApplication `%s'\n"
51
+ #define F_Filtering "\tFiltering level %g%%\n"
52
+ #define F_MaxConds "\tMaxium %d conditions in description\n"
53
+ #define F_MinSubset "\tMinimum %d cases in subset\n"
54
+ #define F_MaxOut "\tShow up to %d possible anomalies\n"
55
+ #define F_NoSift "\tDo not save analysis in .sift file\n"
56
+ #define F_ListAnoms "\tSave case numbers of possible anomalies\n"
57
+ #define F_UnrecogOpt "\n ** Unrecognised option %s"\
58
+ "\n ** Summary of options for GritBot:\n"
59
+ #define F_OptList "\t-f <filestem>\tapplication filestem\n"\
60
+ "\t-l <percent>\tfiltering level\n"\
61
+ "\t-c <integer>\tmaximum conditions in"\
62
+ " description\n"\
63
+ "\t-n <cases>\tlimit number of possible"\
64
+ " anomalies reported\n"\
65
+ "\t-s\t\tdo not save .sift file\n"\
66
+ "\t-r\t\trecord case numbers of"\
67
+ " possible anomalies\n"\
68
+ "\t-h\t\tprint this message\n"
69
+ #define F_ReadData(c,a,f) "\nRead %d cases (%d attributes) from"\
70
+ " %s.data\n", c, a, f
71
+ #define F_ReadTest(c,f) "Read %d cases from %s.test\n", c, f
72
+ #define F_AttChecked "\nAttributes checked:\n"
73
+ #define F_AttNotChecked "\nAttributes not checked:\n"
74
+ #define F_Time(s) "\n\nTime: %.1f secs\n", s
75
+
76
+ #define F_WhileCheck "\n while checking %s:\n"
77
+ #define F_ExcludeMissing(a) ( (a) > 1 ?\
78
+ "\texcluding %d missing values\n" :\
79
+ "\texcluding %d missing value\n" ), a
80
+ #define F_ExcludeNA(a) ( (a) > 1 ?\
81
+ "\texcluding %d N/A values\n" :\
82
+ "\texcluding %d N/A value\n" ), a
83
+ #define F_TooManyIdentical "\ttoo many identical values -- excluded\n"
84
+ #define F_LowTail(c,t) "\texcluding low tail (%d cases below %s)\n",\
85
+ c, t
86
+ #define F_HighTail(c,t) "\texcluding high tail (%d cases above %s)\n",\
87
+ c, t
88
+
89
+ #define F_WarnDemo "\n\t** This demonstration version cannot"\
90
+ " process **\n"\
91
+ "\t** more than %d training or test cases."\
92
+ " **\n"\
93
+
94
+ #define F_PossAnomalies(a) ( (a) != 1 ?\
95
+ "\n%d possible anomalies identified\n" :\
96
+ "\n%d possible anomaly identified\n" ), a
97
+ #define F_NoTestCase(c) "\ntest case %d:", c
98
+ #define F_NoDataCase(c) "\ndata case %d:", c
99
+ #define F_NoCase(c) "\ncase %d:", c
100
+ #define F_LabelCase(l) " (label %s)", l
101
+ #define F_Cases(c) " (%d cases, ", c
102
+ #define F_CvGroup(m,d,p,r,v) "mean %s, %.*f%% %s %s)\n", m, d, p, r, v
103
+ #define F_DvGroup(d,p,v) "%.*f%% `%s')\n", d, p, v
104
+ #define T_and "and"
105
+ #define T_in "in" /* element of set */
106
+
107
+ #define T_ReadTrain "Reading training data"
108
+ #define T_ReadTest "Reading test data"
109
+ #define T_Prelim "Preliminaries"
110
+ #define T_Checking "Checking"
111
+ #define T_Reporting "Reporting anomalies"
112
+ #define T_CleaningUp "Cleaning up"
113
+ #define F_Preliminaries "Preliminaries for %-21.21s\n"
114
+ #define F_Checking(a,x,y,c) "Checking %-21.21s %s%s (%d cases"\
115
+ " checked)\n", a, x, y, c
116
+
117
+ #define F_Line(l,f) "*** line %d of `%s': ", l, f
118
+ #define E_NOFILE(f,e) "cannot open file %s%s\n", f, e
119
+ #define E_ForWrite " for writing"
120
+ #define E_BADATTNAME "`:' or `:=' expected after attribute name"\
121
+ " `%s'\n"
122
+ #define E_UNKNOWNATT "unknown attribute name `%s'\n"
123
+ #define E_EOFINATT "unexpected eof while reading attribute `%s'\n"
124
+ #define E_SINGLEATTVAL(a,v) "attribute `%s' has only one value `%s'\n",\
125
+ a, v
126
+ #define E_DUPATTNAME "multiple attributes with name `%s'\n"
127
+ #define E_BADATTVAL(v,a) "bad value of `%s' for attribute `%s'\n", v, a
128
+ #define E_BADNUMBER(a) "value of `%s' changed to `?'\n", a
129
+ #define E_BADCLASS "bad class value `%s'l\n"
130
+ #define E_NOMEM "unable to allocate sufficient memory\n"
131
+ #define E_TOOMANYVALS(a,n) "too many values for attribute `%s'"\
132
+ " (max %d)\n", a, n
133
+ #define E_BADDISCRETE "bad number of discrete values for attribute"\
134
+ " `%s'\n"
135
+ #define E_LONGNAME "overlength name: check data file formats\n"
136
+ #define E_HITEOF "unexpected end of file\n"
137
+ #define E_MISSNAME "missing name or value before `%s'\n"
138
+ #define E_BADTSTMP(d,a) "bad timestamp `%s' for attribute `%s'\n", d, a
139
+ #define E_BADDATE(d,a) "bad date `%s' for attribute `%s'\n", d, a
140
+ #define E_BADTIME(d,a) "bad time `%s' for attribute `%s'\n", d, a
141
+ #define E_BADDEF1(a,s,x) "in definition of attribute `%s':\n"\
142
+ "\tat `%.12s': expect %s\n", a, s, x
143
+ #define E_BADDEF2(a,s,x) "in definition of attribute `%s':\n"\
144
+ "\t`%s': %s\n", a, s, x
145
+ #define E_SAMEATT(a,b) "attribute `%s' is identical to attribute"\
146
+ " `%s'\n", a, b
147
+ #define E_BADDEF3 "cannot define target attribute `%s'\n"
148
+ #define E_SIFT "sift file corrupted (entry \"%s\")\n"
149
+ #define T_ErrorLimit "\nError limit exceeded\n"
150
+
151
+ #define F_CkOptList "\t-f <filestem>\tapplication filestem\n"\
152
+ "\t-n <cases>\tlimit number of possible"\
153
+ " anomalies reported\n"\
154
+ "\t-r\t\trecord case numbers of"\
155
+ " possible anomalies\n"\
156
+ "\t-h\t\tprint this message\n"
157
+ #define F_ReadSift "\nRead saved analysis from %s.sift\n"
158
+ #define F_ReadCases(c,a,f) "Read %d cases (%d attributes) from"\
159
+ " %s.cases\n", c, a, f
@@ -0,0 +1,126 @@
1
+ /*************************************************************************/
2
+ /* */
3
+ /* Copyright 2010 Rulequest Research Pty Ltd. */
4
+ /* */
5
+ /* This file is part of GritBot GPL Edition, a single-threaded version */
6
+ /* of GritBot release 2.01. */
7
+ /* */
8
+ /* GritBot GPL Edition is free software: you can redistribute it */
9
+ /* and/or modify it under the terms of the GNU General Public License */
10
+ /* as published by the Free Software Foundation, either version 3 of */
11
+ /* the License, or (at your option) any later version. */
12
+ /* */
13
+ /* GritBot GPL Edition is distributed in the hope that it will be */
14
+ /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
15
+ /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
16
+ /* GNU General Public License for more details. */
17
+ /* */
18
+ /* You should have received a copy of the GNU General Public License */
19
+ /* (gpl.txt) along with GritBot GPL Edition. If not, see */
20
+ /* */
21
+ /* <http://www.gnu.org/licenses/>. */
22
+ /* */
23
+ /*************************************************************************/
24
+
25
+
26
+
27
+ /*************************************************************************/
28
+ /* */
29
+ /* Routines that provide information on progress */
30
+ /* --------------------------------------------- */
31
+ /* */
32
+ /*************************************************************************/
33
+
34
+
35
+ #include "defns.i"
36
+ #include "extern.i"
37
+
38
+
39
+ int Stage=0; /* Current stage number */
40
+ FILE *Uf=0; /* File to which update info written */
41
+
42
+
43
+ /*************************************************************************/
44
+ /* */
45
+ /* There are five stages (see messages in Progress() below) */
46
+ /* Record stage and open update file if necessary */
47
+ /* */
48
+ /*************************************************************************/
49
+
50
+
51
+ void NotifyStage(int S)
52
+ /* ----------- */
53
+ {
54
+ Stage = S;
55
+ if ( S == 1 )
56
+ {
57
+ if ( ! (Uf = GetFile(".tmp", "w")) ) Error(NOFILE, "", " for writing");
58
+ }
59
+ }
60
+
61
+
62
+
63
+ /*************************************************************************/
64
+ /* */
65
+ /* Print progress message. This routine is called in two ways: */
66
+ /* * negative Delta = measure of total effort required for stage */
67
+ /* * positive Delta = increment since last call */
68
+ /* */
69
+ /*************************************************************************/
70
+
71
+
72
+ void Progress(int Delta)
73
+ /* -------- */
74
+ {
75
+ static int Att, Current=0, Twentieth=0, LastStage=0;
76
+ int p;
77
+ static char *Message[]={ "",
78
+ T_ReadTrain,
79
+ T_ReadTest,
80
+ T_Prelim,
81
+ T_Checking,
82
+ T_Reporting,
83
+ T_CleaningUp },
84
+ *Done=">>>>>>>>>>>>>>>>>>>>",
85
+ *ToDo="....................";
86
+
87
+ if ( ! Uf ) return;
88
+
89
+ if ( Delta < 0)
90
+ {
91
+ Att = -Delta;
92
+ Current = 0;
93
+ Twentieth = -1;
94
+
95
+ if ( Stage == PRELIM )
96
+ {
97
+ fprintf(Uf, F_Preliminaries, AttName[Att]);
98
+ fflush(Uf);
99
+ }
100
+ }
101
+ else
102
+ {
103
+ Current = Min(MaxCase+1, Current + Delta);
104
+ }
105
+
106
+ if ( Stage != PRELIM &&
107
+ ( (p = rint((20.0 * Current) / (MaxCase+1.01))) != Twentieth ||
108
+ Stage != LastStage ) )
109
+ {
110
+ LastStage = Stage;
111
+ Twentieth = p;
112
+
113
+ if ( Stage == CHECKING )
114
+ {
115
+ fprintf(Uf, F_Checking(AttName[Att],
116
+ Done + (20 - Twentieth), ToDo + Twentieth,
117
+ Current));
118
+ }
119
+ else
120
+ {
121
+ fprintf(Uf, "%s\n", Message[Stage]);
122
+ }
123
+
124
+ fflush(Uf);
125
+ }
126
+ }
@@ -0,0 +1,1029 @@
1
+ /*************************************************************************/
2
+ /* */
3
+ /* Copyright 2010 Rulequest Research Pty Ltd. */
4
+ /* */
5
+ /* This file is part of GritBot GPL Edition, a single-threaded version */
6
+ /* of GritBot release 2.01. */
7
+ /* */
8
+ /* GritBot GPL Edition is free software: you can redistribute it */
9
+ /* and/or modify it under the terms of the GNU General Public License */
10
+ /* as published by the Free Software Foundation, either version 3 of */
11
+ /* the License, or (at your option) any later version. */
12
+ /* */
13
+ /* GritBot GPL Edition is distributed in the hope that it will be */
14
+ /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
15
+ /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
16
+ /* GNU General Public License for more details. */
17
+ /* */
18
+ /* You should have received a copy of the GNU General Public License */
19
+ /* (gpl.txt) along with GritBot GPL Edition. If not, see */
20
+ /* */
21
+ /* <http://www.gnu.org/licenses/>. */
22
+ /* */
23
+ /*************************************************************************/
24
+
25
+
26
+
27
+ /*************************************************************************/
28
+ /* */
29
+ /* Print header for all programs */
30
+ /* ----------------------------- */
31
+ /* */
32
+ /*************************************************************************/
33
+
34
+ #include "defns.i"
35
+ #include "extern.i"
36
+
37
+ #include <sys/unistd.h>
38
+
39
+
40
+ void PrintHeader(String Title)
41
+ /* ----------- */
42
+ {
43
+ char TitleLine[80];
44
+ time_t clock;
45
+ int Underline;
46
+
47
+ clock = time(0);
48
+ sprintf(TitleLine, "%s%s [%s]", T_GritBot, Title, F_Release(RELEASE));
49
+ fprintf(Of, "\n%s \t%s", TitleLine, ctime(&clock));
50
+
51
+ Underline = CharWidth(TitleLine);
52
+ while ( Underline-- ) putc('-', Of);
53
+ putc('\n', Of);
54
+ }
55
+
56
+
57
+
58
+ /*************************************************************************/
59
+ /* */
60
+ /* This is a specialised form of the getopt utility. */
61
+ /* */
62
+ /*************************************************************************/
63
+
64
+
65
+ String OptArg, Option;
66
+
67
+
68
+ char ProcessOption(int Argc, char *Argv[], char *Options)
69
+ /* ------------- */
70
+ {
71
+ int i;
72
+ static int OptNo=1;
73
+
74
+ if ( OptNo >= Argc ) return '\00';
75
+
76
+ if ( *(Option = Argv[OptNo++]) != '-' ) return '?';
77
+
78
+ for ( i = 0 ; Options[i] ; i++ )
79
+ {
80
+ if ( Options[i] == Option[1] )
81
+ {
82
+ OptArg = ( Options[i+1] != '+' ? Nil :
83
+ Option[2] ? Option+2 :
84
+ OptNo < Argc ? Argv[OptNo++] : "0" );
85
+ return Option[1];
86
+ }
87
+ }
88
+
89
+ return '?';
90
+ }
91
+
92
+
93
+
94
+ /*************************************************************************/
95
+ /* */
96
+ /* Protected memory allocation routines */
97
+ /* */
98
+ /*************************************************************************/
99
+
100
+
101
+
102
+ void *Pmalloc(size_t Bytes)
103
+ /* ------- */
104
+ {
105
+ void *p=Nil;
106
+
107
+ if ( ! Bytes || (p = (void *) malloc(Bytes)) )
108
+ {
109
+ return p;
110
+ }
111
+
112
+ Error(NOMEM, "", "");
113
+
114
+ }
115
+
116
+
117
+
118
+ void *Prealloc(void *Present, size_t Bytes)
119
+ /* -------- */
120
+ {
121
+ void *p=Nil;
122
+
123
+ if ( ! Bytes ) return Nil;
124
+
125
+ if ( ! Present ) return Pmalloc(Bytes);
126
+
127
+ if ( (p = (void *) realloc(Present, Bytes)) )
128
+ {
129
+ return p;
130
+ }
131
+
132
+ Error(NOMEM, "", "");
133
+
134
+ }
135
+
136
+
137
+
138
+ void *Pcalloc(size_t Number, unsigned int Size)
139
+ /* ------- */
140
+ {
141
+ void *p=Nil;
142
+
143
+ if ( ! Number || (p = (void *) calloc(Number, Size)) )
144
+ {
145
+ return p;
146
+ }
147
+
148
+ Error(NOMEM, "", "");
149
+
150
+ }
151
+
152
+
153
+
154
+ void FreeVector(void **V, int First, int Last)
155
+ /* ---------- */
156
+ {
157
+ if ( V )
158
+ {
159
+ while ( First <= Last )
160
+ {
161
+ FreeUnlessNil(V[First]);
162
+ First++;
163
+ }
164
+
165
+ Free(V);
166
+ }
167
+ }
168
+
169
+
170
+
171
+ /*************************************************************************/
172
+ /* */
173
+ /* Special memory allocation routines for case memory */
174
+ /* */
175
+ /*************************************************************************/
176
+
177
+ typedef struct _datablockrec *DataBlock;
178
+
179
+ typedef struct _datablockrec
180
+ {
181
+ Description Head; /* first address */
182
+ int Allocated; /* number of cases in this block */
183
+ DataBlock Prev; /* previous data block */
184
+ }
185
+ DataBlockRec;
186
+
187
+ DataBlock DataMem=Nil;
188
+ int DataBlockSize=0;
189
+
190
+
191
+
192
+ Description NewCase()
193
+ /* ------- */
194
+ {
195
+ DataBlock Prev;
196
+
197
+ if ( ! DataMem || DataMem->Allocated == DataBlockSize )
198
+ {
199
+ DataBlockSize = Min(8192, 262144 / (MaxAtt+3) + 1);
200
+
201
+ Prev = DataMem;
202
+ DataMem = AllocZero(1, DataBlockRec);
203
+ DataMem->Head = Alloc(DataBlockSize * (MaxAtt+3), AttValue);
204
+ DataMem->Prev = Prev;
205
+ }
206
+
207
+ return DataMem->Head + (DataMem->Allocated++) * (MaxAtt+3);
208
+ }
209
+
210
+
211
+
212
+ void MemTrim()
213
+ /* ------- */
214
+ {
215
+ Realloc(DataMem->Head, DataMem->Allocated * (MaxAtt+3), AttValue);
216
+ }
217
+
218
+
219
+
220
+ void FreeCases()
221
+ /* --------- */
222
+ {
223
+ DataBlock Prev;
224
+
225
+ while ( DataMem )
226
+ {
227
+ Prev = DataMem->Prev;
228
+ Free(DataMem->Head);
229
+ Free(DataMem);
230
+ DataMem = Prev;
231
+ }
232
+ }
233
+
234
+
235
+
236
+ void FreeLastCase(Description Case)
237
+ /* ------------ */
238
+ {
239
+ Attribute Att;
240
+
241
+ ForEach(Att, 1, MaxAtt)
242
+ {
243
+ if ( Exclude(Att) ) Free(SVal(Case,Att));
244
+ }
245
+
246
+ DataMem->Allocated--;
247
+ }
248
+
249
+
250
+
251
+ /*************************************************************************/
252
+ /* */
253
+ /* Generate uniform random numbers */
254
+ /* */
255
+ /*************************************************************************/
256
+
257
+
258
+ #define Modify(F,S) if ( (F -= S) < 0 ) F += 1.0
259
+
260
+ int KRFp=0, KRSp=0;
261
+
262
+ double KRandom()
263
+ /* ------- */
264
+ {
265
+ static double URD[55];
266
+ double V1, V2;
267
+ int i, j;
268
+
269
+ /* Initialisation */
270
+
271
+ if ( KRFp == KRSp )
272
+ {
273
+ KRFp = 0;
274
+ KRSp = 31;
275
+
276
+ V1 = 1.0;
277
+ V2 = 0.314159285;
278
+
279
+ ForEach(i, 1, 55)
280
+ {
281
+ URD[ j = (i * 21) % 55 ] = V1;
282
+ V1 = V2 - V1;
283
+ if ( V1 < 0 ) V1 += 1.0;
284
+ V2 = URD[j];
285
+ }
286
+
287
+ ForEach(j, 0, 5)
288
+ {
289
+ ForEach(i, 0, 54)
290
+ {
291
+ Modify(URD[i], URD[(i+30) % 55]);
292
+ }
293
+ }
294
+ }
295
+
296
+ KRFp = (KRFp + 1) % 55;
297
+ KRSp = (KRSp + 1) % 55;
298
+ Modify(URD[KRFp], URD[KRSp]);
299
+
300
+ return URD[KRFp];
301
+ }
302
+
303
+
304
+
305
+ void ResetKR(int KRInit)
306
+ /* ------- */
307
+ {
308
+ KRFp = KRSp = 0;
309
+
310
+ KRInit += 1000;
311
+ while ( KRInit-- )
312
+ {
313
+ KRandom();
314
+ }
315
+ }
316
+
317
+
318
+
319
+ /*************************************************************************/
320
+ /* */
321
+ /* Error messages */
322
+ /* */
323
+ /*************************************************************************/
324
+
325
+
326
+ void Error(int ErrNo, String S1, String S2)
327
+ /* ----- */
328
+ {
329
+ Boolean Quit=false;
330
+
331
+
332
+ if ( ! Of ) return;
333
+
334
+ if ( ! ErrMsgs )
335
+ {
336
+ fprintf(Of, "\n");
337
+ }
338
+
339
+ if ( ErrNo == NOFILE || ErrNo == NOMEM || ErrNo == BADSIFT )
340
+ {
341
+ fprintf(Of, "*** ");
342
+ }
343
+ else
344
+ {
345
+ fprintf(Of, F_Line(LineNo, Fn));
346
+ }
347
+
348
+ switch ( ErrNo )
349
+ {
350
+ case NOFILE:
351
+ fprintf(Of, E_NOFILE(Fn, S2));
352
+ Quit = true;
353
+ break;
354
+
355
+ case BADATTNAME:
356
+ fprintf(Of, E_BADATTNAME, S1);
357
+ break;
358
+
359
+ case UNKNOWNATT:
360
+ fprintf(Of, E_UNKNOWNATT, S1);
361
+ break;
362
+
363
+ case EOFINATT:
364
+ fprintf(Of, E_EOFINATT, S1);
365
+ break;
366
+
367
+ case SINGLEATTVAL:
368
+ fprintf(Of, E_SINGLEATTVAL(S1, S2));
369
+ break;
370
+
371
+ case DUPATTNAME:
372
+ fprintf(Of, E_DUPATTNAME, S1);
373
+ break;
374
+
375
+ case BADATTVAL:
376
+ fprintf(Of, E_BADATTVAL(S2, S1));
377
+ break;
378
+
379
+ case BADNUMBER:
380
+ fprintf(Of, E_BADNUMBER(S1));
381
+ break;
382
+
383
+ case BADCLASS:
384
+ fprintf(Of, E_BADCLASS, S2);
385
+ break;
386
+
387
+ case NOMEM:
388
+ fprintf(Of, E_NOMEM);
389
+ Quit = true;
390
+ break;
391
+
392
+ case TOOMANYVALS:
393
+ fprintf(Of, E_TOOMANYVALS(S1, (int) S2));
394
+ break;
395
+
396
+ case BADDISCRETE:
397
+ fprintf(Of, E_BADDISCRETE, S1);
398
+ break;
399
+
400
+ case LONGNAME:
401
+ fprintf(Of, E_LONGNAME);
402
+ Quit = true;
403
+ break;
404
+
405
+ case HITEOF:
406
+ fprintf(Of, E_HITEOF);
407
+ break;
408
+
409
+ case MISSNAME:
410
+ fprintf(Of, E_MISSNAME, S2);
411
+ break;
412
+
413
+ case BADTSTMP:
414
+ fprintf(Of, E_BADTSTMP(S2, S1));
415
+ break;
416
+
417
+ case BADDATE:
418
+ fprintf(Of, E_BADDATE(S2, S1));
419
+ break;
420
+
421
+ case BADTIME:
422
+ fprintf(Of, E_BADTIME(S2, S1));
423
+ break;
424
+
425
+ case BADDEF1:
426
+ fprintf(Of, E_BADDEF1(AttName[MaxAtt], S1, S2));
427
+ break;
428
+
429
+ case BADDEF2:
430
+ fprintf(Of, E_BADDEF2(AttName[MaxAtt], S1, S2));
431
+ break;
432
+
433
+ case SAMEATT:
434
+ fprintf(Of, E_SAMEATT(AttName[MaxAtt], S1));
435
+ break;
436
+
437
+ case BADDEF3:
438
+ fprintf(Of, E_BADDEF3, AttName[MaxAtt]);
439
+ break;
440
+
441
+ case BADSIFT:
442
+ fprintf(Of, E_SIFT, S1);
443
+ Quit = true;
444
+ break;
445
+ }
446
+
447
+ if ( ++ErrMsgs > 10 )
448
+ {
449
+ fprintf(Of, T_ErrorLimit);
450
+ MaxCase--;
451
+ Quit = true;
452
+ }
453
+
454
+ if ( Quit )
455
+ {
456
+ Goodbye(1);
457
+ }
458
+ }
459
+
460
+
461
+
462
+ /*************************************************************************/
463
+ /* */
464
+ /* Generate the label for a case */
465
+ /* */
466
+ /*************************************************************************/
467
+
468
+ char LabelBuffer[1000];
469
+
470
+
471
+ String CaseLabel(CaseNo N)
472
+ /* --------- */
473
+ {
474
+ String p;
475
+
476
+ if ( LabelAtt && (p = SVal(Case[N], LabelAtt)) )
477
+ ;
478
+ else
479
+ {
480
+ sprintf(LabelBuffer, "#%d", N+1);
481
+ p = LabelBuffer;
482
+ }
483
+
484
+ return p;
485
+ }
486
+
487
+
488
+
489
+ /*************************************************************************/
490
+ /* */
491
+ /* Open file with given extension for read/write */
492
+ /* */
493
+ /*************************************************************************/
494
+
495
+
496
+ FILE *GetFile(String Extension, String RW)
497
+ /* -------- */
498
+ {
499
+ strcpy(Fn, FileStem);
500
+ strcat(Fn, Extension);
501
+ return fopen(Fn, RW);
502
+ }
503
+
504
+
505
+
506
+ /*************************************************************************/
507
+ /* */
508
+ /* Determine total elapsed time so far. */
509
+ /* */
510
+ /*************************************************************************/
511
+
512
+
513
+ //#include <sys/resource.h>
514
+ #include <sys/time.h>
515
+
516
+ double ExecTime()
517
+ /* -------- */
518
+ {
519
+ struct timeval TV;
520
+ struct timezone TZ={0,0};
521
+
522
+ gettimeofday(&TV, &TZ);
523
+ return TV.tv_sec + TV.tv_usec / 1000000.0;
524
+ }
525
+
526
+
527
+
528
+
529
+
530
+
531
+ /*************************************************************************/
532
+ /* */
533
+ /* Determine precision of numeric value */
534
+ /* */
535
+ /*************************************************************************/
536
+
537
+
538
+ int Denominator(ContValue Val)
539
+ /* ----------- */
540
+ {
541
+ double RoundErr, Accuracy;
542
+ int Mult;
543
+
544
+ Accuracy = fabs(Val) * 1E-6; /* approximate */
545
+ Val = modf(Val, &RoundErr);
546
+
547
+ for ( Mult = 100000 ; Mult >= 1 ; Mult /= 10 )
548
+ {
549
+ RoundErr = fabs(rint(Val * Mult) / Mult - Val);
550
+ if ( RoundErr > 2 * Accuracy )
551
+ {
552
+ return Mult * 10;
553
+ }
554
+ }
555
+
556
+ return 1;
557
+ }
558
+
559
+
560
+ int FracBase(Attribute Att)
561
+ /* -------- */
562
+ {
563
+ CaseNo i;
564
+ int Denom=0, ThisDenom;
565
+
566
+ ForEach(i, 0, MaxCase)
567
+ {
568
+ if ( ! Unknown(Case[i], Att) &&
569
+ ! NotApplic(Case[i], Att) &&
570
+ (ThisDenom = Denominator(CVal(Case[i], Att))) > Denom )
571
+ {
572
+ Denom = ThisDenom;
573
+ }
574
+ }
575
+
576
+ return Denom;
577
+ }
578
+
579
+
580
+
581
+ /*************************************************************************/
582
+ /* */
583
+ /* Routines to process date (Algorithm due to Gauss?) */
584
+ /* */
585
+ /*************************************************************************/
586
+
587
+
588
+ int GetInt(String S, int N)
589
+ /* ------ */
590
+ {
591
+ int Result=0;
592
+
593
+ while ( N-- )
594
+ {
595
+ if ( ! isdigit(*S) ) return 0;
596
+
597
+ Result = Result * 10 + (*S++ - '0');
598
+ }
599
+
600
+ return Result;
601
+ }
602
+
603
+
604
+ int DateToDay(String DS) /* Day 1 is 0000/03/01 */
605
+ /* --------- */
606
+ {
607
+ int Year, Month, Day;
608
+
609
+ if ( strlen(DS) != 10 ) return 0;
610
+
611
+ Year = GetInt(DS, 4);
612
+ Month = GetInt(DS+5, 2);
613
+ Day = GetInt(DS+8, 2);
614
+
615
+ if ( ! ( DS[4] == '/' && DS[7] == '/' || DS[4] == '-' && DS[7] == '-' ) ||
616
+ Year < 0 || Month < 1 || Day < 1 ||
617
+ Month > 12 ||
618
+ Day > 31 ||
619
+ Day > 30 &&
620
+ ( Month == 4 || Month == 6 || Month == 9 || Month == 11 ) ||
621
+ Month == 2 &&
622
+ ( Day > 29 ||
623
+ Day > 28 && ( Year % 4 != 0 ||
624
+ Year % 100 == 0 && Year % 400 != 0 ) ) )
625
+ {
626
+ return 0;
627
+ }
628
+
629
+ if ( (Month -= 2) <= 0 )
630
+ {
631
+ Month += 12;
632
+ Year -= 1;
633
+ }
634
+
635
+ return Year * 365 + Year / 4 - Year / 100 + Year / 400
636
+ + 367 * Month / 12
637
+ + Day - 30;
638
+ }
639
+
640
+
641
+
642
+ void DayToDate(int Day, String Date)
643
+ /* --------- */
644
+ {
645
+ int Year, Month, OrigDay=Day;
646
+
647
+ if ( Day <= 0 )
648
+ {
649
+ strcpy(Date, "?");
650
+ return;
651
+ }
652
+
653
+ Year = (Day - 1) / 365.2425L; /* Year = completed years */
654
+ Day -= Year * 365 + Year / 4 - Year / 100 + Year / 400;
655
+
656
+ if ( Day < 1 )
657
+ {
658
+ Year--;
659
+ Day = OrigDay - (Year * 365 + Year / 4 - Year / 100 + Year / 400);
660
+ }
661
+ else
662
+ if ( Day > 366 ||
663
+ Day == 366 &&
664
+ ( (Year+1) % 4 != 0 || (Year+1) % 100 == 0 && (Year+1) % 400 != 0 ) )
665
+ {
666
+ Year++;
667
+ Day = OrigDay - (Year * 365 + Year / 4 - Year / 100 + Year / 400);
668
+ }
669
+
670
+ Month = (Day + 30) * 12 / 367;
671
+ Day -= 367 * Month / 12 - 30;
672
+ if ( Day < 1 )
673
+ {
674
+ Month = 11;
675
+ Day = 31;
676
+ }
677
+
678
+ Month += 2;
679
+ if ( Month > 12 )
680
+ {
681
+ Month -= 12;
682
+ Year++;
683
+ }
684
+
685
+ sprintf(Date, "%d/%d%d/%d%d", Year, Month/10, Month % 10, Day/10, Day % 10);
686
+ }
687
+
688
+
689
+
690
+ /*************************************************************************/
691
+ /* */
692
+ /* Routines to process clock time and timestamps */
693
+ /* */
694
+ /*************************************************************************/
695
+
696
+
697
+ int TimeToSecs(String TS)
698
+ /* ---------- */
699
+ {
700
+ int Hour, Mins, Secs;
701
+
702
+ if ( strlen(TS) != 8 ) return -1;
703
+
704
+ Hour = GetInt(TS, 2);
705
+ Mins = GetInt(TS+3, 2);
706
+ Secs = GetInt(TS+6, 2);
707
+
708
+ if ( TS[2] != ':' || TS[5] != ':' ||
709
+ Hour >= 24 || Mins >= 60 || Secs >= 60 )
710
+ {
711
+ return -1;
712
+ }
713
+
714
+ return Hour * 3600 + Mins * 60 + Secs;
715
+ }
716
+
717
+
718
+
719
+ void SecsToTime(int Secs, String Time)
720
+ /* ---------- */
721
+ {
722
+ int Hour, Mins;
723
+
724
+ Hour = Secs / 3600;
725
+ Mins = (Secs % 3600) / 60;
726
+ Secs = Secs % 60;
727
+
728
+ sprintf(Time, "%d%d:%d%d:%d%d",
729
+ Hour / 10, Hour % 10,
730
+ Mins / 10, Mins % 10,
731
+ Secs / 10, Secs % 10);
732
+ }
733
+
734
+
735
+
736
+ void SetTSBase(int y)
737
+ /* --------- */
738
+ {
739
+ y -= 15;
740
+ TSBase = y * 365 + y / 4 - y / 100 + y / 400 + (367 * 4) / 12 + 1 - 30;
741
+ }
742
+
743
+
744
+
745
+ int TStampToMins(String TS)
746
+ /* ------------ */
747
+ {
748
+ int Day, Sec, i;
749
+
750
+ /* Check for reasonable length and space between date and time */
751
+
752
+ if ( strlen(TS) < 19 || ! Space(TS[10]) ) return (1 << 30);
753
+
754
+ /* Read date part */
755
+
756
+ TS[10] = '\00';
757
+ Day = DateToDay(TS);
758
+ TS[10] = ' ';
759
+
760
+ /* Skip one or more spaces */
761
+
762
+ for ( i = 11 ; TS[i] && Space(TS[i]) ; i++ )
763
+ ;
764
+
765
+ /* Read time part */
766
+
767
+ Sec = TimeToSecs(TS+i);
768
+
769
+ /* Return a long time in the future if there is an error */
770
+
771
+ return ( Day < 1 || Sec < 0 ? (1 << 30) :
772
+ (Day - TSBase) * 1440 + (Sec + 30) / 60 );
773
+ }
774
+
775
+
776
+
777
+ /*************************************************************************/
778
+ /* */
779
+ /* Convert a continuous value to a string. DS must be */
780
+ /* large enough to hold any value (e.g. a date, time, ...) */
781
+ /* */
782
+ /*************************************************************************/
783
+
784
+
785
+ void CValToStr(ContValue CV, Attribute Att, String DS)
786
+ /* --------- */
787
+ {
788
+ int Mins;
789
+
790
+ if ( TStampVal(Att) )
791
+ {
792
+ DayToDate(floor(CV / 1440) + TSBase, DS);
793
+ DS[10] = ' ';
794
+ Mins = rint(CV) - floor(CV / 1440) * 1440;
795
+ SecsToTime(Mins * 60, DS+11);
796
+ }
797
+ else
798
+ if ( DateVal(Att) )
799
+ {
800
+ DayToDate(CV, DS);
801
+ }
802
+ else
803
+ if ( TimeVal(Att) )
804
+ {
805
+ SecsToTime(CV, DS);
806
+ }
807
+ else
808
+ {
809
+ sprintf(DS, "%.*g", PREC, CV);
810
+ }
811
+ }
812
+
813
+
814
+
815
+ /*************************************************************************/
816
+ /* */
817
+ /* Check option value */
818
+ /* */
819
+ /*************************************************************************/
820
+
821
+
822
+ void Check(float Val, float Low, float High)
823
+ /* ----- */
824
+ {
825
+ if ( Val < Low || Val > High )
826
+ {
827
+ printf("\t** illegal value %g -- should be between %g and %g\n",
828
+ Val, Low, High);
829
+ exit(1);
830
+ }
831
+ }
832
+
833
+
834
+
835
+ #ifdef UTF8
836
+ ///////////////////////////////////////////////////////////////////////////
837
+ // //
838
+ // Routines for Unicode/UTF-8 processing //
839
+ // ------------------------------------- //
840
+ // //
841
+ ///////////////////////////////////////////////////////////////////////////
842
+
843
+ #include <wchar.h>
844
+
845
+
846
+
847
+ /*************************************************************************/
848
+ /* */
849
+ /* Determine the total character width of a UTF-8 string */
850
+ /* */
851
+ /*************************************************************************/
852
+
853
+
854
+ int UTF8CharWidth(unsigned char *U)
855
+ /* ------------- */
856
+ {
857
+ int CWidth=0, Mask, This;
858
+ wchar_t Unicode;
859
+
860
+ while ( *U )
861
+ {
862
+ Unicode = *U;
863
+
864
+ if ( *U < 0x7F )
865
+ {
866
+ /* ASCII character */
867
+
868
+ CWidth++;
869
+ U++;
870
+ }
871
+ else
872
+ {
873
+ /* Discard header bits */
874
+
875
+ Mask = 0x80;
876
+ while ( Unicode & Mask )
877
+ {
878
+ Unicode ^= Mask;
879
+ Mask = Mask >> 1;
880
+ }
881
+
882
+ while ( ((*(++U)) & 0xc0) == 0x80 )
883
+ {
884
+ Unicode = (Unicode << 6) | (*U & 0x3f);
885
+ }
886
+
887
+ if ( (This = wcwidth(Unicode)) > 0 ) CWidth += This;
888
+ }
889
+ }
890
+
891
+ return CWidth;
892
+ }
893
+
894
+
895
+
896
+ ////////////////////////////////////////////////////////////////////////////////
897
+ // Public domain code to determine the width of a Unicode character //
898
+ ////////////////////////////////////////////////////////////////////////////////
899
+
900
+
901
+ /*
902
+ * This is an implementation of wcwidth() and wcswidth() as defined in
903
+ * "The Single UNIX Specification, Version 2, The Open Group, 1997"
904
+ * <http://www.UNIX-systems.org/online.html>
905
+ *
906
+ * Markus Kuhn -- 2000-02-08 -- public domain
907
+ */
908
+
909
+ //#include <wchar.h>
910
+
911
+ /* These functions define the column width of an ISO 10646 character
912
+ * as follows:
913
+ *
914
+ * - The null character (U+0000) has a column width of 0.
915
+ *
916
+ * - Other C0/C1 control characters and DEL will lead to a return
917
+ * value of -1.
918
+ *
919
+ * - Non-spacing and enclosing combining characters (general
920
+ * category code Mn or Me in the Unicode database) have a
921
+ * column width of 0.
922
+ *
923
+ * - Spacing characters in the East Asian Wide (W) or East Asian
924
+ * FullWidth (F) category as defined in Unicode Technical
925
+ * Report #11 have a column width of 2.
926
+ *
927
+ * - All remaining characters (including all printable
928
+ * ISO 8859-1 and WGL4 characters, Unicode control characters,
929
+ * etc.) have a column width of 1.
930
+ *
931
+ * This implementation assumes that wchar_t characters are encoded
932
+ * in ISO 10646.
933
+ */
934
+
935
+ int wcwidth(wchar_t ucs)
936
+ {
937
+ /* sorted list of non-overlapping intervals of non-spacing characters */
938
+ static const struct interval {
939
+ unsigned short first;
940
+ unsigned short last;
941
+ } combining[] = {
942
+ { 0x0300, 0x034E }, { 0x0360, 0x0362 }, { 0x0483, 0x0486 },
943
+ { 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 },
944
+ { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
945
+ { 0x05C4, 0x05C4 }, { 0x064B, 0x0655 }, { 0x0670, 0x0670 },
946
+ { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
947
+ { 0x0711, 0x0711 }, { 0x0730, 0x074A }, { 0x07A6, 0x07B0 },
948
+ { 0x0901, 0x0902 }, { 0x093C, 0x093C }, { 0x0941, 0x0948 },
949
+ { 0x094D, 0x094D }, { 0x0951, 0x0954 }, { 0x0962, 0x0963 },
950
+ { 0x0981, 0x0981 }, { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 },
951
+ { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 }, { 0x0A02, 0x0A02 },
952
+ { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 },
953
+ { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 },
954
+ { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 },
955
+ { 0x0ACD, 0x0ACD }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
956
+ { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
957
+ { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
958
+ { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
959
+ { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBF, 0x0CBF },
960
+ { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD }, { 0x0D41, 0x0D43 },
961
+ { 0x0D4D, 0x0D4D }, { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 },
962
+ { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A },
963
+ { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 },
964
+ { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 },
965
+ { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 },
966
+ { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 },
967
+ { 0x0F90, 0x0F97 }, { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 },
968
+ { 0x102D, 0x1030 }, { 0x1032, 0x1032 }, { 0x1036, 0x1037 },
969
+ { 0x1039, 0x1039 }, { 0x1058, 0x1059 }, { 0x17B7, 0x17BD },
970
+ { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x18A9, 0x18A9 },
971
+ { 0x20D0, 0x20E3 }, { 0x302A, 0x302F }, { 0x3099, 0x309A },
972
+ { 0xFB1E, 0xFB1E }, { 0xFE20, 0xFE23 }
973
+ };
974
+ int min = 0;
975
+ int max = sizeof(combining) / sizeof(struct interval) - 1;
976
+ int mid;
977
+
978
+ /* test for 8-bit control characters */
979
+ if (ucs == 0)
980
+ return 0;
981
+ if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
982
+ return -1;
983
+
984
+ /* first quick check for Latin-1 etc. characters */
985
+ if (ucs < combining[0].first)
986
+ return 1;
987
+
988
+ /* binary search in table of non-spacing characters */
989
+ while (max >= min) {
990
+ mid = (min + max) / 2;
991
+ if (combining[mid].last < ucs)
992
+ min = mid + 1;
993
+ else if (combining[mid].first > ucs)
994
+ max = mid - 1;
995
+ else if (combining[mid].first <= ucs && combining[mid].last >= ucs)
996
+ return 0;
997
+ }
998
+
999
+ /* if we arrive here, ucs is not a combining or C0/C1 control character */
1000
+
1001
+ /* fast test for majority of non-wide scripts */
1002
+ if (ucs < 0x1100)
1003
+ return 1;
1004
+
1005
+ return 1 +
1006
+ ((ucs >= 0x1100 && ucs <= 0x115f) || /* Hangul Jamo */
1007
+ (ucs >= 0x2e80 && ucs <= 0xa4cf && (ucs & ~0x0011) != 0x300a &&
1008
+ ucs != 0x303f) || /* CJK ... Yi */
1009
+ (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
1010
+ (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
1011
+ (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
1012
+ (ucs >= 0xff00 && ucs <= 0xff5f) || /* Fullwidth Forms */
1013
+ (ucs >= 0xffe0 && ucs <= 0xffe6));
1014
+ }
1015
+
1016
+
1017
+ int wcswidth(const wchar_t *pwcs, size_t n)
1018
+ {
1019
+ int w, width = 0;
1020
+
1021
+ for (;*pwcs && n-- > 0; pwcs++)
1022
+ if ((w = wcwidth(*pwcs)) < 0)
1023
+ return -1;
1024
+ else
1025
+ width += w;
1026
+
1027
+ return width;
1028
+ }
1029
+ #endif