/*! * \param[out] dest Output index group (the union of \p a and \p b). * \param[in] a First index group. * \param[in] b Second index group. * * \p a and \p b can have common items. * \p dest can equal \p a or \p b. * * \see gmx_ana_index_merge() */ void gmx_ana_index_union(gmx_ana_index_t *dest, gmx_ana_index_t *a, gmx_ana_index_t *b) { int dsize; int i, j, k; dsize = gmx_ana_index_difference_size(b, a); i = a->isize - 1; j = b->isize - 1; dest->isize = a->isize + dsize; for (k = dest->isize - 1; k >= 0; k--) { if (i < 0 || (j >= 0 && a->index[i] < b->index[j])) { dest->index[k] = b->index[j--]; } else { if (j >= 0 && a->index[i] == b->index[j]) { --j; } dest->index[k] = a->index[i--]; } } }
/*! \brief * Merges a calculation into another calculation such that the new calculation * can be used as a base. * * \param[in,out] base Base calculation to merge to. * \param[in,out] pc Position calculation to merge to \p base. * * After the call, \p base can be used as a base for \p pc (or any calculation * that used it as a base). * It is assumed that any overlap between \p base and \p pc is in complete * blocks, i.e., that the merge is possible. */ static void merge_to_base(gmx_ana_poscalc_t *base, gmx_ana_poscalc_t *pc) { gmx_ana_index_t gp, gb, g; int isize, bnr; int i, j, bi, bj, bo; gmx_ana_index_set(&gp, pc->b.nra, pc->b.a, NULL, 0); gmx_ana_index_set(&gb, base->b.nra, base->b.a, NULL, 0); isize = gmx_ana_index_difference_size(&gp, &gb); if (isize > 0) { gmx_ana_index_clear(&g); gmx_ana_index_reserve(&g, base->b.nra + isize); /* Find the new blocks */ gmx_ana_index_difference(&g, &gp, &gb); /* Count the blocks in g */ i = bi = bnr = 0; while (i < g.isize) { while (pc->b.a[pc->b.index[bi]] != g.index[i]) { ++bi; } i += pc->b.index[bi+1] - pc->b.index[bi]; ++bnr; ++bi; } /* Merge the atoms into a temporary structure */ gmx_ana_index_merge(&g, &gb, &g); /* Merge the blocks */ srenew(base->b.index, base->b.nr + bnr + 1); i = g.isize - 1; bi = base->b.nr - 1; bj = pc->b.nr - 1; bo = base->b.nr + bnr - 1; base->b.index[bo+1] = i + 1; while (bo >= 0) { if (bi < 0 || base->b.a[base->b.index[bi+1]-1] != g.index[i]) { i -= pc->b.index[bj+1] - pc->b.index[bj]; --bj; } else { if (bj >= 0 && pc->b.a[pc->b.index[bj+1]-1] == g.index[i]) { --bj; } i -= base->b.index[bi+1] - base->b.index[bi]; --bi; } base->b.index[bo] = i + 1; --bo; } base->b.nr += bnr; base->b.nalloc_index += bnr; sfree(base->b.a); base->b.nra = g.isize; base->b.a = g.index; base->b.nalloc_a = g.isize; /* Refresh the gmax field */ gmx_ana_index_set(&base->gmax, base->b.nra, base->b.a, NULL, 0); } }