1 /****************************************
2 *  Computer Algebra System SINGULAR     *
3 ****************************************/
4 /***************************************************************
5  *  File:    p_Procs_Dynamic.cc
6  *  Purpose: source for dynamically loaded version of p_Procs
7  *  Author:  obachman (Olaf Bachmann)
8  *  Created: 12/00
9  *******************************************************************/
10 #include "misc/auxiliary.h"
11 
12 #include "factory/factory.h"
13 
14 #include "reporter/reporter.h"
15 
16 #include "polys/monomials/ring.h"
17 #include "polys/monomials/p_polys.h"
18 
19 #include "polys/kbuckets.h"
20 
21 #include "polys/templates/p_Numbers.h"
22 
23 #include "polys/templates/p_Procs.h"
24 #include "polys/templates/p_MemCmp.h"
25 #include "polys/templates/p_MemAdd.h"
26 #include "polys/templates/p_MemCopy.h"
27 
28 
29 #ifdef HAVE_DL
30 const BOOLEAN p_procs_dynamic = TRUE;
31 
32 #define WARN_MSG "Singular will work properly, but much slower."
33 
34 // need external linkage, so that dynl_sym works
35 #undef LINKAGE
36 #define LINKAGE extern "C"
37 #define p_Procs_Kernel
38 
39 #include "templates/p_Procs.inc"
40 
41 #include "templates/p_Procs_Dynamic.h"
42 // include general p_Proc stuff
43 #include "templates/p_Procs_Impl.h"
44 
45 #include "mod_raw.h"
46 
47 // define to bound for length of p_Proc name
48 #define MAX_PROCNAME_LEN 200
49 
50 void* p_procs_handle_FieldIndep = NULL;
51 void* p_procs_handle_FieldZp = NULL;
52 void* p_procs_handle_FieldQ = NULL;
53 void* p_procs_handle_FieldGeneral = NULL;
54 
p_ProcInitHandle(void ** handle,const char * module)55 static void* p_ProcInitHandle(void** handle, const char* module)
56 {
57   if (*handle == NULL)
58   {
59     char name[25];
60     sprintf(name, "p_Procs_%s", module);
61     *handle = dynl_open_binary_warn(name, WARN_MSG);
62   }
63   return *handle;
64 }
65 
p_ProcGetHandle(p_Proc proc,p_Field field)66 static inline void* p_ProcGetHandle(p_Proc proc, p_Field field)
67 {
68   const char* module =  p_ProcField_2_Module(proc, field);
69 
70   if (strcmp(module, "FieldIndep") == 0)
71     return p_ProcInitHandle(&p_procs_handle_FieldIndep, module);
72   else if (strcmp(module, "FieldZp") == 0)
73     return p_ProcInitHandle(&p_procs_handle_FieldZp, module);
74   else if (strcmp(module, "FieldQ") == 0)
75     return p_ProcInitHandle(&p_procs_handle_FieldQ, module);
76   else if (strcmp(module, "FieldGeneral") == 0)
77     return p_ProcInitHandle(&p_procs_handle_FieldGeneral, module);
78   else
79   {
80     assume(0);
81     return NULL;
82   }
83 }
84 
85 
GetGeneralProc(p_Proc proc)86 static void* GetGeneralProc(p_Proc proc)
87 {
88   switch(proc)
89   {
90       case p_Copy_Proc:
91         return cast_A_to_vptr(p_Copy__FieldGeneral_LengthGeneral_OrdGeneral);
92       case p_Delete_Proc:
93         return cast_A_to_vptr(p_Delete__FieldGeneral_LengthGeneral_OrdGeneral);
94       case p_ShallowCopyDelete_Proc:
95         return cast_A_to_vptr(p_ShallowCopyDelete__FieldGeneral_LengthGeneral_OrdGeneral);
96       case p_Add_q_Proc:
97         return cast_A_to_vptr(p_Add_q__FieldGeneral_LengthGeneral_OrdGeneral);
98       case p_Neg_Proc:
99         return cast_A_to_vptr(p_Neg__FieldGeneral_LengthGeneral_OrdGeneral);
100       case p_Merge_q_Proc:
101         return cast_A_to_vptr(p_Merge_q__FieldGeneral_LengthGeneral_OrdGeneral);
102       case p_kBucketSetLm_Proc:
103         return cast_A_to_vptr(p_kBucketSetLm__FieldGeneral_LengthGeneral_OrdGeneral);
104 #ifdef HAVE_RINGS
105       case p_Mult_nn_Proc:
106         return cast_A_to_vptr(p_Mult_nn__RingGeneral_LengthGeneral_OrdGeneral);
107       case pp_Mult_nn_Proc:
108         return cast_A_to_vptr(pp_Mult_nn__RingGeneral_LengthGeneral_OrdGeneral);
109       case pp_Mult_mm_Proc:
110         return cast_A_to_vptr(pp_Mult_mm__RingGeneral_LengthGeneral_OrdGeneral);
111       case pp_Mult_mm_Noether_Proc:
112         return cast_A_to_vptr(pp_Mult_mm_Noether__RingGeneral_LengthGeneral_OrdGeneral);
113       case p_Mult_mm_Proc:
114         return cast_A_to_vptr(p_Mult_mm__RingGeneral_LengthGeneral_OrdGeneral);
115       case p_Minus_mm_Mult_qq_Proc:
116         return cast_A_to_vptr(p_Minus_mm_Mult_qq__RingGeneral_LengthGeneral_OrdGeneral);
117       case pp_Mult_Coeff_mm_DivSelect_Proc:
118         return cast_A_to_vptr(pp_Mult_Coeff_mm_DivSelect__RingGeneral_LengthGeneral_OrdGeneral);
119       case pp_Mult_Coeff_mm_DivSelectMult_Proc:
120         return cast_A_to_vptr(pp_Mult_Coeff_mm_DivSelectMult__RingGeneral_LengthGeneral_OrdGeneral);
121 #else
122       case p_Mult_nn_Proc:
123         return cast_A_to_vptr(p_Mult_nn__FieldGeneral_LengthGeneral_OrdGeneral);
124       case pp_Mult_nn_Proc:
125         return cast_A_to_vptr(pp_Mult_nn__FieldGeneral_LengthGeneral_OrdGeneral);
126       case pp_Mult_mm_Proc:
127         return cast_A_to_vptr(pp_Mult_mm__FieldGeneral_LengthGeneral_OrdGeneral);
128       case pp_Mult_mm_Noether_Proc:
129         return cast_A_to_vptr(pp_Mult_mm_Noether__FieldGeneral_LengthGeneral_OrdGeneral);
130       case p_Mult_mm_Proc:
131         return cast_A_to_vptr(p_Mult_mm__FieldGeneral_LengthGeneral_OrdGeneral);
132       case p_Minus_mm_Mult_qq_Proc:
133         return cast_A_to_vptr(p_Minus_mm_Mult_qq__FieldGeneral_LengthGeneral_OrdGeneral);
134       case pp_Mult_Coeff_mm_DivSelect_Proc:
135         return cast_A_to_vptr(pp_Mult_Coeff_mm_DivSelect__FieldGeneral_LengthGeneral_OrdGeneral);
136       case pp_Mult_Coeff_mm_DivSelectMult_Proc:
137         return cast_A_to_vptr(pp_Mult_Coeff_mm_DivSelectMult__FieldGeneral_LengthGeneral_OrdGeneral);
138 #endif
139       case p_Unknown_Proc:
140         break;
141   }
142   dReportBug("p_Unknown_Proc");
143   return NULL;
144 }
145 
146 #ifdef RDEBUG
GetGeneralProcName(p_Proc proc)147 static const char* GetGeneralProcName(p_Proc proc)
148 {
149   switch(proc)
150   {
151       case p_Copy_Proc:
152         return "p_Copy__FieldGeneral_LengthGeneral_OrdGeneral";
153       case p_Delete_Proc:
154         return "p_Delete__FieldGeneral_LengthGeneral_OrdGeneral";
155       case p_ShallowCopyDelete_Proc:
156         return "p_ShallowCopyDelete__FieldGeneral_LengthGeneral_OrdGeneral";
157       case p_Add_q_Proc:
158         return "p_Add_q__FieldGeneral_LengthGeneral_OrdGeneral";
159       case p_Neg_Proc:
160         return "p_Neg__FieldGeneral_LengthGeneral_OrdGeneral";
161       case p_Merge_q_Proc:
162         return "p_Merge_q__FieldGeneral_LengthGeneral_OrdGeneral";
163       case p_kBucketSetLm_Proc:
164         return "p_kBucketSetLm__FieldGeneral_LengthGeneral_OrdGeneral";
165       case p_Unknown_Proc:
166         break;
167 #ifdef HAVE_RINGS
168       case p_Mult_nn_Proc:
169         return "p_Mult_nn__RingGeneral_LengthGeneral_OrdGeneral";
170       case pp_Mult_nn_Proc:
171         return "pp_Mult_nn__RingGeneral_LengthGeneral_OrdGeneral";
172       case pp_Mult_mm_Proc:
173         return "pp_Mult_mm__RingGeneral_LengthGeneral_OrdGeneral";
174       case pp_Mult_mm_Noether_Proc:
175         return "pp_Mult_mm_Noether__RingGeneral_LengthGeneral_OrdGeneral";
176       case p_Mult_mm_Proc:
177         return "p_Mult_mm__RingGeneral_LengthGeneral_OrdGeneral";
178       case p_Minus_mm_Mult_qq_Proc:
179         return "p_Minus_mm_Mult_qq__RingGeneral_LengthGeneral_OrdGeneral";
180       case pp_Mult_Coeff_mm_DivSelect_Proc:
181         return "pp_Mult_Coeff_mm_DivSelect__RingGeneral_LengthGeneral_OrdGeneral";
182       case pp_Mult_Coeff_mm_DivSelectMult_Proc:
183         return "pp_Mult_Coeff_mm_DivSelectMult__RingGeneral_LengthGeneral_OrdGeneral";
184 #else
185       case p_Mult_nn_Proc:
186         return "p_Mult_nn__FieldGeneral_LengthGeneral_OrdGeneral";
187       case pp_Mult_nn_Proc:
188         return "pp_Mult_nn__FieldGeneral_LengthGeneral_OrdGeneral";
189       case pp_Mult_mm_Proc:
190         return "pp_Mult_mm__FieldGeneral_LengthGeneral_OrdGeneral";
191       case pp_Mult_mm_Noether_Proc:
192         return "pp_Mult_mm_Noether__FieldGeneral_LengthGeneral_OrdGeneral";
193       case p_Mult_mm_Proc:
194         return "p_Mult_mm__FieldGeneral_LengthGeneral_OrdGeneral";
195       case p_Minus_mm_Mult_qq_Proc:
196         return "p_Minus_mm_Mult_qq__FieldGeneral_LengthGeneral_OrdGeneral";
197       case pp_Mult_Coeff_mm_DivSelect_Proc:
198         return "pp_Mult_Coeff_mm_DivSelect__FieldGeneral_LengthGeneral_OrdGeneral";
199       case pp_Mult_Coeff_mm_DivSelectMult_Proc:
200         return "pp_Mult_Coeff_mm_DivSelectMult__FieldGeneral_LengthGeneral_OrdGeneral";
201 #endif
202   }
203   return "p_Unknown_Proc";
204 }
205 #endif
206 
207 
GetDynamicProc(const char * proc_s,p_Proc proc,p_Field field,p_Length length,p_Ord ord,int get_name=0)208 static void* GetDynamicProc(const char* proc_s, p_Proc proc,
209                             p_Field field, p_Length length, p_Ord ord
210 #ifdef RDEBUG
211                      , int get_name = 0
212 #endif
213                      )
214 {
215   void* proc_ptr = NULL;
216   char proc_name[MAX_PROCNAME_LEN];
217   sprintf(proc_name, "%s__%s_%s_%s", proc_s,
218           p_FieldEnum_2_String(field),
219           p_LengthEnum_2_String(length),
220           p_OrdEnum_2_String(ord));
221   // printf("set %s\n",proc_name);
222   // first, try to get the proc from the kernel
223   proc_ptr = dynl_sym(DYNL_KERNEL_HANDLE, proc_name);
224   if (proc_ptr == NULL)
225   {
226     proc_ptr = dynl_sym_warn(p_ProcGetHandle(proc, field), proc_name, WARN_MSG);
227     // last but not least use general proc
228     if (proc_ptr == NULL)
229     {
230       proc_ptr = GetGeneralProc(proc);
231 #ifdef RDEBUG
232       sprintf(proc_name,"%s", GetGeneralProcName(proc));
233 #endif
234     }
235   }
236 #ifdef RDEBUG
237   if (get_name)
238   {
239     char* name = omStrDup(proc_name);
240 #if (!defined(SING_NDEBUG)) && (!defined(OM_NDEBUG))
241     omMarkAsStaticAddr(name);
242 #endif
243     return (void*) name;
244   }
245 #endif
246   return  proc_ptr;
247 }
248 
249 
250 #define DoReallySetProc(what, field, length, ord)           \
251   _p_procs->what =    cast_vptr_to_A<what##_Proc_Ptr>(      \
252      GetDynamicProc(#what, what##_Proc, field, length, ord))
253 
254 #ifdef RDEBUG
255 #define DoSetProc(what, field, length, ord)                         \
256 do                                                                  \
257 {                                                                   \
258   if (set_names)                                                    \
259     _p_procs->what =    cast_vptr_to_A<what##_Proc_Ptr>(            \
260        GetDynamicProc(#what,  what##_Proc, field, length, ord, 1));  \
261   else                                                              \
262     DoReallySetProc(what, field, length, ord);                      \
263 }                                                                   \
264 while(0)
265 #else
266 #define DoSetProc DoReallySetProc
267 #endif
268 
269 #include "templates/p_Procs_Set.h"
270 
271 #endif
272 
273