1 /* ========================================================================== */
2 /* === SuiteSparse_config =================================================== */
3 /* ========================================================================== */
4 
5 /* Configuration file for SuiteSparse: a Suite of Sparse matrix packages
6  * (AMD, COLAMD, CCOLAMD, CAMD, CHOLMOD, UMFPACK, CXSparse, and others).
7  *
8  * SuiteSparse_config.h provides the definition of the long integer.  On most
9  * systems, a C program can be compiled in LP64 mode, in which long's and
10  * pointers are both 64-bits, and int's are 32-bits.  Windows 64, however, uses
11  * the LLP64 model, in which int's and long's are 32-bits, and long long's and
12  * pointers are 64-bits.
13  *
14  * SuiteSparse packages that include long integer versions are
15  * intended for the LP64 mode.  However, as a workaround for Windows 64
16  * (and perhaps other systems), the long integer can be redefined.
17  *
18  * If _WIN64 is defined, then the __int64 type is used instead of long.
19  *
20  * The long integer can also be defined at compile time.  For example, this
21  * could be added to SuiteSparse_config.mk:
22  *
23  * CFLAGS = -O -D'SuiteSparse_long=long long' \
24  *  -D'SuiteSparse_long_max=9223372036854775801' -D'SuiteSparse_long_idd="lld"'
25  *
26  * This file defines SuiteSparse_long as either long (on all but _WIN64) or
27  * __int64 on Windows 64.  The intent is that a SuiteSparse_long is always a
28  * 64-bit integer in a 64-bit code.  ptrdiff_t might be a better choice than
29  * long; it is always the same size as a pointer.
30  *
31  * This file also defines the SUITESPARSE_VERSION and related definitions.
32  *
33  * Copyright (c) 2012, Timothy A. Davis.  No licensing restrictions apply
34  * to this file or to the SuiteSparse_config directory.
35  * Author: Timothy A. Davis.
36  */
37 
38 
39 /* SuiteSparse configuration : memory manager and printf functions. */
40 
41 /* Copyright (c) 2013, Timothy A. Davis.  No licensing restrictions
42  * apply to this file or to the SuiteSparse_config directory.
43  * Author: Timothy A. Davis.
44  */
45 
46 module SuiteSparse_config;
47 
48 nothrow @nogc extern(C):
49 
50 // Include OSQP Global options for memory management
51 import glob_opts;
52 
53 version (EMBEDDED){
54   import osqp_configure; // for c_malloc and others
55 }
56 
57 import core.stdc.math;
58 import core.stdc.stdlib;
59 import core.stdc.stdio;
60 import core.stdc.limits;
61 //#ifndef NPRINT
62 //#include <stdio.h>
63 //#endif
64 
65 version(MATLAB){
66     //#include "mex.h"
67     //#include "matrix.h"
68     import mex;
69     import matrix;
70 }
71 
72 // todo: How do i check ifndef NULL ?
73 //#ifndef NULL
74 //#define NULL ((void *) 0)
75 //enum void * NULL = (cast(void *) 0);
76 //#endif
77 
78 /* ========================================================================== */
79 /* === SuiteSparse_long ===================================================== */
80 /* ========================================================================== */
81 
82 alias SuiteSparse_long = long;
83 enum long SuiteSparse_long_max = LONG_MAX;
84 enum string SuiteSparse_long_idd = "ld";
85 
86 // todo: review it
87 //#define SuiteSparse_long_id "%" SuiteSparse_long_idd
88 
89 
90 
91 /* ========================================================================== */
92 /* === SuiteSparse_config parameters and functions ========================== */
93 /* ========================================================================== */
94 
95 /* SuiteSparse-wide parameters are placed in this struct.  It is meant to be
96    an extern, globally-accessible struct.  It is not meant to be updated
97    frequently by multiple threads.  Rather, if an application needs to modify
98    SuiteSparse_config, it should do it once at the beginning of the application,
99    before multiple threads are launched.
100 
101    The intent of these function pointers is that they not be used in your
102    application directly, except to assign them to the desired user-provided
103    functions.  Rather, you should use the
104  */
105 
106 alias malloc_func_t = void* function(size_t);
107 alias realloc_func_t = void* function(void*, size_t);
108 alias free_func_t = void function(void*);
109 alias printf_func_t = int function(const char*, ...);
110 alias hypot_func_t = c_float function(c_float, c_float);
111 alias divcomplex_func_t = int function(c_float, c_float, c_float, c_float, c_float*, c_float*);
112 
113 struct SuiteSparse_config_struct
114 {
115     malloc_func_t malloc_func;      // pointer to malloc
116     realloc_func_t realloc_func;    // pointer to realloc
117     free_func_t free_func;          // pointer to free             
118     printf_func_t printf_func;      // pointer to printf
119     hypot_func_t hypot_func;        // pointer to hypot
120     divcomplex_func_t divcomplex_func;
121 };
122 
123 //extern struct SuiteSparse_config_struct SuiteSparse_config ;
124 
125 /* OSQP: disabling this timing code */
126 //#define NTIMER
127 
128 /* determine which timer to use, if any */
129 /*#ifndef NTIMER
130 #ifdef _POSIX_C_SOURCE
131 #if    _POSIX_C_SOURCE >= 199309L
132 #define SUITESPARSE_TIMER_ENABLED
133 #endif
134 #endif
135 #endif
136 */
137 
138 /* SuiteSparse printf macro */
139 /*#define SUITESPARSE_PRINTF(params) \
140 { \
141     if (SuiteSparse_config.printf_func != NULL) \
142     { \
143         (void) (SuiteSparse_config.printf_func) params ; \
144     } \
145 }*/
146 alias SUITESPARSE_PRINTF = c_print;
147 
148 /* ========================================================================== */
149 /* === SuiteSparse version ================================================== */
150 /* ========================================================================== */
151 
152 /* SuiteSparse is not a package itself, but a collection of packages, some of
153  * which must be used together (UMFPACK requires AMD, CHOLMOD requires AMD,
154  * COLAMD, CAMD, and CCOLAMD, etc).  A version number is provided here for the
155  * collection itself.  The versions of packages within each version of
156  * SuiteSparse are meant to work together.  Combining one package from one
157  * version of SuiteSparse, with another package from another version of
158  * SuiteSparse, may or may not work.
159  *
160  * SuiteSparse contains the following packages:
161  *
162  *  SuiteSparse_config version 4.5.3 (version always the same as SuiteSparse)
163  *  AMD             version 2.4.6
164  *  BTF             version 1.2.6
165  *  CAMD            version 2.4.6
166  *  CCOLAMD         version 2.9.6
167  *  CHOLMOD         version 3.0.11
168  *  COLAMD          version 2.9.6
169  *  CSparse         version 3.1.9
170  *  CXSparse        version 3.1.9
171  *  GPUQREngine     version 1.0.5
172  *  KLU             version 1.3.8
173  *  LDL             version 2.2.6
174  *  RBio            version 2.2.6
175  *  SPQR            version 2.0.7
176  *  SuiteSparse_GPURuntime  version 1.0.5
177  *  UMFPACK         version 5.7.6
178  *  MATLAB_Tools    various packages & M-files
179  *  xerbla          version 1.0.3
180  *
181  * Other package dependencies:
182  *  BLAS            required by CHOLMOD and UMFPACK
183  *  LAPACK          required by CHOLMOD
184  *  METIS 5.1.0     required by CHOLMOD (optional) and KLU (optional)
185  *  CUBLAS, CUDART  NVIDIA libraries required by CHOLMOD and SPQR when
186  *                  they are compiled with GPU acceleration.
187  */
188 
189 
190 /* Versions prior to 4.2.0 do not have the above function.  The following
191    code fragment will work with any version of SuiteSparse:
192 
193    #ifdef SUITESPARSE_HAS_VERSION_FUNCTION
194    v = SuiteSparse_version (NULL) ;
195    #else
196    v = SUITESPARSE_VERSION ;
197    #endif
198 */
199 //#define SUITESPARSE_HAS_VERSION_FUNCTION
200 
201 enum string SUITESPARSE_DATE = "May 4, 2016";
202 //#define SUITESPARSE_VER_CODE(main,sub) ((main) * 1000 + (sub))
203 c_int SUITESPARSE_VER_CODE(c_int main, c_int sub) {return (main) * 1000 + (sub);}
204 enum c_int SUITESPARSE_MAIN_VERSION = 4;
205 enum c_int SUITESPARSE_SUB_VERSION = 5;
206 enum c_int SUITESPARSE_SUBSUB_VERSION = 3;
207 //#define SUITESPARSE_VERSION SUITESPARSE_VER_CODE(SUITESPARSE_MAIN_VERSION,SUITESPARSE_SUB_VERSION)
208 enum c_int SUITESPARSE_VERSION = SUITESPARSE_VER_CODE(SUITESPARSE_MAIN_VERSION,SUITESPARSE_SUB_VERSION);
209 
210 
211 /* -------------------------------------------------------------------------- */
212 /* SuiteSparse_config : a global extern struct */
213 /* -------------------------------------------------------------------------- */
214 
215 /* The SuiteSparse_config struct is available to all SuiteSparse functions and
216     to all applications that use those functions.  It must be modified with
217     care, particularly in a multithreaded context.  Normally, the application
218     will initialize this object once, via SuiteSparse_start, possibily followed
219     by application-specific modifications if the applications wants to use
220     alternative memory manager functions.
221 
222     The user can redefine these global pointers at run-time to change the
223     memory manager and printf function used by SuiteSparse.
224 
225     If -DNMALLOC is defined at compile-time, then no memory-manager is
226     specified.  You must define them at run-time, after calling
227     SuiteSparse_start.
228 
229     If -DPRINT is defined a compile time, then printf is disabled, and
230     SuiteSparse will not use printf.
231  */
232 
233 version(PRINTING){
234     SuiteSparse_config_struct SuiteSparse_config =
235     {
236         // Memory allocation from glob_opts.h in OSQP
237         &c_malloc, &c_realloc, &c_free, 
238         
239         &c_print,
240 
241         &SuiteSparse_hypot,
242         &SuiteSparse_divcomplex
243     };
244 } else {
245     SuiteSparse_config_struct SuiteSparse_config =
246     {
247         // Memory allocation from glob_opts.h in OSQP
248         &c_malloc, &c_realloc, &c_free,
249         null,
250         &SuiteSparse_hypot,
251         &SuiteSparse_divcomplex        
252     };
253 }
254 
255 /* -------------------------------------------------------------------------- */
256 /* SuiteSparse_malloc: malloc wrapper */
257 /* -------------------------------------------------------------------------- */
258 
259 void *SuiteSparse_malloc    /* pointer to allocated block of memory */
260 (
261     size_t nitems,          /* number of items to malloc */
262     size_t size_of_item     /* sizeof each item */
263 )
264 {
265     void *p ;
266     size_t size ;
267     if (nitems < 1) nitems = 1 ;
268     if (size_of_item < 1) size_of_item = 1 ;
269     size = nitems * size_of_item  ;
270 
271     if (size != (cast(c_float) nitems) * size_of_item)
272     {
273         /* size_t overflow */
274         //p = NULL ;
275         p = null;
276     }
277     else
278     {
279         p = cast(void *)(SuiteSparse_config.malloc_func(size));
280         //p = cast(void *) c_malloc(size) ; // todo
281     }
282     return (p) ;
283 }
284 
285 
286 
287 /* -------------------------------------------------------------------------- */
288 /* SuiteSparse_realloc: realloc wrapper */
289 /* -------------------------------------------------------------------------- */
290 
291 /* If p is non-NULL on input, it points to a previously allocated object of
292    size nitems_old * size_of_item.  The object is reallocated to be of size
293    nitems_new * size_of_item.  If p is NULL on input, then a new object of that
294    size is allocated.  On success, a pointer to the new object is returned,
295    and ok is returned as 1.  If the allocation fails, ok is set to 0 and a
296    pointer to the old (unmodified) object is returned.
297  */
298 
299 void *SuiteSparse_realloc   /* pointer to reallocated block of memory, or
300                                to original block if the realloc failed. */
301 (
302     size_t nitems_new,      /* new number of items in the object */
303     size_t nitems_old,      /* old number of items in the object */
304     size_t size_of_item,    /* sizeof each item */
305     void *p,                /* old object to reallocate */
306     int *ok                 /* 1 if successful, 0 otherwise */
307 )
308 {
309     size_t size ;
310     if (nitems_old < 1) nitems_old = 1 ;
311     if (nitems_new < 1) nitems_new = 1 ;
312     if (size_of_item < 1) size_of_item = 1 ;
313     size = nitems_new * size_of_item  ;
314 
315     if (size != (cast(c_float) nitems_new) * size_of_item)
316     {
317         /* size_t overflow */
318         (*ok) = 0 ;
319     }
320     else if (p == null) // todo : NULL
321     {
322         /* a fresh object is being allocated */
323         p = SuiteSparse_malloc (nitems_new, size_of_item) ;
324         (*ok) = (p != null) ; // todo : NULL
325     }
326     else if (nitems_old == nitems_new)
327     {
328         /* the object does not change; do nothing */
329         (*ok) = 1 ;
330     }
331     else
332     {
333         /* change the size of the object from nitems_old to nitems_new */
334         void *pnew ;
335         // pnew = (void *) (SuiteSparse_config.realloc_func) (p, size) ;
336         pnew = cast(void *) c_realloc (p, size) ;
337         if (pnew == null)// todo : NULL
338         {
339             if (nitems_new < nitems_old)
340             {
341                 /* the attempt to reduce the size of the block failed, but
342                    the old block is unchanged.  So pretend to succeed. */
343                 (*ok) = 1 ;
344             }
345             else
346             {
347                 /* out of memory */
348                 (*ok) = 0 ;
349             }
350         }
351         else
352         {
353             /* success */
354             p = pnew ;
355             (*ok) = 1 ;
356         }
357     }
358     return (p) ;
359 }
360 
361 /* -------------------------------------------------------------------------- */
362 /* SuiteSparse_free: free wrapper */
363 /* -------------------------------------------------------------------------- */
364 
365 void *SuiteSparse_free      /* always returns NULL */
366 (
367     void *p                 /* block to free */
368 )
369 {
370     if (p)
371     {
372         //cast(SuiteSparse_config.free_func) p ;
373         c_free(p) ;  // todo : i had to get rid of SuiteSparse_config variable in D
374         // because of error
375         // function core.stdc.stdlib.malloc(ulong size) is not callable using argument types () ../lin_sys/direct/qdldl/amd/src/SuiteSparse_config.d(266):   missing argument for parameter #1: ulong size
376     }
377     return (null) ;
378 }
379 
380 
381 /* -------------------------------------------------------------------------- */
382 /* SuiteSparse_tic: return current wall clock time */
383 /* -------------------------------------------------------------------------- */
384 
385 /* Returns the number of seconds (tic [0]) and nanoseconds (tic [1]) since some
386  * unspecified but fixed time in the past.  If no timer is installed, zero is
387  * returned.  A scalar c_float precision value for 'tic' could be used, but this
388  * might cause loss of precision because clock_getttime returns the time from
389  * some distant time in the past.  Thus, an array of size 2 is used.
390  *
391  * The timer is enabled by default.  To disable the timer, compile with
392  * -DNTIMER.  If enabled on a POSIX C 1993 system, the timer requires linking
393  * with the -lrt library.
394  *
395  * example:
396  *
397  *      c_float tic [2], r, s, t ;
398  *      SuiteSparse_tic (tic) ;     // start the timer
399  *      // do some work A
400  *      t = SuiteSparse_toc (tic) ; // t is time for work A, in seconds
401  *      // do some work B
402  *      s = SuiteSparse_toc (tic) ; // s is time for work A and B, in seconds
403  *      SuiteSparse_tic (tic) ;     // restart the timer
404  *      // do some work C
405  *      r = SuiteSparse_toc (tic) ; // s is time for work C, in seconds
406  *
407  * A c_float array of size 2 is used so that this routine can be more easily
408  * ported to non-POSIX systems.  The caller does not rely on the POSIX
409  * <time.h> include file.
410  */
411 /*
412 #ifdef SUITESPARSE_TIMER_ENABLED
413 
414 #include <time.h>
415 
416 void SuiteSparse_tic
417 (
418     c_float tic [2]      // output, contents undefined on input
419 )
420 {
421     // POSIX C 1993 timer, requires -librt
422     struct timespec t ;
423     clock_gettime (CLOCK_MONOTONIC, &t) ;
424     tic [0] = (c_float) (t.tv_sec) ;
425     tic [1] = (c_float) (t.tv_nsec) ;
426 }
427 
428 #else
429 */
430 
431 void SuiteSparse_tic
432 (
433     c_float [2] tic      /* output, contents undefined on input */
434 )
435 {
436     /* no timer installed */
437     tic [0] = 0 ;
438     tic [1] = 0 ;
439 }
440 
441 //#endif
442 
443 
444 /* -------------------------------------------------------------------------- */
445 /* SuiteSparse_toc: return time since last tic */
446 /* -------------------------------------------------------------------------- */
447 
448 /* Assuming SuiteSparse_tic is accurate to the nanosecond, this function is
449  * accurate down to the nanosecond for 2^53 nanoseconds since the last call to
450  * SuiteSparse_tic, which is sufficient for SuiteSparse (about 104 days).  If
451  * additional accuracy is required, the caller can use two calls to
452  * SuiteSparse_tic and do the calculations differently.
453  */
454 
455 c_float SuiteSparse_toc  /* returns time in seconds since last tic */
456 (
457     c_float [2] tic  /* input, not modified from last call to SuiteSparse_tic */
458 )
459 {
460     c_float [2]toc ;
461     SuiteSparse_tic (toc) ;
462     return ((toc [0] - tic [0]) + 1e-9 * (toc [1] - tic [1])) ;
463 }
464 
465 
466 /* -------------------------------------------------------------------------- */
467 /* SuiteSparse_time: return current wallclock time in seconds */
468 /* -------------------------------------------------------------------------- */
469 
470 /* This function might not be accurate down to the nanosecond. */
471 
472 c_float SuiteSparse_time  /* returns current wall clock time in seconds */
473 (
474     //void
475 )
476 {
477     c_float [2]toc ;
478     SuiteSparse_tic (toc) ;
479     return (toc [0] + 1e-9 * toc [1]) ;
480 }
481 
482 
483 /* -------------------------------------------------------------------------- */
484 /* SuiteSparse_version: return the current version of SuiteSparse */
485 /* -------------------------------------------------------------------------- */
486 
487 int SuiteSparse_version
488 (
489     int [3] _version
490 )
491 {
492     if (_version != cast(int[])null)
493     {
494         _version [0] = SUITESPARSE_MAIN_VERSION ;
495         _version [1] = SUITESPARSE_SUB_VERSION ;
496         _version [2] = SUITESPARSE_SUBSUB_VERSION ;
497     }
498     return (SUITESPARSE_VERSION) ;
499 }
500 
501 /* -------------------------------------------------------------------------- */
502 /* SuiteSparse_hypot */
503 /* -------------------------------------------------------------------------- */
504 
505 /* There is an equivalent routine called hypot in <math.h>, which conforms
506  * to ANSI C99.  However, SuiteSparse does not assume that ANSI C99 is
507  * available.  You can use the ANSI C99 hypot routine with:
508  *
509  *      #include <math.h>
510  *i     SuiteSparse_config.hypot_func = hypot ;
511  *
512  * Default value of the SuiteSparse_config.hypot_func pointer is
513  * SuiteSparse_hypot, defined below.
514  *
515  * s = hypot (x,y) computes s = sqrt (x*x + y*y) but does so more accurately.
516  * The NaN cases for the c_float relops x >= y and x+y == x are safely ignored.
517  *
518  * Source: Algorithm 312, "Absolute value and square root of a complex number,"
519  * P. Friedland, Comm. ACM, vol 10, no 10, October 1967, page 665.
520  */
521 
522 c_float SuiteSparse_hypot (c_float x, c_float y)
523 {
524     c_float s, r ;
525     x = fabs (x) ;
526     y = fabs (y) ;
527     if (x >= y)
528     {
529         if (x + y == x)
530         {
531             s = x ;
532         }
533         else
534         {
535             r = y / x ;
536             s = x * sqrt (1.0 + r*r) ;
537         }
538     }
539     else
540     {
541         if (y + x == y)
542         {
543             s = y ;
544         }
545         else
546         {
547             r = x / y ;
548             s = y * sqrt (1.0 + r*r) ;
549         }
550     }
551     return (s) ;
552 }
553 
554 /* -------------------------------------------------------------------------- */
555 /* SuiteSparse_divcomplex */
556 /* -------------------------------------------------------------------------- */
557 
558 /* c = a/b where c, a, and b are complex.  The real and imaginary parts are
559  * passed as separate arguments to this routine.  The NaN case is ignored
560  * for the c_float relop br >= bi.  Returns 1 if the denominator is zero,
561  * 0 otherwise.
562  *
563  * This uses ACM Algo 116, by R. L. Smith, 1962, which tries to avoid
564  * underflow and overflow.
565  *
566  * c can be the same variable as a or b.
567  *
568  * Default value of the SuiteSparse_config.divcomplex_func pointer is
569  * SuiteSparse_divcomplex.
570  */
571 
572 int SuiteSparse_divcomplex
573 (
574     c_float ar, c_float ai,       /* real and imaginary parts of a */
575     c_float br, c_float bi,       /* real and imaginary parts of b */
576     c_float *cr, c_float *ci      /* real and imaginary parts of c */
577 )
578 {
579     c_float tr, ti, r, den ;
580     if (fabs (br) >= fabs (bi))
581     {
582         r = bi / br ;
583         den = br + r * bi ;
584         tr = (ar + ai * r) / den ;
585         ti = (ai - ar * r) / den ;
586     }
587     else
588     {
589         r = br / bi ;
590         den = r * br + bi ;
591         tr = (ar * r + ai) / den ;
592         ti = (ai * r - ar) / den ;
593     }
594     *cr = tr ;
595     *ci = ti ;
596     return (den == 0.) ;
597 }