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 }