see5-installer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.rubocop.yml +11 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +10 -0
- data/README.md +29 -0
- data/Rakefile +12 -0
- data/ext/c5.0/Makefile +86 -0
- data/ext/c5.0/attwinnow.c +394 -0
- data/ext/c5.0/c50.c +330 -0
- data/ext/c5.0/classify.c +700 -0
- data/ext/c5.0/confmat.c +195 -0
- data/ext/c5.0/construct.c +853 -0
- data/ext/c5.0/contin.c +613 -0
- data/ext/c5.0/defns.i +788 -0
- data/ext/c5.0/discr.c +307 -0
- data/ext/c5.0/extern.i +170 -0
- data/ext/c5.0/formrules.c +720 -0
- data/ext/c5.0/formtree.c +1158 -0
- data/ext/c5.0/getdata.c +521 -0
- data/ext/c5.0/getnames.c +733 -0
- data/ext/c5.0/global.c +211 -0
- data/ext/c5.0/gpl.txt +674 -0
- data/ext/c5.0/implicitatt.c +1112 -0
- data/ext/c5.0/info.c +146 -0
- data/ext/c5.0/mcost.c +138 -0
- data/ext/c5.0/modelfiles.c +952 -0
- data/ext/c5.0/p-thresh.c +313 -0
- data/ext/c5.0/prune.c +1069 -0
- data/ext/c5.0/report.c +345 -0
- data/ext/c5.0/rules.c +579 -0
- data/ext/c5.0/ruletree.c +398 -0
- data/ext/c5.0/siftrules.c +1285 -0
- data/ext/c5.0/sort.c +156 -0
- data/ext/c5.0/subset.c +599 -0
- data/ext/c5.0/text.i +223 -0
- data/ext/c5.0/trees.c +740 -0
- data/ext/c5.0/update.c +129 -0
- data/ext/c5.0/utility.c +1146 -0
- data/ext/c5.0/xval +150 -0
- data/ext/c5.0/xval.c +402 -0
- data/ext/gritbot/Makefile +98 -0
- data/ext/gritbot/check.c +1110 -0
- data/ext/gritbot/cluster.c +342 -0
- data/ext/gritbot/common.c +1269 -0
- data/ext/gritbot/continatt.c +412 -0
- data/ext/gritbot/defns.i +623 -0
- data/ext/gritbot/discratt.c +459 -0
- data/ext/gritbot/extern.i +101 -0
- data/ext/gritbot/getdata.c +329 -0
- data/ext/gritbot/getnames.c +573 -0
- data/ext/gritbot/global.c +104 -0
- data/ext/gritbot/gpl.txt +674 -0
- data/ext/gritbot/gritbot.c +295 -0
- data/ext/gritbot/implicitatt.c +1108 -0
- data/ext/gritbot/inspect.c +794 -0
- data/ext/gritbot/modelfiles.c +687 -0
- data/ext/gritbot/outlier.c +415 -0
- data/ext/gritbot/sort.c +130 -0
- data/ext/gritbot/text.i +159 -0
- data/ext/gritbot/update.c +126 -0
- data/ext/gritbot/utility.c +1029 -0
- data/ext/see5-installer/extconf.rb +25 -0
- data/lib/see5/installer.rb +10 -0
- data/lib/see5/installer/version.rb +7 -0
- data/see5-installer.gemspec +30 -0
- metadata +115 -0
data/ext/gritbot/text.i
ADDED
@@ -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
|