3 * Copyright (C) 2007 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 * All the code below is just a first (tacky) draught. It is optimised
39 * in a way, but still, the ardent worshippers of the DRY principle
40 * would tar and feather me for that.
44 /* Synched up with: Not in FSF, not in XE */
52 Lisp_Object Q_arity, Q_result_type, Q_mode, Q_glue;
53 Lisp_Object Q_separator, Q_initiator, Q_terminator;
54 Lisp_Object Qpntw, Qpointwise, Qpoints;
55 Lisp_Object Qkeyw, Qkeywise, Qkeys;
56 Lisp_Object Qcomb, Qcombination, Qcombinations;
57 Lisp_Object Qperm, Qpermutation, Qpermutations;
58 Lisp_Object Qcart, Qcartesian;
60 typedef Lisp_Object(*glue_f)(int nargs, Lisp_Object *args);
62 static Lisp_Object Qinplace, Qlitter, Qconcat;
63 static Lisp_Object Qvector, Qbit_vector;
66 EXFUN(Fbit_vector, MANY);
68 /* until this is available globally */
69 #define DICTP(x) (HASH_TABLEP(x) || SKIPLISTP(x))
72 Lisp_Object ini, ter, sep;
75 #define deco_ini(x) ((x)->ini)
76 #define deco_sep(x) ((x)->sep)
77 #define deco_ter(x) ((x)->ter)
81 static inline Lisp_Object
82 __Flist(int nargs, Lisp_Object *args)
83 __attribute__((always_inline));
84 static inline Lisp_Object
85 __Flist(int nargs, Lisp_Object *args)
87 /* this is just Flist() but inlined */
88 Lisp_Object val = Qnil;
89 Lisp_Object *argp = args + nargs;
92 val = Fcons(*--argp, val);
96 static long unsigned int
97 __ncombinations(register long unsigned int n, long unsigned int k)
99 /* == binomial(n, k) */
100 if (UNLIKELY(n == k || k == 0)) {
102 } else if (UNLIKELY(k == 1 || n - k == 1)) {
104 } else if (k == 2 || n - k == 2) {
105 return (n * (n-1)) >> 1;
107 /* otherwise do the hard work */
108 long unsigned int num = n*(n-1)*(n-k+1), den = k*(k-1);
110 /* swap k if necessary */
115 for (n -= 2, k -= 2; k > 1;) {
123 static long unsigned int
124 __factorial(register long unsigned int n)
126 register long unsigned int r = n;
128 /* trivial cases first */
152 for (long unsigned int i = 9; i < n; i++) {
158 static long unsigned int
159 __nvariations(register long unsigned int n, long unsigned int k)
161 /* == binomial(n, k) * factorial(k) */
162 if (UNLIKELY(k == 0)) {
164 } else if (UNLIKELY(k == n)) {
165 return __factorial(k);
166 } else if (UNLIKELY(k == 1)) {
168 } else if (UNLIKELY(n - k == 1)) {
169 return __factorial(n);
173 return n * (n-1) * (n-2);
175 /* otherwise do the hard work */
176 long unsigned int num = n--;
188 static long unsigned int
189 __ncart(register long unsigned int n, long unsigned int k)
192 long unsigned int res;
207 for (res = n * n * n * n, k -= 4; k > 0; k--) {
215 __advance_multi_index()
216 __attribute__((always_inline));
218 __advance_multi_index(long int idx[], long int j, long int fam_len)
220 /* partially unroll */
221 if (LIKELY(++idx[--j] < fam_len)) {
225 if (LIKELY(++idx[--j] < fam_len)) {
229 if (LIKELY(++idx[--j] < fam_len)) {
234 if (LIKELY(++idx[--j] < fam_len)) {
243 __advance_multi_index_2()
244 __attribute__((always_inline));
246 __advance_multi_index_2(long int idx[], long int j, size_t flen[])
248 /* improved version of __a_m_v() which allows for differently-sized families */
249 /* partially unroll */
250 if (LIKELY((--j, ++idx[j] < (long int)flen[j]))) {
254 if (LIKELY((--j, ++idx[j] < (long int)flen[j]))) {
258 if (LIKELY((--j, ++idx[j] < (long int)flen[j]))) {
263 if (LIKELY((--j, ++idx[j] < (long int)flen[j]))) {
272 __advance_multi_index_3()
273 __attribute__((always_inline));
275 __advance_multi_index_3(
276 long int idx[], long int j, size_t flen[],
277 long int nseqs, size_t arity[])
279 /* improved version of __a_m_v_2() which allows for differently-sized families
280 * and multiplicities thereof
281 * this is for cartesian indexing, i.e. the order goes
282 * [1,0]->[1,1]->[1,2]->[2,0] for arity (., 3) */
283 long int mlt = arity[--nseqs];
285 if (LIKELY(++idx[--j] < (long int)flen[nseqs])) {
290 mlt = arity[--nseqs];
292 if (LIKELY(++idx[--j] < (long int)flen[nseqs])) {
297 mlt = arity[--nseqs];
299 if (LIKELY(++idx[--j] < (long int)flen[nseqs])) {
304 mlt = arity[--nseqs];
306 while (j > 0 && nseqs >= 0) {
307 if (LIKELY(++idx[--j] < (long int)flen[nseqs])) {
312 mlt = arity[--nseqs];
319 __initialise_multi_index()
320 __attribute__((always_inline));
322 __initialise_multi_index(size_t midx[], size_t arity)
325 for (size_t j = 1; j < arity; j++) {
332 __advance_multi_index_comb()
333 __attribute__((always_inline));
335 __advance_multi_index_comb(size_t idx[], size_t len, int arity)
339 for (i = arity-1; (i >= 0) && idx[i] >= len - arity + i; i--);
341 for (; ++i < arity; ) {
344 return (idx[i-1] < len);
348 __advance_multi_index_4()
349 __attribute__((always_inline));
351 __advance_multi_index_4(
352 size_t *midx[], size_t flen[], long int j /*nseqs*/, size_t arity[])
354 /* like __a_m_v_3(), also allowing for differently-sized families
355 * and multiplicities thereof, but for for combinatorial indexing,
356 * i.e. the order goes
357 * [1,2]->[1,3]->[2,3] for arity (., 3) */
359 if (LIKELY(__advance_multi_index_comb(midx[j], flen[j], arity[j]))) {
360 /* if there's more to come, bingo */
363 /* otherwise reinitialise the mindex we're currently shagging */
364 __initialise_multi_index(midx[j], arity[j]);
367 if (LIKELY(__advance_multi_index_comb(midx[j], flen[j], arity[j]))) {
370 /* otherwise reinitialise the mindex we're currently shagging */
371 __initialise_multi_index(midx[j], arity[j]);
375 if (LIKELY(__advance_multi_index_comb(
376 midx[j], flen[j], arity[j]))) {
379 /* otherwise reinitialise the mindex we're currently shagging */
380 __initialise_multi_index(midx[j], arity[j]);
386 /* This is the guts of several mapping functions.
387 Apply FUNCTION to each element of SEQUENCE, one by one,
388 storing the results into elements of VALS, a C vector of Lisp_Objects.
389 LENI is the length of VALS, which should also be the length of SEQUENCE.
391 If VALS is a null pointer, do not accumulate the results. */
394 mapcar1(size_t leni, Lisp_Object * vals,
395 Lisp_Object function, Lisp_Object sequence)
405 memset(vals, 0, leni * sizeof(Lisp_Object));
409 if (LISTP(sequence)) {
410 /* A devious `function' could either:
411 - insert garbage into the list in front of us, causing XCDR to crash
412 - amputate the list behind us using (setcdr), causing the remaining
413 elts to lose their GCPRO status.
415 if (vals != 0) we avoid this by copying the elts into the
416 `vals' array. By a stroke of luck, `vals' is exactly large
417 enough to hold the elts left to be traversed as well as the
418 results computed so far.
420 if (vals == 0) we don't have any free space available and
421 don't want to eat up any more stack with alloca().
422 So we use EXTERNAL_LIST_LOOP_3_NO_DECLARE and GCPRO the tail. */
425 Lisp_Object *val = vals;
428 LIST_LOOP_2(elt, sequence) {
432 for (i = 0; i < leni; i++) {
434 vals[i] = Ffuncall(2, args);
437 Lisp_Object elt, tail;
438 EMACS_INT len_unused;
439 struct gcpro ngcpro1;
444 EXTERNAL_LIST_LOOP_4_NO_DECLARE(elt, sequence,
454 } else if (VECTORP(sequence)) {
455 Lisp_Object *objs = XVECTOR_DATA(sequence);
457 for (size_t i = 0; i < leni; i++) {
459 result = Ffuncall(2, args);
464 } else if (DLLISTP(sequence)) {
465 dllist_item_t elt = XDLLIST_FIRST(sequence);
467 for (size_t i = 0; elt; i++) {
468 args[1] = (Lisp_Object)elt->item;
469 result = Ffuncall(2, args);
475 } else if (STRINGP(sequence)) {
476 /* The string data of `sequence' might be relocated during GC. */
477 Bytecount slen = XSTRING_LENGTH(sequence);
480 int speccount = specpdl_depth();
483 XMALLOC_ATOMIC_OR_ALLOCA(p, slen, Bufbyte);
486 memcpy(p, XSTRING_DATA(sequence), slen);
489 args[1] = make_char(charptr_emchar(p));
491 result = Ffuncall(2, args);
496 XMALLOC_UNBIND(p, slen, speccount);
497 } else if (BIT_VECTORP(sequence)) {
498 Lisp_Bit_Vector *v = XBIT_VECTOR(sequence);
500 for (size_t i = 0; i < leni; i++) {
501 args[1] = make_int(bit_vector_bit(v, i));
502 result = Ffuncall(2, args);
508 /* unreachable, since Flength (sequence) did not get an error */
518 list_map_inplace(Lisp_Object function, Lisp_Object list)
521 struct gcpro gcpro1, gcpro2;
522 Lisp_Object elt = list;
524 GCPRO2(function, list);
529 XCAR(elt) = Ffuncall(2, args);
536 vector_map_inplace(Lisp_Object function, Lisp_Object tuple)
538 Lisp_Object *objs = XVECTOR_DATA(tuple);
540 size_t i, len = XVECTOR_LENGTH(tuple);
541 struct gcpro gcpro1, gcpro2, gcpro3;
543 GCPRO2n(function, tuple, args, countof(args));
546 for (i = 0; i < len; i++) {
548 *objs++ = Ffuncall(2, args);
555 string_map_inplace(Lisp_Object function, Lisp_Object string)
558 size_t len = XSTRING_LENGTH(string);
559 Bufbyte *p = XSTRING_DATA(string);
560 Bufbyte *end = p + len;
561 struct gcpro gcpro1, gcpro2, gcpro3;
563 GCPRO2n(function, string, args, countof(args));
567 args[1] = make_char(charptr_emchar(p));
568 args[1] = Ffuncall(2, args);
570 set_charptr_emchar(p, XCHAR(args[1]));
572 set_charptr_emchar(p, '\000');
580 bit_vector_map_inplace(Lisp_Object function, Lisp_Object bitvec)
582 Lisp_Bit_Vector *v = XBIT_VECTOR(bitvec);
584 struct gcpro gcpro1, gcpro2, gcpro3;
585 size_t i, len = bit_vector_length(XBIT_VECTOR(bitvec));
587 GCPRO2n(function, bitvec, args, countof(args));
590 for (i = 0; i < len; i++) {
591 args[1] = make_int(bit_vector_bit(v, i));
592 args[1] = Ffuncall(2, args);
593 if ((NUMBERP(args[1]) && ent_unrel_zerop(args[1])) ||
595 set_bit_vector_bit(v, i, 0);
597 set_bit_vector_bit(v, i, -1);
604 * The mapfam approach
607 /* auxiliary stuff */
609 __fam_size(Lisp_Object fam)
611 return seq_length((seq_t)(void*)fam);
615 __nfam_min_size(Lisp_Object fam[], size_t nfam)
619 /* catch the horst-case */
620 if (UNLIKELY(nfam == 0)) {
623 /* otherwise unroll a little */
624 res = __fam_size(fam[0]);
625 for (size_t j = 1; j < nfam; j++) {
626 size_t tmp = __fam_size(fam[j]);
635 __nfam_min_size_a(Lisp_Object fam[], size_t nfam, size_t arity[])
639 /* catch the horst-case */
640 if (UNLIKELY(nfam == 0)) {
643 /* otherwise unroll a little */
644 res = __fam_size(fam[0]) / arity[0];
645 for (size_t j = 1; j < nfam; j++) {
646 size_t tmp = __fam_size(fam[j]) / arity[j];
655 __nfam_cart_sum_size(size_t *sum, size_t *cart, size_t nfsz[],
656 Lisp_Object fam[], size_t nfam)
658 /* computes the size of the cartesian set and the maximum size of
659 * the union set, returns the sum of cartesian and union, and puts
660 * intermediately computed family sizes int nfsz */
662 /* catch the horst-case */
663 if (UNLIKELY(nfam == 0)) {
666 } else if (nfam == 1) {
667 /* another horst case
668 * just 1 fam should always call fam_size() */
669 return *sum = *cart = nfsz[0] = __fam_size(fam[0]);
671 /* otherwise unroll a little */
672 nfsz[0] = __fam_size(fam[0]);
673 nfsz[1] = __fam_size(fam[1]);
674 *sum = nfsz[0] + nfsz[1];
675 *cart = nfsz[0] * nfsz[1];
676 for (size_t j = 2; j < nfam; j++) {
677 nfsz[j] = __fam_size(fam[j]);
685 __my_pow_insitu(size_t *base, size_t expon)
687 /* improve me and put me somewhere else, ase-arith.h? */
688 for (size_t i = 1, b = *base; i < expon; i++) {
695 __my_pow_explicit(size_t base, size_t expon)
697 /* improve me and put me somewhere else, ase-arith.h? */
699 for (size_t i = 1; i < expon; i++) {
706 __nfam_cart_sum_size_a(size_t *sum, size_t *cart, size_t *midxsz,
708 Lisp_Object fam[], size_t nfam, size_t arity[])
710 /* computes the size of the cartesian set (put into *cart), the maximum
711 * size of the union set (returned) and the multiplicity of the
712 * multi-index (which is the cross sum of the arity array) returns the
713 * sum of cartesian and union, and puts intermediately computed family
716 /* catch the horst-case */
717 if (UNLIKELY(nfam == 0)) {
718 *sum = *cart = *midxsz = 0;
720 } else if (nfam == 1) {
721 /* another horst case
722 * just 1 fam should always call fam_size() */
723 *sum = *cart = nfsz[0] = __fam_size(fam[0]);
724 __my_pow_insitu(cart, *midxsz = arity[0]);
727 /* otherwise unroll a little */
728 nfsz[0] = __fam_size(fam[0]);
729 nfsz[1] = __fam_size(fam[1]);
730 *sum = nfsz[0] + nfsz[1];
731 *midxsz = arity[0] + arity[1];
732 *cart = __my_pow_explicit(nfsz[0], arity[0]) *
733 __my_pow_explicit(nfsz[1], arity[1]);
734 for (size_t j = 2; j < nfam; j++) {
735 nfsz[j] = __fam_size(fam[j]);
738 *cart *= __my_pow_explicit(nfsz[j], arity[j]);
744 __nfam_comb_sum_size_a(size_t *sum, size_t *comb, size_t *midxsz,
746 Lisp_Object fam[], size_t nfam, size_t arity[])
748 /* computes the size of the cartesian set (returned), the maximum size of
749 * the union set and the multiplicity of the multi-index (which is the
750 * cross sum of the arity array) returns the sum of cartesian and union,
751 * and puts intermediately computed family sizes into nfsz */
753 /* catch the horst-case */
754 if (UNLIKELY(nfam == 0)) {
755 *sum = *comb = *midxsz = 0;
757 } else if (nfam == 1) {
758 /* another horst case
759 * just 1 fam should always call fam_size() */
760 *sum = nfsz[0] = __fam_size(fam[0]);
761 *comb = __ncombinations(nfsz[0], *midxsz = arity[0]);
764 /* otherwise unroll a little */
765 nfsz[0] = __fam_size(fam[0]);
766 nfsz[1] = __fam_size(fam[1]);
767 *sum = nfsz[0] + nfsz[1];
768 *midxsz = arity[0] + arity[1];
769 *comb = __ncombinations(nfsz[0], arity[0]) *
770 __ncombinations(nfsz[1], arity[1]);
771 for (size_t j = 2; j < nfam; j++) {
772 nfsz[j] = __fam_size(fam[j]);
775 *comb *= __ncombinations(nfsz[j], arity[j]);
781 __nfam_perm_sum_size(size_t *sum, size_t *cart, size_t *perm, size_t nfsz[],
782 Lisp_Object fam[], size_t nfam)
784 /* computes the size of the cartesian set and the maximum size of
785 * the union set, returns the sum of cartesian and union, and puts
786 * intermediately computed family sizes int nfsz */
788 /* catch the horst-case */
789 if (UNLIKELY(nfam == 0)) {
790 *sum = *cart = *perm = 0;
792 } else if (nfam == 1) {
793 /* another horst case
794 * just 1 fam should always call fam_size() */
796 return *sum = *cart = nfsz[0] = __fam_size(fam[0]);
798 /* otherwise unroll a little */
799 nfsz[0] = __fam_size(fam[0]);
800 nfsz[1] = __fam_size(fam[1]);
801 *sum = nfsz[0] + nfsz[1];
802 *cart = nfsz[0] * nfsz[1];
803 for (size_t j = 2; j < nfam; j++) {
804 nfsz[j] = __fam_size(fam[j]);
808 *cart *= (*perm = __factorial(nfam));
813 __nfam_perm_sum_size_a(size_t *sum, size_t *var, size_t *perm, size_t *midxsz,
815 Lisp_Object fam[], size_t nfam, size_t arity[])
817 /* computes the size of the cartesian set (returned), the maximum size of
818 * the union set and the multiplicity of the multi-index (which is the
819 * cross sum of the arity array) returns the sum of cartesian and union,
820 * and puts intermediately computed family sizes into nfsz */
822 /* catch the horst-case */
823 if (UNLIKELY(nfam == 0)) {
824 *sum = *var = *perm = *midxsz = 0;
826 } else if (nfam == 1) {
827 /* another horst case
828 * just 1 fam should always call fam_size() */
829 *sum = nfsz[0] = __fam_size(fam[0]);
830 *perm = __factorial(*midxsz = arity[0]);
831 *var = __ncombinations(nfsz[0], arity[0]) * *perm;
834 /* otherwise unroll a little */
835 nfsz[0] = __fam_size(fam[0]);
836 nfsz[1] = __fam_size(fam[1]);
837 *sum = nfsz[0] + nfsz[1];
838 *midxsz = arity[0] + arity[1];
839 *var = __ncombinations(nfsz[0], arity[0]) *
840 __ncombinations(nfsz[1], arity[1]);
841 for (size_t j = 2; j < nfam; j++) {
842 nfsz[j] = __fam_size(fam[j]);
845 *var *= __ncombinations(nfsz[j], arity[j]);
847 /* we computed the number of combinations above, now to compute
848 * the number of variations we have to apply the S_{midxsz} on
849 * each element, hence we simply multiply with the factorial of
850 * midxsz (which is the cross sum of all arities) */
851 *var *= (*perm = __factorial(*midxsz));
856 * dedicated subroutines for 2-combs and 3-combs because they are soooo easy
859 __2comb(Lisp_Object tgts[], size_t SXE_UNUSED(tlen),
860 Lisp_Object supp[], size_t slen,
861 Lisp_Object fun, glue_f gf)
863 /* assumes that everything is gcpro'd properly */
864 Lisp_Object arr[3] = {fun, Qnil, Qnil};
866 if (LIKELY(!NILP(fun) && gf == NULL)) {
867 for (size_t i = 0, l = 0; i < slen-1; i++) {
868 for (size_t j = i+1; j < slen; j++) {
869 /* set up the array */
873 tgts[l++] = Ffuncall(countof(arr), arr);
876 } else if (LIKELY(!NILP(fun))) {
877 for (size_t i = 0, l = 0; i < slen-1; i++) {
878 for (size_t j = i+1; j < slen; j++) {
879 /* set up the array */
883 arr[1] = gf(2, &arr[1]);
885 tgts[l++] = Ffuncall(2, arr);
889 glue_f tgf = gf ? gf : Flist;
890 for (size_t i = 0, l = 0; i < slen-1; i++) {
891 for (size_t j = i+1; j < slen; j++) {
892 /* set up the array */
896 tgts[l++] = tgf(2, &arr[1]);
904 __3comb(Lisp_Object tgts[], size_t SXE_UNUSED(tlen),
905 Lisp_Object supp[], size_t slen,
906 Lisp_Object fun, glue_f gf)
908 /* assumes that everything is gcpro'd properly */
909 Lisp_Object arr[4] = {fun, Qnil, Qnil, Qnil};
911 if (LIKELY(!NILP(fun) && gf == NULL)) {
912 for (size_t i = 0, l = 0; i < slen-2; i++) {
913 for (size_t j = i+1; j < slen-1; j++) {
914 for (size_t k = j+1; k < slen; k++) {
915 /* set up the array */
920 tgts[l++] = Ffuncall(countof(arr), arr);
924 } else if (LIKELY(!NILP(fun))) {
925 for (size_t i = 0, l = 0; i < slen-2; i++) {
926 for (size_t j = i+1; j < slen-1; j++) {
927 for (size_t k = j+1; k < slen; k++) {
928 /* set up the array */
933 arr[1] = gf(3, &arr[1]);
935 tgts[l++] = Ffuncall(2, arr);
940 glue_f tgf = gf ? gf : Flist;
941 for (size_t i = 0, l = 0; i < slen-2; i++) {
942 for (size_t j = i+1; j < slen-1; j++) {
943 for (size_t k = j+1; k < slen; k++) {
944 /* set up the array */
949 tgts[l++] = tgf(3, &arr[1]);
958 __ncomb(Lisp_Object tgts[], size_t tlen,
959 Lisp_Object supp[], size_t slen,
960 Lisp_Object fun, glue_f gf,
963 /* assumes that everything is gcpro'd properly */
966 Lisp_Object fc[arity+1], *v = &fc[1];
969 memset(idx, 0, arity*sizeof(long int));
970 memset(v, 0, arity*sizeof(Lisp_Object));
973 /* special case slen == arity */
974 if (UNLIKELY(slen == arity)) {
975 if (LIKELY(!NILP(fun) && gf == NULL)) {
976 tgts[0] = Ffuncall(slen, supp);
977 } else if (LIKELY(!NILP(fun))) {
978 v[0] = gf(slen, supp);
979 tgts[0] = Ffuncall(2, fc);
981 glue_f tgf = gf ? gf : Flist;
982 tgts[0] = tgf(slen, supp);
987 /* setup, partially unrolled */
990 for (size_t i = 2; i < arity; i++) {
994 if (LIKELY(!NILP(fun) && gf == NULL)) {
998 for (size_t i = 2; i < arity; i++) {
1002 tgts[l++] = Ffuncall(countof(fc), fc);
1003 /* increment, fooking back'n'forth-loop-based
1005 (void)__advance_multi_index_comb(idx, slen, arity);
1007 } else if (LIKELY(!NILP(fun))) {
1009 v[0] = supp[idx[0]];
1010 v[1] = supp[idx[1]];
1011 for (size_t i = 2; i < arity; i++) {
1012 v[i] = supp[idx[i]];
1015 v[0] = gf(arity, v);
1017 tgts[l++] = Ffuncall(2, fc);
1018 /* increment, fooking back'n'forth-loop-based
1020 (void)__advance_multi_index_comb(idx, slen, arity);
1023 glue_f tgf = gf ? gf : Flist;
1025 v[0] = supp[idx[0]];
1026 v[1] = supp[idx[1]];