Matrix r4655
Loading...
Searching...
No Matches
perm.c
Go to the documentation of this file.
1#include "Mdefines.h"
2#include "perm.h"
3
4int isPerm(const int *p, int n, int off)
5{
6 int res = 1;
7 if (n <= 0)
8 return res;
9 int i, j;
10 char *work;
11 Matrix_Calloc(work, n, char);
12 for (i = 0; i < n; ++i) {
13 if (p[i] == NA_INTEGER || (j = p[i] - off) < 0 || j >= n || work[j]) {
14 res = 0;
15 break;
16 }
17 work[j] = 1;
18 }
19 Matrix_Free(work, n);
20 return res;
21}
22
23int signPerm(const int *p, int n, int off)
24{
25 if (!isPerm(p, n, off))
26 error(_("attempt to get sign of non-permutation"));
27 int sign = 1;
28 if (n <= 0)
29 return sign;
30 int i, pos = 0;
31 char *work;
32 Matrix_Calloc(work, n, char);
33 while (pos < n) {
34 work[pos] = 1;
35 i = p[pos] - off;
36 while (!work[i]) { /* transposition */
37 sign = -sign;
38 work[i] = 1;
39 i = p[i] - off;
40 }
41 while (pos < n && work[pos])
42 ++pos;
43 }
44 Matrix_Free(work, n);
45 return sign;
46}
47
48void invertPerm(const int *p, int *ip, int n, int off, int ioff)
49{
50 if (!isPerm(p, n, off))
51 error(_("attempt to invert non-permutation"));
52 int j;
53 for (j = 0; j < n; ++j)
54 ip[p[j] - off] = j + ioff;
55 return;
56}
57
58void asPerm(const int *p, int *ip, int m, int n, int off, int ioff)
59{
60 int i, j, tmp;
61 for (i = 0; i < n; ++i)
62 ip[i] = i + ioff;
63 for (i = 0; i < m; ++i) {
64 j = p[i] - off;
65 if (j < 0 || j >= n)
66 error(_("invalid transposition vector"));
67 if (j != i) {
68 tmp = ip[j];
69 ip[j] = ip[i];
70 ip[i] = tmp;
71 }
72 }
73 return;
74}
75
76SEXP R_isPerm(SEXP p, SEXP off)
77{
78 if (TYPEOF(p) != INTSXP)
79 error(_("'%s' is not of type \"%s\""), "p", "integer");
80 if (TYPEOF(off) != INTSXP)
81 error(_("'%s' is not of type \"%s\""), "off", "integer");
82 if (XLENGTH(off) != 1)
83 error(_("'%s' does not have length %d"), "off", 1);
84 int off_ = INTEGER(off)[0];
85 if (off_ == NA_INTEGER)
86 error(_("'%s' is NA"), "off");
87 R_xlen_t n_ = XLENGTH(p);
88 if (n_ > INT_MAX)
89 return ScalarLogical(0);
90 return ScalarLogical(isPerm(INTEGER(p), (int) n_, off_));
91}
92
93SEXP R_signPerm(SEXP p, SEXP off)
94{
95 if (TYPEOF(p) != INTSXP)
96 error(_("'%s' is not of type \"%s\""), "p", "integer");
97 if (TYPEOF(off) != INTSXP)
98 error(_("'%s' is not of type \"%s\""), "off", "integer");
99 if (XLENGTH(off) != 1)
100 error(_("'%s' does not have length %d"), "off", 1);
101 int off_ = INTEGER(off)[0];
102 if (off_ == NA_INTEGER)
103 error(_("'%s' is NA"), "off");
104 R_xlen_t n_ = XLENGTH(p);
105 if (n_ > INT_MAX)
106 error(_("attempt to get sign of non-permutation"));
107 return ScalarInteger(signPerm(INTEGER(p), (int) n_, off_));
108}
109
110SEXP R_invertPerm(SEXP p, SEXP off, SEXP ioff)
111{
112 if (TYPEOF(p) != INTSXP)
113 error(_("'%s' is not of type \"%s\""), "p", "integer");
114 if (TYPEOF(off) != INTSXP || TYPEOF(ioff) != INTSXP)
115 error(_("'%s' or '%s' is not of type \"%s\""), "off", "ioff", "integer");
116 if (XLENGTH(off) != 1 || XLENGTH(ioff) != 1)
117 error(_("'%s' or '%s' does not have length %d"), "off", "ioff", 1);
118 int off_ = INTEGER(off)[0], ioff_ = INTEGER(ioff)[0];
119 if (off_ == NA_INTEGER || ioff_ == NA_INTEGER)
120 error(_("'%s' or '%s' is NA"), "off", "ioff");
121 R_xlen_t n_ = XLENGTH(p);
122 if (n_ > INT_MAX)
123 error(_("attempt to invert non-permutation"));
124 SEXP ip = PROTECT(allocVector(INTSXP, n_));
125 invertPerm(INTEGER(p), INTEGER(ip), (int) n_, off_, ioff_);
126 UNPROTECT(1);
127 return ip;
128}
129
130SEXP R_asPerm(SEXP p, SEXP off, SEXP ioff, SEXP n)
131{
132 if (TYPEOF(p) != INTSXP)
133 error(_("'%s' is not of type \"%s\""), "p", "integer");
134 R_xlen_t m_ = XLENGTH(p);
135 if (m_ > INT_MAX)
136 error(_("'%s' has length exceeding %s"), "p", "2^31-1");
137 if (TYPEOF(off) != INTSXP || TYPEOF(ioff) != INTSXP)
138 error(_("'%s' or '%s' is not of type \"%s\""), "off", "ioff", "integer");
139 if (XLENGTH(off) != 1 || XLENGTH(ioff) != 1)
140 error(_("'%s' or '%s' does not have length %d"), "off", "ioff", 1);
141 int off_ = INTEGER(off)[0], ioff_ = INTEGER(ioff)[0];
142 if (off_ == NA_INTEGER || ioff_ == NA_INTEGER)
143 error(_("'%s' or '%s' is NA"), "off", "ioff");
144 if (TYPEOF(n) != INTSXP)
145 error(_("'%s' is not of type \"%s\""), "n", "integer");
146 if (XLENGTH(n) != 1)
147 error(_("'%s' does not have length %d"), "n", 1);
148 int n_ = INTEGER(n)[0];
149 if (n_ == NA_INTEGER || n_ < m_)
150 error(_("'%s' is NA or less than %s"), "n", "length(p)");
151 SEXP ip = PROTECT(allocVector(INTSXP, n_));
152 asPerm(INTEGER(p), INTEGER(ip), (int) m_, n_, off_, ioff_);
153 UNPROTECT(1);
154 return ip;
155}
#define _(String)
Definition Mdefines.h:44
#define Matrix_Free(_VAR_, _N_)
Definition Mdefines.h:77
#define Matrix_Calloc(_VAR_, _N_, _CTYPE_)
Definition Mdefines.h:66
void asPerm(const int *p, int *ip, int m, int n, int off, int ioff)
Definition perm.c:58
int isPerm(const int *p, int n, int off)
Definition perm.c:4
SEXP R_invertPerm(SEXP p, SEXP off, SEXP ioff)
Definition perm.c:110
void invertPerm(const int *p, int *ip, int n, int off, int ioff)
Definition perm.c:48
int signPerm(const int *p, int n, int off)
Definition perm.c:23
SEXP R_isPerm(SEXP p, SEXP off)
Definition perm.c:76
SEXP R_asPerm(SEXP p, SEXP off, SEXP ioff, SEXP n)
Definition perm.c:130
SEXP R_signPerm(SEXP p, SEXP off)
Definition perm.c:93