00001 /*----------------------------------------------------------------------- 00002 * Copyright 2008-2010, DKRZ, Hamburg, Germany. 00003 * All rights reserved. Use is subject to OASIS4 license terms. 00004 *-----------------------------------------------------------------------*/ 00005 00006 #include <stddef.h> 00007 #include "PSMILe_f2c.h" 00008 00009 /*This function is based on the code from the MPFUN90 library 00010 *http://crd.lbl.gov/~dhbailey/mpdist/ 00011 * 00012 *It was necessary to rewrite this function in C, because F90 00013 *does not support the volatile keyword. This keyword is 00014 *necessary to avoid compiler optimisations which use more than 00015 *64bit for intermediate floating point results. 00016 *However, this has some performance drawbacks. Another possible 00017 *solution is to force the compiler to use 64bit arithmetics for 00018 *this function. Unfortunately, this would require compiler 00019 *specific flags. Therefore, I will use this general solution for 00020 *now and may add optimisations for different compilers later. 00021 */ 00022 00023 /* This function add two double-double precision numbers.*/ 00024 00025 #ifdef ANSI_C 00026 00027 void psmile_ddadd (double * dda, double * ddb) 00028 00029 #else 00030 00031 void psmile_ddadd (dda, ddb) 00032 00033 double * dda, * ddb; 00034 00035 #endif 00036 00037 { 00038 volatile double e, t1, t2, t2_1, t2_2, t2_3; 00039 /* Compute dda + ddb using Knuth's trick.*/ 00040 t1 = dda[0] + ddb[0]; 00041 e = t1 - dda[0]; 00042 t2_1 = t1 - e; 00043 t2_2 = dda[0] - t2_1; 00044 t2_3 = ddb[0] - e; 00045 t2 = t2_3 + t2_2; 00046 t2 += dda[1]; 00047 t2 += ddb[1]; 00048 00049 /* The result is t1 + t2, after normalization.*/ 00050 ddb[0] = t1 + t2; 00051 e = t1 + t2; 00052 e -= t1; 00053 ddb[1] = t2 - e; 00054 00055 return; 00056 }