xref: /aosp_15_r20/frameworks/rs/cpp/ScriptIntrinsicBLAS.cpp (revision e1eccf28f96817838ad6867f7f39d2351ec11f56)
1*e1eccf28SAndroid Build Coastguard Worker /*
2*e1eccf28SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*e1eccf28SAndroid Build Coastguard Worker  *
4*e1eccf28SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*e1eccf28SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*e1eccf28SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*e1eccf28SAndroid Build Coastguard Worker  *
8*e1eccf28SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*e1eccf28SAndroid Build Coastguard Worker  *
10*e1eccf28SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*e1eccf28SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*e1eccf28SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e1eccf28SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*e1eccf28SAndroid Build Coastguard Worker  * limitations under the License.
15*e1eccf28SAndroid Build Coastguard Worker  */
16*e1eccf28SAndroid Build Coastguard Worker 
17*e1eccf28SAndroid Build Coastguard Worker 
18*e1eccf28SAndroid Build Coastguard Worker #include "RenderScript.h"
19*e1eccf28SAndroid Build Coastguard Worker #include "rsCppInternal.h"
20*e1eccf28SAndroid Build Coastguard Worker 
21*e1eccf28SAndroid Build Coastguard Worker #define NELEM(m) (sizeof(m) / sizeof((m)[0]))
22*e1eccf28SAndroid Build Coastguard Worker 
23*e1eccf28SAndroid Build Coastguard Worker using android::RSC::Allocation;
24*e1eccf28SAndroid Build Coastguard Worker using android::RSC::Element;
25*e1eccf28SAndroid Build Coastguard Worker using android::RSC::RS;
26*e1eccf28SAndroid Build Coastguard Worker using android::RSC::RS_ERROR_INVALID_ELEMENT;
27*e1eccf28SAndroid Build Coastguard Worker using android::RSC::RS_ERROR_INVALID_PARAMETER;
28*e1eccf28SAndroid Build Coastguard Worker using android::RSC::RS_SUCCESS;
29*e1eccf28SAndroid Build Coastguard Worker using android::RSC::ScriptIntrinsicBLAS;
30*e1eccf28SAndroid Build Coastguard Worker using android::RSC::sp;
31*e1eccf28SAndroid Build Coastguard Worker 
32*e1eccf28SAndroid Build Coastguard Worker // ScriptIntrinsicBLAS APIS
ScriptIntrinsicBLAS(sp<RS> rs,sp<const Element> e)33*e1eccf28SAndroid Build Coastguard Worker ScriptIntrinsicBLAS::ScriptIntrinsicBLAS(sp<RS> rs, sp<const Element> e)
34*e1eccf28SAndroid Build Coastguard Worker     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_BLAS, e) {
35*e1eccf28SAndroid Build Coastguard Worker 
36*e1eccf28SAndroid Build Coastguard Worker }
37*e1eccf28SAndroid Build Coastguard Worker 
create(const sp<RS> & rs)38*e1eccf28SAndroid Build Coastguard Worker sp<ScriptIntrinsicBLAS> ScriptIntrinsicBLAS::create(const sp<RS>& rs) {
39*e1eccf28SAndroid Build Coastguard Worker     return new ScriptIntrinsicBLAS(rs, Element::U32(rs));
40*e1eccf28SAndroid Build Coastguard Worker }
41*e1eccf28SAndroid Build Coastguard Worker 
42*e1eccf28SAndroid Build Coastguard Worker enum RsBlasDataType {
43*e1eccf28SAndroid Build Coastguard Worker     SINGLE,
44*e1eccf28SAndroid Build Coastguard Worker     DOUBLE,
45*e1eccf28SAndroid Build Coastguard Worker     SINGLE_COMPLEX,
46*e1eccf28SAndroid Build Coastguard Worker     DOUBLE_COMPLEX
47*e1eccf28SAndroid Build Coastguard Worker };
48*e1eccf28SAndroid Build Coastguard Worker 
49*e1eccf28SAndroid Build Coastguard Worker static RsBlasCall
setUpBLASCall(RsBlasDataType dataType,RsBlasFunction func,int TransA,int TransB,int Side,int Uplo,int Diag,int M,int N,int K,int incX,int incY,int KL,int KU,float alphaF,float betaF,double alphaD,double betaD,float alphaCX,float alphaCY,float betaCX,float betaCY,double alphaZX,double alphaZY,double betaZX,double betaZY)50*e1eccf28SAndroid Build Coastguard Worker setUpBLASCall(RsBlasDataType dataType, RsBlasFunction func,
51*e1eccf28SAndroid Build Coastguard Worker               int TransA, int TransB, int Side, int Uplo, int Diag,
52*e1eccf28SAndroid Build Coastguard Worker               int M, int N, int K, int incX, int incY, int KL, int KU,
53*e1eccf28SAndroid Build Coastguard Worker               float alphaF, float betaF, double alphaD, double betaD,
54*e1eccf28SAndroid Build Coastguard Worker               float alphaCX, float alphaCY, float betaCX, float betaCY,
55*e1eccf28SAndroid Build Coastguard Worker               double alphaZX, double alphaZY, double betaZX, double betaZY
56*e1eccf28SAndroid Build Coastguard Worker               ) {
57*e1eccf28SAndroid Build Coastguard Worker     RsBlasCall call;
58*e1eccf28SAndroid Build Coastguard Worker     memset(&call, 0, sizeof(call));
59*e1eccf28SAndroid Build Coastguard Worker     call.func = func;
60*e1eccf28SAndroid Build Coastguard Worker     call.transA = (RsBlasTranspose)TransA;
61*e1eccf28SAndroid Build Coastguard Worker     call.transB = (RsBlasTranspose)TransB;
62*e1eccf28SAndroid Build Coastguard Worker     call.side = (RsBlasSide)Side;
63*e1eccf28SAndroid Build Coastguard Worker     call.uplo = (RsBlasUplo)Uplo;
64*e1eccf28SAndroid Build Coastguard Worker     call.diag = (RsBlasDiag)Diag;
65*e1eccf28SAndroid Build Coastguard Worker     call.M = M;
66*e1eccf28SAndroid Build Coastguard Worker     call.N = N;
67*e1eccf28SAndroid Build Coastguard Worker     call.K = K;
68*e1eccf28SAndroid Build Coastguard Worker 
69*e1eccf28SAndroid Build Coastguard Worker     switch (dataType) {
70*e1eccf28SAndroid Build Coastguard Worker         case SINGLE:
71*e1eccf28SAndroid Build Coastguard Worker             // For Single-precision BLAS.
72*e1eccf28SAndroid Build Coastguard Worker             call.alpha.f = alphaF;
73*e1eccf28SAndroid Build Coastguard Worker             call.beta.f = betaF;
74*e1eccf28SAndroid Build Coastguard Worker             break;
75*e1eccf28SAndroid Build Coastguard Worker         case DOUBLE:
76*e1eccf28SAndroid Build Coastguard Worker             // For Double-precision BLAS.
77*e1eccf28SAndroid Build Coastguard Worker             call.alpha.d = alphaD;
78*e1eccf28SAndroid Build Coastguard Worker             call.beta.d = betaD;
79*e1eccf28SAndroid Build Coastguard Worker             break;
80*e1eccf28SAndroid Build Coastguard Worker         case SINGLE_COMPLEX:
81*e1eccf28SAndroid Build Coastguard Worker             // For Single-precision complex BLAS.
82*e1eccf28SAndroid Build Coastguard Worker             call.alpha.c.r = alphaCX;
83*e1eccf28SAndroid Build Coastguard Worker             call.alpha.c.i = alphaCY;
84*e1eccf28SAndroid Build Coastguard Worker             call.beta.c.r = betaCX;
85*e1eccf28SAndroid Build Coastguard Worker             call.beta.c.i = betaCY;
86*e1eccf28SAndroid Build Coastguard Worker             break;
87*e1eccf28SAndroid Build Coastguard Worker         case DOUBLE_COMPLEX:
88*e1eccf28SAndroid Build Coastguard Worker             // For Double-precision complex BLAS.
89*e1eccf28SAndroid Build Coastguard Worker             call.alpha.z.r = alphaZX;
90*e1eccf28SAndroid Build Coastguard Worker             call.alpha.z.i = alphaZY;
91*e1eccf28SAndroid Build Coastguard Worker             call.beta.z.r = betaZX;
92*e1eccf28SAndroid Build Coastguard Worker             call.beta.z.i = betaZY;
93*e1eccf28SAndroid Build Coastguard Worker             break;
94*e1eccf28SAndroid Build Coastguard Worker         default:
95*e1eccf28SAndroid Build Coastguard Worker             break;
96*e1eccf28SAndroid Build Coastguard Worker     }
97*e1eccf28SAndroid Build Coastguard Worker 
98*e1eccf28SAndroid Build Coastguard Worker     call.incX = incX;
99*e1eccf28SAndroid Build Coastguard Worker     call.incY = incY;
100*e1eccf28SAndroid Build Coastguard Worker     call.KL = KL;
101*e1eccf28SAndroid Build Coastguard Worker     call.KU = KU;
102*e1eccf28SAndroid Build Coastguard Worker 
103*e1eccf28SAndroid Build Coastguard Worker     return call;
104*e1eccf28SAndroid Build Coastguard Worker }
105*e1eccf28SAndroid Build Coastguard Worker 
106*e1eccf28SAndroid Build Coastguard Worker static void
nScriptIntrinsicBLAS_Single(RS * mRS,RsContext con,RsScript id,RsBlasFunction func,int TransA,int TransB,int Side,int Uplo,int Diag,int M,int N,int K,float alpha,RsAllocation A,RsAllocation B,float beta,RsAllocation C,int incX,int incY,int KL,int KU)107*e1eccf28SAndroid Build Coastguard Worker nScriptIntrinsicBLAS_Single(RS* mRS, RsContext con, RsScript id, RsBlasFunction func, int TransA,
108*e1eccf28SAndroid Build Coastguard Worker                             int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
109*e1eccf28SAndroid Build Coastguard Worker                             float alpha, RsAllocation A, RsAllocation B,
110*e1eccf28SAndroid Build Coastguard Worker                             float beta, RsAllocation C, int incX, int incY, int KL, int KU) {
111*e1eccf28SAndroid Build Coastguard Worker     RsBlasCall call = setUpBLASCall(SINGLE, func, TransA, TransB, Side, Uplo, Diag,
112*e1eccf28SAndroid Build Coastguard Worker                                     M, N, K, incX, incY, KL, KU, alpha, beta, 0.0, 0.0,
113*e1eccf28SAndroid Build Coastguard Worker                                     0.0f, 0.0f, 0.0f, 0.0f, 0.0, 0.0, 0.0, 0.0);
114*e1eccf28SAndroid Build Coastguard Worker     RsAllocation in_allocs[3] = {A, B, C};
115*e1eccf28SAndroid Build Coastguard Worker     tryDispatch(mRS, RS::dispatch->ScriptForEachMulti(con, id, 0, in_allocs, NELEM(in_allocs), nullptr,
116*e1eccf28SAndroid Build Coastguard Worker                                                       &call, sizeof(call), nullptr, 0));
117*e1eccf28SAndroid Build Coastguard Worker }
118*e1eccf28SAndroid Build Coastguard Worker 
119*e1eccf28SAndroid Build Coastguard Worker 
120*e1eccf28SAndroid Build Coastguard Worker static void
nScriptIntrinsicBLAS_Double(RS * mRS,RsContext con,RsScript id,RsBlasFunction func,int TransA,int TransB,int Side,int Uplo,int Diag,int M,int N,int K,double alpha,RsAllocation A,RsAllocation B,double beta,RsAllocation C,int incX,int incY,int KL,int KU)121*e1eccf28SAndroid Build Coastguard Worker nScriptIntrinsicBLAS_Double(RS* mRS, RsContext con, RsScript id, RsBlasFunction func, int TransA,
122*e1eccf28SAndroid Build Coastguard Worker                             int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
123*e1eccf28SAndroid Build Coastguard Worker                             double alpha, RsAllocation A, RsAllocation B,
124*e1eccf28SAndroid Build Coastguard Worker                             double beta, RsAllocation C, int incX, int incY, int KL, int KU) {
125*e1eccf28SAndroid Build Coastguard Worker     RsBlasCall call = setUpBLASCall(DOUBLE, func, TransA, TransB, Side, Uplo, Diag,
126*e1eccf28SAndroid Build Coastguard Worker                                     M, N, K, incX, incY, KL, KU, 0.0f, 0.0f, alpha, beta,
127*e1eccf28SAndroid Build Coastguard Worker                                     0.0f, 0.0f, 0.0f, 0.0f, 0.0, 0.0, 0.0, 0.0);
128*e1eccf28SAndroid Build Coastguard Worker     RsAllocation in_allocs[3] = {A, B, C};
129*e1eccf28SAndroid Build Coastguard Worker     tryDispatch(mRS, RS::dispatch->ScriptForEachMulti(con, id, 0, in_allocs, NELEM(in_allocs), nullptr,
130*e1eccf28SAndroid Build Coastguard Worker                                                       &call, sizeof(call), nullptr, 0));
131*e1eccf28SAndroid Build Coastguard Worker }
132*e1eccf28SAndroid Build Coastguard Worker 
133*e1eccf28SAndroid Build Coastguard Worker static void
nScriptIntrinsicBLAS_Complex(RS * mRS,RsContext con,RsScript id,RsBlasFunction func,int TransA,int TransB,int Side,int Uplo,int Diag,int M,int N,int K,float alphaX,float alphaY,RsAllocation A,RsAllocation B,float betaX,float betaY,RsAllocation C,int incX,int incY,int KL,int KU)134*e1eccf28SAndroid Build Coastguard Worker nScriptIntrinsicBLAS_Complex(RS* mRS, RsContext con, RsScript id, RsBlasFunction func, int TransA,
135*e1eccf28SAndroid Build Coastguard Worker                              int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
136*e1eccf28SAndroid Build Coastguard Worker                              float alphaX, float alphaY, RsAllocation A, RsAllocation B,
137*e1eccf28SAndroid Build Coastguard Worker                              float betaX, float betaY, RsAllocation C, int incX, int incY, int KL, int KU) {
138*e1eccf28SAndroid Build Coastguard Worker     RsBlasCall call = setUpBLASCall(SINGLE_COMPLEX, func, TransA, TransB, Side, Uplo, Diag,
139*e1eccf28SAndroid Build Coastguard Worker                                     M, N, K, incX, incY, KL, KU, 0.0f, 0.0f, 0.0, 0.0,
140*e1eccf28SAndroid Build Coastguard Worker                                     alphaX, alphaY, betaX, betaY, 0.0, 0.0, 0.0, 0.0);
141*e1eccf28SAndroid Build Coastguard Worker     RsAllocation in_allocs[3] = {A, B, C};
142*e1eccf28SAndroid Build Coastguard Worker     tryDispatch(mRS, RS::dispatch->ScriptForEachMulti(con, id, 0, in_allocs, NELEM(in_allocs), nullptr,
143*e1eccf28SAndroid Build Coastguard Worker                                                       &call, sizeof(call), nullptr, 0));
144*e1eccf28SAndroid Build Coastguard Worker }
145*e1eccf28SAndroid Build Coastguard Worker 
146*e1eccf28SAndroid Build Coastguard Worker static void
nScriptIntrinsicBLAS_Z(RS * mRS,RsContext con,RsScript id,RsBlasFunction func,int TransA,int TransB,int Side,int Uplo,int Diag,int M,int N,int K,double alphaX,double alphaY,RsAllocation A,RsAllocation B,double betaX,double betaY,RsAllocation C,int incX,int incY,int KL,int KU)147*e1eccf28SAndroid Build Coastguard Worker nScriptIntrinsicBLAS_Z(RS* mRS, RsContext con, RsScript id, RsBlasFunction func, int TransA,
148*e1eccf28SAndroid Build Coastguard Worker                        int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
149*e1eccf28SAndroid Build Coastguard Worker                        double alphaX, double alphaY, RsAllocation A, RsAllocation B,
150*e1eccf28SAndroid Build Coastguard Worker                        double betaX, double betaY, RsAllocation C, int incX, int incY, int KL, int KU) {
151*e1eccf28SAndroid Build Coastguard Worker     RsBlasCall call = setUpBLASCall(DOUBLE_COMPLEX, func, TransA, TransB, Side, Uplo, Diag,
152*e1eccf28SAndroid Build Coastguard Worker                                     M, N, K, incX, incY, KL, KU, 0.0f, 0.0f, 0.0, 0.0,
153*e1eccf28SAndroid Build Coastguard Worker                                     0.0f, 0.0f, 0.0f, 0.0f, alphaX, alphaY, betaX, betaY);
154*e1eccf28SAndroid Build Coastguard Worker     RsAllocation in_allocs[3] = {A, B, C};
155*e1eccf28SAndroid Build Coastguard Worker     tryDispatch(mRS, RS::dispatch->ScriptForEachMulti(con, id, 0, in_allocs, NELEM(in_allocs), nullptr,
156*e1eccf28SAndroid Build Coastguard Worker                                                       &call, sizeof(call), nullptr, 0));
157*e1eccf28SAndroid Build Coastguard Worker }
158*e1eccf28SAndroid Build Coastguard Worker 
159*e1eccf28SAndroid Build Coastguard Worker 
160*e1eccf28SAndroid Build Coastguard Worker static void
nScriptIntrinsicBLAS_BNNM(RS * mRS,RsContext con,RsScript id,int M,int N,int K,RsAllocation A,int a_offset,RsAllocation B,int b_offset,RsAllocation C,int c_offset,int c_mult_int)161*e1eccf28SAndroid Build Coastguard Worker nScriptIntrinsicBLAS_BNNM(RS* mRS, RsContext con, RsScript id, int M, int N, int K,
162*e1eccf28SAndroid Build Coastguard Worker                           RsAllocation A, int a_offset, RsAllocation B, int b_offset,
163*e1eccf28SAndroid Build Coastguard Worker                           RsAllocation C, int c_offset, int c_mult_int) {
164*e1eccf28SAndroid Build Coastguard Worker     RsBlasCall call;
165*e1eccf28SAndroid Build Coastguard Worker     memset(&call, 0, sizeof(call));
166*e1eccf28SAndroid Build Coastguard Worker     call.func = RsBlas_bnnm;
167*e1eccf28SAndroid Build Coastguard Worker     call.M = M;
168*e1eccf28SAndroid Build Coastguard Worker     call.N = N;
169*e1eccf28SAndroid Build Coastguard Worker     call.K = K;
170*e1eccf28SAndroid Build Coastguard Worker     call.a_offset = a_offset & 0xFF;
171*e1eccf28SAndroid Build Coastguard Worker     call.b_offset = b_offset & 0xFF;
172*e1eccf28SAndroid Build Coastguard Worker     call.c_offset = c_offset;
173*e1eccf28SAndroid Build Coastguard Worker     call.c_mult_int = c_mult_int;
174*e1eccf28SAndroid Build Coastguard Worker 
175*e1eccf28SAndroid Build Coastguard Worker     RsAllocation in_allocs[3] = {A, B, C};
176*e1eccf28SAndroid Build Coastguard Worker     tryDispatch(mRS, RS::dispatch->ScriptForEachMulti(con, id, 0, in_allocs, NELEM(in_allocs), nullptr,
177*e1eccf28SAndroid Build Coastguard Worker                                                       &call, sizeof(call), nullptr, 0));
178*e1eccf28SAndroid Build Coastguard Worker }
179*e1eccf28SAndroid Build Coastguard Worker 
180*e1eccf28SAndroid Build Coastguard Worker /**
181*e1eccf28SAndroid Build Coastguard Worker  * Level 2 BLAS
182*e1eccf28SAndroid Build Coastguard Worker  */
validateGEMV(RS * mRS,const sp<const Element> & e,RsBlasTranspose TransA,const sp<Allocation> & A,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY)183*e1eccf28SAndroid Build Coastguard Worker static void validateGEMV(RS* mRS, const sp<const Element>& e, RsBlasTranspose TransA, const sp<Allocation>& A,
184*e1eccf28SAndroid Build Coastguard Worker                          const sp<Allocation>& X, int incX, const sp<Allocation>& Y, int incY) {
185*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
186*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
187*e1eccf28SAndroid Build Coastguard Worker     if (!A->getType()->getElement()->isCompatible(e) ||
188*e1eccf28SAndroid Build Coastguard Worker         !X->getType()->getElement()->isCompatible(e) ||
189*e1eccf28SAndroid Build Coastguard Worker         !Y->getType()->getElement()->isCompatible(e)) {
190*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
191*e1eccf28SAndroid Build Coastguard Worker     }
192*e1eccf28SAndroid Build Coastguard Worker     if (X->getType()->getY() > 1 || Y->getType()->getY() > 1) {
193*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "BLAS vectors must have Y dimension of 0 or 1");
194*e1eccf28SAndroid Build Coastguard Worker     }
195*e1eccf28SAndroid Build Coastguard Worker 
196*e1eccf28SAndroid Build Coastguard Worker     if (incX <= 0 || incY <= 0) {
197*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Vector increments must be greater than 0");
198*e1eccf28SAndroid Build Coastguard Worker     }
199*e1eccf28SAndroid Build Coastguard Worker     int expectedXDim = -1, expectedYDim = -1;
200*e1eccf28SAndroid Build Coastguard Worker     if (TransA == RsBlasNoTrans) {
201*e1eccf28SAndroid Build Coastguard Worker         expectedXDim = 1 + (N - 1) * incX;
202*e1eccf28SAndroid Build Coastguard Worker         expectedYDim = 1 + (M - 1) * incY;
203*e1eccf28SAndroid Build Coastguard Worker     } else {
204*e1eccf28SAndroid Build Coastguard Worker         expectedXDim = 1 + (M - 1) * incX;
205*e1eccf28SAndroid Build Coastguard Worker         expectedYDim = 1 + (N - 1) * incY;
206*e1eccf28SAndroid Build Coastguard Worker     }
207*e1eccf28SAndroid Build Coastguard Worker     if ((int)X->getType()->getX() != expectedXDim ||
208*e1eccf28SAndroid Build Coastguard Worker         (int)Y->getType()->getX() != expectedYDim) {
209*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for GEMV");
210*e1eccf28SAndroid Build Coastguard Worker     }
211*e1eccf28SAndroid Build Coastguard Worker }
212*e1eccf28SAndroid Build Coastguard Worker 
SGEMV(RsBlasTranspose TransA,float alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,float beta,const sp<Allocation> & Y,int incY)213*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SGEMV(RsBlasTranspose TransA, float alpha, const sp<Allocation>& A, const sp<Allocation>& X,
214*e1eccf28SAndroid Build Coastguard Worker                                 int incX, float beta, const sp<Allocation>& Y, int incY) {
215*e1eccf28SAndroid Build Coastguard Worker     validateGEMV(mRS, Element::F32(mRS), TransA, A, X, incX, Y, incY);
216*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
217*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
218*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_sgemv,
219*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, 0, 0, M, N, 0,
220*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), X->getID(),
221*e1eccf28SAndroid Build Coastguard Worker                                 beta, Y->getID(), incX, incY, 0, 0);
222*e1eccf28SAndroid Build Coastguard Worker }
223*e1eccf28SAndroid Build Coastguard Worker 
DGEMV(RsBlasTranspose TransA,double alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,double beta,const sp<Allocation> & Y,int incY)224*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DGEMV(RsBlasTranspose TransA, double alpha, const sp<Allocation>& A, const sp<Allocation>& X,
225*e1eccf28SAndroid Build Coastguard Worker                                 int incX, double beta, const sp<Allocation>& Y, int incY) {
226*e1eccf28SAndroid Build Coastguard Worker     validateGEMV(mRS, Element::F64(mRS), TransA, A, X, incX, Y, incY);
227*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
228*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
229*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dgemv,
230*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, 0, 0, M, N, 0,
231*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), X->getID(),
232*e1eccf28SAndroid Build Coastguard Worker                                 beta, Y->getID(), incX, incY, 0, 0);
233*e1eccf28SAndroid Build Coastguard Worker }
234*e1eccf28SAndroid Build Coastguard Worker 
CGEMV(RsBlasTranspose TransA,Float2 alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,Float2 beta,const sp<Allocation> & Y,int incY)235*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CGEMV(RsBlasTranspose TransA, Float2 alpha, const sp<Allocation>& A, const sp<Allocation>& X,
236*e1eccf28SAndroid Build Coastguard Worker                                 int incX, Float2 beta, const sp<Allocation>& Y, int incY) {
237*e1eccf28SAndroid Build Coastguard Worker     validateGEMV(mRS, Element::F32_2(mRS), TransA, A, X, incX, Y, incY);
238*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
239*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
240*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_cgemv,
241*e1eccf28SAndroid Build Coastguard Worker                                  TransA, 0, 0, 0, 0, M, N, 0,
242*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, A->getID(), X->getID(),
243*e1eccf28SAndroid Build Coastguard Worker                                  beta.x, beta.y, Y->getID(), incX, incY, 0, 0);
244*e1eccf28SAndroid Build Coastguard Worker }
245*e1eccf28SAndroid Build Coastguard Worker 
ZGEMV(RsBlasTranspose TransA,Double2 alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,Double2 beta,const sp<Allocation> & Y,int incY)246*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZGEMV(RsBlasTranspose TransA, Double2 alpha, const sp<Allocation>& A, const sp<Allocation>& X,
247*e1eccf28SAndroid Build Coastguard Worker                                 int incX, Double2 beta, const sp<Allocation>& Y, int incY) {
248*e1eccf28SAndroid Build Coastguard Worker     validateGEMV(mRS, Element::F64_2(mRS), TransA, A, X, incX, Y, incY);
249*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
250*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
251*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zgemv,
252*e1eccf28SAndroid Build Coastguard Worker                            TransA, 0, 0, 0, 0, M, N, 0,
253*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, A->getID(), X->getID(),
254*e1eccf28SAndroid Build Coastguard Worker                            beta.x, beta.y, Y->getID(), incX, incY, 0, 0);
255*e1eccf28SAndroid Build Coastguard Worker }
256*e1eccf28SAndroid Build Coastguard Worker 
SGBMV(RsBlasTranspose TransA,int KL,int KU,float alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,float beta,const sp<Allocation> & Y,int incY)257*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SGBMV(RsBlasTranspose TransA, int KL, int KU, float alpha, const sp<Allocation>& A,
258*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& X, int incX, float beta, const sp<Allocation>& Y, int incY) {
259*e1eccf28SAndroid Build Coastguard Worker     // GBMV has the same validation requirements as GEMV + KL and KU >= 0
260*e1eccf28SAndroid Build Coastguard Worker     validateGEMV(mRS, Element::F32(mRS), TransA, A, X, incX, Y, incY);
261*e1eccf28SAndroid Build Coastguard Worker     if (KL < 0 || KU < 0) {
262*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "KL and KU must be greater than or equal to 0");
263*e1eccf28SAndroid Build Coastguard Worker     }
264*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
265*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
266*e1eccf28SAndroid Build Coastguard Worker 
267*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_sgbmv,
268*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, 0, 0, M, N, 0,
269*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), X->getID(),
270*e1eccf28SAndroid Build Coastguard Worker                                 beta, Y->getID(), incX, incY, KL, KU);
271*e1eccf28SAndroid Build Coastguard Worker }
272*e1eccf28SAndroid Build Coastguard Worker 
DGBMV(RsBlasTranspose TransA,int KL,int KU,double alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,double beta,const sp<Allocation> & Y,int incY)273*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DGBMV(RsBlasTranspose TransA, int KL, int KU, double alpha, const sp<Allocation>& A,
274*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& X, int incX, double beta, const sp<Allocation>& Y, int incY) {
275*e1eccf28SAndroid Build Coastguard Worker     // GBMV has the same validation requirements as GEMV + KL and KU >= 0
276*e1eccf28SAndroid Build Coastguard Worker     validateGEMV(mRS, Element::F64(mRS), TransA, A, X, incX, Y, incY);
277*e1eccf28SAndroid Build Coastguard Worker     if (KL < 0 || KU < 0) {
278*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "KL and KU must be greater than or equal to 0");
279*e1eccf28SAndroid Build Coastguard Worker     }
280*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
281*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
282*e1eccf28SAndroid Build Coastguard Worker 
283*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dgbmv,
284*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, 0, 0, M, N, 0,
285*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), X->getID(),
286*e1eccf28SAndroid Build Coastguard Worker                                 beta, Y->getID(), incX, incY, KL, KU);
287*e1eccf28SAndroid Build Coastguard Worker }
288*e1eccf28SAndroid Build Coastguard Worker 
CGBMV(RsBlasTranspose TransA,int KL,int KU,Float2 alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,Float2 beta,const sp<Allocation> & Y,int incY)289*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CGBMV(RsBlasTranspose TransA, int KL, int KU, Float2 alpha, const sp<Allocation>& A,
290*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& X, int incX, Float2 beta, const sp<Allocation>& Y, int incY) {
291*e1eccf28SAndroid Build Coastguard Worker     // GBMV has the same validation requirements as GEMV + KL and KU >= 0
292*e1eccf28SAndroid Build Coastguard Worker     validateGEMV(mRS, Element::F32_2(mRS), TransA, A, X, incX, Y, incY);
293*e1eccf28SAndroid Build Coastguard Worker     if (KL < 0 || KU < 0) {
294*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "KL and KU must be greater than or equal to 0");
295*e1eccf28SAndroid Build Coastguard Worker     }
296*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
297*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
298*e1eccf28SAndroid Build Coastguard Worker 
299*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_cgbmv,
300*e1eccf28SAndroid Build Coastguard Worker                                  TransA, 0, 0, 0, 0, M, N, 0,
301*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, A->getID(), X->getID(),
302*e1eccf28SAndroid Build Coastguard Worker                                  beta.x, beta.y, Y->getID(), incX, incY, KL, KU);
303*e1eccf28SAndroid Build Coastguard Worker }
304*e1eccf28SAndroid Build Coastguard Worker 
ZGBMV(RsBlasTranspose TransA,int KL,int KU,Double2 alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,Double2 beta,const sp<Allocation> & Y,int incY)305*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZGBMV(RsBlasTranspose TransA, int KL, int KU, Double2 alpha, const sp<Allocation>& A,
306*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& X, int incX, Double2 beta, const sp<Allocation>& Y, int incY) {
307*e1eccf28SAndroid Build Coastguard Worker     // GBMV has the same validation requirements as GEMV + KL and KU >= 0
308*e1eccf28SAndroid Build Coastguard Worker     validateGEMV(mRS, Element::F64_2(mRS), TransA, A, X, incX, Y, incY);
309*e1eccf28SAndroid Build Coastguard Worker     if (KL < 0 || KU < 0) {
310*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "KL and KU must be greater than or equal to 0");
311*e1eccf28SAndroid Build Coastguard Worker     }
312*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
313*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
314*e1eccf28SAndroid Build Coastguard Worker 
315*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zgbmv,
316*e1eccf28SAndroid Build Coastguard Worker                            TransA, 0, 0, 0, 0, M, N, 0,
317*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, A->getID(), X->getID(),
318*e1eccf28SAndroid Build Coastguard Worker                            beta.x, beta.y, Y->getID(), incX, incY, KL, KU);
319*e1eccf28SAndroid Build Coastguard Worker }
320*e1eccf28SAndroid Build Coastguard Worker 
validateTRMV(RS * mRS,const sp<const Element> & e,RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & A,const sp<Allocation> & X,int incX)321*e1eccf28SAndroid Build Coastguard Worker static void validateTRMV(RS* mRS, const sp<const Element>& e, RsBlasUplo Uplo, RsBlasTranspose TransA,
322*e1eccf28SAndroid Build Coastguard Worker                          RsBlasDiag Diag, const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
323*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
324*e1eccf28SAndroid Build Coastguard Worker     if ((int)A->getType()->getX() != N) {
325*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "A must be a square matrix for TRMV");
326*e1eccf28SAndroid Build Coastguard Worker     }
327*e1eccf28SAndroid Build Coastguard Worker     if (!A->getType()->getElement()->isCompatible(e) ||
328*e1eccf28SAndroid Build Coastguard Worker         !X->getType()->getElement()->isCompatible(e)) {
329*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
330*e1eccf28SAndroid Build Coastguard Worker     }
331*e1eccf28SAndroid Build Coastguard Worker     if (X->getType()->getY() > 1) {
332*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "BLAS vectors must have Y dimension of 0 or 1");
333*e1eccf28SAndroid Build Coastguard Worker     }
334*e1eccf28SAndroid Build Coastguard Worker 
335*e1eccf28SAndroid Build Coastguard Worker     if (incX <= 0) {
336*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Vector increments must be greater than 0");
337*e1eccf28SAndroid Build Coastguard Worker     }
338*e1eccf28SAndroid Build Coastguard Worker     int expectedXDim = 1 + (N - 1) * incX;
339*e1eccf28SAndroid Build Coastguard Worker     if ((int)X->getType()->getX() != expectedXDim) {
340*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for TRMV");
341*e1eccf28SAndroid Build Coastguard Worker     }
342*e1eccf28SAndroid Build Coastguard Worker }
343*e1eccf28SAndroid Build Coastguard Worker 
validateTPMV(RS * mRS,const sp<const Element> & e,RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX)344*e1eccf28SAndroid Build Coastguard Worker static int validateTPMV(RS* mRS, const sp<const Element>& e,  RsBlasUplo Uplo, RsBlasTranspose TransA,
345*e1eccf28SAndroid Build Coastguard Worker                         RsBlasDiag Diag, const sp<Allocation>& Ap, const sp<Allocation>& X, int incX) {
346*e1eccf28SAndroid Build Coastguard Worker     if (!Ap->getType()->getElement()->isCompatible(e) ||
347*e1eccf28SAndroid Build Coastguard Worker         !X->getType()->getElement()->isCompatible(e)) {
348*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
349*e1eccf28SAndroid Build Coastguard Worker     }
350*e1eccf28SAndroid Build Coastguard Worker     if (X->getType()->getY() > 1) {
351*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "BLAS vectors must have Y dimension of 0 or 1");
352*e1eccf28SAndroid Build Coastguard Worker     }
353*e1eccf28SAndroid Build Coastguard Worker 
354*e1eccf28SAndroid Build Coastguard Worker     if (Ap->getType()->getY() > 1) {
355*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Ap must have a Y dimension of 0 or 1");
356*e1eccf28SAndroid Build Coastguard Worker     }
357*e1eccf28SAndroid Build Coastguard Worker 
358*e1eccf28SAndroid Build Coastguard Worker     int N = sqrt((double)Ap->getType()->getX() * 2);
359*e1eccf28SAndroid Build Coastguard Worker     if ((int)Ap->getType()->getX() != ((N * (N+1)) / 2)) {
360*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid dimension for Ap");
361*e1eccf28SAndroid Build Coastguard Worker     }
362*e1eccf28SAndroid Build Coastguard Worker     if (incX <= 0) {
363*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Vector increments must be greater than 0");
364*e1eccf28SAndroid Build Coastguard Worker     }
365*e1eccf28SAndroid Build Coastguard Worker     int expectedXDim = 1 + (N - 1) * incX;
366*e1eccf28SAndroid Build Coastguard Worker     if ((int)X->getType()->getX() != expectedXDim) {
367*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for TPMV");
368*e1eccf28SAndroid Build Coastguard Worker     }
369*e1eccf28SAndroid Build Coastguard Worker 
370*e1eccf28SAndroid Build Coastguard Worker     return N;
371*e1eccf28SAndroid Build Coastguard Worker }
372*e1eccf28SAndroid Build Coastguard Worker 
373*e1eccf28SAndroid Build Coastguard Worker 
STRMV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & A,const sp<Allocation> & X,int incX)374*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::STRMV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
375*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
376*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F32(mRS), Uplo, TransA, Diag, A, X, incX);
377*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
378*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_strmv,
379*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, Uplo, Diag, 0, N, 0, 0,
380*e1eccf28SAndroid Build Coastguard Worker                                 A->getID(), X->getID(), 0, 0, incX, 0, 0, 0);
381*e1eccf28SAndroid Build Coastguard Worker }
382*e1eccf28SAndroid Build Coastguard Worker 
DTRMV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & A,const sp<Allocation> & X,int incX)383*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DTRMV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
384*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
385*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F64(mRS), Uplo, TransA, Diag, A, X, incX);
386*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
387*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dtrmv,
388*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, Uplo, Diag, 0, N, 0, 0,
389*e1eccf28SAndroid Build Coastguard Worker                                 A->getID(), X->getID(), 0, 0, incX, 0, 0, 0);
390*e1eccf28SAndroid Build Coastguard Worker }
391*e1eccf28SAndroid Build Coastguard Worker 
CTRMV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & A,const sp<Allocation> & X,int incX)392*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CTRMV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
393*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
394*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F32_2(mRS), Uplo, TransA, Diag, A, X, incX);
395*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
396*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_ctrmv,
397*e1eccf28SAndroid Build Coastguard Worker                                  TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0,
398*e1eccf28SAndroid Build Coastguard Worker                                  A->getID(), X->getID(), 0, 0, 0, incX, 0, 0, 0);
399*e1eccf28SAndroid Build Coastguard Worker }
400*e1eccf28SAndroid Build Coastguard Worker 
ZTRMV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & A,const sp<Allocation> & X,int incX)401*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZTRMV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
402*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
403*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F64_2(mRS), Uplo, TransA, Diag, A, X, incX);
404*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
405*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_ztrmv,
406*e1eccf28SAndroid Build Coastguard Worker                            TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0,
407*e1eccf28SAndroid Build Coastguard Worker                            A->getID(), X->getID(), 0, 0, 0, incX, 0, 0, 0);
408*e1eccf28SAndroid Build Coastguard Worker }
409*e1eccf28SAndroid Build Coastguard Worker 
STBMV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,int K,const sp<Allocation> & A,const sp<Allocation> & X,int incX)410*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::STBMV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
411*e1eccf28SAndroid Build Coastguard Worker                                 int K, const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
412*e1eccf28SAndroid Build Coastguard Worker     // TBMV has the same requirements as TRMV + K >= 0
413*e1eccf28SAndroid Build Coastguard Worker     if (K < 0) {
414*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "K must be greater than or equal to 0");
415*e1eccf28SAndroid Build Coastguard Worker     }
416*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F32(mRS), Uplo, TransA, Diag, A, X, incX);
417*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
418*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_stbmv,
419*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, Uplo, Diag, 0, N, K, 0,
420*e1eccf28SAndroid Build Coastguard Worker                                 A->getID(), X->getID(), 0, 0, incX, 0, 0, 0);
421*e1eccf28SAndroid Build Coastguard Worker }
422*e1eccf28SAndroid Build Coastguard Worker 
DTBMV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,int K,const sp<Allocation> & A,const sp<Allocation> & X,int incX)423*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DTBMV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
424*e1eccf28SAndroid Build Coastguard Worker                                 int K, const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
425*e1eccf28SAndroid Build Coastguard Worker     // TBMV has the same requirements as TRMV + K >= 0
426*e1eccf28SAndroid Build Coastguard Worker     if (K < 0) {
427*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "K must be greater than or equal to 0");
428*e1eccf28SAndroid Build Coastguard Worker     }
429*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F64(mRS), Uplo, TransA, Diag, A, X, incX);
430*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
431*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dtbmv,
432*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, Uplo, Diag, 0, N, K, 0,
433*e1eccf28SAndroid Build Coastguard Worker                                 A->getID(), X->getID(), 0, 0, incX, 0, 0, 0);
434*e1eccf28SAndroid Build Coastguard Worker }
435*e1eccf28SAndroid Build Coastguard Worker 
CTBMV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,int K,const sp<Allocation> & A,const sp<Allocation> & X,int incX)436*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CTBMV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
437*e1eccf28SAndroid Build Coastguard Worker                                 int K, const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
438*e1eccf28SAndroid Build Coastguard Worker     // TBMV has the same requirements as TRMV + K >= 0
439*e1eccf28SAndroid Build Coastguard Worker     if (K < 0) {
440*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "K must be greater than or equal to 0");
441*e1eccf28SAndroid Build Coastguard Worker     }
442*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F32_2(mRS), Uplo, TransA, Diag, A, X, incX);
443*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
444*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_ctbmv,
445*e1eccf28SAndroid Build Coastguard Worker                                  TransA, 0, 0, Uplo, Diag, 0, N, K, 0, 0,
446*e1eccf28SAndroid Build Coastguard Worker                                  A->getID(), X->getID(), 0, 0, 0, incX, 0, 0, 0);
447*e1eccf28SAndroid Build Coastguard Worker }
448*e1eccf28SAndroid Build Coastguard Worker 
ZTBMV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,int K,const sp<Allocation> & A,const sp<Allocation> & X,int incX)449*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZTBMV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
450*e1eccf28SAndroid Build Coastguard Worker                                 int K, const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
451*e1eccf28SAndroid Build Coastguard Worker     // TBMV has the same requirements as TRMV + K >= 0
452*e1eccf28SAndroid Build Coastguard Worker     if (K < 0) {
453*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "K must be greater than or equal to 0");
454*e1eccf28SAndroid Build Coastguard Worker     }
455*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F64_2(mRS), Uplo, TransA, Diag, A, X, incX);
456*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
457*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_ztbmv,
458*e1eccf28SAndroid Build Coastguard Worker                            TransA, 0, 0, Uplo, Diag, 0, N, K, 0, 0,
459*e1eccf28SAndroid Build Coastguard Worker                            A->getID(), X->getID(), 0, 0, 0, incX, 0, 0, 0);
460*e1eccf28SAndroid Build Coastguard Worker }
461*e1eccf28SAndroid Build Coastguard Worker 
STPMV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX)462*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::STPMV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
463*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Ap, const sp<Allocation>& X, int incX) {
464*e1eccf28SAndroid Build Coastguard Worker     int N = validateTPMV(mRS, Element::F32(mRS), Uplo, TransA, Diag, Ap, X, incX);
465*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_stpmv,
466*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, Uplo, Diag, 0, N, 0, 0,
467*e1eccf28SAndroid Build Coastguard Worker                                 Ap->getID(), X->getID(), 0, 0, incX, 0, 0, 0);
468*e1eccf28SAndroid Build Coastguard Worker }
469*e1eccf28SAndroid Build Coastguard Worker 
DTPMV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX)470*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DTPMV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
471*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Ap, const sp<Allocation>& X, int incX) {
472*e1eccf28SAndroid Build Coastguard Worker     int N = validateTPMV(mRS, Element::F64(mRS), Uplo, TransA, Diag, Ap, X, incX);
473*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dtpmv,
474*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, Uplo, Diag, 0, N, 0, 0,
475*e1eccf28SAndroid Build Coastguard Worker                                 Ap->getID(), X->getID(), 0, 0, incX, 0, 0, 0);
476*e1eccf28SAndroid Build Coastguard Worker }
477*e1eccf28SAndroid Build Coastguard Worker 
CTPMV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX)478*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CTPMV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
479*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Ap,  const sp<Allocation>& X,  int incX) {
480*e1eccf28SAndroid Build Coastguard Worker     int N = validateTPMV(mRS, Element::F32_2(mRS), Uplo, TransA, Diag, Ap, X, incX);
481*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_ctpmv,
482*e1eccf28SAndroid Build Coastguard Worker                                  TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0,
483*e1eccf28SAndroid Build Coastguard Worker                                  Ap->getID(), X->getID(), 0, 0, 0, incX, 0, 0, 0);
484*e1eccf28SAndroid Build Coastguard Worker }
485*e1eccf28SAndroid Build Coastguard Worker 
ZTPMV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX)486*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZTPMV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
487*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Ap, const sp<Allocation>& X, int incX) {
488*e1eccf28SAndroid Build Coastguard Worker     int N = validateTPMV(mRS, Element::F64_2(mRS), Uplo, TransA, Diag, Ap, X, incX);
489*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_ztpmv,
490*e1eccf28SAndroid Build Coastguard Worker                            TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0,
491*e1eccf28SAndroid Build Coastguard Worker                            Ap->getID(), X->getID(), 0, 0, 0, incX, 0, 0, 0);
492*e1eccf28SAndroid Build Coastguard Worker }
493*e1eccf28SAndroid Build Coastguard Worker 
STRSV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & A,const sp<Allocation> & X,int incX)494*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::STRSV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
495*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
496*e1eccf28SAndroid Build Coastguard Worker     // TRSV is the same as TRMV
497*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F32(mRS), Uplo, TransA, Diag, A, X, incX);
498*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
499*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_strsv,
500*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, Uplo, Diag, 0, N, 0, 0,
501*e1eccf28SAndroid Build Coastguard Worker                                 A->getID(), X->getID(), 0, 0, incX, 0, 0, 0);
502*e1eccf28SAndroid Build Coastguard Worker }
503*e1eccf28SAndroid Build Coastguard Worker 
DTRSV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & A,const sp<Allocation> & X,int incX)504*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DTRSV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
505*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A,  const sp<Allocation>& X,  int incX) {
506*e1eccf28SAndroid Build Coastguard Worker     // TRSV is the same as TRMV
507*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F64(mRS), Uplo, TransA, Diag, A, X, incX);
508*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
509*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dtrsv,
510*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, Uplo, Diag, 0, N, 0, 0,
511*e1eccf28SAndroid Build Coastguard Worker                                 A->getID(), X->getID(), 0, 0, incX, 0, 0, 0);
512*e1eccf28SAndroid Build Coastguard Worker 
513*e1eccf28SAndroid Build Coastguard Worker }
514*e1eccf28SAndroid Build Coastguard Worker 
CTRSV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & A,const sp<Allocation> & X,int incX)515*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CTRSV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
516*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
517*e1eccf28SAndroid Build Coastguard Worker     // TRSV is the same as TRMV
518*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F32_2(mRS), Uplo, TransA, Diag, A, X, incX);
519*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
520*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_ctrsv,
521*e1eccf28SAndroid Build Coastguard Worker                                  TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0,
522*e1eccf28SAndroid Build Coastguard Worker                                  A->getID(), X->getID(), 0, 0, 0, incX, 0, 0, 0);
523*e1eccf28SAndroid Build Coastguard Worker 
524*e1eccf28SAndroid Build Coastguard Worker }
525*e1eccf28SAndroid Build Coastguard Worker 
ZTRSV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & A,const sp<Allocation> & X,int incX)526*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZTRSV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
527*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
528*e1eccf28SAndroid Build Coastguard Worker     // TRSV is the same as TRMV
529*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F64_2(mRS), Uplo, TransA, Diag, A, X, incX);
530*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
531*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_ztrsv,
532*e1eccf28SAndroid Build Coastguard Worker                            TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0,
533*e1eccf28SAndroid Build Coastguard Worker                            A->getID(), X->getID(), 0, 0, 0, incX, 0, 0, 0);
534*e1eccf28SAndroid Build Coastguard Worker 
535*e1eccf28SAndroid Build Coastguard Worker }
536*e1eccf28SAndroid Build Coastguard Worker 
STBSV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,int K,const sp<Allocation> & A,const sp<Allocation> & X,int incX)537*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::STBSV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
538*e1eccf28SAndroid Build Coastguard Worker                                 int K, const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
539*e1eccf28SAndroid Build Coastguard Worker     // TBSV is the same as TRMV + K >= 0
540*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F32(mRS), Uplo, TransA, Diag, A, X, incX);
541*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
542*e1eccf28SAndroid Build Coastguard Worker     if (K < 0) {
543*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Number of diagonals must be positive");
544*e1eccf28SAndroid Build Coastguard Worker     }
545*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_stbsv,
546*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, Uplo, Diag, 0, N, K, 0,
547*e1eccf28SAndroid Build Coastguard Worker                                 A->getID(), X->getID(), 0, 0, incX, 0, 0, 0);
548*e1eccf28SAndroid Build Coastguard Worker }
549*e1eccf28SAndroid Build Coastguard Worker 
DTBSV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,int K,const sp<Allocation> & A,const sp<Allocation> & X,int incX)550*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DTBSV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
551*e1eccf28SAndroid Build Coastguard Worker                                 int K, const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
552*e1eccf28SAndroid Build Coastguard Worker     // TBSV is the same as TRMV + K >= 0
553*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F64(mRS), Uplo, TransA, Diag, A, X, incX);
554*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
555*e1eccf28SAndroid Build Coastguard Worker     if (K < 0) {
556*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Number of diagonals must be positive");
557*e1eccf28SAndroid Build Coastguard Worker     }
558*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dtbsv,
559*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, Uplo, Diag, 0, N, K, 0,
560*e1eccf28SAndroid Build Coastguard Worker                                 A->getID(), X->getID(), 0, 0, incX, 0, 0, 0);
561*e1eccf28SAndroid Build Coastguard Worker }
562*e1eccf28SAndroid Build Coastguard Worker 
CTBSV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,int K,const sp<Allocation> & A,const sp<Allocation> & X,int incX)563*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CTBSV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
564*e1eccf28SAndroid Build Coastguard Worker                                 int K, const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
565*e1eccf28SAndroid Build Coastguard Worker     // TBSV is the same as TRMV + K >= 0
566*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F32_2(mRS), Uplo, TransA, Diag, A, X, incX);
567*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
568*e1eccf28SAndroid Build Coastguard Worker     if (K < 0) {
569*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Number of diagonals must be positive");
570*e1eccf28SAndroid Build Coastguard Worker     }
571*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_ctbsv,
572*e1eccf28SAndroid Build Coastguard Worker                                  TransA, 0, 0, Uplo, Diag, 0, N, K,
573*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, A->getID(), X->getID(), 0, 0, 0, incX, 0, 0, 0);
574*e1eccf28SAndroid Build Coastguard Worker }
575*e1eccf28SAndroid Build Coastguard Worker 
ZTBSV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,int K,const sp<Allocation> & A,const sp<Allocation> & X,int incX)576*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZTBSV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
577*e1eccf28SAndroid Build Coastguard Worker                                 int K, const sp<Allocation>& A, const sp<Allocation>& X, int incX) {
578*e1eccf28SAndroid Build Coastguard Worker     // TBSV is the same as TRMV + K >= 0
579*e1eccf28SAndroid Build Coastguard Worker     validateTRMV(mRS, Element::F64_2(mRS), Uplo, TransA, Diag, A, X, incX);
580*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
581*e1eccf28SAndroid Build Coastguard Worker     if (K < 0) {
582*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Number of diagonals must be positive");
583*e1eccf28SAndroid Build Coastguard Worker     }
584*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_ztbsv,
585*e1eccf28SAndroid Build Coastguard Worker                            TransA, 0, 0, Uplo, Diag, 0, N, K, 0, 0,
586*e1eccf28SAndroid Build Coastguard Worker                            A->getID(), X->getID(), 0, 0, 0, incX, 0, 0, 0);
587*e1eccf28SAndroid Build Coastguard Worker }
588*e1eccf28SAndroid Build Coastguard Worker 
STPSV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX)589*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::STPSV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
590*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Ap, const sp<Allocation>& X, int incX) {
591*e1eccf28SAndroid Build Coastguard Worker     // TPSV is same as TPMV
592*e1eccf28SAndroid Build Coastguard Worker     int N = validateTPMV(mRS, Element::F32(mRS), Uplo, TransA, Diag, Ap, X, incX);
593*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_stpsv,
594*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, Uplo, Diag, 0, N, 0, 0,
595*e1eccf28SAndroid Build Coastguard Worker                                 Ap->getID(), X->getID(), 0, 0, incX, 0, 0, 0);
596*e1eccf28SAndroid Build Coastguard Worker }
597*e1eccf28SAndroid Build Coastguard Worker 
DTPSV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX)598*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DTPSV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
599*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Ap, const sp<Allocation>& X, int incX) {
600*e1eccf28SAndroid Build Coastguard Worker     // TPSV is same as TPMV
601*e1eccf28SAndroid Build Coastguard Worker     int N = validateTPMV(mRS, Element::F64(mRS), Uplo, TransA, Diag, Ap, X, incX);
602*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dtpsv,
603*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, 0, Uplo, Diag, 0, N, 0, 0,
604*e1eccf28SAndroid Build Coastguard Worker                                 Ap->getID(), X->getID(), 0, 0, incX, 0, 0, 0);
605*e1eccf28SAndroid Build Coastguard Worker }
606*e1eccf28SAndroid Build Coastguard Worker 
CTPSV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX)607*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CTPSV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
608*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Ap, const sp<Allocation>& X, int incX) {
609*e1eccf28SAndroid Build Coastguard Worker     // TPSV is same as TPMV
610*e1eccf28SAndroid Build Coastguard Worker     int N = validateTPMV(mRS, Element::F32_2(mRS), Uplo, TransA, Diag, Ap, X, incX);
611*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_ctpsv,
612*e1eccf28SAndroid Build Coastguard Worker                                  TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0,
613*e1eccf28SAndroid Build Coastguard Worker                                  Ap->getID(), X->getID(), 0, 0, 0, incX, 0, 0, 0);
614*e1eccf28SAndroid Build Coastguard Worker }
615*e1eccf28SAndroid Build Coastguard Worker 
ZTPSV(RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX)616*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZTPSV(RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
617*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Ap, const sp<Allocation>& X, int incX) {
618*e1eccf28SAndroid Build Coastguard Worker     // TPSV is same as TPMV
619*e1eccf28SAndroid Build Coastguard Worker     int N = validateTPMV(mRS, Element::F64_2(mRS), Uplo, TransA, Diag, Ap, X, incX);
620*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_ztpsv,
621*e1eccf28SAndroid Build Coastguard Worker                            TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0,
622*e1eccf28SAndroid Build Coastguard Worker                            Ap->getID(), X->getID(), 0, 0, 0, incX, 0, 0, 0);
623*e1eccf28SAndroid Build Coastguard Worker }
624*e1eccf28SAndroid Build Coastguard Worker 
625*e1eccf28SAndroid Build Coastguard Worker /**
626*e1eccf28SAndroid Build Coastguard Worker  * Level 2, S and D only
627*e1eccf28SAndroid Build Coastguard Worker  */
validateSYMV(RS * mRS,const sp<const Element> & e,RsBlasUplo Uplo,const sp<Allocation> & A,const sp<Allocation> & X,const sp<Allocation> & Y,int incX,int incY)628*e1eccf28SAndroid Build Coastguard Worker static int validateSYMV(RS* mRS, const sp<const Element>& e, RsBlasUplo Uplo, const sp<Allocation>& A,
629*e1eccf28SAndroid Build Coastguard Worker                         const sp<Allocation>& X, const sp<Allocation>& Y, int incX, int incY) {
630*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getY();
631*e1eccf28SAndroid Build Coastguard Worker     if ((int)A->getType()->getX() != N) {
632*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "A must be a square matrix for SYMV");
633*e1eccf28SAndroid Build Coastguard Worker     }
634*e1eccf28SAndroid Build Coastguard Worker     if (!A->getType()->getElement()->isCompatible(e) ||
635*e1eccf28SAndroid Build Coastguard Worker         !X->getType()->getElement()->isCompatible(e) ||
636*e1eccf28SAndroid Build Coastguard Worker         !Y->getType()->getElement()->isCompatible(e) ) {
637*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
638*e1eccf28SAndroid Build Coastguard Worker     }
639*e1eccf28SAndroid Build Coastguard Worker     if (X->getType()->getY() > 1 || Y->getType()->getY() > 1) {
640*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "BLAS vectors must have Y dimension of 0 or 1");
641*e1eccf28SAndroid Build Coastguard Worker     }
642*e1eccf28SAndroid Build Coastguard Worker 
643*e1eccf28SAndroid Build Coastguard Worker     if (incX <= 0 || incY <= 0) {
644*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Vector increments must be greater than 0");
645*e1eccf28SAndroid Build Coastguard Worker     }
646*e1eccf28SAndroid Build Coastguard Worker     int expectedXDim = 1 + (N - 1) * incX;
647*e1eccf28SAndroid Build Coastguard Worker     if ((int)X->getType()->getX() != expectedXDim) {
648*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for SYMV");
649*e1eccf28SAndroid Build Coastguard Worker     }
650*e1eccf28SAndroid Build Coastguard Worker     int expectedYDim = 1 + (N - 1) * incY;
651*e1eccf28SAndroid Build Coastguard Worker     if ((int)Y->getType()->getX() != expectedYDim) {
652*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for SYMV");
653*e1eccf28SAndroid Build Coastguard Worker     }
654*e1eccf28SAndroid Build Coastguard Worker     return N;
655*e1eccf28SAndroid Build Coastguard Worker }
validateSPMV(RS * mRS,const sp<const Element> & e,RsBlasUplo Uplo,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY)656*e1eccf28SAndroid Build Coastguard Worker static int validateSPMV(RS* mRS, const sp<const Element>& e, RsBlasUplo Uplo, const sp<Allocation>& Ap,
657*e1eccf28SAndroid Build Coastguard Worker                         const sp<Allocation>& X, int incX, const sp<Allocation>& Y, int incY) {
658*e1eccf28SAndroid Build Coastguard Worker     if (!Ap->getType()->getElement()->isCompatible(e) ||
659*e1eccf28SAndroid Build Coastguard Worker         !X->getType()->getElement()->isCompatible(e) ||
660*e1eccf28SAndroid Build Coastguard Worker         !Y->getType()->getElement()->isCompatible(e)) {
661*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
662*e1eccf28SAndroid Build Coastguard Worker     }
663*e1eccf28SAndroid Build Coastguard Worker     if (X->getType()->getY() > 1 || Y->getType()->getY() > 1) {
664*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "BLAS vectors must have Y dimension of 0 or 1");
665*e1eccf28SAndroid Build Coastguard Worker     }
666*e1eccf28SAndroid Build Coastguard Worker 
667*e1eccf28SAndroid Build Coastguard Worker     if (Ap->getType()->getY() > 1) {
668*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Ap must have a Y dimension of 0 or 1");
669*e1eccf28SAndroid Build Coastguard Worker     }
670*e1eccf28SAndroid Build Coastguard Worker 
671*e1eccf28SAndroid Build Coastguard Worker     int N = sqrt((double)Ap->getType()->getX() * 2);
672*e1eccf28SAndroid Build Coastguard Worker     if ((int)Ap->getType()->getX() != ((N * (N+1)) / 2)) {
673*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid dimension for Ap");
674*e1eccf28SAndroid Build Coastguard Worker     }
675*e1eccf28SAndroid Build Coastguard Worker     if (incX <= 0 || incY <= 0) {
676*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Vector increments must be greater than 0");
677*e1eccf28SAndroid Build Coastguard Worker     }
678*e1eccf28SAndroid Build Coastguard Worker     int expectedXDim = 1 + (N - 1) * incX;
679*e1eccf28SAndroid Build Coastguard Worker     if ((int)X->getType()->getX() != expectedXDim) {
680*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for SPMV");
681*e1eccf28SAndroid Build Coastguard Worker     }
682*e1eccf28SAndroid Build Coastguard Worker     int expectedYDim = 1 + (N - 1) * incY;
683*e1eccf28SAndroid Build Coastguard Worker     if ((int)Y->getType()->getX() != expectedYDim) {
684*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for SPMV");
685*e1eccf28SAndroid Build Coastguard Worker     }
686*e1eccf28SAndroid Build Coastguard Worker 
687*e1eccf28SAndroid Build Coastguard Worker     return N;
688*e1eccf28SAndroid Build Coastguard Worker }
validateGER(RS * mRS,const sp<const Element> & e,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & A)689*e1eccf28SAndroid Build Coastguard Worker static void validateGER(RS* mRS, const sp<const Element>& e, const sp<Allocation>& X, int incX,
690*e1eccf28SAndroid Build Coastguard Worker                         const sp<Allocation>& Y, int incY, const sp<Allocation>& A) {
691*e1eccf28SAndroid Build Coastguard Worker     if (!A->getType()->getElement()->isCompatible(e) ||
692*e1eccf28SAndroid Build Coastguard Worker         !X->getType()->getElement()->isCompatible(e) ||
693*e1eccf28SAndroid Build Coastguard Worker         !Y->getType()->getElement()->isCompatible(e) ) {
694*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
695*e1eccf28SAndroid Build Coastguard Worker     }
696*e1eccf28SAndroid Build Coastguard Worker 
697*e1eccf28SAndroid Build Coastguard Worker     if (X->getType()->getY() > 1 || Y->getType()->getY() > 1) {
698*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "BLAS vectors must have Y dimension of 0 or 1");
699*e1eccf28SAndroid Build Coastguard Worker     }
700*e1eccf28SAndroid Build Coastguard Worker 
701*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
702*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
703*e1eccf28SAndroid Build Coastguard Worker 
704*e1eccf28SAndroid Build Coastguard Worker     if (N < 1 || M < 1) {
705*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "M and N must be 1 or greater for GER");
706*e1eccf28SAndroid Build Coastguard Worker     }
707*e1eccf28SAndroid Build Coastguard Worker     if (incX <= 0 || incY <= 0) {
708*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Vector increments must be greater than 0");
709*e1eccf28SAndroid Build Coastguard Worker     }
710*e1eccf28SAndroid Build Coastguard Worker     int expectedXDim = 1 + (M - 1) * incX;
711*e1eccf28SAndroid Build Coastguard Worker     if ((int)X->getType()->getX() != expectedXDim) {
712*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for GER");
713*e1eccf28SAndroid Build Coastguard Worker     }
714*e1eccf28SAndroid Build Coastguard Worker     int expectedYDim = 1 + (N - 1) * incY;
715*e1eccf28SAndroid Build Coastguard Worker     if ((int)Y->getType()->getX() != expectedYDim) {
716*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for GER");
717*e1eccf28SAndroid Build Coastguard Worker     }
718*e1eccf28SAndroid Build Coastguard Worker 
719*e1eccf28SAndroid Build Coastguard Worker 
720*e1eccf28SAndroid Build Coastguard Worker }
validateSYR(RS * mRS,const sp<const Element> & e,RsBlasUplo Uplo,const sp<Allocation> & X,int incX,const sp<Allocation> & A)721*e1eccf28SAndroid Build Coastguard Worker static int validateSYR(RS* mRS, const sp<const Element>& e, RsBlasUplo Uplo,
722*e1eccf28SAndroid Build Coastguard Worker                        const sp<Allocation>& X, int incX, const sp<Allocation>& A) {
723*e1eccf28SAndroid Build Coastguard Worker     if (!A->getType()->getElement()->isCompatible(e) ||
724*e1eccf28SAndroid Build Coastguard Worker         !X->getType()->getElement()->isCompatible(e)) {
725*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
726*e1eccf28SAndroid Build Coastguard Worker     }
727*e1eccf28SAndroid Build Coastguard Worker 
728*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
729*e1eccf28SAndroid Build Coastguard Worker 
730*e1eccf28SAndroid Build Coastguard Worker     if (X->getType()->getY() > 1) {
731*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "BLAS vectors must have Y dimension of 0 or 1");
732*e1eccf28SAndroid Build Coastguard Worker     }
733*e1eccf28SAndroid Build Coastguard Worker     if (N != (int)A->getType()->getY()) {
734*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "A must be a symmetric matrix");
735*e1eccf28SAndroid Build Coastguard Worker     }
736*e1eccf28SAndroid Build Coastguard Worker     if (incX <= 0) {
737*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Vector increments must be greater than 0");
738*e1eccf28SAndroid Build Coastguard Worker     }
739*e1eccf28SAndroid Build Coastguard Worker     int expectedXDim = 1 + (N - 1) * incX;
740*e1eccf28SAndroid Build Coastguard Worker     if ((int)X->getType()->getX() != expectedXDim) {
741*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for SYR");
742*e1eccf28SAndroid Build Coastguard Worker     }
743*e1eccf28SAndroid Build Coastguard Worker     return N;
744*e1eccf28SAndroid Build Coastguard Worker }
validateSPR(RS * mRS,const sp<const Element> & e,RsBlasUplo Uplo,const sp<Allocation> & X,int incX,const sp<Allocation> & Ap)745*e1eccf28SAndroid Build Coastguard Worker static int validateSPR(RS* mRS, const sp<const Element>& e, RsBlasUplo Uplo,
746*e1eccf28SAndroid Build Coastguard Worker                        const sp<Allocation>& X, int incX, const sp<Allocation>& Ap) {
747*e1eccf28SAndroid Build Coastguard Worker     if (!Ap->getType()->getElement()->isCompatible(e) ||
748*e1eccf28SAndroid Build Coastguard Worker         !X->getType()->getElement()->isCompatible(e)) {
749*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
750*e1eccf28SAndroid Build Coastguard Worker     }
751*e1eccf28SAndroid Build Coastguard Worker     if (X->getType()->getY() > 1) {
752*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "BLAS vectors must have Y dimension of 0 or 1");
753*e1eccf28SAndroid Build Coastguard Worker     }
754*e1eccf28SAndroid Build Coastguard Worker 
755*e1eccf28SAndroid Build Coastguard Worker     if (Ap->getType()->getY() > 1) {
756*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Ap must have a Y dimension of 0 or 1");
757*e1eccf28SAndroid Build Coastguard Worker     }
758*e1eccf28SAndroid Build Coastguard Worker 
759*e1eccf28SAndroid Build Coastguard Worker     int N = sqrt((double)Ap->getType()->getX() * 2);
760*e1eccf28SAndroid Build Coastguard Worker     if ((int)Ap->getType()->getX() != ((N * (N+1)) / 2)) {
761*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid dimension for Ap");
762*e1eccf28SAndroid Build Coastguard Worker     }
763*e1eccf28SAndroid Build Coastguard Worker     if (incX <= 0) {
764*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Vector increments must be greater than 0");
765*e1eccf28SAndroid Build Coastguard Worker     }
766*e1eccf28SAndroid Build Coastguard Worker     int expectedXDim = 1 + (N - 1) * incX;
767*e1eccf28SAndroid Build Coastguard Worker     if ((int)X->getType()->getX() != expectedXDim) {
768*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for SPR");
769*e1eccf28SAndroid Build Coastguard Worker     }
770*e1eccf28SAndroid Build Coastguard Worker 
771*e1eccf28SAndroid Build Coastguard Worker     return N;
772*e1eccf28SAndroid Build Coastguard Worker }
773*e1eccf28SAndroid Build Coastguard Worker 
validateSYR2(RS * mRS,const sp<const Element> & e,RsBlasUplo Uplo,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & A)774*e1eccf28SAndroid Build Coastguard Worker static int validateSYR2(RS* mRS, const sp<const Element>& e, RsBlasUplo Uplo, const sp<Allocation>& X,
775*e1eccf28SAndroid Build Coastguard Worker                         int incX, const sp<Allocation>& Y, int incY, const sp<Allocation>& A) {
776*e1eccf28SAndroid Build Coastguard Worker     if (!A->getType()->getElement()->isCompatible(e) ||
777*e1eccf28SAndroid Build Coastguard Worker         !X->getType()->getElement()->isCompatible(e) ||
778*e1eccf28SAndroid Build Coastguard Worker         !Y->getType()->getElement()->isCompatible(e)) {
779*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
780*e1eccf28SAndroid Build Coastguard Worker     }
781*e1eccf28SAndroid Build Coastguard Worker 
782*e1eccf28SAndroid Build Coastguard Worker     if (X->getType()->getY() > 1 || Y->getType()->getY() > 1) {
783*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "BLAS vectors must have Y dimension of 0 or 1");
784*e1eccf28SAndroid Build Coastguard Worker     }
785*e1eccf28SAndroid Build Coastguard Worker 
786*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
787*e1eccf28SAndroid Build Coastguard Worker 
788*e1eccf28SAndroid Build Coastguard Worker     if (N != (int)A->getType()->getY()) {
789*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "A must be a symmetric matrix");
790*e1eccf28SAndroid Build Coastguard Worker     }
791*e1eccf28SAndroid Build Coastguard Worker     if (incX <= 0 || incY <= 0) {
792*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Vector increments must be greater than 0");
793*e1eccf28SAndroid Build Coastguard Worker     }
794*e1eccf28SAndroid Build Coastguard Worker     int expectedXDim = 1 + (N - 1) * incX;
795*e1eccf28SAndroid Build Coastguard Worker     int expectedYDim = 1 + (N - 1) * incY;
796*e1eccf28SAndroid Build Coastguard Worker     if ((int)X->getType()->getX() != expectedXDim || (int)Y->getType()->getX() != expectedYDim) {
797*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for SYR");
798*e1eccf28SAndroid Build Coastguard Worker     }
799*e1eccf28SAndroid Build Coastguard Worker     return N;
800*e1eccf28SAndroid Build Coastguard Worker 
801*e1eccf28SAndroid Build Coastguard Worker }
validateSPR2(RS * mRS,const sp<const Element> & e,RsBlasUplo Uplo,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & Ap)802*e1eccf28SAndroid Build Coastguard Worker static int validateSPR2(RS* mRS, const sp<const Element>& e, RsBlasUplo Uplo, const sp<Allocation>& X,
803*e1eccf28SAndroid Build Coastguard Worker                         int incX, const sp<Allocation>& Y, int incY, const sp<Allocation>& Ap) {
804*e1eccf28SAndroid Build Coastguard Worker     if (!Ap->getType()->getElement()->isCompatible(e) ||
805*e1eccf28SAndroid Build Coastguard Worker         !X->getType()->getElement()->isCompatible(e) ||
806*e1eccf28SAndroid Build Coastguard Worker         !Y->getType()->getElement()->isCompatible(e)) {
807*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
808*e1eccf28SAndroid Build Coastguard Worker     }
809*e1eccf28SAndroid Build Coastguard Worker     if (X->getType()->getY() > 1 || Y->getType()->getY() > 1) {
810*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "BLAS vectors must have Y dimension of 0 or 1");
811*e1eccf28SAndroid Build Coastguard Worker     }
812*e1eccf28SAndroid Build Coastguard Worker 
813*e1eccf28SAndroid Build Coastguard Worker     if (Ap->getType()->getY() > 1) {
814*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Ap must have a Y dimension of 0 or 1");
815*e1eccf28SAndroid Build Coastguard Worker     }
816*e1eccf28SAndroid Build Coastguard Worker 
817*e1eccf28SAndroid Build Coastguard Worker     int N = sqrt((double)Ap->getType()->getX() * 2);
818*e1eccf28SAndroid Build Coastguard Worker     if ((int)Ap->getType()->getX() != ((N * (N+1)) / 2)) {
819*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid dimension for Ap");
820*e1eccf28SAndroid Build Coastguard Worker     }
821*e1eccf28SAndroid Build Coastguard Worker     if (incX <= 0 || incY <= 0) {
822*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Vector increments must be greater than 0");
823*e1eccf28SAndroid Build Coastguard Worker     }
824*e1eccf28SAndroid Build Coastguard Worker     int expectedXDim = 1 + (N - 1) * incX;
825*e1eccf28SAndroid Build Coastguard Worker     int expectedYDim = 1 + (N - 1) * incY;
826*e1eccf28SAndroid Build Coastguard Worker     if ((int)X->getType()->getX() != expectedXDim || (int)Y->getType()->getX() != expectedYDim) {
827*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for SPR2");
828*e1eccf28SAndroid Build Coastguard Worker     }
829*e1eccf28SAndroid Build Coastguard Worker 
830*e1eccf28SAndroid Build Coastguard Worker     return N;
831*e1eccf28SAndroid Build Coastguard Worker }
832*e1eccf28SAndroid Build Coastguard Worker 
SSYMV(RsBlasUplo Uplo,float alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,float beta,const sp<Allocation> & Y,int incY)833*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SSYMV(RsBlasUplo Uplo, float alpha, const sp<Allocation>& A, const sp<Allocation>& X,
834*e1eccf28SAndroid Build Coastguard Worker                                 int incX, float beta, const sp<Allocation>& Y, int incY) {
835*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYMV(mRS, Element::F32(mRS), Uplo, A, X, Y, incX, incY);
836*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_ssymv,
837*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, 0, alpha,
838*e1eccf28SAndroid Build Coastguard Worker                                 A->getID(), X->getID(), beta, Y->getID(), incX, incY, 0, 0);
839*e1eccf28SAndroid Build Coastguard Worker }
840*e1eccf28SAndroid Build Coastguard Worker 
SSBMV(RsBlasUplo Uplo,int K,float alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,float beta,const sp<Allocation> & Y,int incY)841*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SSBMV(RsBlasUplo Uplo, int K, float alpha, const sp<Allocation>& A, const sp<Allocation>& X,
842*e1eccf28SAndroid Build Coastguard Worker                                 int incX, float beta, const sp<Allocation>& Y, int incY) {
843*e1eccf28SAndroid Build Coastguard Worker     // SBMV is the same as SYMV + K >= 0
844*e1eccf28SAndroid Build Coastguard Worker     if (K < 0) {
845*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "K must be greater than or equal to 0");
846*e1eccf28SAndroid Build Coastguard Worker     }
847*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYMV(mRS, Element::F32(mRS), Uplo, A, X, Y, incX, incY);
848*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_ssbmv,
849*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, K, alpha,
850*e1eccf28SAndroid Build Coastguard Worker                                 A->getID(), X->getID(), beta, Y->getID(), incX, incY, 0, 0);
851*e1eccf28SAndroid Build Coastguard Worker }
852*e1eccf28SAndroid Build Coastguard Worker 
SSPMV(RsBlasUplo Uplo,float alpha,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX,float beta,const sp<Allocation> & Y,int incY)853*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SSPMV(RsBlasUplo Uplo, float alpha, const sp<Allocation>& Ap, const sp<Allocation>& X,
854*e1eccf28SAndroid Build Coastguard Worker                                 int incX, float beta, const sp<Allocation>& Y, int incY) {
855*e1eccf28SAndroid Build Coastguard Worker     int N = validateSPMV(mRS, Element::F32(mRS), Uplo, Ap, X, incX, Y, incY);
856*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_sspmv,
857*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, 0, alpha,
858*e1eccf28SAndroid Build Coastguard Worker                                 Ap->getID(), X->getID(), beta, Y->getID(), incX, incY, 0, 0);
859*e1eccf28SAndroid Build Coastguard Worker }
860*e1eccf28SAndroid Build Coastguard Worker 
SGER(float alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & A)861*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SGER(float alpha, const sp<Allocation>& X, int incX,
862*e1eccf28SAndroid Build Coastguard Worker                                const sp<Allocation>& Y, int incY, const sp<Allocation>& A) {
863*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
864*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
865*e1eccf28SAndroid Build Coastguard Worker     validateGER(mRS, Element::F32(mRS), X, incX, Y, incY, A);
866*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_sger,
867*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, 0, 0, M, N, 0, alpha,
868*e1eccf28SAndroid Build Coastguard Worker                                 X->getID(), Y->getID(), 0.f, A->getID(), incX, incY, 0, 0);
869*e1eccf28SAndroid Build Coastguard Worker }
870*e1eccf28SAndroid Build Coastguard Worker 
SSYR(RsBlasUplo Uplo,float alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & A)871*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SSYR(RsBlasUplo Uplo, float alpha, const sp<Allocation>& X,
872*e1eccf28SAndroid Build Coastguard Worker                                int incX, const sp<Allocation>& A) {
873*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYR(mRS, Element::F32(mRS), Uplo, X, incX, A);
874*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_ssyr,
875*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, 0, alpha,
876*e1eccf28SAndroid Build Coastguard Worker                                 X->getID(), A->getID(), 0.f, 0, incX, 0, 0, 0);
877*e1eccf28SAndroid Build Coastguard Worker }
878*e1eccf28SAndroid Build Coastguard Worker 
SSPR(RsBlasUplo Uplo,float alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Ap)879*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SSPR(RsBlasUplo Uplo, float alpha, const sp<Allocation>& X,
880*e1eccf28SAndroid Build Coastguard Worker                                int incX, const sp<Allocation>& Ap) {
881*e1eccf28SAndroid Build Coastguard Worker     int N = validateSPR(mRS, Element::F32(mRS), Uplo, X, incX, Ap);
882*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_sspr,
883*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, 0,
884*e1eccf28SAndroid Build Coastguard Worker                                 alpha, X->getID(), Ap->getID(), 0.f, 0, incX, 0, 0, 0);
885*e1eccf28SAndroid Build Coastguard Worker }
886*e1eccf28SAndroid Build Coastguard Worker 
SSYR2(RsBlasUplo Uplo,float alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & A)887*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SSYR2(RsBlasUplo Uplo, float alpha, const sp<Allocation>& X, int incX,
888*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Y, int incY, const sp<Allocation>& A) {
889*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYR2(mRS, Element::F32(mRS), Uplo, X, incX, Y, incY, A);
890*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_ssyr2,
891*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, 0, alpha,
892*e1eccf28SAndroid Build Coastguard Worker                                 X->getID(), Y->getID(), 0, A->getID(), incX, incY, 0, 0);
893*e1eccf28SAndroid Build Coastguard Worker }
894*e1eccf28SAndroid Build Coastguard Worker 
SSPR2(RsBlasUplo Uplo,float alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & Ap)895*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SSPR2(RsBlasUplo Uplo, float alpha, const sp<Allocation>& X, int incX,
896*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Y, int incY, const sp<Allocation>& Ap) {
897*e1eccf28SAndroid Build Coastguard Worker     int N = validateSPR2(mRS, Element::F32(mRS), Uplo, X, incX, Y, incY, Ap);
898*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_sspr2,
899*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, 0, alpha,
900*e1eccf28SAndroid Build Coastguard Worker                                 X->getID(), Y->getID(), 0, Ap->getID(), incX, incY, 0, 0);
901*e1eccf28SAndroid Build Coastguard Worker }
902*e1eccf28SAndroid Build Coastguard Worker 
DSYMV(RsBlasUplo Uplo,double alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,double beta,const sp<Allocation> & Y,int incY)903*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DSYMV(RsBlasUplo Uplo, double alpha, const sp<Allocation>& A, const sp<Allocation>& X,
904*e1eccf28SAndroid Build Coastguard Worker                                 int incX, double beta, const sp<Allocation>& Y, int incY) {
905*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYMV(mRS, Element::F64(mRS), Uplo, A, X, Y, incX, incY);
906*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dsymv,
907*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, 0, alpha,
908*e1eccf28SAndroid Build Coastguard Worker                                 A->getID(), X->getID(), beta, Y->getID(), incX, incY, 0, 0);
909*e1eccf28SAndroid Build Coastguard Worker }
910*e1eccf28SAndroid Build Coastguard Worker 
DSBMV(RsBlasUplo Uplo,int K,double alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,double beta,const sp<Allocation> & Y,int incY)911*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DSBMV(RsBlasUplo Uplo, int K, double alpha, const sp<Allocation>& A, const sp<Allocation>& X,
912*e1eccf28SAndroid Build Coastguard Worker                                 int incX, double beta, const sp<Allocation>& Y, int incY) {
913*e1eccf28SAndroid Build Coastguard Worker     // SBMV is the same as SYMV + K >= 0
914*e1eccf28SAndroid Build Coastguard Worker     if (K < 0) {
915*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "K must be greater than or equal to 0");
916*e1eccf28SAndroid Build Coastguard Worker     }
917*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYMV(mRS, Element::F64(mRS), Uplo, A, X, Y, incX, incY);
918*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dsbmv,
919*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, K, alpha,
920*e1eccf28SAndroid Build Coastguard Worker                                 A->getID(), X->getID(), beta, Y->getID(), incX, incY, 0, 0);
921*e1eccf28SAndroid Build Coastguard Worker }
922*e1eccf28SAndroid Build Coastguard Worker 
DSPMV(RsBlasUplo Uplo,double alpha,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX,double beta,const sp<Allocation> & Y,int incY)923*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DSPMV(RsBlasUplo Uplo, double alpha, const sp<Allocation>& Ap, const sp<Allocation>& X,
924*e1eccf28SAndroid Build Coastguard Worker                                 int incX, double beta, const sp<Allocation>& Y, int incY) {
925*e1eccf28SAndroid Build Coastguard Worker     int N = validateSPMV(mRS, Element::F64(mRS), Uplo, Ap, X, incX, Y, incY);
926*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dspmv,
927*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, 0, alpha,
928*e1eccf28SAndroid Build Coastguard Worker                                 Ap->getID(), X->getID(), beta, Y->getID(), incX, incY, 0, 0);
929*e1eccf28SAndroid Build Coastguard Worker }
930*e1eccf28SAndroid Build Coastguard Worker 
DGER(double alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & A)931*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DGER(double alpha, const sp<Allocation>& X, int incX, const sp<Allocation>& Y,
932*e1eccf28SAndroid Build Coastguard Worker                                int incY, const sp<Allocation>& A) {
933*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
934*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
935*e1eccf28SAndroid Build Coastguard Worker     validateGER(mRS, Element::F64(mRS), X, incX, Y, incY, A);
936*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dger,
937*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, 0, 0, M, N, 0, alpha,
938*e1eccf28SAndroid Build Coastguard Worker                                 X->getID(), Y->getID(), 0.f, A->getID(), incX, incY, 0, 0);
939*e1eccf28SAndroid Build Coastguard Worker }
940*e1eccf28SAndroid Build Coastguard Worker 
DSYR(RsBlasUplo Uplo,double alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & A)941*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DSYR(RsBlasUplo Uplo, double alpha, const sp<Allocation>& X,
942*e1eccf28SAndroid Build Coastguard Worker                                int incX, const sp<Allocation>& A) {
943*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYR(mRS, Element::F64(mRS), Uplo, X, incX, A);
944*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dsyr,
945*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, 0, alpha,
946*e1eccf28SAndroid Build Coastguard Worker                                 X->getID(), A->getID(), 0.f, 0, incX, 0, 0, 0);
947*e1eccf28SAndroid Build Coastguard Worker }
948*e1eccf28SAndroid Build Coastguard Worker 
DSPR(RsBlasUplo Uplo,double alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Ap)949*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DSPR(RsBlasUplo Uplo, double alpha, const sp<Allocation>& X,
950*e1eccf28SAndroid Build Coastguard Worker                                int incX, const sp<Allocation>& Ap) {
951*e1eccf28SAndroid Build Coastguard Worker     int N = validateSPR(mRS, Element::F64(mRS), Uplo, X, incX, Ap);
952*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dspr,
953*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, 0, alpha,
954*e1eccf28SAndroid Build Coastguard Worker                                 X->getID(), Ap->getID(), 0.f, 0, incX, 0, 0, 0);
955*e1eccf28SAndroid Build Coastguard Worker }
956*e1eccf28SAndroid Build Coastguard Worker 
DSYR2(RsBlasUplo Uplo,double alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & A)957*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DSYR2(RsBlasUplo Uplo, double alpha, const sp<Allocation>& X, int incX,
958*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Y, int incY, const sp<Allocation>& A) {
959*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYR2(mRS, Element::F64(mRS), Uplo, X, incX, Y, incY, A);
960*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dsyr2,
961*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, 0, alpha,
962*e1eccf28SAndroid Build Coastguard Worker                                 X->getID(), Y->getID(), 0, A->getID(), incX, incY, 0, 0);
963*e1eccf28SAndroid Build Coastguard Worker }
964*e1eccf28SAndroid Build Coastguard Worker 
DSPR2(RsBlasUplo Uplo,double alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & Ap)965*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DSPR2(RsBlasUplo Uplo, double alpha, const sp<Allocation>& X, int incX,
966*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Y, int incY, const sp<Allocation>& Ap) {
967*e1eccf28SAndroid Build Coastguard Worker     int N = validateSPR2(mRS, Element::F64(mRS), Uplo, X, incX, Y, incY, Ap);
968*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dspr2,
969*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, 0, Uplo, 0, 0, N, 0, alpha,
970*e1eccf28SAndroid Build Coastguard Worker                                 X->getID(), Y->getID(), 0, Ap->getID(), incX, incY, 0, 0);
971*e1eccf28SAndroid Build Coastguard Worker }
972*e1eccf28SAndroid Build Coastguard Worker 
973*e1eccf28SAndroid Build Coastguard Worker 
974*e1eccf28SAndroid Build Coastguard Worker /**
975*e1eccf28SAndroid Build Coastguard Worker  * Level 2, C and Z only
976*e1eccf28SAndroid Build Coastguard Worker  */
977*e1eccf28SAndroid Build Coastguard Worker 
validateGERU(RS * mRS,const sp<const Element> & e,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & A)978*e1eccf28SAndroid Build Coastguard Worker static void validateGERU(RS* mRS, const sp<const Element>& e, const sp<Allocation>& X, int incX,
979*e1eccf28SAndroid Build Coastguard Worker                          const sp<Allocation>& Y, int incY, const sp<Allocation>& A) {
980*e1eccf28SAndroid Build Coastguard Worker     if (!A->getType()->getElement()->isCompatible(e) ||
981*e1eccf28SAndroid Build Coastguard Worker         !X->getType()->getElement()->isCompatible(e) ||
982*e1eccf28SAndroid Build Coastguard Worker         !Y->getType()->getElement()->isCompatible(e)) {
983*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
984*e1eccf28SAndroid Build Coastguard Worker     }
985*e1eccf28SAndroid Build Coastguard Worker     if (X->getType()->getY() > 1 || Y->getType()->getY() > 1) {
986*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "BLAS vectors must have Y dimension of 0 or 1");
987*e1eccf28SAndroid Build Coastguard Worker     }
988*e1eccf28SAndroid Build Coastguard Worker 
989*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
990*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
991*e1eccf28SAndroid Build Coastguard Worker     if (incX <= 0 || incY <= 0) {
992*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Vector increments must be greater than 0");
993*e1eccf28SAndroid Build Coastguard Worker     }
994*e1eccf28SAndroid Build Coastguard Worker     int expectedXDim = 1 + (M - 1) * incX;
995*e1eccf28SAndroid Build Coastguard Worker     if ((int)X->getType()->getX() != expectedXDim) {
996*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for GERU");
997*e1eccf28SAndroid Build Coastguard Worker     }
998*e1eccf28SAndroid Build Coastguard Worker     int expectedYDim = 1 + (N - 1) * incY;
999*e1eccf28SAndroid Build Coastguard Worker     if ((int)Y->getType()->getX() != expectedYDim) {
1000*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Incorrect vector dimensions for GERU");
1001*e1eccf28SAndroid Build Coastguard Worker     }
1002*e1eccf28SAndroid Build Coastguard Worker 
1003*e1eccf28SAndroid Build Coastguard Worker }
1004*e1eccf28SAndroid Build Coastguard Worker 
CHEMV(RsBlasUplo Uplo,Float2 alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,Float2 beta,const sp<Allocation> & Y,int incY)1005*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CHEMV(RsBlasUplo Uplo, Float2 alpha, const sp<Allocation>& A,
1006*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& X, int incX, Float2 beta, const sp<Allocation>& Y, int incY) {
1007*e1eccf28SAndroid Build Coastguard Worker     // HEMV is the same as SYR2 validation-wise
1008*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYR2(mRS, Element::F32_2(mRS), Uplo, X, incX, Y, incY, A);
1009*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_chemv,
1010*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, 0, Uplo, 0, 0, N, 0,
1011*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, A->getID(), X->getID(),
1012*e1eccf28SAndroid Build Coastguard Worker                                  beta.x, beta.y, Y->getID(), incX, incY, 0, 0);
1013*e1eccf28SAndroid Build Coastguard Worker }
1014*e1eccf28SAndroid Build Coastguard Worker 
CHBMV(RsBlasUplo Uplo,int K,Float2 alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,Float2 beta,const sp<Allocation> & Y,int incY)1015*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CHBMV(RsBlasUplo Uplo, int K, Float2 alpha, const sp<Allocation>& A,
1016*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& X, int incX, Float2 beta, const sp<Allocation>& Y, int incY) {
1017*e1eccf28SAndroid Build Coastguard Worker     // HBMV is the same as SYR2 validation-wise
1018*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYR2(mRS, Element::F32_2(mRS), Uplo, X, incX, Y, incY, A);
1019*e1eccf28SAndroid Build Coastguard Worker     if (K < 0) {
1020*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "K must be 0 or greater for HBMV");
1021*e1eccf28SAndroid Build Coastguard Worker     }
1022*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_chbmv,
1023*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, 0, Uplo, 0, 0, N, K,
1024*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, A->getID(), X->getID(),
1025*e1eccf28SAndroid Build Coastguard Worker                                  beta.x, beta.y, Y->getID(), incX, incY, 0, 0);
1026*e1eccf28SAndroid Build Coastguard Worker }
1027*e1eccf28SAndroid Build Coastguard Worker 
CHPMV(RsBlasUplo Uplo,Float2 alpha,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX,Float2 beta,const sp<Allocation> & Y,int incY)1028*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CHPMV(RsBlasUplo Uplo, Float2 alpha, const sp<Allocation>& Ap,
1029*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& X, int incX, Float2 beta, const sp<Allocation>& Y, int incY) {
1030*e1eccf28SAndroid Build Coastguard Worker     // HPMV is the same as SPR2
1031*e1eccf28SAndroid Build Coastguard Worker     int N = validateSPR2(mRS, Element::F32_2(mRS), Uplo, X, incX, Y, incY, Ap);
1032*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_chpmv,
1033*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, 0, Uplo, 0, 0, N, 0,
1034*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, Ap->getID(), X->getID(),
1035*e1eccf28SAndroid Build Coastguard Worker                                  beta.x, beta.y, Y->getID(), incX, incY, 0, 0);
1036*e1eccf28SAndroid Build Coastguard Worker }
1037*e1eccf28SAndroid Build Coastguard Worker 
CGERU(Float2 alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & A)1038*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CGERU(Float2 alpha, const sp<Allocation>& X, int incX,
1039*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Y, int incY, const sp<Allocation>& A) {
1040*e1eccf28SAndroid Build Coastguard Worker     validateGERU(mRS, Element::F32_2(mRS), X, incX, Y, incY, A);
1041*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
1042*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
1043*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_cgeru,
1044*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, 0, 0, 0, M, N, 0,
1045*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, X->getID(), Y->getID(),
1046*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, A->getID(), incX, incY, 0, 0);
1047*e1eccf28SAndroid Build Coastguard Worker }
1048*e1eccf28SAndroid Build Coastguard Worker 
CGERC(Float2 alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & A)1049*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CGERC(Float2 alpha, const sp<Allocation>& X, int incX,
1050*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Y, int incY, const sp<Allocation>& A) {
1051*e1eccf28SAndroid Build Coastguard Worker     // Same as GERU
1052*e1eccf28SAndroid Build Coastguard Worker     validateGERU(mRS, Element::F32_2(mRS), X, incX, Y, incY, A);
1053*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
1054*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
1055*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_cgerc,
1056*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, 0, 0, 0, M, N, 0,
1057*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, X->getID(), Y->getID(),
1058*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, A->getID(), incX, incY, 0, 0);
1059*e1eccf28SAndroid Build Coastguard Worker }
1060*e1eccf28SAndroid Build Coastguard Worker 
CHER(RsBlasUplo Uplo,float alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & A)1061*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CHER(RsBlasUplo Uplo, float alpha, const sp<Allocation>& X,
1062*e1eccf28SAndroid Build Coastguard Worker                                int incX, const sp<Allocation>& A) {
1063*e1eccf28SAndroid Build Coastguard Worker     // Same as SYR
1064*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYR(mRS, Element::F32_2(mRS), Uplo, X, incX, A);
1065*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_cher,
1066*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, 0, Uplo, 0, 0, N, 0,
1067*e1eccf28SAndroid Build Coastguard Worker                                  alpha, 0, X->getID(), 0,
1068*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, A->getID(), incX, 0, 0, 0);
1069*e1eccf28SAndroid Build Coastguard Worker }
1070*e1eccf28SAndroid Build Coastguard Worker 
CHPR(RsBlasUplo Uplo,float alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Ap)1071*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CHPR(RsBlasUplo Uplo, float alpha, const sp<Allocation>& X,
1072*e1eccf28SAndroid Build Coastguard Worker                                int incX, const sp<Allocation>& Ap) {
1073*e1eccf28SAndroid Build Coastguard Worker     // Equivalent to SPR for validation
1074*e1eccf28SAndroid Build Coastguard Worker     int N = validateSPR(mRS, Element::F32_2(mRS), Uplo, X, incX, Ap);
1075*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_chpr,
1076*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, 0, Uplo, 0, 0, N, 0,
1077*e1eccf28SAndroid Build Coastguard Worker                                  alpha, 0, X->getID(), 0,
1078*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, Ap->getID(), incX, 0, 0, 0);
1079*e1eccf28SAndroid Build Coastguard Worker }
1080*e1eccf28SAndroid Build Coastguard Worker 
CHER2(RsBlasUplo Uplo,Float2 alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & A)1081*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CHER2(RsBlasUplo Uplo, Float2 alpha, const sp<Allocation>& X, int incX,
1082*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Y, int incY, const sp<Allocation>& A) {
1083*e1eccf28SAndroid Build Coastguard Worker     // Same as SYR2
1084*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYR2(mRS, Element::F32_2(mRS), Uplo, X, incX, Y, incY, A);
1085*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_cher2,
1086*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, 0, Uplo, 0, 0, N, 0,
1087*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, X->getID(), Y->getID(),
1088*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, A->getID(), incX, incY, 0, 0);
1089*e1eccf28SAndroid Build Coastguard Worker }
1090*e1eccf28SAndroid Build Coastguard Worker 
CHPR2(RsBlasUplo Uplo,Float2 alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & Ap)1091*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CHPR2(RsBlasUplo Uplo, Float2 alpha, const sp<Allocation>& X, int incX,
1092*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Y, int incY, const sp<Allocation>& Ap) {
1093*e1eccf28SAndroid Build Coastguard Worker     // Same as SPR2
1094*e1eccf28SAndroid Build Coastguard Worker     int N = validateSPR2(mRS, Element::F32_2(mRS), Uplo, X, incX, Y, incY, Ap);
1095*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_chpr2,
1096*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, 0, Uplo, 0, 0, N, 0,
1097*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, X->getID(), Y->getID(),
1098*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, Ap->getID(), incX, incY, 0, 0);
1099*e1eccf28SAndroid Build Coastguard Worker }
1100*e1eccf28SAndroid Build Coastguard Worker 
ZHEMV(RsBlasUplo Uplo,Double2 alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,Double2 beta,const sp<Allocation> & Y,int incY)1101*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZHEMV(RsBlasUplo Uplo, Double2 alpha, const sp<Allocation>& A,
1102*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& X, int incX, Double2 beta, const sp<Allocation>& Y, int incY) {
1103*e1eccf28SAndroid Build Coastguard Worker     // HEMV is the same as SYR2 validation-wise
1104*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYR2(mRS, Element::F64_2(mRS), Uplo, X, incX, Y, incY, A);
1105*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zhemv,
1106*e1eccf28SAndroid Build Coastguard Worker                            0, 0, 0, Uplo, 0, 0, N, 0,
1107*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, A->getID(), X->getID(),
1108*e1eccf28SAndroid Build Coastguard Worker                            beta.x, beta.y, Y->getID(), incX, incY, 0, 0);
1109*e1eccf28SAndroid Build Coastguard Worker }
1110*e1eccf28SAndroid Build Coastguard Worker 
ZHBMV(RsBlasUplo Uplo,int K,Double2 alpha,const sp<Allocation> & A,const sp<Allocation> & X,int incX,Double2 beta,const sp<Allocation> & Y,int incY)1111*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZHBMV(RsBlasUplo Uplo, int K, Double2 alpha, const sp<Allocation>& A, const sp<Allocation>& X,
1112*e1eccf28SAndroid Build Coastguard Worker                                 int incX, Double2 beta, const sp<Allocation>& Y, int incY) {
1113*e1eccf28SAndroid Build Coastguard Worker     // HBMV is the same as SYR2 validation-wise
1114*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYR2(mRS, Element::F64_2(mRS), Uplo, X, incX, Y, incY, A);
1115*e1eccf28SAndroid Build Coastguard Worker     if (K < 0) {
1116*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "K must be 0 or greater for HBMV");
1117*e1eccf28SAndroid Build Coastguard Worker     }
1118*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zhbmv,
1119*e1eccf28SAndroid Build Coastguard Worker                            0, 0, 0, Uplo, 0, 0, N, K,
1120*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, A->getID(), X->getID(),
1121*e1eccf28SAndroid Build Coastguard Worker                            beta.x, beta.y, Y->getID(), incX, incY, 0, 0);
1122*e1eccf28SAndroid Build Coastguard Worker }
1123*e1eccf28SAndroid Build Coastguard Worker 
ZHPMV(RsBlasUplo Uplo,Double2 alpha,const sp<Allocation> & Ap,const sp<Allocation> & X,int incX,Double2 beta,const sp<Allocation> & Y,int incY)1124*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZHPMV(RsBlasUplo Uplo, Double2 alpha, const sp<Allocation>& Ap, const sp<Allocation>& X,
1125*e1eccf28SAndroid Build Coastguard Worker                                 int incX, Double2 beta, const sp<Allocation>& Y, int incY) {
1126*e1eccf28SAndroid Build Coastguard Worker     // HPMV is the same as SPR2
1127*e1eccf28SAndroid Build Coastguard Worker     int N = validateSPR2(mRS, Element::F64_2(mRS), Uplo, X, incX, Y, incY, Ap);
1128*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zhpmv,
1129*e1eccf28SAndroid Build Coastguard Worker                            0, 0, 0, Uplo, 0, 0, N, 0,
1130*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, Ap->getID(), X->getID(),
1131*e1eccf28SAndroid Build Coastguard Worker                            beta.x, beta.y, Y->getID(), incX, incY, 0, 0);
1132*e1eccf28SAndroid Build Coastguard Worker }
1133*e1eccf28SAndroid Build Coastguard Worker 
ZGERU(Double2 alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & A)1134*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZGERU(Double2 alpha, const sp<Allocation>& X, int incX,
1135*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Y, int incY, const sp<Allocation>& A) {
1136*e1eccf28SAndroid Build Coastguard Worker     validateGERU(mRS, Element::F64_2(mRS), X, incX, Y, incY, A);
1137*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
1138*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
1139*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zgeru,
1140*e1eccf28SAndroid Build Coastguard Worker                            0, 0, 0, 0, 0, M, N, 0,
1141*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, X->getID(), Y->getID(),
1142*e1eccf28SAndroid Build Coastguard Worker                            0, 0, A->getID(), incX, incY, 0, 0);
1143*e1eccf28SAndroid Build Coastguard Worker }
1144*e1eccf28SAndroid Build Coastguard Worker 
ZGERC(Double2 alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & A)1145*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZGERC(Double2 alpha, const sp<Allocation>& X, int incX,
1146*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Y, int incY, const sp<Allocation>& A) {
1147*e1eccf28SAndroid Build Coastguard Worker     // Same as GERU
1148*e1eccf28SAndroid Build Coastguard Worker     validateGERU(mRS, Element::F64_2(mRS), X, incX, Y, incY, A);
1149*e1eccf28SAndroid Build Coastguard Worker     int M = A->getType()->getY();
1150*e1eccf28SAndroid Build Coastguard Worker     int N = A->getType()->getX();
1151*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zgerc,
1152*e1eccf28SAndroid Build Coastguard Worker                            0, 0, 0, 0, 0, M, N, 0,
1153*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, X->getID(), Y->getID(),
1154*e1eccf28SAndroid Build Coastguard Worker                            0, 0, A->getID(), incX, incY, 0, 0);
1155*e1eccf28SAndroid Build Coastguard Worker }
1156*e1eccf28SAndroid Build Coastguard Worker 
ZHER(RsBlasUplo Uplo,double alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & A)1157*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZHER(RsBlasUplo Uplo, double alpha, const sp<Allocation>& X,
1158*e1eccf28SAndroid Build Coastguard Worker                                int incX, const sp<Allocation>& A) {
1159*e1eccf28SAndroid Build Coastguard Worker     // Same as SYR
1160*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYR(mRS, Element::F64_2(mRS), Uplo, X, incX, A);
1161*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zher,
1162*e1eccf28SAndroid Build Coastguard Worker                            0, 0, 0, Uplo, 0, 0, N, 0,
1163*e1eccf28SAndroid Build Coastguard Worker                            alpha, 0, X->getID(), 0,
1164*e1eccf28SAndroid Build Coastguard Worker                            0, 0, A->getID(), incX, 0, 0, 0);
1165*e1eccf28SAndroid Build Coastguard Worker }
1166*e1eccf28SAndroid Build Coastguard Worker 
ZHPR(RsBlasUplo Uplo,double alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Ap)1167*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZHPR(RsBlasUplo Uplo, double alpha, const sp<Allocation>& X,
1168*e1eccf28SAndroid Build Coastguard Worker                                int incX, const sp<Allocation>& Ap) {
1169*e1eccf28SAndroid Build Coastguard Worker     // Equivalent to SPR for validation
1170*e1eccf28SAndroid Build Coastguard Worker     int N = validateSPR(mRS, Element::F64_2(mRS), Uplo, X, incX, Ap);
1171*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zhpr,
1172*e1eccf28SAndroid Build Coastguard Worker                            0, 0, 0, Uplo, 0, 0, N, 0,
1173*e1eccf28SAndroid Build Coastguard Worker                            alpha, 0, X->getID(), 0,
1174*e1eccf28SAndroid Build Coastguard Worker                            0, 0, Ap->getID(), incX, 0, 0, 0);
1175*e1eccf28SAndroid Build Coastguard Worker }
1176*e1eccf28SAndroid Build Coastguard Worker 
ZHER2(RsBlasUplo Uplo,Double2 alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & A)1177*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZHER2(RsBlasUplo Uplo, Double2 alpha, const sp<Allocation>& X, int incX,
1178*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Y, int incY, const sp<Allocation>& A) {
1179*e1eccf28SAndroid Build Coastguard Worker     // Same as SYR2
1180*e1eccf28SAndroid Build Coastguard Worker     int N = validateSYR2(mRS, Element::F64_2(mRS), Uplo, X, incX, Y, incY, A);
1181*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zher2,
1182*e1eccf28SAndroid Build Coastguard Worker                            0, 0, 0, Uplo, 0, 0, N, 0,
1183*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, X->getID(), Y->getID(),
1184*e1eccf28SAndroid Build Coastguard Worker                            0, 0, A->getID(), incX, incY, 0, 0);
1185*e1eccf28SAndroid Build Coastguard Worker }
1186*e1eccf28SAndroid Build Coastguard Worker 
ZHPR2(RsBlasUplo Uplo,Double2 alpha,const sp<Allocation> & X,int incX,const sp<Allocation> & Y,int incY,const sp<Allocation> & Ap)1187*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZHPR2(RsBlasUplo Uplo, Double2 alpha, const sp<Allocation>& X, int incX,
1188*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& Y, int incY, const sp<Allocation>& Ap) {
1189*e1eccf28SAndroid Build Coastguard Worker     // Same as SPR2
1190*e1eccf28SAndroid Build Coastguard Worker     int N = validateSPR2(mRS, Element::F64_2(mRS), Uplo, X, incX, Y, incY, Ap);
1191*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zhpr2,
1192*e1eccf28SAndroid Build Coastguard Worker                            0, 0, 0, Uplo, 0, 0, N, 0,
1193*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, X->getID(), Y->getID(),
1194*e1eccf28SAndroid Build Coastguard Worker                            0, 0, Ap->getID(), incX, incY, 0, 0);
1195*e1eccf28SAndroid Build Coastguard Worker }
1196*e1eccf28SAndroid Build Coastguard Worker 
1197*e1eccf28SAndroid Build Coastguard Worker 
1198*e1eccf28SAndroid Build Coastguard Worker /**
1199*e1eccf28SAndroid Build Coastguard Worker  * Level 3 BLAS
1200*e1eccf28SAndroid Build Coastguard Worker  */
1201*e1eccf28SAndroid Build Coastguard Worker 
validateL3(RS * mRS,const sp<const Element> & e,int TransA,int TransB,int Side,const sp<Allocation> & A,const sp<Allocation> & B,const sp<Allocation> & C)1202*e1eccf28SAndroid Build Coastguard Worker static void validateL3(RS* mRS, const sp<const Element>& e, int TransA, int TransB, int Side,
1203*e1eccf28SAndroid Build Coastguard Worker                        const sp<Allocation>& A, const sp<Allocation>& B, const sp<Allocation>& C) {
1204*e1eccf28SAndroid Build Coastguard Worker     int aM = -1, aN = -1, bM = -1, bN = -1, cM = -1, cN = -1;
1205*e1eccf28SAndroid Build Coastguard Worker     if ((A != nullptr && !A->getType()->getElement()->isCompatible(e)) ||
1206*e1eccf28SAndroid Build Coastguard Worker         (B != nullptr && !B->getType()->getElement()->isCompatible(e)) ||
1207*e1eccf28SAndroid Build Coastguard Worker         (C != nullptr && !C->getType()->getElement()->isCompatible(e))) {
1208*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
1209*e1eccf28SAndroid Build Coastguard Worker     }
1210*e1eccf28SAndroid Build Coastguard Worker     if (C == nullptr) {
1211*e1eccf28SAndroid Build Coastguard Worker         // Since matrix C is used to store the result, it cannot be null.
1212*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Allocation C cannot be null");
1213*e1eccf28SAndroid Build Coastguard Worker     }
1214*e1eccf28SAndroid Build Coastguard Worker     cM = C->getType()->getY();
1215*e1eccf28SAndroid Build Coastguard Worker     cN = C->getType()->getX();
1216*e1eccf28SAndroid Build Coastguard Worker 
1217*e1eccf28SAndroid Build Coastguard Worker     if (Side == RsBlasRight) {
1218*e1eccf28SAndroid Build Coastguard Worker         if ((A == nullptr && B != nullptr) || (A != nullptr && B == nullptr)) {
1219*e1eccf28SAndroid Build Coastguard Worker             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Provided Matrix A without Matrix B, or vice versa");
1220*e1eccf28SAndroid Build Coastguard Worker         }
1221*e1eccf28SAndroid Build Coastguard Worker         if (B != nullptr) {
1222*e1eccf28SAndroid Build Coastguard Worker             bM = A->getType()->getY();
1223*e1eccf28SAndroid Build Coastguard Worker             bN = A->getType()->getX();
1224*e1eccf28SAndroid Build Coastguard Worker         }
1225*e1eccf28SAndroid Build Coastguard Worker         if (A != nullptr) {
1226*e1eccf28SAndroid Build Coastguard Worker             aM = B->getType()->getY();
1227*e1eccf28SAndroid Build Coastguard Worker             aN = B->getType()->getX();
1228*e1eccf28SAndroid Build Coastguard Worker         }
1229*e1eccf28SAndroid Build Coastguard Worker     } else {
1230*e1eccf28SAndroid Build Coastguard Worker         if (A != nullptr) {
1231*e1eccf28SAndroid Build Coastguard Worker             if (TransA == RsBlasTrans || TransA == RsBlasConjTrans) {
1232*e1eccf28SAndroid Build Coastguard Worker                 aN = A->getType()->getY();
1233*e1eccf28SAndroid Build Coastguard Worker                 aM = A->getType()->getX();
1234*e1eccf28SAndroid Build Coastguard Worker             } else {
1235*e1eccf28SAndroid Build Coastguard Worker                 aM = A->getType()->getY();
1236*e1eccf28SAndroid Build Coastguard Worker                 aN = A->getType()->getX();
1237*e1eccf28SAndroid Build Coastguard Worker             }
1238*e1eccf28SAndroid Build Coastguard Worker         }
1239*e1eccf28SAndroid Build Coastguard Worker         if (B != nullptr) {
1240*e1eccf28SAndroid Build Coastguard Worker             if (TransB == RsBlasTrans || TransB == RsBlasConjTrans) {
1241*e1eccf28SAndroid Build Coastguard Worker                 bN = B->getType()->getY();
1242*e1eccf28SAndroid Build Coastguard Worker                 bM = B->getType()->getX();
1243*e1eccf28SAndroid Build Coastguard Worker             } else {
1244*e1eccf28SAndroid Build Coastguard Worker                 bM = B->getType()->getY();
1245*e1eccf28SAndroid Build Coastguard Worker                 bN = B->getType()->getX();
1246*e1eccf28SAndroid Build Coastguard Worker             }
1247*e1eccf28SAndroid Build Coastguard Worker         }
1248*e1eccf28SAndroid Build Coastguard Worker     }
1249*e1eccf28SAndroid Build Coastguard Worker     if (A != nullptr && B != nullptr && C != nullptr) {
1250*e1eccf28SAndroid Build Coastguard Worker         if (aN != bM || aM != cM || bN != cN) {
1251*e1eccf28SAndroid Build Coastguard Worker             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called BLAS with invalid dimensions");
1252*e1eccf28SAndroid Build Coastguard Worker         }
1253*e1eccf28SAndroid Build Coastguard Worker     } else if (A != nullptr && C != nullptr) {
1254*e1eccf28SAndroid Build Coastguard Worker         // A and C only, for SYRK
1255*e1eccf28SAndroid Build Coastguard Worker         if (cM != cN) {
1256*e1eccf28SAndroid Build Coastguard Worker             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Matrix C is not symmetric");
1257*e1eccf28SAndroid Build Coastguard Worker         }
1258*e1eccf28SAndroid Build Coastguard Worker         if (aM != cM) {
1259*e1eccf28SAndroid Build Coastguard Worker             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called BLAS with invalid dimensions");
1260*e1eccf28SAndroid Build Coastguard Worker         }
1261*e1eccf28SAndroid Build Coastguard Worker     } else if (A != nullptr && B != nullptr) {
1262*e1eccf28SAndroid Build Coastguard Worker         // A and B only
1263*e1eccf28SAndroid Build Coastguard Worker         if (aN != bM) {
1264*e1eccf28SAndroid Build Coastguard Worker             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called BLAS with invalid dimensions");
1265*e1eccf28SAndroid Build Coastguard Worker         }
1266*e1eccf28SAndroid Build Coastguard Worker     }
1267*e1eccf28SAndroid Build Coastguard Worker 
1268*e1eccf28SAndroid Build Coastguard Worker }
1269*e1eccf28SAndroid Build Coastguard Worker 
SGEMM(RsBlasTranspose TransA,RsBlasTranspose TransB,float alpha,const sp<Allocation> & A,const sp<Allocation> & B,float beta,const sp<Allocation> & C)1270*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SGEMM(RsBlasTranspose TransA, RsBlasTranspose TransB, float alpha,
1271*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& B, float beta, const sp<Allocation>& C) {
1272*e1eccf28SAndroid Build Coastguard Worker     validateL3(mRS, Element::F32(mRS), TransA, TransB, 0, A, B, C);
1273*e1eccf28SAndroid Build Coastguard Worker 
1274*e1eccf28SAndroid Build Coastguard Worker     int M = -1, N = -1, K = -1;
1275*e1eccf28SAndroid Build Coastguard Worker     if (TransA != RsBlasNoTrans) {
1276*e1eccf28SAndroid Build Coastguard Worker         M = A->getType()->getX();
1277*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getY();
1278*e1eccf28SAndroid Build Coastguard Worker     } else {
1279*e1eccf28SAndroid Build Coastguard Worker         M = A->getType()->getY();
1280*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getX();
1281*e1eccf28SAndroid Build Coastguard Worker     }
1282*e1eccf28SAndroid Build Coastguard Worker     if (TransB != RsBlasNoTrans) {
1283*e1eccf28SAndroid Build Coastguard Worker         N = B->getType()->getY();
1284*e1eccf28SAndroid Build Coastguard Worker     } else {
1285*e1eccf28SAndroid Build Coastguard Worker         N = B->getType()->getX();
1286*e1eccf28SAndroid Build Coastguard Worker     }
1287*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_sgemm,
1288*e1eccf28SAndroid Build Coastguard Worker                                 TransA, TransB, 0, 0, 0, M, N, K,
1289*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), B->getID(),
1290*e1eccf28SAndroid Build Coastguard Worker                                 beta, C->getID(), 0, 0, 0, 0);
1291*e1eccf28SAndroid Build Coastguard Worker }
1292*e1eccf28SAndroid Build Coastguard Worker 
DGEMM(RsBlasTranspose TransA,RsBlasTranspose TransB,double alpha,const sp<Allocation> & A,const sp<Allocation> & B,double beta,const sp<Allocation> & C)1293*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DGEMM(RsBlasTranspose TransA, RsBlasTranspose TransB, double alpha,
1294*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& B, double beta, const sp<Allocation>& C) {
1295*e1eccf28SAndroid Build Coastguard Worker     validateL3(mRS, Element::F64(mRS), TransA, TransB, 0, A, B, C);
1296*e1eccf28SAndroid Build Coastguard Worker     int M = -1, N = -1, K = -1;
1297*e1eccf28SAndroid Build Coastguard Worker     if (TransA != RsBlasNoTrans) {
1298*e1eccf28SAndroid Build Coastguard Worker         M = A->getType()->getX();
1299*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getY();
1300*e1eccf28SAndroid Build Coastguard Worker     } else {
1301*e1eccf28SAndroid Build Coastguard Worker         M = A->getType()->getY();
1302*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getX();
1303*e1eccf28SAndroid Build Coastguard Worker     }
1304*e1eccf28SAndroid Build Coastguard Worker     if (TransB != RsBlasNoTrans) {
1305*e1eccf28SAndroid Build Coastguard Worker         N = B->getType()->getY();
1306*e1eccf28SAndroid Build Coastguard Worker     } else {
1307*e1eccf28SAndroid Build Coastguard Worker         N = B->getType()->getX();
1308*e1eccf28SAndroid Build Coastguard Worker     }
1309*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dgemm,
1310*e1eccf28SAndroid Build Coastguard Worker                                 TransA, TransB, 0, 0, 0, M, N, K,
1311*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), B->getID(),
1312*e1eccf28SAndroid Build Coastguard Worker                                 beta, C->getID(), 0, 0, 0, 0);
1313*e1eccf28SAndroid Build Coastguard Worker }
1314*e1eccf28SAndroid Build Coastguard Worker 
CGEMM(RsBlasTranspose TransA,RsBlasTranspose TransB,Float2 alpha,const sp<Allocation> & A,const sp<Allocation> & B,Float2 beta,const sp<Allocation> & C)1315*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CGEMM(RsBlasTranspose TransA, RsBlasTranspose TransB, Float2 alpha,
1316*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& B, Float2 beta, const sp<Allocation>& C) {
1317*e1eccf28SAndroid Build Coastguard Worker     validateL3(mRS, Element::F32_2(mRS), TransA, TransB, 0, A, B, C);
1318*e1eccf28SAndroid Build Coastguard Worker     int M = -1, N = -1, K = -1;
1319*e1eccf28SAndroid Build Coastguard Worker     if (TransA != RsBlasNoTrans) {
1320*e1eccf28SAndroid Build Coastguard Worker         M = A->getType()->getX();
1321*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getY();
1322*e1eccf28SAndroid Build Coastguard Worker     } else {
1323*e1eccf28SAndroid Build Coastguard Worker         M = A->getType()->getY();
1324*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getX();
1325*e1eccf28SAndroid Build Coastguard Worker     }
1326*e1eccf28SAndroid Build Coastguard Worker     if (TransB != RsBlasNoTrans) {
1327*e1eccf28SAndroid Build Coastguard Worker         N = B->getType()->getY();
1328*e1eccf28SAndroid Build Coastguard Worker     } else {
1329*e1eccf28SAndroid Build Coastguard Worker         N = B->getType()->getX();
1330*e1eccf28SAndroid Build Coastguard Worker     }
1331*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_cgemm,
1332*e1eccf28SAndroid Build Coastguard Worker                                  TransA, TransB, 0, 0, 0, M, N, K,
1333*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, A->getID(), B->getID(),
1334*e1eccf28SAndroid Build Coastguard Worker                                  beta.x, beta.y, C->getID(), 0, 0, 0, 0);
1335*e1eccf28SAndroid Build Coastguard Worker }
1336*e1eccf28SAndroid Build Coastguard Worker 
ZGEMM(RsBlasTranspose TransA,RsBlasTranspose TransB,Double2 alpha,const sp<Allocation> & A,const sp<Allocation> & B,Double2 beta,const sp<Allocation> & C)1337*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZGEMM(RsBlasTranspose TransA, RsBlasTranspose TransB, Double2 alpha,
1338*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& B, Double2 beta, const sp<Allocation>& C) {
1339*e1eccf28SAndroid Build Coastguard Worker     validateL3(mRS, Element::F64_2(mRS), TransA, TransB, 0, A, B, C);
1340*e1eccf28SAndroid Build Coastguard Worker     int M = -1, N = -1, K = -1;
1341*e1eccf28SAndroid Build Coastguard Worker     if (TransA != RsBlasNoTrans) {
1342*e1eccf28SAndroid Build Coastguard Worker         M = A->getType()->getX();
1343*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getY();
1344*e1eccf28SAndroid Build Coastguard Worker     } else {
1345*e1eccf28SAndroid Build Coastguard Worker         M = A->getType()->getY();
1346*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getX();
1347*e1eccf28SAndroid Build Coastguard Worker     }
1348*e1eccf28SAndroid Build Coastguard Worker     if (TransB != RsBlasNoTrans) {
1349*e1eccf28SAndroid Build Coastguard Worker         N = B->getType()->getY();
1350*e1eccf28SAndroid Build Coastguard Worker     } else {
1351*e1eccf28SAndroid Build Coastguard Worker         N = B->getType()->getX();
1352*e1eccf28SAndroid Build Coastguard Worker     }
1353*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zgemm,
1354*e1eccf28SAndroid Build Coastguard Worker                            TransA, TransB, 0, 0, 0, M, N, K,
1355*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, A->getID(), B->getID(),
1356*e1eccf28SAndroid Build Coastguard Worker                            beta.x, beta.y, C->getID(), 0, 0, 0, 0);
1357*e1eccf28SAndroid Build Coastguard Worker }
1358*e1eccf28SAndroid Build Coastguard Worker 
SSYMM(RsBlasSide Side,RsBlasUplo Uplo,float alpha,const sp<Allocation> & A,const sp<Allocation> & B,float beta,const sp<Allocation> & C)1359*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SSYMM(RsBlasSide Side, RsBlasUplo Uplo, float alpha,
1360*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& B, float beta, const sp<Allocation>& C) {
1361*e1eccf28SAndroid Build Coastguard Worker     //For SYMM, Matrix A should be symmetric
1362*e1eccf28SAndroid Build Coastguard Worker     if (A->getType()->getX() != A->getType()->getY()) {
1363*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Matrix A is not symmetric");
1364*e1eccf28SAndroid Build Coastguard Worker     }
1365*e1eccf28SAndroid Build Coastguard Worker     validateL3(mRS, Element::F32(mRS), 0, 0, Side, A, B, C);
1366*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_ssymm,
1367*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, Side, Uplo, 0, C->getType()->getY(), C->getType()->getX(), 0,
1368*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), B->getID(),
1369*e1eccf28SAndroid Build Coastguard Worker                                 beta, C->getID(), 0, 0, 0, 0);
1370*e1eccf28SAndroid Build Coastguard Worker }
1371*e1eccf28SAndroid Build Coastguard Worker 
DSYMM(RsBlasSide Side,RsBlasUplo Uplo,double alpha,const sp<Allocation> & A,const sp<Allocation> & B,double beta,const sp<Allocation> & C)1372*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DSYMM(RsBlasSide Side, RsBlasUplo Uplo, double alpha,
1373*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& B, double beta, const sp<Allocation>& C) {
1374*e1eccf28SAndroid Build Coastguard Worker     if (A->getType()->getX() != A->getType()->getY()) {
1375*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Matrix A is not symmetric");
1376*e1eccf28SAndroid Build Coastguard Worker     }
1377*e1eccf28SAndroid Build Coastguard Worker     validateL3(mRS, Element::F64(mRS), 0, 0, Side, A, B, C);
1378*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dsymm,
1379*e1eccf28SAndroid Build Coastguard Worker                                 0, 0, Side, Uplo, 0, C->getType()->getY(), C->getType()->getX(), 0,
1380*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), B->getID(),
1381*e1eccf28SAndroid Build Coastguard Worker                                 beta, C->getID(), 0, 0, 0, 0);
1382*e1eccf28SAndroid Build Coastguard Worker }
1383*e1eccf28SAndroid Build Coastguard Worker 
CSYMM(RsBlasSide Side,RsBlasUplo Uplo,Float2 alpha,const sp<Allocation> & A,const sp<Allocation> & B,Float2 beta,const sp<Allocation> & C)1384*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CSYMM(RsBlasSide Side, RsBlasUplo Uplo, Float2 alpha,
1385*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& B, Float2 beta, const sp<Allocation>& C) {
1386*e1eccf28SAndroid Build Coastguard Worker     if (A->getType()->getX() != A->getType()->getY()) {
1387*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Matrix A is not symmetric");
1388*e1eccf28SAndroid Build Coastguard Worker     }
1389*e1eccf28SAndroid Build Coastguard Worker     validateL3(mRS, Element::F32_2(mRS), 0, 0, Side, A, B, C);
1390*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_csymm,
1391*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, Side, Uplo, 0, C->getType()->getY(), C->getType()->getX(), 0,
1392*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, A->getID(), B->getID(),
1393*e1eccf28SAndroid Build Coastguard Worker                                  beta.x, beta.y, C->getID(), 0, 0, 0, 0);
1394*e1eccf28SAndroid Build Coastguard Worker }
1395*e1eccf28SAndroid Build Coastguard Worker 
ZSYMM(RsBlasSide Side,RsBlasUplo Uplo,Double2 alpha,const sp<Allocation> & A,const sp<Allocation> & B,Double2 beta,const sp<Allocation> & C)1396*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZSYMM(RsBlasSide Side, RsBlasUplo Uplo, Double2 alpha,
1397*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& B, Double2 beta, const sp<Allocation>& C) {
1398*e1eccf28SAndroid Build Coastguard Worker     if (A->getType()->getX() != A->getType()->getY()) {
1399*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Matrix A is not symmetric");
1400*e1eccf28SAndroid Build Coastguard Worker     }
1401*e1eccf28SAndroid Build Coastguard Worker     validateL3(mRS, Element::F64_2(mRS), 0, 0, Side, A, B, C);
1402*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zsymm,
1403*e1eccf28SAndroid Build Coastguard Worker                            0, 0, Side, Uplo, 0, C->getType()->getY(), C->getType()->getX(), 0,
1404*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, A->getID(), B->getID(),
1405*e1eccf28SAndroid Build Coastguard Worker                            beta.x, beta.y, C->getID(), 0, 0, 0, 0);
1406*e1eccf28SAndroid Build Coastguard Worker }
1407*e1eccf28SAndroid Build Coastguard Worker 
SSYRK(RsBlasUplo Uplo,RsBlasTranspose Trans,float alpha,const sp<Allocation> & A,float beta,const sp<Allocation> & C)1408*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SSYRK(RsBlasUplo Uplo, RsBlasTranspose Trans, float alpha,
1409*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, float beta, const sp<Allocation>& C) {
1410*e1eccf28SAndroid Build Coastguard Worker     validateL3(mRS, Element::F32(mRS), Trans, 0, 0, A, nullptr, C);
1411*e1eccf28SAndroid Build Coastguard Worker     int K = -1;
1412*e1eccf28SAndroid Build Coastguard Worker     if (Trans != RsBlasNoTrans) {
1413*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getY();
1414*e1eccf28SAndroid Build Coastguard Worker     } else {
1415*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getX();
1416*e1eccf28SAndroid Build Coastguard Worker     }
1417*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_ssyrk,
1418*e1eccf28SAndroid Build Coastguard Worker                                 Trans, 0, 0, Uplo, 0, 0, C->getType()->getX(), K,
1419*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), 0,
1420*e1eccf28SAndroid Build Coastguard Worker                                 beta, C->getID(), 0, 0, 0, 0);
1421*e1eccf28SAndroid Build Coastguard Worker }
1422*e1eccf28SAndroid Build Coastguard Worker 
DSYRK(RsBlasUplo Uplo,RsBlasTranspose Trans,double alpha,const sp<Allocation> & A,double beta,const sp<Allocation> & C)1423*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DSYRK(RsBlasUplo Uplo, RsBlasTranspose Trans, double alpha,
1424*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, double beta, const sp<Allocation>& C) {
1425*e1eccf28SAndroid Build Coastguard Worker     validateL3(mRS, Element::F64(mRS), Trans, 0, 0, A, nullptr, C);
1426*e1eccf28SAndroid Build Coastguard Worker     int K = -1;
1427*e1eccf28SAndroid Build Coastguard Worker     if (Trans != RsBlasNoTrans) {
1428*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getY();
1429*e1eccf28SAndroid Build Coastguard Worker     } else {
1430*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getX();
1431*e1eccf28SAndroid Build Coastguard Worker     }
1432*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dsyrk,
1433*e1eccf28SAndroid Build Coastguard Worker                                 Trans, 0, 0, Uplo, 0, 0, C->getType()->getX(), K,
1434*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), 0,
1435*e1eccf28SAndroid Build Coastguard Worker                                 beta, C->getID(), 0, 0, 0, 0);
1436*e1eccf28SAndroid Build Coastguard Worker }
1437*e1eccf28SAndroid Build Coastguard Worker 
CSYRK(RsBlasUplo Uplo,RsBlasTranspose Trans,Float2 alpha,const sp<Allocation> & A,Float2 beta,const sp<Allocation> & C)1438*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CSYRK(RsBlasUplo Uplo, RsBlasTranspose Trans, Float2 alpha,
1439*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, Float2 beta, const sp<Allocation>& C) {
1440*e1eccf28SAndroid Build Coastguard Worker     validateL3(mRS, Element::F32_2(mRS), Trans, 0, 0, A, nullptr, C);
1441*e1eccf28SAndroid Build Coastguard Worker     int K = -1;
1442*e1eccf28SAndroid Build Coastguard Worker     if (Trans != RsBlasNoTrans) {
1443*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getY();
1444*e1eccf28SAndroid Build Coastguard Worker     } else {
1445*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getX();
1446*e1eccf28SAndroid Build Coastguard Worker     }
1447*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_csyrk,
1448*e1eccf28SAndroid Build Coastguard Worker                                  Trans, 0, 0, Uplo, 0, 0, C->getType()->getX(), K,
1449*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, A->getID(), 0,
1450*e1eccf28SAndroid Build Coastguard Worker                                  beta.x, beta.y, C->getID(), 0, 0, 0, 0);
1451*e1eccf28SAndroid Build Coastguard Worker }
1452*e1eccf28SAndroid Build Coastguard Worker 
ZSYRK(RsBlasUplo Uplo,RsBlasTranspose Trans,Double2 alpha,const sp<Allocation> & A,Double2 beta,const sp<Allocation> & C)1453*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZSYRK(RsBlasUplo Uplo, RsBlasTranspose Trans, Double2 alpha,
1454*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, Double2 beta, const sp<Allocation>& C) {
1455*e1eccf28SAndroid Build Coastguard Worker     validateL3(mRS, Element::F64_2(mRS), Trans, 0, 0, A, nullptr, C);
1456*e1eccf28SAndroid Build Coastguard Worker     int K = -1;
1457*e1eccf28SAndroid Build Coastguard Worker     if (Trans != RsBlasNoTrans) {
1458*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getY();
1459*e1eccf28SAndroid Build Coastguard Worker     } else {
1460*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getX();
1461*e1eccf28SAndroid Build Coastguard Worker     }
1462*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zsyrk,
1463*e1eccf28SAndroid Build Coastguard Worker                            Trans, 0, 0, Uplo, 0, 0, C->getType()->getX(), K,
1464*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, A->getID(), 0,
1465*e1eccf28SAndroid Build Coastguard Worker                            beta.x, beta.y, C->getID(), 0, 0, 0, 0);
1466*e1eccf28SAndroid Build Coastguard Worker }
1467*e1eccf28SAndroid Build Coastguard Worker 
validateSYR2K(RS * mRS,const sp<const Element> & e,RsBlasTranspose Trans,const sp<Allocation> & A,const sp<Allocation> & B,const sp<Allocation> & C)1468*e1eccf28SAndroid Build Coastguard Worker static void validateSYR2K(RS* mRS, const sp<const Element>& e, RsBlasTranspose Trans,
1469*e1eccf28SAndroid Build Coastguard Worker                           const sp<Allocation>& A, const sp<Allocation>& B, const sp<Allocation>& C) {
1470*e1eccf28SAndroid Build Coastguard Worker     if (!A->getType()->getElement()->isCompatible(e) ||
1471*e1eccf28SAndroid Build Coastguard Worker         !B->getType()->getElement()->isCompatible(e) ||
1472*e1eccf28SAndroid Build Coastguard Worker         !C->getType()->getElement()->isCompatible(e)) {
1473*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
1474*e1eccf28SAndroid Build Coastguard Worker     }
1475*e1eccf28SAndroid Build Coastguard Worker     int Cdim = -1;
1476*e1eccf28SAndroid Build Coastguard Worker     // A is n x k if no transpose, k x n if transpose
1477*e1eccf28SAndroid Build Coastguard Worker     // C is n x n
1478*e1eccf28SAndroid Build Coastguard Worker     if (Trans == RsBlasTrans) {
1479*e1eccf28SAndroid Build Coastguard Worker         // check columns versus C
1480*e1eccf28SAndroid Build Coastguard Worker         Cdim = A->getType()->getX();
1481*e1eccf28SAndroid Build Coastguard Worker     } else {
1482*e1eccf28SAndroid Build Coastguard Worker         // check rows versus C
1483*e1eccf28SAndroid Build Coastguard Worker         Cdim = A->getType()->getY();
1484*e1eccf28SAndroid Build Coastguard Worker     }
1485*e1eccf28SAndroid Build Coastguard Worker     if ((int)C->getType()->getX() != Cdim || (int)C->getType()->getY() != Cdim) {
1486*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid symmetric matrix in SYR2K");
1487*e1eccf28SAndroid Build Coastguard Worker     }
1488*e1eccf28SAndroid Build Coastguard Worker     // A dims == B dims
1489*e1eccf28SAndroid Build Coastguard Worker     if (A->getType()->getX() != B->getType()->getX() || A->getType()->getY() != B->getType()->getY()) {
1490*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid A and B in SYR2K");
1491*e1eccf28SAndroid Build Coastguard Worker     }
1492*e1eccf28SAndroid Build Coastguard Worker }
1493*e1eccf28SAndroid Build Coastguard Worker 
SSYR2K(RsBlasUplo Uplo,RsBlasTranspose Trans,float alpha,const sp<Allocation> & A,const sp<Allocation> & B,float beta,const sp<Allocation> & C)1494*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::SSYR2K(RsBlasUplo Uplo, RsBlasTranspose Trans, float alpha,
1495*e1eccf28SAndroid Build Coastguard Worker                                  const sp<Allocation>& A, const sp<Allocation>& B, float beta, const sp<Allocation>& C) {
1496*e1eccf28SAndroid Build Coastguard Worker     validateSYR2K(mRS, Element::F32(mRS), Trans, A, B, C);
1497*e1eccf28SAndroid Build Coastguard Worker     int K = -1;
1498*e1eccf28SAndroid Build Coastguard Worker     if (Trans != RsBlasNoTrans) {
1499*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getY();
1500*e1eccf28SAndroid Build Coastguard Worker     } else {
1501*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getX();
1502*e1eccf28SAndroid Build Coastguard Worker     }
1503*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_ssyr2k,
1504*e1eccf28SAndroid Build Coastguard Worker                                 Trans, 0, 0, Uplo, 0, 0, C->getType()->getX(), K,
1505*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), B->getID(),
1506*e1eccf28SAndroid Build Coastguard Worker                                 beta, C->getID(), 0, 0, 0, 0);
1507*e1eccf28SAndroid Build Coastguard Worker }
1508*e1eccf28SAndroid Build Coastguard Worker 
DSYR2K(RsBlasUplo Uplo,RsBlasTranspose Trans,double alpha,const sp<Allocation> & A,const sp<Allocation> & B,double beta,const sp<Allocation> & C)1509*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DSYR2K(RsBlasUplo Uplo, RsBlasTranspose Trans, double alpha,
1510*e1eccf28SAndroid Build Coastguard Worker                                  const sp<Allocation>& A, const sp<Allocation>& B, double beta, const sp<Allocation>& C) {
1511*e1eccf28SAndroid Build Coastguard Worker     validateSYR2K(mRS, Element::F64(mRS), Trans, A, B, C);
1512*e1eccf28SAndroid Build Coastguard Worker     int K = -1;
1513*e1eccf28SAndroid Build Coastguard Worker     if (Trans != RsBlasNoTrans) {
1514*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getY();
1515*e1eccf28SAndroid Build Coastguard Worker     } else {
1516*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getX();
1517*e1eccf28SAndroid Build Coastguard Worker     }
1518*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dsyr2k,
1519*e1eccf28SAndroid Build Coastguard Worker                                 Trans, 0, 0, Uplo, 0, 0, C->getType()->getX(), K,
1520*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), B->getID(),
1521*e1eccf28SAndroid Build Coastguard Worker                                 beta, C->getID(), 0, 0, 0, 0);
1522*e1eccf28SAndroid Build Coastguard Worker }
1523*e1eccf28SAndroid Build Coastguard Worker 
CSYR2K(RsBlasUplo Uplo,RsBlasTranspose Trans,Float2 alpha,const sp<Allocation> & A,const sp<Allocation> & B,Float2 beta,const sp<Allocation> & C)1524*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CSYR2K(RsBlasUplo Uplo, RsBlasTranspose Trans, Float2 alpha,
1525*e1eccf28SAndroid Build Coastguard Worker                                  const sp<Allocation>& A, const sp<Allocation>& B, Float2 beta, const sp<Allocation>& C) {
1526*e1eccf28SAndroid Build Coastguard Worker     validateSYR2K(mRS, Element::F32_2(mRS), Trans, A, B, C);
1527*e1eccf28SAndroid Build Coastguard Worker     int K = -1;
1528*e1eccf28SAndroid Build Coastguard Worker     if (Trans != RsBlasNoTrans) {
1529*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getY();
1530*e1eccf28SAndroid Build Coastguard Worker     } else {
1531*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getX();
1532*e1eccf28SAndroid Build Coastguard Worker     }
1533*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_csyr2k,
1534*e1eccf28SAndroid Build Coastguard Worker                                  Trans, 0, 0, Uplo, 0, 0, C->getType()->getX(), K,
1535*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, A->getID(), B->getID(),
1536*e1eccf28SAndroid Build Coastguard Worker                                  beta.x, beta.y, C->getID(), 0, 0, 0, 0);
1537*e1eccf28SAndroid Build Coastguard Worker }
1538*e1eccf28SAndroid Build Coastguard Worker 
ZSYR2K(RsBlasUplo Uplo,RsBlasTranspose Trans,Double2 alpha,const sp<Allocation> & A,const sp<Allocation> & B,Double2 beta,const sp<Allocation> & C)1539*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZSYR2K(RsBlasUplo Uplo, RsBlasTranspose Trans, Double2 alpha,
1540*e1eccf28SAndroid Build Coastguard Worker                                  const sp<Allocation>& A, const sp<Allocation>& B, Double2 beta, const sp<Allocation>& C) {
1541*e1eccf28SAndroid Build Coastguard Worker     validateSYR2K(mRS, Element::F64_2(mRS), Trans, A, B, C);
1542*e1eccf28SAndroid Build Coastguard Worker     int K = -1;
1543*e1eccf28SAndroid Build Coastguard Worker     if (Trans != RsBlasNoTrans) {
1544*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getY();
1545*e1eccf28SAndroid Build Coastguard Worker     } else {
1546*e1eccf28SAndroid Build Coastguard Worker         K = A->getType()->getX();
1547*e1eccf28SAndroid Build Coastguard Worker     }
1548*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zsyr2k,
1549*e1eccf28SAndroid Build Coastguard Worker                            Trans, 0, 0, Uplo, 0, 0, C->getType()->getX(), K,
1550*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, A->getID(), B->getID(),
1551*e1eccf28SAndroid Build Coastguard Worker                            beta.x, beta.y, C->getID(), 0, 0, 0, 0);
1552*e1eccf28SAndroid Build Coastguard Worker }
1553*e1eccf28SAndroid Build Coastguard Worker 
validateTRMM(RS * mRS,const sp<const Element> & e,RsBlasSide Side,RsBlasTranspose TransA,const sp<Allocation> & A,const sp<Allocation> & B)1554*e1eccf28SAndroid Build Coastguard Worker static void validateTRMM(RS* mRS, const sp<const Element>& e, RsBlasSide Side, RsBlasTranspose TransA,
1555*e1eccf28SAndroid Build Coastguard Worker                          const sp<Allocation>& A, const sp<Allocation>& B) {
1556*e1eccf28SAndroid Build Coastguard Worker     int aM = -1, aN = -1, bM = -1, bN = -1;
1557*e1eccf28SAndroid Build Coastguard Worker     if (!A->getType()->getElement()->isCompatible(e) ||
1558*e1eccf28SAndroid Build Coastguard Worker         !B->getType()->getElement()->isCompatible(e)) {
1559*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
1560*e1eccf28SAndroid Build Coastguard Worker     }
1561*e1eccf28SAndroid Build Coastguard Worker 
1562*e1eccf28SAndroid Build Coastguard Worker     aM = A->getType()->getY();
1563*e1eccf28SAndroid Build Coastguard Worker     aN = A->getType()->getX();
1564*e1eccf28SAndroid Build Coastguard Worker     if (aM != aN) {
1565*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called TRMM with a non-symmetric matrix A");
1566*e1eccf28SAndroid Build Coastguard Worker     }
1567*e1eccf28SAndroid Build Coastguard Worker 
1568*e1eccf28SAndroid Build Coastguard Worker     bM = B->getType()->getY();
1569*e1eccf28SAndroid Build Coastguard Worker     bN = B->getType()->getX();
1570*e1eccf28SAndroid Build Coastguard Worker     if (Side == RsBlasLeft) {
1571*e1eccf28SAndroid Build Coastguard Worker         if (aN != bM) {
1572*e1eccf28SAndroid Build Coastguard Worker             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called TRMM with invalid matrices");
1573*e1eccf28SAndroid Build Coastguard Worker         }
1574*e1eccf28SAndroid Build Coastguard Worker     } else {
1575*e1eccf28SAndroid Build Coastguard Worker         if (bN != aM) {
1576*e1eccf28SAndroid Build Coastguard Worker             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called TRMM with invalid matrices");
1577*e1eccf28SAndroid Build Coastguard Worker         }
1578*e1eccf28SAndroid Build Coastguard Worker     }
1579*e1eccf28SAndroid Build Coastguard Worker }
1580*e1eccf28SAndroid Build Coastguard Worker 
STRMM(RsBlasSide Side,RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,float alpha,const sp<Allocation> & A,const sp<Allocation> & B)1581*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::STRMM(RsBlasSide Side, RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
1582*e1eccf28SAndroid Build Coastguard Worker                                 float alpha, const sp<Allocation>& A, const sp<Allocation>& B) {
1583*e1eccf28SAndroid Build Coastguard Worker     validateTRMM(mRS, Element::F32(mRS), Side, TransA, A, B);
1584*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_strmm,
1585*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, Side, Uplo, Diag,\
1586*e1eccf28SAndroid Build Coastguard Worker                                 B->getType()->getY(), B->getType()->getX(), 0,
1587*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), B->getID(), 0.f, 0, 0, 0, 0, 0);
1588*e1eccf28SAndroid Build Coastguard Worker }
1589*e1eccf28SAndroid Build Coastguard Worker 
DTRMM(RsBlasSide Side,RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,double alpha,const sp<Allocation> & A,const sp<Allocation> & B)1590*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DTRMM(RsBlasSide Side, RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
1591*e1eccf28SAndroid Build Coastguard Worker                                 double alpha, const sp<Allocation>& A, const sp<Allocation>& B) {
1592*e1eccf28SAndroid Build Coastguard Worker     validateTRMM(mRS, Element::F64(mRS), Side, TransA, A, B);
1593*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dtrmm,
1594*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, Side, Uplo, Diag,
1595*e1eccf28SAndroid Build Coastguard Worker                                 B->getType()->getY(), B->getType()->getX(), 0,
1596*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), B->getID(), 0, 0, 0, 0, 0, 0);
1597*e1eccf28SAndroid Build Coastguard Worker }
1598*e1eccf28SAndroid Build Coastguard Worker 
CTRMM(RsBlasSide Side,RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,Float2 alpha,const sp<Allocation> & A,const sp<Allocation> & B)1599*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CTRMM(RsBlasSide Side, RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
1600*e1eccf28SAndroid Build Coastguard Worker                                 Float2 alpha, const sp<Allocation>& A, const sp<Allocation>& B) {
1601*e1eccf28SAndroid Build Coastguard Worker     validateTRMM(mRS, Element::F32_2(mRS), Side, TransA, A, B);
1602*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_ctrmm,
1603*e1eccf28SAndroid Build Coastguard Worker                                  TransA, 0, Side, Uplo, Diag,
1604*e1eccf28SAndroid Build Coastguard Worker                                  B->getType()->getY(), B->getType()->getX(), 0,
1605*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, A->getID(), B->getID(), 0, 0, 0, 0, 0, 0, 0);
1606*e1eccf28SAndroid Build Coastguard Worker }
1607*e1eccf28SAndroid Build Coastguard Worker 
ZTRMM(RsBlasSide Side,RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,Double2 alpha,const sp<Allocation> & A,const sp<Allocation> & B)1608*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZTRMM(RsBlasSide Side, RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
1609*e1eccf28SAndroid Build Coastguard Worker                                 Double2 alpha, const sp<Allocation>& A, const sp<Allocation>& B) {
1610*e1eccf28SAndroid Build Coastguard Worker     validateTRMM(mRS, Element::F64_2(mRS), Side, TransA, A, B);
1611*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_ztrmm,
1612*e1eccf28SAndroid Build Coastguard Worker                            TransA, 0, Side, Uplo, Diag,
1613*e1eccf28SAndroid Build Coastguard Worker                            B->getType()->getY(), B->getType()->getX(), 0,
1614*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, A->getID(), B->getID(), 0, 0, 0, 0, 0, 0, 0);
1615*e1eccf28SAndroid Build Coastguard Worker }
1616*e1eccf28SAndroid Build Coastguard Worker 
validateTRSM(RS * mRS,const sp<const Element> & e,RsBlasSide Side,RsBlasTranspose TransA,const sp<Allocation> & A,const sp<Allocation> & B)1617*e1eccf28SAndroid Build Coastguard Worker static void validateTRSM(RS* mRS, const sp<const Element>& e, RsBlasSide Side, RsBlasTranspose TransA,
1618*e1eccf28SAndroid Build Coastguard Worker                          const sp<Allocation>& A, const sp<Allocation>& B) {
1619*e1eccf28SAndroid Build Coastguard Worker     int adim = -1, bM = -1, bN = -1;
1620*e1eccf28SAndroid Build Coastguard Worker     if (!A->getType()->getElement()->isCompatible(e) ||
1621*e1eccf28SAndroid Build Coastguard Worker         !B->getType()->getElement()->isCompatible(e)) {
1622*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
1623*e1eccf28SAndroid Build Coastguard Worker     }
1624*e1eccf28SAndroid Build Coastguard Worker     adim = A->getType()->getX();
1625*e1eccf28SAndroid Build Coastguard Worker     if (adim != (int)A->getType()->getY()) {
1626*e1eccf28SAndroid Build Coastguard Worker         // This may be unnecessary, the restriction could potentially be relaxed.
1627*e1eccf28SAndroid Build Coastguard Worker         // Allocation A needs to contain at least that symmetric matrix but could theoretically
1628*e1eccf28SAndroid Build Coastguard Worker         // be larger for now we assume adapters are sufficient, will reevaluate in the future.
1629*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called TRSM with a non-symmetric matrix A");
1630*e1eccf28SAndroid Build Coastguard Worker     }
1631*e1eccf28SAndroid Build Coastguard Worker     bM = B->getType()->getY();
1632*e1eccf28SAndroid Build Coastguard Worker     bN = B->getType()->getX();
1633*e1eccf28SAndroid Build Coastguard Worker     if (Side == RsBlasLeft) {
1634*e1eccf28SAndroid Build Coastguard Worker         // A is M*M
1635*e1eccf28SAndroid Build Coastguard Worker         if (adim != bM) {
1636*e1eccf28SAndroid Build Coastguard Worker             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called TRSM with invalid matrix dimensions");
1637*e1eccf28SAndroid Build Coastguard Worker         }
1638*e1eccf28SAndroid Build Coastguard Worker     } else {
1639*e1eccf28SAndroid Build Coastguard Worker         // A is N*N
1640*e1eccf28SAndroid Build Coastguard Worker         if (adim != bN) {
1641*e1eccf28SAndroid Build Coastguard Worker             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called TRSM with invalid matrix dimensions");
1642*e1eccf28SAndroid Build Coastguard Worker         }
1643*e1eccf28SAndroid Build Coastguard Worker     }
1644*e1eccf28SAndroid Build Coastguard Worker }
1645*e1eccf28SAndroid Build Coastguard Worker 
STRSM(RsBlasSide Side,RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,float alpha,const sp<Allocation> & A,const sp<Allocation> & B)1646*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::STRSM(RsBlasSide Side, RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
1647*e1eccf28SAndroid Build Coastguard Worker                                 float alpha, const sp<Allocation>& A, const sp<Allocation>& B) {
1648*e1eccf28SAndroid Build Coastguard Worker     validateTRSM(mRS, Element::F32(mRS), Side, TransA, A, B);
1649*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Single(mRS, mRS->getContext(), getID(), RsBlas_strsm,
1650*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, Side, Uplo, Diag,
1651*e1eccf28SAndroid Build Coastguard Worker                                 B->getType()->getY(), B->getType()->getX(), 0,
1652*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), B->getID(), 0, 0, 0, 0, 0, 0);
1653*e1eccf28SAndroid Build Coastguard Worker }
1654*e1eccf28SAndroid Build Coastguard Worker 
DTRSM(RsBlasSide Side,RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,double alpha,const sp<Allocation> & A,const sp<Allocation> & B)1655*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::DTRSM(RsBlasSide Side, RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
1656*e1eccf28SAndroid Build Coastguard Worker                                 double alpha, const sp<Allocation>& A, const sp<Allocation>& B) {
1657*e1eccf28SAndroid Build Coastguard Worker     validateTRSM(mRS, Element::F64(mRS), Side, TransA, A, B);
1658*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Double(mRS, mRS->getContext(), getID(), RsBlas_dtrsm,
1659*e1eccf28SAndroid Build Coastguard Worker                                 TransA, 0, Side, Uplo, Diag,
1660*e1eccf28SAndroid Build Coastguard Worker                                 B->getType()->getY(), B->getType()->getX(), 0,
1661*e1eccf28SAndroid Build Coastguard Worker                                 alpha, A->getID(), B->getID(), 0, 0, 0, 0, 0, 0);
1662*e1eccf28SAndroid Build Coastguard Worker }
1663*e1eccf28SAndroid Build Coastguard Worker 
CTRSM(RsBlasSide Side,RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,Float2 alpha,const sp<Allocation> & A,const sp<Allocation> & B)1664*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CTRSM(RsBlasSide Side, RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
1665*e1eccf28SAndroid Build Coastguard Worker                                 Float2 alpha, const sp<Allocation>& A, const sp<Allocation>& B) {
1666*e1eccf28SAndroid Build Coastguard Worker     validateTRSM(mRS, Element::F32_2(mRS), Side, TransA, A, B);
1667*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_ctrsm,
1668*e1eccf28SAndroid Build Coastguard Worker                                  TransA, 0, Side, Uplo, Diag,
1669*e1eccf28SAndroid Build Coastguard Worker                                  B->getType()->getY(), B->getType()->getX(), 0,
1670*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, A->getID(), B->getID(), 0, 0, 0, 0, 0, 0, 0);
1671*e1eccf28SAndroid Build Coastguard Worker }
1672*e1eccf28SAndroid Build Coastguard Worker 
ZTRSM(RsBlasSide Side,RsBlasUplo Uplo,RsBlasTranspose TransA,RsBlasDiag Diag,Double2 alpha,const sp<Allocation> & A,const sp<Allocation> & B)1673*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZTRSM(RsBlasSide Side, RsBlasUplo Uplo, RsBlasTranspose TransA, RsBlasDiag Diag,
1674*e1eccf28SAndroid Build Coastguard Worker                                 Double2 alpha, const sp<Allocation>& A, const sp<Allocation>& B) {
1675*e1eccf28SAndroid Build Coastguard Worker     validateTRSM(mRS, Element::F64_2(mRS), Side, TransA, A, B);
1676*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_ztrsm,
1677*e1eccf28SAndroid Build Coastguard Worker                            TransA, 0, Side, Uplo, Diag,
1678*e1eccf28SAndroid Build Coastguard Worker                            B->getType()->getY(), B->getType()->getX(), 0,
1679*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, A->getID(), B->getID(), 0, 0, 0, 0, 0, 0, 0);
1680*e1eccf28SAndroid Build Coastguard Worker }
1681*e1eccf28SAndroid Build Coastguard Worker 
validateHEMM(RS * mRS,const sp<const Element> & e,RsBlasSide Side,const sp<Allocation> & A,const sp<Allocation> & B,const sp<Allocation> & C)1682*e1eccf28SAndroid Build Coastguard Worker static void validateHEMM(RS* mRS, const sp<const Element>& e, RsBlasSide Side,
1683*e1eccf28SAndroid Build Coastguard Worker                          const sp<Allocation>& A, const sp<Allocation>& B, const sp<Allocation>& C) {
1684*e1eccf28SAndroid Build Coastguard Worker     if (!A->getType()->getElement()->isCompatible(e) ||
1685*e1eccf28SAndroid Build Coastguard Worker         !B->getType()->getElement()->isCompatible(e) ||
1686*e1eccf28SAndroid Build Coastguard Worker         !C->getType()->getElement()->isCompatible(e)) {
1687*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
1688*e1eccf28SAndroid Build Coastguard Worker     }
1689*e1eccf28SAndroid Build Coastguard Worker 
1690*e1eccf28SAndroid Build Coastguard Worker     // A must be square; can potentially be relaxed similar to TRSM
1691*e1eccf28SAndroid Build Coastguard Worker     int adim = A->getType()->getX();
1692*e1eccf28SAndroid Build Coastguard Worker     if (adim != (int)A->getType()->getY()) {
1693*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called HEMM with non-square A");
1694*e1eccf28SAndroid Build Coastguard Worker     }
1695*e1eccf28SAndroid Build Coastguard Worker     if ((Side == RsBlasLeft && adim != (int)B->getType()->getY()) ||
1696*e1eccf28SAndroid Build Coastguard Worker         (Side == RsBlasRight && adim != (int)B->getType()->getX())) {
1697*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called HEMM with invalid B");
1698*e1eccf28SAndroid Build Coastguard Worker     }
1699*e1eccf28SAndroid Build Coastguard Worker     if (B->getType()->getX() != C->getType()->getX() ||
1700*e1eccf28SAndroid Build Coastguard Worker         B->getType()->getY() != C->getType()->getY()) {
1701*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called HEMM with mismatched B and C");
1702*e1eccf28SAndroid Build Coastguard Worker     }
1703*e1eccf28SAndroid Build Coastguard Worker }
1704*e1eccf28SAndroid Build Coastguard Worker 
CHEMM(RsBlasSide Side,RsBlasUplo Uplo,Float2 alpha,const sp<Allocation> & A,const sp<Allocation> & B,Float2 beta,const sp<Allocation> & C)1705*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CHEMM(RsBlasSide Side, RsBlasUplo Uplo, Float2 alpha,
1706*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& B, Float2 beta, const sp<Allocation>& C) {
1707*e1eccf28SAndroid Build Coastguard Worker     validateHEMM(mRS, Element::F32_2(mRS), Side, A, B, C);
1708*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_chemm,
1709*e1eccf28SAndroid Build Coastguard Worker                                  0, 0, Side, Uplo, 0,
1710*e1eccf28SAndroid Build Coastguard Worker                                  C->getType()->getY(), C->getType()->getX(), 0,
1711*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, A->getID(), B->getID(),
1712*e1eccf28SAndroid Build Coastguard Worker                                  beta.x, beta.y, C->getID(), 0, 0, 0, 0);
1713*e1eccf28SAndroid Build Coastguard Worker }
1714*e1eccf28SAndroid Build Coastguard Worker 
ZHEMM(RsBlasSide Side,RsBlasUplo Uplo,Double2 alpha,const sp<Allocation> & A,const sp<Allocation> & B,Double2 beta,const sp<Allocation> & C)1715*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZHEMM(RsBlasSide Side, RsBlasUplo Uplo, Double2 alpha,
1716*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, const sp<Allocation>& B, Double2 beta, const sp<Allocation>& C) {
1717*e1eccf28SAndroid Build Coastguard Worker     validateHEMM(mRS, Element::F64_2(mRS), Side, A, B, C);
1718*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zhemm,
1719*e1eccf28SAndroid Build Coastguard Worker                            0, 0, Side, Uplo, 0,
1720*e1eccf28SAndroid Build Coastguard Worker                            C->getType()->getY(), C->getType()->getX(), 0,
1721*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, A->getID(), B->getID(),
1722*e1eccf28SAndroid Build Coastguard Worker                            beta.x, beta.y, C->getID(), 0, 0, 0, 0);
1723*e1eccf28SAndroid Build Coastguard Worker }
1724*e1eccf28SAndroid Build Coastguard Worker 
validateHERK(RS * mRS,const sp<const Element> & e,RsBlasTranspose Trans,const sp<Allocation> & A,const sp<Allocation> & C)1725*e1eccf28SAndroid Build Coastguard Worker static void validateHERK(RS* mRS, const sp<const Element>& e, RsBlasTranspose Trans,
1726*e1eccf28SAndroid Build Coastguard Worker                          const sp<Allocation>& A, const sp<Allocation>& C) {
1727*e1eccf28SAndroid Build Coastguard Worker     if (!A->getType()->getElement()->isCompatible(e) ||
1728*e1eccf28SAndroid Build Coastguard Worker         !C->getType()->getElement()->isCompatible(e)) {
1729*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
1730*e1eccf28SAndroid Build Coastguard Worker     }
1731*e1eccf28SAndroid Build Coastguard Worker     if (Trans != RsBlasNoTrans && Trans != RsBlasConjTrans) {
1732*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Call HERK with invalid Transpose");
1733*e1eccf28SAndroid Build Coastguard Worker     }
1734*e1eccf28SAndroid Build Coastguard Worker     int cdim = C->getType()->getX();
1735*e1eccf28SAndroid Build Coastguard Worker     if (cdim != (int)C->getType()->getY()) {
1736*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called HERK with non-square C");
1737*e1eccf28SAndroid Build Coastguard Worker     }
1738*e1eccf28SAndroid Build Coastguard Worker     if (Trans == RsBlasNoTrans) {
1739*e1eccf28SAndroid Build Coastguard Worker         if (cdim != (int)A->getType()->getY()) {
1740*e1eccf28SAndroid Build Coastguard Worker             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called HERK with invalid A");
1741*e1eccf28SAndroid Build Coastguard Worker         }
1742*e1eccf28SAndroid Build Coastguard Worker     } else {
1743*e1eccf28SAndroid Build Coastguard Worker         if (cdim != (int)A->getType()->getX()) {
1744*e1eccf28SAndroid Build Coastguard Worker             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called HERK with invalid A");
1745*e1eccf28SAndroid Build Coastguard Worker         }
1746*e1eccf28SAndroid Build Coastguard Worker     }
1747*e1eccf28SAndroid Build Coastguard Worker }
1748*e1eccf28SAndroid Build Coastguard Worker 
CHERK(RsBlasUplo Uplo,RsBlasTranspose Trans,float alpha,const sp<Allocation> & A,float beta,const sp<Allocation> & C)1749*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CHERK(RsBlasUplo Uplo, RsBlasTranspose Trans, float alpha,
1750*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, float beta, const sp<Allocation>& C) {
1751*e1eccf28SAndroid Build Coastguard Worker     validateHERK(mRS, Element::F32_2(mRS), Trans, A, C);
1752*e1eccf28SAndroid Build Coastguard Worker     int k = 0;
1753*e1eccf28SAndroid Build Coastguard Worker     if (Trans == RsBlasConjTrans) {
1754*e1eccf28SAndroid Build Coastguard Worker         k = A->getType()->getY();
1755*e1eccf28SAndroid Build Coastguard Worker     } else {
1756*e1eccf28SAndroid Build Coastguard Worker         k = A->getType()->getX();
1757*e1eccf28SAndroid Build Coastguard Worker     }
1758*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_cherk,
1759*e1eccf28SAndroid Build Coastguard Worker                                  Trans, 0, 0, Uplo, 0, 0, C->getType()->getX(), k,
1760*e1eccf28SAndroid Build Coastguard Worker                                  alpha, 0, A->getID(), 0,
1761*e1eccf28SAndroid Build Coastguard Worker                                  beta, 0, C->getID(), 0, 0, 0, 0);
1762*e1eccf28SAndroid Build Coastguard Worker }
1763*e1eccf28SAndroid Build Coastguard Worker 
ZHERK(RsBlasUplo Uplo,RsBlasTranspose Trans,double alpha,const sp<Allocation> & A,double beta,const sp<Allocation> & C)1764*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZHERK(RsBlasUplo Uplo, RsBlasTranspose Trans, double alpha,
1765*e1eccf28SAndroid Build Coastguard Worker                                 const sp<Allocation>& A, double beta, const sp<Allocation>& C) {
1766*e1eccf28SAndroid Build Coastguard Worker     validateHERK(mRS, Element::F64_2(mRS), Trans, A, C);
1767*e1eccf28SAndroid Build Coastguard Worker     int k = 0;
1768*e1eccf28SAndroid Build Coastguard Worker     if (Trans == RsBlasConjTrans) {
1769*e1eccf28SAndroid Build Coastguard Worker         k = A->getType()->getY();
1770*e1eccf28SAndroid Build Coastguard Worker     } else {
1771*e1eccf28SAndroid Build Coastguard Worker         k = A->getType()->getX();
1772*e1eccf28SAndroid Build Coastguard Worker     }
1773*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zherk,
1774*e1eccf28SAndroid Build Coastguard Worker                            Trans, 0, 0, Uplo, 0, 0, C->getType()->getX(), k,
1775*e1eccf28SAndroid Build Coastguard Worker                            alpha, 0, A->getID(), 0,
1776*e1eccf28SAndroid Build Coastguard Worker                            beta, 0, C->getID(), 0, 0, 0, 0);
1777*e1eccf28SAndroid Build Coastguard Worker }
1778*e1eccf28SAndroid Build Coastguard Worker 
validateHER2K(RS * mRS,const sp<const Element> & e,RsBlasTranspose Trans,const sp<Allocation> & A,const sp<Allocation> & B,const sp<Allocation> & C)1779*e1eccf28SAndroid Build Coastguard Worker static void validateHER2K(RS* mRS, const sp<const Element>& e, RsBlasTranspose Trans,
1780*e1eccf28SAndroid Build Coastguard Worker                           const sp<Allocation>& A, const sp<Allocation>& B, const sp<Allocation>& C) {
1781*e1eccf28SAndroid Build Coastguard Worker     if (!A->getType()->getElement()->isCompatible(e) ||
1782*e1eccf28SAndroid Build Coastguard Worker         !B->getType()->getElement()->isCompatible(e) ||
1783*e1eccf28SAndroid Build Coastguard Worker         !C->getType()->getElement()->isCompatible(e)) {
1784*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Called BLAS with wrong Element type");
1785*e1eccf28SAndroid Build Coastguard Worker     }
1786*e1eccf28SAndroid Build Coastguard Worker     if (Trans != RsBlasNoTrans && Trans != RsBlasConjTrans) {
1787*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Call HERK with invalid Transpose");
1788*e1eccf28SAndroid Build Coastguard Worker     }
1789*e1eccf28SAndroid Build Coastguard Worker     int cdim = C->getType()->getX();
1790*e1eccf28SAndroid Build Coastguard Worker     if (cdim != (int)C->getType()->getY()) {
1791*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called HER2K with non-square C");
1792*e1eccf28SAndroid Build Coastguard Worker     }
1793*e1eccf28SAndroid Build Coastguard Worker     if (Trans == RsBlasNoTrans) {
1794*e1eccf28SAndroid Build Coastguard Worker         if ((int)A->getType()->getY() != cdim) {
1795*e1eccf28SAndroid Build Coastguard Worker             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called HER2K with invalid matrices");
1796*e1eccf28SAndroid Build Coastguard Worker         }
1797*e1eccf28SAndroid Build Coastguard Worker     } else {
1798*e1eccf28SAndroid Build Coastguard Worker         if ((int)A->getType()->getX() != cdim) {
1799*e1eccf28SAndroid Build Coastguard Worker             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called HER2K with invalid matrices");
1800*e1eccf28SAndroid Build Coastguard Worker         }
1801*e1eccf28SAndroid Build Coastguard Worker     }
1802*e1eccf28SAndroid Build Coastguard Worker     if (A->getType()->getX() != B->getType()->getX() || A->getType()->getY() != B->getType()->getY()) {
1803*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Called HER2K with invalid A and B matrices");
1804*e1eccf28SAndroid Build Coastguard Worker     }
1805*e1eccf28SAndroid Build Coastguard Worker }
1806*e1eccf28SAndroid Build Coastguard Worker 
CHER2K(RsBlasUplo Uplo,RsBlasTranspose Trans,Float2 alpha,const sp<Allocation> & A,const sp<Allocation> & B,float beta,const sp<Allocation> & C)1807*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::CHER2K(RsBlasUplo Uplo, RsBlasTranspose Trans, Float2 alpha,
1808*e1eccf28SAndroid Build Coastguard Worker                                  const sp<Allocation>& A, const sp<Allocation>& B, float beta, const sp<Allocation>& C) {
1809*e1eccf28SAndroid Build Coastguard Worker     validateHER2K(mRS, Element::F32_2(mRS), Trans, A, B, C);
1810*e1eccf28SAndroid Build Coastguard Worker     int k = 0;
1811*e1eccf28SAndroid Build Coastguard Worker     if (Trans == RsBlasNoTrans) {
1812*e1eccf28SAndroid Build Coastguard Worker         k = A->getType()->getX();
1813*e1eccf28SAndroid Build Coastguard Worker     } else {
1814*e1eccf28SAndroid Build Coastguard Worker         k = A->getType()->getY();
1815*e1eccf28SAndroid Build Coastguard Worker     }
1816*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Complex(mRS, mRS->getContext(), getID(), RsBlas_cher2k,
1817*e1eccf28SAndroid Build Coastguard Worker                                  Trans, 0, 0, Uplo, 0, 0, C->getType()->getX(), k,
1818*e1eccf28SAndroid Build Coastguard Worker                                  alpha.x, alpha.y, A->getID(), B->getID(),
1819*e1eccf28SAndroid Build Coastguard Worker                                  beta, 0, C->getID(), 0, 0, 0, 0);
1820*e1eccf28SAndroid Build Coastguard Worker }
1821*e1eccf28SAndroid Build Coastguard Worker 
ZHER2K(RsBlasUplo Uplo,RsBlasTranspose Trans,Double2 alpha,const sp<Allocation> & A,const sp<Allocation> & B,double beta,const sp<Allocation> & C)1822*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::ZHER2K(RsBlasUplo Uplo, RsBlasTranspose Trans, Double2 alpha,
1823*e1eccf28SAndroid Build Coastguard Worker                                  const sp<Allocation>& A, const sp<Allocation>& B, double beta, const sp<Allocation>& C) {
1824*e1eccf28SAndroid Build Coastguard Worker     validateHER2K(mRS, Element::F64_2(mRS), Trans, A, B, C);
1825*e1eccf28SAndroid Build Coastguard Worker     int k = 0;
1826*e1eccf28SAndroid Build Coastguard Worker     if (Trans == RsBlasNoTrans) {
1827*e1eccf28SAndroid Build Coastguard Worker         k = A->getType()->getX();
1828*e1eccf28SAndroid Build Coastguard Worker     } else {
1829*e1eccf28SAndroid Build Coastguard Worker         k = A->getType()->getY();
1830*e1eccf28SAndroid Build Coastguard Worker     }
1831*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_Z(mRS, mRS->getContext(), getID(), RsBlas_zher2k,
1832*e1eccf28SAndroid Build Coastguard Worker                            Trans, 0, 0, Uplo, 0, 0, C->getType()->getX(), k,
1833*e1eccf28SAndroid Build Coastguard Worker                            alpha.x, alpha.y, A->getID(), B->getID(),
1834*e1eccf28SAndroid Build Coastguard Worker                            beta, 0, C->getID(), 0, 0, 0, 0);
1835*e1eccf28SAndroid Build Coastguard Worker }
1836*e1eccf28SAndroid Build Coastguard Worker 
1837*e1eccf28SAndroid Build Coastguard Worker 
1838*e1eccf28SAndroid Build Coastguard Worker 
BNNM(const sp<Allocation> & A,int a_offset,const sp<Allocation> & B,int b_offset,const sp<Allocation> & C,int c_offset,int c_mult)1839*e1eccf28SAndroid Build Coastguard Worker void ScriptIntrinsicBLAS::BNNM(const sp<Allocation>& A, int a_offset, const sp<Allocation>& B, int b_offset,
1840*e1eccf28SAndroid Build Coastguard Worker                                const sp<Allocation>& C, int c_offset, int c_mult) {
1841*e1eccf28SAndroid Build Coastguard Worker     validateL3(mRS, Element::U8(mRS), RsBlasNoTrans, RsBlasTrans, 0, A, B, C);
1842*e1eccf28SAndroid Build Coastguard Worker 
1843*e1eccf28SAndroid Build Coastguard Worker     if (a_offset < 0 || a_offset > 255) {
1844*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid a_offset passed to BNNM");
1845*e1eccf28SAndroid Build Coastguard Worker     }
1846*e1eccf28SAndroid Build Coastguard Worker     if (b_offset < 0 || b_offset > 255) {
1847*e1eccf28SAndroid Build Coastguard Worker         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid b_offset passed to BNNM");
1848*e1eccf28SAndroid Build Coastguard Worker     }
1849*e1eccf28SAndroid Build Coastguard Worker     int M = -1, N = -1, K = -1;
1850*e1eccf28SAndroid Build Coastguard Worker     M = A->getType()->getY();
1851*e1eccf28SAndroid Build Coastguard Worker     N = B->getType()->getY();
1852*e1eccf28SAndroid Build Coastguard Worker     K = A->getType()->getX();
1853*e1eccf28SAndroid Build Coastguard Worker 
1854*e1eccf28SAndroid Build Coastguard Worker     nScriptIntrinsicBLAS_BNNM(mRS, mRS->getContext(), getID(), M, N, K, A->getID(), a_offset,
1855*e1eccf28SAndroid Build Coastguard Worker                               B->getID(), b_offset, C->getID(), c_offset, c_mult);
1856*e1eccf28SAndroid Build Coastguard Worker }
1857