LibreOffice Module sc (master) 1
op_spreadsheet.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10#include "op_spreadsheet.hxx"
11
12#include <rtl/math.hxx>
14
15#include <algorithm>
16#include <sstream>
17
18using namespace formula;
19
20namespace sc::opencl {
21
23 const std::string &sSymName, SubArguments &vSubArguments)
24{
25 GenerateFunctionDeclaration( sSymName, vSubArguments, ss );
26 ss << "{\n";
27 ss << " int gid0=get_global_id(0);\n";
28 ss << " double tmp = CreateDoubleError(NOTAVAILABLE);\n";
29 ss << " double intermediate = DBL_MAX;\n";
30 ss << " int singleIndex = gid0;\n";
31 ss << " int rowNum = -1;\n";
32
33 GenTmpVariables(ss,vSubArguments);
34 int arg=0;
35 CheckSubArgumentIsNan(ss,vSubArguments,arg++);
36 int secondParaWidth = 1;
37
38 // tdf#99512 - for now only allow non-dynamic indices (the
39 // common-case) to validate consistent return types vs. the input.
40 int index = 0;
41 int indexArg = vSubArguments.size() - 2;
42 if (vSubArguments[indexArg]->GetFormulaToken()->GetType() == formula::svDouble)
43 {
44 const formula::FormulaDoubleToken *dblToken = static_cast<const FormulaDoubleToken *>(vSubArguments[indexArg]->GetFormulaToken());
45 index = ::rtl::math::approxFloor(dblToken->GetDouble());
46 }
47
48 if (vSubArguments[1]->GetFormulaToken()->GetType() != formula::svDoubleVectorRef)
49 throw Unhandled(__FILE__, __LINE__); // unusual vlookup.
50
51 FormulaToken *tmpCur = vSubArguments[1]->GetFormulaToken();
52 const formula::DoubleVectorRefToken*pCurDVR = static_cast<const formula::DoubleVectorRefToken *>(tmpCur);
53 const std::vector<VectorRefArray> items = pCurDVR->GetArrays();
54
55 secondParaWidth = items.size();
56
57 if (index < 1 || index > secondParaWidth)
58 throw Unhandled(__FILE__, __LINE__); // oob index.
59
60 if (items[index - 1].mpStringArray)
61 {
62 rtl_uString **pStrings = items[index - 1].mpStringArray;
63 for (size_t i = 0; i < pCurDVR->GetArrayLength(); ++i)
64 {
65 if (pStrings[i] != nullptr)
66 { // TODO: the GroupTokenConverter should do better.
67 throw Unhandled(__FILE__, __LINE__); // mixed arguments.
68 }
69 }
70 }
71
72
73 arg += secondParaWidth;
74 CheckSubArgumentIsNan(ss,vSubArguments,arg++);
75
76 if (vSubArguments.size() == static_cast<unsigned int>(3+(secondParaWidth-1)))
77 {
78 ss << " double tmp";
79 ss << 3+(secondParaWidth-1);
80 ss << "= 1;\n";
81 }
82 else
83 {
84 CheckSubArgumentIsNan(ss,vSubArguments,arg++);
85 }
86
87 if (vSubArguments[1]->GetFormulaToken()->GetType() == formula::svDoubleVectorRef)
88 {
89 tmpCur = vSubArguments[1]->GetFormulaToken();
90 pCurDVR = static_cast<const formula::DoubleVectorRefToken *>(tmpCur);
91 size_t nCurWindowSize = std::min(pCurDVR->GetArrayLength(), pCurDVR->GetRefRowSize());
92 const int unrollSize = 8;
93
94 ss << "\n";
95 ss << " int loop = ";
96 if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed())
97 {
98 ss << "("<<nCurWindowSize<<" - gid0)/";
99 ss << unrollSize<<";\n";
100 }
101 else if (pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
102 {
103 ss << "("<<nCurWindowSize<<" + gid0)/";
104 ss << unrollSize<<";\n";
105 }
106 else
107 {
108 ss << nCurWindowSize<<"/"<< unrollSize<<";\n";
109 }
110
111 ss << " if(tmp";
112 ss << 3+(secondParaWidth-1);
113 ss << " == 0) /* unsorted vlookup */\n";
114 ss << " {\n";
115
116 for( int sorted = 0; sorted < 2; ++sorted ) // sorted vs unsorted vlookup cases
117 {
118 if( sorted == 1 )
119 {
120 ss << " }\n";
121 ss << " else\n";
122 ss << " { /* sorted vlookup */ \n";
123 }
124
125 ss << " for ( int j = 0;j< loop; j++)\n";
126 ss << " {\n";
127 ss << " int i = ";
128 if (!pCurDVR->IsStartFixed()&& pCurDVR->IsEndFixed())
129 {
130 ss << "gid0 + j * "<< unrollSize <<";\n";
131 }
132 else
133 {
134 ss << "j * "<< unrollSize <<";\n";
135 }
136 if (!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
137 {
138 ss << " int doubleIndex = i+gid0;\n";
139 }
140 else
141 {
142 ss << " int doubleIndex = i;\n";
143 }
144
145 for (int j = 0;j < unrollSize; j++)
146 {
147 CheckSubArgumentIsNan(ss,vSubArguments,1);
148
149 if( sorted == 1 )
150 {
151 ss << " if((tmp0 - tmp1)>=0 && intermediate > (tmp0 -tmp1))\n";
152 ss << " {\n";
153 ss << " rowNum = doubleIndex;\n";
154 ss << " intermediate = tmp0 - tmp1;\n";
155 ss << " }\n";
156 ss << " i++;\n";
157 ss << " doubleIndex++;\n";
158 }
159 else
160 {
161 ss << " if(tmp0 == tmp1)\n";
162 ss << " {\n";
163 ss << " rowNum = doubleIndex;\n";
164 ss << " break;\n";
165 ss << " }\n";
166 ss << " i++;\n";
167 ss << " doubleIndex++;\n";
168 }
169 }
170 ss << " }\n\n";
171 }
172
173 ss << " }\n";
174 ss << " if(rowNum!=-1)\n";
175 ss << " {\n";
176 for (int j = 0; j < secondParaWidth; j++)
177 {
178 ss << " if(tmp";
179 ss << 2+(secondParaWidth-1);
180 ss << " == ";
181 ss << j+1;
182 ss << ")\n";
183 ss << " tmp = ";
184 vSubArguments[1+j]->GenDeclRef(ss);
185 ss << "[rowNum];\n";
186 }
187 ss << " return tmp;\n";
188 ss << " }\n";
189
190 ss << " if(tmp";
191 ss << 3+(secondParaWidth-1);
192 ss << " == 0) /* unsorted vlookup */\n";
193 ss << " {\n";
194
195 for( int sorted = 0; sorted < 2; ++sorted ) // sorted vs unsorted vlookup cases
196 {
197 if( sorted == 1 )
198 {
199 ss << " }\n";
200 ss << " else\n";
201 ss << " { /* sorted vlookup */ \n";
202 }
203
204 ss << " for (int i = ";
205 if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed())
206 {
207 ss << "gid0 + loop *"<<unrollSize<<"; i < ";
208 ss << nCurWindowSize <<"; i++)\n";
209 }
210 else if (pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
211 {
212 ss << "0 + loop *"<<unrollSize<<"; i < gid0+";
213 ss << nCurWindowSize <<"; i++)\n";
214 }
215 else
216 {
217 ss << "0 + loop *"<<unrollSize<<"; i < ";
218 ss << nCurWindowSize <<"; i++)\n";
219 }
220 ss << " {\n";
221 if (!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
222 {
223 ss << " int doubleIndex = i+gid0;\n";
224 }
225 else
226 {
227 ss << " int doubleIndex = i;\n";
228 }
229 CheckSubArgumentIsNan(ss,vSubArguments,1);
230
231 if( sorted == 1 )
232 {
233 ss << " if((tmp0 - tmp1)>=0 && intermediate > (tmp0 -tmp1))\n";
234 ss << " {\n";
235 ss << " rowNum = doubleIndex;\n";
236 ss << " intermediate = tmp0 - tmp1;\n";
237 ss << " }\n";
238 }
239 else
240 {
241 ss << " if(tmp0 == tmp1)\n";
242 ss << " {\n";
243 ss << " rowNum = doubleIndex;\n";
244 ss << " break;\n";
245 ss << " }\n";
246 }
247 ss << " }\n\n";
248 }
249
250 ss << " }\n";
251 ss << " if(rowNum!=-1)\n";
252 ss << " {\n";
253
254 for (int j = 0; j < secondParaWidth; j++)
255 {
256 ss << " if(tmp";
257 ss << 2+(secondParaWidth-1);
258 ss << " == ";
259 ss << j+1;
260 ss << ")\n";
261 ss << " tmp = ";
262 vSubArguments[1+j]->GenDeclRef(ss);
263 ss << "[rowNum];\n";
264 }
265 ss << " return tmp;\n";
266 ss << " }\n";
267 }
268 else
269 {
270 CheckSubArgumentIsNan(ss,vSubArguments,1);
271 ss << " if(tmp3 == 1)\n";
272 ss << " {\n";
273 ss << " tmp = tmp1;\n";
274 ss << " }else\n";
275 ss << " {\n";
276 ss << " if(tmp0 == tmp1)\n";
277 ss << " tmp = tmp1;\n";
278 ss << " }\n";
279 }
280 ss << " return tmp;\n";
281 ss << "}";
282}
283
284}
285
286/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const std::vector< VectorRefArray > & GetArrays() const
virtual double GetDouble() const override
static void CheckSubArgumentIsNan(outputstream &ss, SubArguments &vSubArguments, int argumentNum)
Definition: opbase.cxx:608
static void GenTmpVariables(outputstream &ss, const SubArguments &vSubArguments)
Definition: opbase.cxx:597
virtual void GenSlidingWindowFunction(outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments) override
void GenerateFunctionDeclaration(const std::string &sSymName, SubArguments &vSubArguments, outputstream &ss)
Definition: opbase.cxx:566
std::vector< DynamicKernelArgumentRef > SubArguments
Definition: opbase.hxx:347
Inconsistent state.
Definition: opbase.hxx:65
int i
index