aboutsummaryrefslogtreecommitdiffstats
path: root/libnormalform_or2__.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2024-07-19 01:29:42 +0200
committerMattias Andrée <maandree@kth.se>2024-07-19 01:29:42 +0200
commit4294ec0ed06ee34920c9edaeebaeb8b65c720791 (patch)
treee0cded59452597c04fb38f403745a384675cb5f9 /libnormalform_or2__.c
downloadlibnormalform-4294ec0ed06ee34920c9edaeebaeb8b65c720791.tar.gz
libnormalform-4294ec0ed06ee34920c9edaeebaeb8b65c720791.tar.bz2
libnormalform-4294ec0ed06ee34920c9edaeebaeb8b65c720791.tar.xz
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'libnormalform_or2__.c')
-rw-r--r--libnormalform_or2__.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/libnormalform_or2__.c b/libnormalform_or2__.c
new file mode 100644
index 0000000..7d093a0
--- /dev/null
+++ b/libnormalform_or2__.c
@@ -0,0 +1,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