1 /*** ase-permutation.c -- Permutations
3 * Copyright (C) 2006 - 2008 Sebastian Freundt
5 * Author: Sebastian Freundt <hroptatyr@sxemacs.org>
7 * This file is part of SXEmacs.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the author nor the names of any contributors
21 * may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 /* Synched up with: Not in FSF. */
44 #include "ase-permutation.h"
46 PROVIDE(ase_permutation);
47 REQUIRE(ase_permutation, "ase");
49 Lisp_Object Qase_permutation, Qase_permutationp;
50 Lisp_Object Qase_identity_permutation;
51 Lisp_Object Qpermutation_error, Qoverlap_error;
52 static int sane_small;
55 /* stuff for the dynacat */
57 _ase_permutation_prnt_cyc(unsigned long *p, unsigned long idx, Lisp_Object pcf)
61 write_fmt_string(pcf, "(%ld", idx+1);
62 for (q = p[idx]; q != idx; q = p[q])
63 write_fmt_str(pcf, " %ld", q+1);
64 write_c_string(")", pcf);
68 _ase_permutation_prnt(ase_permutation_t n, Lisp_Object pcf)
70 size_t deg = ase_permutation_degree(n);
71 unsigned long *perm = ase_permutation_perm(n);
75 write_c_string("()", pcf);
79 for (i = 0; i < deg; i++) {
80 /* find the smallest element in this cycle */
81 unsigned long q = perm[i];
85 /* if the smallest is the one we started with
86 * lets print the cycle */
87 if (i == q && perm[i] != i) {
88 _ase_permutation_prnt_cyc(perm, i, pcf);
95 ase_permutation_prnt(Lisp_Object obj, Lisp_Object pcf, int unused)
97 EMOD_ASE_DEBUG_PERM("p:0x%08x@0x%08x (rc:%d)\n",
98 (unsigned int)(XASE_PERMUTATION(obj)),
99 (unsigned int)obj, 1);
100 write_c_string("#<ase:permutation ", pcf);
101 _ase_permutation_prnt(XASE_PERMUTATION(obj), pcf);
102 write_c_string(">", pcf);
106 ase_permutation_fini(Lisp_Object obj, int unused)
108 ase_permutation_t free_me = XASE_PERMUTATION(obj);
110 EMOD_ASE_DEBUG_GC("p:%p@%p (rc:%d) shall be freed...\n",
111 free_me, (void*)obj, 1);
113 xfree(ase_permutation_perm(free_me));
119 _ase_permutation_mark(ase_permutation_t SXE_UNUSED(unused))
125 ase_permutation_mark(Lisp_Object obj)
127 EMOD_ASE_DEBUG_PERM("p:0x%08x@0x%08x (rc:%d) shall be marked...\n",
128 (unsigned int)(XASE_PERMUTATION(obj)),
129 (unsigned int)obj, 1);
130 _ase_permutation_mark(XASE_PERMUTATION(obj));
136 _ase_wrap_permutation(ase_permutation_t n)
140 result = make_dynacat(n);
141 XDYNACAT(result)->type = Qase_permutation;
145 ase_permutation_incref(n);
147 set_dynacat_printer(result, ase_permutation_prnt);
148 set_dynacat_marker(result, ase_permutation_mark);
149 set_dynacat_finaliser(result, ase_permutation_fini);
151 EMOD_ASE_DEBUG_PERM("p:0x%08x (rc:%d) shall be wrapped to 0x%08x...\n",
153 1, (unsigned int)result);
158 static inline ase_permutation_t
159 _ase_make_permutation(size_t deg, unsigned long *perm)
161 ase_permutation_t n = xnew_and_zero(struct ase_permutation_s);
163 ase_permutation_degree(n) = deg;
164 ase_permutation_perm(n) = perm;
166 EMOD_ASE_DEBUG_PERM("p:%p (rc:0, deg:%d) shall be created...\n",
172 ase_permutation_vecr_id_p(Lisp_Object vec)
174 size_t i = 0, deg = XVECTOR_LENGTH(vec);
177 Lisp_Object tmp = XVECTOR_DATA(vec)[i];
180 dead_wrong_type_argument(Qnatnump, tmp);
182 if (XUINT(tmp) != ++i)
189 ase_permutation_cycr_id_p(Lisp_Object vec)
191 size_t i, deg = XVECTOR_LENGTH(vec), id_p = 1;
193 for (i = 0; i < deg; i++) {
194 Lisp_Object cyc = XVECTOR_DATA(vec)[i];
202 Lisp_Object img = XCAR(cyc);
205 dead_wrong_type_argument(Qnatnump, img);
214 ase_permutation_determine_deg(Lisp_Object vec)
216 /* vec is assumed to be in cycle representation */
217 size_t len = XVECTOR_LENGTH(vec);
220 for (i = 0; i < len; i++) {
221 Lisp_Object cyc = XVECTOR_DATA(vec)[i];
227 Lisp_Object img = XCAR(cyc);
228 if (XUINT(img) > deg)
237 ase_permutation_init_cycr(size_t deg, unsigned long *p)
239 /* vec is assumed to be in cycle representation */
242 for (i = 0; i < deg; i++) {
249 ase_permutation_copy_cycr(unsigned long *p, Lisp_Object vec)
251 /* vec is assumed to be in cycle representation */
252 size_t len = XVECTOR_LENGTH(vec);
255 for (i = 0; i < len; i++) {
256 Lisp_Object cyc = XVECTOR_DATA(vec)[i];
263 while (!NILP(XCDR(cyc))) {
264 Lisp_Object pre = XCAR(cyc);
265 Lisp_Object post = XCAR((cyc = XCDR(cyc)));
266 p[XUINT(pre)-1] = XUINT(post)-1;
268 /* cyc should now look like (<elm> . nil) */
269 p[XUINT(XCAR(cyc))-1] = XUINT(first)-1;
274 static inline Lisp_Object
275 ase_make_permutation_cycr(Lisp_Object vec)
277 ase_permutation_t a = NULL;
281 EMOD_ASE_DEBUG_PERM("Creating perm from cycle representation ...\n");
283 if (ase_permutation_cycr_id_p(vec))
284 return Qase_identity_permutation;
286 deg = ase_permutation_determine_deg(vec);
287 perm = xnew_array(unsigned long, deg);
288 ase_permutation_init_cycr(deg, perm);
289 ase_permutation_copy_cycr(perm, vec);
291 a = _ase_make_permutation(deg, perm);
292 return _ase_wrap_permutation(a);
296 ase_permutation_copy_vecr(unsigned long *p, Lisp_Object vec)
298 size_t i, deg = XVECTOR_LENGTH(vec);
300 for (i = 0; i < deg; i++) {
301 Lisp_Object tmp = XVECTOR_DATA(vec)[i];
302 unsigned long m = XUINT(tmp)-1;
307 static inline Lisp_Object
308 ase_make_permutation_vecr(Lisp_Object vec)
310 ase_permutation_t a = NULL;
314 EMOD_ASE_DEBUG_PERM("Creating perm from mapping representation ...\n");
316 if (ase_permutation_vecr_id_p(vec))
317 return Qase_identity_permutation;
319 deg = XVECTOR_LENGTH(vec);
320 perm = xnew_array(unsigned long, deg);
321 ase_permutation_copy_vecr(perm, vec);
323 a = _ase_make_permutation(deg, perm);
324 return _ase_wrap_permutation(a);
328 ase_permutation_cycrep_p(Lisp_Object vec)
330 if (XVECTOR_LENGTH(vec) == 0)
332 return (CONSP(XVECTOR_DATA(vec)[0]) ||
333 NILP(XVECTOR_DATA(vec)[0]));
337 ase_make_permutation(Lisp_Object vec)
339 if (ase_permutation_cycrep_p(vec))
340 return ase_make_permutation_cycr(vec);
342 return ase_make_permutation_vecr(vec);
350 DEFUN("ase-permutationp", Fase_permutationp, 1, 1, 0, /*
351 Return non-`nil' iff OBJECT is an ase permutation.
355 if (ASE_PERMUTATIONP(object))
362 DEFUN("ase-permutation", Fase_permutation, 1, 1, 0, /*
363 Return a permutation around with POINT of radius RADIUS
364 with respect to METRIC (optional).
366 If no special metric is given, the supremum metric is used.
370 return ase_make_permutation(vector);
378 /* initialiser code */
379 #define EMODNAME ase_permutation
385 DEFSUBR(Fase_permutation);
387 DEFSUBR(Fase_permutationp);
390 defsymbol(&Qase_permutation, "ase:permutation");
391 defsymbol(&Qase_permutationp, "ase:permutationp");
393 DEFERROR(Qpermutation_error,
394 "Permutation error", Qdomain_error);
395 DEFERROR(Qoverlap_error,
396 "Permutations must not overlap", Qpermutation_error);
398 Fprovide(intern("ase-permutation"));
400 DEFVAR_CONST_LISP("ase-identity-permutation",
401 &Qase_identity_permutation /*
402 The identity permutation.
410 sane_small = (snprintf(NULL, 0, "%ld", EMACS_INT_MAX) + 7) & -3;
411 Qase_identity_permutation =
412 _ase_wrap_permutation(_ase_make_permutation(0, NULL));
413 /* defined in lread.c, declared in ent.h */
414 ase_permutation_f = ase_make_permutation;
420 Frevoke(intern("ase-permutation"));
423 /* ase-permutation ends here */