Rev 85847 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** R : A Computer Language for Statistical Data Analysis* Copyright (C) 2001--2024 The R Core Team.** This header file is free software; you can redistribute it and/or modify* it under the terms of the GNU Lesser General Public License as published by* the Free Software Foundation; either version 2.1 of the License, or* (at your option) any later version.** This file is part of R. R is distributed under the terms of the* GNU General Public License, either Version 2, June 1991 or Version 3,* June 2007. See doc/COPYRIGHTS for details of the copyright status of R.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU Lesser General Public License for more details.** You should have received a copy of the GNU Lesser General Public License* along with this program; if not, a copy is available at* https://www.R-project.org/Licenses/*//*Macros to help defining vectorized functions with proper recyclingand periodic interrupt checks.*/#ifndef R_EXT_ITERMACROS_H_#define R_EXT_ITERMACROS_H_#define LOOP_WITH_INTERRUPT_CHECK(LOOP, ncheck, n, ...) do { \for (size_t __intr_threshold__ = ncheck; \TRUE; \__intr_threshold__ += ncheck) { \size_t __intr_end__ = n < __intr_threshold__ ? \n : __intr_threshold__; \LOOP(__intr_end__, __VA_ARGS__); \if (__intr_end__ == n) break; \else R_CheckUserInterrupt(); \} \} while (0)#define R_ITERATE_CORE(n, i, loop_body) do { \for (; i < n; ++i) { loop_body } \} while (0)#define R_ITERATE(n, i, loop_body) do { \i = 0; \R_ITERATE_CORE(n, i, loop_body); \} while (0)#define R_ITERATE_CHECK(ncheck, n, i, loop_body) do { \i = 0; \LOOP_WITH_INTERRUPT_CHECK(R_ITERATE_CORE, ncheck, n, i, loop_body); \} while (0)#define MOD_ITERATE1_CORE(n, n1, i, i1, loop_body) do { \for (; i < n; \i1 = (++i1 == n1) ? 0 : i1, \++i) { \loop_body \} \} while (0)#define MOD_ITERATE1(n, n1, i, i1, loop_body) do { \i = i1 = 0; \MOD_ITERATE1_CORE(n, n1, i, i1, loop_body); \} while (0)#define MOD_ITERATE1_CHECK(ncheck, n, n1, i, i1, loop_body) do { \i = i1 = 0; \LOOP_WITH_INTERRUPT_CHECK(MOD_ITERATE1_CORE, ncheck, n, \n1, i, i1, loop_body); \} while (0)#define MOD_ITERATE2_CORE(n, n1, n2, i, i1, i2, loop_body) do { \for (; i < n; \i1 = (++i1 == n1) ? 0 : i1, \i2 = (++i2 == n2) ? 0 : i2, \++i) { \loop_body \} \} while (0)#define MOD_ITERATE2(n, n1, n2, i, i1, i2, loop_body) do { \i = i1 = i2 = 0; \MOD_ITERATE2_CORE(n, n1, n2, i, i1, i2, loop_body); \} while (0)#define MOD_ITERATE2_CHECK(ncheck, n, n1, n2, i, i1, i2, loop_body) do { \i = i1 = i2 = 0; \LOOP_WITH_INTERRUPT_CHECK(MOD_ITERATE2_CORE, ncheck, n, \n1, n2, i, i1, i2, loop_body); \} while (0)#define MOD_ITERATE MOD_ITERATE2#define MOD_ITERATE_CORE MOD_ITERATE2_CORE#define MOD_ITERATE_CHECK MOD_ITERATE2_CHECK#define MOD_ITERATE3_CORE(n, n1, n2, n3, i, i1, i2, i3, loop_body) do { \for (; i < n; \i1 = (++i1 == n1) ? 0 : i1, \i2 = (++i2 == n2) ? 0 : i2, \i3 = (++i3 == n3) ? 0 : i3, \++i) { \loop_body \} \} while (0)#define MOD_ITERATE3(n, n1, n2, n3, i, i1, i2, i3, loop_body) do { \i = i1 = i2 = i3 = 0; \MOD_ITERATE3_CORE(n, n1, n2, n3, i, i1, i2, i3, loop_body); \} while (0)#define MOD_ITERATE3_CHECK(ncheck, n, n1, n2, n3, i, i1, i2, i3, loop_body) \do { \i = i1 = i2 = i3 = 0; \LOOP_WITH_INTERRUPT_CHECK(MOD_ITERATE3_CORE, ncheck, n, \n1, n2, n3, i, i1, i2, i3, loop_body); \} while (0)#define MOD_ITERATE4_CORE(n, n1, n2, n3, n4, i, i1, i2, i3, i4, loop_body) \do { \for (; i < n; \i1 = (++i1 == n1) ? 0 : i1, \i2 = (++i2 == n2) ? 0 : i2, \i3 = (++i3 == n3) ? 0 : i3, \i4 = (++i4 == n4) ? 0 : i4, \++i) { \loop_body \} \} while (0)#define MOD_ITERATE4(n, n1, n2, n3, n4, i, i1, i2, i3, i4, loop_body) do { \i = i1 = i2 = i3 = i4 = 0; \MOD_ITERATE4_CORE(n, n1, n2, n3, n4, i, i1, i2, i3, i4, loop_body); \} while (0)#define MOD_ITERATE4_CHECK(ncheck, n, n1, n2, n3, n4, i, i1, i2, i3, i4, \loop_body) \do { \i = i1 = i2 = i3 = i4 = 0; \LOOP_WITH_INTERRUPT_CHECK(MOD_ITERATE4_CORE, ncheck, n, \n1, n2, n3, n4, \i, i1, i2, i3, i4, loop_body); \} while (0)#define MOD_ITERATE5_CORE(n, n1, n2, n3, n4, n5, i, i1, i2, i3, i4, i5, \loop_body) \do { \for (; i < n; \i1 = (++i1 == n1) ? 0 : i1, \i2 = (++i2 == n2) ? 0 : i2, \i3 = (++i3 == n3) ? 0 : i3, \i4 = (++i4 == n4) ? 0 : i4, \i5 = (++i5 == n5) ? 0 : i5, \++i) { \loop_body \} \} while (0)#define MOD_ITERATE5(n, n1, n2, n3, n4, n5, i, i1, i2, i3, i4, i5, loop_body) \do { \i = i1 = i2 = i3 = i4 = i5 = 0; \MOD_ITERATE5_CORE(n, n1, n2, n3, n4, n5, i, i1, i2, i3, i4, i5, \loop_body); \} while (0)#define MOD_ITERATE5_CHECK(ncheck, n, n1, n2, n3, n4, n5, \i, i1, i2, i3, i4, i5, \loop_body) \do { \i = i1 = i2 = i3 = i4 = i5 = 0; \LOOP_WITH_INTERRUPT_CHECK(MOD_ITERATE5_CORE, ncheck, n, \n1, n2, n3, n4, n5, \i, i1, i2, i3, i4, i5, loop_body); \} while (0)#define GET_REGION_BUFSIZE 512#define GET_REGION_PTR(x, i, n, buf, type) \(ALTREP(x) == 0 ? type##0(x) + (i) : (type##_GET_REGION(x, i, n, buf), buf))#define ITERATE_BY_REGION_PARTIAL0(sx, px, idx, nb, etype, vtype, \strt, nfull, expr) do { \etype __ibr_buf__[GET_REGION_BUFSIZE]; \R_xlen_t __ibr_n__ = strt + nfull; \R_xlen_t nb; \for (R_xlen_t idx = strt; idx < __ibr_n__; idx += nb) { \nb = __ibr_n__ - idx > GET_REGION_BUFSIZE ? \GET_REGION_BUFSIZE : __ibr_n__ - idx; \etype *px = (etype *) GET_REGION_PTR(sx, idx, nb, \__ibr_buf__, vtype); \expr \} \} while (0)#define ITERATE_BY_REGION_PARTIAL_REV0(sx, px, idx, nb, etype, vtype, \strt, nfull, expr) do { \etype __ibr_buf__[GET_REGION_BUFSIZE]; \R_xlen_t __ibr_n__ = strt + nfull; \R_xlen_t nb = nfull > GET_REGION_BUFSIZE ? \GET_REGION_BUFSIZE : nfull; \for (R_xlen_t idx = __ibr_n__ - nb; nb > 0; idx -= nb) { \etype *px = (etype *) GET_REGION_PTR(sx, idx, nb, \__ibr_buf__, vtype); \expr \nb = idx - strt > GET_REGION_BUFSIZE ? \GET_REGION_BUFSIZE : idx - strt; \} \} while (0)#define ITERATE_BY_REGION_PARTIAL(sx, px, idx, nb, etype, vtype, \strt, nfull, expr) do { \const etype *px = (etype *) DATAPTR_OR_NULL(sx); \if (px != NULL) { \R_xlen_t idx = strt; \(void) idx; /* variable may be unused in expr */ \R_xlen_t nb = nfull; \px += strt; \if (nb > 0) { \expr \} \} \else ITERATE_BY_REGION_PARTIAL0(sx, px, idx, nb, etype, vtype, \strt, nfull, expr); \} while (0)#define ITERATE_BY_REGION_PARTIAL_REV(sx, px, idx, nb, etype, vtype, \strt, nfull, expr) do { \const etype *px = (etype *) DATAPTR_OR_NULL(sx); \if (px != NULL) { \R_xlen_t idx = strt; \(void) idx; /* variable may be unused in expr */ \R_xlen_t nb = nfull; \px += strt; \if (nb > 0) { \expr \} \} \else ITERATE_BY_REGION_PARTIAL_REV0(sx, px, idx, nb, etype, \vtype, strt, nfull, expr); \} while (0)#define ITERATE_BY_REGION(sx, px, idx, nb, etype, vtype, expr) do { \ITERATE_BY_REGION_PARTIAL(sx, px, idx, nb, etype, vtype, \0, XLENGTH(sx), expr); \} while (0)/* probably no one was using this but it was a declared part of the APIso leave it in out of an overabundance of caution */#define ITERATE_BY_REGION0(sx, px, idx, nb, etype, vtype, expr) do { \ITERATE_BY_REGION_PARTIAL0(sx, px, idx, nb, etype, vtype, \0, XLENGTH(sx), expr); \} while (0)#endif /* R_EXT_ITERMACROS_H_ */