diff options
| author | Julian Weigt <juw@posteo.de> | 2025-12-28 11:20:32 +0000 |
|---|---|---|
| committer | Julian Weigt <juw@posteo.de> | 2026-02-04 15:55:48 +0100 |
| commit | 944f90c47ffcde862dfe5f258de0b1ebf229c20e (patch) | |
| tree | 0d4ef7dd8a8b97c440dc6abec538403c5726d0fd | |
| parent | e65748fa8908c46ae2e6af7ef63d28fb3427238d (diff) | |
Implement double arithmetic with error bounds.
| -rw-r--r-- | charf.c | 20 | ||||
| -rw-r--r-- | double-error.c | 83 | ||||
| -rw-r--r-- | double-error.h | 23 | ||||
| -rw-r--r-- | double.c | 2 | ||||
| -rw-r--r-- | double.h | 2 | ||||
| -rw-r--r-- | ratio.c | 6 | ||||
| -rw-r--r-- | ratio.h | 2 |
7 files changed, 132 insertions, 6 deletions
@@ -4,13 +4,21 @@ #include <pthread.h> #include <assert.h> -#ifndef EXACT -#define EXACT false +#define DOUBLEMODE 0 +#define DOUBLEERRORMODE 1 +#define RATIOMODE 2 + +#ifndef MODE +#define MODE DOUBLEMODE #endif #define NUM_THREADS 6 -#if EXACT +#if MODE == DOUBLEERRORMODE +#include "double-error.h" +#define VALUETYPE double_error +#define EXPTYPE double_error +#elif MODE == RATIOMODE #include "ratio.h" #define VALUETYPE rational #define EXPTYPE unsigned int @@ -173,7 +181,9 @@ void compute(EXPTYPE p, int t){ printf("f: "); for(int i=0;i<D;i++) printf("%1.0f ",to_double(f[i])); printf("\n"); - printf("%.4f\n",to_double(r)); + char s[128]; + to_string(s,r); + printf("%.4f (%s)\n",to_double(r),s); } } @@ -194,7 +204,7 @@ void* perform_work(void* arguments){ int main() { /*exponent p of the L^p norm to consider*/ - EXPTYPE p = 1; + EXPTYPE p = to_exptype(1); /*Iterate over all strings of 0s and 1s with length N. Those will represent f.*/ int t = 1; diff --git a/double-error.c b/double-error.c new file mode 100644 index 0000000..aaaa405 --- /dev/null +++ b/double-error.c @@ -0,0 +1,83 @@ +#include <stdlib.h> +#include <math.h> +#include <stdio.h> +#include <float.h> + +#define EPS 2*DBL_EPSILON + +typedef struct {double d; double e;} double_error; + +double_error convert_int(int i){ + double_error de; + de.d = (double) i; + de.e = EPS*abs(i); + return de; +} + +double_error to_exptype(double d){ + double_error de; + de.d = d; + de.e = EPS*fabs(d); + return de; +} + +double_error sum(double_error de1, double_error de2){ + double_error de; + de.d = de1.d + de2.d; + de.e = de1.e + de2.e + ( fabs(de1.d) + fabs(de2.d) + de1.e + de2.e )*EPS; + return de; +} + +double_error difference(double_error de1, double_error de2){ + double_error de2m; + de2m.d = -de2.d; + de2m.e = de2.e; + return sum(de1,de2m); +} + +bool is_greater(double_error de1, double_error de2){ return (de1.d > de2.d); } + +double_error product(double_error de1, double_error de2){ + double_error de; + de.d = de1.d * de2.d; + double p12 = fabs(de1.d)*de2.e; + double p21 = fabs(de2.d)*de1.e; + double p22 = de1.e+de2.e; + double s = p12 + p21 + p22; + de.e = s + ( fabs(de.d) + s )*EPS; + return de; +} + +double_error ratio(double_error de1, double_error de2){ + double_error de2i; + de2i.d = 1/de2.d; + de2i.e = 2*de2.e/(de2.d*de2.d) + fabs(de2i.d)*EPS; //2* is random extra margin in case error is large + return product(de1,de2i); + +} + +double_error absolute(double_error de){ + double_error dea; + dea.d = fabs(de.d); + dea.e = de.e; + return dea; +} + +double_error power(double_error de, double_error p) { + double_error dep; + dep.d = pow(de.d,p.d); + if(de.d > 0 && p.d > 0){ + dep.e = 2*fabs(dep.d)*( de.e/fabs(de.d) + p.e/fabs(p.d) + EPS ); //again random 2* + } + else { + dep.e = de.e + EPS; + } + return dep; +} + +double to_double(double_error de){ return de.d; } + +bool to_string(char* s, double_error de){ + sprintf(s,"%f +/- %.16f",de.d,de.e); + return true; +} diff --git a/double-error.h b/double-error.h new file mode 100644 index 0000000..413d0dc --- /dev/null +++ b/double-error.h @@ -0,0 +1,23 @@ +typedef struct {double d; double e;} double_error; + +double_error convert_int(int); + +double_error to_exptype(double); + +bool is_greater(double_error,double_error); + +double_error sum(double_error,double_error); + +double_error difference(double_error,double_error); + +double_error product(double_error,double_error); + +double_error ratio(double_error,double_error); + +double_error absolute(double_error); + +double_error power(double_error,double_error); + +double to_double(double_error); + +bool to_string(char*,double_error); @@ -4,6 +4,8 @@ double convert_int(int i){ return (double) i; } +double to_exptype(double d){ return d; } + double sum(double d1, double d2){ return d1+d2; } double difference(double d1, double d2){ return d1-d2; } @@ -1,5 +1,7 @@ double convert_int(int); +double to_exptype(double); + bool is_greater(double,double); double sum(double,double); @@ -2,6 +2,7 @@ #include <stdlib.h> #include <math.h> #include <limits.h> +#include <float.h> typedef unsigned long long num; @@ -35,6 +36,8 @@ rational convert_int(int i){ return r; } +unsigned int to_exptype(unsigned int i){ return i; } + num gcd(num a, num b){ num c; while (b) { @@ -120,6 +123,7 @@ double to_double(rational r){ } bool to_string(char* s,rational r){ - sprintf(s,"%llu / %llu",r.n,r.d); + double f = to_double(r); + sprintf(s,"%llu / %llu = %f +- %.24f",r.n,r.d,f,f*DBL_EPSILON); return true; } @@ -6,6 +6,8 @@ typedef struct {bool s; unsigned long long n; unsigned long long d;} rational; rational convert_int(int); +unsigned int to_exptype(unsigned int); + bool is_greater(rational,rational); rational sum(rational,rational); |
