981e193c12898c8dd27c101c9206e724ec31e230
[ginac.git] / check / genex.cpp
1 /** @file genex.cpp
2  *
3  *  Provides some routines for generating expressions that are later used as 
4  *  input in the consistency checks. */
5
6 /*
7  *  GiNaC Copyright (C) 1999-2019 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 #include "ginac.h"
25 using namespace GiNaC;
26
27 #include <cstdlib>
28 using namespace std;
29
30 /* Create a dense univariate random polynomial in x.
31  * (of the form 9 - 22*a - 17*a^2 + 14*a^3 + 7*a^4 + 7a^5 if degree==5) */
32 const ex
33 dense_univariate_poly(const symbol & x, unsigned degree)
34 {
35         ex unipoly;
36         
37         for (unsigned i=0; i<=degree; ++i)
38                 unipoly += numeric((rand()-RAND_MAX/2))*pow(x,i);
39         
40         return unipoly;
41 }
42
43 /* Create a dense bivariate random polynomial in x1 and x2.
44  * (of the form 9 + 52*x1 - 27*x1^2 + 84*x2 + 7*x2^2 - 12*x1*x2 if degree==2)
45  */
46 const ex
47 dense_bivariate_poly(const symbol & x1, const symbol & x2, unsigned degree)
48 {
49         ex bipoly;
50         
51         for (unsigned i1=0; i1<=degree; ++i1)
52                 for (unsigned i2=0; i2<=degree-i1; ++i2)
53                         bipoly += numeric((rand()-RAND_MAX/2))*pow(x1,i1)*pow(x2,i2);
54         
55         return bipoly;
56 }
57
58 /* Chose a random symbol or number from the argument list. */
59 const ex
60 random_symbol(const symbol & x,
61               const symbol & y,
62               const symbol & z,
63               bool rational = true,
64               bool complex = false)
65 {
66         ex e;
67         switch (abs(rand()) % 4) {
68                 case 0:
69                         e = x;
70                         break;
71                 case 1:
72                         e = y;
73                         break;
74                 case 2:
75                         e = z;
76                         break;
77                 case 3: {
78                         int c1;
79                         do { c1 = rand()%20 - 10; } while (!c1);
80                         int c2;
81                         do { c2 = rand()%20 - 10; } while (!c2);
82                         if (!rational)
83                                 c2 = 1;
84                         e = numeric(c1, c2);
85                         if (complex && !(rand()%5))
86                                 e = e*I;
87                         break;
88                 }
89         }
90         return e;
91 }
92
93 /* Create a sparse random tree in three symbols. */
94 const ex
95 sparse_tree(const symbol & x,
96             const symbol & y,
97             const symbol & z,
98             int level,
99             bool trig = false,  // true includes trigonometric functions
100             bool rational = true, // false excludes coefficients in Q
101             bool complex = false) // true includes complex numbers
102 {
103         if (level == 0)
104                 return random_symbol(x,y,z,rational,complex);
105         switch (abs(rand()) % 10) {
106                 case 0:
107                 case 1:
108                 case 2:
109                 case 3:
110                         return add(sparse_tree(x,y,z,level-1, trig, rational),
111                                            sparse_tree(x,y,z,level-1, trig, rational));
112                 case 4:
113                 case 5:
114                 case 6:
115                         return mul(sparse_tree(x,y,z,level-1, trig, rational),
116                                            sparse_tree(x,y,z,level-1, trig, rational));
117                 case 7:
118                 case 8: {
119                         ex powbase;
120                         do {
121                                 powbase = sparse_tree(x,y,z,level-1, trig, rational);
122                         } while (powbase.is_zero());
123                         return pow(powbase, abs(rand() % 4));
124                         break;
125                 }
126                 case 9:
127                         if (trig) {
128                                 switch (abs(rand()) % 4) {
129                                         case 0:
130                                                 return sin(sparse_tree(x,y,z,level-1, trig, rational));
131                                         case 1:
132                                                 return cos(sparse_tree(x,y,z,level-1, trig, rational));
133                                         case 2:
134                                                 return exp(sparse_tree(x,y,z,level-1, trig, rational));
135                                         case 3: {
136                                                 ex logex;
137                                                 do {
138                                                         ex logarg;
139                                                         do {
140                                                                 logarg = sparse_tree(x,y,z,level-1, trig, rational);
141                                                         } while (logarg.is_zero());
142                                                         // Keep the evaluator from accidentally plugging an
143                                                         // unwanted I in the tree:
144                                                         if (!complex && logarg.info(info_flags::negative))
145                                                                 logarg = -logarg;
146                                                         logex = log(logarg);
147                                                 } while (logex.is_zero());
148                                                 return logex;
149                                                 break;
150                                         }
151                                 }
152                         } else
153                                 return random_symbol(x,y,z,rational,complex);
154         }
155
156         return 0;
157 }