aboutsummaryrefslogtreecommitdiffstats
path: root/libnormalform_or2__.c
blob: 7d093a02e65fce87ec09423daa996db4706a77ce (plain) (blame)
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` (OR implementation)
 */
static LIBNORMALFORM_SENTENCE *
or_inverse(LIBNORMALFORM_SENTENCE *this)
{
	/* ¬(a + b) = ¬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_and2__(l, r);
        if (ret && this->atom) {
		ret->atom = this->atom;
                ret->atom->refcount += 1;
	}
        return ret;
}


/** 
 * See `.equals` in `struct libnormalform_sentence` (OR implementation)
 */
static int
or_equals(LIBNORMALFORM_SENTENCE *this, LIBNORMALFORM_SENTENCE *other, int *inv_out)
{
	LIBNORMALFORM_SENTENCE *tl, *tr;
	LIBNORMALFORM_SENTENCE *ol, *or;
	int inv;

	if (other->type != TYPE_OR && other->type != TYPE_AND)
		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_AND);
}


/** 
 * See `.evaluate` in `struct libnormalform_sentence` (OR implementation)
 */
static int
or_evaluate(LIBNORMALFORM_SENTENCE *this, void *input)
{
	int r = this->data.binary.l->evaluate(this->data.binary.l, input);
	return r ? r : this->data.binary.r->evaluate(this->data.binary.r, input);
}


LIBNORMALFORM_SENTENCE *
(libnormalform_or2__)(LIBNORMALFORM_SENTENCE *l, LIBNORMALFORM_SENTENCE *r)
{
	static const struct libnormalform_sentence prototype = {
		PROTOTYPE_COMMON,
		.type = TYPE_OR,
		.inverse = &or_inverse,
		.equals = &or_equals,
		.evaluate = &or_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