From 4294ec0ed06ee34920c9edaeebaeb8b65c720791 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Fri, 19 Jul 2024 01:29:42 +0200 Subject: First commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- libnormalform_and2__.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 libnormalform_and2__.c (limited to 'libnormalform_and2__.c') diff --git a/libnormalform_and2__.c b/libnormalform_and2__.c new file mode 100644 index 0000000..c20eb3e --- /dev/null +++ b/libnormalform_and2__.c @@ -0,0 +1,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 -- cgit v1.3.1