我编写了一个使用 IIR 滤波器和直方图执行数学计算的代码。该代码应该是 100% 可移植的,是可重入的,不进行系统调用(但 memset),具有双精度常量和初始化变量,并且仅包括 math.h、string.h、stdint.h 和 stddef.h。它已在嵌入式处理器中运行。
使用 Windows MinGW GCC 或 Borland C++ 编译和运行代码时,它将通过所有单元测试。这不会发生在 Linux64 GCC 平台上。进一步的调查表明,该算法变得轻微不稳定,输出值不会收敛到稳定的结果,相反,结果会慢慢趋于无穷大,因此其中一个测试会失败。
大多数代码使用双精度浮点数,在某些变量中也使用单精度。
我需要关于如何解决这个问题的帮助,我必须保证代码的完全可移植性,而且我不知道去哪里找。另外,代码足够大,可以在这里发布,所以,如果你能指出我会遵循的方向。
这是 Linux 上模块的编译行:
gcc -O3 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/flickerModule.d" -MT"src/flickerModule.d" -o "src/flickerModule.o" "../src/flickerModule.c"
这是 Windows 上模块的编译行:
gcc -O0 -g3 -Wall -c -fmessage-length=0 -o src\flickerModule.o ..\src\flickerModule.c
这里我展示了代码的所有依赖:
fanl@fanl-STI:~/WorkFelipe/Codigos/re7k_eclipsewkspace/flicker_unittest/src$ grep -H -n -E 'mem|sqrt|floor' flickerModule.c
flickerModule.c:76: memset(filt, 0x00, sizeof(struct s_filter));
flickerModule.c:81: memset(filt, 0x00, sizeof(struct s_filter));
flickerModule.c:89: memset(&histo->buf, 0x00, sizeof(uint32_t) * NUM_CLASSES);
flickerModule.c:162: return (floorf(x + 0.5));
flickerModule.c:189: memset(&histn, 0x00, sizeof(float) * NUM_CLASSES);
flickerModule.c:262: hp->Urms_meio_ciclo = sqrt(hp->Acc_Urms_meio_ciclo / NUM_AMOSTRAS_MEIO_CICLO_60Hz);
flickerModule.c:370: return (sqrtf(saida));
flickerModule.c:393: p->GanhoNormalizaEntradaFlickerMeter = 1.0 / (p->halfPeriod.Urms_meio_ciclo * sqrt(2));
flickerModule.c:419: dbg->Prms = sqrt(dbg->Acc_Prms / (NUM_AMOSTRAS_1MIN / FATOR_DOWN1));