Using the Modulo Operator with the Embedded Coder to generate MISRA compliant C

Hello!
I am attempting to use the Embedded Coder to generate MISRA compliant C code but I'm having issues resolving all instances of MISRA violation D1.1 becuase the embedded coder is generating eqaulity/inequality operators on floating point numbers.
The majority of these violations can be traced to the usage of the mod operator. It looks like the Embedded coder will generate C code that contains 2 checks for a double equaling 0 every time I write a MATLAB function that contains mod.
An example is this MATALB function:
diff = mod((a1-a2+pi), 2*pi)
Which then generates this C code:
double mod_BPFafXTN(double x)
{
double r;
if (x == 0.0) {
r = 0.0;
} else {
bool rEQ0;
r = fmod(x, 6.2831853071795862);
rEQ0 = (r == 0.0);
if (!rEQ0) {
double q;
q = fabs(x / 6.2831853071795862);
rEQ0 = (fabs(q - floor(q + 0.5)) <= (2.2204460492503131E-16 * q));
}
if (rEQ0) {
r = 0.0;
} else if (x < 0.0) {
r += 6.2831853071795862;
} else {
/* no actions */
}
}
return r;
}
The problem is these lines:
if (x == 0.0) {
&
rEQ0 = (r == 0.0);
Both of these checks seem fairly redundant as you're just avoiding 0 / x which wouldn't result in an exception anyway.
Mathworks does claim compliance with this rule so I'm wondering if I'm missing something but I have set the code generation configuration parameters as suggested https://uk.mathworks.com/help/ecoder/ug/misra-c2012-compliance-information-summary-tables.html
Does anyone have any experience with this issue?
Thanks!

1 Comment

We're looking at this issue now. I don't know of any option that will help. If the rem function meets your needs, you might prefer that.
double tryrem(double x)
{
double y;
if (rtIsNaN(x) || rtIsInf(x)) {
y = rtNaN;
} else {
y = fabs(x / 6.2831853071795862);
if (!(fabs(y - floor(y + 0.5)) > DBL_EPSILON * y)) {
y = 0.0 * x;
} else {
y = fmod(x, 6.2831853071795862);
}
}
return y;
}
but of course the behavior is different in some cases. Speaking of which, the code generated for the mod function is engineered to match MATLAB's edge case behaviors. The code you have shown is generated by specializing more general mod(x,y) code to the case where y is constant 2*pi. Before it was specialized the code was written to get these things right:
  1. mod(x,0) = x even if x = +inf or -inf. This differs from rem(inf,0) and rem(-inf,0), which both return nan.
  2. Behaviors with -0. mod([0,0,-0,-0],[0,-0,0,-0]) returns [0,-0,0,-0].
In this case y cannot be -0 or 0, either one, but x can still be -0 or +0. fmod(-0,2*pi) returns -0, whereas in MATLAB mod(-0,2*pi) it is defined to be +0. That's the purpose of the first comparison to 0, to get that right. It also avoids the wasted processing of calling fmod in that situation. The second is used with the "stretch" behavior involving eps and ultimately to ensure that we don't return -0, since 2*pi is positive.
These details are probably of little interest in your case, but unfortunately I don't think we have an option that would allow you to opt-in to variances with MATLAB behavior in the generated code solely for the sake of MISRA compliance.

Sign in to comment.

Answers (0)

Products

Release

R2023a

Asked:

on 5 Mar 2024

Commented:

on 23 Mar 2024

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!