static void place_children_rect(struct lstopo_output *loutput, hwloc_obj_t parent, unsigned kind, unsigned border, unsigned separator, unsigned *width, unsigned *height) { unsigned numsubobjs = 0, obj_totwidth = 0, obj_totheight = 0; unsigned area = 0; unsigned rows, columns; unsigned totwidth, totheight; /* total children array size, without borders */ unsigned rowwidth; /* current row width */ unsigned maxheight; /* max height for current row */ int found, i; hwloc_obj_t child = NULL; int ncstate; /* Total area for subobjects */ while ((child=next_child(loutput, parent, kind, child, &ncstate)) != NULL) { struct lstopo_obj_userdata *clud = child->userdata; numsubobjs++; obj_totwidth += clud->width + separator; obj_totheight += clud->height + separator; area += (clud->width + separator) * (clud->height + separator); } /* Try to find a fitting rectangle */ found = 0; for (rows = (unsigned) (float) floor(sqrt(numsubobjs)); rows >= (unsigned) (float) ceil(pow(numsubobjs, 0.33)) && rows > 1; rows--) { columns = numsubobjs / rows; if (columns > 1 && columns * rows == numsubobjs) { found = 1; break; } } if (!found) { /* Average object size */ unsigned obj_avgwidth = obj_totwidth / numsubobjs; unsigned obj_avgheight = obj_totheight / numsubobjs; /* Ideal total height for spreading that area with RATIO */ float idealtotheight = (float) sqrt(area/RATIO); float under_ratio, over_ratio; /* approximation of number of rows */ rows = (unsigned) (idealtotheight / obj_avgheight); columns = rows ? (numsubobjs + rows - 1) / rows : 1; /* Ratio obtained by underestimation */ under_ratio = (float) (columns * obj_avgwidth) / (rows * obj_avgheight); /* try to overestimate too */ rows++; columns = (numsubobjs + rows - 1) / rows; /* Ratio obtained by overestimation */ over_ratio = (float) (columns * obj_avgwidth) / (rows * obj_avgheight); /* Did we actually preferred underestimation? (good row/column fit or good ratio) */ if (rows > 1 && prefer_ratio(under_ratio, over_ratio)) { rows--; columns = (numsubobjs + rows - 1) / rows; } } rowwidth = 0; maxheight = 0; totwidth = 0; totheight = 0; for(i = 0, child = next_child(loutput, parent, kind, NULL, &ncstate); child; i++, child = next_child(loutput, parent, kind, child, &ncstate)) { struct lstopo_obj_userdata *clud = child->userdata; /* Newline? */ if (i && i%columns == 0) { /* Update total width using new row */ if (rowwidth > totwidth) totwidth = rowwidth; rowwidth = 0; /* Update total height */ totheight += maxheight + separator; maxheight = 0; } /* Add new child */ clud->xrel = rowwidth + border; clud->yrel = totheight + border; rowwidth += clud->width + separator; if (clud->height > maxheight) maxheight = clud->height; } /* Update total width using last row */ if (rowwidth > totwidth) totwidth = rowwidth; /* Remove spurious separator on the right */ totwidth -= separator; /* Update total height using last row */ totheight += maxheight; /* no separator */ *width = totwidth + 2*border; *height = totheight + 2*border; }
static int prefer_vert(struct lstopo_output *loutput, hwloc_obj_t level, unsigned depth, unsigned x, unsigned y, unsigned separator) { hwloc_topology_t topology = loutput->topology; float horiz_ratio, vert_ratio; unsigned textwidth = 0; unsigned mywidth = 0, myheight = 0; unsigned totwidth, *retwidth = &totwidth, totheight, *retheight = &totheight; RECURSE_HORIZ(level, &null_draw_methods, separator, 0); horiz_ratio = (float)totwidth / totheight; RECURSE_VERT(level, &null_draw_methods, separator, 0); vert_ratio = (float)totwidth / totheight; return loutput->force_orient[level->type] == LSTOPO_ORIENT_VERT || (loutput->force_orient[level->type] != LSTOPO_ORIENT_HORIZ && prefer_ratio(vert_ratio, horiz_ratio)); }