diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..549dce6a --- /dev/null +++ b/.clang-format @@ -0,0 +1,76 @@ +--- +# Configuration for clang-format to match the existing C/C++ code style +Language: Cpp +BasedOnStyle: LLVM + +# Indentation +IndentWidth: 4 +TabWidth: 4 +UseTab: Never +ContinuationIndentWidth: 4 + +# Column limit +ColumnLimit: 80 + +# Brace style +BreakBeforeBraces: Linux + +# Function style - return type on its own line +AlwaysBreakAfterReturnType: TopLevelDefinitions + +# Pointer and reference alignment - space on both sides is most common +PointerAlignment: Middle +DerivePointerAlignment: false + +# Space style +SpaceAfterCStyleCast: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + BeforeNonEmptyParentheses: false + +# Preprocessor indentation - AfterHash to allow spaces after # for nesting +IndentPPDirectives: AfterHash +PPIndentWidth: 1 + +# Comment alignment +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +SpacesBeforeTrailingComments: 1 + +# Line breaks +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLoopsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false + +# Includes +SortIncludes: false + +# Bin packing +BinPackParameters: true +BinPackArguments: true +AllowAllParametersOfDeclarationOnNextLine: true + +# Alignment +AlignConsecutiveMacros: + Enabled: false +AlignConsecutiveAssignments: + Enabled: false +AlignConsecutiveDeclarations: + Enabled: false + +# Macro formatting - don't reformat multi-line macros +AlignEscapedNewlines: Left + +# Other +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 2 +ReflowComments: false diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c1095845..22e65225 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -62,3 +62,10 @@ repos: rev: v1.0.0 hooks: - id: sphinx-lint + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v19.1.7 + hooks: + - id: clang-format + types_or: [c, c++] + files: ^c/ + exclude: ^c/(pow_int\.h|avl\.(c|h)|mt19937/.*) diff --git a/DEVEL-README.md b/DEVEL-README.md index 3c9e93c9..1924f694 100644 --- a/DEVEL-README.md +++ b/DEVEL-README.md @@ -37,3 +37,26 @@ How to extend the R API ======================= Extending the R API requires adding a C wrapper function that converts from R types to C types and export that C function to R. See [`Rmoocore.c`](https://github.com/multi-objective/moocore/blob/main/r/src/Rmoocore.c) and [`init.h`](https://github.com/multi-objective/moocore/blob/main/r/src/init.h) + + +Code Formatting +=============== + +C/C++ Code +---------- + +C/C++ code in the `c/` directory is automatically formatted using `clang-format` via pre-commit hooks. + +The formatting style is configured in `.clang-format` and aims to match the existing code style: +- 4-space indentation +- K&R style (function return type on separate line) +- 80-character column limit +- Space on both sides of pointer declarations (e.g., `type * name`) + +To manually format C/C++ files: + +```bash +clang-format -i c/*.c c/*.h +``` + +The pre-commit hook will automatically format C/C++ files when you commit changes. diff --git a/c/Hypervolume_MEX.c b/c/Hypervolume_MEX.c index 2a8a51cc..6e730e10 100644 --- a/c/Hypervolume_MEX.c +++ b/c/Hypervolume_MEX.c @@ -117,12 +117,12 @@ #include #include -# include "hv.h" +#include "hv.h" #include "mex.h" #if !defined(TRUE) || !defined(FALSE) -#define TRUE 1 -#define FALSE 0 +# define TRUE 1 +# define FALSE 0 #endif @@ -130,146 +130,154 @@ /*#define DEBUG*/ -void version(void) +void +version(void) { - printf( -"\nCopyright (C) 2009" -"\nMEX Interface created by Guillaume Jacquenot" -"\n(guillaume.jacquenot@gmail.com)" -"\n" -"\nbased on previous hypervolume software" -"\n" -"\nCopyright (C) 2006" -"\nCarlos M. Fonseca, Manuel Lopez-Ibanez and Luis Paquete\n" -"\n" -"This is free software, and you are welcome to redistribute it under certain\n" -"conditions. See the GNU General Public License for details. There is NO \n" -"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" -"\n" ); + printf("\nCopyright (C) 2009" + "\nMEX Interface created by Guillaume Jacquenot" + "\n(guillaume.jacquenot@gmail.com)" + "\n" + "\nbased on previous hypervolume software" + "\n" + "\nCopyright (C) 2006" + "\nCarlos M. Fonseca, Manuel Lopez-Ibanez and Luis Paquete\n" + "\n" + "This is free software, and you are welcome to redistribute it " + "under certain\n" + "conditions. See the GNU General Public License for details. There " + "is NO \n" + "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " + "PURPOSE.\n" + "\n"); } - -void description(void) +void +description(void) { printf( -"\nThis program implements a recursive, dimension-sweep algorithm for " -"\ncomputing the hypervolume indicator of the quality of a set of n " -"\nnon-dominated points in d dimensions. It also incorporates a " -"\nrecent result for the three-dimensional special case. The proposed " -"\nalgorithm achieves O(n^{d-2} log n) time and linear space complexity " -"\nin the worst-case, but experimental results show that the pruning " -"\ntechniques used may reduce the time complexity even further. " -"\n " -"\nRelevant literature: " -"\n " -"\n[1] Carlos M. Fonseca, Luís Paquete, and Manuel López-Ibáñez. An " -"\n improved dimension-sweep algorithm for the hypervolume " -"\n indicator. In IEEE Congress on Evolutionary Computation, pages " -"\n 1157-1163, Vancouver, Canada, July 2006. " -"\n[2] Nicola Beume, Carlos M. Fonseca, Manuel Lopez-Ibanez, Luis " -"\n Paquete, and J. Vahrenhold. On the complexity of computing the " -"\n hypervolume indicator. IEEE Transactions on Evolutionary " -"\n Computation, 13(5):1075–1082, 2009. " -"\n" -"\n" -"\n\n\n "); + "\nThis program implements a recursive, dimension-sweep algorithm for " + "\ncomputing the hypervolume indicator of the quality of a set of n " + "\nnon-dominated points in d dimensions. It also incorporates a " + "\nrecent result for the three-dimensional special case. The proposed " + "\nalgorithm achieves O(n^{d-2} log n) time and linear space " + "complexity " + "\nin the worst-case, but experimental results show that the pruning " + "\ntechniques used may reduce the time complexity even further. " + "\n " + "\nRelevant literature: " + "\n " + "\n[1] Carlos M. Fonseca, Luís Paquete, and Manuel López-Ibáñez. An " + "\n improved dimension-sweep algorithm for the hypervolume " + "\n indicator. In IEEE Congress on Evolutionary Computation, pages " + "\n 1157-1163, Vancouver, Canada, July 2006. " + "\n[2] Nicola Beume, Carlos M. Fonseca, Manuel Lopez-Ibanez, Luis " + "\n Paquete, and J. Vahrenhold. On the complexity of computing the " + "\n hypervolume indicator. IEEE Transactions on Evolutionary " + "\n Computation, 13(5):1075–1082, 2009. " + "\n" + "\n" + "\n\n\n "); } -void help(void) +void +help(void) { - mexPrintf("\nHypervolume computation"); - mexPrintf("\nThis function computes the hypervolume value for a set of points in d-dimension."); - mexPrintf("\nAll objectives are considered to be minimized."); - mexPrintf("\nPoints don't have to non-dominated points."); - mexPrintf("\nThis function takes two arguments, the second is optional"); - mexPrintf("\n\tThe first one is the matrix of points"); - mexPrintf("\n\t\tIt contains n rows for the different points"); - mexPrintf("\n\t\tand m columns for the dimension of the points."); - mexPrintf("\n\tThe second argument is a m-dimension vector containing "); - mexPrintf("\n\tthe coordinate of the reference point"); - mexPrintf("\n\tIf not provided, the evaluated Nadir point taken as the maximum"); - mexPrintf("\n\tvalue on all objectives is considered as the reference point."); - mexPrintf("\nThe function is called like this:"); - mexPrintf("\n\tHV = Hypervolume_MEX(Objectives);"); - mexPrintf("\n\tHV = Hypervolume_MEX(Objectives,Reference_point);"); - mexPrintf("\n\n"); - description(); - version(); - mexPrintf("%%2D Example;\n"); - mexPrintf("\tn = 200;\n"); - mexPrintf("\ttheta = linspace(-3*pi/2,-pi,n)';\n"); - mexPrintf("\tFP = [1+cos(theta) 1-sin(theta)];\n"); - mexPrintf("\tRes = Hypervolume_MEX(FP,[1 1])\n"); - mexPrintf("\tdisp('This result tends to pi/4=0.7854 when n goes to infinity');\n\n"); - mexPrintf("%%3D Example;\n"); - mexPrintf("\tn = 50;\n"); - mexPrintf("\t[X,Y] = meshgrid([0:1/n:1]);\n"); - mexPrintf("\tX=X(:);Y=Y(:);\n"); - mexPrintf("\tR = X.^2+Y.^2;\n"); - mexPrintf("\tInd = R<=1;\n"); - mexPrintf("\tXX=X(Ind);\n"); - mexPrintf("\tYY=Y(Ind);\n"); - mexPrintf("\tZZ=sqrt(1-R(Ind));\n"); - mexPrintf("\tRes = Hypervolume_MEX([XX,YY,ZZ],[1 1 1])\n"); - mexPrintf("\tdisp('This result tends to 1-pi/6=0.4764 when n goes to infinity');\n"); - mexPrintf("\tscatter3(XX,YY,ZZ);\n"); + mexPrintf("\nHypervolume computation"); + mexPrintf("\nThis function computes the hypervolume value for a set of " + "points in d-dimension."); + mexPrintf("\nAll objectives are considered to be minimized."); + mexPrintf("\nPoints don't have to non-dominated points."); + mexPrintf("\nThis function takes two arguments, the second is optional"); + mexPrintf("\n\tThe first one is the matrix of points"); + mexPrintf("\n\t\tIt contains n rows for the different points"); + mexPrintf("\n\t\tand m columns for the dimension of the points."); + mexPrintf("\n\tThe second argument is a m-dimension vector containing "); + mexPrintf("\n\tthe coordinate of the reference point"); + mexPrintf( + "\n\tIf not provided, the evaluated Nadir point taken as the maximum"); + mexPrintf( + "\n\tvalue on all objectives is considered as the reference point."); + mexPrintf("\nThe function is called like this:"); + mexPrintf("\n\tHV = Hypervolume_MEX(Objectives);"); + mexPrintf("\n\tHV = Hypervolume_MEX(Objectives,Reference_point);"); + mexPrintf("\n\n"); + description(); + version(); + mexPrintf("%%2D Example;\n"); + mexPrintf("\tn = 200;\n"); + mexPrintf("\ttheta = linspace(-3*pi/2,-pi,n)';\n"); + mexPrintf("\tFP = [1+cos(theta) 1-sin(theta)];\n"); + mexPrintf("\tRes = Hypervolume_MEX(FP,[1 1])\n"); + mexPrintf("\tdisp('This result tends to pi/4=0.7854 when n goes to " + "infinity');\n\n"); + mexPrintf("%%3D Example;\n"); + mexPrintf("\tn = 50;\n"); + mexPrintf("\t[X,Y] = meshgrid([0:1/n:1]);\n"); + mexPrintf("\tX=X(:);Y=Y(:);\n"); + mexPrintf("\tR = X.^2+Y.^2;\n"); + mexPrintf("\tInd = R<=1;\n"); + mexPrintf("\tXX=X(Ind);\n"); + mexPrintf("\tYY=Y(Ind);\n"); + mexPrintf("\tZZ=sqrt(1-R(Ind));\n"); + mexPrintf("\tRes = Hypervolume_MEX([XX,YY,ZZ],[1 1 1])\n"); + mexPrintf("\tdisp('This result tends to 1-pi/6=0.4764 when n goes to " + "infinity');\n"); + mexPrintf("\tscatter3(XX,YY,ZZ);\n"); } -double * data_maximum(double *data, int nobj, int rows) +double * +data_maximum(double * data, int nobj, int rows) { - double *vector; + double * vector; int n, r, k; - vector = MALLOC(nobj*sizeof(double)); + vector = MALLOC(nobj * sizeof(double)); - for (k = 0; k < nobj; k++) - vector[k] = data[k]; + for (k = 0; k < nobj; k++) vector[k] = data[k]; - for (r = 1 ; r < rows; r++) { + for (r = 1; r < rows; r++) { for (n = 0; n < nobj; n++, k++) { - if (vector[n] < data[k] ) - vector[n] = data[k]; + if (vector[n] < data[k]) vector[n] = data[k]; } } return vector; } -void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +void +mexFunction(int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) { - int nobj; /* Number of objectives */ - int popsize; /* Number of solutions */ + int nobj; /* Number of objectives */ + int popsize; /* Number of solutions */ - double *MatLab_Obj; /* Pointer to the objective matrix */ + double * MatLab_Obj; /* Pointer to the objective matrix */ - double *reference; /* Reference vector*/ - double *data; /* Reshaped vector of MatLab_Obj */ - double *volume = 0; /* Hypervolume computation */ + double * reference; /* Reference vector*/ + double * data; /* Reshaped vector of MatLab_Obj */ + double * volume = 0; /* Hypervolume computation */ - int i,j,k; - if ((nrhs==0)||mxIsChar(prhs[0])) - { + int i, j, k; + if ((nrhs == 0) || mxIsChar(prhs[0])) { help(); return; } if (!mxIsNumeric(prhs[0])) mexErrMsgTxt("Data points must be a numeric matrix."); - nobj = mxGetN(prhs[0]); + nobj = mxGetN(prhs[0]); popsize = mxGetM(prhs[0]); - #ifdef DEBUG - mexPrintf("nobj=%d\n",nobj); - mexPrintf("popsize=%d\n",popsize); - #endif - MatLab_Obj = mxGetPr(prhs[0]); +#ifdef DEBUG + mexPrintf("nobj=%d\n", nobj); + mexPrintf("popsize=%d\n", popsize); +#endif + MatLab_Obj = mxGetPr(prhs[0]); /* Transpose the objective matrice*/ - data = MALLOC(nobj*popsize*sizeof(double)); + data = MALLOC(nobj * popsize * sizeof(double)); k = 0; - for (i=0;idepth : 0) -#define L_DEPTH(n) (NODE_DEPTH((n)->left)) -#define R_DEPTH(n) (NODE_DEPTH((n)->right)) -#define CALC_DEPTH(n) (unsigned char)((L_DEPTH(n)>R_DEPTH(n)?L_DEPTH(n):R_DEPTH(n)) + 1) +#define NODE_DEPTH(n) ((n) ? (n)->depth : 0) +#define L_DEPTH(n) (NODE_DEPTH((n)->left)) +#define R_DEPTH(n) (NODE_DEPTH((n)->right)) +#define CALC_DEPTH(n) \ + (unsigned char)((L_DEPTH(n) > R_DEPTH(n) ? L_DEPTH(n) : R_DEPTH(n)) + 1) -static int avl_check_balance(const avl_node_t *avlnode) { - int d = R_DEPTH(avlnode) - L_DEPTH(avlnode); - return d < -1 ? -1 : d > 1 ? 1 : 0; +static int +avl_check_balance(const avl_node_t * avlnode) +{ + int d = R_DEPTH(avlnode) - L_DEPTH(avlnode); + return d < -1 ? -1 : d > 1 ? 1 : 0; } /* Searches for a node with the key closest (or equal) to the given item. @@ -80,20 +83,21 @@ static int avl_check_balance(const avl_node_t *avlnode) { 1 if the returned node is smaller O(lg n) */ static int -avl_search_closest(const avl_tree_t *avltree, const avl_item_t *item, avl_node_t **avlnode) +avl_search_closest(const avl_tree_t * avltree, const avl_item_t * item, + avl_node_t ** avlnode) { - avl_node_t *node = avltree->top; + avl_node_t * node = avltree->top; assert(node); avl_compare_t cmp = avltree->cmp; - while(true) { + while (true) { int c = cmp(item, node->item); - if(c < 0) { - if(node->left) + if (c < 0) { + if (node->left) node = node->left; else return *avlnode = node, -1; - } else if(c > 0) { - if(node->right) + } else if (c > 0) { + if (node->right) node = node->right; else return *avlnode = node, 1; @@ -108,7 +112,8 @@ avl_search_closest(const avl_tree_t *avltree, const avl_item_t *item, avl_node_t * Returns the value of avltree (even if it's NULL). * O(1) */ static avl_tree_t * -avl_init_tree(avl_tree_t *rc, avl_compare_t cmp) { +avl_init_tree(avl_tree_t * rc, avl_compare_t cmp) +{ rc->head = NULL; rc->tail = NULL; rc->top = NULL; @@ -120,9 +125,10 @@ avl_init_tree(avl_tree_t *rc, avl_compare_t cmp) { * Compare and freeitem functions are left alone. * O(1) */ static void -avl_clear_node(avl_node_t *newnode) { - newnode->left = newnode->right = NULL; - newnode->depth = 1; +avl_clear_node(avl_node_t * newnode) +{ + newnode->left = newnode->right = NULL; + newnode->depth = 1; } /* Insert a node in an empty tree. If avlnode is NULL, the tree will be @@ -130,80 +136,80 @@ avl_clear_node(avl_node_t *newnode) { * If the tree is not empty, the old nodes are left dangling. * O(1) */ static avl_node_t * -avl_insert_top(avl_tree_t *avltree, avl_node_t *newnode) { - avl_clear_node(newnode); - newnode->prev = newnode->next = newnode->parent = NULL; - avltree->head = avltree->tail = avltree->top = newnode; - return newnode; +avl_insert_top(avl_tree_t * avltree, avl_node_t * newnode) +{ + avl_clear_node(newnode); + newnode->prev = newnode->next = newnode->parent = NULL; + avltree->head = avltree->tail = avltree->top = newnode; + return newnode; } -static avl_node_t * -avl_insert_after(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode); +static avl_node_t * avl_insert_after(avl_tree_t * avltree, avl_node_t * node, + avl_node_t * newnode); /* Insert a node before another node. Returns the new node. * If old is NULL, the item is appended to the tree. * O(lg n) */ static avl_node_t * -avl_insert_before(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode) { - if(!node) - return avltree->tail - ? avl_insert_after(avltree, avltree->tail, newnode) - : avl_insert_top(avltree, newnode); +avl_insert_before(avl_tree_t * avltree, avl_node_t * node, avl_node_t * newnode) +{ + if (!node) + return avltree->tail ? avl_insert_after(avltree, avltree->tail, newnode) + : avl_insert_top(avltree, newnode); - if(node->left) - return avl_insert_after(avltree, node->prev, newnode); + if (node->left) return avl_insert_after(avltree, node->prev, newnode); - assert (node); - assert (!node->left); + assert(node); + assert(!node->left); - avl_clear_node(newnode); + avl_clear_node(newnode); - newnode->next = node; - newnode->parent = node; + newnode->next = node; + newnode->parent = node; - newnode->prev = node->prev; - if(node->prev) - node->prev->next = newnode; - else - avltree->head = newnode; - node->prev = newnode; + newnode->prev = node->prev; + if (node->prev) + node->prev->next = newnode; + else + avltree->head = newnode; + node->prev = newnode; - node->left = newnode; - avl_rebalance(avltree, node); - return newnode; + node->left = newnode; + avl_rebalance(avltree, node); + return newnode; } /* Insert a node after another node. Returns the new node. * If old is NULL, the item is prepended to the tree. * O(lg n) */ static avl_node_t * -avl_insert_after(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode) { - if(!node) - return avltree->head - ? avl_insert_before(avltree, avltree->head, newnode) - : avl_insert_top(avltree, newnode); +avl_insert_after(avl_tree_t * avltree, avl_node_t * node, avl_node_t * newnode) +{ + if (!node) + return avltree->head + ? avl_insert_before(avltree, avltree->head, newnode) + : avl_insert_top(avltree, newnode); - if(node->right) - return avl_insert_before(avltree, node->next, newnode); + if (node->right) return avl_insert_before(avltree, node->next, newnode); - assert (node); - assert (!node->right); + assert(node); + assert(!node->right); - avl_clear_node(newnode); + avl_clear_node(newnode); - newnode->prev = node; - newnode->parent = node; + newnode->prev = node; + newnode->parent = node; - newnode->next = node->next; - if(node->next) - node->next->prev = newnode; - else - avltree->tail = newnode; - node->next = newnode; + newnode->next = node->next; + if (node->next) + node->next->prev = newnode; + else + avltree->tail = newnode; + node->next = newnode; - node->right = newnode; - avl_rebalance(avltree, node); - return newnode; + node->right = newnode; + avl_rebalance(avltree, node); + return newnode; } /* Deletes the node from the tree. Does not delete the item at that node. @@ -211,58 +217,57 @@ avl_insert_after(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode) { * (In other words, it is not referenced by this function.) * O(lg n) */ static void -avl_unlink_node(avl_tree_t *avltree, avl_node_t *avlnode) { - avl_node_t *parent; - avl_node_t **superparent; - avl_node_t *subst, *left, *right; - avl_node_t *balnode; - - if(avlnode->prev) - avlnode->prev->next = avlnode->next; - else - avltree->head = avlnode->next; - - if(avlnode->next) - avlnode->next->prev = avlnode->prev; - else - avltree->tail = avlnode->prev; - - parent = avlnode->parent; - - superparent = parent - ? avlnode == parent->left ? &parent->left : &parent->right - : &avltree->top; - - left = avlnode->left; - right = avlnode->right; - if(!left) { - *superparent = right; - if(right) - right->parent = parent; - balnode = parent; - } else if(!right) { - *superparent = left; - left->parent = parent; - balnode = parent; - } else { - subst = avlnode->prev; - if(subst == left) { - balnode = subst; - } else { - balnode = subst->parent; - balnode->right = subst->left; - if(balnode->right) - balnode->right->parent = balnode; - subst->left = left; - left->parent = subst; - } - subst->right = right; - subst->parent = parent; - right->parent = subst; - *superparent = subst; - } - - avl_rebalance(avltree, balnode); +avl_unlink_node(avl_tree_t * avltree, avl_node_t * avlnode) +{ + avl_node_t * parent; + avl_node_t ** superparent; + avl_node_t *subst, *left, *right; + avl_node_t * balnode; + + if (avlnode->prev) + avlnode->prev->next = avlnode->next; + else + avltree->head = avlnode->next; + + if (avlnode->next) + avlnode->next->prev = avlnode->prev; + else + avltree->tail = avlnode->prev; + + parent = avlnode->parent; + + superparent = parent + ? avlnode == parent->left ? &parent->left : &parent->right + : &avltree->top; + + left = avlnode->left; + right = avlnode->right; + if (!left) { + *superparent = right; + if (right) right->parent = parent; + balnode = parent; + } else if (!right) { + *superparent = left; + left->parent = parent; + balnode = parent; + } else { + subst = avlnode->prev; + if (subst == left) { + balnode = subst; + } else { + balnode = subst->parent; + balnode->right = subst->left; + if (balnode->right) balnode->right->parent = balnode; + subst->left = left; + left->parent = subst; + } + subst->right = right; + subst->parent = parent; + right->parent = subst; + *superparent = subst; + } + + avl_rebalance(avltree, balnode); } /* @@ -275,93 +280,84 @@ avl_unlink_node(avl_tree_t *avltree, avl_node_t *avlnode) { * longer going to be the same node. */ static void -avl_rebalance(avl_tree_t *avltree, avl_node_t *avlnode) { - avl_node_t *child; - avl_node_t *gchild; - avl_node_t *parent; - avl_node_t **superparent; - - parent = avlnode; - - while(avlnode) { - parent = avlnode->parent; - - superparent = parent - ? avlnode == parent->left ? &parent->left : &parent->right - : &avltree->top; - - switch(avl_check_balance(avlnode)) { - case -1: - child = avlnode->left; - if(L_DEPTH(child) >= R_DEPTH(child)) { - avlnode->left = child->right; - if(avlnode->left) - avlnode->left->parent = avlnode; - child->right = avlnode; - avlnode->parent = child; - *superparent = child; - child->parent = parent; - avlnode->depth = CALC_DEPTH(avlnode); - child->depth = CALC_DEPTH(child); - } else { - gchild = child->right; - avlnode->left = gchild->right; - if(avlnode->left) - avlnode->left->parent = avlnode; - child->right = gchild->left; - if(child->right) - child->right->parent = child; - gchild->right = avlnode; - if(gchild->right) - gchild->right->parent = gchild; - gchild->left = child; - if(gchild->left) - gchild->left->parent = gchild; - *superparent = gchild; - gchild->parent = parent; - avlnode->depth = CALC_DEPTH(avlnode); - child->depth = CALC_DEPTH(child); - gchild->depth = CALC_DEPTH(gchild); - } - break; - case 1: - child = avlnode->right; - if(R_DEPTH(child) >= L_DEPTH(child)) { - avlnode->right = child->left; - if(avlnode->right) - avlnode->right->parent = avlnode; - child->left = avlnode; - avlnode->parent = child; - *superparent = child; - child->parent = parent; - avlnode->depth = CALC_DEPTH(avlnode); - child->depth = CALC_DEPTH(child); - } else { - gchild = child->left; - avlnode->right = gchild->left; - if(avlnode->right) - avlnode->right->parent = avlnode; - child->left = gchild->right; - if(child->left) - child->left->parent = child; - gchild->left = avlnode; - if(gchild->left) - gchild->left->parent = gchild; - gchild->right = child; - if(gchild->right) - gchild->right->parent = gchild; - *superparent = gchild; - gchild->parent = parent; - avlnode->depth = CALC_DEPTH(avlnode); - child->depth = CALC_DEPTH(child); - gchild->depth = CALC_DEPTH(gchild); - } - break; - default: - avlnode->depth = CALC_DEPTH(avlnode); - } - avlnode = parent; - } +avl_rebalance(avl_tree_t * avltree, avl_node_t * avlnode) +{ + avl_node_t * child; + avl_node_t * gchild; + avl_node_t * parent; + avl_node_t ** superparent; + + parent = avlnode; + + while (avlnode) { + parent = avlnode->parent; + + superparent = + parent ? avlnode == parent->left ? &parent->left : &parent->right + : &avltree->top; + + switch (avl_check_balance(avlnode)) { + case -1: + child = avlnode->left; + if (L_DEPTH(child) >= R_DEPTH(child)) { + avlnode->left = child->right; + if (avlnode->left) avlnode->left->parent = avlnode; + child->right = avlnode; + avlnode->parent = child; + *superparent = child; + child->parent = parent; + avlnode->depth = CALC_DEPTH(avlnode); + child->depth = CALC_DEPTH(child); + } else { + gchild = child->right; + avlnode->left = gchild->right; + if (avlnode->left) avlnode->left->parent = avlnode; + child->right = gchild->left; + if (child->right) child->right->parent = child; + gchild->right = avlnode; + if (gchild->right) gchild->right->parent = gchild; + gchild->left = child; + if (gchild->left) gchild->left->parent = gchild; + *superparent = gchild; + gchild->parent = parent; + avlnode->depth = CALC_DEPTH(avlnode); + child->depth = CALC_DEPTH(child); + gchild->depth = CALC_DEPTH(gchild); + } + break; + case 1: + child = avlnode->right; + if (R_DEPTH(child) >= L_DEPTH(child)) { + avlnode->right = child->left; + if (avlnode->right) avlnode->right->parent = avlnode; + child->left = avlnode; + avlnode->parent = child; + *superparent = child; + child->parent = parent; + avlnode->depth = CALC_DEPTH(avlnode); + child->depth = CALC_DEPTH(child); + } else { + gchild = child->left; + avlnode->right = gchild->left; + if (avlnode->right) avlnode->right->parent = avlnode; + child->left = gchild->right; + if (child->left) child->left->parent = child; + gchild->left = avlnode; + if (gchild->left) gchild->left->parent = gchild; + gchild->right = child; + if (gchild->right) gchild->right->parent = gchild; + *superparent = gchild; + gchild->parent = parent; + avlnode->depth = CALC_DEPTH(avlnode); + child->depth = CALC_DEPTH(child); + gchild->depth = CALC_DEPTH(gchild); + } + break; + default: + avlnode->depth = CALC_DEPTH(avlnode); + } + avlnode = parent; + } } /*----------------------------------------------------------------------------- diff --git a/c/bit_array.h b/c/bit_array.h index 2c4c6c79..9ab92417 100644 --- a/c/bit_array.h +++ b/c/bit_array.h @@ -15,35 +15,49 @@ typedef uint8_t word_offset_t; // Offset within a 64 bit word static const size_t bit_array_word_size = sizeof(bit_array_word_t) * 8; static inline size_t -bitset_index(const bit_array *b, size_t pos) { return(pos % (sizeof(*b)*8)); } +bitset_index(const bit_array * b, size_t pos) +{ + return (pos % (sizeof(*b) * 8)); +} static inline size_t -bitset_word(const bit_array *b, size_t pos) { return(pos / (sizeof(*b)*8)); } +bitset_word(const bit_array * b, size_t pos) +{ + return (pos / (sizeof(*b) * 8)); +} static inline bit_array -bitset_mask(size_t k) { return (bit_array)((bit_array)1 << k); } +bitset_mask(size_t k) +{ + return (bit_array)((bit_array)1 << k); +} static inline void -bit_array_set_one(bit_array * b, size_t i) { - b[bitset_word(b, i)] |= bitset_mask(bitset_index(b,i)); +bit_array_set_one(bit_array * b, size_t i) +{ + b[bitset_word(b, i)] |= bitset_mask(bitset_index(b, i)); } static inline void -bit_array_set_zero(bit_array * b, size_t i) { - b[bitset_word(b,i)] &=~ bitset_mask(bitset_index(b,i)); +bit_array_set_zero(bit_array * b, size_t i) +{ + b[bitset_word(b, i)] &= ~bitset_mask(bitset_index(b, i)); } static inline char -bit_array_get(const bit_array * b, size_t i) { - return (b[bitset_word(b,i)] >> bitset_index(b,i)) & 0x1; +bit_array_get(const bit_array * b, size_t i) +{ + return (b[bitset_word(b, i)] >> bitset_index(b, i)) & 0x1; } static inline size_t -bit_nwords(size_t nbits) { - return (nbits + bit_array_word_size - 1) / bit_array_word_size; +bit_nwords(size_t nbits) +{ + return (nbits + bit_array_word_size - 1) / bit_array_word_size; } -static inline size_t bit_array_bytesize(size_t n) +static inline size_t +bit_array_bytesize(size_t n) { return sizeof(bit_array_word_t) * bit_nwords(n); } @@ -52,31 +66,32 @@ static inline bit_array * bit_array_alloc(size_t n) { //fprintf(stderr, "n= %ld, word_size = %ld size = %ld\n", n, bit_array_word_size, bit_nwords(n)); - return (bit_array *) malloc(bit_array_bytesize(n)); + return (bit_array *)malloc(bit_array_bytesize(n)); } static inline bit_array * bit_array_calloc(size_t n) { //fprintf(stderr, "word_size = %ld size = %ld", bit_array_word_size, bit_nwords(n)); - return (bit_array *) calloc(bit_nwords(n), sizeof(bit_array_word_t)); + return (bit_array *)calloc(bit_nwords(n), sizeof(bit_array_word_t)); } static inline bit_array * -bit_array_realloc(bit_array *b, size_t n) +bit_array_realloc(bit_array * b, size_t n) { //fprintf(stderr, "word_size = %ld size = %ld", bit_array_word_size, bit_nwords(n)); - return (bit_array *) realloc(b, bit_array_bytesize(n)); + return (bit_array *)realloc(b, bit_array_bytesize(n)); } static inline void -bit_array_zero_all(bit_array *b, size_t n) +bit_array_zero_all(bit_array * b, size_t n) { memset(b, 0, sizeof(bit_array_word_t) * bit_nwords(n)); } static inline void -bit_array_set(bit_array * b, size_t i, bool x) { +bit_array_set(bit_array * b, size_t i, bool x) +{ x ? bit_array_set_one(b, i) : bit_array_set_zero(b, i); } @@ -84,21 +99,22 @@ bit_array_set(bit_array * b, size_t i, bool x) { static inline void bitset_check(const bit_array * restrict b, const bool * restrict ref, size_t n) { - for(size_t i = 0; i < n; i++) { + for (size_t i = 0; i < n; i++) { if (bit_array_get(b, i) != ref[i]) { - fatal_error("bit_array_check_failed at %zu: %d != %d : %zu!\n", - i, bit_array_get(b, i), ref[i], n); + fatal_error("bit_array_check_failed at %zu: %d != %d : %zu!\n", i, + bit_array_get(b, i), ref[i], n); } } } static inline bit_array * -bit_array_offset(bit_array *b, size_t k, size_t nbits) +bit_array_offset(bit_array * b, size_t k, size_t nbits) { return b + k * bit_nwords(nbits); } static inline void -bit_array_check (bit_array * restrict b, const bool * restrict ref, size_t n, size_t nbits) +bit_array_check(bit_array * restrict b, const bool * restrict ref, size_t n, + size_t nbits) { for (size_t k = 0; k < n; k++) { // fprintf(stderr,"checking: k=%ld n=%ld, nbits=%ld offset=%ld\n", @@ -108,14 +124,16 @@ bit_array_check (bit_array * restrict b, const bool * restrict ref, size_t n, si } static inline void -bit_array_copy(bit_array * restrict dest, const bit_array * restrict src, size_t n) { +bit_array_copy(bit_array * restrict dest, const bit_array * restrict src, + size_t n) +{ memcpy(dest, src, sizeof(bit_array_word_t) * bit_nwords(n)); } #ifndef R_PACKAGE static inline void -bit_array_fprintf(FILE *stream, bit_array *b, size_t n) +bit_array_fprintf(FILE * stream, bit_array * b, size_t n) { for (size_t k = 0; k < n; k++) { fprintf(stream, "%d", bit_array_get(b, k) ? 1 : 0); diff --git a/c/cmdline.c b/c/cmdline.c index cfb78bc4..64582bcf 100644 --- a/c/cmdline.c +++ b/c/cmdline.c @@ -1,38 +1,41 @@ #include // If GNU libc, this includes feature.h and defines __USE_GNU #include "common.h" #ifdef __USE_GNU // Defined if _GNU_SOURCE is defined and GNU libc is used. -extern char *program_invocation_short_name; +extern char * program_invocation_short_name; #else -char *program_invocation_short_name; +char * program_invocation_short_name; #endif /* Do not inline it so we can set a breakpoint when debugging. */ -void fatal_error(const char *format,...) +void +fatal_error(const char * format, ...) { va_list ap; fprintf(stderr, "%s: fatal error: ", program_invocation_short_name); - va_start(ap,format); + va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); fprintf(stderr, "\n"); exit(EXIT_FAILURE); } -void errprintf(const char *format,...) +void +errprintf(const char * format, ...) { va_list ap; fprintf(stderr, "%s: error: ", program_invocation_short_name); - va_start(ap,format); + va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); fprintf(stderr, "\n"); } -void warnprintf(const char *format,...) +void +warnprintf(const char * format, ...) { va_list ap; fprintf(stderr, "%s: warning: ", program_invocation_short_name); - va_start(ap,format); + va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); fprintf(stderr, "\n"); diff --git a/c/cmdline.h b/c/cmdline.h index e85aa616..0a2f794a 100644 --- a/c/cmdline.h +++ b/c/cmdline.h @@ -4,78 +4,84 @@ #include "io.h" #ifndef CMDLINE_COPYRIGHT_YEARS -#define CMDLINE_COPYRIGHT_YEARS "2007-2025" +# define CMDLINE_COPYRIGHT_YEARS "2007-2025" #endif #ifndef CMDLINE_AUTHORS -#define CMDLINE_AUTHORS "Manuel Lopez-Ibanez \n" +# define CMDLINE_AUTHORS \ + "Manuel Lopez-Ibanez \n" #endif -#define OPTION_HELP_STR \ - " -h, --help print this summary and exit;\n" -#define OPTION_VERSION_STR \ - " --version print version number (and compilation flags) and exit;\n" -#define OPTION_OBJ_STR \ - " -o, --obj=[+|-]... specify whether each objective should be minimised (-)\n" \ +#define OPTION_HELP_STR " -h, --help print this summary and exit;\n" +#define OPTION_VERSION_STR \ + " --version print version number (and compilation flags) and " \ + "exit;\n" +#define OPTION_OBJ_STR \ + " -o, --obj=[+|-]... specify whether each objective should be minimised " \ + "(-)\n" \ " or maximised (+). By default all are minimised;\n" -#define OPTION_QUIET_STR \ - " -q, --quiet print as little as possible;\n" +#define OPTION_QUIET_STR " -q, --quiet print as little as possible;\n" #define OPTION_MAXIMISE_STR \ " --maximise all objectives must be maximised;\n" -#define OPTION_NOCHECK_STR \ - " --no-check do not check nondominance of sets (faster but unsafe);\n" -#define OPTION_SEED_STR \ - " -S, --seed=SEED Seed of the random number generator (positive integer).\n" +#define OPTION_NOCHECK_STR \ + " --no-check do not check nondominance of sets (faster but " \ + "unsafe);\n" +#define OPTION_SEED_STR \ + " -S, --seed=SEED Seed of the random number generator (positive " \ + "integer).\n" #include #include // for isspace() -extern char *program_invocation_short_name; +extern char * program_invocation_short_name; -static void version(void) +static void +version(void) { #if defined(DEBUG) && DEBUG >= 1 -#define DEBUG_LEVEL_STR " [DEBUG=" MOOCORE_STRINGIFY_MACRO(DEBUG) "]" +# define DEBUG_LEVEL_STR " [DEBUG=" MOOCORE_STRINGIFY_MACRO(DEBUG) "]" #else -#define DEBUG_LEVEL_STR "" +# define DEBUG_LEVEL_STR "" #endif #ifdef MARCH -#define OPTIMISED_FOR_STR " (optimised for "MARCH")" +# define OPTIMISED_FOR_STR " (optimised for " MARCH ")" #else -#define OPTIMISED_FOR_STR "" +# define OPTIMISED_FOR_STR "" #endif - printf("%s version " VERSION OPTIMISED_FOR_STR DEBUG_LEVEL_STR - "\n\n", program_invocation_short_name); - printf( -"Copyright (C) " CMDLINE_COPYRIGHT_YEARS "\n" CMDLINE_AUTHORS "\n" -"This is free software, and you are welcome to redistribute it under certain\n" -"conditions. See the GNU General Public License for details. There is NO \n" -"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" -"\n" ); + printf("%s version " VERSION OPTIMISED_FOR_STR DEBUG_LEVEL_STR "\n\n", + program_invocation_short_name); + printf("Copyright (C) " CMDLINE_COPYRIGHT_YEARS "\n" CMDLINE_AUTHORS "\n" + "This is free software, and you are welcome to redistribute it " + "under certain\n" + "conditions. See the GNU General Public License for details. There " + "is NO \n" + "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " + "PURPOSE.\n" + "\n"); } #ifndef READ_INPUT_WRONG_INITIAL_DIM_ERRSTR -#define READ_INPUT_WRONG_INITIAL_DIM_ERRSTR "-r, --reference" +# define READ_INPUT_WRONG_INITIAL_DIM_ERRSTR "-r, --reference" #endif static inline void -handle_read_data_error (int err, const char *filename) +handle_read_data_error(int err, const char * filename) { switch (err) { - case 0: /* No error */ - break; - - case READ_INPUT_FILE_EMPTY: - if (!filename) - filename = stdin_name; - errprintf ("%s: no input data.", filename); - exit (EXIT_FAILURE); - - case READ_INPUT_WRONG_INITIAL_DIM: - errprintf ("check the argument of " READ_INPUT_WRONG_INITIAL_DIM_ERRSTR "."); - /* fall-through */ - default: - exit (EXIT_FAILURE); + case 0: /* No error */ + break; + + case READ_INPUT_FILE_EMPTY: + if (!filename) filename = stdin_name; + errprintf("%s: no input data.", filename); + exit(EXIT_FAILURE); + + case READ_INPUT_WRONG_INITIAL_DIM: + errprintf("check the argument of " READ_INPUT_WRONG_INITIAL_DIM_ERRSTR + "."); + /* fall-through */ + default: + exit(EXIT_FAILURE); } } @@ -91,20 +97,19 @@ handle_read_data_error (int err, const char *filename) */ static inline size_t -read_reference_set (double **reference_p, const char *filename, int *nobj_p) +read_reference_set(double ** reference_p, const char * filename, int * nobj_p) { - double *reference = NULL; - int *cumsizes = NULL; + double * reference = NULL; + int * cumsizes = NULL; int nruns = 0; int nobj = *nobj_p; size_t reference_size; handle_read_data_error( - read_double_data (filename, &reference, &nobj, &cumsizes, &nruns), + read_double_data(filename, &reference, &nobj, &cumsizes, &nruns), filename); - if (!filename) - filename = stdin_name; - reference_size = (size_t) cumsizes[nruns - 1]; + if (!filename) filename = stdin_name; + reference_size = (size_t)cumsizes[nruns - 1]; free(cumsizes); *nobj_p = nobj; *reference_p = reference; @@ -133,7 +138,7 @@ read_point(char * str, int * nobj) // not end of string: error while (*cursor != '\0') { if (!isspace(*cursor)) { - free (point); + free(point); return NULL; } cursor++; @@ -143,26 +148,25 @@ read_point(char * str, int * nobj) free(point); return NULL; } - if (k < size) - point = realloc(point, k * sizeof(double)); + if (k < size) point = realloc(point, k * sizeof(double)); *nobj = k - 1; return point; } static inline double * -robust_read_point(char * restrict optarg, int *nobj, const char * restrict errmsg) +robust_read_point(char * restrict optarg, int * nobj, + const char * restrict errmsg) { double * point = read_point(optarg, nobj); - if (point == NULL) - fatal_error(errmsg, optarg); + if (point == NULL) fatal_error(errmsg, optarg); return point; } #include // INFINITY static void -data_bounds(double **minimum_p, double **maximum_p, - const double *data, int nobj, int rows) +data_bounds(double ** minimum_p, double ** maximum_p, const double * data, + int nobj, int rows) { ASSUME(nobj > 1); ASSUME(nobj <= 32); @@ -170,83 +174,84 @@ data_bounds(double **minimum_p, double **maximum_p, double * minimum = *minimum_p; if (minimum == NULL) { - minimum = malloc (nobj * sizeof(double)); - for (k = 0; k < nobj; k++) - minimum[k] = INFINITY; + minimum = malloc(nobj * sizeof(double)); + for (k = 0; k < nobj; k++) minimum[k] = INFINITY; *minimum_p = minimum; } double * maximum = *maximum_p; if (maximum == NULL) { - maximum = malloc (nobj * sizeof(double)); - for (k = 0; k < nobj; k++) - maximum[k] = -INFINITY; + maximum = malloc(nobj * sizeof(double)); + for (k = 0; k < nobj; k++) maximum[k] = -INFINITY; *maximum_p = maximum; } for (int r = 0, n = 0; r < rows; r++) { for (k = 0; k < nobj; k++, n++) { - if (maximum[k] < data[n]) - maximum[k] = data[n]; - if (minimum[k] > data[n]) - minimum[k] = data[n]; + if (maximum[k] < data[n]) maximum[k] = data[n]; + if (minimum[k] > data[n]) minimum[k] = data[n]; } } } _attr_maybe_unused static void -file_bounds (const char *filename, double **maximum_p, double **minimum_p, - int *dim_p) +file_bounds(const char * filename, double ** maximum_p, double ** minimum_p, + int * dim_p) { - double *data = NULL; - int *cumsizes = NULL; + double * data = NULL; + int * cumsizes = NULL; int nruns = 0; handle_read_data_error( - read_double_data(filename, &data, dim_p, &cumsizes, &nruns), - filename); + read_double_data(filename, &data, dim_p, &cumsizes, &nruns), filename); data_bounds(minimum_p, maximum_p, data, *dim_p, cumsizes[nruns - 1]); free(data); free(cumsizes); } -static inline char * m_strcat(const char * a, const char * b) +static inline char * +m_strcat(const char * a, const char * b) { size_t dest_len = strlen(a) + strlen(b) + 1; char * dest = malloc(sizeof(char) * dest_len); - if (unlikely(dest == NULL)) - return NULL; - strcpy (dest, a); - strcat (dest, b); + if (unlikely(dest == NULL)) return NULL; + strcpy(dest, a); + strcat(dest, b); return dest; } -static inline const char *str_is_default(bool flag) +static inline const char * +str_is_default(bool flag) { return flag ? "(default)" : ""; } -static inline void set_program_invocation_short_name(char *s) +static inline void +set_program_invocation_short_name(char * s) { - if (program_invocation_short_name == NULL || program_invocation_short_name[0] == '\0') + if (program_invocation_short_name == NULL || + program_invocation_short_name[0] == '\0') program_invocation_short_name = s; } static inline const signed char * -parse_cmdline_minmax(const signed char * minmax, const char *optarg, int *nobj_p) +parse_cmdline_minmax(const signed char * minmax, const char * optarg, + int * nobj_p) { int tmp_nobj = 0, nobj = *nobj_p; - if (minmax != NULL) - free((void *) minmax); - minmax = read_minmax (optarg, &tmp_nobj); + if (minmax != NULL) free((void *)minmax); + minmax = read_minmax(optarg, &tmp_nobj); if (minmax == NULL) { - errprintf ("invalid argument '%s' for -o, --obj" - ", it should be a sequence of '+' or '-'\n", optarg); + errprintf("invalid argument '%s' for -o, --obj" + ", it should be a sequence of '+' or '-'\n", + optarg); exit(EXIT_FAILURE); } if (nobj == 0) { nobj = tmp_nobj; } else if (tmp_nobj != nobj) { - errprintf ("number of objectives in --obj (%d) and reference set (%d) do not match", tmp_nobj, nobj); + errprintf("number of objectives in --obj (%d) and reference set (%d) " + "do not match", + tmp_nobj, nobj); exit(EXIT_FAILURE); } *nobj_p = nobj; @@ -255,22 +260,23 @@ parse_cmdline_minmax(const signed char * minmax, const char *optarg, int *nobj_p static void usage(void); -static inline void default_cmdline_handler(int opt) +static inline void +default_cmdline_handler(int opt) { switch (opt) { - case 'V': // --version - version(); - exit(EXIT_SUCCESS); - case '?': - // getopt prints an error message right here - fprintf(stderr, "Try `%s --help' for more information.\n", - program_invocation_short_name); - exit(EXIT_FAILURE); - case 'h': // --help - usage(); - exit(EXIT_SUCCESS); - default: - unreachable(); + case 'V': // --version + version(); + exit(EXIT_SUCCESS); + case '?': + // getopt prints an error message right here + fprintf(stderr, "Try `%s --help' for more information.\n", + program_invocation_short_name); + exit(EXIT_FAILURE); + case 'h': // --help + usage(); + exit(EXIT_SUCCESS); + default: + unreachable(); } } diff --git a/c/common.h b/c/common.h index 484fb500..6687de30 100644 --- a/c/common.h +++ b/c/common.h @@ -3,31 +3,37 @@ #include "config.h" #ifdef R_PACKAGE -#define R_NO_REMAP -#include -#define assert(EXP) \ - do { if (unlikely(!(EXP))) { Rf_error("error: assertion failed: '%s' at %s:%d", \ - #EXP, __FILE__, __LINE__);}} while(0) -#include "gcc_attribs.h" -#define fatal_error(...) Rf_error(__VA_ARGS__) -#define moocore_perror(...) Rf_error(__VA_ARGS__) -#define errprintf Rf_error -#define warnprintf Rf_warning +# define R_NO_REMAP +# include +# define assert(EXP) \ + do { \ + if (unlikely(!(EXP))) { \ + Rf_error("error: assertion failed: '%s' at %s:%d", #EXP, \ + __FILE__, __LINE__); \ + } \ + } while (0) +# include "gcc_attribs.h" +# define fatal_error(...) Rf_error(__VA_ARGS__) +# define moocore_perror(...) Rf_error(__VA_ARGS__) +# define errprintf Rf_error +# define warnprintf Rf_warning #else -#include -#include -#include -#include -#include "gcc_attribs.h" -__noreturn _attr_maybe_unused void fatal_error(const char * format,...) ATTRIBUTE_FORMAT_PRINTF(1, 2); -void errprintf(const char * format,...) ATTRIBUTE_FORMAT_PRINTF(1, 2); -void warnprintf(const char *format,...) ATTRIBUTE_FORMAT_PRINTF(1, 2); -#define moocore_perror(...) do { \ - char buffer[1024] = ""; \ - snprintf(buffer, 1024, __VA_ARGS__); \ - perror(buffer); \ - exit(EXIT_FAILURE); \ - } while(0) +# include +# include +# include +# include +# include "gcc_attribs.h" +__noreturn _attr_maybe_unused void fatal_error(const char * format, ...) + ATTRIBUTE_FORMAT_PRINTF(1, 2); +void errprintf(const char * format, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); +void warnprintf(const char * format, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); +# define moocore_perror(...) \ + do { \ + char buffer[1024] = ""; \ + snprintf(buffer, 1024, __VA_ARGS__); \ + perror(buffer); \ + exit(EXIT_FAILURE); \ + } while (0) #endif // R_PACKAGE #define MOOCORE_STRINGIFY(name) #name @@ -35,7 +41,7 @@ void warnprintf(const char *format,...) ATTRIBUTE_FORMAT_PRINTF(1, 2); #include static inline void * -moocore_malloc(size_t nmemb, size_t size, const char *file, int line) +moocore_malloc(size_t nmemb, size_t size, const char * file, int line) { // FIXME: Check multiplication overflow. // https://github.com/bminor/glibc/blob/e64a1e81aadf6c401174ac9471ced0f0125c2912/malloc/malloc.c#L3709 @@ -43,81 +49,106 @@ moocore_malloc(size_t nmemb, size_t size, const char *file, int line) // https://github.com/python/cpython/blob/89df62c12093bfa079860a93032468ebece3774d/Include/internal/mimalloc/mimalloc/internal.h#L323 void * p = malloc(nmemb * size); if (unlikely(!p)) - moocore_perror("%s:%d: malloc (%zu * %zu) failed", - file, line, nmemb, size); + moocore_perror("%s:%d: malloc (%zu * %zu) failed", file, line, nmemb, + size); return p; } -#define MOOCORE_MALLOC(NMEMB, TYPE) moocore_malloc((NMEMB), sizeof(TYPE), __FILE__, __LINE__) +#define MOOCORE_MALLOC(NMEMB, TYPE) \ + moocore_malloc((NMEMB), sizeof(TYPE), __FILE__, __LINE__) #if (defined(__GNUC__) && __GNUC__ >= 3) || defined(__clang__) -#define __cmp_op_min < -#define __cmp_op_max > -#define __cmp(op, x, y) ((x) __cmp_op_##op (y) ? (x) : (y)) -#define __careful_cmp(op, x, y) __extension__({ \ - __auto_type _x__ = (x); \ - __auto_type _y__ = (y); \ - (void) (&_x__ == &_y__); \ - __cmp(op, _x__, _y__); }) - -#define MAX(x,y) __careful_cmp(max, x, y) -#define MIN(x,y) __careful_cmp(min, x, y) - -#define CLAMP(x, xmin, xmax) __extension__({ \ - __auto_type _x__ = (x); \ - __typeof__(_x__) _xmin__ = (xmin); \ - __typeof__(_x__) _xmax__ = (xmax); \ - _x__ <= _xmin__ ? _xmin__ : _x__ >= _xmax__ ? _xmax__ : _x__; }) +# define __cmp_op_min < +# define __cmp_op_max > +# define __cmp(op, x, y) ((x)__cmp_op_##op(y) ? (x) : (y)) +# define __careful_cmp(op, x, y) \ + __extension__({ \ + __auto_type _x__ = (x); \ + __auto_type _y__ = (y); \ + (void)(&_x__ == &_y__); \ + __cmp(op, _x__, _y__); \ + }) + +# define MAX(x, y) __careful_cmp(max, x, y) +# define MIN(x, y) __careful_cmp(min, x, y) + +# define CLAMP(x, xmin, xmax) \ + __extension__({ \ + __auto_type _x__ = (x); \ + __typeof__(_x__) _xmin__ = (xmin); \ + __typeof__(_x__) _xmax__ = (xmax); \ + _x__ <= _xmin__ ? _xmin__ : _x__ >= _xmax__ ? _xmax__ : _x__; \ + }) #else -#define MAX(x,y) ((x) > (y) ? (x) : (y)) -#define MIN(x,y) ((x) < (y) ? (x) : (y)) -#define CLAMP(x, xmin, xmax) (MAX((xim), (MIN((x), (xmax))))) +# define MAX(x, y) ((x) > (y) ? (x) : (y)) +# define MIN(x, y) ((x) < (y) ? (x) : (y)) +# define CLAMP(x, xmin, xmax) (MAX((xim), (MIN((x), (xmax))))) #endif -#define DEBUG_DO(X) do{ X;} while(0) -#define DEBUG_NOT_DO(X) while(0){ X;} +#define DEBUG_DO(X) \ + do { \ + X; \ + } while (0) +#define DEBUG_NOT_DO(X) \ + while (0) { \ + X; \ + } #if DEBUG >= 1 -#define DEBUG1(X) DEBUG_DO(X) +# define DEBUG1(X) DEBUG_DO(X) #else -#define DEBUG1(X) DEBUG_NOT_DO(X) +# define DEBUG1(X) DEBUG_NOT_DO(X) #endif #if DEBUG >= 2 -#define DEBUG2(X) DEBUG_DO(X) +# define DEBUG2(X) DEBUG_DO(X) #else -#define DEBUG2(X) DEBUG_NOT_DO(X) +# define DEBUG2(X) DEBUG_NOT_DO(X) #endif #if DEBUG >= 3 -#define DEBUG3(X) DEBUG_DO(X) +# define DEBUG3(X) DEBUG_DO(X) #else -#define DEBUG3(X) DEBUG_NOT_DO(X) +# define DEBUG3(X) DEBUG_NOT_DO(X) #endif #if DEBUG >= 4 -#define DEBUG4(X) DEBUG_DO(X) +# define DEBUG4(X) DEBUG_DO(X) #else -#define DEBUG4(X) DEBUG_NOT_DO(X) +# define DEBUG4(X) DEBUG_NOT_DO(X) #endif #ifndef R_PACKAGE -# define DEBUG1_PRINT(...) DEBUG1(fprintf(stderr, __VA_ARGS__)) -# define DEBUG2_PRINT(...) DEBUG2(fprintf(stderr, __VA_ARGS__)) +# define DEBUG1_PRINT(...) DEBUG1(fprintf(stderr, __VA_ARGS__)) +# define DEBUG2_PRINT(...) DEBUG2(fprintf(stderr, __VA_ARGS__)) #else -# define DEBUG1_PRINT(...) DEBUG1(Rprintf( __VA_ARGS__)) -# define DEBUG2_PRINT(...) DEBUG2(Rprintf( __VA_ARGS__)) +# define DEBUG1_PRINT(...) DEBUG1(Rprintf(__VA_ARGS__)) +# define DEBUG2_PRINT(...) DEBUG2(Rprintf(__VA_ARGS__)) #endif -#define DEBUG2_FUNPRINT(...) \ - do { DEBUG2_PRINT ("%s(): ", __FUNCTION__); \ - DEBUG2_PRINT (__VA_ARGS__); } while(0) +#define DEBUG2_FUNPRINT(...) \ + do { \ + DEBUG2_PRINT("%s(): ", __FUNCTION__); \ + DEBUG2_PRINT(__VA_ARGS__); \ + } while (0) #if DEBUG >= 1 -#define ASSERT_OR_DO(COND, X) do{ if (!(COND)) { X;} assert(COND); } while(0) +# define ASSERT_OR_DO(COND, X) \ + do { \ + if (!(COND)) { \ + X; \ + } \ + assert(COND); \ + } while (0) #else -#define ASSERT_OR_DO(COND, X) while(0){ if (!(COND)) { X;} assert(COND); } +# define ASSERT_OR_DO(COND, X) \ + while (0) { \ + if (!(COND)) { \ + X; \ + } \ + assert(COND); \ + } #endif /* This is deprecated. See https://www.gnu.org/software/libc/manual/html_node/Heap-Consistency-Checking.html @@ -129,20 +160,24 @@ moocore_malloc(size_t nmemb, size_t size, const char *file, int line) */ #ifndef ignore_unused_result -#define ignore_unused_result(X) do { if(X) {}} while(0); +# define ignore_unused_result(X) \ + do { \ + if (X) { \ + } \ + } while (0); #endif #ifdef __cplusplus -#define STATIC_CAST(TYPE,OP) (static_cast(OP)) +# define STATIC_CAST(TYPE, OP) (static_cast(OP)) #else -#define STATIC_CAST(TYPE,OP) ((TYPE)(OP)) +# define STATIC_CAST(TYPE, OP) ((TYPE)(OP)) #endif /* FIXME: Move this to a better place: matrix.h ? */ /* FIXME: Measure if this is faster than the R implementation of t() */ static inline void -matrix_transpose_double(double *dst, const double *src, - const size_t nrows, const size_t ncols) +matrix_transpose_double(double * dst, const double * src, const size_t nrows, + const size_t ncols) { size_t j, i, pos = 0; for (j = 0; j < ncols; j++) { @@ -160,7 +195,8 @@ typedef uint_fast8_t dimension_t; enum objs_agree_t { AGREE_MINIMISE = -1, AGREE_NONE = 0, AGREE_MAXIMISE = 1 }; static inline enum objs_agree_t -check_all_minimize_maximize(const signed char * restrict minmax, dimension_t dim) +check_all_minimize_maximize(const signed char * restrict minmax, + dimension_t dim) { bool all_minimize = true, all_maximize = true; for (dimension_t d = 0; d < dim; d++) { @@ -197,8 +233,7 @@ new_bool_maximise(dimension_t nobj, bool maximise_all) ASSUME(nobj > 0); ASSUME(nobj < 128); bool * maximise = malloc(sizeof(bool) * nobj); - for (dimension_t k = 0; k < nobj; k++) - maximise[k] = maximise_all; + for (dimension_t k = 0; k < nobj; k++) maximise[k] = maximise_all; return maximise; } @@ -208,8 +243,7 @@ default_minmax(dimension_t nobj, signed char default_value) ASSUME(nobj > 0); ASSUME(default_value == AGREE_MINIMISE || default_value == AGREE_MAXIMISE); signed char * minmax = malloc(sizeof(signed char) * nobj); - for (dimension_t i = 0; i < nobj; i++) - minmax[i] = default_value; + for (dimension_t i = 0; i < nobj; i++) minmax[i] = default_value; return minmax; } @@ -225,4 +259,4 @@ minmax_maximise(dimension_t nobj) return default_minmax(nobj, AGREE_MAXIMISE); } -#endif /* !MOOCORE_COMMON_H_ */ +#endif /* !MOOCORE_COMMON_H_ */ diff --git a/c/config.h b/c/config.h index 5e748021..42154947 100644 --- a/c/config.h +++ b/c/config.h @@ -1,12 +1,12 @@ #ifndef _MOOCORE_CONFIG_H_ #define _MOOCORE_CONFIG_H_ -#if (defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)) \ - && !defined(_UCRT) && !defined(__USE_MINGW_ANSI_STDIO) -#if !defined(__cplusplus) && !defined(_ISOC99_SOURCE) -#define _ISOC99_SOURCE -#endif -#define __USE_MINGW_ANSI_STDIO 1 +#if (defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)) && \ + !defined(_UCRT) && !defined(__USE_MINGW_ANSI_STDIO) +# if !defined(__cplusplus) && !defined(_ISOC99_SOURCE) +# define _ISOC99_SOURCE +# endif +# define __USE_MINGW_ANSI_STDIO 1 #endif // Silence deprecation warnings from Clang and MSVC on Windows diff --git a/c/cvector.h b/c/cvector.h index 6467fe18..a493e1c8 100644 --- a/c/cvector.h +++ b/c/cvector.h @@ -2,8 +2,8 @@ #define __CVECTOR_H__ #ifndef cvector_assert -#include -#define cvector_assert(X) assert(X) +# include +# define cvector_assert(X) assert(X) #endif #include @@ -11,82 +11,84 @@ // This warning is buggy in GCC 12. #if defined(__GNUC__) && __GNUC__ == 12 -# pragma GCC diagnostic ignored "-Wuse-after-free" +# pragma GCC diagnostic ignored "-Wuse-after-free" #endif -#define vector_define(VECTOR_TYPE, BASE_TYPE) \ -struct VECTOR_TYPE; \ -typedef struct VECTOR_TYPE VECTOR_TYPE; \ - \ -struct VECTOR_TYPE { \ - BASE_TYPE *_begin; \ - BASE_TYPE *_end; \ - BASE_TYPE *_capacity; \ -}; \ - \ -static inline \ -void VECTOR_TYPE##_reserve(VECTOR_TYPE * v, size_t n); \ - \ -/* Default constructor: constructs an empty vector, with no content - and a size of zero. */ \ -static inline \ -void VECTOR_TYPE##_ctor_zero(VECTOR_TYPE * v) \ -{ \ - v->_begin = NULL; \ - v->_end = NULL; \ - v->_capacity = NULL; \ -} \ - \ -/* Default constructor: constructs an empty vector, with no content - and a size of zero. */ \ -static inline \ -void VECTOR_TYPE##_ctor(VECTOR_TYPE * v, size_t n) \ -{ \ - VECTOR_TYPE##_ctor_zero (v); \ - VECTOR_TYPE##_reserve (v, n); \ -} \ - \ -/* Default constructor: dynamically allocates an empty vector, with no - content and a size of zero. */ \ -static inline \ -VECTOR_TYPE * VECTOR_TYPE##_new(size_t n) \ -{ \ - VECTOR_TYPE * v = malloc (sizeof(VECTOR_TYPE)); \ - VECTOR_TYPE##_ctor (v, n); \ - return v; \ -} \ - \ -/* Destructor. It frees the memory allocated to the vector, but it - does not try to free each of its elements or the vector itself. */ \ -static inline \ -void VECTOR_TYPE##_dtor(VECTOR_TYPE * v) \ -{ free(v->_begin); } \ - \ -/* Destructor. It frees the memory allocated to a dynamically +#define vector_define(VECTOR_TYPE, BASE_TYPE) \ + struct VECTOR_TYPE; \ + typedef struct VECTOR_TYPE VECTOR_TYPE; \ + \ + struct VECTOR_TYPE { \ + BASE_TYPE * _begin; \ + BASE_TYPE * _end; \ + BASE_TYPE * _capacity; \ + }; \ + \ + static inline void VECTOR_TYPE##_reserve(VECTOR_TYPE * v, size_t n); \ + \ + /* Default constructor: constructs an empty vector, with no content + and a size of zero. */ \ + static inline void VECTOR_TYPE##_ctor_zero(VECTOR_TYPE * v) \ + { \ + v->_begin = NULL; \ + v->_end = NULL; \ + v->_capacity = NULL; \ + } \ + \ + /* Default constructor: constructs an empty vector, with no content + and a size of zero. */ \ + static inline void VECTOR_TYPE##_ctor(VECTOR_TYPE * v, size_t n) \ + { \ + VECTOR_TYPE##_ctor_zero(v); \ + VECTOR_TYPE##_reserve(v, n); \ + } \ + \ + /* Default constructor: dynamically allocates an empty vector, with no + content and a size of zero. */ \ + static inline VECTOR_TYPE * VECTOR_TYPE##_new(size_t n) \ + { \ + VECTOR_TYPE * v = malloc(sizeof(VECTOR_TYPE)); \ + VECTOR_TYPE##_ctor(v, n); \ + return v; \ + } \ + \ + /* Destructor. It frees the memory allocated to the vector, but it + does not try to free each of its elements or the vector itself. */ \ + static inline void VECTOR_TYPE##_dtor(VECTOR_TYPE * v) \ + { \ + free(v->_begin); \ + } \ + \ + /* Destructor. It frees the memory allocated to a dynamically allocated vector, but it does not try to free each of its - elements. */ \ -static inline \ -void VECTOR_TYPE##_delete(VECTOR_TYPE * v) \ -{ VECTOR_TYPE##_dtor(v); free(v); } \ - \ - \ -/* Returns the number of elements in the vector container. */ \ -static inline \ -size_t VECTOR_TYPE##_size(const VECTOR_TYPE * v) \ -{ return v->_end - v->_begin; } \ - \ -/* Return size of allocated storage capacity. */ \ -static inline \ -size_t VECTOR_TYPE##_capacity(const VECTOR_TYPE * v) \ -{ return v->_capacity - v->_begin; } \ - \ -/* Returns whether the vector container is empty, i.e. whether its - size is 0. */ \ -static inline \ -bool VECTOR_TYPE##_empty(const VECTOR_TYPE * v) \ -{ return v->_begin == v->_end; } \ - \ -/* Requests that the capacity of the allocated storage space for the + elements. */ \ + static inline void VECTOR_TYPE##_delete(VECTOR_TYPE * v) \ + { \ + VECTOR_TYPE##_dtor(v); \ + free(v); \ + } \ + \ + \ + /* Returns the number of elements in the vector container. */ \ + static inline size_t VECTOR_TYPE##_size(const VECTOR_TYPE * v) \ + { \ + return v->_end - v->_begin; \ + } \ + \ + /* Return size of allocated storage capacity. */ \ + static inline size_t VECTOR_TYPE##_capacity(const VECTOR_TYPE * v) \ + { \ + return v->_capacity - v->_begin; \ + } \ + \ + /* Returns whether the vector container is empty, i.e. whether its + size is 0. */ \ + static inline bool VECTOR_TYPE##_empty(const VECTOR_TYPE * v) \ + { \ + return v->_begin == v->_end; \ + } \ + \ + /* Requests that the capacity of the allocated storage space for the elements of the vector container be at least enough to hold n elements. @@ -105,22 +107,21 @@ bool VECTOR_TYPE##_empty(const VECTOR_TYPE * v) \ references and pointers to elements of the vector. In any case, a call to this function never affects the elements - contained in the vector, nor the vector size. */ \ -static inline \ -void VECTOR_TYPE##_reserve(VECTOR_TYPE * v, size_t n) \ -{ \ - size_t old_capacity = VECTOR_TYPE##_capacity(v); \ - size_t old_size = VECTOR_TYPE##_size(v); \ - if (n > old_capacity) { \ - cvector_assert(SIZE_MAX / sizeof(BASE_TYPE) >= n); \ - v->_begin = realloc(v->_begin, sizeof(BASE_TYPE) * n); \ - cvector_assert(v->_begin != NULL); \ - v->_end = v->_begin + old_size; \ - v->_capacity = v->_begin + n; \ - } \ -} \ - \ -/* Adds a new element at the end of the vector, after its current last + contained in the vector, nor the vector size. */ \ + static inline void VECTOR_TYPE##_reserve(VECTOR_TYPE * v, size_t n) \ + { \ + size_t old_capacity = VECTOR_TYPE##_capacity(v); \ + size_t old_size = VECTOR_TYPE##_size(v); \ + if (n > old_capacity) { \ + cvector_assert(SIZE_MAX / sizeof(BASE_TYPE) >= n); \ + v->_begin = realloc(v->_begin, sizeof(BASE_TYPE) * n); \ + cvector_assert(v->_begin != NULL); \ + v->_end = v->_begin + old_size; \ + v->_capacity = v->_begin + n; \ + } \ + } \ + \ + /* Adds a new element at the end of the vector, after its current last element. The content of this new element is initialized to a copy of x. @@ -128,74 +129,72 @@ void VECTOR_TYPE##_reserve(VECTOR_TYPE * v, size_t n) \ reallocation of the internal allocated storage if the vector size was equal to the vector capacity before the call. Reallocations invalidate all previously obtained iterators, references and - pointers. */ \ -static inline \ -void VECTOR_TYPE##_push_back(VECTOR_TYPE * v, BASE_TYPE x) \ -{ \ - if (v->_end == v->_capacity) { \ - size_t capacity = VECTOR_TYPE##_capacity(v); \ - VECTOR_TYPE##_reserve(v, capacity == 0 ? 8 : 2 * capacity); \ - } \ - *(v->_end) = x; \ - v->_end++; \ -} \ - \ -/* Removes the last element in the vector, effectively reducing the + pointers. */ \ + static inline void VECTOR_TYPE##_push_back(VECTOR_TYPE * v, BASE_TYPE x) \ + { \ + if (v->_end == v->_capacity) { \ + size_t capacity = VECTOR_TYPE##_capacity(v); \ + VECTOR_TYPE##_reserve(v, capacity == 0 ? 8 : 2 * capacity); \ + } \ + *(v->_end) = x; \ + v->_end++; \ + } \ + \ + /* Removes the last element in the vector, effectively reducing the vector size by one and invalidating all iterators and references to - it. Note that the element is not freed. */ \ -static inline \ -BASE_TYPE VECTOR_TYPE##_pop_back(VECTOR_TYPE * v) \ -{ \ - cvector_assert(!VECTOR_TYPE##_empty(v)); \ - v->_end--; \ - return *(v->_end); \ -} \ - \ -/* Returns the first element in the vector container. This is not a - reference like in C++! */ \ -static inline \ -BASE_TYPE VECTOR_TYPE##_front(const VECTOR_TYPE * v) \ -{ \ - cvector_assert (!VECTOR_TYPE##_empty(v)); \ - return v->_begin[0]; \ -} \ - \ -/* Returns the last element in the vector container. This is not a - reference like in C++! */ \ -static inline \ -BASE_TYPE VECTOR_TYPE##_back(const VECTOR_TYPE * v) \ -{ \ - cvector_assert (!VECTOR_TYPE##_empty(v)); \ - return *(v->_end - 1); \ -} \ - \ -/* Returns an iterator (pointer) referring to the first element in the - vector container. */ \ -static inline \ -BASE_TYPE * VECTOR_TYPE##_begin(const VECTOR_TYPE * v) \ -{ return v->_begin; } \ - \ -/* Returns an iterator (pointer) referring to the past-the-end element - in the vector container. */ \ -static inline \ -BASE_TYPE * VECTOR_TYPE##_end(const VECTOR_TYPE * v) \ -{ return v->_end; } \ - \ -/* Returns the element at position pos. */ \ -static inline \ -BASE_TYPE VECTOR_TYPE##_at(const VECTOR_TYPE * v, size_t pos) \ -{ \ - cvector_assert(pos <= VECTOR_TYPE##_size(v)); \ - return v->_begin[pos]; \ -} \ - \ -/* Set the element at position pos to value e and return it. */ \ -static inline \ -BASE_TYPE VECTOR_TYPE##_set(const VECTOR_TYPE * v, size_t pos, BASE_TYPE e) \ -{ \ - cvector_assert(pos <= VECTOR_TYPE##_size(v)); \ - return (v->_begin[pos] = e); \ -} \ + it. Note that the element is not freed. */ \ + static inline BASE_TYPE VECTOR_TYPE##_pop_back(VECTOR_TYPE * v) \ + { \ + cvector_assert(!VECTOR_TYPE##_empty(v)); \ + v->_end--; \ + return *(v->_end); \ + } \ + \ + /* Returns the first element in the vector container. This is not a + reference like in C++! */ \ + static inline BASE_TYPE VECTOR_TYPE##_front(const VECTOR_TYPE * v) \ + { \ + cvector_assert(!VECTOR_TYPE##_empty(v)); \ + return v->_begin[0]; \ + } \ + \ + /* Returns the last element in the vector container. This is not a + reference like in C++! */ \ + static inline BASE_TYPE VECTOR_TYPE##_back(const VECTOR_TYPE * v) \ + { \ + cvector_assert(!VECTOR_TYPE##_empty(v)); \ + return *(v->_end - 1); \ + } \ + \ + /* Returns an iterator (pointer) referring to the first element in the + vector container. */ \ + static inline BASE_TYPE * VECTOR_TYPE##_begin(const VECTOR_TYPE * v) \ + { \ + return v->_begin; \ + } \ + \ + /* Returns an iterator (pointer) referring to the past-the-end element + in the vector container. */ \ + static inline BASE_TYPE * VECTOR_TYPE##_end(const VECTOR_TYPE * v) \ + { \ + return v->_end; \ + } \ + \ + /* Returns the element at position pos. */ \ + static inline BASE_TYPE VECTOR_TYPE##_at(const VECTOR_TYPE * v, \ + size_t pos) \ + { \ + cvector_assert(pos <= VECTOR_TYPE##_size(v)); \ + return v->_begin[pos]; \ + } \ + \ + /* Set the element at position pos to value e and return it. */ \ + static inline BASE_TYPE VECTOR_TYPE##_set(const VECTOR_TYPE * v, \ + size_t pos, BASE_TYPE e) \ + { \ + cvector_assert(pos <= VECTOR_TYPE##_size(v)); \ + return (v->_begin[pos] = e); \ + } #endif diff --git a/c/dominatedsets.c b/c/dominatedsets.c index 8c2bee36..7abce392 100644 --- a/c/dominatedsets.c +++ b/c/dominatedsets.c @@ -45,7 +45,7 @@ #include #include #include // for strndup() -#include // for getopt() +#include // for getopt() #include // for getopt_long() #include "epsilon.h" @@ -54,24 +54,25 @@ #define READ_INPUT_WRONG_INITIAL_DIM_ERRSTR "-o, --obj" #include "cmdline.h" -static void usage(void) +static void +usage(void) { printf("\n" - "Usage: %s [OPTIONS] [FILE...]\n\n", program_invocation_short_name); - - printf( -"Calculates the number of Pareto sets from one file that \n" -"dominate the Pareto sets of the other files. \n\n" - -"Options:\n" -OPTION_HELP_STR -OPTION_VERSION_STR -" -v, --verbose print some information (time, number of points, etc.) \n" -OPTION_QUIET_STR -" -p, --percentages print results also as percentages. \n" -" --no-check do not check nondominance of sets (faster but unsafe).\n" -OPTION_OBJ_STR -"\n"); + "Usage: %s [OPTIONS] [FILE...]\n\n", + program_invocation_short_name); + + printf("Calculates the number of Pareto sets from one file that " + " \n" + "dominate the Pareto sets of the other files. " + " \n\n" + + "Options:\n" OPTION_HELP_STR OPTION_VERSION_STR + " -v, --verbose print some information (time, number of " + "points, etc.) \n" OPTION_QUIET_STR + " -p, --percentages print results also as percentages. " + " \n" + " --no-check do not check nondominance of sets (faster but " + "unsafe).\n" OPTION_OBJ_STR "\n"); } @@ -81,30 +82,30 @@ static bool check_flag = true; // strnlen() is not available in C99. static inline size_t -x_strnlen(const char *s, size_t maxlen) +x_strnlen(const char * s, size_t maxlen) { size_t len = 0; - while (len < maxlen && s[len] != '\0') - len++; + while (len < maxlen && s[len] != '\0') len++; return len; } // strndup() is not available in C99. -static char * x_strndup(const char *s, size_t n) +static char * +x_strndup(const char * s, size_t n) { - size_t len = x_strnlen(s, n); // Find length up to n or end of string - char * new_str = malloc(len + 1); // Allocate memory (+1 for null terminator) - if (unlikely(new_str == NULL)) - return NULL; // malloc failed - memcpy(new_str, s, len); // Copy the string up to len - new_str[len] = '\0'; // Null-terminate + size_t len = x_strnlen(s, n); // Find length up to n or end of string + char * new_str = + malloc(len + 1); // Allocate memory (+1 for null terminator) + if (unlikely(new_str == NULL)) return NULL; // malloc failed + memcpy(new_str, s, len); // Copy the string up to len + new_str[len] = '\0'; // Null-terminate return new_str; } void -print_results (char **filenames, int numfiles, int *nruns, int **results) +print_results(char ** filenames, int numfiles, int * nruns, int ** results) { - int k,j; + int k, j; int max_col_len = 0; int max_filename_len = 0; int max_result = 0; @@ -112,76 +113,77 @@ print_results (char **filenames, int numfiles, int *nruns, int **results) /* longest filename. */ for (k = 0; k < numfiles; k++) - max_filename_len = MAX (max_filename_len, (int) strlen(filenames[k])); + max_filename_len = MAX(max_filename_len, (int)strlen(filenames[k])); /* longest number. */ for (k = 0; k < numfiles; k++) for (j = 0; j < numfiles; j++) - max_result = MAX (max_result, results[k][j]); + max_result = MAX(max_result, results[k][j]); snprintf(buffer, 32, "%d", max_result); buffer[31] = '\0'; - max_col_len = MAX (max_filename_len, (int) strlen(buffer)); + max_col_len = MAX(max_filename_len, (int)strlen(buffer)); printf("\n\n" "Number of times that is better than :\n"); /* Header row. */ - printf ("\n%*s", max_filename_len, ""); + printf("\n%*s", max_filename_len, ""); for (k = 0; k < numfiles; k++) { - printf (" %*s", max_col_len, filenames[k]); + printf(" %*s", max_col_len, filenames[k]); } for (k = 0; k < numfiles; k++) { printf("\n%*s", max_filename_len, filenames[k]); for (j = 0; j < numfiles; j++) { if (k == j) - printf (" %*s", max_col_len, "--"); + printf(" %*s", max_col_len, "--"); else - printf (" %*d", max_col_len, results[k][j]); + printf(" %*d", max_col_len, results[k][j]); } } - printf ("\n"); + printf("\n"); if (percentages_flag) { - max_col_len = MAX (max_col_len, (int) strlen("100.0")); + max_col_len = MAX(max_col_len, (int)strlen("100.0")); printf("\n\n" "Percentage of times that is better than :\n"); /* Header row. */ - printf ("\n%*s", max_filename_len, ""); + printf("\n%*s", max_filename_len, ""); for (k = 0; k < numfiles; k++) { - printf (" %*s", max_col_len, filenames[k]); + printf(" %*s", max_col_len, filenames[k]); } for (k = 0; k < numfiles; k++) { printf("\n%*s", max_filename_len, filenames[k]); for (j = 0; j < numfiles; j++) { if (k == j) - printf (" %*s", max_col_len, "--"); + printf(" %*s", max_col_len, "--"); else - printf (" %*.1f", max_col_len, - results[k][j] * 100.0 / (nruns[k] * nruns[j])); + printf(" %*.1f", max_col_len, + results[k][j] * 100.0 / (nruns[k] * nruns[j])); } } } - printf ("\n\n"); + printf("\n\n"); - printf ("Ranks:"); + printf("Ranks:"); for (k = 0; k < numfiles; k++) { int rank = 0; for (j = 0; j < numfiles; j++) { if (k == j) continue; rank += results[j][k]; } - printf (" %3d", rank); + printf(" %3d", rank); } - printf ("\n"); + printf("\n"); } static inline int -dominance (int dim, const double *a, const double *b, const signed char *minmax) +dominance(int dim, const double * a, const double * b, + const signed char * minmax) /*********************************************** return: O -> if a == b 1 -> if a dominates b @@ -193,51 +195,43 @@ dominance (int dim, const double *a, const double *b, const signed char *minmax) /* If any objective is worse, A can't dominate B. */ for (d = 0; d < dim; d++) - if ((minmax[d] < 0 && a[d] > b[d]) - || (minmax[d] > 0 && a[d] < b[d])) + if ((minmax[d] < 0 && a[d] > b[d]) || (minmax[d] > 0 && a[d] < b[d])) return -1; /* If any objective is better, then A dominates B. */ for (d = 0; d < dim; d++) - if ((minmax[d] < 0 && a[d] < b[d]) - || (minmax[d] > 0 && a[d] > b[d])) + if ((minmax[d] < 0 && a[d] < b[d]) || (minmax[d] > 0 && a[d] > b[d])) return 1; return 0; } -static int set_dominates (int dim, const signed char *minmax, - const double *points_x, int size_x, - const double *points_y, int size_y) +static int +set_dominates(int dim, const signed char * minmax, const double * points_x, + int size_x, const double * points_y, int size_y) { - bool x_dominates_y = false, - x_weakly_dominates_y = false; + bool x_dominates_y = false, x_weakly_dominates_y = false; for (int y = 0; y < size_y; y++) { x_weakly_dominates_y = false; for (int x = 0; x < size_x; x++) { - DEBUG2 ( - printf ("X:"); - vector_printf (points_x + x * dim, dim); - printf ("Y:"); - vector_printf (points_y + y * dim, dim); - ); - int result = dominance (dim, &points_x[x * dim], - &points_y[y * dim], minmax); + DEBUG2(printf("X:"); vector_printf(points_x + x * dim, dim); + printf("Y:"); vector_printf(points_y + y * dim, dim);); + int result = + dominance(dim, &points_x[x * dim], &points_y[y * dim], minmax); if (result == 1) { - DEBUG2(printf ("X dominates Y!\n")); + DEBUG2(printf("X dominates Y!\n")); x_weakly_dominates_y = true; x_dominates_y = true; break; } else if (result == 0) { - DEBUG2(printf ("X weakly dominates Y!\n")); + DEBUG2(printf("X weakly dominates Y!\n")); x_weakly_dominates_y = true; break; } } - if (!x_weakly_dominates_y) - break; + if (!x_weakly_dominates_y) break; } if (!x_weakly_dominates_y) @@ -249,14 +243,13 @@ static int set_dominates (int dim, const signed char *minmax, } int -pareto_better (int dim, const signed char *minmax, - const double *points_a, int size_a, - const double *points_b, int size_b) +pareto_better(int dim, const signed char * minmax, const double * points_a, + int size_a, const double * points_b, int size_b) { - int result = set_dominates (dim, minmax, points_a, size_a, points_b, size_b); + int result = set_dominates(dim, minmax, points_a, size_a, points_b, size_b); if (result == 1) { - DEBUG2 (printf ("Trying with B\n")); - result = set_dominates (dim, minmax, points_b, size_b, points_a, size_a); + DEBUG2(printf("Trying with B\n")); + result = set_dominates(dim, minmax, points_b, size_b, points_a, size_a); result = -result; if (result != 1) { DEBUG2(printf("A || B\n")); @@ -264,42 +257,36 @@ pareto_better (int dim, const signed char *minmax, } } - int result2 = epsilon_additive_ind ((dimension_t) dim, minmax, points_a, size_a, points_b, size_b); + int result2 = epsilon_additive_ind((dimension_t)dim, minmax, points_a, + size_a, points_b, size_b); - DEBUG2 ( - printf ("result = %d, result2 = %d\n", result, result2); - for (int a = 0; a < size_a; a++) { - vector_printf (points_a + a * dim, dim); - } - printf("\n\n"); - for (int b = 0; b < size_b; b++) { - vector_printf (points_b + b * dim, dim); - }); + DEBUG2( + printf("result = %d, result2 = %d\n", result, result2); + for (int a = 0; a < size_a; + a++) { vector_printf(points_a + a * dim, dim); } printf("\n\n"); + for (int b = 0; b < size_b; + b++) { vector_printf(points_b + b * dim, dim); }); if (result != result2) { - printf ("result = %d != result2 = %d\n", result, result2); + printf("result = %d != result2 = %d\n", result, result2); abort(); } return result; } void -cmpparetos (int dim, const signed char *minmax, - const double * points_a, int nruns_a, - const int *cumsizes_a, int *numbetter_a, - const double * points_b, int nruns_b, - const int *cumsizes_b, int *numbetter_b) +cmpparetos(int dim, const signed char * minmax, const double * points_a, + int nruns_a, const int * cumsizes_a, int * numbetter_a, + const double * points_b, int nruns_b, const int * cumsizes_b, + int * numbetter_b) { *numbetter_a = 0; *numbetter_b = 0; for (int a = 0, size_a = 0; a < nruns_a; a++) { for (int b = 0, size_b = 0; b < nruns_b; b++) { - int result = - pareto_better (dim, minmax, - points_a + (dim * size_a), - cumsizes_a[a] - size_a, - points_b + (dim * size_b), - cumsizes_b[b] - size_b); + int result = pareto_better( + dim, minmax, points_a + (dim * size_a), cumsizes_a[a] - size_a, + points_b + (dim * size_b), cumsizes_b[b] - size_b); if (result < 0) (*numbetter_a)++; else if (result > 0) @@ -311,35 +298,36 @@ cmpparetos (int dim, const signed char *minmax, } } -int main(int argc, char *argv[]) +int +main(int argc, char * argv[]) { - int *nruns = NULL; - int **cumsizes = NULL; - double **points = NULL; + int * nruns = NULL; + int ** cumsizes = NULL; + double ** points = NULL; int dim = 0; - char **filenames; + char ** filenames; int numfiles; - const signed char *minmax = NULL; + const signed char * minmax = NULL; int k, n, j; /* see the man page for getopt_long for an explanation of these fields */ static const char short_options[] = "hVvqpo:"; static const struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {"verbose", no_argument, NULL, 'v'}, - {"quiet", no_argument, NULL, 'q'}, - {"percentages",no_argument, NULL, 'p'}, - {"no-check", no_argument, NULL, 'c'}, - {"obj", required_argument, NULL, 'o'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {"verbose", no_argument, NULL, 'v'}, + {"quiet", no_argument, NULL, 'q'}, + {"percentages", no_argument, NULL, 'p'}, + {"no-check", no_argument, NULL, 'c'}, + {"obj", required_argument, NULL, 'o'}, {NULL, 0, NULL, 0} /* marks end of list */ }; set_program_invocation_short_name(argv[0]); int opt; /* it's actually going to hold a char */ int longopt_index; - while (0 < (opt = getopt_long(argc, argv, short_options, - long_options, &longopt_index))) { + while (0 < (opt = getopt_long(argc, argv, short_options, long_options, + &longopt_index))) { switch (opt) { case 'q': // --quiet verbose_flag = false; @@ -375,53 +363,50 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - filenames = malloc (sizeof(char *) * numfiles); - points = malloc (sizeof(double *) * numfiles); - nruns = malloc (sizeof(int) * numfiles); - cumsizes = malloc (sizeof(int *) * numfiles); + filenames = malloc(sizeof(char *) * numfiles); + points = malloc(sizeof(double *) * numfiles); + nruns = malloc(sizeof(int) * numfiles); + cumsizes = malloc(sizeof(int *) * numfiles); for (k = 0; k < numfiles; optind++, k++) { filenames[k] = argv[optind]; points[k] = NULL; cumsizes[k] = NULL; nruns[k] = 0; - handle_read_data_error( - read_double_data (filenames[k], &points[k], &dim, &cumsizes[k], &nruns[k]), - filenames[k]); + handle_read_data_error(read_double_data(filenames[k], &points[k], &dim, + &cumsizes[k], &nruns[k]), + filenames[k]); } /* Default minmax if not set yet. */ - if (minmax == NULL) - minmax = minmax_minimise((dimension_t) dim); + if (minmax == NULL) minmax = minmax_minimise((dimension_t)dim); /* Print filename substitutions. */ for (k = 0; k < numfiles; k++) { char buffer[32]; snprintf(buffer, 31, "f%d", k + 1); buffer[31] = '\0'; - char *p = x_strndup(buffer, 31); + char * p = x_strndup(buffer, 31); if (unlikely(!p)) fatal_error("%s:%d: malloc failed", __FILE__, __LINE__); - printf ("# %s: %s\n", p, filenames[k]); + printf("# %s: %s\n", p, filenames[k]); filenames[k] = p; } - printf ("\n"); + printf("\n"); /* Print some info about input files. */ for (k = 0; k < numfiles; k++) { - printf ("# %s: %d (%d", filenames[k], nruns[k], cumsizes[k][0]); - for (n = 1; n < nruns[k]; n++) - printf (", %d", cumsizes[k][n]); - printf (")\n"); + printf("# %s: %d (%d", filenames[k], nruns[k], cumsizes[k][0]); + for (n = 1; n < nruns[k]; n++) printf(", %d", cumsizes[k][n]); + printf(")\n"); } /* Print some info. */ - printf ("# objectives (%d): ", dim); + printf("# objectives (%d): ", dim); for (k = 0; k < dim; k++) { - printf ("%c", (minmax[k] < 0) ? '-' - : (minmax[k] > 0) ? '+' : 'i'); + printf("%c", (minmax[k] < 0) ? '-' : (minmax[k] > 0) ? '+' : 'i'); } - printf ("\n"); + printf("\n"); if (check_flag) { bool check_failed = false; @@ -429,40 +414,37 @@ int main(int argc, char *argv[]) for (k = 0; k < numfiles; k++) { int size = 0; for (n = 0; n < nruns[k]; n++) { - size_t failed_pos - = find_dominated_point (&points[k][dim * size], dim, - cumsizes[k][n] - size, minmax); + size_t failed_pos = find_dominated_point( + &points[k][dim * size], dim, cumsizes[k][n] - size, minmax); if (failed_pos < SIZE_MAX) { - fprintf (stderr, - "%s: %s: set %d: point %zu is dominated.\n", - program_invocation_short_name, - filenames[k], n, failed_pos); + fprintf(stderr, "%s: %s: set %d: point %zu is dominated.\n", + program_invocation_short_name, filenames[k], n, + failed_pos); check_failed = true; } - size = cumsizes[k][n]; + size = cumsizes[k][n]; } } if (check_failed) { - errprintf ("input must be a collection of nondominated sets."); - exit (EXIT_FAILURE); + errprintf("input must be a collection of nondominated sets."); + exit(EXIT_FAILURE); } } - int **results = malloc (sizeof(int) * numfiles * numfiles - + sizeof(int *) * numfiles); + int ** results = + malloc(sizeof(int) * numfiles * numfiles + sizeof(int *) * numfiles); for (k = 0; k < numfiles; k++) { - results[k] = (int *) (results + numfiles) + k * numfiles; - for (j = 0; j < numfiles; j++) - results[k][j] = -1; + results[k] = (int *)(results + numfiles) + k * numfiles; + for (j = 0; j < numfiles; j++) results[k][j] = -1; } for (k = 0; k < numfiles; k++) for (j = k + 1; j < numfiles; j++) - cmpparetos (dim, minmax, - points[k], nruns[k], cumsizes[k], &(results[k][j]), - points[j], nruns[j], cumsizes[j], &(results[j][k])); + cmpparetos(dim, minmax, points[k], nruns[k], cumsizes[k], + &(results[k][j]), points[j], nruns[j], cumsizes[j], + &(results[j][k])); - print_results (filenames, numfiles, nruns, results); + print_results(filenames, numfiles, nruns, results); if (verbose_flag) { } diff --git a/c/eaf.c b/c/eaf.c index 16e492b5..08b1caa5 100644 --- a/c/eaf.c +++ b/c/eaf.c @@ -27,14 +27,15 @@ #include "eaf.h" #ifndef DEBUG -#define DEBUG 0 +# define DEBUG 0 #endif #ifndef DEBUG_POLYGONS -#define DEBUG_POLYGONS 0 +# define DEBUG_POLYGONS 0 #endif -static int compare_x_asc (const void *p1, const void *p2) +static int +compare_x_asc(const void * p1, const void * p2) { objective_t x1 = **(objective_t **)p1; objective_t x2 = **(objective_t **)p2; @@ -42,31 +43,34 @@ static int compare_x_asc (const void *p1, const void *p2) return (x1 < x2) ? -1 : ((x1 > x2) ? 1 : 0); } -static int compare_y_desc (const void *p1, const void *p2) +static int +compare_y_desc(const void * p1, const void * p2) { - objective_t y1 = *(*(objective_t **)p1+1); - objective_t y2 = *(*(objective_t **)p2+1); + objective_t y1 = *(*(objective_t **)p1 + 1); + objective_t y2 = *(*(objective_t **)p2 + 1); return (y1 > y2) ? -1 : ((y1 < y2) ? 1 : 0); } static void -point2d_printf(FILE *stream, const objective_t x, const objective_t y) +point2d_printf(FILE * stream, const objective_t x, const objective_t y) { - fprintf(stream, point_printf_format point_printf_sep point_printf_format, x, y); + fprintf(stream, point_printf_format point_printf_sep point_printf_format, x, + y); } static void -point_printf(FILE *stream, const objective_t *p, int nobj) +point_printf(FILE * stream, const objective_t * p, int nobj) { point2d_printf(stream, p[0], p[1]); for (int k = 2; k < nobj; k++) - fprintf (stream, point_printf_sep point_printf_format, p[k]); + fprintf(stream, point_printf_sep point_printf_format, p[k]); } -eaf_t * eaf_create (int nobj, int nruns, int npoints) +eaf_t * +eaf_create(int nobj, int nruns, int npoints) { - eaf_t *eaf = MOOCORE_MALLOC(1, eaf_t); + eaf_t * eaf = MOOCORE_MALLOC(1, eaf_t); eaf->nruns = nruns; eaf->size = 0; eaf->nreallocs = 0; @@ -80,41 +84,42 @@ eaf_t * eaf_create (int nobj, int nruns, int npoints) return eaf; } -void eaf_delete (eaf_t * eaf) +void +eaf_delete(eaf_t * eaf) { - free (eaf->data); - free (eaf->bit_attained); - free (eaf); + free(eaf->data); + free(eaf->bit_attained); + free(eaf); } -void eaf_free(eaf_t ** eaf, int nruns) +void +eaf_free(eaf_t ** eaf, int nruns) { - for (int k = 0; k < nruns; k++) - eaf_delete (eaf[k]); + for (int k = 0; k < nruns; k++) eaf_delete(eaf[k]); free(eaf); } -void eaf_realloc(eaf_t * eaf, size_t nobj) +void +eaf_realloc(eaf_t * eaf, size_t nobj) { const int nruns = eaf->nruns; - eaf->data = realloc (eaf->data, - sizeof(objective_t) * nobj * eaf->maxsize); + eaf->data = realloc(eaf->data, sizeof(objective_t) * nobj * eaf->maxsize); assert(eaf->data); - eaf->bit_attained = realloc (eaf->bit_attained, - bit_array_bytesize(nruns) * eaf->maxsize); + eaf->bit_attained = + realloc(eaf->bit_attained, bit_array_bytesize(nruns) * eaf->maxsize); assert(eaf->bit_attained); } objective_t * -eaf_store_point_help (eaf_t * eaf, int nobj, - const int *save_attained) +eaf_store_point_help(eaf_t * eaf, int nobj, const int * save_attained) { const int nruns = eaf->nruns; if (eaf->size == eaf->maxsize) { - assert (eaf->size < INT_MAX / 2); + assert(eaf->size < INT_MAX / 2); //size_t old_maxsize = eaf->maxsize; - eaf->maxsize = (size_t) ((double) eaf->maxsize * (1.0 + 1.0 / pow(2, eaf->nreallocs / 4.0))); + eaf->maxsize = (size_t)((double)eaf->maxsize * + (1.0 + 1.0 / pow(2, eaf->nreallocs / 4.0))); eaf->maxsize += 100; // At least we increase it by 100 points /* fprintf(stderr,"maxsize (%d): %ld -> %ld\n", eaf->nreallocs, */ /* old_maxsize, eaf->maxsize); */ @@ -124,13 +129,14 @@ eaf_store_point_help (eaf_t * eaf, int nobj, } // FIXME: provide a bit_array function to do this. for (int k = 0; k < nruns; k++) { - bit_array_set(bit_array_offset(eaf->bit_attained, eaf->size, nruns), k, (bool) save_attained[k]); + bit_array_set(bit_array_offset(eaf->bit_attained, eaf->size, nruns), k, + (bool)save_attained[k]); } return eaf->data + nobj * eaf->size; } static void -eaf_adjust_memory (eaf_t * eaf, int nobj) +eaf_adjust_memory(eaf_t * eaf, int nobj) { if (eaf->size < eaf->maxsize) { //fprintf(stderr,"reduce size: %ld -> %ld\n", eaf->maxsize, eaf->size); @@ -140,78 +146,79 @@ eaf_adjust_memory (eaf_t * eaf, int nobj) } static void -eaf_store_point_2d (eaf_t * eaf, objective_t x, objective_t y, - const int *save_attained) +eaf_store_point_2d(eaf_t * eaf, objective_t x, objective_t y, + const int * save_attained) { const int nobj = 2; - objective_t * pos = eaf_store_point_help (eaf, nobj, save_attained); + objective_t * pos = eaf_store_point_help(eaf, nobj, save_attained); pos[0] = x; pos[1] = y; eaf->size++; } static void -eaf_print_line (FILE *coord_file, FILE *indic_file, FILE *diff_file, - const objective_t *x, int nobj, - const bit_array *attained, int nruns) +eaf_print_line(FILE * coord_file, FILE * indic_file, FILE * diff_file, + const objective_t * x, int nobj, const bit_array * attained, + int nruns) { if (coord_file) { point_printf(coord_file, x, nobj); - fprintf (coord_file, - (coord_file == indic_file) || (coord_file == diff_file) - ? "\t" : "\n"); + fprintf(coord_file, + (coord_file == indic_file) || (coord_file == diff_file) ? "\t" + : "\n"); } int k, count1 = 0, count2 = 0; if (indic_file) { - fprintf (indic_file, "%d", - bit_array_get(attained, 0) ? (count1++,1) : 0); - for (k = 1; k < nruns/2; k++) - fprintf (indic_file, " %d", - bit_array_get(attained, k) ? (count1++,1) : 0); - for (k = nruns/2; k < nruns; k++) - fprintf (indic_file, " %d", - bit_array_get(attained, k) ? (count2++,1) : 0); - - fprintf (indic_file, (indic_file == diff_file) ? "\t" : "\n"); + fprintf(indic_file, "%d", + bit_array_get(attained, 0) ? (count1++, 1) : 0); + for (k = 1; k < nruns / 2; k++) + fprintf(indic_file, " %d", + bit_array_get(attained, k) ? (count1++, 1) : 0); + for (k = nruns / 2; k < nruns; k++) + fprintf(indic_file, " %d", + bit_array_get(attained, k) ? (count2++, 1) : 0); + + fprintf(indic_file, (indic_file == diff_file) ? "\t" : "\n"); } else if (diff_file) { - attained_left_right(attained, nruns/2, nruns, &count1, &count2); + attained_left_right(attained, nruns / 2, nruns, &count1, &count2); } - if (diff_file) - fprintf (diff_file,"%d %d\n", count1, count2); + if (diff_file) fprintf(diff_file, "%d %d\n", count1, count2); } /* Print one attainment surface of the EAF. */ void -eaf_print_attsurf (const eaf_t * eaf, int nobj, FILE *coord_file, FILE *indic_file, FILE *diff_file) +eaf_print_attsurf(const eaf_t * eaf, int nobj, FILE * coord_file, + FILE * indic_file, FILE * diff_file) { for (size_t i = 0; i < eaf->size; i++) { - const objective_t *p = eaf->data + i * nobj; + const objective_t * p = eaf->data + i * nobj; /* bit_array_fprintf(stderr, eaf->bit_attained, eaf->nruns * eaf->size); */ - eaf_print_line (coord_file, indic_file, diff_file, - p, nobj, - bit_array_offset(eaf->bit_attained, i, eaf->nruns), - eaf->nruns); + eaf_print_line(coord_file, indic_file, diff_file, p, nobj, + bit_array_offset(eaf->bit_attained, i, eaf->nruns), + eaf->nruns); } } _attr_maybe_unused static void -fprint_set2d (FILE *stream, const objective_t * const *data, int ntotal) +fprint_set2d(FILE * stream, const objective_t * const * data, int ntotal) { for (int k = 0; k < ntotal; k++) - fprintf (stream, "%6d: " point_printf_format " " point_printf_format "\n", k, - data[k][0], data[k][1]); + fprintf(stream, + "%6d: " point_printf_format " " point_printf_format "\n", k, + data[k][0], data[k][1]); } void -eaf2matrix_R (double *rmat, eaf_t * const * eaf, int nobj, int totalpoints, - const double * percentile, int nlevels) +eaf2matrix_R(double * rmat, eaf_t * const * eaf, int nobj, int totalpoints, + const double * percentile, int nlevels) { int pos = 0; for (int k = 0; k < nlevels; k++) { size_t npoints = eaf[k]->size; - double p = percentile ? percentile[k] : level2percentile(k+1, nlevels); + double p = + percentile ? percentile[k] : level2percentile(k + 1, nlevels); for (size_t i = 0; i < npoints; i++) { for (int j = 0; j < nobj; j++) { rmat[pos + j * totalpoints] = eaf[k]->data[j + i * nobj]; @@ -223,14 +230,16 @@ eaf2matrix_R (double *rmat, eaf_t * const * eaf, int nobj, int totalpoints, } void -eaf2matrix (double *rmat, eaf_t * const * eaf, int nobj, _attr_maybe_unused int totalpoints, - const double * percentile, int nlevels) +eaf2matrix(double * rmat, eaf_t * const * eaf, int nobj, + _attr_maybe_unused int totalpoints, const double * percentile, + int nlevels) { int pos = 0; int ncol = nobj + 1; for (int k = 0; k < nlevels; k++) { size_t npoints = eaf[k]->size; - double p = percentile ? percentile[k] : level2percentile(k+1, nlevels); + double p = + percentile ? percentile[k] : level2percentile(k + 1, nlevels); for (size_t i = 0; i < npoints; i++) { for (int j = 0; j < nobj; j++) { rmat[j + pos * ncol] = eaf[k]->data[j + i * nobj]; @@ -242,15 +251,16 @@ eaf2matrix (double *rmat, eaf_t * const * eaf, int nobj, _attr_maybe_unused int } double * -eaf_compute_matrix(int *eaf_npoints, double * data, int nobj, const int *cumsizes, int nruns, - const double * percentile, int nlevels) +eaf_compute_matrix(int * eaf_npoints, double * data, int nobj, + const int * cumsizes, int nruns, const double * percentile, + int nlevels) { - int *level = levels_from_percentiles(percentile, nlevels, nruns); - eaf_t **eaf = attsurf(data, nobj, cumsizes, nruns, level, nlevels); - free (level); + int * level = levels_from_percentiles(percentile, nlevels, nruns); + eaf_t ** eaf = attsurf(data, nobj, cumsizes, nruns, level, nlevels); + free(level); - int totalpoints = eaf_totalpoints (eaf, nlevels); - double *mat = malloc(sizeof(double) * totalpoints * (nobj + 1)); + int totalpoints = eaf_totalpoints(eaf, nlevels); + double * mat = malloc(sizeof(double) * totalpoints * (nobj + 1)); eaf2matrix(mat, eaf, nobj, totalpoints, percentile, nlevels); eaf_free(eaf, nlevels); *eaf_npoints = totalpoints; @@ -276,74 +286,63 @@ eaf_compute_matrix(int *eaf_npoints, double * data, int nobj, const int *cumsize */ eaf_t ** -eaf2d (const objective_t *data, const int *cumsize, int nruns, - const int *attlevel, const int nlevels) +eaf2d(const objective_t * data, const int * cumsize, int nruns, + const int * attlevel, const int nlevels) { const int nobj = 2; - eaf_t **eaf; + eaf_t ** eaf; const objective_t **datax, **datay; /* used to access the data sorted according to x or y */ const int ntotal = cumsize[nruns - 1]; /* total number of points in data */ - int *runtab; + int * runtab; int *attained, *save_attained; int k, j, l; /* Access to the data is made via two arrays of pointers: ix, iy These are sorted, to allow for dimension sweeping */ - datax = malloc (ntotal * sizeof(objective_t *)); - datay = malloc (ntotal * sizeof(objective_t *)); + datax = malloc(ntotal * sizeof(objective_t *)); + datay = malloc(ntotal * sizeof(objective_t *)); - for (k = 0; k < ntotal ; k++) - datax[k] = datay[k] = data + nobj * k; + for (k = 0; k < ntotal; k++) datax[k] = datay[k] = data + nobj * k; DEBUG1(/* Sanity check. */ - for (k = 1; k < nruns ; k++) - assert(cumsize[k-1] < cumsize[k]); - ); + for (k = 1; k < nruns; k++) assert(cumsize[k - 1] < cumsize[k]);); - DEBUG2( - fprintf (stderr, "Original data:\n"); - fprint_set2d (stderr, datax, ntotal); - ); + DEBUG2(fprintf(stderr, "Original data:\n"); + fprint_set2d(stderr, datax, ntotal);); - qsort (datax, ntotal, sizeof(*datax), &compare_x_asc); - qsort (datay, ntotal, sizeof(*datay), &compare_y_desc); + qsort(datax, ntotal, sizeof(*datax), &compare_x_asc); + qsort(datay, ntotal, sizeof(*datay), &compare_y_desc); - DEBUG2( - fprintf (stderr, "Sorted data (x):\n"); - fprint_set2d (stderr, datax, ntotal); - fprintf (stderr, "Sorted data (y):\n"); - fprint_set2d (stderr, datay, ntotal); - ); + DEBUG2(fprintf(stderr, "Sorted data (x):\n"); + fprint_set2d(stderr, datax, ntotal); + fprintf(stderr, "Sorted data (y):\n"); + fprint_set2d(stderr, datay, ntotal);); /* Setup a lookup table to go from a point to the approximation set (run) to which it belongs. */ - runtab = malloc (ntotal * sizeof(int)); + runtab = malloc(ntotal * sizeof(int)); for (k = 0, j = 0; k < ntotal; k++) { - if (k == cumsize[j]) - j++; + if (k == cumsize[j]) j++; runtab[k] = j; } - DEBUG2( - fprintf (stderr, "Runtab:\n"); - for (k = 0; k < ntotal; k++) - fprintf (stderr, "%6d: %6d\n", k, runtab[k]); - ); + DEBUG2(fprintf(stderr, "Runtab:\n"); for (k = 0; k < ntotal; k++) + fprintf(stderr, "%6d: %6d\n", k, runtab[k]);); /* Setup tables to keep attainment statistics. In particular, save_attained is needed to cope with repeated values on the same axis. */ - attained = malloc (nruns * sizeof(int)); - save_attained = malloc (nruns * sizeof(int)); - eaf = malloc(nlevels * sizeof(eaf_t*)); + attained = malloc(nruns * sizeof(int)); + save_attained = malloc(nruns * sizeof(int)); + eaf = malloc(nlevels * sizeof(eaf_t *)); for (l = 0; l < nlevels; l++) { - eaf[l] = eaf_create (nobj, nruns, ntotal); + eaf[l] = eaf_create(nobj, nruns, ntotal); int level = attlevel[l]; int x = 0; int y = 0; @@ -359,23 +358,20 @@ eaf2d (const objective_t *data, const int *cumsize, int nruns, do { /* Move right until desired attainment level is reached */ while (x < ntotal - 1 && - (nattained < level || datax[x][0] == datax[x+1][0])) { + (nattained < level || datax[x][0] == datax[x + 1][0])) { x++; if (datax[x][1] <= datay[y][1]) { - run = runtab[(datax[x] - data)/nobj]; - if (!attained[run]) - nattained++; + run = runtab[(datax[x] - data) / nobj]; + if (!attained[run]) nattained++; attained[run]++; } } #if DEBUG > 1 - for (k = 0; k < nruns; k++) - fprintf (stderr, "%d ", attained[k]); - fprintf (stderr, "\n"); + for (k = 0; k < nruns; k++) fprintf(stderr, "%d ", attained[k]); + fprintf(stderr, "\n"); #endif - if (nattained < level) - continue; + if (nattained < level) continue; /* Now move down until desired attainment level is no longer reached. */ @@ -383,28 +379,27 @@ eaf2d (const objective_t *data, const int *cumsize, int nruns, /* If there are repeated values along the y axis, we need to remember where we are. */ /*save_nattained = nattained;*/ - memcpy (save_attained, attained, nruns * sizeof(*attained)); + memcpy(save_attained, attained, nruns * sizeof(*attained)); do { if (datay[y][0] <= datax[x][0]) { - run = runtab[(datay[y] - data)/nobj]; + run = runtab[(datay[y] - data) / nobj]; attained[run]--; - if (!attained[run]) - nattained--; + if (!attained[run]) nattained--; } #if DEBUG > 1 for (k = 0; k < nruns; k++) - fprintf (stderr, "%d ", attained[k]); - fprintf (stderr, "\n"); + fprintf(stderr, "%d ", attained[k]); + fprintf(stderr, "\n"); #endif y++; } while (y < ntotal && datay[y][1] == datay[y - 1][1]); } while (nattained >= level && y < ntotal); - assert (nattained < level); + assert(nattained < level); - eaf_store_point_2d (eaf[l], datax[x][0], datay[y - 1][1], - save_attained); + eaf_store_point_2d(eaf[l], datax[x][0], datay[y - 1][1], + save_attained); } while (x < ntotal - 1 && y < ntotal); eaf_adjust_memory(eaf[l], nobj); @@ -420,12 +415,15 @@ eaf2d (const objective_t *data, const int *cumsize, int nruns, #if DEBUG_POLYGONS > 0 -#define PRINT_POINT(X,Y,C) do { \ - fprintf(stdout, "PRINT_POINT:"); point2d_printf(stdout, X, Y); \ - if (C != INT_MIN) fprintf(stdout, "\t%d", C); \ - fprintf(stdout, "\n"); } while(0) +# define PRINT_POINT(X, Y, C) \ + do { \ + fprintf(stdout, "PRINT_POINT:"); \ + point2d_printf(stdout, X, Y); \ + if (C != INT_MIN) fprintf(stdout, "\t%d", C); \ + fprintf(stdout, "\n"); \ + } while (0) #else -#define PRINT_POINT(X,Y,C) (void)0 +# define PRINT_POINT(X, Y, C) (void)0 #endif static int @@ -433,18 +431,19 @@ eaf_max_size(eaf_t * const * eaf, int nlevels) { size_t max_size = 0; for (int a = 0; a < nlevels; a++) { - if (max_size < eaf[a]->size) - max_size = eaf[a]->size; + if (max_size < eaf[a]->size) max_size = eaf[a]->size; } - return (int) max_size; + return (int)max_size; } static int eaf_diff_color(const eaf_t * eaf, size_t k, int nruns) { - const bit_array *bit_attained = bit_array_offset(eaf->bit_attained, k, nruns); + const bit_array * bit_attained = + bit_array_offset(eaf->bit_attained, k, nruns); int count_left, count_right; - attained_left_right (bit_attained, nruns/2, nruns, &count_left, &count_right); + attained_left_right(bit_attained, nruns / 2, nruns, &count_left, + &count_right); return count_left - count_right; } @@ -457,18 +456,16 @@ init_colors(int * color, const eaf_t * eaf, size_t eaf_size, int nruns) } static const objective_t * -next_polygon(const objective_t *src, int nobj, const objective_t * end) +next_polygon(const objective_t * src, int nobj, const objective_t * end) { - while (src < end && *src != objective_MIN) - src += nobj; + while (src < end && *src != objective_MIN) src += nobj; src += nobj; return src; } static void -min_max_in_objective(const objective_t *v, - int nobj, int k, - objective_t *min_ref, objective_t *max_ref) +min_max_in_objective(const objective_t * v, int nobj, int k, + objective_t * min_ref, objective_t * max_ref) { assert(k < nobj); assert(v[k] != objective_MIN); // Empty polygon? @@ -486,7 +483,7 @@ min_max_in_objective(const objective_t *v, } static bool -polygon_dominates_point(const objective_t *p, const objective_t *x, int nobj) +polygon_dominates_point(const objective_t * p, const objective_t * x, int nobj) { assert(x[0] != objective_MIN); while (p[0] != objective_MIN) { @@ -503,7 +500,8 @@ polygon_dominates_point(const objective_t *p, const objective_t *x, int nobj) } static bool -polygon_dominates_any_point(const objective_t *a, const objective_t *b, int nobj) +polygon_dominates_any_point(const objective_t * a, const objective_t * b, + int nobj) { while (b[0] != objective_MIN) { if (polygon_dominates_point(a, b, nobj)) return true; @@ -513,7 +511,7 @@ polygon_dominates_any_point(const objective_t *a, const objective_t *b, int nobj } static bool -polygons_intersect(const objective_t *a, const objective_t *b, int nobj) +polygons_intersect(const objective_t * a, const objective_t * b, int nobj) { for (int k = 0; k < nobj; k++) { objective_t min_a, max_a, min_b, max_b; @@ -526,12 +524,13 @@ polygons_intersect(const objective_t *a, const objective_t *b, int nobj) // Two orthogonal polygons intersect if there is a corner of A that is // dominated by a corner of B and there is a corner of B that is dominated // by a corner of A - return polygon_dominates_any_point(a, b, nobj) && polygon_dominates_any_point(b, a, nobj); + return polygon_dominates_any_point(a, b, nobj) && + polygon_dominates_any_point(b, a, nobj); } _attr_maybe_unused static void -polygon_print(const objective_t *p, int nobj) +polygon_print(const objective_t * p, int nobj) { while (p[0] != objective_MIN) { point_printf(stderr, p, nobj); @@ -543,7 +542,7 @@ polygon_print(const objective_t *p, int nobj) } _attr_maybe_unused static void -eaf_check_polygons(eaf_polygon_t *p, int nobj) +eaf_check_polygons(eaf_polygon_t * p, int nobj) { // This only works for 2 objectives. assert(nobj == 2); @@ -573,39 +572,45 @@ eaf_check_polygons(eaf_polygon_t *p, int nobj) // same color as the polygon. //TODO - - } /* Produce a polygon suitable to be plotted by the polygon function in R. */ eaf_polygon_t * -eaf_compute_polygon (eaf_t **eaf, int nobj, int nlevels) +eaf_compute_polygon(eaf_t ** eaf, int nobj, int nlevels) { -/* FIXME: Don't add anything if color_0 == 0 */ - -#define POLY_SIZE_CHECK() \ - do { _poly_size_check--; assert(_poly_size_check >= 4); \ - assert(_poly_size_check % 2 == 0); _poly_size_check = 0; } while(0) -#define eaf_point(A,K) (eaf[(A)]->data + (K) * nobj) -#define push_point_color(X, Y, C) \ - do { vector_objective_push_back (&polygon->xy, (X)); \ - vector_objective_push_back (&polygon->xy, (Y)); \ - _poly_size_check++; PRINT_POINT(X,Y, C); \ - } while(0) - -#define push_point(X, Y) push_point_color(X,Y, INT_MIN) + /* FIXME: Don't add anything if color_0 == 0 */ + +#define POLY_SIZE_CHECK() \ + do { \ + _poly_size_check--; \ + assert(_poly_size_check >= 4); \ + assert(_poly_size_check % 2 == 0); \ + _poly_size_check = 0; \ + } while (0) +#define eaf_point(A, K) (eaf[(A)]->data + (K) * nobj) +#define push_point_color(X, Y, C) \ + do { \ + vector_objective_push_back(&polygon->xy, (X)); \ + vector_objective_push_back(&polygon->xy, (Y)); \ + _poly_size_check++; \ + PRINT_POINT(X, Y, C); \ + } while (0) + +#define push_point(X, Y) push_point_color(X, Y, INT_MIN) #if DEBUG_POLYGONS > 0 -#define EXPENSIVE_CHECK_POLYGONS() eaf_check_polygons(polygon, nobj) +# define EXPENSIVE_CHECK_POLYGONS() eaf_check_polygons(polygon, nobj) #else -#define EXPENSIVE_CHECK_POLYGONS() (void)0 +# define EXPENSIVE_CHECK_POLYGONS() (void)0 #endif -#define polygon_close(COLOR) do { \ - vector_int_push_back (&polygon->col, COLOR); \ - push_point_color(objective_MIN, objective_MIN, COLOR); \ - POLY_SIZE_CHECK(); EXPENSIVE_CHECK_POLYGONS(); \ - } while(0) +#define polygon_close(COLOR) \ + do { \ + vector_int_push_back(&polygon->col, COLOR); \ + push_point_color(objective_MIN, objective_MIN, COLOR); \ + POLY_SIZE_CHECK(); \ + EXPENSIVE_CHECK_POLYGONS(); \ + } while (0) _attr_maybe_unused int _poly_size_check = 0; int nruns = eaf[0]->nruns; @@ -615,13 +620,13 @@ eaf_compute_polygon (eaf_t **eaf, int nobj, int nlevels) int max_size = eaf_max_size(eaf, nlevels); int * color = MOOCORE_MALLOC(max_size, int); eaf_polygon_t * polygon = MOOCORE_MALLOC(1, eaf_polygon_t); - vector_objective_ctor (&polygon->xy, max_size); - vector_int_ctor (&polygon->col, max_size); + vector_objective_ctor(&polygon->xy, max_size); + vector_int_ctor(&polygon->col, max_size); for (int b = 1; b < nlevels; b++) { const int a = b - 1; - const int eaf_a_size = (int) eaf[a]->size; - const int eaf_b_size = (int) eaf[b]->size; + const int eaf_a_size = (int)eaf[a]->size; + const int eaf_b_size = (int)eaf[b]->size; init_colors(color, eaf[a], eaf_a_size, nruns); /* Find color transitions along the EAF level set. */ @@ -634,10 +639,9 @@ eaf_compute_polygon (eaf_t **eaf, int nobj, int nlevels) int kb = last_b + 1; // Find a point in a that does not overlap with a point in b while (ka < eaf_a_size && kb < eaf_b_size) { - pka = eaf_point (a, ka); - pkb = eaf_point (b, kb); - if (pkb[0] != pka[0]) - break; + pka = eaf_point(a, ka); + pkb = eaf_point(b, kb); + if (pkb[0] != pka[0]) break; // They overlap in x, so we will skip kb, remember it. topleft_y = pkb[1]; last_b = kb; @@ -645,7 +649,8 @@ eaf_compute_polygon (eaf_t **eaf, int nobj, int nlevels) /* Ignore points that exactly overlap. */ // FIXME: This should not happen, but it does. We should remove these points. // assert(false); - ka++; kb++; + ka++; + kb++; } else { /* b intersects a above pka. */ assert(pkb[1] > pka[1]); @@ -655,36 +660,34 @@ eaf_compute_polygon (eaf_t **eaf, int nobj, int nlevels) } /* Everything in A was overlapping. */ - if (ka == eaf_a_size) - break; + if (ka == eaf_a_size) break; objective_t prev_pka_y = topleft_y; int color_0 = color[ka]; /* Print points and corners until we reach a different color. */ do { - pka = eaf_point (a, ka); + pka = eaf_point(a, ka); /* Find the point in B not above the current point in A. */ while (kb < eaf_b_size) { - pkb = eaf_point (b, kb); + pkb = eaf_point(b, kb); assert(pkb[0] > pka[0]); - if (pkb[1] <= pka[1]) - break; + if (pkb[1] <= pka[1]) break; kb++; } assert(pka[1] < prev_pka_y); - push_point (pka[0], prev_pka_y); - push_point (pka[0], pka[1]); + push_point(pka[0], prev_pka_y); + push_point(pka[0], pka[1]); prev_pka_y = pka[1]; ka++; if (kb < eaf_b_size && ka < eaf_a_size) { - const objective_t * pka_next = eaf_point (a, ka); - assert (pkb[0] > pka[0]); - assert (pkb[1] <= pka[1]); + const objective_t * pka_next = eaf_point(a, ka); + assert(pkb[0] > pka[0]); + assert(pkb[1] <= pka[1]); if (pkb[0] <= pka_next[0]) { /* If B intersects with A, stop here. */ assert(pkb[1] == pka[1] || pkb[0] == pka_next[0]); - assert (prev_pka_y >= pkb[1]); + assert(prev_pka_y >= pkb[1]); break; } } @@ -693,7 +696,7 @@ eaf_compute_polygon (eaf_t **eaf, int nobj, int nlevels) /* pka is the point before changing color, but ka is the position after. */ - if (ka == eaf_a_size) {/* We reached the end of eaf_a */ + if (ka == eaf_a_size) { /* We reached the end of eaf_a */ /* We don't have to go down the other side since eaf_a completely dominates eaf_b, so just start by the end. */ @@ -701,20 +704,20 @@ eaf_compute_polygon (eaf_t **eaf, int nobj, int nlevels) /* The last point we skipped was the last point, so there is nothing on the other side, just create two points in the infinity. */ - push_point (objective_MAX, pka[1]); - push_point (objective_MAX, topleft_y); + push_point(objective_MAX, pka[1]); + push_point(objective_MAX, topleft_y); assert(topleft_y > pka[1]); } else { kb = eaf_b_size - 1; pkb = eaf_point(b, kb); - assert (pkb[1] >= pka[1]); + assert(pkb[1] >= pka[1]); if (pkb[1] > pka[1]) { // Create two points in the infinity to jump from a to b (turn the corner). /* If pkb is above pkda, then it may happen that pkb[0] <= pka[0] if pkb is dominated by a previous pka. */ - push_point (objective_MAX, pka[1]); - push_point (objective_MAX, pkb[1]); - assert (pkb[1] <= topleft_y); + push_point(objective_MAX, pka[1]); + push_point(objective_MAX, pkb[1]); + assert(pkb[1] <= topleft_y); } else { // If they are at the same y-level, then pka must be to // the left, otherwise we should have found the @@ -723,57 +726,57 @@ eaf_compute_polygon (eaf_t **eaf, int nobj, int nlevels) } /* Now print in reverse. */ objective_t prev_pkb_x = pkb[0]; - push_point (pkb[0], pkb[1]); + push_point(pkb[0], pkb[1]); kb--; while (kb > last_b) { pkb = eaf_point(b, kb); - assert (pkb[1] > pka[1]); // pkb cannot be below pka - push_point (prev_pkb_x, pkb[1]); - push_point (pkb[0], pkb[1]); + assert(pkb[1] > pka[1]); // pkb cannot be below pka + push_point(prev_pkb_x, pkb[1]); + push_point(pkb[0], pkb[1]); prev_pkb_x = pkb[0]; kb--; } - push_point (pkb[0], topleft_y); - assert (topleft_y > pkb[1]); + push_point(pkb[0], topleft_y); + assert(topleft_y > pkb[1]); } /* last_b = eaf_b_size - 1; */ polygon_close(color_0); /* DONE */ - break; /* Really done! */ + break; /* Really done! */ } else { if (kb == eaf_b_size) { - assert (pka[1] < topleft_y); + assert(pka[1] < topleft_y); /* There is nothing on the other side, just create two points in the infinity. */ - push_point (objective_MAX, pka[1]); - push_point (objective_MAX, topleft_y); + push_point(objective_MAX, pka[1]); + push_point(objective_MAX, topleft_y); last_b = eaf_b_size - 1; } else { // This polygon is bounded above by eaf_b from last_b up to kb. - assert (kb < eaf_b_size); - pkb = eaf_point (b, kb); + assert(kb < eaf_b_size); + pkb = eaf_point(b, kb); // If we have not finished eaf_b is because pkb is not above pka - assert (pkb[1] <= pka[1]); - assert (pkb[0] != pka[0]); + assert(pkb[1] <= pka[1]); + assert(pkb[0] != pka[0]); /* If pkb and pka are in the same horizontal, pkb does not affect the next polygon. Otherwise, it does. */ int save_last_b = (pkb[1] == pka[1]) ? kb : kb - 1; /* Now print eaf_b in reverse. */ objective_t prev_pkb_x = pkb[0]; - push_point (pkb[0], pka[1]); + push_point(pkb[0], pka[1]); kb--; while (kb > last_b) { - pkb = eaf_point (b, kb); + pkb = eaf_point(b, kb); // pkb must be above pka or we would have found the // intersection earlier. - assert (pkb[1] > pka[1]); - push_point (prev_pkb_x, pkb[1]); - push_point (pkb[0], pkb[1]); + assert(pkb[1] > pka[1]); + push_point(prev_pkb_x, pkb[1]); + push_point(pkb[0], pkb[1]); prev_pkb_x = pkb[0]; kb--; } - push_point (pkb[0], topleft_y); - assert (topleft_y > pkb[1]); + push_point(pkb[0], topleft_y); + assert(topleft_y > pkb[1]); last_b = save_last_b; } polygon_close(color_0); /* DONE */ @@ -782,7 +785,7 @@ eaf_compute_polygon (eaf_t **eaf, int nobj, int nlevels) } } } - free (color); + free(color); #if DEBUG >= 1 eaf_check_polygons(polygon, nobj); // This is slow with lots of polygons #endif @@ -793,7 +796,7 @@ eaf_compute_polygon (eaf_t **eaf, int nobj, int nlevels) much simpler, but it produces artifacts when plotted with the polygon function in R. */ eaf_polygon_t * -eaf_compute_polygon_old (eaf_t **eaf, int nobj, int nlevels) +eaf_compute_polygon_old(eaf_t ** eaf, int nobj, int nlevels) { _attr_maybe_unused int _poly_size_check = 0; int max_size = eaf_max_size(eaf, nlevels); @@ -802,13 +805,13 @@ eaf_compute_polygon_old (eaf_t **eaf, int nobj, int nlevels) int * color = MOOCORE_MALLOC(max_size, int); eaf_polygon_t * polygon = MOOCORE_MALLOC(1, eaf_polygon_t); - vector_objective_ctor (&polygon->xy, max_size); - vector_int_ctor (&polygon->col, max_size); + vector_objective_ctor(&polygon->xy, max_size); + vector_int_ctor(&polygon->col, max_size); for (int b = 1; b < nlevels; b++) { const int a = b - 1; - const int eaf_a_size = (int) eaf[a]->size; - const int eaf_b_size = (int) eaf[a + 1]->size; + const int eaf_a_size = (int)eaf[a]->size; + const int eaf_b_size = (int)eaf[a + 1]->size; init_colors(color, eaf[a], eaf_a_size, nruns); /* Find color transitions along the EAF level set. */ int last_b = -1; @@ -821,16 +824,16 @@ eaf_compute_polygon_old (eaf_t **eaf, int nobj, int nlevels) /* Print points and corners until we reach a different color. */ int color_0 = color[ka]; do { - pka = eaf_point (a, ka); - push_point (pka[0], prev_pka_y); - push_point (pka[0], pka[1]); + pka = eaf_point(a, ka); + push_point(pka[0], prev_pka_y); + push_point(pka[0], pka[1]); prev_pka_y = pka[1]; ka++; } while (ka < eaf_a_size && color_0 == color[ka]); /* pka is the point before changing color, but ka is the position after. */ - if (ka == eaf_a_size) {/* We reached the end of eaf_a */ + if (ka == eaf_a_size) { /* We reached the end of eaf_a */ /* We don't have to go down the other side since eaf_a completely dominates eaf_b, so just start by the end. */ @@ -839,27 +842,27 @@ eaf_compute_polygon_old (eaf_t **eaf, int nobj, int nlevels) if (last_b == kb) { /* There is nothing on the other side, just create two points in the infinity. */ - push_point (objective_MAX, pka[1]); - push_point (objective_MAX, topleft_y); + push_point(objective_MAX, pka[1]); + push_point(objective_MAX, topleft_y); } else { const objective_t * pkb = eaf_point(a + 1, kb); - assert (pkb[1] >= pka[1]); + assert(pkb[1] >= pka[1]); if (pkb[1] > pka[1]) { /* Create two points in the infinity. */ - push_point (objective_MAX, pka[1]); - push_point (objective_MAX, pkb[1]); + push_point(objective_MAX, pka[1]); + push_point(objective_MAX, pkb[1]); } objective_t prev_pkb_x = pkb[0]; - push_point (pkb[0], pkb[1]); + push_point(pkb[0], pkb[1]); kb--; while (kb > last_b) { pkb = eaf_point(a + 1, kb); - push_point (prev_pkb_x, pkb[1]); - push_point (pkb[0], pkb[1]); + push_point(prev_pkb_x, pkb[1]); + push_point(pkb[0], pkb[1]); prev_pkb_x = pkb[0]; kb--; } - push_point (pkb[0], topleft_y); + push_point(pkb[0], topleft_y); last_b = eaf_b_size - 1; } polygon_close(color_0); /* DONE */ @@ -870,36 +873,35 @@ eaf_compute_polygon_old (eaf_t **eaf, int nobj, int nlevels) if (kb == eaf_b_size) { /* There is nothing on the other side, just create two points in the infinity. */ - push_point (objective_MAX, pka[1]); - push_point (objective_MAX, topleft_y); + push_point(objective_MAX, pka[1]); + push_point(objective_MAX, topleft_y); polygon_close(color_0); /* DONE */ } else { const objective_t * pkb; do { - pkb = eaf_point (b, kb); - if (pkb[1] <= pka[1]) - break; + pkb = eaf_point(b, kb); + if (pkb[1] <= pka[1]) break; kb++; } while (kb < eaf_b_size); int save_last_b = kb - 1; if (kb == eaf_b_size) { /* There is nothing on the other side, just create two points in the infinity. */ - push_point (objective_MAX, pka[1]); - push_point (objective_MAX, pkb[1]); - } else {/* pkb_y <= pka_y */ + push_point(objective_MAX, pka[1]); + push_point(objective_MAX, pkb[1]); + } else { /* pkb_y <= pka_y */ objective_t prev_pkb_x = pkb[0]; - push_point (pkb[0], pka[1]); + push_point(pkb[0], pka[1]); /* Now print in reverse. */ kb--; while (kb > last_b) { - pkb = eaf_point (b, kb); - push_point (prev_pkb_x, pkb[1]); - push_point (pkb[0], pkb[1]); + pkb = eaf_point(b, kb); + push_point(prev_pkb_x, pkb[1]); + push_point(pkb[0], pkb[1]); prev_pkb_x = pkb[0]; kb--; } - push_point (pkb[0], topleft_y); + push_point(pkb[0], topleft_y); } polygon_close(color_0); /* DONE */ last_b = save_last_b; @@ -909,7 +911,7 @@ eaf_compute_polygon_old (eaf_t **eaf, int nobj, int nlevels) } } - free (color); + free(color); return polygon; } #undef eaf_point @@ -919,38 +921,36 @@ eaf_compute_polygon_old (eaf_t **eaf, int nobj, int nlevels) #undef POLY_SIZE_CHECK void -eaf_print_polygon (FILE *stream, eaf_t **eaf, int nobj, int nlevels) +eaf_print_polygon(FILE * stream, eaf_t ** eaf, int nobj, int nlevels) { - eaf_polygon_t *p = eaf_compute_area (eaf, nobj, nlevels); + eaf_polygon_t * p = eaf_compute_area(eaf, nobj, nlevels); - for(size_t i = 0; i < vector_objective_size(&p->xy); i += 2) { + for (size_t i = 0; i < vector_objective_size(&p->xy); i += 2) { point2d_printf(stream, vector_objective_at(&p->xy, i), vector_objective_at(&p->xy, i + 1)); fprintf(stream, "\n"); } - fprintf (stream, "# col ="); - for (size_t k = 0; k < vector_int_size (&p->col); k++) - fprintf (stream, " %d", vector_int_at(&p->col, k)); - fprintf (stream, "\n"); + fprintf(stream, "# col ="); + for (size_t k = 0; k < vector_int_size(&p->col); k++) + fprintf(stream, " %d", vector_int_at(&p->col, k)); + fprintf(stream, "\n"); - vector_objective_dtor (&p->xy); - vector_int_dtor (&p->col); + vector_objective_dtor(&p->xy); + vector_int_dtor(&p->col); free(p); } static size_t -rectangle_add(eaf_polygon_t * regions, - objective_t lx, objective_t ly, - objective_t ux, objective_t uy, - int color) +rectangle_add(eaf_polygon_t * regions, objective_t lx, objective_t ly, + objective_t ux, objective_t uy, int color) { #if 0 printf("rectangle_add: (" point_printf_format ", " point_printf_format ", " point_printf_format ", " point_printf_format ")[%d]\n", lx, ly, ux, uy, color); #endif assert(lx < ux); assert(ly < uy); - vector_objective *rect = ®ions->xy; + vector_objective * rect = ®ions->xy; vector_objective_push_back(rect, lx); vector_objective_push_back(rect, ly); vector_objective_push_back(rect, ux); @@ -961,15 +961,17 @@ rectangle_add(eaf_polygon_t * regions, } eaf_polygon_t * -eaf_compute_rectangles (eaf_t **eaf, int nobj, int nlevels) +eaf_compute_rectangles(eaf_t ** eaf, int nobj, int nlevels) { -#define eaf_point(A,K) (eaf[(A)]->data + (K) * nobj) +#define eaf_point(A, K) (eaf[(A)]->data + (K) * nobj) #if 0 -#define printf_points(ka,kb,pka,pkb) \ - printf("%4d: pa[%d]=(" point_printf_format ", " point_printf_format "), pb[%d] = (" point_printf_format ", " point_printf_format ")\n", \ - __LINE__, ka, pka[0], pka[1], kb, pkb[0], pkb[1]) +# define printf_points(ka, kb, pka, pkb) \ + printf("%4d: pa[%d]=(" point_printf_format ", " point_printf_format \ + "), pb[%d] = (" point_printf_format ", " point_printf_format \ + ")\n", \ + __LINE__, ka, pka[0], pka[1], kb, pkb[0], pkb[1]) #else -#define printf_points(ka,kb,pka,pkb) +# define printf_points(ka, kb, pka, pkb) #endif int nruns = eaf[0]->nruns; @@ -978,31 +980,32 @@ eaf_compute_rectangles (eaf_t **eaf, int nobj, int nlevels) int max_size = eaf_max_size(eaf, nlevels); int * color = MOOCORE_MALLOC(max_size, int); eaf_polygon_t * regions = MOOCORE_MALLOC(1, eaf_polygon_t); - vector_objective_ctor (®ions->xy, max_size); - vector_int_ctor (®ions->col, max_size); + vector_objective_ctor(®ions->xy, max_size); + vector_int_ctor(®ions->col, max_size); for (int b = 1; b < nlevels; b++) { const int a = b - 1; - const int eaf_a_size = (int) eaf[a]->size; - const int eaf_b_size = (int) eaf[b]->size; + const int eaf_a_size = (int)eaf[a]->size; + const int eaf_b_size = (int)eaf[b]->size; if (eaf_a_size == 0 || eaf_b_size == 0) continue; // FIXME: Skip points with color 0? init_colors(color, eaf[a], eaf_a_size, nruns); objective_t top = objective_MAX; int ka = 0, kb = 0; - const objective_t * pkb = eaf_point (b, kb); - const objective_t * pka = eaf_point (a, ka); + const objective_t * pkb = eaf_point(b, kb); + const objective_t * pka = eaf_point(a, ka); printf_points(ka, kb, pka, pkb); while (true) { while (pka[1] < pkb[1]) { if (pka[0] < pkb[0]) // pka strictly dominates pkb - rectangle_add(regions, pka[0], pkb[1], pkb[0], top, color[ka]); + rectangle_add(regions, pka[0], pkb[1], pkb[0], top, + color[ka]); top = pkb[1]; kb++; if (kb >= eaf_b_size) goto close_eaf; - pkb = eaf_point (b, kb); + pkb = eaf_point(b, kb); printf_points(ka, kb, pka, pkb); } // pka_above_equal_pkb: @@ -1015,14 +1018,14 @@ eaf_compute_rectangles (eaf_t **eaf, int nobj, int nlevels) top = pka[1]; ka++; if (ka >= eaf_a_size) goto next_eaf; - pka = eaf_point (a, ka); + pka = eaf_point(a, ka); printf_points(ka, kb, pka, pkb); if (pkb[1] == top) { // pkb was not above but equal to previous pka // Move to next pkb kb++; if (kb >= eaf_b_size) goto close_eaf; - pkb = eaf_point (b, kb); + pkb = eaf_point(b, kb); printf_points(ka, kb, pka, pkb); } } @@ -1030,11 +1033,12 @@ eaf_compute_rectangles (eaf_t **eaf, int nobj, int nlevels) // b is finished, add one rectangle for each pka point. while (true) { assert(pka[1] < pkb[1]); - rectangle_add(regions, pka[0], pka[1], objective_MAX, top, color[ka]); + rectangle_add(regions, pka[0], pka[1], objective_MAX, top, + color[ka]); top = pka[1]; ka++; if (ka >= eaf_a_size) break; - pka = eaf_point (a, ka); + pka = eaf_point(a, ka); printf_points(ka, kb, pka, pkb); } next_eaf: diff --git a/c/eaf.h b/c/eaf.h index 38b25c74..2b26ff56 100644 --- a/c/eaf.h +++ b/c/eaf.h @@ -45,7 +45,7 @@ # define fread_objective_t fread_int # define read_objective_t_data read_int_data #else -#error "Unknown OBJECTIVE_TYPE= value" +# error "Unknown OBJECTIVE_TYPE= value" #endif #include "bit_array.h" @@ -55,96 +55,94 @@ typedef struct { size_t size; size_t maxsize; unsigned int nreallocs; - bit_array *bit_attained; - objective_t *data; + bit_array * bit_attained; + objective_t * data; } eaf_t; void -eaf_print_attsurf (const eaf_t *, int nobj, - FILE *coord_file, /* output file (coordinates) */ - FILE *indic_file, /* output file (attainment indicators) */ - FILE *diff_file); /* output file (difference nruns/2) */ - -eaf_t * eaf_create (int nobj, int nruns, int npoints); -void eaf_delete (eaf_t * eaf); -void eaf_free (eaf_t ** eaf, int nruns); -objective_t * -eaf_store_point_help (eaf_t * eaf, int nobj, const int *save_attained); - -static inline int eaf_totalpoints (eaf_t **eaf, int n) +eaf_print_attsurf(const eaf_t *, int nobj, + FILE * coord_file, /* output file (coordinates) */ + FILE * indic_file, /* output file (attainment indicators) */ + FILE * diff_file); /* output file (difference nruns/2) */ + +eaf_t * eaf_create(int nobj, int nruns, int npoints); +void eaf_delete(eaf_t * eaf); +void eaf_free(eaf_t ** eaf, int nruns); +objective_t * eaf_store_point_help(eaf_t * eaf, int nobj, + const int * save_attained); + +static inline int +eaf_totalpoints(eaf_t ** eaf, int n) { int totalpoints = 0; - for (int k = 0; k < n; k++) - totalpoints += (int) eaf[k]->size; + for (int k = 0; k < n; k++) totalpoints += (int)eaf[k]->size; return totalpoints; } -eaf_t ** -eaf2d (const objective_t *data, /* the objective vectors */ - const int *cumsize, /* the cumulative sizes of the runs */ - int nruns, /* the number of runs */ - const int *attlevel, /* the desired attainment levels */ - int nlevels /* the number of att levels */ - ); +eaf_t ** eaf2d(const objective_t * data, /* the objective vectors */ + const int * cumsize, /* the cumulative sizes of the runs */ + int nruns, /* the number of runs */ + const int * attlevel, /* the desired attainment levels */ + int nlevels /* the number of att levels */ +); -eaf_t ** -eaf3d (objective_t *data, const int *cumsize, int nruns, - const int *attlevel, const int nlevels); +eaf_t ** eaf3d(objective_t * data, const int * cumsize, int nruns, + const int * attlevel, const int nlevels); static inline eaf_t ** -attsurf (objective_t *data, /* the objective vectors */ - int nobj, /* the number of objectives */ - const int *cumsize, /* the cumulative sizes of the runs */ - int nruns, /* the number of runs */ - const int *attlevel, /* the desired attainment levels */ - int nlevels /* the number of att levels */ - ) +attsurf(objective_t * data, /* the objective vectors */ + int nobj, /* the number of objectives */ + const int * cumsize, /* the cumulative sizes of the runs */ + int nruns, /* the number of runs */ + const int * attlevel, /* the desired attainment levels */ + int nlevels /* the number of att levels */ +) { switch (nobj) { - case 2: - return eaf2d (data, cumsize, nruns, attlevel, nlevels); - break; - case 3: - return eaf3d (data, cumsize, nruns, attlevel, nlevels); - break; - default: - fatal_error("this implementation only supports two or three dimensions.\n"); + case 2: + return eaf2d(data, cumsize, nruns, attlevel, nlevels); + break; + case 3: + return eaf3d(data, cumsize, nruns, attlevel, nlevels); + break; + default: + fatal_error( + "this implementation only supports two or three dimensions.\n"); } } static inline void -attained_left_right (const bit_array *attained, int division, int total, - int *count_left, int *count_right) +attained_left_right(const bit_array * attained, int division, int total, + int * count_left, int * count_right) { - assert (division < total); + assert(division < total); int count_l = 0; int count_r = 0; int k; for (k = 0; k < division; k++) - if (bit_array_get(attained, k)) count_l++; + if (bit_array_get(attained, k)) count_l++; for (k = division; k < total; k++) - if (bit_array_get(attained, k)) count_r++; + if (bit_array_get(attained, k)) count_r++; *count_left = count_l; *count_right = count_r; } static inline double -level2percentile (int level, int n) +level2percentile(int level, int n) { if (level == n) return 100.; - return ((double)level * 100.0) / (double) n; + return ((double)level * 100.0) / (double)n; } static inline int -percentile2level (double p, int n) +percentile2level(double p, int n) { const double tolerance = sqrt(DBL_EPSILON); double x = (n * p) / 100.0; - int level = (x - floor(x) <= tolerance) - ? (int) floor(x) : (int) ceil(x); + int level = (x - floor(x) <= tolerance) ? (int)floor(x) : (int)ceil(x); assert(level <= n); assert(level >= 0); @@ -155,68 +153,68 @@ percentile2level (double p, int n) _attr_maybe_unused static int * levels_from_percentiles(const double * percentile, int nlevels, int nruns) { - int *level; + int * level; if (percentile) { level = malloc(sizeof(int) * nlevels); for (int k = 0; k < nlevels; k++) level[k] = percentile2level(percentile[k], nruns); } else { - assert (nlevels == nruns); + assert(nlevels == nruns); level = malloc(sizeof(int) * nruns); - for (int k = 0; k < nruns; k++) - level[k] = k + 1; + for (int k = 0; k < nruns; k++) level[k] = k + 1; } return level; } _attr_maybe_unused static void -all_percentiles (double * percentiles, int n_sets) +all_percentiles(double * percentiles, int n_sets) { const double x = 100.0 / (double)n_sets; - for (int i = 1; i <= n_sets; i++) - percentiles[i-1] = i * x; + for (int i = 1; i <= n_sets; i++) percentiles[i - 1] = i * x; } -void eaf2matrix_R(double *rmat, eaf_t * const * eaf, int nobj, int totalpoints, +void eaf2matrix_R(double * rmat, eaf_t * const * eaf, int nobj, int totalpoints, const double * percentile, int nlevels); -void eaf2matrix(double *rmat, eaf_t * const * eaf, int nobj, _attr_maybe_unused int totalpoints, - const double * percentile, int nlevels); +void eaf2matrix(double * rmat, eaf_t * const * eaf, int nobj, + _attr_maybe_unused int totalpoints, const double * percentile, + int nlevels); -double * -eaf_compute_matrix(int *eaf_npoints, double * data, int nobj, const int *cumsizes, int nruns, - const double * percentile, int nlevels); +double * eaf_compute_matrix(int * eaf_npoints, double * data, int nobj, + const int * cumsizes, int nruns, + const double * percentile, int nlevels); static inline double -eafdiff_percentile (const eaf_t * eaf, size_t i, int division, int nruns, int n_intervals) +eafdiff_percentile(const eaf_t * eaf, size_t i, int division, int nruns, + int n_intervals) { - const bit_array *bit_attained = bit_array_offset(eaf->bit_attained, i, nruns); + const bit_array * bit_attained = + bit_array_offset(eaf->bit_attained, i, nruns); int count_left, count_right; - attained_left_right (bit_attained, division, nruns, &count_left, &count_right); - return n_intervals * (double) ((count_left / (double) division) - - (count_right / (double) (nruns - division))); + attained_left_right(bit_attained, division, nruns, &count_left, + &count_right); + return n_intervals * (double)((count_left / (double)division) - + (count_right / (double)(nruns - division))); } -double * -eafdiff_compute_rectangles(int *eaf_npoints, double * data, int nobj, - const int *cumsizes, int nruns, int intervals); -double * -eafdiff_compute_matrix(int *eaf_npoints, double * data, int nobj, - const int *cumsizes, int nruns, int intervals); +double * eafdiff_compute_rectangles(int * eaf_npoints, double * data, int nobj, + const int * cumsizes, int nruns, + int intervals); +double * eafdiff_compute_matrix(int * eaf_npoints, double * data, int nobj, + const int * cumsizes, int nruns, int intervals); #define cvector_assert(X) assert(X) #include "cvector.h" -vector_define(vector_objective, objective_t) -vector_define(vector_int, int) +vector_define(vector_objective, objective_t) vector_define(vector_int, int) -typedef struct { + typedef struct { vector_objective xy; vector_int col; } eaf_polygon_t; #define eaf_compute_area eaf_compute_polygon -eaf_polygon_t *eaf_compute_polygon (eaf_t **eaf, int nobj, int nlevels); -eaf_polygon_t *eaf_compute_polygon_old (eaf_t **eaf, int nobj, int nlevels); -void eaf_print_polygon (FILE* stream, eaf_t **eaf, int nobj, int nlevels); -eaf_polygon_t * eaf_compute_rectangles (eaf_t **eaf, int nobj, int nlevels); +eaf_polygon_t * eaf_compute_polygon(eaf_t ** eaf, int nobj, int nlevels); +eaf_polygon_t * eaf_compute_polygon_old(eaf_t ** eaf, int nobj, int nlevels); +void eaf_print_polygon(FILE * stream, eaf_t ** eaf, int nobj, int nlevels); +eaf_polygon_t * eaf_compute_rectangles(eaf_t ** eaf, int nobj, int nlevels); diff --git a/c/eaf3d.c b/c/eaf3d.c index 738024b6..fc242c51 100644 --- a/c/eaf3d.c +++ b/c/eaf3d.c @@ -30,14 +30,14 @@ #include "avl.h" typedef struct dlnode { - objective_t *x; /* The data vector */ - struct dlnode *next; - struct dlnode *prev; + objective_t * x; /* The data vector */ + struct dlnode * next; + struct dlnode * prev; int set; } dlnode_t; typedef struct removed_list { - avl_node_t *head; + avl_node_t * head; } removed_list_t; /* @@ -47,18 +47,20 @@ static bool avl_tree_is_empty (const avl_tree_t *avltree) } */ -static inline objective_t *node_point(const avl_node_t *node) +static inline objective_t * +node_point(const avl_node_t * node) { - return (objective_t*) node->item; + return (objective_t *)node->item; } -static int compare_node(const void *p1, const void *p2) +static int +compare_node(const void * p1, const void * p2) { const objective_t x1 = *((*(const dlnode_t **)p1)->x); const objective_t x2 = *((*(const dlnode_t **)p2)->x); - return (x1 < x2) ? -1 : ( x1 > x2 ) ? 1 : 0; + return (x1 < x2) ? -1 : (x1 > x2) ? 1 : 0; } @@ -66,10 +68,10 @@ static int compare_node(const void *p1, const void *p2) Create a list of points, ordered by the third coordinate. */ static dlnode_t * -setup_cdllist(objective_t *data, int d, const int *cumsize, int nsets) +setup_cdllist(objective_t * data, int d, const int * cumsize, int nsets) { int n = cumsize[nsets - 1]; - dlnode_t *head = malloc ((n + 1) * sizeof(dlnode_t)); + dlnode_t * head = malloc((n + 1) * sizeof(dlnode_t)); head->x = data; head[0].set = 0; @@ -77,38 +79,36 @@ setup_cdllist(objective_t *data, int d, const int *cumsize, int nsets) for (i = 0, k = 0; i < n; i++) { if (i == cumsize[k]) k++; - head[i+1].set = k; + head[i + 1].set = k; // ->x points to the first coordinate of each point. - head[i+1].x = head[i].x + d ;// this will be fixed a few lines below... - head[i+1].next = head[i].next; - head[i+1].prev = head[i].prev; + head[i + 1].x = + head[i].x + d; // this will be fixed a few lines below... + head[i + 1].next = head[i].next; + head[i + 1].prev = head[i].prev; } head->x = NULL; // head contains no data - dlnode_t **scratch = malloc(n * sizeof(dlnode_t*)); - for (i = 0; i < n; i++) - scratch[i] = head + i + 1; + dlnode_t ** scratch = malloc(n * sizeof(dlnode_t *)); + for (i = 0; i < n; i++) scratch[i] = head + i + 1; // ->x points to the last coordinate of each point. - for (i = 0; i < n; i++) - scratch[i]->x--; + for (i = 0; i < n; i++) scratch[i]->x--; // Sort according to the last coordinate. - qsort(scratch, n, sizeof(dlnode_t*), compare_node); + qsort(scratch, n, sizeof(dlnode_t *), compare_node); head->next = scratch[0]; scratch[0]->prev = head; for (i = 1; i < n; i++) { - scratch[i-1]->next = scratch[i]; - scratch[i]->prev = scratch[i-1]; + scratch[i - 1]->next = scratch[i]; + scratch[i]->prev = scratch[i - 1]; } - scratch[n-1]->next = head; - head->prev = scratch[n-1]; + scratch[n - 1]->next = head; + head->prev = scratch[n - 1]; // ->x points to the first coordinate. - for (i = 0; i < n; i++) - scratch[i]->x -= d - 1; + for (i = 0; i < n; i++) scratch[i]->x -= d - 1; free(scratch); @@ -117,7 +117,8 @@ setup_cdllist(objective_t *data, int d, const int *cumsize, int nsets) /* FIXME: Why this variant in one single indirection and the eaf2d equivalent is 2. */ -static int compare_tree_asc_x(const void *p1, const void *p2) +static int +compare_tree_asc_x(const void * p1, const void * p2) { const objective_t x1 = *((const objective_t *)p1); const objective_t x2 = *((const objective_t *)p2); @@ -125,23 +126,26 @@ static int compare_tree_asc_x(const void *p1, const void *p2) return (x1 < x2) ? -1 : (x1 > x2) ? 1 : 0; } -static int compare_tree_desc_y( const void *p1, const void *p2) +static int +compare_tree_desc_y(const void * p1, const void * p2) { - const objective_t y1 = *((const objective_t *)p1+1); - const objective_t y2 = *((const objective_t *)p2+1); + const objective_t y1 = *((const objective_t *)p1 + 1); + const objective_t y2 = *((const objective_t *)p2 + 1); return (y1 > y2) ? -1 : (y1 < y2) ? 1 : 0; } -static int avl_search_closest_y(const avl_tree_t *avltree, const void *item, avl_node_t **avlnode) { - avl_node_t *node; +static int +avl_search_closest_y(const avl_tree_t * avltree, const void * item, + avl_node_t ** avlnode) +{ + avl_node_t * node; int c; - if(!avlnode) - avlnode = &node; + if (!avlnode) avlnode = &node; node = avltree->top; - if(!node) { + if (!node) { *avlnode = NULL; return 0; } @@ -149,14 +153,14 @@ static int avl_search_closest_y(const avl_tree_t *avltree, const void *item, avl do { c = compare_tree_desc_y(item, node->item); if (c < 0) { - if(node->left) + if (node->left) node = node->left; else { *avlnode = node; return -1; } } else if (c > 0) { - if(node->right) + if (node->right) node = node->right; else { *avlnode = node; @@ -166,14 +170,14 @@ static int avl_search_closest_y(const avl_tree_t *avltree, const void *item, avl *avlnode = node; return 0; } - } while(true); + } while (true); } static void find_all_promoters(avl_node_t * avlnode, int * dom_sets, int nruns) { - avl_node_t *node = avlnode; + avl_node_t * node = avlnode; while (node != NULL) { dom_sets[node->set] = 1; @@ -195,13 +199,13 @@ find_all_promoters(avl_node_t * avlnode, int * dom_sets, int nruns) The values printed are the values from dimension 0 to dimension dim of each point */ static void -printlist(const avl_tree_t *avltree, int dim, FILE *outfile) +printlist(const avl_tree_t * avltree, int dim, FILE * outfile) { - avl_node_t *aux = avltree->head; - while(aux){ + avl_node_t * aux = avltree->head; + while (aux) { objective_t * val = (objective_t *)aux->item; //printf("-> "); - for (int i = 0; i < dim; i++){ + for (int i = 0; i < dim; i++) { fprintf(outfile, point_printf_format "\t", val[i]); } fprintf(outfile, "\n"); @@ -210,23 +214,25 @@ printlist(const avl_tree_t *avltree, int dim, FILE *outfile) } -void printset(FILE* stream, avl_tree_t **set, int nset) +void +printset(FILE * stream, avl_tree_t ** set, int nset) { fprintf(stream, "# sets\n----------------------\n"); - for (int i = 0; i < nset; i++){ + for (int i = 0; i < nset; i++) { if (set[i]->top != NULL) { - fprintf (stream, "set: %d", i); + fprintf(stream, "set: %d", i); printlist(set[i], 3, stream); } } } -void printlevel(FILE * stream, avl_tree_t **level, int nset) +void +printlevel(FILE * stream, avl_tree_t ** level, int nset) { - fprintf (stream, "#levels\n-------------------\n"); - for (int i = 0; i < nset; i++){ - if (level[i]->top != NULL){ - fprintf (stream, "level: %d\n", i); + fprintf(stream, "#levels\n-------------------\n"); + for (int i = 0; i < nset; i++) { + if (level[i]->top != NULL) { + fprintf(stream, "level: %d\n", i); printlist(level[i], 3, stream); } } @@ -234,26 +240,26 @@ void printlevel(FILE * stream, avl_tree_t **level, int nset) static int -printlist_points_indic(avl_tree_t *avltree, int dim, int nruns, FILE *outfile, FILE *outfileindic) +printlist_points_indic(avl_tree_t * avltree, int dim, int nruns, FILE * outfile, + FILE * outfileindic) { - int * dom_sets = (int *) malloc(nruns * sizeof(int)); + int * dom_sets = (int *)malloc(nruns * sizeof(int)); int i, k, totalp = 0; - avl_node_t *aux = avltree->head; + avl_node_t * aux = avltree->head; while (aux) { - objective_t * val = (objective_t *)aux->item; + objective_t * val = (objective_t *)aux->item; if (outfile) { fprintf(outfile, point_printf_format, val[0]); - for (i = 1; i < dim; i++){ + for (i = 1; i < dim; i++) { fprintf(outfile, "\t" point_printf_format, val[i]); } fprintf(outfile, (outfile == outfileindic) ? "\t" : "\n"); } if (outfileindic) { - for (k = 0; k < nruns; k++) - dom_sets[k] = 0; + for (k = 0; k < nruns; k++) dom_sets[k] = 0; find_all_promoters(aux, dom_sets, nruns); fprintf(outfileindic, "%d", dom_sets[0]); - for (k = 1; k < nruns; k++){ + for (k = 1; k < nruns; k++) { fprintf(outfileindic, "\t%d", dom_sets[k]); } fprintf(outfileindic, "\n"); @@ -268,22 +274,27 @@ printlist_points_indic(avl_tree_t *avltree, int dim, int nruns, FILE *outfile, F } /* Returns the total number of points printed */ -int printoutput(avl_tree_t **level, int nset, int d, FILE **outfile, int noutfiles, FILE **outfileindic, int noutfilesi, int * attlevel, int nlevels) +int +printoutput(avl_tree_t ** level, int nset, int d, FILE ** outfile, + int noutfiles, FILE ** outfileindic, int noutfilesi, int * attlevel, + int nlevels) { int totalp = 0; - for (int i = 0; i < nlevels; i++){ + for (int i = 0; i < nlevels; i++) { int k = attlevel[i] - 1; int f = (noutfiles > 1) ? i : 0; int fi = (noutfilesi > 1) ? i : 0; if (level[k]->head != NULL) { - totalp += printlist_points_indic(level[k], d, nset, (outfile ? outfile[f] : NULL), (outfileindic ? outfileindic[fi] : NULL)); + totalp += printlist_points_indic( + level[k], d, nset, (outfile ? outfile[f] : NULL), + (outfileindic ? outfileindic[fi] : NULL)); } if (i < nlevels - 1) { - if (outfile) - fprintf(outfile[f], "\n"); - if (outfileindic && (outfile == NULL || outfile[f] != outfileindic[fi])){ + if (outfile) fprintf(outfile[f], "\n"); + if (outfileindic && + (outfile == NULL || outfile[f] != outfileindic[fi])) { fprintf(outfileindic[fi], "\n"); } } @@ -292,19 +303,19 @@ int printoutput(avl_tree_t **level, int nset, int d, FILE **outfile, int noutfil } - -static void print_list_indic(avl_tree_t * level, int nruns, FILE * indicfile) +static void +print_list_indic(avl_tree_t * level, int nruns, FILE * indicfile) { - int * dom_sets = (int *) malloc(nruns * sizeof(int)); + int * dom_sets = (int *)malloc(nruns * sizeof(int)); int i; avl_node_t * avlnode = level->head; while (avlnode) { - for (i = 0; i < nruns; i++){ + for (i = 0; i < nruns; i++) { dom_sets[i] = 0; } find_all_promoters(avlnode, dom_sets, nruns); - for (i = 0; i < nruns; i++){ + for (i = 0; i < nruns; i++) { fprintf(indicfile, "%d\t", dom_sets[i]); } fprintf(indicfile, "\n"); @@ -314,13 +325,15 @@ static void print_list_indic(avl_tree_t * level, int nruns, FILE * indicfile) free(dom_sets); } -void printindic(avl_tree_t ** levels, int nruns, FILE ** indicfile, int nfiles, int * attlevel, int nlevels) +void +printindic(avl_tree_t ** levels, int nruns, FILE ** indicfile, int nfiles, + int * attlevel, int nlevels) { - for (int i = 0; i < nlevels; i++){ + for (int i = 0; i < nlevels; i++) { int k = attlevel[i] - 1; int f = (nfiles == 1) ? 0 : i; - if (levels[k]->head != NULL){ + if (levels[k]->head != NULL) { print_list_indic(levels[k], nruns, indicfile[f]); } @@ -329,7 +342,8 @@ void printindic(avl_tree_t ** levels, int nruns, FILE ** indicfile, int nfiles, } -void add2output(avl_tree_t *output, avl_node_t *tnode) +void +add2output(avl_tree_t * output, avl_node_t * tnode) { if (output->top != NULL) { output->tail->next = tnode; @@ -339,9 +353,11 @@ void add2output(avl_tree_t *output, avl_node_t *tnode) } } -void add2output_all(avl_tree_t *output, avl_tree_t *tree_add){ +void +add2output_all(avl_tree_t * output, avl_tree_t * tree_add) +{ - avl_node_t *node = tree_add->head; + avl_node_t * node = tree_add->head; avl_unlink_node(tree_add, node); free(node->item); free(node); @@ -352,41 +368,40 @@ void add2output_all(avl_tree_t *output, avl_tree_t *tree_add){ free(node); - if(tree_add->head != NULL){ - if(output->tail != NULL){ - output->tail->next=tree_add->head; - }else{ - output->head=tree_add->head; + if (tree_add->head != NULL) { + if (output->tail != NULL) { + output->tail->next = tree_add->head; + } else { + output->head = tree_add->head; } } } - //this fuction is called only when item isn't dominated by any point in tree. //note: prevnode is above and at item's left, so any dominated point that it may dominate is at its right static void -add2set(avl_tree_t *tree, avl_node_t *prevnode, avl_node_t *tnode, objective_t *item) +add2set(avl_tree_t * tree, avl_node_t * prevnode, avl_node_t * tnode, + objective_t * item) { - avl_init_node (tnode, item); - if (node_point(prevnode)[0] == item[0]) - prevnode = prevnode->prev; - avl_insert_after (tree, prevnode, tnode); + avl_init_node(tnode, item); + if (node_point(prevnode)[0] == item[0]) prevnode = prevnode->prev; + avl_insert_after(tree, prevnode, tnode); tnode = tnode->next; // tnode->next is dominated by item while (node_point(tnode)[1] >= item[1]) { avl_unlink_node(tree, tnode); - avl_node_t *node = tnode; + avl_node_t * node = tnode; tnode = tnode->next; free(node); } - } -static void avl_add_promoter(avl_node_t *avlnode, int set, avl_node_t *promoter) +static void +avl_add_promoter(avl_node_t * avlnode, int set, avl_node_t * promoter) { avlnode->set = set; avlnode->promoter = promoter; @@ -395,48 +410,50 @@ static void avl_add_promoter(avl_node_t *avlnode, int set, avl_node_t *promoter) } -static void add_removed(removed_list_t * removed_list, avl_node_t *node) +static void +add_removed(removed_list_t * removed_list, avl_node_t * node) { node->next = removed_list->head; removed_list->head = node; } static avl_node_t * -add2level(removed_list_t * removed_list, avl_tree_t *tree, - objective_t *item, avl_tree_t *output, int set, avl_node_t * promoter) +add2level(removed_list_t * removed_list, avl_tree_t * tree, objective_t * item, + avl_tree_t * output, int set, avl_node_t * promoter) { - avl_node_t *prevnode; + avl_node_t * prevnode; switch (avl_search_closest_y(tree, item, &prevnode)) { - case -1: - prevnode = prevnode->prev; - break; - case 0: - prevnode = (node_point(prevnode)[0] > item[0]) - ? prevnode : prevnode->prev; - break; - - case 1: break; + case -1: + prevnode = prevnode->prev; + break; + case 0: + prevnode = + (node_point(prevnode)[0] > item[0]) ? prevnode : prevnode->prev; + break; + + case 1: + break; } //aux represents the point immediately below item. - avl_node_t *aux = prevnode->next; + avl_node_t * aux = prevnode->next; // A new point (item) is added, but only if it isn't dominated. if (node_point(aux)[0] > item[0]) { - avl_node_t *tnode = malloc(sizeof(avl_node_t)); + avl_node_t * tnode = malloc(sizeof(avl_node_t)); avl_init_node(tnode, item); avl_add_promoter(tnode, set, promoter); - avl_node_t *newnode = tnode; + avl_node_t * newnode = tnode; avl_insert_after(tree, prevnode, tnode); tnode = tnode->prev; // tnode->prev is dominated by item while (node_point(tnode)[0] >= item[0]) { - avl_unlink_node(tree,tnode); + avl_unlink_node(tree, tnode); aux = tnode; tnode = tnode->prev; if (node_point(aux)[2] < item[2]) add2output(output, aux); - else{ + else { free(aux->item); add_removed(removed_list, aux); aux->remover = newnode; @@ -447,16 +464,17 @@ add2level(removed_list_t * removed_list, avl_tree_t *tree, dimension 0 to 1. */ } return newnode; - } else{ + } else { free(item); return NULL; } } -static objective_t * copy_point(const objective_t * v) +static objective_t * +copy_point(const objective_t * v) { - objective_t *value = malloc(3 * sizeof(objective_t)); + objective_t * value = malloc(3 * sizeof(objective_t)); value[0] = v[0]; value[1] = v[1]; @@ -466,9 +484,11 @@ static objective_t * copy_point(const objective_t * v) } //at left or equal -static avl_node_t * find_point_at_left(avl_tree_t *tree, objective_t *item){ +static avl_node_t * +find_point_at_left(avl_tree_t * tree, objective_t * item) +{ - avl_node_t *leftNode; + avl_node_t * leftNode; if (avl_search_closest(tree, item, &leftNode) < 0) leftNode = leftNode->prev; @@ -477,9 +497,10 @@ static avl_node_t * find_point_at_left(avl_tree_t *tree, objective_t *item){ } //below and not equal -static avl_node_t * find_point_below(avl_tree_t *tree, objective_t *item) +static avl_node_t * +find_point_below(avl_tree_t * tree, objective_t * item) { - avl_node_t *belowNode; + avl_node_t * belowNode; if (avl_search_closest_y(tree, item, &belowNode) >= 0) belowNode = belowNode->next; @@ -488,10 +509,10 @@ static avl_node_t * find_point_below(avl_tree_t *tree, objective_t *item) } - -static objective_t * new_point(objective_t x1, objective_t x2, objective_t x3) +static objective_t * +new_point(objective_t x1, objective_t x2, objective_t x3) { - objective_t *value = malloc(3 * sizeof(objective_t)); + objective_t * value = malloc(3 * sizeof(objective_t)); value[0] = x1; value[1] = x2; value[2] = x3; @@ -500,13 +521,13 @@ static objective_t * new_point(objective_t x1, objective_t x2, objective_t x3) void -eaf3df(removed_list_t * removed_list, dlnode_t *list, avl_tree_t **set, - avl_tree_t **level, avl_tree_t **output, int nset) +eaf3df(removed_list_t * removed_list, dlnode_t * list, avl_tree_t ** set, + avl_tree_t ** level, avl_tree_t ** output, int nset) { struct aux_nodes { /* levelNode[t] is the point being verified (possibly to be promoted) from level t, corresponds to s_t in pseudocode */ - avl_node_t *levelNode; + avl_node_t * levelNode; /* these points are needed to represent the intersections of new with the point, of each level, immediately at new's left */ avl_node_t intersectNode; @@ -516,7 +537,7 @@ eaf3df(removed_list_t * removed_list, dlnode_t *list, avl_tree_t **set, struct aux_nodes * aux = malloc(sizeof(struct aux_nodes) * nset); - dlnode_t *new = list->next; //new - represents the new point + dlnode_t * new = list->next; //new - represents the new point //add new to its set avl_node_t * tnode = avl_init_node(malloc(sizeof(avl_node_t)), new->x); @@ -527,11 +548,14 @@ eaf3df(removed_list_t * removed_list, dlnode_t *list, avl_tree_t **set, avl_add_promoter(tnode, new->set, NULL); avl_insert_after(level[0], level[0]->head, tnode); - bool * mask = malloc(sizeof(bool) * nset); // needed to know how many different sets were considered so far + bool * mask = malloc( + sizeof(bool) * + nset); // needed to know how many different sets were considered so far memset(mask, false, nset * sizeof(mask[0])); mask[new->set] = true; - int start_at = 0, stop_at; // indicates which levels must be verified (from and to which) + int start_at = 0, + stop_at; // indicates which levels must be verified (from and to which) // Points are sorted in ascending order with respect to the third coordinate. while (new->next->x != NULL) { @@ -539,20 +563,20 @@ eaf3df(removed_list_t * removed_list, dlnode_t *list, avl_tree_t **set, /* newPrev: point from new's set immediately at its left, it corresponds to q in pseudocode. */ - avl_node_t *newPrev = find_point_at_left(set[new->set], new->x); + avl_node_t * newPrev = find_point_at_left(set[new->set], new->x); // if new is dominated by a point from its set, skip it. if (node_point(newPrev)[1] <= new->x[1]) { continue; } - avl_node_t *dom_new = NULL; + avl_node_t * dom_new = NULL; stop_at = 0; // First part for (int k = start_at; k >= stop_at; k--) { // point from some level immediately at new's left, corresponds to r in pseudocode - avl_node_t *leftNodeL = find_point_at_left(level[k], new->x); + avl_node_t * leftNodeL = find_point_at_left(level[k], new->x); // new is dominated by a point from level k if (node_point(leftNodeL)[1] <= new->x[1]) { @@ -580,7 +604,7 @@ eaf3df(removed_list_t * removed_list, dlnode_t *list, avl_tree_t **set, /* setNode: a point from new's set at its right, it also corresponds to q in pseudocode. */ - avl_node_t *setNode = newPrev; + avl_node_t * setNode = newPrev; //Second part do { @@ -589,16 +613,26 @@ eaf3df(removed_list_t * removed_list, dlnode_t *list, avl_tree_t **set, for (int k = start_at; k >= stop_at; k--) { //while levelNode is dominated by new but not by any point from new's set, levelNode is promoted - while (node_point(aux[k].levelNode)[1] >= lbound - && (node_point(aux[k].levelNode)[1] > lbound || lbound > new->x[1])) { - - if (node_point(setNode)[0] <= node_point(aux[k].levelNode)[0]) { - aux[k].levelNode = find_point_below(level[k], setNode->item); + while (node_point(aux[k].levelNode)[1] >= lbound && + (node_point(aux[k].levelNode)[1] > lbound || + lbound > new->x[1])) { + + if (node_point(setNode)[0] <= + node_point(aux[k].levelNode)[0]) { + aux[k].levelNode = + find_point_below(level[k], setNode->item); aux[k].promoter = aux[k].levelNode; } else { - objective_t *value = new_point(node_point(aux[k].levelNode)[0], node_point(aux[k].levelNode)[1], new->x[2]); - tnode = add2level(removed_list, level[k+1], value, output[k+1], new->set, aux[k].promoter); - if(tnode != NULL && new->x[2] == node_point(aux[k].promoter)[2] && node_point(aux[k].levelNode)[0] == node_point(aux[k].promoter)[0]){ + objective_t * value = new_point( + node_point(aux[k].levelNode)[0], + node_point(aux[k].levelNode)[1], new->x[2]); + tnode = + add2level(removed_list, level[k + 1], value, + output[k + 1], new->set, aux[k].promoter); + if (tnode != NULL && + new->x[2] == node_point(aux[k].promoter)[2] && + node_point(aux[k].levelNode)[0] == + node_point(aux[k].promoter)[0]) { aux[k].promoter->equal = tnode; } @@ -611,14 +645,18 @@ eaf3df(removed_list_t * removed_list, dlnode_t *list, avl_tree_t **set, } while (node_point(setNode)[1] > new->x[1]); //Third part - for (int k = start_at; k >= stop_at; k--){ + for (int k = start_at; k >= stop_at; k--) { //if the intersection point of new with the point from level k immediately below new //isn't dominated, it is added to level k+1 - if(node_point(aux[k].levelNode)[0] < node_point(setNode)[0]){ - - objective_t *value =new_point(node_point(aux[k].levelNode)[0], new->x[1], new->x[2]); - tnode = add2level(removed_list, level[k+1], value, output[k+1], new->set, aux[k].promoter); - if (tnode != NULL && new->x[2] == node_point(aux[k].levelNode)[2] && new->x[1] == node_point(aux[k].levelNode)[1]){ + if (node_point(aux[k].levelNode)[0] < node_point(setNode)[0]) { + + objective_t * value = new_point(node_point(aux[k].levelNode)[0], + new->x[1], new->x[2]); + tnode = add2level(removed_list, level[k + 1], value, + output[k + 1], new->set, aux[k].promoter); + if (tnode != NULL && + new->x[2] == node_point(aux[k].levelNode)[2] && + new->x[1] == node_point(aux[k].levelNode)[1]) { aux[k].promoter->equal = tnode; } } @@ -629,15 +667,17 @@ eaf3df(removed_list_t * removed_list, dlnode_t *list, avl_tree_t **set, add2set(set[new->set], newPrev, tnode, new->x); //add new to the lowest level where it isn't dominated by any point from that level - tnode = add2level(removed_list, level[stop_at], copy_point(new->x), output[stop_at], new->set, dom_new); - if(stop_at > 0 && tnode != NULL && new->x[2] == node_point(dom_new)[2] && - new->x[1] == node_point(dom_new)[1] && new->x[0] == node_point(dom_new)[0]){ + tnode = add2level(removed_list, level[stop_at], copy_point(new->x), + output[stop_at], new->set, dom_new); + if (stop_at > 0 && tnode != NULL && + new->x[2] == node_point(dom_new)[2] && + new->x[1] == node_point(dom_new)[1] && + new->x[0] == node_point(dom_new)[0]) { dom_new->equal = tnode; } if (!mask[new->set]) { - if (start_at < (nset - 2)) - start_at++; + if (start_at < (nset - 2)) start_at++; mask[new->set] = true; } } @@ -647,13 +687,13 @@ eaf3df(removed_list_t * removed_list, dlnode_t *list, avl_tree_t **set, static void -freetree(avl_tree_t *avltree) +freetree(avl_tree_t * avltree) { avl_node_t *aux, *aux2; - aux=avltree->head; + aux = avltree->head; - if(aux){ // FIXME: Double check of aux? - while(aux){ + if (aux) { // FIXME: Double check of aux? + while (aux) { aux2 = aux; aux = aux2->next; free(aux2->item); @@ -665,14 +705,14 @@ freetree(avl_tree_t *avltree) } static void -freetree2(avl_tree_t *avltree) +freetree2(avl_tree_t * avltree) { avl_node_t *aux, *aux2; - aux=avltree->head; + aux = avltree->head; free(aux->item); - while(aux->next){ + while (aux->next) { aux2 = aux; aux = aux2->next; // FIXME: aux2->time is not freed? @@ -686,7 +726,8 @@ freetree2(avl_tree_t *avltree) } -static void free_removed(removed_list_t * removed_list) +static void +free_removed(removed_list_t * removed_list) { avl_node_t * node = removed_list->head; while (node != NULL) { @@ -699,9 +740,9 @@ static void free_removed(removed_list_t * removed_list) } _attr_maybe_unused static void -freeoutput(removed_list_t * removed_list, avl_tree_t **output, int nset) +freeoutput(removed_list_t * removed_list, avl_tree_t ** output, int nset) { - for (int i = 0; i < nset; i++){ + for (int i = 0; i < nset; i++) { freetree(output[i]); } free(output); @@ -709,29 +750,30 @@ freeoutput(removed_list_t * removed_list, avl_tree_t **output, int nset) } -void add_sentinels(avl_tree_t * tree, int n) +void +add_sentinels(avl_tree_t * tree, int n) { - objective_t *value = malloc(n * sizeof(objective_t)); + objective_t * value = malloc(n * sizeof(objective_t)); value[0] = objective_MIN; value[1] = objective_MAX; - avl_node_t *tnode = avl_init_node(malloc(sizeof(avl_node_t)), value); + avl_node_t * tnode = avl_init_node(malloc(sizeof(avl_node_t)), value); avl_insert_top(tree, tnode); value = malloc(n * sizeof(objective_t)); value[0] = objective_MAX; value[1] = objective_MIN; - avl_node_t *tnode2 = avl_init_node(malloc(sizeof(avl_node_t)), value); + avl_node_t * tnode2 = avl_init_node(malloc(sizeof(avl_node_t)), value); avl_insert_after(tree, tnode, tnode2); } static void -eaf_store_point_3d (eaf_t * eaf, objective_t x, objective_t y, objective_t z, - const int *save_attained) +eaf_store_point_3d(eaf_t * eaf, objective_t x, objective_t y, objective_t z, + const int * save_attained) { const int nobj = 3; - objective_t * pos = eaf_store_point_help (eaf, nobj, save_attained); + objective_t * pos = eaf_store_point_help(eaf, nobj, save_attained); pos[0] = x; pos[1] = y; pos[2] = z; @@ -740,15 +782,14 @@ eaf_store_point_3d (eaf_t * eaf, objective_t x, objective_t y, objective_t z, eaf_t ** -eaf3d (objective_t *data, const int *cumsize, int nruns, - const int *attlevel, const int nlevels) +eaf3d(objective_t * data, const int * cumsize, int nruns, const int * attlevel, + const int nlevels) { const int nobj = 3; const int ntotal = cumsize[nruns - 1]; /* total number of points in data */ - DEBUG1(/* Sanity check. */ - for (int i = 1; i < nruns ; i++) - assert(cumsize[i-1] < cumsize[i]); - ); + DEBUG1( /* Sanity check. */ + for (int i = 1; i < nruns; i++) + assert(cumsize[i - 1] < cumsize[i]);); /* FIXME: This seems wrong. It should be: avl_tree_t * set = malloc (nruns * sizeof(*set)); @@ -758,24 +799,27 @@ eaf3d (objective_t *data, const int *cumsize, int nruns, This way we do not need to do avl_alloc_tree for each tree, which creates a lot of small memory chunks. */ - avl_tree_t **set = malloc (nruns * sizeof(avl_tree_t)); - avl_tree_t **level = malloc (nruns * sizeof(avl_tree_t)); - avl_tree_t **output = malloc (nruns * sizeof(avl_tree_t)); + avl_tree_t ** set = malloc(nruns * sizeof(avl_tree_t)); + avl_tree_t ** level = malloc(nruns * sizeof(avl_tree_t)); + avl_tree_t ** output = malloc(nruns * sizeof(avl_tree_t)); int i; for (i = 0; i < nruns; i++) { - set[i] = avl_alloc_tree ((avl_compare_t) compare_tree_asc_x, (avl_freeitem_t) free); - level[i] = avl_alloc_tree ((avl_compare_t) compare_tree_asc_x, (avl_freeitem_t) free); - output[i] = avl_alloc_tree ((avl_compare_t) compare_tree_asc_x, (avl_freeitem_t) free); + set[i] = avl_alloc_tree((avl_compare_t)compare_tree_asc_x, + (avl_freeitem_t)free); + level[i] = avl_alloc_tree((avl_compare_t)compare_tree_asc_x, + (avl_freeitem_t)free); + output[i] = avl_alloc_tree((avl_compare_t)compare_tree_asc_x, + (avl_freeitem_t)free); add_sentinels(set[i], nobj); add_sentinels(level[i], nobj); - } - removed_list_t * removed_list = (removed_list_t *) malloc(sizeof(removed_list_t)); + removed_list_t * removed_list = + (removed_list_t *)malloc(sizeof(removed_list_t)); removed_list->head = NULL; - dlnode_t *list = setup_cdllist(data, nobj, cumsize, nruns); + dlnode_t * list = setup_cdllist(data, nobj, cumsize, nruns); eaf3df(removed_list, list, set, level, output, nruns); for (i = 0; i < nruns; i++) { @@ -794,19 +838,17 @@ eaf3d (objective_t *data, const int *cumsize, int nruns, /* Create output EAF */ /* FIXME: This should be done earlier instead of creating the trees. */ - eaf_t **eaf = malloc(nlevels * sizeof(eaf_t*)); + eaf_t ** eaf = malloc(nlevels * sizeof(eaf_t *)); int * attained = malloc(nruns * sizeof(int)); for (int l = 0; l < nlevels; l++) { - eaf[l] = eaf_create (nobj, nruns, ntotal); + eaf[l] = eaf_create(nobj, nruns, ntotal); int k = attlevel[l] - 1; avl_node_t * aux = output[k]->head; while (aux) { objective_t * val = aux->item; - for(int j = 0; j < nruns; j++) - attained[j] = 0; + for (int j = 0; j < nruns; j++) attained[j] = 0; find_all_promoters(aux, attained, nruns); - eaf_store_point_3d (eaf[l], val[0], val[1], val[2], - attained); + eaf_store_point_3d(eaf[l], val[0], val[1], val[2], attained); aux = aux->next; } } diff --git a/c/eaf_main.c b/c/eaf_main.c index 6f7aaefa..e8381867 100644 --- a/c/eaf_main.c +++ b/c/eaf_main.c @@ -25,49 +25,67 @@ #include #include // for bool, true and false -#include // for getopt() +#include // for getopt() #include // for getopt_long() #include #include "eaf.h" #define CMDLINE_COPYRIGHT_YEARS "2009-2023" -#define CMDLINE_AUTHORS "Carlos Fonseca \n" \ +#define CMDLINE_AUTHORS \ + "Carlos Fonseca \n" \ "Manuel Lopez-Ibanez \n" #include "cmdline.h" -static void usage(void) +static void +usage(void) { - printf("\nUsage:\t%s [OPTIONS] [FILE...]\n\n", program_invocation_short_name); - printf( -"Computes the empirical attainment function (EAF) of all input FILEs. \n" -"With no FILE, or when FILE is -, read standard input.\n\n" - -"Options:\n" -OPTION_HELP_STR -OPTION_VERSION_STR -" -v, --verbose print some information (time, input points, output \n" -" points, etc) in stderr. Default is --quiet \n" -" -o, --output FILE write output to FILE instead of standard output. \n" -" -q, --quiet print just the EAF (as opposed to --verbose) \n" -" -b, --best compute best attainment surface \n" -" -m, --median compute median attainment surface \n" -" -w, --worst compute worst attainment surface \n" -" -p, --percentile REAL compute the given percentile of the EAF \n" -" -l, --level LEVEL compute the given level of the EAF \n" -" -i[FILE], --indices[=FILE] write attainment indices to FILE. \n" -" If FILE is '-', print to stdout. \n" -" If FILE is missing use the same file as for output. \n" -" -d[FILE], --diff[=FILE] write difference between half of runs to FILE. \n" -" If FILE is '-', print to stdout. \n" -" If FILE is missing use the same file as for output. \n" -" , --polygons Write EAF as R polygons. \n" -"\n\n" ); + printf("\nUsage:\t%s [OPTIONS] [FILE...]\n\n", + program_invocation_short_name); + printf("Computes the empirical attainment function (EAF) of all input " + "FILEs. \n" + "With no FILE, or when FILE is -, read standard input.\n\n" + + "Options:\n" OPTION_HELP_STR OPTION_VERSION_STR + " -v, --verbose print some information (time, input points, " + "output \n" + " points, etc) in stderr. Default is --quiet " + " \n" + " -o, --output FILE write output to FILE instead of standard " + "output. \n" + " -q, --quiet print just the EAF (as opposed to --verbose) " + " \n" + " -b, --best compute best attainment surface " + " \n" + " -m, --median compute median attainment surface " + " \n" + " -w, --worst compute worst attainment surface " + " \n" + " -p, --percentile REAL compute the given percentile of the EAF " + " \n" + " -l, --level LEVEL compute the given level of the EAF " + " \n" + " -i[FILE], --indices[=FILE] write attainment indices to FILE. " + " \n" + " If FILE is '-', print to stdout. " + " \n" + " If FILE is missing use the same file as for " + "output. \n" + " -d[FILE], --diff[=FILE] write difference between half of runs to " + "FILE. \n" + " If FILE is '-', print to stdout. " + " \n" + " If FILE is missing use the same file as for " + "output. \n" + " , --polygons Write EAF as R polygons. " + " \n" + "\n\n"); } // FIXME: How to implement this with const char *str? -static int read_doubles (double *vec, char *str) +static int +read_doubles(double * vec, char * str) { char * cursor; char * endp = str; @@ -86,22 +104,23 @@ static int read_doubles (double *vec, char *str) // not end of string: error while (*cursor != '\0') { if (!isspace(*cursor)) { - errprintf ("invalid argument to --percentiles '%s'", str); - exit (EXIT_FAILURE); + errprintf("invalid argument to --percentiles '%s'", str); + exit(EXIT_FAILURE); } cursor++; } // no number: error if (k == 1) { - errprintf ("invalid argument to --percentiles '%s'", str); - exit (EXIT_FAILURE); + errprintf("invalid argument to --percentiles '%s'", str); + exit(EXIT_FAILURE); } return k - 1; } -static int read_ints (int *levels, char *str) +static int +read_ints(int * levels, char * str) { char * cursor; char * endp = str; @@ -109,7 +128,7 @@ static int read_ints (int *levels, char *str) do { cursor = endp; - levels[k] = (int) strtol(cursor, &endp, 10); + levels[k] = (int)strtol(cursor, &endp, 10); if (cursor == endp && (*endp == ',' || *endp == ';')) { endp++; continue; @@ -120,29 +139,29 @@ static int read_ints (int *levels, char *str) // not end of string: error while (*cursor != '\0') { if (!isspace(*cursor)) { - errprintf ("invalid argument to --levels '%s'", str); - exit (EXIT_FAILURE); + errprintf("invalid argument to --levels '%s'", str); + exit(EXIT_FAILURE); } cursor++; } // no number: error if (k == 1) { - errprintf ("invalid argument to --levels '%s'", str); - exit (EXIT_FAILURE); + errprintf("invalid argument to --levels '%s'", str); + exit(EXIT_FAILURE); } return k - 1; } static void -eaf_print (eaf_t **eaf, int nobj, int nlevels, - FILE *coord_file, FILE *indic_file, FILE *diff_file) +eaf_print(eaf_t ** eaf, int nobj, int nlevels, FILE * coord_file, + FILE * indic_file, FILE * diff_file) { for (int k = 0; k < nlevels; k++) { - eaf_print_attsurf (eaf[k], nobj, coord_file, indic_file, diff_file); + eaf_print_attsurf(eaf[k], nobj, coord_file, indic_file, diff_file); if (coord_file) - fprintf (coord_file, "\n"); + fprintf(coord_file, "\n"); else if (indic_file) fprintf(indic_file, "\n"); else if (diff_file) @@ -150,72 +169,75 @@ eaf_print (eaf_t **eaf, int nobj, int nlevels, } } -void read_input_data (const char *filename, objective_t **data_p, - int *nobjs_p, int **cumsizes_p, int *nsets_p) +void +read_input_data(const char * filename, objective_t ** data_p, int * nobjs_p, + int ** cumsizes_p, int * nsets_p) { - int error = read_objective_t_data (filename, data_p, nobjs_p, cumsizes_p, nsets_p); + int error = + read_objective_t_data(filename, data_p, nobjs_p, cumsizes_p, nsets_p); switch (error) { - case 0: /* No error */ - break; - case READ_INPUT_FILE_EMPTY: - case READ_INPUT_WRONG_INITIAL_DIM: - break; - case ERROR_FOPEN: - case ERROR_CONVERSION: - case ERROR_COLUMNS: - exit (EXIT_FAILURE); - default: - exit (EXIT_FAILURE); + case 0: /* No error */ + break; + case READ_INPUT_FILE_EMPTY: + case READ_INPUT_WRONG_INITIAL_DIM: + break; + case ERROR_FOPEN: + case ERROR_CONVERSION: + case ERROR_COLUMNS: + exit(EXIT_FAILURE); + default: + exit(EXIT_FAILURE); } } -int main(int argc, char *argv[]) +int +main(int argc, char * argv[]) { bool verbose_flag = true; - bool best_flag = false; + bool best_flag = false; bool median_flag = false; - bool worst_flag = false; - bool polygon_flag = false; - const char *coord_filename = NULL; - const char *indic_filename = NULL; - const char *diff_filename = NULL; - FILE *coord_file = stdout; - FILE *indic_file = NULL; - FILE *diff_file = NULL; + bool worst_flag = false; + bool polygon_flag = false; + const char * coord_filename = NULL; + const char * indic_filename = NULL; + const char * diff_filename = NULL; + FILE * coord_file = stdout; + FILE * indic_file = NULL; + FILE * diff_file = NULL; int option; int longopt_index; /* see the man page for getopt_long for an explanation of these fields */ static const char short_options[] = "hVvqbmwl:p:o:i::d::P"; static const struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {"verbose", no_argument, NULL, 'v'}, - {"quiet", no_argument, NULL, 'q'}, - {"best", no_argument, NULL, 'b'}, - {"median", no_argument, NULL, 'm'}, - {"worst", no_argument, NULL, 'w'}, - {"output", required_argument, NULL, 'o'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {"verbose", no_argument, NULL, 'v'}, + {"quiet", no_argument, NULL, 'q'}, + {"best", no_argument, NULL, 'b'}, + {"median", no_argument, NULL, 'm'}, + {"worst", no_argument, NULL, 'w'}, + {"output", required_argument, NULL, 'o'}, /* The optional_argument must be together with the parameter such as -iFILE or -i=FILE, otherwise it will be considered an input file. */ - {"indices", optional_argument, NULL, 'i'}, - {"diff", optional_argument, NULL, 'd'}, + {"indices", optional_argument, NULL, 'i'}, + {"diff", optional_argument, NULL, 'd'}, {"percentile", required_argument, NULL, 'p'}, - {"level", required_argument, NULL, 'l'}, - {"polygons", no_argument, NULL, 'P'}, + {"level", required_argument, NULL, 'l'}, + {"polygons", no_argument, NULL, 'P'}, {NULL, 0, NULL, 0} /* marks end of list */ }; #define MAX_LEVELS 50 - int *level = malloc(MAX_LEVELS * sizeof(int)); + int * level = malloc(MAX_LEVELS * sizeof(int)); int nlevels = 0; - double *percentile = malloc(MAX_LEVELS * sizeof(double)); + double * percentile = malloc(MAX_LEVELS * sizeof(double)); int npercentiles = 0; set_program_invocation_short_name(argv[0]); - while (0 < (option = getopt_long(argc, argv, short_options, - long_options, &longopt_index))) { + while (0 < (option = getopt_long(argc, argv, short_options, long_options, + &longopt_index))) { switch (option) { case 'l': assert(nlevels < MAX_LEVELS); @@ -228,40 +250,36 @@ int main(int argc, char *argv[]) break; case 'o': - if (!strcmp(optarg,"-")) { - coord_file = stdout; + if (!strcmp(optarg, "-")) { + coord_file = stdout; coord_filename = NULL; } else coord_filename = optarg; - break; + break; - case 'i': + case 'i': if (!optarg) { indic_file = stdin; /* Overwrite with coord_file later. */ indic_filename = NULL; - } - else if (!strcmp(optarg,"-")) { - indic_file = stdout; + } else if (!strcmp(optarg, "-")) { + indic_file = stdout; indic_filename = NULL; - } - else { + } else { indic_filename = optarg; } - break; + break; - case 'd': + case 'd': if (!optarg) { diff_file = stdin; /* Overwrite with coord_file later. */ diff_filename = NULL; - } - else if (!strcmp(optarg,"-")) { - diff_file = stdout; + } else if (!strcmp(optarg, "-")) { + diff_file = stdout; diff_filename = NULL; - } - else { + } else { diff_filename = optarg; } - break; + break; case 'b': best_flag = true; @@ -292,26 +310,25 @@ int main(int argc, char *argv[]) } } - objective_t *data = NULL; - int* cumsizes = NULL; + objective_t * data = NULL; + int * cumsizes = NULL; int nobj = 0, nruns = 0, k; if (optind < argc) { for (k = optind; k < argc; k++) { - if (strcmp (argv[k],"-")) - read_input_data (argv[k], &data, &nobj, - &cumsizes, &nruns); + if (strcmp(argv[k], "-")) + read_input_data(argv[k], &data, &nobj, &cumsizes, &nruns); else - read_input_data (NULL, &data, &nobj, &cumsizes, &nruns); + read_input_data(NULL, &data, &nobj, &cumsizes, &nruns); } } else - read_input_data (NULL, &data, &nobj, &cumsizes, &nruns); + read_input_data(NULL, &data, &nobj, &cumsizes, &nruns); if (coord_filename) { - coord_file = fopen (coord_filename, "w"); + coord_file = fopen(coord_filename, "w"); if (NULL == coord_file) { - errprintf ("%s: %s", coord_filename, strerror (errno)); - exit (EXIT_FAILURE); + errprintf("%s: %s", coord_filename, strerror(errno)); + exit(EXIT_FAILURE); } } @@ -322,12 +339,12 @@ int main(int argc, char *argv[]) indic_filename = coord_filename; } /* If a different filename as for --output was given, open it. */ - if (indic_filename - && (!coord_filename || strcmp (indic_filename, coord_filename))) { - indic_file = fopen (indic_filename, "w"); + if (indic_filename && + (!coord_filename || strcmp(indic_filename, coord_filename))) { + indic_file = fopen(indic_filename, "w"); if (NULL == indic_file) { - errprintf ("%s: %s", indic_filename, strerror (errno)); - exit (EXIT_FAILURE); + errprintf("%s: %s", indic_filename, strerror(errno)); + exit(EXIT_FAILURE); } } @@ -339,12 +356,12 @@ int main(int argc, char *argv[]) } /* If a different filename as for --output and --indices was given, open it. */ - if (diff_filename - && (!coord_filename || strcmp (diff_filename, coord_filename)) - && (!indic_filename || strcmp (diff_filename, indic_filename))) { - diff_file = fopen (diff_filename, "w"); + if (diff_filename && + (!coord_filename || strcmp(diff_filename, coord_filename)) && + (!indic_filename || strcmp(diff_filename, indic_filename))) { + diff_file = fopen(diff_filename, "w"); if (NULL == diff_file) { - errprintf ("%s: %s", diff_filename, strerror (errno)); + errprintf("%s: %s", diff_filename, strerror(errno)); exit(EXIT_FAILURE); } } @@ -352,72 +369,65 @@ int main(int argc, char *argv[]) if (best_flag) { level[0] = 1; nlevels = 1; - } - else if (median_flag) { - level[0] = percentile2level (50, nruns); + } else if (median_flag) { + level[0] = percentile2level(50, nruns); nlevels = 1; - } - else if (worst_flag) { + } else if (worst_flag) { level[0] = nruns; nlevels = 1; - } - else if (npercentiles > 0) { + } else if (npercentiles > 0) { nlevels = npercentiles; for (k = 0; k < nlevels; k++) { if (percentile[k] <= 0) { - errprintf ("arg to --percentile must be higher than 0.\n"); - exit (EXIT_FAILURE); + errprintf("arg to --percentile must be higher than 0.\n"); + exit(EXIT_FAILURE); } else if (percentile[k] > 100) { - errprintf ("arg to --percentile must be <= 100.\n"); - exit (EXIT_FAILURE); + errprintf("arg to --percentile must be <= 100.\n"); + exit(EXIT_FAILURE); } level[k] = percentile2level(percentile[k], nruns); } - } - else if (nlevels > 0) { - level = realloc (level, nlevels * sizeof(int)); + } else if (nlevels > 0) { + level = realloc(level, nlevels * sizeof(int)); for (k = 0; k < nlevels; k++) { if (level[k] <= 0) { - errprintf ("arg to --level must be higher than 0.\n"); - exit (EXIT_FAILURE); + errprintf("arg to --level must be higher than 0.\n"); + exit(EXIT_FAILURE); } else if (level[k] > nruns) { - errprintf ("arg to --level must not be higher than number of" - " approximation sets (%d).\n", nruns); - exit (EXIT_FAILURE); + errprintf("arg to --level must not be higher than number of" + " approximation sets (%d).\n", + nruns); + exit(EXIT_FAILURE); } } - } - else if (nlevels == 0) { + } else if (nlevels == 0) { nlevels = nruns; - level = realloc (level, nlevels * sizeof(int)); + level = realloc(level, nlevels * sizeof(int)); for (k = 0; k < nruns; k++) { level[k] = k + 1; } } if (verbose_flag) { - fprintf (stderr, "# objectives (%d): --\n", nobj); - fprintf (stderr, "# sets: %d\n", nruns); - fprintf (stderr, "# points: %d\n", cumsizes[nruns - 1]); - fprintf (stderr, "# calculating levels:"); - for (k = 0; k < nlevels; k++) - fprintf (stderr, " %d", level[k]); - fprintf (stderr, "\n"); + fprintf(stderr, "# objectives (%d): --\n", nobj); + fprintf(stderr, "# sets: %d\n", nruns); + fprintf(stderr, "# points: %d\n", cumsizes[nruns - 1]); + fprintf(stderr, "# calculating levels:"); + for (k = 0; k < nlevels; k++) fprintf(stderr, " %d", level[k]); + fprintf(stderr, "\n"); } - eaf_t **eaf = attsurf (data, nobj, cumsizes, nruns, level, nlevels); + eaf_t ** eaf = attsurf(data, nobj, cumsizes, nruns, level, nlevels); if (polygon_flag) { - eaf_print_polygon (coord_file, eaf, nobj, nlevels); - fclose (coord_file); + eaf_print_polygon(coord_file, eaf, nobj, nlevels); + fclose(coord_file); } else { - eaf_print (eaf, nobj, nlevels, - coord_file, indic_file, diff_file); - fclose (coord_file); - if (indic_file && indic_file != coord_file) - fclose (indic_file); + eaf_print(eaf, nobj, nlevels, coord_file, indic_file, diff_file); + fclose(coord_file); + if (indic_file && indic_file != coord_file) fclose(indic_file); if (diff_file && diff_file != coord_file && diff_file != indic_file) - fclose (diff_file); + fclose(diff_file); } free(level); diff --git a/c/eafdiff.c b/c/eafdiff.c index 4f605093..7986d3b8 100644 --- a/c/eafdiff.c +++ b/c/eafdiff.c @@ -3,32 +3,31 @@ /* FIXME: Rmoocore.R contains another version of this function. */ /* FIXME: data cannot be const because eaf_compute_rectangles will sort it. */ double * -eafdiff_compute_rectangles(int *eaf_npoints, double * data, int nobj, - const int *cumsizes, int nruns, int intervals) +eafdiff_compute_rectangles(int * eaf_npoints, double * data, int nobj, + const int * cumsizes, int nruns, int intervals) { /* This returns all levels. attsurf() should probably handle this case. */ int * level = levels_from_percentiles(NULL, nruns, nruns); - eaf_t **eaf = attsurf(data, nobj, cumsizes, nruns, level, nruns); - free (level); + eaf_t ** eaf = attsurf(data, nobj, cumsizes, nruns, level, nruns); + free(level); eaf_polygon_t * rects = eaf_compute_rectangles(eaf, nobj, nruns); eaf_free(eaf, nruns); const int division = nruns / 2; - int nrow = (int) vector_int_size(&rects->col); + int nrow = (int)vector_int_size(&rects->col); // Two points per row + color const int ncol = 2 * nobj + 1; - double *result = malloc(sizeof(double) * nrow * ncol); + double * result = malloc(sizeof(double) * nrow * ncol); const double * p_xy = vector_objective_begin(&rects->xy); for (int k = 0; k < nrow; k++) { - for (int i = 0; i < ncol - 1; i++, p_xy++) - result[k * ncol + i] = *p_xy; + for (int i = 0; i < ncol - 1; i++, p_xy++) result[k * ncol + i] = *p_xy; double color = vector_int_at(&rects->col, k); // Each color is within [0, nruns / 2] or [-nruns / 2, 0] - result[k * ncol + ncol - 1] = intervals * color / (double) division; + result[k * ncol + ncol - 1] = intervals * color / (double)division; } - vector_objective_dtor (&rects->xy); - vector_int_dtor (&rects->col); + vector_objective_dtor(&rects->xy); + vector_int_dtor(&rects->col); free(rects); *eaf_npoints = nrow; // FIXME: This may return duplicated rows, remove them. @@ -36,29 +35,30 @@ eafdiff_compute_rectangles(int *eaf_npoints, double * data, int nobj, } double * -eafdiff_compute_matrix(int *eaf_npoints, double * data, int nobj, - const int *cumsizes, int nruns, int intervals) +eafdiff_compute_matrix(int * eaf_npoints, double * data, int nobj, + const int * cumsizes, int nruns, int intervals) { // FIXME: This assumes that half of the runs come from each side of the // difference but we could make this a parameter. const int nsets1 = nruns / 2; /* This returns all levels. attsurf() should probably handle this case. */ int * level = levels_from_percentiles(NULL, nruns, nruns); - eaf_t **eaf = attsurf(data, nobj, cumsizes, nruns, level, nruns); - free (level); + eaf_t ** eaf = attsurf(data, nobj, cumsizes, nruns, level, nruns); + free(level); - const int nrow = eaf_totalpoints (eaf, nruns); + const int nrow = eaf_totalpoints(eaf, nruns); const int ncol = nobj + 1; - double *result = malloc(sizeof(double) * nrow * ncol); + double * result = malloc(sizeof(double) * nrow * ncol); int pos = 0; for (int k = 0; k < nruns; k++) { - int npoints = (int) eaf[k]->size; + int npoints = (int)eaf[k]->size; // FIXME: Find the most efficient order of the loop. for (int i = 0; i < npoints; i++) { for (int j = 0; j < nobj; j++) { result[pos * ncol + j] = eaf[k]->data[i * nobj + j]; } - result[pos * ncol + nobj] = eafdiff_percentile(eaf[k], i, nsets1, nruns, intervals); + result[pos * ncol + nobj] = + eafdiff_percentile(eaf[k], i, nsets1, nruns, intervals); pos++; } } diff --git a/c/epsilon.c b/c/epsilon.c index df350906..103dc463 100644 --- a/c/epsilon.c +++ b/c/epsilon.c @@ -44,7 +44,7 @@ #include #include #include -#include // for getopt() +#include // for getopt() #include // for getopt_long() #include "epsilon.h" @@ -55,9 +55,10 @@ static bool verbose_flag = false; static bool additive_flag = true; -static const char *suffix = NULL; +static const char * suffix = NULL; -static void usage(void) +static void +usage(void) { printf("\n" "Usage:\n" @@ -66,51 +67,55 @@ static void usage(void) program_invocation_short_name, program_invocation_short_name); printf( -"Calculates the epsilon measure for the Pareto sets given as input\n\n" - -"Options:\n" -OPTION_HELP_STR -OPTION_VERSION_STR -" -v, --verbose print some information (time, number of points, etc.).\n" -OPTION_QUIET_STR -" -a, --additive epsilon additive value %s. \n" -" -m, --multiplicative epsilon multiplicative value %s. \n" -" -r, --reference FILE file that contains the reference set \n" -OPTION_OBJ_STR -OPTION_MAXIMISE_STR -" -s, --suffix=STRING Create an output file for each input file by appending\n" -" this suffix. This is ignored when reading from stdin. \n" -" If missing, output is sent to stdout. \n" -"\n", str_is_default(additive_flag), str_is_default(!additive_flag)); + "Calculates the epsilon measure for the Pareto sets given as input\n\n" + + "Options:\n" OPTION_HELP_STR OPTION_VERSION_STR + " -v, --verbose print some information (time, number of points, " + "etc.).\n" OPTION_QUIET_STR " -a, --additive epsilon additive " + "value %s. \n" + " -m, --multiplicative epsilon multiplicative value %s. " + " \n" + " -r, --reference FILE file that contains the reference set " + " \n" OPTION_OBJ_STR OPTION_MAXIMISE_STR + " -s, --suffix=STRING Create an output file for each input file by " + "appending\n" + " this suffix. This is ignored when reading from " + "stdin. \n" + " If missing, output is sent to stdout. " + " \n" + "\n", + str_is_default(additive_flag), str_is_default(!additive_flag)); } static void -do_file (const char *filename, double *reference, size_t reference_size, - int *nobj_p, const signed char * minmax, bool maximise_all_flag) +do_file(const char * filename, double * reference, size_t reference_size, + int * nobj_p, const signed char * minmax, bool maximise_all_flag) { - double *data = NULL; - int *cumsizes = NULL; + double * data = NULL; + int * cumsizes = NULL; int nruns = 0; int nobj = *nobj_p; handle_read_data_error( - read_double_data (filename, &data, &nobj, &cumsizes, &nruns), filename); - if (!filename) - filename = stdin_name; - - if (!additive_flag && !all_positive(data, cumsizes[nruns - 1], (dimension_t) nobj)) { - errprintf("cannot calculate multiplicative epsilon indicator with non-positive values when reading '%s'.", filename); + read_double_data(filename, &data, &nobj, &cumsizes, &nruns), filename); + if (!filename) filename = stdin_name; + + if (!additive_flag && + !all_positive(data, cumsizes[nruns - 1], (dimension_t)nobj)) { + errprintf("cannot calculate multiplicative epsilon indicator with " + "non-positive values when reading '%s'.", + filename); exit(EXIT_FAILURE); } - char *outfilename = NULL; - FILE *outfile = stdout; + char * outfilename = NULL; + FILE * outfile = stdout; if (filename != stdin_name && suffix) { outfilename = m_strcat(filename, suffix); - outfile = fopen (outfilename, "w"); + outfile = fopen(outfilename, "w"); if (outfile == NULL) { - errprintf ("%s: %s\n", outfilename, strerror(errno)); - exit (EXIT_FAILURE); + errprintf("%s: %s\n", outfilename, strerror(errno)); + exit(EXIT_FAILURE); } } #if 0 @@ -120,34 +125,35 @@ do_file (const char *filename, double *reference, size_t reference_size, } #endif ASSUME(nobj > 1 && nobj < 256); - dimension_t dim = (dimension_t) nobj; + dimension_t dim = (dimension_t)nobj; /* Default minmax if not set yet. */ bool free_minmax = false; if (minmax == NULL) { - minmax = maximise_all_flag ? minmax_maximise(dim) : minmax_minimise(dim); + minmax = + maximise_all_flag ? minmax_maximise(dim) : minmax_minimise(dim); free_minmax = true; } - if (verbose_flag) - printf("# file: %s\n", filename); + if (verbose_flag) printf("# file: %s\n", filename); for (int n = 0, cumsize = 0; n < nruns; cumsize = cumsizes[n], n++) { // double time_elapsed = 0; //Timer_start (); - double epsilon = (additive_flag) - ? epsilon_additive_minmax (dim, minmax, - &data[nobj * cumsize], cumsizes[n] - cumsize, - reference, reference_size) - : epsilon_mult_minmax (dim, minmax, - &data[nobj * cumsize], cumsizes[n] - cumsize, - reference, reference_size); + double epsilon = + (additive_flag) + ? epsilon_additive_minmax(dim, minmax, &data[nobj * cumsize], + cumsizes[n] - cumsize, reference, + reference_size) + : epsilon_mult_minmax(dim, minmax, &data[nobj * cumsize], + cumsizes[n] - cumsize, reference, + reference_size); // time_elapsed = Timer_elapsed_virtual (); - fprintf (outfile, indicator_printf_format "\n", epsilon); + fprintf(outfile, indicator_printf_format "\n", epsilon); if ((additive_flag && epsilon < 0) || (!additive_flag && epsilon < 1)) { - errprintf ("%s: some points are not dominated by the reference set", - filename); - exit (EXIT_FAILURE); - }/* + errprintf("%s: some points are not dominated by the reference set", + filename); + exit(EXIT_FAILURE); + } /* if (verbose_flag) fprintf (outfile, "# Time: %f seconds\n", time_elapsed); */ @@ -155,40 +161,41 @@ do_file (const char *filename, double *reference, size_t reference_size, if (outfilename) { if (verbose_flag) - fprintf (stderr, "# %s -> %s\n", filename, outfilename); - fclose (outfile); - free (outfilename); + fprintf(stderr, "# %s -> %s\n", filename, outfilename); + fclose(outfile); + free(outfilename); } - free (data); - free (cumsizes); - if (free_minmax) free( (void *) minmax); + free(data); + free(cumsizes); + if (free_minmax) free((void *)minmax); *nobj_p = nobj; } -int main(int argc, char *argv[]) +int +main(int argc, char * argv[]) { bool check_flag = true; - double *reference = NULL; + double * reference = NULL; size_t reference_size = 0; - const signed char *minmax = NULL; + const signed char * minmax = NULL; bool maximise_all_flag = false; int nobj = 0, tmp_nobj = 0; /* see the man page for getopt_long for an explanation of these fields */ static const char short_options[] = "hVvqamMr:s:o:"; static const struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {"verbose", no_argument, NULL, 'v'}, - {"quiet", no_argument, NULL, 'q'}, - {"no-check", no_argument, NULL, 'c'}, - {"additive", no_argument, NULL, 'a'}, - {"multiplicative", no_argument, NULL, 'm'}, - {"maximise", no_argument, NULL, 'M'}, - {"maximize", no_argument, NULL, 'M'}, - {"reference", required_argument, NULL, 'r'}, - {"suffix", required_argument, NULL, 's'}, - {"obj", required_argument, NULL, 'o'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {"verbose", no_argument, NULL, 'v'}, + {"quiet", no_argument, NULL, 'q'}, + {"no-check", no_argument, NULL, 'c'}, + {"additive", no_argument, NULL, 'a'}, + {"multiplicative", no_argument, NULL, 'm'}, + {"maximise", no_argument, NULL, 'M'}, + {"maximize", no_argument, NULL, 'M'}, + {"reference", required_argument, NULL, 'r'}, + {"suffix", required_argument, NULL, 's'}, + {"obj", required_argument, NULL, 'o'}, {NULL, 0, NULL, 0} /* marks end of list */ }; @@ -196,10 +203,10 @@ int main(int argc, char *argv[]) int opt; /* it's actually going to hold a char */ int longopt_index; - while (0 < (opt = getopt_long(argc, argv, short_options, - long_options, &longopt_index))) { + while (0 < (opt = getopt_long(argc, argv, short_options, long_options, + &longopt_index))) { switch (opt) { - case 'c': // --no-check + case 'c': // --no-check check_flag = false; break; @@ -222,13 +229,15 @@ int main(int argc, char *argv[]) case 'r': // --reference reference_size = read_reference_set(&reference, optarg, &tmp_nobj); if (reference == NULL || reference_size == 0) { - errprintf ("invalid reference set '%s", optarg); + errprintf("invalid reference set '%s", optarg); exit(EXIT_FAILURE); } if (nobj == 0) { nobj = tmp_nobj; } else if (tmp_nobj != nobj) { - errprintf ("number of objectives in --obj (%d) and reference set (%d) do not match", nobj, tmp_nobj); + errprintf("number of objectives in --obj (%d) and reference " + "set (%d) do not match", + nobj, tmp_nobj); exit(EXIT_FAILURE); } break; @@ -251,34 +260,40 @@ int main(int argc, char *argv[]) } if (verbose_flag) - fprintf (stderr, (additive_flag) - ? "# Additive epsilon indicator\n" - : "# Multiplicative epsilon indicator\n"); + fprintf(stderr, (additive_flag) + ? "# Additive epsilon indicator\n" + : "# Multiplicative epsilon indicator\n"); if (reference == NULL) { - errprintf ("a reference set must be provided (--reference)"); - exit (EXIT_FAILURE); + errprintf("a reference set must be provided (--reference)"); + exit(EXIT_FAILURE); } if (minmax == NULL) { - minmax = maximise_all_flag ? minmax_maximise((dimension_t) nobj) : minmax_minimise((dimension_t) nobj); + minmax = maximise_all_flag ? minmax_maximise((dimension_t)nobj) + : minmax_minimise((dimension_t)nobj); } if (check_flag) { /* Ensure the reference set is nondominated. */ size_t prev_reference_size = reference_size; - reference_size = filter_dominated_set(reference, nobj, reference_size, minmax); + reference_size = + filter_dominated_set(reference, nobj, reference_size, minmax); if (prev_reference_size > reference_size) warnprintf("removed %zd dominated points from the reference set", prev_reference_size - reference_size); } - if (!additive_flag && !all_positive(reference, reference_size, (dimension_t) nobj)) { - errprintf("cannot calculate multiplicative epsilon indicator with non-positive values in reference front."); + if (!additive_flag && + !all_positive(reference, reference_size, (dimension_t)nobj)) { + errprintf("cannot calculate multiplicative epsilon indicator with " + "non-positive values in reference front."); exit(EXIT_FAILURE); } int numfiles = argc - optind; if (numfiles < 1) { /* Read stdin. */ - do_file (NULL, reference, reference_size, &nobj, minmax, maximise_all_flag); + do_file(NULL, reference, reference_size, &nobj, minmax, + maximise_all_flag); } else if (numfiles == 1) { - do_file (argv[optind], reference, reference_size, &nobj, minmax, maximise_all_flag); + do_file(argv[optind], reference, reference_size, &nobj, minmax, + maximise_all_flag); } else { int k; /* FIXME: Calculate the nondominated front among all input @@ -303,10 +318,11 @@ int main(int argc, char *argv[]) } #endif for (k = 0; k < numfiles; k++) - do_file (argv[optind + k], reference, reference_size, &nobj, minmax, maximise_all_flag); + do_file(argv[optind + k], reference, reference_size, &nobj, minmax, + maximise_all_flag); } free(reference); - free((void*)minmax); + free((void *)minmax); return EXIT_SUCCESS; } diff --git a/c/epsilon.h b/c/epsilon.h index 6290d72e..01862bdf 100644 --- a/c/epsilon.h +++ b/c/epsilon.h @@ -6,7 +6,7 @@ #include #include #ifndef INFINITY -#define INFINITY (HUGE_VAL) +# define INFINITY (HUGE_VAL) #endif #include "common.h" @@ -16,8 +16,7 @@ all_positive(const double * restrict points, size_t size, dimension_t dim) ASSUME(dim <= 32); for (size_t a = 0; a < size; a++) for (dimension_t d = 0; d < dim; d++) - if (points[a * dim + d] <= 0) - return false; + if (points[a * dim + d] <= 0) return false; return true; } @@ -42,9 +41,9 @@ all_positive(const double * restrict points, size_t size, dimension_t dim) for negative values doesn't make sense. */ static inline double -epsilon_mult_minimize(dimension_t dim, - const double * restrict points_a, size_t size_a, - const double * restrict points_b, size_t size_b) +epsilon_mult_minimize(dimension_t dim, const double * restrict points_a, + size_t size_a, const double * restrict points_b, + size_t size_b) { ASSUME(dim >= 2); ASSUME(dim <= 32); @@ -56,17 +55,17 @@ epsilon_mult_minimize(dimension_t dim, double epsilon_min = INFINITY; for (a = 0; a < size_a; a++) { double epsilon_max = points_a[a * dim + 0] / points_b[b * dim + 0]; - if (epsilon_max >= epsilon_min) - continue; + if (epsilon_max >= epsilon_min) continue; for (d = 1; d < dim; d++) { - double epsilon_temp = points_a[a * dim + d] / points_b[b * dim + d]; + double epsilon_temp = + points_a[a * dim + d] / points_b[b * dim + d]; epsilon_max = MAX(epsilon_max, epsilon_temp); } if (epsilon_max <= epsilon) { skip_max = true; break; } - epsilon_min = MIN (epsilon_min, epsilon_max); + epsilon_min = MIN(epsilon_min, epsilon_max); } if (skip_max) continue; epsilon = MAX(epsilon, epsilon_min); @@ -75,9 +74,9 @@ epsilon_mult_minimize(dimension_t dim, } static inline double -epsilon_mult_maximize(dimension_t dim, - const double * restrict points_a, size_t size_a, - const double * restrict points_b, size_t size_b) +epsilon_mult_maximize(dimension_t dim, const double * restrict points_a, + size_t size_a, const double * restrict points_b, + size_t size_b) { ASSUME(dim >= 2); ASSUME(dim <= 32); @@ -89,17 +88,17 @@ epsilon_mult_maximize(dimension_t dim, double epsilon_min = INFINITY; for (a = 0; a < size_a; a++) { double epsilon_max = points_b[b * dim + 0] / points_a[a * dim + 0]; - if (epsilon_max >= epsilon_min) - continue; + if (epsilon_max >= epsilon_min) continue; for (d = 1; d < dim; d++) { - double epsilon_temp = points_b[b * dim + d] / points_a[a * dim + d]; - epsilon_max = MAX (epsilon_max, epsilon_temp); + double epsilon_temp = + points_b[b * dim + d] / points_a[a * dim + d]; + epsilon_max = MAX(epsilon_max, epsilon_temp); } if (epsilon_max <= epsilon) { skip_max = true; break; } - epsilon_min = MIN (epsilon_min, epsilon_max); + epsilon_min = MIN(epsilon_min, epsilon_max); } if (skip_max) continue; epsilon = MAX(epsilon, epsilon_min); @@ -108,7 +107,7 @@ epsilon_mult_maximize(dimension_t dim, } static inline double -epsilon_mult_minmax_ (dimension_t dim, const signed char * restrict minmax, +epsilon_mult_minmax_(dimension_t dim, const signed char * restrict minmax, const double * restrict points_a, size_t size_a, const double * restrict points_b, size_t size_b) { @@ -119,63 +118,67 @@ epsilon_mult_minmax_ (dimension_t dim, const signed char * restrict minmax, bool skip_max = false; double epsilon_min = INFINITY; for (a = 0; a < size_a; a++) { - double epsilon_max = (minmax[0] < 0) - ? points_a[a * dim + 0] / points_b[b * dim + 0] + double epsilon_max = + (minmax[0] < 0) ? points_a[a * dim + 0] / points_b[b * dim + 0] : (minmax[0] > 0) - ? points_b[b * dim + 0] / points_a[a * dim + 0] - : 0; - if (epsilon_max >= epsilon_min) - continue; + ? points_b[b * dim + 0] / points_a[a * dim + 0] + : 0; + if (epsilon_max >= epsilon_min) continue; for (d = 1; d < dim; d++) { double epsilon_temp; if (minmax[d] < 0) - epsilon_temp = points_a[a * dim + d] / points_b[b * dim + d]; + epsilon_temp = + points_a[a * dim + d] / points_b[b * dim + d]; else if (minmax[d] > 0) - epsilon_temp = points_b[b * dim + d] / points_a[a * dim + d]; + epsilon_temp = + points_b[b * dim + d] / points_a[a * dim + d]; else - epsilon_temp = 1; + epsilon_temp = 1; ASSUME(epsilon_temp >= 0); - epsilon_max = MAX (epsilon_max, epsilon_temp); + epsilon_max = MAX(epsilon_max, epsilon_temp); } if (epsilon_max <= epsilon) { skip_max = true; break; } - epsilon_min = MIN (epsilon_min, epsilon_max); + epsilon_min = MIN(epsilon_min, epsilon_max); } if (skip_max) continue; - epsilon = MAX (epsilon, epsilon_min); + epsilon = MAX(epsilon, epsilon_min); } return epsilon; } static inline double -epsilon_mult_minmax (dimension_t dim, const signed char * restrict minmax, - const double * restrict points_a, size_t size_a, - const double * restrict points_b, size_t size_b) +epsilon_mult_minmax(dimension_t dim, const signed char * restrict minmax, + const double * restrict points_a, size_t size_a, + const double * restrict points_b, size_t size_b) { #if DEBUG >= 1 - if (!all_positive(points_a, size_a, dim) || !all_positive(points_b, size_b, dim)) { - errprintf("cannot calculate multiplicative epsilon indicator with values <= 0."); + if (!all_positive(points_a, size_a, dim) || + !all_positive(points_b, size_b, dim)) { + errprintf("cannot calculate multiplicative epsilon indicator with " + "values <= 0."); return INFINITY; } #endif switch (check_all_minimize_maximize(minmax, dim)) { - case AGREE_MINIMISE: - return epsilon_mult_minimize(dim, points_a, size_a, points_b, size_b); - case AGREE_MAXIMISE: - return epsilon_mult_maximize(dim, points_a, size_a, points_b, size_b); - default: - return epsilon_mult_minmax_(dim, minmax, points_a, size_a, points_b, size_b); + case AGREE_MINIMISE: + return epsilon_mult_minimize(dim, points_a, size_a, points_b, size_b); + case AGREE_MAXIMISE: + return epsilon_mult_maximize(dim, points_a, size_a, points_b, size_b); + default: + return epsilon_mult_minmax_(dim, minmax, points_a, size_a, points_b, + size_b); } } static inline double -epsilon_additive_minimize(dimension_t dim, - const double * restrict points_a, size_t size_a, - const double * restrict points_b, size_t size_b) +epsilon_additive_minimize(dimension_t dim, const double * restrict points_a, + size_t size_a, const double * restrict points_b, + size_t size_b) { ASSUME(dim >= 2); ASSUME(dim <= 32); @@ -187,17 +190,17 @@ epsilon_additive_minimize(dimension_t dim, double epsilon_min = INFINITY; for (a = 0; a < size_a; a++) { double epsilon_max = points_a[a * dim + 0] - points_b[b * dim + 0]; - if (epsilon_max >= epsilon_min) - continue; + if (epsilon_max >= epsilon_min) continue; for (d = 1; d < dim; d++) { - double epsilon_temp = points_a[a * dim + d] - points_b[b * dim + d]; + double epsilon_temp = + points_a[a * dim + d] - points_b[b * dim + d]; epsilon_max = MAX(epsilon_max, epsilon_temp); } if (epsilon_max <= epsilon) { skip_max = true; break; } - epsilon_min = MIN (epsilon_min, epsilon_max); + epsilon_min = MIN(epsilon_min, epsilon_max); } if (skip_max) continue; epsilon = MAX(epsilon, epsilon_min); @@ -206,9 +209,9 @@ epsilon_additive_minimize(dimension_t dim, } static inline double -epsilon_additive_maximize(dimension_t dim, - const double * restrict points_a, size_t size_a, - const double * restrict points_b, size_t size_b) +epsilon_additive_maximize(dimension_t dim, const double * restrict points_a, + size_t size_a, const double * restrict points_b, + size_t size_b) { ASSUME(dim >= 2); ASSUME(dim <= 32); @@ -220,17 +223,17 @@ epsilon_additive_maximize(dimension_t dim, double epsilon_min = INFINITY; for (a = 0; a < size_a; a++) { double epsilon_max = points_b[b * dim + 0] - points_a[a * dim + 0]; - if (epsilon_max >= epsilon_min) - continue; + if (epsilon_max >= epsilon_min) continue; for (d = 1; d < dim; d++) { - double epsilon_temp = points_b[b * dim + d] - points_a[a * dim + d]; - epsilon_max = MAX (epsilon_max, epsilon_temp); + double epsilon_temp = + points_b[b * dim + d] - points_a[a * dim + d]; + epsilon_max = MAX(epsilon_max, epsilon_temp); } if (epsilon_max <= epsilon) { skip_max = true; break; } - epsilon_min = MIN (epsilon_min, epsilon_max); + epsilon_min = MIN(epsilon_min, epsilon_max); } if (skip_max) continue; epsilon = MAX(epsilon, epsilon_min); @@ -250,26 +253,26 @@ epsilon_additive_minmax_(dimension_t dim, const signed char * restrict minmax, bool skip_max = false; double epsilon_min = INFINITY; for (a = 0; a < size_a; a++) { - double epsilon_max = (minmax[0] < 0) - ? points_a[a * dim + 0] - points_b[b * dim + 0] + double epsilon_max = + (minmax[0] < 0) ? points_a[a * dim + 0] - points_b[b * dim + 0] : (minmax[0] > 0) - ? points_b[b * dim + 0] - points_a[a * dim + 0] - : 0; - if (epsilon_max >= epsilon_min) - continue; + ? points_b[b * dim + 0] - points_a[a * dim + 0] + : 0; + if (epsilon_max >= epsilon_min) continue; for (d = 1; d < dim; d++) { - double epsilon_temp = points_a[a * dim + d] - points_b[b * dim + d]; + double epsilon_temp = + points_a[a * dim + d] - points_b[b * dim + d]; if (minmax[d] > 0) epsilon_temp = -epsilon_temp; else if (minmax[d] == 0) epsilon_temp = 0; - epsilon_max = MAX (epsilon_max, epsilon_temp); + epsilon_max = MAX(epsilon_max, epsilon_temp); } if (epsilon_max <= epsilon) { skip_max = true; break; } - epsilon_min = MIN (epsilon_min, epsilon_max); + epsilon_min = MIN(epsilon_min, epsilon_max); } if (skip_max) continue; epsilon = MAX(epsilon, epsilon_min); @@ -283,58 +286,63 @@ epsilon_additive_minmax(dimension_t dim, const signed char * restrict minmax, const double * restrict points_b, size_t size_b) { switch (check_all_minimize_maximize(minmax, dim)) { - case AGREE_MINIMISE: - return epsilon_additive_minimize(dim, points_a, size_a, points_b, size_b); - case AGREE_MAXIMISE: - return epsilon_additive_maximize(dim, points_a, size_a, points_b, size_b); - default: - return epsilon_additive_minmax_(dim, minmax, points_a, size_a, points_b, size_b); + case AGREE_MINIMISE: + return epsilon_additive_minimize(dim, points_a, size_a, points_b, + size_b); + case AGREE_MAXIMISE: + return epsilon_additive_maximize(dim, points_a, size_a, points_b, + size_b); + default: + return epsilon_additive_minmax_(dim, minmax, points_a, size_a, points_b, + size_b); } } _attr_maybe_unused static double -epsilon_additive (const double * restrict data, int nobj, int npoints, - const double * restrict ref, int ref_size, - const bool * restrict maximise) +epsilon_additive(const double * restrict data, int nobj, int npoints, + const double * restrict ref, int ref_size, + const bool * restrict maximise) { ASSUME(nobj >= 2); ASSUME(npoints >= 0); ASSUME(ref_size >= 0); - dimension_t dim = (dimension_t) nobj; - const signed char *minmax = minmax_from_bool(dim, maximise); - double value = epsilon_additive_minmax(dim, minmax, data, npoints, ref, ref_size); - free ((void *)minmax); - return(value); + dimension_t dim = (dimension_t)nobj; + const signed char * minmax = minmax_from_bool(dim, maximise); + double value = + epsilon_additive_minmax(dim, minmax, data, npoints, ref, ref_size); + free((void *)minmax); + return (value); } _attr_maybe_unused static double -epsilon_mult (const double * restrict data, int nobj, int npoints, - const double * restrict ref, int ref_size, - const bool * restrict maximise) +epsilon_mult(const double * restrict data, int nobj, int npoints, + const double * restrict ref, int ref_size, + const bool * restrict maximise) { ASSUME(nobj >= 2); ASSUME(npoints >= 0); ASSUME(ref_size >= 0); - dimension_t dim = (dimension_t) nobj; - const signed char *minmax = minmax_from_bool(dim, maximise); - double value = epsilon_mult_minmax (dim, minmax, data, npoints, ref, ref_size); - free ((void *)minmax); - return(value); + dimension_t dim = (dimension_t)nobj; + const signed char * minmax = minmax_from_bool(dim, maximise); + double value = + epsilon_mult_minmax(dim, minmax, data, npoints, ref, ref_size); + free((void *)minmax); + return (value); } /* FIXME: this can be done much faster. For example, the diff needs to be calculated just once and stored on a temporary array diff[]. */ static inline int -epsilon_additive_ind (dimension_t dim, const signed char * restrict minmax, - const double * restrict points_a, size_t size_a, - const double * restrict points_b, size_t size_b) +epsilon_additive_ind(dimension_t dim, const signed char * restrict minmax, + const double * restrict points_a, size_t size_a, + const double * restrict points_b, size_t size_b) { - double eps_ab = epsilon_additive_minmax( - dim, minmax, points_a, size_a, points_b, size_b); - double eps_ba = epsilon_additive_minmax( - dim, minmax, points_b, size_b, points_a, size_a); + double eps_ab = epsilon_additive_minmax(dim, minmax, points_a, size_a, + points_b, size_b); + double eps_ba = epsilon_additive_minmax(dim, minmax, points_b, size_b, + points_a, size_a); - DEBUG2(printf ("eps_ab = %g, eps_ba = %g\n", eps_ab, eps_ba)); + DEBUG2(printf("eps_ab = %g, eps_ba = %g\n", eps_ab, eps_ba)); if (eps_ab <= 0 && eps_ba > 0) return -1; diff --git a/c/gcc_attribs.h b/c/gcc_attribs.h index 591e37e8..3a330dca 100644 --- a/c/gcc_attribs.h +++ b/c/gcc_attribs.h @@ -1,8 +1,8 @@ #ifndef GCC_ATTRIBUTES #define GCC_ATTRIBUTES -#if !defined(__GNUC__) && !defined(__clang__ ) && !defined(__ICC) -# define __attribute__(x) /* Elide __attribute__ */ +#if !defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) +# define __attribute__(x) /* Elide __attribute__ */ #endif /* When passing the -Wunused flag, entities that are unused by the program may @@ -15,7 +15,7 @@ variable, a function or method, a function parameter, an enumeration, an enumerator, a non-static data member, or a label. */ #ifndef _attr_maybe_unused -# define _attr_maybe_unused __attribute__((unused)) +# define _attr_maybe_unused __attribute__((unused)) #endif /* Calls to functions whose return value is not affected by changes to the @@ -33,10 +33,10 @@ invocations of the function. In general, since a function cannot distinguish data that might change from data that cannot, const functions should never take pointer or, in C++, reference arguments. */ -#if defined(__GNUC__) || defined(__clang__ ) || defined(__ICC) -# define _attr_const_func __attribute__((const)) +#if defined(__GNUC__) || defined(__clang__) || defined(__ICC) +# define _attr_const_func __attribute__((const)) #else -# define _attr_const_func +# define _attr_const_func #endif /* The pure attribute prohibits a function from modifying the state of the @@ -84,32 +84,32 @@ it to the new pointer) after the function returns a non-NULL value. */ #ifndef __malloc -# define __malloc __attribute__((__malloc__)) +# define __malloc __attribute__((__malloc__)) #endif /* The warn_unused_result attribute causes a warning to be emitted if a caller of the function with this attribute does not use its return value. */ #ifndef __must_check -# define __must_check __attribute__((__warn_unused_result__)) +# define __must_check __attribute__((__warn_unused_result__)) #endif /* The deprecated attribute results in a warning if the function is used anywhere in the source file. */ #ifndef __deprecated -# define __deprecated __attribute__((__deprecated__)) +# define __deprecated __attribute__((__deprecated__)) #endif /* FIXME: add the explanation from the GCC documentation to each attribute. */ #ifndef __used -# define __used __attribute__((__used__)) +# define __used __attribute__((__used__)) #endif #ifndef __packed -# define __packed __attribute__((__packed__)) +# define __packed __attribute__((__packed__)) #endif #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) -# define _attr_aligned(x) __attribute__((aligned (x))) +# define _attr_aligned(x) __attribute__((aligned(x))) #elif defined(_MSC_VER) # define _attr_aligned(x) __declspec(align(x)) #else @@ -118,14 +118,15 @@ #if (defined(__GNUC__) && __GNUC__ >= 3) || defined(__clang__) -# define likely(x) __builtin_expect(!!(x), 1) -# define unlikely(x) __builtin_expect(!!(x), 0) -#elif (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) -# define likely(x) (x) [[likely]] -# define unlikely(x) (x) [[unlikely]] +# define likely(x) __builtin_expect(!!(x), 1) +# define unlikely(x) __builtin_expect(!!(x), 0) +#elif (defined(__cplusplus) && __cplusplus >= 202002L) || \ + (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) +# define likely(x) (x) [[likely]] +# define unlikely(x) (x) [[unlikely]] #else -# define likely(x) (x) -# define unlikely(x) (x) +# define likely(x) (x) +# define unlikely(x) (x) #endif #ifdef _MSC_VER @@ -138,7 +139,7 @@ # define __force_inline__ inline #endif -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99 +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99 /* "restrict" is a known keyword */ #elif defined(__GNUC__) || defined(__clang__) // GCC or Clang # define restrict __restrict__ @@ -153,16 +154,17 @@ The correct format archetype to use for MinGW varies. */ #ifdef __MINGW_PRINTF_FORMAT // Defined by MinGW in stdio.h -#define ATTRIBUTE_FORMAT_PRINTF_ARCHETYPE __MINGW_PRINTF_FORMAT +# define ATTRIBUTE_FORMAT_PRINTF_ARCHETYPE __MINGW_PRINTF_FORMAT #elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__) // Otherwise, __gnu_printf__ is a good default for MinGW. -#define ATTRIBUTE_FORMAT_PRINTF_ARCHETYPE __gnu_printf__ +# define ATTRIBUTE_FORMAT_PRINTF_ARCHETYPE __gnu_printf__ #else -#define ATTRIBUTE_FORMAT_PRINTF_ARCHETYPE __printf__ +# define ATTRIBUTE_FORMAT_PRINTF_ARCHETYPE __printf__ #endif #define ATTRIBUTE_FORMAT_PRINTF(STRING_INDEX, FIRST_TO_CHECK) \ - __attribute__((__format__(ATTRIBUTE_FORMAT_PRINTF_ARCHETYPE, STRING_INDEX, FIRST_TO_CHECK))) + __attribute__((__format__(ATTRIBUTE_FORMAT_PRINTF_ARCHETYPE, STRING_INDEX, \ + FIRST_TO_CHECK))) #ifndef INTERNAL_ASSUME // C++ standard attribute @@ -189,9 +191,13 @@ /* Allow to redefine assert, for example, for R packages */ #ifndef assert -#include +# include #endif -#define ASSUME(EXPR) do { assert(EXPR); INTERNAL_ASSUME(EXPR); } while(0) +#define ASSUME(EXPR) \ + do { \ + assert(EXPR); \ + INTERNAL_ASSUME(EXPR); \ + } while (0) /* unreachable() is sometimes defined by stddef.h */ #ifndef unreachable @@ -201,7 +207,11 @@ # define unreachable() __assume(0) # else # include -# define unreachable() do { assert(0); abort(); } while(0) +# define unreachable() \ + do { \ + assert(0); \ + abort(); \ + } while (0) # endif #endif diff --git a/c/hv.c b/c/hv.c index 47f17063..e40007f5 100644 --- a/c/hv.c +++ b/c/hv.c @@ -40,16 +40,17 @@ #define STOP_DIMENSION 3 /* default: stop on dimension 4 */ typedef struct fpli_dlnode { - const double *x; /* The data vector */ - struct fpli_dlnode **next; /* Next-node vector */ - struct fpli_dlnode **prev; /* Previous-node vector */ - double *area; /* Area */ - double *vol; /* Volume */ - dimension_t ignore; /* Restricts dim to be 255. */ + const double * x; /* The data vector */ + struct fpli_dlnode ** next; /* Next-node vector */ + struct fpli_dlnode ** prev; /* Previous-node vector */ + double * area; /* Area */ + double * vol; /* Volume */ + dimension_t ignore; /* Restricts dim to be 255. */ } fpli_dlnode_t; -static int compare_node(const void *p1, const void* p2) +static int +compare_node(const void * p1, const void * p2) { const double x1 = *((*(const fpli_dlnode_t **)p1)->x); const double x2 = *((*(const fpli_dlnode_t **)p2)->x); @@ -68,13 +69,13 @@ fpli_setup_cdllist(const double * restrict data, dimension_t d, ASSUME(d > STOP_DIMENSION); dimension_t d_stop = d - STOP_DIMENSION; size_t n = *size; - fpli_dlnode_t *head = malloc ((n+1) * sizeof(*head)); - head->next = malloc(2 * d_stop * (n+1) * sizeof(fpli_dlnode_t*)); - head->prev = head->next + d_stop * (n+1); - head->area = malloc(2 * d_stop * (n+1) * sizeof(double)); - head->vol = head->area + d_stop * (n+1); - head->x = NULL; /* head contains no data */ - head->ignore = 0; /* should never get used */ + fpli_dlnode_t * head = malloc((n + 1) * sizeof(*head)); + head->next = malloc(2 * d_stop * (n + 1) * sizeof(fpli_dlnode_t *)); + head->prev = head->next + d_stop * (n + 1); + head->area = malloc(2 * d_stop * (n + 1) * sizeof(double)); + head->vol = head->area + d_stop * (n + 1); + head->x = NULL; /* head contains no data */ + head->ignore = 0; /* should never get used */ size_t i = 1; for (size_t j = 0; j < n; j++) { @@ -82,7 +83,9 @@ fpli_setup_cdllist(const double * restrict data, dimension_t d, point. This is needed to assure that the points left are only those that are needed to calculate the hypervolume. */ if (likely(strongly_dominates(data + j * d, ref, d))) { - head[i].x = data + (j+1) * d; /* this will be fixed a few lines below... */ + head[i].x = + data + + (j + 1) * d; /* this will be fixed a few lines below... */ head[i].ignore = 0; head[i].next = head->next + i * d_stop; head[i].prev = head->prev + i * d_stop; @@ -92,71 +95,66 @@ fpli_setup_cdllist(const double * restrict data, dimension_t d, } } n = i - 1; - if (unlikely(n == 0)) - goto finish; + if (unlikely(n == 0)) goto finish; - fpli_dlnode_t **scratch = malloc(n * sizeof(fpli_dlnode_t*)); - for (i = 0; i < n; i++) - scratch[i] = head + i + 1; + fpli_dlnode_t ** scratch = malloc(n * sizeof(fpli_dlnode_t *)); + for (i = 0; i < n; i++) scratch[i] = head + i + 1; - for (int k = d-1; k >= 0; k--) { - for (i = 0; i < n; i++) - scratch[i]->x--; + for (int k = d - 1; k >= 0; k--) { + for (i = 0; i < n; i++) scratch[i]->x--; int j = k - STOP_DIMENSION; - if (j < 0) - continue; - qsort(scratch, n, sizeof(fpli_dlnode_t*), compare_node); + if (j < 0) continue; + qsort(scratch, n, sizeof(fpli_dlnode_t *), compare_node); head->next[j] = scratch[0]; scratch[0]->prev[j] = head; for (i = 1; i < n; i++) { - scratch[i-1]->next[j] = scratch[i]; - scratch[i]->prev[j] = scratch[i-1]; + scratch[i - 1]->next[j] = scratch[i]; + scratch[i]->prev[j] = scratch[i - 1]; } - scratch[n-1]->next[j] = head; - head->prev[j] = scratch[n-1]; + scratch[n - 1]->next[j] = head; + head->prev[j] = scratch[n - 1]; } free(scratch); // FIXME: This should not be necessary. - for (i = 0; i < d_stop; i++) - head->area[i] = 0; + for (i = 0; i < d_stop; i++) head->area[i] = 0; finish: *size = n; return head; } -static void fpli_free_cdllist(fpli_dlnode_t * head) +static void +fpli_free_cdllist(fpli_dlnode_t * head) { free(head->next); free(head->area); free(head); } -static void -delete(fpli_dlnode_t * restrict nodep, dimension_t dim, double * restrict bound) +static void delete(fpli_dlnode_t * restrict nodep, dimension_t dim, + double * restrict bound) { ASSUME(dim > STOP_DIMENSION); for (dimension_t i = STOP_DIMENSION; i < dim; i++) { dimension_t d = i - STOP_DIMENSION; nodep->prev[d]->next[d] = nodep->next[d]; nodep->next[d]->prev[d] = nodep->prev[d]; - if (bound[d] > nodep->x[i]) - bound[d] = nodep->x[i]; + if (bound[d] > nodep->x[i]) bound[d] = nodep->x[i]; } } static void -reinsert(fpli_dlnode_t * restrict nodep, dimension_t dim, double * restrict bound) +reinsert(fpli_dlnode_t * restrict nodep, dimension_t dim, + double * restrict bound) { ASSUME(dim > STOP_DIMENSION); for (dimension_t i = STOP_DIMENSION; i < dim; i++) { dimension_t d = i - STOP_DIMENSION; nodep->prev[d]->next[d] = nodep; nodep->next[d]->prev[d] = nodep; - if (bound[d] > nodep->x[i]) - bound[d] = nodep->x[i]; + if (bound[d] > nodep->x[i]) bound[d] = nodep->x[i]; } } @@ -168,19 +166,16 @@ fpli_hv4d_setup_cdllist(const fpli_dlnode_t * restrict pp, reset_sentinels(list); const dimension_t d = HV_DIMENSION - 3; // index within the list. - dlnode_t * q = list+1; - dlnode_t * list3 = list+3; + dlnode_t * q = list + 1; + dlnode_t * list3 = list + 3; assert(list->next[d] == list + 1); assert(q->next[d] == list + 2); for (size_t i = 0; pp->x != NULL; pp = pp->next[0]) { dlnode_t * p = list3 + i; p->x = pp->x; // Initialize it when debugging so it will crash if uninitialized. - DEBUG1( - p->closest[0] = NULL; - p->closest[1] = NULL; - p->cnext[0] = NULL; - p->cnext[1] = NULL;); + DEBUG1(p->closest[0] = NULL; p->closest[1] = NULL; p->cnext[0] = NULL; + p->cnext[1] = NULL;); // FIXME: Can we use pp->ignore to initialize p->ndomr? //p->ndomr = 0; // Link the list in order. @@ -190,25 +185,25 @@ fpli_hv4d_setup_cdllist(const fpli_dlnode_t * restrict pp, i++; } assert((list3 + n - 1) == q); - assert(list+2 == list->prev[d]); + assert(list + 2 == list->prev[d]); // q = last point, q->next = s3, s3->prev = last point - q->next[d] = list+2; - (list+2)->prev[d] = q; + q->next[d] = list + 2; + (list + 2)->prev[d] = q; } static double -one_point_hv(const double * restrict x, const double * restrict ref, dimension_t d) +one_point_hv(const double * restrict x, const double * restrict ref, + dimension_t d) { double hv = ref[0] - x[0]; - for (dimension_t i = 1; i < d; i++) - hv *= (ref[i] - x[i]); + for (dimension_t i = 1; i < d; i++) hv *= (ref[i] - x[i]); return hv; } double hv4dplusU(dlnode_t * list); static double -fpli_hv4d(fpli_dlnode_t *list, dlnode_t * restrict list4d, size_t c) +fpli_hv4d(fpli_dlnode_t * list, dlnode_t * restrict list4d, size_t c) { ASSUME(c > 1); fpli_hv4d_setup_cdllist(list->next[0], list4d, c); @@ -218,8 +213,8 @@ fpli_hv4d(fpli_dlnode_t *list, dlnode_t * restrict list4d, size_t c) static double hv_recursive(fpli_dlnode_t * restrict list, dlnode_t * restrict list4d, - dimension_t dim, size_t c, - const double * restrict ref, double * restrict bound) + dimension_t dim, size_t c, const double * restrict ref, + double * restrict bound) { ASSUME(dim > STOP_DIMENSION); ASSUME(c > 1); @@ -227,35 +222,36 @@ hv_recursive(fpli_dlnode_t * restrict list, dlnode_t * restrict list4d, General case for dimensions higher than 4D ------------------------------------------------------ */ const dimension_t d_stop = dim - STOP_DIMENSION; - fpli_dlnode_t *p1 = list->prev[d_stop]; - for (fpli_dlnode_t *pp = p1; pp->x; pp = pp->prev[d_stop]) { - if (pp->ignore < dim) - pp->ignore = 0; + fpli_dlnode_t * p1 = list->prev[d_stop]; + for (fpli_dlnode_t * pp = p1; pp->x; pp = pp->prev[d_stop]) { + if (pp->ignore < dim) pp->ignore = 0; } - fpli_dlnode_t *p0 = list; + fpli_dlnode_t * p0 = list; /* Delete all points x[dim] > bound[d_stop]. In case of repeated coordinates, delete also all points x[dim] == bound[d_stop] except one. */ - while (p1->x[dim] > bound[d_stop] || p1->prev[d_stop]->x[dim] >= bound[d_stop]) { + while (p1->x[dim] > bound[d_stop] || + p1->prev[d_stop]->x[dim] >= bound[d_stop]) { // FIXME: Instead of deleting each point, unlink the start and end // nodes after the loop. - delete(p1, dim, bound); + delete (p1, dim, bound); p0 = p1; p1 = p1->prev[d_stop]; c--; - if (c == 1) - break; + if (c == 1) break; } double hyperv = 0; if (c > 1) { - hyperv = p1->prev[d_stop]->vol[d_stop] + p1->prev[d_stop]->area[d_stop] - * (p1->x[dim] - p1->prev[d_stop]->x[dim]); + hyperv = p1->prev[d_stop]->vol[d_stop] + + p1->prev[d_stop]->area[d_stop] * + (p1->x[dim] - p1->prev[d_stop]->x[dim]); } else { ASSUME(c == 1); p1->area[0] = one_point_hv(p1->x, ref, STOP_DIMENSION); for (dimension_t i = STOP_DIMENSION; i < dim; i++) - p1->area[i + 1 - STOP_DIMENSION] = p1->area[i - STOP_DIMENSION] * (ref[i] - p1->x[i]); + p1->area[i + 1 - STOP_DIMENSION] = + p1->area[i - STOP_DIMENSION] * (ref[i] - p1->x[i]); p1->vol[d_stop] = 0; if (p0->x == NULL) { return p1->area[d_stop] * (ref[dim] - p1->x[dim]); @@ -281,10 +277,9 @@ hv_recursive(fpli_dlnode_t * restrict list, dlnode_t * restrict list4d, --------------------------------------*/ hypera = fpli_hv4d(list, list4d, c); } else { - hypera = hv_recursive(list, list4d, dim-1, c, ref, bound); + hypera = hv_recursive(list, list4d, dim - 1, c, ref, bound); } - if (hypera <= p1->prev[d_stop]->area[d_stop]) - p1->ignore = dim; + if (hypera <= p1->prev[d_stop]->area[d_stop]) p1->ignore = dim; } p1->area[d_stop] = hypera; if (p0->x == NULL) { @@ -303,7 +298,7 @@ hv_recursive(fpli_dlnode_t * restrict list, dlnode_t * restrict list4d, static double hv2d(const double * restrict data, size_t n, const double * restrict ref) { - const double **p = generate_sorted_doublep_2d(data, &n, ref[0]); + const double ** p = generate_sorted_doublep_2d(data, &n, ref[0]); if (unlikely(n == 0)) return 0; if (unlikely(!p)) return -1; @@ -324,24 +319,27 @@ hv2d(const double * restrict data, size_t n, const double * restrict ref) return hyperv; } -double hv3d(const double * restrict data, size_t n, const double * restrict ref); -double hv4d(const double * restrict data, size_t n, const double * restrict ref); +double hv3d(const double * restrict data, size_t n, + const double * restrict ref); +double hv4d(const double * restrict data, size_t n, + const double * restrict ref); /* Returns 0 if no point strictly dominates ref. Returns -1 if out of memory. */ -double fpli_hv(const double * restrict data, int d, int npoints, - const double * restrict ref) +double +fpli_hv(const double * restrict data, int d, int npoints, + const double * restrict ref) { - size_t n = (size_t) npoints; + size_t n = (size_t)npoints; if (unlikely(n == 0)) return 0.0; ASSUME(d < 256); ASSUME(d > 1); if (d == 4) return hv4d(data, n, ref); if (d == 3) return hv3d(data, n, ref); if (d == 2) return hv2d(data, n, ref); - dimension_t dim = (dimension_t) d; + dimension_t dim = (dimension_t)d; fpli_dlnode_t * list = fpli_setup_cdllist(data, dim, &n, ref); double hyperv; if (unlikely(n == 0)) { @@ -351,10 +349,10 @@ double fpli_hv(const double * restrict data, int d, int npoints, hyperv = one_point_hv(list->next[0]->x, ref, dim); } else { const dimension_t d_stop = dim - STOP_DIMENSION; - ASSUME(d_stop > 1 && d_stop < 255); // Silence -Walloc-size-larger-than= warning + ASSUME(d_stop > 1 && + d_stop < 255); // Silence -Walloc-size-larger-than= warning double * bound = malloc(d_stop * sizeof(double)); - for (dimension_t i = 0; i < d_stop; i++) - bound[i] = -DBL_MAX; + for (dimension_t i = 0; i < d_stop; i++) bound[i] = -DBL_MAX; dlnode_t * list4d = new_cdllist(n, ref); hyperv = hv_recursive(list, list4d, dim - 1, n, ref, bound); free_cdllist(list4d); diff --git a/c/hv.h b/c/hv.h index db260be7..79503ba9 100644 --- a/c/hv.h +++ b/c/hv.h @@ -25,9 +25,11 @@ // C++ needs to know that types and declarations are C, not C++. BEGIN_C_DECLS -MOOCORE_API double fpli_hv(const double *data, int d, int n, const double *ref); -MOOCORE_API double hv_contributions(double *hvc, double *points, int dim, int size, - const double * ref, bool ignore_dominated); +MOOCORE_API double fpli_hv(const double * data, int d, int n, + const double * ref); +MOOCORE_API double hv_contributions(double * hvc, double * points, int dim, + int size, const double * ref, + bool ignore_dominated); END_C_DECLS #endif // HV_H_ diff --git a/c/hv3d_priv.h b/c/hv3d_priv.h index d9e8579a..5015a333 100644 --- a/c/hv3d_priv.h +++ b/c/hv3d_priv.h @@ -3,11 +3,11 @@ typedef const double avl_item_t; typedef struct avl_node_t { - struct avl_node_t *next; - struct avl_node_t *prev; - struct avl_node_t *parent; - struct avl_node_t *left; - struct avl_node_t *right; + struct avl_node_t * next; + struct avl_node_t * prev; + struct avl_node_t * parent; + struct avl_node_t * left; + struct avl_node_t * right; avl_item_t * item; dlnode_t * dlnode; unsigned char depth; @@ -16,7 +16,7 @@ typedef struct avl_node_t { #include "avl_tiny.h" static inline const double * -node_point(const avl_node_t *node) +node_point(const avl_node_t * node) { return node->item; } @@ -42,30 +42,33 @@ hv3d_preprocessing(dlnode_t * list, size_t n) { // FIXME: Can we unify these two paths to always use either ->cnext or ->closest? #ifdef HVC_ONLY -# define set_delimiters(DLNODE, DEM0, DEM1) do { \ - (DLNODE)->closest[0] = (DEM0); \ - (DLNODE)->closest[1] = (DEM1); \ - } while(false) +# define set_delimiters(DLNODE, DEM0, DEM1) \ + do { \ + (DLNODE)->closest[0] = (DEM0); \ + (DLNODE)->closest[1] = (DEM1); \ + } while (false) #else -# define set_delimiters(DLNODE, DEM0, DEM1) do { \ - (DLNODE)->cnext[0] = (DEM0); \ - (DLNODE)->cnext[1] = (DEM1); \ - } while(false) +# define set_delimiters(DLNODE, DEM0, DEM1) \ + do { \ + (DLNODE)->cnext[0] = (DEM0); \ + (DLNODE)->cnext[1] = (DEM1); \ + } while (false) #endif ASSUME(n >= 1); - assert(list+1 == list->next[0]); - assert(list+2 == list->prev[0]); + assert(list + 1 == list->next[0]); + assert(list + 2 == list->prev[0]); avl_tree_t tree; - avl_init_tree(&tree, cmp_double_asc_y_des_x); // FIXME: cmp_double_asc_y_des_x - avl_node_t * tnodes = malloc((n+2) * sizeof(*tnodes)); + avl_init_tree(&tree, + cmp_double_asc_y_des_x); // FIXME: cmp_double_asc_y_des_x + avl_node_t * tnodes = malloc((n + 2) * sizeof(*tnodes)); // At the top we insert the first point, which is never dominated. - dlnode_t * p = (list+1)->next[0]; + dlnode_t * p = (list + 1)->next[0]; avl_node_t * nodeaux = new_avl_node(p, tnodes); avl_insert_top(&tree, nodeaux); - set_delimiters(p, list+1, list); + set_delimiters(p, list + 1, list); // After the top node, we insert sentinel 1 (-INF, ref[1]) avl_node_t * node = new_avl_node(list, tnodes + 1); @@ -75,7 +78,7 @@ hv3d_preprocessing(dlnode_t * list, size_t n) avl_insert_before(&tree, nodeaux, node); set_delimiters(p, nodeaux->prev->dlnode, nodeaux->next->dlnode); - const dlnode_t * stop = list+2; + const dlnode_t * stop = list + 2; p = p->next[0]; while (p != stop) { const double * px = p->x; @@ -87,8 +90,10 @@ hv3d_preprocessing(dlnode_t * list, size_t n) } else { prev_x = node_point(nodeaux->prev); } - assert(node_point(nodeaux)[1] > px[1] // node_point(nodeaux) comes after px. - || (node_point(nodeaux)[1] == px[1] && node_point(nodeaux)[0] < px[0])); + assert(node_point(nodeaux)[1] > + px[1] // node_point(nodeaux) comes after px. + || (node_point(nodeaux)[1] == px[1] && + node_point(nodeaux)[0] < px[0])); assert(prev_x[1] <= px[1]); assert(prev_x[2] <= px[2]); if (prev_x[0] <= px[0]) { // px is dominated by a point in the tree. @@ -97,7 +102,8 @@ hv3d_preprocessing(dlnode_t * list, size_t n) nodeaux->prev->dlnode->ignore = true; // It will have zero hvc. #endif remove_from_z(p); - } else if (node_point(nodeaux)[1] == px[1]) { // px is dominated by a point in the tree. + } else if (node_point(nodeaux)[1] == + px[1]) { // px is dominated by a point in the tree. // FIXME: If the points were ordered by asc x we would only need the first condition. assert(node_point(nodeaux)[0] < px[0]); remove_from_z(p); diff --git a/c/hv3dplus.c b/c/hv3dplus.c index a46a0632..2664a5b0 100644 --- a/c/hv3dplus.c +++ b/c/hv3dplus.c @@ -44,20 +44,20 @@ static double hv3dplus_list(dlnode_t * list) { restart_list_y(list); - assert(list+2 == list->prev[0]); + assert(list + 2 == list->prev[0]); double area = 0, volume = 0; - dlnode_t * p = (list+1)->next[0]; - const dlnode_t * stop = list+2; + dlnode_t * p = (list + 1)->next[0]; + const dlnode_t * stop = list + 2; while (p != stop) { area += compute_area3d_simple(p->x, p->cnext[0]); p->cnext[0]->cnext[1] = p; p->cnext[1]->cnext[0] = p; - ASSERT_OR_DO( - (p->next[0]->x[2] > p->x[2]) || (p->next[0]->x[0] < p->x[0]) || (p->next[0]->x[1] < p->x[1]), - print_x(p); - print_x(p->next[0]); - ); + ASSERT_OR_DO((p->next[0]->x[2] > p->x[2]) || + (p->next[0]->x[0] < p->x[0]) || + (p->next[0]->x[1] < p->x[1]), + print_x(p); + print_x(p->next[0]);); assert(area > 0); /* It is possible to have two points with the same z-value, e.g., (1,2,3) and (2,1,3). */ diff --git a/c/hv4d.c b/c/hv4d.c index 9029eec3..d568d91d 100644 --- a/c/hv4d.c +++ b/c/hv4d.c @@ -36,20 +36,20 @@ // ---------- Data Structures Functions --------------------------------------- static inline void _attr_maybe_unused -print_point(const char *s, const double * x) +print_point(const char * s, const double * x) { fprintf(stderr, "%s: %g %g %g %g\n", s, x[0], x[1], x[2], x[4]); } - - // ------------ Update data structure ----------------------------------------- static inline void add_to_z(dlnode_t * new) { - new->next[0] = new->prev[0]->next[0]; //in case new->next[0] was removed for being dominated + new->next[0] = + new->prev[0] + ->next[0]; //in case new->next[0] was removed for being dominated new->next[0]->prev[0] = new; new->prev[0]->next[0] = new; } @@ -57,13 +57,15 @@ add_to_z(dlnode_t * new) static inline bool lex_cmp_3d_102(const double * restrict a, const double * restrict b) { - return a[1] < b[1] || (a[1] == b[1] && (a[0] < b[0] || (a[0] == b[0] && a[2] < b[2]))); + return a[1] < b[1] || + (a[1] == b[1] && (a[0] < b[0] || (a[0] == b[0] && a[2] < b[2]))); } static inline bool lex_cmp_3d_012(const double * restrict a, const double * restrict b) { - return a[0] < b[0] || (a[0] == b[0] && (a[1] < b[1] || (a[1] == b[1] && a[2] < b[2]))); + return a[0] < b[0] || + (a[0] == b[0] && (a[1] < b[1] || (a[1] == b[1] && a[2] < b[2]))); } /* @@ -74,26 +76,30 @@ lex_cmp_3d_012(const double * restrict a, const double * restrict b) static void update_links(dlnode_t * restrict list, dlnode_t * restrict new) { - assert(list+2 == list->prev[0]); + assert(list + 2 == list->prev[0]); const double * newx = new->x; dlnode_t * p = new->next[0]; const double * px = p->x; - dlnode_t * stop = list+2; + dlnode_t * stop = list + 2; while (p != stop) { // px dominates newx (but not equal) - if (px[0] <= newx[0] && px[1] <= newx[1] && (px[0] < newx[0] || px[1] < newx[1])) + if (px[0] <= newx[0] && px[1] <= newx[1] && + (px[0] < newx[0] || px[1] < newx[1])) return; - if (newx[0] <= px[0]){ + if (newx[0] <= px[0]) { //new <= p - if (newx[1] <= px[1]){ + if (newx[1] <= px[1]) { assert(weakly_dominates(newx, px, 3)); //p->ndomr++; remove_from_z(p); - } else if (newx[0] < px[0] && lex_cmp_3d_102(newx, p->closest[1]->x)) { // newx[1] > px[1] + } else if (newx[0] < px[0] && + lex_cmp_3d_102(newx, + p->closest[1]->x)) { // newx[1] > px[1] p->closest[1] = new; } - } else if (newx[1] < px[1] && lex_cmp_3d_012(newx, p->closest[0]->x)) {//newx[0] > px[0] + } else if (newx[1] < px[1] && + lex_cmp_3d_012(newx, p->closest[0]->x)) { //newx[0] > px[0] p->closest[0] = new; } p = p->next[0]; @@ -102,24 +108,24 @@ update_links(dlnode_t * restrict list, dlnode_t * restrict new) } - // This does what setupZandClosest does while reconstructing L at z = new->x[2]. __attribute__((hot)) static bool -restart_base_setup_z_and_closest(dlnode_t * restrict list, dlnode_t * restrict new) +restart_base_setup_z_and_closest(dlnode_t * restrict list, + dlnode_t * restrict new) { const double * restrict newx = new->x; // FIXME: This is the most expensive function in the HV4D+ algorithm. - assert(list+1 == list->next[0]); + assert(list + 1 == list->next[0]); dlnode_t * closest1 = list; - dlnode_t * closest0 = list+1; + dlnode_t * closest0 = list + 1; const double * closest0x = closest0->x; const double * closest1x = closest1->x; - dlnode_t * p = list+1; + dlnode_t * p = list + 1; assert(p->next[0] == list->next[0]->next[0]); restart_list_y(list); while (true) { p = p->next[0]; - const double * restrict px = p->x; + const double * restrict px = p->x; // Help auto-vectorization. bool p_leq_new_0 = px[0] <= newx[0]; bool p_leq_new_1 = px[1] <= newx[1]; @@ -131,8 +137,7 @@ restart_base_setup_z_and_closest(dlnode_t * restrict list, dlnode_t * restrict n return false; } - if (!lexicographic_less_3d(px, newx)) - break; + if (!lexicographic_less_3d(px, newx)) break; // reconstruct set_cnext_to_closest(p); @@ -141,10 +146,14 @@ restart_base_setup_z_and_closest(dlnode_t * restrict list, dlnode_t * restrict n // setup_z_and_closest assert(px[0] > newx[0] || px[1] > newx[1]); - if (px[1] < newx[1] && (px[0] < closest0x[0] || (px[0] == closest0x[0] && px[1] < closest0x[1]))) { + if (px[1] < newx[1] && + (px[0] < closest0x[0] || + (px[0] == closest0x[0] && px[1] < closest0x[1]))) { closest0 = p; closest0x = px; - } else if (px[0] < newx[0] && (px[1] < closest1x[1] || (px[1] == closest1x[1] && px[0] < closest1x[0]))) { + } else if (px[0] < newx[0] && + (px[1] < closest1x[1] || + (px[1] == closest1x[1] && px[0] < closest1x[0]))) { closest1 = p; closest1x = px; } @@ -176,17 +185,16 @@ one_contribution_3d(dlnode_t * restrict new) px = p->x; volume += area * (px[2] - lastz); - if (px[0] <= newx[0] && px[1] <= newx[1]) - return volume; + if (px[0] <= newx[0] && px[1] <= newx[1]) return volume; assert(px[0] > newx[0] || px[1] > newx[1]); assert(!weakly_dominates(px, p->next[0]->x, 4)); set_cnext_to_closest(p); - if (px[0] < newx[0]) { + if (px[0] < newx[0]) { if (px[1] <= new->cnext[1]->x[1]) { - const double tmpx[] = { newx[0], px[1] }; + const double tmpx[] = {newx[0], px[1]}; // if px[1] == new->cnext[1]->x[1] then area starts at 0. area -= compute_area_no_inners(tmpx, new->cnext[1], 0); p->cnext[1] = new->cnext[1]; @@ -195,7 +203,7 @@ one_contribution_3d(dlnode_t * restrict new) } } else if (px[1] < newx[1]) { if (px[0] <= new->cnext[0]->x[0]) { - const double tmpx[] = { px[0], newx[1] }; + const double tmpx[] = {px[0], newx[1]}; // if px[0] == new->cnext[0]->x[0] then area starts at 0. area -= compute_area_no_inners(tmpx, new->cnext[0], 1); p->cnext[0] = new->cnext[0]; @@ -218,13 +226,13 @@ one_contribution_3d(dlnode_t * restrict new) double hv4dplusU(dlnode_t * list) { - assert(list+2 == list->prev[0]); - assert(list+2 == list->prev[1]); - assert(list+1 == list->next[1]); + assert(list + 2 == list->prev[0]); + assert(list + 2 == list->prev[1]); + assert(list + 1 == list->next[1]); double volume = 0, hv = 0; - dlnode_t * new = (list+1)->next[1]; - dlnode_t * last = list+2; + dlnode_t * new = (list + 1)->next[1]; + dlnode_t * last = list + 2; while (new != last) { if (restart_base_setup_z_and_closest(list, new)) { // new was not dominated by something else. diff --git a/c/hv_contrib.c b/c/hv_contrib.c index 10e98d87..d1b1e6cb 100644 --- a/c/hv_contrib.c +++ b/c/hv_contrib.c @@ -12,7 +12,7 @@ hvc_1point_diff(const double * restrict points, dimension_t dim, size_t size, const double * restrict ref, const double hv_total) { const double tolerance = sqrt(DBL_EPSILON); - double hvc = hv_total - fpli_hv(points, dim, (int) size, ref); + double hvc = hv_total - fpli_hv(points, dim, (int)size, ref); // Handle very small values. hvc = (hvc >= tolerance) ? hvc : 0.0; return hvc; @@ -27,8 +27,9 @@ hvc_1point_diff(const double * restrict points, dimension_t dim, size_t size, one point. */ static void -hvc_1point_diffs(double * restrict hvc, double * restrict points, dimension_t dim, size_t size, - const double * restrict ref, const bool * uev, const double hv_total) +hvc_1point_diffs(double * restrict hvc, double * restrict points, + dimension_t dim, size_t size, const double * restrict ref, + const bool * uev, const double hv_total) { ASSUME(size > 1); bool keep_uevs = uev != NULL; @@ -39,7 +40,8 @@ hvc_1point_diffs(double * restrict hvc, double * restrict points, dimension_t di for (size_t i = 0; i < size - 1; i++) { if (unlikely(keep_uevs && uev[i])) { hvc[i] = hv_total; - } else if (nondom[i] && strongly_dominates(points + i * dim, ref, dim)) { + } else if (nondom[i] && + strongly_dominates(points + i * dim, ref, dim)) { memcpy(tmp, points + i * dim, sizeof(double) * dim); memcpy(points + i * dim, last, sizeof(double) * dim); hvc[i] = hvc_1point_diff(points, dim, size - 1, ref, hv_total); @@ -67,16 +69,18 @@ hvc_1point_diffs_nondom(double * restrict hvc, double * restrict points, const double hv_total) { ASSUME(size > 1); -#define swap_points(A,B) do { \ - memcpy(tmp_point, points + (A) * dim, sizeof(double) * dim); \ - memcpy(points + (A) * dim, points + (B) * dim, sizeof(double) * dim); \ - memcpy(points + (B) * dim, tmp_point, sizeof(double) * dim); \ - } while(0) +#define swap_points(A, B) \ + do { \ + memcpy(tmp_point, points + (A) * dim, sizeof(double) * dim); \ + memcpy(points + (A) * dim, points + (B) * dim, sizeof(double) * dim); \ + memcpy(points + (B) * dim, tmp_point, sizeof(double) * dim); \ + } while (0) bool keep_uevs = uev != NULL; bool * nondom = nondom_init(size); // Duplicated points will still contribute zero. - size_t new_size = find_weak_nondominated_set_minimise(points, dim, size, nondom); + size_t new_size = + find_weak_nondominated_set_minimise(points, dim, size, nondom); size_t first = 0; double * tmp_point = MOOCORE_MALLOC(dim, double); if (new_size < size) { @@ -147,14 +151,13 @@ hvc2d(double * restrict hvc, const double * restrict data, size_t n, const double * restrict ref) { ASSUME(n > 0); - const double **p = generate_sorted_doublep_2d(data, &n, ref[0]); + const double ** p = generate_sorted_doublep_2d(data, &n, ref[0]); if (unlikely(n == 0)) return 0; if (unlikely(!p)) return -1; size_t j = 0; // Find first point below the reference point. - while (j < n && p[j][1] >= ref[1]) - j++; + while (j < n && p[j][1] >= ref[1]) j++; if (unlikely(j == n)) { free(p); return 0; @@ -174,9 +177,8 @@ hvc2d(double * restrict hvc, const double * restrict data, size_t n, we may have computed partial contributions. */ hvc[(prev - data) / 2] += (p[j][0] - prev[0]) * height; DEBUG2_PRINT("hvc[%lld] += %g * %g = %g\n", - (long long) (prev - data) / 2, - p[j][0] - prev[0], height, - (p[j][0] - prev[0]) * height); + (long long)(prev - data) / 2, p[j][0] - prev[0], + height, (p[j][0] - prev[0]) * height); height = prev[1] - p[j][1]; // Compute the hypervolume of p[j] hyperv += (ref[0] - p[j][0]) * height; @@ -186,10 +188,11 @@ hvc2d(double * restrict hvc, const double * restrict data, size_t n, // prev[1] <= p[j][1], thus pj contributes partially to hvc[prev]. double new_h = p[j][1] - prev[1]; if (new_h < height) { - hvc[(prev - data) / 2] += (p[j][0] - prev[0]) * (height - new_h); + hvc[(prev - data) / 2] += + (p[j][0] - prev[0]) * (height - new_h); DEBUG2_PRINT("hvc[%lld] += %g * %g = %g\n", - (long long) (prev - data) / 2, - p[j][0] - prev[0], height - new_h, + (long long)(prev - data) / 2, p[j][0] - prev[0], + height - new_h, (p[j][0] - prev[0]) * (height - new_h)); height = new_h; } @@ -222,7 +225,7 @@ hvc2d(double * restrict hvc, const double * restrict data, size_t n, hvc[(prev - data) / 2] += (ref[0] - prev[0]) * height; DEBUG2_PRINT("hvc[%lld] = %g * %g = %g\n", (long long)(prev - data) / 2, - ref[0] - prev[0], height, (ref[0] - prev[0]) * height); + ref[0] - prev[0], height, (ref[0] - prev[0]) * height); free(p); return hyperv; } @@ -232,14 +235,13 @@ hvc2d_nondom(double * restrict hvc, const double * restrict data, size_t n, const double * restrict ref) { ASSUME(n > 0); - const double **p = generate_sorted_doublep_2d(data, &n, ref[0]); + const double ** p = generate_sorted_doublep_2d(data, &n, ref[0]); if (unlikely(n == 0)) return 0; if (unlikely(!p)) return -1; size_t j = 0; // Find first point below the reference point. - while (j < n && p[j][1] >= ref[1]) - j++; + while (j < n && p[j][1] >= ref[1]) j++; if (unlikely(j == n)) { free(p); return 0; @@ -258,9 +260,8 @@ hvc2d_nondom(double * restrict hvc, const double * restrict data, size_t n, /* Compute the contribution of prev. */ hvc[(prev - data) / 2] = (p[j][0] - prev[0]) * height; DEBUG2_PRINT("hvc[%lld] = %g * %g = %g\n", - (long long) (prev - data) / 2, - p[j][0] - prev[0], height, - (p[j][0] - prev[0]) * height); + (long long)(prev - data) / 2, p[j][0] - prev[0], + height, (p[j][0] - prev[0]) * height); height = prev[1] - p[j][1]; // Compute the hypervolume of p[j] hyperv += (ref[0] - p[j][0]) * height; @@ -292,7 +293,7 @@ hvc2d_nondom(double * restrict hvc, const double * restrict data, size_t n, hvc[(prev - data) / 2] = (ref[0] - prev[0]) * height; DEBUG2_PRINT("hvc[%lld] = %g * %g = %g\n", (long long)(prev - data) / 2, - ref[0] - prev[0], height, (ref[0] - prev[0]) * height); + ref[0] - prev[0], height, (ref[0] - prev[0]) * height); free(p); return hyperv; } @@ -302,21 +303,22 @@ hvc2d_nondom(double * restrict hvc, const double * restrict data, size_t n, definition of fatal_error(). */ static inline void hvc_check(double hv_total, const double * restrict hvc, - double * restrict points, - dimension_t dim, size_t size, const double * restrict ref, - bool ignore_dominated) + double * restrict points, dimension_t dim, size_t size, + const double * restrict ref, bool ignore_dominated) { const double tolerance = sqrt(DBL_EPSILON); - double hv_total_true = fpli_hv(points, dim, (int) size, ref); + double hv_total_true = fpli_hv(points, dim, (int)size, ref); if (fabs(hv_total_true - hv_total) > tolerance) { - fatal_error("hv_total = %-22.15g != hv_total_true = %-22.15g !", hv_total, hv_total_true); + fatal_error("hv_total = %-22.15g != hv_total_true = %-22.15g !", + hv_total, hv_total_true); } double * hvc_true = MOOCORE_MALLOC(size, double); /* The functions below will skip points that do not dominate the reference point. */ memset(hvc_true, 0, size * sizeof(double)); if (ignore_dominated) - hvc_1point_diffs_nondom(hvc_true, points, dim, size, ref, NULL, hv_total); + hvc_1point_diffs_nondom(hvc_true, points, dim, size, ref, NULL, + hv_total); else hvc_1point_diffs(hvc_true, points, dim, size, ref, NULL, hv_total); for (size_t i = 0; i < size; i++) { @@ -326,14 +328,15 @@ hvc_check(double hv_total, const double * restrict hvc, fprintf(stderr, " %-22.15g", points[i * dim + d]); } fprintf(stderr, "\n"); - fatal_error("hvc[%zu] = %-22.15g != hvc_true[%zu] = %-22.15g !", i, hvc[i], i, hvc_true[i]); + fatal_error("hvc[%zu] = %-22.15g != hvc_true[%zu] = %-22.15g !", i, + hvc[i], i, hvc_true[i]); } } free(hvc_true); } -extern double -hvc3d(double * restrict hvc, const double * restrict data, size_t n, const double * restrict ref); +extern double hvc3d(double * restrict hvc, const double * restrict data, + size_t n, const double * restrict ref); /* Store the exclusive hypervolume contribution of each input point in hvc[], which is allocated by the caller. @@ -349,11 +352,11 @@ hv_contributions(double * restrict hvc, double * restrict points, int d, int n, assert(hvc != NULL); ASSUME(d > 1 && d <= 32); ASSUME(n >= 0); - dimension_t dim = (dimension_t) d; - size_t size = (size_t) n; + dimension_t dim = (dimension_t)d; + size_t size = (size_t)n; if (size == 0) return 0; if (size == 1) { - hvc[0] = fpli_hv(points, dim, (int) size, ref); + hvc[0] = fpli_hv(points, dim, (int)size, ref); return hvc[0]; } /* We cannot rely on the caller and the functions below will skip points @@ -362,18 +365,19 @@ hv_contributions(double * restrict hvc, double * restrict points, int d, int n, double hv_total; if (dim == 2) { - hv_total = ignore_dominated - ? hvc2d_nondom(hvc, points, size, ref) - : hvc2d(hvc, points, size, ref); - DEBUG1(hvc_check(hv_total, hvc, points, dim, size, ref, ignore_dominated)); + hv_total = ignore_dominated ? hvc2d_nondom(hvc, points, size, ref) + : hvc2d(hvc, points, size, ref); + DEBUG1( + hvc_check(hv_total, hvc, points, dim, size, ref, ignore_dominated)); } else if (dim == 3 && ignore_dominated) { hv_total = hvc3d(hvc, points, size, ref); DEBUG1(hvc_check(hv_total, hvc, points, dim, size, ref, - /* ignore_dominated = */true)); + /* ignore_dominated = */ true)); } else { - hv_total = fpli_hv(points, dim, (int) size, ref); + hv_total = fpli_hv(points, dim, (int)size, ref); if (ignore_dominated) - hvc_1point_diffs_nondom(hvc, points, dim, size, ref, NULL, hv_total); + hvc_1point_diffs_nondom(hvc, points, dim, size, ref, NULL, + hv_total); else hvc_1point_diffs(hvc, points, dim, size, ref, NULL, hv_total); } diff --git a/c/hv_priv.h b/c/hv_priv.h index 20b1f037..39258de4 100644 --- a/c/hv_priv.h +++ b/c/hv_priv.h @@ -2,10 +2,10 @@ #define _HV_PRIV_H #if !defined(HV_DIMENSION) || (HV_DIMENSION != 3 && HV_DIMENSION != 4) -#error "HV_DIMENSION must be 3 or 4" +# error "HV_DIMENSION must be 3 or 4" #endif -#include // DBL_MAX +#include // DBL_MAX #include // memcpy #include "sort.h" @@ -17,10 +17,14 @@ */ typedef struct dlnode { - const double * x; // point coordinates (objective vector). - struct dlnode * next[HV_DIMENSION - 2]; /* keeps the points sorted according to coordinates 2,3 and 4 + const double * x; // point coordinates (objective vector). + struct dlnode * + next[HV_DIMENSION - + 2]; /* keeps the points sorted according to coordinates 2,3 and 4 (in the case of 2 and 3, only the points swept by 4 are kept) */ - struct dlnode * prev[HV_DIMENSION - 2]; //keeps the points sorted according to coordinates 2 and 3 (except the sentinel 3) + struct dlnode * prev + [HV_DIMENSION - + 2]; //keeps the points sorted according to coordinates 2 and 3 (except the sentinel 3) struct dlnode * cnext[2]; //current next #if HV_DIMENSION == 4 || defined(HVC_ONLY) struct dlnode * closest[2]; // closest[0] == cx, closest[1] == cy @@ -29,9 +33,9 @@ typedef struct dlnode { #endif #ifdef HVC_ONLY double area, volume; - double last_slice_z; // FIXME: Is this really needed? + double last_slice_z; // FIXME: Is this really needed? struct dlnode * head[2]; // lowest (x, y) - bool ignore; // hvc should be zero (duplicated or dominated) + bool ignore; // hvc should be zero (duplicated or dominated) #endif } dlnode_t; @@ -41,9 +45,9 @@ typedef struct dlnode { static inline void restart_list_y(dlnode_t * list) { - assert(list+1 == list->next[0]); - list->cnext[0] = list+1; - (list+1)->cnext[1] = list; + assert(list + 1 == list->next[0]); + list->cnext[0] = list + 1; + (list + 1)->cnext[1] = list; } #if HV_DIMENSION == 4 || defined(HVC_ONLY) @@ -76,7 +80,7 @@ print_x(const dlnode_t * p) } #if HV_DIMENSION == 3 -#include "hv3d_priv.h" +# include "hv3d_priv.h" #endif // HV_DIMENSION == 3 // ------------------------ Circular double-linked list ---------------------- @@ -143,13 +147,13 @@ init_sentinels(dlnode_t * list, const double * ref) // Allocate the 3 sentinels of dimension dim. const double z[] = { #if HV_DIMENSION == 3 - -DBL_MAX, ref[1], -DBL_MAX, // Sentinel 1 - ref[0], -DBL_MAX, -DBL_MAX, // Sentinel 2 - -DBL_MAX, -DBL_MAX, ref[2] // Sentinel 2 + -DBL_MAX, ref[1], -DBL_MAX, // Sentinel 1 + ref[0], -DBL_MAX, -DBL_MAX, // Sentinel 2 + -DBL_MAX, -DBL_MAX, ref[2] // Sentinel 2 #else - -DBL_MAX, ref[1], -DBL_MAX, -DBL_MAX, // Sentinel 1 - ref[0], -DBL_MAX, -DBL_MAX, -DBL_MAX, // Sentinel 2 - -DBL_MAX, -DBL_MAX, ref[2], ref[3] // Sentinel 2 + -DBL_MAX, ref[1], -DBL_MAX, -DBL_MAX, // Sentinel 1 + ref[0], -DBL_MAX, -DBL_MAX, -DBL_MAX, // Sentinel 2 + -DBL_MAX, -DBL_MAX, ref[2], ref[3] // Sentinel 2 #endif }; @@ -162,15 +166,15 @@ init_sentinels(dlnode_t * list, const double * ref) to the 1st and 2nd coordinates, and for that list we need two sentinels to represent (-inf, ref[1]) and (ref[0], -inf). */ reset_sentinels(list); - init_sentinel(list, x); // Sentinel 1 - init_sentinel(list+1, x + HV_DIMENSION); // Sentinel 2 - init_sentinel(list+2, x + 2 * HV_DIMENSION); // Sentinel 3 + init_sentinel(list, x); // Sentinel 1 + init_sentinel(list + 1, x + HV_DIMENSION); // Sentinel 2 + init_sentinel(list + 2, x + 2 * HV_DIMENSION); // Sentinel 3 } static inline dlnode_t * new_cdllist(size_t n, const double * ref) { - dlnode_t * list = (dlnode_t *) malloc((n + 3) * sizeof(*list)); + dlnode_t * list = (dlnode_t *)malloc((n + 3) * sizeof(*list)); init_sentinels(list, ref); return list; } @@ -179,11 +183,12 @@ new_cdllist(size_t n, const double * ref) * Setup circular double-linked list in each dimension */ static inline dlnode_t * -setup_cdllist(const double * restrict data, size_t n, const double * restrict ref) +setup_cdllist(const double * restrict data, size_t n, + const double * restrict ref) { ASSUME(n >= 1); const dimension_t dim = HV_DIMENSION; - const double **scratch = malloc(n * sizeof(*scratch)); + const double ** scratch = malloc(n * sizeof(*scratch)); size_t i, j; for (i = 0, j = 0; j < n; j++) { /* Filter those points that do not strictly dominate the reference @@ -196,14 +201,16 @@ setup_cdllist(const double * restrict data, size_t n, const double * restrict re } n = i; // Update number of points. if (likely(n > 1)) - qsort(scratch, n, sizeof(*scratch), + qsort( + scratch, n, sizeof(*scratch), #ifdef HVC_ONLY - // Lexicographic ordering ensures that we do not have dominated points in the AVL-tree. - cmp_double_asc_rev_3d + // Lexicographic ordering ensures that we do not have dominated points in the AVL-tree. + cmp_double_asc_rev_3d #else - (HV_DIMENSION == 3) ? cmp_double_asc_only_3d : cmp_double_asc_only_4d + (HV_DIMENSION == 3) ? cmp_double_asc_only_3d + : cmp_double_asc_only_4d #endif - ); + ); dlnode_t * list = new_cdllist(n, ref); if (unlikely(n == 0)) { @@ -212,9 +219,9 @@ setup_cdllist(const double * restrict data, size_t n, const double * restrict re } const dimension_t d = HV_DIMENSION - 3; // index within the list. - assert(list->next[d] == list+1); - dlnode_t * q = list+1; - dlnode_t * list3 = list+3; + assert(list->next[d] == list + 1); + dlnode_t * q = list + 1; + dlnode_t * list3 = list + 3; assert(q->next[d] == list + 2); for (i = 0, j = 0; j < n; j++) { dlnode_t * p = list3 + i; @@ -230,7 +237,7 @@ setup_cdllist(const double * restrict data, size_t n, const double * restrict re // Initialize it when debugging so it will crash if uninitialized. DEBUG1(p->head[0] = p->head[1] = NULL); #endif - // Link the list in order. + // Link the list in order. q->next[d] = p; p->prev[d] = q; q = p; @@ -239,10 +246,10 @@ setup_cdllist(const double * restrict data, size_t n, const double * restrict re n = i; free(scratch); assert((list3 + n - 1) == q); - assert(list+2 == list->prev[d]); + assert(list + 2 == list->prev[d]); // q = last point, q->next = s3, s3->prev = last point - q->next[d] = list+2; - (list+2)->prev[d] = q; + q->next[d] = list + 2; + (list + 2)->prev[d] = q; #if HV_DIMENSION == 3 hv3d_preprocessing(list, n); #endif @@ -252,7 +259,7 @@ setup_cdllist(const double * restrict data, size_t n, const double * restrict re static inline void free_cdllist(dlnode_t * list) { - free((void*) list->x); // Free sentinels. + free((void *)list->x); // Free sentinels. free(list); } @@ -273,7 +280,8 @@ free_cdllist(dlnode_t * list) then u=q->cnext[i]. */ static inline double -compute_area_simple(const double * px, const dlnode_t * q, const dlnode_t * u, uint_fast8_t i) +compute_area_simple(const double * px, const dlnode_t * q, const dlnode_t * u, + uint_fast8_t i) { ASSUME(i == 0 || i == 1); const uint_fast8_t j = 1 - i; diff --git a/c/hvapprox.c b/c/hvapprox.c index 56960210..82621f64 100644 --- a/c/hvapprox.c +++ b/c/hvapprox.c @@ -6,23 +6,28 @@ #include "pow_int.h" #include "rng.h" -static inline long double fractl(long double x) { return x - truncl(x); } +static inline long double +fractl(long double x) +{ + return x - truncl(x); +} #define ALMOST_ZERO_WEIGHT 1e-20 #ifndef M_PIl -# define M_PIl 3.141592653589793238462643383279502884L /* pi */ +# define M_PIl 3.141592653589793238462643383279502884L /* pi */ #endif #ifndef M_PI_2l -# define M_PI_2l 1.570796326794896619231321691639751442L /* pi/2 */ +# define M_PI_2l 1.570796326794896619231321691639751442L /* pi/2 */ #endif #ifndef M_PI_4l -# define M_PI_4l 0.785398163397448309615660845819875721L /* pi/4 */ +# define M_PI_4l 0.785398163397448309615660845819875721L /* pi/4 */ #endif static double * -transform_and_filter(const double * restrict data, dimension_t dim, size_t * restrict npoints_p, - const double * restrict ref, const bool * restrict maximise) +transform_and_filter(const double * restrict data, dimension_t dim, + size_t * restrict npoints_p, const double * restrict ref, + const bool * restrict maximise) { size_t npoints = *npoints_p; double * points = malloc(dim * npoints * sizeof(double)); @@ -32,26 +37,23 @@ transform_and_filter(const double * restrict data, dimension_t dim, size_t * res for (i = 0, j = 0; i < npoints; i++) { for (k = 0; k < dim; k++) { points[j * dim + k] = ref[k] - data[i * dim + k]; - if (maximise[k]) - points[j * dim + k] = -points[j * dim + k]; + if (maximise[k]) points[j * dim + k] = -points[j * dim + k]; // Filter out dominated points (must be >0 in all objectives) - if (points[j * dim + k] <= 0) - break; + if (points[j * dim + k] <= 0) break; } - if (k == dim) - j++; + if (k == dim) j++; } *npoints_p = j; if (*npoints_p == 0) { - free (points); + free(points); return NULL; } return points; } static inline double -get_expected_value(const double * restrict points, dimension_t dim, size_t npoints, - const double * restrict w) +get_expected_value(const double * restrict points, dimension_t dim, + size_t npoints, const double * restrict w) { ASSUME(1 <= dim && dim <= 32); ASSUME(npoints >= 1); @@ -75,8 +77,8 @@ get_expected_value(const double * restrict points, dimension_t dim, size_t npoin precision as possible. */ static const long double sphere_area_div_2_pow_d[] = { - 0.0L, // d = 0, value = 0.0 - 1.0L, // d = 1, value = 1.0 + 0.0L, // d = 0, value = 0.0 + 1.0L, // d = 1, value = 1.0 0x1.921fb54442d18469898cc51701b839a252049c1115p+00L, // d = 2, value = 1.5707963267948966 0x1.921fb54442d18469898cc51701b839a252049c1115p+00L, // d = 3, value = 1.5707963267948966 0x1.3bd3cc9be45de5a4adc4d9b30118358e10acd47fc2p+00L, // d = 4, value = 1.2337005501361697 @@ -116,8 +118,8 @@ static const long double sphere_area_div_2_pow_d[] = { precision as possible. */ static const long double sphere_area_div_2_pow_d_times_d[] = { - 0.0L, // d = 0, value = 0.0 - 1.0L, // d = 1, value = 1.0 + 0.0L, // d = 0, value = 0.0 + 1.0L, // d = 1, value = 1.0 0x1.921fb54442d18469898cc51701b839a252049c1115p-01L, // d = 2, value = 0.7853981633974483 0x1.0c152382d73658465bb32e0f567ad116e158680b63p-01L, // d = 3, value = 0.5235987755982989 0x1.3bd3cc9be45de5a4adc4d9b30118358e10acd47fc2p-02L, // d = 4, value = 0.30842513753404244 @@ -165,11 +167,11 @@ hv_approx_normal(const double * restrict data, int nobjs, int n, ASSUME(nobjs > 1); ASSUME(nobjs < 32); ASSUME(n >= 0); - const dimension_t dim = (dimension_t) nobjs; - size_t npoints = (size_t) n; - const double * points = transform_and_filter(data, dim, &npoints, ref, maximise); - if (points == NULL) - return 0; + const dimension_t dim = (dimension_t)nobjs; + size_t npoints = (size_t)n; + const double * points = + transform_and_filter(data, dim, &npoints, ref, maximise); + if (points == NULL) return 0; rng_state * rng = rng_new(random_seed); double * w = malloc(dim * sizeof(double)); @@ -186,8 +188,7 @@ hv_approx_normal(const double * restrict data, int nobjs, int n, w[k] = ALMOST_ZERO_WEIGHT; } double norm = 0.0; - for (k = 0; k < dim; k++) - norm += w[k] * w[k]; + for (k = 0; k < dim; k++) norm += w[k] * w[k]; norm = sqrt(norm); for (k = 0; k < dim; k++) { // 1 / (w[k] / norm) so we avoid the division when calculating the @@ -198,9 +199,10 @@ hv_approx_normal(const double * restrict data, int nobjs, int n, } free(w); free(rng); - free((void*)points); + free((void *)points); const long double c_m = sphere_area_div_2_pow_d_times_d[dim]; - return STATIC_CAST(double, c_m * (expected / STATIC_CAST(long double, nsamples))); + return STATIC_CAST(double, + c_m *(expected / STATIC_CAST(long double, nsamples))); } @@ -209,44 +211,40 @@ construct_polar_a(dimension_t dim, uint_fast32_t nsamples) { ASSUME(1 <= dim && dim <= 32); // Step 1: find prime p such that dim <= eularfunction(p)/2 == (p-1)/2 - static const dimension_t primes [] = { - 1, 3, 5, 7, 11, 11, 13, 17, 17, 19, - 23, 23, 29, 29, 29, 31, 37, 37, 37, 41, - 41, 43, 47, 47, 53, 53, 53, 59, 59, 59, - 61, 67, 67 }; + static const dimension_t primes[] = { + 1, 3, 5, 7, 11, 11, 13, 17, 17, 19, 23, 23, 29, 29, 29, 31, 37, + 37, 37, 41, 41, 43, 47, 47, 53, 53, 53, 59, 59, 59, 61, 67, 67}; const dimension_t p = primes[dim]; DEBUG2_PRINT("construct_polar_a: prime: %u\n", (unsigned int)p); uint_fast32_t * a = malloc(dim * sizeof(uint_fast32_t)); a[0] = 1; - DEBUG2_PRINT("construct_polar_a: a[%u] = %lu", - (unsigned int) dim, (unsigned long) a[0]); + DEBUG2_PRINT("construct_polar_a: a[%u] = %lu", (unsigned int)dim, + (unsigned long)a[0]); for (dimension_t k = 1; k < dim; k++) { long double temp = 2 * fabsl(cosl(2 * M_PIl * k / p)); temp = fractl(temp); a[k] = STATIC_CAST(uint_fast32_t, llroundl(nsamples * temp)); - DEBUG2_PRINT(", %lu", (unsigned long) a[k]); + DEBUG2_PRINT(", %lu", (unsigned long)a[k]); } DEBUG2_PRINT("\n"); return a; } static void -compute_polar_sample(long double * sample, dimension_t dim, - uint_fast32_t i, uint_fast32_t nsamples, - const uint_fast32_t * a) +compute_polar_sample(long double * sample, dimension_t dim, uint_fast32_t i, + uint_fast32_t nsamples, const uint_fast32_t * a) { ASSUME(i + 1 <= nsamples); if (i + 1 < nsamples) { - long double factor = (i+1) / STATIC_CAST(long double, nsamples); + long double factor = (i + 1) / STATIC_CAST(long double, nsamples); for (dimension_t k = 0; k < dim; k++) { long double val = (factor * a[k]); sample[k] = fractl(val); } } else { // Last point is always 0. - for (dimension_t k = 0; k < dim; k++) - sample[k] = 0.0; + for (dimension_t k = 0; k < dim; k++) sample[k] = 0.0; } } @@ -317,111 +315,292 @@ int_of_power_of_sin_from_0_to_b(dimension_t m, double b) double sin_b, cos_b; switch (m) { - case 0: - return b; - case 1: - return 1 - cos(b); - case 2: - return 0.5*b - 0.25*sin(2*b); - case 3: - cos_b = cos(b); - return POW(cos_b, 3)/3 - cos_b + 2/3.; - case 4: - sin_b = sin(b); cos_b = cos(b); - return 0.375*b - cos_b*sin_b*(0.25*POW(sin_b, 2) + 0.375); - case 5: - cos_b = cos(b); - return 8/15. - cos_b*(POW(cos_b, 4)/5 - 2/3.*POW(cos_b, 2) + 1); - case 6: - sin_b = sin(b); cos_b = cos(b); - return 0.3125*b - cos_b*sin_b*(POW(sin_b, 4)/6 + (5/24.)*POW(sin_b, 2) + 0.3125); - case 7: - cos_b = cos(b); - return cos_b*(POW(cos_b, 6)/7 - 3/5.*POW(cos_b, 4) + POW(cos_b, 2) - 1) + 16/35.; - case 8: - sin_b = sin(b); cos_b = cos(b); - return 0.2734375*b - cos_b*sin_b*(0.125*POW(sin_b, 6) + (7/48.)*POW(sin_b, 4) + (35/192.)*POW(sin_b, 2) + 0.2734375); - case 9: - cos_b = cos(b); - return 128/315. - cos_b*(POW(cos_b, 8)/9. - 4/7.*POW(cos_b, 6) + (6/5.)*POW(cos_b, 4) - 4/3.*POW(cos_b, 2) + 1); - case 10: - sin_b = sin(b); cos_b = cos(b); - return 0.24609375*b - cos_b*sin_b*(POW(sin_b, 8)/10. + 9/80.*POW(sin_b, 6) + 21/160.*POW(sin_b, 4) + 0.1640625*POW(sin_b, 2) + 0.24609375); - case 11: - cos_b = cos(b); - return POW(cos_b, 11)/11. - 5/9.*POW(cos_b, 9) + (10/7.)*POW(cos_b, 7) - 2*POW(cos_b, 5) + (5/3.)*POW(cos_b, 3) - cos_b + 256/693.; - case 12: - sin_b = sin(b); cos_b = cos(b); - return 0.2255859375*b - cos_b*sin_b*(POW(sin_b, 10)/12 + 11/120.*POW(sin_b, 8) + 33/320.*POW(sin_b, 6) + 77/640.*POW(sin_b, 4) + 0.150390625*POW(sin_b, 2) + 0.2255859375); - case 13: - cos_b = cos(b); - return 1024/3003. -POW(cos_b, 13)/13. + (6/11.)*POW(cos_b, 11) - 5/3.*POW(cos_b, 9) + (20/7.)*POW(cos_b, 7) - 3*POW(cos_b, 5) + 2*POW(cos_b, 3) - cos_b; - case 14: - sin_b = sin(b); cos_b = cos(b); - return 0.20947265625*b - cos_b*sin_b*(POW(sin_b, 12)/14. + 13/168.*POW(sin_b, 10) + 143/1680.*POW(sin_b, 8) + 429/4480.*POW(sin_b, 6) + 143/1280.*POW(sin_b, 4) + 0.1396484375*POW(sin_b, 2) + 0.20947265625); - case 15: - cos_b = cos(b); - return POW(cos_b, 15)/15. - 7/13.*POW(cos_b, 13) + (21/11.)*POW(cos_b, 11) - 35/9.*POW(cos_b, 9) + 5*POW(cos_b, 7) - 21/5.*POW(cos_b, 5) + (7/3.)*POW(cos_b, 3) - cos_b + 2048/6435.; - case 16: - sin_b = sin(b); cos_b = cos(b); - return 0.196380615234375*b - cos_b*sin_b*(0.0625*POW(sin_b, 14) + 15/224.*POW(sin_b, 12) + 65/896.*POW(sin_b, 10) + 143/1792.*POW(sin_b, 8) + 1287/14336.*POW(sin_b, 6) + 0.104736328125*POW(sin_b, 4) + 0.13092041015625*POW(sin_b, 2) + 0.196380615234375); - case 17: - cos_b = cos(b); - return 32768/109395. - POW(cos_b, 17)/17. + (8/15.)*POW(cos_b, 15) - 28/13.*POW(cos_b, 13) + (56/11.)*POW(cos_b, 11) - 70/9.*POW(cos_b, 9) + 8*POW(cos_b, 7) - 28/5.*POW(cos_b, 5) + (8/3.)*POW(cos_b, 3) - cos_b; - case 18: - sin_b = sin(b); cos_b = cos(b); - return 0.1854705810546875*b - cos_b*sin_b*(POW(sin_b, 16)/18. + 17/288.*POW(sin_b, 14) + 85/1344.*POW(sin_b, 12) + 1105/16128.*POW(sin_b, 10) + 2431/32256.*POW(sin_b, 8) + 2431/28672.*POW(sin_b, 6) + 2431/24576.*POW(sin_b, 4) + 12155/98304.*POW(sin_b, 2) + 0.1854705810546875); - case 19: - cos_b = cos(b); - return POW(cos_b, 19)/19. - 9/17.*POW(cos_b, 17) + (12/5.)*POW(cos_b, 15) - 84/13.*POW(cos_b, 13) + (126/11.)*POW(cos_b, 11) - 14*POW(cos_b, 9) + 12*POW(cos_b, 7) - 36/5.*POW(cos_b, 5) + 3*POW(cos_b, 3) - cos_b + 65536/230945.; - case 20: - sin_b = sin(b); cos_b = cos(b); - return 0.17619705200195313*b - cos_b*sin_b*(POW(sin_b, 18)/20. + 19/360.*POW(sin_b, 16) + 323/5760.*POW(sin_b, 14) + 323/5376.*POW(sin_b, 12) + 4199/64512.*POW(sin_b, 10) + 46189/645120.*POW(sin_b, 8) + 46189/573440.*POW(sin_b, 6) + 46189/491520.*POW(sin_b, 4) + 46189/393216.*POW(sin_b, 2) + 0.17619705200195313); - case 21: - cos_b = cos(b); - return 262144/969969. -POW(cos_b, 21)/21 + (10/19.)*POW(cos_b, 19) - 45/17.*POW(cos_b, 17) + 8*POW(cos_b, 15) - 210/13.*POW(cos_b, 13) + (252/11.)*POW(cos_b, 11) - 70/3.*POW(cos_b, 9) + (120/7.)*POW(cos_b, 7) - 9*POW(cos_b, 5) + (10/3.)*POW(cos_b, 3) - cos_b; - case 22: - sin_b = sin(b); cos_b = cos(b); - return 0.16818809509277344*b - cos_b*sin_b*( - POW(sin_b, 20)/22. + 21/440.*POW(sin_b, 18) + 133/2640.*POW(sin_b, 16) + 2261/42240.*POW(sin_b, 14) + 323/5632.*POW(sin_b, 12) + 4199/67584.*POW(sin_b, 10) - + 4199/61440.*POW(sin_b, 8) + 12597/163840.*POW(sin_b, 6) + 29393/327680.*POW(sin_b, 4) + 0.11212539672851563*POW(sin_b, 2) + 0.16818809509277344); - case 23: - cos_b = cos(b); - return POW(cos_b, 23)/23 - 11/21.*POW(cos_b, 21) + (55/19.)*POW(cos_b, 19) - 165/17.*POW(cos_b, 17) + 22*POW(cos_b, 15) - 462/13.*POW(cos_b, 13) + 42*POW(cos_b, 11) - 110/3.*POW(cos_b, 9) + (165/7.)*POW(cos_b, 7) - 11*POW(cos_b, 5) + (11/3.)*POW(cos_b, 3) - cos_b + 524288/2028117.; - case 24: - sin_b = sin(b); cos_b = cos(b); - return 0.16118025779724121*b - cos_b*sin_b*(POW(sin_b, 22)/24. + 23/528.*POW(sin_b, 20) + 161/3520.*POW(sin_b, 18) + 3059/63360.*POW(sin_b, 16) + 52003/1013760.*POW(sin_b, 14) + 7429/135168.*POW(sin_b, 12) + 96577/1622016.*POW(sin_b, 10) + 96577/1474560.*POW(sin_b, 8) + 96577/1310720.*POW(sin_b, 6) + 676039/7864320.*POW(sin_b, 4) + 676039/6291456.*POW(sin_b, 2) + 0.16118025779724121); - case 25: - cos_b = cos(b); - return 4194304/16900975. - POW(cos_b, 25)/25. + (12/23.)*POW(cos_b, 23) - 22/7.*POW(cos_b, 21) + (220/19.)*POW(cos_b, 19) - 495/17.*POW(cos_b, 17) + (264/5.)*POW(cos_b, 15) - 924/13.*POW(cos_b, 13) + 72*POW(cos_b, 11) - 55*POW(cos_b, 9) + (220/7.)*POW(cos_b, 7) - 66/5.*POW(cos_b, 5) + 4*POW(cos_b, 3) - cos_b; - case 26: - sin_b = sin(b); cos_b = cos(b); - return 0.15498101711273193*b - cos_b*sin_b*( - POW(sin_b, 24)/26. + 25/624.*POW(sin_b, 22) + 575/13728.*POW(sin_b, 20) + 805/18304.*POW(sin_b, 18) + 15295/329472.*POW(sin_b, 16) + 260015/5271552.*POW(sin_b, 14) - + 185725/3514368.*POW(sin_b, 12) + 185725/3244032.*POW(sin_b, 10) + 37145/589824.*POW(sin_b, 8) + 0.070848464965820313*POW(sin_b, 6) + 260015/3145728.*POW(sin_b, 4) + 1300075/12582912.*POW(sin_b, 2) + 0.15498101711273193); - case 27: - cos_b = cos(b); - return POW(cos_b, 27)/27. - 13/25.*POW(cos_b, 25) + (78/23.)*POW(cos_b, 23) - 286/21.*POW(cos_b, 21) + (715/19.)*POW(cos_b, 19) - 1287/17.*POW(cos_b, 17) + (572/5.)*POW(cos_b, 15) - 132*POW(cos_b, 13) + 117*POW(cos_b, 11) - 715/9.*POW(cos_b, 9) + (286/7.)*POW(cos_b, 7) - 78/5.*POW(cos_b, 5) + (13/3.)*POW(cos_b, 3) - cos_b + 8388608/35102025.; - case 28: - sin_b = sin(b); cos_b = cos(b); - return 0.14944598078727722*b - cos_b*sin_b*( - POW(sin_b, 26)/28. + 27/728.*POW(sin_b, 24) + 225/5824.*POW(sin_b, 22) + 5175/128128.*POW(sin_b, 20) + 3105/73216.*POW(sin_b, 18) + 6555/146432.*POW(sin_b, 16) + 111435/2342912.*POW(sin_b, 14) + 1671525/32800768.*POW(sin_b, 12) + 557175/10092544.*POW(sin_b, 10) + 111435/1835008.*POW(sin_b, 8) + 1002915/14680064.*POW(sin_b, 6) + 0.079704523086547852*POW(sin_b, 4) + 0.099630653858184814*POW(sin_b, 2) + 0.14944598078727722); - case 29: - cos_b = cos(b); - return 33554432/145422675. - POW(cos_b, 29)/29 + (14/27.)*POW(cos_b, 27) - 91/25.*POW(cos_b, 25) + (364/23.)*POW(cos_b, 23) - 143/3.*POW(cos_b, 21) + (2002/19.)*POW(cos_b, 19) - 3003/17.*POW(cos_b, 17) + (1144/5.)*POW(cos_b, 15) - 231*POW(cos_b, 13) + 182*POW(cos_b, 11) - 1001/9.*POW(cos_b, 9) + 52*POW(cos_b, 7) - 91/5.*POW(cos_b, 5) + (14/3.)*POW(cos_b, 3) - cos_b; - case 30: - sin_b = sin(b); cos_b = cos(b); - return 0.14446444809436798*b - cos_b*sin_b*( - POW(sin_b, 28)/30. + 29/840.*POW(sin_b, 26) + 261/7280.*POW(sin_b, 24) + 435/11648.*POW(sin_b, 22) + 10005/256256.*POW(sin_b, 20) + 6003/146432.*POW(sin_b, 18) + 12673/292864.*POW(sin_b, 16) + 215441/4685824.*POW(sin_b, 14) + 3231615/65601536.*POW(sin_b, 12) + 1077205/20185088.*POW(sin_b, 10) + 215441/3670016.*POW(sin_b, 8) + 1938969/29360128.*POW(sin_b, 6) + 0.07704770565032959*POW(sin_b, 4) + 0.096309632062911987*POW(sin_b, 2) + 0.14446444809436798); - case 31: - cos_b = cos(b); - return POW(cos_b, 31)/31. - 15/29.*POW(cos_b, 29) + (35/9.)*POW(cos_b, 27) - 91/5.*POW(cos_b, 25) + (1365/23.)*POW(cos_b, 23) - 143*POW(cos_b, 21) + (5005/19.)*POW(cos_b, 19) - 6435/17.*POW(cos_b, 17) + 429*POW(cos_b, 15) - 385*POW(cos_b, 13) + 273*POW(cos_b, 11) - 455/3.*POW(cos_b, 9) + 65*POW(cos_b, 7) - 21*POW(cos_b, 5) + 5*POW(cos_b, 3) - cos_b + 67108864/300540195.; - case 32: - sin_b = sin(b); cos_b = cos(b); - return 0.13994993409141898*b - cos_b*sin_b*( - 0.03125*POW(sin_b, 30) + 31/960.*POW(sin_b, 28) + 899/26880.*POW(sin_b, 26) + 8091/232960.*POW(sin_b, 24) + 13485/372736.*POW(sin_b, 22) + 310155/8200192.*POW(sin_b, 20) + 186093/4685824.*POW(sin_b, 18) + 392863/9371648.*POW(sin_b, 16) + 6678671/149946368.*POW(sin_b, 14) + 100180065/2099249152.*POW(sin_b, 12) + 33393355/645922816.*POW(sin_b, 10) + 6678671/117440512.*POW(sin_b, 8) + 60108039/939524096.*POW(sin_b, 6) + 0.07463996484875679*POW(sin_b, 4) + 0.093299956060945988*POW(sin_b, 2) + 0.13994993409141898); - default: - unreachable(); + case 0: + return b; + case 1: + return 1 - cos(b); + case 2: + return 0.5 * b - 0.25 * sin(2 * b); + case 3: + cos_b = cos(b); + return POW(cos_b, 3) / 3 - cos_b + 2 / 3.; + case 4: + sin_b = sin(b); + cos_b = cos(b); + return 0.375 * b - cos_b * sin_b * (0.25 * POW(sin_b, 2) + 0.375); + case 5: + cos_b = cos(b); + return 8 / 15. - + cos_b * (POW(cos_b, 4) / 5 - 2 / 3. * POW(cos_b, 2) + 1); + case 6: + sin_b = sin(b); + cos_b = cos(b); + return 0.3125 * b - + cos_b * sin_b * + (POW(sin_b, 4) / 6 + (5 / 24.) * POW(sin_b, 2) + 0.3125); + case 7: + cos_b = cos(b); + return cos_b * (POW(cos_b, 6) / 7 - 3 / 5. * POW(cos_b, 4) + + POW(cos_b, 2) - 1) + + 16 / 35.; + case 8: + sin_b = sin(b); + cos_b = cos(b); + return 0.2734375 * b - + cos_b * sin_b * + (0.125 * POW(sin_b, 6) + (7 / 48.) * POW(sin_b, 4) + + (35 / 192.) * POW(sin_b, 2) + 0.2734375); + case 9: + cos_b = cos(b); + return 128 / 315. - + cos_b * (POW(cos_b, 8) / 9. - 4 / 7. * POW(cos_b, 6) + + (6 / 5.) * POW(cos_b, 4) - 4 / 3. * POW(cos_b, 2) + 1); + case 10: + sin_b = sin(b); + cos_b = cos(b); + return 0.24609375 * b - + cos_b * sin_b * + (POW(sin_b, 8) / 10. + 9 / 80. * POW(sin_b, 6) + + 21 / 160. * POW(sin_b, 4) + 0.1640625 * POW(sin_b, 2) + + 0.24609375); + case 11: + cos_b = cos(b); + return POW(cos_b, 11) / 11. - 5 / 9. * POW(cos_b, 9) + + (10 / 7.) * POW(cos_b, 7) - 2 * POW(cos_b, 5) + + (5 / 3.) * POW(cos_b, 3) - cos_b + 256 / 693.; + case 12: + sin_b = sin(b); + cos_b = cos(b); + return 0.2255859375 * b - + cos_b * sin_b * + (POW(sin_b, 10) / 12 + 11 / 120. * POW(sin_b, 8) + + 33 / 320. * POW(sin_b, 6) + 77 / 640. * POW(sin_b, 4) + + 0.150390625 * POW(sin_b, 2) + 0.2255859375); + case 13: + cos_b = cos(b); + return 1024 / 3003. - POW(cos_b, 13) / 13. + + (6 / 11.) * POW(cos_b, 11) - 5 / 3. * POW(cos_b, 9) + + (20 / 7.) * POW(cos_b, 7) - 3 * POW(cos_b, 5) + + 2 * POW(cos_b, 3) - cos_b; + case 14: + sin_b = sin(b); + cos_b = cos(b); + return 0.20947265625 * b - + cos_b * sin_b * + (POW(sin_b, 12) / 14. + 13 / 168. * POW(sin_b, 10) + + 143 / 1680. * POW(sin_b, 8) + 429 / 4480. * POW(sin_b, 6) + + 143 / 1280. * POW(sin_b, 4) + 0.1396484375 * POW(sin_b, 2) + + 0.20947265625); + case 15: + cos_b = cos(b); + return POW(cos_b, 15) / 15. - 7 / 13. * POW(cos_b, 13) + + (21 / 11.) * POW(cos_b, 11) - 35 / 9. * POW(cos_b, 9) + + 5 * POW(cos_b, 7) - 21 / 5. * POW(cos_b, 5) + + (7 / 3.) * POW(cos_b, 3) - cos_b + 2048 / 6435.; + case 16: + sin_b = sin(b); + cos_b = cos(b); + return 0.196380615234375 * b - + cos_b * sin_b * + (0.0625 * POW(sin_b, 14) + 15 / 224. * POW(sin_b, 12) + + 65 / 896. * POW(sin_b, 10) + 143 / 1792. * POW(sin_b, 8) + + 1287 / 14336. * POW(sin_b, 6) + + 0.104736328125 * POW(sin_b, 4) + + 0.13092041015625 * POW(sin_b, 2) + 0.196380615234375); + case 17: + cos_b = cos(b); + return 32768 / 109395. - POW(cos_b, 17) / 17. + + (8 / 15.) * POW(cos_b, 15) - 28 / 13. * POW(cos_b, 13) + + (56 / 11.) * POW(cos_b, 11) - 70 / 9. * POW(cos_b, 9) + + 8 * POW(cos_b, 7) - 28 / 5. * POW(cos_b, 5) + + (8 / 3.) * POW(cos_b, 3) - cos_b; + case 18: + sin_b = sin(b); + cos_b = cos(b); + return 0.1854705810546875 * b - + cos_b * sin_b * + (POW(sin_b, 16) / 18. + 17 / 288. * POW(sin_b, 14) + + 85 / 1344. * POW(sin_b, 12) + + 1105 / 16128. * POW(sin_b, 10) + + 2431 / 32256. * POW(sin_b, 8) + + 2431 / 28672. * POW(sin_b, 6) + + 2431 / 24576. * POW(sin_b, 4) + + 12155 / 98304. * POW(sin_b, 2) + 0.1854705810546875); + case 19: + cos_b = cos(b); + return POW(cos_b, 19) / 19. - 9 / 17. * POW(cos_b, 17) + + (12 / 5.) * POW(cos_b, 15) - 84 / 13. * POW(cos_b, 13) + + (126 / 11.) * POW(cos_b, 11) - 14 * POW(cos_b, 9) + + 12 * POW(cos_b, 7) - 36 / 5. * POW(cos_b, 5) + + 3 * POW(cos_b, 3) - cos_b + 65536 / 230945.; + case 20: + sin_b = sin(b); + cos_b = cos(b); + return 0.17619705200195313 * b - + cos_b * sin_b * + (POW(sin_b, 18) / 20. + 19 / 360. * POW(sin_b, 16) + + 323 / 5760. * POW(sin_b, 14) + + 323 / 5376. * POW(sin_b, 12) + + 4199 / 64512. * POW(sin_b, 10) + + 46189 / 645120. * POW(sin_b, 8) + + 46189 / 573440. * POW(sin_b, 6) + + 46189 / 491520. * POW(sin_b, 4) + + 46189 / 393216. * POW(sin_b, 2) + 0.17619705200195313); + case 21: + cos_b = cos(b); + return 262144 / 969969. - POW(cos_b, 21) / 21 + + (10 / 19.) * POW(cos_b, 19) - 45 / 17. * POW(cos_b, 17) + + 8 * POW(cos_b, 15) - 210 / 13. * POW(cos_b, 13) + + (252 / 11.) * POW(cos_b, 11) - 70 / 3. * POW(cos_b, 9) + + (120 / 7.) * POW(cos_b, 7) - 9 * POW(cos_b, 5) + + (10 / 3.) * POW(cos_b, 3) - cos_b; + case 22: + sin_b = sin(b); + cos_b = cos(b); + return 0.16818809509277344 * b - + cos_b * sin_b * + (POW(sin_b, 20) / 22. + 21 / 440. * POW(sin_b, 18) + + 133 / 2640. * POW(sin_b, 16) + + 2261 / 42240. * POW(sin_b, 14) + + 323 / 5632. * POW(sin_b, 12) + + 4199 / 67584. * POW(sin_b, 10) + + 4199 / 61440. * POW(sin_b, 8) + + 12597 / 163840. * POW(sin_b, 6) + + 29393 / 327680. * POW(sin_b, 4) + + 0.11212539672851563 * POW(sin_b, 2) + 0.16818809509277344); + case 23: + cos_b = cos(b); + return POW(cos_b, 23) / 23 - 11 / 21. * POW(cos_b, 21) + + (55 / 19.) * POW(cos_b, 19) - 165 / 17. * POW(cos_b, 17) + + 22 * POW(cos_b, 15) - 462 / 13. * POW(cos_b, 13) + + 42 * POW(cos_b, 11) - 110 / 3. * POW(cos_b, 9) + + (165 / 7.) * POW(cos_b, 7) - 11 * POW(cos_b, 5) + + (11 / 3.) * POW(cos_b, 3) - cos_b + 524288 / 2028117.; + case 24: + sin_b = sin(b); + cos_b = cos(b); + return 0.16118025779724121 * b - + cos_b * sin_b * + (POW(sin_b, 22) / 24. + 23 / 528. * POW(sin_b, 20) + + 161 / 3520. * POW(sin_b, 18) + + 3059 / 63360. * POW(sin_b, 16) + + 52003 / 1013760. * POW(sin_b, 14) + + 7429 / 135168. * POW(sin_b, 12) + + 96577 / 1622016. * POW(sin_b, 10) + + 96577 / 1474560. * POW(sin_b, 8) + + 96577 / 1310720. * POW(sin_b, 6) + + 676039 / 7864320. * POW(sin_b, 4) + + 676039 / 6291456. * POW(sin_b, 2) + 0.16118025779724121); + case 25: + cos_b = cos(b); + return 4194304 / 16900975. - POW(cos_b, 25) / 25. + + (12 / 23.) * POW(cos_b, 23) - 22 / 7. * POW(cos_b, 21) + + (220 / 19.) * POW(cos_b, 19) - 495 / 17. * POW(cos_b, 17) + + (264 / 5.) * POW(cos_b, 15) - 924 / 13. * POW(cos_b, 13) + + 72 * POW(cos_b, 11) - 55 * POW(cos_b, 9) + + (220 / 7.) * POW(cos_b, 7) - 66 / 5. * POW(cos_b, 5) + + 4 * POW(cos_b, 3) - cos_b; + case 26: + sin_b = sin(b); + cos_b = cos(b); + return 0.15498101711273193 * b - + cos_b * sin_b * + (POW(sin_b, 24) / 26. + 25 / 624. * POW(sin_b, 22) + + 575 / 13728. * POW(sin_b, 20) + + 805 / 18304. * POW(sin_b, 18) + + 15295 / 329472. * POW(sin_b, 16) + + 260015 / 5271552. * POW(sin_b, 14) + + 185725 / 3514368. * POW(sin_b, 12) + + 185725 / 3244032. * POW(sin_b, 10) + + 37145 / 589824. * POW(sin_b, 8) + + 0.070848464965820313 * POW(sin_b, 6) + + 260015 / 3145728. * POW(sin_b, 4) + + 1300075 / 12582912. * POW(sin_b, 2) + 0.15498101711273193); + case 27: + cos_b = cos(b); + return POW(cos_b, 27) / 27. - 13 / 25. * POW(cos_b, 25) + + (78 / 23.) * POW(cos_b, 23) - 286 / 21. * POW(cos_b, 21) + + (715 / 19.) * POW(cos_b, 19) - 1287 / 17. * POW(cos_b, 17) + + (572 / 5.) * POW(cos_b, 15) - 132 * POW(cos_b, 13) + + 117 * POW(cos_b, 11) - 715 / 9. * POW(cos_b, 9) + + (286 / 7.) * POW(cos_b, 7) - 78 / 5. * POW(cos_b, 5) + + (13 / 3.) * POW(cos_b, 3) - cos_b + 8388608 / 35102025.; + case 28: + sin_b = sin(b); + cos_b = cos(b); + return 0.14944598078727722 * b - + cos_b * sin_b * + (POW(sin_b, 26) / 28. + 27 / 728. * POW(sin_b, 24) + + 225 / 5824. * POW(sin_b, 22) + + 5175 / 128128. * POW(sin_b, 20) + + 3105 / 73216. * POW(sin_b, 18) + + 6555 / 146432. * POW(sin_b, 16) + + 111435 / 2342912. * POW(sin_b, 14) + + 1671525 / 32800768. * POW(sin_b, 12) + + 557175 / 10092544. * POW(sin_b, 10) + + 111435 / 1835008. * POW(sin_b, 8) + + 1002915 / 14680064. * POW(sin_b, 6) + + 0.079704523086547852 * POW(sin_b, 4) + + 0.099630653858184814 * POW(sin_b, 2) + 0.14944598078727722); + case 29: + cos_b = cos(b); + return 33554432 / 145422675. - POW(cos_b, 29) / 29 + + (14 / 27.) * POW(cos_b, 27) - 91 / 25. * POW(cos_b, 25) + + (364 / 23.) * POW(cos_b, 23) - 143 / 3. * POW(cos_b, 21) + + (2002 / 19.) * POW(cos_b, 19) - 3003 / 17. * POW(cos_b, 17) + + (1144 / 5.) * POW(cos_b, 15) - 231 * POW(cos_b, 13) + + 182 * POW(cos_b, 11) - 1001 / 9. * POW(cos_b, 9) + + 52 * POW(cos_b, 7) - 91 / 5. * POW(cos_b, 5) + + (14 / 3.) * POW(cos_b, 3) - cos_b; + case 30: + sin_b = sin(b); + cos_b = cos(b); + return 0.14446444809436798 * b - + cos_b * sin_b * + (POW(sin_b, 28) / 30. + 29 / 840. * POW(sin_b, 26) + + 261 / 7280. * POW(sin_b, 24) + + 435 / 11648. * POW(sin_b, 22) + + 10005 / 256256. * POW(sin_b, 20) + + 6003 / 146432. * POW(sin_b, 18) + + 12673 / 292864. * POW(sin_b, 16) + + 215441 / 4685824. * POW(sin_b, 14) + + 3231615 / 65601536. * POW(sin_b, 12) + + 1077205 / 20185088. * POW(sin_b, 10) + + 215441 / 3670016. * POW(sin_b, 8) + + 1938969 / 29360128. * POW(sin_b, 6) + + 0.07704770565032959 * POW(sin_b, 4) + + 0.096309632062911987 * POW(sin_b, 2) + 0.14446444809436798); + case 31: + cos_b = cos(b); + return POW(cos_b, 31) / 31. - 15 / 29. * POW(cos_b, 29) + + (35 / 9.) * POW(cos_b, 27) - 91 / 5. * POW(cos_b, 25) + + (1365 / 23.) * POW(cos_b, 23) - 143 * POW(cos_b, 21) + + (5005 / 19.) * POW(cos_b, 19) - 6435 / 17. * POW(cos_b, 17) + + 429 * POW(cos_b, 15) - 385 * POW(cos_b, 13) + + 273 * POW(cos_b, 11) - 455 / 3. * POW(cos_b, 9) + + 65 * POW(cos_b, 7) - 21 * POW(cos_b, 5) + 5 * POW(cos_b, 3) - + cos_b + 67108864 / 300540195.; + case 32: + sin_b = sin(b); + cos_b = cos(b); + return 0.13994993409141898 * b - + cos_b * sin_b * + (0.03125 * POW(sin_b, 30) + 31 / 960. * POW(sin_b, 28) + + 899 / 26880. * POW(sin_b, 26) + + 8091 / 232960. * POW(sin_b, 24) + + 13485 / 372736. * POW(sin_b, 22) + + 310155 / 8200192. * POW(sin_b, 20) + + 186093 / 4685824. * POW(sin_b, 18) + + 392863 / 9371648. * POW(sin_b, 16) + + 6678671 / 149946368. * POW(sin_b, 14) + + 100180065 / 2099249152. * POW(sin_b, 12) + + 33393355 / 645922816. * POW(sin_b, 10) + + 6678671 / 117440512. * POW(sin_b, 8) + + 60108039 / 939524096. * POW(sin_b, 6) + + 0.07463996484875679 * POW(sin_b, 4) + + 0.093299956060945988 * POW(sin_b, 2) + 0.13994993409141898); + default: + unreachable(); } #undef POW } @@ -434,7 +613,8 @@ static const long double int_power_of_sin_from_0_to_half_pi[] = { /* GCC on powerpc cannot fold some floating-point expressions involving IBM long double into constant initializers, unless -ffast-math is enabled. See https://gcc.gnu.org/PR19779 */ -#if defined(__GNUC__) && (defined(__PPC__) || defined(__POWERPC__) || defined(__ppc__)) +#if defined(__GNUC__) && \ + (defined(__PPC__) || defined(__POWERPC__) || defined(__ppc__)) /* d = 3 */ 2. / 3., /* d = 4 */ 3.L * M_PI / 16.L, /* d = 5 */ 8. / 15., @@ -531,8 +711,7 @@ compute_int_all(dimension_t dm1) #if DEBUG >= 1 long double prod_int_all = int_all[0]; - for (i = 1; i < dm1; i++) - prod_int_all *= int_all[i]; + for (i = 1; i < dm1; i++) prod_int_all *= int_all[i]; ASSUME(prod_int_all > 0); const long double S_value = sphere_area_div_2_pow_d[dm1 + 1]; DEBUG2_PRINT("sphere / prod_int_all = %22.15Lg / %22.15Lg = %22.15Lg\n", @@ -545,14 +724,15 @@ compute_int_all(dimension_t dm1) } static void -compute_theta(long double *theta, dimension_t dim, const long double *int_all) +compute_theta(long double * theta, dimension_t dim, const long double * int_all) { ASSUME(dim >= 2); ASSUME(dim <= 32); for (dimension_t j = 0; j < dim - 1; j++) { // We multiply here because we computed 1 / int_all[j] before. - theta[j] = solve_inverse_int_of_power_sin(theta[j] * int_all[(dim - 2) - j], - STATIC_CAST(dimension_t, (dim - j) - 2)); + theta[j] = solve_inverse_int_of_power_sin( + theta[j] * int_all[(dim - 2) - j], + STATIC_CAST(dimension_t, (dim - j) - 2)); } } @@ -575,8 +755,8 @@ compute_hua_wang_direction(double * direction, dimension_t dim, for (k = 0; k < dim; k++) { // FIXME: Can direction[k] be negative? If not, then we don't need fabs(). direction[k] = (fabs(direction[k]) <= ALMOST_ZERO_WEIGHT) - ? 1. / ALMOST_ZERO_WEIGHT - : 1. / direction[k]; + ? 1. / ALMOST_ZERO_WEIGHT + : 1. / direction[k]; } } @@ -594,11 +774,11 @@ hv_approx_hua_wang(const double * restrict data, int nobjs, int n, ASSUME(nobjs > 1); ASSUME(nobjs < 32); ASSUME(n >= 0); - const dimension_t dim = (dimension_t) nobjs; - size_t npoints = (size_t) n; - const double * points = transform_and_filter(data, dim, &npoints, ref, maximise); - if (points == NULL) - return 0; + const dimension_t dim = (dimension_t)nobjs; + size_t npoints = (size_t)n; + const double * points = + transform_and_filter(data, dim, &npoints, ref, maximise); + if (points == NULL) return 0; const long double * int_all = compute_int_all(dim - 1); const uint_fast32_t * polar_a = construct_polar_a(dim - 1, nsamples); @@ -617,9 +797,10 @@ hv_approx_hua_wang(const double * restrict data, int nobjs, int n, free(theta); free(w); } - free((void *) int_all); - free((void *) polar_a); - free((void*)points); + free((void *)int_all); + free((void *)polar_a); + free((void *)points); const long double c_m = sphere_area_div_2_pow_d_times_d[dim]; - return STATIC_CAST(double, c_m * (expected / STATIC_CAST(long double, nsamples))); + return STATIC_CAST(double, + c_m *(expected / STATIC_CAST(long double, nsamples))); } diff --git a/c/hvc3d.c b/c/hvc3d.c index b224c490..5e76d3b4 100644 --- a/c/hvc3d.c +++ b/c/hvc3d.c @@ -60,19 +60,21 @@ add_nondominated_point(dlnode_t * p) p->cnext[1]->head[1] = p->cnext[1]->cnext[1]; } else { dlnode_t * q = p->cnext[1]->head[1]; - while (q->x[0] >= p->x[0]){ + while (q->x[0] >= p->x[0]) { q = q->cnext[1]; } p->cnext[1]->head[1] = q; q->cnext[0] = p; } - if (p->cnext[0]->cnext[1]->x[1] > p->x[1] - || (p->cnext[0]->cnext[1]->x[1] == p->x[1] && p->cnext[0]->cnext[1]->x[0] > p->x[0])) + if (p->cnext[0]->cnext[1]->x[1] > p->x[1] || + (p->cnext[0]->cnext[1]->x[1] == p->x[1] && + p->cnext[0]->cnext[1]->x[0] > p->x[0])) p->cnext[0]->cnext[1] = p; - if (p->cnext[1]->cnext[0]->x[0] > p->x[0] - || (p->cnext[1]->cnext[0]->x[0] == p->x[0] && p->cnext[1]->cnext[0]->x[1] > p->x[1])) + if (p->cnext[1]->cnext[0]->x[0] > p->x[0] || + (p->cnext[1]->cnext[0]->x[0] == p->x[0] && + p->cnext[1]->cnext[0]->x[1] > p->x[1])) p->cnext[1]->cnext[0] = p; } @@ -111,12 +113,11 @@ update_volume_simple(const double * px, dlnode_t * q, uint_fast8_t i) static double hvc3d_list(dlnode_t * list) { - assert(list->next[0] == list+1); - assert(list->prev[0] == list+2); - dlnode_t * p = (list+1)->next[0]; - const dlnode_t * stop = list+2; - if (p == stop) - return 0; + assert(list->next[0] == list + 1); + assert(list->prev[0] == list + 2); + dlnode_t * p = (list + 1)->next[0]; + const dlnode_t * stop = list + 2; + if (p == stop) return 0; restart_list_y(list); // Process the first point. @@ -143,12 +144,13 @@ hvc3d_list(dlnode_t * list) area += p->area; dlnode_t * q = p->cnext[0]; - double x[] = { q->x[0], p->x[1] }; // join(p,q) - (x[2] is not important) + double x[] = {q->x[0], p->x[1]}; // join(p,q) - (x[2] is not important) //x[0] = q->x[0]; x[1] = p->x[1]; x[2] = p->x[2]; q->area -= compute_area_simple(x, p->head[1], q->head[0], 0); q = p->cnext[1]; - x[0] = p->x[0]; x[1] = q->x[1]; + x[0] = p->x[0]; + x[1] = q->x[1]; q->area -= compute_area_simple(x, p->head[0], q->head[1], 1); add_nondominated_point(p); @@ -161,13 +163,14 @@ hvc3d_list(dlnode_t * list) } setup_nondominated_point(p); // FIXME: p->head[1]->cnext[0] is always a sentinel, which is pointless to update. - assert(p->head[1]->cnext[0] == list+1); + assert(p->head[1]->cnext[0] == list + 1); update_volume_simple(p->x, p->head[1], 1); return volume; } static void -save_contributions(double * hvc, const dlnode_t * list, const double * restrict data) +save_contributions(double * hvc, const dlnode_t * list, + const double * restrict data) { // FIXME: We could just loop over list+3 n times? // - We need to mark dominated points also as ignored. @@ -179,21 +182,21 @@ save_contributions(double * hvc, const dlnode_t * list, const double * restrict hvc[(p->x - data)/3] = p->volume; } */ - assert(list+1 == list->next[0]); - const dlnode_t * p = (list+1)->next[0]; - const dlnode_t * stop = list+2; + assert(list + 1 == list->next[0]); + const dlnode_t * p = (list + 1)->next[0]; + const dlnode_t * stop = list + 2; while (p != stop) { /* print_x(p); */ /* fprintf(stderr, "hvc = %g\n", p->volume); */ - if (!p->ignore) - hvc[(p->x - data)/3] = p->volume; + if (!p->ignore) hvc[(p->x - data) / 3] = p->volume; p = p->next[0]; } } /* The caller must have initialized hvc to zero. */ double -hvc3d(double * restrict hvc, const double * restrict data, size_t n, const double * restrict ref) +hvc3d(double * restrict hvc, const double * restrict data, size_t n, + const double * restrict ref) { dlnode_t * list = setup_cdllist(data, n, ref); double hv = hvc3d_list(list); diff --git a/c/igd.c b/c/igd.c index 4c73503f..26d566a6 100644 --- a/c/igd.c +++ b/c/igd.c @@ -46,14 +46,15 @@ #include #include -#include // for getopt() +#include // for getopt() #include // for getopt_long() #include "igd.h" #include "nondominated.h" #define CMDLINE_COPYRIGHT_YEARS "2016-2024" -#define CMDLINE_AUTHORS "Manuel Lopez-Ibanez \n" \ +#define CMDLINE_AUTHORS \ + "Manuel Lopez-Ibanez \n" \ "Leonardo C. T. Bezerra \n" #include "cmdline.h" @@ -66,8 +67,9 @@ static bool igdp = false; static bool igdplus = false; static bool hausdorff = false; -static const char *suffix = NULL; -static void usage(void) +static const char * suffix = NULL; +static void +usage(void) { printf("\n" "Usage:\n" @@ -75,53 +77,53 @@ static void usage(void) " %s [OPTIONS] < [INPUT] > [OUTPUT]\n\n", program_invocation_short_name, program_invocation_short_name); - printf( -"Calculates the inverted generational distance (IGD) measure for the Pareto sets given as input\n\n" - -"Options:\n" -OPTION_HELP_STR -OPTION_VERSION_STR -" -v, --verbose print some information (time, number of points, etc.) \n" -OPTION_QUIET_STR -" , --gd report classical GD\n" -" , --igd report classical IGD\n" -" , --gd-p report GD_p (p=1 by default)\n" -" , --igd-p (default) report IGD_p (p=1 by default)\n" -" , --igd-plus report IGD+\n" -" , --hausdorff report avg Hausdorff distance = max (GD_p, IGD_p)\n" -" -a, --all compute everything\n" -" -p, exponent that averages the distances\n" -" -r, --reference FILE file that contains the reference set \n" -OPTION_OBJ_STR -OPTION_MAXIMISE_STR -" -s, --suffix=STRING Create an output file for each input file by appending\n" -" this suffix. This is ignored when reading from stdin. \n" -" If missing, output is sent to stdout. \n" -"\n"); + printf("Calculates the inverted generational distance (IGD) measure for " + "the Pareto sets given as input\n\n" + + "Options:\n" OPTION_HELP_STR OPTION_VERSION_STR + " -v, --verbose print some information (time, number of " + "points, etc.) \n" OPTION_QUIET_STR + " , --gd report classical GD\n" + " , --igd report classical IGD\n" + " , --gd-p report GD_p (p=1 by default)\n" + " , --igd-p (default) report IGD_p (p=1 by default)\n" + " , --igd-plus report IGD+\n" + " , --hausdorff report avg Hausdorff distance = max (GD_p, " + "IGD_p)\n" + " -a, --all compute everything\n" + " -p, exponent that averages the distances\n" + " -r, --reference FILE file that contains the reference set " + " \n" OPTION_OBJ_STR OPTION_MAXIMISE_STR + " -s, --suffix=STRING Create an output file for each input file by " + "appending\n" + " this suffix. This is ignored when reading " + "from stdin. \n" + " If missing, output is sent to stdout. " + " \n" + "\n"); } static void -do_file (const char *filename, double *reference, size_t reference_size, - int *nobj_p, const signed char * minmax, bool maximise_all_flag) +do_file(const char * filename, double * reference, size_t reference_size, + int * nobj_p, const signed char * minmax, bool maximise_all_flag) { - double *data = NULL; - int *cumsizes = NULL; + double * data = NULL; + int * cumsizes = NULL; int nruns = 0; int nobj = *nobj_p; handle_read_data_error( - read_double_data (filename, &data, &nobj, &cumsizes, &nruns), filename); - if (!filename) - filename = stdin_name; + read_double_data(filename, &data, &nobj, &cumsizes, &nruns), filename); + if (!filename) filename = stdin_name; - char *outfilename = NULL; - FILE *outfile = stdout; + char * outfilename = NULL; + FILE * outfile = stdout; if (filename != stdin_name && suffix) { outfilename = m_strcat(filename, suffix); - outfile = fopen (outfilename, "w"); + outfile = fopen(outfilename, "w"); if (outfile == NULL) { - errprintf ("%s: %s\n", outfilename, strerror(errno)); - exit (EXIT_FAILURE); + errprintf("%s: %s\n", outfilename, strerror(errno)); + exit(EXIT_FAILURE); } } #if 0 @@ -133,7 +135,8 @@ do_file (const char *filename, double *reference, size_t reference_size, /* Default minmax if not set yet. */ bool free_minmax = false; if (minmax == NULL) { - minmax = maximise_all_flag ? minmax_maximise((dimension_t) nobj) : minmax_minimise((dimension_t) nobj); + minmax = maximise_all_flag ? minmax_maximise((dimension_t)nobj) + : minmax_minimise((dimension_t)nobj); free_minmax = true; } @@ -145,21 +148,21 @@ do_file (const char *filename, double *reference, size_t reference_size, use __VA_OPT__ in the future when more compilers support it: https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html */ #if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" #endif -#define print_value_if(IF, WHAT, ...) \ - do { \ - if (IF) { \ - fprintf(outfile, "%s" WHAT, sep, ## __VA_ARGS__); \ - sep = "\t"; \ - } \ - } while (0) +#define print_value_if(IF, WHAT, ...) \ + do { \ + if (IF) { \ + fprintf(outfile, "%s" WHAT, sep, ##__VA_ARGS__); \ + sep = "\t"; \ + } \ + } while (0) print_value_if(gd, "GD"); print_value_if(igd, "IGD"); print_value_if(gdp, "GD_%d", exponent_p); - print_value_if(igdp,"IGD_%d", exponent_p); + print_value_if(igdp, "IGD_%d", exponent_p); print_value_if(igdplus, "IGD+"); print_value_if(hausdorff, "avg_Hausdorff"); #undef print_value_if @@ -169,18 +172,19 @@ do_file (const char *filename, double *reference, size_t reference_size, for (int n = 0, cumsize = 0; n < nruns; cumsize = cumsizes[n], n++) { _attr_maybe_unused double time_elapsed = 0; int size_a = cumsizes[n] - cumsize; - const double *points_a = &data[nobj * cumsize]; + const double * points_a = &data[nobj * cumsize]; //Timer_start (); sep = "\0"; -#define print_value_if(IF, FUN, ...) \ - do { \ - if (IF) { \ - fprintf (outfile, "%s" indicator_printf_format, sep, \ - FUN(nobj, minmax, points_a, size_a, reference, (int) reference_size, ## __VA_ARGS__)); \ - sep = "\t"; \ - } \ - } while (0) +#define print_value_if(IF, FUN, ...) \ + do { \ + if (IF) { \ + fprintf(outfile, "%s" indicator_printf_format, sep, \ + FUN(nobj, minmax, points_a, size_a, reference, \ + (int)reference_size, ##__VA_ARGS__)); \ + sep = "\t"; \ + } \ + } while (0) print_value_if(gd, GD_minmax); print_value_if(igd, IGD_minmax); @@ -190,103 +194,109 @@ do_file (const char *filename, double *reference, size_t reference_size, print_value_if(hausdorff, avg_Hausdorff_dist_minmax, exponent_p); #undef print_value_if #if defined(__clang__) -# pragma clang diagnostic pop +# pragma clang diagnostic pop #endif //time_elapsed = Timer_elapsed_virtual (); fprintf(outfile, "\n"); /* if (verbose_flag) */ /* fprintf (outfile, "# Time: %f seconds\n", time_elapsed); */ - } if (outfilename) { if (verbose_flag) - fprintf (stderr, "# %s -> %s\n", filename, outfilename); - fclose (outfile); - free (outfilename); + fprintf(stderr, "# %s -> %s\n", filename, outfilename); + fclose(outfile); + free(outfilename); } - free (data); - free (cumsizes); - if (free_minmax) free( (void *) minmax); + free(data); + free(cumsizes); + if (free_minmax) free((void *)minmax); *nobj_p = nobj; } -int main(int argc, char *argv[]) +int +main(int argc, char * argv[]) { - double *reference = NULL; + double * reference = NULL; size_t reference_size = 0; - const signed char *minmax = NULL; + const signed char * minmax = NULL; bool maximise_all_flag = false; int nobj = 0, tmp_nobj = 0; - enum { GD_opt = 1000, - IGD_opt, GD_p_opt, IGD_p_opt, IGD_plus_opt, hausdorff_opt}; + enum { + GD_opt = 1000, + IGD_opt, + GD_p_opt, + IGD_p_opt, + IGD_plus_opt, + hausdorff_opt + }; /* see the man page for getopt_long for an explanation of these fields */ static const char short_options[] = "hVvqap:Mr:s:o:"; static const struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {"verbose", no_argument, NULL, 'v'}, - {"quiet", no_argument, NULL, 'q'}, - {"gd", no_argument, NULL, GD_opt}, - {"igd", no_argument, NULL, IGD_opt}, - {"gd-p", no_argument, NULL, GD_p_opt}, - {"igd-p", no_argument, NULL, IGD_p_opt}, - {"igd-plus", no_argument, NULL, IGD_plus_opt}, - {"hausdorff", no_argument, NULL, hausdorff_opt}, - {"all", no_argument, NULL, 'a'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {"verbose", no_argument, NULL, 'v'}, + {"quiet", no_argument, NULL, 'q'}, + {"gd", no_argument, NULL, GD_opt}, + {"igd", no_argument, NULL, IGD_opt}, + {"gd-p", no_argument, NULL, GD_p_opt}, + {"igd-p", no_argument, NULL, IGD_p_opt}, + {"igd-plus", no_argument, NULL, IGD_plus_opt}, + {"hausdorff", no_argument, NULL, hausdorff_opt}, + {"all", no_argument, NULL, 'a'}, {"exponent-p", required_argument, NULL, 'p'}, - {"maximise", no_argument, NULL, 'M'}, - {"maximize", no_argument, NULL, 'M'}, - {"reference", required_argument, NULL, 'r'}, - {"suffix", required_argument, NULL, 's'}, - {"obj", required_argument, NULL, 'o'}, + {"maximise", no_argument, NULL, 'M'}, + {"maximize", no_argument, NULL, 'M'}, + {"reference", required_argument, NULL, 'r'}, + {"suffix", required_argument, NULL, 's'}, + {"obj", required_argument, NULL, 'o'}, {NULL, 0, NULL, 0} /* marks end of list */ }; set_program_invocation_short_name(argv[0]); int opt; int longopt_index; - while (0 < (opt = getopt_long(argc, argv, short_options, - long_options, &longopt_index))) { + while (0 < (opt = getopt_long(argc, argv, short_options, long_options, + &longopt_index))) { switch (opt) { - case 'p': - // FIXME: Use strtol - exponent_p = atoi(optarg); - break; - - case 'a': // --all - gd = true; - igd = true; - gdp = true; - igdp = true; - igdplus = true; - hausdorff = true; - break; - - case GD_opt: - gd = true; - break; - - case IGD_opt: - igd = true; - break; - - case GD_p_opt: - gdp = true; - break; - - case IGD_p_opt: - igdp = true; - break; - - case IGD_plus_opt: - igdplus = true; - break; - - case hausdorff_opt: - hausdorff = true; - break; + case 'p': + // FIXME: Use strtol + exponent_p = atoi(optarg); + break; + + case 'a': // --all + gd = true; + igd = true; + gdp = true; + igdp = true; + igdplus = true; + hausdorff = true; + break; + + case GD_opt: + gd = true; + break; + + case IGD_opt: + igd = true; + break; + + case GD_p_opt: + gdp = true; + break; + + case IGD_p_opt: + igdp = true; + break; + + case IGD_plus_opt: + igdplus = true; + break; + + case hausdorff_opt: + hausdorff = true; + break; case 'M': // --maximise maximise_all_flag = true; @@ -299,13 +309,15 @@ int main(int argc, char *argv[]) case 'r': // --reference reference_size = read_reference_set(&reference, optarg, &tmp_nobj); if (reference == NULL || reference_size == 0) { - errprintf ("invalid reference set '%s", optarg); + errprintf("invalid reference set '%s", optarg); exit(EXIT_FAILURE); } if (nobj == 0) { nobj = tmp_nobj; } else if (tmp_nobj != nobj) { - errprintf ("number of objectives in --obj (%d) and reference set (%d) do not match", nobj, tmp_nobj); + errprintf("number of objectives in --obj (%d) and reference " + "set (%d) do not match", + nobj, tmp_nobj); exit(EXIT_FAILURE); } break; @@ -332,19 +344,23 @@ int main(int argc, char *argv[]) } if (reference == NULL) { - errprintf ("a reference set must be provided (--reference)"); + errprintf("a reference set must be provided (--reference)"); exit(EXIT_FAILURE); } if (minmax == NULL) { - minmax = maximise_all_flag ? minmax_maximise((dimension_t) nobj) : minmax_minimise((dimension_t) nobj); + minmax = maximise_all_flag ? minmax_maximise((dimension_t)nobj) + : minmax_minimise((dimension_t)nobj); } - reference_size = filter_dominated_set(reference, nobj, reference_size, minmax); + reference_size = + filter_dominated_set(reference, nobj, reference_size, minmax); int numfiles = argc - optind; - if (numfiles < 1) {/* Read stdin. */ - do_file (NULL, reference, reference_size, &nobj, minmax, maximise_all_flag); + if (numfiles < 1) { /* Read stdin. */ + do_file(NULL, reference, reference_size, &nobj, minmax, + maximise_all_flag); } else if (numfiles == 1) { - do_file (argv[optind], reference, reference_size, &nobj, minmax, maximise_all_flag); + do_file(argv[optind], reference, reference_size, &nobj, minmax, + maximise_all_flag); } else { /* FIXME: Calculate the nondominated front among all input files to use as reference set. */ @@ -368,10 +384,11 @@ int main(int argc, char *argv[]) } #endif for (int k = 0; k < numfiles; k++) - do_file (argv[optind + k], reference, reference_size, &nobj, minmax, maximise_all_flag); + do_file(argv[optind + k], reference, reference_size, &nobj, minmax, + maximise_all_flag); } free(reference); - free((void*)minmax); + free((void *)minmax); return EXIT_SUCCESS; } diff --git a/c/igd.h b/c/igd.h index 4e82fa4a..b296ba88 100644 --- a/c/igd.h +++ b/c/igd.h @@ -50,17 +50,17 @@ #include #include #ifndef INFINITY -#define INFINITY (HUGE_VAL) +# define INFINITY (HUGE_VAL) #endif #include #include "common.h" #include "pow_int.h" static inline double -gd_common (int dim, const signed char * restrict minmax, - const double * restrict points_a, int size_a, - const double * restrict points_r, int size_r, - bool plus, bool psize, uint_fast8_t p) +gd_common(int dim, const signed char * restrict minmax, + const double * restrict points_a, int size_a, + const double * restrict points_r, int size_r, bool plus, bool psize, + uint_fast8_t p) { if (size_a == 0) return INFINITY; ASSUME(size_a > 0); @@ -77,9 +77,10 @@ gd_common (int dim, const signed char * restrict minmax, if (minmax[d] == 0) continue; double a_d = points_a[a * dim + d]; double r_d = points_r[r * dim + d]; - double diff = (!plus) - ? (r_d - a_d) - : MAX((minmax[d] < 0) ? (r_d - a_d) : (a_d - r_d), 0.0); + double diff = + (!plus) + ? (r_d - a_d) + : MAX((minmax[d] < 0) ? (r_d - a_d) : (a_d - r_d), 0.0); // TODO: Implement taxicab and infinity norms dist += diff * diff; } @@ -90,128 +91,115 @@ gd_common (int dim, const signed char * restrict minmax, } // Here we calculate the actual Euclidean distance. if (p == 1) - min_dist = (double) sqrtl(min_dist); + min_dist = (double)sqrtl(min_dist); else if (p % 2 == 0) - min_dist = pow_uint(min_dist, p/2); + min_dist = pow_uint(min_dist, p / 2); else - min_dist = pow_uint((double) sqrtl(min_dist), p); + min_dist = pow_uint((double)sqrtl(min_dist), p); gd += min_dist; } if (p == 1) - return gd / (double) size_a; + return gd / (double)size_a; else if (psize) - return (double) powl(gd / (double) size_a, 1.0 / p); + return (double)powl(gd / (double)size_a, 1.0 / p); else - return (double) powl(gd, 1.0 / p) / (double) size_a; + return (double)powl(gd, 1.0 / p) / (double)size_a; } static inline double -GD_minmax (int dim, const signed char * restrict minmax, - const double * restrict points_a, int size_a, - const double * restrict points_r, int size_r) +GD_minmax(int dim, const signed char * restrict minmax, + const double * restrict points_a, int size_a, + const double * restrict points_r, int size_r) { - return gd_common (dim, minmax, - points_a, size_a, - points_r, size_r, - /*plus=*/false, /*psize=*/false, - /*p=*/(uint_fast8_t)1); + return gd_common(dim, minmax, points_a, size_a, points_r, size_r, + /*plus=*/false, /*psize=*/false, + /*p=*/(uint_fast8_t)1); } static inline double -IGD_minmax (int dim, const signed char * restrict minmax, - const double * restrict points_a, int size_a, - const double * restrict points_r, int size_r) +IGD_minmax(int dim, const signed char * restrict minmax, + const double * restrict points_a, int size_a, + const double * restrict points_r, int size_r) { - return gd_common (dim, minmax, - points_r, size_r, - points_a, size_a, - /*plus=*/false, /*psize=*/false, - /*p=*/(uint_fast8_t)1); + return gd_common(dim, minmax, points_r, size_r, points_a, size_a, + /*plus=*/false, /*psize=*/false, + /*p=*/(uint_fast8_t)1); } _attr_maybe_unused static double -IGD (const double * restrict data, int nobj, int npoints, - const double * restrict ref, int ref_size, - const bool * restrict maximise) +IGD(const double * restrict data, int nobj, int npoints, + const double * restrict ref, int ref_size, const bool * restrict maximise) { - const signed char *minmax = minmax_from_bool((dimension_t) nobj, maximise); - double value = IGD_minmax (nobj, minmax, data, npoints, ref, ref_size); - free ((void *)minmax); + const signed char * minmax = minmax_from_bool((dimension_t)nobj, maximise); + double value = IGD_minmax(nobj, minmax, data, npoints, ref, ref_size); + free((void *)minmax); return value; } static inline double -GD_p (int dim, const signed char * restrict minmax, - const double * restrict points_a, int size_a, - const double * restrict points_r, int size_r, unsigned int p) +GD_p(int dim, const signed char * restrict minmax, + const double * restrict points_a, int size_a, + const double * restrict points_r, int size_r, unsigned int p) { - return gd_common (dim, minmax, - points_a, size_a, - points_r, size_r, - /*plus=*/false, /*psize=*/true, (uint_fast8_t)p); + return gd_common(dim, minmax, points_a, size_a, points_r, size_r, + /*plus=*/false, /*psize=*/true, (uint_fast8_t)p); } static inline double -IGD_p (int dim, const signed char * restrict minmax, - const double * restrict points_a, int size_a, - const double * restrict points_r, int size_r, unsigned int p) +IGD_p(int dim, const signed char * restrict minmax, + const double * restrict points_a, int size_a, + const double * restrict points_r, int size_r, unsigned int p) { - return gd_common (dim, minmax, - points_r, size_r, - points_a, size_a, - /*plus=*/false, /*psize=*/true, (uint_fast8_t) p); + return gd_common(dim, minmax, points_r, size_r, points_a, size_a, + /*plus=*/false, /*psize=*/true, (uint_fast8_t)p); } static inline double -IGD_plus_minmax (int dim, const signed char * restrict minmax, - const double * restrict points_a, int size_a, - const double * restrict points_r, int size_r) +IGD_plus_minmax(int dim, const signed char * restrict minmax, + const double * restrict points_a, int size_a, + const double * restrict points_r, int size_r) { - return gd_common (dim, minmax, - points_r, size_r, - points_a, size_a, - /*plus=*/true, /*psize=*/true, /*p=*/(uint_fast8_t)1); + return gd_common(dim, minmax, points_r, size_r, points_a, size_a, + /*plus=*/true, /*psize=*/true, /*p=*/(uint_fast8_t)1); } _attr_maybe_unused static double -IGD_plus (const double * restrict data, int nobj, int npoints, const double * restrict ref, int ref_size, - const bool * restrict maximise) +IGD_plus(const double * restrict data, int nobj, int npoints, + const double * restrict ref, int ref_size, + const bool * restrict maximise) { - const signed char *minmax = minmax_from_bool((dimension_t) nobj, maximise); - double value = IGD_plus_minmax (nobj, minmax, data, npoints, ref, ref_size); - free ((void *)minmax); - return(value); + const signed char * minmax = minmax_from_bool((dimension_t)nobj, maximise); + double value = IGD_plus_minmax(nobj, minmax, data, npoints, ref, ref_size); + free((void *)minmax); + return (value); } static inline double -avg_Hausdorff_dist_minmax (int dim, const signed char * restrict minmax, - const double * restrict points_a, int size_a, - const double * restrict points_r, int size_r, - unsigned int p) +avg_Hausdorff_dist_minmax(int dim, const signed char * restrict minmax, + const double * restrict points_a, int size_a, + const double * restrict points_r, int size_r, + unsigned int p) { - double gd_p = gd_common (dim, minmax, - points_a, size_a, - points_r, size_r, - /*plus=*/false, /*psize=*/true, (uint_fast8_t)p); + double gd_p = gd_common(dim, minmax, points_a, size_a, points_r, size_r, + /*plus=*/false, /*psize=*/true, (uint_fast8_t)p); - double igd_p = gd_common (dim, minmax, - points_r, size_r, - points_a, size_a, - /*plus=*/false, /*psize=*/true, (uint_fast8_t)p); + double igd_p = gd_common(dim, minmax, points_r, size_r, points_a, size_a, + /*plus=*/false, /*psize=*/true, (uint_fast8_t)p); return MAX(gd_p, igd_p); } /* TODO: Implement p=INFINITY See [4] */ _attr_maybe_unused static double -avg_Hausdorff_dist (const double * restrict data, int nobj, int npoints, - const double * restrict ref, int ref_size, - const bool * restrict maximise, unsigned int p) +avg_Hausdorff_dist(const double * restrict data, int nobj, int npoints, + const double * restrict ref, int ref_size, + const bool * restrict maximise, unsigned int p) { - const signed char * minmax = minmax_from_bool((dimension_t) nobj, maximise); - double value = avg_Hausdorff_dist_minmax (nobj, minmax, data, npoints, ref, ref_size, p); - free ((void *)minmax); - return(value); + const signed char * minmax = minmax_from_bool((dimension_t)nobj, maximise); + double value = avg_Hausdorff_dist_minmax(nobj, minmax, data, npoints, ref, + ref_size, p); + free((void *)minmax); + return (value); } #endif /* IGD_H */ diff --git a/c/io.c b/c/io.c index 07896dcb..371a4cf1 100644 --- a/c/io.c +++ b/c/io.c @@ -33,7 +33,7 @@ #include "io.h" /* FIXME: Do we need to handle the following weird files? */ - /* +/* fscanf (instream, "%*[ \t]"); retval = fscanf (instream, "%1[\r\n]", newline); // We do not consider that '\r\n' starts a new set. @@ -48,46 +48,38 @@ skip_trailing_whitespace(FILE * instream) c = fgetc(instream); } while (c == ' ' || c == '\t' || unlikely(c == '\r')); - if (c == '\n') - return 1; - if (unlikely(c == EOF)) - return EOF; - ungetc(c, instream); // Push the non-whitespace character back + if (c == '\n') return 1; + if (unlikely(c == EOF)) return EOF; + ungetc(c, instream); // Push the non-whitespace character back return 0; } /* skip full lines starting with # */ static inline int -skip_comment_line(FILE *instream) +skip_comment_line(FILE * instream) { int c = skip_trailing_whitespace(instream); - if (c == 1) - return 1; - if (unlikely(c == EOF)) - return EOF; + if (c == 1) return 1; + if (unlikely(c == EOF)) return EOF; c = fgetc(instream); if (unlikely(c == '#')) { do { // Skip the rest of the line c = fgetc(instream); - if (c == '\n') - return 1; - if (unlikely(c == EOF)) - return EOF; + if (c == '\n') return 1; + if (unlikely(c == EOF)) return EOF; } while (true); } - if (c == '\n') - return 1; - if (unlikely(c == EOF)) - return EOF; + if (c == '\n') return 1; + if (unlikely(c == EOF)) return EOF; - ungetc(c, instream); // Not a comment, push back + ungetc(c, instream); // Not a comment, push back return 0; } int -fread_double(FILE *instream, double *number) +fread_double(FILE * instream, double * number) { int c; // Skip leading whitespace. @@ -95,35 +87,30 @@ fread_double(FILE *instream, double *number) c = fgetc(instream); } while (c == ' ' || c == '\t' || c == '\r'); - if (unlikely(c == EOF)) - return EOF; + if (unlikely(c == EOF)) return EOF; char buffer[128]; size_t i = 0; do { - buffer[i] = (char) c; + buffer[i] = (char)c; i++; c = fgetc(instream); - if (isspace(c) || unlikely(c == EOF)) - break; - if (unlikely(i == sizeof(buffer) - 1)) - return 0; // Number is too long. + if (isspace(c) || unlikely(c == EOF)) break; + if (unlikely(i == sizeof(buffer) - 1)) return 0; // Number is too long. } while (true); - if (c == '\n') - ungetc(c, instream); // Push back newlines + if (c == '\n') ungetc(c, instream); // Push back newlines buffer[i] = '\0'; - char *endptr; + char * endptr; *number = strtod(buffer, &endptr); - if (unlikely(endptr == buffer)) - return 0; // Invalid conversion + if (unlikely(endptr == buffer)) return 0; // Invalid conversion return 1; // Success ! } int -fread_int(FILE *instream, int *number) +fread_int(FILE * instream, int * number) { int c; // Skip leading whitespace. @@ -131,35 +118,29 @@ fread_int(FILE *instream, int *number) c = fgetc(instream); } while (c == ' ' || c == '\t' || c == '\r'); - if (c == EOF) - return EOF; + if (c == EOF) return EOF; char buffer[64]; size_t i = 0; do { - buffer[i] = (char) c; + buffer[i] = (char)c; i++; c = fgetc(instream); - if (isspace(c) || c == EOF) - break; - if (i == sizeof(buffer) - 1) - return 0; // Number is too long. + if (isspace(c) || c == EOF) break; + if (i == sizeof(buffer) - 1) return 0; // Number is too long. } while (true); - if (c == '\n') - ungetc(c, instream); // Push back newlines. + if (c == '\n') ungetc(c, instream); // Push back newlines. buffer[i] = '\0'; - char *endptr; + char * endptr; long value = strtol(buffer, &endptr, /*base=*/10); - if (endptr == buffer) - return 0; // Invalid conversion. + if (endptr == buffer) return 0; // Invalid conversion. - if (value < INT_MIN || value > INT_MAX) - return 0; // Out of range. + if (value < INT_MIN || value > INT_MAX) return 0; // Out of range. - *number = (int) value; + *number = (int)value; return 1; // Success ! } @@ -181,14 +162,14 @@ fread_int(FILE *instream, int *number) /* Convenience wrapper to read_double_data used by Python's moocore. */ int -read_datasets(const char * filename, double **data_p, int *ncols_p, int *datasize_p) +read_datasets(const char * filename, double ** data_p, int * ncols_p, + int * datasize_p) { double * data = NULL; int * cumsizes = NULL; int nsets = 0, nobjs = 0; int error = read_double_data(filename, &data, &nobjs, &cumsizes, &nsets); - if (unlikely(error)) - return error; + if (unlikely(error)) return error; int ncols = nobjs + 1; // For the column 'set' int nrows = cumsizes[nsets - 1]; @@ -200,10 +181,9 @@ read_datasets(const char * filename, double **data_p, int *ncols_p, int *datasiz for (int j = 0; j < nobjs; j++) { newdata[i * ncols + j] = data[i * nobjs + j]; } - newdata[i * ncols + nobjs] = (double) set; + newdata[i * ncols + nobjs] = (double)set; i++; - if (i == cumsizes[set - 1]) - set++; + if (i == cumsizes[set - 1]) set++; } free(data); free(cumsizes); @@ -216,66 +196,63 @@ read_datasets(const char * filename, double **data_p, int *ncols_p, int *datasiz #ifndef R_PACKAGE void -vector_fprintf (FILE *stream, const double * vector, int size) +vector_fprintf(FILE * stream, const double * vector, int size) { ASSUME(size > 0); - fprintf (stream, point_printf_format, vector[0]); + fprintf(stream, point_printf_format, vector[0]); for (int k = 1; k < size; k++) - fprintf (stream, point_printf_sep "" point_printf_format, vector[k]); + fprintf(stream, point_printf_sep "" point_printf_format, vector[k]); } void -vector_printf (const double *vector, int size) +vector_printf(const double * vector, int size) { - vector_fprintf (stdout, vector, size); + vector_fprintf(stdout, vector, size); } void -vector_int_fprintf (FILE *stream, const int * vector, int size) +vector_int_fprintf(FILE * stream, const int * vector, int size) { ASSUME(size > 0); - for (int k = 0; k < size; k++) - fprintf (stream, "%d ", vector[k]); + for (int k = 0; k < size; k++) fprintf(stream, "%d ", vector[k]); } void -vector_int_printf (const int *vector, int size) +vector_int_printf(const int * vector, int size) { - vector_int_fprintf (stdout, vector, size); + vector_int_fprintf(stdout, vector, size); } int -write_sets (FILE *outfile, const double *data, int ncols, - const int *cumsizes, int nruns) +write_sets(FILE * outfile, const double * data, int ncols, const int * cumsizes, + int nruns) { int size = 0; ASSUME(nruns > 0); for (int set = 0; set < nruns; set++) { ASSUME(cumsizes[set] >= 0); - if (set > 0) - fprintf (outfile, "\n"); + if (set > 0) fprintf(outfile, "\n"); for (; size < cumsizes[set]; size++) { - vector_fprintf (outfile, &data[ncols * size], ncols); - fprintf (outfile, "\n"); + vector_fprintf(outfile, &data[ncols * size], ncols); + fprintf(outfile, "\n"); } } return 0; } int -write_sets_filtered (FILE *outfile, const double *data, int ncols, - const int *cumsizes, int nruns, const bool *write_p) +write_sets_filtered(FILE * outfile, const double * data, int ncols, + const int * cumsizes, int nruns, const bool * write_p) { int size = 0; ASSUME(nruns > 0); for (int set = 0; set < nruns; set++) { ASSUME(cumsizes[set] >= 0); - if (set > 0) - fprintf (outfile, "\n"); + if (set > 0) fprintf(outfile, "\n"); for (; size < cumsizes[set]; size++) { if (write_p[size]) { - vector_fprintf (outfile, &data[ncols * size], ncols); - fprintf (outfile, "\n"); + vector_fprintf(outfile, &data[ncols * size], ncols); + fprintf(outfile, "\n"); } } } diff --git a/c/io.h b/c/io.h index 205c24ab..19533362 100644 --- a/c/io.h +++ b/c/io.h @@ -3,10 +3,10 @@ #include "config.h" #ifndef R_PACKAGE -#include -#include -#include -#include +# include +# include +# include +# include #endif #include "common.h" @@ -15,68 +15,67 @@ static const char stdin_name[] = ""; // Longest number is -1.23456789012345e-308 #define point_printf_format "%-22.15g" -#define point_printf_sep " " +#define point_printf_sep " " #define indicator_printf_format "%-22.15g" /* Error codes for read_data. */ -enum ERROR_READ_DATA { READ_INPUT_FILE_EMPTY = -1, - READ_INPUT_WRONG_INITIAL_DIM = -2, - ERROR_FOPEN = -3, - ERROR_CONVERSION = -4, - ERROR_COLUMNS = -5, +enum ERROR_READ_DATA { + READ_INPUT_FILE_EMPTY = -1, + READ_INPUT_WRONG_INITIAL_DIM = -2, + ERROR_FOPEN = -3, + ERROR_CONVERSION = -4, + ERROR_COLUMNS = -5, }; -int -read_int_data (const char *filename, int **data_p, - int *nobjs_p, int **cumsizes_p, int *nsets_p); -int -read_double_data (const char *filename, double **data_p, - int *nobjs_p, int **cumsizes_p, int *nsets_p); +int read_int_data(const char * filename, int ** data_p, int * nobjs_p, + int ** cumsizes_p, int * nsets_p); +int read_double_data(const char * filename, double ** data_p, int * nobjs_p, + int ** cumsizes_p, int * nsets_p); #ifndef R_PACKAGE -void vector_fprintf (FILE *stream, const double * vector, int size); -void vector_printf (const double *vector, int size); -void vector_int_fprintf (FILE *stream, const int * vector, int size); -void vector_int_printf (const int *vector, int size); -int read_datasets(const char * filename, double **data_p, int *ncols_p, int *datasize_p); -int write_sets (FILE *outfile, const double *data, int ncols, - const int *cumsizes, int nruns); -int write_sets_filtered (FILE *outfile, const double *data, int ncols, - const int *cumsizes, int nruns, - const bool *write_p); +void vector_fprintf(FILE * stream, const double * vector, int size); +void vector_printf(const double * vector, int size); +void vector_int_fprintf(FILE * stream, const int * vector, int size); +void vector_int_printf(const int * vector, int size); +int read_datasets(const char * filename, double ** data_p, int * ncols_p, + int * datasize_p); +int write_sets(FILE * outfile, const double * data, int ncols, + const int * cumsizes, int nruns); +int write_sets_filtered(FILE * outfile, const double * data, int ncols, + const int * cumsizes, int nruns, const bool * write_p); static inline const signed char * -read_minmax (const char *str, int *nobj_p) +read_minmax(const char * str, int * nobj_p) { - assert (str != NULL); + assert(str != NULL); size_t len = strlen(str); bool all_ignored = true; - size_t nobj = (size_t) *nobj_p; - signed char * minmax = malloc (sizeof(signed char) * MAX(len, nobj)); + size_t nobj = (size_t)*nobj_p; + signed char * minmax = malloc(sizeof(signed char) * MAX(len, nobj)); for (size_t i = 0; i < len; i++) { switch (str[i]) { - case '+': - minmax[i] = 1; - all_ignored = false; - break; - case '-': - minmax[i] = -1; - all_ignored = false; - break; - case '0': - case 'i': - minmax[i] = 0; - break; - default: /* something unexpected was found */ - return NULL; - break; + case '+': + minmax[i] = 1; + all_ignored = false; + break; + case '-': + minmax[i] = -1; + all_ignored = false; + break; + case '0': + case 'i': + minmax[i] = 0; + break; + default: /* something unexpected was found */ + return NULL; + break; } } if (all_ignored == true) { - warnprintf ("all objectives ignored because of --obj=%s\n", str); - exit (EXIT_SUCCESS); + warnprintf("all objectives ignored because of --obj=%s\n", str); + exit(EXIT_SUCCESS); } // FIXME: How to adjust minmax dynamically according to the number of objectives? if (len < nobj) { // Cycle @@ -84,30 +83,29 @@ read_minmax (const char *str, int *nobj_p) minmax[len + i] = minmax[i]; } } - *nobj_p = (int) len; + *nobj_p = (int)len; return minmax; } static inline const bool * -read_bitvector (const char *str, int *nobj_p) +read_bitvector(const char * str, int * nobj_p) { size_t nobj = *nobj_p; if (str == NULL) { /* Default all false. */ - assert (nobj > 0); - return (bool *) calloc(nobj, sizeof(bool)); + assert(nobj > 0); + return (bool *)calloc(nobj, sizeof(bool)); } - size_t len = strlen (str); + size_t len = strlen(str); for (size_t i = 0; i < len; i++) if (str[i] != '0' && str[i] != '1') /* something unexpected was found */ return NULL; - bool * vec = malloc (sizeof(bool) * len); - for (size_t i = 0; i < len; i++) - vec[i] = (str[i] == '1'); + bool * vec = malloc(sizeof(bool) * len); + for (size_t i = 0; i < len; i++) vec[i] = (str[i] == '1'); - *nobj_p = (int) len; + *nobj_p = (int)len; return vec; } diff --git a/c/io_priv.h b/c/io_priv.h index 55679030..a15073df 100644 --- a/c/io_priv.h +++ b/c/io_priv.h @@ -2,16 +2,16 @@ #include #include #include /* for strerror() */ -#include /* for errno */ +#include /* for errno */ #define objective_t_str MOOCORE_STRINGIFY_MACRO(objective_t) #ifndef fread_objective_t -#error "fread_objective_t is not defined" +# error "fread_objective_t is not defined" #endif /* allocate ~512kB at once, allowing for malloc overhead */ #ifndef IO_SLAB_SIZE -#define IO_SLAB_SIZE (512*1024 - 32) +# define IO_SLAB_SIZE (512 * 1024 - 32) #endif #define DATA_INC (IO_SLAB_SIZE / sizeof(objective_t)) #define CUMSIZE_INC (128) @@ -22,47 +22,46 @@ * nobjs : number of objectives, also the number of columns. */ int -read_objective_t_data (const char *filename, objective_t **data_p, - int *nobjs_p, int **cumsizes_p, int *nsets_p) +read_objective_t_data(const char * filename, objective_t ** data_p, + int * nobjs_p, int ** cumsizes_p, int * nsets_p) { - int nobjs = *nobjs_p; /* number of objectives (and columns). */ - int *cumsizes = *cumsizes_p; /* cumulative sizes of data sets. */ - int nsets = *nsets_p; /* number of data sets. */ - objective_t *data = *data_p; + int nobjs = *nobjs_p; /* number of objectives (and columns). */ + int * cumsizes = *cumsizes_p; /* cumulative sizes of data sets. */ + int nsets = *nsets_p; /* number of data sets. */ + objective_t * data = *data_p; - FILE *instream; + FILE * instream; if (filename == NULL) { instream = stdin; filename = stdin_name; /* used to diagnose errors. */ - } else if (unlikely(NULL == (instream = fopen (filename,"rb")))) { - errprintf ("%s: %s", filename, strerror (errno)); + } else if (unlikely(NULL == (instream = fopen(filename, "rb")))) { + errprintf("%s: %s", filename, strerror(errno)); return ERROR_FOPEN; } - size_t ntotal = 0; /* the current element of (*datap) */ + size_t ntotal = 0; /* the current element of (*datap) */ size_t sizessize = 0; size_t datasize = 0; if (nsets > 0) { - ntotal = (size_t) nobjs * cumsizes[nsets - 1]; + ntotal = (size_t)nobjs * cumsizes[nsets - 1]; assert(ntotal > 0); sizessize = nsets + CUMSIZE_INC; - datasize = ((ntotal - 1) / DATA_INC + 1) * DATA_INC; + datasize = ((ntotal - 1) / DATA_INC + 1) * DATA_INC; } /* If size is equal to zero, this is equivalent to free(). That is, reinitialize the data structures. */ - data = realloc (data, datasize * sizeof(objective_t)); - cumsizes = realloc (cumsizes, sizessize * sizeof(int)); + data = realloc(data, datasize * sizeof(objective_t)); + cumsizes = realloc(cumsizes, sizessize * sizeof(int)); /* skip over leading whitespace, comments and empty lines. */ - int retval; /* return value for fscanf */ - int column = 0, - line = 0; + int retval; /* return value for fscanf */ + int column = 0, line = 0; do { line++; /* skip full lines starting with # */ - retval = skip_comment_line (instream); + retval = skip_comment_line(instream); } while (retval == 1); int errorcode = 0; @@ -73,32 +72,33 @@ read_objective_t_data (const char *filename, objective_t **data_p, do { /* beginning of data set */ - if ((size_t) nsets == sizessize) { + if ((size_t)nsets == sizessize) { sizessize += CUMSIZE_INC; cumsizes = realloc(cumsizes, sizessize * sizeof(int)); } - cumsizes[nsets] = (nsets == 0) ? 0 : cumsizes[nsets - 1]; + cumsizes[nsets] = (nsets == 0) ? 0 : cumsizes[nsets - 1]; do { /* beginning of row */ - column = 0; + column = 0; - do { + do { /* new column */ column++; objective_t number; retval = fread_objective_t(instream, &number); if (unlikely(retval != 1)) { char buffer[64]; - if (fscanf (instream, "%60[^ \t\r\n]", buffer) != 1) { - errprintf ("%s: line %d column %d: " - "read error or unexpected end of file", - filename, line, column); + if (fscanf(instream, "%60[^ \t\r\n]", buffer) != 1) { + errprintf("%s: line %d column %d: " + "read error or unexpected end of file", + filename, line, column); } else { - errprintf ("%s: line %d column %d: " - "could not convert string `%s' to %s", - filename, line, column, buffer, objective_t_str); + errprintf("%s: line %d column %d: " + "could not convert string `%s' to %s", + filename, line, column, buffer, + objective_t_str); } errorcode = ERROR_CONVERSION; goto read_data_finish; @@ -106,56 +106,58 @@ read_objective_t_data (const char *filename, objective_t **data_p, if (ntotal == datasize) { datasize += DATA_INC; - data = realloc (data, datasize * sizeof(objective_t)); + data = realloc(data, datasize * sizeof(objective_t)); } data[ntotal] = number; ntotal++; - DEBUG2_PRINT("%s:%d:%d(%d) %d (set %d) = " point_printf_format "\n", - filename, line, column, nobjs, - cumsizes[nsets], nsets, (double) number); + DEBUG2_PRINT("%s:%d:%d(%d) %d (set %d) = " point_printf_format + "\n", + filename, line, column, nobjs, cumsizes[nsets], + nsets, (double)number); /* skip possible trailing whitespace */ retval = skip_trailing_whitespace(instream); - } while (retval == 0); + } while (retval == 0); - if (!nobjs) - nobjs = column; + if (!nobjs) + nobjs = column; else if (likely(column == nobjs)) ; /* OK */ - else if (unlikely(cumsizes[0] == 0)) { /* just finished first row. */ - errprintf ("%s: line %d: input has dimension %d" - " while previous data has dimension %d", - filename,line, column, nobjs); + else if (unlikely(cumsizes[0] == + 0)) { /* just finished first row. */ + errprintf("%s: line %d: input has dimension %d" + " while previous data has dimension %d", + filename, line, column, nobjs); errorcode = READ_INPUT_WRONG_INITIAL_DIM; goto read_data_finish; } else { - errprintf ("%s: line %d has different number of columns (%d)" - " from first row (%d)\n", - filename, line, column, nobjs); + errprintf("%s: line %d has different number of columns (%d)" + " from first row (%d)\n", + filename, line, column, nobjs); errorcode = ERROR_COLUMNS; goto read_data_finish; - } - cumsizes[nsets]++; + } + cumsizes[nsets]++; /* look for an empty line */ line++; - retval = skip_comment_line (instream); - } while (retval == 0); + retval = skip_comment_line(instream); + } while (retval == 0); - nsets++; /* new data set */ - DEBUG2_PRINT("%s: set %d, read %d rows\n", - filename, nsets, cumsizes[nsets - 1]); + nsets++; /* new data set */ + DEBUG2_PRINT("%s: set %d, read %d rows\n", filename, nsets, + cumsizes[nsets - 1]); /* skip over successive empty lines */ do { line++; - retval = skip_comment_line (instream); + retval = skip_comment_line(instream); } while (retval == 1); } while (retval != EOF); /* faster than !feof() */ /* adjust to real size (saves memory but probably slower). */ - data = realloc (data, ntotal * sizeof(objective_t)); - cumsizes = realloc (cumsizes, nsets * sizeof(int)); + data = realloc(data, ntotal * sizeof(objective_t)); + cumsizes = realloc(cumsizes, nsets * sizeof(int)); read_data_finish: @@ -164,8 +166,7 @@ read_objective_t_data (const char *filename, objective_t **data_p, *cumsizes_p = cumsizes; *data_p = data; - if (instream != stdin) - fclose(instream); + if (instream != stdin) fclose(instream); return errorcode; } diff --git a/c/libmoocore-config.h b/c/libmoocore-config.h index 22a9a495..7ad37a56 100644 --- a/c/libmoocore-config.h +++ b/c/libmoocore-config.h @@ -1,8 +1,9 @@ -#ifndef LIBMOOCORE_CONFIG_H_ -# define LIBMOOCORE_CONFIG_H_ +#ifndef LIBMOOCORE_CONFIG_H_ +#define LIBMOOCORE_CONFIG_H_ #ifndef R_PACKAGE -# if defined(_WIN32) && !(defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)) +# if defined(_WIN32) && \ + !(defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)) # ifndef MOOCORE_STATIC_LIB # ifdef MOOCORE_SHARED_LIB # define MOOCORE_API extern __declspec(dllexport) @@ -19,12 +20,12 @@ # define MOOCORE_API extern #endif -#ifdef __cplusplus +#ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else # define BEGIN_C_DECLS // empty -# define END_C_DECLS // empty +# define END_C_DECLS // empty #endif #endif // ! LIBMOOCORE_CONFIG_H_ diff --git a/c/libutil.c b/c/libutil.c index e6490d4e..0c27dd97 100644 --- a/c/libutil.c +++ b/c/libutil.c @@ -5,7 +5,8 @@ // FIXME: Avoid duplication with cmdline.c #ifndef R_PACKAGE -void fatal_error(const char *format,...) +void +fatal_error(const char * format, ...) { va_list ap; va_start(ap, format); @@ -14,21 +15,23 @@ void fatal_error(const char *format,...) exit(EXIT_FAILURE); } -void errprintf(const char *format,...) +void +errprintf(const char * format, ...) { va_list ap; fprintf(stderr, "error: "); - va_start(ap,format); + va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); fprintf(stderr, "\n"); } -void warnprintf(const char *format,...) +void +warnprintf(const char * format, ...) { va_list ap; fprintf(stderr, "warning: "); - va_start(ap,format); + va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); fprintf(stderr, "\n"); diff --git a/c/main-hv.c b/c/main-hv.c index 3fa48a4c..f51dc4da 100644 --- a/c/main-hv.c +++ b/c/main-hv.c @@ -34,13 +34,14 @@ #include #include #include -#include // for getopt() +#include // for getopt() #include // for getopt_long() #include "hv.h" #include "timer.h" #define CMDLINE_COPYRIGHT_YEARS "2010-2023" -#define CMDLINE_AUTHORS "Carlos M. Fonseca \n" \ +#define CMDLINE_AUTHORS \ + "Carlos M. Fonseca \n" \ "Manuel Lopez-Ibanez \n" \ "Luis Paquete \n" #include "cmdline.h" @@ -48,34 +49,46 @@ static int verbose_flag = 1; static bool union_flag = false; static bool contributions_flag = false; -static char *suffix = NULL; +static char * suffix = NULL; -static void usage(void) +static void +usage(void) { printf("\n" - "Usage: %s [OPTIONS] [FILE...]\n\n", program_invocation_short_name); - - printf( -"Calculate the hypervolume of each input set of each FILE. \n" -"With no FILE, or when FILE is -, read standard input.\n\n" - -"Options:\n" -OPTION_HELP_STR -OPTION_VERSION_STR -" -v, --verbose print some information (time, maximum, etc). \n" -" -q, --quiet print just the hypervolume (as opposed to --verbose). \n" -" -u, --union treat all input sets within a FILE as a single set. \n" -" -r, --reference=POINT use POINT as reference point. POINT must be within \n" -" quotes, e.g., \"10 10 10\". If no reference point is \n" -" given, it is taken as max + 0.1 * (max - min) for each\n" -" coordinate from the union of all input points. \n" -" -c, --contributions print the exclusive contribution of each input point; \n" -" weakly dominated points have zero contribution and do \n" -" not change the contribution of nondominated points. \n" -" -s, --suffix=STRING Create an output file for each input file by appending\n" -" this suffix. This is ignored when reading from stdin. \n" -" If missing, output is sent to stdout. \n" -"\n"); + "Usage: %s [OPTIONS] [FILE...]\n\n", + program_invocation_short_name); + + printf("Calculate the hypervolume of each input set of each FILE. \n" + "With no FILE, or when FILE is -, read standard input.\n\n" + + "Options:\n" OPTION_HELP_STR OPTION_VERSION_STR + " -v, --verbose print some information (time, maximum, etc). " + " \n" + " -q, --quiet print just the hypervolume (as opposed to " + "--verbose). \n" + " -u, --union treat all input sets within a FILE as a " + "single set. \n" + " -r, --reference=POINT use POINT as reference point. POINT must be " + "within \n" + " quotes, e.g., \"10 10 10\". If no reference " + "point is \n" + " given, it is taken as max + 0.1 * (max - min) " + "for each\n" + " coordinate from the union of all input " + "points. \n" + " -c, --contributions print the exclusive contribution of each " + "input point; \n" + " weakly dominated points have zero " + "contribution and do \n" + " not change the contribution of nondominated " + "points. \n" + " -s, --suffix=STRING Create an output file for each input file by " + "appending\n" + " this suffix. This is ignored when reading " + "from stdin. \n" + " If missing, output is sent to stdout. " + " \n" + "\n"); } static void @@ -100,29 +113,28 @@ fprint_hvc(FILE * outfile, const double * hvc, size_t n) */ static void -hv_file (const char *filename, double *reference, - double *maximum, double *minimum, int *nobj_p) +hv_file(const char * filename, double * reference, double * maximum, + double * minimum, int * nobj_p) { - double *data = NULL; - int *cumsizes = NULL; + double * data = NULL; + int * cumsizes = NULL; int cumsize; int nruns = 0; int n; int nobj = *nobj_p; - char *outfilename = NULL; - FILE *outfile = stdout; + char * outfilename = NULL; + FILE * outfile = stdout; handle_read_data_error( - read_double_data (filename, &data, &nobj, &cumsizes, &nruns), filename); - if (!filename) - filename = stdin_name; + read_double_data(filename, &data, &nobj, &cumsizes, &nruns), filename); + if (!filename) filename = stdin_name; if (filename != stdin_name && suffix) { outfilename = m_strcat(filename, suffix); - outfile = fopen (outfilename, "w"); + outfile = fopen(outfilename, "w"); if (outfile == NULL) { - errprintf ("%s: %s\n", outfilename, strerror(errno)); - exit (EXIT_FAILURE); + errprintf("%s: %s\n", outfilename, strerror(errno)); + exit(EXIT_FAILURE); } } @@ -131,28 +143,27 @@ hv_file (const char *filename, double *reference, nruns = 1; } - if (verbose_flag >= 2) - printf("# file: %s\n", filename); + if (verbose_flag >= 2) printf("# file: %s\n", filename); bool needs_minimum = (minimum == NULL); if (needs_minimum) { - data_bounds (&minimum, &maximum, data, nobj, cumsizes[nruns-1]); + data_bounds(&minimum, &maximum, data, nobj, cumsizes[nruns - 1]); if (verbose_flag >= 2) { - printf ("# minimum: "); - vector_printf (minimum, nobj); - printf ("\n"); - printf ("# maximum: "); - vector_printf (maximum, nobj); - printf ("\n"); + printf("# minimum: "); + vector_printf(minimum, nobj); + printf("\n"); + printf("# maximum: "); + vector_printf(maximum, nobj); + printf("\n"); } } if (reference != NULL) { for (n = 0; n < nobj; n++) { if (reference[n] <= maximum[n]) { - warnprintf ("%s: some points do not strictly dominate " - "the reference point and they will be discarded", - filename); + warnprintf("%s: some points do not strictly dominate " + "the reference point and they will be discarded", + filename); break; } } @@ -171,14 +182,14 @@ hv_file (const char *filename, double *reference, } if (verbose_flag >= 2) { - printf ("# reference: "); - vector_printf (reference, nobj); - printf ("\n"); + printf("# reference: "); + vector_printf(reference, nobj); + printf("\n"); } double * hvc = NULL; for (n = 0, cumsize = 0; n < nruns; cumsize = cumsizes[n], n++) { - Timer_start (); + Timer_start(); double volume, time_elapsed; if (contributions_flag) { hvc = realloc(hvc, (cumsizes[n] - cumsize) * sizeof(*hvc)); @@ -186,99 +197,102 @@ hv_file (const char *filename, double *reference, cumsizes[n] - cumsize, reference, /*ignore_dominated=*/true); } else { - volume = fpli_hv(&data[nobj * cumsize], nobj, cumsizes[n] - cumsize, reference); + volume = fpli_hv(&data[nobj * cumsize], nobj, cumsizes[n] - cumsize, + reference); } if (volume == 0.0) { - errprintf ("none of the points strictly dominates the reference point\n"); - exit (EXIT_FAILURE); + errprintf( + "none of the points strictly dominates the reference point\n"); + exit(EXIT_FAILURE); } time_elapsed = Timer_elapsed_virtual(); if (contributions_flag) { fprint_hvc(outfile, hvc, cumsizes[n] - cumsize); } else { - fprintf (outfile, indicator_printf_format "\n", volume); + fprintf(outfile, indicator_printf_format "\n", volume); } if (verbose_flag >= 2) - fprintf (outfile, "# Time: %f seconds\n", time_elapsed); + fprintf(outfile, "# Time: %f seconds\n", time_elapsed); } - if (contributions_flag) - free(hvc); + if (contributions_flag) free(hvc); free(data); free(cumsizes); if (outfilename) { if (verbose_flag) - fprintf (stderr, "# %s -> %s\n", filename, outfilename); - fclose (outfile); - free (outfilename); + fprintf(stderr, "# %s -> %s\n", filename, outfilename); + fclose(outfile); + free(outfilename); } *nobj_p = nobj; } -int main(int argc, char *argv[]) +int +main(int argc, char * argv[]) { /* See the man page for getopt_long for an explanation of these fields. */ static const char short_options[] = "hVvqucr:s:S"; static const struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {"verbose", no_argument, NULL, 'v'}, - {"quiet", no_argument, NULL, 'q'}, - {"reference", required_argument, NULL, 'r'}, - {"union", no_argument, NULL, 'u'}, - {"contributions", no_argument, NULL, 'c'}, - {"suffix", required_argument, NULL, 's'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {"verbose", no_argument, NULL, 'v'}, + {"quiet", no_argument, NULL, 'q'}, + {"reference", required_argument, NULL, 'r'}, + {"union", no_argument, NULL, 'u'}, + {"contributions", no_argument, NULL, 'c'}, + {"suffix", required_argument, NULL, 's'}, {NULL, 0, NULL, 0} /* marks end of list */ }; set_program_invocation_short_name(argv[0]); - double *reference = NULL; + double * reference = NULL; int nobj = 0; int opt; /* it's actually going to hold a char. */ int longopt_index; - while (0 < (opt = getopt_long (argc, argv, short_options, - long_options, &longopt_index))) { + while (0 < (opt = getopt_long(argc, argv, short_options, long_options, + &longopt_index))) { switch (opt) { - case 'r': // --reference - reference = robust_read_point(optarg, &nobj, "invalid reference point '%s'"); - break; + case 'r': // --reference + reference = robust_read_point(optarg, &nobj, + "invalid reference point '%s'"); + break; - case 'u': // --union - union_flag = true; - break; + case 'u': // --union + union_flag = true; + break; - case 'c': // --contributions - contributions_flag = true; - break; + case 'c': // --contributions + contributions_flag = true; + break; - case 's': // --suffix - suffix = optarg; - break; + case 's': // --suffix + suffix = optarg; + break; - case 'q': // --quiet - verbose_flag = 0; - break; + case 'q': // --quiet + verbose_flag = 0; + break; - case 'v': // --verbose - verbose_flag = 2; - break; + case 'v': // --verbose + verbose_flag = 2; + break; - default: - default_cmdline_handler(opt); + default: + default_cmdline_handler(opt); } } int numfiles = argc - optind; if (numfiles < 1) /* Read stdin. */ - hv_file (NULL, reference, NULL, NULL, &nobj); + hv_file(NULL, reference, NULL, NULL, &nobj); else if (numfiles == 1) { - hv_file (argv[optind], reference, NULL, NULL, &nobj); + hv_file(argv[optind], reference, NULL, NULL, &nobj); } else { int k; - double *maximum = NULL; - double *minimum = NULL; + double * maximum = NULL; + double * minimum = NULL; if (reference == NULL) { /* Calculate the maximum among all input files to use as reference point. */ @@ -286,16 +300,16 @@ int main(int argc, char *argv[]) file_bounds(argv[optind + k], &maximum, &minimum, &nobj); if (verbose_flag >= 2) { - printf ("# maximum:"); - vector_printf (maximum, nobj); - printf ("\n"); - printf ("# minimum:"); - vector_printf (minimum, nobj); - printf ("\n"); + printf("# maximum:"); + vector_printf(maximum, nobj); + printf("\n"); + printf("# minimum:"); + vector_printf(minimum, nobj); + printf("\n"); } } for (k = 0; k < numfiles; k++) - hv_file (argv[optind + k], reference, maximum, minimum, &nobj); + hv_file(argv[optind + k], reference, maximum, minimum, &nobj); free(minimum); free(maximum); diff --git a/c/main-hvapprox.c b/c/main-hvapprox.c index d00da0f6..117163d6 100644 --- a/c/main-hvapprox.c +++ b/c/main-hvapprox.c @@ -22,53 +22,68 @@ #include #include #include -#include // for getopt() -#include // for getopt_long() -#include // time() -#include // LONG_MAX +#include // for getopt() +#include // for getopt_long() +#include // time() +#include // LONG_MAX #include // PRIu32 #include "hvapprox.h" #include "timer.h" #define CMDLINE_COPYRIGHT_YEARS "2025" -#define CMDLINE_AUTHORS "Manuel Lopez-Ibanez \n" +#define CMDLINE_AUTHORS \ + "Manuel Lopez-Ibanez \n" #include "cmdline.h" static int verbose_flag = 1; static bool union_flag = false; -static char *suffix = NULL; +static char * suffix = NULL; -enum approx_method_t { DZ2019_MC=1, DZ2019_HW=2 }; +enum approx_method_t { DZ2019_MC = 1, DZ2019_HW = 2 }; -static void usage(void) +static void +usage(void) { printf("\n" - "Usage: %s [OPTIONS] [FILE...]\n\n", program_invocation_short_name); + "Usage: %s [OPTIONS] [FILE...]\n\n", + program_invocation_short_name); printf( -"Approximate the hypervolume value of each input set of each FILE. \n" -"The approximation uses Monte-Carlo sampling, thus gets more accurate with larger\n" -"values of --nsamples. With no FILE, or when FILE is -, read standard input.\n\n" - -"Options:\n" -OPTION_HELP_STR -OPTION_VERSION_STR -" -v, --verbose print some information (time, maximum, etc). \n" -" -q, --quiet print just the hypervolume (as opposed to --verbose). \n" -" -u, --union treat all input sets within a FILE as a single set. \n" -" -r, --reference=POINT use POINT as reference point. POINT must be within \n" -" quotes, e.g., \"10 10 10\". If no reference point is \n" -" given, it is taken as max + 0.1 * (max - min) for each\n" -" coordinate from the union of all input points. \n" -" -s, --suffix=STRING Create an output file for each input file by appending\n" -" this suffix. This is ignored when reading from stdin. \n" -" If missing, output is sent to stdout. \n" -" -n, --nsamples=N Number of Monte-Carlo samples (N is a positive integer).\n" -" -m, --method=M 1: Monte-Carlo sampling using normal distribution; \n" -" 2: Hua-Wang deterministic sampling (default). \n" -OPTION_SEED_STR -" Only method=1. \n" -"\n"); + "Approximate the hypervolume value of each input set of each FILE. \n" + "The approximation uses Monte-Carlo sampling, thus gets more accurate " + "with larger\n" + "values of --nsamples. With no FILE, or when FILE is -, read standard " + "input.\n\n" + + "Options:\n" OPTION_HELP_STR OPTION_VERSION_STR + " -v, --verbose print some information (time, maximum, etc). " + " \n" + " -q, --quiet print just the hypervolume (as opposed to " + "--verbose). \n" + " -u, --union treat all input sets within a FILE as a single " + "set. \n" + " -r, --reference=POINT use POINT as reference point. POINT must be " + "within \n" + " quotes, e.g., \"10 10 10\". If no reference " + "point is \n" + " given, it is taken as max + 0.1 * (max - min) " + "for each\n" + " coordinate from the union of all input points. " + " \n" + " -s, --suffix=STRING Create an output file for each input file by " + "appending\n" + " this suffix. This is ignored when reading from " + "stdin. \n" + " If missing, output is sent to stdout. " + " \n" + " -n, --nsamples=N Number of Monte-Carlo samples (N is a positive " + "integer).\n" + " -m, --method=M 1: Monte-Carlo sampling using normal " + "distribution; \n" + " 2: Hua-Wang deterministic sampling (default). " + " \n" OPTION_SEED_STR " Only method=1. " + " \n" + "\n"); } /* @@ -86,30 +101,29 @@ OPTION_SEED_STR // FIXME: There is a similar function in main-hv.c static void -hvapprox_file (const char *filename, double *reference, - double *maximum, double *minimum, int *nobj_p, - uint_fast32_t nsamples, enum approx_method_t hv_approx_method, uint32_t seed) +hvapprox_file(const char * filename, double * reference, double * maximum, + double * minimum, int * nobj_p, uint_fast32_t nsamples, + enum approx_method_t hv_approx_method, uint32_t seed) { - double *data = NULL; - int *cumsizes = NULL; + double * data = NULL; + int * cumsizes = NULL; int cumsize; int nruns = 0; int n; int nobj = *nobj_p; - char *outfilename = NULL; - FILE *outfile = stdout; + char * outfilename = NULL; + FILE * outfile = stdout; handle_read_data_error( - read_double_data (filename, &data, &nobj, &cumsizes, &nruns), filename); - if (!filename) - filename = stdin_name; + read_double_data(filename, &data, &nobj, &cumsizes, &nruns), filename); + if (!filename) filename = stdin_name; if (filename != stdin_name && suffix) { outfilename = m_strcat(filename, suffix); - outfile = fopen (outfilename, "w"); + outfile = fopen(outfilename, "w"); if (outfile == NULL) { - errprintf ("%s: %s\n", outfilename, strerror(errno)); - exit (EXIT_FAILURE); + errprintf("%s: %s\n", outfilename, strerror(errno)); + exit(EXIT_FAILURE); } } @@ -118,28 +132,27 @@ hvapprox_file (const char *filename, double *reference, nruns = 1; } - if (verbose_flag >= 2) - printf("# file: %s\n", filename); + if (verbose_flag >= 2) printf("# file: %s\n", filename); bool needs_minimum = (minimum == NULL); if (needs_minimum) { - data_bounds (&minimum, &maximum, data, nobj, cumsizes[nruns-1]); + data_bounds(&minimum, &maximum, data, nobj, cumsizes[nruns - 1]); if (verbose_flag >= 2) { - printf ("# minimum: "); - vector_printf (minimum, nobj); - printf ("\n"); - printf ("# maximum: "); - vector_printf (maximum, nobj); - printf ("\n"); + printf("# minimum: "); + vector_printf(minimum, nobj); + printf("\n"); + printf("# maximum: "); + vector_printf(maximum, nobj); + printf("\n"); } } if (reference != NULL) { for (n = 0; n < nobj; n++) { if (reference[n] <= maximum[n]) { - warnprintf ("%s: some points do not strictly dominate " - "the reference point and they will be discarded", - filename); + warnprintf("%s: some points do not strictly dominate " + "the reference point and they will be discarded", + filename); break; } } @@ -153,76 +166,82 @@ hvapprox_file (const char *filename, double *reference, } if (verbose_flag >= 2) { - printf ("# reference: "); - vector_printf (reference, nobj); - printf ("\n"); + printf("# reference: "); + vector_printf(reference, nobj); + printf("\n"); } // Minimise everything by default. - const bool * maximise = new_bool_maximise((dimension_t) nobj, false); + const bool * maximise = new_bool_maximise((dimension_t)nobj, false); for (n = 0, cumsize = 0; n < nruns; cumsize = cumsizes[n], n++) { - Timer_start (); + Timer_start(); double volume; switch (hv_approx_method) { - case DZ2019_MC: - volume = hv_approx_normal(&data[nobj * cumsize], nobj, cumsizes[n] - cumsize, reference, maximise, nsamples, seed); - break; - case DZ2019_HW: - volume = hv_approx_hua_wang(&data[nobj * cumsize], nobj, cumsizes[n] - cumsize, reference, maximise, nsamples); - break; - default: - unreachable(); + case DZ2019_MC: + volume = hv_approx_normal(&data[nobj * cumsize], nobj, + cumsizes[n] - cumsize, reference, + maximise, nsamples, seed); + break; + case DZ2019_HW: + volume = hv_approx_hua_wang(&data[nobj * cumsize], nobj, + cumsizes[n] - cumsize, reference, + maximise, nsamples); + break; + default: + unreachable(); } if (volume == 0.0) { - fatal_error("none of the points strictly dominates the reference point\n"); + fatal_error( + "none of the points strictly dominates the reference point\n"); } - double time_elapsed = Timer_elapsed_virtual (); + double time_elapsed = Timer_elapsed_virtual(); - fprintf (outfile, indicator_printf_format "\n", volume); + fprintf(outfile, indicator_printf_format "\n", volume); if (verbose_flag >= 2) - fprintf (outfile, "# Time: %f seconds\n", time_elapsed); + fprintf(outfile, "# Time: %f seconds\n", time_elapsed); } if (outfilename) { if (verbose_flag) - fprintf (stderr, "# %s -> %s\n", filename, outfilename); - fclose (outfile); - free (outfilename); + fprintf(stderr, "# %s -> %s\n", filename, outfilename); + fclose(outfile); + free(outfilename); } - free ((void *) maximise); - free (data); - free (cumsizes); + free((void *)maximise); + free(data); + free(cumsizes); if (needs_minimum) { - free (minimum); - free (maximum); + free(minimum); + free(maximum); } *nobj_p = nobj; } -int main(int argc, char *argv[]) +int +main(int argc, char * argv[]) { /* See the man page for getopt_long for an explanation of these fields. */ static const char short_options[] = "hVvqur:s:n:m:S:"; static const struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {"verbose", no_argument, NULL, 'v'}, - {"quiet", no_argument, NULL, 'q'}, - {"reference", required_argument, NULL, 'r'}, - {"union", no_argument, NULL, 'u'}, - {"suffix", required_argument, NULL, 's'}, - {"method", required_argument, NULL, 'm'}, - {"nsamples", required_argument, NULL, 'n'}, - {"seed", required_argument, NULL, 'S'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {"verbose", no_argument, NULL, 'v'}, + {"quiet", no_argument, NULL, 'q'}, + {"reference", required_argument, NULL, 'r'}, + {"union", no_argument, NULL, 'u'}, + {"suffix", required_argument, NULL, 's'}, + {"method", required_argument, NULL, 'm'}, + {"nsamples", required_argument, NULL, 'n'}, + {"seed", required_argument, NULL, 'S'}, {NULL, 0, NULL, 0} /* marks end of list */ }; set_program_invocation_short_name(argv[0]); - double *reference = NULL; + double * reference = NULL; int nobj = 0; uint32_t seed = 0; uint_fast32_t nsamples = 0; @@ -230,51 +249,60 @@ int main(int argc, char *argv[]) int opt; /* it's actually going to hold a char. */ int longopt_index; - while (0 < (opt = getopt_long (argc, argv, short_options, - long_options, &longopt_index))) { + while (0 < (opt = getopt_long(argc, argv, short_options, long_options, + &longopt_index))) { switch (opt) { - case 'r': // --reference - reference = robust_read_point(optarg, &nobj, "invalid reference point '%s'"); - break; - - case 'u': // --union - union_flag = true; - break; - - case 's': // --suffix - suffix = optarg; - break; - - case 'n': { // --nsamples - char *endp; - long int value = strtol(optarg, &endp, 10); - if (endp == optarg || *endp != '\0' || value <= 0 || value == LONG_MAX) { - fatal_error("value of --nsamples must be a positive integer '%s'", optarg); - } - nsamples = (uint_fast32_t) value; - break; - } - - case 'm': // --method - switch (*optarg) { - case '1': - hv_approx_method = DZ2019_MC; break; - case '2': - hv_approx_method = DZ2019_HW; break; - default: - fatal_error("valid values of --method (-m) are: 1 or 2, not '%s'", optarg); - } - break; - - case 'S': {// --seed - char *endp; - long int value = strtol(optarg, &endp, 10); - if (endp == optarg || *endp != '\0' || value <= 0) { - fatal_error("value of --seed must be a positive integer '%s'", optarg); - } - seed = (uint32_t) value; - break; - } + case 'r': // --reference + reference = robust_read_point(optarg, &nobj, + "invalid reference point '%s'"); + break; + + case 'u': // --union + union_flag = true; + break; + + case 's': // --suffix + suffix = optarg; + break; + + case 'n': { // --nsamples + char * endp; + long int value = strtol(optarg, &endp, 10); + if (endp == optarg || *endp != '\0' || value <= 0 || + value == LONG_MAX) { + fatal_error( + "value of --nsamples must be a positive integer '%s'", + optarg); + } + nsamples = (uint_fast32_t)value; + break; + } + + case 'm': // --method + switch (*optarg) { + case '1': + hv_approx_method = DZ2019_MC; + break; + case '2': + hv_approx_method = DZ2019_HW; + break; + default: + fatal_error( + "valid values of --method (-m) are: 1 or 2, not '%s'", + optarg); + } + break; + + case 'S': { // --seed + char * endp; + long int value = strtol(optarg, &endp, 10); + if (endp == optarg || *endp != '\0' || value <= 0) { + fatal_error("value of --seed must be a positive integer '%s'", + optarg); + } + seed = (uint32_t)value; + break; + } case 'q': // --quiet verbose_flag = 0; break; @@ -289,29 +317,32 @@ int main(int argc, char *argv[]) } if (nsamples == 0) { - fatal_error("must specify a value for --nsamples, for example, --nsamples 100000"); + fatal_error("must specify a value for --nsamples, for example, " + "--nsamples 100000"); } if (seed == 0) { - if (hv_approx_method == DZ2019_MC) - seed = (uint32_t) time(NULL); + if (hv_approx_method == DZ2019_MC) seed = (uint32_t)time(NULL); } else if (hv_approx_method == DZ2019_HW) { fatal_error("cannot use --seed with --method=2"); } if (verbose_flag >= 2) - printf("# seed: %"PRIu32 "\n# nsamples: %lu\n", seed, (unsigned long) nsamples); + printf("# seed: %" PRIu32 "\n# nsamples: %lu\n", seed, + (unsigned long)nsamples); int numfiles = argc - optind; if (numfiles < 1) /* Read stdin. */ - hvapprox_file(NULL, reference, NULL, NULL, &nobj, nsamples, hv_approx_method, seed); + hvapprox_file(NULL, reference, NULL, NULL, &nobj, nsamples, + hv_approx_method, seed); else if (numfiles == 1) { - hvapprox_file (argv[optind], reference, NULL, NULL, &nobj, nsamples, hv_approx_method, seed); + hvapprox_file(argv[optind], reference, NULL, NULL, &nobj, nsamples, + hv_approx_method, seed); } else { int k; - double *maximum = NULL; - double *minimum = NULL; + double * maximum = NULL; + double * minimum = NULL; if (reference == NULL) { /* Calculate the maximum among all input files to use as reference point. */ @@ -319,16 +350,17 @@ int main(int argc, char *argv[]) file_bounds(argv[optind + k], &maximum, &minimum, &nobj); if (verbose_flag >= 2) { - printf ("# maximum:"); - vector_printf (maximum, nobj); - printf ("\n"); - printf ("# minimum:"); - vector_printf (minimum, nobj); - printf ("\n"); + printf("# maximum:"); + vector_printf(maximum, nobj); + printf("\n"); + printf("# minimum:"); + vector_printf(minimum, nobj); + printf("\n"); } } for (k = 0; k < numfiles; k++) - hvapprox_file (argv[optind + k], reference, maximum, minimum, &nobj, nsamples, hv_approx_method, seed); + hvapprox_file(argv[optind + k], reference, maximum, minimum, &nobj, + nsamples, hv_approx_method, seed); free(minimum); free(maximum); diff --git a/c/ndsort.c b/c/ndsort.c index f29f6315..965e08eb 100644 --- a/c/ndsort.c +++ b/c/ndsort.c @@ -31,9 +31,9 @@ #include #include -#include // for getopt() +#include // for getopt() #include // for getopt_long() -#include // for INFINITY +#include // for INFINITY #include "common.h" #include "hv.h" @@ -42,57 +42,57 @@ #define READ_INPUT_WRONG_INITIAL_DIM_ERRSTR "-o, --obj" #include "cmdline.h" -static void usage(void) +static void +usage(void) { printf("\n" - "Usage: %s [OPTIONS] [FILE...]\n\n", program_invocation_short_name); + "Usage: %s [OPTIONS] [FILE...]\n\n", + program_invocation_short_name); printf( -"Perform nondominated sorting in a list of points. \n\n" - -"Options:\n" -OPTION_HELP_STR -OPTION_VERSION_STR -" -v, --verbose print some information (time, number of points, etc.) \n" -OPTION_QUIET_STR -//" -H, --hypervolume use hypervolume contribution to break ties \n" -" -k, --keep-uevs keep uniquely extreme values \n" -" -r, --rank don't break ties using hypervolume contribution \n" -OPTION_OBJ_STR -"\n"); + "Perform nondominated sorting in a list of points. " + " \n\n" + + "Options:\n" OPTION_HELP_STR OPTION_VERSION_STR + " -v, --verbose print some information (time, number of points, " + "etc.) \n" OPTION_QUIET_STR + //" -H, --hypervolume use hypervolume contribution to break ties \n" + " -k, --keep-uevs keep uniquely extreme values " + " \n" + " -r, --rank don't break ties using hypervolume contribution " + " \n" OPTION_OBJ_STR "\n"); } static bool verbose_flag = false; static void -fprint_rank (FILE * stream, const int * rank, int size) +fprint_rank(FILE * stream, const int * rank, int size) { int k; for (k = 0; k < size; k++) { - fprintf (stream, "%d\n", rank[k]); + fprintf(stream, "%d\n", rank[k]); } } -static void fprint_vector_double (FILE * stream, const double * vec, int size) +static void +fprint_vector_double(FILE * stream, const double * vec, int size) { - for (int k = 0; k < size; k++) - fprintf (stream, "%g\n", vec[k]); + for (int k = 0; k < size; k++) fprintf(stream, "%g\n", vec[k]); } static bool * -calculate_uev (bool *uev, const double *points, int dim, int size, - const double *lbound, const double *ubound) +calculate_uev(bool * uev, const double * points, int dim, int size, + const double * lbound, const double * ubound) { if (uev == NULL) { - uev = malloc (sizeof(bool) * size); + uev = malloc(sizeof(bool) * size); } - for (int j = 0; j < size; j++) - uev[j] = false; + for (int j = 0; j < size; j++) uev[j] = false; for (int i = 0; i < dim; i++) { - assert (ubound[i] > -INFINITY); - assert (lbound[i] < INFINITY); + assert(ubound[i] > -INFINITY); + assert(lbound[i] < INFINITY); for (int j = 0; j < size; j++) { if (points[j * dim + i] == ubound[i]) { uev[j] = true; @@ -109,29 +109,30 @@ calculate_uev (bool *uev, const double *points, int dim, int size, return uev; } -int main(int argc, char *argv[]) +int +main(int argc, char * argv[]) { int nsets = 0; - int *cumsizes = NULL; - double *points = NULL; + int * cumsizes = NULL; + double * points = NULL; int dim = 0; - const char *filename; - const signed char *minmax = NULL; + const char * filename; + const signed char * minmax = NULL; bool only_rank_flag = false; -// bool hypervolume_flag = false; -// bool keep_uevs_flag = false; + // bool hypervolume_flag = false; + // bool keep_uevs_flag = false; /* see the man page for getopt_long for an explanation of these fields */ static const char short_options[] = "hVvqkro:"; static const struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {"verbose", no_argument, NULL, 'v'}, - {"quiet", no_argument, NULL, 'q'}, -// {"hypervolume",no_argument, NULL, 'H'}, - {"keep-uevs", no_argument, NULL, 'k'}, - {"rank", no_argument, NULL, 'r'}, - {"obj", required_argument, NULL, 'o'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {"verbose", no_argument, NULL, 'v'}, + {"quiet", no_argument, NULL, 'q'}, + // {"hypervolume",no_argument, NULL, 'H'}, + {"keep-uevs", no_argument, NULL, 'k'}, + {"rank", no_argument, NULL, 'r'}, + {"obj", required_argument, NULL, 'o'}, {NULL, 0, NULL, 0} /* marks end of list */ }; @@ -139,8 +140,8 @@ int main(int argc, char *argv[]) int opt; /* it's actually going to hold a char */ int longopt_index; - while (0 < (opt = getopt_long(argc, argv, short_options, - long_options, &longopt_index))) { + while (0 < (opt = getopt_long(argc, argv, short_options, long_options, + &longopt_index))) { switch (opt) { case 'q': // --quiet verbose_flag = false; @@ -155,8 +156,9 @@ int main(int argc, char *argv[]) break; case 'k': // --keep-uevs -// keep_uevs_flag = true; - fprintf(stderr, "%s: --keep-uevs not implemented yet!\n",program_invocation_short_name); + // keep_uevs_flag = true; + fprintf(stderr, "%s: --keep-uevs not implemented yet!\n", + program_invocation_short_name); exit(EXIT_FAILURE); break; @@ -171,58 +173,54 @@ int main(int argc, char *argv[]) int numfiles = argc - optind; - if (numfiles <= 0) {/* No input files: read stdin. */ + if (numfiles <= 0) { /* No input files: read stdin. */ filename = NULL; } else if (numfiles == 1) { filename = argv[optind]; } else { - errprintf ("more than one input file not handled yet."); + errprintf("more than one input file not handled yet."); exit(EXIT_FAILURE); } /* FIXME: Instead of this strange call, create a wrapper read_data_robust. */ handle_read_data_error( - read_double_data (filename, &points, &dim, &cumsizes, &nsets), - filename); - if (!filename) - filename = stdin_name; + read_double_data(filename, &points, &dim, &cumsizes, &nsets), filename); + if (!filename) filename = stdin_name; const int size = cumsizes[0] = cumsizes[nsets - 1]; nsets = 1; /* Default minmax if not set yet. */ - if (minmax == NULL) - minmax = minmax_minimise((dimension_t) dim); + if (minmax == NULL) minmax = minmax_minimise((dimension_t)dim); if (verbose_flag) { - printf ("# file: %s\n", filename); - printf ("# points: %d\n", size); + printf("# file: %s\n", filename); + printf("# points: %d\n", size); } - int * rank = pareto_rank (points, dim, size); + int * rank = pareto_rank(points, dim, size); if (only_rank_flag) { - fprint_rank (stdout, rank, size); + fprint_rank(stdout, rank, size); } else { - bool *uev = NULL; + bool * uev = NULL; static const double upper_range = 0.9; static const double lower_range = 0.0; - double * order = malloc (sizeof(double) * size); + double * order = malloc(sizeof(double) * size); int max_rank = 0; for (int k = 0; k < size; k++) { if (rank[k] > max_rank) max_rank = rank[k]; order[k] = rank[k]; } - double * data = malloc (sizeof(double) * size * dim); + double * data = malloc(sizeof(double) * size * dim); double * lbound = malloc(sizeof(double) * dim); double * ubound = malloc(sizeof(double) * dim); double * ref = malloc(sizeof(double) * dim); - for (int d = 0; d < dim; d++) - ref[d] = 1.0; + for (int d = 0; d < dim; d++) ref[d] = 1.0; max_rank = 1; for (int i = 1; i <= max_rank; i++) { @@ -233,8 +231,8 @@ int main(int argc, char *argv[]) int data_size = 0; for (int k = 0; k < size; k++) { if (rank[k] != i) continue; - const double *src = points + k * dim; - memcpy (data + data_size * dim, src, sizeof(double) * dim); + const double * src = points + k * dim; + memcpy(data + data_size * dim, src, sizeof(double) * dim); data_size++; for (int d = 0; d < dim; d++) { if (lbound[d] > src[d]) lbound[d] = src[d]; @@ -242,32 +240,32 @@ int main(int argc, char *argv[]) } } - uev = calculate_uev (uev, data, dim, data_size, lbound, ubound); + uev = calculate_uev(uev, data, dim, data_size, lbound, ubound); - normalise (data, dim, data_size, minmax, AGREE_NONE, - lower_range, upper_range, - lbound, ubound); + normalise(data, dim, data_size, minmax, AGREE_NONE, lower_range, + upper_range, lbound, ubound); - double *hvc = malloc(sizeof(double) * data_size); - hv_contributions(hvc, data, dim, data_size, ref, /*ignore_dominated=*/true); + double * hvc = malloc(sizeof(double) * data_size); + hv_contributions(hvc, data, dim, data_size, ref, + /*ignore_dominated=*/true); /* FIXME: handle uevs: keep_uevs_flag ? uev : NULL);*/ for (int k = 0, j = 0; k < size; k++) { if (rank[k] != i) continue; order[k] += (1 - hvc[j++]); } - free (hvc); + free(hvc); } - free (data); - free (lbound); - free (ubound); - free (ref); - fprint_vector_double (stdout, order, size); - free (order); + free(data); + free(lbound); + free(ubound); + free(ref); + fprint_vector_double(stdout, order, size); + free(order); } - free (rank); - free (cumsizes); - free (points); - free ((void *) minmax); + free(rank); + free(cumsizes); + free(points); + free((void *)minmax); return 0; } diff --git a/c/nondominated.c b/c/nondominated.c index cf171e24..f57a2e9e 100644 --- a/c/nondominated.c +++ b/c/nondominated.c @@ -34,13 +34,14 @@ #include #include // for isspace() #include -#include // for getopt() +#include // for getopt() #include // for getopt_long() -#include // for log10() +#include // for log10() #include "nondominated.h" -#define READ_INPUT_WRONG_INITIAL_DIM_ERRSTR "either -o, --obj, -u, --upper or -l, --lower" +#define READ_INPUT_WRONG_INITIAL_DIM_ERRSTR \ + "either -o, --obj, -u, --upper or -l, --lower" #include "cmdline.h" @@ -50,9 +51,10 @@ static bool check_flag = true; static bool filter_flag = false; static bool normalise_flag = false; static bool force_bounds_flag = false; -static const char *suffix = "_dat"; +static const char * suffix = "_dat"; -static void usage(void) +static void +usage(void) { printf("\n" "Usage:\n" @@ -60,51 +62,65 @@ static void usage(void) " %s [OPTIONS] < [INPUT] > [OUTPUT]\n\n", program_invocation_short_name, program_invocation_short_name); - printf( -"Obtain information and perform some operations on the nondominated sets " -"given as input. \n\n" - -"Options:\n" -OPTION_HELP_STR -OPTION_VERSION_STR -" -v, --verbose print some extra information; \n" -OPTION_QUIET_STR -OPTION_NOCHECK_STR -OPTION_OBJ_STR -OPTION_MAXIMISE_STR -" -u, --upper-bound POINT defines an upper bound to check, e.g. \"10 5 30\";\n" -" -l, --lower-bound POINT defines a lower bound to check;\n" -" -U, --union consider each file as a whole approximation set, \n" -" (by default, approximation sets are separated by an \n" -" empty line within a file); \n" -" -s, --suffix=STRING suffix to add to output files. Default is \"%s\". \n" -" The empty string means overwrite the input file. \n" -" This is ignored when reading from stdin because output\n" -" is sent to stdout. \n" -"\n" -" The following options OVERWRITE output files:\n" -" -a, --agree= transform objectives so all are maximised (or \n" -" minimised). See also the option --obj. \n" -" -f, --filter check and filter out dominated points; \n" -" -b, --force-bound remove points that do not satisfy the bounds; \n" -" -n, --normalise RANGE normalise all objectives to a range, e.g., \"1 2\". \n" -" If bounds are given with -l and -u, they are used \n" -" for the normalisation. \n" -" -L, --log=[1|0]... specify whether each objective should be transformed \n" -" to logarithmic scale (1) or not (0). \n" -"\n", suffix); + printf("Obtain information and perform some operations on the nondominated " + "sets " + "given as input. \n\n" + + "Options:\n" OPTION_HELP_STR OPTION_VERSION_STR + " -v, --verbose print some extra information; " + " \n" OPTION_QUIET_STR OPTION_NOCHECK_STR + OPTION_OBJ_STR OPTION_MAXIMISE_STR + " -u, --upper-bound POINT defines an upper bound to check, e.g. " + "\"10 5 30\";\n" + " -l, --lower-bound POINT defines a lower bound to check;\n" + " -U, --union consider each file as a whole approximation " + "set, \n" + " (by default, approximation sets are separated " + "by an \n" + " empty line within a file); " + " \n" + " -s, --suffix=STRING suffix to add to output files. Default is " + "\"%s\". \n" + " The empty string means overwrite the input " + "file. \n" + " This is ignored when reading from stdin " + "because output\n" + " is sent to stdout. " + " \n" + "\n" + " The following options OVERWRITE output files:\n" + " -a, --agree= transform objectives so all are maximised " + "(or \n" + " minimised). See also the option --obj. " + " \n" + " -f, --filter check and filter out dominated points; " + " \n" + " -b, --force-bound remove points that do not satisfy the bounds; " + " \n" + " -n, --normalise RANGE normalise all objectives to a range, e.g., " + "\"1 2\". \n" + " If bounds are given with -l and -u, they " + "are used \n" + " for the normalisation. " + " \n" + " -L, --log=[1|0]... specify whether each objective should be " + "transformed \n" + " to logarithmic scale (1) or not (0). " + " \n" + "\n", + suffix); } static bool -read_range (char *str, double *lower, double *upper) +read_range(char * str, double * lower, double * upper) { - char *endp; + char * endp; - *lower = strtod (str, &endp); + *lower = strtod(str, &endp); if (str == endp) return false; str = endp; - *upper = strtod (str, &endp); + *upper = strtod(str, &endp); if (str == endp) return false; str = endp; @@ -118,22 +134,20 @@ read_range (char *str, double *lower, double *upper) } static inline bool -any_less_than (const double *a, const double *b, int nobj) +any_less_than(const double * a, const double * b, int nobj) { for (int d = 0; d < nobj; d++) - if (a[d] < b[d]) - return true; + if (a[d] < b[d]) return true; return false; } static void -logarithm_scale (double *points, int nobj, int size, - const bool *logarithm) +logarithm_scale(double * points, int nobj, int size, const bool * logarithm) { int k, d; - assert (logarithm); + assert(logarithm); for (d = 0; d < nobj; d++) { if (!logarithm[d]) continue; @@ -143,16 +157,16 @@ logarithm_scale (double *points, int nobj, int size, } static bool -force_bounds (double *points, int nobj, int *cumsizes, int nsets, - const double *lbound, const double *ubound) +force_bounds(double * points, int nobj, int * cumsizes, int nsets, + const double * lbound, const double * ubound) { int n, n2, k; int size = cumsizes[nsets - 1]; - bool *outbounds = malloc (sizeof(bool) * size); + bool * outbounds = malloc(sizeof(bool) * size); int outbounds_found = -1; for (n = size - 1; n >= 0; n--) { - if (any_less_than (&points[n * nobj], lbound, nobj) - || any_less_than (ubound, &points[n * nobj], nobj)) { + if (any_less_than(&points[n * nobj], lbound, nobj) || + any_less_than(ubound, &points[n * nobj], nobj)) { outbounds[n] = true; outbounds_found = n; } else @@ -160,16 +174,14 @@ force_bounds (double *points, int nobj, int *cumsizes, int nsets, } if (outbounds_found < 0) { - if (verbose_flag >= 2) - fprintf (stderr, "# out of bounds: 0\n"); - free (outbounds); + if (verbose_flag >= 2) fprintf(stderr, "# out of bounds: 0\n"); + free(outbounds); return false; } - int *ssizes = malloc (sizeof(int) * nsets); + int * ssizes = malloc(sizeof(int) * nsets); ssizes[0] = cumsizes[0]; - for (k = 1; k < nsets; k++) - ssizes[k] = cumsizes[k] - cumsizes[k-1]; + for (k = 1; k < nsets; k++) ssizes[k] = cumsizes[k] - cumsizes[k - 1]; /* Find the set of the first out-of-bounds point. */ for (k = 0; outbounds_found >= cumsizes[k]; k++); @@ -181,73 +193,69 @@ force_bounds (double *points, int nobj, int *cumsizes, int nsets, for (n = outbounds_found, n2 = outbounds_found + 1; k < nsets; k++) { while (n2 < cumsizes[k]) { if (outbounds[n2]) { - n2++; ssizes[k]--; + n2++; + ssizes[k]--; } else { - memcpy (&points[n * nobj], &points[n2 * nobj], - sizeof(double) * nobj); + memcpy(&points[n * nobj], &points[n2 * nobj], + sizeof(double) * nobj); n++, n2++; } } } - if (verbose_flag >= 2) - fprintf (stderr, "# out of bounds: %d\n", n2 - n); + if (verbose_flag >= 2) fprintf(stderr, "# out of bounds: %d\n", n2 - n); cumsizes[0] = ssizes[0]; - for (k = 1; k < nsets; k++) - cumsizes[k] = ssizes[k] + cumsizes[k-1]; + for (k = 1; k < nsets; k++) cumsizes[k] = ssizes[k] + cumsizes[k - 1]; - free (ssizes); - free (outbounds); + free(ssizes); + free(outbounds); return true; } static bool -check_nondominated (const char * filename, const double *points, - int nobj, const int *cumsizes, int nruns, - const signed char *minmax, const signed char agree, - bool **nondom_p) +check_nondominated(const char * filename, const double * points, int nobj, + const int * cumsizes, int nruns, const signed char * minmax, + const signed char agree, bool ** nondom_p) { - bool *nondom = nondom_p ? *nondom_p : NULL; + bool * nondom = nondom_p ? *nondom_p : NULL; bool free_nondom = false; if (nondom == NULL) { free_nondom = true; - nondom = nondom_init (cumsizes[nruns - 1]); + nondom = nondom_init(cumsizes[nruns - 1]); } bool first_time = true; bool dominated_found = false; - int filename_len = (int) MAX(strlen(filename), strlen("filename")); + int filename_len = (int)MAX(strlen(filename), strlen("filename")); for (int n = 0, cumsize = 0; n < nruns; cumsize = cumsizes[n], n++) { size_t old_size = cumsizes[n] - cumsize; - size_t new_size - = find_nondominated_set_agree (&points[nobj * cumsize], nobj, - old_size, minmax, agree, - &nondom[cumsize]); + size_t new_size = + find_nondominated_set_agree(&points[nobj * cumsize], nobj, old_size, + minmax, agree, &nondom[cumsize]); if (verbose_flag >= 2) { if (first_time) { - fprintf (stderr, "# %*s\tset\tsize\tnondom\tdom\n", - filename_len - 2, "filename"); + fprintf(stderr, "# %*s\tset\tsize\tnondom\tdom\n", + filename_len - 2, "filename"); first_time = false; } - fprintf (stderr, "%-*s\t%d\t%zu\t%zu\t%zd\n", - filename_len, filename, n+1, old_size, new_size, old_size - new_size); + fprintf(stderr, "%-*s\t%d\t%zu\t%zu\t%zd\n", filename_len, filename, + n + 1, old_size, new_size, old_size - new_size); } else if (verbose_flag && new_size < old_size) { if (first_time) { - fprintf (stderr, "%-*s\tset\tdom\n", filename_len, "filename"); + fprintf(stderr, "%-*s\tset\tdom\n", filename_len, "filename"); first_time = false; } - fprintf (stderr, "%-*s\t%d\t%zd dominated\n", - filename_len, filename, n+1, old_size - new_size); + fprintf(stderr, "%-*s\t%d\t%zd dominated\n", filename_len, filename, + n + 1, old_size - new_size); } if (new_size < old_size) { dominated_found = true; - } - else if (new_size > old_size) {/* This can't happen. */ - fatal_error ("%s:%d: a bug happened: new_size > old_size!\n", - __FILE__, __LINE__); + } else if (new_size > old_size) { /* This can't happen. */ + fatal_error("%s:%d: a bug happened: new_size > old_size!\n", + __FILE__, __LINE__); } } @@ -260,94 +268,89 @@ check_nondominated (const char * filename, const double *points, } static void -print_file_info (FILE *stream, const char *filename, - int nobj, const signed char *minmax) +print_file_info(FILE * stream, const char * filename, int nobj, + const signed char * minmax) { /* Print some info about input files. */ - fprintf (stream, "# file: %s\n", filename); - fprintf (stream, "# objectives (%d): ", nobj); + fprintf(stream, "# file: %s\n", filename); + fprintf(stream, "# objectives (%d): ", nobj); for (int n = 0; n < nobj; n++) { - fprintf (stream, "%c", (minmax[n] < 0) ? '-' - : ((minmax[n] > 0) ? '+' : 'i')); + fprintf(stream, "%c", + (minmax[n] < 0) ? '-' : ((minmax[n] > 0) ? '+' : 'i')); } - fprintf (stream, "\n"); + fprintf(stream, "\n"); } static void -print_output_header (FILE *stream, const char *filename, - int nobj, const signed char *minmax, - signed char agree, - double lrange, double urange, - const double *lbound, const double *ubound, - const bool *logarithm) +print_output_header(FILE * stream, const char * filename, int nobj, + const signed char * minmax, signed char agree, + double lrange, double urange, const double * lbound, + const double * ubound, const bool * logarithm) { - print_file_info (stream, filename, nobj, minmax); - fprintf (stream, "# agree: %s\n", (agree < 0) ? "min" - : ((agree > 0) ? "max" : "no")); + print_file_info(stream, filename, nobj, minmax); + fprintf(stream, "# agree: %s\n", + (agree < 0) ? "min" : ((agree > 0) ? "max" : "no")); if (logarithm) { - fprintf (stream, "# logarithm: "); + fprintf(stream, "# logarithm: "); for (int n = 0; n < nobj; n++) { - fprintf (stream, "%c", logarithm[n] ? '1' : '0'); + fprintf(stream, "%c", logarithm[n] ? '1' : '0'); } - fprintf (stream, "\n"); + fprintf(stream, "\n"); } if (normalise_flag) - fprintf (stream, "# range: " - point_printf_format " " point_printf_format - "\n", lrange, urange); - - fprintf (stream, "# lower bound: "); - vector_fprintf (stream, lbound, nobj); - fprintf (stream, "\n"); - fprintf (stream, "# upper bound: "); - vector_fprintf (stream, ubound, nobj); - fprintf (stream, "\n"); + fprintf(stream, + "# range: " point_printf_format " " point_printf_format "\n", + lrange, urange); + + fprintf(stream, "# lower bound: "); + vector_fprintf(stream, lbound, nobj); + fprintf(stream, "\n"); + fprintf(stream, "# upper bound: "); + vector_fprintf(stream, ubound, nobj); + fprintf(stream, "\n"); } static void -print_input_info (FILE *stream, const char *filename, - int nobj, const int *cumsizes, int nruns, - const signed char *minmax, - const double *minimum, const double *maximum) +print_input_info(FILE * stream, const char * filename, int nobj, + const int * cumsizes, int nruns, const signed char * minmax, + const double * minimum, const double * maximum) { - print_file_info (stream, filename, nobj, minmax); - fprintf (stream, "# sets: %d\n", nruns); - fprintf (stream, "# sizes: %d", cumsizes[0]); + print_file_info(stream, filename, nobj, minmax); + fprintf(stream, "# sets: %d\n", nruns); + fprintf(stream, "# sizes: %d", cumsizes[0]); for (int n = 1; n < nruns; n++) - fprintf (stream, ", %d", cumsizes[n] - cumsizes[n - 1]); - fprintf (stream, "\n# points: %d\n", cumsizes[nruns - 1]); - fprintf (stream, "# minimum: "); - vector_fprintf (stream, minimum, nobj); - fprintf (stream, "\n# maximum: "); - vector_fprintf (stream, maximum, nobj); - fprintf (stream, "\n"); + fprintf(stream, ", %d", cumsizes[n] - cumsizes[n - 1]); + fprintf(stream, "\n# points: %d\n", cumsizes[nruns - 1]); + fprintf(stream, "# minimum: "); + vector_fprintf(stream, minimum, nobj); + fprintf(stream, "\n# maximum: "); + vector_fprintf(stream, maximum, nobj); + fprintf(stream, "\n"); } static bool -process_file (const char *filename, - const signed char *minmax, int *nobj_p, signed char agree, - double lrange, double urange, - double *lbound, double *ubound, - double **minimum_p, double **maximum_p, - bool check_minimum, bool check_maximum, bool maximise_all_flag, - const bool *logarithm) +process_file(const char * filename, const signed char * minmax, int * nobj_p, + signed char agree, double lrange, double urange, double * lbound, + double * ubound, double ** minimum_p, double ** maximum_p, + bool check_minimum, bool check_maximum, bool maximise_all_flag, + const bool * logarithm) { - bool *nondom = NULL; + bool * nondom = NULL; bool logarithm_flag = false; - double *points = NULL; + double * points = NULL; int nobj = *nobj_p; - int *cumsizes = NULL; + int * cumsizes = NULL; int nsets = 0; handle_read_data_error( - read_double_data (filename, &points, &nobj, &cumsizes, &nsets), filename); + read_double_data(filename, &points, &nobj, &cumsizes, &nsets), + filename); ASSUME(nobj > 1 && nobj < 128); - if (!filename) - filename = stdin_name; + if (!filename) filename = stdin_name; if (union_flag) { cumsizes[0] = cumsizes[nsets - 1]; @@ -357,51 +360,52 @@ process_file (const char *filename, /* Default minmax if not set yet. */ bool free_minmax = false; if (minmax == NULL) { - minmax = maximise_all_flag ? minmax_maximise((dimension_t)nobj) : minmax_minimise((dimension_t)nobj); + minmax = maximise_all_flag ? minmax_maximise((dimension_t)nobj) + : minmax_minimise((dimension_t)nobj); free_minmax = true; } - double *minimum = NULL; - double *maximum = NULL; + double * minimum = NULL; + double * maximum = NULL; data_bounds(&minimum, &maximum, points, nobj, cumsizes[nsets - 1]); if (verbose_flag >= 2) - print_input_info (stderr, filename, nobj, cumsizes, nsets, minmax, - minimum, maximum); + print_input_info(stderr, filename, nobj, cumsizes, nsets, minmax, + minimum, maximum); if (lbound == NULL) lbound = minimum; - else if (check_minimum && !force_bounds_flag - && any_less_than (minimum, lbound, nobj)) { - errprintf ("%s: found vector smaller than lower bound:", filename); - vector_fprintf (stderr, minimum, nobj); - fprintf (stderr, "\n"); - exit (EXIT_FAILURE); + else if (check_minimum && !force_bounds_flag && + any_less_than(minimum, lbound, nobj)) { + errprintf("%s: found vector smaller than lower bound:", filename); + vector_fprintf(stderr, minimum, nobj); + fprintf(stderr, "\n"); + exit(EXIT_FAILURE); } if (ubound == NULL) ubound = maximum; - else if (check_maximum && !force_bounds_flag - && any_less_than (ubound, maximum, nobj)) { - errprintf ("%s: found vector larger than upper bound:", filename); - vector_fprintf (stderr, maximum, nobj); - fprintf (stderr, "\n"); - exit (EXIT_FAILURE); + else if (check_maximum && !force_bounds_flag && + any_less_than(ubound, maximum, nobj)) { + errprintf("%s: found vector larger than upper bound:", filename); + vector_fprintf(stderr, maximum, nobj); + fprintf(stderr, "\n"); + exit(EXIT_FAILURE); } if (force_bounds_flag) { - force_bounds (points, nobj, cumsizes, nsets, lbound, ubound); + force_bounds(points, nobj, cumsizes, nsets, lbound, ubound); } - double *log_lbound = NULL; - double *log_ubound = NULL; + double * log_lbound = NULL; + double * log_ubound = NULL; if (logarithm) { log_lbound = malloc(sizeof(double) * nobj); log_ubound = malloc(sizeof(double) * nobj); - memcpy (log_lbound, lbound, sizeof(double) * nobj); - memcpy (log_ubound, ubound, sizeof(double) * nobj); + memcpy(log_lbound, lbound, sizeof(double) * nobj); + memcpy(log_ubound, ubound, sizeof(double) * nobj); for (int d = 0; d < nobj; d++) { if (!logarithm[d]) continue; @@ -413,116 +417,115 @@ process_file (const char *filename, if (logarithm_flag) { lbound = log_lbound; ubound = log_ubound; - logarithm_scale (points, nobj, cumsizes[nsets - 1], logarithm); + logarithm_scale(points, nobj, cumsizes[nsets - 1], logarithm); } } if (agree) - agree_objectives (points, nobj, cumsizes[nsets - 1], minmax, agree); + agree_objectives(points, nobj, cumsizes[nsets - 1], minmax, agree); if (normalise_flag) - normalise (points, nobj, cumsizes[nsets - 1], minmax, agree, - lrange, urange, lbound, ubound); + normalise(points, nobj, cumsizes[nsets - 1], minmax, agree, lrange, + urange, lbound, ubound); bool dominated_found = false; /* Check sets. */ if (check_flag || filter_flag) dominated_found = - check_nondominated (filename, points, nobj, cumsizes, nsets, - minmax, agree, filter_flag ? &nondom : NULL); + check_nondominated(filename, points, nobj, cumsizes, nsets, minmax, + agree, filter_flag ? &nondom : NULL); if (verbose_flag >= 2) - fprintf (stderr, "# nondominated: %s\n", - dominated_found ? "FALSE" : "TRUE"); + fprintf(stderr, "# nondominated: %s\n", + dominated_found ? "FALSE" : "TRUE"); /* Write out nondominated sets. */ - if (filter_flag || agree || normalise_flag || force_bounds_flag - || logarithm_flag) { + if (filter_flag || agree || normalise_flag || force_bounds_flag || + logarithm_flag) { - const char *outfilename = ""; - FILE *outfile = stdout; + const char * outfilename = ""; + FILE * outfile = stdout; if (filename != stdin_name) { outfilename = m_strcat(filename, suffix); - outfile = fopen (outfilename, "w"); + outfile = fopen(outfilename, "w"); if (outfile == NULL) fatal_error("%s: %s\n", outfilename, strerror(errno)); } if (verbose_flag) - print_output_header (outfile, filename, nobj, minmax, agree, - lrange, urange, lbound, ubound, - logarithm); + print_output_header(outfile, filename, nobj, minmax, agree, lrange, + urange, lbound, ubound, logarithm); if (filter_flag && dominated_found) - write_sets_filtered (outfile, points, nobj, cumsizes, nsets, nondom); + write_sets_filtered(outfile, points, nobj, cumsizes, nsets, nondom); else - write_sets (outfile, points, nobj, cumsizes, nsets); + write_sets(outfile, points, nobj, cumsizes, nsets); if (verbose_flag) - fprintf (stderr, "# %s -> %s\n", filename, outfilename); + fprintf(stderr, "# %s -> %s\n", filename, outfilename); if (outfile != stdout) { - fclose (outfile); - free ( (void *) outfilename); + fclose(outfile); + free((void *)outfilename); } } - free (points); - free (cumsizes); - if (free_minmax) free( (void *) minmax); - if (nondom) free (nondom); - if (log_lbound) free (log_lbound); - if (log_ubound) free (log_ubound); + free(points); + free(cumsizes); + if (free_minmax) free((void *)minmax); + if (nondom) free(nondom); + if (log_lbound) free(log_lbound); + if (log_ubound) free(log_ubound); *minimum_p = minimum; *maximum_p = maximum; *nobj_p = nobj; - if (verbose_flag >= 2) - fprintf (stderr, "#\n"); + if (verbose_flag >= 2) fprintf(stderr, "#\n"); return dominated_found; } -int main(int argc, char *argv[]) +int +main(int argc, char * argv[]) { signed char agree = 0; double lower_range = 0.0; double upper_range = 0.0; - double *lower_bound = NULL; - double *upper_bound = NULL; + double * lower_bound = NULL; + double * upper_bound = NULL; - const signed char *minmax = NULL; + const signed char * minmax = NULL; bool maximise_all_flag = false; - const bool *logarithm = NULL; + const bool * logarithm = NULL; int nobj = 0; /* see the man page for getopt_long for an explanation of these fields */ static const char short_options[] = "hVvqfo:a:n:u:l:Us:b"; static const struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {"verbose", no_argument, NULL, 'v'}, - {"quiet", no_argument, NULL, 'q'}, - {"no-check", no_argument, NULL, 'c'}, - {"filter", no_argument, NULL, 'f'}, - {"force-bounds",no_argument, NULL, 'b'}, - {"obj", required_argument, NULL, 'o'}, - {"agree", required_argument, NULL, 'a'}, - {"maximise", no_argument, NULL, 'M'}, - {"maximize", no_argument, NULL, 'M'}, - {"normalise", required_argument, NULL, 'n'}, - {"upper-bound",required_argument, NULL, 'u'}, - {"lower-bound",required_argument, NULL, 'l'}, - {"union", no_argument, NULL, 'U'}, - {"suffix", required_argument, NULL, 's'}, - {"log", required_argument, NULL, 'L'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {"verbose", no_argument, NULL, 'v'}, + {"quiet", no_argument, NULL, 'q'}, + {"no-check", no_argument, NULL, 'c'}, + {"filter", no_argument, NULL, 'f'}, + {"force-bounds", no_argument, NULL, 'b'}, + {"obj", required_argument, NULL, 'o'}, + {"agree", required_argument, NULL, 'a'}, + {"maximise", no_argument, NULL, 'M'}, + {"maximize", no_argument, NULL, 'M'}, + {"normalise", required_argument, NULL, 'n'}, + {"upper-bound", required_argument, NULL, 'u'}, + {"lower-bound", required_argument, NULL, 'l'}, + {"union", no_argument, NULL, 'U'}, + {"suffix", required_argument, NULL, 's'}, + {"log", required_argument, NULL, 'L'}, {NULL, 0, NULL, 0} /* marks end of list */ }; set_program_invocation_short_name(argv[0]); int opt; /* it's actually going to hold a char */ int longopt_index; - while (0 < (opt = getopt_long (argc, argv, short_options, - long_options, &longopt_index))) { + while (0 < (opt = getopt_long(argc, argv, short_options, long_options, + &longopt_index))) { switch (opt) { case 'q': // --quiet verbose_flag = 0; @@ -538,7 +541,7 @@ int main(int argc, char *argv[]) case 'f': // --filter filter_flag = true; - check_flag = true; + check_flag = true; break; case 'b': // --force-bounds @@ -554,9 +557,9 @@ int main(int argc, char *argv[]) break; case 'a': // --agree - if (!strcmp (optarg, "max")) + if (!strcmp(optarg, "max")) agree = 1; - else if (!strcmp (optarg, "min")) + else if (!strcmp(optarg, "min")) agree = -1; else { fatal_error("invalid argument '%s' for -a, --agree" @@ -571,20 +574,24 @@ int main(int argc, char *argv[]) case 'n': // --normalise normalise_flag = true; - if (!read_range (optarg, &lower_range, &upper_range)) { + if (!read_range(optarg, &lower_range, &upper_range)) { fatal_error("invalid range '%s' for -n, --normalise" - ", use for example -n \"1 2\"\n", optarg); + ", use for example -n \"1 2\"\n", + optarg); } else if (lower_range >= upper_range) { - fatal_error ("lower range must be smaller than upper range for -n, --normalise\n"); + fatal_error("lower range must be smaller than upper range for " + "-n, --normalise\n"); } break; case 'u': // --upper-bound - upper_bound = robust_read_point(optarg, &nobj, "invalid upper bound point '%s'"); + upper_bound = robust_read_point(optarg, &nobj, + "invalid upper bound point '%s'"); break; case 'l': // --lower-bound - lower_bound = robust_read_point(optarg, &nobj, "invalid lower bound point '%s'"); + lower_bound = robust_read_point(optarg, &nobj, + "invalid lower bound point '%s'"); break; case 's': // --suffix @@ -592,7 +599,7 @@ int main(int argc, char *argv[]) break; case 'L': // --log - logarithm = read_bitvector (optarg, &nobj); + logarithm = read_bitvector(optarg, &nobj); if (logarithm == NULL) fatal_error("invalid argument to --log '%s'", optarg); break; @@ -602,27 +609,25 @@ int main(int argc, char *argv[]) } } - if (lower_bound && upper_bound - && any_less_than (upper_bound, lower_bound, nobj)) { + if (lower_bound && upper_bound && + any_less_than(upper_bound, lower_bound, nobj)) { fatal_error("upper bound must be higher than lower bound."); } int numfiles = argc - optind; - double *minimum = NULL; - double *maximum = NULL; + double * minimum = NULL; + double * maximum = NULL; - if (numfiles <= 1) {/* <= 0 means: No input files: read stdin. */ + if (numfiles <= 1) { /* <= 0 means: No input files: read stdin. */ bool dominated_found = - process_file ((numfiles == 1) ? argv[optind] : NULL, - minmax, &nobj, agree, - lower_range, upper_range, - lower_bound, upper_bound, - &minimum, &maximum, - /*check_minimum=*/true, /*check_maximum=*/true, - maximise_all_flag, logarithm); + process_file((numfiles == 1) ? argv[optind] : NULL, minmax, &nobj, + agree, lower_range, upper_range, lower_bound, + upper_bound, &minimum, &maximum, + /*check_minimum=*/true, /*check_maximum=*/true, + maximise_all_flag, logarithm); free(minimum); free(maximum); - free((void*)minmax); + free((void *)minmax); return filter_flag ? EXIT_SUCCESS : dominated_found; } @@ -632,55 +637,49 @@ int main(int argc, char *argv[]) /* Calculate the bounds among all input files. */ minimum = NULL, maximum = NULL; for (k = 0; k < numfiles; k++) - file_bounds (argv[optind + k], &minimum, &maximum, &nobj); + file_bounds(argv[optind + k], &minimum, &maximum, &nobj); k = 0; } else { /* If the bounds were given, initialize minimum and maximum. */ - dominated_found = - process_file (argv[optind], minmax, &nobj, agree, - lower_range, upper_range, - lower_bound, upper_bound, - &minimum, &maximum, - /*check_minimum=*/true, /*check_maximum=*/true, - maximise_all_flag, logarithm); + dominated_found = process_file( + argv[optind], minmax, &nobj, agree, lower_range, upper_range, + lower_bound, upper_bound, &minimum, &maximum, + /*check_minimum=*/true, /*check_maximum=*/true, maximise_all_flag, + logarithm); k = 1; } for (; k < numfiles; k++) { - double *tmp_maximum = NULL; - double *tmp_minimum = NULL; - - if (process_file (argv[optind + k], minmax, &nobj, agree, - lower_range, upper_range, - (lower_bound) ? lower_bound : minimum, - (upper_bound) ? upper_bound : maximum, - &tmp_minimum, &tmp_maximum, - lower_bound != NULL, upper_bound != NULL, - maximise_all_flag, logarithm)) + double * tmp_maximum = NULL; + double * tmp_minimum = NULL; + + if (process_file(argv[optind + k], minmax, &nobj, agree, lower_range, + upper_range, (lower_bound) ? lower_bound : minimum, + (upper_bound) ? upper_bound : maximum, &tmp_minimum, + &tmp_maximum, lower_bound != NULL, upper_bound != NULL, + maximise_all_flag, logarithm)) dominated_found = true; /* If the bounds were given, the real minimum and maximum must be calculated as we process the files. */ if (lower_bound && upper_bound) for (int n = 0; n < nobj; n++) { - if (minimum[n] > tmp_minimum[n]) - minimum[n] = tmp_minimum[n]; - if (maximum[n] < tmp_maximum[n]) - maximum[n] = tmp_maximum[n]; + if (minimum[n] > tmp_minimum[n]) minimum[n] = tmp_minimum[n]; + if (maximum[n] < tmp_maximum[n]) maximum[n] = tmp_maximum[n]; } - free (tmp_minimum); - free (tmp_maximum); + free(tmp_minimum); + free(tmp_maximum); } if (verbose_flag) { - printf ("# Total files: %d\n", numfiles); - printf ("# Total minimum:"); - vector_printf (minimum, nobj); - printf ("\n"); - printf ("# Total maximum:"); - vector_printf (maximum, nobj); - printf ("\n"); - printf ("# Nondominated: %s\n", dominated_found ? "FALSE": "TRUE"); + printf("# Total files: %d\n", numfiles); + printf("# Total minimum:"); + vector_printf(minimum, nobj); + printf("\n"); + printf("# Total maximum:"); + vector_printf(maximum, nobj); + printf("\n"); + printf("# Nondominated: %s\n", dominated_found ? "FALSE" : "TRUE"); } free(minimum); free(maximum); diff --git a/c/nondominated.h b/c/nondominated.h index 39e57a88..28a7e402 100644 --- a/c/nondominated.h +++ b/c/nondominated.h @@ -2,35 +2,34 @@ #define NONDOMINATED_H #include // memcpy -#include // INFINITY +#include // INFINITY #include "common.h" #include "sort.h" typedef const double avl_item_t; typedef struct avl_node_t { - struct avl_node_t *next; - struct avl_node_t *prev; - struct avl_node_t *parent; - struct avl_node_t *left; - struct avl_node_t *right; - avl_item_t *item; + struct avl_node_t * next; + struct avl_node_t * prev; + struct avl_node_t * parent; + struct avl_node_t * left; + struct avl_node_t * right; + avl_item_t * item; unsigned char depth; } avl_node_t; #include "avl_tiny.h" static inline bool * -nondom_init (size_t size) +nondom_init(size_t size) { bool * nondom = malloc(size * sizeof(*nondom)); - for (size_t n = 0; n < size; n++) - nondom[n] = true; + for (size_t n = 0; n < size; n++) nondom[n] = true; return nondom; } static inline const double * -force_agree_minimize(const double * restrict points, dimension_t dim, size_t size, - const signed char * restrict minmax, +force_agree_minimize(const double * restrict points, dimension_t dim, + size_t size, const signed char * restrict minmax, _attr_maybe_unused const signed char agree) { assert(agree != AGREE_MINIMISE); @@ -41,8 +40,7 @@ force_agree_minimize(const double * restrict points, dimension_t dim, size_t siz break; } } - if (no_copy) - return points; + if (no_copy) return points; double * pnew = malloc(dim * size * sizeof(*pnew)); memcpy(pnew, points, dim * size * sizeof(*pnew)); @@ -57,11 +55,10 @@ force_agree_minimize(const double * restrict points, dimension_t dim, size_t siz } static inline const double ** -generate_sorted_pp_2d(const double *points, size_t size) +generate_sorted_pp_2d(const double * points, size_t size) { - const double **p = malloc (size * sizeof(*p)); - for (size_t k = 0; k < size; k++) - p[k] = points + 2 * k; + const double ** p = malloc(size * sizeof(*p)); + for (size_t k = 0; k < size; k++) p[k] = points + 2 * k; // Sort in ascending lexicographic order from the last dimension. qsort(p, size, sizeof(*p), &cmp_double_asc_rev_2d); @@ -69,11 +66,10 @@ generate_sorted_pp_2d(const double *points, size_t size) } static inline const double ** -generate_sorted_pp_3d(const double *points, size_t size) +generate_sorted_pp_3d(const double * points, size_t size) { - const double **p = malloc (size * sizeof(*p)); - for (size_t k = 0; k < size; k++) - p[k] = points + 3 * k; + const double ** p = malloc(size * sizeof(*p)); + for (size_t k = 0; k < size; k++) p[k] = points + 3 * k; // Sort in ascending lexicographic order from the last dimension. qsort(p, size, sizeof(*p), &cmp_double_asc_rev_3d); @@ -87,10 +83,10 @@ generate_sorted_pp_3d(const double *points, size_t size) */ static inline size_t -find_dominated_2d_(const double *points, size_t size, const bool keep_weakly) +find_dominated_2d_(const double * points, size_t size, const bool keep_weakly) { ASSUME(size >= 2); - const double **p = generate_sorted_pp_2d(points, size); + const double ** p = generate_sorted_pp_2d(points, size); // SIZE_MAX means "no dominated solution found". size_t pos_first_dom = SIZE_MAX, k = 0, j = 1; do { @@ -128,7 +124,7 @@ find_nondominated_set_2d_(const double * restrict points, size_t size, ASSUME(size >= 2); // When compiling with -O3, GCC is able to create two versions of this loop // and move keep_weakly out. - const double **p = generate_sorted_pp_2d(points, size); + const double ** p = generate_sorted_pp_2d(points, size); size_t n_nondom = size, k = 0, j = 1; do { if (p[k][0] > p[j][0]) { @@ -164,17 +160,17 @@ find_nondominated_set_3d_helper(const double * restrict points, size_t size, const bool find_dominated_p, const bool keep_weakly) { - ASSUME (size >= 2); - const double **p = generate_sorted_pp_3d(points, size); + ASSUME(size >= 2); + const double ** p = generate_sorted_pp_3d(points, size); avl_tree_t tree; avl_init_tree(&tree, cmp_double_asc_x_asc_y); - avl_node_t * tnodes = malloc((size+1) * sizeof(*tnodes)); + avl_node_t * tnodes = malloc((size + 1) * sizeof(*tnodes)); avl_node_t * node = tnodes; node->item = p[0]; avl_insert_top(&tree, node); - const double sentinel[2] = { INFINITY, INFINITY }; + const double sentinel[2] = {INFINITY, INFINITY}; (++node)->item = sentinel; avl_insert_after(&tree, node - 1, node); const avl_node_t * end = node; @@ -201,15 +197,16 @@ find_nondominated_set_3d_helper(const double * restrict points, size_t size, // If pj[0] == point[0], then pj[1] < point[1] assert(pj[0] < point[0] || pj[1] < point[1]); - if (prev && prev[1] <= pj[1]) { // pj is dominated by a point in the tree. + if (prev && + prev[1] <= pj[1]) { // pj is dominated by a point in the tree. assert(prev[0] <= pj[0]); // It cannot be a duplicate because we already handled them above. - assert(prev[0] != pj[0] || prev[1] != pj[1] || prev[2] != pj[2]); + assert(prev[0] != pj[0] || prev[1] != pj[1] || + prev[2] != pj[2]); /* Map the order in p[], which is sorted, to the original order in points. */ pos_last_dom = (pj - points) / 3; - if (find_dominated_p) - goto early_end; + if (find_dominated_p) goto early_end; nondom[pos_last_dom] = false; n_nondom--; } else { @@ -229,14 +226,14 @@ find_nondominated_set_3d_helper(const double * restrict points, size_t size, } // Handle duplicates and points that are dominated by the immediate previous one. else if (!keep_weakly // we don't keep duplicates; // or it is not a duplicate, so it is non-weakly dominated; - || prev[0] != pj[0] || prev[1] != pj[1] || prev[2] != pj[2] + || prev[0] != pj[0] || prev[1] != pj[1] || + prev[2] != pj[2] // or the prev was dominated, then this one is also dominated. - || pos_last_dom == (size_t) ((prev - points) / 3)) { + || pos_last_dom == (size_t)((prev - points) / 3)) { /* Map the order in p[], which is sorted, to the original order in points. */ pos_last_dom = (pj - points) / 3; - if (find_dominated_p) - goto early_end; + if (find_dominated_p) goto early_end; nondom[pos_last_dom] = false; n_nondom--; } @@ -254,7 +251,8 @@ static inline size_t find_dominated_3d_(const double * points, size_t size, const bool keep_weakly) { return find_nondominated_set_3d_helper(points, size, /* nondom=*/NULL, - /*find_dominated_p=*/true, keep_weakly); + /*find_dominated_p=*/true, + keep_weakly); } /* @@ -262,15 +260,19 @@ find_dominated_3d_(const double * points, size_t size, const bool keep_weakly) nondominated points. */ static inline size_t -find_nondominated_set_3d_(const double * points, size_t size, bool * nondom, const bool keep_weakly) +find_nondominated_set_3d_(const double * points, size_t size, bool * nondom, + const bool keep_weakly) { return find_nondominated_set_3d_helper(points, size, nondom, - /*find_dominated_p=*/false, keep_weakly); + /*find_dominated_p=*/false, + keep_weakly); } static inline size_t -find_dominated_point_agree_none(const double * restrict points, dimension_t dim, size_t size, - const signed char * restrict minmax, const bool keep_weakly) +find_dominated_point_agree_none(const double * restrict points, dimension_t dim, + size_t size, + const signed char * restrict minmax, + const bool keep_weakly) { ASSUME(dim > 3); for (size_t k = 1; k < size; k++) { @@ -304,8 +306,8 @@ find_dominated_point_agree_none(const double * restrict points, dimension_t dim, } static inline size_t -find_dominated_point_agree_min(const double * restrict points, dimension_t dim, size_t size, - const bool keep_weakly) +find_dominated_point_agree_min(const double * restrict points, dimension_t dim, + size_t size, const bool keep_weakly) { ASSUME(dim > 3); for (size_t k = 1; k < size; k++) { @@ -339,8 +341,8 @@ find_dominated_point_agree_min(const double * restrict points, dimension_t dim, } static inline size_t -find_dominated_point_agree_max(const double * restrict points, dimension_t dim, size_t size, - const bool keep_weakly) +find_dominated_point_agree_max(const double * restrict points, dimension_t dim, + size_t size, const bool keep_weakly) { ASSUME(dim > 3); for (size_t k = 1; k < size; k++) { @@ -374,7 +376,8 @@ find_dominated_point_agree_max(const double * restrict points, dimension_t dim, } static inline size_t -find_nondominated_set_agree_none(const double * restrict points, dimension_t dim, size_t size, +find_nondominated_set_agree_none(const double * restrict points, + dimension_t dim, size_t size, const signed char * restrict minmax, bool * restrict nondom, const bool keep_weakly) { @@ -421,8 +424,9 @@ find_nondominated_set_agree_none(const double * restrict points, dimension_t dim } static inline size_t -find_nondominated_set_agree_min(const double * restrict points, dimension_t dim, size_t size, - bool * restrict nondom, const bool keep_weakly) +find_nondominated_set_agree_min(const double * restrict points, dimension_t dim, + size_t size, bool * restrict nondom, + const bool keep_weakly) { ASSUME(dim > 3); size_t new_size = size; @@ -467,8 +471,9 @@ find_nondominated_set_agree_min(const double * restrict points, dimension_t dim, } static inline size_t -find_nondominated_set_agree_max(const double * restrict points, dimension_t dim, size_t size, - bool * restrict nondom, const bool keep_weakly) +find_nondominated_set_agree_max(const double * restrict points, dimension_t dim, + size_t size, bool * restrict nondom, + const bool keep_weakly) { ASSUME(dim > 3); size_t new_size = size; @@ -517,45 +522,42 @@ find_nondominated_set_agree_max(const double * restrict points, dimension_t dim, /* Stop as soon as one dominated point is found and return its position. **/ static inline size_t -find_dominated_point_(const double * restrict points, dimension_t dim, size_t size, - const signed char * restrict minmax, signed char agree, - const bool keep_weakly) +find_dominated_point_(const double * restrict points, dimension_t dim, + size_t size, const signed char * restrict minmax, + signed char agree, const bool keep_weakly) { ASSUME(minmax != NULL); - if (size < 2) - return size; + if (size < 2) return size; ASSUME(dim >= 2); if (dim <= 3) { - const double *pp = force_agree_minimize (points, dim, size, minmax, agree); + const double * pp = + force_agree_minimize(points, dim, size, minmax, agree); size_t res; if (dim == 2) { res = find_dominated_2d_(pp, size, keep_weakly); } else { res = find_dominated_3d_(pp, size, keep_weakly); } - if (pp != points) - free((void*)pp); + if (pp != points) free((void *)pp); return res; } /* FIXME: Do not handle agree here, assume that objectives have been fixed already to agree on minimization/maximization. */ if (agree == AGREE_NONE) - agree = (signed char) check_all_minimize_maximize(minmax, dim); + agree = (signed char)check_all_minimize_maximize(minmax, dim); switch (agree) { - case AGREE_NONE: - return find_dominated_point_agree_none( - points, dim, size, minmax, keep_weakly); - case AGREE_MINIMISE: - return find_dominated_point_agree_min( - points, dim, size, keep_weakly); - case AGREE_MAXIMISE: - return find_dominated_point_agree_max( - points, dim, size, keep_weakly); - default: - unreachable(); + case AGREE_NONE: + return find_dominated_point_agree_none(points, dim, size, minmax, + keep_weakly); + case AGREE_MINIMISE: + return find_dominated_point_agree_min(points, dim, size, keep_weakly); + case AGREE_MAXIMISE: + return find_dominated_point_agree_max(points, dim, size, keep_weakly); + default: + unreachable(); } } @@ -563,46 +565,45 @@ find_dominated_point_(const double * restrict points, dimension_t dim, size_t si nondominated points. **/ static inline size_t -find_nondominated_set_(const double * restrict points, dimension_t dim, size_t size, - const signed char * restrict minmax, signed char agree, - bool * nondom, const bool keep_weakly) +find_nondominated_set_(const double * restrict points, dimension_t dim, + size_t size, const signed char * restrict minmax, + signed char agree, bool * nondom, const bool keep_weakly) { ASSUME(minmax != NULL); ASSUME(nondom != NULL); - if (size < 2) - return size; + if (size < 2) return size; ASSUME(dim >= 2); if (dim <= 3) { - const double *pp = force_agree_minimize (points, dim, size, minmax, agree); + const double * pp = + force_agree_minimize(points, dim, size, minmax, agree); size_t res; if (dim == 2) { res = find_nondominated_set_2d_(pp, size, nondom, keep_weakly); } else { res = find_nondominated_set_3d_(pp, size, nondom, keep_weakly); } - if (pp != points) - free((void*)pp); + if (pp != points) free((void *)pp); return res; } /* FIXME: Do not handle agree here, assume that objectives have been fixed already to agree on minimization/maximization. */ if (agree == AGREE_NONE) - agree = (signed char) check_all_minimize_maximize(minmax, dim); + agree = (signed char)check_all_minimize_maximize(minmax, dim); switch (agree) { - case AGREE_NONE: - return find_nondominated_set_agree_none( - points, dim, size, minmax, nondom, keep_weakly); - case AGREE_MINIMISE: - return find_nondominated_set_agree_min( - points, dim, size, nondom, keep_weakly); - case AGREE_MAXIMISE: - return find_nondominated_set_agree_max( - points, dim, size, nondom, keep_weakly); - default: - unreachable(); + case AGREE_NONE: + return find_nondominated_set_agree_none(points, dim, size, minmax, + nondom, keep_weakly); + case AGREE_MINIMISE: + return find_nondominated_set_agree_min(points, dim, size, nondom, + keep_weakly); + case AGREE_MAXIMISE: + return find_nondominated_set_agree_max(points, dim, size, nondom, + keep_weakly); + default: + unreachable(); } } @@ -612,97 +613,100 @@ find_dominated_point(const double * restrict points, int dim, size_t size, { ASSUME(dim >= 2); ASSUME(dim <= 32); - return find_dominated_point_(points, (dimension_t) dim, size, minmax, - AGREE_NONE, /* keep_weakly = */false); + return find_dominated_point_(points, (dimension_t)dim, size, minmax, + AGREE_NONE, /* keep_weakly = */ false); } static inline size_t -find_weakly_dominated_point(const double * restrict points, int dim, size_t size, - const bool * restrict maximise) +find_weakly_dominated_point(const double * restrict points, int dim, + size_t size, const bool * restrict maximise) { ASSUME(dim >= 2); ASSUME(dim <= 32); - const signed char * minmax = minmax_from_bool((dimension_t) dim, maximise); - size_t pos = find_dominated_point_(points, (dimension_t) dim, size, minmax, - AGREE_NONE, /* keep_weakly = */false); + const signed char * minmax = minmax_from_bool((dimension_t)dim, maximise); + size_t pos = find_dominated_point_(points, (dimension_t)dim, size, minmax, + AGREE_NONE, /* keep_weakly = */ false); free((void *)minmax); return pos; } static inline size_t -find_nondominated_set_agree (const double *points, int dim, size_t size, - const signed char *minmax, const signed char agree, - bool *nondom) +find_nondominated_set_agree(const double * points, int dim, size_t size, + const signed char * minmax, const signed char agree, + bool * nondom) { ASSUME(dim >= 2); ASSUME(dim <= 32); - return find_nondominated_set_(points, (dimension_t) dim, size, minmax, - agree, nondom, /* keep_weakly = */false); + return find_nondominated_set_(points, (dimension_t)dim, size, minmax, agree, + nondom, /* keep_weakly = */ false); } static inline size_t -find_nondominated_set (const double *points, dimension_t dim, size_t size, - const signed char *minmax, bool *nondom) +find_nondominated_set(const double * points, dimension_t dim, size_t size, + const signed char * minmax, bool * nondom) { ASSUME(dim >= 2); ASSUME(dim <= 32); - size_t new_size = find_nondominated_set_( - points, dim, size, minmax, AGREE_NONE, nondom, - /* keep_weakly = */false); - - if (new_size > size || new_size == 0 || new_size == SIZE_MAX) { /* This can't happen. */ - fatal_error ("%s:%d: a bug happened: new_size > old_size!\n" - "# size\tnondom\tdom\n" - " %zu\t%zu\t%zd\n", - __FILE__, __LINE__, size, new_size, size - new_size); + size_t new_size = + find_nondominated_set_(points, dim, size, minmax, AGREE_NONE, nondom, + /* keep_weakly = */ false); + + if (new_size > size || new_size == 0 || + new_size == SIZE_MAX) { /* This can't happen. */ + fatal_error("%s:%d: a bug happened: new_size > old_size!\n" + "# size\tnondom\tdom\n" + " %zu\t%zu\t%zd\n", + __FILE__, __LINE__, size, new_size, size - new_size); } return new_size; } static inline size_t -find_weak_nondominated_set(const double * restrict points, dimension_t dim, size_t size, - const signed char * restrict minmax, +find_weak_nondominated_set(const double * restrict points, dimension_t dim, + size_t size, const signed char * restrict minmax, bool * restrict nondom) { ASSUME(dim >= 2); ASSUME(dim <= 32); return find_nondominated_set_(points, dim, size, minmax, AGREE_NONE, nondom, - /* keep_weakly = */true); + /* keep_weakly = */ true); } static inline size_t -find_weak_nondominated_set_minimise(const double * restrict points, dimension_t dim, - size_t size, bool * restrict nondom) +find_weak_nondominated_set_minimise(const double * restrict points, + dimension_t dim, size_t size, + bool * restrict nondom) { ASSUME(dim >= 2); ASSUME(dim <= 32); const signed char * minmax = minmax_minimise(dim); ASSUME(minmax != NULL); - size_t new_size = find_weak_nondominated_set(points, dim, size, minmax, - nondom); + size_t new_size = + find_weak_nondominated_set(points, dim, size, minmax, nondom); free((void *)minmax); return new_size; } static inline size_t -get_nondominated_set (double **pareto_set_p, - const double *points, int dim, size_t size, - const signed char *minmax) +get_nondominated_set(double ** pareto_set_p, const double * points, int dim, + size_t size, const signed char * minmax) { ASSUME(dim >= 2); ASSUME(dim <= 32); ASSUME(size > 0); - bool *nondom = nondom_init(size); - size_t new_size = find_nondominated_set(points, (dimension_t) dim, size, minmax, nondom); - double *pareto_set = malloc(sizeof (double) * new_size * dim); + bool * nondom = nondom_init(size); + size_t new_size = + find_nondominated_set(points, (dimension_t)dim, size, minmax, nondom); + double * pareto_set = malloc(sizeof(double) * new_size * dim); if (new_size < size) { size_t n = 0, k = 0; do { while (!nondom[n]) n++; - memcpy(pareto_set + dim * k, points + dim * n, sizeof(points[0]) * dim); + memcpy(pareto_set + dim * k, points + dim * n, + sizeof(points[0]) * dim); k++; n++; } while (k < new_size); @@ -710,7 +714,7 @@ get_nondominated_set (double **pareto_set_p, // Nothing is dominated. Copy everything in one go. memcpy(pareto_set, points, sizeof(points[0]) * dim * size); } - free (nondom); + free(nondom); *pareto_set_p = pareto_set; return new_size; } @@ -723,8 +727,9 @@ filter_dominated_set(double * restrict points, int dim, size_t size, ASSUME(dim <= 32); ASSUME(size > 0); - bool *nondom = nondom_init(size); - size_t new_size = find_nondominated_set(points, (dimension_t) dim, size, minmax, nondom); + bool * nondom = nondom_init(size); + size_t new_size = + find_nondominated_set(points, (dimension_t)dim, size, minmax, nondom); if (new_size < size) { size_t k = 0; @@ -738,17 +743,18 @@ filter_dominated_set(double * restrict points, int dim, size_t size, k++; } } - free (nondom); + free(nondom); return new_size; } static inline bool * -is_nondominated_minmax(const double * restrict data, dimension_t nobj, size_t npoint, - const signed char * restrict minmax, bool keep_weakly) +is_nondominated_minmax(const double * restrict data, dimension_t nobj, + size_t npoint, const signed char * restrict minmax, + bool keep_weakly) { bool * nondom = nondom_init(npoint); find_nondominated_set_(data, nobj, npoint, minmax, AGREE_NONE, nondom, - /* keep_weakly = */keep_weakly); + /* keep_weakly = */ keep_weakly); return nondom; } @@ -757,9 +763,9 @@ is_nondominated_minimise(const double * data, dimension_t nobj, size_t npoint, bool keep_weakly) { const signed char * minmax = minmax_minimise(nobj); - bool * nondom = is_nondominated_minmax(data, nobj, npoint, minmax, - keep_weakly); - free((void *) minmax); + bool * nondom = + is_nondominated_minmax(data, nobj, npoint, minmax, keep_weakly); + free((void *)minmax); return nondom; } @@ -769,70 +775,66 @@ is_nondominated(const double * restrict data, int nobj, size_t npoint, { ASSUME(nobj >= 2); ASSUME(nobj <= 32); - const signed char * minmax = minmax_from_bool((dimension_t) nobj, maximise); - bool * nondom = is_nondominated_minmax(data, (dimension_t) nobj, npoint, + const signed char * minmax = minmax_from_bool((dimension_t)nobj, maximise); + bool * nondom = is_nondominated_minmax(data, (dimension_t)nobj, npoint, minmax, keep_weakly); free((void *)minmax); return nondom; } static inline void -agree_objectives (double *points, int dim, int size, - const signed char *minmax, const signed char agree) +agree_objectives(double * points, int dim, int size, const signed char * minmax, + const signed char agree) { for (int d = 0; d < dim; d++) - if ((agree > 0 && minmax[d] < 0) - || (agree < 0 && minmax[d] > 0)) + if ((agree > 0 && minmax[d] < 0) || (agree < 0 && minmax[d] > 0)) for (int k = 0; k < size; k++) points[k * dim + d] = -(points[k * dim + d]); } static inline void -normalise (double *points, int dim, int size, - const signed char *minmax, signed char agree, - const double lower_range, const double upper_range, - const double *lbound, const double *ubound) +normalise(double * points, int dim, int size, const signed char * minmax, + signed char agree, const double lower_range, const double upper_range, + const double * lbound, const double * ubound) { const double range = upper_range - lower_range; - double *diff = malloc (dim * sizeof(double)); + double * diff = malloc(dim * sizeof(double)); int k, d; for (d = 0; d < dim; d++) { diff[d] = ubound[d] - lbound[d]; if (diff[d] == 0.0) // FIXME: Should we use approximate equality? - diff[d] = 1; // FIXME: Do we need to handle agree? + diff[d] = 1; // FIXME: Do we need to handle agree? } for (k = 0; k < size; k++) { - double *p = points + k * dim; + double * p = points + k * dim; for (d = 0; d < dim; d++) - if ((agree > 0 && minmax[d] < 0) - || (agree < 0 && minmax[d] > 0)) + if ((agree > 0 && minmax[d] < 0) || (agree < 0 && minmax[d] > 0)) p[d] = lower_range + range * (ubound[d] + p[d]) / diff[d]; else p[d] = lower_range + range * (p[d] - lbound[d]) / diff[d]; } - free (diff); + free(diff); } _attr_maybe_unused static void -agree_normalise (double *data, int nobj, int npoint, - const bool * maximise, - const double lower_range, const double upper_range, - const double *lbound, const double *ubound) +agree_normalise(double * data, int nobj, int npoint, const bool * maximise, + const double lower_range, const double upper_range, + const double * lbound, const double * ubound) { const signed char * minmax = minmax_from_bool((dimension_t)nobj, maximise); // We have to make the objectives agree before normalisation. // FIXME: Do normalisation and agree in one step. - agree_objectives (data, nobj, npoint, minmax, AGREE_MINIMISE); - normalise(data, nobj, npoint, minmax, AGREE_MINIMISE, - lower_range, upper_range, lbound, ubound); - free ((void *)minmax); + agree_objectives(data, nobj, npoint, minmax, AGREE_MINIMISE); + normalise(data, nobj, npoint, minmax, AGREE_MINIMISE, lower_range, + upper_range, lbound, ubound); + free((void *)minmax); } -int * pareto_rank (const double *points, int dim, int size); +int * pareto_rank(const double * points, int dim, int size); #endif /* NONDOMINATED_H */ diff --git a/c/pareto.c b/c/pareto.c index 2f91ecf5..55416818 100644 --- a/c/pareto.c +++ b/c/pareto.c @@ -1,16 +1,16 @@ #include "nondominated.h" struct point_2d_front { - const double *p; + const double * p; unsigned int i; unsigned int f; }; static int -point_2d_front_cmp (const void * a, const void * b) +point_2d_front_cmp(const void * a, const void * b) { - const double *pa = ((const struct point_2d_front *)a)->p; - const double *pb = ((const struct point_2d_front *)b)->p; + const double * pa = ((const struct point_2d_front *)a)->p; + const double * pb = ((const struct point_2d_front *)b)->p; const double x0 = pa[0]; const double x1 = pa[1]; @@ -18,7 +18,7 @@ point_2d_front_cmp (const void * a, const void * b) const double y1 = pb[1]; /* FIXME: Use ?: */ - if (x0 < y0) + if (x0 < y0) return -1; else if (x0 > y0) return 1; @@ -40,26 +40,26 @@ point_2d_front_cmp (const void * a, const void * b) FIXME: Could we avoid creating a copy of the points? Yes, see find_nondominated_set_2d_() */ #if DEBUG >= 2 -#include "io.h" +# include "io.h" #endif static int * -pareto_rank_2D (const double *points, int size) +pareto_rank_2D(const double * points, int size) { const int dim = 2; int k; - struct point_2d_front *data = malloc(sizeof(struct point_2d_front) * size); + struct point_2d_front * data = malloc(sizeof(struct point_2d_front) * size); for (k = 0; k < size; k++) { data[k].p = &points[k * dim]; - data[k].i = (unsigned) k; + data[k].i = (unsigned)k; data[k].f = 0; } #if DEBUG >= 2 -#define PARETO_RANK_2D_DEBUG - double *help_0 = malloc (size * sizeof(double)); - double *help_1 = malloc (size * sizeof(double)); - int * help_i = malloc (size * sizeof(int)); +# define PARETO_RANK_2D_DEBUG + double * help_0 = malloc(size * sizeof(double)); + double * help_1 = malloc(size * sizeof(double)); + int * help_i = malloc(size * sizeof(int)); for (k = 0; k < size; k++) { help_0[k] = data[k].p[0]; @@ -67,38 +67,44 @@ pareto_rank_2D (const double *points, int size) help_i[k] = data[k].i; } fprintf(stderr, "%s():\n-------------------\n>>INPUT:", __FUNCTION__); - fprintf(stderr, "\nIndex: "); vector_int_fprintf(stderr, help_i, size); - fprintf(stderr, "\n[0] : "); vector_fprintf (stderr, help_0, size); - fprintf(stderr, "\n[1] : "); vector_fprintf (stderr, help_1, size); + fprintf(stderr, "\nIndex: "); + vector_int_fprintf(stderr, help_i, size); + fprintf(stderr, "\n[0] : "); + vector_fprintf(stderr, help_0, size); + fprintf(stderr, "\n[1] : "); + vector_fprintf(stderr, help_1, size); #endif - qsort (data, size, sizeof(struct point_2d_front), point_2d_front_cmp); + qsort(data, size, sizeof(struct point_2d_front), point_2d_front_cmp); #ifdef PARETO_RANK_2D_DEBUG for (k = 0; k < size; k++) { - help_0[k] = data[k].p[0]; - help_1[k] = data[k].p[1]; - help_i[k] = data[k].i; + help_0[k] = data[k].p[0]; + help_1[k] = data[k].p[1]; + help_i[k] = data[k].i; } fprintf(stderr, "%s():\n-------------------\n>>SORTED:", __FUNCTION__); - fprintf(stderr, "\nIndex: "); vector_int_fprintf(stderr, help_i, size); - fprintf(stderr, "\n[0] : "); vector_fprintf (stderr, help_0, size); - fprintf(stderr, "\n[1] : "); vector_fprintf (stderr, help_1, size); + fprintf(stderr, "\nIndex: "); + vector_int_fprintf(stderr, help_i, size); + fprintf(stderr, "\n[0] : "); + vector_fprintf(stderr, help_0, size); + fprintf(stderr, "\n[1] : "); + vector_fprintf(stderr, help_1, size); #endif int n_front = 0; - int * front_last = malloc (size * sizeof(int)); + int * front_last = malloc(size * sizeof(int)); front_last[0] = 0; data[0].f = 0; /* The first point is in the first front. */ for (k = 1; k < size; k++) { - const double *p = data[k].p; + const double * p = data[k].p; if (p[1] < data[front_last[n_front]].p[1]) { int low = 0; int high = n_front + 1; do { - int mid = low + (high - low) /2; - assert (mid <= n_front); - const double *pmid = data[front_last[mid]].p; + int mid = low + (high - low) / 2; + assert(mid <= n_front); + const double * pmid = data[front_last[mid]].p; if (p[1] < pmid[1]) high = mid; else if (p[1] > pmid[1] || (p[1] == pmid[1] && p[0] > pmid[0])) @@ -108,14 +114,14 @@ pareto_rank_2D (const double *points, int size) break; } } while (low < high); - assert (low <= n_front); - assert (p[1] < data[front_last[low]].p[1] - || (p[1] == data[front_last[low]].p[1] - && p[0] == data[front_last[low]].p[0])); + assert(low <= n_front); + assert(p[1] < data[front_last[low]].p[1] || + (p[1] == data[front_last[low]].p[1] && + p[0] == data[front_last[low]].p[0])); front_last[low] = k; data[k].f = low; - } else if (p[1] == data[front_last[n_front]].p[1] - && p[0] == data[front_last[n_front]].p[0]) { + } else if (p[1] == data[front_last[n_front]].p[1] && + p[0] == data[front_last[n_front]].p[0]) { front_last[n_front] = k; data[k].f = n_front; } else { @@ -124,35 +130,36 @@ pareto_rank_2D (const double *points, int size) data[k].f = n_front; } } - free (front_last); + free(front_last); #ifdef PARETO_RANK_2D_DEBUG { n_front++; // count max + 1 int f, i; - int *front_size = calloc(n_front, sizeof(int)); + int * front_size = calloc(n_front, sizeof(int)); int ** front = calloc(n_front, sizeof(int *)); for (k = 0; k < size; k++) { f = data[k].f; if (front_size[f] == 0) { - front[f] = malloc (size * sizeof(int)); + front[f] = malloc(size * sizeof(int)); } front[f][front_size[f]] = k; front_size[f]++; } - int *order = malloc (size * sizeof(int)); + int * order = malloc(size * sizeof(int)); f = 0, k = 0, i = 0; do { order[i] = front[f][k]; - fprintf (stderr, "\n_front[%d][%d] = %d = { %g , %g, %d, %d }", - f, k, front[f][k], - data[front[f][k]].p[0], data[front[f][k]].p[1], - data[front[f][k]].i, data[front[f][k]].f); + fprintf(stderr, "\n_front[%d][%d] = %d = { %g , %g, %d, %d }", f, k, + front[f][k], data[front[f][k]].p[0], data[front[f][k]].p[1], + data[front[f][k]].i, data[front[f][k]].f); i++, k++; - if (k == front_size[f]) { f++; k = 0; } + if (k == front_size[f]) { + f++; + k = 0; + } } while (f != n_front); - for (f = 0; f < n_front; f++) - free(front[f]); + for (f = 0; f < n_front; f++) free(front[f]); free(front); free(front_size); @@ -162,16 +169,18 @@ pareto_rank_2D (const double *points, int size) help_i[k] = data[order[k]].i; } fprintf(stderr, "%s():\n-------------------\n>>OUTPUT:", __FUNCTION__); - fprintf(stderr, "\nIndex: "); vector_int_fprintf(stderr, help_i, size); - fprintf(stderr, "\n[0] : "); vector_fprintf (stderr, help_0, size); - fprintf(stderr, "\n[1] : "); vector_fprintf (stderr, help_1, size); - - free (order); - + fprintf(stderr, "\nIndex: "); + vector_int_fprintf(stderr, help_i, size); + fprintf(stderr, "\n[0] : "); + vector_fprintf(stderr, help_0, size); + fprintf(stderr, "\n[1] : "); + vector_fprintf(stderr, help_1, size); + + free(order); } - free (help_0); - free (help_1); - free (help_i); + free(help_0); + free(help_1); + free(help_i); exit(1); #endif @@ -179,7 +188,7 @@ pareto_rank_2D (const double *points, int size) for (k = 0; k < size; k++) { rank[data[k].i] = data[k].f + 1; } - free (data); + free(data); return rank; } @@ -190,10 +199,10 @@ pareto_rank_2D (const double *points, int size) Evolutionary Computation, 7(5):503–515, 2003. */ int * -pareto_rank (const double *points, int d, int size) +pareto_rank(const double * points, int d, int size) { ASSUME(d >= 2 && d <= 32); - dimension_t dim = (dimension_t) d; + dimension_t dim = (dimension_t)d; int * rank2 = NULL; if (dim == 2) { rank2 = pareto_rank_2D(points, size); @@ -202,7 +211,7 @@ pareto_rank (const double *points, int d, int size) #endif } - int * rank = malloc(size * sizeof(int)); + int * rank = malloc(size * sizeof(int)); for (int k = 0; k < size; k++) { rank[k] = 1; } @@ -219,8 +228,8 @@ pareto_rank (const double *points, int d, int size) for (int k = 0; k < size; k++) { if (k == j) continue; if (rank[k] != level - 1) continue; - const double *pj = points + j * dim; - const double *pk = points + k * dim; + const double * pj = points + j * dim; + const double * pk = points + k * dim; bool j_leq_k = weakly_dominates(pj, pk, dim); bool k_leq_j = weakly_dominates(pk, pj, dim); if (j_leq_k && !k_leq_j) { diff --git a/c/rng.c b/c/rng.c index dd925848..7939bab4 100644 --- a/c/rng.c +++ b/c/rng.c @@ -69,7 +69,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ double -rng_standard_normal(rng_state *rng) +rng_standard_normal(rng_state * rng) { for (;;) { /* r = e3n52sb8 */ @@ -78,34 +78,33 @@ rng_standard_normal(rng_state *rng) r >>= 8; int sign = r & 0x1; uint64_t rabs = (r >> 1) & 0x000fffffffffffff; - double x = (double) rabs * wi_double[idx]; - if (sign & 0x1) - x = -x; - if (rabs < ki_double[idx]) - return x; /* 99.3% of the time return here */ + double x = (double)rabs * wi_double[idx]; + if (sign & 0x1) x = -x; + if (rabs < ki_double[idx]) return x; /* 99.3% of the time return here */ if (idx == 0) { for (;;) { /* Switch to 1.0 - U to avoid log(0.0), see GH 13361 */ - double xx = -ziggurat_nor_inv_r * log1p(-mt19937_next_double(rng)); + double xx = + -ziggurat_nor_inv_r * log1p(-mt19937_next_double(rng)); double yy = -log1p(-mt19937_next_double(rng)); if (yy + yy > xx * xx) return ((rabs >> 8) & 0x1) ? -(ziggurat_nor_r + xx) - : ziggurat_nor_r + xx; + : ziggurat_nor_r + xx; } - } else if (((fi_double[idx - 1] - fi_double[idx]) * mt19937_next_double(rng) + + } else if (((fi_double[idx - 1] - fi_double[idx]) * + mt19937_next_double(rng) + fi_double[idx]) < exp(-0.5 * x * x)) - return x; + return x; } } void -rng_bivariate_normal_fill(rng_state * rng, - double mu1, double mu2, +rng_bivariate_normal_fill(rng_state * rng, double mu1, double mu2, double sigma1, double sigma2, double rho, - double *out, int n) + double * out, int n) { const double sigma2rho = sigma2 * rho; - const double nu = sigma2 * sqrt(1 - rho*rho); + const double nu = sigma2 * sqrt(1 - rho * rho); for (int i = 0; i < n; i++) { const double x1 = rng_standard_normal(rng); *out = mu1 + x1 * sigma1; diff --git a/c/rng.h b/c/rng.h index 00876ec1..7ffc13f0 100644 --- a/c/rng.h +++ b/c/rng.h @@ -29,14 +29,12 @@ static inline double rng_uniform(rng_state * rng, double low, double high) { assert(rng != NULL); - if (low >= high) - return low; + if (low >= high) return low; return low + (high - low) * rng_random(rng); } -double rng_standard_normal(rng_state *rng); -void rng_bivariate_normal_fill(rng_state * rng, - double mu1, double mu2, +double rng_standard_normal(rng_state * rng); +void rng_bivariate_normal_fill(rng_state * rng, double mu1, double mu2, double sigma1, double sigma2, double rho, - double *out, int n); + double * out, int n); diff --git a/c/sort.h b/c/sort.h index 59709db6..524c3c99 100644 --- a/c/sort.h +++ b/c/sort.h @@ -1,5 +1,5 @@ -#ifndef SORT_H_ -# define SORT_H_ +#ifndef SORT_H_ +#define SORT_H_ #include "common.h" @@ -11,17 +11,18 @@ */ static inline bool -strongly_dominates(const double * restrict x, const double * restrict y, dimension_t dim) +strongly_dominates(const double * restrict x, const double * restrict y, + dimension_t dim) { ASSUME(dim >= 2); for (dimension_t d = 0; d < dim; d++) - if (x[d] >= y[d]) - return false; + if (x[d] >= y[d]) return false; return true; } static inline bool -weakly_dominates(const double * restrict x, const double * restrict y, const dimension_t dim) +weakly_dominates(const double * restrict x, const double * restrict y, + const dimension_t dim) { ASSUME(dim >= 2); /* The code below is a vectorized version of this code: @@ -33,28 +34,28 @@ weakly_dominates(const double * restrict x, const double * restrict y, const dim // GCC 15 is not able to infer this initialization from ASSUME(). // unsigned instead of bool to help auto-vectorization. unsigned x_leq_y = (x[0] <= y[0]) & (x[1] <= y[1]); - for (dimension_t d = 2; d < dim; d++) - x_leq_y &= (x[d] <= y[d]); - return (bool) x_leq_y; + for (dimension_t d = 2; d < dim; d++) x_leq_y &= (x[d] <= y[d]); + return (bool)x_leq_y; } static inline bool lexicographic_less_3d(const double * restrict a, const double * restrict b) { - return a[2] < b[2] || (a[2] == b[2] && (a[1] < b[1] || (a[1] == b[1] && a[0] <= b[0]))); + return a[2] < b[2] || + (a[2] == b[2] && (a[1] < b[1] || (a[1] == b[1] && a[0] <= b[0]))); } static inline bool -all_equal_double(const double * restrict x, const double * restrict y, dimension_t dim) +all_equal_double(const double * restrict x, const double * restrict y, + dimension_t dim) { ASSUME(dim >= 2); // The code below is written in a way that helps vectorization. // GCC 15 is not able to infer this initialization from ASSUME(). // unsigned instead of bool to help auto-vectorization. unsigned x_eq_y = (x[0] == y[0]) & (x[1] == y[1]); - for (dimension_t d = 2; d < dim; d++) - x_eq_y &= (x[d] == y[d]); - return (bool) x_eq_y; + for (dimension_t d = 2; d < dim; d++) x_eq_y &= (x[d] == y[d]); + return (bool)x_eq_y; } // ---------- Comparison functions (e.g, qsort). Return 'int' ---------------- @@ -63,15 +64,14 @@ all_equal_double(const double * restrict x, const double * restrict y, dimension typedef int (*cmp_fun_t)(const void *, const void *); static inline int -cmp_double_asc_rev(const void * restrict p1, const void * restrict p2, dimension_t dim) +cmp_double_asc_rev(const void * restrict p1, const void * restrict p2, + dimension_t dim) { const double * restrict x1 = *((const double **)p1); const double * restrict x2 = *((const double **)p2); for (int i = dim - 1; i >= 0; i--) { - if (x1[i] < x2[i]) - return -1; - if (x1[i] > x2[i]) - return 1; + if (x1[i] < x2[i]) return -1; + if (x1[i] > x2[i]) return 1; } return 0; } @@ -96,7 +96,8 @@ cmp_double_asc_rev_4d(const void * restrict p1, const void * restrict p2) } static inline int -cmp_double_asc_only_dim(const void * restrict p1, const void * restrict p2, dimension_t dim) +cmp_double_asc_only_dim(const void * restrict p1, const void * restrict p2, + dimension_t dim) { const double x1 = *(*(const double **)p1 + dim); const double x2 = *(*(const double **)p2 + dim); @@ -106,13 +107,13 @@ cmp_double_asc_only_dim(const void * restrict p1, const void * restrict p2, dime static inline int cmp_double_asc_only_3d(const void * restrict p1, const void * restrict p2) { - return cmp_double_asc_only_dim(p1,p2, 2); + return cmp_double_asc_only_dim(p1, p2, 2); } static inline int cmp_double_asc_only_4d(const void * restrict p1, const void * restrict p2) { - return cmp_double_asc_only_dim(p1,p2, 3); + return cmp_double_asc_only_dim(p1, p2, 3); } static inline int @@ -120,9 +121,9 @@ cmp_double_asc_y_des_x(const void * restrict p1, const void * restrict p2) { const double x1 = *(const double *)p1; const double x2 = *(const double *)p2; - const double y1 = *((const double *)p1+1); - const double y2 = *((const double *)p2+1); - return (y1 < y2) ? -1: ((y1 > y2) ? 1 : (x1 > x2 ? -1 : 1)); + const double y1 = *((const double *)p1 + 1); + const double y2 = *((const double *)p2 + 1); + return (y1 < y2) ? -1 : ((y1 > y2) ? 1 : (x1 > x2 ? -1 : 1)); } static inline int @@ -130,9 +131,9 @@ cmp_double_asc_x_asc_y(const void * restrict p1, const void * restrict p2) { const double x1 = *(const double *)p1; const double x2 = *(const double *)p2; - const double y1 = *((const double *)p1+1); - const double y2 = *((const double *)p2+1); - return (x1 < x2) ? -1: ((x1 > x2) ? 1 : (y1 < y2 ? -1 : 1)); + const double y1 = *((const double *)p1 + 1); + const double y2 = *((const double *)p2 + 1); + return (x1 < x2) ? -1 : ((x1 > x2) ? 1 : (y1 < y2 ? -1 : 1)); } static inline int @@ -140,9 +141,9 @@ cmp_double_asc_x_des_y(const void * restrict p1, const void * restrict p2) { const double x1 = *(const double *)p1; const double x2 = *(const double *)p2; - const double y1 = *((const double *)p1+1); - const double y2 = *((const double *)p2+1); - return (x1 < x2) ? -1: ((x1 > x2) ? 1 : (y1 > y2 ? -1 : 1)); + const double y1 = *((const double *)p1 + 1); + const double y2 = *((const double *)p2 + 1); + return (x1 < x2) ? -1 : ((x1 > x2) ? 1 : (y1 > y2 ? -1 : 1)); } static inline int @@ -152,8 +153,8 @@ cmp_doublep_x_asc_y_asc(const void * restrict p1, const void * restrict p2) const double x2 = **(const double **)p2; const double y1 = *(*(const double **)p1 + 1); const double y2 = *(*(const double **)p2 + 1); - return (x1 < x2) ? -1 : ((x1 > x2) ? 1 : - ((y1 < y2) ? -1 : ((y1 > y2) ? 1 : 0))); + return (x1 < x2) ? -1 + : ((x1 > x2) ? 1 : ((y1 < y2) ? -1 : ((y1 > y2) ? 1 : 0))); } static inline const double ** @@ -161,7 +162,7 @@ generate_sorted_doublep_2d(const double * restrict points, size_t * restrict size, const double ref0) { size_t n = *size; - const double **p = malloc(n * sizeof(*p)); + const double ** p = malloc(n * sizeof(*p)); size_t j = 0; for (size_t k = 0; k < n; k++) { /* There is no point in checking p[k][1] < ref[1] here because the @@ -183,4 +184,4 @@ generate_sorted_doublep_2d(const double * restrict points, } -#endif /* !SORT_H_ */ +#endif /* !SORT_H_ */ diff --git a/c/timer.c b/c/timer.c index d15c98b2..29e3e53f 100644 --- a/c/timer.c +++ b/c/timer.c @@ -6,11 +6,11 @@ #include "config.h" #include #if DEBUG >= 1 -#include +# include #endif #include /* for struct timeval */ #ifndef WIN32 -#include /* for getrusage */ +# include /* for getrusage */ #else /* getrusage @@ -46,33 +46,31 @@ * Based on: * http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/resource.h.html */ -#define RUSAGE_SELF (1<<0) -#define RUSAGE_CHILDREN (1<<1) +# define RUSAGE_SELF (1 << 0) +# define RUSAGE_CHILDREN (1 << 1) -struct rusage -{ - struct timeval ru_utime; /* user time used */ - struct timeval ru_stime; /* system time used */ +struct rusage { + struct timeval ru_utime; /* user time used */ + struct timeval ru_stime; /* system time used */ }; /* Include only the minimum from windows.h */ -#define WIN32_LEAN_AND_MEAN -#include -#include -#include +# define WIN32_LEAN_AND_MEAN +# include +# include +# include static void -FILETIME_to_timeval (struct timeval *tv, FILETIME *ft) +FILETIME_to_timeval(struct timeval * tv, FILETIME * ft) { - int64_t fulltime = ((((int64_t) ft->dwHighDateTime) << 32) - | ((int64_t) ft->dwLowDateTime)); + int64_t fulltime = + ((((int64_t)ft->dwHighDateTime) << 32) | ((int64_t)ft->dwLowDateTime)); fulltime /= 10LL; /* 100-ns -> us */ - tv->tv_sec = (__typeof__(tv->tv_sec)) fulltime / 1000000L; - tv->tv_usec = (__typeof__(tv->tv_sec)) fulltime % 1000000L; + tv->tv_sec = (__typeof__(tv->tv_sec))fulltime / 1000000L; + tv->tv_usec = (__typeof__(tv->tv_sec))fulltime % 1000000L; } -static int __cdecl -getrusage(int who, struct rusage *r_usage) +static int __cdecl getrusage(int who, struct rusage * r_usage) { FILETIME starttime; FILETIME exittime; @@ -89,26 +87,23 @@ getrusage(int who, struct rusage *r_usage) return -1; } - if (GetProcessTimes (GetCurrentProcess (), - &starttime, &exittime, - &kerneltime, &usertime) == 0) { + if (GetProcessTimes(GetCurrentProcess(), &starttime, &exittime, &kerneltime, + &usertime) == 0) { return -1; } - FILETIME_to_timeval (&r_usage->ru_stime, &kerneltime); - FILETIME_to_timeval (&r_usage->ru_utime, &usertime); + FILETIME_to_timeval(&r_usage->ru_stime, &kerneltime); + FILETIME_to_timeval(&r_usage->ru_utime, &usertime); return 0; } #endif #include "timer.h" -#define TIMER_CPUTIME(X) ( (double)X.ru_utime.tv_sec + \ - (double)X.ru_stime.tv_sec + \ - ((double)X.ru_utime.tv_usec + \ - (double)X.ru_stime.tv_usec ) * 1.0E-6) +#define TIMER_CPUTIME(X) \ + ((double)X.ru_utime.tv_sec + (double)X.ru_stime.tv_sec + \ + ((double)X.ru_utime.tv_usec + (double)X.ru_stime.tv_usec) * 1.0E-6) -#define TIMER_WALLTIME(X) ( (double)X.tv_sec + \ - (double)X.tv_usec * 1.0E-6 ) +#define TIMER_WALLTIME(X) ((double)X.tv_sec + (double)X.tv_usec * 1.0E-6) static struct rusage res; static struct timeval tp; @@ -122,12 +117,13 @@ static double stop_virtual_time, stop_real_time; * to get the amount of time used by the backtracking routine. */ -void Timer_start(void) +void +Timer_start(void) { - gettimeofday (&tp, NULL ); - real_time = TIMER_WALLTIME(tp); + gettimeofday(&tp, NULL); + real_time = TIMER_WALLTIME(tp); - getrusage (RUSAGE_SELF, &res ); + getrusage(RUSAGE_SELF, &res); virtual_time = TIMER_CPUTIME(res); } @@ -135,17 +131,19 @@ void Timer_start(void) * Return the time used in seconds (either * REAL or VIRTUAL time, depending on ``type''). */ -double Timer_elapsed_virtual (void) +double +Timer_elapsed_virtual(void) { - getrusage (RUSAGE_SELF, &res); + getrusage(RUSAGE_SELF, &res); double timer_tmp_time = TIMER_CPUTIME(res) - virtual_time; #if DEBUG >= 4 - if (timer_tmp_time < 0.0) { - fprintf(stderr, "%s: Timer_elapsed(): warning: " - "negative increase in time ", __FILE__); - fprintf(stderr, "(%.6g - %.6g = ", - TIMER_CPUTIME(res) , virtual_time); + if (timer_tmp_time < 0.0) { + fprintf(stderr, + "%s: Timer_elapsed(): warning: " + "negative increase in time ", + __FILE__); + fprintf(stderr, "(%.6g - %.6g = ", TIMER_CPUTIME(res), virtual_time); fprintf(stderr, "%.6g)\n", timer_tmp_time); } #endif @@ -153,18 +151,20 @@ double Timer_elapsed_virtual (void) return (timer_tmp_time < 0.0) ? 0 : timer_tmp_time; } -double Timer_elapsed_real (void) +double +Timer_elapsed_real(void) { - gettimeofday (&tp, NULL); + gettimeofday(&tp, NULL); double timer_tmp_time = TIMER_WALLTIME(tp) - real_time; #if DEBUG >= 2 - if (timer_tmp_time < 0.0) { - fprintf(stderr, "%s: Timer_elapsed(): warning: " - "negative increase in time ", __FILE__); - fprintf(stderr, "(%.6g - %.6g = ", - TIMER_WALLTIME(tp) , real_time); + if (timer_tmp_time < 0.0) { + fprintf(stderr, + "%s: Timer_elapsed(): warning: " + "negative increase in time ", + __FILE__); + fprintf(stderr, "(%.6g - %.6g = ", TIMER_WALLTIME(tp), real_time); fprintf(stderr, "%.6g)\n", timer_tmp_time); } #endif @@ -172,30 +172,32 @@ double Timer_elapsed_real (void) return (timer_tmp_time < 0.0) ? 0 : timer_tmp_time; } -double Timer_elapsed( TIMER_TYPE type ) +double +Timer_elapsed(TIMER_TYPE type) { - return (type == REAL_TIME) - ? Timer_elapsed_real () - : Timer_elapsed_virtual (); + return (type == REAL_TIME) ? Timer_elapsed_real() : Timer_elapsed_virtual(); } -void Timer_stop(void) +void +Timer_stop(void) { - gettimeofday( &tp, NULL ); - stop_real_time = TIMER_WALLTIME(tp); + gettimeofday(&tp, NULL); + stop_real_time = TIMER_WALLTIME(tp); - getrusage( RUSAGE_SELF, &res ); + getrusage(RUSAGE_SELF, &res); stop_virtual_time = TIMER_CPUTIME(res); } -void Timer_continue(void) +void +Timer_continue(void) { - gettimeofday( &tp, NULL ); + gettimeofday(&tp, NULL); double timer_tmp_time = TIMER_WALLTIME(tp) - stop_real_time; #if DEBUG >= 2 - if (timer_tmp_time < 0.0) { - fprintf(stderr, "%s: Timer_continue(): warning: " + if (timer_tmp_time < 0.0) { + fprintf(stderr, + "%s: Timer_continue(): warning: " "negative increase in time (%.6g - %.6g = %.6g)\n", __FILE__, TIMER_WALLTIME(tp), stop_real_time, timer_tmp_time); } @@ -203,14 +205,16 @@ void Timer_continue(void) if (timer_tmp_time > 0.0) real_time += timer_tmp_time; - getrusage( RUSAGE_SELF, &res ); - timer_tmp_time = TIMER_CPUTIME(res) - stop_virtual_time; + getrusage(RUSAGE_SELF, &res); + timer_tmp_time = TIMER_CPUTIME(res) - stop_virtual_time; #if DEBUG >= 2 - if (timer_tmp_time < 0.0) { - fprintf(stderr, "%s: Timer_continue(): warning: " + if (timer_tmp_time < 0.0) { + fprintf(stderr, + "%s: Timer_continue(): warning: " "negative increase in time (%.6g - %.6g = %.6g)\n", - __FILE__, TIMER_CPUTIME(res),stop_virtual_time,timer_tmp_time); + __FILE__, TIMER_CPUTIME(res), stop_virtual_time, + timer_tmp_time); } #endif diff --git a/c/timer.h b/c/timer.h index 3bf10274..3f6e97a1 100644 --- a/c/timer.h +++ b/c/timer.h @@ -15,7 +15,7 @@ #ifndef TIMER_H_ #define TIMER_H_ -typedef enum type_timer {REAL_TIME, VIRTUAL_TIME} TIMER_TYPE; +typedef enum type_timer { REAL_TIME, VIRTUAL_TIME } TIMER_TYPE; void Timer_start(void); double Timer_elapsed_virtual(void); double Timer_elapsed_real(void); diff --git a/c/whv.c b/c/whv.c index e37490a3..0014fbb1 100644 --- a/c/whv.c +++ b/c/whv.c @@ -4,30 +4,36 @@ #include "common.h" #include -static int cmp_data_y_desc (const void *p1, const void *p2) +static int +cmp_data_y_desc(const void * p1, const void * p2) { - const double *x1 = (const double *)p1; - const double *x2 = (const double *)p2; - - return (x1[1] > x2[1]) ? -1 : (x1[1] < x2[1]) ? 1 : - (x1[0] < x2[0]) ? -1 : (x1[0] > x2[0]) ? 1 - : 0; + const double * x1 = (const double *)p1; + const double * x2 = (const double *)p2; + + return (x1[1] > x2[1]) ? -1 + : (x1[1] < x2[1]) ? 1 + : (x1[0] < x2[0]) ? -1 + : (x1[0] > x2[0]) ? 1 + : 0; } -static int cmp_rectangles_y_desc (const void *p1, const void *p2) +static int +cmp_rectangles_y_desc(const void * p1, const void * p2) { - const double *x1 = (const double *)p1; - const double *x2 = (const double *)p2; + const double * x1 = (const double *)p1; + const double * x2 = (const double *)p2; // Order by upper (top-right) corner. - return (x1[3] > x2[3]) ? -1 : (x1[3] < x2[3]) ? 1 : - (x1[2] < x2[2]) ? -1 : (x1[2] > x2[2]) ? 1 - : 0; + return (x1[3] > x2[3]) ? -1 + : (x1[3] < x2[3]) ? 1 + : (x1[2] < x2[2]) ? -1 + : (x1[2] > x2[2]) ? 1 + : 0; } static double * whv_preprocess_rectangles(double * rectangles, int nrow, - const double *reference, int *new_nrow_p) + const double * reference, int * new_nrow_p) { const int ncol = 5; for (int k = 0; k < nrow; k++) { @@ -39,8 +45,8 @@ whv_preprocess_rectangles(double * rectangles, int nrow, int * skip = malloc(nrow * sizeof(int)); int skip_nrow = 0; for (int k = 0; k < nrow; k++) { - if (rectangles[k * ncol + 0] == rectangles[k * ncol + 2] - || rectangles[k * ncol + 1] == rectangles[k * ncol + 3]) + if (rectangles[k * ncol + 0] == rectangles[k * ncol + 2] || + rectangles[k * ncol + 1] == rectangles[k * ncol + 3]) skip[skip_nrow++] = k; } @@ -55,7 +61,7 @@ whv_preprocess_rectangles(double * rectangles, int nrow, *new_nrow_p = 0; return NULL; } - double *dest = malloc(sizeof(double) * 5 * new_nrow); + double * dest = malloc(sizeof(double) * 5 * new_nrow); skip[skip_nrow] = nrow; int j = 0, k = 0; for (int s = 0; s <= skip_nrow; s++) { @@ -72,61 +78,68 @@ whv_preprocess_rectangles(double * rectangles, int nrow, } double -rect_weighted_hv2d(double *data, int n, double * rectangles, +rect_weighted_hv2d(double * data, int n, double * rectangles, int rectangles_nrow, const double * reference) { -#define print_point(k, p, r, rect) \ - DEBUG2_PRINT("%d: p[%lu] = (%16.15g, %16.15g)" \ - "\trectangle[%lu] = (%16.15g, %16.15g, %16.15g, %16.15g)\n", \ - __LINE__, (unsigned long) k, p[0], p[1], (unsigned long) r, rect[0], rect[1], rect[2], rect[3]) - -#define print_rect(r, rect) \ - DEBUG2_PRINT("%d: rectangle[%lu] = (%16.15g, %16.15g, %16.15g, %16.15g, %16.15g)\n", \ - __LINE__, (unsigned long) r, rect[0], rect[1], rect[2], rect[3], rect[4]) +#define print_point(k, p, r, rect) \ + DEBUG2_PRINT("%d: p[%lu] = (%16.15g, %16.15g)" \ + "\trectangle[%lu] = (%16.15g, %16.15g, %16.15g, %16.15g)\n", \ + __LINE__, (unsigned long)k, p[0], p[1], (unsigned long)r, \ + rect[0], rect[1], rect[2], rect[3]) + +#define print_rect(r, rect) \ + DEBUG2_PRINT("%d: rectangle[%lu] = (%16.15g, %16.15g, %16.15g, %16.15g, " \ + "%16.15g)\n", \ + __LINE__, (unsigned long)r, rect[0], rect[1], rect[2], \ + rect[3], rect[4]) // rectangles: Two points per row + color // FIXME: Should we really allow color == 0 -#define get_rectangle(ROW) do { \ - rect = rectangles + (ROW) * (nobj * 2 + 1); \ - lower0= rect[0]; lower1= rect[1]; upper0= rect[2]; upper1= rect[3]; \ - color = rect[4]; \ - print_rect(ROW, rect); \ - assert(lower0 < upper0); \ - assert(lower1 < upper1); \ - assert(color >= 0); \ - } while(0) - -#define next_point() do { \ +#define get_rectangle(ROW) \ + do { \ + rect = rectangles + (ROW) * (nobj * 2 + 1); \ + lower0 = rect[0]; \ + lower1 = rect[1]; \ + upper0 = rect[2]; \ + upper1 = rect[3]; \ + color = rect[4]; \ + print_rect(ROW, rect); \ + assert(lower0 < upper0); \ + assert(lower1 < upper1); \ + assert(color >= 0); \ + } while (0) + +#define next_point() \ + do { \ top = p[1]; \ pk++; \ - if (pk >= n || top == last_top || p[0] >= last_right) \ - goto return_whv; \ + if (pk >= n || top == last_top || p[0] >= last_right) goto return_whv; \ p += nobj; \ print_point(pk, p, r, rect); \ - } while(0) + } while (0) // We cannot use %zu for size_t because of MingW compiler. - DEBUG2_PRINT("n = %lu\trectangles = %lu\n", (unsigned long)n, (unsigned long)rectangles_nrow); + DEBUG2_PRINT("n = %lu\trectangles = %lu\n", (unsigned long)n, + (unsigned long)rectangles_nrow); if (rectangles_nrow <= 0 || n <= 0) return 0; int old_rectangles_nrow = rectangles_nrow; - rectangles = - whv_preprocess_rectangles(rectangles, old_rectangles_nrow, reference, &rectangles_nrow); - if (rectangles_nrow == 0) - return 0; + rectangles = whv_preprocess_rectangles(rectangles, old_rectangles_nrow, + reference, &rectangles_nrow); + if (rectangles_nrow == 0) return 0; const int nobj = 2; - qsort (data, n, 2 * sizeof(*data), &cmp_data_y_desc); - qsort (rectangles, rectangles_nrow, (nobj * 2 + 1) * sizeof(*rectangles), - &cmp_rectangles_y_desc); + qsort(data, n, 2 * sizeof(*data), &cmp_data_y_desc); + qsort(rectangles, rectangles_nrow, (nobj * 2 + 1) * sizeof(*rectangles), + &cmp_rectangles_y_desc); double whv = 0.0; int r = 0; - const double *rect; + const double * rect; // rectangles: Two points per row + color double lower0, lower1, upper0, upper1, color; get_rectangle(r); - const double *p = data; + const double * p = data; int pk = 0; print_point(pk, p, r, rect); double top = upper1; @@ -135,7 +148,7 @@ rect_weighted_hv2d(double *data, int n, double * rectangles, // largest upper0; double last_right = -DBL_MAX; for (r = 0; r < rectangles_nrow; r++) { - last_right = MAX (last_right, rectangles[r * (nobj * 2 + 1) + 2]); + last_right = MAX(last_right, rectangles[r * (nobj * 2 + 1) + 2]); } // Find first useful point. while (p[1] >= upper1) { @@ -155,7 +168,8 @@ rect_weighted_hv2d(double *data, int n, double * rectangles, assert(top > lower1); assert(top > p[1]); // min(top, upper1) because the whole rect may be below top. - whv += (upper0 - MAX(p[0],lower0)) * (MIN(top, upper1) - MAX(p[1], lower1)) * color; + whv += (upper0 - MAX(p[0], lower0)) * + (MIN(top, upper1) - MAX(p[1], lower1)) * color; DEBUG2_PRINT("whv: %16.15g\n", whv); } // else case #3: not dominated or already completed, skip // Next rectangle @@ -166,15 +180,14 @@ rect_weighted_hv2d(double *data, int n, double * rectangles, // Also restart rectangles r = 0; get_rectangle(r); - do { + do { // FIXME: we need to loop because of repeated/dominated points when // sorting. We should delete them, skip for now. next_point(); } while (top == p[1] && p[1] >= upper1); } return_whv: - if (old_rectangles_nrow != rectangles_nrow) - free (rectangles); + if (old_rectangles_nrow != rectangles_nrow) free(rectangles); DEBUG2_PRINT("whv: %16.15g\n", whv); return whv; diff --git a/c/whv.h b/c/whv.h index 18814c44..6f8c942a 100644 --- a/c/whv.h +++ b/c/whv.h @@ -1,4 +1,5 @@ #ifndef WHV_H #define WHV_H -double rect_weighted_hv2d(double *data, int n, double * rectangles, int rectangles_nrow, const double *reference); +double rect_weighted_hv2d(double * data, int n, double * rectangles, + int rectangles_nrow, const double * reference); #endif // WHV_H diff --git a/c/whv_hype.c b/c/whv_hype.c index 97d347e6..56f32d6b 100644 --- a/c/whv_hype.c +++ b/c/whv_hype.c @@ -7,11 +7,15 @@ #include #include -enum hype_sample_dist_type { HYPE_DIST_UNIFORM, HYPE_DIST_EXPONENTIAL, HYPE_DIST_GAUSSIAN }; +enum hype_sample_dist_type { + HYPE_DIST_UNIFORM, + HYPE_DIST_EXPONENTIAL, + HYPE_DIST_GAUSSIAN +}; typedef struct hype_sample_dist hype_sample_dist; -typedef double *(*hype_sample_fn)(hype_sample_dist *, int); +typedef double * (*hype_sample_fn)(hype_sample_dist *, int); struct hype_sample_dist { enum hype_sample_dist_type type; @@ -37,10 +41,8 @@ gaussian_dist_sample(hype_sample_dist * dist, int nsamples) /* FIXME: Dimo's paper uses a t vector instead of rho */ double sigma_x = 0.25; double sigma_y = 0.25; - rng_bivariate_normal_fill(dist->rng, - dist->mu[0], dist->mu[1], - sigma_x, sigma_y, /*rho=*/1.0, - samples, nsamples); + rng_bivariate_normal_fill(dist->rng, dist->mu[0], dist->mu[1], sigma_x, + sigma_y, /*rho=*/1.0, samples, nsamples); /* FIXME: do we need to use the truncated distribution? samples[i * nobj + 0] = CLAMP(dist->mu[0] + x, 0.0, 1.0); samples[i * nobj + 1] = CLAMP(dist->mu[1] + y, 0.0, 1.0); @@ -52,8 +54,8 @@ static double * exp_dist_sample(hype_sample_dist * dist, int nsamples) { const int nobj = 2; - const double *lower = dist->lower; - const double *range = dist->range; + const double * lower = dist->lower; + const double * range = dist->range; double * samples = malloc(sizeof(double) * nsamples * nobj); int n = (int)(0.5 * nsamples); @@ -80,8 +82,8 @@ static double * uniform_dist_sample(hype_sample_dist * dist, int nsamples) { const int nobj = 2; - const double *lower = dist->lower; - const double *range = dist->range; + const double * lower = dist->lower; + const double * range = dist->range; rng_state * rng = dist->rng; double * samples = malloc(sizeof(double) * nsamples * nobj); for (int i = 0; i < nsamples; i++) { @@ -110,9 +112,9 @@ hype_dist_new(uint32_t seed) } static hype_sample_dist * -hype_dist_gaussian_new(uint32_t seed, const double *mu) +hype_dist_gaussian_new(uint32_t seed, const double * mu) { - hype_sample_dist *dist = hype_dist_new(seed); + hype_sample_dist * dist = hype_dist_new(seed); dist->type = HYPE_DIST_GAUSSIAN; const int nobj = 2; dist->mu = malloc(sizeof(double) * nobj); @@ -124,7 +126,7 @@ hype_dist_gaussian_new(uint32_t seed, const double *mu) static hype_sample_dist * hype_dist_exp_new(uint32_t seed, double mu) { - hype_sample_dist *dist = hype_dist_new(seed); + hype_sample_dist * dist = hype_dist_new(seed); dist->type = HYPE_DIST_EXPONENTIAL; dist->mu = malloc(sizeof(double) * 1); dist->mu[0] = mu; @@ -135,7 +137,7 @@ hype_dist_exp_new(uint32_t seed, double mu) static hype_sample_dist * hype_dist_unif_new(uint32_t seed) { - hype_sample_dist *dist = hype_dist_new(seed); + hype_sample_dist * dist = hype_dist_new(seed); dist->type = HYPE_DIST_UNIFORM; dist->create_samples = uniform_dist_sample; return dist; @@ -152,8 +154,8 @@ hype_dist_free(hype_sample_dist * d) } static double -estimate_whv(const double *points, int npoints, - const double * samples, int nsamples) +estimate_whv(const double * points, int npoints, const double * samples, + int nsamples) { const int nobj = 2; /* // compute alpha factor of HypE fitness: */ @@ -166,11 +168,11 @@ estimate_whv(const double *points, int npoints, unsigned int * dominated = calloc(nsamples, sizeof(unsigned int)); bool * is_dominator = malloc(npoints * sizeof(bool)); for (int s = 0; s < nsamples; s++) { - const double *sample = samples + s * nobj; + const double * sample = samples + s * nobj; // compute amount of dominators in p for each sample: for (int j = 0; j < npoints; j++) { bool dom = true; - const double *p = points + j * nobj; + const double * p = points + j * nobj; for (int d = 0; d < nobj; d++) { if (sample[d] < p[d]) { dom = false; @@ -196,7 +198,7 @@ estimate_whv(const double *points, int npoints, } static double -calculate_volume_between_points(const double *p1, const double * p2, int dim) +calculate_volume_between_points(const double * p1, const double * p2, int dim) { double volume = 1.0; for (int k = 0; k < dim; k++) volume *= (p2[k] - p1[k]); @@ -204,18 +206,18 @@ calculate_volume_between_points(const double *p1, const double * p2, int dim) } static void -normalise01_inplace(double *points, int dim, int npoints, - const double *lbound, const double *ubound) +normalise01_inplace(double * points, int dim, int npoints, + const double * lbound, const double * ubound) { - const signed char * minmax = minmax_minimise((dimension_t) dim); - normalise(points, dim, npoints, minmax, /*agree=*/-1, 0.0, 1.0, - lbound, ubound); - free((void *) minmax); + const signed char * minmax = minmax_minimise((dimension_t)dim); + normalise(points, dim, npoints, minmax, /*agree=*/-1, 0.0, 1.0, lbound, + ubound); + free((void *)minmax); } static double * -normalise01(const double *points, int dim, int npoints, - const double *lbound, const double *ubound) +normalise01(const double * points, int dim, int npoints, const double * lbound, + const double * ubound) { double * points2 = malloc(sizeof(double) * dim * npoints); memcpy(points2, points, sizeof(double) * dim * npoints); @@ -225,9 +227,8 @@ normalise01(const double *points, int dim, int npoints, static double -whv_hype_sample(const double *points, int npoints, - const double *ideal, const double *ref, - int nsamples, hype_sample_dist * dist) +whv_hype_sample(const double * points, int npoints, const double * ideal, + const double * ref, int nsamples, hype_sample_dist * dist) { const int nobj = 2; const double * samples = dist->create_samples(dist, nsamples); @@ -243,9 +244,8 @@ whv_hype_sample(const double *points, int npoints, } double -whv_hype_estimate(const double *points, int npoints, - const double *ideal, const double *ref, - hype_sample_dist * dist, int nsamples) +whv_hype_estimate(const double * points, int npoints, const double * ideal, + const double * ref, hype_sample_dist * dist, int nsamples) { const int nobj = 2; /* FIXME: this modifies mu, it would be better to keep mu and use a copy */ @@ -257,9 +257,8 @@ whv_hype_estimate(const double *points, int npoints, } double -whv_hype_unif(const double *points, int npoints, - const double *ideal, const double *ref, - int nsamples, uint32_t seed) +whv_hype_unif(const double * points, int npoints, const double * ideal, + const double * ref, int nsamples, uint32_t seed) { hype_sample_dist * dist = hype_dist_unif_new(seed); double whv = whv_hype_sample(points, npoints, ideal, ref, nsamples, dist); @@ -268,9 +267,8 @@ whv_hype_unif(const double *points, int npoints, } double -whv_hype_expo(const double *points, int npoints, - const double *ideal, const double *ref, - int nsamples, uint32_t seed, double mu) +whv_hype_expo(const double * points, int npoints, const double * ideal, + const double * ref, int nsamples, uint32_t seed, double mu) { hype_sample_dist * dist = hype_dist_exp_new(seed, mu); double whv = whv_hype_sample(points, npoints, ideal, ref, nsamples, dist); @@ -279,9 +277,9 @@ whv_hype_expo(const double *points, int npoints, } double -whv_hype_gaus(const double *points, int npoints, - const double *ideal, const double *ref, - int nsamples, uint32_t seed, const double *mu) +whv_hype_gaus(const double * points, int npoints, const double * ideal, + const double * ref, int nsamples, uint32_t seed, + const double * mu) { hype_sample_dist * dist = hype_dist_gaussian_new(seed, mu); const int nobj = 2; diff --git a/c/whv_hype.h b/c/whv_hype.h index 74d0c585..8ad50b76 100644 --- a/c/whv_hype.h +++ b/c/whv_hype.h @@ -2,14 +2,13 @@ #define WHV_HYPE_H #include -double whv_hype_unif(const double *points, int npoints, - const double *ideal, const double *ref, - int nsamples, uint32_t seed); -double whv_hype_expo(const double *points, int npoints, - const double *ideal, const double *ref, - int nsamples, uint32_t seed, double mu); -double whv_hype_gaus(const double *points, int npoints, - const double *ideal, const double *ref, - int nsamples, uint32_t seed, const double *mu); +double whv_hype_unif(const double * points, int npoints, const double * ideal, + const double * ref, int nsamples, uint32_t seed); +double whv_hype_expo(const double * points, int npoints, const double * ideal, + const double * ref, int nsamples, uint32_t seed, + double mu); +double whv_hype_gaus(const double * points, int npoints, const double * ideal, + const double * ref, int nsamples, uint32_t seed, + const double * mu); #endif