Update copyright statements and change license to LGPL
[alexxy/gromacs.git] / src / gmxlib / selection / selelem.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2009, The GROMACS development team,
6  * check out http://www.gromacs.org for more information.
7  * Copyright (c) 2012, by the GROMACS development team, led by
8  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9  * others, as listed in the AUTHORS file in the top-level source
10  * directory and at http://www.gromacs.org.
11  *
12  * GROMACS is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation; either version 2.1
15  * of the License, or (at your option) any later version.
16  *
17  * GROMACS is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GROMACS; if not, see
24  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
26  *
27  * If you want to redistribute modifications to GROMACS, please
28  * consider that scientific software is very special. Version
29  * control is crucial - bugs must be traceable. We will be happy to
30  * consider code for inclusion in the official distribution, but
31  * derived work must not be called official GROMACS. Details are found
32  * in the README & COPYING files - if they are missing, get the
33  * official version at http://www.gromacs.org.
34  *
35  * To help us fund GROMACS development, we humbly ask that you cite
36  * the research papers on the package. Check out http://www.gromacs.org.
37  */
38 /*! \internal \file
39  * \brief Implementation of functions in selelem.h.
40  */
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif
44
45 #include <smalloc.h>
46 #include <gmx_fatal.h>
47
48 #include <indexutil.h>
49 #include <poscalc.h>
50 #include <position.h>
51 #include <selmethod.h>
52
53 #include "keywords.h"
54 #include "mempool.h"
55 #include "selelem.h"
56
57 /*!
58  * \param[in] sel Selection for which the string is requested
59  * \returns   Pointer to a string that corresponds to \p sel->type.
60  *
61  * The return value points to a string constant and should not be \p free'd.
62  * 
63  * The function returns NULL if \p sel->type is not one of the valid values.
64  */
65 const char *
66 _gmx_selelem_type_str(t_selelem *sel)
67 {
68     switch (sel->type)
69     {
70         case SEL_CONST:      return "CONST";
71         case SEL_EXPRESSION: return "EXPR";
72         case SEL_BOOLEAN:    return "BOOL";
73         case SEL_ARITHMETIC: return "ARITH";
74         case SEL_ROOT:       return "ROOT";
75         case SEL_SUBEXPR:    return "SUBEXPR";
76         case SEL_SUBEXPRREF: return "REF";
77         case SEL_MODIFIER:   return "MODIFIER";
78     }
79     return NULL;
80 }
81
82 /*!
83  * \param[in] val Value structore for which the string is requested.
84  * \returns   Pointer to a string that corresponds to \p val->type,
85  *   NULL if the type value is invalid.
86  *
87  * The return value points to a string constant and should not be \p free'd.
88  */
89 const char *
90 _gmx_sel_value_type_str(gmx_ana_selvalue_t *val)
91 {
92     switch (val->type)
93     {
94         case NO_VALUE:       return "NONE";
95         case INT_VALUE:      return "INT";
96         case REAL_VALUE:     return "REAL";
97         case STR_VALUE:      return "STR";
98         case POS_VALUE:      return "VEC";
99         case GROUP_VALUE:    return "GROUP";
100     }
101     return NULL;
102 }
103
104 /*! \copydoc _gmx_selelem_type_str() */
105 const char *
106 _gmx_selelem_gmx_boolean_type_str(t_selelem *sel)
107 {
108     switch (sel->u.boolt)
109     {
110         case BOOL_NOT:  return "NOT"; break;
111         case BOOL_AND:  return "AND"; break;
112         case BOOL_OR:   return "OR";  break;
113         case BOOL_XOR:  return "XOR"; break;
114     }
115     return NULL;
116 }
117
118 /*!
119  * \param[in] type Type of selection element to allocate.
120  * \returns   Pointer to the newly allocated and initialized element.
121  *
122  * \c t_selelem::type is set to \p type,
123  * \c t_selelem::v::type is set to \ref GROUP_VALUE for gmx_boolean and comparison
124  * expressions and \ref NO_VALUE for others,
125  * \ref SEL_ALLOCVAL is set for non-root elements (\ref SEL_ALLOCDATA is also
126  * set for \ref SEL_BOOLEAN elements),
127  * and \c t_selelem::refcount is set to one.
128  * All the pointers are set to NULL.
129  */
130 t_selelem *
131 _gmx_selelem_create(e_selelem_t type)
132 {
133     t_selelem *sel;
134
135     snew(sel, 1);
136     sel->name       = NULL;
137     sel->type       = type;
138     sel->flags      = (type != SEL_ROOT) ? SEL_ALLOCVAL : 0;
139     if (type == SEL_BOOLEAN)
140     {
141         sel->v.type = GROUP_VALUE;
142         sel->flags |= SEL_ALLOCDATA;
143     }
144     else
145     {
146         sel->v.type = NO_VALUE;
147     }
148     _gmx_selvalue_clear(&sel->v);
149     sel->evaluate   = NULL;
150     sel->mempool    = NULL;
151     sel->child      = NULL;
152     sel->next       = NULL;
153     sel->refcount   = 1;
154
155     return sel;
156 }
157
158 /*!
159  * \param[in,out] sel   Selection element to set the type for.
160  * \param[in]     vtype Value type for the selection element.
161  * \returns       0 on success, EINVAL if the value type is invalid.
162  *
163  * If the new type is \ref GROUP_VALUE or \ref POS_VALUE, the
164  * \ref SEL_ALLOCDATA flag is also set.
165  *
166  * This function should only be called at most once for each element,
167  * preferably right after calling _gmx_selelem_create().
168  */
169 int
170 _gmx_selelem_set_vtype(t_selelem *sel, e_selvalue_t vtype)
171 {
172     if (sel->type == SEL_BOOLEAN && vtype != GROUP_VALUE)
173     {
174         gmx_bug("internal error");
175         return EINVAL;
176     }
177     if (sel->v.type != NO_VALUE && vtype != sel->v.type)
178     {
179         gmx_call("_gmx_selelem_set_vtype() called more than once");
180         return EINVAL;
181     }
182     sel->v.type = vtype;
183     if (vtype == GROUP_VALUE || vtype == POS_VALUE)
184     {
185         sel->flags |= SEL_ALLOCDATA;
186     }
187     return 0;
188 }
189
190 /*!
191  * \param[in,out] sel   Selection element to reserve.
192  * \param[in]     count Number of values to reserve memory for.
193  * \returns       0 on success or if no memory pool, non-zero on error.
194  *
195  * Reserves memory for the values of \p sel from the \p sel->mempool
196  * memory pool. If no memory pool is set, nothing is done.
197  */
198 int
199 _gmx_selelem_mempool_reserve(t_selelem *sel, int count)
200 {
201     int rc = 0;
202
203     if (!sel->mempool)
204     {
205         return 0;
206     }
207     switch (sel->v.type)
208     {
209         case INT_VALUE:
210             rc = _gmx_sel_mempool_alloc(sel->mempool, (void **)&sel->v.u.i,
211                                         sizeof(*sel->v.u.i)*count);
212             break;
213
214         case REAL_VALUE:
215             rc = _gmx_sel_mempool_alloc(sel->mempool, (void **)&sel->v.u.r,
216                                         sizeof(*sel->v.u.r)*count);
217             break;
218
219         case GROUP_VALUE:
220             rc = _gmx_sel_mempool_alloc_group(sel->mempool, sel->v.u.g, count);
221             break;
222
223         default:
224             gmx_incons("mem pooling not implemented for requested type");
225             return -1;
226     }
227     return rc;
228 }
229
230 /*!
231  * \param[in,out] sel   Selection element to release.
232  *
233  * Releases the memory allocated for the values of \p sel from the
234  * \p sel->mempool memory pool. If no memory pool is set, nothing is done.
235  */
236 void
237 _gmx_selelem_mempool_release(t_selelem *sel)
238 {
239     if (!sel->mempool)
240     {
241         return;
242     }
243     switch (sel->v.type)
244     {
245         case INT_VALUE:
246         case REAL_VALUE:
247             _gmx_sel_mempool_free(sel->mempool, sel->v.u.ptr);
248             _gmx_selvalue_setstore(&sel->v, NULL);
249             break;
250
251         case GROUP_VALUE:
252             if (sel->v.u.g)
253             {
254                 _gmx_sel_mempool_free_group(sel->mempool, sel->v.u.g);
255             }
256             break;
257
258         default:
259             gmx_incons("mem pooling not implemented for requested type");
260             break;
261     }
262 }
263
264 /*!
265  * \param[in] sel Selection to free.
266  */
267 void
268 _gmx_selelem_free_values(t_selelem *sel)
269 {
270     int   i, n;
271
272     _gmx_selelem_mempool_release(sel);
273     if ((sel->flags & SEL_ALLOCDATA) && sel->v.u.ptr)
274     {
275         /* The number of position/group structures is constant, so the
276          * backup of using sel->v.nr should work for them.
277          * For strings, we report an error if we don't know the allocation
278          * size here. */
279         n = (sel->v.nalloc > 0) ? sel->v.nalloc : sel->v.nr;
280         switch (sel->v.type)
281         {
282             case STR_VALUE:
283                 if (sel->v.nalloc == 0)
284                 {
285                     gmx_bug("SEL_ALLOCDATA should only be set for allocated STR_VALUE values");
286                     break;
287                 }
288                 for (i = 0; i < n; ++i)
289                 {
290                     sfree(sel->v.u.s[i]);
291                 }
292                 break;
293             case POS_VALUE:
294                 for (i = 0; i < n; ++i)
295                 {
296                     gmx_ana_pos_deinit(&sel->v.u.p[i]);
297                 }
298                 break;
299             case GROUP_VALUE:
300                 for (i = 0; i < n; ++i)
301                 {
302                     gmx_ana_index_deinit(&sel->v.u.g[i]);
303                 }
304                 break;
305             default: /* No special handling for other types */
306                 break;
307         }
308     }
309     if (sel->flags & SEL_ALLOCVAL)
310     {
311         sfree(sel->v.u.ptr);
312     }
313     _gmx_selvalue_setstore(&sel->v, NULL);
314     if (sel->type == SEL_SUBEXPRREF && sel->u.param)
315     {
316         sel->u.param->val.u.ptr = NULL;
317     }
318 }
319
320 /*!
321  * \param[in] method Method to free.
322  * \param[in] mdata  Method data to free.
323  */
324 void
325 _gmx_selelem_free_method(gmx_ana_selmethod_t *method, void *mdata)
326 {
327     sel_freefunc free_func = NULL;
328
329     /* Save the pointer to the free function. */
330     if (method && method->free)
331     {
332         free_func = method->free;
333     }
334
335     /* Free the method itself.
336      * Has to be done before freeing the method data, because parameter
337      * values are typically stored in the method data, and here we may
338      * access them. */
339     if (method)
340     {
341         int  i, j;
342
343         /* Free the memory allocated for the parameters that are not managed
344          * by the selection method itself. */
345         for (i = 0; i < method->nparams; ++i)
346         {
347             gmx_ana_selparam_t *param = &method->param[i];
348
349             if (param->val.u.ptr)
350             {
351                 if (param->val.type == GROUP_VALUE)
352                 {
353                     for (j = 0; j < param->val.nr; ++j)
354                     {
355                         gmx_ana_index_deinit(&param->val.u.g[j]);
356                     }
357                 }
358                 else if (param->val.type == POS_VALUE)
359                 {
360                     for (j = 0; j < param->val.nr; ++j)
361                     {
362                         gmx_ana_pos_deinit(&param->val.u.p[j]);
363                     }
364                 }
365
366                 if (param->val.nalloc > 0)
367                 {
368                     sfree(param->val.u.ptr);
369                 }
370             }
371         }
372         sfree(method->param);
373         sfree(method);
374     }
375     /* Free method data. */
376     if (mdata)
377     {
378         if (free_func)
379         {
380             free_func(mdata);
381         }
382         sfree(mdata);
383     }
384 }
385
386 /*!
387  * \param[in] sel Selection to free.
388  */
389 void
390 _gmx_selelem_free_exprdata(t_selelem *sel)
391 {
392     if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
393     {
394         _gmx_selelem_free_method(sel->u.expr.method, sel->u.expr.mdata);
395         sel->u.expr.mdata = NULL;
396         sel->u.expr.method = NULL;
397         /* Free position data */
398         if (sel->u.expr.pos)
399         {
400             gmx_ana_pos_free(sel->u.expr.pos);
401             sel->u.expr.pos = NULL;
402         }
403         /* Free position calculation data */
404         if (sel->u.expr.pc)
405         {
406             gmx_ana_poscalc_free(sel->u.expr.pc);
407             sel->u.expr.pc = NULL;
408         }
409     }
410     if (sel->type == SEL_ARITHMETIC)
411     {
412         sfree(sel->u.arith.opstr);
413         sel->u.arith.opstr = NULL;
414     }
415     if (sel->type == SEL_SUBEXPR || sel->type == SEL_ROOT
416         || (sel->type == SEL_CONST && sel->v.type == GROUP_VALUE))
417     {
418         gmx_ana_index_deinit(&sel->u.cgrp);
419     }
420 }
421
422 /*!
423  * \param[in] sel Selection to free.
424  *
425  * Decrements \ref t_selelem::refcount "sel->refcount" and frees the
426  * memory allocated for \p sel and all its children if the reference count
427  * reaches zero.
428  */
429 void
430 _gmx_selelem_free(t_selelem *sel)
431 {
432     /* Decrement the reference counter and do nothing if references remain */
433     sel->refcount--;
434     if (sel->refcount > 0)
435     {
436         return;
437     }
438
439     /* Free the children.
440      * Must be done before freeing other data, because the children may hold
441      * references to data in this element. */
442     _gmx_selelem_free_chain(sel->child);
443
444     /* Free value storage */
445     _gmx_selelem_free_values(sel);
446
447     /* Free other storage */
448     _gmx_selelem_free_exprdata(sel);
449
450     /* Free temporary compiler data if present */
451     _gmx_selelem_free_compiler_data(sel);
452
453     sfree(sel);
454 }
455
456 /*!
457  * \param[in] first First selection to free.
458  *
459  * Frees \p first and all selections accessible through the
460  * \ref t_selelem::next "first->next" pointer.
461  */
462 void
463 _gmx_selelem_free_chain(t_selelem *first)
464 {
465     t_selelem *child, *prev;
466
467     child = first;
468     while (child)
469     {
470         prev = child;
471         child = child->next;
472         _gmx_selelem_free(prev);
473     }
474 }
475
476 /*!
477  * \param[in] fp      File handle to receive the output.
478  * \param[in] sel     Root of the selection subtree to print.
479  * \param[in] bValues If TRUE, the evaluated values of selection elements
480  *   are printed as well.
481  * \param[in] level   Indentation level, starting from zero.
482  */
483 void
484 _gmx_selelem_print_tree(FILE *fp, t_selelem *sel, gmx_bool bValues, int level)
485 {
486     t_selelem *child;
487     int          i;
488
489     fprintf(fp, "%*c %s %s", level*2+1, '*',
490             _gmx_selelem_type_str(sel), _gmx_sel_value_type_str(&sel->v));
491     if (sel->name)
492     {
493         fprintf(fp, " \"%s\"", sel->name);
494     }
495     fprintf(fp, " flg=");
496     if (sel->flags & SEL_FLAGSSET)
497     {
498         fprintf(fp, "s");
499     }
500     if (sel->flags & SEL_SINGLEVAL)
501     {
502         fprintf(fp, "S");
503     }
504     if (sel->flags & SEL_ATOMVAL)
505     {
506         fprintf(fp, "A");
507     }
508     if (sel->flags & SEL_VARNUMVAL)
509     {
510         fprintf(fp, "V");
511     }
512     if (sel->flags & SEL_DYNAMIC)
513     {
514         fprintf(fp, "D");
515     }
516     if (!(sel->flags & SEL_VALFLAGMASK))
517     {
518         fprintf(fp, "0");
519     }
520     if (sel->mempool)
521     {
522         fprintf(fp, "P");
523     }
524     if (sel->type == SEL_CONST)
525     {
526         if (sel->v.type == INT_VALUE)
527         {
528             fprintf(fp, " %d", sel->v.u.i[0]);
529         }
530         else if (sel->v.type == REAL_VALUE)
531         {
532             fprintf(fp, " %f", sel->v.u.r[0]);
533         }
534         else if (sel->v.type == GROUP_VALUE)
535         {
536             gmx_ana_index_t *g = sel->v.u.g;
537             if (!g || g->isize == 0)
538                 g = &sel->u.cgrp;
539             fprintf(fp, " (%d atoms)", g->isize);
540         }
541     }
542     else if (sel->type == SEL_BOOLEAN)
543     {
544         fprintf(fp, " %s", _gmx_selelem_gmx_boolean_type_str(sel));
545     }
546     else if (sel->type == SEL_EXPRESSION
547              && sel->u.expr.method->name == sm_compare.name)
548     {
549         _gmx_selelem_print_compare_info(fp, sel->u.expr.mdata);
550     }
551     if (sel->evaluate)
552     {
553         fprintf(fp, " eval=");
554         _gmx_sel_print_evalfunc_name(fp, sel->evaluate);
555     }
556     if (sel->refcount > 1)
557     {
558         fprintf(fp, " refc=%d", sel->refcount);
559     }
560     if (!(sel->flags & SEL_ALLOCVAL))
561     {
562         fprintf(fp, " (ext. output)");
563     }
564     fprintf(fp, "\n");
565
566     if ((sel->type == SEL_CONST && sel->v.type == GROUP_VALUE) || sel->type == SEL_ROOT)
567     {
568         gmx_ana_index_t *g = sel->v.u.g;
569         if (!g || g->isize == 0 || sel->evaluate != NULL)
570         {
571             g = &sel->u.cgrp;
572         }
573         if (g->isize < 0)
574         {
575             fprintf(fp, "%*c group: (null)\n", level*2+1, ' ');
576         }
577         else if (g->isize > 0)
578         {
579             fprintf(fp, "%*c group:", level*2+1, ' ');
580             if (g->isize <= 20)
581             {
582                 for (i = 0; i < g->isize; ++i)
583                 {
584                     fprintf(fp, " %d", g->index[i] + 1);
585                 }
586             }
587             else
588             {
589                 fprintf(fp, " %d atoms", g->isize);
590             }
591             fprintf(fp, "\n");
592         }
593     }
594     else if (sel->type == SEL_EXPRESSION)
595     {
596         if (sel->u.expr.pc)
597         {
598             fprintf(fp, "%*c COM", level*2+3, '*');
599             fprintf(fp, "\n");
600         }
601     }
602
603     if (sel->cdata)
604     {
605         _gmx_selelem_print_compiler_info(fp, sel, level);
606     }
607
608     if (bValues && sel->type != SEL_CONST && sel->type != SEL_ROOT && sel->v.u.ptr)
609     {
610         fprintf(fp, "%*c value: ", level*2+1, ' ');
611         switch (sel->v.type)
612         {
613             case POS_VALUE:
614                 /* In normal use, the pointer should never be NULL, but it's
615                  * useful to have the check for debugging to avoid accidental
616                  * segfaults when printing the selection tree. */
617                 if (sel->v.u.p->x)
618                 {
619                     fprintf(fp, "(%f, %f, %f)",
620                             sel->v.u.p->x[0][XX], sel->v.u.p->x[0][YY],
621                             sel->v.u.p->x[0][ZZ]);
622                 }
623                 else
624                 {
625                     fprintf(fp, "(null)");
626                 }
627                 break;
628             case GROUP_VALUE:
629                 fprintf(fp, "%d atoms", sel->v.u.g->isize);
630                 if (sel->v.u.g->isize < 20)
631                 {
632                     if (sel->v.u.g->isize > 0)
633                     {
634                         fprintf(fp, ":");
635                     }
636                     for (i = 0; i < sel->v.u.g->isize; ++i)
637                     {
638                         fprintf(fp, " %d", sel->v.u.g->index[i] + 1);
639                     }
640                 }
641                 break;
642             default:
643                 fprintf(fp, "???");
644                 break;
645         }
646         fprintf(fp, "\n");
647     }
648
649     /* Print the subexpressions with one more level of indentation */
650     child = sel->child;
651     while (child)
652     {
653         if (!(sel->type == SEL_SUBEXPRREF && child->type == SEL_SUBEXPR))
654         {
655             _gmx_selelem_print_tree(fp, child, bValues, level+1);
656         }
657         child = child->next;
658     }
659 }
660
661 /*!
662  * \param[in] root Root of the subtree to query.
663  * \returns TRUE if \p root or any any of its elements require topology
664  *   information, FALSE otherwise.
665  */
666 gmx_bool
667 _gmx_selelem_requires_top(t_selelem *root)
668 {
669     t_selelem *child;
670
671     if (root->type == SEL_EXPRESSION || root->type == SEL_MODIFIER)
672     {
673         if (root->u.expr.method && (root->u.expr.method->flags & SMETH_REQTOP))
674         {
675             return TRUE;
676         }
677         if (root->u.expr.pc && gmx_ana_poscalc_requires_top(root->u.expr.pc))
678         {
679             return TRUE;
680         }
681     }
682     child = root->child;
683     while (child)
684     {
685         if (_gmx_selelem_requires_top(child))
686         {
687             return TRUE;
688         }
689         child = child->next;
690     }
691     return FALSE;
692 }