2
* Grace - GRaphing, Advanced Computation and Exploration of data
4
* Home page: http://plasma-gate.weizmann.ac.il/Grace/
6
* Copyright (c) 1991-1995 Paul J Turner, Portland, OR
7
* Copyright (c) 1996-2000 Grace Development Team
9
* Maintained by Evgeny Stambulchik <fnevgeny@plasma-gate.weizmann.ac.il>
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.
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.
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.
31
* routines to allocate, manipulate, and return
32
* information about sets.
52
* return the string version of the set type
54
char *set_types(int it)
117
int get_settype_by_name(char *s)
121
for (i = 0; i < NUMBER_OF_SETTYPES; i++) {
122
if (strcmp(set_types(i), s) == 0) {
129
int settype_cols(int type)
171
* return the string version of the dataset column
173
char *dataset_colname(int col)
198
errmsg("Internal error in dataset_colname()");
204
int zero_set_data(Dataset *dsp)
210
for (k = 0; k < MAX_SET_COLS; k++) {
214
return RETURN_SUCCESS;
216
return RETURN_FAILURE;
223
int free_set_data(Dataset *dsp)
229
for (k = 0; k < MAX_SET_COLS; k++) {
233
for (k = 0; k < dsp->len; k++) {
241
return RETURN_SUCCESS;
243
return RETURN_FAILURE;
248
* free set data, but preserve the parameter settings
250
void killsetdata(int gno, int setno)
252
if (is_valid_setno(gno, setno)) {
253
free_set_data(&g[gno].p[setno].data);
258
* (re)allocate data arrays for a set of length len.
260
int setlength(int gno, int setno, int len)
263
int i, j, ncols, oldlen;
265
if (is_valid_setno(gno, setno) != TRUE) {
266
return RETURN_FAILURE;
269
p = &g[gno].p[setno];
271
oldlen = p->data.len;
273
return RETURN_SUCCESS;
276
return RETURN_FAILURE;
279
ncols = settype_cols(p->type);
282
errmsg("Set type not found in setlength()!");
283
return RETURN_FAILURE;
286
for (i = 0; i < ncols; i++) {
287
if ((p->data.ex[i] = xrealloc(p->data.ex[i], len*SIZEOF_DOUBLE)) == NULL
289
return RETURN_FAILURE;
291
for (j = oldlen; j < len; j++) {
292
p->data.ex[i][j] = 0.0;
296
if (p->data.s != NULL) {
297
for (i = len; i < oldlen; i++) {
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, "");
310
return RETURN_SUCCESS;
316
int moveset(int gnofrom, int setfrom, int gnoto, int setto)
318
if (gnoto == gnofrom && setfrom == setto) {
319
return RETURN_FAILURE;
322
if (is_valid_setno(gnofrom, setfrom) != TRUE) {
323
return RETURN_FAILURE;
326
if (is_set_active(gnoto, setto)) {
327
killset(gnoto, setto);
329
activateset(gnoto, setto);
331
memcpy(&g[gnoto].p[setto], &g[gnofrom].p[setfrom], sizeof(plotarr));
333
zero_set_data(&g[gnofrom].p[setfrom].data);
335
g[gnofrom].p[setfrom].hidden = TRUE;
338
return RETURN_SUCCESS;
343
* copy a set to another set, if the to set doesn't exist allocate it
345
int copyset(int gfrom, int setfrom, int gto, int setto)
347
int i, k, len, ncols;
348
double *savec[MAX_SET_COLS];
352
if (!is_set_active(gfrom, setfrom)) {
353
return RETURN_FAILURE;
355
if (!is_valid_gno(gto)) {
356
return RETURN_FAILURE;
358
if (setfrom == setto && gfrom == gto) {
359
return RETURN_FAILURE;
361
if (is_set_active(gto, setto)) {
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;
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;
377
for (k = 0; k < MAX_SET_COLS; k++) {
378
savec[k] = getcol(gto, setto, k);
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],
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]);
396
sprintf(buf, "copy of set G%d.S%d", gfrom, setfrom);
397
setcomment(gto, setto, buf);
401
return RETURN_SUCCESS;
405
* same as copyset(), but doesn't alter the to set appearance
407
int copysetdata(int gfrom, int setfrom, int gto, int setto)
409
int i, k, len, ncols;
412
if (!is_set_active(gfrom, setfrom)) {
413
return RETURN_FAILURE;
415
if (!is_valid_gno(gto)) {
416
return RETURN_FAILURE;
418
if (setfrom == setto && gfrom == gto) {
419
return RETURN_FAILURE;
421
if (is_set_active(gto, setto)) {
422
killsetdata(gto, setto);
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));
430
if (setlength(gto, setto, len) != RETURN_SUCCESS) {
431
return RETURN_FAILURE;
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;
439
for (k = 0; k < ncols; k++) {
440
memcpy(g[gto].p[setto].data.ex[k],
441
g[gfrom].p[setfrom].data.ex[k],
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]);
451
sprintf(buf, "copy of setdata G%d.S%d", gfrom, setfrom);
452
setcomment(gto, setto, buf);
456
return RETURN_SUCCESS;
460
* swap a set with another set
462
int swapset(int gno1, int setno1, int gno2, int setno2)
466
if (is_valid_setno(gno1, setno1) == FALSE ||
467
is_valid_setno(gno2, setno2) == FALSE) {
468
return RETURN_FAILURE;
470
if (setno1 == setno2 && gno1 == gno2) {
471
return RETURN_FAILURE;
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));
480
return RETURN_SUCCESS;
486
void killset(int gno, int setno)
488
if (is_valid_setno(gno, setno)) {
489
killsetdata(gno, setno);
490
set_default_plotarr(&g[gno].p[setno]);
494
double *getcol(int gno, int setno, int col)
496
if (is_valid_setno(gno, setno)) {
497
return g[gno].p[setno].data.ex[col];
503
void setcol(int gno, int setno, int col, double *x, int len)
505
if (is_valid_setno(gno, setno) != TRUE) {
508
g[gno].p[setno].data.ex[col] = x;
509
g[gno].p[setno].data.len = len;
513
char **get_set_strings(int gno, int setno)
515
if (is_valid_setno(gno, setno)) {
516
return g[gno].p[setno].data.s;
522
int set_set_strings(int gno, int setno, int len, char **s)
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;
528
return RETURN_SUCCESS;
530
return RETURN_FAILURE;
534
int getsetlength(int gno, int setno)
536
if (is_valid_setno(gno, setno)) {
537
return g[gno].p[setno].data.len;
543
int setcomment(int gno, int setno, char *s)
545
if (is_valid_setno(gno, setno) && s != NULL) {
546
strncpy(g[gno].p[setno].comments, s, MAX_STRING_LENGTH - 1);
548
return RETURN_SUCCESS;
550
return RETURN_FAILURE;
554
char *getcomment(int gno, int setno)
556
if (is_valid_setno(gno, setno)) {
557
return g[gno].p[setno].comments;
563
int set_legend_string(int gno, int setno, char *s)
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;
569
return RETURN_FAILURE;
573
char *get_legend_string(int gno, int setno)
575
if (is_valid_setno(gno, setno)) {
576
return g[gno].p[setno].lstr;
582
int set_dataset_type(int gno, int setno, int type)
584
int old_type = dataset_type(gno, setno);
587
/* wrong gno/setno */
588
return RETURN_FAILURE;
589
} else if (old_type == type) {
590
/* nothing changed */
591
return RETURN_SUCCESS;
593
int i, len, ncols_old, ncols_new;
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);
601
for (i = ncols_new; i < ncols_old; i++) {
602
XCFREE(g[gno].p[setno].data.ex[i]);
605
g[gno].p[setno].type = type;
608
return RETURN_SUCCESS;
612
int dataset_type(int gno, int setno)
614
if (is_valid_setno(gno, setno)) {
615
return g[gno].p[setno].type;
623
void set_hotlink(int gno, int setno, int onoroff, char *fname, int src)
625
if (is_valid_setno(gno, setno) != TRUE) {
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;
637
int is_hotlinked(int gno, int setno)
639
if (is_valid_setno(gno, setno) != TRUE) {
643
if (g[gno].p[setno].hotlink && strlen(g[gno].p[setno].hotfile)) {
644
return g[gno].p[setno].hotlink;
650
char *get_hotlink_file(int gno, int setno)
652
if (is_valid_setno(gno, setno) != TRUE) {
655
return g[gno].p[setno].hotfile;
659
int get_hotlink_src(int gno, int setno)
661
if (is_valid_setno(gno, setno) != TRUE) {
664
return g[gno].p[setno].hotsrc;
668
void do_update_hotlink(int gno, int setno)
670
if (is_valid_setno(gno, setno) != TRUE) {
673
read_xyset_fromfile(gno, setno, g[gno].p[setno].hotfile,
674
g[gno].p[setno].hotsrc, g[gno].p[setno].hotlink);
680
* get the min/max fields of a set
682
int getsetminmax(int gno, int setno,
683
double *xmin, double *xmax, double *ymin, double *ymax)
687
double x1, x2, y1, y2;
689
int imin, imax; /* dummy */
691
if (setno == ALL_SETS) {
692
for (i = 0; i < number_of_sets(gno); i++) {
693
if (is_set_drawable(gno, i)) {
694
x = getcol(gno, i, 0);
695
y = getcol(gno, i, 1);
696
len = getsetlength(gno, i);
697
minmax(x, len, &x1, &x2, &imin, &imax);
698
minmax(y, len, &y1, &y2, &imin, &imax);
706
*xmin = (x1 < *xmin) ? x1 : *xmin;
707
*xmax = (x2 > *xmax) ? x2 : *xmax;
708
*ymin = (y1 < *ymin) ? y1 : *ymin;
709
*ymax = (y2 > *ymax) ? y2 : *ymax;
713
} else if (is_valid_setno(gno, setno)) {
714
x = getcol(gno, setno, 0);
715
y = getcol(gno, setno, 1);
716
len = getsetlength(gno, setno);
717
minmax(x, len, xmin, xmax, &imin, &imax);
718
minmax(y, len, ymin, ymax, &imin, &imax);
722
if (first == FALSE) {
723
return RETURN_SUCCESS;
725
return RETURN_FAILURE;
730
* get the min/max fields of a set with fixed x/y range
732
int getsetminmax_c(int gno, int setno,
733
double *xmin, double *xmax, double *ymin, double *ymax, int ivec)
735
double vmin_t, vmax_t, *vmin, *vmax, bvmin, bvmax, *vec, *bvec;
736
int i, start, stop, n;
737
int first = TRUE, hits;
750
if (setno == ALL_SETS) {
752
stop = number_of_sets(gno) - 1;
753
} else if (is_valid_setno(gno, setno)) {
757
return RETURN_FAILURE;
760
for (i = start; i <= stop; i++) {
761
if (is_set_drawable(gno, i)) {
771
n = getsetlength(gno, i);
772
hits = minmaxrange(bvec, vec, n, bvmin, bvmax, &vmin_t, &vmax_t);
773
if (hits == RETURN_SUCCESS) {
779
*vmin = MIN2(vmin_t, *vmin);
780
*vmax = MAX2(vmax_t, *vmax);
786
if (first == FALSE) {
787
return RETURN_SUCCESS;
789
return RETURN_FAILURE;
795
* compute the mins and maxes of a vector x
797
void minmax(double *x, int n, double *xmin, double *xmax, int *imin, int *imax)
813
for (i = 1; i < n; i++) {
827
* compute the min and max of vector vec calculated for indices such that
828
* bvec values lie within [bmin, bmax] range
829
* returns RETURN_FAILURE if none found
831
int minmaxrange(double *bvec, double *vec, int n, double bvmin, double bvmax,
832
double *vmin, double *vmax)
836
if ((vec == NULL) || (bvec == NULL)) {
837
return RETURN_FAILURE;
840
for (i = 0; i < n; i++) {
841
if ((bvec[i] >= bvmin) && (bvec[i] <= bvmax)) {
847
if (vec[i] < *vmin) {
849
} else if (vec[i] > *vmax) {
856
if (first == FALSE) {
857
return RETURN_SUCCESS;
859
return RETURN_FAILURE;
865
* compute the mins and maxes of a vector x
867
double vmin(double *x, int n)
875
for (i = 1; i < n; i++) {
883
double vmax(double *x, int n)
891
for (i = 1; i < n; i++) {
899
int set_point(int gno, int setno, int seti, WPoint wp)
901
if (is_valid_setno(gno, setno) != TRUE) {
902
return RETURN_FAILURE;
904
if (seti >= getsetlength(gno, setno) || seti < 0) {
905
return RETURN_FAILURE;
907
(getcol(gno, setno, DATA_X))[seti] = wp.x;
908
(getcol(gno, setno, DATA_Y))[seti] = wp.y;
910
return RETURN_SUCCESS;
913
int get_point(int gno, int setno, int seti, WPoint *wp)
915
if (is_valid_setno(gno, setno) != TRUE) {
916
return RETURN_FAILURE;
918
if (seti >= getsetlength(gno, setno) || seti < 0) {
919
return RETURN_FAILURE;
921
wp->x = (getcol(gno, setno, DATA_X))[seti];
922
wp->y = (getcol(gno, setno, DATA_Y))[seti];
923
return RETURN_SUCCESS;
926
void copycol2(int gfrom, int setfrom, int gto, int setto, int col)
931
if (is_valid_setno(gfrom, setfrom) != TRUE ||
932
is_valid_setno(gto, setto) != TRUE) {
935
n1 = getsetlength(gfrom, setfrom);
936
n2 = getsetlength(gto, setto);
940
x1 = getcol(gfrom, setfrom, col);
941
x2 = getcol(gto, setto, col);
942
for (i = 0; i < n1; i++) {
949
int pushset(int gno, int setno, int push_type)
953
if (is_valid_setno(gno, setno) != TRUE) {
954
return RETURN_FAILURE;
957
case PUSH_SET_TOFRONT:
958
newsetno = number_of_sets(gno) - 1;
959
for (i = setno; i < newsetno; i++) {
960
if (swapset(gno, i, gno, i + 1) != RETURN_SUCCESS) {
961
return RETURN_FAILURE;
965
case PUSH_SET_TOBACK:
967
for (i = setno; i > newsetno; i--) {
968
if (swapset(gno, i, gno, i - 1) != RETURN_SUCCESS) {
969
return RETURN_FAILURE;
974
return RETURN_FAILURE;
977
return RETURN_SUCCESS;
983
* pack all sets leaving no gaps in the set structure
985
void packsets(int gno)
989
for (i = 0; i < number_of_sets(gno); i++) {
990
if (is_set_active(gno, i)) {
991
for (j = 0; j < i; j++) {
992
if (is_set_active(gno, j) != TRUE) {
993
moveset(gno, i, gno, j);
1000
int allocate_set(int gno, int setno)
1002
if (is_valid_setno(gno, setno)) {
1003
return RETURN_SUCCESS;
1005
return realloc_graph_plots(gno, setno + 1);
1009
int activateset(int gno, int setno)
1013
if (is_valid_gno(gno) != TRUE) {
1014
return RETURN_FAILURE;
1016
retval = allocate_set(gno, setno);
1017
if (retval == RETURN_SUCCESS) {
1018
set_set_hidden(gno, setno, FALSE);
1024
static target recent_target = {-1, -1};
1026
int get_recent_setno(void)
1028
return recent_target.setno;
1031
int get_recent_gno(void)
1033
return recent_target.gno;
1037
* return the next available set in graph gno
1038
* If target is allocated but with no data, choose it (used for loading sets
1039
* from project files when sets aren't packed)
1041
int nextset(int gno)
1046
if (is_valid_gno(gno) != TRUE) {
1050
if ( (target_set.gno == gno) &&
1051
is_valid_setno(target_set.gno, target_set.setno) &&
1052
!is_set_active(gno, target_set.setno)) {
1053
setno = target_set.setno;
1054
target_set.gno = -1;
1055
target_set.setno = -1;
1057
maxplot = number_of_sets(gno);
1058
for (setno = 0; setno < maxplot; setno++) {
1059
if (!is_set_active(gno, setno)) {
1063
/* if no sets found, try allocating new one */
1064
if (setno == maxplot && allocate_set(gno, setno) != RETURN_SUCCESS) {
1068
recent_target.gno = gno;
1069
recent_target.setno = setno;
1073
int is_set_active(int gno, int setno)
1075
if (is_valid_setno(gno, setno) && getsetlength(gno, setno) > 0) {
1083
* return number of active set(s) in gno
1085
int number_of_active_sets(int gno)
1089
if (is_valid_gno(gno) != TRUE) {
1094
for (setno = 0; setno < number_of_sets(gno); setno++) {
1095
if (is_set_active(gno, setno) == TRUE) {
1103
* drop points from a set
1105
void droppoints(int gno, int setno, int startno, int endno)
1109
int i, j, len, ncols, dist;
1111
if (is_valid_setno(gno, setno) != TRUE) {
1115
dist = endno - startno + 1;
1120
len = getsetlength(gno, setno);
1123
killsetdata(gno, setno);
1127
ncols = dataset_cols(gno, setno);
1128
for (j = 0; j < ncols; j++) {
1129
x = getcol(gno, setno, j);
1130
for (i = endno + 1; i < len; i++) {
1134
if ((s = get_set_strings(gno, setno)) != NULL) {
1135
for (i = endno + 1; i < len; i++) {
1136
s[i - dist] = copy_string(s[i - dist], s[i]);
1139
setlength(gno, setno, len - dist);
1143
* join several sets together; all but the first set in the list will be killed
1145
int join_sets(int gno, int *sets, int nsets)
1147
int i, j, n, setno, setno_final, ncols, old_length, new_length;
1152
errmsg("nsets < 2");
1153
return RETURN_FAILURE;
1156
setno_final = sets[0];
1157
ncols = dataset_cols(gno, setno_final);
1158
for (i = 0; i < nsets; i++) {
1160
if (is_valid_setno(gno, setno) != TRUE) {
1161
errmsg("Invalid setno in the list");
1162
return RETURN_FAILURE;
1164
if (dataset_cols(gno, setno) != ncols) {
1165
errmsg("Can't join datasets with different number of cols");
1166
return RETURN_FAILURE;
1170
new_length = getsetlength(gno, setno_final);
1171
for (i = 1; i < nsets; i++) {
1173
old_length = new_length;
1174
new_length += getsetlength(gno, setno);
1175
if (setlength(gno, setno_final, new_length) != RETURN_SUCCESS) {
1176
return RETURN_FAILURE;
1178
for (j = 0; j < ncols; j++) {
1179
x1 = getcol(gno, setno_final, j);
1180
x2 = getcol(gno, setno, j);
1181
for (n = old_length; n < new_length; n++) {
1182
x1[n] = x2[n - old_length];
1185
s1 = get_set_strings(gno, setno_final);
1186
s2 = get_set_strings(gno, setno);
1187
if (s1 != NULL && s2 != NULL) {
1188
for (n = old_length; n < new_length; n++) {
1189
s1[n] = copy_string(s1[n], s2[n - old_length]);
1192
killset(gno, setno);
1195
return RETURN_SUCCESS;
1198
void reverse_set(int gno, int setno)
1200
int n, i, j, k, ncols;
1204
if (!is_valid_setno(gno, setno)) {
1207
n = getsetlength(gno, setno);
1208
ncols = dataset_cols(gno, setno);
1209
for (k = 0; k < ncols; k++) {
1210
x = getcol(gno, setno, k);
1211
for (i = 0; i < n / 2; i++) {
1213
fswap(&x[i], &x[j]);
1216
if ((s = get_set_strings(gno, setno)) != NULL) {
1218
for (i = 0; i < n / 2; i++) {
1230
static double *vptr;
1233
* for ascending and descending sorts
1236
static int compare_points1(const void *p1, const void *p2)
1240
i1 = (const int *)p1;
1241
i2 = (const int *)p2;
1253
static int compare_points2(const void *p1, const void *p2)
1257
i1 = (const int *)p1;
1258
i2 = (const int *)p2;
1270
void sortset(int gno, int setno, int sorton, int stype)
1272
int i, j, nc, len, *ind;
1276
/* get the vector to sort on */
1277
vptr = getcol(gno, setno, sorton);
1279
errmsg("NULL vector in sort, operation cancelled, check set type");
1283
len = getsetlength(gno, setno);
1288
/* allocate memory for permuted indices */
1289
ind = xmalloc(len*SIZEOF_INT);
1293
/* allocate memory for temporary array */
1294
xtmp = xmalloc(len*SIZEOF_DOUBLE);
1300
s = get_set_strings(gno, setno);
1302
stmp = xmalloc(len*sizeof(char *));
1311
/* initialize indices */
1312
for (i = 0; i < len; i++) {
1317
qsort(ind, len, SIZEOF_INT, stype ? compare_points2 : compare_points1);
1319
/* straighten things out - done one vector at a time for storage */
1321
nc = dataset_cols(gno, setno);
1322
/* loop over the number of columns */
1323
for (j = 0; j < nc; j++) {
1324
/* get this vector and put into the temporary vector in the right order */
1325
x = getcol(gno, setno, j);
1326
for (i = 0; i < len; i++) {
1327
xtmp[i] = x[ind[i]];
1330
/* load it back to the set */
1331
for (i = 0; i < len; i++) {
1336
/* same with strings, if any */
1338
for (i = 0; i < len; i++) {
1339
stmp[i] = s[ind[i]];
1342
for (i = 0; i < len; i++) {
1347
/* free allocated temporary arrays */
1358
void sort_xy(double *tmp1, double *tmp2, int up, int sorton, int stype)
1374
for (d = up - lo + 1; d > 1;) {
1378
d = (5 * d - 1) / 11;
1379
for (i = up - d; i >= lo; i--) {
1383
for (j = i + d; j <= up && (t1 > tmp1[j]); j += d) {
1384
tmp1[j - d] = tmp1[j];
1385
tmp2[j - d] = tmp2[j];
1390
for (j = i + d; j <= up && (t1 < tmp1[j]); j += d) {
1391
tmp1[j - d] = tmp1[j];
1392
tmp2[j - d] = tmp2[j];
1403
* delete the point pt in setno
1405
void del_point(int gno, int setno, int pt)
1407
droppoints(gno, setno, pt, pt);
1411
* add a point to setno
1413
void add_point(int gno, int setno, double px, double py)
1418
if (is_valid_setno(gno, setno)) {
1419
len = getsetlength(gno, setno);
1420
setlength(gno, setno, len + 1);
1421
x = getx(gno, setno);
1422
y = gety(gno, setno);
1428
void zero_datapoint(Datapoint *dpoint)
1432
for (k = 0; k < MAX_SET_COLS; k++) {
1433
dpoint->ex[k] = 0.0;
1439
* add a point to setno at ind
1441
int add_point_at(int gno, int setno, int ind, const Datapoint *dpoint)
1443
int len, col, ncols;
1447
if (is_valid_setno(gno, setno)) {
1448
len = getsetlength(gno, setno);
1449
if (ind < 0 || ind > len) {
1450
return RETURN_FAILURE;
1453
setlength(gno, setno, len);
1454
ncols = dataset_cols(gno, setno);
1455
for (col = 0; col < ncols; col++) {
1456
ex = getcol(gno, setno, col);
1457
if (ind < len - 1) {
1458
memmove(ex + ind + 1, ex + ind, (len - ind - 1)*SIZEOF_DOUBLE);
1460
ex[ind] = dpoint->ex[col];
1462
s = get_set_strings(gno, setno);
1464
if (ind < len - 1) {
1465
memmove(s + ind + 1, s + ind, (len - ind - 1)*sizeof(char *));
1467
s[ind] = copy_string(NULL, dpoint->s);
1470
return RETURN_SUCCESS;
1472
return RETURN_FAILURE;
1476
int get_datapoint(int gno, int setno, int ind, int *ncols, Datapoint *dpoint)
1482
n = getsetlength(gno, setno);
1483
if (ind < 0 || ind >= n) {
1484
return RETURN_FAILURE;
1486
*ncols = dataset_cols(gno, setno);
1487
for (col = 0; col < *ncols; col++) {
1488
ex = getcol(gno, setno, col);
1489
dpoint->ex[col] = ex[ind];
1491
s = get_set_strings(gno, setno);
1497
return RETURN_SUCCESS;
1501
void delete_byindex(int gno, int setno, int *ind)
1504
int ncols = dataset_cols(gno, setno);
1506
if (is_valid_setno(gno, setno) != TRUE) {
1510
for (i = 0; i < getsetlength(gno, setno); i++) {
1515
if (cnt == getsetlength(gno, setno)) {
1516
killset(gno, setno);
1520
for (i = 0; i < getsetlength(gno, setno); i++) {
1522
for (j = 0; j < ncols; j++) {
1523
(getcol(gno, setno, j))[cnt] = (getcol(gno, setno, j))[i];
1528
setlength(gno, setno, cnt);
1533
* move a set to another set, in possibly another graph
1535
int do_moveset(int gfrom, int setfrom, int gto, int setto)
1540
retval = moveset(gfrom, setfrom, gto, setto);
1541
if (retval != RETURN_SUCCESS) {
1543
"Error moving G%d.S%d to G%d.S%d",
1544
gfrom, setfrom, gto, setto);
1553
int do_copyset(int gfrom, int setfrom, int gto, int setto)
1558
retval = copyset(gfrom, setfrom, gto, setto);
1559
if (retval != RETURN_SUCCESS) {
1561
"Error copying G%d.S%d to G%d.S%d",
1562
gfrom, setfrom, gto, setto);
1571
int do_swapset(int gfrom, int setfrom, int gto, int setto)
1576
retval = swapset(gfrom, setfrom, gto, setto);
1577
if (retval != RETURN_SUCCESS) {
1579
"Error swapping G%d.S%d with G%d.S%d",
1580
gfrom, setfrom, gto, setto);
1587
* split a set into lpart length sets
1589
void do_splitsets(int gno, int setno, int lpart)
1591
int i, j, k, ncols, len, plen, tmpset, npsets;
1597
if ((len = getsetlength(gno, setno)) < 2) {
1598
errmsg("Set length < 2");
1602
errmsg("Split length >= set length");
1606
errmsg("Split length <= 0");
1610
npsets = (len - 1)/lpart + 1;
1612
/* get number of columns in this set */
1613
ncols = dataset_cols(gno, setno);
1615
p = g[gno].p[setno];
1617
/* save the contents to a temporary buffer */
1618
memcpy(&ds, &p.data, sizeof(Dataset));
1620
/* zero data contents of the original set */
1621
zero_set_data(&g[gno].p[setno].data);
1623
/* now load each set */
1624
for (i = 0; i < npsets; i++) {
1625
plen = MIN2(lpart, len - i*lpart);
1626
tmpset = nextset(gno);
1627
if (!is_valid_setno(gno, tmpset)) {
1628
errmsg("Can't create new set");
1632
/* set the plot parameters */
1633
dstmp = g[gno].p[tmpset].data;
1634
g[gno].p[tmpset] = p;
1635
g[gno].p[tmpset].data = dstmp;
1637
set_set_hidden(gno, tmpset, FALSE);
1638
if (setlength(gno, tmpset, plen) != RETURN_SUCCESS) {
1639
/* should not happen */
1643
g[gno].p[tmpset].data.s = xmalloc(plen*sizeof(char *));
1646
/* load the data into each column */
1647
for (k = 0; k < ncols; k++) {
1648
x = getcol(gno, tmpset, k);
1649
for (j = 0; j < plen; j++) {
1650
x[j] = ds.ex[k][i*lpart + j];
1654
for (j = 0; j < plen; j++) {
1655
g[gno].p[tmpset].data.s[j] =
1656
copy_string(NULL, ds.s[i*lpart + j]);
1660
sprintf(s, "partition %d of set G%d.S%d", i + 1, gno, setno);
1661
setcomment(gno, tmpset, s);
1668
* drop points from an active set
1670
void do_drop_points(int gno, int setno, int startno, int endno)
1675
if (!is_set_active(gno, setno)) {
1676
sprintf(buf, "Set %d not active", setno);
1681
setlength = getsetlength(gno, setno);
1683
startno = setlength + 1 + startno;
1686
endno = setlength + 1 + endno;
1689
if (startno > endno) {
1690
iswap(&startno, &endno);
1694
errmsg("Start # < 0");
1697
if (endno >= setlength) {
1698
errmsg("Ending # >= set length");
1702
droppoints(gno, setno, startno, endno);
1707
* sort sets, only works on sets of type XY
1709
void do_sort(int setno, int sorton, int stype)
1711
int i, gno = get_cg();
1715
for (i = 0; i < number_of_sets(gno); i++) {
1716
if (is_set_active(gno, i)) {
1717
sortset(gno, i, sorton, stype);
1721
if (!is_set_active(gno, setno)) {
1722
sprintf(buf, "Set %d not active", setno);
1726
sortset(gno, setno, sorton, stype);
1732
double setybase(int gno, int setno)
1734
double dummy, *y, ybase = 0.0;
1737
if (is_valid_setno(gno, setno) != TRUE) {
1741
y = getcol(gno, setno, DATA_Y);
1742
len = getsetlength(gno, setno);
1744
switch (g[gno].p[setno].baseline_type) {
1745
case BASELINE_TYPE_0:
1748
case BASELINE_TYPE_SMIN:
1749
ybase = vmin(y, len);
1751
case BASELINE_TYPE_SAVG:
1752
stasum(y, len, &ybase, &dummy);
1754
case BASELINE_TYPE_SMAX:
1755
ybase = vmax(y, len);
1757
case BASELINE_TYPE_GMIN:
1758
ybase = g[gno].w.yg1;
1760
case BASELINE_TYPE_GMAX:
1761
ybase = g[gno].w.yg2;
1764
errmsg("Wrong type of baseline");
1771
int dataset_cols(int gno, int setno)
1773
return settype_cols(dataset_type(gno, setno));
1776
int load_comments_to_legend(int gno, int setno)
1778
return set_legend_string(gno, setno, getcomment(gno, setno));
1781
int filter_set(int gno, int setno, char *rarray)
1783
int i, ip, j, ncols;
1786
if (is_valid_setno(gno, setno) != TRUE) {
1787
return RETURN_FAILURE;
1789
if (rarray == NULL) {
1790
return RETURN_SUCCESS;
1792
ncols = dataset_cols(gno, setno);
1793
dsp = &(g[gno].p[setno].data);
1795
for (i = 0; i < dsp->len; i++) {
1797
for (j = 0; j < ncols; j++) {
1798
dsp->ex[j][ip] = dsp->ex[j][i];
1800
if (dsp->s != NULL) {
1801
dsp->s[ip] = copy_string(dsp->s[ip], dsp->s[i]);
1806
setlength(gno, setno, ip);
1807
return RETURN_SUCCESS;