1 /*
2 * Grace - GRaphing, Advanced Computation and Exploration of data
3 *
4 * Home page: http://plasma-gate.weizmann.ac.il/Grace/
5 *
6 * Copyright (c) 1991-1995 Paul J Turner, Portland, OR
7 * Copyright (c) 1996-2000 Grace Development Team
8 *
9 * Maintained by Evgeny Stambulchik
10 *
11 *
12 * All Rights Reserved
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29 /*
30 *
31 * routines to allocate, manipulate, and return
32 * information about sets.
33 *
34 */
35
36 #include <config.h>
37 #include <cmath.h>
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #include "globals.h"
44 #include "utils.h"
45 #include "files.h"
46 #include "graphs.h"
47 #include "protos.h"
48
49 extern graph *g;
50
51 /*
52 * return the string version of the set type
53 */
set_types(int it)54 char *set_types(int it)
55 {
56 char *s = "xy";
57
58 switch (it) {
59 case SET_XY:
60 s = "xy";
61 break;
62 case SET_BAR:
63 s = "bar";
64 break;
65 case SET_BARDY:
66 s = "bardy";
67 break;
68 case SET_BARDYDY:
69 s = "bardydy";
70 break;
71 case SET_XYZ:
72 s = "xyz";
73 break;
74 case SET_XYDX:
75 s = "xydx";
76 break;
77 case SET_XYDY:
78 s = "xydy";
79 break;
80 case SET_XYDXDX:
81 s = "xydxdx";
82 break;
83 case SET_XYDYDY:
84 s = "xydydy";
85 break;
86 case SET_XYDXDY:
87 s = "xydxdy";
88 break;
89 case SET_XYDXDXDYDY:
90 s = "xydxdxdydy";
91 break;
92 case SET_XYHILO:
93 s = "xyhilo";
94 break;
95 case SET_XYR:
96 s = "xyr";
97 break;
98 case SET_XYCOLOR:
99 s = "xycolor";
100 break;
101 case SET_XYCOLPAT:
102 s = "xycolpat";
103 break;
104 case SET_XYVMAP:
105 s = "xyvmap";
106 break;
107 case SET_BOXPLOT:
108 s = "xyboxplot";
109 break;
110 case SET_XYSIZE:
111 s = "xysize";
112 break;
113 }
114 return s;
115 }
116
get_settype_by_name(char * s)117 int get_settype_by_name(char *s)
118 {
119 int i;
120
121 for (i = 0; i < NUMBER_OF_SETTYPES; i++) {
122 if (strcmp(set_types(i), s) == 0) {
123 return i;
124 }
125 }
126 return SET_BAD;
127 }
128
settype_cols(int type)129 int settype_cols(int type)
130 {
131 int ncols;
132
133 switch (type) {
134 case SET_XY:
135 case SET_BAR:
136 ncols = 2;
137 break;
138 case SET_XYDX:
139 case SET_XYDY:
140 case SET_XYZ:
141 case SET_BARDY:
142 case SET_XYR:
143 case SET_XYCOLOR:
144 case SET_XYSIZE:
145 ncols = 3;
146 break;
147 case SET_XYDXDX:
148 case SET_XYDYDY:
149 case SET_XYDXDY:
150 case SET_BARDYDY:
151 case SET_XYCOLPAT:
152 case SET_XYVMAP:
153 ncols = 4;
154 break;
155 case SET_XYHILO:
156 ncols = 5;
157 break;
158 case SET_XYDXDXDYDY:
159 case SET_BOXPLOT:
160 ncols = 6;
161 break;
162 default:
163 ncols = 0;
164 break;
165 }
166
167 return ncols;
168 }
169
170 /*
171 * return the string version of the dataset column
172 */
dataset_colname(int col)173 char *dataset_colname(int col)
174 {
175 char *s;
176
177 switch (col) {
178 case 0:
179 s = "X";
180 break;
181 case 1:
182 s = "Y";
183 break;
184 case 2:
185 s = "Y1";
186 break;
187 case 3:
188 s = "Y2";
189 break;
190 case 4:
191 s = "Y3";
192 break;
193 case 5:
194 s = "Y4";
195 break;
196 default:
197 s = "?";
198 errmsg("Internal error in dataset_colname()");
199 break;
200 }
201 return s;
202 }
203
zero_set_data(Dataset * dsp)204 int zero_set_data(Dataset *dsp)
205 {
206 int k;
207
208 if (dsp) {
209 dsp->len = 0;
210 for (k = 0; k < MAX_SET_COLS; k++) {
211 dsp->ex[k] = NULL;
212 }
213 dsp->s = NULL;
214 return RETURN_SUCCESS;
215 } else {
216 return RETURN_FAILURE;
217 }
218 }
219
220 /*
221 * free set data
222 */
free_set_data(Dataset * dsp)223 int free_set_data(Dataset *dsp)
224 {
225 int k;
226
227 if (dsp) {
228 if (dsp->len) {
229 for (k = 0; k < MAX_SET_COLS; k++) {
230 XCFREE(dsp->ex[k]);
231 }
232 if (dsp->s) {
233 for (k = 0; k < dsp->len; k++) {
234 XCFREE(dsp->s[k]);
235 }
236 XCFREE(dsp->s);
237 }
238 dsp->len = 0;
239 set_dirtystate();
240 }
241 return RETURN_SUCCESS;
242 } else {
243 return RETURN_FAILURE;
244 }
245 }
246
247 /*
248 * free set data, but preserve the parameter settings
249 */
killsetdata(int gno,int setno)250 void killsetdata(int gno, int setno)
251 {
252 if (is_valid_setno(gno, setno)) {
253 free_set_data(&g[gno].p[setno].data);
254 }
255 }
256
257 /*
258 * (re)allocate data arrays for a set of length len.
259 */
setlength(int gno,int setno,int len)260 int setlength(int gno, int setno, int len)
261 {
262 plotarr *p;
263 int i, j, ncols, oldlen;
264
265 if (is_valid_setno(gno, setno) != TRUE) {
266 return RETURN_FAILURE;
267 }
268
269 p = &g[gno].p[setno];
270
271 oldlen = p->data.len;
272 if (len == oldlen) {
273 return RETURN_SUCCESS;
274 }
275 if (len < 0) {
276 return RETURN_FAILURE;
277 }
278
279 ncols = settype_cols(p->type);
280
281 if (ncols == 0) {
282 errmsg("Set type not found in setlength()!");
283 return RETURN_FAILURE;
284 }
285
286 for (i = 0; i < ncols; i++) {
287 if ((p->data.ex[i] = xrealloc(p->data.ex[i], len*SIZEOF_DOUBLE)) == NULL
288 && len != 0) {
289 return RETURN_FAILURE;
290 }
291 for (j = oldlen; j < len; j++) {
292 p->data.ex[i][j] = 0.0;
293 }
294 }
295
296 if (p->data.s != NULL) {
297 for (i = len; i < oldlen; i++) {
298 xfree(p->data.s[i]);
299 }
300 p->data.s = xrealloc(p->data.s, len*sizeof(char *));
301 for (j = oldlen; j < len; j++) {
302 p->data.s[j] = copy_string(NULL, "");
303 }
304 }
305
306 p->data.len = len;
307
308 set_dirtystate();
309
310 return RETURN_SUCCESS;
311 }
312
313 /*
314 * moveset
315 */
moveset(int gnofrom,int setfrom,int gnoto,int setto)316 int moveset(int gnofrom, int setfrom, int gnoto, int setto)
317 {
318 if (gnoto == gnofrom && setfrom == setto) {
319 return RETURN_FAILURE;
320 }
321
322 if (is_valid_setno(gnofrom, setfrom) != TRUE) {
323 return RETURN_FAILURE;
324 }
325
326 if (is_set_active(gnoto, setto)) {
327 killset(gnoto, setto);
328 }
329 activateset(gnoto, setto);
330
331 memcpy(&g[gnoto].p[setto], &g[gnofrom].p[setfrom], sizeof(plotarr));
332
333 zero_set_data(&g[gnofrom].p[setfrom].data);
334
335 g[gnofrom].p[setfrom].hidden = TRUE;
336
337 set_dirtystate();
338 return RETURN_SUCCESS;
339 }
340
341
342 /*
343 * copy a set to another set, if the to set doesn't exist allocate it
344 */
copyset(int gfrom,int setfrom,int gto,int setto)345 int copyset(int gfrom, int setfrom, int gto, int setto)
346 {
347 int i, k, len, ncols;
348 double *savec[MAX_SET_COLS];
349 char **saves;
350 char buf[256];
351
352 if (!is_set_active(gfrom, setfrom)) {
353 return RETURN_FAILURE;
354 }
355 if (!is_valid_gno(gto)) {
356 return RETURN_FAILURE;
357 }
358 if (setfrom == setto && gfrom == gto) {
359 return RETURN_FAILURE;
360 }
361 if (is_set_active(gto, setto)) {
362 killset(gto, setto);
363 }
364 len = getsetlength(gfrom, setfrom);
365 ncols = dataset_cols(gfrom, setfrom);
366 activateset(gto, setto);
367 set_dataset_type(gto, setto, dataset_type(gfrom, setfrom));
368 if (setlength(gto, setto, len) != RETURN_SUCCESS) {
369 return RETURN_FAILURE;
370 }
371 if (g[gfrom].p[setfrom].data.s != NULL) {
372 if ((g[gto].p[setto].data.s = xmalloc(len*sizeof(char *))) == NULL) {
373 return RETURN_FAILURE;
374 }
375 }
376
377 for (k = 0; k < MAX_SET_COLS; k++) {
378 savec[k] = getcol(gto, setto, k);
379 }
380 saves = get_set_strings(gto, setto);
381 memcpy(&g[gto].p[setto], &g[gfrom].p[setfrom], sizeof(plotarr));
382 for (k = 0; k < ncols; k++) {
383 g[gto].p[setto].data.ex[k] = savec[k];
384 memcpy(g[gto].p[setto].data.ex[k],
385 g[gfrom].p[setfrom].data.ex[k],
386 len*SIZEOF_DOUBLE);
387 }
388 g[gto].p[setto].data.s = saves;
389 if (g[gfrom].p[setfrom].data.s != NULL) {
390 for (i = 0; i < len; i++) {
391 g[gto].p[setto].data.s[i] =
392 copy_string(NULL, g[gfrom].p[setfrom].data.s[i]);
393 }
394 }
395
396 sprintf(buf, "copy of set G%d.S%d", gfrom, setfrom);
397 setcomment(gto, setto, buf);
398
399 set_dirtystate();
400
401 return RETURN_SUCCESS;
402 }
403
404 /*
405 * same as copyset(), but doesn't alter the to set appearance
406 */
copysetdata(int gfrom,int setfrom,int gto,int setto)407 int copysetdata(int gfrom, int setfrom, int gto, int setto)
408 {
409 int i, k, len, ncols;
410 char buf[256];
411
412 if (!is_set_active(gfrom, setfrom)) {
413 return RETURN_FAILURE;
414 }
415 if (!is_valid_gno(gto)) {
416 return RETURN_FAILURE;
417 }
418 if (setfrom == setto && gfrom == gto) {
419 return RETURN_FAILURE;
420 }
421 if (is_set_active(gto, setto)) {
422 killsetdata(gto, setto);
423 }
424 len = getsetlength(gfrom, setfrom);
425 ncols = dataset_cols(gfrom, setfrom);
426 activateset(gto, setto);
427 if (dataset_cols(gto, setto) != ncols) {
428 set_dataset_type(gto, setto, dataset_type(gfrom, setfrom));
429 }
430 if (setlength(gto, setto, len) != RETURN_SUCCESS) {
431 return RETURN_FAILURE;
432 }
433 if (g[gfrom].p[setfrom].data.s != NULL) {
434 if ((g[gto].p[setto].data.s = xmalloc(len*sizeof(char *))) == NULL) {
435 return RETURN_FAILURE;
436 }
437 }
438
439 for (k = 0; k < ncols; k++) {
440 memcpy(g[gto].p[setto].data.ex[k],
441 g[gfrom].p[setfrom].data.ex[k],
442 len*SIZEOF_DOUBLE);
443 }
444 if (g[gfrom].p[setfrom].data.s != NULL) {
445 for (i = 0; i < len; i++) {
446 g[gto].p[setto].data.s[i] =
447 copy_string(NULL, g[gfrom].p[setfrom].data.s[i]);
448 }
449 }
450
451 sprintf(buf, "copy of setdata G%d.S%d", gfrom, setfrom);
452 setcomment(gto, setto, buf);
453
454 set_dirtystate();
455
456 return RETURN_SUCCESS;
457 }
458
459 /*
460 * swap a set with another set
461 */
swapset(int gno1,int setno1,int gno2,int setno2)462 int swapset(int gno1, int setno1, int gno2, int setno2)
463 {
464 plotarr p;
465
466 if (is_valid_setno(gno1, setno1) == FALSE ||
467 is_valid_setno(gno2, setno2) == FALSE) {
468 return RETURN_FAILURE;
469 }
470 if (setno1 == setno2 && gno1 == gno2) {
471 return RETURN_FAILURE;
472 }
473
474 memcpy(&p, &g[gno2].p[setno2], sizeof(plotarr));
475 memcpy(&g[gno2].p[setno2], &g[gno1].p[setno1], sizeof(plotarr));
476 memcpy(&g[gno1].p[setno1], &p, sizeof(plotarr));
477
478 set_dirtystate();
479
480 return RETURN_SUCCESS;
481 }
482
483 /*
484 * kill a set
485 */
killset(int gno,int setno)486 void killset(int gno, int setno)
487 {
488 if (is_valid_setno(gno, setno)) {
489 killsetdata(gno, setno);
490 set_default_plotarr(&g[gno].p[setno]);
491 }
492 }
493
getcol(int gno,int setno,int col)494 double *getcol(int gno, int setno, int col)
495 {
496 if (is_valid_setno(gno, setno)) {
497 return g[gno].p[setno].data.ex[col];
498 } else {
499 return NULL;
500 }
501 }
502
setcol(int gno,int setno,int col,double * x,int len)503 void setcol(int gno, int setno, int col, double *x, int len)
504 {
505 if (is_valid_setno(gno, setno) != TRUE) {
506 return;
507 }
508 g[gno].p[setno].data.ex[col] = x;
509 g[gno].p[setno].data.len = len;
510 set_dirtystate();
511 }
512
get_set_strings(int gno,int setno)513 char **get_set_strings(int gno, int setno)
514 {
515 if (is_valid_setno(gno, setno)) {
516 return g[gno].p[setno].data.s;
517 } else {
518 return NULL;
519 }
520 }
521
set_set_strings(int gno,int setno,int len,char ** s)522 int set_set_strings(int gno, int setno, int len, char **s)
523 {
524 if (is_valid_setno(gno, setno) && len > 0 && s!= NULL) {
525 g[gno].p[setno].data.s = s;
526 g[gno].p[setno].data.len = len;
527 set_dirtystate();
528 return RETURN_SUCCESS;
529 } else {
530 return RETURN_FAILURE;
531 }
532 }
533
getsetlength(int gno,int setno)534 int getsetlength(int gno, int setno)
535 {
536 if (is_valid_setno(gno, setno)) {
537 return g[gno].p[setno].data.len;
538 } else {
539 return -1;
540 }
541 }
542
setcomment(int gno,int setno,char * s)543 int setcomment(int gno, int setno, char *s)
544 {
545 if (is_valid_setno(gno, setno) && s != NULL) {
546 strncpy(g[gno].p[setno].comments, s, MAX_STRING_LENGTH - 1);
547 set_dirtystate();
548 return RETURN_SUCCESS;
549 } else {
550 return RETURN_FAILURE;
551 }
552 }
553
getcomment(int gno,int setno)554 char *getcomment(int gno, int setno)
555 {
556 if (is_valid_setno(gno, setno)) {
557 return g[gno].p[setno].comments;
558 } else {
559 return NULL;
560 }
561 }
562
set_legend_string(int gno,int setno,char * s)563 int set_legend_string(int gno, int setno, char *s)
564 {
565 if (is_valid_setno(gno, setno) && s != NULL) {
566 strncpy(g[gno].p[setno].lstr, s, MAX_STRING_LENGTH - 1);
567 return RETURN_SUCCESS;
568 } else {
569 return RETURN_FAILURE;
570 }
571 }
572
get_legend_string(int gno,int setno)573 char *get_legend_string(int gno, int setno)
574 {
575 if (is_valid_setno(gno, setno)) {
576 return g[gno].p[setno].lstr;
577 } else {
578 return NULL;
579 }
580 }
581
set_dataset_type(int gno,int setno,int type)582 int set_dataset_type(int gno, int setno, int type)
583 {
584 int old_type = dataset_type(gno, setno);
585
586 if (old_type < 0) {
587 /* wrong gno/setno */
588 return RETURN_FAILURE;
589 } else if (old_type == type) {
590 /* nothing changed */
591 return RETURN_SUCCESS;
592 } else {
593 int i, len, ncols_old, ncols_new;
594
595 len = getsetlength(gno, setno);
596 ncols_old = dataset_cols(gno, setno);
597 ncols_new = settype_cols(type);
598 for (i = ncols_old; i < ncols_new; i++) {
599 g[gno].p[setno].data.ex[i] = xcalloc(len, SIZEOF_DOUBLE);
600 }
601 for (i = ncols_new; i < ncols_old; i++) {
602 XCFREE(g[gno].p[setno].data.ex[i]);
603 }
604
605 g[gno].p[setno].type = type;
606
607 set_dirtystate();
608 return RETURN_SUCCESS;
609 }
610 }
611
dataset_type(int gno,int setno)612 int dataset_type(int gno, int setno)
613 {
614 if (is_valid_setno(gno, setno)) {
615 return g[gno].p[setno].type;
616 } else {
617 return -1;
618 }
619 }
620
621
622
set_hotlink(int gno,int setno,int onoroff,char * fname,int src)623 void set_hotlink(int gno, int setno, int onoroff, char *fname, int src)
624 {
625 if (is_valid_setno(gno, setno) != TRUE) {
626 return;
627 }
628
629 g[gno].p[setno].hotlink = onoroff;
630 if (onoroff && fname != NULL) {
631 strcpy(g[gno].p[setno].hotfile, fname);
632 g[gno].p[setno].hotsrc = src;
633 }
634 set_dirtystate();
635 }
636
is_hotlinked(int gno,int setno)637 int is_hotlinked(int gno, int setno)
638 {
639 if (is_valid_setno(gno, setno) != TRUE) {
640 return FALSE;
641 }
642
643 if (g[gno].p[setno].hotlink && strlen(g[gno].p[setno].hotfile)) {
644 return g[gno].p[setno].hotlink;
645 } else {
646 return FALSE;
647 }
648 }
649
get_hotlink_file(int gno,int setno)650 char *get_hotlink_file(int gno, int setno)
651 {
652 if (is_valid_setno(gno, setno) != TRUE) {
653 return NULL;
654 } else {
655 return g[gno].p[setno].hotfile;
656 }
657 }
658
get_hotlink_src(int gno,int setno)659 int get_hotlink_src(int gno, int setno)
660 {
661 if (is_valid_setno(gno, setno) != TRUE) {
662 return -1;
663 } else {
664 return g[gno].p[setno].hotsrc;
665 }
666 }
667
do_update_hotlink(int gno,int setno)668 void do_update_hotlink(int gno, int setno)
669 {
670 if (is_hotlinked(gno, setno) != TRUE) {
671 return;
672 } else {
673 plotarr *p;
674 p = &g[gno].p[setno];
675 update_set_from_file(gno, setno, p->hotfile, p->hotsrc);
676 }
677 }
678
679
680 /*
681 * get the min/max fields of a set
682 */
getsetminmax(int gno,int setno,double * xmin,double * xmax,double * ymin,double * ymax)683 int getsetminmax(int gno, int setno,
684 double *xmin, double *xmax, double *ymin, double *ymax)
685 {
686 double *x, *y;
687 int len;
688 double x1, x2, y1, y2;
689 int i, first = TRUE;
690 int imin, imax; /* dummy */
691
692 if (setno == ALL_SETS) {
693 for (i = 0; i < number_of_sets(gno); i++) {
694 if (is_set_drawable(gno, i)) {
695 x = getcol(gno, i, 0);
696 y = getcol(gno, i, 1);
697 len = getsetlength(gno, i);
698 minmax(x, len, &x1, &x2, &imin, &imax);
699 minmax(y, len, &y1, &y2, &imin, &imax);
700 if (first) {
701 *xmin = x1;
702 *xmax = x2;
703 *ymin = y1;
704 *ymax = y2;
705 first = FALSE;
706 } else {
707 *xmin = (x1 < *xmin) ? x1 : *xmin;
708 *xmax = (x2 > *xmax) ? x2 : *xmax;
709 *ymin = (y1 < *ymin) ? y1 : *ymin;
710 *ymax = (y2 > *ymax) ? y2 : *ymax;
711 }
712 }
713 }
714 } else if (is_valid_setno(gno, setno)) {
715 x = getcol(gno, setno, 0);
716 y = getcol(gno, setno, 1);
717 len = getsetlength(gno, setno);
718 minmax(x, len, xmin, xmax, &imin, &imax);
719 minmax(y, len, ymin, ymax, &imin, &imax);
720 first = FALSE;
721 }
722
723 if (first == FALSE) {
724 return RETURN_SUCCESS;
725 } else {
726 return RETURN_FAILURE;
727 }
728 }
729
730 /*
731 * get the min/max fields of a set with fixed x/y range
732 */
getsetminmax_c(int gno,int setno,double * xmin,double * xmax,double * ymin,double * ymax,int ivec)733 int getsetminmax_c(int gno, int setno,
734 double *xmin, double *xmax, double *ymin, double *ymax, int ivec)
735 {
736 double vmin_t, vmax_t, *vmin, *vmax, bvmin, bvmax, *vec, *bvec;
737 int i, start, stop, n;
738 int first = TRUE, hits;
739
740 if (ivec == 1) {
741 bvmin = *xmin;
742 bvmax = *xmax;
743 vmin = ymin;
744 vmax = ymax;
745 } else {
746 bvmin = *ymin;
747 bvmax = *ymax;
748 vmin = xmin;
749 vmax = xmax;
750 }
751 if (setno == ALL_SETS) {
752 start = 0;
753 stop = number_of_sets(gno) - 1;
754 } else if (is_valid_setno(gno, setno)) {
755 start = setno;
756 stop = setno;
757 } else {
758 return RETURN_FAILURE;
759 }
760
761 for (i = start; i <= stop; i++) {
762 if (is_set_drawable(gno, i)) {
763
764 if (ivec == 1) {
765 bvec = getx(gno, i);
766 vec = gety(gno, i);
767 } else {
768 bvec = gety(gno, i);
769 vec = getx(gno, i);
770 }
771
772 n = getsetlength(gno, i);
773 hits = minmaxrange(bvec, vec, n, bvmin, bvmax, &vmin_t, &vmax_t);
774 if (hits == RETURN_SUCCESS) {
775 if (first) {
776 *vmin = vmin_t;
777 *vmax = vmax_t;
778 first = FALSE;
779 } else {
780 *vmin = MIN2(vmin_t, *vmin);
781 *vmax = MAX2(vmax_t, *vmax);
782 }
783 }
784 }
785 }
786
787 if (first == FALSE) {
788 return RETURN_SUCCESS;
789 } else {
790 return RETURN_FAILURE;
791 }
792 }
793
794
795 /*
796 * compute the mins and maxes of a vector x
797 */
minmax(double * x,int n,double * xmin,double * xmax,int * imin,int * imax)798 void minmax(double *x, int n, double *xmin, double *xmax, int *imin, int *imax)
799 {
800 int i;
801
802 *imin = 0;
803 *imax = 0;
804
805 if (x == NULL) {
806 *xmin = 0.0;
807 *xmax = 0.0;
808 return;
809 }
810
811 *xmin = x[0];
812 *xmax = x[0];
813
814 for (i = 1; i < n; i++) {
815 if (x[i] < *xmin) {
816 *xmin = x[i];
817 *imin = i;
818 }
819 if (x[i] > *xmax) {
820 *xmax = x[i];
821 *imax = i;
822 }
823 }
824 }
825
826
827 /*
828 * compute the min and max of vector vec calculated for indices such that
829 * bvec values lie within [bmin, bmax] range
830 * returns RETURN_FAILURE if none found
831 */
minmaxrange(double * bvec,double * vec,int n,double bvmin,double bvmax,double * vmin,double * vmax)832 int minmaxrange(double *bvec, double *vec, int n, double bvmin, double bvmax,
833 double *vmin, double *vmax)
834 {
835 int i, first = TRUE;
836
837 if ((vec == NULL) || (bvec == NULL)) {
838 return RETURN_FAILURE;
839 }
840
841 for (i = 0; i < n; i++) {
842 if ((bvec[i] >= bvmin) && (bvec[i] <= bvmax)) {
843 if (first == TRUE) {
844 *vmin = vec[i];
845 *vmax = vec[i];
846 first = FALSE;
847 } else {
848 if (vec[i] < *vmin) {
849 *vmin = vec[i];
850 } else if (vec[i] > *vmax) {
851 *vmax = vec[i];
852 }
853 }
854 }
855 }
856
857 if (first == FALSE) {
858 return RETURN_SUCCESS;
859 } else {
860 return RETURN_FAILURE;
861 }
862 }
863
864
865 /*
866 * compute the mins and maxes of a vector x
867 */
vmin(double * x,int n)868 double vmin(double *x, int n)
869 {
870 int i;
871 double xmin;
872 if (n <= 0) {
873 return 0.0;
874 }
875 xmin = x[0];
876 for (i = 1; i < n; i++) {
877 if (x[i] < xmin) {
878 xmin = x[i];
879 }
880 }
881 return xmin;
882 }
883
vmax(double * x,int n)884 double vmax(double *x, int n)
885 {
886 int i;
887 double xmax;
888 if (n <= 0) {
889 return 0.0;
890 }
891 xmax = x[0];
892 for (i = 1; i < n; i++) {
893 if (x[i] > xmax) {
894 xmax = x[i];
895 }
896 }
897 return xmax;
898 }
899
set_point(int gno,int setno,int seti,WPoint wp)900 int set_point(int gno, int setno, int seti, WPoint wp)
901 {
902 if (is_valid_setno(gno, setno) != TRUE) {
903 return RETURN_FAILURE;
904 }
905 if (seti >= getsetlength(gno, setno) || seti < 0) {
906 return RETURN_FAILURE;
907 }
908 (getcol(gno, setno, DATA_X))[seti] = wp.x;
909 (getcol(gno, setno, DATA_Y))[seti] = wp.y;
910 set_dirtystate();
911 return RETURN_SUCCESS;
912 }
913
get_point(int gno,int setno,int seti,WPoint * wp)914 int get_point(int gno, int setno, int seti, WPoint *wp)
915 {
916 if (is_valid_setno(gno, setno) != TRUE) {
917 return RETURN_FAILURE;
918 }
919 if (seti >= getsetlength(gno, setno) || seti < 0) {
920 return RETURN_FAILURE;
921 }
922 wp->x = (getcol(gno, setno, DATA_X))[seti];
923 wp->y = (getcol(gno, setno, DATA_Y))[seti];
924 return RETURN_SUCCESS;
925 }
926
copycol2(int gfrom,int setfrom,int gto,int setto,int col)927 void copycol2(int gfrom, int setfrom, int gto, int setto, int col)
928 {
929 int i, n1, n2;
930 double *x1, *x2;
931
932 if (is_valid_setno(gfrom, setfrom) != TRUE ||
933 is_valid_setno(gto, setto) != TRUE) {
934 return;
935 }
936 n1 = getsetlength(gfrom, setfrom);
937 n2 = getsetlength(gto, setto);
938 if (n1 != n2) {
939 return;
940 }
941 x1 = getcol(gfrom, setfrom, col);
942 x2 = getcol(gto, setto, col);
943 for (i = 0; i < n1; i++) {
944 x2[i] = x1[i];
945 }
946 set_dirtystate();
947 }
948
949
pushset(int gno,int setno,int push_type)950 int pushset(int gno, int setno, int push_type)
951 {
952 int i, newsetno;
953
954 if (is_valid_setno(gno, setno) != TRUE) {
955 return RETURN_FAILURE;
956 } else {
957 switch (push_type) {
958 case PUSH_SET_TOFRONT:
959 newsetno = number_of_sets(gno) - 1;
960 for (i = setno; i < newsetno; i++) {
961 if (swapset(gno, i, gno, i + 1) != RETURN_SUCCESS) {
962 return RETURN_FAILURE;
963 }
964 }
965 break;
966 case PUSH_SET_TOBACK:
967 newsetno = 0;
968 for (i = setno; i > newsetno; i--) {
969 if (swapset(gno, i, gno, i - 1) != RETURN_SUCCESS) {
970 return RETURN_FAILURE;
971 }
972 }
973 break;
974 default:
975 return RETURN_FAILURE;
976 break;
977 }
978 return RETURN_SUCCESS;
979 }
980 }
981
982
983 /*
984 * pack all sets leaving no gaps in the set structure
985 */
packsets(int gno)986 void packsets(int gno)
987 {
988 int i, j;
989
990 for (i = 0; i < number_of_sets(gno); i++) {
991 if (is_set_active(gno, i)) {
992 for (j = 0; j < i; j++) {
993 if (is_set_active(gno, j) != TRUE) {
994 moveset(gno, i, gno, j);
995 }
996 }
997 }
998 }
999 }
1000
allocate_set(int gno,int setno)1001 int allocate_set(int gno, int setno)
1002 {
1003 if (is_valid_setno(gno, setno)) {
1004 return RETURN_SUCCESS;
1005 } else
1006 if (setno >= 0) {
1007 return realloc_graph_plots(gno, setno + 1);
1008 } else {
1009 return RETURN_FAILURE;
1010 }
1011 }
1012
activateset(int gno,int setno)1013 int activateset(int gno, int setno)
1014 {
1015 int retval;
1016
1017 if (is_valid_gno(gno) != TRUE) {
1018 return RETURN_FAILURE;
1019 } else {
1020 retval = allocate_set(gno, setno);
1021 if (retval == RETURN_SUCCESS) {
1022 set_set_hidden(gno, setno, FALSE);
1023 }
1024 return retval;
1025 }
1026 }
1027
1028 static target recent_target = {-1, -1};
1029
get_recent_setno(void)1030 int get_recent_setno(void)
1031 {
1032 return recent_target.setno;
1033 }
1034
get_recent_gno(void)1035 int get_recent_gno(void)
1036 {
1037 return recent_target.gno;
1038 }
1039
1040 /*
1041 * return the next available set in graph gno
1042 * If target is allocated but with no data, choose it (used for loading sets
1043 * from project files when sets aren't packed)
1044 */
nextset(int gno)1045 int nextset(int gno)
1046 {
1047 int setno;
1048 int maxplot;
1049
1050 if (is_valid_gno(gno) != TRUE) {
1051 return (-1);
1052 }
1053
1054 if ( (target_set.gno == gno) &&
1055 is_valid_setno(target_set.gno, target_set.setno) &&
1056 !is_set_active(gno, target_set.setno)) {
1057 setno = target_set.setno;
1058 target_set.gno = -1;
1059 target_set.setno = -1;
1060 } else {
1061 maxplot = number_of_sets(gno);
1062 for (setno = 0; setno < maxplot; setno++) {
1063 if (!is_set_active(gno, setno)) {
1064 break;
1065 }
1066 }
1067 /* if no sets found, try allocating new one */
1068 if (setno == maxplot && allocate_set(gno, setno) != RETURN_SUCCESS) {
1069 return (-1);
1070 }
1071 }
1072 recent_target.gno = gno;
1073 recent_target.setno = setno;
1074 return (setno);
1075 }
1076
is_set_active(int gno,int setno)1077 int is_set_active(int gno, int setno)
1078 {
1079 if (is_valid_setno(gno, setno) && getsetlength(gno, setno) > 0) {
1080 return TRUE;
1081 } else {
1082 return FALSE;
1083 }
1084 }
1085
1086 /*
1087 * return number of active set(s) in gno
1088 */
number_of_active_sets(int gno)1089 int number_of_active_sets(int gno)
1090 {
1091 int setno, na;
1092
1093 if (is_valid_gno(gno) != TRUE) {
1094 return -1;
1095 }
1096
1097 na = 0;
1098 for (setno = 0; setno < number_of_sets(gno); setno++) {
1099 if (is_set_active(gno, setno) == TRUE) {
1100 na++;
1101 }
1102 }
1103 return na;
1104 }
1105
1106 /*
1107 * drop points from a set
1108 */
droppoints(int gno,int setno,int startno,int endno)1109 void droppoints(int gno, int setno, int startno, int endno)
1110 {
1111 double *x;
1112 char **s;
1113 int i, j, len, ncols, dist;
1114
1115 if (is_valid_setno(gno, setno) != TRUE) {
1116 return;
1117 }
1118
1119 dist = endno - startno + 1;
1120 if (dist <= 0) {
1121 return;
1122 }
1123
1124 len = getsetlength(gno, setno);
1125
1126 if (dist == len) {
1127 killsetdata(gno, setno);
1128 return;
1129 }
1130
1131 ncols = dataset_cols(gno, setno);
1132 for (j = 0; j < ncols; j++) {
1133 x = getcol(gno, setno, j);
1134 for (i = endno + 1; i < len; i++) {
1135 x[i - dist] = x[i];
1136 }
1137 }
1138 if ((s = get_set_strings(gno, setno)) != NULL) {
1139 for (i = endno + 1; i < len; i++) {
1140 s[i - dist] = copy_string(s[i - dist], s[i]);
1141 }
1142 }
1143 setlength(gno, setno, len - dist);
1144 }
1145
1146 /*
1147 * join several sets together; all but the first set in the list will be killed
1148 */
join_sets(int gno,int * sets,int nsets)1149 int join_sets(int gno, int *sets, int nsets)
1150 {
1151 int i, j, n, setno, setno_final, ncols, old_length, new_length;
1152 double *x1, *x2;
1153 char **s1, **s2;
1154
1155 if (nsets < 2) {
1156 errmsg("nsets < 2");
1157 return RETURN_FAILURE;
1158 }
1159
1160 setno_final = sets[0];
1161 ncols = dataset_cols(gno, setno_final);
1162 for (i = 0; i < nsets; i++) {
1163 setno = sets[i];
1164 if (is_valid_setno(gno, setno) != TRUE) {
1165 errmsg("Invalid setno in the list");
1166 return RETURN_FAILURE;
1167 }
1168 if (dataset_cols(gno, setno) != ncols) {
1169 errmsg("Can't join datasets with different number of cols");
1170 return RETURN_FAILURE;
1171 }
1172 }
1173
1174 new_length = getsetlength(gno, setno_final);
1175 for (i = 1; i < nsets; i++) {
1176 setno = sets[i];
1177 old_length = new_length;
1178 new_length += getsetlength(gno, setno);
1179 if (setlength(gno, setno_final, new_length) != RETURN_SUCCESS) {
1180 return RETURN_FAILURE;
1181 }
1182 for (j = 0; j < ncols; j++) {
1183 x1 = getcol(gno, setno_final, j);
1184 x2 = getcol(gno, setno, j);
1185 for (n = old_length; n < new_length; n++) {
1186 x1[n] = x2[n - old_length];
1187 }
1188 }
1189 s1 = get_set_strings(gno, setno_final);
1190 s2 = get_set_strings(gno, setno);
1191 if (s1 != NULL && s2 != NULL) {
1192 for (n = old_length; n < new_length; n++) {
1193 s1[n] = copy_string(s1[n], s2[n - old_length]);
1194 }
1195 }
1196 killset(gno, setno);
1197 }
1198
1199 return RETURN_SUCCESS;
1200 }
1201
reverse_set(int gno,int setno)1202 void reverse_set(int gno, int setno)
1203 {
1204 int n, i, j, k, ncols;
1205 double *x;
1206 char **s;
1207
1208 if (!is_valid_setno(gno, setno)) {
1209 return;
1210 }
1211 n = getsetlength(gno, setno);
1212 ncols = dataset_cols(gno, setno);
1213 for (k = 0; k < ncols; k++) {
1214 x = getcol(gno, setno, k);
1215 for (i = 0; i < n / 2; i++) {
1216 j = (n - 1) - i;
1217 fswap(&x[i], &x[j]);
1218 }
1219 }
1220 if ((s = get_set_strings(gno, setno)) != NULL) {
1221 char *stmp;
1222 for (i = 0; i < n / 2; i++) {
1223 j = (n - 1) - i;
1224 stmp = s[i];
1225 s[i] = s[j];
1226 s[j] = stmp;
1227 }
1228 }
1229 set_dirtystate();
1230 }
1231 /*
1232 * sort a set
1233 */
1234 static double *vptr;
1235
1236 /*
1237 * for ascending and descending sorts
1238 */
1239
compare_points1(const void * p1,const void * p2)1240 static int compare_points1(const void *p1, const void *p2)
1241 {
1242 const int *i1, *i2;
1243 double a, b;
1244 i1 = (const int *)p1;
1245 i2 = (const int *)p2;
1246 a = vptr[*i1];
1247 b = vptr[*i2];
1248 if (a < b) {
1249 return -1;
1250 }
1251 if (a > b) {
1252 return 1;
1253 }
1254 return 0;
1255 }
1256
compare_points2(const void * p1,const void * p2)1257 static int compare_points2(const void *p1, const void *p2)
1258 {
1259 const int *i1, *i2;
1260 double a, b;
1261 i1 = (const int *)p1;
1262 i2 = (const int *)p2;
1263 a = vptr[*i1];
1264 b = vptr[*i2];
1265 if (a > b) {
1266 return -1;
1267 }
1268 if (a < b) {
1269 return 1;
1270 }
1271 return 0;
1272 }
1273
sortset(int gno,int setno,int sorton,int stype)1274 void sortset(int gno, int setno, int sorton, int stype)
1275 {
1276 int i, j, nc, len, *ind;
1277 double *x, *xtmp;
1278 char **s, **stmp;
1279
1280 /* get the vector to sort on */
1281 vptr = getcol(gno, setno, sorton);
1282 if (vptr == NULL) {
1283 errmsg("NULL vector in sort, operation cancelled, check set type");
1284 return;
1285 }
1286
1287 len = getsetlength(gno, setno);
1288 if (len <= 1) {
1289 return;
1290 }
1291
1292 /* allocate memory for permuted indices */
1293 ind = xmalloc(len*SIZEOF_INT);
1294 if (ind == NULL) {
1295 return;
1296 }
1297 /* allocate memory for temporary array */
1298 xtmp = xmalloc(len*SIZEOF_DOUBLE);
1299 if (xtmp == NULL) {
1300 xfree(ind);
1301 return;
1302 }
1303
1304 s = get_set_strings(gno, setno);
1305 if (s != NULL) {
1306 stmp = xmalloc(len*sizeof(char *));
1307 if (stmp == NULL) {
1308 xfree(xtmp);
1309 xfree(ind);
1310 }
1311 } else {
1312 stmp = NULL;
1313 }
1314
1315 /* initialize indices */
1316 for (i = 0; i < len; i++) {
1317 ind[i] = i;
1318 }
1319
1320 /* sort */
1321 qsort(ind, len, SIZEOF_INT, stype ? compare_points2 : compare_points1);
1322
1323 /* straighten things out - done one vector at a time for storage */
1324
1325 nc = dataset_cols(gno, setno);
1326 /* loop over the number of columns */
1327 for (j = 0; j < nc; j++) {
1328 /* get this vector and put into the temporary vector in the right order */
1329 x = getcol(gno, setno, j);
1330 for (i = 0; i < len; i++) {
1331 xtmp[i] = x[ind[i]];
1332 }
1333
1334 /* load it back to the set */
1335 for (i = 0; i < len; i++) {
1336 x[i] = xtmp[i];
1337 }
1338 }
1339
1340 /* same with strings, if any */
1341 if (s != NULL) {
1342 for (i = 0; i < len; i++) {
1343 stmp[i] = s[ind[i]];
1344 }
1345
1346 for (i = 0; i < len; i++) {
1347 s[i] = stmp[i];
1348 }
1349 }
1350
1351 /* free allocated temporary arrays */
1352 xfree(stmp);
1353 xfree(xtmp);
1354 xfree(ind);
1355
1356 set_dirtystate();
1357 }
1358
1359 /*
1360 * sort two arrays
1361 */
sort_xy(double * tmp1,double * tmp2,int up,int sorton,int stype)1362 void sort_xy(double *tmp1, double *tmp2, int up, int sorton, int stype)
1363 {
1364
1365 int d, i, j;
1366 int lo = 0;
1367 double t1, t2;
1368
1369 if (sorton == 1) {
1370 double *ttmp;
1371
1372 ttmp = tmp1;
1373 tmp1 = tmp2;
1374 tmp2 = ttmp;
1375 }
1376 up--;
1377
1378 for (d = up - lo + 1; d > 1;) {
1379 if (d < 5)
1380 d = 1;
1381 else
1382 d = (5 * d - 1) / 11;
1383 for (i = up - d; i >= lo; i--) {
1384 t1 = tmp1[i];
1385 t2 = tmp2[i];
1386 if (!stype) {
1387 for (j = i + d; j <= up && (t1 > tmp1[j]); j += d) {
1388 tmp1[j - d] = tmp1[j];
1389 tmp2[j - d] = tmp2[j];
1390 }
1391 tmp1[j - d] = t1;
1392 tmp2[j - d] = t2;
1393 } else {
1394 for (j = i + d; j <= up && (t1 < tmp1[j]); j += d) {
1395 tmp1[j - d] = tmp1[j];
1396 tmp2[j - d] = tmp2[j];
1397 }
1398 tmp1[j - d] = t1;
1399 tmp2[j - d] = t2;
1400 }
1401 }
1402 }
1403 set_dirtystate();
1404 }
1405
1406 /*
1407 * delete the point pt in setno
1408 */
del_point(int gno,int setno,int pt)1409 void del_point(int gno, int setno, int pt)
1410 {
1411 droppoints(gno, setno, pt, pt);
1412 }
1413
1414 /*
1415 * add a point to setno
1416 */
add_point(int gno,int setno,double px,double py)1417 void add_point(int gno, int setno, double px, double py)
1418 {
1419 int len;
1420 double *x, *y;
1421
1422 if (is_valid_setno(gno, setno)) {
1423 len = getsetlength(gno, setno);
1424 setlength(gno, setno, len + 1);
1425 x = getx(gno, setno);
1426 y = gety(gno, setno);
1427 x[len] = px;
1428 y[len] = py;
1429 }
1430 }
1431
zero_datapoint(Datapoint * dpoint)1432 void zero_datapoint(Datapoint *dpoint)
1433 {
1434 int k;
1435
1436 for (k = 0; k < MAX_SET_COLS; k++) {
1437 dpoint->ex[k] = 0.0;
1438 }
1439 dpoint->s = NULL;
1440 }
1441
1442 /*
1443 * add a point to setno at ind
1444 */
add_point_at(int gno,int setno,int ind,const Datapoint * dpoint)1445 int add_point_at(int gno, int setno, int ind, const Datapoint *dpoint)
1446 {
1447 int len, col, ncols;
1448 double *ex;
1449 char **s;
1450
1451 if (is_valid_setno(gno, setno)) {
1452 len = getsetlength(gno, setno);
1453 if (ind < 0 || ind > len) {
1454 return RETURN_FAILURE;
1455 }
1456 len++;
1457 setlength(gno, setno, len);
1458 ncols = dataset_cols(gno, setno);
1459 for (col = 0; col < ncols; col++) {
1460 ex = getcol(gno, setno, col);
1461 if (ind < len - 1) {
1462 memmove(ex + ind + 1, ex + ind, (len - ind - 1)*SIZEOF_DOUBLE);
1463 }
1464 ex[ind] = dpoint->ex[col];
1465 }
1466 s = get_set_strings(gno, setno);
1467 if (s != NULL) {
1468 if (ind < len - 1) {
1469 memmove(s + ind + 1, s + ind, (len - ind - 1)*sizeof(char *));
1470 }
1471 s[ind] = copy_string(NULL, dpoint->s);
1472 }
1473 set_dirtystate();
1474 return RETURN_SUCCESS;
1475 } else {
1476 return RETURN_FAILURE;
1477 }
1478 }
1479
get_datapoint(int gno,int setno,int ind,int * ncols,Datapoint * dpoint)1480 int get_datapoint(int gno, int setno, int ind, int *ncols, Datapoint *dpoint)
1481 {
1482 int n, col;
1483 double *ex;
1484 char **s;
1485
1486 n = getsetlength(gno, setno);
1487 if (ind < 0 || ind >= n) {
1488 return RETURN_FAILURE;
1489 } else {
1490 *ncols = dataset_cols(gno, setno);
1491 for (col = 0; col < *ncols; col++) {
1492 ex = getcol(gno, setno, col);
1493 dpoint->ex[col] = ex[ind];
1494 }
1495 s = get_set_strings(gno, setno);
1496 if (s != NULL) {
1497 dpoint->s = s[ind];
1498 } else {
1499 dpoint->s = NULL;
1500 }
1501 return RETURN_SUCCESS;
1502 }
1503 }
1504
delete_byindex(int gno,int setno,int * ind)1505 void delete_byindex(int gno, int setno, int *ind)
1506 {
1507 int i, j, cnt = 0;
1508 int ncols = dataset_cols(gno, setno);
1509
1510 if (is_valid_setno(gno, setno) != TRUE) {
1511 return;
1512 }
1513
1514 for (i = 0; i < getsetlength(gno, setno); i++) {
1515 if (ind[i]) {
1516 cnt++;
1517 }
1518 }
1519 if (cnt == getsetlength(gno, setno)) {
1520 killset(gno, setno);
1521 return;
1522 }
1523 cnt = 0;
1524 for (i = 0; i < getsetlength(gno, setno); i++) {
1525 if (ind[i] == 0) {
1526 for (j = 0; j < ncols; j++) {
1527 (getcol(gno, setno, j))[cnt] = (getcol(gno, setno, j))[i];
1528 }
1529 cnt++;
1530 }
1531 }
1532 setlength(gno, setno, cnt);
1533 }
1534
1535
1536 /*
1537 * move a set to another set, in possibly another graph
1538 */
do_moveset(int gfrom,int setfrom,int gto,int setto)1539 int do_moveset(int gfrom, int setfrom, int gto, int setto)
1540 {
1541 int retval;
1542 char buf[64];
1543
1544 retval = moveset(gfrom, setfrom, gto, setto);
1545 if (retval != RETURN_SUCCESS) {
1546 sprintf(buf,
1547 "Error moving G%d.S%d to G%d.S%d",
1548 gfrom, setfrom, gto, setto);
1549 errmsg(buf);
1550 }
1551 return retval;
1552 }
1553
1554 /*
1555 * do_copyset
1556 */
do_copyset(int gfrom,int setfrom,int gto,int setto)1557 int do_copyset(int gfrom, int setfrom, int gto, int setto)
1558 {
1559 int retval;
1560 char buf[64];
1561
1562 retval = copyset(gfrom, setfrom, gto, setto);
1563 if (retval != RETURN_SUCCESS) {
1564 sprintf(buf,
1565 "Error copying G%d.S%d to G%d.S%d",
1566 gfrom, setfrom, gto, setto);
1567 errmsg(buf);
1568 }
1569 return retval;
1570 }
1571
1572 /*
1573 * do_swapset
1574 */
do_swapset(int gfrom,int setfrom,int gto,int setto)1575 int do_swapset(int gfrom, int setfrom, int gto, int setto)
1576 {
1577 int retval;
1578 char buf[64];
1579
1580 retval = swapset(gfrom, setfrom, gto, setto);
1581 if (retval != RETURN_SUCCESS) {
1582 sprintf(buf,
1583 "Error swapping G%d.S%d with G%d.S%d",
1584 gfrom, setfrom, gto, setto);
1585 errmsg(buf);
1586 }
1587 return retval;
1588 }
1589
1590 /*
1591 * split a set into lpart length sets
1592 */
do_splitsets(int gno,int setno,int lpart)1593 void do_splitsets(int gno, int setno, int lpart)
1594 {
1595 int i, j, k, ncols, len, plen, tmpset, npsets;
1596 double *x;
1597 char s[256];
1598 plotarr p;
1599 Dataset ds, dstmp;
1600
1601 if ((len = getsetlength(gno, setno)) < 2) {
1602 errmsg("Set length < 2");
1603 return;
1604 }
1605 if (lpart >= len) {
1606 errmsg("Split length >= set length");
1607 return;
1608 }
1609 if (lpart <= 0) {
1610 errmsg("Split length <= 0");
1611 return;
1612 }
1613
1614 npsets = (len - 1)/lpart + 1;
1615
1616 /* get number of columns in this set */
1617 ncols = dataset_cols(gno, setno);
1618
1619 p = g[gno].p[setno];
1620
1621 /* save the contents to a temporary buffer */
1622 memcpy(&ds, &p.data, sizeof(Dataset));
1623
1624 /* zero data contents of the original set */
1625 zero_set_data(&g[gno].p[setno].data);
1626
1627 /* now load each set */
1628 for (i = 0; i < npsets; i++) {
1629 plen = MIN2(lpart, len - i*lpart);
1630 tmpset = nextset(gno);
1631 if (!is_valid_setno(gno, tmpset)) {
1632 errmsg("Can't create new set");
1633 return;
1634 }
1635
1636 /* set the plot parameters */
1637 dstmp = g[gno].p[tmpset].data;
1638 g[gno].p[tmpset] = p;
1639 g[gno].p[tmpset].data = dstmp;
1640
1641 set_set_hidden(gno, tmpset, FALSE);
1642 if (setlength(gno, tmpset, plen) != RETURN_SUCCESS) {
1643 /* should not happen */
1644 return;
1645 }
1646 if (ds.s) {
1647 g[gno].p[tmpset].data.s = xmalloc(plen*sizeof(char *));
1648 }
1649
1650 /* load the data into each column */
1651 for (k = 0; k < ncols; k++) {
1652 x = getcol(gno, tmpset, k);
1653 for (j = 0; j < plen; j++) {
1654 x[j] = ds.ex[k][i*lpart + j];
1655 }
1656 }
1657 if (ds.s) {
1658 for (j = 0; j < plen; j++) {
1659 g[gno].p[tmpset].data.s[j] =
1660 copy_string(NULL, ds.s[i*lpart + j]);
1661 }
1662 }
1663
1664 sprintf(s, "partition %d of set G%d.S%d", i + 1, gno, setno);
1665 setcomment(gno, tmpset, s);
1666 }
1667
1668 free_set_data(&ds);
1669 }
1670
1671 /*
1672 * drop points from an active set
1673 */
do_drop_points(int gno,int setno,int startno,int endno)1674 void do_drop_points(int gno, int setno, int startno, int endno)
1675 {
1676 int setlength;
1677 char buf[256];
1678
1679 if (!is_set_active(gno, setno)) {
1680 sprintf(buf, "Set %d not active", setno);
1681 errmsg(buf);
1682 return;
1683 }
1684
1685 setlength = getsetlength(gno, setno);
1686 if (startno < 0) {
1687 startno = setlength + 1 + startno;
1688 }
1689 if (endno < 0) {
1690 endno = setlength + 1 + endno;
1691 }
1692
1693 if (startno > endno) {
1694 iswap(&startno, &endno);
1695 }
1696
1697 if (startno < 0) {
1698 errmsg("Start # < 0");
1699 return;
1700 }
1701 if (endno >= setlength) {
1702 errmsg("Ending # >= set length");
1703 return;
1704 }
1705
1706 droppoints(gno, setno, startno, endno);
1707 }
1708
1709
1710 /*
1711 * sort sets, only works on sets of type XY
1712 */
do_sort(int setno,int sorton,int stype)1713 void do_sort(int setno, int sorton, int stype)
1714 {
1715 int i, gno = get_cg();
1716 char buf[256];
1717
1718 if (setno == -1) {
1719 for (i = 0; i < number_of_sets(gno); i++) {
1720 if (is_set_active(gno, i)) {
1721 sortset(gno, i, sorton, stype);
1722 }
1723 }
1724 } else {
1725 if (!is_set_active(gno, setno)) {
1726 sprintf(buf, "Set %d not active", setno);
1727 errmsg(buf);
1728 return;
1729 } else {
1730 sortset(gno, setno, sorton, stype);
1731 }
1732 }
1733 }
1734
1735
setybase(int gno,int setno)1736 double setybase(int gno, int setno)
1737 {
1738 double dummy, *y, ybase = 0.0;
1739 int len;
1740
1741 if (is_valid_setno(gno, setno) != TRUE) {
1742 return 0.0;
1743 }
1744
1745 y = getcol(gno, setno, DATA_Y);
1746 len = getsetlength(gno, setno);
1747
1748 switch (g[gno].p[setno].baseline_type) {
1749 case BASELINE_TYPE_0:
1750 ybase = 0.0;
1751 break;
1752 case BASELINE_TYPE_SMIN:
1753 ybase = vmin(y, len);
1754 break;
1755 case BASELINE_TYPE_SAVG:
1756 stasum(y, len, &ybase, &dummy);
1757 break;
1758 case BASELINE_TYPE_SMAX:
1759 ybase = vmax(y, len);
1760 break;
1761 case BASELINE_TYPE_GMIN:
1762 ybase = g[gno].w.yg1;
1763 break;
1764 case BASELINE_TYPE_GMAX:
1765 ybase = g[gno].w.yg2;
1766 break;
1767 default:
1768 errmsg("Wrong type of baseline");
1769 }
1770
1771 return(ybase);
1772 }
1773
1774
dataset_cols(int gno,int setno)1775 int dataset_cols(int gno, int setno)
1776 {
1777 return settype_cols(dataset_type(gno, setno));
1778 }
1779
load_comments_to_legend(int gno,int setno)1780 int load_comments_to_legend(int gno, int setno)
1781 {
1782 return set_legend_string(gno, setno, getcomment(gno, setno));
1783 }
1784
filter_set(int gno,int setno,char * rarray)1785 int filter_set(int gno, int setno, char *rarray)
1786 {
1787 int i, ip, j, ncols;
1788 Dataset *dsp;
1789
1790 if (is_valid_setno(gno, setno) != TRUE) {
1791 return RETURN_FAILURE;
1792 }
1793 if (rarray == NULL) {
1794 return RETURN_SUCCESS;
1795 }
1796 ncols = dataset_cols(gno, setno);
1797 dsp = &(g[gno].p[setno].data);
1798 ip = 0;
1799 for (i = 0; i < dsp->len; i++) {
1800 if (rarray[i]) {
1801 for (j = 0; j < ncols; j++) {
1802 dsp->ex[j][ip] = dsp->ex[j][i];
1803 }
1804 if (dsp->s != NULL) {
1805 dsp->s[ip] = copy_string(dsp->s[ip], dsp->s[i]);
1806 }
1807 ip++;
1808 }
1809 }
1810 setlength(gno, setno, ip);
1811 return RETURN_SUCCESS;
1812 }
1813