summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2019-03-04 17:23:53 +0100
committerAnton Khirnov <anton@khirnov.net>2019-03-04 17:24:06 +0100
commit2133d8675e828cca541b46ff0a51a8885f853def (patch)
treee2f8997c9dd30c6e46b4c39a68ca027567af5522
parentf2cd89401721d1f547a54ff6619d0dc9c8c9e863 (diff)
mg2d: refactor levels allocation
This should simplify future improvements.
-rw-r--r--mg2d.c69
1 files 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;
}