atof.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:5k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17. /*
  18.   A quicker atof. About 2-10 times faster than standard atof on sparc.
  19.   This don't handle iee-options (NaN...) and the presission :s is a little
  20.   less for some high exponential numbers (+-1 at 14th place).
  21.   Returns 0.0 if overflow or wrong number.
  22.   Must be inited with init_my_atof to handle possibly overflows.
  23. */
  24. #include <global.h>
  25. #ifdef USE_MY_ATOF /* Skipp if we don't want it */
  26. #include <m_ctype.h>
  27. #include <floatingpoint.h>
  28. #include <signal.h>
  29. /* Read a double. If float is wrong return 0.
  30.    float ::= [space]* [sign] {digit}+  decimal-point {digit}+ [exponent] |
  31.    [sign] {digit}+  [decimal-point {digit}*] exponent |
  32.    [sign] {digit}+  decimal-point [{digit}*] exponent |
  33.    [sign] decimal-point {digit}* exponent |
  34.    exponent :: = exponent-marker [sign] {digit}+
  35.    exponent-marker ::= E e
  36.    */
  37. #define is_exponent_marker(ch) (ch == 'E' || ch == 'e')
  38. static void my_atof_overflow  _A((int sig,int code, struct sigcontext *scp,
  39.       char *addr));
  40. static int parse_sign _A((char **str));
  41. static void parse_float_number_part _A((char **str,double *number, int *length));
  42. static void parse_decimal_number_part _A((char **str,double *number));
  43. static int parse_int_number_part _A((char **str,uint *number));
  44. static int volatile overflow,in_my_atof;
  45. static sigfpe_handler_type old_overflow_handler;
  46. void init_my_atof()
  47. {
  48.   old_overflow_handler = (sigfpe_handler_type)
  49.     ieee_handler("get", "overflow", old_overflow_handler);
  50.   VOID(ieee_handler("set", "overflow", my_atof_overflow));
  51.   return;
  52. }
  53. static void my_atof_overflow(sig, code, scp, addr)
  54. int sig;
  55. int code;
  56. struct sigcontext *scp;
  57. char *addr;
  58. {
  59.   if (!in_my_atof)
  60.     old_overflow_handler(sig,code,scp,addr);
  61.   else
  62.     overflow=1;
  63.   return;
  64. }
  65. double my_atof(src)
  66. const char *src;
  67. {
  68.   int sign, exp_sign; /* is number negative (+1) or positive (-1) */
  69.   int length_before_point;
  70.   double after_point; /* Number after decimal point and before exp */
  71.   uint exponent; /* Exponent value */
  72.   double exp_log,exp_val;
  73.   char *tmp_src;
  74.   double result_number;
  75.   tmp_src = (char*) src;
  76.   while (isspace(tmp_src[0]))
  77.     tmp_src++; /* Skipp pre-space */
  78.   sign = parse_sign(&tmp_src);
  79.   overflow=0;
  80.   in_my_atof=1;
  81.   parse_float_number_part(&tmp_src, &result_number, &length_before_point);
  82.   if (*tmp_src == '.')
  83.   {
  84.     tmp_src++;
  85.     parse_decimal_number_part(&tmp_src, &after_point);
  86.     result_number += after_point;
  87.   }
  88.   else if (length_before_point == 0)
  89.   {
  90.     in_my_atof=0;
  91.     return 0.0;
  92.   }
  93.   if (is_exponent_marker(*tmp_src))
  94.   {
  95.     tmp_src++;
  96.     exp_sign = parse_sign(&tmp_src);
  97.     overflow|=parse_int_number_part(&tmp_src, &exponent);
  98.     exp_log=10.0; exp_val=1.0;
  99.     for (;;)
  100.     {
  101.       if (exponent & 1)
  102.       {
  103. exp_val*= exp_log;
  104. exponent--;
  105.       }
  106.       if (!exponent)
  107. break;
  108.       exp_log*=exp_log;
  109.       exponent>>=1;
  110.     }
  111.     if (exp_sign < 0)
  112.       result_number*=exp_val;
  113.     else
  114.       result_number/=exp_val;
  115.   }
  116.   if (sign > 0)
  117.     result_number= -result_number;
  118.   in_my_atof=0;
  119.   if (overflow)
  120.     return 0.0;
  121.   return result_number;
  122. }
  123. static int parse_sign(str)
  124. char **str;
  125. {
  126.   if (**str == '-')
  127.   {
  128.     (*str)++;
  129.     return 1;
  130.   }
  131.   if (**str == '+')
  132.     (*str)++;
  133.   return -1;
  134. }
  135. /* Get number with may be separated with ',' */
  136. static void parse_float_number_part(str, number, length)
  137. char **str;
  138. double *number;
  139. int *length;
  140. {
  141.   *number = 0;
  142.   *length = 0;
  143.   for (;;)
  144.   {
  145.     while (isdigit(**str))
  146.     {
  147.       (*length)++;
  148.       *number = (*number * 10) + (**str - '0');
  149.       (*str)++;
  150.     }
  151.     if (**str != ',')
  152.       return; /* Skipp possibly ',' */
  153.     (*str)++;
  154.   }
  155. }
  156. static void parse_decimal_number_part(str, number)
  157. char **str;
  158. double *number;
  159. {
  160.   double exp_log;
  161.   *number = 0;
  162.   exp_log=1/10.0;
  163.   while (isdigit(**str))
  164.   {
  165.     *number+= (**str - '0')*exp_log;
  166.     exp_log/=10;
  167.     (*str)++;
  168.   }
  169. }
  170. /* Parses int suitably for exponent */
  171. static int parse_int_number_part(str, number)
  172. char **str;
  173. uint *number;
  174. {
  175.   *number = 0;
  176.   while (isdigit(**str))
  177.   {
  178.     if (*number >= ((uint) ~0)/10)
  179.       return 1; /* Don't overflow */
  180.     *number = (*number * 10) + **str - '0';
  181.     (*str)++;
  182.   }
  183.   return 0;
  184. }
  185. #endif