home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume21 / lyap / part01 < prev    next >
Encoding:
Text File  |  1993-10-07  |  53.4 KB  |  1,669 lines

  1. Newsgroups: comp.sources.x
  2. From: rr@sco.com (Ronald Joe Record)
  3. Subject: v21i004:  lyap - Calculate Lyapunov fractals, Part01/03
  4. Message-ID: <csx-v21i004=lyap.124624@sparky.Sterling.COM>
  5. X-Md4-Signature: 729ec9dae6c6a2e720a5fd49f36c7404
  6. Sender: chris@sparky.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Thu, 7 Oct 1993 17:46:45 GMT
  9. Approved: chris@sterling.com
  10.  
  11. Submitted-by: rr@sco.com (Ronald Joe Record)
  12. Posting-number: Volume 21, Issue 4
  13. Archive-name: lyap/part01
  14. Environment: X11
  15. Supersedes: lyapunov-xlib: Volume 17, Issue 48-49
  16.  
  17. The idea here is to calculate the Lyapunov exponent for a periodically
  18. forced logistic map (later i added several other nonlinear maps of the unit
  19. interval). In order to turn the 1-dimensional parameter space of the
  20. logistic map into a 2-dimensional parameter space, select two parameter
  21. values ('a' and 'b') then alternate the iterations of the logistic map using
  22. first 'a' then 'b' as the parameter. This program accepts an argument to 
  23. specify a forcing function, so instead of just alternating 'a' and 'b', you
  24. can use 'a' as the parameter for say 6 iterations, then 'b' for 6 iterations
  25. and so on. An interesting forcing function to look at is abbabaab (the
  26. Morse-Thue sequence, an aperiodic self-similar, self-generating sequence).
  27. Anyway, step through all the values of 'a' and 'b' in the ranges you want,
  28. calculating the Lyapunov exponent for each pair of values. The exponent
  29. is calculated by iterating out a ways (specified by the variable "settle")
  30. then on subsequent iterations calculating an average of the logarithm of
  31. the absolute value of the derivative at that point. Points in parameter
  32. space with a negative Lyapunov exponent are colored one way (using the
  33. value of the exponent to index into a color map) while points with a
  34. non-negative exponent are colored differently. 
  35.  
  36. The algorithm was taken from the September 1991 Scientific American article
  37. by A. K. Dewdney who gives credit to Mario Markus of the Max Planck Institute
  38. for its creation. Additional information and ideas were gleaned from the
  39. discussion on alt.fractals involving Stephen Hall, Ed Kubaitis, Dave Platt
  40. and Baback Moghaddam. Assistance with colormaps and spinning color wheels
  41. and X was gleaned from Hiram Clawson. Rubber banding code was adapted from
  42. an existing Mandelbrot program written by Stacey Campbell.
  43.  
  44. #! /bin/sh
  45. # This is a shell archive.  Remove anything before this line, then feed it
  46. # into a shell via "sh file" or similar.  To overwrite existing files,
  47. # type "sh file -c".
  48. # Contents:  lyap lyap/lib lyap/lyap.c lyap/params lyap/testit
  49. # Wrapped by chris@sparky on Thu Oct  7 12:38:39 1993
  50. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  51. echo If this archive is complete, you will see the following message:
  52. echo '          "shar: End of archive 1 (of 3)."'
  53. if test ! -d 'lyap' ; then
  54.     echo shar: Creating directory \"'lyap'\"
  55.     mkdir 'lyap'
  56. fi
  57. if test ! -d 'lyap/lib' ; then
  58.     echo shar: Creating directory \"'lyap/lib'\"
  59.     mkdir 'lyap/lib'
  60. fi
  61. if test -f 'lyap/lyap.c' -a "${1}" != "-c" ; then 
  62.   echo shar: Will not clobber existing file \"'lyap/lyap.c'\"
  63. else
  64.   echo shar: Extracting \"'lyap/lyap.c'\" \(47187 characters\)
  65.   sed "s/^X//" >'lyap/lyap.c' <<'END_OF_FILE'
  66. X/*
  67. X *    @(#) lyap.c 9.9 93/08/23 SCOINC
  68. X */
  69. X/*************************************************************************
  70. X *                                                                       *
  71. X *  Copyright (c) 1992, 1993 Ronald Joe Record                           *
  72. X *                                                                       *
  73. X *  All rights reserved. No part of this program or publication may be   *
  74. X *  reproduced, transmitted, transcribed, stored in a retrieval system,  *
  75. X *  or translated into any language or computer language, in any form or *
  76. X *  by any means, electronic, mechanical, magnetic, optical, chemical,   *
  77. X *  biological, or otherwise, without the prior written permission of:   *
  78. X *                                                                       *
  79. X *      Ronald Joe Record (408) 458-3718                                 *
  80. X *      212 Owen St., Santa Cruz, California 95062 USA                   *
  81. X *                                                                       *
  82. X *************************************************************************/
  83. X
  84. X/* Lyap - calculate and display Lyapunov exponents */
  85. X
  86. X/* Written by Ronald Record (rr@sco.com) 03 Sep 1991 */
  87. X
  88. X/* The idea here is to calculate the Lyapunov exponent for a periodically
  89. X * forced logistic map (later i added several other nonlinear maps of the unit
  90. X * interval). In order to turn the 1-dimensional parameter space of the
  91. X * logistic map into a 2-dimensional parameter space, select two parameter
  92. X * values ('a' and 'b') then alternate the iterations of the logistic map using
  93. X * first 'a' then 'b' as the parameter. This program accepts an argument to 
  94. X * specify a forcing function, so instead of just alternating 'a' and 'b', you
  95. X * can use 'a' as the parameter for say 6 iterations, then 'b' for 6 iterations
  96. X * and so on. An interesting forcing function to look at is abbabaab (the
  97. X * Morse-Thue sequence, an aperiodic self-similar, self-generating sequence).
  98. X * Anyway, step through all the values of 'a' and 'b' in the ranges you want,
  99. X * calculating the Lyapunov exponent for each pair of values. The exponent
  100. X * is calculated by iterating out a ways (specified by the variable "settle")
  101. X * then on subsequent iterations calculating an average of the logarithm of
  102. X * the absolute value of the derivative at that point. Points in parameter
  103. X * space with a negative Lyapunov exponent are colored one way (using the
  104. X * value of the exponent to index into a color map) while points with a
  105. X * non-negative exponent are colored differently. 
  106. X * 
  107. X * The algorithm was taken from the September 1991 Scientific American article
  108. X * by A. K. Dewdney who gives credit to Mario Markus of the Max Planck Institute
  109. X * for its creation. Additional information and ideas were gleaned from the
  110. X * discussion on alt.fractals involving Stephen Hall, Ed Kubaitis, Dave Platt
  111. X * and Baback Moghaddam. Assistance with colormaps and spinning color wheels
  112. X * and X was gleaned from Hiram Clawson. Rubber banding code was adapted from
  113. X * an existing Mandelbrot program written by Stacey Campbell.
  114. X */
  115. X
  116. X#include "lyap.h"
  117. X
  118. Xstatic char *lyap_c_id = "@(#) lyap.c 9.9 93/08/23 SCOINC";
  119. Xstatic char *version = LYAP_VERSION;
  120. X
  121. Xextern void BufferPoint(), InitBuffer(), FlushBuffer();
  122. X
  123. Xvoid
  124. XCleanup() {
  125. X    XCloseDisplay(dpy);
  126. X}
  127. X
  128. Xmain(ac, av)
  129. X    int ac;
  130. X    char **av;
  131. X{
  132. X    int i, j;
  133. X    XSizeHints hint;
  134. X    extern void init_canvas(), init_data(), init_color(), parseargs();
  135. X    extern void Clear(), restor_picture();
  136. X
  137. X    parseargs(ac, av);
  138. X    dpy = XOpenDisplay("");
  139. X    screen = DefaultScreen(dpy);
  140. X    background = BlackPixel(dpy, screen);
  141. X    if (width < 1)
  142. X        width = XDisplayWidth(dpy, screen);
  143. X    if (height < 1)
  144. X        height = XDisplayHeight(dpy, screen);
  145. X    setupmem();
  146. X    init_data();
  147. X    if (displayplanes > 1)
  148. X        foreground = startcolor;
  149. X    else
  150. X        foreground = WhitePixel(dpy,XDefaultScreen(dpy));
  151. X    if (xposition < 0)
  152. X        xposition = Max(0,(XDisplayWidth(dpy, screen) - width)/2);
  153. X    if (yposition < 0)
  154. X        yposition = Max(0,(XDisplayHeight(dpy, screen) - height)/2);
  155. X    hint.x = xposition;
  156. X    hint.y = yposition;
  157. X    hint.width = width;
  158. X    hint.height = height;
  159. X    hint.flags = PPosition | PSize;
  160. X    /*
  161. X     * Create the window to display the Lyapunov exponents 
  162. X     */
  163. X    canvas = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
  164. X        hint.x, hint.y, hint.width, hint.height,
  165. X        5, foreground, background);
  166. X    XSetStandardProperties(dpy, canvas, "Lyap by Ron Record", 
  167. X        "Lyap", None, av, ac, &hint);
  168. X    XChangeProperty( dpy, canvas, XA_WM_CLASS, XA_STRING, 8, PropModeReplace, 
  169. X                    "lyap", strlen("lyap"));
  170. X    init_canvas();
  171. X    XMapRaised(dpy, canvas);
  172. X    /* Try to write into a new color map */
  173. X    cmap = XCreateColormap(dpy, canvas, DefaultVisual(dpy, screen), AllocAll);
  174. X    if (displayplanes > 1)
  175. X        init_color(dpy, canvas, cmap, Colors, startcolor, mincolindex, 
  176. X                    numcolors, numwheels, "lyap", "Lyap", 0);
  177. X    else
  178. X        XQueryColors(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), 
  179. X                Colors, numcolors);
  180. X    pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, 
  181. X                           DefaultDepth(dpy, screen));
  182. X    rubber_data.band_cursor=XCreateFontCursor(dpy, XC_hand2);
  183. X    CreateXorGC();
  184. X    Clear();
  185. X    if (restfile)
  186. X        restor_picture();
  187. X    if (demo)
  188. X        for(;;) {
  189. X            if (!run) {
  190. X                DemoSpin(dpy, cmap, Colors, startcolor, maxcolor, delay, 2);
  191. X                for (i=0; i<=MAXWHEELS; i++) {
  192. X                    init_color(dpy, canvas, cmap, Colors, startcolor, 
  193. X                            mincolindex, numcolors, i, "lyap", "Lyap", 0);
  194. X                    sleep(1);
  195. X                }
  196. X                if (!run) {
  197. X                    Cleanup();
  198. X                    exit(0);
  199. X                } 
  200. X            }
  201. X        }
  202. X    else {
  203. X        XSelectInput(dpy,canvas,KeyPressMask|ButtonPressMask|ButtonMotionMask|
  204. X                ButtonReleaseMask|ExposureMask|StructureNotifyMask);
  205. X        for(;;)
  206. X            main_event();
  207. X    }
  208. X}
  209. X
  210. Xmain_event()
  211. X{
  212. X    int n;
  213. X    XEvent event;
  214. X
  215. X    if (complyap() == TRUE)
  216. X        run=0;
  217. X    n = XEventsQueued(dpy, QueuedAfterFlush);
  218. X    while (n--) {
  219. X        XNextEvent(dpy, &event);
  220. X        switch(event.type) {
  221. X            case KeyPress: Getkey(&event); break;
  222. X            case Expose: redisplay(canvas, &event); break;
  223. X            case ConfigureNotify: resize(); break;
  224. X            case ButtonPress: StartRubberBand(canvas, &rubber_data, &event);
  225. X                 break;
  226. X            case MotionNotify: TrackRubberBand(canvas, &rubber_data, &event);
  227. X                 break;
  228. X            case ButtonRelease: EndRubberBand(canvas, &rubber_data, &event);
  229. X                 break;
  230. X        }
  231. X    }
  232. X}
  233. X
  234. X/* complyap() is the guts of the program. This is where the Lyapunov exponent
  235. X * is calculated. For each iteration (past some large number of iterations)
  236. X * calculate the logarithm of the absolute value of the derivative at that
  237. X * point. Then average them over some large number of iterations. Some small
  238. X * speed up is achieved by utilizing the fact that log(a*b) = log(a) + log(b).
  239. X */
  240. Xcomplyap()
  241. X{
  242. X    register i, bindex, findex;
  243. X    double total, prod, x, r;
  244. X    extern void save_to_file(), store_to_file();
  245. X
  246. X    if (!run)
  247. X        return TRUE;
  248. X    if (a >= max_a)
  249. X        if (sendpoint(lyapunov) == TRUE)
  250. X            return FALSE;
  251. X        else {
  252. X            run=0;
  253. X            FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  254. X            if (savefile)
  255. X                save_to_file();
  256. X            else if (storefile)
  257. X                store_to_file();
  258. X            return TRUE;
  259. X        }
  260. X    if (b >= max_b) {
  261. X        run=0;
  262. X        FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  263. X        if (savefile)
  264. X            save_to_file();
  265. X        else if (storefile)
  266. X            store_to_file();
  267. X        return TRUE;
  268. X    }
  269. X    prod = 1.0;
  270. X    total = 0.0;
  271. X    bindex = 0;
  272. X    x = start_x;
  273. X    r = (forcing[bindex]) ? b : a;
  274. X#ifdef MAPS
  275. X    findex = 0;
  276. X    map = Maps[Forcing[findex]];
  277. X#endif
  278. X    for (i=0;i<settle;i++) {       /* Here's where we let the thing */
  279. X        x = (*map)(x, r);       /* "settle down". There is usually */
  280. X        if (++bindex >= maxindex) { /* some initial "noise" in the */
  281. X            bindex = 0;       /* iterations. How can we optimize */
  282. X            if (Rflag)        /* the value of settle ??? */
  283. X                setforcing();
  284. X        }
  285. X        r = (forcing[bindex]) ? b : a;
  286. X#ifdef MAPS
  287. X        if (++findex >= funcmaxindex)
  288. X            findex = 0;
  289. X        map = Maps[Forcing[findex]];
  290. X#endif
  291. X    }
  292. X#ifdef MAPS
  293. X    deriv = Derivs[Forcing[findex]];
  294. X#endif
  295. X    if (useprod) {            /* using log(a*b) */
  296. X        for (i=0;i<dwell;i++) {
  297. X            x = (*map)(x, r);
  298. X            prod *= ABS((*deriv)(x, r));
  299. X            /* we need to prevent overflow and underflow */
  300. X            if ((prod > 1.0e12) || (prod < 1.0e-12)) {
  301. X                if (prod == 0.0)
  302. X                    total += LN_MINDOUBLE;
  303. X                else if (prod < 0.0)
  304. X                    total += LN_MAXDOUBLE;
  305. X                else
  306. X                    total += log(prod);
  307. X                prod = 1.0;
  308. X            }
  309. X            if (++bindex >= maxindex) {
  310. X                bindex = 0;
  311. X                if (Rflag)
  312. X                    setforcing();
  313. X            }
  314. X            r = (forcing[bindex]) ? b : a;
  315. X#ifdef MAPS
  316. X            if (++findex >= funcmaxindex)
  317. X                findex = 0;
  318. X            map = Maps[Forcing[findex]];
  319. X            deriv = Derivs[Forcing[findex]];
  320. X#endif
  321. X        }
  322. X        if (prod == 0.0)
  323. X            total += LN_MINDOUBLE;
  324. X        else if (prod < 0.0)
  325. X            total += LN_MAXDOUBLE;
  326. X        else
  327. X            total += log(prod);
  328. X        lyapunov = (total * M_LOG2E) / (double)dwell;
  329. X    }
  330. X    else {                /* use log(a) + log(b) */
  331. X        for (i=0;i<dwell;i++) {
  332. X            x = (*map)(x, r);
  333. X            total += log(ABS((*deriv)(x, r)));
  334. X            if (++bindex >= maxindex) {
  335. X                bindex = 0;
  336. X                if (Rflag)
  337. X                    setforcing();
  338. X            }
  339. X            r = (forcing[bindex]) ? b : a;
  340. X#ifdef MAPS
  341. X            if (++findex >= funcmaxindex)
  342. X                findex = 0;
  343. X            map = Maps[Forcing[findex]];
  344. X            deriv = Derivs[Forcing[findex]];
  345. X#endif
  346. X        }
  347. X        lyapunov = (total * M_LOG2E) / (double)dwell;
  348. X    }
  349. X    if (sendpoint(lyapunov) == TRUE)
  350. X        return FALSE;
  351. X    else {
  352. X        run=0;
  353. X        FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  354. X        if (savefile)
  355. X            save_to_file();
  356. X        else if (storefile)
  357. X            store_to_file();
  358. X        return TRUE;
  359. X    }
  360. X}
  361. X
  362. Xdouble
  363. Xlogistic(x, r)            /* the familiar logistic map */
  364. Xdouble x, r;
  365. X{
  366. X    return(r * x * (1.0 - x));
  367. X}
  368. X
  369. Xdouble
  370. Xdlogistic(x, r)            /* the derivative of logistic map */
  371. Xdouble x, r;
  372. X{
  373. X    return(r - (2.0 * r * x));
  374. X}
  375. X
  376. Xdouble
  377. Xcircle(x, r)            /* sin() hump or sorta like the circle map */
  378. Xdouble x, r;
  379. X{
  380. X    extern double sin();
  381. X
  382. X    return(r * sin(M_PI * x));
  383. X}
  384. X
  385. Xdouble
  386. Xdcircle(x, r)            /* derivative of the "sin() hump" */
  387. Xdouble x, r;
  388. X{
  389. X    extern double cos();
  390. X
  391. X    return(r * M_PI * cos(M_PI * x));
  392. X}
  393. X
  394. Xdouble
  395. Xleftlog(x, r)            /* left skewed logistic */
  396. Xdouble x, r;
  397. X{
  398. X    double d;
  399. X
  400. X    d = 1.0 - x;
  401. X    return(r * x * d * d);
  402. X}
  403. X
  404. Xdouble
  405. Xdleftlog(x, r)            /* derivative of the left skewed logistic */
  406. Xdouble x, r;
  407. X{
  408. X    return(r * (1.0 - (4.0 * x) + (3.0 * x * x)));
  409. X}
  410. X
  411. Xdouble
  412. Xrightlog(x, r)            /* right skewed logistic */
  413. Xdouble x, r;
  414. X{
  415. X    return(r * x * x * (1.0 - x));
  416. X}
  417. X
  418. Xdouble
  419. Xdrightlog(x, r)            /* derivative of the right skewed logistic */
  420. Xdouble x, r;
  421. X{
  422. X    return(r * ((2.0 * x) - (3.0 * x * x)));
  423. X}
  424. X
  425. Xdouble
  426. Xdoublelog(x, r)            /* double logistic */
  427. Xdouble x, r;
  428. X{
  429. X    double d;
  430. X
  431. X    d = 1.0 - x;
  432. X    return(r * x * x * d * d);
  433. X}
  434. X
  435. Xdouble
  436. Xddoublelog(x, r)        /* derivative of the double logistic */
  437. Xdouble x, r;
  438. X{
  439. X    double d;
  440. X
  441. X    d = x * x;
  442. X    return(r * ((2.0 * x) - (6.0 * d) + (4.0 * x * d)));
  443. X}
  444. X
  445. Xvoid
  446. Xinit_data()
  447. X{
  448. X    static int i;
  449. X
  450. X    numcolors = XDisplayCells(dpy, XDefaultScreen(dpy));
  451. X    displayplanes = DisplayPlanes(dpy, XDefaultScreen(dpy));
  452. X    if (numcolors > maxcolor)
  453. X        numcolors = maxcolor;
  454. X    if (numcolors <= 16) {
  455. X        maxcolor = 16; startcolor = 0; 
  456. X        color_offset = 0; mincolindex = 1;
  457. X    }
  458. X    numfreecols = numcolors - mincolindex;
  459. X    lowrange = mincolindex - startcolor;
  460. X    a_inc = a_range / (double)width;
  461. X    b_inc = b_range / (double)height;
  462. X    if (!restfile) {
  463. X        point.x = point.y = 0;
  464. X        a = min_a; b = min_b;
  465. X    }
  466. X    rubber_data.p_min = min_a;
  467. X    rubber_data.q_min = min_b;
  468. X    rubber_data.p_max = max_a;
  469. X    rubber_data.q_max = max_b;
  470. X    if (show)
  471. X        show_defaults();
  472. X    InitBuffer(&Points, maxcolor);
  473. X    srand48(time(0));
  474. X}
  475. X
  476. Xvoid
  477. Xinit_canvas()
  478. X{
  479. X    static int i;
  480. X
  481. X    /*
  482. X     * create default, writable, graphics contexts for the canvas.
  483. X     */
  484. X    for (i=0; i<maxcolor; i++) {
  485. X        Data_GC[i] = XCreateGC(dpy, DefaultRootWindow(dpy),
  486. X                (unsigned long) NULL, (XGCValues *) NULL);
  487. X        /* set the background to black */
  488. X        XSetBackground(dpy,Data_GC[i],BlackPixel(dpy,XDefaultScreen(dpy)));
  489. X        /* set the foreground of the ith context to i */
  490. X        XSetForeground(dpy, Data_GC[i], i);
  491. X    }
  492. X    if (displayplanes == 1) {
  493. X        XSetForeground(dpy,Data_GC[0],BlackPixel(dpy,XDefaultScreen(dpy)));
  494. X        XSetForeground(dpy,Data_GC[1],WhitePixel(dpy,XDefaultScreen(dpy)));
  495. X    }
  496. X}
  497. X
  498. Xvoid
  499. Xparseargs(ac, av)
  500. Xint ac;
  501. Xchar **av;
  502. X{
  503. X    static int c;
  504. X    static int i;
  505. X    int bindex=0, findex;
  506. X    char *ch;
  507. X    extern int optind;
  508. X    extern char *optarg;
  509. X    extern double atof();
  510. X    extern void check_params(), usage(), restor_params();
  511. X
  512. X    map = Maps[0];
  513. X    deriv = Derivs[0];
  514. X    maxexp=minlyap; minexp= -1.0 * minlyap;
  515. X
  516. X    while ((c=getopt(ac,av,
  517. X        "Ldpuvc:i:m:C:W:H:I:M:N:O:R:S:a:b:D:F:f:o:w:h:s:x:y:"))!=EOF){
  518. X        switch (c) {
  519. X        case 'C':    mincolindex=atoi(optarg); break;
  520. X        case 'D':    if (strcmp(optarg, "elay"))
  521. X                        dwell=atoi(optarg); 
  522. X                     else
  523. X                        delay = atoi(av[optind++]);
  524. X                     break;
  525. X#ifdef MAPS
  526. X        case 'F':    funcmaxindex = strlen(optarg);
  527. X                if (funcmaxindex > FUNCMAXINDEX)
  528. X                    usage();
  529. X                ch = optarg;
  530. X                Force++;
  531. X                for (findex=0;findex<funcmaxindex;findex++) {
  532. X                    Forcing[findex] = (int)(*ch++ - '0');
  533. X                    if (Forcing[findex] >= NUMMAPS)
  534. X                        usage();
  535. X                }
  536. X                break;
  537. X#endif
  538. X        case 'H':    height=atoi(optarg); break;
  539. X        case 'I':    start_x=atof(optarg); break;
  540. X        case 'L':    useprod=0; break;
  541. X        case 'M':    minlyap=ABS(atof(optarg)); 
  542. X                maxexp=minlyap; minexp= -1.0 * minlyap; break;
  543. X        case 'N':    maxcolor=ABS(atoi(optarg)); 
  544. X                if ((maxcolor - startcolor) <= 0)
  545. X                    startcolor = 0;
  546. X                if ((maxcolor - mincolindex) <= 0) {
  547. X                    mincolindex = 1;
  548. X                    color_offset = 0;
  549. X                }
  550. X                break;
  551. X        case 'O':    color_offset=atoi(optarg); break;
  552. X        case 'R':    prob=atof(optarg); Rflag++; setforcing(); break;
  553. X        case 'S':    settle=atoi(optarg); break;
  554. X        case 'W':    width=atoi(optarg); break;
  555. X        case 'a':    min_a=atof(optarg); aflag++; break;
  556. X        case 'b':    min_b=atof(optarg); bflag++; break;
  557. X        case 'c':    numwheels=atoi(optarg); break;
  558. X        case 'd':    demo++; break;
  559. X        case 'f':    maxindex = strlen(optarg);
  560. X                if (maxindex > MAXINDEX)
  561. X                    usage();
  562. X                ch = optarg;
  563. X                force++;
  564. X                while (bindex < maxindex) {
  565. X                    if (*ch == 'a')
  566. X                        forcing[bindex++] = 0;
  567. X                    else if (*ch == 'b')
  568. X                        forcing[bindex++] = 1;
  569. X                    else
  570. X                        usage();
  571. X                    ch++;
  572. X                }
  573. X                break;
  574. X        case 'h':    b_range=atof(optarg); hflag++; break;
  575. X        case 'i':    restfile++; inname=optarg; break;
  576. X        case 'm':    mapindex=atoi(optarg); 
  577. X                if ((mapindex >= NUMMAPS) || (mapindex < 0))
  578. X                    usage();
  579. X                map = Maps[mapindex];
  580. X                deriv = Derivs[mapindex];
  581. X                if (!aflag)
  582. X                    min_a = amins[mapindex];
  583. X                if (!wflag)
  584. X                    a_range = aranges[mapindex];
  585. X                if (!bflag)
  586. X                    min_b = bmins[mapindex];
  587. X                if (!hflag)
  588. X                    b_range = branges[mapindex];
  589. X                if (!Force)
  590. X                    for (i=0;i<FUNCMAXINDEX;i++)
  591. X                        Forcing[i] = mapindex;
  592. X                break;
  593. X        case 'o':    savefile++; outname=optarg; break;
  594. X        case 'p':    negative--; break;
  595. X        case 's':    storefile++; savname=optarg; break;
  596. X        case 'u':    usage(); break;
  597. X        case 'v':    show=1; break;
  598. X        case 'w':    a_range=atof(optarg); wflag++; break;
  599. X        case 'x':    xposition=atoi(optarg); break;
  600. X        case 'y':    yposition=atoi(optarg); break;
  601. X        case '?':    usage(); break;
  602. X        }
  603. X    }
  604. X    if (restfile)
  605. X        restor_params();
  606. X    else {
  607. X        max_a = min_a + a_range;
  608. X        max_b = min_b + b_range;
  609. X    }
  610. X    a_minimums[0] = min_a; b_minimums[0] = min_b;
  611. X    a_maximums[0] = max_a; b_maximums[0] = max_b;
  612. X    if (Force)
  613. X        if (maxindex == funcmaxindex)
  614. X            for (findex=0;findex<funcmaxindex;findex++)
  615. X                check_params(Forcing[findex],forcing[findex]);
  616. X        else
  617. X            fprintf(stderr, "Warning! Unable to check parameters\n");
  618. X    else
  619. X        check_params(mapindex,2);
  620. X}
  621. X
  622. Xvoid
  623. Xcheck_params(mapnum, parnum)
  624. Xint mapnum;
  625. Xint parnum;
  626. X{
  627. X
  628. X    if (parnum != 1) {
  629. X        if ((max_a > pmaxs[mapnum]) || (min_a < pmins[mapnum])) {
  630. X            fprintf(stderr, "Warning! Parameter 'a' out of range.\n");
  631. X            fprintf(stderr, "You have requested a range of (%lf,%lf).\n",
  632. X                    min_a,max_a);
  633. X            fprintf(stderr, "Valid range is (%lf,%lf).\n",
  634. X                    pmins[mapnum],pmaxs[mapnum]);
  635. X        }
  636. X    }
  637. X    if (parnum != 0) {
  638. X        if ((max_b > pmaxs[mapnum]) || (min_b < pmins[mapnum])) {
  639. X            fprintf(stderr, "Warning! Parameter 'b' out of range.\n");
  640. X            fprintf(stderr, "You have requested a range of (%lf,%lf).\n",
  641. X                    min_b,max_b);
  642. X            fprintf(stderr, "Valid range is (%lf,%lf).\n",
  643. X                    pmins[mapnum],pmaxs[mapnum]);
  644. X        }
  645. X    }
  646. X}
  647. X
  648. Xvoid
  649. Xusage()
  650. X{
  651. X    fprintf(stderr,"lyap [-Ls][-W#][-H#][-a#][-b#][-w#][-h#][-x xstart]\n");
  652. X    fprintf(stderr,"\t[-M#][-S#][-D#][-f string][-r#][-O#][-C#][-c#][-m#]\n");
  653. X#ifdef MAPS
  654. X    fprintf(stderr,"\t[-F string]\n");
  655. X#endif
  656. X    fprintf(stderr,"\tWhere: -C# specifies the minimum color index\n");
  657. X    fprintf(stderr,"\t       -r# specifies the maxzimum rgb value\n");
  658. X    fprintf(stderr,"\t       -u displays this message\n");
  659. X    fprintf(stderr,"\t       -a# specifies the minimum horizontal parameter\n");
  660. X    fprintf(stderr,"\t       -b# specifies the minimum vertical parameter\n");
  661. X    fprintf(stderr,"\t       -w# specifies the horizontal parameter range\n");
  662. X    fprintf(stderr,"\t       -h# specifies the vertical parameter range\n");
  663. X    fprintf(stderr,"\t       -D# specifies the dwell\n");
  664. X    fprintf(stderr,"\t       -S# specifies the settle\n");
  665. X    fprintf(stderr,"\t       -H# specifies the initial window height\n");
  666. X    fprintf(stderr,"\t       -W# specifies the initial window width\n");
  667. X    fprintf(stderr,"\t       -O# specifies the color offset\n");
  668. X    fprintf(stderr,"\t       -c# specifies the desired color wheel\n");
  669. X    fprintf(stderr,"\t       -m# specifies the desired map (0-4)\n");
  670. X    fprintf(stderr,"\t       -f aabbb specifies a forcing function of 00111\n");
  671. X#ifdef MAPS
  672. X    fprintf(stderr,"\t       -F 00111 specifies the function forcing function\n");
  673. X#endif
  674. X    fprintf(stderr,"\t       -L indicates use log(x)+log(y) rather than log(xy)\n");
  675. X    fprintf(stderr,"\tDuring display :\n");
  676. X    fprintf(stderr,"\t     Use the mouse to zoom in on an area\n");
  677. X    fprintf(stderr,"\t     e or E recalculates color indices\n");
  678. X    fprintf(stderr,"\t     f or F saves exponents to a file\n");
  679. X    fprintf(stderr,"\t     KJmn increase/decrease minimum negative exponent\n");
  680. X    fprintf(stderr,"\t     r or R redraws\n");
  681. X    fprintf(stderr,"\t     s or S spins the colorwheel\n");
  682. X    fprintf(stderr,"\t     w or W changes the color wheel\n");
  683. X    fprintf(stderr,"\t     x or X clears the window\n");
  684. X    fprintf(stderr,"\t     q or Q exits\n");
  685. X    exit(1);
  686. X}
  687. X
  688. XCycle_frames()
  689. X{
  690. X    static int i;
  691. X    extern void redraw();
  692. X
  693. X    for (i=0;i<=maxframe;i++)
  694. X        redraw(exponents[i], expind[i], 1); 
  695. X}
  696. X
  697. XGetkey(event)
  698. XXKeyEvent *event;
  699. X{
  700. X    unsigned char key;
  701. X    static int i, running, spindir=0, spinning=0;
  702. X    extern void init_color(), recalc(), print_values(), print_help();
  703. X    extern void go_init(), go_back(), go_down(), Clear();
  704. X    extern void save_to_file(), Redraw(), redraw(), store_to_file();
  705. X
  706. X    if (XLookupString(event, (char *)&key, sizeof(key), (KeySym *)0,
  707. X            (XComposeStatus *) 0) > 0)
  708. X        switch (key) {
  709. X            case '(': delay -= 25; if (delay < 0) delay = 0; break;
  710. X            case ')': delay += 25; break;
  711. X            case '<': dwell /= 2; if (dwell < 1) dwell = 1; break;
  712. X            case '>': dwell *= 2; break;
  713. X            case '[': settle /= 2; if (settle < 1) settle = 0; break;
  714. X            case ']': settle *= 2; if (settle < 1) settle = 1; break;
  715. X            case 'd': go_down(); break;
  716. X            case 'D': FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 
  717. X                                0, maxcolor); 
  718. X                    break;
  719. X            case 'e':
  720. X            case 'E': FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 
  721. X                                0, maxcolor);
  722. X                  dorecalc = (!dorecalc);
  723. X                  if (dorecalc)
  724. X                      recalc(); 
  725. X                  else {
  726. X                      maxexp = minlyap; minexp = -1.0 * minlyap;
  727. X                  }
  728. X                  redraw(exponents[frame], expind[frame], 1);
  729. X                  break;
  730. X            case 'f': FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 
  731. X                        0, maxcolor);
  732. X                      store_to_file(); break;
  733. X            case 'F': FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 
  734. X                        0, maxcolor);
  735. X                      save_to_file(); break;
  736. X            case 'i': 
  737. X                  if (stripe_interval > 0) {
  738. X                      stripe_interval--;
  739. X                      if (displayplanes > 1) {
  740. X                          running = run; run = 0;
  741. X                          init_color(dpy,canvas,cmap,Colors,startcolor,
  742. X                               mincolindex,numcolors,numwheels,"lyap","Lyap",0);
  743. X                          run = running;
  744. X                      }
  745. X                  }
  746. X                  break;
  747. X            case 'I': stripe_interval++;
  748. X                  if (displayplanes > 1) {
  749. X                      running = run; run = 0;
  750. X                      init_color(dpy,canvas,cmap,Colors,startcolor,
  751. X                            mincolindex,numcolors,numwheels,"lyap","Lyap",0);
  752. X                      run = running;
  753. X                  }
  754. X                  break;
  755. X            case 'K': if (minlyap > 0.05)
  756. X                          minlyap -= 0.05;
  757. X                   break;
  758. X            case 'J': minlyap += 0.05; 
  759. X                   break;
  760. X            case 'm': mapindex++;
  761. X                  if (mapindex >= NUMMAPS)
  762. X                      mapindex=0;
  763. X                  map = Maps[mapindex];
  764. X                  deriv = Derivs[mapindex];
  765. X                  if (!aflag)
  766. X                      min_a = amins[mapindex];
  767. X                  if (!wflag)
  768. X                      a_range = aranges[mapindex];
  769. X                  if (!bflag)
  770. X                      min_b = bmins[mapindex];
  771. X                  if (!hflag)
  772. X                      b_range = branges[mapindex];
  773. X                  if (!Force)
  774. X                      for (i=0;i<FUNCMAXINDEX;i++)
  775. X                           Forcing[i] = mapindex;
  776. X                  max_a = min_a + a_range;
  777. X                  max_b = min_b + b_range;
  778. X                  a_minimums[0] = min_a; b_minimums[0] = min_b;
  779. X                  a_maximums[0] = max_a; b_maximums[0] = max_b;
  780. X                  a_inc = a_range / (double)width;
  781. X                  b_inc = b_range / (double)height;
  782. X                  point.x = 0;
  783. X                  point.y = 0;
  784. X                  a = rubber_data.p_min = min_a;
  785. X                  b = rubber_data.q_min = min_b;
  786. X                  rubber_data.p_max = max_a;
  787. X                  rubber_data.q_max = max_b;
  788. X                  Clear();
  789. X                  run = 1;
  790. X                  break;
  791. X            case 'M': if (minlyap > 0.005)
  792. X                      minlyap -= 0.005;
  793. X                  break;
  794. X            case 'N': minlyap += 0.005;
  795. X                  break;
  796. X            case 'p':
  797. X            case 'P': negative = (!negative); 
  798. X                  FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 
  799. X                                0, maxcolor); 
  800. X                  redraw(exponents[frame], expind[frame], 1); 
  801. X                  break;
  802. X            case 'r': FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 
  803. X                            0, maxcolor); 
  804. X                  redraw(exponents[frame],expind[frame],1); 
  805. X                  break;
  806. X            case 'R': FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 
  807. X                            0, maxcolor); 
  808. X                  Redraw(); 
  809. X                  break;
  810. X            case 'S': spinning=0; break;
  811. X            case 's': spinning=1; spindir=(!spindir); 
  812. X                  Spin(dpy,cmap,Colors,startcolor,numcolors,delay,spindir); 
  813. X                  break;
  814. X            case 'u': go_back(); break;
  815. X            case 'U': go_init(); break;
  816. X            case 'v':
  817. X            case 'V': print_values(); break;
  818. X            case '\027': /* (ctrl-W) read color palette from $HOME/.lyapmap */
  819. X                  numwheels = 0;
  820. X                  if (displayplanes > 1) {
  821. X                      running = run; run = 0;
  822. X                      init_color(dpy,canvas,cmap,Colors,startcolor,
  823. X                            mincolindex,numcolors,numwheels,"lyap","Lyap",0);
  824. X                      run = running;
  825. X                  }
  826. X                  break;
  827. X            case 'W': if (numwheels < MAXWHEELS)
  828. X                          numwheels++;
  829. X                      else
  830. X                          numwheels = 0;
  831. X                      if (displayplanes > 1) {
  832. X                          running = run; run = 0;
  833. X                            init_color(dpy,canvas,cmap,Colors,startcolor,
  834. X                               mincolindex,numcolors,numwheels,"lyap","Lyap",0);
  835. X                          run = running;
  836. X                      }
  837. X                      break;
  838. X            case 'w': if (numwheels > 0)
  839. X                          numwheels--;
  840. X                      else
  841. X                          numwheels = MAXWHEELS;
  842. X                      if (displayplanes > 1) {
  843. X                          running = run; run = 0;
  844. X                            init_color(dpy,canvas,cmap,Colors,startcolor,
  845. X                               mincolindex,numcolors,numwheels,"lyap","Lyap",0);
  846. X                          run = running;
  847. X                      }
  848. X                      break;
  849. X            case 'x': Clear(); break;
  850. X            case 'X': Destroy_frame(); break;
  851. X            case 'z': running = run; run = 0;
  852. X                  Cycle_frames(); 
  853. X                  run = running; redraw(exponents[frame], expind[frame], 1);
  854. X                  break;
  855. X            case 'Z': running = run; run = 0;
  856. X                  while (!XPending(dpy)) Cycle_frames(); 
  857. X                  run = running; redraw(exponents[frame], expind[frame], 1); 
  858. X                  break;
  859. X            case 'q':
  860. X            case 'Q': Cleanup(); exit(0); break;
  861. X            case '?':
  862. X            case 'h':
  863. X            case 'H': print_help(); break;
  864. X            default:  break;
  865. X        }
  866. X        if (spinning)
  867. X            Spin(dpy,cmap,Colors,startcolor,numcolors,delay,spindir); 
  868. X}
  869. X
  870. X/* Here's where we index into a color map. After the Lyapunov exponent is
  871. X * calculated, it is used to determine what color to use for that point.
  872. X * I suppose there are a lot of ways to do this. I used the following :
  873. X * if it's non-negative then there's a reserved area at the lower range
  874. X * of the color map that i index into. The ratio of some "minimum exponent
  875. X * value" and the calculated value is used as a ratio of how high to index
  876. X * into this reserved range. Usually these colors are dark red (see init_color).
  877. X * If the exponent is negative, the same ratio (expo/minlyap) is used to index
  878. X * into the remaining portion of the colormap (which is usually some light
  879. X * shades of color or a rainbow wheel). The coloring scheme can actually make
  880. X * a great deal of difference in the quality of the picture. Different colormaps
  881. X * bring out different details of the dynamics while different indexing
  882. X * algorithms also greatly effect what details are seen. Play around with this.
  883. X */
  884. Xsendpoint(expo)
  885. Xdouble expo;
  886. X{
  887. X    static int index;
  888. X    static double tmpexpo;
  889. X    extern double exp();
  890. X
  891. X    tmpexpo = (negative) ? expo : -1.0 * expo;
  892. X    if (tmpexpo > 0) {
  893. X        if (displayplanes >1) {
  894. X            index = (int)(tmpexpo*lowrange/maxexp);
  895. X            index = (index % lowrange) + startcolor;
  896. X        }
  897. X        else
  898. X            index = 0;
  899. X    }
  900. X    else {
  901. X        if (displayplanes >1) {
  902. X            index = (int)(tmpexpo*numfreecols/minexp);
  903. X            index = (index % numfreecols) + mincolindex;
  904. X        }
  905. X        else
  906. X            index = 1;
  907. X    }
  908. X    BufferPoint(dpy, canvas, pixmap, Data_GC, &Points, index, point.x, point.y);
  909. X    point.x++;
  910. X    a += a_inc;
  911. X    if (save)
  912. X        exponents[frame][expind[frame]++] = expo;
  913. X    if (point.x >= width) {
  914. X        point.y++;
  915. X        point.x = 0;
  916. X        if (save) {
  917. X            b += b_inc;
  918. X            a = min_a;
  919. X        }
  920. X        if (point.y >= height)
  921. X            return FALSE;
  922. X        else
  923. X            return TRUE;
  924. X    }
  925. X    return TRUE;
  926. X}
  927. X
  928. Xvoid 
  929. Xredisplay (w, event)
  930. XWindow          w;
  931. XXExposeEvent    *event;
  932. X{
  933. X    /*
  934. X     * Extract the exposed area from the event and copy
  935. X     * from the saved pixmap to the window.
  936. X     */
  937. X    XCopyArea(dpy, pixmap, canvas, Data_GC[0], 
  938. X           event->x, event->y, event->width, event->height, 
  939. X           event->x, event->y);
  940. X}
  941. X
  942. Xvoid
  943. Xresize()
  944. X{
  945. X    Window r;
  946. X    int n, x, y;
  947. X    unsigned int bw, d, new_w, new_h;
  948. X    extern void Clear(), Redraw();
  949. X
  950. X    XGetGeometry(dpy,canvas,&r,&x,&y,&new_w,&new_h,&bw,&d);
  951. X    if ((new_w == width) && (new_h == height))
  952. X        return;
  953. X    freemem();
  954. X    width = new_w; height = new_h;
  955. X    XClearWindow(dpy, canvas);
  956. X    if (pixmap)
  957. X        XFreePixmap(dpy, pixmap);
  958. X    pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), 
  959. X            width, height, DefaultDepth(dpy, screen));
  960. X    a_inc = a_range / (double)width;
  961. X    b_inc = b_range / (double)height;
  962. X    point.x = 0;
  963. X    point.y = 0;
  964. X    run = 1;
  965. X    a = rubber_data.p_min = min_a;
  966. X    b = rubber_data.q_min = min_b;
  967. X    rubber_data.p_max = max_a;
  968. X    rubber_data.q_max = max_b;
  969. X    setupmem();
  970. X    for (n=0;n<MAXFRAMES;n++)
  971. X        if ((n <= maxframe) && (n != frame))
  972. X            resized[n] = 1;
  973. X    InitBuffer(&Points, maxcolor);
  974. X    Clear();
  975. X    Redraw();
  976. X}
  977. X
  978. Xvoid
  979. Xredraw(exparray, index, cont)
  980. Xdouble *exparray;
  981. Xint index, cont;
  982. X{
  983. X    static int i;
  984. X    static int x_sav, y_sav;
  985. X
  986. X    x_sav = point.x;
  987. X    y_sav = point.y;
  988. X
  989. X    point.x = 0;
  990. X    point.y = 0;
  991. X
  992. X    save=0;
  993. X    for (i=0;i<index;i++)
  994. X        sendpoint(exparray[i]);
  995. X    save=1;
  996. X    
  997. X    if (cont) {
  998. X        point.x = x_sav;
  999. X        point.y = y_sav;
  1000. X    }
  1001. X    else {
  1002. X        a = point.x * a_inc + min_a;
  1003. X        b = point.y * b_inc + min_b;
  1004. X    }
  1005. X    FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  1006. X}
  1007. X
  1008. Xvoid
  1009. XRedraw() 
  1010. X{
  1011. X    FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  1012. X    point.x = 0;
  1013. X    point.y = 0;
  1014. X    run = 1;
  1015. X    a = min_a;
  1016. X    b = min_b;
  1017. X    expind[frame] = 0;
  1018. X    resized[frame] = 0;
  1019. X}
  1020. X
  1021. X/* Store colormap indices in file so we can read them in later */
  1022. Xvoid
  1023. Xstore_to_file() 
  1024. X{
  1025. X    FILE *outfile;
  1026. X    unsigned char c;
  1027. X    XImage *ximage;
  1028. X    static int i,j;
  1029. X
  1030. X    outfile = fopen(savname,"w");
  1031. X    if(!outfile) {
  1032. X        perror(savname);
  1033. X        Cleanup();
  1034. X        exit(-1);
  1035. X    }
  1036. X    fprintf(outfile,"# width=%d height=%d \n",width,height);
  1037. X    fprintf(outfile,"# settle=%d dwell=%d start_x=%lf \n",settle,dwell,start_x);
  1038. X    fprintf(outfile,"# min_a=%lf a_rng=%lf max_a=%lf \n",min_a,a_range,max_a);
  1039. X    fprintf(outfile,"# min_b=%lf b_rng=%lf max_b=%lf \n",min_b,b_range,max_b);
  1040. X    fprintf(outfile,"# run=%d point.x=%d point.y=%d \n",run,point.x,point.y);
  1041. X    fprintf(outfile,"# negative=%d mincolindex=%d startcolor=%d \n",
  1042. X            negative,mincolindex,startcolor);
  1043. X    fprintf(outfile,"# minexp=%lf maxexp=%lf a=%lf b=%lf \n",
  1044. X            minexp,maxexp,a,b);
  1045. X    fprintf(outfile,"# Force=%d force=%d useprod=%d \n",Force,force,useprod);
  1046. X    fprintf(outfile,"# mapindex=%d maxindex=%d \n", mapindex, maxindex);
  1047. X    fprintf(outfile,"# numwheels=%d Rflag=%d color_offset=%d \n",
  1048. X            numwheels,Rflag,color_offset);
  1049. X    fprintf(outfile,"# maxcolor=%d start_x=%lf minlyap=%lf prob=%lf\n",
  1050. X            maxcolor,start_x,minlyap,prob);
  1051. X    fprintf(outfile,"# maxindex=%d periodic forcing=", maxindex);
  1052. X        for (i=0;i<maxindex;i++) {
  1053. X            fprintf(outfile," %d",forcing[i]);
  1054. X        }
  1055. X    fprintf(outfile," \n");
  1056. X    fprintf(outfile,"# funcmaxindex=%d function forcing=", funcmaxindex);
  1057. X    for (i=0;i<funcmaxindex;i++)
  1058. X         fprintf(outfile," %d",Forcing[i]);
  1059. X    fprintf(outfile," \n");
  1060. X    fprintf(outfile,"# numcolors=%d\n",numcolors);
  1061. X
  1062. X    ximage=XGetImage(dpy, pixmap, 0, 0, 
  1063. X            (unsigned int)width, (unsigned int)height, AllPlanes, XYPixmap);
  1064. X
  1065. X    for (j=0;j<=point.y;j++)
  1066. X        for (i=0;i<width;i++) {
  1067. X            c = (unsigned char)XGetPixel(ximage,i,j);
  1068. X            fwrite((char *)&c,sizeof c,1,outfile);
  1069. X        }
  1070. X    fclose(outfile);
  1071. X}
  1072. X
  1073. X/* Store color pics in PPM format and monochrome in PGM */
  1074. Xvoid
  1075. Xsave_to_file() 
  1076. X{
  1077. X    FILE *outfile;
  1078. X    unsigned char c;
  1079. X    XImage *ximage;
  1080. X    static int i,j;
  1081. X    struct Colormap {
  1082. X        unsigned char red;
  1083. X        unsigned char green;
  1084. X        unsigned char blue;
  1085. X    };
  1086. X    struct Colormap *colormap=NULL;
  1087. X
  1088. X    if (colormap)
  1089. X        free(colormap);
  1090. X    if ((colormap=
  1091. X        (struct Colormap *)malloc(sizeof(struct Colormap)*maxcolor))
  1092. X            == NULL) {
  1093. X        fprintf(stderr,"Error malloc'ing colormap array\n");
  1094. X        Cleanup();
  1095. X        exit(-1);
  1096. X    }
  1097. X    outfile = fopen(outname,"w");
  1098. X    if(!outfile) {
  1099. X        perror(outname);
  1100. X        Cleanup();
  1101. X        exit(-1);
  1102. X    }
  1103. X
  1104. X    ximage=XGetImage(dpy, pixmap, 0, 0, width, height, AllPlanes, XYPixmap);
  1105. X
  1106. X    if (displayplanes > 1) {
  1107. X        for (i=0;i<maxcolor;i++) {
  1108. X            colormap[i].red=(unsigned char)(Colors[i].red >> 8);
  1109. X            colormap[i].green=(unsigned char)(Colors[i].green >> 8);
  1110. X            colormap[i].blue =(unsigned char)(Colors[i].blue >> 8);
  1111. X        }
  1112. X        fprintf(outfile,"P%d %d %d\n",6,width,height);
  1113. X    }
  1114. X    else
  1115. X        fprintf(outfile,"P%d %d %d\n",5,width,height);
  1116. X    fprintf(outfile,"# settle=%d  dwell=%d start_x=%lf\n",settle,dwell,start_x);
  1117. X    fprintf(outfile,"# min_a=%lf  a_rng=%lf  max_a=%lf\n",min_a,a_range,max_a);
  1118. X    fprintf(outfile,"# min_b=%lf  b_rng=%lf  max_b=%lf\n",min_b,b_range,max_b);
  1119. X    if (Rflag)
  1120. X        fprintf(outfile,"# pseudo-random forcing\n");
  1121. X    else if (force) {
  1122. X        fprintf(outfile,"# periodic forcing=");
  1123. X        for (i=0;i<maxindex;i++) {
  1124. X            fprintf(outfile,"%d",forcing[i]);
  1125. X        }
  1126. X        fprintf(outfile,"\n");
  1127. X    }
  1128. X    else
  1129. X         fprintf(outfile,"# periodic forcing=01\n");
  1130. X    if (Force) {
  1131. X         fprintf(outfile,"# function forcing=");
  1132. X         for (i=0;i<funcmaxindex;i++)
  1133. X             fprintf(outfile,"%d",Forcing[i]);
  1134. X         fprintf(outfile,"\n");
  1135. X    }
  1136. X    fprintf(outfile,"%d\n",numcolors-1);
  1137. X
  1138. X    for (j=0;j<height;j++)
  1139. X        for (i=0;i<width;i++) {
  1140. X            c = (unsigned char)XGetPixel(ximage,i,j);
  1141. X            if (displayplanes > 1)
  1142. X                fwrite((char *)&colormap[c],sizeof colormap[0],1,outfile);
  1143. X            else
  1144. X                fwrite((char *)&c,sizeof c,1,outfile);
  1145. X        }
  1146. X    fclose(outfile);
  1147. X}
  1148. X
  1149. X/* Read saved file with parameters */
  1150. Xvoid
  1151. Xrestor_params() 
  1152. X{
  1153. X    unsigned char s[16];
  1154. X    static int i;
  1155. X
  1156. X    infile = fopen(inname,"r");
  1157. X    if(!infile) {
  1158. X        perror(inname);
  1159. X        Cleanup();
  1160. X        exit(-1);
  1161. X    }
  1162. X
  1163. X    fscanf(infile,"%1s%6s%d%7s%d",s,s,&width,s,&height);
  1164. X    fscanf(infile,"%1s%7s%d%6s%d%8s%lf",s,s,&settle,s,&dwell,s,&start_x);
  1165. X    fscanf(infile,"%1s%6s%lf%6s%lf%6s%lf", s,s,&min_a,s,&a_range,s,&max_a);
  1166. X    fscanf(infile,"%1s%6s%lf%6s%lf%6s%lf", s,s,&min_b,s,&b_range,s,&max_b);
  1167. X    fscanf(infile,"%1s%4s%d%8s%d%8s%d",s,s,&run,s,&point.x,s,&point.y);
  1168. X    fscanf(infile,"%1s%9s%d%12s%d%11s%d",
  1169. X            s,s,&negative,s,&mincolindex,s,&startcolor);
  1170. X    fscanf(infile,"%1s%7s%lf%7s%lf%2s%lf%2s%lf",
  1171. X            s,s,&minexp,s,&maxexp,s,&a,s,&b);
  1172. X    fscanf(infile,"%1s%6s%d%6s%d%8s%d",s,s,&Force,s,&force,s,&useprod);
  1173. X    fscanf(infile,"%1s%9s%d%9s%d",
  1174. X            s,s,&mapindex,s,&maxindex);
  1175. X    fscanf(infile,"%1s%10s%d%6s%d%13s%d",
  1176. X            s,s,&numwheels,s,&Rflag,s,&color_offset);
  1177. X    fscanf(infile,"%1s%9s%d%8s%lf%8s%lf%5s%lf",
  1178. X            s,s,&maxcolor,s,&start_x,s,&minlyap,s,&prob);
  1179. X    fscanf(infile,"%1s%9s%d%s%s", s,s,&maxindex,s,s);
  1180. X    for(i=0;i<maxindex;i++) {
  1181. X        fscanf(infile, "%d", &forcing[i]);
  1182. X    }
  1183. X    fscanf(infile,"%1s%13s%d%s%s", s,s,&funcmaxindex,s,s);
  1184. X    for(i=0;i<funcmaxindex;i++)
  1185. X        fscanf(infile, "%d", &Forcing[i]);
  1186. X    fscanf(infile, "%1s%10s%d", s,s,&numcolors);
  1187. X    fread(s, sizeof s[0], 1, infile);
  1188. X    map = Maps[mapindex];
  1189. X    deriv = Derivs[mapindex];
  1190. X}
  1191. X
  1192. Xvoid
  1193. Xrestor_picture() {
  1194. X    static int i, j, k;
  1195. X    unsigned char c;
  1196. X
  1197. X    for (j=0;j<point.y;j++)
  1198. X        for (i=0;i<width;i++) {
  1199. X            k = fread(&c, sizeof c, 1, infile);
  1200. X            if (k) {
  1201. X                BufferPoint(dpy,canvas,pixmap,Data_GC,&Points,(int)c,i,j);
  1202. X                if (k < mincolindex)
  1203. X                    exponents[frame][expind[frame]++] = 
  1204. X                        -(double)k/(double)mincolindex;
  1205. X                else
  1206. X                    exponents[frame][expind[frame]++] = 
  1207. X                        (double)k/(double)numfreecols;
  1208. X            }
  1209. X            else
  1210. X                break;
  1211. X        }
  1212. X    for (j=0;j<point.x;j++) {
  1213. X        k = fread(&c, sizeof c, 1, infile);
  1214. X        if (k) {
  1215. X            BufferPoint(dpy,canvas,pixmap,Data_GC,&Points,(int)c,j,point.y);
  1216. X            if (k < mincolindex)
  1217. X                exponents[frame][expind[frame]++] = 
  1218. X                    -(double)k/(double)mincolindex;
  1219. X            else
  1220. X                exponents[frame][expind[frame]++] = 
  1221. X                    (double)k/(double)numfreecols;
  1222. X        }
  1223. X        else
  1224. X            break;
  1225. X    }
  1226. X    fclose(infile);
  1227. X    FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  1228. X}
  1229. X
  1230. Xvoid
  1231. Xrecalc() 
  1232. X{
  1233. X    static int i, index, x, y;
  1234. X    
  1235. X    minexp = maxexp = 0.0;
  1236. X    x = y = 0;
  1237. X    for (i=0;i<expind[frame];i++) {
  1238. X        if (exponents[frame][i] < minexp)
  1239. X            minexp = exponents[frame][i];
  1240. X        if (exponents[frame][i] > maxexp)
  1241. X            maxexp = exponents[frame][i];
  1242. X    }
  1243. X}
  1244. X
  1245. Xvoid
  1246. XClear() 
  1247. X{
  1248. X    XFillRectangle(dpy, pixmap, Data_GC[0], 0, 0, width, height);
  1249. X    XCopyArea(dpy, pixmap, canvas, Data_GC[0], 
  1250. X                0, 0, width, height, 0, 0);
  1251. X    InitBuffer(&Points, maxcolor);
  1252. X}
  1253. X
  1254. Xvoid
  1255. Xshow_defaults() 
  1256. X{
  1257. X
  1258. X    printf("Width=%d  Height=%d  numcolors=%d  settle=%d  dwell=%d\n",
  1259. X        width,height,numcolors,settle,dwell);
  1260. X    printf("min_a=%lf  a_range=%lf  max_a=%lf\n", min_a,a_range,max_a);
  1261. X    printf("min_b=%lf  b_range=%lf  max_b=%lf\n", min_b,b_range,max_b);
  1262. X    printf("minlyap=%lf  minexp=%lf  maxexp=%lf\n", minlyap,minexp,maxexp);
  1263. X    exit(0);
  1264. X}
  1265. X
  1266. Xvoid
  1267. XCreateXorGC()
  1268. X{
  1269. X    XGCValues values;
  1270. X
  1271. X    values.foreground = foreground;
  1272. X    values.line_style = LineSolid;
  1273. X    values.function = GXxor;
  1274. X    RubberGC = XCreateGC(dpy, DefaultRootWindow(dpy),
  1275. X          GCForeground | GCBackground | GCFunction | GCLineStyle, &values);
  1276. X}
  1277. X
  1278. Xvoid 
  1279. XStartRubberBand(w, data, event)
  1280. XWindow w;
  1281. Ximage_data_t *data;
  1282. XXEvent *event;
  1283. X{
  1284. X    XPoint corners[5];
  1285. X    extern void SetupCorners();
  1286. X
  1287. X    nostart = 0;
  1288. X    data->rubber_band.last_x = data->rubber_band.start_x = event->xbutton.x;
  1289. X    data->rubber_band.last_y = data->rubber_band.start_y = event->xbutton.y;
  1290. X    SetupCorners(corners, data);
  1291. X    XDrawLines(dpy, canvas, RubberGC,
  1292. X        corners, sizeof(corners) / sizeof(corners[0]), CoordModeOrigin);
  1293. X}
  1294. X
  1295. Xvoid
  1296. XSetupCorners(corners, data)
  1297. XXPoint *corners;
  1298. Ximage_data_t *data;
  1299. X{
  1300. X    corners[0].x = data->rubber_band.start_x;
  1301. X    corners[0].y = data->rubber_band.start_y;
  1302. X    corners[1].x = data->rubber_band.start_x;
  1303. X    corners[1].y = data->rubber_band.last_y;
  1304. X    corners[2].x = data->rubber_band.last_x;
  1305. X    corners[2].y = data->rubber_band.last_y;
  1306. X    corners[3].x = data->rubber_band.last_x;
  1307. X    corners[3].y = data->rubber_band.start_y;
  1308. X    corners[4] = corners[0];
  1309. X}
  1310. X
  1311. Xvoid 
  1312. XTrackRubberBand(w, data, event)
  1313. XWindow w;
  1314. Ximage_data_t *data;
  1315. XXEvent *event;
  1316. X{
  1317. X    XPoint corners[5];
  1318. X    int xdiff, ydiff, diff;
  1319. X    extern void SetupCorners();
  1320. X
  1321. X    if (nostart)
  1322. X        return;
  1323. X    SetupCorners(corners, data);
  1324. X    XDrawLines(dpy, canvas, RubberGC, corners, 
  1325. X               sizeof(corners) / sizeof(corners[0]), CoordModeOrigin);
  1326. X    ydiff = event->xbutton.y - data->rubber_band.start_y;
  1327. X    xdiff = event->xbutton.x - data->rubber_band.start_x;
  1328. X    data->rubber_band.last_x = data->rubber_band.start_x + xdiff;
  1329. X    data->rubber_band.last_y = data->rubber_band.start_y + ydiff;
  1330. X    if (data->rubber_band.last_y < data->rubber_band.start_y ||
  1331. X        data->rubber_band.last_x < data->rubber_band.start_x) {
  1332. X            data->rubber_band.last_y = data->rubber_band.start_y;
  1333. X            data->rubber_band.last_x = data->rubber_band.start_x;
  1334. X    }
  1335. X    SetupCorners(corners, data);
  1336. X    XDrawLines(dpy, canvas, RubberGC, corners, 
  1337. X               sizeof(corners) / sizeof(corners[0]), CoordModeOrigin);
  1338. X}
  1339. X
  1340. Xvoid 
  1341. XEndRubberBand(w, data, event)
  1342. XWindow w;
  1343. Ximage_data_t *data;
  1344. XXEvent *event;
  1345. X{
  1346. X    XPoint corners[5];
  1347. X    XPoint top, bot;
  1348. X    double delta, diff;
  1349. X    extern void set_new_params(), SetupCorners();
  1350. X
  1351. X    nostart = 1;
  1352. X    SetupCorners(corners, data);
  1353. X    XDrawLines(dpy, canvas, RubberGC,
  1354. X        corners, sizeof(corners) / sizeof(corners[0]), CoordModeOrigin);
  1355. X    if (data->rubber_band.start_x >= data->rubber_band.last_x ||
  1356. X        data->rubber_band.start_y >= data->rubber_band.last_y)
  1357. X        return;
  1358. X    top.x = data->rubber_band.start_x;
  1359. X    bot.x = data->rubber_band.last_x;
  1360. X    top.y = data->rubber_band.start_y;
  1361. X    bot.y = data->rubber_band.last_y;
  1362. X    diff = data->q_max - data->q_min;
  1363. X    delta = (double)top.y / (double)height;
  1364. X    data->q_min += diff * delta;
  1365. X    delta = (double)(height - bot.y) / (double)height;
  1366. X    data->q_max -= diff * delta;
  1367. X    diff = data->p_max - data->p_min;
  1368. X    delta = (double)top.x / (double)width;
  1369. X    data->p_min += diff * delta;
  1370. X    delta = (double)(width - bot.x) / (double)width;
  1371. X    data->p_max -= diff * delta;
  1372. X    fflush(stdout);
  1373. X    set_new_params(w, data);
  1374. X}
  1375. X
  1376. Xvoid
  1377. Xset_new_params(w, data)
  1378. XWindow w;
  1379. Ximage_data_t *data;
  1380. X{
  1381. X    extern void Clear();
  1382. X
  1383. X    frame = (maxframe + 1) % MAXFRAMES;
  1384. X    if (frame > maxframe)
  1385. X        maxframe = frame;
  1386. X    a_range = data->p_max - data->p_min;
  1387. X    b_range = data->q_max - data->q_min;
  1388. X    a_minimums[frame] = min_a = data->p_min;
  1389. X    b_minimums[frame] = min_b = data->q_min;
  1390. X    a_inc = a_range / (double)width;
  1391. X    b_inc = b_range / (double)height;
  1392. X    point.x = 0;
  1393. X    point.y = 0;
  1394. X    run = 1;
  1395. X    a = min_a;
  1396. X    b = min_b;
  1397. X    a_maximums[frame] = max_a = data->p_max;
  1398. X    b_maximums[frame] = max_b = data->q_max;
  1399. X    expind[frame] = 0;
  1400. X    Clear();
  1401. X}
  1402. X
  1403. Xvoid
  1404. Xgo_down() 
  1405. X{
  1406. X    static int i;
  1407. X    
  1408. X    frame++;
  1409. X    if (frame > maxframe)
  1410. X        frame = 0;
  1411. X    jumpwin();
  1412. X}
  1413. X
  1414. Xvoid
  1415. Xgo_back() 
  1416. X{
  1417. X    static int i;
  1418. X    
  1419. X    frame--;
  1420. X    if (frame < 0)
  1421. X        frame = maxframe;
  1422. X    jumpwin();
  1423. X}
  1424. X
  1425. Xjumpwin()
  1426. X{
  1427. X    rubber_data.p_min = min_a = a_minimums[frame];
  1428. X    rubber_data.q_min = min_b = b_minimums[frame];
  1429. X    rubber_data.p_max = max_a = a_maximums[frame];
  1430. X    rubber_data.q_max = max_b = b_maximums[frame];
  1431. X    a_range = max_a - min_a;
  1432. X    b_range = max_b - min_b;
  1433. X    a_inc = a_range / (double)width;
  1434. X    b_inc = b_range / (double)height;
  1435. X    point.x = 0;
  1436. X    point.y = 0;
  1437. X    a = min_a;
  1438. X    b = min_b;
  1439. X    Clear();
  1440. X    if (resized[frame])
  1441. X        Redraw();
  1442. X    else
  1443. X        redraw(exponents[frame], expind[frame], 0);
  1444. X}
  1445. X
  1446. Xvoid
  1447. Xgo_init() 
  1448. X{
  1449. X    static int i;
  1450. X    
  1451. X    frame = 0;
  1452. X    jumpwin();
  1453. X}
  1454. X
  1455. XDestroy_frame()
  1456. X{
  1457. X    static int i;
  1458. X
  1459. X    for (i=frame; i<maxframe; i++) {
  1460. X        exponents[frame] = exponents[frame+1];
  1461. X        expind[frame] = expind[frame+1];
  1462. X        a_minimums[frame] = a_minimums[frame+1];
  1463. X        b_minimums[frame] = b_minimums[frame+1];
  1464. X        a_maximums[frame] = a_maximums[frame+1];
  1465. X        b_maximums[frame] = b_maximums[frame+1];
  1466. X    }
  1467. X    maxframe--;
  1468. X    go_back();
  1469. X}
  1470. X
  1471. Xvoid
  1472. Xprint_help() 
  1473. X{
  1474. X    printf("During run-time, interactive control can be exerted via : \n");
  1475. X    printf("Mouse buttons allow rubber-banding of a zoom box\n");
  1476. X    printf("< halves the 'dwell', > doubles the 'dwell'\n");
  1477. X    printf("[ halves the 'settle', ] doubles the 'settle'\n");
  1478. X    printf("D flushes the drawing buffer\n");
  1479. X    printf("d descends a ladder of windows created via the u or U keys\n");
  1480. X    printf("e or E recalculates color indices\n");
  1481. X    printf("f saves program state to a file\n");
  1482. X    printf("F saves window to a PPM file\n");
  1483. X    printf("h or H or ? displays this message\n");
  1484. X    printf("i decrements, I increments the stripe interval\n");
  1485. X    printf("KJMN increase/decrease minimum negative exponent\n");
  1486. X    printf("m increments the map index, changing maps\n");
  1487. X    printf("p or P reverses the colormap for negative/positive exponents\n");
  1488. X    printf("r redraws without recalculating\n");
  1489. X    printf("R redraws, recalculating with new dwell and settle values\n");
  1490. X    printf("s or S spins the colorwheel\n");
  1491. X    printf("u pops back up to the last zoom\n");
  1492. X    printf("U pops back up to the first picture\n");
  1493. X    printf("v or V displays the values of various settings\n");
  1494. X    printf("w decrements, W increments the color wheel index\n");
  1495. X    printf("x or X clears the window\n");
  1496. X    printf("q or Q exits\n");
  1497. X}
  1498. X
  1499. Xvoid
  1500. Xprint_values() 
  1501. X{
  1502. X    static int i;
  1503. X
  1504. X    printf("\nminlyap=%lf minexp=%lf maxexp=%lf\n",minlyap,minexp,maxexp);
  1505. X    printf("width=%d height=%d\n",width,height);
  1506. X    printf("settle=%d  dwell=%d start_x=%lf\n",settle,dwell, start_x);
  1507. X    printf("min_a=%lf  a_rng=%lf  max_a=%lf\n",min_a,a_range,max_a);
  1508. X    printf("min_b=%lf  b_rng=%lf  max_b=%lf\n",min_b,b_range,max_b);
  1509. X    if (Rflag)
  1510. X        printf("pseudo-random forcing\n");
  1511. X    else if (force) {
  1512. X        printf("periodic forcing=");
  1513. X        for (i=0;i<maxindex;i++)
  1514. X            printf("%d",forcing[i]);
  1515. X        printf("\n");
  1516. X    }
  1517. X    else
  1518. X        printf("periodic forcing=01\n");
  1519. X    if (Force) {
  1520. X        printf("function forcing=");
  1521. X        for (i=0;i<funcmaxindex;i++)
  1522. X            printf("%d",Forcing[i]);
  1523. X        printf("\n");
  1524. X    }
  1525. X    printf("numcolors=%d\n",numcolors);
  1526. X}
  1527. X
  1528. Xfreemem()
  1529. X{
  1530. X    static int i;
  1531. X    for (i=0;i<MAXFRAMES;i++)
  1532. X        free(exponents[i]);
  1533. X}
  1534. X
  1535. Xsetupmem()
  1536. X{
  1537. X    static int i;
  1538. X
  1539. X    for (i=0;i<MAXFRAMES;i++) {
  1540. X        if((exponents[i]=
  1541. X            (double *)malloc(sizeof(double)*width*height))==NULL){
  1542. X                fprintf(stderr,"Error malloc'ing exponent array.\n");
  1543. X                exit(-1);
  1544. X        }
  1545. X    }
  1546. X}
  1547. X
  1548. Xsetforcing()
  1549. X{
  1550. X    static int i;
  1551. X    extern double drand48();
  1552. X
  1553. X    for (i=0;i<MAXINDEX;i++)
  1554. X        forcing[i] = (drand48() > prob) ? 0 : 1;
  1555. X}
  1556. END_OF_FILE
  1557.   if test 47187 -ne `wc -c <'lyap/lyap.c'`; then
  1558.     echo shar: \"'lyap/lyap.c'\" unpacked with wrong size!
  1559.   fi
  1560.   # end of 'lyap/lyap.c'
  1561. fi
  1562. if test ! -d 'lyap/params' ; then
  1563.     echo shar: Creating directory \"'lyap/params'\"
  1564.     mkdir 'lyap/params'
  1565. fi
  1566. if test -f 'lyap/testit' -a "${1}" != "-c" ; then 
  1567.   echo shar: Will not clobber existing file \"'lyap/testit'\"
  1568. else
  1569.   echo shar: Extracting \"'lyap/testit'\" \(1389 characters\)
  1570.   sed "s/^X//" >'lyap/testit' <<'END_OF_FILE'
  1571. X#! /bin/sh
  1572. X# Test Harness for Lyapunov Space Exploring Program
  1573. X
  1574. XS=4
  1575. XD=8
  1576. XW=128
  1577. XH=120
  1578. XV=$1
  1579. X
  1580. X[ "$V" = "demo" ] && {
  1581. X    S=40
  1582. X    D=80
  1583. X    W=350
  1584. X    H=300
  1585. X}
  1586. X
  1587. X[ "$V" = "vista" ] &&
  1588. X    echo "vista:hits 1.3" >> hits
  1589. X
  1590. X# testing function
  1591. Xtest_case() 
  1592. X{
  1593. X
  1594. X    [ "$V" = "vista" ] && echo partition "$1" >> hits
  1595. X
  1596. X    if [ "$V" = "demo" ] ; then
  1597. X        $1
  1598. X    else
  1599. X        $1 > /dev/null 2>&1
  1600. X    fi
  1601. X    if [ $? = 0 ] ; then
  1602. X    [ "$V" = "demo" ] || echo $1 : PASS
  1603. X    else
  1604. X    [ "$V" = "demo" ] || echo $1 : FAIL
  1605. X    fi
  1606. X}
  1607. X
  1608. X[ "$V" = "demo" ] || {
  1609. X    echo ""
  1610. X    echo "    Running Suite of Test Cases for Lyap"
  1611. X    echo ""
  1612. X}
  1613. X
  1614. X[ "$V" = "demo" ] || {
  1615. X    echo "Usage message should report as test FAIL"
  1616. X    test_case "./lyap -u -d -S $S -D $D -W $W -H $H"
  1617. X    echo ""
  1618. X}
  1619. X
  1620. Xtest_case "./lyap -d -S $S -D $D -W $W -H $H"
  1621. Xtest_case "./lyap -d -f aaaaaabbbbbb -S $S -D $D -W $W -H $H"
  1622. Xtest_case "./lyap -d -f aaaaaabbbbbb -F 000000111111 -S $S -D $D -W $W -H $H"
  1623. Xtest_case "./lyap -d -f abbabaab -m 1 -S $S -D $D -W $W -H $H"
  1624. Xtest_case "./lyap -d -m 2 -S $S -D $D -W $W -H $H"
  1625. Xtest_case "./lyap -d -m 3 -S $S -D $D -W $W -H $H"
  1626. Xtest_case "./lyap -d -m 4 -S $S -D $D -W $W -H $H"
  1627. X
  1628. X[ "$V" = "demo" ] || {
  1629. X    echo ""
  1630. X    echo "Map index too high should report as test FAIL"
  1631. X    test_case "./lyap -d -m 5 -S $S -D $D -W $W -H $H"
  1632. X    echo ""
  1633. X    echo "    Test Cases Complete "
  1634. X    echo ""
  1635. X}
  1636. X
  1637. X[ "$V" = "vista" ] &&
  1638. X    echo "  Run ViSTA Reports MetGen, AudGen & CovGen"
  1639. Xecho ""
  1640. END_OF_FILE
  1641.   if test 1389 -ne `wc -c <'lyap/testit'`; then
  1642.     echo shar: \"'lyap/testit'\" unpacked with wrong size!
  1643.   fi
  1644.   chmod +x 'lyap/testit'
  1645.   # end of 'lyap/testit'
  1646. fi
  1647. echo shar: End of archive 1 \(of 3\).
  1648. cp /dev/null ark1isdone
  1649. MISSING=""
  1650. for I in 1 2 3 ; do
  1651.     if test ! -f ark${I}isdone ; then
  1652.     MISSING="${MISSING} ${I}"
  1653.     fi
  1654. done
  1655. if test "${MISSING}" = "" ; then
  1656.     echo You have unpacked all 3 archives.
  1657.     rm -f ark[1-9]isdone
  1658. else
  1659.     echo You still must unpack the following archives:
  1660.     echo "        " ${MISSING}
  1661. fi
  1662. exit 0
  1663. exit 0 # Just in case...
  1664. -- 
  1665.   // chris@Sterling.COM           | Send comp.sources.x submissions to:
  1666. \X/  Amiga - The only way to fly! |    sources-x@sterling.com
  1667.  "It's intuitively obvious to the |
  1668.   most casual observer..."        | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
  1669.