gfortran 4.8.0 bug? Return type mismatch of function - gfortran

I just use gfortran 4.1.2 and gfortran 4.8.0 to compile the following simple code:
function foo(a, b) result(res)
integer, intent(in) :: a, b
integer res
res = a+b
end function foo
program test
integer a, b, c
c = foo(a, b)
end program test
gfortran 4.1.2 succeeds, but gfortran 4.8.0 gives the weird error:
test.F90:14.11:
c = foo(a, b)
1
Error: Return type mismatch of function 'foo' at (1) (REAL(4)/INTEGER(4))
Any idea?

There is a bug in your code, namely that you don't specify the return type of the function foo in the main program. Per the Fortran implicit typing rules it thus gets a type of default real.
You should (1) always use 'implicit none', furthermore if at all possible, (2) use modules or contained procedures thus giving you explicit interfaces.
The reason why GFortran 4.1 doesn't report this error is that older versions of GFortran always functioned in a 'procedure at a time' mode; thus the compiler is happily oblivious to any other functions in the same file. Newer versions work in 'whole file' mode (default since 4.6) where the compiler 'sees' all the procedures in a file at a time. This allows the compiler to catch errors such as the one in your code, and also provides some optimization opportunities.

Related

Missing entries in the stack trace in Erlang

When I compile the following module:
-module(x).
-export([inp/0]).
f(X) ->
g(X).
g(X) ->
error(X).
inp() ->
f(123).
And evaluate x:inp() I get the following output:
[{x,g,1,[{file,"x.erl"},{line,8}]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,689}]},
{erl_eval,try_clauses,8,[{file,"erl_eval.erl"},{line,919}]},
{shell,exprs,7,[{file,"shell.erl"},{line,686}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,642}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,627}]}]
Where did the calls to f and inp go? This behavior makes it significantly harder to track the causes of errors in my case, how can I get the full stacktrace?
I am using OTP24
This is because of Erlang's compiler optimization. The compiler deduces that, in this specific case, functions f() and inp() are only used to pass a number to function g() and they cannot be used for anything else, not even theoretically. So the compiler "optimizes them away" and de facto only compiles function g().

Creating a simple Rcpp package with dependency with other Rcpp package

I am trying to improve my loop computation speed by using foreach, but there is a simple Rcpp function I defined inside of this loop. I saved the Rcpp function as mproduct.cpp, and I call out the function simply using
sourceCpp("mproduct.cpp")
and the Rcpp function is a simple one, which is to perform matrix product in C++:
// [[Rcpp::depends(RcppArmadillo, RcppEigen)]]
#include <RcppArmadillo.h>
#include <RcppEigen.h>
// [[Rcpp::export]]
SEXP MP(const Eigen::Map<Eigen::MatrixXd> A, Eigen::Map<Eigen::MatrixXd> B){
Eigen::MatrixXd C = A * B;
return Rcpp::wrap(C);
}
So, the function in the Rcpp file is MP, referring to matrix product. I need to perform the following foreach loop (I have simplified the code for illustration):
foreach(j=1:n, .package='Rcpp',.noexport= c("mproduct.cpp"),.combine=rbind)%dopar%{
n=1000000
A<-matrix(rnorm(n,1000,1000))
B<-matrix(rnorm(n,1000,1000))
S<-MP(A,B)
return(S)
}
Since the size of matrix A and B are large, it is why I want to use foreach to alleviate the computational cost.
However, the above code does not work, since it provides me error message:
task 1 failed - "NULL value passed as symbol address"
The reason I added .noexport= c("mproduct.cpp") is to follow some suggestions from people who solved similar issues (Can't run Rcpp function in foreach - "NULL value passed as symbol address"). But somehow this does not solve my issue.
So I tried to install my Rcpp function as a library. I used the following code:
Rcpp.package.skeleton('mp',cpp_files = "<my working directory>")
but it returns me a warning message:
The following packages are referenced using Rcpp::depends attributes however are not listed in the Depends, Imports or LinkingTo fields of the package DESCRIPTION file: RcppArmadillo, RcppEigen
so when I tried to install my package using
install.packages("<my working directory>",repos = NULL,type='source')
I got the warning message:
Error in untar2(tarfile, files, list, exdir, restore_times) :
incomplete block on file
In R CMD INSTALL
Warning in install.packages :
installation of package ‘C:/Users/Lenovo/Documents/mproduct.cpp’ had non-zero exit status
So can someone help me out how to solve 1) using foreach with Rcpp function MP, or 2) install the Rcpp file as a package?
Thank you all very much.
The first step would be making sure that you are optimizing the right thing. For me, this would not be the case as this simple benchmark shows:
set.seed(42)
n <- 1000
A<-matrix(rnorm(n*n), n, n)
B<-matrix(rnorm(n*n), n, n)
MP <- Rcpp::cppFunction("SEXP MP(const Eigen::Map<Eigen::MatrixXd> A, Eigen::Map<Eigen::MatrixXd> B){
Eigen::MatrixXd C = A * B;
return Rcpp::wrap(C);
}", depends = "RcppEigen")
bench::mark(MP(A, B), A %*% B)[1:5]
#> # A tibble: 2 x 5
#> expression min median `itr/sec` mem_alloc
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt>
#> 1 MP(A, B) 277.8ms 278ms 3.60 7.63MB
#> 2 A %*% B 37.4ms 39ms 22.8 7.63MB
So for me the matrix product via %*% is several times faster than the one via RcppEigen. However, I am using Linux with OpenBLAS for matrix operations while you are on Windows, which often means reference BLAS for matrix operations. It might be that RcppEigen is faster on your system. I am not sure how difficult it is for Windows user to get a faster BLAS implementation (https://csgillespie.github.io/efficientR/set-up.html#blas-and-alternative-r-interpreters might contain some pointers), but I would suggest spending some time on investigating this.
Now if you come to the conclusion that you do need RcppEigen or RcppArmadillo in your code and want to put that code into a package, you can do the following. Instead of Rcpp::Rcpp.package.skeleton() use RcppEigen::RcppEigen.package.skeleton() or RcppArmadillo::RcppArmadillo.package.skeleton() to create a starting point for a package based on RcppEigen or RcppArmadillo, respectively.

Erlang Doesn't Warn About Unused Function Argument

If I declare a function
test(A) -> 3.
Erlang generates a warning about variable A not being used. However the definition
isEqual(X,X) -> 1.
Doesn't produce any warning but
isEqual(X,X) -> 1;
isEqual(X,Y) -> 0.
again produces a warning but only for the second line.
The reason why that doesn't generate a warning is because in the second case you are asserting (through pattern matching), by using the same variable name, that the first and second arguments to isEqual/2 have the same value. So you are actually using the value of the argument.
It might help to understand better if we look at the Core Erlang code produced from is_equal/2. You can get .core source files by compiling your .erl file in the following way: erlc +to_core pattern.erl (see here for pattern.erl).
This will produce a pattern.core file that will look something like this (module_info/[0,1] functions removed):
module 'pattern' ['is_equal'/2]
attributes []
'is_equal'/2 = fun (_cor1,_cor0) ->
case <_cor1,_cor0> of
%% Line 5
<X,_cor4> when call 'erlang':'=:=' (_cor4, X) ->
1
%% Line 6
<X,Y> when 'true' ->
0
end
As you can see, each function clause from is_equal/2 in the .erl source code gets translated to a case clause in Core Erlang. X does get used in the first clause since it needs to be compared to the other argument. On the other hand neither X or Y are used in the second clause.

.fsx script ignoring a function call when I add a parameter to it

Alright, so I'm a happy fsx-script programmer, because I love how I can have the compiler shout at me when I do mistakes before they show up at runtime.
However I've found a case which really bothers me because I was expecting that by doing some refactoring (i.e.: adding an argument to a function) I was going to be warned by the compiler about all the places where I need to put the new argument. But, not only this did not happen, fsharpi ran my script and ignored the function call completely!! :(
How can I expect to refactor my scripts if this happens?
Here is my code:
let Foo (bar: string) =
Console.WriteLine("I received " + bar)
Foo("hey")
It works.
Now, later, I decide to add a second argument to the function (but I forget to add the argument to all the calls to it):
let Foo (bar: string) (baz: bool) =
Console.WriteLine("I received " + bar)
Foo("hey")
The result of this is: instead of the compiler telling me that I'm missing an argument, it is fsharpi running the script and ignoring the call to Foo! Why?
PS: I know the difference between currying and tuples, so I know Foo("hey") becomes a function (instead of a function call), because of partial application. But I want to understand better why the compiler is not expecting a function evaluation here, instead of seeing a function and ignoring it. Can I enable a warningAsError somehow? I would like to avoid resorting to using tuples in order to workaround this problem.
The fsharpi (or fsi if you're on Windows) interpreter makes no distinction between running a script and typing code at the interactive prompt (or, most often, submitting code from your editor via a select-and-hit-Alt-Enter keyboard shortcut).
Therefore, if you got what you're asking for -- fsharpi issuing a warning whenever a script line has a return value that isn't () -- it would ruin the value of fsharpi for the most common use case, which is people using an interactive fsharpi session to test their code, and rapidly iterate through non-working prototypes to get to one that works correctly. This is one of F#'s great strengths, and giving you what you're asking for would eliminate that strength. It is therefore never going to happen.
BUT... that doesn't mean that you're sunk. If you have functions that return unit, and you want fsharpi to give you a compile-time error when you refactor them to take more arguments, you can do it this way. Replace all occurrences of:
Foo("hey")
with:
() = Foo("hey")
As long as the function Foo has only one argument (and returns null), this will evaluate to true; the true value will be happily ignored by fsharpi, and your script will run. However, if you then change Foo to take two arguments, so that Foo("hey") now returns a function, the () = Foo("hey") line will no longer compile, and you'll get an error like:
error FS0001: This expression was expected to have type
unit
but here has type
'a -> unit
So if you want fsharpi to refuse to compile your script when you refactor a function, go through and change your calls to () = myfunc arg1 arg2. For functions that don't return unit, make the value you're testing against a value of that function's return type. For example, given this function:
let f x = x * 2
You could do
0 = f 5
This will be false, of course, but it will compile. But if you refactor f:
let f x y = x * 2 + y
Now the line 0 = f 5 will not compile, but will give you the error message:
error FS0001: This expression was expected to have type
int
but here has type
int -> int
To summarize: you won't ever get the feature you're looking for, because it would harm the language. But with a bit of work, you can do something that fits your needs.
Or in other words, as the famous philosopher Mick Jagger once put it:
You can't always get what you want. But if you try, sometimes you might find you get what you need.

installing agda fails on duplicate instance declarations

I'm trying to give agda a shot, but I can't get it installed. I'm running GHC 7.8.3 in a cabal sandbox.
Failed to install Agda-2.4.0.1
Build log ( /Users/jsnavely/project/agda/.cabal-sandbox/logs/Agda-2.4.0.1.log ):
[1 of 1] Compiling Main ( /var/folders/dh/ckhr9p0j3kq3bx12176p7rlw0000gn/T/Agda-2.4.0.1-77992/Agda-2.4.0.1/dist/dist-sandbox-eeb4211c/setup/setup.hs, /var/folders/dh/ckhr9p0j3kq3bx12176p7rlw0000gn/T/Agda-2.4.0.1-77992/Agda-2.4.0.1/dist/dist-sandbox-eeb4211c/setup/Main.o )
Linking /var/folders/dh/ckhr9p0j3kq3bx12176p7rlw0000gn/T/Agda-2.4.0.1-77992/Agda-2.4.0.1/dist/dist-sandbox-eeb4211c/setup/setup ...
Configuring Agda-2.4.0.1...
Building Agda-2.4.0.1...
Preprocessing library Agda-2.4.0.1...
[ 1 of 272] Compiling Agda.Utils.Maybe.Strict ( src/full/Agda/Utils/Maybe/Strict.hs, dist/dist-sandbox-eeb4211c/build/Agda/Utils/Maybe/Strict.o )
[ 2 of 272] Compiling Agda.Utils.SemiRing ( src/full/Agda/Utils/SemiRing.hs, dist/dist-sandbox-eeb4211c/build/Agda/Utils/SemiRing.o )
[ 3 of 272] Compiling Agda.TypeChecking.Monad.Debug ( src/full/Agda/TypeChecking/Monad/Debug.hs, dist/dist-sandbox-eeb4211c/build/Agda/TypeChecking/Monad/Debug.o )
[ 4 of 272] Compiling Agda.Utils.Cluster ( src/full/Agda/Utils/Cluster.hs, dist/dist-sandbox-eeb4211c/build/Agda/Utils/Cluster.o )
src/full/Agda/Utils/Cluster.hs:50:10:
Duplicate instance declarations:
instance Monad m => Functor (EquivT s x y m)
-- Defined at src/full/Agda/Utils/Cluster.hs:50:10
instance Functor m => Functor (EquivT s c v m)
-- Defined in ‘Data.Equivalence.Monad’
cabal: Error: some packages failed to install:
Agda-2.4.0.1 failed during the building phase. The exception was:
ExitFailure 1
I'd be happy to unpack the cabal package, but I'm not sure what I'd fiddle with. Can we remove one of the definitions?
This problem is fixed in the git(hub) version of Agda. The fix will be released with 2.4.0.2.
The problem is that equivalence library (hackage) didn't define Functor instance for EquivT and for that reason Agda defined its own. The latest versions (0.2.4 and later) added this missing instance and there is now conflict with the Agda one.
You have basically two choices: either downgrade to equivalence-0.2.3 or remove the instance from Agda source files. I checked and the implementations match. However, the Agda one comes with different constraints (as can be seen from the error message):
instance Monad m => Functor (EquivT s x y m) -- Agda
instance Functor m => Functor (EquivT s c v m) -- equivalence
So, while the instance can be safely removed, it is possible (although unlikely) that there will be some broken type class constraints - for example a type with a Monad instance but without a Functor one.
Also consider reporting this problem on the official bugtracker. As far as I can tell, it hasn't been reported yet.

Resources