GiNaC 1.8.7
utils.h
Go to the documentation of this file.
1
6/*
7 * GiNaC Copyright (C) 1999-2023 Johannes Gutenberg University Mainz, Germany
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#ifndef GINAC_UTILS_H
25#define GINAC_UTILS_H
26
27#include "assertion.h"
28
29#include <functional>
30#include <cstdint> // for uintptr_t
31#include <string>
32
33namespace GiNaC {
34
37class dunno {};
38
39// some compilers (e.g. cygwin) define a macro log2, causing confusion
40#ifdef log2
41#undef log2
42#endif
43
44unsigned log2(unsigned n);
45
48inline unsigned rotate_left(unsigned n)
49{
50 return (n & 0x80000000U) ? (n << 1 | 0x00000001U) : (n << 1);
51}
52
55template <class T>
56inline int compare_pointers(const T * a, const T * b)
57{
58 // '<' is not defined for pointers that don't point to the same array,
59 // but std::less is.
60 if (std::less<const T *>()(a, b))
61 return -1;
62 else if (std::less<const T *>()(b, a))
63 return 1;
64 return 0;
65}
66
68inline unsigned golden_ratio_hash(uintptr_t n)
69{
70 return n * UINT64_C(0x4f1bbcdd);
71}
72
73/* Compute the sign of a permutation of a container, with and without an
74 explicitly supplied comparison function. If the sign returned is 1 or -1,
75 the container is sorted after the operation. */
76template <class It>
77int permutation_sign(It first, It last)
78{
79 using std::swap;
80 if (first == last)
81 return 0;
82 --last;
83 if (first == last)
84 return 0;
85 It flag = first;
86 int sign = 1;
87
88 do {
89 It i = last, other = last;
90 --other;
91 bool swapped = false;
92 while (i != first) {
93 if (*i < *other) {
94 swap(*other, *i);
95 flag = other;
96 swapped = true;
97 sign = -sign;
98 } else if (!(*other < *i))
99 return 0;
100 --i;
101 if (i != first)
102 --other;
103 }
104 if (!swapped)
105 return sign;
106 ++flag;
107 if (flag == last)
108 return sign;
109 first = flag;
110 i = first; other = first;
111 ++other;
112 swapped = false;
113 while (i != last) {
114 if (*other < *i) {
115 swap(*i, *other);
116 flag = other;
117 swapped = true;
118 sign = -sign;
119 } else if (!(*i < *other))
120 return 0;
121 ++i;
122 if (i != last)
123 ++other;
124 }
125 if (!swapped)
126 return sign;
127 last = flag;
128 --last;
129 } while (first != last);
130
131 return sign;
132}
133
134template <class It, class Cmp, class Swap>
135int permutation_sign(It first, It last, Cmp comp, Swap swapit)
136{
137 if (first == last)
138 return 0;
139 --last;
140 if (first == last)
141 return 0;
142 It flag = first;
143 int sign = 1;
144
145 do {
146 It i = last, other = last;
147 --other;
148 bool swapped = false;
149 while (i != first) {
150 if (comp(*i, *other)) {
151 swapit(*other, *i);
152 flag = other;
153 swapped = true;
154 sign = -sign;
155 } else if (!comp(*other, *i))
156 return 0;
157 --i;
158 if (i != first)
159 --other;
160 }
161 if (!swapped)
162 return sign;
163 ++flag;
164 if (flag == last)
165 return sign;
166 first = flag;
167 i = first; other = first;
168 ++other;
169 swapped = false;
170 while (i != last) {
171 if (comp(*other, *i)) {
172 swapit(*i, *other);
173 flag = other;
174 swapped = true;
175 sign = -sign;
176 } else if (!comp(*i, *other))
177 return 0;
178 ++i;
179 if (i != last)
180 ++other;
181 }
182 if (!swapped)
183 return sign;
184 last = flag;
185 --last;
186 } while (first != last);
187
188 return sign;
189}
190
191/* Implementation of shaker sort, only compares adjacent elements. */
192template <class It, class Cmp, class Swap>
193void shaker_sort(It first, It last, Cmp comp, Swap swapit)
194{
195 if (first == last)
196 return;
197 --last;
198 if (first == last)
199 return;
200 It flag = first;
201
202 do {
203 It i = last, other = last;
204 --other;
205 bool swapped = false;
206 while (i != first) {
207 if (comp(*i, *other)) {
208 swapit(*other, *i);
209 flag = other;
210 swapped = true;
211 }
212 --i;
213 if (i != first)
214 --other;
215 }
216 if (!swapped)
217 return;
218 ++flag;
219 if (flag == last)
220 return;
221 first = flag;
222 i = first; other = first;
223 ++other;
224 swapped = false;
225 while (i != last) {
226 if (comp(*other, *i)) {
227 swapit(*i, *other);
228 flag = other;
229 swapped = true;
230 }
231 ++i;
232 if (i != last)
233 ++other;
234 }
235 if (!swapped)
236 return;
237 last = flag;
238 --last;
239 } while (first != last);
240}
241
242/* In-place cyclic permutation of a container (no copying, only swapping). */
243template <class It, class Swap>
244void cyclic_permutation(It first, It last, It new_first, Swap swapit)
245{
246 unsigned num = last - first;
247again:
248 if (first == new_first || num < 2)
249 return;
250
251 unsigned num1 = new_first - first, num2 = last - new_first;
252 if (num1 >= num2) {
253 It a = first, b = new_first;
254 while (b != last) {
255 swapit(*a, *b);
256 ++a; ++b;
257 }
258 if (num1 > num2) {
259 first += num2;
260 num = num1;
261 goto again;
262 }
263 } else {
264 It a = new_first, b = last;
265 do {
266 --a; --b;
267 swapit(*a, *b);
268 } while (a != first);
269 last -= num1;
270 num = num2;
271 goto again;
272 }
273}
274
279protected:
280 // Partitions n into m parts, not including zero parts.
281 // (Cf. OEIS sequence A008284; implementation adapted from Jörg Arndt's
282 // FXT library)
284 {
285 // partition: x[1] + x[2] + ... + x[m] = n and sentinel x[0] == 0
286 std::vector<unsigned> x;
287 unsigned n; // n>0
288 unsigned m; // 0<m<=n
289 mpartition2(unsigned n_, unsigned m_)
290 : x(m_+1), n(n_), m(m_)
291 {
292 for (unsigned k=1; k<m; ++k)
293 x[k] = 1;
294 x[m] = n - m + 1;
295 }
297 {
298 unsigned u = x[m]; // last element
299 unsigned k = m;
300 unsigned s = u;
301 while (--k) {
302 s += x[k];
303 if (x[k] + 2 <= u)
304 break;
305 }
306 if (k==0)
307 return false; // current is last
308 unsigned f = x[k] + 1;
309 while (k < m) {
310 x[k] = f;
311 s -= f;
312 ++k;
313 }
314 x[m] = s;
315 return true;
316 }
317 };
319 basic_partition_generator(unsigned n_, unsigned m_)
320 : mpgen(n_, m_)
321 { }
322};
323
328private:
329 unsigned m; // number of parts 0<m
330 mutable std::vector<unsigned> partition; // current partition
331 mutable bool current_updated; // whether partition vector has been updated
332public:
333 partition_with_zero_parts_generator(unsigned n_, unsigned m_)
334 : basic_partition_generator(n_, 1), m(m_), partition(m_), current_updated(false)
335 { }
336 // returns current partition in non-decreasing order, padded with zeros
337 const std::vector<unsigned>& get() const
338 {
339 if (!current_updated) {
340 for (unsigned i = 0; i < m - mpgen.m; ++i)
341 partition[i] = 0; // pad with zeros
342
343 for (unsigned i = m - mpgen.m; i < m; ++i)
344 partition[i] = mpgen.x[i - m + mpgen.m + 1];
345
346 current_updated = true;
347 }
348 return partition;
349 }
350 bool next()
351 {
352 current_updated = false;
353 if (!mpgen.next_partition()) {
354 if (mpgen.m == m || mpgen.m == mpgen.n)
355 return false; // current is last
356 // increment number of parts
357 mpgen = mpartition2(mpgen.n, mpgen.m + 1);
358 }
359 return true;
360 }
361};
362
367private:
368 mutable std::vector<unsigned> partition; // current partition
369 mutable bool current_updated; // whether partition vector has been updated
370public:
371 partition_generator(unsigned n_, unsigned m_)
373 { }
374 // returns current partition in non-decreasing order, padded with zeros
375 const std::vector<unsigned>& get() const
376 {
377 if (!current_updated) {
378 for (unsigned i = 0; i < mpgen.m; ++i)
379 partition[i] = mpgen.x[i + 1];
380
381 current_updated = true;
382 }
383 return partition;
384 }
385 bool next()
386 {
387 current_updated = false;
388 return mpgen.next_partition();
389 }
390};
391
396private:
397 // Generates all distinct permutations of a multiset.
398 // (Based on Aaron Williams' algorithm 1 from "Loopless Generation of
399 // Multiset Permutations using a Constant Number of Variables by Prefix
400 // Shifts." <https://dl.acm.org/doi/pdf/10.5555/1496770.1496877>)
401 struct coolmulti {
402 // element of singly linked list
403 struct element {
404 unsigned value;
406 element(unsigned val, element* n)
407 : value(val), next(n) {}
409 { // recurses down to the end of the singly linked list
410 delete next;
411 }
412 };
414 // NB: Partition must be sorted in non-decreasing order.
415 explicit coolmulti(const std::vector<unsigned>& partition)
416 : head(nullptr), i(nullptr), after_i(nullptr)
417 {
418 for (unsigned n = 0; n < partition.size(); ++n) {
419 head = new element(partition[n], head);
420 if (n <= 1)
421 i = head;
422 }
423 after_i = i->next;
424 }
426 { // deletes singly linked list
427 delete head;
428 }
430 {
431 element *before_k;
432 if (after_i->next != nullptr && i->value >= after_i->next->value)
433 before_k = after_i;
434 else
435 before_k = i;
436 element *k = before_k->next;
437 before_k->next = k->next;
438 k->next = head;
439 if (k->value < head->value)
440 i = k;
441 after_i = i->next;
442 head = k;
443 }
444 bool finished() const
445 {
446 return after_i->next == nullptr && after_i->value >= head->value;
447 }
449 bool atend; // needed for simplifying iteration over permutations
450 bool trivial; // likewise, true if all elements are equal
451 mutable std::vector<unsigned> composition; // current compositions
452 mutable bool current_updated; // whether composition vector has been updated
453public:
454 explicit composition_generator(const std::vector<unsigned>& partition)
455 : cmgen(partition), atend(false), trivial(true), composition(partition.size()), current_updated(false)
456 {
457 for (unsigned i=1; i<partition.size(); ++i)
458 trivial = trivial && (partition[0] == partition[i]);
459 }
460 const std::vector<unsigned>& get() const
461 {
462 if (!current_updated) {
464 size_t i = 0;
465 while (it != nullptr) {
466 composition[i] = it->value;
467 it = it->next;
468 ++i;
469 }
470 current_updated = true;
471 }
472 return composition;
473 }
474 bool next()
475 {
476 // This ugly contortion is needed because the original coolmulti
477 // algorithm requires code duplication of the payload procedure,
478 // one before the loop and one inside it.
479 if (trivial || atend)
480 return false;
482 current_updated = false;
483 atend = cmgen.finished();
484 return true;
485 }
486};
487
491const numeric
492multinomial_coefficient(const std::vector<unsigned> & p);
493
494
495// Collection of `construct on first use' wrappers for safely avoiding
496// internal object replication without running into the `static
497// initialization order fiasco'. This chest of numbers helps speed up
498// the library but should not be used outside it since it is
499// potentially confusing.
500
501class ex;
502
503extern const numeric *_num_120_p;
504extern const ex _ex_120;
505extern const numeric *_num_60_p;
506extern const ex _ex_60;
507extern const numeric *_num_48_p;
508extern const ex _ex_48;
509extern const numeric *_num_30_p;
510extern const ex _ex_30;
511extern const numeric *_num_25_p;
512extern const ex _ex_25;
513extern const numeric *_num_24_p;
514extern const ex _ex_24;
515extern const numeric *_num_20_p;
516extern const ex _ex_20;
517extern const numeric *_num_18_p;
518extern const ex _ex_18;
519extern const numeric *_num_15_p;
520extern const ex _ex_15;
521extern const numeric *_num_12_p;
522extern const ex _ex_12;
523extern const numeric *_num_11_p;
524extern const ex _ex_11;
525extern const numeric *_num_10_p;
526extern const ex _ex_10;
527extern const numeric *_num_9_p;
528extern const ex _ex_9;
529extern const numeric *_num_8_p;
530extern const ex _ex_8;
531extern const numeric *_num_7_p;
532extern const ex _ex_7;
533extern const numeric *_num_6_p;
534extern const ex _ex_6;
535extern const numeric *_num_5_p;
536extern const ex _ex_5;
537extern const numeric *_num_4_p;
538extern const ex _ex_4;
539extern const numeric *_num_3_p;
540extern const ex _ex_3;
541extern const numeric *_num_2_p;
542extern const ex _ex_2;
543extern const numeric *_num_1_p;
544extern const ex _ex_1;
545extern const numeric *_num_1_2_p;
546extern const ex _ex_1_2;
547extern const numeric *_num_1_3_p;
548extern const ex _ex_1_3;
549extern const numeric *_num_1_4_p;
550extern const ex _ex_1_4;
551extern const numeric *_num0_p;
552extern const basic *_num0_bp;
553extern const ex _ex0;
554extern const numeric *_num1_4_p;
555extern const ex _ex1_4;
556extern const numeric *_num1_3_p;
557extern const ex _ex1_3;
558extern const numeric *_num1_2_p;
559extern const ex _ex1_2;
560extern const numeric *_num1_p;
561extern const ex _ex1;
562extern const numeric *_num2_p;
563extern const ex _ex2;
564extern const numeric *_num3_p;
565extern const ex _ex3;
566extern const numeric *_num4_p;
567extern const ex _ex4;
568extern const numeric *_num5_p;
569extern const ex _ex5;
570extern const numeric *_num6_p;
571extern const ex _ex6;
572extern const numeric *_num7_p;
573extern const ex _ex7;
574extern const numeric *_num8_p;
575extern const ex _ex8;
576extern const numeric *_num9_p;
577extern const ex _ex9;
578extern const numeric *_num10_p;
579extern const ex _ex10;
580extern const numeric *_num11_p;
581extern const ex _ex11;
582extern const numeric *_num12_p;
583extern const ex _ex12;
584extern const numeric *_num15_p;
585extern const ex _ex15;
586extern const numeric *_num18_p;
587extern const ex _ex18;
588extern const numeric *_num20_p;
589extern const ex _ex20;
590extern const numeric *_num24_p;
591extern const ex _ex24;
592extern const numeric *_num25_p;
593extern const ex _ex25;
594extern const numeric *_num30_p;
595extern const ex _ex30;
596extern const numeric *_num48_p;
597extern const ex _ex48;
598extern const numeric *_num60_p;
599extern const ex _ex60;
600extern const numeric *_num120_p;
601extern const ex _ex120;
602
603
604// Helper macros for class implementations (mostly useful for trivial classes)
605
606#define DEFAULT_CTOR(classname) \
607classname::classname() { setflag(status_flags::evaluated | status_flags::expanded); }
608
609#define DEFAULT_COMPARE(classname) \
610int classname::compare_same_type(const basic & other) const \
611{ \
612 /* by default, the objects are always identical */ \
613 return 0; \
614}
615
616#define DEFAULT_PRINT(classname, text) \
617void classname::do_print(const print_context & c, unsigned level) const \
618{ \
619 c.s << text; \
620}
621
622#define DEFAULT_PRINT_LATEX(classname, text, latex) \
623DEFAULT_PRINT(classname, text) \
624void classname::do_print_latex(const print_latex & c, unsigned level) const \
625{ \
626 c.s << latex; \
627}
628
629} // namespace GiNaC
630
631#endif // ndef GINAC_UTILS_H
Assertion macro definition.
Base class for generating all bounded combinatorial partitions of an integer n with exactly m parts i...
Definition: utils.h:278
basic_partition_generator(unsigned n_, unsigned m_)
Definition: utils.h:319
Generate all compositions of a partition of an integer n, starting with the compositions which has no...
Definition: utils.h:395
std::vector< unsigned > composition
Definition: utils.h:451
struct GiNaC::composition_generator::coolmulti cmgen
composition_generator(const std::vector< unsigned > &partition)
Definition: utils.h:454
const std::vector< unsigned > & get() const
Definition: utils.h:460
Exception class thrown by functions to signal unimplemented functionality so the expression may just ...
Definition: utils.h:37
Generate all bounded combinatorial partitions of an integer n with exactly m parts (not including zer...
Definition: utils.h:366
const std::vector< unsigned > & get() const
Definition: utils.h:375
partition_generator(unsigned n_, unsigned m_)
Definition: utils.h:371
std::vector< unsigned > partition
Definition: utils.h:368
Generate all bounded combinatorial partitions of an integer n with exactly m parts (including zero pa...
Definition: utils.h:327
partition_with_zero_parts_generator(unsigned n_, unsigned m_)
Definition: utils.h:333
const std::vector< unsigned > & get() const
Definition: utils.h:337
std::vector< unsigned > partition
Definition: utils.h:330
vector< int > k
Definition: factor.cpp:1435
size_t n
Definition: factor.cpp:1432
size_t last
Definition: factor.cpp:1434
Definition: add.cpp:38
const ex _ex_20
Definition: utils.cpp:296
const numeric * _num_3_p
Definition: utils.cpp:343
const numeric * _num_24_p
Definition: utils.cpp:291
const ex _ex_12
Definition: utils.cpp:308
const numeric * _num1_3_p
Definition: utils.cpp:376
const ex _ex9
Definition: utils.cpp:417
const numeric * _num_1_p
Definition: utils.cpp:351
const ex _ex_120
Definition: utils.cpp:272
const ex _ex2
Definition: utils.cpp:389
const numeric * _num_120_p
Definition: utils.cpp:271
const ex _ex_1_2
Definition: utils.cpp:356
const numeric * _num_30_p
Definition: utils.cpp:283
const numeric * _num6_p
Definition: utils.cpp:404
unsigned golden_ratio_hash(uintptr_t n)
Truncated multiplication with golden ratio, for computing hash values.
Definition: utils.h:68
const numeric * _num_1_3_p
Definition: utils.cpp:359
const ex _ex1_2
Definition: utils.cpp:381
const numeric * _num_1_2_p
Definition: utils.cpp:355
const numeric * _num3_p
Definition: utils.cpp:392
const ex _ex7
Definition: utils.cpp:409
const numeric * _num_1_4_p
Definition: utils.cpp:363
const numeric * _num1_2_p
Definition: utils.cpp:380
const ex _ex24
Definition: utils.cpp:445
const numeric * _num25_p
Definition: utils.cpp:448
const ex _ex12
Definition: utils.cpp:429
const ex _ex1
Definition: utils.cpp:385
const numeric * _num_10_p
Definition: utils.cpp:315
const ex _ex_60
Definition: utils.cpp:276
const numeric * _num_8_p
Definition: utils.cpp:323
const numeric * _num1_4_p
Definition: utils.cpp:372
const numeric * _num_5_p
Definition: utils.cpp:335
int compare_pointers(const T *a, const T *b)
Compare two pointers (just to establish some sort of canonical order).
Definition: utils.h:56
const numeric * _num24_p
Definition: utils.cpp:444
const ex _ex15
Definition: utils.cpp:433
const numeric * _num_11_p
Definition: utils.cpp:311
const numeric * _num30_p
Definition: utils.cpp:452
const ex _ex3
Definition: utils.cpp:393
const numeric * _num10_p
Definition: utils.cpp:420
const ex _ex6
Definition: utils.cpp:405
const numeric * _num4_p
Definition: utils.cpp:396
const numeric * _num_12_p
Definition: utils.cpp:307
const numeric * _num_2_p
Definition: utils.cpp:347
const numeric * _num_9_p
Definition: utils.cpp:319
const numeric * _num2_p
Definition: utils.cpp:388
const ex _ex11
Definition: utils.cpp:425
const ex _ex_4
Definition: utils.cpp:340
const ex _ex_24
Definition: utils.cpp:292
const ex _ex_25
Definition: utils.cpp:288
const ex _ex120
Definition: utils.cpp:465
const numeric * _num11_p
Definition: utils.cpp:424
const numeric * _num_48_p
Definition: utils.cpp:279
const numeric * _num7_p
Definition: utils.cpp:408
const ex _ex_5
Definition: utils.cpp:336
const ex _ex_1
Definition: utils.cpp:352
const ex _ex_3
Definition: utils.cpp:344
const numeric * _num12_p
Definition: utils.cpp:428
const ex _ex20
Definition: utils.cpp:441
const numeric * _num48_p
Definition: utils.cpp:456
unsigned log2(unsigned n)
Integer binary logarithm.
Definition: utils.cpp:48
const ex _ex30
Definition: utils.cpp:453
const numeric * _num_6_p
Definition: utils.cpp:331
const ex _ex_6
Definition: utils.cpp:332
const numeric * _num9_p
Definition: utils.cpp:416
const basic * _num0_bp
Definition: utils.cpp:368
const numeric * _num_18_p
Definition: utils.cpp:299
const ex _ex_2
Definition: utils.cpp:348
const ex _ex_10
Definition: utils.cpp:316
const ex _ex4
Definition: utils.cpp:397
const ex _ex_15
Definition: utils.cpp:304
const ex _ex5
Definition: utils.cpp:401
unsigned rotate_left(unsigned n)
Rotate bits of unsigned value by one bit to the left.
Definition: utils.h:48
const ex _ex_7
Definition: utils.cpp:328
const numeric * _num_60_p
Definition: utils.cpp:275
const ex _ex25
Definition: utils.cpp:449
const numeric * _num_7_p
Definition: utils.cpp:327
const numeric * _num1_p
Definition: utils.cpp:384
const numeric * _num8_p
Definition: utils.cpp:412
const ex _ex10
Definition: utils.cpp:421
void shaker_sort(It first, It last, Cmp comp, Swap swapit)
Definition: utils.h:193
const ex _ex48
Definition: utils.cpp:457
const numeric * _num_15_p
Definition: utils.cpp:303
const ex _ex18
Definition: utils.cpp:437
void cyclic_permutation(It first, It last, It new_first, Swap swapit)
Definition: utils.h:244
void swap(ex &e1, ex &e2)
Definition: ex.h:838
const ex _ex_11
Definition: utils.cpp:312
const numeric * _num60_p
Definition: utils.cpp:460
const ex _ex_1_4
Definition: utils.cpp:364
const ex _ex60
Definition: utils.cpp:461
const ex _ex1_4
Definition: utils.cpp:373
const ex _ex_48
Definition: utils.cpp:280
int permutation_sign(It first, It last)
Definition: utils.h:77
const numeric * _num_4_p
Definition: utils.cpp:339
const numeric * _num15_p
Definition: utils.cpp:432
const ex _ex_8
Definition: utils.cpp:324
const ex _ex_1_3
Definition: utils.cpp:360
const ex _ex0
Definition: utils.cpp:369
const numeric * _num120_p
Definition: utils.cpp:464
const ex _ex_18
Definition: utils.cpp:300
const numeric * _num_20_p
Definition: utils.cpp:295
const ex _ex_30
Definition: utils.cpp:284
const numeric * _num_25_p
Definition: utils.cpp:287
const numeric multinomial_coefficient(const std::vector< unsigned > &p)
Compute the multinomial coefficient n!/(p1!*p2!*...*pk!) where n = p1+p2+...+pk, i....
Definition: utils.cpp:60
const numeric * _num20_p
Definition: utils.cpp:440
const numeric * _num18_p
Definition: utils.cpp:436
const ex _ex8
Definition: utils.cpp:413
const ex _ex_9
Definition: utils.cpp:320
const numeric * _num0_p
Definition: utils.cpp:367
const numeric * _num5_p
Definition: utils.cpp:400
const ex _ex1_3
Definition: utils.cpp:377
void swap(GiNaC::ex &a, GiNaC::ex &b)
Specialization of std::swap() for ex objects.
Definition: ex.h:991
mpartition2(unsigned n_, unsigned m_)
Definition: utils.h:289
coolmulti(const std::vector< unsigned > &partition)
Definition: utils.h:415

This page is part of the GiNaC developer's reference. It was generated automatically by doxygen. For an introduction, see the tutorial.