aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interval.c82
-rw-r--r--interval.h16
-rw-r--r--mkfile7
-rw-r--r--readme.md3
-rw-r--r--test.c41
5 files changed, 149 insertions, 0 deletions
diff --git a/interval.c b/interval.c
new file mode 100644
index 0000000..df9c14c
--- /dev/null
+++ b/interval.c
@@ -0,0 +1,82 @@
+/*
+ * for reference:
+ * - James F. Allen, Maintaining Knowledge about Temporal Intervals, CACM November 1983, Vol. 26, No. 11
+ * - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6188649/
+ */
+#include <u.h>
+#include <libc.h>
+#include "interval.h"
+
+static int
+interval_before(Interval *i, Interval *ii)
+{
+ return i->t1 < ii->t0;
+}
+
+static int
+interval_equals(Interval *i, Interval *ii)
+{
+ return i->t0 == ii->t0 &&
+ i->t1 == ii->t1;
+}
+
+static int
+interval_overlaps(Interval *i, Interval *ii)
+{
+ return i->t0 < ii->t0 &&
+ i->t1 > ii->t0 &&
+ i->t1 < ii->t1;
+}
+
+static int
+interval_meets(Interval *i, Interval *ii)
+{
+ return i->t1 == ii->t0;
+}
+
+static int
+interval_during(Interval *i, Interval *ii)
+{
+ return (i->t0 > ii->t0 && i->t1 <= ii->t1) ||
+ (i->t0 >= ii->t0 && i->t1 < ii->t1);
+}
+
+static int
+interval_intersects(Interval *i, Interval *ii)
+{
+ return i->equals(i, ii) ||
+ i->overlaps(i, ii) ||
+ ii->overlaps(ii, i) ||
+ i->during(i, ii) ||
+ ii->during(ii, i);
+}
+
+Interval *
+mkinterval(uvlong t0, uvlong t1)
+{
+ Interval *i;
+
+ assert(t0 <= t1);
+
+ i = malloc(sizeof(Interval));
+ if(i == nil)
+ sysfatal("mkinterval: %r");
+
+ i->t0 = t0;
+ i->t1 = t1;
+ i->∆t = t1-t0;
+ i->before = interval_before;
+ i->equals = interval_equals;
+ i->overlaps = interval_overlaps;
+ i->meets = interval_meets;
+ i->during = interval_during;
+ i->intersects = interval_intersects;
+
+ return i;
+}
+
+void
+rminterval(Interval *i)
+{
+ free(i);
+}
diff --git a/interval.h b/interval.h
new file mode 100644
index 0000000..e4a799e
--- /dev/null
+++ b/interval.h
@@ -0,0 +1,16 @@
+typedef struct Interval Interval;
+struct Interval
+{
+ uvlong t0, t1;
+ uvlong ∆t; /* duration */
+
+ int (*before)(Interval*, Interval*);
+ int (*equals)(Interval*, Interval*);
+ int (*overlaps)(Interval*, Interval*);
+ int (*meets)(Interval*, Interval*);
+ int (*during)(Interval*, Interval*);
+ int (*intersects)(Interval*, Interval*);
+};
+
+Interval *mkinterval(uvlong, uvlong);
+void rminterval(Interval*);
diff --git a/mkfile b/mkfile
new file mode 100644
index 0000000..40c98dd
--- /dev/null
+++ b/mkfile
@@ -0,0 +1,7 @@
+</$objtype/mkfile
+
+LIB=libinterval.a$O
+OFILES=interval.$O
+HFILES=interval.h
+
+</sys/src/cmd/mklib
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..df2e81b
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,3 @@
+# libinterval
+
+Implementation of the ideas published in James F. Allen, Maintaining Knowledge about Temporal Intervals, CACM November 1983, Vol. 26, No. 11.
diff --git a/test.c b/test.c
new file mode 100644
index 0000000..2246330
--- /dev/null
+++ b/test.c
@@ -0,0 +1,41 @@
+#include <u.h>
+#include <libc.h>
+#include "interval.h"
+
+char *
+yn(int n)
+{
+ return n == 0? "no": "yes";
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s\n", argv0);
+ exits("usage");
+}
+
+void
+main(int argc, char *argv[])
+{
+ Interval *a, *b;
+
+ ARGBEGIN{
+ default: usage();
+ }ARGEND;
+ if(argc != 0)
+ usage();
+
+ a = mkinterval(20, 30);
+ b = mkinterval(25, 60);
+ print("a before b:\t%s\n", yn(a->before(a, b)));
+ print("a equals b:\t%s\n", yn(a->equals(a, b)));
+ print("a overlaps b:\t%s\n", yn(a->overlaps(a, b)));
+ print("a meets b:\t%s\n", yn(a->meets(a, b)));
+ print("a during b:\t%s\n", yn(a->during(a, b)));
+ print("a intersects b:\t%s\n", yn(a->intersects(a, b)));
+ rminterval(a);
+ rminterval(b);
+
+ exits(nil);
+}