scs 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +84 -0
  5. data/ext/scs/Rakefile +11 -0
  6. data/lib/scs/ffi.rb +117 -0
  7. data/lib/scs/solver.rb +178 -0
  8. data/lib/scs/version.rb +3 -0
  9. data/lib/scs.rb +17 -0
  10. data/vendor/scs/LICENSE.txt +21 -0
  11. data/vendor/scs/Makefile +164 -0
  12. data/vendor/scs/README.md +220 -0
  13. data/vendor/scs/include/aa.h +56 -0
  14. data/vendor/scs/include/cones.h +46 -0
  15. data/vendor/scs/include/ctrlc.h +33 -0
  16. data/vendor/scs/include/glbopts.h +177 -0
  17. data/vendor/scs/include/linalg.h +26 -0
  18. data/vendor/scs/include/linsys.h +64 -0
  19. data/vendor/scs/include/normalize.h +18 -0
  20. data/vendor/scs/include/rw.h +17 -0
  21. data/vendor/scs/include/scs.h +161 -0
  22. data/vendor/scs/include/scs_blas.h +51 -0
  23. data/vendor/scs/include/util.h +65 -0
  24. data/vendor/scs/linsys/amatrix.c +305 -0
  25. data/vendor/scs/linsys/amatrix.h +36 -0
  26. data/vendor/scs/linsys/amatrix.o +0 -0
  27. data/vendor/scs/linsys/cpu/direct/private.c +366 -0
  28. data/vendor/scs/linsys/cpu/direct/private.h +26 -0
  29. data/vendor/scs/linsys/cpu/direct/private.o +0 -0
  30. data/vendor/scs/linsys/cpu/indirect/private.c +256 -0
  31. data/vendor/scs/linsys/cpu/indirect/private.h +31 -0
  32. data/vendor/scs/linsys/cpu/indirect/private.o +0 -0
  33. data/vendor/scs/linsys/external/amd/LICENSE.txt +934 -0
  34. data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +469 -0
  35. data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +254 -0
  36. data/vendor/scs/linsys/external/amd/SuiteSparse_config.o +0 -0
  37. data/vendor/scs/linsys/external/amd/amd.h +400 -0
  38. data/vendor/scs/linsys/external/amd/amd_1.c +180 -0
  39. data/vendor/scs/linsys/external/amd/amd_1.o +0 -0
  40. data/vendor/scs/linsys/external/amd/amd_2.c +1842 -0
  41. data/vendor/scs/linsys/external/amd/amd_2.o +0 -0
  42. data/vendor/scs/linsys/external/amd/amd_aat.c +184 -0
  43. data/vendor/scs/linsys/external/amd/amd_aat.o +0 -0
  44. data/vendor/scs/linsys/external/amd/amd_control.c +64 -0
  45. data/vendor/scs/linsys/external/amd/amd_control.o +0 -0
  46. data/vendor/scs/linsys/external/amd/amd_defaults.c +37 -0
  47. data/vendor/scs/linsys/external/amd/amd_defaults.o +0 -0
  48. data/vendor/scs/linsys/external/amd/amd_dump.c +179 -0
  49. data/vendor/scs/linsys/external/amd/amd_dump.o +0 -0
  50. data/vendor/scs/linsys/external/amd/amd_global.c +16 -0
  51. data/vendor/scs/linsys/external/amd/amd_global.o +0 -0
  52. data/vendor/scs/linsys/external/amd/amd_info.c +119 -0
  53. data/vendor/scs/linsys/external/amd/amd_info.o +0 -0
  54. data/vendor/scs/linsys/external/amd/amd_internal.h +304 -0
  55. data/vendor/scs/linsys/external/amd/amd_order.c +199 -0
  56. data/vendor/scs/linsys/external/amd/amd_order.o +0 -0
  57. data/vendor/scs/linsys/external/amd/amd_post_tree.c +120 -0
  58. data/vendor/scs/linsys/external/amd/amd_post_tree.o +0 -0
  59. data/vendor/scs/linsys/external/amd/amd_postorder.c +206 -0
  60. data/vendor/scs/linsys/external/amd/amd_postorder.o +0 -0
  61. data/vendor/scs/linsys/external/amd/amd_preprocess.c +118 -0
  62. data/vendor/scs/linsys/external/amd/amd_preprocess.o +0 -0
  63. data/vendor/scs/linsys/external/amd/amd_valid.c +92 -0
  64. data/vendor/scs/linsys/external/amd/amd_valid.o +0 -0
  65. data/vendor/scs/linsys/external/amd/changes +11 -0
  66. data/vendor/scs/linsys/external/qdldl/LICENSE +201 -0
  67. data/vendor/scs/linsys/external/qdldl/README.md +120 -0
  68. data/vendor/scs/linsys/external/qdldl/changes +4 -0
  69. data/vendor/scs/linsys/external/qdldl/qdldl.c +298 -0
  70. data/vendor/scs/linsys/external/qdldl/qdldl.h +177 -0
  71. data/vendor/scs/linsys/external/qdldl/qdldl.o +0 -0
  72. data/vendor/scs/linsys/external/qdldl/qdldl_types.h +21 -0
  73. data/vendor/scs/linsys/gpu/gpu.c +41 -0
  74. data/vendor/scs/linsys/gpu/gpu.h +85 -0
  75. data/vendor/scs/linsys/gpu/indirect/private.c +304 -0
  76. data/vendor/scs/linsys/gpu/indirect/private.h +36 -0
  77. data/vendor/scs/scs.mk +181 -0
  78. data/vendor/scs/src/aa.c +224 -0
  79. data/vendor/scs/src/aa.o +0 -0
  80. data/vendor/scs/src/cones.c +802 -0
  81. data/vendor/scs/src/cones.o +0 -0
  82. data/vendor/scs/src/ctrlc.c +77 -0
  83. data/vendor/scs/src/ctrlc.o +0 -0
  84. data/vendor/scs/src/linalg.c +84 -0
  85. data/vendor/scs/src/linalg.o +0 -0
  86. data/vendor/scs/src/normalize.c +93 -0
  87. data/vendor/scs/src/normalize.o +0 -0
  88. data/vendor/scs/src/rw.c +167 -0
  89. data/vendor/scs/src/rw.o +0 -0
  90. data/vendor/scs/src/scs.c +975 -0
  91. data/vendor/scs/src/scs.o +0 -0
  92. data/vendor/scs/src/scs_version.c +5 -0
  93. data/vendor/scs/src/scs_version.o +0 -0
  94. data/vendor/scs/src/util.c +196 -0
  95. data/vendor/scs/src/util.o +0 -0
  96. data/vendor/scs/test/data/small_random_socp +0 -0
  97. data/vendor/scs/test/minunit.h +13 -0
  98. data/vendor/scs/test/problem_utils.h +93 -0
  99. data/vendor/scs/test/problems/rob_gauss_cov_est.h +85 -0
  100. data/vendor/scs/test/problems/small_lp.h +50 -0
  101. data/vendor/scs/test/problems/small_random_socp.h +33 -0
  102. data/vendor/scs/test/random_socp_prob.c +171 -0
  103. data/vendor/scs/test/run_from_file.c +69 -0
  104. data/vendor/scs/test/run_tests +2 -0
  105. data/vendor/scs/test/run_tests.c +32 -0
  106. 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
+ }