多维循环 [英] Multi dimentionnal for loop

查看:39
本文介绍了多维循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有简单的方法可以将其转换

Is there a simple way to convert this

for (int i=0; i < 31; i++)
    for (int j=0; j < 74; j++)
        for (int k=1; k < 12; k++)
            for (int l=13; l < 15; l++)
                ...

简单一点

mfor (int start[]={0,0,1,13}; int max[]={31,74,12,15}) {
    printf("%i %i\n", start[1], start[3]);
}

是否有宏或类似插件的内容?

Is there a macro or a plugin-like ?

此循环可以迭代思想Tensor(如图像)来执行Tensor Convolution或Pooling之类的操作.任何尺寸(可以大于4)

This loop can iterate thought Tensor (like an image) to do stuff like Tensor Convolution or Pooling. In any dimentions (can be more than 4)

或者如何向C添加一些语法.我已经实现了 mfor 循环.因为 for 循环实际上是 while 循环.

Or how to add some syntax to C. I have the implementation for mfor loop. Because for loop is in real a while loop.

推荐答案

没有简单的方法,但是您可以实现类似迭代器的类型,该类型在给定范围内在 n 范围内生成笛卡尔乘积.

There's no simple way, but you could implement an iterator-like type that generates the Cartesian product over n given ranges:

enum {
    MAX = 8
};

typedef struct Combinator Combinator;

struct Combinator {
    size_t index;       // running index of generated numbers
    size_t n;           // number of dimensions
    int data[MAX];      // current combination
    int start[MAX];     // lower and ...
    int end[MAX];       // .. exclusive upper limits
};

/*
 *      Adds a dimensin with valid range [start, end) to the combinator
 */
void combo_add(Combinator *c, int start, int end)
{
    if (c->n < MAX && start < end) {
        c->data[c->n] = start;
        c->start[c->n] = start;
        c->end[c->n] = end;
        c->n++;
    }
}

/*
 *      Reset the combinator to the lower limits
 */
void combo_reset(Combinator *c)
{
    c->index = 0;
    memcpy(c->data, c->start, sizeof(c->start));
}

/*
 *      Get the next comnination in c->data. Returns 1 if there
 *      is a next combination, 0 otherwise.
 */
int combo_next(Combinator *c)
{
    size_t i = 0;
    
    if (c->index++ == 0) return 1;
    
    do {
        c->data[i]++;
        if(c->data[i] < c->end[i]) return 1;
        c->data[i] = c->start[i];
        i++;
    } while (i < c->n);
    
    return 0;
}

这实现了一个类似里程表的计数器:它增加了第一个计数器.如果溢出,它将重置并递增下一个计数器,并根据需要移至下一个计数器.如果最后一个计数器溢出,组合的生成将停止.(第一个组合的索引有些混乱,因此您可以从 while 循环的循环条件中控制所有内容.可能有一种更优雅的解决方法.)

This implements an odometer-like counter: It increments the first counter. If it overflows, it resets it and increments the next counter, moving to te next counter as needed. If the last counter overflows, the generation of combinations stops. (There's a bit of a kludge with the index for the first combination so that you can control everything from the loop condition of a while loop. There's probably a more elegant way to solve this.)

像这样使用组合器:

Combinator combo = {0};      // Must initialize with zero

combo_add(&combo, 0, 3);
combo_add(&combo, 10, 12);
combo_add(&combo, 4, 7);

while (combo_next(&combo)) {
    printf("%4zu: [%d, %d, %d]\n", combo.index,
        combo.data[0], combo.data[1], combo.data[2]);
} 

此组合器只能使用一次:创建它,设置范围,然后用尽所有组合.

This combiinator is designed to use only once: Create it, set up the ranges, then exhaust the combinations.

如果您中断,那么组合器将保持其状态,以便在中断时继续调用 combo_next .您可以通过调用 combo_reset 重新开始.(这有点像从文件中读取:使用它们的通常方法是读取所有内容,但是您可以倒退.)

If you break out of the loop, the combinator retains its state, so that further call to combo_next continue where you broke off. You can start afresh by calling combo_reset. (This is a bit like reading from a file: The usual way to use them is to read everything, but you can rewind.)

这篇关于多维循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆