From aa44f08845c08cf4374ea7e9ad6879715cf7352c Mon Sep 17 00:00:00 2001
From: Miloslav Metelka <miloslav.metelka@oracle.com>
Date: Fri, 12 Jan 2018 12:15:38 +0100
Subject: [PATCH] Implemented qr_coef_cmplx internal builtin.

---
 .../r/ffi/impl/llvm/TruffleLLVM_Lapack.java   | 38 +++++++++++
 .../ffi/impl/managed/Managed_LapackRFFI.java  | 10 +++
 .../r/ffi/impl/nfi/TruffleNFI_Lapack.java     | 36 ++++++++++
 .../fficall/src/truffle_common/lapack_rffi.c  | 31 +++++++++
 .../r/nodes/builtin/base/BasePackage.java     |  1 +
 .../r/nodes/builtin/base/LaFunctions.java     | 66 +++++++++++++++++++
 .../truffle/r/nodes/builtin/InternalNode.java |  2 +-
 .../com/oracle/truffle/r/runtime/RError.java  |  3 +-
 .../r/runtime/data/nodes/GetReadonlyData.java | 19 ++++++
 .../truffle/r/runtime/ffi/LapackRFFI.java     | 22 +++++++
 .../truffle/r/runtime/ffi/NativeFunction.java |  2 +
 .../truffle/r/test/ExpectedTestOutput.test    |  2 +-
 .../r/test/builtins/TestBuiltin_qr.java       |  4 +-
 13 files changed, 230 insertions(+), 6 deletions(-)

diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Lapack.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Lapack.java
index f908ab424e..9a978fdcb1 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Lapack.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Lapack.java
@@ -258,6 +258,34 @@ public class TruffleLLVM_Lapack implements LapackRFFI {
         }
     }
 
+    private static final class TruffleLLVM_ZunmqrNode extends TruffleLLVM_DownCallNode implements ZunmqrNode {
+
+        @Override
+        protected NativeFunction getFunction() {
+            return NativeFunction.zunmqr;
+        }
+
+        @Override
+        public int execute(String side, String trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) {
+            return (int) call(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork);
+        }
+
+    }
+
+    private static final class TruffleLLVM_ZtrtrsNode extends TruffleLLVM_DownCallNode implements ZtrtrsNode {
+
+        @Override
+        protected NativeFunction getFunction() {
+            return NativeFunction.ztrtrs;
+        }
+
+        @Override
+        public int execute(String uplo, String trans, String diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) {
+            return (int) call(uplo, trans, diag, n, nrhs, a, lda, b, ldb);
+        }
+
+    }
+
     @Override
     public IlaverNode createIlaverNode() {
         return new TruffleLLVM_IlaverNode();
@@ -327,4 +355,14 @@ public class TruffleLLVM_Lapack implements LapackRFFI {
     public DsyevrNode createDsyevrNode() {
         return new TruffleLLVM_DsyevrNode();
     }
+
+    @Override
+    public ZunmqrNode createZunmqrNode() {
+        return new TruffleLLVM_ZunmqrNode();
+    }
+
+    @Override
+    public ZtrtrsNode createZtrtrsNode() {
+        return new TruffleLLVM_ZtrtrsNode();
+    }
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_LapackRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_LapackRFFI.java
index 7ed0ec3855..f523bdb16e 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_LapackRFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_LapackRFFI.java
@@ -96,4 +96,14 @@ public class Managed_LapackRFFI implements LapackRFFI {
     public DsyevrNode createDsyevrNode() {
         throw unsupported("lapack");
     }
+
+    @Override
+    public ZunmqrNode createZunmqrNode() {
+        throw unsupported("lapack");
+    }
+
+    @Override
+    public ZtrtrsNode createZtrtrsNode() {
+        throw unsupported("lapack");
+    }
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Lapack.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Lapack.java
index 420c684bc6..8cbb1163c7 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Lapack.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Lapack.java
@@ -196,6 +196,32 @@ public class TruffleNFI_Lapack implements LapackRFFI {
         }
     }
 
+    private static class TruffleNFI_ZunmqrNode extends TruffleNFI_DownCallNode implements ZunmqrNode {
+        @Override
+        protected NativeFunction getFunction() {
+            return NativeFunction.zunmqr;
+        }
+
+        @Override
+        public int execute(String side, String trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) {
+            return (int) call(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork);
+        }
+
+    }
+
+    private static final class TruffleNFI_ZtrtrsNode extends TruffleNFI_DownCallNode implements ZtrtrsNode {
+
+        @Override
+        protected NativeFunction getFunction() {
+            return NativeFunction.ztrtrs;
+        }
+
+        @Override
+        public int execute(String uplo, String trans, String diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) {
+            return (int) call(uplo, trans, diag, n, nrhs, a, lda, b, ldb);
+        }
+    }
+
     @Override
     public IlaverNode createIlaverNode() {
         return new TruffleNFI_IlaverNode();
@@ -265,4 +291,14 @@ public class TruffleNFI_Lapack implements LapackRFFI {
     public DsyevrNode createDsyevrNode() {
         return new TruffleNFI_DsyevrNode();
     }
+
+    @Override
+    public ZunmqrNode createZunmqrNode() {
+        return new TruffleNFI_ZunmqrNode();
+    }
+
+    @Override
+    public ZtrtrsNode createZtrtrsNode() {
+        return new TruffleNFI_ZtrtrsNode();
+    }
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/lapack_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_common/lapack_rffi.c
index 5e7a0e2f16..fc0e123705 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_common/lapack_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/lapack_rffi.c
@@ -23,6 +23,8 @@
 
 #include <rffiutils.h>
 
+#define DOUBLES_AS_COMPLEX(d)   ((Rcomplex *)(d))
+
 extern void ilaver_(int *major, int *minor, int *patch);
 
 void call_lapack_ilaver(int* version) {
@@ -141,3 +143,32 @@ int call_lapack_dsyevr(char jobz, char range, char uplo, int n, double *a, int l
             z, &ldz, isuppz, work, &lwork, iwork, &liwork, &info);
     return info;
 }
+
+extern void zunmqr_(const char *side, const char *trans,
+		 const int *m, const int *n, const int *k,
+		 Rcomplex *a, const int *lda,
+		 Rcomplex *tau,
+		 Rcomplex *c, const int *ldc,
+		 Rcomplex *work, const int *lwork, int *info);
+
+int call_lapack_zunmqr(const char *side, const char *trans, int m, int n, int k, double *a, int lda, double *tau,
+		 double *c, int ldc, double *work, int lwork) {
+    int info;
+    zunmqr_(side, trans, &m, &n, &k, DOUBLES_AS_COMPLEX(a), &lda, DOUBLES_AS_COMPLEX(tau),
+            DOUBLES_AS_COMPLEX(c), &ldc, DOUBLES_AS_COMPLEX(work), &lwork, &info);
+    return info;
+}
+
+
+extern void ztrtrs_(const char *uplo, const char *trans, const char *diag,
+		 const int *n, const int *nrhs,
+		 Rcomplex *a, const int *lda,
+		 Rcomplex *b, const int *ldb, int *info);
+
+int call_lapack_ztrtrs(const char *uplo, const char *trans, const char *diag,
+		 int n, int nrhs, double *a, int lda, double *b, int ldb) {
+    int info;
+    ztrtrs_(uplo, trans, diag, &n, &nrhs, DOUBLES_AS_COMPLEX(a), &lda, DOUBLES_AS_COMPLEX(b), &ldb, &info);
+    return info;
+}
+
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 600fcf2b2c..2ee57e66f0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -584,6 +584,7 @@ public class BasePackage extends RBuiltinPackage {
         add(LaFunctions.LaChol2Inv.class, LaFunctionsFactory.LaChol2InvNodeGen::create);
         add(LaFunctions.Qr.class, LaFunctionsFactory.QrNodeGen::create);
         add(LaFunctions.QrCoefReal.class, LaFunctionsFactory.QrCoefRealNodeGen::create);
+        add(LaFunctions.QrCoefCmplx.class, LaFunctionsFactory.QrCoefCmplxNodeGen::create);
         add(LaFunctions.Rg.class, LaFunctionsFactory.RgNodeGen::create);
         add(LaFunctions.Rs.class, LaFunctionsFactory.RsNodeGen::create);
         add(LaFunctions.Version.class, LaFunctionsFactory.VersionNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index b1681c9175..9f06c3b793 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -39,7 +39,9 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
 import com.oracle.truffle.r.nodes.attributes.CopyAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
@@ -50,6 +52,7 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNames
 import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.unary.CastComplexNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen;
 import com.oracle.truffle.r.runtime.RAccuracyInfo;
@@ -58,14 +61,18 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDataFactory.VectorFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.data.nodes.GetReadonlyData;
+import com.oracle.truffle.r.runtime.data.nodes.VectorDataReuse;
 import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
@@ -369,6 +376,65 @@ public class LaFunctions {
         }
     }
 
+    @RBuiltin(name = "qr_coef_cmplx", kind = INTERNAL, parameterNames = {"q", "b"}, behavior = PURE)
+    public abstract static class QrCoefCmplx extends RBuiltinNode.Arg2 {
+
+        static {
+            Casts casts = new Casts(QrCoefCmplx.class);
+            casts.arg(0).mustBe(RList.class);
+            casts.arg(1).asComplexVector(false, true, false).mustBe(matrix(), Message.MUST_BE_COMPLEX_MATRIX, "b");
+        }
+
+        @Node.Child private LapackRFFI.ZunmqrNode zunmqrNode = LapackRFFI.ZunmqrNode.create();
+        @Node.Child private LapackRFFI.ZtrtrsNode ztrtrsNode = LapackRFFI.ZtrtrsNode.create();
+
+        @Specialization
+        Object doQrCoefCmplx(RList q, RAbstractComplexVector b,
+                        @Cached("create()") GetReadonlyData.Complex getReadonlyData,
+                        @Cached("create()") VectorDataReuse.Complex vectorDataReuse,
+                        @Cached("create()") ExtractListElement extractQrElement,
+                        @Cached("create()") ExtractListElement extractTauElement,
+                        @Cached("create()") GetDimAttributeNode getQDimAttribute,
+                        @Cached("create()") GetDimAttributeNode getBDimAttribute,
+                        @Cached("create()") CastComplexNode bAsComplex,
+                        @Cached("create()") VectorFactory resultVectorFactory) {
+            RAbstractComplexVector qr = (RAbstractComplexVector) extractQrElement.execute(q, 0);
+            RAbstractComplexVector tau = (RAbstractComplexVector) extractTauElement.execute(q, 2);
+            int k = tau.getLength();
+            int[] qDims = getQDimAttribute.getDimensions(qr);
+            int[] bDims = getBDimAttribute.getDimensions(b);
+            int n = qDims[0];
+            if (bDims[0] != n) {
+                throw error(Message.RHS_SHOULD_HAVE_ROWS, n, bDims[0]);
+            }
+            int nrhs = bDims[1];
+            int lwork = -1;
+            double[] tmp = new double[2]; // Complex
+            double[] qrData = getReadonlyData.execute(qr.materialize());
+            double[] tauData = getReadonlyData.execute(tau.materialize());
+            double[] bComplexData = vectorDataReuse.execute(b.materialize());
+            int info = zunmqrNode.execute(
+                            "L", "C", n, nrhs, k, qrData, n, tauData, bComplexData, n, tmp, lwork);
+            if (info != 0) {
+                throw error(Message.LAPACK_ERROR, info, "zunmqr");
+            }
+            lwork = (int) tmp[0];
+            double[] work = new double[2]; // Complex
+            info = zunmqrNode.execute(
+                            "L", "C", n, nrhs, k, qrData, n, tauData, bComplexData, n, work, lwork);
+            if (info != 0) {
+                throw error(Message.LAPACK_ERROR, info, "zunmqr");
+            }
+            info = ztrtrsNode.execute(
+                            "U", "N", "N", k, nrhs, qrData, n, bComplexData, n);
+            if (info != 0) {
+                throw error(Message.LAPACK_ERROR, info, "zunmqr");
+            }
+            return resultVectorFactory.createComplexVector(bComplexData, b.isComplete(), bDims);
+        }
+
+    }
+
     @RBuiltin(name = "det_ge_real", kind = INTERNAL, parameterNames = {"a", "uselog"}, behavior = PURE)
     public abstract static class DetGeReal extends RBuiltinNode.Arg2 {
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
index 2a45c170d9..db1d98d560 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
@@ -353,5 +353,5 @@ public abstract class InternalNode extends OperatorNode {
                     "setNumMathThreads", "setMaxNumMathThreads", "isatty", "isIncomplete", "pipe", "fifo", "unz", "truncate", "rawConnection",
                     "rawConnectionValue", "sockSelect", "gzcon", "memCompress", "memDecompress", "mkUnbound", "env.profile", "setSessionTimeLimit", "icuSetCollate", "findInterval", "rowsum_df",
                     "La_qr_cmplx", "La_rs_cmplx", "La_rg_cmplx", "La_rs_cmplx", "La_dlange", "La_dgecon", "La_dtrcon", "La_zgecon", "La_ztrcon", "La_solve_cmplx", "La_chol2inv", "qr_qy_real",
-                    "qr_coef_cmplx", "qr_qy_cmpl", "La_svd", "La_svd_cmplx");
+                    "qr_qy_cmpl", "La_svd", "La_svd_cmplx");
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 13c2aa50eb..b605ab1a5f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -916,7 +916,8 @@ public final class RError extends RuntimeException implements TruffleException {
         MUST_BE_MULTIPLE("argument '%s' must be a multiple of %d long"),
         MUSTNOT_CONTAIN_NAS("argument '%s' must not contain NAs"),
         VERSION_N_NOT_SUPPORTED("version %d not supported"),
-        ATOMIC_VECTOR_ARGUMENTS_ONLY("atomic vector arguments only");
+        ATOMIC_VECTOR_ARGUMENTS_ONLY("atomic vector arguments only"),
+        MUST_BE_COMPLEX_MATRIX("'%s' must be a complex matrix");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetReadonlyData.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetReadonlyData.java
index 18a56b1561..767bbae89a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetReadonlyData.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetReadonlyData.java
@@ -26,6 +26,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.NativeDataAccess;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -60,6 +61,24 @@ public class GetReadonlyData {
         }
     }
 
+    public abstract static class Complex extends Node {
+        public abstract double[] execute(RComplexVector vector);
+
+        @Specialization(guards = "!vec.hasNativeMemoryData()")
+        protected double[] doManagedRVector(RComplexVector vec) {
+            return vec.getInternalManagedData();
+        }
+
+        @Specialization(guards = "vec.hasNativeMemoryData()")
+        protected double[] doNativeDataRVector(RComplexVector vec) {
+            return NativeDataAccess.copyComplexNativeData(vec.getNativeMirror());
+        }
+
+        public static Complex create() {
+            return GetReadonlyDataFactory.ComplexNodeGen.create();
+        }
+    }
+
     public abstract static class Int extends Node {
         public abstract int[] execute(RIntVector vector);
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java
index 92f000c636..2b30690ddb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java
@@ -189,6 +189,24 @@ public interface LapackRFFI {
         }
     }
 
+    interface ZunmqrNode extends NodeInterface {
+
+        int execute(String side, String trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork);
+
+        static ZunmqrNode create() {
+            return RFFIFactory.getLapackRFFI().createZunmqrNode();
+        }
+    }
+
+    interface ZtrtrsNode extends NodeInterface {
+
+        int execute(String uplo, String trans, String diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb);
+
+        static ZtrtrsNode create() {
+            return RFFIFactory.getLapackRFFI().createZtrtrsNode();
+        }
+    }
+
     IlaverNode createIlaverNode();
 
     DgeevNode createDgeevNode();
@@ -217,4 +235,8 @@ public interface LapackRFFI {
 
     DsyevrNode createDsyevrNode();
 
+    ZunmqrNode createZunmqrNode();
+
+    ZtrtrsNode createZtrtrsNode();
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeFunction.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeFunction.java
index 2459063d8d..3f9a500372 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeFunction.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeFunction.java
@@ -70,6 +70,8 @@ public enum NativeFunction {
     dsyevr(
                     "(uint8, uint8, uint8, sint32, [double], sint32, double, double, sint32, sint32, double, [sint32], [double], [double], sint32, [sint32], [double], sint32, [sint32], sint32) : sint32",
                     "call_lapack_"),
+    zunmqr("(string, string, sint32, sint32, sint32, [double], sint32, [double], [double], sint32, [double], sint32) : sint32", "call_lapack_"),
+    ztrtrs("(string, string, string, sint32, sint32, [double], sint32, [double], sint32) : sint32", "call_lapack_"),
     // misc
     exactSumFunc("([double], sint32, sint32, sint32): double", "call_misc_"),
     dqrls("([double], sint32, sint32, [double], sint32, double, [double], [double], [double], [sint32], [sint32], [double], [double]): void", "call_misc_"),
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 57a4818c80..1f503b574c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -49128,7 +49128,7 @@ Error in qr.coef(x, 1:2) : right-hand side should have 10 not 2 rows
 #{ x <- qr(t(cbind(1:10,2:11)), LAPACK=TRUE) ; qr.coef(x, 1:2) }
  [1]  1 NA NA NA NA NA NA NA NA  0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_qr.testqr1#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_qr.testqr1#
 #argv <- list(structure(list(qr = structure(c(-2.99896066496855+0i, 0.0864255261791181+0i, -0.13772470327145+0i, -0.49098351645158+0i, 0.249389337649224+0i, 1.17331892183982+0i, -1.54960102684918+0i, -0.573648421141553+0i, 0.376760682628698+0i, 0.412090084647403+0i, 0.603959683330493+0i, -0.0216928335770876+0i, -1.2469936242596+0i, 0.224366164923213+0i, 0.341798188737913+0i, 1.04294423444024+0i, 0.270564951504877+0i, -0.315381666175534+0i, 0.787566751532822+0i, 0.229154517629245+0i, -2.25109940279642+0i, 0.530750192641659+0i, -0.0977755443891602+0i, 0.6614171819615+0i, -0.0856949989622426+0i), .Dim = c(5L, 5L), .Dimnames = list(c('1', '2', '3', '4', '5'), c('c', 'a', 'd', 'b', 'e'))), rank = 5L, qraux = c(1.50410169966891+0i, 1.21888836143069+0i, 1.71355205288103+0i, 1.90021623833265+0i, 0+0i), pivot = c(3L, 1L, 4L, 2L, 5L)), .Names = c('qr', 'rank', 'qraux', 'pivot'), class = 'qr'), structure(1:5, .Dim = c(5L, 1L))); .Internal(qr_coef_cmplx(argv[[1]], argv[[2]]))
              [,1]
 [1,] -7.390881+0i
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java
index c176d24ca4..c32e998238 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java
@@ -19,9 +19,7 @@ public class TestBuiltin_qr extends TestBase {
 
     @Test
     public void testqr1() {
-        // FIXME RInternalError: not implemented: .Internal qr_coef_cmplx
-        assertEval(Ignored.Unimplemented,
-                        "argv <- list(structure(list(qr = structure(c(-2.99896066496855+0i, 0.0864255261791181+0i, -0.13772470327145+0i, -0.49098351645158+0i, 0.249389337649224+0i, 1.17331892183982+0i, -1.54960102684918+0i, -0.573648421141553+0i, 0.376760682628698+0i, 0.412090084647403+0i, 0.603959683330493+0i, -0.0216928335770876+0i, -1.2469936242596+0i, 0.224366164923213+0i, 0.341798188737913+0i, 1.04294423444024+0i, 0.270564951504877+0i, -0.315381666175534+0i, 0.787566751532822+0i, 0.229154517629245+0i, -2.25109940279642+0i, 0.530750192641659+0i, -0.0977755443891602+0i, 0.6614171819615+0i, -0.0856949989622426+0i), .Dim = c(5L, 5L), .Dimnames = list(c('1', '2', '3', '4', '5'), c('c', 'a', 'd', 'b', 'e'))), rank = 5L, qraux = c(1.50410169966891+0i, 1.21888836143069+0i, 1.71355205288103+0i, 1.90021623833265+0i, 0+0i), pivot = c(3L, 1L, 4L, 2L, 5L)), .Names = c('qr', 'rank', 'qraux', 'pivot'), class = 'qr'), structure(1:5, .Dim = c(5L, 1L))); .Internal(qr_coef_cmplx(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(list(qr = structure(c(-2.99896066496855+0i, 0.0864255261791181+0i, -0.13772470327145+0i, -0.49098351645158+0i, 0.249389337649224+0i, 1.17331892183982+0i, -1.54960102684918+0i, -0.573648421141553+0i, 0.376760682628698+0i, 0.412090084647403+0i, 0.603959683330493+0i, -0.0216928335770876+0i, -1.2469936242596+0i, 0.224366164923213+0i, 0.341798188737913+0i, 1.04294423444024+0i, 0.270564951504877+0i, -0.315381666175534+0i, 0.787566751532822+0i, 0.229154517629245+0i, -2.25109940279642+0i, 0.530750192641659+0i, -0.0977755443891602+0i, 0.6614171819615+0i, -0.0856949989622426+0i), .Dim = c(5L, 5L), .Dimnames = list(c('1', '2', '3', '4', '5'), c('c', 'a', 'd', 'b', 'e'))), rank = 5L, qraux = c(1.50410169966891+0i, 1.21888836143069+0i, 1.71355205288103+0i, 1.90021623833265+0i, 0+0i), pivot = c(3L, 1L, 4L, 2L, 5L)), .Names = c('qr', 'rank', 'qraux', 'pivot'), class = 'qr'), structure(1:5, .Dim = c(5L, 1L))); .Internal(qr_coef_cmplx(argv[[1]], argv[[2]]))");
     }
 
     @Test
-- 
GitLab