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 | |
---|
24 | static unsigned int comb_num(unsigned int n, unsigned int r); |
---|
25 | static unsigned int gcd(unsigned int a, unsigned int b); |
---|
26 | static void init_order_index(unsigned int nv, unsigned int nd); |
---|
27 | static void init_prod_index(unsigned int nv, unsigned int nd); |
---|
28 | static bool within_limit(TNVND nv, TNVND nd); |
---|
29 | static TNVND* choose(TNVND n, TNVND r, TNVND* p, TNVND nv, TNVND nd); |
---|
30 | static void init_base(TNVND nv, TNVND nd); |
---|
31 | static 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). |
---|
38 | static const unsigned int MAX_N_BASE = |
---|
39 | std::numeric_limits<unsigned int>::max()/2; |
---|
40 | |
---|
41 | //! global nv, nd |
---|
42 | static TNVND gnv, gnd; |
---|
43 | |
---|
44 | //! C(nv+nd, nd) |
---|
45 | static unsigned int FULL_VEC_LEN; |
---|
46 | |
---|
47 | //! Automatic Differentiation |
---|
48 | //! starting index of elements with certain orders. |
---|
49 | static unsigned int* order_index; |
---|
50 | |
---|
51 | |
---|
52 | static 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. |
---|
57 | static TNVND *base; |
---|
58 | static unsigned int** prdidx; // index of product |
---|
59 | static TNVND nvec; // number of vec assigned. |
---|
60 | static TNVND* vec; // vec initialized. |
---|
61 | // static unsigned int tblsize; // not used |
---|
62 | |
---|
63 | // memory pool |
---|
64 | static double **advecpool; |
---|
65 | static std::vector<double*> advec; |
---|
66 | static std::vector<unsigned int> adveclen; |
---|
67 | |
---|
68 | |
---|
69 | using namespace std; |
---|
70 | |
---|
71 | //! Greatest Common Divisor, Euclidean algorithm. |
---|
72 | unsigned 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 |
---|
95 | unsigned 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 |
---|
162 | void 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 |
---|
176 | void 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 |
---|
258 | void 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. |
---|
282 | bool 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. |
---|
297 | TNVND* 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 | // |
---|
351 | void 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 |
---|
397 | extern "C" _declspec(dllexport) void _stdcall ad_init(const TNVND* nvar, const TNVND* nord) |
---|
398 | #else |
---|
399 | void 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 |
---|
442 | void 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 |
---|
463 | void 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 |
---|
507 | void 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 |
---|
525 | void 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 |
---|
546 | void 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 |
---|
559 | void 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 |
---|
577 | void 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 |
---|
597 | void 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 |
---|
614 | void 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 |
---|
669 | void 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 |
---|
695 | void 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 |
---|
751 | void 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 |
---|
809 | void 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 |
---|
823 | void 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 |
---|
837 | void 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 |
---|
868 | void 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 |
---|
877 | void 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 |
---|
917 | void 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 |
---|
989 | void 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 |
---|
1003 | void 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 |
---|
1019 | void 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 |
---|
1093 | void 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 |
---|
1133 | void 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 |
---|
1178 | void 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 |
---|
1235 | void 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 |
---|
1295 | void 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 |
---|
1311 | void 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 |
---|
1398 | void 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 |
---|
1473 | void 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 |
---|
1561 | void 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 |
---|
1640 | void 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 |
---|
1730 | void 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 |
---|
1807 | void 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 |
---|
1925 | void 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 |
---|
1934 | void 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 |
---|
1944 | void 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 |
---|
1994 | void 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 |
---|
2022 | void 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 | |
---|
2063 | void 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 |
---|
2105 | void 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 |
---|
2114 | void 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 |
---|
2193 | extern "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 |
---|