order.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /* File: order.c
  2. *
  3. * Created: 2 Mar 2008
  4. *
  5. * Last modified: 2 Mar 2008
  6. * Author: Pavel Sakov
  7. * NERSC
  8. *
  9. * Purpose: Put indices of an array of double in an order of increasing
  10. * value.
  11. *
  12. * Description: Given a double array x[n], sort its subset specified by an
  13. * integer array of indices good[ngood] and return the indices
  14. * of sorted elements in the integer array inorder[ngood].
  15. *
  16. * It is assumed that good[ngood] stores the "fortran" indices
  17. * (from 1 to N rather than from 0 to N - 1).
  18. *
  19. * Modifications: none
  20. */
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <math.h>
  25. #include "cfortran.h"
  26. typedef struct {
  27. int index;
  28. double v;
  29. } indexedvalue;
  30. static int comp(const void* p1, const void* p2)
  31. {
  32. indexedvalue* v1 = (indexedvalue*) p1;
  33. indexedvalue* v2 = (indexedvalue*) p2;
  34. if (v1->v > v2->v)
  35. return 1;
  36. else if (v1->v < v2->v)
  37. return -1;
  38. return 0;
  39. }
  40. /** Sorts a specified subset within an array of double according to values.
  41. *
  42. * Given a double array x[n], sorts its subset specified by an integer array
  43. * good[ngood] and returns the indices of sorted elements in the preallocated
  44. * integer array inorder[ngood].
  45. *
  46. * It is assumed that good[ngood] stores the "fortran" indices (from 1 to N
  47. * rather than from 0 to N - 1).
  48. *
  49. * @param pn Number of elements in the data array
  50. * @param x Data array
  51. * @param pngood Number of elements in the data array to be sorted
  52. * @param good Indices of the elements in the data array to be sorted
  53. * @param inorder Output array of size of `ngood' such that the corresponding
  54. * elements of the data array are in increasing order
  55. */
  56. void order(double pn[], double x[], double pngood[], int good[], int inorder[])
  57. {
  58. int n = (int) pn[0];
  59. int ngood = (int) pngood[0];
  60. indexedvalue* iv = NULL;
  61. int i;
  62. if (n <= 0) {
  63. for (i = 0; i < ngood; ++i)
  64. inorder[i] = -1;
  65. return;
  66. }
  67. iv = malloc(n * sizeof(indexedvalue));
  68. if (n < ngood) {
  69. fprintf(stderr, "ERROR: order.c: order(): size of the data = %d is less than the requested size of the sorted array %d\n", n, ngood);
  70. exit(1);
  71. }
  72. /*
  73. * a bit of quality control
  74. */
  75. for (i = 0; i < ngood; ++i) {
  76. double xx;
  77. if (good[i] < 1 || good[i] > n) {
  78. fprintf(stderr, "ERROR: order.c: order(): good[%d] = %d, n = %d\n", i, good[i], n);
  79. exit(1);
  80. }
  81. xx = x[good[i] - 1];
  82. if (isnan(xx) || fabs(xx) > 1.0e+10 || xx == -999.0) {
  83. fprintf(stderr, "ERROR: order.c: order(): x[%d] = %.15g\n", good[i] - 1, xx);
  84. exit(1);
  85. }
  86. }
  87. for (i = 0; i < ngood; ++i) {
  88. iv[i].index = good[i];
  89. iv[i].v = x[good[i] - 1];
  90. }
  91. qsort(iv, ngood, sizeof(indexedvalue), comp);
  92. for (i = 0; i < ngood; ++i)
  93. inorder[i] = iv[i].index;
  94. free(iv);
  95. }
  96. FCALLSCSUB5(order, ORDER, order, PDOUBLE, PDOUBLE, PDOUBLE, PINT, PINT)