1 module glob_opts;
2 
3 nothrow @nogc extern(C):
4 
5 /*
6    Define OSQP compiler flags
7  */
8 
9 // cmake generated compiler flags
10 //#include "osqp_configure.h"
11 import osqp_configure;
12 
13 /* DATA CUSTOMIZATIONS (depending on memory manager)-----------------------   */
14 
15 // We do not need memory allocation functions if EMBEDDED is enabled
16 version (EMBEDDED) {}
17 else {  // # ifndef EMBEDDED
18 /* define custom printfs and memory allocation (e.g. matlab/python) */
19   version (MATLAB)
20   {
21     // todo: not tested
22     // #   include "mex.h"
23     import mex;
24     static void* c_calloc(size_t num, size_t size) {
25     void *m = mxCalloc(num, size);
26       mexMakeMemoryPersistent(m);
27       return m;
28     }
29 
30     static void* c_malloc(size_t size) {
31       void *m = mxMalloc(size);
32       mexMakeMemoryPersistent(m);
33       return m;
34     }
35 
36     static void* c_realloc(void *ptr, size_t size) {
37       void *m = mxRealloc(ptr, size);
38       mexMakeMemoryPersistent(m);
39       return m;
40     }
41 
42     //#   define c_free mxFree
43     alias c_free = mxFree;    
44   }
45   else {   // elif defined PYTHON
46     version (PYTHON) 
47     {
48       // Define memory allocation for python. Note that in Python 2 memory manager
49       // Calloc is not implemented
50         import python;
51         //#   include <Python.h>
52         //#   define c_malloc PyMem_Malloc
53         alias c_malloc = PyMem_Malloc;
54         
55         // todo : not tested, review below
56 
57         /*
58         #   if PY_MAJOR_VERSION >= 3
59         #    define c_calloc PyMem_Calloc
60         #   else  // if PY_MAJOR_VERSION >= 3 
61         static void* c_calloc(size_t num, size_t size) {
62           void *m = PyMem_Malloc(num * size);
63           memset(m, 0, num * size);
64           return m;
65         }
66           #   endif  *//* if PY_MAJOR_VERSION >= 3 */
67           alias c_free = PyMem_Free;
68           alias c_realloc = PyMem_Realloc;
69           //#   define c_free PyMem_Free
70           //#   define c_realloc PyMem_Realloc
71     }
72     else {
73       version (OSQP_CUSTOM_MEMORY) {}
74       else {
75       /* If no custom memory allocator defined, use
76       * standard linux functions. Custom memory allocator definitions
77       * appear in the osqp_configure.d generated file. */
78           import core.stdc.stdlib;
79           alias c_malloc = malloc;
80           alias c_calloc = calloc;
81           alias c_free = free;
82           alias c_realloc = realloc;
83       }
84     }
85   }
86 }
87 
88 /* Use customized number representation -----------------------------------   */
89 version (DLONG)
90 {
91   alias c_int = long; /* for indices */
92 }
93 else { // standard integers
94   alias c_int = int;       /* for indices */
95 }
96 
97 version (DFLOAT)
98 {
99   alias c_float = float;  /* for numerical values  */
100 }
101 else {
102   alias c_float = double; /* for numerical values  */
103 }
104 
105 /* Use customized operations */
106 
107 //# ifndef c_absval
108 //#  define c_absval(x) (((x) < 0) ? -(x) : (x))
109 //# endif /* ifndef c_absval */
110 auto ref c_absval(T)(auto ref return T x) { return (x < 0) ? -x : x; }
111 
112 //# ifndef c_max
113 //#  define c_max(a, b) (((a) > (b)) ? (a) : (b))
114 //# endif /* ifndef c_max */
115 auto ref c_max(T)(auto ref return T a, auto ref return T b) { return (a > b) ? a : b; }
116 
117 //# ifndef c_min
118 //#  define c_min(a, b) (((a) < (b)) ? (a) : (b))
119 //# endif /* ifndef c_min */
120 auto ref c_min(T)(auto ref return T a, auto ref return T b) { return (a < b) ? a : b; }
121 
122 // Round x to the nearest multiple of N
123 //# ifndef c_roundmultiple
124 //#  define c_roundmultiple(x, N) ((x) + .5 * (N)-c_fmod((x) + .5 * (N), (N)))
125 //# endif /* ifndef c_roundmultiple */
126 auto ref c_roundmultiple(T)(auto ref return T x, auto ref return T N) { return x + .5 * N-c_fmod(x + .5 * N, N); }
127 
128 
129 /* Use customized functions -----------------------------------------------   */
130 
131 // todo : test EMBEDDED_1
132 version (EMBEDDED_1) {} // if EMBEDDED != 1
133 else {
134   import core.stdc.math;
135   version (DFLOAT){
136     //#define c_sqrt sqrtf
137     //#define c_fmod fmodf
138     alias c_sqrt = sqrtf;
139     alias c_fmod = fmodf;
140   }
141   else {
142     //#define c_sqrt sqrt
143     //#define c_fmod fmod
144     alias c_sqrt = sqrt;
145     alias c_fmod = fmod;
146   }
147 }
148 
149 import core.stdc.stdio;
150 alias c_print = printf; // todo : for SuiteSparse_config module
151 
152 version (PRINTING)
153 {
154   import core.stdc.stdio;
155   import core.stdc.string;
156 
157   version (MATLAB)
158   {
159     //define c_print mexPrintf
160     alias c_print = mexPrintf;
161     // The following trick slows down the performance a lot. Since many solvers
162     // actually
163     // call mexPrintf and immediately force print buffer flush
164     // otherwise messages don't appear until solver termination
165     // ugly because matlab does not provide a vprintf mex interface
166     // #include <stdarg.h>
167     // static int c_print(char *msg, ...)
168     // {
169     //   va_list argList;
170     //   va_start(argList, msg);
171     //   //message buffer
172     //   int bufferSize = 256;
173     //   char buffer[bufferSize];
174     //   vsnprintf(buffer,bufferSize-1, msg, argList);
175     //   va_end(argList);
176     //   int out = mexPrintf(buffer); //print to matlab display
177     //   mexEvalString("drawnow;");   // flush matlab print buffer
178     //   return out;
179     // }
180   }
181   else {
182     version (PYTHON)
183     {
184       //include <Python.h>
185       //#   define c_print PySys_WriteStdout
186       // todo : not tested
187       import python;
188       alias c_print = PySys_WriteStdout;
189     }
190     else {
191       version (R_LANG)
192       {        
193         //include <R_ext/Print.h>
194         //#   define c_print Rprintf
195         // todo : not tested
196         import R_ext.Print;
197         alias c_print = Rprintf;
198       }
199       else {
200         //define c_print printf
201         alias c_print = printf;
202       }
203     }
204   }  
205 
206   alias c_eprint = c_print;
207 
208   /* Print error macro */
209   //#  define c_eprint(...) c_print("ERROR in %s: ", __FUNCTION__); c_print(__VA_ARGS__); c_print("\n");
210   //void c_eprint(ref c_int a, ref c_int b) { c_print("ERROR in %s: ", __FUNCTION__); c_print(__VA_ARGS__); c_print("\n"); }
211 /*
212   import core.stdc.stdarg;
213   import core.vararg;  
214 
215   void c_eprint(char* a, ...) {
216     // We can't use hte following method because of
217     // Error: @nogc function glob_opts.c_eprint cannot call non-@nogc function core.stdc.stdarg.va_end
218     //va_list args;
219     //va_start(args, a);
220     // it's up to you to figure out the end of the list!
221     // isn't that fun?
222     //va_end(args);
223   
224     // todo : so I skip all arguments printing for now
225 
226     c_print("ERROR in %s: ", __FUNCTION__.ptr); 
227     //for (int i = 0; i < _arguments.length; i++) c_print(_arguments[i]);  // works only for extern (D) functions
228 
229   
230 
231     c_print("\n"); 
232   }*/
233 }