src/sct_accuracy.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2007 by Aleksander Morgado Juez                         *
00003  *   scitime@aleksander_morgado.mm.st                                      *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU Library General Public License as       *
00007  *   published by the Free Software Foundation; either version 2 of the    *
00008  *   License, or (at your option) any later version.                       *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU Library General Public     *
00016  *   License along with this program; if not, write to the                 *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 
00021 #include "scitime.h"
00022 
00023 static int _sct_get_exponent_from_double(const double number, int *pExponent);
00024 
00025 SCT_RET sct_set_accuracy (sct_time_ptr pElem, SCT_ACCURACY accuracy)
00026 {
00027     pElem->accuracy = accuracy;
00028     return SCT_RET_OK;
00029 }
00030 
00031 
00032 SCT_ACCURACY sct_get_accuracy (sct_time_ptr pElem)
00033 {
00034     return pElem->accuracy;
00035 }
00036 
00037 
00038 
00039 
00040 
00041 
00042 SCT_ACCURACY sct_get_accuracy_from_jd(const double jd)
00043 {
00044     int accuracyValue = 100;
00045     int exponent = 0;
00046 
00047     if( _sct_get_exponent_from_double(jd, &exponent) != SCT_RET_OK)
00048     {
00049         #ifdef SCT_DEBUG
00050             fprintf(stderr, "[scitime:%s] >> Could not get exponent...\n",
00051             __FUNCTION__);
00052         #endif
00053         return SCT_ACCURACY_DAYS;
00054     }
00055 
00056     // From http://en.wikipedia.org/wiki/IEEE_754
00057     //Double precision doubles structure:
00058     // - 1 bit for the sign (63)
00059     // - 11 bits for the exponent (52 to 62)
00060     // - 52 bit for the fraction
00061 
00062     //The number of correct digits in the whole double is given by:
00063     // 2^52 is = 4503599627370496 (16 digits) 
00064     // We will say it's 15 de maximum number of correct digits (skipping the
00065     //    last one)
00066     // So, the correct number of digits after the comma will be:
00067     //  c = 15 - exponent
00068     // For example, if the number is 10.5, exponent will be 1, so the correct
00069     //  number of digits after the comma will be 14
00070     // In this example, if the given value is a JD date, it says that its
00071     //  accuracy is correct until the 14th decimal value--> 10^-14 days!
00072 
00073     // Now accuracy must be converted to secs directly...
00074     //  1 sec = 1.15 E-5 days ... so... 5 full digits are due to getting
00075     //  the seconds of the number
00076 
00077 
00078     // So, finally... the correct number of digits AFTER the secs is 10
00079     accuracyValue = exponent -10;
00080 
00081     if(accuracyValue > SCT_ACCURACY_DAYS)
00082     {
00083         #ifdef SCT_DEBUG
00084             fprintf(stderr, "[scitime:%s] >> Accuracy is WORSE than days "
00085                 "(1E%d secs)!\n", __FUNCTION__, accuracyValue);
00086         #endif
00087         return SCT_ACCURACY_DAYS;
00088     }
00089     if(accuracyValue < SCT_ACCURACY_FEMTOSECS)
00090     {
00091         #ifdef SCT_DEBUG
00092             fprintf(stderr, "[scitime:%s] >> Accuracy is BETTER than femtosecs "
00093                 "(1E%d secs)! (Resetting to 1E-15 secs)\n",
00094             __FUNCTION__, accuracyValue);
00095         #endif
00096         return SCT_ACCURACY_FEMTOSECS;
00097     }
00098 
00099     return (SCT_ACCURACY)(accuracyValue);
00100 }
00101 
00102 SCT_ACCURACY sct_get_accuracy_from_secs(const double secs)
00103 {
00104     int accuracyValue = 100;
00105     int exponent = 0;
00106 
00107     if( _sct_get_exponent_from_double(secs, &exponent) != SCT_RET_OK)
00108     {
00109         #ifdef SCT_DEBUG
00110             fprintf(stderr, "[scitime:%s] >> Could not get exponent...\n",
00111             __FUNCTION__);
00112         #endif
00113         return SCT_ACCURACY_DAYS;
00114     }
00115 
00116     // From http://en.wikipedia.org/wiki/IEEE_754
00117     //Double precision doubles structure:
00118     // - 1 bit for the sign (63)
00119     // - 11 bits for the exponent (52 to 62)
00120     // - 52 bit for the fraction
00121 
00122     //The number of correct digits in the whole double is given by:
00123     // 2^52 is = 4503599627370496 (16 digits) 
00124     // We will say it's 15 de maximum number of correct digits (skipping the
00125     //    last one)
00126     // So, the correct number of digits after the comma will be:
00127     //  c = 15 - exponent
00128     // For example, if the number is 10.5, exponent will be 1, so the correct
00129     //  number of digits after the comma will be 14
00130 
00131     // Now accuracy must be converted to secs directly... but it's already in
00132     //  seconds!! 
00133 
00134     // So... the correct number of digits is 15
00135     accuracyValue = exponent -15;
00136 
00137     if(accuracyValue > SCT_ACCURACY_DAYS)
00138     {
00139         #ifdef SCT_DEBUG
00140             fprintf(stderr, "[scitime:%s] >> Accuracy is WORSE than days "
00141                 "(1E%d secs)!\n", __FUNCTION__, accuracyValue);
00142         #endif
00143         return SCT_ACCURACY_DAYS;
00144     }
00145     if(accuracyValue < SCT_ACCURACY_FEMTOSECS)
00146     {
00147         #ifdef SCT_DEBUG
00148             fprintf(stderr, "[scitime:%s] >> Accuracy is BETTER than femtosecs "
00149                 "(1E%d secs)! (Resetting to 1E-15 secs)\n",
00150             __FUNCTION__, accuracyValue);
00151         #endif
00152         return SCT_ACCURACY_FEMTOSECS;
00153     }
00154 
00155     return (SCT_ACCURACY)(accuracyValue);
00156 }
00157 
00158 
00159 static int _sct_get_exponent_from_double(const double number, int *pExponent)
00160 {
00161     char aux[50];
00162     char *expS = NULL;
00163 
00164     //Get value of the EXPONENT... can be done faster probably (TODO)
00165     memset(&aux[0],0,sizeof(char)*50);
00166     sprintf(aux,"%E",number);
00167     expS = strstr(aux,"E");
00168     if(expS == NULL)
00169     {
00170         #ifdef SCT_DEBUG
00171         fprintf(stderr, "[scitime:%s] >> Invalid string (%s) to get the "
00172             "exponent!\n", __FUNCTION__, aux);
00173         #endif
00174         return SCT_RET_INVALID_NUMBER;
00175     }
00176     else
00177     {
00178         *pExponent = atoi(&expS[1]);
00179     }
00180     return SCT_RET_OK;
00181 }
00182 

Generated on Sun May 20 15:32:42 2007 for scitime by  doxygen 1.5.1