Skip to content

Commit

Permalink
Add boolexpr argset data type
Browse files Browse the repository at this point in the history
  • Loading branch information
cjdrake committed May 24, 2015
1 parent 3efa736 commit 9e8fc72
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 0 deletions.
2 changes: 2 additions & 0 deletions extension/boolexpr/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ all: bld/test/run bld/cover/run bld/lib/libboolexpr.a
BOOLEXPR_HDRS := boolexpr.h

BOOLEXPR_SRCS := \
argset.c \
array.c \
array2.c \
binary.c \
Expand All @@ -63,6 +64,7 @@ BOOLEXPR_TEST_HDRS := test/boolexprtest.hpp
BOOLEXPR_TEST_SRCS := \
test/main.cpp \
test/boolexprtest.cpp \
test/test_argset.cpp \
test/test_array.cpp \
test/test_array2.cpp \
test/test_basic.cpp \
Expand Down
87 changes: 87 additions & 0 deletions extension/boolexpr/argset.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
** Filename: argset.c
*/


#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>

#include "boolexpr.h"


struct BoolExprOrAndArgSet *
BoolExprOrAndArgSet_New(BoolExprKind kind)
{
struct BoolExprOrAndArgSet *argset;

argset = (struct BoolExprOrAndArgSet *) malloc(sizeof(struct BoolExprOrAndArgSet));
if (argset == NULL)
return NULL; // LCOV_EXCL_LINE

argset->kind = kind;
argset->min = true;
argset->max = false;

argset->xs = BoolExprSet_New();
if (argset->xs == NULL) {
free(argset); // LCOV_EXCL_LINE
return NULL; // LCOV_EXCL_LINE
}

return argset;
}


void
BoolExprOrAndArgSet_Del(struct BoolExprOrAndArgSet *argset)
{
BoolExprSet_Del(argset->xs);

free(argset);
}


bool
BoolExprOrAndArgSet_Insert(struct BoolExprOrAndArgSet *argset, struct BoolExpr *key)
{
// 1 + x = 1 ; 0 & x = 0
// x + 0 = x ; x & 1 = x
if (argset->max || key == IDENTITY[argset->kind])
return true;

bool dominate = false;
// x + 1 = 1 ; x & 0 = 0
if (key == DOMINATOR[argset->kind]) {
dominate = true;
}
// x + ~x = 1 ; x & ~x = 0
else if (IS_LIT(key) || IS_NOT(key)) {
struct BoolExpr *ex = Not(key);
dominate = BoolExprSet_Contains(argset->xs, ex);
BoolExpr_DecRef(ex);
}
if (dominate) {
argset->min = false;
argset->max = true;
BoolExprSet_Clear(argset->xs);
return true;
}

// x + (y + z) = x + y + z ; x & (y & z) = x & y & z
if (key->kind == argset->kind) {
for (size_t i = 0; i < key->data.xs->length; ++i) {
if (!BoolExprOrAndArgSet_Insert(argset, key->data.xs->items[i]))
return false; // LCOV_EXCL_LINE
}
return true;
}

// x + x = x
if (!BoolExprSet_Insert(argset->xs, key))
return false; // LCOV_EXCL_LINE
argset->min = false;

return true;
}

18 changes: 18 additions & 0 deletions extension/boolexpr/boolexpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,14 @@ struct BoolExprSetIter {
};


struct BoolExprOrAndArgSet {
BoolExprKind kind;
bool min;
bool max;
struct BoolExprSet *xs;
};


/* Constant expressions */
extern struct BoolExpr Zero;
extern struct BoolExpr One;
Expand Down Expand Up @@ -472,6 +480,16 @@ bool BoolExprSet_Equal(struct BoolExprSet *, struct BoolExprSet *);
void BoolExprSet_Clear(struct BoolExprSet *);


/*
** Return a new OR/AND set
*/
struct BoolExprOrAndArgSet * BoolExprOrAndArgSet_New(BoolExprKind kind);

void BoolExprOrAndArgSet_Del(struct BoolExprOrAndArgSet *);

bool BoolExprOrAndArgSet_Insert(struct BoolExprOrAndArgSet *, struct BoolExpr *key);


#ifdef __cplusplus
}
#endif
Expand Down
72 changes: 72 additions & 0 deletions extension/boolexpr/test/test_argset.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
** Filename: test_argset.cpp
**
** Test the BoolExprArgSet data types.
*/


#include "boolexprtest.hpp"


class BoolExprArgSetTest: public BoolExprTest {};


TEST_F(BoolExprArgSetTest, OrBasic)
{
BoolExprOrAndArgSet *a = BoolExprOrAndArgSet_New(OP_OR);

EXPECT_EQ(a->kind, OP_OR);
EXPECT_TRUE(a->min);
EXPECT_FALSE(a->max);

BoolExprOrAndArgSet_Insert(a, xns[0]);
EXPECT_FALSE(a->min);
EXPECT_EQ(a->xs->length, 1);

BoolExprOrAndArgSet_Insert(a, &Zero);
EXPECT_EQ(a->xs->length, 1);

ops[0] = OrN(2, xs[1], xs[2]);
ops[1] = OrN(2, xs[3], xs[4]);
ops[2] = OrN(2, ops[0], ops[1]);
BoolExprOrAndArgSet_Insert(a, ops[2]);
EXPECT_EQ(a->xs->length, 5);

BoolExprOrAndArgSet_Insert(a, xs[0]);
EXPECT_FALSE(a->min);
EXPECT_TRUE(a->max);
EXPECT_EQ(a->xs->length, 0);

BoolExprOrAndArgSet_Del(a);
}


TEST_F(BoolExprArgSetTest, AndBasic)
{
BoolExprOrAndArgSet *a = BoolExprOrAndArgSet_New(OP_AND);

EXPECT_EQ(a->kind, OP_AND);
EXPECT_TRUE(a->min);
EXPECT_FALSE(a->max);

BoolExprOrAndArgSet_Insert(a, xns[0]);
EXPECT_FALSE(a->min);
EXPECT_EQ(a->xs->length, 1);

BoolExprOrAndArgSet_Insert(a, &One);
EXPECT_EQ(a->xs->length, 1);

ops[0] = AndN(2, xs[1], xs[2]);
ops[1] = AndN(2, xs[3], xs[4]);
ops[2] = AndN(2, ops[0], ops[1]);
BoolExprOrAndArgSet_Insert(a, ops[2]);
EXPECT_EQ(a->xs->length, 5);

BoolExprOrAndArgSet_Insert(a, &Zero);
EXPECT_FALSE(a->min);
EXPECT_TRUE(a->max);
EXPECT_EQ(a->xs->length, 0);

BoolExprOrAndArgSet_Del(a);
}

1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@
pjoin('extension', 'boolexpr'),
],
sources = [
pjoin('extension', 'boolexpr', 'argset.c'),
pjoin('extension', 'boolexpr', 'array.c'),
pjoin('extension', 'boolexpr', 'array2.c'),
pjoin('extension', 'boolexpr', 'binary.c'),
Expand Down

0 comments on commit 9e8fc72

Please sign in to comment.