diff options
| author | Mattias Andrée <maandree@kth.se> | 2024-07-19 01:29:42 +0200 |
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2024-07-19 01:29:42 +0200 |
| commit | 4294ec0ed06ee34920c9edaeebaeb8b65c720791 (patch) | |
| tree | e0cded59452597c04fb38f403745a384675cb5f9 /libnormalform_or2__.c | |
| download | libnormalform-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__.c | 119 |
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 |
