summaryrefslogtreecommitdiff
path: root/sc/inc/scmatrix.hxx
blob: d057437106425e5921a2c5bf11849250e7a13e9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_SC_INC_SCMATRIX_HXX
#define INCLUDED_SC_INC_SCMATRIX_HXX

#include "global.hxx"
#include "matrixoperators.hxx"
#include "types.hxx"
#include <formula/errorcodes.hxx>
#include "scdllapi.h"
#include <rtl/ustring.hxx>
#include <svl/sharedstring.hxx>

#include <functional>
#include <memory>
#include <utility>
#include <vector>
#include <boost/intrusive_ptr.hpp>

#define DEBUG_MATRIX 0

class ScInterpreter;
class SvNumberFormatter;
class ScMatrixImpl;

namespace formula { class DoubleVectorRefToken; }

namespace sc {

struct Compare;
struct CompareOptions;

}

/**
 * Try NOT to use this struct.  This struct should go away in a hopefully
 * not so distant future.
 */
struct ScMatrixValue
{
    double fVal;
    svl::SharedString aStr;
    ScMatValType nType;

    /// Only valid if ScMatrix methods indicate so!
    svl::SharedString GetString() const { return aStr; }

    /// Only valid if ScMatrix methods indicate that this is no string!
    sal_uInt16 GetError() const         { return GetDoubleErrorValue( fVal); }

    /// Only valid if ScMatrix methods indicate that this is a boolean
    bool GetBoolean() const         { return fVal != 0.0; }

    ScMatrixValue() : fVal(0.0), nType(SC_MATVAL_EMPTY) {}

    ScMatrixValue(const ScMatrixValue& r) :
        fVal(r.fVal), aStr(r.aStr), nType(r.nType) {}

    bool operator== (const ScMatrixValue& r) const
    {
        if (nType != r.nType)
            return false;

        switch (nType)
        {
            case SC_MATVAL_VALUE:
            case SC_MATVAL_BOOLEAN:
                return fVal == r.fVal;
            break;
            default:
                ;
        }

        return aStr == r.aStr;
    }

    bool operator!= (const ScMatrixValue& r) const
    {
        return !operator==(r);
    }

    ScMatrixValue& operator= (const ScMatrixValue& r)
    {
        if (this == &r)
            return *this;

        nType = r.nType;
        fVal = r.fVal;
        aStr = r.aStr;
        return *this;
    }
};

/// Abstract base class for ScFullMatrix and ScVectorRefMatrix implementations.
class SC_DLLPUBLIC ScMatrix
{
    mutable size_t  nRefCnt;    // reference count
    bool            mbCloneIfConst; // Whether the matrix is cloned with a CloneIfConst() call.

    ScMatrix( const ScMatrix& ) = delete;
    ScMatrix& operator=( const ScMatrix&) = delete;

protected:
    virtual ~ScMatrix() {}

public:
    enum Op { Add, Sub, Mul, Div };

    /**
     * When adding all numerical matrix elements for a scalar result such as
     * summation, the interpreter wants to separate the first non-zero value
     * with the rest of the summed values.
     *
     * TODO: Find out if we still need to do this.  If not, we can re-write
     * ScInterpreter::IterateParameters() to make it simpler and remove this
     * struct.
     */
    struct IterateResult
    {
        double mfFirst;
        double mfRest;
        size_t mnCount;

        IterateResult(double fFirst, double fRest, size_t nCount) :
            mfFirst(fFirst), mfRest(fRest), mnCount(nCount) {}

        IterateResult(const IterateResult& r) :
            mfFirst(r.mfFirst), mfRest(r.mfRest), mnCount(r.mnCount) {}
    };

    /// The maximum number of elements a matrix may have at runtime.
    inline static size_t GetElementsMax()
    {
        // TODO: Fix me.
        return 0x08000000;
#if 0
        // Roughly 125MB in total, divided by 8+1 per element => 14M elements.
        const size_t nMemMax = 0x08000000 / (sizeof(ScMatrixValue) + sizeof(ScMatValType));
        // With MAXROWCOUNT==65536 and 128 columns => 8M elements ~72MB.
        const size_t nArbitraryLimit = (size_t)MAXROWCOUNT * 128;
        // Stuffed with a million rows would limit this to 14 columns.
        return nMemMax < nArbitraryLimit ? nMemMax : nArbitraryLimit;
#endif
    }

    /** Checks nC or nR for zero and uses GetElementsMax() whether a matrix of
        the size of nC*nR could be allocated. A zero size (both nC and nR zero)
        matrix is allowed for later resize.
     */
    bool static IsSizeAllocatable( SCSIZE nC, SCSIZE nR );

    /// Value or boolean.
    inline static bool IsValueType( ScMatValType nType )
    {
        return nType <= SC_MATVAL_BOOLEAN;
    }

    /// Boolean.
    inline static bool IsBooleanType( ScMatValType nType )
    {
        return nType == SC_MATVAL_BOOLEAN;
    }

    /// String, empty or empty path, but not value nor boolean.
    inline static bool IsNonValueType( ScMatValType nType )
    {
        return (nType & SC_MATVAL_NONVALUE) != 0;
    }

    /** String, but not empty or empty path or any other type.
        Not named IsStringType to prevent confusion because previously
        IsNonValueType was named IsStringType. */
    inline static bool IsRealStringType( ScMatValType nType )
    {
        return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_STRING;
    }

    /// Empty, but not empty path or any other type.
    inline static bool IsEmptyType( ScMatValType nType )
    {
        return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTY;
    }

    /// Empty path, but not empty or any other type.
    inline static bool IsEmptyPathType( ScMatValType nType )
    {
        return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTYPATH;
    }

    ScMatrix() : nRefCnt(0), mbCloneIfConst(true) {}

    /** Clone the matrix. */
    virtual ScMatrix* Clone() const = 0;

    /** Clone the matrix if mbCloneIfConst (immutable) is set, otherwise
        return _this_ matrix, to be assigned to a ScMatrixRef. */
    ScMatrix* CloneIfConst();

    /** Set the matrix to (im)mutable for CloneIfConst(), only the interpreter
        should do this and know the consequences. */
    void SetImmutable( bool bVal );

    /**
     * Resize the matrix to specified new dimension.
     */
    virtual void Resize(SCSIZE nC, SCSIZE nR) = 0;

    virtual void Resize(SCSIZE nC, SCSIZE nR, double fVal) = 0;

    /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
        MUST be at least of the size of the original matrix. */
    virtual ScMatrix* CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const = 0;

    void IncRef() const;
    void DecRef() const;

    virtual void SetErrorInterpreter( ScInterpreter* p) = 0;
    virtual void GetDimensions( SCSIZE& rC, SCSIZE& rR) const = 0;
    virtual SCSIZE GetElementCount() const = 0;
    virtual bool ValidColRow( SCSIZE nC, SCSIZE nR) const = 0;

    /** For a row vector or column vector, if the position does not point into
        the vector but is a valid column or row offset it is adapted such that
        it points to an element to be replicated, same column row 0 for a row
        vector, same row column 0 for a column vector. Else, for a 2D matrix,
        returns false.
     */
    virtual bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const = 0;

    /** Checks if the matrix position is within the matrix. If it is not, for a
        row vector or column vector the position is adapted such that it points
        to an element to be replicated, same column row 0 for a row vector,
        same row column 0 for a column vector. Else, for a 2D matrix and
        position not within matrix, returns false.
     */
    virtual bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const = 0;

    virtual void PutDouble( double fVal, SCSIZE nC, SCSIZE nR) = 0;
    virtual void PutDouble( double fVal, SCSIZE nIndex) = 0;
    virtual void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) = 0;

    virtual void PutString( const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR) = 0;
    virtual void PutString( const svl::SharedString& rStr, SCSIZE nIndex) = 0;
    virtual void PutString( const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) = 0;

    virtual void PutEmpty( SCSIZE nC, SCSIZE nR) = 0;

    /// Jump sal_False without path
    virtual void PutEmptyPath( SCSIZE nC, SCSIZE nR) = 0;
    virtual void PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR ) = 0;
    virtual void PutBoolean( bool bVal, SCSIZE nC, SCSIZE nR) = 0;

    virtual void FillDouble( double fVal,
            SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 ) = 0;

    /** Put a column vector of doubles, starting at row nR, must fit into dimensions. */
    virtual void PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR ) = 0;

    /** Put a column vector of strings, starting at row nR, must fit into dimensions. */
    virtual void PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR ) = 0;

    /** Put a column vector of empties, starting at row nR, must fit into dimensions. */
    virtual void PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) = 0;

    /** Put a column vector of empty results, starting at row nR, must fit into dimensions. */
    virtual void PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) = 0;

    /** Put a column vector of empty paths, starting at row nR, must fit into dimensions. */
    virtual void PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) = 0;

    /** May be used before obtaining the double value of an element to avoid
        passing its NAN around.
        @ATTENTION: MUST NOT be used if the element is a string!
                    Use GetErrorIfNotString() instead if not sure.
        @returns 0 if no error, else one of err... constants */
    virtual sal_uInt16 GetError( SCSIZE nC, SCSIZE nR) const = 0;

    /** Use in ScInterpreter to obtain the error code, if any.
        @returns 0 if no error or string element, else one of err... constants */
    sal_uInt16 GetErrorIfNotString( SCSIZE nC, SCSIZE nR) const
        { return IsValue( nC, nR) ? GetError( nC, nR) : 0; }

    /// @return 0.0 if empty or empty path, else value or DoubleError.
    virtual double GetDouble( SCSIZE nC, SCSIZE nR) const = 0;
    /// @return 0.0 if empty or empty path, else value or DoubleError.
    virtual double GetDouble( SCSIZE nIndex) const = 0;

    /// @return empty string if empty or empty path, else string content.
    virtual svl::SharedString GetString( SCSIZE nC, SCSIZE nR) const = 0;
    /// @return empty string if empty or empty path, else string content.
    virtual svl::SharedString GetString( SCSIZE nIndex) const = 0;

    /** @returns the matrix element's string if one is present, otherwise the
        numerical value formatted as string, or in case of an error the error
        string is returned; an empty string for empty, a "FALSE" string for
        empty path. */
    virtual svl::SharedString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const = 0;

    /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
    /// an empty string!
    virtual ScMatrixValue Get( SCSIZE nC, SCSIZE nR) const = 0;

    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
    virtual bool IsString( SCSIZE nIndex ) const = 0;

    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
    virtual bool IsString( SCSIZE nC, SCSIZE nR ) const = 0;

    /// @return <TRUE/> if empty or empty cell or empty result, not empty path.
    virtual bool IsEmpty( SCSIZE nC, SCSIZE nR ) const = 0;

    /// @return <TRUE/> if empty cell, not empty or empty result or empty path.
    virtual bool IsEmptyCell( SCSIZE nC, SCSIZE nR ) const = 0;

    /// @return <TRUE/> if empty result, not empty or empty cell or empty path.
    virtual bool IsEmptyResult( SCSIZE nC, SCSIZE nR ) const = 0;

    /// @return <TRUE/> if empty path, not empty or empty cell or empty result.
    virtual bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const = 0;

    /// @return <TRUE/> if value or boolean.
    virtual bool IsValue( SCSIZE nIndex ) const = 0;

    /// @return <TRUE/> if value or boolean.
    virtual bool IsValue( SCSIZE nC, SCSIZE nR ) const = 0;

    /// @return <TRUE/> if value or boolean or empty or empty path.
    virtual bool IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const = 0;

    /// @return <TRUE/> if boolean.
    virtual bool IsBoolean( SCSIZE nC, SCSIZE nR ) const = 0;

    /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
    virtual bool IsNumeric() const = 0;

    virtual void MatTrans( ScMatrix& mRes) const = 0;
    virtual void MatCopy ( ScMatrix& mRes) const = 0;

    // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
    virtual void CompareEqual() = 0;
    virtual void CompareNotEqual() = 0;
    virtual void CompareLess() = 0;
    virtual void CompareGreater() = 0;
    virtual void CompareLessEqual() = 0;
    virtual void CompareGreaterEqual() = 0;

    virtual double And() const = 0;       // logical AND of all matrix values, or NAN
    virtual double Or() const = 0;        // logical OR of all matrix values, or NAN
    virtual double Xor() const = 0;       // logical XOR of all matrix values, or NAN

    virtual IterateResult Sum(bool bTextAsZero) const = 0;
    virtual IterateResult SumSquare(bool bTextAsZero) const = 0;
    virtual IterateResult Product(bool bTextAsZero) const = 0;
    virtual size_t Count(bool bCountStrings) const = 0;
    virtual size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const = 0;
    virtual size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const = 0;

    virtual double GetMaxValue( bool bTextAsZero ) const = 0;
    virtual double GetMinValue( bool bTextAsZero ) const = 0;

    virtual ScMatrixRef CompareMatrix(
        sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions = nullptr ) const = 0;

    /**
     * Convert the content of matrix into a linear array of numeric values.
     * String elements are mapped to NaN's and empty elements are mapped to
     * either NaN or zero values.
     *
     * @param bEmptyAsZero if true empty elements are mapped to zero values,
     *                     otherwise they become NaN values.
     */
    virtual void GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero = true ) const = 0;
    virtual void MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const = 0;

    virtual void NotOp(ScMatrix& rMat) = 0;
    virtual void NegOp(ScMatrix& rMat) = 0;
    virtual void AddOp(double fVal, ScMatrix& rMat) = 0;
    virtual void SubOp(bool bFlag, double fVal, ScMatrix& rMat) = 0;
    virtual void MulOp(double fVal, ScMatrix& rMat) = 0;
    virtual void DivOp(bool bFlag, double fVal, ScMatrix& rMat) = 0;
    virtual void PowOp(bool bFlag, double fVal, ScMatrix& rMat) = 0;

    virtual std::vector<ScMatrix::IterateResult> Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp) = 0;

#if DEBUG_MATRIX
    void Dump() const;
#endif
};

/**
 * Matrix data type that can store values of mixed types.  Each element can
 * be one of the following types: numeric, string, boolean, empty, and empty
 * path.
 */
class SC_DLLPUBLIC ScFullMatrix : public ScMatrix
{
    friend class ScMatrixImpl;

    std::unique_ptr<ScMatrixImpl> pImpl;

    ScFullMatrix( const ScFullMatrix& ) = delete;
    ScFullMatrix& operator=( const ScFullMatrix&) = delete;

public:

    ScFullMatrix(SCSIZE nC, SCSIZE nR);
    ScFullMatrix(SCSIZE nC, SCSIZE nR, double fInitVal);

    ScFullMatrix( size_t nC, size_t nR, const std::vector<double>& rInitVals );

    virtual ~ScFullMatrix();

    /** Clone the matrix. */
    virtual ScMatrix* Clone() const override;

    /**
     * Resize the matrix to specified new dimension.
     */
    virtual void Resize( SCSIZE nC, SCSIZE nR) override;

    virtual void Resize(SCSIZE nC, SCSIZE nR, double fVal) override;

    /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
        MUST be at least of the size of the original matrix. */
    virtual ScMatrix* CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const override;

    virtual void SetErrorInterpreter( ScInterpreter* p) override;
    virtual void GetDimensions( SCSIZE& rC, SCSIZE& rR) const override;
    virtual SCSIZE GetElementCount() const override;
    virtual bool ValidColRow( SCSIZE nC, SCSIZE nR) const override;

    /** For a row vector or column vector, if the position does not point into
        the vector but is a valid column or row offset it is adapted such that
        it points to an element to be replicated, same column row 0 for a row
        vector, same row column 0 for a column vector. Else, for a 2D matrix,
        returns false.
     */
    virtual bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const override;

    /** Checks if the matrix position is within the matrix. If it is not, for a
        row vector or column vector the position is adapted such that it points
        to an element to be replicated, same column row 0 for a row vector,
        same row column 0 for a column vector. Else, for a 2D matrix and
        position not within matrix, returns false.
     */
    virtual bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const override;

    virtual void PutDouble( double fVal, SCSIZE nC, SCSIZE nR) override;
    virtual void PutDouble( double fVal, SCSIZE nIndex) override;
    virtual void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) override;

    virtual void PutString( const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR) override;
    virtual void PutString( const svl::SharedString& rStr, SCSIZE nIndex) override;
    virtual void PutString( const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) override;

    virtual void PutEmpty( SCSIZE nC, SCSIZE nR) override;

    /// Jump sal_False without path
    virtual void PutEmptyPath( SCSIZE nC, SCSIZE nR) override;
    virtual void PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR ) override;
    virtual void PutBoolean( bool bVal, SCSIZE nC, SCSIZE nR) override;

    virtual void FillDouble( double fVal,
            SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 ) override;

    /** Put a column vector of doubles, starting at row nR, must fit into dimensions. */
    virtual void PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR ) override;

    /** Put a column vector of strings, starting at row nR, must fit into dimensions. */
    virtual void PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR ) override;

    /** Put a column vector of empties, starting at row nR, must fit into dimensions. */
    virtual void PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) override;

    /** Put a column vector of empty results, starting at row nR, must fit into dimensions. */
    virtual void PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) override;

    /** Put a column vector of empty paths, starting at row nR, must fit into dimensions. */
    virtual void PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) override;

    /** May be used before obtaining the double value of an element to avoid
        passing its NAN around.
        @ATTENTION: MUST NOT be used if the element is a string!
                    Use GetErrorIfNotString() instead if not sure.
        @returns 0 if no error, else one of err... constants */
    virtual sal_uInt16 GetError( SCSIZE nC, SCSIZE nR) const override;

    /// @return 0.0 if empty or empty path, else value or DoubleError.
    virtual double GetDouble( SCSIZE nC, SCSIZE nR) const override;
    /// @return 0.0 if empty or empty path, else value or DoubleError.
    virtual double GetDouble( SCSIZE nIndex) const override;

    /// @return empty string if empty or empty path, else string content.
    virtual svl::SharedString GetString( SCSIZE nC, SCSIZE nR) const override;
    /// @return empty string if empty or empty path, else string content.
    virtual svl::SharedString GetString( SCSIZE nIndex) const override;

    /** @returns the matrix element's string if one is present, otherwise the
        numerical value formatted as string, or in case of an error the error
        string is returned; an empty string for empty, a "FALSE" string for
        empty path. */
    virtual svl::SharedString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const override;

    /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
    /// an empty string!
    virtual ScMatrixValue Get( SCSIZE nC, SCSIZE nR) const override;

    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
    virtual bool IsString( SCSIZE nIndex ) const override;

    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
    virtual bool IsString( SCSIZE nC, SCSIZE nR ) const override;

    /// @return <TRUE/> if empty or empty cell or empty result, not empty path.
    virtual bool IsEmpty( SCSIZE nC, SCSIZE nR ) const override;

    /// @return <TRUE/> if empty cell, not empty or empty result or empty path.
    virtual bool IsEmptyCell( SCSIZE nC, SCSIZE nR ) const override;

    /// @return <TRUE/> if empty result, not empty or empty cell or empty path.
    virtual bool IsEmptyResult( SCSIZE nC, SCSIZE nR ) const override;

    /// @return <TRUE/> if empty path, not empty or empty cell or empty result.
    virtual bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const override;

    /// @return <TRUE/> if value or boolean.
    virtual bool IsValue( SCSIZE nIndex ) const override;

    /// @return <TRUE/> if value or boolean.
    virtual bool IsValue( SCSIZE nC, SCSIZE nR ) const override;

    /// @return <TRUE/> if value or boolean or empty or empty path.
    virtual bool IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const override;

    /// @return <TRUE/> if boolean.
    virtual bool IsBoolean( SCSIZE nC, SCSIZE nR ) const override;

    /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
    virtual bool IsNumeric() const override;

    virtual void MatTrans( ScMatrix& mRes) const override;
    virtual void MatCopy ( ScMatrix& mRes) const override;

    // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
    virtual void CompareEqual() override;
    virtual void CompareNotEqual() override;
    virtual void CompareLess() override;
    virtual void CompareGreater() override;
    virtual void CompareLessEqual() override;
    virtual void CompareGreaterEqual() override;

    virtual double And() const override;       // logical AND of all matrix values, or NAN
    virtual double Or() const override;        // logical OR of all matrix values, or NAN
    virtual double Xor() const override;       // logical XOR of all matrix values, or NAN

    virtual IterateResult Sum(bool bTextAsZero) const override;
    virtual IterateResult SumSquare(bool bTextAsZero) const override;
    virtual IterateResult Product(bool bTextAsZero) const override;
    virtual size_t Count(bool bCountStrings) const override;
    virtual size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const override;
    virtual size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const override;

    virtual double GetMaxValue( bool bTextAsZero ) const override;
    virtual double GetMinValue( bool bTextAsZero ) const override;

    virtual ScMatrixRef CompareMatrix(
        sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions = nullptr ) const override;

    /**
     * Convert the content of matrix into a linear array of numeric values.
     * String elements are mapped to NaN's and empty elements are mapped to
     * either NaN or zero values.
     *
     * @param bEmptyAsZero if true empty elements are mapped to zero values,
     *                     otherwise they become NaN values.
     */
    virtual void GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero = true ) const override;
    virtual void MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const override;

    virtual void NotOp(ScMatrix& rMat) override;
    virtual void NegOp(ScMatrix& rMat) override;
    virtual void AddOp(double fVal, ScMatrix& rMat) override;
    virtual void SubOp(bool bFlag, double fVal, ScMatrix& rMat) override;
    virtual void MulOp(double fVal, ScMatrix& rMat) override;
    virtual void DivOp(bool bFlag, double fVal, ScMatrix& rMat) override;
    virtual void PowOp(bool bFlag, double fVal, ScMatrix& rMat) override;

    virtual std::vector<ScMatrix::IterateResult> Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp) override;

    ScFullMatrix& operator+= ( const ScFullMatrix& r );

#if DEBUG_MATRIX
    void Dump() const;
#endif
};

class SC_DLLPUBLIC ScVectorRefMatrix : public ScMatrix
{
    const formula::DoubleVectorRefToken* mpToken;
    ScInterpreter* mpErrorInterpreter;

    /// For the operations that are not fully implemented, create a ScFullMatrix, and operate on it.
    std::unique_ptr<ScFullMatrix> mpFullMatrix;

    SCSIZE mnRowStart;
    SCSIZE mnRowSize;

    ScVectorRefMatrix( const ScVectorRefMatrix& ) = delete;
    ScVectorRefMatrix& operator=( const ScVectorRefMatrix&) = delete;

    /// For the operations that are not fully implemented, create a ScFullMatrix, and operate on it.
    ///
    /// Note: This is potentially an expensive operation.
    /// TODO: Implement as much as possible directly using the DoubleVectorRefToken.
    void ensureFullMatrix();

public:

    ScVectorRefMatrix(const formula::DoubleVectorRefToken* pToken, SCSIZE nRowStart, SCSIZE nRowSize);

    virtual ~ScVectorRefMatrix();

    /** Clone the matrix. */
    virtual ScMatrix* Clone() const override;

    /**
     * Resize the matrix to specified new dimension.
     */
    virtual void Resize(SCSIZE nC, SCSIZE nR) override;

    virtual void Resize(SCSIZE nC, SCSIZE nR, double fVal) override;

    /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
        MUST be at least of the size of the original matrix. */
    virtual ScMatrix* CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const override;

    virtual void SetErrorInterpreter(ScInterpreter* p) override;
    virtual void GetDimensions(SCSIZE& rC, SCSIZE& rR) const override;
    virtual SCSIZE GetElementCount() const override;
    virtual bool ValidColRow( SCSIZE nC, SCSIZE nR) const override;

    /** For a row vector or column vector, if the position does not point into
        the vector but is a valid column or row offset it is adapted such that
        it points to an element to be replicated, same column row 0 for a row
        vector, same row column 0 for a column vector. Else, for a 2D matrix,
        returns false.
     */
    virtual bool ValidColRowReplicated(SCSIZE & rC, SCSIZE & rR) const override;

    /** Checks if the matrix position is within the matrix. If it is not, for a
        row vector or column vector the position is adapted such that it points
        to an element to be replicated, same column row 0 for a row vector,
        same row column 0 for a column vector. Else, for a 2D matrix and
        position not within matrix, returns false.
     */
    virtual bool ValidColRowOrReplicated(SCSIZE & rC, SCSIZE & rR) const override;

    virtual void PutDouble(double fVal, SCSIZE nC, SCSIZE nR) override;
    virtual void PutDouble(double fVal, SCSIZE nIndex) override;
    virtual void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) override;

    virtual void PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR) override;
    virtual void PutString(const svl::SharedString& rStr, SCSIZE nIndex) override;
    virtual void PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) override;

    virtual void PutEmpty(SCSIZE nC, SCSIZE nR) override;

    /// Jump sal_False without path
    virtual void PutEmptyPath(SCSIZE nC, SCSIZE nR) override;
    virtual void PutError(sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR ) override;
    virtual void PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR) override;

    virtual void FillDouble(double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2) override;

    /** Put a column vector of doubles, starting at row nR, must fit into dimensions. */
    virtual void PutDoubleVector(const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR) override;

    /** Put a column vector of strings, starting at row nR, must fit into dimensions. */
    virtual void PutStringVector(const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR) override;

    /** Put a column vector of empties, starting at row nR, must fit into dimensions. */
    virtual void PutEmptyVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR) override;

    /** Put a column vector of empty results, starting at row nR, must fit into dimensions. */
    virtual void PutEmptyResultVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR) override;

    /** Put a column vector of empty paths, starting at row nR, must fit into dimensions. */
    virtual void PutEmptyPathVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR) override;

    /** May be used before obtaining the double value of an element to avoid
        passing its NAN around.
        @ATTENTION: MUST NOT be used if the element is a string!
                    Use GetErrorIfNotString() instead if not sure.
        @returns 0 if no error, else one of err... constants */
    virtual sal_uInt16 GetError(SCSIZE nC, SCSIZE nR) const override;

    /// @return 0.0 if empty or empty path, else value or DoubleError.
    virtual double GetDouble(SCSIZE nC, SCSIZE nR) const override;
    /// @return 0.0 if empty or empty path, else value or DoubleError.
    virtual double GetDouble(SCSIZE nIndex) const override;

    /// @return empty string if empty or empty path, else string content.
    virtual svl::SharedString GetString(SCSIZE nC, SCSIZE nR) const override;
    /// @return empty string if empty or empty path, else string content.
    virtual svl::SharedString GetString(SCSIZE nIndex) const override;

    /** @returns the matrix element's string if one is present, otherwise the
        numerical value formatted as string, or in case of an error the error
        string is returned; an empty string for empty, a "FALSE" string for
        empty path. */
    virtual svl::SharedString GetString(SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const override;

    /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
    /// an empty string!
    virtual ScMatrixValue Get(SCSIZE nC, SCSIZE nR) const override;

    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
    virtual bool IsString(SCSIZE nIndex) const override;

    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
    virtual bool IsString(SCSIZE nC, SCSIZE nR) const override;

    /// @return <TRUE/> if empty or empty cell or empty result, not empty path.
    virtual bool IsEmpty(SCSIZE nC, SCSIZE nR) const override;

    /// @return <TRUE/> if empty cell, not empty or empty result or empty path.
    virtual bool IsEmptyCell(SCSIZE nC, SCSIZE nR) const override;

    /// @return <TRUE/> if empty result, not empty or empty cell or empty path.
    virtual bool IsEmptyResult(SCSIZE nC, SCSIZE nR) const override;

    /// @return <TRUE/> if empty path, not empty or empty cell or empty result.
    virtual bool IsEmptyPath(SCSIZE nC, SCSIZE nR) const override;

    /// @return <TRUE/> if value or boolean.
    virtual bool IsValue(SCSIZE nIndex) const override;

    /// @return <TRUE/> if value or boolean.
    virtual bool IsValue(SCSIZE nC, SCSIZE nR) const override;

    /// @return <TRUE/> if value or boolean or empty or empty path.
    virtual bool IsValueOrEmpty(SCSIZE nC, SCSIZE nR) const override;

    /// @return <TRUE/> if boolean.
    virtual bool IsBoolean(SCSIZE nC, SCSIZE nR) const override;

    /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
    virtual bool IsNumeric() const override;

    virtual void MatTrans(ScMatrix& mRes) const override;
    virtual void MatCopy (ScMatrix& mRes) const override;

    // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
    virtual void CompareEqual() override;
    virtual void CompareNotEqual() override;
    virtual void CompareLess() override;
    virtual void CompareGreater() override;
    virtual void CompareLessEqual() override;
    virtual void CompareGreaterEqual() override;

    virtual double And() const override;       // logical AND of all matrix values, or NAN
    virtual double Or() const override;        // logical OR of all matrix values, or NAN
    virtual double Xor() const override;       // logical XOR of all matrix values, or NAN

    virtual IterateResult Sum(bool bTextAsZero) const override;
    virtual IterateResult SumSquare(bool bTextAsZero) const override;
    virtual IterateResult Product(bool bTextAsZero) const override;
    virtual size_t Count(bool bCountStrings) const override;
    virtual size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const override;
    virtual size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const override;

    virtual double GetMaxValue(bool bTextAsZero) const override;
    virtual double GetMinValue(bool bTextAsZero) const override;

    virtual ScMatrixRef CompareMatrix(sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions = nullptr) const override;

    /**
     * Convert the content of matrix into a linear array of numeric values.
     * String elements are mapped to NaN's and empty elements are mapped to
     * either NaN or zero values.
     *
     * @param bEmptyAsZero if true empty elements are mapped to zero values,
     *                     otherwise they become NaN values.
     */
    virtual void GetDoubleArray(std::vector<double>& rVector, bool bEmptyAsZero = true) const override;
    virtual void MergeDoubleArray(std::vector<double>& rVector, Op eOp) const override;

    virtual void NotOp(ScMatrix& rMat) override;
    virtual void NegOp(ScMatrix& rMat) override;
    virtual void AddOp(double fVal, ScMatrix& rMat) override;
    virtual void SubOp(bool bFlag, double fVal, ScMatrix& rMat) override;
    virtual void MulOp(double fVal, ScMatrix& rMat) override;
    virtual void DivOp(bool bFlag, double fVal, ScMatrix& rMat) override;
    virtual void PowOp(bool bFlag, double fVal, ScMatrix& rMat) override;

    virtual std::vector<ScMatrix::IterateResult> Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp) override;

    ScVectorRefMatrix& operator+=(const ScVectorRefMatrix& r);
};

inline void intrusive_ptr_add_ref(const ScMatrix* p)
{
    p->IncRef();
}

inline void intrusive_ptr_release(const ScMatrix* p)
{
    p->DecRef();
}

#endif // INCLUDED_SC_INC_SCMATRIX_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */