aboutsummaryrefslogtreecommitdiff
path: root/src/benchmarks/cfrac/padd.c
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fl.fischer@fau.de>2019-08-24 17:57:51 +0200
committerFlorian Fischer <florian.fl.fischer@fau.de>2019-08-24 17:57:51 +0200
commit77ac9ce0a5c55d4f79f8fb8f7daa59ddb53cb507 (patch)
tree93d4e30a207265af03394d347bfff76ba677f3ce /src/benchmarks/cfrac/padd.c
parent971adefadb94e8780b1a73f08ed11d76c2ead8a2 (diff)
downloadallocbench-77ac9ce0a5c55d4f79f8fb8f7daa59ddb53cb507.tar.gz
allocbench-77ac9ce0a5c55d4f79f8fb8f7daa59ddb53cb507.zip
add cfrac benchmark
Diffstat (limited to 'src/benchmarks/cfrac/padd.c')
-rw-r--r--src/benchmarks/cfrac/padd.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/benchmarks/cfrac/padd.c b/src/benchmarks/cfrac/padd.c
new file mode 100644
index 0000000..62b93d5
--- /dev/null
+++ b/src/benchmarks/cfrac/padd.c
@@ -0,0 +1,94 @@
+#include "pdefs.h"
+#include "precision.h"
+#include <string.h>
+
+#ifdef ASM_16BIT
+#include "asm16bit.h"
+#endif
+
+/*
+ * Add
+ *
+ * This will work correctly if -0 is passed as input
+ */
+precision padd(u, v)
+ register precision v;
+#ifndef ASM_16BIT
+ precision u;
+{
+ register digitPtr wPtr, uPtr, vPtr;
+#else
+ register precision u;
+{
+ register digitPtr wPtr;
+ digitPtr uPtr;
+#endif
+ precision w; /* function result */
+ register accumulator temp; /* 0 <= temp < 2*base */
+ register digit carry; /* 0 <= carry <= 1 */
+#ifdef ASM_16BIT
+ register int size;
+#endif
+
+ (void) pparm(u);
+ (void) pparm(v);
+ if (u->sign != v->sign) { /* Are we are actually subtracting? */
+ w = pUndef;
+ if (v->sign) {
+ v->sign = !v->sign; /* can't generate -0 */
+ pset(&w, psub(u, v));
+ v->sign = !v->sign;
+ } else {
+ u->sign = !u->sign; /* can't generate -0 */
+ pset(&w, psub(v, u));
+ u->sign = !u->sign;
+ }
+ } else {
+ if (u->size < v->size) { /* u is always biggest number */
+ w = u; u = v; v = w;
+ }
+
+ w = palloc(u->size+1); /* there is at most one added digit */
+ if (w == pUndef) return w; /* arguments not destroyed */
+
+ w->sign = u->sign;
+
+ uPtr = u->value;
+ wPtr = w->value;
+#ifndef ASM_16BIT
+ vPtr = v->value;
+ carry = 0;
+ do { /* Add digits in both args */
+ temp = *uPtr++ + *vPtr++; /* 0 <= temp < 2*base-1 */
+ temp += carry; /* 0 <= temp < 2*base */
+ carry = divBase(temp); /* 0 <= carry <= 1 */
+ *wPtr++ = modBase(temp); /* mod has positive args */
+ } while (vPtr < v->value + v->size);
+
+ while (uPtr < u->value + u->size) { /* propogate carry */
+ temp = *uPtr++ + carry;
+ carry = divBase(temp);
+ *wPtr++ = modBase(temp);
+ }
+ *wPtr = carry;
+#else
+ size = v->size;
+ temp = u->size - size;
+ carry = memaddw(wPtr, uPtr, v->value, size);
+ if (temp > 0) {
+ memcpy(wPtr + size, uPtr + size, temp * sizeof(digit));
+ if (carry) {
+ carry = memincw(wPtr + size, temp);
+ }
+ }
+ wPtr[u->size] = carry; /* yes, I do mean u->size */
+#endif
+ if (carry == 0) {
+ --(w->size);
+ }
+ }
+
+ pdestroy(u);
+ pdestroy(v);
+ return presult(w);
+}