What happens
quickr correctly refuses character values and unsupported complex
operations, but the refusals are unreadable:
quick(function(x) { declare(type(x = character(1))); x })("a")
#> Error: unrecognized kind: <quickr::Variable> @ mode : chr "character"
#> @ dims :List of 1 .. $ : int 1 @ name : chr "x" ... (an S7 dump)
fn <- function(x, y) {
declare(type(x = complex(1)), type(y = complex(1)))
x < y
}
quick(fn)(1i, 2i)
#> Error: Compilation Error
#> ... f2_fsub.f90:13:10: out_ = (x < y)
#> Compiler Error: COMPLEX quantities cannot be compared at (1) ...
x %% y on complex operands fails the same way (a raw gfortran dump).
R errors in all three cases (invalid comparison with complex values,
unimplemented complex operation) — the refusals are right, the
diagnostics are not.
Why it happens
Character declarations pass type_call_to_var() (R/sizes.R) untouched
and only die when the manifest generator finds no Fortran kind for the
mode — stop("unrecognized kind: ", format(var)) prints the whole S7
object. Complex order comparisons and complex %% are never
intercepted at all: the operands promote to complex and gfortran
rejects the emitted < / modulo().
Complex operands flow into the real BLAS/LAPACK routines (found in
external review) — worse than an ugly error, this is a silent wrong
answer. The linalg paths cast logical/integer operands to double and
pass complex through untouched, so dgemm/dgesv read complex storage
as reals:
complex_dot <- quick(function(x, y) {
declare(type(x = complex(2)), type(y = complex(2)))
x %*% y
})
complex_dot(c(1 + 1i, 2 + 0i), c(3 + 0i, 4 + 1i))
#> matrix(3), typeof double
#> R: matrix(11 + 5i), typeof complex
The 3 is c(1, 1) . c(3, 0): dgemm reads the interleaved complex
storage as a plain double array, so the real and imaginary halves of the
first element become the two elements of a length-2 real vector. The
answer is arbitrary, not a real-part projection.
Expected behavior
A mode or operation with no Fortran translation should be a clean
compile-time error naming what is unsupported: character declarations
refused at declare(), complex ordering and complex %% refused at
the operator with R's own error messages. Complex equality (==/!=)
keeps working — R supports it. Complex operands anywhere on the
linear-algebra surface (%*%, crossprod, solve, chol, svd, outer, ...)
are refused at compile time — quickr's lowerings are double-only; the
mode-preserving standalone t() keeps working.
What happens
quickr correctly refuses character values and unsupported complex
operations, but the refusals are unreadable:
x %% yon complex operands fails the same way (a raw gfortran dump).R errors in all three cases (
invalid comparison with complex values,unimplemented complex operation) — the refusals are right, thediagnostics are not.
Why it happens
Character declarations pass
type_call_to_var()(R/sizes.R) untouchedand only die when the manifest generator finds no Fortran kind for the
mode —
stop("unrecognized kind: ", format(var))prints the whole S7object. Complex order comparisons and complex
%%are neverintercepted at all: the operands promote to complex and gfortran
rejects the emitted
</modulo().Complex operands flow into the real BLAS/LAPACK routines (found in
external review) — worse than an ugly error, this is a silent wrong
answer. The linalg paths cast logical/integer operands to double and
pass complex through untouched, so
dgemm/dgesvread complex storageas reals:
The
3isc(1, 1) . c(3, 0): dgemm reads the interleaved complexstorage as a plain double array, so the real and imaginary halves of the
first element become the two elements of a length-2 real vector. The
answer is arbitrary, not a real-part projection.
Expected behavior
A mode or operation with no Fortran translation should be a clean
compile-time error naming what is unsupported: character declarations
refused at
declare(), complex ordering and complex%%refused atthe operator with R's own error messages. Complex equality (
==/!=)keeps working — R supports it. Complex operands anywhere on the
linear-algebra surface (
%*%, crossprod, solve, chol, svd, outer, ...)are refused at compile time — quickr's lowerings are double-only; the
mode-preserving standalone
t()keeps working.