Improve performance for loop and insertion
[scilab.git] / scilab / modules / ast / src / cpp / types / implicitlist.cpp
index a20ff2d..a813a52 100644 (file)
@@ -16,6 +16,7 @@
 #include "implicitlist.hxx"
 #include "int.hxx"
 #include "configvariable.hxx"
+#include "scilabWrite.hxx"
 
 #ifndef NDEBUG
 #include "inspector.hxx"
@@ -30,12 +31,6 @@ extern "C"
 #include "finite.h"
 }
 
-/* ISNAN overloading for Mac OS X */
-#ifdef __APPLE__
-#undef ISNAN
-#define ISNAN std::isnan
-#endif
-
 std::wstring printInLinePoly(types::SinglePoly* _pPoly, std::wstring _stVar);
 std::wstring printDouble(types::Double* _pD);
 long long convert_input(types::InternalType* _poIT);
@@ -50,32 +45,23 @@ ImplicitList::~ImplicitList()
         if (m_poStart)
         {
             m_poStart->DecreaseRef();
-            if (m_poStart->isDeletable())
-            {
-                delete m_poStart;
-            }
+            m_poStart->killMe();
         }
 
         if (m_poStep)
         {
             m_poStep->DecreaseRef();
-            if (m_poStep->isDeletable())
-            {
-                delete m_poStep;
-            }
+            m_poStep->killMe();
         }
 
         if (m_poEnd)
         {
             m_poEnd->DecreaseRef();
-            if (m_poEnd->isDeletable())
-            {
-                delete m_poEnd;
-            }
+            m_poEnd->killMe();
         }
     }
 #ifndef NDEBUG
-    //Inspector::removeItem(this);
+    Inspector::removeItem(this);
 #endif
 }
 
@@ -92,7 +78,7 @@ ImplicitList::ImplicitList()
     m_pDblEnd   = NULL;
 
 #ifndef NDEBUG
-    //Inspector::addItem(this);
+    Inspector::addItem(this);
 #endif
 }
 
@@ -113,7 +99,7 @@ ImplicitList::ImplicitList(InternalType* _poStart, InternalType* _poStep, Intern
     setEnd(_poEnd);
     compute();
 #ifndef NDEBUG
-    //Inspector::addItem(this);
+    Inspector::addItem(this);
 #endif
 }
 
@@ -143,11 +129,8 @@ void ImplicitList::setStart(InternalType *_poIT)
     {
         //clear previous value
         m_poStart->DecreaseRef();
-        if (m_poStart->isDeletable())
-        {
-            delete m_poStart;
-            m_poStart = NULL;
-        }
+        m_poStart->killMe();
+        m_poStart = NULL;
     }
 
     m_poStart = _poIT;
@@ -165,11 +148,8 @@ void ImplicitList::setStep(InternalType *_poIT)
     {
         //clear previous value
         m_poStep->DecreaseRef();
-        if (m_poStep->isDeletable())
-        {
-            delete m_poStep;
-            m_poStep = NULL;
-        }
+        m_poStep->killMe();
+        m_poStep = NULL;
     }
 
     m_poStep = _poIT;
@@ -187,11 +167,8 @@ void ImplicitList::setEnd(InternalType* _poIT)
     {
         //clear previous value
         m_poEnd->DecreaseRef();
-        if (m_poEnd->isDeletable())
-        {
-            delete m_poEnd;
-            m_poEnd = NULL;
-        }
+        m_poEnd->killMe();
+        m_poEnd = NULL;
     }
 
     m_poEnd = _poIT;
@@ -237,8 +214,8 @@ bool ImplicitList::compute()
             // no finite values
             if ( finite(dblStart) == 0 || finite(dblStep) == 0 || finite(dblEnd) == 0)
             {
-                if (dblStep > 0 && dblStart < dblEnd ||
-                        dblStep < 0 && dblStart > dblEnd)
+                if ((dblStep > 0 && dblStart < dblEnd) ||
+                        (dblStep < 0 && dblStart > dblEnd))
                 {
                     // return nan
                     m_iSize = -1;
@@ -258,7 +235,7 @@ bool ImplicitList::compute()
 
             double dblVal = dblStart; // temp value
             double dblEps = getRelativeMachinePrecision();
-            double dblPrec = 2 * Max(fabs(dblStart), fabs(dblEnd)) * dblEps;
+            double dblPrec = 2 * std::max(fabs(dblStart), fabs(dblEnd)) * dblEps;
 
             while (dblStep * (dblVal - dblEnd) <= 0)
             {
@@ -270,25 +247,6 @@ bool ImplicitList::compute()
             {
                 m_iSize++;
             }
-
-            //if(dblStep > 0)
-            //{
-            //    m_iSize = static_cast<int>(floor((dblEnd - dblStart) / dblStep)) + 1;
-            //}
-            //else if(dblStep < 0)
-            //{
-            //    m_iSize = static_cast<int>(floor((dblStart - dblEnd) / -dblStep)) + 1;
-            //}
-            //else
-            //{
-            //    m_iSize = 0;
-            //}
-
-            //if(m_iSize < 0)
-            //{
-            //    m_iSize = 0;
-            //}
-            //                m_iSize = static_cast<long long>(floor(fabs(dblEnd - dblStart) / fabs(dblStep))) + 1;
         }
         else //m_eOutType == ScilabInt
         {
@@ -374,7 +332,10 @@ bool ImplicitList::toString(std::wostringstream& ostr)
 {
     if (isComputable())
     {
-        return extractFullMatrix()->toString(ostr);
+        types::InternalType* pIT = extractFullMatrix();
+        bool ret = pIT->toString(ostr);
+        delete pIT;
+        return ret;
     }
     else
     {
@@ -425,72 +386,101 @@ InternalType::ScilabType ImplicitList::getOutputType()
     return m_eOutType;
 }
 
-double ImplicitList::extractValueInDouble(int _iOccur)
+void ImplicitList::extractValueAsDouble(int _iOccur, Double* d)
 {
-    double dblStart            = m_pDblStart->get(0);
-    double dblStep             = m_pDblStep->get(0);
-    return dblStart + _iOccur * dblStep;
+    double dblStart = m_pDblStart->get(0);
+    double dblStep = m_pDblStep->get(0);
+    d->get()[0] = dblStart + _iOccur * dblStep;
 }
 
-long long ImplicitList::extractValueInInteger(int _iOccur)
+template<typename T>
+void ImplicitList::extractValueAsInteger(int _iOccur, T* val)
 {
-    return convert_input(m_poStart) + _iOccur * convert_input(m_poStep);
+
+    val->get()[0] = static_cast<typename T::type>(convert_input(m_poStart)) +
+                    _iOccur * static_cast<typename T::type>(convert_input(m_poStep));
 }
 
-unsigned long long ImplicitList::extractValueInUnsignedInteger(int _iOccur)
+template<typename T>
+void ImplicitList::extractValueAsUnsignedInteger(int _iOccur, T* val)
 {
-    return convert_unsigned_input(m_poStart) + _iOccur * convert_unsigned_input(m_poStep);
+    val->get()[0] = static_cast<typename T::type>(convert_unsigned_input(m_poStart)) +
+                    _iOccur * static_cast<typename T::type>(convert_unsigned_input(m_poStep));
 }
 
-//extract single value in a InternalType
-InternalType* ImplicitList::extractValue(int _iOccur)
+InternalType* ImplicitList::getInitalType()
 {
-    InternalType* pIT = NULL;
     if (compute())
     {
-        long long llVal             = extractValueInInteger(_iOccur);
-        unsigned long long ullVal   = extractValueInUnsignedInteger(_iOccur);
-        if (m_eOutType == ScilabInt8)
-        {
-            pIT        = new Int8((char)llVal);
-        }
-        else if (m_eOutType == ScilabUInt8)
-        {
-            pIT        = new UInt8((unsigned char)ullVal);
+        int iDims = 2;
+        int piDms[2] = {1, 1};
+        switch (m_eOutType)
+        {
+            case ScilabDouble:
+                return new Double(iDims, piDms);
+            case ScilabInt8:
+                return new Int8(iDims, piDms);
+            case ScilabInt16:
+                return new Int16(iDims, piDms);
+            case ScilabInt32:
+                return new Int32(iDims, piDms);
+            case ScilabInt64:
+                return new Int64(iDims, piDms);
+            case ScilabUInt8:
+                return new UInt8(iDims, piDms);
+            case ScilabUInt16:
+                return new UInt16(iDims, piDms);
+            case ScilabUInt32:
+                return new UInt32(iDims, piDms);
+            case ScilabUInt64:
+                return new UInt64(iDims, piDms);
         }
-        else if (m_eOutType == ScilabInt16)
-        {
-            pIT        = new Int16((short)llVal);
-        }
-        else if (m_eOutType == ScilabUInt16)
-        {
-            pIT        = new UInt16((unsigned short)ullVal);
-        }
-        else if (m_eOutType == ScilabInt32)
-        {
-            pIT        = new Int32((int)llVal);
-        }
-        else if (m_eOutType == ScilabUInt32)
-        {
-            pIT        = new UInt32((unsigned int)ullVal);
-        }
-        else if (m_eOutType == ScilabInt64)
-        {
-            pIT        = new Int64((long long)llVal);
-        }
-        else if (m_eOutType == ScilabUInt64)
-        {
-            pIT        = new UInt64((unsigned long long)ullVal);
-        }
-        else //ScilabDouble
-        {
-            double dblStart = m_poStart->getAs<Double>()->getReal(0, 0);
-            double dblStep  = m_poStep->getAs<Double>()->getReal(0, 0);
-            Double* pD      = new Double(dblStart + _iOccur * dblStep);
-            pIT = pD;
+    }
+
+    return nullptr;
+}
+
+//extract single value in a InternalType
+void ImplicitList::extractValue(int _iOccur, InternalType* pIT)
+{
+    if (pIT == nullptr)
+    {
+        return;
+    }
+
+    if (compute())
+    {
+        switch (m_eOutType)
+        {
+            case ScilabInt8:
+                extractValueAsInteger(_iOccur, pIT->getAs<Int8>());
+                break;
+            case ScilabInt16:
+                extractValueAsInteger(_iOccur, pIT->getAs<Int16>());
+                break;
+            case ScilabInt32:
+                extractValueAsInteger(_iOccur, pIT->getAs<Int32>());
+                break;
+            case ScilabInt64:
+                extractValueAsInteger(_iOccur, pIT->getAs<Int64>());
+                break;
+            case ScilabUInt8:
+                extractValueAsUnsignedInteger(_iOccur, pIT->getAs<UInt8>());
+                break;
+            case ScilabUInt16:
+                extractValueAsUnsignedInteger(_iOccur, pIT->getAs<UInt16>());
+                break;
+            case ScilabUInt32:
+                extractValueAsUnsignedInteger(_iOccur, pIT->getAs<UInt32>());
+                break;
+            case ScilabUInt64:
+                extractValueAsUnsignedInteger(_iOccur, pIT->getAs<UInt64>());
+                break;
+            case ScilabDouble:
+                extractValueAsDouble(_iOccur, pIT->getAs<Double>());
+                break;
         }
     }
-    return pIT;
 }
 
 //extract matrix in a Internaltype
@@ -512,72 +502,74 @@ InternalType* ImplicitList::extractFullMatrix()
         else if (m_eOutType == ScilabDouble)
         {
             pIT = new Double(1, m_iSize);
-            extractFullMatrix(pIT->getAs<Double>()->get());
+            extractFullMatrix(pIT->getAs<Double>());
         }
         else if (m_eOutType == ScilabInt8)
         {
             pIT        = new Int8(1, m_iSize);
-            extractFullMatrix(pIT->getAs<Int8>()->get());
+            extractFullMatrix(pIT->getAs<Int8>());
         }
         else if (m_eOutType == ScilabUInt8)
         {
             pIT        = new UInt8(1, m_iSize);
-            extractFullMatrix(pIT->getAs<UInt8>()->get());
+            extractFullMatrix(pIT->getAs<UInt8>());
         }
         else if (m_eOutType == ScilabInt16)
         {
             pIT        = new Int16(1, m_iSize);
-            extractFullMatrix(pIT->getAs<Int16>()->get());
+            extractFullMatrix(pIT->getAs<Int16>());
         }
         else if (m_eOutType == ScilabUInt16)
         {
             pIT        = new UInt16(1, m_iSize);
-            extractFullMatrix(pIT->getAs<UInt16>()->get());
+            extractFullMatrix(pIT->getAs<UInt16>());
         }
         else if (m_eOutType == ScilabInt32)
         {
             pIT        = new Int32(1, m_iSize);
-            extractFullMatrix(pIT->getAs<Int32>()->get());
+            extractFullMatrix(pIT->getAs<Int32>());
         }
         else if (m_eOutType == ScilabUInt32)
         {
             pIT        = new UInt32(1, m_iSize);
-            extractFullMatrix(pIT->getAs<UInt32>()->get());
+            extractFullMatrix(pIT->getAs<UInt32>());
         }
         else if (m_eOutType == ScilabInt64)
         {
             pIT        = new Int64(1, m_iSize);
-            extractFullMatrix(pIT->getAs<Int64>()->get());
+            extractFullMatrix(pIT->getAs<Int64>());
         }
         else if (m_eOutType == ScilabUInt64)
         {
             pIT        = new UInt64(1, m_iSize);
-            extractFullMatrix(pIT->getAs<UInt64>()->get());
+            extractFullMatrix(pIT->getAs<UInt64>());
         }
     }
     return pIT;
 }
 
-void ImplicitList::extractFullMatrix(double *_pdbl)
+void ImplicitList::extractFullMatrix(Double *_p)
 {
     double dblStart = m_poStart->getAs<Double>()->get(0);
     double dblStep  = m_poStep->getAs<Double>()->get(0);
 
+    double* p = _p->get();
     for (int i = 0 ; i < m_iSize ; i++)
     {
-        _pdbl[i] = dblStart + i * dblStep;
+        p[i] = dblStart + i * dblStep;
     }
 }
 
 template<typename T>
 void ImplicitList::extractFullMatrix(T *_pT)
 {
-    T tStart = static_cast<T>(convert_input(m_poStart));
-    T tStep    = static_cast<T>(convert_input(m_poStep));
+    typename T::type tStart = static_cast<typename T::type>(convert_input(m_poStart));
+    typename T::type tStep = static_cast<typename T::type>(convert_input(m_poStep));
 
+    typename T::type* p = _pT->get();
     for (int i = 0 ; i < m_iSize ; i++)
     {
-        _pT[i] = tStart + i * tStep;
+        p[i] = tStart + i * tStep;
     }
 }
 
@@ -587,7 +579,7 @@ bool ImplicitList::transpose(InternalType *& out)
     {
         Double * pIT = new Double(m_iSize, 1);
         out = pIT;
-        extractFullMatrix(pIT->get());
+        extractFullMatrix(pIT);
 
         return true;
     }
@@ -608,23 +600,124 @@ bool ImplicitList::neg(InternalType *& out)
     return false;
 }
 
+bool ImplicitList::invoke(typed_list & in, optional_list & /*opt*/, int /*_iRetCount*/, typed_list & out, ast::ConstVisitor & /*execFunc*/, const ast::Exp & e)
+{
+    if (in.size() == 0)
+    {
+        out.push_back(this);
+    }
+    else
+    {
+        InternalType * _out = extract(&in);
+        if (!_out)
+        {
+            std::wostringstream os;
+            os << _W("Invalid index.\n");
+            throw ast::ScilabError(os.str(), 999, e.getLocation());
+        }
+        out.push_back(_out);
+    }
+
+    return true;
+}
+
+InternalType* ImplicitList::extract(typed_list* _pArgs)
+{
+    int iDims = (int)_pArgs->size();
+    typed_list pArg;
+    InternalType* pOut = NULL;
+    int index = 0;
+
+    int* piMaxDim = new int[iDims];
+    int* piCountDim = new int[iDims];
+
+    //evaluate each argument and replace by appropriate value and compute the count of combinations
+    int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
+    if (iSeqCount == 0)
+    {
+        //free pArg content
+        cleanIndexesArguments(_pArgs, &pArg);
+        return createEmptyDouble();
+    }
+
+    if (iDims == 1 && iSeqCount == 1)
+    {
+        if (piMaxDim[0] > 0 && piMaxDim[0] <= 3)
+        {
+            //standard case a(1)
+            Double* pDbl = pArg[0]->getAs<Double>();
+            index = (int)pDbl->get()[0] - 1;
+        }
+        else
+        {
+            index = 0;
+        }
+    }
+    else
+    {
+        int* piDims = new int[iDims];
+        for (int i = 0 ; i < iDims ; i++)
+        {
+            piDims[i] = 1;
+        }
+
+        for (int i = 0 ; i < iSeqCount ; i++)
+        {
+            int* pIndex = new int[iDims];
+            for (int j = 0 ; j < iDims ; j++)
+            {
+                Double* pDbl = pArg[j]->getAs<Double>();
+                pIndex[j] = (int)pDbl->get()[i] - 1;
+            }
+
+            index = getIndexWithDims(pIndex, piDims, iDims);
+        }
+    }
+
+    switch (index)
+    {
+        case 0 :
+            pOut = getStart();
+            break;
+        case 1 :
+            pOut = getStep();
+            break;
+        case 2 :
+            pOut = getEnd();
+            break;
+        default :
+            pOut = NULL;
+            break;
+    }
+
+    //free pArg content
+    cleanIndexesArguments(_pArgs, &pArg);
+
+    delete[] piMaxDim;
+    delete[] piCountDim;
+    return pOut;
+}
 }
 
 std::wstring printInLinePoly(types::SinglePoly* _pPoly, std::wstring _stVar)
 {
     std::wostringstream ostr;
-    for (int i = 0 ; i < _pPoly->getRank() ; i++)
+    double* pdblIn = _pPoly->get();
+    for (int i = 0 ; i < _pPoly->getSize() ; i++)
     {
-        double dbl = _pPoly->getCoef()->getReal()[i];
-        if (dbl != 0)
+
+        if (pdblIn[i] != 0)
         {
             DoubleFormat df;
-            getDoubleFormat(dbl, &df);
+            getDoubleFormat(pdblIn[i], &df);
             df.bPrintPoint = ostr.str().size() != 0;
             df.bPrintPlusSign = true;
             df.bPrintOne = i == 0;
             df.bPaddSign = false;
-            addDoubleValue(&ostr, dbl, &df);
+            df.bPrintBlank = false;
+            df.bPrintPlusSign = false;
+
+            addDoubleValue(&ostr, pdblIn[i], &df);
             if (i != 0)
             {
                 ostr << _stVar;
@@ -643,85 +736,66 @@ std::wstring printDouble(types::Double* _pD)
     std::wostringstream ostr;
     DoubleFormat df;
     getDoubleFormat(_pD->get(0), &df);
+    df.bPrintPoint = false;
     df.bPaddSign = true;
+    df.bPaddSign = false;
+    df.bPrintBlank = false;
     addDoubleValue(&ostr, _pD->get(0), &df);
     return ostr.str();
 }
 
 long long convert_input(types::InternalType* _poIT)
 {
-    long long llValue = 0;
     switch (_poIT->getType())
     {
-        case types::GenericType::ScilabDouble :
-            llValue = static_cast<long long>(_poIT->getAs<types::Double>()->get(0));
-            break;
-        case types::GenericType::ScilabInt8 :
-            llValue = static_cast<long long>(_poIT->getAs<types::Int8>()->get(0));
-            break;
-        case types::GenericType::ScilabUInt8 :
-            llValue = static_cast<long long>(_poIT->getAs<types::UInt8>()->get(0));
-            break;
-        case types::GenericType::ScilabInt16 :
-            llValue = static_cast<long long>(_poIT->getAs<types::Int16>()->get(0));
-            break;
-        case types::GenericType::ScilabUInt16 :
-            llValue = static_cast<long long>(_poIT->getAs<types::UInt16>()->get(0));
-            break;
-        case types::GenericType::ScilabInt32 :
-            llValue = static_cast<long long>(_poIT->getAs<types::Int32>()->get(0));
-            break;
-        case types::GenericType::ScilabUInt32 :
-            llValue = static_cast<long long>(_poIT->getAs<types::UInt32>()->get(0));
-            break;
-        case types::GenericType::ScilabInt64 :
-            llValue = static_cast<long long>(_poIT->getAs<types::Int64>()->get(0));
-            break;
-        case types::GenericType::ScilabUInt64 :
-            llValue = static_cast<long long>(_poIT->getAs<types::UInt64>()->get(0));
-            break;
+        case types::InternalType::ScilabDouble:
+            return static_cast<long long>(_poIT->getAs<types::Double>()->get(0));
+        case types::InternalType::ScilabInt8:
+            return static_cast<long long>(_poIT->getAs<types::Int8>()->get(0));
+        case types::InternalType::ScilabUInt8:
+            return static_cast<long long>(_poIT->getAs<types::UInt8>()->get(0));
+        case types::InternalType::ScilabInt16:
+            return static_cast<long long>(_poIT->getAs<types::Int16>()->get(0));
+        case types::InternalType::ScilabUInt16:
+            return static_cast<long long>(_poIT->getAs<types::UInt16>()->get(0));
+        case types::InternalType::ScilabInt32:
+            return static_cast<long long>(_poIT->getAs<types::Int32>()->get(0));
+        case types::InternalType::ScilabUInt32:
+            return static_cast<long long>(_poIT->getAs<types::UInt32>()->get(0));
+        case types::InternalType::ScilabInt64:
+            return static_cast<long long>(_poIT->getAs<types::Int64>()->get(0));
+        case types::InternalType::ScilabUInt64:
+            return static_cast<long long>(_poIT->getAs<types::UInt64>()->get(0));
         default:
-            // FIXME : Trigger an error ??
-            break;
+            return 0;
     }
-    return llValue;
+    return 0;
 }
 
 unsigned long long convert_unsigned_input(types::InternalType* _poIT)
 {
-    unsigned long long ullValue = 0;
     switch (_poIT->getType())
     {
-        case types::GenericType::ScilabDouble :
-            ullValue = static_cast<unsigned long long>(_poIT->getAs<types::Double>()->get(0));
-            break;
-        case types::GenericType::ScilabInt8 :
-            ullValue = static_cast<unsigned long long>(_poIT->getAs<types::Int8>()->get(0));
-            break;
-        case types::GenericType::ScilabUInt8 :
-            ullValue = static_cast<unsigned long long>(_poIT->getAs<types::UInt8>()->get(0));
-            break;
-        case types::GenericType::ScilabInt16 :
-            ullValue = static_cast<unsigned long long>(_poIT->getAs<types::Int16>()->get(0));
-            break;
-        case types::GenericType::ScilabUInt16 :
-            ullValue = static_cast<unsigned long long>(_poIT->getAs<types::UInt16>()->get(0));
-            break;
-        case types::GenericType::ScilabInt32 :
-            ullValue = static_cast<unsigned long long>(_poIT->getAs<types::Int32>()->get(0));
-            break;
-        case types::GenericType::ScilabUInt32 :
-            ullValue = static_cast<unsigned long long>(_poIT->getAs<types::UInt32>()->get(0));
-            break;
-        case types::GenericType::ScilabInt64 :
-            ullValue = static_cast<unsigned long long>(_poIT->getAs<types::Int64>()->get(0));
-            break;
-        case types::GenericType::ScilabUInt64 :
-            ullValue = static_cast<unsigned long long>(_poIT->getAs<types::UInt64>()->get(0));
-            break;
+        case types::InternalType::ScilabDouble:
+            return static_cast<unsigned long long>(_poIT->getAs<types::Double>()->get(0));
+        case types::InternalType::ScilabInt8:
+            return static_cast<unsigned long long>(_poIT->getAs<types::Int8>()->get(0));
+        case types::InternalType::ScilabUInt8:
+            return static_cast<unsigned long long>(_poIT->getAs<types::UInt8>()->get(0));
+        case types::InternalType::ScilabInt16:
+            return static_cast<unsigned long long>(_poIT->getAs<types::Int16>()->get(0));
+        case types::InternalType::ScilabUInt16:
+            return static_cast<unsigned long long>(_poIT->getAs<types::UInt16>()->get(0));
+        case types::InternalType::ScilabInt32:
+            return static_cast<unsigned long long>(_poIT->getAs<types::Int32>()->get(0));
+        case types::InternalType::ScilabUInt32:
+            return static_cast<unsigned long long>(_poIT->getAs<types::UInt32>()->get(0));
+        case types::InternalType::ScilabInt64:
+            return static_cast<unsigned long long>(_poIT->getAs<types::Int64>()->get(0));
+        case types::InternalType::ScilabUInt64:
+            return static_cast<unsigned long long>(_poIT->getAs<types::UInt64>()->get(0));
         default:
-            // FIXME : Trigger an error ??
-            break;
+            return 0;
     }
-    return ullValue;
+    return 0;
 }