You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
copilot-c99: Fix issue in C99 implementation of signum. Refs #278.
copilot-c99's translation of the function signum to C99 differs from the
meaning of the same function in the interpreter. The C99 backend uses
the function copysign, whose meaning differs from Haskell's signum.
For example, as evaluated by the interpreter, signum 0 returns 0, but
the C99 code generated for it (which executes copysign(1.0, 0)), returns
1. Moreover, when dealing with floating-point numbers, signum (-0) and
signum NaN return -0 and NaN, respectively, in the interpreter, but the
C99-based implementation returns -1.0 and ±1.0 (depending on the sign
bit of the NaN), respectively.
The meaning of all Copilot constructs should be consistent between the
interpreter and all backends.
This commit replaces the `copysign`-based implementation such that
`signum e` now returns `e > 0 ? 1 : (e < 0 ? -1 : e)`. This new
implementation follows the definition of signum in Haskell's base,
including for cases where `e` is `±0` or `NaN`.
It is possible to reproduce the error, and check the fix, by comparing
the output of the compiled code and the interpreter for a stream with
signum. For example, given the following specification:
```
{-# LANGUAGE CPP #-}
{-# LANGUAGE NoImplicitPrelude #-}
-- | An example of a specification using the 'signum' function.
module Main where
import Data.List (genericLength)
import Copilot.Compile.C99
import Language.Copilot
nums :: [Int32]
nums = [-2, -1, 0, 1, 2]
stream :: Stream Int32
stream = extern "stream" (Just nums)
spec :: Spec
spec =
trigger "func" true [arg (signum stream)]
main :: IO ()
main = do
spec' <- reify spec
#ifdef INTERPRET
csv (genericLength nums) spec
#else
compile "signum" spec'
#endif
```
with -DINTERPRET, the program will print:
```
$ cabal v1-exec -- runhaskell -DINTERPRET Signum.hs
Note: CSV format does not output observers.
#
func,-1
#
func,-1
#
func,0
#
func,1
#
func,1
```
The generated C99 can be executed with the following main:
```
#include <stdint.h>
#include <stdio.h>
#include "signum.h"
int32_t nums[5] = { -2, -1, 0, 1, 2 };
int32_t stream;
void func (int32_t sign)
{
printf ("%d\n", sign);
}
int main () {
int i = 0;
for (i=0; i<5; i++)
{
stream = nums[i];
step();
}
return 0;
}
```
And it will print:
```
-1
-1
1
1
1
```
so long as the bug is present. The new implementation corrects that
behavior to print, instead, the same values produced by the interpreter.
Co-authored-by: Ivan Perez <ivan.perezdominguez@nasa.gov>
0 commit comments