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>
13 #include <formula/vectortoken.hxx>
14 
15 #include <algorithm>
16 #include <sstream>
17 
18 using namespace formula;
19 
20 namespace sc::opencl {
21 
22 void OpVLookup::GenSlidingWindowFunction(std::stringstream &ss,
23  const std::string &sSymName, SubArguments &vSubArguments)
24 {
25  ss << "\ndouble " << sSymName;
26  ss << "_"<< BinFuncName() <<"(";
27  for (size_t i = 0; i < vSubArguments.size(); i++)
28  {
29  if (i)
30  ss << ",";
31  vSubArguments[i]->GenSlidingWindowDecl(ss);
32  }
33  ss << ")\n {\n";
34  ss << " int gid0=get_global_id(0);\n";
35  ss << " double tmp = CreateDoubleError(NOTAVAILABLE);\n";
36  ss << " double intermediate = DBL_MAX;\n";
37  ss << " int singleIndex = gid0;\n";
38  ss << " int rowNum = -1;\n";
39 
40  GenTmpVariables(ss,vSubArguments);
41  int arg=0;
42  CheckSubArgumentIsNan(ss,vSubArguments,arg++);
43  int secondParaWidth = 1;
44 
45  // tdf#99512 - for now only allow non-dynamic indices (the
46  // common-case) to validate consistent return types vs. the input.
47  int index = 0;
48  int indexArg = vSubArguments.size() - 2;
49  if (vSubArguments[indexArg]->GetFormulaToken()->GetType() == formula::svDouble)
50  {
51  const formula::FormulaDoubleToken *dblToken = static_cast<const FormulaDoubleToken *>(vSubArguments[indexArg]->GetFormulaToken());
52  index = ::rtl::math::approxFloor(dblToken->GetDouble());
53  }
54 
55  if (vSubArguments[1]->GetFormulaToken()->GetType() != formula::svDoubleVectorRef)
56  throw Unhandled(__FILE__, __LINE__); // unusual vlookup.
57 
58  FormulaToken *tmpCur = vSubArguments[1]->GetFormulaToken();
59  const formula::DoubleVectorRefToken*pCurDVR = static_cast<const formula::DoubleVectorRefToken *>(tmpCur);
60  const std::vector<VectorRefArray> items = pCurDVR->GetArrays();
61 
62  secondParaWidth = items.size();
63 
64  if (index < 1 || index > secondParaWidth)
65  throw Unhandled(__FILE__, __LINE__); // oob index.
66 
67  if (items[index - 1].mpStringArray)
68  {
69  rtl_uString **pStrings = items[index - 1].mpStringArray;
70  for (size_t i = 0; i < pCurDVR->GetArrayLength(); ++i)
71  {
72  if (pStrings[i] != nullptr)
73  { // TODO: the GroupTokenConverter should do better.
74  throw Unhandled(__FILE__, __LINE__); // mixed arguments.
75  }
76  }
77  }
78 
79 
80  arg += secondParaWidth;
81  CheckSubArgumentIsNan(ss,vSubArguments,arg++);
82 
83  if (vSubArguments.size() == static_cast<unsigned int>(3+(secondParaWidth-1)))
84  {
85  ss << " double tmp";
86  ss << 3+(secondParaWidth-1);
87  ss << "= 1;\n";
88  }
89  else
90  {
91  CheckSubArgumentIsNan(ss,vSubArguments,arg++);
92  }
93 
94  if (vSubArguments[1]->GetFormulaToken()->GetType() == formula::svDoubleVectorRef)
95  {
96  tmpCur = vSubArguments[1]->GetFormulaToken();
97  pCurDVR = static_cast<const formula::DoubleVectorRefToken *>(tmpCur);
98  size_t nCurWindowSize = std::min(pCurDVR->GetArrayLength(), pCurDVR->GetRefRowSize());
99  int unrollSize = 8;
100  ss << " int loop;\n";
101  if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed())
102  {
103  ss << " loop = ("<<nCurWindowSize<<" - gid0)/";
104  ss << unrollSize<<";\n";
105 
106  }
107  else if (pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
108  {
109  ss << " loop = ("<<nCurWindowSize<<" + gid0)/";
110  ss << unrollSize<<";\n";
111 
112  }
113  else
114  {
115  ss << " loop = "<<nCurWindowSize<<"/"<< unrollSize<<";\n";
116  }
117 
118  for (int i = 0; i < secondParaWidth; i++)
119  {
120  ss << " for ( int j = 0;j< loop; j++)\n";
121  ss << " {\n";
122  ss << " int i = ";
123  if (!pCurDVR->IsStartFixed()&& pCurDVR->IsEndFixed())
124  {
125  ss << "gid0 + j * "<< unrollSize <<";\n";
126  }
127  else
128  {
129  ss << "j * "<< unrollSize <<";\n";
130  }
131  if (!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
132  {
133  ss << " int doubleIndex = i+gid0;\n";
134  }
135  else
136  {
137  ss << " int doubleIndex = i;\n";
138  }
139  ss << " if(tmp";
140  ss << 3+(secondParaWidth-1);
141  ss << " == 1)\n";
142  ss << " {\n";
143 
144  for (int j = 0;j < unrollSize; j++)
145  {
146  CheckSubArgumentIsNan(ss,vSubArguments,1+i);
147 
148  ss << " if((tmp0 - tmp";
149  ss << 1+i;
150  ss << ")>=0 && intermediate > ( tmp0 -tmp";
151  ss << 1+i;
152  ss << "))\n";
153  ss << " {\n";
154  ss << " rowNum = doubleIndex;\n";
155  ss << " intermediate = tmp0 - tmp";
156  ss << 1+i;
157  ss << ";\n";
158  ss << " }\n";
159  ss << " i++;\n";
160  ss << " doubleIndex++;\n";
161  }
162 
163  ss << " }else\n";
164  ss << " {\n";
165  for (int j = 0; j < unrollSize; j++)
166  {
167  CheckSubArgumentIsNan(ss,vSubArguments,1+i);
168 
169  ss << " if(tmp0 == tmp";
170  ss << 1+i;
171  ss << " && rowNum == -1)\n";
172  ss << " {\n";
173  ss << " rowNum = doubleIndex;\n";
174  ss << " }\n";
175  ss << " i++;\n";
176  ss << " doubleIndex++;\n";
177  }
178  ss << " }\n\n";
179 
180  ss << " }\n";
181  ss << " if(rowNum!=-1)\n";
182  ss << " {\n";
183  for (int j = 0; j < secondParaWidth; j++)
184  {
185  ss << " if(tmp";
186  ss << 2+(secondParaWidth-1);
187  ss << " == ";
188  ss << j+1;
189  ss << ")\n";
190  ss << " tmp = ";
191  vSubArguments[1+j]->GenDeclRef(ss);
192  ss << "[rowNum];\n";
193  }
194  ss << " return tmp;\n";
195  ss << " }\n";
196  ss << " for (int i = ";
197  if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed())
198  {
199  ss << "gid0 + loop *"<<unrollSize<<"; i < ";
200  ss << nCurWindowSize <<"; i++)\n";
201  }
202  else if (pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
203  {
204  ss << "0 + loop *"<<unrollSize<<"; i < gid0+";
205  ss << nCurWindowSize <<"; i++)\n";
206  }
207  else
208  {
209  ss << "0 + loop *"<<unrollSize<<"; i < ";
210  ss << nCurWindowSize <<"; i++)\n";
211  }
212  ss << " {\n";
213  if (!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
214  {
215  ss << " int doubleIndex = i+gid0;\n";
216  }
217  else
218  {
219  ss << " int doubleIndex = i;\n";
220  }
221  CheckSubArgumentIsNan(ss,vSubArguments,1+i);
222  ss << " if(tmp";
223  ss << 3+(secondParaWidth-1);
224  ss << " == 1)\n";
225  ss << " {\n";
226  ss << " if((tmp0 - tmp";
227  ss << 1+i;
228  ss << ")>=0 && intermediate > ( tmp0 -tmp";
229  ss << 1+i;
230  ss << "))\n";
231  ss << " {\n";
232  ss << " rowNum = doubleIndex;\n";
233  ss << " intermediate = tmp0 - tmp";
234  ss << 1+i;
235  ss << ";\n";
236  ss << " }\n";
237  ss << " }\n";
238  ss << " else\n";
239  ss << " {\n";
240  ss << " if(tmp0 == tmp";
241  ss << 1+i;
242  ss << " && rowNum == -1)\n";
243  ss << " {\n";
244  ss << " rowNum = doubleIndex;\n";
245  ss << " }\n";
246  ss << " }\n";
247 
248  ss << " }\n\n";
249  ss << " if(rowNum!=-1)\n";
250  ss << " {\n";
251 
252  for (int j = 0; j < secondParaWidth; j++)
253  {
254  ss << " if(tmp";
255  ss << 2+(secondParaWidth-1);
256  ss << " == ";
257  ss << j+1;
258  ss << ")\n";
259  ss << " tmp = ";
260  vSubArguments[1+j]->GenDeclRef(ss);
261  ss << "[rowNum];\n";
262  }
263  ss << " return tmp;\n";
264  ss << " }\n";
265 
266  }
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: */
Inconsistent state.
Definition: opbase.hxx:53
const std::vector< VectorRefArray > & GetArrays() const
int i
virtual double GetDouble() const override
std::vector< DynamicKernelArgumentRef > SubArguments
Definition: opbase.hxx:214
Arguments that are actually compile-time constant string Currently, only the hash is passed...
tuple index
size_t GetArrayLength() const