File: matrix-sort.cpp

package info (click to toggle)
macaulay2 1.21%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 133,096 kB
  • sloc: cpp: 110,377; ansic: 16,306; javascript: 4,193; makefile: 3,821; sh: 3,580; lisp: 764; yacc: 590; xml: 177; python: 140; perl: 114; lex: 65; awk: 3
file content (120 lines) | stat: -rw-r--r-- 2,756 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "matrix.hpp"

class MatrixSorter
{
  const Ring *R;
  int deg_ascending;
  int ringorder_ascending;
  int *sort_vals;
  vec *sort_vecs;
  int *sort_degs;
  M2_arrayint result;

  int sort_compare(int i, int j)
  {
    if (i == j) return 0;
    vec v1 = sort_vecs[i];
    vec v2 = sort_vecs[j];
    if (v1 == NULL) return 1;
    if (v2 == NULL) return -1;
    if (deg_ascending != 0)
      {
        int d1 = sort_degs[i];
        int d2 = sort_degs[j];
        if (d1 > d2) return -deg_ascending;
        if (d1 < d2) return deg_ascending;
      }
    int cmp = R->compare_vecs(v1, v2);
    if (cmp > 0) return -ringorder_ascending;
    if (cmp < 0) return ringorder_ascending;
    return 0;
  }

  int sort_partition(int lo, int hi)
  {
    int pivot = sort_vals[lo];
    int i = lo - 1;
    int j = hi + 1;
    for (;;)
      {
        do
          {
            j--;
          }
        while (sort_compare(sort_vals[j], pivot) < 0);
        do
          {
            i++;
          }
        while (sort_compare(sort_vals[i], pivot) > 0);

        if (i < j)
          {
            int tmp = sort_vals[j];
            sort_vals[j] = sort_vals[i];
            sort_vals[i] = tmp;
          }
        else
          return j;
      }
  }

  void sort_range(int lo, int hi)
  {
    if (lo < hi)
      {
        int q = sort_partition(lo, hi);
        sort_range(lo, q);
        sort_range(q + 1, hi);
      }
  }

 public:
  MatrixSorter(const Matrix *m, int degorder, int ringorder);

  M2_arrayintOrNull value();
};

MatrixSorter::MatrixSorter(const Matrix *m, int degorder, int ringorder)
    : deg_ascending(degorder), ringorder_ascending(ringorder)
{
  R = m->get_ring();

  int nelems = m->n_cols();

  if (degorder != 0)
    {
      sort_degs = newarray_atomic(int, nelems);
      for (int i = 0; i < nelems; i++)
        sort_degs[i] = m->cols()->primary_degree(i);
    }

  result = M2_makearrayint(nelems);

  sort_vals = result->array;
  for (int i = 0; i < nelems; i++) sort_vals[i] = i;

  sort_vecs = newarray(vec, nelems);
  for (int i = 0; i < nelems; i++) sort_vecs[i] = m->elem(i);
}

M2_arrayintOrNull MatrixSorter::value()
{
  sort_range(0, result->len - 1);
  return result;
}

M2_arrayint Matrix::sort(int degorder, int ringorder) const
// Sort the columns of 'this': Place the column indices into 'result'.
// If degorder < 0, sort in descending degree order, if >0 ascending degree
// If ==0, or in the event that two columns have the same (simple) degree,
// use the ring order: ringorder > 0 means ascending, <0 means descending.
{
  MatrixSorter sorter(this, degorder, ringorder);
  return sorter.value();
}

// Local Variables:
// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
// indent-tabs-mode: nil
// End: