PageRenderTime 298ms CodeModel.GetById 90ms app.highlight 186ms RepoModel.GetById 1ms app.codeStats 2ms

/libreoffice-3.6.0.2/binfilter/bf_sc/source/core/tool/sc_interpr5.cxx

#
C++ | 4058 lines | 3932 code | 64 blank | 62 comment | 915 complexity | c9a4ec24175cae2fb65466adfd8f45bd MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
   2/*************************************************************************
   3 *
   4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5 *
   6 * Copyright 2000, 2010 Oracle and/or its affiliates.
   7 *
   8 * OpenOffice.org - a multi-platform office productivity suite
   9 *
  10 * This file is part of OpenOffice.org.
  11 *
  12 * OpenOffice.org is free software: you can redistribute it and/or modify
  13 * it under the terms of the GNU Lesser General Public License version 3
  14 * only, as published by the Free Software Foundation.
  15 *
  16 * OpenOffice.org is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU Lesser General Public License version 3 for more details
  20 * (a copy is included in the LICENSE file that accompanied this code).
  21 *
  22 * You should have received a copy of the GNU Lesser General Public License
  23 * version 3 along with OpenOffice.org.  If not, see
  24 * <http://www.openoffice.org/license.html>
  25 * for a copy of the LGPLv3 License.
  26 *
  27 ************************************************************************/
  28
  29#ifdef _MSC_VER
  30#pragma hdrstop
  31#endif
  32
  33#include <string.h>
  34
  35#include <bf_svtools/zforlist.hxx>
  36
  37#include "interpre.hxx"
  38#include "dociter.hxx"
  39#include "scmatrix.hxx"
  40#include "globstr.hrc"
  41namespace binfilter {
  42
  43// STATIC DATA -----------------------------------------------------------
  44
  45#define SCdEpsilon                1.0E-7
  46
  47
  48// -----------------------------------------------------------------------
  49
  50double ScInterpreter::ScGetGGT(double fx, double fy)
  51{
  52    if (fy == 0.0 || fx == 0.0)
  53    {
  54        SetError(errIllegalArgument);
  55        return 1.0;
  56    }
  57    else
  58    {
  59        double fz = fmod(fx, fy);
  60        while (fz > 0.0)
  61        {
  62            fx = fy;
  63            fy = fz;
  64            fz = fmod(fx, fy);
  65        }
  66        return fy;
  67    }
  68}
  69
  70void ScInterpreter::ScGGT()
  71{
  72    BYTE nParamCount = GetByte();
  73    if ( MustHaveParamCountMin( nParamCount, 1 ) )
  74    {
  75        double fSign = 1.0;
  76        double fx, fy = 0.0;
  77        switch (GetStackType())
  78        {
  79            case svDouble :
  80            case svString:
  81            case svSingleRef:
  82            {
  83                fy = GetDouble();
  84                if (fy < 0.0)
  85                {
  86                    fy *= -1.0;
  87                    fSign *= -1.0;
  88                }
  89            }
  90            break;
  91            case svDoubleRef :
  92            {
  93                ScRange aRange;
  94                USHORT nErr = 0;
  95                PopDoubleRef( aRange );
  96                double nCellVal;
  97                ScValueIterator aValIter(pDok, aRange, glSubTotal);
  98                if (aValIter.GetFirst(nCellVal, nErr))
  99                {
 100                    fy = nCellVal;
 101                    if (fy < 0.0)
 102                    {
 103                        fy *= -1.0;
 104                        fSign *= -1.0;
 105                    }
 106                    while (nErr == 0 && aValIter.GetNext(nCellVal, nErr))
 107                    {
 108                        fx = nCellVal;
 109                        if (fx < 0.0)
 110                        {
 111                            fx *= -1.0;
 112                            fSign *= -1.0;
 113                        }
 114                        fy = ScGetGGT(fx, fy);
 115                    }
 116                    SetError(nErr);
 117                }
 118                else
 119                    SetError(errIllegalArgument);
 120            }
 121            break;
 122            case svMatrix :
 123            {
 124                ScMatrix* pMat = PopMatrix();
 125                if (pMat)
 126                {
 127                    USHORT nC, nR;
 128                    pMat->GetDimensions(nC, nR);
 129                    if (nC == 0 || nR == 0)
 130                        SetError(errIllegalArgument);
 131                    else
 132                    {
 133                        if (!pMat->IsValue(0))
 134                        {
 135                            SetIllegalArgument();
 136                            return;
 137                        }
 138                        fy = pMat->GetDouble(0);
 139                        if (fy < 0.0)
 140                        {
 141                            fy *= -1.0;
 142                            fSign *= -1.0;
 143                        }
 144                        ULONG nCount = (ULONG) nC * nR;
 145                        for ( ULONG j = 1; j < nCount; j++ )
 146                        {
 147                            if (!pMat->IsValue(j))
 148                            {
 149                                SetIllegalArgument();
 150                                return;
 151                            }
 152                            fx = pMat->GetDouble(j);
 153                            if (fx < 0.0)
 154                            {
 155                                fx *= -1.0;
 156                                fSign *= -1.0;
 157                            }
 158                            fy = ScGetGGT(fx, fy);
 159                        }
 160                    }
 161                }
 162            }
 163            break;
 164            default : SetError(errIllegalParameter); break;
 165        }
 166        ScRange aRange;
 167        for (short i = 0; i < (short) nParamCount - 1; i++)
 168        {
 169            switch (GetStackType())
 170            {
 171                case svDouble :
 172                case svString:
 173                case svSingleRef:
 174                {
 175                    fx = GetDouble();
 176                    if (fx < 0.0)
 177                    {
 178                        fx *= -1.0;
 179                        fSign *= -1.0;
 180                    }
 181                    fy = ScGetGGT(fx, fy);
 182                }
 183                break;
 184                case svDoubleRef :
 185                {
 186                    USHORT nErr = 0;
 187                    PopDoubleRef( aRange );
 188                    double nCellVal;
 189                    ScValueIterator aValIter(pDok, aRange, glSubTotal);
 190                    if (aValIter.GetFirst(nCellVal, nErr))
 191                    {
 192                        fx = nCellVal;
 193                        if (fx < 0.0)
 194                        {
 195                            fx *= -1.0;
 196                            fSign *= -1.0;
 197                        }
 198                        fy = ScGetGGT(fx, fy);
 199                        while (nErr == 0 && aValIter.GetNext(nCellVal, nErr))
 200                        {
 201                            fx = nCellVal;
 202                            if (fx < 0.0)
 203                            {
 204                                fx *= -1.0;
 205                                fSign *= -1.0;
 206                            }
 207                            fy = ScGetGGT(fx, fy);
 208                        }
 209                        SetError(nErr);
 210                    }
 211                    else
 212                        SetError(errIllegalArgument);
 213                }
 214                break;
 215                case svMatrix :
 216                {
 217                    ScMatrix* pMat = PopMatrix();
 218                    if (pMat)
 219                    {
 220                        USHORT nC, nR;
 221                        pMat->GetDimensions(nC, nR);
 222                        if (nC == 0 || nR == 0)
 223                            SetError(errIllegalArgument);
 224                        else
 225                        {
 226                            if (!pMat->IsValue(0))
 227                            {
 228                                SetIllegalArgument();
 229                                return;
 230                            }
 231                            fx = pMat->GetDouble(0);
 232                            if (fx < 0.0)
 233                            {
 234                                fx *= -1.0;
 235                                fSign *= -1.0;
 236                            }
 237                            fy = ScGetGGT(fx, fy);
 238                            ULONG nCount = (ULONG) nC * nR;
 239                            for ( ULONG j = 1; j < nCount; j++ )
 240                            {
 241                                if (!pMat->IsValue(j))
 242                                {
 243                                    SetIllegalArgument();
 244                                    return;
 245                                }
 246                                fx = pMat->GetDouble(j);
 247                                if (fx < 0.0)
 248                                {
 249                                    fx *= -1.0;
 250                                    fSign *= -1.0;
 251                                }
 252                                fy = ScGetGGT(fx, fy);
 253                            }
 254                        }
 255                    }
 256                }
 257                break;
 258                default : SetError(errIllegalParameter); break;
 259            }
 260        }
 261        if (fSign == -1.0)
 262            PushDouble(-fy);
 263        else
 264            PushDouble(fy);
 265    }
 266}
 267
 268void ScInterpreter:: ScKGV()
 269{
 270    BYTE nParamCount = GetByte();
 271    if ( MustHaveParamCountMin( nParamCount, 1 ) )
 272    {
 273        double fSign = 1.0;
 274        double fx, fy = 0.0;
 275        switch (GetStackType())
 276        {
 277            case svDouble :
 278            case svString:
 279            case svSingleRef:
 280            {
 281                fy = GetDouble();
 282                if (fy < 0.0)
 283                {
 284                    fy *= -1.0;
 285                    fSign *= -1.0;
 286                }
 287            }
 288            break;
 289            case svDoubleRef :
 290            {
 291                ScRange aRange;
 292                USHORT nErr = 0;
 293                PopDoubleRef( aRange );
 294                double nCellVal;
 295                ScValueIterator aValIter(pDok, aRange, glSubTotal);
 296                if (aValIter.GetFirst(nCellVal, nErr))
 297                {
 298                    fy = nCellVal;
 299                    if (fy < 0.0)
 300                    {
 301                        fy *= -1.0;
 302                        fSign *= -1.0;
 303                    }
 304                    while (nErr == 0 && aValIter.GetNext(nCellVal, nErr))
 305                    {
 306                        fx = nCellVal;
 307                        if (fx < 0.0)
 308                        {
 309                            fx *= -1.0;
 310                            fSign *= -1.0;
 311                        }
 312                        fy = fx * fy / ScGetGGT(fx, fy);
 313                    }
 314                    SetError(nErr);
 315                }
 316                else
 317                    SetError(errIllegalArgument);
 318            }
 319            break;
 320            case svMatrix :
 321            {
 322                ScMatrix* pMat = PopMatrix();
 323                if (pMat)
 324                {
 325                    USHORT nC, nR;
 326                    pMat->GetDimensions(nC, nR);
 327                    if (nC == 0 || nR == 0)
 328                        SetError(errIllegalArgument);
 329                    else
 330                    {
 331                        if (!pMat->IsValue(0))
 332                        {
 333                            SetIllegalArgument();
 334                            return;
 335                        }
 336                        fy = pMat->GetDouble(0);
 337                        if (fy < 0.0)
 338                        {
 339                            fy *= -1.0;
 340                            fSign *= -1.0;
 341                        }
 342                        ULONG nCount = (ULONG) nC * nR;
 343                        for ( ULONG j = 1; j < nCount; j++ )
 344                        {
 345                            if (!pMat->IsValue(j))
 346                            {
 347                                SetIllegalArgument();
 348                                return;
 349                            }
 350                            fx = pMat->GetDouble(j);
 351                            if (fx < 0.0)
 352                            {
 353                                fx *= -1.0;
 354                                fSign *= -1.0;
 355                            }
 356                            fy = fx * fy / ScGetGGT(fx, fy);
 357                        }
 358                    }
 359                }
 360            }
 361            break;
 362            default : SetError(errIllegalParameter); break;
 363        }
 364        ScRange aRange;
 365        for (short i = 0; i < (short) nParamCount - 1; i++)
 366        {
 367            switch (GetStackType())
 368            {
 369                case svDouble :
 370                case svString:
 371                case svSingleRef:
 372                {
 373                    fx = GetDouble();
 374                    if (fx < 0.0)
 375                    {
 376                        fx *= -1.0;
 377                        fSign *= -1.0;
 378                    }
 379                    fy = fx * fy / ScGetGGT(fx, fy);
 380                }
 381                break;
 382                case svDoubleRef :
 383                {
 384                    USHORT nErr = 0;
 385                    PopDoubleRef( aRange );
 386                    double nCellVal;
 387                    ScValueIterator aValIter(pDok, aRange, glSubTotal);
 388                    if (aValIter.GetFirst(nCellVal, nErr))
 389                    {
 390                        fx = nCellVal;
 391                        if (fx < 0.0)
 392                        {
 393                            fx *= -1.0;
 394                            fSign *= -1.0;
 395                        }
 396                        fy = fx * fy / ScGetGGT(fx, fy);
 397                        while (nErr == 0 && aValIter.GetNext(nCellVal, nErr))
 398                        {
 399                            fx = nCellVal;
 400                            if (fx < 0.0)
 401                            {
 402                                fx *= -1.0;
 403                                fSign *= -1.0;
 404                            }
 405                            fy = fx * fy / ScGetGGT(fx, fy);
 406                        }
 407                        SetError(nErr);
 408                    }
 409                    else
 410                        SetError(errIllegalArgument);
 411                }
 412                break;
 413                case svMatrix :
 414                {
 415                    ScMatrix* pMat = PopMatrix();
 416                    if (pMat)
 417                    {
 418                        USHORT nC, nR;
 419                        pMat->GetDimensions(nC, nR);
 420                        if (nC == 0 || nR == 0)
 421                            SetError(errIllegalArgument);
 422                        else
 423                        {
 424                            if (!pMat->IsValue(0))
 425                            {
 426                                SetIllegalArgument();
 427                                return;
 428                            }
 429                            fx = pMat->GetDouble(0);
 430                            if (fx < 0.0)
 431                            {
 432                                fx *= -1.0;
 433                                fSign *= -1.0;
 434                            }
 435                            fy = fx * fy / ScGetGGT(fx, fy);
 436                            ULONG nCount = (ULONG) nC * nR;
 437                            for ( ULONG j = 1; j < nCount; j++ )
 438                            {
 439                                if (!pMat->IsValue(j))
 440                                {
 441                                    SetIllegalArgument();
 442                                    return;
 443                                }
 444                                fx = pMat->GetDouble(j);
 445                                if (fx < 0.0)
 446                                {
 447                                    fx *= -1.0;
 448                                    fSign *= -1.0;
 449                                }
 450                                fy = fx * fy / ScGetGGT(fx, fy);
 451                            }
 452                        }
 453                    }
 454                }
 455                break;
 456                default : SetError(errIllegalParameter); break;
 457            }
 458        }
 459        if (fSign == -1.0)
 460            PushDouble(-fy);
 461        else
 462            PushDouble(fy);
 463    }
 464}
 465
 466/*N*/ ScMatrix* ScInterpreter::GetNewMat(USHORT nC, USHORT nR, USHORT& nMatInd)
 467/*N*/ {
 468/*N*/   if (nMatCount == MAX_ANZ_MAT)
 469/*N*/   {
 470/*N*/       OSL_FAIL("ScInterpreter::GetNewMat: Matrixueberlauf");
 471/*N*/       SetError(errCodeOverflow);
 472/*N*/       nMatInd = MAX_ANZ_MAT;
 473/*N*/       return NULL;
 474/*N*/   }
 475/*N*/   else
 476/*N*/   {
 477/*N*/       if (!bMatDel)                               // beim ersten Mal
 478/*N*/       {
 479/*N*/           ppTempMatArray = new ScMatrix* [MAX_ANZ_MAT];
 480/*N*/           for (USHORT i = 0; i < MAX_ANZ_MAT; i++)
 481/*N*/               ppTempMatArray[i] = NULL;
 482/*N*/           bMatDel = TRUE;
 483/*N*/       }
 484/*N*/       ppTempMatArray[nMatCount] = new ScMatrix(nC, nR);
 485/*N*/       nMatInd = nMatCount++;
 486/*N*/       return ppTempMatArray[nMatInd];
 487/*N*/   }
 488/*N*/ }
 489
 490/*N*/ void ScInterpreter::ResetNewMat(USHORT nIndex)
 491/*N*/ {
 492/*N*/   if (nIndex < MAX_ANZ_MAT)
 493/*N*/   {
 494/*N*/       ppTempMatArray[nIndex] = NULL;
 495/*N*/       if (nIndex == nMatCount - 1)
 496/*N*/           nMatCount--;
 497/*N*/   }
 498/*N*/ }
 499
 500/*N*/ ScMatrix* ScInterpreter::GetMatrix(USHORT& nMatInd)
 501/*N*/ {
 502/*N*/   ScMatrix* pMat = NULL;
 503/*N*/   switch (GetStackType())
 504/*N*/   {
 505/*?*/       case svSingleRef :
 506/*?*/       {
 507/*?*/           ScAddress aAdr;
 508/*?*/           PopSingleRef( aAdr );
 509/*?*/           pMat = GetNewMat(1, 1, nMatInd);
 510/*?*/           if (pMat)
 511/*?*/           {
 512/*?*/               ScBaseCell* pCell = GetCell( aAdr );
 513/*?*/               if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
 514/*?*/               {
 515/*?*/                   if (HasCellValueData(pCell))
 516/*?*/                         pMat->PutDouble(GetCellValue(aAdr, pCell), 0);
 517/*?*/                   else
 518/*?*/                   {
 519/*?*/                       String aStr;
 520/*?*/                       GetCellString(aStr, pCell);
 521/*?*/                         pMat->PutString(aStr, 0);
 522/*?*/                   }
 523/*?*/               }
 524/*?*/               else
 525/*?*/                     pMat->PutEmpty( 0 );
 526/*?*/           }
 527/*?*/           else
 528/*?*/               SetError(errCodeOverflow);
 529/*?*/       }
 530/*?*/       break;
 531/*N*/       case svDoubleRef:
 532/*N*/       {
 533/*N*/           USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
 534/*N*/           PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
 535/*N*/           if (nTab1 == nTab2)
 536/*N*/           {
 537/*N*/               USHORT i, j;
 538/*N*/               if ( (ULONG) (nRow2 - nRow1 + 1) * (nCol2 - nCol1 + 1) >
 539/*N*/                       ScMatrix::GetElementsMax() )
 540/*N*/                   SetError(errStackOverflow);
 541/*N*/               else
 542/*N*/               {
 543/*N*/                   pMat = GetNewMat(nCol2 - nCol1 + 1, nRow2 - nRow1 + 1, nMatInd);
 544/*N*/                   if (pMat)
 545/*N*/                   {
 546/*N*/                       ScAddress aAdr( nCol1, nRow1, nTab1 );
 547/*N*/                       for (i = nRow1; i <= nRow2; i++)
 548/*N*/                       {
 549/*N*/                           aAdr.SetRow( i );
 550/*N*/                           for (j = nCol1; j <= nCol2; j++)
 551/*N*/                           {
 552/*N*/                               aAdr.SetCol( j );
 553/*N*/                               ScBaseCell* pCell = GetCell( aAdr );
 554/*N*/                               if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
 555/*N*/                               {
 556/*N*/                                   if (HasCellValueData(pCell))
 557/*N*/                                       pMat->PutDouble(
 558/*N*/                                               GetCellValue( aAdr, pCell ),
 559/*N*/                                               j-nCol1, i-nRow1);
 560/*N*/                                   else
 561/*N*/                                   {
 562/*?*/                                       String aStr;
 563/*?*/                                       GetCellString(aStr, pCell);
 564/*?*/                                       pMat->PutString(aStr, j-nCol1, i-nRow1);
 565/*N*/                                   }
 566/*N*/                               }
 567/*N*/                               else
 568/*?*/                                   pMat->PutEmpty( j-nCol1, i-nRow1 );
 569/*N*/                           }
 570/*N*/                       }
 571/*N*/                   }
 572/*N*/                   else
 573/*N*/                       SetError(errCodeOverflow);
 574/*N*/               }
 575/*N*/           }
 576/*N*/           else                                // keine 2D-Matrix
 577/*N*/           {
 578/*N*/               nMatInd = MAX_ANZ_MAT;
 579/*N*/               SetError(errIllegalParameter);
 580/*N*/           }
 581/*N*/       }
 582/*N*/       break;
 583/*N*/       case svMatrix:
 584/*N*/           pMat = PopMatrix();
 585/*N*/           nMatInd = MAX_ANZ_MAT;
 586/*N*/       break;
 587/*?*/       default:
 588/*?*/           Pop();
 589/*?*/           nMatInd = MAX_ANZ_MAT;
 590/*?*/           SetError(errIllegalParameter);
 591/*?*/       break;
 592/*N*/   }
 593/*N*/   return pMat;
 594/*N*/ }
 595
 596void ScInterpreter::ScMatValue()
 597{
 598    if ( MustHaveParamCount( GetByte(), 3 ) )
 599    {
 600        USHORT nR = (USHORT) ::rtl::math::approxFloor(GetDouble());     // 0 bis nAnz - 1
 601        USHORT nC = (USHORT) ::rtl::math::approxFloor(GetDouble());     // 0 bis nAnz - 1
 602        switch (GetStackType())
 603        {
 604            case svSingleRef :
 605            {
 606                ScAddress aAdr;
 607                PopSingleRef( aAdr );
 608                ScBaseCell* pCell = GetCell( aAdr );
 609                if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
 610                {
 611                    USHORT nErrCode = ((ScFormulaCell*)pCell)->GetErrCode();
 612                    if (nErrCode != 0)
 613                    {
 614                        SetError(nErrCode);
 615                        PushInt(0);
 616                    }
 617                    else
 618                    {
 619                        ScMatrix* pMat;
 620                        ((ScFormulaCell*)pCell)->GetMatrix(&pMat);
 621                        if (pMat)
 622                        {
 623                            USHORT nCl, nRw;
 624                            pMat->GetDimensions(nCl, nRw);
 625                            if (nC < nCl && nR < nRw)
 626                            {
 627                                BOOL bIsString;
 628                                const MatValue* pMatVal = pMat->Get(nC, nR, bIsString);
 629                                if (bIsString)
 630                                    PushString( pMatVal->GetString() );
 631                                else
 632                                    PushDouble(pMatVal->fVal);
 633                            }
 634                            else
 635                                SetNoValue();
 636                        }
 637                        else
 638                            SetNoValue();
 639                    }
 640                }
 641                else
 642                    SetIllegalParameter();
 643            }
 644            break;
 645            case svDoubleRef :
 646            {
 647                USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
 648                PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
 649                if (nCol2 - nCol1 >= nR && nRow2 - nRow1 >= nC && nTab1 == nTab2)
 650                {
 651                    ScAddress aAdr( nCol1 + nR, nRow1 + nC, nTab1 );
 652                    ScBaseCell* pCell = GetCell( aAdr );
 653                    if (HasCellValueData(pCell))
 654                        PushDouble(GetCellValue( aAdr, pCell ));
 655                    else
 656                    {
 657                        String aStr;
 658                        GetCellString(aStr, pCell);
 659                        PushString(aStr);
 660                    }
 661                }
 662                else
 663                    SetNoValue();
 664            }
 665            break;
 666            case svMatrix:
 667            {
 668                ScMatrix* pMat = PopMatrix();
 669                if (pMat)
 670                {
 671                    USHORT nCl, nRw;
 672                    pMat->GetDimensions(nCl, nRw);
 673                    if (nC < nCl && nR < nRw)
 674                    {
 675                        BOOL bIsString;
 676                        const MatValue* pMatVal = pMat->Get(nC, nR, bIsString);
 677                        if (bIsString)
 678                            PushString( pMatVal->GetString() );
 679                        else
 680                            PushDouble(pMatVal->fVal);
 681                    }
 682                    else
 683                        SetNoValue();
 684                }
 685                else
 686                    SetNoValue();
 687            }
 688            break;
 689            default:
 690                Pop();
 691                SetIllegalParameter();
 692            break;
 693        }
 694    }
 695}
 696
 697void ScInterpreter::ScEMat()
 698{
 699    if ( MustHaveParamCount( GetByte(), 1 ) )
 700    {
 701        ULONG nDim = (ULONG) ::rtl::math::approxFloor(GetDouble());
 702        if ( nDim * nDim > ScMatrix::GetElementsMax() || nDim == 0)
 703            SetIllegalArgument();
 704        else
 705        {
 706            USHORT nMatInd;
 707            ScMatrix* pRMat = GetNewMat((USHORT)nDim, (USHORT)nDim, nMatInd);
 708            if (pRMat)
 709            {
 710                MEMat(pRMat, (USHORT) nDim);
 711                nRetMat = nMatInd;
 712                PushMatrix(pRMat);
 713            }
 714            else
 715                SetError(errStackOverflow);
 716        }
 717    }
 718}
 719
 720void ScInterpreter::MEMat(ScMatrix* mM, USHORT n)
 721{
 722    mM->FillDouble(0.0, 0, 0, n-1, n-1);
 723    for (USHORT i = 0; i < n; i++)
 724        mM->PutDouble(1.0, i, i);
 725}
 726
 727void ScInterpreter::MFastMult(ScMatrix* pA, ScMatrix* pB, ScMatrix* pR,
 728                              USHORT n, USHORT m, USHORT l)
 729        // Multipliziert n x m Mat a mit m x l Mat b nach Mat r
 730{
 731    double sum;
 732    for (USHORT i = 0; i < n; i++)
 733    {
 734        for (USHORT j = 0; j < l; j++)
 735        {
 736            sum = 0.0;
 737            for (USHORT k = 0; k < m; k++)
 738                sum += pA->GetDouble(i,k)*pB->GetDouble(k,j);
 739            pR->PutDouble(sum, i, j);
 740        }
 741    }
 742}
 743
 744void ScInterpreter::MFastSub(ScMatrix* pA, ScMatrix* pB, ScMatrix* pR,
 745                              USHORT n, USHORT m)
 746        // Subtrahiert n x m Mat a - m x l Mat b nach Mat r
 747{
 748    for (USHORT i = 0; i < n; i++)
 749    {
 750        for (USHORT j = 0; j < m; j++)
 751            pR->PutDouble(pA->GetDouble(i,j) - pB->GetDouble(i,j), i, j);
 752    }
 753}
 754
 755void ScInterpreter::MFastTrans(ScMatrix* pA, ScMatrix* pR,
 756                              USHORT n, USHORT m)
 757        // Transponiert n x m Mat a nach Mat r
 758{
 759    for (USHORT i = 0; i < n; i++)
 760        for (USHORT j = 0; j < m; j++)
 761            pR->PutDouble(pA->GetDouble(i, j), j, i);
 762}
 763
 764BOOL ScInterpreter::MFastBackSubst(ScMatrix* pA, ScMatrix* pR, USHORT n, BOOL bIsUpper)
 765        // F?hrt R?ckwaertsersetzung der Dreickesmatrix Mat a nach Mat r durch
 766        // 2 Versionen fuer obere (U)  oder untere (L- Unit) Dreiecksmatrizen
 767{
 768    short i, j, k;
 769    double fSum;
 770    if (!bIsUpper)                          // L-Matrix, immer invertierbar
 771    {
 772        MEMat(pR, n);
 773        for (i = 1; i < (short) n; i++)
 774        {
 775            for (j = 0; j < i; j++)
 776            {
 777                fSum = 0.0;
 778                for (k = 0; k < i; k++)
 779                    fSum += pA->GetDouble(i,k) * pR->GetDouble(k,j);
 780                pR->PutDouble(-fSum, i, j);
 781            }
 782        }
 783    }
 784    else                                    // U-Matrix
 785    {
 786        for (i = 0; i < (short) n; i++)                         // Ist invertierbar?
 787            if (fabs(pA->GetDouble(i,i)) < SCdEpsilon)
 788                return FALSE;
 789        pR->FillDoubleLowerLeft(0.0, n-1);                      // untere Haelfte
 790        pR->PutDouble(1.0/pA->GetDouble(n-1, n-1), n-1, n-1);   // n-1, n-1
 791        for (i = (short) n-2; i >= 0; i--)
 792        {
 793            for (j = (short) n-1; j > i; j--)
 794            {
 795                fSum = 0.0;
 796                for (k = (short) n-1; k > i; k--)
 797                    fSum += pA->GetDouble(i, k) * pR->GetDouble(k, j);
 798                pR->PutDouble(-fSum/pA->GetDouble(i, i), i, j);
 799            }
 800            fSum = 0.0;                                         // Hauptdiagonale:
 801            for (k = (short) n-1; k > i; k--)
 802                fSum += pA->GetDouble(i, k) * pR->GetDouble(k, j);
 803            pR->PutDouble((1.0-fSum)/pA->GetDouble(i, i), i, i);
 804        }
 805    }
 806    return TRUE;
 807}
 808
 809BOOL ScInterpreter::ScMatLUP(ScMatrix* mA, USHORT m, USHORT p,
 810                             ScMatrix* mL, ScMatrix* mU, ScMatrix* mP,
 811                             ULONG& rPermutCounter, BOOL& bIsInvertable)
 812    // Returnwert = False <=> Matrixarray voll
 813    // BIsInvertable = False: <= mA hat nicht Rang m
 814{
 815    USHORT nMatInd1, nMatInd2, nMatInd3, nMatInd4, nMatInd5;
 816    USHORT i, j;
 817    if (m == 1)
 818    {
 819        mL->PutDouble(1.0,0,0);
 820        for (j = 0; j < p; j++)
 821            if (fabs(mA->GetDouble(0, j)) >= SCdEpsilon)
 822                break;
 823        if (j == p)
 824        {
 825            bIsInvertable = FALSE;
 826            return TRUE;
 827        }
 828        MEMat(mP, p);
 829        if (j > 0 && j < p)
 830        {
 831            mP->PutDouble(0.0, 0, 0);
 832            mP->PutDouble(1.0, j, 0);
 833            mP->PutDouble(0.0, j, j);
 834            mP->PutDouble(1.0, 0, j);
 835            rPermutCounter++;
 836        }
 837        MFastMult(mA, mP, mU, m, p, p);
 838    }
 839    else
 840    {
 841        USHORT md2 = m/2;
 842        ScMatrix* mB = GetNewMat(md2, p, nMatInd1);
 843        ScMatrix* mC = GetNewMat(md2, p, nMatInd2);
 844        ScMatrix* mL1 = GetNewMat(md2, md2, nMatInd3);
 845        ScMatrix* mU1 = GetNewMat(md2, p, nMatInd4);
 846        ScMatrix* mP1 = GetNewMat(p, p, nMatInd5);
 847        if (!mB || !mC || !mL1 || !mU1 || !mP1 )
 848            return FALSE;
 849        for (i = 0; i < md2; i++)
 850        {
 851            for (j = 0; j < p; j++)
 852            {
 853                mB->PutDouble(mA->GetDouble(i, j), i, j);
 854                mC->PutDouble(mA->GetDouble(md2+i,j), i, j);
 855            }
 856        }
 857        if (!ScMatLUP(mB, md2, p, mL1, mU1, mP1, rPermutCounter, bIsInvertable))
 858            return FALSE;
 859        if (!bIsInvertable)
 860        {
 861            ResetNewMat(nMatInd5);
 862            ResetNewMat(nMatInd4);
 863            ResetNewMat(nMatInd3);
 864            ResetNewMat(nMatInd2);
 865            ResetNewMat(nMatInd1);
 866            delete mP1;
 867            delete mU1;
 868            delete mL1;
 869            delete mC;
 870            delete mB;
 871            return TRUE;
 872        }
 873        USHORT nMatInd6, nMatInd7, nMatInd8, nMatInd9, nMatInd10;
 874        USHORT nMatInd11, nMatInd12, nMatInd13;
 875        ScMatrix* mE    = GetNewMat(md2, md2,         nMatInd6);
 876        ScMatrix* mF    = GetNewMat(md2, md2,         nMatInd7);
 877        ScMatrix* mEInv = GetNewMat(md2, md2,         nMatInd8);
 878        ScMatrix* mG    = GetNewMat(md2, p,           nMatInd9);
 879        ScMatrix* mGs   = GetNewMat(md2, p - md2,     nMatInd10);
 880        ScMatrix* mU2   = GetNewMat(md2, p - md2,     nMatInd11);
 881        ScMatrix* mP2   = GetNewMat(p - md2, p - md2, nMatInd12);
 882        if (!mP2 || !mU2 || !mGs|| !mG || !mEInv || !mF || !mE)
 883            return FALSE;
 884        MFastTrans(mP1, mP, p, p);              // mP = mP1 hoch  -1
 885        ScMatrix* mD = mB;                      // mB wird nicht mehr gebraucht
 886        MFastMult(mC, mP, mD, md2, p, p);
 887        for (i = 0; i < md2; i++)
 888        {
 889            for (j = 0; j < md2; j++)
 890            {
 891                mE->PutDouble(mU1->GetDouble(i, j), i, j);
 892                mF->PutDouble(mD->GetDouble(i, j), i, j);
 893            }
 894        }
 895        BOOL bEInvok = MFastBackSubst(mE, mEInv, md2, TRUE); // MeInv = E hoch -1
 896        if (!bEInvok)
 897        {
 898            bIsInvertable = FALSE;
 899            ResetNewMat(nMatInd12);
 900            ResetNewMat(nMatInd11);
 901            ResetNewMat(nMatInd10);
 902            ResetNewMat(nMatInd9);
 903            ResetNewMat(nMatInd8);
 904            ResetNewMat(nMatInd7);
 905            ResetNewMat(nMatInd6);
 906            ResetNewMat(nMatInd5);
 907            ResetNewMat(nMatInd4);
 908            ResetNewMat(nMatInd3);
 909            ResetNewMat(nMatInd2);
 910            ResetNewMat(nMatInd1);
 911            delete mP2;
 912            delete mU2;
 913            delete mGs;
 914            delete mG;
 915            delete mEInv;
 916            delete mF;
 917            delete mE;
 918            delete mP1;
 919            delete mU1;
 920            delete mL1;
 921            delete mC;
 922            delete mB;
 923            return TRUE;
 924        }
 925        ScMatrix* mFEInv = mE;              // mE wird nicht mehr gebraucht.
 926        MFastMult(mF, mEInv, mFEInv, md2, md2, md2);
 927        ScMatrix* mFEInvU1 = mC;            // mC wird nicht mehr gebraucht
 928        MFastMult(mFEInv, mU1, mFEInvU1, md2, md2, p);
 929        MFastSub(mD, mFEInvU1, mG, md2, p);
 930        for (i = 0; i < md2; i++)
 931        {
 932            for (j = 0; j < p-md2; j++)
 933                mGs->PutDouble(mG->GetDouble(i, md2+j), i, j);
 934        }
 935        ScMatrix* mL2 = mF;                 // mF wird nicht mehr gebraucht
 936        if (!ScMatLUP(mGs, md2, p - md2, mL2, mU2, mP2, rPermutCounter, bIsInvertable))
 937            return FALSE;
 938        if (!bIsInvertable)
 939        {
 940            ResetNewMat(nMatInd12);
 941            ResetNewMat(nMatInd11);
 942            ResetNewMat(nMatInd10);
 943            ResetNewMat(nMatInd9);
 944            ResetNewMat(nMatInd8);
 945            ResetNewMat(nMatInd7);
 946            ResetNewMat(nMatInd6);
 947            ResetNewMat(nMatInd5);
 948            ResetNewMat(nMatInd4);
 949            ResetNewMat(nMatInd3);
 950            ResetNewMat(nMatInd2);
 951            ResetNewMat(nMatInd1);
 952            delete mP2;
 953            delete mU2;
 954            delete mGs;
 955            delete mG;
 956            delete mEInv;
 957            delete mF;
 958            delete mE;
 959            delete mP1;
 960            delete mU1;
 961            delete mL1;
 962            delete mC;
 963            delete mB;
 964            return TRUE;
 965        }
 966        ScMatrix* mP3 =  GetNewMat(p, p, nMatInd13);
 967        if (!mP3)
 968            return FALSE;
 969        MEMat(mP3, p);
 970        for (i = md2; i < p; i++)
 971        {
 972            for (j = md2; j < p; j++)
 973                mP3->PutDouble(mP2->GetDouble(i-md2, j-md2), i, j);
 974        }
 975        MFastMult(mP3, mP1, mP, p, p, p);       // Ergebnis P !!
 976        ScMatrix* mP3Inv = mP1;                 // mP1 wird nicht mehr gebraucht;
 977        MFastTrans(mP3, mP3Inv, p, p);
 978        ScMatrix* mH = mD;                      // mD wird nicht mehr gebraucht
 979        MFastMult(mU1, mP3Inv, mH, md2, p, p);
 980        MEMat(mL, m);                           // Ergebnis L :
 981        for (i = 0; i < md2; i++)
 982        {
 983            for (j = 0; j < i; j++)
 984                mL->PutDouble(mL1->GetDouble(i, j), i, j);
 985        }
 986        for (i = md2; i < m; i++)
 987            for (j = md2; j < i; j++)
 988                mL->PutDouble(mL2->GetDouble(i-md2, j-md2), i, j);
 989        for (i = md2; i < m; i++)
 990            for (j = 0; j < md2; j++)
 991                mL->PutDouble(mFEInv->GetDouble(i-md2, j), i, j);
 992                                                // Ergebnis U:
 993        mU->FillDoubleLowerLeft(0.0, m-1);
 994        for (i = 0; i < md2; i++)
 995            for (j = i; j < p; j++)
 996                mU->PutDouble(mH->GetDouble(i, j), i, j);
 997        for (i = md2; i < m; i++)
 998            for (j = i; j < p; j++)
 999                mU->PutDouble(mU2->GetDouble(i - md2, j - md2), i, j);
1000        ResetNewMat(nMatInd13);             // alle wieder freigeben;
1001        ResetNewMat(nMatInd12);
1002        ResetNewMat(nMatInd11);
1003        ResetNewMat(nMatInd10);
1004        ResetNewMat(nMatInd9);
1005        ResetNewMat(nMatInd8);
1006        ResetNewMat(nMatInd7);
1007        ResetNewMat(nMatInd6);
1008        ResetNewMat(nMatInd5);
1009        ResetNewMat(nMatInd4);
1010        ResetNewMat(nMatInd3);
1011        ResetNewMat(nMatInd2);
1012        ResetNewMat(nMatInd1);
1013        delete mP3;
1014        delete mP2;
1015        delete mU2;
1016        delete mGs;
1017        delete mG;
1018        delete mEInv;
1019        delete mF;
1020        delete mE;
1021        delete mP1;
1022        delete mU1;
1023        delete mL1;
1024        delete mC;
1025        delete mB;
1026    }
1027    return TRUE;
1028}
1029
1030void ScInterpreter::ScMatDet()
1031{
1032    if ( MustHaveParamCount( GetByte(), 1 ) )
1033    {
1034        USHORT nMatInd;
1035        ScMatrix* pMat = GetMatrix(nMatInd);
1036        if (!pMat)
1037        {
1038            SetIllegalParameter();
1039            return;
1040        }
1041        if ( !pMat->IsNumeric() )
1042        {
1043            SetNoValue();
1044            return;
1045        }
1046        USHORT nC, nR;
1047        pMat->GetDimensions(nC, nR);
1048        if ( nC != nR || nC == 0 || (ULONG) nC * nC > ScMatrix::GetElementsMax() )
1049            SetIllegalParameter();
1050        else
1051        {
1052            double fVal = log((double)nC) / log(2.0);
1053            if (fVal - floor(fVal) != 0.0)
1054                fVal = floor(fVal) + 1.0;
1055            USHORT nDim = (USHORT) pow(2.0, fVal);
1056            USHORT nMatInd1, nMatInd2, nMatInd3;
1057            USHORT nMatInd4 = MAX_ANZ_MAT;
1058            ScMatrix* pU = GetNewMat(nDim, nDim, nMatInd1);
1059            ScMatrix* pL = GetNewMat(nDim, nDim, nMatInd2);
1060            ScMatrix* pP = GetNewMat(nDim, nDim, nMatInd3);
1061            ScMatrix* pA;
1062            if (nC == nDim)
1063                pA = pMat;
1064            else
1065            {
1066                pA = GetNewMat(nDim, nDim, nMatInd4);
1067                MEMat(pA, nDim);
1068                for (USHORT i = 0; i < nC; i++)
1069                    for (USHORT j = 0; j < nC; j++)
1070                    {
1071                        pA->PutDouble(pMat->GetDouble(i, j), i, j);
1072                    }
1073            }
1074            ULONG nPermutCounter = 0;
1075            BOOL bIsInvertable = TRUE;
1076            BOOL bOk = ScMatLUP(pA, nDim, nDim, pL, pU, pP,
1077                                nPermutCounter, bIsInvertable);
1078            ResetNewMat(nMatInd4);
1079            ResetNewMat(nMatInd3);
1080            ResetNewMat(nMatInd2);
1081            if (nC != nDim)
1082                delete pA;
1083            delete pP;
1084            delete pL;
1085            if (bOk)
1086            {
1087                if (!bIsInvertable)
1088                    PushInt(0);
1089                else
1090                {
1091                    double fDet = 1.0;
1092                    for (USHORT i = 0; i < nC; i++)
1093                        fDet *= pU->GetDouble(i, i);
1094                    if (nPermutCounter % 2 != 0)
1095                        fDet *= -1.0;
1096                    PushDouble(fDet);
1097                }
1098            }
1099            else
1100            {
1101                SetError(errCodeOverflow);
1102                PushInt(0);
1103            }
1104            ResetNewMat(nMatInd1);
1105            delete pU;
1106        }
1107    }
1108}
1109
1110void ScInterpreter::ScMatInv()
1111{
1112    if ( MustHaveParamCount( GetByte(), 1 ) )
1113    {
1114        USHORT nMatInd;
1115        ScMatrix* pMat = GetMatrix(nMatInd);
1116        if (!pMat)
1117        {
1118            SetIllegalParameter();
1119            return;
1120        }
1121        if ( !pMat->IsNumeric() )
1122        {
1123            SetNoValue();
1124            return;
1125        }
1126        USHORT nC, nR;
1127        pMat->GetDimensions(nC, nR);
1128        if ( nC != nR || nC == 0 || (ULONG) nC * nC > ScMatrix::GetElementsMax() )
1129            SetIllegalParameter();
1130        else
1131        {
1132            double fVal = log((double)nC) / log(2.0);
1133            if (fVal - floor(fVal) != 0.0)
1134                fVal = floor(fVal) + 1.0;
1135            USHORT nDim = (USHORT) pow(2.0, fVal);
1136            USHORT nMatInd1, nMatInd2, nMatInd3;
1137            USHORT nMatInd4 = MAX_ANZ_MAT;
1138            ScMatrix* pU = GetNewMat(nDim, nDim, nMatInd1);
1139            ScMatrix* pL = GetNewMat(nDim, nDim, nMatInd2);
1140            ScMatrix* pP = GetNewMat(nDim, nDim, nMatInd3);
1141            ScMatrix* pA;
1142            if (nC == nDim)
1143                pA = pMat;
1144            else
1145            {
1146                pA = GetNewMat(nDim, nDim, nMatInd4);
1147                MEMat(pA, nDim);
1148                for (USHORT i = 0; i < nC; i++)
1149                    for (USHORT j = 0; j < nC; j++)
1150                    {
1151                        pA->PutDouble(pMat->GetDouble(i, j), i, j);
1152                    }
1153            }
1154            ULONG nPermutCounter = 0;
1155            BOOL bIsInvertable = TRUE;
1156            BOOL bOk = ScMatLUP(pA, nDim, nDim, pL, pU, pP,
1157                                nPermutCounter, bIsInvertable);
1158            if (bOk)
1159            {
1160                if (!bIsInvertable)
1161                    SetNoValue();
1162                else
1163                {
1164                    USHORT nMatInd5;
1165                    ScMatrix* pUInv = GetNewMat(nDim, nDim, nMatInd5);
1166                    if (!pUInv)
1167                        PushInt(0);
1168                    else
1169                    {
1170                        bOk = MFastBackSubst(pU, pUInv, nDim, TRUE);
1171                        if (!bOk)
1172                            SetNoValue();
1173                        else
1174                        {
1175                            ScMatrix* pPInv = pU;
1176                            MFastTrans(pP, pPInv, nDim, nDim);
1177                            ScMatrix* pPInvUInv = pP;
1178                            MFastMult(pPInv, pUInv, pPInvUInv, nDim, nDim, nDim);
1179                            ScMatrix* pLInv = pPInv;
1180                            MFastBackSubst(pL, pLInv, nDim, FALSE);
1181                            if (nDim == nC)
1182                                MFastMult(pPInvUInv, pLInv, pMat, nDim, nDim, nDim);
1183                            else
1184                            {
1185                                MFastMult(pPInvUInv, pLInv, pL, nDim, nDim, nDim);
1186                                for (USHORT i = 0; i < nC; i++)
1187                                    for (USHORT j = 0; j < nC; j++)
1188                                        pMat->PutDouble(pL->GetDouble(i, j), i, j);
1189                            }
1190                            PushMatrix(pMat);
1191                            if (nMatInd != MAX_ANZ_MAT) // vorher neue Matrix
1192                                nRetMat = nMatInd;      // sonst nRetMat wie vorher
1193                            ResetNewMat(nMatInd5);
1194                            delete pUInv;
1195                        }
1196                    }
1197                }
1198            }
1199            else
1200            {
1201                SetError(errCodeOverflow);
1202                PushInt(0);
1203            }
1204            ResetNewMat(nMatInd4);
1205            ResetNewMat(nMatInd3);
1206            ResetNewMat(nMatInd2);
1207            ResetNewMat(nMatInd1);
1208            if (nC != nDim)
1209                delete pA;
1210            delete pP;
1211            delete pL;
1212            delete pU;
1213        }
1214    }
1215}
1216
1217void ScInterpreter::ScMatMult()
1218{
1219    if ( MustHaveParamCount( GetByte(), 2 ) )
1220    {
1221        USHORT nMatInd1, nMatInd2;
1222        ScMatrix* pMat2 = GetMatrix(nMatInd2);
1223        ScMatrix* pMat1 = GetMatrix(nMatInd1);
1224        ScMatrix* pRMat;
1225        if (pMat1 && pMat2)
1226        {
1227            if ( pMat1->IsNumeric() && pMat2->IsNumeric() )
1228            {
1229                USHORT nC1, nR1, nC2, nR2;
1230                pMat1->GetDimensions(nC1, nR1);
1231                pMat2->GetDimensions(nC2, nR2);
1232                if (nC1 != nR2)
1233                    SetIllegalParameter();
1234                else
1235                {
1236                    USHORT nMatInd;
1237                    pRMat = GetNewMat(nC2, nR1, nMatInd);       // Matrixabsicherung
1238                    if (pRMat)
1239                    {
1240                        double sum;
1241                        for (USHORT i = 0; i < nR1; i++)
1242                        {
1243                            for (USHORT j = 0; j < nC2; j++)
1244                            {
1245                                sum = 0.0;
1246                                for (USHORT k = 0; k < nC1; k++)
1247                                {
1248                                    sum += pMat1->GetDouble(k,i)*pMat2->GetDouble(j,k);
1249                                }
1250                                pRMat->PutDouble(sum, j, i);
1251                            }
1252                        }
1253                        PushMatrix(pRMat);
1254                        nRetMat = nMatInd;
1255                    }
1256                    else
1257                        SetNoValue();
1258                }
1259            }
1260            else
1261                SetNoValue();
1262        }
1263        else
1264            SetIllegalParameter();
1265    }
1266}
1267
1268void ScInterpreter::ScMatTrans()
1269{
1270    if ( MustHaveParamCount( GetByte(), 1 ) )
1271    {
1272        USHORT nMatInd, nMatInd1;
1273        ScMatrix* pMat = GetMatrix(nMatInd);
1274        ScMatrix* pRMat;
1275        if (pMat)
1276        {
1277            USHORT nC, nR;
1278            pMat->GetDimensions(nC, nR);
1279            pRMat = GetNewMat(nR, nC, nMatInd1);
1280            pMat->MatTrans(*pRMat);
1281            PushMatrix(pRMat);
1282            nRetMat = nMatInd1;
1283        }
1284        else
1285            SetIllegalParameter();
1286    }
1287}
1288
1289/*N*/ ScMatrix* ScInterpreter::MatAdd(ScMatrix* pMat1, ScMatrix* pMat2)
1290/*N*/ {
1291/*N*/   USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
1292/*N*/   pMat1->GetDimensions(nC1, nR1);
1293/*N*/   pMat2->GetDimensions(nC2, nR2);
1294/*N*/   if (nC1 < nC2)
1295/*N*/       nMinC = nC1;
1296/*N*/   else
1297/*N*/       nMinC = nC2;
1298/*N*/   if (nR1 < nR2)
1299/*N*/       nMinR = nR1;
1300/*N*/   else
1301/*N*/       nMinR = nR2;
1302/*N*/   USHORT nMatInd;
1303/*N*/   ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
1304/*N*/   if (pResMat)
1305/*N*/   {
1306/*N*/       for (i = 0; i < nMinC; i++)
1307/*N*/       {
1308/*N*/           for (j = 0; j < nMinR; j++)
1309/*N*/           {
1310/*N*/               if (pMat1->IsValueOrEmpty(i,j) && pMat2->IsValueOrEmpty(i,j))
1311/*N*/                   pResMat->PutDouble( ::rtl::math::approxAdd( pMat1->GetDouble(i,j),
1312/*N*/                                      pMat2->GetDouble(i,j)), i, j);
1313/*N*/               else
1314/*?*/                   pResMat->PutString(ScGlobal::GetRscString(
1315/*N*/                                                   STR_NO_VALUE), i, j);
1316/*N*/           }
1317/*N*/       }
1318/*N*/       nRetMat = nMatInd;
1319/*N*/   }
1320/*N*/   return pResMat;
1321/*N*/ }
1322
1323ScMatrix* ScInterpreter::MatSub(ScMatrix* pMat1, ScMatrix* pMat2)
1324{
1325    USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
1326    pMat1->GetDimensions(nC1, nR1);
1327    pMat2->GetDimensions(nC2, nR2);
1328    if (nC1 < nC2)
1329        nMinC = nC1;
1330    else
1331        nMinC = nC2;
1332    if (nR1 < nR2)
1333        nMinR = nR1;
1334    else
1335        nMinR = nR2;
1336    USHORT nMatInd;
1337    ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
1338    if (pResMat)
1339    {
1340        for (i = 0; i < nMinC; i++)
1341        {
1342            for (j = 0; j < nMinR; j++)
1343            {
1344                if (pMat1->IsValueOrEmpty(i,j) && pMat2->IsValueOrEmpty(i,j))
1345                    pResMat->PutDouble( ::rtl::math::approxSub( pMat1->GetDouble(i,j),
1346                                       pMat2->GetDouble(i,j)), i, j);
1347                else
1348                    pResMat->PutString(ScGlobal::GetRscString(
1349                                                    STR_NO_VALUE), i, j);
1350            }
1351        }
1352        nRetMat = nMatInd;
1353    }
1354    return pResMat;
1355}
1356
1357/*N*/ ScMatrix* ScInterpreter::MatMul(ScMatrix* pMat1, ScMatrix* pMat2)
1358/*N*/ {
1359/*N*/   USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
1360/*N*/   pMat1->GetDimensions(nC1, nR1);
1361/*N*/   pMat2->GetDimensions(nC2, nR2);
1362/*N*/   if (nC1 < nC2)
1363/*N*/       nMinC = nC1;
1364/*N*/   else
1365/*N*/       nMinC = nC2;
1366/*N*/   if (nR1 < nR2)
1367/*N*/       nMinR = nR1;
1368/*N*/   else
1369/*N*/       nMinR = nR2;
1370/*N*/   USHORT nMatInd;
1371/*N*/   ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
1372/*N*/   if (pResMat)
1373/*N*/   {
1374/*N*/       for (i = 0; i < nMinC; i++)
1375/*N*/       {
1376/*N*/           for (j = 0; j < nMinR; j++)
1377/*N*/           {
1378/*N*/               if (pMat1->IsValueOrEmpty(i,j) && pMat2->IsValueOrEmpty(i,j))
1379/*N*/                   pResMat->PutDouble(pMat1->GetDouble(i,j) *
1380/*N*/                                      pMat2->GetDouble(i,j), i, j);
1381/*N*/               else
1382/*?*/                   pResMat->PutString(ScGlobal::GetRscString(
1383/*N*/                                                   STR_NO_VALUE), i, j);
1384/*N*/           }
1385/*N*/       }
1386/*N*/       nRetMat = nMatInd;
1387/*N*/   }
1388/*N*/   return pResMat;
1389/*N*/ }
1390
1391ScMatrix* ScInterpreter::MatDiv(ScMatrix* pMat1, ScMatrix* pMat2)
1392{
1393    USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
1394    pMat1->GetDimensions(nC1, nR1);
1395    pMat2->GetDimensions(nC2, nR2);
1396    if (nC1 < nC2)
1397        nMinC = nC1;
1398    else
1399        nMinC = nC2;
1400    if (nR1 < nR2)
1401        nMinR = nR1;
1402    else
1403        nMinR = nR2;
1404    USHORT nMatInd;
1405    ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
1406    if (pResMat)
1407    {
1408        for (i = 0; i < nMinC; i++)
1409        {
1410            for (j = 0; j < nMinR; j++)
1411            {
1412                if (pMat1->IsValueOrEmpty(i,j) && pMat2->IsValueOrEmpty(i,j))
1413                    pResMat->PutDouble(pMat1->GetDouble(i,j) /
1414                                       pMat2->GetDouble(i,j), i, j);
1415                else
1416                    pResMat->PutString(ScGlobal::GetRscString(
1417                                                    STR_NO_VALUE), i, j);
1418            }
1419        }
1420        nRetMat = nMatInd;
1421    }
1422    return pResMat;
1423}
1424
1425ScMatrix* ScInterpreter::MatPow(ScMatrix* pMat1, ScMatrix* pMat2)
1426{
1427    USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
1428    pMat1->GetDimensions(nC1, nR1);
1429    pMat2->GetDimensions(nC2, nR2);
1430    if (nC1 < nC2)
1431        nMinC = nC1;
1432    else
1433        nMinC = nC2;
1434    if (nR1 < nR2)
1435        nMinR = nR1;
1436    else
1437        nMinR = nR2;
1438    USHORT nMatInd;
1439    ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
1440    if (pResMat)
1441    {
1442        for (i = 0; i < nMinC; i++)
1443        {
1444            for (j = 0; j < nMinR; j++)
1445            {
1446                if (pMat1->IsValueOrEmpty(i,j) && pMat2->IsValueOrEmpty(i,j))
1447                    pResMat->PutDouble(pow(pMat1->GetDouble(i,j),
1448                                           pMat2->GetDouble(i,j)), i, j);
1449                else
1450                    pResMat->PutString(ScGlobal::GetRscString(
1451                                                    STR_NO_VALUE), i, j);
1452            }
1453        }
1454        nRetMat = nMatInd;
1455    }
1456    return pResMat;
1457}
1458
1459ScMatrix* ScInterpreter::MatConcat(ScMatrix* pMat1, ScMatrix* pMat2)
1460{
1461    USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
1462    pMat1->GetDimensions(nC1, nR1);
1463    pMat2->GetDimensions(nC2, nR2);
1464    if (nC1 < nC2)
1465        nMinC = nC1;
1466    else
1467        nMinC = nC2;
1468    if (nR1 < nR2)
1469        nMinR = nR1;
1470    else
1471        nMinR = nR2;
1472    USHORT nMatInd;
1473    ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
1474    if (pResMat)
1475    {
1476        for (i = 0; i < nMinC; i++)
1477        {
1478            for (j = 0; j < nMinR; j++)
1479            {
1480                if (pMat1->IsString(i,j) && pMat2->IsString(i,j))
1481                {
1482                    String aTmp( pMat1->GetString(i,j) );
1483                    aTmp += pMat2->GetString(i,j);
1484                    pResMat->PutString( aTmp , i, j);
1485                }
1486      

Large files files are truncated, but you can click here to view the full file