]> www.ginac.de Git - cln.git/blob - src/polynomial/elem/cl_UP_named.cc
Finalize CLN 1.3.7 release.
[cln.git] / src / polynomial / elem / cl_UP_named.cc
1 // find_univpoly_ring().
2
3 // General includes.
4 #include "base/cl_sysdep.h"
5
6 // Specification.
7 #include "cln/univpoly.h"
8
9
10 // Implementation.
11
12 #include "polynomial/cl_UP.h"
13
14 namespace cln {
15
16 // Create a new univariate polynomial ring with a named variable.
17
18 static inline cl_heap_univpoly_ring* cl_make_univpoly_ring (const cl_ring& r, const cl_symbol& varname)
19 {
20         cl_heap_univpoly_ring* UPR = cl_make_univpoly_ring(r);
21         UPR->add_property(new cl_varname_property(cl_univpoly_varname_key,varname));
22         return UPR;
23 }
24
25 }  // namespace cln
26
27 // The table of univariate polynomial rings with named variable.
28 // A weak hash table (cl_ring,cl_symbol) -> cl_univpoly_ring.
29
30 #include "base/hash/cl_rcpointer2_hashweak_rcpointer.h"
31
32 namespace cln {
33
34 // An entry can be collected when the value (the ring) isn't referenced any more
35 // except from the hash table, and when the keys (the base ring and the name)
36 // are't referenced any more except from the hash table and the ring. Note that
37 // the ring contains exactly one reference to the base ring and exactly one
38 // reference to the name (on the property list).
39
40 static bool maygc_htentry (const cl_htentry_from_rcpointer2_to_rcpointer& entry)
41 {
42         if (!entry.key1.pointer_p() || (entry.key1.heappointer->refcount == 2))
43                 if (!entry.key2.pointer_p() || (entry.key2.heappointer->refcount == 2))
44                         if (!entry.val.pointer_p() || (entry.val.heappointer->refcount == 1))
45                                 return true;
46         return false;
47 }
48
49 class named_univpoly_ring_cache
50 {
51         static cl_wht_from_rcpointer2_to_rcpointer* univpoly_ring_table;
52         static int count;
53 public:
54         named_univpoly_ring_cache();
55         ~named_univpoly_ring_cache();
56
57         inline cl_univpoly_ring* get_univpoly_ring(const cl_ring& r, const cl_symbol& v)
58         {
59                 return (cl_univpoly_ring*) univpoly_ring_table->get(r,v);
60         }
61         inline void store_univpoly_ring(const cl_univpoly_ring& R)
62         {
63                 univpoly_ring_table->put(R->basering(),
64                                          ((cl_varname_property*)(R->get_property(cl_univpoly_varname_key)))->varname,
65                                          R);
66         }
67 };
68
69 cl_wht_from_rcpointer2_to_rcpointer* named_univpoly_ring_cache::univpoly_ring_table = 0;
70 int named_univpoly_ring_cache::count = 0;
71
72 named_univpoly_ring_cache::named_univpoly_ring_cache()
73 {
74         if (count++ == 0)
75                 univpoly_ring_table = new cl_wht_from_rcpointer2_to_rcpointer(maygc_htentry);
76 }
77
78
79 named_univpoly_ring_cache::~named_univpoly_ring_cache()
80 {
81         if (--count == 0)
82                 delete univpoly_ring_table;
83 }
84
85 const cl_univpoly_ring find_univpoly_ring (const cl_ring& r, const cl_symbol& varname)
86 {
87         static named_univpoly_ring_cache cache;
88         var cl_univpoly_ring* ring_in_table = cache.get_univpoly_ring(r,varname);
89         if (!ring_in_table) {
90                 var cl_univpoly_ring R = cl_make_univpoly_ring(r,varname);
91                 cache.store_univpoly_ring(R);
92                 ring_in_table = cache.get_univpoly_ring(r,varname);
93                 if (!ring_in_table)
94                         throw runtime_exception();
95         }
96         return *ring_in_table;
97 }
98
99 }  // namespace cln
100