scs 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +84 -0
- data/ext/scs/Rakefile +11 -0
- data/lib/scs/ffi.rb +117 -0
- data/lib/scs/solver.rb +178 -0
- data/lib/scs/version.rb +3 -0
- data/lib/scs.rb +17 -0
- data/vendor/scs/LICENSE.txt +21 -0
- data/vendor/scs/Makefile +164 -0
- data/vendor/scs/README.md +220 -0
- data/vendor/scs/include/aa.h +56 -0
- data/vendor/scs/include/cones.h +46 -0
- data/vendor/scs/include/ctrlc.h +33 -0
- data/vendor/scs/include/glbopts.h +177 -0
- data/vendor/scs/include/linalg.h +26 -0
- data/vendor/scs/include/linsys.h +64 -0
- data/vendor/scs/include/normalize.h +18 -0
- data/vendor/scs/include/rw.h +17 -0
- data/vendor/scs/include/scs.h +161 -0
- data/vendor/scs/include/scs_blas.h +51 -0
- data/vendor/scs/include/util.h +65 -0
- data/vendor/scs/linsys/amatrix.c +305 -0
- data/vendor/scs/linsys/amatrix.h +36 -0
- data/vendor/scs/linsys/amatrix.o +0 -0
- data/vendor/scs/linsys/cpu/direct/private.c +366 -0
- data/vendor/scs/linsys/cpu/direct/private.h +26 -0
- data/vendor/scs/linsys/cpu/direct/private.o +0 -0
- data/vendor/scs/linsys/cpu/indirect/private.c +256 -0
- data/vendor/scs/linsys/cpu/indirect/private.h +31 -0
- data/vendor/scs/linsys/cpu/indirect/private.o +0 -0
- data/vendor/scs/linsys/external/amd/LICENSE.txt +934 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +469 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +254 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.o +0 -0
- data/vendor/scs/linsys/external/amd/amd.h +400 -0
- data/vendor/scs/linsys/external/amd/amd_1.c +180 -0
- data/vendor/scs/linsys/external/amd/amd_1.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_2.c +1842 -0
- data/vendor/scs/linsys/external/amd/amd_2.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_aat.c +184 -0
- data/vendor/scs/linsys/external/amd/amd_aat.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_control.c +64 -0
- data/vendor/scs/linsys/external/amd/amd_control.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_defaults.c +37 -0
- data/vendor/scs/linsys/external/amd/amd_defaults.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_dump.c +179 -0
- data/vendor/scs/linsys/external/amd/amd_dump.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_global.c +16 -0
- data/vendor/scs/linsys/external/amd/amd_global.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_info.c +119 -0
- data/vendor/scs/linsys/external/amd/amd_info.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_internal.h +304 -0
- data/vendor/scs/linsys/external/amd/amd_order.c +199 -0
- data/vendor/scs/linsys/external/amd/amd_order.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_post_tree.c +120 -0
- data/vendor/scs/linsys/external/amd/amd_post_tree.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_postorder.c +206 -0
- data/vendor/scs/linsys/external/amd/amd_postorder.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_preprocess.c +118 -0
- data/vendor/scs/linsys/external/amd/amd_preprocess.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_valid.c +92 -0
- data/vendor/scs/linsys/external/amd/amd_valid.o +0 -0
- data/vendor/scs/linsys/external/amd/changes +11 -0
- data/vendor/scs/linsys/external/qdldl/LICENSE +201 -0
- data/vendor/scs/linsys/external/qdldl/README.md +120 -0
- data/vendor/scs/linsys/external/qdldl/changes +4 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.c +298 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.h +177 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.o +0 -0
- data/vendor/scs/linsys/external/qdldl/qdldl_types.h +21 -0
- data/vendor/scs/linsys/gpu/gpu.c +41 -0
- data/vendor/scs/linsys/gpu/gpu.h +85 -0
- data/vendor/scs/linsys/gpu/indirect/private.c +304 -0
- data/vendor/scs/linsys/gpu/indirect/private.h +36 -0
- data/vendor/scs/scs.mk +181 -0
- data/vendor/scs/src/aa.c +224 -0
- data/vendor/scs/src/aa.o +0 -0
- data/vendor/scs/src/cones.c +802 -0
- data/vendor/scs/src/cones.o +0 -0
- data/vendor/scs/src/ctrlc.c +77 -0
- data/vendor/scs/src/ctrlc.o +0 -0
- data/vendor/scs/src/linalg.c +84 -0
- data/vendor/scs/src/linalg.o +0 -0
- data/vendor/scs/src/normalize.c +93 -0
- data/vendor/scs/src/normalize.o +0 -0
- data/vendor/scs/src/rw.c +167 -0
- data/vendor/scs/src/rw.o +0 -0
- data/vendor/scs/src/scs.c +975 -0
- data/vendor/scs/src/scs.o +0 -0
- data/vendor/scs/src/scs_version.c +5 -0
- data/vendor/scs/src/scs_version.o +0 -0
- data/vendor/scs/src/util.c +196 -0
- data/vendor/scs/src/util.o +0 -0
- data/vendor/scs/test/data/small_random_socp +0 -0
- data/vendor/scs/test/minunit.h +13 -0
- data/vendor/scs/test/problem_utils.h +93 -0
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +85 -0
- data/vendor/scs/test/problems/small_lp.h +50 -0
- data/vendor/scs/test/problems/small_random_socp.h +33 -0
- data/vendor/scs/test/random_socp_prob.c +171 -0
- data/vendor/scs/test/run_from_file.c +69 -0
- data/vendor/scs/test/run_tests +2 -0
- data/vendor/scs/test/run_tests.c +32 -0
- metadata +203 -0
@@ -0,0 +1,469 @@
|
|
1
|
+
/* ========================================================================== */
|
2
|
+
/* === SuiteSparse_config =================================================== */
|
3
|
+
/* ========================================================================== */
|
4
|
+
|
5
|
+
/* SuiteSparse configuration : memory manager and printf functions. */
|
6
|
+
|
7
|
+
/* Copyright (c) 2013, Timothy A. Davis. No licensing restrictions
|
8
|
+
* apply to this file or to the SuiteSparse_config directory.
|
9
|
+
* Author: Timothy A. Davis.
|
10
|
+
*/
|
11
|
+
|
12
|
+
#include <math.h>
|
13
|
+
#include <stdlib.h>
|
14
|
+
|
15
|
+
#ifndef NPRINT
|
16
|
+
#include <stdio.h>
|
17
|
+
#endif
|
18
|
+
|
19
|
+
#ifdef MATLAB_MEX_FILE
|
20
|
+
#include "mex.h"
|
21
|
+
#include "matrix.h"
|
22
|
+
#endif
|
23
|
+
|
24
|
+
#ifndef NULL
|
25
|
+
#define NULL ((void *) 0)
|
26
|
+
#endif
|
27
|
+
|
28
|
+
#include "SuiteSparse_config.h"
|
29
|
+
|
30
|
+
/* -------------------------------------------------------------------------- */
|
31
|
+
/* SuiteSparse_config : a global extern struct */
|
32
|
+
/* -------------------------------------------------------------------------- */
|
33
|
+
|
34
|
+
/* The SuiteSparse_config struct is available to all SuiteSparse functions and
|
35
|
+
to all applications that use those functions. It must be modified with
|
36
|
+
care, particularly in a multithreaded context. Normally, the application
|
37
|
+
will initialize this object once, via SuiteSparse_start, possibily followed
|
38
|
+
by application-specific modifications if the applications wants to use
|
39
|
+
alternative memory manager functions.
|
40
|
+
|
41
|
+
The user can redefine these global pointers at run-time to change the
|
42
|
+
memory manager and printf function used by SuiteSparse.
|
43
|
+
|
44
|
+
If -DNMALLOC is defined at compile-time, then no memory-manager is
|
45
|
+
specified. You must define them at run-time, after calling
|
46
|
+
SuiteSparse_start.
|
47
|
+
|
48
|
+
If -DPRINT is defined a compile time, then printf is disabled, and
|
49
|
+
SuiteSparse will not use printf.
|
50
|
+
*/
|
51
|
+
|
52
|
+
struct SuiteSparse_config_struct SuiteSparse_config =
|
53
|
+
{
|
54
|
+
_scs_malloc, _scs_calloc, _scs_realloc, _scs_free, _scs_printf,
|
55
|
+
SuiteSparse_hypot,
|
56
|
+
SuiteSparse_divcomplex
|
57
|
+
|
58
|
+
} ;
|
59
|
+
|
60
|
+
/* -------------------------------------------------------------------------- */
|
61
|
+
/* SuiteSparse_start */
|
62
|
+
/* -------------------------------------------------------------------------- */
|
63
|
+
|
64
|
+
/* All applications that use SuiteSparse should call SuiteSparse_start prior
|
65
|
+
to using any SuiteSparse function. Only a single thread should call this
|
66
|
+
function, in a multithreaded application. Currently, this function is
|
67
|
+
optional, since all this function currently does is to set the four memory
|
68
|
+
function pointers to NULL (which tells SuiteSparse to use the default
|
69
|
+
functions). In a multi- threaded application, only a single thread should
|
70
|
+
call this function.
|
71
|
+
|
72
|
+
Future releases of SuiteSparse might enforce a requirement that
|
73
|
+
SuiteSparse_start be called prior to calling any SuiteSparse function.
|
74
|
+
*/
|
75
|
+
|
76
|
+
void SuiteSparse_start ( void )
|
77
|
+
{
|
78
|
+
SuiteSparse_config.malloc_func = _scs_malloc ;
|
79
|
+
SuiteSparse_config.calloc_func = _scs_calloc ;
|
80
|
+
SuiteSparse_config.realloc_func = _scs_realloc ;
|
81
|
+
SuiteSparse_config.free_func = _scs_free ;
|
82
|
+
SuiteSparse_config.printf_func = _scs_printf ;
|
83
|
+
/* math functions */
|
84
|
+
SuiteSparse_config.hypot_func = SuiteSparse_hypot ;
|
85
|
+
SuiteSparse_config.divcomplex_func = SuiteSparse_divcomplex ;
|
86
|
+
}
|
87
|
+
|
88
|
+
/* -------------------------------------------------------------------------- */
|
89
|
+
/* SuiteSparse_finish */
|
90
|
+
/* -------------------------------------------------------------------------- */
|
91
|
+
|
92
|
+
/* This currently does nothing, but in the future, applications should call
|
93
|
+
SuiteSparse_start before calling any SuiteSparse function, and then
|
94
|
+
SuiteSparse_finish after calling the last SuiteSparse function, just before
|
95
|
+
exiting. In a multithreaded application, only a single thread should call
|
96
|
+
this function.
|
97
|
+
|
98
|
+
Future releases of SuiteSparse might use this function for any
|
99
|
+
SuiteSparse-wide cleanup operations or finalization of statistics.
|
100
|
+
*/
|
101
|
+
|
102
|
+
void SuiteSparse_finish ( void )
|
103
|
+
{
|
104
|
+
/* do nothing */ ;
|
105
|
+
}
|
106
|
+
|
107
|
+
/* -------------------------------------------------------------------------- */
|
108
|
+
/* SuiteSparse_malloc: malloc wrapper */
|
109
|
+
/* -------------------------------------------------------------------------- */
|
110
|
+
|
111
|
+
void *SuiteSparse_malloc /* pointer to allocated block of memory */
|
112
|
+
(
|
113
|
+
size_t nitems, /* number of items to malloc */
|
114
|
+
size_t size_of_item /* sizeof each item */
|
115
|
+
)
|
116
|
+
{
|
117
|
+
void *p ;
|
118
|
+
size_t size ;
|
119
|
+
if (nitems < 1) nitems = 1 ;
|
120
|
+
if (size_of_item < 1) size_of_item = 1 ;
|
121
|
+
size = nitems * size_of_item ;
|
122
|
+
|
123
|
+
if (size != ((scs_float) nitems) * size_of_item)
|
124
|
+
{
|
125
|
+
/* size_t overflow */
|
126
|
+
p = NULL ;
|
127
|
+
}
|
128
|
+
else
|
129
|
+
{
|
130
|
+
p = (void *) (SuiteSparse_config.malloc_func) (size) ;
|
131
|
+
}
|
132
|
+
return (p) ;
|
133
|
+
}
|
134
|
+
|
135
|
+
|
136
|
+
/* -------------------------------------------------------------------------- */
|
137
|
+
/* SuiteSparse_calloc: calloc wrapper */
|
138
|
+
/* -------------------------------------------------------------------------- */
|
139
|
+
|
140
|
+
void *SuiteSparse_calloc /* pointer to allocated block of memory */
|
141
|
+
(
|
142
|
+
size_t nitems, /* number of items to calloc */
|
143
|
+
size_t size_of_item /* sizeof each item */
|
144
|
+
)
|
145
|
+
{
|
146
|
+
void *p ;
|
147
|
+
size_t size ;
|
148
|
+
if (nitems < 1) nitems = 1 ;
|
149
|
+
if (size_of_item < 1) size_of_item = 1 ;
|
150
|
+
size = nitems * size_of_item ;
|
151
|
+
|
152
|
+
if (size != ((scs_float) nitems) * size_of_item)
|
153
|
+
{
|
154
|
+
/* size_t overflow */
|
155
|
+
p = NULL ;
|
156
|
+
}
|
157
|
+
else
|
158
|
+
{
|
159
|
+
p = (void *) (SuiteSparse_config.calloc_func) (nitems, size_of_item) ;
|
160
|
+
}
|
161
|
+
return (p) ;
|
162
|
+
}
|
163
|
+
|
164
|
+
/* -------------------------------------------------------------------------- */
|
165
|
+
/* SuiteSparse_realloc: realloc wrapper */
|
166
|
+
/* -------------------------------------------------------------------------- */
|
167
|
+
|
168
|
+
/* If p is non-NULL on input, it points to a previously allocated object of
|
169
|
+
size nitems_old * size_of_item. The object is reallocated to be of size
|
170
|
+
nitems_new * size_of_item. If p is NULL on input, then a new object of that
|
171
|
+
size is allocated. On success, a pointer to the new object is returned,
|
172
|
+
and ok is returned as 1. If the allocation fails, ok is set to 0 and a
|
173
|
+
pointer to the old (unmodified) object is returned.
|
174
|
+
*/
|
175
|
+
|
176
|
+
void *SuiteSparse_realloc /* pointer to reallocated block of memory, or
|
177
|
+
to original block if the realloc failed. */
|
178
|
+
(
|
179
|
+
size_t nitems_new, /* new number of items in the object */
|
180
|
+
size_t nitems_old, /* old number of items in the object */
|
181
|
+
size_t size_of_item, /* sizeof each item */
|
182
|
+
void *p, /* old object to reallocate */
|
183
|
+
int *ok /* 1 if successful, 0 otherwise */
|
184
|
+
)
|
185
|
+
{
|
186
|
+
size_t size ;
|
187
|
+
if (nitems_old < 1) nitems_old = 1 ;
|
188
|
+
if (nitems_new < 1) nitems_new = 1 ;
|
189
|
+
if (size_of_item < 1) size_of_item = 1 ;
|
190
|
+
size = nitems_new * size_of_item ;
|
191
|
+
|
192
|
+
if (size != ((scs_float) nitems_new) * size_of_item)
|
193
|
+
{
|
194
|
+
/* size_t overflow */
|
195
|
+
(*ok) = 0 ;
|
196
|
+
}
|
197
|
+
else if (p == NULL)
|
198
|
+
{
|
199
|
+
/* a fresh object is being allocated */
|
200
|
+
p = SuiteSparse_malloc (nitems_new, size_of_item) ;
|
201
|
+
(*ok) = (p != NULL) ;
|
202
|
+
}
|
203
|
+
else if (nitems_old == nitems_new)
|
204
|
+
{
|
205
|
+
/* the object does not change; do nothing */
|
206
|
+
(*ok) = 1 ;
|
207
|
+
}
|
208
|
+
else
|
209
|
+
{
|
210
|
+
/* change the size of the object from nitems_old to nitems_new */
|
211
|
+
void *pnew ;
|
212
|
+
pnew = (void *) (SuiteSparse_config.realloc_func) (p, size) ;
|
213
|
+
if (pnew == NULL)
|
214
|
+
{
|
215
|
+
if (nitems_new < nitems_old)
|
216
|
+
{
|
217
|
+
/* the attempt to reduce the size of the block failed, but
|
218
|
+
the old block is unchanged. So pretend to succeed. */
|
219
|
+
(*ok) = 1 ;
|
220
|
+
}
|
221
|
+
else
|
222
|
+
{
|
223
|
+
/* out of memory */
|
224
|
+
(*ok) = 0 ;
|
225
|
+
}
|
226
|
+
}
|
227
|
+
else
|
228
|
+
{
|
229
|
+
/* success */
|
230
|
+
p = pnew ;
|
231
|
+
(*ok) = 1 ;
|
232
|
+
}
|
233
|
+
}
|
234
|
+
return (p) ;
|
235
|
+
}
|
236
|
+
|
237
|
+
/* -------------------------------------------------------------------------- */
|
238
|
+
/* SuiteSparse_free: free wrapper */
|
239
|
+
/* -------------------------------------------------------------------------- */
|
240
|
+
|
241
|
+
void *SuiteSparse_free /* always returns NULL */
|
242
|
+
(
|
243
|
+
void *p /* block to free */
|
244
|
+
)
|
245
|
+
{
|
246
|
+
if (p)
|
247
|
+
{
|
248
|
+
(SuiteSparse_config.free_func) (p) ;
|
249
|
+
}
|
250
|
+
return (NULL) ;
|
251
|
+
}
|
252
|
+
|
253
|
+
|
254
|
+
/* -------------------------------------------------------------------------- */
|
255
|
+
/* SuiteSparse_tic: return current wall clock time */
|
256
|
+
/* -------------------------------------------------------------------------- */
|
257
|
+
|
258
|
+
/* Returns the number of seconds (tic [0]) and nanoseconds (tic [1]) since some
|
259
|
+
* unspecified but fixed time in the past. If no timer is installed, zero is
|
260
|
+
* returned. A scalar scs_float precision value for 'tic' could be used, but this
|
261
|
+
* might cause loss of precision because clock_getttime returns the time from
|
262
|
+
* some distant time in the past. Thus, an array of size 2 is used.
|
263
|
+
*
|
264
|
+
* The timer is enabled by default. To disable the timer, compile with
|
265
|
+
* -DNTIMER. If enabled on a POSIX C 1993 system, the timer requires linking
|
266
|
+
* with the -lrt library.
|
267
|
+
*
|
268
|
+
* example:
|
269
|
+
*
|
270
|
+
* scs_float tic [2], r, s, t ;
|
271
|
+
* SuiteSparse_tic (tic) ; // start the timer
|
272
|
+
* // do some work A
|
273
|
+
* t = SuiteSparse_toc (tic) ; // t is time for work A, in seconds
|
274
|
+
* // do some work B
|
275
|
+
* s = SuiteSparse_toc (tic) ; // s is time for work A and B, in seconds
|
276
|
+
* SuiteSparse_tic (tic) ; // restart the timer
|
277
|
+
* // do some work C
|
278
|
+
* r = SuiteSparse_toc (tic) ; // s is time for work C, in seconds
|
279
|
+
*
|
280
|
+
* A scs_float array of size 2 is used so that this routine can be more easily
|
281
|
+
* ported to non-POSIX systems. The caller does not rely on the POSIX
|
282
|
+
* <time.h> include file.
|
283
|
+
*/
|
284
|
+
|
285
|
+
#ifdef SUITESPARSE_TIMER_ENABLED
|
286
|
+
|
287
|
+
#include <time.h>
|
288
|
+
|
289
|
+
void SuiteSparse_tic
|
290
|
+
(
|
291
|
+
scs_float tic [2] /* output, contents undefined on input */
|
292
|
+
)
|
293
|
+
{
|
294
|
+
/* POSIX C 1993 timer, requires -librt */
|
295
|
+
struct timespec t ;
|
296
|
+
clock_gettime (CLOCK_MONOTONIC, &t) ;
|
297
|
+
tic [0] = (scs_float) (t.tv_sec) ;
|
298
|
+
tic [1] = (scs_float) (t.tv_nsec) ;
|
299
|
+
}
|
300
|
+
|
301
|
+
#else
|
302
|
+
|
303
|
+
void SuiteSparse_tic
|
304
|
+
(
|
305
|
+
scs_float tic [2] /* output, contents undefined on input */
|
306
|
+
)
|
307
|
+
{
|
308
|
+
/* no timer installed */
|
309
|
+
tic [0] = 0 ;
|
310
|
+
tic [1] = 0 ;
|
311
|
+
}
|
312
|
+
|
313
|
+
#endif
|
314
|
+
|
315
|
+
|
316
|
+
/* -------------------------------------------------------------------------- */
|
317
|
+
/* SuiteSparse_toc: return time since last tic */
|
318
|
+
/* -------------------------------------------------------------------------- */
|
319
|
+
|
320
|
+
/* Assuming SuiteSparse_tic is accurate to the nanosecond, this function is
|
321
|
+
* accurate down to the nanosecond for 2^53 nanoseconds since the last call to
|
322
|
+
* SuiteSparse_tic, which is sufficient for SuiteSparse (about 104 days). If
|
323
|
+
* additional accuracy is required, the caller can use two calls to
|
324
|
+
* SuiteSparse_tic and do the calculations differently.
|
325
|
+
*/
|
326
|
+
|
327
|
+
scs_float SuiteSparse_toc /* returns time in seconds since last tic */
|
328
|
+
(
|
329
|
+
scs_float tic [2] /* input, not modified from last call to SuiteSparse_tic */
|
330
|
+
)
|
331
|
+
{
|
332
|
+
scs_float toc [2] ;
|
333
|
+
SuiteSparse_tic (toc) ;
|
334
|
+
return ((toc [0] - tic [0]) + 1e-9 * (toc [1] - tic [1])) ;
|
335
|
+
}
|
336
|
+
|
337
|
+
|
338
|
+
/* -------------------------------------------------------------------------- */
|
339
|
+
/* SuiteSparse_time: return current wallclock time in seconds */
|
340
|
+
/* -------------------------------------------------------------------------- */
|
341
|
+
|
342
|
+
/* This function might not be accurate down to the nanosecond. */
|
343
|
+
|
344
|
+
scs_float SuiteSparse_time /* returns current wall clock time in seconds */
|
345
|
+
(
|
346
|
+
void
|
347
|
+
)
|
348
|
+
{
|
349
|
+
scs_float toc [2] ;
|
350
|
+
SuiteSparse_tic (toc) ;
|
351
|
+
return (toc [0] + 1e-9 * toc [1]) ;
|
352
|
+
}
|
353
|
+
|
354
|
+
|
355
|
+
/* -------------------------------------------------------------------------- */
|
356
|
+
/* SuiteSparse_version: return the current version of SuiteSparse */
|
357
|
+
/* -------------------------------------------------------------------------- */
|
358
|
+
|
359
|
+
int SuiteSparse_version
|
360
|
+
(
|
361
|
+
int version [3]
|
362
|
+
)
|
363
|
+
{
|
364
|
+
if (version != NULL)
|
365
|
+
{
|
366
|
+
version [0] = SUITESPARSE_MAIN_VERSION ;
|
367
|
+
version [1] = SUITESPARSE_SUB_VERSION ;
|
368
|
+
version [2] = SUITESPARSE_SUBSUB_VERSION ;
|
369
|
+
}
|
370
|
+
return (SUITESPARSE_VERSION) ;
|
371
|
+
}
|
372
|
+
|
373
|
+
/* -------------------------------------------------------------------------- */
|
374
|
+
/* SuiteSparse_hypot */
|
375
|
+
/* -------------------------------------------------------------------------- */
|
376
|
+
|
377
|
+
/* There is an equivalent routine called hypot in <math.h>, which conforms
|
378
|
+
* to ANSI C99. However, SuiteSparse does not assume that ANSI C99 is
|
379
|
+
* available. You can use the ANSI C99 hypot routine with:
|
380
|
+
*
|
381
|
+
* #include <math.h>
|
382
|
+
*i SuiteSparse_config.hypot_func = hypot ;
|
383
|
+
*
|
384
|
+
* Default value of the SuiteSparse_config.hypot_func pointer is
|
385
|
+
* SuiteSparse_hypot, defined below.
|
386
|
+
*
|
387
|
+
* s = hypot (x,y) computes s = sqrt (x*x + y*y) but does so more accurately.
|
388
|
+
* The NaN cases for the scs_float relops x >= y and x+y == x are safely ignored.
|
389
|
+
*
|
390
|
+
* Source: Algorithm 312, "Absolute value and square root of a complex number,"
|
391
|
+
* P. Friedland, Comm. ACM, vol 10, no 10, October 1967, page 665.
|
392
|
+
*/
|
393
|
+
|
394
|
+
scs_float SuiteSparse_hypot (scs_float x, scs_float y)
|
395
|
+
{
|
396
|
+
scs_float s, r ;
|
397
|
+
x = fabs (x) ;
|
398
|
+
y = fabs (y) ;
|
399
|
+
if (x >= y)
|
400
|
+
{
|
401
|
+
if (x + y == x)
|
402
|
+
{
|
403
|
+
s = x ;
|
404
|
+
}
|
405
|
+
else
|
406
|
+
{
|
407
|
+
r = y / x ;
|
408
|
+
s = x * sqrt (1.0 + r*r) ;
|
409
|
+
}
|
410
|
+
}
|
411
|
+
else
|
412
|
+
{
|
413
|
+
if (y + x == y)
|
414
|
+
{
|
415
|
+
s = y ;
|
416
|
+
}
|
417
|
+
else
|
418
|
+
{
|
419
|
+
r = x / y ;
|
420
|
+
s = y * sqrt (1.0 + r*r) ;
|
421
|
+
}
|
422
|
+
}
|
423
|
+
return (s) ;
|
424
|
+
}
|
425
|
+
|
426
|
+
/* -------------------------------------------------------------------------- */
|
427
|
+
/* SuiteSparse_divcomplex */
|
428
|
+
/* -------------------------------------------------------------------------- */
|
429
|
+
|
430
|
+
/* c = a/b where c, a, and b are complex. The real and imaginary parts are
|
431
|
+
* passed as separate arguments to this routine. The NaN case is ignored
|
432
|
+
* for the scs_float relop br >= bi. Returns 1 if the denominator is zero,
|
433
|
+
* 0 otherwise.
|
434
|
+
*
|
435
|
+
* This uses ACM Algo 116, by R. L. Smith, 1962, which tries to avoid
|
436
|
+
* underflow and overflow.
|
437
|
+
*
|
438
|
+
* c can be the same variable as a or b.
|
439
|
+
*
|
440
|
+
* Default value of the SuiteSparse_config.divcomplex_func pointer is
|
441
|
+
* SuiteSparse_divcomplex.
|
442
|
+
*/
|
443
|
+
|
444
|
+
int SuiteSparse_divcomplex
|
445
|
+
(
|
446
|
+
scs_float ar, scs_float ai, /* real and imaginary parts of a */
|
447
|
+
scs_float br, scs_float bi, /* real and imaginary parts of b */
|
448
|
+
scs_float *cr, scs_float *ci /* real and imaginary parts of c */
|
449
|
+
)
|
450
|
+
{
|
451
|
+
scs_float tr, ti, r, den ;
|
452
|
+
if (fabs (br) >= fabs (bi))
|
453
|
+
{
|
454
|
+
r = bi / br ;
|
455
|
+
den = br + r * bi ;
|
456
|
+
tr = (ar + ai * r) / den ;
|
457
|
+
ti = (ai - ar * r) / den ;
|
458
|
+
}
|
459
|
+
else
|
460
|
+
{
|
461
|
+
r = br / bi ;
|
462
|
+
den = r * br + bi ;
|
463
|
+
tr = (ar * r + ai) / den ;
|
464
|
+
ti = (ai * r - ar) / den ;
|
465
|
+
}
|
466
|
+
*cr = tr ;
|
467
|
+
*ci = ti ;
|
468
|
+
return (den == 0.) ;
|
469
|
+
}
|