source: PSPA/madxPSPA/src/tpsa.cpp @ 437

Last change on this file since 437 was 430, checked in by touze, 11 years ago

import madx-5.01.00

File size: 56.8 KB
Line 
1/*
2 * Copyright(C) 2008 by Lingyun Yang
3 * lingyun(.dot.]yang@gmail.com
4 * http://www.lingyunyang.com
5 *
6 * Please get permission from Lingyun Yang before you redistribute this file.
7 *
8 */
9
10//! \brief Automatic Differentiation Test
11//! \file tpsa.cpp
12//! \version $Id: tpsa.cpp,v 1.4 2009-06-08 10:48:43 frs Exp $
13//! \author Lingyun Yang, http://www.lingyunyang.com/
14
15#include <iostream>
16#include <ctime>
17#include <vector>
18#include <algorithm>
19#include <cmath>
20#include <cstdlib>
21
22#include "tpsa.h"
23
24static unsigned int comb_num(unsigned int n, unsigned int r);
25static unsigned int gcd(unsigned int a, unsigned int b);
26static void init_order_index(unsigned int nv, unsigned int nd);
27static void init_prod_index(unsigned int nv, unsigned int nd);
28static bool within_limit(TNVND nv, TNVND nd);
29static TNVND* choose(TNVND n, TNVND r, TNVND* p, TNVND nv, TNVND nd);
30static void init_base(TNVND nv, TNVND nd);
31static void print_vec(unsigned int, std::ostream&);
32
33//! Search for the element index of the product of two elements.
34// static unsigned int prod_index(TNVND* pb, TNVND* pm, TNVND order);
35
36//! Maximum length of AD vector. A system with nv variables and nd orders will
37//! have length C(nv+nd, nd).
38static const unsigned int MAX_N_BASE =
39    std::numeric_limits<unsigned int>::max()/2;
40
41//! global nv, nd
42static TNVND gnv, gnd;
43
44//! C(nv+nd, nd)
45static unsigned int FULL_VEC_LEN;
46
47//! Automatic Differentiation
48//! starting index of elements with certain orders.
49static unsigned int* order_index;
50
51
52static unsigned int** H;
53
54//! base vector.
55//! e.g. (000) to (004) if 4th order 3 variables, C(nv+nd,nd)
56//! vectors in total.
57static TNVND *base;
58static unsigned int** prdidx; // index of product
59static TNVND nvec; // number of vec assigned.
60static TNVND* vec; // vec initialized.
61// static unsigned int tblsize; // not used
62
63// memory pool
64static double **advecpool;
65static std::vector<double*> advec;
66static std::vector<unsigned int> adveclen;
67
68
69using namespace std;
70
71//! Greatest Common Divisor, Euclidean algorithm.
72unsigned int gcd(unsigned int a, unsigned int b)
73{
74    unsigned int t;
75    while (b != 0u) {
76        t = b;
77        b = a % b;
78        a = t;
79    }
80    return a;
81}
82
83//! \brief Combinatorial Number (Binomial Coefficient, choose r from n)
84//
85// The result should fit into a unsigned int(e.g. on 32bit system 4294967296).
86//
87// C(15,10) = 3003
88// C(17,10) = 19448
89// C(18,10) = 43758
90// int16    = 65536
91// C(19,10) = 92378
92// C(20,10) = 184756
93// C(30,10) = 30045015
94// int32    = 4294967296
95unsigned int comb_num(unsigned int n, unsigned int r)
96{
97    const unsigned int MAX_N_R = 100;
98
99    if (n == 0 || r == 0) return 1;
100
101    // not allowed, regardless of mathematical meaning.
102    if (n < r) return 0;
103
104    // obviously too large fitting in a unsigned int
105    if (r > MAX_N_R && (n-r) > MAX_N_R) return 0;
106
107    unsigned int k = (r > n-r ? n-r : r);
108
109    std::vector<int> numerator(k), denominator(k);
110
111    for (unsigned int i = 0; i < k; ++i) {
112        numerator[i] = n - i;
113        denominator[i] = k - i;
114    }
115
116    int c = 1;
117    for (size_t i = 0; i < k; ++i) {
118        // deal with denominator[i]
119        for (size_t j = 0; j < k; ++j) {
120            if ( (c=gcd(denominator[i], numerator[j])) > 1 ) {
121                if (numerator[j] % c != 0 || denominator[i] % c != 0) {
122                 #ifdef DEBUG
123                    std::cerr << "ERROR: gcd error, " << k << " = gcd("
124                              << denominator[i] << ","
125                              << numerator[j] << ")" << std::endl;
126                 #endif
127
128                    return 0;
129                }
130                numerator[j] /= c;
131                denominator[i] /= c;
132            }
133        }
134    }
135
136    // check if the result is an integer, i.e. the denominator vector is
137    // (1,1,1, ... ,1)
138    for (size_t i = 0; i < k; ++i) {
139        if (denominator[i] != 1) {
140         #ifdef DEBUG
141            std::cerr << "ERROR: denominator is not dividable by numerator"
142                      << std::endl;
143         #endif
144
145            return 0;
146        }
147    }
148
149    size_t N = 1;
150
151    for (size_t i = 0; i < k; ++i) {
152        if (MAX_N_BASE*1.0/numerator[i] < N) {
153            return 0;
154        }
155        N *= numerator[i];
156    }
157    return N;
158}
159
160//! Initialize the index of orders up to nv+1.
161//! init the index of each order in monimial vec
162void init_order_index(unsigned int nv, unsigned int nd)
163{
164    order_index = new unsigned int[nd+2];
165    size_t i = 0, N = 0;
166    order_index[0] = 0;
167
168    while (i < nd+1) {
169        N += comb_num(nv+i-1, i);
170        order_index[++i] = N;
171    }
172    order_index[nd+1] = FULL_VEC_LEN;
173}
174
175//! Initialize hash table
176void init_prod_index(unsigned int nv, unsigned int nd)
177{
178    //unsigned int m[nv+1][nd+2];
179    unsigned int** m;
180    m = new unsigned int* [nv+1];
181    for (size_t i = 0; i < nv+1; ++i) {
182        m[i] = new unsigned int[nd+2];
183    }
184
185    TNVND* vtmp = new TNVND[nv+1];
186    // hash table
187    H = new unsigned int*[nv+1];
188
189    vtmp[0] = 0;
190    for (TNVND i = 0; i < nv+1; ++i) {
191        H[i] = new unsigned int[nd+2];
192
193        m[i][0] = H[i][0] = 0;
194        m[i][1] = H[i][1] = 1;
195        for (TNVND j = 2; j < nd+2; ++j) {
196            m[i][j] = H[i][j] = m[i][j-1]*(i+j-2)/(j-1);
197        }
198        for (TNVND j = 1; j < nd+2; ++j) {
199            m[i][j] += m[i][j-1];
200            H[i][j] += H[i][j-1];
201        }
202    }
203
204 #ifdef PRT_H
205    int width_h = 3;
206    if (order_index[nd] > 999) width_h = 5;
207    else if (order_index[nd] > 99) width_h = 4;
208
209    std::cout << std::setw(width_h) << ' ';
210    for (TNVND i = 0; i < nv + 2; ++i) {
211        std::cout << std::setw(width_h) << (unsigned int)i;
212    }
213    std::cout << std::endl;
214    std::cout << "   ------------------" << std::endl;
215
216    for (TNVND i = 0; i < nv+1; ++i) {
217        std::cout << std::setw(4) << (unsigned int) i;
218        for (TNVND j = 0; j < nd+2; ++j)
219            std::cout << std::setw(4) << m[i][j];
220        std::cout << std::endl;
221    }
222    std::cout << std::endl;
223 #endif
224
225    unsigned NS = 0;
226    prdidx = new unsigned int*[FULL_VEC_LEN];
227    prdidx[0] = NULL;
228    TNVND ord = 1;
229    TNVND *pb=base;
230
231    // allocating memory.
232    for (size_t i = 1; i < order_index[nd]; ++i) {
233        if (order_index[ord+1] <= i) ++ord;
234        size_t M = order_index[nd-ord+1];
235        prdidx[i] = new unsigned int[M];
236        NS += M;
237        for (size_t j = 1; j < M; ++j) {
238            prdidx[i][j] = 0;
239            size_t idx = 0;
240            for(TNVND k = 0; k < nv; ++k) {
241                idx += m[nv-k][*(pb+i*nv+k) + *(pb+j*nv+k)];
242            }
243            prdidx[i][j] = idx;
244        }
245    }
246    // tblsize = NS; not used
247    //std::cout << "Mem: " << NS << std::endl;
248}
249
250//! \brief Reserve space for n number of TPS vectors.
251//!
252/** \param n number of TPS vectors
253 * \see ad_init
254 */
255#ifdef MSVC_DLL
256_declspec(dllexport) void _stdcall ad_reserve(const TVEC* n)
257#else
258void ad_reserve(const unsigned int* n)
259#endif
260{
261    const unsigned int N = *n;
262
263    if (N <= 0) return;
264
265    advecpool = new double*[N];
266    for (size_t i = 0; i < N; ++i) {
267        advecpool[i] = new double[FULL_VEC_LEN];
268        advec.push_back(NULL);
269        if (adveclen.size() <= i) adveclen.push_back(0);
270        else adveclen[i] = 0;
271    }
272
273 #ifdef DEBUG_ALL
274    std::cout << "Initialize: " << advec.size() << " vectors" << std::endl;
275 #endif
276}
277
278
279
280//! \brief Check if C(nd+nv, nv) is in the maximum number
281//! allowed. i.e. C(nv+nd, nv) < MAX_N_BASE.
282bool within_limit(TNVND nv, TNVND nd)
283{
284    if (nv == 0 || nd == 0) return true;
285
286    unsigned int N = comb_num(nv+nd, nv);
287
288    // too large, can not fit in an unsigned int.
289    if (N == 0) return false;
290
291    if ( N >= MAX_N_BASE ) return false;
292    else return true;
293}
294
295//! \brief Get all the combinations, choose r from n.
296//! Do nothing if n==0 or r==0. other numbers are not checked.
297TNVND* choose(TNVND n, TNVND r, TNVND* p, TNVND nv, TNVND /* nd */)
298{
299    std::vector<TNVND> c(r);
300    TNVND i, j, k;
301
302    // size_t n = 0;
303    // Boundary condition
304    if (n == 0 || r == 0) return 0;
305
306    for (i = 0; i < r; ++i) {
307        c[i] = i;
308    }
309    c[r-1] = r-2;
310    while(true) {
311        j = r - 1;
312        // for unsigned types, this is tricky.
313        // two more constraint j < r, c[j] < n.
314        // j >= 0 is always true
315        while(j < r && c[j] >= n - r +j && c[j] < n) j--;
316        // if (j < 0) break;
317        if (j >= r ) break;
318
319        ++c[j];
320        for ( k = j + 1; k < r; ++k) c[k] = c[k-1] + 1;
321
322        /*
323          for (TNVND iv = 0; iv < r; ++iv)
324          std::cout << ' ' << static_cast<unsigned int>(c[iv]-iv);
325          // std::cout << std::endl;
326          std::cout << "     ";
327        */
328
329        // CoeffMatrix.push_back(c);
330        for (size_t iv = 0; iv < r; ++iv)
331            ++(*(p+c[iv]-iv));
332        p += nv;
333
334
335        /*
336          TNVND* h = p - nv;
337          for (size_t iv = 0; iv < nv; ++iv) {
338          std::cout << ' ' << static_cast<unsigned int>(*h);
339          ++h;
340          }
341          std::cout << std::endl;
342        */
343
344        // ++n;
345    }
346
347    return p;
348}
349
350//
351void init_base(TNVND nv, TNVND nd)
352{
353    // int nv = variable; // max num of variables
354    // unsigned int nm = 0;
355    // tps_base.push_back(base);
356    base = new TNVND[nv*FULL_VEC_LEN];
357    for (size_t i = 0; i < nv*FULL_VEC_LEN; ++i) base[i] = 0;
358
359    TNVND* pb = base;
360
361    if ( !within_limit(nv, nd) ) {
362        return;
363    }
364
365    // std::cout << "Address: " << (unsigned int)(base) << std::endl;
366    for (size_t i = 0; i < nv; ++i) {
367        *pb = 0;
368        ++pb;
369    }
370
371    // std::cout << "Address: " << (unsigned int)(pb) << std::endl;
372    for (size_t d = 1; d <= nd; ++d) {
373        pb = choose(nv+d-1, d, pb, nv, nd);
374        // std::cout << "Address: " << (unsigned int)(pb) << std::endl;
375
376    }
377    // std::cout << "Total: " << pb << std::endl;
378    pb = base;
379    for (size_t i = 0; i < FULL_VEC_LEN; ++i) {
380        TNVND x = 0;
381        for (TNVND k = 0; k < nv; ++k) {
382            x += *(pb+nv-1-k);
383            *(pb+nv-1-k) = x;
384        }
385        pb += nv;
386    }
387}
388
389/**\brief Initialize the TPSA library.
390 *
391 * \param nvar number of variables
392 * \param nord highest order of TPS.
393 *
394 * This must be called before any use of TPS vector, and followed by ad_reserve
395 */
396#ifdef MSVC_DLL
397extern "C" _declspec(dllexport) void _stdcall ad_init(const TNVND* nvar, const TNVND* nord)
398#else
399void ad_init(const TNVND* nvar, const TNVND* nord)
400#endif
401{
402    TNVND nv = *nvar;
403    TNVND nd = *nord;
404
405 #ifdef DEBUG
406    std::cerr << "Initialize nv= " << *nvar << " nd= " << *nord << std::endl;
407 #endif
408    advecpool = NULL;
409    gnv = nv; // assign to global nv
410    gnd = nd; // assign to global nd
411
412    FULL_VEC_LEN = comb_num(gnv+gnd, gnd);
413    init_order_index(gnv, gnd);
414
415    // overflow !!
416    if (FULL_VEC_LEN == 0) {
417        std::cerr << "Overflow!  (" << nv << "," << nd << ")" << std::endl;
418        std::exit(1);
419    }
420
421    // this reset the base vector
422    vec = new TNVND[nv];
423    for (TNVND i = 0; i < nv; ++i) vec[i] = 0;
424
425    nvec = 0;
426
427    init_base(gnv, gnd);
428
429    init_prod_index(gnv, gnd);
430
431    // random number generator
432    srand(1U);
433}
434
435/** \brief Reset the base vectors.
436 * To avoid confusions when starting a new set of TPSA calculations, call this before a new ad_init().
437 * with nv from ad_nvar(nv).
438 */
439#ifdef MSVC_DLL
440_declspec(dllexport) void _stdcall ad_resetvars(const TNVND* nvar)
441#else
442void ad_resetvars(const TNVND* nvar)
443#endif
444{
445    if (!vec) return;
446    if (*nvar > gnv) {
447        //std::cerr << "ERROR: Reset more base vectors than earlier initialization. "
448        //          << std::endl;
449        //std::cerr << "   global nv = " << gnv << "  input= " << *nvar << std::endl;
450        for (TNVND i = 0; i < gnv; ++i) vec[i] = 0;
451    } else {
452        for (TNVND i = 0; i < *nvar; ++i) vec[i] = 0;
453    }
454    nvec = 0;
455}
456
457/** \brief Allocate space for one TPS vector.
458 * \param i return a new integer representing the allocated TPS vector.
459 */
460#ifdef MSVC_DLL
461_declspec(dllexport) void _stdcall ad_alloc(TVEC* i)
462#else
463void ad_alloc(unsigned int* i)
464#endif
465{
466    // didn't check the upper limit of i
467    *i = advec.size();
468    for (size_t j = 0; j < advec.size(); ++j) {
469        if (!advec[j]) {
470            *i = j;
471            break;
472        }
473    }
474
475    if (*i >= advec.size()) {
476        std::cerr << "Run out of vectors" << std::endl;
477        exit(-1);
478        //return;
479    }
480
481
482    //size_t n = 0;
483    //ad_count(&n);
484    //std::cerr << "Found space for AD vector: " << *i << " " << n << std::endl;
485    unsigned int iv = *i;
486
487    // initialize as a constant 0, length 1
488    advec[iv] = advecpool[iv];
489    for (size_t j = 0; j < FULL_VEC_LEN; ++j) {
490        advec[iv][j] = 0;
491    }
492    adveclen[iv] = 1;
493    advec[iv][0] = 0;
494
495 #ifdef DEBUG_ALL
496    std::cout << "Allocate: " << iv << " len: " << adveclen[iv] << std::endl;
497    ad_print(&iv);
498 #endif
499}
500
501/** \brief Free the memory allocated by ad_alloc
502 * \param i TPS vector
503 */
504#ifdef MSVC_DLL
505_declspec(dllexport) void _stdcall ad_free(const TVEC* i)
506#else
507void ad_free(const unsigned int* i)
508#endif
509{
510    advec[*i] = NULL;
511    adveclen[*i] = 0;
512
513 #ifdef DEBUG_ALL
514    std::cout << "AD free " << *i << std::endl;
515 #endif
516}
517
518/** \brief Copy TPS vector
519 * \param isrc source
520 * \param idst destination
521 */
522#ifdef MSVC_DLL
523_declspec(dllexport) void _stdcall ad_copy(const TVEC* isrc, const TVEC* idst)
524#else
525void ad_copy(const unsigned int* isrc, const unsigned int* idst)
526#endif
527{
528    unsigned int i = *isrc;
529    unsigned int j = *idst;
530    if (i == j) return;
531    // did not check if j is allocated.
532    for (size_t k = 0; k < FULL_VEC_LEN; ++k)
533        advec[j][k] = advec[i][k];
534    adveclen[j] = adveclen[i];
535 #ifdef DEBUG_ALL
536    std::cout << "Copy from " << i << " to " << j << std::endl;
537 #endif
538    //ad_print(idst);
539}
540
541/** \brief Count how many vectors has been allocated
542 */
543#ifdef MSVC_DLL
544_declspec(dllexport) void _stdcall ad_count(TVEC* n)
545#else
546void ad_count(TVEC* n)
547#endif
548{
549    *n = 0;
550    for(size_t i = 0; i < advec.size(); ++i)
551        if (advec[i]) ++(*n);
552}
553
554/** \brief Set a TPS vector as a constant
555 */
556#ifdef MSVC_DLL
557_declspec(dllexport) void _stdcall ad_const(const TVEC* iv, const double* r)
558#else
559void ad_const(const TVEC* iv, const double* r)
560#endif
561{
562    unsigned int ii = *iv;
563    for(size_t i = 0; i < adveclen[ii]; ++i)
564        advec[ii][i] = 0;
565    advec[ii][0] = *r;
566 #ifdef DEBUG_ALL
567    std::cout << "Set const: iv " << *iv << " = " << *r << std::endl;
568 #endif
569    adveclen[ii] = 1;
570}
571
572/** \brief Set the small TPS coefficients as 0 if they are less than eps.
573 */
574#ifdef MSVC_DLL
575_declspec(dllexport) void _stdcall ad_clean(const TVEC* iv, const double* eps)
576#else
577void ad_clean(const TVEC* iv, const double* eps)
578#endif
579{
580    unsigned int N = 0;
581    for(size_t i = 0; i < adveclen[*iv]; ++i) {
582        if (abs(advec[*iv][0]) < abs(*eps)) advec[*iv][i] = 0;
583        else N = i;
584    }
585    if (adveclen[*iv] > N+1) {
586        adveclen[*iv] = N+1;
587    }
588}
589
590/** \brief Fill the TPS coefficients as a random number in [0,1]
591 *
592 * The length(highest nonzero coefficients) is not changed.
593 */
594#ifdef MSVC_DLL
595_declspec(dllexport) void _stdcall ad_fill_ran(const TVEC* iv, const double* ratio, const double* xm)
596#else
597void ad_fill_ran(const TVEC* iv, const double* ratio, const double* xm)
598#endif
599{
600    for(size_t i = 0; i < adveclen[*iv]; ++i) {
601        if (std::rand()*1.0/RAND_MAX > *ratio)
602            advec[*iv][i] = 0;
603        else advec[*iv][i] = std::rand()*(*xm)/RAND_MAX;
604        //std::cout << advec[*iv][i] << " ";
605    }
606    //std::cout << std::endl;
607}
608
609/**
610 */
611#ifdef MSVC_DLL
612_declspec(dllexport) void _stdcall ad_pok(const TVEC* ivec, int* c, size_t* n, double* x)
613#else
614void ad_pok(const unsigned int* ivec, int* c, size_t* n, double* x)
615#endif
616{
617    const unsigned int ii = *ivec;
618    size_t N = (*n > gnv) ? gnv : *n;
619    double r = *x;
620 #ifdef DEBUG_ALL
621    std::cout << "AD Pok ivec= " << *ivec << " n= " << *n << " x= " << *x << std::endl;
622 #endif
623
624    unsigned int *cef = new unsigned int[gnv];
625    unsigned int *bv = new unsigned int[gnv];
626    unsigned int d = 0;
627    for (size_t i = 0; i < N; ++i) {
628        //std::cout << " " << c[i];
629        cef[i] = c[i];
630        d += c[i];
631    }
632    // didn't check if
633    for (size_t i = N; i < gnv; ++i) cef[i] = 0;
634
635    //std::cout  << std::endl;
636    //for (int i = 0; i < FULL_VEC_LEN; ++i) {
637    //    advec[ii][i] = 0;
638    //}
639
640    if (d > gnd) return;
641
642    size_t k = 0;
643
644    //std::cout << "order: " << (unsigned int)d << std::endl;
645    for (size_t i = 0; i < gnv; ++i){
646        bv[i] = d;
647        d -= cef[i];
648        //std::cout << (unsigned int)i << " : "
649        //          << (unsigned int) t << ' '
650        //          << (unsigned int)bv[i] << ' '
651        //          << (unsigned int)d << std::endl;
652        k += H[gnv-i][bv[i]];
653    }
654    //std::cout << std::endl;
655    //std::cout << k << std::endl;
656    advec[ii][k] = r;
657
658    if (k+1>adveclen[ii])
659        adveclen[ii] =  k+1;
660    delete []cef;
661    delete []bv;
662}
663
664// ith element of ivec, save pattern in c, value in x
665// c has length gnv
666#ifdef MSVC_DLL
667_declspec(dllexport) void _stdcall ad_elem(const TVEC* ivec, unsigned int* idx, unsigned int* c, double* x)
668#else
669void ad_elem(const TVEC* ivec, unsigned int* idx, unsigned int* c, double* x)
670#endif
671{
672    const TVEC ii = *ivec;
673
674    for (size_t i = 0; i < gnv; ++i) c[i] = 0;
675    if (*idx > adveclen[ii] || *idx < 1) {
676        * x = 0;
677        return;
678    }
679
680    //
681    double* v = advec[ii];
682    *x = v[*idx-1];
683    TNVND* p = base + gnv*(*idx-1);
684    for (size_t j = 0; j < gnv-1; ++j) {
685        c[j] = (unsigned int) (*p-*(p+1));
686        ++p;
687    }
688    c[gnv-1] = (unsigned int) *p;
689}
690
691
692#ifdef MSVC_DLL
693_declspec(dllexport) void _stdcall ad_pek(const TVEC* ivec, int* c, size_t* n, double* x)
694#else
695void ad_pek(const unsigned int* ivec, int* c, size_t* n, double* x)
696#endif
697{
698    const unsigned int ii = *ivec;
699    size_t N = (*n > gnv) ? gnv : *n;
700    //double r = *x;
701
702 #ifdef DEBUG_ALL
703    std::cout << "AD Pek ivec= " << *ivec << " n= " << *n << " x= " << *x << std::endl;
704 #endif
705
706    unsigned int *cef = new unsigned int[gnv];
707    unsigned int *bv = new unsigned int[gnv];
708    unsigned int d = 0;
709    for (size_t i = 0; i < N; ++i) {
710        //std::cout << " " << c[i];
711        cef[i] = c[i];
712        d += c[i];
713    }
714    // didn't check if
715    for (size_t i = N; i < gnv; ++i) cef[i] = 0;
716
717    //std::cout  << std::endl;
718    //for (int i = 0; i < FULL_VEC_LEN; ++i) {
719    //    advec[ii][i] = 0;
720    //}
721
722    if (d > gnd) return;
723
724    size_t k = 0;
725
726    //std::cout << "order: " << (unsigned int)d << std::endl;
727    for (size_t i = 0; i < gnv; ++i){
728        bv[i] = d;
729        d -= cef[i];
730        //std::cout << (unsigned int)i << " : "
731        //          << (unsigned int) t << ' '
732        //          << (unsigned int)bv[i] << ' '
733        //          << (unsigned int)d << std::endl;
734        k += H[gnv-i][bv[i]];
735    }
736    //std::cout << std::endl;
737    //std::cout << k << std::endl;
738
739    if (k > adveclen[ii]) *x = 0;
740    else *x = advec[ii][k];
741
742    delete []bv;
743    delete []cef;
744}
745
746// set the vector ii be the base vector iv
747// ii, iv are 0-started index.
748#ifdef MSVC_DLL
749_declspec(dllexport) void _stdcall ad_var(const TVEC* ivec, const double* x, unsigned int* ibvec)
750#else
751void ad_var(const unsigned int* ivec, const double* x, unsigned int* ibvec)
752#endif
753{
754    const unsigned int iv = *ivec;
755    unsigned int ibv = *ibvec;
756    double x0 = *x;
757    //unsigned int nbvmax;
758    // TNVND i = iv - 1;
759    double *v = advec[iv];
760 #ifdef DEBUG_ALL
761    std::cout << "Enter ad_var " << *ivec << "  " << *x << "  " << *ibvec << std::endl;
762 #endif
763
764    for (size_t k = 0; k < FULL_VEC_LEN; ++k) v[k] = 0;
765    v[0] = x0;
766    //v[iv] = 1;
767
768    // check iv and is not set before
769    if (ibv < gnv && vec[ibv] == 0) {
770        ++vec[ibv];
771        ++nvec;
772        adveclen[iv] = ibv + 2; // length is const+first order, 1+(iv+1)
773        v[ibv+1] = 1;
774    } else if (ibv >= gnv ) {
775        std::cerr << "Out of boundary, init as an ordinary variable"
776                  << std::endl;
777        adveclen[iv] = 1;
778    } else if (vec[ibv] > 0)  {
779      #ifdef DEBUG
780        // this will update the vec[iv]
781        if (vec[ibv] == 1) {
782            std::cerr << "WARNING: Base vector " << (unsigned int) ibv
783                      << " has been initialized [" << gnv << "]: (";
784            for (TNVND j = 0; j < gnv; ++j) {
785                if (vec[j]) std::cerr << ' ' << (unsigned int)vec[j];
786                else std::cerr << " N";
787            }
788            std::cerr << ")" << std::endl;
789        }
790        ++vec[ibv];
791    #endif
792        adveclen[iv] = ibv + 2;
793        v[ibv+1] = 1;
794    } else {
795        std::cerr << "What else ?" << std::endl;
796    }
797
798 #ifdef DEBUG_ALL
799    std::cout << "Exit ad_var" << std::endl;
800    ad_print(&iv);
801 #endif
802    //std::exit(-1);
803    //for (size_t k = 1; k < iv; ++k) v[k] = 0;
804}
805
806#ifdef MSVC_DLL
807_declspec(dllexport) void _stdcall ad_abs(const TVEC* iv, double* r)
808#else
809void ad_abs(const TVEC* iv, double* r)
810#endif
811{
812    *r = 0;
813    for (size_t i = 0; i < adveclen[*iv]; ++i) {
814        *r += std::abs(advec[*iv][i]);
815        //std::cout << advec[*iv][i] << ' ';
816    }
817    //std::cout << "abs: " << *r << std::endl;
818}
819
820#ifdef MSVC_DLL
821_declspec(dllexport) void _stdcall ad_truncate(const TVEC* iv, const TNVND* d)
822#else
823void ad_truncate(const TVEC* iv, const TNVND* d)
824#endif
825{
826    if (*d > gnd) return;
827
828    for(size_t i = order_index[*d]; i < adveclen[*iv]; ++i) {
829        advec[*iv][i] = 0;
830    }
831    adveclen[*iv] = order_index[*d];
832}
833
834#ifdef MSVC_DLL
835_declspec(dllexport) void _stdcall ad_add(const TVEC* idst, const TVEC* jsrc)
836#else
837void ad_add(const unsigned int* idst, const unsigned int* jsrc)
838#endif
839{
840    unsigned int i = *idst;
841    unsigned int j = *jsrc;
842
843    double *v = advec[i];
844    double *rhsv = advec[j];
845    //double *resv = advec[k];
846
847    if (adveclen[i] < adveclen[j]) {
848        // two blocks for overlap part and non-overlap part.
849        for (size_t ii = 0; ii < adveclen[i]; ++ii) v[ii] += rhsv[ii];
850        for (size_t ii = adveclen[i]; ii < adveclen[j]; ++ii) v[ii] = rhsv[ii];
851        adveclen[i] = adveclen[j];
852    }else {
853        for (size_t ii = 0; ii < adveclen[j]; ++ii) v[ii] += rhsv[ii];
854    }
855
856 #ifdef DEBUG_ALL
857    std::cout << "AD add " << *idst << " " << *jsrc << std::endl;
858 #endif
859
860    //while(std::abs(advec[*idst][adveclen[*idst]-1]) < std::numeric_limits<double>::min()  && adveclen[*idst] > 2) --adveclen[*idst];
861
862    //return *this;
863}
864
865#ifdef MSVC_DLL
866_declspec(dllexport) void _stdcall ad_add_const(const TVEC* i, double *r)
867#else
868void ad_add_const(const TVEC* i, double *r)
869#endif
870{
871    advec[*i][0] += *r;
872}
873
874#ifdef MSVC_DLL
875_declspec(dllexport) void _stdcall ad_sub(const TVEC* idst, const TVEC* jsrc)
876#else
877void ad_sub(const unsigned int* idst, const unsigned int* jsrc)
878#endif
879{
880    unsigned int i = *idst;
881    unsigned int j = *jsrc;
882
883    double *v = advec[i];
884    double *rhsv = advec[j];
885
886 #ifdef DEBUG_ALL
887    std::cout << "AD sub " << *idst << " ["  << adveclen[i]
888              << "]  " << *jsrc << "  [" << adveclen[j] << "]"
889              << std::endl;
890 #endif
891
892    //double *resv = advec[k];
893    if (adveclen[i] == 0 || adveclen[j] == 0) {
894        std::cerr << "ERROR: AD sub zero length vector" << std::endl;
895        //std::exit(-1);
896        return;
897    }
898
899    if (adveclen[i] < adveclen[j]) {
900        // two blocks for overlap part and non-overlap part.
901        for (size_t ii = 0; ii < adveclen[i]; ++ii) v[ii] -= rhsv[ii];
902        for (size_t ii = adveclen[i]; ii < adveclen[j]; ++ii) v[ii] = -rhsv[ii];
903        adveclen[i] = adveclen[j];
904    }else {
905        for (size_t ii = 0; ii < adveclen[j]; ++ii) v[ii] -= rhsv[ii];
906    }
907
908    //while(abs(advec[*idst][adveclen[*idst]-1]) < std::numeric_limits<double>::min()  && adveclen[*idst] > 1) --adveclen[*idst];
909
910    //return *this;
911}
912
913//! internal multiplication, dst should be different from lhs and rhs.
914#ifdef MSVC_DLL
915_declspec(dllexport) void _stdcall ad_mult(const TVEC* ilhs, const TVEC* irhs, TVEC* idst)
916#else
917void ad_mult(const unsigned int* ilhs, const unsigned int* irhs, unsigned int* idst)
918#endif
919{
920    unsigned int lhs = *ilhs;
921    unsigned int rhs = *irhs;
922    unsigned int dst = *idst;
923
924 #ifdef DEBUG_ALL
925    std::cout << "AD mult " << *ilhs << " " << *irhs
926              << " " << *idst << std::endl;
927    ad_print(ilhs);
928    ad_print(irhs);
929 #endif
930
931    // can speed up without copy-constructor.
932    for (size_t i = 0; i < adveclen[dst]; ++i) advec[dst][i] = 0;
933
934    adveclen[dst] = adveclen[lhs];
935
936    advec[dst][0] = advec[lhs][0] * advec[rhs][0];
937    for (size_t i = 1; i < adveclen[rhs]; ++i) {
938        advec[dst][i] += advec[lhs][0]*advec[rhs][i];
939    }
940    for (size_t i = 1; i < adveclen[lhs]; ++i) {
941        advec[dst][i] += advec[lhs][i]*advec[rhs][0];
942    }
943
944 #ifdef DEBUG_MULT
945    int width_v = 1;
946    if (nv > static_cast<TNVND>(9)) width_v = 2;
947 #endif
948
949    // It is symmetric, but not when lhs rhs have different size, .....
950    TNVND ord = 1;
951    size_t L = std::max(adveclen[lhs], adveclen[rhs]);
952 #ifdef DEBUG_ALL
953    std::cerr << "Length: " << L << " nv " << gnv << "  nd " << gnd << std::endl;
954 #endif
955
956    for (size_t i = 1; i < std::min(adveclen[lhs], order_index[gnd]); ++i) {
957        if (order_index[ord+1] <= i) ++ord;
958        unsigned int M = order_index[gnd-ord+1];
959        if (M > adveclen[rhs]) M = adveclen[rhs];
960        //dst.v[prdidx[i][i]] += lhs.v[i]*rhs.v[i];
961        //if (prdidx[i][i] > L) L = prdidx[i][i];
962        for (size_t j = 1; j < M; ++j) {
963            advec[dst][prdidx[i][j]] += advec[lhs][i]*advec[rhs][j];
964            //dst.v[prdidx[i][j]] += lhs.v[j]*rhs.v[i];
965            //if (prdidx[i][j] >= L) L = prdidx[i][j] + 1;
966            //std::cout << i << ',' << j << "  " << L << std::endl;
967        }
968        //std::cout << i << ',' << M-1 << "  p=" << prdidx[i][M-1] << " L=" << L;
969        if (prdidx[i][M-1] >= L) {
970            L = prdidx[i][M-1] + 1;
971            //std::cout << ' ' << L << std::endl;
972        }
973    }
974
975    //while(abs(dst.v[L-1]) < std::numeric_limits<T>::min()) --L;
976    if (L > FULL_VEC_LEN) L = FULL_VEC_LEN;
977    adveclen[dst] = L;
978
979    while(std::abs(advec[dst][adveclen[dst]-1]) < std::numeric_limits<double>::min()  && adveclen[dst] > 1) --adveclen[dst];
980
981    //std::cerr << "Len: " << adveclen[dst] << std::endl;
982    //ad_print(idst);
983    //dst.len = FULL_VEC_LEN;
984}
985
986#ifdef MSVC_DLL
987_declspec(dllexport) void _stdcall ad_mult_const(const TVEC* iv, double* c)
988#else
989void ad_mult_const(const TVEC* iv, double* c)
990#endif
991{
992    double* v = advec[*iv];
993    for (size_t i = 0; i < adveclen[*iv]; ++i)
994        v[i] *= (*c);
995 #ifdef DEBUG_ALL
996    std::cout << "AD mult const " << *iv << " const= " << *c << std::endl;
997 #endif
998}
999
1000#ifdef MSVC_DLL
1001_declspec(dllexport) void _stdcall ad_div_c(const TVEC* iv, const double* c)
1002#else
1003void ad_div_c(const TVEC* iv, const double* c)
1004#endif
1005{
1006    if (std::abs(*c) < std::numeric_limits<double>::min()) {
1007        std::cerr << "ERROR: divide a two small number! " << *c << std::endl;
1008        std::exit(-1);
1009    }
1010
1011    for (size_t i = 0; i < adveclen[*iv]; ++i)
1012        advec[*iv][i] /= *c;
1013}
1014
1015//
1016#ifdef MSVC_DLL
1017_declspec(dllexport) void _stdcall ad_c_div(const TVEC* iv, const double* c, TVEC* ivret)
1018#else
1019void ad_c_div(const TVEC* iv, const double* c, TVEC* ivret)
1020#endif
1021{
1022    TVEC ipn, ip, itmp;
1023    ad_alloc(&ipn);
1024    ad_alloc(&ip);
1025    //ad_alloc(&iret);
1026    ad_alloc(&itmp);
1027
1028    TVEC iret = *ivret;
1029
1030    double *pn = advec[ipn];
1031    double *p = advec[ip];
1032    double *ret = advec[iret];
1033    double *v = advec[*iv];
1034
1035    ad_copy(iv, &ip);
1036    ad_copy(iv, &ipn);
1037
1038    // TODO: didn't check c = 0.0
1039    double x0 = v[0];
1040 #ifdef DEBUG_ALL
1041    std::cout << "x0 " << x0 << std::endl;
1042 #endif
1043    for (size_t i = 1; i < adveclen[ip]; ++i) {
1044        p[i] /= -x0;
1045        pn[i] = p[i];
1046    }
1047    pn[0] = p[0] = 0;
1048
1049    ret[0] = 1;
1050    adveclen[iret] = 1;
1051    //ret += p;
1052 #ifdef DEBUG_ALL
1053    std::cout << "-- ret[0]= " << ret[0] << " " << adveclen[iret]
1054              << " " << p[0] << " " << adveclen[ip] << std::endl;
1055 #endif
1056
1057    ad_add(&iret, &ip);
1058    //ad_print(&ip);
1059 #ifdef DEBUG_ALL
1060    std::cout << "-- ret[0]= " << ret[0] << " " << adveclen[iret]
1061              << " " << p[0] << " " << adveclen[ip]<< std::endl;
1062 #endif
1063
1064    for (TNVND nd = 2; nd < gnd+1; ++nd) {
1065        ad_mult(&ipn, &ip, &itmp);
1066        ad_copy(&itmp, &ipn);
1067      for (size_t i = 0; i < adveclen[ipn]; ++i)
1068          ret[i] += pn[i];
1069     #ifdef DEBUG_ALL
1070        std::cout << "ret[0]= " << ret[0] << std::endl;
1071     #endif
1072    }
1073    adveclen[iret] = FULL_VEC_LEN;
1074
1075    //std::cout << "AD " << iret << std::endl;
1076    for (size_t i = 0; i < adveclen[iret]; ++i) {
1077        ret[i] /= x0/(*c);
1078        //std::cout << ' ' << ret[i];
1079    }
1080    //std::cout << std::endl;
1081 #ifdef DEBUG_ALL
1082    std::cout << ret[0] << std::endl;
1083 #endif
1084
1085    ad_free(&itmp);
1086    ad_free(&ip);
1087    ad_free(&ipn);
1088}
1089
1090#ifdef MSVC_DLL
1091_declspec(dllexport) void _stdcall ad_div(const TVEC* ilhs, const TVEC* irhs, TVEC* idst)
1092#else
1093void ad_div(const TVEC* ilhs, const TVEC* irhs, TVEC* idst)
1094#endif
1095{
1096    TVEC itmp;
1097    double c = 1.0;
1098    bool nonzero = false;
1099    for (size_t i = 0; i < adveclen[*irhs]; ++i) {
1100        if(std::abs(advec[*irhs][i]) > std::numeric_limits<double>::min()) {
1101            nonzero = true;
1102            break;
1103        }
1104    }
1105
1106    if (!nonzero) {
1107        std::cerr << "ERROR: Divided by zero: " << std::endl;
1108        ad_print(irhs);
1109        c = std::sqrt(-1.0);
1110        std::cerr << c << std::endl;
1111        std::exit(-1);
1112    }
1113
1114    ad_alloc(&itmp);
1115    ad_c_div(irhs, &c, &itmp);
1116
1117 #ifdef DEBUG_ALL
1118    std::cout << "AD div" << std::endl;
1119    ad_print(&itmp);
1120    std::cout << "AD mult" << std::endl;
1121    ad_print(ilhs);
1122 #endif
1123
1124    ad_mult(ilhs, &itmp, idst);
1125
1126    //ad_print(idst);
1127    ad_free(&itmp);
1128}
1129
1130#ifdef MSVC_DLL
1131_declspec(dllexport) void _stdcall ad_sqrt(const TVEC* iv, const TVEC* iret)
1132#else
1133void ad_sqrt(const TVEC* iv, const TVEC* iret)
1134#endif
1135{
1136    double x = advec[*iv][0];
1137    double c;
1138    TVEC itmp, ip, ipn;
1139    ad_alloc(&itmp);
1140    ad_alloc(&ip);
1141    ad_alloc(&ipn);
1142    ad_copy(iv, &ip);
1143    ad_div_c(&ip, &x);
1144    advec[ip][0] = 0;
1145    ad_reset(iret);
1146    advec[*iret][0] = 1;
1147    adveclen[*iret] = 1;
1148    // ip is the delta_x
1149    ad_copy(&ip, &itmp);
1150    ad_copy(&ip, &ipn);
1151    c = .5;
1152 #ifdef DEBUG_ALL
1153    std::cout << "Coef: c= " << c << std::endl;
1154 #endif
1155    for(size_t i = 1; i < gnd+1; ++i) {
1156        ad_mult_const(&itmp, &c);
1157        ad_add(iret, &itmp);
1158        c = c*(1-2.0*i)/2/(i+1.0);
1159     #ifdef DEBUG_ALL
1160        std::cout << "   " << i << ":" << c << std::endl;
1161     #endif
1162        ad_mult(&ip, &ipn, &itmp);
1163        ad_copy(&itmp, &ipn);
1164    }
1165 #ifdef DEBUG_ALL
1166    std::cout << std::endl;
1167 #endif
1168    x =std::sqrt(x);
1169    ad_mult_const(iret, &x);
1170    ad_free(&ipn);
1171    ad_free(&ip);
1172    ad_free(&itmp);
1173}
1174
1175#ifdef MSVC_DLL
1176_declspec(dllexport) void _stdcall ad_exp(const TVEC* iv, const TVEC* iret)
1177#else
1178void ad_exp(const TVEC* iv, const TVEC* iret)
1179#endif
1180{
1181    double x = std::exp(advec[*iv][0]);
1182    double c;
1183    TVEC itmp, ip, ipn;
1184
1185 #ifdef DEBUG_ALL
1186    std::cout << "AD exp " << *iv << " " << x << "  ret: " << *iret << std::endl;
1187 #endif
1188
1189    ad_alloc(&itmp);
1190    ad_alloc(&ip);
1191    ad_alloc(&ipn);
1192
1193    ad_copy(iv, &ip);
1194    //ad_div_c(&ip, &x);
1195    advec[ip][0] = 0;
1196
1197    ad_reset(iret);
1198    advec[*iret][0] = 1.0;
1199    adveclen[*iret] = 1;
1200    // ip is the delta_x
1201
1202 #ifdef DEBUG_ALL
1203    std::cout << "reset" << std::endl;
1204 #endif
1205
1206    ad_copy(&ip, &itmp);
1207    ad_copy(&ip, &ipn);
1208    c = 1.0;
1209 #ifdef DEBUG_ALL
1210    std::cout << "Coef: c= " << c << std::endl;
1211 #endif
1212
1213    for(size_t i = 1; i < gnd+1; ++i) {
1214        c = c*1.0*i;
1215        ad_div_c(&itmp, &c);
1216        ad_add(iret, &itmp);
1217     #ifdef DEBUG_ALL
1218        std::cout << "   " << i << ":" << c << std::endl;
1219     #endif
1220        ad_mult(&ip, &ipn, &itmp);
1221        ad_copy(&itmp, &ipn);
1222    }
1223 #ifdef DEBUG_ALL
1224    std::cout << std::endl;
1225 #endif
1226    ad_mult_const(iret, &x);
1227    ad_free(&ipn);
1228    ad_free(&ip);
1229    ad_free(&itmp);
1230}
1231
1232#ifdef MSVC_DLL
1233_declspec(dllexport) void _stdcall ad_log(const TVEC* iv, const TVEC* iret)
1234#else
1235void ad_log(const TVEC* iv, const TVEC* iret)
1236#endif
1237{
1238    double x = std::log(advec[*iv][0]);
1239    double c;
1240    TVEC itmp, ip, ipn;
1241
1242 #ifdef DEBUG_ALL
1243    std::cout << "AD exp " << *iv << " " << x << "  ret: " << *iret << std::endl;
1244 #endif
1245
1246    ad_alloc(&itmp);
1247    ad_alloc(&ip);
1248    ad_alloc(&ipn);
1249
1250    ad_copy(iv, &ip);
1251    ad_div_c(&ip, advec[*iv]);
1252    advec[ip][0] = 0;
1253
1254    ad_reset(iret);
1255    advec[*iret][0] = x;
1256    adveclen[*iret] = 1;
1257    // ip is the delta_x
1258
1259 #ifdef DEBUG_ALL
1260    std::cout << "reset" << std::endl;
1261 #endif
1262
1263    ad_copy(&ip, &itmp);
1264    ad_copy(&ip, &ipn);
1265    c = 1.0;
1266 #ifdef DEBUG_ALL
1267    std::cout << "Coef: c= " << c << std::endl;
1268 #endif
1269
1270    for(size_t i = 1; i < gnd+1; ++i) {
1271        c = (i % 2 == 0 ? -1.0*i: (1.0*i) );
1272        ad_div_c(&itmp, &c);
1273        ad_add(iret, &itmp);
1274     #ifdef DEBUG_ALL
1275        std::cout << "   " << i << ":" << c << std::endl;
1276     #endif
1277
1278        ad_mult(&ip, &ipn, &itmp);
1279        ad_copy(&itmp, &ipn);
1280    }
1281 #ifdef DEBUG_ALL
1282    std::cout << std::endl;
1283 #endif
1284    //ad_mult_const(iret, &x);
1285    ad_free(&ipn);
1286    ad_free(&ip);
1287    ad_free(&itmp);
1288}
1289
1290/** \brief Reset to a constant 0
1291 */
1292#ifdef MSVC_DLL
1293_declspec(dllexport) void _stdcall ad_reset(const TVEC* iv)
1294#else
1295void ad_reset(const TVEC* iv)
1296#endif
1297{
1298 #ifdef DEBUG_ALL
1299    std::cout << "AD reset " << *iv << std::endl;
1300 #endif
1301
1302    for (size_t i = 0; i < adveclen[*iv]; ++i)
1303        advec[*iv][i] = 0;
1304    adveclen[*iv] = 0;
1305}
1306
1307
1308#ifdef MSVC_DLL
1309_declspec(dllexport) void _stdcall ad_sin(const TVEC* iv, const TVEC* iret)
1310#else
1311void ad_sin(const TVEC* iv, const TVEC* iret)
1312#endif
1313{
1314    //AD<T,nv,nd> ret(v), pnev(v), pnod(v), p(v);
1315    TVEC ipnev, ipnod, ip;
1316    ad_alloc(&ipnev);
1317    ad_alloc(&ipnod);
1318    ad_alloc(&ip);
1319
1320    ad_copy(iv, iret);
1321    ad_copy(iv, &ipnev);
1322    ad_copy(iv, &ipnod);
1323    ad_copy(iv, &ip);
1324
1325    double *v = advec[*iv];
1326    double *ret = advec[*iret];
1327    double *pnod = advec[ipnod];
1328    double *pnev = advec[ipnev];
1329    double *p = advec[ip];
1330
1331 #ifdef DEBUG_ALL
1332    std::cout << ' ' << *iret << ' ' << ret
1333              << ", " << ipnev << ' ' << pnev
1334              << ", " << ipnod << ' ' << pnod
1335              << ", " << ip << ' ' << p
1336              << std::endl;
1337 #endif
1338    // TODO: didn't check c = 0.0
1339    double s = sin(v[0]);
1340    double c = cos(v[0]);
1341
1342    // odd and even
1343//    size_t pnevlen = adveclen[ipnev], pnodlen=adveclen[ipnod]; // not used
1344
1345    pnev[0] = pnod[0] = p[0] = 0;
1346
1347    ret[0] = s;
1348
1349    for (size_t i = 1; i < adveclen[ip]; ++i) {
1350        ret[i] *= c;
1351    }
1352
1353    //std::cout << (unsigned int) pnev.v << std::endl << pnev << std::endl;
1354    for (TNVND k = 2; k < gnd+1; ++k) {
1355        //std::cout << (unsigned int) p.v << std::endl << p << std::endl;
1356        //std::cout << (unsigned int) pnod.v << std::endl << pnod << std::endl;
1357        //std::cout << (unsigned int) pnev.v << std::endl << pnev << std::endl;
1358        ad_mult(&ip, &ipnod, &ipnev);
1359        //AD<T,nv,nd>::mult(p, pnod, pnev);
1360        //std::cout << (unsigned int) pnev.v << std::endl << pnev << std::endl;
1361      for (size_t i = 0; i < adveclen[ipnev]; ++i) {
1362            pnev[i] /= 1.0*k;
1363            switch(k % 4) {
1364            case 0:
1365                ret[i] += s*pnev[i];
1366                break;
1367            case 1:
1368                ret[i] += c*pnev[i];
1369                break;
1370            case 2:
1371                ret[i] -= s*pnev[i];
1372                break;
1373            case 3:
1374                ret[i] -= c*pnev[i];
1375                break;
1376            }
1377        }
1378        std::swap(ipnev, ipnod);
1379        //std::swap(pnev, pnod);
1380        //std::swap(pnevlen, pnodlen);
1381        pnev = advec[ipnev];
1382        pnod = advec[ipnod];
1383//        pnevlen = adveclen[ipnev]; // not used
1384//        pnodlen = adveclen[ipnod]; // not used
1385    }
1386
1387    adveclen[*iret] = FULL_VEC_LEN;
1388
1389    ad_free(&ip);
1390    ad_free(&ipnod);
1391    ad_free(&ipnev);
1392}
1393
1394
1395#ifdef MSVC_DLL
1396_declspec(dllexport) void _stdcall ad_cos(const TVEC* iv, const TVEC* iret)
1397#else
1398void ad_cos(const TVEC* iv, const TVEC* iret)
1399#endif
1400{
1401    //AD<T,nv,nd> ret(v), pnev(v), pnod(v), p(v);
1402    TVEC ipnev, ipnod, ip;
1403    ad_alloc(&ipnev);
1404    ad_alloc(&ipnod);
1405    ad_alloc(&ip);
1406    ad_copy(iv, iret);
1407    ad_copy(iv, &ipnev);
1408    ad_copy(iv, &ipnod);
1409    ad_copy(iv, &ip);
1410
1411    double *v = advec[*iv];
1412    double *ret = advec[*iret];
1413    double *pnev = advec[ipnev];
1414    double *pnod = advec[ipnod];
1415    double *p = advec[ip];
1416
1417    // TODO: didn't check c = 0.0
1418    double s = std::sin(v[0]);
1419    double c = std::cos(v[0]);
1420
1421    pnev[0] = pnod[0] = p[0] = 0;
1422
1423    ret[0] = c;
1424
1425    size_t plen=adveclen[ip], pnevlen = adveclen[ipnev], pnodlen=adveclen[ipnod];
1426
1427    for (size_t i = 1; i < plen; ++i) {
1428        ret[i] *= -s;
1429    }
1430
1431    //std::cout << (unsigned int) pnev.v << std::endl << pnev << std::endl;
1432    for (TNVND k = 2; k < gnd+1; ++k) {
1433        //std::cout << (unsigned int) p.v << std::endl << p << std::endl;
1434        //std::cout << (unsigned int) pnod.v << std::endl << pnod << std::endl;
1435        //std::cout << (unsigned int) pnev.v << std::endl << pnev << std::endl;
1436        //AD<T,nv,nd>::mult(p, pnod, pnev);
1437        ad_mult(&ip, &ipnod, &ipnev);
1438        //std::cout << (unsigned int) pnev.v << std::endl << pnev << std::endl;
1439      for (size_t i = 0; i < adveclen[ipnev]; ++i) {
1440            pnev[i] /= 1.0*k;
1441            switch(k % 4) {
1442            case 0:
1443                ret[i] += c*pnev[i];
1444                break;
1445            case 1:
1446                ret[i] -= s*pnev[i];
1447                break;
1448            case 2:
1449                ret[i] -= c*pnev[i];
1450                break;
1451            case 3:
1452                ret[i] += s*pnev[i];
1453                break;
1454            }
1455        }
1456        std::swap(ipnev, ipnod);
1457        pnev = advec[ipnev];
1458        pnod = advec[ipnod];
1459        std::swap(pnevlen, pnodlen);
1460    }
1461
1462    adveclen[*iret] = FULL_VEC_LEN;
1463
1464    ad_free(&ip);
1465    ad_free(&ipnod);
1466    ad_free(&ipnev);
1467
1468}
1469
1470#ifdef MSVC_DLL
1471_declspec(dllexport) void _stdcall ad_derivative(const TVEC* iv, unsigned int* expo, const TVEC* iret)
1472#else
1473void ad_derivative(const TVEC* iv, unsigned int* expo, const TVEC* iret)
1474#endif
1475{
1476    TNVND* p = base;
1477    //size_t k = 0;
1478    unsigned int iexpo = *expo;
1479
1480    unsigned int *cef = new unsigned int[gnv];
1481    unsigned int *bv = new unsigned int[gnv];
1482    unsigned int d = 0, jexp;
1483
1484    ad_reset(iret);
1485    advec[*iret][0] = 0;
1486    adveclen[*iret] = 1;
1487
1488    // const part was kept
1489    //if (adveclen[*iv] > 0) {
1490    //    advec[*iret][0] = advec[*iv][0];
1491    //    adveclen[*iret] = 1;
1492    //}
1493
1494    for (size_t i = 0; i < adveclen[*iv]; ++i) {
1495        d = 0;
1496        for (size_t j = 0; j < gnv-1; ++j) {
1497            //std::cout << " " << c[i];
1498            cef[j] = *p - *(p+1);
1499            ++p;
1500            d += cef[j];
1501        }
1502        cef[gnv-1] = *p;
1503        d += *p;
1504        ++p;
1505
1506     #ifdef DEBUG_ALL
1507        for(size_t j=0; j < gnv; ++j) {
1508            std::cout << ' ' << cef[j];
1509        }
1510        std::cout << "  order: " << d << std::endl;
1511     #endif
1512
1513        if (cef[iexpo] <= 0) {
1514            advec[*iret][i] = 0;
1515            continue;
1516        }
1517
1518        jexp = cef[iexpo];
1519
1520        cef[iexpo] -= 1;
1521        --d;
1522
1523     #ifdef DEBUG_ALL
1524        std::cout << " --> ";
1525        for (size_t j = 0; j < gnv; ++j) std::cout << ' ' << cef[j];
1526        std::cout << "  order: " << d << std::endl;
1527     #endif
1528
1529        size_t k = 0;
1530
1531        //std::cout << "order: " << (unsigned int)d << std::endl;
1532        for (size_t j = 0; j < gnv; ++j){
1533            bv[j] = d;
1534            d -= cef[j];
1535            k += H[gnv-j][bv[j]];
1536        }
1537        //std::cout << std::endl;
1538        //std::cout << k << std::endl;
1539
1540        advec[*iret][k] = advec[*iv][i] * 1.0 * jexp;
1541        if (k >= adveclen[*iret]) adveclen[*iret] = k+1;
1542     #ifdef DEBUG_ALL
1543        std::cout << "Set: " << k << ' ' << advec[*iret][k] << "  len: " << adveclen[*iret] << std::endl;
1544     #endif
1545    }
1546
1547    //if (adveclen[*iret] == 0) {
1548    //    adveclen[*iret] = 1;
1549    //    advec[*iret] = 0;
1550    //}
1551
1552    delete []bv;
1553    delete []cef;
1554
1555}
1556
1557//! similar to ad_derivative, but doesn't multiply the exponent part of x_{expo}
1558#ifdef MSVC_DLL
1559_declspec(dllexport) void _stdcall ad_tra(const TVEC* iv, unsigned int* expo, const TVEC* iret)
1560#else
1561void ad_tra(const TVEC* iv, unsigned int* expo, const TVEC* iret)
1562#endif
1563{
1564    TNVND* p = base;
1565    //size_t k = 0;
1566    unsigned int iexpo = *expo;
1567
1568    unsigned int *cef = new unsigned int[gnv];
1569    unsigned int *bv = new unsigned int[gnv];
1570    unsigned int d = 0; // , jexp; not used
1571
1572    ad_reset(iret);
1573    // const part was kept
1574    //if (adveclen[*iv] > 0) {
1575    //    advec[*iret][0] = advec[*iv][0];
1576    //    adveclen[*iret] = 1;
1577    //}
1578
1579    for (size_t i = 0; i < adveclen[*iv]; ++i) {
1580        d = 0;
1581        for (size_t j = 0; j < gnv-1; ++j) {
1582            //std::cout << " " << c[i];
1583            cef[j] = *p - *(p+1);
1584            ++p;
1585            d += cef[j];
1586        }
1587        cef[gnv-1] = *p;
1588        d += *p;
1589        ++p;
1590
1591     #ifdef DEBUG_ALL
1592        for(size_t j=0; j < gnv; ++j) {
1593            std::cout << ' ' << cef[j];
1594        }
1595        std::cout << "  order: " << d << std::endl;
1596     #endif
1597
1598        if (cef[iexpo] <= 0) {
1599            advec[*iret][i] = 0;
1600            continue;
1601        }
1602
1603//        jexp = cef[iexpo]; // not used
1604
1605        cef[iexpo] -= 1;
1606        --d;
1607
1608     #ifdef DEBUG_ALL
1609        std::cout << " --> ";
1610        for (size_t j = 0; j < gnv; ++j) std::cout << ' ' << cef[j];
1611        std::cout << "  order: " << d << std::endl;
1612     #endif
1613
1614        size_t k = 0;
1615
1616        //std::cout << "order: " << (unsigned int)d << std::endl;
1617        for (size_t j = 0; j < gnv; ++j){
1618            bv[j] = d;
1619            d -= cef[j];
1620            k += H[gnv-j][bv[j]];
1621        }
1622        //std::cout << std::endl;
1623        //std::cout << k << std::endl;
1624
1625        advec[*iret][k] = advec[*iv][i];
1626        if (k >= adveclen[*iret]) adveclen[*iret] = k+1;
1627     #ifdef DEBUG_ALL
1628        std::cout << "Set: " << k << ' ' << advec[*iret][k] << "  len: " << adveclen[*iret] << std::endl;
1629     #endif
1630    }
1631
1632    delete []bv;
1633    delete []cef;
1634
1635}
1636
1637#ifdef MSVC_DLL
1638_declspec(dllexport) void _stdcall ad_shift(const TVEC* iv, unsigned int* ishift, const TVEC* iret, const double* eps)
1639#else
1640void ad_shift(const TVEC* iv, unsigned int* ishift, const TVEC* iret, const double* eps)
1641#endif
1642{
1643    double epsv = *eps;
1644    TNVND* p = base;
1645
1646    unsigned int *cef = new unsigned int[gnv];
1647    unsigned int *bv = new unsigned int[gnv];
1648
1649    ad_reset(iret);
1650
1651    if (std::abs(*eps) < std::numeric_limits<double>::min()) {
1652        epsv = std::numeric_limits<double>::min();
1653    } else {
1654        epsv = std::abs(*eps);
1655    }
1656
1657    unsigned int d = 0, k=0;
1658
1659    for (size_t i = 0; i < adveclen[*iv]; ++i) {
1660        if (std::abs(advec[*iv][i]) < epsv) {
1661            p += gnv;
1662            continue;
1663        }
1664
1665        d = k = 0;
1666        for (size_t j = 0; j < gnv-1; ++j) {
1667            //std::cout << " " << c[i];
1668            cef[j] = *p - *(p+1);
1669            ++p;
1670            d += cef[j];
1671        }
1672        cef[gnv-1] = *p;
1673        d += *p;
1674        ++p;
1675
1676        for (size_t j = 0; j < *ishift; ++j) {
1677            k += cef[j];
1678        }
1679
1680        if (k > 0) {
1681            std::cerr << "TPSA: shift a vector, but the first " << *ishift << " components are non-zero" << std::endl;
1682            std::exit(-1);
1683        }
1684
1685        for (size_t j = 0; j < gnv; ++j) {
1686            if (j+*ishift >= gnv)
1687                cef[j] = 0;
1688            else cef[j] = cef[j+*ishift];
1689        }
1690
1691     #ifdef DEBUG_ALL
1692        for(size_t j=0; j < gnv; ++j) {
1693            std::cout << ' ' << cef[j];
1694        }
1695        std::cout << "  order: " << d << std::endl;
1696     #endif
1697
1698     #ifdef DEBUG_ALL
1699        std::cout << " --> ";
1700        for (size_t j = 0; j < gnv; ++j) std::cout << ' ' << cef[j];
1701        std::cout << "  order: " << d << std::endl;
1702     #endif
1703
1704        k = 0;
1705
1706        //std::cout << "order: " << (unsigned int)d << std::endl;
1707        for (size_t j = 0; j < gnv; ++j){
1708            bv[j] = d;
1709            d -= cef[j];
1710            k += H[gnv-j][bv[j]];
1711        }
1712        //std::cout << std::endl;
1713        //std::cout << k << std::endl;
1714
1715        advec[*iret][k] = advec[*iv][i];
1716        if (k >= adveclen[*iret]) adveclen[*iret] = k+1;
1717     #ifdef DEBUG_ALL
1718        std::cout << "Set: " << k << ' ' << advec[*iret][k] << "  len: " << adveclen[*iret] << std::endl;
1719     #endif
1720    }
1721
1722    delete []bv;
1723    delete []cef;
1724
1725}
1726
1727#ifdef MSVC_DLL
1728_declspec(dllexport) void _stdcall ad_subst(const TVEC* iv, const TVEC* ibv, const TNVND* nbv, const TVEC* iret)
1729#else
1730void ad_subst(const TVEC* iv, const TVEC* ibv, const TNVND* nbv, const TVEC* iret)
1731#endif
1732{
1733  (void)nbv; // ldeniau 2011.11.04: avoid g++ warning
1734 
1735 #ifdef DEBUG_ALL
1736    std::cout << "AD substitute " << std::endl;
1737    std::cout << "  ia[" << adveclen[*iv] << "]:" << *iv
1738              << " ret:" << *iret << " " << *nbv << std::endl;
1739    for(size_t i = 0; i < *nbv; ++i) {
1740        std::cout << " ib  " << i << "  " << ibv[i]
1741                  << "  len=" << adveclen[ibv[i]] << std::endl;
1742    }
1743 #endif
1744
1745 #ifdef DEBUG_ALL
1746    std::cout << "v before subst " << std::endl;
1747    ad_print(iv);
1748    //std::cout << "ib be new var" << std::endl;
1749    //for (size_t i = 0; i < *nbv; ++i)
1750    //    ad_print(&ibv[i]);
1751 #endif
1752
1753    ad_reset(iret);
1754    TVEC it1, it2;
1755    ad_alloc(&it1);
1756    ad_alloc(&it2);
1757    TNVND* pb = base;
1758    double* pv1 = advec[it1];
1759    //double* pv2 = advec[it2];
1760    // loop every entry(monimial)
1761    for(size_t i = 0; i < adveclen[*iv]; ++i) {
1762        // only problem of this "== 0" would be(if any) is the speed.
1763        //if (advec[*iv][i] == 0) {
1764        if (std::abs(advec[*iv][i]) < std::numeric_limits<double>::min()) {
1765            pb += gnv;
1766            continue;
1767        }
1768
1769     #ifdef DEBUG_ALL
1770        std::cout << " base " << i << " : " << *pb << " : ";
1771     #endif
1772
1773
1774        // loop over every konob(base vector), nvb == gnv
1775        ad_reset(&it1);
1776        ad_reset(&it2);
1777
1778        pv1[0] = advec[*iv][i];
1779        adveclen[it1] = 1;
1780        for(size_t j = 0; j < gnv; ++j) {
1781            TNVND ord = *(pb+j);
1782            if (j < gnv-1) ord -= *(pb+j+1);
1783         #ifdef DEBUG_ALL
1784            std::cout << ' ' << ord;
1785         #endif
1786            if (ord == 0) continue;
1787            //ad_copy(ibv+j, &it1);
1788            for (TNVND k = 0; k < ord; ++k) {
1789                ad_mult(ibv+j, &it1, &it2);
1790                ad_copy(&it2, &it1);
1791            }
1792        }
1793        //
1794        ad_add(iret, &it1);
1795     #ifdef DEBUG_ALL
1796        std::cout << std::endl;
1797     #endif
1798        pb += gnv;
1799    }
1800    ad_free(&it1);
1801    ad_free(&it2);
1802}
1803
1804#ifdef MSVC_DLL
1805_declspec(dllexport) void _stdcall ad_inverse(const TVEC* iva, const TNVND* nva, const TVEC* iret, const TNVND* nret)
1806#else
1807void ad_inverse(const TVEC* iva, const TNVND* nva, const TVEC* iret, const TNVND* nret)
1808#endif
1809{
1810  (void)iva; (void)nva; (void)iret; (void)nret; // ldeniau 2011.11.04: avoid g++ warnings
1811
1812 #ifdef DEBUG_ALL
1813    std::cout << "AD inverse " << std::endl;
1814    for(size_t i = 0; i < *nva; ++i) {
1815        std::cout << " iv  " << i << "  " << iva[i] << "  " << iret[i] << std::endl;
1816        ad_print(&iva[i]);
1817    }
1818 #endif
1819
1820 #ifdef T
1821    for (TNVND i = 0; i < *nret; ++i) {
1822        ad_const(&iret[i], 0);
1823    }
1824
1825    TVEC* ms = new TVEC[*nret];
1826    TVEC* ml = new TVEC[*nret];
1827    TNVND* J = new TNVND[gnv];
1828
1829    for(size_t i = 0; i < *nret; ++i) {
1830        ad_alloc(&ms[i]);
1831        ad_alloc(&ml[i]);
1832    }
1833
1834    double vjj;
1835
1836    for(size_t i = 0; i < *nret; ++i) {
1837        for (size_t j = 0; j < *nret; ++j) {
1838            for (size_t k = 0; k < gnv; ++k)
1839                J[k] = 0;
1840            J[j] = 1;
1841            ad_pek(&iva[i], J, &vjj);
1842            if (std::abs(vjj) > 1e-10) ad_pok(&iva[i], J, gnv, 0);
1843            //save vjj for inverse.
1844            if (j!=i){
1845                ad_pok(&ms[i], J, &gnv, 0.);
1846                ad_pok(&ml[i], J, &gnv, 0.);
1847            }else {
1848                ad_pok(&ms[i], J, &gnv, 1.);
1849                ad_pok(&ml[i], J, &gnv, 1.);
1850            }
1851        }
1852        //ad_print(&ms[i]);
1853        //ad_print(&ml[i]);
1854        ad_mult_const(&iva[i], -1.0);
1855    }
1856 #endif
1857
1858 #ifdef OLD
1859    // loop gnd order.
1860    for (size_t iord = 1; iord < gnd; ++iord) {
1861        for(size_t i = 0; i < *nret; ++i) {
1862            ad_copy(&vt[i], &vdt[i]);
1863            // clear the constant part and linear.
1864            for (size_t k = 0; k < gnv+1; ++k) {
1865                advec[vdt[i]][k] = 0;
1866            }
1867         #ifdef DEBUG_ALL
1868            std::cout << "vdt  " << i << std::endl;
1869            ad_print(&vdt[i]);
1870         #endif
1871        }
1872        for(size_t i = 0; i < *nret; ++i) {
1873            // clear the constant part and linear.
1874            ad_copy(&vI[i], &vImdt[i]);
1875            ad_sub(&vImdt[i], &vdt[i]);
1876        }
1877
1878        // now vI and vdt is ready
1879        for (size_t i = 0; i < *nret; ++i) {
1880            ad_subst(&vt[i], vImdt, nret, &vt1[i]);
1881
1882         #ifdef DEBUG_ALL
1883            std::cout << "vt1 after subst " << i << std::endl;
1884            ad_print(&vt1[i]);
1885         #endif
1886
1887        }
1888        for (size_t i = 0; i < *nret; ++i) {
1889            ad_copy(&vt1[i], &vt[i]);
1890        }
1891
1892        for (size_t i = 0; i < *nret; ++i) {
1893            ad_subst(&iret[i], vImdt, nret, &vt1[i]);
1894        }
1895        for (size_t i = 0; i < *nret; ++i) {
1896            ad_copy(&vt1[i], &iret[i]);
1897        }
1898     #ifdef DEBUG_ALL
1899        std::cout << "So far the result " << std::endl;
1900        for (size_t i = 0; i < *nret; ++i)
1901            ad_print(&iret[i]);
1902     #endif
1903    }
1904
1905    for(size_t i = 0; i < *nret; ++i) {
1906        ad_free(&vt[i]);
1907        ad_free(&vt1[i]);
1908        ad_free(&vI[i]);
1909        ad_free(&vdt[i]);
1910        ad_free(&vImdt[i]);
1911    }
1912 #endif
1913
1914 #ifdef T
1915    for(size_t i = 0; i < *nret; ++i) {
1916        ad_free(&ml[i]);
1917        ad_free(&ms[i]);
1918    }
1919 #endif
1920}
1921
1922#ifdef MSVC_DLL
1923_declspec(dllexport) void _stdcall ad_nvar(TVEC* n)
1924#else
1925void ad_nvar(TVEC* n)
1926#endif
1927{
1928    *n = gnv;
1929}
1930
1931#ifdef MSVC_DLL
1932_declspec(dllexport) void _stdcall ad_length(const TVEC* iv, unsigned int* n)
1933#else
1934void ad_length(const TVEC* iv, unsigned int* n)
1935#endif
1936{
1937    *n = adveclen[*iv];
1938}
1939
1940#ifdef MSVC_DLL
1941_declspec(dllexport) void _stdcall ad_read_block(const TVEC* iv,
1942                                                 double* v, TNVND* J, const unsigned int* N)
1943#else
1944void ad_read_block(const TVEC* iv,
1945                   double* v, TNVND* J, const unsigned int* N)
1946#endif
1947{
1948    //unsigned int ii = *iv;
1949    if (*N < adveclen[*iv]) {
1950        for(size_t i = 0; i < *N; ++i) {
1951            v[i] = 0;
1952            for (size_t j = 0; j < gnv; ++j) {
1953                J[i*gnv+j] = 0;
1954            }
1955        }
1956        return;
1957    }
1958
1959    TNVND* p = base;
1960    //os << "iv= " << ii << std::endl;
1961    //std::cout << "Len: " << *N << ' ' << adveclen[*iv] << std::endl;
1962    for (size_t i = 0; i < adveclen[*iv]; ++i) {
1963        v[i] = advec[*iv][i];
1964        for (size_t j = 0; j < gnv-1; ++j) {
1965            J[i*gnv+j] = (unsigned int)(*p-*(p+1));
1966            //std::cout << ' ' << J[i*gnv+j];
1967            //std::cout << ' ' << *p;
1968            ++p;
1969        }
1970        //std::cout << ' ' << *p << ' ' << &(J[gnv-1][i]) << std::endl;
1971        J[i*gnv+gnv-1] = *p;
1972        ++p;
1973        //std::cout << ' ' << v[i];
1974    }
1975
1976    //std::cout << std::endl;
1977
1978 #ifdef DEBUG_ALL
1979    std::cout << std::endl;
1980    for (size_t i = 0; i < adveclen[*iv]*gnv; ++i) {
1981        std::cout << ' ' << J[i];
1982        if (i % gnv == gnv-1) std::cout << std::endl;
1983    }
1984    //std::cout << "min: " << std::numeric_limits<double>::min() << std::endl;
1985    //std::cout << "eps: " << std::numeric_limits<double>::epsilon() << std::endl;
1986 #endif
1987}
1988
1989//! blind set, assuming order of J is right.
1990#ifdef MSVC_DLL
1991_declspec(dllexport) void _stdcall ad_save_block(const TVEC* iv,
1992                                                 const double* v, const TNVND* J, const unsigned int* N)
1993#else
1994void ad_save_block(const TVEC* iv, const double* v, const TNVND* J, const unsigned int* N)
1995#endif
1996{
1997    (void)J; // ldeniau 2011.11.04: avoid g++ warning
1998
1999    //unsigned int ii = *iv;
2000    //TNVND* p = base;
2001    //os << "iv= " << ii << std::endl;
2002    adveclen[*iv] = *N;
2003
2004    for (size_t i = 0; i < *N; ++i) {
2005        advec[*iv][i] = v[i] ;
2006        //for (size_t j = 0; j < gnv-1; ++j) {
2007        //    J[i][j] = (*p-*(p+1));
2008        //    ++p;
2009        //}
2010    }
2011
2012 #ifdef DEBUG_ALL
2013    //std::cout << "min: " << std::numeric_limits<double>::min() << std::endl;
2014    //std::cout << "eps: " << std::numeric_limits<double>::epsilon() << std::endl;
2015 #endif
2016}
2017
2018//! Print out ad vector represented by i
2019#ifdef MSVC_DLL
2020_declspec(dllexport) void _stdcall print_index(std::ostream& os)
2021#else
2022void print_index(std::ostream& os)
2023#endif
2024{
2025    int width_idx=6, width_elem = 3;
2026    if (FULL_VEC_LEN < 100) width_elem = 3;
2027    else width_elem = 4;
2028
2029    os << std::setw(width_idx+width_elem-2) << "Index";
2030    for (size_t i = 1; i < gnv; ++i) {
2031        for (size_t j = order_index[i]; j < order_index[i+1]; ++j)
2032            os << std::setw(width_elem) << j;
2033        if (i < gnv-1) os << " .";
2034    }
2035    os << std::endl;
2036
2037    os << std::setw(width_idx) << ' ';
2038    for (size_t i = 0; i < width_elem*order_index[gnv]; ++i) {
2039        os << '_';
2040    }
2041    os << std::endl;
2042
2043    TNVND ord = 1;
2044    for (size_t i = 1; i < order_index[gnd]; ++i) {
2045        if (order_index[ord+1] <= i) ++ord;
2046        unsigned int M = order_index[gnd-ord+1];
2047        os << std::setw(width_idx) << i << ' ';
2048
2049        size_t k = 2;
2050
2051        for (size_t j = 1; j < M; ++j) {
2052            if (j == order_index[k]) {
2053                os << " .";
2054                ++k;
2055            }
2056            os << std::setw(width_elem) << prdidx[i][j];
2057        }
2058        std::cout << std::endl;
2059    }
2060
2061}
2062
2063void print_vec(unsigned int ii, std::ostream& os)
2064{
2065    //unsigned int ii = *iv;
2066    TNVND* p = base;
2067    //os << "iv= " << ii << std::endl;
2068
2069    std::ios::fmtflags prevflags = os.flags();
2070    double* v = advec[ii];
2071
2072    int width_base = 2;
2073    if (gnd > static_cast<TNVND>(9))  ++width_base;
2074
2075    os << "          V [" << ii << "]              Base  [ "
2076       << adveclen[ii] << " / " << FULL_VEC_LEN << " ]" << std::endl
2077       << "----------------------------------------------" << std::endl;
2078    for (size_t i = 0; i < adveclen[ii]; ++i) {
2079        if (std::abs(v[i]) < std::numeric_limits<double>::min()) {
2080            p += gnv;
2081            continue;
2082        }
2083        os << ' ' << std::setprecision(15)
2084           << std::scientific << std::setw(15+8) << v[i] << "    ";
2085        for (size_t j = 0; j < gnv-1; ++j) {
2086            os << std::setw(width_base) << (unsigned int) (*p-*(p+1));
2087            ++p;
2088        }
2089        os << std::setw(width_base) << (unsigned int)*p++ << std::setw(6) << i << std::endl;
2090    }
2091    os << std::endl;
2092
2093    os.flags(prevflags);
2094
2095 #ifdef DEBUG_ALL
2096    //std::cout << "min: " << std::numeric_limits<double>::min() << std::endl;
2097    //std::cout << "eps: " << std::numeric_limits<double>::epsilon() << std::endl;
2098 #endif
2099}
2100
2101
2102#ifdef MSVC_DLL
2103_declspec(dllexport) void _stdcall ad_print(const TVEC* iv)
2104#else
2105void ad_print(const unsigned int* iv)
2106#endif
2107{
2108    print_vec(*iv, std::cout);
2109}
2110
2111#ifdef MSVC_DLL
2112_declspec(dllexport) void _stdcall ad_print_array(const TVEC* iv, const TVEC* nv)
2113#else
2114void ad_print_array(const TVEC* iv, const TVEC* nv)
2115#endif
2116{
2117    std::ostream& os = std::cout;
2118    //unsigned int ii = *iv;
2119    //TNVND* p = base;
2120    //os << "iv= " << ii << std::endl;
2121 #ifdef V_BY_V
2122    // vector by vector, each vector one line
2123    std::ios::fmtflags prevflags = os.flags();
2124    double* v;
2125    double x;
2126
2127    int width_base = 2;
2128    if (gnd > static_cast<TNVND>(9))  ++width_base;
2129    os << "    const.  |    linear " << std::endl;
2130    for (size_t i = 0; i < *nv; ++i) {
2131        v = advec[iv[i]];
2132        for (size_t j = 0; j < gnv+1; ++j) {
2133            if (j < adveclen[iv[i]]) x = v[j];
2134            else x = 0;
2135
2136            os << ' ' << std::setprecision(3)
2137               << std::scientific << std::setw(3+7) << x;
2138            if (j==0) os << " |";
2139        }
2140        os << std::endl;
2141    }
2142
2143    os.flags(prevflags);
2144 #endif
2145
2146    //unsigned int ii = *iv;
2147    TNVND* p = base;
2148    //os << "iv= " << ii << std::endl;
2149    const char* s = "          ";
2150    std::ios::fmtflags prevflags = os.flags();
2151    double* v;
2152    double xm = 0.0;
2153
2154    int width_base = 2;
2155    if (gnd > static_cast<TNVND>(9))  ++width_base;
2156
2157    std::cout << "# min: " << std::numeric_limits<double>::min() << std::endl;
2158    std::cout << "# eps: " << std::numeric_limits<double>::epsilon() << std::endl;
2159    os << "          V              Base  [ "
2160       << " / " << FULL_VEC_LEN << " ]" << std::endl
2161       << "----------------------------------------------" << std::endl;
2162    for (size_t i = 0; i < adveclen[*iv]; ++i) {
2163        for (size_t j = 0; j < *nv; ++j) {
2164            v = advec[iv[j]];
2165            double x = v[i];
2166            if (std::abs(x) > xm && std::abs(x) < 1)  xm =  std::abs(x);
2167            if (std::abs(x) < std::numeric_limits<double>::epsilon()){
2168                x = 0;
2169                os << ' ' << s;
2170            } else {
2171                os << ' ' << std::setprecision(3)
2172                   << std::scientific << std::setw(3+7) << x;
2173            }
2174        }
2175        os << "   ";
2176        for (size_t j = 0; j < gnv-1; ++j) {
2177            os << std::setw(width_base) << (unsigned int) (*p-*(p+1));
2178            ++p;
2179        }
2180        os << std::setw(width_base) << (unsigned int)*p++ << std::setw(6) << i << std::endl;
2181    }
2182    os << std::endl;
2183    os << "# abs(max in [0,1))= " << xm << std::endl;
2184    os.flags(prevflags);
2185
2186 #ifdef DEBUG_ALL
2187 #endif
2188}
2189
2190#ifdef MSVC_DLL
2191#define DLL_PROCESS_DETACH 0
2192#define DLL_PROCESS_ATTACH 1
2193extern "C" unsigned long __stdcall DllEntryPoint(void *hDll, unsigned long Reason, void *Reserved)
2194{
2195    if (Reason == DLL_PROCESS_ATTACH)
2196    {
2197        /*perform DLL initialization tasks here*/
2198    }
2199    return (1);
2200}
2201#endif
Note: See TracBrowser for help on using the repository browser.