Set set length on assignment.
[grace.git] / src / set_utils.c
blob7719a42ec7252bffa42f13e4b37171c54c68acea
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-2003 Grace Development Team
8 *
9 * Maintained by Evgeny Stambulchik
12 * All Rights Reserved
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.
36 #include <config.h>
38 #include <stdlib.h>
40 #include "core_utils.h"
41 #include "utils.h"
42 #include "numerics.h"
45 * same as copyset(), but doesn't alter the to set appearance
47 int copysetdata(Quark *psrc, Quark *pdest)
49 Dataset *dsp = set_get_dataset(psrc);
51 return set_set_dataset(pdest, dsp);
55 * get the min/max fields of a set
57 int getsetminmax(Quark **sets, int nsets,
58 double *xmin, double *xmax, double *ymin, double *ymax)
60 int i, first = TRUE;
62 if (nsets < 1 || !sets) {
63 return RETURN_FAILURE;
66 for (i = 0; i < nsets; i++) {
67 Quark *pset = sets[i];
68 if (set_is_drawable(pset)) {
69 double x1, x2, y1, y2;
70 set_get_minmax(pset, &x1, &x2, &y1, &y2);
71 if (first) {
72 *xmin = x1;
73 *xmax = x2;
74 *ymin = y1;
75 *ymax = y2;
76 first = FALSE;
77 } else {
78 *xmin = (x1 < *xmin) ? x1 : *xmin;
79 *xmax = (x2 > *xmax) ? x2 : *xmax;
80 *ymin = (y1 < *ymin) ? y1 : *ymin;
81 *ymax = (y2 > *ymax) ? y2 : *ymax;
86 if (first == FALSE) {
87 return RETURN_SUCCESS;
88 } else {
89 return RETURN_FAILURE;
94 * get the min/max fields of a set with fixed x/y range
96 int getsetminmax_c(Quark **sets, int nsets,
97 double *xmin, double *xmax, double *ymin, double *ymax, int ivec)
99 double vmin_t, vmax_t, *vmin, *vmax, bvmin, bvmax, *vec, *bvec;
100 int i, n;
101 int first = TRUE, hits;
103 if (nsets < 1 || !sets) {
104 return RETURN_FAILURE;
107 if (ivec == 1) {
108 bvmin = *xmin;
109 bvmax = *xmax;
110 vmin = ymin;
111 vmax = ymax;
112 } else {
113 bvmin = *ymin;
114 bvmax = *ymax;
115 vmin = xmin;
116 vmax = xmax;
119 for (i = 0; i < nsets; i++) {
120 Quark *pset = sets[i];
121 if (set_is_drawable(pset)) {
123 if (ivec == 1) {
124 bvec = getx(pset);
125 vec = gety(pset);
126 } else {
127 bvec = gety(pset);
128 vec = getx(pset);
131 n = set_get_length(pset);
132 hits = minmaxrange(bvec, vec, n, bvmin, bvmax, &vmin_t, &vmax_t);
133 if (hits == RETURN_SUCCESS) {
134 if (first) {
135 *vmin = vmin_t;
136 *vmax = vmax_t;
137 first = FALSE;
138 } else {
139 *vmin = MIN2(vmin_t, *vmin);
140 *vmax = MAX2(vmax_t, *vmax);
146 if (first == FALSE) {
147 return RETURN_SUCCESS;
148 } else {
149 return RETURN_FAILURE;
154 int set_point(Quark *pset, int seti, const WPoint *wp)
156 if (!pset) {
157 return RETURN_FAILURE;
159 if (seti >= set_get_length(pset) || seti < 0) {
160 return RETURN_FAILURE;
162 (set_get_col(pset, DATA_X))[seti] = wp->x;
163 (set_get_col(pset, DATA_Y))[seti] = wp->y;
164 quark_dirtystate_set(pset, TRUE);
165 return RETURN_SUCCESS;
168 int get_point(Quark *pset, int seti, WPoint *wp)
170 if (!pset) {
171 return RETURN_FAILURE;
173 if (seti >= set_get_length(pset) || seti < 0) {
174 return RETURN_FAILURE;
176 wp->x = (set_get_col(pset, DATA_X))[seti];
177 wp->y = (set_get_col(pset, DATA_Y))[seti];
178 return RETURN_SUCCESS;
181 int set_point_shift(Quark *pset, int seti, const VVector *vshift)
183 WPoint wp;
184 VPoint vp;
186 if (get_point(pset, seti, &wp) == RETURN_SUCCESS &&
187 Wpoint2Vpoint(pset, &wp, &vp) == RETURN_SUCCESS) {
188 vp.x += vshift->x;
189 vp.y += vshift->y;
190 Vpoint2Wpoint(pset, &vp, &wp);
191 return set_point(pset, seti, &wp);
192 } else {
193 return RETURN_FAILURE;
198 * delete the point pt in setno
200 void del_point(Quark *pset, int pt)
202 ssd_delete_rows(get_parent_ssd(pset), pt, pt);
205 int set_set_colors(Quark *pset, unsigned int color)
207 set *p = set_get_data(pset);
208 GraceApp *gapp = gapp_from_quark(pset);
209 if (!p || !gapp) {
210 return RETURN_FAILURE;
213 if (color < number_of_colors(grace_get_canvas(gapp->grace))) {
214 p->line.line.pen.color = color;
215 p->sym.line.pen.color = color;
216 p->sym.fillpen.color = color;
217 p->errbar.pen.color = color;
219 quark_dirtystate_set(pset, TRUE);
220 return RETURN_SUCCESS;
221 } else {
222 return RETURN_FAILURE;
226 Quark *gapp_set_new(Quark *parent)
228 Quark *pset, *pr;
229 RunTime *rt;
231 pr = get_parent_project(parent);
233 pset = set_new(parent);
235 rt = rt_from_quark(pset);
237 if (!pset || !rt) {
238 return NULL;
241 rt->setcolor++;
242 rt->setcolor %= project_get_ncolors(pr);
243 if (rt->setcolor == 0) {
244 rt->setcolor = 1;
246 set_set_colors(pset, rt->setcolor);
248 return pset;
250 #if 0
252 * sort sets
254 void do_sort(Quark *pset, int sorton, int stype)
256 if (set_is_dataless(pset)) {
257 errmsg("Set not active");
258 return;
259 } else {
260 sortset(pset, sorton, stype);
266 * join several sets together; all but the first set in the list will be killed
268 int join_sets(Quark **sets, int nsets)
270 int i, j, n, ncols, old_length, new_length;
271 Quark *pset, *pset_final;
272 double *x1, *x2;
273 char **s1, **s2;
275 if (nsets < 2) {
276 errmsg("nsets < 2");
277 return RETURN_FAILURE;
280 pset_final = sets[0];
281 ncols = set_get_ncols(pset_final);
282 for (i = 0; i < nsets; i++) {
283 pset = sets[i];
284 if (!pset) {
285 errmsg("Invalid pset in the list");
286 return RETURN_FAILURE;
288 if (set_get_ncols(pset) != ncols) {
289 errmsg("Can't join datasets with different number of cols");
290 return RETURN_FAILURE;
294 new_length = set_get_length(pset_final);
295 for (i = 1; i < nsets; i++) {
296 pset = sets[i];
297 old_length = new_length;
298 new_length += set_get_length(pset);
299 if (set_set_length(pset_final, new_length) != RETURN_SUCCESS) {
300 return RETURN_FAILURE;
302 for (j = 0; j < ncols; j++) {
303 x1 = set_get_col(pset_final, j);
304 x2 = set_get_col(pset, j);
305 for (n = old_length; n < new_length; n++) {
306 x1[n] = x2[n - old_length];
309 s1 = set_get_strings(pset_final);
310 s2 = set_get_strings(pset);
311 if (s1 != NULL && s2 != NULL) {
312 for (n = old_length; n < new_length; n++) {
313 s1[n] = copy_string(s1[n], s2[n - old_length]);
316 quark_free(pset);
319 return RETURN_SUCCESS;
323 * sort a set
325 static double *vptr;
328 * for ascending and descending sorts
331 static int compare_points1(const void *p1, const void *p2)
333 const int *i1, *i2;
334 double a, b;
335 i1 = (const int *)p1;
336 i2 = (const int *)p2;
337 a = vptr[*i1];
338 b = vptr[*i2];
339 if (a < b) {
340 return -1;
342 if (a > b) {
343 return 1;
345 return 0;
348 static int compare_points2(const void *p1, const void *p2)
350 const int *i1, *i2;
351 double a, b;
352 i1 = (const int *)p1;
353 i2 = (const int *)p2;
354 a = vptr[*i1];
355 b = vptr[*i2];
356 if (a > b) {
357 return -1;
359 if (a < b) {
360 return 1;
362 return 0;
365 void sortset(Quark *pset, int sorton, int stype)
367 int i, j, nc, len, *ind;
368 double *x, *xtmp;
369 char **s, **stmp;
371 /* get the vector to sort on */
372 vptr = set_get_col(pset, sorton);
373 if (vptr == NULL) {
374 errmsg("NULL vector in sort, operation cancelled, check set type");
375 return;
378 len = set_get_length(pset);
379 if (len <= 1) {
380 return;
383 /* allocate memory for permuted indices */
384 ind = xmalloc(len*SIZEOF_INT);
385 if (ind == NULL) {
386 return;
388 /* allocate memory for temporary array */
389 xtmp = xmalloc(len*SIZEOF_DOUBLE);
390 if (xtmp == NULL) {
391 xfree(ind);
392 return;
395 s = set_get_strings(pset);
396 if (s != NULL) {
397 stmp = xmalloc(len*sizeof(char *));
398 if (stmp == NULL) {
399 xfree(xtmp);
400 xfree(ind);
402 } else {
403 stmp = NULL;
406 /* initialize indices */
407 for (i = 0; i < len; i++) {
408 ind[i] = i;
411 /* sort */
412 qsort(ind, len, SIZEOF_INT, stype ? compare_points2 : compare_points1);
414 /* straighten things out - done one vector at a time for storage */
416 nc = set_get_ncols(pset);
417 /* loop over the number of columns */
418 for (j = 0; j < nc; j++) {
419 /* get this vector and put into the temporary vector in the right order */
420 x = set_get_col(pset, j);
421 for (i = 0; i < len; i++) {
422 xtmp[i] = x[ind[i]];
425 /* load it back to the set */
426 for (i = 0; i < len; i++) {
427 x[i] = xtmp[i];
431 /* same with strings, if any */
432 if (s != NULL) {
433 for (i = 0; i < len; i++) {
434 stmp[i] = s[ind[i]];
437 for (i = 0; i < len; i++) {
438 s[i] = stmp[i];
442 /* free allocated temporary arrays */
443 xfree(stmp);
444 xfree(xtmp);
445 xfree(ind);
447 quark_dirtystate_set(pset, TRUE);
450 int get_datapoint(Quark *pset, int ind, int *ncols, Datapoint *dpoint)
452 int n, col;
453 double *ex;
454 char **s;
456 n = set_get_length(pset);
457 if (ind < 0 || ind >= n) {
458 return RETURN_FAILURE;
459 } else {
460 *ncols = set_get_ncols(pset);
461 for (col = 0; col < *ncols; col++) {
462 ex = set_get_col(pset, col);
463 dpoint->ex[col] = ex[ind];
465 s = set_get_strings(pset);
466 if (s != NULL) {
467 dpoint->s = s[ind];
468 } else {
469 dpoint->s = NULL;
471 return RETURN_SUCCESS;
476 * split a set into lpart length sets
478 int do_splitsets(Quark *pset, int lpart)
480 int i, j, k, ncols, len, plen, npsets;
481 double *x;
482 char s[256];
483 Quark *gr, *ptmp;
484 Dataset *dsp, *dsptmp;
486 if ((len = set_get_length(pset)) < 2) {
487 errmsg("Set length < 2");
488 return RETURN_FAILURE;
490 if (lpart >= len) {
491 errmsg("Split length >= set length");
492 return RETURN_FAILURE;
494 if (lpart <= 0) {
495 errmsg("Split length <= 0");
496 return RETURN_FAILURE;
499 npsets = (len - 1)/lpart + 1;
501 /* get number of columns in this set */
502 ncols = set_get_ncols(pset);
504 gr = get_parent_graph(pset);
505 dsp = set_get_dataset(pset);
507 /* now load each set */
508 for (i = 0; i < npsets; i++) {
509 plen = MIN2(lpart, len - i*lpart);
510 ptmp = gapp_set_new(gr);
511 if (!ptmp) {
512 errmsg("Can't create new set");
513 return RETURN_FAILURE;
516 dsptmp = set_get_dataset(ptmp);
518 /* set the plot parameters */
519 copy_set_params(pset, ptmp);
521 if (set_set_length(ptmp, plen) != RETURN_SUCCESS) {
522 return RETURN_FAILURE;
524 if (dsp->s) {
525 dataset_enable_scol(dsptmp, TRUE);
528 /* load the data into each column */
529 for (k = 0; k < ncols; k++) {
530 x = set_get_col(ptmp, k);
531 for (j = 0; j < plen; j++) {
532 x[j] = dsp->ex[k][i*lpart + j];
535 if (dsp->s) {
536 for (j = 0; j < plen; j++) {
537 dsptmp->s[j] =
538 copy_string(NULL, dsp->s[i*lpart + j]);
542 sprintf(s, "partition %d of set %s", i + 1, quark_idstr_get(pset));
543 set_set_comment(ptmp, s);
546 /* kill the original set */
547 quark_free(pset);
548 return RETURN_SUCCESS;
550 #endif