home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / xbase / library / clipper / cgoodies / nsupport.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-06-08  |  9.5 KB  |  803 lines

  1. /***
  2. *    nsupport.c
  3. *
  4. *    Clipper Summer87
  5. *    Floating point support; C equivalents.
  6. *
  7. *    Copyright (c) 1988 Nantucket Corp.  All rights reserved.
  8. *
  9. *    CAUTION -- Intended for informational purposes.
  10. */
  11.  
  12.  
  13. /* nandef header file (found on Clipper distribution disks) */
  14. #include "nandef.h"
  15.  
  16. /* nsupport header file (with XDOUBLE defined as true 'double' type) */
  17. #define REAL_DOUBLES
  18. #include "nsupport.h"
  19.  
  20.  
  21. /* convenience macros */
  22. #define isdigit(c)    ((byte)(c) >= '0' && (byte)(c) <= '9')
  23. #define iswhite(c)    ((byte)(c) == ' ' || (byte)(c) == '\t')
  24. #define issign(c)    ((byte)(c) == '+' || (byte)(c) == '-')
  25. #define ispoint(c)    ((byte)(c) == '.')
  26.  
  27.  
  28. /* C support routines -- see C manual */
  29. extern double far cdecl fmod(double, double);
  30. extern double far cdecl floor(double);
  31. extern double far cdecl ceil(double);
  32. extern double far cdecl pow(double, double);
  33. extern double far cdecl log(double);
  34. extern double far cdecl sqrt(double);
  35. extern double far cdecl exp(double);
  36.  
  37. extern double far cdecl atof(byte far *);
  38. extern char far * far cdecl fcvt(double, quant, int far *, int far *);
  39. extern char far * far cdecl ltoa(long, byte far *, quant);
  40.  
  41.  
  42. /* static data */
  43. static double near _DV_P5 = (double)0.5;
  44. static double near _DV_NP5 = (double)-0.5;
  45. static double near _DV_10 = (double)10.0;
  46. static double near _DV_0 = (double)0;
  47.  
  48.  
  49. /* conversion buffer */
  50. static byte near nbuff[32];
  51.  
  52.  
  53. /***************************************
  54. *
  55. *    initialization
  56. *
  57. */
  58.  
  59.  
  60. /***
  61. *    _dvinit()
  62. *
  63. *    This entry point is called once at the beginning of execution.
  64. *    Note that there is no corresponding exit routine. (!)
  65. */
  66.  
  67. void far cdecl _dvinit()
  68.  
  69. {
  70. }
  71.  
  72.  
  73.  
  74. /***************************************
  75. *
  76. *    relational operators
  77. *
  78. */
  79.  
  80.  
  81. /***
  82. *    _dvlt
  83. */
  84.  
  85. Boolean far cdecl _dvlt(x, y)
  86.  
  87. double x;
  88. double y;
  89.  
  90. {
  91.     return (x < y);
  92. }
  93.  
  94.  
  95. /***
  96. *    _dvle
  97. */
  98.  
  99. Boolean far cdecl _dvle(x, y)
  100.  
  101. double x;
  102. double y;
  103.  
  104. {
  105.     return (x <= y);
  106. }
  107.  
  108.  
  109. /***
  110. *    _dveq
  111. */
  112.  
  113. Boolean far cdecl _dveq(x, y)
  114.  
  115. double x;
  116. double y;
  117.  
  118. {
  119.     return (x == y);
  120. }
  121.  
  122.  
  123. /***
  124. *    _dvge
  125. */
  126.  
  127. Boolean far cdecl _dvge(x, y)
  128.  
  129. double x;
  130. double y;
  131.  
  132. {
  133.     return (x >= y);
  134. }
  135.  
  136.  
  137. /***
  138. *    _dvgt
  139. */
  140.  
  141. Boolean far cdecl _dvgt(x, y)
  142.  
  143. double x;
  144. double y;
  145.  
  146. {
  147.     return (x > y);
  148. }
  149.  
  150.  
  151. /***
  152. *    _dvne
  153. */
  154.  
  155. Boolean far cdecl _dvne(x, y)
  156.  
  157. double x;
  158. double y;
  159.  
  160. {
  161.     return (x != y);
  162. }
  163.  
  164.  
  165. /***
  166. *    _dvltz
  167. */
  168.  
  169. Boolean far cdecl _dvltz(x)
  170.  
  171. double x;
  172.  
  173. {
  174.     return (x < _DV_0);
  175. }
  176.  
  177.  
  178. /***
  179. *    _dveqz
  180. */
  181.  
  182. Boolean far cdecl _dveqz(x)
  183.  
  184. double x;
  185.  
  186. {
  187.     return (x == _DV_0);
  188. }
  189.  
  190.  
  191.  
  192. /***************************************
  193. *
  194. *    simple operators
  195. *
  196. */
  197.  
  198.  
  199. /***
  200. *    _dvadd
  201. */
  202.  
  203. double far cdecl _dvadd(x, y)
  204.  
  205. double x;
  206. double y;
  207.  
  208. {
  209.     return (x + y);
  210. }
  211.  
  212.  
  213. /***
  214. *    _dvsub
  215. */
  216.  
  217. double far cdecl _dvsub(x, y)
  218.  
  219. double x;
  220. double y;
  221.  
  222. {
  223.     return (x - y);
  224. }
  225.  
  226.  
  227. /***
  228. *    _dvmul
  229. */
  230.  
  231. double far cdecl _dvmul(x, y)
  232.  
  233. double x;
  234. double y;
  235.  
  236. {
  237.     return (x * y);
  238. }
  239.  
  240.  
  241. /***
  242. *    _dvdiv
  243. */
  244.  
  245. double far cdecl _dvdiv(x, y)
  246.  
  247. double x;
  248. double y;
  249.  
  250. {
  251.     return (x / y);
  252. }
  253.  
  254.  
  255. /***
  256. *    _dvmod
  257. */
  258.  
  259. double far cdecl _dvmod(x, y)
  260.  
  261. double x;
  262. double y;
  263.  
  264. {
  265.     return (fmod(x, y));
  266. }
  267.  
  268.  
  269. /***
  270. *    _dvneg
  271. */
  272.  
  273. double far cdecl _dvneg(x)
  274.  
  275. double x;
  276.  
  277. {
  278.     return (-x);
  279. }
  280.  
  281.  
  282. /***
  283. *    _dvabs
  284. */
  285.  
  286. double far cdecl _dvabs(x)
  287.  
  288. double x;
  289.  
  290. {
  291.     return ((x < _DV_0) ? -x : x);
  292. }
  293.  
  294.  
  295. /***
  296. *    _dvint
  297. */
  298.  
  299. double far cdecl _dvint(x)
  300.  
  301. double x;
  302.  
  303. {
  304.     if (x < _DV_0)
  305.         return (ceil(x));
  306.  
  307.     return (floor(x));
  308. }
  309.  
  310.  
  311. /***
  312. *    _dvpow
  313. */
  314.  
  315. double far cdecl _dvpow(x, y)
  316.  
  317. double x;
  318. double y;
  319.  
  320. {
  321.     return (pow(x, y));
  322. }
  323.  
  324.  
  325. /***
  326. *    _dvlog
  327. */
  328.  
  329. double far cdecl _dvlog(x)
  330.  
  331. double x;
  332.  
  333. {
  334.     return (log(x));
  335. }
  336.  
  337.  
  338. /***
  339. *    _dvsqr
  340. */
  341.  
  342. double far cdecl _dvsqr(x)
  343.  
  344. double x;
  345.  
  346. {
  347.     return (sqrt(x));
  348. }
  349.  
  350.  
  351. /***
  352. *    _dvexp
  353. */
  354.  
  355. double far cdecl _dvexp(x)
  356.  
  357. double x;
  358.  
  359. {
  360.     return (exp(x));
  361. }
  362.  
  363.  
  364. /***
  365. *    _dvrnd(x, d)
  366. *
  367. *    x:    double value
  368. *    d:    int number of decimal places
  369. *
  370. *    Returns  'x'  rounded to  'd'  decimal places.
  371. */
  372.  
  373. double far cdecl _dvrnd(x, d)
  374.  
  375. double x;
  376. int d;
  377.  
  378. {
  379.     double p10;
  380.     double half;
  381.  
  382.  
  383.     p10 = pow(_DV_10, _dvfmi(d));
  384.  
  385.     if (x < _DV_0)
  386.         half = _DV_NP5;        /* -0.5 */
  387.     else
  388.         half = _DV_P5;        /* 0.5 */
  389.  
  390.     return (_dvint(x * p10 + half) / p10);
  391. }
  392.  
  393.  
  394.  
  395. /***************************************
  396. *
  397. *    simple type conversions
  398. *
  399. */
  400.  
  401.  
  402. /***
  403. *    _dvfmq
  404. */
  405.  
  406. double far cdecl _dvfmq(x)
  407.  
  408. quant x;
  409.  
  410. {
  411.     return ((double)x);
  412. }
  413.  
  414.  
  415. /***
  416. *    _dvfmi
  417. */
  418.  
  419. double far cdecl _dvfmi(x)
  420.  
  421. int x;
  422.  
  423. {
  424.     return ((double)x);
  425. }
  426.  
  427.  
  428. /***
  429. *    _dvfml
  430. */
  431.  
  432. double far cdecl _dvfml(x)
  433.  
  434. long x;
  435.  
  436. {
  437.     return ((double)x);
  438. }
  439.  
  440.  
  441. /***
  442. *    _dvtoq
  443. */
  444.  
  445. quant far cdecl _dvtoq(x)
  446.  
  447. double x;
  448.  
  449. {
  450.     return ((quant)x);
  451. }
  452.  
  453.  
  454. /***
  455. *    _dvtoi
  456. */
  457.  
  458. int far cdecl _dvtoi(x)
  459.  
  460. double x;
  461.  
  462. {
  463.     return ((int)x);
  464. }
  465.  
  466.  
  467. /***
  468. *    _dvtol
  469. */
  470.  
  471. long far cdecl _dvtol(x)
  472.  
  473. double x;
  474.  
  475. {
  476.     return ((long)x);
  477. }
  478.  
  479.  
  480.  
  481. /***************************************
  482. *
  483. *    ASCII type conversions
  484. *
  485. */
  486.  
  487.  
  488. /***
  489. *
  490. *    dval = _dvfma(str, len)
  491. *
  492. *    Convert printable ASCII to double value.
  493. *
  494. *    str:    string to convert.
  495. *    len:    length of string (not including null byte).
  496. *    dval:    double value returned.
  497. */
  498.  
  499. double far cdecl _dvfma(str, len)
  500.  
  501. byte far * str;
  502. quant len;
  503.  
  504. {
  505.     quant i;
  506.     quant j;
  507.  
  508.  
  509.     i = 0;
  510.     j = 0;
  511.  
  512.     /* scan over whites */
  513.     while (i < len && iswhite(str[i]))
  514.     {
  515.         i++;
  516.     }
  517.  
  518.     if (isdigit(str[i]) || issign(str[i]))
  519.     {
  520.         /* copy sign / whole digits */
  521.         do
  522.         {
  523.             nbuff[j++] = str[i++];
  524.         } while (i < len && j < sizeof(nbuff) - 1 && isdigit(str[i]));
  525.     }
  526.  
  527.     if (ispoint(str[i]))
  528.     {
  529.         /* copy point, numerics */
  530.         do
  531.         {
  532.             nbuff[j++] = str[i++];
  533.         } while (i < len && j < sizeof(nbuff) - 1 && isdigit(str[i]));
  534.     }
  535.  
  536.     /* terminator */
  537.     nbuff[j] = '\0';
  538.  
  539.     return (atof(nbuff));
  540. }
  541.  
  542.  
  543. /***
  544. *
  545. *    _aton(str, len, dvalp, lenp, decp)
  546. *
  547. *    Convert printable ASCII to double value.
  548. *
  549. *    str:    string to convert.
  550. *    len:    length of string (not including null byte).
  551. *    dvalp:    pointer to double which receives converted value.
  552. *    lenp:    pointer to quant which receives display length.
  553. *    decp:    pointer to quant which receives number of decimal digits.
  554. *
  555. */
  556.  
  557. void far cdecl _aton(str, len, dvalp, lenp, decp)
  558.  
  559. byte far * str;
  560. quant len;
  561. double far * dvalp;
  562. quant far * lenp;
  563. quant far * decp;
  564.  
  565. {
  566.     quant i;
  567.  
  568.  
  569.     /* scan for point */
  570.     i = 0;
  571.     while (i < len && !ispoint(str[i]))
  572.     {
  573.         i++;
  574.     }
  575.  
  576.     if (i < len)
  577.     {
  578.         /* figure decimal count */
  579.         *decp = (len - i) - 1;
  580.     }
  581.  
  582.     *decp = i;
  583.     *lenp = len;
  584.     *dvalp = _dvfma(str, len);
  585. }
  586.  
  587.  
  588. /***
  589. *
  590. *    _ntoa(dval, len, dec, dest)
  591. *
  592. *    Convert double to printable ASCII.
  593. *
  594. *    dval:    value to convert.
  595. *    len:    desired total length.
  596. *    dec:    desired number of decimal places.
  597. *    dest:    destination buffer.
  598. *
  599. *    Decimal digits are rounded to desired number of places.  If whole digits
  600. *    cannot be fully represented, destination is filled with asterisks.
  601. *
  602. *    Caution --    dest must be at least len+1 long.
  603. */
  604.  
  605. void far cdecl _ntoa(dval, len, dec, dest)
  606.  
  607. double dval;
  608. quant len;
  609. quant dec;
  610. byte far * dest;
  611.  
  612. {
  613.     byte far * buff;
  614.     int expt;
  615.     int sign;
  616.     quant total;
  617.     quant b;
  618.     quant d;
  619.  
  620.  
  621.     buff = fcvt(dval, dec, &expt, &sign);
  622.  
  623.     /* check for overflow */
  624.     total = 0;
  625.     while (buff[total])
  626.     {
  627.         total++;
  628.     }
  629.  
  630.     if (sign)
  631.     {
  632.         /* room for sign */
  633.         total++;
  634.     }
  635.  
  636.     if (dec)
  637.     {
  638.         /* room for decimal point */
  639.         total++;
  640.  
  641.         if (expt < 1)
  642.         {
  643.             /* room for single whole zero */
  644.             total++;
  645.  
  646.             /* room for leading fractional zeros */
  647.             total += -expt;
  648.         }
  649.     }
  650.  
  651.  
  652.     b = 0;
  653.     d = 0;
  654.  
  655.     if (total > len)
  656.     {
  657.         /* overflow */
  658.         while (d < len)
  659.         {
  660.             dest[d++] = '*';
  661.         }
  662.     }
  663.     else
  664.     {
  665.         while (total < len)
  666.         {
  667.             /* leading blanks */
  668.             dest[d++] = ' ';
  669.             total++;
  670.         }
  671.  
  672.         if (sign)
  673.         {
  674.             /* put in sign */
  675.             dest[d++] = '-';
  676.         }
  677.  
  678.         if (expt < 1)
  679.         {
  680.             /* whole zero and point */
  681.             dest[d++] = '0';
  682.             dest[d++] = '.';
  683.  
  684.             while (expt)
  685.             {
  686.                 /* frac leading zeros */
  687.                 dest[d++] = '0';
  688.                 expt++;
  689.             }
  690.         }
  691.         else
  692.         {
  693.             while (expt)
  694.             {
  695.                 /* copy whole digits */
  696.                 dest[d++] = buff[b++];
  697.                 expt--;
  698.             }
  699.  
  700.             if (dec)
  701.             {
  702.                 /* point */
  703.                 dest[d++] = '.';
  704.             }
  705.         }
  706.  
  707.         while (buff[b])
  708.         {
  709.             /* other digits */
  710.             dest[d++] = buff[b++];
  711.         }
  712.     }
  713.  
  714.     /* terminator */
  715.     dest[d] = '\0';
  716. }
  717.  
  718.  
  719. /***
  720. *
  721. *    _lntoa(dest, lval, len, dec)
  722. *
  723. *    Convert long to printable ASCII.
  724. *
  725. *    lval:    value to convert.
  726. *    len:    desired length.
  727. *    dec:    desired number of decimal places.
  728. *    dest:    destination buffer.
  729. *
  730. *    If value is too large to be contained in alloted length,
  731. *    buffer is filled with asterisks.
  732. *
  733. *    Caution --    dest must be at least len+1 long.
  734. */
  735.  
  736. void far cdecl _lntoa(dest, lval, len, dec)
  737.  
  738. byte far * dest;
  739. long lval;
  740. quant len;
  741. quant dec;
  742.  
  743. {
  744.     byte far * buff;
  745.     quant total;
  746.     quant i;
  747.  
  748.  
  749.     buff = ltoa(lval, nbuff, 10);
  750.  
  751.     /* check for overflow */
  752.     total = 0;
  753.     while (buff[total])
  754.     {
  755.         /* room for digits */
  756.         total++;
  757.     }
  758.  
  759.     if (dec)
  760.     {
  761.         /* room for point and frac zeros */
  762.         total += (dec + 1);
  763.     }
  764.  
  765.     if (total > len)
  766.     {
  767.         /* overflow */
  768.         for (i = 0; i < len; i++)
  769.         {
  770.             dest[i] = '*';
  771.         }
  772.     }
  773.     else
  774.     {
  775.         /* leading blanks */
  776.         for (i = 0; i < len - total; i++)
  777.         {
  778.             dest[i] = ' ';
  779.         }
  780.  
  781.         /* copy whole digits */
  782.         while (*buff)
  783.         {
  784.             dest[i++] = *buff++;
  785.         }
  786.  
  787.         /* point and frac zeros */
  788.         if (dec)
  789.         {
  790.             dest[i++] = '.';
  791.  
  792.             while (dec--)
  793.             {
  794.                 dest[i++] = '0';
  795.             }
  796.         }
  797.     }
  798.  
  799.     /* terminator */
  800.     dest[i] = '\0';
  801. }
  802.  
  803.