From 11da511c784eca003deb90c23570f0873954e0de Mon Sep 17 00:00:00 2001 From: Duncan Wilkie Date: Sat, 18 Nov 2023 06:11:09 -0600 Subject: Initial commit. --- ic-reals-6.3/base/strictAlt.c | 129 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 ic-reals-6.3/base/strictAlt.c (limited to 'ic-reals-6.3/base/strictAlt.c') diff --git a/ic-reals-6.3/base/strictAlt.c b/ic-reals-6.3/base/strictAlt.c new file mode 100644 index 0000000..9ae4434 --- /dev/null +++ b/ic-reals-6.3/base/strictAlt.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2000, Imperial College + * + * This file is part of the Imperial College Exact Real Arithmetic Library. + * See the copyright notice included in the distribution for conditions + * of use. + */ + +#include +#include "real.h" +#include "real-impl.h" + +/* + * The conditional is implemented as a function: + * + * void * realAlt(Bool, *void, ...) + * + * where the arguments are a list of guard/value pairs. This is implemented + * using stdarg(3). The last guard must be the constant DEFAULT_GUARD. + */ + +typedef struct ALT_CELL { + Bool guard; + void *value; + struct ALT_CELL *next; +} AltCell; + +#include + +/* + * ### A better scheme would be to put the alt in the heap as well. Perhaps + * later. + */ +void * +realAlt(Bool guard, void *value, ...) +{ + va_list ap; + AltCell *head, *ptr; + AltCell **prev; + void *defaultValue; + void runStack(); + + /* + * The caller is a wally if the first argument is the default guard. + * But we accept it. + */ + if ((unsigned) guard == DEFAULT_GUARD) + return value; + + if (guard->gen.tag.value == LAZY_TRUE) + return value; + + if ((head = (AltCell *) alloca(sizeof(AltCell))) == NULL) + Error(FATAL, E_INT, "realAlt", "alloca failed"); + + head->guard = guard; + head->value = value; + head->next = NULL; + ptr = head; + + /* + * Now we consume the arguments. Each is a guard/value pair. If + * the guard is true, then we just return the value. If not then + * we allocate a cell with the guard and value and add it to + * the list of cells. + */ + va_start(ap, value); + while ((unsigned) (guard = va_arg(ap, Bool)) != DEFAULT_GUARD) { + value = va_arg(ap, void *); + + if (guard->gen.tag.value == LAZY_TRUE) + return value; + + if ((ptr->next = (AltCell *) alloca(sizeof(AltCell))) == NULL) + Error(FATAL, E_INT, "realAlt", "alloca failed"); + + ptr = ptr->next; + ptr->guard = guard; + ptr->value = value; + ptr->next = NULL; + } + defaultValue = va_arg(ap, void *); + va_end(ap); + + /* + * If we reach here, then we have a list of AltCells which + * have guards having value LAZY_UNKNOWN. We now walk down this + * list repeatedly. For each alternative, we force the next value + * in the boolean stream. If any guard becomes true, then we + * return the corresponding value. If something becomes false, + * it gets removed from the list. The loop ends when the list + * becomes empty whereupon we return the default value provided + * at the end of the argument list. + */ + ptr = head; + prev = &head; + while (ptr != NULL) { + if (ptr->guard->gen.tag.value == LAZY_UNKNOWN) { + PUSH_2(ptr->guard->gen.force, ptr->guard); + runStack(); + } + switch (ptr->guard->gen.tag.value) { + case LAZY_TRUE : + return ptr->value; + break; + case LAZY_FALSE : + *prev = ptr->next; /* unlink the cell */ + ptr = ptr->next; + break; + case LAZY_UNKNOWN : + prev = &(ptr->next); + ptr = ptr->next; + break; + default : + Error(FATAL, E_INT, "realAlt", + "invalid boolean value encountered"); + break; + } + + /* + * Reached the end of the list so start from the beginning again. + */ + if (ptr == NULL) { + ptr = head; + prev = &head; + } + } + return defaultValue; +} -- cgit v1.2.3