LibreOffice Module sc (master) 1
opbase.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
12#include <sal/log.hxx>
13#include <utility>
14
15#include "opbase.hxx"
16
17using namespace formula;
18
19namespace sc::opencl {
20
22 const char* m, std::string fn, int ln ) :
23 mMessage(m), mFile(std::move(fn)), mLineNumber(ln) {}
24
25OpenCLError::OpenCLError( std::string function, cl_int error, std::string file, int line ) :
26 mFunction(std::move(function)), mError(error), mFile(std::move(file)), mLineNumber(line)
27{
28 // Not sure if this SAL_INFO() is useful; the place in
29 // CLInterpreterContext::launchKernel() where OpenCLError is
30 // caught already uses SAL_WARN() to display it.
31
32 // SAL_INFO("sc.opencl", "OpenCL error: " << openclwrapper::errorString(mError));
33}
34
35Unhandled::Unhandled( std::string fn, int ln ) :
36 mFile(std::move(fn)), mLineNumber(ln) {}
37
38InvalidParameterCount::InvalidParameterCount( int parameterCount, std::string file, int ln ) :
39 mParameterCount(parameterCount), mFile(std::move(file)), mLineNumber(ln) {}
40
43 mCalcConfig(config), mSymName(std::move(s)), mFormulaTree(std::move(ft)) { }
44
46{
47 return std::string("");
48}
49
52{
53 return std::string("");
54}
55
58{
59 ss << mSymName;
60}
61
63
65{
66 return mFormulaTree->GetFormulaToken();
67}
68
70{
71 return std::string("");
72}
73
74void DynamicKernelArgument::DumpInlineFun( std::set<std::string>&, std::set<std::string>& ) const {}
75
76const std::string& DynamicKernelArgument::GetName() const
77{
78 return mSymName;
79}
80
82{
83 return false;
84}
85
86VectorRef::VectorRef( const ScCalcConfig& config, const std::string& s, const FormulaTreeNodeRef& ft, int idx ) :
87 DynamicKernelArgument(config, s, ft), mpClmem(nullptr), mnIndex(idx), forceStringsToZero( false )
88{
89 if (mnIndex)
90 {
91 outputstream ss;
92 ss << mSymName << "s" << mnIndex;
93 mSymName = ss.str();
94 }
95}
96
98{
99 if (mpClmem)
100 {
101 cl_int err;
102 err = clReleaseMemObject(mpClmem);
103 SAL_WARN_IF(err != CL_SUCCESS, "sc.opencl", "clReleaseMemObject failed: " << openclwrapper::errorString(err));
104 }
105}
106
109{
110 ss << "__global double *" << mSymName;
111}
112
115{
117}
118
120std::string VectorRef::GenSlidingWindowDeclRef( bool nested ) const
121{
122 outputstream ss;
125 if (pSVR && !nested)
126 ss << "(gid0 < " << pSVR->GetArrayLength() << "?";
127 ss << mSymName << "[gid0]";
128 if (pSVR && !nested)
129 ss << ":NAN)";
130 return ss.str();
131}
132
134
136{
137 FormulaToken* pCur = mFormulaTree->GetFormulaToken();
138 assert(pCur);
139 if (const formula::DoubleVectorRefToken* pCurDVR =
140 dynamic_cast<const formula::DoubleVectorRefToken*>(pCur))
141 {
142 return pCurDVR->GetRefRowSize();
143 }
144 else if (dynamic_cast<const formula::SingleVectorRefToken*>(pCur))
145 {
146 // Prepare intermediate results (on CPU for now)
147 return 1;
148 }
149 else
150 {
151 throw Unhandled(__FILE__, __LINE__);
152 }
153}
154
155std::string VectorRef::DumpOpName() const
156{
157 return std::string("");
158}
159
160void VectorRef::DumpInlineFun( std::set<std::string>&, std::set<std::string>& ) const {}
161
162const std::string& VectorRef::GetName() const
163{
164 return mSymName;
165}
166
168{
169 return mpClmem;
170}
171
173{
174 return false;
175}
176
178 const FormulaTreeNodeRef& ft, int index )
179 : VectorRef( config, s, ft, index )
180{
181 forceStringsToZero = true;
182}
183
184void SlidingFunctionBase::GenerateArg( const char* name, int arg, SubArguments& vSubArguments,
185 outputstream& ss, EmptyArgType empty )
186{
187 assert( arg < int( vSubArguments.size()));
188 FormulaToken *token = vSubArguments[arg]->GetFormulaToken();
189 if( token == nullptr )
190 throw Unhandled( __FILE__, __LINE__ );
191 if(token->GetOpCode() == ocPush)
192 {
193 if(token->GetType() == formula::svSingleVectorRef)
194 {
196 static_cast<const formula::SingleVectorRefToken *>(token);
197 ss << " double " << name << " = NAN;\n";
198 ss << " if (gid0 < " << svr->GetArrayLength() << ")\n";
199 ss << " " << name << " = ";
200 ss << vSubArguments[arg]->GenSlidingWindowDeclRef() << ";\n";
201 switch( empty )
202 {
203 case EmptyIsZero:
204 ss << " if( isnan( " << name << " ))\n";
205 ss << " " << name << " = 0;\n";
206 break;
207 case EmptyIsNan:
208 break;
209 case SkipEmpty:
210 abort();
211 break;
212 }
213 }
214 else if(token->GetType() == formula::svDouble)
215 ss << " double " << name << " = " << token->GetDouble() << ";\n";
216 else if(token->GetType() == formula::svString)
217 {
218 assert( dynamic_cast<DynamicKernelStringToZeroArgument*>(vSubArguments[arg].get()));
219 ss << " double " << name << " = 0.0;\n";
220 }
221 else
222 throw Unhandled( __FILE__, __LINE__ );
223 }
224 else
225 {
226 ss << " double " << name << " = ";
227 ss << vSubArguments[arg]->GenSlidingWindowDeclRef() << ";\n";
228 }
229}
230
232 EmptyArgType empty )
233{
234 char buf[ 30 ];
235 sprintf( buf, "arg%d", arg );
236 GenerateArg( buf, arg, vSubArguments, ss, empty );
237}
238
239void SlidingFunctionBase::GenerateArgWithDefault( const char* name, int arg, double def,
240 SubArguments& vSubArguments, outputstream& ss, EmptyArgType empty )
241{
242 if( arg < int(vSubArguments.size()))
243 GenerateArg( name, arg, vSubArguments, ss, empty );
244 else
245 ss << " double " << name << " = " << def << ";\n";
246}
247
248void SlidingFunctionBase::GenerateRangeArgs( int firstArg, int lastArg, SubArguments& vSubArguments,
249 outputstream& ss, EmptyArgType empty, const char* code )
250{
251 assert( firstArg >= 0 );
252 assert( firstArg <= lastArg );
253 assert( lastArg < int( vSubArguments.size()));
254 for( int i = firstArg;
255 i <= lastArg;
256 ++i )
257 {
258 FormulaToken *token = vSubArguments[i]->GetFormulaToken();
259 if( token == nullptr )
260 throw Unhandled( __FILE__, __LINE__ );
261 if(token->GetOpCode() == ocPush)
262 {
263 if (token->GetType() == formula::svDoubleVectorRef)
264 {
266 static_cast<const formula::DoubleVectorRefToken *>(token);
267 GenerateDoubleVectorLoopHeader( ss, pDVR, nullptr );
268 ss << " double arg = ";
269 ss << vSubArguments[i]->GenSlidingWindowDeclRef();
270 ss << ";\n";
271 switch( empty )
272 {
273 case EmptyIsZero:
274 ss << " if( isnan( arg ))\n";
275 ss << " arg = 0;\n";
276 break;
277 case EmptyIsNan:
278 break;
279 case SkipEmpty:
280 ss << " if( isnan( arg ))\n";
281 ss << " continue;\n";
282 break;
283 }
284 ss << code;
285 ss << " }\n";
286 }
287 else if (token->GetType() == formula::svSingleVectorRef)
288 {
290 static_cast< const formula::SingleVectorRefToken*>(token);
291 ss << " if (gid0 < " << pSVR->GetArrayLength() << ")\n";
292 ss << " {\n";
293 ss << " double arg = ";
294 ss << vSubArguments[i]->GenSlidingWindowDeclRef() << ";\n";
295 switch( empty )
296 {
297 case EmptyIsZero:
298 ss << " if( isnan( arg ))\n";
299 ss << " arg = 0;\n";
300 ss << code;
301 break;
302 case EmptyIsNan:
303 ss << code;
304 break;
305 case SkipEmpty:
306 ss << " if( !isnan( arg ))\n";
307 ss << " {\n";
308 ss << code;
309 ss << " }\n";
310 break;
311 }
312 ss << " }\n";
313 }
314 else if(token->GetType() == formula::svDouble)
315 {
316 ss << " {\n";
317 ss << " double arg = " << token->GetDouble() << ";\n";
318 ss << code;
319 ss << " }\n";
320 }
321 else if(token->GetType() == formula::svString)
322 {
323 assert( dynamic_cast<DynamicKernelStringToZeroArgument*>(vSubArguments[i].get()));
324 ss << " {\n";
325 ss << " double arg = 0.0;\n";
326 ss << code;
327 ss << " }\n";
328 }
329 else
330 throw Unhandled( __FILE__, __LINE__ );
331 }
332 else
333 {
334 ss << " {\n";
335 ss << " double arg = ";
336 ss << vSubArguments[i]->GenSlidingWindowDeclRef() << ";\n";
337 ss << code;
338 ss << " }\n";
339 }
340 }
341}
342
344 outputstream& ss, EmptyArgType empty, const char* code )
345{
346 GenerateRangeArgs( 0, vSubArguments.size() - 1, vSubArguments, ss, empty, code );
347}
348
350 outputstream& ss, EmptyArgType empty, const char* code )
351{
352 GenerateRangeArgs( arg, arg, vSubArguments, ss, empty, code );
353}
354
355void SlidingFunctionBase::GenerateRangeArgPair( int arg1, int arg2, SubArguments& vSubArguments,
356 outputstream& ss, EmptyArgType empty, const char* code, const char* firstElementDiff )
357{
358 assert( arg1 >= 0 && arg1 < int (vSubArguments.size()));
359 assert( arg2 >= 0 && arg2 < int (vSubArguments.size()));
360 assert( arg1 != arg2 );
361 FormulaToken *token1 = vSubArguments[arg1]->GetFormulaToken();
362 if( token1 == nullptr )
363 throw Unhandled( __FILE__, __LINE__ );
364 FormulaToken *token2 = vSubArguments[arg2]->GetFormulaToken();
365 if( token2 == nullptr )
366 throw Unhandled( __FILE__, __LINE__ );
367 if(token1->GetType() != formula::svDoubleVectorRef
368 || token2->GetType() != formula::svDoubleVectorRef)
369 {
370 throw Unhandled( __FILE__, __LINE__ );
371 }
372 const formula::DoubleVectorRefToken* pDVR1 =
373 static_cast<const formula::DoubleVectorRefToken *>(token1);
374 const formula::DoubleVectorRefToken* pDVR2 =
375 static_cast<const formula::DoubleVectorRefToken *>(token2);
376
377 size_t nCurWindowSize1 = pDVR1->GetRefRowSize();
378 size_t nCurWindowSize2 = pDVR2->GetRefRowSize();
379
380 if(nCurWindowSize1 != nCurWindowSize2)
381 throw Unhandled( __FILE__, __LINE__ );
382 if(pDVR1->IsStartFixed() != pDVR2->IsStartFixed()
383 || pDVR1->IsEndFixed() != pDVR2->IsEndFixed())
384 {
385 throw Unhandled( __FILE__, __LINE__ );
386 }
387
388 // If either of the ranges ends with empty cells, it will not include those last
389 // nan values (its GetArrayLength() will be less than its GetRefRowSize().
390 // If we skip empty cells, just iterate until both ranges have elements, but if
391 // we need to iterate even over empty cells, so use the longer one.
392 // FIXME: If both ranges end with empty cells, this does not actually iterate
393 // over all empty cells.
394 const formula::DoubleVectorRefToken* loopDVR;
395 bool checkBounds;
396 if( empty == SkipEmpty )
397 {
398 loopDVR = pDVR1->GetArrayLength() < pDVR2->GetArrayLength() ? pDVR1 : pDVR2;
399 checkBounds = false;
400 }
401 else
402 {
403 loopDVR = pDVR1->GetArrayLength() > pDVR2->GetArrayLength() ? pDVR1 : pDVR2;
404 checkBounds = true;
405 }
406 GenerateDoubleVectorLoopHeader( ss, loopDVR, firstElementDiff );
407 ss << " double arg1 = ";
408 ss << vSubArguments[arg1]->GenSlidingWindowDeclRef(!checkBounds) << ";\n";
409 ss << " double arg2 = ";
410 ss << vSubArguments[arg2]->GenSlidingWindowDeclRef(!checkBounds) << ";\n";
411 switch( empty )
412 {
413 case EmptyIsZero:
414 ss << " if( isnan( arg1 ))\n";
415 ss << " arg1 = 0;\n";
416 ss << " if( isnan( arg2 ))\n";
417 ss << " arg2 = 0;\n";
418 break;
419 case EmptyIsNan:
420 break;
421 case SkipEmpty:
422 ss << " if( isnan( arg1 ) || isnan( arg2 ))\n";
423 ss << " continue;\n";
424 break;
425 }
426 ss << code;
427 ss << " }\n";
428}
429
430void SlidingFunctionBase::GenerateRangeArgElement( const char* name, int arg, const char* element,
431 SubArguments& vSubArguments, outputstream& ss, EmptyArgType empty )
432{
433 assert( arg >= 0 && arg < int (vSubArguments.size()));
434 FormulaToken *token = vSubArguments[arg]->GetFormulaToken();
435 if( token == nullptr )
436 throw Unhandled( __FILE__, __LINE__ );
437 if(token->GetType() != formula::svDoubleVectorRef)
438 throw Unhandled( __FILE__, __LINE__ );
440 static_cast<const formula::DoubleVectorRefToken *>(token);
441 ss << " double " << name << " = NAN;\n";
442 ss << " {\n";
443 // GenSlidingWindowDeclRef() may refer to 'i' variable.
444 ss << " int i = 0;\n";
445 ss << " if( ";
446 if( !pDVR->IsStartFixed())
447 ss << "gid0 + ";
448 ss << element << " < " << pDVR->GetArrayLength() << " )\n";
449 ss << " " << name << " = " << vSubArguments[arg]->GenSlidingWindowDeclRef(true) << ";\n";
450 ss << " }\n";
451 switch( empty )
452 {
453 case EmptyIsZero:
454 ss << " if( isnan( " << name << " ))\n";
455 ss << " " << name << " = 0;\n";
456 break;
457 case EmptyIsNan:
458 break;
459 case SkipEmpty:
460 abort();
461 break;
462 }
463}
464
466 const formula::DoubleVectorRefToken* pDVR, const char* firstElementDiff )
467{
468 size_t nCurWindowSize = pDVR->GetRefRowSize();
469 std::string startDiff;
470 if( firstElementDiff )
471 startDiff = std::string( " + " ) + firstElementDiff;
472 ss << " for (int i = ";
473 if (!pDVR->IsStartFixed() && pDVR->IsEndFixed())
474 {
475 ss << "gid0" << startDiff << "; i < " << pDVR->GetArrayLength();
476 ss << " && i < " << nCurWindowSize << "; i++)\n";
477 ss << " {\n";
478 }
479 else if (pDVR->IsStartFixed() && !pDVR->IsEndFixed())
480 {
481 ss << "0" << startDiff << "; i < " << pDVR->GetArrayLength();
482 ss << " && i < gid0+" << nCurWindowSize << "; i++)\n";
483 ss << " {\n";
484 }
485 else if (!pDVR->IsStartFixed() && !pDVR->IsEndFixed())
486 {
487 ss << "0" << startDiff << "; i + gid0 < " << pDVR->GetArrayLength();
488 ss << " && i < " << nCurWindowSize << "; i++)\n";
489 ss << " {\n";
490 }
491 else
492 {
493 ss << "0" << startDiff << "; i < " << pDVR->GetArrayLength() << "; i++)\n";
494 ss << " {\n";
495 }
496}
497
498void SlidingFunctionBase::GenerateFunctionDeclaration( const std::string& sSymName,
499 SubArguments& vSubArguments, outputstream& ss )
500{
501 ss << "\ndouble " << sSymName;
502 ss << "_"<< BinFuncName() <<"(";
503 for (size_t i = 0; i < vSubArguments.size(); i++)
504 {
505 if (i)
506 ss << ", ";
507 vSubArguments[i]->GenSlidingWindowDecl(ss);
508 }
509 ss << ")\n";
510}
511
513 outputstream& ss, const std::string& sSymName, SubArguments& vSubArguments )
514{
515 GenerateFunctionDeclaration( sSymName, vSubArguments, ss );
516 ss << "{\n\t";
517 ss << "double tmp = " << GetBottom() << ";\n\t";
518 ss << "int gid0 = get_global_id(0);\n\t";
519 ss << "tmp = ";
520 std::vector<std::string> argVector;
521 for (size_t i = 0; i < vSubArguments.size(); i++)
522 argVector.push_back(vSubArguments[i]->GenSlidingWindowDeclRef());
523 ss << Gen(argVector);
524 ss << ";\n\t";
525 ss << "return tmp;\n";
526 ss << "}";
527}
528
530 outputstream& ss, const SubArguments& vSubArguments )
531{
532 for (size_t i = 0; i < vSubArguments.size(); i++)
533 {
534 ss << " double tmp";
535 ss << i;
536 ss << ";\n";
537 }
538}
539
541 SubArguments& vSubArguments, int argumentNum )
542{
543 int i = argumentNum;
544 if (vSubArguments[i]->GetFormulaToken()->GetType() ==
546 {
547 const formula::SingleVectorRefToken* pTmpDVR1 =
548 static_cast<const formula::SingleVectorRefToken*>(vSubArguments[i]->GetFormulaToken());
549 ss << " if(singleIndex>=";
550 ss << pTmpDVR1->GetArrayLength();
551 ss << " ||";
552 ss << "isnan(";
553 ss << vSubArguments[i]->GenSlidingWindowDeclRef(true);
554 ss << "))\n";
555 ss << " tmp";
556 ss << i;
557 ss << "=0;\n else \n";
558 ss << " tmp";
559 ss << i;
560 ss << "=";
561 ss << vSubArguments[i]->GenSlidingWindowDeclRef(true);
562 ss << ";\n";
563 }
564 if (vSubArguments[i]->GetFormulaToken()->GetType() ==
566 {
567 const formula::DoubleVectorRefToken* pTmpDVR2 =
568 static_cast<const formula::DoubleVectorRefToken*>(vSubArguments[i]->GetFormulaToken());
569 ss << " if(doubleIndex>=";
570 ss << pTmpDVR2->GetArrayLength();
571 ss << " ||";
572 ss << "isnan(";
573 ss << vSubArguments[i]->GenSlidingWindowDeclRef();
574 ss << "))\n";
575 ss << " tmp";
576 ss << i;
577 ss << "=0;\n else \n";
578 ss << " tmp";
579 ss << i;
580 ss << "=";
581 ss << vSubArguments[i]->GenSlidingWindowDeclRef();
582 ss << ";\n";
583 }
584 if (vSubArguments[i]->GetFormulaToken()->GetType() == formula::svDouble ||
585 vSubArguments[i]->GetFormulaToken()->GetOpCode() != ocPush)
586 {
587 ss << " if(";
588 ss << "isnan(";
589 ss << vSubArguments[i]->GenSlidingWindowDeclRef();
590 ss << "))\n";
591 ss << " tmp";
592 ss << i;
593 ss << "=0;\n else \n";
594 ss << " tmp";
595 ss << i;
596 ss << "=";
597 ss << vSubArguments[i]->GenSlidingWindowDeclRef();
598 ss << ";\n";
599
600 }
601
602}
603
605 SubArguments& vSubArguments, int argumentNum, const std::string& p )
606{
607 int i = argumentNum;
608 if (vSubArguments[i]->GetFormulaToken()->GetType() == formula::svDouble)
609 {
610 ss << " tmp";
611 ss << i;
612 ss << "=";
613 vSubArguments[i]->GenDeclRef(ss);
614 ss << ";\n";
615 return;
616 }
617
618 ss << " tmp";
619 ss << i;
620 ss << "= fsum(";
621 vSubArguments[i]->GenDeclRef(ss);
622 if (vSubArguments[i]->GetFormulaToken()->GetType() ==
624 ss << "[" << p.c_str() << "]";
625 else if (vSubArguments[i]->GetFormulaToken()->GetType() ==
627 ss << "[get_group_id(1)]";
628 ss << ", 0);\n";
629}
630
632 outputstream& ss, SubArguments& vSubArguments )
633{
634 ss << " int k = gid0;\n";
635 for (size_t i = 0; i < vSubArguments.size(); i++)
636 {
637 CheckSubArgumentIsNan(ss, vSubArguments, i);
638 }
639}
640
642 const outputstream& unrollstr, const formula::DoubleVectorRefToken* pCurDVR,
643 int nCurWindowSize )
644{
645 int unrollSize = 16;
646 if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed())
647 {
648 ss << " loop = (" << nCurWindowSize << " - gid0)/";
649 ss << unrollSize << ";\n";
650 }
651 else if (pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
652 {
653 ss << " loop = (" << nCurWindowSize << " + gid0)/";
654 ss << unrollSize << ";\n";
655
656 }
657 else
658 {
659 ss << " loop = " << nCurWindowSize << "/" << unrollSize << ";\n";
660 }
661
662 ss << " for ( int j = 0;j< loop; j++)\n";
663 ss << " {\n";
664 ss << " int i = ";
665 if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed())
666 {
667 ss << "gid0 + j * " << unrollSize << ";\n";
668 }
669 else
670 {
671 ss << "j * " << unrollSize << ";\n";
672 }
673
674 if (!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
675 {
676 ss << " int doubleIndex = i+gid0;\n";
677 }
678 else
679 {
680 ss << " int doubleIndex = i;\n";
681 }
682
683 for (int j = 0; j < unrollSize; j++)
684 {
685 ss << unrollstr.str();
686 ss << "i++;\n";
687 ss << "doubleIndex++;\n";
688 }
689 ss << " }\n";
690 ss << " for (int i = ";
691 if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed())
692 {
693 ss << "gid0 + loop *" << unrollSize << "; i < ";
694 ss << nCurWindowSize << "; i++)\n";
695 }
696 else if (pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
697 {
698 ss << "0 + loop *" << unrollSize << "; i < gid0+";
699 ss << nCurWindowSize << "; i++)\n";
700 }
701 else
702 {
703 ss << "0 + loop *" << unrollSize << "; i < ";
704 ss << nCurWindowSize << "; i++)\n";
705 }
706 ss << " {\n";
707 if (!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
708 {
709 ss << " int doubleIndex = i+gid0;\n";
710 }
711 else
712 {
713 ss << " int doubleIndex = i;\n";
714 }
715 ss << unrollstr.str();
716 ss << " }\n";
717}
718
720 const std::string& sSymName, SubArguments& vSubArguments )
721{
722 GenerateFunctionDeclaration( sSymName, vSubArguments, ss );
723 ss << "{\n";
724 ss << "double tmp = " << GetBottom() << ";\n";
725 ss << "int gid0 = get_global_id(0);\n";
726 if (isAverage() || isMinOrMax())
727 ss << "int nCount = 0;\n";
728 ss << "double tmpBottom;\n";
729 unsigned i = vSubArguments.size();
730 while (i--)
731 {
732 if (NumericRange* NR = dynamic_cast<NumericRange*>(vSubArguments[i].get()))
733 {
734 bool needBody;
735 NR->GenReductionLoopHeader(ss, needBody);
736 if (!needBody)
737 continue;
738 }
739 else if (NumericRangeStringsToZero* NRS = dynamic_cast<NumericRangeStringsToZero*>(vSubArguments[i].get()))
740 {
741 bool needBody;
742 NRS->GenReductionLoopHeader(ss, needBody);
743 if (!needBody)
744 continue;
745 }
746 else if (ParallelNumericRange* PNR = dynamic_cast<ParallelNumericRange*>(vSubArguments[i].get()))
747 {
748 //did not handle yet
749 bool bNeedBody = false;
750 PNR->GenReductionLoopHeader(ss, mnResultSize, bNeedBody);
751 if (!bNeedBody)
752 continue;
753 }
754 else if (StringRange* SR = dynamic_cast<StringRange*>(vSubArguments[i].get()))
755 {
756 //did not handle yet
757 bool needBody;
758 SR->GenReductionLoopHeader(ss, needBody);
759 if (!needBody)
760 continue;
761 }
762 else
763 {
764 FormulaToken* pCur = vSubArguments[i]->GetFormulaToken();
765 if( pCur == nullptr || pCur->GetType() == formula::svDoubleVectorRef )
766 {
767 throw Unhandled(__FILE__, __LINE__);
768 }
769 ss << "{\n";
770 }
771 if (ocPush == vSubArguments[i]->GetFormulaToken()->GetOpCode())
772 {
773 bool bNanHandled = HandleNaNArgument(ss, i, vSubArguments);
774
775 ss << " tmpBottom = " << GetBottom() << ";\n";
776
777 if (!bNanHandled)
778 {
779 ss << " if (isnan(";
780 ss << vSubArguments[i]->GenSlidingWindowDeclRef();
781 ss << "))\n";
782 if (ZeroReturnZero())
783 ss << " return 0;\n";
784 else
785 {
786 ss << " tmp = ";
787 ss << Gen2("tmpBottom", "tmp") << ";\n";
788 }
789 ss << " else\n";
790 }
791 ss << " tmp = ";
792 ss << Gen2(vSubArguments[i]->GenSlidingWindowDeclRef(), "tmp");
793 ss << ";\n";
794 }
795 else
796 {
797 ss << " tmp = ";
798 ss << Gen2(vSubArguments[i]->GenSlidingWindowDeclRef(), "tmp");
799 ss << ";\n";
800 }
801 ss << "}\n";
802 }
803 if (isAverage())
804 ss <<
805 "if (nCount==0)\n"
806 " return CreateDoubleError(DivisionByZero);\n";
807 else if (isMinOrMax())
808 ss <<
809 "if (nCount==0)\n"
810 " return 0;\n";
811 ss << "return tmp";
812 if (isAverage())
813 ss << "/(double)nCount";
814 ss << ";\n}";
815}
816
817}
818
819/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
int mnIndex
OpCode GetOpCode() const
StackVar GetType() const
virtual double GetDouble() const
static void CheckSubArgumentIsNan2(outputstream &ss, SubArguments &vSubArguments, int argumentNum, const std::string &p)
Definition: opbase.cxx:604
static void CheckSubArgumentIsNan(outputstream &ss, SubArguments &vSubArguments, int argumentNum)
Definition: opbase.cxx:540
static void GenTmpVariables(outputstream &ss, const SubArguments &vSubArguments)
Definition: opbase.cxx:529
static void UnrollDoubleVector(outputstream &ss, const outputstream &unrollstr, const formula::DoubleVectorRefToken *pCurDVR, int nCurWindowSize)
Definition: opbase.cxx:641
static void CheckAllSubArgumentIsNan(outputstream &ss, SubArguments &vSubArguments)
Definition: opbase.cxx:631
(Partially) abstract base class for an operand
Definition: opbase.hxx:125
virtual std::string GenStringSlidingWindowDeclRef(bool=false) const
When Mix, it will be called.
Definition: opbase.cxx:51
virtual void DumpInlineFun(std::set< std::string > &, std::set< std::string > &) const
Definition: opbase.cxx:74
virtual std::string DumpOpName() const
Definition: opbase.cxx:69
formula::FormulaToken * GetFormulaToken() const
Definition: opbase.cxx:64
virtual bool NeedParallelReduction() const
Definition: opbase.cxx:81
virtual void GenDeclRef(outputstream &ss) const
Generate use/references to the argument.
Definition: opbase.cxx:57
const std::string & GetName() const
Definition: opbase.cxx:76
virtual void GenSlidingWindowFunction(outputstream &)
Definition: opbase.cxx:62
DynamicKernelArgument(const DynamicKernelArgument &)=delete
delete copy constructor
FormulaTreeNodeRef mFormulaTree
Definition: opbase.hxx:171
virtual std::string GenDoubleSlidingWindowDeclRef(bool=false) const
When Mix, it will be called.
Definition: opbase.cxx:45
Handling a Double Vector that is used as a sliding window input to either a sliding window average or...
Definition: opbase.hxx:426
InvalidParameterCount(int parameterCount, std::string file, int ln)
Definition: opbase.cxx:38
virtual void GenSlidingWindowFunction(outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments) override
Definition: opbase.cxx:512
virtual std::string GetBottom()
Definition: opbase.hxx:318
virtual bool ZeroReturnZero()
Definition: opbase.hxx:331
virtual std::string Gen2(const std::string &, const std::string &) const
Definition: opbase.hxx:319
static std::string Gen(std::vector< std::string > &)
Definition: opbase.hxx:321
virtual std::string BinFuncName() const
Definition: opbase.hxx:322
OpenCLError(std::string function, cl_int error, std::string file, int line)
Definition: opbase.cxx:25
Handling a Double Vector that is used as a sliding window input Performs parallel reduction based on ...
Definition: opbase.hxx:458
int const mnResultSize
Definition: opbase.hxx:487
virtual bool isMinOrMax() const
Definition: opbase.hxx:504
virtual void GenSlidingWindowFunction(outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments) override
Definition: opbase.cxx:719
virtual bool isAverage() const
Definition: opbase.hxx:503
virtual bool HandleNaNArgument(outputstream &, unsigned, SubArguments &) const
Definition: opbase.hxx:496
static void GenerateArg(const char *name, int arg, SubArguments &vSubArguments, outputstream &ss, EmptyArgType empty=EmptyIsZero)
Definition: opbase.cxx:184
static void GenerateDoubleVectorLoopHeader(outputstream &ss, const formula::DoubleVectorRefToken *pDVR, const char *firstElementDiff)
Definition: opbase.cxx:465
static void GenerateRangeArgElement(const char *name, int arg, const char *element, SubArguments &vSubArguments, outputstream &ss, EmptyArgType empty)
Definition: opbase.cxx:430
static void GenerateRangeArg(int arg, SubArguments &vSubArguments, outputstream &ss, EmptyArgType empty, const char *code)
Definition: opbase.cxx:349
static void GenerateArgWithDefault(const char *name, int arg, double def, SubArguments &vSubArguments, outputstream &ss, EmptyArgType empty=EmptyIsZero)
Definition: opbase.cxx:239
void GenerateFunctionDeclaration(const std::string &sSymName, SubArguments &vSubArguments, outputstream &ss)
Definition: opbase.cxx:498
static void GenerateRangeArgPair(int arg1, int arg2, SubArguments &vSubArguments, outputstream &ss, EmptyArgType empty, const char *code, const char *firstElementDiff=nullptr)
Definition: opbase.cxx:355
static void GenerateRangeArgs(int firstArg, int lastArg, SubArguments &vSubArguments, outputstream &ss, EmptyArgType empty, const char *code)
Definition: opbase.cxx:248
std::vector< DynamicKernelArgumentRef > SubArguments
Definition: opbase.hxx:340
UnhandledToken(const char *m, std::string fn, int ln)
Definition: opbase.cxx:21
Inconsistent state.
Definition: opbase.hxx:65
Unhandled(std::string fn, int ln)
Definition: opbase.cxx:35
VectorRefStringsToZero(const ScCalcConfig &config, const std::string &s, const FormulaTreeNodeRef &ft, int index=0)
Definition: opbase.cxx:177
Holds an input (read-only) argument reference to a SingleVectorRef.
Definition: opbase.hxx:182
VectorRef(const ScCalcConfig &config, const std::string &s, const FormulaTreeNodeRef &ft, int index=0)
Definition: opbase.cxx:86
virtual bool NeedParallelReduction() const override
Definition: opbase.cxx:172
virtual void GenSlidingWindowDecl(outputstream &ss) const override
When declared as input to a sliding window function.
Definition: opbase.cxx:114
virtual std::string GenSlidingWindowDeclRef(bool=false) const override
When referenced in a sliding window function.
Definition: opbase.cxx:120
virtual void GenDecl(outputstream &ss) const override
Generate declaration.
Definition: opbase.cxx:108
const std::string & GetName() const
Definition: opbase.cxx:162
virtual void DumpInlineFun(std::set< std::string > &, std::set< std::string > &) const override
Definition: opbase.cxx:160
cl_mem GetCLBuffer() const
Definition: opbase.cxx:167
virtual std::string DumpOpName() const override
Definition: opbase.cxx:155
virtual size_t GetWindowSize() const override
Definition: opbase.cxx:135
virtual ~VectorRef() override
Definition: opbase.cxx:97
virtual void GenSlidingWindowFunction(outputstream &) override
Definition: opbase.cxx:133
ScCalcConfig mCalcConfig
const char * name
const sal_uInt16 idx[]
void * p
#define SAL_WARN_IF(condition, area, stream)
err
config
int i
line
index
m
const char * errorString(cl_int nError)
Arguments that are actually compile-time constant string Currently, only the hash is passed.
std::shared_ptr< FormulaTreeNode > FormulaTreeNodeRef
Definition: opbase.hxx:104
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
sal_Unicode code
ocPush
Configuration options for formula interpreter.
Definition: calcconfig.hxx:44