numeric.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:5k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: numeric.c,v $
  4.  * PRODUCTION Revision 1000.0  2003/10/29 20:35:08  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R1.1
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
  10.  * Copyright (C) 1998-1999  Brian Bruns
  11.  *
  12.  * This library is free software; you can redistribute it and/or
  13.  * modify it under the terms of the GNU Library General Public
  14.  * License as published by the Free Software Foundation; either
  15.  * version 2 of the License, or (at your option) any later version.
  16.  *
  17.  * This library is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  20.  * Library General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU Library General Public
  23.  * License along with this library; if not, write to the
  24.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  25.  * Boston, MA 02111-1307, USA.
  26.  */
  27. #include <tds_config.h>
  28. #include <tds.h>
  29. #include <stdio.h>
  30. #ifdef DMALLOC
  31. #include <dmalloc.h>
  32. #endif
  33. /* 
  34. ** these routines use arrays of unsigned char to handle arbitrary
  35. ** precision numbers.  All-in-all it's probably pretty slow, but it
  36. ** does work. I just heard of a GNU lib for arb. precision math, so
  37. ** that might be an option in the future.
  38. */
  39. static int multiply_byte(unsigned char *product, int num, unsigned char *multiplier);
  40. static int do_carry(unsigned char *product);
  41. static char *array_to_string(unsigned char *array, int scale, char *s);
  42. /*
  43. ** The following little table is indexed by precision-1 and will
  44. ** tell us the number of bytes required to store the specified
  45. ** precision (with the sign).
  46. ** Support precision up to 77 digits
  47. */
  48. const int g__numeric_bytes_per_prec[] =
  49. {
  50.  -1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 
  51.   6, 6, 6, 7, 7, 8, 8, 9, 9, 9,
  52.   10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 
  53.   14, 14, 15, 15, 16, 16, 16, 17, 17, 18, 
  54.   18, 19, 19, 19, 20, 20, 21, 21, 21, 22, 
  55.   22, 23, 23, 24, 24, 24, 25, 25, 26, 26, 
  56.   26, 27, 27, 28, 28, 28, 29, 29, 30, 30,
  57.   31, 31, 31, 32, 32, 33, 33, 33
  58. };
  59. /*
  60. ** money is a special case of numeric really...that why its here
  61. */
  62. char *tds_money_to_string(TDS_MONEY *money, char *s)
  63. {
  64. unsigned char multiplier[MAXPRECISION], temp[MAXPRECISION];
  65. unsigned char product[MAXPRECISION];
  66. unsigned char *number;
  67. #ifndef WORDS_BIGENDIAN
  68. unsigned char reorder[8];
  69. #endif
  70. int num_bytes = 8;
  71. int i;
  72. int pos;
  73. int neg=0;
  74. memset(multiplier,0,MAXPRECISION);
  75. memset(product,0,MAXPRECISION);
  76. multiplier[0]=1;
  77. #ifdef WORDS_BIGENDIAN
  78. /* big endian makes things easy */
  79. number = (unsigned char *) money;
  80. #else
  81. /* money is two 32 bit ints and thus is out of order on 
  82. ** little endian machines. Proof of the superiority of 
  83. ** big endian design. ;)
  84. */
  85. number = (unsigned char *) money;
  86. for (i=0;i<4;i++)
  87. reorder[3-i] = number[i];
  88. for (i=4;i<8;i++)
  89. reorder[7-i+4] = number[i];
  90. number = reorder;
  91. #endif
  92. if (number[0] & 0x80) {
  93. /* negative number -- preform two's complement */
  94. neg = 1;
  95. for (i=0;i<8;i++) {
  96. number[i] = ~number[i];
  97. }
  98. for (i=7; i>=0; i--) {
  99. number[i] += 1;
  100. if (number[i]!=0) break;
  101. }
  102. }
  103. for (pos=num_bytes-1;pos>=0;pos--) {
  104. multiply_byte(product, number[pos], multiplier);
  105. memcpy(temp, multiplier, MAXPRECISION);
  106. memset(multiplier,0,MAXPRECISION);
  107. multiply_byte(multiplier, 256, temp);
  108. }
  109. if (neg) {
  110. s[0]='-';
  111. array_to_string(product, 4, &s[1]);
  112. } else {
  113. array_to_string(product, 4, s);
  114. }
  115. return s;
  116. }
  117. char *tds_numeric_to_string(TDS_NUMERIC *numeric, char *s)
  118. {
  119. unsigned char multiplier[MAXPRECISION], temp[MAXPRECISION];
  120. unsigned char product[MAXPRECISION];
  121. unsigned char *number;
  122. int num_bytes;
  123. int pos;
  124. memset(multiplier,0,MAXPRECISION);
  125. memset(product,0,MAXPRECISION);
  126. multiplier[0]=1;
  127. number = numeric->array;
  128. num_bytes = g__numeric_bytes_per_prec[numeric->precision];
  129. if (numeric->array[0] == 1)
  130. *s++ = '-';
  131. for (pos=num_bytes-1;pos>0;pos--) {
  132. multiply_byte(product, number[pos], multiplier);
  133. memcpy(temp, multiplier, MAXPRECISION);
  134. memset(multiplier,0,MAXPRECISION);
  135. multiply_byte(multiplier, 256, temp);
  136. }
  137. array_to_string(product, numeric->scale, s);
  138. return s;
  139. }
  140. static int multiply_byte(unsigned char *product, int num, unsigned char *multiplier)
  141. {
  142. unsigned char number[3];
  143. int i, top, j, start;
  144. number[0]=num%10;
  145. number[1]=(num/10)%10;
  146. number[2]=(num/100)%10;
  147. for (top=MAXPRECISION-1;top>=0 && !multiplier[top];top--);
  148. start=0;
  149. for (i=0;i<=top;i++) {
  150. for (j=0;j<3;j++) {
  151. product[j+start]+=multiplier[i]*number[j];
  152. }
  153. do_carry(product);
  154. start++;
  155. }
  156. return 0;
  157. }
  158. static int do_carry(unsigned char *product)
  159. {
  160. int j;
  161. for (j=0;j<MAXPRECISION;j++) {
  162. if (product[j]>9) {
  163. product[j+1]+=product[j]/10;
  164. product[j]=product[j]%10;
  165. }
  166. }
  167. return 0;
  168. }
  169. static char *array_to_string(unsigned char *array, int scale, char *s)
  170. {
  171. int top, i, j;
  172. for (top=MAXPRECISION-1;top>=0 && top>scale && !array[top];top--);
  173. if (top == -1)
  174. {
  175. s[0] = '0';
  176. s[1] = '';
  177. return s;
  178. }
  179. j=0;
  180. for (i=top;i>=0;i--) {
  181. if (top+1-j == scale) s[j++]='.';
  182. s[j++]=array[i]+'0';
  183. }
  184. s[j]='';
  185. return s;
  186. }