LCOV - code coverage report
Current view: top level - synthesis/MeasurementEquations/lbfgs - alglibinternal.cc (source / functions) Hit Total Coverage
Test: ctest_coverage.info Lines: 235 5817 4.0 %
Date: 2023-11-06 10:06:49 Functions: 9 357 2.5 %

          Line data    Source code
       1             : /*************************************************************************
       2             : ALGLIB 3.17.0 (source code generated 2020-12-27)
       3             : Copyright (c) Sergey Bochkanov (ALGLIB project).
       4             : 
       5             : >>> SOURCE LICENSE >>>
       6             : This program is free software; you can redistribute it and/or modify
       7             : it under the terms of the GNU General Public License as published by
       8             : the Free Software Foundation (www.fsf.org); either version 2 of the 
       9             : License, or (at your option) any later version.
      10             : 
      11             : This program is distributed in the hope that it will be useful,
      12             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : GNU General Public License for more details.
      15             : 
      16             : A copy of the GNU General Public License is available at
      17             : http://www.fsf.org/licensing/licenses
      18             : >>> END OF LICENSE >>>
      19             : *************************************************************************/
      20             : #ifdef _MSC_VER
      21             : #define _CRT_SECURE_NO_WARNINGS
      22             : #endif
      23             : #include "stdafx.h"
      24             : #include "alglibinternal.h"
      25             : 
      26             : // disable some irrelevant warnings
      27             : #if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS)
      28             : #pragma warning(disable:4100)
      29             : #pragma warning(disable:4127)
      30             : #pragma warning(disable:4611)
      31             : #pragma warning(disable:4702)
      32             : #pragma warning(disable:4996)
      33             : #endif
      34             : 
      35             : /////////////////////////////////////////////////////////////////////////
      36             : //
      37             : // THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE
      38             : //
      39             : /////////////////////////////////////////////////////////////////////////
      40             : namespace alglib
      41             : {
      42             : 
      43             : 
      44             : }
      45             : 
      46             : /////////////////////////////////////////////////////////////////////////
      47             : //
      48             : // THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE
      49             : //
      50             : /////////////////////////////////////////////////////////////////////////
      51             : namespace alglib_impl
      52             : {
      53             : #if defined(AE_COMPILE_SCODES) || !defined(AE_PARTIAL_BUILD)
      54             : 
      55             : 
      56             : #endif
      57             : #if defined(AE_COMPILE_APSERV) || !defined(AE_PARTIAL_BUILD)
      58             : 
      59             : 
      60             : #endif
      61             : #if defined(AE_COMPILE_TSORT) || !defined(AE_PARTIAL_BUILD)
      62             : static void tsort_tagsortfastirec(/* Real    */ ae_vector* a,
      63             :      /* Integer */ ae_vector* b,
      64             :      /* Real    */ ae_vector* bufa,
      65             :      /* Integer */ ae_vector* bufb,
      66             :      ae_int_t i1,
      67             :      ae_int_t i2,
      68             :      ae_state *_state);
      69             : static void tsort_tagsortfastrrec(/* Real    */ ae_vector* a,
      70             :      /* Real    */ ae_vector* b,
      71             :      /* Real    */ ae_vector* bufa,
      72             :      /* Real    */ ae_vector* bufb,
      73             :      ae_int_t i1,
      74             :      ae_int_t i2,
      75             :      ae_state *_state);
      76             : static void tsort_tagsortfastrec(/* Real    */ ae_vector* a,
      77             :      /* Real    */ ae_vector* bufa,
      78             :      ae_int_t i1,
      79             :      ae_int_t i2,
      80             :      ae_state *_state);
      81             : 
      82             : 
      83             : #endif
      84             : #if defined(AE_COMPILE_ABLASF) || !defined(AE_PARTIAL_BUILD)
      85             : 
      86             : 
      87             : #endif
      88             : #if defined(AE_COMPILE_ABLASMKL) || !defined(AE_PARTIAL_BUILD)
      89             : 
      90             : 
      91             : #endif
      92             : #if defined(AE_COMPILE_CREFLECTIONS) || !defined(AE_PARTIAL_BUILD)
      93             : 
      94             : 
      95             : #endif
      96             : #if defined(AE_COMPILE_ROTATIONS) || !defined(AE_PARTIAL_BUILD)
      97             : 
      98             : 
      99             : #endif
     100             : #if defined(AE_COMPILE_TRLINSOLVE) || !defined(AE_PARTIAL_BUILD)
     101             : 
     102             : 
     103             : #endif
     104             : #if defined(AE_COMPILE_SAFESOLVE) || !defined(AE_PARTIAL_BUILD)
     105             : static ae_bool safesolve_cbasicsolveandupdate(ae_complex alpha,
     106             :      ae_complex beta,
     107             :      double lnmax,
     108             :      double bnorm,
     109             :      double maxgrowth,
     110             :      double* xnorm,
     111             :      ae_complex* x,
     112             :      ae_state *_state);
     113             : 
     114             : 
     115             : #endif
     116             : #if defined(AE_COMPILE_HBLAS) || !defined(AE_PARTIAL_BUILD)
     117             : 
     118             : 
     119             : #endif
     120             : #if defined(AE_COMPILE_SBLAS) || !defined(AE_PARTIAL_BUILD)
     121             : 
     122             : 
     123             : #endif
     124             : #if defined(AE_COMPILE_BLAS) || !defined(AE_PARTIAL_BUILD)
     125             : 
     126             : 
     127             : #endif
     128             : #if defined(AE_COMPILE_LINMIN) || !defined(AE_PARTIAL_BUILD)
     129             : static double linmin_ftol = 0.001;
     130             : static double linmin_xtol = 100*ae_machineepsilon;
     131             : static ae_int_t linmin_maxfev = 20;
     132             : static double linmin_stpmin = 1.0E-50;
     133             : static double linmin_defstpmax = 1.0E+50;
     134             : static double linmin_armijofactor = 1.3;
     135             : static void linmin_mcstep(double* stx,
     136             :      double* fx,
     137             :      double* dx,
     138             :      double* sty,
     139             :      double* fy,
     140             :      double* dy,
     141             :      double* stp,
     142             :      double fp,
     143             :      double dp,
     144             :      ae_bool* brackt,
     145             :      double stmin,
     146             :      double stmax,
     147             :      ae_int_t* info,
     148             :      ae_state *_state);
     149             : 
     150             : 
     151             : #endif
     152             : #if defined(AE_COMPILE_XBLAS) || !defined(AE_PARTIAL_BUILD)
     153             : static void xblas_xsum(/* Real    */ ae_vector* w,
     154             :      double mx,
     155             :      ae_int_t n,
     156             :      double* r,
     157             :      double* rerr,
     158             :      ae_state *_state);
     159             : static double xblas_xfastpow(double r, ae_int_t n, ae_state *_state);
     160             : 
     161             : 
     162             : #endif
     163             : #if defined(AE_COMPILE_BASICSTATOPS) || !defined(AE_PARTIAL_BUILD)
     164             : 
     165             : 
     166             : #endif
     167             : #if defined(AE_COMPILE_HPCCORES) || !defined(AE_PARTIAL_BUILD)
     168             : static ae_bool hpccores_hpcpreparechunkedgradientx(/* Real    */ ae_vector* weights,
     169             :      ae_int_t wcount,
     170             :      /* Real    */ ae_vector* hpcbuf,
     171             :      ae_state *_state);
     172             : static ae_bool hpccores_hpcfinalizechunkedgradientx(/* Real    */ ae_vector* buf,
     173             :      ae_int_t wcount,
     174             :      /* Real    */ ae_vector* grad,
     175             :      ae_state *_state);
     176             : 
     177             : 
     178             : #endif
     179             : #if defined(AE_COMPILE_NTHEORY) || !defined(AE_PARTIAL_BUILD)
     180             : static ae_bool ntheory_isprime(ae_int_t n, ae_state *_state);
     181             : static ae_int_t ntheory_modmul(ae_int_t a,
     182             :      ae_int_t b,
     183             :      ae_int_t n,
     184             :      ae_state *_state);
     185             : static ae_int_t ntheory_modexp(ae_int_t a,
     186             :      ae_int_t b,
     187             :      ae_int_t n,
     188             :      ae_state *_state);
     189             : 
     190             : 
     191             : #endif
     192             : #if defined(AE_COMPILE_FTBASE) || !defined(AE_PARTIAL_BUILD)
     193             : static ae_int_t ftbase_coltype = 0;
     194             : static ae_int_t ftbase_coloperandscnt = 1;
     195             : static ae_int_t ftbase_coloperandsize = 2;
     196             : static ae_int_t ftbase_colmicrovectorsize = 3;
     197             : static ae_int_t ftbase_colparam0 = 4;
     198             : static ae_int_t ftbase_colparam1 = 5;
     199             : static ae_int_t ftbase_colparam2 = 6;
     200             : static ae_int_t ftbase_colparam3 = 7;
     201             : static ae_int_t ftbase_colscnt = 8;
     202             : static ae_int_t ftbase_opend = 0;
     203             : static ae_int_t ftbase_opcomplexreffft = 1;
     204             : static ae_int_t ftbase_opbluesteinsfft = 2;
     205             : static ae_int_t ftbase_opcomplexcodeletfft = 3;
     206             : static ae_int_t ftbase_opcomplexcodelettwfft = 4;
     207             : static ae_int_t ftbase_opradersfft = 5;
     208             : static ae_int_t ftbase_opcomplextranspose = -1;
     209             : static ae_int_t ftbase_opcomplexfftfactors = -2;
     210             : static ae_int_t ftbase_opstart = -3;
     211             : static ae_int_t ftbase_opjmp = -4;
     212             : static ae_int_t ftbase_opparallelcall = -5;
     213             : static ae_int_t ftbase_maxradix = 6;
     214             : static ae_int_t ftbase_updatetw = 16;
     215             : static ae_int_t ftbase_recursivethreshold = 1024;
     216             : static ae_int_t ftbase_raderthreshold = 19;
     217             : static ae_int_t ftbase_ftbasecodeletrecommended = 5;
     218             : static double ftbase_ftbaseinefficiencyfactor = 1.3;
     219             : static ae_int_t ftbase_ftbasemaxsmoothfactor = 5;
     220             : static void ftbase_ftdeterminespacerequirements(ae_int_t n,
     221             :      ae_int_t* precrsize,
     222             :      ae_int_t* precisize,
     223             :      ae_state *_state);
     224             : static void ftbase_ftcomplexfftplanrec(ae_int_t n,
     225             :      ae_int_t k,
     226             :      ae_bool childplan,
     227             :      ae_bool topmostplan,
     228             :      ae_int_t* rowptr,
     229             :      ae_int_t* bluesteinsize,
     230             :      ae_int_t* precrptr,
     231             :      ae_int_t* preciptr,
     232             :      fasttransformplan* plan,
     233             :      ae_state *_state);
     234             : static void ftbase_ftpushentry(fasttransformplan* plan,
     235             :      ae_int_t* rowptr,
     236             :      ae_int_t etype,
     237             :      ae_int_t eopcnt,
     238             :      ae_int_t eopsize,
     239             :      ae_int_t emcvsize,
     240             :      ae_int_t eparam0,
     241             :      ae_state *_state);
     242             : static void ftbase_ftpushentry2(fasttransformplan* plan,
     243             :      ae_int_t* rowptr,
     244             :      ae_int_t etype,
     245             :      ae_int_t eopcnt,
     246             :      ae_int_t eopsize,
     247             :      ae_int_t emcvsize,
     248             :      ae_int_t eparam0,
     249             :      ae_int_t eparam1,
     250             :      ae_state *_state);
     251             : static void ftbase_ftpushentry4(fasttransformplan* plan,
     252             :      ae_int_t* rowptr,
     253             :      ae_int_t etype,
     254             :      ae_int_t eopcnt,
     255             :      ae_int_t eopsize,
     256             :      ae_int_t emcvsize,
     257             :      ae_int_t eparam0,
     258             :      ae_int_t eparam1,
     259             :      ae_int_t eparam2,
     260             :      ae_int_t eparam3,
     261             :      ae_state *_state);
     262             : static void ftbase_ftapplysubplan(fasttransformplan* plan,
     263             :      ae_int_t subplan,
     264             :      /* Real    */ ae_vector* a,
     265             :      ae_int_t abase,
     266             :      ae_int_t aoffset,
     267             :      /* Real    */ ae_vector* buf,
     268             :      ae_int_t repcnt,
     269             :      ae_state *_state);
     270             : static void ftbase_ftapplycomplexreffft(/* Real    */ ae_vector* a,
     271             :      ae_int_t offs,
     272             :      ae_int_t operandscnt,
     273             :      ae_int_t operandsize,
     274             :      ae_int_t microvectorsize,
     275             :      /* Real    */ ae_vector* buf,
     276             :      ae_state *_state);
     277             : static void ftbase_ftapplycomplexcodeletfft(/* Real    */ ae_vector* a,
     278             :      ae_int_t offs,
     279             :      ae_int_t operandscnt,
     280             :      ae_int_t operandsize,
     281             :      ae_int_t microvectorsize,
     282             :      ae_state *_state);
     283             : static void ftbase_ftapplycomplexcodelettwfft(/* Real    */ ae_vector* a,
     284             :      ae_int_t offs,
     285             :      ae_int_t operandscnt,
     286             :      ae_int_t operandsize,
     287             :      ae_int_t microvectorsize,
     288             :      ae_state *_state);
     289             : static void ftbase_ftprecomputebluesteinsfft(ae_int_t n,
     290             :      ae_int_t m,
     291             :      /* Real    */ ae_vector* precr,
     292             :      ae_int_t offs,
     293             :      ae_state *_state);
     294             : static void ftbase_ftbluesteinsfft(fasttransformplan* plan,
     295             :      /* Real    */ ae_vector* a,
     296             :      ae_int_t abase,
     297             :      ae_int_t aoffset,
     298             :      ae_int_t operandscnt,
     299             :      ae_int_t n,
     300             :      ae_int_t m,
     301             :      ae_int_t precoffs,
     302             :      ae_int_t subplan,
     303             :      /* Real    */ ae_vector* bufa,
     304             :      /* Real    */ ae_vector* bufb,
     305             :      /* Real    */ ae_vector* bufc,
     306             :      /* Real    */ ae_vector* bufd,
     307             :      ae_state *_state);
     308             : static void ftbase_ftprecomputeradersfft(ae_int_t n,
     309             :      ae_int_t rq,
     310             :      ae_int_t riq,
     311             :      /* Real    */ ae_vector* precr,
     312             :      ae_int_t offs,
     313             :      ae_state *_state);
     314             : static void ftbase_ftradersfft(fasttransformplan* plan,
     315             :      /* Real    */ ae_vector* a,
     316             :      ae_int_t abase,
     317             :      ae_int_t aoffset,
     318             :      ae_int_t operandscnt,
     319             :      ae_int_t n,
     320             :      ae_int_t subplan,
     321             :      ae_int_t rq,
     322             :      ae_int_t riq,
     323             :      ae_int_t precoffs,
     324             :      /* Real    */ ae_vector* buf,
     325             :      ae_state *_state);
     326             : static void ftbase_ftfactorize(ae_int_t n,
     327             :      ae_bool isroot,
     328             :      ae_int_t* n1,
     329             :      ae_int_t* n2,
     330             :      ae_state *_state);
     331             : static ae_int_t ftbase_ftoptimisticestimate(ae_int_t n, ae_state *_state);
     332             : static void ftbase_ffttwcalc(/* Real    */ ae_vector* a,
     333             :      ae_int_t aoffset,
     334             :      ae_int_t n1,
     335             :      ae_int_t n2,
     336             :      ae_state *_state);
     337             : static void ftbase_internalcomplexlintranspose(/* Real    */ ae_vector* a,
     338             :      ae_int_t m,
     339             :      ae_int_t n,
     340             :      ae_int_t astart,
     341             :      /* Real    */ ae_vector* buf,
     342             :      ae_state *_state);
     343             : static void ftbase_ffticltrec(/* Real    */ ae_vector* a,
     344             :      ae_int_t astart,
     345             :      ae_int_t astride,
     346             :      /* Real    */ ae_vector* b,
     347             :      ae_int_t bstart,
     348             :      ae_int_t bstride,
     349             :      ae_int_t m,
     350             :      ae_int_t n,
     351             :      ae_state *_state);
     352             : static void ftbase_fftirltrec(/* Real    */ ae_vector* a,
     353             :      ae_int_t astart,
     354             :      ae_int_t astride,
     355             :      /* Real    */ ae_vector* b,
     356             :      ae_int_t bstart,
     357             :      ae_int_t bstride,
     358             :      ae_int_t m,
     359             :      ae_int_t n,
     360             :      ae_state *_state);
     361             : static void ftbase_ftbasefindsmoothrec(ae_int_t n,
     362             :      ae_int_t seed,
     363             :      ae_int_t leastfactor,
     364             :      ae_int_t* best,
     365             :      ae_state *_state);
     366             : 
     367             : 
     368             : #endif
     369             : #if defined(AE_COMPILE_NEARUNITYUNIT) || !defined(AE_PARTIAL_BUILD)
     370             : 
     371             : 
     372             : #endif
     373             : #if defined(AE_COMPILE_ALGLIBBASICS) || !defined(AE_PARTIAL_BUILD)
     374             : 
     375             : 
     376             : #endif
     377             : 
     378             : #if defined(AE_COMPILE_SCODES) || !defined(AE_PARTIAL_BUILD)
     379             : 
     380             : 
     381           0 : ae_int_t getrdfserializationcode(ae_state *_state)
     382             : {
     383             :     ae_int_t result;
     384             : 
     385             : 
     386           0 :     result = 1;
     387           0 :     return result;
     388             : }
     389             : 
     390             : 
     391           0 : ae_int_t getkdtreeserializationcode(ae_state *_state)
     392             : {
     393             :     ae_int_t result;
     394             : 
     395             : 
     396           0 :     result = 2;
     397           0 :     return result;
     398             : }
     399             : 
     400             : 
     401           0 : ae_int_t getmlpserializationcode(ae_state *_state)
     402             : {
     403             :     ae_int_t result;
     404             : 
     405             : 
     406           0 :     result = 3;
     407           0 :     return result;
     408             : }
     409             : 
     410             : 
     411           0 : ae_int_t getmlpeserializationcode(ae_state *_state)
     412             : {
     413             :     ae_int_t result;
     414             : 
     415             : 
     416           0 :     result = 4;
     417           0 :     return result;
     418             : }
     419             : 
     420             : 
     421           0 : ae_int_t getrbfserializationcode(ae_state *_state)
     422             : {
     423             :     ae_int_t result;
     424             : 
     425             : 
     426           0 :     result = 5;
     427           0 :     return result;
     428             : }
     429             : 
     430             : 
     431           0 : ae_int_t getspline2dserializationcode(ae_state *_state)
     432             : {
     433             :     ae_int_t result;
     434             : 
     435             : 
     436           0 :     result = 6;
     437           0 :     return result;
     438             : }
     439             : 
     440             : 
     441           0 : ae_int_t getidwserializationcode(ae_state *_state)
     442             : {
     443             :     ae_int_t result;
     444             : 
     445             : 
     446           0 :     result = 7;
     447           0 :     return result;
     448             : }
     449             : 
     450             : 
     451           0 : ae_int_t getknnserializationcode(ae_state *_state)
     452             : {
     453             :     ae_int_t result;
     454             : 
     455             : 
     456           0 :     result = 108;
     457           0 :     return result;
     458             : }
     459             : 
     460             : 
     461             : #endif
     462             : #if defined(AE_COMPILE_APSERV) || !defined(AE_PARTIAL_BUILD)
     463             : 
     464             : 
     465             : /*************************************************************************
     466             : Internally calls SetErrorFlag() with condition:
     467             : 
     468             :     Abs(Val-RefVal)>Tol*Max(Abs(RefVal),S)
     469             :     
     470             : This function is used to test relative error in Val against  RefVal,  with
     471             : relative error being replaced by absolute when scale  of  RefVal  is  less
     472             : than S.
     473             : 
     474             : This function returns value of COND.
     475             : *************************************************************************/
     476           0 : void seterrorflagdiff(ae_bool* flag,
     477             :      double val,
     478             :      double refval,
     479             :      double tol,
     480             :      double s,
     481             :      ae_state *_state)
     482             : {
     483             : 
     484             : 
     485           0 :     ae_set_error_flag(flag, ae_fp_greater(ae_fabs(val-refval, _state),tol*ae_maxreal(ae_fabs(refval, _state), s, _state)), __FILE__, __LINE__, "apserv.ap:162");
     486           0 : }
     487             : 
     488             : 
     489             : /*************************************************************************
     490             : The function always returns False.
     491             : It may be used sometimes to prevent spurious warnings.
     492             : 
     493             :   -- ALGLIB --
     494             :      Copyright 17.09.2012 by Bochkanov Sergey
     495             : *************************************************************************/
     496           0 : ae_bool alwaysfalse(ae_state *_state)
     497             : {
     498             :     ae_bool result;
     499             : 
     500             : 
     501           0 :     result = ae_false;
     502           0 :     return result;
     503             : }
     504             : 
     505             : 
     506             : /*************************************************************************
     507             : The function "touches" integer - it is used  to  avoid  compiler  messages
     508             : about unused variables (in rare cases when we do NOT want to remove  these
     509             : variables).
     510             : 
     511             :   -- ALGLIB --
     512             :      Copyright 17.09.2012 by Bochkanov Sergey
     513             : *************************************************************************/
     514           0 : void touchint(ae_int_t* a, ae_state *_state)
     515             : {
     516             : 
     517             : 
     518           0 : }
     519             : 
     520             : 
     521             : /*************************************************************************
     522             : The function "touches" real   -  it is used  to  avoid  compiler  messages
     523             : about unused variables (in rare cases when we do NOT want to remove  these
     524             : variables).
     525             : 
     526             :   -- ALGLIB --
     527             :      Copyright 17.09.2012 by Bochkanov Sergey
     528             : *************************************************************************/
     529           0 : void touchreal(double* a, ae_state *_state)
     530             : {
     531             : 
     532             : 
     533           0 : }
     534             : 
     535             : 
     536             : /*************************************************************************
     537             : The function performs zero-coalescing on real value.
     538             : 
     539             : NOTE: no check is performed for B<>0
     540             : 
     541             :   -- ALGLIB --
     542             :      Copyright 18.05.2015 by Bochkanov Sergey
     543             : *************************************************************************/
     544           0 : double coalesce(double a, double b, ae_state *_state)
     545             : {
     546             :     double result;
     547             : 
     548             : 
     549           0 :     result = a;
     550           0 :     if( ae_fp_eq(a,0.0) )
     551             :     {
     552           0 :         result = b;
     553             :     }
     554           0 :     return result;
     555             : }
     556             : 
     557             : 
     558             : /*************************************************************************
     559             : The function performs zero-coalescing on integer value.
     560             : 
     561             : NOTE: no check is performed for B<>0
     562             : 
     563             :   -- ALGLIB --
     564             :      Copyright 18.05.2015 by Bochkanov Sergey
     565             : *************************************************************************/
     566           0 : ae_int_t coalescei(ae_int_t a, ae_int_t b, ae_state *_state)
     567             : {
     568             :     ae_int_t result;
     569             : 
     570             : 
     571           0 :     result = a;
     572           0 :     if( a==0 )
     573             :     {
     574           0 :         result = b;
     575             :     }
     576           0 :     return result;
     577             : }
     578             : 
     579             : 
     580             : /*************************************************************************
     581             : The function convert integer value to real value.
     582             : 
     583             :   -- ALGLIB --
     584             :      Copyright 17.09.2012 by Bochkanov Sergey
     585             : *************************************************************************/
     586           0 : double inttoreal(ae_int_t a, ae_state *_state)
     587             : {
     588             :     double result;
     589             : 
     590             : 
     591           0 :     result = (double)(a);
     592           0 :     return result;
     593             : }
     594             : 
     595             : 
     596             : /*************************************************************************
     597             : The function calculates binary logarithm.
     598             : 
     599             : NOTE: it costs twice as much as Ln(x)
     600             : 
     601             :   -- ALGLIB --
     602             :      Copyright 17.09.2012 by Bochkanov Sergey
     603             : *************************************************************************/
     604           0 : double logbase2(double x, ae_state *_state)
     605             : {
     606             :     double result;
     607             : 
     608             : 
     609           0 :     result = ae_log(x, _state)/ae_log((double)(2), _state);
     610           0 :     return result;
     611             : }
     612             : 
     613             : 
     614             : /*************************************************************************
     615             : This function compares two numbers for approximate equality, with tolerance
     616             : to errors as large as tol.
     617             : 
     618             : 
     619             :   -- ALGLIB --
     620             :      Copyright 02.12.2009 by Bochkanov Sergey
     621             : *************************************************************************/
     622           0 : ae_bool approxequal(double a, double b, double tol, ae_state *_state)
     623             : {
     624             :     ae_bool result;
     625             : 
     626             : 
     627           0 :     result = ae_fp_less_eq(ae_fabs(a-b, _state),tol);
     628           0 :     return result;
     629             : }
     630             : 
     631             : 
     632             : /*************************************************************************
     633             : This function compares two numbers for approximate equality, with tolerance
     634             : to errors as large as max(|a|,|b|)*tol.
     635             : 
     636             : 
     637             :   -- ALGLIB --
     638             :      Copyright 02.12.2009 by Bochkanov Sergey
     639             : *************************************************************************/
     640           0 : ae_bool approxequalrel(double a, double b, double tol, ae_state *_state)
     641             : {
     642             :     ae_bool result;
     643             : 
     644             : 
     645           0 :     result = ae_fp_less_eq(ae_fabs(a-b, _state),ae_maxreal(ae_fabs(a, _state), ae_fabs(b, _state), _state)*tol);
     646           0 :     return result;
     647             : }
     648             : 
     649             : 
     650             : /*************************************************************************
     651             : This  function  generates  1-dimensional  general  interpolation task with
     652             : moderate Lipshitz constant (close to 1.0)
     653             : 
     654             : If N=1 then suborutine generates only one point at the middle of [A,B]
     655             : 
     656             :   -- ALGLIB --
     657             :      Copyright 02.12.2009 by Bochkanov Sergey
     658             : *************************************************************************/
     659           0 : void taskgenint1d(double a,
     660             :      double b,
     661             :      ae_int_t n,
     662             :      /* Real    */ ae_vector* x,
     663             :      /* Real    */ ae_vector* y,
     664             :      ae_state *_state)
     665             : {
     666             :     ae_int_t i;
     667             :     double h;
     668             : 
     669           0 :     ae_vector_clear(x);
     670           0 :     ae_vector_clear(y);
     671             : 
     672           0 :     ae_assert(n>=1, "TaskGenInterpolationEqdist1D: N<1!", _state);
     673           0 :     ae_vector_set_length(x, n, _state);
     674           0 :     ae_vector_set_length(y, n, _state);
     675           0 :     if( n>1 )
     676             :     {
     677           0 :         x->ptr.p_double[0] = a;
     678           0 :         y->ptr.p_double[0] = 2*ae_randomreal(_state)-1;
     679           0 :         h = (b-a)/(n-1);
     680           0 :         for(i=1; i<=n-1; i++)
     681             :         {
     682           0 :             if( i!=n-1 )
     683             :             {
     684           0 :                 x->ptr.p_double[i] = a+(i+0.2*(2*ae_randomreal(_state)-1))*h;
     685             :             }
     686             :             else
     687             :             {
     688           0 :                 x->ptr.p_double[i] = b;
     689             :             }
     690           0 :             y->ptr.p_double[i] = y->ptr.p_double[i-1]+(2*ae_randomreal(_state)-1)*(x->ptr.p_double[i]-x->ptr.p_double[i-1]);
     691             :         }
     692             :     }
     693             :     else
     694             :     {
     695           0 :         x->ptr.p_double[0] = 0.5*(a+b);
     696           0 :         y->ptr.p_double[0] = 2*ae_randomreal(_state)-1;
     697             :     }
     698           0 : }
     699             : 
     700             : 
     701             : /*************************************************************************
     702             : This function generates  1-dimensional equidistant interpolation task with
     703             : moderate Lipshitz constant (close to 1.0)
     704             : 
     705             : If N=1 then suborutine generates only one point at the middle of [A,B]
     706             : 
     707             :   -- ALGLIB --
     708             :      Copyright 02.12.2009 by Bochkanov Sergey
     709             : *************************************************************************/
     710           0 : void taskgenint1dequidist(double a,
     711             :      double b,
     712             :      ae_int_t n,
     713             :      /* Real    */ ae_vector* x,
     714             :      /* Real    */ ae_vector* y,
     715             :      ae_state *_state)
     716             : {
     717             :     ae_int_t i;
     718             :     double h;
     719             : 
     720           0 :     ae_vector_clear(x);
     721           0 :     ae_vector_clear(y);
     722             : 
     723           0 :     ae_assert(n>=1, "TaskGenInterpolationEqdist1D: N<1!", _state);
     724           0 :     ae_vector_set_length(x, n, _state);
     725           0 :     ae_vector_set_length(y, n, _state);
     726           0 :     if( n>1 )
     727             :     {
     728           0 :         x->ptr.p_double[0] = a;
     729           0 :         y->ptr.p_double[0] = 2*ae_randomreal(_state)-1;
     730           0 :         h = (b-a)/(n-1);
     731           0 :         for(i=1; i<=n-1; i++)
     732             :         {
     733           0 :             x->ptr.p_double[i] = a+i*h;
     734           0 :             y->ptr.p_double[i] = y->ptr.p_double[i-1]+(2*ae_randomreal(_state)-1)*h;
     735             :         }
     736             :     }
     737             :     else
     738             :     {
     739           0 :         x->ptr.p_double[0] = 0.5*(a+b);
     740           0 :         y->ptr.p_double[0] = 2*ae_randomreal(_state)-1;
     741             :     }
     742           0 : }
     743             : 
     744             : 
     745             : /*************************************************************************
     746             : This function generates  1-dimensional Chebyshev-1 interpolation task with
     747             : moderate Lipshitz constant (close to 1.0)
     748             : 
     749             : If N=1 then suborutine generates only one point at the middle of [A,B]
     750             : 
     751             :   -- ALGLIB --
     752             :      Copyright 02.12.2009 by Bochkanov Sergey
     753             : *************************************************************************/
     754           0 : void taskgenint1dcheb1(double a,
     755             :      double b,
     756             :      ae_int_t n,
     757             :      /* Real    */ ae_vector* x,
     758             :      /* Real    */ ae_vector* y,
     759             :      ae_state *_state)
     760             : {
     761             :     ae_int_t i;
     762             : 
     763           0 :     ae_vector_clear(x);
     764           0 :     ae_vector_clear(y);
     765             : 
     766           0 :     ae_assert(n>=1, "TaskGenInterpolation1DCheb1: N<1!", _state);
     767           0 :     ae_vector_set_length(x, n, _state);
     768           0 :     ae_vector_set_length(y, n, _state);
     769           0 :     if( n>1 )
     770             :     {
     771           0 :         for(i=0; i<=n-1; i++)
     772             :         {
     773           0 :             x->ptr.p_double[i] = 0.5*(b+a)+0.5*(b-a)*ae_cos(ae_pi*(2*i+1)/(2*n), _state);
     774           0 :             if( i==0 )
     775             :             {
     776           0 :                 y->ptr.p_double[i] = 2*ae_randomreal(_state)-1;
     777             :             }
     778             :             else
     779             :             {
     780           0 :                 y->ptr.p_double[i] = y->ptr.p_double[i-1]+(2*ae_randomreal(_state)-1)*(x->ptr.p_double[i]-x->ptr.p_double[i-1]);
     781             :             }
     782             :         }
     783             :     }
     784             :     else
     785             :     {
     786           0 :         x->ptr.p_double[0] = 0.5*(a+b);
     787           0 :         y->ptr.p_double[0] = 2*ae_randomreal(_state)-1;
     788             :     }
     789           0 : }
     790             : 
     791             : 
     792             : /*************************************************************************
     793             : This function generates  1-dimensional Chebyshev-2 interpolation task with
     794             : moderate Lipshitz constant (close to 1.0)
     795             : 
     796             : If N=1 then suborutine generates only one point at the middle of [A,B]
     797             : 
     798             :   -- ALGLIB --
     799             :      Copyright 02.12.2009 by Bochkanov Sergey
     800             : *************************************************************************/
     801           0 : void taskgenint1dcheb2(double a,
     802             :      double b,
     803             :      ae_int_t n,
     804             :      /* Real    */ ae_vector* x,
     805             :      /* Real    */ ae_vector* y,
     806             :      ae_state *_state)
     807             : {
     808             :     ae_int_t i;
     809             : 
     810           0 :     ae_vector_clear(x);
     811           0 :     ae_vector_clear(y);
     812             : 
     813           0 :     ae_assert(n>=1, "TaskGenInterpolation1DCheb2: N<1!", _state);
     814           0 :     ae_vector_set_length(x, n, _state);
     815           0 :     ae_vector_set_length(y, n, _state);
     816           0 :     if( n>1 )
     817             :     {
     818           0 :         for(i=0; i<=n-1; i++)
     819             :         {
     820           0 :             x->ptr.p_double[i] = 0.5*(b+a)+0.5*(b-a)*ae_cos(ae_pi*i/(n-1), _state);
     821           0 :             if( i==0 )
     822             :             {
     823           0 :                 y->ptr.p_double[i] = 2*ae_randomreal(_state)-1;
     824             :             }
     825             :             else
     826             :             {
     827           0 :                 y->ptr.p_double[i] = y->ptr.p_double[i-1]+(2*ae_randomreal(_state)-1)*(x->ptr.p_double[i]-x->ptr.p_double[i-1]);
     828             :             }
     829             :         }
     830             :     }
     831             :     else
     832             :     {
     833           0 :         x->ptr.p_double[0] = 0.5*(a+b);
     834           0 :         y->ptr.p_double[0] = 2*ae_randomreal(_state)-1;
     835             :     }
     836           0 : }
     837             : 
     838             : 
     839             : /*************************************************************************
     840             : This function checks that all values from X[] are distinct. It does more
     841             : than just usual floating point comparison:
     842             : * first, it calculates max(X) and min(X)
     843             : * second, it maps X[] from [min,max] to [1,2]
     844             : * only at this stage actual comparison is done
     845             : 
     846             : The meaning of such check is to ensure that all values are "distinct enough"
     847             : and will not cause interpolation subroutine to fail.
     848             : 
     849             : NOTE:
     850             :     X[] must be sorted by ascending (subroutine ASSERT's it)
     851             : 
     852             :   -- ALGLIB --
     853             :      Copyright 02.12.2009 by Bochkanov Sergey
     854             : *************************************************************************/
     855           0 : ae_bool aredistinct(/* Real    */ ae_vector* x,
     856             :      ae_int_t n,
     857             :      ae_state *_state)
     858             : {
     859             :     double a;
     860             :     double b;
     861             :     ae_int_t i;
     862             :     ae_bool nonsorted;
     863             :     ae_bool result;
     864             : 
     865             : 
     866           0 :     ae_assert(n>=1, "APSERVAreDistinct: internal error (N<1)", _state);
     867           0 :     if( n==1 )
     868             :     {
     869             :         
     870             :         /*
     871             :          * everything is alright, it is up to caller to decide whether it
     872             :          * can interpolate something with just one point
     873             :          */
     874           0 :         result = ae_true;
     875           0 :         return result;
     876             :     }
     877           0 :     a = x->ptr.p_double[0];
     878           0 :     b = x->ptr.p_double[0];
     879           0 :     nonsorted = ae_false;
     880           0 :     for(i=1; i<=n-1; i++)
     881             :     {
     882           0 :         a = ae_minreal(a, x->ptr.p_double[i], _state);
     883           0 :         b = ae_maxreal(b, x->ptr.p_double[i], _state);
     884           0 :         nonsorted = nonsorted||ae_fp_greater_eq(x->ptr.p_double[i-1],x->ptr.p_double[i]);
     885             :     }
     886           0 :     ae_assert(!nonsorted, "APSERVAreDistinct: internal error (not sorted)", _state);
     887           0 :     for(i=1; i<=n-1; i++)
     888             :     {
     889           0 :         if( ae_fp_eq((x->ptr.p_double[i]-a)/(b-a)+1,(x->ptr.p_double[i-1]-a)/(b-a)+1) )
     890             :         {
     891           0 :             result = ae_false;
     892           0 :             return result;
     893             :         }
     894             :     }
     895           0 :     result = ae_true;
     896           0 :     return result;
     897             : }
     898             : 
     899             : 
     900             : /*************************************************************************
     901             : This function checks that two boolean values are the same (both  are  True 
     902             : or both are False).
     903             : 
     904             :   -- ALGLIB --
     905             :      Copyright 02.12.2009 by Bochkanov Sergey
     906             : *************************************************************************/
     907           0 : ae_bool aresameboolean(ae_bool v1, ae_bool v2, ae_state *_state)
     908             : {
     909             :     ae_bool result;
     910             : 
     911             : 
     912           0 :     result = (v1&&v2)||(!v1&&!v2);
     913           0 :     return result;
     914             : }
     915             : 
     916             : 
     917             : /*************************************************************************
     918             : Resizes X and fills by zeros
     919             : 
     920             :   -- ALGLIB --
     921             :      Copyright 20.03.2009 by Bochkanov Sergey
     922             : *************************************************************************/
     923           0 : void setlengthzero(/* Real    */ ae_vector* x,
     924             :      ae_int_t n,
     925             :      ae_state *_state)
     926             : {
     927             :     ae_int_t i;
     928             : 
     929             : 
     930           0 :     ae_assert(n>=0, "SetLengthZero: N<0", _state);
     931           0 :     ae_vector_set_length(x, n, _state);
     932           0 :     for(i=0; i<=n-1; i++)
     933             :     {
     934           0 :         x->ptr.p_double[i] = (double)(0);
     935             :     }
     936           0 : }
     937             : 
     938             : 
     939             : /*************************************************************************
     940             : If Length(X)<N, resizes X
     941             : 
     942             :   -- ALGLIB --
     943             :      Copyright 20.03.2009 by Bochkanov Sergey
     944             : *************************************************************************/
     945           0 : void bvectorsetlengthatleast(/* Boolean */ ae_vector* x,
     946             :      ae_int_t n,
     947             :      ae_state *_state)
     948             : {
     949             : 
     950             : 
     951           0 :     if( x->cnt<n )
     952             :     {
     953           0 :         ae_vector_set_length(x, n, _state);
     954             :     }
     955           0 : }
     956             : 
     957             : 
     958             : /*************************************************************************
     959             : If Length(X)<N, resizes X
     960             : 
     961             :   -- ALGLIB --
     962             :      Copyright 20.03.2009 by Bochkanov Sergey
     963             : *************************************************************************/
     964           0 : void ivectorsetlengthatleast(/* Integer */ ae_vector* x,
     965             :      ae_int_t n,
     966             :      ae_state *_state)
     967             : {
     968             : 
     969             : 
     970           0 :     if( x->cnt<n )
     971             :     {
     972           0 :         ae_vector_set_length(x, n, _state);
     973             :     }
     974           0 : }
     975             : 
     976             : 
     977             : /*************************************************************************
     978             : If Length(X)<N, resizes X
     979             : 
     980             :   -- ALGLIB --
     981             :      Copyright 20.03.2009 by Bochkanov Sergey
     982             : *************************************************************************/
     983        6972 : void rvectorsetlengthatleast(/* Real    */ ae_vector* x,
     984             :      ae_int_t n,
     985             :      ae_state *_state)
     986             : {
     987             : 
     988             : 
     989        6972 :     if( x->cnt<n )
     990             :     {
     991        5976 :         ae_vector_set_length(x, n, _state);
     992             :     }
     993        6972 : }
     994             : 
     995             : 
     996             : /*************************************************************************
     997             : If Cols(X)<N or Rows(X)<M, resizes X
     998             : 
     999             :   -- ALGLIB --
    1000             :      Copyright 20.03.2009 by Bochkanov Sergey
    1001             : *************************************************************************/
    1002         996 : void rmatrixsetlengthatleast(/* Real    */ ae_matrix* x,
    1003             :      ae_int_t m,
    1004             :      ae_int_t n,
    1005             :      ae_state *_state)
    1006             : {
    1007             : 
    1008             : 
    1009         996 :     if( m>0&&n>0 )
    1010             :     {
    1011         996 :         if( x->rows<m||x->cols<n )
    1012             :         {
    1013         996 :             ae_matrix_set_length(x, m, n, _state);
    1014             :         }
    1015             :     }
    1016         996 : }
    1017             : 
    1018             : 
    1019             : /*************************************************************************
    1020             : If Cols(X)<N or Rows(X)<M, resizes X
    1021             : 
    1022             :   -- ALGLIB --
    1023             :      Copyright 20.03.2009 by Bochkanov Sergey
    1024             : *************************************************************************/
    1025           0 : void bmatrixsetlengthatleast(/* Boolean */ ae_matrix* x,
    1026             :      ae_int_t m,
    1027             :      ae_int_t n,
    1028             :      ae_state *_state)
    1029             : {
    1030             : 
    1031             : 
    1032           0 :     if( m>0&&n>0 )
    1033             :     {
    1034           0 :         if( x->rows<m||x->cols<n )
    1035             :         {
    1036           0 :             ae_matrix_set_length(x, m, n, _state);
    1037             :         }
    1038             :     }
    1039           0 : }
    1040             : 
    1041             : 
    1042             : /*************************************************************************
    1043             : Grows X, i.e. changes its size in such a way that:
    1044             : a) contents is preserved
    1045             : b) new size is at least N
    1046             : c) new size can be larger than N, so subsequent grow() calls can return
    1047             :    without reallocation
    1048             : 
    1049             :   -- ALGLIB --
    1050             :      Copyright 20.03.2009 by Bochkanov Sergey
    1051             : *************************************************************************/
    1052           0 : void bvectorgrowto(/* Boolean */ ae_vector* x,
    1053             :      ae_int_t n,
    1054             :      ae_state *_state)
    1055             : {
    1056             :     ae_frame _frame_block;
    1057             :     ae_vector oldx;
    1058             :     ae_int_t i;
    1059             :     ae_int_t n2;
    1060             : 
    1061           0 :     ae_frame_make(_state, &_frame_block);
    1062           0 :     memset(&oldx, 0, sizeof(oldx));
    1063           0 :     ae_vector_init(&oldx, 0, DT_BOOL, _state, ae_true);
    1064             : 
    1065             :     
    1066             :     /*
    1067             :      * Enough place
    1068             :      */
    1069           0 :     if( x->cnt>=n )
    1070             :     {
    1071           0 :         ae_frame_leave(_state);
    1072           0 :         return;
    1073             :     }
    1074             :     
    1075             :     /*
    1076             :      * Choose new size
    1077             :      */
    1078           0 :     n = ae_maxint(n, ae_round(1.8*x->cnt+1, _state), _state);
    1079             :     
    1080             :     /*
    1081             :      * Grow
    1082             :      */
    1083           0 :     n2 = x->cnt;
    1084           0 :     ae_swap_vectors(x, &oldx);
    1085           0 :     ae_vector_set_length(x, n, _state);
    1086           0 :     for(i=0; i<=n-1; i++)
    1087             :     {
    1088           0 :         if( i<n2 )
    1089             :         {
    1090           0 :             x->ptr.p_bool[i] = oldx.ptr.p_bool[i];
    1091             :         }
    1092             :         else
    1093             :         {
    1094           0 :             x->ptr.p_bool[i] = ae_false;
    1095             :         }
    1096             :     }
    1097           0 :     ae_frame_leave(_state);
    1098             : }
    1099             : 
    1100             : 
    1101             : /*************************************************************************
    1102             : Grows X, i.e. changes its size in such a way that:
    1103             : a) contents is preserved
    1104             : b) new size is at least N
    1105             : c) new size can be larger than N, so subsequent grow() calls can return
    1106             :    without reallocation
    1107             : 
    1108             :   -- ALGLIB --
    1109             :      Copyright 20.03.2009 by Bochkanov Sergey
    1110             : *************************************************************************/
    1111           0 : void ivectorgrowto(/* Integer */ ae_vector* x,
    1112             :      ae_int_t n,
    1113             :      ae_state *_state)
    1114             : {
    1115             :     ae_frame _frame_block;
    1116             :     ae_vector oldx;
    1117             :     ae_int_t i;
    1118             :     ae_int_t n2;
    1119             : 
    1120           0 :     ae_frame_make(_state, &_frame_block);
    1121           0 :     memset(&oldx, 0, sizeof(oldx));
    1122           0 :     ae_vector_init(&oldx, 0, DT_INT, _state, ae_true);
    1123             : 
    1124             :     
    1125             :     /*
    1126             :      * Enough place
    1127             :      */
    1128           0 :     if( x->cnt>=n )
    1129             :     {
    1130           0 :         ae_frame_leave(_state);
    1131           0 :         return;
    1132             :     }
    1133             :     
    1134             :     /*
    1135             :      * Choose new size
    1136             :      */
    1137           0 :     n = ae_maxint(n, ae_round(1.8*x->cnt+1, _state), _state);
    1138             :     
    1139             :     /*
    1140             :      * Grow
    1141             :      */
    1142           0 :     n2 = x->cnt;
    1143           0 :     ae_swap_vectors(x, &oldx);
    1144           0 :     ae_vector_set_length(x, n, _state);
    1145           0 :     for(i=0; i<=n-1; i++)
    1146             :     {
    1147           0 :         if( i<n2 )
    1148             :         {
    1149           0 :             x->ptr.p_int[i] = oldx.ptr.p_int[i];
    1150             :         }
    1151             :         else
    1152             :         {
    1153           0 :             x->ptr.p_int[i] = 0;
    1154             :         }
    1155             :     }
    1156           0 :     ae_frame_leave(_state);
    1157             : }
    1158             : 
    1159             : 
    1160             : /*************************************************************************
    1161             : Grows X, i.e. appends rows in such a way that:
    1162             : a) contents is preserved
    1163             : b) new row count is at least N
    1164             : c) new row count can be larger than N, so subsequent grow() calls can return
    1165             :    without reallocation
    1166             : d) new matrix has at least MinCols columns (if less than specified amount
    1167             :    of columns is present, new columns are added with undefined contents);
    1168             :    MinCols can be 0 or negative value = ignored
    1169             : 
    1170             :   -- ALGLIB --
    1171             :      Copyright 20.03.2009 by Bochkanov Sergey
    1172             : *************************************************************************/
    1173           0 : void rmatrixgrowrowsto(/* Real    */ ae_matrix* a,
    1174             :      ae_int_t n,
    1175             :      ae_int_t mincols,
    1176             :      ae_state *_state)
    1177             : {
    1178             :     ae_frame _frame_block;
    1179             :     ae_matrix olda;
    1180             :     ae_int_t i;
    1181             :     ae_int_t j;
    1182             :     ae_int_t n2;
    1183             :     ae_int_t m;
    1184             : 
    1185           0 :     ae_frame_make(_state, &_frame_block);
    1186           0 :     memset(&olda, 0, sizeof(olda));
    1187           0 :     ae_matrix_init(&olda, 0, 0, DT_REAL, _state, ae_true);
    1188             : 
    1189             :     
    1190             :     /*
    1191             :      * Enough place?
    1192             :      */
    1193           0 :     if( a->rows>=n&&a->cols>=mincols )
    1194             :     {
    1195           0 :         ae_frame_leave(_state);
    1196           0 :         return;
    1197             :     }
    1198             :     
    1199             :     /*
    1200             :      * Sizes and metrics
    1201             :      */
    1202           0 :     if( a->rows<n )
    1203             :     {
    1204           0 :         n = ae_maxint(n, ae_round(1.8*a->rows+1, _state), _state);
    1205             :     }
    1206           0 :     n2 = ae_minint(a->rows, n, _state);
    1207           0 :     m = a->cols;
    1208             :     
    1209             :     /*
    1210             :      * Grow
    1211             :      */
    1212           0 :     ae_swap_matrices(a, &olda);
    1213           0 :     ae_matrix_set_length(a, n, ae_maxint(m, mincols, _state), _state);
    1214           0 :     for(i=0; i<=n2-1; i++)
    1215             :     {
    1216           0 :         for(j=0; j<=m-1; j++)
    1217             :         {
    1218           0 :             a->ptr.pp_double[i][j] = olda.ptr.pp_double[i][j];
    1219             :         }
    1220             :     }
    1221           0 :     ae_frame_leave(_state);
    1222             : }
    1223             : 
    1224             : 
    1225             : /*************************************************************************
    1226             : Grows X, i.e. appends cols in such a way that:
    1227             : a) contents is preserved
    1228             : b) new col count is at least N
    1229             : c) new col count can be larger than N, so subsequent grow() calls can return
    1230             :    without reallocation
    1231             : d) new matrix has at least MinRows row (if less than specified amount
    1232             :    of rows is present, new rows are added with undefined contents);
    1233             :    MinRows can be 0 or negative value = ignored
    1234             : 
    1235             :   -- ALGLIB --
    1236             :      Copyright 20.03.2009 by Bochkanov Sergey
    1237             : *************************************************************************/
    1238           0 : void rmatrixgrowcolsto(/* Real    */ ae_matrix* a,
    1239             :      ae_int_t n,
    1240             :      ae_int_t minrows,
    1241             :      ae_state *_state)
    1242             : {
    1243             :     ae_frame _frame_block;
    1244             :     ae_matrix olda;
    1245             :     ae_int_t i;
    1246             :     ae_int_t j;
    1247             :     ae_int_t n2;
    1248             :     ae_int_t m;
    1249             : 
    1250           0 :     ae_frame_make(_state, &_frame_block);
    1251           0 :     memset(&olda, 0, sizeof(olda));
    1252           0 :     ae_matrix_init(&olda, 0, 0, DT_REAL, _state, ae_true);
    1253             : 
    1254             :     
    1255             :     /*
    1256             :      * Enough place?
    1257             :      */
    1258           0 :     if( a->cols>=n&&a->rows>=minrows )
    1259             :     {
    1260           0 :         ae_frame_leave(_state);
    1261           0 :         return;
    1262             :     }
    1263             :     
    1264             :     /*
    1265             :      * Sizes and metrics
    1266             :      */
    1267           0 :     if( a->cols<n )
    1268             :     {
    1269           0 :         n = ae_maxint(n, ae_round(1.8*a->cols+1, _state), _state);
    1270             :     }
    1271           0 :     n2 = ae_minint(a->cols, n, _state);
    1272           0 :     m = a->rows;
    1273             :     
    1274             :     /*
    1275             :      * Grow
    1276             :      */
    1277           0 :     ae_swap_matrices(a, &olda);
    1278           0 :     ae_matrix_set_length(a, ae_maxint(m, minrows, _state), n, _state);
    1279           0 :     for(i=0; i<=m-1; i++)
    1280             :     {
    1281           0 :         for(j=0; j<=n2-1; j++)
    1282             :         {
    1283           0 :             a->ptr.pp_double[i][j] = olda.ptr.pp_double[i][j];
    1284             :         }
    1285             :     }
    1286           0 :     ae_frame_leave(_state);
    1287             : }
    1288             : 
    1289             : 
    1290             : /*************************************************************************
    1291             : Grows X, i.e. changes its size in such a way that:
    1292             : a) contents is preserved
    1293             : b) new size is at least N
    1294             : c) new size can be larger than N, so subsequent grow() calls can return
    1295             :    without reallocation
    1296             : 
    1297             :   -- ALGLIB --
    1298             :      Copyright 20.03.2009 by Bochkanov Sergey
    1299             : *************************************************************************/
    1300           0 : void rvectorgrowto(/* Real    */ ae_vector* x,
    1301             :      ae_int_t n,
    1302             :      ae_state *_state)
    1303             : {
    1304             :     ae_frame _frame_block;
    1305             :     ae_vector oldx;
    1306             :     ae_int_t i;
    1307             :     ae_int_t n2;
    1308             : 
    1309           0 :     ae_frame_make(_state, &_frame_block);
    1310           0 :     memset(&oldx, 0, sizeof(oldx));
    1311           0 :     ae_vector_init(&oldx, 0, DT_REAL, _state, ae_true);
    1312             : 
    1313             :     
    1314             :     /*
    1315             :      * Enough place
    1316             :      */
    1317           0 :     if( x->cnt>=n )
    1318             :     {
    1319           0 :         ae_frame_leave(_state);
    1320           0 :         return;
    1321             :     }
    1322             :     
    1323             :     /*
    1324             :      * Choose new size
    1325             :      */
    1326           0 :     n = ae_maxint(n, ae_round(1.8*x->cnt+1, _state), _state);
    1327             :     
    1328             :     /*
    1329             :      * Grow
    1330             :      */
    1331           0 :     n2 = x->cnt;
    1332           0 :     ae_swap_vectors(x, &oldx);
    1333           0 :     ae_vector_set_length(x, n, _state);
    1334           0 :     for(i=0; i<=n-1; i++)
    1335             :     {
    1336           0 :         if( i<n2 )
    1337             :         {
    1338           0 :             x->ptr.p_double[i] = oldx.ptr.p_double[i];
    1339             :         }
    1340             :         else
    1341             :         {
    1342           0 :             x->ptr.p_double[i] = (double)(0);
    1343             :         }
    1344             :     }
    1345           0 :     ae_frame_leave(_state);
    1346             : }
    1347             : 
    1348             : 
    1349             : /*************************************************************************
    1350             : Resizes X and:
    1351             : * preserves old contents of X
    1352             : * fills new elements by zeros
    1353             : 
    1354             :   -- ALGLIB --
    1355             :      Copyright 20.03.2009 by Bochkanov Sergey
    1356             : *************************************************************************/
    1357           0 : void ivectorresize(/* Integer */ ae_vector* x,
    1358             :      ae_int_t n,
    1359             :      ae_state *_state)
    1360             : {
    1361             :     ae_frame _frame_block;
    1362             :     ae_vector oldx;
    1363             :     ae_int_t i;
    1364             :     ae_int_t n2;
    1365             : 
    1366           0 :     ae_frame_make(_state, &_frame_block);
    1367           0 :     memset(&oldx, 0, sizeof(oldx));
    1368           0 :     ae_vector_init(&oldx, 0, DT_INT, _state, ae_true);
    1369             : 
    1370           0 :     n2 = x->cnt;
    1371           0 :     ae_swap_vectors(x, &oldx);
    1372           0 :     ae_vector_set_length(x, n, _state);
    1373           0 :     for(i=0; i<=n-1; i++)
    1374             :     {
    1375           0 :         if( i<n2 )
    1376             :         {
    1377           0 :             x->ptr.p_int[i] = oldx.ptr.p_int[i];
    1378             :         }
    1379             :         else
    1380             :         {
    1381           0 :             x->ptr.p_int[i] = 0;
    1382             :         }
    1383             :     }
    1384           0 :     ae_frame_leave(_state);
    1385           0 : }
    1386             : 
    1387             : 
    1388             : /*************************************************************************
    1389             : Resizes X and:
    1390             : * preserves old contents of X
    1391             : * fills new elements by zeros
    1392             : 
    1393             :   -- ALGLIB --
    1394             :      Copyright 20.03.2009 by Bochkanov Sergey
    1395             : *************************************************************************/
    1396           0 : void rvectorresize(/* Real    */ ae_vector* x,
    1397             :      ae_int_t n,
    1398             :      ae_state *_state)
    1399             : {
    1400             :     ae_frame _frame_block;
    1401             :     ae_vector oldx;
    1402             :     ae_int_t i;
    1403             :     ae_int_t n2;
    1404             : 
    1405           0 :     ae_frame_make(_state, &_frame_block);
    1406           0 :     memset(&oldx, 0, sizeof(oldx));
    1407           0 :     ae_vector_init(&oldx, 0, DT_REAL, _state, ae_true);
    1408             : 
    1409           0 :     n2 = x->cnt;
    1410           0 :     ae_swap_vectors(x, &oldx);
    1411           0 :     ae_vector_set_length(x, n, _state);
    1412           0 :     for(i=0; i<=n-1; i++)
    1413             :     {
    1414           0 :         if( i<n2 )
    1415             :         {
    1416           0 :             x->ptr.p_double[i] = oldx.ptr.p_double[i];
    1417             :         }
    1418             :         else
    1419             :         {
    1420           0 :             x->ptr.p_double[i] = (double)(0);
    1421             :         }
    1422             :     }
    1423           0 :     ae_frame_leave(_state);
    1424           0 : }
    1425             : 
    1426             : 
    1427             : /*************************************************************************
    1428             : Resizes X and:
    1429             : * preserves old contents of X
    1430             : * fills new elements by zeros
    1431             : 
    1432             :   -- ALGLIB --
    1433             :      Copyright 20.03.2009 by Bochkanov Sergey
    1434             : *************************************************************************/
    1435           0 : void rmatrixresize(/* Real    */ ae_matrix* x,
    1436             :      ae_int_t m,
    1437             :      ae_int_t n,
    1438             :      ae_state *_state)
    1439             : {
    1440             :     ae_frame _frame_block;
    1441             :     ae_matrix oldx;
    1442             :     ae_int_t i;
    1443             :     ae_int_t j;
    1444             :     ae_int_t m2;
    1445             :     ae_int_t n2;
    1446             : 
    1447           0 :     ae_frame_make(_state, &_frame_block);
    1448           0 :     memset(&oldx, 0, sizeof(oldx));
    1449           0 :     ae_matrix_init(&oldx, 0, 0, DT_REAL, _state, ae_true);
    1450             : 
    1451           0 :     m2 = x->rows;
    1452           0 :     n2 = x->cols;
    1453           0 :     ae_swap_matrices(x, &oldx);
    1454           0 :     ae_matrix_set_length(x, m, n, _state);
    1455           0 :     for(i=0; i<=m-1; i++)
    1456             :     {
    1457           0 :         for(j=0; j<=n-1; j++)
    1458             :         {
    1459           0 :             if( i<m2&&j<n2 )
    1460             :             {
    1461           0 :                 x->ptr.pp_double[i][j] = oldx.ptr.pp_double[i][j];
    1462             :             }
    1463             :             else
    1464             :             {
    1465           0 :                 x->ptr.pp_double[i][j] = 0.0;
    1466             :             }
    1467             :         }
    1468             :     }
    1469           0 :     ae_frame_leave(_state);
    1470           0 : }
    1471             : 
    1472             : 
    1473             : /*************************************************************************
    1474             : Resizes X and:
    1475             : * preserves old contents of X
    1476             : * fills new elements by zeros
    1477             : 
    1478             :   -- ALGLIB --
    1479             :      Copyright 20.03.2009 by Bochkanov Sergey
    1480             : *************************************************************************/
    1481           0 : void imatrixresize(/* Integer */ ae_matrix* x,
    1482             :      ae_int_t m,
    1483             :      ae_int_t n,
    1484             :      ae_state *_state)
    1485             : {
    1486             :     ae_frame _frame_block;
    1487             :     ae_matrix oldx;
    1488             :     ae_int_t i;
    1489             :     ae_int_t j;
    1490             :     ae_int_t m2;
    1491             :     ae_int_t n2;
    1492             : 
    1493           0 :     ae_frame_make(_state, &_frame_block);
    1494           0 :     memset(&oldx, 0, sizeof(oldx));
    1495           0 :     ae_matrix_init(&oldx, 0, 0, DT_INT, _state, ae_true);
    1496             : 
    1497           0 :     m2 = x->rows;
    1498           0 :     n2 = x->cols;
    1499           0 :     ae_swap_matrices(x, &oldx);
    1500           0 :     ae_matrix_set_length(x, m, n, _state);
    1501           0 :     for(i=0; i<=m-1; i++)
    1502             :     {
    1503           0 :         for(j=0; j<=n-1; j++)
    1504             :         {
    1505           0 :             if( i<m2&&j<n2 )
    1506             :             {
    1507           0 :                 x->ptr.pp_int[i][j] = oldx.ptr.pp_int[i][j];
    1508             :             }
    1509             :             else
    1510             :             {
    1511           0 :                 x->ptr.pp_int[i][j] = 0;
    1512             :             }
    1513             :         }
    1514             :     }
    1515           0 :     ae_frame_leave(_state);
    1516           0 : }
    1517             : 
    1518             : 
    1519             : /*************************************************************************
    1520             : appends element to X
    1521             : 
    1522             :   -- ALGLIB --
    1523             :      Copyright 20.03.2009 by Bochkanov Sergey
    1524             : *************************************************************************/
    1525           0 : void ivectorappend(/* Integer */ ae_vector* x,
    1526             :      ae_int_t v,
    1527             :      ae_state *_state)
    1528             : {
    1529             :     ae_frame _frame_block;
    1530             :     ae_vector oldx;
    1531             :     ae_int_t i;
    1532             :     ae_int_t n;
    1533             : 
    1534           0 :     ae_frame_make(_state, &_frame_block);
    1535           0 :     memset(&oldx, 0, sizeof(oldx));
    1536           0 :     ae_vector_init(&oldx, 0, DT_INT, _state, ae_true);
    1537             : 
    1538           0 :     n = x->cnt;
    1539           0 :     ae_swap_vectors(x, &oldx);
    1540           0 :     ae_vector_set_length(x, n+1, _state);
    1541           0 :     for(i=0; i<=n-1; i++)
    1542             :     {
    1543           0 :         x->ptr.p_int[i] = oldx.ptr.p_int[i];
    1544             :     }
    1545           0 :     x->ptr.p_int[n] = v;
    1546           0 :     ae_frame_leave(_state);
    1547           0 : }
    1548             : 
    1549             : 
    1550             : /*************************************************************************
    1551             : This function checks that length(X) is at least N and first N values  from
    1552             : X[] are finite
    1553             : 
    1554             :   -- ALGLIB --
    1555             :      Copyright 18.06.2010 by Bochkanov Sergey
    1556             : *************************************************************************/
    1557         996 : ae_bool isfinitevector(/* Real    */ ae_vector* x,
    1558             :      ae_int_t n,
    1559             :      ae_state *_state)
    1560             : {
    1561             :     ae_int_t i;
    1562             :     double v;
    1563             :     ae_bool result;
    1564             : 
    1565             : 
    1566         996 :     ae_assert(n>=0, "APSERVIsFiniteVector: internal error (N<0)", _state);
    1567         996 :     if( n==0 )
    1568             :     {
    1569           0 :         result = ae_true;
    1570           0 :         return result;
    1571             :     }
    1572         996 :     if( x->cnt<n )
    1573             :     {
    1574           0 :         result = ae_false;
    1575           0 :         return result;
    1576             :     }
    1577         996 :     v = (double)(0);
    1578        2988 :     for(i=0; i<=n-1; i++)
    1579             :     {
    1580        1992 :         v = 0.01*v+x->ptr.p_double[i];
    1581             :     }
    1582         996 :     result = ae_isfinite(v, _state);
    1583         996 :     return result;
    1584             : }
    1585             : 
    1586             : 
    1587             : /*************************************************************************
    1588             : This function checks that first N values from X[] are finite
    1589             : 
    1590             :   -- ALGLIB --
    1591             :      Copyright 18.06.2010 by Bochkanov Sergey
    1592             : *************************************************************************/
    1593           0 : ae_bool isfinitecvector(/* Complex */ ae_vector* z,
    1594             :      ae_int_t n,
    1595             :      ae_state *_state)
    1596             : {
    1597             :     ae_int_t i;
    1598             :     ae_bool result;
    1599             : 
    1600             : 
    1601           0 :     ae_assert(n>=0, "APSERVIsFiniteCVector: internal error (N<0)", _state);
    1602           0 :     for(i=0; i<=n-1; i++)
    1603             :     {
    1604           0 :         if( !ae_isfinite(z->ptr.p_complex[i].x, _state)||!ae_isfinite(z->ptr.p_complex[i].y, _state) )
    1605             :         {
    1606           0 :             result = ae_false;
    1607           0 :             return result;
    1608             :         }
    1609             :     }
    1610           0 :     result = ae_true;
    1611           0 :     return result;
    1612             : }
    1613             : 
    1614             : 
    1615             : /*************************************************************************
    1616             : This function checks that size of X is at least MxN and values from
    1617             : X[0..M-1,0..N-1] are finite.
    1618             : 
    1619             :   -- ALGLIB --
    1620             :      Copyright 18.06.2010 by Bochkanov Sergey
    1621             : *************************************************************************/
    1622           0 : ae_bool apservisfinitematrix(/* Real    */ ae_matrix* x,
    1623             :      ae_int_t m,
    1624             :      ae_int_t n,
    1625             :      ae_state *_state)
    1626             : {
    1627             :     ae_int_t i;
    1628             :     ae_int_t j;
    1629             :     ae_bool result;
    1630             : 
    1631             : 
    1632           0 :     ae_assert(n>=0, "APSERVIsFiniteMatrix: internal error (N<0)", _state);
    1633           0 :     ae_assert(m>=0, "APSERVIsFiniteMatrix: internal error (M<0)", _state);
    1634           0 :     if( m==0||n==0 )
    1635             :     {
    1636           0 :         result = ae_true;
    1637           0 :         return result;
    1638             :     }
    1639           0 :     if( x->rows<m||x->cols<n )
    1640             :     {
    1641           0 :         result = ae_false;
    1642           0 :         return result;
    1643             :     }
    1644           0 :     for(i=0; i<=m-1; i++)
    1645             :     {
    1646           0 :         for(j=0; j<=n-1; j++)
    1647             :         {
    1648           0 :             if( !ae_isfinite(x->ptr.pp_double[i][j], _state) )
    1649             :             {
    1650           0 :                 result = ae_false;
    1651           0 :                 return result;
    1652             :             }
    1653             :         }
    1654             :     }
    1655           0 :     result = ae_true;
    1656           0 :     return result;
    1657             : }
    1658             : 
    1659             : 
    1660             : /*************************************************************************
    1661             : This function checks that all values from X[0..M-1,0..N-1] are finite
    1662             : 
    1663             :   -- ALGLIB --
    1664             :      Copyright 18.06.2010 by Bochkanov Sergey
    1665             : *************************************************************************/
    1666           0 : ae_bool apservisfinitecmatrix(/* Complex */ ae_matrix* x,
    1667             :      ae_int_t m,
    1668             :      ae_int_t n,
    1669             :      ae_state *_state)
    1670             : {
    1671             :     ae_int_t i;
    1672             :     ae_int_t j;
    1673             :     ae_bool result;
    1674             : 
    1675             : 
    1676           0 :     ae_assert(n>=0, "APSERVIsFiniteCMatrix: internal error (N<0)", _state);
    1677           0 :     ae_assert(m>=0, "APSERVIsFiniteCMatrix: internal error (M<0)", _state);
    1678           0 :     for(i=0; i<=m-1; i++)
    1679             :     {
    1680           0 :         for(j=0; j<=n-1; j++)
    1681             :         {
    1682           0 :             if( !ae_isfinite(x->ptr.pp_complex[i][j].x, _state)||!ae_isfinite(x->ptr.pp_complex[i][j].y, _state) )
    1683             :             {
    1684           0 :                 result = ae_false;
    1685           0 :                 return result;
    1686             :             }
    1687             :         }
    1688             :     }
    1689           0 :     result = ae_true;
    1690           0 :     return result;
    1691             : }
    1692             : 
    1693             : 
    1694             : /*************************************************************************
    1695             : This function checks that size of X is at least NxN and all values from
    1696             : upper/lower triangle of X[0..N-1,0..N-1] are finite
    1697             : 
    1698             :   -- ALGLIB --
    1699             :      Copyright 18.06.2010 by Bochkanov Sergey
    1700             : *************************************************************************/
    1701           0 : ae_bool isfinitertrmatrix(/* Real    */ ae_matrix* x,
    1702             :      ae_int_t n,
    1703             :      ae_bool isupper,
    1704             :      ae_state *_state)
    1705             : {
    1706             :     ae_int_t i;
    1707             :     ae_int_t j1;
    1708             :     ae_int_t j2;
    1709             :     ae_int_t j;
    1710             :     ae_bool result;
    1711             : 
    1712             : 
    1713           0 :     ae_assert(n>=0, "APSERVIsFiniteRTRMatrix: internal error (N<0)", _state);
    1714           0 :     if( n==0 )
    1715             :     {
    1716           0 :         result = ae_true;
    1717           0 :         return result;
    1718             :     }
    1719           0 :     if( x->rows<n||x->cols<n )
    1720             :     {
    1721           0 :         result = ae_false;
    1722           0 :         return result;
    1723             :     }
    1724           0 :     for(i=0; i<=n-1; i++)
    1725             :     {
    1726           0 :         if( isupper )
    1727             :         {
    1728           0 :             j1 = i;
    1729           0 :             j2 = n-1;
    1730             :         }
    1731             :         else
    1732             :         {
    1733           0 :             j1 = 0;
    1734           0 :             j2 = i;
    1735             :         }
    1736           0 :         for(j=j1; j<=j2; j++)
    1737             :         {
    1738           0 :             if( !ae_isfinite(x->ptr.pp_double[i][j], _state) )
    1739             :             {
    1740           0 :                 result = ae_false;
    1741           0 :                 return result;
    1742             :             }
    1743             :         }
    1744             :     }
    1745           0 :     result = ae_true;
    1746           0 :     return result;
    1747             : }
    1748             : 
    1749             : 
    1750             : /*************************************************************************
    1751             : This function checks that all values from upper/lower triangle of
    1752             : X[0..N-1,0..N-1] are finite
    1753             : 
    1754             :   -- ALGLIB --
    1755             :      Copyright 18.06.2010 by Bochkanov Sergey
    1756             : *************************************************************************/
    1757           0 : ae_bool apservisfinitectrmatrix(/* Complex */ ae_matrix* x,
    1758             :      ae_int_t n,
    1759             :      ae_bool isupper,
    1760             :      ae_state *_state)
    1761             : {
    1762             :     ae_int_t i;
    1763             :     ae_int_t j1;
    1764             :     ae_int_t j2;
    1765             :     ae_int_t j;
    1766             :     ae_bool result;
    1767             : 
    1768             : 
    1769           0 :     ae_assert(n>=0, "APSERVIsFiniteCTRMatrix: internal error (N<0)", _state);
    1770           0 :     for(i=0; i<=n-1; i++)
    1771             :     {
    1772           0 :         if( isupper )
    1773             :         {
    1774           0 :             j1 = i;
    1775           0 :             j2 = n-1;
    1776             :         }
    1777             :         else
    1778             :         {
    1779           0 :             j1 = 0;
    1780           0 :             j2 = i;
    1781             :         }
    1782           0 :         for(j=j1; j<=j2; j++)
    1783             :         {
    1784           0 :             if( !ae_isfinite(x->ptr.pp_complex[i][j].x, _state)||!ae_isfinite(x->ptr.pp_complex[i][j].y, _state) )
    1785             :             {
    1786           0 :                 result = ae_false;
    1787           0 :                 return result;
    1788             :             }
    1789             :         }
    1790             :     }
    1791           0 :     result = ae_true;
    1792           0 :     return result;
    1793             : }
    1794             : 
    1795             : 
    1796             : /*************************************************************************
    1797             : This function checks that all values from X[0..M-1,0..N-1] are  finite  or
    1798             : NaN's.
    1799             : 
    1800             :   -- ALGLIB --
    1801             :      Copyright 18.06.2010 by Bochkanov Sergey
    1802             : *************************************************************************/
    1803           0 : ae_bool apservisfiniteornanmatrix(/* Real    */ ae_matrix* x,
    1804             :      ae_int_t m,
    1805             :      ae_int_t n,
    1806             :      ae_state *_state)
    1807             : {
    1808             :     ae_int_t i;
    1809             :     ae_int_t j;
    1810             :     ae_bool result;
    1811             : 
    1812             : 
    1813           0 :     ae_assert(n>=0, "APSERVIsFiniteOrNaNMatrix: internal error (N<0)", _state);
    1814           0 :     ae_assert(m>=0, "APSERVIsFiniteOrNaNMatrix: internal error (M<0)", _state);
    1815           0 :     for(i=0; i<=m-1; i++)
    1816             :     {
    1817           0 :         for(j=0; j<=n-1; j++)
    1818             :         {
    1819           0 :             if( !(ae_isfinite(x->ptr.pp_double[i][j], _state)||ae_isnan(x->ptr.pp_double[i][j], _state)) )
    1820             :             {
    1821           0 :                 result = ae_false;
    1822           0 :                 return result;
    1823             :             }
    1824             :         }
    1825             :     }
    1826           0 :     result = ae_true;
    1827           0 :     return result;
    1828             : }
    1829             : 
    1830             : 
    1831             : /*************************************************************************
    1832             : Safe sqrt(x^2+y^2)
    1833             : 
    1834             :   -- ALGLIB --
    1835             :      Copyright by Bochkanov Sergey
    1836             : *************************************************************************/
    1837           0 : double safepythag2(double x, double y, ae_state *_state)
    1838             : {
    1839             :     double w;
    1840             :     double xabs;
    1841             :     double yabs;
    1842             :     double z;
    1843             :     double result;
    1844             : 
    1845             : 
    1846           0 :     xabs = ae_fabs(x, _state);
    1847           0 :     yabs = ae_fabs(y, _state);
    1848           0 :     w = ae_maxreal(xabs, yabs, _state);
    1849           0 :     z = ae_minreal(xabs, yabs, _state);
    1850           0 :     if( ae_fp_eq(z,(double)(0)) )
    1851             :     {
    1852           0 :         result = w;
    1853             :     }
    1854             :     else
    1855             :     {
    1856           0 :         result = w*ae_sqrt(1+ae_sqr(z/w, _state), _state);
    1857             :     }
    1858           0 :     return result;
    1859             : }
    1860             : 
    1861             : 
    1862             : /*************************************************************************
    1863             : Safe sqrt(x^2+y^2)
    1864             : 
    1865             :   -- ALGLIB --
    1866             :      Copyright by Bochkanov Sergey
    1867             : *************************************************************************/
    1868           0 : double safepythag3(double x, double y, double z, ae_state *_state)
    1869             : {
    1870             :     double w;
    1871             :     double result;
    1872             : 
    1873             : 
    1874           0 :     w = ae_maxreal(ae_fabs(x, _state), ae_maxreal(ae_fabs(y, _state), ae_fabs(z, _state), _state), _state);
    1875           0 :     if( ae_fp_eq(w,(double)(0)) )
    1876             :     {
    1877           0 :         result = (double)(0);
    1878           0 :         return result;
    1879             :     }
    1880           0 :     x = x/w;
    1881           0 :     y = y/w;
    1882           0 :     z = z/w;
    1883           0 :     result = w*ae_sqrt(ae_sqr(x, _state)+ae_sqr(y, _state)+ae_sqr(z, _state), _state);
    1884           0 :     return result;
    1885             : }
    1886             : 
    1887             : 
    1888             : /*************************************************************************
    1889             : Safe division.
    1890             : 
    1891             : This function attempts to calculate R=X/Y without overflow.
    1892             : 
    1893             : It returns:
    1894             : * +1, if abs(X/Y)>=MaxRealNumber or undefined - overflow-like situation
    1895             :       (no overlfow is generated, R is either NAN, PosINF, NegINF)
    1896             : *  0, if MinRealNumber<abs(X/Y)<MaxRealNumber or X=0, Y<>0
    1897             :       (R contains result, may be zero)
    1898             : * -1, if 0<abs(X/Y)<MinRealNumber - underflow-like situation
    1899             :       (R contains zero; it corresponds to underflow)
    1900             : 
    1901             : No overflow is generated in any case.
    1902             : 
    1903             :   -- ALGLIB --
    1904             :      Copyright by Bochkanov Sergey
    1905             : *************************************************************************/
    1906           0 : ae_int_t saferdiv(double x, double y, double* r, ae_state *_state)
    1907             : {
    1908             :     ae_int_t result;
    1909             : 
    1910           0 :     *r = 0;
    1911             : 
    1912             :     
    1913             :     /*
    1914             :      * Two special cases:
    1915             :      * * Y=0
    1916             :      * * X=0 and Y<>0
    1917             :      */
    1918           0 :     if( ae_fp_eq(y,(double)(0)) )
    1919             :     {
    1920           0 :         result = 1;
    1921           0 :         if( ae_fp_eq(x,(double)(0)) )
    1922             :         {
    1923           0 :             *r = _state->v_nan;
    1924             :         }
    1925           0 :         if( ae_fp_greater(x,(double)(0)) )
    1926             :         {
    1927           0 :             *r = _state->v_posinf;
    1928             :         }
    1929           0 :         if( ae_fp_less(x,(double)(0)) )
    1930             :         {
    1931           0 :             *r = _state->v_neginf;
    1932             :         }
    1933           0 :         return result;
    1934             :     }
    1935           0 :     if( ae_fp_eq(x,(double)(0)) )
    1936             :     {
    1937           0 :         *r = (double)(0);
    1938           0 :         result = 0;
    1939           0 :         return result;
    1940             :     }
    1941             :     
    1942             :     /*
    1943             :      * make Y>0
    1944             :      */
    1945           0 :     if( ae_fp_less(y,(double)(0)) )
    1946             :     {
    1947           0 :         x = -x;
    1948           0 :         y = -y;
    1949             :     }
    1950             :     
    1951             :     /*
    1952             :      *
    1953             :      */
    1954           0 :     if( ae_fp_greater_eq(y,(double)(1)) )
    1955             :     {
    1956           0 :         *r = x/y;
    1957           0 :         if( ae_fp_less_eq(ae_fabs(*r, _state),ae_minrealnumber) )
    1958             :         {
    1959           0 :             result = -1;
    1960           0 :             *r = (double)(0);
    1961             :         }
    1962             :         else
    1963             :         {
    1964           0 :             result = 0;
    1965             :         }
    1966             :     }
    1967             :     else
    1968             :     {
    1969           0 :         if( ae_fp_greater_eq(ae_fabs(x, _state),ae_maxrealnumber*y) )
    1970             :         {
    1971           0 :             if( ae_fp_greater(x,(double)(0)) )
    1972             :             {
    1973           0 :                 *r = _state->v_posinf;
    1974             :             }
    1975             :             else
    1976             :             {
    1977           0 :                 *r = _state->v_neginf;
    1978             :             }
    1979           0 :             result = 1;
    1980             :         }
    1981             :         else
    1982             :         {
    1983           0 :             *r = x/y;
    1984           0 :             result = 0;
    1985             :         }
    1986             :     }
    1987           0 :     return result;
    1988             : }
    1989             : 
    1990             : 
    1991             : /*************************************************************************
    1992             : This function calculates "safe" min(X/Y,V) for positive finite X, Y, V.
    1993             : No overflow is generated in any case.
    1994             : 
    1995             :   -- ALGLIB --
    1996             :      Copyright by Bochkanov Sergey
    1997             : *************************************************************************/
    1998           0 : double safeminposrv(double x, double y, double v, ae_state *_state)
    1999             : {
    2000             :     double r;
    2001             :     double result;
    2002             : 
    2003             : 
    2004           0 :     if( ae_fp_greater_eq(y,(double)(1)) )
    2005             :     {
    2006             :         
    2007             :         /*
    2008             :          * Y>=1, we can safely divide by Y
    2009             :          */
    2010           0 :         r = x/y;
    2011           0 :         result = v;
    2012           0 :         if( ae_fp_greater(v,r) )
    2013             :         {
    2014           0 :             result = r;
    2015             :         }
    2016             :         else
    2017             :         {
    2018           0 :             result = v;
    2019             :         }
    2020             :     }
    2021             :     else
    2022             :     {
    2023             :         
    2024             :         /*
    2025             :          * Y<1, we can safely multiply by Y
    2026             :          */
    2027           0 :         if( ae_fp_less(x,v*y) )
    2028             :         {
    2029           0 :             result = x/y;
    2030             :         }
    2031             :         else
    2032             :         {
    2033           0 :             result = v;
    2034             :         }
    2035             :     }
    2036           0 :     return result;
    2037             : }
    2038             : 
    2039             : 
    2040             : /*************************************************************************
    2041             : This function makes periodic mapping of X to [A,B].
    2042             : 
    2043             : It accepts X, A, B (A>B). It returns T which lies in  [A,B] and integer K,
    2044             : such that X = T + K*(B-A).
    2045             : 
    2046             : NOTES:
    2047             : * K is represented as real value, although actually it is integer
    2048             : * T is guaranteed to be in [A,B]
    2049             : * T replaces X
    2050             : 
    2051             :   -- ALGLIB --
    2052             :      Copyright by Bochkanov Sergey
    2053             : *************************************************************************/
    2054           0 : void apperiodicmap(double* x,
    2055             :      double a,
    2056             :      double b,
    2057             :      double* k,
    2058             :      ae_state *_state)
    2059             : {
    2060             : 
    2061           0 :     *k = 0;
    2062             : 
    2063           0 :     ae_assert(ae_fp_less(a,b), "APPeriodicMap: internal error!", _state);
    2064           0 :     *k = (double)(ae_ifloor((*x-a)/(b-a), _state));
    2065           0 :     *x = *x-*k*(b-a);
    2066           0 :     while(ae_fp_less(*x,a))
    2067             :     {
    2068           0 :         *x = *x+(b-a);
    2069           0 :         *k = *k-1;
    2070             :     }
    2071           0 :     while(ae_fp_greater(*x,b))
    2072             :     {
    2073           0 :         *x = *x-(b-a);
    2074           0 :         *k = *k+1;
    2075             :     }
    2076           0 :     *x = ae_maxreal(*x, a, _state);
    2077           0 :     *x = ae_minreal(*x, b, _state);
    2078           0 : }
    2079             : 
    2080             : 
    2081             : /*************************************************************************
    2082             : Returns random normal number using low-quality system-provided generator
    2083             : 
    2084             :   -- ALGLIB --
    2085             :      Copyright 20.03.2009 by Bochkanov Sergey
    2086             : *************************************************************************/
    2087           0 : double randomnormal(ae_state *_state)
    2088             : {
    2089             :     double u;
    2090             :     double v;
    2091             :     double s;
    2092             :     double result;
    2093             : 
    2094             : 
    2095             :     for(;;)
    2096             :     {
    2097           0 :         u = 2*ae_randomreal(_state)-1;
    2098           0 :         v = 2*ae_randomreal(_state)-1;
    2099           0 :         s = ae_sqr(u, _state)+ae_sqr(v, _state);
    2100           0 :         if( ae_fp_greater(s,(double)(0))&&ae_fp_less(s,(double)(1)) )
    2101             :         {
    2102             :             
    2103             :             /*
    2104             :              * two Sqrt's instead of one to
    2105             :              * avoid overflow when S is too small
    2106             :              */
    2107           0 :             s = ae_sqrt(-2*ae_log(s, _state), _state)/ae_sqrt(s, _state);
    2108           0 :             result = u*s;
    2109           0 :             break;
    2110             :         }
    2111             :     }
    2112           0 :     return result;
    2113             : }
    2114             : 
    2115             : 
    2116             : /*************************************************************************
    2117             : Generates random unit vector using low-quality system-provided generator.
    2118             : Reallocates array if its size is too short.
    2119             : 
    2120             :   -- ALGLIB --
    2121             :      Copyright 20.03.2009 by Bochkanov Sergey
    2122             : *************************************************************************/
    2123           0 : void randomunit(ae_int_t n, /* Real    */ ae_vector* x, ae_state *_state)
    2124             : {
    2125             :     ae_int_t i;
    2126             :     double v;
    2127             :     double vv;
    2128             : 
    2129             : 
    2130           0 :     ae_assert(n>0, "RandomUnit: N<=0", _state);
    2131           0 :     if( x->cnt<n )
    2132             :     {
    2133           0 :         ae_vector_set_length(x, n, _state);
    2134             :     }
    2135           0 :     do
    2136             :     {
    2137           0 :         v = 0.0;
    2138           0 :         for(i=0; i<=n-1; i++)
    2139             :         {
    2140           0 :             vv = randomnormal(_state);
    2141           0 :             x->ptr.p_double[i] = vv;
    2142           0 :             v = v+vv*vv;
    2143             :         }
    2144             :     }
    2145           0 :     while(ae_fp_less_eq(v,(double)(0)));
    2146           0 :     v = 1/ae_sqrt(v, _state);
    2147           0 :     for(i=0; i<=n-1; i++)
    2148             :     {
    2149           0 :         x->ptr.p_double[i] = x->ptr.p_double[i]*v;
    2150             :     }
    2151           0 : }
    2152             : 
    2153             : 
    2154             : /*************************************************************************
    2155             : This function is used to swap two integer values
    2156             : *************************************************************************/
    2157           0 : void swapi(ae_int_t* v0, ae_int_t* v1, ae_state *_state)
    2158             : {
    2159             :     ae_int_t v;
    2160             : 
    2161             : 
    2162           0 :     v = *v0;
    2163           0 :     *v0 = *v1;
    2164           0 :     *v1 = v;
    2165           0 : }
    2166             : 
    2167             : 
    2168             : /*************************************************************************
    2169             : This function is used to swap two real values
    2170             : *************************************************************************/
    2171           0 : void swapr(double* v0, double* v1, ae_state *_state)
    2172             : {
    2173             :     double v;
    2174             : 
    2175             : 
    2176           0 :     v = *v0;
    2177           0 :     *v0 = *v1;
    2178           0 :     *v1 = v;
    2179           0 : }
    2180             : 
    2181             : 
    2182             : /*************************************************************************
    2183             : This function is used to swap two rows of the matrix; if NCols<0, automatically
    2184             : determined from the matrix size.
    2185             : *************************************************************************/
    2186           0 : void swaprows(/* Real    */ ae_matrix* a,
    2187             :      ae_int_t i0,
    2188             :      ae_int_t i1,
    2189             :      ae_int_t ncols,
    2190             :      ae_state *_state)
    2191             : {
    2192             :     ae_int_t j;
    2193             :     double v;
    2194             : 
    2195             : 
    2196           0 :     if( i0==i1 )
    2197             :     {
    2198           0 :         return;
    2199             :     }
    2200           0 :     if( ncols<0 )
    2201             :     {
    2202           0 :         ncols = a->cols;
    2203             :     }
    2204           0 :     for(j=0; j<=ncols-1; j++)
    2205             :     {
    2206           0 :         v = a->ptr.pp_double[i0][j];
    2207           0 :         a->ptr.pp_double[i0][j] = a->ptr.pp_double[i1][j];
    2208           0 :         a->ptr.pp_double[i1][j] = v;
    2209             :     }
    2210             : }
    2211             : 
    2212             : 
    2213             : /*************************************************************************
    2214             : This function is used to swap two cols of the matrix; if NRows<0, automatically
    2215             : determined from the matrix size.
    2216             : *************************************************************************/
    2217           0 : void swapcols(/* Real    */ ae_matrix* a,
    2218             :      ae_int_t j0,
    2219             :      ae_int_t j1,
    2220             :      ae_int_t nrows,
    2221             :      ae_state *_state)
    2222             : {
    2223             :     ae_int_t i;
    2224             :     double v;
    2225             : 
    2226             : 
    2227           0 :     if( j0==j1 )
    2228             :     {
    2229           0 :         return;
    2230             :     }
    2231           0 :     if( nrows<0 )
    2232             :     {
    2233           0 :         nrows = a->rows;
    2234             :     }
    2235           0 :     for(i=0; i<=nrows-1; i++)
    2236             :     {
    2237           0 :         v = a->ptr.pp_double[i][j0];
    2238           0 :         a->ptr.pp_double[i][j0] = a->ptr.pp_double[i][j1];
    2239           0 :         a->ptr.pp_double[i][j1] = v;
    2240             :     }
    2241             : }
    2242             : 
    2243             : 
    2244             : /*************************************************************************
    2245             : This function is used to swap two "entries" in 1-dimensional array composed
    2246             : from D-element entries
    2247             : *************************************************************************/
    2248           0 : void swapentries(/* Real    */ ae_vector* a,
    2249             :      ae_int_t i0,
    2250             :      ae_int_t i1,
    2251             :      ae_int_t entrywidth,
    2252             :      ae_state *_state)
    2253             : {
    2254             :     ae_int_t offs0;
    2255             :     ae_int_t offs1;
    2256             :     ae_int_t j;
    2257             :     double v;
    2258             : 
    2259             : 
    2260           0 :     if( i0==i1 )
    2261             :     {
    2262           0 :         return;
    2263             :     }
    2264           0 :     offs0 = i0*entrywidth;
    2265           0 :     offs1 = i1*entrywidth;
    2266           0 :     for(j=0; j<=entrywidth-1; j++)
    2267             :     {
    2268           0 :         v = a->ptr.p_double[offs0+j];
    2269           0 :         a->ptr.p_double[offs0+j] = a->ptr.p_double[offs1+j];
    2270           0 :         a->ptr.p_double[offs1+j] = v;
    2271             :     }
    2272             : }
    2273             : 
    2274             : 
    2275             : /*************************************************************************
    2276             : This function is used to swap two elements of the vector
    2277             : *************************************************************************/
    2278           0 : void swapelements(/* Real    */ ae_vector* a,
    2279             :      ae_int_t i0,
    2280             :      ae_int_t i1,
    2281             :      ae_state *_state)
    2282             : {
    2283             :     double v;
    2284             : 
    2285             : 
    2286           0 :     if( i0==i1 )
    2287             :     {
    2288           0 :         return;
    2289             :     }
    2290           0 :     v = a->ptr.p_double[i0];
    2291           0 :     a->ptr.p_double[i0] = a->ptr.p_double[i1];
    2292           0 :     a->ptr.p_double[i1] = v;
    2293             : }
    2294             : 
    2295             : 
    2296             : /*************************************************************************
    2297             : This function is used to swap two elements of the vector
    2298             : *************************************************************************/
    2299           0 : void swapelementsi(/* Integer */ ae_vector* a,
    2300             :      ae_int_t i0,
    2301             :      ae_int_t i1,
    2302             :      ae_state *_state)
    2303             : {
    2304             :     ae_int_t v;
    2305             : 
    2306             : 
    2307           0 :     if( i0==i1 )
    2308             :     {
    2309           0 :         return;
    2310             :     }
    2311           0 :     v = a->ptr.p_int[i0];
    2312           0 :     a->ptr.p_int[i0] = a->ptr.p_int[i1];
    2313           0 :     a->ptr.p_int[i1] = v;
    2314             : }
    2315             : 
    2316             : 
    2317             : /*************************************************************************
    2318             : This function is used to return maximum of three real values
    2319             : *************************************************************************/
    2320           0 : double maxreal3(double v0, double v1, double v2, ae_state *_state)
    2321             : {
    2322             :     double result;
    2323             : 
    2324             : 
    2325           0 :     result = v0;
    2326           0 :     if( ae_fp_less(result,v1) )
    2327             :     {
    2328           0 :         result = v1;
    2329             :     }
    2330           0 :     if( ae_fp_less(result,v2) )
    2331             :     {
    2332           0 :         result = v2;
    2333             :     }
    2334           0 :     return result;
    2335             : }
    2336             : 
    2337             : 
    2338             : /*************************************************************************
    2339             : This function is used to increment value of integer variable
    2340             : *************************************************************************/
    2341           0 : void inc(ae_int_t* v, ae_state *_state)
    2342             : {
    2343             : 
    2344             : 
    2345           0 :     *v = *v+1;
    2346           0 : }
    2347             : 
    2348             : 
    2349             : /*************************************************************************
    2350             : This function is used to decrement value of integer variable
    2351             : *************************************************************************/
    2352           0 : void dec(ae_int_t* v, ae_state *_state)
    2353             : {
    2354             : 
    2355             : 
    2356           0 :     *v = *v-1;
    2357           0 : }
    2358             : 
    2359             : 
    2360             : /*************************************************************************
    2361             : This function is used to increment value of integer variable; name of  the
    2362             : function suggests that increment is done in multithreaded setting  in  the
    2363             : thread-unsafe manner (optional progress reports which do not need guaranteed
    2364             : correctness)
    2365             : *************************************************************************/
    2366           0 : void threadunsafeinc(ae_int_t* v, ae_state *_state)
    2367             : {
    2368             : 
    2369             : 
    2370           0 :     *v = *v+1;
    2371           0 : }
    2372             : 
    2373             : 
    2374             : /*************************************************************************
    2375             : This function is used to increment value of integer variable; name of  the
    2376             : function suggests that increment is done in multithreaded setting  in  the
    2377             : thread-unsafe manner (optional progress reports which do not need guaranteed
    2378             : correctness)
    2379             : *************************************************************************/
    2380           0 : void threadunsafeincby(ae_int_t* v, ae_int_t k, ae_state *_state)
    2381             : {
    2382             : 
    2383             : 
    2384           0 :     *v = *v+k;
    2385           0 : }
    2386             : 
    2387             : 
    2388             : /*************************************************************************
    2389             : This function performs two operations:
    2390             : 1. decrements value of integer variable, if it is positive
    2391             : 2. explicitly sets variable to zero if it is non-positive
    2392             : It is used by some algorithms to decrease value of internal counters.
    2393             : *************************************************************************/
    2394           0 : void countdown(ae_int_t* v, ae_state *_state)
    2395             : {
    2396             : 
    2397             : 
    2398           0 :     if( *v>0 )
    2399             :     {
    2400           0 :         *v = *v-1;
    2401             :     }
    2402             :     else
    2403             :     {
    2404           0 :         *v = 0;
    2405             :     }
    2406           0 : }
    2407             : 
    2408             : 
    2409             : /*************************************************************************
    2410             : This function returns +1 or -1 depending on sign of X.
    2411             : x=0 results in +1 being returned.
    2412             : *************************************************************************/
    2413           0 : double possign(double x, ae_state *_state)
    2414             : {
    2415             :     double result;
    2416             : 
    2417             : 
    2418           0 :     if( ae_fp_greater_eq(x,(double)(0)) )
    2419             :     {
    2420           0 :         result = (double)(1);
    2421             :     }
    2422             :     else
    2423             :     {
    2424           0 :         result = (double)(-1);
    2425             :     }
    2426           0 :     return result;
    2427             : }
    2428             : 
    2429             : 
    2430             : /*************************************************************************
    2431             : This function returns product of two real numbers. It is convenient when
    2432             : you have to perform typecast-and-product of two INTEGERS.
    2433             : *************************************************************************/
    2434           0 : double rmul2(double v0, double v1, ae_state *_state)
    2435             : {
    2436             :     double result;
    2437             : 
    2438             : 
    2439           0 :     result = v0*v1;
    2440           0 :     return result;
    2441             : }
    2442             : 
    2443             : 
    2444             : /*************************************************************************
    2445             : This function returns product of three real numbers. It is convenient when
    2446             : you have to perform typecast-and-product of two INTEGERS.
    2447             : *************************************************************************/
    2448           0 : double rmul3(double v0, double v1, double v2, ae_state *_state)
    2449             : {
    2450             :     double result;
    2451             : 
    2452             : 
    2453           0 :     result = v0*v1*v2;
    2454           0 :     return result;
    2455             : }
    2456             : 
    2457             : 
    2458             : /*************************************************************************
    2459             : This function returns (A div B) rounded up; it expects that A>0, B>0, but
    2460             : does not check it.
    2461             : *************************************************************************/
    2462           0 : ae_int_t idivup(ae_int_t a, ae_int_t b, ae_state *_state)
    2463             : {
    2464             :     ae_int_t result;
    2465             : 
    2466             : 
    2467           0 :     result = a/b;
    2468           0 :     if( a%b>0 )
    2469             :     {
    2470           0 :         result = result+1;
    2471             :     }
    2472           0 :     return result;
    2473             : }
    2474             : 
    2475             : 
    2476             : /*************************************************************************
    2477             : This function returns min(i0,i1)
    2478             : *************************************************************************/
    2479           0 : ae_int_t imin2(ae_int_t i0, ae_int_t i1, ae_state *_state)
    2480             : {
    2481             :     ae_int_t result;
    2482             : 
    2483             : 
    2484           0 :     result = i0;
    2485           0 :     if( i1<result )
    2486             :     {
    2487           0 :         result = i1;
    2488             :     }
    2489           0 :     return result;
    2490             : }
    2491             : 
    2492             : 
    2493             : /*************************************************************************
    2494             : This function returns min(i0,i1,i2)
    2495             : *************************************************************************/
    2496           0 : ae_int_t imin3(ae_int_t i0, ae_int_t i1, ae_int_t i2, ae_state *_state)
    2497             : {
    2498             :     ae_int_t result;
    2499             : 
    2500             : 
    2501           0 :     result = i0;
    2502           0 :     if( i1<result )
    2503             :     {
    2504           0 :         result = i1;
    2505             :     }
    2506           0 :     if( i2<result )
    2507             :     {
    2508           0 :         result = i2;
    2509             :     }
    2510           0 :     return result;
    2511             : }
    2512             : 
    2513             : 
    2514             : /*************************************************************************
    2515             : This function returns max(i0,i1)
    2516             : *************************************************************************/
    2517           0 : ae_int_t imax2(ae_int_t i0, ae_int_t i1, ae_state *_state)
    2518             : {
    2519             :     ae_int_t result;
    2520             : 
    2521             : 
    2522           0 :     result = i0;
    2523           0 :     if( i1>result )
    2524             :     {
    2525           0 :         result = i1;
    2526             :     }
    2527           0 :     return result;
    2528             : }
    2529             : 
    2530             : 
    2531             : /*************************************************************************
    2532             : This function returns max(i0,i1,i2)
    2533             : *************************************************************************/
    2534           0 : ae_int_t imax3(ae_int_t i0, ae_int_t i1, ae_int_t i2, ae_state *_state)
    2535             : {
    2536             :     ae_int_t result;
    2537             : 
    2538             : 
    2539           0 :     result = i0;
    2540           0 :     if( i1>result )
    2541             :     {
    2542           0 :         result = i1;
    2543             :     }
    2544           0 :     if( i2>result )
    2545             :     {
    2546           0 :         result = i2;
    2547             :     }
    2548           0 :     return result;
    2549             : }
    2550             : 
    2551             : 
    2552             : /*************************************************************************
    2553             : This function returns max(r0,r1,r2)
    2554             : *************************************************************************/
    2555           0 : double rmax3(double r0, double r1, double r2, ae_state *_state)
    2556             : {
    2557             :     double result;
    2558             : 
    2559             : 
    2560           0 :     result = r0;
    2561           0 :     if( ae_fp_greater(r1,result) )
    2562             :     {
    2563           0 :         result = r1;
    2564             :     }
    2565           0 :     if( ae_fp_greater(r2,result) )
    2566             :     {
    2567           0 :         result = r2;
    2568             :     }
    2569           0 :     return result;
    2570             : }
    2571             : 
    2572             : 
    2573             : /*************************************************************************
    2574             : This function returns max(|r0|,|r1|,|r2|)
    2575             : *************************************************************************/
    2576           0 : double rmaxabs3(double r0, double r1, double r2, ae_state *_state)
    2577             : {
    2578             :     double result;
    2579             : 
    2580             : 
    2581           0 :     r0 = ae_fabs(r0, _state);
    2582           0 :     r1 = ae_fabs(r1, _state);
    2583           0 :     r2 = ae_fabs(r2, _state);
    2584           0 :     result = r0;
    2585           0 :     if( ae_fp_greater(r1,result) )
    2586             :     {
    2587           0 :         result = r1;
    2588             :     }
    2589           0 :     if( ae_fp_greater(r2,result) )
    2590             :     {
    2591           0 :         result = r2;
    2592             :     }
    2593           0 :     return result;
    2594             : }
    2595             : 
    2596             : 
    2597             : /*************************************************************************
    2598             : 'bounds' value: maps X to [B1,B2]
    2599             : 
    2600             :   -- ALGLIB --
    2601             :      Copyright 20.03.2009 by Bochkanov Sergey
    2602             : *************************************************************************/
    2603           0 : double boundval(double x, double b1, double b2, ae_state *_state)
    2604             : {
    2605             :     double result;
    2606             : 
    2607             : 
    2608           0 :     if( ae_fp_less_eq(x,b1) )
    2609             :     {
    2610           0 :         result = b1;
    2611           0 :         return result;
    2612             :     }
    2613           0 :     if( ae_fp_greater_eq(x,b2) )
    2614             :     {
    2615           0 :         result = b2;
    2616           0 :         return result;
    2617             :     }
    2618           0 :     result = x;
    2619           0 :     return result;
    2620             : }
    2621             : 
    2622             : 
    2623             : /*************************************************************************
    2624             : 'bounds' value: maps X to [B1,B2]
    2625             : 
    2626             :   -- ALGLIB --
    2627             :      Copyright 20.03.2009 by Bochkanov Sergey
    2628             : *************************************************************************/
    2629           0 : ae_int_t iboundval(ae_int_t x, ae_int_t b1, ae_int_t b2, ae_state *_state)
    2630             : {
    2631             :     ae_int_t result;
    2632             : 
    2633             : 
    2634           0 :     if( x<=b1 )
    2635             :     {
    2636           0 :         result = b1;
    2637           0 :         return result;
    2638             :     }
    2639           0 :     if( x>=b2 )
    2640             :     {
    2641           0 :         result = b2;
    2642           0 :         return result;
    2643             :     }
    2644           0 :     result = x;
    2645           0 :     return result;
    2646             : }
    2647             : 
    2648             : 
    2649             : /*************************************************************************
    2650             : 'bounds' value: maps X to [B1,B2]
    2651             : 
    2652             :   -- ALGLIB --
    2653             :      Copyright 20.03.2009 by Bochkanov Sergey
    2654             : *************************************************************************/
    2655           0 : double rboundval(double x, double b1, double b2, ae_state *_state)
    2656             : {
    2657             :     double result;
    2658             : 
    2659             : 
    2660           0 :     if( ae_fp_less_eq(x,b1) )
    2661             :     {
    2662           0 :         result = b1;
    2663           0 :         return result;
    2664             :     }
    2665           0 :     if( ae_fp_greater_eq(x,b2) )
    2666             :     {
    2667           0 :         result = b2;
    2668           0 :         return result;
    2669             :     }
    2670           0 :     result = x;
    2671           0 :     return result;
    2672             : }
    2673             : 
    2674             : 
    2675             : /*************************************************************************
    2676             : Returns number of non-zeros
    2677             : *************************************************************************/
    2678           0 : ae_int_t countnz1(/* Real    */ ae_vector* v,
    2679             :      ae_int_t n,
    2680             :      ae_state *_state)
    2681             : {
    2682             :     ae_int_t i;
    2683             :     ae_int_t result;
    2684             : 
    2685             : 
    2686           0 :     result = 0;
    2687           0 :     for(i=0; i<=n-1; i++)
    2688             :     {
    2689           0 :         if( !(v->ptr.p_double[i]==0) )
    2690             :         {
    2691           0 :             result = result+1;
    2692             :         }
    2693             :     }
    2694           0 :     return result;
    2695             : }
    2696             : 
    2697             : 
    2698             : /*************************************************************************
    2699             : Returns number of non-zeros
    2700             : *************************************************************************/
    2701           0 : ae_int_t countnz2(/* Real    */ ae_matrix* v,
    2702             :      ae_int_t m,
    2703             :      ae_int_t n,
    2704             :      ae_state *_state)
    2705             : {
    2706             :     ae_int_t i;
    2707             :     ae_int_t j;
    2708             :     ae_int_t result;
    2709             : 
    2710             : 
    2711           0 :     result = 0;
    2712           0 :     for(i=0; i<=m-1; i++)
    2713             :     {
    2714           0 :         for(j=0; j<=n-1; j++)
    2715             :         {
    2716           0 :             if( !(v->ptr.pp_double[i][j]==0) )
    2717             :             {
    2718           0 :                 result = result+1;
    2719             :             }
    2720             :         }
    2721             :     }
    2722           0 :     return result;
    2723             : }
    2724             : 
    2725             : 
    2726             : /*************************************************************************
    2727             : Allocation of serializer: complex value
    2728             : *************************************************************************/
    2729           0 : void alloccomplex(ae_serializer* s, ae_complex v, ae_state *_state)
    2730             : {
    2731             : 
    2732             : 
    2733           0 :     ae_serializer_alloc_entry(s);
    2734           0 :     ae_serializer_alloc_entry(s);
    2735           0 : }
    2736             : 
    2737             : 
    2738             : /*************************************************************************
    2739             : Serialization: complex value
    2740             : *************************************************************************/
    2741           0 : void serializecomplex(ae_serializer* s, ae_complex v, ae_state *_state)
    2742             : {
    2743             : 
    2744             : 
    2745           0 :     ae_serializer_serialize_double(s, v.x, _state);
    2746           0 :     ae_serializer_serialize_double(s, v.y, _state);
    2747           0 : }
    2748             : 
    2749             : 
    2750             : /*************************************************************************
    2751             : Unserialization: complex value
    2752             : *************************************************************************/
    2753           0 : ae_complex unserializecomplex(ae_serializer* s, ae_state *_state)
    2754             : {
    2755             :     ae_complex result;
    2756             : 
    2757             : 
    2758           0 :     ae_serializer_unserialize_double(s, &result.x, _state);
    2759           0 :     ae_serializer_unserialize_double(s, &result.y, _state);
    2760           0 :     return result;
    2761             : }
    2762             : 
    2763             : 
    2764             : /*************************************************************************
    2765             : Allocation of serializer: real array
    2766             : *************************************************************************/
    2767           0 : void allocrealarray(ae_serializer* s,
    2768             :      /* Real    */ ae_vector* v,
    2769             :      ae_int_t n,
    2770             :      ae_state *_state)
    2771             : {
    2772             :     ae_int_t i;
    2773             : 
    2774             : 
    2775           0 :     if( n<0 )
    2776             :     {
    2777           0 :         n = v->cnt;
    2778             :     }
    2779           0 :     ae_serializer_alloc_entry(s);
    2780           0 :     for(i=0; i<=n-1; i++)
    2781             :     {
    2782           0 :         ae_serializer_alloc_entry(s);
    2783             :     }
    2784           0 : }
    2785             : 
    2786             : 
    2787             : /*************************************************************************
    2788             : Serialization: complex value
    2789             : *************************************************************************/
    2790           0 : void serializerealarray(ae_serializer* s,
    2791             :      /* Real    */ ae_vector* v,
    2792             :      ae_int_t n,
    2793             :      ae_state *_state)
    2794             : {
    2795             :     ae_int_t i;
    2796             : 
    2797             : 
    2798           0 :     if( n<0 )
    2799             :     {
    2800           0 :         n = v->cnt;
    2801             :     }
    2802           0 :     ae_serializer_serialize_int(s, n, _state);
    2803           0 :     for(i=0; i<=n-1; i++)
    2804             :     {
    2805           0 :         ae_serializer_serialize_double(s, v->ptr.p_double[i], _state);
    2806             :     }
    2807           0 : }
    2808             : 
    2809             : 
    2810             : /*************************************************************************
    2811             : Unserialization: complex value
    2812             : *************************************************************************/
    2813           0 : void unserializerealarray(ae_serializer* s,
    2814             :      /* Real    */ ae_vector* v,
    2815             :      ae_state *_state)
    2816             : {
    2817             :     ae_int_t n;
    2818             :     ae_int_t i;
    2819             :     double t;
    2820             : 
    2821           0 :     ae_vector_clear(v);
    2822             : 
    2823           0 :     ae_serializer_unserialize_int(s, &n, _state);
    2824           0 :     if( n==0 )
    2825             :     {
    2826           0 :         return;
    2827             :     }
    2828           0 :     ae_vector_set_length(v, n, _state);
    2829           0 :     for(i=0; i<=n-1; i++)
    2830             :     {
    2831           0 :         ae_serializer_unserialize_double(s, &t, _state);
    2832           0 :         v->ptr.p_double[i] = t;
    2833             :     }
    2834             : }
    2835             : 
    2836             : 
    2837             : /*************************************************************************
    2838             : Allocation of serializer: Integer array
    2839             : *************************************************************************/
    2840           0 : void allocintegerarray(ae_serializer* s,
    2841             :      /* Integer */ ae_vector* v,
    2842             :      ae_int_t n,
    2843             :      ae_state *_state)
    2844             : {
    2845             :     ae_int_t i;
    2846             : 
    2847             : 
    2848           0 :     if( n<0 )
    2849             :     {
    2850           0 :         n = v->cnt;
    2851             :     }
    2852           0 :     ae_serializer_alloc_entry(s);
    2853           0 :     for(i=0; i<=n-1; i++)
    2854             :     {
    2855           0 :         ae_serializer_alloc_entry(s);
    2856             :     }
    2857           0 : }
    2858             : 
    2859             : 
    2860             : /*************************************************************************
    2861             : Serialization: Integer array
    2862             : *************************************************************************/
    2863           0 : void serializeintegerarray(ae_serializer* s,
    2864             :      /* Integer */ ae_vector* v,
    2865             :      ae_int_t n,
    2866             :      ae_state *_state)
    2867             : {
    2868             :     ae_int_t i;
    2869             : 
    2870             : 
    2871           0 :     if( n<0 )
    2872             :     {
    2873           0 :         n = v->cnt;
    2874             :     }
    2875           0 :     ae_serializer_serialize_int(s, n, _state);
    2876           0 :     for(i=0; i<=n-1; i++)
    2877             :     {
    2878           0 :         ae_serializer_serialize_int(s, v->ptr.p_int[i], _state);
    2879             :     }
    2880           0 : }
    2881             : 
    2882             : 
    2883             : /*************************************************************************
    2884             : Unserialization: complex value
    2885             : *************************************************************************/
    2886           0 : void unserializeintegerarray(ae_serializer* s,
    2887             :      /* Integer */ ae_vector* v,
    2888             :      ae_state *_state)
    2889             : {
    2890             :     ae_int_t n;
    2891             :     ae_int_t i;
    2892             :     ae_int_t t;
    2893             : 
    2894           0 :     ae_vector_clear(v);
    2895             : 
    2896           0 :     ae_serializer_unserialize_int(s, &n, _state);
    2897           0 :     if( n==0 )
    2898             :     {
    2899           0 :         return;
    2900             :     }
    2901           0 :     ae_vector_set_length(v, n, _state);
    2902           0 :     for(i=0; i<=n-1; i++)
    2903             :     {
    2904           0 :         ae_serializer_unserialize_int(s, &t, _state);
    2905           0 :         v->ptr.p_int[i] = t;
    2906             :     }
    2907             : }
    2908             : 
    2909             : 
    2910             : /*************************************************************************
    2911             : Allocation of serializer: real matrix
    2912             : *************************************************************************/
    2913           0 : void allocrealmatrix(ae_serializer* s,
    2914             :      /* Real    */ ae_matrix* v,
    2915             :      ae_int_t n0,
    2916             :      ae_int_t n1,
    2917             :      ae_state *_state)
    2918             : {
    2919             :     ae_int_t i;
    2920             :     ae_int_t j;
    2921             : 
    2922             : 
    2923           0 :     if( n0<0 )
    2924             :     {
    2925           0 :         n0 = v->rows;
    2926             :     }
    2927           0 :     if( n1<0 )
    2928             :     {
    2929           0 :         n1 = v->cols;
    2930             :     }
    2931           0 :     ae_serializer_alloc_entry(s);
    2932           0 :     ae_serializer_alloc_entry(s);
    2933           0 :     for(i=0; i<=n0-1; i++)
    2934             :     {
    2935           0 :         for(j=0; j<=n1-1; j++)
    2936             :         {
    2937           0 :             ae_serializer_alloc_entry(s);
    2938             :         }
    2939             :     }
    2940           0 : }
    2941             : 
    2942             : 
    2943             : /*************************************************************************
    2944             : Serialization: complex value
    2945             : *************************************************************************/
    2946           0 : void serializerealmatrix(ae_serializer* s,
    2947             :      /* Real    */ ae_matrix* v,
    2948             :      ae_int_t n0,
    2949             :      ae_int_t n1,
    2950             :      ae_state *_state)
    2951             : {
    2952             :     ae_int_t i;
    2953             :     ae_int_t j;
    2954             : 
    2955             : 
    2956           0 :     if( n0<0 )
    2957             :     {
    2958           0 :         n0 = v->rows;
    2959             :     }
    2960           0 :     if( n1<0 )
    2961             :     {
    2962           0 :         n1 = v->cols;
    2963             :     }
    2964           0 :     ae_serializer_serialize_int(s, n0, _state);
    2965           0 :     ae_serializer_serialize_int(s, n1, _state);
    2966           0 :     for(i=0; i<=n0-1; i++)
    2967             :     {
    2968           0 :         for(j=0; j<=n1-1; j++)
    2969             :         {
    2970           0 :             ae_serializer_serialize_double(s, v->ptr.pp_double[i][j], _state);
    2971             :         }
    2972             :     }
    2973           0 : }
    2974             : 
    2975             : 
    2976             : /*************************************************************************
    2977             : Unserialization: complex value
    2978             : *************************************************************************/
    2979           0 : void unserializerealmatrix(ae_serializer* s,
    2980             :      /* Real    */ ae_matrix* v,
    2981             :      ae_state *_state)
    2982             : {
    2983             :     ae_int_t i;
    2984             :     ae_int_t j;
    2985             :     ae_int_t n0;
    2986             :     ae_int_t n1;
    2987             :     double t;
    2988             : 
    2989           0 :     ae_matrix_clear(v);
    2990             : 
    2991           0 :     ae_serializer_unserialize_int(s, &n0, _state);
    2992           0 :     ae_serializer_unserialize_int(s, &n1, _state);
    2993           0 :     if( n0==0||n1==0 )
    2994             :     {
    2995           0 :         return;
    2996             :     }
    2997           0 :     ae_matrix_set_length(v, n0, n1, _state);
    2998           0 :     for(i=0; i<=n0-1; i++)
    2999             :     {
    3000           0 :         for(j=0; j<=n1-1; j++)
    3001             :         {
    3002           0 :             ae_serializer_unserialize_double(s, &t, _state);
    3003           0 :             v->ptr.pp_double[i][j] = t;
    3004             :         }
    3005             :     }
    3006             : }
    3007             : 
    3008             : 
    3009             : /*************************************************************************
    3010             : Copy boolean array
    3011             : *************************************************************************/
    3012           0 : void copybooleanarray(/* Boolean */ ae_vector* src,
    3013             :      /* Boolean */ ae_vector* dst,
    3014             :      ae_state *_state)
    3015             : {
    3016             :     ae_int_t i;
    3017             : 
    3018           0 :     ae_vector_clear(dst);
    3019             : 
    3020           0 :     if( src->cnt>0 )
    3021             :     {
    3022           0 :         ae_vector_set_length(dst, src->cnt, _state);
    3023           0 :         for(i=0; i<=src->cnt-1; i++)
    3024             :         {
    3025           0 :             dst->ptr.p_bool[i] = src->ptr.p_bool[i];
    3026             :         }
    3027             :     }
    3028           0 : }
    3029             : 
    3030             : 
    3031             : /*************************************************************************
    3032             : Copy integer array
    3033             : *************************************************************************/
    3034           0 : void copyintegerarray(/* Integer */ ae_vector* src,
    3035             :      /* Integer */ ae_vector* dst,
    3036             :      ae_state *_state)
    3037             : {
    3038             :     ae_int_t i;
    3039             : 
    3040           0 :     ae_vector_clear(dst);
    3041             : 
    3042           0 :     if( src->cnt>0 )
    3043             :     {
    3044           0 :         ae_vector_set_length(dst, src->cnt, _state);
    3045           0 :         for(i=0; i<=src->cnt-1; i++)
    3046             :         {
    3047           0 :             dst->ptr.p_int[i] = src->ptr.p_int[i];
    3048             :         }
    3049             :     }
    3050           0 : }
    3051             : 
    3052             : 
    3053             : /*************************************************************************
    3054             : Copy real array
    3055             : *************************************************************************/
    3056           0 : void copyrealarray(/* Real    */ ae_vector* src,
    3057             :      /* Real    */ ae_vector* dst,
    3058             :      ae_state *_state)
    3059             : {
    3060             :     ae_int_t i;
    3061             : 
    3062           0 :     ae_vector_clear(dst);
    3063             : 
    3064           0 :     if( src->cnt>0 )
    3065             :     {
    3066           0 :         ae_vector_set_length(dst, src->cnt, _state);
    3067           0 :         for(i=0; i<=src->cnt-1; i++)
    3068             :         {
    3069           0 :             dst->ptr.p_double[i] = src->ptr.p_double[i];
    3070             :         }
    3071             :     }
    3072           0 : }
    3073             : 
    3074             : 
    3075             : /*************************************************************************
    3076             : Copy real matrix
    3077             : *************************************************************************/
    3078           0 : void copyrealmatrix(/* Real    */ ae_matrix* src,
    3079             :      /* Real    */ ae_matrix* dst,
    3080             :      ae_state *_state)
    3081             : {
    3082             :     ae_int_t i;
    3083             :     ae_int_t j;
    3084             : 
    3085           0 :     ae_matrix_clear(dst);
    3086             : 
    3087           0 :     if( src->rows>0&&src->cols>0 )
    3088             :     {
    3089           0 :         ae_matrix_set_length(dst, src->rows, src->cols, _state);
    3090           0 :         for(i=0; i<=src->rows-1; i++)
    3091             :         {
    3092           0 :             for(j=0; j<=src->cols-1; j++)
    3093             :             {
    3094           0 :                 dst->ptr.pp_double[i][j] = src->ptr.pp_double[i][j];
    3095             :             }
    3096             :         }
    3097             :     }
    3098           0 : }
    3099             : 
    3100             : 
    3101             : /*************************************************************************
    3102             : Clears integer array
    3103             : *************************************************************************/
    3104           0 : void unsetintegerarray(/* Integer */ ae_vector* a, ae_state *_state)
    3105             : {
    3106             : 
    3107           0 :     ae_vector_clear(a);
    3108             : 
    3109           0 : }
    3110             : 
    3111             : 
    3112             : /*************************************************************************
    3113             : Clears real array
    3114             : *************************************************************************/
    3115           0 : void unsetrealarray(/* Real    */ ae_vector* a, ae_state *_state)
    3116             : {
    3117             : 
    3118           0 :     ae_vector_clear(a);
    3119             : 
    3120           0 : }
    3121             : 
    3122             : 
    3123             : /*************************************************************************
    3124             : Clears real matrix
    3125             : *************************************************************************/
    3126           0 : void unsetrealmatrix(/* Real    */ ae_matrix* a, ae_state *_state)
    3127             : {
    3128             : 
    3129           0 :     ae_matrix_clear(a);
    3130             : 
    3131           0 : }
    3132             : 
    3133             : 
    3134             : /*************************************************************************
    3135             : This function is used in parallel functions for recurrent division of large
    3136             : task into two smaller tasks.
    3137             : 
    3138             : It has following properties:
    3139             : * it works only for TaskSize>=2 and TaskSize>TileSize (assertion is thrown otherwise)
    3140             : * Task0+Task1=TaskSize, Task0>0, Task1>0
    3141             : * Task0 and Task1 are close to each other
    3142             : * Task0>=Task1
    3143             : * Task0 is always divisible by TileSize
    3144             : 
    3145             :   -- ALGLIB --
    3146             :      Copyright 07.04.2013 by Bochkanov Sergey
    3147             : *************************************************************************/
    3148           0 : void tiledsplit(ae_int_t tasksize,
    3149             :      ae_int_t tilesize,
    3150             :      ae_int_t* task0,
    3151             :      ae_int_t* task1,
    3152             :      ae_state *_state)
    3153             : {
    3154             :     ae_int_t cc;
    3155             : 
    3156           0 :     *task0 = 0;
    3157           0 :     *task1 = 0;
    3158             : 
    3159           0 :     ae_assert(tasksize>=2, "TiledSplit: TaskSize<2", _state);
    3160           0 :     ae_assert(tasksize>tilesize, "TiledSplit: TaskSize<=TileSize", _state);
    3161           0 :     cc = chunkscount(tasksize, tilesize, _state);
    3162           0 :     ae_assert(cc>=2, "TiledSplit: integrity check failed", _state);
    3163           0 :     *task0 = idivup(cc, 2, _state)*tilesize;
    3164           0 :     *task1 = tasksize-(*task0);
    3165           0 :     ae_assert(*task0>=1, "TiledSplit: internal error", _state);
    3166           0 :     ae_assert(*task1>=1, "TiledSplit: internal error", _state);
    3167           0 :     ae_assert(*task0%tilesize==0, "TiledSplit: internal error", _state);
    3168           0 :     ae_assert(*task0>=(*task1), "TiledSplit: internal error", _state);
    3169           0 : }
    3170             : 
    3171             : 
    3172             : /*************************************************************************
    3173             : This function searches integer array. Elements in this array are actually
    3174             : records, each NRec elements wide. Each record has unique header - NHeader
    3175             : integer values, which identify it. Records are lexicographically sorted by
    3176             : header.
    3177             : 
    3178             : Records are identified by their index, not offset (offset = NRec*index).
    3179             : 
    3180             : This function searches A (records with indices [I0,I1)) for a record with
    3181             : header B. It returns index of this record (not offset!), or -1 on failure.
    3182             : 
    3183             :   -- ALGLIB --
    3184             :      Copyright 28.03.2011 by Bochkanov Sergey
    3185             : *************************************************************************/
    3186           0 : ae_int_t recsearch(/* Integer */ ae_vector* a,
    3187             :      ae_int_t nrec,
    3188             :      ae_int_t nheader,
    3189             :      ae_int_t i0,
    3190             :      ae_int_t i1,
    3191             :      /* Integer */ ae_vector* b,
    3192             :      ae_state *_state)
    3193             : {
    3194             :     ae_int_t mididx;
    3195             :     ae_int_t cflag;
    3196             :     ae_int_t k;
    3197             :     ae_int_t offs;
    3198             :     ae_int_t result;
    3199             : 
    3200             : 
    3201           0 :     result = -1;
    3202             :     for(;;)
    3203             :     {
    3204           0 :         if( i0>=i1 )
    3205             :         {
    3206           0 :             break;
    3207             :         }
    3208           0 :         mididx = (i0+i1)/2;
    3209           0 :         offs = nrec*mididx;
    3210           0 :         cflag = 0;
    3211           0 :         for(k=0; k<=nheader-1; k++)
    3212             :         {
    3213           0 :             if( a->ptr.p_int[offs+k]<b->ptr.p_int[k] )
    3214             :             {
    3215           0 :                 cflag = -1;
    3216           0 :                 break;
    3217             :             }
    3218           0 :             if( a->ptr.p_int[offs+k]>b->ptr.p_int[k] )
    3219             :             {
    3220           0 :                 cflag = 1;
    3221           0 :                 break;
    3222             :             }
    3223             :         }
    3224           0 :         if( cflag==0 )
    3225             :         {
    3226           0 :             result = mididx;
    3227           0 :             return result;
    3228             :         }
    3229           0 :         if( cflag<0 )
    3230             :         {
    3231           0 :             i0 = mididx+1;
    3232             :         }
    3233             :         else
    3234             :         {
    3235           0 :             i1 = mididx;
    3236             :         }
    3237             :     }
    3238           0 :     return result;
    3239             : }
    3240             : 
    3241             : 
    3242             : /*************************************************************************
    3243             : This function is used in parallel functions for recurrent division of large
    3244             : task into two smaller tasks.
    3245             : 
    3246             : It has following properties:
    3247             : * it works only for TaskSize>=2 (assertion is thrown otherwise)
    3248             : * for TaskSize=2, it returns Task0=1, Task1=1
    3249             : * in case TaskSize is odd,  Task0=TaskSize-1, Task1=1
    3250             : * in case TaskSize is even, Task0 and Task1 are approximately TaskSize/2
    3251             :   and both Task0 and Task1 are even, Task0>=Task1
    3252             : 
    3253             :   -- ALGLIB --
    3254             :      Copyright 07.04.2013 by Bochkanov Sergey
    3255             : *************************************************************************/
    3256           0 : void splitlengtheven(ae_int_t tasksize,
    3257             :      ae_int_t* task0,
    3258             :      ae_int_t* task1,
    3259             :      ae_state *_state)
    3260             : {
    3261             : 
    3262           0 :     *task0 = 0;
    3263           0 :     *task1 = 0;
    3264             : 
    3265           0 :     ae_assert(tasksize>=2, "SplitLengthEven: TaskSize<2", _state);
    3266           0 :     if( tasksize==2 )
    3267             :     {
    3268           0 :         *task0 = 1;
    3269           0 :         *task1 = 1;
    3270           0 :         return;
    3271             :     }
    3272           0 :     if( tasksize%2==0 )
    3273             :     {
    3274             :         
    3275             :         /*
    3276             :          * Even division
    3277             :          */
    3278           0 :         *task0 = tasksize/2;
    3279           0 :         *task1 = tasksize/2;
    3280           0 :         if( *task0%2!=0 )
    3281             :         {
    3282           0 :             *task0 = *task0+1;
    3283           0 :             *task1 = *task1-1;
    3284             :         }
    3285             :     }
    3286             :     else
    3287             :     {
    3288             :         
    3289             :         /*
    3290             :          * Odd task size, split trailing odd part from it.
    3291             :          */
    3292           0 :         *task0 = tasksize-1;
    3293           0 :         *task1 = 1;
    3294             :     }
    3295           0 :     ae_assert(*task0>=1, "SplitLengthEven: internal error", _state);
    3296           0 :     ae_assert(*task1>=1, "SplitLengthEven: internal error", _state);
    3297             : }
    3298             : 
    3299             : 
    3300             : /*************************************************************************
    3301             : This function is used to calculate number of chunks (including partial,
    3302             : non-complete chunks) in some set. It expects that ChunkSize>=1, TaskSize>=0.
    3303             : Assertion is thrown otherwise.
    3304             : 
    3305             : Function result is equivalent to Ceil(TaskSize/ChunkSize), but with guarantees
    3306             : that rounding errors won't ruin results.
    3307             : 
    3308             :   -- ALGLIB --
    3309             :      Copyright 21.01.2015 by Bochkanov Sergey
    3310             : *************************************************************************/
    3311           0 : ae_int_t chunkscount(ae_int_t tasksize,
    3312             :      ae_int_t chunksize,
    3313             :      ae_state *_state)
    3314             : {
    3315             :     ae_int_t result;
    3316             : 
    3317             : 
    3318           0 :     ae_assert(tasksize>=0, "ChunksCount: TaskSize<0", _state);
    3319           0 :     ae_assert(chunksize>=1, "ChunksCount: ChunkSize<1", _state);
    3320           0 :     result = tasksize/chunksize;
    3321           0 :     if( tasksize%chunksize!=0 )
    3322             :     {
    3323           0 :         result = result+1;
    3324             :     }
    3325           0 :     return result;
    3326             : }
    3327             : 
    3328             : 
    3329             : /*************************************************************************
    3330             : Returns maximum density for level 2 sparse/dense functions. Density values
    3331             : below one returned by this function are better to handle via sparse Level 2
    3332             : functionality.
    3333             : 
    3334             :   -- ALGLIB routine --
    3335             :      10.01.2019
    3336             :      Bochkanov Sergey
    3337             : *************************************************************************/
    3338           0 : double sparselevel2density(ae_state *_state)
    3339             : {
    3340             :     double result;
    3341             : 
    3342             : 
    3343           0 :     result = 0.1;
    3344           0 :     return result;
    3345             : }
    3346             : 
    3347             : 
    3348             : /*************************************************************************
    3349             : Returns A-tile size for a matrix.
    3350             : 
    3351             : A-tiles are smallest tiles (32x32), suitable for processing by ALGLIB  own
    3352             : implementation of Level 3 linear algebra.
    3353             : 
    3354             :   -- ALGLIB routine --
    3355             :      10.01.2019
    3356             :      Bochkanov Sergey
    3357             : *************************************************************************/
    3358           0 : ae_int_t matrixtilesizea(ae_state *_state)
    3359             : {
    3360             :     ae_int_t result;
    3361             : 
    3362             : 
    3363           0 :     result = 32;
    3364           0 :     return result;
    3365             : }
    3366             : 
    3367             : 
    3368             : /*************************************************************************
    3369             : Returns B-tile size for a matrix.
    3370             : 
    3371             : B-tiles are larger  tiles (64x64), suitable for parallel execution or for
    3372             : processing by vendor's implementation of Level 3 linear algebra.
    3373             : 
    3374             :   -- ALGLIB routine --
    3375             :      10.01.2019
    3376             :      Bochkanov Sergey
    3377             : *************************************************************************/
    3378           0 : ae_int_t matrixtilesizeb(ae_state *_state)
    3379             : {
    3380             : #ifndef ALGLIB_INTERCEPTS_MKL
    3381             :     ae_int_t result;
    3382             : 
    3383             : 
    3384           0 :     result = 64;
    3385           0 :     return result;
    3386             : #else
    3387             :     return _ialglib_i_matrixtilesizeb();
    3388             : #endif
    3389             : }
    3390             : 
    3391             : 
    3392             : /*************************************************************************
    3393             : This function returns minimum cost of task which is feasible for
    3394             : multithreaded processing. It returns real number in order to avoid overflow
    3395             : problems.
    3396             : 
    3397             :   -- ALGLIB --
    3398             :      Copyright 10.01.2018 by Bochkanov Sergey
    3399             : *************************************************************************/
    3400           0 : double smpactivationlevel(ae_state *_state)
    3401             : {
    3402             :     double nn;
    3403             :     double result;
    3404             : 
    3405             : 
    3406           0 :     nn = (double)(2*matrixtilesizeb(_state));
    3407           0 :     result = ae_maxreal(0.95*2*nn*nn*nn, 1.0E7, _state);
    3408           0 :     return result;
    3409             : }
    3410             : 
    3411             : 
    3412             : /*************************************************************************
    3413             : This function returns minimum cost of task which is feasible for
    3414             : spawn (given that multithreading is active).
    3415             : 
    3416             : It returns real number in order to avoid overflow problems.
    3417             : 
    3418             :   -- ALGLIB --
    3419             :      Copyright 10.01.2018 by Bochkanov Sergey
    3420             : *************************************************************************/
    3421           0 : double spawnlevel(ae_state *_state)
    3422             : {
    3423             :     double nn;
    3424             :     double result;
    3425             : 
    3426             : 
    3427           0 :     nn = (double)(2*matrixtilesizea(_state));
    3428           0 :     result = 0.95*2*nn*nn*nn;
    3429           0 :     return result;
    3430             : }
    3431             : 
    3432             : 
    3433             : /*************************************************************************
    3434             : --- OBSOLETE FUNCTION, USE TILED SPLIT INSTEAD --- 
    3435             : 
    3436             : This function is used in parallel functions for recurrent division of large
    3437             : task into two smaller tasks.
    3438             : 
    3439             : It has following properties:
    3440             : * it works only for TaskSize>=2 and ChunkSize>=2
    3441             :   (assertion is thrown otherwise)
    3442             : * Task0+Task1=TaskSize, Task0>0, Task1>0
    3443             : * Task0 and Task1 are close to each other
    3444             : * in case TaskSize>ChunkSize, Task0 is always divisible by ChunkSize
    3445             : 
    3446             :   -- ALGLIB --
    3447             :      Copyright 07.04.2013 by Bochkanov Sergey
    3448             : *************************************************************************/
    3449           0 : void splitlength(ae_int_t tasksize,
    3450             :      ae_int_t chunksize,
    3451             :      ae_int_t* task0,
    3452             :      ae_int_t* task1,
    3453             :      ae_state *_state)
    3454             : {
    3455             : 
    3456           0 :     *task0 = 0;
    3457           0 :     *task1 = 0;
    3458             : 
    3459           0 :     ae_assert(chunksize>=2, "SplitLength: ChunkSize<2", _state);
    3460           0 :     ae_assert(tasksize>=2, "SplitLength: TaskSize<2", _state);
    3461           0 :     *task0 = tasksize/2;
    3462           0 :     if( *task0>chunksize&&*task0%chunksize!=0 )
    3463             :     {
    3464           0 :         *task0 = *task0-*task0%chunksize;
    3465             :     }
    3466           0 :     *task1 = tasksize-(*task0);
    3467           0 :     ae_assert(*task0>=1, "SplitLength: internal error", _state);
    3468           0 :     ae_assert(*task1>=1, "SplitLength: internal error", _state);
    3469           0 : }
    3470             : 
    3471             : 
    3472             : /*************************************************************************
    3473             : Outputs vector A[I0,I1-1] to trace log using either:
    3474             : a)  6-digit exponential format (no trace flags is set)
    3475             : b) 15-ditit exponential format ('PREC.E15' trace flag is set)
    3476             : b)  6-ditit fixed-point format ('PREC.F6' trace flag is set)
    3477             : 
    3478             : This function checks trace flags every time it is called.
    3479             : *************************************************************************/
    3480           0 : void tracevectorautoprec(/* Real    */ ae_vector* a,
    3481             :      ae_int_t i0,
    3482             :      ae_int_t i1,
    3483             :      ae_state *_state)
    3484             : {
    3485             :     ae_int_t i;
    3486             :     ae_int_t prectouse;
    3487             : 
    3488             : 
    3489             :     
    3490             :     /*
    3491             :      * Determine precision to use
    3492             :      */
    3493           0 :     prectouse = 0;
    3494           0 :     if( ae_is_trace_enabled("PREC.E15") )
    3495             :     {
    3496           0 :         prectouse = 1;
    3497             :     }
    3498           0 :     if( ae_is_trace_enabled("PREC.F6") )
    3499             :     {
    3500           0 :         prectouse = 2;
    3501             :     }
    3502             :     
    3503             :     /*
    3504             :      * Output
    3505             :      */
    3506           0 :     ae_trace("[ ");
    3507           0 :     for(i=i0; i<=i1-1; i++)
    3508             :     {
    3509           0 :         if( prectouse==0 )
    3510             :         {
    3511           0 :             ae_trace("%14.6e",
    3512           0 :                 (double)(a->ptr.p_double[i]));
    3513             :         }
    3514           0 :         if( prectouse==1 )
    3515             :         {
    3516           0 :             ae_trace("%23.15e",
    3517           0 :                 (double)(a->ptr.p_double[i]));
    3518             :         }
    3519           0 :         if( prectouse==2 )
    3520             :         {
    3521           0 :             ae_trace("%13.6f",
    3522           0 :                 (double)(a->ptr.p_double[i]));
    3523             :         }
    3524           0 :         if( i<i1-1 )
    3525             :         {
    3526           0 :             ae_trace(" ");
    3527             :         }
    3528             :     }
    3529           0 :     ae_trace(" ]");
    3530           0 : }
    3531             : 
    3532             : 
    3533             : /*************************************************************************
    3534             : Unscales/unshifts vector A[N] by computing A*Scl+Sft and outputs result to
    3535             : trace log using either:
    3536             : a)  6-digit exponential format (no trace flags is set)
    3537             : b) 15-ditit exponential format ('PREC.E15' trace flag is set)
    3538             : b)  6-ditit fixed-point format ('PREC.F6' trace flag is set)
    3539             : 
    3540             : This function checks trace flags every time it is called.
    3541             : Both Scl and Sft can be omitted.
    3542             : *************************************************************************/
    3543           0 : void tracevectorunscaledunshiftedautoprec(/* Real    */ ae_vector* x,
    3544             :      ae_int_t n,
    3545             :      /* Real    */ ae_vector* scl,
    3546             :      ae_bool applyscl,
    3547             :      /* Real    */ ae_vector* sft,
    3548             :      ae_bool applysft,
    3549             :      ae_state *_state)
    3550             : {
    3551             :     ae_int_t i;
    3552             :     ae_int_t prectouse;
    3553             :     double v;
    3554             : 
    3555             : 
    3556             :     
    3557             :     /*
    3558             :      * Determine precision to use
    3559             :      */
    3560           0 :     prectouse = 0;
    3561           0 :     if( ae_is_trace_enabled("PREC.E15") )
    3562             :     {
    3563           0 :         prectouse = 1;
    3564             :     }
    3565           0 :     if( ae_is_trace_enabled("PREC.F6") )
    3566             :     {
    3567           0 :         prectouse = 2;
    3568             :     }
    3569             :     
    3570             :     /*
    3571             :      * Output
    3572             :      */
    3573           0 :     ae_trace("[ ");
    3574           0 :     for(i=0; i<=n-1; i++)
    3575             :     {
    3576           0 :         v = x->ptr.p_double[i];
    3577           0 :         if( applyscl )
    3578             :         {
    3579           0 :             v = v*scl->ptr.p_double[i];
    3580             :         }
    3581           0 :         if( applysft )
    3582             :         {
    3583           0 :             v = v+sft->ptr.p_double[i];
    3584             :         }
    3585           0 :         if( prectouse==0 )
    3586             :         {
    3587           0 :             ae_trace("%14.6e",
    3588             :                 (double)(v));
    3589             :         }
    3590           0 :         if( prectouse==1 )
    3591             :         {
    3592           0 :             ae_trace("%23.15e",
    3593             :                 (double)(v));
    3594             :         }
    3595           0 :         if( prectouse==2 )
    3596             :         {
    3597           0 :             ae_trace("%13.6f",
    3598             :                 (double)(v));
    3599             :         }
    3600           0 :         if( i<n-1 )
    3601             :         {
    3602           0 :             ae_trace(" ");
    3603             :         }
    3604             :     }
    3605           0 :     ae_trace(" ]");
    3606           0 : }
    3607             : 
    3608             : 
    3609             : /*************************************************************************
    3610             : Outputs vector of 1-norms of rows [I0,I1-1] of A[I0...I1-1,J0...J1-1]   to
    3611             : trace log using either:
    3612             : a)  6-digit exponential format (no trace flags is set)
    3613             : b) 15-ditit exponential format ('PREC.E15' trace flag is set)
    3614             : b)  6-ditit fixed-point format ('PREC.F6' trace flag is set)
    3615             : 
    3616             : This function checks trace flags every time it is called.
    3617             : *************************************************************************/
    3618           0 : void tracerownrm1autoprec(/* Real    */ ae_matrix* a,
    3619             :      ae_int_t i0,
    3620             :      ae_int_t i1,
    3621             :      ae_int_t j0,
    3622             :      ae_int_t j1,
    3623             :      ae_state *_state)
    3624             : {
    3625             :     ae_int_t i;
    3626             :     ae_int_t j;
    3627             :     double v;
    3628             :     ae_int_t prectouse;
    3629             : 
    3630             : 
    3631             :     
    3632             :     /*
    3633             :      * Determine precision to use
    3634             :      */
    3635           0 :     prectouse = 0;
    3636           0 :     if( ae_is_trace_enabled("PREC.E15") )
    3637             :     {
    3638           0 :         prectouse = 1;
    3639             :     }
    3640           0 :     if( ae_is_trace_enabled("PREC.F6") )
    3641             :     {
    3642           0 :         prectouse = 2;
    3643             :     }
    3644             :     
    3645             :     /*
    3646             :      * Output
    3647             :      */
    3648           0 :     ae_trace("[ ");
    3649           0 :     for(i=i0; i<=i1-1; i++)
    3650             :     {
    3651           0 :         v = (double)(0);
    3652           0 :         for(j=j0; j<=j1-1; j++)
    3653             :         {
    3654           0 :             v = ae_maxreal(v, ae_fabs(a->ptr.pp_double[i][j], _state), _state);
    3655             :         }
    3656           0 :         if( prectouse==0 )
    3657             :         {
    3658           0 :             ae_trace("%14.6e",
    3659             :                 (double)(v));
    3660             :         }
    3661           0 :         if( prectouse==1 )
    3662             :         {
    3663           0 :             ae_trace("%23.15e",
    3664             :                 (double)(v));
    3665             :         }
    3666           0 :         if( prectouse==2 )
    3667             :         {
    3668           0 :             ae_trace("%13.6f",
    3669             :                 (double)(v));
    3670             :         }
    3671           0 :         if( i<i1-1 )
    3672             :         {
    3673           0 :             ae_trace(" ");
    3674             :         }
    3675             :     }
    3676           0 :     ae_trace(" ]");
    3677           0 : }
    3678             : 
    3679             : 
    3680             : /*************************************************************************
    3681             : Outputs vector A[I0,I1-1] to trace log using E8 precision
    3682             : *************************************************************************/
    3683           0 : void tracevectore6(/* Real    */ ae_vector* a,
    3684             :      ae_int_t i0,
    3685             :      ae_int_t i1,
    3686             :      ae_state *_state)
    3687             : {
    3688             :     ae_int_t i;
    3689             : 
    3690             : 
    3691           0 :     ae_trace("[ ");
    3692           0 :     for(i=i0; i<=i1-1; i++)
    3693             :     {
    3694           0 :         ae_trace("%14.6e",
    3695           0 :             (double)(a->ptr.p_double[i]));
    3696           0 :         if( i<i1-1 )
    3697             :         {
    3698           0 :             ae_trace(" ");
    3699             :         }
    3700             :     }
    3701           0 :     ae_trace(" ]");
    3702           0 : }
    3703             : 
    3704             : 
    3705             : /*************************************************************************
    3706             : Outputs vector A[I0,I1-1] to trace log using E8 or E15 precision
    3707             : *************************************************************************/
    3708           0 : void tracevectore615(/* Real    */ ae_vector* a,
    3709             :      ae_int_t i0,
    3710             :      ae_int_t i1,
    3711             :      ae_bool usee15,
    3712             :      ae_state *_state)
    3713             : {
    3714             :     ae_int_t i;
    3715             : 
    3716             : 
    3717           0 :     ae_trace("[ ");
    3718           0 :     for(i=i0; i<=i1-1; i++)
    3719             :     {
    3720           0 :         if( usee15 )
    3721             :         {
    3722           0 :             ae_trace("%23.15e",
    3723           0 :                 (double)(a->ptr.p_double[i]));
    3724             :         }
    3725             :         else
    3726             :         {
    3727           0 :             ae_trace("%14.6e",
    3728           0 :                 (double)(a->ptr.p_double[i]));
    3729             :         }
    3730           0 :         if( i<i1-1 )
    3731             :         {
    3732           0 :             ae_trace(" ");
    3733             :         }
    3734             :     }
    3735           0 :     ae_trace(" ]");
    3736           0 : }
    3737             : 
    3738             : 
    3739             : /*************************************************************************
    3740             : Outputs vector of 1-norms of rows [I0,I1-1] of A[I0...I1-1,J0...J1-1]   to
    3741             : trace log using E8 precision
    3742             : *************************************************************************/
    3743           0 : void tracerownrm1e6(/* Real    */ ae_matrix* a,
    3744             :      ae_int_t i0,
    3745             :      ae_int_t i1,
    3746             :      ae_int_t j0,
    3747             :      ae_int_t j1,
    3748             :      ae_state *_state)
    3749             : {
    3750             :     ae_int_t i;
    3751             :     ae_int_t j;
    3752             :     double v;
    3753             : 
    3754             : 
    3755           0 :     ae_trace("[ ");
    3756           0 :     for(i=i0; i<=i1-1; i++)
    3757             :     {
    3758           0 :         v = (double)(0);
    3759           0 :         for(j=j0; j<=j1-1; j++)
    3760             :         {
    3761           0 :             v = ae_maxreal(v, ae_fabs(a->ptr.pp_double[i][j], _state), _state);
    3762             :         }
    3763           0 :         ae_trace("%14.6e",
    3764             :             (double)(v));
    3765           0 :         if( i<i1-1 )
    3766             :         {
    3767           0 :             ae_trace(" ");
    3768             :         }
    3769             :     }
    3770           0 :     ae_trace(" ]");
    3771           0 : }
    3772             : 
    3773             : 
    3774           0 : void _apbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic)
    3775             : {
    3776           0 :     apbuffers *p = (apbuffers*)_p;
    3777           0 :     ae_touch_ptr((void*)p);
    3778           0 :     ae_vector_init(&p->ba0, 0, DT_BOOL, _state, make_automatic);
    3779           0 :     ae_vector_init(&p->ia0, 0, DT_INT, _state, make_automatic);
    3780           0 :     ae_vector_init(&p->ia1, 0, DT_INT, _state, make_automatic);
    3781           0 :     ae_vector_init(&p->ia2, 0, DT_INT, _state, make_automatic);
    3782           0 :     ae_vector_init(&p->ia3, 0, DT_INT, _state, make_automatic);
    3783           0 :     ae_vector_init(&p->ra0, 0, DT_REAL, _state, make_automatic);
    3784           0 :     ae_vector_init(&p->ra1, 0, DT_REAL, _state, make_automatic);
    3785           0 :     ae_vector_init(&p->ra2, 0, DT_REAL, _state, make_automatic);
    3786           0 :     ae_vector_init(&p->ra3, 0, DT_REAL, _state, make_automatic);
    3787           0 :     ae_matrix_init(&p->rm0, 0, 0, DT_REAL, _state, make_automatic);
    3788           0 :     ae_matrix_init(&p->rm1, 0, 0, DT_REAL, _state, make_automatic);
    3789           0 : }
    3790             : 
    3791             : 
    3792           0 : void _apbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
    3793             : {
    3794           0 :     apbuffers *dst = (apbuffers*)_dst;
    3795           0 :     apbuffers *src = (apbuffers*)_src;
    3796           0 :     ae_vector_init_copy(&dst->ba0, &src->ba0, _state, make_automatic);
    3797           0 :     ae_vector_init_copy(&dst->ia0, &src->ia0, _state, make_automatic);
    3798           0 :     ae_vector_init_copy(&dst->ia1, &src->ia1, _state, make_automatic);
    3799           0 :     ae_vector_init_copy(&dst->ia2, &src->ia2, _state, make_automatic);
    3800           0 :     ae_vector_init_copy(&dst->ia3, &src->ia3, _state, make_automatic);
    3801           0 :     ae_vector_init_copy(&dst->ra0, &src->ra0, _state, make_automatic);
    3802           0 :     ae_vector_init_copy(&dst->ra1, &src->ra1, _state, make_automatic);
    3803           0 :     ae_vector_init_copy(&dst->ra2, &src->ra2, _state, make_automatic);
    3804           0 :     ae_vector_init_copy(&dst->ra3, &src->ra3, _state, make_automatic);
    3805           0 :     ae_matrix_init_copy(&dst->rm0, &src->rm0, _state, make_automatic);
    3806           0 :     ae_matrix_init_copy(&dst->rm1, &src->rm1, _state, make_automatic);
    3807           0 : }
    3808             : 
    3809             : 
    3810           0 : void _apbuffers_clear(void* _p)
    3811             : {
    3812           0 :     apbuffers *p = (apbuffers*)_p;
    3813           0 :     ae_touch_ptr((void*)p);
    3814           0 :     ae_vector_clear(&p->ba0);
    3815           0 :     ae_vector_clear(&p->ia0);
    3816           0 :     ae_vector_clear(&p->ia1);
    3817           0 :     ae_vector_clear(&p->ia2);
    3818           0 :     ae_vector_clear(&p->ia3);
    3819           0 :     ae_vector_clear(&p->ra0);
    3820           0 :     ae_vector_clear(&p->ra1);
    3821           0 :     ae_vector_clear(&p->ra2);
    3822           0 :     ae_vector_clear(&p->ra3);
    3823           0 :     ae_matrix_clear(&p->rm0);
    3824           0 :     ae_matrix_clear(&p->rm1);
    3825           0 : }
    3826             : 
    3827             : 
    3828           0 : void _apbuffers_destroy(void* _p)
    3829             : {
    3830           0 :     apbuffers *p = (apbuffers*)_p;
    3831           0 :     ae_touch_ptr((void*)p);
    3832           0 :     ae_vector_destroy(&p->ba0);
    3833           0 :     ae_vector_destroy(&p->ia0);
    3834           0 :     ae_vector_destroy(&p->ia1);
    3835           0 :     ae_vector_destroy(&p->ia2);
    3836           0 :     ae_vector_destroy(&p->ia3);
    3837           0 :     ae_vector_destroy(&p->ra0);
    3838           0 :     ae_vector_destroy(&p->ra1);
    3839           0 :     ae_vector_destroy(&p->ra2);
    3840           0 :     ae_vector_destroy(&p->ra3);
    3841           0 :     ae_matrix_destroy(&p->rm0);
    3842           0 :     ae_matrix_destroy(&p->rm1);
    3843           0 : }
    3844             : 
    3845             : 
    3846           0 : void _sboolean_init(void* _p, ae_state *_state, ae_bool make_automatic)
    3847             : {
    3848           0 :     sboolean *p = (sboolean*)_p;
    3849           0 :     ae_touch_ptr((void*)p);
    3850           0 : }
    3851             : 
    3852             : 
    3853           0 : void _sboolean_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
    3854             : {
    3855           0 :     sboolean *dst = (sboolean*)_dst;
    3856           0 :     sboolean *src = (sboolean*)_src;
    3857           0 :     dst->val = src->val;
    3858           0 : }
    3859             : 
    3860             : 
    3861           0 : void _sboolean_clear(void* _p)
    3862             : {
    3863           0 :     sboolean *p = (sboolean*)_p;
    3864           0 :     ae_touch_ptr((void*)p);
    3865           0 : }
    3866             : 
    3867             : 
    3868           0 : void _sboolean_destroy(void* _p)
    3869             : {
    3870           0 :     sboolean *p = (sboolean*)_p;
    3871           0 :     ae_touch_ptr((void*)p);
    3872           0 : }
    3873             : 
    3874             : 
    3875           0 : void _sbooleanarray_init(void* _p, ae_state *_state, ae_bool make_automatic)
    3876             : {
    3877           0 :     sbooleanarray *p = (sbooleanarray*)_p;
    3878           0 :     ae_touch_ptr((void*)p);
    3879           0 :     ae_vector_init(&p->val, 0, DT_BOOL, _state, make_automatic);
    3880           0 : }
    3881             : 
    3882             : 
    3883           0 : void _sbooleanarray_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
    3884             : {
    3885           0 :     sbooleanarray *dst = (sbooleanarray*)_dst;
    3886           0 :     sbooleanarray *src = (sbooleanarray*)_src;
    3887           0 :     ae_vector_init_copy(&dst->val, &src->val, _state, make_automatic);
    3888           0 : }
    3889             : 
    3890             : 
    3891           0 : void _sbooleanarray_clear(void* _p)
    3892             : {
    3893           0 :     sbooleanarray *p = (sbooleanarray*)_p;
    3894           0 :     ae_touch_ptr((void*)p);
    3895           0 :     ae_vector_clear(&p->val);
    3896           0 : }
    3897             : 
    3898             : 
    3899           0 : void _sbooleanarray_destroy(void* _p)
    3900             : {
    3901           0 :     sbooleanarray *p = (sbooleanarray*)_p;
    3902           0 :     ae_touch_ptr((void*)p);
    3903           0 :     ae_vector_destroy(&p->val);
    3904           0 : }
    3905             : 
    3906             : 
    3907           0 : void _sinteger_init(void* _p, ae_state *_state, ae_bool make_automatic)
    3908             : {
    3909           0 :     sinteger *p = (sinteger*)_p;
    3910           0 :     ae_touch_ptr((void*)p);
    3911           0 : }
    3912             : 
    3913             : 
    3914           0 : void _sinteger_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
    3915             : {
    3916           0 :     sinteger *dst = (sinteger*)_dst;
    3917           0 :     sinteger *src = (sinteger*)_src;
    3918           0 :     dst->val = src->val;
    3919           0 : }
    3920             : 
    3921             : 
    3922           0 : void _sinteger_clear(void* _p)
    3923             : {
    3924           0 :     sinteger *p = (sinteger*)_p;
    3925           0 :     ae_touch_ptr((void*)p);
    3926           0 : }
    3927             : 
    3928             : 
    3929           0 : void _sinteger_destroy(void* _p)
    3930             : {
    3931           0 :     sinteger *p = (sinteger*)_p;
    3932           0 :     ae_touch_ptr((void*)p);
    3933           0 : }
    3934             : 
    3935             : 
    3936           0 : void _sintegerarray_init(void* _p, ae_state *_state, ae_bool make_automatic)
    3937             : {
    3938           0 :     sintegerarray *p = (sintegerarray*)_p;
    3939           0 :     ae_touch_ptr((void*)p);
    3940           0 :     ae_vector_init(&p->val, 0, DT_INT, _state, make_automatic);
    3941           0 : }
    3942             : 
    3943             : 
    3944           0 : void _sintegerarray_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
    3945             : {
    3946           0 :     sintegerarray *dst = (sintegerarray*)_dst;
    3947           0 :     sintegerarray *src = (sintegerarray*)_src;
    3948           0 :     ae_vector_init_copy(&dst->val, &src->val, _state, make_automatic);
    3949           0 : }
    3950             : 
    3951             : 
    3952           0 : void _sintegerarray_clear(void* _p)
    3953             : {
    3954           0 :     sintegerarray *p = (sintegerarray*)_p;
    3955           0 :     ae_touch_ptr((void*)p);
    3956           0 :     ae_vector_clear(&p->val);
    3957           0 : }
    3958             : 
    3959             : 
    3960           0 : void _sintegerarray_destroy(void* _p)
    3961             : {
    3962           0 :     sintegerarray *p = (sintegerarray*)_p;
    3963           0 :     ae_touch_ptr((void*)p);
    3964           0 :     ae_vector_destroy(&p->val);
    3965           0 : }
    3966             : 
    3967             : 
    3968           0 : void _sreal_init(void* _p, ae_state *_state, ae_bool make_automatic)
    3969             : {
    3970           0 :     sreal *p = (sreal*)_p;
    3971           0 :     ae_touch_ptr((void*)p);
    3972           0 : }
    3973             : 
    3974             : 
    3975           0 : void _sreal_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
    3976             : {
    3977           0 :     sreal *dst = (sreal*)_dst;
    3978           0 :     sreal *src = (sreal*)_src;
    3979           0 :     dst->val = src->val;
    3980           0 : }
    3981             : 
    3982             : 
    3983           0 : void _sreal_clear(void* _p)
    3984             : {
    3985           0 :     sreal *p = (sreal*)_p;
    3986           0 :     ae_touch_ptr((void*)p);
    3987           0 : }
    3988             : 
    3989             : 
    3990           0 : void _sreal_destroy(void* _p)
    3991             : {
    3992           0 :     sreal *p = (sreal*)_p;
    3993           0 :     ae_touch_ptr((void*)p);
    3994           0 : }
    3995             : 
    3996             : 
    3997           0 : void _srealarray_init(void* _p, ae_state *_state, ae_bool make_automatic)
    3998             : {
    3999           0 :     srealarray *p = (srealarray*)_p;
    4000           0 :     ae_touch_ptr((void*)p);
    4001           0 :     ae_vector_init(&p->val, 0, DT_REAL, _state, make_automatic);
    4002           0 : }
    4003             : 
    4004             : 
    4005           0 : void _srealarray_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
    4006             : {
    4007           0 :     srealarray *dst = (srealarray*)_dst;
    4008           0 :     srealarray *src = (srealarray*)_src;
    4009           0 :     ae_vector_init_copy(&dst->val, &src->val, _state, make_automatic);
    4010           0 : }
    4011             : 
    4012             : 
    4013           0 : void _srealarray_clear(void* _p)
    4014             : {
    4015           0 :     srealarray *p = (srealarray*)_p;
    4016           0 :     ae_touch_ptr((void*)p);
    4017           0 :     ae_vector_clear(&p->val);
    4018           0 : }
    4019             : 
    4020             : 
    4021           0 : void _srealarray_destroy(void* _p)
    4022             : {
    4023           0 :     srealarray *p = (srealarray*)_p;
    4024           0 :     ae_touch_ptr((void*)p);
    4025           0 :     ae_vector_destroy(&p->val);
    4026           0 : }
    4027             : 
    4028             : 
    4029           0 : void _scomplex_init(void* _p, ae_state *_state, ae_bool make_automatic)
    4030             : {
    4031           0 :     scomplex *p = (scomplex*)_p;
    4032           0 :     ae_touch_ptr((void*)p);
    4033           0 : }
    4034             : 
    4035             : 
    4036           0 : void _scomplex_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
    4037             : {
    4038           0 :     scomplex *dst = (scomplex*)_dst;
    4039           0 :     scomplex *src = (scomplex*)_src;
    4040           0 :     dst->val = src->val;
    4041           0 : }
    4042             : 
    4043             : 
    4044           0 : void _scomplex_clear(void* _p)
    4045             : {
    4046           0 :     scomplex *p = (scomplex*)_p;
    4047           0 :     ae_touch_ptr((void*)p);
    4048           0 : }
    4049             : 
    4050             : 
    4051           0 : void _scomplex_destroy(void* _p)
    4052             : {
    4053           0 :     scomplex *p = (scomplex*)_p;
    4054           0 :     ae_touch_ptr((void*)p);
    4055           0 : }
    4056             : 
    4057             : 
    4058           0 : void _scomplexarray_init(void* _p, ae_state *_state, ae_bool make_automatic)
    4059             : {
    4060           0 :     scomplexarray *p = (scomplexarray*)_p;
    4061           0 :     ae_touch_ptr((void*)p);
    4062           0 :     ae_vector_init(&p->val, 0, DT_COMPLEX, _state, make_automatic);
    4063           0 : }
    4064             : 
    4065             : 
    4066           0 : void _scomplexarray_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
    4067             : {
    4068           0 :     scomplexarray *dst = (scomplexarray*)_dst;
    4069           0 :     scomplexarray *src = (scomplexarray*)_src;
    4070           0 :     ae_vector_init_copy(&dst->val, &src->val, _state, make_automatic);
    4071           0 : }
    4072             : 
    4073             : 
    4074           0 : void _scomplexarray_clear(void* _p)
    4075             : {
    4076           0 :     scomplexarray *p = (scomplexarray*)_p;
    4077           0 :     ae_touch_ptr((void*)p);
    4078           0 :     ae_vector_clear(&p->val);
    4079           0 : }
    4080             : 
    4081             : 
    4082           0 : void _scomplexarray_destroy(void* _p)
    4083             : {
    4084           0 :     scomplexarray *p = (scomplexarray*)_p;
    4085           0 :     ae_touch_ptr((void*)p);
    4086           0 :     ae_vector_destroy(&p->val);
    4087           0 : }
    4088             : 
    4089             : 
    4090             : #endif
    4091             : #if defined(AE_COMPILE_TSORT) || !defined(AE_PARTIAL_BUILD)
    4092             : 
    4093             : 
    4094             : /*************************************************************************
    4095             : This function sorts array of real keys by ascending.
    4096             : 
    4097             : Its results are:
    4098             : * sorted array A
    4099             : * permutation tables P1, P2
    4100             : 
    4101             : Algorithm outputs permutation tables using two formats:
    4102             : * as usual permutation of [0..N-1]. If P1[i]=j, then sorted A[i]  contains
    4103             :   value which was moved there from J-th position.
    4104             : * as a sequence of pairwise permutations. Sorted A[] may  be  obtained  by
    4105             :   swaping A[i] and A[P2[i]] for all i from 0 to N-1.
    4106             :   
    4107             : INPUT PARAMETERS:
    4108             :     A       -   unsorted array
    4109             :     N       -   array size
    4110             : 
    4111             : OUPUT PARAMETERS:
    4112             :     A       -   sorted array
    4113             :     P1, P2  -   permutation tables, array[N]
    4114             :     
    4115             : NOTES:
    4116             :     this function assumes that A[] is finite; it doesn't checks that
    4117             :     condition. All other conditions (size of input arrays, etc.) are not
    4118             :     checked too.
    4119             : 
    4120             :   -- ALGLIB --
    4121             :      Copyright 14.05.2008 by Bochkanov Sergey
    4122             : *************************************************************************/
    4123           0 : void tagsort(/* Real    */ ae_vector* a,
    4124             :      ae_int_t n,
    4125             :      /* Integer */ ae_vector* p1,
    4126             :      /* Integer */ ae_vector* p2,
    4127             :      ae_state *_state)
    4128             : {
    4129             :     ae_frame _frame_block;
    4130             :     apbuffers buf;
    4131             : 
    4132           0 :     ae_frame_make(_state, &_frame_block);
    4133           0 :     memset(&buf, 0, sizeof(buf));
    4134           0 :     ae_vector_clear(p1);
    4135           0 :     ae_vector_clear(p2);
    4136           0 :     _apbuffers_init(&buf, _state, ae_true);
    4137             : 
    4138           0 :     tagsortbuf(a, n, p1, p2, &buf, _state);
    4139           0 :     ae_frame_leave(_state);
    4140           0 : }
    4141             : 
    4142             : 
    4143             : /*************************************************************************
    4144             : Buffered variant of TagSort, which accepts preallocated output arrays as
    4145             : well as special structure for buffered allocations. If arrays are too
    4146             : short, they are reallocated. If they are large enough, no memory
    4147             : allocation is done.
    4148             : 
    4149             : It is intended to be used in the performance-critical parts of code, where
    4150             : additional allocations can lead to severe performance degradation
    4151             : 
    4152             :   -- ALGLIB --
    4153             :      Copyright 14.05.2008 by Bochkanov Sergey
    4154             : *************************************************************************/
    4155           0 : void tagsortbuf(/* Real    */ ae_vector* a,
    4156             :      ae_int_t n,
    4157             :      /* Integer */ ae_vector* p1,
    4158             :      /* Integer */ ae_vector* p2,
    4159             :      apbuffers* buf,
    4160             :      ae_state *_state)
    4161             : {
    4162             :     ae_int_t i;
    4163             :     ae_int_t lv;
    4164             :     ae_int_t lp;
    4165             :     ae_int_t rv;
    4166             :     ae_int_t rp;
    4167             : 
    4168             : 
    4169             :     
    4170             :     /*
    4171             :      * Special cases
    4172             :      */
    4173           0 :     if( n<=0 )
    4174             :     {
    4175           0 :         return;
    4176             :     }
    4177           0 :     if( n==1 )
    4178             :     {
    4179           0 :         ivectorsetlengthatleast(p1, 1, _state);
    4180           0 :         ivectorsetlengthatleast(p2, 1, _state);
    4181           0 :         p1->ptr.p_int[0] = 0;
    4182           0 :         p2->ptr.p_int[0] = 0;
    4183           0 :         return;
    4184             :     }
    4185             :     
    4186             :     /*
    4187             :      * General case, N>1: prepare permutations table P1
    4188             :      */
    4189           0 :     ivectorsetlengthatleast(p1, n, _state);
    4190           0 :     for(i=0; i<=n-1; i++)
    4191             :     {
    4192           0 :         p1->ptr.p_int[i] = i;
    4193             :     }
    4194             :     
    4195             :     /*
    4196             :      * General case, N>1: sort, update P1
    4197             :      */
    4198           0 :     rvectorsetlengthatleast(&buf->ra0, n, _state);
    4199           0 :     ivectorsetlengthatleast(&buf->ia0, n, _state);
    4200           0 :     tagsortfasti(a, p1, &buf->ra0, &buf->ia0, n, _state);
    4201             :     
    4202             :     /*
    4203             :      * General case, N>1: fill permutations table P2
    4204             :      *
    4205             :      * To fill P2 we maintain two arrays:
    4206             :      * * PV (Buf.IA0), Position(Value). PV[i] contains position of I-th key at the moment
    4207             :      * * VP (Buf.IA1), Value(Position). VP[i] contains key which has position I at the moment
    4208             :      *
    4209             :      * At each step we making permutation of two items:
    4210             :      *   Left, which is given by position/value pair LP/LV
    4211             :      *   and Right, which is given by RP/RV
    4212             :      * and updating PV[] and VP[] correspondingly.
    4213             :      */
    4214           0 :     ivectorsetlengthatleast(&buf->ia0, n, _state);
    4215           0 :     ivectorsetlengthatleast(&buf->ia1, n, _state);
    4216           0 :     ivectorsetlengthatleast(p2, n, _state);
    4217           0 :     for(i=0; i<=n-1; i++)
    4218             :     {
    4219           0 :         buf->ia0.ptr.p_int[i] = i;
    4220           0 :         buf->ia1.ptr.p_int[i] = i;
    4221             :     }
    4222           0 :     for(i=0; i<=n-1; i++)
    4223             :     {
    4224             :         
    4225             :         /*
    4226             :          * calculate LP, LV, RP, RV
    4227             :          */
    4228           0 :         lp = i;
    4229           0 :         lv = buf->ia1.ptr.p_int[lp];
    4230           0 :         rv = p1->ptr.p_int[i];
    4231           0 :         rp = buf->ia0.ptr.p_int[rv];
    4232             :         
    4233             :         /*
    4234             :          * Fill P2
    4235             :          */
    4236           0 :         p2->ptr.p_int[i] = rp;
    4237             :         
    4238             :         /*
    4239             :          * update PV and VP
    4240             :          */
    4241           0 :         buf->ia1.ptr.p_int[lp] = rv;
    4242           0 :         buf->ia1.ptr.p_int[rp] = lv;
    4243           0 :         buf->ia0.ptr.p_int[lv] = rp;
    4244           0 :         buf->ia0.ptr.p_int[rv] = lp;
    4245             :     }
    4246             : }
    4247             : 
    4248             : 
    4249             : /*************************************************************************
    4250             : Same as TagSort, but optimized for real keys and integer labels.
    4251             : 
    4252             : A is sorted, and same permutations are applied to B.
    4253             : 
    4254             : NOTES:
    4255             : 1.  this function assumes that A[] is finite; it doesn't checks that
    4256             :     condition. All other conditions (size of input arrays, etc.) are not
    4257             :     checked too.
    4258             : 2.  this function uses two buffers, BufA and BufB, each is N elements large.
    4259             :     They may be preallocated (which will save some time) or not, in which
    4260             :     case function will automatically allocate memory.
    4261             : 
    4262             :   -- ALGLIB --
    4263             :      Copyright 11.12.2008 by Bochkanov Sergey
    4264             : *************************************************************************/
    4265           0 : void tagsortfasti(/* Real    */ ae_vector* a,
    4266             :      /* Integer */ ae_vector* b,
    4267             :      /* Real    */ ae_vector* bufa,
    4268             :      /* Integer */ ae_vector* bufb,
    4269             :      ae_int_t n,
    4270             :      ae_state *_state)
    4271             : {
    4272             :     ae_int_t i;
    4273             :     ae_int_t j;
    4274             :     ae_bool isascending;
    4275             :     ae_bool isdescending;
    4276             :     double tmpr;
    4277             :     ae_int_t tmpi;
    4278             : 
    4279             : 
    4280             :     
    4281             :     /*
    4282             :      * Special case
    4283             :      */
    4284           0 :     if( n<=1 )
    4285             :     {
    4286           0 :         return;
    4287             :     }
    4288             :     
    4289             :     /*
    4290             :      * Test for already sorted set
    4291             :      */
    4292           0 :     isascending = ae_true;
    4293           0 :     isdescending = ae_true;
    4294           0 :     for(i=1; i<=n-1; i++)
    4295             :     {
    4296           0 :         isascending = isascending&&a->ptr.p_double[i]>=a->ptr.p_double[i-1];
    4297           0 :         isdescending = isdescending&&a->ptr.p_double[i]<=a->ptr.p_double[i-1];
    4298             :     }
    4299           0 :     if( isascending )
    4300             :     {
    4301           0 :         return;
    4302             :     }
    4303           0 :     if( isdescending )
    4304             :     {
    4305           0 :         for(i=0; i<=n-1; i++)
    4306             :         {
    4307           0 :             j = n-1-i;
    4308           0 :             if( j<=i )
    4309             :             {
    4310           0 :                 break;
    4311             :             }
    4312           0 :             tmpr = a->ptr.p_double[i];
    4313           0 :             a->ptr.p_double[i] = a->ptr.p_double[j];
    4314           0 :             a->ptr.p_double[j] = tmpr;
    4315           0 :             tmpi = b->ptr.p_int[i];
    4316           0 :             b->ptr.p_int[i] = b->ptr.p_int[j];
    4317           0 :             b->ptr.p_int[j] = tmpi;
    4318             :         }
    4319           0 :         return;
    4320             :     }
    4321             :     
    4322             :     /*
    4323             :      * General case
    4324             :      */
    4325           0 :     if( bufa->cnt<n )
    4326             :     {
    4327           0 :         ae_vector_set_length(bufa, n, _state);
    4328             :     }
    4329           0 :     if( bufb->cnt<n )
    4330             :     {
    4331           0 :         ae_vector_set_length(bufb, n, _state);
    4332             :     }
    4333           0 :     tsort_tagsortfastirec(a, b, bufa, bufb, 0, n-1, _state);
    4334             : }
    4335             : 
    4336             : 
    4337             : /*************************************************************************
    4338             : Same as TagSort, but optimized for real keys and real labels.
    4339             : 
    4340             : A is sorted, and same permutations are applied to B.
    4341             : 
    4342             : NOTES:
    4343             : 1.  this function assumes that A[] is finite; it doesn't checks that
    4344             :     condition. All other conditions (size of input arrays, etc.) are not
    4345             :     checked too.
    4346             : 2.  this function uses two buffers, BufA and BufB, each is N elements large.
    4347             :     They may be preallocated (which will save some time) or not, in which
    4348             :     case function will automatically allocate memory.
    4349             : 
    4350             :   -- ALGLIB --
    4351             :      Copyright 11.12.2008 by Bochkanov Sergey
    4352             : *************************************************************************/
    4353           0 : void tagsortfastr(/* Real    */ ae_vector* a,
    4354             :      /* Real    */ ae_vector* b,
    4355             :      /* Real    */ ae_vector* bufa,
    4356             :      /* Real    */ ae_vector* bufb,
    4357             :      ae_int_t n,
    4358             :      ae_state *_state)
    4359             : {
    4360             :     ae_int_t i;
    4361             :     ae_int_t j;
    4362             :     ae_bool isascending;
    4363             :     ae_bool isdescending;
    4364             :     double tmpr;
    4365             : 
    4366             : 
    4367             :     
    4368             :     /*
    4369             :      * Special case
    4370             :      */
    4371           0 :     if( n<=1 )
    4372             :     {
    4373           0 :         return;
    4374             :     }
    4375             :     
    4376             :     /*
    4377             :      * Test for already sorted set
    4378             :      */
    4379           0 :     isascending = ae_true;
    4380           0 :     isdescending = ae_true;
    4381           0 :     for(i=1; i<=n-1; i++)
    4382             :     {
    4383           0 :         isascending = isascending&&a->ptr.p_double[i]>=a->ptr.p_double[i-1];
    4384           0 :         isdescending = isdescending&&a->ptr.p_double[i]<=a->ptr.p_double[i-1];
    4385             :     }
    4386           0 :     if( isascending )
    4387             :     {
    4388           0 :         return;
    4389             :     }
    4390           0 :     if( isdescending )
    4391             :     {
    4392           0 :         for(i=0; i<=n-1; i++)
    4393             :         {
    4394           0 :             j = n-1-i;
    4395           0 :             if( j<=i )
    4396             :             {
    4397           0 :                 break;
    4398             :             }
    4399           0 :             tmpr = a->ptr.p_double[i];
    4400           0 :             a->ptr.p_double[i] = a->ptr.p_double[j];
    4401           0 :             a->ptr.p_double[j] = tmpr;
    4402           0 :             tmpr = b->ptr.p_double[i];
    4403           0 :             b->ptr.p_double[i] = b->ptr.p_double[j];
    4404           0 :             b->ptr.p_double[j] = tmpr;
    4405             :         }
    4406           0 :         return;
    4407             :     }
    4408             :     
    4409             :     /*
    4410             :      * General case
    4411             :      */
    4412           0 :     if( bufa->cnt<n )
    4413             :     {
    4414           0 :         ae_vector_set_length(bufa, n, _state);
    4415             :     }
    4416           0 :     if( bufb->cnt<n )
    4417             :     {
    4418           0 :         ae_vector_set_length(bufb, n, _state);
    4419             :     }
    4420           0 :     tsort_tagsortfastrrec(a, b, bufa, bufb, 0, n-1, _state);
    4421             : }
    4422             : 
    4423             : 
    4424             : /*************************************************************************
    4425             : Same as TagSort, but optimized for real keys without labels.
    4426             : 
    4427             : A is sorted, and that's all.
    4428             : 
    4429             : NOTES:
    4430             : 1.  this function assumes that A[] is finite; it doesn't checks that
    4431             :     condition. All other conditions (size of input arrays, etc.) are not
    4432             :     checked too.
    4433             : 2.  this function uses buffer, BufA, which is N elements large. It may be
    4434             :     preallocated (which will save some time) or not, in which case
    4435             :     function will automatically allocate memory.
    4436             : 
    4437             :   -- ALGLIB --
    4438             :      Copyright 11.12.2008 by Bochkanov Sergey
    4439             : *************************************************************************/
    4440           0 : void tagsortfast(/* Real    */ ae_vector* a,
    4441             :      /* Real    */ ae_vector* bufa,
    4442             :      ae_int_t n,
    4443             :      ae_state *_state)
    4444             : {
    4445             :     ae_int_t i;
    4446             :     ae_int_t j;
    4447             :     ae_bool isascending;
    4448             :     ae_bool isdescending;
    4449             :     double tmpr;
    4450             : 
    4451             : 
    4452             :     
    4453             :     /*
    4454             :      * Special case
    4455             :      */
    4456           0 :     if( n<=1 )
    4457             :     {
    4458           0 :         return;
    4459             :     }
    4460             :     
    4461             :     /*
    4462             :      * Test for already sorted set
    4463             :      */
    4464           0 :     isascending = ae_true;
    4465           0 :     isdescending = ae_true;
    4466           0 :     for(i=1; i<=n-1; i++)
    4467             :     {
    4468           0 :         isascending = isascending&&a->ptr.p_double[i]>=a->ptr.p_double[i-1];
    4469           0 :         isdescending = isdescending&&a->ptr.p_double[i]<=a->ptr.p_double[i-1];
    4470             :     }
    4471           0 :     if( isascending )
    4472             :     {
    4473           0 :         return;
    4474             :     }
    4475           0 :     if( isdescending )
    4476             :     {
    4477           0 :         for(i=0; i<=n-1; i++)
    4478             :         {
    4479           0 :             j = n-1-i;
    4480           0 :             if( j<=i )
    4481             :             {
    4482           0 :                 break;
    4483             :             }
    4484           0 :             tmpr = a->ptr.p_double[i];
    4485           0 :             a->ptr.p_double[i] = a->ptr.p_double[j];
    4486           0 :             a->ptr.p_double[j] = tmpr;
    4487             :         }
    4488           0 :         return;
    4489             :     }
    4490             :     
    4491             :     /*
    4492             :      * General case
    4493             :      */
    4494           0 :     if( bufa->cnt<n )
    4495             :     {
    4496           0 :         ae_vector_set_length(bufa, n, _state);
    4497             :     }
    4498           0 :     tsort_tagsortfastrec(a, bufa, 0, n-1, _state);
    4499             : }
    4500             : 
    4501             : 
    4502             : /*************************************************************************
    4503             : Sorting function optimized for integer keys and real labels, can be used
    4504             : to sort middle of the array
    4505             : 
    4506             : A is sorted, and same permutations are applied to B.
    4507             : 
    4508             : NOTES:
    4509             :     this function assumes that A[] is finite; it doesn't checks that
    4510             :     condition. All other conditions (size of input arrays, etc.) are not
    4511             :     checked too.
    4512             : 
    4513             :   -- ALGLIB --
    4514             :      Copyright 11.12.2008 by Bochkanov Sergey
    4515             : *************************************************************************/
    4516           0 : void tagsortmiddleir(/* Integer */ ae_vector* a,
    4517             :      /* Real    */ ae_vector* b,
    4518             :      ae_int_t offset,
    4519             :      ae_int_t n,
    4520             :      ae_state *_state)
    4521             : {
    4522             :     ae_int_t i;
    4523             :     ae_int_t k;
    4524             :     ae_int_t t;
    4525             :     ae_int_t tmp;
    4526             :     double tmpr;
    4527             :     ae_int_t p0;
    4528             :     ae_int_t p1;
    4529             :     ae_int_t at;
    4530             :     ae_int_t ak;
    4531             :     ae_int_t ak1;
    4532             :     double bt;
    4533             : 
    4534             : 
    4535             :     
    4536             :     /*
    4537             :      * Special cases
    4538             :      */
    4539           0 :     if( n<=1 )
    4540             :     {
    4541           0 :         return;
    4542             :     }
    4543             :     
    4544             :     /*
    4545             :      * General case, N>1: sort, update B
    4546             :      */
    4547           0 :     for(i=2; i<=n; i++)
    4548             :     {
    4549           0 :         t = i;
    4550           0 :         while(t!=1)
    4551             :         {
    4552           0 :             k = t/2;
    4553           0 :             p0 = offset+k-1;
    4554           0 :             p1 = offset+t-1;
    4555           0 :             ak = a->ptr.p_int[p0];
    4556           0 :             at = a->ptr.p_int[p1];
    4557           0 :             if( ak>=at )
    4558             :             {
    4559           0 :                 break;
    4560             :             }
    4561           0 :             a->ptr.p_int[p0] = at;
    4562           0 :             a->ptr.p_int[p1] = ak;
    4563           0 :             tmpr = b->ptr.p_double[p0];
    4564           0 :             b->ptr.p_double[p0] = b->ptr.p_double[p1];
    4565           0 :             b->ptr.p_double[p1] = tmpr;
    4566           0 :             t = k;
    4567             :         }
    4568             :     }
    4569           0 :     for(i=n-1; i>=1; i--)
    4570             :     {
    4571           0 :         p0 = offset+0;
    4572           0 :         p1 = offset+i;
    4573           0 :         tmp = a->ptr.p_int[p1];
    4574           0 :         a->ptr.p_int[p1] = a->ptr.p_int[p0];
    4575           0 :         a->ptr.p_int[p0] = tmp;
    4576           0 :         at = tmp;
    4577           0 :         tmpr = b->ptr.p_double[p1];
    4578           0 :         b->ptr.p_double[p1] = b->ptr.p_double[p0];
    4579           0 :         b->ptr.p_double[p0] = tmpr;
    4580           0 :         bt = tmpr;
    4581           0 :         t = 0;
    4582             :         for(;;)
    4583             :         {
    4584           0 :             k = 2*t+1;
    4585           0 :             if( k+1>i )
    4586             :             {
    4587           0 :                 break;
    4588             :             }
    4589           0 :             p0 = offset+t;
    4590           0 :             p1 = offset+k;
    4591           0 :             ak = a->ptr.p_int[p1];
    4592           0 :             if( k+1<i )
    4593             :             {
    4594           0 :                 ak1 = a->ptr.p_int[p1+1];
    4595           0 :                 if( ak1>ak )
    4596             :                 {
    4597           0 :                     ak = ak1;
    4598           0 :                     p1 = p1+1;
    4599           0 :                     k = k+1;
    4600             :                 }
    4601             :             }
    4602           0 :             if( at>=ak )
    4603             :             {
    4604           0 :                 break;
    4605             :             }
    4606           0 :             a->ptr.p_int[p1] = at;
    4607           0 :             a->ptr.p_int[p0] = ak;
    4608           0 :             b->ptr.p_double[p0] = b->ptr.p_double[p1];
    4609           0 :             b->ptr.p_double[p1] = bt;
    4610           0 :             t = k;
    4611             :         }
    4612             :     }
    4613             : }
    4614             : 
    4615             : 
    4616             : /*************************************************************************
    4617             : Sorting function optimized for integer keys and real labels, can be used
    4618             : to sort middle of the array
    4619             : 
    4620             : A is sorted, and same permutations are applied to B.
    4621             : 
    4622             : NOTES:
    4623             :     this function assumes that A[] is finite; it doesn't checks that
    4624             :     condition. All other conditions (size of input arrays, etc.) are not
    4625             :     checked too.
    4626             : 
    4627             :   -- ALGLIB --
    4628             :      Copyright 11.12.2008 by Bochkanov Sergey
    4629             : *************************************************************************/
    4630           0 : void tagsortmiddlei(/* Integer */ ae_vector* a,
    4631             :      ae_int_t offset,
    4632             :      ae_int_t n,
    4633             :      ae_state *_state)
    4634             : {
    4635             :     ae_int_t i;
    4636             :     ae_int_t k;
    4637             :     ae_int_t t;
    4638             :     ae_int_t tmp;
    4639             :     ae_int_t p0;
    4640             :     ae_int_t p1;
    4641             :     ae_int_t at;
    4642             :     ae_int_t ak;
    4643             :     ae_int_t ak1;
    4644             : 
    4645             : 
    4646             :     
    4647             :     /*
    4648             :      * Special cases
    4649             :      */
    4650           0 :     if( n<=1 )
    4651             :     {
    4652           0 :         return;
    4653             :     }
    4654             :     
    4655             :     /*
    4656             :      * General case, N>1: sort, update B
    4657             :      */
    4658           0 :     for(i=2; i<=n; i++)
    4659             :     {
    4660           0 :         t = i;
    4661           0 :         while(t!=1)
    4662             :         {
    4663           0 :             k = t/2;
    4664           0 :             p0 = offset+k-1;
    4665           0 :             p1 = offset+t-1;
    4666           0 :             ak = a->ptr.p_int[p0];
    4667           0 :             at = a->ptr.p_int[p1];
    4668           0 :             if( ak>=at )
    4669             :             {
    4670           0 :                 break;
    4671             :             }
    4672           0 :             a->ptr.p_int[p0] = at;
    4673           0 :             a->ptr.p_int[p1] = ak;
    4674           0 :             t = k;
    4675             :         }
    4676             :     }
    4677           0 :     for(i=n-1; i>=1; i--)
    4678             :     {
    4679           0 :         p0 = offset+0;
    4680           0 :         p1 = offset+i;
    4681           0 :         tmp = a->ptr.p_int[p1];
    4682           0 :         a->ptr.p_int[p1] = a->ptr.p_int[p0];
    4683           0 :         a->ptr.p_int[p0] = tmp;
    4684           0 :         at = tmp;
    4685           0 :         t = 0;
    4686             :         for(;;)
    4687             :         {
    4688           0 :             k = 2*t+1;
    4689           0 :             if( k+1>i )
    4690             :             {
    4691           0 :                 break;
    4692             :             }
    4693           0 :             p0 = offset+t;
    4694           0 :             p1 = offset+k;
    4695           0 :             ak = a->ptr.p_int[p1];
    4696           0 :             if( k+1<i )
    4697             :             {
    4698           0 :                 ak1 = a->ptr.p_int[p1+1];
    4699           0 :                 if( ak1>ak )
    4700             :                 {
    4701           0 :                     ak = ak1;
    4702           0 :                     p1 = p1+1;
    4703           0 :                     k = k+1;
    4704             :                 }
    4705             :             }
    4706           0 :             if( at>=ak )
    4707             :             {
    4708           0 :                 break;
    4709             :             }
    4710           0 :             a->ptr.p_int[p1] = at;
    4711           0 :             a->ptr.p_int[p0] = ak;
    4712           0 :             t = k;
    4713             :         }
    4714             :     }
    4715             : }
    4716             : 
    4717             : 
    4718             : /*************************************************************************
    4719             : Sorting function optimized for integer values (only keys, no labels),  can
    4720             : be used to sort middle of the array
    4721             : 
    4722             :   -- ALGLIB --
    4723             :      Copyright 11.12.2008 by Bochkanov Sergey
    4724             : *************************************************************************/
    4725           0 : void sortmiddlei(/* Integer */ ae_vector* a,
    4726             :      ae_int_t offset,
    4727             :      ae_int_t n,
    4728             :      ae_state *_state)
    4729             : {
    4730             :     ae_int_t i;
    4731             :     ae_int_t k;
    4732             :     ae_int_t t;
    4733             :     ae_int_t tmp;
    4734             :     ae_int_t p0;
    4735             :     ae_int_t p1;
    4736             :     ae_int_t at;
    4737             :     ae_int_t ak;
    4738             :     ae_int_t ak1;
    4739             : 
    4740             : 
    4741             :     
    4742             :     /*
    4743             :      * Special cases
    4744             :      */
    4745           0 :     if( n<=1 )
    4746             :     {
    4747           0 :         return;
    4748             :     }
    4749             :     
    4750             :     /*
    4751             :      * General case, N>1: sort, update B
    4752             :      */
    4753           0 :     for(i=2; i<=n; i++)
    4754             :     {
    4755           0 :         t = i;
    4756           0 :         while(t!=1)
    4757             :         {
    4758           0 :             k = t/2;
    4759           0 :             p0 = offset+k-1;
    4760           0 :             p1 = offset+t-1;
    4761           0 :             ak = a->ptr.p_int[p0];
    4762           0 :             at = a->ptr.p_int[p1];
    4763           0 :             if( ak>=at )
    4764             :             {
    4765           0 :                 break;
    4766             :             }
    4767           0 :             a->ptr.p_int[p0] = at;
    4768           0 :             a->ptr.p_int[p1] = ak;
    4769           0 :             t = k;
    4770             :         }
    4771             :     }
    4772           0 :     for(i=n-1; i>=1; i--)
    4773             :     {
    4774           0 :         p0 = offset+0;
    4775           0 :         p1 = offset+i;
    4776           0 :         tmp = a->ptr.p_int[p1];
    4777           0 :         a->ptr.p_int[p1] = a->ptr.p_int[p0];
    4778           0 :         a->ptr.p_int[p0] = tmp;
    4779           0 :         at = tmp;
    4780           0 :         t = 0;
    4781             :         for(;;)
    4782             :         {
    4783           0 :             k = 2*t+1;
    4784           0 :             if( k+1>i )
    4785             :             {
    4786           0 :                 break;
    4787             :             }
    4788           0 :             p0 = offset+t;
    4789           0 :             p1 = offset+k;
    4790           0 :             ak = a->ptr.p_int[p1];
    4791           0 :             if( k+1<i )
    4792             :             {
    4793           0 :                 ak1 = a->ptr.p_int[p1+1];
    4794           0 :                 if( ak1>ak )
    4795             :                 {
    4796           0 :                     ak = ak1;
    4797           0 :                     p1 = p1+1;
    4798           0 :                     k = k+1;
    4799             :                 }
    4800             :             }
    4801           0 :             if( at>=ak )
    4802             :             {
    4803           0 :                 break;
    4804             :             }
    4805           0 :             a->ptr.p_int[p1] = at;
    4806           0 :             a->ptr.p_int[p0] = ak;
    4807           0 :             t = k;
    4808             :         }
    4809             :     }
    4810             : }
    4811             : 
    4812             : 
    4813             : /*************************************************************************
    4814             : Heap operations: adds element to the heap
    4815             : 
    4816             : PARAMETERS:
    4817             :     A       -   heap itself, must be at least array[0..N]
    4818             :     B       -   array of integer tags, which are updated according to
    4819             :                 permutations in the heap
    4820             :     N       -   size of the heap (without new element).
    4821             :                 updated on output
    4822             :     VA      -   value of the element being added
    4823             :     VB      -   value of the tag
    4824             : 
    4825             :   -- ALGLIB --
    4826             :      Copyright 28.02.2010 by Bochkanov Sergey
    4827             : *************************************************************************/
    4828           0 : void tagheappushi(/* Real    */ ae_vector* a,
    4829             :      /* Integer */ ae_vector* b,
    4830             :      ae_int_t* n,
    4831             :      double va,
    4832             :      ae_int_t vb,
    4833             :      ae_state *_state)
    4834             : {
    4835             :     ae_int_t j;
    4836             :     ae_int_t k;
    4837             :     double v;
    4838             : 
    4839             : 
    4840           0 :     if( *n<0 )
    4841             :     {
    4842           0 :         return;
    4843             :     }
    4844             :     
    4845             :     /*
    4846             :      * N=0 is a special case
    4847             :      */
    4848           0 :     if( *n==0 )
    4849             :     {
    4850           0 :         a->ptr.p_double[0] = va;
    4851           0 :         b->ptr.p_int[0] = vb;
    4852           0 :         *n = *n+1;
    4853           0 :         return;
    4854             :     }
    4855             :     
    4856             :     /*
    4857             :      * add current point to the heap
    4858             :      * (add to the bottom, then move up)
    4859             :      *
    4860             :      * we don't write point to the heap
    4861             :      * until its final position is determined
    4862             :      * (it allow us to reduce number of array access operations)
    4863             :      */
    4864           0 :     j = *n;
    4865           0 :     *n = *n+1;
    4866           0 :     while(j>0)
    4867             :     {
    4868           0 :         k = (j-1)/2;
    4869           0 :         v = a->ptr.p_double[k];
    4870           0 :         if( v<va )
    4871             :         {
    4872             :             
    4873             :             /*
    4874             :              * swap with higher element
    4875             :              */
    4876           0 :             a->ptr.p_double[j] = v;
    4877           0 :             b->ptr.p_int[j] = b->ptr.p_int[k];
    4878           0 :             j = k;
    4879             :         }
    4880             :         else
    4881             :         {
    4882             :             
    4883             :             /*
    4884             :              * element in its place. terminate.
    4885             :              */
    4886           0 :             break;
    4887             :         }
    4888             :     }
    4889           0 :     a->ptr.p_double[j] = va;
    4890           0 :     b->ptr.p_int[j] = vb;
    4891             : }
    4892             : 
    4893             : 
    4894             : /*************************************************************************
    4895             : Heap operations: replaces top element with new element
    4896             : (which is moved down)
    4897             : 
    4898             : PARAMETERS:
    4899             :     A       -   heap itself, must be at least array[0..N-1]
    4900             :     B       -   array of integer tags, which are updated according to
    4901             :                 permutations in the heap
    4902             :     N       -   size of the heap
    4903             :     VA      -   value of the element which replaces top element
    4904             :     VB      -   value of the tag
    4905             : 
    4906             :   -- ALGLIB --
    4907             :      Copyright 28.02.2010 by Bochkanov Sergey
    4908             : *************************************************************************/
    4909           0 : void tagheapreplacetopi(/* Real    */ ae_vector* a,
    4910             :      /* Integer */ ae_vector* b,
    4911             :      ae_int_t n,
    4912             :      double va,
    4913             :      ae_int_t vb,
    4914             :      ae_state *_state)
    4915             : {
    4916             :     ae_int_t j;
    4917             :     ae_int_t k1;
    4918             :     ae_int_t k2;
    4919             :     double v;
    4920             :     double v1;
    4921             :     double v2;
    4922             : 
    4923             : 
    4924           0 :     if( n<1 )
    4925             :     {
    4926           0 :         return;
    4927             :     }
    4928             :     
    4929             :     /*
    4930             :      * N=1 is a special case
    4931             :      */
    4932           0 :     if( n==1 )
    4933             :     {
    4934           0 :         a->ptr.p_double[0] = va;
    4935           0 :         b->ptr.p_int[0] = vb;
    4936           0 :         return;
    4937             :     }
    4938             :     
    4939             :     /*
    4940             :      * move down through heap:
    4941             :      * * J  -   current element
    4942             :      * * K1 -   first child (always exists)
    4943             :      * * K2 -   second child (may not exists)
    4944             :      *
    4945             :      * we don't write point to the heap
    4946             :      * until its final position is determined
    4947             :      * (it allow us to reduce number of array access operations)
    4948             :      */
    4949           0 :     j = 0;
    4950           0 :     k1 = 1;
    4951           0 :     k2 = 2;
    4952           0 :     while(k1<n)
    4953             :     {
    4954           0 :         if( k2>=n )
    4955             :         {
    4956             :             
    4957             :             /*
    4958             :              * only one child.
    4959             :              *
    4960             :              * swap and terminate (because this child
    4961             :              * have no siblings due to heap structure)
    4962             :              */
    4963           0 :             v = a->ptr.p_double[k1];
    4964           0 :             if( v>va )
    4965             :             {
    4966           0 :                 a->ptr.p_double[j] = v;
    4967           0 :                 b->ptr.p_int[j] = b->ptr.p_int[k1];
    4968           0 :                 j = k1;
    4969             :             }
    4970           0 :             break;
    4971             :         }
    4972             :         else
    4973             :         {
    4974             :             
    4975             :             /*
    4976             :              * two childs
    4977             :              */
    4978           0 :             v1 = a->ptr.p_double[k1];
    4979           0 :             v2 = a->ptr.p_double[k2];
    4980           0 :             if( v1>v2 )
    4981             :             {
    4982           0 :                 if( va<v1 )
    4983             :                 {
    4984           0 :                     a->ptr.p_double[j] = v1;
    4985           0 :                     b->ptr.p_int[j] = b->ptr.p_int[k1];
    4986           0 :                     j = k1;
    4987             :                 }
    4988             :                 else
    4989             :                 {
    4990           0 :                     break;
    4991             :                 }
    4992             :             }
    4993             :             else
    4994             :             {
    4995           0 :                 if( va<v2 )
    4996             :                 {
    4997           0 :                     a->ptr.p_double[j] = v2;
    4998           0 :                     b->ptr.p_int[j] = b->ptr.p_int[k2];
    4999           0 :                     j = k2;
    5000             :                 }
    5001             :                 else
    5002             :                 {
    5003           0 :                     break;
    5004             :                 }
    5005             :             }
    5006           0 :             k1 = 2*j+1;
    5007           0 :             k2 = 2*j+2;
    5008             :         }
    5009             :     }
    5010           0 :     a->ptr.p_double[j] = va;
    5011           0 :     b->ptr.p_int[j] = vb;
    5012             : }
    5013             : 
    5014             : 
    5015             : /*************************************************************************
    5016             : Heap operations: pops top element from the heap
    5017             : 
    5018             : PARAMETERS:
    5019             :     A       -   heap itself, must be at least array[0..N-1]
    5020             :     B       -   array of integer tags, which are updated according to
    5021             :                 permutations in the heap
    5022             :     N       -   size of the heap, N>=1
    5023             : 
    5024             : On output top element is moved to A[N-1], B[N-1], heap is reordered, N is
    5025             : decreased by 1.
    5026             : 
    5027             :   -- ALGLIB --
    5028             :      Copyright 28.02.2010 by Bochkanov Sergey
    5029             : *************************************************************************/
    5030           0 : void tagheappopi(/* Real    */ ae_vector* a,
    5031             :      /* Integer */ ae_vector* b,
    5032             :      ae_int_t* n,
    5033             :      ae_state *_state)
    5034             : {
    5035             :     double va;
    5036             :     ae_int_t vb;
    5037             : 
    5038             : 
    5039           0 :     if( *n<1 )
    5040             :     {
    5041           0 :         return;
    5042             :     }
    5043             :     
    5044             :     /*
    5045             :      * N=1 is a special case
    5046             :      */
    5047           0 :     if( *n==1 )
    5048             :     {
    5049           0 :         *n = 0;
    5050           0 :         return;
    5051             :     }
    5052             :     
    5053             :     /*
    5054             :      * swap top element and last element,
    5055             :      * then reorder heap
    5056             :      */
    5057           0 :     va = a->ptr.p_double[*n-1];
    5058           0 :     vb = b->ptr.p_int[*n-1];
    5059           0 :     a->ptr.p_double[*n-1] = a->ptr.p_double[0];
    5060           0 :     b->ptr.p_int[*n-1] = b->ptr.p_int[0];
    5061           0 :     *n = *n-1;
    5062           0 :     tagheapreplacetopi(a, b, *n, va, vb, _state);
    5063             : }
    5064             : 
    5065             : 
    5066             : /*************************************************************************
    5067             : Search first element less than T in sorted array.
    5068             : 
    5069             : PARAMETERS:
    5070             :     A - sorted array by ascending from 0 to N-1
    5071             :     N - number of elements in array
    5072             :     T - the desired element
    5073             : 
    5074             : RESULT:
    5075             :     The very first element's index, which isn't less than T.
    5076             : In the case when there aren't such elements, returns N.
    5077             : *************************************************************************/
    5078           0 : ae_int_t lowerbound(/* Real    */ ae_vector* a,
    5079             :      ae_int_t n,
    5080             :      double t,
    5081             :      ae_state *_state)
    5082             : {
    5083             :     ae_int_t l;
    5084             :     ae_int_t half;
    5085             :     ae_int_t first;
    5086             :     ae_int_t middle;
    5087             :     ae_int_t result;
    5088             : 
    5089             : 
    5090           0 :     l = n;
    5091           0 :     first = 0;
    5092           0 :     while(l>0)
    5093             :     {
    5094           0 :         half = l/2;
    5095           0 :         middle = first+half;
    5096           0 :         if( ae_fp_less(a->ptr.p_double[middle],t) )
    5097             :         {
    5098           0 :             first = middle+1;
    5099           0 :             l = l-half-1;
    5100             :         }
    5101             :         else
    5102             :         {
    5103           0 :             l = half;
    5104             :         }
    5105             :     }
    5106           0 :     result = first;
    5107           0 :     return result;
    5108             : }
    5109             : 
    5110             : 
    5111             : /*************************************************************************
    5112             : Search first element more than T in sorted array.
    5113             : 
    5114             : PARAMETERS:
    5115             :     A - sorted array by ascending from 0 to N-1
    5116             :     N - number of elements in array
    5117             :     T - the desired element
    5118             : 
    5119             :     RESULT:
    5120             :     The very first element's index, which more than T.
    5121             : In the case when there aren't such elements, returns N.
    5122             : *************************************************************************/
    5123           0 : ae_int_t upperbound(/* Real    */ ae_vector* a,
    5124             :      ae_int_t n,
    5125             :      double t,
    5126             :      ae_state *_state)
    5127             : {
    5128             :     ae_int_t l;
    5129             :     ae_int_t half;
    5130             :     ae_int_t first;
    5131             :     ae_int_t middle;
    5132             :     ae_int_t result;
    5133             : 
    5134             : 
    5135           0 :     l = n;
    5136           0 :     first = 0;
    5137           0 :     while(l>0)
    5138             :     {
    5139           0 :         half = l/2;
    5140           0 :         middle = first+half;
    5141           0 :         if( ae_fp_less(t,a->ptr.p_double[middle]) )
    5142             :         {
    5143           0 :             l = half;
    5144             :         }
    5145             :         else
    5146             :         {
    5147           0 :             first = middle+1;
    5148           0 :             l = l-half-1;
    5149             :         }
    5150             :     }
    5151           0 :     result = first;
    5152           0 :     return result;
    5153             : }
    5154             : 
    5155             : 
    5156             : /*************************************************************************
    5157             : Internal TagSortFastI: sorts A[I1...I2] (both bounds are included),
    5158             : applies same permutations to B.
    5159             : 
    5160             :   -- ALGLIB --
    5161             :      Copyright 06.09.2010 by Bochkanov Sergey
    5162             : *************************************************************************/
    5163           0 : static void tsort_tagsortfastirec(/* Real    */ ae_vector* a,
    5164             :      /* Integer */ ae_vector* b,
    5165             :      /* Real    */ ae_vector* bufa,
    5166             :      /* Integer */ ae_vector* bufb,
    5167             :      ae_int_t i1,
    5168             :      ae_int_t i2,
    5169             :      ae_state *_state)
    5170             : {
    5171             :     ae_int_t i;
    5172             :     ae_int_t j;
    5173             :     ae_int_t k;
    5174             :     ae_int_t cntless;
    5175             :     ae_int_t cnteq;
    5176             :     ae_int_t cntgreater;
    5177             :     double tmpr;
    5178             :     ae_int_t tmpi;
    5179             :     double v0;
    5180             :     double v1;
    5181             :     double v2;
    5182             :     double vp;
    5183             : 
    5184             : 
    5185             :     
    5186             :     /*
    5187             :      * Fast exit
    5188             :      */
    5189           0 :     if( i2<=i1 )
    5190             :     {
    5191           0 :         return;
    5192             :     }
    5193             :     
    5194             :     /*
    5195             :      * Non-recursive sort for small arrays
    5196             :      */
    5197           0 :     if( i2-i1<=16 )
    5198             :     {
    5199           0 :         for(j=i1+1; j<=i2; j++)
    5200             :         {
    5201             :             
    5202             :             /*
    5203             :              * Search elements [I1..J-1] for place to insert Jth element.
    5204             :              *
    5205             :              * This code stops immediately if we can leave A[J] at J-th position
    5206             :              * (all elements have same value of A[J] larger than any of them)
    5207             :              */
    5208           0 :             tmpr = a->ptr.p_double[j];
    5209           0 :             tmpi = j;
    5210           0 :             for(k=j-1; k>=i1; k--)
    5211             :             {
    5212           0 :                 if( a->ptr.p_double[k]<=tmpr )
    5213             :                 {
    5214           0 :                     break;
    5215             :                 }
    5216           0 :                 tmpi = k;
    5217             :             }
    5218           0 :             k = tmpi;
    5219             :             
    5220             :             /*
    5221             :              * Insert Jth element into Kth position
    5222             :              */
    5223           0 :             if( k!=j )
    5224             :             {
    5225           0 :                 tmpr = a->ptr.p_double[j];
    5226           0 :                 tmpi = b->ptr.p_int[j];
    5227           0 :                 for(i=j-1; i>=k; i--)
    5228             :                 {
    5229           0 :                     a->ptr.p_double[i+1] = a->ptr.p_double[i];
    5230           0 :                     b->ptr.p_int[i+1] = b->ptr.p_int[i];
    5231             :                 }
    5232           0 :                 a->ptr.p_double[k] = tmpr;
    5233           0 :                 b->ptr.p_int[k] = tmpi;
    5234             :             }
    5235             :         }
    5236           0 :         return;
    5237             :     }
    5238             :     
    5239             :     /*
    5240             :      * Quicksort: choose pivot
    5241             :      * Here we assume that I2-I1>=2
    5242             :      */
    5243           0 :     v0 = a->ptr.p_double[i1];
    5244           0 :     v1 = a->ptr.p_double[i1+(i2-i1)/2];
    5245           0 :     v2 = a->ptr.p_double[i2];
    5246           0 :     if( v0>v1 )
    5247             :     {
    5248           0 :         tmpr = v1;
    5249           0 :         v1 = v0;
    5250           0 :         v0 = tmpr;
    5251             :     }
    5252           0 :     if( v1>v2 )
    5253             :     {
    5254           0 :         tmpr = v2;
    5255           0 :         v2 = v1;
    5256           0 :         v1 = tmpr;
    5257             :     }
    5258           0 :     if( v0>v1 )
    5259             :     {
    5260           0 :         tmpr = v1;
    5261           0 :         v1 = v0;
    5262           0 :         v0 = tmpr;
    5263             :     }
    5264           0 :     vp = v1;
    5265             :     
    5266             :     /*
    5267             :      * now pass through A/B and:
    5268             :      * * move elements that are LESS than VP to the left of A/B
    5269             :      * * move elements that are EQUAL to VP to the right of BufA/BufB (in the reverse order)
    5270             :      * * move elements that are GREATER than VP to the left of BufA/BufB (in the normal order
    5271             :      * * move elements from the tail of BufA/BufB to the middle of A/B (restoring normal order)
    5272             :      * * move elements from the left of BufA/BufB to the end of A/B
    5273             :      */
    5274           0 :     cntless = 0;
    5275           0 :     cnteq = 0;
    5276           0 :     cntgreater = 0;
    5277           0 :     for(i=i1; i<=i2; i++)
    5278             :     {
    5279           0 :         v0 = a->ptr.p_double[i];
    5280           0 :         if( v0<vp )
    5281             :         {
    5282             :             
    5283             :             /*
    5284             :              * LESS
    5285             :              */
    5286           0 :             k = i1+cntless;
    5287           0 :             if( i!=k )
    5288             :             {
    5289           0 :                 a->ptr.p_double[k] = v0;
    5290           0 :                 b->ptr.p_int[k] = b->ptr.p_int[i];
    5291             :             }
    5292           0 :             cntless = cntless+1;
    5293           0 :             continue;
    5294             :         }
    5295           0 :         if( v0==vp )
    5296             :         {
    5297             :             
    5298             :             /*
    5299             :              * EQUAL
    5300             :              */
    5301           0 :             k = i2-cnteq;
    5302           0 :             bufa->ptr.p_double[k] = v0;
    5303           0 :             bufb->ptr.p_int[k] = b->ptr.p_int[i];
    5304           0 :             cnteq = cnteq+1;
    5305           0 :             continue;
    5306             :         }
    5307             :         
    5308             :         /*
    5309             :          * GREATER
    5310             :          */
    5311           0 :         k = i1+cntgreater;
    5312           0 :         bufa->ptr.p_double[k] = v0;
    5313           0 :         bufb->ptr.p_int[k] = b->ptr.p_int[i];
    5314           0 :         cntgreater = cntgreater+1;
    5315             :     }
    5316           0 :     for(i=0; i<=cnteq-1; i++)
    5317             :     {
    5318           0 :         j = i1+cntless+cnteq-1-i;
    5319           0 :         k = i2+i-(cnteq-1);
    5320           0 :         a->ptr.p_double[j] = bufa->ptr.p_double[k];
    5321           0 :         b->ptr.p_int[j] = bufb->ptr.p_int[k];
    5322             :     }
    5323           0 :     for(i=0; i<=cntgreater-1; i++)
    5324             :     {
    5325           0 :         j = i1+cntless+cnteq+i;
    5326           0 :         k = i1+i;
    5327           0 :         a->ptr.p_double[j] = bufa->ptr.p_double[k];
    5328           0 :         b->ptr.p_int[j] = bufb->ptr.p_int[k];
    5329             :     }
    5330             :     
    5331             :     /*
    5332             :      * Sort left and right parts of the array (ignoring middle part)
    5333             :      */
    5334           0 :     tsort_tagsortfastirec(a, b, bufa, bufb, i1, i1+cntless-1, _state);
    5335           0 :     tsort_tagsortfastirec(a, b, bufa, bufb, i1+cntless+cnteq, i2, _state);
    5336             : }
    5337             : 
    5338             : 
    5339             : /*************************************************************************
    5340             : Internal TagSortFastR: sorts A[I1...I2] (both bounds are included),
    5341             : applies same permutations to B.
    5342             : 
    5343             :   -- ALGLIB --
    5344             :      Copyright 06.09.2010 by Bochkanov Sergey
    5345             : *************************************************************************/
    5346           0 : static void tsort_tagsortfastrrec(/* Real    */ ae_vector* a,
    5347             :      /* Real    */ ae_vector* b,
    5348             :      /* Real    */ ae_vector* bufa,
    5349             :      /* Real    */ ae_vector* bufb,
    5350             :      ae_int_t i1,
    5351             :      ae_int_t i2,
    5352             :      ae_state *_state)
    5353             : {
    5354             :     ae_int_t i;
    5355             :     ae_int_t j;
    5356             :     ae_int_t k;
    5357             :     double tmpr;
    5358             :     double tmpr2;
    5359             :     ae_int_t tmpi;
    5360             :     ae_int_t cntless;
    5361             :     ae_int_t cnteq;
    5362             :     ae_int_t cntgreater;
    5363             :     double v0;
    5364             :     double v1;
    5365             :     double v2;
    5366             :     double vp;
    5367             : 
    5368             : 
    5369             :     
    5370             :     /*
    5371             :      * Fast exit
    5372             :      */
    5373           0 :     if( i2<=i1 )
    5374             :     {
    5375           0 :         return;
    5376             :     }
    5377             :     
    5378             :     /*
    5379             :      * Non-recursive sort for small arrays
    5380             :      */
    5381           0 :     if( i2-i1<=16 )
    5382             :     {
    5383           0 :         for(j=i1+1; j<=i2; j++)
    5384             :         {
    5385             :             
    5386             :             /*
    5387             :              * Search elements [I1..J-1] for place to insert Jth element.
    5388             :              *
    5389             :              * This code stops immediatly if we can leave A[J] at J-th position
    5390             :              * (all elements have same value of A[J] larger than any of them)
    5391             :              */
    5392           0 :             tmpr = a->ptr.p_double[j];
    5393           0 :             tmpi = j;
    5394           0 :             for(k=j-1; k>=i1; k--)
    5395             :             {
    5396           0 :                 if( a->ptr.p_double[k]<=tmpr )
    5397             :                 {
    5398           0 :                     break;
    5399             :                 }
    5400           0 :                 tmpi = k;
    5401             :             }
    5402           0 :             k = tmpi;
    5403             :             
    5404             :             /*
    5405             :              * Insert Jth element into Kth position
    5406             :              */
    5407           0 :             if( k!=j )
    5408             :             {
    5409           0 :                 tmpr = a->ptr.p_double[j];
    5410           0 :                 tmpr2 = b->ptr.p_double[j];
    5411           0 :                 for(i=j-1; i>=k; i--)
    5412             :                 {
    5413           0 :                     a->ptr.p_double[i+1] = a->ptr.p_double[i];
    5414           0 :                     b->ptr.p_double[i+1] = b->ptr.p_double[i];
    5415             :                 }
    5416           0 :                 a->ptr.p_double[k] = tmpr;
    5417           0 :                 b->ptr.p_double[k] = tmpr2;
    5418             :             }
    5419             :         }
    5420           0 :         return;
    5421             :     }
    5422             :     
    5423             :     /*
    5424             :      * Quicksort: choose pivot
    5425             :      * Here we assume that I2-I1>=16
    5426             :      */
    5427           0 :     v0 = a->ptr.p_double[i1];
    5428           0 :     v1 = a->ptr.p_double[i1+(i2-i1)/2];
    5429           0 :     v2 = a->ptr.p_double[i2];
    5430           0 :     if( v0>v1 )
    5431             :     {
    5432           0 :         tmpr = v1;
    5433           0 :         v1 = v0;
    5434           0 :         v0 = tmpr;
    5435             :     }
    5436           0 :     if( v1>v2 )
    5437             :     {
    5438           0 :         tmpr = v2;
    5439           0 :         v2 = v1;
    5440           0 :         v1 = tmpr;
    5441             :     }
    5442           0 :     if( v0>v1 )
    5443             :     {
    5444           0 :         tmpr = v1;
    5445           0 :         v1 = v0;
    5446           0 :         v0 = tmpr;
    5447             :     }
    5448           0 :     vp = v1;
    5449             :     
    5450             :     /*
    5451             :      * now pass through A/B and:
    5452             :      * * move elements that are LESS than VP to the left of A/B
    5453             :      * * move elements that are EQUAL to VP to the right of BufA/BufB (in the reverse order)
    5454             :      * * move elements that are GREATER than VP to the left of BufA/BufB (in the normal order
    5455             :      * * move elements from the tail of BufA/BufB to the middle of A/B (restoring normal order)
    5456             :      * * move elements from the left of BufA/BufB to the end of A/B
    5457             :      */
    5458           0 :     cntless = 0;
    5459           0 :     cnteq = 0;
    5460           0 :     cntgreater = 0;
    5461           0 :     for(i=i1; i<=i2; i++)
    5462             :     {
    5463           0 :         v0 = a->ptr.p_double[i];
    5464           0 :         if( v0<vp )
    5465             :         {
    5466             :             
    5467             :             /*
    5468             :              * LESS
    5469             :              */
    5470           0 :             k = i1+cntless;
    5471           0 :             if( i!=k )
    5472             :             {
    5473           0 :                 a->ptr.p_double[k] = v0;
    5474           0 :                 b->ptr.p_double[k] = b->ptr.p_double[i];
    5475             :             }
    5476           0 :             cntless = cntless+1;
    5477           0 :             continue;
    5478             :         }
    5479           0 :         if( v0==vp )
    5480             :         {
    5481             :             
    5482             :             /*
    5483             :              * EQUAL
    5484             :              */
    5485           0 :             k = i2-cnteq;
    5486           0 :             bufa->ptr.p_double[k] = v0;
    5487           0 :             bufb->ptr.p_double[k] = b->ptr.p_double[i];
    5488           0 :             cnteq = cnteq+1;
    5489           0 :             continue;
    5490             :         }
    5491             :         
    5492             :         /*
    5493             :          * GREATER
    5494             :          */
    5495           0 :         k = i1+cntgreater;
    5496           0 :         bufa->ptr.p_double[k] = v0;
    5497           0 :         bufb->ptr.p_double[k] = b->ptr.p_double[i];
    5498           0 :         cntgreater = cntgreater+1;
    5499             :     }
    5500           0 :     for(i=0; i<=cnteq-1; i++)
    5501             :     {
    5502           0 :         j = i1+cntless+cnteq-1-i;
    5503           0 :         k = i2+i-(cnteq-1);
    5504           0 :         a->ptr.p_double[j] = bufa->ptr.p_double[k];
    5505           0 :         b->ptr.p_double[j] = bufb->ptr.p_double[k];
    5506             :     }
    5507           0 :     for(i=0; i<=cntgreater-1; i++)
    5508             :     {
    5509           0 :         j = i1+cntless+cnteq+i;
    5510           0 :         k = i1+i;
    5511           0 :         a->ptr.p_double[j] = bufa->ptr.p_double[k];
    5512           0 :         b->ptr.p_double[j] = bufb->ptr.p_double[k];
    5513             :     }
    5514             :     
    5515             :     /*
    5516             :      * Sort left and right parts of the array (ignoring middle part)
    5517             :      */
    5518           0 :     tsort_tagsortfastrrec(a, b, bufa, bufb, i1, i1+cntless-1, _state);
    5519           0 :     tsort_tagsortfastrrec(a, b, bufa, bufb, i1+cntless+cnteq, i2, _state);
    5520             : }
    5521             : 
    5522             : 
    5523             : /*************************************************************************
    5524             : Internal TagSortFastI: sorts A[I1...I2] (both bounds are included),
    5525             : applies same permutations to B.
    5526             : 
    5527             :   -- ALGLIB --
    5528             :      Copyright 06.09.2010 by Bochkanov Sergey
    5529             : *************************************************************************/
    5530           0 : static void tsort_tagsortfastrec(/* Real    */ ae_vector* a,
    5531             :      /* Real    */ ae_vector* bufa,
    5532             :      ae_int_t i1,
    5533             :      ae_int_t i2,
    5534             :      ae_state *_state)
    5535             : {
    5536             :     ae_int_t cntless;
    5537             :     ae_int_t cnteq;
    5538             :     ae_int_t cntgreater;
    5539             :     ae_int_t i;
    5540             :     ae_int_t j;
    5541             :     ae_int_t k;
    5542             :     double tmpr;
    5543             :     ae_int_t tmpi;
    5544             :     double v0;
    5545             :     double v1;
    5546             :     double v2;
    5547             :     double vp;
    5548             : 
    5549             : 
    5550             :     
    5551             :     /*
    5552             :      * Fast exit
    5553             :      */
    5554           0 :     if( i2<=i1 )
    5555             :     {
    5556           0 :         return;
    5557             :     }
    5558             :     
    5559             :     /*
    5560             :      * Non-recursive sort for small arrays
    5561             :      */
    5562           0 :     if( i2-i1<=16 )
    5563             :     {
    5564           0 :         for(j=i1+1; j<=i2; j++)
    5565             :         {
    5566             :             
    5567             :             /*
    5568             :              * Search elements [I1..J-1] for place to insert Jth element.
    5569             :              *
    5570             :              * This code stops immediatly if we can leave A[J] at J-th position
    5571             :              * (all elements have same value of A[J] larger than any of them)
    5572             :              */
    5573           0 :             tmpr = a->ptr.p_double[j];
    5574           0 :             tmpi = j;
    5575           0 :             for(k=j-1; k>=i1; k--)
    5576             :             {
    5577           0 :                 if( a->ptr.p_double[k]<=tmpr )
    5578             :                 {
    5579           0 :                     break;
    5580             :                 }
    5581           0 :                 tmpi = k;
    5582             :             }
    5583           0 :             k = tmpi;
    5584             :             
    5585             :             /*
    5586             :              * Insert Jth element into Kth position
    5587             :              */
    5588           0 :             if( k!=j )
    5589             :             {
    5590           0 :                 tmpr = a->ptr.p_double[j];
    5591           0 :                 for(i=j-1; i>=k; i--)
    5592             :                 {
    5593           0 :                     a->ptr.p_double[i+1] = a->ptr.p_double[i];
    5594             :                 }
    5595           0 :                 a->ptr.p_double[k] = tmpr;
    5596             :             }
    5597             :         }
    5598           0 :         return;
    5599             :     }
    5600             :     
    5601             :     /*
    5602             :      * Quicksort: choose pivot
    5603             :      * Here we assume that I2-I1>=16
    5604             :      */
    5605           0 :     v0 = a->ptr.p_double[i1];
    5606           0 :     v1 = a->ptr.p_double[i1+(i2-i1)/2];
    5607           0 :     v2 = a->ptr.p_double[i2];
    5608           0 :     if( v0>v1 )
    5609             :     {
    5610           0 :         tmpr = v1;
    5611           0 :         v1 = v0;
    5612           0 :         v0 = tmpr;
    5613             :     }
    5614           0 :     if( v1>v2 )
    5615             :     {
    5616           0 :         tmpr = v2;
    5617           0 :         v2 = v1;
    5618           0 :         v1 = tmpr;
    5619             :     }
    5620           0 :     if( v0>v1 )
    5621             :     {
    5622           0 :         tmpr = v1;
    5623           0 :         v1 = v0;
    5624           0 :         v0 = tmpr;
    5625             :     }
    5626           0 :     vp = v1;
    5627             :     
    5628             :     /*
    5629             :      * now pass through A/B and:
    5630             :      * * move elements that are LESS than VP to the left of A/B
    5631             :      * * move elements that are EQUAL to VP to the right of BufA/BufB (in the reverse order)
    5632             :      * * move elements that are GREATER than VP to the left of BufA/BufB (in the normal order
    5633             :      * * move elements from the tail of BufA/BufB to the middle of A/B (restoring normal order)
    5634             :      * * move elements from the left of BufA/BufB to the end of A/B
    5635             :      */
    5636           0 :     cntless = 0;
    5637           0 :     cnteq = 0;
    5638           0 :     cntgreater = 0;
    5639           0 :     for(i=i1; i<=i2; i++)
    5640             :     {
    5641           0 :         v0 = a->ptr.p_double[i];
    5642           0 :         if( v0<vp )
    5643             :         {
    5644             :             
    5645             :             /*
    5646             :              * LESS
    5647             :              */
    5648           0 :             k = i1+cntless;
    5649           0 :             if( i!=k )
    5650             :             {
    5651           0 :                 a->ptr.p_double[k] = v0;
    5652             :             }
    5653           0 :             cntless = cntless+1;
    5654           0 :             continue;
    5655             :         }
    5656           0 :         if( v0==vp )
    5657             :         {
    5658             :             
    5659             :             /*
    5660             :              * EQUAL
    5661             :              */
    5662           0 :             k = i2-cnteq;
    5663           0 :             bufa->ptr.p_double[k] = v0;
    5664           0 :             cnteq = cnteq+1;
    5665           0 :             continue;
    5666             :         }
    5667             :         
    5668             :         /*
    5669             :          * GREATER
    5670             :          */
    5671           0 :         k = i1+cntgreater;
    5672           0 :         bufa->ptr.p_double[k] = v0;
    5673           0 :         cntgreater = cntgreater+1;
    5674             :     }
    5675           0 :     for(i=0; i<=cnteq-1; i++)
    5676             :     {
    5677           0 :         j = i1+cntless+cnteq-1-i;
    5678           0 :         k = i2+i-(cnteq-1);
    5679           0 :         a->ptr.p_double[j] = bufa->ptr.p_double[k];
    5680             :     }
    5681           0 :     for(i=0; i<=cntgreater-1; i++)
    5682             :     {
    5683           0 :         j = i1+cntless+cnteq+i;
    5684           0 :         k = i1+i;
    5685           0 :         a->ptr.p_double[j] = bufa->ptr.p_double[k];
    5686             :     }
    5687             :     
    5688             :     /*
    5689             :      * Sort left and right parts of the array (ignoring middle part)
    5690             :      */
    5691           0 :     tsort_tagsortfastrec(a, bufa, i1, i1+cntless-1, _state);
    5692           0 :     tsort_tagsortfastrec(a, bufa, i1+cntless+cnteq, i2, _state);
    5693             : }
    5694             : 
    5695             : 
    5696             : #endif
    5697             : #if defined(AE_COMPILE_ABLASF) || !defined(AE_PARTIAL_BUILD)
    5698             : 
    5699             : 
    5700             : /*************************************************************************
    5701             : Computes dot product (X,Y) for elements [0,N) of X[] and Y[]
    5702             : 
    5703             : INPUT PARAMETERS:
    5704             :     N       -   vector length
    5705             :     X       -   array[N], vector to process
    5706             :     Y       -   array[N], vector to process
    5707             : 
    5708             : RESULT:
    5709             :     (X,Y)
    5710             : 
    5711             :   -- ALGLIB --
    5712             :      Copyright 20.01.2020 by Bochkanov Sergey
    5713             : *************************************************************************/
    5714           0 : double rdotv(ae_int_t n,
    5715             :      /* Real    */ ae_vector* x,
    5716             :      /* Real    */ ae_vector* y,
    5717             :      ae_state *_state)
    5718             : {
    5719             :     ae_int_t i;
    5720             :     double result;
    5721             : 
    5722             : 
    5723           0 :     result = (double)(0);
    5724           0 :     for(i=0; i<=n-1; i++)
    5725             :     {
    5726           0 :         result = result+x->ptr.p_double[i]*y->ptr.p_double[i];
    5727             :     }
    5728           0 :     return result;
    5729             : }
    5730             : 
    5731             : 
    5732             : /*************************************************************************
    5733             : Computes dot product (X,A[i]) for elements [0,N) of vector X[] and row A[i,*]
    5734             : 
    5735             : INPUT PARAMETERS:
    5736             :     N       -   vector length
    5737             :     X       -   array[N], vector to process
    5738             :     A       -   array[?,N], matrix to process
    5739             :     I       -   row index
    5740             : 
    5741             : RESULT:
    5742             :     (X,Ai)
    5743             : 
    5744             :   -- ALGLIB --
    5745             :      Copyright 20.01.2020 by Bochkanov Sergey
    5746             : *************************************************************************/
    5747           0 : double rdotvr(ae_int_t n,
    5748             :      /* Real    */ ae_vector* x,
    5749             :      /* Real    */ ae_matrix* a,
    5750             :      ae_int_t i,
    5751             :      ae_state *_state)
    5752             : {
    5753             :     ae_int_t j;
    5754             :     double result;
    5755             : 
    5756             : 
    5757           0 :     result = (double)(0);
    5758           0 :     for(j=0; j<=n-1; j++)
    5759             :     {
    5760           0 :         result = result+x->ptr.p_double[j]*a->ptr.pp_double[i][j];
    5761             :     }
    5762           0 :     return result;
    5763             : }
    5764             : 
    5765             : 
    5766             : /*************************************************************************
    5767             : Computes dot product (X,A[i]) for rows A[ia,*] and B[ib,*]
    5768             : 
    5769             : INPUT PARAMETERS:
    5770             :     N       -   vector length
    5771             :     X       -   array[N], vector to process
    5772             :     A       -   array[?,N], matrix to process
    5773             :     I       -   row index
    5774             : 
    5775             : RESULT:
    5776             :     (X,Ai)
    5777             : 
    5778             :   -- ALGLIB --
    5779             :      Copyright 20.01.2020 by Bochkanov Sergey
    5780             : *************************************************************************/
    5781           0 : double rdotrr(ae_int_t n,
    5782             :      /* Real    */ ae_matrix* a,
    5783             :      ae_int_t ia,
    5784             :      /* Real    */ ae_matrix* b,
    5785             :      ae_int_t ib,
    5786             :      ae_state *_state)
    5787             : {
    5788             :     ae_int_t j;
    5789             :     double result;
    5790             : 
    5791             : 
    5792           0 :     result = (double)(0);
    5793           0 :     for(j=0; j<=n-1; j++)
    5794             :     {
    5795           0 :         result = result+a->ptr.pp_double[ia][j]*b->ptr.pp_double[ib][j];
    5796             :     }
    5797           0 :     return result;
    5798             : }
    5799             : 
    5800             : 
    5801             : /*************************************************************************
    5802             : Computes dot product (X,X) for elements [0,N) of X[]
    5803             : 
    5804             : INPUT PARAMETERS:
    5805             :     N       -   vector length
    5806             :     X       -   array[N], vector to process
    5807             : 
    5808             : RESULT:
    5809             :     (X,X)
    5810             : 
    5811             :   -- ALGLIB --
    5812             :      Copyright 20.01.2020 by Bochkanov Sergey
    5813             : *************************************************************************/
    5814           0 : double rdotv2(ae_int_t n, /* Real    */ ae_vector* x, ae_state *_state)
    5815             : {
    5816             :     ae_int_t i;
    5817             :     double v;
    5818             :     double result;
    5819             : 
    5820             : 
    5821           0 :     result = (double)(0);
    5822           0 :     for(i=0; i<=n-1; i++)
    5823             :     {
    5824           0 :         v = x->ptr.p_double[i];
    5825           0 :         result = result+v*v;
    5826             :     }
    5827           0 :     return result;
    5828             : }
    5829             : 
    5830             : 
    5831             : /*************************************************************************
    5832             : Performs inplace addition of Y[] to X[]
    5833             : 
    5834             : INPUT PARAMETERS:
    5835             :     N       -   vector length
    5836             :     Alpha   -   multiplier
    5837             :     Y       -   array[N], vector to process
    5838             :     X       -   array[N], vector to process
    5839             : 
    5840             : RESULT:
    5841             :     X := X + alpha*Y
    5842             : 
    5843             :   -- ALGLIB --
    5844             :      Copyright 20.01.2020 by Bochkanov Sergey
    5845             : *************************************************************************/
    5846           0 : void raddv(ae_int_t n,
    5847             :      double alpha,
    5848             :      /* Real    */ ae_vector* y,
    5849             :      /* Real    */ ae_vector* x,
    5850             :      ae_state *_state)
    5851             : {
    5852             :     ae_int_t i;
    5853             : 
    5854             : 
    5855           0 :     for(i=0; i<=n-1; i++)
    5856             :     {
    5857           0 :         x->ptr.p_double[i] = x->ptr.p_double[i]+alpha*y->ptr.p_double[i];
    5858             :     }
    5859           0 : }
    5860             : 
    5861             : 
    5862             : /*************************************************************************
    5863             : Performs inplace addition of Y[] to X[]
    5864             : 
    5865             : INPUT PARAMETERS:
    5866             :     N       -   vector length
    5867             :     Alpha   -   multiplier
    5868             :     Y       -   source vector
    5869             :     OffsY   -   source offset
    5870             :     X       -   destination vector
    5871             :     OffsX   -   destination offset
    5872             : 
    5873             : RESULT:
    5874             :     X := X + alpha*Y
    5875             : 
    5876             :   -- ALGLIB --
    5877             :      Copyright 20.01.2020 by Bochkanov Sergey
    5878             : *************************************************************************/
    5879           0 : void raddvx(ae_int_t n,
    5880             :      double alpha,
    5881             :      /* Real    */ ae_vector* y,
    5882             :      ae_int_t offsy,
    5883             :      /* Real    */ ae_vector* x,
    5884             :      ae_int_t offsx,
    5885             :      ae_state *_state)
    5886             : {
    5887             :     ae_int_t i;
    5888             : 
    5889             : 
    5890           0 :     for(i=0; i<=n-1; i++)
    5891             :     {
    5892           0 :         x->ptr.p_double[offsx+i] = x->ptr.p_double[offsx+i]+alpha*y->ptr.p_double[offsy+i];
    5893             :     }
    5894           0 : }
    5895             : 
    5896             : 
    5897             : /*************************************************************************
    5898             : Performs inplace addition of vector Y[] to column X[]
    5899             : 
    5900             : INPUT PARAMETERS:
    5901             :     N       -   vector length
    5902             :     Alpha   -   multiplier
    5903             :     Y       -   vector to add
    5904             :     X       -   target column ColIdx
    5905             : 
    5906             : RESULT:
    5907             :     X := X + alpha*Y
    5908             : 
    5909             :   -- ALGLIB --
    5910             :      Copyright 20.01.2020 by Bochkanov Sergey
    5911             : *************************************************************************/
    5912           0 : void raddvc(ae_int_t n,
    5913             :      double alpha,
    5914             :      /* Real    */ ae_vector* y,
    5915             :      /* Real    */ ae_matrix* x,
    5916             :      ae_int_t colidx,
    5917             :      ae_state *_state)
    5918             : {
    5919             :     ae_int_t i;
    5920             : 
    5921             : 
    5922           0 :     for(i=0; i<=n-1; i++)
    5923             :     {
    5924           0 :         x->ptr.pp_double[i][colidx] = x->ptr.pp_double[i][colidx]+alpha*y->ptr.p_double[i];
    5925             :     }
    5926           0 : }
    5927             : 
    5928             : 
    5929             : /*************************************************************************
    5930             : Performs inplace addition of vector Y[] to row X[]
    5931             : 
    5932             : INPUT PARAMETERS:
    5933             :     N       -   vector length
    5934             :     Alpha   -   multiplier
    5935             :     Y       -   vector to add
    5936             :     X       -   target row RowIdx
    5937             : 
    5938             : RESULT:
    5939             :     X := X + alpha*Y
    5940             : 
    5941             :   -- ALGLIB --
    5942             :      Copyright 20.01.2020 by Bochkanov Sergey
    5943             : *************************************************************************/
    5944           0 : void raddvr(ae_int_t n,
    5945             :      double alpha,
    5946             :      /* Real    */ ae_vector* y,
    5947             :      /* Real    */ ae_matrix* x,
    5948             :      ae_int_t rowidx,
    5949             :      ae_state *_state)
    5950             : {
    5951             :     ae_int_t i;
    5952             : 
    5953             : 
    5954           0 :     for(i=0; i<=n-1; i++)
    5955             :     {
    5956           0 :         x->ptr.pp_double[rowidx][i] = x->ptr.pp_double[rowidx][i]+alpha*y->ptr.p_double[i];
    5957             :     }
    5958           0 : }
    5959             : 
    5960             : 
    5961             : /*************************************************************************
    5962             : Performs componentwise multiplication of row X[] by vector Y[]
    5963             : 
    5964             : INPUT PARAMETERS:
    5965             :     N       -   vector length
    5966             :     Y       -   vector to multiply by
    5967             :     X       -   target row RowIdx
    5968             : 
    5969             : RESULT:
    5970             :     X := componentwise(X*Y)
    5971             : 
    5972             :   -- ALGLIB --
    5973             :      Copyright 20.01.2020 by Bochkanov Sergey
    5974             : *************************************************************************/
    5975           0 : void rmergemulvr(ae_int_t n,
    5976             :      /* Real    */ ae_vector* y,
    5977             :      /* Real    */ ae_matrix* x,
    5978             :      ae_int_t rowidx,
    5979             :      ae_state *_state)
    5980             : {
    5981             :     ae_int_t i;
    5982             : 
    5983             : 
    5984           0 :     for(i=0; i<=n-1; i++)
    5985             :     {
    5986           0 :         x->ptr.pp_double[rowidx][i] = x->ptr.pp_double[rowidx][i]*y->ptr.p_double[i];
    5987             :     }
    5988           0 : }
    5989             : 
    5990             : 
    5991             : /*************************************************************************
    5992             : Performs componentwise max of row X[I] and vector Y[] 
    5993             : 
    5994             : INPUT PARAMETERS:
    5995             :     N       -   vector length
    5996             :     X       -   matrix, I-th row is source
    5997             :     X       -   target row RowIdx
    5998             : 
    5999             : RESULT:
    6000             :     X := componentwise(X*Y)
    6001             : 
    6002             :   -- ALGLIB --
    6003             :      Copyright 20.01.2020 by Bochkanov Sergey
    6004             : *************************************************************************/
    6005           0 : void rmergemaxrv(ae_int_t n,
    6006             :      /* Real    */ ae_matrix* x,
    6007             :      ae_int_t rowidx,
    6008             :      /* Real    */ ae_vector* y,
    6009             :      ae_state *_state)
    6010             : {
    6011             :     ae_int_t i;
    6012             : 
    6013             : 
    6014           0 :     for(i=0; i<=n-1; i++)
    6015             :     {
    6016           0 :         y->ptr.p_double[i] = ae_maxreal(y->ptr.p_double[i], x->ptr.pp_double[rowidx][i], _state);
    6017             :     }
    6018           0 : }
    6019             : 
    6020             : 
    6021             : /*************************************************************************
    6022             : Performs inplace addition of Y[RIdx,...] to X[]
    6023             : 
    6024             : INPUT PARAMETERS:
    6025             :     N       -   vector length
    6026             :     Alpha   -   multiplier
    6027             :     Y       -   array[?,N], matrix whose RIdx-th row is added
    6028             :     RIdx    -   row index
    6029             :     X       -   array[N], vector to process
    6030             : 
    6031             : RESULT:
    6032             :     X := X + alpha*Y
    6033             : 
    6034             :   -- ALGLIB --
    6035             :      Copyright 20.01.2020 by Bochkanov Sergey
    6036             : *************************************************************************/
    6037           0 : void raddrv(ae_int_t n,
    6038             :      double alpha,
    6039             :      /* Real    */ ae_matrix* y,
    6040             :      ae_int_t ridx,
    6041             :      /* Real    */ ae_vector* x,
    6042             :      ae_state *_state)
    6043             : {
    6044             :     ae_int_t i;
    6045             : 
    6046             : 
    6047           0 :     for(i=0; i<=n-1; i++)
    6048             :     {
    6049           0 :         x->ptr.p_double[i] = x->ptr.p_double[i]+alpha*y->ptr.pp_double[ridx][i];
    6050             :     }
    6051           0 : }
    6052             : 
    6053             : 
    6054             : /*************************************************************************
    6055             : Performs inplace multiplication of X[] by V
    6056             : 
    6057             : INPUT PARAMETERS:
    6058             :     N       -   vector length
    6059             :     X       -   array[N], vector to process
    6060             :     V       -   multiplier
    6061             : 
    6062             : OUTPUT PARAMETERS:
    6063             :     X       -   elements 0...N-1 multiplied by V
    6064             : 
    6065             :   -- ALGLIB --
    6066             :      Copyright 20.01.2020 by Bochkanov Sergey
    6067             : *************************************************************************/
    6068           0 : void rmulv(ae_int_t n,
    6069             :      double v,
    6070             :      /* Real    */ ae_vector* x,
    6071             :      ae_state *_state)
    6072             : {
    6073             :     ae_int_t i;
    6074             : 
    6075             : 
    6076           0 :     for(i=0; i<=n-1; i++)
    6077             :     {
    6078           0 :         x->ptr.p_double[i] = x->ptr.p_double[i]*v;
    6079             :     }
    6080           0 : }
    6081             : 
    6082             : 
    6083             : /*************************************************************************
    6084             : Performs inplace multiplication of X[] by V
    6085             : 
    6086             : INPUT PARAMETERS:
    6087             :     N       -   row length
    6088             :     X       -   array[?,N], row to process
    6089             :     V       -   multiplier
    6090             : 
    6091             : OUTPUT PARAMETERS:
    6092             :     X       -   elements 0...N-1 of row RowIdx are multiplied by V
    6093             : 
    6094             :   -- ALGLIB --
    6095             :      Copyright 20.01.2020 by Bochkanov Sergey
    6096             : *************************************************************************/
    6097           0 : void rmulr(ae_int_t n,
    6098             :      double v,
    6099             :      /* Real    */ ae_matrix* x,
    6100             :      ae_int_t rowidx,
    6101             :      ae_state *_state)
    6102             : {
    6103             :     ae_int_t i;
    6104             : 
    6105             : 
    6106           0 :     for(i=0; i<=n-1; i++)
    6107             :     {
    6108           0 :         x->ptr.pp_double[rowidx][i] = x->ptr.pp_double[rowidx][i]*v;
    6109             :     }
    6110           0 : }
    6111             : 
    6112             : 
    6113             : /*************************************************************************
    6114             : Performs inplace multiplication of X[OffsX:OffsX+N-1] by V
    6115             : 
    6116             : INPUT PARAMETERS:
    6117             :     N       -   subvector length
    6118             :     X       -   vector to process
    6119             :     V       -   multiplier
    6120             : 
    6121             : OUTPUT PARAMETERS:
    6122             :     X       -   elements OffsX:OffsX+N-1 multiplied by V
    6123             : 
    6124             :   -- ALGLIB --
    6125             :      Copyright 20.01.2020 by Bochkanov Sergey
    6126             : *************************************************************************/
    6127           0 : void rmulvx(ae_int_t n,
    6128             :      double v,
    6129             :      /* Real    */ ae_vector* x,
    6130             :      ae_int_t offsx,
    6131             :      ae_state *_state)
    6132             : {
    6133             :     ae_int_t i;
    6134             : 
    6135             : 
    6136           0 :     for(i=0; i<=n-1; i++)
    6137             :     {
    6138           0 :         x->ptr.p_double[offsx+i] = x->ptr.p_double[offsx+i]*v;
    6139             :     }
    6140           0 : }
    6141             : 
    6142             : 
    6143             : /*************************************************************************
    6144             : Returns maximum |X|
    6145             : 
    6146             : INPUT PARAMETERS:
    6147             :     N       -   vector length
    6148             :     X       -   array[N], vector to process
    6149             : 
    6150             : OUTPUT PARAMETERS:
    6151             :     max(|X[i]|)
    6152             : 
    6153             :   -- ALGLIB --
    6154             :      Copyright 20.01.2020 by Bochkanov Sergey
    6155             : *************************************************************************/
    6156           0 : double rmaxabsv(ae_int_t n, /* Real    */ ae_vector* x, ae_state *_state)
    6157             : {
    6158             :     ae_int_t i;
    6159             :     double v;
    6160             :     double result;
    6161             : 
    6162             : 
    6163           0 :     result = (double)(0);
    6164           0 :     for(i=0; i<=n-1; i++)
    6165             :     {
    6166           0 :         v = ae_fabs(x->ptr.p_double[i], _state);
    6167           0 :         if( ae_fp_greater(v,result) )
    6168             :         {
    6169           0 :             result = v;
    6170             :         }
    6171             :     }
    6172           0 :     return result;
    6173             : }
    6174             : 
    6175             : 
    6176             : /*************************************************************************
    6177             : Sets vector X[] to V
    6178             : 
    6179             : INPUT PARAMETERS:
    6180             :     N       -   vector length
    6181             :     V       -   value to set
    6182             :     X       -   array[N]
    6183             : 
    6184             : OUTPUT PARAMETERS:
    6185             :     X       -   leading N elements are replaced by V
    6186             : 
    6187             :   -- ALGLIB --
    6188             :      Copyright 20.01.2020 by Bochkanov Sergey
    6189             : *************************************************************************/
    6190           0 : void rsetv(ae_int_t n,
    6191             :      double v,
    6192             :      /* Real    */ ae_vector* x,
    6193             :      ae_state *_state)
    6194             : {
    6195             :     ae_int_t j;
    6196             : 
    6197             : 
    6198           0 :     for(j=0; j<=n-1; j++)
    6199             :     {
    6200           0 :         x->ptr.p_double[j] = v;
    6201             :     }
    6202           0 : }
    6203             : 
    6204             : 
    6205             : /*************************************************************************
    6206             : Sets X[OffsX:OffsX+N-1] to V
    6207             : 
    6208             : INPUT PARAMETERS:
    6209             :     N       -   subvector length
    6210             :     V       -   value to set
    6211             :     X       -   array[N]
    6212             : 
    6213             : OUTPUT PARAMETERS:
    6214             :     X       -   X[OffsX:OffsX+N-1] is replaced by V
    6215             : 
    6216             :   -- ALGLIB --
    6217             :      Copyright 20.01.2020 by Bochkanov Sergey
    6218             : *************************************************************************/
    6219           0 : void rsetvx(ae_int_t n,
    6220             :      double v,
    6221             :      /* Real    */ ae_vector* x,
    6222             :      ae_int_t offsx,
    6223             :      ae_state *_state)
    6224             : {
    6225             :     ae_int_t j;
    6226             : 
    6227             : 
    6228           0 :     for(j=0; j<=n-1; j++)
    6229             :     {
    6230           0 :         x->ptr.p_double[offsx+j] = v;
    6231             :     }
    6232           0 : }
    6233             : 
    6234             : 
    6235             : /*************************************************************************
    6236             : Sets vector X[] to V
    6237             : 
    6238             : INPUT PARAMETERS:
    6239             :     N       -   vector length
    6240             :     V       -   value to set
    6241             :     X       -   array[N]
    6242             : 
    6243             : OUTPUT PARAMETERS:
    6244             :     X       -   leading N elements are replaced by V
    6245             : 
    6246             :   -- ALGLIB --
    6247             :      Copyright 20.01.2020 by Bochkanov Sergey
    6248             : *************************************************************************/
    6249           0 : void isetv(ae_int_t n,
    6250             :      ae_int_t v,
    6251             :      /* Integer */ ae_vector* x,
    6252             :      ae_state *_state)
    6253             : {
    6254             :     ae_int_t j;
    6255             : 
    6256             : 
    6257           0 :     for(j=0; j<=n-1; j++)
    6258             :     {
    6259           0 :         x->ptr.p_int[j] = v;
    6260             :     }
    6261           0 : }
    6262             : 
    6263             : 
    6264             : /*************************************************************************
    6265             : Sets vector X[] to V
    6266             : 
    6267             : INPUT PARAMETERS:
    6268             :     N       -   vector length
    6269             :     V       -   value to set
    6270             :     X       -   array[N]
    6271             : 
    6272             : OUTPUT PARAMETERS:
    6273             :     X       -   leading N elements are replaced by V
    6274             : 
    6275             :   -- ALGLIB --
    6276             :      Copyright 20.01.2020 by Bochkanov Sergey
    6277             : *************************************************************************/
    6278           0 : void bsetv(ae_int_t n,
    6279             :      ae_bool v,
    6280             :      /* Boolean */ ae_vector* x,
    6281             :      ae_state *_state)
    6282             : {
    6283             :     ae_int_t j;
    6284             : 
    6285             : 
    6286           0 :     for(j=0; j<=n-1; j++)
    6287             :     {
    6288           0 :         x->ptr.p_bool[j] = v;
    6289             :     }
    6290           0 : }
    6291             : 
    6292             : 
    6293             : /*************************************************************************
    6294             : Sets matrix A[] to V
    6295             : 
    6296             : INPUT PARAMETERS:
    6297             :     M, N    -   rows/cols count
    6298             :     V       -   value to set
    6299             :     A       -   array[M,N]
    6300             : 
    6301             : OUTPUT PARAMETERS:
    6302             :     A       -   leading M rows, N cols are replaced by V
    6303             : 
    6304             :   -- ALGLIB --
    6305             :      Copyright 20.01.2020 by Bochkanov Sergey
    6306             : *************************************************************************/
    6307           0 : void rsetm(ae_int_t m,
    6308             :      ae_int_t n,
    6309             :      double v,
    6310             :      /* Real    */ ae_matrix* a,
    6311             :      ae_state *_state)
    6312             : {
    6313             :     ae_int_t i;
    6314             :     ae_int_t j;
    6315             : 
    6316             : 
    6317           0 :     for(i=0; i<=m-1; i++)
    6318             :     {
    6319           0 :         for(j=0; j<=n-1; j++)
    6320             :         {
    6321           0 :             a->ptr.pp_double[i][j] = v;
    6322             :         }
    6323             :     }
    6324           0 : }
    6325             : 
    6326             : 
    6327             : /*************************************************************************
    6328             : Sets vector X[] to V, reallocating X[] if too small
    6329             : 
    6330             : INPUT PARAMETERS:
    6331             :     N       -   vector length
    6332             :     V       -   value to set
    6333             :     X       -   possibly preallocated array
    6334             : 
    6335             : OUTPUT PARAMETERS:
    6336             :     X       -   leading N elements are replaced by V; array is reallocated
    6337             :                 if its length is less than N.
    6338             : 
    6339             :   -- ALGLIB --
    6340             :      Copyright 20.01.2020 by Bochkanov Sergey
    6341             : *************************************************************************/
    6342           0 : void rsetallocv(ae_int_t n,
    6343             :      double v,
    6344             :      /* Real    */ ae_vector* x,
    6345             :      ae_state *_state)
    6346             : {
    6347             : 
    6348             : 
    6349           0 :     if( x->cnt<n )
    6350             :     {
    6351           0 :         ae_vector_set_length(x, n, _state);
    6352             :     }
    6353           0 :     rsetv(n, v, x, _state);
    6354           0 : }
    6355             : 
    6356             : 
    6357             : /*************************************************************************
    6358             : Sets vector A[] to V, reallocating A[] if too small.
    6359             : 
    6360             : INPUT PARAMETERS:
    6361             :     M       -   rows count
    6362             :     N       -   cols count
    6363             :     V       -   value to set
    6364             :     A       -   possibly preallocated matrix
    6365             : 
    6366             : OUTPUT PARAMETERS:
    6367             :     A       -   leading M rows, N cols are replaced by V; the matrix is
    6368             :                 reallocated if its rows/cols count is less than M/N.
    6369             : 
    6370             :   -- ALGLIB --
    6371             :      Copyright 20.01.2020 by Bochkanov Sergey
    6372             : *************************************************************************/
    6373           0 : void rsetallocm(ae_int_t m,
    6374             :      ae_int_t n,
    6375             :      double v,
    6376             :      /* Real    */ ae_matrix* a,
    6377             :      ae_state *_state)
    6378             : {
    6379             : 
    6380             : 
    6381           0 :     if( a->rows<m||a->cols<n )
    6382             :     {
    6383           0 :         ae_matrix_set_length(a, m, n, _state);
    6384             :     }
    6385           0 :     rsetm(m, n, v, a, _state);
    6386           0 : }
    6387             : 
    6388             : 
    6389             : /*************************************************************************
    6390             : Reallocates X[] if its length is less than required value. Does not change
    6391             : its length and contents if it is large enough.
    6392             : 
    6393             : INPUT PARAMETERS:
    6394             :     N       -   desired vector length
    6395             :     X       -   possibly preallocated array
    6396             : 
    6397             : OUTPUT PARAMETERS:
    6398             :     X       -   length(X)>=N
    6399             : 
    6400             :   -- ALGLIB --
    6401             :      Copyright 20.01.2020 by Bochkanov Sergey
    6402             : *************************************************************************/
    6403           0 : void rallocv(ae_int_t n, /* Real    */ ae_vector* x, ae_state *_state)
    6404             : {
    6405             : 
    6406             : 
    6407           0 :     if( x->cnt<n )
    6408             :     {
    6409           0 :         ae_vector_set_length(x, n, _state);
    6410             :     }
    6411           0 : }
    6412             : 
    6413             : 
    6414             : /*************************************************************************
    6415             : Reallocates X[] if its length is less than required value. Does not change
    6416             : its length and contents if it is large enough.
    6417             : 
    6418             : INPUT PARAMETERS:
    6419             :     N       -   desired vector length
    6420             :     X       -   possibly preallocated array
    6421             : 
    6422             : OUTPUT PARAMETERS:
    6423             :     X       -   length(X)>=N
    6424             : 
    6425             :   -- ALGLIB --
    6426             :      Copyright 20.01.2020 by Bochkanov Sergey
    6427             : *************************************************************************/
    6428           0 : void ballocv(ae_int_t n, /* Boolean */ ae_vector* x, ae_state *_state)
    6429             : {
    6430             : 
    6431             : 
    6432           0 :     if( x->cnt<n )
    6433             :     {
    6434           0 :         ae_vector_set_length(x, n, _state);
    6435             :     }
    6436           0 : }
    6437             : 
    6438             : 
    6439             : /*************************************************************************
    6440             : Reallocates matrix if its rows or cols count is less than  required.  Does
    6441             : not change its size if it is exactly that size or larger.
    6442             : 
    6443             : INPUT PARAMETERS:
    6444             :     M       -   rows count
    6445             :     N       -   cols count
    6446             :     A       -   possibly preallocated matrix
    6447             : 
    6448             : OUTPUT PARAMETERS:
    6449             :     A       -   size is at least M*N
    6450             : 
    6451             :   -- ALGLIB --
    6452             :      Copyright 20.01.2020 by Bochkanov Sergey
    6453             : *************************************************************************/
    6454           0 : void rallocm(ae_int_t m,
    6455             :      ae_int_t n,
    6456             :      /* Real    */ ae_matrix* a,
    6457             :      ae_state *_state)
    6458             : {
    6459             : 
    6460             : 
    6461           0 :     if( a->rows<m||a->cols<n )
    6462             :     {
    6463           0 :         ae_matrix_set_length(a, m, n, _state);
    6464             :     }
    6465           0 : }
    6466             : 
    6467             : 
    6468             : /*************************************************************************
    6469             : Sets vector X[] to V, reallocating X[] if too small
    6470             : 
    6471             : INPUT PARAMETERS:
    6472             :     N       -   vector length
    6473             :     V       -   value to set
    6474             :     X       -   possibly preallocated array
    6475             : 
    6476             : OUTPUT PARAMETERS:
    6477             :     X       -   leading N elements are replaced by V; array is reallocated
    6478             :                 if its length is less than N.
    6479             : 
    6480             :   -- ALGLIB --
    6481             :      Copyright 20.01.2020 by Bochkanov Sergey
    6482             : *************************************************************************/
    6483           0 : void isetallocv(ae_int_t n,
    6484             :      ae_int_t v,
    6485             :      /* Integer */ ae_vector* x,
    6486             :      ae_state *_state)
    6487             : {
    6488             : 
    6489             : 
    6490           0 :     if( x->cnt<n )
    6491             :     {
    6492           0 :         ae_vector_set_length(x, n, _state);
    6493             :     }
    6494           0 :     isetv(n, v, x, _state);
    6495           0 : }
    6496             : 
    6497             : 
    6498             : /*************************************************************************
    6499             : Sets vector X[] to V, reallocating X[] if too small
    6500             : 
    6501             : INPUT PARAMETERS:
    6502             :     N       -   vector length
    6503             :     V       -   value to set
    6504             :     X       -   possibly preallocated array
    6505             : 
    6506             : OUTPUT PARAMETERS:
    6507             :     X       -   leading N elements are replaced by V; array is reallocated
    6508             :                 if its length is less than N.
    6509             : 
    6510             :   -- ALGLIB --
    6511             :      Copyright 20.01.2020 by Bochkanov Sergey
    6512             : *************************************************************************/
    6513           0 : void bsetallocv(ae_int_t n,
    6514             :      ae_bool v,
    6515             :      /* Boolean */ ae_vector* x,
    6516             :      ae_state *_state)
    6517             : {
    6518             : 
    6519             : 
    6520           0 :     if( x->cnt<n )
    6521             :     {
    6522           0 :         ae_vector_set_length(x, n, _state);
    6523             :     }
    6524           0 :     bsetv(n, v, x, _state);
    6525           0 : }
    6526             : 
    6527             : 
    6528             : /*************************************************************************
    6529             : Sets row I of A[,] to V
    6530             : 
    6531             : INPUT PARAMETERS:
    6532             :     N       -   vector length
    6533             :     V       -   value to set
    6534             :     A       -   array[N,N] or larger
    6535             :     I       -   row index
    6536             : 
    6537             : OUTPUT PARAMETERS:
    6538             :     A       -   leading N elements of I-th row are replaced by V
    6539             : 
    6540             :   -- ALGLIB --
    6541             :      Copyright 20.01.2020 by Bochkanov Sergey
    6542             : *************************************************************************/
    6543           0 : void rsetr(ae_int_t n,
    6544             :      double v,
    6545             :      /* Real    */ ae_matrix* a,
    6546             :      ae_int_t i,
    6547             :      ae_state *_state)
    6548             : {
    6549             :     ae_int_t j;
    6550             : 
    6551             : 
    6552           0 :     for(j=0; j<=n-1; j++)
    6553             :     {
    6554           0 :         a->ptr.pp_double[i][j] = v;
    6555             :     }
    6556           0 : }
    6557             : 
    6558             : 
    6559             : /*************************************************************************
    6560             : Sets col J of A[,] to V
    6561             : 
    6562             : INPUT PARAMETERS:
    6563             :     N       -   vector length
    6564             :     V       -   value to set
    6565             :     A       -   array[N,N] or larger
    6566             :     J       -   col index
    6567             : 
    6568             : OUTPUT PARAMETERS:
    6569             :     A       -   leading N elements of I-th col are replaced by V
    6570             : 
    6571             :   -- ALGLIB --
    6572             :      Copyright 20.01.2020 by Bochkanov Sergey
    6573             : *************************************************************************/
    6574           0 : void rsetc(ae_int_t n,
    6575             :      double v,
    6576             :      /* Real    */ ae_matrix* a,
    6577             :      ae_int_t j,
    6578             :      ae_state *_state)
    6579             : {
    6580             :     ae_int_t i;
    6581             : 
    6582             : 
    6583           0 :     for(i=0; i<=n-1; i++)
    6584             :     {
    6585           0 :         a->ptr.pp_double[i][j] = v;
    6586             :     }
    6587           0 : }
    6588             : 
    6589             : 
    6590             : /*************************************************************************
    6591             : Copies vector X[] to Y[]
    6592             : 
    6593             : INPUT PARAMETERS:
    6594             :     N       -   vector length
    6595             :     X       -   array[N], source
    6596             :     Y       -   preallocated array[N]
    6597             : 
    6598             : OUTPUT PARAMETERS:
    6599             :     Y       -   leading N elements are replaced by X
    6600             : 
    6601             :     
    6602             : NOTE: destination and source should NOT overlap
    6603             : 
    6604             :   -- ALGLIB --
    6605             :      Copyright 20.01.2020 by Bochkanov Sergey
    6606             : *************************************************************************/
    6607           0 : void rcopyv(ae_int_t n,
    6608             :      /* Real    */ ae_vector* x,
    6609             :      /* Real    */ ae_vector* y,
    6610             :      ae_state *_state)
    6611             : {
    6612             :     ae_int_t j;
    6613             : 
    6614             : 
    6615           0 :     for(j=0; j<=n-1; j++)
    6616             :     {
    6617           0 :         y->ptr.p_double[j] = x->ptr.p_double[j];
    6618             :     }
    6619           0 : }
    6620             : 
    6621             : 
    6622             : /*************************************************************************
    6623             : Copies vector X[] to Y[]
    6624             : 
    6625             : INPUT PARAMETERS:
    6626             :     N       -   vector length
    6627             :     X       -   array[N], source
    6628             :     Y       -   preallocated array[N]
    6629             : 
    6630             : OUTPUT PARAMETERS:
    6631             :     Y       -   leading N elements are replaced by X
    6632             : 
    6633             :     
    6634             : NOTE: destination and source should NOT overlap
    6635             : 
    6636             :   -- ALGLIB --
    6637             :      Copyright 20.01.2020 by Bochkanov Sergey
    6638             : *************************************************************************/
    6639           0 : void bcopyv(ae_int_t n,
    6640             :      /* Boolean */ ae_vector* x,
    6641             :      /* Boolean */ ae_vector* y,
    6642             :      ae_state *_state)
    6643             : {
    6644             :     ae_int_t j;
    6645             : 
    6646             : 
    6647           0 :     for(j=0; j<=n-1; j++)
    6648             :     {
    6649           0 :         y->ptr.p_bool[j] = x->ptr.p_bool[j];
    6650             :     }
    6651           0 : }
    6652             : 
    6653             : 
    6654             : /*************************************************************************
    6655             : Copies vector X[] to Y[], extended version
    6656             : 
    6657             : INPUT PARAMETERS:
    6658             :     N       -   vector length
    6659             :     X       -   source array
    6660             :     OffsX   -   source offset
    6661             :     Y       -   preallocated array[N]
    6662             :     OffsY   -   destination offset
    6663             : 
    6664             : OUTPUT PARAMETERS:
    6665             :     Y       -   N elements starting from OffsY are replaced by X[OffsX:OffsX+N-1]
    6666             :     
    6667             : NOTE: destination and source should NOT overlap
    6668             : 
    6669             :   -- ALGLIB --
    6670             :      Copyright 20.01.2020 by Bochkanov Sergey
    6671             : *************************************************************************/
    6672           0 : void rcopyvx(ae_int_t n,
    6673             :      /* Real    */ ae_vector* x,
    6674             :      ae_int_t offsx,
    6675             :      /* Real    */ ae_vector* y,
    6676             :      ae_int_t offsy,
    6677             :      ae_state *_state)
    6678             : {
    6679             :     ae_int_t j;
    6680             : 
    6681             : 
    6682           0 :     for(j=0; j<=n-1; j++)
    6683             :     {
    6684           0 :         y->ptr.p_double[offsy+j] = x->ptr.p_double[offsx+j];
    6685             :     }
    6686           0 : }
    6687             : 
    6688             : 
    6689             : /*************************************************************************
    6690             : Copies vector X[] to Y[], resizing Y[] if needed.
    6691             : 
    6692             : INPUT PARAMETERS:
    6693             :     N       -   vector length
    6694             :     X       -   array[N], source
    6695             :     Y       -   possibly preallocated array[N] (resized if needed)
    6696             : 
    6697             : OUTPUT PARAMETERS:
    6698             :     Y       -   leading N elements are replaced by X
    6699             : 
    6700             :   -- ALGLIB --
    6701             :      Copyright 20.01.2020 by Bochkanov Sergey
    6702             : *************************************************************************/
    6703           0 : void rcopyallocv(ae_int_t n,
    6704             :      /* Real    */ ae_vector* x,
    6705             :      /* Real    */ ae_vector* y,
    6706             :      ae_state *_state)
    6707             : {
    6708             :     ae_int_t j;
    6709             : 
    6710             : 
    6711           0 :     if( y->cnt<n )
    6712             :     {
    6713           0 :         ae_vector_set_length(y, n, _state);
    6714             :     }
    6715           0 :     for(j=0; j<=n-1; j++)
    6716             :     {
    6717           0 :         y->ptr.p_double[j] = x->ptr.p_double[j];
    6718             :     }
    6719           0 : }
    6720             : 
    6721             : 
    6722             : /*************************************************************************
    6723             : Copies matrix X[] to Y[], resizing Y[] if needed. On resize, dimensions of
    6724             : Y[] are increased - but not decreased.
    6725             : 
    6726             : INPUT PARAMETERS:
    6727             :     M       -   rows count
    6728             :     N       -   cols count
    6729             :     X       -   array[M,N], source
    6730             :     Y       -   possibly preallocated array[M,N] (resized if needed)
    6731             : 
    6732             : OUTPUT PARAMETERS:
    6733             :     Y       -   leading [M,N] elements are replaced by X
    6734             : 
    6735             :   -- ALGLIB --
    6736             :      Copyright 20.01.2020 by Bochkanov Sergey
    6737             : *************************************************************************/
    6738           0 : void rcopyallocm(ae_int_t m,
    6739             :      ae_int_t n,
    6740             :      /* Real    */ ae_matrix* x,
    6741             :      /* Real    */ ae_matrix* y,
    6742             :      ae_state *_state)
    6743             : {
    6744             :     ae_int_t i;
    6745             :     ae_int_t j;
    6746             : 
    6747             : 
    6748           0 :     if( m==0||n==0 )
    6749             :     {
    6750           0 :         return;
    6751             :     }
    6752           0 :     if( y->rows<m||y->cols<n )
    6753             :     {
    6754           0 :         ae_matrix_set_length(y, ae_maxint(m, y->rows, _state), ae_maxint(n, y->cols, _state), _state);
    6755             :     }
    6756           0 :     for(i=0; i<=m-1; i++)
    6757             :     {
    6758           0 :         for(j=0; j<=n-1; j++)
    6759             :         {
    6760           0 :             y->ptr.pp_double[i][j] = x->ptr.pp_double[i][j];
    6761             :         }
    6762             :     }
    6763             : }
    6764             : 
    6765             : 
    6766             : /*************************************************************************
    6767             : Copies vector X[] to Y[], resizing Y[] if needed.
    6768             : 
    6769             : INPUT PARAMETERS:
    6770             :     N       -   vector length
    6771             :     X       -   array[N], source
    6772             :     Y       -   possibly preallocated array[N] (resized if needed)
    6773             : 
    6774             : OUTPUT PARAMETERS:
    6775             :     Y       -   leading N elements are replaced by X
    6776             : 
    6777             :   -- ALGLIB --
    6778             :      Copyright 20.01.2020 by Bochkanov Sergey
    6779             : *************************************************************************/
    6780           0 : void icopyallocv(ae_int_t n,
    6781             :      /* Integer */ ae_vector* x,
    6782             :      /* Integer */ ae_vector* y,
    6783             :      ae_state *_state)
    6784             : {
    6785             :     ae_int_t j;
    6786             : 
    6787             : 
    6788           0 :     if( y->cnt<n )
    6789             :     {
    6790           0 :         ae_vector_set_length(y, n, _state);
    6791             :     }
    6792           0 :     for(j=0; j<=n-1; j++)
    6793             :     {
    6794           0 :         y->ptr.p_int[j] = x->ptr.p_int[j];
    6795             :     }
    6796           0 : }
    6797             : 
    6798             : 
    6799             : /*************************************************************************
    6800             : Copies vector X[] to Y[], resizing Y[] if needed.
    6801             : 
    6802             : INPUT PARAMETERS:
    6803             :     N       -   vector length
    6804             :     X       -   array[N], source
    6805             :     Y       -   possibly preallocated array[N] (resized if needed)
    6806             : 
    6807             : OUTPUT PARAMETERS:
    6808             :     Y       -   leading N elements are replaced by X
    6809             : 
    6810             :   -- ALGLIB --
    6811             :      Copyright 20.01.2020 by Bochkanov Sergey
    6812             : *************************************************************************/
    6813           0 : void bcopyallocv(ae_int_t n,
    6814             :      /* Boolean */ ae_vector* x,
    6815             :      /* Boolean */ ae_vector* y,
    6816             :      ae_state *_state)
    6817             : {
    6818             :     ae_int_t j;
    6819             : 
    6820             : 
    6821           0 :     if( y->cnt<n )
    6822             :     {
    6823           0 :         ae_vector_set_length(y, n, _state);
    6824             :     }
    6825           0 :     for(j=0; j<=n-1; j++)
    6826             :     {
    6827           0 :         y->ptr.p_bool[j] = x->ptr.p_bool[j];
    6828             :     }
    6829           0 : }
    6830             : 
    6831             : 
    6832             : /*************************************************************************
    6833             : Copies vector X[] to Y[]
    6834             : 
    6835             : INPUT PARAMETERS:
    6836             :     N       -   vector length
    6837             :     X       -   source array
    6838             :     Y       -   preallocated array[N]
    6839             : 
    6840             : OUTPUT PARAMETERS:
    6841             :     Y       -   X copied to Y
    6842             : 
    6843             :   -- ALGLIB --
    6844             :      Copyright 20.01.2020 by Bochkanov Sergey
    6845             : *************************************************************************/
    6846           0 : void icopyv(ae_int_t n,
    6847             :      /* Integer */ ae_vector* x,
    6848             :      /* Integer */ ae_vector* y,
    6849             :      ae_state *_state)
    6850             : {
    6851             :     ae_int_t j;
    6852             : 
    6853             : 
    6854           0 :     for(j=0; j<=n-1; j++)
    6855             :     {
    6856           0 :         y->ptr.p_int[j] = x->ptr.p_int[j];
    6857             :     }
    6858           0 : }
    6859             : 
    6860             : 
    6861             : /*************************************************************************
    6862             : Copies vector X[] to Y[], extended version
    6863             : 
    6864             : INPUT PARAMETERS:
    6865             :     N       -   vector length
    6866             :     X       -   source array
    6867             :     OffsX   -   source offset
    6868             :     Y       -   preallocated array[N]
    6869             :     OffsY   -   destination offset
    6870             : 
    6871             : OUTPUT PARAMETERS:
    6872             :     Y       -   N elements starting from OffsY are replaced by X[OffsX:OffsX+N-1]
    6873             :     
    6874             : NOTE: destination and source should NOT overlap
    6875             : 
    6876             :   -- ALGLIB --
    6877             :      Copyright 20.01.2020 by Bochkanov Sergey
    6878             : *************************************************************************/
    6879           0 : void icopyvx(ae_int_t n,
    6880             :      /* Integer */ ae_vector* x,
    6881             :      ae_int_t offsx,
    6882             :      /* Integer */ ae_vector* y,
    6883             :      ae_int_t offsy,
    6884             :      ae_state *_state)
    6885             : {
    6886             :     ae_int_t j;
    6887             : 
    6888             : 
    6889           0 :     for(j=0; j<=n-1; j++)
    6890             :     {
    6891           0 :         y->ptr.p_int[offsy+j] = x->ptr.p_int[offsx+j];
    6892             :     }
    6893           0 : }
    6894             : 
    6895             : 
    6896             : /*************************************************************************
    6897             : Grows X, i.e. changes its size in such a way that:
    6898             : a) contents is preserved
    6899             : b) new size is at least N
    6900             : c) actual size can be larger than N, so subsequent grow() calls can return
    6901             :    without reallocation
    6902             : 
    6903             :   -- ALGLIB --
    6904             :      Copyright 20.03.2009 by Bochkanov Sergey
    6905             : *************************************************************************/
    6906           0 : void igrowv(ae_int_t newn, /* Integer */ ae_vector* x, ae_state *_state)
    6907             : {
    6908             :     ae_frame _frame_block;
    6909             :     ae_vector oldx;
    6910             :     ae_int_t oldn;
    6911             : 
    6912           0 :     ae_frame_make(_state, &_frame_block);
    6913           0 :     memset(&oldx, 0, sizeof(oldx));
    6914           0 :     ae_vector_init(&oldx, 0, DT_INT, _state, ae_true);
    6915             : 
    6916           0 :     if( x->cnt>=newn )
    6917             :     {
    6918           0 :         ae_frame_leave(_state);
    6919           0 :         return;
    6920             :     }
    6921           0 :     oldn = x->cnt;
    6922           0 :     newn = ae_maxint(newn, ae_round(1.8*oldn+1, _state), _state);
    6923           0 :     ae_swap_vectors(x, &oldx);
    6924           0 :     ae_vector_set_length(x, newn, _state);
    6925           0 :     icopyv(oldn, &oldx, x, _state);
    6926           0 :     ae_frame_leave(_state);
    6927             : }
    6928             : 
    6929             : 
    6930             : /*************************************************************************
    6931             : Performs copying with multiplication of V*X[] to Y[]
    6932             : 
    6933             : INPUT PARAMETERS:
    6934             :     N       -   vector length
    6935             :     V       -   multiplier
    6936             :     X       -   array[N], source
    6937             :     Y       -   preallocated array[N]
    6938             : 
    6939             : OUTPUT PARAMETERS:
    6940             :     Y       -   array[N], Y = V*X
    6941             : 
    6942             :   -- ALGLIB --
    6943             :      Copyright 20.01.2020 by Bochkanov Sergey
    6944             : *************************************************************************/
    6945           0 : void rcopymulv(ae_int_t n,
    6946             :      double v,
    6947             :      /* Real    */ ae_vector* x,
    6948             :      /* Real    */ ae_vector* y,
    6949             :      ae_state *_state)
    6950             : {
    6951             :     ae_int_t i;
    6952             : 
    6953             : 
    6954           0 :     for(i=0; i<=n-1; i++)
    6955             :     {
    6956           0 :         y->ptr.p_double[i] = v*x->ptr.p_double[i];
    6957             :     }
    6958           0 : }
    6959             : 
    6960             : 
    6961             : /*************************************************************************
    6962             : Performs copying with multiplication of V*X[] to Y[I,*]
    6963             : 
    6964             : INPUT PARAMETERS:
    6965             :     N       -   vector length
    6966             :     V       -   multiplier
    6967             :     X       -   array[N], source
    6968             :     Y       -   preallocated array[?,N]
    6969             :     RIdx    -   destination row index
    6970             : 
    6971             : OUTPUT PARAMETERS:
    6972             :     Y       -   Y[RIdx,...] = V*X
    6973             : 
    6974             :   -- ALGLIB --
    6975             :      Copyright 20.01.2020 by Bochkanov Sergey
    6976             : *************************************************************************/
    6977           0 : void rcopymulvr(ae_int_t n,
    6978             :      double v,
    6979             :      /* Real    */ ae_vector* x,
    6980             :      /* Real    */ ae_matrix* y,
    6981             :      ae_int_t ridx,
    6982             :      ae_state *_state)
    6983             : {
    6984             :     ae_int_t i;
    6985             : 
    6986             : 
    6987           0 :     for(i=0; i<=n-1; i++)
    6988             :     {
    6989           0 :         y->ptr.pp_double[ridx][i] = v*x->ptr.p_double[i];
    6990             :     }
    6991           0 : }
    6992             : 
    6993             : 
    6994             : /*************************************************************************
    6995             : Copies vector X[] to row I of A[,]
    6996             : 
    6997             : INPUT PARAMETERS:
    6998             :     N       -   vector length
    6999             :     X       -   array[N], source
    7000             :     A       -   preallocated 2D array large enough to store result
    7001             :     I       -   destination row index
    7002             : 
    7003             : OUTPUT PARAMETERS:
    7004             :     A       -   leading N elements of I-th row are replaced by X
    7005             : 
    7006             :   -- ALGLIB --
    7007             :      Copyright 20.01.2020 by Bochkanov Sergey
    7008             : *************************************************************************/
    7009           0 : void rcopyvr(ae_int_t n,
    7010             :      /* Real    */ ae_vector* x,
    7011             :      /* Real    */ ae_matrix* a,
    7012             :      ae_int_t i,
    7013             :      ae_state *_state)
    7014             : {
    7015             :     ae_int_t j;
    7016             : 
    7017             : 
    7018           0 :     for(j=0; j<=n-1; j++)
    7019             :     {
    7020           0 :         a->ptr.pp_double[i][j] = x->ptr.p_double[j];
    7021             :     }
    7022           0 : }
    7023             : 
    7024             : 
    7025             : /*************************************************************************
    7026             : Copies row I of A[,] to vector X[]
    7027             : 
    7028             : INPUT PARAMETERS:
    7029             :     N       -   vector length
    7030             :     A       -   2D array, source
    7031             :     I       -   source row index
    7032             :     X       -   preallocated destination
    7033             : 
    7034             : OUTPUT PARAMETERS:
    7035             :     X       -   array[N], destination
    7036             : 
    7037             :   -- ALGLIB --
    7038             :      Copyright 20.01.2020 by Bochkanov Sergey
    7039             : *************************************************************************/
    7040           0 : void rcopyrv(ae_int_t n,
    7041             :      /* Real    */ ae_matrix* a,
    7042             :      ae_int_t i,
    7043             :      /* Real    */ ae_vector* x,
    7044             :      ae_state *_state)
    7045             : {
    7046             :     ae_int_t j;
    7047             : 
    7048             : 
    7049           0 :     for(j=0; j<=n-1; j++)
    7050             :     {
    7051           0 :         x->ptr.p_double[j] = a->ptr.pp_double[i][j];
    7052             :     }
    7053           0 : }
    7054             : 
    7055             : 
    7056             : /*************************************************************************
    7057             : Copies row I of A[,] to row K of B[,].
    7058             : 
    7059             : A[i,...] and B[k,...] may overlap.
    7060             : 
    7061             : INPUT PARAMETERS:
    7062             :     N       -   vector length
    7063             :     A       -   2D array, source
    7064             :     I       -   source row index
    7065             :     B       -   preallocated destination
    7066             :     K       -   destination row index
    7067             : 
    7068             : OUTPUT PARAMETERS:
    7069             :     B       -   row K overwritten
    7070             : 
    7071             :   -- ALGLIB --
    7072             :      Copyright 20.01.2020 by Bochkanov Sergey
    7073             : *************************************************************************/
    7074           0 : void rcopyrr(ae_int_t n,
    7075             :      /* Real    */ ae_matrix* a,
    7076             :      ae_int_t i,
    7077             :      /* Real    */ ae_matrix* b,
    7078             :      ae_int_t k,
    7079             :      ae_state *_state)
    7080             : {
    7081             :     ae_int_t j;
    7082             : 
    7083             : 
    7084           0 :     for(j=0; j<=n-1; j++)
    7085             :     {
    7086           0 :         b->ptr.pp_double[k][j] = a->ptr.pp_double[i][j];
    7087             :     }
    7088           0 : }
    7089             : 
    7090             : 
    7091             : /*************************************************************************
    7092             : Copies vector X[] to column J of A[,]
    7093             : 
    7094             : INPUT PARAMETERS:
    7095             :     N       -   vector length
    7096             :     X       -   array[N], source
    7097             :     A       -   preallocated 2D array large enough to store result
    7098             :     J       -   destination col index
    7099             : 
    7100             : OUTPUT PARAMETERS:
    7101             :     A       -   leading N elements of J-th column are replaced by X
    7102             : 
    7103             :   -- ALGLIB --
    7104             :      Copyright 20.01.2020 by Bochkanov Sergey
    7105             : *************************************************************************/
    7106           0 : void rcopyvc(ae_int_t n,
    7107             :      /* Real    */ ae_vector* x,
    7108             :      /* Real    */ ae_matrix* a,
    7109             :      ae_int_t j,
    7110             :      ae_state *_state)
    7111             : {
    7112             :     ae_int_t i;
    7113             : 
    7114             : 
    7115           0 :     for(i=0; i<=n-1; i++)
    7116             :     {
    7117           0 :         a->ptr.pp_double[i][j] = x->ptr.p_double[i];
    7118             :     }
    7119           0 : }
    7120             : 
    7121             : 
    7122             : /*************************************************************************
    7123             : Copies column J of A[,] to vector X[]
    7124             : 
    7125             : INPUT PARAMETERS:
    7126             :     N       -   vector length
    7127             :     A       -   source 2D array
    7128             :     J       -   source col index
    7129             : 
    7130             : OUTPUT PARAMETERS:
    7131             :     X       -   preallocated array[N], destination
    7132             : 
    7133             :   -- ALGLIB --
    7134             :      Copyright 20.01.2020 by Bochkanov Sergey
    7135             : *************************************************************************/
    7136           0 : void rcopycv(ae_int_t n,
    7137             :      /* Real    */ ae_matrix* a,
    7138             :      ae_int_t j,
    7139             :      /* Real    */ ae_vector* x,
    7140             :      ae_state *_state)
    7141             : {
    7142             :     ae_int_t i;
    7143             : 
    7144             : 
    7145           0 :     for(i=0; i<=n-1; i++)
    7146             :     {
    7147           0 :         x->ptr.p_double[i] = a->ptr.pp_double[i][j];
    7148             :     }
    7149           0 : }
    7150             : 
    7151             : 
    7152             : /*************************************************************************
    7153             : Fast kernel
    7154             : 
    7155             :   -- ALGLIB routine --
    7156             :      19.01.2010
    7157             :      Bochkanov Sergey
    7158             : *************************************************************************/
    7159           0 : ae_bool rmatrixgerf(ae_int_t m,
    7160             :      ae_int_t n,
    7161             :      /* Real    */ ae_matrix* a,
    7162             :      ae_int_t ia,
    7163             :      ae_int_t ja,
    7164             :      double ralpha,
    7165             :      /* Real    */ ae_vector* u,
    7166             :      ae_int_t iu,
    7167             :      /* Real    */ ae_vector* v,
    7168             :      ae_int_t iv,
    7169             :      ae_state *_state)
    7170             : {
    7171             : #ifndef ALGLIB_INTERCEPTS_ABLAS
    7172             :     ae_bool result;
    7173             : 
    7174             : 
    7175             :     result = ae_false;
    7176             :     return result;
    7177             : #else
    7178           0 :     return _ialglib_i_rmatrixgerf(m, n, a, ia, ja, ralpha, u, iu, v, iv);
    7179             : #endif
    7180             : }
    7181             : 
    7182             : 
    7183             : /*************************************************************************
    7184             : Fast kernel
    7185             : 
    7186             :   -- ALGLIB routine --
    7187             :      19.01.2010
    7188             :      Bochkanov Sergey
    7189             : *************************************************************************/
    7190           0 : ae_bool cmatrixrank1f(ae_int_t m,
    7191             :      ae_int_t n,
    7192             :      /* Complex */ ae_matrix* a,
    7193             :      ae_int_t ia,
    7194             :      ae_int_t ja,
    7195             :      /* Complex */ ae_vector* u,
    7196             :      ae_int_t iu,
    7197             :      /* Complex */ ae_vector* v,
    7198             :      ae_int_t iv,
    7199             :      ae_state *_state)
    7200             : {
    7201             : #ifndef ALGLIB_INTERCEPTS_ABLAS
    7202             :     ae_bool result;
    7203             : 
    7204             : 
    7205             :     result = ae_false;
    7206             :     return result;
    7207             : #else
    7208           0 :     return _ialglib_i_cmatrixrank1f(m, n, a, ia, ja, u, iu, v, iv);
    7209             : #endif
    7210             : }
    7211             : 
    7212             : 
    7213             : /*************************************************************************
    7214             : Fast kernel
    7215             : 
    7216             :   -- ALGLIB routine --
    7217             :      19.01.2010
    7218             :      Bochkanov Sergey
    7219             : *************************************************************************/
    7220           0 : ae_bool rmatrixrank1f(ae_int_t m,
    7221             :      ae_int_t n,
    7222             :      /* Real    */ ae_matrix* a,
    7223             :      ae_int_t ia,
    7224             :      ae_int_t ja,
    7225             :      /* Real    */ ae_vector* u,
    7226             :      ae_int_t iu,
    7227             :      /* Real    */ ae_vector* v,
    7228             :      ae_int_t iv,
    7229             :      ae_state *_state)
    7230             : {
    7231             : #ifndef ALGLIB_INTERCEPTS_ABLAS
    7232             :     ae_bool result;
    7233             : 
    7234             : 
    7235             :     result = ae_false;
    7236             :     return result;
    7237             : #else
    7238           0 :     return _ialglib_i_rmatrixrank1f(m, n, a, ia, ja, u, iu, v, iv);
    7239             : #endif
    7240             : }
    7241             : 
    7242             : 
    7243             : /*************************************************************************
    7244             : Fast kernel
    7245             : 
    7246             :   -- ALGLIB routine --
    7247             :      19.01.2010
    7248             :      Bochkanov Sergey
    7249             : *************************************************************************/
    7250           0 : ae_bool cmatrixrighttrsmf(ae_int_t m,
    7251             :      ae_int_t n,
    7252             :      /* Complex */ ae_matrix* a,
    7253             :      ae_int_t i1,
    7254             :      ae_int_t j1,
    7255             :      ae_bool isupper,
    7256             :      ae_bool isunit,
    7257             :      ae_int_t optype,
    7258             :      /* Complex */ ae_matrix* x,
    7259             :      ae_int_t i2,
    7260             :      ae_int_t j2,
    7261             :      ae_state *_state)
    7262             : {
    7263             : #ifndef ALGLIB_INTERCEPTS_ABLAS
    7264             :     ae_bool result;
    7265             : 
    7266             : 
    7267             :     result = ae_false;
    7268             :     return result;
    7269             : #else
    7270           0 :     return _ialglib_i_cmatrixrighttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2);
    7271             : #endif
    7272             : }
    7273             : 
    7274             : 
    7275             : /*************************************************************************
    7276             : Fast kernel
    7277             : 
    7278             :   -- ALGLIB routine --
    7279             :      19.01.2010
    7280             :      Bochkanov Sergey
    7281             : *************************************************************************/
    7282           0 : ae_bool cmatrixlefttrsmf(ae_int_t m,
    7283             :      ae_int_t n,
    7284             :      /* Complex */ ae_matrix* a,
    7285             :      ae_int_t i1,
    7286             :      ae_int_t j1,
    7287             :      ae_bool isupper,
    7288             :      ae_bool isunit,
    7289             :      ae_int_t optype,
    7290             :      /* Complex */ ae_matrix* x,
    7291             :      ae_int_t i2,
    7292             :      ae_int_t j2,
    7293             :      ae_state *_state)
    7294             : {
    7295             : #ifndef ALGLIB_INTERCEPTS_ABLAS
    7296             :     ae_bool result;
    7297             : 
    7298             : 
    7299             :     result = ae_false;
    7300             :     return result;
    7301             : #else
    7302           0 :     return _ialglib_i_cmatrixlefttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2);
    7303             : #endif
    7304             : }
    7305             : 
    7306             : 
    7307             : /*************************************************************************
    7308             : Fast kernel
    7309             : 
    7310             :   -- ALGLIB routine --
    7311             :      19.01.2010
    7312             :      Bochkanov Sergey
    7313             : *************************************************************************/
    7314           0 : ae_bool rmatrixrighttrsmf(ae_int_t m,
    7315             :      ae_int_t n,
    7316             :      /* Real    */ ae_matrix* a,
    7317             :      ae_int_t i1,
    7318             :      ae_int_t j1,
    7319             :      ae_bool isupper,
    7320             :      ae_bool isunit,
    7321             :      ae_int_t optype,
    7322             :      /* Real    */ ae_matrix* x,
    7323             :      ae_int_t i2,
    7324             :      ae_int_t j2,
    7325             :      ae_state *_state)
    7326             : {
    7327             : #ifndef ALGLIB_INTERCEPTS_ABLAS
    7328             :     ae_bool result;
    7329             : 
    7330             : 
    7331             :     result = ae_false;
    7332             :     return result;
    7333             : #else
    7334           0 :     return _ialglib_i_rmatrixrighttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2);
    7335             : #endif
    7336             : }
    7337             : 
    7338             : 
    7339             : /*************************************************************************
    7340             : Fast kernel
    7341             : 
    7342             :   -- ALGLIB routine --
    7343             :      19.01.2010
    7344             :      Bochkanov Sergey
    7345             : *************************************************************************/
    7346           0 : ae_bool rmatrixlefttrsmf(ae_int_t m,
    7347             :      ae_int_t n,
    7348             :      /* Real    */ ae_matrix* a,
    7349             :      ae_int_t i1,
    7350             :      ae_int_t j1,
    7351             :      ae_bool isupper,
    7352             :      ae_bool isunit,
    7353             :      ae_int_t optype,
    7354             :      /* Real    */ ae_matrix* x,
    7355             :      ae_int_t i2,
    7356             :      ae_int_t j2,
    7357             :      ae_state *_state)
    7358             : {
    7359             : #ifndef ALGLIB_INTERCEPTS_ABLAS
    7360             :     ae_bool result;
    7361             : 
    7362             : 
    7363             :     result = ae_false;
    7364             :     return result;
    7365             : #else
    7366           0 :     return _ialglib_i_rmatrixlefttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2);
    7367             : #endif
    7368             : }
    7369             : 
    7370             : 
    7371             : /*************************************************************************
    7372             : Fast kernel
    7373             : 
    7374             :   -- ALGLIB routine --
    7375             :      19.01.2010
    7376             :      Bochkanov Sergey
    7377             : *************************************************************************/
    7378           0 : ae_bool cmatrixherkf(ae_int_t n,
    7379             :      ae_int_t k,
    7380             :      double alpha,
    7381             :      /* Complex */ ae_matrix* a,
    7382             :      ae_int_t ia,
    7383             :      ae_int_t ja,
    7384             :      ae_int_t optypea,
    7385             :      double beta,
    7386             :      /* Complex */ ae_matrix* c,
    7387             :      ae_int_t ic,
    7388             :      ae_int_t jc,
    7389             :      ae_bool isupper,
    7390             :      ae_state *_state)
    7391             : {
    7392             : #ifndef ALGLIB_INTERCEPTS_ABLAS
    7393             :     ae_bool result;
    7394             : 
    7395             : 
    7396             :     result = ae_false;
    7397             :     return result;
    7398             : #else
    7399           0 :     return _ialglib_i_cmatrixherkf(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper);
    7400             : #endif
    7401             : }
    7402             : 
    7403             : 
    7404             : /*************************************************************************
    7405             : Fast kernel
    7406             : 
    7407             :   -- ALGLIB routine --
    7408             :      19.01.2010
    7409             :      Bochkanov Sergey
    7410             : *************************************************************************/
    7411           0 : ae_bool rmatrixsyrkf(ae_int_t n,
    7412             :      ae_int_t k,
    7413             :      double alpha,
    7414             :      /* Real    */ ae_matrix* a,
    7415             :      ae_int_t ia,
    7416             :      ae_int_t ja,
    7417             :      ae_int_t optypea,
    7418             :      double beta,
    7419             :      /* Real    */ ae_matrix* c,
    7420             :      ae_int_t ic,
    7421             :      ae_int_t jc,
    7422             :      ae_bool isupper,
    7423             :      ae_state *_state)
    7424             : {
    7425             : #ifndef ALGLIB_INTERCEPTS_ABLAS
    7426             :     ae_bool result;
    7427             : 
    7428             : 
    7429             :     result = ae_false;
    7430             :     return result;
    7431             : #else
    7432           0 :     return _ialglib_i_rmatrixsyrkf(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper);
    7433             : #endif
    7434             : }
    7435             : 
    7436             : 
    7437             : /*************************************************************************
    7438             : Fast kernel
    7439             : 
    7440             :   -- ALGLIB routine --
    7441             :      19.01.2010
    7442             :      Bochkanov Sergey
    7443             : *************************************************************************/
    7444           0 : ae_bool rmatrixgemmf(ae_int_t m,
    7445             :      ae_int_t n,
    7446             :      ae_int_t k,
    7447             :      double alpha,
    7448             :      /* Real    */ ae_matrix* a,
    7449             :      ae_int_t ia,
    7450             :      ae_int_t ja,
    7451             :      ae_int_t optypea,
    7452             :      /* Real    */ ae_matrix* b,
    7453             :      ae_int_t ib,
    7454             :      ae_int_t jb,
    7455             :      ae_int_t optypeb,
    7456             :      double beta,
    7457             :      /* Real    */ ae_matrix* c,
    7458             :      ae_int_t ic,
    7459             :      ae_int_t jc,
    7460             :      ae_state *_state)
    7461             : {
    7462             : #ifndef ALGLIB_INTERCEPTS_ABLAS
    7463             :     ae_bool result;
    7464             : 
    7465             : 
    7466             :     result = ae_false;
    7467             :     return result;
    7468             : #else
    7469           0 :     return _ialglib_i_rmatrixgemmf(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc);
    7470             : #endif
    7471             : }
    7472             : 
    7473             : 
    7474             : /*************************************************************************
    7475             : Fast kernel
    7476             : 
    7477             :   -- ALGLIB routine --
    7478             :      19.01.2010
    7479             :      Bochkanov Sergey
    7480             : *************************************************************************/
    7481           0 : ae_bool cmatrixgemmf(ae_int_t m,
    7482             :      ae_int_t n,
    7483             :      ae_int_t k,
    7484             :      ae_complex alpha,
    7485             :      /* Complex */ ae_matrix* a,
    7486             :      ae_int_t ia,
    7487             :      ae_int_t ja,
    7488             :      ae_int_t optypea,
    7489             :      /* Complex */ ae_matrix* b,
    7490             :      ae_int_t ib,
    7491             :      ae_int_t jb,
    7492             :      ae_int_t optypeb,
    7493             :      ae_complex beta,
    7494             :      /* Complex */ ae_matrix* c,
    7495             :      ae_int_t ic,
    7496             :      ae_int_t jc,
    7497             :      ae_state *_state)
    7498             : {
    7499             : #ifndef ALGLIB_INTERCEPTS_ABLAS
    7500             :     ae_bool result;
    7501             : 
    7502             : 
    7503             :     result = ae_false;
    7504             :     return result;
    7505             : #else
    7506           0 :     return _ialglib_i_cmatrixgemmf(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc);
    7507             : #endif
    7508             : }
    7509             : 
    7510             : 
    7511             : /*************************************************************************
    7512             : CMatrixGEMM kernel, basecase code for CMatrixGEMM.
    7513             : 
    7514             : This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where:
    7515             : * C is MxN general matrix
    7516             : * op1(A) is MxK matrix
    7517             : * op2(B) is KxN matrix
    7518             : * "op" may be identity transformation, transposition, conjugate transposition
    7519             : 
    7520             : Additional info:
    7521             : * multiplication result replaces C. If Beta=0, C elements are not used in
    7522             :   calculations (not multiplied by zero - just not referenced)
    7523             : * if Alpha=0, A is not used (not multiplied by zero - just not referenced)
    7524             : * if both Beta and Alpha are zero, C is filled by zeros.
    7525             : 
    7526             : IMPORTANT:
    7527             : 
    7528             : This function does NOT preallocate output matrix C, it MUST be preallocated
    7529             : by caller prior to calling this function. In case C does not have  enough
    7530             : space to store result, exception will be generated.
    7531             : 
    7532             : INPUT PARAMETERS
    7533             :     M       -   matrix size, M>0
    7534             :     N       -   matrix size, N>0
    7535             :     K       -   matrix size, K>0
    7536             :     Alpha   -   coefficient
    7537             :     A       -   matrix
    7538             :     IA      -   submatrix offset
    7539             :     JA      -   submatrix offset
    7540             :     OpTypeA -   transformation type:
    7541             :                 * 0 - no transformation
    7542             :                 * 1 - transposition
    7543             :                 * 2 - conjugate transposition
    7544             :     B       -   matrix
    7545             :     IB      -   submatrix offset
    7546             :     JB      -   submatrix offset
    7547             :     OpTypeB -   transformation type:
    7548             :                 * 0 - no transformation
    7549             :                 * 1 - transposition
    7550             :                 * 2 - conjugate transposition
    7551             :     Beta    -   coefficient
    7552             :     C       -   PREALLOCATED output matrix
    7553             :     IC      -   submatrix offset
    7554             :     JC      -   submatrix offset
    7555             : 
    7556             :   -- ALGLIB routine --
    7557             :      27.03.2013
    7558             :      Bochkanov Sergey
    7559             : *************************************************************************/
    7560           0 : void cmatrixgemmk(ae_int_t m,
    7561             :      ae_int_t n,
    7562             :      ae_int_t k,
    7563             :      ae_complex alpha,
    7564             :      /* Complex */ ae_matrix* a,
    7565             :      ae_int_t ia,
    7566             :      ae_int_t ja,
    7567             :      ae_int_t optypea,
    7568             :      /* Complex */ ae_matrix* b,
    7569             :      ae_int_t ib,
    7570             :      ae_int_t jb,
    7571             :      ae_int_t optypeb,
    7572             :      ae_complex beta,
    7573             :      /* Complex */ ae_matrix* c,
    7574             :      ae_int_t ic,
    7575             :      ae_int_t jc,
    7576             :      ae_state *_state)
    7577             : {
    7578             :     ae_int_t i;
    7579             :     ae_int_t j;
    7580             :     ae_complex v;
    7581             :     ae_complex v00;
    7582             :     ae_complex v01;
    7583             :     ae_complex v10;
    7584             :     ae_complex v11;
    7585             :     double v00x;
    7586             :     double v00y;
    7587             :     double v01x;
    7588             :     double v01y;
    7589             :     double v10x;
    7590             :     double v10y;
    7591             :     double v11x;
    7592             :     double v11y;
    7593             :     double a0x;
    7594             :     double a0y;
    7595             :     double a1x;
    7596             :     double a1y;
    7597             :     double b0x;
    7598             :     double b0y;
    7599             :     double b1x;
    7600             :     double b1y;
    7601             :     ae_int_t idxa0;
    7602             :     ae_int_t idxa1;
    7603             :     ae_int_t idxb0;
    7604             :     ae_int_t idxb1;
    7605             :     ae_int_t i0;
    7606             :     ae_int_t i1;
    7607             :     ae_int_t ik;
    7608             :     ae_int_t j0;
    7609             :     ae_int_t j1;
    7610             :     ae_int_t jk;
    7611             :     ae_int_t t;
    7612             :     ae_int_t offsa;
    7613             :     ae_int_t offsb;
    7614             : 
    7615             : 
    7616             :     
    7617             :     /*
    7618             :      * if matrix size is zero
    7619             :      */
    7620           0 :     if( m==0||n==0 )
    7621             :     {
    7622           0 :         return;
    7623             :     }
    7624             :     
    7625             :     /*
    7626             :      * Try optimized code
    7627             :      */
    7628           0 :     if( cmatrixgemmf(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state) )
    7629             :     {
    7630           0 :         return;
    7631             :     }
    7632             :     
    7633             :     /*
    7634             :      * if K=0 or Alpha=0, then C=Beta*C
    7635             :      */
    7636           0 :     if( k==0||ae_c_eq_d(alpha,(double)(0)) )
    7637             :     {
    7638           0 :         if( ae_c_neq_d(beta,(double)(1)) )
    7639             :         {
    7640           0 :             if( ae_c_neq_d(beta,(double)(0)) )
    7641             :             {
    7642           0 :                 for(i=0; i<=m-1; i++)
    7643             :                 {
    7644           0 :                     for(j=0; j<=n-1; j++)
    7645             :                     {
    7646           0 :                         c->ptr.pp_complex[ic+i][jc+j] = ae_c_mul(beta,c->ptr.pp_complex[ic+i][jc+j]);
    7647             :                     }
    7648             :                 }
    7649             :             }
    7650             :             else
    7651             :             {
    7652           0 :                 for(i=0; i<=m-1; i++)
    7653             :                 {
    7654           0 :                     for(j=0; j<=n-1; j++)
    7655             :                     {
    7656           0 :                         c->ptr.pp_complex[ic+i][jc+j] = ae_complex_from_i(0);
    7657             :                     }
    7658             :                 }
    7659             :             }
    7660             :         }
    7661           0 :         return;
    7662             :     }
    7663             :     
    7664             :     /*
    7665             :      * This phase is not really necessary, but compiler complains
    7666             :      * about "possibly uninitialized variables"
    7667             :      */
    7668           0 :     a0x = (double)(0);
    7669           0 :     a0y = (double)(0);
    7670           0 :     a1x = (double)(0);
    7671           0 :     a1y = (double)(0);
    7672           0 :     b0x = (double)(0);
    7673           0 :     b0y = (double)(0);
    7674           0 :     b1x = (double)(0);
    7675           0 :     b1y = (double)(0);
    7676             :     
    7677             :     /*
    7678             :      * General case
    7679             :      */
    7680           0 :     i = 0;
    7681           0 :     while(i<m)
    7682             :     {
    7683           0 :         j = 0;
    7684           0 :         while(j<n)
    7685             :         {
    7686             :             
    7687             :             /*
    7688             :              * Choose between specialized 4x4 code and general code
    7689             :              */
    7690           0 :             if( i+2<=m&&j+2<=n )
    7691             :             {
    7692             :                 
    7693             :                 /*
    7694             :                  * Specialized 4x4 code for [I..I+3]x[J..J+3] submatrix of C.
    7695             :                  *
    7696             :                  * This submatrix is calculated as sum of K rank-1 products,
    7697             :                  * with operands cached in local variables in order to speed
    7698             :                  * up operations with arrays.
    7699             :                  */
    7700           0 :                 v00x = 0.0;
    7701           0 :                 v00y = 0.0;
    7702           0 :                 v01x = 0.0;
    7703           0 :                 v01y = 0.0;
    7704           0 :                 v10x = 0.0;
    7705           0 :                 v10y = 0.0;
    7706           0 :                 v11x = 0.0;
    7707           0 :                 v11y = 0.0;
    7708           0 :                 if( optypea==0 )
    7709             :                 {
    7710           0 :                     idxa0 = ia+i+0;
    7711           0 :                     idxa1 = ia+i+1;
    7712           0 :                     offsa = ja;
    7713             :                 }
    7714             :                 else
    7715             :                 {
    7716           0 :                     idxa0 = ja+i+0;
    7717           0 :                     idxa1 = ja+i+1;
    7718           0 :                     offsa = ia;
    7719             :                 }
    7720           0 :                 if( optypeb==0 )
    7721             :                 {
    7722           0 :                     idxb0 = jb+j+0;
    7723           0 :                     idxb1 = jb+j+1;
    7724           0 :                     offsb = ib;
    7725             :                 }
    7726             :                 else
    7727             :                 {
    7728           0 :                     idxb0 = ib+j+0;
    7729           0 :                     idxb1 = ib+j+1;
    7730           0 :                     offsb = jb;
    7731             :                 }
    7732           0 :                 for(t=0; t<=k-1; t++)
    7733             :                 {
    7734           0 :                     if( optypea==0 )
    7735             :                     {
    7736           0 :                         a0x = a->ptr.pp_complex[idxa0][offsa].x;
    7737           0 :                         a0y = a->ptr.pp_complex[idxa0][offsa].y;
    7738           0 :                         a1x = a->ptr.pp_complex[idxa1][offsa].x;
    7739           0 :                         a1y = a->ptr.pp_complex[idxa1][offsa].y;
    7740             :                     }
    7741           0 :                     if( optypea==1 )
    7742             :                     {
    7743           0 :                         a0x = a->ptr.pp_complex[offsa][idxa0].x;
    7744           0 :                         a0y = a->ptr.pp_complex[offsa][idxa0].y;
    7745           0 :                         a1x = a->ptr.pp_complex[offsa][idxa1].x;
    7746           0 :                         a1y = a->ptr.pp_complex[offsa][idxa1].y;
    7747             :                     }
    7748           0 :                     if( optypea==2 )
    7749             :                     {
    7750           0 :                         a0x = a->ptr.pp_complex[offsa][idxa0].x;
    7751           0 :                         a0y = -a->ptr.pp_complex[offsa][idxa0].y;
    7752           0 :                         a1x = a->ptr.pp_complex[offsa][idxa1].x;
    7753           0 :                         a1y = -a->ptr.pp_complex[offsa][idxa1].y;
    7754             :                     }
    7755           0 :                     if( optypeb==0 )
    7756             :                     {
    7757           0 :                         b0x = b->ptr.pp_complex[offsb][idxb0].x;
    7758           0 :                         b0y = b->ptr.pp_complex[offsb][idxb0].y;
    7759           0 :                         b1x = b->ptr.pp_complex[offsb][idxb1].x;
    7760           0 :                         b1y = b->ptr.pp_complex[offsb][idxb1].y;
    7761             :                     }
    7762           0 :                     if( optypeb==1 )
    7763             :                     {
    7764           0 :                         b0x = b->ptr.pp_complex[idxb0][offsb].x;
    7765           0 :                         b0y = b->ptr.pp_complex[idxb0][offsb].y;
    7766           0 :                         b1x = b->ptr.pp_complex[idxb1][offsb].x;
    7767           0 :                         b1y = b->ptr.pp_complex[idxb1][offsb].y;
    7768             :                     }
    7769           0 :                     if( optypeb==2 )
    7770             :                     {
    7771           0 :                         b0x = b->ptr.pp_complex[idxb0][offsb].x;
    7772           0 :                         b0y = -b->ptr.pp_complex[idxb0][offsb].y;
    7773           0 :                         b1x = b->ptr.pp_complex[idxb1][offsb].x;
    7774           0 :                         b1y = -b->ptr.pp_complex[idxb1][offsb].y;
    7775             :                     }
    7776           0 :                     v00x = v00x+a0x*b0x-a0y*b0y;
    7777           0 :                     v00y = v00y+a0x*b0y+a0y*b0x;
    7778           0 :                     v01x = v01x+a0x*b1x-a0y*b1y;
    7779           0 :                     v01y = v01y+a0x*b1y+a0y*b1x;
    7780           0 :                     v10x = v10x+a1x*b0x-a1y*b0y;
    7781           0 :                     v10y = v10y+a1x*b0y+a1y*b0x;
    7782           0 :                     v11x = v11x+a1x*b1x-a1y*b1y;
    7783           0 :                     v11y = v11y+a1x*b1y+a1y*b1x;
    7784           0 :                     offsa = offsa+1;
    7785           0 :                     offsb = offsb+1;
    7786             :                 }
    7787           0 :                 v00.x = v00x;
    7788           0 :                 v00.y = v00y;
    7789           0 :                 v10.x = v10x;
    7790           0 :                 v10.y = v10y;
    7791           0 :                 v01.x = v01x;
    7792           0 :                 v01.y = v01y;
    7793           0 :                 v11.x = v11x;
    7794           0 :                 v11.y = v11y;
    7795           0 :                 if( ae_c_eq_d(beta,(double)(0)) )
    7796             :                 {
    7797           0 :                     c->ptr.pp_complex[ic+i+0][jc+j+0] = ae_c_mul(alpha,v00);
    7798           0 :                     c->ptr.pp_complex[ic+i+0][jc+j+1] = ae_c_mul(alpha,v01);
    7799           0 :                     c->ptr.pp_complex[ic+i+1][jc+j+0] = ae_c_mul(alpha,v10);
    7800           0 :                     c->ptr.pp_complex[ic+i+1][jc+j+1] = ae_c_mul(alpha,v11);
    7801             :                 }
    7802             :                 else
    7803             :                 {
    7804           0 :                     c->ptr.pp_complex[ic+i+0][jc+j+0] = ae_c_add(ae_c_mul(beta,c->ptr.pp_complex[ic+i+0][jc+j+0]),ae_c_mul(alpha,v00));
    7805           0 :                     c->ptr.pp_complex[ic+i+0][jc+j+1] = ae_c_add(ae_c_mul(beta,c->ptr.pp_complex[ic+i+0][jc+j+1]),ae_c_mul(alpha,v01));
    7806           0 :                     c->ptr.pp_complex[ic+i+1][jc+j+0] = ae_c_add(ae_c_mul(beta,c->ptr.pp_complex[ic+i+1][jc+j+0]),ae_c_mul(alpha,v10));
    7807           0 :                     c->ptr.pp_complex[ic+i+1][jc+j+1] = ae_c_add(ae_c_mul(beta,c->ptr.pp_complex[ic+i+1][jc+j+1]),ae_c_mul(alpha,v11));
    7808             :                 }
    7809             :             }
    7810             :             else
    7811             :             {
    7812             :                 
    7813             :                 /*
    7814             :                  * Determine submatrix [I0..I1]x[J0..J1] to process
    7815             :                  */
    7816           0 :                 i0 = i;
    7817           0 :                 i1 = ae_minint(i+1, m-1, _state);
    7818           0 :                 j0 = j;
    7819           0 :                 j1 = ae_minint(j+1, n-1, _state);
    7820             :                 
    7821             :                 /*
    7822             :                  * Process submatrix
    7823             :                  */
    7824           0 :                 for(ik=i0; ik<=i1; ik++)
    7825             :                 {
    7826           0 :                     for(jk=j0; jk<=j1; jk++)
    7827             :                     {
    7828           0 :                         if( k==0||ae_c_eq_d(alpha,(double)(0)) )
    7829             :                         {
    7830           0 :                             v = ae_complex_from_i(0);
    7831             :                         }
    7832             :                         else
    7833             :                         {
    7834           0 :                             v = ae_complex_from_d(0.0);
    7835           0 :                             if( optypea==0&&optypeb==0 )
    7836             :                             {
    7837           0 :                                 v = ae_v_cdotproduct(&a->ptr.pp_complex[ia+ik][ja], 1, "N", &b->ptr.pp_complex[ib][jb+jk], b->stride, "N", ae_v_len(ja,ja+k-1));
    7838             :                             }
    7839           0 :                             if( optypea==0&&optypeb==1 )
    7840             :                             {
    7841           0 :                                 v = ae_v_cdotproduct(&a->ptr.pp_complex[ia+ik][ja], 1, "N", &b->ptr.pp_complex[ib+jk][jb], 1, "N", ae_v_len(ja,ja+k-1));
    7842             :                             }
    7843           0 :                             if( optypea==0&&optypeb==2 )
    7844             :                             {
    7845           0 :                                 v = ae_v_cdotproduct(&a->ptr.pp_complex[ia+ik][ja], 1, "N", &b->ptr.pp_complex[ib+jk][jb], 1, "Conj", ae_v_len(ja,ja+k-1));
    7846             :                             }
    7847           0 :                             if( optypea==1&&optypeb==0 )
    7848             :                             {
    7849           0 :                                 v = ae_v_cdotproduct(&a->ptr.pp_complex[ia][ja+ik], a->stride, "N", &b->ptr.pp_complex[ib][jb+jk], b->stride, "N", ae_v_len(ia,ia+k-1));
    7850             :                             }
    7851           0 :                             if( optypea==1&&optypeb==1 )
    7852             :                             {
    7853           0 :                                 v = ae_v_cdotproduct(&a->ptr.pp_complex[ia][ja+ik], a->stride, "N", &b->ptr.pp_complex[ib+jk][jb], 1, "N", ae_v_len(ia,ia+k-1));
    7854             :                             }
    7855           0 :                             if( optypea==1&&optypeb==2 )
    7856             :                             {
    7857           0 :                                 v = ae_v_cdotproduct(&a->ptr.pp_complex[ia][ja+ik], a->stride, "N", &b->ptr.pp_complex[ib+jk][jb], 1, "Conj", ae_v_len(ia,ia+k-1));
    7858             :                             }
    7859           0 :                             if( optypea==2&&optypeb==0 )
    7860             :                             {
    7861           0 :                                 v = ae_v_cdotproduct(&a->ptr.pp_complex[ia][ja+ik], a->stride, "Conj", &b->ptr.pp_complex[ib][jb+jk], b->stride, "N", ae_v_len(ia,ia+k-1));
    7862             :                             }
    7863           0 :                             if( optypea==2&&optypeb==1 )
    7864             :                             {
    7865           0 :                                 v = ae_v_cdotproduct(&a->ptr.pp_complex[ia][ja+ik], a->stride, "Conj", &b->ptr.pp_complex[ib+jk][jb], 1, "N", ae_v_len(ia,ia+k-1));
    7866             :                             }
    7867           0 :                             if( optypea==2&&optypeb==2 )
    7868             :                             {
    7869           0 :                                 v = ae_v_cdotproduct(&a->ptr.pp_complex[ia][ja+ik], a->stride, "Conj", &b->ptr.pp_complex[ib+jk][jb], 1, "Conj", ae_v_len(ia,ia+k-1));
    7870             :                             }
    7871             :                         }
    7872           0 :                         if( ae_c_eq_d(beta,(double)(0)) )
    7873             :                         {
    7874           0 :                             c->ptr.pp_complex[ic+ik][jc+jk] = ae_c_mul(alpha,v);
    7875             :                         }
    7876             :                         else
    7877             :                         {
    7878           0 :                             c->ptr.pp_complex[ic+ik][jc+jk] = ae_c_add(ae_c_mul(beta,c->ptr.pp_complex[ic+ik][jc+jk]),ae_c_mul(alpha,v));
    7879             :                         }
    7880             :                     }
    7881             :                 }
    7882             :             }
    7883           0 :             j = j+2;
    7884             :         }
    7885           0 :         i = i+2;
    7886             :     }
    7887             : }
    7888             : 
    7889             : 
    7890             : /*************************************************************************
    7891             : RMatrixGEMM kernel, basecase code for RMatrixGEMM.
    7892             : 
    7893             : This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where:
    7894             : * C is MxN general matrix
    7895             : * op1(A) is MxK matrix
    7896             : * op2(B) is KxN matrix
    7897             : * "op" may be identity transformation, transposition
    7898             : 
    7899             : Additional info:
    7900             : * multiplication result replaces C. If Beta=0, C elements are not used in
    7901             :   calculations (not multiplied by zero - just not referenced)
    7902             : * if Alpha=0, A is not used (not multiplied by zero - just not referenced)
    7903             : * if both Beta and Alpha are zero, C is filled by zeros.
    7904             : 
    7905             : IMPORTANT:
    7906             : 
    7907             : This function does NOT preallocate output matrix C, it MUST be preallocated
    7908             : by caller prior to calling this function. In case C does not have  enough
    7909             : space to store result, exception will be generated.
    7910             : 
    7911             : INPUT PARAMETERS
    7912             :     M       -   matrix size, M>0
    7913             :     N       -   matrix size, N>0
    7914             :     K       -   matrix size, K>0
    7915             :     Alpha   -   coefficient
    7916             :     A       -   matrix
    7917             :     IA      -   submatrix offset
    7918             :     JA      -   submatrix offset
    7919             :     OpTypeA -   transformation type:
    7920             :                 * 0 - no transformation
    7921             :                 * 1 - transposition
    7922             :     B       -   matrix
    7923             :     IB      -   submatrix offset
    7924             :     JB      -   submatrix offset
    7925             :     OpTypeB -   transformation type:
    7926             :                 * 0 - no transformation
    7927             :                 * 1 - transposition
    7928             :     Beta    -   coefficient
    7929             :     C       -   PREALLOCATED output matrix
    7930             :     IC      -   submatrix offset
    7931             :     JC      -   submatrix offset
    7932             : 
    7933             :   -- ALGLIB routine --
    7934             :      27.03.2013
    7935             :      Bochkanov Sergey
    7936             : *************************************************************************/
    7937           0 : void rmatrixgemmk(ae_int_t m,
    7938             :      ae_int_t n,
    7939             :      ae_int_t k,
    7940             :      double alpha,
    7941             :      /* Real    */ ae_matrix* a,
    7942             :      ae_int_t ia,
    7943             :      ae_int_t ja,
    7944             :      ae_int_t optypea,
    7945             :      /* Real    */ ae_matrix* b,
    7946             :      ae_int_t ib,
    7947             :      ae_int_t jb,
    7948             :      ae_int_t optypeb,
    7949             :      double beta,
    7950             :      /* Real    */ ae_matrix* c,
    7951             :      ae_int_t ic,
    7952             :      ae_int_t jc,
    7953             :      ae_state *_state)
    7954             : {
    7955             :     ae_int_t i;
    7956             :     ae_int_t j;
    7957             : 
    7958             : 
    7959             :     
    7960             :     /*
    7961             :      * if matrix size is zero
    7962             :      */
    7963           0 :     if( m==0||n==0 )
    7964             :     {
    7965           0 :         return;
    7966             :     }
    7967             :     
    7968             :     /*
    7969             :      * Try optimized code
    7970             :      */
    7971           0 :     if( rmatrixgemmf(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state) )
    7972             :     {
    7973           0 :         return;
    7974             :     }
    7975             :     
    7976             :     /*
    7977             :      * if K=0 or Alpha=0, then C=Beta*C
    7978             :      */
    7979           0 :     if( k==0||ae_fp_eq(alpha,(double)(0)) )
    7980             :     {
    7981           0 :         if( ae_fp_neq(beta,(double)(1)) )
    7982             :         {
    7983           0 :             if( ae_fp_neq(beta,(double)(0)) )
    7984             :             {
    7985           0 :                 for(i=0; i<=m-1; i++)
    7986             :                 {
    7987           0 :                     for(j=0; j<=n-1; j++)
    7988             :                     {
    7989           0 :                         c->ptr.pp_double[ic+i][jc+j] = beta*c->ptr.pp_double[ic+i][jc+j];
    7990             :                     }
    7991             :                 }
    7992             :             }
    7993             :             else
    7994             :             {
    7995           0 :                 for(i=0; i<=m-1; i++)
    7996             :                 {
    7997           0 :                     for(j=0; j<=n-1; j++)
    7998             :                     {
    7999           0 :                         c->ptr.pp_double[ic+i][jc+j] = (double)(0);
    8000             :                     }
    8001             :                 }
    8002             :             }
    8003             :         }
    8004           0 :         return;
    8005             :     }
    8006             :     
    8007             :     /*
    8008             :      * Call specialized code.
    8009             :      *
    8010             :      * NOTE: specialized code was moved to separate function because of strange
    8011             :      *       issues with instructions cache on some systems; Having too long
    8012             :      *       functions significantly slows down internal loop of the algorithm.
    8013             :      */
    8014           0 :     if( optypea==0&&optypeb==0 )
    8015             :     {
    8016           0 :         rmatrixgemmk44v00(m, n, k, alpha, a, ia, ja, b, ib, jb, beta, c, ic, jc, _state);
    8017             :     }
    8018           0 :     if( optypea==0&&optypeb!=0 )
    8019             :     {
    8020           0 :         rmatrixgemmk44v01(m, n, k, alpha, a, ia, ja, b, ib, jb, beta, c, ic, jc, _state);
    8021             :     }
    8022           0 :     if( optypea!=0&&optypeb==0 )
    8023             :     {
    8024           0 :         rmatrixgemmk44v10(m, n, k, alpha, a, ia, ja, b, ib, jb, beta, c, ic, jc, _state);
    8025             :     }
    8026           0 :     if( optypea!=0&&optypeb!=0 )
    8027             :     {
    8028           0 :         rmatrixgemmk44v11(m, n, k, alpha, a, ia, ja, b, ib, jb, beta, c, ic, jc, _state);
    8029             :     }
    8030             : }
    8031             : 
    8032             : 
    8033             : /*************************************************************************
    8034             : RMatrixGEMM kernel, basecase code for RMatrixGEMM, specialized for sitation
    8035             : with OpTypeA=0 and OpTypeB=0.
    8036             : 
    8037             : Additional info:
    8038             : * this function requires that Alpha<>0 (assertion is thrown otherwise)
    8039             : 
    8040             : INPUT PARAMETERS
    8041             :     M       -   matrix size, M>0
    8042             :     N       -   matrix size, N>0
    8043             :     K       -   matrix size, K>0
    8044             :     Alpha   -   coefficient
    8045             :     A       -   matrix
    8046             :     IA      -   submatrix offset
    8047             :     JA      -   submatrix offset
    8048             :     B       -   matrix
    8049             :     IB      -   submatrix offset
    8050             :     JB      -   submatrix offset
    8051             :     Beta    -   coefficient
    8052             :     C       -   PREALLOCATED output matrix
    8053             :     IC      -   submatrix offset
    8054             :     JC      -   submatrix offset
    8055             : 
    8056             :   -- ALGLIB routine --
    8057             :      27.03.2013
    8058             :      Bochkanov Sergey
    8059             : *************************************************************************/
    8060           0 : void rmatrixgemmk44v00(ae_int_t m,
    8061             :      ae_int_t n,
    8062             :      ae_int_t k,
    8063             :      double alpha,
    8064             :      /* Real    */ ae_matrix* a,
    8065             :      ae_int_t ia,
    8066             :      ae_int_t ja,
    8067             :      /* Real    */ ae_matrix* b,
    8068             :      ae_int_t ib,
    8069             :      ae_int_t jb,
    8070             :      double beta,
    8071             :      /* Real    */ ae_matrix* c,
    8072             :      ae_int_t ic,
    8073             :      ae_int_t jc,
    8074             :      ae_state *_state)
    8075             : {
    8076             :     ae_int_t i;
    8077             :     ae_int_t j;
    8078             :     double v;
    8079             :     double v00;
    8080             :     double v01;
    8081             :     double v02;
    8082             :     double v03;
    8083             :     double v10;
    8084             :     double v11;
    8085             :     double v12;
    8086             :     double v13;
    8087             :     double v20;
    8088             :     double v21;
    8089             :     double v22;
    8090             :     double v23;
    8091             :     double v30;
    8092             :     double v31;
    8093             :     double v32;
    8094             :     double v33;
    8095             :     double a0;
    8096             :     double a1;
    8097             :     double a2;
    8098             :     double a3;
    8099             :     double b0;
    8100             :     double b1;
    8101             :     double b2;
    8102             :     double b3;
    8103             :     ae_int_t idxa0;
    8104             :     ae_int_t idxa1;
    8105             :     ae_int_t idxa2;
    8106             :     ae_int_t idxa3;
    8107             :     ae_int_t idxb0;
    8108             :     ae_int_t idxb1;
    8109             :     ae_int_t idxb2;
    8110             :     ae_int_t idxb3;
    8111             :     ae_int_t i0;
    8112             :     ae_int_t i1;
    8113             :     ae_int_t ik;
    8114             :     ae_int_t j0;
    8115             :     ae_int_t j1;
    8116             :     ae_int_t jk;
    8117             :     ae_int_t t;
    8118             :     ae_int_t offsa;
    8119             :     ae_int_t offsb;
    8120             : 
    8121             : 
    8122           0 :     ae_assert(ae_fp_neq(alpha,(double)(0)), "RMatrixGEMMK44V00: internal error (Alpha=0)", _state);
    8123             :     
    8124             :     /*
    8125             :      * if matrix size is zero
    8126             :      */
    8127           0 :     if( m==0||n==0 )
    8128             :     {
    8129           0 :         return;
    8130             :     }
    8131             :     
    8132             :     /*
    8133             :      * A*B
    8134             :      */
    8135           0 :     i = 0;
    8136           0 :     while(i<m)
    8137             :     {
    8138           0 :         j = 0;
    8139           0 :         while(j<n)
    8140             :         {
    8141             :             
    8142             :             /*
    8143             :              * Choose between specialized 4x4 code and general code
    8144             :              */
    8145           0 :             if( i+4<=m&&j+4<=n )
    8146             :             {
    8147             :                 
    8148             :                 /*
    8149             :                  * Specialized 4x4 code for [I..I+3]x[J..J+3] submatrix of C.
    8150             :                  *
    8151             :                  * This submatrix is calculated as sum of K rank-1 products,
    8152             :                  * with operands cached in local variables in order to speed
    8153             :                  * up operations with arrays.
    8154             :                  */
    8155           0 :                 idxa0 = ia+i+0;
    8156           0 :                 idxa1 = ia+i+1;
    8157           0 :                 idxa2 = ia+i+2;
    8158           0 :                 idxa3 = ia+i+3;
    8159           0 :                 offsa = ja;
    8160           0 :                 idxb0 = jb+j+0;
    8161           0 :                 idxb1 = jb+j+1;
    8162           0 :                 idxb2 = jb+j+2;
    8163           0 :                 idxb3 = jb+j+3;
    8164           0 :                 offsb = ib;
    8165           0 :                 v00 = 0.0;
    8166           0 :                 v01 = 0.0;
    8167           0 :                 v02 = 0.0;
    8168           0 :                 v03 = 0.0;
    8169           0 :                 v10 = 0.0;
    8170           0 :                 v11 = 0.0;
    8171           0 :                 v12 = 0.0;
    8172           0 :                 v13 = 0.0;
    8173           0 :                 v20 = 0.0;
    8174           0 :                 v21 = 0.0;
    8175           0 :                 v22 = 0.0;
    8176           0 :                 v23 = 0.0;
    8177           0 :                 v30 = 0.0;
    8178           0 :                 v31 = 0.0;
    8179           0 :                 v32 = 0.0;
    8180           0 :                 v33 = 0.0;
    8181             :                 
    8182             :                 /*
    8183             :                  * Different variants of internal loop
    8184             :                  */
    8185           0 :                 for(t=0; t<=k-1; t++)
    8186             :                 {
    8187           0 :                     a0 = a->ptr.pp_double[idxa0][offsa];
    8188           0 :                     a1 = a->ptr.pp_double[idxa1][offsa];
    8189           0 :                     b0 = b->ptr.pp_double[offsb][idxb0];
    8190           0 :                     b1 = b->ptr.pp_double[offsb][idxb1];
    8191           0 :                     v00 = v00+a0*b0;
    8192           0 :                     v01 = v01+a0*b1;
    8193           0 :                     v10 = v10+a1*b0;
    8194           0 :                     v11 = v11+a1*b1;
    8195           0 :                     a2 = a->ptr.pp_double[idxa2][offsa];
    8196           0 :                     a3 = a->ptr.pp_double[idxa3][offsa];
    8197           0 :                     v20 = v20+a2*b0;
    8198           0 :                     v21 = v21+a2*b1;
    8199           0 :                     v30 = v30+a3*b0;
    8200           0 :                     v31 = v31+a3*b1;
    8201           0 :                     b2 = b->ptr.pp_double[offsb][idxb2];
    8202           0 :                     b3 = b->ptr.pp_double[offsb][idxb3];
    8203           0 :                     v22 = v22+a2*b2;
    8204           0 :                     v23 = v23+a2*b3;
    8205           0 :                     v32 = v32+a3*b2;
    8206           0 :                     v33 = v33+a3*b3;
    8207           0 :                     v02 = v02+a0*b2;
    8208           0 :                     v03 = v03+a0*b3;
    8209           0 :                     v12 = v12+a1*b2;
    8210           0 :                     v13 = v13+a1*b3;
    8211           0 :                     offsa = offsa+1;
    8212           0 :                     offsb = offsb+1;
    8213             :                 }
    8214           0 :                 if( ae_fp_eq(beta,(double)(0)) )
    8215             :                 {
    8216           0 :                     c->ptr.pp_double[ic+i+0][jc+j+0] = alpha*v00;
    8217           0 :                     c->ptr.pp_double[ic+i+0][jc+j+1] = alpha*v01;
    8218           0 :                     c->ptr.pp_double[ic+i+0][jc+j+2] = alpha*v02;
    8219           0 :                     c->ptr.pp_double[ic+i+0][jc+j+3] = alpha*v03;
    8220           0 :                     c->ptr.pp_double[ic+i+1][jc+j+0] = alpha*v10;
    8221           0 :                     c->ptr.pp_double[ic+i+1][jc+j+1] = alpha*v11;
    8222           0 :                     c->ptr.pp_double[ic+i+1][jc+j+2] = alpha*v12;
    8223           0 :                     c->ptr.pp_double[ic+i+1][jc+j+3] = alpha*v13;
    8224           0 :                     c->ptr.pp_double[ic+i+2][jc+j+0] = alpha*v20;
    8225           0 :                     c->ptr.pp_double[ic+i+2][jc+j+1] = alpha*v21;
    8226           0 :                     c->ptr.pp_double[ic+i+2][jc+j+2] = alpha*v22;
    8227           0 :                     c->ptr.pp_double[ic+i+2][jc+j+3] = alpha*v23;
    8228           0 :                     c->ptr.pp_double[ic+i+3][jc+j+0] = alpha*v30;
    8229           0 :                     c->ptr.pp_double[ic+i+3][jc+j+1] = alpha*v31;
    8230           0 :                     c->ptr.pp_double[ic+i+3][jc+j+2] = alpha*v32;
    8231           0 :                     c->ptr.pp_double[ic+i+3][jc+j+3] = alpha*v33;
    8232             :                 }
    8233             :                 else
    8234             :                 {
    8235           0 :                     c->ptr.pp_double[ic+i+0][jc+j+0] = beta*c->ptr.pp_double[ic+i+0][jc+j+0]+alpha*v00;
    8236           0 :                     c->ptr.pp_double[ic+i+0][jc+j+1] = beta*c->ptr.pp_double[ic+i+0][jc+j+1]+alpha*v01;
    8237           0 :                     c->ptr.pp_double[ic+i+0][jc+j+2] = beta*c->ptr.pp_double[ic+i+0][jc+j+2]+alpha*v02;
    8238           0 :                     c->ptr.pp_double[ic+i+0][jc+j+3] = beta*c->ptr.pp_double[ic+i+0][jc+j+3]+alpha*v03;
    8239           0 :                     c->ptr.pp_double[ic+i+1][jc+j+0] = beta*c->ptr.pp_double[ic+i+1][jc+j+0]+alpha*v10;
    8240           0 :                     c->ptr.pp_double[ic+i+1][jc+j+1] = beta*c->ptr.pp_double[ic+i+1][jc+j+1]+alpha*v11;
    8241           0 :                     c->ptr.pp_double[ic+i+1][jc+j+2] = beta*c->ptr.pp_double[ic+i+1][jc+j+2]+alpha*v12;
    8242           0 :                     c->ptr.pp_double[ic+i+1][jc+j+3] = beta*c->ptr.pp_double[ic+i+1][jc+j+3]+alpha*v13;
    8243           0 :                     c->ptr.pp_double[ic+i+2][jc+j+0] = beta*c->ptr.pp_double[ic+i+2][jc+j+0]+alpha*v20;
    8244           0 :                     c->ptr.pp_double[ic+i+2][jc+j+1] = beta*c->ptr.pp_double[ic+i+2][jc+j+1]+alpha*v21;
    8245           0 :                     c->ptr.pp_double[ic+i+2][jc+j+2] = beta*c->ptr.pp_double[ic+i+2][jc+j+2]+alpha*v22;
    8246           0 :                     c->ptr.pp_double[ic+i+2][jc+j+3] = beta*c->ptr.pp_double[ic+i+2][jc+j+3]+alpha*v23;
    8247           0 :                     c->ptr.pp_double[ic+i+3][jc+j+0] = beta*c->ptr.pp_double[ic+i+3][jc+j+0]+alpha*v30;
    8248           0 :                     c->ptr.pp_double[ic+i+3][jc+j+1] = beta*c->ptr.pp_double[ic+i+3][jc+j+1]+alpha*v31;
    8249           0 :                     c->ptr.pp_double[ic+i+3][jc+j+2] = beta*c->ptr.pp_double[ic+i+3][jc+j+2]+alpha*v32;
    8250           0 :                     c->ptr.pp_double[ic+i+3][jc+j+3] = beta*c->ptr.pp_double[ic+i+3][jc+j+3]+alpha*v33;
    8251             :                 }
    8252             :             }
    8253             :             else
    8254             :             {
    8255             :                 
    8256             :                 /*
    8257             :                  * Determine submatrix [I0..I1]x[J0..J1] to process
    8258             :                  */
    8259           0 :                 i0 = i;
    8260           0 :                 i1 = ae_minint(i+3, m-1, _state);
    8261           0 :                 j0 = j;
    8262           0 :                 j1 = ae_minint(j+3, n-1, _state);
    8263             :                 
    8264             :                 /*
    8265             :                  * Process submatrix
    8266             :                  */
    8267           0 :                 for(ik=i0; ik<=i1; ik++)
    8268             :                 {
    8269           0 :                     for(jk=j0; jk<=j1; jk++)
    8270             :                     {
    8271           0 :                         if( k==0||ae_fp_eq(alpha,(double)(0)) )
    8272             :                         {
    8273           0 :                             v = (double)(0);
    8274             :                         }
    8275             :                         else
    8276             :                         {
    8277           0 :                             v = ae_v_dotproduct(&a->ptr.pp_double[ia+ik][ja], 1, &b->ptr.pp_double[ib][jb+jk], b->stride, ae_v_len(ja,ja+k-1));
    8278             :                         }
    8279           0 :                         if( ae_fp_eq(beta,(double)(0)) )
    8280             :                         {
    8281           0 :                             c->ptr.pp_double[ic+ik][jc+jk] = alpha*v;
    8282             :                         }
    8283             :                         else
    8284             :                         {
    8285           0 :                             c->ptr.pp_double[ic+ik][jc+jk] = beta*c->ptr.pp_double[ic+ik][jc+jk]+alpha*v;
    8286             :                         }
    8287             :                     }
    8288             :                 }
    8289             :             }
    8290           0 :             j = j+4;
    8291             :         }
    8292           0 :         i = i+4;
    8293             :     }
    8294             : }
    8295             : 
    8296             : 
    8297             : /*************************************************************************
    8298             : RMatrixGEMM kernel, basecase code for RMatrixGEMM, specialized for sitation
    8299             : with OpTypeA=0 and OpTypeB=1.
    8300             : 
    8301             : Additional info:
    8302             : * this function requires that Alpha<>0 (assertion is thrown otherwise)
    8303             : 
    8304             : INPUT PARAMETERS
    8305             :     M       -   matrix size, M>0
    8306             :     N       -   matrix size, N>0
    8307             :     K       -   matrix size, K>0
    8308             :     Alpha   -   coefficient
    8309             :     A       -   matrix
    8310             :     IA      -   submatrix offset
    8311             :     JA      -   submatrix offset
    8312             :     B       -   matrix
    8313             :     IB      -   submatrix offset
    8314             :     JB      -   submatrix offset
    8315             :     Beta    -   coefficient
    8316             :     C       -   PREALLOCATED output matrix
    8317             :     IC      -   submatrix offset
    8318             :     JC      -   submatrix offset
    8319             : 
    8320             :   -- ALGLIB routine --
    8321             :      27.03.2013
    8322             :      Bochkanov Sergey
    8323             : *************************************************************************/
    8324           0 : void rmatrixgemmk44v01(ae_int_t m,
    8325             :      ae_int_t n,
    8326             :      ae_int_t k,
    8327             :      double alpha,
    8328             :      /* Real    */ ae_matrix* a,
    8329             :      ae_int_t ia,
    8330             :      ae_int_t ja,
    8331             :      /* Real    */ ae_matrix* b,
    8332             :      ae_int_t ib,
    8333             :      ae_int_t jb,
    8334             :      double beta,
    8335             :      /* Real    */ ae_matrix* c,
    8336             :      ae_int_t ic,
    8337             :      ae_int_t jc,
    8338             :      ae_state *_state)
    8339             : {
    8340             :     ae_int_t i;
    8341             :     ae_int_t j;
    8342             :     double v;
    8343             :     double v00;
    8344             :     double v01;
    8345             :     double v02;
    8346             :     double v03;
    8347             :     double v10;
    8348             :     double v11;
    8349             :     double v12;
    8350             :     double v13;
    8351             :     double v20;
    8352             :     double v21;
    8353             :     double v22;
    8354             :     double v23;
    8355             :     double v30;
    8356             :     double v31;
    8357             :     double v32;
    8358             :     double v33;
    8359             :     double a0;
    8360             :     double a1;
    8361             :     double a2;
    8362             :     double a3;
    8363             :     double b0;
    8364             :     double b1;
    8365             :     double b2;
    8366             :     double b3;
    8367             :     ae_int_t idxa0;
    8368             :     ae_int_t idxa1;
    8369             :     ae_int_t idxa2;
    8370             :     ae_int_t idxa3;
    8371             :     ae_int_t idxb0;
    8372             :     ae_int_t idxb1;
    8373             :     ae_int_t idxb2;
    8374             :     ae_int_t idxb3;
    8375             :     ae_int_t i0;
    8376             :     ae_int_t i1;
    8377             :     ae_int_t ik;
    8378             :     ae_int_t j0;
    8379             :     ae_int_t j1;
    8380             :     ae_int_t jk;
    8381             :     ae_int_t t;
    8382             :     ae_int_t offsa;
    8383             :     ae_int_t offsb;
    8384             : 
    8385             : 
    8386           0 :     ae_assert(ae_fp_neq(alpha,(double)(0)), "RMatrixGEMMK44V00: internal error (Alpha=0)", _state);
    8387             :     
    8388             :     /*
    8389             :      * if matrix size is zero
    8390             :      */
    8391           0 :     if( m==0||n==0 )
    8392             :     {
    8393           0 :         return;
    8394             :     }
    8395             :     
    8396             :     /*
    8397             :      * A*B'
    8398             :      */
    8399           0 :     i = 0;
    8400           0 :     while(i<m)
    8401             :     {
    8402           0 :         j = 0;
    8403           0 :         while(j<n)
    8404             :         {
    8405             :             
    8406             :             /*
    8407             :              * Choose between specialized 4x4 code and general code
    8408             :              */
    8409           0 :             if( i+4<=m&&j+4<=n )
    8410             :             {
    8411             :                 
    8412             :                 /*
    8413             :                  * Specialized 4x4 code for [I..I+3]x[J..J+3] submatrix of C.
    8414             :                  *
    8415             :                  * This submatrix is calculated as sum of K rank-1 products,
    8416             :                  * with operands cached in local variables in order to speed
    8417             :                  * up operations with arrays.
    8418             :                  */
    8419           0 :                 idxa0 = ia+i+0;
    8420           0 :                 idxa1 = ia+i+1;
    8421           0 :                 idxa2 = ia+i+2;
    8422           0 :                 idxa3 = ia+i+3;
    8423           0 :                 offsa = ja;
    8424           0 :                 idxb0 = ib+j+0;
    8425           0 :                 idxb1 = ib+j+1;
    8426           0 :                 idxb2 = ib+j+2;
    8427           0 :                 idxb3 = ib+j+3;
    8428           0 :                 offsb = jb;
    8429           0 :                 v00 = 0.0;
    8430           0 :                 v01 = 0.0;
    8431           0 :                 v02 = 0.0;
    8432           0 :                 v03 = 0.0;
    8433           0 :                 v10 = 0.0;
    8434           0 :                 v11 = 0.0;
    8435           0 :                 v12 = 0.0;
    8436           0 :                 v13 = 0.0;
    8437           0 :                 v20 = 0.0;
    8438           0 :                 v21 = 0.0;
    8439           0 :                 v22 = 0.0;
    8440           0 :                 v23 = 0.0;
    8441           0 :                 v30 = 0.0;
    8442           0 :                 v31 = 0.0;
    8443           0 :                 v32 = 0.0;
    8444           0 :                 v33 = 0.0;
    8445           0 :                 for(t=0; t<=k-1; t++)
    8446             :                 {
    8447           0 :                     a0 = a->ptr.pp_double[idxa0][offsa];
    8448           0 :                     a1 = a->ptr.pp_double[idxa1][offsa];
    8449           0 :                     b0 = b->ptr.pp_double[idxb0][offsb];
    8450           0 :                     b1 = b->ptr.pp_double[idxb1][offsb];
    8451           0 :                     v00 = v00+a0*b0;
    8452           0 :                     v01 = v01+a0*b1;
    8453           0 :                     v10 = v10+a1*b0;
    8454           0 :                     v11 = v11+a1*b1;
    8455           0 :                     a2 = a->ptr.pp_double[idxa2][offsa];
    8456           0 :                     a3 = a->ptr.pp_double[idxa3][offsa];
    8457           0 :                     v20 = v20+a2*b0;
    8458           0 :                     v21 = v21+a2*b1;
    8459           0 :                     v30 = v30+a3*b0;
    8460           0 :                     v31 = v31+a3*b1;
    8461           0 :                     b2 = b->ptr.pp_double[idxb2][offsb];
    8462           0 :                     b3 = b->ptr.pp_double[idxb3][offsb];
    8463           0 :                     v22 = v22+a2*b2;
    8464           0 :                     v23 = v23+a2*b3;
    8465           0 :                     v32 = v32+a3*b2;
    8466           0 :                     v33 = v33+a3*b3;
    8467           0 :                     v02 = v02+a0*b2;
    8468           0 :                     v03 = v03+a0*b3;
    8469           0 :                     v12 = v12+a1*b2;
    8470           0 :                     v13 = v13+a1*b3;
    8471           0 :                     offsa = offsa+1;
    8472           0 :                     offsb = offsb+1;
    8473             :                 }
    8474           0 :                 if( ae_fp_eq(beta,(double)(0)) )
    8475             :                 {
    8476           0 :                     c->ptr.pp_double[ic+i+0][jc+j+0] = alpha*v00;
    8477           0 :                     c->ptr.pp_double[ic+i+0][jc+j+1] = alpha*v01;
    8478           0 :                     c->ptr.pp_double[ic+i+0][jc+j+2] = alpha*v02;
    8479           0 :                     c->ptr.pp_double[ic+i+0][jc+j+3] = alpha*v03;
    8480           0 :                     c->ptr.pp_double[ic+i+1][jc+j+0] = alpha*v10;
    8481           0 :                     c->ptr.pp_double[ic+i+1][jc+j+1] = alpha*v11;
    8482           0 :                     c->ptr.pp_double[ic+i+1][jc+j+2] = alpha*v12;
    8483           0 :                     c->ptr.pp_double[ic+i+1][jc+j+3] = alpha*v13;
    8484           0 :                     c->ptr.pp_double[ic+i+2][jc+j+0] = alpha*v20;
    8485           0 :                     c->ptr.pp_double[ic+i+2][jc+j+1] = alpha*v21;
    8486           0 :                     c->ptr.pp_double[ic+i+2][jc+j+2] = alpha*v22;
    8487           0 :                     c->ptr.pp_double[ic+i+2][jc+j+3] = alpha*v23;
    8488           0 :                     c->ptr.pp_double[ic+i+3][jc+j+0] = alpha*v30;
    8489           0 :                     c->ptr.pp_double[ic+i+3][jc+j+1] = alpha*v31;
    8490           0 :                     c->ptr.pp_double[ic+i+3][jc+j+2] = alpha*v32;
    8491           0 :                     c->ptr.pp_double[ic+i+3][jc+j+3] = alpha*v33;
    8492             :                 }
    8493             :                 else
    8494             :                 {
    8495           0 :                     c->ptr.pp_double[ic+i+0][jc+j+0] = beta*c->ptr.pp_double[ic+i+0][jc+j+0]+alpha*v00;
    8496           0 :                     c->ptr.pp_double[ic+i+0][jc+j+1] = beta*c->ptr.pp_double[ic+i+0][jc+j+1]+alpha*v01;
    8497           0 :                     c->ptr.pp_double[ic+i+0][jc+j+2] = beta*c->ptr.pp_double[ic+i+0][jc+j+2]+alpha*v02;
    8498           0 :                     c->ptr.pp_double[ic+i+0][jc+j+3] = beta*c->ptr.pp_double[ic+i+0][jc+j+3]+alpha*v03;
    8499           0 :                     c->ptr.pp_double[ic+i+1][jc+j+0] = beta*c->ptr.pp_double[ic+i+1][jc+j+0]+alpha*v10;
    8500           0 :                     c->ptr.pp_double[ic+i+1][jc+j+1] = beta*c->ptr.pp_double[ic+i+1][jc+j+1]+alpha*v11;
    8501           0 :                     c->ptr.pp_double[ic+i+1][jc+j+2] = beta*c->ptr.pp_double[ic+i+1][jc+j+2]+alpha*v12;
    8502           0 :                     c->ptr.pp_double[ic+i+1][jc+j+3] = beta*c->ptr.pp_double[ic+i+1][jc+j+3]+alpha*v13;
    8503           0 :                     c->ptr.pp_double[ic+i+2][jc+j+0] = beta*c->ptr.pp_double[ic+i+2][jc+j+0]+alpha*v20;
    8504           0 :                     c->ptr.pp_double[ic+i+2][jc+j+1] = beta*c->ptr.pp_double[ic+i+2][jc+j+1]+alpha*v21;
    8505           0 :                     c->ptr.pp_double[ic+i+2][jc+j+2] = beta*c->ptr.pp_double[ic+i+2][jc+j+2]+alpha*v22;
    8506           0 :                     c->ptr.pp_double[ic+i+2][jc+j+3] = beta*c->ptr.pp_double[ic+i+2][jc+j+3]+alpha*v23;
    8507           0 :                     c->ptr.pp_double[ic+i+3][jc+j+0] = beta*c->ptr.pp_double[ic+i+3][jc+j+0]+alpha*v30;
    8508           0 :                     c->ptr.pp_double[ic+i+3][jc+j+1] = beta*c->ptr.pp_double[ic+i+3][jc+j+1]+alpha*v31;
    8509           0 :                     c->ptr.pp_double[ic+i+3][jc+j+2] = beta*c->ptr.pp_double[ic+i+3][jc+j+2]+alpha*v32;
    8510           0 :                     c->ptr.pp_double[ic+i+3][jc+j+3] = beta*c->ptr.pp_double[ic+i+3][jc+j+3]+alpha*v33;
    8511             :                 }
    8512             :             }
    8513             :             else
    8514             :             {
    8515             :                 
    8516             :                 /*
    8517             :                  * Determine submatrix [I0..I1]x[J0..J1] to process
    8518             :                  */
    8519           0 :                 i0 = i;
    8520           0 :                 i1 = ae_minint(i+3, m-1, _state);
    8521           0 :                 j0 = j;
    8522           0 :                 j1 = ae_minint(j+3, n-1, _state);
    8523             :                 
    8524             :                 /*
    8525             :                  * Process submatrix
    8526             :                  */
    8527           0 :                 for(ik=i0; ik<=i1; ik++)
    8528             :                 {
    8529           0 :                     for(jk=j0; jk<=j1; jk++)
    8530             :                     {
    8531           0 :                         if( k==0||ae_fp_eq(alpha,(double)(0)) )
    8532             :                         {
    8533           0 :                             v = (double)(0);
    8534             :                         }
    8535             :                         else
    8536             :                         {
    8537           0 :                             v = ae_v_dotproduct(&a->ptr.pp_double[ia+ik][ja], 1, &b->ptr.pp_double[ib+jk][jb], 1, ae_v_len(ja,ja+k-1));
    8538             :                         }
    8539           0 :                         if( ae_fp_eq(beta,(double)(0)) )
    8540             :                         {
    8541           0 :                             c->ptr.pp_double[ic+ik][jc+jk] = alpha*v;
    8542             :                         }
    8543             :                         else
    8544             :                         {
    8545           0 :                             c->ptr.pp_double[ic+ik][jc+jk] = beta*c->ptr.pp_double[ic+ik][jc+jk]+alpha*v;
    8546             :                         }
    8547             :                     }
    8548             :                 }
    8549             :             }
    8550           0 :             j = j+4;
    8551             :         }
    8552           0 :         i = i+4;
    8553             :     }
    8554             : }
    8555             : 
    8556             : 
    8557             : /*************************************************************************
    8558             : RMatrixGEMM kernel, basecase code for RMatrixGEMM, specialized for sitation
    8559             : with OpTypeA=1 and OpTypeB=0.
    8560             : 
    8561             : Additional info:
    8562             : * this function requires that Alpha<>0 (assertion is thrown otherwise)
    8563             : 
    8564             : INPUT PARAMETERS
    8565             :     M       -   matrix size, M>0
    8566             :     N       -   matrix size, N>0
    8567             :     K       -   matrix size, K>0
    8568             :     Alpha   -   coefficient
    8569             :     A       -   matrix
    8570             :     IA      -   submatrix offset
    8571             :     JA      -   submatrix offset
    8572             :     B       -   matrix
    8573             :     IB      -   submatrix offset
    8574             :     JB      -   submatrix offset
    8575             :     Beta    -   coefficient
    8576             :     C       -   PREALLOCATED output matrix
    8577             :     IC      -   submatrix offset
    8578             :     JC      -   submatrix offset
    8579             : 
    8580             :   -- ALGLIB routine --
    8581             :      27.03.2013
    8582             :      Bochkanov Sergey
    8583             : *************************************************************************/
    8584           0 : void rmatrixgemmk44v10(ae_int_t m,
    8585             :      ae_int_t n,
    8586             :      ae_int_t k,
    8587             :      double alpha,
    8588             :      /* Real    */ ae_matrix* a,
    8589             :      ae_int_t ia,
    8590             :      ae_int_t ja,
    8591             :      /* Real    */ ae_matrix* b,
    8592             :      ae_int_t ib,
    8593             :      ae_int_t jb,
    8594             :      double beta,
    8595             :      /* Real    */ ae_matrix* c,
    8596             :      ae_int_t ic,
    8597             :      ae_int_t jc,
    8598             :      ae_state *_state)
    8599             : {
    8600             :     ae_int_t i;
    8601             :     ae_int_t j;
    8602             :     double v;
    8603             :     double v00;
    8604             :     double v01;
    8605             :     double v02;
    8606             :     double v03;
    8607             :     double v10;
    8608             :     double v11;
    8609             :     double v12;
    8610             :     double v13;
    8611             :     double v20;
    8612             :     double v21;
    8613             :     double v22;
    8614             :     double v23;
    8615             :     double v30;
    8616             :     double v31;
    8617             :     double v32;
    8618             :     double v33;
    8619             :     double a0;
    8620             :     double a1;
    8621             :     double a2;
    8622             :     double a3;
    8623             :     double b0;
    8624             :     double b1;
    8625             :     double b2;
    8626             :     double b3;
    8627             :     ae_int_t idxa0;
    8628             :     ae_int_t idxa1;
    8629             :     ae_int_t idxa2;
    8630             :     ae_int_t idxa3;
    8631             :     ae_int_t idxb0;
    8632             :     ae_int_t idxb1;
    8633             :     ae_int_t idxb2;
    8634             :     ae_int_t idxb3;
    8635             :     ae_int_t i0;
    8636             :     ae_int_t i1;
    8637             :     ae_int_t ik;
    8638             :     ae_int_t j0;
    8639             :     ae_int_t j1;
    8640             :     ae_int_t jk;
    8641             :     ae_int_t t;
    8642             :     ae_int_t offsa;
    8643             :     ae_int_t offsb;
    8644             : 
    8645             : 
    8646           0 :     ae_assert(ae_fp_neq(alpha,(double)(0)), "RMatrixGEMMK44V00: internal error (Alpha=0)", _state);
    8647             :     
    8648             :     /*
    8649             :      * if matrix size is zero
    8650             :      */
    8651           0 :     if( m==0||n==0 )
    8652             :     {
    8653           0 :         return;
    8654             :     }
    8655             :     
    8656             :     /*
    8657             :      * A'*B
    8658             :      */
    8659           0 :     i = 0;
    8660           0 :     while(i<m)
    8661             :     {
    8662           0 :         j = 0;
    8663           0 :         while(j<n)
    8664             :         {
    8665             :             
    8666             :             /*
    8667             :              * Choose between specialized 4x4 code and general code
    8668             :              */
    8669           0 :             if( i+4<=m&&j+4<=n )
    8670             :             {
    8671             :                 
    8672             :                 /*
    8673             :                  * Specialized 4x4 code for [I..I+3]x[J..J+3] submatrix of C.
    8674             :                  *
    8675             :                  * This submatrix is calculated as sum of K rank-1 products,
    8676             :                  * with operands cached in local variables in order to speed
    8677             :                  * up operations with arrays.
    8678             :                  */
    8679           0 :                 idxa0 = ja+i+0;
    8680           0 :                 idxa1 = ja+i+1;
    8681           0 :                 idxa2 = ja+i+2;
    8682           0 :                 idxa3 = ja+i+3;
    8683           0 :                 offsa = ia;
    8684           0 :                 idxb0 = jb+j+0;
    8685           0 :                 idxb1 = jb+j+1;
    8686           0 :                 idxb2 = jb+j+2;
    8687           0 :                 idxb3 = jb+j+3;
    8688           0 :                 offsb = ib;
    8689           0 :                 v00 = 0.0;
    8690           0 :                 v01 = 0.0;
    8691           0 :                 v02 = 0.0;
    8692           0 :                 v03 = 0.0;
    8693           0 :                 v10 = 0.0;
    8694           0 :                 v11 = 0.0;
    8695           0 :                 v12 = 0.0;
    8696           0 :                 v13 = 0.0;
    8697           0 :                 v20 = 0.0;
    8698           0 :                 v21 = 0.0;
    8699           0 :                 v22 = 0.0;
    8700           0 :                 v23 = 0.0;
    8701           0 :                 v30 = 0.0;
    8702           0 :                 v31 = 0.0;
    8703           0 :                 v32 = 0.0;
    8704           0 :                 v33 = 0.0;
    8705           0 :                 for(t=0; t<=k-1; t++)
    8706             :                 {
    8707           0 :                     a0 = a->ptr.pp_double[offsa][idxa0];
    8708           0 :                     a1 = a->ptr.pp_double[offsa][idxa1];
    8709           0 :                     b0 = b->ptr.pp_double[offsb][idxb0];
    8710           0 :                     b1 = b->ptr.pp_double[offsb][idxb1];
    8711           0 :                     v00 = v00+a0*b0;
    8712           0 :                     v01 = v01+a0*b1;
    8713           0 :                     v10 = v10+a1*b0;
    8714           0 :                     v11 = v11+a1*b1;
    8715           0 :                     a2 = a->ptr.pp_double[offsa][idxa2];
    8716           0 :                     a3 = a->ptr.pp_double[offsa][idxa3];
    8717           0 :                     v20 = v20+a2*b0;
    8718           0 :                     v21 = v21+a2*b1;
    8719           0 :                     v30 = v30+a3*b0;
    8720           0 :                     v31 = v31+a3*b1;
    8721           0 :                     b2 = b->ptr.pp_double[offsb][idxb2];
    8722           0 :                     b3 = b->ptr.pp_double[offsb][idxb3];
    8723           0 :                     v22 = v22+a2*b2;
    8724           0 :                     v23 = v23+a2*b3;
    8725           0 :                     v32 = v32+a3*b2;
    8726           0 :                     v33 = v33+a3*b3;
    8727           0 :                     v02 = v02+a0*b2;
    8728           0 :                     v03 = v03+a0*b3;
    8729           0 :                     v12 = v12+a1*b2;
    8730           0 :                     v13 = v13+a1*b3;
    8731           0 :                     offsa = offsa+1;
    8732           0 :                     offsb = offsb+1;
    8733             :                 }
    8734           0 :                 if( ae_fp_eq(beta,(double)(0)) )
    8735             :                 {
    8736           0 :                     c->ptr.pp_double[ic+i+0][jc+j+0] = alpha*v00;
    8737           0 :                     c->ptr.pp_double[ic+i+0][jc+j+1] = alpha*v01;
    8738           0 :                     c->ptr.pp_double[ic+i+0][jc+j+2] = alpha*v02;
    8739           0 :                     c->ptr.pp_double[ic+i+0][jc+j+3] = alpha*v03;
    8740           0 :                     c->ptr.pp_double[ic+i+1][jc+j+0] = alpha*v10;
    8741           0 :                     c->ptr.pp_double[ic+i+1][jc+j+1] = alpha*v11;
    8742           0 :                     c->ptr.pp_double[ic+i+1][jc+j+2] = alpha*v12;
    8743           0 :                     c->ptr.pp_double[ic+i+1][jc+j+3] = alpha*v13;
    8744           0 :                     c->ptr.pp_double[ic+i+2][jc+j+0] = alpha*v20;
    8745           0 :                     c->ptr.pp_double[ic+i+2][jc+j+1] = alpha*v21;
    8746           0 :                     c->ptr.pp_double[ic+i+2][jc+j+2] = alpha*v22;
    8747           0 :                     c->ptr.pp_double[ic+i+2][jc+j+3] = alpha*v23;
    8748           0 :                     c->ptr.pp_double[ic+i+3][jc+j+0] = alpha*v30;
    8749           0 :                     c->ptr.pp_double[ic+i+3][jc+j+1] = alpha*v31;
    8750           0 :                     c->ptr.pp_double[ic+i+3][jc+j+2] = alpha*v32;
    8751           0 :                     c->ptr.pp_double[ic+i+3][jc+j+3] = alpha*v33;
    8752             :                 }
    8753             :                 else
    8754             :                 {
    8755           0 :                     c->ptr.pp_double[ic+i+0][jc+j+0] = beta*c->ptr.pp_double[ic+i+0][jc+j+0]+alpha*v00;
    8756           0 :                     c->ptr.pp_double[ic+i+0][jc+j+1] = beta*c->ptr.pp_double[ic+i+0][jc+j+1]+alpha*v01;
    8757           0 :                     c->ptr.pp_double[ic+i+0][jc+j+2] = beta*c->ptr.pp_double[ic+i+0][jc+j+2]+alpha*v02;
    8758           0 :                     c->ptr.pp_double[ic+i+0][jc+j+3] = beta*c->ptr.pp_double[ic+i+0][jc+j+3]+alpha*v03;
    8759           0 :                     c->ptr.pp_double[ic+i+1][jc+j+0] = beta*c->ptr.pp_double[ic+i+1][jc+j+0]+alpha*v10;
    8760           0 :                     c->ptr.pp_double[ic+i+1][jc+j+1] = beta*c->ptr.pp_double[ic+i+1][jc+j+1]+alpha*v11;
    8761           0 :                     c->ptr.pp_double[ic+i+1][jc+j+2] = beta*c->ptr.pp_double[ic+i+1][jc+j+2]+alpha*v12;
    8762           0 :                     c->ptr.pp_double[ic+i+1][jc+j+3] = beta*c->ptr.pp_double[ic+i+1][jc+j+3]+alpha*v13;
    8763           0 :                     c->ptr.pp_double[ic+i+2][jc+j+0] = beta*c->ptr.pp_double[ic+i+2][jc+j+0]+alpha*v20;
    8764           0 :                     c->ptr.pp_double[ic+i+2][jc+j+1] = beta*c->ptr.pp_double[ic+i+2][jc+j+1]+alpha*v21;
    8765           0 :                     c->ptr.pp_double[ic+i+2][jc+j+2] = beta*c->ptr.pp_double[ic+i+2][jc+j+2]+alpha*v22;
    8766           0 :                     c->ptr.pp_double[ic+i+2][jc+j+3] = beta*c->ptr.pp_double[ic+i+2][jc+j+3]+alpha*v23;
    8767           0 :                     c->ptr.pp_double[ic+i+3][jc+j+0] = beta*c->ptr.pp_double[ic+i+3][jc+j+0]+alpha*v30;
    8768           0 :                     c->ptr.pp_double[ic+i+3][jc+j+1] = beta*c->ptr.pp_double[ic+i+3][jc+j+1]+alpha*v31;
    8769           0 :                     c->ptr.pp_double[ic+i+3][jc+j+2] = beta*c->ptr.pp_double[ic+i+3][jc+j+2]+alpha*v32;
    8770           0 :                     c->ptr.pp_double[ic+i+3][jc+j+3] = beta*c->ptr.pp_double[ic+i+3][jc+j+3]+alpha*v33;
    8771             :                 }
    8772             :             }
    8773             :             else
    8774             :             {
    8775             :                 
    8776             :                 /*
    8777             :                  * Determine submatrix [I0..I1]x[J0..J1] to process
    8778             :                  */
    8779           0 :                 i0 = i;
    8780           0 :                 i1 = ae_minint(i+3, m-1, _state);
    8781           0 :                 j0 = j;
    8782           0 :                 j1 = ae_minint(j+3, n-1, _state);
    8783             :                 
    8784             :                 /*
    8785             :                  * Process submatrix
    8786             :                  */
    8787           0 :                 for(ik=i0; ik<=i1; ik++)
    8788             :                 {
    8789           0 :                     for(jk=j0; jk<=j1; jk++)
    8790             :                     {
    8791           0 :                         if( k==0||ae_fp_eq(alpha,(double)(0)) )
    8792             :                         {
    8793           0 :                             v = (double)(0);
    8794             :                         }
    8795             :                         else
    8796             :                         {
    8797           0 :                             v = 0.0;
    8798           0 :                             v = ae_v_dotproduct(&a->ptr.pp_double[ia][ja+ik], a->stride, &b->ptr.pp_double[ib][jb+jk], b->stride, ae_v_len(ia,ia+k-1));
    8799             :                         }
    8800           0 :                         if( ae_fp_eq(beta,(double)(0)) )
    8801             :                         {
    8802           0 :                             c->ptr.pp_double[ic+ik][jc+jk] = alpha*v;
    8803             :                         }
    8804             :                         else
    8805             :                         {
    8806           0 :                             c->ptr.pp_double[ic+ik][jc+jk] = beta*c->ptr.pp_double[ic+ik][jc+jk]+alpha*v;
    8807             :                         }
    8808             :                     }
    8809             :                 }
    8810             :             }
    8811           0 :             j = j+4;
    8812             :         }
    8813           0 :         i = i+4;
    8814             :     }
    8815             : }
    8816             : 
    8817             : 
    8818             : /*************************************************************************
    8819             : RMatrixGEMM kernel, basecase code for RMatrixGEMM, specialized for sitation
    8820             : with OpTypeA=1 and OpTypeB=1.
    8821             : 
    8822             : Additional info:
    8823             : * this function requires that Alpha<>0 (assertion is thrown otherwise)
    8824             : 
    8825             : INPUT PARAMETERS
    8826             :     M       -   matrix size, M>0
    8827             :     N       -   matrix size, N>0
    8828             :     K       -   matrix size, K>0
    8829             :     Alpha   -   coefficient
    8830             :     A       -   matrix
    8831             :     IA      -   submatrix offset
    8832             :     JA      -   submatrix offset
    8833             :     B       -   matrix
    8834             :     IB      -   submatrix offset
    8835             :     JB      -   submatrix offset
    8836             :     Beta    -   coefficient
    8837             :     C       -   PREALLOCATED output matrix
    8838             :     IC      -   submatrix offset
    8839             :     JC      -   submatrix offset
    8840             : 
    8841             :   -- ALGLIB routine --
    8842             :      27.03.2013
    8843             :      Bochkanov Sergey
    8844             : *************************************************************************/
    8845           0 : void rmatrixgemmk44v11(ae_int_t m,
    8846             :      ae_int_t n,
    8847             :      ae_int_t k,
    8848             :      double alpha,
    8849             :      /* Real    */ ae_matrix* a,
    8850             :      ae_int_t ia,
    8851             :      ae_int_t ja,
    8852             :      /* Real    */ ae_matrix* b,
    8853             :      ae_int_t ib,
    8854             :      ae_int_t jb,
    8855             :      double beta,
    8856             :      /* Real    */ ae_matrix* c,
    8857             :      ae_int_t ic,
    8858             :      ae_int_t jc,
    8859             :      ae_state *_state)
    8860             : {
    8861             :     ae_int_t i;
    8862             :     ae_int_t j;
    8863             :     double v;
    8864             :     double v00;
    8865             :     double v01;
    8866             :     double v02;
    8867             :     double v03;
    8868             :     double v10;
    8869             :     double v11;
    8870             :     double v12;
    8871             :     double v13;
    8872             :     double v20;
    8873             :     double v21;
    8874             :     double v22;
    8875             :     double v23;
    8876             :     double v30;
    8877             :     double v31;
    8878             :     double v32;
    8879             :     double v33;
    8880             :     double a0;
    8881             :     double a1;
    8882             :     double a2;
    8883             :     double a3;
    8884             :     double b0;
    8885             :     double b1;
    8886             :     double b2;
    8887             :     double b3;
    8888             :     ae_int_t idxa0;
    8889             :     ae_int_t idxa1;
    8890             :     ae_int_t idxa2;
    8891             :     ae_int_t idxa3;
    8892             :     ae_int_t idxb0;
    8893             :     ae_int_t idxb1;
    8894             :     ae_int_t idxb2;
    8895             :     ae_int_t idxb3;
    8896             :     ae_int_t i0;
    8897             :     ae_int_t i1;
    8898             :     ae_int_t ik;
    8899             :     ae_int_t j0;
    8900             :     ae_int_t j1;
    8901             :     ae_int_t jk;
    8902             :     ae_int_t t;
    8903             :     ae_int_t offsa;
    8904             :     ae_int_t offsb;
    8905             : 
    8906             : 
    8907           0 :     ae_assert(ae_fp_neq(alpha,(double)(0)), "RMatrixGEMMK44V00: internal error (Alpha=0)", _state);
    8908             :     
    8909             :     /*
    8910             :      * if matrix size is zero
    8911             :      */
    8912           0 :     if( m==0||n==0 )
    8913             :     {
    8914           0 :         return;
    8915             :     }
    8916             :     
    8917             :     /*
    8918             :      * A'*B'
    8919             :      */
    8920           0 :     i = 0;
    8921           0 :     while(i<m)
    8922             :     {
    8923           0 :         j = 0;
    8924           0 :         while(j<n)
    8925             :         {
    8926             :             
    8927             :             /*
    8928             :              * Choose between specialized 4x4 code and general code
    8929             :              */
    8930           0 :             if( i+4<=m&&j+4<=n )
    8931             :             {
    8932             :                 
    8933             :                 /*
    8934             :                  * Specialized 4x4 code for [I..I+3]x[J..J+3] submatrix of C.
    8935             :                  *
    8936             :                  * This submatrix is calculated as sum of K rank-1 products,
    8937             :                  * with operands cached in local variables in order to speed
    8938             :                  * up operations with arrays.
    8939             :                  */
    8940           0 :                 idxa0 = ja+i+0;
    8941           0 :                 idxa1 = ja+i+1;
    8942           0 :                 idxa2 = ja+i+2;
    8943           0 :                 idxa3 = ja+i+3;
    8944           0 :                 offsa = ia;
    8945           0 :                 idxb0 = ib+j+0;
    8946           0 :                 idxb1 = ib+j+1;
    8947           0 :                 idxb2 = ib+j+2;
    8948           0 :                 idxb3 = ib+j+3;
    8949           0 :                 offsb = jb;
    8950           0 :                 v00 = 0.0;
    8951           0 :                 v01 = 0.0;
    8952           0 :                 v02 = 0.0;
    8953           0 :                 v03 = 0.0;
    8954           0 :                 v10 = 0.0;
    8955           0 :                 v11 = 0.0;
    8956           0 :                 v12 = 0.0;
    8957           0 :                 v13 = 0.0;
    8958           0 :                 v20 = 0.0;
    8959           0 :                 v21 = 0.0;
    8960           0 :                 v22 = 0.0;
    8961           0 :                 v23 = 0.0;
    8962           0 :                 v30 = 0.0;
    8963           0 :                 v31 = 0.0;
    8964           0 :                 v32 = 0.0;
    8965           0 :                 v33 = 0.0;
    8966           0 :                 for(t=0; t<=k-1; t++)
    8967             :                 {
    8968           0 :                     a0 = a->ptr.pp_double[offsa][idxa0];
    8969           0 :                     a1 = a->ptr.pp_double[offsa][idxa1];
    8970           0 :                     b0 = b->ptr.pp_double[idxb0][offsb];
    8971           0 :                     b1 = b->ptr.pp_double[idxb1][offsb];
    8972           0 :                     v00 = v00+a0*b0;
    8973           0 :                     v01 = v01+a0*b1;
    8974           0 :                     v10 = v10+a1*b0;
    8975           0 :                     v11 = v11+a1*b1;
    8976           0 :                     a2 = a->ptr.pp_double[offsa][idxa2];
    8977           0 :                     a3 = a->ptr.pp_double[offsa][idxa3];
    8978           0 :                     v20 = v20+a2*b0;
    8979           0 :                     v21 = v21+a2*b1;
    8980           0 :                     v30 = v30+a3*b0;
    8981           0 :                     v31 = v31+a3*b1;
    8982           0 :                     b2 = b->ptr.pp_double[idxb2][offsb];
    8983           0 :                     b3 = b->ptr.pp_double[idxb3][offsb];
    8984           0 :                     v22 = v22+a2*b2;
    8985           0 :                     v23 = v23+a2*b3;
    8986           0 :                     v32 = v32+a3*b2;
    8987           0 :                     v33 = v33+a3*b3;
    8988           0 :                     v02 = v02+a0*b2;
    8989           0 :                     v03 = v03+a0*b3;
    8990           0 :                     v12 = v12+a1*b2;
    8991           0 :                     v13 = v13+a1*b3;
    8992           0 :                     offsa = offsa+1;
    8993           0 :                     offsb = offsb+1;
    8994             :                 }
    8995           0 :                 if( ae_fp_eq(beta,(double)(0)) )
    8996             :                 {
    8997           0 :                     c->ptr.pp_double[ic+i+0][jc+j+0] = alpha*v00;
    8998           0 :                     c->ptr.pp_double[ic+i+0][jc+j+1] = alpha*v01;
    8999           0 :                     c->ptr.pp_double[ic+i+0][jc+j+2] = alpha*v02;
    9000           0 :                     c->ptr.pp_double[ic+i+0][jc+j+3] = alpha*v03;
    9001           0 :                     c->ptr.pp_double[ic+i+1][jc+j+0] = alpha*v10;
    9002           0 :                     c->ptr.pp_double[ic+i+1][jc+j+1] = alpha*v11;
    9003           0 :                     c->ptr.pp_double[ic+i+1][jc+j+2] = alpha*v12;
    9004           0 :                     c->ptr.pp_double[ic+i+1][jc+j+3] = alpha*v13;
    9005           0 :                     c->ptr.pp_double[ic+i+2][jc+j+0] = alpha*v20;
    9006           0 :                     c->ptr.pp_double[ic+i+2][jc+j+1] = alpha*v21;
    9007           0 :                     c->ptr.pp_double[ic+i+2][jc+j+2] = alpha*v22;
    9008           0 :                     c->ptr.pp_double[ic+i+2][jc+j+3] = alpha*v23;
    9009           0 :                     c->ptr.pp_double[ic+i+3][jc+j+0] = alpha*v30;
    9010           0 :                     c->ptr.pp_double[ic+i+3][jc+j+1] = alpha*v31;
    9011           0 :                     c->ptr.pp_double[ic+i+3][jc+j+2] = alpha*v32;
    9012           0 :                     c->ptr.pp_double[ic+i+3][jc+j+3] = alpha*v33;
    9013             :                 }
    9014             :                 else
    9015             :                 {
    9016           0 :                     c->ptr.pp_double[ic+i+0][jc+j+0] = beta*c->ptr.pp_double[ic+i+0][jc+j+0]+alpha*v00;
    9017           0 :                     c->ptr.pp_double[ic+i+0][jc+j+1] = beta*c->ptr.pp_double[ic+i+0][jc+j+1]+alpha*v01;
    9018           0 :                     c->ptr.pp_double[ic+i+0][jc+j+2] = beta*c->ptr.pp_double[ic+i+0][jc+j+2]+alpha*v02;
    9019           0 :                     c->ptr.pp_double[ic+i+0][jc+j+3] = beta*c->ptr.pp_double[ic+i+0][jc+j+3]+alpha*v03;
    9020           0 :                     c->ptr.pp_double[ic+i+1][jc+j+0] = beta*c->ptr.pp_double[ic+i+1][jc+j+0]+alpha*v10;
    9021           0 :                     c->ptr.pp_double[ic+i+1][jc+j+1] = beta*c->ptr.pp_double[ic+i+1][jc+j+1]+alpha*v11;
    9022           0 :                     c->ptr.pp_double[ic+i+1][jc+j+2] = beta*c->ptr.pp_double[ic+i+1][jc+j+2]+alpha*v12;
    9023           0 :                     c->ptr.pp_double[ic+i+1][jc+j+3] = beta*c->ptr.pp_double[ic+i+1][jc+j+3]+alpha*v13;
    9024           0 :                     c->ptr.pp_double[ic+i+2][jc+j+0] = beta*c->ptr.pp_double[ic+i+2][jc+j+0]+alpha*v20;
    9025           0 :                     c->ptr.pp_double[ic+i+2][jc+j+1] = beta*c->ptr.pp_double[ic+i+2][jc+j+1]+alpha*v21;
    9026           0 :                     c->ptr.pp_double[ic+i+2][jc+j+2] = beta*c->ptr.pp_double[ic+i+2][jc+j+2]+alpha*v22;
    9027           0 :                     c->ptr.pp_double[ic+i+2][jc+j+3] = beta*c->ptr.pp_double[ic+i+2][jc+j+3]+alpha*v23;
    9028           0 :                     c->ptr.pp_double[ic+i+3][jc+j+0] = beta*c->ptr.pp_double[ic+i+3][jc+j+0]+alpha*v30;
    9029           0 :                     c->ptr.pp_double[ic+i+3][jc+j+1] = beta*c->ptr.pp_double[ic+i+3][jc+j+1]+alpha*v31;
    9030           0 :                     c->ptr.pp_double[ic+i+3][jc+j+2] = beta*c->ptr.pp_double[ic+i+3][jc+j+2]+alpha*v32;
    9031           0 :                     c->ptr.pp_double[ic+i+3][jc+j+3] = beta*c->ptr.pp_double[ic+i+3][jc+j+3]+alpha*v33;
    9032             :                 }
    9033             :             }
    9034             :             else
    9035             :             {
    9036             :                 
    9037             :                 /*
    9038             :                  * Determine submatrix [I0..I1]x[J0..J1] to process
    9039             :                  */
    9040           0 :                 i0 = i;
    9041           0 :                 i1 = ae_minint(i+3, m-1, _state);
    9042           0 :                 j0 = j;
    9043           0 :                 j1 = ae_minint(j+3, n-1, _state);
    9044             :                 
    9045             :                 /*
    9046             :                  * Process submatrix
    9047             :                  */
    9048           0 :                 for(ik=i0; ik<=i1; ik++)
    9049             :                 {
    9050           0 :                     for(jk=j0; jk<=j1; jk++)
    9051             :                     {
    9052           0 :                         if( k==0||ae_fp_eq(alpha,(double)(0)) )
    9053             :                         {
    9054           0 :                             v = (double)(0);
    9055             :                         }
    9056             :                         else
    9057             :                         {
    9058           0 :                             v = 0.0;
    9059           0 :                             v = ae_v_dotproduct(&a->ptr.pp_double[ia][ja+ik], a->stride, &b->ptr.pp_double[ib+jk][jb], 1, ae_v_len(ia,ia+k-1));
    9060             :                         }
    9061           0 :                         if( ae_fp_eq(beta,(double)(0)) )
    9062             :                         {
    9063           0 :                             c->ptr.pp_double[ic+ik][jc+jk] = alpha*v;
    9064             :                         }
    9065             :                         else
    9066             :                         {
    9067           0 :                             c->ptr.pp_double[ic+ik][jc+jk] = beta*c->ptr.pp_double[ic+ik][jc+jk]+alpha*v;
    9068             :                         }
    9069             :                     }
    9070             :                 }
    9071             :             }
    9072           0 :             j = j+4;
    9073             :         }
    9074           0 :         i = i+4;
    9075             :     }
    9076             : }
    9077             : 
    9078             : 
    9079             : #endif
    9080             : #if defined(AE_COMPILE_ABLASMKL) || !defined(AE_PARTIAL_BUILD)
    9081             : 
    9082             : 
    9083             : /*************************************************************************
    9084             : MKL-based kernel
    9085             : 
    9086             :   -- ALGLIB routine --
    9087             :      12.10.2017
    9088             :      Bochkanov Sergey
    9089             : *************************************************************************/
    9090           0 : ae_bool rmatrixgermkl(ae_int_t m,
    9091             :      ae_int_t n,
    9092             :      /* Real    */ ae_matrix* a,
    9093             :      ae_int_t ia,
    9094             :      ae_int_t ja,
    9095             :      double alpha,
    9096             :      /* Real    */ ae_vector* u,
    9097             :      ae_int_t iu,
    9098             :      /* Real    */ ae_vector* v,
    9099             :      ae_int_t iv,
    9100             :      ae_state *_state)
    9101             : {
    9102             : #ifndef ALGLIB_INTERCEPTS_MKL
    9103             :     ae_bool result;
    9104             : 
    9105             : 
    9106           0 :     result = ae_false;
    9107           0 :     return result;
    9108             : #else
    9109             :     return _ialglib_i_rmatrixgermkl(m, n, a, ia, ja, alpha, u, iu, v, iv);
    9110             : #endif
    9111             : }
    9112             : 
    9113             : 
    9114             : /*************************************************************************
    9115             : MKL-based kernel
    9116             : 
    9117             :   -- ALGLIB routine --
    9118             :      12.10.2017
    9119             :      Bochkanov Sergey
    9120             : *************************************************************************/
    9121           0 : ae_bool cmatrixrank1mkl(ae_int_t m,
    9122             :      ae_int_t n,
    9123             :      /* Complex */ ae_matrix* a,
    9124             :      ae_int_t ia,
    9125             :      ae_int_t ja,
    9126             :      /* Complex */ ae_vector* u,
    9127             :      ae_int_t iu,
    9128             :      /* Complex */ ae_vector* v,
    9129             :      ae_int_t iv,
    9130             :      ae_state *_state)
    9131             : {
    9132             : #ifndef ALGLIB_INTERCEPTS_MKL
    9133             :     ae_bool result;
    9134             : 
    9135             : 
    9136           0 :     result = ae_false;
    9137           0 :     return result;
    9138             : #else
    9139             :     return _ialglib_i_cmatrixrank1mkl(m, n, a, ia, ja, u, iu, v, iv);
    9140             : #endif
    9141             : }
    9142             : 
    9143             : 
    9144             : /*************************************************************************
    9145             : MKL-based kernel
    9146             : 
    9147             :   -- ALGLIB routine --
    9148             :      12.10.2017
    9149             :      Bochkanov Sergey
    9150             : *************************************************************************/
    9151           0 : ae_bool rmatrixrank1mkl(ae_int_t m,
    9152             :      ae_int_t n,
    9153             :      /* Real    */ ae_matrix* a,
    9154             :      ae_int_t ia,
    9155             :      ae_int_t ja,
    9156             :      /* Real    */ ae_vector* u,
    9157             :      ae_int_t iu,
    9158             :      /* Real    */ ae_vector* v,
    9159             :      ae_int_t iv,
    9160             :      ae_state *_state)
    9161             : {
    9162             : #ifndef ALGLIB_INTERCEPTS_MKL
    9163             :     ae_bool result;
    9164             : 
    9165             : 
    9166           0 :     result = ae_false;
    9167           0 :     return result;
    9168             : #else
    9169             :     return _ialglib_i_rmatrixrank1mkl(m, n, a, ia, ja, u, iu, v, iv);
    9170             : #endif
    9171             : }
    9172             : 
    9173             : 
    9174             : /*************************************************************************
    9175             : MKL-based kernel
    9176             : 
    9177             :   -- ALGLIB routine --
    9178             :      12.10.2017
    9179             :      Bochkanov Sergey
    9180             : *************************************************************************/
    9181           0 : ae_bool cmatrixmvmkl(ae_int_t m,
    9182             :      ae_int_t n,
    9183             :      /* Complex */ ae_matrix* a,
    9184             :      ae_int_t ia,
    9185             :      ae_int_t ja,
    9186             :      ae_int_t opa,
    9187             :      /* Complex */ ae_vector* x,
    9188             :      ae_int_t ix,
    9189             :      /* Complex */ ae_vector* y,
    9190             :      ae_int_t iy,
    9191             :      ae_state *_state)
    9192             : {
    9193             : #ifndef ALGLIB_INTERCEPTS_MKL
    9194             :     ae_bool result;
    9195             : 
    9196             : 
    9197           0 :     result = ae_false;
    9198           0 :     return result;
    9199             : #else
    9200             :     return _ialglib_i_cmatrixmvmkl(m, n, a, ia, ja, opa, x, ix, y, iy);
    9201             : #endif
    9202             : }
    9203             : 
    9204             : 
    9205             : /*************************************************************************
    9206             : MKL-based kernel
    9207             : 
    9208             :   -- ALGLIB routine --
    9209             :      12.10.2017
    9210             :      Bochkanov Sergey
    9211             : *************************************************************************/
    9212           0 : ae_bool rmatrixmvmkl(ae_int_t m,
    9213             :      ae_int_t n,
    9214             :      /* Real    */ ae_matrix* a,
    9215             :      ae_int_t ia,
    9216             :      ae_int_t ja,
    9217             :      ae_int_t opa,
    9218             :      /* Real    */ ae_vector* x,
    9219             :      ae_int_t ix,
    9220             :      /* Real    */ ae_vector* y,
    9221             :      ae_int_t iy,
    9222             :      ae_state *_state)
    9223             : {
    9224             : #ifndef ALGLIB_INTERCEPTS_MKL
    9225             :     ae_bool result;
    9226             : 
    9227             : 
    9228           0 :     result = ae_false;
    9229           0 :     return result;
    9230             : #else
    9231             :     return _ialglib_i_rmatrixmvmkl(m, n, a, ia, ja, opa, x, ix, y, iy);
    9232             : #endif
    9233             : }
    9234             : 
    9235             : 
    9236             : /*************************************************************************
    9237             : MKL-based kernel
    9238             : 
    9239             :   -- ALGLIB routine --
    9240             :      12.10.2017
    9241             :      Bochkanov Sergey
    9242             : *************************************************************************/
    9243           0 : ae_bool rmatrixgemvmkl(ae_int_t m,
    9244             :      ae_int_t n,
    9245             :      double alpha,
    9246             :      /* Real    */ ae_matrix* a,
    9247             :      ae_int_t ia,
    9248             :      ae_int_t ja,
    9249             :      ae_int_t opa,
    9250             :      /* Real    */ ae_vector* x,
    9251             :      ae_int_t ix,
    9252             :      double beta,
    9253             :      /* Real    */ ae_vector* y,
    9254             :      ae_int_t iy,
    9255             :      ae_state *_state)
    9256             : {
    9257             : #ifndef ALGLIB_INTERCEPTS_MKL
    9258             :     ae_bool result;
    9259             : 
    9260             : 
    9261           0 :     result = ae_false;
    9262           0 :     return result;
    9263             : #else
    9264             :     return _ialglib_i_rmatrixgemvmkl(m, n, alpha, a, ia, ja, opa, x, ix, beta, y, iy);
    9265             : #endif
    9266             : }
    9267             : 
    9268             : 
    9269             : /*************************************************************************
    9270             : MKL-based kernel
    9271             : 
    9272             :   -- ALGLIB routine --
    9273             :      12.10.2017
    9274             :      Bochkanov Sergey
    9275             : *************************************************************************/
    9276           0 : ae_bool rmatrixtrsvmkl(ae_int_t n,
    9277             :      /* Real    */ ae_matrix* a,
    9278             :      ae_int_t ia,
    9279             :      ae_int_t ja,
    9280             :      ae_bool isupper,
    9281             :      ae_bool isunit,
    9282             :      ae_int_t optype,
    9283             :      /* Real    */ ae_vector* x,
    9284             :      ae_int_t ix,
    9285             :      ae_state *_state)
    9286             : {
    9287             : #ifndef ALGLIB_INTERCEPTS_MKL
    9288             :     ae_bool result;
    9289             : 
    9290             : 
    9291           0 :     result = ae_false;
    9292           0 :     return result;
    9293             : #else
    9294             :     return _ialglib_i_rmatrixtrsvmkl(n, a, ia, ja, isupper, isunit, optype, x, ix);
    9295             : #endif
    9296             : }
    9297             : 
    9298             : 
    9299             : /*************************************************************************
    9300             : MKL-based kernel
    9301             : 
    9302             :   -- ALGLIB routine --
    9303             :      01.10.2013
    9304             :      Bochkanov Sergey
    9305             : *************************************************************************/
    9306           0 : ae_bool rmatrixsyrkmkl(ae_int_t n,
    9307             :      ae_int_t k,
    9308             :      double alpha,
    9309             :      /* Real    */ ae_matrix* a,
    9310             :      ae_int_t ia,
    9311             :      ae_int_t ja,
    9312             :      ae_int_t optypea,
    9313             :      double beta,
    9314             :      /* Real    */ ae_matrix* c,
    9315             :      ae_int_t ic,
    9316             :      ae_int_t jc,
    9317             :      ae_bool isupper,
    9318             :      ae_state *_state)
    9319             : {
    9320             : #ifndef ALGLIB_INTERCEPTS_MKL
    9321             :     ae_bool result;
    9322             : 
    9323             : 
    9324           0 :     result = ae_false;
    9325           0 :     return result;
    9326             : #else
    9327             :     return _ialglib_i_rmatrixsyrkmkl(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper);
    9328             : #endif
    9329             : }
    9330             : 
    9331             : 
    9332             : /*************************************************************************
    9333             : MKL-based kernel
    9334             : 
    9335             :   -- ALGLIB routine --
    9336             :      01.10.2013
    9337             :      Bochkanov Sergey
    9338             : *************************************************************************/
    9339           0 : ae_bool cmatrixherkmkl(ae_int_t n,
    9340             :      ae_int_t k,
    9341             :      double alpha,
    9342             :      /* Complex */ ae_matrix* a,
    9343             :      ae_int_t ia,
    9344             :      ae_int_t ja,
    9345             :      ae_int_t optypea,
    9346             :      double beta,
    9347             :      /* Complex */ ae_matrix* c,
    9348             :      ae_int_t ic,
    9349             :      ae_int_t jc,
    9350             :      ae_bool isupper,
    9351             :      ae_state *_state)
    9352             : {
    9353             : #ifndef ALGLIB_INTERCEPTS_MKL
    9354             :     ae_bool result;
    9355             : 
    9356             : 
    9357           0 :     result = ae_false;
    9358           0 :     return result;
    9359             : #else
    9360             :     return _ialglib_i_cmatrixherkmkl(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper);
    9361             : #endif
    9362             : }
    9363             : 
    9364             : 
    9365             : /*************************************************************************
    9366             : MKL-based kernel
    9367             : 
    9368             :   -- ALGLIB routine --
    9369             :      01.10.2013
    9370             :      Bochkanov Sergey
    9371             : *************************************************************************/
    9372           0 : ae_bool rmatrixgemmmkl(ae_int_t m,
    9373             :      ae_int_t n,
    9374             :      ae_int_t k,
    9375             :      double alpha,
    9376             :      /* Real    */ ae_matrix* a,
    9377             :      ae_int_t ia,
    9378             :      ae_int_t ja,
    9379             :      ae_int_t optypea,
    9380             :      /* Real    */ ae_matrix* b,
    9381             :      ae_int_t ib,
    9382             :      ae_int_t jb,
    9383             :      ae_int_t optypeb,
    9384             :      double beta,
    9385             :      /* Real    */ ae_matrix* c,
    9386             :      ae_int_t ic,
    9387             :      ae_int_t jc,
    9388             :      ae_state *_state)
    9389             : {
    9390             : #ifndef ALGLIB_INTERCEPTS_MKL
    9391             :     ae_bool result;
    9392             : 
    9393             : 
    9394           0 :     result = ae_false;
    9395           0 :     return result;
    9396             : #else
    9397             :     return _ialglib_i_rmatrixgemmmkl(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc);
    9398             : #endif
    9399             : }
    9400             : 
    9401             : 
    9402             : /*************************************************************************
    9403             : MKL-based kernel
    9404             : 
    9405             :   -- ALGLIB routine --
    9406             :      01.10.2017
    9407             :      Bochkanov Sergey
    9408             : *************************************************************************/
    9409           0 : ae_bool rmatrixsymvmkl(ae_int_t n,
    9410             :      double alpha,
    9411             :      /* Real    */ ae_matrix* a,
    9412             :      ae_int_t ia,
    9413             :      ae_int_t ja,
    9414             :      ae_bool isupper,
    9415             :      /* Real    */ ae_vector* x,
    9416             :      ae_int_t ix,
    9417             :      double beta,
    9418             :      /* Real    */ ae_vector* y,
    9419             :      ae_int_t iy,
    9420             :      ae_state *_state)
    9421             : {
    9422             : #ifndef ALGLIB_INTERCEPTS_MKL
    9423             :     ae_bool result;
    9424             : 
    9425             : 
    9426           0 :     result = ae_false;
    9427           0 :     return result;
    9428             : #else
    9429             :     return _ialglib_i_rmatrixsymvmkl(n, alpha, a, ia, ja, isupper, x, ix, beta, y, iy);
    9430             : #endif
    9431             : }
    9432             : 
    9433             : 
    9434             : /*************************************************************************
    9435             : MKL-based kernel
    9436             : 
    9437             :   -- ALGLIB routine --
    9438             :      16.10.2014
    9439             :      Bochkanov Sergey
    9440             : *************************************************************************/
    9441           0 : ae_bool cmatrixgemmmkl(ae_int_t m,
    9442             :      ae_int_t n,
    9443             :      ae_int_t k,
    9444             :      ae_complex alpha,
    9445             :      /* Complex */ ae_matrix* a,
    9446             :      ae_int_t ia,
    9447             :      ae_int_t ja,
    9448             :      ae_int_t optypea,
    9449             :      /* Complex */ ae_matrix* b,
    9450             :      ae_int_t ib,
    9451             :      ae_int_t jb,
    9452             :      ae_int_t optypeb,
    9453             :      ae_complex beta,
    9454             :      /* Complex */ ae_matrix* c,
    9455             :      ae_int_t ic,
    9456             :      ae_int_t jc,
    9457             :      ae_state *_state)
    9458             : {
    9459             : #ifndef ALGLIB_INTERCEPTS_MKL
    9460             :     ae_bool result;
    9461             : 
    9462             : 
    9463           0 :     result = ae_false;
    9464           0 :     return result;
    9465             : #else
    9466             :     return _ialglib_i_cmatrixgemmmkl(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc);
    9467             : #endif
    9468             : }
    9469             : 
    9470             : 
    9471             : /*************************************************************************
    9472             : MKL-based kernel
    9473             : 
    9474             :   -- ALGLIB routine --
    9475             :      16.10.2014
    9476             :      Bochkanov Sergey
    9477             : *************************************************************************/
    9478           0 : ae_bool cmatrixlefttrsmmkl(ae_int_t m,
    9479             :      ae_int_t n,
    9480             :      /* Complex */ ae_matrix* a,
    9481             :      ae_int_t i1,
    9482             :      ae_int_t j1,
    9483             :      ae_bool isupper,
    9484             :      ae_bool isunit,
    9485             :      ae_int_t optype,
    9486             :      /* Complex */ ae_matrix* x,
    9487             :      ae_int_t i2,
    9488             :      ae_int_t j2,
    9489             :      ae_state *_state)
    9490             : {
    9491             : #ifndef ALGLIB_INTERCEPTS_MKL
    9492             :     ae_bool result;
    9493             : 
    9494             : 
    9495           0 :     result = ae_false;
    9496           0 :     return result;
    9497             : #else
    9498             :     return _ialglib_i_cmatrixlefttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2);
    9499             : #endif
    9500             : }
    9501             : 
    9502             : 
    9503             : /*************************************************************************
    9504             : MKL-based kernel
    9505             : 
    9506             :   -- ALGLIB routine --
    9507             :      16.10.2014
    9508             :      Bochkanov Sergey
    9509             : *************************************************************************/
    9510           0 : ae_bool cmatrixrighttrsmmkl(ae_int_t m,
    9511             :      ae_int_t n,
    9512             :      /* Complex */ ae_matrix* a,
    9513             :      ae_int_t i1,
    9514             :      ae_int_t j1,
    9515             :      ae_bool isupper,
    9516             :      ae_bool isunit,
    9517             :      ae_int_t optype,
    9518             :      /* Complex */ ae_matrix* x,
    9519             :      ae_int_t i2,
    9520             :      ae_int_t j2,
    9521             :      ae_state *_state)
    9522             : {
    9523             : #ifndef ALGLIB_INTERCEPTS_MKL
    9524             :     ae_bool result;
    9525             : 
    9526             : 
    9527           0 :     result = ae_false;
    9528           0 :     return result;
    9529             : #else
    9530             :     return _ialglib_i_cmatrixrighttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2);
    9531             : #endif
    9532             : }
    9533             : 
    9534             : 
    9535             : /*************************************************************************
    9536             : MKL-based kernel
    9537             : 
    9538             :   -- ALGLIB routine --
    9539             :      16.10.2014
    9540             :      Bochkanov Sergey
    9541             : *************************************************************************/
    9542           0 : ae_bool rmatrixlefttrsmmkl(ae_int_t m,
    9543             :      ae_int_t n,
    9544             :      /* Real    */ ae_matrix* a,
    9545             :      ae_int_t i1,
    9546             :      ae_int_t j1,
    9547             :      ae_bool isupper,
    9548             :      ae_bool isunit,
    9549             :      ae_int_t optype,
    9550             :      /* Real    */ ae_matrix* x,
    9551             :      ae_int_t i2,
    9552             :      ae_int_t j2,
    9553             :      ae_state *_state)
    9554             : {
    9555             : #ifndef ALGLIB_INTERCEPTS_MKL
    9556             :     ae_bool result;
    9557             : 
    9558             : 
    9559           0 :     result = ae_false;
    9560           0 :     return result;
    9561             : #else
    9562             :     return _ialglib_i_rmatrixlefttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2);
    9563             : #endif
    9564             : }
    9565             : 
    9566             : 
    9567             : /*************************************************************************
    9568             : MKL-based kernel
    9569             : 
    9570             :   -- ALGLIB routine --
    9571             :      16.10.2014
    9572             :      Bochkanov Sergey
    9573             : *************************************************************************/
    9574           0 : ae_bool rmatrixrighttrsmmkl(ae_int_t m,
    9575             :      ae_int_t n,
    9576             :      /* Real    */ ae_matrix* a,
    9577             :      ae_int_t i1,
    9578             :      ae_int_t j1,
    9579             :      ae_bool isupper,
    9580             :      ae_bool isunit,
    9581             :      ae_int_t optype,
    9582             :      /* Real    */ ae_matrix* x,
    9583             :      ae_int_t i2,
    9584             :      ae_int_t j2,
    9585             :      ae_state *_state)
    9586             : {
    9587             : #ifndef ALGLIB_INTERCEPTS_MKL
    9588             :     ae_bool result;
    9589             : 
    9590             : 
    9591           0 :     result = ae_false;
    9592           0 :     return result;
    9593             : #else
    9594             :     return _ialglib_i_rmatrixrighttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2);
    9595             : #endif
    9596             : }
    9597             : 
    9598             : 
    9599             : /*************************************************************************
    9600             : MKL-based kernel.
    9601             : 
    9602             : NOTE:
    9603             : 
    9604             : if function returned False, CholResult is NOT modified. Not ever referenced!
    9605             : if function returned True, CholResult is set to status of Cholesky decomposition
    9606             : (True on succeess).
    9607             : 
    9608             :   -- ALGLIB routine --
    9609             :      16.10.2014
    9610             :      Bochkanov Sergey
    9611             : *************************************************************************/
    9612           0 : ae_bool spdmatrixcholeskymkl(/* Real    */ ae_matrix* a,
    9613             :      ae_int_t offs,
    9614             :      ae_int_t n,
    9615             :      ae_bool isupper,
    9616             :      ae_bool* cholresult,
    9617             :      ae_state *_state)
    9618             : {
    9619             : #ifndef ALGLIB_INTERCEPTS_MKL
    9620             :     ae_bool result;
    9621             : 
    9622             : 
    9623           0 :     result = ae_false;
    9624           0 :     return result;
    9625             : #else
    9626             :     return _ialglib_i_spdmatrixcholeskymkl(a, offs, n, isupper, cholresult);
    9627             : #endif
    9628             : }
    9629             : 
    9630             : 
    9631             : /*************************************************************************
    9632             : MKL-based kernel.
    9633             : 
    9634             :   -- ALGLIB routine --
    9635             :      20.10.2014
    9636             :      Bochkanov Sergey
    9637             : *************************************************************************/
    9638           0 : ae_bool rmatrixplumkl(/* Real    */ ae_matrix* a,
    9639             :      ae_int_t offs,
    9640             :      ae_int_t m,
    9641             :      ae_int_t n,
    9642             :      /* Integer */ ae_vector* pivots,
    9643             :      ae_state *_state)
    9644             : {
    9645             : #ifndef ALGLIB_INTERCEPTS_MKL
    9646             :     ae_bool result;
    9647             : 
    9648             : 
    9649           0 :     result = ae_false;
    9650           0 :     return result;
    9651             : #else
    9652             :     return _ialglib_i_rmatrixplumkl(a, offs, m, n, pivots);
    9653             : #endif
    9654             : }
    9655             : 
    9656             : 
    9657             : /*************************************************************************
    9658             : MKL-based kernel.
    9659             : 
    9660             : NOTE: this function needs preallocated output/temporary arrays.
    9661             :       D and E must be at least max(M,N)-wide.
    9662             : 
    9663             :   -- ALGLIB routine --
    9664             :      20.10.2014
    9665             :      Bochkanov Sergey
    9666             : *************************************************************************/
    9667           0 : ae_bool rmatrixbdmkl(/* Real    */ ae_matrix* a,
    9668             :      ae_int_t m,
    9669             :      ae_int_t n,
    9670             :      /* Real    */ ae_vector* d,
    9671             :      /* Real    */ ae_vector* e,
    9672             :      /* Real    */ ae_vector* tauq,
    9673             :      /* Real    */ ae_vector* taup,
    9674             :      ae_state *_state)
    9675             : {
    9676             : #ifndef ALGLIB_INTERCEPTS_MKL
    9677             :     ae_bool result;
    9678             : 
    9679             : 
    9680           0 :     result = ae_false;
    9681           0 :     return result;
    9682             : #else
    9683             :     return _ialglib_i_rmatrixbdmkl(a, m, n, d, e, tauq, taup);
    9684             : #endif
    9685             : }
    9686             : 
    9687             : 
    9688             : /*************************************************************************
    9689             : MKL-based kernel.
    9690             : 
    9691             : If ByQ is True,  TauP is not used (can be empty array).
    9692             : If ByQ is False, TauQ is not used (can be empty array).
    9693             : 
    9694             :   -- ALGLIB routine --
    9695             :      20.10.2014
    9696             :      Bochkanov Sergey
    9697             : *************************************************************************/
    9698           0 : ae_bool rmatrixbdmultiplybymkl(/* Real    */ ae_matrix* qp,
    9699             :      ae_int_t m,
    9700             :      ae_int_t n,
    9701             :      /* Real    */ ae_vector* tauq,
    9702             :      /* Real    */ ae_vector* taup,
    9703             :      /* Real    */ ae_matrix* z,
    9704             :      ae_int_t zrows,
    9705             :      ae_int_t zcolumns,
    9706             :      ae_bool byq,
    9707             :      ae_bool fromtheright,
    9708             :      ae_bool dotranspose,
    9709             :      ae_state *_state)
    9710             : {
    9711             : #ifndef ALGLIB_INTERCEPTS_MKL
    9712             :     ae_bool result;
    9713             : 
    9714             : 
    9715           0 :     result = ae_false;
    9716           0 :     return result;
    9717             : #else
    9718             :     return _ialglib_i_rmatrixbdmultiplybymkl(qp, m, n, tauq, taup, z, zrows, zcolumns, byq, fromtheright, dotranspose);
    9719             : #endif
    9720             : }
    9721             : 
    9722             : 
    9723             : /*************************************************************************
    9724             : MKL-based kernel.
    9725             : 
    9726             : NOTE: Tau must be preallocated array with at least N-1 elements.
    9727             : 
    9728             :   -- ALGLIB routine --
    9729             :      20.10.2014
    9730             :      Bochkanov Sergey
    9731             : *************************************************************************/
    9732           0 : ae_bool rmatrixhessenbergmkl(/* Real    */ ae_matrix* a,
    9733             :      ae_int_t n,
    9734             :      /* Real    */ ae_vector* tau,
    9735             :      ae_state *_state)
    9736             : {
    9737             : #ifndef ALGLIB_INTERCEPTS_MKL
    9738             :     ae_bool result;
    9739             : 
    9740             : 
    9741           0 :     result = ae_false;
    9742           0 :     return result;
    9743             : #else
    9744             :     return _ialglib_i_rmatrixhessenbergmkl(a, n, tau);
    9745             : #endif
    9746             : }
    9747             : 
    9748             : 
    9749             : /*************************************************************************
    9750             : MKL-based kernel.
    9751             : 
    9752             : NOTE: Q must be preallocated N*N array
    9753             : 
    9754             :   -- ALGLIB routine --
    9755             :      20.10.2014
    9756             :      Bochkanov Sergey
    9757             : *************************************************************************/
    9758           0 : ae_bool rmatrixhessenbergunpackqmkl(/* Real    */ ae_matrix* a,
    9759             :      ae_int_t n,
    9760             :      /* Real    */ ae_vector* tau,
    9761             :      /* Real    */ ae_matrix* q,
    9762             :      ae_state *_state)
    9763             : {
    9764             : #ifndef ALGLIB_INTERCEPTS_MKL
    9765             :     ae_bool result;
    9766             : 
    9767             : 
    9768           0 :     result = ae_false;
    9769           0 :     return result;
    9770             : #else
    9771             :     return _ialglib_i_rmatrixhessenbergunpackqmkl(a, n, tau, q);
    9772             : #endif
    9773             : }
    9774             : 
    9775             : 
    9776             : /*************************************************************************
    9777             : MKL-based kernel.
    9778             : 
    9779             : NOTE: Tau, D, E must be preallocated arrays;
    9780             :       length(E)=length(Tau)=N-1 (or larger)
    9781             :       length(D)=N (or larger)
    9782             : 
    9783             :   -- ALGLIB routine --
    9784             :      20.10.2014
    9785             :      Bochkanov Sergey
    9786             : *************************************************************************/
    9787           0 : ae_bool smatrixtdmkl(/* Real    */ ae_matrix* a,
    9788             :      ae_int_t n,
    9789             :      ae_bool isupper,
    9790             :      /* Real    */ ae_vector* tau,
    9791             :      /* Real    */ ae_vector* d,
    9792             :      /* Real    */ ae_vector* e,
    9793             :      ae_state *_state)
    9794             : {
    9795             : #ifndef ALGLIB_INTERCEPTS_MKL
    9796             :     ae_bool result;
    9797             : 
    9798             : 
    9799           0 :     result = ae_false;
    9800           0 :     return result;
    9801             : #else
    9802             :     return _ialglib_i_smatrixtdmkl(a, n, isupper, tau, d, e);
    9803             : #endif
    9804             : }
    9805             : 
    9806             : 
    9807             : /*************************************************************************
    9808             : MKL-based kernel.
    9809             : 
    9810             : NOTE: Q must be preallocated N*N array
    9811             : 
    9812             :   -- ALGLIB routine --
    9813             :      20.10.2014
    9814             :      Bochkanov Sergey
    9815             : *************************************************************************/
    9816           0 : ae_bool smatrixtdunpackqmkl(/* Real    */ ae_matrix* a,
    9817             :      ae_int_t n,
    9818             :      ae_bool isupper,
    9819             :      /* Real    */ ae_vector* tau,
    9820             :      /* Real    */ ae_matrix* q,
    9821             :      ae_state *_state)
    9822             : {
    9823             : #ifndef ALGLIB_INTERCEPTS_MKL
    9824             :     ae_bool result;
    9825             : 
    9826             : 
    9827           0 :     result = ae_false;
    9828           0 :     return result;
    9829             : #else
    9830             :     return _ialglib_i_smatrixtdunpackqmkl(a, n, isupper, tau, q);
    9831             : #endif
    9832             : }
    9833             : 
    9834             : 
    9835             : /*************************************************************************
    9836             : MKL-based kernel.
    9837             : 
    9838             : NOTE: Tau, D, E must be preallocated arrays;
    9839             :       length(E)=length(Tau)=N-1 (or larger)
    9840             :       length(D)=N (or larger)
    9841             : 
    9842             :   -- ALGLIB routine --
    9843             :      20.10.2014
    9844             :      Bochkanov Sergey
    9845             : *************************************************************************/
    9846           0 : ae_bool hmatrixtdmkl(/* Complex */ ae_matrix* a,
    9847             :      ae_int_t n,
    9848             :      ae_bool isupper,
    9849             :      /* Complex */ ae_vector* tau,
    9850             :      /* Real    */ ae_vector* d,
    9851             :      /* Real    */ ae_vector* e,
    9852             :      ae_state *_state)
    9853             : {
    9854             : #ifndef ALGLIB_INTERCEPTS_MKL
    9855             :     ae_bool result;
    9856             : 
    9857             : 
    9858           0 :     result = ae_false;
    9859           0 :     return result;
    9860             : #else
    9861             :     return _ialglib_i_hmatrixtdmkl(a, n, isupper, tau, d, e);
    9862             : #endif
    9863             : }
    9864             : 
    9865             : 
    9866             : /*************************************************************************
    9867             : MKL-based kernel.
    9868             : 
    9869             : NOTE: Q must be preallocated N*N array
    9870             : 
    9871             :   -- ALGLIB routine --
    9872             :      20.10.2014
    9873             :      Bochkanov Sergey
    9874             : *************************************************************************/
    9875           0 : ae_bool hmatrixtdunpackqmkl(/* Complex */ ae_matrix* a,
    9876             :      ae_int_t n,
    9877             :      ae_bool isupper,
    9878             :      /* Complex */ ae_vector* tau,
    9879             :      /* Complex */ ae_matrix* q,
    9880             :      ae_state *_state)
    9881             : {
    9882             : #ifndef ALGLIB_INTERCEPTS_MKL
    9883             :     ae_bool result;
    9884             : 
    9885             : 
    9886           0 :     result = ae_false;
    9887           0 :     return result;
    9888             : #else
    9889             :     return _ialglib_i_hmatrixtdunpackqmkl(a, n, isupper, tau, q);
    9890             : #endif
    9891             : }
    9892             : 
    9893             : 
    9894             : /*************************************************************************
    9895             : MKL-based kernel.
    9896             : 
    9897             : Returns True if MKL was present and handled request (MKL  completion  code
    9898             : is returned as separate output parameter).
    9899             : 
    9900             : D and E are pre-allocated arrays with length N (both of them!). On output,
    9901             : D constraints singular values, and E is destroyed.
    9902             : 
    9903             : SVDResult is modified if and only if MKL is present.
    9904             : 
    9905             :   -- ALGLIB routine --
    9906             :      20.10.2014
    9907             :      Bochkanov Sergey
    9908             : *************************************************************************/
    9909           0 : ae_bool rmatrixbdsvdmkl(/* Real    */ ae_vector* d,
    9910             :      /* Real    */ ae_vector* e,
    9911             :      ae_int_t n,
    9912             :      ae_bool isupper,
    9913             :      /* Real    */ ae_matrix* u,
    9914             :      ae_int_t nru,
    9915             :      /* Real    */ ae_matrix* c,
    9916             :      ae_int_t ncc,
    9917             :      /* Real    */ ae_matrix* vt,
    9918             :      ae_int_t ncvt,
    9919             :      ae_bool* svdresult,
    9920             :      ae_state *_state)
    9921             : {
    9922             : #ifndef ALGLIB_INTERCEPTS_MKL
    9923             :     ae_bool result;
    9924             : 
    9925             : 
    9926           0 :     result = ae_false;
    9927           0 :     return result;
    9928             : #else
    9929             :     return _ialglib_i_rmatrixbdsvdmkl(d, e, n, isupper, u, nru, c, ncc, vt, ncvt, svdresult);
    9930             : #endif
    9931             : }
    9932             : 
    9933             : 
    9934             : /*************************************************************************
    9935             : MKL-based DHSEQR kernel.
    9936             : 
    9937             : Returns True if MKL was present and handled request.
    9938             : 
    9939             : WR and WI are pre-allocated arrays with length N.
    9940             : Z is pre-allocated array[N,N].
    9941             : 
    9942             :   -- ALGLIB routine --
    9943             :      20.10.2014
    9944             :      Bochkanov Sergey
    9945             : *************************************************************************/
    9946           0 : ae_bool rmatrixinternalschurdecompositionmkl(/* Real    */ ae_matrix* h,
    9947             :      ae_int_t n,
    9948             :      ae_int_t tneeded,
    9949             :      ae_int_t zneeded,
    9950             :      /* Real    */ ae_vector* wr,
    9951             :      /* Real    */ ae_vector* wi,
    9952             :      /* Real    */ ae_matrix* z,
    9953             :      ae_int_t* info,
    9954             :      ae_state *_state)
    9955             : {
    9956             : #ifndef ALGLIB_INTERCEPTS_MKL
    9957             :     ae_bool result;
    9958             : 
    9959             : 
    9960           0 :     result = ae_false;
    9961           0 :     return result;
    9962             : #else
    9963             :     return _ialglib_i_rmatrixinternalschurdecompositionmkl(h, n, tneeded, zneeded, wr, wi, z, info);
    9964             : #endif
    9965             : }
    9966             : 
    9967             : 
    9968             : /*************************************************************************
    9969             : MKL-based DTREVC kernel.
    9970             : 
    9971             : Returns True if MKL was present and handled request.
    9972             : 
    9973             : NOTE: this function does NOT support HOWMNY=3!!!!
    9974             : 
    9975             : VL and VR are pre-allocated arrays with length N*N, if required. If particalar
    9976             : variables is not required, it can be dummy (empty) array.
    9977             : 
    9978             :   -- ALGLIB routine --
    9979             :      20.10.2014
    9980             :      Bochkanov Sergey
    9981             : *************************************************************************/
    9982           0 : ae_bool rmatrixinternaltrevcmkl(/* Real    */ ae_matrix* t,
    9983             :      ae_int_t n,
    9984             :      ae_int_t side,
    9985             :      ae_int_t howmny,
    9986             :      /* Real    */ ae_matrix* vl,
    9987             :      /* Real    */ ae_matrix* vr,
    9988             :      ae_int_t* m,
    9989             :      ae_int_t* info,
    9990             :      ae_state *_state)
    9991             : {
    9992             : #ifndef ALGLIB_INTERCEPTS_MKL
    9993             :     ae_bool result;
    9994             : 
    9995             : 
    9996           0 :     result = ae_false;
    9997           0 :     return result;
    9998             : #else
    9999             :     return _ialglib_i_rmatrixinternaltrevcmkl(t, n, side, howmny, vl, vr, m, info);
   10000             : #endif
   10001             : }
   10002             : 
   10003             : 
   10004             : /*************************************************************************
   10005             : MKL-based kernel.
   10006             : 
   10007             : Returns True if MKL was present and handled request (MKL  completion  code
   10008             : is returned as separate output parameter).
   10009             : 
   10010             : D and E are pre-allocated arrays with length N (both of them!). On output,
   10011             : D constraints eigenvalues, and E is destroyed.
   10012             : 
   10013             : Z is preallocated array[N,N] for ZNeeded<>0; ignored for ZNeeded=0.
   10014             : 
   10015             : EVDResult is modified if and only if MKL is present.
   10016             : 
   10017             :   -- ALGLIB routine --
   10018             :      20.10.2014
   10019             :      Bochkanov Sergey
   10020             : *************************************************************************/
   10021           0 : ae_bool smatrixtdevdmkl(/* Real    */ ae_vector* d,
   10022             :      /* Real    */ ae_vector* e,
   10023             :      ae_int_t n,
   10024             :      ae_int_t zneeded,
   10025             :      /* Real    */ ae_matrix* z,
   10026             :      ae_bool* evdresult,
   10027             :      ae_state *_state)
   10028             : {
   10029             : #ifndef ALGLIB_INTERCEPTS_MKL
   10030             :     ae_bool result;
   10031             : 
   10032             : 
   10033           0 :     result = ae_false;
   10034           0 :     return result;
   10035             : #else
   10036             :     return _ialglib_i_smatrixtdevdmkl(d, e, n, zneeded, z, evdresult);
   10037             : #endif
   10038             : }
   10039             : 
   10040             : 
   10041             : /*************************************************************************
   10042             : MKL-based kernel.
   10043             : 
   10044             : Returns True if MKL was present and handled request (MKL  completion  code
   10045             : is returned as separate output parameter).
   10046             : 
   10047             : D and E are pre-allocated arrays with length N (both of them!). On output,
   10048             : D constraints eigenvalues, and E is destroyed.
   10049             : 
   10050             : Z is preallocated array[N,N] for ZNeeded<>0; ignored for ZNeeded=0.
   10051             : 
   10052             : EVDResult is modified if and only if MKL is present.
   10053             : 
   10054             :   -- ALGLIB routine --
   10055             :      20.10.2014
   10056             :      Bochkanov Sergey
   10057             : *************************************************************************/
   10058           0 : ae_bool sparsegemvcrsmkl(ae_int_t opa,
   10059             :      ae_int_t arows,
   10060             :      ae_int_t acols,
   10061             :      double alpha,
   10062             :      /* Real    */ ae_vector* vals,
   10063             :      /* Integer */ ae_vector* cidx,
   10064             :      /* Integer */ ae_vector* ridx,
   10065             :      /* Real    */ ae_vector* x,
   10066             :      ae_int_t ix,
   10067             :      double beta,
   10068             :      /* Real    */ ae_vector* y,
   10069             :      ae_int_t iy,
   10070             :      ae_state *_state)
   10071             : {
   10072             : #ifndef ALGLIB_INTERCEPTS_MKL
   10073             :     ae_bool result;
   10074             : 
   10075             : 
   10076           0 :     result = ae_false;
   10077           0 :     return result;
   10078             : #else
   10079             :     return _ialglib_i_sparsegemvcrsmkl(opa, arows, acols, alpha, vals, cidx, ridx, x, ix, beta, y, iy);
   10080             : #endif
   10081             : }
   10082             : 
   10083             : 
   10084             : #endif
   10085             : #if defined(AE_COMPILE_CREFLECTIONS) || !defined(AE_PARTIAL_BUILD)
   10086             : 
   10087             : 
   10088             : /*************************************************************************
   10089             : Generation of an elementary complex reflection transformation
   10090             : 
   10091             : The subroutine generates elementary complex reflection H of  order  N,  so
   10092             : that, for a given X, the following equality holds true:
   10093             : 
   10094             :      ( X(1) )   ( Beta )
   10095             : H' * (  ..  ) = (  0   ),   H'*H = I,   Beta is a real number
   10096             :      ( X(n) )   (  0   )
   10097             : 
   10098             : where
   10099             : 
   10100             :               ( V(1) )
   10101             : H = 1 - Tau * (  ..  ) * ( conj(V(1)), ..., conj(V(n)) )
   10102             :               ( V(n) )
   10103             : 
   10104             : where the first component of vector V equals 1.
   10105             : 
   10106             : Input parameters:
   10107             :     X   -   vector. Array with elements [1..N].
   10108             :     N   -   reflection order.
   10109             : 
   10110             : Output parameters:
   10111             :     X   -   components from 2 to N are replaced by vector V.
   10112             :             The first component is replaced with parameter Beta.
   10113             :     Tau -   scalar value Tau.
   10114             : 
   10115             : This subroutine is the modification of CLARFG subroutines  from the LAPACK
   10116             : library. It has similar functionality except for the fact that it  doesn't
   10117             : handle errors when intermediate results cause an overflow.
   10118             : 
   10119             :   -- LAPACK auxiliary routine (version 3.0) --
   10120             :      Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
   10121             :      Courant Institute, Argonne National Lab, and Rice University
   10122             :      September 30, 1994
   10123             : *************************************************************************/
   10124           0 : void complexgeneratereflection(/* Complex */ ae_vector* x,
   10125             :      ae_int_t n,
   10126             :      ae_complex* tau,
   10127             :      ae_state *_state)
   10128             : {
   10129             :     ae_int_t j;
   10130             :     ae_complex alpha;
   10131             :     double alphi;
   10132             :     double alphr;
   10133             :     double beta;
   10134             :     double xnorm;
   10135             :     double mx;
   10136             :     ae_complex t;
   10137             :     double s;
   10138             :     ae_complex v;
   10139             : 
   10140           0 :     tau->x = 0;
   10141           0 :     tau->y = 0;
   10142             : 
   10143           0 :     if( n<=0 )
   10144             :     {
   10145           0 :         *tau = ae_complex_from_i(0);
   10146           0 :         return;
   10147             :     }
   10148             :     
   10149             :     /*
   10150             :      * Scale if needed (to avoid overflow/underflow during intermediate
   10151             :      * calculations).
   10152             :      */
   10153           0 :     mx = (double)(0);
   10154           0 :     for(j=1; j<=n; j++)
   10155             :     {
   10156           0 :         mx = ae_maxreal(ae_c_abs(x->ptr.p_complex[j], _state), mx, _state);
   10157             :     }
   10158           0 :     s = (double)(1);
   10159           0 :     if( ae_fp_neq(mx,(double)(0)) )
   10160             :     {
   10161           0 :         if( ae_fp_less(mx,(double)(1)) )
   10162             :         {
   10163           0 :             s = ae_sqrt(ae_minrealnumber, _state);
   10164           0 :             v = ae_complex_from_d(1/s);
   10165           0 :             ae_v_cmulc(&x->ptr.p_complex[1], 1, ae_v_len(1,n), v);
   10166             :         }
   10167             :         else
   10168             :         {
   10169           0 :             s = ae_sqrt(ae_maxrealnumber, _state);
   10170           0 :             v = ae_complex_from_d(1/s);
   10171           0 :             ae_v_cmulc(&x->ptr.p_complex[1], 1, ae_v_len(1,n), v);
   10172             :         }
   10173             :     }
   10174             :     
   10175             :     /*
   10176             :      * calculate
   10177             :      */
   10178           0 :     alpha = x->ptr.p_complex[1];
   10179           0 :     mx = (double)(0);
   10180           0 :     for(j=2; j<=n; j++)
   10181             :     {
   10182           0 :         mx = ae_maxreal(ae_c_abs(x->ptr.p_complex[j], _state), mx, _state);
   10183             :     }
   10184           0 :     xnorm = (double)(0);
   10185           0 :     if( ae_fp_neq(mx,(double)(0)) )
   10186             :     {
   10187           0 :         for(j=2; j<=n; j++)
   10188             :         {
   10189           0 :             t = ae_c_div_d(x->ptr.p_complex[j],mx);
   10190           0 :             xnorm = xnorm+ae_c_mul(t,ae_c_conj(t, _state)).x;
   10191             :         }
   10192           0 :         xnorm = ae_sqrt(xnorm, _state)*mx;
   10193             :     }
   10194           0 :     alphr = alpha.x;
   10195           0 :     alphi = alpha.y;
   10196           0 :     if( ae_fp_eq(xnorm,(double)(0))&&ae_fp_eq(alphi,(double)(0)) )
   10197             :     {
   10198           0 :         *tau = ae_complex_from_i(0);
   10199           0 :         x->ptr.p_complex[1] = ae_c_mul_d(x->ptr.p_complex[1],s);
   10200           0 :         return;
   10201             :     }
   10202           0 :     mx = ae_maxreal(ae_fabs(alphr, _state), ae_fabs(alphi, _state), _state);
   10203           0 :     mx = ae_maxreal(mx, ae_fabs(xnorm, _state), _state);
   10204           0 :     beta = -mx*ae_sqrt(ae_sqr(alphr/mx, _state)+ae_sqr(alphi/mx, _state)+ae_sqr(xnorm/mx, _state), _state);
   10205           0 :     if( ae_fp_less(alphr,(double)(0)) )
   10206             :     {
   10207           0 :         beta = -beta;
   10208             :     }
   10209           0 :     tau->x = (beta-alphr)/beta;
   10210           0 :     tau->y = -alphi/beta;
   10211           0 :     alpha = ae_c_d_div(1,ae_c_sub_d(alpha,beta));
   10212           0 :     if( n>1 )
   10213             :     {
   10214           0 :         ae_v_cmulc(&x->ptr.p_complex[2], 1, ae_v_len(2,n), alpha);
   10215             :     }
   10216           0 :     alpha = ae_complex_from_d(beta);
   10217           0 :     x->ptr.p_complex[1] = alpha;
   10218             :     
   10219             :     /*
   10220             :      * Scale back
   10221             :      */
   10222           0 :     x->ptr.p_complex[1] = ae_c_mul_d(x->ptr.p_complex[1],s);
   10223             : }
   10224             : 
   10225             : 
   10226             : /*************************************************************************
   10227             : Application of an elementary reflection to a rectangular matrix of size MxN
   10228             : 
   10229             : The  algorithm  pre-multiplies  the  matrix  by  an  elementary reflection
   10230             : transformation  which  is  given  by  column  V  and  scalar  Tau (see the
   10231             : description of the GenerateReflection). Not the whole matrix  but  only  a
   10232             : part of it is transformed (rows from M1 to M2, columns from N1 to N2). Only
   10233             : the elements of this submatrix are changed.
   10234             : 
   10235             : Note: the matrix is multiplied by H, not by H'.   If  it  is  required  to
   10236             : multiply the matrix by H', it is necessary to pass Conj(Tau) instead of Tau.
   10237             : 
   10238             : Input parameters:
   10239             :     C       -   matrix to be transformed.
   10240             :     Tau     -   scalar defining transformation.
   10241             :     V       -   column defining transformation.
   10242             :                 Array whose index ranges within [1..M2-M1+1]
   10243             :     M1, M2  -   range of rows to be transformed.
   10244             :     N1, N2  -   range of columns to be transformed.
   10245             :     WORK    -   working array whose index goes from N1 to N2.
   10246             : 
   10247             : Output parameters:
   10248             :     C       -   the result of multiplying the input matrix C by the
   10249             :                 transformation matrix which is given by Tau and V.
   10250             :                 If N1>N2 or M1>M2, C is not modified.
   10251             : 
   10252             :   -- LAPACK auxiliary routine (version 3.0) --
   10253             :      Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
   10254             :      Courant Institute, Argonne National Lab, and Rice University
   10255             :      September 30, 1994
   10256             : *************************************************************************/
   10257           0 : void complexapplyreflectionfromtheleft(/* Complex */ ae_matrix* c,
   10258             :      ae_complex tau,
   10259             :      /* Complex */ ae_vector* v,
   10260             :      ae_int_t m1,
   10261             :      ae_int_t m2,
   10262             :      ae_int_t n1,
   10263             :      ae_int_t n2,
   10264             :      /* Complex */ ae_vector* work,
   10265             :      ae_state *_state)
   10266             : {
   10267             :     ae_complex t;
   10268             :     ae_int_t i;
   10269             : 
   10270             : 
   10271           0 :     if( (ae_c_eq_d(tau,(double)(0))||n1>n2)||m1>m2 )
   10272             :     {
   10273           0 :         return;
   10274             :     }
   10275             :     
   10276             :     /*
   10277             :      * w := C^T * conj(v)
   10278             :      */
   10279           0 :     for(i=n1; i<=n2; i++)
   10280             :     {
   10281           0 :         work->ptr.p_complex[i] = ae_complex_from_i(0);
   10282             :     }
   10283           0 :     for(i=m1; i<=m2; i++)
   10284             :     {
   10285           0 :         t = ae_c_conj(v->ptr.p_complex[i+1-m1], _state);
   10286           0 :         ae_v_caddc(&work->ptr.p_complex[n1], 1, &c->ptr.pp_complex[i][n1], 1, "N", ae_v_len(n1,n2), t);
   10287             :     }
   10288             :     
   10289             :     /*
   10290             :      * C := C - tau * v * w^T
   10291             :      */
   10292           0 :     for(i=m1; i<=m2; i++)
   10293             :     {
   10294           0 :         t = ae_c_mul(v->ptr.p_complex[i-m1+1],tau);
   10295           0 :         ae_v_csubc(&c->ptr.pp_complex[i][n1], 1, &work->ptr.p_complex[n1], 1, "N", ae_v_len(n1,n2), t);
   10296             :     }
   10297             : }
   10298             : 
   10299             : 
   10300             : /*************************************************************************
   10301             : Application of an elementary reflection to a rectangular matrix of size MxN
   10302             : 
   10303             : The  algorithm  post-multiplies  the  matrix  by  an elementary reflection
   10304             : transformation  which  is  given  by  column  V  and  scalar  Tau (see the
   10305             : description  of  the  GenerateReflection). Not the whole matrix but only a
   10306             : part  of  it  is  transformed (rows from M1 to M2, columns from N1 to N2).
   10307             : Only the elements of this submatrix are changed.
   10308             : 
   10309             : Input parameters:
   10310             :     C       -   matrix to be transformed.
   10311             :     Tau     -   scalar defining transformation.
   10312             :     V       -   column defining transformation.
   10313             :                 Array whose index ranges within [1..N2-N1+1]
   10314             :     M1, M2  -   range of rows to be transformed.
   10315             :     N1, N2  -   range of columns to be transformed.
   10316             :     WORK    -   working array whose index goes from M1 to M2.
   10317             : 
   10318             : Output parameters:
   10319             :     C       -   the result of multiplying the input matrix C by the
   10320             :                 transformation matrix which is given by Tau and V.
   10321             :                 If N1>N2 or M1>M2, C is not modified.
   10322             : 
   10323             :   -- LAPACK auxiliary routine (version 3.0) --
   10324             :      Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
   10325             :      Courant Institute, Argonne National Lab, and Rice University
   10326             :      September 30, 1994
   10327             : *************************************************************************/
   10328           0 : void complexapplyreflectionfromtheright(/* Complex */ ae_matrix* c,
   10329             :      ae_complex tau,
   10330             :      /* Complex */ ae_vector* v,
   10331             :      ae_int_t m1,
   10332             :      ae_int_t m2,
   10333             :      ae_int_t n1,
   10334             :      ae_int_t n2,
   10335             :      /* Complex */ ae_vector* work,
   10336             :      ae_state *_state)
   10337             : {
   10338             :     ae_complex t;
   10339             :     ae_int_t i;
   10340             :     ae_int_t vm;
   10341             : 
   10342             : 
   10343           0 :     if( (ae_c_eq_d(tau,(double)(0))||n1>n2)||m1>m2 )
   10344             :     {
   10345           0 :         return;
   10346             :     }
   10347             :     
   10348             :     /*
   10349             :      * w := C * v
   10350             :      */
   10351           0 :     vm = n2-n1+1;
   10352           0 :     for(i=m1; i<=m2; i++)
   10353             :     {
   10354           0 :         t = ae_v_cdotproduct(&c->ptr.pp_complex[i][n1], 1, "N", &v->ptr.p_complex[1], 1, "N", ae_v_len(n1,n2));
   10355           0 :         work->ptr.p_complex[i] = t;
   10356             :     }
   10357             :     
   10358             :     /*
   10359             :      * C := C - w * conj(v^T)
   10360             :      */
   10361           0 :     ae_v_cmove(&v->ptr.p_complex[1], 1, &v->ptr.p_complex[1], 1, "Conj", ae_v_len(1,vm));
   10362           0 :     for(i=m1; i<=m2; i++)
   10363             :     {
   10364           0 :         t = ae_c_mul(work->ptr.p_complex[i],tau);
   10365           0 :         ae_v_csubc(&c->ptr.pp_complex[i][n1], 1, &v->ptr.p_complex[1], 1, "N", ae_v_len(n1,n2), t);
   10366             :     }
   10367           0 :     ae_v_cmove(&v->ptr.p_complex[1], 1, &v->ptr.p_complex[1], 1, "Conj", ae_v_len(1,vm));
   10368             : }
   10369             : 
   10370             : 
   10371             : #endif
   10372             : #if defined(AE_COMPILE_ROTATIONS) || !defined(AE_PARTIAL_BUILD)
   10373             : 
   10374             : 
   10375             : /*************************************************************************
   10376             : Application of a sequence of  elementary rotations to a matrix
   10377             : 
   10378             : The algorithm pre-multiplies the matrix by a sequence of rotation
   10379             : transformations which is given by arrays C and S. Depending on the value
   10380             : of the IsForward parameter either 1 and 2, 3 and 4 and so on (if IsForward=true)
   10381             : rows are rotated, or the rows N and N-1, N-2 and N-3 and so on, are rotated.
   10382             : 
   10383             : Not the whole matrix but only a part of it is transformed (rows from M1 to
   10384             : M2, columns from N1 to N2). Only the elements of this submatrix are changed.
   10385             : 
   10386             : Input parameters:
   10387             :     IsForward   -   the sequence of the rotation application.
   10388             :     M1,M2       -   the range of rows to be transformed.
   10389             :     N1, N2      -   the range of columns to be transformed.
   10390             :     C,S         -   transformation coefficients.
   10391             :                     Array whose index ranges within [1..M2-M1].
   10392             :     A           -   processed matrix.
   10393             :     WORK        -   working array whose index ranges within [N1..N2].
   10394             : 
   10395             : Output parameters:
   10396             :     A           -   transformed matrix.
   10397             : 
   10398             : Utility subroutine.
   10399             : *************************************************************************/
   10400           0 : void applyrotationsfromtheleft(ae_bool isforward,
   10401             :      ae_int_t m1,
   10402             :      ae_int_t m2,
   10403             :      ae_int_t n1,
   10404             :      ae_int_t n2,
   10405             :      /* Real    */ ae_vector* c,
   10406             :      /* Real    */ ae_vector* s,
   10407             :      /* Real    */ ae_matrix* a,
   10408             :      /* Real    */ ae_vector* work,
   10409             :      ae_state *_state)
   10410             : {
   10411             :     ae_int_t j;
   10412             :     ae_int_t jp1;
   10413             :     double ctemp;
   10414             :     double stemp;
   10415             :     double temp;
   10416             : 
   10417             : 
   10418           0 :     if( m1>m2||n1>n2 )
   10419             :     {
   10420           0 :         return;
   10421             :     }
   10422             :     
   10423             :     /*
   10424             :      * Form  P * A
   10425             :      */
   10426           0 :     if( isforward )
   10427             :     {
   10428           0 :         if( n1!=n2 )
   10429             :         {
   10430             :             
   10431             :             /*
   10432             :              * Common case: N1<>N2
   10433             :              */
   10434           0 :             for(j=m1; j<=m2-1; j++)
   10435             :             {
   10436           0 :                 ctemp = c->ptr.p_double[j-m1+1];
   10437           0 :                 stemp = s->ptr.p_double[j-m1+1];
   10438           0 :                 if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) )
   10439             :                 {
   10440           0 :                     jp1 = j+1;
   10441           0 :                     ae_v_moved(&work->ptr.p_double[n1], 1, &a->ptr.pp_double[jp1][n1], 1, ae_v_len(n1,n2), ctemp);
   10442           0 :                     ae_v_subd(&work->ptr.p_double[n1], 1, &a->ptr.pp_double[j][n1], 1, ae_v_len(n1,n2), stemp);
   10443           0 :                     ae_v_muld(&a->ptr.pp_double[j][n1], 1, ae_v_len(n1,n2), ctemp);
   10444           0 :                     ae_v_addd(&a->ptr.pp_double[j][n1], 1, &a->ptr.pp_double[jp1][n1], 1, ae_v_len(n1,n2), stemp);
   10445           0 :                     ae_v_move(&a->ptr.pp_double[jp1][n1], 1, &work->ptr.p_double[n1], 1, ae_v_len(n1,n2));
   10446             :                 }
   10447             :             }
   10448             :         }
   10449             :         else
   10450             :         {
   10451             :             
   10452             :             /*
   10453             :              * Special case: N1=N2
   10454             :              */
   10455           0 :             for(j=m1; j<=m2-1; j++)
   10456             :             {
   10457           0 :                 ctemp = c->ptr.p_double[j-m1+1];
   10458           0 :                 stemp = s->ptr.p_double[j-m1+1];
   10459           0 :                 if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) )
   10460             :                 {
   10461           0 :                     temp = a->ptr.pp_double[j+1][n1];
   10462           0 :                     a->ptr.pp_double[j+1][n1] = ctemp*temp-stemp*a->ptr.pp_double[j][n1];
   10463           0 :                     a->ptr.pp_double[j][n1] = stemp*temp+ctemp*a->ptr.pp_double[j][n1];
   10464             :                 }
   10465             :             }
   10466             :         }
   10467             :     }
   10468             :     else
   10469             :     {
   10470           0 :         if( n1!=n2 )
   10471             :         {
   10472             :             
   10473             :             /*
   10474             :              * Common case: N1<>N2
   10475             :              */
   10476           0 :             for(j=m2-1; j>=m1; j--)
   10477             :             {
   10478           0 :                 ctemp = c->ptr.p_double[j-m1+1];
   10479           0 :                 stemp = s->ptr.p_double[j-m1+1];
   10480           0 :                 if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) )
   10481             :                 {
   10482           0 :                     jp1 = j+1;
   10483           0 :                     ae_v_moved(&work->ptr.p_double[n1], 1, &a->ptr.pp_double[jp1][n1], 1, ae_v_len(n1,n2), ctemp);
   10484           0 :                     ae_v_subd(&work->ptr.p_double[n1], 1, &a->ptr.pp_double[j][n1], 1, ae_v_len(n1,n2), stemp);
   10485           0 :                     ae_v_muld(&a->ptr.pp_double[j][n1], 1, ae_v_len(n1,n2), ctemp);
   10486           0 :                     ae_v_addd(&a->ptr.pp_double[j][n1], 1, &a->ptr.pp_double[jp1][n1], 1, ae_v_len(n1,n2), stemp);
   10487           0 :                     ae_v_move(&a->ptr.pp_double[jp1][n1], 1, &work->ptr.p_double[n1], 1, ae_v_len(n1,n2));
   10488             :                 }
   10489             :             }
   10490             :         }
   10491             :         else
   10492             :         {
   10493             :             
   10494             :             /*
   10495             :              * Special case: N1=N2
   10496             :              */
   10497           0 :             for(j=m2-1; j>=m1; j--)
   10498             :             {
   10499           0 :                 ctemp = c->ptr.p_double[j-m1+1];
   10500           0 :                 stemp = s->ptr.p_double[j-m1+1];
   10501           0 :                 if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) )
   10502             :                 {
   10503           0 :                     temp = a->ptr.pp_double[j+1][n1];
   10504           0 :                     a->ptr.pp_double[j+1][n1] = ctemp*temp-stemp*a->ptr.pp_double[j][n1];
   10505           0 :                     a->ptr.pp_double[j][n1] = stemp*temp+ctemp*a->ptr.pp_double[j][n1];
   10506             :                 }
   10507             :             }
   10508             :         }
   10509             :     }
   10510             : }
   10511             : 
   10512             : 
   10513             : /*************************************************************************
   10514             : Application of a sequence of  elementary rotations to a matrix
   10515             : 
   10516             : The algorithm post-multiplies the matrix by a sequence of rotation
   10517             : transformations which is given by arrays C and S. Depending on the value
   10518             : of the IsForward parameter either 1 and 2, 3 and 4 and so on (if IsForward=true)
   10519             : rows are rotated, or the rows N and N-1, N-2 and N-3 and so on are rotated.
   10520             : 
   10521             : Not the whole matrix but only a part of it is transformed (rows from M1
   10522             : to M2, columns from N1 to N2). Only the elements of this submatrix are changed.
   10523             : 
   10524             : Input parameters:
   10525             :     IsForward   -   the sequence of the rotation application.
   10526             :     M1,M2       -   the range of rows to be transformed.
   10527             :     N1, N2      -   the range of columns to be transformed.
   10528             :     C,S         -   transformation coefficients.
   10529             :                     Array whose index ranges within [1..N2-N1].
   10530             :     A           -   processed matrix.
   10531             :     WORK        -   working array whose index ranges within [M1..M2].
   10532             : 
   10533             : Output parameters:
   10534             :     A           -   transformed matrix.
   10535             : 
   10536             : Utility subroutine.
   10537             : *************************************************************************/
   10538           0 : void applyrotationsfromtheright(ae_bool isforward,
   10539             :      ae_int_t m1,
   10540             :      ae_int_t m2,
   10541             :      ae_int_t n1,
   10542             :      ae_int_t n2,
   10543             :      /* Real    */ ae_vector* c,
   10544             :      /* Real    */ ae_vector* s,
   10545             :      /* Real    */ ae_matrix* a,
   10546             :      /* Real    */ ae_vector* work,
   10547             :      ae_state *_state)
   10548             : {
   10549             :     ae_int_t j;
   10550             :     ae_int_t jp1;
   10551             :     double ctemp;
   10552             :     double stemp;
   10553             :     double temp;
   10554             : 
   10555             : 
   10556             :     
   10557             :     /*
   10558             :      * Form A * P'
   10559             :      */
   10560           0 :     if( isforward )
   10561             :     {
   10562           0 :         if( m1!=m2 )
   10563             :         {
   10564             :             
   10565             :             /*
   10566             :              * Common case: M1<>M2
   10567             :              */
   10568           0 :             for(j=n1; j<=n2-1; j++)
   10569             :             {
   10570           0 :                 ctemp = c->ptr.p_double[j-n1+1];
   10571           0 :                 stemp = s->ptr.p_double[j-n1+1];
   10572           0 :                 if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) )
   10573             :                 {
   10574           0 :                     jp1 = j+1;
   10575           0 :                     ae_v_moved(&work->ptr.p_double[m1], 1, &a->ptr.pp_double[m1][jp1], a->stride, ae_v_len(m1,m2), ctemp);
   10576           0 :                     ae_v_subd(&work->ptr.p_double[m1], 1, &a->ptr.pp_double[m1][j], a->stride, ae_v_len(m1,m2), stemp);
   10577           0 :                     ae_v_muld(&a->ptr.pp_double[m1][j], a->stride, ae_v_len(m1,m2), ctemp);
   10578           0 :                     ae_v_addd(&a->ptr.pp_double[m1][j], a->stride, &a->ptr.pp_double[m1][jp1], a->stride, ae_v_len(m1,m2), stemp);
   10579           0 :                     ae_v_move(&a->ptr.pp_double[m1][jp1], a->stride, &work->ptr.p_double[m1], 1, ae_v_len(m1,m2));
   10580             :                 }
   10581             :             }
   10582             :         }
   10583             :         else
   10584             :         {
   10585             :             
   10586             :             /*
   10587             :              * Special case: M1=M2
   10588             :              */
   10589           0 :             for(j=n1; j<=n2-1; j++)
   10590             :             {
   10591           0 :                 ctemp = c->ptr.p_double[j-n1+1];
   10592           0 :                 stemp = s->ptr.p_double[j-n1+1];
   10593           0 :                 if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) )
   10594             :                 {
   10595           0 :                     temp = a->ptr.pp_double[m1][j+1];
   10596           0 :                     a->ptr.pp_double[m1][j+1] = ctemp*temp-stemp*a->ptr.pp_double[m1][j];
   10597           0 :                     a->ptr.pp_double[m1][j] = stemp*temp+ctemp*a->ptr.pp_double[m1][j];
   10598             :                 }
   10599             :             }
   10600             :         }
   10601             :     }
   10602             :     else
   10603             :     {
   10604           0 :         if( m1!=m2 )
   10605             :         {
   10606             :             
   10607             :             /*
   10608             :              * Common case: M1<>M2
   10609             :              */
   10610           0 :             for(j=n2-1; j>=n1; j--)
   10611             :             {
   10612           0 :                 ctemp = c->ptr.p_double[j-n1+1];
   10613           0 :                 stemp = s->ptr.p_double[j-n1+1];
   10614           0 :                 if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) )
   10615             :                 {
   10616           0 :                     jp1 = j+1;
   10617           0 :                     ae_v_moved(&work->ptr.p_double[m1], 1, &a->ptr.pp_double[m1][jp1], a->stride, ae_v_len(m1,m2), ctemp);
   10618           0 :                     ae_v_subd(&work->ptr.p_double[m1], 1, &a->ptr.pp_double[m1][j], a->stride, ae_v_len(m1,m2), stemp);
   10619           0 :                     ae_v_muld(&a->ptr.pp_double[m1][j], a->stride, ae_v_len(m1,m2), ctemp);
   10620           0 :                     ae_v_addd(&a->ptr.pp_double[m1][j], a->stride, &a->ptr.pp_double[m1][jp1], a->stride, ae_v_len(m1,m2), stemp);
   10621           0 :                     ae_v_move(&a->ptr.pp_double[m1][jp1], a->stride, &work->ptr.p_double[m1], 1, ae_v_len(m1,m2));
   10622             :                 }
   10623             :             }
   10624             :         }
   10625             :         else
   10626             :         {
   10627             :             
   10628             :             /*
   10629             :              * Special case: M1=M2
   10630             :              */
   10631           0 :             for(j=n2-1; j>=n1; j--)
   10632             :             {
   10633           0 :                 ctemp = c->ptr.p_double[j-n1+1];
   10634           0 :                 stemp = s->ptr.p_double[j-n1+1];
   10635           0 :                 if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) )
   10636             :                 {
   10637           0 :                     temp = a->ptr.pp_double[m1][j+1];
   10638           0 :                     a->ptr.pp_double[m1][j+1] = ctemp*temp-stemp*a->ptr.pp_double[m1][j];
   10639           0 :                     a->ptr.pp_double[m1][j] = stemp*temp+ctemp*a->ptr.pp_double[m1][j];
   10640             :                 }
   10641             :             }
   10642             :         }
   10643             :     }
   10644           0 : }
   10645             : 
   10646             : 
   10647             : /*************************************************************************
   10648             : The subroutine generates the elementary rotation, so that:
   10649             : 
   10650             : [  CS  SN  ]  .  [ F ]  =  [ R ]
   10651             : [ -SN  CS  ]     [ G ]     [ 0 ]
   10652             : 
   10653             : CS**2 + SN**2 = 1
   10654             : *************************************************************************/
   10655           0 : void generaterotation(double f,
   10656             :      double g,
   10657             :      double* cs,
   10658             :      double* sn,
   10659             :      double* r,
   10660             :      ae_state *_state)
   10661             : {
   10662             :     double f1;
   10663             :     double g1;
   10664             : 
   10665           0 :     *cs = 0;
   10666           0 :     *sn = 0;
   10667           0 :     *r = 0;
   10668             : 
   10669           0 :     if( ae_fp_eq(g,(double)(0)) )
   10670             :     {
   10671           0 :         *cs = (double)(1);
   10672           0 :         *sn = (double)(0);
   10673           0 :         *r = f;
   10674             :     }
   10675             :     else
   10676             :     {
   10677           0 :         if( ae_fp_eq(f,(double)(0)) )
   10678             :         {
   10679           0 :             *cs = (double)(0);
   10680           0 :             *sn = (double)(1);
   10681           0 :             *r = g;
   10682             :         }
   10683             :         else
   10684             :         {
   10685           0 :             f1 = f;
   10686           0 :             g1 = g;
   10687           0 :             if( ae_fp_greater(ae_fabs(f1, _state),ae_fabs(g1, _state)) )
   10688             :             {
   10689           0 :                 *r = ae_fabs(f1, _state)*ae_sqrt(1+ae_sqr(g1/f1, _state), _state);
   10690             :             }
   10691             :             else
   10692             :             {
   10693           0 :                 *r = ae_fabs(g1, _state)*ae_sqrt(1+ae_sqr(f1/g1, _state), _state);
   10694             :             }
   10695           0 :             *cs = f1/(*r);
   10696           0 :             *sn = g1/(*r);
   10697           0 :             if( ae_fp_greater(ae_fabs(f, _state),ae_fabs(g, _state))&&ae_fp_less(*cs,(double)(0)) )
   10698             :             {
   10699           0 :                 *cs = -*cs;
   10700           0 :                 *sn = -*sn;
   10701           0 :                 *r = -*r;
   10702             :             }
   10703             :         }
   10704             :     }
   10705           0 : }
   10706             : 
   10707             : 
   10708             : #endif
   10709             : #if defined(AE_COMPILE_TRLINSOLVE) || !defined(AE_PARTIAL_BUILD)
   10710             : 
   10711             : 
   10712             : /*************************************************************************
   10713             : Utility subroutine performing the "safe" solution of system of linear
   10714             : equations with triangular coefficient matrices.
   10715             : 
   10716             : The subroutine uses scaling and solves the scaled system A*x=s*b (where  s
   10717             : is  a  scalar  value)  instead  of  A*x=b,  choosing  s  so  that x can be
   10718             : represented by a floating-point number. The closer the system  gets  to  a
   10719             : singular, the less s is. If the system is singular, s=0 and x contains the
   10720             : non-trivial solution of equation A*x=0.
   10721             : 
   10722             : The feature of an algorithm is that it could not cause an  overflow  or  a
   10723             : division by zero regardless of the matrix used as the input.
   10724             : 
   10725             : The algorithm can solve systems of equations with  upper/lower  triangular
   10726             : matrices,  with/without unit diagonal, and systems of type A*x=b or A'*x=b
   10727             : (where A' is a transposed matrix A).
   10728             : 
   10729             : Input parameters:
   10730             :     A       -   system matrix. Array whose indexes range within [0..N-1, 0..N-1].
   10731             :     N       -   size of matrix A.
   10732             :     X       -   right-hand member of a system.
   10733             :                 Array whose index ranges within [0..N-1].
   10734             :     IsUpper -   matrix type. If it is True, the system matrix is the upper
   10735             :                 triangular and is located in  the  corresponding  part  of
   10736             :                 matrix A.
   10737             :     Trans   -   problem type. If it is True, the problem to be  solved  is
   10738             :                 A'*x=b, otherwise it is A*x=b.
   10739             :     Isunit  -   matrix type. If it is True, the system matrix has  a  unit
   10740             :                 diagonal (the elements on the main diagonal are  not  used
   10741             :                 in the calculation process), otherwise the matrix is considered
   10742             :                 to be a general triangular matrix.
   10743             : 
   10744             : Output parameters:
   10745             :     X       -   solution. Array whose index ranges within [0..N-1].
   10746             :     S       -   scaling factor.
   10747             : 
   10748             :   -- LAPACK auxiliary routine (version 3.0) --
   10749             :      Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
   10750             :      Courant Institute, Argonne National Lab, and Rice University
   10751             :      June 30, 1992
   10752             : *************************************************************************/
   10753           0 : void rmatrixtrsafesolve(/* Real    */ ae_matrix* a,
   10754             :      ae_int_t n,
   10755             :      /* Real    */ ae_vector* x,
   10756             :      double* s,
   10757             :      ae_bool isupper,
   10758             :      ae_bool istrans,
   10759             :      ae_bool isunit,
   10760             :      ae_state *_state)
   10761             : {
   10762             :     ae_frame _frame_block;
   10763             :     ae_bool normin;
   10764             :     ae_vector cnorm;
   10765             :     ae_matrix a1;
   10766             :     ae_vector x1;
   10767             :     ae_int_t i;
   10768             : 
   10769           0 :     ae_frame_make(_state, &_frame_block);
   10770           0 :     memset(&cnorm, 0, sizeof(cnorm));
   10771           0 :     memset(&a1, 0, sizeof(a1));
   10772           0 :     memset(&x1, 0, sizeof(x1));
   10773           0 :     *s = 0;
   10774           0 :     ae_vector_init(&cnorm, 0, DT_REAL, _state, ae_true);
   10775           0 :     ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true);
   10776           0 :     ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
   10777             : 
   10778             :     
   10779             :     /*
   10780             :      * From 0-based to 1-based
   10781             :      */
   10782           0 :     normin = ae_false;
   10783           0 :     ae_matrix_set_length(&a1, n+1, n+1, _state);
   10784           0 :     ae_vector_set_length(&x1, n+1, _state);
   10785           0 :     for(i=1; i<=n; i++)
   10786             :     {
   10787           0 :         ae_v_move(&a1.ptr.pp_double[i][1], 1, &a->ptr.pp_double[i-1][0], 1, ae_v_len(1,n));
   10788             :     }
   10789           0 :     ae_v_move(&x1.ptr.p_double[1], 1, &x->ptr.p_double[0], 1, ae_v_len(1,n));
   10790             :     
   10791             :     /*
   10792             :      * Solve 1-based
   10793             :      */
   10794           0 :     safesolvetriangular(&a1, n, &x1, s, isupper, istrans, isunit, normin, &cnorm, _state);
   10795             :     
   10796             :     /*
   10797             :      * From 1-based to 0-based
   10798             :      */
   10799           0 :     ae_v_move(&x->ptr.p_double[0], 1, &x1.ptr.p_double[1], 1, ae_v_len(0,n-1));
   10800           0 :     ae_frame_leave(_state);
   10801           0 : }
   10802             : 
   10803             : 
   10804             : /*************************************************************************
   10805             : Obsolete 1-based subroutine.
   10806             : See RMatrixTRSafeSolve for 0-based replacement.
   10807             : *************************************************************************/
   10808           0 : void safesolvetriangular(/* Real    */ ae_matrix* a,
   10809             :      ae_int_t n,
   10810             :      /* Real    */ ae_vector* x,
   10811             :      double* s,
   10812             :      ae_bool isupper,
   10813             :      ae_bool istrans,
   10814             :      ae_bool isunit,
   10815             :      ae_bool normin,
   10816             :      /* Real    */ ae_vector* cnorm,
   10817             :      ae_state *_state)
   10818             : {
   10819             :     ae_int_t i;
   10820             :     ae_int_t imax;
   10821             :     ae_int_t j;
   10822             :     ae_int_t jfirst;
   10823             :     ae_int_t jinc;
   10824             :     ae_int_t jlast;
   10825             :     ae_int_t jm1;
   10826             :     ae_int_t jp1;
   10827             :     ae_int_t ip1;
   10828             :     ae_int_t im1;
   10829             :     ae_int_t k;
   10830             :     ae_int_t flg;
   10831             :     double v;
   10832             :     double vd;
   10833             :     double bignum;
   10834             :     double grow;
   10835             :     double rec;
   10836             :     double smlnum;
   10837             :     double sumj;
   10838             :     double tjj;
   10839             :     double tjjs;
   10840             :     double tmax;
   10841             :     double tscal;
   10842             :     double uscal;
   10843             :     double xbnd;
   10844             :     double xj;
   10845             :     double xmax;
   10846             :     ae_bool notran;
   10847             :     ae_bool upper;
   10848             :     ae_bool nounit;
   10849             : 
   10850           0 :     *s = 0;
   10851             : 
   10852           0 :     upper = isupper;
   10853           0 :     notran = !istrans;
   10854           0 :     nounit = !isunit;
   10855             :     
   10856             :     /*
   10857             :      * these initializers are not really necessary,
   10858             :      * but without them compiler complains about uninitialized locals
   10859             :      */
   10860           0 :     tjjs = (double)(0);
   10861             :     
   10862             :     /*
   10863             :      * Quick return if possible
   10864             :      */
   10865           0 :     if( n==0 )
   10866             :     {
   10867           0 :         return;
   10868             :     }
   10869             :     
   10870             :     /*
   10871             :      * Determine machine dependent parameters to control overflow.
   10872             :      */
   10873           0 :     smlnum = ae_minrealnumber/(ae_machineepsilon*2);
   10874           0 :     bignum = 1/smlnum;
   10875           0 :     *s = (double)(1);
   10876           0 :     if( !normin )
   10877             :     {
   10878           0 :         ae_vector_set_length(cnorm, n+1, _state);
   10879             :         
   10880             :         /*
   10881             :          * Compute the 1-norm of each column, not including the diagonal.
   10882             :          */
   10883           0 :         if( upper )
   10884             :         {
   10885             :             
   10886             :             /*
   10887             :              * A is upper triangular.
   10888             :              */
   10889           0 :             for(j=1; j<=n; j++)
   10890             :             {
   10891           0 :                 v = (double)(0);
   10892           0 :                 for(k=1; k<=j-1; k++)
   10893             :                 {
   10894           0 :                     v = v+ae_fabs(a->ptr.pp_double[k][j], _state);
   10895             :                 }
   10896           0 :                 cnorm->ptr.p_double[j] = v;
   10897             :             }
   10898             :         }
   10899             :         else
   10900             :         {
   10901             :             
   10902             :             /*
   10903             :              * A is lower triangular.
   10904             :              */
   10905           0 :             for(j=1; j<=n-1; j++)
   10906             :             {
   10907           0 :                 v = (double)(0);
   10908           0 :                 for(k=j+1; k<=n; k++)
   10909             :                 {
   10910           0 :                     v = v+ae_fabs(a->ptr.pp_double[k][j], _state);
   10911             :                 }
   10912           0 :                 cnorm->ptr.p_double[j] = v;
   10913             :             }
   10914           0 :             cnorm->ptr.p_double[n] = (double)(0);
   10915             :         }
   10916             :     }
   10917             :     
   10918             :     /*
   10919             :      * Scale the column norms by TSCAL if the maximum element in CNORM is
   10920             :      * greater than BIGNUM.
   10921             :      */
   10922           0 :     imax = 1;
   10923           0 :     for(k=2; k<=n; k++)
   10924             :     {
   10925           0 :         if( ae_fp_greater(cnorm->ptr.p_double[k],cnorm->ptr.p_double[imax]) )
   10926             :         {
   10927           0 :             imax = k;
   10928             :         }
   10929             :     }
   10930           0 :     tmax = cnorm->ptr.p_double[imax];
   10931           0 :     if( ae_fp_less_eq(tmax,bignum) )
   10932             :     {
   10933           0 :         tscal = (double)(1);
   10934             :     }
   10935             :     else
   10936             :     {
   10937           0 :         tscal = 1/(smlnum*tmax);
   10938           0 :         ae_v_muld(&cnorm->ptr.p_double[1], 1, ae_v_len(1,n), tscal);
   10939             :     }
   10940             :     
   10941             :     /*
   10942             :      * Compute a bound on the computed solution vector to see if the
   10943             :      * Level 2 BLAS routine DTRSV can be used.
   10944             :      */
   10945           0 :     j = 1;
   10946           0 :     for(k=2; k<=n; k++)
   10947             :     {
   10948           0 :         if( ae_fp_greater(ae_fabs(x->ptr.p_double[k], _state),ae_fabs(x->ptr.p_double[j], _state)) )
   10949             :         {
   10950           0 :             j = k;
   10951             :         }
   10952             :     }
   10953           0 :     xmax = ae_fabs(x->ptr.p_double[j], _state);
   10954           0 :     xbnd = xmax;
   10955           0 :     if( notran )
   10956             :     {
   10957             :         
   10958             :         /*
   10959             :          * Compute the growth in A * x = b.
   10960             :          */
   10961           0 :         if( upper )
   10962             :         {
   10963           0 :             jfirst = n;
   10964           0 :             jlast = 1;
   10965           0 :             jinc = -1;
   10966             :         }
   10967             :         else
   10968             :         {
   10969           0 :             jfirst = 1;
   10970           0 :             jlast = n;
   10971           0 :             jinc = 1;
   10972             :         }
   10973           0 :         if( ae_fp_neq(tscal,(double)(1)) )
   10974             :         {
   10975           0 :             grow = (double)(0);
   10976             :         }
   10977             :         else
   10978             :         {
   10979           0 :             if( nounit )
   10980             :             {
   10981             :                 
   10982             :                 /*
   10983             :                  * A is non-unit triangular.
   10984             :                  *
   10985             :                  * Compute GROW = 1/G(j) and XBND = 1/M(j).
   10986             :                  * Initially, G(0) = max{x(i), i=1,...,n}.
   10987             :                  */
   10988           0 :                 grow = 1/ae_maxreal(xbnd, smlnum, _state);
   10989           0 :                 xbnd = grow;
   10990           0 :                 j = jfirst;
   10991           0 :                 while((jinc>0&&j<=jlast)||(jinc<0&&j>=jlast))
   10992             :                 {
   10993             :                     
   10994             :                     /*
   10995             :                      * Exit the loop if the growth factor is too small.
   10996             :                      */
   10997           0 :                     if( ae_fp_less_eq(grow,smlnum) )
   10998             :                     {
   10999           0 :                         break;
   11000             :                     }
   11001             :                     
   11002             :                     /*
   11003             :                      * M(j) = G(j-1) / abs(A(j,j))
   11004             :                      */
   11005           0 :                     tjj = ae_fabs(a->ptr.pp_double[j][j], _state);
   11006           0 :                     xbnd = ae_minreal(xbnd, ae_minreal((double)(1), tjj, _state)*grow, _state);
   11007           0 :                     if( ae_fp_greater_eq(tjj+cnorm->ptr.p_double[j],smlnum) )
   11008             :                     {
   11009             :                         
   11010             :                         /*
   11011             :                          * G(j) = G(j-1)*( 1 + CNORM(j) / abs(A(j,j)) )
   11012             :                          */
   11013           0 :                         grow = grow*(tjj/(tjj+cnorm->ptr.p_double[j]));
   11014             :                     }
   11015             :                     else
   11016             :                     {
   11017             :                         
   11018             :                         /*
   11019             :                          * G(j) could overflow, set GROW to 0.
   11020             :                          */
   11021           0 :                         grow = (double)(0);
   11022             :                     }
   11023           0 :                     if( j==jlast )
   11024             :                     {
   11025           0 :                         grow = xbnd;
   11026             :                     }
   11027           0 :                     j = j+jinc;
   11028             :                 }
   11029             :             }
   11030             :             else
   11031             :             {
   11032             :                 
   11033             :                 /*
   11034             :                  * A is unit triangular.
   11035             :                  *
   11036             :                  * Compute GROW = 1/G(j), where G(0) = max{x(i), i=1,...,n}.
   11037             :                  */
   11038           0 :                 grow = ae_minreal((double)(1), 1/ae_maxreal(xbnd, smlnum, _state), _state);
   11039           0 :                 j = jfirst;
   11040           0 :                 while((jinc>0&&j<=jlast)||(jinc<0&&j>=jlast))
   11041             :                 {
   11042             :                     
   11043             :                     /*
   11044             :                      * Exit the loop if the growth factor is too small.
   11045             :                      */
   11046           0 :                     if( ae_fp_less_eq(grow,smlnum) )
   11047             :                     {
   11048           0 :                         break;
   11049             :                     }
   11050             :                     
   11051             :                     /*
   11052             :                      * G(j) = G(j-1)*( 1 + CNORM(j) )
   11053             :                      */
   11054           0 :                     grow = grow*(1/(1+cnorm->ptr.p_double[j]));
   11055           0 :                     j = j+jinc;
   11056             :                 }
   11057             :             }
   11058             :         }
   11059             :     }
   11060             :     else
   11061             :     {
   11062             :         
   11063             :         /*
   11064             :          * Compute the growth in A' * x = b.
   11065             :          */
   11066           0 :         if( upper )
   11067             :         {
   11068           0 :             jfirst = 1;
   11069           0 :             jlast = n;
   11070           0 :             jinc = 1;
   11071             :         }
   11072             :         else
   11073             :         {
   11074           0 :             jfirst = n;
   11075           0 :             jlast = 1;
   11076           0 :             jinc = -1;
   11077             :         }
   11078           0 :         if( ae_fp_neq(tscal,(double)(1)) )
   11079             :         {
   11080           0 :             grow = (double)(0);
   11081             :         }
   11082             :         else
   11083             :         {
   11084           0 :             if( nounit )
   11085             :             {
   11086             :                 
   11087             :                 /*
   11088             :                  * A is non-unit triangular.
   11089             :                  *
   11090             :                  * Compute GROW = 1/G(j) and XBND = 1/M(j).
   11091             :                  * Initially, M(0) = max{x(i), i=1,...,n}.
   11092             :                  */
   11093           0 :                 grow = 1/ae_maxreal(xbnd, smlnum, _state);
   11094           0 :                 xbnd = grow;
   11095           0 :                 j = jfirst;
   11096           0 :                 while((jinc>0&&j<=jlast)||(jinc<0&&j>=jlast))
   11097             :                 {
   11098             :                     
   11099             :                     /*
   11100             :                      * Exit the loop if the growth factor is too small.
   11101             :                      */
   11102           0 :                     if( ae_fp_less_eq(grow,smlnum) )
   11103             :                     {
   11104           0 :                         break;
   11105             :                     }
   11106             :                     
   11107             :                     /*
   11108             :                      * G(j) = max( G(j-1), M(j-1)*( 1 + CNORM(j) ) )
   11109             :                      */
   11110           0 :                     xj = 1+cnorm->ptr.p_double[j];
   11111           0 :                     grow = ae_minreal(grow, xbnd/xj, _state);
   11112             :                     
   11113             :                     /*
   11114             :                      * M(j) = M(j-1)*( 1 + CNORM(j) ) / abs(A(j,j))
   11115             :                      */
   11116           0 :                     tjj = ae_fabs(a->ptr.pp_double[j][j], _state);
   11117           0 :                     if( ae_fp_greater(xj,tjj) )
   11118             :                     {
   11119           0 :                         xbnd = xbnd*(tjj/xj);
   11120             :                     }
   11121           0 :                     if( j==jlast )
   11122             :                     {
   11123           0 :                         grow = ae_minreal(grow, xbnd, _state);
   11124             :                     }
   11125           0 :                     j = j+jinc;
   11126             :                 }
   11127             :             }
   11128             :             else
   11129             :             {
   11130             :                 
   11131             :                 /*
   11132             :                  * A is unit triangular.
   11133             :                  *
   11134             :                  * Compute GROW = 1/G(j), where G(0) = max{x(i), i=1,...,n}.
   11135             :                  */
   11136           0 :                 grow = ae_minreal((double)(1), 1/ae_maxreal(xbnd, smlnum, _state), _state);
   11137           0 :                 j = jfirst;
   11138           0 :                 while((jinc>0&&j<=jlast)||(jinc<0&&j>=jlast))
   11139             :                 {
   11140             :                     
   11141             :                     /*
   11142             :                      * Exit the loop if the growth factor is too small.
   11143             :                      */
   11144           0 :                     if( ae_fp_less_eq(grow,smlnum) )
   11145             :                     {
   11146           0 :                         break;
   11147             :                     }
   11148             :                     
   11149             :                     /*
   11150             :                      * G(j) = ( 1 + CNORM(j) )*G(j-1)
   11151             :                      */
   11152           0 :                     xj = 1+cnorm->ptr.p_double[j];
   11153           0 :                     grow = grow/xj;
   11154           0 :                     j = j+jinc;
   11155             :                 }
   11156             :             }
   11157             :         }
   11158             :     }
   11159           0 :     if( ae_fp_greater(grow*tscal,smlnum) )
   11160             :     {
   11161             :         
   11162             :         /*
   11163             :          * Use the Level 2 BLAS solve if the reciprocal of the bound on
   11164             :          * elements of X is not too small.
   11165             :          */
   11166           0 :         if( (upper&&notran)||(!upper&&!notran) )
   11167             :         {
   11168           0 :             if( nounit )
   11169             :             {
   11170           0 :                 vd = a->ptr.pp_double[n][n];
   11171             :             }
   11172             :             else
   11173             :             {
   11174           0 :                 vd = (double)(1);
   11175             :             }
   11176           0 :             x->ptr.p_double[n] = x->ptr.p_double[n]/vd;
   11177           0 :             for(i=n-1; i>=1; i--)
   11178             :             {
   11179           0 :                 ip1 = i+1;
   11180           0 :                 if( upper )
   11181             :                 {
   11182           0 :                     v = ae_v_dotproduct(&a->ptr.pp_double[i][ip1], 1, &x->ptr.p_double[ip1], 1, ae_v_len(ip1,n));
   11183             :                 }
   11184             :                 else
   11185             :                 {
   11186           0 :                     v = ae_v_dotproduct(&a->ptr.pp_double[ip1][i], a->stride, &x->ptr.p_double[ip1], 1, ae_v_len(ip1,n));
   11187             :                 }
   11188           0 :                 if( nounit )
   11189             :                 {
   11190           0 :                     vd = a->ptr.pp_double[i][i];
   11191             :                 }
   11192             :                 else
   11193             :                 {
   11194           0 :                     vd = (double)(1);
   11195             :                 }
   11196           0 :                 x->ptr.p_double[i] = (x->ptr.p_double[i]-v)/vd;
   11197             :             }
   11198             :         }
   11199             :         else
   11200             :         {
   11201           0 :             if( nounit )
   11202             :             {
   11203           0 :                 vd = a->ptr.pp_double[1][1];
   11204             :             }
   11205             :             else
   11206             :             {
   11207           0 :                 vd = (double)(1);
   11208             :             }
   11209           0 :             x->ptr.p_double[1] = x->ptr.p_double[1]/vd;
   11210           0 :             for(i=2; i<=n; i++)
   11211             :             {
   11212           0 :                 im1 = i-1;
   11213           0 :                 if( upper )
   11214             :                 {
   11215           0 :                     v = ae_v_dotproduct(&a->ptr.pp_double[1][i], a->stride, &x->ptr.p_double[1], 1, ae_v_len(1,im1));
   11216             :                 }
   11217             :                 else
   11218             :                 {
   11219           0 :                     v = ae_v_dotproduct(&a->ptr.pp_double[i][1], 1, &x->ptr.p_double[1], 1, ae_v_len(1,im1));
   11220             :                 }
   11221           0 :                 if( nounit )
   11222             :                 {
   11223           0 :                     vd = a->ptr.pp_double[i][i];
   11224             :                 }
   11225             :                 else
   11226             :                 {
   11227           0 :                     vd = (double)(1);
   11228             :                 }
   11229           0 :                 x->ptr.p_double[i] = (x->ptr.p_double[i]-v)/vd;
   11230             :             }
   11231             :         }
   11232             :     }
   11233             :     else
   11234             :     {
   11235             :         
   11236             :         /*
   11237             :          * Use a Level 1 BLAS solve, scaling intermediate results.
   11238             :          */
   11239           0 :         if( ae_fp_greater(xmax,bignum) )
   11240             :         {
   11241             :             
   11242             :             /*
   11243             :              * Scale X so that its components are less than or equal to
   11244             :              * BIGNUM in absolute value.
   11245             :              */
   11246           0 :             *s = bignum/xmax;
   11247           0 :             ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), *s);
   11248           0 :             xmax = bignum;
   11249             :         }
   11250           0 :         if( notran )
   11251             :         {
   11252             :             
   11253             :             /*
   11254             :              * Solve A * x = b
   11255             :              */
   11256           0 :             j = jfirst;
   11257           0 :             while((jinc>0&&j<=jlast)||(jinc<0&&j>=jlast))
   11258             :             {
   11259             :                 
   11260             :                 /*
   11261             :                  * Compute x(j) = b(j) / A(j,j), scaling x if necessary.
   11262             :                  */
   11263           0 :                 xj = ae_fabs(x->ptr.p_double[j], _state);
   11264           0 :                 flg = 0;
   11265           0 :                 if( nounit )
   11266             :                 {
   11267           0 :                     tjjs = a->ptr.pp_double[j][j]*tscal;
   11268             :                 }
   11269             :                 else
   11270             :                 {
   11271           0 :                     tjjs = tscal;
   11272           0 :                     if( ae_fp_eq(tscal,(double)(1)) )
   11273             :                     {
   11274           0 :                         flg = 100;
   11275             :                     }
   11276             :                 }
   11277           0 :                 if( flg!=100 )
   11278             :                 {
   11279           0 :                     tjj = ae_fabs(tjjs, _state);
   11280           0 :                     if( ae_fp_greater(tjj,smlnum) )
   11281             :                     {
   11282             :                         
   11283             :                         /*
   11284             :                          * abs(A(j,j)) > SMLNUM:
   11285             :                          */
   11286           0 :                         if( ae_fp_less(tjj,(double)(1)) )
   11287             :                         {
   11288           0 :                             if( ae_fp_greater(xj,tjj*bignum) )
   11289             :                             {
   11290             :                                 
   11291             :                                 /*
   11292             :                                  * Scale x by 1/b(j).
   11293             :                                  */
   11294           0 :                                 rec = 1/xj;
   11295           0 :                                 ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), rec);
   11296           0 :                                 *s = *s*rec;
   11297           0 :                                 xmax = xmax*rec;
   11298             :                             }
   11299             :                         }
   11300           0 :                         x->ptr.p_double[j] = x->ptr.p_double[j]/tjjs;
   11301           0 :                         xj = ae_fabs(x->ptr.p_double[j], _state);
   11302             :                     }
   11303             :                     else
   11304             :                     {
   11305           0 :                         if( ae_fp_greater(tjj,(double)(0)) )
   11306             :                         {
   11307             :                             
   11308             :                             /*
   11309             :                              * 0 < abs(A(j,j)) <= SMLNUM:
   11310             :                              */
   11311           0 :                             if( ae_fp_greater(xj,tjj*bignum) )
   11312             :                             {
   11313             :                                 
   11314             :                                 /*
   11315             :                                  * Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM
   11316             :                                  * to avoid overflow when dividing by A(j,j).
   11317             :                                  */
   11318           0 :                                 rec = tjj*bignum/xj;
   11319           0 :                                 if( ae_fp_greater(cnorm->ptr.p_double[j],(double)(1)) )
   11320             :                                 {
   11321             :                                     
   11322             :                                     /*
   11323             :                                      * Scale by 1/CNORM(j) to avoid overflow when
   11324             :                                      * multiplying x(j) times column j.
   11325             :                                      */
   11326           0 :                                     rec = rec/cnorm->ptr.p_double[j];
   11327             :                                 }
   11328           0 :                                 ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), rec);
   11329           0 :                                 *s = *s*rec;
   11330           0 :                                 xmax = xmax*rec;
   11331             :                             }
   11332           0 :                             x->ptr.p_double[j] = x->ptr.p_double[j]/tjjs;
   11333           0 :                             xj = ae_fabs(x->ptr.p_double[j], _state);
   11334             :                         }
   11335             :                         else
   11336             :                         {
   11337             :                             
   11338             :                             /*
   11339             :                              * A(j,j) = 0:  Set x(1:n) = 0, x(j) = 1, and
   11340             :                              * scale = 0, and compute a solution to A*x = 0.
   11341             :                              */
   11342           0 :                             for(i=1; i<=n; i++)
   11343             :                             {
   11344           0 :                                 x->ptr.p_double[i] = (double)(0);
   11345             :                             }
   11346           0 :                             x->ptr.p_double[j] = (double)(1);
   11347           0 :                             xj = (double)(1);
   11348           0 :                             *s = (double)(0);
   11349           0 :                             xmax = (double)(0);
   11350             :                         }
   11351             :                     }
   11352             :                 }
   11353             :                 
   11354             :                 /*
   11355             :                  * Scale x if necessary to avoid overflow when adding a
   11356             :                  * multiple of column j of A.
   11357             :                  */
   11358           0 :                 if( ae_fp_greater(xj,(double)(1)) )
   11359             :                 {
   11360           0 :                     rec = 1/xj;
   11361           0 :                     if( ae_fp_greater(cnorm->ptr.p_double[j],(bignum-xmax)*rec) )
   11362             :                     {
   11363             :                         
   11364             :                         /*
   11365             :                          * Scale x by 1/(2*abs(x(j))).
   11366             :                          */
   11367           0 :                         rec = rec*0.5;
   11368           0 :                         ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), rec);
   11369           0 :                         *s = *s*rec;
   11370             :                     }
   11371             :                 }
   11372             :                 else
   11373             :                 {
   11374           0 :                     if( ae_fp_greater(xj*cnorm->ptr.p_double[j],bignum-xmax) )
   11375             :                     {
   11376             :                         
   11377             :                         /*
   11378             :                          * Scale x by 1/2.
   11379             :                          */
   11380           0 :                         ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), 0.5);
   11381           0 :                         *s = *s*0.5;
   11382             :                     }
   11383             :                 }
   11384           0 :                 if( upper )
   11385             :                 {
   11386           0 :                     if( j>1 )
   11387             :                     {
   11388             :                         
   11389             :                         /*
   11390             :                          * Compute the update
   11391             :                          * x(1:j-1) := x(1:j-1) - x(j) * A(1:j-1,j)
   11392             :                          */
   11393           0 :                         v = x->ptr.p_double[j]*tscal;
   11394           0 :                         jm1 = j-1;
   11395           0 :                         ae_v_subd(&x->ptr.p_double[1], 1, &a->ptr.pp_double[1][j], a->stride, ae_v_len(1,jm1), v);
   11396           0 :                         i = 1;
   11397           0 :                         for(k=2; k<=j-1; k++)
   11398             :                         {
   11399           0 :                             if( ae_fp_greater(ae_fabs(x->ptr.p_double[k], _state),ae_fabs(x->ptr.p_double[i], _state)) )
   11400             :                             {
   11401           0 :                                 i = k;
   11402             :                             }
   11403             :                         }
   11404           0 :                         xmax = ae_fabs(x->ptr.p_double[i], _state);
   11405             :                     }
   11406             :                 }
   11407             :                 else
   11408             :                 {
   11409           0 :                     if( j<n )
   11410             :                     {
   11411             :                         
   11412             :                         /*
   11413             :                          * Compute the update
   11414             :                          * x(j+1:n) := x(j+1:n) - x(j) * A(j+1:n,j)
   11415             :                          */
   11416           0 :                         jp1 = j+1;
   11417           0 :                         v = x->ptr.p_double[j]*tscal;
   11418           0 :                         ae_v_subd(&x->ptr.p_double[jp1], 1, &a->ptr.pp_double[jp1][j], a->stride, ae_v_len(jp1,n), v);
   11419           0 :                         i = j+1;
   11420           0 :                         for(k=j+2; k<=n; k++)
   11421             :                         {
   11422           0 :                             if( ae_fp_greater(ae_fabs(x->ptr.p_double[k], _state),ae_fabs(x->ptr.p_double[i], _state)) )
   11423             :                             {
   11424           0 :                                 i = k;
   11425             :                             }
   11426             :                         }
   11427           0 :                         xmax = ae_fabs(x->ptr.p_double[i], _state);
   11428             :                     }
   11429             :                 }
   11430           0 :                 j = j+jinc;
   11431             :             }
   11432             :         }
   11433             :         else
   11434             :         {
   11435             :             
   11436             :             /*
   11437             :              * Solve A' * x = b
   11438             :              */
   11439           0 :             j = jfirst;
   11440           0 :             while((jinc>0&&j<=jlast)||(jinc<0&&j>=jlast))
   11441             :             {
   11442             :                 
   11443             :                 /*
   11444             :                  * Compute x(j) = b(j) - sum A(k,j)*x(k).
   11445             :                  *   k<>j
   11446             :                  */
   11447           0 :                 xj = ae_fabs(x->ptr.p_double[j], _state);
   11448           0 :                 uscal = tscal;
   11449           0 :                 rec = 1/ae_maxreal(xmax, (double)(1), _state);
   11450           0 :                 if( ae_fp_greater(cnorm->ptr.p_double[j],(bignum-xj)*rec) )
   11451             :                 {
   11452             :                     
   11453             :                     /*
   11454             :                      * If x(j) could overflow, scale x by 1/(2*XMAX).
   11455             :                      */
   11456           0 :                     rec = rec*0.5;
   11457           0 :                     if( nounit )
   11458             :                     {
   11459           0 :                         tjjs = a->ptr.pp_double[j][j]*tscal;
   11460             :                     }
   11461             :                     else
   11462             :                     {
   11463           0 :                         tjjs = tscal;
   11464             :                     }
   11465           0 :                     tjj = ae_fabs(tjjs, _state);
   11466           0 :                     if( ae_fp_greater(tjj,(double)(1)) )
   11467             :                     {
   11468             :                         
   11469             :                         /*
   11470             :                          * Divide by A(j,j) when scaling x if A(j,j) > 1.
   11471             :                          */
   11472           0 :                         rec = ae_minreal((double)(1), rec*tjj, _state);
   11473           0 :                         uscal = uscal/tjjs;
   11474             :                     }
   11475           0 :                     if( ae_fp_less(rec,(double)(1)) )
   11476             :                     {
   11477           0 :                         ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), rec);
   11478           0 :                         *s = *s*rec;
   11479           0 :                         xmax = xmax*rec;
   11480             :                     }
   11481             :                 }
   11482           0 :                 sumj = (double)(0);
   11483           0 :                 if( ae_fp_eq(uscal,(double)(1)) )
   11484             :                 {
   11485             :                     
   11486             :                     /*
   11487             :                      * If the scaling needed for A in the dot product is 1,
   11488             :                      * call DDOT to perform the dot product.
   11489             :                      */
   11490           0 :                     if( upper )
   11491             :                     {
   11492           0 :                         if( j>1 )
   11493             :                         {
   11494           0 :                             jm1 = j-1;
   11495           0 :                             sumj = ae_v_dotproduct(&a->ptr.pp_double[1][j], a->stride, &x->ptr.p_double[1], 1, ae_v_len(1,jm1));
   11496             :                         }
   11497             :                         else
   11498             :                         {
   11499           0 :                             sumj = (double)(0);
   11500             :                         }
   11501             :                     }
   11502             :                     else
   11503             :                     {
   11504           0 :                         if( j<n )
   11505             :                         {
   11506           0 :                             jp1 = j+1;
   11507           0 :                             sumj = ae_v_dotproduct(&a->ptr.pp_double[jp1][j], a->stride, &x->ptr.p_double[jp1], 1, ae_v_len(jp1,n));
   11508             :                         }
   11509             :                     }
   11510             :                 }
   11511             :                 else
   11512             :                 {
   11513             :                     
   11514             :                     /*
   11515             :                      * Otherwise, use in-line code for the dot product.
   11516             :                      */
   11517           0 :                     if( upper )
   11518             :                     {
   11519           0 :                         for(i=1; i<=j-1; i++)
   11520             :                         {
   11521           0 :                             v = a->ptr.pp_double[i][j]*uscal;
   11522           0 :                             sumj = sumj+v*x->ptr.p_double[i];
   11523             :                         }
   11524             :                     }
   11525             :                     else
   11526             :                     {
   11527           0 :                         if( j<n )
   11528             :                         {
   11529           0 :                             for(i=j+1; i<=n; i++)
   11530             :                             {
   11531           0 :                                 v = a->ptr.pp_double[i][j]*uscal;
   11532           0 :                                 sumj = sumj+v*x->ptr.p_double[i];
   11533             :                             }
   11534             :                         }
   11535             :                     }
   11536             :                 }
   11537           0 :                 if( ae_fp_eq(uscal,tscal) )
   11538             :                 {
   11539             :                     
   11540             :                     /*
   11541             :                      * Compute x(j) := ( x(j) - sumj ) / A(j,j) if 1/A(j,j)
   11542             :                      * was not used to scale the dotproduct.
   11543             :                      */
   11544           0 :                     x->ptr.p_double[j] = x->ptr.p_double[j]-sumj;
   11545           0 :                     xj = ae_fabs(x->ptr.p_double[j], _state);
   11546           0 :                     flg = 0;
   11547           0 :                     if( nounit )
   11548             :                     {
   11549           0 :                         tjjs = a->ptr.pp_double[j][j]*tscal;
   11550             :                     }
   11551             :                     else
   11552             :                     {
   11553           0 :                         tjjs = tscal;
   11554           0 :                         if( ae_fp_eq(tscal,(double)(1)) )
   11555             :                         {
   11556           0 :                             flg = 150;
   11557             :                         }
   11558             :                     }
   11559             :                     
   11560             :                     /*
   11561             :                      * Compute x(j) = x(j) / A(j,j), scaling if necessary.
   11562             :                      */
   11563           0 :                     if( flg!=150 )
   11564             :                     {
   11565           0 :                         tjj = ae_fabs(tjjs, _state);
   11566           0 :                         if( ae_fp_greater(tjj,smlnum) )
   11567             :                         {
   11568             :                             
   11569             :                             /*
   11570             :                              * abs(A(j,j)) > SMLNUM:
   11571             :                              */
   11572           0 :                             if( ae_fp_less(tjj,(double)(1)) )
   11573             :                             {
   11574           0 :                                 if( ae_fp_greater(xj,tjj*bignum) )
   11575             :                                 {
   11576             :                                     
   11577             :                                     /*
   11578             :                                      * Scale X by 1/abs(x(j)).
   11579             :                                      */
   11580           0 :                                     rec = 1/xj;
   11581           0 :                                     ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), rec);
   11582           0 :                                     *s = *s*rec;
   11583           0 :                                     xmax = xmax*rec;
   11584             :                                 }
   11585             :                             }
   11586           0 :                             x->ptr.p_double[j] = x->ptr.p_double[j]/tjjs;
   11587             :                         }
   11588             :                         else
   11589             :                         {
   11590           0 :                             if( ae_fp_greater(tjj,(double)(0)) )
   11591             :                             {
   11592             :                                 
   11593             :                                 /*
   11594             :                                  * 0 < abs(A(j,j)) <= SMLNUM:
   11595             :                                  */
   11596           0 :                                 if( ae_fp_greater(xj,tjj*bignum) )
   11597             :                                 {
   11598             :                                     
   11599             :                                     /*
   11600             :                                      * Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM.
   11601             :                                      */
   11602           0 :                                     rec = tjj*bignum/xj;
   11603           0 :                                     ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), rec);
   11604           0 :                                     *s = *s*rec;
   11605           0 :                                     xmax = xmax*rec;
   11606             :                                 }
   11607           0 :                                 x->ptr.p_double[j] = x->ptr.p_double[j]/tjjs;
   11608             :                             }
   11609             :                             else
   11610             :                             {
   11611             :                                 
   11612             :                                 /*
   11613             :                                  * A(j,j) = 0:  Set x(1:n) = 0, x(j) = 1, and
   11614             :                                  * scale = 0, and compute a solution to A'*x = 0.
   11615             :                                  */
   11616           0 :                                 for(i=1; i<=n; i++)
   11617             :                                 {
   11618           0 :                                     x->ptr.p_double[i] = (double)(0);
   11619             :                                 }
   11620           0 :                                 x->ptr.p_double[j] = (double)(1);
   11621           0 :                                 *s = (double)(0);
   11622           0 :                                 xmax = (double)(0);
   11623             :                             }
   11624             :                         }
   11625             :                     }
   11626             :                 }
   11627             :                 else
   11628             :                 {
   11629             :                     
   11630             :                     /*
   11631             :                      * Compute x(j) := x(j) / A(j,j)  - sumj if the dot
   11632             :                      * product has already been divided by 1/A(j,j).
   11633             :                      */
   11634           0 :                     x->ptr.p_double[j] = x->ptr.p_double[j]/tjjs-sumj;
   11635             :                 }
   11636           0 :                 xmax = ae_maxreal(xmax, ae_fabs(x->ptr.p_double[j], _state), _state);
   11637           0 :                 j = j+jinc;
   11638             :             }
   11639             :         }
   11640           0 :         *s = *s/tscal;
   11641             :     }
   11642             :     
   11643             :     /*
   11644             :      * Scale the column norms by 1/TSCAL for return.
   11645             :      */
   11646           0 :     if( ae_fp_neq(tscal,(double)(1)) )
   11647             :     {
   11648           0 :         v = 1/tscal;
   11649           0 :         ae_v_muld(&cnorm->ptr.p_double[1], 1, ae_v_len(1,n), v);
   11650             :     }
   11651             : }
   11652             : 
   11653             : 
   11654             : #endif
   11655             : #if defined(AE_COMPILE_SAFESOLVE) || !defined(AE_PARTIAL_BUILD)
   11656             : 
   11657             : 
   11658             : /*************************************************************************
   11659             : Real implementation of CMatrixScaledTRSafeSolve
   11660             : 
   11661             :   -- ALGLIB routine --
   11662             :      21.01.2010
   11663             :      Bochkanov Sergey
   11664             : *************************************************************************/
   11665           0 : ae_bool rmatrixscaledtrsafesolve(/* Real    */ ae_matrix* a,
   11666             :      double sa,
   11667             :      ae_int_t n,
   11668             :      /* Real    */ ae_vector* x,
   11669             :      ae_bool isupper,
   11670             :      ae_int_t trans,
   11671             :      ae_bool isunit,
   11672             :      double maxgrowth,
   11673             :      ae_state *_state)
   11674             : {
   11675             :     ae_frame _frame_block;
   11676             :     double lnmax;
   11677             :     double nrmb;
   11678             :     double nrmx;
   11679             :     ae_int_t i;
   11680             :     ae_complex alpha;
   11681             :     ae_complex beta;
   11682             :     double vr;
   11683             :     ae_complex cx;
   11684             :     ae_vector tmp;
   11685             :     ae_bool result;
   11686             : 
   11687           0 :     ae_frame_make(_state, &_frame_block);
   11688           0 :     memset(&tmp, 0, sizeof(tmp));
   11689           0 :     ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
   11690             : 
   11691           0 :     ae_assert(n>0, "RMatrixTRSafeSolve: incorrect N!", _state);
   11692           0 :     ae_assert(trans==0||trans==1, "RMatrixTRSafeSolve: incorrect Trans!", _state);
   11693           0 :     result = ae_true;
   11694           0 :     lnmax = ae_log(ae_maxrealnumber, _state);
   11695             :     
   11696             :     /*
   11697             :      * Quick return if possible
   11698             :      */
   11699           0 :     if( n<=0 )
   11700             :     {
   11701           0 :         ae_frame_leave(_state);
   11702           0 :         return result;
   11703             :     }
   11704             :     
   11705             :     /*
   11706             :      * Load norms: right part and X
   11707             :      */
   11708           0 :     nrmb = (double)(0);
   11709           0 :     for(i=0; i<=n-1; i++)
   11710             :     {
   11711           0 :         nrmb = ae_maxreal(nrmb, ae_fabs(x->ptr.p_double[i], _state), _state);
   11712             :     }
   11713           0 :     nrmx = (double)(0);
   11714             :     
   11715             :     /*
   11716             :      * Solve
   11717             :      */
   11718           0 :     ae_vector_set_length(&tmp, n, _state);
   11719           0 :     result = ae_true;
   11720           0 :     if( isupper&&trans==0 )
   11721             :     {
   11722             :         
   11723             :         /*
   11724             :          * U*x = b
   11725             :          */
   11726           0 :         for(i=n-1; i>=0; i--)
   11727             :         {
   11728             :             
   11729             :             /*
   11730             :              * Task is reduced to alpha*x[i] = beta
   11731             :              */
   11732           0 :             if( isunit )
   11733             :             {
   11734           0 :                 alpha = ae_complex_from_d(sa);
   11735             :             }
   11736             :             else
   11737             :             {
   11738           0 :                 alpha = ae_complex_from_d(a->ptr.pp_double[i][i]*sa);
   11739             :             }
   11740           0 :             if( i<n-1 )
   11741             :             {
   11742           0 :                 ae_v_moved(&tmp.ptr.p_double[i+1], 1, &a->ptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1), sa);
   11743           0 :                 vr = ae_v_dotproduct(&tmp.ptr.p_double[i+1], 1, &x->ptr.p_double[i+1], 1, ae_v_len(i+1,n-1));
   11744           0 :                 beta = ae_complex_from_d(x->ptr.p_double[i]-vr);
   11745             :             }
   11746             :             else
   11747             :             {
   11748           0 :                 beta = ae_complex_from_d(x->ptr.p_double[i]);
   11749             :             }
   11750             :             
   11751             :             /*
   11752             :              * solve alpha*x[i] = beta
   11753             :              */
   11754           0 :             result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &cx, _state);
   11755           0 :             if( !result )
   11756             :             {
   11757           0 :                 ae_frame_leave(_state);
   11758           0 :                 return result;
   11759             :             }
   11760           0 :             x->ptr.p_double[i] = cx.x;
   11761             :         }
   11762           0 :         ae_frame_leave(_state);
   11763           0 :         return result;
   11764             :     }
   11765           0 :     if( !isupper&&trans==0 )
   11766             :     {
   11767             :         
   11768             :         /*
   11769             :          * L*x = b
   11770             :          */
   11771           0 :         for(i=0; i<=n-1; i++)
   11772             :         {
   11773             :             
   11774             :             /*
   11775             :              * Task is reduced to alpha*x[i] = beta
   11776             :              */
   11777           0 :             if( isunit )
   11778             :             {
   11779           0 :                 alpha = ae_complex_from_d(sa);
   11780             :             }
   11781             :             else
   11782             :             {
   11783           0 :                 alpha = ae_complex_from_d(a->ptr.pp_double[i][i]*sa);
   11784             :             }
   11785           0 :             if( i>0 )
   11786             :             {
   11787           0 :                 ae_v_moved(&tmp.ptr.p_double[0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,i-1), sa);
   11788           0 :                 vr = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,i-1));
   11789           0 :                 beta = ae_complex_from_d(x->ptr.p_double[i]-vr);
   11790             :             }
   11791             :             else
   11792             :             {
   11793           0 :                 beta = ae_complex_from_d(x->ptr.p_double[i]);
   11794             :             }
   11795             :             
   11796             :             /*
   11797             :              * solve alpha*x[i] = beta
   11798             :              */
   11799           0 :             result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &cx, _state);
   11800           0 :             if( !result )
   11801             :             {
   11802           0 :                 ae_frame_leave(_state);
   11803           0 :                 return result;
   11804             :             }
   11805           0 :             x->ptr.p_double[i] = cx.x;
   11806             :         }
   11807           0 :         ae_frame_leave(_state);
   11808           0 :         return result;
   11809             :     }
   11810           0 :     if( isupper&&trans==1 )
   11811             :     {
   11812             :         
   11813             :         /*
   11814             :          * U^T*x = b
   11815             :          */
   11816           0 :         for(i=0; i<=n-1; i++)
   11817             :         {
   11818             :             
   11819             :             /*
   11820             :              * Task is reduced to alpha*x[i] = beta
   11821             :              */
   11822           0 :             if( isunit )
   11823             :             {
   11824           0 :                 alpha = ae_complex_from_d(sa);
   11825             :             }
   11826             :             else
   11827             :             {
   11828           0 :                 alpha = ae_complex_from_d(a->ptr.pp_double[i][i]*sa);
   11829             :             }
   11830           0 :             beta = ae_complex_from_d(x->ptr.p_double[i]);
   11831             :             
   11832             :             /*
   11833             :              * solve alpha*x[i] = beta
   11834             :              */
   11835           0 :             result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &cx, _state);
   11836           0 :             if( !result )
   11837             :             {
   11838           0 :                 ae_frame_leave(_state);
   11839           0 :                 return result;
   11840             :             }
   11841           0 :             x->ptr.p_double[i] = cx.x;
   11842             :             
   11843             :             /*
   11844             :              * update the rest of right part
   11845             :              */
   11846           0 :             if( i<n-1 )
   11847             :             {
   11848           0 :                 vr = cx.x;
   11849           0 :                 ae_v_moved(&tmp.ptr.p_double[i+1], 1, &a->ptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1), sa);
   11850           0 :                 ae_v_subd(&x->ptr.p_double[i+1], 1, &tmp.ptr.p_double[i+1], 1, ae_v_len(i+1,n-1), vr);
   11851             :             }
   11852             :         }
   11853           0 :         ae_frame_leave(_state);
   11854           0 :         return result;
   11855             :     }
   11856           0 :     if( !isupper&&trans==1 )
   11857             :     {
   11858             :         
   11859             :         /*
   11860             :          * L^T*x = b
   11861             :          */
   11862           0 :         for(i=n-1; i>=0; i--)
   11863             :         {
   11864             :             
   11865             :             /*
   11866             :              * Task is reduced to alpha*x[i] = beta
   11867             :              */
   11868           0 :             if( isunit )
   11869             :             {
   11870           0 :                 alpha = ae_complex_from_d(sa);
   11871             :             }
   11872             :             else
   11873             :             {
   11874           0 :                 alpha = ae_complex_from_d(a->ptr.pp_double[i][i]*sa);
   11875             :             }
   11876           0 :             beta = ae_complex_from_d(x->ptr.p_double[i]);
   11877             :             
   11878             :             /*
   11879             :              * solve alpha*x[i] = beta
   11880             :              */
   11881           0 :             result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &cx, _state);
   11882           0 :             if( !result )
   11883             :             {
   11884           0 :                 ae_frame_leave(_state);
   11885           0 :                 return result;
   11886             :             }
   11887           0 :             x->ptr.p_double[i] = cx.x;
   11888             :             
   11889             :             /*
   11890             :              * update the rest of right part
   11891             :              */
   11892           0 :             if( i>0 )
   11893             :             {
   11894           0 :                 vr = cx.x;
   11895           0 :                 ae_v_moved(&tmp.ptr.p_double[0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,i-1), sa);
   11896           0 :                 ae_v_subd(&x->ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,i-1), vr);
   11897             :             }
   11898             :         }
   11899           0 :         ae_frame_leave(_state);
   11900           0 :         return result;
   11901             :     }
   11902           0 :     result = ae_false;
   11903           0 :     ae_frame_leave(_state);
   11904           0 :     return result;
   11905             : }
   11906             : 
   11907             : 
   11908             : /*************************************************************************
   11909             : Internal subroutine for safe solution of
   11910             : 
   11911             :     SA*op(A)=b
   11912             :     
   11913             : where  A  is  NxN  upper/lower  triangular/unitriangular  matrix, op(A) is
   11914             : either identity transform, transposition or Hermitian transposition, SA is
   11915             : a scaling factor such that max(|SA*A[i,j]|) is close to 1.0 in magnutude.
   11916             : 
   11917             : This subroutine  limits  relative  growth  of  solution  (in inf-norm)  by
   11918             : MaxGrowth,  returning  False  if  growth  exceeds MaxGrowth. Degenerate or
   11919             : near-degenerate matrices are handled correctly (False is returned) as long
   11920             : as MaxGrowth is significantly less than MaxRealNumber/norm(b).
   11921             : 
   11922             :   -- ALGLIB routine --
   11923             :      21.01.2010
   11924             :      Bochkanov Sergey
   11925             : *************************************************************************/
   11926           0 : ae_bool cmatrixscaledtrsafesolve(/* Complex */ ae_matrix* a,
   11927             :      double sa,
   11928             :      ae_int_t n,
   11929             :      /* Complex */ ae_vector* x,
   11930             :      ae_bool isupper,
   11931             :      ae_int_t trans,
   11932             :      ae_bool isunit,
   11933             :      double maxgrowth,
   11934             :      ae_state *_state)
   11935             : {
   11936             :     ae_frame _frame_block;
   11937             :     double lnmax;
   11938             :     double nrmb;
   11939             :     double nrmx;
   11940             :     ae_int_t i;
   11941             :     ae_complex alpha;
   11942             :     ae_complex beta;
   11943             :     ae_complex vc;
   11944             :     ae_vector tmp;
   11945             :     ae_bool result;
   11946             : 
   11947           0 :     ae_frame_make(_state, &_frame_block);
   11948           0 :     memset(&tmp, 0, sizeof(tmp));
   11949           0 :     ae_vector_init(&tmp, 0, DT_COMPLEX, _state, ae_true);
   11950             : 
   11951           0 :     ae_assert(n>0, "CMatrixTRSafeSolve: incorrect N!", _state);
   11952           0 :     ae_assert((trans==0||trans==1)||trans==2, "CMatrixTRSafeSolve: incorrect Trans!", _state);
   11953           0 :     result = ae_true;
   11954           0 :     lnmax = ae_log(ae_maxrealnumber, _state);
   11955             :     
   11956             :     /*
   11957             :      * Quick return if possible
   11958             :      */
   11959           0 :     if( n<=0 )
   11960             :     {
   11961           0 :         ae_frame_leave(_state);
   11962           0 :         return result;
   11963             :     }
   11964             :     
   11965             :     /*
   11966             :      * Load norms: right part and X
   11967             :      */
   11968           0 :     nrmb = (double)(0);
   11969           0 :     for(i=0; i<=n-1; i++)
   11970             :     {
   11971           0 :         nrmb = ae_maxreal(nrmb, ae_c_abs(x->ptr.p_complex[i], _state), _state);
   11972             :     }
   11973           0 :     nrmx = (double)(0);
   11974             :     
   11975             :     /*
   11976             :      * Solve
   11977             :      */
   11978           0 :     ae_vector_set_length(&tmp, n, _state);
   11979           0 :     result = ae_true;
   11980           0 :     if( isupper&&trans==0 )
   11981             :     {
   11982             :         
   11983             :         /*
   11984             :          * U*x = b
   11985             :          */
   11986           0 :         for(i=n-1; i>=0; i--)
   11987             :         {
   11988             :             
   11989             :             /*
   11990             :              * Task is reduced to alpha*x[i] = beta
   11991             :              */
   11992           0 :             if( isunit )
   11993             :             {
   11994           0 :                 alpha = ae_complex_from_d(sa);
   11995             :             }
   11996             :             else
   11997             :             {
   11998           0 :                 alpha = ae_c_mul_d(a->ptr.pp_complex[i][i],sa);
   11999             :             }
   12000           0 :             if( i<n-1 )
   12001             :             {
   12002           0 :                 ae_v_cmoved(&tmp.ptr.p_complex[i+1], 1, &a->ptr.pp_complex[i][i+1], 1, "N", ae_v_len(i+1,n-1), sa);
   12003           0 :                 vc = ae_v_cdotproduct(&tmp.ptr.p_complex[i+1], 1, "N", &x->ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,n-1));
   12004           0 :                 beta = ae_c_sub(x->ptr.p_complex[i],vc);
   12005             :             }
   12006             :             else
   12007             :             {
   12008           0 :                 beta = x->ptr.p_complex[i];
   12009             :             }
   12010             :             
   12011             :             /*
   12012             :              * solve alpha*x[i] = beta
   12013             :              */
   12014           0 :             result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &vc, _state);
   12015           0 :             if( !result )
   12016             :             {
   12017           0 :                 ae_frame_leave(_state);
   12018           0 :                 return result;
   12019             :             }
   12020           0 :             x->ptr.p_complex[i] = vc;
   12021             :         }
   12022           0 :         ae_frame_leave(_state);
   12023           0 :         return result;
   12024             :     }
   12025           0 :     if( !isupper&&trans==0 )
   12026             :     {
   12027             :         
   12028             :         /*
   12029             :          * L*x = b
   12030             :          */
   12031           0 :         for(i=0; i<=n-1; i++)
   12032             :         {
   12033             :             
   12034             :             /*
   12035             :              * Task is reduced to alpha*x[i] = beta
   12036             :              */
   12037           0 :             if( isunit )
   12038             :             {
   12039           0 :                 alpha = ae_complex_from_d(sa);
   12040             :             }
   12041             :             else
   12042             :             {
   12043           0 :                 alpha = ae_c_mul_d(a->ptr.pp_complex[i][i],sa);
   12044             :             }
   12045           0 :             if( i>0 )
   12046             :             {
   12047           0 :                 ae_v_cmoved(&tmp.ptr.p_complex[0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,i-1), sa);
   12048           0 :                 vc = ae_v_cdotproduct(&tmp.ptr.p_complex[0], 1, "N", &x->ptr.p_complex[0], 1, "N", ae_v_len(0,i-1));
   12049           0 :                 beta = ae_c_sub(x->ptr.p_complex[i],vc);
   12050             :             }
   12051             :             else
   12052             :             {
   12053           0 :                 beta = x->ptr.p_complex[i];
   12054             :             }
   12055             :             
   12056             :             /*
   12057             :              * solve alpha*x[i] = beta
   12058             :              */
   12059           0 :             result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &vc, _state);
   12060           0 :             if( !result )
   12061             :             {
   12062           0 :                 ae_frame_leave(_state);
   12063           0 :                 return result;
   12064             :             }
   12065           0 :             x->ptr.p_complex[i] = vc;
   12066             :         }
   12067           0 :         ae_frame_leave(_state);
   12068           0 :         return result;
   12069             :     }
   12070           0 :     if( isupper&&trans==1 )
   12071             :     {
   12072             :         
   12073             :         /*
   12074             :          * U^T*x = b
   12075             :          */
   12076           0 :         for(i=0; i<=n-1; i++)
   12077             :         {
   12078             :             
   12079             :             /*
   12080             :              * Task is reduced to alpha*x[i] = beta
   12081             :              */
   12082           0 :             if( isunit )
   12083             :             {
   12084           0 :                 alpha = ae_complex_from_d(sa);
   12085             :             }
   12086             :             else
   12087             :             {
   12088           0 :                 alpha = ae_c_mul_d(a->ptr.pp_complex[i][i],sa);
   12089             :             }
   12090           0 :             beta = x->ptr.p_complex[i];
   12091             :             
   12092             :             /*
   12093             :              * solve alpha*x[i] = beta
   12094             :              */
   12095           0 :             result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &vc, _state);
   12096           0 :             if( !result )
   12097             :             {
   12098           0 :                 ae_frame_leave(_state);
   12099           0 :                 return result;
   12100             :             }
   12101           0 :             x->ptr.p_complex[i] = vc;
   12102             :             
   12103             :             /*
   12104             :              * update the rest of right part
   12105             :              */
   12106           0 :             if( i<n-1 )
   12107             :             {
   12108           0 :                 ae_v_cmoved(&tmp.ptr.p_complex[i+1], 1, &a->ptr.pp_complex[i][i+1], 1, "N", ae_v_len(i+1,n-1), sa);
   12109           0 :                 ae_v_csubc(&x->ptr.p_complex[i+1], 1, &tmp.ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,n-1), vc);
   12110             :             }
   12111             :         }
   12112           0 :         ae_frame_leave(_state);
   12113           0 :         return result;
   12114             :     }
   12115           0 :     if( !isupper&&trans==1 )
   12116             :     {
   12117             :         
   12118             :         /*
   12119             :          * L^T*x = b
   12120             :          */
   12121           0 :         for(i=n-1; i>=0; i--)
   12122             :         {
   12123             :             
   12124             :             /*
   12125             :              * Task is reduced to alpha*x[i] = beta
   12126             :              */
   12127           0 :             if( isunit )
   12128             :             {
   12129           0 :                 alpha = ae_complex_from_d(sa);
   12130             :             }
   12131             :             else
   12132             :             {
   12133           0 :                 alpha = ae_c_mul_d(a->ptr.pp_complex[i][i],sa);
   12134             :             }
   12135           0 :             beta = x->ptr.p_complex[i];
   12136             :             
   12137             :             /*
   12138             :              * solve alpha*x[i] = beta
   12139             :              */
   12140           0 :             result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &vc, _state);
   12141           0 :             if( !result )
   12142             :             {
   12143           0 :                 ae_frame_leave(_state);
   12144           0 :                 return result;
   12145             :             }
   12146           0 :             x->ptr.p_complex[i] = vc;
   12147             :             
   12148             :             /*
   12149             :              * update the rest of right part
   12150             :              */
   12151           0 :             if( i>0 )
   12152             :             {
   12153           0 :                 ae_v_cmoved(&tmp.ptr.p_complex[0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,i-1), sa);
   12154           0 :                 ae_v_csubc(&x->ptr.p_complex[0], 1, &tmp.ptr.p_complex[0], 1, "N", ae_v_len(0,i-1), vc);
   12155             :             }
   12156             :         }
   12157           0 :         ae_frame_leave(_state);
   12158           0 :         return result;
   12159             :     }
   12160           0 :     if( isupper&&trans==2 )
   12161             :     {
   12162             :         
   12163             :         /*
   12164             :          * U^H*x = b
   12165             :          */
   12166           0 :         for(i=0; i<=n-1; i++)
   12167             :         {
   12168             :             
   12169             :             /*
   12170             :              * Task is reduced to alpha*x[i] = beta
   12171             :              */
   12172           0 :             if( isunit )
   12173             :             {
   12174           0 :                 alpha = ae_complex_from_d(sa);
   12175             :             }
   12176             :             else
   12177             :             {
   12178           0 :                 alpha = ae_c_mul_d(ae_c_conj(a->ptr.pp_complex[i][i], _state),sa);
   12179             :             }
   12180           0 :             beta = x->ptr.p_complex[i];
   12181             :             
   12182             :             /*
   12183             :              * solve alpha*x[i] = beta
   12184             :              */
   12185           0 :             result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &vc, _state);
   12186           0 :             if( !result )
   12187             :             {
   12188           0 :                 ae_frame_leave(_state);
   12189           0 :                 return result;
   12190             :             }
   12191           0 :             x->ptr.p_complex[i] = vc;
   12192             :             
   12193             :             /*
   12194             :              * update the rest of right part
   12195             :              */
   12196           0 :             if( i<n-1 )
   12197             :             {
   12198           0 :                 ae_v_cmoved(&tmp.ptr.p_complex[i+1], 1, &a->ptr.pp_complex[i][i+1], 1, "Conj", ae_v_len(i+1,n-1), sa);
   12199           0 :                 ae_v_csubc(&x->ptr.p_complex[i+1], 1, &tmp.ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,n-1), vc);
   12200             :             }
   12201             :         }
   12202           0 :         ae_frame_leave(_state);
   12203           0 :         return result;
   12204             :     }
   12205           0 :     if( !isupper&&trans==2 )
   12206             :     {
   12207             :         
   12208             :         /*
   12209             :          * L^T*x = b
   12210             :          */
   12211           0 :         for(i=n-1; i>=0; i--)
   12212             :         {
   12213             :             
   12214             :             /*
   12215             :              * Task is reduced to alpha*x[i] = beta
   12216             :              */
   12217           0 :             if( isunit )
   12218             :             {
   12219           0 :                 alpha = ae_complex_from_d(sa);
   12220             :             }
   12221             :             else
   12222             :             {
   12223           0 :                 alpha = ae_c_mul_d(ae_c_conj(a->ptr.pp_complex[i][i], _state),sa);
   12224             :             }
   12225           0 :             beta = x->ptr.p_complex[i];
   12226             :             
   12227             :             /*
   12228             :              * solve alpha*x[i] = beta
   12229             :              */
   12230           0 :             result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &vc, _state);
   12231           0 :             if( !result )
   12232             :             {
   12233           0 :                 ae_frame_leave(_state);
   12234           0 :                 return result;
   12235             :             }
   12236           0 :             x->ptr.p_complex[i] = vc;
   12237             :             
   12238             :             /*
   12239             :              * update the rest of right part
   12240             :              */
   12241           0 :             if( i>0 )
   12242             :             {
   12243           0 :                 ae_v_cmoved(&tmp.ptr.p_complex[0], 1, &a->ptr.pp_complex[i][0], 1, "Conj", ae_v_len(0,i-1), sa);
   12244           0 :                 ae_v_csubc(&x->ptr.p_complex[0], 1, &tmp.ptr.p_complex[0], 1, "N", ae_v_len(0,i-1), vc);
   12245             :             }
   12246             :         }
   12247           0 :         ae_frame_leave(_state);
   12248           0 :         return result;
   12249             :     }
   12250           0 :     result = ae_false;
   12251           0 :     ae_frame_leave(_state);
   12252           0 :     return result;
   12253             : }
   12254             : 
   12255             : 
   12256             : /*************************************************************************
   12257             : complex basic solver-updater for reduced linear system
   12258             : 
   12259             :     alpha*x[i] = beta
   12260             : 
   12261             : solves this equation and updates it in overlfow-safe manner (keeping track
   12262             : of relative growth of solution).
   12263             : 
   12264             : Parameters:
   12265             :     Alpha   -   alpha
   12266             :     Beta    -   beta
   12267             :     LnMax   -   precomputed Ln(MaxRealNumber)
   12268             :     BNorm   -   inf-norm of b (right part of original system)
   12269             :     MaxGrowth-  maximum growth of norm(x) relative to norm(b)
   12270             :     XNorm   -   inf-norm of other components of X (which are already processed)
   12271             :                 it is updated by CBasicSolveAndUpdate.
   12272             :     X       -   solution
   12273             : 
   12274             :   -- ALGLIB routine --
   12275             :      26.01.2009
   12276             :      Bochkanov Sergey
   12277             : *************************************************************************/
   12278           0 : static ae_bool safesolve_cbasicsolveandupdate(ae_complex alpha,
   12279             :      ae_complex beta,
   12280             :      double lnmax,
   12281             :      double bnorm,
   12282             :      double maxgrowth,
   12283             :      double* xnorm,
   12284             :      ae_complex* x,
   12285             :      ae_state *_state)
   12286             : {
   12287             :     double v;
   12288             :     ae_bool result;
   12289             : 
   12290           0 :     x->x = 0;
   12291           0 :     x->y = 0;
   12292             : 
   12293           0 :     result = ae_false;
   12294           0 :     if( ae_c_eq_d(alpha,(double)(0)) )
   12295             :     {
   12296           0 :         return result;
   12297             :     }
   12298           0 :     if( ae_c_neq_d(beta,(double)(0)) )
   12299             :     {
   12300             :         
   12301             :         /*
   12302             :          * alpha*x[i]=beta
   12303             :          */
   12304           0 :         v = ae_log(ae_c_abs(beta, _state), _state)-ae_log(ae_c_abs(alpha, _state), _state);
   12305           0 :         if( ae_fp_greater(v,lnmax) )
   12306             :         {
   12307           0 :             return result;
   12308             :         }
   12309           0 :         *x = ae_c_div(beta,alpha);
   12310             :     }
   12311             :     else
   12312             :     {
   12313             :         
   12314             :         /*
   12315             :          * alpha*x[i]=0
   12316             :          */
   12317           0 :         *x = ae_complex_from_i(0);
   12318             :     }
   12319             :     
   12320             :     /*
   12321             :      * update NrmX, test growth limit
   12322             :      */
   12323           0 :     *xnorm = ae_maxreal(*xnorm, ae_c_abs(*x, _state), _state);
   12324           0 :     if( ae_fp_greater(*xnorm,maxgrowth*bnorm) )
   12325             :     {
   12326           0 :         return result;
   12327             :     }
   12328           0 :     result = ae_true;
   12329           0 :     return result;
   12330             : }
   12331             : 
   12332             : 
   12333             : #endif
   12334             : #if defined(AE_COMPILE_HBLAS) || !defined(AE_PARTIAL_BUILD)
   12335             : 
   12336             : 
   12337           0 : void hermitianmatrixvectormultiply(/* Complex */ ae_matrix* a,
   12338             :      ae_bool isupper,
   12339             :      ae_int_t i1,
   12340             :      ae_int_t i2,
   12341             :      /* Complex */ ae_vector* x,
   12342             :      ae_complex alpha,
   12343             :      /* Complex */ ae_vector* y,
   12344             :      ae_state *_state)
   12345             : {
   12346             :     ae_int_t i;
   12347             :     ae_int_t ba1;
   12348             :     ae_int_t by1;
   12349             :     ae_int_t by2;
   12350             :     ae_int_t bx1;
   12351             :     ae_int_t bx2;
   12352             :     ae_int_t n;
   12353             :     ae_complex v;
   12354             : 
   12355             : 
   12356           0 :     n = i2-i1+1;
   12357           0 :     if( n<=0 )
   12358             :     {
   12359           0 :         return;
   12360             :     }
   12361             :     
   12362             :     /*
   12363             :      * Let A = L + D + U, where
   12364             :      *  L is strictly lower triangular (main diagonal is zero)
   12365             :      *  D is diagonal
   12366             :      *  U is strictly upper triangular (main diagonal is zero)
   12367             :      *
   12368             :      * A*x = L*x + D*x + U*x
   12369             :      *
   12370             :      * Calculate D*x first
   12371             :      */
   12372           0 :     for(i=i1; i<=i2; i++)
   12373             :     {
   12374           0 :         y->ptr.p_complex[i-i1+1] = ae_c_mul(a->ptr.pp_complex[i][i],x->ptr.p_complex[i-i1+1]);
   12375             :     }
   12376             :     
   12377             :     /*
   12378             :      * Add L*x + U*x
   12379             :      */
   12380           0 :     if( isupper )
   12381             :     {
   12382           0 :         for(i=i1; i<=i2-1; i++)
   12383             :         {
   12384             :             
   12385             :             /*
   12386             :              * Add L*x to the result
   12387             :              */
   12388           0 :             v = x->ptr.p_complex[i-i1+1];
   12389           0 :             by1 = i-i1+2;
   12390           0 :             by2 = n;
   12391           0 :             ba1 = i+1;
   12392           0 :             ae_v_caddc(&y->ptr.p_complex[by1], 1, &a->ptr.pp_complex[i][ba1], 1, "Conj", ae_v_len(by1,by2), v);
   12393             :             
   12394             :             /*
   12395             :              * Add U*x to the result
   12396             :              */
   12397           0 :             bx1 = i-i1+2;
   12398           0 :             bx2 = n;
   12399           0 :             ba1 = i+1;
   12400           0 :             v = ae_v_cdotproduct(&x->ptr.p_complex[bx1], 1, "N", &a->ptr.pp_complex[i][ba1], 1, "N", ae_v_len(bx1,bx2));
   12401           0 :             y->ptr.p_complex[i-i1+1] = ae_c_add(y->ptr.p_complex[i-i1+1],v);
   12402             :         }
   12403             :     }
   12404             :     else
   12405             :     {
   12406           0 :         for(i=i1+1; i<=i2; i++)
   12407             :         {
   12408             :             
   12409             :             /*
   12410             :              * Add L*x to the result
   12411             :              */
   12412           0 :             bx1 = 1;
   12413           0 :             bx2 = i-i1;
   12414           0 :             ba1 = i1;
   12415           0 :             v = ae_v_cdotproduct(&x->ptr.p_complex[bx1], 1, "N", &a->ptr.pp_complex[i][ba1], 1, "N", ae_v_len(bx1,bx2));
   12416           0 :             y->ptr.p_complex[i-i1+1] = ae_c_add(y->ptr.p_complex[i-i1+1],v);
   12417             :             
   12418             :             /*
   12419             :              * Add U*x to the result
   12420             :              */
   12421           0 :             v = x->ptr.p_complex[i-i1+1];
   12422           0 :             by1 = 1;
   12423           0 :             by2 = i-i1;
   12424           0 :             ba1 = i1;
   12425           0 :             ae_v_caddc(&y->ptr.p_complex[by1], 1, &a->ptr.pp_complex[i][ba1], 1, "Conj", ae_v_len(by1,by2), v);
   12426             :         }
   12427             :     }
   12428           0 :     ae_v_cmulc(&y->ptr.p_complex[1], 1, ae_v_len(1,n), alpha);
   12429             : }
   12430             : 
   12431             : 
   12432           0 : void hermitianrank2update(/* Complex */ ae_matrix* a,
   12433             :      ae_bool isupper,
   12434             :      ae_int_t i1,
   12435             :      ae_int_t i2,
   12436             :      /* Complex */ ae_vector* x,
   12437             :      /* Complex */ ae_vector* y,
   12438             :      /* Complex */ ae_vector* t,
   12439             :      ae_complex alpha,
   12440             :      ae_state *_state)
   12441             : {
   12442             :     ae_int_t i;
   12443             :     ae_int_t tp1;
   12444             :     ae_int_t tp2;
   12445             :     ae_complex v;
   12446             : 
   12447             : 
   12448           0 :     if( isupper )
   12449             :     {
   12450           0 :         for(i=i1; i<=i2; i++)
   12451             :         {
   12452           0 :             tp1 = i+1-i1;
   12453           0 :             tp2 = i2-i1+1;
   12454           0 :             v = ae_c_mul(alpha,x->ptr.p_complex[i+1-i1]);
   12455           0 :             ae_v_cmovec(&t->ptr.p_complex[tp1], 1, &y->ptr.p_complex[tp1], 1, "Conj", ae_v_len(tp1,tp2), v);
   12456           0 :             v = ae_c_mul(ae_c_conj(alpha, _state),y->ptr.p_complex[i+1-i1]);
   12457           0 :             ae_v_caddc(&t->ptr.p_complex[tp1], 1, &x->ptr.p_complex[tp1], 1, "Conj", ae_v_len(tp1,tp2), v);
   12458           0 :             ae_v_cadd(&a->ptr.pp_complex[i][i], 1, &t->ptr.p_complex[tp1], 1, "N", ae_v_len(i,i2));
   12459             :         }
   12460             :     }
   12461             :     else
   12462             :     {
   12463           0 :         for(i=i1; i<=i2; i++)
   12464             :         {
   12465           0 :             tp1 = 1;
   12466           0 :             tp2 = i+1-i1;
   12467           0 :             v = ae_c_mul(alpha,x->ptr.p_complex[i+1-i1]);
   12468           0 :             ae_v_cmovec(&t->ptr.p_complex[tp1], 1, &y->ptr.p_complex[tp1], 1, "Conj", ae_v_len(tp1,tp2), v);
   12469           0 :             v = ae_c_mul(ae_c_conj(alpha, _state),y->ptr.p_complex[i+1-i1]);
   12470           0 :             ae_v_caddc(&t->ptr.p_complex[tp1], 1, &x->ptr.p_complex[tp1], 1, "Conj", ae_v_len(tp1,tp2), v);
   12471           0 :             ae_v_cadd(&a->ptr.pp_complex[i][i1], 1, &t->ptr.p_complex[tp1], 1, "N", ae_v_len(i1,i));
   12472             :         }
   12473             :     }
   12474           0 : }
   12475             : 
   12476             : 
   12477             : #endif
   12478             : #if defined(AE_COMPILE_SBLAS) || !defined(AE_PARTIAL_BUILD)
   12479             : 
   12480             : 
   12481           0 : void symmetricmatrixvectormultiply(/* Real    */ ae_matrix* a,
   12482             :      ae_bool isupper,
   12483             :      ae_int_t i1,
   12484             :      ae_int_t i2,
   12485             :      /* Real    */ ae_vector* x,
   12486             :      double alpha,
   12487             :      /* Real    */ ae_vector* y,
   12488             :      ae_state *_state)
   12489             : {
   12490             :     ae_int_t i;
   12491             :     ae_int_t ba1;
   12492             :     ae_int_t ba2;
   12493             :     ae_int_t by1;
   12494             :     ae_int_t by2;
   12495             :     ae_int_t bx1;
   12496             :     ae_int_t bx2;
   12497             :     ae_int_t n;
   12498             :     double v;
   12499             : 
   12500             : 
   12501           0 :     n = i2-i1+1;
   12502           0 :     if( n<=0 )
   12503             :     {
   12504           0 :         return;
   12505             :     }
   12506             :     
   12507             :     /*
   12508             :      * Let A = L + D + U, where
   12509             :      *  L is strictly lower triangular (main diagonal is zero)
   12510             :      *  D is diagonal
   12511             :      *  U is strictly upper triangular (main diagonal is zero)
   12512             :      *
   12513             :      * A*x = L*x + D*x + U*x
   12514             :      *
   12515             :      * Calculate D*x first
   12516             :      */
   12517           0 :     for(i=i1; i<=i2; i++)
   12518             :     {
   12519           0 :         y->ptr.p_double[i-i1+1] = a->ptr.pp_double[i][i]*x->ptr.p_double[i-i1+1];
   12520             :     }
   12521             :     
   12522             :     /*
   12523             :      * Add L*x + U*x
   12524             :      */
   12525           0 :     if( isupper )
   12526             :     {
   12527           0 :         for(i=i1; i<=i2-1; i++)
   12528             :         {
   12529             :             
   12530             :             /*
   12531             :              * Add L*x to the result
   12532             :              */
   12533           0 :             v = x->ptr.p_double[i-i1+1];
   12534           0 :             by1 = i-i1+2;
   12535           0 :             by2 = n;
   12536           0 :             ba1 = i+1;
   12537           0 :             ba2 = i2;
   12538           0 :             ae_v_addd(&y->ptr.p_double[by1], 1, &a->ptr.pp_double[i][ba1], 1, ae_v_len(by1,by2), v);
   12539             :             
   12540             :             /*
   12541             :              * Add U*x to the result
   12542             :              */
   12543           0 :             bx1 = i-i1+2;
   12544           0 :             bx2 = n;
   12545           0 :             ba1 = i+1;
   12546           0 :             ba2 = i2;
   12547           0 :             v = ae_v_dotproduct(&x->ptr.p_double[bx1], 1, &a->ptr.pp_double[i][ba1], 1, ae_v_len(bx1,bx2));
   12548           0 :             y->ptr.p_double[i-i1+1] = y->ptr.p_double[i-i1+1]+v;
   12549             :         }
   12550             :     }
   12551             :     else
   12552             :     {
   12553           0 :         for(i=i1+1; i<=i2; i++)
   12554             :         {
   12555             :             
   12556             :             /*
   12557             :              * Add L*x to the result
   12558             :              */
   12559           0 :             bx1 = 1;
   12560           0 :             bx2 = i-i1;
   12561           0 :             ba1 = i1;
   12562           0 :             ba2 = i-1;
   12563           0 :             v = ae_v_dotproduct(&x->ptr.p_double[bx1], 1, &a->ptr.pp_double[i][ba1], 1, ae_v_len(bx1,bx2));
   12564           0 :             y->ptr.p_double[i-i1+1] = y->ptr.p_double[i-i1+1]+v;
   12565             :             
   12566             :             /*
   12567             :              * Add U*x to the result
   12568             :              */
   12569           0 :             v = x->ptr.p_double[i-i1+1];
   12570           0 :             by1 = 1;
   12571           0 :             by2 = i-i1;
   12572           0 :             ba1 = i1;
   12573           0 :             ba2 = i-1;
   12574           0 :             ae_v_addd(&y->ptr.p_double[by1], 1, &a->ptr.pp_double[i][ba1], 1, ae_v_len(by1,by2), v);
   12575             :         }
   12576             :     }
   12577           0 :     ae_v_muld(&y->ptr.p_double[1], 1, ae_v_len(1,n), alpha);
   12578           0 :     touchint(&ba2, _state);
   12579             : }
   12580             : 
   12581             : 
   12582           0 : void symmetricrank2update(/* Real    */ ae_matrix* a,
   12583             :      ae_bool isupper,
   12584             :      ae_int_t i1,
   12585             :      ae_int_t i2,
   12586             :      /* Real    */ ae_vector* x,
   12587             :      /* Real    */ ae_vector* y,
   12588             :      /* Real    */ ae_vector* t,
   12589             :      double alpha,
   12590             :      ae_state *_state)
   12591             : {
   12592             :     ae_int_t i;
   12593             :     ae_int_t tp1;
   12594             :     ae_int_t tp2;
   12595             :     double v;
   12596             : 
   12597             : 
   12598           0 :     if( isupper )
   12599             :     {
   12600           0 :         for(i=i1; i<=i2; i++)
   12601             :         {
   12602           0 :             tp1 = i+1-i1;
   12603           0 :             tp2 = i2-i1+1;
   12604           0 :             v = x->ptr.p_double[i+1-i1];
   12605           0 :             ae_v_moved(&t->ptr.p_double[tp1], 1, &y->ptr.p_double[tp1], 1, ae_v_len(tp1,tp2), v);
   12606           0 :             v = y->ptr.p_double[i+1-i1];
   12607           0 :             ae_v_addd(&t->ptr.p_double[tp1], 1, &x->ptr.p_double[tp1], 1, ae_v_len(tp1,tp2), v);
   12608           0 :             ae_v_muld(&t->ptr.p_double[tp1], 1, ae_v_len(tp1,tp2), alpha);
   12609           0 :             ae_v_add(&a->ptr.pp_double[i][i], 1, &t->ptr.p_double[tp1], 1, ae_v_len(i,i2));
   12610             :         }
   12611             :     }
   12612             :     else
   12613             :     {
   12614           0 :         for(i=i1; i<=i2; i++)
   12615             :         {
   12616           0 :             tp1 = 1;
   12617           0 :             tp2 = i+1-i1;
   12618           0 :             v = x->ptr.p_double[i+1-i1];
   12619           0 :             ae_v_moved(&t->ptr.p_double[tp1], 1, &y->ptr.p_double[tp1], 1, ae_v_len(tp1,tp2), v);
   12620           0 :             v = y->ptr.p_double[i+1-i1];
   12621           0 :             ae_v_addd(&t->ptr.p_double[tp1], 1, &x->ptr.p_double[tp1], 1, ae_v_len(tp1,tp2), v);
   12622           0 :             ae_v_muld(&t->ptr.p_double[tp1], 1, ae_v_len(tp1,tp2), alpha);
   12623           0 :             ae_v_add(&a->ptr.pp_double[i][i1], 1, &t->ptr.p_double[tp1], 1, ae_v_len(i1,i));
   12624             :         }
   12625             :     }
   12626           0 : }
   12627             : 
   12628             : 
   12629             : #endif
   12630             : #if defined(AE_COMPILE_BLAS) || !defined(AE_PARTIAL_BUILD)
   12631             : 
   12632             : 
   12633           0 : double vectornorm2(/* Real    */ ae_vector* x,
   12634             :      ae_int_t i1,
   12635             :      ae_int_t i2,
   12636             :      ae_state *_state)
   12637             : {
   12638             :     ae_int_t n;
   12639             :     ae_int_t ix;
   12640             :     double absxi;
   12641             :     double scl;
   12642             :     double ssq;
   12643             :     double result;
   12644             : 
   12645             : 
   12646           0 :     n = i2-i1+1;
   12647           0 :     if( n<1 )
   12648             :     {
   12649           0 :         result = (double)(0);
   12650           0 :         return result;
   12651             :     }
   12652           0 :     if( n==1 )
   12653             :     {
   12654           0 :         result = ae_fabs(x->ptr.p_double[i1], _state);
   12655           0 :         return result;
   12656             :     }
   12657           0 :     scl = (double)(0);
   12658           0 :     ssq = (double)(1);
   12659           0 :     for(ix=i1; ix<=i2; ix++)
   12660             :     {
   12661           0 :         if( ae_fp_neq(x->ptr.p_double[ix],(double)(0)) )
   12662             :         {
   12663           0 :             absxi = ae_fabs(x->ptr.p_double[ix], _state);
   12664           0 :             if( ae_fp_less(scl,absxi) )
   12665             :             {
   12666           0 :                 ssq = 1+ssq*ae_sqr(scl/absxi, _state);
   12667           0 :                 scl = absxi;
   12668             :             }
   12669             :             else
   12670             :             {
   12671           0 :                 ssq = ssq+ae_sqr(absxi/scl, _state);
   12672             :             }
   12673             :         }
   12674             :     }
   12675           0 :     result = scl*ae_sqrt(ssq, _state);
   12676           0 :     return result;
   12677             : }
   12678             : 
   12679             : 
   12680           0 : ae_int_t vectoridxabsmax(/* Real    */ ae_vector* x,
   12681             :      ae_int_t i1,
   12682             :      ae_int_t i2,
   12683             :      ae_state *_state)
   12684             : {
   12685             :     ae_int_t i;
   12686             :     ae_int_t result;
   12687             : 
   12688             : 
   12689           0 :     result = i1;
   12690           0 :     for(i=i1+1; i<=i2; i++)
   12691             :     {
   12692           0 :         if( ae_fp_greater(ae_fabs(x->ptr.p_double[i], _state),ae_fabs(x->ptr.p_double[result], _state)) )
   12693             :         {
   12694           0 :             result = i;
   12695             :         }
   12696             :     }
   12697           0 :     return result;
   12698             : }
   12699             : 
   12700             : 
   12701           0 : ae_int_t columnidxabsmax(/* Real    */ ae_matrix* x,
   12702             :      ae_int_t i1,
   12703             :      ae_int_t i2,
   12704             :      ae_int_t j,
   12705             :      ae_state *_state)
   12706             : {
   12707             :     ae_int_t i;
   12708             :     ae_int_t result;
   12709             : 
   12710             : 
   12711           0 :     result = i1;
   12712           0 :     for(i=i1+1; i<=i2; i++)
   12713             :     {
   12714           0 :         if( ae_fp_greater(ae_fabs(x->ptr.pp_double[i][j], _state),ae_fabs(x->ptr.pp_double[result][j], _state)) )
   12715             :         {
   12716           0 :             result = i;
   12717             :         }
   12718             :     }
   12719           0 :     return result;
   12720             : }
   12721             : 
   12722             : 
   12723           0 : ae_int_t rowidxabsmax(/* Real    */ ae_matrix* x,
   12724             :      ae_int_t j1,
   12725             :      ae_int_t j2,
   12726             :      ae_int_t i,
   12727             :      ae_state *_state)
   12728             : {
   12729             :     ae_int_t j;
   12730             :     ae_int_t result;
   12731             : 
   12732             : 
   12733           0 :     result = j1;
   12734           0 :     for(j=j1+1; j<=j2; j++)
   12735             :     {
   12736           0 :         if( ae_fp_greater(ae_fabs(x->ptr.pp_double[i][j], _state),ae_fabs(x->ptr.pp_double[i][result], _state)) )
   12737             :         {
   12738           0 :             result = j;
   12739             :         }
   12740             :     }
   12741           0 :     return result;
   12742             : }
   12743             : 
   12744             : 
   12745           0 : double upperhessenberg1norm(/* Real    */ ae_matrix* a,
   12746             :      ae_int_t i1,
   12747             :      ae_int_t i2,
   12748             :      ae_int_t j1,
   12749             :      ae_int_t j2,
   12750             :      /* Real    */ ae_vector* work,
   12751             :      ae_state *_state)
   12752             : {
   12753             :     ae_int_t i;
   12754             :     ae_int_t j;
   12755             :     double result;
   12756             : 
   12757             : 
   12758           0 :     ae_assert(i2-i1==j2-j1, "UpperHessenberg1Norm: I2-I1<>J2-J1!", _state);
   12759           0 :     for(j=j1; j<=j2; j++)
   12760             :     {
   12761           0 :         work->ptr.p_double[j] = (double)(0);
   12762             :     }
   12763           0 :     for(i=i1; i<=i2; i++)
   12764             :     {
   12765           0 :         for(j=ae_maxint(j1, j1+i-i1-1, _state); j<=j2; j++)
   12766             :         {
   12767           0 :             work->ptr.p_double[j] = work->ptr.p_double[j]+ae_fabs(a->ptr.pp_double[i][j], _state);
   12768             :         }
   12769             :     }
   12770           0 :     result = (double)(0);
   12771           0 :     for(j=j1; j<=j2; j++)
   12772             :     {
   12773           0 :         result = ae_maxreal(result, work->ptr.p_double[j], _state);
   12774             :     }
   12775           0 :     return result;
   12776             : }
   12777             : 
   12778             : 
   12779           0 : void copymatrix(/* Real    */ ae_matrix* a,
   12780             :      ae_int_t is1,
   12781             :      ae_int_t is2,
   12782             :      ae_int_t js1,
   12783             :      ae_int_t js2,
   12784             :      /* Real    */ ae_matrix* b,
   12785             :      ae_int_t id1,
   12786             :      ae_int_t id2,
   12787             :      ae_int_t jd1,
   12788             :      ae_int_t jd2,
   12789             :      ae_state *_state)
   12790             : {
   12791             :     ae_int_t isrc;
   12792             :     ae_int_t idst;
   12793             : 
   12794             : 
   12795           0 :     if( is1>is2||js1>js2 )
   12796             :     {
   12797           0 :         return;
   12798             :     }
   12799           0 :     ae_assert(is2-is1==id2-id1, "CopyMatrix: different sizes!", _state);
   12800           0 :     ae_assert(js2-js1==jd2-jd1, "CopyMatrix: different sizes!", _state);
   12801           0 :     for(isrc=is1; isrc<=is2; isrc++)
   12802             :     {
   12803           0 :         idst = isrc-is1+id1;
   12804           0 :         ae_v_move(&b->ptr.pp_double[idst][jd1], 1, &a->ptr.pp_double[isrc][js1], 1, ae_v_len(jd1,jd2));
   12805             :     }
   12806             : }
   12807             : 
   12808             : 
   12809           0 : void inplacetranspose(/* Real    */ ae_matrix* a,
   12810             :      ae_int_t i1,
   12811             :      ae_int_t i2,
   12812             :      ae_int_t j1,
   12813             :      ae_int_t j2,
   12814             :      /* Real    */ ae_vector* work,
   12815             :      ae_state *_state)
   12816             : {
   12817             :     ae_int_t i;
   12818             :     ae_int_t j;
   12819             :     ae_int_t ips;
   12820             :     ae_int_t jps;
   12821             :     ae_int_t l;
   12822             : 
   12823             : 
   12824           0 :     if( i1>i2||j1>j2 )
   12825             :     {
   12826           0 :         return;
   12827             :     }
   12828           0 :     ae_assert(i1-i2==j1-j2, "InplaceTranspose error: incorrect array size!", _state);
   12829           0 :     for(i=i1; i<=i2-1; i++)
   12830             :     {
   12831           0 :         j = j1+i-i1;
   12832           0 :         ips = i+1;
   12833           0 :         jps = j1+ips-i1;
   12834           0 :         l = i2-i;
   12835           0 :         ae_v_move(&work->ptr.p_double[1], 1, &a->ptr.pp_double[ips][j], a->stride, ae_v_len(1,l));
   12836           0 :         ae_v_move(&a->ptr.pp_double[ips][j], a->stride, &a->ptr.pp_double[i][jps], 1, ae_v_len(ips,i2));
   12837           0 :         ae_v_move(&a->ptr.pp_double[i][jps], 1, &work->ptr.p_double[1], 1, ae_v_len(jps,j2));
   12838             :     }
   12839             : }
   12840             : 
   12841             : 
   12842           0 : void copyandtranspose(/* Real    */ ae_matrix* a,
   12843             :      ae_int_t is1,
   12844             :      ae_int_t is2,
   12845             :      ae_int_t js1,
   12846             :      ae_int_t js2,
   12847             :      /* Real    */ ae_matrix* b,
   12848             :      ae_int_t id1,
   12849             :      ae_int_t id2,
   12850             :      ae_int_t jd1,
   12851             :      ae_int_t jd2,
   12852             :      ae_state *_state)
   12853             : {
   12854             :     ae_int_t isrc;
   12855             :     ae_int_t jdst;
   12856             : 
   12857             : 
   12858           0 :     if( is1>is2||js1>js2 )
   12859             :     {
   12860           0 :         return;
   12861             :     }
   12862           0 :     ae_assert(is2-is1==jd2-jd1, "CopyAndTranspose: different sizes!", _state);
   12863           0 :     ae_assert(js2-js1==id2-id1, "CopyAndTranspose: different sizes!", _state);
   12864           0 :     for(isrc=is1; isrc<=is2; isrc++)
   12865             :     {
   12866           0 :         jdst = isrc-is1+jd1;
   12867           0 :         ae_v_move(&b->ptr.pp_double[id1][jdst], b->stride, &a->ptr.pp_double[isrc][js1], 1, ae_v_len(id1,id2));
   12868             :     }
   12869             : }
   12870             : 
   12871             : 
   12872           0 : void matrixvectormultiply(/* Real    */ ae_matrix* a,
   12873             :      ae_int_t i1,
   12874             :      ae_int_t i2,
   12875             :      ae_int_t j1,
   12876             :      ae_int_t j2,
   12877             :      ae_bool trans,
   12878             :      /* Real    */ ae_vector* x,
   12879             :      ae_int_t ix1,
   12880             :      ae_int_t ix2,
   12881             :      double alpha,
   12882             :      /* Real    */ ae_vector* y,
   12883             :      ae_int_t iy1,
   12884             :      ae_int_t iy2,
   12885             :      double beta,
   12886             :      ae_state *_state)
   12887             : {
   12888             :     ae_int_t i;
   12889             :     double v;
   12890             : 
   12891             : 
   12892           0 :     if( !trans )
   12893             :     {
   12894             :         
   12895             :         /*
   12896             :          * y := alpha*A*x + beta*y;
   12897             :          */
   12898           0 :         if( i1>i2||j1>j2 )
   12899             :         {
   12900           0 :             return;
   12901             :         }
   12902           0 :         ae_assert(j2-j1==ix2-ix1, "MatrixVectorMultiply: A and X dont match!", _state);
   12903           0 :         ae_assert(i2-i1==iy2-iy1, "MatrixVectorMultiply: A and Y dont match!", _state);
   12904             :         
   12905             :         /*
   12906             :          * beta*y
   12907             :          */
   12908           0 :         if( ae_fp_eq(beta,(double)(0)) )
   12909             :         {
   12910           0 :             for(i=iy1; i<=iy2; i++)
   12911             :             {
   12912           0 :                 y->ptr.p_double[i] = (double)(0);
   12913             :             }
   12914             :         }
   12915             :         else
   12916             :         {
   12917           0 :             ae_v_muld(&y->ptr.p_double[iy1], 1, ae_v_len(iy1,iy2), beta);
   12918             :         }
   12919             :         
   12920             :         /*
   12921             :          * alpha*A*x
   12922             :          */
   12923           0 :         for(i=i1; i<=i2; i++)
   12924             :         {
   12925           0 :             v = ae_v_dotproduct(&a->ptr.pp_double[i][j1], 1, &x->ptr.p_double[ix1], 1, ae_v_len(j1,j2));
   12926           0 :             y->ptr.p_double[iy1+i-i1] = y->ptr.p_double[iy1+i-i1]+alpha*v;
   12927             :         }
   12928             :     }
   12929             :     else
   12930             :     {
   12931             :         
   12932             :         /*
   12933             :          * y := alpha*A'*x + beta*y;
   12934             :          */
   12935           0 :         if( i1>i2||j1>j2 )
   12936             :         {
   12937           0 :             return;
   12938             :         }
   12939           0 :         ae_assert(i2-i1==ix2-ix1, "MatrixVectorMultiply: A and X dont match!", _state);
   12940           0 :         ae_assert(j2-j1==iy2-iy1, "MatrixVectorMultiply: A and Y dont match!", _state);
   12941             :         
   12942             :         /*
   12943             :          * beta*y
   12944             :          */
   12945           0 :         if( ae_fp_eq(beta,(double)(0)) )
   12946             :         {
   12947           0 :             for(i=iy1; i<=iy2; i++)
   12948             :             {
   12949           0 :                 y->ptr.p_double[i] = (double)(0);
   12950             :             }
   12951             :         }
   12952             :         else
   12953             :         {
   12954           0 :             ae_v_muld(&y->ptr.p_double[iy1], 1, ae_v_len(iy1,iy2), beta);
   12955             :         }
   12956             :         
   12957             :         /*
   12958             :          * alpha*A'*x
   12959             :          */
   12960           0 :         for(i=i1; i<=i2; i++)
   12961             :         {
   12962           0 :             v = alpha*x->ptr.p_double[ix1+i-i1];
   12963           0 :             ae_v_addd(&y->ptr.p_double[iy1], 1, &a->ptr.pp_double[i][j1], 1, ae_v_len(iy1,iy2), v);
   12964             :         }
   12965             :     }
   12966             : }
   12967             : 
   12968             : 
   12969           0 : double pythag2(double x, double y, ae_state *_state)
   12970             : {
   12971             :     double w;
   12972             :     double xabs;
   12973             :     double yabs;
   12974             :     double z;
   12975             :     double result;
   12976             : 
   12977             : 
   12978           0 :     xabs = ae_fabs(x, _state);
   12979           0 :     yabs = ae_fabs(y, _state);
   12980           0 :     w = ae_maxreal(xabs, yabs, _state);
   12981           0 :     z = ae_minreal(xabs, yabs, _state);
   12982           0 :     if( ae_fp_eq(z,(double)(0)) )
   12983             :     {
   12984           0 :         result = w;
   12985             :     }
   12986             :     else
   12987             :     {
   12988           0 :         result = w*ae_sqrt(1+ae_sqr(z/w, _state), _state);
   12989             :     }
   12990           0 :     return result;
   12991             : }
   12992             : 
   12993             : 
   12994           0 : void matrixmatrixmultiply(/* Real    */ ae_matrix* a,
   12995             :      ae_int_t ai1,
   12996             :      ae_int_t ai2,
   12997             :      ae_int_t aj1,
   12998             :      ae_int_t aj2,
   12999             :      ae_bool transa,
   13000             :      /* Real    */ ae_matrix* b,
   13001             :      ae_int_t bi1,
   13002             :      ae_int_t bi2,
   13003             :      ae_int_t bj1,
   13004             :      ae_int_t bj2,
   13005             :      ae_bool transb,
   13006             :      double alpha,
   13007             :      /* Real    */ ae_matrix* c,
   13008             :      ae_int_t ci1,
   13009             :      ae_int_t ci2,
   13010             :      ae_int_t cj1,
   13011             :      ae_int_t cj2,
   13012             :      double beta,
   13013             :      /* Real    */ ae_vector* work,
   13014             :      ae_state *_state)
   13015             : {
   13016             :     ae_int_t arows;
   13017             :     ae_int_t acols;
   13018             :     ae_int_t brows;
   13019             :     ae_int_t bcols;
   13020             :     ae_int_t crows;
   13021             :     ae_int_t i;
   13022             :     ae_int_t j;
   13023             :     ae_int_t k;
   13024             :     ae_int_t l;
   13025             :     ae_int_t r;
   13026             :     double v;
   13027             : 
   13028             : 
   13029             :     
   13030             :     /*
   13031             :      * Setup
   13032             :      */
   13033           0 :     if( !transa )
   13034             :     {
   13035           0 :         arows = ai2-ai1+1;
   13036           0 :         acols = aj2-aj1+1;
   13037             :     }
   13038             :     else
   13039             :     {
   13040           0 :         arows = aj2-aj1+1;
   13041           0 :         acols = ai2-ai1+1;
   13042             :     }
   13043           0 :     if( !transb )
   13044             :     {
   13045           0 :         brows = bi2-bi1+1;
   13046           0 :         bcols = bj2-bj1+1;
   13047             :     }
   13048             :     else
   13049             :     {
   13050           0 :         brows = bj2-bj1+1;
   13051           0 :         bcols = bi2-bi1+1;
   13052             :     }
   13053           0 :     ae_assert(acols==brows, "MatrixMatrixMultiply: incorrect matrix sizes!", _state);
   13054           0 :     if( ((arows<=0||acols<=0)||brows<=0)||bcols<=0 )
   13055             :     {
   13056           0 :         return;
   13057             :     }
   13058           0 :     crows = arows;
   13059             :     
   13060             :     /*
   13061             :      * Test WORK
   13062             :      */
   13063           0 :     i = ae_maxint(arows, acols, _state);
   13064           0 :     i = ae_maxint(brows, i, _state);
   13065           0 :     i = ae_maxint(i, bcols, _state);
   13066           0 :     work->ptr.p_double[1] = (double)(0);
   13067           0 :     work->ptr.p_double[i] = (double)(0);
   13068             :     
   13069             :     /*
   13070             :      * Prepare C
   13071             :      */
   13072           0 :     if( ae_fp_eq(beta,(double)(0)) )
   13073             :     {
   13074           0 :         for(i=ci1; i<=ci2; i++)
   13075             :         {
   13076           0 :             for(j=cj1; j<=cj2; j++)
   13077             :             {
   13078           0 :                 c->ptr.pp_double[i][j] = (double)(0);
   13079             :             }
   13080             :         }
   13081             :     }
   13082             :     else
   13083             :     {
   13084           0 :         for(i=ci1; i<=ci2; i++)
   13085             :         {
   13086           0 :             ae_v_muld(&c->ptr.pp_double[i][cj1], 1, ae_v_len(cj1,cj2), beta);
   13087             :         }
   13088             :     }
   13089             :     
   13090             :     /*
   13091             :      * A*B
   13092             :      */
   13093           0 :     if( !transa&&!transb )
   13094             :     {
   13095           0 :         for(l=ai1; l<=ai2; l++)
   13096             :         {
   13097           0 :             for(r=bi1; r<=bi2; r++)
   13098             :             {
   13099           0 :                 v = alpha*a->ptr.pp_double[l][aj1+r-bi1];
   13100           0 :                 k = ci1+l-ai1;
   13101           0 :                 ae_v_addd(&c->ptr.pp_double[k][cj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(cj1,cj2), v);
   13102             :             }
   13103             :         }
   13104           0 :         return;
   13105             :     }
   13106             :     
   13107             :     /*
   13108             :      * A*B'
   13109             :      */
   13110           0 :     if( !transa&&transb )
   13111             :     {
   13112           0 :         if( arows*acols<brows*bcols )
   13113             :         {
   13114           0 :             for(r=bi1; r<=bi2; r++)
   13115             :             {
   13116           0 :                 for(l=ai1; l<=ai2; l++)
   13117             :                 {
   13118           0 :                     v = ae_v_dotproduct(&a->ptr.pp_double[l][aj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(aj1,aj2));
   13119           0 :                     c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1] = c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1]+alpha*v;
   13120             :                 }
   13121             :             }
   13122           0 :             return;
   13123             :         }
   13124             :         else
   13125             :         {
   13126           0 :             for(l=ai1; l<=ai2; l++)
   13127             :             {
   13128           0 :                 for(r=bi1; r<=bi2; r++)
   13129             :                 {
   13130           0 :                     v = ae_v_dotproduct(&a->ptr.pp_double[l][aj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(aj1,aj2));
   13131           0 :                     c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1] = c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1]+alpha*v;
   13132             :                 }
   13133             :             }
   13134           0 :             return;
   13135             :         }
   13136             :     }
   13137             :     
   13138             :     /*
   13139             :      * A'*B
   13140             :      */
   13141           0 :     if( transa&&!transb )
   13142             :     {
   13143           0 :         for(l=aj1; l<=aj2; l++)
   13144             :         {
   13145           0 :             for(r=bi1; r<=bi2; r++)
   13146             :             {
   13147           0 :                 v = alpha*a->ptr.pp_double[ai1+r-bi1][l];
   13148           0 :                 k = ci1+l-aj1;
   13149           0 :                 ae_v_addd(&c->ptr.pp_double[k][cj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(cj1,cj2), v);
   13150             :             }
   13151             :         }
   13152           0 :         return;
   13153             :     }
   13154             :     
   13155             :     /*
   13156             :      * A'*B'
   13157             :      */
   13158           0 :     if( transa&&transb )
   13159             :     {
   13160           0 :         if( arows*acols<brows*bcols )
   13161             :         {
   13162           0 :             for(r=bi1; r<=bi2; r++)
   13163             :             {
   13164           0 :                 k = cj1+r-bi1;
   13165           0 :                 for(i=1; i<=crows; i++)
   13166             :                 {
   13167           0 :                     work->ptr.p_double[i] = 0.0;
   13168             :                 }
   13169           0 :                 for(l=ai1; l<=ai2; l++)
   13170             :                 {
   13171           0 :                     v = alpha*b->ptr.pp_double[r][bj1+l-ai1];
   13172           0 :                     ae_v_addd(&work->ptr.p_double[1], 1, &a->ptr.pp_double[l][aj1], 1, ae_v_len(1,crows), v);
   13173             :                 }
   13174           0 :                 ae_v_add(&c->ptr.pp_double[ci1][k], c->stride, &work->ptr.p_double[1], 1, ae_v_len(ci1,ci2));
   13175             :             }
   13176           0 :             return;
   13177             :         }
   13178             :         else
   13179             :         {
   13180           0 :             for(l=aj1; l<=aj2; l++)
   13181             :             {
   13182           0 :                 k = ai2-ai1+1;
   13183           0 :                 ae_v_move(&work->ptr.p_double[1], 1, &a->ptr.pp_double[ai1][l], a->stride, ae_v_len(1,k));
   13184           0 :                 for(r=bi1; r<=bi2; r++)
   13185             :                 {
   13186           0 :                     v = ae_v_dotproduct(&work->ptr.p_double[1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(1,k));
   13187           0 :                     c->ptr.pp_double[ci1+l-aj1][cj1+r-bi1] = c->ptr.pp_double[ci1+l-aj1][cj1+r-bi1]+alpha*v;
   13188             :                 }
   13189             :             }
   13190           0 :             return;
   13191             :         }
   13192             :     }
   13193             : }
   13194             : 
   13195             : 
   13196             : #endif
   13197             : #if defined(AE_COMPILE_LINMIN) || !defined(AE_PARTIAL_BUILD)
   13198             : 
   13199             : 
   13200             : /*************************************************************************
   13201             : Normalizes direction/step pair: makes |D|=1, scales Stp.
   13202             : If |D|=0, it returns, leavind D/Stp unchanged.
   13203             : 
   13204             :   -- ALGLIB --
   13205             :      Copyright 01.04.2010 by Bochkanov Sergey
   13206             : *************************************************************************/
   13207        1269 : void linminnormalized(/* Real    */ ae_vector* d,
   13208             :      double* stp,
   13209             :      ae_int_t n,
   13210             :      ae_state *_state)
   13211             : {
   13212             :     double mx;
   13213             :     double s;
   13214             :     ae_int_t i;
   13215             : 
   13216             : 
   13217             :     
   13218             :     /*
   13219             :      * first, scale D to avoid underflow/overflow durng squaring
   13220             :      */
   13221        1269 :     mx = (double)(0);
   13222        3807 :     for(i=0; i<=n-1; i++)
   13223             :     {
   13224        2538 :         mx = ae_maxreal(mx, ae_fabs(d->ptr.p_double[i], _state), _state);
   13225             :     }
   13226        1269 :     if( ae_fp_eq(mx,(double)(0)) )
   13227             :     {
   13228           0 :         return;
   13229             :     }
   13230        1269 :     s = 1/mx;
   13231        1269 :     ae_v_muld(&d->ptr.p_double[0], 1, ae_v_len(0,n-1), s);
   13232        1269 :     *stp = *stp/s;
   13233             :     
   13234             :     /*
   13235             :      * normalize D
   13236             :      */
   13237        1269 :     s = ae_v_dotproduct(&d->ptr.p_double[0], 1, &d->ptr.p_double[0], 1, ae_v_len(0,n-1));
   13238        1269 :     s = 1/ae_sqrt(s, _state);
   13239        1269 :     ae_v_muld(&d->ptr.p_double[0], 1, ae_v_len(0,n-1), s);
   13240        1269 :     *stp = *stp/s;
   13241             : }
   13242             : 
   13243             : 
   13244             : /*************************************************************************
   13245             : THE  PURPOSE  OF  MCSRCH  IS  TO  FIND A STEP WHICH SATISFIES A SUFFICIENT
   13246             : DECREASE CONDITION AND A CURVATURE CONDITION.
   13247             : 
   13248             : AT EACH STAGE THE SUBROUTINE  UPDATES  AN  INTERVAL  OF  UNCERTAINTY  WITH
   13249             : ENDPOINTS  STX  AND  STY.  THE INTERVAL OF UNCERTAINTY IS INITIALLY CHOSEN
   13250             : SO THAT IT CONTAINS A MINIMIZER OF THE MODIFIED FUNCTION
   13251             : 
   13252             :     F(X+STP*S) - F(X) - FTOL*STP*(GRADF(X)'S).
   13253             : 
   13254             : IF  A STEP  IS OBTAINED FOR  WHICH THE MODIFIED FUNCTION HAS A NONPOSITIVE
   13255             : FUNCTION  VALUE  AND  NONNEGATIVE  DERIVATIVE,   THEN   THE   INTERVAL  OF
   13256             : UNCERTAINTY IS CHOSEN SO THAT IT CONTAINS A MINIMIZER OF F(X+STP*S).
   13257             : 
   13258             : THE  ALGORITHM  IS  DESIGNED TO FIND A STEP WHICH SATISFIES THE SUFFICIENT
   13259             : DECREASE CONDITION
   13260             : 
   13261             :     F(X+STP*S) .LE. F(X) + FTOL*STP*(GRADF(X)'S),
   13262             : 
   13263             : AND THE CURVATURE CONDITION
   13264             : 
   13265             :     ABS(GRADF(X+STP*S)'S)) .LE. GTOL*ABS(GRADF(X)'S).
   13266             : 
   13267             : IF  FTOL  IS  LESS  THAN GTOL AND IF, FOR EXAMPLE, THE FUNCTION IS BOUNDED
   13268             : BELOW,  THEN  THERE  IS  ALWAYS  A  STEP  WHICH SATISFIES BOTH CONDITIONS.
   13269             : IF  NO  STEP  CAN BE FOUND  WHICH  SATISFIES  BOTH  CONDITIONS,  THEN  THE
   13270             : ALGORITHM  USUALLY STOPS  WHEN  ROUNDING ERRORS  PREVENT FURTHER PROGRESS.
   13271             : IN THIS CASE STP ONLY SATISFIES THE SUFFICIENT DECREASE CONDITION.
   13272             : 
   13273             : 
   13274             : :::::::::::::IMPORTANT NOTES:::::::::::::
   13275             : 
   13276             : NOTE 1:
   13277             : 
   13278             : This routine  guarantees that it will stop at the last point where function
   13279             : value was calculated. It won't make several additional function evaluations
   13280             : after finding good point. So if you store function evaluations requested by
   13281             : this routine, you can be sure that last one is the point where we've stopped.
   13282             : 
   13283             : NOTE 2:
   13284             : 
   13285             : when 0<StpMax<StpMin, algorithm will terminate with INFO=5 and Stp=StpMax
   13286             : 
   13287             : NOTE 3:
   13288             : 
   13289             : this algorithm guarantees that, if MCINFO=1 or MCINFO=5, then:
   13290             : * F(final_point)<F(initial_point) - strict inequality
   13291             : * final_point<>initial_point - after rounding to machine precision
   13292             : 
   13293             : NOTE 4:
   13294             : 
   13295             : when non-descent direction is specified, algorithm stops with MCINFO=0,
   13296             : Stp=0 and initial point at X[].
   13297             : :::::::::::::::::::::::::::::::::::::::::
   13298             : 
   13299             : 
   13300             : PARAMETERS DESCRIPRION
   13301             : 
   13302             : STAGE IS ZERO ON FIRST CALL, ZERO ON FINAL EXIT
   13303             : 
   13304             : N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER OF VARIABLES.
   13305             : 
   13306             : X IS  AN  ARRAY  OF  LENGTH N. ON INPUT IT MUST CONTAIN THE BASE POINT FOR
   13307             : THE LINE SEARCH. ON OUTPUT IT CONTAINS X+STP*S.
   13308             : 
   13309             : F IS  A  VARIABLE. ON INPUT IT MUST CONTAIN THE VALUE OF F AT X. ON OUTPUT
   13310             : IT CONTAINS THE VALUE OF F AT X + STP*S.
   13311             : 
   13312             : G IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE GRADIENT OF F AT X.
   13313             : ON OUTPUT IT CONTAINS THE GRADIENT OF F AT X + STP*S.
   13314             : 
   13315             : S IS AN INPUT ARRAY OF LENGTH N WHICH SPECIFIES THE SEARCH DIRECTION.
   13316             : 
   13317             : STP  IS  A NONNEGATIVE VARIABLE. ON INPUT STP CONTAINS AN INITIAL ESTIMATE
   13318             : OF A SATISFACTORY STEP. ON OUTPUT STP CONTAINS THE FINAL ESTIMATE.
   13319             : 
   13320             : FTOL AND GTOL ARE NONNEGATIVE INPUT VARIABLES. TERMINATION OCCURS WHEN THE
   13321             : SUFFICIENT DECREASE CONDITION AND THE DIRECTIONAL DERIVATIVE CONDITION ARE
   13322             : SATISFIED.
   13323             : 
   13324             : XTOL IS A NONNEGATIVE INPUT VARIABLE. TERMINATION OCCURS WHEN THE RELATIVE
   13325             : WIDTH OF THE INTERVAL OF UNCERTAINTY IS AT MOST XTOL.
   13326             : 
   13327             : STPMIN AND STPMAX ARE NONNEGATIVE INPUT VARIABLES WHICH SPECIFY LOWER  AND
   13328             : UPPER BOUNDS FOR THE STEP.
   13329             : 
   13330             : MAXFEV IS A POSITIVE INTEGER INPUT VARIABLE. TERMINATION OCCURS WHEN THE
   13331             : NUMBER OF CALLS TO FCN IS AT LEAST MAXFEV BY THE END OF AN ITERATION.
   13332             : 
   13333             : INFO IS AN INTEGER OUTPUT VARIABLE SET AS FOLLOWS:
   13334             :     INFO = 0  IMPROPER INPUT PARAMETERS.
   13335             : 
   13336             :     INFO = 1  THE SUFFICIENT DECREASE CONDITION AND THE
   13337             :               DIRECTIONAL DERIVATIVE CONDITION HOLD.
   13338             : 
   13339             :     INFO = 2  RELATIVE WIDTH OF THE INTERVAL OF UNCERTAINTY
   13340             :               IS AT MOST XTOL.
   13341             : 
   13342             :     INFO = 3  NUMBER OF CALLS TO FCN HAS REACHED MAXFEV.
   13343             : 
   13344             :     INFO = 4  THE STEP IS AT THE LOWER BOUND STPMIN.
   13345             : 
   13346             :     INFO = 5  THE STEP IS AT THE UPPER BOUND STPMAX.
   13347             : 
   13348             :     INFO = 6  ROUNDING ERRORS PREVENT FURTHER PROGRESS.
   13349             :               THERE MAY NOT BE A STEP WHICH SATISFIES THE
   13350             :               SUFFICIENT DECREASE AND CURVATURE CONDITIONS.
   13351             :               TOLERANCES MAY BE TOO SMALL.
   13352             : 
   13353             : NFEV IS AN INTEGER OUTPUT VARIABLE SET TO THE NUMBER OF CALLS TO FCN.
   13354             : 
   13355             : WA IS A WORK ARRAY OF LENGTH N.
   13356             : 
   13357             : ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JUNE 1983
   13358             : JORGE J. MORE', DAVID J. THUENTE
   13359             : *************************************************************************/
   13360        5660 : void mcsrch(ae_int_t n,
   13361             :      /* Real    */ ae_vector* x,
   13362             :      double* f,
   13363             :      /* Real    */ ae_vector* g,
   13364             :      /* Real    */ ae_vector* s,
   13365             :      double* stp,
   13366             :      double stpmax,
   13367             :      double gtol,
   13368             :      ae_int_t* info,
   13369             :      ae_int_t* nfev,
   13370             :      /* Real    */ ae_vector* wa,
   13371             :      linminstate* state,
   13372             :      ae_int_t* stage,
   13373             :      ae_state *_state)
   13374             : {
   13375             :     ae_int_t i;
   13376             :     double v;
   13377             :     double p5;
   13378             :     double p66;
   13379             :     double zero;
   13380             : 
   13381             : 
   13382             :     
   13383             :     /*
   13384             :      * init
   13385             :      */
   13386        5660 :     p5 = 0.5;
   13387        5660 :     p66 = 0.66;
   13388        5660 :     state->xtrapf = 4.0;
   13389        5660 :     zero = (double)(0);
   13390        5660 :     if( ae_fp_eq(stpmax,(double)(0)) )
   13391             :     {
   13392        5660 :         stpmax = linmin_defstpmax;
   13393             :     }
   13394        5660 :     if( ae_fp_less(*stp,linmin_stpmin) )
   13395             :     {
   13396           0 :         *stp = linmin_stpmin;
   13397             :     }
   13398        5660 :     if( ae_fp_greater(*stp,stpmax) )
   13399             :     {
   13400           0 :         *stp = stpmax;
   13401             :     }
   13402             :     
   13403             :     /*
   13404             :      * Main cycle
   13405             :      */
   13406             :     for(;;)
   13407             :     {
   13408       11320 :         if( *stage==0 )
   13409             :         {
   13410             :             
   13411             :             /*
   13412             :              * NEXT
   13413             :              */
   13414        1269 :             *stage = 2;
   13415        1269 :             continue;
   13416             :         }
   13417       10051 :         if( *stage==2 )
   13418             :         {
   13419        1269 :             state->infoc = 1;
   13420        1269 :             *info = 0;
   13421             :             
   13422             :             /*
   13423             :              *     CHECK THE INPUT PARAMETERS FOR ERRORS.
   13424             :              */
   13425        1269 :             if( ae_fp_less(stpmax,linmin_stpmin)&&ae_fp_greater(stpmax,(double)(0)) )
   13426             :             {
   13427           0 :                 *info = 5;
   13428           0 :                 *stp = stpmax;
   13429           0 :                 *stage = 0;
   13430           0 :                 return;
   13431             :             }
   13432        1269 :             if( ((((((n<=0||ae_fp_less_eq(*stp,(double)(0)))||ae_fp_less(linmin_ftol,(double)(0)))||ae_fp_less(gtol,zero))||ae_fp_less(linmin_xtol,zero))||ae_fp_less(linmin_stpmin,zero))||ae_fp_less(stpmax,linmin_stpmin))||linmin_maxfev<=0 )
   13433             :             {
   13434           0 :                 *stage = 0;
   13435           0 :                 return;
   13436             :             }
   13437             :             
   13438             :             /*
   13439             :              *     COMPUTE THE INITIAL GRADIENT IN THE SEARCH DIRECTION
   13440             :              *     AND CHECK THAT S IS A DESCENT DIRECTION.
   13441             :              */
   13442        1269 :             v = ae_v_dotproduct(&g->ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1));
   13443        1269 :             state->dginit = v;
   13444        1269 :             if( ae_fp_greater_eq(state->dginit,(double)(0)) )
   13445             :             {
   13446           0 :                 *stage = 0;
   13447           0 :                 *stp = (double)(0);
   13448           0 :                 return;
   13449             :             }
   13450             :             
   13451             :             /*
   13452             :              *     INITIALIZE LOCAL VARIABLES.
   13453             :              */
   13454        1269 :             state->brackt = ae_false;
   13455        1269 :             state->stage1 = ae_true;
   13456        1269 :             *nfev = 0;
   13457        1269 :             state->finit = *f;
   13458        1269 :             state->dgtest = linmin_ftol*state->dginit;
   13459        1269 :             state->width = stpmax-linmin_stpmin;
   13460        1269 :             state->width1 = state->width/p5;
   13461        1269 :             ae_v_move(&wa->ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
   13462             :             
   13463             :             /*
   13464             :              *     THE VARIABLES STX, FX, DGX CONTAIN THE VALUES OF THE STEP,
   13465             :              *     FUNCTION, AND DIRECTIONAL DERIVATIVE AT THE BEST STEP.
   13466             :              *     THE VARIABLES STY, FY, DGY CONTAIN THE VALUE OF THE STEP,
   13467             :              *     FUNCTION, AND DERIVATIVE AT THE OTHER ENDPOINT OF
   13468             :              *     THE INTERVAL OF UNCERTAINTY.
   13469             :              *     THE VARIABLES STP, F, DG CONTAIN THE VALUES OF THE STEP,
   13470             :              *     FUNCTION, AND DERIVATIVE AT THE CURRENT STEP.
   13471             :              */
   13472        1269 :             state->stx = (double)(0);
   13473        1269 :             state->fx = state->finit;
   13474        1269 :             state->dgx = state->dginit;
   13475        1269 :             state->sty = (double)(0);
   13476        1269 :             state->fy = state->finit;
   13477        1269 :             state->dgy = state->dginit;
   13478             :             
   13479             :             /*
   13480             :              * NEXT
   13481             :              */
   13482        1269 :             *stage = 3;
   13483        1269 :             continue;
   13484             :         }
   13485        8782 :         if( *stage==3 )
   13486             :         {
   13487             :             
   13488             :             /*
   13489             :              *     START OF ITERATION.
   13490             :              *
   13491             :              *     SET THE MINIMUM AND MAXIMUM STEPS TO CORRESPOND
   13492             :              *     TO THE PRESENT INTERVAL OF UNCERTAINTY.
   13493             :              */
   13494        4391 :             if( state->brackt )
   13495             :             {
   13496        2631 :                 if( ae_fp_less(state->stx,state->sty) )
   13497             :                 {
   13498        2415 :                     state->stmin = state->stx;
   13499        2415 :                     state->stmax = state->sty;
   13500             :                 }
   13501             :                 else
   13502             :                 {
   13503         216 :                     state->stmin = state->sty;
   13504         216 :                     state->stmax = state->stx;
   13505             :                 }
   13506             :             }
   13507             :             else
   13508             :             {
   13509        1760 :                 state->stmin = state->stx;
   13510        1760 :                 state->stmax = *stp+state->xtrapf*(*stp-state->stx);
   13511             :             }
   13512             :             
   13513             :             /*
   13514             :              *        FORCE THE STEP TO BE WITHIN THE BOUNDS STPMAX AND STPMIN.
   13515             :              */
   13516        4391 :             if( ae_fp_greater(*stp,stpmax) )
   13517             :             {
   13518           0 :                 *stp = stpmax;
   13519             :             }
   13520        4391 :             if( ae_fp_less(*stp,linmin_stpmin) )
   13521             :             {
   13522           0 :                 *stp = linmin_stpmin;
   13523             :             }
   13524             :             
   13525             :             /*
   13526             :              *        IF AN UNUSUAL TERMINATION IS TO OCCUR THEN LET
   13527             :              *        STP BE THE LOWEST POINT OBTAINED SO FAR.
   13528             :              */
   13529        4391 :             if( (((state->brackt&&(ae_fp_less_eq(*stp,state->stmin)||ae_fp_greater_eq(*stp,state->stmax)))||*nfev>=linmin_maxfev-1)||state->infoc==0)||(state->brackt&&ae_fp_less_eq(state->stmax-state->stmin,linmin_xtol*state->stmax)) )
   13530             :             {
   13531         121 :                 *stp = state->stx;
   13532             :             }
   13533             :             
   13534             :             /*
   13535             :              *        EVALUATE THE FUNCTION AND GRADIENT AT STP
   13536             :              *        AND COMPUTE THE DIRECTIONAL DERIVATIVE.
   13537             :              */
   13538        4391 :             ae_v_move(&x->ptr.p_double[0], 1, &wa->ptr.p_double[0], 1, ae_v_len(0,n-1));
   13539        4391 :             ae_v_addd(&x->ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1), *stp);
   13540             :             
   13541             :             /*
   13542             :              * NEXT
   13543             :              */
   13544        4391 :             *stage = 4;
   13545        4391 :             return;
   13546             :         }
   13547        4391 :         if( *stage==4 )
   13548             :         {
   13549        4391 :             *info = 0;
   13550        4391 :             *nfev = *nfev+1;
   13551        4391 :             v = ae_v_dotproduct(&g->ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1));
   13552        4391 :             state->dg = v;
   13553        4391 :             state->ftest1 = state->finit+*stp*state->dgtest;
   13554             :             
   13555             :             /*
   13556             :              *        TEST FOR CONVERGENCE.
   13557             :              */
   13558        4391 :             if( (state->brackt&&(ae_fp_less_eq(*stp,state->stmin)||ae_fp_greater_eq(*stp,state->stmax)))||state->infoc==0 )
   13559             :             {
   13560         121 :                 *info = 6;
   13561             :             }
   13562        4391 :             if( ((ae_fp_eq(*stp,stpmax)&&ae_fp_less(*f,state->finit))&&ae_fp_less_eq(*f,state->ftest1))&&ae_fp_less_eq(state->dg,state->dgtest) )
   13563             :             {
   13564           0 :                 *info = 5;
   13565             :             }
   13566        4391 :             if( ae_fp_eq(*stp,linmin_stpmin)&&((ae_fp_greater_eq(*f,state->finit)||ae_fp_greater(*f,state->ftest1))||ae_fp_greater_eq(state->dg,state->dgtest)) )
   13567             :             {
   13568           0 :                 *info = 4;
   13569             :             }
   13570        4391 :             if( *nfev>=linmin_maxfev )
   13571             :             {
   13572         121 :                 *info = 3;
   13573             :             }
   13574        4391 :             if( state->brackt&&ae_fp_less_eq(state->stmax-state->stmin,linmin_xtol*state->stmax) )
   13575             :             {
   13576           0 :                 *info = 2;
   13577             :             }
   13578        4391 :             if( (ae_fp_less(*f,state->finit)&&ae_fp_less_eq(*f,state->ftest1))&&ae_fp_less_eq(ae_fabs(state->dg, _state),-gtol*state->dginit) )
   13579             :             {
   13580        1148 :                 *info = 1;
   13581             :             }
   13582             :             
   13583             :             /*
   13584             :              *        CHECK FOR TERMINATION.
   13585             :              */
   13586        4391 :             if( *info!=0 )
   13587             :             {
   13588             :                 
   13589             :                 /*
   13590             :                  * Check guarantees provided by the function for INFO=1 or INFO=5
   13591             :                  */
   13592        1269 :                 if( *info==1||*info==5 )
   13593             :                 {
   13594        1148 :                     v = 0.0;
   13595        3444 :                     for(i=0; i<=n-1; i++)
   13596             :                     {
   13597        2296 :                         v = v+(wa->ptr.p_double[i]-x->ptr.p_double[i])*(wa->ptr.p_double[i]-x->ptr.p_double[i]);
   13598             :                     }
   13599        1148 :                     if( ae_fp_greater_eq(*f,state->finit)||ae_fp_eq(v,0.0) )
   13600             :                     {
   13601           0 :                         *info = 6;
   13602             :                     }
   13603             :                 }
   13604        1269 :                 *stage = 0;
   13605        1269 :                 return;
   13606             :             }
   13607             :             
   13608             :             /*
   13609             :              *        IN THE FIRST STAGE WE SEEK A STEP FOR WHICH THE MODIFIED
   13610             :              *        FUNCTION HAS A NONPOSITIVE VALUE AND NONNEGATIVE DERIVATIVE.
   13611             :              */
   13612        3122 :             if( (state->stage1&&ae_fp_less_eq(*f,state->ftest1))&&ae_fp_greater_eq(state->dg,ae_minreal(linmin_ftol, gtol, _state)*state->dginit) )
   13613             :             {
   13614         113 :                 state->stage1 = ae_false;
   13615             :             }
   13616             :             
   13617             :             /*
   13618             :              *        A MODIFIED FUNCTION IS USED TO PREDICT THE STEP ONLY IF
   13619             :              *        WE HAVE NOT OBTAINED A STEP FOR WHICH THE MODIFIED
   13620             :              *        FUNCTION HAS A NONPOSITIVE FUNCTION VALUE AND NONNEGATIVE
   13621             :              *        DERIVATIVE, AND IF A LOWER FUNCTION VALUE HAS BEEN
   13622             :              *        OBTAINED BUT THE DECREASE IS NOT SUFFICIENT.
   13623             :              */
   13624        3122 :             if( (state->stage1&&ae_fp_less_eq(*f,state->fx))&&ae_fp_greater(*f,state->ftest1) )
   13625             :             {
   13626             :                 
   13627             :                 /*
   13628             :                  *           DEFINE THE MODIFIED FUNCTION AND DERIVATIVE VALUES.
   13629             :                  */
   13630           4 :                 state->fm = *f-*stp*state->dgtest;
   13631           4 :                 state->fxm = state->fx-state->stx*state->dgtest;
   13632           4 :                 state->fym = state->fy-state->sty*state->dgtest;
   13633           4 :                 state->dgm = state->dg-state->dgtest;
   13634           4 :                 state->dgxm = state->dgx-state->dgtest;
   13635           4 :                 state->dgym = state->dgy-state->dgtest;
   13636             :                 
   13637             :                 /*
   13638             :                  *           CALL CSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY
   13639             :                  *           AND TO COMPUTE THE NEW STEP.
   13640             :                  */
   13641           4 :                 linmin_mcstep(&state->stx, &state->fxm, &state->dgxm, &state->sty, &state->fym, &state->dgym, stp, state->fm, state->dgm, &state->brackt, state->stmin, state->stmax, &state->infoc, _state);
   13642             :                 
   13643             :                 /*
   13644             :                  *           RESET THE FUNCTION AND GRADIENT VALUES FOR F.
   13645             :                  */
   13646           4 :                 state->fx = state->fxm+state->stx*state->dgtest;
   13647           4 :                 state->fy = state->fym+state->sty*state->dgtest;
   13648           4 :                 state->dgx = state->dgxm+state->dgtest;
   13649           4 :                 state->dgy = state->dgym+state->dgtest;
   13650             :             }
   13651             :             else
   13652             :             {
   13653             :                 
   13654             :                 /*
   13655             :                  *           CALL MCSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY
   13656             :                  *           AND TO COMPUTE THE NEW STEP.
   13657             :                  */
   13658        3118 :                 linmin_mcstep(&state->stx, &state->fx, &state->dgx, &state->sty, &state->fy, &state->dgy, stp, *f, state->dg, &state->brackt, state->stmin, state->stmax, &state->infoc, _state);
   13659             :             }
   13660             :             
   13661             :             /*
   13662             :              *        FORCE A SUFFICIENT DECREASE IN THE SIZE OF THE
   13663             :              *        INTERVAL OF UNCERTAINTY.
   13664             :              */
   13665        3122 :             if( state->brackt )
   13666             :             {
   13667        2631 :                 if( ae_fp_greater_eq(ae_fabs(state->sty-state->stx, _state),p66*state->width1) )
   13668             :                 {
   13669         314 :                     *stp = state->stx+p5*(state->sty-state->stx);
   13670             :                 }
   13671        2631 :                 state->width1 = state->width;
   13672        2631 :                 state->width = ae_fabs(state->sty-state->stx, _state);
   13673             :             }
   13674             :             
   13675             :             /*
   13676             :              *  NEXT.
   13677             :              */
   13678        3122 :             *stage = 3;
   13679        3122 :             continue;
   13680             :         }
   13681             :     }
   13682             : }
   13683             : 
   13684             : 
   13685             : /*************************************************************************
   13686             : These functions perform Armijo line search using  at  most  FMAX  function
   13687             : evaluations.  It  doesn't  enforce  some  kind  of  " sufficient decrease"
   13688             : criterion - it just tries different Armijo steps and returns optimum found
   13689             : so far.
   13690             : 
   13691             : Optimization is done using F-rcomm interface:
   13692             : * ArmijoCreate initializes State structure
   13693             :   (reusing previously allocated buffers)
   13694             : * ArmijoIteration is subsequently called
   13695             : * ArmijoResults returns results
   13696             : 
   13697             : INPUT PARAMETERS:
   13698             :     N       -   problem size
   13699             :     X       -   array[N], starting point
   13700             :     F       -   F(X+S*STP)
   13701             :     S       -   step direction, S>0
   13702             :     STP     -   step length
   13703             :     STPMAX  -   maximum value for STP or zero (if no limit is imposed)
   13704             :     FMAX    -   maximum number of function evaluations
   13705             :     State   -   optimization state
   13706             : 
   13707             :   -- ALGLIB --
   13708             :      Copyright 05.10.2010 by Bochkanov Sergey
   13709             : *************************************************************************/
   13710           0 : void armijocreate(ae_int_t n,
   13711             :      /* Real    */ ae_vector* x,
   13712             :      double f,
   13713             :      /* Real    */ ae_vector* s,
   13714             :      double stp,
   13715             :      double stpmax,
   13716             :      ae_int_t fmax,
   13717             :      armijostate* state,
   13718             :      ae_state *_state)
   13719             : {
   13720             : 
   13721             : 
   13722           0 :     if( state->x.cnt<n )
   13723             :     {
   13724           0 :         ae_vector_set_length(&state->x, n, _state);
   13725             :     }
   13726           0 :     if( state->xbase.cnt<n )
   13727             :     {
   13728           0 :         ae_vector_set_length(&state->xbase, n, _state);
   13729             :     }
   13730           0 :     if( state->s.cnt<n )
   13731             :     {
   13732           0 :         ae_vector_set_length(&state->s, n, _state);
   13733             :     }
   13734           0 :     state->stpmax = stpmax;
   13735           0 :     state->fmax = fmax;
   13736           0 :     state->stplen = stp;
   13737           0 :     state->fcur = f;
   13738           0 :     state->n = n;
   13739           0 :     ae_v_move(&state->xbase.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
   13740           0 :     ae_v_move(&state->s.ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1));
   13741           0 :     ae_vector_set_length(&state->rstate.ia, 0+1, _state);
   13742           0 :     ae_vector_set_length(&state->rstate.ra, 0+1, _state);
   13743           0 :     state->rstate.stage = -1;
   13744           0 : }
   13745             : 
   13746             : 
   13747             : /*************************************************************************
   13748             : This is rcomm-based search function
   13749             : 
   13750             :   -- ALGLIB --
   13751             :      Copyright 05.10.2010 by Bochkanov Sergey
   13752             : *************************************************************************/
   13753           0 : ae_bool armijoiteration(armijostate* state, ae_state *_state)
   13754             : {
   13755             :     double v;
   13756             :     ae_int_t n;
   13757             :     ae_bool result;
   13758             : 
   13759             : 
   13760             :     
   13761             :     /*
   13762             :      * Reverse communication preparations
   13763             :      * I know it looks ugly, but it works the same way
   13764             :      * anywhere from C++ to Python.
   13765             :      *
   13766             :      * This code initializes locals by:
   13767             :      * * random values determined during code
   13768             :      *   generation - on first subroutine call
   13769             :      * * values from previous call - on subsequent calls
   13770             :      */
   13771           0 :     if( state->rstate.stage>=0 )
   13772             :     {
   13773           0 :         n = state->rstate.ia.ptr.p_int[0];
   13774           0 :         v = state->rstate.ra.ptr.p_double[0];
   13775             :     }
   13776             :     else
   13777             :     {
   13778           0 :         n = 359;
   13779           0 :         v = -58;
   13780             :     }
   13781           0 :     if( state->rstate.stage==0 )
   13782             :     {
   13783           0 :         goto lbl_0;
   13784             :     }
   13785           0 :     if( state->rstate.stage==1 )
   13786             :     {
   13787           0 :         goto lbl_1;
   13788             :     }
   13789           0 :     if( state->rstate.stage==2 )
   13790             :     {
   13791           0 :         goto lbl_2;
   13792             :     }
   13793           0 :     if( state->rstate.stage==3 )
   13794             :     {
   13795           0 :         goto lbl_3;
   13796             :     }
   13797             :     
   13798             :     /*
   13799             :      * Routine body
   13800             :      */
   13801           0 :     if( (ae_fp_less_eq(state->stplen,(double)(0))||ae_fp_less(state->stpmax,(double)(0)))||state->fmax<2 )
   13802             :     {
   13803           0 :         state->info = 0;
   13804           0 :         result = ae_false;
   13805           0 :         return result;
   13806             :     }
   13807           0 :     if( ae_fp_less_eq(state->stplen,linmin_stpmin) )
   13808             :     {
   13809           0 :         state->info = 4;
   13810           0 :         result = ae_false;
   13811           0 :         return result;
   13812             :     }
   13813           0 :     n = state->n;
   13814           0 :     state->nfev = 0;
   13815             :     
   13816             :     /*
   13817             :      * We always need F
   13818             :      */
   13819           0 :     state->needf = ae_true;
   13820             :     
   13821             :     /*
   13822             :      * Bound StpLen
   13823             :      */
   13824           0 :     if( ae_fp_greater(state->stplen,state->stpmax)&&ae_fp_neq(state->stpmax,(double)(0)) )
   13825             :     {
   13826           0 :         state->stplen = state->stpmax;
   13827             :     }
   13828             :     
   13829             :     /*
   13830             :      * Increase length
   13831             :      */
   13832           0 :     v = state->stplen*linmin_armijofactor;
   13833           0 :     if( ae_fp_greater(v,state->stpmax)&&ae_fp_neq(state->stpmax,(double)(0)) )
   13834             :     {
   13835           0 :         v = state->stpmax;
   13836             :     }
   13837           0 :     ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
   13838           0 :     ae_v_addd(&state->x.ptr.p_double[0], 1, &state->s.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
   13839           0 :     state->rstate.stage = 0;
   13840           0 :     goto lbl_rcomm;
   13841           0 : lbl_0:
   13842           0 :     state->nfev = state->nfev+1;
   13843           0 :     if( ae_fp_greater_eq(state->f,state->fcur) )
   13844             :     {
   13845           0 :         goto lbl_4;
   13846             :     }
   13847           0 :     state->stplen = v;
   13848           0 :     state->fcur = state->f;
   13849           0 : lbl_6:
   13850             :     if( ae_false )
   13851             :     {
   13852             :         goto lbl_7;
   13853             :     }
   13854             :     
   13855             :     /*
   13856             :      * test stopping conditions
   13857             :      */
   13858           0 :     if( state->nfev>=state->fmax )
   13859             :     {
   13860           0 :         state->info = 3;
   13861           0 :         result = ae_false;
   13862           0 :         return result;
   13863             :     }
   13864           0 :     if( ae_fp_greater_eq(state->stplen,state->stpmax) )
   13865             :     {
   13866           0 :         state->info = 5;
   13867           0 :         result = ae_false;
   13868           0 :         return result;
   13869             :     }
   13870             :     
   13871             :     /*
   13872             :      * evaluate F
   13873             :      */
   13874           0 :     v = state->stplen*linmin_armijofactor;
   13875           0 :     if( ae_fp_greater(v,state->stpmax)&&ae_fp_neq(state->stpmax,(double)(0)) )
   13876             :     {
   13877           0 :         v = state->stpmax;
   13878             :     }
   13879           0 :     ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
   13880           0 :     ae_v_addd(&state->x.ptr.p_double[0], 1, &state->s.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
   13881           0 :     state->rstate.stage = 1;
   13882           0 :     goto lbl_rcomm;
   13883           0 : lbl_1:
   13884           0 :     state->nfev = state->nfev+1;
   13885             :     
   13886             :     /*
   13887             :      * make decision
   13888             :      */
   13889           0 :     if( ae_fp_less(state->f,state->fcur) )
   13890             :     {
   13891           0 :         state->stplen = v;
   13892           0 :         state->fcur = state->f;
   13893             :     }
   13894             :     else
   13895             :     {
   13896           0 :         state->info = 1;
   13897           0 :         result = ae_false;
   13898           0 :         return result;
   13899             :     }
   13900           0 :     goto lbl_6;
   13901           0 : lbl_7:
   13902           0 : lbl_4:
   13903             :     
   13904             :     /*
   13905             :      * Decrease length
   13906             :      */
   13907           0 :     v = state->stplen/linmin_armijofactor;
   13908           0 :     ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
   13909           0 :     ae_v_addd(&state->x.ptr.p_double[0], 1, &state->s.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
   13910           0 :     state->rstate.stage = 2;
   13911           0 :     goto lbl_rcomm;
   13912           0 : lbl_2:
   13913           0 :     state->nfev = state->nfev+1;
   13914           0 :     if( ae_fp_greater_eq(state->f,state->fcur) )
   13915             :     {
   13916           0 :         goto lbl_8;
   13917             :     }
   13918           0 :     state->stplen = state->stplen/linmin_armijofactor;
   13919           0 :     state->fcur = state->f;
   13920           0 : lbl_10:
   13921             :     if( ae_false )
   13922             :     {
   13923             :         goto lbl_11;
   13924             :     }
   13925             :     
   13926             :     /*
   13927             :      * test stopping conditions
   13928             :      */
   13929           0 :     if( state->nfev>=state->fmax )
   13930             :     {
   13931           0 :         state->info = 3;
   13932           0 :         result = ae_false;
   13933           0 :         return result;
   13934             :     }
   13935           0 :     if( ae_fp_less_eq(state->stplen,linmin_stpmin) )
   13936             :     {
   13937           0 :         state->info = 4;
   13938           0 :         result = ae_false;
   13939           0 :         return result;
   13940             :     }
   13941             :     
   13942             :     /*
   13943             :      * evaluate F
   13944             :      */
   13945           0 :     v = state->stplen/linmin_armijofactor;
   13946           0 :     ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
   13947           0 :     ae_v_addd(&state->x.ptr.p_double[0], 1, &state->s.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
   13948           0 :     state->rstate.stage = 3;
   13949           0 :     goto lbl_rcomm;
   13950           0 : lbl_3:
   13951           0 :     state->nfev = state->nfev+1;
   13952             :     
   13953             :     /*
   13954             :      * make decision
   13955             :      */
   13956           0 :     if( ae_fp_less(state->f,state->fcur) )
   13957             :     {
   13958           0 :         state->stplen = state->stplen/linmin_armijofactor;
   13959           0 :         state->fcur = state->f;
   13960             :     }
   13961             :     else
   13962             :     {
   13963           0 :         state->info = 1;
   13964           0 :         result = ae_false;
   13965           0 :         return result;
   13966             :     }
   13967           0 :     goto lbl_10;
   13968           0 : lbl_11:
   13969           0 : lbl_8:
   13970             :     
   13971             :     /*
   13972             :      * Nothing to be done
   13973             :      */
   13974           0 :     state->info = 1;
   13975           0 :     result = ae_false;
   13976           0 :     return result;
   13977             :     
   13978             :     /*
   13979             :      * Saving state
   13980             :      */
   13981           0 : lbl_rcomm:
   13982           0 :     result = ae_true;
   13983           0 :     state->rstate.ia.ptr.p_int[0] = n;
   13984           0 :     state->rstate.ra.ptr.p_double[0] = v;
   13985           0 :     return result;
   13986             : }
   13987             : 
   13988             : 
   13989             : /*************************************************************************
   13990             : Results of Armijo search
   13991             : 
   13992             : OUTPUT PARAMETERS:
   13993             :     INFO    -   on output it is set to one of the return codes:
   13994             :                 * 0     improper input params
   13995             :                 * 1     optimum step is found with at most FMAX evaluations
   13996             :                 * 3     FMAX evaluations were used,
   13997             :                         X contains optimum found so far
   13998             :                 * 4     step is at lower bound STPMIN
   13999             :                 * 5     step is at upper bound
   14000             :     STP     -   step length (in case of failure it is still returned)
   14001             :     F       -   function value (in case of failure it is still returned)
   14002             : 
   14003             :   -- ALGLIB --
   14004             :      Copyright 05.10.2010 by Bochkanov Sergey
   14005             : *************************************************************************/
   14006           0 : void armijoresults(armijostate* state,
   14007             :      ae_int_t* info,
   14008             :      double* stp,
   14009             :      double* f,
   14010             :      ae_state *_state)
   14011             : {
   14012             : 
   14013             : 
   14014           0 :     *info = state->info;
   14015           0 :     *stp = state->stplen;
   14016           0 :     *f = state->fcur;
   14017           0 : }
   14018             : 
   14019             : 
   14020        3122 : static void linmin_mcstep(double* stx,
   14021             :      double* fx,
   14022             :      double* dx,
   14023             :      double* sty,
   14024             :      double* fy,
   14025             :      double* dy,
   14026             :      double* stp,
   14027             :      double fp,
   14028             :      double dp,
   14029             :      ae_bool* brackt,
   14030             :      double stmin,
   14031             :      double stmax,
   14032             :      ae_int_t* info,
   14033             :      ae_state *_state)
   14034             : {
   14035             :     ae_bool bound;
   14036             :     double gamma;
   14037             :     double p;
   14038             :     double q;
   14039             :     double r;
   14040             :     double s;
   14041             :     double sgnd;
   14042             :     double stpc;
   14043             :     double stpf;
   14044             :     double stpq;
   14045             :     double theta;
   14046             : 
   14047             : 
   14048        3122 :     *info = 0;
   14049             :     
   14050             :     /*
   14051             :      *     CHECK THE INPUT PARAMETERS FOR ERRORS.
   14052             :      */
   14053        3122 :     if( ((*brackt&&(ae_fp_less_eq(*stp,ae_minreal(*stx, *sty, _state))||ae_fp_greater_eq(*stp,ae_maxreal(*stx, *sty, _state))))||ae_fp_greater_eq(*dx*(*stp-(*stx)),(double)(0)))||ae_fp_less(stmax,stmin) )
   14054             :     {
   14055           0 :         return;
   14056             :     }
   14057             :     
   14058             :     /*
   14059             :      *     DETERMINE IF THE DERIVATIVES HAVE OPPOSITE SIGN.
   14060             :      */
   14061        3122 :     sgnd = dp*(*dx/ae_fabs(*dx, _state));
   14062             :     
   14063             :     /*
   14064             :      *     FIRST CASE. A HIGHER FUNCTION VALUE.
   14065             :      *     THE MINIMUM IS BRACKETED. IF THE CUBIC STEP IS CLOSER
   14066             :      *     TO STX THAN THE QUADRATIC STEP, THE CUBIC STEP IS TAKEN,
   14067             :      *     ELSE THE AVERAGE OF THE CUBIC AND QUADRATIC STEPS IS TAKEN.
   14068             :      */
   14069        3122 :     if( ae_fp_greater(fp,*fx) )
   14070             :     {
   14071        1296 :         *info = 1;
   14072        1296 :         bound = ae_true;
   14073        1296 :         theta = 3*(*fx-fp)/(*stp-(*stx))+(*dx)+dp;
   14074        1296 :         s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dx, _state), ae_fabs(dp, _state), _state), _state);
   14075        1296 :         gamma = s*ae_sqrt(ae_sqr(theta/s, _state)-*dx/s*(dp/s), _state);
   14076        1296 :         if( ae_fp_less(*stp,*stx) )
   14077             :         {
   14078          34 :             gamma = -gamma;
   14079             :         }
   14080        1296 :         p = gamma-(*dx)+theta;
   14081        1296 :         q = gamma-(*dx)+gamma+dp;
   14082        1296 :         r = p/q;
   14083        1296 :         stpc = *stx+r*(*stp-(*stx));
   14084        1296 :         stpq = *stx+*dx/((*fx-fp)/(*stp-(*stx))+(*dx))/2*(*stp-(*stx));
   14085        1296 :         if( ae_fp_less(ae_fabs(stpc-(*stx), _state),ae_fabs(stpq-(*stx), _state)) )
   14086             :         {
   14087        1272 :             stpf = stpc;
   14088             :         }
   14089             :         else
   14090             :         {
   14091          24 :             stpf = stpc+(stpq-stpc)/2;
   14092             :         }
   14093        1296 :         *brackt = ae_true;
   14094             :     }
   14095             :     else
   14096             :     {
   14097        1826 :         if( ae_fp_less(sgnd,(double)(0)) )
   14098             :         {
   14099             :             
   14100             :             /*
   14101             :              *     SECOND CASE. A LOWER FUNCTION VALUE AND DERIVATIVES OF
   14102             :              *     OPPOSITE SIGN. THE MINIMUM IS BRACKETED. IF THE CUBIC
   14103             :              *     STEP IS CLOSER TO STX THAN THE QUADRATIC (SECANT) STEP,
   14104             :              *     THE CUBIC STEP IS TAKEN, ELSE THE QUADRATIC STEP IS TAKEN.
   14105             :              */
   14106         113 :             *info = 2;
   14107         113 :             bound = ae_false;
   14108         113 :             theta = 3*(*fx-fp)/(*stp-(*stx))+(*dx)+dp;
   14109         113 :             s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dx, _state), ae_fabs(dp, _state), _state), _state);
   14110         113 :             gamma = s*ae_sqrt(ae_sqr(theta/s, _state)-*dx/s*(dp/s), _state);
   14111         113 :             if( ae_fp_greater(*stp,*stx) )
   14112             :             {
   14113         113 :                 gamma = -gamma;
   14114             :             }
   14115         113 :             p = gamma-dp+theta;
   14116         113 :             q = gamma-dp+gamma+(*dx);
   14117         113 :             r = p/q;
   14118         113 :             stpc = *stp+r*(*stx-(*stp));
   14119         113 :             stpq = *stp+dp/(dp-(*dx))*(*stx-(*stp));
   14120         113 :             if( ae_fp_greater(ae_fabs(stpc-(*stp), _state),ae_fabs(stpq-(*stp), _state)) )
   14121             :             {
   14122          69 :                 stpf = stpc;
   14123             :             }
   14124             :             else
   14125             :             {
   14126          44 :                 stpf = stpq;
   14127             :             }
   14128         113 :             *brackt = ae_true;
   14129             :         }
   14130             :         else
   14131             :         {
   14132        1713 :             if( ae_fp_less(ae_fabs(dp, _state),ae_fabs(*dx, _state)) )
   14133             :             {
   14134             :                 
   14135             :                 /*
   14136             :                  *     THIRD CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE
   14137             :                  *     SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DECREASES.
   14138             :                  *     THE CUBIC STEP IS ONLY USED IF THE CUBIC TENDS TO INFINITY
   14139             :                  *     IN THE DIRECTION OF THE STEP OR IF THE MINIMUM OF THE CUBIC
   14140             :                  *     IS BEYOND STP. OTHERWISE THE CUBIC STEP IS DEFINED TO BE
   14141             :                  *     EITHER STPMIN OR STPMAX. THE QUADRATIC (SECANT) STEP IS ALSO
   14142             :                  *     COMPUTED AND IF THE MINIMUM IS BRACKETED THEN THE THE STEP
   14143             :                  *     CLOSEST TO STX IS TAKEN, ELSE THE STEP FARTHEST AWAY IS TAKEN.
   14144             :                  */
   14145        1300 :                 *info = 3;
   14146        1300 :                 bound = ae_true;
   14147        1300 :                 theta = 3*(*fx-fp)/(*stp-(*stx))+(*dx)+dp;
   14148        1300 :                 s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dx, _state), ae_fabs(dp, _state), _state), _state);
   14149             :                 
   14150             :                 /*
   14151             :                  *        THE CASE GAMMA = 0 ONLY ARISES IF THE CUBIC DOES NOT TEND
   14152             :                  *        TO INFINITY IN THE DIRECTION OF THE STEP.
   14153             :                  */
   14154        1300 :                 gamma = s*ae_sqrt(ae_maxreal((double)(0), ae_sqr(theta/s, _state)-*dx/s*(dp/s), _state), _state);
   14155        1300 :                 if( ae_fp_greater(*stp,*stx) )
   14156             :                 {
   14157        1270 :                     gamma = -gamma;
   14158             :                 }
   14159        1300 :                 p = gamma-dp+theta;
   14160        1300 :                 q = gamma+(*dx-dp)+gamma;
   14161        1300 :                 r = p/q;
   14162        1300 :                 if( ae_fp_less(r,(double)(0))&&ae_fp_neq(gamma,(double)(0)) )
   14163             :                 {
   14164         779 :                     stpc = *stp+r*(*stx-(*stp));
   14165             :                 }
   14166             :                 else
   14167             :                 {
   14168         521 :                     if( ae_fp_greater(*stp,*stx) )
   14169             :                     {
   14170         510 :                         stpc = stmax;
   14171             :                     }
   14172             :                     else
   14173             :                     {
   14174          11 :                         stpc = stmin;
   14175             :                     }
   14176             :                 }
   14177        1300 :                 stpq = *stp+dp/(dp-(*dx))*(*stx-(*stp));
   14178        1300 :                 if( *brackt )
   14179             :                 {
   14180         826 :                     if( ae_fp_less(ae_fabs(*stp-stpc, _state),ae_fabs(*stp-stpq, _state)) )
   14181             :                     {
   14182         754 :                         stpf = stpc;
   14183             :                     }
   14184             :                     else
   14185             :                     {
   14186          72 :                         stpf = stpq;
   14187             :                     }
   14188             :                 }
   14189             :                 else
   14190             :                 {
   14191         474 :                     if( ae_fp_greater(ae_fabs(*stp-stpc, _state),ae_fabs(*stp-stpq, _state)) )
   14192             :                     {
   14193         153 :                         stpf = stpc;
   14194             :                     }
   14195             :                     else
   14196             :                     {
   14197         321 :                         stpf = stpq;
   14198             :                     }
   14199             :                 }
   14200             :             }
   14201             :             else
   14202             :             {
   14203             :                 
   14204             :                 /*
   14205             :                  *     FOURTH CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE
   14206             :                  *     SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DOES
   14207             :                  *     NOT DECREASE. IF THE MINIMUM IS NOT BRACKETED, THE STEP
   14208             :                  *     IS EITHER STPMIN OR STPMAX, ELSE THE CUBIC STEP IS TAKEN.
   14209             :                  */
   14210         413 :                 *info = 4;
   14211         413 :                 bound = ae_false;
   14212         413 :                 if( *brackt )
   14213             :                 {
   14214         396 :                     theta = 3*(fp-(*fy))/(*sty-(*stp))+(*dy)+dp;
   14215         396 :                     s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dy, _state), ae_fabs(dp, _state), _state), _state);
   14216         396 :                     gamma = s*ae_sqrt(ae_sqr(theta/s, _state)-*dy/s*(dp/s), _state);
   14217         396 :                     if( ae_fp_greater(*stp,*sty) )
   14218             :                     {
   14219          39 :                         gamma = -gamma;
   14220             :                     }
   14221         396 :                     p = gamma-dp+theta;
   14222         396 :                     q = gamma-dp+gamma+(*dy);
   14223         396 :                     r = p/q;
   14224         396 :                     stpc = *stp+r*(*sty-(*stp));
   14225         396 :                     stpf = stpc;
   14226             :                 }
   14227             :                 else
   14228             :                 {
   14229          17 :                     if( ae_fp_greater(*stp,*stx) )
   14230             :                     {
   14231          17 :                         stpf = stmax;
   14232             :                     }
   14233             :                     else
   14234             :                     {
   14235           0 :                         stpf = stmin;
   14236             :                     }
   14237             :                 }
   14238             :             }
   14239             :         }
   14240             :     }
   14241             :     
   14242             :     /*
   14243             :      *     UPDATE THE INTERVAL OF UNCERTAINTY. THIS UPDATE DOES NOT
   14244             :      *     DEPEND ON THE NEW STEP OR THE CASE ANALYSIS ABOVE.
   14245             :      */
   14246        3122 :     if( ae_fp_greater(fp,*fx) )
   14247             :     {
   14248        1296 :         *sty = *stp;
   14249        1296 :         *fy = fp;
   14250        1296 :         *dy = dp;
   14251             :     }
   14252             :     else
   14253             :     {
   14254        1826 :         if( ae_fp_less(sgnd,0.0) )
   14255             :         {
   14256         113 :             *sty = *stx;
   14257         113 :             *fy = *fx;
   14258         113 :             *dy = *dx;
   14259             :         }
   14260        1826 :         *stx = *stp;
   14261        1826 :         *fx = fp;
   14262        1826 :         *dx = dp;
   14263             :     }
   14264             :     
   14265             :     /*
   14266             :      *     COMPUTE THE NEW STEP AND SAFEGUARD IT.
   14267             :      */
   14268        3122 :     stpf = ae_minreal(stmax, stpf, _state);
   14269        3122 :     stpf = ae_maxreal(stmin, stpf, _state);
   14270        3122 :     *stp = stpf;
   14271        3122 :     if( *brackt&&bound )
   14272             :     {
   14273        2122 :         if( ae_fp_greater(*sty,*stx) )
   14274             :         {
   14275        2058 :             *stp = ae_minreal(*stx+0.66*(*sty-(*stx)), *stp, _state);
   14276             :         }
   14277             :         else
   14278             :         {
   14279          64 :             *stp = ae_maxreal(*stx+0.66*(*sty-(*stx)), *stp, _state);
   14280             :         }
   14281             :     }
   14282             : }
   14283             : 
   14284             : 
   14285         498 : void _linminstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
   14286             : {
   14287         498 :     linminstate *p = (linminstate*)_p;
   14288         498 :     ae_touch_ptr((void*)p);
   14289         498 : }
   14290             : 
   14291             : 
   14292           0 : void _linminstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
   14293             : {
   14294           0 :     linminstate *dst = (linminstate*)_dst;
   14295           0 :     linminstate *src = (linminstate*)_src;
   14296           0 :     dst->brackt = src->brackt;
   14297           0 :     dst->stage1 = src->stage1;
   14298           0 :     dst->infoc = src->infoc;
   14299           0 :     dst->dg = src->dg;
   14300           0 :     dst->dgm = src->dgm;
   14301           0 :     dst->dginit = src->dginit;
   14302           0 :     dst->dgtest = src->dgtest;
   14303           0 :     dst->dgx = src->dgx;
   14304           0 :     dst->dgxm = src->dgxm;
   14305           0 :     dst->dgy = src->dgy;
   14306           0 :     dst->dgym = src->dgym;
   14307           0 :     dst->finit = src->finit;
   14308           0 :     dst->ftest1 = src->ftest1;
   14309           0 :     dst->fm = src->fm;
   14310           0 :     dst->fx = src->fx;
   14311           0 :     dst->fxm = src->fxm;
   14312           0 :     dst->fy = src->fy;
   14313           0 :     dst->fym = src->fym;
   14314           0 :     dst->stx = src->stx;
   14315           0 :     dst->sty = src->sty;
   14316           0 :     dst->stmin = src->stmin;
   14317           0 :     dst->stmax = src->stmax;
   14318           0 :     dst->width = src->width;
   14319           0 :     dst->width1 = src->width1;
   14320           0 :     dst->xtrapf = src->xtrapf;
   14321           0 : }
   14322             : 
   14323             : 
   14324         498 : void _linminstate_clear(void* _p)
   14325             : {
   14326         498 :     linminstate *p = (linminstate*)_p;
   14327         498 :     ae_touch_ptr((void*)p);
   14328         498 : }
   14329             : 
   14330             : 
   14331         498 : void _linminstate_destroy(void* _p)
   14332             : {
   14333         498 :     linminstate *p = (linminstate*)_p;
   14334         498 :     ae_touch_ptr((void*)p);
   14335         498 : }
   14336             : 
   14337             : 
   14338           0 : void _armijostate_init(void* _p, ae_state *_state, ae_bool make_automatic)
   14339             : {
   14340           0 :     armijostate *p = (armijostate*)_p;
   14341           0 :     ae_touch_ptr((void*)p);
   14342           0 :     ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
   14343           0 :     ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic);
   14344           0 :     ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
   14345           0 :     _rcommstate_init(&p->rstate, _state, make_automatic);
   14346           0 : }
   14347             : 
   14348             : 
   14349           0 : void _armijostate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
   14350             : {
   14351           0 :     armijostate *dst = (armijostate*)_dst;
   14352           0 :     armijostate *src = (armijostate*)_src;
   14353           0 :     dst->needf = src->needf;
   14354           0 :     ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
   14355           0 :     dst->f = src->f;
   14356           0 :     dst->n = src->n;
   14357           0 :     ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic);
   14358           0 :     ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
   14359           0 :     dst->stplen = src->stplen;
   14360           0 :     dst->fcur = src->fcur;
   14361           0 :     dst->stpmax = src->stpmax;
   14362           0 :     dst->fmax = src->fmax;
   14363           0 :     dst->nfev = src->nfev;
   14364           0 :     dst->info = src->info;
   14365           0 :     _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
   14366           0 : }
   14367             : 
   14368             : 
   14369           0 : void _armijostate_clear(void* _p)
   14370             : {
   14371           0 :     armijostate *p = (armijostate*)_p;
   14372           0 :     ae_touch_ptr((void*)p);
   14373           0 :     ae_vector_clear(&p->x);
   14374           0 :     ae_vector_clear(&p->xbase);
   14375           0 :     ae_vector_clear(&p->s);
   14376           0 :     _rcommstate_clear(&p->rstate);
   14377           0 : }
   14378             : 
   14379             : 
   14380           0 : void _armijostate_destroy(void* _p)
   14381             : {
   14382           0 :     armijostate *p = (armijostate*)_p;
   14383           0 :     ae_touch_ptr((void*)p);
   14384           0 :     ae_vector_destroy(&p->x);
   14385           0 :     ae_vector_destroy(&p->xbase);
   14386           0 :     ae_vector_destroy(&p->s);
   14387           0 :     _rcommstate_destroy(&p->rstate);
   14388           0 : }
   14389             : 
   14390             : 
   14391             : #endif
   14392             : #if defined(AE_COMPILE_XBLAS) || !defined(AE_PARTIAL_BUILD)
   14393             : 
   14394             : 
   14395             : /*************************************************************************
   14396             : More precise dot-product. Absolute error of  subroutine  result  is  about
   14397             : 1 ulp of max(MX,V), where:
   14398             :     MX = max( |a[i]*b[i]| )
   14399             :     V  = |(a,b)|
   14400             : 
   14401             : INPUT PARAMETERS
   14402             :     A       -   array[0..N-1], vector 1
   14403             :     B       -   array[0..N-1], vector 2
   14404             :     N       -   vectors length, N<2^29.
   14405             :     Temp    -   array[0..N-1], pre-allocated temporary storage
   14406             : 
   14407             : OUTPUT PARAMETERS
   14408             :     R       -   (A,B)
   14409             :     RErr    -   estimate of error. This estimate accounts for both  errors
   14410             :                 during  calculation  of  (A,B)  and  errors  introduced by
   14411             :                 rounding of A and B to fit in double (about 1 ulp).
   14412             : 
   14413             :   -- ALGLIB --
   14414             :      Copyright 24.08.2009 by Bochkanov Sergey
   14415             : *************************************************************************/
   14416           0 : void xdot(/* Real    */ ae_vector* a,
   14417             :      /* Real    */ ae_vector* b,
   14418             :      ae_int_t n,
   14419             :      /* Real    */ ae_vector* temp,
   14420             :      double* r,
   14421             :      double* rerr,
   14422             :      ae_state *_state)
   14423             : {
   14424             :     ae_int_t i;
   14425             :     double mx;
   14426             :     double v;
   14427             : 
   14428           0 :     *r = 0;
   14429           0 :     *rerr = 0;
   14430             : 
   14431             :     
   14432             :     /*
   14433             :      * special cases:
   14434             :      * * N=0
   14435             :      */
   14436           0 :     if( n==0 )
   14437             :     {
   14438           0 :         *r = (double)(0);
   14439           0 :         *rerr = (double)(0);
   14440           0 :         return;
   14441             :     }
   14442           0 :     mx = (double)(0);
   14443           0 :     for(i=0; i<=n-1; i++)
   14444             :     {
   14445           0 :         v = a->ptr.p_double[i]*b->ptr.p_double[i];
   14446           0 :         temp->ptr.p_double[i] = v;
   14447           0 :         mx = ae_maxreal(mx, ae_fabs(v, _state), _state);
   14448             :     }
   14449           0 :     if( ae_fp_eq(mx,(double)(0)) )
   14450             :     {
   14451           0 :         *r = (double)(0);
   14452           0 :         *rerr = (double)(0);
   14453           0 :         return;
   14454             :     }
   14455           0 :     xblas_xsum(temp, mx, n, r, rerr, _state);
   14456             : }
   14457             : 
   14458             : 
   14459             : /*************************************************************************
   14460             : More precise complex dot-product. Absolute error of  subroutine  result is
   14461             : about 1 ulp of max(MX,V), where:
   14462             :     MX = max( |a[i]*b[i]| )
   14463             :     V  = |(a,b)|
   14464             : 
   14465             : INPUT PARAMETERS
   14466             :     A       -   array[0..N-1], vector 1
   14467             :     B       -   array[0..N-1], vector 2
   14468             :     N       -   vectors length, N<2^29.
   14469             :     Temp    -   array[0..2*N-1], pre-allocated temporary storage
   14470             : 
   14471             : OUTPUT PARAMETERS
   14472             :     R       -   (A,B)
   14473             :     RErr    -   estimate of error. This estimate accounts for both  errors
   14474             :                 during  calculation  of  (A,B)  and  errors  introduced by
   14475             :                 rounding of A and B to fit in double (about 1 ulp).
   14476             : 
   14477             :   -- ALGLIB --
   14478             :      Copyright 27.01.2010 by Bochkanov Sergey
   14479             : *************************************************************************/
   14480           0 : void xcdot(/* Complex */ ae_vector* a,
   14481             :      /* Complex */ ae_vector* b,
   14482             :      ae_int_t n,
   14483             :      /* Real    */ ae_vector* temp,
   14484             :      ae_complex* r,
   14485             :      double* rerr,
   14486             :      ae_state *_state)
   14487             : {
   14488             :     ae_int_t i;
   14489             :     double mx;
   14490             :     double v;
   14491             :     double rerrx;
   14492             :     double rerry;
   14493             : 
   14494           0 :     r->x = 0;
   14495           0 :     r->y = 0;
   14496           0 :     *rerr = 0;
   14497             : 
   14498             :     
   14499             :     /*
   14500             :      * special cases:
   14501             :      * * N=0
   14502             :      */
   14503           0 :     if( n==0 )
   14504             :     {
   14505           0 :         *r = ae_complex_from_i(0);
   14506           0 :         *rerr = (double)(0);
   14507           0 :         return;
   14508             :     }
   14509             :     
   14510             :     /*
   14511             :      * calculate real part
   14512             :      */
   14513           0 :     mx = (double)(0);
   14514           0 :     for(i=0; i<=n-1; i++)
   14515             :     {
   14516           0 :         v = a->ptr.p_complex[i].x*b->ptr.p_complex[i].x;
   14517           0 :         temp->ptr.p_double[2*i+0] = v;
   14518           0 :         mx = ae_maxreal(mx, ae_fabs(v, _state), _state);
   14519           0 :         v = -a->ptr.p_complex[i].y*b->ptr.p_complex[i].y;
   14520           0 :         temp->ptr.p_double[2*i+1] = v;
   14521           0 :         mx = ae_maxreal(mx, ae_fabs(v, _state), _state);
   14522             :     }
   14523           0 :     if( ae_fp_eq(mx,(double)(0)) )
   14524             :     {
   14525           0 :         r->x = (double)(0);
   14526           0 :         rerrx = (double)(0);
   14527             :     }
   14528             :     else
   14529             :     {
   14530           0 :         xblas_xsum(temp, mx, 2*n, &r->x, &rerrx, _state);
   14531             :     }
   14532             :     
   14533             :     /*
   14534             :      * calculate imaginary part
   14535             :      */
   14536           0 :     mx = (double)(0);
   14537           0 :     for(i=0; i<=n-1; i++)
   14538             :     {
   14539           0 :         v = a->ptr.p_complex[i].x*b->ptr.p_complex[i].y;
   14540           0 :         temp->ptr.p_double[2*i+0] = v;
   14541           0 :         mx = ae_maxreal(mx, ae_fabs(v, _state), _state);
   14542           0 :         v = a->ptr.p_complex[i].y*b->ptr.p_complex[i].x;
   14543           0 :         temp->ptr.p_double[2*i+1] = v;
   14544           0 :         mx = ae_maxreal(mx, ae_fabs(v, _state), _state);
   14545             :     }
   14546           0 :     if( ae_fp_eq(mx,(double)(0)) )
   14547             :     {
   14548           0 :         r->y = (double)(0);
   14549           0 :         rerry = (double)(0);
   14550             :     }
   14551             :     else
   14552             :     {
   14553           0 :         xblas_xsum(temp, mx, 2*n, &r->y, &rerry, _state);
   14554             :     }
   14555             :     
   14556             :     /*
   14557             :      * total error
   14558             :      */
   14559           0 :     if( ae_fp_eq(rerrx,(double)(0))&&ae_fp_eq(rerry,(double)(0)) )
   14560             :     {
   14561           0 :         *rerr = (double)(0);
   14562             :     }
   14563             :     else
   14564             :     {
   14565           0 :         *rerr = ae_maxreal(rerrx, rerry, _state)*ae_sqrt(1+ae_sqr(ae_minreal(rerrx, rerry, _state)/ae_maxreal(rerrx, rerry, _state), _state), _state);
   14566             :     }
   14567             : }
   14568             : 
   14569             : 
   14570             : /*************************************************************************
   14571             : Internal subroutine for extra-precise calculation of SUM(w[i]).
   14572             : 
   14573             : INPUT PARAMETERS:
   14574             :     W   -   array[0..N-1], values to be added
   14575             :             W is modified during calculations.
   14576             :     MX  -   max(W[i])
   14577             :     N   -   array size
   14578             :     
   14579             : OUTPUT PARAMETERS:
   14580             :     R   -   SUM(w[i])
   14581             :     RErr-   error estimate for R
   14582             : 
   14583             :   -- ALGLIB --
   14584             :      Copyright 24.08.2009 by Bochkanov Sergey
   14585             : *************************************************************************/
   14586           0 : static void xblas_xsum(/* Real    */ ae_vector* w,
   14587             :      double mx,
   14588             :      ae_int_t n,
   14589             :      double* r,
   14590             :      double* rerr,
   14591             :      ae_state *_state)
   14592             : {
   14593             :     ae_int_t i;
   14594             :     ae_int_t k;
   14595             :     ae_int_t ks;
   14596             :     double v;
   14597             :     double s;
   14598             :     double ln2;
   14599             :     double chunk;
   14600             :     double invchunk;
   14601             :     ae_bool allzeros;
   14602             : 
   14603           0 :     *r = 0;
   14604           0 :     *rerr = 0;
   14605             : 
   14606             :     
   14607             :     /*
   14608             :      * special cases:
   14609             :      * * N=0
   14610             :      * * N is too large to use integer arithmetics
   14611             :      */
   14612           0 :     if( n==0 )
   14613             :     {
   14614           0 :         *r = (double)(0);
   14615           0 :         *rerr = (double)(0);
   14616           0 :         return;
   14617             :     }
   14618           0 :     if( ae_fp_eq(mx,(double)(0)) )
   14619             :     {
   14620           0 :         *r = (double)(0);
   14621           0 :         *rerr = (double)(0);
   14622           0 :         return;
   14623             :     }
   14624           0 :     ae_assert(n<536870912, "XDot: N is too large!", _state);
   14625             :     
   14626             :     /*
   14627             :      * Prepare
   14628             :      */
   14629           0 :     ln2 = ae_log((double)(2), _state);
   14630           0 :     *rerr = mx*ae_machineepsilon;
   14631             :     
   14632             :     /*
   14633             :      * 1. find S such that 0.5<=S*MX<1
   14634             :      * 2. multiply W by S, so task is normalized in some sense
   14635             :      * 3. S:=1/S so we can obtain original vector multiplying by S
   14636             :      */
   14637           0 :     k = ae_round(ae_log(mx, _state)/ln2, _state);
   14638           0 :     s = xblas_xfastpow((double)(2), -k, _state);
   14639           0 :     if( !ae_isfinite(s, _state) )
   14640             :     {
   14641             :         
   14642             :         /*
   14643             :          * Overflow or underflow during evaluation of S; fallback low-precision code
   14644             :          */
   14645           0 :         *r = (double)(0);
   14646           0 :         *rerr = mx*ae_machineepsilon;
   14647           0 :         for(i=0; i<=n-1; i++)
   14648             :         {
   14649           0 :             *r = *r+w->ptr.p_double[i];
   14650             :         }
   14651           0 :         return;
   14652             :     }
   14653           0 :     while(ae_fp_greater_eq(s*mx,(double)(1)))
   14654             :     {
   14655           0 :         s = 0.5*s;
   14656             :     }
   14657           0 :     while(ae_fp_less(s*mx,0.5))
   14658             :     {
   14659           0 :         s = 2*s;
   14660             :     }
   14661           0 :     ae_v_muld(&w->ptr.p_double[0], 1, ae_v_len(0,n-1), s);
   14662           0 :     s = 1/s;
   14663             :     
   14664             :     /*
   14665             :      * find Chunk=2^M such that N*Chunk<2^29
   14666             :      *
   14667             :      * we have chosen upper limit (2^29) with enough space left
   14668             :      * to tolerate possible problems with rounding and N's close
   14669             :      * to the limit, so we don't want to be very strict here.
   14670             :      */
   14671           0 :     k = ae_trunc(ae_log((double)536870912/(double)n, _state)/ln2, _state);
   14672           0 :     chunk = xblas_xfastpow((double)(2), k, _state);
   14673           0 :     if( ae_fp_less(chunk,(double)(2)) )
   14674             :     {
   14675           0 :         chunk = (double)(2);
   14676             :     }
   14677           0 :     invchunk = 1/chunk;
   14678             :     
   14679             :     /*
   14680             :      * calculate result
   14681             :      */
   14682           0 :     *r = (double)(0);
   14683           0 :     ae_v_muld(&w->ptr.p_double[0], 1, ae_v_len(0,n-1), chunk);
   14684             :     for(;;)
   14685             :     {
   14686           0 :         s = s*invchunk;
   14687           0 :         allzeros = ae_true;
   14688           0 :         ks = 0;
   14689           0 :         for(i=0; i<=n-1; i++)
   14690             :         {
   14691           0 :             v = w->ptr.p_double[i];
   14692           0 :             k = ae_trunc(v, _state);
   14693           0 :             if( ae_fp_neq(v,(double)(k)) )
   14694             :             {
   14695           0 :                 allzeros = ae_false;
   14696             :             }
   14697           0 :             w->ptr.p_double[i] = chunk*(v-k);
   14698           0 :             ks = ks+k;
   14699             :         }
   14700           0 :         *r = *r+s*ks;
   14701           0 :         v = ae_fabs(*r, _state);
   14702           0 :         if( allzeros||ae_fp_eq(s*n+mx,mx) )
   14703             :         {
   14704           0 :             break;
   14705             :         }
   14706             :     }
   14707             :     
   14708             :     /*
   14709             :      * correct error
   14710             :      */
   14711           0 :     *rerr = ae_maxreal(*rerr, ae_fabs(*r, _state)*ae_machineepsilon, _state);
   14712             : }
   14713             : 
   14714             : 
   14715             : /*************************************************************************
   14716             : Fast Pow
   14717             : 
   14718             :   -- ALGLIB --
   14719             :      Copyright 24.08.2009 by Bochkanov Sergey
   14720             : *************************************************************************/
   14721           0 : static double xblas_xfastpow(double r, ae_int_t n, ae_state *_state)
   14722             : {
   14723             :     double result;
   14724             : 
   14725             : 
   14726           0 :     result = (double)(0);
   14727           0 :     if( n>0 )
   14728             :     {
   14729           0 :         if( n%2==0 )
   14730             :         {
   14731           0 :             result = ae_sqr(xblas_xfastpow(r, n/2, _state), _state);
   14732             :         }
   14733             :         else
   14734             :         {
   14735           0 :             result = r*xblas_xfastpow(r, n-1, _state);
   14736             :         }
   14737           0 :         return result;
   14738             :     }
   14739           0 :     if( n==0 )
   14740             :     {
   14741           0 :         result = (double)(1);
   14742             :     }
   14743           0 :     if( n<0 )
   14744             :     {
   14745           0 :         result = xblas_xfastpow(1/r, -n, _state);
   14746             :     }
   14747           0 :     return result;
   14748             : }
   14749             : 
   14750             : 
   14751             : #endif
   14752             : #if defined(AE_COMPILE_BASICSTATOPS) || !defined(AE_PARTIAL_BUILD)
   14753             : 
   14754             : 
   14755             : /*************************************************************************
   14756             : Internal tied ranking subroutine.
   14757             : 
   14758             : INPUT PARAMETERS:
   14759             :     X       -   array to rank
   14760             :     N       -   array size
   14761             :     IsCentered- whether ranks are centered or not:
   14762             :                 * True      -   ranks are centered in such way that  their
   14763             :                                 sum is zero
   14764             :                 * False     -   ranks are not centered
   14765             :     Buf     -   temporary buffers
   14766             :     
   14767             : NOTE: when IsCentered is True and all X[] are equal, this  function  fills
   14768             :       X by zeros (exact zeros are used, not sum which is only approximately
   14769             :       equal to zero).
   14770             : *************************************************************************/
   14771           0 : void rankx(/* Real    */ ae_vector* x,
   14772             :      ae_int_t n,
   14773             :      ae_bool iscentered,
   14774             :      apbuffers* buf,
   14775             :      ae_state *_state)
   14776             : {
   14777             :     ae_int_t i;
   14778             :     ae_int_t j;
   14779             :     ae_int_t k;
   14780             :     double tmp;
   14781             :     double voffs;
   14782             : 
   14783             : 
   14784             :     
   14785             :     /*
   14786             :      * Prepare
   14787             :      */
   14788           0 :     if( n<1 )
   14789             :     {
   14790           0 :         return;
   14791             :     }
   14792           0 :     if( n==1 )
   14793             :     {
   14794           0 :         x->ptr.p_double[0] = (double)(0);
   14795           0 :         return;
   14796             :     }
   14797           0 :     if( buf->ra1.cnt<n )
   14798             :     {
   14799           0 :         ae_vector_set_length(&buf->ra1, n, _state);
   14800             :     }
   14801           0 :     if( buf->ia1.cnt<n )
   14802             :     {
   14803           0 :         ae_vector_set_length(&buf->ia1, n, _state);
   14804             :     }
   14805           0 :     for(i=0; i<=n-1; i++)
   14806             :     {
   14807           0 :         buf->ra1.ptr.p_double[i] = x->ptr.p_double[i];
   14808           0 :         buf->ia1.ptr.p_int[i] = i;
   14809             :     }
   14810           0 :     tagsortfasti(&buf->ra1, &buf->ia1, &buf->ra2, &buf->ia2, n, _state);
   14811             :     
   14812             :     /*
   14813             :      * Special test for all values being equal
   14814             :      */
   14815           0 :     if( ae_fp_eq(buf->ra1.ptr.p_double[0],buf->ra1.ptr.p_double[n-1]) )
   14816             :     {
   14817           0 :         if( iscentered )
   14818             :         {
   14819           0 :             tmp = 0.0;
   14820             :         }
   14821             :         else
   14822             :         {
   14823           0 :             tmp = (double)(n-1)/(double)2;
   14824             :         }
   14825           0 :         for(i=0; i<=n-1; i++)
   14826             :         {
   14827           0 :             x->ptr.p_double[i] = tmp;
   14828             :         }
   14829           0 :         return;
   14830             :     }
   14831             :     
   14832             :     /*
   14833             :      * compute tied ranks
   14834             :      */
   14835           0 :     i = 0;
   14836           0 :     while(i<=n-1)
   14837             :     {
   14838           0 :         j = i+1;
   14839           0 :         while(j<=n-1)
   14840             :         {
   14841           0 :             if( ae_fp_neq(buf->ra1.ptr.p_double[j],buf->ra1.ptr.p_double[i]) )
   14842             :             {
   14843           0 :                 break;
   14844             :             }
   14845           0 :             j = j+1;
   14846             :         }
   14847           0 :         for(k=i; k<=j-1; k++)
   14848             :         {
   14849           0 :             buf->ra1.ptr.p_double[k] = (double)(i+j-1)/(double)2;
   14850             :         }
   14851           0 :         i = j;
   14852             :     }
   14853             :     
   14854             :     /*
   14855             :      * back to x
   14856             :      */
   14857           0 :     if( iscentered )
   14858             :     {
   14859           0 :         voffs = (double)(n-1)/(double)2;
   14860             :     }
   14861             :     else
   14862             :     {
   14863           0 :         voffs = 0.0;
   14864             :     }
   14865           0 :     for(i=0; i<=n-1; i++)
   14866             :     {
   14867           0 :         x->ptr.p_double[buf->ia1.ptr.p_int[i]] = buf->ra1.ptr.p_double[i]-voffs;
   14868             :     }
   14869             : }
   14870             : 
   14871             : 
   14872             : /*************************************************************************
   14873             : Internal untied ranking subroutine.
   14874             : 
   14875             : INPUT PARAMETERS:
   14876             :     X       -   array to rank
   14877             :     N       -   array size
   14878             :     Buf     -   temporary buffers
   14879             : 
   14880             : Returns untied ranks (in case of a tie ranks are resolved arbitrarily).
   14881             : *************************************************************************/
   14882           0 : void rankxuntied(/* Real    */ ae_vector* x,
   14883             :      ae_int_t n,
   14884             :      apbuffers* buf,
   14885             :      ae_state *_state)
   14886             : {
   14887             :     ae_int_t i;
   14888             : 
   14889             : 
   14890             :     
   14891             :     /*
   14892             :      * Prepare
   14893             :      */
   14894           0 :     if( n<1 )
   14895             :     {
   14896           0 :         return;
   14897             :     }
   14898           0 :     if( n==1 )
   14899             :     {
   14900           0 :         x->ptr.p_double[0] = (double)(0);
   14901           0 :         return;
   14902             :     }
   14903           0 :     if( buf->ra1.cnt<n )
   14904             :     {
   14905           0 :         ae_vector_set_length(&buf->ra1, n, _state);
   14906             :     }
   14907           0 :     if( buf->ia1.cnt<n )
   14908             :     {
   14909           0 :         ae_vector_set_length(&buf->ia1, n, _state);
   14910             :     }
   14911           0 :     for(i=0; i<=n-1; i++)
   14912             :     {
   14913           0 :         buf->ra1.ptr.p_double[i] = x->ptr.p_double[i];
   14914           0 :         buf->ia1.ptr.p_int[i] = i;
   14915             :     }
   14916           0 :     tagsortfasti(&buf->ra1, &buf->ia1, &buf->ra2, &buf->ia2, n, _state);
   14917           0 :     for(i=0; i<=n-1; i++)
   14918             :     {
   14919           0 :         x->ptr.p_double[buf->ia1.ptr.p_int[i]] = (double)(i);
   14920             :     }
   14921             : }
   14922             : 
   14923             : 
   14924             : #endif
   14925             : #if defined(AE_COMPILE_HPCCORES) || !defined(AE_PARTIAL_BUILD)
   14926             : 
   14927             : 
   14928             : /*************************************************************************
   14929             : Prepares HPC compuations  of  chunked  gradient with HPCChunkedGradient().
   14930             : You  have to call this function  before  calling  HPCChunkedGradient() for
   14931             : a new set of weights. You have to call it only once, see example below:
   14932             : 
   14933             : HOW TO PROCESS DATASET WITH THIS FUNCTION:
   14934             :     Grad:=0
   14935             :     HPCPrepareChunkedGradient(Weights, WCount, NTotal, NOut, Buf)
   14936             :     foreach chunk-of-dataset do
   14937             :         HPCChunkedGradient(...)
   14938             :     HPCFinalizeChunkedGradient(Buf, Grad)
   14939             : 
   14940             : *************************************************************************/
   14941           0 : void hpcpreparechunkedgradient(/* Real    */ ae_vector* weights,
   14942             :      ae_int_t wcount,
   14943             :      ae_int_t ntotal,
   14944             :      ae_int_t nin,
   14945             :      ae_int_t nout,
   14946             :      mlpbuffers* buf,
   14947             :      ae_state *_state)
   14948             : {
   14949             :     ae_int_t i;
   14950             :     ae_int_t batch4size;
   14951             :     ae_int_t chunksize;
   14952             : 
   14953             : 
   14954           0 :     chunksize = 4;
   14955           0 :     batch4size = 3*chunksize*ntotal+chunksize*(2*nout+1);
   14956           0 :     if( buf->xy.rows<chunksize||buf->xy.cols<nin+nout )
   14957             :     {
   14958           0 :         ae_matrix_set_length(&buf->xy, chunksize, nin+nout, _state);
   14959             :     }
   14960           0 :     if( buf->xy2.rows<chunksize||buf->xy2.cols<nin+nout )
   14961             :     {
   14962           0 :         ae_matrix_set_length(&buf->xy2, chunksize, nin+nout, _state);
   14963             :     }
   14964           0 :     if( buf->xyrow.cnt<nin+nout )
   14965             :     {
   14966           0 :         ae_vector_set_length(&buf->xyrow, nin+nout, _state);
   14967             :     }
   14968           0 :     if( buf->x.cnt<nin )
   14969             :     {
   14970           0 :         ae_vector_set_length(&buf->x, nin, _state);
   14971             :     }
   14972           0 :     if( buf->y.cnt<nout )
   14973             :     {
   14974           0 :         ae_vector_set_length(&buf->y, nout, _state);
   14975             :     }
   14976           0 :     if( buf->desiredy.cnt<nout )
   14977             :     {
   14978           0 :         ae_vector_set_length(&buf->desiredy, nout, _state);
   14979             :     }
   14980           0 :     if( buf->batch4buf.cnt<batch4size )
   14981             :     {
   14982           0 :         ae_vector_set_length(&buf->batch4buf, batch4size, _state);
   14983             :     }
   14984           0 :     if( buf->hpcbuf.cnt<wcount )
   14985             :     {
   14986           0 :         ae_vector_set_length(&buf->hpcbuf, wcount, _state);
   14987             :     }
   14988           0 :     if( buf->g.cnt<wcount )
   14989             :     {
   14990           0 :         ae_vector_set_length(&buf->g, wcount, _state);
   14991             :     }
   14992           0 :     if( !hpccores_hpcpreparechunkedgradientx(weights, wcount, &buf->hpcbuf, _state) )
   14993             :     {
   14994           0 :         for(i=0; i<=wcount-1; i++)
   14995             :         {
   14996           0 :             buf->hpcbuf.ptr.p_double[i] = 0.0;
   14997             :         }
   14998             :     }
   14999           0 :     buf->wcount = wcount;
   15000           0 :     buf->ntotal = ntotal;
   15001           0 :     buf->nin = nin;
   15002           0 :     buf->nout = nout;
   15003           0 :     buf->chunksize = chunksize;
   15004           0 : }
   15005             : 
   15006             : 
   15007             : /*************************************************************************
   15008             : Finalizes HPC compuations  of  chunked gradient with HPCChunkedGradient().
   15009             : You  have to call this function  after  calling  HPCChunkedGradient()  for
   15010             : a new set of weights. You have to call it only once, see example below:
   15011             : 
   15012             : HOW TO PROCESS DATASET WITH THIS FUNCTION:
   15013             :     Grad:=0
   15014             :     HPCPrepareChunkedGradient(Weights, WCount, NTotal, NOut, Buf)
   15015             :     foreach chunk-of-dataset do
   15016             :         HPCChunkedGradient(...)
   15017             :     HPCFinalizeChunkedGradient(Buf, Grad)
   15018             : 
   15019             : *************************************************************************/
   15020           0 : void hpcfinalizechunkedgradient(mlpbuffers* buf,
   15021             :      /* Real    */ ae_vector* grad,
   15022             :      ae_state *_state)
   15023             : {
   15024             :     ae_int_t i;
   15025             : 
   15026             : 
   15027           0 :     if( !hpccores_hpcfinalizechunkedgradientx(&buf->hpcbuf, buf->wcount, grad, _state) )
   15028             :     {
   15029           0 :         for(i=0; i<=buf->wcount-1; i++)
   15030             :         {
   15031           0 :             grad->ptr.p_double[i] = grad->ptr.p_double[i]+buf->hpcbuf.ptr.p_double[i];
   15032             :         }
   15033             :     }
   15034           0 : }
   15035             : 
   15036             : 
   15037             : /*************************************************************************
   15038             : Fast kernel for chunked gradient.
   15039             : 
   15040             : *************************************************************************/
   15041           0 : ae_bool hpcchunkedgradient(/* Real    */ ae_vector* weights,
   15042             :      /* Integer */ ae_vector* structinfo,
   15043             :      /* Real    */ ae_vector* columnmeans,
   15044             :      /* Real    */ ae_vector* columnsigmas,
   15045             :      /* Real    */ ae_matrix* xy,
   15046             :      ae_int_t cstart,
   15047             :      ae_int_t csize,
   15048             :      /* Real    */ ae_vector* batch4buf,
   15049             :      /* Real    */ ae_vector* hpcbuf,
   15050             :      double* e,
   15051             :      ae_bool naturalerrorfunc,
   15052             :      ae_state *_state)
   15053             : {
   15054             : #ifndef ALGLIB_INTERCEPTS_SSE2
   15055             :     ae_bool result;
   15056             : 
   15057             : 
   15058           0 :     result = ae_false;
   15059           0 :     return result;
   15060             : #else
   15061             :     return _ialglib_i_hpcchunkedgradient(weights, structinfo, columnmeans, columnsigmas, xy, cstart, csize, batch4buf, hpcbuf, e, naturalerrorfunc);
   15062             : #endif
   15063             : }
   15064             : 
   15065             : 
   15066             : /*************************************************************************
   15067             : Fast kernel for chunked processing.
   15068             : 
   15069             : *************************************************************************/
   15070           0 : ae_bool hpcchunkedprocess(/* Real    */ ae_vector* weights,
   15071             :      /* Integer */ ae_vector* structinfo,
   15072             :      /* Real    */ ae_vector* columnmeans,
   15073             :      /* Real    */ ae_vector* columnsigmas,
   15074             :      /* Real    */ ae_matrix* xy,
   15075             :      ae_int_t cstart,
   15076             :      ae_int_t csize,
   15077             :      /* Real    */ ae_vector* batch4buf,
   15078             :      /* Real    */ ae_vector* hpcbuf,
   15079             :      ae_state *_state)
   15080             : {
   15081             : #ifndef ALGLIB_INTERCEPTS_SSE2
   15082             :     ae_bool result;
   15083             : 
   15084             : 
   15085           0 :     result = ae_false;
   15086           0 :     return result;
   15087             : #else
   15088             :     return _ialglib_i_hpcchunkedprocess(weights, structinfo, columnmeans, columnsigmas, xy, cstart, csize, batch4buf, hpcbuf);
   15089             : #endif
   15090             : }
   15091             : 
   15092             : 
   15093             : /*************************************************************************
   15094             : Stub function.
   15095             : 
   15096             :   -- ALGLIB routine --
   15097             :      14.06.2013
   15098             :      Bochkanov Sergey
   15099             : *************************************************************************/
   15100           0 : static ae_bool hpccores_hpcpreparechunkedgradientx(/* Real    */ ae_vector* weights,
   15101             :      ae_int_t wcount,
   15102             :      /* Real    */ ae_vector* hpcbuf,
   15103             :      ae_state *_state)
   15104             : {
   15105             : #ifndef ALGLIB_INTERCEPTS_SSE2
   15106             :     ae_bool result;
   15107             : 
   15108             : 
   15109           0 :     result = ae_false;
   15110           0 :     return result;
   15111             : #else
   15112             :     return _ialglib_i_hpcpreparechunkedgradientx(weights, wcount, hpcbuf);
   15113             : #endif
   15114             : }
   15115             : 
   15116             : 
   15117             : /*************************************************************************
   15118             : Stub function.
   15119             : 
   15120             :   -- ALGLIB routine --
   15121             :      14.06.2013
   15122             :      Bochkanov Sergey
   15123             : *************************************************************************/
   15124           0 : static ae_bool hpccores_hpcfinalizechunkedgradientx(/* Real    */ ae_vector* buf,
   15125             :      ae_int_t wcount,
   15126             :      /* Real    */ ae_vector* grad,
   15127             :      ae_state *_state)
   15128             : {
   15129             : #ifndef ALGLIB_INTERCEPTS_SSE2
   15130             :     ae_bool result;
   15131             : 
   15132             : 
   15133           0 :     result = ae_false;
   15134           0 :     return result;
   15135             : #else
   15136             :     return _ialglib_i_hpcfinalizechunkedgradientx(buf, wcount, grad);
   15137             : #endif
   15138             : }
   15139             : 
   15140             : 
   15141           0 : void _mlpbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic)
   15142             : {
   15143           0 :     mlpbuffers *p = (mlpbuffers*)_p;
   15144           0 :     ae_touch_ptr((void*)p);
   15145           0 :     ae_vector_init(&p->batch4buf, 0, DT_REAL, _state, make_automatic);
   15146           0 :     ae_vector_init(&p->hpcbuf, 0, DT_REAL, _state, make_automatic);
   15147           0 :     ae_matrix_init(&p->xy, 0, 0, DT_REAL, _state, make_automatic);
   15148           0 :     ae_matrix_init(&p->xy2, 0, 0, DT_REAL, _state, make_automatic);
   15149           0 :     ae_vector_init(&p->xyrow, 0, DT_REAL, _state, make_automatic);
   15150           0 :     ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
   15151           0 :     ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic);
   15152           0 :     ae_vector_init(&p->desiredy, 0, DT_REAL, _state, make_automatic);
   15153           0 :     ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic);
   15154           0 :     ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
   15155           0 : }
   15156             : 
   15157             : 
   15158           0 : void _mlpbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
   15159             : {
   15160           0 :     mlpbuffers *dst = (mlpbuffers*)_dst;
   15161           0 :     mlpbuffers *src = (mlpbuffers*)_src;
   15162           0 :     dst->chunksize = src->chunksize;
   15163           0 :     dst->ntotal = src->ntotal;
   15164           0 :     dst->nin = src->nin;
   15165           0 :     dst->nout = src->nout;
   15166           0 :     dst->wcount = src->wcount;
   15167           0 :     ae_vector_init_copy(&dst->batch4buf, &src->batch4buf, _state, make_automatic);
   15168           0 :     ae_vector_init_copy(&dst->hpcbuf, &src->hpcbuf, _state, make_automatic);
   15169           0 :     ae_matrix_init_copy(&dst->xy, &src->xy, _state, make_automatic);
   15170           0 :     ae_matrix_init_copy(&dst->xy2, &src->xy2, _state, make_automatic);
   15171           0 :     ae_vector_init_copy(&dst->xyrow, &src->xyrow, _state, make_automatic);
   15172           0 :     ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
   15173           0 :     ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic);
   15174           0 :     ae_vector_init_copy(&dst->desiredy, &src->desiredy, _state, make_automatic);
   15175           0 :     dst->e = src->e;
   15176           0 :     ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic);
   15177           0 :     ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
   15178           0 : }
   15179             : 
   15180             : 
   15181           0 : void _mlpbuffers_clear(void* _p)
   15182             : {
   15183           0 :     mlpbuffers *p = (mlpbuffers*)_p;
   15184           0 :     ae_touch_ptr((void*)p);
   15185           0 :     ae_vector_clear(&p->batch4buf);
   15186           0 :     ae_vector_clear(&p->hpcbuf);
   15187           0 :     ae_matrix_clear(&p->xy);
   15188           0 :     ae_matrix_clear(&p->xy2);
   15189           0 :     ae_vector_clear(&p->xyrow);
   15190           0 :     ae_vector_clear(&p->x);
   15191           0 :     ae_vector_clear(&p->y);
   15192           0 :     ae_vector_clear(&p->desiredy);
   15193           0 :     ae_vector_clear(&p->g);
   15194           0 :     ae_vector_clear(&p->tmp0);
   15195           0 : }
   15196             : 
   15197             : 
   15198           0 : void _mlpbuffers_destroy(void* _p)
   15199             : {
   15200           0 :     mlpbuffers *p = (mlpbuffers*)_p;
   15201           0 :     ae_touch_ptr((void*)p);
   15202           0 :     ae_vector_destroy(&p->batch4buf);
   15203           0 :     ae_vector_destroy(&p->hpcbuf);
   15204           0 :     ae_matrix_destroy(&p->xy);
   15205           0 :     ae_matrix_destroy(&p->xy2);
   15206           0 :     ae_vector_destroy(&p->xyrow);
   15207           0 :     ae_vector_destroy(&p->x);
   15208           0 :     ae_vector_destroy(&p->y);
   15209           0 :     ae_vector_destroy(&p->desiredy);
   15210           0 :     ae_vector_destroy(&p->g);
   15211           0 :     ae_vector_destroy(&p->tmp0);
   15212           0 : }
   15213             : 
   15214             : 
   15215             : #endif
   15216             : #if defined(AE_COMPILE_NTHEORY) || !defined(AE_PARTIAL_BUILD)
   15217             : 
   15218             : 
   15219           0 : void findprimitiverootandinverse(ae_int_t n,
   15220             :      ae_int_t* proot,
   15221             :      ae_int_t* invproot,
   15222             :      ae_state *_state)
   15223             : {
   15224             :     ae_int_t candroot;
   15225             :     ae_int_t phin;
   15226             :     ae_int_t q;
   15227             :     ae_int_t f;
   15228             :     ae_bool allnonone;
   15229             :     ae_int_t x;
   15230             :     ae_int_t lastx;
   15231             :     ae_int_t y;
   15232             :     ae_int_t lasty;
   15233             :     ae_int_t a;
   15234             :     ae_int_t b;
   15235             :     ae_int_t t;
   15236             :     ae_int_t n2;
   15237             : 
   15238           0 :     *proot = 0;
   15239           0 :     *invproot = 0;
   15240             : 
   15241           0 :     ae_assert(n>=3, "FindPrimitiveRootAndInverse: N<3", _state);
   15242           0 :     *proot = 0;
   15243           0 :     *invproot = 0;
   15244             :     
   15245             :     /*
   15246             :      * check that N is prime
   15247             :      */
   15248           0 :     ae_assert(ntheory_isprime(n, _state), "FindPrimitiveRoot: N is not prime", _state);
   15249             :     
   15250             :     /*
   15251             :      * Because N is prime, Euler totient function is equal to N-1
   15252             :      */
   15253           0 :     phin = n-1;
   15254             :     
   15255             :     /*
   15256             :      * Test different values of PRoot - from 2 to N-1.
   15257             :      * One of these values MUST be primitive root.
   15258             :      *
   15259             :      * For testing we use algorithm from Wiki (Primitive root modulo n):
   15260             :      * * compute phi(N)
   15261             :      * * determine the different prime factors of phi(N), say p1, ..., pk
   15262             :      * * for every element m of Zn*, compute m^(phi(N)/pi) mod N for i=1..k
   15263             :      *   using a fast algorithm for modular exponentiation.
   15264             :      * * a number m for which these k results are all different from 1 is a
   15265             :      *   primitive root.
   15266             :      */
   15267           0 :     for(candroot=2; candroot<=n-1; candroot++)
   15268             :     {
   15269             :         
   15270             :         /*
   15271             :          * We have current candidate root in CandRoot.
   15272             :          *
   15273             :          * Scan different prime factors of PhiN. Here:
   15274             :          * * F is a current candidate factor
   15275             :          * * Q is a current quotient - amount which was left after dividing PhiN
   15276             :          *   by all previous factors
   15277             :          *
   15278             :          * For each factor, perform test mentioned above.
   15279             :          */
   15280           0 :         q = phin;
   15281           0 :         f = 2;
   15282           0 :         allnonone = ae_true;
   15283           0 :         while(q>1)
   15284             :         {
   15285           0 :             if( q%f==0 )
   15286             :             {
   15287           0 :                 t = ntheory_modexp(candroot, phin/f, n, _state);
   15288           0 :                 if( t==1 )
   15289             :                 {
   15290           0 :                     allnonone = ae_false;
   15291           0 :                     break;
   15292             :                 }
   15293           0 :                 while(q%f==0)
   15294             :                 {
   15295           0 :                     q = q/f;
   15296             :                 }
   15297             :             }
   15298           0 :             f = f+1;
   15299             :         }
   15300           0 :         if( allnonone )
   15301             :         {
   15302           0 :             *proot = candroot;
   15303           0 :             break;
   15304             :         }
   15305             :     }
   15306           0 :     ae_assert(*proot>=2, "FindPrimitiveRoot: internal error (root not found)", _state);
   15307             :     
   15308             :     /*
   15309             :      * Use extended Euclidean algorithm to find multiplicative inverse of primitive root
   15310             :      */
   15311           0 :     x = 0;
   15312           0 :     lastx = 1;
   15313           0 :     y = 1;
   15314           0 :     lasty = 0;
   15315           0 :     a = *proot;
   15316           0 :     b = n;
   15317           0 :     while(b!=0)
   15318             :     {
   15319           0 :         q = a/b;
   15320           0 :         t = a%b;
   15321           0 :         a = b;
   15322           0 :         b = t;
   15323           0 :         t = lastx-q*x;
   15324           0 :         lastx = x;
   15325           0 :         x = t;
   15326           0 :         t = lasty-q*y;
   15327           0 :         lasty = y;
   15328           0 :         y = t;
   15329             :     }
   15330           0 :     while(lastx<0)
   15331             :     {
   15332           0 :         lastx = lastx+n;
   15333             :     }
   15334           0 :     *invproot = lastx;
   15335             :     
   15336             :     /*
   15337             :      * Check that it is safe to perform multiplication modulo N.
   15338             :      * Check results for consistency.
   15339             :      */
   15340           0 :     n2 = (n-1)*(n-1);
   15341           0 :     ae_assert(n2/(n-1)==n-1, "FindPrimitiveRoot: internal error", _state);
   15342           0 :     ae_assert(*proot*(*invproot)/(*proot)==(*invproot), "FindPrimitiveRoot: internal error", _state);
   15343           0 :     ae_assert(*proot*(*invproot)/(*invproot)==(*proot), "FindPrimitiveRoot: internal error", _state);
   15344           0 :     ae_assert(*proot*(*invproot)%n==1, "FindPrimitiveRoot: internal error", _state);
   15345           0 : }
   15346             : 
   15347             : 
   15348           0 : static ae_bool ntheory_isprime(ae_int_t n, ae_state *_state)
   15349             : {
   15350             :     ae_int_t p;
   15351             :     ae_bool result;
   15352             : 
   15353             : 
   15354           0 :     result = ae_false;
   15355           0 :     p = 2;
   15356           0 :     while(p*p<=n)
   15357             :     {
   15358           0 :         if( n%p==0 )
   15359             :         {
   15360           0 :             return result;
   15361             :         }
   15362           0 :         p = p+1;
   15363             :     }
   15364           0 :     result = ae_true;
   15365           0 :     return result;
   15366             : }
   15367             : 
   15368             : 
   15369           0 : static ae_int_t ntheory_modmul(ae_int_t a,
   15370             :      ae_int_t b,
   15371             :      ae_int_t n,
   15372             :      ae_state *_state)
   15373             : {
   15374             :     ae_int_t t;
   15375             :     double ra;
   15376             :     double rb;
   15377             :     ae_int_t result;
   15378             : 
   15379             : 
   15380           0 :     ae_assert(a>=0&&a<n, "ModMul: A<0 or A>=N", _state);
   15381           0 :     ae_assert(b>=0&&b<n, "ModMul: B<0 or B>=N", _state);
   15382             :     
   15383             :     /*
   15384             :      * Base cases
   15385             :      */
   15386           0 :     ra = (double)(a);
   15387           0 :     rb = (double)(b);
   15388           0 :     if( b==0||a==0 )
   15389             :     {
   15390           0 :         result = 0;
   15391           0 :         return result;
   15392             :     }
   15393           0 :     if( b==1||a==1 )
   15394             :     {
   15395           0 :         result = a*b;
   15396           0 :         return result;
   15397             :     }
   15398           0 :     if( ae_fp_eq(ra*rb,(double)(a*b)) )
   15399             :     {
   15400           0 :         result = a*b%n;
   15401           0 :         return result;
   15402             :     }
   15403             :     
   15404             :     /*
   15405             :      * Non-base cases
   15406             :      */
   15407           0 :     if( b%2==0 )
   15408             :     {
   15409             :         
   15410             :         /*
   15411             :          * A*B = (A*(B/2)) * 2
   15412             :          *
   15413             :          * Product T=A*(B/2) is calculated recursively, product T*2 is
   15414             :          * calculated as follows:
   15415             :          * * result:=T-N
   15416             :          * * result:=result+T
   15417             :          * * if result<0 then result:=result+N
   15418             :          *
   15419             :          * In case integer result overflows, we generate exception
   15420             :          */
   15421           0 :         t = ntheory_modmul(a, b/2, n, _state);
   15422           0 :         result = t-n;
   15423           0 :         result = result+t;
   15424           0 :         if( result<0 )
   15425             :         {
   15426           0 :             result = result+n;
   15427             :         }
   15428             :     }
   15429             :     else
   15430             :     {
   15431             :         
   15432             :         /*
   15433             :          * A*B = (A*(B div 2)) * 2 + A
   15434             :          *
   15435             :          * Product T=A*(B/2) is calculated recursively, product T*2 is
   15436             :          * calculated as follows:
   15437             :          * * result:=T-N
   15438             :          * * result:=result+T
   15439             :          * * if result<0 then result:=result+N
   15440             :          *
   15441             :          * In case integer result overflows, we generate exception
   15442             :          */
   15443           0 :         t = ntheory_modmul(a, b/2, n, _state);
   15444           0 :         result = t-n;
   15445           0 :         result = result+t;
   15446           0 :         if( result<0 )
   15447             :         {
   15448           0 :             result = result+n;
   15449             :         }
   15450           0 :         result = result-n;
   15451           0 :         result = result+a;
   15452           0 :         if( result<0 )
   15453             :         {
   15454           0 :             result = result+n;
   15455             :         }
   15456             :     }
   15457           0 :     return result;
   15458             : }
   15459             : 
   15460             : 
   15461           0 : static ae_int_t ntheory_modexp(ae_int_t a,
   15462             :      ae_int_t b,
   15463             :      ae_int_t n,
   15464             :      ae_state *_state)
   15465             : {
   15466             :     ae_int_t t;
   15467             :     ae_int_t result;
   15468             : 
   15469             : 
   15470           0 :     ae_assert(a>=0&&a<n, "ModExp: A<0 or A>=N", _state);
   15471           0 :     ae_assert(b>=0, "ModExp: B<0", _state);
   15472             :     
   15473             :     /*
   15474             :      * Base cases
   15475             :      */
   15476           0 :     if( b==0 )
   15477             :     {
   15478           0 :         result = 1;
   15479           0 :         return result;
   15480             :     }
   15481           0 :     if( b==1 )
   15482             :     {
   15483           0 :         result = a;
   15484           0 :         return result;
   15485             :     }
   15486             :     
   15487             :     /*
   15488             :      * Non-base cases
   15489             :      */
   15490           0 :     if( b%2==0 )
   15491             :     {
   15492           0 :         t = ntheory_modmul(a, a, n, _state);
   15493           0 :         result = ntheory_modexp(t, b/2, n, _state);
   15494             :     }
   15495             :     else
   15496             :     {
   15497           0 :         t = ntheory_modmul(a, a, n, _state);
   15498           0 :         result = ntheory_modexp(t, b/2, n, _state);
   15499           0 :         result = ntheory_modmul(result, a, n, _state);
   15500             :     }
   15501           0 :     return result;
   15502             : }
   15503             : 
   15504             : 
   15505             : #endif
   15506             : #if defined(AE_COMPILE_FTBASE) || !defined(AE_PARTIAL_BUILD)
   15507             : 
   15508             : 
   15509             : /*************************************************************************
   15510             : This subroutine generates FFT plan for K complex FFT's with length N each.
   15511             : 
   15512             : INPUT PARAMETERS:
   15513             :     N           -   FFT length (in complex numbers), N>=1
   15514             :     K           -   number of repetitions, K>=1
   15515             :     
   15516             : OUTPUT PARAMETERS:
   15517             :     Plan        -   plan
   15518             : 
   15519             :   -- ALGLIB --
   15520             :      Copyright 05.04.2013 by Bochkanov Sergey
   15521             : *************************************************************************/
   15522           0 : void ftcomplexfftplan(ae_int_t n,
   15523             :      ae_int_t k,
   15524             :      fasttransformplan* plan,
   15525             :      ae_state *_state)
   15526             : {
   15527             :     ae_frame _frame_block;
   15528             :     srealarray bluesteinbuf;
   15529             :     ae_int_t rowptr;
   15530             :     ae_int_t bluesteinsize;
   15531             :     ae_int_t precrptr;
   15532             :     ae_int_t preciptr;
   15533             :     ae_int_t precrsize;
   15534             :     ae_int_t precisize;
   15535             : 
   15536           0 :     ae_frame_make(_state, &_frame_block);
   15537           0 :     memset(&bluesteinbuf, 0, sizeof(bluesteinbuf));
   15538           0 :     _fasttransformplan_clear(plan);
   15539           0 :     _srealarray_init(&bluesteinbuf, _state, ae_true);
   15540             : 
   15541             :     
   15542             :     /*
   15543             :      * Initial check for parameters
   15544             :      */
   15545           0 :     ae_assert(n>0, "FTComplexFFTPlan: N<=0", _state);
   15546           0 :     ae_assert(k>0, "FTComplexFFTPlan: K<=0", _state);
   15547             :     
   15548             :     /*
   15549             :      * Determine required sizes of precomputed real and integer
   15550             :      * buffers. This stage of code is highly dependent on internals
   15551             :      * of FTComplexFFTPlanRec() and must be kept synchronized with
   15552             :      * possible changes in internals of plan generation function.
   15553             :      *
   15554             :      * Buffer size is determined as follows:
   15555             :      * * N is factorized
   15556             :      * * we factor out anything which is less or equal to MaxRadix
   15557             :      * * prime factor F>RaderThreshold requires 4*FTBaseFindSmooth(2*F-1)
   15558             :      *   real entries to store precomputed Quantities for Bluestein's
   15559             :      *   transformation
   15560             :      * * prime factor F<=RaderThreshold does NOT require
   15561             :      *   precomputed storage
   15562             :      */
   15563           0 :     precrsize = 0;
   15564           0 :     precisize = 0;
   15565           0 :     ftbase_ftdeterminespacerequirements(n, &precrsize, &precisize, _state);
   15566           0 :     if( precrsize>0 )
   15567             :     {
   15568           0 :         ae_vector_set_length(&plan->precr, precrsize, _state);
   15569             :     }
   15570           0 :     if( precisize>0 )
   15571             :     {
   15572           0 :         ae_vector_set_length(&plan->preci, precisize, _state);
   15573             :     }
   15574             :     
   15575             :     /*
   15576             :      * Generate plan
   15577             :      */
   15578           0 :     rowptr = 0;
   15579           0 :     precrptr = 0;
   15580           0 :     preciptr = 0;
   15581           0 :     bluesteinsize = 1;
   15582           0 :     ae_vector_set_length(&plan->buffer, 2*n*k, _state);
   15583           0 :     ftbase_ftcomplexfftplanrec(n, k, ae_true, ae_true, &rowptr, &bluesteinsize, &precrptr, &preciptr, plan, _state);
   15584           0 :     ae_vector_set_length(&bluesteinbuf.val, bluesteinsize, _state);
   15585           0 :     ae_shared_pool_set_seed(&plan->bluesteinpool, &bluesteinbuf, sizeof(bluesteinbuf), _srealarray_init, _srealarray_init_copy, _srealarray_destroy, _state);
   15586             :     
   15587             :     /*
   15588             :      * Check that actual amount of precomputed space used by transformation
   15589             :      * plan is EXACTLY equal to amount of space allocated by us.
   15590             :      */
   15591           0 :     ae_assert(precrptr==precrsize, "FTComplexFFTPlan: internal error (PrecRPtr<>PrecRSize)", _state);
   15592           0 :     ae_assert(preciptr==precisize, "FTComplexFFTPlan: internal error (PrecRPtr<>PrecRSize)", _state);
   15593           0 :     ae_frame_leave(_state);
   15594           0 : }
   15595             : 
   15596             : 
   15597             : /*************************************************************************
   15598             : This subroutine applies transformation plan to input/output array A.
   15599             : 
   15600             : INPUT PARAMETERS:
   15601             :     Plan        -   transformation plan
   15602             :     A           -   array, must be large enough for plan to work
   15603             :     OffsA       -   offset of the subarray to process
   15604             :     RepCnt      -   repetition count (transformation is repeatedly applied
   15605             :                     to subsequent subarrays)
   15606             :     
   15607             : OUTPUT PARAMETERS:
   15608             :     Plan        -   plan (temporary buffers can be modified, plan itself
   15609             :                     is unchanged and can be reused)
   15610             :     A           -   transformed array
   15611             : 
   15612             :   -- ALGLIB --
   15613             :      Copyright 05.04.2013 by Bochkanov Sergey
   15614             : *************************************************************************/
   15615           0 : void ftapplyplan(fasttransformplan* plan,
   15616             :      /* Real    */ ae_vector* a,
   15617             :      ae_int_t offsa,
   15618             :      ae_int_t repcnt,
   15619             :      ae_state *_state)
   15620             : {
   15621             :     ae_int_t plansize;
   15622             :     ae_int_t i;
   15623             : 
   15624             : 
   15625           0 :     plansize = plan->entries.ptr.pp_int[0][ftbase_coloperandscnt]*plan->entries.ptr.pp_int[0][ftbase_coloperandsize]*plan->entries.ptr.pp_int[0][ftbase_colmicrovectorsize];
   15626           0 :     for(i=0; i<=repcnt-1; i++)
   15627             :     {
   15628           0 :         ftbase_ftapplysubplan(plan, 0, a, offsa+plansize*i, 0, &plan->buffer, 1, _state);
   15629             :     }
   15630           0 : }
   15631             : 
   15632             : 
   15633             : /*************************************************************************
   15634             : Returns good factorization N=N1*N2.
   15635             : 
   15636             : Usually N1<=N2 (but not always - small N's may be exception).
   15637             : if N1<>1 then N2<>1.
   15638             : 
   15639             : Factorization is chosen depending on task type and codelets we have.
   15640             : 
   15641             :   -- ALGLIB --
   15642             :      Copyright 01.05.2009 by Bochkanov Sergey
   15643             : *************************************************************************/
   15644           0 : void ftbasefactorize(ae_int_t n,
   15645             :      ae_int_t tasktype,
   15646             :      ae_int_t* n1,
   15647             :      ae_int_t* n2,
   15648             :      ae_state *_state)
   15649             : {
   15650             :     ae_int_t j;
   15651             : 
   15652           0 :     *n1 = 0;
   15653           0 :     *n2 = 0;
   15654             : 
   15655           0 :     *n1 = 0;
   15656           0 :     *n2 = 0;
   15657             :     
   15658             :     /*
   15659             :      * try to find good codelet
   15660             :      */
   15661           0 :     if( *n1*(*n2)!=n )
   15662             :     {
   15663           0 :         for(j=ftbase_ftbasecodeletrecommended; j>=2; j--)
   15664             :         {
   15665           0 :             if( n%j==0 )
   15666             :             {
   15667           0 :                 *n1 = j;
   15668           0 :                 *n2 = n/j;
   15669           0 :                 break;
   15670             :             }
   15671             :         }
   15672             :     }
   15673             :     
   15674             :     /*
   15675             :      * try to factorize N
   15676             :      */
   15677           0 :     if( *n1*(*n2)!=n )
   15678             :     {
   15679           0 :         for(j=ftbase_ftbasecodeletrecommended+1; j<=n-1; j++)
   15680             :         {
   15681           0 :             if( n%j==0 )
   15682             :             {
   15683           0 :                 *n1 = j;
   15684           0 :                 *n2 = n/j;
   15685           0 :                 break;
   15686             :             }
   15687             :         }
   15688             :     }
   15689             :     
   15690             :     /*
   15691             :      * looks like N is prime :(
   15692             :      */
   15693           0 :     if( *n1*(*n2)!=n )
   15694             :     {
   15695           0 :         *n1 = 1;
   15696           0 :         *n2 = n;
   15697             :     }
   15698             :     
   15699             :     /*
   15700             :      * normalize
   15701             :      */
   15702           0 :     if( *n2==1&&*n1!=1 )
   15703             :     {
   15704           0 :         *n2 = *n1;
   15705           0 :         *n1 = 1;
   15706             :     }
   15707           0 : }
   15708             : 
   15709             : 
   15710             : /*************************************************************************
   15711             : Is number smooth?
   15712             : 
   15713             :   -- ALGLIB --
   15714             :      Copyright 01.05.2009 by Bochkanov Sergey
   15715             : *************************************************************************/
   15716           0 : ae_bool ftbaseissmooth(ae_int_t n, ae_state *_state)
   15717             : {
   15718             :     ae_int_t i;
   15719             :     ae_bool result;
   15720             : 
   15721             : 
   15722           0 :     for(i=2; i<=ftbase_ftbasemaxsmoothfactor; i++)
   15723             :     {
   15724           0 :         while(n%i==0)
   15725             :         {
   15726           0 :             n = n/i;
   15727             :         }
   15728             :     }
   15729           0 :     result = n==1;
   15730           0 :     return result;
   15731             : }
   15732             : 
   15733             : 
   15734             : /*************************************************************************
   15735             : Returns smallest smooth (divisible only by 2, 3, 5) number that is greater
   15736             : than or equal to max(N,2)
   15737             : 
   15738             :   -- ALGLIB --
   15739             :      Copyright 01.05.2009 by Bochkanov Sergey
   15740             : *************************************************************************/
   15741           0 : ae_int_t ftbasefindsmooth(ae_int_t n, ae_state *_state)
   15742             : {
   15743             :     ae_int_t best;
   15744             :     ae_int_t result;
   15745             : 
   15746             : 
   15747           0 :     best = 2;
   15748           0 :     while(best<n)
   15749             :     {
   15750           0 :         best = 2*best;
   15751             :     }
   15752           0 :     ftbase_ftbasefindsmoothrec(n, 1, 2, &best, _state);
   15753           0 :     result = best;
   15754           0 :     return result;
   15755             : }
   15756             : 
   15757             : 
   15758             : /*************************************************************************
   15759             : Returns  smallest  smooth  (divisible only by 2, 3, 5) even number that is
   15760             : greater than or equal to max(N,2)
   15761             : 
   15762             :   -- ALGLIB --
   15763             :      Copyright 01.05.2009 by Bochkanov Sergey
   15764             : *************************************************************************/
   15765           0 : ae_int_t ftbasefindsmootheven(ae_int_t n, ae_state *_state)
   15766             : {
   15767             :     ae_int_t best;
   15768             :     ae_int_t result;
   15769             : 
   15770             : 
   15771           0 :     best = 2;
   15772           0 :     while(best<n)
   15773             :     {
   15774           0 :         best = 2*best;
   15775             :     }
   15776           0 :     ftbase_ftbasefindsmoothrec(n, 2, 2, &best, _state);
   15777           0 :     result = best;
   15778           0 :     return result;
   15779             : }
   15780             : 
   15781             : 
   15782             : /*************************************************************************
   15783             : Returns estimate of FLOP count for the FFT.
   15784             : 
   15785             : It is only an estimate based on operations count for the PERFECT FFT
   15786             : and relative inefficiency of the algorithm actually used.
   15787             : 
   15788             : N should be power of 2, estimates are badly wrong for non-power-of-2 N's.
   15789             : 
   15790             :   -- ALGLIB --
   15791             :      Copyright 01.05.2009 by Bochkanov Sergey
   15792             : *************************************************************************/
   15793           0 : double ftbasegetflopestimate(ae_int_t n, ae_state *_state)
   15794             : {
   15795             :     double result;
   15796             : 
   15797             : 
   15798           0 :     result = ftbase_ftbaseinefficiencyfactor*(4*n*ae_log((double)(n), _state)/ae_log((double)(2), _state)-6*n+8);
   15799           0 :     return result;
   15800             : }
   15801             : 
   15802             : 
   15803             : /*************************************************************************
   15804             : This function returns EXACT estimate of the space requirements for N-point
   15805             : FFT. Internals of this function are highly dependent on details of different
   15806             : FFTs employed by this unit, so every time algorithm is changed this function
   15807             : has to be rewritten.
   15808             : 
   15809             : INPUT PARAMETERS:
   15810             :     N           -   transform length
   15811             :     PrecRSize   -   must be set to zero
   15812             :     PrecISize   -   must be set to zero
   15813             :     
   15814             : OUTPUT PARAMETERS:
   15815             :     PrecRSize   -   number of real temporaries required for transformation
   15816             :     PrecISize   -   number of integer temporaries required for transformation
   15817             : 
   15818             :     
   15819             :   -- ALGLIB --
   15820             :      Copyright 05.04.2013 by Bochkanov Sergey
   15821             : *************************************************************************/
   15822           0 : static void ftbase_ftdeterminespacerequirements(ae_int_t n,
   15823             :      ae_int_t* precrsize,
   15824             :      ae_int_t* precisize,
   15825             :      ae_state *_state)
   15826             : {
   15827             :     ae_int_t ncur;
   15828             :     ae_int_t f;
   15829             :     ae_int_t i;
   15830             : 
   15831             : 
   15832             :     
   15833             :     /*
   15834             :      * Determine required sizes of precomputed real and integer
   15835             :      * buffers. This stage of code is highly dependent on internals
   15836             :      * of FTComplexFFTPlanRec() and must be kept synchronized with
   15837             :      * possible changes in internals of plan generation function.
   15838             :      *
   15839             :      * Buffer size is determined as follows:
   15840             :      * * N is factorized
   15841             :      * * we factor out anything which is less or equal to MaxRadix
   15842             :      * * prime factor F>RaderThreshold requires 4*FTBaseFindSmooth(2*F-1)
   15843             :      *   real entries to store precomputed Quantities for Bluestein's
   15844             :      *   transformation
   15845             :      * * prime factor F<=RaderThreshold requires 2*(F-1)+ESTIMATE(F-1)
   15846             :      *   precomputed storage
   15847             :      */
   15848           0 :     ncur = n;
   15849           0 :     for(i=2; i<=ftbase_maxradix; i++)
   15850             :     {
   15851           0 :         while(ncur%i==0)
   15852             :         {
   15853           0 :             ncur = ncur/i;
   15854             :         }
   15855             :     }
   15856           0 :     f = 2;
   15857           0 :     while(f<=ncur)
   15858             :     {
   15859           0 :         while(ncur%f==0)
   15860             :         {
   15861           0 :             if( f>ftbase_raderthreshold )
   15862             :             {
   15863           0 :                 *precrsize = *precrsize+4*ftbasefindsmooth(2*f-1, _state);
   15864             :             }
   15865             :             else
   15866             :             {
   15867           0 :                 *precrsize = *precrsize+2*(f-1);
   15868           0 :                 ftbase_ftdeterminespacerequirements(f-1, precrsize, precisize, _state);
   15869             :             }
   15870           0 :             ncur = ncur/f;
   15871             :         }
   15872           0 :         f = f+1;
   15873             :     }
   15874           0 : }
   15875             : 
   15876             : 
   15877             : /*************************************************************************
   15878             : Recurrent function called by FTComplexFFTPlan() and other functions. It
   15879             : recursively builds transformation plan
   15880             : 
   15881             : INPUT PARAMETERS:
   15882             :     N           -   FFT length (in complex numbers), N>=1
   15883             :     K           -   number of repetitions, K>=1
   15884             :     ChildPlan   -   if True, plan generator inserts OpStart/opEnd in the
   15885             :                     plan header/footer.
   15886             :     TopmostPlan -   if True, plan generator assumes that it is topmost plan:
   15887             :                     * it may use global buffer for transpositions
   15888             :                     and there is no other plan which executes in parallel
   15889             :     RowPtr      -   index which points to past-the-last entry generated so far
   15890             :     BluesteinSize-  amount of storage (in real numbers) required for Bluestein buffer
   15891             :     PrecRPtr    -   pointer to unused part of precomputed real buffer (Plan.PrecR):
   15892             :                     * when this function stores some data to precomputed buffer,
   15893             :                       it advances pointer.
   15894             :                     * it is responsibility of the function to assert that
   15895             :                       Plan.PrecR has enough space to store data before actually
   15896             :                       writing to buffer.
   15897             :                     * it is responsibility of the caller to allocate enough
   15898             :                       space before calling this function
   15899             :     PrecIPtr    -   pointer to unused part of precomputed integer buffer (Plan.PrecI):
   15900             :                     * when this function stores some data to precomputed buffer,
   15901             :                       it advances pointer.
   15902             :                     * it is responsibility of the function to assert that
   15903             :                       Plan.PrecR has enough space to store data before actually
   15904             :                       writing to buffer.
   15905             :                     * it is responsibility of the caller to allocate enough
   15906             :                       space before calling this function
   15907             :     Plan        -   plan (generated so far)
   15908             :     
   15909             : OUTPUT PARAMETERS:
   15910             :     RowPtr      -   updated pointer (advanced by number of entries generated
   15911             :                     by function)
   15912             :     BluesteinSize-  updated amount
   15913             :                     (may be increased, but may never be decreased)
   15914             :         
   15915             : NOTE: in case TopmostPlan is True, ChildPlan is also must be True.
   15916             :     
   15917             :   -- ALGLIB --
   15918             :      Copyright 05.04.2013 by Bochkanov Sergey
   15919             : *************************************************************************/
   15920           0 : static void ftbase_ftcomplexfftplanrec(ae_int_t n,
   15921             :      ae_int_t k,
   15922             :      ae_bool childplan,
   15923             :      ae_bool topmostplan,
   15924             :      ae_int_t* rowptr,
   15925             :      ae_int_t* bluesteinsize,
   15926             :      ae_int_t* precrptr,
   15927             :      ae_int_t* preciptr,
   15928             :      fasttransformplan* plan,
   15929             :      ae_state *_state)
   15930             : {
   15931             :     ae_frame _frame_block;
   15932             :     srealarray localbuf;
   15933             :     ae_int_t m;
   15934             :     ae_int_t n1;
   15935             :     ae_int_t n2;
   15936             :     ae_int_t gq;
   15937             :     ae_int_t giq;
   15938             :     ae_int_t row0;
   15939             :     ae_int_t row1;
   15940             :     ae_int_t row2;
   15941             :     ae_int_t row3;
   15942             : 
   15943           0 :     ae_frame_make(_state, &_frame_block);
   15944           0 :     memset(&localbuf, 0, sizeof(localbuf));
   15945           0 :     _srealarray_init(&localbuf, _state, ae_true);
   15946             : 
   15947           0 :     ae_assert(n>0, "FTComplexFFTPlan: N<=0", _state);
   15948           0 :     ae_assert(k>0, "FTComplexFFTPlan: K<=0", _state);
   15949           0 :     ae_assert(!topmostplan||childplan, "FTComplexFFTPlan: ChildPlan is inconsistent with TopmostPlan", _state);
   15950             :     
   15951             :     /*
   15952             :      * Try to generate "topmost" plan
   15953             :      */
   15954           0 :     if( topmostplan&&n>ftbase_recursivethreshold )
   15955             :     {
   15956           0 :         ftbase_ftfactorize(n, ae_false, &n1, &n2, _state);
   15957           0 :         if( n1*n2==0 )
   15958             :         {
   15959             :             
   15960             :             /*
   15961             :              * Handle prime-factor FFT with Bluestein's FFT.
   15962             :              * Determine size of Bluestein's buffer.
   15963             :              */
   15964           0 :             m = ftbasefindsmooth(2*n-1, _state);
   15965           0 :             *bluesteinsize = ae_maxint(2*m, *bluesteinsize, _state);
   15966             :             
   15967             :             /*
   15968             :              * Generate plan
   15969             :              */
   15970           0 :             ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state);
   15971           0 :             ftbase_ftpushentry4(plan, rowptr, ftbase_opbluesteinsfft, k, n, 2, m, 2, *precrptr, 0, _state);
   15972           0 :             row0 = *rowptr;
   15973           0 :             ftbase_ftpushentry(plan, rowptr, ftbase_opjmp, 0, 0, 0, 0, _state);
   15974           0 :             ftbase_ftcomplexfftplanrec(m, 1, ae_true, ae_true, rowptr, bluesteinsize, precrptr, preciptr, plan, _state);
   15975           0 :             row1 = *rowptr;
   15976           0 :             plan->entries.ptr.pp_int[row0][ftbase_colparam0] = row1-row0;
   15977           0 :             ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state);
   15978             :             
   15979             :             /*
   15980             :              * Fill precomputed buffer
   15981             :              */
   15982           0 :             ftbase_ftprecomputebluesteinsfft(n, m, &plan->precr, *precrptr, _state);
   15983             :             
   15984             :             /*
   15985             :              * Update pointer to the precomputed area
   15986             :              */
   15987           0 :             *precrptr = *precrptr+4*m;
   15988             :         }
   15989             :         else
   15990             :         {
   15991             :             
   15992             :             /*
   15993             :              * Handle composite FFT with recursive Cooley-Tukey which
   15994             :              * uses global buffer instead of local one.
   15995             :              */
   15996           0 :             ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state);
   15997           0 :             ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state);
   15998           0 :             row0 = *rowptr;
   15999           0 :             ftbase_ftpushentry2(plan, rowptr, ftbase_opparallelcall, k*n2, n1, 2, 0, ftbase_ftoptimisticestimate(n, _state), _state);
   16000           0 :             ftbase_ftpushentry(plan, rowptr, ftbase_opcomplexfftfactors, k, n, 2, n1, _state);
   16001           0 :             ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n2, _state);
   16002           0 :             row2 = *rowptr;
   16003           0 :             ftbase_ftpushentry2(plan, rowptr, ftbase_opparallelcall, k*n1, n2, 2, 0, ftbase_ftoptimisticestimate(n, _state), _state);
   16004           0 :             ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state);
   16005           0 :             ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state);
   16006           0 :             row1 = *rowptr;
   16007           0 :             ftbase_ftcomplexfftplanrec(n1, 1, ae_true, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state);
   16008           0 :             plan->entries.ptr.pp_int[row0][ftbase_colparam0] = row1-row0;
   16009           0 :             row3 = *rowptr;
   16010           0 :             ftbase_ftcomplexfftplanrec(n2, 1, ae_true, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state);
   16011           0 :             plan->entries.ptr.pp_int[row2][ftbase_colparam0] = row3-row2;
   16012             :         }
   16013           0 :         ae_frame_leave(_state);
   16014           0 :         return;
   16015             :     }
   16016             :     
   16017             :     /*
   16018             :      * Prepare "non-topmost" plan:
   16019             :      * * calculate factorization
   16020             :      * * use local (shared) buffer
   16021             :      * * update buffer size - ANY plan will need at least
   16022             :      *   2*N temporaries, additional requirements can be
   16023             :      *   applied later
   16024             :      */
   16025           0 :     ftbase_ftfactorize(n, ae_false, &n1, &n2, _state);
   16026             :     
   16027             :     /*
   16028             :      * Handle FFT's with N1*N2=0: either small-N or prime-factor
   16029             :      */
   16030           0 :     if( n1*n2==0 )
   16031             :     {
   16032           0 :         if( n<=ftbase_maxradix )
   16033             :         {
   16034             :             
   16035             :             /*
   16036             :              * Small-N FFT
   16037             :              */
   16038           0 :             if( childplan )
   16039             :             {
   16040           0 :                 ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state);
   16041             :             }
   16042           0 :             ftbase_ftpushentry(plan, rowptr, ftbase_opcomplexcodeletfft, k, n, 2, 0, _state);
   16043           0 :             if( childplan )
   16044             :             {
   16045           0 :                 ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state);
   16046             :             }
   16047           0 :             ae_frame_leave(_state);
   16048           0 :             return;
   16049             :         }
   16050           0 :         if( n<=ftbase_raderthreshold )
   16051             :         {
   16052             :             
   16053             :             /*
   16054             :              * Handle prime-factor FFT's with Rader's FFT
   16055             :              */
   16056           0 :             m = n-1;
   16057           0 :             if( childplan )
   16058             :             {
   16059           0 :                 ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state);
   16060             :             }
   16061           0 :             findprimitiverootandinverse(n, &gq, &giq, _state);
   16062           0 :             ftbase_ftpushentry4(plan, rowptr, ftbase_opradersfft, k, n, 2, 2, gq, giq, *precrptr, _state);
   16063           0 :             ftbase_ftprecomputeradersfft(n, gq, giq, &plan->precr, *precrptr, _state);
   16064           0 :             *precrptr = *precrptr+2*(n-1);
   16065           0 :             row0 = *rowptr;
   16066           0 :             ftbase_ftpushentry(plan, rowptr, ftbase_opjmp, 0, 0, 0, 0, _state);
   16067           0 :             ftbase_ftcomplexfftplanrec(m, 1, ae_true, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state);
   16068           0 :             row1 = *rowptr;
   16069           0 :             plan->entries.ptr.pp_int[row0][ftbase_colparam0] = row1-row0;
   16070           0 :             if( childplan )
   16071             :             {
   16072           0 :                 ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state);
   16073             :             }
   16074             :         }
   16075             :         else
   16076             :         {
   16077             :             
   16078             :             /*
   16079             :              * Handle prime-factor FFT's with Bluestein's FFT
   16080             :              */
   16081           0 :             m = ftbasefindsmooth(2*n-1, _state);
   16082           0 :             *bluesteinsize = ae_maxint(2*m, *bluesteinsize, _state);
   16083           0 :             if( childplan )
   16084             :             {
   16085           0 :                 ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state);
   16086             :             }
   16087           0 :             ftbase_ftpushentry4(plan, rowptr, ftbase_opbluesteinsfft, k, n, 2, m, 2, *precrptr, 0, _state);
   16088           0 :             ftbase_ftprecomputebluesteinsfft(n, m, &plan->precr, *precrptr, _state);
   16089           0 :             *precrptr = *precrptr+4*m;
   16090           0 :             row0 = *rowptr;
   16091           0 :             ftbase_ftpushentry(plan, rowptr, ftbase_opjmp, 0, 0, 0, 0, _state);
   16092           0 :             ftbase_ftcomplexfftplanrec(m, 1, ae_true, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state);
   16093           0 :             row1 = *rowptr;
   16094           0 :             plan->entries.ptr.pp_int[row0][ftbase_colparam0] = row1-row0;
   16095           0 :             if( childplan )
   16096             :             {
   16097           0 :                 ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state);
   16098             :             }
   16099             :         }
   16100           0 :         ae_frame_leave(_state);
   16101           0 :         return;
   16102             :     }
   16103             :     
   16104             :     /*
   16105             :      * Handle Cooley-Tukey FFT with small N1
   16106             :      */
   16107           0 :     if( n1<=ftbase_maxradix )
   16108             :     {
   16109             :         
   16110             :         /*
   16111             :          * Specialized transformation for small N1:
   16112             :          * * N2 short inplace FFT's, each N1-point, with integrated twiddle factors
   16113             :          * * N1 long FFT's
   16114             :          * * final transposition
   16115             :          */
   16116           0 :         if( childplan )
   16117             :         {
   16118           0 :             ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state);
   16119             :         }
   16120           0 :         ftbase_ftpushentry(plan, rowptr, ftbase_opcomplexcodelettwfft, k, n1, 2*n2, 0, _state);
   16121           0 :         ftbase_ftcomplexfftplanrec(n2, k*n1, ae_false, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state);
   16122           0 :         ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state);
   16123           0 :         if( childplan )
   16124             :         {
   16125           0 :             ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state);
   16126             :         }
   16127           0 :         ae_frame_leave(_state);
   16128           0 :         return;
   16129             :     }
   16130             :     
   16131             :     /*
   16132             :      * Handle general Cooley-Tukey FFT, either "flat" or "recursive"
   16133             :      */
   16134           0 :     if( n<=ftbase_recursivethreshold )
   16135             :     {
   16136             :         
   16137             :         /*
   16138             :          * General code for large N1/N2, "flat" version without explicit recurrence
   16139             :          * (nested subplans are inserted directly into the body of the plan)
   16140             :          */
   16141           0 :         if( childplan )
   16142             :         {
   16143           0 :             ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state);
   16144             :         }
   16145           0 :         ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state);
   16146           0 :         ftbase_ftcomplexfftplanrec(n1, k*n2, ae_false, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state);
   16147           0 :         ftbase_ftpushentry(plan, rowptr, ftbase_opcomplexfftfactors, k, n, 2, n1, _state);
   16148           0 :         ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n2, _state);
   16149           0 :         ftbase_ftcomplexfftplanrec(n2, k*n1, ae_false, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state);
   16150           0 :         ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state);
   16151           0 :         if( childplan )
   16152             :         {
   16153           0 :             ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state);
   16154             :         }
   16155             :     }
   16156             :     else
   16157             :     {
   16158             :         
   16159             :         /*
   16160             :          * General code for large N1/N2, "recursive" version - nested subplans
   16161             :          * are separated from the plan body.
   16162             :          *
   16163             :          * Generate parent plan.
   16164             :          */
   16165           0 :         if( childplan )
   16166             :         {
   16167           0 :             ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state);
   16168             :         }
   16169           0 :         ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state);
   16170           0 :         row0 = *rowptr;
   16171           0 :         ftbase_ftpushentry2(plan, rowptr, ftbase_opparallelcall, k*n2, n1, 2, 0, ftbase_ftoptimisticestimate(n, _state), _state);
   16172           0 :         ftbase_ftpushentry(plan, rowptr, ftbase_opcomplexfftfactors, k, n, 2, n1, _state);
   16173           0 :         ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n2, _state);
   16174           0 :         row2 = *rowptr;
   16175           0 :         ftbase_ftpushentry2(plan, rowptr, ftbase_opparallelcall, k*n1, n2, 2, 0, ftbase_ftoptimisticestimate(n, _state), _state);
   16176           0 :         ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state);
   16177           0 :         if( childplan )
   16178             :         {
   16179           0 :             ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state);
   16180             :         }
   16181             :         
   16182             :         /*
   16183             :          * Generate child subplans, insert refence to parent plans
   16184             :          */
   16185           0 :         row1 = *rowptr;
   16186           0 :         ftbase_ftcomplexfftplanrec(n1, 1, ae_true, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state);
   16187           0 :         plan->entries.ptr.pp_int[row0][ftbase_colparam0] = row1-row0;
   16188           0 :         row3 = *rowptr;
   16189           0 :         ftbase_ftcomplexfftplanrec(n2, 1, ae_true, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state);
   16190           0 :         plan->entries.ptr.pp_int[row2][ftbase_colparam0] = row3-row2;
   16191             :     }
   16192           0 :     ae_frame_leave(_state);
   16193             : }
   16194             : 
   16195             : 
   16196             : /*************************************************************************
   16197             : This function pushes one more entry to the plan. It resizes Entries matrix
   16198             : if needed.
   16199             : 
   16200             : INPUT PARAMETERS:
   16201             :     Plan        -   plan (generated so far)
   16202             :     RowPtr      -   index which points to past-the-last entry generated so far
   16203             :     EType       -   entry type
   16204             :     EOpCnt      -   operands count
   16205             :     EOpSize     -   operand size
   16206             :     EMcvSize    -   microvector size
   16207             :     EParam0     -   parameter 0
   16208             :     
   16209             : OUTPUT PARAMETERS:
   16210             :     Plan        -   updated plan    
   16211             :     RowPtr      -   updated pointer
   16212             : 
   16213             : NOTE: Param1 is set to -1.
   16214             :     
   16215             :   -- ALGLIB --
   16216             :      Copyright 05.04.2013 by Bochkanov Sergey
   16217             : *************************************************************************/
   16218           0 : static void ftbase_ftpushentry(fasttransformplan* plan,
   16219             :      ae_int_t* rowptr,
   16220             :      ae_int_t etype,
   16221             :      ae_int_t eopcnt,
   16222             :      ae_int_t eopsize,
   16223             :      ae_int_t emcvsize,
   16224             :      ae_int_t eparam0,
   16225             :      ae_state *_state)
   16226             : {
   16227             : 
   16228             : 
   16229           0 :     ftbase_ftpushentry2(plan, rowptr, etype, eopcnt, eopsize, emcvsize, eparam0, -1, _state);
   16230           0 : }
   16231             : 
   16232             : 
   16233             : /*************************************************************************
   16234             : Same as FTPushEntry(), but sets Param0 AND Param1.
   16235             : This function pushes one more entry to the plan. It resized Entries matrix
   16236             : if needed.
   16237             : 
   16238             : INPUT PARAMETERS:
   16239             :     Plan        -   plan (generated so far)
   16240             :     RowPtr      -   index which points to past-the-last entry generated so far
   16241             :     EType       -   entry type
   16242             :     EOpCnt      -   operands count
   16243             :     EOpSize     -   operand size
   16244             :     EMcvSize    -   microvector size
   16245             :     EParam0     -   parameter 0
   16246             :     EParam1     -   parameter 1
   16247             :     
   16248             : OUTPUT PARAMETERS:
   16249             :     Plan        -   updated plan    
   16250             :     RowPtr      -   updated pointer
   16251             : 
   16252             :   -- ALGLIB --
   16253             :      Copyright 05.04.2013 by Bochkanov Sergey
   16254             : *************************************************************************/
   16255           0 : static void ftbase_ftpushentry2(fasttransformplan* plan,
   16256             :      ae_int_t* rowptr,
   16257             :      ae_int_t etype,
   16258             :      ae_int_t eopcnt,
   16259             :      ae_int_t eopsize,
   16260             :      ae_int_t emcvsize,
   16261             :      ae_int_t eparam0,
   16262             :      ae_int_t eparam1,
   16263             :      ae_state *_state)
   16264             : {
   16265             : 
   16266             : 
   16267           0 :     if( *rowptr>=plan->entries.rows )
   16268             :     {
   16269           0 :         imatrixresize(&plan->entries, ae_maxint(2*plan->entries.rows, 1, _state), ftbase_colscnt, _state);
   16270             :     }
   16271           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_coltype] = etype;
   16272           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_coloperandscnt] = eopcnt;
   16273           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_coloperandsize] = eopsize;
   16274           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_colmicrovectorsize] = emcvsize;
   16275           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_colparam0] = eparam0;
   16276           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_colparam1] = eparam1;
   16277           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_colparam2] = 0;
   16278           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_colparam3] = 0;
   16279           0 :     *rowptr = *rowptr+1;
   16280           0 : }
   16281             : 
   16282             : 
   16283             : /*************************************************************************
   16284             : Same as FTPushEntry(), but sets Param0, Param1, Param2 and Param3.
   16285             : This function pushes one more entry to the plan. It resized Entries matrix
   16286             : if needed.
   16287             : 
   16288             : INPUT PARAMETERS:
   16289             :     Plan        -   plan (generated so far)
   16290             :     RowPtr      -   index which points to past-the-last entry generated so far
   16291             :     EType       -   entry type
   16292             :     EOpCnt      -   operands count
   16293             :     EOpSize     -   operand size
   16294             :     EMcvSize    -   microvector size
   16295             :     EParam0     -   parameter 0
   16296             :     EParam1     -   parameter 1
   16297             :     EParam2     -   parameter 2
   16298             :     EParam3     -   parameter 3
   16299             :     
   16300             : OUTPUT PARAMETERS:
   16301             :     Plan        -   updated plan    
   16302             :     RowPtr      -   updated pointer
   16303             : 
   16304             :   -- ALGLIB --
   16305             :      Copyright 05.04.2013 by Bochkanov Sergey
   16306             : *************************************************************************/
   16307           0 : static void ftbase_ftpushentry4(fasttransformplan* plan,
   16308             :      ae_int_t* rowptr,
   16309             :      ae_int_t etype,
   16310             :      ae_int_t eopcnt,
   16311             :      ae_int_t eopsize,
   16312             :      ae_int_t emcvsize,
   16313             :      ae_int_t eparam0,
   16314             :      ae_int_t eparam1,
   16315             :      ae_int_t eparam2,
   16316             :      ae_int_t eparam3,
   16317             :      ae_state *_state)
   16318             : {
   16319             : 
   16320             : 
   16321           0 :     if( *rowptr>=plan->entries.rows )
   16322             :     {
   16323           0 :         imatrixresize(&plan->entries, ae_maxint(2*plan->entries.rows, 1, _state), ftbase_colscnt, _state);
   16324             :     }
   16325           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_coltype] = etype;
   16326           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_coloperandscnt] = eopcnt;
   16327           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_coloperandsize] = eopsize;
   16328           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_colmicrovectorsize] = emcvsize;
   16329           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_colparam0] = eparam0;
   16330           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_colparam1] = eparam1;
   16331           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_colparam2] = eparam2;
   16332           0 :     plan->entries.ptr.pp_int[*rowptr][ftbase_colparam3] = eparam3;
   16333           0 :     *rowptr = *rowptr+1;
   16334           0 : }
   16335             : 
   16336             : 
   16337             : /*************************************************************************
   16338             : This subroutine applies subplan to input/output array A.
   16339             : 
   16340             : INPUT PARAMETERS:
   16341             :     Plan        -   transformation plan
   16342             :     SubPlan     -   subplan index
   16343             :     A           -   array, must be large enough for plan to work
   16344             :     ABase       -   base offset in array A, this value points to start of
   16345             :                     subarray whose length is equal to length of the plan
   16346             :     AOffset     -   offset with respect to ABase, 0<=AOffset<PlanLength.
   16347             :                     This is an offset within large PlanLength-subarray of
   16348             :                     the chunk to process.
   16349             :     Buf         -   temporary buffer whose length is equal to plan length
   16350             :                     (without taking into account RepCnt) or larger.
   16351             :     OffsBuf     -   offset in the buffer array
   16352             :     RepCnt      -   repetition count (transformation is repeatedly applied
   16353             :                     to subsequent subarrays)
   16354             :     
   16355             : OUTPUT PARAMETERS:
   16356             :     Plan        -   plan (temporary buffers can be modified, plan itself
   16357             :                     is unchanged and can be reused)
   16358             :     A           -   transformed array
   16359             : 
   16360             :   -- ALGLIB --
   16361             :      Copyright 05.04.2013 by Bochkanov Sergey
   16362             : *************************************************************************/
   16363           0 : static void ftbase_ftapplysubplan(fasttransformplan* plan,
   16364             :      ae_int_t subplan,
   16365             :      /* Real    */ ae_vector* a,
   16366             :      ae_int_t abase,
   16367             :      ae_int_t aoffset,
   16368             :      /* Real    */ ae_vector* buf,
   16369             :      ae_int_t repcnt,
   16370             :      ae_state *_state)
   16371             : {
   16372             :     ae_frame _frame_block;
   16373             :     ae_int_t rowidx;
   16374             :     ae_int_t i;
   16375             :     ae_int_t n1;
   16376             :     ae_int_t n2;
   16377             :     ae_int_t operation;
   16378             :     ae_int_t operandscnt;
   16379             :     ae_int_t operandsize;
   16380             :     ae_int_t microvectorsize;
   16381             :     ae_int_t param0;
   16382             :     ae_int_t param1;
   16383             :     ae_int_t parentsize;
   16384             :     ae_int_t childsize;
   16385             :     ae_int_t chunksize;
   16386             :     ae_int_t lastchunksize;
   16387             :     srealarray *bufa;
   16388             :     ae_smart_ptr _bufa;
   16389             :     srealarray *bufb;
   16390             :     ae_smart_ptr _bufb;
   16391             :     srealarray *bufc;
   16392             :     ae_smart_ptr _bufc;
   16393             :     srealarray *bufd;
   16394             :     ae_smart_ptr _bufd;
   16395             : 
   16396           0 :     ae_frame_make(_state, &_frame_block);
   16397           0 :     memset(&_bufa, 0, sizeof(_bufa));
   16398           0 :     memset(&_bufb, 0, sizeof(_bufb));
   16399           0 :     memset(&_bufc, 0, sizeof(_bufc));
   16400           0 :     memset(&_bufd, 0, sizeof(_bufd));
   16401           0 :     ae_smart_ptr_init(&_bufa, (void**)&bufa, _state, ae_true);
   16402           0 :     ae_smart_ptr_init(&_bufb, (void**)&bufb, _state, ae_true);
   16403           0 :     ae_smart_ptr_init(&_bufc, (void**)&bufc, _state, ae_true);
   16404           0 :     ae_smart_ptr_init(&_bufd, (void**)&bufd, _state, ae_true);
   16405             : 
   16406           0 :     ae_assert(plan->entries.ptr.pp_int[subplan][ftbase_coltype]==ftbase_opstart, "FTApplySubPlan: incorrect subplan header", _state);
   16407           0 :     rowidx = subplan+1;
   16408           0 :     while(plan->entries.ptr.pp_int[rowidx][ftbase_coltype]!=ftbase_opend)
   16409             :     {
   16410           0 :         operation = plan->entries.ptr.pp_int[rowidx][ftbase_coltype];
   16411           0 :         operandscnt = repcnt*plan->entries.ptr.pp_int[rowidx][ftbase_coloperandscnt];
   16412           0 :         operandsize = plan->entries.ptr.pp_int[rowidx][ftbase_coloperandsize];
   16413           0 :         microvectorsize = plan->entries.ptr.pp_int[rowidx][ftbase_colmicrovectorsize];
   16414           0 :         param0 = plan->entries.ptr.pp_int[rowidx][ftbase_colparam0];
   16415           0 :         param1 = plan->entries.ptr.pp_int[rowidx][ftbase_colparam1];
   16416           0 :         touchint(&param1, _state);
   16417             :         
   16418             :         /*
   16419             :          * Process "jump" operation
   16420             :          */
   16421           0 :         if( operation==ftbase_opjmp )
   16422             :         {
   16423           0 :             rowidx = rowidx+plan->entries.ptr.pp_int[rowidx][ftbase_colparam0];
   16424           0 :             continue;
   16425             :         }
   16426             :         
   16427             :         /*
   16428             :          * Process "parallel call" operation:
   16429             :          * * we perform initial check for consistency between parent and child plans
   16430             :          * * we call FTSplitAndApplyParallelPlan(), which splits parallel plan into
   16431             :          *   several parallel tasks
   16432             :          */
   16433           0 :         if( operation==ftbase_opparallelcall )
   16434             :         {
   16435           0 :             parentsize = operandsize*microvectorsize;
   16436           0 :             childsize = plan->entries.ptr.pp_int[rowidx+param0][ftbase_coloperandscnt]*plan->entries.ptr.pp_int[rowidx+param0][ftbase_coloperandsize]*plan->entries.ptr.pp_int[rowidx+param0][ftbase_colmicrovectorsize];
   16437           0 :             ae_assert(plan->entries.ptr.pp_int[rowidx+param0][ftbase_coltype]==ftbase_opstart, "FTApplySubPlan: incorrect child subplan header", _state);
   16438           0 :             ae_assert(parentsize==childsize, "FTApplySubPlan: incorrect child subplan header", _state);
   16439           0 :             chunksize = ae_maxint(ftbase_recursivethreshold/childsize, 1, _state);
   16440           0 :             lastchunksize = operandscnt%chunksize;
   16441           0 :             if( lastchunksize==0 )
   16442             :             {
   16443           0 :                 lastchunksize = chunksize;
   16444             :             }
   16445           0 :             i = 0;
   16446           0 :             while(i<operandscnt)
   16447             :             {
   16448           0 :                 chunksize = ae_minint(chunksize, operandscnt-i, _state);
   16449           0 :                 ftbase_ftapplysubplan(plan, rowidx+param0, a, abase, aoffset+i*childsize, buf, chunksize, _state);
   16450           0 :                 i = i+chunksize;
   16451             :             }
   16452           0 :             rowidx = rowidx+1;
   16453           0 :             continue;
   16454             :         }
   16455             :         
   16456             :         /*
   16457             :          * Process "reference complex FFT" operation
   16458             :          */
   16459           0 :         if( operation==ftbase_opcomplexreffft )
   16460             :         {
   16461           0 :             ftbase_ftapplycomplexreffft(a, abase+aoffset, operandscnt, operandsize, microvectorsize, buf, _state);
   16462           0 :             rowidx = rowidx+1;
   16463           0 :             continue;
   16464             :         }
   16465             :         
   16466             :         /*
   16467             :          * Process "codelet FFT" operation
   16468             :          */
   16469           0 :         if( operation==ftbase_opcomplexcodeletfft )
   16470             :         {
   16471           0 :             ftbase_ftapplycomplexcodeletfft(a, abase+aoffset, operandscnt, operandsize, microvectorsize, _state);
   16472           0 :             rowidx = rowidx+1;
   16473           0 :             continue;
   16474             :         }
   16475             :         
   16476             :         /*
   16477             :          * Process "integrated codelet FFT" operation
   16478             :          */
   16479           0 :         if( operation==ftbase_opcomplexcodelettwfft )
   16480             :         {
   16481           0 :             ftbase_ftapplycomplexcodelettwfft(a, abase+aoffset, operandscnt, operandsize, microvectorsize, _state);
   16482           0 :             rowidx = rowidx+1;
   16483           0 :             continue;
   16484             :         }
   16485             :         
   16486             :         /*
   16487             :          * Process Bluestein's FFT operation
   16488             :          */
   16489           0 :         if( operation==ftbase_opbluesteinsfft )
   16490             :         {
   16491           0 :             ae_assert(microvectorsize==2, "FTApplySubPlan: microvectorsize!=2 for Bluesteins FFT", _state);
   16492           0 :             ae_shared_pool_retrieve(&plan->bluesteinpool, &_bufa, _state);
   16493           0 :             ae_shared_pool_retrieve(&plan->bluesteinpool, &_bufb, _state);
   16494           0 :             ae_shared_pool_retrieve(&plan->bluesteinpool, &_bufc, _state);
   16495           0 :             ae_shared_pool_retrieve(&plan->bluesteinpool, &_bufd, _state);
   16496           0 :             ftbase_ftbluesteinsfft(plan, a, abase, aoffset, operandscnt, operandsize, plan->entries.ptr.pp_int[rowidx][ftbase_colparam0], plan->entries.ptr.pp_int[rowidx][ftbase_colparam2], rowidx+plan->entries.ptr.pp_int[rowidx][ftbase_colparam1], &bufa->val, &bufb->val, &bufc->val, &bufd->val, _state);
   16497           0 :             ae_shared_pool_recycle(&plan->bluesteinpool, &_bufa, _state);
   16498           0 :             ae_shared_pool_recycle(&plan->bluesteinpool, &_bufb, _state);
   16499           0 :             ae_shared_pool_recycle(&plan->bluesteinpool, &_bufc, _state);
   16500           0 :             ae_shared_pool_recycle(&plan->bluesteinpool, &_bufd, _state);
   16501           0 :             rowidx = rowidx+1;
   16502           0 :             continue;
   16503             :         }
   16504             :         
   16505             :         /*
   16506             :          * Process Rader's FFT
   16507             :          */
   16508           0 :         if( operation==ftbase_opradersfft )
   16509             :         {
   16510           0 :             ftbase_ftradersfft(plan, a, abase, aoffset, operandscnt, operandsize, rowidx+plan->entries.ptr.pp_int[rowidx][ftbase_colparam0], plan->entries.ptr.pp_int[rowidx][ftbase_colparam1], plan->entries.ptr.pp_int[rowidx][ftbase_colparam2], plan->entries.ptr.pp_int[rowidx][ftbase_colparam3], buf, _state);
   16511           0 :             rowidx = rowidx+1;
   16512           0 :             continue;
   16513             :         }
   16514             :         
   16515             :         /*
   16516             :          * Process "complex twiddle factors" operation
   16517             :          */
   16518           0 :         if( operation==ftbase_opcomplexfftfactors )
   16519             :         {
   16520           0 :             ae_assert(microvectorsize==2, "FTApplySubPlan: MicrovectorSize<>1", _state);
   16521           0 :             n1 = plan->entries.ptr.pp_int[rowidx][ftbase_colparam0];
   16522           0 :             n2 = operandsize/n1;
   16523           0 :             for(i=0; i<=operandscnt-1; i++)
   16524             :             {
   16525           0 :                 ftbase_ffttwcalc(a, abase+aoffset+i*operandsize*2, n1, n2, _state);
   16526             :             }
   16527           0 :             rowidx = rowidx+1;
   16528           0 :             continue;
   16529             :         }
   16530             :         
   16531             :         /*
   16532             :          * Process "complex transposition" operation
   16533             :          */
   16534           0 :         if( operation==ftbase_opcomplextranspose )
   16535             :         {
   16536           0 :             ae_assert(microvectorsize==2, "FTApplySubPlan: MicrovectorSize<>1", _state);
   16537           0 :             n1 = plan->entries.ptr.pp_int[rowidx][ftbase_colparam0];
   16538           0 :             n2 = operandsize/n1;
   16539           0 :             for(i=0; i<=operandscnt-1; i++)
   16540             :             {
   16541           0 :                 ftbase_internalcomplexlintranspose(a, n1, n2, abase+aoffset+i*operandsize*2, buf, _state);
   16542             :             }
   16543           0 :             rowidx = rowidx+1;
   16544           0 :             continue;
   16545             :         }
   16546             :         
   16547             :         /*
   16548             :          * Error
   16549             :          */
   16550           0 :         ae_assert(ae_false, "FTApplySubPlan: unexpected plan type", _state);
   16551             :     }
   16552           0 :     ae_frame_leave(_state);
   16553           0 : }
   16554             : 
   16555             : 
   16556             : /*************************************************************************
   16557             : This subroutine applies complex reference FFT to input/output array A.
   16558             : 
   16559             : VERY SLOW OPERATION, do not use it in real life plans :)
   16560             : 
   16561             : INPUT PARAMETERS:
   16562             :     A           -   array, must be large enough for plan to work
   16563             :     Offs        -   offset of the subarray to process
   16564             :     OperandsCnt -   operands count (see description of FastTransformPlan)
   16565             :     OperandSize -   operand size (see description of FastTransformPlan)
   16566             :     MicrovectorSize-microvector size (see description of FastTransformPlan)
   16567             :     Buf         -   temporary array, must be at least OperandsCnt*OperandSize*MicrovectorSize
   16568             :     
   16569             : OUTPUT PARAMETERS:
   16570             :     A           -   transformed array
   16571             : 
   16572             :   -- ALGLIB --
   16573             :      Copyright 05.04.2013 by Bochkanov Sergey
   16574             : *************************************************************************/
   16575           0 : static void ftbase_ftapplycomplexreffft(/* Real    */ ae_vector* a,
   16576             :      ae_int_t offs,
   16577             :      ae_int_t operandscnt,
   16578             :      ae_int_t operandsize,
   16579             :      ae_int_t microvectorsize,
   16580             :      /* Real    */ ae_vector* buf,
   16581             :      ae_state *_state)
   16582             : {
   16583             :     ae_int_t opidx;
   16584             :     ae_int_t i;
   16585             :     ae_int_t k;
   16586             :     double hre;
   16587             :     double him;
   16588             :     double c;
   16589             :     double s;
   16590             :     double re;
   16591             :     double im;
   16592             :     ae_int_t n;
   16593             : 
   16594             : 
   16595           0 :     ae_assert(operandscnt>=1, "FTApplyComplexRefFFT: OperandsCnt<1", _state);
   16596           0 :     ae_assert(operandsize>=1, "FTApplyComplexRefFFT: OperandSize<1", _state);
   16597           0 :     ae_assert(microvectorsize==2, "FTApplyComplexRefFFT: MicrovectorSize<>2", _state);
   16598           0 :     n = operandsize;
   16599           0 :     for(opidx=0; opidx<=operandscnt-1; opidx++)
   16600             :     {
   16601           0 :         for(i=0; i<=n-1; i++)
   16602             :         {
   16603           0 :             hre = (double)(0);
   16604           0 :             him = (double)(0);
   16605           0 :             for(k=0; k<=n-1; k++)
   16606             :             {
   16607           0 :                 re = a->ptr.p_double[offs+opidx*operandsize*2+2*k+0];
   16608           0 :                 im = a->ptr.p_double[offs+opidx*operandsize*2+2*k+1];
   16609           0 :                 c = ae_cos(-2*ae_pi*k*i/n, _state);
   16610           0 :                 s = ae_sin(-2*ae_pi*k*i/n, _state);
   16611           0 :                 hre = hre+c*re-s*im;
   16612           0 :                 him = him+c*im+s*re;
   16613             :             }
   16614           0 :             buf->ptr.p_double[2*i+0] = hre;
   16615           0 :             buf->ptr.p_double[2*i+1] = him;
   16616             :         }
   16617           0 :         for(i=0; i<=operandsize*2-1; i++)
   16618             :         {
   16619           0 :             a->ptr.p_double[offs+opidx*operandsize*2+i] = buf->ptr.p_double[i];
   16620             :         }
   16621             :     }
   16622           0 : }
   16623             : 
   16624             : 
   16625             : /*************************************************************************
   16626             : This subroutine applies complex codelet FFT to input/output array A.
   16627             : 
   16628             : INPUT PARAMETERS:
   16629             :     A           -   array, must be large enough for plan to work
   16630             :     Offs        -   offset of the subarray to process
   16631             :     OperandsCnt -   operands count (see description of FastTransformPlan)
   16632             :     OperandSize -   operand size (see description of FastTransformPlan)
   16633             :     MicrovectorSize-microvector size, must be 2
   16634             :     
   16635             : OUTPUT PARAMETERS:
   16636             :     A           -   transformed array
   16637             : 
   16638             :   -- ALGLIB --
   16639             :      Copyright 05.04.2013 by Bochkanov Sergey
   16640             : *************************************************************************/
   16641           0 : static void ftbase_ftapplycomplexcodeletfft(/* Real    */ ae_vector* a,
   16642             :      ae_int_t offs,
   16643             :      ae_int_t operandscnt,
   16644             :      ae_int_t operandsize,
   16645             :      ae_int_t microvectorsize,
   16646             :      ae_state *_state)
   16647             : {
   16648             :     ae_int_t opidx;
   16649             :     ae_int_t n;
   16650             :     ae_int_t aoffset;
   16651             :     double a0x;
   16652             :     double a0y;
   16653             :     double a1x;
   16654             :     double a1y;
   16655             :     double a2x;
   16656             :     double a2y;
   16657             :     double a3x;
   16658             :     double a3y;
   16659             :     double a4x;
   16660             :     double a4y;
   16661             :     double a5x;
   16662             :     double a5y;
   16663             :     double v0;
   16664             :     double v1;
   16665             :     double v2;
   16666             :     double v3;
   16667             :     double t1x;
   16668             :     double t1y;
   16669             :     double t2x;
   16670             :     double t2y;
   16671             :     double t3x;
   16672             :     double t3y;
   16673             :     double t4x;
   16674             :     double t4y;
   16675             :     double t5x;
   16676             :     double t5y;
   16677             :     double m1x;
   16678             :     double m1y;
   16679             :     double m2x;
   16680             :     double m2y;
   16681             :     double m3x;
   16682             :     double m3y;
   16683             :     double m4x;
   16684             :     double m4y;
   16685             :     double m5x;
   16686             :     double m5y;
   16687             :     double s1x;
   16688             :     double s1y;
   16689             :     double s2x;
   16690             :     double s2y;
   16691             :     double s3x;
   16692             :     double s3y;
   16693             :     double s4x;
   16694             :     double s4y;
   16695             :     double s5x;
   16696             :     double s5y;
   16697             :     double c1;
   16698             :     double c2;
   16699             :     double c3;
   16700             :     double c4;
   16701             :     double c5;
   16702             :     double v;
   16703             : 
   16704             : 
   16705           0 :     ae_assert(operandscnt>=1, "FTApplyComplexCodeletFFT: OperandsCnt<1", _state);
   16706           0 :     ae_assert(operandsize>=1, "FTApplyComplexCodeletFFT: OperandSize<1", _state);
   16707           0 :     ae_assert(microvectorsize==2, "FTApplyComplexCodeletFFT: MicrovectorSize<>2", _state);
   16708           0 :     n = operandsize;
   16709             :     
   16710             :     /*
   16711             :      * Hard-coded transforms for different N's
   16712             :      */
   16713           0 :     ae_assert(n<=ftbase_maxradix, "FTApplyComplexCodeletFFT: N>MaxRadix", _state);
   16714           0 :     if( n==2 )
   16715             :     {
   16716           0 :         for(opidx=0; opidx<=operandscnt-1; opidx++)
   16717             :         {
   16718           0 :             aoffset = offs+opidx*operandsize*2;
   16719           0 :             a0x = a->ptr.p_double[aoffset+0];
   16720           0 :             a0y = a->ptr.p_double[aoffset+1];
   16721           0 :             a1x = a->ptr.p_double[aoffset+2];
   16722           0 :             a1y = a->ptr.p_double[aoffset+3];
   16723           0 :             v0 = a0x+a1x;
   16724           0 :             v1 = a0y+a1y;
   16725           0 :             v2 = a0x-a1x;
   16726           0 :             v3 = a0y-a1y;
   16727           0 :             a->ptr.p_double[aoffset+0] = v0;
   16728           0 :             a->ptr.p_double[aoffset+1] = v1;
   16729           0 :             a->ptr.p_double[aoffset+2] = v2;
   16730           0 :             a->ptr.p_double[aoffset+3] = v3;
   16731             :         }
   16732           0 :         return;
   16733             :     }
   16734           0 :     if( n==3 )
   16735             :     {
   16736           0 :         c1 = ae_cos(2*ae_pi/3, _state)-1;
   16737           0 :         c2 = ae_sin(2*ae_pi/3, _state);
   16738           0 :         for(opidx=0; opidx<=operandscnt-1; opidx++)
   16739             :         {
   16740           0 :             aoffset = offs+opidx*operandsize*2;
   16741           0 :             a0x = a->ptr.p_double[aoffset+0];
   16742           0 :             a0y = a->ptr.p_double[aoffset+1];
   16743           0 :             a1x = a->ptr.p_double[aoffset+2];
   16744           0 :             a1y = a->ptr.p_double[aoffset+3];
   16745           0 :             a2x = a->ptr.p_double[aoffset+4];
   16746           0 :             a2y = a->ptr.p_double[aoffset+5];
   16747           0 :             t1x = a1x+a2x;
   16748           0 :             t1y = a1y+a2y;
   16749           0 :             a0x = a0x+t1x;
   16750           0 :             a0y = a0y+t1y;
   16751           0 :             m1x = c1*t1x;
   16752           0 :             m1y = c1*t1y;
   16753           0 :             m2x = c2*(a1y-a2y);
   16754           0 :             m2y = c2*(a2x-a1x);
   16755           0 :             s1x = a0x+m1x;
   16756           0 :             s1y = a0y+m1y;
   16757           0 :             a1x = s1x+m2x;
   16758           0 :             a1y = s1y+m2y;
   16759           0 :             a2x = s1x-m2x;
   16760           0 :             a2y = s1y-m2y;
   16761           0 :             a->ptr.p_double[aoffset+0] = a0x;
   16762           0 :             a->ptr.p_double[aoffset+1] = a0y;
   16763           0 :             a->ptr.p_double[aoffset+2] = a1x;
   16764           0 :             a->ptr.p_double[aoffset+3] = a1y;
   16765           0 :             a->ptr.p_double[aoffset+4] = a2x;
   16766           0 :             a->ptr.p_double[aoffset+5] = a2y;
   16767             :         }
   16768           0 :         return;
   16769             :     }
   16770           0 :     if( n==4 )
   16771             :     {
   16772           0 :         for(opidx=0; opidx<=operandscnt-1; opidx++)
   16773             :         {
   16774           0 :             aoffset = offs+opidx*operandsize*2;
   16775           0 :             a0x = a->ptr.p_double[aoffset+0];
   16776           0 :             a0y = a->ptr.p_double[aoffset+1];
   16777           0 :             a1x = a->ptr.p_double[aoffset+2];
   16778           0 :             a1y = a->ptr.p_double[aoffset+3];
   16779           0 :             a2x = a->ptr.p_double[aoffset+4];
   16780           0 :             a2y = a->ptr.p_double[aoffset+5];
   16781           0 :             a3x = a->ptr.p_double[aoffset+6];
   16782           0 :             a3y = a->ptr.p_double[aoffset+7];
   16783           0 :             t1x = a0x+a2x;
   16784           0 :             t1y = a0y+a2y;
   16785           0 :             t2x = a1x+a3x;
   16786           0 :             t2y = a1y+a3y;
   16787           0 :             m2x = a0x-a2x;
   16788           0 :             m2y = a0y-a2y;
   16789           0 :             m3x = a1y-a3y;
   16790           0 :             m3y = a3x-a1x;
   16791           0 :             a->ptr.p_double[aoffset+0] = t1x+t2x;
   16792           0 :             a->ptr.p_double[aoffset+1] = t1y+t2y;
   16793           0 :             a->ptr.p_double[aoffset+4] = t1x-t2x;
   16794           0 :             a->ptr.p_double[aoffset+5] = t1y-t2y;
   16795           0 :             a->ptr.p_double[aoffset+2] = m2x+m3x;
   16796           0 :             a->ptr.p_double[aoffset+3] = m2y+m3y;
   16797           0 :             a->ptr.p_double[aoffset+6] = m2x-m3x;
   16798           0 :             a->ptr.p_double[aoffset+7] = m2y-m3y;
   16799             :         }
   16800           0 :         return;
   16801             :     }
   16802           0 :     if( n==5 )
   16803             :     {
   16804           0 :         v = 2*ae_pi/5;
   16805           0 :         c1 = (ae_cos(v, _state)+ae_cos(2*v, _state))/2-1;
   16806           0 :         c2 = (ae_cos(v, _state)-ae_cos(2*v, _state))/2;
   16807           0 :         c3 = -ae_sin(v, _state);
   16808           0 :         c4 = -(ae_sin(v, _state)+ae_sin(2*v, _state));
   16809           0 :         c5 = ae_sin(v, _state)-ae_sin(2*v, _state);
   16810           0 :         for(opidx=0; opidx<=operandscnt-1; opidx++)
   16811             :         {
   16812           0 :             aoffset = offs+opidx*operandsize*2;
   16813           0 :             t1x = a->ptr.p_double[aoffset+2]+a->ptr.p_double[aoffset+8];
   16814           0 :             t1y = a->ptr.p_double[aoffset+3]+a->ptr.p_double[aoffset+9];
   16815           0 :             t2x = a->ptr.p_double[aoffset+4]+a->ptr.p_double[aoffset+6];
   16816           0 :             t2y = a->ptr.p_double[aoffset+5]+a->ptr.p_double[aoffset+7];
   16817           0 :             t3x = a->ptr.p_double[aoffset+2]-a->ptr.p_double[aoffset+8];
   16818           0 :             t3y = a->ptr.p_double[aoffset+3]-a->ptr.p_double[aoffset+9];
   16819           0 :             t4x = a->ptr.p_double[aoffset+6]-a->ptr.p_double[aoffset+4];
   16820           0 :             t4y = a->ptr.p_double[aoffset+7]-a->ptr.p_double[aoffset+5];
   16821           0 :             t5x = t1x+t2x;
   16822           0 :             t5y = t1y+t2y;
   16823           0 :             a->ptr.p_double[aoffset+0] = a->ptr.p_double[aoffset+0]+t5x;
   16824           0 :             a->ptr.p_double[aoffset+1] = a->ptr.p_double[aoffset+1]+t5y;
   16825           0 :             m1x = c1*t5x;
   16826           0 :             m1y = c1*t5y;
   16827           0 :             m2x = c2*(t1x-t2x);
   16828           0 :             m2y = c2*(t1y-t2y);
   16829           0 :             m3x = -c3*(t3y+t4y);
   16830           0 :             m3y = c3*(t3x+t4x);
   16831           0 :             m4x = -c4*t4y;
   16832           0 :             m4y = c4*t4x;
   16833           0 :             m5x = -c5*t3y;
   16834           0 :             m5y = c5*t3x;
   16835           0 :             s3x = m3x-m4x;
   16836           0 :             s3y = m3y-m4y;
   16837           0 :             s5x = m3x+m5x;
   16838           0 :             s5y = m3y+m5y;
   16839           0 :             s1x = a->ptr.p_double[aoffset+0]+m1x;
   16840           0 :             s1y = a->ptr.p_double[aoffset+1]+m1y;
   16841           0 :             s2x = s1x+m2x;
   16842           0 :             s2y = s1y+m2y;
   16843           0 :             s4x = s1x-m2x;
   16844           0 :             s4y = s1y-m2y;
   16845           0 :             a->ptr.p_double[aoffset+2] = s2x+s3x;
   16846           0 :             a->ptr.p_double[aoffset+3] = s2y+s3y;
   16847           0 :             a->ptr.p_double[aoffset+4] = s4x+s5x;
   16848           0 :             a->ptr.p_double[aoffset+5] = s4y+s5y;
   16849           0 :             a->ptr.p_double[aoffset+6] = s4x-s5x;
   16850           0 :             a->ptr.p_double[aoffset+7] = s4y-s5y;
   16851           0 :             a->ptr.p_double[aoffset+8] = s2x-s3x;
   16852           0 :             a->ptr.p_double[aoffset+9] = s2y-s3y;
   16853             :         }
   16854           0 :         return;
   16855             :     }
   16856           0 :     if( n==6 )
   16857             :     {
   16858           0 :         c1 = ae_cos(2*ae_pi/3, _state)-1;
   16859           0 :         c2 = ae_sin(2*ae_pi/3, _state);
   16860           0 :         c3 = ae_cos(-ae_pi/3, _state);
   16861           0 :         c4 = ae_sin(-ae_pi/3, _state);
   16862           0 :         for(opidx=0; opidx<=operandscnt-1; opidx++)
   16863             :         {
   16864           0 :             aoffset = offs+opidx*operandsize*2;
   16865           0 :             a0x = a->ptr.p_double[aoffset+0];
   16866           0 :             a0y = a->ptr.p_double[aoffset+1];
   16867           0 :             a1x = a->ptr.p_double[aoffset+2];
   16868           0 :             a1y = a->ptr.p_double[aoffset+3];
   16869           0 :             a2x = a->ptr.p_double[aoffset+4];
   16870           0 :             a2y = a->ptr.p_double[aoffset+5];
   16871           0 :             a3x = a->ptr.p_double[aoffset+6];
   16872           0 :             a3y = a->ptr.p_double[aoffset+7];
   16873           0 :             a4x = a->ptr.p_double[aoffset+8];
   16874           0 :             a4y = a->ptr.p_double[aoffset+9];
   16875           0 :             a5x = a->ptr.p_double[aoffset+10];
   16876           0 :             a5y = a->ptr.p_double[aoffset+11];
   16877           0 :             v0 = a0x;
   16878           0 :             v1 = a0y;
   16879           0 :             a0x = a0x+a3x;
   16880           0 :             a0y = a0y+a3y;
   16881           0 :             a3x = v0-a3x;
   16882           0 :             a3y = v1-a3y;
   16883           0 :             v0 = a1x;
   16884           0 :             v1 = a1y;
   16885           0 :             a1x = a1x+a4x;
   16886           0 :             a1y = a1y+a4y;
   16887           0 :             a4x = v0-a4x;
   16888           0 :             a4y = v1-a4y;
   16889           0 :             v0 = a2x;
   16890           0 :             v1 = a2y;
   16891           0 :             a2x = a2x+a5x;
   16892           0 :             a2y = a2y+a5y;
   16893           0 :             a5x = v0-a5x;
   16894           0 :             a5y = v1-a5y;
   16895           0 :             t4x = a4x*c3-a4y*c4;
   16896           0 :             t4y = a4x*c4+a4y*c3;
   16897           0 :             a4x = t4x;
   16898           0 :             a4y = t4y;
   16899           0 :             t5x = -a5x*c3-a5y*c4;
   16900           0 :             t5y = a5x*c4-a5y*c3;
   16901           0 :             a5x = t5x;
   16902           0 :             a5y = t5y;
   16903           0 :             t1x = a1x+a2x;
   16904           0 :             t1y = a1y+a2y;
   16905           0 :             a0x = a0x+t1x;
   16906           0 :             a0y = a0y+t1y;
   16907           0 :             m1x = c1*t1x;
   16908           0 :             m1y = c1*t1y;
   16909           0 :             m2x = c2*(a1y-a2y);
   16910           0 :             m2y = c2*(a2x-a1x);
   16911           0 :             s1x = a0x+m1x;
   16912           0 :             s1y = a0y+m1y;
   16913           0 :             a1x = s1x+m2x;
   16914           0 :             a1y = s1y+m2y;
   16915           0 :             a2x = s1x-m2x;
   16916           0 :             a2y = s1y-m2y;
   16917           0 :             t1x = a4x+a5x;
   16918           0 :             t1y = a4y+a5y;
   16919           0 :             a3x = a3x+t1x;
   16920           0 :             a3y = a3y+t1y;
   16921           0 :             m1x = c1*t1x;
   16922           0 :             m1y = c1*t1y;
   16923           0 :             m2x = c2*(a4y-a5y);
   16924           0 :             m2y = c2*(a5x-a4x);
   16925           0 :             s1x = a3x+m1x;
   16926           0 :             s1y = a3y+m1y;
   16927           0 :             a4x = s1x+m2x;
   16928           0 :             a4y = s1y+m2y;
   16929           0 :             a5x = s1x-m2x;
   16930           0 :             a5y = s1y-m2y;
   16931           0 :             a->ptr.p_double[aoffset+0] = a0x;
   16932           0 :             a->ptr.p_double[aoffset+1] = a0y;
   16933           0 :             a->ptr.p_double[aoffset+2] = a3x;
   16934           0 :             a->ptr.p_double[aoffset+3] = a3y;
   16935           0 :             a->ptr.p_double[aoffset+4] = a1x;
   16936           0 :             a->ptr.p_double[aoffset+5] = a1y;
   16937           0 :             a->ptr.p_double[aoffset+6] = a4x;
   16938           0 :             a->ptr.p_double[aoffset+7] = a4y;
   16939           0 :             a->ptr.p_double[aoffset+8] = a2x;
   16940           0 :             a->ptr.p_double[aoffset+9] = a2y;
   16941           0 :             a->ptr.p_double[aoffset+10] = a5x;
   16942           0 :             a->ptr.p_double[aoffset+11] = a5y;
   16943             :         }
   16944           0 :         return;
   16945             :     }
   16946             : }
   16947             : 
   16948             : 
   16949             : /*************************************************************************
   16950             : This subroutine applies complex "integrated" codelet FFT  to  input/output
   16951             : array A. "Integrated" codelet differs from "normal" one in following ways:
   16952             : * it can work with MicrovectorSize>1
   16953             : * hence, it can be used in Cooley-Tukey FFT without transpositions
   16954             : * it performs inlined multiplication by twiddle factors of Cooley-Tukey
   16955             :   FFT with N2=MicrovectorSize/2.
   16956             : 
   16957             : INPUT PARAMETERS:
   16958             :     A           -   array, must be large enough for plan to work
   16959             :     Offs        -   offset of the subarray to process
   16960             :     OperandsCnt -   operands count (see description of FastTransformPlan)
   16961             :     OperandSize -   operand size (see description of FastTransformPlan)
   16962             :     MicrovectorSize-microvector size, must be 1
   16963             :     
   16964             : OUTPUT PARAMETERS:
   16965             :     A           -   transformed array
   16966             : 
   16967             :   -- ALGLIB --
   16968             :      Copyright 05.04.2013 by Bochkanov Sergey
   16969             : *************************************************************************/
   16970           0 : static void ftbase_ftapplycomplexcodelettwfft(/* Real    */ ae_vector* a,
   16971             :      ae_int_t offs,
   16972             :      ae_int_t operandscnt,
   16973             :      ae_int_t operandsize,
   16974             :      ae_int_t microvectorsize,
   16975             :      ae_state *_state)
   16976             : {
   16977             :     ae_int_t opidx;
   16978             :     ae_int_t mvidx;
   16979             :     ae_int_t n;
   16980             :     ae_int_t m;
   16981             :     ae_int_t aoffset0;
   16982             :     ae_int_t aoffset2;
   16983             :     ae_int_t aoffset4;
   16984             :     ae_int_t aoffset6;
   16985             :     ae_int_t aoffset8;
   16986             :     ae_int_t aoffset10;
   16987             :     double a0x;
   16988             :     double a0y;
   16989             :     double a1x;
   16990             :     double a1y;
   16991             :     double a2x;
   16992             :     double a2y;
   16993             :     double a3x;
   16994             :     double a3y;
   16995             :     double a4x;
   16996             :     double a4y;
   16997             :     double a5x;
   16998             :     double a5y;
   16999             :     double v0;
   17000             :     double v1;
   17001             :     double v2;
   17002             :     double v3;
   17003             :     double q0x;
   17004             :     double q0y;
   17005             :     double t1x;
   17006             :     double t1y;
   17007             :     double t2x;
   17008             :     double t2y;
   17009             :     double t3x;
   17010             :     double t3y;
   17011             :     double t4x;
   17012             :     double t4y;
   17013             :     double t5x;
   17014             :     double t5y;
   17015             :     double m1x;
   17016             :     double m1y;
   17017             :     double m2x;
   17018             :     double m2y;
   17019             :     double m3x;
   17020             :     double m3y;
   17021             :     double m4x;
   17022             :     double m4y;
   17023             :     double m5x;
   17024             :     double m5y;
   17025             :     double s1x;
   17026             :     double s1y;
   17027             :     double s2x;
   17028             :     double s2y;
   17029             :     double s3x;
   17030             :     double s3y;
   17031             :     double s4x;
   17032             :     double s4y;
   17033             :     double s5x;
   17034             :     double s5y;
   17035             :     double c1;
   17036             :     double c2;
   17037             :     double c3;
   17038             :     double c4;
   17039             :     double c5;
   17040             :     double v;
   17041             :     double tw0;
   17042             :     double tw1;
   17043             :     double twx;
   17044             :     double twxm1;
   17045             :     double twy;
   17046             :     double tw2x;
   17047             :     double tw2y;
   17048             :     double tw3x;
   17049             :     double tw3y;
   17050             :     double tw4x;
   17051             :     double tw4y;
   17052             :     double tw5x;
   17053             :     double tw5y;
   17054             : 
   17055             : 
   17056           0 :     ae_assert(operandscnt>=1, "FTApplyComplexCodeletFFT: OperandsCnt<1", _state);
   17057           0 :     ae_assert(operandsize>=1, "FTApplyComplexCodeletFFT: OperandSize<1", _state);
   17058           0 :     ae_assert(microvectorsize>=1, "FTApplyComplexCodeletFFT: MicrovectorSize<>1", _state);
   17059           0 :     ae_assert(microvectorsize%2==0, "FTApplyComplexCodeletFFT: MicrovectorSize is not even", _state);
   17060           0 :     n = operandsize;
   17061           0 :     m = microvectorsize/2;
   17062             :     
   17063             :     /*
   17064             :      * Hard-coded transforms for different N's
   17065             :      */
   17066           0 :     ae_assert(n<=ftbase_maxradix, "FTApplyComplexCodeletTwFFT: N>MaxRadix", _state);
   17067           0 :     if( n==2 )
   17068             :     {
   17069           0 :         v = -2*ae_pi/(n*m);
   17070           0 :         tw0 = -2*ae_sqr(ae_sin(0.5*v, _state), _state);
   17071           0 :         tw1 = ae_sin(v, _state);
   17072           0 :         for(opidx=0; opidx<=operandscnt-1; opidx++)
   17073             :         {
   17074           0 :             aoffset0 = offs+opidx*operandsize*microvectorsize;
   17075           0 :             aoffset2 = aoffset0+microvectorsize;
   17076           0 :             twxm1 = 0.0;
   17077           0 :             twy = 0.0;
   17078           0 :             for(mvidx=0; mvidx<=m-1; mvidx++)
   17079             :             {
   17080           0 :                 a0x = a->ptr.p_double[aoffset0];
   17081           0 :                 a0y = a->ptr.p_double[aoffset0+1];
   17082           0 :                 a1x = a->ptr.p_double[aoffset2];
   17083           0 :                 a1y = a->ptr.p_double[aoffset2+1];
   17084           0 :                 v0 = a0x+a1x;
   17085           0 :                 v1 = a0y+a1y;
   17086           0 :                 v2 = a0x-a1x;
   17087           0 :                 v3 = a0y-a1y;
   17088           0 :                 a->ptr.p_double[aoffset0] = v0;
   17089           0 :                 a->ptr.p_double[aoffset0+1] = v1;
   17090           0 :                 a->ptr.p_double[aoffset2] = v2*(1+twxm1)-v3*twy;
   17091           0 :                 a->ptr.p_double[aoffset2+1] = v3*(1+twxm1)+v2*twy;
   17092           0 :                 aoffset0 = aoffset0+2;
   17093           0 :                 aoffset2 = aoffset2+2;
   17094           0 :                 if( (mvidx+1)%ftbase_updatetw==0 )
   17095             :                 {
   17096           0 :                     v = -2*ae_pi*(mvidx+1)/(n*m);
   17097           0 :                     twxm1 = ae_sin(0.5*v, _state);
   17098           0 :                     twxm1 = -2*twxm1*twxm1;
   17099           0 :                     twy = ae_sin(v, _state);
   17100             :                 }
   17101             :                 else
   17102             :                 {
   17103           0 :                     v = twxm1+tw0+twxm1*tw0-twy*tw1;
   17104           0 :                     twy = twy+tw1+twxm1*tw1+twy*tw0;
   17105           0 :                     twxm1 = v;
   17106             :                 }
   17107             :             }
   17108             :         }
   17109           0 :         return;
   17110             :     }
   17111           0 :     if( n==3 )
   17112             :     {
   17113           0 :         v = -2*ae_pi/(n*m);
   17114           0 :         tw0 = -2*ae_sqr(ae_sin(0.5*v, _state), _state);
   17115           0 :         tw1 = ae_sin(v, _state);
   17116           0 :         c1 = ae_cos(2*ae_pi/3, _state)-1;
   17117           0 :         c2 = ae_sin(2*ae_pi/3, _state);
   17118           0 :         for(opidx=0; opidx<=operandscnt-1; opidx++)
   17119             :         {
   17120           0 :             aoffset0 = offs+opidx*operandsize*microvectorsize;
   17121           0 :             aoffset2 = aoffset0+microvectorsize;
   17122           0 :             aoffset4 = aoffset2+microvectorsize;
   17123           0 :             twx = 1.0;
   17124           0 :             twxm1 = 0.0;
   17125           0 :             twy = 0.0;
   17126           0 :             for(mvidx=0; mvidx<=m-1; mvidx++)
   17127             :             {
   17128           0 :                 a0x = a->ptr.p_double[aoffset0];
   17129           0 :                 a0y = a->ptr.p_double[aoffset0+1];
   17130           0 :                 a1x = a->ptr.p_double[aoffset2];
   17131           0 :                 a1y = a->ptr.p_double[aoffset2+1];
   17132           0 :                 a2x = a->ptr.p_double[aoffset4];
   17133           0 :                 a2y = a->ptr.p_double[aoffset4+1];
   17134           0 :                 t1x = a1x+a2x;
   17135           0 :                 t1y = a1y+a2y;
   17136           0 :                 a0x = a0x+t1x;
   17137           0 :                 a0y = a0y+t1y;
   17138           0 :                 m1x = c1*t1x;
   17139           0 :                 m1y = c1*t1y;
   17140           0 :                 m2x = c2*(a1y-a2y);
   17141           0 :                 m2y = c2*(a2x-a1x);
   17142           0 :                 s1x = a0x+m1x;
   17143           0 :                 s1y = a0y+m1y;
   17144           0 :                 a1x = s1x+m2x;
   17145           0 :                 a1y = s1y+m2y;
   17146           0 :                 a2x = s1x-m2x;
   17147           0 :                 a2y = s1y-m2y;
   17148           0 :                 tw2x = twx*twx-twy*twy;
   17149           0 :                 tw2y = 2*twx*twy;
   17150           0 :                 a->ptr.p_double[aoffset0] = a0x;
   17151           0 :                 a->ptr.p_double[aoffset0+1] = a0y;
   17152           0 :                 a->ptr.p_double[aoffset2] = a1x*twx-a1y*twy;
   17153           0 :                 a->ptr.p_double[aoffset2+1] = a1y*twx+a1x*twy;
   17154           0 :                 a->ptr.p_double[aoffset4] = a2x*tw2x-a2y*tw2y;
   17155           0 :                 a->ptr.p_double[aoffset4+1] = a2y*tw2x+a2x*tw2y;
   17156           0 :                 aoffset0 = aoffset0+2;
   17157           0 :                 aoffset2 = aoffset2+2;
   17158           0 :                 aoffset4 = aoffset4+2;
   17159           0 :                 if( (mvidx+1)%ftbase_updatetw==0 )
   17160             :                 {
   17161           0 :                     v = -2*ae_pi*(mvidx+1)/(n*m);
   17162           0 :                     twxm1 = ae_sin(0.5*v, _state);
   17163           0 :                     twxm1 = -2*twxm1*twxm1;
   17164           0 :                     twy = ae_sin(v, _state);
   17165           0 :                     twx = twxm1+1;
   17166             :                 }
   17167             :                 else
   17168             :                 {
   17169           0 :                     v = twxm1+tw0+twxm1*tw0-twy*tw1;
   17170           0 :                     twy = twy+tw1+twxm1*tw1+twy*tw0;
   17171           0 :                     twxm1 = v;
   17172           0 :                     twx = v+1;
   17173             :                 }
   17174             :             }
   17175             :         }
   17176           0 :         return;
   17177             :     }
   17178           0 :     if( n==4 )
   17179             :     {
   17180           0 :         v = -2*ae_pi/(n*m);
   17181           0 :         tw0 = -2*ae_sqr(ae_sin(0.5*v, _state), _state);
   17182           0 :         tw1 = ae_sin(v, _state);
   17183           0 :         for(opidx=0; opidx<=operandscnt-1; opidx++)
   17184             :         {
   17185           0 :             aoffset0 = offs+opidx*operandsize*microvectorsize;
   17186           0 :             aoffset2 = aoffset0+microvectorsize;
   17187           0 :             aoffset4 = aoffset2+microvectorsize;
   17188           0 :             aoffset6 = aoffset4+microvectorsize;
   17189           0 :             twx = 1.0;
   17190           0 :             twxm1 = 0.0;
   17191           0 :             twy = 0.0;
   17192           0 :             for(mvidx=0; mvidx<=m-1; mvidx++)
   17193             :             {
   17194           0 :                 a0x = a->ptr.p_double[aoffset0];
   17195           0 :                 a0y = a->ptr.p_double[aoffset0+1];
   17196           0 :                 a1x = a->ptr.p_double[aoffset2];
   17197           0 :                 a1y = a->ptr.p_double[aoffset2+1];
   17198           0 :                 a2x = a->ptr.p_double[aoffset4];
   17199           0 :                 a2y = a->ptr.p_double[aoffset4+1];
   17200           0 :                 a3x = a->ptr.p_double[aoffset6];
   17201           0 :                 a3y = a->ptr.p_double[aoffset6+1];
   17202           0 :                 t1x = a0x+a2x;
   17203           0 :                 t1y = a0y+a2y;
   17204           0 :                 t2x = a1x+a3x;
   17205           0 :                 t2y = a1y+a3y;
   17206           0 :                 m2x = a0x-a2x;
   17207           0 :                 m2y = a0y-a2y;
   17208           0 :                 m3x = a1y-a3y;
   17209           0 :                 m3y = a3x-a1x;
   17210           0 :                 tw2x = twx*twx-twy*twy;
   17211           0 :                 tw2y = 2*twx*twy;
   17212           0 :                 tw3x = twx*tw2x-twy*tw2y;
   17213           0 :                 tw3y = twx*tw2y+twy*tw2x;
   17214           0 :                 a1x = m2x+m3x;
   17215           0 :                 a1y = m2y+m3y;
   17216           0 :                 a2x = t1x-t2x;
   17217           0 :                 a2y = t1y-t2y;
   17218           0 :                 a3x = m2x-m3x;
   17219           0 :                 a3y = m2y-m3y;
   17220           0 :                 a->ptr.p_double[aoffset0] = t1x+t2x;
   17221           0 :                 a->ptr.p_double[aoffset0+1] = t1y+t2y;
   17222           0 :                 a->ptr.p_double[aoffset2] = a1x*twx-a1y*twy;
   17223           0 :                 a->ptr.p_double[aoffset2+1] = a1y*twx+a1x*twy;
   17224           0 :                 a->ptr.p_double[aoffset4] = a2x*tw2x-a2y*tw2y;
   17225           0 :                 a->ptr.p_double[aoffset4+1] = a2y*tw2x+a2x*tw2y;
   17226           0 :                 a->ptr.p_double[aoffset6] = a3x*tw3x-a3y*tw3y;
   17227           0 :                 a->ptr.p_double[aoffset6+1] = a3y*tw3x+a3x*tw3y;
   17228           0 :                 aoffset0 = aoffset0+2;
   17229           0 :                 aoffset2 = aoffset2+2;
   17230           0 :                 aoffset4 = aoffset4+2;
   17231           0 :                 aoffset6 = aoffset6+2;
   17232           0 :                 if( (mvidx+1)%ftbase_updatetw==0 )
   17233             :                 {
   17234           0 :                     v = -2*ae_pi*(mvidx+1)/(n*m);
   17235           0 :                     twxm1 = ae_sin(0.5*v, _state);
   17236           0 :                     twxm1 = -2*twxm1*twxm1;
   17237           0 :                     twy = ae_sin(v, _state);
   17238           0 :                     twx = twxm1+1;
   17239             :                 }
   17240             :                 else
   17241             :                 {
   17242           0 :                     v = twxm1+tw0+twxm1*tw0-twy*tw1;
   17243           0 :                     twy = twy+tw1+twxm1*tw1+twy*tw0;
   17244           0 :                     twxm1 = v;
   17245           0 :                     twx = v+1;
   17246             :                 }
   17247             :             }
   17248             :         }
   17249           0 :         return;
   17250             :     }
   17251           0 :     if( n==5 )
   17252             :     {
   17253           0 :         v = -2*ae_pi/(n*m);
   17254           0 :         tw0 = -2*ae_sqr(ae_sin(0.5*v, _state), _state);
   17255           0 :         tw1 = ae_sin(v, _state);
   17256           0 :         v = 2*ae_pi/5;
   17257           0 :         c1 = (ae_cos(v, _state)+ae_cos(2*v, _state))/2-1;
   17258           0 :         c2 = (ae_cos(v, _state)-ae_cos(2*v, _state))/2;
   17259           0 :         c3 = -ae_sin(v, _state);
   17260           0 :         c4 = -(ae_sin(v, _state)+ae_sin(2*v, _state));
   17261           0 :         c5 = ae_sin(v, _state)-ae_sin(2*v, _state);
   17262           0 :         for(opidx=0; opidx<=operandscnt-1; opidx++)
   17263             :         {
   17264           0 :             aoffset0 = offs+opidx*operandsize*microvectorsize;
   17265           0 :             aoffset2 = aoffset0+microvectorsize;
   17266           0 :             aoffset4 = aoffset2+microvectorsize;
   17267           0 :             aoffset6 = aoffset4+microvectorsize;
   17268           0 :             aoffset8 = aoffset6+microvectorsize;
   17269           0 :             twx = 1.0;
   17270           0 :             twxm1 = 0.0;
   17271           0 :             twy = 0.0;
   17272           0 :             for(mvidx=0; mvidx<=m-1; mvidx++)
   17273             :             {
   17274           0 :                 a0x = a->ptr.p_double[aoffset0];
   17275           0 :                 a0y = a->ptr.p_double[aoffset0+1];
   17276           0 :                 a1x = a->ptr.p_double[aoffset2];
   17277           0 :                 a1y = a->ptr.p_double[aoffset2+1];
   17278           0 :                 a2x = a->ptr.p_double[aoffset4];
   17279           0 :                 a2y = a->ptr.p_double[aoffset4+1];
   17280           0 :                 a3x = a->ptr.p_double[aoffset6];
   17281           0 :                 a3y = a->ptr.p_double[aoffset6+1];
   17282           0 :                 a4x = a->ptr.p_double[aoffset8];
   17283           0 :                 a4y = a->ptr.p_double[aoffset8+1];
   17284           0 :                 t1x = a1x+a4x;
   17285           0 :                 t1y = a1y+a4y;
   17286           0 :                 t2x = a2x+a3x;
   17287           0 :                 t2y = a2y+a3y;
   17288           0 :                 t3x = a1x-a4x;
   17289           0 :                 t3y = a1y-a4y;
   17290           0 :                 t4x = a3x-a2x;
   17291           0 :                 t4y = a3y-a2y;
   17292           0 :                 t5x = t1x+t2x;
   17293           0 :                 t5y = t1y+t2y;
   17294           0 :                 q0x = a0x+t5x;
   17295           0 :                 q0y = a0y+t5y;
   17296           0 :                 m1x = c1*t5x;
   17297           0 :                 m1y = c1*t5y;
   17298           0 :                 m2x = c2*(t1x-t2x);
   17299           0 :                 m2y = c2*(t1y-t2y);
   17300           0 :                 m3x = -c3*(t3y+t4y);
   17301           0 :                 m3y = c3*(t3x+t4x);
   17302           0 :                 m4x = -c4*t4y;
   17303           0 :                 m4y = c4*t4x;
   17304           0 :                 m5x = -c5*t3y;
   17305           0 :                 m5y = c5*t3x;
   17306           0 :                 s3x = m3x-m4x;
   17307           0 :                 s3y = m3y-m4y;
   17308           0 :                 s5x = m3x+m5x;
   17309           0 :                 s5y = m3y+m5y;
   17310           0 :                 s1x = q0x+m1x;
   17311           0 :                 s1y = q0y+m1y;
   17312           0 :                 s2x = s1x+m2x;
   17313           0 :                 s2y = s1y+m2y;
   17314           0 :                 s4x = s1x-m2x;
   17315           0 :                 s4y = s1y-m2y;
   17316           0 :                 tw2x = twx*twx-twy*twy;
   17317           0 :                 tw2y = 2*twx*twy;
   17318           0 :                 tw3x = twx*tw2x-twy*tw2y;
   17319           0 :                 tw3y = twx*tw2y+twy*tw2x;
   17320           0 :                 tw4x = tw2x*tw2x-tw2y*tw2y;
   17321           0 :                 tw4y = tw2x*tw2y+tw2y*tw2x;
   17322           0 :                 a1x = s2x+s3x;
   17323           0 :                 a1y = s2y+s3y;
   17324           0 :                 a2x = s4x+s5x;
   17325           0 :                 a2y = s4y+s5y;
   17326           0 :                 a3x = s4x-s5x;
   17327           0 :                 a3y = s4y-s5y;
   17328           0 :                 a4x = s2x-s3x;
   17329           0 :                 a4y = s2y-s3y;
   17330           0 :                 a->ptr.p_double[aoffset0] = q0x;
   17331           0 :                 a->ptr.p_double[aoffset0+1] = q0y;
   17332           0 :                 a->ptr.p_double[aoffset2] = a1x*twx-a1y*twy;
   17333           0 :                 a->ptr.p_double[aoffset2+1] = a1x*twy+a1y*twx;
   17334           0 :                 a->ptr.p_double[aoffset4] = a2x*tw2x-a2y*tw2y;
   17335           0 :                 a->ptr.p_double[aoffset4+1] = a2x*tw2y+a2y*tw2x;
   17336           0 :                 a->ptr.p_double[aoffset6] = a3x*tw3x-a3y*tw3y;
   17337           0 :                 a->ptr.p_double[aoffset6+1] = a3x*tw3y+a3y*tw3x;
   17338           0 :                 a->ptr.p_double[aoffset8] = a4x*tw4x-a4y*tw4y;
   17339           0 :                 a->ptr.p_double[aoffset8+1] = a4x*tw4y+a4y*tw4x;
   17340           0 :                 aoffset0 = aoffset0+2;
   17341           0 :                 aoffset2 = aoffset2+2;
   17342           0 :                 aoffset4 = aoffset4+2;
   17343           0 :                 aoffset6 = aoffset6+2;
   17344           0 :                 aoffset8 = aoffset8+2;
   17345           0 :                 if( (mvidx+1)%ftbase_updatetw==0 )
   17346             :                 {
   17347           0 :                     v = -2*ae_pi*(mvidx+1)/(n*m);
   17348           0 :                     twxm1 = ae_sin(0.5*v, _state);
   17349           0 :                     twxm1 = -2*twxm1*twxm1;
   17350           0 :                     twy = ae_sin(v, _state);
   17351           0 :                     twx = twxm1+1;
   17352             :                 }
   17353             :                 else
   17354             :                 {
   17355           0 :                     v = twxm1+tw0+twxm1*tw0-twy*tw1;
   17356           0 :                     twy = twy+tw1+twxm1*tw1+twy*tw0;
   17357           0 :                     twxm1 = v;
   17358           0 :                     twx = v+1;
   17359             :                 }
   17360             :             }
   17361             :         }
   17362           0 :         return;
   17363             :     }
   17364           0 :     if( n==6 )
   17365             :     {
   17366           0 :         c1 = ae_cos(2*ae_pi/3, _state)-1;
   17367           0 :         c2 = ae_sin(2*ae_pi/3, _state);
   17368           0 :         c3 = ae_cos(-ae_pi/3, _state);
   17369           0 :         c4 = ae_sin(-ae_pi/3, _state);
   17370           0 :         v = -2*ae_pi/(n*m);
   17371           0 :         tw0 = -2*ae_sqr(ae_sin(0.5*v, _state), _state);
   17372           0 :         tw1 = ae_sin(v, _state);
   17373           0 :         for(opidx=0; opidx<=operandscnt-1; opidx++)
   17374             :         {
   17375           0 :             aoffset0 = offs+opidx*operandsize*microvectorsize;
   17376           0 :             aoffset2 = aoffset0+microvectorsize;
   17377           0 :             aoffset4 = aoffset2+microvectorsize;
   17378           0 :             aoffset6 = aoffset4+microvectorsize;
   17379           0 :             aoffset8 = aoffset6+microvectorsize;
   17380           0 :             aoffset10 = aoffset8+microvectorsize;
   17381           0 :             twx = 1.0;
   17382           0 :             twxm1 = 0.0;
   17383           0 :             twy = 0.0;
   17384           0 :             for(mvidx=0; mvidx<=m-1; mvidx++)
   17385             :             {
   17386           0 :                 a0x = a->ptr.p_double[aoffset0+0];
   17387           0 :                 a0y = a->ptr.p_double[aoffset0+1];
   17388           0 :                 a1x = a->ptr.p_double[aoffset2+0];
   17389           0 :                 a1y = a->ptr.p_double[aoffset2+1];
   17390           0 :                 a2x = a->ptr.p_double[aoffset4+0];
   17391           0 :                 a2y = a->ptr.p_double[aoffset4+1];
   17392           0 :                 a3x = a->ptr.p_double[aoffset6+0];
   17393           0 :                 a3y = a->ptr.p_double[aoffset6+1];
   17394           0 :                 a4x = a->ptr.p_double[aoffset8+0];
   17395           0 :                 a4y = a->ptr.p_double[aoffset8+1];
   17396           0 :                 a5x = a->ptr.p_double[aoffset10+0];
   17397           0 :                 a5y = a->ptr.p_double[aoffset10+1];
   17398           0 :                 v0 = a0x;
   17399           0 :                 v1 = a0y;
   17400           0 :                 a0x = a0x+a3x;
   17401           0 :                 a0y = a0y+a3y;
   17402           0 :                 a3x = v0-a3x;
   17403           0 :                 a3y = v1-a3y;
   17404           0 :                 v0 = a1x;
   17405           0 :                 v1 = a1y;
   17406           0 :                 a1x = a1x+a4x;
   17407           0 :                 a1y = a1y+a4y;
   17408           0 :                 a4x = v0-a4x;
   17409           0 :                 a4y = v1-a4y;
   17410           0 :                 v0 = a2x;
   17411           0 :                 v1 = a2y;
   17412           0 :                 a2x = a2x+a5x;
   17413           0 :                 a2y = a2y+a5y;
   17414           0 :                 a5x = v0-a5x;
   17415           0 :                 a5y = v1-a5y;
   17416           0 :                 t4x = a4x*c3-a4y*c4;
   17417           0 :                 t4y = a4x*c4+a4y*c3;
   17418           0 :                 a4x = t4x;
   17419           0 :                 a4y = t4y;
   17420           0 :                 t5x = -a5x*c3-a5y*c4;
   17421           0 :                 t5y = a5x*c4-a5y*c3;
   17422           0 :                 a5x = t5x;
   17423           0 :                 a5y = t5y;
   17424           0 :                 t1x = a1x+a2x;
   17425           0 :                 t1y = a1y+a2y;
   17426           0 :                 a0x = a0x+t1x;
   17427           0 :                 a0y = a0y+t1y;
   17428           0 :                 m1x = c1*t1x;
   17429           0 :                 m1y = c1*t1y;
   17430           0 :                 m2x = c2*(a1y-a2y);
   17431           0 :                 m2y = c2*(a2x-a1x);
   17432           0 :                 s1x = a0x+m1x;
   17433           0 :                 s1y = a0y+m1y;
   17434           0 :                 a1x = s1x+m2x;
   17435           0 :                 a1y = s1y+m2y;
   17436           0 :                 a2x = s1x-m2x;
   17437           0 :                 a2y = s1y-m2y;
   17438           0 :                 t1x = a4x+a5x;
   17439           0 :                 t1y = a4y+a5y;
   17440           0 :                 a3x = a3x+t1x;
   17441           0 :                 a3y = a3y+t1y;
   17442           0 :                 m1x = c1*t1x;
   17443           0 :                 m1y = c1*t1y;
   17444           0 :                 m2x = c2*(a4y-a5y);
   17445           0 :                 m2y = c2*(a5x-a4x);
   17446           0 :                 s1x = a3x+m1x;
   17447           0 :                 s1y = a3y+m1y;
   17448           0 :                 a4x = s1x+m2x;
   17449           0 :                 a4y = s1y+m2y;
   17450           0 :                 a5x = s1x-m2x;
   17451           0 :                 a5y = s1y-m2y;
   17452           0 :                 tw2x = twx*twx-twy*twy;
   17453           0 :                 tw2y = 2*twx*twy;
   17454           0 :                 tw3x = twx*tw2x-twy*tw2y;
   17455           0 :                 tw3y = twx*tw2y+twy*tw2x;
   17456           0 :                 tw4x = tw2x*tw2x-tw2y*tw2y;
   17457           0 :                 tw4y = 2*tw2x*tw2y;
   17458           0 :                 tw5x = tw3x*tw2x-tw3y*tw2y;
   17459           0 :                 tw5y = tw3x*tw2y+tw3y*tw2x;
   17460           0 :                 a->ptr.p_double[aoffset0+0] = a0x;
   17461           0 :                 a->ptr.p_double[aoffset0+1] = a0y;
   17462           0 :                 a->ptr.p_double[aoffset2+0] = a3x*twx-a3y*twy;
   17463           0 :                 a->ptr.p_double[aoffset2+1] = a3y*twx+a3x*twy;
   17464           0 :                 a->ptr.p_double[aoffset4+0] = a1x*tw2x-a1y*tw2y;
   17465           0 :                 a->ptr.p_double[aoffset4+1] = a1y*tw2x+a1x*tw2y;
   17466           0 :                 a->ptr.p_double[aoffset6+0] = a4x*tw3x-a4y*tw3y;
   17467           0 :                 a->ptr.p_double[aoffset6+1] = a4y*tw3x+a4x*tw3y;
   17468           0 :                 a->ptr.p_double[aoffset8+0] = a2x*tw4x-a2y*tw4y;
   17469           0 :                 a->ptr.p_double[aoffset8+1] = a2y*tw4x+a2x*tw4y;
   17470           0 :                 a->ptr.p_double[aoffset10+0] = a5x*tw5x-a5y*tw5y;
   17471           0 :                 a->ptr.p_double[aoffset10+1] = a5y*tw5x+a5x*tw5y;
   17472           0 :                 aoffset0 = aoffset0+2;
   17473           0 :                 aoffset2 = aoffset2+2;
   17474           0 :                 aoffset4 = aoffset4+2;
   17475           0 :                 aoffset6 = aoffset6+2;
   17476           0 :                 aoffset8 = aoffset8+2;
   17477           0 :                 aoffset10 = aoffset10+2;
   17478           0 :                 if( (mvidx+1)%ftbase_updatetw==0 )
   17479             :                 {
   17480           0 :                     v = -2*ae_pi*(mvidx+1)/(n*m);
   17481           0 :                     twxm1 = ae_sin(0.5*v, _state);
   17482           0 :                     twxm1 = -2*twxm1*twxm1;
   17483           0 :                     twy = ae_sin(v, _state);
   17484           0 :                     twx = twxm1+1;
   17485             :                 }
   17486             :                 else
   17487             :                 {
   17488           0 :                     v = twxm1+tw0+twxm1*tw0-twy*tw1;
   17489           0 :                     twy = twy+tw1+twxm1*tw1+twy*tw0;
   17490           0 :                     twxm1 = v;
   17491           0 :                     twx = v+1;
   17492             :                 }
   17493             :             }
   17494             :         }
   17495           0 :         return;
   17496             :     }
   17497             : }
   17498             : 
   17499             : 
   17500             : /*************************************************************************
   17501             : This subroutine precomputes data for complex Bluestein's  FFT  and  writes
   17502             : them to array PrecR[] at specified offset. It  is  responsibility  of  the
   17503             : caller to make sure that PrecR[] is large enough.
   17504             : 
   17505             : INPUT PARAMETERS:
   17506             :     N           -   original size of the transform
   17507             :     M           -   size of the "padded" Bluestein's transform
   17508             :     PrecR       -   preallocated array
   17509             :     Offs        -   offset
   17510             :     
   17511             : OUTPUT PARAMETERS:
   17512             :     PrecR       -   data at Offs:Offs+4*M-1 are modified:
   17513             :                     * PrecR[Offs:Offs+2*M-1] stores Z[k]=exp(i*pi*k^2/N)
   17514             :                     * PrecR[Offs+2*M:Offs+4*M-1] stores FFT of the Z
   17515             :                     Other parts of PrecR are unchanged.
   17516             :                     
   17517             : NOTE: this function performs internal M-point FFT. It allocates temporary
   17518             :       plan which is destroyed after leaving this function.
   17519             : 
   17520             :   -- ALGLIB --
   17521             :      Copyright 08.05.2013 by Bochkanov Sergey
   17522             : *************************************************************************/
   17523           0 : static void ftbase_ftprecomputebluesteinsfft(ae_int_t n,
   17524             :      ae_int_t m,
   17525             :      /* Real    */ ae_vector* precr,
   17526             :      ae_int_t offs,
   17527             :      ae_state *_state)
   17528             : {
   17529             :     ae_frame _frame_block;
   17530             :     ae_int_t i;
   17531             :     double bx;
   17532             :     double by;
   17533             :     fasttransformplan plan;
   17534             : 
   17535           0 :     ae_frame_make(_state, &_frame_block);
   17536           0 :     memset(&plan, 0, sizeof(plan));
   17537           0 :     _fasttransformplan_init(&plan, _state, ae_true);
   17538             : 
   17539             :     
   17540             :     /*
   17541             :      * Fill first half of PrecR with b[k] = exp(i*pi*k^2/N)
   17542             :      */
   17543           0 :     for(i=0; i<=2*m-1; i++)
   17544             :     {
   17545           0 :         precr->ptr.p_double[offs+i] = (double)(0);
   17546             :     }
   17547           0 :     for(i=0; i<=n-1; i++)
   17548             :     {
   17549           0 :         bx = ae_cos(ae_pi/n*i*i, _state);
   17550           0 :         by = ae_sin(ae_pi/n*i*i, _state);
   17551           0 :         precr->ptr.p_double[offs+2*i+0] = bx;
   17552           0 :         precr->ptr.p_double[offs+2*i+1] = by;
   17553           0 :         precr->ptr.p_double[offs+2*((m-i)%m)+0] = bx;
   17554           0 :         precr->ptr.p_double[offs+2*((m-i)%m)+1] = by;
   17555             :     }
   17556             :     
   17557             :     /*
   17558             :      * Precomputed FFT
   17559             :      */
   17560           0 :     ftcomplexfftplan(m, 1, &plan, _state);
   17561           0 :     for(i=0; i<=2*m-1; i++)
   17562             :     {
   17563           0 :         precr->ptr.p_double[offs+2*m+i] = precr->ptr.p_double[offs+i];
   17564             :     }
   17565           0 :     ftbase_ftapplysubplan(&plan, 0, precr, offs+2*m, 0, &plan.buffer, 1, _state);
   17566           0 :     ae_frame_leave(_state);
   17567           0 : }
   17568             : 
   17569             : 
   17570             : /*************************************************************************
   17571             : This subroutine applies complex Bluestein's FFT to input/output array A.
   17572             : 
   17573             : INPUT PARAMETERS:
   17574             :     Plan        -   transformation plan
   17575             :     A           -   array, must be large enough for plan to work
   17576             :     ABase       -   base offset in array A, this value points to start of
   17577             :                     subarray whose length is equal to length of the plan
   17578             :     AOffset     -   offset with respect to ABase, 0<=AOffset<PlanLength.
   17579             :                     This is an offset within large PlanLength-subarray of
   17580             :                     the chunk to process.
   17581             :     OperandsCnt -   number of repeated operands (length N each)
   17582             :     N           -   original data length (measured in complex numbers)
   17583             :     M           -   padded data length (measured in complex numbers)
   17584             :     PrecOffs    -   offset of the precomputed data for the plan
   17585             :     SubPlan     -   position of the length-M FFT subplan which is used by
   17586             :                     transformation
   17587             :     BufA        -   temporary buffer, at least 2*M elements
   17588             :     BufB        -   temporary buffer, at least 2*M elements
   17589             :     BufC        -   temporary buffer, at least 2*M elements
   17590             :     BufD        -   temporary buffer, at least 2*M elements
   17591             :     
   17592             : OUTPUT PARAMETERS:
   17593             :     A           -   transformed array
   17594             : 
   17595             :   -- ALGLIB --
   17596             :      Copyright 05.04.2013 by Bochkanov Sergey
   17597             : *************************************************************************/
   17598           0 : static void ftbase_ftbluesteinsfft(fasttransformplan* plan,
   17599             :      /* Real    */ ae_vector* a,
   17600             :      ae_int_t abase,
   17601             :      ae_int_t aoffset,
   17602             :      ae_int_t operandscnt,
   17603             :      ae_int_t n,
   17604             :      ae_int_t m,
   17605             :      ae_int_t precoffs,
   17606             :      ae_int_t subplan,
   17607             :      /* Real    */ ae_vector* bufa,
   17608             :      /* Real    */ ae_vector* bufb,
   17609             :      /* Real    */ ae_vector* bufc,
   17610             :      /* Real    */ ae_vector* bufd,
   17611             :      ae_state *_state)
   17612             : {
   17613             :     ae_int_t op;
   17614             :     ae_int_t i;
   17615             :     double x;
   17616             :     double y;
   17617             :     double bx;
   17618             :     double by;
   17619             :     double ax;
   17620             :     double ay;
   17621             :     double rx;
   17622             :     double ry;
   17623             :     ae_int_t p0;
   17624             :     ae_int_t p1;
   17625             :     ae_int_t p2;
   17626             : 
   17627             : 
   17628           0 :     for(op=0; op<=operandscnt-1; op++)
   17629             :     {
   17630             :         
   17631             :         /*
   17632             :          * Multiply A by conj(Z), store to buffer.
   17633             :          * Pad A by zeros.
   17634             :          *
   17635             :          * NOTE: Z[k]=exp(i*pi*k^2/N)
   17636             :          */
   17637           0 :         p0 = abase+aoffset+op*2*n;
   17638           0 :         p1 = precoffs;
   17639           0 :         for(i=0; i<=n-1; i++)
   17640             :         {
   17641           0 :             x = a->ptr.p_double[p0+0];
   17642           0 :             y = a->ptr.p_double[p0+1];
   17643           0 :             bx = plan->precr.ptr.p_double[p1+0];
   17644           0 :             by = -plan->precr.ptr.p_double[p1+1];
   17645           0 :             bufa->ptr.p_double[2*i+0] = x*bx-y*by;
   17646           0 :             bufa->ptr.p_double[2*i+1] = x*by+y*bx;
   17647           0 :             p0 = p0+2;
   17648           0 :             p1 = p1+2;
   17649             :         }
   17650           0 :         for(i=2*n; i<=2*m-1; i++)
   17651             :         {
   17652           0 :             bufa->ptr.p_double[i] = (double)(0);
   17653             :         }
   17654             :         
   17655             :         /*
   17656             :          * Perform convolution of A and Z (using precomputed
   17657             :          * FFT of Z stored in Plan structure).
   17658             :          */
   17659           0 :         ftbase_ftapplysubplan(plan, subplan, bufa, 0, 0, bufc, 1, _state);
   17660           0 :         p0 = 0;
   17661           0 :         p1 = precoffs+2*m;
   17662           0 :         for(i=0; i<=m-1; i++)
   17663             :         {
   17664           0 :             ax = bufa->ptr.p_double[p0+0];
   17665           0 :             ay = bufa->ptr.p_double[p0+1];
   17666           0 :             bx = plan->precr.ptr.p_double[p1+0];
   17667           0 :             by = plan->precr.ptr.p_double[p1+1];
   17668           0 :             bufa->ptr.p_double[p0+0] = ax*bx-ay*by;
   17669           0 :             bufa->ptr.p_double[p0+1] = -(ax*by+ay*bx);
   17670           0 :             p0 = p0+2;
   17671           0 :             p1 = p1+2;
   17672             :         }
   17673           0 :         ftbase_ftapplysubplan(plan, subplan, bufa, 0, 0, bufc, 1, _state);
   17674             :         
   17675             :         /*
   17676             :          * Post processing:
   17677             :          *     A:=conj(Z)*conj(A)/M
   17678             :          * Here conj(A)/M corresponds to last stage of inverse DFT,
   17679             :          * and conj(Z) comes from Bluestein's FFT algorithm.
   17680             :          */
   17681           0 :         p0 = precoffs;
   17682           0 :         p1 = 0;
   17683           0 :         p2 = abase+aoffset+op*2*n;
   17684           0 :         for(i=0; i<=n-1; i++)
   17685             :         {
   17686           0 :             bx = plan->precr.ptr.p_double[p0+0];
   17687           0 :             by = plan->precr.ptr.p_double[p0+1];
   17688           0 :             rx = bufa->ptr.p_double[p1+0]/m;
   17689           0 :             ry = -bufa->ptr.p_double[p1+1]/m;
   17690           0 :             a->ptr.p_double[p2+0] = rx*bx-ry*(-by);
   17691           0 :             a->ptr.p_double[p2+1] = rx*(-by)+ry*bx;
   17692           0 :             p0 = p0+2;
   17693           0 :             p1 = p1+2;
   17694           0 :             p2 = p2+2;
   17695             :         }
   17696             :     }
   17697           0 : }
   17698             : 
   17699             : 
   17700             : /*************************************************************************
   17701             : This subroutine precomputes data for complex Rader's FFT and  writes  them
   17702             : to array PrecR[] at specified offset. It  is  responsibility of the caller
   17703             : to make sure that PrecR[] is large enough.
   17704             : 
   17705             : INPUT PARAMETERS:
   17706             :     N           -   original size of the transform (before reduction to N-1)
   17707             :     RQ          -   primitive root modulo N
   17708             :     RIQ         -   inverse of primitive root modulo N
   17709             :     PrecR       -   preallocated array
   17710             :     Offs        -   offset
   17711             :     
   17712             : OUTPUT PARAMETERS:
   17713             :     PrecR       -   data at Offs:Offs+2*(N-1)-1 store FFT of Rader's factors,
   17714             :                     other parts of PrecR are unchanged.
   17715             :                     
   17716             : NOTE: this function performs internal (N-1)-point FFT. It allocates temporary
   17717             :       plan which is destroyed after leaving this function.
   17718             : 
   17719             :   -- ALGLIB --
   17720             :      Copyright 08.05.2013 by Bochkanov Sergey
   17721             : *************************************************************************/
   17722           0 : static void ftbase_ftprecomputeradersfft(ae_int_t n,
   17723             :      ae_int_t rq,
   17724             :      ae_int_t riq,
   17725             :      /* Real    */ ae_vector* precr,
   17726             :      ae_int_t offs,
   17727             :      ae_state *_state)
   17728             : {
   17729             :     ae_frame _frame_block;
   17730             :     ae_int_t q;
   17731             :     fasttransformplan plan;
   17732             :     ae_int_t kiq;
   17733             :     double v;
   17734             : 
   17735           0 :     ae_frame_make(_state, &_frame_block);
   17736           0 :     memset(&plan, 0, sizeof(plan));
   17737           0 :     _fasttransformplan_init(&plan, _state, ae_true);
   17738             : 
   17739             :     
   17740             :     /*
   17741             :      * Fill PrecR with Rader factors, perform FFT
   17742             :      */
   17743           0 :     kiq = 1;
   17744           0 :     for(q=0; q<=n-2; q++)
   17745             :     {
   17746           0 :         v = -2*ae_pi*kiq/n;
   17747           0 :         precr->ptr.p_double[offs+2*q+0] = ae_cos(v, _state);
   17748           0 :         precr->ptr.p_double[offs+2*q+1] = ae_sin(v, _state);
   17749           0 :         kiq = kiq*riq%n;
   17750             :     }
   17751           0 :     ftcomplexfftplan(n-1, 1, &plan, _state);
   17752           0 :     ftbase_ftapplysubplan(&plan, 0, precr, offs, 0, &plan.buffer, 1, _state);
   17753           0 :     ae_frame_leave(_state);
   17754           0 : }
   17755             : 
   17756             : 
   17757             : /*************************************************************************
   17758             : This subroutine applies complex Rader's FFT to input/output array A.
   17759             : 
   17760             : INPUT PARAMETERS:
   17761             :     A           -   array, must be large enough for plan to work
   17762             :     ABase       -   base offset in array A, this value points to start of
   17763             :                     subarray whose length is equal to length of the plan
   17764             :     AOffset     -   offset with respect to ABase, 0<=AOffset<PlanLength.
   17765             :                     This is an offset within large PlanLength-subarray of
   17766             :                     the chunk to process.
   17767             :     OperandsCnt -   number of repeated operands (length N each)
   17768             :     N           -   original data length (measured in complex numbers)
   17769             :     SubPlan     -   position of the (N-1)-point FFT subplan which is used
   17770             :                     by transformation
   17771             :     RQ          -   primitive root modulo N
   17772             :     RIQ         -   inverse of primitive root modulo N
   17773             :     PrecOffs    -   offset of the precomputed data for the plan
   17774             :     Buf         -   temporary array
   17775             :     
   17776             : OUTPUT PARAMETERS:
   17777             :     A           -   transformed array
   17778             : 
   17779             :   -- ALGLIB --
   17780             :      Copyright 05.04.2013 by Bochkanov Sergey
   17781             : *************************************************************************/
   17782           0 : static void ftbase_ftradersfft(fasttransformplan* plan,
   17783             :      /* Real    */ ae_vector* a,
   17784             :      ae_int_t abase,
   17785             :      ae_int_t aoffset,
   17786             :      ae_int_t operandscnt,
   17787             :      ae_int_t n,
   17788             :      ae_int_t subplan,
   17789             :      ae_int_t rq,
   17790             :      ae_int_t riq,
   17791             :      ae_int_t precoffs,
   17792             :      /* Real    */ ae_vector* buf,
   17793             :      ae_state *_state)
   17794             : {
   17795             :     ae_int_t opidx;
   17796             :     ae_int_t i;
   17797             :     ae_int_t q;
   17798             :     ae_int_t kq;
   17799             :     ae_int_t kiq;
   17800             :     double x0;
   17801             :     double y0;
   17802             :     ae_int_t p0;
   17803             :     ae_int_t p1;
   17804             :     double ax;
   17805             :     double ay;
   17806             :     double bx;
   17807             :     double by;
   17808             :     double rx;
   17809             :     double ry;
   17810             : 
   17811             : 
   17812           0 :     ae_assert(operandscnt>=1, "FTApplyComplexRefFFT: OperandsCnt<1", _state);
   17813             :     
   17814             :     /*
   17815             :      * Process operands
   17816             :      */
   17817           0 :     for(opidx=0; opidx<=operandscnt-1; opidx++)
   17818             :     {
   17819             :         
   17820             :         /*
   17821             :          * fill QA
   17822             :          */
   17823           0 :         kq = 1;
   17824           0 :         p0 = abase+aoffset+opidx*n*2;
   17825           0 :         p1 = aoffset+opidx*n*2;
   17826           0 :         rx = a->ptr.p_double[p0+0];
   17827           0 :         ry = a->ptr.p_double[p0+1];
   17828           0 :         x0 = rx;
   17829           0 :         y0 = ry;
   17830           0 :         for(q=0; q<=n-2; q++)
   17831             :         {
   17832           0 :             ax = a->ptr.p_double[p0+2*kq+0];
   17833           0 :             ay = a->ptr.p_double[p0+2*kq+1];
   17834           0 :             buf->ptr.p_double[p1+0] = ax;
   17835           0 :             buf->ptr.p_double[p1+1] = ay;
   17836           0 :             rx = rx+ax;
   17837           0 :             ry = ry+ay;
   17838           0 :             kq = kq*rq%n;
   17839           0 :             p1 = p1+2;
   17840             :         }
   17841           0 :         p0 = abase+aoffset+opidx*n*2;
   17842           0 :         p1 = aoffset+opidx*n*2;
   17843           0 :         for(q=0; q<=n-2; q++)
   17844             :         {
   17845           0 :             a->ptr.p_double[p0] = buf->ptr.p_double[p1];
   17846           0 :             a->ptr.p_double[p0+1] = buf->ptr.p_double[p1+1];
   17847           0 :             p0 = p0+2;
   17848           0 :             p1 = p1+2;
   17849             :         }
   17850             :         
   17851             :         /*
   17852             :          * Convolution
   17853             :          */
   17854           0 :         ftbase_ftapplysubplan(plan, subplan, a, abase, aoffset+opidx*n*2, buf, 1, _state);
   17855           0 :         p0 = abase+aoffset+opidx*n*2;
   17856           0 :         p1 = precoffs;
   17857           0 :         for(i=0; i<=n-2; i++)
   17858             :         {
   17859           0 :             ax = a->ptr.p_double[p0+0];
   17860           0 :             ay = a->ptr.p_double[p0+1];
   17861           0 :             bx = plan->precr.ptr.p_double[p1+0];
   17862           0 :             by = plan->precr.ptr.p_double[p1+1];
   17863           0 :             a->ptr.p_double[p0+0] = ax*bx-ay*by;
   17864           0 :             a->ptr.p_double[p0+1] = -(ax*by+ay*bx);
   17865           0 :             p0 = p0+2;
   17866           0 :             p1 = p1+2;
   17867             :         }
   17868           0 :         ftbase_ftapplysubplan(plan, subplan, a, abase, aoffset+opidx*n*2, buf, 1, _state);
   17869           0 :         p0 = abase+aoffset+opidx*n*2;
   17870           0 :         for(i=0; i<=n-2; i++)
   17871             :         {
   17872           0 :             a->ptr.p_double[p0+0] = a->ptr.p_double[p0+0]/(n-1);
   17873           0 :             a->ptr.p_double[p0+1] = -a->ptr.p_double[p0+1]/(n-1);
   17874           0 :             p0 = p0+2;
   17875             :         }
   17876             :         
   17877             :         /*
   17878             :          * Result
   17879             :          */
   17880           0 :         buf->ptr.p_double[aoffset+opidx*n*2+0] = rx;
   17881           0 :         buf->ptr.p_double[aoffset+opidx*n*2+1] = ry;
   17882           0 :         kiq = 1;
   17883           0 :         p0 = aoffset+opidx*n*2;
   17884           0 :         p1 = abase+aoffset+opidx*n*2;
   17885           0 :         for(q=0; q<=n-2; q++)
   17886             :         {
   17887           0 :             buf->ptr.p_double[p0+2*kiq+0] = x0+a->ptr.p_double[p1+0];
   17888           0 :             buf->ptr.p_double[p0+2*kiq+1] = y0+a->ptr.p_double[p1+1];
   17889           0 :             kiq = kiq*riq%n;
   17890           0 :             p1 = p1+2;
   17891             :         }
   17892           0 :         p0 = abase+aoffset+opidx*n*2;
   17893           0 :         p1 = aoffset+opidx*n*2;
   17894           0 :         for(q=0; q<=n-1; q++)
   17895             :         {
   17896           0 :             a->ptr.p_double[p0] = buf->ptr.p_double[p1];
   17897           0 :             a->ptr.p_double[p0+1] = buf->ptr.p_double[p1+1];
   17898           0 :             p0 = p0+2;
   17899           0 :             p1 = p1+2;
   17900             :         }
   17901             :     }
   17902           0 : }
   17903             : 
   17904             : 
   17905             : /*************************************************************************
   17906             : Factorizes task size N into product of two smaller sizes N1 and N2
   17907             : 
   17908             : INPUT PARAMETERS:
   17909             :     N       -   task size, N>0
   17910             :     IsRoot  -   whether taks is root task (first one in a sequence)
   17911             :     
   17912             : OUTPUT PARAMETERS:
   17913             :     N1, N2  -   such numbers that:
   17914             :                 * for prime N:                  N1=N2=0
   17915             :                 * for composite N<=MaxRadix:    N1=N2=0
   17916             :                 * for composite N>MaxRadix:     1<=N1<=N2, N1*N2=N
   17917             : 
   17918             :   -- ALGLIB --
   17919             :      Copyright 08.04.2013 by Bochkanov Sergey
   17920             : *************************************************************************/
   17921           0 : static void ftbase_ftfactorize(ae_int_t n,
   17922             :      ae_bool isroot,
   17923             :      ae_int_t* n1,
   17924             :      ae_int_t* n2,
   17925             :      ae_state *_state)
   17926             : {
   17927             :     ae_int_t j;
   17928             :     ae_int_t k;
   17929             : 
   17930           0 :     *n1 = 0;
   17931           0 :     *n2 = 0;
   17932             : 
   17933           0 :     ae_assert(n>0, "FTFactorize: N<=0", _state);
   17934           0 :     *n1 = 0;
   17935           0 :     *n2 = 0;
   17936             :     
   17937             :     /*
   17938             :      * Small N
   17939             :      */
   17940           0 :     if( n<=ftbase_maxradix )
   17941             :     {
   17942           0 :         return;
   17943             :     }
   17944             :     
   17945             :     /*
   17946             :      * Large N, recursive split
   17947             :      */
   17948           0 :     if( n>ftbase_recursivethreshold )
   17949             :     {
   17950           0 :         k = ae_iceil(ae_sqrt((double)(n), _state), _state)+1;
   17951           0 :         ae_assert(k*k>=n, "FTFactorize: internal error during recursive factorization", _state);
   17952           0 :         for(j=k; j>=2; j--)
   17953             :         {
   17954           0 :             if( n%j==0 )
   17955             :             {
   17956           0 :                 *n1 = ae_minint(n/j, j, _state);
   17957           0 :                 *n2 = ae_maxint(n/j, j, _state);
   17958           0 :                 return;
   17959             :             }
   17960             :         }
   17961             :     }
   17962             :     
   17963             :     /*
   17964             :      * N>MaxRadix, try to find good codelet
   17965             :      */
   17966           0 :     for(j=ftbase_maxradix; j>=2; j--)
   17967             :     {
   17968           0 :         if( n%j==0 )
   17969             :         {
   17970           0 :             *n1 = j;
   17971           0 :             *n2 = n/j;
   17972           0 :             break;
   17973             :         }
   17974             :     }
   17975             :     
   17976             :     /*
   17977             :      * In case no good codelet was found,
   17978             :      * try to factorize N into product of ANY primes.
   17979             :      */
   17980           0 :     if( *n1*(*n2)!=n )
   17981             :     {
   17982           0 :         for(j=2; j<=n-1; j++)
   17983             :         {
   17984           0 :             if( n%j==0 )
   17985             :             {
   17986           0 :                 *n1 = j;
   17987           0 :                 *n2 = n/j;
   17988           0 :                 break;
   17989             :             }
   17990           0 :             if( j*j>n )
   17991             :             {
   17992           0 :                 break;
   17993             :             }
   17994             :         }
   17995             :     }
   17996             :     
   17997             :     /*
   17998             :      * normalize
   17999             :      */
   18000           0 :     if( *n1>(*n2) )
   18001             :     {
   18002           0 :         j = *n1;
   18003           0 :         *n1 = *n2;
   18004           0 :         *n2 = j;
   18005             :     }
   18006             : }
   18007             : 
   18008             : 
   18009             : /*************************************************************************
   18010             : Returns optimistic estimate of the FFT cost, in UNITs (1 UNIT = 100 KFLOPs)
   18011             : 
   18012             : INPUT PARAMETERS:
   18013             :     N       -   task size, N>0
   18014             :     
   18015             : RESULU:
   18016             :     cost in UNITs, rounded down to nearest integer
   18017             : 
   18018             : NOTE: If FFT cost is less than 1 UNIT, it will return 0 as result.
   18019             : 
   18020             :   -- ALGLIB --
   18021             :      Copyright 08.04.2013 by Bochkanov Sergey
   18022             : *************************************************************************/
   18023           0 : static ae_int_t ftbase_ftoptimisticestimate(ae_int_t n, ae_state *_state)
   18024             : {
   18025             :     ae_int_t result;
   18026             : 
   18027             : 
   18028           0 :     ae_assert(n>0, "FTOptimisticEstimate: N<=0", _state);
   18029           0 :     result = ae_ifloor(1.0E-5*5*n*ae_log((double)(n), _state)/ae_log((double)(2), _state), _state);
   18030           0 :     return result;
   18031             : }
   18032             : 
   18033             : 
   18034             : /*************************************************************************
   18035             : Twiddle factors calculation
   18036             : 
   18037             :   -- ALGLIB --
   18038             :      Copyright 01.05.2009 by Bochkanov Sergey
   18039             : *************************************************************************/
   18040           0 : static void ftbase_ffttwcalc(/* Real    */ ae_vector* a,
   18041             :      ae_int_t aoffset,
   18042             :      ae_int_t n1,
   18043             :      ae_int_t n2,
   18044             :      ae_state *_state)
   18045             : {
   18046             :     ae_int_t i;
   18047             :     ae_int_t j2;
   18048             :     ae_int_t n;
   18049             :     ae_int_t halfn1;
   18050             :     ae_int_t offs;
   18051             :     double x;
   18052             :     double y;
   18053             :     double twxm1;
   18054             :     double twy;
   18055             :     double twbasexm1;
   18056             :     double twbasey;
   18057             :     double twrowxm1;
   18058             :     double twrowy;
   18059             :     double tmpx;
   18060             :     double tmpy;
   18061             :     double v;
   18062             :     ae_int_t updatetw2;
   18063             : 
   18064             : 
   18065             :     
   18066             :     /*
   18067             :      * Multiplication by twiddle factors for complex Cooley-Tukey FFT
   18068             :      * with N factorized as N1*N2.
   18069             :      *
   18070             :      * Naive solution to this problem is given below:
   18071             :      *
   18072             :      *     > for K:=1 to N2-1 do
   18073             :      *     >     for J:=1 to N1-1 do
   18074             :      *     >     begin
   18075             :      *     >         Idx:=K*N1+J;
   18076             :      *     >         X:=A[AOffset+2*Idx+0];
   18077             :      *     >         Y:=A[AOffset+2*Idx+1];
   18078             :      *     >         TwX:=Cos(-2*Pi()*K*J/(N1*N2));
   18079             :      *     >         TwY:=Sin(-2*Pi()*K*J/(N1*N2));
   18080             :      *     >         A[AOffset+2*Idx+0]:=X*TwX-Y*TwY;
   18081             :      *     >         A[AOffset+2*Idx+1]:=X*TwY+Y*TwX;
   18082             :      *     >     end;
   18083             :      *
   18084             :      * However, there are exist more efficient solutions.
   18085             :      *
   18086             :      * Each pass of the inner cycle corresponds to multiplication of one
   18087             :      * entry of A by W[k,j]=exp(-I*2*pi*k*j/N). This factor can be rewritten
   18088             :      * as exp(-I*2*pi*k/N)^j. So we can replace costly exponentiation by
   18089             :      * repeated multiplication: W[k,j+1]=W[k,j]*exp(-I*2*pi*k/N), with
   18090             :      * second factor being computed once in the beginning of the iteration.
   18091             :      *
   18092             :      * Also, exp(-I*2*pi*k/N) can be represented as exp(-I*2*pi/N)^k, i.e.
   18093             :      * we have W[K+1,1]=W[K,1]*W[1,1].
   18094             :      *
   18095             :      * In our loop we use following variables:
   18096             :      * * [TwBaseXM1,TwBaseY] =   [cos(2*pi/N)-1,     sin(2*pi/N)]
   18097             :      * * [TwRowXM1, TwRowY]  =   [cos(2*pi*I/N)-1,   sin(2*pi*I/N)]
   18098             :      * * [TwXM1,    TwY]     =   [cos(2*pi*I*J/N)-1, sin(2*pi*I*J/N)]
   18099             :      *
   18100             :      * Meaning of the variables:
   18101             :      * * [TwXM1,TwY] is current twiddle factor W[I,J]
   18102             :      * * [TwRowXM1, TwRowY] is W[I,1]
   18103             :      * * [TwBaseXM1,TwBaseY] is W[1,1]
   18104             :      *
   18105             :      * During inner loop we multiply current twiddle factor by W[I,1],
   18106             :      * during outer loop we update W[I,1].
   18107             :      *
   18108             :      */
   18109           0 :     ae_assert(ftbase_updatetw>=2, "FFTTwCalc: internal error - UpdateTw<2", _state);
   18110           0 :     updatetw2 = ftbase_updatetw/2;
   18111           0 :     halfn1 = n1/2;
   18112           0 :     n = n1*n2;
   18113           0 :     v = -2*ae_pi/n;
   18114           0 :     twbasexm1 = -2*ae_sqr(ae_sin(0.5*v, _state), _state);
   18115           0 :     twbasey = ae_sin(v, _state);
   18116           0 :     twrowxm1 = (double)(0);
   18117           0 :     twrowy = (double)(0);
   18118           0 :     offs = aoffset;
   18119           0 :     for(i=0; i<=n2-1; i++)
   18120             :     {
   18121             :         
   18122             :         /*
   18123             :          * Initialize twiddle factor for current row
   18124             :          */
   18125           0 :         twxm1 = (double)(0);
   18126           0 :         twy = (double)(0);
   18127             :         
   18128             :         /*
   18129             :          * N1-point block is separated into 2-point chunks and residual 1-point chunk
   18130             :          * (in case N1 is odd). Unrolled loop is several times faster.
   18131             :          */
   18132           0 :         for(j2=0; j2<=halfn1-1; j2++)
   18133             :         {
   18134             :             
   18135             :             /*
   18136             :              * Processing:
   18137             :              * * process first element in a chunk.
   18138             :              * * update twiddle factor (unconditional update)
   18139             :              * * process second element
   18140             :              * * conditional update of the twiddle factor
   18141             :              */
   18142           0 :             x = a->ptr.p_double[offs+0];
   18143           0 :             y = a->ptr.p_double[offs+1];
   18144           0 :             tmpx = x*(1+twxm1)-y*twy;
   18145           0 :             tmpy = x*twy+y*(1+twxm1);
   18146           0 :             a->ptr.p_double[offs+0] = tmpx;
   18147           0 :             a->ptr.p_double[offs+1] = tmpy;
   18148           0 :             tmpx = (1+twxm1)*twrowxm1-twy*twrowy;
   18149           0 :             twy = twy+(1+twxm1)*twrowy+twy*twrowxm1;
   18150           0 :             twxm1 = twxm1+tmpx;
   18151           0 :             x = a->ptr.p_double[offs+2];
   18152           0 :             y = a->ptr.p_double[offs+3];
   18153           0 :             tmpx = x*(1+twxm1)-y*twy;
   18154           0 :             tmpy = x*twy+y*(1+twxm1);
   18155           0 :             a->ptr.p_double[offs+2] = tmpx;
   18156           0 :             a->ptr.p_double[offs+3] = tmpy;
   18157           0 :             offs = offs+4;
   18158           0 :             if( (j2+1)%updatetw2==0&&j2<halfn1-1 )
   18159             :             {
   18160             :                 
   18161             :                 /*
   18162             :                  * Recalculate twiddle factor
   18163             :                  */
   18164           0 :                 v = -2*ae_pi*i*2*(j2+1)/n;
   18165           0 :                 twxm1 = ae_sin(0.5*v, _state);
   18166           0 :                 twxm1 = -2*twxm1*twxm1;
   18167           0 :                 twy = ae_sin(v, _state);
   18168             :             }
   18169             :             else
   18170             :             {
   18171             :                 
   18172             :                 /*
   18173             :                  * Update twiddle factor
   18174             :                  */
   18175           0 :                 tmpx = (1+twxm1)*twrowxm1-twy*twrowy;
   18176           0 :                 twy = twy+(1+twxm1)*twrowy+twy*twrowxm1;
   18177           0 :                 twxm1 = twxm1+tmpx;
   18178             :             }
   18179             :         }
   18180           0 :         if( n1%2==1 )
   18181             :         {
   18182             :             
   18183             :             /*
   18184             :              * Handle residual chunk
   18185             :              */
   18186           0 :             x = a->ptr.p_double[offs+0];
   18187           0 :             y = a->ptr.p_double[offs+1];
   18188           0 :             tmpx = x*(1+twxm1)-y*twy;
   18189           0 :             tmpy = x*twy+y*(1+twxm1);
   18190           0 :             a->ptr.p_double[offs+0] = tmpx;
   18191           0 :             a->ptr.p_double[offs+1] = tmpy;
   18192           0 :             offs = offs+2;
   18193             :         }
   18194             :         
   18195             :         /*
   18196             :          * update TwRow: TwRow(new) = TwRow(old)*TwBase
   18197             :          */
   18198           0 :         if( i<n2-1 )
   18199             :         {
   18200           0 :             if( (i+1)%ftbase_updatetw==0 )
   18201             :             {
   18202           0 :                 v = -2*ae_pi*(i+1)/n;
   18203           0 :                 twrowxm1 = ae_sin(0.5*v, _state);
   18204           0 :                 twrowxm1 = -2*twrowxm1*twrowxm1;
   18205           0 :                 twrowy = ae_sin(v, _state);
   18206             :             }
   18207             :             else
   18208             :             {
   18209           0 :                 tmpx = twbasexm1+twrowxm1*twbasexm1-twrowy*twbasey;
   18210           0 :                 tmpy = twbasey+twrowxm1*twbasey+twrowy*twbasexm1;
   18211           0 :                 twrowxm1 = twrowxm1+tmpx;
   18212           0 :                 twrowy = twrowy+tmpy;
   18213             :             }
   18214             :         }
   18215             :     }
   18216           0 : }
   18217             : 
   18218             : 
   18219             : /*************************************************************************
   18220             : Linear transpose: transpose complex matrix stored in 1-dimensional array
   18221             : 
   18222             :   -- ALGLIB --
   18223             :      Copyright 01.05.2009 by Bochkanov Sergey
   18224             : *************************************************************************/
   18225           0 : static void ftbase_internalcomplexlintranspose(/* Real    */ ae_vector* a,
   18226             :      ae_int_t m,
   18227             :      ae_int_t n,
   18228             :      ae_int_t astart,
   18229             :      /* Real    */ ae_vector* buf,
   18230             :      ae_state *_state)
   18231             : {
   18232             : 
   18233             : 
   18234           0 :     ftbase_ffticltrec(a, astart, n, buf, 0, m, m, n, _state);
   18235           0 :     ae_v_move(&a->ptr.p_double[astart], 1, &buf->ptr.p_double[0], 1, ae_v_len(astart,astart+2*m*n-1));
   18236           0 : }
   18237             : 
   18238             : 
   18239             : /*************************************************************************
   18240             : Recurrent subroutine for a InternalComplexLinTranspose
   18241             : 
   18242             : Write A^T to B, where:
   18243             : * A is m*n complex matrix stored in array A as pairs of real/image values,
   18244             :   beginning from AStart position, with AStride stride
   18245             : * B is n*m complex matrix stored in array B as pairs of real/image values,
   18246             :   beginning from BStart position, with BStride stride
   18247             : stride is measured in complex numbers, i.e. in real/image pairs.
   18248             : 
   18249             :   -- ALGLIB --
   18250             :      Copyright 01.05.2009 by Bochkanov Sergey
   18251             : *************************************************************************/
   18252           0 : static void ftbase_ffticltrec(/* Real    */ ae_vector* a,
   18253             :      ae_int_t astart,
   18254             :      ae_int_t astride,
   18255             :      /* Real    */ ae_vector* b,
   18256             :      ae_int_t bstart,
   18257             :      ae_int_t bstride,
   18258             :      ae_int_t m,
   18259             :      ae_int_t n,
   18260             :      ae_state *_state)
   18261             : {
   18262             :     ae_int_t i;
   18263             :     ae_int_t j;
   18264             :     ae_int_t idx1;
   18265             :     ae_int_t idx2;
   18266             :     ae_int_t m2;
   18267             :     ae_int_t m1;
   18268             :     ae_int_t n1;
   18269             : 
   18270             : 
   18271           0 :     if( m==0||n==0 )
   18272             :     {
   18273           0 :         return;
   18274             :     }
   18275           0 :     if( ae_maxint(m, n, _state)<=8 )
   18276             :     {
   18277           0 :         m2 = 2*bstride;
   18278           0 :         for(i=0; i<=m-1; i++)
   18279             :         {
   18280           0 :             idx1 = bstart+2*i;
   18281           0 :             idx2 = astart+2*i*astride;
   18282           0 :             for(j=0; j<=n-1; j++)
   18283             :             {
   18284           0 :                 b->ptr.p_double[idx1+0] = a->ptr.p_double[idx2+0];
   18285           0 :                 b->ptr.p_double[idx1+1] = a->ptr.p_double[idx2+1];
   18286           0 :                 idx1 = idx1+m2;
   18287           0 :                 idx2 = idx2+2;
   18288             :             }
   18289             :         }
   18290           0 :         return;
   18291             :     }
   18292           0 :     if( n>m )
   18293             :     {
   18294             :         
   18295             :         /*
   18296             :          * New partition:
   18297             :          *
   18298             :          * "A^T -> B" becomes "(A1 A2)^T -> ( B1 )
   18299             :          *                                  ( B2 )
   18300             :          */
   18301           0 :         n1 = n/2;
   18302           0 :         if( n-n1>=8&&n1%8!=0 )
   18303             :         {
   18304           0 :             n1 = n1+(8-n1%8);
   18305             :         }
   18306           0 :         ae_assert(n-n1>0, "Assertion failed", _state);
   18307           0 :         ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m, n1, _state);
   18308           0 :         ftbase_ffticltrec(a, astart+2*n1, astride, b, bstart+2*n1*bstride, bstride, m, n-n1, _state);
   18309             :     }
   18310             :     else
   18311             :     {
   18312             :         
   18313             :         /*
   18314             :          * New partition:
   18315             :          *
   18316             :          * "A^T -> B" becomes "( A1 )^T -> ( B1 B2 )
   18317             :          *                     ( A2 )
   18318             :          */
   18319           0 :         m1 = m/2;
   18320           0 :         if( m-m1>=8&&m1%8!=0 )
   18321             :         {
   18322           0 :             m1 = m1+(8-m1%8);
   18323             :         }
   18324           0 :         ae_assert(m-m1>0, "Assertion failed", _state);
   18325           0 :         ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m1, n, _state);
   18326           0 :         ftbase_ffticltrec(a, astart+2*m1*astride, astride, b, bstart+2*m1, bstride, m-m1, n, _state);
   18327             :     }
   18328             : }
   18329             : 
   18330             : 
   18331             : /*************************************************************************
   18332             : Recurrent subroutine for a InternalRealLinTranspose
   18333             : 
   18334             : 
   18335             :   -- ALGLIB --
   18336             :      Copyright 01.05.2009 by Bochkanov Sergey
   18337             : *************************************************************************/
   18338           0 : static void ftbase_fftirltrec(/* Real    */ ae_vector* a,
   18339             :      ae_int_t astart,
   18340             :      ae_int_t astride,
   18341             :      /* Real    */ ae_vector* b,
   18342             :      ae_int_t bstart,
   18343             :      ae_int_t bstride,
   18344             :      ae_int_t m,
   18345             :      ae_int_t n,
   18346             :      ae_state *_state)
   18347             : {
   18348             :     ae_int_t i;
   18349             :     ae_int_t j;
   18350             :     ae_int_t idx1;
   18351             :     ae_int_t idx2;
   18352             :     ae_int_t m1;
   18353             :     ae_int_t n1;
   18354             : 
   18355             : 
   18356           0 :     if( m==0||n==0 )
   18357             :     {
   18358           0 :         return;
   18359             :     }
   18360           0 :     if( ae_maxint(m, n, _state)<=8 )
   18361             :     {
   18362           0 :         for(i=0; i<=m-1; i++)
   18363             :         {
   18364           0 :             idx1 = bstart+i;
   18365           0 :             idx2 = astart+i*astride;
   18366           0 :             for(j=0; j<=n-1; j++)
   18367             :             {
   18368           0 :                 b->ptr.p_double[idx1] = a->ptr.p_double[idx2];
   18369           0 :                 idx1 = idx1+bstride;
   18370           0 :                 idx2 = idx2+1;
   18371             :             }
   18372             :         }
   18373           0 :         return;
   18374             :     }
   18375           0 :     if( n>m )
   18376             :     {
   18377             :         
   18378             :         /*
   18379             :          * New partition:
   18380             :          *
   18381             :          * "A^T -> B" becomes "(A1 A2)^T -> ( B1 )
   18382             :          *                                  ( B2 )
   18383             :          */
   18384           0 :         n1 = n/2;
   18385           0 :         if( n-n1>=8&&n1%8!=0 )
   18386             :         {
   18387           0 :             n1 = n1+(8-n1%8);
   18388             :         }
   18389           0 :         ae_assert(n-n1>0, "Assertion failed", _state);
   18390           0 :         ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m, n1, _state);
   18391           0 :         ftbase_fftirltrec(a, astart+n1, astride, b, bstart+n1*bstride, bstride, m, n-n1, _state);
   18392             :     }
   18393             :     else
   18394             :     {
   18395             :         
   18396             :         /*
   18397             :          * New partition:
   18398             :          *
   18399             :          * "A^T -> B" becomes "( A1 )^T -> ( B1 B2 )
   18400             :          *                     ( A2 )
   18401             :          */
   18402           0 :         m1 = m/2;
   18403           0 :         if( m-m1>=8&&m1%8!=0 )
   18404             :         {
   18405           0 :             m1 = m1+(8-m1%8);
   18406             :         }
   18407           0 :         ae_assert(m-m1>0, "Assertion failed", _state);
   18408           0 :         ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m1, n, _state);
   18409           0 :         ftbase_fftirltrec(a, astart+m1*astride, astride, b, bstart+m1, bstride, m-m1, n, _state);
   18410             :     }
   18411             : }
   18412             : 
   18413             : 
   18414             : /*************************************************************************
   18415             : recurrent subroutine for FFTFindSmoothRec
   18416             : 
   18417             :   -- ALGLIB --
   18418             :      Copyright 01.05.2009 by Bochkanov Sergey
   18419             : *************************************************************************/
   18420           0 : static void ftbase_ftbasefindsmoothrec(ae_int_t n,
   18421             :      ae_int_t seed,
   18422             :      ae_int_t leastfactor,
   18423             :      ae_int_t* best,
   18424             :      ae_state *_state)
   18425             : {
   18426             : 
   18427             : 
   18428           0 :     ae_assert(ftbase_ftbasemaxsmoothfactor<=5, "FTBaseFindSmoothRec: internal error!", _state);
   18429           0 :     if( seed>=n )
   18430             :     {
   18431           0 :         *best = ae_minint(*best, seed, _state);
   18432           0 :         return;
   18433             :     }
   18434           0 :     if( leastfactor<=2 )
   18435             :     {
   18436           0 :         ftbase_ftbasefindsmoothrec(n, seed*2, 2, best, _state);
   18437             :     }
   18438           0 :     if( leastfactor<=3 )
   18439             :     {
   18440           0 :         ftbase_ftbasefindsmoothrec(n, seed*3, 3, best, _state);
   18441             :     }
   18442           0 :     if( leastfactor<=5 )
   18443             :     {
   18444           0 :         ftbase_ftbasefindsmoothrec(n, seed*5, 5, best, _state);
   18445             :     }
   18446             : }
   18447             : 
   18448             : 
   18449           0 : void _fasttransformplan_init(void* _p, ae_state *_state, ae_bool make_automatic)
   18450             : {
   18451           0 :     fasttransformplan *p = (fasttransformplan*)_p;
   18452           0 :     ae_touch_ptr((void*)p);
   18453           0 :     ae_matrix_init(&p->entries, 0, 0, DT_INT, _state, make_automatic);
   18454           0 :     ae_vector_init(&p->buffer, 0, DT_REAL, _state, make_automatic);
   18455           0 :     ae_vector_init(&p->precr, 0, DT_REAL, _state, make_automatic);
   18456           0 :     ae_vector_init(&p->preci, 0, DT_REAL, _state, make_automatic);
   18457           0 :     ae_shared_pool_init(&p->bluesteinpool, _state, make_automatic);
   18458           0 : }
   18459             : 
   18460             : 
   18461           0 : void _fasttransformplan_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
   18462             : {
   18463           0 :     fasttransformplan *dst = (fasttransformplan*)_dst;
   18464           0 :     fasttransformplan *src = (fasttransformplan*)_src;
   18465           0 :     ae_matrix_init_copy(&dst->entries, &src->entries, _state, make_automatic);
   18466           0 :     ae_vector_init_copy(&dst->buffer, &src->buffer, _state, make_automatic);
   18467           0 :     ae_vector_init_copy(&dst->precr, &src->precr, _state, make_automatic);
   18468           0 :     ae_vector_init_copy(&dst->preci, &src->preci, _state, make_automatic);
   18469           0 :     ae_shared_pool_init_copy(&dst->bluesteinpool, &src->bluesteinpool, _state, make_automatic);
   18470           0 : }
   18471             : 
   18472             : 
   18473           0 : void _fasttransformplan_clear(void* _p)
   18474             : {
   18475           0 :     fasttransformplan *p = (fasttransformplan*)_p;
   18476           0 :     ae_touch_ptr((void*)p);
   18477           0 :     ae_matrix_clear(&p->entries);
   18478           0 :     ae_vector_clear(&p->buffer);
   18479           0 :     ae_vector_clear(&p->precr);
   18480           0 :     ae_vector_clear(&p->preci);
   18481           0 :     ae_shared_pool_clear(&p->bluesteinpool);
   18482           0 : }
   18483             : 
   18484             : 
   18485           0 : void _fasttransformplan_destroy(void* _p)
   18486             : {
   18487           0 :     fasttransformplan *p = (fasttransformplan*)_p;
   18488           0 :     ae_touch_ptr((void*)p);
   18489           0 :     ae_matrix_destroy(&p->entries);
   18490           0 :     ae_vector_destroy(&p->buffer);
   18491           0 :     ae_vector_destroy(&p->precr);
   18492           0 :     ae_vector_destroy(&p->preci);
   18493           0 :     ae_shared_pool_destroy(&p->bluesteinpool);
   18494           0 : }
   18495             : 
   18496             : 
   18497             : #endif
   18498             : #if defined(AE_COMPILE_NEARUNITYUNIT) || !defined(AE_PARTIAL_BUILD)
   18499             : 
   18500             : 
   18501           0 : double nulog1p(double x, ae_state *_state)
   18502             : {
   18503             :     double z;
   18504             :     double lp;
   18505             :     double lq;
   18506             :     double result;
   18507             : 
   18508             : 
   18509           0 :     z = 1.0+x;
   18510           0 :     if( ae_fp_less(z,0.70710678118654752440)||ae_fp_greater(z,1.41421356237309504880) )
   18511             :     {
   18512           0 :         result = ae_log(z, _state);
   18513           0 :         return result;
   18514             :     }
   18515           0 :     z = x*x;
   18516           0 :     lp = 4.5270000862445199635215E-5;
   18517           0 :     lp = lp*x+4.9854102823193375972212E-1;
   18518           0 :     lp = lp*x+6.5787325942061044846969E0;
   18519           0 :     lp = lp*x+2.9911919328553073277375E1;
   18520           0 :     lp = lp*x+6.0949667980987787057556E1;
   18521           0 :     lp = lp*x+5.7112963590585538103336E1;
   18522           0 :     lp = lp*x+2.0039553499201281259648E1;
   18523           0 :     lq = 1.0000000000000000000000E0;
   18524           0 :     lq = lq*x+1.5062909083469192043167E1;
   18525           0 :     lq = lq*x+8.3047565967967209469434E1;
   18526           0 :     lq = lq*x+2.2176239823732856465394E2;
   18527           0 :     lq = lq*x+3.0909872225312059774938E2;
   18528           0 :     lq = lq*x+2.1642788614495947685003E2;
   18529           0 :     lq = lq*x+6.0118660497603843919306E1;
   18530           0 :     z = -0.5*z+x*(z*lp/lq);
   18531           0 :     result = x+z;
   18532           0 :     return result;
   18533             : }
   18534             : 
   18535             : 
   18536           0 : double nuexpm1(double x, ae_state *_state)
   18537             : {
   18538             :     double r;
   18539             :     double xx;
   18540             :     double ep;
   18541             :     double eq;
   18542             :     double result;
   18543             : 
   18544             : 
   18545           0 :     if( ae_fp_less(x,-0.5)||ae_fp_greater(x,0.5) )
   18546             :     {
   18547           0 :         result = ae_exp(x, _state)-1.0;
   18548           0 :         return result;
   18549             :     }
   18550           0 :     xx = x*x;
   18551           0 :     ep = 1.2617719307481059087798E-4;
   18552           0 :     ep = ep*xx+3.0299440770744196129956E-2;
   18553           0 :     ep = ep*xx+9.9999999999999999991025E-1;
   18554           0 :     eq = 3.0019850513866445504159E-6;
   18555           0 :     eq = eq*xx+2.5244834034968410419224E-3;
   18556           0 :     eq = eq*xx+2.2726554820815502876593E-1;
   18557           0 :     eq = eq*xx+2.0000000000000000000897E0;
   18558           0 :     r = x*ep;
   18559           0 :     r = r/(eq-r);
   18560           0 :     result = r+r;
   18561           0 :     return result;
   18562             : }
   18563             : 
   18564             : 
   18565           0 : double nucosm1(double x, ae_state *_state)
   18566             : {
   18567             :     double xx;
   18568             :     double c;
   18569             :     double result;
   18570             : 
   18571             : 
   18572           0 :     if( ae_fp_less(x,-0.25*ae_pi)||ae_fp_greater(x,0.25*ae_pi) )
   18573             :     {
   18574           0 :         result = ae_cos(x, _state)-1;
   18575           0 :         return result;
   18576             :     }
   18577           0 :     xx = x*x;
   18578           0 :     c = 4.7377507964246204691685E-14;
   18579           0 :     c = c*xx-1.1470284843425359765671E-11;
   18580           0 :     c = c*xx+2.0876754287081521758361E-9;
   18581           0 :     c = c*xx-2.7557319214999787979814E-7;
   18582           0 :     c = c*xx+2.4801587301570552304991E-5;
   18583           0 :     c = c*xx-1.3888888888888872993737E-3;
   18584           0 :     c = c*xx+4.1666666666666666609054E-2;
   18585           0 :     result = -0.5*xx+xx*xx*c;
   18586           0 :     return result;
   18587             : }
   18588             : 
   18589             : 
   18590             : #endif
   18591             : #if defined(AE_COMPILE_ALGLIBBASICS) || !defined(AE_PARTIAL_BUILD)
   18592             : 
   18593             : 
   18594             : #endif
   18595             : 
   18596             : }
   18597             : 

Generated by: LCOV version 1.16