1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
/* See LICENSE file for copyright and license details. */
#include "common.h"
#ifndef TEST
/**
* See `.inverse` in `struct libnormalform_sentence` (AND implementation)
*/
static LIBNORMALFORM_SENTENCE *
and_inverse(LIBNORMALFORM_SENTENCE *this)
{
/* ¬(ab) = ¬a + ¬b */
LIBNORMALFORM_SENTENCE *l, *r, *ret;
l = this->data.binary.l->inverse(this->data.binary.l);
if (!l)
return NULL;
r = this->data.binary.r->inverse(this->data.binary.r);
if (!r) {
libnormalform_free(l);
return NULL;
}
ret = libnormalform_or2__(l, r);
if (ret && this->atom) {
ret->atom = this->atom;
ret->atom->refcount += 1;
}
return ret;
}
/**
* See `.equals` in `struct libnormalform_sentence` (AND implementation)
*/
static int
and_equals(LIBNORMALFORM_SENTENCE *this, LIBNORMALFORM_SENTENCE *other, int *inv_out)
{
LIBNORMALFORM_SENTENCE *tl, *tr;
LIBNORMALFORM_SENTENCE *ol, *or;
int inv;
if (other->type != TYPE_AND && other->type != TYPE_OR)
return other->type == TYPE_XOR && other->equals(other, this, inv_out);
tl = this->data.binary.l;
tr = this->data.binary.r;
ol = other->data.binary.l;
or = other->data.binary.r;
if (tl->hash != ol->hash || tr->hash != or->hash)
return 0;
if (!tl->equals(tl, ol, inv_out)) {
if (tl->hash == tr->hash) {
ol = other->data.binary.r;
or = other->data.binary.l;
if (!tl->equals(tl, ol, inv_out))
return 0;
} else {
return 0;
}
}
if (!tr->equals(tr, or, &inv))
return 0;
return inv == *inv_out && inv == (other->type == TYPE_OR);
}
/**
* See `.evaluate` in `struct libnormalform_sentence` (AND implementation)
*/
static int
and_evaluate(LIBNORMALFORM_SENTENCE *this, void *input)
{
int r = this->data.binary.l->evaluate(this->data.binary.l, input);
return r <= 0 ? r : this->data.binary.r->evaluate(this->data.binary.r, input);
}
LIBNORMALFORM_SENTENCE *
(libnormalform_and2__)(LIBNORMALFORM_SENTENCE *l, LIBNORMALFORM_SENTENCE *r)
{
static const struct libnormalform_sentence prototype = {
PROTOTYPE_COMMON,
.type = TYPE_AND,
.inverse = &and_inverse,
.equals = &and_equals,
.evaluate = &and_evaluate
};
LIBNORMALFORM_SENTENCE *ret = malloc(sizeof(*ret));
if (!ret) {
libnormalform_free(l);
libnormalform_free(r);
return NULL;
}
*ret = prototype;
ret->hash = AND_OR_HASH(l, r);
if (l->hash <= r->hash) {
ret->data.binary.l = l;
ret->data.binary.r = r;
} else {
ret->data.binary.l = r;
ret->data.binary.r = l;
}
return ret;
}
#else
CONST int
main(void)
{
return 0; /* indirectly tested */
}
#endif
|