Xmipp  v3.23.11-Nereus
ap.cpp
Go to the documentation of this file.
1 /*************************************************************************
2 Copyright (c) Sergey Bochkanov (ALGLIB project).
3 
4 >>> SOURCE LICENSE >>>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation (www.fsf.org); either version 2 of the
8 License, or (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 A copy of the GNU General Public License is available at
16 http://www.fsf.org/licensing/licenses
17 >>> END OF LICENSE >>>
18 *************************************************************************/
19 #include "stdafx.h"
20 #include "ap.h"
21 #include <limits>
22 #include <locale.h>
23 using namespace std;
24 
25 #if defined(AE_CPU)
26 #if (AE_CPU==AE_INTEL)
27 
28 #if AE_COMPILER==AE_MSVC
29 #include <intrin.h>
30 #endif
31 
32 #endif
33 #endif
34 
35 // disable some irrelevant warnings
36 #if (AE_COMPILER==AE_MSVC)
37 #pragma warning(disable:4100)
38 #pragma warning(disable:4127)
39 #pragma warning(disable:4702)
40 #pragma warning(disable:4996)
41 #endif
42 
44 //
45 // THIS SECTION IMPLEMENTS BASIC FUNCTIONALITY LIKE
46 // MEMORY MANAGEMENT FOR VECTORS/MATRICES WHICH IS
47 // SHARED BETWEEN C++ AND PURE C LIBRARIES
48 //
50 namespace alglib_impl
51 {
52 /*
53  * local definitions
54  */
55 #define x_nb 16
56 #define AE_DATA_ALIGN 16
57 #define AE_PTR_ALIGN sizeof(void*)
58 #define DYN_BOTTOM ((void*)1)
59 #define DYN_FRAME ((void*)2)
60 #define AE_LITTLE_ENDIAN 1
61 #define AE_BIG_ENDIAN 2
62 #define AE_MIXED_ENDIAN 3
63 #define AE_SER_ENTRY_LENGTH 11
64 #define AE_SER_ENTRIES_PER_ROW 5
65 
66 #define AE_SM_DEFAULT 0
67 #define AE_SM_ALLOC 1
68 #define AE_SM_READY2S 2
69 #define AE_SM_TO_STRING 10
70 #define AE_SM_FROM_STRING 20
71 #define AE_SM_TO_CPPSTRING 11
72 
73 #define AE_LOCK_CYCLES 512
74 #define AE_LOCK_TESTS_BEFORE_YIELD 16
75 #define AE_CRITICAL_ASSERT(x) if( !(x) ) abort()
76 
77 
78 /*
79  * alloc counter (if used)
80  */
81 #ifdef AE_USE_ALLOC_COUNTER
82 ae_int64_t _alloc_counter = 0;
83 #endif
84 #ifdef AE_DEBUGRNG
85 static ae_int_t _debug_rng_s0 = 11;
86 static ae_int_t _debug_rng_s1 = 13;
87 #endif
88 #ifdef AE_SMP_DEBUGCOUNTERS
89 __declspec(align(AE_LOCK_ALIGNMENT)) volatile ae_int64_t _ae_dbg_lock_acquisitions = 0;
90 __declspec(align(AE_LOCK_ALIGNMENT)) volatile ae_int64_t _ae_dbg_lock_spinwaits = 0;
91 __declspec(align(AE_LOCK_ALIGNMENT)) volatile ae_int64_t _ae_dbg_lock_yields = 0;
92 #endif
93 
94 /*
95  * These declarations are used to ensure that
96  * sizeof(ae_int32_t)==4, sizeof(ae_int64_t)==8, sizeof(ae_int_t)==sizeof(void*).
97  * they will lead to syntax error otherwise (array size will be negative).
98  *
99  * you can remove them, if you want - they are not used anywhere.
100  *
101  */
102 static char _ae_int32_t_must_be_32_bits_wide[1-2*((int)(sizeof(ae_int32_t))-4)*((int)(sizeof(ae_int32_t))-4)];
103 static char _ae_int64_t_must_be_64_bits_wide[1-2*((int)(sizeof(ae_int64_t))-8)*((int)(sizeof(ae_int64_t))-8)];
104 static char _ae_int_t_must_be_pointer_sized [1-2*((int)(sizeof(ae_int_t))-(int)sizeof(void*))*((int)(sizeof(ae_int_t))-(int)(sizeof(void*)))];
105 
106 /*
107  * This variable is used to prevent some tricky optimizations which may degrade multithreaded performance.
108  * It is touched once in the ae_init_pool() function from smp.c in order to prevent optimizations.
109  *
110  */
111 static volatile ae_int_t ae_never_change_it = 1;
112 
113 ae_int_t ae_misalignment(const void *ptr, size_t alignment)
114 {
115  union _u
116  {
117  const void *ptr;
118  ae_int_t iptr;
119  } u;
120  u.ptr = ptr;
121  return (ae_int_t)(u.iptr%alignment);
122 }
123 
124 void* ae_align(void *ptr, size_t alignment)
125 {
126  char *result = (char*)ptr;
127  if( (result-(char*)0)%alignment!=0 )
128  result += alignment - (result-(char*)0)%alignment;
129  return result;
130 }
131 
132 void ae_break(ae_state *state, ae_error_type error_type, const char *msg)
133 {
134 #ifndef AE_USE_CPP_ERROR_HANDLING
135  if( state!=NULL )
136  {
137  if( state->thread_exception_handler!=NULL )
138  state->thread_exception_handler(state);
139  ae_state_clear(state);
140  state->last_error = error_type;
141  state->error_msg = msg;
142  if( state->break_jump!=NULL )
143  longjmp(*(state->break_jump), 1);
144  else
145  abort();
146  }
147  else
148  abort();
149 #else
150  if( state!=NULL )
151  {
152  if( state->thread_exception_handler!=NULL )
153  state->thread_exception_handler(state);
154  ae_state_clear(state);
155  state->last_error = error_type;
156  state->error_msg = msg;
157  }
158  throw error_type;
159 #endif
160 }
161 
162 void* aligned_malloc(size_t size, size_t alignment)
163 {
164  if( size==0 )
165  return NULL;
166  if( alignment<=1 )
167  {
168  /* no alignment, just call malloc */
169  void *block;
170  void **p; ;
171  block = malloc(sizeof(void*)+size);
172  if( block==NULL )
173  return NULL;
174  p = (void**)block;
175  *p = block;
176 #ifdef AE_USE_ALLOC_COUNTER
177  _alloc_counter++;
178 #endif
179  return (void*)((char*)block+sizeof(void*));
180  }
181  else
182  {
183  /* align */
184  void *block;
185  char *result;
186  block = malloc(alignment-1+sizeof(void*)+size);
187  if( block==NULL )
188  return NULL;
189  result = (char*)block+sizeof(void*);
190  /*if( (result-(char*)0)%alignment!=0 )
191  result += alignment - (result-(char*)0)%alignment;*/
192  result = (char*)ae_align(result, alignment);
193  *((void**)(result-sizeof(void*))) = block;
194 #ifdef AE_USE_ALLOC_COUNTER
195  _alloc_counter++;
196 #endif
197  return result;
198  }
199 }
200 
201 void aligned_free(void *block)
202 {
203  void *p;
204  if( block==NULL )
205  return;
206  p = *((void**)((char*)block-sizeof(void*)));
207  free(p);
208 #ifdef AE_USE_ALLOC_COUNTER
209  _alloc_counter--;
210 #endif
211 }
212 
213 /************************************************************************
214 Malloc's memory with automatic alignment.
215 
216 Returns NULL when zero size is specified.
217 
218 Error handling:
219 * if state is NULL, returns NULL on allocation error
220 * if state is not NULL, calls ae_break() on allocation error
221 ************************************************************************/
222 void* ae_malloc(size_t size, ae_state *state)
223 {
224  void *result;
225  if( size==0 )
226  return NULL;
227  result = aligned_malloc(size,AE_DATA_ALIGN);
228  if( result==NULL && state!=NULL)
229  {
230  char buf[256];
231  sprintf(buf, "ae_malloc(): out of memory (attempted to allocate %llu bytes)", (unsigned long long)size);
232  ae_break(state, ERR_OUT_OF_MEMORY, buf);
233  }
234  return result;
235 }
236 
237 void ae_free(void *p)
238 {
239  if( p!=NULL )
240  aligned_free(p);
241 }
242 
243 /************************************************************************
244 Sets pointers to the matrix rows.
245 
246 * dst must be correctly initialized matrix
247 * dst->data.ptr points to the beginning of memory block allocated for
248  row pointers.
249 * dst->ptr - undefined (initialized during algorithm processing)
250 * storage parameter points to the beginning of actual storage
251 ************************************************************************/
252 void ae_matrix_update_row_pointers(ae_matrix *dst, void *storage)
253 {
254  char *p_base;
255  void **pp_ptr;
256  ae_int_t i;
257  if( dst->rows>0 && dst->cols>0 )
258  {
259  p_base = (char*)storage;
260  pp_ptr = (void**)dst->data.ptr;
261  dst->ptr.pp_void = pp_ptr;
262  for(i=0; i<dst->rows; i++, p_base+=dst->stride*ae_sizeof(dst->datatype))
263  pp_ptr[i] = p_base;
264  }
265  else
266  dst->ptr.pp_void = NULL;
267 }
268 
269 /************************************************************************
270 Returns size of datatype.
271 Zero for dynamic types like strings or multiple precision types.
272 ************************************************************************/
274 {
275  switch(datatype)
276  {
277  case DT_BOOL: return (ae_int_t)sizeof(ae_bool);
278  case DT_INT: return (ae_int_t)sizeof(ae_int_t);
279  case DT_REAL: return (ae_int_t)sizeof(double);
280  case DT_COMPLEX: return 2*(ae_int_t)sizeof(double);
281  default: return 0;
282  }
283 }
284 
285 
286 /************************************************************************
287 This dummy function is used to prevent compiler messages about unused
288 locals in automatically generated code.
289 
290 It makes nothing - just accepts pointer, "touches" it - and that is all.
291 It performs several tricky operations without side effects which confuse
292 compiler so it does not compain about unused locals in THIS function.
293 ************************************************************************/
294 void ae_touch_ptr(void *p)
295 {
296  void * volatile fake_variable0 = p;
297  void * volatile fake_variable1 = fake_variable0;
298  fake_variable0 = fake_variable1;
299 }
300 
301 /************************************************************************
302 This function initializes ALGLIB environment state.
303 
304 NOTES:
305 * stacks contain no frames, so ae_make_frame() must be called before
306  attaching dynamic blocks. Without it ae_leave_frame() will cycle
307  forever (which is intended behavior).
308 ************************************************************************/
310 {
311  ae_int32_t *vp;
312 
313  /*
314  * p_next points to itself because:
315  * * correct program should be able to detect end of the list
316  * by looking at the ptr field.
317  * * NULL p_next may be used to distinguish automatic blocks
318  * (in the list) from non-automatic (not in the list)
319  */
320  state->last_block.p_next = &(state->last_block);
321  state->last_block.deallocator = NULL;
322  state->last_block.ptr = DYN_BOTTOM;
323  state->p_top_block = &(state->last_block);
324 #ifndef AE_USE_CPP_ERROR_HANDLING
325  state->break_jump = NULL;
326 #endif
327  state->error_msg = "";
328 
329  /*
330  * determine endianness and initialize precomputed IEEE special quantities.
331  */
332  state->endianness = ae_get_endianness();
333  if( state->endianness==AE_LITTLE_ENDIAN )
334  {
335  vp = (ae_int32_t*)(&state->v_nan);
336  vp[0] = 0;
337  vp[1] = (ae_int32_t)0x7FF80000;
338  vp = (ae_int32_t*)(&state->v_posinf);
339  vp[0] = 0;
340  vp[1] = (ae_int32_t)0x7FF00000;
341  vp = (ae_int32_t*)(&state->v_neginf);
342  vp[0] = 0;
343  vp[1] = (ae_int32_t)0xFFF00000;
344  }
345  else if( state->endianness==AE_BIG_ENDIAN )
346  {
347  vp = (ae_int32_t*)(&state->v_nan);
348  vp[1] = 0;
349  vp[0] = (ae_int32_t)0x7FF80000;
350  vp = (ae_int32_t*)(&state->v_posinf);
351  vp[1] = 0;
352  vp[0] = (ae_int32_t)0x7FF00000;
353  vp = (ae_int32_t*)(&state->v_neginf);
354  vp[1] = 0;
355  vp[0] = (ae_int32_t)0xFFF00000;
356  }
357  else
358  abort();
359 
360  /*
361  * set threading information
362  */
363  state->worker_thread = NULL;
364  state->parent_task = NULL;
365  state->thread_exception_handler = NULL;
366 }
367 
368 
369 /************************************************************************
370 This function clears ALGLIB environment state.
371 All dynamic data controlled by state are freed.
372 ************************************************************************/
374 {
375  while( state->p_top_block->ptr!=DYN_BOTTOM )
376  ae_frame_leave(state);
377 }
378 
379 
380 #ifndef AE_USE_CPP_ERROR_HANDLING
381 /************************************************************************
382 This function sets jump buffer for error handling.
383 
384 buf may be NULL.
385 ************************************************************************/
386 void ae_state_set_break_jump(ae_state *state, jmp_buf *buf)
387 {
388  state->break_jump = buf;
389 }
390 #endif
391 
392 
393 /************************************************************************
394 This function makes new stack frame.
395 
396 This function takes two parameters: environment state and pointer to the
397 dynamic block which will be used as indicator of the frame beginning.
398 This dynamic block must be initialized by caller and mustn't be changed/
399 deallocated/reused till ae_leave_frame called. It may be global or local
400 variable (local is even better).
401 ************************************************************************/
402 void ae_frame_make(ae_state *state, ae_frame *tmp)
403 {
404  tmp->db_marker.p_next = state->p_top_block;
405  tmp->db_marker.deallocator = NULL;
406  tmp->db_marker.ptr = DYN_FRAME;
407  state->p_top_block = &tmp->db_marker;
408 }
409 
410 
411 /************************************************************************
412 This function leaves current stack frame and deallocates all automatic
413 dynamic blocks which were attached to this frame.
414 ************************************************************************/
416 {
417  while( state->p_top_block->ptr!=DYN_FRAME && state->p_top_block->ptr!=DYN_BOTTOM)
418  {
419  if( state->p_top_block->ptr!=NULL && state->p_top_block->deallocator!=NULL)
420  ((ae_deallocator)(state->p_top_block->deallocator))(state->p_top_block->ptr);
421  state->p_top_block = state->p_top_block->p_next;
422  }
423  state->p_top_block = state->p_top_block->p_next;
424 }
425 
426 
427 /************************************************************************
428 This function attaches block to the dynamic block list
429 
430 block block
431 state ALGLIB environment state
432 
433 NOTES:
434 * never call it for special blocks which marks frame boundaries!
435 ************************************************************************/
436 void ae_db_attach(ae_dyn_block *block, ae_state *state)
437 {
438  block->p_next = state->p_top_block;
439  state->p_top_block = block;
440 }
441 
442 
443 /************************************************************************
444 This function malloc's dynamic block:
445 
446 block destination block, assumed to be uninitialized
447 size size (in bytes)
448 state ALGLIB environment state. May be NULL.
449 make_automatic if true, vector is added to the dynamic block list
450 
451 block is assumed to be uninitialized, its fields are ignored.
452 
453 Error handling:
454 * if state is NULL, returns ae_false on allocation error
455 * if state is not NULL, calls ae_break() on allocation error
456 * returns ae_true on success
457 
458 NOTES:
459 * never call it for blocks which are already in the list
460 ************************************************************************/
461 ae_bool ae_db_malloc(ae_dyn_block *block, ae_int_t size, ae_state *state, ae_bool make_automatic)
462 {
463  /* ensure that size is >=0
464  two ways to exit: 1) through ae_assert, if we have non-NULL state, 2) by returning ae_false */
465  if( state!=NULL )
466  ae_assert(size>=0, "ae_db_malloc(): negative size", state);
467  if( size<0 )
468  return ae_false;
469 
470  /* alloc */
471  block->ptr = ae_malloc((size_t)size, state);
472  if( block->ptr==NULL && size!=0 )
473  return ae_false;
474  if( make_automatic && state!=NULL )
475  ae_db_attach(block, state);
476  else
477  block->p_next = NULL;
478  block->deallocator = ae_free;
479  return ae_true;
480 }
481 
482 
483 /************************************************************************
484 This function realloc's dynamic block:
485 
486 block destination block (initialized)
487 size new size (in bytes)
488 state ALGLIB environment state
489 
490 block is assumed to be initialized.
491 
492 This function:
493 * deletes old contents
494 * preserves automatic state
495 
496 Error handling:
497 * if state is NULL, returns ae_false on allocation error
498 * if state is not NULL, calls ae_break() on allocation error
499 * returns ae_true on success
500 
501 NOTES:
502 * never call it for special blocks which mark frame boundaries!
503 ************************************************************************/
505 {
506  /* ensure that size is >=0
507  two ways to exit: 1) through ae_assert, if we have non-NULL state, 2) by returning ae_false */
508  if( state!=NULL )
509  ae_assert(size>=0, "ae_db_realloc(): negative size", state);
510  if( size<0 )
511  return ae_false;
512 
513  /* realloc */
514  if( block->ptr!=NULL )
515  ((ae_deallocator)block->deallocator)(block->ptr);
516  block->ptr = ae_malloc((size_t)size, state);
517  if( block->ptr==NULL && size!=0 )
518  return ae_false;
519  block->deallocator = ae_free;
520  return ae_true;
521 }
522 
523 
524 /************************************************************************
525 This function clears dynamic block (releases all dynamically allocated
526 memory). Dynamic block may be in automatic management list - in this case
527 it will NOT be removed from list.
528 
529 block destination block (initialized)
530 
531 NOTES:
532 * never call it for special blocks which marks frame boundaries!
533 ************************************************************************/
535 {
536  if( block->ptr!=NULL )
537  ((ae_deallocator)block->deallocator)(block->ptr);
538  block->ptr = NULL;
539  block->deallocator = ae_free;
540 }
541 
542 /************************************************************************
543 This function swaps contents of two dynamic blocks (pointers and
544 deallocators) leaving other parameters (automatic management settings,
545 etc.) unchanged.
546 
547 NOTES:
548 * never call it for special blocks which marks frame boundaries!
549 ************************************************************************/
550 void ae_db_swap(ae_dyn_block *block1, ae_dyn_block *block2)
551 {
552  void (*deallocator)(void*) = NULL;
553  void * volatile ptr;
554  ptr = block1->ptr;
555  deallocator = block1->deallocator;
556  block1->ptr = block2->ptr;
557  block1->deallocator = block2->deallocator;
558  block2->ptr = ptr;
559  block2->deallocator = deallocator;
560 }
561 
562 /************************************************************************
563 This function creates ae_vector.
564 
565 Vector size may be zero. Vector contents is uninitialized.
566 
567 dst destination vector
568 size vector size, may be zero
569 datatype guess what...
570 state ALGLIB environment state
571 make_automatic if true, vector is added to the dynamic block list
572 
573 Error handling:
574 * if state is NULL, returns ae_false on allocation error
575 * if state is not NULL, calls ae_break() on allocation error
576 * returns ae_true on success
577 
578 dst is assumed to be uninitialized, its fields are ignored.
579 ************************************************************************/
580 ae_bool ae_vector_init(ae_vector *dst, ae_int_t size, ae_datatype datatype, ae_state *state, ae_bool make_automatic)
581 {
582  /* ensure that size is >=0
583  two ways to exit: 1) through ae_assert, if we have non-NULL state, 2) by returning ae_false */
584  if( state!=NULL )
585  ae_assert(size>=0, "ae_vector_init(): negative size", state);
586  if( size<0 )
587  return ae_false;
588 
589  /* init */
590  dst->cnt = size;
591  dst->datatype = datatype;
592  if( !ae_db_malloc(&dst->data, size*ae_sizeof(datatype), state, make_automatic) )
593  return ae_false;
594  dst->ptr.p_ptr = dst->data.ptr;
595  return ae_true;
596 }
597 
598 
599 /************************************************************************
600 This function creates copy of ae_vector.
601 
602 dst destination vector
603 src well, it is source
604 state ALGLIB environment state
605 make_automatic if true, vector is added to the dynamic block list
606 
607 Error handling:
608 * if state is NULL, returns ae_false on allocation error
609 * if state is not NULL, calls ae_break() on allocation error
610 * returns ae_true on success
611 
612 dst is assumed to be uninitialized, its fields are ignored.
613 ************************************************************************/
614 ae_bool ae_vector_init_copy(ae_vector *dst, ae_vector *src, ae_state *state, ae_bool make_automatic)
615 {
616  if( !ae_vector_init(dst, src->cnt, src->datatype, state, make_automatic) )
617  return ae_false;
618  if( src->cnt!=0 )
619  memcpy(dst->ptr.p_ptr, src->ptr.p_ptr, (size_t)(src->cnt*ae_sizeof(src->datatype)));
620  return ae_true;
621 }
622 
623 /************************************************************************
624 This function creates ae_vector from x_vector:
625 
626 dst destination vector
627 src source, vector in x-format
628 state ALGLIB environment state
629 make_automatic if true, vector is added to the dynamic block list
630 
631 dst is assumed to be uninitialized, its fields are ignored.
632 ************************************************************************/
633 void ae_vector_init_from_x(ae_vector *dst, x_vector *src, ae_state *state, ae_bool make_automatic)
634 {
635  ae_vector_init(dst, (ae_int_t)src->cnt, (ae_datatype)src->datatype, state, make_automatic);
636  if( src->cnt>0 )
637  memcpy(dst->ptr.p_ptr, src->ptr, (size_t)(((ae_int_t)src->cnt)*ae_sizeof((ae_datatype)src->datatype)));
638 }
639 
640 
641 /************************************************************************
642 This function changes length of ae_vector.
643 
644 dst destination vector
645 newsize vector size, may be zero
646 state ALGLIB environment state
647 
648 Error handling:
649 * if state is NULL, returns ae_false on allocation error
650 * if state is not NULL, calls ae_break() on allocation error
651 * returns ae_true on success
652 
653 NOTES:
654 * vector must be initialized
655 * all contents is destroyed during setlength() call
656 * new size may be zero.
657 ************************************************************************/
659 {
660  /* ensure that size is >=0
661  two ways to exit: 1) through ae_assert, if we have non-NULL state, 2) by returning ae_false */
662  if( state!=NULL )
663  ae_assert(newsize>=0, "ae_vector_set_length(): negative size", state);
664  if( newsize<0 )
665  return ae_false;
666 
667  /* set length */
668  if( dst->cnt==newsize )
669  return ae_true;
670  dst->cnt = newsize;
671  if( !ae_db_realloc(&dst->data, newsize*ae_sizeof(dst->datatype), state) )
672  return ae_false;
673  dst->ptr.p_ptr = dst->data.ptr;
674  return ae_true;
675 }
676 
677 
678 /************************************************************************
679 This function provides "CLEAR" functionality for vector (contents is
680 cleared, but structure still left in valid state).
681 
682 The function clears vector contents (releases all dynamically allocated
683 memory). Vector may be in automatic management list - in this case it
684 will NOT be removed from list.
685 
686 IMPORTANT: this function does NOT invalidates dst; it just releases all
687 dynamically allocated storage, but dst still may be used after call to
688 ae_vector_set_length().
689 
690 dst destination vector
691 ************************************************************************/
693 {
694  dst->cnt = 0;
695  ae_db_free(&dst->data);
696  dst->ptr.p_ptr = 0;
697 }
698 
699 
700 /************************************************************************
701 This function provides "DESTROY" functionality for vector (contents is
702 cleared, all internal structures are destroyed). For vectors it is same
703 as CLEAR.
704 
705 dst destination vector
706 ************************************************************************/
708 {
709  ae_vector_clear(dst);
710 }
711 
712 
713 /************************************************************************
714 This function efficiently swaps contents of two vectors, leaving other
715 pararemeters (automatic management, etc.) unchanged.
716 ************************************************************************/
718 {
719  ae_int_t cnt;
720  ae_datatype datatype;
721  void *p_ptr;
722 
723  ae_db_swap(&vec1->data, &vec2->data);
724 
725  cnt = vec1->cnt;
726  datatype = vec1->datatype;
727  p_ptr = vec1->ptr.p_ptr;
728  vec1->cnt = vec2->cnt;
729  vec1->datatype = vec2->datatype;
730  vec1->ptr.p_ptr = vec2->ptr.p_ptr;
731  vec2->cnt = cnt;
732  vec2->datatype = datatype;
733  vec2->ptr.p_ptr = p_ptr;
734 }
735 
736 /************************************************************************
737 This function creates ae_matrix.
738 
739 Matrix size may be zero, in such cases both rows and cols are zero.
740 Matrix contents is uninitialized.
741 
742 dst destination natrix
743 rows rows count
744 cols cols count
745 datatype element type
746 state ALGLIB environment state
747 make_automatic if true, matrix is added to the dynamic block list
748 
749 Error handling:
750 * if state is NULL, returns ae_false on allocation error
751 * if state is not NULL, calls ae_break() on allocation error
752 * returns ae_true on success
753 
754 dst is assumed to be uninitialized, its fields are ignored.
755 ************************************************************************/
756 ae_bool ae_matrix_init(ae_matrix *dst, ae_int_t rows, ae_int_t cols, ae_datatype datatype, ae_state *state, ae_bool make_automatic)
757 {
758  /* ensure that size is >=0
759  two ways to exit: 1) through ae_assert, if we have non-NULL state, 2) by returning ae_false */
760  if( state!=NULL )
761  ae_assert(rows>=0 && cols>=0, "ae_matrix_init(): negative length", state);
762  if( rows<0 || cols<0 )
763  return ae_false;
764 
765  /* if one of rows/cols is zero, another MUST be too */
766  if( rows==0 || cols==0 )
767  {
768  rows = 0;
769  cols = 0;
770  }
771 
772  /* init */
773  dst->rows = rows;
774  dst->cols = cols;
775  dst->stride = cols;
776  while( dst->stride*ae_sizeof(datatype)%AE_DATA_ALIGN!=0 )
777  dst->stride++;
778  dst->datatype = datatype;
779  if( !ae_db_malloc(&dst->data, dst->rows*((ae_int_t)sizeof(void*)+dst->stride*ae_sizeof(datatype))+AE_DATA_ALIGN-1, state, make_automatic) )
780  return ae_false;
781  ae_matrix_update_row_pointers(dst, ae_align((char*)dst->data.ptr+dst->rows*sizeof(void*),AE_DATA_ALIGN));
782  return ae_true;
783 }
784 
785 
786 /************************************************************************
787 This function creates copy of ae_matrix.
788 
789 dst destination matrix
790 src well, it is source
791 state ALGLIB environment state
792 make_automatic if true, matrix is added to the dynamic block list
793 
794 Error handling:
795 * if state is NULL, returns ae_false on allocation error
796 * if state is not NULL, calls ae_break() on allocation error
797 * returns ae_true on success
798 
799 dst is assumed to be uninitialized, its fields are ignored.
800 ************************************************************************/
801 ae_bool ae_matrix_init_copy(ae_matrix *dst, ae_matrix *src, ae_state *state, ae_bool make_automatic)
802 {
803  ae_int_t i;
804  if( !ae_matrix_init(dst, src->rows, src->cols, src->datatype, state, make_automatic) )
805  return ae_false;
806  if( src->rows!=0 && src->cols!=0 )
807  {
808  if( dst->stride==src->stride )
809  memcpy(dst->ptr.pp_void[0], src->ptr.pp_void[0], (size_t)(src->rows*src->stride*ae_sizeof(src->datatype)));
810  else
811  for(i=0; i<dst->rows; i++)
812  memcpy(dst->ptr.pp_void[i], src->ptr.pp_void[i], (size_t)(dst->cols*ae_sizeof(dst->datatype)));
813  }
814  return ae_true;
815 }
816 
817 
818 void ae_matrix_init_from_x(ae_matrix *dst, x_matrix *src, ae_state *state, ae_bool make_automatic)
819 {
820  char *p_src_row;
821  char *p_dst_row;
822  ae_int_t row_size;
823  ae_int_t i;
824  ae_matrix_init(dst, (ae_int_t)src->rows, (ae_int_t)src->cols, (ae_datatype)src->datatype, state, make_automatic);
825  if( src->rows!=0 && src->cols!=0 )
826  {
827  p_src_row = (char*)src->ptr;
828  p_dst_row = (char*)(dst->ptr.pp_void[0]);
829  row_size = ae_sizeof((ae_datatype)src->datatype)*(ae_int_t)src->cols;
830  for(i=0; i<src->rows; i++, p_src_row+=src->stride*ae_sizeof((ae_datatype)src->datatype), p_dst_row+=dst->stride*ae_sizeof((ae_datatype)src->datatype))
831  memcpy(p_dst_row, p_src_row, (size_t)(row_size));
832  }
833 }
834 
835 
836 /************************************************************************
837 This function changes length of ae_matrix.
838 
839 dst destination matrix
840 rows size, may be zero
841 cols size, may be zero
842 state ALGLIB environment state
843 
844 Error handling:
845 * if state is NULL, returns ae_false on allocation error
846 * if state is not NULL, calls ae_break() on allocation error
847 * returns ae_true on success
848 
849 NOTES:
850 * matrix must be initialized
851 * all contents is destroyed during setlength() call
852 * new size may be zero.
853 ************************************************************************/
855 {
856  /* ensure that size is >=0
857  two ways to exit: 1) through ae_assert, if we have non-NULL state, 2) by returning ae_false */
858  if( state!=NULL )
859  ae_assert(rows>=0 && cols>=0, "ae_matrix_set_length(): negative length", state);
860  if( rows<0 || cols<0 )
861  return ae_false;
862 
863  if( dst->rows==rows && dst->cols==cols )
864  return ae_true;
865  dst->rows = rows;
866  dst->cols = cols;
867  dst->stride = cols;
868  while( dst->stride*ae_sizeof(dst->datatype)%AE_DATA_ALIGN!=0 )
869  dst->stride++;
870  if( !ae_db_realloc(&dst->data, dst->rows*((ae_int_t)sizeof(void*)+dst->stride*ae_sizeof(dst->datatype))+AE_DATA_ALIGN-1, state) )
871  return ae_false;
872  ae_matrix_update_row_pointers(dst, ae_align((char*)dst->data.ptr+dst->rows*sizeof(void*),AE_DATA_ALIGN));
873  return ae_true;
874 }
875 
876 
877 /************************************************************************
878 This function provides "CLEAR" functionality for vector (contents is
879 cleared, but structure still left in valid state).
880 
881 The function clears matrix contents (releases all dynamically allocated
882 memory). Matrix may be in automatic management list - in this case it
883 will NOT be removed from list.
884 
885 IMPORTANT: this function does NOT invalidates dst; it just releases all
886 dynamically allocated storage, but dst still may be used after call to
887 ae_matrix_set_length().
888 
889 dst destination matrix
890 ************************************************************************/
892 {
893  dst->rows = 0;
894  dst->cols = 0;
895  dst->stride = 0;
896  ae_db_free(&dst->data);
897  dst->ptr.p_ptr = 0;
898 }
899 
900 
901 /************************************************************************
902 This function provides "DESTROY" functionality for matrix (contents is
903 cleared, but structure still left in valid state).
904 
905 For matrices it is same as CLEAR.
906 
907 dst destination matrix
908 ************************************************************************/
910 {
911  ae_matrix_clear(dst);
912 }
913 
914 
915 /************************************************************************
916 This function efficiently swaps contents of two vectors, leaving other
917 pararemeters (automatic management, etc.) unchanged.
918 ************************************************************************/
920 {
921  ae_int_t rows;
922  ae_int_t cols;
923  ae_int_t stride;
924  ae_datatype datatype;
925  void *p_ptr;
926 
927  ae_db_swap(&mat1->data, &mat2->data);
928 
929  rows = mat1->rows;
930  cols = mat1->cols;
931  stride = mat1->stride;
932  datatype = mat1->datatype;
933  p_ptr = mat1->ptr.p_ptr;
934 
935  mat1->rows = mat2->rows;
936  mat1->cols = mat2->cols;
937  mat1->stride = mat2->stride;
938  mat1->datatype = mat2->datatype;
939  mat1->ptr.p_ptr = mat2->ptr.p_ptr;
940 
941  mat2->rows = rows;
942  mat2->cols = cols;
943  mat2->stride = stride;
944  mat2->datatype = datatype;
945  mat2->ptr.p_ptr = p_ptr;
946 }
947 
948 
949 /************************************************************************
950 This function creates smart pointer structure.
951 
952 dst destination smart pointer.
953  already allocated, but not initialized.
954 subscriber pointer to pointer which receives updates in the
955  internal object stored in ae_smart_ptr. Any update to
956  dst->ptr is translated to subscriber. Can be NULL.
957 state ALGLIB environment state
958 make_automatic if true, smart pointer is added to the dynamic block list
959 
960 After initialization, smart pointer stores NULL pointer.
961 
962 Error handling:
963 * if state is NULL, returns ae_false on allocation error
964 * if state is not NULL, calls ae_break() on allocation error
965 * returns ae_true on success
966 ************************************************************************/
967 ae_bool ae_smart_ptr_init(ae_smart_ptr *dst, void **subscriber, ae_state *state, ae_bool make_automatic)
968 {
969  dst->subscriber = subscriber;
970  dst->ptr = NULL;
971  if( dst->subscriber!=NULL )
972  *(dst->subscriber) = dst->ptr;
973  dst->is_owner = ae_false;
974  dst->is_dynamic = ae_false;
976  dst->frame_entry.ptr = dst;
977  if( make_automatic && state!=NULL )
978  ae_db_attach(&dst->frame_entry, state);
979  return ae_true;
980 }
981 
982 
983 /************************************************************************
984 This function clears smart pointer structure.
985 
986 dst destination smart pointer.
987 
988 After call to this function smart pointer contains NULL reference, which
989 is propagated to its subscriber (in cases non-NULL subscruber was
990 specified during pointer creation).
991 ************************************************************************/
992 void ae_smart_ptr_clear(void *_dst)
993 {
994  ae_smart_ptr *dst = (ae_smart_ptr*)_dst;
995  if( dst->is_owner && dst->ptr!=NULL )
996  {
997  dst->destroy(dst->ptr);
998  if( dst->is_dynamic )
999  ae_free(dst->ptr);
1000  }
1001  dst->is_owner = ae_false;
1002  dst->is_dynamic = ae_false;
1003  dst->ptr = NULL;
1004  dst->destroy = NULL;
1005  if( dst->subscriber!=NULL )
1006  *(dst->subscriber) = NULL;
1007 }
1008 
1009 
1010 /************************************************************************
1011 This function dstroys smart pointer structure (same as clearing it).
1012 
1013 dst destination smart pointer.
1014 ************************************************************************/
1015 void ae_smart_ptr_destroy(void *_dst)
1016 {
1017  ae_smart_ptr_clear(_dst);
1018 }
1019 
1020 
1021 /************************************************************************
1022 This function assigns pointer to ae_smart_ptr structure.
1023 
1024 dst destination smart pointer.
1025 new_ptr new pointer to assign
1026 is_owner whether smart pointer owns new_ptr
1027 is_dynamic whether object is dynamic - clearing such object
1028  requires BOTH calling destructor function AND calling
1029  ae_free() for memory occupied by object.
1030 destroy destructor function
1031 
1032 In case smart pointer already contains non-NULL value and owns this value,
1033 it is freed before assigning new pointer.
1034 
1035 Changes in pointer are propagated to its subscriber (in case non-NULL
1036 subscriber was specified during pointer creation).
1037 
1038 You can specify NULL new_ptr, in which case is_owner/destroy are ignored.
1039 ************************************************************************/
1040 void ae_smart_ptr_assign(ae_smart_ptr *dst, void *new_ptr, ae_bool is_owner, ae_bool is_dynamic, void (*destroy)(void*))
1041 {
1042  if( dst->is_owner && dst->ptr!=NULL )
1043  dst->destroy(dst->ptr);
1044  if( new_ptr!=NULL )
1045  {
1046  dst->ptr = new_ptr;
1047  dst->is_owner = is_owner;
1048  dst->is_dynamic = is_dynamic;
1049  dst->destroy = destroy;
1050  }
1051  else
1052  {
1053  dst->ptr = NULL;
1054  dst->is_owner = ae_false;
1055  dst->is_dynamic = ae_false;
1056  dst->destroy = NULL;
1057  }
1058  if( dst->subscriber!=NULL )
1059  *(dst->subscriber) = dst->ptr;
1060 }
1061 
1062 
1063 /************************************************************************
1064 This function releases pointer owned by ae_smart_ptr structure:
1065 * all internal fields are set to NULL
1066 * destructor function for internal pointer is NOT called even when we own
1067  this pointer. After this call ae_smart_ptr releases ownership of its
1068  pointer and passes it to caller.
1069 * changes in pointer are propagated to its subscriber (in case non-NULL
1070  subscriber was specified during pointer creation).
1071 
1072 dst destination smart pointer.
1073 ************************************************************************/
1075 {
1076  dst->is_owner = ae_false;
1077  dst->is_dynamic = ae_false;
1078  dst->ptr = NULL;
1079  dst->destroy = NULL;
1080  if( dst->subscriber!=NULL )
1081  *(dst->subscriber) = NULL;
1082 }
1083 
1084 /************************************************************************
1085 This function fills x_vector by ae_vector's contents:
1086 
1087 dst destination vector
1088 src source, vector in x-format
1089 state ALGLIB environment state
1090 
1091 NOTES:
1092 * dst is assumed to be initialized. Its contents is freed before copying
1093  data from src (if size / type are different) or overwritten (if
1094  possible given destination size).
1095 ************************************************************************/
1096 void ae_x_set_vector(x_vector *dst, ae_vector *src, ae_state *state)
1097 {
1098  if( dst->cnt!=src->cnt || dst->datatype!=src->datatype )
1099  {
1100  if( dst->owner==OWN_AE )
1101  ae_free(dst->ptr);
1102  dst->ptr = ae_malloc((size_t)(src->cnt*ae_sizeof(src->datatype)), state);
1104  dst->cnt = src->cnt;
1105  dst->datatype = src->datatype;
1106  dst->owner = OWN_AE;
1107  }
1108  else
1110  if( src->cnt )
1111  memcpy(dst->ptr, src->ptr.p_ptr, (size_t)(src->cnt*ae_sizeof(src->datatype)));
1112 }
1113 
1114 /************************************************************************
1115 This function fills x_matrix by ae_matrix's contents:
1116 
1117 dst destination vector
1118 src source, matrix in x-format
1119 state ALGLIB environment state
1120 
1121 NOTES:
1122 * dst is assumed to be initialized. Its contents is freed before copying
1123  data from src (if size / type are different) or overwritten (if
1124  possible given destination size).
1125 ************************************************************************/
1126 void ae_x_set_matrix(x_matrix *dst, ae_matrix *src, ae_state *state)
1127 {
1128  char *p_src_row;
1129  char *p_dst_row;
1130  ae_int_t i;
1131  ae_int_t row_size;
1132  if( dst->rows!=src->rows || dst->cols!=src->cols || dst->datatype!=src->datatype )
1133  {
1134  if( dst->owner==OWN_AE )
1135  ae_free(dst->ptr);
1136  dst->rows = src->rows;
1137  dst->cols = src->cols;
1138  dst->stride = src->cols;
1139  dst->datatype = src->datatype;
1140  dst->ptr = ae_malloc((size_t)(dst->rows*((ae_int_t)dst->stride)*ae_sizeof(src->datatype)), state);
1142  dst->owner = OWN_AE;
1143  }
1144  else
1146  if( src->rows!=0 && src->cols!=0 )
1147  {
1148  p_src_row = (char*)(src->ptr.pp_void[0]);
1149  p_dst_row = (char*)dst->ptr;
1150  row_size = ae_sizeof(src->datatype)*src->cols;
1151  for(i=0; i<src->rows; i++, p_src_row+=src->stride*ae_sizeof(src->datatype), p_dst_row+=dst->stride*ae_sizeof(src->datatype))
1152  memcpy(p_dst_row, p_src_row, (size_t)(row_size));
1153  }
1154 }
1155 
1156 /************************************************************************
1157 This function attaches x_vector to ae_vector's contents.
1158 Ownership of memory allocated is not changed (it is still managed by
1159 ae_matrix).
1160 
1161 dst destination vector
1162 src source, vector in x-format
1163 state ALGLIB environment state
1164 
1165 NOTES:
1166 * dst is assumed to be initialized. Its contents is freed before
1167  attaching to src.
1168 * this function doesn't need ae_state parameter because it can't fail
1169  (assuming correctly initialized src)
1170 ************************************************************************/
1172 {
1173  if( dst->owner==OWN_AE )
1174  ae_free(dst->ptr);
1175  dst->ptr = src->ptr.p_ptr;
1177  dst->cnt = src->cnt;
1178  dst->datatype = src->datatype;
1179  dst->owner = OWN_CALLER;
1180 }
1181 
1182 /************************************************************************
1183 This function attaches x_matrix to ae_matrix's contents.
1184 Ownership of memory allocated is not changed (it is still managed by
1185 ae_matrix).
1186 
1187 dst destination vector
1188 src source, matrix in x-format
1189 state ALGLIB environment state
1190 
1191 NOTES:
1192 * dst is assumed to be initialized. Its contents is freed before
1193  attaching to src.
1194 * this function doesn't need ae_state parameter because it can't fail
1195  (assuming correctly initialized src)
1196 ************************************************************************/
1198 {
1199  if( dst->owner==OWN_AE )
1200  ae_free(dst->ptr);
1201  dst->rows = src->rows;
1202  dst->cols = src->cols;
1203  dst->stride = src->stride;
1204  dst->datatype = src->datatype;
1205  dst->ptr = &(src->ptr.pp_double[0][0]);
1207  dst->owner = OWN_CALLER;
1208 }
1209 
1210 /************************************************************************
1211 This function clears x_vector. It does nothing if vector is not owned by
1212 ALGLIB environment.
1213 
1214 dst vector
1215 ************************************************************************/
1217 {
1218  if( dst->owner==OWN_AE )
1219  aligned_free(dst->ptr);
1220  dst->ptr = NULL;
1221  dst->cnt = 0;
1222 }
1223 
1224 /************************************************************************
1225 Assertion
1226 ************************************************************************/
1227 void ae_assert(ae_bool cond, const char *msg, ae_state *state)
1228 {
1229  if( !cond )
1230  ae_break(state, ERR_ASSERTION_FAILED, msg);
1231 }
1232 
1233 /************************************************************************
1234 CPUID
1235 
1236 Returns information about features CPU and compiler support.
1237 
1238 You must tell ALGLIB what CPU family is used by defining AE_CPU symbol
1239 (without this hint zero will be returned).
1240 
1241 Note: results of this function depend on both CPU and compiler;
1242 if compiler doesn't support SSE intrinsics, function won't set
1243 corresponding flag.
1244 ************************************************************************/
1245 static volatile ae_bool _ae_cpuid_initialized = ae_false;
1246 static volatile ae_bool _ae_cpuid_has_sse2 = ae_false;
1248 {
1249  /*
1250  * to speed up CPU detection we cache results from previous attempts
1251  * there is no synchronization, but it is still thread safe.
1252  *
1253  * thread safety is guaranteed on all modern architectures which
1254  * have following property: simultaneous writes by different cores
1255  * to the same location will be executed in serial manner.
1256  *
1257  */
1258  ae_int_t result;
1259 
1260  /*
1261  * if not initialized, determine system properties
1262  */
1263  if( !_ae_cpuid_initialized )
1264  {
1265  /*
1266  * SSE2
1267  */
1268 #if defined(AE_CPU)
1269 #if (AE_CPU==AE_INTEL) && defined(AE_HAS_SSE2_INTRINSICS)
1270 #if AE_COMPILER==AE_MSVC
1271  {
1272  int CPUInfo[4];
1273  __cpuid(CPUInfo, 1);
1274  if( (CPUInfo[3]&0x04000000)!=0 )
1275  _ae_cpuid_has_sse2 = ae_true;
1276  }
1277 #elif AE_COMPILER==AE_GNUC
1278  {
1279  ae_int_t a,b,c,d;
1280  __asm__ __volatile__ ("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (1));
1281  if( (d&0x04000000)!=0 )
1282  _ae_cpuid_has_sse2 = ae_true;
1283  }
1284 #elif AE_COMPILER==AE_SUNC
1285  {
1286  ae_int_t a,b,c,d;
1287  __asm__ __volatile__ ("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (1));
1288  if( (d&0x04000000)!=0 )
1289  _ae_cpuid_has_sse2 = ae_true;
1290  }
1291 #else
1292 #endif
1293 #endif
1294 #endif
1295  /*
1296  * set initialization flag
1297  */
1298  _ae_cpuid_initialized = ae_true;
1299  }
1300 
1301  /*
1302  * return
1303  */
1304  result = 0;
1305  if( _ae_cpuid_has_sse2 )
1306  result = result|CPU_SSE2;
1307  return result;
1308 }
1309 
1310 /************************************************************************
1311 Real math functions
1312 ************************************************************************/
1313 ae_bool ae_fp_eq(double v1, double v2)
1314 {
1315  /* IEEE-strict floating point comparison */
1316  volatile double x = v1;
1317  volatile double y = v2;
1318  return x==y;
1319 }
1320 
1321 ae_bool ae_fp_neq(double v1, double v2)
1322 {
1323  /* IEEE-strict floating point comparison */
1324  return !ae_fp_eq(v1,v2);
1325 }
1326 
1327 ae_bool ae_fp_less(double v1, double v2)
1328 {
1329  /* IEEE-strict floating point comparison */
1330  volatile double x = v1;
1331  volatile double y = v2;
1332  return x<y;
1333 }
1334 
1335 ae_bool ae_fp_less_eq(double v1, double v2)
1336 {
1337  /* IEEE-strict floating point comparison */
1338  volatile double x = v1;
1339  volatile double y = v2;
1340  return x<=y;
1341 }
1342 
1343 ae_bool ae_fp_greater(double v1, double v2)
1344 {
1345  /* IEEE-strict floating point comparison */
1346  volatile double x = v1;
1347  volatile double y = v2;
1348  return x>y;
1349 }
1350 
1351 ae_bool ae_fp_greater_eq(double v1, double v2)
1352 {
1353  /* IEEE-strict floating point comparison */
1354  volatile double x = v1;
1355  volatile double y = v2;
1356  return x>=y;
1357 }
1358 
1360 {
1361  union _u
1362  {
1363  double a;
1364  ae_int32_t p[2];
1365  } u;
1366  ae_int32_t high;
1367  u.a = x;
1368  if( endianness==AE_LITTLE_ENDIAN )
1369  high = u.p[1];
1370  else
1371  high = u.p[0];
1372  return (high & (ae_int32_t)0x7FF00000)!=(ae_int32_t)0x7FF00000;
1373 }
1374 
1376 {
1377  union _u
1378  {
1379  double a;
1380  ae_int32_t p[2];
1381  } u;
1382  ae_int32_t high, low;
1383  u.a = x;
1384  if( endianness==AE_LITTLE_ENDIAN )
1385  {
1386  high = u.p[1];
1387  low = u.p[0];
1388  }
1389  else
1390  {
1391  high = u.p[0];
1392  low = u.p[1];
1393  }
1394  return ((high &0x7FF00000)==0x7FF00000) && (((high &0x000FFFFF)!=0) || (low!=0));
1395 }
1396 
1398 {
1399  union _u
1400  {
1401  double a;
1402  ae_int32_t p[2];
1403  } u;
1404  ae_int32_t high, low;
1405  u.a = x;
1406  if( endianness==AE_LITTLE_ENDIAN )
1407  {
1408  high = u.p[1];
1409  low = u.p[0];
1410  }
1411  else
1412  {
1413  high = u.p[0];
1414  low = u.p[1];
1415  }
1416 
1417  /* 31 least significant bits of high are compared */
1418  return ((high&0x7FFFFFFF)==0x7FF00000) && (low==0);
1419 }
1420 
1422 {
1423  union _u
1424  {
1425  double a;
1426  ae_int32_t p[2];
1427  } u;
1428  ae_int32_t high, low;
1429  u.a = x;
1430  if( endianness==AE_LITTLE_ENDIAN )
1431  {
1432  high = u.p[1];
1433  low = u.p[0];
1434  }
1435  else
1436  {
1437  high = u.p[0];
1438  low = u.p[1];
1439  }
1440 
1441  /* all 32 bits of high are compared */
1442  return (high==(ae_int32_t)0x7FF00000) && (low==0);
1443 }
1444 
1446 {
1447  union _u
1448  {
1449  double a;
1450  ae_int32_t p[2];
1451  } u;
1452  ae_int32_t high, low;
1453  u.a = x;
1454  if( endianness==AE_LITTLE_ENDIAN )
1455  {
1456  high = u.p[1];
1457  low = u.p[0];
1458  }
1459  else
1460  {
1461  high = u.p[0];
1462  low = u.p[1];
1463  }
1464 
1465  /* this code is a bit tricky to avoid comparison of high with 0xFFF00000, which may be unsafe with some buggy compilers */
1466  return ((high&0x7FFFFFFF)==0x7FF00000) && (high!=(ae_int32_t)0x7FF00000) && (low==0);
1467 }
1468 
1470 {
1471  union
1472  {
1473  double a;
1474  ae_int32_t p[2];
1475  } u;
1476 
1477  /*
1478  * determine endianness
1479  * two types are supported: big-endian and little-endian.
1480  * mixed-endian hardware is NOT supported.
1481  *
1482  * 1983 is used as magic number because its non-periodic double
1483  * representation allow us to easily distinguish between upper
1484  * and lower halfs and to detect mixed endian hardware.
1485  *
1486  */
1487  u.a = 1.0/1983.0;
1488  if( u.p[1]==(ae_int32_t)0x3f408642 )
1489  return AE_LITTLE_ENDIAN;
1490  if( u.p[0]==(ae_int32_t)0x3f408642 )
1491  return AE_BIG_ENDIAN;
1492  return AE_MIXED_ENDIAN;
1493 }
1494 
1496 {
1497  return ae_isfinite_stateless(x, state->endianness);
1498 }
1499 
1500 ae_bool ae_isnan(double x, ae_state *state)
1501 {
1502  return ae_isnan_stateless(x, state->endianness);
1503 }
1504 
1505 ae_bool ae_isinf(double x, ae_state *state)
1506 {
1507  return ae_isinf_stateless(x, state->endianness);
1508 }
1509 
1511 {
1512  return ae_isposinf_stateless(x, state->endianness);
1513 }
1514 
1516 {
1517  return ae_isneginf_stateless(x, state->endianness);
1518 }
1519 
1520 double ae_fabs(double x, ae_state *state)
1521 {
1522  return fabs(x);
1523 }
1524 
1526 {
1527  return x>=0 ? x : -x;
1528 }
1529 
1530 double ae_sqr(double x, ae_state *state)
1531 {
1532  return x*x;
1533 }
1534 
1535 double ae_sqrt(double x, ae_state *state)
1536 {
1537  return sqrt(x);
1538 }
1539 
1540 ae_int_t ae_sign(double x, ae_state *state)
1541 {
1542  if( x>0 ) return 1;
1543  if( x<0 ) return -1;
1544  return 0;
1545 }
1546 
1547 ae_int_t ae_round(double x, ae_state *state)
1548 {
1549  return (ae_int_t)(ae_ifloor(x+0.5,state));
1550 }
1551 
1552 ae_int_t ae_trunc(double x, ae_state *state)
1553 {
1554  return (ae_int_t)(x>0 ? ae_ifloor(x,state) : ae_iceil(x,state));
1555 }
1556 
1557 ae_int_t ae_ifloor(double x, ae_state *state)
1558 {
1559  return (ae_int_t)(floor(x));
1560 }
1561 
1562 ae_int_t ae_iceil(double x, ae_state *state)
1563 {
1564  return (ae_int_t)(ceil(x));
1565 }
1566 
1568 {
1569  return m1>m2 ? m1 : m2;
1570 }
1571 
1573 {
1574  return m1>m2 ? m2 : m1;
1575 }
1576 
1577 double ae_maxreal(double m1, double m2, ae_state *state)
1578 {
1579  return m1>m2 ? m1 : m2;
1580 }
1581 
1582 double ae_minreal(double m1, double m2, ae_state *state)
1583 {
1584  return m1>m2 ? m2 : m1;
1585 }
1586 
1587 #ifdef AE_DEBUGRNG
1588 ae_int_t ae_debugrng()
1589 {
1590  ae_int_t k;
1591  ae_int_t result;
1592  k = _debug_rng_s0/53668;
1593  _debug_rng_s0 = 40014*(_debug_rng_s0-k*53668)-k*12211;
1594  if( _debug_rng_s0<0 )
1595  _debug_rng_s0 = _debug_rng_s0+2147483563;
1596  k = _debug_rng_s1/52774;
1597  _debug_rng_s1 = 40692*(_debug_rng_s1-k*52774)-k*3791;
1598  if( _debug_rng_s1<0 )
1599  _debug_rng_s1 = _debug_rng_s1+2147483399;
1600  result = _debug_rng_s0-_debug_rng_s1;
1601  if( result<1 )
1602  result = result+2147483562;
1603  return result;
1604 }
1605 #endif
1606 
1607 double ae_randomreal(ae_state *state)
1608 {
1609 #ifdef AE_DEBUGRNG
1610  return ae_debugrng()/2147483563.0;
1611 #else
1612  int i1 = rand();
1613  int i2 = rand();
1614  double mx = (double)(RAND_MAX)+1.0;
1615  volatile double tmp0 = i2/mx;
1616  volatile double tmp1 = i1+tmp0;
1617  return tmp1/mx;
1618 #endif
1619 }
1620 
1622 {
1623 #ifdef AE_DEBUGRNG
1624  return (ae_debugrng()-1)%maxv;
1625 #else
1626  return rand()%maxv;
1627 #endif
1628 }
1629 
1630 double ae_sin(double x, ae_state *state)
1631 {
1632  return sin(x);
1633 }
1634 
1635 double ae_cos(double x, ae_state *state)
1636 {
1637  return cos(x);
1638 }
1639 
1640 double ae_tan(double x, ae_state *state)
1641 {
1642  return tan(x);
1643 }
1644 
1645 double ae_sinh(double x, ae_state *state)
1646 {
1647  return sinh(x);
1648 }
1649 
1650 double ae_cosh(double x, ae_state *state)
1651 {
1652  return cosh(x);
1653 }
1654 double ae_tanh(double x, ae_state *state)
1655 {
1656  return tanh(x);
1657 }
1658 
1659 double ae_asin(double x, ae_state *state)
1660 {
1661  return asin(x);
1662 }
1663 
1664 double ae_acos(double x, ae_state *state)
1665 {
1666  return acos(x);
1667 }
1668 
1669 double ae_atan(double x, ae_state *state)
1670 {
1671  return atan(x);
1672 }
1673 
1674 double ae_atan2(double y, double x, ae_state *state)
1675 {
1676  return atan2(y,x);
1677 }
1678 
1679 double ae_log(double x, ae_state *state)
1680 {
1681  return log(x);
1682 }
1683 
1684 double ae_pow(double x, double y, ae_state *state)
1685 {
1686  return pow(x,y);
1687 }
1688 
1689 double ae_exp(double x, ae_state *state)
1690 {
1691  return exp(x);
1692 }
1693 
1694 /************************************************************************
1695 Symmetric/Hermitian properties: check and force
1696 ************************************************************************/
1697 static void x_split_length(ae_int_t n, ae_int_t nb, ae_int_t* n1, ae_int_t* n2)
1698 {
1699  ae_int_t r;
1700  if( n<=nb )
1701  {
1702  *n1 = n;
1703  *n2 = 0;
1704  }
1705  else
1706  {
1707  if( n%nb!=0 )
1708  {
1709  *n2 = n%nb;
1710  *n1 = n-(*n2);
1711  }
1712  else
1713  {
1714  *n2 = n/2;
1715  *n1 = n-(*n2);
1716  if( *n1%nb==0 )
1717  {
1718  return;
1719  }
1720  r = nb-*n1%nb;
1721  *n1 = *n1+r;
1722  *n2 = *n2-r;
1723  }
1724  }
1725 }
1726 static double x_safepythag2(double x, double y)
1727 {
1728  double w;
1729  double xabs;
1730  double yabs;
1731  double z;
1732  xabs = fabs(x);
1733  yabs = fabs(y);
1734  w = xabs>yabs ? xabs : yabs;
1735  z = xabs<yabs ? xabs : yabs;
1736  if( z==0 )
1737  return w;
1738  else
1739  {
1740  double t;
1741  t = z/w;
1742  return w*sqrt(1+t*t);
1743  }
1744 }
1745 /*
1746  * this function checks difference between offdiagonal blocks BL and BU
1747  * (see below). Block BL is specified by offsets (offset0,offset1) and
1748  * sizes (len0,len1).
1749  *
1750  * [ . ]
1751  * [ A0 BU ]
1752  * A = [ BL A1 ]
1753  * [ . ]
1754  *
1755  * this subroutine updates current values of:
1756  * a) mx maximum value of A[i,j] found so far
1757  * b) err componentwise difference between elements of BL and BU^T
1758  *
1759  */
1760 static void is_symmetric_rec_off_stat(x_matrix *a, ae_int_t offset0, ae_int_t offset1, ae_int_t len0, ae_int_t len1, ae_bool *nonfinite, double *mx, double *err, ae_state *_state)
1761 {
1762  /* try to split problem into two smaller ones */
1763  if( len0>x_nb || len1>x_nb )
1764  {
1765  ae_int_t n1, n2;
1766  if( len0>len1 )
1767  {
1768  x_split_length(len0, x_nb, &n1, &n2);
1769  is_symmetric_rec_off_stat(a, offset0, offset1, n1, len1, nonfinite, mx, err, _state);
1770  is_symmetric_rec_off_stat(a, offset0+n1, offset1, n2, len1, nonfinite, mx, err, _state);
1771  }
1772  else
1773  {
1774  x_split_length(len1, x_nb, &n1, &n2);
1775  is_symmetric_rec_off_stat(a, offset0, offset1, len0, n1, nonfinite, mx, err, _state);
1776  is_symmetric_rec_off_stat(a, offset0, offset1+n1, len0, n2, nonfinite, mx, err, _state);
1777  }
1778  return;
1779  }
1780  else
1781  {
1782  /* base case */
1783  double *p1, *p2, *prow, *pcol;
1784  double v;
1785  ae_int_t i, j;
1786 
1787  p1 = (double*)(a->ptr)+offset0*a->stride+offset1;
1788  p2 = (double*)(a->ptr)+offset1*a->stride+offset0;
1789  for(i=0; i<len0; i++)
1790  {
1791  pcol = p2+i;
1792  prow = p1+i*a->stride;
1793  for(j=0; j<len1; j++)
1794  {
1795  if( !ae_isfinite(*pcol,_state) || !ae_isfinite(*prow,_state) )
1796  {
1797  *nonfinite = ae_true;
1798  }
1799  else
1800  {
1801  v = fabs(*pcol);
1802  *mx = *mx>v ? *mx : v;
1803  v = fabs(*prow);
1804  *mx = *mx>v ? *mx : v;
1805  v = fabs(*pcol-*prow);
1806  *err = *err>v ? *err : v;
1807  }
1808  pcol += a->stride;
1809  prow++;
1810  }
1811  }
1812  }
1813 }
1814 /*
1815  * this function checks that diagonal block A0 is symmetric.
1816  * Block A0 is specified by its offset and size.
1817  *
1818  * [ . ]
1819  * [ A0 ]
1820  * A = [ . ]
1821  * [ . ]
1822  *
1823  * this subroutine updates current values of:
1824  * a) mx maximum value of A[i,j] found so far
1825  * b) err componentwise difference between A0 and A0^T
1826  *
1827  */
1828 static void is_symmetric_rec_diag_stat(x_matrix *a, ae_int_t offset, ae_int_t len, ae_bool *nonfinite, double *mx, double *err, ae_state *_state)
1829 {
1830  double *p, *prow, *pcol;
1831  double v;
1832  ae_int_t i, j;
1833 
1834  /* try to split problem into two smaller ones */
1835  if( len>x_nb )
1836  {
1837  ae_int_t n1, n2;
1838  x_split_length(len, x_nb, &n1, &n2);
1839  is_symmetric_rec_diag_stat(a, offset, n1, nonfinite, mx, err, _state);
1840  is_symmetric_rec_diag_stat(a, offset+n1, n2, nonfinite, mx, err, _state);
1841  is_symmetric_rec_off_stat(a, offset+n1, offset, n2, n1, nonfinite, mx, err, _state);
1842  return;
1843  }
1844 
1845  /* base case */
1846  p = (double*)(a->ptr)+offset*a->stride+offset;
1847  for(i=0; i<len; i++)
1848  {
1849  pcol = p+i;
1850  prow = p+i*a->stride;
1851  for(j=0; j<i; j++,pcol+=a->stride,prow++)
1852  {
1853  if( !ae_isfinite(*pcol,_state) || !ae_isfinite(*prow,_state) )
1854  {
1855  *nonfinite = ae_true;
1856  }
1857  else
1858  {
1859  v = fabs(*pcol);
1860  *mx = *mx>v ? *mx : v;
1861  v = fabs(*prow);
1862  *mx = *mx>v ? *mx : v;
1863  v = fabs(*pcol-*prow);
1864  *err = *err>v ? *err : v;
1865  }
1866  }
1867  v = fabs(p[i+i*a->stride]);
1868  *mx = *mx>v ? *mx : v;
1869  }
1870 }
1871 /*
1872  * this function checks difference between offdiagonal blocks BL and BU
1873  * (see below). Block BL is specified by offsets (offset0,offset1) and
1874  * sizes (len0,len1).
1875  *
1876  * [ . ]
1877  * [ A0 BU ]
1878  * A = [ BL A1 ]
1879  * [ . ]
1880  *
1881  * this subroutine updates current values of:
1882  * a) mx maximum value of A[i,j] found so far
1883  * b) err componentwise difference between elements of BL and BU^H
1884  *
1885  */
1886 static void is_hermitian_rec_off_stat(x_matrix *a, ae_int_t offset0, ae_int_t offset1, ae_int_t len0, ae_int_t len1, ae_bool *nonfinite, double *mx, double *err, ae_state *_state)
1887 {
1888  /* try to split problem into two smaller ones */
1889  if( len0>x_nb || len1>x_nb )
1890  {
1891  ae_int_t n1, n2;
1892  if( len0>len1 )
1893  {
1894  x_split_length(len0, x_nb, &n1, &n2);
1895  is_hermitian_rec_off_stat(a, offset0, offset1, n1, len1, nonfinite, mx, err, _state);
1896  is_hermitian_rec_off_stat(a, offset0+n1, offset1, n2, len1, nonfinite, mx, err, _state);
1897  }
1898  else
1899  {
1900  x_split_length(len1, x_nb, &n1, &n2);
1901  is_hermitian_rec_off_stat(a, offset0, offset1, len0, n1, nonfinite, mx, err, _state);
1902  is_hermitian_rec_off_stat(a, offset0, offset1+n1, len0, n2, nonfinite, mx, err, _state);
1903  }
1904  return;
1905  }
1906  else
1907  {
1908  /* base case */
1909  ae_complex *p1, *p2, *prow, *pcol;
1910  double v;
1911  ae_int_t i, j;
1912 
1913  p1 = (ae_complex*)(a->ptr)+offset0*a->stride+offset1;
1914  p2 = (ae_complex*)(a->ptr)+offset1*a->stride+offset0;
1915  for(i=0; i<len0; i++)
1916  {
1917  pcol = p2+i;
1918  prow = p1+i*a->stride;
1919  for(j=0; j<len1; j++)
1920  {
1921  if( !ae_isfinite(pcol->x, _state) || !ae_isfinite(pcol->y, _state) || !ae_isfinite(prow->x, _state) || !ae_isfinite(prow->y, _state) )
1922  {
1923  *nonfinite = ae_true;
1924  }
1925  else
1926  {
1927  v = x_safepythag2(pcol->x, pcol->y);
1928  *mx = *mx>v ? *mx : v;
1929  v = x_safepythag2(prow->x, prow->y);
1930  *mx = *mx>v ? *mx : v;
1931  v = x_safepythag2(pcol->x-prow->x, pcol->y+prow->y);
1932  *err = *err>v ? *err : v;
1933  }
1934  pcol += a->stride;
1935  prow++;
1936  }
1937  }
1938  }
1939 }
1940 /*
1941  * this function checks that diagonal block A0 is Hermitian.
1942  * Block A0 is specified by its offset and size.
1943  *
1944  * [ . ]
1945  * [ A0 ]
1946  * A = [ . ]
1947  * [ . ]
1948  *
1949  * this subroutine updates current values of:
1950  * a) mx maximum value of A[i,j] found so far
1951  * b) err componentwise difference between A0 and A0^H
1952  *
1953  */
1954 static void is_hermitian_rec_diag_stat(x_matrix *a, ae_int_t offset, ae_int_t len, ae_bool *nonfinite, double *mx, double *err, ae_state *_state)
1955 {
1956  ae_complex *p, *prow, *pcol;
1957  double v;
1958  ae_int_t i, j;
1959 
1960  /* try to split problem into two smaller ones */
1961  if( len>x_nb )
1962  {
1963  ae_int_t n1, n2;
1964  x_split_length(len, x_nb, &n1, &n2);
1965  is_hermitian_rec_diag_stat(a, offset, n1, nonfinite, mx, err, _state);
1966  is_hermitian_rec_diag_stat(a, offset+n1, n2, nonfinite, mx, err, _state);
1967  is_hermitian_rec_off_stat(a, offset+n1, offset, n2, n1, nonfinite, mx, err, _state);
1968  return;
1969  }
1970 
1971  /* base case */
1972  p = (ae_complex*)(a->ptr)+offset*a->stride+offset;
1973  for(i=0; i<len; i++)
1974  {
1975  pcol = p+i;
1976  prow = p+i*a->stride;
1977  for(j=0; j<i; j++,pcol+=a->stride,prow++)
1978  {
1979  if( !ae_isfinite(pcol->x, _state) || !ae_isfinite(pcol->y, _state) || !ae_isfinite(prow->x, _state) || !ae_isfinite(prow->y, _state) )
1980  {
1981  *nonfinite = ae_true;
1982  }
1983  else
1984  {
1985  v = x_safepythag2(pcol->x, pcol->y);
1986  *mx = *mx>v ? *mx : v;
1987  v = x_safepythag2(prow->x, prow->y);
1988  *mx = *mx>v ? *mx : v;
1989  v = x_safepythag2(pcol->x-prow->x, pcol->y+prow->y);
1990  *err = *err>v ? *err : v;
1991  }
1992  }
1993  if( !ae_isfinite(p[i+i*a->stride].x, _state) || !ae_isfinite(p[i+i*a->stride].y, _state) )
1994  {
1995  *nonfinite = ae_true;
1996  }
1997  else
1998  {
1999  v = fabs(p[i+i*a->stride].x);
2000  *mx = *mx>v ? *mx : v;
2001  v = fabs(p[i+i*a->stride].y);
2002  *err = *err>v ? *err : v;
2003  }
2004  }
2005 }
2006 /*
2007  * this function copies offdiagonal block BL to its symmetric counterpart
2008  * BU (see below). Block BL is specified by offsets (offset0,offset1)
2009  * and sizes (len0,len1).
2010  *
2011  * [ . ]
2012  * [ A0 BU ]
2013  * A = [ BL A1 ]
2014  * [ . ]
2015  *
2016  */
2017 static void force_symmetric_rec_off_stat(x_matrix *a, ae_int_t offset0, ae_int_t offset1, ae_int_t len0, ae_int_t len1)
2018 {
2019  /* try to split problem into two smaller ones */
2020  if( len0>x_nb || len1>x_nb )
2021  {
2022  ae_int_t n1, n2;
2023  if( len0>len1 )
2024  {
2025  x_split_length(len0, x_nb, &n1, &n2);
2026  force_symmetric_rec_off_stat(a, offset0, offset1, n1, len1);
2027  force_symmetric_rec_off_stat(a, offset0+n1, offset1, n2, len1);
2028  }
2029  else
2030  {
2031  x_split_length(len1, x_nb, &n1, &n2);
2032  force_symmetric_rec_off_stat(a, offset0, offset1, len0, n1);
2033  force_symmetric_rec_off_stat(a, offset0, offset1+n1, len0, n2);
2034  }
2035  return;
2036  }
2037  else
2038  {
2039  /* base case */
2040  double *p1, *p2, *prow, *pcol;
2041  ae_int_t i, j;
2042 
2043  p1 = (double*)(a->ptr)+offset0*a->stride+offset1;
2044  p2 = (double*)(a->ptr)+offset1*a->stride+offset0;
2045  for(i=0; i<len0; i++)
2046  {
2047  pcol = p2+i;
2048  prow = p1+i*a->stride;
2049  for(j=0; j<len1; j++)
2050  {
2051  *pcol = *prow;
2052  pcol += a->stride;
2053  prow++;
2054  }
2055  }
2056  }
2057 }
2058 /*
2059  * this function copies lower part of diagonal block A0 to its upper part
2060  * Block is specified by offset and size.
2061  *
2062  * [ . ]
2063  * [ A0 ]
2064  * A = [ . ]
2065  * [ . ]
2066  *
2067  */
2068 static void force_symmetric_rec_diag_stat(x_matrix *a, ae_int_t offset, ae_int_t len)
2069 {
2070  double *p, *prow, *pcol;
2071  ae_int_t i, j;
2072 
2073  /* try to split problem into two smaller ones */
2074  if( len>x_nb )
2075  {
2076  ae_int_t n1, n2;
2077  x_split_length(len, x_nb, &n1, &n2);
2078  force_symmetric_rec_diag_stat(a, offset, n1);
2079  force_symmetric_rec_diag_stat(a, offset+n1, n2);
2080  force_symmetric_rec_off_stat(a, offset+n1, offset, n2, n1);
2081  return;
2082  }
2083 
2084  /* base case */
2085  p = (double*)(a->ptr)+offset*a->stride+offset;
2086  for(i=0; i<len; i++)
2087  {
2088  pcol = p+i;
2089  prow = p+i*a->stride;
2090  for(j=0; j<i; j++,pcol+=a->stride,prow++)
2091  *pcol = *prow;
2092  }
2093 }
2094 /*
2095  * this function copies Hermitian transpose of offdiagonal block BL to
2096  * its symmetric counterpart BU (see below). Block BL is specified by
2097  * offsets (offset0,offset1) and sizes (len0,len1).
2098  *
2099  * [ . ]
2100  * [ A0 BU ]
2101  * A = [ BL A1 ]
2102  * [ . ]
2103  */
2104 static void force_hermitian_rec_off_stat(x_matrix *a, ae_int_t offset0, ae_int_t offset1, ae_int_t len0, ae_int_t len1)
2105 {
2106  /* try to split problem into two smaller ones */
2107  if( len0>x_nb || len1>x_nb )
2108  {
2109  ae_int_t n1, n2;
2110  if( len0>len1 )
2111  {
2112  x_split_length(len0, x_nb, &n1, &n2);
2113  force_hermitian_rec_off_stat(a, offset0, offset1, n1, len1);
2114  force_hermitian_rec_off_stat(a, offset0+n1, offset1, n2, len1);
2115  }
2116  else
2117  {
2118  x_split_length(len1, x_nb, &n1, &n2);
2119  force_hermitian_rec_off_stat(a, offset0, offset1, len0, n1);
2120  force_hermitian_rec_off_stat(a, offset0, offset1+n1, len0, n2);
2121  }
2122  return;
2123  }
2124  else
2125  {
2126  /* base case */
2127  ae_complex *p1, *p2, *prow, *pcol;
2128  ae_int_t i, j;
2129 
2130  p1 = (ae_complex*)(a->ptr)+offset0*a->stride+offset1;
2131  p2 = (ae_complex*)(a->ptr)+offset1*a->stride+offset0;
2132  for(i=0; i<len0; i++)
2133  {
2134  pcol = p2+i;
2135  prow = p1+i*a->stride;
2136  for(j=0; j<len1; j++)
2137  {
2138  *pcol = *prow;
2139  pcol += a->stride;
2140  prow++;
2141  }
2142  }
2143  }
2144 }
2145 /*
2146  * this function copies Hermitian transpose of lower part of
2147  * diagonal block A0 to its upper part Block is specified by offset and size.
2148  *
2149  * [ . ]
2150  * [ A0 ]
2151  * A = [ . ]
2152  * [ . ]
2153  *
2154  */
2155 static void force_hermitian_rec_diag_stat(x_matrix *a, ae_int_t offset, ae_int_t len)
2156 {
2157  ae_complex *p, *prow, *pcol;
2158  ae_int_t i, j;
2159 
2160  /* try to split problem into two smaller ones */
2161  if( len>x_nb )
2162  {
2163  ae_int_t n1, n2;
2164  x_split_length(len, x_nb, &n1, &n2);
2165  force_hermitian_rec_diag_stat(a, offset, n1);
2166  force_hermitian_rec_diag_stat(a, offset+n1, n2);
2167  force_hermitian_rec_off_stat(a, offset+n1, offset, n2, n1);
2168  return;
2169  }
2170 
2171  /* base case */
2172  p = (ae_complex*)(a->ptr)+offset*a->stride+offset;
2173  for(i=0; i<len; i++)
2174  {
2175  pcol = p+i;
2176  prow = p+i*a->stride;
2177  for(j=0; j<i; j++,pcol+=a->stride,prow++)
2178  *pcol = *prow;
2179  }
2180 }
2182 {
2183  double mx, err;
2184  ae_bool nonfinite;
2185  ae_state _alglib_env_state;
2186  if( a->datatype!=DT_REAL )
2187  return ae_false;
2188  if( a->cols!=a->rows )
2189  return ae_false;
2190  if( a->cols==0 || a->rows==0 )
2191  return ae_true;
2192  ae_state_init(&_alglib_env_state);
2193  mx = 0;
2194  err = 0;
2195  nonfinite = ae_false;
2196  is_symmetric_rec_diag_stat(a, 0, (ae_int_t)a->rows, &nonfinite, &mx, &err, &_alglib_env_state);
2197  if( nonfinite )
2198  return ae_false;
2199  if( mx==0 )
2200  return ae_true;
2201  return err/mx<=1.0E-14;
2202 }
2204 {
2205  double mx, err;
2206  ae_bool nonfinite;
2207  ae_state _alglib_env_state;
2208  if( a->datatype!=DT_COMPLEX )
2209  return ae_false;
2210  if( a->cols!=a->rows )
2211  return ae_false;
2212  if( a->cols==0 || a->rows==0 )
2213  return ae_true;
2214  ae_state_init(&_alglib_env_state);
2215  mx = 0;
2216  err = 0;
2217  nonfinite = ae_false;
2218  is_hermitian_rec_diag_stat(a, 0, (ae_int_t)a->rows, &nonfinite, &mx, &err, &_alglib_env_state);
2219  if( nonfinite )
2220  return ae_false;
2221  if( mx==0 )
2222  return ae_true;
2223  return err/mx<=1.0E-14;
2224 }
2226 {
2227  if( a->datatype!=DT_REAL )
2228  return ae_false;
2229  if( a->cols!=a->rows )
2230  return ae_false;
2231  if( a->cols==0 || a->rows==0 )
2232  return ae_true;
2233  force_symmetric_rec_diag_stat(a, 0, (ae_int_t)a->rows);
2234  return ae_true;
2235 }
2237 {
2238  if( a->datatype!=DT_COMPLEX )
2239  return ae_false;
2240  if( a->cols!=a->rows )
2241  return ae_false;
2242  if( a->cols==0 || a->rows==0 )
2243  return ae_true;
2244  force_hermitian_rec_diag_stat(a, 0, (ae_int_t)a->rows);
2245  return ae_true;
2246 }
2247 
2249 {
2250  x_matrix x;
2251  x.owner = OWN_CALLER;
2252  ae_x_attach_to_matrix(&x, a);
2253  return x_is_symmetric(&x);
2254 }
2255 
2257 {
2258  x_matrix x;
2259  x.owner = OWN_CALLER;
2260  ae_x_attach_to_matrix(&x, a);
2261  return x_is_hermitian(&x);
2262 }
2263 
2265 {
2266  x_matrix x;
2267  x.owner = OWN_CALLER;
2268  ae_x_attach_to_matrix(&x, a);
2269  return x_force_symmetric(&x);
2270 }
2271 
2273 {
2274  x_matrix x;
2275  x.owner = OWN_CALLER;
2276  ae_x_attach_to_matrix(&x, a);
2277  return x_force_hermitian(&x);
2278 }
2279 
2280 /************************************************************************
2281 This function converts six-bit value (from 0 to 63) to character (only
2282 digits, lowercase and uppercase letters, minus and underscore are used).
2283 
2284 If v is negative or greater than 63, this function returns '?'.
2285 ************************************************************************/
2286 static char _sixbits2char_tbl[64] = {
2287  '0', '1', '2', '3', '4', '5', '6', '7',
2288  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
2289  'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
2290  'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
2291  'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
2292  'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
2293  'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
2294  'u', 'v', 'w', 'x', 'y', 'z', '-', '_' };
2295 
2297 {
2298 
2299  if( v<0 || v>63 )
2300  return '?';
2301  return _sixbits2char_tbl[v];
2302 
2303  /* v is correct, process it */
2304  /*if( v<10 )
2305  return '0'+v;
2306  v -= 10;
2307  if( v<26 )
2308  return 'A'+v;
2309  v -= 26;
2310  if( v<26 )
2311  return 'a'+v;
2312  v -= 26;
2313  return v==0 ? '-' : '_';*/
2314 }
2315 
2316 /************************************************************************
2317 This function converts character to six-bit value (from 0 to 63).
2318 
2319 This function is inverse of ae_sixbits2char()
2320 If c is not correct character, this function returns -1.
2321 ************************************************************************/
2322 static ae_int_t _ae_char2sixbits_tbl[] = {
2323  -1, -1, -1, -1, -1, -1, -1, -1,
2324  -1, -1, -1, -1, -1, -1, -1, -1,
2325  -1, -1, -1, -1, -1, -1, -1, -1,
2326  -1, -1, -1, -1, -1, -1, -1, -1,
2327  -1, -1, -1, -1, -1, -1, -1, -1,
2328  -1, -1, -1, -1, -1, 62, -1, -1,
2329  0, 1, 2, 3, 4, 5, 6, 7,
2330  8, 9, -1, -1, -1, -1, -1, -1,
2331  -1, 10, 11, 12, 13, 14, 15, 16,
2332  17, 18, 19, 20, 21, 22, 23, 24,
2333  25, 26, 27, 28, 29, 30, 31, 32,
2334  33, 34, 35, -1, -1, -1, -1, 63,
2335  -1, 36, 37, 38, 39, 40, 41, 42,
2336  43, 44, 45, 46, 47, 48, 49, 50,
2337  51, 52, 53, 54, 55, 56, 57, 58,
2338  59, 60, 61, -1, -1, -1, -1, -1 };
2340 {
2341  return (c>=0 && c<127) ? _ae_char2sixbits_tbl[(int)c] : -1;
2342 }
2343 
2344 /************************************************************************
2345 This function converts three bytes (24 bits) to four six-bit values
2346 (24 bits again).
2347 
2348 src pointer to three bytes
2349 dst pointer to four ints
2350 ************************************************************************/
2351 void ae_threebytes2foursixbits(const unsigned char *src, ae_int_t *dst)
2352 {
2353  dst[0] = src[0] & 0x3F;
2354  dst[1] = (src[0]>>6) | ((src[1]&0x0F)<<2);
2355  dst[2] = (src[1]>>4) | ((src[2]&0x03)<<4);
2356  dst[3] = src[2]>>2;
2357 }
2358 
2359 /************************************************************************
2360 This function converts four six-bit values (24 bits) to three bytes
2361 (24 bits again).
2362 
2363 src pointer to four ints
2364 dst pointer to three bytes
2365 ************************************************************************/
2366 void ae_foursixbits2threebytes(const ae_int_t *src, unsigned char *dst)
2367 {
2368  dst[0] = (unsigned char)( src[0] | ((src[1]&0x03)<<6));
2369  dst[1] = (unsigned char)((src[1]>>2) | ((src[2]&0x0F)<<4));
2370  dst[2] = (unsigned char)((src[2]>>4) | (src[3]<<2));
2371 }
2372 
2373 /************************************************************************
2374 This function serializes boolean value into buffer
2375 
2376 v boolean value to be serialized
2377 buf buffer, at least 12 characters wide
2378  (11 chars for value, one for trailing zero)
2379 state ALGLIB environment state
2380 ************************************************************************/
2381 void ae_bool2str(ae_bool v, char *buf, ae_state *state)
2382 {
2383  char c = v ? '1' : '0';
2384  ae_int_t i;
2385  for(i=0; i<AE_SER_ENTRY_LENGTH; i++)
2386  buf[i] = c;
2387  buf[AE_SER_ENTRY_LENGTH] = 0;
2388 }
2389 
2390 /************************************************************************
2391 This function unserializes boolean value from buffer
2392 
2393 buf buffer which contains value; leading spaces/tabs/newlines are
2394  ignored, traling spaces/tabs/newlines are treated as end of
2395  the boolean value.
2396 state ALGLIB environment state
2397 
2398 This function raises an error in case unexpected symbol is found
2399 ************************************************************************/
2400 ae_bool ae_str2bool(const char *buf, ae_state *state, const char **pasttheend)
2401 {
2402  ae_bool was0, was1;
2403  const char *emsg = "ALGLIB: unable to read boolean value from stream";
2404 
2405  was0 = ae_false;
2406  was1 = ae_false;
2407  while( *buf==' ' || *buf=='\t' || *buf=='\n' || *buf=='\r' )
2408  buf++;
2409  while( *buf!=' ' && *buf!='\t' && *buf!='\n' && *buf!='\r' && *buf!=0 )
2410  {
2411  if( *buf=='0' )
2412  {
2413  was0 = ae_true;
2414  buf++;
2415  continue;
2416  }
2417  if( *buf=='1' )
2418  {
2419  was1 = ae_true;
2420  buf++;
2421  continue;
2422  }
2423  ae_break(state, ERR_ASSERTION_FAILED, emsg);
2424  }
2425  *pasttheend = buf;
2426  if( (!was0) && (!was1) )
2427  ae_break(state, ERR_ASSERTION_FAILED, emsg);
2428  if( was0 && was1 )
2429  ae_break(state, ERR_ASSERTION_FAILED, emsg);
2430  return was1 ? ae_true : ae_false;
2431 }
2432 
2433 /************************************************************************
2434 This function serializes integer value into buffer
2435 
2436 v integer value to be serialized
2437 buf buffer, at least 12 characters wide
2438  (11 chars for value, one for trailing zero)
2439 state ALGLIB environment state
2440 ************************************************************************/
2441 void ae_int2str(ae_int_t v, char *buf, ae_state *state)
2442 {
2443  union _u
2444  {
2445  ae_int_t ival;
2446  unsigned char bytes[9];
2447  } u;
2448  ae_int_t i;
2449  ae_int_t sixbits[12];
2450  unsigned char c;
2451 
2452  /*
2453  * copy v to array of chars, sign extending it and
2454  * converting to little endian order
2455  *
2456  * because we don't want to mention size of ae_int_t explicitly,
2457  * we do it as follows:
2458  * 1. we fill u.bytes by zeros or ones (depending on sign of v)
2459  * 2. we copy v to u.ival
2460  * 3. if we run on big endian architecture, we reorder u.bytes
2461  * 4. now we have signed 64-bit representation of v stored in u.bytes
2462  * 5. additionally, we set 9th byte of u.bytes to zero in order to
2463  * simplify conversion to six-bit representation
2464  */
2465  c = v<0 ? (unsigned char)0xFF : (unsigned char)0x00;
2466  u.ival = v;
2467  for(i=sizeof(ae_int_t); i<=8; i++) /* <=8 is preferred because it avoids unnecessary compiler warnings*/
2468  u.bytes[i] = c;
2469  u.bytes[8] = 0;
2470  if( state->endianness==AE_BIG_ENDIAN )
2471  {
2472  for(i=0; i<(ae_int_t)(sizeof(ae_int_t)/2); i++)
2473  {
2474  unsigned char tc;
2475  tc = u.bytes[i];
2476  u.bytes[i] = u.bytes[sizeof(ae_int_t)-1-i];
2477  u.bytes[sizeof(ae_int_t)-1-i] = tc;
2478  }
2479  }
2480 
2481  /*
2482  * convert to six-bit representation, output
2483  *
2484  * NOTE: last 12th element of sixbits is always zero, we do not output it
2485  */
2486  ae_threebytes2foursixbits(u.bytes+0, sixbits+0);
2487  ae_threebytes2foursixbits(u.bytes+3, sixbits+4);
2488  ae_threebytes2foursixbits(u.bytes+6, sixbits+8);
2489  for(i=0; i<AE_SER_ENTRY_LENGTH; i++)
2490  buf[i] = ae_sixbits2char(sixbits[i]);
2491  buf[AE_SER_ENTRY_LENGTH] = 0x00;
2492 }
2493 
2494 /************************************************************************
2495 This function unserializes integer value from string
2496 
2497 buf buffer which contains value; leading spaces/tabs/newlines are
2498  ignored, traling spaces/tabs/newlines are treated as end of
2499  the boolean value.
2500 state ALGLIB environment state
2501 
2502 This function raises an error in case unexpected symbol is found
2503 ************************************************************************/
2504 ae_int_t ae_str2int(const char *buf, ae_state *state, const char **pasttheend)
2505 {
2506  const char *emsg = "ALGLIB: unable to read integer value from stream";
2507  ae_int_t sixbits[12];
2508  ae_int_t sixbitsread, i;
2509  union _u
2510  {
2511  ae_int_t ival;
2512  unsigned char bytes[9];
2513  } u;
2514  /*
2515  * 1. skip leading spaces
2516  * 2. read and decode six-bit digits
2517  * 3. set trailing digits to zeros
2518  * 4. convert to little endian 64-bit integer representation
2519  * 5. convert to big endian representation, if needed
2520  */
2521  while( *buf==' ' || *buf=='\t' || *buf=='\n' || *buf=='\r' )
2522  buf++;
2523  sixbitsread = 0;
2524  while( *buf!=' ' && *buf!='\t' && *buf!='\n' && *buf!='\r' && *buf!=0 )
2525  {
2526  ae_int_t d;
2527  d = ae_char2sixbits(*buf);
2528  if( d<0 || sixbitsread>=AE_SER_ENTRY_LENGTH )
2529  ae_break(state, ERR_ASSERTION_FAILED, emsg);
2530  sixbits[sixbitsread] = d;
2531  sixbitsread++;
2532  buf++;
2533  }
2534  *pasttheend = buf;
2535  if( sixbitsread==0 )
2536  ae_break(state, ERR_ASSERTION_FAILED, emsg);
2537  for(i=sixbitsread; i<12; i++)
2538  sixbits[i] = 0;
2539  ae_foursixbits2threebytes(sixbits+0, u.bytes+0);
2540  ae_foursixbits2threebytes(sixbits+4, u.bytes+3);
2541  ae_foursixbits2threebytes(sixbits+8, u.bytes+6);
2542  if( state->endianness==AE_BIG_ENDIAN )
2543  {
2544  for(i=0; i<(ae_int_t)(sizeof(ae_int_t)/2); i++)
2545  {
2546  unsigned char tc;
2547  tc = u.bytes[i];
2548  u.bytes[i] = u.bytes[sizeof(ae_int_t)-1-i];
2549  u.bytes[sizeof(ae_int_t)-1-i] = tc;
2550  }
2551  }
2552  return u.ival;
2553 }
2554 
2555 
2556 /************************************************************************
2557 This function serializes double value into buffer
2558 
2559 v double value to be serialized
2560 buf buffer, at least 12 characters wide
2561  (11 chars for value, one for trailing zero)
2562 state ALGLIB environment state
2563 ************************************************************************/
2564 void ae_double2str(double v, char *buf, ae_state *state)
2565 {
2566  union _u
2567  {
2568  double dval;
2569  unsigned char bytes[9];
2570  } u;
2571  ae_int_t i;
2572  ae_int_t sixbits[12];
2573 
2574  /*
2575  * handle special quantities
2576  */
2577  if( ae_isnan(v, state) )
2578  {
2579  const char *s = ".nan_______";
2580  memcpy(buf, s, strlen(s)+1);
2581  return;
2582  }
2583  if( ae_isposinf(v, state) )
2584  {
2585  const char *s = ".posinf____";
2586  memcpy(buf, s, strlen(s)+1);
2587  return;
2588  }
2589  if( ae_isneginf(v, state) )
2590  {
2591  const char *s = ".neginf____";
2592  memcpy(buf, s, strlen(s)+1);
2593  return;
2594  }
2595 
2596  /*
2597  * process general case:
2598  * 1. copy v to array of chars
2599  * 2. set 9th byte of u.bytes to zero in order to
2600  * simplify conversion to six-bit representation
2601  * 3. convert to little endian (if needed)
2602  * 4. convert to six-bit representation
2603  * (last 12th element of sixbits is always zero, we do not output it)
2604  */
2605  u.dval = v;
2606  u.bytes[8] = 0;
2607  if( state->endianness==AE_BIG_ENDIAN )
2608  {
2609  for(i=0; i<(ae_int_t)(sizeof(double)/2); i++)
2610  {
2611  unsigned char tc;
2612  tc = u.bytes[i];
2613  u.bytes[i] = u.bytes[sizeof(double)-1-i];
2614  u.bytes[sizeof(double)-1-i] = tc;
2615  }
2616  }
2617  ae_threebytes2foursixbits(u.bytes+0, sixbits+0);
2618  ae_threebytes2foursixbits(u.bytes+3, sixbits+4);
2619  ae_threebytes2foursixbits(u.bytes+6, sixbits+8);
2620  for(i=0; i<AE_SER_ENTRY_LENGTH; i++)
2621  buf[i] = ae_sixbits2char(sixbits[i]);
2622  buf[AE_SER_ENTRY_LENGTH] = 0x00;
2623 }
2624 
2625 /************************************************************************
2626 This function unserializes double value from string
2627 
2628 buf buffer which contains value; leading spaces/tabs/newlines are
2629  ignored, traling spaces/tabs/newlines are treated as end of
2630  the boolean value.
2631 state ALGLIB environment state
2632 
2633 This function raises an error in case unexpected symbol is found
2634 ************************************************************************/
2635 double ae_str2double(const char *buf, ae_state *state, const char **pasttheend)
2636 {
2637  const char *emsg = "ALGLIB: unable to read double value from stream";
2638  ae_int_t sixbits[12];
2639  ae_int_t sixbitsread, i;
2640  union _u
2641  {
2642  double dval;
2643  unsigned char bytes[9];
2644  } u;
2645 
2646 
2647  /*
2648  * skip leading spaces
2649  */
2650  while( *buf==' ' || *buf=='\t' || *buf=='\n' || *buf=='\r' )
2651  buf++;
2652 
2653  /*
2654  * Handle special cases
2655  */
2656  if( *buf=='.' )
2657  {
2658  const char *s_nan = ".nan_______";
2659  const char *s_posinf = ".posinf____";
2660  const char *s_neginf = ".neginf____";
2661  if( strncmp(buf, s_nan, strlen(s_nan))==0 )
2662  {
2663  *pasttheend = buf+strlen(s_nan);
2664  return state->v_nan;
2665  }
2666  if( strncmp(buf, s_posinf, strlen(s_posinf))==0 )
2667  {
2668  *pasttheend = buf+strlen(s_posinf);
2669  return state->v_posinf;
2670  }
2671  if( strncmp(buf, s_neginf, strlen(s_neginf))==0 )
2672  {
2673  *pasttheend = buf+strlen(s_neginf);
2674  return state->v_neginf;
2675  }
2676  ae_break(state, ERR_ASSERTION_FAILED, emsg);
2677  }
2678 
2679  /*
2680  * General case:
2681  * 1. read and decode six-bit digits
2682  * 2. check that all 11 digits were read
2683  * 3. set last 12th digit to zero (needed for simplicity of conversion)
2684  * 4. convert to 8 bytes
2685  * 5. convert to big endian representation, if needed
2686  */
2687  sixbitsread = 0;
2688  while( *buf!=' ' && *buf!='\t' && *buf!='\n' && *buf!='\r' && *buf!=0 )
2689  {
2690  ae_int_t d;
2691  d = ae_char2sixbits(*buf);
2692  if( d<0 || sixbitsread>=AE_SER_ENTRY_LENGTH )
2693  ae_break(state, ERR_ASSERTION_FAILED, emsg);
2694  sixbits[sixbitsread] = d;
2695  sixbitsread++;
2696  buf++;
2697  }
2698  *pasttheend = buf;
2699  if( sixbitsread!=AE_SER_ENTRY_LENGTH )
2700  ae_break(state, ERR_ASSERTION_FAILED, emsg);
2701  sixbits[AE_SER_ENTRY_LENGTH] = 0;
2702  ae_foursixbits2threebytes(sixbits+0, u.bytes+0);
2703  ae_foursixbits2threebytes(sixbits+4, u.bytes+3);
2704  ae_foursixbits2threebytes(sixbits+8, u.bytes+6);
2705  if( state->endianness==AE_BIG_ENDIAN )
2706  {
2707  for(i=0; i<(ae_int_t)(sizeof(double)/2); i++)
2708  {
2709  unsigned char tc;
2710  tc = u.bytes[i];
2711  u.bytes[i] = u.bytes[sizeof(double)-1-i];
2712  u.bytes[sizeof(double)-1-i] = tc;
2713  }
2714  }
2715  return u.dval;
2716 }
2717 
2718 
2719 /************************************************************************
2720 This function performs given number of spin-wait iterations
2721 ************************************************************************/
2723 {
2724  /*
2725  * these strange operations with ae_never_change_it are necessary to
2726  * prevent compiler optimization of the loop.
2727  */
2728  volatile ae_int_t i;
2729 
2730  /* very unlikely because no one will wait for such amount of cycles */
2731  if( cnt>0x12345678 )
2732  ae_never_change_it = cnt%10;
2733 
2734  /* spin wait, test condition which will never be true */
2735  for(i=0; i<cnt; i++)
2736  if( ae_never_change_it>0 )
2737  ae_never_change_it--;
2738 }
2739 
2740 
2741 /************************************************************************
2742 This function causes the calling thread to relinquish the CPU. The thread
2743 is moved to the end of the queue and some other thread gets to run.
2744 
2745 NOTE: this function should NOT be called when AE_OS is AE_UNKNOWN - the
2746  whole program will be abnormally terminated.
2747 ************************************************************************/
2748 void ae_yield()
2749 {
2750 #if AE_OS==AE_WINDOWS
2751  if( !SwitchToThread() )
2752  Sleep(0);
2753 #elif AE_OS==AE_POSIX
2754  sched_yield();
2755 #else
2756  abort();
2757 #endif
2758 }
2759 
2760 /************************************************************************
2761 This function initializes ae_lock structure and sets lock in a free mode.
2762 ************************************************************************/
2764 {
2765 #if AE_OS==AE_WINDOWS
2766  lock->p_lock = (ae_int_t*)ae_align((void*)(&lock->buf),AE_LOCK_ALIGNMENT);
2767  lock->p_lock[0] = 0;
2768 #elif AE_OS==AE_POSIX
2769  pthread_mutex_init(&lock->mutex, NULL);
2770 #else
2771  lock->is_locked = ae_false;
2772 #endif
2773 }
2774 
2775 
2776 /************************************************************************
2777 This function acquires lock. In case lock is busy, we perform several
2778 iterations inside tight loop before trying again.
2779 ************************************************************************/
2781 {
2782 #if AE_OS==AE_WINDOWS
2783  ae_int_t cnt = 0;
2784 #ifdef AE_SMP_DEBUGCOUNTERS
2785  InterlockedIncrement((LONG volatile *)&_ae_dbg_lock_acquisitions);
2786 #endif
2787  for(;;)
2788  {
2789  if( InterlockedCompareExchange((LONG volatile *)lock->p_lock, 1, 0)==0 )
2790  return;
2792 #ifdef AE_SMP_DEBUGCOUNTERS
2793  InterlockedIncrement((LONG volatile *)&_ae_dbg_lock_spinwaits);
2794 #endif
2795  cnt++;
2796  if( cnt%AE_LOCK_TESTS_BEFORE_YIELD==0 )
2797  {
2798 #ifdef AE_SMP_DEBUGCOUNTERS
2799  InterlockedIncrement((LONG volatile *)&_ae_dbg_lock_yields);
2800 #endif
2801  ae_yield();
2802  }
2803  }
2804 #elif AE_OS==AE_POSIX
2805  ae_int_t cnt = 0;
2806  for(;;)
2807  {
2808  if( pthread_mutex_trylock(&lock->mutex)==0 )
2809  return;
2811  cnt++;
2812  if( cnt%AE_LOCK_TESTS_BEFORE_YIELD==0 )
2813  ae_yield();
2814  }
2815  ;
2816 #else
2817  AE_CRITICAL_ASSERT(!lock->is_locked);
2818  lock->is_locked = ae_true;
2819 #endif
2820 }
2821 
2822 
2823 /************************************************************************
2824 This function releases lock.
2825 ************************************************************************/
2827 {
2828 #if AE_OS==AE_WINDOWS
2829  InterlockedExchange((LONG volatile *)lock->p_lock, 0);
2830 #elif AE_OS==AE_POSIX
2831  pthread_mutex_unlock(&lock->mutex);
2832 #else
2833  lock->is_locked = ae_false;
2834 #endif
2835 }
2836 
2837 
2838 /************************************************************************
2839 This function frees ae_lock structure.
2840 ************************************************************************/
2842 {
2843 #if AE_OS==AE_POSIX
2844  pthread_mutex_destroy(&lock->mutex);
2845 #endif
2846 }
2847 
2848 
2849 /************************************************************************
2850 This function creates ae_shared_pool structure.
2851 
2852 dst destination shared pool;
2853  already allocated, but not initialized.
2854 state ALGLIB environment state
2855 make_automatic if true, pool is added to the dynamic block list
2856 
2857 Error handling:
2858 * if state is NULL, returns ae_false on allocation error
2859 * if state is not NULL, calls ae_break() on allocation error
2860 * returns ae_true on success
2861 
2862 dst is assumed to be uninitialized, its fields are ignored.
2863 ************************************************************************/
2864 ae_bool ae_shared_pool_init(void *_dst, ae_state *state, ae_bool make_automatic)
2865 {
2866  ae_shared_pool *dst;
2867 
2868  dst = (ae_shared_pool*)_dst;
2869 
2870  /* init */
2871  dst->seed_object = NULL;
2872  dst->recycled_objects = NULL;
2873  dst->recycled_entries = NULL;
2874  dst->enumeration_counter = NULL;
2875  dst->size_of_object = 0;
2876  dst->init = NULL;
2877  dst->init_copy = NULL;
2878  dst->destroy = NULL;
2880  dst->frame_entry.ptr = dst;
2881  if( make_automatic && state!=NULL )
2882  ae_db_attach(&dst->frame_entry, state);
2883  ae_init_lock(&dst->pool_lock);
2884  return ae_true;
2885 }
2886 
2887 
2888 /************************************************************************
2889 This function clears all dynamically allocated fields of the pool except
2890 for the lock. It does NOT try to acquire pool_lock.
2891 
2892 NOTE: this function is NOT thread-safe, it is not protected by lock.
2893 ************************************************************************/
2894 static void ae_shared_pool_internalclear(ae_shared_pool *dst)
2895 {
2896  ae_shared_pool_entry *ptr, *tmp;
2897 
2898  /* destroy seed */
2899  if( dst->seed_object!=NULL )
2900  {
2901  dst->destroy((void*)dst->seed_object);
2902  ae_free((void*)dst->seed_object);
2903  dst->seed_object = NULL;
2904  }
2905 
2906  /* destroy recycled objects */
2907  for(ptr=dst->recycled_objects; ptr!=NULL;)
2908  {
2909  tmp = (ae_shared_pool_entry*)ptr->next_entry;
2910  dst->destroy(ptr->obj);
2911  ae_free(ptr->obj);
2912  ae_free(ptr);
2913  ptr = tmp;
2914  }
2915  dst->recycled_objects = NULL;
2916 
2917  /* destroy recycled entries */
2918  for(ptr=dst->recycled_entries; ptr!=NULL;)
2919  {
2920  tmp = (ae_shared_pool_entry*)ptr->next_entry;
2921  ae_free(ptr);
2922  ptr = tmp;
2923  }
2924  dst->recycled_entries = NULL;
2925 }
2926 
2927 
2928 /************************************************************************
2929 This function creates copy of ae_shared_pool.
2930 
2931 dst destination pool, allocated but not initialized
2932 src source pool
2933 state ALGLIB environment state
2934 make_automatic if true, pool is added to the dynamic block list
2935 
2936 Error handling:
2937 * if state is NULL, returns ae_false on allocation error
2938 * if state is not NULL, calls ae_break() on allocation error
2939 * returns ae_true on success
2940 
2941 dst is assumed to be uninitialized, its fields are ignored.
2942 
2943 NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
2944  you should NOT call it when lock can be used by another thread.
2945 ************************************************************************/
2946 ae_bool ae_shared_pool_init_copy(void *_dst, void *_src, ae_state *state, ae_bool make_automatic)
2947 {
2948  ae_shared_pool *dst, *src;
2949  ae_shared_pool_entry *ptr;
2950 
2951  dst = (ae_shared_pool*)_dst;
2952  src = (ae_shared_pool*)_src;
2953  if( !ae_shared_pool_init(dst, state, make_automatic) )
2954  return ae_false;
2955 
2956  /* copy non-pointer fields */
2957  dst->size_of_object = src->size_of_object;
2958  dst->init = src->init;
2959  dst->init_copy = src->init_copy;
2960  dst->destroy = src->destroy;
2961  ae_init_lock(&dst->pool_lock);
2962 
2963  /* copy seed object */
2964  if( src->seed_object!=NULL )
2965  {
2966  dst->seed_object = ae_malloc(dst->size_of_object, state);
2967  if( dst->seed_object==NULL )
2968  return ae_false;
2969  if( !dst->init_copy(dst->seed_object, src->seed_object, state, ae_false) )
2970  return ae_false;
2971  }
2972 
2973  /* copy recycled objects */
2974  dst->recycled_objects = NULL;
2975  for(ptr=src->recycled_objects; ptr!=NULL; ptr=(ae_shared_pool_entry*)ptr->next_entry)
2976  {
2977  ae_shared_pool_entry *tmp;
2978  tmp = (ae_shared_pool_entry*)ae_malloc(sizeof(ae_shared_pool_entry), state);
2979  if( tmp==NULL )
2980  return ae_false;
2981  tmp->obj = ae_malloc(dst->size_of_object, state);
2982  if( tmp->obj==NULL )
2983  return ae_false;
2984  if( !dst->init_copy(tmp->obj, ptr->obj, state, ae_false) )
2985  return ae_false;
2986  tmp->next_entry = dst->recycled_objects;
2987  dst->recycled_objects = tmp;
2988  }
2989 
2990  /* recycled entries are not copied because they do not store any information */
2991  dst->recycled_entries = NULL;
2992 
2993  /* enumeration counter is reset on copying */
2994  dst->enumeration_counter = NULL;
2995 
2996  /* initialize frame record */
2998  dst->frame_entry.ptr = dst;
2999 
3000  /* return */
3001  return ae_true;
3002 }
3003 
3004 
3005 /************************************************************************
3006 This function clears contents of the pool, but pool remain usable.
3007 
3008 IMPORTANT: this function invalidates dst, it can not be used after it is
3009  cleared.
3010 
3011 NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
3012  you should NOT call it when lock can be used by another thread.
3013 ************************************************************************/
3014 void ae_shared_pool_clear(void *_dst)
3015 {
3016  ae_shared_pool *dst = (ae_shared_pool*)_dst;
3017 
3018  /* clear seed and lists */
3019  ae_shared_pool_internalclear(dst);
3020 
3021  /* clear fields */
3022  dst->seed_object = NULL;
3023  dst->recycled_objects = NULL;
3024  dst->recycled_entries = NULL;
3025  dst->enumeration_counter = NULL;
3026  dst->size_of_object = 0;
3027  dst->init = NULL;
3028  dst->init_copy = NULL;
3029  dst->destroy = NULL;
3030 }
3031 
3032 
3033 /************************************************************************
3034 This function destroys pool (object is left in invalid state, all
3035 dynamically allocated memory is freed).
3036 
3037 NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
3038  you should NOT call it when lock can be used by another thread.
3039 ************************************************************************/
3040 void ae_shared_pool_destroy(void *_dst)
3041 {
3042  ae_shared_pool *dst = (ae_shared_pool*)_dst;
3043  ae_shared_pool_clear(_dst);
3044  ae_free_lock(&dst->pool_lock);
3045 }
3046 
3047 
3048 /************************************************************************
3049 This function returns True, if internal seed object was set. It returns
3050 False for un-seeded pool.
3051 
3052 dst destination pool (initialized by constructor function)
3053 
3054 NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
3055  you should NOT call it when lock can be used by another thread.
3056 ************************************************************************/
3058 {
3059  ae_shared_pool *dst = (ae_shared_pool*)_dst;
3060  return dst->seed_object!=NULL;
3061 }
3062 
3063 
3064 /************************************************************************
3065 This function sets internal seed object. All objects owned by the pool
3066 (current seed object, recycled objects) are automatically freed.
3067 
3068 dst destination pool (initialized by constructor function)
3069 seed_object new seed object
3070 size_of_object sizeof(), used to allocate memory
3071 init constructor function
3072 init_copy copy constructor
3073 clear destructor function
3074 state ALGLIB environment state
3075 
3076 NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
3077  you should NOT call it when lock can be used by another thread.
3078 ************************************************************************/
3080  ae_shared_pool *dst,
3081  void *seed_object,
3082  ae_int_t size_of_object,
3083  ae_bool (*init)(void* dst, ae_state* state, ae_bool make_automatic),
3084  ae_bool (*init_copy)(void* dst, void* src, ae_state* state, ae_bool make_automatic),
3085  void (*destroy)(void* ptr),
3086  ae_state *state)
3087 {
3088  /* destroy internal objects */
3089  ae_shared_pool_internalclear(dst);
3090 
3091  /* set non-pointer fields */
3092  dst->size_of_object = size_of_object;
3093  dst->init = init;
3094  dst->init_copy = init_copy;
3095  dst->destroy = destroy;
3096 
3097  /* set seed object */
3098  dst->seed_object = ae_malloc(size_of_object, state);
3099  ae_assert(dst->seed_object!=NULL, "ALGLIB: unable to allocate memory for ae_shared_pool_set_seed()", state);
3100  ae_assert(
3101  init_copy(dst->seed_object, seed_object, state, ae_false),
3102  "ALGLIB: unable to initialize seed in ae_shared_pool_set_seed()",
3103  state);
3104 }
3105 
3106 
3107 /************************************************************************
3108 This function retrieves a copy of the seed object from the pool and
3109 stores it to target smart pointer ptr.
3110 
3111 In case target pointer owns non-NULL value, it is deallocated before
3112 storing value retrieved from pool. Target pointer becomes owner of the
3113 value which was retrieved from pool.
3114 
3115 pool pool
3116 pptr pointer to ae_smart_ptr structure
3117 state ALGLIB environment state
3118 
3119 NOTE: this function IS thread-safe. It acquires pool lock during its
3120  operation and can be used simultaneously from several threads.
3121 ************************************************************************/
3123  ae_shared_pool *pool,
3124  ae_smart_ptr *pptr,
3125  ae_state *state)
3126 {
3127  void *new_obj;
3128 
3129  /* assert that pool was seeded */
3130  ae_assert(
3131  pool->seed_object!=NULL,
3132  "ALGLIB: shared pool is not seeded, PoolRetrieve() failed",
3133  state);
3134 
3135  /* acquire lock */
3136  ae_acquire_lock(&pool->pool_lock);
3137 
3138  /* try to reuse recycled objects */
3139  if( pool->recycled_objects!=NULL )
3140  {
3141  void *new_obj;
3142  ae_shared_pool_entry *result;
3143 
3144  /* retrieve entry/object from list of recycled objects */
3145  result = pool->recycled_objects;
3147  new_obj = result->obj;
3148  result->obj = NULL;
3149 
3150  /* move entry to list of recycled entries */
3151  result->next_entry = pool->recycled_entries;
3152  pool->recycled_entries = result;
3153 
3154  /* release lock */
3155  ae_release_lock(&pool->pool_lock);
3156 
3157  /* assign object to smart pointer */
3158  ae_smart_ptr_assign(pptr, new_obj, ae_true, ae_true, pool->destroy);
3159  return;
3160  }
3161 
3162  /* release lock; we do not need it anymore because copy constructor does not modify source variable */
3163  ae_release_lock(&pool->pool_lock);
3164 
3165  /* create new object from seed */
3166  new_obj = ae_malloc(pool->size_of_object, state);
3167  ae_assert(new_obj!=NULL, "ALGLIB: unable to allocate memory for ae_shared_pool_retrieve()", state);
3168  ae_assert(
3169  pool->init_copy(new_obj, pool->seed_object, state, ae_false),
3170  "ALGLIB: unable to initialize object in ae_shared_pool_retrieve()",
3171  state);
3172 
3173  /* assign object to smart pointer and return */
3174  ae_smart_ptr_assign(pptr, new_obj, ae_true, ae_true, pool->destroy);
3175 }
3176 
3177 
3178 /************************************************************************
3179 This function recycles object owned by smart pointer by moving it to
3180 internal storage of the shared pool.
3181 
3182 Source pointer must own the object. After function is over, it owns NULL
3183 pointer.
3184 
3185 pool pool
3186 pptr pointer to ae_smart_ptr structure
3187 state ALGLIB environment state
3188 
3189 NOTE: this function IS thread-safe. It acquires pool lock during its
3190  operation and can be used simultaneously from several threads.
3191 ************************************************************************/
3193  ae_shared_pool *pool,
3194  ae_smart_ptr *pptr,
3195  ae_state *state)
3196 {
3197  ae_shared_pool_entry *new_entry;
3198 
3199  /* assert that pool was seeded */
3200  ae_assert(
3201  pool->seed_object!=NULL,
3202  "ALGLIB: shared pool is not seeded, PoolRecycle() failed",
3203  state);
3204 
3205  /* assert that pointer non-null and owns the object */
3206  ae_assert(pptr->is_owner, "ALGLIB: pptr in ae_shared_pool_recycle() does not own its pointer", state);
3207  ae_assert(pptr->ptr!=NULL, "ALGLIB: pptr in ae_shared_pool_recycle() is NULL", state);
3208 
3209  /* acquire lock */
3210  ae_acquire_lock(&pool->pool_lock);
3211 
3212  /* acquire shared pool entry (reuse one from recycled_entries or malloc new one) */
3213  if( pool->recycled_entries!=NULL )
3214  {
3215  /* reuse previously allocated entry */
3216  new_entry = pool->recycled_entries;
3217  pool->recycled_entries = (ae_shared_pool_entry*)new_entry->next_entry;
3218  }
3219  else
3220  {
3221  /*
3222  * Allocate memory for new entry.
3223  *
3224  * NOTE: we release pool lock during allocation because ae_malloc() may raise
3225  * exception and we do not want our pool to be left in the locked state.
3226  */
3227  ae_release_lock(&pool->pool_lock);
3228  new_entry = (ae_shared_pool_entry*)ae_malloc(sizeof(ae_shared_pool_entry), state);
3229  ae_assert(new_entry!=NULL, "ALGLIB: unable to allocate memory in ae_shared_pool_recycle()", state);
3230  ae_acquire_lock(&pool->pool_lock);
3231  }
3232 
3233  /* add object to the list of recycled objects */
3234  new_entry->obj = pptr->ptr;
3235  new_entry->next_entry = pool->recycled_objects;
3236  pool->recycled_objects = new_entry;
3237 
3238  /* release lock object */
3239  ae_release_lock(&pool->pool_lock);
3240 
3241  /* release source pointer */
3242  ae_smart_ptr_release(pptr);
3243 }
3244 
3245 
3246 /************************************************************************
3247 This function clears internal list of recycled objects, but does not
3248 change seed object managed by the pool.
3249 
3250 pool pool
3251 state ALGLIB environment state
3252 
3253 NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
3254  you should NOT call it when lock can be used by another thread.
3255 ************************************************************************/
3257  ae_shared_pool *pool,
3258  ae_state *state)
3259 {
3260  ae_shared_pool_entry *ptr, *tmp;
3261 
3262  /* clear recycled objects */
3263  for(ptr=pool->recycled_objects; ptr!=NULL;)
3264  {
3265  tmp = (ae_shared_pool_entry*)ptr->next_entry;
3266  pool->destroy(ptr->obj);
3267  ae_free(ptr->obj);
3268  ae_free(ptr);
3269  ptr = tmp;
3270  }
3271  pool->recycled_objects = NULL;
3272 }
3273 
3274 
3275 /************************************************************************
3276 This function allows to enumerate recycled elements of the shared pool.
3277 It stores pointer to the first recycled object in the smart pointer.
3278 
3279 IMPORTANT:
3280 * in case target pointer owns non-NULL value, it is deallocated before
3281  storing value retrieved from pool.
3282 * recycled object IS NOT removed from pool
3283 * target pointer DOES NOT become owner of the new value
3284 * this function IS NOT thread-safe
3285 * you SHOULD NOT modify shared pool during enumeration (although you can
3286  modify state of the objects retrieved from pool)
3287 * in case there is no recycled objects in the pool, NULL is stored to pptr
3288 * in case pool is not seeded, NULL is stored to pptr
3289 
3290 pool pool
3291 pptr pointer to ae_smart_ptr structure
3292 state ALGLIB environment state
3293 ************************************************************************/
3295  ae_shared_pool *pool,
3296  ae_smart_ptr *pptr,
3297  ae_state *state)
3298 {
3299  /* modify internal enumeration counter */
3300  pool->enumeration_counter = pool->recycled_objects;
3301 
3302  /* exit on empty list */
3303  if( pool->enumeration_counter==NULL )
3304  {
3305  ae_smart_ptr_assign(pptr, NULL, ae_false, ae_false, NULL);
3306  return;
3307  }
3308 
3309  /* assign object to smart pointer */
3311 }
3312 
3313 
3314 /************************************************************************
3315 This function allows to enumerate recycled elements of the shared pool.
3316 It stores pointer to the next recycled object in the smart pointer.
3317 
3318 IMPORTANT:
3319 * in case target pointer owns non-NULL value, it is deallocated before
3320  storing value retrieved from pool.
3321 * recycled object IS NOT removed from pool
3322 * target pointer DOES NOT become owner of the new value
3323 * this function IS NOT thread-safe
3324 * you SHOULD NOT modify shared pool during enumeration (although you can
3325  modify state of the objects retrieved from pool)
3326 * in case there is no recycled objects left in the pool, NULL is stored.
3327 * in case pool is not seeded, NULL is stored.
3328 
3329 pool pool
3330 pptr pointer to ae_smart_ptr structure
3331 state ALGLIB environment state
3332 ************************************************************************/
3334  ae_shared_pool *pool,
3335  ae_smart_ptr *pptr,
3336  ae_state *state)
3337 {
3338  /* exit on end of list */
3339  if( pool->enumeration_counter==NULL )
3340  {
3341  ae_smart_ptr_assign(pptr, NULL, ae_false, ae_false, NULL);
3342  return;
3343  }
3344 
3345  /* modify internal enumeration counter */
3347 
3348  /* exit on empty list */
3349  if( pool->enumeration_counter==NULL )
3350  {
3351  ae_smart_ptr_assign(pptr, NULL, ae_false, ae_false, NULL);
3352  return;
3353  }
3354 
3355  /* assign object to smart pointer */
3357 }
3358 
3359 
3360 
3361 /************************************************************************
3362 This function clears internal list of recycled objects and seed object.
3363 However, pool still can be used (after initialization with another seed).
3364 
3365 pool pool
3366 state ALGLIB environment state
3367 
3368 NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
3369  you should NOT call it when lock can be used by another thread.
3370 ************************************************************************/
3372  ae_shared_pool *pool,
3373  ae_state *state)
3374 {
3375  /* clear seed and lists */
3376  ae_shared_pool_internalclear(pool);
3377 
3378  /* clear fields */
3379  pool->seed_object = NULL;
3380  pool->recycled_objects = NULL;
3381  pool->recycled_entries = NULL;
3382  pool->enumeration_counter = NULL;
3383  pool->size_of_object = 0;
3384  pool->init = NULL;
3385  pool->init_copy = NULL;
3386  pool->destroy = NULL;
3387 }
3388 
3389 
3390 /************************************************************************
3391 This function initializes serializer
3392 ************************************************************************/
3394 {
3395  serializer->mode = AE_SM_DEFAULT;
3396  serializer->entries_needed = 0;
3397  serializer->bytes_asked = 0;
3398 }
3399 
3401 {
3402 }
3403 
3405 {
3406  serializer->entries_needed = 0;
3407  serializer->bytes_asked = 0;
3408  serializer->mode = AE_SM_ALLOC;
3409 }
3410 
3412 {
3413  serializer->entries_needed++;
3414 }
3415 
3417 {
3418  ae_int_t rows, lastrowsize, result;
3419 
3420  serializer->mode = AE_SM_READY2S;
3421 
3422  /* if no entries needes (degenerate case) */
3423  if( serializer->entries_needed==0 )
3424  {
3425  serializer->bytes_asked = 1;
3426  return serializer->bytes_asked;
3427  }
3428 
3429  /* non-degenerate case */
3430  rows = serializer->entries_needed/AE_SER_ENTRIES_PER_ROW;
3431  lastrowsize = AE_SER_ENTRIES_PER_ROW;
3432  if( serializer->entries_needed%AE_SER_ENTRIES_PER_ROW )
3433  {
3434  lastrowsize = serializer->entries_needed%AE_SER_ENTRIES_PER_ROW;
3435  rows++;
3436  }
3437 
3438  /* calculate result size */
3439  result = ((rows-1)*AE_SER_ENTRIES_PER_ROW+lastrowsize)*AE_SER_ENTRY_LENGTH;
3440  result += (rows-1)*(AE_SER_ENTRIES_PER_ROW-1)+(lastrowsize-1);
3441  result += rows*2;
3442  serializer->bytes_asked = result;
3443  return result;
3444 }
3445 
3446 #ifdef AE_USE_CPP_SERIALIZATION
3447 void ae_serializer_sstart_str(ae_serializer *serializer, std::string *buf)
3448 {
3449  serializer->mode = AE_SM_TO_CPPSTRING;
3450  serializer->out_cppstr = buf;
3451  serializer->entries_saved = 0;
3452  serializer->bytes_written = 0;
3453 }
3454 #endif
3455 
3456 #ifdef AE_USE_CPP_SERIALIZATION
3457 void ae_serializer_ustart_str(ae_serializer *serializer, const std::string *buf)
3458 {
3459  serializer->mode = AE_SM_FROM_STRING;
3460  serializer->in_str = buf->c_str();
3461 }
3462 #endif
3463 
3464 void ae_serializer_sstart_str(ae_serializer *serializer, char *buf)
3465 {
3466  serializer->mode = AE_SM_TO_STRING;
3467  serializer->out_str = buf;
3468  serializer->out_str[0] = 0;
3469  serializer->entries_saved = 0;
3470  serializer->bytes_written = 0;
3471 }
3472 
3473 void ae_serializer_ustart_str(ae_serializer *serializer, const char *buf)
3474 {
3475  serializer->mode = AE_SM_FROM_STRING;
3476  serializer->in_str = buf;
3477 }
3478 
3480 {
3481  char buf[AE_SER_ENTRY_LENGTH+2+1];
3482  const char *emsg = "ALGLIB: serialization integrity error";
3483  ae_int_t bytes_appended;
3484 
3485  /* prepare serialization, check consistency */
3486  ae_bool2str(v, buf, state);
3487  serializer->entries_saved++;
3488  if( serializer->entries_saved%AE_SER_ENTRIES_PER_ROW )
3489  strcat(buf, " ");
3490  else
3491  strcat(buf, "\r\n");
3492  bytes_appended = (ae_int_t)strlen(buf);
3493  if( serializer->bytes_written+bytes_appended > serializer->bytes_asked )
3494  ae_break(state, ERR_ASSERTION_FAILED, emsg);
3495  serializer->bytes_written += bytes_appended;
3496 
3497  /* append to buffer */
3498 #ifdef AE_USE_CPP_SERIALIZATION
3499  if( serializer->mode==AE_SM_TO_CPPSTRING )
3500  {
3501  *(serializer->out_cppstr) += buf;
3502  return;
3503  }
3504 #endif
3505  if( serializer->mode==AE_SM_TO_STRING )
3506  {
3507  strcat(serializer->out_str, buf);
3508  serializer->out_str += bytes_appended;
3509  return;
3510  }
3511  ae_break(state, ERR_ASSERTION_FAILED, emsg);
3512 }
3513 
3515 {
3516  char buf[AE_SER_ENTRY_LENGTH+2+1];
3517  const char *emsg = "ALGLIB: serialization integrity error";
3518  ae_int_t bytes_appended;
3519 
3520  /* prepare serialization, check consistency */
3521  ae_int2str(v, buf, state);
3522  serializer->entries_saved++;
3523  if( serializer->entries_saved%AE_SER_ENTRIES_PER_ROW )
3524  strcat(buf, " ");
3525  else
3526  strcat(buf, "\r\n");
3527  bytes_appended = (ae_int_t)strlen(buf);
3528  if( serializer->bytes_written+bytes_appended > serializer->bytes_asked )
3529  ae_break(state, ERR_ASSERTION_FAILED, emsg);
3530  serializer->bytes_written += bytes_appended;
3531 
3532  /* append to buffer */
3533 #ifdef AE_USE_CPP_SERIALIZATION
3534  if( serializer->mode==AE_SM_TO_CPPSTRING )
3535  {
3536  *(serializer->out_cppstr) += buf;
3537  return;
3538  }
3539 #endif
3540  if( serializer->mode==AE_SM_TO_STRING )
3541  {
3542  strcat(serializer->out_str, buf);
3543  serializer->out_str += bytes_appended;
3544  return;
3545  }
3546  ae_break(state, ERR_ASSERTION_FAILED, emsg);
3547 }
3548 
3549 void ae_serializer_serialize_double(ae_serializer *serializer, double v, ae_state *state)
3550 {
3551  char buf[AE_SER_ENTRY_LENGTH+2+1];
3552  const char *emsg = "ALGLIB: serialization integrity error";
3553  ae_int_t bytes_appended;
3554 
3555  /* prepare serialization, check consistency */
3556  ae_double2str(v, buf, state);
3557  serializer->entries_saved++;
3558  if( serializer->entries_saved%AE_SER_ENTRIES_PER_ROW )
3559  strcat(buf, " ");
3560  else
3561  strcat(buf, "\r\n");
3562  bytes_appended = (ae_int_t)strlen(buf);
3563  if( serializer->bytes_written+bytes_appended > serializer->bytes_asked )
3564  ae_break(state, ERR_ASSERTION_FAILED, emsg);
3565  serializer->bytes_written += bytes_appended;
3566 
3567  /* append to buffer */
3568 #ifdef AE_USE_CPP_SERIALIZATION
3569  if( serializer->mode==AE_SM_TO_CPPSTRING )
3570  {
3571  *(serializer->out_cppstr) += buf;
3572  return;
3573  }
3574 #endif
3575  if( serializer->mode==AE_SM_TO_STRING )
3576  {
3577  strcat(serializer->out_str, buf);
3578  serializer->out_str += bytes_appended;
3579  return;
3580  }
3581  ae_break(state, ERR_ASSERTION_FAILED, emsg);
3582 }
3583 
3585 {
3586  *v = ae_str2bool(serializer->in_str, state, &serializer->in_str);
3587 }
3588 
3590 {
3591  *v = ae_str2int(serializer->in_str, state, &serializer->in_str);
3592 }
3593 
3594 void ae_serializer_unserialize_double(ae_serializer *serializer, double *v, ae_state *state)
3595 {
3596  *v = ae_str2double(serializer->in_str, state, &serializer->in_str);
3597 }
3598 
3600 {
3601 }
3602 
3603 
3604 /************************************************************************
3605 Complex math functions
3606 ************************************************************************/
3608 {
3609  ae_complex r;
3610  r.x = v;
3611  r.y = 0.0;
3612  return r;
3613 }
3614 
3616 {
3617  ae_complex result;
3618  result.x = -lhs.x;
3619  result.y = -lhs.y;
3620  return result;
3621 }
3622 
3624 {
3625  ae_complex result;
3626  result.x = +lhs.x;
3627  result.y = -lhs.y;
3628  return result;
3629 }
3630 
3632 {
3633  ae_complex result;
3634  result.x = lhs.x*lhs.x-lhs.y*lhs.y;
3635  result.y = 2*lhs.x*lhs.y;
3636  return result;
3637 }
3638 
3640 {
3641  double w;
3642  double xabs;
3643  double yabs;
3644  double v;
3645 
3646  xabs = fabs(z.x);
3647  yabs = fabs(z.y);
3648  w = xabs>yabs ? xabs : yabs;
3649  v = xabs<yabs ? xabs : yabs;
3650  if( v==0 )
3651  return w;
3652  else
3653  {
3654  double t = v/w;
3655  return w*sqrt(1+t*t);
3656  }
3657 }
3658 
3660 {
3661  volatile double x1 = lhs.x;
3662  volatile double x2 = rhs.x;
3663  volatile double y1 = lhs.y;
3664  volatile double y2 = rhs.y;
3665  return x1==x2 && y1==y2;
3666 }
3667 
3669 {
3670  volatile double x1 = lhs.x;
3671  volatile double x2 = rhs.x;
3672  volatile double y1 = lhs.y;
3673  volatile double y2 = rhs.y;
3674  return x1!=x2 || y1!=y2;
3675 }
3676 
3678 {
3679  ae_complex result;
3680  result.x = lhs.x+rhs.x;
3681  result.y = lhs.y+rhs.y;
3682  return result;
3683 }
3684 
3686 {
3687  ae_complex result;
3688  result.x = lhs.x*rhs.x-lhs.y*rhs.y;
3689  result.y = lhs.x*rhs.y+lhs.y*rhs.x;
3690  return result;
3691 }
3692 
3694 {
3695  ae_complex result;
3696  result.x = lhs.x-rhs.x;
3697  result.y = lhs.y-rhs.y;
3698  return result;
3699 }
3700 
3702 {
3703  ae_complex result;
3704  double e;
3705  double f;
3706  if( fabs(rhs.y)<fabs(rhs.x) )
3707  {
3708  e = rhs.y/rhs.x;
3709  f = rhs.x+rhs.y*e;
3710  result.x = (lhs.x+lhs.y*e)/f;
3711  result.y = (lhs.y-lhs.x*e)/f;
3712  }
3713  else
3714  {
3715  e = rhs.x/rhs.y;
3716  f = rhs.y+rhs.x*e;
3717  result.x = (lhs.y+lhs.x*e)/f;
3718  result.y = (-lhs.x+lhs.y*e)/f;
3719  }
3720  return result;
3721 }
3722 
3723 ae_bool ae_c_eq_d(ae_complex lhs, double rhs)
3724 {
3725  volatile double x1 = lhs.x;
3726  volatile double x2 = rhs;
3727  volatile double y1 = lhs.y;
3728  volatile double y2 = 0;
3729  return x1==x2 && y1==y2;
3730 }
3731 
3733 {
3734  volatile double x1 = lhs.x;
3735  volatile double x2 = rhs;
3736  volatile double y1 = lhs.y;
3737  volatile double y2 = 0;
3738  return x1!=x2 || y1!=y2;
3739 }
3740 
3742 {
3743  ae_complex result;
3744  result.x = lhs.x+rhs;
3745  result.y = lhs.y;
3746  return result;
3747 }
3748 
3750 {
3751  ae_complex result;
3752  result.x = lhs.x*rhs;
3753  result.y = lhs.y*rhs;
3754  return result;
3755 }
3756 
3758 {
3759  ae_complex result;
3760  result.x = lhs.x-rhs;
3761  result.y = lhs.y;
3762  return result;
3763 }
3764 
3766 {
3767  ae_complex result;
3768  result.x = lhs-rhs.x;
3769  result.y = -rhs.y;
3770  return result;
3771 }
3772 
3774 {
3775  ae_complex result;
3776  result.x = lhs.x/rhs;
3777  result.y = lhs.y/rhs;
3778  return result;
3779 }
3780 
3782 {
3783  ae_complex result;
3784  double e;
3785  double f;
3786  if( fabs(rhs.y)<fabs(rhs.x) )
3787  {
3788  e = rhs.y/rhs.x;
3789  f = rhs.x+rhs.y*e;
3790  result.x = lhs/f;
3791  result.y = -lhs*e/f;
3792  }
3793  else
3794  {
3795  e = rhs.x/rhs.y;
3796  f = rhs.y+rhs.x*e;
3797  result.x = lhs*e/f;
3798  result.y = -lhs/f;
3799  }
3800  return result;
3801 }
3802 
3803 
3804 /************************************************************************
3805 Complex BLAS operations
3806 ************************************************************************/
3807 ae_complex ae_v_cdotproduct(const ae_complex *v0, ae_int_t stride0, const char *conj0, const ae_complex *v1, ae_int_t stride1, const char *conj1, ae_int_t n)
3808 {
3809  double rx = 0, ry = 0;
3810  ae_int_t i;
3811  ae_bool bconj0 = !((conj0[0]=='N') || (conj0[0]=='n'));
3812  ae_bool bconj1 = !((conj1[0]=='N') || (conj1[0]=='n'));
3813  ae_complex result;
3814  if( bconj0 && bconj1 )
3815  {
3816  double v0x, v0y, v1x, v1y;
3817  for(i=0; i<n; i++, v0+=stride0, v1+=stride1)
3818  {
3819  v0x = v0->x;
3820  v0y = -v0->y;
3821  v1x = v1->x;
3822  v1y = -v1->y;
3823  rx += v0x*v1x-v0y*v1y;
3824  ry += v0x*v1y+v0y*v1x;
3825  }
3826  }
3827  if( !bconj0 && bconj1 )
3828  {
3829  double v0x, v0y, v1x, v1y;
3830  for(i=0; i<n; i++, v0+=stride0, v1+=stride1)
3831  {
3832  v0x = v0->x;
3833  v0y = v0->y;
3834  v1x = v1->x;
3835  v1y = -v1->y;
3836  rx += v0x*v1x-v0y*v1y;
3837  ry += v0x*v1y+v0y*v1x;
3838  }
3839  }
3840  if( bconj0 && !bconj1 )
3841  {
3842  double v0x, v0y, v1x, v1y;
3843  for(i=0; i<n; i++, v0+=stride0, v1+=stride1)
3844  {
3845  v0x = v0->x;
3846  v0y = -v0->y;
3847  v1x = v1->x;
3848  v1y = v1->y;
3849  rx += v0x*v1x-v0y*v1y;
3850  ry += v0x*v1y+v0y*v1x;
3851  }
3852  }
3853  if( !bconj0 && !bconj1 )
3854  {
3855  double v0x, v0y, v1x, v1y;
3856  for(i=0; i<n; i++, v0+=stride0, v1+=stride1)
3857  {
3858  v0x = v0->x;
3859  v0y = v0->y;
3860  v1x = v1->x;
3861  v1y = v1->y;
3862  rx += v0x*v1x-v0y*v1y;
3863  ry += v0x*v1y+v0y*v1x;
3864  }
3865  }
3866  result.x = rx;
3867  result.y = ry;
3868  return result;
3869 }
3870 
3871 void ae_v_cmove(ae_complex *vdst, ae_int_t stride_dst, const ae_complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n)
3872 {
3873  ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
3874  ae_int_t i;
3875  if( stride_dst!=1 || stride_src!=1 )
3876  {
3877  /*
3878  * general unoptimized case
3879  */
3880  if( bconj )
3881  {
3882  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
3883  {
3884  vdst->x = vsrc->x;
3885  vdst->y = -vsrc->y;
3886  }
3887  }
3888  else
3889  {
3890  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
3891  *vdst = *vsrc;
3892  }
3893  }
3894  else
3895  {
3896  /*
3897  * optimized case
3898  */
3899  if( bconj )
3900  {
3901  for(i=0; i<n; i++, vdst++, vsrc++)
3902  {
3903  vdst->x = vsrc->x;
3904  vdst->y = -vsrc->y;
3905  }
3906  }
3907  else
3908  {
3909  for(i=0; i<n; i++, vdst++, vsrc++)
3910  *vdst = *vsrc;
3911  }
3912  }
3913 }
3914 
3915 void ae_v_cmoveneg(ae_complex *vdst, ae_int_t stride_dst, const ae_complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n)
3916 {
3917  ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
3918  ae_int_t i;
3919  if( stride_dst!=1 || stride_src!=1 )
3920  {
3921  /*
3922  * general unoptimized case
3923  */
3924  if( bconj )
3925  {
3926  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
3927  {
3928  vdst->x = -vsrc->x;
3929  vdst->y = vsrc->y;
3930  }
3931  }
3932  else
3933  {
3934  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
3935  {
3936  vdst->x = -vsrc->x;
3937  vdst->y = -vsrc->y;
3938  }
3939  }
3940  }
3941  else
3942  {
3943  /*
3944  * optimized case
3945  */
3946  if( bconj )
3947  {
3948  for(i=0; i<n; i++, vdst++, vsrc++)
3949  {
3950  vdst->x = -vsrc->x;
3951  vdst->y = vsrc->y;
3952  }
3953  }
3954  else
3955  {
3956  for(i=0; i<n; i++, vdst++, vsrc++)
3957  {
3958  vdst->x = -vsrc->x;
3959  vdst->y = -vsrc->y;
3960  }
3961  }
3962  }
3963 }
3964 
3965 void ae_v_cmoved(ae_complex *vdst, ae_int_t stride_dst, const ae_complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha)
3966 {
3967  ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
3968  ae_int_t i;
3969  if( stride_dst!=1 || stride_src!=1 )
3970  {
3971  /*
3972  * general unoptimized case
3973  */
3974  if( bconj )
3975  {
3976  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
3977  {
3978  vdst->x = alpha*vsrc->x;
3979  vdst->y = -alpha*vsrc->y;
3980  }
3981  }
3982  else
3983  {
3984  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
3985  {
3986  vdst->x = alpha*vsrc->x;
3987  vdst->y = alpha*vsrc->y;
3988  }
3989  }
3990  }
3991  else
3992  {
3993  /*
3994  * optimized case
3995  */
3996  if( bconj )
3997  {
3998  for(i=0; i<n; i++, vdst++, vsrc++)
3999  {
4000  vdst->x = alpha*vsrc->x;
4001  vdst->y = -alpha*vsrc->y;
4002  }
4003  }
4004  else
4005  {
4006  for(i=0; i<n; i++, vdst++, vsrc++)
4007  {
4008  vdst->x = alpha*vsrc->x;
4009  vdst->y = alpha*vsrc->y;
4010  }
4011  }
4012  }
4013 }
4014 
4015 void ae_v_cmovec(ae_complex *vdst, ae_int_t stride_dst, const ae_complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, ae_complex alpha)
4016 {
4017  ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
4018  ae_int_t i;
4019  if( stride_dst!=1 || stride_src!=1 )
4020  {
4021  /*
4022  * general unoptimized case
4023  */
4024  if( bconj )
4025  {
4026  double ax = alpha.x, ay = alpha.y;
4027  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4028  {
4029  vdst->x = ax*vsrc->x+ay*vsrc->y;
4030  vdst->y = -ax*vsrc->y+ay*vsrc->x;
4031  }
4032  }
4033  else
4034  {
4035  double ax = alpha.x, ay = alpha.y;
4036  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4037  {
4038  vdst->x = ax*vsrc->x-ay*vsrc->y;
4039  vdst->y = ax*vsrc->y+ay*vsrc->x;
4040  }
4041  }
4042  }
4043  else
4044  {
4045  /*
4046  * highly optimized case
4047  */
4048  if( bconj )
4049  {
4050  double ax = alpha.x, ay = alpha.y;
4051  for(i=0; i<n; i++, vdst++, vsrc++)
4052  {
4053  vdst->x = ax*vsrc->x+ay*vsrc->y;
4054  vdst->y = -ax*vsrc->y+ay*vsrc->x;
4055  }
4056  }
4057  else
4058  {
4059  double ax = alpha.x, ay = alpha.y;
4060  for(i=0; i<n; i++, vdst++, vsrc++)
4061  {
4062  vdst->x = ax*vsrc->x-ay*vsrc->y;
4063  vdst->y = ax*vsrc->y+ay*vsrc->x;
4064  }
4065  }
4066  }
4067 }
4068 
4069 void ae_v_cadd(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n)
4070 {
4071  ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
4072  ae_int_t i;
4073  if( stride_dst!=1 || stride_src!=1 )
4074  {
4075  /*
4076  * general unoptimized case
4077  */
4078  if( bconj )
4079  {
4080  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4081  {
4082  vdst->x += vsrc->x;
4083  vdst->y -= vsrc->y;
4084  }
4085  }
4086  else
4087  {
4088  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4089  {
4090  vdst->x += vsrc->x;
4091  vdst->y += vsrc->y;
4092  }
4093  }
4094  }
4095  else
4096  {
4097  /*
4098  * optimized case
4099  */
4100  if( bconj )
4101  {
4102  for(i=0; i<n; i++, vdst++, vsrc++)
4103  {
4104  vdst->x += vsrc->x;
4105  vdst->y -= vsrc->y;
4106  }
4107  }
4108  else
4109  {
4110  for(i=0; i<n; i++, vdst++, vsrc++)
4111  {
4112  vdst->x += vsrc->x;
4113  vdst->y += vsrc->y;
4114  }
4115  }
4116  }
4117 }
4118 
4119 void ae_v_caddd(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha)
4120 {
4121  ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
4122  ae_int_t i;
4123  if( stride_dst!=1 || stride_src!=1 )
4124  {
4125  /*
4126  * general unoptimized case
4127  */
4128  if( bconj )
4129  {
4130  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4131  {
4132  vdst->x += alpha*vsrc->x;
4133  vdst->y -= alpha*vsrc->y;
4134  }
4135  }
4136  else
4137  {
4138  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4139  {
4140  vdst->x += alpha*vsrc->x;
4141  vdst->y += alpha*vsrc->y;
4142  }
4143  }
4144  }
4145  else
4146  {
4147  /*
4148  * optimized case
4149  */
4150  if( bconj )
4151  {
4152  for(i=0; i<n; i++, vdst++, vsrc++)
4153  {
4154  vdst->x += alpha*vsrc->x;
4155  vdst->y -= alpha*vsrc->y;
4156  }
4157  }
4158  else
4159  {
4160  for(i=0; i<n; i++, vdst++, vsrc++)
4161  {
4162  vdst->x += alpha*vsrc->x;
4163  vdst->y += alpha*vsrc->y;
4164  }
4165  }
4166  }
4167 }
4168 
4169 void ae_v_caddc(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, ae_complex alpha)
4170 {
4171  ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
4172  ae_int_t i;
4173  if( stride_dst!=1 || stride_src!=1 )
4174  {
4175  /*
4176  * general unoptimized case
4177  */
4178  double ax = alpha.x, ay = alpha.y;
4179  if( bconj )
4180  {
4181  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4182  {
4183  vdst->x += ax*vsrc->x+ay*vsrc->y;
4184  vdst->y -= ax*vsrc->y-ay*vsrc->x;
4185  }
4186  }
4187  else
4188  {
4189  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4190  {
4191  vdst->x += ax*vsrc->x-ay*vsrc->y;
4192  vdst->y += ax*vsrc->y+ay*vsrc->x;
4193  }
4194  }
4195  }
4196  else
4197  {
4198  /*
4199  * highly optimized case
4200  */
4201  double ax = alpha.x, ay = alpha.y;
4202  if( bconj )
4203  {
4204  for(i=0; i<n; i++, vdst++, vsrc++)
4205  {
4206  vdst->x += ax*vsrc->x+ay*vsrc->y;
4207  vdst->y -= ax*vsrc->y-ay*vsrc->x;
4208  }
4209  }
4210  else
4211  {
4212  for(i=0; i<n; i++, vdst++, vsrc++)
4213  {
4214  vdst->x += ax*vsrc->x-ay*vsrc->y;
4215  vdst->y += ax*vsrc->y+ay*vsrc->x;
4216  }
4217  }
4218  }
4219 }
4220 
4221 void ae_v_csub(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n)
4222 {
4223  ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
4224  ae_int_t i;
4225  if( stride_dst!=1 || stride_src!=1 )
4226  {
4227  /*
4228  * general unoptimized case
4229  */
4230  if( bconj )
4231  {
4232  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4233  {
4234  vdst->x -= vsrc->x;
4235  vdst->y += vsrc->y;
4236  }
4237  }
4238  else
4239  {
4240  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4241  {
4242  vdst->x -= vsrc->x;
4243  vdst->y -= vsrc->y;
4244  }
4245  }
4246  }
4247  else
4248  {
4249  /*
4250  * highly optimized case
4251  */
4252  if( bconj )
4253  {
4254  for(i=0; i<n; i++, vdst++, vsrc++)
4255  {
4256  vdst->x -= vsrc->x;
4257  vdst->y += vsrc->y;
4258  }
4259  }
4260  else
4261  {
4262  for(i=0; i<n; i++, vdst++, vsrc++)
4263  {
4264  vdst->x -= vsrc->x;
4265  vdst->y -= vsrc->y;
4266  }
4267  }
4268  }
4269 }
4270 
4271 void ae_v_csubd(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha)
4272 {
4273  ae_v_caddd(vdst, stride_dst, vsrc, stride_src, conj_src, n, -alpha);
4274 }
4275 
4276 void ae_v_csubc(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, ae_complex alpha)
4277 {
4278  alpha.x = -alpha.x;
4279  alpha.y = -alpha.y;
4280  ae_v_caddc(vdst, stride_dst, vsrc, stride_src, conj_src, n, alpha);
4281 }
4282 
4283 void ae_v_cmuld(ae_complex *vdst, ae_int_t stride_dst, ae_int_t n, double alpha)
4284 {
4285  ae_int_t i;
4286  if( stride_dst!=1 )
4287  {
4288  /*
4289  * general unoptimized case
4290  */
4291  for(i=0; i<n; i++, vdst+=stride_dst)
4292  {
4293  vdst->x *= alpha;
4294  vdst->y *= alpha;
4295  }
4296  }
4297  else
4298  {
4299  /*
4300  * optimized case
4301  */
4302  for(i=0; i<n; i++, vdst++)
4303  {
4304  vdst->x *= alpha;
4305  vdst->y *= alpha;
4306  }
4307  }
4308 }
4309 
4310 void ae_v_cmulc(ae_complex *vdst, ae_int_t stride_dst, ae_int_t n, ae_complex alpha)
4311 {
4312  ae_int_t i;
4313  if( stride_dst!=1 )
4314  {
4315  /*
4316  * general unoptimized case
4317  */
4318  double ax = alpha.x, ay = alpha.y;
4319  for(i=0; i<n; i++, vdst+=stride_dst)
4320  {
4321  double dstx = vdst->x, dsty = vdst->y;
4322  vdst->x = ax*dstx-ay*dsty;
4323  vdst->y = ax*dsty+ay*dstx;
4324  }
4325  }
4326  else
4327  {
4328  /*
4329  * highly optimized case
4330  */
4331  double ax = alpha.x, ay = alpha.y;
4332  for(i=0; i<n; i++, vdst++)
4333  {
4334  double dstx = vdst->x, dsty = vdst->y;
4335  vdst->x = ax*dstx-ay*dsty;
4336  vdst->y = ax*dsty+ay*dstx;
4337  }
4338  }
4339 }
4340 
4341 /************************************************************************
4342 Real BLAS operations
4343 ************************************************************************/
4344 double ae_v_dotproduct(const double *v0, ae_int_t stride0, const double *v1, ae_int_t stride1, ae_int_t n)
4345 {
4346  double result = 0;
4347  ae_int_t i;
4348  if( stride0!=1 || stride1!=1 )
4349  {
4350  /*
4351  * slow general code
4352  */
4353  for(i=0; i<n; i++, v0+=stride0, v1+=stride1)
4354  result += (*v0)*(*v1);
4355  }
4356  else
4357  {
4358  /*
4359  * optimized code for stride=1
4360  */
4361  ae_int_t n4 = n/4;
4362  ae_int_t nleft = n%4;
4363  for(i=0; i<n4; i++, v0+=4, v1+=4)
4364  result += v0[0]*v1[0]+v0[1]*v1[1]+v0[2]*v1[2]+v0[3]*v1[3];
4365  for(i=0; i<nleft; i++, v0++, v1++)
4366  result += v0[0]*v1[0];
4367  }
4368  return result;
4369 }
4370 
4371 void ae_v_move(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n)
4372 {
4373  ae_int_t i;
4374  if( stride_dst!=1 || stride_src!=1 )
4375  {
4376  /*
4377  * general unoptimized case
4378  */
4379  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4380  *vdst = *vsrc;
4381  }
4382  else
4383  {
4384  /*
4385  * optimized case
4386  */
4387  ae_int_t n2 = n/2;
4388  for(i=0; i<n2; i++, vdst+=2, vsrc+=2)
4389  {
4390  vdst[0] = vsrc[0];
4391  vdst[1] = vsrc[1];
4392  }
4393  if( n%2!=0 )
4394  vdst[0] = vsrc[0];
4395  }
4396 }
4397 
4398 void ae_v_moveneg(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n)
4399 {
4400  ae_int_t i;
4401  if( stride_dst!=1 || stride_src!=1 )
4402  {
4403  /*
4404  * general unoptimized case
4405  */
4406  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4407  *vdst = -*vsrc;
4408  }
4409  else
4410  {
4411  /*
4412  * optimized case
4413  */
4414  ae_int_t n2 = n/2;
4415  for(i=0; i<n2; i++, vdst+=2, vsrc+=2)
4416  {
4417  vdst[0] = -vsrc[0];
4418  vdst[1] = -vsrc[1];
4419  }
4420  if( n%2!=0 )
4421  vdst[0] = -vsrc[0];
4422  }
4423 }
4424 
4425 void ae_v_moved(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
4426 {
4427  ae_int_t i;
4428  if( stride_dst!=1 || stride_src!=1 )
4429  {
4430  /*
4431  * general unoptimized case
4432  */
4433  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4434  *vdst = alpha*(*vsrc);
4435  }
4436  else
4437  {
4438  /*
4439  * optimized case
4440  */
4441  ae_int_t n2 = n/2;
4442  for(i=0; i<n2; i++, vdst+=2, vsrc+=2)
4443  {
4444  vdst[0] = alpha*vsrc[0];
4445  vdst[1] = alpha*vsrc[1];
4446  }
4447  if( n%2!=0 )
4448  vdst[0] = alpha*vsrc[0];
4449  }
4450 }
4451 
4452 void ae_v_add(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
4453 {
4454  ae_int_t i;
4455  if( stride_dst!=1 || stride_src!=1 )
4456  {
4457  /*
4458  * general unoptimized case
4459  */
4460  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4461  *vdst += *vsrc;
4462  }
4463  else
4464  {
4465  /*
4466  * optimized case
4467  */
4468  ae_int_t n2 = n/2;
4469  for(i=0; i<n2; i++, vdst+=2, vsrc+=2)
4470  {
4471  vdst[0] += vsrc[0];
4472  vdst[1] += vsrc[1];
4473  }
4474  if( n%2!=0 )
4475  vdst[0] += vsrc[0];
4476  }
4477 }
4478 
4479 void ae_v_addd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
4480 {
4481  ae_int_t i;
4482  if( stride_dst!=1 || stride_src!=1 )
4483  {
4484  /*
4485  * general unoptimized case
4486  */
4487  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4488  *vdst += alpha*(*vsrc);
4489  }
4490  else
4491  {
4492  /*
4493  * optimized case
4494  */
4495  ae_int_t n2 = n/2;
4496  for(i=0; i<n2; i++, vdst+=2, vsrc+=2)
4497  {
4498  vdst[0] += alpha*vsrc[0];
4499  vdst[1] += alpha*vsrc[1];
4500  }
4501  if( n%2!=0 )
4502  vdst[0] += alpha*vsrc[0];
4503  }
4504 }
4505 
4506 void ae_v_sub(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
4507 {
4508  ae_int_t i;
4509  if( stride_dst!=1 || stride_src!=1 )
4510  {
4511  /*
4512  * general unoptimized case
4513  */
4514  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
4515  *vdst -= *vsrc;
4516  }
4517  else
4518  {
4519  /*
4520  * highly optimized case
4521  */
4522  ae_int_t n2 = n/2;
4523  for(i=0; i<n2; i++, vdst+=2, vsrc+=2)
4524  {
4525  vdst[0] -= vsrc[0];
4526  vdst[1] -= vsrc[1];
4527  }
4528  if( n%2!=0 )
4529  vdst[0] -= vsrc[0];
4530  }
4531 }
4532 
4533 void ae_v_subd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
4534 {
4535  ae_v_addd(vdst, stride_dst, vsrc, stride_src, n, -alpha);
4536 }
4537 
4538 void ae_v_muld(double *vdst, ae_int_t stride_dst, ae_int_t n, double alpha)
4539 {
4540  ae_int_t i;
4541  if( stride_dst!=1 )
4542  {
4543  /*
4544  * general unoptimized case
4545  */
4546  for(i=0; i<n; i++, vdst+=stride_dst)
4547  *vdst *= alpha;
4548  }
4549  else
4550  {
4551  /*
4552  * highly optimized case
4553  */
4554  for(i=0; i<n; i++, vdst++)
4555  *vdst *= alpha;
4556  }
4557 }
4558 
4559 /************************************************************************
4560 Other functions
4561 ************************************************************************/
4563 {
4564  return b-a+1;
4565 }
4566 
4567 /************************************************************************
4568 RComm functions
4569 ************************************************************************/
4571 {
4572  if( !ae_vector_init(&p->ba, 0, DT_BOOL, _state, make_automatic) )
4573  return ae_false;
4574  if( !ae_vector_init(&p->ia, 0, DT_INT, _state, make_automatic) )
4575  return ae_false;
4576  if( !ae_vector_init(&p->ra, 0, DT_REAL, _state, make_automatic) )
4577  return ae_false;
4578  if( !ae_vector_init(&p->ca, 0, DT_COMPLEX, _state, make_automatic) )
4579  return ae_false;
4580  return ae_true;
4581 }
4582 
4584 {
4585  if( !ae_vector_init_copy(&dst->ba, &src->ba, _state, make_automatic) )
4586  return ae_false;
4587  if( !ae_vector_init_copy(&dst->ia, &src->ia, _state, make_automatic) )
4588  return ae_false;
4589  if( !ae_vector_init_copy(&dst->ra, &src->ra, _state, make_automatic) )
4590  return ae_false;
4591  if( !ae_vector_init_copy(&dst->ca, &src->ca, _state, make_automatic) )
4592  return ae_false;
4593  dst->stage = src->stage;
4594  return ae_true;
4595 }
4596 
4598 {
4599  ae_vector_clear(&p->ba);
4600  ae_vector_clear(&p->ia);
4601  ae_vector_clear(&p->ra);
4602  ae_vector_clear(&p->ca);
4603 }
4604 
4606 {
4607  _rcommstate_clear(p);
4608 }
4609 
4610 #ifdef AE_DEBUG4WINDOWS
4611 int _tickcount()
4612 {
4613  return GetTickCount();
4614 }
4615 #endif
4616 
4617 #ifdef AE_DEBUG4POSIX
4618 #include <time.h>
4619 int _tickcount()
4620 {
4621  struct timespec now;
4622  if (clock_gettime(CLOCK_MONOTONIC, &now) )
4623  return 0;
4624  return now.tv_sec * 1000.0 + now.tv_nsec / 1000000.0;
4625 }
4626 #endif
4627 
4628 #ifdef AE_DEBUGRNG
4629 void ae_set_seed(ae_int_t s0, ae_int_t s1)
4630 {
4631  ae_int_t hqrnd_hqrndm1 = 2147483563;
4632  ae_int_t hqrnd_hqrndm2 = 2147483399;
4633 
4634  while(s0<1)
4635  s0 += hqrnd_hqrndm1-1;
4636  while(s0>hqrnd_hqrndm1-1)
4637  s0 -= hqrnd_hqrndm1-1;
4638 
4639  while(s1<1)
4640  s1 += hqrnd_hqrndm2-1;
4641  while(s1>hqrnd_hqrndm2-1)
4642  s1 -= hqrnd_hqrndm2-1;
4643 
4644  _debug_rng_s0 = s0;
4645  _debug_rng_s1 = s1;
4646 }
4647 
4648 void ae_get_seed(ae_int_t *s0, ae_int_t *s1)
4649 {
4650  *s0 = _debug_rng_s0;
4651  *s1 = _debug_rng_s1;
4652 }
4653 #endif
4654 
4655 }
4656 
4658 //
4659 // THIS SECTION CONTAINS C++ RELATED FUNCTIONALITY
4660 //
4662 /********************************************************************
4663 Internal forwards
4664 ********************************************************************/
4665 namespace alglib
4666 {
4667  double get_aenv_nan();
4668  double get_aenv_posinf();
4669  double get_aenv_neginf();
4670  ae_int_t my_stricmp(const char *s1, const char *s2);
4671  char* filter_spaces(const char *s);
4672  void str_vector_create(const char *src, bool match_head_only, std::vector<const char*> *p_vec);
4673  void str_matrix_create(const char *src, std::vector< std::vector<const char*> > *p_mat);
4674 
4675  ae_bool parse_bool_delim(const char *s, const char *delim);
4676  ae_int_t parse_int_delim(const char *s, const char *delim);
4677  bool _parse_real_delim(const char *s, const char *delim, double *result, const char **new_s);
4678  double parse_real_delim(const char *s, const char *delim);
4679  alglib::complex parse_complex_delim(const char *s, const char *delim);
4680 
4681  std::string arraytostring(const bool *ptr, ae_int_t n);
4682  std::string arraytostring(const ae_int_t *ptr, ae_int_t n);
4683  std::string arraytostring(const double *ptr, ae_int_t n, int dps);
4684  std::string arraytostring(const alglib::complex *ptr, ae_int_t n, int dps);
4685 }
4686 
4687 /********************************************************************
4688 Global and local constants
4689 ********************************************************************/
4690 const double alglib::machineepsilon = 5E-16;
4691 const double alglib::maxrealnumber = 1E300;
4692 const double alglib::minrealnumber = 1E-300;
4697 
4698 
4699 /********************************************************************
4700 ap_error
4701 ********************************************************************/
4703 {
4704 }
4705 
4707 {
4708  msg = s;
4709 }
4710 
4712 {
4713  if(!bClause)
4714  throw ap_error();
4715 }
4716 
4717 void alglib::ap_error::make_assertion(bool bClause, const char *msg)
4718 {
4719  if(!bClause)
4720  throw ap_error(msg);
4721 }
4722 
4723 
4724 /********************************************************************
4725 Complex number with double precision.
4726 ********************************************************************/
4728 {
4729 }
4730 
4731 alglib::complex::complex(const double &_x):x(_x),y(0.0)
4732 {
4733 }
4734 
4735 alglib::complex::complex(const double &_x, const double &_y):x(_x),y(_y)
4736 {
4737 }
4738 
4740 {
4741 }
4742 
4744 {
4745  x = v;
4746  y = 0.0;
4747  return *this;
4748 }
4749 
4751 {
4752  x += v;
4753  return *this;
4754 }
4755 
4757 {
4758  x -= v;
4759  return *this;
4760 }
4761 
4763 {
4764  x *= v;
4765  y *= v;
4766  return *this;
4767 }
4768 
4770 {
4771  x /= v;
4772  y /= v;
4773  return *this;
4774 }
4775 
4777 {
4778  x = z.x;
4779  y = z.y;
4780  return *this;
4781 }
4782 
4784 {
4785  x += z.x;
4786  y += z.y;
4787  return *this;
4788 }
4789 
4791 {
4792  x -= z.x;
4793  y -= z.y;
4794  return *this;
4795 }
4796 
4798 {
4799  double t = x*z.x-y*z.y;
4800  y = x*z.y+y*z.x;
4801  x = t;
4802  return *this;
4803 }
4804 
4806 {
4807  alglib::complex result;
4808  double e;
4809  double f;
4810  if( fabs(z.y)<fabs(z.x) )
4811  {
4812  e = z.y/z.x;
4813  f = z.x+z.y*e;
4814  result.x = (x+y*e)/f;
4815  result.y = (y-x*e)/f;
4816  }
4817  else
4818  {
4819  e = z.x/z.y;
4820  f = z.y+z.x*e;
4821  result.x = (y+x*e)/f;
4822  result.y = (-x+y*e)/f;
4823  }
4824  *this = result;
4825  return *this;
4826 }
4827 
4829 {
4830  return (alglib_impl::ae_complex*)this;
4831 }
4832 
4834 {
4835  return (const alglib_impl::ae_complex*)this;
4836 }
4837 
4838 std::string alglib::complex::tostring(int _dps) const
4839 {
4840  char mask[32];
4841  char buf_x[32];
4842  char buf_y[32];
4843  char buf_zero[32];
4844  int dps = _dps>=0 ? _dps : -_dps;
4845  if( dps<=0 || dps>=20 )
4846  throw ap_error("complex::tostring(): incorrect dps");
4847 
4848  // handle IEEE special quantities
4849  if( fp_isnan(x) || fp_isnan(y) )
4850  return "NAN";
4851  if( fp_isinf(x) || fp_isinf(y) )
4852  return "INF";
4853 
4854  // generate mask
4855  if( sprintf(mask, "%%.%d%s", dps, _dps>=0 ? "f" : "e")>=(int)sizeof(mask) )
4856  throw ap_error("complex::tostring(): buffer overflow");
4857 
4858  // print |x|, |y| and zero with same mask and compare
4859  if( sprintf(buf_x, mask, (double)(fabs(x)))>=(int)sizeof(buf_x) )
4860  throw ap_error("complex::tostring(): buffer overflow");
4861  if( sprintf(buf_y, mask, (double)(fabs(y)))>=(int)sizeof(buf_y) )
4862  throw ap_error("complex::tostring(): buffer overflow");
4863  if( sprintf(buf_zero, mask, (double)0)>=(int)sizeof(buf_zero) )
4864  throw ap_error("complex::tostring(): buffer overflow");
4865 
4866  // different zero/nonzero patterns
4867  if( strcmp(buf_x,buf_zero)!=0 && strcmp(buf_y,buf_zero)!=0 )
4868  return std::string(x>0 ? "" : "-")+buf_x+(y>0 ? "+" : "-")+buf_y+"i";
4869  if( strcmp(buf_x,buf_zero)!=0 && strcmp(buf_y,buf_zero)==0 )
4870  return std::string(x>0 ? "" : "-")+buf_x;
4871  if( strcmp(buf_x,buf_zero)==0 && strcmp(buf_y,buf_zero)!=0 )
4872  return std::string(y>0 ? "" : "-")+buf_y+"i";
4873  return std::string("0");
4874 }
4875 
4876 const bool alglib::operator==(const alglib::complex& lhs, const alglib::complex& rhs)
4877 {
4878  volatile double x1 = lhs.x;
4879  volatile double x2 = rhs.x;
4880  volatile double y1 = lhs.y;
4881  volatile double y2 = rhs.y;
4882  return x1==x2 && y1==y2;
4883 }
4884 
4885 const bool alglib::operator!=(const alglib::complex& lhs, const alglib::complex& rhs)
4886 { return !(lhs==rhs); }
4887 
4889 { return lhs; }
4890 
4892 { return alglib::complex(-lhs.x, -lhs.y); }
4893 
4895 { alglib::complex r = lhs; r += rhs; return r; }
4896 
4897 const alglib::complex alglib::operator+(const alglib::complex& lhs, const double& rhs)
4898 { alglib::complex r = lhs; r += rhs; return r; }
4899 
4900 const alglib::complex alglib::operator+(const double& lhs, const alglib::complex& rhs)
4901 { alglib::complex r = rhs; r += lhs; return r; }
4902 
4904 { alglib::complex r = lhs; r -= rhs; return r; }
4905 
4906 const alglib::complex alglib::operator-(const alglib::complex& lhs, const double& rhs)
4907 { alglib::complex r = lhs; r -= rhs; return r; }
4908 
4909 const alglib::complex alglib::operator-(const double& lhs, const alglib::complex& rhs)
4910 { alglib::complex r = lhs; r -= rhs; return r; }
4911 
4913 { return alglib::complex(lhs.x*rhs.x - lhs.y*rhs.y, lhs.x*rhs.y + lhs.y*rhs.x); }
4914 
4915 const alglib::complex alglib::operator*(const alglib::complex& lhs, const double& rhs)
4916 { return alglib::complex(lhs.x*rhs, lhs.y*rhs); }
4917 
4918 const alglib::complex alglib::operator*(const double& lhs, const alglib::complex& rhs)
4919 { return alglib::complex(lhs*rhs.x, lhs*rhs.y); }
4920 
4922 {
4923  alglib::complex result;
4924  double e;
4925  double f;
4926  if( fabs(rhs.y)<fabs(rhs.x) )
4927  {
4928  e = rhs.y/rhs.x;
4929  f = rhs.x+rhs.y*e;
4930  result.x = (lhs.x+lhs.y*e)/f;
4931  result.y = (lhs.y-lhs.x*e)/f;
4932  }
4933  else
4934  {
4935  e = rhs.x/rhs.y;
4936  f = rhs.y+rhs.x*e;
4937  result.x = (lhs.y+lhs.x*e)/f;
4938  result.y = (-lhs.x+lhs.y*e)/f;
4939  }
4940  return result;
4941 }
4942 
4943 const alglib::complex alglib::operator/(const double& lhs, const alglib::complex& rhs)
4944 {
4945  alglib::complex result;
4946  double e;
4947  double f;
4948  if( fabs(rhs.y)<fabs(rhs.x) )
4949  {
4950  e = rhs.y/rhs.x;
4951  f = rhs.x+rhs.y*e;
4952  result.x = lhs/f;
4953  result.y = -lhs*e/f;
4954  }
4955  else
4956  {
4957  e = rhs.x/rhs.y;
4958  f = rhs.y+rhs.x*e;
4959  result.x = lhs*e/f;
4960  result.y = -lhs/f;
4961  }
4962  return result;
4963 }
4964 
4965 const alglib::complex alglib::operator/(const alglib::complex& lhs, const double& rhs)
4966 { return alglib::complex(lhs.x/rhs, lhs.y/rhs); }
4967 
4969 {
4970  double w;
4971  double xabs;
4972  double yabs;
4973  double v;
4974 
4975  xabs = fabs(z.x);
4976  yabs = fabs(z.y);
4977  w = xabs>yabs ? xabs : yabs;
4978  v = xabs<yabs ? xabs : yabs;
4979  if( v==0 )
4980  return w;
4981  else
4982  {
4983  double t = v/w;
4984  return w*sqrt(1+t*t);
4985  }
4986 }
4987 
4989 { return alglib::complex(z.x, -z.y); }
4990 
4992 { return alglib::complex(z.x*z.x-z.y*z.y, 2*z.x*z.y); }
4993 
4995 {
4996 #ifdef AE_HPC
4997  alglib_impl::ae_set_cores_to_use(nworkers);
4998 #endif
4999 }
5000 
5001 /********************************************************************
5002 Level 1 BLAS functions
5003 ********************************************************************/
5004 double alglib::vdotproduct(const double *v0, ae_int_t stride0, const double *v1, ae_int_t stride1, ae_int_t n)
5005 {
5006  double result = 0;
5007  ae_int_t i;
5008  if( stride0!=1 || stride1!=1 )
5009  {
5010  //
5011  // slow general code
5012  //
5013  for(i=0; i<n; i++, v0+=stride0, v1+=stride1)
5014  result += (*v0)*(*v1);
5015  }
5016  else
5017  {
5018  //
5019  // optimized code for stride=1
5020  //
5021  ae_int_t n4 = n/4;
5022  ae_int_t nleft = n%4;
5023  for(i=0; i<n4; i++, v0+=4, v1+=4)
5024  result += v0[0]*v1[0]+v0[1]*v1[1]+v0[2]*v1[2]+v0[3]*v1[3];
5025  for(i=0; i<nleft; i++, v0++, v1++)
5026  result += v0[0]*v1[0];
5027  }
5028  return result;
5029 }
5030 
5031 double alglib::vdotproduct(const double *v1, const double *v2, ae_int_t N)
5032 {
5033  return vdotproduct(v1, 1, v2, 1, N);
5034 }
5035 
5036 alglib::complex alglib::vdotproduct(const alglib::complex *v0, ae_int_t stride0, const char *conj0, const alglib::complex *v1, ae_int_t stride1, const char *conj1, ae_int_t n)
5037 {
5038  double rx = 0, ry = 0;
5039  ae_int_t i;
5040  bool bconj0 = !((conj0[0]=='N') || (conj0[0]=='n'));
5041  bool bconj1 = !((conj1[0]=='N') || (conj1[0]=='n'));
5042  if( bconj0 && bconj1 )
5043  {
5044  double v0x, v0y, v1x, v1y;
5045  for(i=0; i<n; i++, v0+=stride0, v1+=stride1)
5046  {
5047  v0x = v0->x;
5048  v0y = -v0->y;
5049  v1x = v1->x;
5050  v1y = -v1->y;
5051  rx += v0x*v1x-v0y*v1y;
5052  ry += v0x*v1y+v0y*v1x;
5053  }
5054  }
5055  if( !bconj0 && bconj1 )
5056  {
5057  double v0x, v0y, v1x, v1y;
5058  for(i=0; i<n; i++, v0+=stride0, v1+=stride1)
5059  {
5060  v0x = v0->x;
5061  v0y = v0->y;
5062  v1x = v1->x;
5063  v1y = -v1->y;
5064  rx += v0x*v1x-v0y*v1y;
5065  ry += v0x*v1y+v0y*v1x;
5066  }
5067  }
5068  if( bconj0 && !bconj1 )
5069  {
5070  double v0x, v0y, v1x, v1y;
5071  for(i=0; i<n; i++, v0+=stride0, v1+=stride1)
5072  {
5073  v0x = v0->x;
5074  v0y = -v0->y;
5075  v1x = v1->x;
5076  v1y = v1->y;
5077  rx += v0x*v1x-v0y*v1y;
5078  ry += v0x*v1y+v0y*v1x;
5079  }
5080  }
5081  if( !bconj0 && !bconj1 )
5082  {
5083  double v0x, v0y, v1x, v1y;
5084  for(i=0; i<n; i++, v0+=stride0, v1+=stride1)
5085  {
5086  v0x = v0->x;
5087  v0y = v0->y;
5088  v1x = v1->x;
5089  v1y = v1->y;
5090  rx += v0x*v1x-v0y*v1y;
5091  ry += v0x*v1y+v0y*v1x;
5092  }
5093  }
5094  return alglib::complex(rx,ry);
5095 }
5096 
5098 {
5099  return vdotproduct(v1, 1, "N", v2, 1, "N", N);
5100 }
5101 
5102 void alglib::vmove(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n)
5103 {
5104  ae_int_t i;
5105  if( stride_dst!=1 || stride_src!=1 )
5106  {
5107  //
5108  // general unoptimized case
5109  //
5110  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5111  *vdst = *vsrc;
5112  }
5113  else
5114  {
5115  //
5116  // optimized case
5117  //
5118  ae_int_t n2 = n/2;
5119  for(i=0; i<n2; i++, vdst+=2, vsrc+=2)
5120  {
5121  vdst[0] = vsrc[0];
5122  vdst[1] = vsrc[1];
5123  }
5124  if( n%2!=0 )
5125  vdst[0] = vsrc[0];
5126  }
5127 }
5128 
5129 void alglib::vmove(double *vdst, const double* vsrc, ae_int_t N)
5130 {
5131  vmove(vdst, 1, vsrc, 1, N);
5132 }
5133 
5134 void alglib::vmove(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n)
5135 {
5136  bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
5137  ae_int_t i;
5138  if( stride_dst!=1 || stride_src!=1 )
5139  {
5140  //
5141  // general unoptimized case
5142  //
5143  if( bconj )
5144  {
5145  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5146  {
5147  vdst->x = vsrc->x;
5148  vdst->y = -vsrc->y;
5149  }
5150  }
5151  else
5152  {
5153  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5154  *vdst = *vsrc;
5155  }
5156  }
5157  else
5158  {
5159  //
5160  // optimized case
5161  //
5162  if( bconj )
5163  {
5164  for(i=0; i<n; i++, vdst++, vsrc++)
5165  {
5166  vdst->x = vsrc->x;
5167  vdst->y = -vsrc->y;
5168  }
5169  }
5170  else
5171  {
5172  for(i=0; i<n; i++, vdst++, vsrc++)
5173  *vdst = *vsrc;
5174  }
5175  }
5176 }
5177 
5179 {
5180  vmove(vdst, 1, vsrc, 1, "N", N);
5181 }
5182 
5183 void alglib::vmoveneg(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n)
5184 {
5185  ae_int_t i;
5186  if( stride_dst!=1 || stride_src!=1 )
5187  {
5188  //
5189  // general unoptimized case
5190  //
5191  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5192  *vdst = -*vsrc;
5193  }
5194  else
5195  {
5196  //
5197  // optimized case
5198  //
5199  ae_int_t n2 = n/2;
5200  for(i=0; i<n2; i++, vdst+=2, vsrc+=2)
5201  {
5202  vdst[0] = -vsrc[0];
5203  vdst[1] = -vsrc[1];
5204  }
5205  if( n%2!=0 )
5206  vdst[0] = -vsrc[0];
5207  }
5208 }
5209 
5210 void alglib::vmoveneg(double *vdst, const double *vsrc, ae_int_t N)
5211 {
5212  vmoveneg(vdst, 1, vsrc, 1, N);
5213 }
5214 
5215 void alglib::vmoveneg(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n)
5216 {
5217  bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
5218  ae_int_t i;
5219  if( stride_dst!=1 || stride_src!=1 )
5220  {
5221  //
5222  // general unoptimized case
5223  //
5224  if( bconj )
5225  {
5226  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5227  {
5228  vdst->x = -vsrc->x;
5229  vdst->y = vsrc->y;
5230  }
5231  }
5232  else
5233  {
5234  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5235  {
5236  vdst->x = -vsrc->x;
5237  vdst->y = -vsrc->y;
5238  }
5239  }
5240  }
5241  else
5242  {
5243  //
5244  // optimized case
5245  //
5246  if( bconj )
5247  {
5248  for(i=0; i<n; i++, vdst++, vsrc++)
5249  {
5250  vdst->x = -vsrc->x;
5251  vdst->y = vsrc->y;
5252  }
5253  }
5254  else
5255  {
5256  for(i=0; i<n; i++, vdst++, vsrc++)
5257  {
5258  vdst->x = -vsrc->x;
5259  vdst->y = -vsrc->y;
5260  }
5261  }
5262  }
5263 }
5264 
5266 {
5267  vmoveneg(vdst, 1, vsrc, 1, "N", N);
5268 }
5269 
5270 void alglib::vmove(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
5271 {
5272  ae_int_t i;
5273  if( stride_dst!=1 || stride_src!=1 )
5274  {
5275  //
5276  // general unoptimized case
5277  //
5278  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5279  *vdst = alpha*(*vsrc);
5280  }
5281  else
5282  {
5283  //
5284  // optimized case
5285  //
5286  ae_int_t n2 = n/2;
5287  for(i=0; i<n2; i++, vdst+=2, vsrc+=2)
5288  {
5289  vdst[0] = alpha*vsrc[0];
5290  vdst[1] = alpha*vsrc[1];
5291  }
5292  if( n%2!=0 )
5293  vdst[0] = alpha*vsrc[0];
5294  }
5295 }
5296 
5297 void alglib::vmove(double *vdst, const double *vsrc, ae_int_t N, double alpha)
5298 {
5299  vmove(vdst, 1, vsrc, 1, N, alpha);
5300 }
5301 
5302 void alglib::vmove(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha)
5303 {
5304  bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
5305  ae_int_t i;
5306  if( stride_dst!=1 || stride_src!=1 )
5307  {
5308  //
5309  // general unoptimized case
5310  //
5311  if( bconj )
5312  {
5313  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5314  {
5315  vdst->x = alpha*vsrc->x;
5316  vdst->y = -alpha*vsrc->y;
5317  }
5318  }
5319  else
5320  {
5321  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5322  {
5323  vdst->x = alpha*vsrc->x;
5324  vdst->y = alpha*vsrc->y;
5325  }
5326  }
5327  }
5328  else
5329  {
5330  //
5331  // optimized case
5332  //
5333  if( bconj )
5334  {
5335  for(i=0; i<n; i++, vdst++, vsrc++)
5336  {
5337  vdst->x = alpha*vsrc->x;
5338  vdst->y = -alpha*vsrc->y;
5339  }
5340  }
5341  else
5342  {
5343  for(i=0; i<n; i++, vdst++, vsrc++)
5344  {
5345  vdst->x = alpha*vsrc->x;
5346  vdst->y = alpha*vsrc->y;
5347  }
5348  }
5349  }
5350 }
5351 
5352 void alglib::vmove(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N, double alpha)
5353 {
5354  vmove(vdst, 1, vsrc, 1, "N", N, alpha);
5355 }
5356 
5357 void alglib::vmove(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, alglib::complex alpha)
5358 {
5359  bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
5360  ae_int_t i;
5361  if( stride_dst!=1 || stride_src!=1 )
5362  {
5363  //
5364  // general unoptimized case
5365  //
5366  if( bconj )
5367  {
5368  double ax = alpha.x, ay = alpha.y;
5369  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5370  {
5371  vdst->x = ax*vsrc->x+ay*vsrc->y;
5372  vdst->y = -ax*vsrc->y+ay*vsrc->x;
5373  }
5374  }
5375  else
5376  {
5377  double ax = alpha.x, ay = alpha.y;
5378  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5379  {
5380  vdst->x = ax*vsrc->x-ay*vsrc->y;
5381  vdst->y = ax*vsrc->y+ay*vsrc->x;
5382  }
5383  }
5384  }
5385  else
5386  {
5387  //
5388  // optimized case
5389  //
5390  if( bconj )
5391  {
5392  double ax = alpha.x, ay = alpha.y;
5393  for(i=0; i<n; i++, vdst++, vsrc++)
5394  {
5395  vdst->x = ax*vsrc->x+ay*vsrc->y;
5396  vdst->y = -ax*vsrc->y+ay*vsrc->x;
5397  }
5398  }
5399  else
5400  {
5401  double ax = alpha.x, ay = alpha.y;
5402  for(i=0; i<n; i++, vdst++, vsrc++)
5403  {
5404  vdst->x = ax*vsrc->x-ay*vsrc->y;
5405  vdst->y = ax*vsrc->y+ay*vsrc->x;
5406  }
5407  }
5408  }
5409 }
5410 
5412 {
5413  vmove(vdst, 1, vsrc, 1, "N", N, alpha);
5414 }
5415 
5416 void alglib::vadd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
5417 {
5418  ae_int_t i;
5419  if( stride_dst!=1 || stride_src!=1 )
5420  {
5421  //
5422  // general unoptimized case
5423  //
5424  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5425  *vdst += *vsrc;
5426  }
5427  else
5428  {
5429  //
5430  // optimized case
5431  //
5432  ae_int_t n2 = n/2;
5433  for(i=0; i<n2; i++, vdst+=2, vsrc+=2)
5434  {
5435  vdst[0] += vsrc[0];
5436  vdst[1] += vsrc[1];
5437  }
5438  if( n%2!=0 )
5439  vdst[0] += vsrc[0];
5440  }
5441 }
5442 
5443 void alglib::vadd(double *vdst, const double *vsrc, ae_int_t N)
5444 {
5445  vadd(vdst, 1, vsrc, 1, N);
5446 }
5447 
5448 void alglib::vadd(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n)
5449 {
5450  bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
5451  ae_int_t i;
5452  if( stride_dst!=1 || stride_src!=1 )
5453  {
5454  //
5455  // general unoptimized case
5456  //
5457  if( bconj )
5458  {
5459  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5460  {
5461  vdst->x += vsrc->x;
5462  vdst->y -= vsrc->y;
5463  }
5464  }
5465  else
5466  {
5467  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5468  {
5469  vdst->x += vsrc->x;
5470  vdst->y += vsrc->y;
5471  }
5472  }
5473  }
5474  else
5475  {
5476  //
5477  // optimized case
5478  //
5479  if( bconj )
5480  {
5481  for(i=0; i<n; i++, vdst++, vsrc++)
5482  {
5483  vdst->x += vsrc->x;
5484  vdst->y -= vsrc->y;
5485  }
5486  }
5487  else
5488  {
5489  for(i=0; i<n; i++, vdst++, vsrc++)
5490  {
5491  vdst->x += vsrc->x;
5492  vdst->y += vsrc->y;
5493  }
5494  }
5495  }
5496 }
5497 
5499 {
5500  vadd(vdst, 1, vsrc, 1, "N", N);
5501 }
5502 
5503 void alglib::vadd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
5504 {
5505  ae_int_t i;
5506  if( stride_dst!=1 || stride_src!=1 )
5507  {
5508  //
5509  // general unoptimized case
5510  //
5511  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5512  *vdst += alpha*(*vsrc);
5513  }
5514  else
5515  {
5516  //
5517  // optimized case
5518  //
5519  ae_int_t n2 = n/2;
5520  for(i=0; i<n2; i++, vdst+=2, vsrc+=2)
5521  {
5522  vdst[0] += alpha*vsrc[0];
5523  vdst[1] += alpha*vsrc[1];
5524  }
5525  if( n%2!=0 )
5526  vdst[0] += alpha*vsrc[0];
5527  }
5528 }
5529 
5530 void alglib::vadd(double *vdst, const double *vsrc, ae_int_t N, double alpha)
5531 {
5532  vadd(vdst, 1, vsrc, 1, N, alpha);
5533 }
5534 
5535 void alglib::vadd(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha)
5536 {
5537  bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
5538  ae_int_t i;
5539  if( stride_dst!=1 || stride_src!=1 )
5540  {
5541  //
5542  // general unoptimized case
5543  //
5544  if( bconj )
5545  {
5546  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5547  {
5548  vdst->x += alpha*vsrc->x;
5549  vdst->y -= alpha*vsrc->y;
5550  }
5551  }
5552  else
5553  {
5554  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5555  {
5556  vdst->x += alpha*vsrc->x;
5557  vdst->y += alpha*vsrc->y;
5558  }
5559  }
5560  }
5561  else
5562  {
5563  //
5564  // optimized case
5565  //
5566  if( bconj )
5567  {
5568  for(i=0; i<n; i++, vdst++, vsrc++)
5569  {
5570  vdst->x += alpha*vsrc->x;
5571  vdst->y -= alpha*vsrc->y;
5572  }
5573  }
5574  else
5575  {
5576  for(i=0; i<n; i++, vdst++, vsrc++)
5577  {
5578  vdst->x += alpha*vsrc->x;
5579  vdst->y += alpha*vsrc->y;
5580  }
5581  }
5582  }
5583 }
5584 
5585 void alglib::vadd(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N, double alpha)
5586 {
5587  vadd(vdst, 1, vsrc, 1, "N", N, alpha);
5588 }
5589 
5590 void alglib::vadd(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, alglib::complex alpha)
5591 {
5592  bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
5593  ae_int_t i;
5594  if( stride_dst!=1 || stride_src!=1 )
5595  {
5596  //
5597  // general unoptimized case
5598  //
5599  double ax = alpha.x, ay = alpha.y;
5600  if( bconj )
5601  {
5602  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5603  {
5604  vdst->x += ax*vsrc->x+ay*vsrc->y;
5605  vdst->y -= ax*vsrc->y-ay*vsrc->x;
5606  }
5607  }
5608  else
5609  {
5610  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5611  {
5612  vdst->x += ax*vsrc->x-ay*vsrc->y;
5613  vdst->y += ax*vsrc->y+ay*vsrc->x;
5614  }
5615  }
5616  }
5617  else
5618  {
5619  //
5620  // optimized case
5621  //
5622  double ax = alpha.x, ay = alpha.y;
5623  if( bconj )
5624  {
5625  for(i=0; i<n; i++, vdst++, vsrc++)
5626  {
5627  vdst->x += ax*vsrc->x+ay*vsrc->y;
5628  vdst->y -= ax*vsrc->y-ay*vsrc->x;
5629  }
5630  }
5631  else
5632  {
5633  for(i=0; i<n; i++, vdst++, vsrc++)
5634  {
5635  vdst->x += ax*vsrc->x-ay*vsrc->y;
5636  vdst->y += ax*vsrc->y+ay*vsrc->x;
5637  }
5638  }
5639  }
5640 }
5641 
5643 {
5644  vadd(vdst, 1, vsrc, 1, "N", N, alpha);
5645 }
5646 
5647 void alglib::vsub(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
5648 {
5649  ae_int_t i;
5650  if( stride_dst!=1 || stride_src!=1 )
5651  {
5652  //
5653  // general unoptimized case
5654  //
5655  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5656  *vdst -= *vsrc;
5657  }
5658  else
5659  {
5660  //
5661  // optimized case
5662  //
5663  ae_int_t n2 = n/2;
5664  for(i=0; i<n2; i++, vdst+=2, vsrc+=2)
5665  {
5666  vdst[0] -= vsrc[0];
5667  vdst[1] -= vsrc[1];
5668  }
5669  if( n%2!=0 )
5670  vdst[0] -= vsrc[0];
5671  }
5672 }
5673 
5674 void alglib::vsub(double *vdst, const double *vsrc, ae_int_t N)
5675 {
5676  vsub(vdst, 1, vsrc, 1, N);
5677 }
5678 
5679 void alglib::vsub(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n)
5680 {
5681  bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n'));
5682  ae_int_t i;
5683  if( stride_dst!=1 || stride_src!=1 )
5684  {
5685  //
5686  // general unoptimized case
5687  //
5688  if( bconj )
5689  {
5690  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5691  {
5692  vdst->x -= vsrc->x;
5693  vdst->y += vsrc->y;
5694  }
5695  }
5696  else
5697  {
5698  for(i=0; i<n; i++, vdst+=stride_dst, vsrc+=stride_src)
5699  {
5700  vdst->x -= vsrc->x;
5701  vdst->y -= vsrc->y;
5702  }
5703  }
5704  }
5705  else
5706  {
5707  //
5708  // optimized case
5709  //
5710  if( bconj )
5711  {
5712  for(i=0; i<n; i++, vdst++, vsrc++)
5713  {
5714  vdst->x -= vsrc->x;
5715  vdst->y += vsrc->y;
5716  }
5717  }
5718  else
5719  {
5720  for(i=0; i<n; i++, vdst++, vsrc++)
5721  {
5722  vdst->x -= vsrc->x;
5723  vdst->y -= vsrc->y;
5724  }
5725  }
5726  }
5727 }
5728 
5730 {
5731  vsub(vdst, 1, vsrc, 1, "N", N);
5732 }
5733 
5734 void alglib::vsub(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
5735 {
5736  vadd(vdst, stride_dst, vsrc, stride_src, n, -alpha);
5737 }
5738 
5739 void alglib::vsub(double *vdst, const double *vsrc, ae_int_t N, double alpha)
5740 {
5741  vadd(vdst, 1, vsrc, 1, N, -alpha);
5742 }
5743 
5744 void alglib::vsub(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha)
5745 {
5746  vadd(vdst, stride_dst, vsrc, stride_src, conj_src, n, -alpha);
5747 }
5748 
5749 void alglib::vsub(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t n, double alpha)
5750 {
5751  vadd(vdst, 1, vsrc, 1, "N", n, -alpha);
5752 }
5753 
5754 void alglib::vsub(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, alglib::complex alpha)
5755 {
5756  vadd(vdst, stride_dst, vsrc, stride_src, conj_src, n, -alpha);
5757 }
5758 
5760 {
5761  vadd(vdst, 1, vsrc, 1, "N", n, -alpha);
5762 }
5763 void alglib::vmul(double *vdst, ae_int_t stride_dst, ae_int_t n, double alpha)
5764 {
5765  ae_int_t i;
5766  if( stride_dst!=1 )
5767  {
5768  //
5769  // general unoptimized case
5770  //
5771  for(i=0; i<n; i++, vdst+=stride_dst)
5772  *vdst *= alpha;
5773  }
5774  else
5775  {
5776  //
5777  // optimized case
5778  //
5779  for(i=0; i<n; i++, vdst++)
5780  *vdst *= alpha;
5781  }
5782 }
5783 
5784 void alglib::vmul(double *vdst, ae_int_t N, double alpha)
5785 {
5786  vmul(vdst, 1, N, alpha);
5787 }
5788 
5789 void alglib::vmul(alglib::complex *vdst, ae_int_t stride_dst, ae_int_t n, double alpha)
5790 {
5791  ae_int_t i;
5792  if( stride_dst!=1 )
5793  {
5794  //
5795  // general unoptimized case
5796  //
5797  for(i=0; i<n; i++, vdst+=stride_dst)
5798  {
5799  vdst->x *= alpha;
5800  vdst->y *= alpha;
5801  }
5802  }
5803  else
5804  {
5805  //
5806  // optimized case
5807  //
5808  for(i=0; i<n; i++, vdst++)
5809  {
5810  vdst->x *= alpha;
5811  vdst->y *= alpha;
5812  }
5813  }
5814 }
5815 
5816 void alglib::vmul(alglib::complex *vdst, ae_int_t N, double alpha)
5817 {
5818  vmul(vdst, 1, N, alpha);
5819 }
5820 
5822 {
5823  ae_int_t i;
5824  if( stride_dst!=1 )
5825  {
5826  //
5827  // general unoptimized case
5828  //
5829  double ax = alpha.x, ay = alpha.y;
5830  for(i=0; i<n; i++, vdst+=stride_dst)
5831  {
5832  double dstx = vdst->x, dsty = vdst->y;
5833  vdst->x = ax*dstx-ay*dsty;
5834  vdst->y = ax*dsty+ay*dstx;
5835  }
5836  }
5837  else
5838  {
5839  //
5840  // optimized case
5841  //
5842  double ax = alpha.x, ay = alpha.y;
5843  for(i=0; i<n; i++, vdst++)
5844  {
5845  double dstx = vdst->x, dsty = vdst->y;
5846  vdst->x = ax*dstx-ay*dsty;
5847  vdst->y = ax*dsty+ay*dstx;
5848  }
5849  }
5850 }
5851 
5853 {
5854  vmul(vdst, 1, N, alpha);
5855 }
5856 
5857 
5858 /********************************************************************
5859 Matrices and vectors
5860 ********************************************************************/
5862 {
5863  p_vec = NULL;
5864 }
5865 
5867 {
5868  if( p_vec==&vec )
5869  ae_vector_clear(p_vec);
5870 }
5871 
5873 {
5874  if( p_vec==NULL )
5875  throw alglib::ap_error("ALGLIB: setlength() error, p_vec==NULL (array was not correctly initialized)");
5876  if( p_vec!=&vec )
5877  throw alglib::ap_error("ALGLIB: setlength() error, p_vec!=&vec (attempt to resize frozen array)");
5878  if( !ae_vector_set_length(p_vec, iLen, NULL) )
5879  throw alglib::ap_error("ALGLIB: malloc error");
5880 }
5881 
5883 {
5884  if( p_vec==NULL )
5885  return 0;
5886  return p_vec->cnt;
5887 }
5888 
5890 {
5891  if( ptr==&vec )
5892  throw alglib::ap_error("ALGLIB: attempt to attach vector to itself");
5893  if( p_vec==&vec )
5894  ae_vector_clear(p_vec);
5895  p_vec = ptr;
5896 }
5897 
5899 {
5900  if( p_vec==&vec )
5901  ae_vector_clear(p_vec);
5902  p_vec = &vec;
5903  if( !ae_vector_init(p_vec, size, datatype, NULL, false) )
5904  throw alglib::ap_error("ALGLIB: malloc error");
5905 }
5906 
5908 {
5909  return p_vec;
5910 }
5911 
5913 {
5914  return p_vec;
5915 }
5916 
5918 {
5919  if( rhs.p_vec!=NULL )
5920  {
5921  p_vec = &vec;
5922  if( !ae_vector_init_copy(p_vec, rhs.p_vec, NULL, ae_false) )
5923  throw alglib::ap_error("ALGLIB: malloc error!");
5924  }
5925  else
5926  p_vec = NULL;
5927 }
5928 
5930 {
5931  std::vector<const char*> svec;
5932  size_t i;
5933  char *p = filter_spaces(s);
5934  try
5935  {
5936  str_vector_create(p, true, &svec);
5937  allocate_own((ae_int_t)(svec.size()), datatype);
5938  for(i=0; i<svec.size(); i++)
5939  {
5940  if( datatype==alglib_impl::DT_BOOL )
5941  p_vec->ptr.p_bool[i] = parse_bool_delim(svec[i],",]");
5942  if( datatype==alglib_impl::DT_INT )
5943  p_vec->ptr.p_int[i] = parse_int_delim(svec[i],",]");
5944  if( datatype==alglib_impl::DT_REAL )
5945  p_vec->ptr.p_double[i] = parse_real_delim(svec[i],",]");
5946  if( datatype==alglib_impl::DT_COMPLEX )
5947  {
5948  alglib::complex t = parse_complex_delim(svec[i],",]");
5949  p_vec->ptr.p_complex[i].x = t.x;
5950  p_vec->ptr.p_complex[i].y = t.y;
5951  }
5952  }
5954  }
5955  catch(...)
5956  {
5958  throw;
5959  }
5960 }
5961 
5963 {
5964  if( this==&rhs )
5965  return;
5966  if( p_vec==&vec || p_vec==NULL )
5967  {
5968  //
5969  // Assignment to non-proxy object
5970  //
5971  ae_vector_clear(p_vec);
5972  if( rhs.p_vec!=NULL )
5973  {
5974  p_vec = &vec;
5975  if( !ae_vector_init_copy(p_vec, rhs.p_vec, NULL, ae_false) )
5976  throw alglib::ap_error("ALGLIB: malloc error!");
5977  }
5978  else
5979  p_vec = NULL;
5980  }
5981  else
5982  {
5983  //
5984  // Assignment to proxy object
5985  //
5986  if( rhs.p_vec==NULL )
5987  throw alglib::ap_error("ALGLIB: incorrect assignment to array (sizes do not match)");
5988  if( rhs.p_vec->datatype!=p_vec->datatype )
5989  throw alglib::ap_error("ALGLIB: incorrect assignment to array (types do not match)");
5990  if( rhs.p_vec->cnt!=p_vec->cnt )
5991  throw alglib::ap_error("ALGLIB: incorrect assignment to array (sizes do not match)");
5992  memcpy(p_vec->ptr.p_ptr, rhs.p_vec->ptr.p_ptr, p_vec->cnt*alglib_impl::ae_sizeof(p_vec->datatype));
5993  }
5994 }
5995 
5997 {
5998  allocate_own(0, alglib_impl::DT_BOOL);
5999 }
6000 
6002 {
6003  create(s, alglib_impl::DT_BOOL);
6004 }
6005 
6007 {
6008  create(rhs);
6009 }
6010 
6012 {
6013  p_vec = NULL;
6014  attach_to(p);
6015 }
6016 
6018 {
6019  assign(rhs);
6020  return *this;
6021 }
6022 
6024 {
6025 }
6026 
6028 {
6029  return p_vec->ptr.p_bool[i];
6030 }
6031 
6033 {
6034  return p_vec->ptr.p_bool[i];
6035 }
6036 
6038 {
6039  return p_vec->ptr.p_bool[i];
6040 }
6041 
6043 {
6044  return p_vec->ptr.p_bool[i];
6045 }
6046 
6047 void alglib::boolean_1d_array::setcontent(ae_int_t iLen, const bool *pContent )
6048 {
6049  ae_int_t i;
6050  setlength(iLen);
6051  for(i=0; i<iLen; i++)
6052  p_vec->ptr.p_bool[i] = pContent[i];
6053 }
6054 
6056 {
6057  return p_vec->ptr.p_bool;
6058 }
6059 
6061 {
6062  return p_vec->ptr.p_bool;
6063 }
6064 
6066 {
6067  if( length()==0 )
6068  return "[]";
6069  return arraytostring(&(operator()(0)), length());
6070 }
6071 
6073 {
6074  allocate_own(0, alglib_impl::DT_INT);
6075 }
6076 
6078 {
6079  p_vec = NULL;
6080  attach_to(p);
6081 }
6082 
6084 {
6085  create(s, alglib_impl::DT_INT);
6086 }
6087 
6089 {
6090  create(rhs);
6091 }
6092 
6094 {
6095  assign(rhs);
6096  return *this;
6097 }
6098 
6100 {
6101 }
6102 
6104 {
6105  return p_vec->ptr.p_int[i];
6106 }
6107 
6109 {
6110  return p_vec->ptr.p_int[i];
6111 }
6112 
6114 {
6115  return p_vec->ptr.p_int[i];
6116 }
6117 
6119 {
6120  return p_vec->ptr.p_int[i];
6121 }
6122 
6124 {
6125  ae_int_t i;
6126  setlength(iLen);
6127  for(i=0; i<iLen; i++)
6128  p_vec->ptr.p_int[i] = pContent[i];
6129 }
6130 
6132 {
6133  return p_vec->ptr.p_int;
6134 }
6135 
6137 {
6138  return p_vec->ptr.p_int;
6139 }
6140 
6142 {
6143  if( length()==0 )
6144  return "[]";
6145  return arraytostring(&operator()(0), length());
6146 }
6147 
6149 {
6150  allocate_own(0, alglib_impl::DT_REAL);
6151 }
6152 
6154 {
6155  p_vec = NULL;
6156  attach_to(p);
6157 }
6158 
6160 {
6161  create(s, alglib_impl::DT_REAL);
6162 }
6163 
6165 {
6166  create(rhs);
6167 }
6168 
6170 {
6171  assign(rhs);
6172  return *this;
6173 }
6174 
6176 {
6177 }
6178 
6180 {
6181  return p_vec->ptr.p_double[i];
6182 }
6183 
6185 {
6186  return p_vec->ptr.p_double[i];
6187 }
6188 
6190 {
6191  return p_vec->ptr.p_double[i];
6192 }
6193 
6195 {
6196  return p_vec->ptr.p_double[i];
6197 }
6198 
6199 void alglib::real_1d_array::setcontent(ae_int_t iLen, const double *pContent )
6200 {
6201  ae_int_t i;
6202  setlength(iLen);
6203  for(i=0; i<iLen; i++)
6204  p_vec->ptr.p_double[i] = pContent[i];
6205 }
6206 
6208 {
6209  return p_vec->ptr.p_double;
6210 }
6211 
6213 {
6214  return p_vec->ptr.p_double;
6215 }
6216 
6217 std::string alglib::real_1d_array::tostring(int dps) const
6218 {
6219  if( length()==0 )
6220  return "[]";
6221  return arraytostring(&operator()(0), length(), dps);
6222 }
6223 
6225 {
6226  allocate_own(0, alglib_impl::DT_COMPLEX);
6227 }
6228 
6230 {
6231  p_vec = NULL;
6232  attach_to(p);
6233 }
6234 
6236 {
6237  create(s, alglib_impl::DT_COMPLEX);
6238 }
6239 
6241 {
6242  create(rhs);
6243 }
6244 
6246 {
6247  assign(rhs);
6248  return *this;
6249 }
6250 
6252 {
6253 }
6254 
6256 {
6257  return *((const alglib::complex*)(p_vec->ptr.p_complex+i));
6258 }
6259 
6261 {
6262  return *((alglib::complex*)(p_vec->ptr.p_complex+i));
6263 }
6264 
6266 {
6267  return *((const alglib::complex*)(p_vec->ptr.p_complex+i));
6268 }
6269 
6271 {
6272  return *((alglib::complex*)(p_vec->ptr.p_complex+i));
6273 }
6274 
6276 {
6277  ae_int_t i;
6278  setlength(iLen);
6279  for(i=0; i<iLen; i++)
6280  {
6281  p_vec->ptr.p_complex[i].x = pContent[i].x;
6282  p_vec->ptr.p_complex[i].y = pContent[i].y;
6283  }
6284 }
6285 
6287 {
6288  return (alglib::complex*)p_vec->ptr.p_complex;
6289 }
6290 
6292 {
6293  return (const alglib::complex*)p_vec->ptr.p_complex;
6294 }
6295 
6296 std::string alglib::complex_1d_array::tostring(int dps) const
6297 {
6298  if( length()==0 )
6299  return "[]";
6300  return arraytostring(&operator()(0), length(), dps);
6301 }
6302 
6304 {
6305  p_mat = NULL;
6306 }
6307 
6309 {
6310  if( p_mat==&mat )
6311  ae_matrix_clear(p_mat);
6312 }
6313 
6315 {
6316  assign(rhs);
6317  return *this;
6318 }
6319 
6321 {
6322  if( rhs.p_mat!=NULL )
6323  {
6324  p_mat = &mat;
6325  if( !ae_matrix_init_copy(p_mat, rhs.p_mat, NULL, ae_false) )
6326  throw alglib::ap_error("ALGLIB: malloc error!");
6327  }
6328  else
6329  p_mat = NULL;
6330 }
6331 
6333 {
6334  std::vector< std::vector<const char*> > smat;
6335  size_t i, j;
6336  char *p = filter_spaces(s);
6337  try
6338  {
6339  str_matrix_create(p, &smat);
6340  if( smat.size()!=0 )
6341  {
6342  allocate_own((ae_int_t)(smat.size()), (ae_int_t)(smat[0].size()), datatype);
6343  for(i=0; i<smat.size(); i++)
6344  for(j=0; j<smat[0].size(); j++)
6345  {
6346  if( datatype==alglib_impl::DT_BOOL )
6347  p_mat->ptr.pp_bool[i][j] = parse_bool_delim(smat[i][j],",]");
6348  if( datatype==alglib_impl::DT_INT )
6349  p_mat->ptr.pp_int[i][j] = parse_int_delim(smat[i][j],",]");
6350  if( datatype==alglib_impl::DT_REAL )
6351  p_mat->ptr.pp_double[i][j] = parse_real_delim(smat[i][j],",]");
6352  if( datatype==alglib_impl::DT_COMPLEX )
6353  {
6354  alglib::complex t = parse_complex_delim(smat[i][j],",]");
6355  p_mat->ptr.pp_complex[i][j].x = t.x;
6356  p_mat->ptr.pp_complex[i][j].y = t.y;
6357  }
6358  }
6359  }
6360  else
6361  allocate_own(0, 0, datatype);
6363  }
6364  catch(...)
6365  {
6367  throw;
6368  }
6369 }
6370 
6372 {
6373  if( this==&rhs )
6374  return;
6375  if( p_mat==&mat || p_mat==NULL )
6376  {
6377  //
6378  // Assignment to non-proxy object
6379  //
6380  ae_matrix_clear(p_mat);
6381  if( rhs.p_mat!=NULL )
6382  {
6383  p_mat = &mat;
6384  if( !ae_matrix_init_copy(p_mat, rhs.p_mat, NULL, ae_false) )
6385  throw alglib::ap_error("ALGLIB: malloc error!");
6386  }
6387  else
6388  p_mat = NULL;
6389  }
6390  else
6391  {
6392  //
6393  // Assignment to proxy object
6394  //
6395  ae_int_t i;
6396  if( rhs.p_mat==NULL )
6397  throw alglib::ap_error("ALGLIB: incorrect assignment to array (sizes do not match)");
6398  if( rhs.p_mat->datatype!=p_mat->datatype )
6399  throw alglib::ap_error("ALGLIB: incorrect assignment to array (types do not match)");
6400  if( rhs.p_mat->rows!=p_mat->rows )
6401  throw alglib::ap_error("ALGLIB: incorrect assignment to array (sizes do not match)");
6402  if( rhs.p_mat->cols!=p_mat->cols )
6403  throw alglib::ap_error("ALGLIB: incorrect assignment to array (sizes do not match)");
6404  for(i=0; i<p_mat->rows; i++)
6405  memcpy(p_mat->ptr.pp_void[i], rhs.p_mat->ptr.pp_void[i], p_mat->cols*alglib_impl::ae_sizeof(p_mat->datatype));
6406  }
6407 }
6408 
6410 {
6411  if( p_mat==NULL )
6412  throw alglib::ap_error("ALGLIB: setlength() error, p_mat==NULL (array was not correctly initialized)");
6413  if( p_mat!=&mat )
6414  throw alglib::ap_error("ALGLIB: setlength() error, p_mat!=&mat (attempt to resize frozen array)");
6415  if( !ae_matrix_set_length(p_mat, rows, cols, NULL) )
6416  throw alglib::ap_error("ALGLIB: malloc error");
6417 }
6418 
6420 {
6421  if( p_mat==NULL )
6422  return 0;
6423  return p_mat->rows;
6424 }
6425 
6427 {
6428  if( p_mat==NULL )
6429  return 0;
6430  return p_mat->cols;
6431 }
6432 
6434 {
6435  return rows()==0 || cols()==0;
6436 }
6437 
6439 {
6440  if( p_mat==NULL )
6441  return 0;
6442  return p_mat->stride;
6443 }
6444 
6446 {
6447  if( ptr==&mat )
6448  throw alglib::ap_error("ALGLIB: attempt to attach matrix to itself");
6449  if( p_mat==&mat )
6450  ae_matrix_clear(p_mat);
6451  p_mat = ptr;
6452 }
6453 
6455 {
6456  if( p_mat==&mat )
6457  ae_matrix_clear(p_mat);
6458  p_mat = &mat;
6459  if( !ae_matrix_init(p_mat, rows, cols, datatype, NULL, false) )
6460  throw alglib::ap_error("ALGLIB: malloc error");
6461 }
6462 
6464 {
6465  return p_mat;
6466 }
6467 
6469 {
6470  return p_mat;
6471 }
6472 
6474 {
6475  allocate_own(0, 0, alglib_impl::DT_BOOL);
6476 }
6477 
6479 {
6480  create(rhs);
6481 }
6482 
6484 {
6485  p_mat = NULL;
6486  attach_to(p);
6487 }
6488 
6490 {
6491  create(s, alglib_impl::DT_BOOL);
6492 }
6493 
6495 {
6496 }
6497 
6499 {
6500  return p_mat->ptr.pp_bool[i][j];
6501 }
6502 
6504 {
6505  return p_mat->ptr.pp_bool[i][j];
6506 }
6507 
6509 {
6510  return p_mat->ptr.pp_bool[i];
6511 }
6512 
6514 {
6515  return p_mat->ptr.pp_bool[i];
6516 }
6517 
6518 void alglib::boolean_2d_array::setcontent(ae_int_t irows, ae_int_t icols, const bool *pContent )
6519 {
6520  ae_int_t i, j;
6521  setlength(irows, icols);
6522  for(i=0; i<irows; i++)
6523  for(j=0; j<icols; j++)
6524  p_mat->ptr.pp_bool[i][j] = pContent[i*icols+j];
6525 }
6526 
6528 {
6529  std::string result;
6530  ae_int_t i;
6531  if( isempty() )
6532  return "[[]]";
6533  result = "[";
6534  for(i=0; i<rows(); i++)
6535  {
6536  if( i!=0 )
6537  result += ",";
6538  result += arraytostring(&operator()(i,0), cols());
6539  }
6540  result += "]";
6541  return result;
6542 }
6543 
6545 {
6546  allocate_own(0, 0, alglib_impl::DT_INT);
6547 }
6548 
6550 {
6551  create(rhs);
6552 }
6553 
6555 {
6556  p_mat = NULL;
6557  attach_to(p);
6558 }
6559 
6561 {
6562  create(s, alglib_impl::DT_INT);
6563 }
6564 
6566 {
6567 }
6568 
6570 {
6571  return p_mat->ptr.pp_int[i][j];
6572 }
6573 
6575 {
6576  return p_mat->ptr.pp_int[i][j];
6577 }
6578 
6580 {
6581  return p_mat->ptr.pp_int[i];
6582 }
6583 
6585 {
6586  return p_mat->ptr.pp_int[i];
6587 }
6588 
6590 {
6591  ae_int_t i, j;
6592  setlength(irows, icols);
6593  for(i=0; i<irows; i++)
6594  for(j=0; j<icols; j++)
6595  p_mat->ptr.pp_int[i][j] = pContent[i*icols+j];
6596 }
6597 
6599 {
6600  std::string result;
6601  ae_int_t i;
6602  if( isempty() )
6603  return "[[]]";
6604  result = "[";
6605  for(i=0; i<rows(); i++)
6606  {
6607  if( i!=0 )
6608  result += ",";
6609  result += arraytostring(&operator()(i,0), cols());
6610  }
6611  result += "]";
6612  return result;
6613 }
6614 
6616 {
6617  allocate_own(0, 0, alglib_impl::DT_REAL);
6618 }
6619 
6621 {
6622  create(rhs);
6623 }
6624 
6626 {
6627  p_mat = NULL;
6628  attach_to(p);
6629 }
6630 
6632 {
6633  create(s, alglib_impl::DT_REAL);
6634 }
6635 
6637 {
6638 }
6639 
6641 {
6642  return p_mat->ptr.pp_double[i][j];
6643 }
6644 
6646 {
6647  return p_mat->ptr.pp_double[i][j];
6648 }
6649 
6651 {
6652  return p_mat->ptr.pp_double[i];
6653 }
6654 
6656 {
6657  return p_mat->ptr.pp_double[i];
6658 }
6659 
6660 void alglib::real_2d_array::setcontent(ae_int_t irows, ae_int_t icols, const double *pContent )
6661 {
6662  ae_int_t i, j;
6663  setlength(irows, icols);
6664  for(i=0; i<irows; i++)
6665  for(j=0; j<icols; j++)
6666  p_mat->ptr.pp_double[i][j] = pContent[i*icols+j];
6667 }
6668 
6669 std::string alglib::real_2d_array::tostring(int dps) const
6670 {
6671  std::string result;
6672  ae_int_t i;
6673  if( isempty() )
6674  return "[[]]";
6675  result = "[";
6676  for(i=0; i<rows(); i++)
6677  {
6678  if( i!=0 )
6679  result += ",";
6680  result += arraytostring(&operator()(i,0), cols(), dps);
6681  }
6682  result += "]";
6683  return result;
6684 }
6685 
6687 {
6688  allocate_own(0, 0, alglib_impl::DT_COMPLEX);
6689 }
6690 
6692 {
6693  create(rhs);
6694 }
6695 
6697 {
6698  p_mat = NULL;
6699  attach_to(p);
6700 }
6701 
6703 {
6704  create(s, alglib_impl::DT_COMPLEX);
6705 }
6706 
6708 {
6709 }
6710 
6712 {
6713  return *((const alglib::complex*)(p_mat->ptr.pp_complex[i]+j));
6714 }
6715 
6717 {
6718  return *((alglib::complex*)(p_mat->ptr.pp_complex[i]+j));
6719 }
6720 
6722 {
6723  return (const alglib::complex*)(p_mat->ptr.pp_complex[i]);
6724 }
6725 
6727 {
6728  return (alglib::complex*)(p_mat->ptr.pp_complex[i]);
6729 }
6730 
6732 {
6733  ae_int_t i, j;
6734  setlength(irows, icols);
6735  for(i=0; i<irows; i++)
6736  for(j=0; j<icols; j++)
6737  {
6738  p_mat->ptr.pp_complex[i][j].x = pContent[i*icols+j].x;
6739  p_mat->ptr.pp_complex[i][j].y = pContent[i*icols+j].y;
6740  }
6741 }
6742 
6743 std::string alglib::complex_2d_array::tostring(int dps) const
6744 {
6745  std::string result;
6746  ae_int_t i;
6747  if( isempty() )
6748  return "[[]]";
6749  result = "[";
6750  for(i=0; i<rows(); i++)
6751  {
6752  if( i!=0 )
6753  result += ",";
6754  result += arraytostring(&operator()(i,0), cols(), dps);
6755  }
6756  result += "]";
6757  return result;
6758 }
6759 
6760 
6761 /********************************************************************
6762 Internal functions
6763 ********************************************************************/
6765 {
6766  double r;
6767  alglib_impl::ae_state _alglib_env_state;
6768  alglib_impl::ae_state_init(&_alglib_env_state);
6769  r = _alglib_env_state.v_nan;
6770  alglib_impl::ae_state_clear(&_alglib_env_state);
6771  return r;
6772 }
6773 
6775 {
6776  double r;
6777  alglib_impl::ae_state _alglib_env_state;
6778  alglib_impl::ae_state_init(&_alglib_env_state);
6779  r = _alglib_env_state.v_posinf;
6780  alglib_impl::ae_state_clear(&_alglib_env_state);
6781  return r;
6782 }
6783 
6785 {
6786  double r;
6787  alglib_impl::ae_state _alglib_env_state;
6788  alglib_impl::ae_state_init(&_alglib_env_state);
6789  r = _alglib_env_state.v_neginf;
6790  alglib_impl::ae_state_clear(&_alglib_env_state);
6791  return r;
6792 }
6793 
6794 alglib::ae_int_t alglib::my_stricmp(const char *s1, const char *s2)
6795 {
6796  int c1, c2;
6797 
6798  //
6799  // handle special cases
6800  //
6801  if(s1==NULL && s2!=NULL)
6802  return -1;
6803  if(s1!=NULL && s2==NULL)
6804  return +1;
6805  if(s1==NULL && s2==NULL)
6806  return 0;
6807 
6808  //
6809  // compare
6810  //
6811  for (;;)
6812  {
6813  c1 = *s1;
6814  c2 = *s2;
6815  s1++;
6816  s2++;
6817  if( c1==0 )
6818  return c2==0 ? 0 : -1;
6819  if( c2==0 )
6820  return c1==0 ? 0 : +1;
6821  c1 = tolower(c1);
6822  c2 = tolower(c2);
6823  if( c1<c2 )
6824  return -1;
6825  if( c1>c2 )
6826  return +1;
6827  }
6828 }
6829 
6830 char* alglib::filter_spaces(const char *s)
6831 {
6832  size_t i, n;
6833  char *r;
6834  char *r0;
6835  n = strlen(s);
6836  r = (char*)alglib_impl::ae_malloc(n+1, NULL);
6837  if( r==NULL )
6838  throw ap_error("malloc error");
6839  for(i=0,r0=r; i<=n; i++,s++)
6840  if( !isspace(*s) )
6841  {
6842  *r0 = *s;
6843  r0++;
6844  }
6845  return r;
6846 }
6847 
6848 void alglib::str_vector_create(const char *src, bool match_head_only, std::vector<const char*> *p_vec)
6849 {
6850  //
6851  // parse beginning of the string.
6852  // try to handle "[]" string
6853  //
6854  p_vec->clear();
6855  if( *src!='[' )
6856  throw alglib::ap_error("Incorrect initializer for vector");
6857  src++;
6858  if( *src==']' )
6859  return;
6860  p_vec->push_back(src);
6861  for(;;)
6862  {
6863  if( *src==0 )
6864  throw alglib::ap_error("Incorrect initializer for vector");
6865  if( *src==']' )
6866  {
6867  if( src[1]==0 || !match_head_only)
6868  return;
6869  throw alglib::ap_error("Incorrect initializer for vector");
6870  }
6871  if( *src==',' )
6872  {
6873  p_vec->push_back(src+1);
6874  src++;
6875  continue;
6876  }
6877  src++;
6878  }
6879 }
6880 
6881 void alglib::str_matrix_create(const char *src, std::vector< std::vector<const char*> > *p_mat)
6882 {
6883  p_mat->clear();
6884 
6885  //
6886  // Try to handle "[[]]" string
6887  //
6888  if( strcmp(src, "[[]]")==0 )
6889  return;
6890 
6891  //
6892  // Parse non-empty string
6893  //
6894  if( *src!='[' )
6895  throw alglib::ap_error("Incorrect initializer for matrix");
6896  src++;
6897  for(;;)
6898  {
6899  p_mat->push_back(std::vector<const char*>());
6900  str_vector_create(src, false, &p_mat->back());
6901  if( p_mat->back().size()==0 || p_mat->back().size()!=(*p_mat)[0].size() )
6902  throw alglib::ap_error("Incorrect initializer for matrix");
6903  src = strchr(src, ']');
6904  if( src==NULL )
6905  throw alglib::ap_error("Incorrect initializer for matrix");
6906  src++;
6907  if( *src==',' )
6908  {
6909  src++;
6910  continue;
6911  }
6912  if( *src==']' )
6913  break;
6914  throw alglib::ap_error("Incorrect initializer for matrix");
6915  }
6916  src++;
6917  if( *src!=0 )
6918  throw alglib::ap_error("Incorrect initializer for matrix");
6919 }
6920 
6921 ae_bool alglib::parse_bool_delim(const char *s, const char *delim)
6922 {
6923  const char *p;
6924  char buf[8];
6925 
6926  // try to parse false
6927  p = "false";
6928  memset(buf, 0, sizeof(buf));
6929  strncpy(buf, s, strlen(p));
6930  if( my_stricmp(buf, p)==0 )
6931  {
6932  if( s[strlen(p)]==0 || strchr(delim,s[strlen(p)])==NULL )
6933  throw alglib::ap_error("Cannot parse value");
6934  return ae_false;
6935  }
6936 
6937  // try to parse true
6938  p = "true";
6939  memset(buf, 0, sizeof(buf));
6940  strncpy(buf, s, strlen(p));
6941  if( my_stricmp(buf, p)==0 )
6942  {
6943  if( s[strlen(p)]==0 || strchr(delim,s[strlen(p)])==NULL )
6944  throw alglib::ap_error("Cannot parse value");
6945  return ae_true;
6946  }
6947 
6948  // error
6949  throw alglib::ap_error("Cannot parse value");
6950 }
6951 
6952 alglib::ae_int_t alglib::parse_int_delim(const char *s, const char *delim)
6953 {
6954  const char *p;
6955  long long_val;
6956  volatile ae_int_t ae_val;
6957 
6958  p = s;
6959 
6960  //
6961  // check string structure:
6962  // * leading sign
6963  // * at least one digit
6964  // * delimiter
6965  //
6966  if( *s=='-' || *s=='+' )
6967  s++;
6968  if( *s==0 || strchr("1234567890",*s)==NULL)
6969  throw alglib::ap_error("Cannot parse value");
6970  while( *s!=0 && strchr("1234567890",*s)!=NULL )
6971  s++;
6972  if( *s==0 || strchr(delim,*s)==NULL )
6973  throw alglib::ap_error("Cannot parse value");
6974 
6975  // convert and ensure that value fits into ae_int_t
6976  s = p;
6977  long_val = atol(s);
6978  ae_val = long_val;
6979  if( ae_val!=long_val )
6980  throw alglib::ap_error("Cannot parse value");
6981  return ae_val;
6982 }
6983 
6984 bool alglib::_parse_real_delim(const char *s, const char *delim, double *result, const char **new_s)
6985 {
6986  const char *p;
6987  char *t;
6988  bool has_digits;
6989  char buf[64];
6990  int isign;
6991  lconv *loc;
6992 
6993  p = s;
6994 
6995  //
6996  // check string structure and decide what to do
6997  //
6998  isign = 1;
6999  if( *s=='-' || *s=='+' )
7000  {
7001  isign = *s=='-' ? -1 : +1;
7002  s++;
7003  }
7004  memset(buf, 0, sizeof(buf));
7005  strncpy(buf, s, 3);
7006  if( my_stricmp(buf,"nan")!=0 && my_stricmp(buf,"inf")!=0 )
7007  {
7008  //
7009  // [sign] [ddd] [.] [ddd] [e|E[sign]ddd]
7010  //
7011  has_digits = false;
7012  if( *s!=0 && strchr("1234567890",*s)!=NULL )
7013  {
7014  has_digits = true;
7015  while( *s!=0 && strchr("1234567890",*s)!=NULL )
7016  s++;
7017  }
7018  if( *s=='.' )
7019  s++;
7020  if( *s!=0 && strchr("1234567890",*s)!=NULL )
7021  {
7022  has_digits = true;
7023  while( *s!=0 && strchr("1234567890",*s)!=NULL )
7024  s++;
7025  }
7026  if (!has_digits )
7027  return false;
7028  if( *s=='e' || *s=='E' )
7029  {
7030  s++;
7031  if( *s=='-' || *s=='+' )
7032  s++;
7033  if( *s==0 || strchr("1234567890",*s)==NULL )
7034  return false;
7035  while( *s!=0 && strchr("1234567890",*s)!=NULL )
7036  s++;
7037  }
7038  if( *s==0 || strchr(delim,*s)==NULL )
7039  return false;
7040  *new_s = s;
7041 
7042  //
7043  // finite value conversion
7044  //
7045  if( *new_s-p>=(int)sizeof(buf) )
7046  return false;
7047  strncpy(buf, p, (size_t)(*new_s-p));
7048  buf[*new_s-p] = 0;
7049  loc = localeconv();
7050  t = strchr(buf,'.');
7051  if( t!=NULL )
7052  *t = *loc->decimal_point;
7053  *result = atof(buf);
7054  return true;
7055  }
7056  else
7057  {
7058  //
7059  // check delimiter and update *new_s
7060  //
7061  s += 3;
7062  if( *s==0 || strchr(delim,*s)==NULL )
7063  return false;
7064  *new_s = s;
7065 
7066  //
7067  // NAN, INF conversion
7068  //
7069  if( my_stricmp(buf,"nan")==0 )
7070  *result = fp_nan;
7071  if( my_stricmp(buf,"inf")==0 )
7072  *result = isign>0 ? fp_posinf : fp_neginf;
7073  return true;
7074  }
7075 }
7076 
7077 double alglib::parse_real_delim(const char *s, const char *delim)
7078 {
7079  double result;
7080  const char *new_s;
7081  if( !_parse_real_delim(s, delim, &result, &new_s) )
7082  throw alglib::ap_error("Cannot parse value");
7083  return result;
7084 }
7085 
7086 alglib::complex alglib::parse_complex_delim(const char *s, const char *delim)
7087 {
7088  double d_result;
7089  const char *new_s;
7090  alglib::complex c_result;
7091 
7092  // parse as real value
7093  if( _parse_real_delim(s, delim, &d_result, &new_s) )
7094  return d_result;
7095 
7096  // parse as "a+bi" or "a-bi"
7097  if( _parse_real_delim(s, "+-", &c_result.x, &new_s) )
7098  {
7099  s = new_s;
7100  if( !_parse_real_delim(s, "i", &c_result.y, &new_s) )
7101  throw alglib::ap_error("Cannot parse value");
7102  s = new_s+1;
7103  if( *s==0 || strchr(delim,*s)==NULL )
7104  throw alglib::ap_error("Cannot parse value");
7105  return c_result;
7106  }
7107 
7108  // parse as complex value "bi+a" or "bi-a"
7109  if( _parse_real_delim(s, "i", &c_result.y, &new_s) )
7110  {
7111  s = new_s+1;
7112  if( *s==0 )
7113  throw alglib::ap_error("Cannot parse value");
7114  if( strchr(delim,*s)!=NULL )
7115  {
7116  c_result.x = 0;
7117  return c_result;
7118  }
7119  if( strchr("+-",*s)!=NULL )
7120  {
7121  if( !_parse_real_delim(s, delim, &c_result.x, &new_s) )
7122  throw alglib::ap_error("Cannot parse value");
7123  return c_result;
7124  }
7125  throw alglib::ap_error("Cannot parse value");
7126  }
7127 
7128  // error
7129  throw alglib::ap_error("Cannot parse value");
7130 }
7131 
7132 std::string alglib::arraytostring(const bool *ptr, ae_int_t n)
7133 {
7134  std::string result;
7135  ae_int_t i;
7136  result = "[";
7137  for(i=0; i<n; i++)
7138  {
7139  if( i!=0 )
7140  result += ",";
7141  result += ptr[i] ? "true" : "false";
7142  }
7143  result += "]";
7144  return result;
7145 }
7146 
7147 std::string alglib::arraytostring(const ae_int_t *ptr, ae_int_t n)
7148 {
7149  std::string result;
7150  ae_int_t i;
7151  char buf[64];
7152  result = "[";
7153  for(i=0; i<n; i++)
7154  {
7155  if( sprintf(buf, i==0 ? "%ld" : ",%ld", long(ptr[i]))>=(int)sizeof(buf) )
7156  throw ap_error("arraytostring(): buffer overflow");
7157  result += buf;
7158  }
7159  result += "]";
7160  return result;
7161 }
7162 
7163 std::string alglib::arraytostring(const double *ptr, ae_int_t n, int _dps)
7164 {
7165  std::string result;
7166  ae_int_t i;
7167  char buf[67];
7168  char mask1[64];
7169  char mask2[66];
7170  int dps = _dps>=0 ? _dps : -_dps;
7171  result = "[";
7172  if( sprintf(mask1, "%%.%d%s", dps, _dps>=0 ? "f" : "e")>=(int)sizeof(mask1) )
7173  throw ap_error("arraytostring(): buffer overflow");
7174  if( sprintf(mask2, ",%s", mask1)>=(int)sizeof(mask2) )
7175  throw ap_error("arraytostring(): buffer overflow");
7176  for(i=0; i<n; i++)
7177  {
7178  buf[0] = 0;
7179  if( fp_isfinite(ptr[i]) )
7180  {
7181  if( sprintf(buf, i==0 ? mask1 : mask2, double(ptr[i]))>=(int)sizeof(buf) )
7182  throw ap_error("arraytostring(): buffer overflow");
7183  }
7184  else if( fp_isnan(ptr[i]) )
7185  strcpy(buf, i==0 ? "NAN" : ",NAN");
7186  else if( fp_isposinf(ptr[i]) )
7187  strcpy(buf, i==0 ? "+INF" : ",+INF");
7188  else if( fp_isneginf(ptr[i]) )
7189  strcpy(buf, i==0 ? "-INF" : ",-INF");
7190  result += buf;
7191  }
7192  result += "]";
7193  return result;
7194 }
7195 
7196 std::string alglib::arraytostring(const alglib::complex *ptr, ae_int_t n, int dps)
7197 {
7198  std::string result;
7199  ae_int_t i;
7200  result = "[";
7201  for(i=0; i<n; i++)
7202  {
7203  if( i!=0 )
7204  result += ",";
7205  result += ptr[i].tostring(dps);
7206  }
7207  result += "]";
7208  return result;
7209 }
7210 
7211 
7212 /********************************************************************
7213 standard functions
7214 ********************************************************************/
7215 int alglib::sign(double x)
7216 {
7217  if( x>0 ) return 1;
7218  if( x<0 ) return -1;
7219  return 0;
7220 }
7221 
7223 {
7224 #ifdef AE_DEBUGRNG
7225  return alglib_impl::ae_debugrng()/2147483563.0;
7226 #else
7227  int i1 = rand();
7228  int i2 = rand();
7229  double mx = (double)(RAND_MAX)+1.0;
7230  volatile double tmp0 = i2/mx;
7231  volatile double tmp1 = i1+tmp0;
7232  return tmp1/mx;
7233 #endif
7234 }
7235 
7237 {
7238 #ifdef AE_DEBUGRNG
7239  return ((alglib::ae_int_t)(alglib_impl::ae_debugrng()-1))%maxv;
7240 #else
7241  return ((alglib::ae_int_t)rand())%maxv;
7242 #endif
7243 }
7244 
7245 int alglib::round(double x)
7246 { return int(floor(x+0.5)); }
7247 
7248 int alglib::trunc(double x)
7249 { return int(x>0 ? floor(x) : ceil(x)); }
7250 
7251 int alglib::ifloor(double x)
7252 { return int(floor(x)); }
7253 
7254 int alglib::iceil(double x)
7255 { return int(ceil(x)); }
7256 
7257 double alglib::pi()
7258 { return 3.14159265358979323846; }
7259 
7260 double alglib::sqr(double x)
7261 { return x*x; }
7262 
7263 int alglib::maxint(int m1, int m2)
7264 {
7265  return m1>m2 ? m1 : m2;
7266 }
7267 
7268 int alglib::minint(int m1, int m2)
7269 {
7270  return m1>m2 ? m2 : m1;
7271 }
7272 
7273 double alglib::maxreal(double m1, double m2)
7274 {
7275  return m1>m2 ? m1 : m2;
7276 }
7277 
7278 double alglib::minreal(double m1, double m2)
7279 {
7280  return m1>m2 ? m2 : m1;
7281 }
7282 
7283 bool alglib::fp_eq(double v1, double v2)
7284 {
7285  // IEEE-strict floating point comparison
7286  volatile double x = v1;
7287  volatile double y = v2;
7288  return x==y;
7289 }
7290 
7291 bool alglib::fp_neq(double v1, double v2)
7292 {
7293  // IEEE-strict floating point comparison
7294  return !fp_eq(v1,v2);
7295 }
7296 
7297 bool alglib::fp_less(double v1, double v2)
7298 {
7299  // IEEE-strict floating point comparison
7300  volatile double x = v1;
7301  volatile double y = v2;
7302  return x<y;
7303 }
7304 
7305 bool alglib::fp_less_eq(double v1, double v2)
7306 {
7307  // IEEE-strict floating point comparison
7308  volatile double x = v1;
7309  volatile double y = v2;
7310  return x<=y;
7311 }
7312 
7313 bool alglib::fp_greater(double v1, double v2)
7314 {
7315  // IEEE-strict floating point comparison
7316  volatile double x = v1;
7317  volatile double y = v2;
7318  return x>y;
7319 }
7320 
7321 bool alglib::fp_greater_eq(double v1, double v2)
7322 {
7323  // IEEE-strict floating point comparison
7324  volatile double x = v1;
7325  volatile double y = v2;
7326  return x>=y;
7327 }
7328 
7329 bool alglib::fp_isnan(double x)
7330 {
7332 }
7333 
7334 bool alglib::fp_isposinf(double x)
7335 {
7337 }
7338 
7339 bool alglib::fp_isneginf(double x)
7340 {
7342 }
7343 
7344 bool alglib::fp_isinf(double x)
7345 {
7347 }
7348 
7349 bool alglib::fp_isfinite(double x)
7350 {
7352 }
7353 
7354 /********************************************************************
7355 Dataset functions
7356 ********************************************************************/
7357 /*bool alglib::readstrings(std::string file, std::list<std::string> *pOutput)
7358 {
7359  return readstrings(file, pOutput, "");
7360 }
7361 
7362 bool alglib::readstrings(std::string file, std::list<std::string> *pOutput, std::string comment)
7363 {
7364  std::string cmd, s;
7365  FILE *f;
7366  char buf[32768];
7367  char *str;
7368 
7369  f = fopen(file.c_str(), "rb");
7370  if( !f )
7371  return false;
7372  s = "";
7373  pOutput->clear();
7374  while(str=fgets(buf, sizeof(buf), f))
7375  {
7376  // TODO: read file by small chunks, combine in one large string
7377  if( strlen(str)==0 )
7378  continue;
7379 
7380  //
7381  // trim trailing newline chars
7382  //
7383  char *eos = str+strlen(str)-1;
7384  if( *eos=='\n' )
7385  {
7386  *eos = 0;
7387  eos--;
7388  }
7389  if( *eos=='\r' )
7390  {
7391  *eos = 0;
7392  eos--;
7393  }
7394  s = str;
7395 
7396  //
7397  // skip comments
7398  //
7399  if( comment.length()>0 )
7400  if( strncmp(s.c_str(), comment.c_str(), comment.length())==0 )
7401  {
7402  s = "";
7403  continue;
7404  }
7405 
7406  //
7407  // read data
7408  //
7409  if( s.length()<1 )
7410  {
7411  fclose(f);
7412  throw alglib::ap_error("internal error in read_strings");
7413  }
7414  pOutput->push_back(s);
7415  }
7416  fclose(f);
7417  return true;
7418 }
7419 
7420 void alglib::explodestring(std::string s, char sep, std::vector<std::string> *pOutput)
7421 {
7422  std::string tmp;
7423  int i;
7424  tmp = "";
7425  pOutput->clear();
7426  for(i=0; i<s.length(); i++)
7427  {
7428  if( s[i]!=sep )
7429  {
7430  tmp += s[i];
7431  continue;
7432  }
7433  //if( tmp.length()!=0 )
7434  pOutput->push_back(tmp);
7435  tmp = "";
7436  }
7437  if( tmp.length()!=0 )
7438  pOutput->push_back(tmp);
7439 }
7440 
7441 std::string alglib::strtolower(const std::string &s)
7442 {
7443  std::string r = s;
7444  for(int i=0; i<r.length(); i++)
7445  r[i] = tolower(r[i]);
7446  return r;
7447 }
7448 
7449 std::string alglib::xtrim(std::string s)
7450 {
7451  char *pstr = (char*)malloc(s.length()+1);
7452  char *p2 = pstr;
7453  if( pstr==NULL )
7454  throw "xalloc in xtrim()";
7455  try
7456  {
7457  bool bws;
7458  int i;
7459 
7460  //
7461  // special cases:
7462  // * zero length string
7463  // * string includes only spaces
7464  //
7465  if( s.length()==0 )
7466  {
7467  free(pstr);
7468  return "";
7469  }
7470  bws = true;
7471  for(i=0; i<s.length(); i++)
7472  if( s[i]!=' ' )
7473  bws = false;
7474  if( bws )
7475  {
7476  free(pstr);
7477  return "";
7478  }
7479 
7480  //
7481  // merge internal spaces
7482  //
7483  bws = false;
7484  for(i=0; i<s.length(); i++)
7485  {
7486  if( s[i]==' ' && bws )
7487  continue;
7488  if( s[i]==' ' )
7489  {
7490  *p2 = ' ';
7491  p2++;
7492  bws = true;
7493  continue;
7494  }
7495  *p2 = s[i];
7496  bws = false;
7497  p2++;
7498  }
7499  *p2 = 0;
7500 
7501  //
7502  // trim leading/trailing spaces.
7503  // we expect at least one non-space character in the string
7504  //
7505  p2--;
7506  while(*p2==' ')
7507  {
7508  *p2 = 0;
7509  p2--;
7510  }
7511  p2 = pstr;
7512  while((*p2)==' ')
7513  p2++;
7514 
7515  //
7516  // result
7517  //
7518  std::string r = p2;
7519  free(pstr);
7520  return r;
7521  }
7522  catch(...)
7523  {
7524  free(pstr);
7525  throw "unknown exception in xtrim()";
7526  }
7527 }
7528 
7529 bool alglib::opendataset(std::string file, dataset *pdataset)
7530 {
7531  std::list<std::string> Lines;
7532  std::vector<std::string> Values, RowsArr, ColsArr, VarsArr, HeadArr;
7533  std::list<std::string>::iterator i;
7534  std::string s;
7535  int TrnFirst, TrnLast, ValFirst, ValLast, TstFirst, TstLast, LinesRead, j;
7536 
7537  //
7538  // Read data
7539  //
7540  if( pdataset==NULL )
7541  return false;
7542  if( !readstrings(file, &Lines, "//") )
7543  return false;
7544  i = Lines.begin();
7545  *pdataset = dataset();
7546 
7547  //
7548  // Read header
7549  //
7550  if( i==Lines.end() )
7551  return false;
7552  s = alglib::xtrim(*i);
7553  alglib::explodestring(s, '#', &HeadArr);
7554  if( HeadArr.size()!=2 )
7555  return false;
7556 
7557  //
7558  // Rows info
7559  //
7560  alglib::explodestring(alglib::xtrim(HeadArr[0]), ' ', &RowsArr);
7561  if( RowsArr.size()==0 || RowsArr.size()>3 )
7562  return false;
7563  if( RowsArr.size()==1 )
7564  {
7565  pdataset->totalsize = atol(RowsArr[0].c_str());
7566  pdataset->trnsize = pdataset->totalsize;
7567  }
7568  if( RowsArr.size()==2 )
7569  {
7570  pdataset->trnsize = atol(RowsArr[0].c_str());
7571  pdataset->tstsize = atol(RowsArr[1].c_str());
7572  pdataset->totalsize = pdataset->trnsize + pdataset->tstsize;
7573  }
7574  if( RowsArr.size()==3 )
7575  {
7576  pdataset->trnsize = atol(RowsArr[0].c_str());
7577  pdataset->valsize = atol(RowsArr[1].c_str());
7578  pdataset->tstsize = atol(RowsArr[2].c_str());
7579  pdataset->totalsize = pdataset->trnsize + pdataset->valsize + pdataset->tstsize;
7580  }
7581  if( pdataset->totalsize<=0 || pdataset->trnsize<0 || pdataset->valsize<0 || pdataset->tstsize<0 )
7582  return false;
7583  TrnFirst = 0;
7584  TrnLast = TrnFirst + pdataset->trnsize;
7585  ValFirst = TrnLast;
7586  ValLast = ValFirst + pdataset->valsize;
7587  TstFirst = ValLast;
7588  TstLast = TstFirst + pdataset->tstsize;
7589 
7590  //
7591  // columns
7592  //
7593  alglib::explodestring(alglib::xtrim(HeadArr[1]), ' ', &ColsArr);
7594  if( ColsArr.size()!=1 && ColsArr.size()!=4 )
7595  return false;
7596  if( ColsArr.size()==1 )
7597  {
7598  pdataset->nin = atoi(ColsArr[0].c_str());
7599  if( pdataset->nin<=0 )
7600  return false;
7601  }
7602  if( ColsArr.size()==4 )
7603  {
7604  if( alglib::strtolower(ColsArr[0])!="reg" && alglib::strtolower(ColsArr[0])!="cls" )
7605  return false;
7606  if( ColsArr[2]!="=>" )
7607  return false;
7608  pdataset->nin = atol(ColsArr[1].c_str());
7609  if( pdataset->nin<1 )
7610  return false;
7611  if( alglib::strtolower(ColsArr[0])=="reg" )
7612  {
7613  pdataset->nclasses = 0;
7614  pdataset->nout = atol(ColsArr[3].c_str());
7615  if( pdataset->nout<1 )
7616  return false;
7617  }
7618  else
7619  {
7620  pdataset->nclasses = atol(ColsArr[3].c_str());
7621  pdataset->nout = 1;
7622  if( pdataset->nclasses<2 )
7623  return false;
7624  }
7625  }
7626 
7627  //
7628  // initialize arrays
7629  //
7630  pdataset->all.setlength(pdataset->totalsize, pdataset->nin+pdataset->nout);
7631  if( pdataset->trnsize>0 ) pdataset->trn.setlength(pdataset->trnsize, pdataset->nin+pdataset->nout);
7632  if( pdataset->valsize>0 ) pdataset->val.setlength(pdataset->valsize, pdataset->nin+pdataset->nout);
7633  if( pdataset->tstsize>0 ) pdataset->tst.setlength(pdataset->tstsize, pdataset->nin+pdataset->nout);
7634 
7635  //
7636  // read data
7637  //
7638  for(LinesRead=0, i++; i!=Lines.end() && LinesRead<pdataset->totalsize; i++, LinesRead++)
7639  {
7640  std::string sss = *i;
7641  alglib::explodestring(alglib::xtrim(*i), ' ', &VarsArr);
7642  if( VarsArr.size()!=pdataset->nin+pdataset->nout )
7643  return false;
7644  int tmpc = alglib::round(atof(VarsArr[pdataset->nin+pdataset->nout-1].c_str()));
7645  if( pdataset->nclasses>0 && (tmpc<0 || tmpc>=pdataset->nclasses) )
7646  return false;
7647  for(j=0; j<pdataset->nin+pdataset->nout; j++)
7648  {
7649  pdataset->all(LinesRead,j) = atof(VarsArr[j].c_str());
7650  if( LinesRead>=TrnFirst && LinesRead<TrnLast )
7651  pdataset->trn(LinesRead-TrnFirst,j) = atof(VarsArr[j].c_str());
7652  if( LinesRead>=ValFirst && LinesRead<ValLast )
7653  pdataset->val(LinesRead-ValFirst,j) = atof(VarsArr[j].c_str());
7654  if( LinesRead>=TstFirst && LinesRead<TstLast )
7655  pdataset->tst(LinesRead-TstFirst,j) = atof(VarsArr[j].c_str());
7656  }
7657  }
7658  if( LinesRead!=pdataset->totalsize )
7659  return false;
7660  return true;
7661 }*/
7662 
7663 /*
7664 previous variant
7665 bool alglib::opendataset(std::string file, dataset *pdataset)
7666 {
7667  std::list<std::string> Lines;
7668  std::vector<std::string> Values;
7669  std::list<std::string>::iterator i;
7670  int nCol, nRow, nSplitted;
7671  int nColumns, nRows;
7672 
7673  //
7674  // Read data
7675  //
7676  if( pdataset==NULL )
7677  return false;
7678  if( !readstrings(file, &Lines, "//") )
7679  return false;
7680  i = Lines.begin();
7681  *pdataset = dataset();
7682 
7683  //
7684  // Read columns info
7685  //
7686  if( i==Lines.end() )
7687  return false;
7688  if( sscanf(i->c_str(), " columns = %d %d ", &pdataset->nin, &pdataset->nout)!=2 )
7689  return false;
7690  if( pdataset->nin<=0 || pdataset->nout==0 || pdataset->nout==-1)
7691  return false;
7692  if( pdataset->nout<0 )
7693  {
7694  pdataset->nclasses = -pdataset->nout;
7695  pdataset->nout = 1;
7696  pdataset->iscls = true;
7697  }
7698  else
7699  {
7700  pdataset->isreg = true;
7701  }
7702  nColumns = pdataset->nin+pdataset->nout;
7703  i++;
7704 
7705  //
7706  // Read rows info
7707  //
7708  if( i==Lines.end() )
7709  return false;
7710  if( sscanf(i->c_str(), " rows = %d %d %d ", &pdataset->trnsize, &pdataset->valsize, &pdataset->tstsize)!=3 )
7711  return false;
7712  if( (pdataset->trnsize<0) || (pdataset->valsize<0) || (pdataset->tstsize<0) )
7713  return false;
7714  if( (pdataset->trnsize==0) && (pdataset->valsize==0) && (pdataset->tstsize==0) )
7715  return false;
7716  nRows = pdataset->trnsize+pdataset->valsize+pdataset->tstsize;
7717  pdataset->size = nRows;
7718  if( Lines.size()!=nRows+2 )
7719  return false;
7720  i++;
7721 
7722  //
7723  // Read all cases
7724  //
7725  alglib::real_2d_array &arr = pdataset->all;
7726  arr.setbounds(0, nRows-1, 0, nColumns-1);
7727  for(nRow=0; nRow<nRows; nRow++)
7728  {
7729  alglib::ap_error::make_assertion(i!=Lines.end());
7730  explodestring(*i, '\t', &Values);
7731  if( Values.size()!=nColumns )
7732  return false;
7733  for(nCol=0; nCol<nColumns; nCol++)
7734  {
7735  double v;
7736  if( sscanf(Values[nCol].c_str(), "%lg", &v)!=1 )
7737  return false;
7738  if( (nCol==nColumns-1) && pdataset->iscls && ((round(v)<0) || (round(v)>=pdataset->nclasses)) )
7739  return false;
7740  if( (nCol==nColumns-1) && pdataset->iscls )
7741  arr(nRow, nCol) = round(v);
7742  else
7743  arr(nRow, nCol) = v;
7744  }
7745  i++;
7746  }
7747 
7748  //
7749  // Split to training, validation and test sets
7750  //
7751  if( pdataset->trnsize>0 )
7752  pdataset->trn.setbounds(0, pdataset->trnsize-1, 0, nColumns-1);
7753  if( pdataset->valsize>0 )
7754  pdataset->val.setbounds(0, pdataset->valsize-1, 0, nColumns-1);
7755  if( pdataset->tstsize>0 )
7756  pdataset->tst.setbounds(0, pdataset->tstsize-1, 0, nColumns-1);
7757  nSplitted=0;
7758  for(nRow=0; nRow<=pdataset->trnsize-1; nRow++, nSplitted++)
7759  for(nCol=0; nCol<=nColumns-1; nCol++)
7760  pdataset->trn(nRow,nCol) = arr(nSplitted,nCol);
7761  for(nRow=0; nRow<=pdataset->valsize-1; nRow++, nSplitted++)
7762  for(nCol=0; nCol<=nColumns-1; nCol++)
7763  pdataset->val(nRow,nCol) = arr(nSplitted,nCol);
7764  for(nRow=0; nRow<=pdataset->tstsize-1; nRow++, nSplitted++)
7765  for(nCol=0; nCol<=nColumns-1; nCol++)
7766  pdataset->tst(nRow,nCol) = arr(nSplitted,nCol);
7767  return true;
7768 }*/
7769 
7771 {
7772  return n2-n1+1;
7773 }
7774 
7775 
7776 
7778 //
7779 // THIS SECTIONS CONTAINS OPTIMIZED LINEAR ALGEBRA CODE
7780 // IT IS SHARED BETWEEN C++ AND PURE C LIBRARIES
7781 //
7783 namespace alglib_impl
7784 {
7785 #define alglib_simd_alignment 16
7786 
7787 #define alglib_r_block 32
7788 #define alglib_half_r_block 16
7789 #define alglib_twice_r_block 64
7790 
7791 #define alglib_c_block 24
7792 #define alglib_half_c_block 12
7793 #define alglib_twice_c_block 48
7794 
7795 
7796 /********************************************************************
7797 This subroutine calculates fast 32x32 real matrix-vector product:
7798 
7799  y := beta*y + alpha*A*x
7800 
7801 using either generic C code or native optimizations (if available)
7802 
7803 IMPORTANT:
7804 * A must be stored in row-major order,
7805  stride is alglib_r_block,
7806  aligned on alglib_simd_alignment boundary
7807 * X must be aligned on alglib_simd_alignment boundary
7808 * Y may be non-aligned
7809 ********************************************************************/
7810 void _ialglib_mv_32(const double *a, const double *x, double *y, ae_int_t stride, double alpha, double beta)
7811 {
7812  ae_int_t i, k;
7813  const double *pa0, *pa1, *pb;
7814 
7815  pa0 = a;
7816  pa1 = a+alglib_r_block;
7817  pb = x;
7818  for(i=0; i<16; i++)
7819  {
7820  double v0 = 0, v1 = 0;
7821  for(k=0; k<4; k++)
7822  {
7823  v0 += pa0[0]*pb[0];
7824  v1 += pa1[0]*pb[0];
7825  v0 += pa0[1]*pb[1];
7826  v1 += pa1[1]*pb[1];
7827  v0 += pa0[2]*pb[2];
7828  v1 += pa1[2]*pb[2];
7829  v0 += pa0[3]*pb[3];
7830  v1 += pa1[3]*pb[3];
7831  v0 += pa0[4]*pb[4];
7832  v1 += pa1[4]*pb[4];
7833  v0 += pa0[5]*pb[5];
7834  v1 += pa1[5]*pb[5];
7835  v0 += pa0[6]*pb[6];
7836  v1 += pa1[6]*pb[6];
7837  v0 += pa0[7]*pb[7];
7838  v1 += pa1[7]*pb[7];
7839  pa0 += 8;
7840  pa1 += 8;
7841  pb += 8;
7842  }
7843  y[0] = beta*y[0]+alpha*v0;
7844  y[stride] = beta*y[stride]+alpha*v1;
7845 
7846  /*
7847  * now we've processed rows I and I+1,
7848  * pa0 and pa1 are pointing to rows I+1 and I+2.
7849  * move to I+2 and I+3.
7850  */
7851  pa0 += alglib_r_block;
7852  pa1 += alglib_r_block;
7853  pb = x;
7854  y+=2*stride;
7855  }
7856 }
7857 
7858 
7859 /*************************************************************************
7860 This function calculates MxN real matrix-vector product:
7861 
7862  y := beta*y + alpha*A*x
7863 
7864 using generic C code. It calls _ialglib_mv_32 if both M=32 and N=32.
7865 
7866 If beta is zero, we do not use previous values of y (they are overwritten
7867 by alpha*A*x without ever being read). If alpha is zero, no matrix-vector
7868 product is calculated (only beta is updated); however, this update is not
7869 efficient and this function should NOT be used for multiplication of
7870 vector and scalar.
7871 
7872 IMPORTANT:
7873 * 0<=M<=alglib_r_block, 0<=N<=alglib_r_block
7874 * A must be stored in row-major order with stride equal to alglib_r_block
7875 *************************************************************************/
7876 void _ialglib_rmv(ae_int_t m, ae_int_t n, const double *a, const double *x, double *y, ae_int_t stride, double alpha, double beta)
7877 {
7878  /*
7879  * Handle special cases:
7880  * - alpha is zero or n is zero
7881  * - m is zero
7882  */
7883  if( m==0 )
7884  return;
7885  if( alpha==0.0 || n==0 )
7886  {
7887  ae_int_t i;
7888  if( beta==0.0 )
7889  {
7890  for(i=0; i<m; i++)
7891  {
7892  *y = 0.0;
7893  y += stride;
7894  }
7895  }
7896  else
7897  {
7898  for(i=0; i<m; i++)
7899  {
7900  *y *= beta;
7901  y += stride;
7902  }
7903  }
7904  return;
7905  }
7906 
7907  /*
7908  * Handle general case: nonzero alpha, n and m
7909  *
7910  */
7911  if( m==32 && n==32 )
7912  {
7913  /*
7914  * 32x32, may be we have something better than general implementation
7915  */
7916  _ialglib_mv_32(a, x, y, stride, alpha, beta);
7917  }
7918  else
7919  {
7920  ae_int_t i, k, m2, n8, n2, ntrail2;
7921  const double *pa0, *pa1, *pb;
7922 
7923  /*
7924  * First M/2 rows of A are processed in pairs.
7925  * optimized code is used.
7926  */
7927  m2 = m/2;
7928  n8 = n/8;
7929  ntrail2 = (n-8*n8)/2;
7930  for(i=0; i<m2; i++)
7931  {
7932  double v0 = 0, v1 = 0;
7933 
7934  /*
7935  * 'a' points to the part of the matrix which
7936  * is not processed yet
7937  */
7938  pb = x;
7939  pa0 = a;
7940  pa1 = a+alglib_r_block;
7941  a += alglib_twice_r_block;
7942 
7943  /*
7944  * 8 elements per iteration
7945  */
7946  for(k=0; k<n8; k++)
7947  {
7948  v0 += pa0[0]*pb[0];
7949  v1 += pa1[0]*pb[0];
7950  v0 += pa0[1]*pb[1];
7951  v1 += pa1[1]*pb[1];
7952  v0 += pa0[2]*pb[2];
7953  v1 += pa1[2]*pb[2];
7954  v0 += pa0[3]*pb[3];
7955  v1 += pa1[3]*pb[3];
7956  v0 += pa0[4]*pb[4];
7957  v1 += pa1[4]*pb[4];
7958  v0 += pa0[5]*pb[5];
7959  v1 += pa1[5]*pb[5];
7960  v0 += pa0[6]*pb[6];
7961  v1 += pa1[6]*pb[6];
7962  v0 += pa0[7]*pb[7];
7963  v1 += pa1[7]*pb[7];
7964  pa0 += 8;
7965  pa1 += 8;
7966  pb += 8;
7967  }
7968 
7969  /*
7970  * 2 elements per iteration
7971  */
7972  for(k=0; k<ntrail2; k++)
7973  {
7974  v0 += pa0[0]*pb[0];
7975  v1 += pa1[0]*pb[0];
7976  v0 += pa0[1]*pb[1];
7977  v1 += pa1[1]*pb[1];
7978  pa0 += 2;
7979  pa1 += 2;
7980  pb += 2;
7981  }
7982 
7983  /*
7984  * last element, if needed
7985  */
7986  if( n%2!=0 )
7987  {
7988  v0 += pa0[0]*pb[0];
7989  v1 += pa1[0]*pb[0];
7990  }
7991 
7992  /*
7993  * final update
7994  */
7995  if( beta!=0 )
7996  {
7997  y[0] = beta*y[0]+alpha*v0;
7998  y[stride] = beta*y[stride]+alpha*v1;
7999  }
8000  else
8001  {
8002  y[0] = alpha*v0;
8003  y[stride] = alpha*v1;
8004  }
8005 
8006  /*
8007  * move to the next pair of elements
8008  */
8009  y+=2*stride;
8010  }
8011 
8012 
8013  /*
8014  * Last (odd) row is processed with less optimized code.
8015  */
8016  if( m%2!=0 )
8017  {
8018  double v0 = 0;
8019 
8020  /*
8021  * 'a' points to the part of the matrix which
8022  * is not processed yet
8023  */
8024  pb = x;
8025  pa0 = a;
8026 
8027  /*
8028  * 2 elements per iteration
8029  */
8030  n2 = n/2;
8031  for(k=0; k<n2; k++)
8032  {
8033  v0 += pa0[0]*pb[0]+pa0[1]*pb[1];
8034  pa0 += 2;
8035  pb += 2;
8036  }
8037 
8038  /*
8039  * last element, if needed
8040  */
8041  if( n%2!=0 )
8042  v0 += pa0[0]*pb[0];
8043 
8044  /*
8045  * final update
8046  */
8047  if( beta!=0 )
8048  y[0] = beta*y[0]+alpha*v0;
8049  else
8050  y[0] = alpha*v0;
8051  }
8052  }
8053 }
8054 
8055 
8056 /*************************************************************************
8057 This function calculates MxN real matrix-vector product:
8058 
8059  y := beta*y + alpha*A*x
8060 
8061 using generic C code. It calls _ialglib_mv_32 if both M=32 and N=32.
8062 
8063 If beta is zero, we do not use previous values of y (they are overwritten
8064 by alpha*A*x without ever being read). If alpha is zero, no matrix-vector
8065 product is calculated (only beta is updated); however, this update is not
8066 efficient and this function should NOT be used for multiplication of
8067 vector and scalar.
8068 
8069 IMPORTANT:
8070 * 0<=M<=alglib_r_block, 0<=N<=alglib_r_block
8071 * A must be stored in row-major order with stride equal to alglib_r_block
8072 * y may be non-aligned
8073 * both A and x must have same offset with respect to 16-byte boundary:
8074  either both are aligned, or both are aligned with offset 8. Function
8075  will crash your system if you try to call it with misaligned or
8076  incorrectly aligned data.
8077 
8078 This function supports SSE2; it can be used when:
8079 1. AE_HAS_SSE2_INTRINSICS was defined (checked at compile-time)
8080 2. ae_cpuid() result contains CPU_SSE2 (checked at run-time)
8081 
8082 If (1) is failed, this function will be undefined. If (2) is failed, call
8083 to this function will probably crash your system.
8084 
8085 If you want to know whether it is safe to call it, you should check
8086 results of ae_cpuid(). If CPU_SSE2 bit is set, this function is callable
8087 and will do its work.
8088 *************************************************************************/
8089 #if defined(AE_HAS_SSE2_INTRINSICS)
8090 void _ialglib_rmv_sse2(ae_int_t m, ae_int_t n, const double *a, const double *x, double *y, ae_int_t stride, double alpha, double beta)
8091 {
8092  ae_int_t i, k, n2;
8093  ae_int_t mb3, mtail, nhead, nb8, nb2, ntail;
8094  const double *pa0, *pa1, *pa2, *pb;
8095  __m128d v0, v1, v2, va0, va1, va2, vx, vtmp;
8096  double buf3[3], buf6[6];
8097  double d;
8098 
8099  /*
8100  * Handle special cases:
8101  * - alpha is zero or n is zero
8102  * - m is zero
8103  */
8104  if( m==0 )
8105  return;
8106  if( alpha==0.0 || n==0 )
8107  {
8108  if( beta==0.0 )
8109  {
8110  for(i=0; i<m; i++)
8111  {
8112  *y = 0.0;
8113  y += stride;
8114  }
8115  }
8116  else
8117  {
8118  for(i=0; i<m; i++)
8119  {
8120  *y *= beta;
8121  y += stride;
8122  }
8123  }
8124  return;
8125  }
8126 
8127  /*
8128  * Handle general case: nonzero alpha, n and m
8129  *
8130  * We divide problem as follows...
8131  *
8132  * Rows M are divided into:
8133  * - mb3 blocks, each 3xN
8134  * - mtail blocks, each 1xN
8135  *
8136  * Within a row, elements are divided into:
8137  * - nhead 1x1 blocks (used to align the rest, either 0 or 1)
8138  * - nb8 1x8 blocks, aligned to 16-byte boundary
8139  * - nb2 1x2 blocks, aligned to 16-byte boundary
8140  * - ntail 1x1 blocks, aligned too (although we don't rely on it)
8141  *
8142  */
8143  n2 = n/2;
8144  mb3 = m/3;
8145  mtail = m%3;
8146  nhead = ae_misalignment(a,alglib_simd_alignment)==0 ? 0 : 1;
8147  nb8 = (n-nhead)/8;
8148  nb2 = (n-nhead-8*nb8)/2;
8149  ntail = n-nhead-8*nb8-2*nb2;
8150  for(i=0; i<mb3; i++)
8151  {
8152  double row0, row1, row2;
8153  row0 = 0;
8154  row1 = 0;
8155  row2 = 0;
8156  pb = x;
8157  pa0 = a;
8158  pa1 = a+alglib_r_block;
8159  pa2 = a+alglib_twice_r_block;
8160  a += 3*alglib_r_block;
8161  if( nhead==1 )
8162  {
8163  vx = _mm_load_sd(pb);
8164  v0 = _mm_load_sd(pa0);
8165  v1 = _mm_load_sd(pa1);
8166  v2 = _mm_load_sd(pa2);
8167 
8168  v0 = _mm_mul_sd(v0,vx);
8169  v1 = _mm_mul_sd(v1,vx);
8170  v2 = _mm_mul_sd(v2,vx);
8171 
8172  pa0++;
8173  pa1++;
8174  pa2++;
8175  pb++;
8176  }
8177  else
8178  {
8179  v0 = _mm_setzero_pd();
8180  v1 = _mm_setzero_pd();
8181  v2 = _mm_setzero_pd();
8182  }
8183  for(k=0; k<nb8; k++)
8184  {
8185  /*
8186  * this code is a shuffle of simultaneous dot product.
8187  * see below for commented unshuffled original version.
8188  */
8189  vx = _mm_load_pd(pb);
8190  va0 = _mm_load_pd(pa0);
8191  va1 = _mm_load_pd(pa1);
8192  va0 = _mm_mul_pd(va0,vx);
8193  va2 = _mm_load_pd(pa2);
8194  v0 = _mm_add_pd(va0,v0);
8195  va1 = _mm_mul_pd(va1,vx);
8196  va0 = _mm_load_pd(pa0+2);
8197  v1 = _mm_add_pd(va1,v1);
8198  va2 = _mm_mul_pd(va2,vx);
8199  va1 = _mm_load_pd(pa1+2);
8200  v2 = _mm_add_pd(va2,v2);
8201  vx = _mm_load_pd(pb+2);
8202  va0 = _mm_mul_pd(va0,vx);
8203  va2 = _mm_load_pd(pa2+2);
8204  v0 = _mm_add_pd(va0,v0);
8205  va1 = _mm_mul_pd(va1,vx);
8206  va0 = _mm_load_pd(pa0+4);
8207  v1 = _mm_add_pd(va1,v1);
8208  va2 = _mm_mul_pd(va2,vx);
8209  va1 = _mm_load_pd(pa1+4);
8210  v2 = _mm_add_pd(va2,v2);
8211  vx = _mm_load_pd(pb+4);
8212  va0 = _mm_mul_pd(va0,vx);
8213  va2 = _mm_load_pd(pa2+4);
8214  v0 = _mm_add_pd(va0,v0);
8215  va1 = _mm_mul_pd(va1,vx);
8216  va0 = _mm_load_pd(pa0+6);
8217  v1 = _mm_add_pd(va1,v1);
8218  va2 = _mm_mul_pd(va2,vx);
8219  va1 = _mm_load_pd(pa1+6);
8220  v2 = _mm_add_pd(va2,v2);
8221  vx = _mm_load_pd(pb+6);
8222  va0 = _mm_mul_pd(va0,vx);
8223  v0 = _mm_add_pd(va0,v0);
8224  va2 = _mm_load_pd(pa2+6);
8225  va1 = _mm_mul_pd(va1,vx);
8226  v1 = _mm_add_pd(va1,v1);
8227  va2 = _mm_mul_pd(va2,vx);
8228  v2 = _mm_add_pd(va2,v2);
8229 
8230  pa0 += 8;
8231  pa1 += 8;
8232  pa2 += 8;
8233  pb += 8;
8234 
8235  /*
8236  this is unshuffled version of code above
8237 
8238  vx = _mm_load_pd(pb);
8239  va0 = _mm_load_pd(pa0);
8240  va1 = _mm_load_pd(pa1);
8241  va2 = _mm_load_pd(pa2);
8242 
8243  va0 = _mm_mul_pd(va0,vx);
8244  va1 = _mm_mul_pd(va1,vx);
8245  va2 = _mm_mul_pd(va2,vx);
8246 
8247  v0 = _mm_add_pd(va0,v0);
8248  v1 = _mm_add_pd(va1,v1);
8249  v2 = _mm_add_pd(va2,v2);
8250 
8251  vx = _mm_load_pd(pb+2);
8252  va0 = _mm_load_pd(pa0+2);
8253  va1 = _mm_load_pd(pa1+2);
8254  va2 = _mm_load_pd(pa2+2);
8255 
8256  va0 = _mm_mul_pd(va0,vx);
8257  va1 = _mm_mul_pd(va1,vx);
8258  va2 = _mm_mul_pd(va2,vx);
8259 
8260  v0 = _mm_add_pd(va0,v0);
8261  v1 = _mm_add_pd(va1,v1);
8262  v2 = _mm_add_pd(va2,v2);
8263 
8264  vx = _mm_load_pd(pb+4);
8265  va0 = _mm_load_pd(pa0+4);
8266  va1 = _mm_load_pd(pa1+4);
8267  va2 = _mm_load_pd(pa2+4);
8268 
8269  va0 = _mm_mul_pd(va0,vx);
8270  va1 = _mm_mul_pd(va1,vx);
8271  va2 = _mm_mul_pd(va2,vx);
8272 
8273  v0 = _mm_add_pd(va0,v0);
8274  v1 = _mm_add_pd(va1,v1);
8275  v2 = _mm_add_pd(va2,v2);
8276 
8277  vx = _mm_load_pd(pb+6);
8278  va0 = _mm_load_pd(pa0+6);
8279  va1 = _mm_load_pd(pa1+6);
8280  va2 = _mm_load_pd(pa2+6);
8281 
8282  va0 = _mm_mul_pd(va0,vx);
8283  va1 = _mm_mul_pd(va1,vx);
8284  va2 = _mm_mul_pd(va2,vx);
8285 
8286  v0 = _mm_add_pd(va0,v0);
8287  v1 = _mm_add_pd(va1,v1);
8288  v2 = _mm_add_pd(va2,v2);
8289  */
8290  }
8291  for(k=0; k<nb2; k++)
8292  {
8293  vx = _mm_load_pd(pb);
8294  va0 = _mm_load_pd(pa0);
8295  va1 = _mm_load_pd(pa1);
8296  va2 = _mm_load_pd(pa2);
8297 
8298  va0 = _mm_mul_pd(va0,vx);
8299  v0 = _mm_add_pd(va0,v0);
8300  va1 = _mm_mul_pd(va1,vx);
8301  v1 = _mm_add_pd(va1,v1);
8302  va2 = _mm_mul_pd(va2,vx);
8303  v2 = _mm_add_pd(va2,v2);
8304 
8305  pa0 += 2;
8306  pa1 += 2;
8307  pa2 += 2;
8308  pb += 2;
8309  }
8310  for(k=0; k<ntail; k++)
8311  {
8312  vx = _mm_load1_pd(pb);
8313  va0 = _mm_load1_pd(pa0);
8314  va1 = _mm_load1_pd(pa1);
8315  va2 = _mm_load1_pd(pa2);
8316 
8317  va0 = _mm_mul_sd(va0,vx);
8318  v0 = _mm_add_sd(v0,va0);
8319  va1 = _mm_mul_sd(va1,vx);
8320  v1 = _mm_add_sd(v1,va1);
8321  va2 = _mm_mul_sd(va2,vx);
8322  v2 = _mm_add_sd(v2,va2);
8323  }
8324  vtmp = _mm_add_pd(_mm_unpacklo_pd(v0,v1),_mm_unpackhi_pd(v0,v1));
8325  _mm_storel_pd(&row0, vtmp);
8326  _mm_storeh_pd(&row1, vtmp);
8327  v2 = _mm_add_sd(_mm_shuffle_pd(v2,v2,1),v2);
8328  _mm_storel_pd(&row2, v2);
8329  if( beta!=0 )
8330  {
8331  y[0] = beta*y[0]+alpha*row0;
8332  y[stride] = beta*y[stride]+alpha*row1;
8333  y[2*stride] = beta*y[2*stride]+alpha*row2;
8334  }
8335  else
8336  {
8337  y[0] = alpha*row0;
8338  y[stride] = alpha*row1;
8339  y[2*stride] = alpha*row2;
8340  }
8341  y+=3*stride;
8342  }
8343  for(i=0; i<mtail; i++)
8344  {
8345  double row0;
8346  row0 = 0;
8347  pb = x;
8348  pa0 = a;
8349  a += alglib_r_block;
8350  for(k=0; k<n2; k++)
8351  {
8352  row0 += pb[0]*pa0[0]+pb[1]*pa0[1];
8353  pa0 += 2;
8354  pb += 2;
8355  }
8356  if( n%2 )
8357  row0 += pb[0]*pa0[0];
8358  if( beta!=0 )
8359  y[0] = beta*y[0]+alpha*row0;
8360  else
8361  y[0] = alpha*row0;
8362  y+=stride;
8363  }
8364 }
8365 #endif
8366 
8367 
8368 /*************************************************************************
8369 This subroutine calculates fast MxN complex matrix-vector product:
8370 
8371  y := beta*y + alpha*A*x
8372 
8373 using generic C code, where A, x, y, alpha and beta are complex.
8374 
8375 If beta is zero, we do not use previous values of y (they are overwritten
8376 by alpha*A*x without ever being read). However, when alpha is zero, we
8377 still calculate A*x and multiply it by alpha (this distinction can be
8378 important when A or x contain infinities/NANs).
8379 
8380 IMPORTANT:
8381 * 0<=M<=alglib_c_block, 0<=N<=alglib_c_block
8382 * A must be stored in row-major order, as sequence of double precision
8383  pairs. Stride is alglib_c_block (it is measured in pairs of doubles, not
8384  in doubles).
8385 * Y may be referenced by cy (pointer to ae_complex) or
8386  dy (pointer to array of double precision pair) depending on what type of
8387  output you wish. Pass pointer to Y as one of these parameters,
8388  AND SET OTHER PARAMETER TO NULL.
8389 * both A and x must be aligned; y may be non-aligned.
8390 *************************************************************************/
8391 void _ialglib_cmv(ae_int_t m, ae_int_t n, const double *a, const double *x, ae_complex *cy, double *dy, ae_int_t stride, ae_complex alpha, ae_complex beta)
8392 {
8393  ae_int_t i, j;
8394  const double *pa, *parow, *pb;
8395 
8396  parow = a;
8397  for(i=0; i<m; i++)
8398  {
8399  double v0 = 0, v1 = 0;
8400  pa = parow;
8401  pb = x;
8402  for(j=0; j<n; j++)
8403  {
8404  v0 += pa[0]*pb[0];
8405  v1 += pa[0]*pb[1];
8406  v0 -= pa[1]*pb[1];
8407  v1 += pa[1]*pb[0];
8408 
8409  pa += 2;
8410  pb += 2;
8411  }
8412  if( cy!=NULL )
8413  {
8414  double tx = (beta.x*cy->x-beta.y*cy->y)+(alpha.x*v0-alpha.y*v1);
8415  double ty = (beta.x*cy->y+beta.y*cy->x)+(alpha.x*v1+alpha.y*v0);
8416  cy->x = tx;
8417  cy->y = ty;
8418  cy+=stride;
8419  }
8420  else
8421  {
8422  double tx = (beta.x*dy[0]-beta.y*dy[1])+(alpha.x*v0-alpha.y*v1);
8423  double ty = (beta.x*dy[1]+beta.y*dy[0])+(alpha.x*v1+alpha.y*v0);
8424  dy[0] = tx;
8425  dy[1] = ty;
8426  dy += 2*stride;
8427  }
8428  parow += 2*alglib_c_block;
8429  }
8430 }
8431 
8432 
8433 /*************************************************************************
8434 This subroutine calculates fast MxN complex matrix-vector product:
8435 
8436  y := beta*y + alpha*A*x
8437 
8438 using generic C code, where A, x, y, alpha and beta are complex.
8439 
8440 If beta is zero, we do not use previous values of y (they are overwritten
8441 by alpha*A*x without ever being read). However, when alpha is zero, we
8442 still calculate A*x and multiply it by alpha (this distinction can be
8443 important when A or x contain infinities/NANs).
8444 
8445 IMPORTANT:
8446 * 0<=M<=alglib_c_block, 0<=N<=alglib_c_block
8447 * A must be stored in row-major order, as sequence of double precision
8448  pairs. Stride is alglib_c_block (it is measured in pairs of doubles, not
8449  in doubles).
8450 * Y may be referenced by cy (pointer to ae_complex) or
8451  dy (pointer to array of double precision pair) depending on what type of
8452  output you wish. Pass pointer to Y as one of these parameters,
8453  AND SET OTHER PARAMETER TO NULL.
8454 * both A and x must be aligned; y may be non-aligned.
8455 
8456 This function supports SSE2; it can be used when:
8457 1. AE_HAS_SSE2_INTRINSICS was defined (checked at compile-time)
8458 2. ae_cpuid() result contains CPU_SSE2 (checked at run-time)
8459 
8460 If (1) is failed, this function will be undefined. If (2) is failed, call
8461 to this function will probably crash your system.
8462 
8463 If you want to know whether it is safe to call it, you should check
8464 results of ae_cpuid(). If CPU_SSE2 bit is set, this function is callable
8465 and will do its work.
8466 *************************************************************************/
8467 #if defined(AE_HAS_SSE2_INTRINSICS)
8468 void _ialglib_cmv_sse2(ae_int_t m, ae_int_t n, const double *a, const double *x, ae_complex *cy, double *dy, ae_int_t stride, ae_complex alpha, ae_complex beta)
8469 {
8470  ae_int_t i, j, m2;
8471  const double *pa0, *pa1, *parow, *pb;
8472  __m128d vbeta, vbetax, vbetay;
8473  __m128d valpha, valphax, valphay;
8474 
8475  m2 = m/2;
8476  parow = a;
8477  if( cy!=NULL )
8478  {
8479  dy = (double*)cy;
8480  cy = NULL;
8481  }
8482  vbeta = _mm_loadh_pd(_mm_load_sd(&beta.x),&beta.y);
8483  vbetax = _mm_unpacklo_pd(vbeta,vbeta);
8484  vbetay = _mm_unpackhi_pd(vbeta,vbeta);
8485  valpha = _mm_loadh_pd(_mm_load_sd(&alpha.x),&alpha.y);
8486  valphax = _mm_unpacklo_pd(valpha,valpha);
8487  valphay = _mm_unpackhi_pd(valpha,valpha);
8488  for(i=0; i<m2; i++)
8489  {
8490  double v0 = 0, v1 = 0, v2 = 0, v3 = 0;
8491  double tx, ty;
8492  __m128d vx, vy, vt0, vt1, vt2, vt3, vt4, vt5, vrx, vry, vtx, vty, vbeta;
8493  pa0 = parow;
8494  pa1 = parow+2*alglib_c_block;
8495  pb = x;
8496  vx = _mm_setzero_pd();
8497  vy = _mm_setzero_pd();
8498  for(j=0; j<n; j++)
8499  {
8500  vt0 = _mm_load1_pd(pb);
8501  vt1 = _mm_load1_pd(pb+1);
8502  vt2 = _mm_load_pd(pa0);
8503  vt3 = _mm_load_pd(pa1);
8504  vt5 = _mm_unpacklo_pd(vt2,vt3);
8505  vt4 = _mm_unpackhi_pd(vt2,vt3);
8506  vt2 = vt5;
8507  vt3 = vt4;
8508 
8509  vt2 = _mm_mul_pd(vt2,vt0);
8510  vx = _mm_add_pd(vx,vt2);
8511  vt3 = _mm_mul_pd(vt3,vt1);
8512  vx = _mm_sub_pd(vx,vt3);
8513  vt4 = _mm_mul_pd(vt4,vt0);
8514  vy = _mm_add_pd(vy,vt4);
8515  vt5 = _mm_mul_pd(vt5,vt1);
8516  vy = _mm_add_pd(vy,vt5);
8517 
8518  pa0 += 2;
8519  pa1 += 2;
8520  pb += 2;
8521  }
8522  if( beta.x==0.0 && beta.y==0.0 )
8523  {
8524  vrx = _mm_setzero_pd();
8525  vry = _mm_setzero_pd();
8526  }
8527  else
8528  {
8529  vtx = _mm_loadh_pd(_mm_load_sd(dy+0),dy+2*stride+0);
8530  vty = _mm_loadh_pd(_mm_load_sd(dy+1),dy+2*stride+1);
8531  vrx = _mm_sub_pd(_mm_mul_pd(vbetax,vtx),_mm_mul_pd(vbetay,vty));
8532  vry = _mm_add_pd(_mm_mul_pd(vbetax,vty),_mm_mul_pd(vbetay,vtx));
8533  }
8534  vtx = _mm_sub_pd(_mm_mul_pd(valphax,vx),_mm_mul_pd(valphay,vy));
8535  vty = _mm_add_pd(_mm_mul_pd(valphax,vy),_mm_mul_pd(valphay,vx));
8536  vrx = _mm_add_pd(vrx,vtx);
8537  vry = _mm_add_pd(vry,vty);
8538  _mm_storel_pd(dy+0, vrx);
8539  _mm_storeh_pd(dy+2*stride+0, vrx);
8540  _mm_storel_pd(dy+1, vry);
8541  _mm_storeh_pd(dy+2*stride+1, vry);
8542  dy += 4*stride;
8543  parow += 4*alglib_c_block;
8544  }
8545  if( m%2 )
8546  {
8547  double v0 = 0, v1 = 0, v2 = 0, v3 = 0;
8548  double tx, ty;
8549  pa0 = parow;
8550  pb = x;
8551  for(j=0; j<n; j++)
8552  {
8553  v0 += pa0[0]*pb[0];
8554  v1 += pa0[0]*pb[1];
8555  v0 -= pa0[1]*pb[1];
8556  v1 += pa0[1]*pb[0];
8557 
8558  pa0 += 2;
8559  pb += 2;
8560  }
8561  if( beta.x==0.0 && beta.y==0.0 )
8562  {
8563  tx = 0.0;
8564  ty = 0.0;
8565  }
8566  else
8567  {
8568  tx = beta.x*dy[0]-beta.y*dy[1];
8569  ty = beta.x*dy[1]+beta.y*dy[0];
8570  }
8571  tx += alpha.x*v0-alpha.y*v1;
8572  ty += alpha.x*v1+alpha.y*v0;
8573  dy[0] = tx;
8574  dy[1] = ty;
8575  dy += 2*stride;
8576  parow += 2*alglib_c_block;
8577  }
8578 }
8579 #endif
8580 
8581 /********************************************************************
8582 This subroutine sets vector to zero
8583 ********************************************************************/
8584 void _ialglib_vzero(ae_int_t n, double *p, ae_int_t stride)
8585 {
8586  ae_int_t i;
8587  if( stride==1 )
8588  {
8589  for(i=0; i<n; i++,p++)
8590  *p = 0.0;
8591  }
8592  else
8593  {
8594  for(i=0; i<n; i++,p+=stride)
8595  *p = 0.0;
8596  }
8597 }
8598 
8599 /********************************************************************
8600 This subroutine sets vector to zero
8601 ********************************************************************/
8603 {
8604  ae_int_t i;
8605  if( stride==1 )
8606  {
8607  for(i=0; i<n; i++,p++)
8608  {
8609  p->x = 0.0;
8610  p->y = 0.0;
8611  }
8612  }
8613  else
8614  {
8615  for(i=0; i<n; i++,p+=stride)
8616  {
8617  p->x = 0.0;
8618  p->y = 0.0;
8619  }
8620  }
8621 }
8622 
8623 
8624 /********************************************************************
8625 This subroutine copies unaligned real vector
8626 ********************************************************************/
8627 void _ialglib_vcopy(ae_int_t n, const double *a, ae_int_t stridea, double *b, ae_int_t strideb)
8628 {
8629  ae_int_t i, n2;
8630  if( stridea==1 && strideb==1 )
8631  {
8632  n2 = n/2;
8633  for(i=n2; i!=0; i--, a+=2, b+=2)
8634  {
8635  b[0] = a[0];
8636  b[1] = a[1];
8637  }
8638  if( n%2!=0 )
8639  b[0] = a[0];
8640  }
8641  else
8642  {
8643  for(i=0; i<n; i++,a+=stridea,b+=strideb)
8644  *b = *a;
8645  }
8646 }
8647 
8648 
8649 /********************************************************************
8650 This subroutine copies unaligned complex vector
8651 (passed as ae_complex*)
8652 
8653 1. strideb is stride measured in complex numbers, not doubles
8654 2. conj may be "N" (no conj.) or "C" (conj.)
8655 ********************************************************************/
8656 void _ialglib_vcopy_complex(ae_int_t n, const ae_complex *a, ae_int_t stridea, double *b, ae_int_t strideb, const char *conj)
8657 {
8658  ae_int_t i;
8659 
8660  /*
8661  * more general case
8662  */
8663  if( conj[0]=='N' || conj[0]=='n' )
8664  {
8665  for(i=0; i<n; i++,a+=stridea,b+=2*strideb)
8666  {
8667  b[0] = a->x;
8668  b[1] = a->y;
8669  }
8670  }
8671  else
8672  {
8673  for(i=0; i<n; i++,a+=stridea,b+=2*strideb)
8674  {
8675  b[0] = a->x;
8676  b[1] = -a->y;
8677  }
8678  }
8679 }
8680 
8681 
8682 /********************************************************************
8683 This subroutine copies unaligned complex vector (passed as double*)
8684 
8685 1. strideb is stride measured in complex numbers, not doubles
8686 2. conj may be "N" (no conj.) or "C" (conj.)
8687 ********************************************************************/
8688 void _ialglib_vcopy_dcomplex(ae_int_t n, const double *a, ae_int_t stridea, double *b, ae_int_t strideb, const char *conj)
8689 {
8690  ae_int_t i;
8691 
8692  /*
8693  * more general case
8694  */
8695  if( conj[0]=='N' || conj[0]=='n' )
8696  {
8697  for(i=0; i<n; i++,a+=2*stridea,b+=2*strideb)
8698  {
8699  b[0] = a[0];
8700  b[1] = a[1];
8701  }
8702  }
8703  else
8704  {
8705  for(i=0; i<n; i++,a+=2*stridea,b+=2*strideb)
8706  {
8707  b[0] = a[0];
8708  b[1] = -a[1];
8709  }
8710  }
8711 }
8712 
8713 
8714 /********************************************************************
8715 This subroutine copies matrix from non-aligned non-contigous storage
8716 to aligned contigous storage
8717 
8718 A:
8719 * MxN
8720 * non-aligned
8721 * non-contigous
8722 * may be transformed during copying (as prescribed by op)
8723 
8724 B:
8725 * alglib_r_block*alglib_r_block (only MxN/NxM submatrix is used)
8726 * aligned
8727 * stride is alglib_r_block
8728 
8729 Transformation types:
8730 * 0 - no transform
8731 * 1 - transposition
8732 ********************************************************************/
8733 void _ialglib_mcopyblock(ae_int_t m, ae_int_t n, const double *a, ae_int_t op, ae_int_t stride, double *b)
8734 {
8735  ae_int_t i, j, n2;
8736  const double *psrc;
8737  double *pdst;
8738  if( op==0 )
8739  {
8740  n2 = n/2;
8741  for(i=0,psrc=a; i<m; i++,a+=stride,b+=alglib_r_block,psrc=a)
8742  {
8743  for(j=0,pdst=b; j<n2; j++,pdst+=2,psrc+=2)
8744  {
8745  pdst[0] = psrc[0];
8746  pdst[1] = psrc[1];
8747  }
8748  if( n%2!=0 )
8749  pdst[0] = psrc[0];
8750  }
8751  }
8752  else
8753  {
8754  n2 = n/2;
8755  for(i=0,psrc=a; i<m; i++,a+=stride,b+=1,psrc=a)
8756  {
8757  for(j=0,pdst=b; j<n2; j++,pdst+=alglib_twice_r_block,psrc+=2)
8758  {
8759  pdst[0] = psrc[0];
8760  pdst[alglib_r_block] = psrc[1];
8761  }
8762  if( n%2!=0 )
8763  pdst[0] = psrc[0];
8764  }
8765  }
8766 }
8767 
8768 
8769 /********************************************************************
8770 This subroutine copies matrix from non-aligned non-contigous storage
8771 to aligned contigous storage
8772 
8773 A:
8774 * MxN
8775 * non-aligned
8776 * non-contigous
8777 * may be transformed during copying (as prescribed by op)
8778 
8779 B:
8780 * alglib_r_block*alglib_r_block (only MxN/NxM submatrix is used)
8781 * aligned
8782 * stride is alglib_r_block
8783 
8784 Transformation types:
8785 * 0 - no transform
8786 * 1 - transposition
8787 
8788 This function supports SSE2; it can be used when:
8789 1. AE_HAS_SSE2_INTRINSICS was defined (checked at compile-time)
8790 2. ae_cpuid() result contains CPU_SSE2 (checked at run-time)
8791 
8792 If (1) is failed, this function will be undefined. If (2) is failed, call
8793 to this function will probably crash your system.
8794 
8795 If you want to know whether it is safe to call it, you should check
8796 results of ae_cpuid(). If CPU_SSE2 bit is set, this function is callable
8797 and will do its work.
8798 ********************************************************************/
8799 #if defined(AE_HAS_SSE2_INTRINSICS)
8800 void _ialglib_mcopyblock_sse2(ae_int_t m, ae_int_t n, const double *a, ae_int_t op, ae_int_t stride, double *b)
8801 {
8802  ae_int_t i, j, nb8, mb2, ntail;
8803  const double *psrc0, *psrc1;
8804  double *pdst;
8805  nb8 = n/8;
8806  ntail = n-8*nb8;
8807  if( op==0 )
8808  {
8809  for(i=0,psrc0=a; i<m; i++,a+=stride,b+=alglib_r_block,psrc0=a)
8810  {
8811  pdst=b;
8812  for(j=0; j<nb8; j++)
8813  {
8814  __m128d v0, v1;
8815  v0 = _mm_loadu_pd(psrc0);
8816  _mm_store_pd(pdst, v0);
8817  v1 = _mm_loadu_pd(psrc0+2);
8818  _mm_store_pd(pdst+2, v1);
8819  v1 = _mm_loadu_pd(psrc0+4);
8820  _mm_store_pd(pdst+4, v1);
8821  v1 = _mm_loadu_pd(psrc0+6);
8822  _mm_store_pd(pdst+6, v1);
8823  pdst+=8;
8824  psrc0+=8;
8825  }
8826  for(j=0; j<ntail; j++)
8827  pdst[j] = psrc0[j];
8828  }
8829  }
8830  else
8831  {
8832  const double *arow0, *arow1;
8833  double *bcol0, *bcol1, *pdst0, *pdst1;
8834  ae_int_t nb4, ntail, n2;
8835 
8836  n2 = n/2;
8837  mb2 = m/2;
8838  nb4 = n/4;
8839  ntail = n-4*nb4;
8840 
8841  arow0 = a;
8842  arow1 = a+stride;
8843  bcol0 = b;
8844  bcol1 = b+1;
8845  for(i=0; i<mb2; i++)
8846  {
8847  psrc0 = arow0;
8848  psrc1 = arow1;
8849  pdst0 = bcol0;
8850  pdst1 = bcol1;
8851  for(j=0; j<nb4; j++)
8852  {
8853  __m128d v0, v1, v2, v3;
8854  v0 = _mm_loadu_pd(psrc0);
8855  v1 = _mm_loadu_pd(psrc1);
8856  v2 = _mm_loadu_pd(psrc0+2);
8857  v3 = _mm_loadu_pd(psrc1+2);
8858  _mm_store_pd(pdst0, _mm_unpacklo_pd(v0,v1));
8859  _mm_store_pd(pdst0+alglib_r_block, _mm_unpackhi_pd(v0,v1));
8860  _mm_store_pd(pdst0+2*alglib_r_block, _mm_unpacklo_pd(v2,v3));
8861  _mm_store_pd(pdst0+3*alglib_r_block, _mm_unpackhi_pd(v2,v3));
8862 
8863  pdst0 += 4*alglib_r_block;
8864  pdst1 += 4*alglib_r_block;
8865  psrc0 += 4;
8866  psrc1 += 4;
8867  }
8868  for(j=0; j<ntail; j++)
8869  {
8870  pdst0[0] = psrc0[0];
8871  pdst1[0] = psrc1[0];
8872  pdst0 += alglib_r_block;
8873  pdst1 += alglib_r_block;
8874  psrc0 += 1;
8875  psrc1 += 1;
8876  }
8877  arow0 += 2*stride;
8878  arow1 += 2*stride;
8879  bcol0 += 2;
8880  bcol1 += 2;
8881  }
8882  if( m%2 )
8883  {
8884  psrc0 = arow0;
8885  pdst0 = bcol0;
8886  for(j=0; j<n2; j++)
8887  {
8888  pdst0[0] = psrc0[0];
8889  pdst0[alglib_r_block] = psrc0[1];
8890  pdst0 += alglib_twice_r_block;
8891  psrc0 += 2;
8892  }
8893  if( n%2!=0 )
8894  pdst0[0] = psrc0[0];
8895  }
8896  }
8897 }
8898 #endif
8899 
8900 
8901 /********************************************************************
8902 This subroutine copies matrix from aligned contigous storage to non-
8903 aligned non-contigous storage
8904 
8905 A:
8906 * MxN
8907 * aligned
8908 * contigous
8909 * stride is alglib_r_block
8910 * may be transformed during copying (as prescribed by op)
8911 
8912 B:
8913 * alglib_r_block*alglib_r_block (only MxN/NxM submatrix is used)
8914 * non-aligned, non-contigous
8915 
8916 Transformation types:
8917 * 0 - no transform
8918 * 1 - transposition
8919 ********************************************************************/
8920 void _ialglib_mcopyunblock(ae_int_t m, ae_int_t n, const double *a, ae_int_t op, double *b, ae_int_t stride)
8921 {
8922  ae_int_t i, j, n2;
8923  const double *psrc;
8924  double *pdst;
8925  if( op==0 )
8926  {
8927  n2 = n/2;
8928  for(i=0,psrc=a; i<m; i++,a+=alglib_r_block,b+=stride,psrc=a)
8929  {
8930  for(j=0,pdst=b; j<n2; j++,pdst+=2,psrc+=2)
8931  {
8932  pdst[0] = psrc[0];
8933  pdst[1] = psrc[1];
8934  }
8935  if( n%2!=0 )
8936  pdst[0] = psrc[0];
8937  }
8938  }
8939  else
8940  {
8941  n2 = n/2;
8942  for(i=0,psrc=a; i<m; i++,a++,b+=stride,psrc=a)
8943  {
8944  for(j=0,pdst=b; j<n2; j++,pdst+=2,psrc+=alglib_twice_r_block)
8945  {
8946  pdst[0] = psrc[0];
8947  pdst[1] = psrc[alglib_r_block];
8948  }
8949  if( n%2!=0 )
8950  pdst[0] = psrc[0];
8951  }
8952  }
8953 }
8954 
8955 
8956 /********************************************************************
8957 This subroutine copies matrix from non-aligned non-contigous storage
8958 to aligned contigous storage
8959 
8960 A:
8961 * MxN
8962 * non-aligned
8963 * non-contigous
8964 * may be transformed during copying (as prescribed by op)
8965 * pointer to ae_complex is passed
8966 
8967 B:
8968 * 2*alglib_c_block*alglib_c_block doubles (only MxN/NxM submatrix is used)
8969 * aligned
8970 * stride is alglib_c_block
8971 * pointer to double is passed
8972 
8973 Transformation types:
8974 * 0 - no transform
8975 * 1 - transposition
8976 * 2 - conjugate transposition
8977 * 3 - conjugate, but no transposition
8978 ********************************************************************/
8979 void _ialglib_mcopyblock_complex(ae_int_t m, ae_int_t n, const ae_complex *a, ae_int_t op, ae_int_t stride, double *b)
8980 {
8981  ae_int_t i, j;
8982  const ae_complex *psrc;
8983  double *pdst;
8984  if( op==0 )
8985  {
8986  for(i=0,psrc=a; i<m; i++,a+=stride,b+=alglib_twice_c_block,psrc=a)
8987  for(j=0,pdst=b; j<n; j++,pdst+=2,psrc++)
8988  {
8989  pdst[0] = psrc->x;
8990  pdst[1] = psrc->y;
8991  }
8992  }
8993  if( op==1 )
8994  {
8995  for(i=0,psrc=a; i<m; i++,a+=stride,b+=2,psrc=a)
8996  for(j=0,pdst=b; j<n; j++,pdst+=alglib_twice_c_block,psrc++)
8997  {
8998  pdst[0] = psrc->x;
8999  pdst[1] = psrc->y;
9000  }
9001  }
9002  if( op==2 )
9003  {
9004  for(i=0,psrc=a; i<m; i++,a+=stride,b+=2,psrc=a)
9005  for(j=0,pdst=b; j<n; j++,pdst+=alglib_twice_c_block,psrc++)
9006  {
9007  pdst[0] = psrc->x;
9008  pdst[1] = -psrc->y;
9009  }
9010  }
9011  if( op==3 )
9012  {
9013  for(i=0,psrc=a; i<m; i++,a+=stride,b+=alglib_twice_c_block,psrc=a)
9014  for(j=0,pdst=b; j<n; j++,pdst+=2,psrc++)
9015  {
9016  pdst[0] = psrc->x;
9017  pdst[1] = -psrc->y;
9018  }
9019  }
9020 }
9021 
9022 
9023 /********************************************************************
9024 This subroutine copies matrix from aligned contigous storage to
9025 non-aligned non-contigous storage
9026 
9027 A:
9028 * 2*alglib_c_block*alglib_c_block doubles (only MxN submatrix is used)
9029 * aligned
9030 * stride is alglib_c_block
9031 * pointer to double is passed
9032 * may be transformed during copying (as prescribed by op)
9033 
9034 B:
9035 * MxN
9036 * non-aligned
9037 * non-contigous
9038 * pointer to ae_complex is passed
9039 
9040 Transformation types:
9041 * 0 - no transform
9042 * 1 - transposition
9043 * 2 - conjugate transposition
9044 * 3 - conjugate, but no transposition
9045 ********************************************************************/
9046 void _ialglib_mcopyunblock_complex(ae_int_t m, ae_int_t n, const double *a, ae_int_t op, ae_complex* b, ae_int_t stride)
9047 {
9048  ae_int_t i, j;
9049  const double *psrc;
9050  ae_complex *pdst;
9051  if( op==0 )
9052  {
9053  for(i=0,psrc=a; i<m; i++,a+=alglib_twice_c_block,b+=stride,psrc=a)
9054  for(j=0,pdst=b; j<n; j++,pdst++,psrc+=2)
9055  {
9056  pdst->x = psrc[0];
9057  pdst->y = psrc[1];
9058  }
9059  }
9060  if( op==1 )
9061  {
9062  for(i=0,psrc=a; i<m; i++,a+=2,b+=stride,psrc=a)
9063  for(j=0,pdst=b; j<n; j++,pdst++,psrc+=alglib_twice_c_block)
9064  {
9065  pdst->x = psrc[0];
9066  pdst->y = psrc[1];
9067  }
9068  }
9069  if( op==2 )
9070  {
9071  for(i=0,psrc=a; i<m; i++,a+=2,b+=stride,psrc=a)
9072  for(j=0,pdst=b; j<n; j++,pdst++,psrc+=alglib_twice_c_block)
9073  {
9074  pdst->x = psrc[0];
9075  pdst->y = -psrc[1];
9076  }
9077  }
9078  if( op==3 )
9079  {
9080  for(i=0,psrc=a; i<m; i++,a+=alglib_twice_c_block,b+=stride,psrc=a)
9081  for(j=0,pdst=b; j<n; j++,pdst++,psrc+=2)
9082  {
9083  pdst->x = psrc[0];
9084  pdst->y = -psrc[1];
9085  }
9086  }
9087 }
9088 
9089 
9090 /********************************************************************
9091 Real GEMM kernel
9092 ********************************************************************/
9094  ae_int_t n,
9095  ae_int_t k,
9096  double alpha,
9097  double *_a,
9098  ae_int_t _a_stride,
9099  ae_int_t optypea,
9100  double *_b,
9101  ae_int_t _b_stride,
9102  ae_int_t optypeb,
9103  double beta,
9104  double *_c,
9105  ae_int_t _c_stride)
9106 {
9107  int i;
9108  double *crow;
9109  double _abuf[alglib_r_block+alglib_simd_alignment];
9111  double * const abuf = (double * const) ae_align(_abuf,alglib_simd_alignment);
9112  double * const b = (double * const) ae_align(_bbuf,alglib_simd_alignment);
9113  void (*rmv)(ae_int_t, ae_int_t, const double *, const double *, double *, ae_int_t, double, double) = &_ialglib_rmv;
9114  void (*mcopyblock)(ae_int_t, ae_int_t, const double *, ae_int_t, ae_int_t, double *) = &_ialglib_mcopyblock;
9115 
9116  if( m>alglib_r_block || n>alglib_r_block || k>alglib_r_block || m<=0 || n<=0 || k<=0 || alpha==0.0 )
9117  return ae_false;
9118 
9119  /*
9120  * Check for SSE2 support
9121  */
9122 #ifdef AE_HAS_SSE2_INTRINSICS
9123  if( ae_cpuid() & CPU_SSE2 )
9124  {
9125  rmv = &_ialglib_rmv_sse2;
9126  mcopyblock = &_ialglib_mcopyblock_sse2;
9127  }
9128 #endif
9129 
9130  /*
9131  * copy b
9132  */
9133  if( optypeb==0 )
9134  mcopyblock(k, n, _b, 1, _b_stride, b);
9135  else
9136  mcopyblock(n, k, _b, 0, _b_stride, b);
9137 
9138  /*
9139  * multiply B by A (from the right, by rows)
9140  * and store result in C
9141  */
9142  crow = _c;
9143  if( optypea==0 )
9144  {
9145  const double *arow = _a;
9146  for(i=0; i<m; i++)
9147  {
9148  _ialglib_vcopy(k, arow, 1, abuf, 1);
9149  if( beta==0 )
9150  _ialglib_vzero(n, crow, 1);
9151  rmv(n, k, b, abuf, crow, 1, alpha, beta);
9152  crow += _c_stride;
9153  arow += _a_stride;
9154  }
9155  }
9156  else
9157  {
9158  const double *acol = _a;
9159  for(i=0; i<m; i++)
9160  {
9161  _ialglib_vcopy(k, acol, _a_stride, abuf, 1);
9162  if( beta==0 )
9163  _ialglib_vzero(n, crow, 1);
9164  rmv(n, k, b, abuf, crow, 1, alpha, beta);
9165  crow += _c_stride;
9166  acol++;
9167  }
9168  }
9169  return ae_true;
9170 }
9171 
9172 
9173 /********************************************************************
9174 Complex GEMM kernel
9175 ********************************************************************/
9177  ae_int_t n,
9178  ae_int_t k,
9179  ae_complex alpha,
9180  ae_complex *_a,
9181  ae_int_t _a_stride,
9182  ae_int_t optypea,
9183  ae_complex *_b,
9184  ae_int_t _b_stride,
9185  ae_int_t optypeb,
9186  ae_complex beta,
9187  ae_complex *_c,
9188  ae_int_t _c_stride)
9189  {
9190  const ae_complex *arow;
9191  ae_complex *crow;
9192  ae_int_t i;
9193  double _loc_abuf[2*alglib_c_block+alglib_simd_alignment];
9195  double * const abuf = (double * const) ae_align(_loc_abuf,alglib_simd_alignment);
9196  double * const b = (double * const) ae_align(_loc_b, alglib_simd_alignment);
9197  ae_int_t brows;
9198  ae_int_t bcols;
9199  void (*cmv)(ae_int_t, ae_int_t, const double *, const double *, ae_complex *, double *, ae_int_t, ae_complex, ae_complex) = &_ialglib_cmv;
9200 
9201  if( m>alglib_c_block || n>alglib_c_block || k>alglib_c_block )
9202  return ae_false;
9203 
9204  /*
9205  * Check for SSE2 support
9206  */
9207 #ifdef AE_HAS_SSE2_INTRINSICS
9208  if( ae_cpuid() & CPU_SSE2 )
9209  {
9210  cmv = &_ialglib_cmv_sse2;
9211  }
9212 #endif
9213 
9214  /*
9215  * copy b
9216  */
9217  brows = optypeb==0 ? k : n;
9218  bcols = optypeb==0 ? n : k;
9219  if( optypeb==0 )
9220  _ialglib_mcopyblock_complex(brows, bcols, _b, 1, _b_stride, b);
9221  if( optypeb==1 )
9222  _ialglib_mcopyblock_complex(brows, bcols, _b, 0, _b_stride, b);
9223  if( optypeb==2 )
9224  _ialglib_mcopyblock_complex(brows, bcols, _b, 3, _b_stride, b);
9225 
9226  /*
9227  * multiply B by A (from the right, by rows)
9228  * and store result in C
9229  */
9230  arow = _a;
9231  crow = _c;
9232  for(i=0; i<m; i++)
9233  {
9234  if( optypea==0 )
9235  {
9236  _ialglib_vcopy_complex(k, arow, 1, abuf, 1, "No conj");
9237  arow += _a_stride;
9238  }
9239  else if( optypea==1 )
9240  {
9241  _ialglib_vcopy_complex(k, arow, _a_stride, abuf, 1, "No conj");
9242  arow++;
9243  }
9244  else
9245  {
9246  _ialglib_vcopy_complex(k, arow, _a_stride, abuf, 1, "Conj");
9247  arow++;
9248  }
9249  if( beta.x==0 && beta.y==0 )
9250  _ialglib_vzero_complex(n, crow, 1);
9251  cmv(n, k, b, abuf, crow, NULL, 1, alpha, beta);
9252  crow += _c_stride;
9253  }
9254  return ae_true;
9255 }
9256 
9257 
9258 /********************************************************************
9259 complex TRSM kernel
9260 ********************************************************************/
9262  ae_int_t n,
9263  ae_complex *_a,
9264  ae_int_t _a_stride,
9265  ae_bool isupper,
9266  ae_bool isunit,
9267  ae_int_t optype,
9268  ae_complex *_x,
9269  ae_int_t _x_stride)
9270 {
9271  /*
9272  * local buffers
9273  */
9274  double *pdiag;
9275  ae_int_t i;
9278  double _loc_tmpbuf[2*alglib_c_block+alglib_simd_alignment];
9279  double * const abuf = (double * const) ae_align(_loc_abuf, alglib_simd_alignment);
9280  double * const xbuf = (double * const) ae_align(_loc_xbuf, alglib_simd_alignment);
9281  double * const tmpbuf = (double * const) ae_align(_loc_tmpbuf,alglib_simd_alignment);
9282  ae_bool uppera;
9283  void (*cmv)(ae_int_t, ae_int_t, const double *, const double *, ae_complex *, double *, ae_int_t, ae_complex, ae_complex) = &_ialglib_cmv;
9284 
9285  if( m>alglib_c_block || n>alglib_c_block )
9286  return ae_false;
9287 
9288  /*
9289  * Check for SSE2 support
9290  */
9291 #ifdef AE_HAS_SSE2_INTRINSICS
9292  if( ae_cpuid() & CPU_SSE2 )
9293  {
9294  cmv = &_ialglib_cmv_sse2;
9295  }
9296 #endif
9297 
9298  /*
9299  * Prepare
9300  */
9301  _ialglib_mcopyblock_complex(n, n, _a, optype, _a_stride, abuf);
9302  _ialglib_mcopyblock_complex(m, n, _x, 0, _x_stride, xbuf);
9303  if( isunit )
9304  for(i=0,pdiag=abuf; i<n; i++,pdiag+=2*(alglib_c_block+1))
9305  {
9306  pdiag[0] = 1.0;
9307  pdiag[1] = 0.0;
9308  }
9309  if( optype==0 )
9310  uppera = isupper;
9311  else
9312  uppera = !isupper;
9313 
9314  /*
9315  * Solve Y*A^-1=X where A is upper or lower triangular
9316  */
9317  if( uppera )
9318  {
9319  for(i=0,pdiag=abuf; i<n; i++,pdiag+=2*(alglib_c_block+1))
9320  {
9321  ae_complex tmp_c;
9322  ae_complex beta;
9323  ae_complex alpha;
9324  tmp_c.x = pdiag[0];
9325  tmp_c.y = pdiag[1];
9326  beta = ae_c_d_div(1.0, tmp_c);
9327  alpha.x = -beta.x;
9328  alpha.y = -beta.y;
9329  _ialglib_vcopy_dcomplex(i, abuf+2*i, alglib_c_block, tmpbuf, 1, "No conj");
9330  cmv(m, i, xbuf, tmpbuf, NULL, xbuf+2*i, alglib_c_block, alpha, beta);
9331  }
9332  _ialglib_mcopyunblock_complex(m, n, xbuf, 0, _x, _x_stride);
9333  }
9334  else
9335  {
9336  for(i=n-1,pdiag=abuf+2*((n-1)*alglib_c_block+(n-1)); i>=0; i--,pdiag-=2*(alglib_c_block+1))
9337  {
9338  ae_complex tmp_c;
9339  ae_complex beta;
9340  ae_complex alpha;
9341  tmp_c.x = pdiag[0];
9342  tmp_c.y = pdiag[1];
9343  beta = ae_c_d_div(1.0, tmp_c);
9344  alpha.x = -beta.x;
9345  alpha.y = -beta.y;
9346  _ialglib_vcopy_dcomplex(n-1-i, pdiag+2*alglib_c_block, alglib_c_block, tmpbuf, 1, "No conj");
9347  cmv(m, n-1-i, xbuf+2*(i+1), tmpbuf, NULL, xbuf+2*i, alglib_c_block, alpha, beta);
9348  }
9349  _ialglib_mcopyunblock_complex(m, n, xbuf, 0, _x, _x_stride);
9350  }
9351  return ae_true;
9352 }
9353 
9354 
9355 /********************************************************************
9356 real TRSM kernel
9357 ********************************************************************/
9359  ae_int_t n,
9360  double *_a,
9361  ae_int_t _a_stride,
9362  ae_bool isupper,
9363  ae_bool isunit,
9364  ae_int_t optype,
9365  double *_x,
9366  ae_int_t _x_stride)
9367 {
9368  /*
9369  * local buffers
9370  */
9371  double *pdiag;
9372  ae_int_t i;
9375  double _loc_tmpbuf[alglib_r_block+alglib_simd_alignment];
9376  double * const abuf = (double * const) ae_align(_loc_abuf, alglib_simd_alignment);
9377  double * const xbuf = (double * const) ae_align(_loc_xbuf, alglib_simd_alignment);
9378  double * const tmpbuf = (double * const) ae_align(_loc_tmpbuf,alglib_simd_alignment);
9379  ae_bool uppera;
9380  void (*rmv)(ae_int_t, ae_int_t, const double *, const double *, double *, ae_int_t, double, double) = &_ialglib_rmv;
9381  void (*mcopyblock)(ae_int_t, ae_int_t, const double *, ae_int_t, ae_int_t, double *) = &_ialglib_mcopyblock;
9382 
9383  if( m>alglib_r_block || n>alglib_r_block )
9384  return ae_false;
9385 
9386  /*
9387  * Check for SSE2 support
9388  */
9389 #ifdef AE_HAS_SSE2_INTRINSICS
9390  if( ae_cpuid() & CPU_SSE2 )
9391  {
9392  rmv = &_ialglib_rmv_sse2;
9393  mcopyblock = &_ialglib_mcopyblock_sse2;
9394  }
9395 #endif
9396 
9397  /*
9398  * Prepare
9399  */
9400  mcopyblock(n, n, _a, optype, _a_stride, abuf);
9401  mcopyblock(m, n, _x, 0, _x_stride, xbuf);
9402  if( isunit )
9403  for(i=0,pdiag=abuf; i<n; i++,pdiag+=alglib_r_block+1)
9404  *pdiag = 1.0;
9405  if( optype==0 )
9406  uppera = isupper;
9407  else
9408  uppera = !isupper;
9409 
9410  /*
9411  * Solve Y*A^-1=X where A is upper or lower triangular
9412  */
9413  if( uppera )
9414  {
9415  for(i=0,pdiag=abuf; i<n; i++,pdiag+=alglib_r_block+1)
9416  {
9417  double beta = 1.0/(*pdiag);
9418  double alpha = -beta;
9419  _ialglib_vcopy(i, abuf+i, alglib_r_block, tmpbuf, 1);
9420  rmv(m, i, xbuf, tmpbuf, xbuf+i, alglib_r_block, alpha, beta);
9421  }
9422  _ialglib_mcopyunblock(m, n, xbuf, 0, _x, _x_stride);
9423  }
9424  else
9425  {
9426  for(i=n-1,pdiag=abuf+(n-1)*alglib_r_block+(n-1); i>=0; i--,pdiag-=alglib_r_block+1)
9427  {
9428  double beta = 1.0/(*pdiag);
9429  double alpha = -beta;
9430  _ialglib_vcopy(n-1-i, pdiag+alglib_r_block, alglib_r_block, tmpbuf+i+1, 1);
9431  rmv(m, n-1-i, xbuf+i+1, tmpbuf+i+1, xbuf+i, alglib_r_block, alpha, beta);
9432  }
9433  _ialglib_mcopyunblock(m, n, xbuf, 0, _x, _x_stride);
9434  }
9435  return ae_true;
9436 }
9437 
9438 
9439 /********************************************************************
9440 complex TRSM kernel
9441 ********************************************************************/
9443  ae_int_t n,
9444  ae_complex *_a,
9445  ae_int_t _a_stride,
9446  ae_bool isupper,
9447  ae_bool isunit,
9448  ae_int_t optype,
9449  ae_complex *_x,
9450  ae_int_t _x_stride)
9451 {
9452  /*
9453  * local buffers
9454  */
9455  double *pdiag, *arow;
9456  ae_int_t i;
9459  double _loc_tmpbuf[2*alglib_c_block+alglib_simd_alignment];
9460  double * const abuf = (double * const) ae_align(_loc_abuf, alglib_simd_alignment);
9461  double * const xbuf = (double * const) ae_align(_loc_xbuf, alglib_simd_alignment);
9462  double * const tmpbuf = (double * const) ae_align(_loc_tmpbuf,alglib_simd_alignment);
9463  ae_bool uppera;
9464  void (*cmv)(ae_int_t, ae_int_t, const double *, const double *, ae_complex *, double *, ae_int_t, ae_complex, ae_complex) = &_ialglib_cmv;
9465 
9466  if( m>alglib_c_block || n>alglib_c_block )
9467  return ae_false;
9468 
9469  /*
9470  * Check for SSE2 support
9471  */
9472 #ifdef AE_HAS_SSE2_INTRINSICS
9473  if( ae_cpuid() & CPU_SSE2 )
9474  {
9475  cmv = &_ialglib_cmv_sse2;
9476  }
9477 #endif
9478 
9479  /*
9480  * Prepare
9481  * Transpose X (so we may use mv, which calculates A*x, but not x*A)
9482  */
9483  _ialglib_mcopyblock_complex(m, m, _a, optype, _a_stride, abuf);
9484  _ialglib_mcopyblock_complex(m, n, _x, 1, _x_stride, xbuf);
9485  if( isunit )
9486  for(i=0,pdiag=abuf; i<m; i++,pdiag+=2*(alglib_c_block+1))
9487  {
9488  pdiag[0] = 1.0;
9489  pdiag[1] = 0.0;
9490  }
9491  if( optype==0 )
9492  uppera = isupper;
9493  else
9494  uppera = !isupper;
9495 
9496  /*
9497  * Solve A^-1*Y^T=X^T where A is upper or lower triangular
9498  */
9499  if( uppera )
9500  {
9501  for(i=m-1,pdiag=abuf+2*((m-1)*alglib_c_block+(m-1)); i>=0; i--,pdiag-=2*(alglib_c_block+1))
9502  {
9503  ae_complex tmp_c;
9504  ae_complex beta;
9505  ae_complex alpha;
9506  tmp_c.x = pdiag[0];
9507  tmp_c.y = pdiag[1];
9508  beta = ae_c_d_div(1.0, tmp_c);
9509  alpha.x = -beta.x;
9510  alpha.y = -beta.y;
9511  _ialglib_vcopy_dcomplex(m-1-i, pdiag+2, 1, tmpbuf, 1, "No conj");
9512  cmv(n, m-1-i, xbuf+2*(i+1), tmpbuf, NULL, xbuf+2*i, alglib_c_block, alpha, beta);
9513  }
9514  _ialglib_mcopyunblock_complex(m, n, xbuf, 1, _x, _x_stride);
9515  }
9516  else
9517  { for(i=0,pdiag=abuf,arow=abuf; i<m; i++,pdiag+=2*(alglib_c_block+1),arow+=2*alglib_c_block)
9518  {
9519  ae_complex tmp_c;
9520  ae_complex beta;
9521  ae_complex alpha;
9522  tmp_c.x = pdiag[0];
9523  tmp_c.y = pdiag[1];
9524  beta = ae_c_d_div(1.0, tmp_c);
9525  alpha.x = -beta.x;
9526  alpha.y = -beta.y;
9527  _ialglib_vcopy_dcomplex(i, arow, 1, tmpbuf, 1, "No conj");
9528  cmv(n, i, xbuf, tmpbuf, NULL, xbuf+2*i, alglib_c_block, alpha, beta);
9529  }
9530  _ialglib_mcopyunblock_complex(m, n, xbuf, 1, _x, _x_stride);
9531  }
9532  return ae_true;
9533 }
9534 
9535 
9536 /********************************************************************
9537 real TRSM kernel
9538 ********************************************************************/
9540  ae_int_t n,
9541  double *_a,
9542  ae_int_t _a_stride,
9543  ae_bool isupper,
9544  ae_bool isunit,
9545  ae_int_t optype,
9546  double *_x,
9547  ae_int_t _x_stride)
9548 {
9549  /*
9550  * local buffers
9551  */
9552  double *pdiag, *arow;
9553  ae_int_t i;
9556  double _loc_tmpbuf[alglib_r_block+alglib_simd_alignment];
9557  double * const abuf = (double * const) ae_align(_loc_abuf, alglib_simd_alignment);
9558  double * const xbuf = (double * const) ae_align(_loc_xbuf, alglib_simd_alignment);
9559  double * const tmpbuf = (double * const) ae_align(_loc_tmpbuf,alglib_simd_alignment);
9560  ae_bool uppera;
9561  void (*rmv)(ae_int_t, ae_int_t, const double *, const double *, double *, ae_int_t, double, double) = &_ialglib_rmv;
9562  void (*mcopyblock)(ae_int_t, ae_int_t, const double *, ae_int_t, ae_int_t, double *) = &_ialglib_mcopyblock;
9563 
9564  if( m>alglib_r_block || n>alglib_r_block )
9565  return ae_false;
9566 
9567  /*
9568  * Check for SSE2 support
9569  */
9570 #ifdef AE_HAS_SSE2_INTRINSICS
9571  if( ae_cpuid() & CPU_SSE2 )
9572  {
9573  rmv = &_ialglib_rmv_sse2;
9574  mcopyblock = &_ialglib_mcopyblock_sse2;
9575  }
9576 #endif
9577 
9578  /*
9579  * Prepare
9580  * Transpose X (so we may use mv, which calculates A*x, but not x*A)
9581  */
9582  mcopyblock(m, m, _a, optype, _a_stride, abuf);
9583  mcopyblock(m, n, _x, 1, _x_stride, xbuf);
9584  if( isunit )
9585  for(i=0,pdiag=abuf; i<m; i++,pdiag+=alglib_r_block+1)
9586  *pdiag = 1.0;
9587  if( optype==0 )
9588  uppera = isupper;
9589  else
9590  uppera = !isupper;
9591 
9592  /*
9593  * Solve A^-1*Y^T=X^T where A is upper or lower triangular
9594  */
9595  if( uppera )
9596  {
9597  for(i=m-1,pdiag=abuf+(m-1)*alglib_r_block+(m-1); i>=0; i--,pdiag-=alglib_r_block+1)
9598  {
9599  double beta = 1.0/(*pdiag);
9600  double alpha = -beta;
9601  _ialglib_vcopy(m-1-i, pdiag+1, 1, tmpbuf+i+1, 1);
9602  rmv(n, m-1-i, xbuf+i+1, tmpbuf+i+1, xbuf+i, alglib_r_block, alpha, beta);
9603  }
9604  _ialglib_mcopyunblock(m, n, xbuf, 1, _x, _x_stride);
9605  }
9606  else
9607  { for(i=0,pdiag=abuf,arow=abuf; i<m; i++,pdiag+=alglib_r_block+1,arow+=alglib_r_block)
9608  {
9609  double beta = 1.0/(*pdiag);
9610  double alpha = -beta;
9611  _ialglib_vcopy(i, arow, 1, tmpbuf, 1);
9612  rmv(n, i, xbuf, tmpbuf, xbuf+i, alglib_r_block, alpha, beta);
9613  }
9614  _ialglib_mcopyunblock(m, n, xbuf, 1, _x, _x_stride);
9615  }
9616  return ae_true;
9617 }
9618 
9619 
9620 /********************************************************************
9621 complex SYRK kernel
9622 ********************************************************************/
9624  ae_int_t k,
9625  double alpha,
9626  ae_complex *_a,
9627  ae_int_t _a_stride,
9628  ae_int_t optypea,
9629  double beta,
9630  ae_complex *_c,
9631  ae_int_t _c_stride,
9632  ae_bool isupper)
9633 {
9634  /*
9635  * local buffers
9636  */
9637  double *arow, *crow;
9638  ae_complex c_alpha, c_beta;
9639  ae_int_t i;
9642  double _loc_tmpbuf[2*alglib_c_block+alglib_simd_alignment];
9643  double * const abuf = (double * const) ae_align(_loc_abuf, alglib_simd_alignment);
9644  double * const cbuf = (double * const) ae_align(_loc_cbuf, alglib_simd_alignment);
9645  double * const tmpbuf = (double * const) ae_align(_loc_tmpbuf,alglib_simd_alignment);
9646 
9647  if( n>alglib_c_block || k>alglib_c_block )
9648  return ae_false;
9649  if( n==0 )
9650  return ae_true;
9651 
9652  /*
9653  * copy A and C, task is transformed to "A*A^H"-form.
9654  * if beta==0, then C is filled by zeros (and not referenced)
9655  *
9656  * alpha==0 or k==0 are correctly processed (A is not referenced)
9657  */
9658  c_alpha.x = alpha;
9659  c_alpha.y = 0;
9660  c_beta.x = beta;
9661  c_beta.y = 0;
9662  if( alpha==0 )
9663  k = 0;
9664  if( k>0 )
9665  {
9666  if( optypea==0 )
9667  _ialglib_mcopyblock_complex(n, k, _a, 3, _a_stride, abuf);
9668  else
9669  _ialglib_mcopyblock_complex(k, n, _a, 1, _a_stride, abuf);
9670  }
9671  _ialglib_mcopyblock_complex(n, n, _c, 0, _c_stride, cbuf);
9672  if( beta==0 )
9673  {
9674  for(i=0,crow=cbuf; i<n; i++,crow+=2*alglib_c_block)
9675  if( isupper )
9676  _ialglib_vzero(2*(n-i), crow+2*i, 1);
9677  else
9678  _ialglib_vzero(2*(i+1), crow, 1);
9679  }
9680 
9681 
9682  /*
9683  * update C
9684  */
9685  if( isupper )
9686  {
9687  for(i=0,arow=abuf,crow=cbuf; i<n; i++,arow+=2*alglib_c_block,crow+=2*alglib_c_block)
9688  {
9689  _ialglib_vcopy_dcomplex(k, arow, 1, tmpbuf, 1, "Conj");
9690  _ialglib_cmv(n-i, k, arow, tmpbuf, NULL, crow+2*i, 1, c_alpha, c_beta);
9691  }
9692  }
9693  else
9694  {
9695  for(i=0,arow=abuf,crow=cbuf; i<n; i++,arow+=2*alglib_c_block,crow+=2*alglib_c_block)
9696  {
9697  _ialglib_vcopy_dcomplex(k, arow, 1, tmpbuf, 1, "Conj");
9698  _ialglib_cmv(i+1, k, abuf, tmpbuf, NULL, crow, 1, c_alpha, c_beta);
9699  }
9700  }
9701 
9702  /*
9703  * copy back
9704  */
9705  _ialglib_mcopyunblock_complex(n, n, cbuf, 0, _c, _c_stride);
9706 
9707  return ae_true;
9708 }
9709 
9710 
9711 /********************************************************************
9712 real SYRK kernel
9713 ********************************************************************/
9715  ae_int_t k,
9716  double alpha,
9717  double *_a,
9718  ae_int_t _a_stride,
9719  ae_int_t optypea,
9720  double beta,
9721  double *_c,
9722  ae_int_t _c_stride,
9723  ae_bool isupper)
9724 {
9725  /*
9726  * local buffers
9727  */
9728  double *arow, *crow;
9729  ae_int_t i;
9732  double * const abuf = (double * const) ae_align(_loc_abuf, alglib_simd_alignment);
9733  double * const cbuf = (double * const) ae_align(_loc_cbuf, alglib_simd_alignment);
9734 
9735  if( n>alglib_r_block || k>alglib_r_block )
9736  return ae_false;
9737  if( n==0 )
9738  return ae_true;
9739 
9740  /*
9741  * copy A and C, task is transformed to "A*A^T"-form.
9742  * if beta==0, then C is filled by zeros (and not referenced)
9743  *
9744  * alpha==0 or k==0 are correctly processed (A is not referenced)
9745  */
9746  if( alpha==0 )
9747  k = 0;
9748  if( k>0 )
9749  {
9750  if( optypea==0 )
9751  _ialglib_mcopyblock(n, k, _a, 0, _a_stride, abuf);
9752  else
9753  _ialglib_mcopyblock(k, n, _a, 1, _a_stride, abuf);
9754  }
9755  _ialglib_mcopyblock(n, n, _c, 0, _c_stride, cbuf);
9756  if( beta==0 )
9757  {
9758  for(i=0,crow=cbuf; i<n; i++,crow+=alglib_r_block)
9759  if( isupper )
9760  _ialglib_vzero(n-i, crow+i, 1);
9761  else
9762  _ialglib_vzero(i+1, crow, 1);
9763  }
9764 
9765 
9766  /*
9767  * update C
9768  */
9769  if( isupper )
9770  {
9771  for(i=0,arow=abuf,crow=cbuf; i<n; i++,arow+=alglib_r_block,crow+=alglib_r_block)
9772  {
9773  _ialglib_rmv(n-i, k, arow, arow, crow+i, 1, alpha, beta);
9774  }
9775  }
9776  else
9777  {
9778  for(i=0,arow=abuf,crow=cbuf; i<n; i++,arow+=alglib_r_block,crow+=alglib_r_block)
9779  {
9780  _ialglib_rmv(i+1, k, abuf, arow, crow, 1, alpha, beta);
9781  }
9782  }
9783 
9784  /*
9785  * copy back
9786  */
9787  _ialglib_mcopyunblock(n, n, cbuf, 0, _c, _c_stride);
9788 
9789  return ae_true;
9790 }
9791 
9792 
9793 /********************************************************************
9794 complex rank-1 kernel
9795 ********************************************************************/
9797  ae_int_t n,
9798  ae_complex *_a,
9799  ae_int_t _a_stride,
9800  ae_complex *_u,
9801  ae_complex *_v)
9802 {
9803  ae_complex *arow, *pu, *pv, *vtmp, *dst;
9804  ae_int_t n2 = n/2;
9805  ae_int_t i, j;
9806 
9807  /*
9808  * update pairs of rows
9809  */
9810  arow = _a;
9811  pu = _u;
9812  vtmp = _v;
9813  for(i=0; i<m; i++, arow+=_a_stride, pu++)
9814  {
9815  /*
9816  * update by two
9817  */
9818  for(j=0,pv=vtmp, dst=arow; j<n2; j++, dst+=2, pv+=2)
9819  {
9820  double ux = pu[0].x;
9821  double uy = pu[0].y;
9822  double v0x = pv[0].x;
9823  double v0y = pv[0].y;
9824  double v1x = pv[1].x;
9825  double v1y = pv[1].y;
9826  dst[0].x += ux*v0x-uy*v0y;
9827  dst[0].y += ux*v0y+uy*v0x;
9828  dst[1].x += ux*v1x-uy*v1y;
9829  dst[1].y += ux*v1y+uy*v1x;
9830  }
9831 
9832  /*
9833  * final update
9834  */
9835  if( n%2!=0 )
9836  {
9837  double ux = pu[0].x;
9838  double uy = pu[0].y;
9839  double vx = pv[0].x;
9840  double vy = pv[0].y;
9841  dst[0].x += ux*vx-uy*vy;
9842  dst[0].y += ux*vy+uy*vx;
9843  }
9844  }
9845  return ae_true;
9846 }
9847 
9848 
9849 /********************************************************************
9850 real rank-1 kernel
9851 ********************************************************************/
9853  ae_int_t n,
9854  double *_a,
9855  ae_int_t _a_stride,
9856  double *_u,
9857  double *_v)
9858 {
9859  double *arow0, *arow1, *pu, *pv, *vtmp, *dst0, *dst1;
9860  ae_int_t m2 = m/2;
9861  ae_int_t n2 = n/2;
9862  ae_int_t stride = _a_stride;
9863  ae_int_t stride2 = 2*_a_stride;
9864  ae_int_t i, j;
9865 
9866  /*
9867  * update pairs of rows
9868  */
9869  arow0 = _a;
9870  arow1 = arow0+stride;
9871  pu = _u;
9872  vtmp = _v;
9873  for(i=0; i<m2; i++,arow0+=stride2,arow1+=stride2,pu+=2)
9874  {
9875  /*
9876  * update by two
9877  */
9878  for(j=0,pv=vtmp, dst0=arow0, dst1=arow1; j<n2; j++, dst0+=2, dst1+=2, pv+=2)
9879  {
9880  dst0[0] += pu[0]*pv[0];
9881  dst0[1] += pu[0]*pv[1];
9882  dst1[0] += pu[1]*pv[0];
9883  dst1[1] += pu[1]*pv[1];
9884  }
9885 
9886  /*
9887  * final update
9888  */
9889  if( n%2!=0 )
9890  {
9891  dst0[0] += pu[0]*pv[0];
9892  dst1[0] += pu[1]*pv[0];
9893  }
9894  }
9895 
9896  /*
9897  * update last row
9898  */
9899  if( m%2!=0 )
9900  {
9901  /*
9902  * update by two
9903  */
9904  for(j=0,pv=vtmp, dst0=arow0; j<n2; j++, dst0+=2, pv+=2)
9905  {
9906  dst0[0] += pu[0]*pv[0];
9907  dst0[1] += pu[0]*pv[1];
9908  }
9909 
9910  /*
9911  * final update
9912  */
9913  if( n%2!=0 )
9914  dst0[0] += pu[0]*pv[0];
9915  }
9916  return ae_true;
9917 }
9918 
9919 
9920 /********************************************************************
9921 Interface functions for efficient kernels
9922 ********************************************************************/
9924  ae_int_t n,
9925  ae_int_t k,
9926  double alpha,
9927  ae_matrix *_a,
9928  ae_int_t ia,
9929  ae_int_t ja,
9930  ae_int_t optypea,
9931  ae_matrix *_b,
9932  ae_int_t ib,
9933  ae_int_t jb,
9934  ae_int_t optypeb,
9935  double beta,
9936  ae_matrix *_c,
9937  ae_int_t ic,
9938  ae_int_t jc)
9939 {
9940  return _ialglib_rmatrixgemm(m, n, k, alpha, _a->ptr.pp_double[ia]+ja, _a->stride, optypea, _b->ptr.pp_double[ib]+jb, _b->stride, optypeb, beta, _c->ptr.pp_double[ic]+jc, _c->stride);
9941 }
9942 
9944  ae_int_t n,
9945  ae_int_t k,
9946  ae_complex alpha,
9947  ae_matrix *_a,
9948  ae_int_t ia,
9949  ae_int_t ja,
9950  ae_int_t optypea,
9951  ae_matrix *_b,
9952  ae_int_t ib,
9953  ae_int_t jb,
9954  ae_int_t optypeb,
9955  ae_complex beta,
9956  ae_matrix *_c,
9957  ae_int_t ic,
9958  ae_int_t jc)
9959 {
9960  return _ialglib_cmatrixgemm(m, n, k, alpha, _a->ptr.pp_complex[ia]+ja, _a->stride, optypea, _b->ptr.pp_complex[ib]+jb, _b->stride, optypeb, beta, _c->ptr.pp_complex[ic]+jc, _c->stride);
9961 }
9962 
9964  ae_int_t n,
9965  ae_matrix *a,
9966  ae_int_t i1,
9967  ae_int_t j1,
9968  ae_bool isupper,
9969  ae_bool isunit,
9970  ae_int_t optype,
9971  ae_matrix *x,
9972  ae_int_t i2,
9973  ae_int_t j2)
9974 {
9975  return _ialglib_cmatrixrighttrsm(m, n, &a->ptr.pp_complex[i1][j1], a->stride, isupper, isunit, optype, &x->ptr.pp_complex[i2][j2], x->stride);
9976 }
9977 
9979  ae_int_t n,
9980  ae_matrix *a,
9981  ae_int_t i1,
9982  ae_int_t j1,
9983  ae_bool isupper,
9984  ae_bool isunit,
9985  ae_int_t optype,
9986  ae_matrix *x,
9987  ae_int_t i2,
9988  ae_int_t j2)
9989 {
9990  return _ialglib_rmatrixrighttrsm(m, n, &a->ptr.pp_double[i1][j1], a->stride, isupper, isunit, optype, &x->ptr.pp_double[i2][j2], x->stride);
9991 }
9992 
9994  ae_int_t n,
9995  ae_matrix *a,
9996  ae_int_t i1,
9997  ae_int_t j1,
9998  ae_bool isupper,
9999  ae_bool isunit,
10000  ae_int_t optype,
10001  ae_matrix *x,
10002  ae_int_t i2,
10003  ae_int_t j2)
10004 {
10005  return _ialglib_cmatrixlefttrsm(m, n, &a->ptr.pp_complex[i1][j1], a->stride, isupper, isunit, optype, &x->ptr.pp_complex[i2][j2], x->stride);
10006 }
10007 
10009  ae_int_t n,
10010  ae_matrix *a,
10011  ae_int_t i1,
10012  ae_int_t j1,
10013  ae_bool isupper,
10014  ae_bool isunit,
10015  ae_int_t optype,
10016  ae_matrix *x,
10017  ae_int_t i2,
10018  ae_int_t j2)
10019 {
10020  return _ialglib_rmatrixlefttrsm(m, n, &a->ptr.pp_double[i1][j1], a->stride, isupper, isunit, optype, &x->ptr.pp_double[i2][j2], x->stride);
10021 }
10022 
10024  ae_int_t k,
10025  double alpha,
10026  ae_matrix *a,
10027  ae_int_t ia,
10028  ae_int_t ja,
10029  ae_int_t optypea,
10030  double beta,
10031  ae_matrix *c,
10032  ae_int_t ic,
10033  ae_int_t jc,
10034  ae_bool isupper)
10035 {
10036  return _ialglib_cmatrixsyrk(n, k, alpha, &a->ptr.pp_complex[ia][ja], a->stride, optypea, beta, &c->ptr.pp_complex[ic][jc], c->stride, isupper);
10037 }
10038 
10040  ae_int_t k,
10041  double alpha,
10042  ae_matrix *a,
10043  ae_int_t ia,
10044  ae_int_t ja,
10045  ae_int_t optypea,
10046  double beta,
10047  ae_matrix *c,
10048  ae_int_t ic,
10049  ae_int_t jc,
10050  ae_bool isupper)
10051 {
10052  return _ialglib_rmatrixsyrk(n, k, alpha, &a->ptr.pp_double[ia][ja], a->stride, optypea, beta, &c->ptr.pp_double[ic][jc], c->stride, isupper);
10053 }
10054 
10056  ae_int_t n,
10057  ae_matrix *a,
10058  ae_int_t ia,
10059  ae_int_t ja,
10060  ae_vector *u,
10061  ae_int_t uoffs,
10062  ae_vector *v,
10063  ae_int_t voffs)
10064 {
10065  return _ialglib_cmatrixrank1(m, n, &a->ptr.pp_complex[ia][ja], a->stride, &u->ptr.p_complex[uoffs], &v->ptr.p_complex[voffs]);
10066 }
10067 
10069  ae_int_t n,
10070  ae_matrix *a,
10071  ae_int_t ia,
10072  ae_int_t ja,
10073  ae_vector *u,
10074  ae_int_t uoffs,
10075  ae_vector *v,
10076  ae_int_t voffs)
10077 {
10078  return _ialglib_rmatrixrank1(m, n, &a->ptr.pp_double[ia][ja], a->stride, &u->ptr.p_double[uoffs], &v->ptr.p_double[voffs]);
10079 }
10080 
10081 
10082 
10083 
10084 /********************************************************************
10085 This function reads rectangular matrix A given by two column pointers
10086 col0 and col1 and stride src_stride and moves it into contiguous row-
10087 by-row storage given by dst.
10088 
10089 It can handle following special cases:
10090 * col1==NULL in this case second column of A is filled by zeros
10091 ********************************************************************/
10093  double *col0,
10094  double *col1,
10095  ae_int_t n,
10096  ae_int_t src_stride,
10097  double *dst)
10098 {
10099  ae_int_t n2, j, stride2;
10100 
10101  /*
10102  * handle special case
10103  */
10104  if( col1==NULL )
10105  {
10106  for(j=0; j<n; j++)
10107  {
10108  dst[0] = *col0;
10109  dst[1] = 0.0;
10110  col0 += src_stride;
10111  dst += 2;
10112  }
10113  return;
10114  }
10115 
10116  /*
10117  * handle general case
10118  */
10119  n2 = n/2;
10120  stride2 = src_stride*2;
10121  for(j=0; j<n2; j++)
10122  {
10123  dst[0] = *col0;
10124  dst[1] = *col1;
10125  dst[2] = col0[src_stride];
10126  dst[3] = col1[src_stride];
10127  col0 += stride2;
10128  col1 += stride2;
10129  dst += 4;
10130  }
10131  if( n%2 )
10132  {
10133  dst[0] = *col0;
10134  dst[1] = *col1;
10135  }
10136 }
10137 
10138 /*************************************************************************
10139 This function reads rectangular matrix A given by two column pointers col0
10140 and col1 and stride src_stride and moves it into contiguous row-by-row
10141 storage given by dst.
10142 
10143 dst must be aligned, col0 and col1 may be non-aligned.
10144 
10145 It can handle following special cases:
10146 * col1==NULL in this case second column of A is filled by zeros
10147 * src_stride==1 efficient SSE-based code is used
10148 * col1-col0==1 efficient SSE-based code is used
10149 
10150 This function supports SSE2; it can be used when:
10151 1. AE_HAS_SSE2_INTRINSICS was defined (checked at compile-time)
10152 2. ae_cpuid() result contains CPU_SSE2 (checked at run-time)
10153 
10154 If you want to know whether it is safe to call it, you should check
10155 results of ae_cpuid(). If CPU_SSE2 bit is set, this function is callable
10156 and will do its work.
10157 *************************************************************************/
10158 #if defined(AE_HAS_SSE2_INTRINSICS)
10159 void _ialglib_pack_n2_sse2(
10160  double *col0,
10161  double *col1,
10162  ae_int_t n,
10163  ae_int_t src_stride,
10164  double *dst)
10165 {
10166  ae_int_t n2, j, stride2;
10167 
10168  /*
10169  * handle special case: col1==NULL
10170  */
10171  if( col1==NULL )
10172  {
10173  for(j=0; j<n; j++)
10174  {
10175  dst[0] = *col0;
10176  dst[1] = 0.0;
10177  col0 += src_stride;
10178  dst += 2;
10179  }
10180  return;
10181  }
10182 
10183  /*
10184  * handle unit stride
10185  */
10186  if( src_stride==1 )
10187  {
10188  __m128d v0, v1, r0, r1;
10189  n2 = n/2;
10190  for(j=0; j<n2; j++)
10191  {
10192  v0 = _mm_loadu_pd(col0);
10193  col0 += 2;
10194  v1 = _mm_loadu_pd(col1);
10195  col1 += 2;
10196  _mm_store_pd(dst, _mm_unpacklo_pd(v0,v1));
10197  _mm_store_pd(dst+2,_mm_unpackhi_pd(v0,v1));
10198  dst += 4;
10199  }
10200  if( n%2 )
10201  {
10202  dst[0] = *col0;
10203  dst[1] = *col1;
10204  }
10205  return;
10206  }
10207 
10208  /*
10209  * handle col1-col0==1
10210  */
10211  if( col1-col0==1 )
10212  {
10213  __m128d v0, v1;
10214  n2 = n/2;
10215  stride2 = 2*src_stride;
10216  for(j=0; j<n2; j++)
10217  {
10218  v0 = _mm_loadu_pd(col0);
10219  v1 = _mm_loadu_pd(col0+src_stride);
10220  _mm_store_pd(dst, v0);
10221  _mm_store_pd(dst+2,v1);
10222  col0 += stride2;
10223  dst += 4;
10224  }
10225  if( n%2 )
10226  {
10227  dst[0] = col0[0];
10228  dst[1] = col0[1];
10229  }
10230  return;
10231  }
10232 
10233  /*
10234  * handle general case
10235  */
10236  n2 = n/2;
10237  stride2 = src_stride*2;
10238  for(j=0; j<n2; j++)
10239  {
10240  dst[0] = *col0;
10241  dst[1] = *col1;
10242  dst[2] = col0[src_stride];
10243  dst[3] = col1[src_stride];
10244  col0 += stride2;
10245  col1 += stride2;
10246  dst += 4;
10247  }
10248  if( n%2 )
10249  {
10250  dst[0] = *col0;
10251  dst[1] = *col1;
10252  }
10253 }
10254 #endif
10255 
10256 
10257 /********************************************************************
10258 This function calculates R := alpha*A'*B+beta*R where A and B are Kx2
10259 matrices stored in contiguous row-by-row storage, R is 2x2 matrix
10260 stored in non-contiguous row-by-row storage.
10261 
10262 A and B must be aligned; R may be non-aligned.
10263 
10264 If beta is zero, contents of R is ignored (not multiplied by zero -
10265 just ignored).
10266 
10267 However, when alpha is zero, we still calculate A'*B, which is
10268 multiplied by zero afterwards.
10269 
10270 Function accepts additional parameter store_mode:
10271 * if 0, full R is stored
10272 * if 1, only first row of R is stored
10273 * if 2, only first column of R is stored
10274 * if 3, only top left element of R is stored
10275 ********************************************************************/
10276 void _ialglib_mm22(double alpha, const double *a, const double *b, ae_int_t k, double beta, double *r, ae_int_t stride, ae_int_t store_mode)
10277 {
10278  double v00, v01, v10, v11;
10279  ae_int_t t;
10280  v00 = 0.0;
10281  v01 = 0.0;
10282  v10 = 0.0;
10283  v11 = 0.0;
10284  for(t=0; t<k; t++)
10285  {
10286  v00 += a[0]*b[0];
10287  v01 += a[0]*b[1];
10288  v10 += a[1]*b[0];
10289  v11 += a[1]*b[1];
10290  a+=2;
10291  b+=2;
10292  }
10293  if( store_mode==0 )
10294  {
10295  if( beta==0 )
10296  {
10297  r[0] = alpha*v00;
10298  r[1] = alpha*v01;
10299  r[stride+0] = alpha*v10;
10300  r[stride+1] = alpha*v11;
10301  }
10302  else
10303  {
10304  r[0] = beta*r[0] + alpha*v00;
10305  r[1] = beta*r[1] + alpha*v01;
10306  r[stride+0] = beta*r[stride+0] + alpha*v10;
10307  r[stride+1] = beta*r[stride+1] + alpha*v11;
10308  }
10309  return;
10310  }
10311  if( store_mode==1 )
10312  {
10313  if( beta==0 )
10314  {
10315  r[0] = alpha*v00;
10316  r[1] = alpha*v01;
10317  }
10318  else
10319  {
10320  r[0] = beta*r[0] + alpha*v00;
10321  r[1] = beta*r[1] + alpha*v01;
10322  }
10323  return;
10324  }
10325  if( store_mode==2 )
10326  {
10327  if( beta==0 )
10328  {
10329  r[0] =alpha*v00;
10330  r[stride+0] = alpha*v10;
10331  }
10332  else
10333  {
10334  r[0] = beta*r[0] + alpha*v00;
10335  r[stride+0] = beta*r[stride+0] + alpha*v10;
10336  }
10337  return;
10338  }
10339  if( store_mode==3 )
10340  {
10341  if( beta==0 )
10342  {
10343  r[0] = alpha*v00;
10344  }
10345  else
10346  {
10347  r[0] = beta*r[0] + alpha*v00;
10348  }
10349  return;
10350  }
10351 }
10352 
10353 
10354 /********************************************************************
10355 This function calculates R := alpha*A'*B+beta*R where A and B are Kx2
10356 matrices stored in contiguous row-by-row storage, R is 2x2 matrix
10357 stored in non-contiguous row-by-row storage.
10358 
10359 A and B must be aligned; R may be non-aligned.
10360 
10361 If beta is zero, contents of R is ignored (not multiplied by zero -
10362 just ignored).
10363 
10364 However, when alpha is zero, we still calculate A'*B, which is
10365 multiplied by zero afterwards.
10366 
10367 Function accepts additional parameter store_mode:
10368 * if 0, full R is stored
10369 * if 1, only first row of R is stored
10370 * if 2, only first column of R is stored
10371 * if 3, only top left element of R is stored
10372 
10373 This function supports SSE2; it can be used when:
10374 1. AE_HAS_SSE2_INTRINSICS was defined (checked at compile-time)
10375 2. ae_cpuid() result contains CPU_SSE2 (checked at run-time)
10376 
10377 If (1) is failed, this function will still be defined and callable, but it
10378 will do nothing. If (2) is failed , call to this function will probably
10379 crash your system.
10380 
10381 If you want to know whether it is safe to call it, you should check
10382 results of ae_cpuid(). If CPU_SSE2 bit is set, this function is callable
10383 and will do its work.
10384 ********************************************************************/
10385 #if defined(AE_HAS_SSE2_INTRINSICS)
10386 void _ialglib_mm22_sse2(double alpha, const double *a, const double *b, ae_int_t k, double beta, double *r, ae_int_t stride, ae_int_t store_mode)
10387 {
10388  /*
10389  * We calculate product of two Kx2 matrices (result is 2x2).
10390  * VA and VB store result as follows:
10391  *
10392  * [ VD[0] VE[0] ]
10393  * A'*B = [ ]
10394  * [ VE[1] VD[1] ]
10395  *
10396  */
10397  __m128d va, vb, vd, ve, vt, vt0, vt1, r0, r1, valpha, vbeta;
10398  ae_int_t t, k2, k3;
10399 
10400  /*
10401  * calculate product
10402  */
10403  k2 = k/2;
10404  vd = _mm_setzero_pd();
10405  ve = _mm_setzero_pd();
10406  for(t=0; t<k2; t++)
10407  {
10408  vb = _mm_load_pd(b);
10409  va = _mm_load_pd(a);
10410  vt = vb;
10411  vb = _mm_mul_pd(va,vb);
10412  vt = _mm_shuffle_pd(vt, vt, 1);
10413  vd = _mm_add_pd(vb,vd);
10414  vt = _mm_mul_pd(va,vt);
10415  vb = _mm_load_pd(b+2);
10416  ve = _mm_add_pd(vt,ve);
10417  va = _mm_load_pd(a+2);
10418  vt = vb;
10419  vb = _mm_mul_pd(va,vb);
10420  vt = _mm_shuffle_pd(vt, vt, 1);
10421  vd = _mm_add_pd(vb,vd);
10422  vt = _mm_mul_pd(va,vt);
10423  ve = _mm_add_pd(vt,ve);
10424  a+=4;
10425  b+=4;
10426  }
10427  if( k%2 )
10428  {
10429  va = _mm_load_pd(a);
10430  vb = _mm_load_pd(b);
10431  vt = _mm_shuffle_pd(vb, vb, 1);
10432  vd = _mm_add_pd(_mm_mul_pd(va,vb),vd);
10433  ve = _mm_add_pd(_mm_mul_pd(va,vt),ve);
10434  }
10435 
10436  /*
10437  * r0 is first row of alpha*A'*B, r1 is second row
10438  */
10439  valpha = _mm_load1_pd(&alpha);
10440  r0 = _mm_mul_pd(_mm_unpacklo_pd(vd,ve),valpha);
10441  r1 = _mm_mul_pd(_mm_unpackhi_pd(ve,vd),valpha);
10442 
10443  /*
10444  * store
10445  */
10446  if( store_mode==0 )
10447  {
10448  if( beta==0 )
10449  {
10450  _mm_storeu_pd(r,r0);
10451  _mm_storeu_pd(r+stride,r1);
10452  }
10453  else
10454  {
10455  vbeta = _mm_load1_pd(&beta);
10456  _mm_storeu_pd(r,_mm_add_pd(_mm_mul_pd(_mm_loadu_pd(r),vbeta),r0));
10457  _mm_storeu_pd(r+stride,_mm_add_pd(_mm_mul_pd(_mm_loadu_pd(r+stride),vbeta),r1));
10458  }
10459  return;
10460  }
10461  if( store_mode==1 )
10462  {
10463  if( beta==0 )
10464  _mm_storeu_pd(r,r0);
10465  else
10466  _mm_storeu_pd(r,_mm_add_pd(_mm_mul_pd(_mm_loadu_pd(r),_mm_load1_pd(&beta)),r0));
10467  return;
10468  }
10469  if( store_mode==2 )
10470  {
10471  double buf[4];
10472  _mm_storeu_pd(buf,r0);
10473  _mm_storeu_pd(buf+2,r1);
10474  if( beta==0 )
10475  {
10476  r[0] =buf[0];
10477  r[stride+0] = buf[2];
10478  }
10479  else
10480  {
10481  r[0] = beta*r[0] + buf[0];
10482  r[stride+0] = beta*r[stride+0] + buf[2];
10483  }
10484  return;
10485  }
10486  if( store_mode==3 )
10487  {
10488  double buf[2];
10489  _mm_storeu_pd(buf,r0);
10490  if( beta==0 )
10491  r[0] = buf[0];
10492  else
10493  r[0] = beta*r[0] + buf[0];
10494  return;
10495  }
10496 }
10497 #endif
10498 
10499 
10500 /*************************************************************************
10501 This function calculates R := alpha*A'*(B0|B1)+beta*R where A, B0 and B1
10502 are Kx2 matrices stored in contiguous row-by-row storage, R is 2x4 matrix
10503 stored in non-contiguous row-by-row storage.
10504 
10505 A, B0 and B1 must be aligned; R may be non-aligned.
10506 
10507 Note that B0 and B1 are two separate matrices stored in different
10508 locations.
10509 
10510 If beta is zero, contents of R is ignored (not multiplied by zero - just
10511 ignored).
10512 
10513 However, when alpha is zero , we still calculate MM product, which is
10514 multiplied by zero afterwards.
10515 
10516 Unlike mm22 functions, this function does NOT support partial output of R
10517 - we always store full 2x4 matrix.
10518 *************************************************************************/
10519 void _ialglib_mm22x2(double alpha, const double *a, const double *b0, const double *b1, ae_int_t k, double beta, double *r, ae_int_t stride)
10520 {
10521  _ialglib_mm22(alpha, a, b0, k, beta, r, stride, 0);
10522  _ialglib_mm22(alpha, a, b1, k, beta, r+2, stride, 0);
10523 }
10524 
10525 /*************************************************************************
10526 This function calculates R := alpha*A'*(B0|B1)+beta*R where A, B0 and B1
10527 are Kx2 matrices stored in contiguous row-by-row storage, R is 2x4 matrix
10528 stored in non-contiguous row-by-row storage.
10529 
10530 A, B0 and B1 must be aligned; R may be non-aligned.
10531 
10532 Note that B0 and B1 are two separate matrices stored in different
10533 locations.
10534 
10535 If beta is zero, contents of R is ignored (not multiplied by zero - just
10536 ignored).
10537 
10538 However, when alpha is zero , we still calculate MM product, which is
10539 multiplied by zero afterwards.
10540 
10541 Unlike mm22 functions, this function does NOT support partial output of R
10542 - we always store full 2x4 matrix.
10543 
10544 This function supports SSE2; it can be used when:
10545 1. AE_HAS_SSE2_INTRINSICS was defined (checked at compile-time)
10546 2. ae_cpuid() result contains CPU_SSE2 (checked at run-time)
10547 
10548 If (1) is failed, this function will still be defined and callable, but it
10549 will do nothing. If (2) is failed , call to this function will probably
10550 crash your system.
10551 
10552 If you want to know whether it is safe to call it, you should check
10553 results of ae_cpuid(). If CPU_SSE2 bit is set, this function is callable
10554 and will do its work.
10555 *************************************************************************/
10556 #if defined(AE_HAS_SSE2_INTRINSICS)
10557 void _ialglib_mm22x2_sse2(double alpha, const double *a, const double *b0, const double *b1, ae_int_t k, double beta, double *r, ae_int_t stride)
10558 {
10559  /*
10560  * We calculate product of two Kx2 matrices (result is 2x2).
10561  * V0, V1, V2, V3 store result as follows:
10562  *
10563  * [ V0[0] V1[1] V2[0] V3[1] ]
10564  * R = [ ]
10565  * [ V1[0] V0[1] V3[0] V2[1] ]
10566  *
10567  * VA0 stores current 1x2 block of A, VA1 stores shuffle of VA0,
10568  * VB0 and VB1 are used to store two copies of 1x2 block of B0 or B1
10569  * (both vars store same data - either B0 or B1). Results from multiplication
10570  * by VA0/VA1 are stored in VB0/VB1 too.
10571  *
10572  */
10573  __m128d v0, v1, v2, v3, va0, va1, vb0, vb1;
10574  __m128d r00, r01, r10, r11, valpha, vbeta;
10575  ae_int_t t, k2;
10576 
10577  k2 = k/2;
10578  v0 = _mm_setzero_pd();
10579  v1 = _mm_setzero_pd();
10580  v2 = _mm_setzero_pd();
10581  v3 = _mm_setzero_pd();
10582  for(t=0; t<k; t++)
10583  {
10584  va0 = _mm_load_pd(a);
10585  vb0 = _mm_load_pd(b0);
10586  va1 = _mm_load_pd(a);
10587 
10588  vb0 = _mm_mul_pd(va0,vb0);
10589  vb1 = _mm_load_pd(b0);
10590  v0 = _mm_add_pd(v0,vb0);
10591  vb1 = _mm_mul_pd(va1,vb1);
10592  vb0 = _mm_load_pd(b1);
10593  v1 = _mm_add_pd(v1,vb1);
10594 
10595  vb0 = _mm_mul_pd(va0,vb0);
10596  vb1 = _mm_load_pd(b1);
10597  v2 = _mm_add_pd(v2,vb0);
10598  vb1 = _mm_mul_pd(va1,vb1);
10599  v3 = _mm_add_pd(v3,vb1);
10600 
10601  a+=2;
10602  b0+=2;
10603  b1+=2;
10604  }
10605 
10606  /*
10607  * shuffle V1 and V3 (conversion to more convenient storage format):
10608  *
10609  * [ V0[0] V1[0] V2[0] V3[0] ]
10610  * R = [ ]
10611  * [ V1[1] V0[1] V3[1] V2[1] ]
10612  *
10613  * unpack results to
10614  *
10615  * [ r00 r01 ]
10616  * [ r10 r11 ]
10617  *
10618  */
10619  valpha = _mm_load1_pd(&alpha);
10620  v1 = _mm_shuffle_pd(v1, v1, 1);
10621  v3 = _mm_shuffle_pd(v3, v3, 1);
10622  r00 = _mm_mul_pd(_mm_unpacklo_pd(v0,v1),valpha);
10623  r10 = _mm_mul_pd(_mm_unpackhi_pd(v1,v0),valpha);
10624  r01 = _mm_mul_pd(_mm_unpacklo_pd(v2,v3),valpha);
10625  r11 = _mm_mul_pd(_mm_unpackhi_pd(v3,v2),valpha);
10626 
10627  /*
10628  * store
10629  */
10630  if( beta==0 )
10631  {
10632  _mm_storeu_pd(r,r00);
10633  _mm_storeu_pd(r+2,r01);
10634  _mm_storeu_pd(r+stride,r10);
10635  _mm_storeu_pd(r+stride+2,r11);
10636  }
10637  else
10638  {
10639  vbeta = _mm_load1_pd(&beta);
10640  _mm_storeu_pd(r, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(r),vbeta),r00));
10641  _mm_storeu_pd(r+2, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(r+2),vbeta),r01));
10642  _mm_storeu_pd(r+stride, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(r+stride),vbeta),r10));
10643  _mm_storeu_pd(r+stride+2, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(r+stride+2),vbeta),r11));
10644  }
10645 }
10646 #endif
10647 
10648 }
10649 
10650 
10652 //
10653 // THIS SECTION CONTAINS PARALLEL SUBROUTINES
10654 //
10656 namespace alglib_impl
10657 {
10658 
10659 
10660 }
10661 
ae_int64_t stride
Definition: ap.h:306
virtual ~complex_2d_array()
Definition: ap.cpp:6707
void ae_shared_pool_reset(ae_shared_pool *pool, ae_state *state)
Definition: ap.cpp:3371
ae_int64_t last_action
Definition: ap.h:270
ae_bool _ialglib_i_cmatrixrighttrsmf(ae_int_t m, ae_int_t n, ae_matrix *a, ae_int_t i1, ae_int_t j1, ae_bool isupper, ae_bool isunit, ae_int_t optype, ae_matrix *x, ae_int_t i2, ae_int_t j2)
Definition: ap.cpp:9963
const boolean_1d_array & operator=(const boolean_1d_array &rhs)
Definition: ap.cpp:6017
void ae_vector_init_from_x(ae_vector *dst, x_vector *src, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:633
const alglib::complex operator-(const alglib::complex &lhs)
Definition: ap.cpp:4891
void ae_v_cmove(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n)
Definition: ap.cpp:3871
ae_int64_t cnt
Definition: ap.h:267
void _ialglib_vcopy_dcomplex(ae_int_t n, const double *a, ae_int_t stridea, double *b, ae_int_t strideb, const char *conj)
Definition: ap.cpp:8688
void *volatile next_entry
Definition: ap.h:516
virtual ~boolean_2d_array()
Definition: ap.cpp:6494
ae_bool ae_fp_greater_eq(double v1, double v2)
Definition: ap.cpp:1351
void setcontent(ae_int_t irows, ae_int_t icols, const bool *pContent)
Definition: ap.cpp:6518
const alglib::complex & operator()(ae_int_t i, ae_int_t j) const
Definition: ap.cpp:6711
bool fp_isneginf(double x)
Definition: ap.cpp:7339
void setnworkers(alglib::ae_int_t nworkers)
Definition: ap.cpp:4994
void ae_serializer_init(ae_serializer *serializer)
Definition: ap.cpp:3393
void create(const ae_matrix_wrapper &rhs)
Definition: ap.cpp:6320
double v_posinf
Definition: ap.h:360
const bool operator==(const alglib::complex &lhs, const alglib::complex &rhs)
Definition: ap.cpp:4876
ae_dyn_block data
Definition: ap.h:431
double ae_c_abs(ae_complex z, ae_state *state)
Definition: ap.cpp:3639
void ae_v_moved(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
Definition: ap.cpp:4425
bool fp_less(double v1, double v2)
Definition: ap.cpp:7297
void ae_x_set_matrix(x_matrix *dst, ae_matrix *src, ae_state *state)
Definition: ap.cpp:1126
const double & operator()(ae_int_t i, ae_int_t j) const
Definition: ap.cpp:6640
ae_int_t cols
Definition: ap.h:445
const ae_int_t & operator()(ae_int_t i) const
Definition: ap.cpp:6103
alglib::complex conj(const alglib::complex &z)
Definition: ap.cpp:4988
ae_dyn_block frame_entry
Definition: ap.h:479
double ae_sin(double x, ae_state *state)
Definition: ap.cpp:1630
bool _parse_real_delim(const char *s, const char *delim, double *result, const char **new_s)
Definition: ap.cpp:6984
ae_bool ae_shared_pool_init(void *_dst, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:2864
#define AE_SM_ALLOC
Definition: ap.cpp:67
double minreal(double m1, double m2)
Definition: ap.cpp:7278
void ae_serializer_serialize_bool(ae_serializer *serializer, ae_bool v, ae_state *state)
Definition: ap.cpp:3479
ae_int_t ae_serializer_get_alloc_size(ae_serializer *serializer)
Definition: ap.cpp:3416
__host__ __device__ float2 floor(const float2 v)
void setcontent(ae_int_t iLen, const bool *pContent)
Definition: ap.cpp:6047
const alglib::complex & operator[](ae_int_t i) const
Definition: ap.cpp:6265
ae_bool _ialglib_rmatrixlefttrsm(ae_int_t m, ae_int_t n, double *_a, ae_int_t _a_stride, ae_bool isupper, ae_bool isunit, ae_int_t optype, double *_x, ae_int_t _x_stride)
Definition: ap.cpp:9539
ae_bool ae_is_symmetric(ae_matrix *a)
Definition: ap.cpp:2248
bool fp_greater(double v1, double v2)
Definition: ap.cpp:7313
void ae_shared_pool_first_recycled(ae_shared_pool *pool, ae_smart_ptr *pptr, ae_state *state)
Definition: ap.cpp:3294
void ae_v_muld(double *vdst, ae_int_t stride_dst, ae_int_t n, double alpha)
Definition: ap.cpp:4538
ae_int_t ae_misalignment(const void *ptr, size_t alignment)
Definition: ap.cpp:113
void _ialglib_vzero_complex(ae_int_t n, ae_complex *p, ae_int_t stride)
Definition: ap.cpp:8602
ae_bool ae_c_neq(ae_complex lhs, ae_complex rhs)
Definition: ap.cpp:3668
#define AE_SER_ENTRIES_PER_ROW
Definition: ap.cpp:64
void ae_shared_pool_retrieve(ae_shared_pool *pool, ae_smart_ptr *pptr, ae_state *state)
Definition: ap.cpp:3122
double ae_fabs(double x, ae_state *state)
Definition: ap.cpp:1520
#define AE_SER_ENTRY_LENGTH
Definition: ap.cpp:63
void ae_shared_pool_clear(void *_dst)
Definition: ap.cpp:3014
double ae_tan(double x, ae_state *state)
Definition: ap.cpp:1640
ae_int_t getstride() const
Definition: ap.cpp:6438
ae_int_t ae_str2int(const char *buf, ae_state *state, const char **pasttheend)
Definition: ap.cpp:2504
doublereal * c
bool fp_eq(double v1, double v2)
Definition: ap.cpp:7283
complex & operator+=(const double &v)
Definition: ap.cpp:4750
double ae_pow(double x, double y, ae_state *state)
Definition: ap.cpp:1684
void ** subscriber
Definition: ap.h:463
ae_int64_t datatype
Definition: ap.h:268
#define ae_false
Definition: ap.h:196
void ae_int2str(ae_int_t v, char *buf, ae_state *state)
Definition: ap.cpp:2441
void * ae_malloc(size_t size, ae_state *state)
Definition: ap.cpp:222
ae_int_t stride
Definition: ap.h:446
std::string tostring(int dps) const
Definition: ap.cpp:4838
void ae_db_free(ae_dyn_block *block)
Definition: ap.cpp:534
int ae_int32_t
Definition: ap.h:166
#define AE_BIG_ENDIAN
Definition: ap.cpp:61
double beta(const double a, const double b)
#define alglib_simd_alignment
Definition: ap.cpp:7785
void _ialglib_mcopyblock(ae_int_t m, ae_int_t n, const double *a, ae_int_t op, ae_int_t stride, double *b)
Definition: ap.cpp:8733
ae_bool parse_bool_delim(const char *s, const char *delim)
Definition: ap.cpp:6921
void sqrt(Image< double > &op)
ae_vector ca
Definition: ap.h:840
bool fp_less_eq(double v1, double v2)
Definition: ap.cpp:7305
union alglib_impl::ae_matrix::@12 ptr
void _ialglib_mcopyblock_complex(ae_int_t m, ae_int_t n, const ae_complex *a, ae_int_t op, ae_int_t stride, double *b)
Definition: ap.cpp:8979
ae_bool ae_isposinf(double x, ae_state *state)
Definition: ap.cpp:1510
void(* destroy)(void *)
Definition: ap.h:476
ae_int_t bytes_written
Definition: ap.h:416
void ae_frame_make(ae_state *state, ae_frame *tmp)
Definition: ap.cpp:402
#define AE_LOCK_ALIGNMENT
Definition: ap.h:47
const bool operator!=(const alglib::complex &lhs, const alglib::complex &rhs)
Definition: ap.cpp:4885
static double * y
ae_complex ae_c_d_sub(double lhs, ae_complex rhs)
Definition: ap.cpp:3765
complex & operator-=(const double &v)
Definition: ap.cpp:4756
const ae_int_t endianness
Definition: ap.cpp:4693
ae_shared_pool_entry *volatile recycled_objects
Definition: ap.h:533
void x_vector_clear(x_vector *dst)
Definition: ap.cpp:1216
int maxint(int m1, int m2)
Definition: ap.cpp:7263
alglib_impl::ae_matrix * p_mat
Definition: ap.h:1252
const alglib::complex operator/(const alglib::complex &lhs, const alglib::complex &rhs)
Definition: ap.cpp:4921
ae_error_type volatile last_error
Definition: ap.h:384
ae_bool x_force_symmetric(x_matrix *a)
Definition: ap.cpp:2225
std::string tostring(int dps) const
Definition: ap.cpp:6296
void _ialglib_cmv(ae_int_t m, ae_int_t n, const double *a, const double *x, ae_complex *cy, double *dy, ae_int_t stride, ae_complex alpha, ae_complex beta)
Definition: ap.cpp:8391
static void make_assertion(bool bClause)
Definition: ap.cpp:4711
ae_bool ae_c_eq_d(ae_complex lhs, double rhs)
Definition: ap.cpp:3723
ae_complex ae_c_conj(ae_complex lhs, ae_state *state)
Definition: ap.cpp:3623
void setcontent(ae_int_t iLen, const ae_int_t *pContent)
Definition: ap.cpp:6123
void setcontent(ae_int_t iLen, const alglib::complex *pContent)
Definition: ap.cpp:6275
ae_vector ia
Definition: ap.h:837
ae_bool ae_db_realloc(ae_dyn_block *block, ae_int_t size, ae_state *state)
Definition: ap.cpp:504
const ae_matrix_wrapper & operator=(const ae_matrix_wrapper &rhs)
Definition: ap.cpp:6314
void(* deallocator)(void *)
Definition: ap.h:330
ae_complex ae_complex_from_d(double v)
Definition: ap.cpp:3607
ae_int_t ae_sign(double x, ae_state *state)
Definition: ap.cpp:1540
const double fp_neginf
Definition: ap.cpp:4696
void ae_double2str(double v, char *buf, ae_state *state)
Definition: ap.cpp:2564
std::string tostring() const
Definition: ap.cpp:6598
void vmul(double *vdst, ae_int_t stride_dst, ae_int_t n, double alpha)
Definition: ap.cpp:5763
void ae_db_swap(ae_dyn_block *block1, ae_dyn_block *block2)
Definition: ap.cpp:550
ae_bool ae_force_hermitian(ae_matrix *a)
Definition: ap.cpp:2272
alglib::complex parse_complex_delim(const char *s, const char *delim)
Definition: ap.cpp:7086
void ae_swap_vectors(ae_vector *vec1, ae_vector *vec2)
Definition: ap.cpp:717
ae_bool _ialglib_cmatrixgemm(ae_int_t m, ae_int_t n, ae_int_t k, ae_complex alpha, ae_complex *_a, ae_int_t _a_stride, ae_int_t optypea, ae_complex *_b, ae_int_t _b_stride, ae_int_t optypeb, ae_complex beta, ae_complex *_c, ae_int_t _c_stride)
Definition: ap.cpp:9176
double v_neginf
Definition: ap.h:365
ae_dyn_block frame_entry
Definition: ap.h:560
doublereal * w
ae_bool ae_isnan_stateless(double x, ae_int_t endianness)
Definition: ap.cpp:1375
#define AE_SM_TO_STRING
Definition: ap.cpp:69
double get_aenv_nan()
Definition: ap.cpp:6764
double * p_double
Definition: ap.h:437
ae_bool ae_isneginf_stateless(double x, ae_int_t endianness)
Definition: ap.cpp:1445
ae_bool _ialglib_i_rmatrixgemmf(ae_int_t m, ae_int_t n, ae_int_t k, double alpha, ae_matrix *_a, ae_int_t ia, ae_int_t ja, ae_int_t optypea, ae_matrix *_b, ae_int_t ib, ae_int_t jb, ae_int_t optypeb, double beta, ae_matrix *_c, ae_int_t ic, ae_int_t jc)
Definition: ap.cpp:9923
void ae_v_csubd(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha)
Definition: ap.cpp:4271
void ae_shared_pool_recycle(ae_shared_pool *pool, ae_smart_ptr *pptr, ae_state *state)
Definition: ap.cpp:3192
virtual ~real_1d_array()
Definition: ap.cpp:6175
ae_complex ae_c_div_d(ae_complex lhs, double rhs)
Definition: ap.cpp:3773
int minint(int m1, int m2)
Definition: ap.cpp:7268
void ae_serializer_stop(ae_serializer *serializer)
Definition: ap.cpp:3599
double parse_real_delim(const char *s, const char *delim)
Definition: ap.cpp:7077
#define alglib_twice_c_block
Definition: ap.cpp:7793
ae_bool ae_c_neq_d(ae_complex lhs, double rhs)
Definition: ap.cpp:3732
void ae_matrix_update_row_pointers(ae_matrix *dst, void *storage)
Definition: ap.cpp:252
ae_bool _ialglib_rmatrixgemm(ae_int_t m, ae_int_t n, ae_int_t k, double alpha, double *_a, ae_int_t _a_stride, ae_int_t optypea, double *_b, ae_int_t _b_stride, ae_int_t optypeb, double beta, double *_c, ae_int_t _c_stride)
Definition: ap.cpp:9093
void ae_state_clear(ae_state *state)
Definition: ap.cpp:373
double get_aenv_posinf()
Definition: ap.cpp:6774
char ae_sixbits2char(ae_int_t v)
Definition: ap.cpp:2296
ae_bool ae_isposinf_stateless(double x, ae_int_t endianness)
Definition: ap.cpp:1421
const alglib_impl::ae_matrix * c_ptr() const
Definition: ap.cpp:6463
ae_bool ae_fp_eq(double v1, double v2)
Definition: ap.cpp:1313
void ae_smart_ptr_assign(ae_smart_ptr *dst, void *new_ptr, ae_bool is_owner, ae_bool is_dynamic, void(*destroy)(void *))
Definition: ap.cpp:1040
void ae_v_cmulc(ae_complex *vdst, ae_int_t stride_dst, ae_int_t n, ae_complex alpha)
Definition: ap.cpp:4310
double sqr(double x)
Definition: ap.cpp:7260
void vsub(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:5647
void allocate_own(ae_int_t rows, ae_int_t cols, alglib_impl::ae_datatype datatype)
Definition: ap.cpp:6454
const double * operator[](ae_int_t i) const
Definition: ap.cpp:6650
ae_bool ae_db_malloc(ae_dyn_block *block, ae_int_t size, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:461
std::string * out_cppstr
Definition: ap.h:419
complex & operator=(const double &v)
Definition: ap.cpp:4743
double ae_cos(double x, ae_state *state)
Definition: ap.cpp:1635
ae_bool ae_isneginf(double x, ae_state *state)
Definition: ap.cpp:1515
ae_bool ae_matrix_init_copy(ae_matrix *dst, ae_matrix *src, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:801
ae_bool ae_matrix_init(ae_matrix *dst, ae_int_t rows, ae_int_t cols, ae_datatype datatype, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:756
void _ialglib_pack_n2(double *col0, double *col1, ae_int_t n, ae_int_t src_stride, double *dst)
Definition: ap.cpp:10092
void attach_to(alglib_impl::ae_vector *ptr)
Definition: ap.cpp:5889
void * ae_align(void *ptr, size_t alignment)
Definition: ap.cpp:124
doublereal * x
ae_int_t size_of_object
Definition: ap.h:548
void ae_matrix_destroy(ae_matrix *dst)
Definition: ap.cpp:909
double v_nan
Definition: ap.h:355
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
void * aligned_malloc(size_t size, size_t alignment)
Definition: ap.cpp:162
void ae_v_add(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:4452
ae_bool _ialglib_rmatrixrank1(ae_int_t m, ae_int_t n, double *_a, ae_int_t _a_stride, double *_u, double *_v)
Definition: ap.cpp:9852
double randomreal()
Definition: ap.cpp:7222
ae_bool * getcontent()
Definition: ap.cpp:6055
doublereal * d
ae_complex ae_c_sub_d(ae_complex lhs, double rhs)
Definition: ap.cpp:3757
ae_bool x_is_hermitian(x_matrix *a)
Definition: ap.cpp:2203
ae_int_t ae_char2sixbits(char c)
Definition: ap.cpp:2339
void ae_serializer_clear(ae_serializer *serializer)
Definition: ap.cpp:3400
void ae_db_attach(ae_dyn_block *block, ae_state *state)
Definition: ap.cpp:436
#define DYN_BOTTOM
Definition: ap.cpp:58
ae_bool _ialglib_cmatrixsyrk(ae_int_t n, ae_int_t k, double alpha, ae_complex *_a, ae_int_t _a_stride, ae_int_t optypea, double beta, ae_complex *_c, ae_int_t _c_stride, ae_bool isupper)
Definition: ap.cpp:9623
const integer_1d_array & operator=(const integer_1d_array &rhs)
Definition: ap.cpp:6093
ae_int_t entries_saved
Definition: ap.h:414
alglib::complex * getcontent()
Definition: ap.cpp:6286
void ae_serializer_sstart_str(ae_serializer *serializer, char *buf)
Definition: ap.cpp:3464
Definition: ap.h:513
ae_dyn_block data
Definition: ap.h:448
void ae_smart_ptr_release(ae_smart_ptr *dst)
Definition: ap.cpp:1074
alglib::complex csqr(const alglib::complex &z)
Definition: ap.cpp:4991
double ae_asin(double x, ae_state *state)
Definition: ap.cpp:1659
void setcontent(ae_int_t irows, ae_int_t icols, const alglib::complex *pContent)
Definition: ap.cpp:6731
void ae_serializer_serialize_int(ae_serializer *serializer, ae_int_t v, ae_state *state)
Definition: ap.cpp:3514
#define AE_SM_TO_CPPSTRING
Definition: ap.cpp:71
#define alglib_twice_r_block
Definition: ap.cpp:7789
ae_int_t ae_randominteger(ae_int_t maxv, ae_state *state)
Definition: ap.cpp:1621
#define AE_MIXED_ENDIAN
Definition: ap.cpp:62
void _rcommstate_destroy(rcommstate *p)
Definition: ap.cpp:4605
virtual ~integer_2d_array()
Definition: ap.cpp:6565
alglib_impl::ae_vector * p_vec
Definition: ap.h:1103
void(* thread_exception_handler)(void *)
Definition: ap.h:403
bool fp_isfinite(double x)
Definition: ap.cpp:7349
void(* destroy)(void *ptr)
Definition: ap.h:557
ae_int_t ae_v_len(ae_int_t a, ae_int_t b)
Definition: ap.cpp:4562
void ae_vector_destroy(ae_vector *dst)
Definition: ap.cpp:707
ae_bool _rcommstate_init(rcommstate *p, ae_state *_state, ae_bool make_automatic)
Definition: ap.cpp:4570
#define AE_SM_READY2S
Definition: ap.cpp:68
void setlength(ae_int_t iLen)
Definition: ap.cpp:5872
virtual ~integer_1d_array()
Definition: ap.cpp:6099
struct ae_dyn_block *volatile p_next
Definition: ap.h:328
doublereal * b
void * worker_thread
Definition: ap.h:401
virtual ~ae_vector_wrapper()
Definition: ap.cpp:5866
ae_int_t my_stricmp(const char *s1, const char *s2)
Definition: ap.cpp:6794
int iceil(double x)
Definition: ap.cpp:7254
void ae_shared_pool_set_seed(ae_shared_pool *dst, void *seed_object, ae_int_t size_of_object, ae_bool(*init)(void *dst, ae_state *state, ae_bool make_automatic), ae_bool(*init_copy)(void *dst, void *src, ae_state *state, ae_bool make_automatic), void(*destroy)(void *ptr), ae_state *state)
Definition: ap.cpp:3079
double v1
void log(Image< double > &op)
const complex_1d_array & operator=(const complex_1d_array &rhs)
Definition: ap.cpp:6245
ae_complex ae_c_sqr(ae_complex lhs, ae_state *state)
Definition: ap.cpp:3631
ae_int64_t last_action
Definition: ap.h:309
void ae_v_csub(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n)
Definition: ap.cpp:4221
void ae_free_lock(ae_lock *lock)
Definition: ap.cpp:2841
ae_bool(* init)(void *dst, ae_state *state, ae_bool make_automatic)
Definition: ap.h:551
void vmove(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:5102
ae_bool _rcommstate_init_copy(rcommstate *dst, rcommstate *src, ae_state *_state, ae_bool make_automatic)
Definition: ap.cpp:4583
void ae_v_move(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:4371
ae_int_t endianness
Definition: ap.h:350
#define AE_LITTLE_ENDIAN
Definition: ap.cpp:60
#define alglib_c_block
Definition: ap.cpp:7791
void ae_swap_matrices(ae_matrix *mat1, ae_matrix *mat2)
Definition: ap.cpp:919
ae_int_t rows
Definition: ap.h:444
ae_int64_t owner
Definition: ap.h:269
void setcontent(ae_int_t irows, ae_int_t icols, const ae_int_t *pContent)
Definition: ap.cpp:6589
ae_complex ae_c_div(ae_complex lhs, ae_complex rhs)
Definition: ap.cpp:3701
void str_vector_create(const char *src, bool match_head_only, std::vector< const char *> *p_vec)
Definition: ap.cpp:6848
ae_bool _ialglib_i_cmatrixgemmf(ae_int_t m, ae_int_t n, ae_int_t k, ae_complex alpha, ae_matrix *_a, ae_int_t ia, ae_int_t ja, ae_int_t optypea, ae_matrix *_b, ae_int_t ib, ae_int_t jb, ae_int_t optypeb, ae_complex beta, ae_matrix *_c, ae_int_t ic, ae_int_t jc)
Definition: ap.cpp:9943
ae_bool ae_isinf(double x, ae_state *state)
Definition: ap.cpp:1505
double * f
ae_int_t bytes_asked
Definition: ap.h:415
ae_complex ae_c_add(ae_complex lhs, ae_complex rhs)
Definition: ap.cpp:3677
void ae_vector_clear(ae_vector *dst)
Definition: ap.cpp:692
void(* ae_deallocator)(void *)
Definition: ap.h:425
void ae_v_csubc(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, ae_complex alpha)
Definition: ap.cpp:4276
ae_bool ae_force_symmetric(ae_matrix *a)
Definition: ap.cpp:2264
ae_int_t length() const
Definition: ap.cpp:5882
ae_bool ae_isinf_stateless(double x, ae_int_t endianness)
Definition: ap.cpp:1397
ae_complex ** pp_complex
Definition: ap.h:456
ae_bool ae_fp_less(double v1, double v2)
Definition: ap.cpp:1327
void _ialglib_mv_32(const double *a, const double *x, double *y, ae_int_t stride, double alpha, double beta)
Definition: ap.cpp:7810
const double fp_posinf
Definition: ap.cpp:4695
const ae_bool * operator[](ae_int_t i) const
Definition: ap.cpp:6508
std::string tostring() const
Definition: ap.cpp:6527
ae_bool ae_shared_pool_is_initialized(void *_dst)
Definition: ap.cpp:3057
void ae_break(ae_state *state, ae_error_type error_type, const char *msg)
Definition: ap.cpp:132
void ae_spin_wait(ae_int_t cnt)
Definition: ap.cpp:2722
ae_int_t ae_iceil(double x, ae_state *state)
Definition: ap.cpp:1562
std::string arraytostring(const alglib::complex *ptr, ae_int_t n, int dps)
Definition: ap.cpp:7196
void ae_serializer_unserialize_int(ae_serializer *serializer, ae_int_t *v, ae_state *state)
Definition: ap.cpp:3589
ae_vector ra
Definition: ap.h:839
double ae_randomreal(ae_state *state)
Definition: ap.cpp:1607
std::string tostring() const
Definition: ap.cpp:6141
ae_int_t ae_sizeof(ae_datatype datatype)
Definition: ap.cpp:273
ae_bool ae_smart_ptr_init(ae_smart_ptr *dst, void **subscriber, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:967
std::string tostring(int dps) const
Definition: ap.cpp:6743
const double machineepsilon
Definition: ap.cpp:4690
#define alglib_r_block
Definition: ap.cpp:7787
ae_complex ae_c_add_d(ae_complex lhs, double rhs)
Definition: ap.cpp:3741
void ae_v_caddc(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, ae_complex alpha)
Definition: ap.cpp:4169
void ae_release_lock(ae_lock *lock)
Definition: ap.cpp:2826
ae_bool is_dynamic
Definition: ap.h:473
ae_bool ae_shared_pool_init_copy(void *_dst, void *_src, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:2946
void ae_threebytes2foursixbits(const unsigned char *src, ae_int_t *dst)
Definition: ap.cpp:2351
#define ae_bool
Definition: ap.h:194
ae_complex ae_c_sub(ae_complex lhs, ae_complex rhs)
Definition: ap.cpp:3693
ae_bool ae_fp_neq(double v1, double v2)
Definition: ap.cpp:1321
ae_bool ae_isnan(double x, ae_state *state)
Definition: ap.cpp:1500
void ae_v_cmoved(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha)
Definition: ap.cpp:3965
void vmoveneg(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:5183
free((char *) ob)
const alglib::complex * operator[](ae_int_t i) const
Definition: ap.cpp:6721
ae_bool x_force_hermitian(x_matrix *a)
Definition: ap.cpp:2236
const double & operator()(ae_int_t i) const
Definition: ap.cpp:6179
double z
void ae_shared_pool_next_recycled(ae_shared_pool *pool, ae_smart_ptr *pptr, ae_state *state)
Definition: ap.cpp:3333
__host__ __device__ float length(float2 v)
void ae_v_cadd(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n)
Definition: ap.cpp:4069
std::string tostring() const
Definition: ap.cpp:6065
const double minrealnumber
Definition: ap.cpp:4692
void ae_touch_ptr(void *p)
Definition: ap.cpp:294
void ae_acquire_lock(ae_lock *lock)
Definition: ap.cpp:2780
virtual ~ae_matrix_wrapper()
Definition: ap.cpp:6308
ae_dyn_block db_marker
Definition: ap.h:339
double ae_maxreal(double m1, double m2, ae_state *state)
Definition: ap.cpp:1577
ae_error_type
Definition: ap.h:201
bool fp_isinf(double x)
Definition: ap.cpp:7344
ae_complex ae_v_cdotproduct(const ae_complex *v0, ae_int_t stride0, const char *conj0, const ae_complex *v1, ae_int_t stride1, const char *conj1, ae_int_t n)
Definition: ap.cpp:3807
void _ialglib_rmv(ae_int_t m, ae_int_t n, const double *a, const double *x, double *y, ae_int_t stride, double alpha, double beta)
Definition: ap.cpp:7876
ae_datatype datatype
Definition: ap.h:447
void ae_x_attach_to_vector(x_vector *dst, ae_vector *src)
Definition: ap.cpp:1171
virtual ~complex_1d_array()
Definition: ap.cpp:6251
void ae_bool2str(ae_bool v, char *buf, ae_state *state)
Definition: ap.cpp:2381
ae_bool ae_vector_set_length(ae_vector *dst, ae_int_t newsize, ae_state *state)
Definition: ap.cpp:658
alglib_impl::ae_complex * c_ptr()
Definition: ap.cpp:4828
void ae_v_sub(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:4506
complex & operator/=(const double &v)
Definition: ap.cpp:4769
bool fp_neq(double v1, double v2)
Definition: ap.cpp:7291
const ae_bool & operator()(ae_int_t i) const
Definition: ap.cpp:6027
void _ialglib_vcopy_complex(ae_int_t n, const ae_complex *a, ae_int_t stridea, double *b, ae_int_t strideb, const char *conj)
Definition: ap.cpp:8656
ae_bool _ialglib_cmatrixrighttrsm(ae_int_t m, ae_int_t n, ae_complex *_a, ae_int_t _a_stride, ae_bool isupper, ae_bool isunit, ae_int_t optype, ae_complex *_x, ae_int_t _x_stride)
Definition: ap.cpp:9261
ae_bool _ialglib_i_cmatrixlefttrsmf(ae_int_t m, ae_int_t n, ae_matrix *a, ae_int_t i1, ae_int_t j1, ae_bool isupper, ae_bool isunit, ae_int_t optype, ae_matrix *x, ae_int_t i2, ae_int_t j2)
Definition: ap.cpp:9993
ae_datatype datatype
Definition: ap.h:430
void _ialglib_mcopyunblock(ae_int_t m, ae_int_t n, const double *a, ae_int_t op, double *b, ae_int_t stride)
Definition: ap.cpp:8920
double ae_log(double x, ae_state *state)
Definition: ap.cpp:1679
void ae_serializer_serialize_double(ae_serializer *serializer, double v, ae_state *state)
Definition: ap.cpp:3549
ae_int_t ae_datatype
Definition: ap.h:209
void _ialglib_vzero(ae_int_t n, double *p, ae_int_t stride)
Definition: ap.cpp:8584
const ae_bool & operator[](ae_int_t i) const
Definition: ap.cpp:6037
std::string arraytostring(const bool *ptr, ae_int_t n)
Definition: ap.cpp:7132
const alglib_impl::ae_vector * c_ptr() const
Definition: ap.cpp:5907
ae_bool _ialglib_cmatrixrank1(ae_int_t m, ae_int_t n, ae_complex *_a, ae_int_t _a_stride, ae_complex *_u, ae_complex *_v)
Definition: ap.cpp:9796
void ae_smart_ptr_clear(void *_dst)
Definition: ap.cpp:992
#define j
double ae_minreal(double m1, double m2, ae_state *state)
Definition: ap.cpp:1582
ae_bool _ialglib_i_rmatrixrank1f(ae_int_t m, ae_int_t n, ae_matrix *a, ae_int_t ia, ae_int_t ja, ae_vector *u, ae_int_t uoffs, ae_vector *v, ae_int_t voffs)
Definition: ap.cpp:10068
void *volatile obj
Definition: ap.h:515
ae_bool is_locked
Definition: ap.h:504
ae_complex ae_c_d_div(double lhs, ae_complex rhs)
Definition: ap.cpp:3781
void attach_to(alglib_impl::ae_matrix *ptr)
Definition: ap.cpp:6445
ae_bool ae_c_eq(ae_complex lhs, ae_complex rhs)
Definition: ap.cpp:3659
double ae_str2double(const char *buf, ae_state *state, const char **pasttheend)
Definition: ap.cpp:2635
int m
int trunc(double x)
Definition: ap.cpp:7248
bool fp_greater_eq(double v1, double v2)
Definition: ap.cpp:7321
const ae_int_t * operator[](ae_int_t i) const
Definition: ap.cpp:6579
ae_bool _ialglib_rmatrixrighttrsm(ae_int_t m, ae_int_t n, double *_a, ae_int_t _a_stride, ae_bool isupper, ae_bool isunit, ae_int_t optype, double *_x, ae_int_t _x_stride)
Definition: ap.cpp:9358
ae_vector ba
Definition: ap.h:838
ae_bool _ialglib_i_rmatrixlefttrsmf(ae_int_t m, ae_int_t n, ae_matrix *a, ae_int_t i1, ae_int_t j1, ae_bool isupper, ae_bool isunit, ae_int_t optype, ae_matrix *x, ae_int_t i2, ae_int_t j2)
Definition: ap.cpp:10008
void _ialglib_vcopy(ae_int_t n, const double *a, ae_int_t stridea, double *b, ae_int_t strideb)
Definition: ap.cpp:8627
int ifloor(double x)
Definition: ap.cpp:7251
double ae_acos(double x, ae_state *state)
Definition: ap.cpp:1664
void ae_serializer_ustart_str(ae_serializer *serializer, const char *buf)
Definition: ap.cpp:3473
double ae_sinh(double x, ae_state *state)
Definition: ap.cpp:1645
const char * in_str
Definition: ap.h:422
ae_bool _ialglib_i_rmatrixsyrkf(ae_int_t n, ae_int_t k, double alpha, ae_matrix *a, ae_int_t ia, ae_int_t ja, ae_int_t optypea, double beta, ae_matrix *c, ae_int_t ic, ae_int_t jc, ae_bool isupper)
Definition: ap.cpp:10039
#define len
ae_int_t ae_ifloor(double x, ae_state *state)
Definition: ap.cpp:1557
ae_int_t ae_iabs(ae_int_t x, ae_state *state)
Definition: ap.cpp:1525
virtual ~boolean_1d_array()
Definition: ap.cpp:6023
ae_complex * p_complex
Definition: ap.h:438
double ** pp_double
Definition: ap.h:455
ae_shared_pool_entry *volatile recycled_entries
Definition: ap.h:542
double abscomplex(const alglib::complex &z)
Definition: ap.cpp:4968
const alglib::complex operator+(const alglib::complex &lhs)
Definition: ap.cpp:4888
void ae_state_init(ae_state *state)
Definition: ap.cpp:309
#define x_nb
Definition: ap.cpp:55
void ae_shared_pool_destroy(void *_dst)
Definition: ap.cpp:3040
void ae_matrix_init_from_x(ae_matrix *dst, x_matrix *src, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:818
ae_int64_t cols
Definition: ap.h:305
#define AE_SM_FROM_STRING
Definition: ap.cpp:70
#define AE_CRITICAL_ASSERT(x)
Definition: ap.cpp:75
ae_bool _ialglib_cmatrixlefttrsm(ae_int_t m, ae_int_t n, ae_complex *_a, ae_int_t _a_stride, ae_bool isupper, ae_bool isunit, ae_int_t optype, ae_complex *_x, ae_int_t _x_stride)
Definition: ap.cpp:9442
double ae_sqrt(double x, ae_state *state)
Definition: ap.cpp:1535
void ae_assert(ae_bool cond, const char *msg, ae_state *state)
Definition: ap.cpp:1227
union alglib_impl::ae_vector::@11 ptr
signed long long ae_int64_t
Definition: ap.h:181
ae_int_t rows() const
Definition: ap.cpp:6419
const ae_int_t & operator()(ae_int_t i, ae_int_t j) const
Definition: ap.cpp:6569
ae_bool _ialglib_i_cmatrixrank1f(ae_int_t m, ae_int_t n, ae_matrix *a, ae_int_t ia, ae_int_t ja, ae_vector *u, ae_int_t uoffs, ae_vector *v, ae_int_t voffs)
Definition: ap.cpp:10055
const ae_int_t & operator[](ae_int_t i) const
Definition: ap.cpp:6113
int round(double x)
Definition: ap.cpp:7245
void ae_v_moveneg(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:4398
void ae_v_cmoveneg(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n)
Definition: ap.cpp:3915
ae_bool ae_isfinite_stateless(double x, ae_int_t endianness)
Definition: ap.cpp:1359
const double & operator[](ae_int_t i) const
Definition: ap.cpp:6189
void ae_serializer_alloc_start(ae_serializer *serializer)
Definition: ap.cpp:3404
const char *volatile error_msg
Definition: ap.h:389
const double maxrealnumber
Definition: ap.cpp:4691
const double fp_nan
Definition: ap.cpp:4694
T align(T number, uint32_t alignment)
ae_bool x_is_symmetric(x_matrix *a)
Definition: ap.cpp:2181
ae_bool _ialglib_rmatrixsyrk(ae_int_t n, ae_int_t k, double alpha, double *_a, ae_int_t _a_stride, ae_int_t optypea, double beta, double *_c, ae_int_t _c_stride, ae_bool isupper)
Definition: ap.cpp:9714
double vdotproduct(const double *v0, ae_int_t stride0, const double *v1, ae_int_t stride1, ae_int_t n)
Definition: ap.cpp:5004
double ae_atan(double x, ae_state *state)
Definition: ap.cpp:1669
void ae_yield()
Definition: ap.cpp:2748
double * getcontent()
Definition: ap.cpp:6207
bool isempty() const
Definition: ap.cpp:6433
complex & operator*=(const double &v)
Definition: ap.cpp:4762
ae_int_t entries_needed
Definition: ap.h:413
ae_bool _ialglib_i_cmatrixsyrkf(ae_int_t n, ae_int_t k, double alpha, ae_matrix *a, ae_int_t ia, ae_int_t ja, ae_int_t optypea, double beta, ae_matrix *c, ae_int_t ic, ae_int_t jc, ae_bool isupper)
Definition: ap.cpp:10023
ae_int64_t owner
Definition: ap.h:308
double ae_cosh(double x, ae_state *state)
Definition: ap.cpp:1650
ae_int64_t datatype
Definition: ap.h:307
ae_bool ae_str2bool(const char *buf, ae_state *state, const char **pasttheend)
Definition: ap.cpp:2400
double ae_exp(double x, ae_state *state)
Definition: ap.cpp:1689
void ae_x_attach_to_matrix(x_matrix *dst, ae_matrix *src)
Definition: ap.cpp:1197
double ae_tanh(double x, ae_state *state)
Definition: ap.cpp:1654
void ae_v_caddd(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha)
Definition: ap.cpp:4119
void assign(const ae_vector_wrapper &rhs)
Definition: ap.cpp:5962
void assign(const ae_matrix_wrapper &rhs)
Definition: ap.cpp:6371
std::string tostring(int dps) const
Definition: ap.cpp:6217
ae_complex ae_c_mul(ae_complex lhs, ae_complex rhs)
Definition: ap.cpp:3685
void *volatile seed_object
Definition: ap.h:525
char * filter_spaces(const char *s)
Definition: ap.cpp:6830
void vadd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:5416
ae_dyn_block *volatile p_top_block
Definition: ap.h:371
void _rcommstate_clear(rcommstate *p)
Definition: ap.cpp:4597
ptrdiff_t ae_int_t
Definition: ap.h:186
doublereal * u
void ae_v_subd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
Definition: ap.cpp:4533
ae_bool ae_vector_init(ae_vector *dst, ae_int_t size, ae_datatype datatype, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:580
double maxreal(double m1, double m2)
Definition: ap.cpp:7273
ae_int_t ae_maxint(ae_int_t m1, ae_int_t m2, ae_state *state)
Definition: ap.cpp:1567
ae_complex ae_c_mul_d(ae_complex lhs, double rhs)
Definition: ap.cpp:3749
void aligned_free(void *block)
Definition: ap.cpp:201
ae_bool ae_isfinite(double x, ae_state *state)
Definition: ap.cpp:1495
void ae_serializer_unserialize_bool(ae_serializer *serializer, ae_bool *v, ae_state *state)
Definition: ap.cpp:3584
double ae_sqr(double x, ae_state *state)
Definition: ap.cpp:1530
void ** pp_void
Definition: ap.h:452
#define AE_LOCK_CYCLES
Definition: ap.cpp:73
void setcontent(ae_int_t irows, ae_int_t icols, const double *pContent)
Definition: ap.cpp:6660
#define AE_LOCK_TESTS_BEFORE_YIELD
Definition: ap.cpp:74
void ae_serializer_alloc_entry(ae_serializer *serializer)
Definition: ap.cpp:3411
void * parent_task
Definition: ap.h:402
void ae_serializer_unserialize_double(ae_serializer *serializer, double *v, ae_state *state)
Definition: ap.cpp:3594
ae_int_t ae_cpuid()
Definition: ap.cpp:1247
void ae_init_lock(ae_lock *lock)
Definition: ap.cpp:2763
#define AE_SM_DEFAULT
Definition: ap.cpp:66
const alglib::complex & operator()(ae_int_t i) const
Definition: ap.cpp:6255
ae_complex ae_c_neg(ae_complex lhs)
Definition: ap.cpp:3615
void _ialglib_mm22x2(double alpha, const double *a, const double *b0, const double *b1, ae_int_t k, double beta, double *r, ae_int_t stride)
Definition: ap.cpp:10519
ae_dyn_block last_block
Definition: ap.h:372
ae_int64_t rows
Definition: ap.h:304
int sign(double x)
Definition: ap.cpp:7215
const real_1d_array & operator=(const real_1d_array &rhs)
Definition: ap.cpp:6169
void ae_v_addd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
Definition: ap.cpp:4479
ae_bool ae_vector_init_copy(ae_vector *dst, ae_vector *src, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:614
void ae_v_cmuld(ae_complex *vdst, ae_int_t stride_dst, ae_int_t n, double alpha)
Definition: ap.cpp:4283
bool fp_isnan(double x)
Definition: ap.cpp:7329
ae_bool ae_is_hermitian(ae_matrix *a)
Definition: ap.cpp:2256
ae_bool ae_fp_less_eq(double v1, double v2)
Definition: ap.cpp:1335
ae_int_t ae_round(double x, ae_state *state)
Definition: ap.cpp:1547
#define AE_DATA_ALIGN
Definition: ap.cpp:56
double v0
ae_int_t ae_get_endianness()
Definition: ap.cpp:1469
void _ialglib_mm22(double alpha, const double *a, const double *b, ae_int_t k, double beta, double *r, ae_int_t stride, ae_int_t store_mode)
Definition: ap.cpp:10276
alglib_impl::ae_int_t ae_int_t
Definition: ap.h:889
void allocate_own(ae_int_t size, alglib_impl::ae_datatype datatype)
Definition: ap.cpp:5898
ae_shared_pool_entry *volatile enumeration_counter
Definition: ap.h:545
ae_int_t * getcontent()
Definition: ap.cpp:6131
void ae_frame_leave(ae_state *state)
Definition: ap.cpp:415
void ae_matrix_clear(ae_matrix *dst)
Definition: ap.cpp:891
ae_bool(* init_copy)(void *dst, void *src, ae_state *state, ae_bool make_automatic)
Definition: ap.h:554
ae_int_t vlen(ae_int_t n1, ae_int_t n2)
Definition: ap.cpp:7770
double pi()
Definition: ap.cpp:7257
#define ae_true
Definition: ap.h:195
void setlength(ae_int_t rows, ae_int_t cols)
Definition: ap.cpp:6409
void *volatile ptr
Definition: ap.h:331
int * n
void ae_shared_pool_clear_recycled(ae_shared_pool *pool, ae_state *state)
Definition: ap.cpp:3256
ae_int_t cols() const
Definition: ap.cpp:6426
ae_bool ae_fp_greater(double v1, double v2)
Definition: ap.cpp:1343
void ae_smart_ptr_destroy(void *_dst)
Definition: ap.cpp:1015
std::string tostring(int dps) const
Definition: ap.cpp:6669
ae_int_t cnt
Definition: ap.h:429
ae_bool ae_matrix_set_length(ae_matrix *dst, ae_int_t rows, ae_int_t cols, ae_state *state)
Definition: ap.cpp:854
double y
Definition: ap.h:941
doublereal * a
double get_aenv_neginf()
Definition: ap.cpp:6784
void ae_x_set_vector(x_vector *dst, ae_vector *src, ae_state *state)
Definition: ap.cpp:1096
virtual ~real_2d_array()
Definition: ap.cpp:6636
double x
Definition: ap.h:941
void setcontent(ae_int_t iLen, const double *pContent)
Definition: ap.cpp:6199
ae_bool _ialglib_i_rmatrixrighttrsmf(ae_int_t m, ae_int_t n, ae_matrix *a, ae_int_t i1, ae_int_t j1, ae_bool isupper, ae_bool isunit, ae_int_t optype, ae_matrix *x, ae_int_t i2, ae_int_t j2)
Definition: ap.cpp:9978
ae_int_t ae_minint(ae_int_t m1, ae_int_t m2, ae_state *state)
Definition: ap.cpp:1572
void str_matrix_create(const char *src, std::vector< std::vector< const char *> > *p_mat)
Definition: ap.cpp:6881
void ae_free(void *p)
Definition: ap.cpp:237
ae_int_t ae_trunc(double x, ae_state *state)
Definition: ap.cpp:1552
void ae_foursixbits2threebytes(const ae_int_t *src, unsigned char *dst)
Definition: ap.cpp:2366
const ae_bool & operator()(ae_int_t i, ae_int_t j) const
Definition: ap.cpp:6498
const alglib::complex operator*(const alglib::complex &lhs, const alglib::complex &rhs)
Definition: ap.cpp:4912
float r1
double ae_atan2(double y, double x, ae_state *state)
Definition: ap.cpp:1674
double ae_v_dotproduct(const double *v0, ae_int_t stride0, const double *v1, ae_int_t stride1, ae_int_t n)
Definition: ap.cpp:4344
#define DYN_FRAME
Definition: ap.cpp:59
ae_int_t randominteger(ae_int_t maxv)
Definition: ap.cpp:7236
void create(const ae_vector_wrapper &rhs)
Definition: ap.cpp:5917
bool fp_isposinf(double x)
Definition: ap.cpp:7334
void _ialglib_mcopyunblock_complex(ae_int_t m, ae_int_t n, const double *a, ae_int_t op, ae_complex *b, ae_int_t stride)
Definition: ap.cpp:9046
void ae_v_cmovec(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, ae_complex alpha)
Definition: ap.cpp:4015
ae_int_t parse_int_delim(const char *s, const char *delim)
Definition: ap.cpp:6952