00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "postgres.h"
00020
00021 #include <limits.h>
00022 #include <ctype.h>
00023 #include <math.h>
00024 #include <locale.h>
00025
00026 #include "libpq/pqformat.h"
00027 #include "utils/builtins.h"
00028 #include "utils/cash.h"
00029 #include "utils/int8.h"
00030 #include "utils/numeric.h"
00031 #include "utils/pg_locale.h"
00032
00033
00034
00035
00036
00037
00038 static const char *
00039 num_word(Cash value)
00040 {
00041 static char buf[128];
00042 static const char *small[] = {
00043 "zero", "one", "two", "three", "four", "five", "six", "seven",
00044 "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
00045 "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty",
00046 "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"
00047 };
00048 const char **big = small + 18;
00049 int tu = value % 100;
00050
00051
00052 if (value <= 20)
00053 return small[value];
00054
00055
00056 if (!tu)
00057 {
00058 sprintf(buf, "%s hundred", small[value / 100]);
00059 return buf;
00060 }
00061
00062
00063 if (value > 99)
00064 {
00065
00066 if (value % 10 == 0 && tu > 10)
00067 sprintf(buf, "%s hundred %s",
00068 small[value / 100], big[tu / 10]);
00069 else if (tu < 20)
00070 sprintf(buf, "%s hundred and %s",
00071 small[value / 100], small[tu]);
00072 else
00073 sprintf(buf, "%s hundred %s %s",
00074 small[value / 100], big[tu / 10], small[tu % 10]);
00075 }
00076 else
00077 {
00078
00079 if (value % 10 == 0 && tu > 10)
00080 sprintf(buf, "%s", big[tu / 10]);
00081 else if (tu < 20)
00082 sprintf(buf, "%s", small[tu]);
00083 else
00084 sprintf(buf, "%s %s", big[tu / 10], small[tu % 10]);
00085 }
00086
00087 return buf;
00088 }
00089
00090
00091
00092
00093
00094
00095
00096 Datum
00097 cash_in(PG_FUNCTION_ARGS)
00098 {
00099 char *str = PG_GETARG_CSTRING(0);
00100 Cash result;
00101 Cash value = 0;
00102 Cash dec = 0;
00103 Cash sgn = 1;
00104 bool seen_dot = false;
00105 const char *s = str;
00106 int fpoint;
00107 char dsymbol;
00108 const char *ssymbol,
00109 *psymbol,
00110 *nsymbol,
00111 *csymbol;
00112 struct lconv *lconvert = PGLC_localeconv();
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 fpoint = lconvert->frac_digits;
00125 if (fpoint < 0 || fpoint > 10)
00126 fpoint = 2;
00127
00128
00129 if (*lconvert->mon_decimal_point != '\0' &&
00130 lconvert->mon_decimal_point[1] == '\0')
00131 dsymbol = *lconvert->mon_decimal_point;
00132 else
00133 dsymbol = '.';
00134 if (*lconvert->mon_thousands_sep != '\0')
00135 ssymbol = lconvert->mon_thousands_sep;
00136 else
00137 ssymbol = (dsymbol != ',') ? "," : ".";
00138 csymbol = (*lconvert->currency_symbol != '\0') ? lconvert->currency_symbol : "$";
00139 psymbol = (*lconvert->positive_sign != '\0') ? lconvert->positive_sign : "+";
00140 nsymbol = (*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-";
00141
00142 #ifdef CASHDEBUG
00143 printf("cashin- precision '%d'; decimal '%c'; thousands '%s'; currency '%s'; positive '%s'; negative '%s'\n",
00144 fpoint, dsymbol, ssymbol, csymbol, psymbol, nsymbol);
00145 #endif
00146
00147
00148
00149 while (isspace((unsigned char) *s))
00150 s++;
00151 if (strncmp(s, csymbol, strlen(csymbol)) == 0)
00152 s += strlen(csymbol);
00153 while (isspace((unsigned char) *s))
00154 s++;
00155
00156 #ifdef CASHDEBUG
00157 printf("cashin- string is '%s'\n", s);
00158 #endif
00159
00160
00161
00162
00163 if (strncmp(s, nsymbol, strlen(nsymbol)) == 0)
00164 {
00165 sgn = -1;
00166 s += strlen(nsymbol);
00167 }
00168 else if (*s == '(')
00169 {
00170 sgn = -1;
00171 s++;
00172 }
00173 else if (strncmp(s, psymbol, strlen(psymbol)) == 0)
00174 s += strlen(psymbol);
00175
00176 #ifdef CASHDEBUG
00177 printf("cashin- string is '%s'\n", s);
00178 #endif
00179
00180
00181 while (isspace((unsigned char) *s))
00182 s++;
00183 if (strncmp(s, csymbol, strlen(csymbol)) == 0)
00184 s += strlen(csymbol);
00185 while (isspace((unsigned char) *s))
00186 s++;
00187
00188 #ifdef CASHDEBUG
00189 printf("cashin- string is '%s'\n", s);
00190 #endif
00191
00192 for (; *s; s++)
00193 {
00194
00195
00196 if (isdigit((unsigned char) *s) && (!seen_dot || dec < fpoint))
00197 {
00198 value = (value * 10) + (*s - '0');
00199
00200 if (seen_dot)
00201 dec++;
00202 }
00203
00204 else if (*s == dsymbol && !seen_dot)
00205 {
00206 seen_dot = true;
00207 }
00208
00209 else if (strncmp(s, ssymbol, strlen(ssymbol)) == 0)
00210 s += strlen(ssymbol) - 1;
00211 else
00212 break;
00213 }
00214
00215
00216 if (isdigit((unsigned char) *s) && *s >= '5')
00217 value++;
00218
00219
00220 for (; dec < fpoint; dec++)
00221 value *= 10;
00222
00223
00224
00225
00226
00227 while (isdigit((unsigned char) *s))
00228 s++;
00229
00230 while (*s)
00231 {
00232 if (isspace((unsigned char) *s) || *s == ')')
00233 s++;
00234 else if (strncmp(s, nsymbol, strlen(nsymbol)) == 0)
00235 {
00236 sgn = -1;
00237 s += strlen(nsymbol);
00238 }
00239 else if (strncmp(s, psymbol, strlen(psymbol)) == 0)
00240 s += strlen(psymbol);
00241 else if (strncmp(s, csymbol, strlen(csymbol)) == 0)
00242 s += strlen(csymbol);
00243 else
00244 ereport(ERROR,
00245 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00246 errmsg("invalid input syntax for type money: \"%s\"",
00247 str)));
00248 }
00249
00250 result = value * sgn;
00251
00252 #ifdef CASHDEBUG
00253 printf("cashin- result is " INT64_FORMAT "\n", result);
00254 #endif
00255
00256 PG_RETURN_CASH(result);
00257 }
00258
00259
00260
00261
00262
00263
00264 Datum
00265 cash_out(PG_FUNCTION_ARGS)
00266 {
00267 Cash value = PG_GETARG_CASH(0);
00268 char *result;
00269 char buf[128];
00270 char *bufptr;
00271 int digit_pos;
00272 int points,
00273 mon_group;
00274 char dsymbol;
00275 const char *ssymbol,
00276 *csymbol,
00277 *signsymbol;
00278 char sign_posn,
00279 cs_precedes,
00280 sep_by_space;
00281 struct lconv *lconvert = PGLC_localeconv();
00282
00283
00284 points = lconvert->frac_digits;
00285 if (points < 0 || points > 10)
00286 points = 2;
00287
00288
00289
00290
00291
00292 mon_group = *lconvert->mon_grouping;
00293 if (mon_group <= 0 || mon_group > 6)
00294 mon_group = 3;
00295
00296
00297 if (*lconvert->mon_decimal_point != '\0' &&
00298 lconvert->mon_decimal_point[1] == '\0')
00299 dsymbol = *lconvert->mon_decimal_point;
00300 else
00301 dsymbol = '.';
00302 if (*lconvert->mon_thousands_sep != '\0')
00303 ssymbol = lconvert->mon_thousands_sep;
00304 else
00305 ssymbol = (dsymbol != ',') ? "," : ".";
00306 csymbol = (*lconvert->currency_symbol != '\0') ? lconvert->currency_symbol : "$";
00307
00308 if (value < 0)
00309 {
00310
00311 value = -value;
00312
00313 signsymbol = (*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-";
00314 sign_posn = lconvert->n_sign_posn;
00315 cs_precedes = lconvert->n_cs_precedes;
00316 sep_by_space = lconvert->n_sep_by_space;
00317 }
00318 else
00319 {
00320 signsymbol = lconvert->positive_sign;
00321 sign_posn = lconvert->p_sign_posn;
00322 cs_precedes = lconvert->p_cs_precedes;
00323 sep_by_space = lconvert->p_sep_by_space;
00324 }
00325
00326
00327 bufptr = buf + sizeof(buf) - 1;
00328 *bufptr = '\0';
00329
00330
00331
00332
00333
00334
00335
00336 digit_pos = points;
00337 do
00338 {
00339 if (points && digit_pos == 0)
00340 {
00341
00342 *(--bufptr) = dsymbol;
00343 }
00344 else if (digit_pos < 0 && (digit_pos % mon_group) == 0)
00345 {
00346
00347 bufptr -= strlen(ssymbol);
00348 memcpy(bufptr, ssymbol, strlen(ssymbol));
00349 }
00350
00351 *(--bufptr) = ((uint64) value % 10) + '0';
00352 value = ((uint64) value) / 10;
00353 digit_pos--;
00354 } while (value || digit_pos >= 0);
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 result = palloc(strlen(bufptr) + strlen(csymbol) + strlen(signsymbol) + 4);
00381
00382 switch (sign_posn)
00383 {
00384 case 0:
00385 if (cs_precedes)
00386 sprintf(result, "(%s%s%s)",
00387 csymbol,
00388 (sep_by_space == 1) ? " " : "",
00389 bufptr);
00390 else
00391 sprintf(result, "(%s%s%s)",
00392 bufptr,
00393 (sep_by_space == 1) ? " " : "",
00394 csymbol);
00395 break;
00396 case 1:
00397 default:
00398 if (cs_precedes)
00399 sprintf(result, "%s%s%s%s%s",
00400 signsymbol,
00401 (sep_by_space == 2) ? " " : "",
00402 csymbol,
00403 (sep_by_space == 1) ? " " : "",
00404 bufptr);
00405 else
00406 sprintf(result, "%s%s%s%s%s",
00407 signsymbol,
00408 (sep_by_space == 2) ? " " : "",
00409 bufptr,
00410 (sep_by_space == 1) ? " " : "",
00411 csymbol);
00412 break;
00413 case 2:
00414 if (cs_precedes)
00415 sprintf(result, "%s%s%s%s%s",
00416 csymbol,
00417 (sep_by_space == 1) ? " " : "",
00418 bufptr,
00419 (sep_by_space == 2) ? " " : "",
00420 signsymbol);
00421 else
00422 sprintf(result, "%s%s%s%s%s",
00423 bufptr,
00424 (sep_by_space == 1) ? " " : "",
00425 csymbol,
00426 (sep_by_space == 2) ? " " : "",
00427 signsymbol);
00428 break;
00429 case 3:
00430 if (cs_precedes)
00431 sprintf(result, "%s%s%s%s%s",
00432 signsymbol,
00433 (sep_by_space == 2) ? " " : "",
00434 csymbol,
00435 (sep_by_space == 1) ? " " : "",
00436 bufptr);
00437 else
00438 sprintf(result, "%s%s%s%s%s",
00439 bufptr,
00440 (sep_by_space == 1) ? " " : "",
00441 signsymbol,
00442 (sep_by_space == 2) ? " " : "",
00443 csymbol);
00444 break;
00445 case 4:
00446 if (cs_precedes)
00447 sprintf(result, "%s%s%s%s%s",
00448 csymbol,
00449 (sep_by_space == 2) ? " " : "",
00450 signsymbol,
00451 (sep_by_space == 1) ? " " : "",
00452 bufptr);
00453 else
00454 sprintf(result, "%s%s%s%s%s",
00455 bufptr,
00456 (sep_by_space == 1) ? " " : "",
00457 csymbol,
00458 (sep_by_space == 2) ? " " : "",
00459 signsymbol);
00460 break;
00461 }
00462
00463 PG_RETURN_CSTRING(result);
00464 }
00465
00466
00467
00468
00469 Datum
00470 cash_recv(PG_FUNCTION_ARGS)
00471 {
00472 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
00473
00474 PG_RETURN_CASH((Cash) pq_getmsgint64(buf));
00475 }
00476
00477
00478
00479
00480 Datum
00481 cash_send(PG_FUNCTION_ARGS)
00482 {
00483 Cash arg1 = PG_GETARG_CASH(0);
00484 StringInfoData buf;
00485
00486 pq_begintypsend(&buf);
00487 pq_sendint64(&buf, arg1);
00488 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
00489 }
00490
00491
00492
00493
00494
00495 Datum
00496 cash_eq(PG_FUNCTION_ARGS)
00497 {
00498 Cash c1 = PG_GETARG_CASH(0);
00499 Cash c2 = PG_GETARG_CASH(1);
00500
00501 PG_RETURN_BOOL(c1 == c2);
00502 }
00503
00504 Datum
00505 cash_ne(PG_FUNCTION_ARGS)
00506 {
00507 Cash c1 = PG_GETARG_CASH(0);
00508 Cash c2 = PG_GETARG_CASH(1);
00509
00510 PG_RETURN_BOOL(c1 != c2);
00511 }
00512
00513 Datum
00514 cash_lt(PG_FUNCTION_ARGS)
00515 {
00516 Cash c1 = PG_GETARG_CASH(0);
00517 Cash c2 = PG_GETARG_CASH(1);
00518
00519 PG_RETURN_BOOL(c1 < c2);
00520 }
00521
00522 Datum
00523 cash_le(PG_FUNCTION_ARGS)
00524 {
00525 Cash c1 = PG_GETARG_CASH(0);
00526 Cash c2 = PG_GETARG_CASH(1);
00527
00528 PG_RETURN_BOOL(c1 <= c2);
00529 }
00530
00531 Datum
00532 cash_gt(PG_FUNCTION_ARGS)
00533 {
00534 Cash c1 = PG_GETARG_CASH(0);
00535 Cash c2 = PG_GETARG_CASH(1);
00536
00537 PG_RETURN_BOOL(c1 > c2);
00538 }
00539
00540 Datum
00541 cash_ge(PG_FUNCTION_ARGS)
00542 {
00543 Cash c1 = PG_GETARG_CASH(0);
00544 Cash c2 = PG_GETARG_CASH(1);
00545
00546 PG_RETURN_BOOL(c1 >= c2);
00547 }
00548
00549 Datum
00550 cash_cmp(PG_FUNCTION_ARGS)
00551 {
00552 Cash c1 = PG_GETARG_CASH(0);
00553 Cash c2 = PG_GETARG_CASH(1);
00554
00555 if (c1 > c2)
00556 PG_RETURN_INT32(1);
00557 else if (c1 == c2)
00558 PG_RETURN_INT32(0);
00559 else
00560 PG_RETURN_INT32(-1);
00561 }
00562
00563
00564
00565
00566
00567 Datum
00568 cash_pl(PG_FUNCTION_ARGS)
00569 {
00570 Cash c1 = PG_GETARG_CASH(0);
00571 Cash c2 = PG_GETARG_CASH(1);
00572 Cash result;
00573
00574 result = c1 + c2;
00575
00576 PG_RETURN_CASH(result);
00577 }
00578
00579
00580
00581
00582
00583 Datum
00584 cash_mi(PG_FUNCTION_ARGS)
00585 {
00586 Cash c1 = PG_GETARG_CASH(0);
00587 Cash c2 = PG_GETARG_CASH(1);
00588 Cash result;
00589
00590 result = c1 - c2;
00591
00592 PG_RETURN_CASH(result);
00593 }
00594
00595
00596
00597
00598
00599 Datum
00600 cash_div_cash(PG_FUNCTION_ARGS)
00601 {
00602 Cash dividend = PG_GETARG_CASH(0);
00603 Cash divisor = PG_GETARG_CASH(1);
00604 float8 quotient;
00605
00606 if (divisor == 0)
00607 ereport(ERROR,
00608 (errcode(ERRCODE_DIVISION_BY_ZERO),
00609 errmsg("division by zero")));
00610
00611 quotient = (float8) dividend / (float8) divisor;
00612 PG_RETURN_FLOAT8(quotient);
00613 }
00614
00615
00616
00617
00618
00619 Datum
00620 cash_mul_flt8(PG_FUNCTION_ARGS)
00621 {
00622 Cash c = PG_GETARG_CASH(0);
00623 float8 f = PG_GETARG_FLOAT8(1);
00624 Cash result;
00625
00626 result = c * f;
00627 PG_RETURN_CASH(result);
00628 }
00629
00630
00631
00632
00633
00634 Datum
00635 flt8_mul_cash(PG_FUNCTION_ARGS)
00636 {
00637 float8 f = PG_GETARG_FLOAT8(0);
00638 Cash c = PG_GETARG_CASH(1);
00639 Cash result;
00640
00641 result = f * c;
00642 PG_RETURN_CASH(result);
00643 }
00644
00645
00646
00647
00648
00649 Datum
00650 cash_div_flt8(PG_FUNCTION_ARGS)
00651 {
00652 Cash c = PG_GETARG_CASH(0);
00653 float8 f = PG_GETARG_FLOAT8(1);
00654 Cash result;
00655
00656 if (f == 0.0)
00657 ereport(ERROR,
00658 (errcode(ERRCODE_DIVISION_BY_ZERO),
00659 errmsg("division by zero")));
00660
00661 result = rint(c / f);
00662 PG_RETURN_CASH(result);
00663 }
00664
00665
00666
00667
00668
00669 Datum
00670 cash_mul_flt4(PG_FUNCTION_ARGS)
00671 {
00672 Cash c = PG_GETARG_CASH(0);
00673 float4 f = PG_GETARG_FLOAT4(1);
00674 Cash result;
00675
00676 result = c * f;
00677 PG_RETURN_CASH(result);
00678 }
00679
00680
00681
00682
00683
00684 Datum
00685 flt4_mul_cash(PG_FUNCTION_ARGS)
00686 {
00687 float4 f = PG_GETARG_FLOAT4(0);
00688 Cash c = PG_GETARG_CASH(1);
00689 Cash result;
00690
00691 result = f * c;
00692 PG_RETURN_CASH(result);
00693 }
00694
00695
00696
00697
00698
00699
00700 Datum
00701 cash_div_flt4(PG_FUNCTION_ARGS)
00702 {
00703 Cash c = PG_GETARG_CASH(0);
00704 float4 f = PG_GETARG_FLOAT4(1);
00705 Cash result;
00706
00707 if (f == 0.0)
00708 ereport(ERROR,
00709 (errcode(ERRCODE_DIVISION_BY_ZERO),
00710 errmsg("division by zero")));
00711
00712 result = rint(c / f);
00713 PG_RETURN_CASH(result);
00714 }
00715
00716
00717
00718
00719
00720 Datum
00721 cash_mul_int8(PG_FUNCTION_ARGS)
00722 {
00723 Cash c = PG_GETARG_CASH(0);
00724 int64 i = PG_GETARG_INT64(1);
00725 Cash result;
00726
00727 result = c * i;
00728 PG_RETURN_CASH(result);
00729 }
00730
00731
00732
00733
00734
00735 Datum
00736 int8_mul_cash(PG_FUNCTION_ARGS)
00737 {
00738 int64 i = PG_GETARG_INT64(0);
00739 Cash c = PG_GETARG_CASH(1);
00740 Cash result;
00741
00742 result = i * c;
00743 PG_RETURN_CASH(result);
00744 }
00745
00746
00747
00748
00749 Datum
00750 cash_div_int8(PG_FUNCTION_ARGS)
00751 {
00752 Cash c = PG_GETARG_CASH(0);
00753 int64 i = PG_GETARG_INT64(1);
00754 Cash result;
00755
00756 if (i == 0)
00757 ereport(ERROR,
00758 (errcode(ERRCODE_DIVISION_BY_ZERO),
00759 errmsg("division by zero")));
00760
00761 result = rint(c / i);
00762
00763 PG_RETURN_CASH(result);
00764 }
00765
00766
00767
00768
00769
00770 Datum
00771 cash_mul_int4(PG_FUNCTION_ARGS)
00772 {
00773 Cash c = PG_GETARG_CASH(0);
00774 int32 i = PG_GETARG_INT32(1);
00775 Cash result;
00776
00777 result = c * i;
00778 PG_RETURN_CASH(result);
00779 }
00780
00781
00782
00783
00784
00785 Datum
00786 int4_mul_cash(PG_FUNCTION_ARGS)
00787 {
00788 int32 i = PG_GETARG_INT32(0);
00789 Cash c = PG_GETARG_CASH(1);
00790 Cash result;
00791
00792 result = i * c;
00793 PG_RETURN_CASH(result);
00794 }
00795
00796
00797
00798
00799
00800
00801 Datum
00802 cash_div_int4(PG_FUNCTION_ARGS)
00803 {
00804 Cash c = PG_GETARG_CASH(0);
00805 int32 i = PG_GETARG_INT32(1);
00806 Cash result;
00807
00808 if (i == 0)
00809 ereport(ERROR,
00810 (errcode(ERRCODE_DIVISION_BY_ZERO),
00811 errmsg("division by zero")));
00812
00813 result = rint(c / i);
00814
00815 PG_RETURN_CASH(result);
00816 }
00817
00818
00819
00820
00821
00822 Datum
00823 cash_mul_int2(PG_FUNCTION_ARGS)
00824 {
00825 Cash c = PG_GETARG_CASH(0);
00826 int16 s = PG_GETARG_INT16(1);
00827 Cash result;
00828
00829 result = c * s;
00830 PG_RETURN_CASH(result);
00831 }
00832
00833
00834
00835
00836 Datum
00837 int2_mul_cash(PG_FUNCTION_ARGS)
00838 {
00839 int16 s = PG_GETARG_INT16(0);
00840 Cash c = PG_GETARG_CASH(1);
00841 Cash result;
00842
00843 result = s * c;
00844 PG_RETURN_CASH(result);
00845 }
00846
00847
00848
00849
00850
00851 Datum
00852 cash_div_int2(PG_FUNCTION_ARGS)
00853 {
00854 Cash c = PG_GETARG_CASH(0);
00855 int16 s = PG_GETARG_INT16(1);
00856 Cash result;
00857
00858 if (s == 0)
00859 ereport(ERROR,
00860 (errcode(ERRCODE_DIVISION_BY_ZERO),
00861 errmsg("division by zero")));
00862
00863 result = rint(c / s);
00864 PG_RETURN_CASH(result);
00865 }
00866
00867
00868
00869
00870 Datum
00871 cashlarger(PG_FUNCTION_ARGS)
00872 {
00873 Cash c1 = PG_GETARG_CASH(0);
00874 Cash c2 = PG_GETARG_CASH(1);
00875 Cash result;
00876
00877 result = (c1 > c2) ? c1 : c2;
00878
00879 PG_RETURN_CASH(result);
00880 }
00881
00882
00883
00884
00885 Datum
00886 cashsmaller(PG_FUNCTION_ARGS)
00887 {
00888 Cash c1 = PG_GETARG_CASH(0);
00889 Cash c2 = PG_GETARG_CASH(1);
00890 Cash result;
00891
00892 result = (c1 < c2) ? c1 : c2;
00893
00894 PG_RETURN_CASH(result);
00895 }
00896
00897
00898
00899
00900
00901 Datum
00902 cash_words(PG_FUNCTION_ARGS)
00903 {
00904 Cash value = PG_GETARG_CASH(0);
00905 uint64 val;
00906 char buf[256];
00907 char *p = buf;
00908 Cash m0;
00909 Cash m1;
00910 Cash m2;
00911 Cash m3;
00912 Cash m4;
00913 Cash m5;
00914 Cash m6;
00915
00916
00917 if (value < 0)
00918 {
00919 value = -value;
00920 strcpy(buf, "minus ");
00921 p += 6;
00922 }
00923 else
00924 buf[0] = '\0';
00925
00926
00927 val = (uint64) value;
00928
00929 m0 = val % INT64CONST(100);
00930 m1 = (val / INT64CONST(100)) % 1000;
00931 m2 = (val / INT64CONST(100000)) % 1000;
00932 m3 = (val / INT64CONST(100000000)) % 1000;
00933 m4 = (val / INT64CONST(100000000000)) % 1000;
00934 m5 = (val / INT64CONST(100000000000000)) % 1000;
00935 m6 = (val / INT64CONST(100000000000000000)) % 1000;
00936
00937 if (m6)
00938 {
00939 strcat(buf, num_word(m6));
00940 strcat(buf, " quadrillion ");
00941 }
00942
00943 if (m5)
00944 {
00945 strcat(buf, num_word(m5));
00946 strcat(buf, " trillion ");
00947 }
00948
00949 if (m4)
00950 {
00951 strcat(buf, num_word(m4));
00952 strcat(buf, " billion ");
00953 }
00954
00955 if (m3)
00956 {
00957 strcat(buf, num_word(m3));
00958 strcat(buf, " million ");
00959 }
00960
00961 if (m2)
00962 {
00963 strcat(buf, num_word(m2));
00964 strcat(buf, " thousand ");
00965 }
00966
00967 if (m1)
00968 strcat(buf, num_word(m1));
00969
00970 if (!*p)
00971 strcat(buf, "zero");
00972
00973 strcat(buf, (val / 100) == 1 ? " dollar and " : " dollars and ");
00974 strcat(buf, num_word(m0));
00975 strcat(buf, m0 == 1 ? " cent" : " cents");
00976
00977
00978 buf[0] = pg_toupper((unsigned char) buf[0]);
00979
00980
00981 PG_RETURN_TEXT_P(cstring_to_text(buf));
00982 }
00983
00984
00985
00986
00987
00988 Datum
00989 cash_numeric(PG_FUNCTION_ARGS)
00990 {
00991 Cash money = PG_GETARG_CASH(0);
00992 Numeric result;
00993 int fpoint;
00994 int64 scale;
00995 int i;
00996 Datum amount;
00997 Datum numeric_scale;
00998 Datum quotient;
00999 struct lconv *lconvert = PGLC_localeconv();
01000
01001
01002 fpoint = lconvert->frac_digits;
01003 if (fpoint < 0 || fpoint > 10)
01004 fpoint = 2;
01005
01006
01007 scale = 1;
01008 for (i = 0; i < fpoint; i++)
01009 scale *= 10;
01010
01011
01012 amount = DirectFunctionCall1(int8_numeric, Int64GetDatum(money));
01013 numeric_scale = DirectFunctionCall1(int8_numeric, Int64GetDatum(scale));
01014 quotient = DirectFunctionCall2(numeric_div, amount, numeric_scale);
01015
01016
01017 result = DatumGetNumeric(DirectFunctionCall2(numeric_round,
01018 quotient,
01019 Int32GetDatum(fpoint)));
01020
01021 PG_RETURN_NUMERIC(result);
01022 }
01023
01024
01025
01026
01027 Datum
01028 numeric_cash(PG_FUNCTION_ARGS)
01029 {
01030 Datum amount = PG_GETARG_DATUM(0);
01031 Cash result;
01032 int fpoint;
01033 int64 scale;
01034 int i;
01035 Datum numeric_scale;
01036 struct lconv *lconvert = PGLC_localeconv();
01037
01038
01039 fpoint = lconvert->frac_digits;
01040 if (fpoint < 0 || fpoint > 10)
01041 fpoint = 2;
01042
01043
01044 scale = 1;
01045 for (i = 0; i < fpoint; i++)
01046 scale *= 10;
01047
01048
01049 numeric_scale = DirectFunctionCall1(int8_numeric, Int64GetDatum(scale));
01050 amount = DirectFunctionCall2(numeric_mul, amount, numeric_scale);
01051
01052
01053 result = DatumGetInt64(DirectFunctionCall1(numeric_int8, amount));
01054
01055 PG_RETURN_CASH(result);
01056 }
01057
01058
01059
01060
01061 Datum
01062 int4_cash(PG_FUNCTION_ARGS)
01063 {
01064 int32 amount = PG_GETARG_INT32(0);
01065 Cash result;
01066 int fpoint;
01067 int64 scale;
01068 int i;
01069 struct lconv *lconvert = PGLC_localeconv();
01070
01071
01072 fpoint = lconvert->frac_digits;
01073 if (fpoint < 0 || fpoint > 10)
01074 fpoint = 2;
01075
01076
01077 scale = 1;
01078 for (i = 0; i < fpoint; i++)
01079 scale *= 10;
01080
01081
01082 result = DatumGetInt64(DirectFunctionCall2(int8mul, Int64GetDatum(amount),
01083 Int64GetDatum(scale)));
01084
01085 PG_RETURN_CASH(result);
01086 }
01087
01088
01089
01090
01091 Datum
01092 int8_cash(PG_FUNCTION_ARGS)
01093 {
01094 int64 amount = PG_GETARG_INT64(0);
01095 Cash result;
01096 int fpoint;
01097 int64 scale;
01098 int i;
01099 struct lconv *lconvert = PGLC_localeconv();
01100
01101
01102 fpoint = lconvert->frac_digits;
01103 if (fpoint < 0 || fpoint > 10)
01104 fpoint = 2;
01105
01106
01107 scale = 1;
01108 for (i = 0; i < fpoint; i++)
01109 scale *= 10;
01110
01111
01112 result = DatumGetInt64(DirectFunctionCall2(int8mul, Int64GetDatum(amount),
01113 Int64GetDatum(scale)));
01114
01115 PG_RETURN_CASH(result);
01116 }