source: git/factory/ftest/fbinops.m4 @ 3ba84c

spielwiese
Last change on this file since 3ba84c was 3ba84c, checked in by Jens Schmidt <schmidt@…>, 26 years ago
***** merge from branch `factory-gcd' to main trunk git-svn-id: file:///usr/local/Singular/svn/trunk@1329 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 9.1 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2/* $Id: fbinops.m4,v 1.5 1998-04-06 11:05:17 schmidt Exp $ */
3
4ftestSetNameOfGame( fbinops, `"
5Usage: fbinops [<options>] [<envSpec>] <f> <operator> <g>
6  executes operator an canonical forms f, g.
7
8  The following operators (with aliases) are recognized:
9  `+', `-', `*' (= `mul'), `/', `div', `%', `mod': return a canonicalform;
10  `==', `!=', `<' (= `lt'), `>' (= `gt'): return an integer (i.e. boolean)
11"'`' )
12
13//{{{ docu
14//
15// ftestAlgorithm.m4 - ftestAlgorithm test program.
16//
17// To create ftestAlgorithm.cc, run m4 using the ftest_util.m4 library in
18// the following way:
19//
20// m4 ftest_util.m4 ftestAlgorithm.m4 > ftestAlgorithm.cc
21//
22//}}}
23
24ftestPreprocInit();
25
26ftestGlobalInit();
27
28//{{{ typedef binOpCFT, binOpBoolT, binOpCFTestT
29//{{{ docu
30//
31// typedef binOpCFT, binOpBoolT, binOpCFTestT -
32//   pointer to functions types.
33//
34// binOpCFT, binOpBoolT: pointers to binary operators getting two
35//   CanonicalForms and returning a CanonicalForm or a bool, resp.
36// binOpCFTestT: pointers to test functions getting three
37//   CanonicalForms and returning a ftestStatusT.
38//
39//}}}
40typedef CanonicalForm (* binOpCFT)( const CanonicalForm &, const CanonicalForm & );
41typedef bool (* binOpBoolT)( const CanonicalForm &, const CanonicalForm & );
42typedef ftestStatusT (* binOpCFTestT)( const CanonicalForm &, const CanonicalForm &, const CanonicalForm & );
43//}}}
44
45//{{{ struct binOpCFSpecT, binOpBoolSpecT
46//{{{ docu
47//
48// struct binOpCFSpecT, struct binOpBoolSpecT - types describing a binary
49//   operator.
50//
51// binOpCFSpecT describes binary operators returning a CanonicalForm.
52// binOpBoolSpecT describes binary operators returning a bool.
53//
54// op: pointer to operator
55// test: test function
56// operatorName: symbolic name, used as a key
57// operatorTag: tag to print result
58//
59//}}}
60struct binOpCFSpecT
61{
62    binOpCFT op;
63    binOpCFTestT test;
64    const char * operatorName;
65    const char * operatorTag;
66};
67
68struct binOpBoolSpecT
69{
70    binOpBoolT op;
71    const char * operatorName;
72    const char * operatorTag;
73};
74//}}}
75
76//{{{ comparison functions, tests
77static inline bool
78ftestBoolEquiv ( bool a, bool b )
79{
80    return ( ( !a || b ) && ( !b || a ) );
81}
82
83static inline bool
84ftestCheckImplementation ( const CanonicalForm & f, const CanonicalForm & g )
85{
86    return ( ftestBoolEquiv( f == g, !(f != g) )
87             && ftestBoolEquiv( f < g, g > f )
88             && ftestBoolEquiv( f != g, (f < g) || (f > g) ) );
89}
90
91static inline bool
92ftestCheckTrichotomy ( const CanonicalForm & f, const CanonicalForm & g )
93{
94    if ( f == g ) {
95        if ( f < g ) return false;
96        if ( g < f ) return false;
97        return true;
98    } else if ( f < g ) {
99        if ( f == g ) return false;
100        if ( g < f ) return false;
101        return true;
102    } else if ( g < f ) {
103        if ( f == g ) return false;
104        if ( f < g ) return false;
105        return true;
106    } else
107        return false;
108}
109
110static ftestStatusT
111ftestRelOpTest ( const CanonicalForm & f, const CanonicalForm & g )
112{
113    // check reflexivity
114    if ( ! ( f == f ) ) {
115        ftestError( CheckError, "reflexivity check (f) failed\n" );
116        return Failed;
117    }
118    // check reflexivity
119    if ( ! ( g == g ) ) {
120        ftestError( CheckError, "reflexivity check (g) failed\n" );
121        return Failed;
122    }
123    // check symmetry
124    if ( ! ftestBoolEquiv( f == g, g == f ) ) {
125        ftestError( CheckError, "symmetry check failed\n" );
126        return Failed;
127    }
128    // check implementation of operators
129    if ( ! ftestCheckImplementation( f, g ) ) {
130        ftestError( CheckError, "implementation check (f, g) failed\n" );
131        return Failed;
132    }
133    // check implementation of operators
134    if ( ! ftestCheckImplementation( g, f ) ) {
135        ftestError( CheckError, "implementation check (g, f) failed\n" );
136        return Failed;
137    }
138    // check trichotomy
139    if ( ! ftestCheckTrichotomy( f, g ) ) {
140        ftestError( CheckError, "trichotomy check (f, g) failed\n" );
141        return Failed;
142    }
143    // check trichotomy
144    if ( ! ftestCheckTrichotomy( g, f ) ) {
145        ftestError( CheckError, "trichotomy check (g, f) failed\n" );
146        return Failed;
147    }
148
149    return Passed;
150}
151//}}}
152
153//{{{ arithmetic functions, tests
154static ftestStatusT
155ftestArithTest( const CanonicalForm &, const CanonicalForm &, const CanonicalForm & )
156{
157    return UndefinedResult;
158}
159
160static ftestStatusT
161ftestDivideTest( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm & quot )
162{
163    CanonicalForm rem = f % g;
164    if ( ! ((quot*g)+rem-f).isZero() ) {
165        ftestError( CheckError, "f != (f/g)*g+(f%%g)\n" );
166        return Failed;
167    } else if ( f.inBaseDomain() && g.inBaseDomain() && getCharacteristic() == 0
168                && (rem < 0 || rem > abs( g )) ) {
169        // check euclidean division in Z
170        ftestError( CheckError, "!(0 <= f%g < abs(g))\n" );
171        return Failed;
172    } else if ( f.inPolyDomain() || g.inPolyDomain() ) {
173        // check euclidean division in R[x]
174        Variable x = (mvar( f ) >= mvar( g )) ? mvar( f ) : mvar( g );
175        if ( rem.isZero() || degree( rem, x ) < degree( g, x ) )
176            return Passed;
177        else {
178            ftestError( CheckError, "degree(rem) >= degree(g)\n" );
179            return Failed;
180        }
181    } else
182        return Passed;
183}
184
185static ftestStatusT
186ftestDivTest( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm & quot )
187{
188    if ( ! (f%g).isZero() ) {
189        ftestError( CheckError, "g does not divide f\n" );
190        return Failed;
191    } else if ( f != (quot*g) ) {
192        ftestError( CheckError, "f != (div(f, g)*g)\n" );
193        return Failed;
194    } else
195        return Passed;
196}
197
198static ftestStatusT
199ftestModuloTest( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm & rem )
200{
201    if ( ! (((f/g)*g)+(rem)-f).isZero() ) {
202        ftestError( CheckError, "f != (f/g)*g+(f%%g)\n" );
203        return Failed;
204    } else if ( f.inBaseDomain() && g.inBaseDomain() && getCharacteristic() == 0
205                && (rem < 0 || rem > abs( g )) ) {
206        // check euclidean division in Z
207        ftestError( CheckError, "!(0 <= f%g < abs(g))\n" );
208        return Failed;
209    } else if ( f.inPolyDomain() || g.inPolyDomain() ) {
210        // check euclidean division in R[x]
211        Variable x = (mvar( f ) >= mvar( g )) ? mvar( f ) : mvar( g );
212        if ( rem.isZero() || degree( rem, x ) < degree( g, x ) )
213            return Passed;
214        else {
215            ftestError( CheckError, "degree(rem) >= degree(g)\n" );
216            return Failed;
217        }
218    } else
219        return Passed;
220}
221//}}}
222
223//{{{ binOpCFSpecArray, binOpBoolSpecArray
224//{{{ docu
225//
226// binOpCFSpec, binOpBoolSpec - arrays of operator descriptions.
227//
228//}}}
229binOpCFSpecT binOpCFSpecArray[] =
230{
231    { &operator+, ftestArithTest, "+", "f+g" },
232    { &operator-, ftestArithTest, "-", "f-g" },
233    { &operator*, ftestArithTest, "*", "f*g" },
234    { &operator*, ftestArithTest, "mul", "f*g" },
235    { &operator/, ftestDivideTest, "/", "f/g" },
236    { &div, ftestDivTest, "div", "div(f,g)" },
237    { &operator%, ftestModuloTest, "%", "f%g" },
238    { &mod, ftestModuloTest, "mod", "mod(f,g)" },
239    { 0, 0, 0, 0 }
240};
241
242binOpBoolSpecT binOpBoolSpecArray[] =
243{
244    { &operator==, "==", "f==g" },
245    { &operator!=, "!=", "f!=g" },
246    { &operator>, ">", "f>g" },
247    { &operator>, "gt", "f>g" },
248    { &operator<, "<", "f<g" },
249    { &operator<, "lt", "f<g" },
250    { 0, 0, 0 }
251};
252//}}}
253
254//
255// - main program.
256//
257int
258main ( int argc, char ** argv )
259{
260    // initialization
261    ftestMainInit();
262
263    // declare input and output variables
264    ftestOutVar( CanonicalForm, resultCF );
265    ftestOutVar( bool, resultBool );
266    ftestInVar( CanonicalForm, f );
267    ftestInVar( CanonicalForm, g );
268
269    // process argument list and set environment
270    ftestGetOpts();
271    ftestGetEnv();
272
273    // read first operand
274    ftestGetInVar( f );
275
276    // declarations to search operator
277    const char * operatorName = 0;
278    const char * operatorTag = 0;
279    binOpCFT binOpCF = 0;
280    binOpBoolT binOpBool = 0;
281    binOpCFTestT binOpCFTest = 0;
282
283    // get and search operator
284    if ( argv[ optind ] ) {
285        operatorName = ftestSkipBlancs( argv[ optind++ ] );
286    } else
287        ftestError( CommandlineError,
288                    "expected operator specification at position %d in commandline\n",
289                    optind );
290
291    // search through binOpCFSpecArray
292    int i = 0;
293    while ( binOpCFSpecArray[i].operatorName ) {
294        if ( strcmp( binOpCFSpecArray[i].operatorName, operatorName ) == 0 ) {
295            binOpCF = binOpCFSpecArray[i].op;
296            binOpCFTest = binOpCFSpecArray[i].test;
297            operatorTag = binOpCFSpecArray[i].operatorTag;
298            break;
299        }
300        i++;
301    }
302
303    // search through binOpBoolSpecArray
304    i = 0;
305    if ( ! binOpCF )
306        while ( binOpBoolSpecArray[i].operatorName ) {
307            if ( strcmp( binOpBoolSpecArray[i].operatorName, operatorName ) == 0 ) {
308                binOpBool = binOpBoolSpecArray[i].op;
309                operatorTag = binOpBoolSpecArray[i].operatorTag;
310                break;
311            }
312            i++;
313        }
314
315    // check whether operator has been found
316    if ( binOpCF == 0 && binOpBool == 0 )
317        ftestError( CommandlineError,
318                    "unknown operator `%s'\n", operatorName );
319
320    // read second operand
321    ftestGetInVar( g );
322
323    // do the test!
324    if ( binOpCF ) {
325        ftestRun(
326            resultCF = binOpCF( f, g ); );
327        ftestCheck(
328            binOpCFTest( f, g, resultCF ) );
329    } else {
330        ftestRun(
331            resultBool = binOpBool( f, g ); );
332        ftestCheck(
333            ftestRelOpTest( f, g ) );
334    }
335
336    // print results
337    if ( binOpCF ) {
338        ftestOutput( operatorTag, resultCF );
339    } else {
340        ftestOutput( operatorTag, resultBool );
341    }
342
343    // clean up
344    ftestMainExit();
345}
Note: See TracBrowser for help on using the repository browser.