/* 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