X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Futils.cpp;h=5ac9a60f9bb75056923a253cae2e2679089defa4;hp=f44ed9fa821fd6fbcb8bd4c08c029ad8c3899fbf;hb=b773294dd380ae81056c3d37b647500aae738ea1;hpb=aff357309f6611a59efb10d06d3dcfd3812a9ec5 diff --git a/ginac/utils.cpp b/ginac/utils.cpp index f44ed9fa..5ac9a60f 100644 --- a/ginac/utils.cpp +++ b/ginac/utils.cpp @@ -4,7 +4,7 @@ * but not of any interest to the user of the library. */ /* - * GiNaC Copyright (C) 1999-2008 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2020 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 & 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(-120); + _num_60_p = (const numeric *)&dynallocate(-60); + _num_48_p = (const numeric *)&dynallocate(-48); + _num_30_p = (const numeric *)&dynallocate(-30); + _num_25_p = (const numeric *)&dynallocate(-25); + _num_24_p = (const numeric *)&dynallocate(-24); + _num_20_p = (const numeric *)&dynallocate(-20); + _num_18_p = (const numeric *)&dynallocate(-18); + _num_15_p = (const numeric *)&dynallocate(-15); + _num_12_p = (const numeric *)&dynallocate(-12); + _num_11_p = (const numeric *)&dynallocate(-11); + _num_10_p = (const numeric *)&dynallocate(-10); + _num_9_p = (const numeric *)&dynallocate(-9); + _num_8_p = (const numeric *)&dynallocate(-8); + _num_7_p = (const numeric *)&dynallocate(-7); + _num_6_p = (const numeric *)&dynallocate(-6); + _num_5_p = (const numeric *)&dynallocate(-5); + _num_4_p = (const numeric *)&dynallocate(-4); + _num_3_p = (const numeric *)&dynallocate(-3); + _num_2_p = (const numeric *)&dynallocate(-2); + _num_1_p = (const numeric *)&dynallocate(-1); + _num_1_2_p = (const numeric *)&dynallocate(-1,2); + _num_1_3_p = (const numeric *)&dynallocate(-1,3); + _num_1_4_p = (const numeric *)&dynallocate(-1,4); + _num0_p = (const numeric *)&dynallocate(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(1,4); + _num1_3_p = (const numeric *)&dynallocate(1,3); + _num1_2_p = (const numeric *)&dynallocate(1,2); + _num1_p = (const numeric *)&dynallocate(1); + _num2_p = (const numeric *)&dynallocate(2); + _num3_p = (const numeric *)&dynallocate(3); + _num4_p = (const numeric *)&dynallocate(4); + _num5_p = (const numeric *)&dynallocate(5); + _num6_p = (const numeric *)&dynallocate(6); + _num7_p = (const numeric *)&dynallocate(7); + _num8_p = (const numeric *)&dynallocate(8); + _num9_p = (const numeric *)&dynallocate(9); + _num10_p = (const numeric *)&dynallocate(10); + _num11_p = (const numeric *)&dynallocate(11); + _num12_p = (const numeric *)&dynallocate(12); + _num15_p = (const numeric *)&dynallocate(15); + _num18_p = (const numeric *)&dynallocate(18); + _num20_p = (const numeric *)&dynallocate(20); + _num24_p = (const numeric *)&dynallocate(24); + _num25_p = (const numeric *)&dynallocate(25); + _num30_p = (const numeric *)&dynallocate(30); + _num48_p = (const numeric *)&dynallocate(48); + _num60_p = (const numeric *)&dynallocate(60); + _num120_p = (const numeric *)&dynallocate(120); new((void*)&_ex_120) ex(*_num_120_p); new((void*)&_ex_60) ex(*_num_60_p); @@ -391,58 +404,61 @@ 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(); } } +void library_init::init_unarchivers() { } + // comment skeleton for header files