From 2133d8675e828cca541b46ff0a51a8885f853def Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 4 Mar 2019 17:23:53 +0100 Subject: mg2d: refactor levels allocation This should simplify future improvements. --- mg2d.c | 69 ++++++++++++++++++++++++++++++++---------------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/mg2d.c b/mg2d.c index eb3973b..5f5b73e 100644 --- a/mg2d.c +++ b/mg2d.c @@ -622,45 +622,42 @@ static int log2i(int n) static int mg_levels_alloc(MG2DContext *ctx, size_t domain_size) { MG2DInternal *priv = ctx->priv; - MG2DLevel *cur, **last; - size_t last_size; - unsigned int last_depth; - - priv->root = mg_level_alloc(EGS_SOLVER_RELAXATION, domain_size); - if (!priv->root) - return -ENOMEM; - - // choose the domain size for the first child - // the children all have sizes 2**n + 1 - // but we skip the closest lower one if it is too close - if (domain_size <= 2) - goto finish; - domain_size = (1 << log2i(domain_size - 2)) + 1; - if ((double)priv->root->solver->domain_size[0] / domain_size < 1.5) - domain_size = (domain_size >> 1) + 1; - - cur = priv->root; - for (int i = 0; i < LEVELS_MAX && domain_size > 4; i++) { - cur->child = mg_level_alloc(EGS_SOLVER_RELAXATION, domain_size); - if (!cur->child) + + MG2DLevel **dst; + enum EGSType next_type; + size_t next_size; + + dst = &priv->root; + next_size = domain_size; + + for (int depth = 0; depth < LEVELS_MAX; depth++) { + enum EGSType cur_type; + size_t cur_size = next_size; + + // choose the domain size for the next child + // the children all have sizes 2**n + 1 + // but on the top level we skip the closest lower one if it is too close + if (depth == 0) { + next_size = (1 << log2i(cur_size - 2)) + 1; + if ((double)cur_size / next_size < 1.5) + next_size = (next_size >> 1) + 1; + } else + next_size = (cur_size >> 1) + 1; + + cur_type = (depth == LEVELS_MAX - 1 || cur_size < 9) ? EGS_SOLVER_EXACT : EGS_SOLVER_RELAXATION; + + *dst = mg_level_alloc(cur_type, cur_size); + if (!*dst) return -ENOMEM; - cur->child->depth = i + 1; + (*dst)->depth = depth; - cur = cur->child; - domain_size = (domain_size >> 1) + 1; - } + if (cur_type == EGS_SOLVER_EXACT) + break; + if (next_size <= 4) + break; -finish: - last = &priv->root; - while ((*last)->child) - last = &((*last)->child); - last_size = (*last)->solver->domain_size[0]; - last_depth = (*last)->depth; - mg_level_free(last); - *last = mg_level_alloc(EGS_SOLVER_EXACT, last_size); - if (!*last) - return -ENOMEM; - (*last)->depth = last_depth; + dst = &(*dst)->child; + } return 0; } -- cgit v1.2.3