]> www.ginac.de Git - ginac.git/blobdiff - ginac/utils.cpp
Happy New Year!
[ginac.git] / ginac / utils.cpp
index b7f6641efc273072e29868a7bf1e47b05617a260..6935bcd8e1a71fc93b436efc96b4fb8aa09ea2dd 100644 (file)
@@ -4,7 +4,7 @@
  *  but not of any interest to the user of the library. */
 
 /*
- *  GiNaC Copyright (C) 1999-2010 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2019 Johannes Gutenberg University Mainz, Germany
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -53,6 +53,19 @@ unsigned log2(unsigned n)
        return k;
 }
 
+/** Compute the multinomial coefficient n!/(p1!*p2!*...*pk!) where
+ *  n = p1+p2+...+pk, i.e. p is a partition of n.
+ */
+const numeric
+multinomial_coefficient(const std::vector<unsigned> & p)
+{
+       numeric n = 0, d = 1;
+       for (auto & it : p) {
+               n = n.add(numeric(it));
+               d = d.mul(factorial(numeric(it)));
+       }
+       return factorial(n).div(d);
+}
 
 //////////
 // flyweight chest of numbers is initialized here:
@@ -264,56 +277,56 @@ const ex _ex120 = _ex120;
 library_init::library_init()
 {
        if (count++==0) {
-               (_num_120_p = new numeric(-120))->setflag(status_flags::dynallocated);
-               (_num_60_p = new numeric(-60))->setflag(status_flags::dynallocated);
-               (_num_48_p = new numeric(-48))->setflag(status_flags::dynallocated);
-               (_num_30_p = new numeric(-30))->setflag(status_flags::dynallocated);
-               (_num_25_p = new numeric(-25))->setflag(status_flags::dynallocated);
-               (_num_24_p = new numeric(-24))->setflag(status_flags::dynallocated);
-               (_num_20_p = new numeric(-20))->setflag(status_flags::dynallocated);
-               (_num_18_p = new numeric(-18))->setflag(status_flags::dynallocated);
-               (_num_15_p = new numeric(-15))->setflag(status_flags::dynallocated);
-               (_num_12_p = new numeric(-12))->setflag(status_flags::dynallocated);
-               (_num_11_p = new numeric(-11))->setflag(status_flags::dynallocated);
-               (_num_10_p = new numeric(-10))->setflag(status_flags::dynallocated);
-               (_num_9_p = new numeric(-9))->setflag(status_flags::dynallocated);
-               (_num_8_p = new numeric(-8))->setflag(status_flags::dynallocated);
-               (_num_7_p = new numeric(-7))->setflag(status_flags::dynallocated);
-               (_num_6_p = new numeric(-6))->setflag(status_flags::dynallocated);
-               (_num_5_p = new numeric(-5))->setflag(status_flags::dynallocated);
-               (_num_4_p = new numeric(-4))->setflag(status_flags::dynallocated);
-               (_num_3_p = new numeric(-3))->setflag(status_flags::dynallocated);
-               (_num_2_p = new numeric(-2))->setflag(status_flags::dynallocated);
-               (_num_1_p = new numeric(-1))->setflag(status_flags::dynallocated);
-               (_num_1_2_p = new numeric(-1,2))->setflag(status_flags::dynallocated);
-               (_num_1_3_p = new numeric(-1,3))->setflag(status_flags::dynallocated);
-               (_num_1_4_p = new numeric(-1,4))->setflag(status_flags::dynallocated);
-               (_num0_p = new numeric(0))->setflag(status_flags::dynallocated);
+               _num_120_p = (const numeric *)&dynallocate<numeric>(-120);
+               _num_60_p = (const numeric *)&dynallocate<numeric>(-60);
+               _num_48_p = (const numeric *)&dynallocate<numeric>(-48);
+               _num_30_p = (const numeric *)&dynallocate<numeric>(-30);
+               _num_25_p = (const numeric *)&dynallocate<numeric>(-25);
+               _num_24_p = (const numeric *)&dynallocate<numeric>(-24);
+               _num_20_p = (const numeric *)&dynallocate<numeric>(-20);
+               _num_18_p = (const numeric *)&dynallocate<numeric>(-18);
+               _num_15_p = (const numeric *)&dynallocate<numeric>(-15);
+               _num_12_p = (const numeric *)&dynallocate<numeric>(-12);
+               _num_11_p = (const numeric *)&dynallocate<numeric>(-11);
+               _num_10_p = (const numeric *)&dynallocate<numeric>(-10);
+               _num_9_p = (const numeric *)&dynallocate<numeric>(-9);
+               _num_8_p = (const numeric *)&dynallocate<numeric>(-8);
+               _num_7_p = (const numeric *)&dynallocate<numeric>(-7);
+               _num_6_p = (const numeric *)&dynallocate<numeric>(-6);
+               _num_5_p = (const numeric *)&dynallocate<numeric>(-5);
+               _num_4_p = (const numeric *)&dynallocate<numeric>(-4);
+               _num_3_p = (const numeric *)&dynallocate<numeric>(-3);
+               _num_2_p = (const numeric *)&dynallocate<numeric>(-2);
+               _num_1_p = (const numeric *)&dynallocate<numeric>(-1);
+               _num_1_2_p = (const numeric *)&dynallocate<numeric>(-1,2);
+               _num_1_3_p = (const numeric *)&dynallocate<numeric>(-1,3);
+               _num_1_4_p = (const numeric *)&dynallocate<numeric>(-1,4);
+               _num0_p = (const numeric *)&dynallocate<numeric>(0);
                _num0_bp  = _num0_p;  // Cf. class ex default ctor.
-               (_num1_4_p = new numeric(1,4))->setflag(status_flags::dynallocated);
-               (_num1_3_p = new numeric(1,3))->setflag(status_flags::dynallocated);
-               (_num1_2_p = new numeric(1,2))->setflag(status_flags::dynallocated);
-               (_num1_p = new numeric(1))->setflag(status_flags::dynallocated);
-               (_num2_p = new numeric(2))->setflag(status_flags::dynallocated);
-               (_num3_p = new numeric(3))->setflag(status_flags::dynallocated);
-               (_num4_p = new numeric(4))->setflag(status_flags::dynallocated);
-               (_num5_p = new numeric(5))->setflag(status_flags::dynallocated);
-               (_num6_p = new numeric(6))->setflag(status_flags::dynallocated);
-               (_num7_p = new numeric(7))->setflag(status_flags::dynallocated);
-               (_num8_p = new numeric(8))->setflag(status_flags::dynallocated);
-               (_num9_p = new numeric(9))->setflag(status_flags::dynallocated);
-               (_num10_p = new numeric(10))->setflag(status_flags::dynallocated);
-               (_num11_p = new numeric(11))->setflag(status_flags::dynallocated);
-               (_num12_p = new numeric(12))->setflag(status_flags::dynallocated);
-               (_num15_p = new numeric(15))->setflag(status_flags::dynallocated);
-               (_num18_p = new numeric(18))->setflag(status_flags::dynallocated);
-               (_num20_p = new numeric(20))->setflag(status_flags::dynallocated);
-               (_num24_p = new numeric(24))->setflag(status_flags::dynallocated);
-               (_num25_p = new numeric(25))->setflag(status_flags::dynallocated);
-               (_num30_p = new numeric(30))->setflag(status_flags::dynallocated);
-               (_num48_p = new numeric(48))->setflag(status_flags::dynallocated);
-               (_num60_p = new numeric(60))->setflag(status_flags::dynallocated);
-               (_num120_p = new numeric(120))->setflag(status_flags::dynallocated);
+               _num1_4_p = (const numeric *)&dynallocate<numeric>(1,4);
+               _num1_3_p = (const numeric *)&dynallocate<numeric>(1,3);
+               _num1_2_p = (const numeric *)&dynallocate<numeric>(1,2);
+               _num1_p = (const numeric *)&dynallocate<numeric>(1);
+               _num2_p = (const numeric *)&dynallocate<numeric>(2);
+               _num3_p = (const numeric *)&dynallocate<numeric>(3);
+               _num4_p = (const numeric *)&dynallocate<numeric>(4);
+               _num5_p = (const numeric *)&dynallocate<numeric>(5);
+               _num6_p = (const numeric *)&dynallocate<numeric>(6);
+               _num7_p = (const numeric *)&dynallocate<numeric>(7);
+               _num8_p = (const numeric *)&dynallocate<numeric>(8);
+               _num9_p = (const numeric *)&dynallocate<numeric>(9);
+               _num10_p = (const numeric *)&dynallocate<numeric>(10);
+               _num11_p = (const numeric *)&dynallocate<numeric>(11);
+               _num12_p = (const numeric *)&dynallocate<numeric>(12);
+               _num15_p = (const numeric *)&dynallocate<numeric>(15);
+               _num18_p = (const numeric *)&dynallocate<numeric>(18);
+               _num20_p = (const numeric *)&dynallocate<numeric>(20);
+               _num24_p = (const numeric *)&dynallocate<numeric>(24);
+               _num25_p = (const numeric *)&dynallocate<numeric>(25);
+               _num30_p = (const numeric *)&dynallocate<numeric>(30);
+               _num48_p = (const numeric *)&dynallocate<numeric>(48);
+               _num60_p = (const numeric *)&dynallocate<numeric>(60);
+               _num120_p = (const numeric *)&dynallocate<numeric>(120);
 
                new((void*)&_ex_120) ex(*_num_120_p);
                new((void*)&_ex_60) ex(*_num_60_p);
@@ -391,55 +404,56 @@ library_init::~library_init()
                // It's really necessary to clean up, since the program
                // lifetime might not be the same as libginac.{so,dll} one
                // (e.g. consider // dlopen/dlsym/dlclose sequence).
-               delete _num120_p;
-               delete _num_120_p;
-               delete _num60_p;
-               delete _num_60_p;
-               delete _num48_p;
-               delete _num_48_p;
-               delete _num30_p;
-               delete _num_30_p;
-               delete _num25_p;
-               delete _num_25_p;
-               delete _num24_p;
-               delete _num_24_p;
-               delete _num20_p;
-               delete _num_20_p;
-               delete _num18_p;
-               delete _num_18_p;
-               delete _num15_p;
-               delete _num_15_p;
-               delete _num12_p;
-               delete _num_12_p;
-               delete _num11_p;
-               delete _num_11_p;
-               delete _num10_p;
-               delete _num_10_p;
-               delete _num9_p;
-               delete _num_9_p;
-               delete _num8_p;
-               delete _num_8_p;
-               delete _num7_p;
-               delete _num_7_p;
-               delete _num6_p;
-               delete _num_6_p;
-               delete _num5_p;
-               delete _num_5_p;
-               delete _num4_p;
-               delete _num_4_p;
-               delete _num3_p;
-               delete _num_3_p;
-               delete _num2_p;
-               delete _num_2_p;
-               delete _num1_p;
-               delete _num_1_p;
-               delete _num1_2_p;
-               delete _num_1_2_p;
-               delete _num1_3_p;
-               delete _num_1_3_p;
-               delete _num1_4_p;
-               delete _num_1_4_p;
-               delete _num0_p;
+               // Let the ex dtors care for deleting the numerics!
+               _ex120.~ex();
+               _ex_120.~ex();
+               _ex60.~ex();
+               _ex_60.~ex();
+               _ex48.~ex();
+               _ex_48.~ex();
+               _ex30.~ex();
+               _ex_30.~ex();
+               _ex25.~ex();
+               _ex_25.~ex();
+               _ex24.~ex();
+               _ex_24.~ex();
+               _ex20.~ex();
+               _ex_20.~ex();
+               _ex18.~ex();
+               _ex_18.~ex();
+               _ex15.~ex();
+               _ex_15.~ex();
+               _ex12.~ex();
+               _ex_12.~ex();
+               _ex11.~ex();
+               _ex_11.~ex();
+               _ex10.~ex();
+               _ex_10.~ex();
+               _ex9.~ex();
+               _ex_9.~ex();
+               _ex8.~ex();
+               _ex_8.~ex();
+               _ex7.~ex();
+               _ex_7.~ex();
+               _ex6.~ex();
+               _ex_6.~ex();
+               _ex5.~ex();
+               _ex_5.~ex();
+               _ex4.~ex();
+               _ex_4.~ex();
+               _ex3.~ex();
+               _ex_3.~ex();
+               _ex2.~ex();
+               _ex_2.~ex();
+               _ex1.~ex();
+               _ex_1.~ex();
+               _ex1_2.~ex();
+               _ex_1_2.~ex();
+               _ex1_3.~ex();
+               _ex_1_3.~ex();
+               _ex1_4.~ex();
+               _ex_1_4.~ex();
+               _ex0.~ex();
        }
 }