home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snipps97.zip / LOGSCALE.C < prev    next >
C/C++ Source or Header  |  1997-07-04  |  3KB  |  154 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /*
  4. **  L O G S C A L E
  5. **
  6. **  Logarithmically scale from long integer to long integer. The
  7. **  function domain (input) & range (output) both start from 0
  8. **  and the range MUST be smaller than the domain.
  9. **
  10. **  This scaling function was especially designed to colour fractals.
  11. **  In order to preserve detail & to ensure that no colours are wasted,
  12. **  the function is almost linear with a slope near 1 for early values.
  13. **
  14. **  Written by M. Stapleton of Graphic Bits
  15. **
  16. **  Public domain
  17. **
  18. **  May 18 1997
  19. */
  20.  
  21. #include "snipmath.h"
  22.  
  23.  
  24. /* "Shifted" logarithm = log(u+v) - log(v) */
  25.  
  26. #define shlog(u,v) (log(((double)(u) + (double)(v)) / (double)(v)))
  27.  
  28. static double alpha;            /* Scaling parameter */
  29.  
  30. /*
  31. **  Calculate scaling parameter (alpha) using Newton's method,
  32. **  where rmax = alpha * shlog(dmax, alpha)
  33. **  Boolean return: 0 on failure
  34. */
  35.  
  36. int initlogscale(long dmax, long rmax)
  37. {
  38.       double dm = (double) dmax;
  39.       double rm = (double) rmax;
  40.       double x = 1.0, dx, y, yy, t;
  41.  
  42.       if (dm <= rm)
  43.             return 0;
  44.  
  45.       do
  46.       {
  47.             t = shlog(dm, x);
  48.             y = x * t - rm;
  49.             yy = t - dm / (x + dm);
  50.             dx = y / yy;
  51.             x -= dx;
  52.             /* printf("Alpha = %f\n", x); */
  53.       } while (abs(dx) > 1E-4);
  54.  
  55.       alpha = x;
  56.  
  57.       return 1;
  58. }
  59.  
  60. /*
  61. **  Logarithmically scale d, offset by alpha
  62. */
  63.  
  64. long logscale(long d)
  65. {
  66.       double r = alpha * shlog(d, alpha);
  67.  
  68.       return (long) floor(0.5 + r);
  69. }
  70.  
  71. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  72.  
  73. #ifdef TEST
  74.  
  75. #include <stdio.h>
  76. #include <stdlib.h>
  77.  
  78. /*
  79. **  Default domain & range maxima.
  80. */
  81.  
  82. #define DMAX 1000
  83. #define RMAX 255
  84.  
  85. /*
  86. **  Test logscale
  87. */
  88.  
  89. int main(int argc, char *argv[])
  90. {
  91.       long d, dmax = 0, r0, r1, rmax = 0;
  92.  
  93.       if (argc == 2 && *argv[1] == '?')
  94.       {
  95.             printf("Test logscale()\n Usage:\n");
  96.             printf("%s [domain] [range]\n", argv[0]);
  97.             return EXIT_FAILURE;
  98.       }
  99.  
  100.       /*
  101.       **  Get domain & range maxima
  102.       */
  103.  
  104.       if (argc > 1)
  105.             dmax = atol(argv[1]);
  106.       if (dmax == 0)
  107.             dmax = DMAX;
  108.  
  109.       if (argc > 2)
  110.             rmax = atol(argv[2]);
  111.       if (rmax == 0)
  112.             rmax = RMAX;
  113.  
  114.       if (rmax >= dmax)
  115.       {
  116.             printf("Warning: range must be smaller than domain!\n");
  117.  
  118.             /*
  119.             **  A real program we would exit here, but we go on to test
  120.             **  initlogscale's error handling...
  121.             */
  122.       }
  123.  
  124.       /*
  125.       ** Initialise scaling parameter
  126.       */
  127.  
  128.       if (!initlogscale(dmax, rmax))
  129.       {
  130.             printf("Error: cannot initialise logscale!\n");
  131.             return EXIT_FAILURE;
  132.       }
  133.  
  134.       /*
  135.       **  Calculate function for every domain value.
  136.       ** Only print where the range value changes.
  137.       */
  138.  
  139.       for (r0 = -1, d = 0; d < dmax; d++)
  140.       {
  141.             r1 = logscale(d);
  142.             if (r1 != r0)
  143.             {
  144.                   printf("%ld -> %ld\n", d, r1);
  145.                   r0 = r1;
  146.             }
  147.       }
  148.       printf("%ld -> %ld\n", d, r1);
  149.  
  150.       return EXIT_SUCCESS;
  151. }
  152.  
  153. #endif /* TEST */
  154.