1 /*
2 * This file is part of MPSolve 3.2.1
3 *
4 * Copyright (C) 2001-2020, Dipartimento di Matematica "L. Tonelli", Pisa.
5 * License: http://www.gnu.org/licenses/gpl.html GPL version 3 or higher
6 *
7 * Authors:
8 * Dario Andrea Bini <bini@dm.unipi.it>
9 * Giuseppe Fiorentino <fiorent@dm.unipi.it>
10 * Leonardo Robol <leonardo.robol@unipi.it>
11 */
12
13
14 #include <mps/mps.h>
15 #include <mps/link.h>
16 #include <gmp.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <assert.h>
21
22 #ifdef MPS_CATCH_FPE
23 #include <fenv.h>
24 int feenableexcept (int excepts);
25 #endif
26
27 #if HAVE_CONFIG_H
28 # include <config.h>
29 #endif
30 #undef malloc
31 #undef realloc
32
33 void *malloc (size_t n);
34 void *realloc (void * ptr, size_t n);
35
36 /**
37 * @brief Perform some preliminary checks and setup before starting the real
38 * MPSolve loop.
39 */
40 static void
mps_preliminary_setup(mps_context * ctx)41 mps_preliminary_setup (mps_context * ctx)
42 {
43 /* Make sure that non thread safe polynomial implementations are handled
44 * in a safe way. */
45 if (!ctx->active_poly->thread_safe)
46 {
47 mps_thread_pool_set_concurrency_limit (ctx, NULL, 1);
48 }
49 }
50
51 /**
52 * @brief Call the real polynomial (or secular equation, or whatever) solver
53 * and do the computation.
54 *
55 * The algorithm used must be selected before this call with <code>mps_select_algorithm</code>
56 * and the data (the coefficients, or whatever the algorithm may require) should be provided
57 * after that.
58 *
59 * Roots can then be obtained with the functions <code>mps_context_get_roots_*</code>
60 *
61 */
62 void
mps_mpsolve(mps_context * s)63 mps_mpsolve (mps_context * s)
64 {
65 #ifdef MPS_CATCH_FPE
66 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
67 #endif
68
69 if (mps_context_has_errors (s))
70 return;
71
72 mps_preliminary_setup (s);
73
74 (*s->mpsolve_ptr)(s);
75 }
76
77 static void*
mps_caller(mps_context * s)78 mps_caller (mps_context * s)
79 {
80 if (!mps_context_has_errors (s))
81 {
82 mps_preliminary_setup (s);
83 s->mpsolve_ptr (s);
84 }
85
86 /* Call user defined callback if available */
87 if (s->callback == NULL)
88 return NULL;
89 else
90 return (*s->callback)(s, s->user_data);
91 }
92
93 void
mps_mpsolve_async(mps_context * s,mps_callback callback,void * user_data)94 mps_mpsolve_async (mps_context * s, mps_callback callback, void * user_data)
95 {
96 #ifdef MPS_CATCH_FPE
97 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
98 #endif
99
100 /* Set up callbacks */
101 s->callback = callback;
102 s->user_data = user_data;
103
104 mps_thread_pool * private_pool = mps_thread_pool_new (s, 1);
105 mps_thread_pool_set_strict_async (private_pool, true);
106 s->self_thread_pool = private_pool;
107 mps_thread_pool_assign (s, private_pool, (mps_thread_work) mps_caller, s);
108 }
109
110 /**
111 * @brief Allocator for memory to be used in mpsolve.
112 */
113 void *
mps_malloc(size_t size)114 mps_malloc (size_t size)
115 {
116 /* fprintf (stderr, "Allocating %lu bytes of memory\n", size); */
117 register void *value = malloc (size);
118
119 if (value == 0)
120 {
121 fprintf (stderr, "virtual memory exhausted");
122 abort ();
123 }
124 return value;
125 }
126
127 /**
128 * @brief Reallocator for memory used in MPSolve.
129 */
130 void *
mps_realloc(void * pointer,size_t size)131 mps_realloc (void * pointer, size_t size)
132 {
133 register void *value = realloc (pointer, size);
134
135 if (value == 0 && size > 0)
136 {
137 fprintf (stderr, "virtual memory exhausted");
138 abort ();
139 }
140 return value;
141 }
142