1 // -*- mode:C++ ; compile-command: "g++ -I.. -I../include -DHAVE_CONFIG_H -DIN_GIAC -DGIAC_GENERIC_CONSTANTS -fno-strict-aliasing -g -c gen.cc -Wall" -*-
2 #include "giacPCH.h"
3 #ifdef KHICAS
4 #include "kdisplay.h"
5 #if defined DEVICE && !defined NSPIRE_NEWLIB
6 size_t stackptr=0x20036000;
7 #else
8 size_t stackptr=0xffffffffffffffff;
9 #endif
10 #endif
11
12 /*
13 * Copyright (C) 2001,14 B. Parisse, Institut Fourier, 38402 St Martin d'Heres
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 3 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 */
28 using namespace std;
29 #if !defined NSPIRE && !defined FXCG && !defined KHICAS
30 #include <cstdlib>
31 #include <iomanip>
32 #endif
33 #define __USE_ISOC9X 1
34 #include <stdexcept>
35 #include <ctype.h>
36 #include <math.h>
37 #include <list>
38 #include <errno.h>
39 #include <string.h>
40 // #include <wstring.h>
41 #include "gen.h"
42 #include "gausspol.h"
43 #include "identificateur.h"
44 #include "poly.h"
45 #include "usual.h"
46 #include "input_lexer.h"
47 #include "sym2poly.h"
48 #include "vecteur.h"
49 #include "modpoly.h"
50 #include "alg_ext.h"
51 #include "prog.h"
52 #include "rpn.h"
53 #include "plot.h"
54 #include "intg.h"
55 #include "subst.h"
56 #include "derive.h"
57 #include "threaded.h"
58 #include "maple.h"
59 #include "solve.h"
60 #include "csturm.h"
61 #include "sparse.h"
62 #if defined GIAC_HAS_STO_38 || defined NSPIRE || defined NSPIRE_NEWLIB || defined FXCG || defined GIAC_GGB || defined USE_GMP_REPLACEMENTS || defined KHICAS
is_graphe(const giac::gen & g,std::string & disp_out,const giac::context *)63 inline bool is_graphe(const giac::gen &g,std::string &disp_out,const giac::context *){ return false; }
64 #else
65 #include "graphtheory.h"
66 #endif
67 #include "giacintl.h"
68 #ifdef RTOS_THREADX
69 extern "C" uint32_t mainThreadStack[];
70 #endif
71 #ifdef HAVE_PTHREAD_H
72 #include <pthread.h>
73 #endif
74
75 #ifdef EMCC_BIND
76 #include <emscripten/bind.h>
77 #endif
78
79 #if defined EMCC && !defined GIAC_GGB
80
81 #if 0 // def EMCC_GLUT
82 #include <GL/glut.h>
83 #else
84 #include "SDL/SDL.h"
85 #include <SDL/SDL_ttf.h>
86 #include <emscripten.h>
87 //#include "SDL/SDL_image.h"
88 #include "SDL/SDL_opengl.h"
89 #endif
90
91 #include "opengl.h"
92 #endif
93
94 #ifdef USE_GMP_REPLACEMENTS
95 #undef HAVE_GMPXX_H
96 #undef HAVE_LIBMPFR
97 #endif
98
99 #ifndef NO_NAMESPACE_GIAC
100 namespace giac {
101 #endif // ndef NO_NAMESPACE_GIAC
102
103 #if 0 // def ASPEN_GEOMETRY
104 #define ALLOCSMALL
105 #endif
106
107 #ifdef ALLOCSMALL
108
109 // 32 bytes structure: 4096/32=128 slots of memory
110 struct eight_int {
111 int i1,i2,i3,i4,i5,i6,i7,i8;
112 };
113
114 struct six_int {
115 int i1,i2,i3,i4,i5,i6;
116 };
117
118 struct four_int {
119 int i1,i2,i3,i4;
120 };
121
122 #ifdef RTOS_THREADX
123 const int ALLOC24=5*32;
124 const int ALLOC32=2*32;
125 const int ALLOC16=4*32;
126 static unsigned int freeslot24[ALLOC24/32]={0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,0xffffffff};
127 static unsigned int freeslot16[ALLOC16/32]={0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
128 static unsigned int freeslot32[ALLOC32/32]={0xffffffff, 0xffffffff};
129 #else
130 const int ALLOC24=16*32;
131 const int ALLOC32=16*32;
132 const int ALLOC16=16*32;
133 static unsigned int freeslot24[ALLOC24/32]={
134 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
135 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
136 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
137 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
138 };
139 static unsigned int freeslot16[ALLOC16/32]={
140 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
141 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
142 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
143 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
144 };
145 static unsigned int freeslot32[ALLOC32/32]={
146 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
147 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
148 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
149 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
150 };
151 #endif
152 static six_int tab24[ALLOC24];
153 static four_int tab16[ALLOC16];
154 static eight_int tab32[ALLOC32];
155
freeslotpos(unsigned n)156 unsigned freeslotpos(unsigned n){
157 unsigned r=1;
158 if (n<<16==0) r+= 16, n>>=16;
159 if (n<<24==0) r+= 8, n>>=8;
160 if (n<<28==0) r+= 4, n>>=4;
161 if (n<<30==0) r+= 2, n>>=2;
162 r -= n&1;
163 return r;
164 }
165
allocfast(std::size_t size)166 static void* allocfast(std::size_t size){
167 int i,pos;
168 if (size==24){
169 for (i=0;i<ALLOC24/32;++i){
170 if (freeslot24[i]){
171 pos=freeslotpos(freeslot24[i]);
172 freeslot24[i] &= ~(1<<pos);
173 return (void *) (tab24+i*32+pos);
174 }
175 }
176 }
177 if (size==16){
178 for (i=0;i<ALLOC16/32;++i){
179 if (freeslot16[i]){
180 pos=freeslotpos(freeslot16[i]);
181 freeslot16[i] &= ~(1<<pos);
182 return (void *) (tab16+i*32+pos);
183 }
184 }
185 }
186 if (size==32){
187 for (i=0;i<ALLOC32/32;++i){
188 if (freeslot32[i]){
189 pos=freeslotpos(freeslot32[i]);
190 freeslot32[i] &= ~(1<<pos);
191 return (void *) (tab32+i*32+pos);
192 }
193 }
194 }
195 void * p = std::malloc(size);
196 #ifndef NO_STDEXCEPT
197 if(!p) {
198 std::bad_alloc ba;
199 throw ba;
200 }
201 #endif
202 return p;
203 }
204
deletefast(void * obj)205 static void deletefast(void* obj){
206 if ( ((size_t)obj >= (size_t) &tab24[0]) &&
207 ((size_t)obj < (size_t) &tab24[ALLOC24]) ){
208 int pos= ((size_t)obj -((size_t) &tab24[0]))/sizeof(six_int);
209 freeslot24[pos/32] |= 1 << (pos%32);
210 return;
211 }
212 if ( ((size_t)obj>=(size_t) &tab16[0] ) &&
213 ((size_t)obj<(size_t) &tab16[ALLOC16] ) ){
214 * (unsigned *) obj= 0;
215 int pos= ((size_t)obj -((size_t) &tab16[0]))/sizeof(four_int);
216 freeslot16[pos/32] |= 1 << (pos%32);
217 return;
218 }
219 if ( ((size_t)obj>=(size_t) &tab32[0]) &&
220 ((size_t)obj<(size_t) &tab32[ALLOC32]) ){
221 int pos= ((size_t)obj -((size_t) &tab32[0]))/sizeof(eight_int);
222 freeslot32[pos/32] |= 1 << (pos%32);
223 }
224 else
225 free(obj);
226 }
227 #endif // ALLOCSMALL
228
229 #if defined(SMARTPTR64) || !defined(ALLOCSMALL)
deletecomplex(ref_complex * ptr)230 inline void deletecomplex(ref_complex * ptr){
231 delete ptr ;
232 }
233 #else
deletecomplex(ref_complex * ptr)234 static void deletecomplex(ref_complex * ptr){
235 ptr->re=0;
236 ptr->im=0;
237 deletefast(ptr);
238 }
239 #endif
240
241 #if defined(SMARTPTR64) || !defined(ALLOCSMALL)
deletesymbolic(ref_symbolic * ptr)242 inline void deletesymbolic(ref_symbolic * ptr){
243 delete ptr ;
244 }
245 #else
deletesymbolic(ref_symbolic * ptr)246 static void deletesymbolic(ref_symbolic * ptr){
247 ptr->s.feuille=0;
248 deletefast(ptr);
249 }
250 #endif
251
252 #if defined(SMARTPTR64) || !defined(IMMEDIATE_VECTOR) || !defined(ALLOCSMALL)
delete_ref_vecteur(ref_vecteur * ptr)253 void delete_ref_vecteur(ref_vecteur * ptr){
254 delete ptr ;
255 }
256 #else
delete_ref_vecteur(ref_vecteur * ptr)257 void delete_ref_vecteur(ref_vecteur * ptr){
258 ptr->v.clear();
259 deletefast(ptr);
260 }
261 #endif
262
263 /*
264 unsigned control_c_counter=0;
265 unsigned control_c_counter_mask=0xff;
266 */
267
268 #ifdef HAVE_LIBPTHREAD
269 pthread_mutex_t mpfr_mutex = PTHREAD_MUTEX_INITIALIZER;
270 pthread_mutex_t locale_mutex = PTHREAD_MUTEX_INITIALIZER;
271 #endif
272
sprintfdouble(char * ch,const char * format,double d)273 void sprintfdouble(char * ch,const char * format,double d){
274 #ifdef FXCG
275 sprint_double(ch,d); // no format
276 #else
277 #ifdef NSPIRE
278 dtostr(d,8,ch); // FIXME!
279 #else
280 #ifdef EMCC
281 sprintf(ch,format,d);
282 #else
283 my_sprintf(ch,format,d);
284 #endif
285 #endif
286 #endif
287 }
288
289 // bool is_inevalf=false;
290
last_evaled_function(GIAC_CONTEXT)291 static string last_evaled_function(GIAC_CONTEXT){
292 const char * last =last_evaled_function_name(contextptr);
293 if (!last)
294 return "";
295 string res;
296 bool paren=true;
297 if (abs_calc_mode(contextptr)==38 && !strcmp(last,"sqrt"))
298 res="√";
299 else {
300 string tmp=unlocalize(autosimplify(contextptr));
301 if (tmp!=last)
302 res=last;
303 else
304 paren=false;
305 }
306 if (paren) res +="(";
307 const gen * lastarg= last_evaled_argptr(contextptr);
308 if (lastarg){
309 if (strcmp(last,"try_catch")==0 && lastarg->type==_VECT && !lastarg->_VECTptr->empty()){ // workaround for optimizations on some operations like *
310 res = lastarg->_VECTptr->front().print(contextptr);
311 paren = false;
312 }
313 else
314 res += lastarg->print(contextptr);
315 }
316 if (paren) res += ")";
317 debug_struct * dbg = debug_ptr(contextptr);
318 if (!dbg->sst_at_stack.empty()){
319 res += gettext(" in ");
320 gen pos=dbg->args_stack.back();
321 string tmp;
322 if (pos.type==_VECT && pos._VECTptr->size()>=2){
323 vecteur v(pos._VECTptr->begin()+1,pos._VECTptr->end());
324 if (v.size()==1){
325 if (v.front().type==_VECT && v.front()._VECTptr->empty())
326 tmp=pos._VECTptr->front().print(contextptr)+"()";
327 else
328 tmp=pos._VECTptr->front().print(contextptr)+"("+v.front().print(contextptr)+")";
329 }
330 else
331 tmp = pos._VECTptr->front().print(contextptr)+"("+gen(v,_SEQ__VECT).print(contextptr)+")";
332 }
333 else
334 tmp = pos.print(contextptr);
335 res += tmp;
336 res += gettext(" instruction #");
337 res += print_INT_(dbg->current_instruction);
338 res += gettext(" error, try debug(")+tmp+")";
339 }
340 else
341 res += ' ';
342 return res+"\n ";
343 }
344
345 #ifdef NO_STDEXCEPT // FIXME
settypeerr(GIAC_CONTEXT)346 void settypeerr(GIAC_CONTEXT){
347 gentypeerr(contextptr);
348 }
349
setsizeerr(GIAC_CONTEXT)350 void setsizeerr(GIAC_CONTEXT){
351 gensizeerr(contextptr);
352 }
353
setdimerr(GIAC_CONTEXT)354 void setdimerr(GIAC_CONTEXT){
355 gendimerr(contextptr);
356 }
357
settypeerr(const string & s)358 void settypeerr(const string & s){
359 gentypeerr(s);
360 }
361
setsizeerr(const string & s)362 void setsizeerr(const string & s){
363 gensizeerr(s);
364 }
365
setdimerr(const string & s)366 void setdimerr(const string & s){
367 gendimerr(s);
368 }
369
divisionby0err(const gen & e,GIAC_CONTEXT)370 void divisionby0err(const gen & e,GIAC_CONTEXT){
371 gendivisionby0err(e,contextptr);
372 }
373
cksignerr(const gen & e,GIAC_CONTEXT)374 void cksignerr(const gen & e,GIAC_CONTEXT){
375 gencksignerr(e,contextptr);
376 }
377
invalidserieserr(const string & s,GIAC_CONTEXT)378 void invalidserieserr(const string & s,GIAC_CONTEXT){
379 geninvalidserieserr(s,contextptr);
380 }
381
toofewargs(const string & s,GIAC_CONTEXT)382 void toofewargs(const string & s,GIAC_CONTEXT){
383 gentoofewargs(s,contextptr);
384 }
385
toomanyargs(const string & s,GIAC_CONTEXT)386 void toomanyargs(const string & s,GIAC_CONTEXT){
387 gentoomanyargs(s,contextptr);
388 }
389
maxordererr(GIAC_CONTEXT)390 void maxordererr(GIAC_CONTEXT){
391 genmaxordererr(contextptr);
392 }
393
setstabilityerr(GIAC_CONTEXT)394 void setstabilityerr(GIAC_CONTEXT){
395 genstabilityerr(contextptr);
396 }
397 #else
settypeerr(GIAC_CONTEXT)398 void settypeerr(GIAC_CONTEXT){
399 throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Bad Argument Type")));
400 }
401
setsizeerr(GIAC_CONTEXT)402 void setsizeerr(GIAC_CONTEXT){
403 throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Bad Argument Value")));
404 }
405
setdimerr(GIAC_CONTEXT)406 void setdimerr(GIAC_CONTEXT){
407 throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Invalid dimension")));
408 }
409
settypeerr(const string & s)410 void settypeerr(const string & s){
411 throw(std::runtime_error(s+gettext(" Error: Bad Argument Type")));
412 }
413
setsizeerr(const string & s)414 void setsizeerr(const string & s){
415 throw(std::runtime_error(s+gettext(" Error: Bad Argument Value")));
416 }
417
setdimerr(const string & s)418 void setdimerr(const string & s){
419 throw(std::runtime_error(s+gettext(" Error: Invalid dimension")));
420 }
421
divisionby0err(const gen & e,GIAC_CONTEXT)422 void divisionby0err(const gen & e,GIAC_CONTEXT){
423 throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Division of ") + e.print(contextptr)+ gettext(" by 0")));
424 }
425
cksignerr(const gen & e,GIAC_CONTEXT)426 void cksignerr(const gen & e,GIAC_CONTEXT){
427 throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Unable to check sign: ")+e.print(contextptr)));
428 }
429
invalidserieserr(const string & s,GIAC_CONTEXT)430 void invalidserieserr(const string & s,GIAC_CONTEXT){
431 throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Invalid series expansion: ")+s));
432 }
433
toofewargs(const string & s,GIAC_CONTEXT)434 void toofewargs(const string & s,GIAC_CONTEXT){
435 throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Too few arguments: ")+s));
436 }
437
toomanyargs(const string & s,GIAC_CONTEXT)438 void toomanyargs(const string & s,GIAC_CONTEXT){
439 throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Too many arguments: ")+s));
440 }
441
maxordererr(GIAC_CONTEXT)442 void maxordererr(GIAC_CONTEXT){
443 throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Max order (")+gen(max_series_expansion_order).print(contextptr)+gettext(") exceeded or non unidirectional series")));
444 }
445
setstabilityerr(GIAC_CONTEXT)446 void setstabilityerr(GIAC_CONTEXT){
447 throw(std::runtime_error(last_evaled_function(contextptr)+gettext("calculation size limit exceeded")));
448 }
449 #endif // NO_STDEXCEPT
450
undeferr(const string & s)451 gen undeferr(const string & s){
452 #ifdef EMCC
453 CERR << s << '\n';
454 #endif
455 #if defined NSPIRE || defined FXCG
456 wait_1ms(1);
457 #else
458 #ifdef GIAC_HAS_STO_38
459 usleep(10);
460 #else
461 usleep(1000);
462 #endif
463 #endif
464 #if !defined NO_STDEXCEPT && !defined EMCC
465 if (debug_infolevel!=-5)
466 throw(std::runtime_error(s));
467 #endif
468 gen res(string2gen(s,false));
469 res.subtype=-1;
470 return res;
471 }
472
gentypeerr(GIAC_CONTEXT)473 gen gentypeerr(GIAC_CONTEXT){
474 return undeferr(last_evaled_function(contextptr)+gettext("Error: Bad Argument Type"));
475 }
476
gentypeerr(gen & g,GIAC_CONTEXT)477 void gentypeerr(gen & g,GIAC_CONTEXT){
478 g=undeferr(last_evaled_function(contextptr)+gettext("Error: Bad Argument Type"));
479 }
480
gensizeerr(GIAC_CONTEXT)481 gen gensizeerr(GIAC_CONTEXT){
482 return undeferr(last_evaled_function(contextptr)+gettext("Error: Bad Argument Value"));
483 }
484
gensizeerr(gen & g,GIAC_CONTEXT)485 void gensizeerr(gen & g,GIAC_CONTEXT){
486 g=undeferr(last_evaled_function(contextptr)+gettext("Error: Bad Argument Value"));
487 }
488
gendimerr(GIAC_CONTEXT)489 gen gendimerr(GIAC_CONTEXT){
490 return undeferr(last_evaled_function(contextptr)+gettext("Error: Invalid dimension"));
491 }
492
gendimerr(gen & g,GIAC_CONTEXT)493 void gendimerr(gen & g,GIAC_CONTEXT){
494 g=undeferr(last_evaled_function(contextptr)+gettext("Error: Invalid dimension"));
495 }
496
gentypeerr(const string & s)497 gen gentypeerr(const string & s){
498 return undeferr(s+gettext(" Error: Bad Argument Type"));
499 }
500
gentypeerr(const char * ch,gen & g)501 void gentypeerr(const char * ch,gen & g){
502 g=undeferr(string(gettext(ch))+gettext(" Error: Bad Argument Type"));
503 }
504
gensizeerr(const string & s)505 gen gensizeerr(const string & s){
506 return undeferr(s+gettext(" Error: Bad Argument Value"));
507 }
508
gensizeerr(const char * ch,gen & g)509 void gensizeerr(const char * ch,gen & g){
510 g=undeferr(string(gettext(ch))+gettext(" Error: Bad Argument Value"));
511 }
512
gendimerr(const string & s)513 gen gendimerr(const string & s){
514 return undeferr(s+gettext(" Error: Invalid dimension"));
515 }
516
gendimerr(const char * ch,gen & g)517 void gendimerr(const char * ch,gen & g){
518 g=undeferr(string(gettext(ch))+gettext(" Error: Invalid dimension"));
519 }
520
gendivisionby0err(const gen & e,GIAC_CONTEXT)521 gen gendivisionby0err(const gen & e,GIAC_CONTEXT){
522 return undeferr(last_evaled_function(contextptr)+gettext("Error: Division of ") + e.print(contextptr)+ gettext(" by 0"));
523 }
524
gencksignerr(const gen & e,GIAC_CONTEXT)525 gen gencksignerr(const gen & e,GIAC_CONTEXT){
526 return undeferr(last_evaled_function(contextptr)+gettext("Error: Unable to check sign: ")+e.print(contextptr));
527 }
528
geninvalidserieserr(const string & s,GIAC_CONTEXT)529 gen geninvalidserieserr(const string & s,GIAC_CONTEXT){
530 *logptr(contextptr) << undeferr(last_evaled_function(contextptr)+gettext("Error: Invalid series expansion: ")+s) << '\n';
531 return undef;
532 }
533
gentoofewargs(const string & s,GIAC_CONTEXT)534 gen gentoofewargs(const string & s,GIAC_CONTEXT){
535 return undeferr(last_evaled_function(contextptr)+gettext("Error: Too few arguments: ")+s);
536 }
537
gentoomanyargs(const string & s,GIAC_CONTEXT)538 gen gentoomanyargs(const string & s,GIAC_CONTEXT){
539 return undeferr(last_evaled_function(contextptr)+gettext("Error: Too many arguments: ")+s);
540 }
541
genmaxordererr(GIAC_CONTEXT)542 gen genmaxordererr(GIAC_CONTEXT){
543 return undeferr(last_evaled_function(contextptr)+gettext("Error: Max order (")+gen(max_series_expansion_order).print(contextptr)+gettext(") exceeded or non unidirectional series"));
544 }
545
genstabilityerr(GIAC_CONTEXT)546 gen genstabilityerr(GIAC_CONTEXT){
547 return undeferr(last_evaled_function(contextptr)+gettext("Error: calculation size limit exceeded"));
548 }
549
550 // void parseerror(){
551 // throw(std::runtime_error("Parse error"));
552 // }
553
554 enum { debugtype=_CPLX };
555 #define debugtypeptr _CPLXptr
556
557 /* Constructors, destructors, copy */
vector2vecteur(const vecteur & v)558 gen vector2vecteur(const vecteur & v){
559 gen g=v.back()-v.front();
560 if (g.type!=_VECT)
561 return makenewvecteur(re(g,context0),im(g,context0));
562 return g;
563 }
564
change_subtype(int newsubtype)565 gen gen::change_subtype(int newsubtype){
566 subtype=newsubtype;
567 return *this;
568 }
569
change_subtype(const gen & g,int newsubtype)570 gen change_subtype(const gen & g,int newsubtype){
571 gen g_(g);
572 g_.subtype=newsubtype;
573 return g_;
574 }
575
complex_display_ptr(const gen & g)576 int * complex_display_ptr(const gen & g) {
577 if (g.type!=_CPLX)
578 return 0;
579 return (int *)(g._CPLXptr)-1;
580 }
581
gen(long i)582 gen::gen(long i) {
583 #ifdef COMPILE_FOR_STABILITY
584 control_c();
585 #endif
586 #ifdef SMARTPTR64
587 * ((ulonglong * ) this)=0;
588 #endif
589 val=(int)i;
590 // longlong temp=val;
591 if (val==i && val!=1<<31){
592 #ifndef SMARTPTR64
593 type=_INT_;
594 subtype=0;
595 #endif
596 }
597 else {
598 #ifdef SMARTPTR64
599 * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(64)) << 16;
600 #else
601 __ZINTptr = new ref_mpz_t(64);
602 #endif
603 type =_ZINT;
604 subtype=0;
605 // convert longlong to mpz_t
606 bool signe=(i<0);
607 if (signe)
608 i=-i;
609 unsigned int i1=sizeof(long)==4?0:i>>32;
610 unsigned int i2=(unsigned int)i;
611 mpz_set_ui(*_ZINTptr,i1);
612 mpz_mul_2exp(*_ZINTptr,*_ZINTptr,32);
613 mpz_add_ui(*_ZINTptr,*_ZINTptr,i2);
614 if (signe)
615 mpz_neg(*_ZINTptr,*_ZINTptr);
616 }
617 }
618
gen(longlong i)619 gen::gen(longlong i) {
620 #ifdef COMPILE_FOR_STABILITY
621 control_c();
622 #endif
623 #ifdef SMARTPTR64
624 * ((ulonglong * ) this)=0;
625 #endif
626 val=(int)i;
627 // longlong temp=val;
628 if (val==i && val!=1<<31){
629 #ifndef SMARTPTR64
630 type=_INT_;
631 subtype=0;
632 #endif
633 }
634 else {
635 #ifdef SMARTPTR64
636 * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(64)) << 16;
637 #else
638 __ZINTptr = new ref_mpz_t(64);
639 #endif
640 type =_ZINT;
641 subtype=0;
642 // convert longlong to mpz_t
643 bool signe=(i<0);
644 if (signe)
645 i=-i;
646 unsigned int i1=i>>32;
647 unsigned int i2=(unsigned int)i;
648 mpz_set_ui(*_ZINTptr,i1);
649 mpz_mul_2exp(*_ZINTptr,*_ZINTptr,32);
650 mpz_add_ui(*_ZINTptr,*_ZINTptr,i2);
651 if (signe)
652 mpz_neg(*_ZINTptr,*_ZINTptr);
653 /*
654 longlong lbase=65536;
655 long base=65536;
656 longlong i1=i/lbase;
657 long i2=i1/lbase; // i2=i/2^32
658 //COUT << "Initialization of " << _ZINTptr << '\n' ;
659 mpz_init_set_si(*_ZINTptr,i2);
660 mpz_mul_ui(*_ZINTptr,*_ZINTptr,base); // i/2^32 * 2^16
661 long i2mod=i1 % lbase;
662 if (i2mod>0)
663 mpz_add_ui(*_ZINTptr,*_ZINTptr,i2mod);
664 else
665 mpz_sub_ui(*_ZINTptr,*_ZINTptr,-i2mod); // i/2^16
666 mpz_mul_ui(*_ZINTptr,*_ZINTptr,base); // i/2^16 * 2^16
667 long i1mod = i % lbase;
668 if (i1mod>0)
669 mpz_add_ui(*_ZINTptr,*_ZINTptr,i1mod);
670 else
671 mpz_sub_ui(*_ZINTptr,*_ZINTptr,-i1mod); // i
672 */
673 }
674 }
675
gen(longlong i,int nbits)676 gen::gen(longlong i,int nbits) {
677 #ifdef COMPILE_FOR_STABILITY
678 control_c();
679 #endif
680 #ifdef SMARTPTR64
681 * ((ulonglong * ) this)=0;
682 #endif
683 val=(int)i;
684 // longlong temp=val;
685 if (val==i && val!=1<<31){
686 #ifndef SMARTPTR64
687 type=_INT_;
688 subtype=0;
689 #endif
690 }
691 else {
692 #ifdef SMARTPTR64
693 * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(nbits)) << 16;
694 #else
695 __ZINTptr = new ref_mpz_t(nbits);
696 #endif
697 type =_ZINT;
698 subtype=0;
699 // convert longlong to mpz_t
700 bool signe=(i<0);
701 if (signe)
702 i=-i;
703 unsigned int i1=i>>32;
704 unsigned int i2=(unsigned int)i;
705 mpz_set_ui(*_ZINTptr,i1);
706 mpz_mul_2exp(*_ZINTptr,*_ZINTptr,32);
707 mpz_add_ui(*_ZINTptr,*_ZINTptr,i2);
708 if (signe)
709 mpz_neg(*_ZINTptr,*_ZINTptr);
710 }
711 }
712
713 #ifdef INT128
gen(int128_t i)714 gen::gen(int128_t i) {
715 #ifdef COMPILE_FOR_STABILITY
716 control_c();
717 #endif
718 #ifdef SMARTPTR64
719 * ((ulonglong * ) this)=0;
720 #endif
721 val=i;
722 // longlong temp=val;
723 if (val==i && val!=1<<31){
724 #ifndef SMARTPTR64
725 type=_INT_;
726 subtype=0;
727 #endif
728 }
729 else {
730 #ifdef SMARTPTR64
731 * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(128)) << 16;
732 #else
733 __ZINTptr = new ref_mpz_t(128);
734 #endif
735 type =_ZINT;
736 subtype=0;
737 bool signe=(i<0);
738 if (signe)
739 i=-i;
740 #if !defined(USE_GMP_REPLACEMENTS)
741 mpz_import(*_ZINTptr,4/* count*/,-1/*1 for least significant first*/,4/* sizeof unsigned*/,0,0,&i);
742 // CERR << gen(*_ZINTptr) ;
743 #else
744 unsigned int i3= i;
745 i = i>>32;
746 unsigned int i2= i;
747 i = i>>32;
748 unsigned int i1= i;
749 i = i>>32;
750 // convert to mpz_t
751 if (i1 || i){
752 mpz_set_ui(*_ZINTptr,(unsigned int) i);
753 mpz_mul_2exp(*_ZINTptr,*_ZINTptr,32);
754 mpz_add_ui(*_ZINTptr,*_ZINTptr,i1);
755 mpz_mul_2exp(*_ZINTptr,*_ZINTptr,32);
756 mpz_add_ui(*_ZINTptr,*_ZINTptr,i2);
757 }
758 else
759 mpz_set_ui(*_ZINTptr,i2);
760 mpz_mul_2exp(*_ZINTptr,*_ZINTptr,32);
761 mpz_add_ui(*_ZINTptr,*_ZINTptr,i3);
762 #endif
763 if (signe)
764 mpz_neg(*_ZINTptr,*_ZINTptr);
765 // CERR << " " << gen(*_ZINTptr) << '\n' ;
766 }
767 }
768 #endif
769
gen(const mpz_t & m)770 gen::gen(const mpz_t & m) {
771 if (int(mpz_sizeinbase(m,2))>MPZ_MAXLOG2){
772 type=0;
773 #if 1
774 *this=undef;
775 #else
776 *this=mpz_sgn(m)==-1?minus_inf:plus_inf;
777 #endif
778 return;
779 }
780 #ifdef COMPILE_FOR_STABILITY
781 control_c();
782 #endif
783 #ifdef SMARTPTR64
784 * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(m)) << 16;
785 #else
786 __ZINTptr= new ref_mpz_t(m);
787 #endif
788 #ifdef KHICAS
789 if ((size_t) _ZINTptr > stackptr)
790 ctrl_c=interrupted=true;
791 #endif
792 type =_ZINT;
793 subtype=0;
794 }
795
796 #if defined HAVE_GMPXX_H && !defined USE_GMP_REPLACEMENTS
gen(const mpz_class & m)797 gen::gen(const mpz_class & m){
798 int l=mpz_sizeinbase(m.get_mpz_t(),2);
799 if (l<32){
800 type = _INT_;
801 val = mpz_get_si(m.get_mpz_t());
802 }
803 else {
804 #ifdef SMARTPTR64
805 ref_mpz_t * ptr=new ref_mpz_t;
806 mpz_set(ptr->z,m.get_mpz_t());
807 * ((ulonglong * ) this) = ulonglong(ptr) << 16;
808 #else
809 __ZINTptr= new ref_mpz_t();
810 #ifdef KHICAS
811 if ((size_t) _ZINTptr > stackptr)
812 ctrl_c=interrupted=true;
813 #endif
814 mpz_set(__ZINTptr->z,m.get_mpz_t());
815 #endif
816 type =_ZINT;
817 }
818 subtype=0;
819 }
820 #endif
821
gen(const identificateur & s)822 gen::gen(const identificateur & s){
823 #ifdef COMPILE_FOR_STABILITY
824 control_c();
825 #endif
826 #ifdef SMARTPTR64
827 * ((ulonglong * ) this) = ulonglong(new ref_identificateur(s)) << 16;
828 #else
829 __IDNTptr= new ref_identificateur(s);
830 #endif
831 type=_IDNT;
832 subtype=0;
833 }
834
835 #if defined(SMARTPTR64) || !defined(IMMEDIATE_VECTOR) || !defined(ALLOCSMALL)
new_ref_vecteur(const vecteur & v)836 ref_vecteur * new_ref_vecteur(const vecteur & v){
837 return new ref_vecteur(v);
838 }
839 #else
new_ref_vecteur(const vecteur & v)840 ref_vecteur * new_ref_vecteur(const vecteur & v){
841 ref_vecteur * ptr=(ref_vecteur *) allocfast(sizeof(ref_vecteur));
842 ptr->ref_count=1;
843 *(unsigned *)&ptr->v=0;
844 *((unsigned *)&ptr->v+1)=0;
845 *((unsigned *)&ptr->v+2)=0;
846 *((unsigned *)&ptr->v+3)=0;
847 *((unsigned *)&ptr->v+4)=0;
848 *((unsigned *)&ptr->v+5)=0;
849 *((unsigned *)&ptr->v+6)=0;
850 ptr->v=v;
851 return ptr;
852 }
853 #endif
854
gen(const vecteur & v,short int s)855 gen::gen(const vecteur & v,short int s)
856 {
857 #ifdef SMARTPTR64
858 * ((ulonglong * ) this) = ulonglong(new ref_vecteur(v)) << 16;
859 #else
860 __VECTptr= new_ref_vecteur(v);
861 #endif
862 #ifdef KHICAS
863 if (v.size()>1 &&
864 ( (size_t) _VECTptr > stackptr ||
865 (size_t) _VECTptr->begin() > stackptr)
866 )
867 ctrl_c=interrupted=true;
868 #endif
869 type=_VECT;
870 subtype=(signed char)s;
871 }
872
gen(ref_vecteur * vptr,short int s)873 gen::gen(ref_vecteur * vptr,short int s){
874 #ifdef SMARTPTR64
875 * ((ulonglong * ) this) = ulonglong(vptr) << 16;
876 #else
877 __VECTptr= vptr;
878 #endif
879 type=_VECT;
880 subtype=(signed char)s;
881 #ifdef KHICAS
882 if (_VECTptr->size()>1 &&
883 ( (size_t) _VECTptr > stackptr ||
884 (size_t) _VECTptr->begin() > stackptr)
885 )
886 ctrl_c=interrupted=true;
887 #endif
888 }
889
890 #if defined(SMARTPTR64) || !defined(ALLOCSMALL)
new_ref_symbolic(const symbolic & s)891 ref_symbolic * new_ref_symbolic(const symbolic & s){
892 return new ref_symbolic(s);
893 }
894 #else
new_ref_symbolic(const symbolic & s)895 ref_symbolic * new_ref_symbolic(const symbolic & s){
896 ref_symbolic * ptr=(ref_symbolic *) allocfast(sizeof(ref_symbolic));
897 ptr->ref_count=1;
898 * (unsigned *) &ptr->s.sommet = 0;
899 ptr->s.feuille.type=0;
900 ptr->s=s;
901 return ptr;
902 }
903 #endif
904
gen(const symbolic & s)905 gen::gen(const symbolic & s){
906 #ifdef COMPILE_FOR_STABILITY
907 control_c();
908 #endif
909 #ifdef SMARTPTR64
910 * ((ulonglong * ) this) = ulonglong(new_ref_symbolic(s)) << 16;
911 #else
912 __SYMBptr = new_ref_symbolic(s) ;
913 #endif
914 type = _SYMB;
915 subtype = 0;
916 #ifdef KHICAS
917 if (_SYMBptr->sommet!=at_restart && _SYMBptr->sommet!=at_purge && (size_t) _SYMBptr > stackptr)
918 ctrl_c=interrupted=true;
919 #endif
920 }
921
gen(ref_symbolic * sptr)922 gen::gen(ref_symbolic * sptr){
923 #ifdef SMARTPTR64
924 * ((ulonglong * ) this) = ulonglong(sptr) << 16;
925 #else
926 __SYMBptr = sptr;
927 #endif
928 type = _SYMB;
929 subtype = 0;
930 #ifdef KHICAS
931 if (_SYMBptr->sommet!=at_restart && _SYMBptr->sommet!=at_purge && (size_t) _SYMBptr > stackptr)
932 ctrl_c=interrupted=true;
933 #endif
934 }
935
gen(ref_identificateur * sptr)936 gen::gen(ref_identificateur * sptr){
937 #ifdef SMARTPTR64
938 * ((ulonglong * ) this) = ulonglong(sptr) << 16;
939 #else
940 __IDNTptr = sptr;
941 #endif
942 type = _IDNT;
943 subtype = 0;
944 }
945
gen(const gen_user & g)946 gen::gen(const gen_user & g){
947 #ifdef SMARTPTR64
948 * ((ulonglong * ) this) = ulonglong(new ref_gen_user(g)) << 16;
949 #else
950 __USERptr = new ref_gen_user(g) ;
951 #endif
952 type = _USER;
953 subtype=0;
954 }
955
gen(ref_gen_user * sptr)956 gen::gen(ref_gen_user * sptr){
957 #ifdef SMARTPTR64
958 * ((ulonglong * ) this) = ulonglong(sptr) << 16;
959 #else
960 __USERptr = sptr;
961 #endif
962 type = _USER;
963 subtype = 0;
964 }
965
gen(const eqwdata & g)966 gen::gen(const eqwdata & g){
967 #ifdef SMARTPTR64
968 * ((ulonglong * ) this) = ulonglong(new ref_eqwdata(g)) << 16;
969 #else
970 __EQWptr = new ref_eqwdata(g);
971 #endif
972 type = _EQW;
973 subtype=0;
974 }
975
gen(const grob & g)976 gen::gen(const grob & g){
977 #ifdef SMARTPTR64
978 * ((ulonglong * ) this) = ulonglong(new ref_grob(g)) << 16;
979 #else
980 __GROBptr = new ref_grob(g);
981 #endif
982 type = _GROB;
983 subtype=0;
984 }
985
makemap()986 gen makemap(){
987 gen g;
988 #ifdef SMARTPTR64
989 * ((ulonglong * ) &g) = ulonglong(new ref_gen_map) << 16;
990 #else
991 #if 1 // def NSPIRE
992 g.__MAPptr = new ref_gen_map;
993 #else
994 g.__MAPptr = new ref_gen_map(ptr_fun(islesscomplexthanf));
995 #endif
996 #endif
997 g.type=_MAP;
998 g.subtype=0;
999 return g;
1000 }
1001
gen(const gen_map & s)1002 gen::gen(const gen_map & s){
1003 #ifdef SMARTPTR64
1004 * ((ulonglong * ) this) = ulonglong(new ref_gen_map(s)) << 16;
1005 #else
1006 __MAPptr = new ref_gen_map(s) ;
1007 #endif
1008 type = _MAP;
1009 subtype = 0;
1010 }
1011
gen(const polynome & p)1012 gen::gen(const polynome & p){
1013 subtype=0;
1014 if (p.coord.empty()){
1015 type = _INT_;
1016 val = 0;
1017 }
1018 else {
1019 if (Tis_constant<gen>(p) && is_atomic(p.coord.front().value) ){
1020 type = _INT_;
1021 * this = p.coord.front().value;
1022 }
1023 else {
1024 #ifdef SMARTPTR64
1025 * ((ulonglong * ) this) = ulonglong(new Tref_tensor<gen>(p)) << 16;
1026 #else
1027 __POLYptr = new Tref_tensor<gen>(p) ;
1028 #endif
1029 #ifdef KHICAS
1030 if ((size_t) _POLYptr > stackptr)
1031 ctrl_c=interrupted=true;
1032 #endif
1033 type = _POLY;
1034 }
1035 }
1036 }
1037
gen(const fraction & p)1038 gen::gen(const fraction & p){
1039 subtype=0;
1040 if (is_undef(p.num) || is_undef(p.den)){
1041 type=_INT_;
1042 *this=undef;
1043 return;
1044 }
1045 if (is_inf(p.den)){
1046 type=_INT_;
1047 val=0;
1048 if (is_inf(p.num))
1049 *this=undef;
1050 return;
1051 }
1052 if (is_exactly_zero(p.num)){
1053 type=_INT_;
1054 val=0;
1055 return;
1056 }
1057 if (is_one(p.den)){
1058 type=_INT_;
1059 *this = p.num;
1060 return;
1061 }
1062 if (is_minus_one(p.den)){
1063 type=_INT_;
1064 *this = -p.num;
1065 }
1066 else {
1067 #ifdef SMARTPTR64
1068 * ((ulonglong * ) this) = ulonglong(new Tref_fraction<gen>(p)) << 16;
1069 #else
1070 __FRACptr = new Tref_fraction<gen>(p) ;
1071 #endif
1072 type = _FRAC;
1073 }
1074 }
1075
gen(Tref_tensor<gen> * pptr)1076 gen::gen(Tref_tensor<gen> * pptr){
1077 #ifdef SMARTPTR64
1078 * ((ulonglong * ) this) = ulonglong(pptr) << 16;
1079 #else
1080 __POLYptr = pptr ;
1081 #endif
1082 #ifdef KHICAS
1083 if ((size_t) _POLYptr > stackptr)
1084 ctrl_c=interrupted=true;
1085 #endif
1086 subtype=0;
1087 type = _POLY;
1088 }
1089
1090 // WARNING coerce *mptr to an int if possible, in this case delete mptr
1091 // Pls do not use this constructor unless you know exactly what you do!!
gen(ref_mpz_t * mptr)1092 gen::gen(ref_mpz_t * mptr){
1093 int l=mpz_sizeinbase(mptr->z,2);
1094 // if (l<17){
1095 if (l<32){
1096 type = _INT_;
1097 val = mpz_get_si(mptr->z);
1098 // COUT << "Destruction by mpz_t * " << *mptr << '\n';
1099 delete mptr;
1100 }
1101 else {
1102 if (l>MPZ_MAXLOG2){
1103 type=0;
1104 #if 1
1105 *this=undef;
1106 #else
1107 *this=(mpz_sgn(mptr->z)==-1)?minus_inf:plus_inf;
1108 #endif
1109 delete mptr;
1110 return;
1111 }
1112 #ifdef SMARTPTR64
1113 * ((ulonglong * ) this) = ulonglong(mptr) << 16;
1114 #else
1115 __ZINTptr = mptr;
1116 #endif
1117 #ifdef KHICAS
1118 if ((size_t) _ZINTptr > stackptr)
1119 ctrl_c=interrupted=true;
1120 #endif
1121 type =_ZINT;
1122 }
1123 subtype=0;
1124 // COUT << *this << '\n';
1125 }
1126
1127 // WARNING coerce *mptr to an int if possible, in this case delete mptr
1128 // Pls do not use this constructor unless you know exactly what you do!!
ref_mpz_t2gen(ref_mpz_t * mptr,gen & g)1129 bool ref_mpz_t2gen(ref_mpz_t * mptr,gen & g){
1130 if (g.type>_DOUBLE_){
1131 g=mptr;
1132 return true;
1133 }
1134 int l=mpz_sizeinbase(mptr->z,2);
1135 // if (l<17){
1136 if (l<32){
1137 g.type=_INT_;
1138 g.subtype=0;
1139 g.val = mpz_get_si(mptr->z);
1140 // COUT << "Destruction by mpz_t * " << *mptr << '\n';
1141 return false;
1142 }
1143 else {
1144 if (l>MPZ_MAXLOG2){
1145 g.type=0;
1146 #if 1
1147 g=undef;
1148 #else
1149 g=(mpz_sgn(mptr->z)==-1)?minus_inf:plus_inf;
1150 #endif
1151 return false;
1152 }
1153 #ifdef SMARTPTR64
1154 * ((ulonglong * ) &g) = ulonglong(mptr) << 16;
1155 #else
1156 g.__ZINTptr = mptr;
1157 #endif
1158 g.type =_ZINT;
1159 g.subtype=0;
1160 return true;
1161 }
1162 }
1163
gen(const my_mpz & z)1164 gen::gen(const my_mpz& z){
1165 int l=mpz_sizeinbase(z.ptr,2);
1166 if (l<32){
1167 type = _INT_;
1168 val = mpz_get_si(z.ptr);
1169 }
1170 else {
1171 if (l>MPZ_MAXLOG2){
1172 type=0;
1173 #if 1
1174 *this=undef;
1175 #else
1176 *this=(mpz_sgn(z.ptr)==-1)?minus_inf:plus_inf;
1177 #endif
1178 return;
1179 }
1180 #ifdef SMARTPTR64
1181 * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(z.ptr)) << 16;
1182 #else
1183 __ZINTptr = new ref_mpz_t(z.ptr);
1184 #endif
1185 #ifdef KHICAS
1186 if ((size_t) _ZINTptr > stackptr)
1187 ctrl_c=interrupted=true;
1188 #endif
1189 type =_ZINT;
1190 }
1191 subtype=0;
1192 }
1193
gen(const gen & e)1194 gen::gen(const gen & e) {
1195 if (e.type>_DOUBLE_ && e.type!=_FLOAT_
1196 #ifndef SMARTPTR64
1197 && e.type!=_FUNC
1198 #endif
1199 ) {
1200 if (
1201 #ifdef SMARTPTR64
1202 (*((ulonglong *) &e) >> 16)
1203 #else
1204 e.__ZINTptr
1205 #endif
1206 ){
1207 ref_count_t * rc=(ref_count_t *)&e.ref_count();
1208 if (*rc!=-1)
1209 ++(*rc);
1210 }
1211 }
1212 #ifdef DOUBLEVAL
1213 _DOUBLE_val = e._DOUBLE_val;
1214 #else
1215 * ((longlong *) this) = *((longlong * ) &e);
1216 #endif
1217 #ifndef SMARTPTR64
1218 __ZINTptr=e.__ZINTptr;
1219 #endif
1220 type=e.type;
1221 subtype=e.subtype;
1222 }
1223
new_ref_complex(gen a,gen b)1224 inline ref_complex * new_ref_complex(gen a,gen b){
1225 #if defined(SMARTPTR64) || !defined(ALLOCSMALL)
1226 return new ref_complex(a,b);
1227 #else
1228 ref_complex * ptr= (ref_complex *) allocfast(sizeof(ref_complex));
1229 ptr->ref_count=1;
1230 ptr->display=0;
1231 ptr->re.type=0;
1232 ptr->re=a;
1233 ptr->im.type=0;
1234 ptr->im=b;
1235 return ptr;
1236 #endif
1237 }
1238
gen(int a,int b)1239 gen::gen(int a,int b) {
1240 subtype=0;
1241 if (!b){
1242 type=_INT_;
1243 val=a;
1244 }
1245 else {
1246 #ifdef SMARTPTR64
1247 * ((ulonglong * ) this) = ulonglong(new ref_complex(a,b)) << 16;
1248 #else
1249 __CPLXptr = new_ref_complex(a,b);
1250 #endif
1251 type =_CPLX;
1252 subtype=0;
1253 }
1254 }
1255
1256 #ifndef DOUBLEVAL
gen(double d)1257 gen::gen(double d){
1258 opaque_double_copy(&d,this); type=_DOUBLE_;
1259 };
1260 #endif
1261
gen(double a,double b)1262 gen::gen(double a,double b){
1263 subtype=0;
1264 // COUT << a << " " << b << " " << epsilon << '\n';
1265 if (fabs(b)<1e-12*fabs(a)){
1266 #ifdef DOUBLEVAL
1267 _DOUBLE_val=a;
1268 #else
1269 *((double *) this) = a;
1270 #endif
1271 type=_DOUBLE_;
1272 }
1273 else {
1274 #ifdef SMARTPTR64
1275 * ((ulonglong * ) this) = ulonglong(new ref_complex(a,b)) << 16;
1276 #else
1277 __CPLXptr = new_ref_complex(a,b);
1278 #endif
1279 type =_CPLX;
1280 subtype=3;
1281 }
1282 }
1283
gen(const gen & a,const gen & b)1284 gen::gen(const gen & a,const gen & b) { // a and b must be type <2!
1285 if ( (a.type>=_CPLX && a.type!=_FLOAT_) || (b.type>=_CPLX && b.type!=_FLOAT_) ){
1286 type=0;
1287 *this=a+cst_i*b; // gentypeerr(gettext("complex constructor"));
1288 return;
1289 }
1290 if (is_exactly_zero(b)){
1291 if (a.type==_FLOAT_){
1292 type=0;
1293 *this=a;
1294 }
1295 else {
1296 type=a.type;
1297 switch (type ) {
1298 case _INT_:
1299 val=a.val;
1300 subtype=0;
1301 break;
1302 case _DOUBLE_:
1303 #ifdef DOUBLEVAL
1304 _DOUBLE_val = a._DOUBLE_val;
1305 #else
1306 *((double *) this) = a._DOUBLE_val;
1307 type=_DOUBLE_;
1308 #endif
1309 break;
1310 case _ZINT:
1311 #ifdef SMARTPTR64
1312 * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(*a._ZINTptr)) << 16;
1313 #else
1314 __ZINTptr=new ref_mpz_t(a.__ZINTptr->z); // a is a _ZINT
1315 #endif
1316 type=_ZINT;
1317 subtype=0;
1318 break;
1319 case _REAL:
1320 subtype=0;
1321 #ifdef SMARTPTR64
1322 #ifndef NO_RTTI
1323 if (real_interval * ptr=dynamic_cast<real_interval *>(a._REALptr)){
1324 * ((ulonglong * ) this) = ulonglong(new ref_real_interval(*ptr)) << 16;
1325 subtype=1;
1326 }
1327 else
1328 #endif
1329 * ((ulonglong * ) this) = ulonglong(new ref_real_object(*a._REALptr)) << 16;
1330 #else
1331 #ifndef NO_RTTI
1332 if (real_interval * ptr=dynamic_cast<real_interval *>(a._REALptr)){
1333 __REALptr=(ref_real_object *) new ref_real_interval(*ptr);
1334 subtype=1;
1335 }
1336 else
1337 #endif
1338 __REALptr=new ref_real_object(a.__REALptr->r);
1339 #endif
1340 type=_REAL;
1341 break;
1342 default:
1343 type=0;
1344 *this=gentypeerr(gettext("complex constructor"));
1345 }
1346 }
1347 }
1348 else {
1349 #ifdef SMARTPTR64
1350 * ((ulonglong * ) this) = ulonglong(new ref_complex(a,b)) << 16;
1351 #else
1352 __CPLXptr = new_ref_complex(a,b);
1353 #endif
1354 type =_CPLX;
1355 subtype= (a.type==_DOUBLE_) + (b.type==_DOUBLE_)*2;
1356 }
1357 }
gen(const complex<double> & c)1358 gen::gen(const complex<double> & c) {
1359 #ifdef SMARTPTR64
1360 * ((ulonglong * ) this) = ulonglong(new ref_complex(c)) << 16;
1361 #else
1362 __CPLXptr = new ref_complex(c);
1363 #endif
1364 type=_CPLX;
1365 subtype=3;
1366 }
1367
DOUBLE_val() const1368 double gen::DOUBLE_val() const {
1369 #ifdef DOUBLEVAL
1370 return _DOUBLE_val;
1371 #else
1372 return opaque_double_val(this);
1373 #endif
1374 }
1375
FLOAT_val() const1376 giac_float gen::FLOAT_val() const {
1377 #ifdef DOUBLEVAL
1378 return _FLOAT_val;
1379 #else
1380 longlong r = * (longlong *)(this) ;
1381 // * (unsigned char *) (&r) = 0;
1382 #ifdef BCD
1383 return * (giac_float *)(&r);
1384 #else
1385 return giac_float(* (double *)(&r));
1386 #endif // BCD
1387 #endif // DOUBLEVAL
1388 }
1389
makegen(int i) const1390 gen gen::makegen(int i) const {
1391 switch (type){
1392 case _INT_: case _ZINT: case _CPLX:
1393 return gen(i);
1394 case _VECT:
1395 return vecteur(1,i);
1396 case _USER:
1397 return _USERptr->makegen(i);
1398 default:
1399 return gensizeerr(gettext("makegen of type ")+print(context0));
1400 }
1401 }
1402
gen2complex_d(const gen & e)1403 complex<double> gen2complex_d(const gen & e){
1404 if (e.type==_CPLX){
1405 if (e.subtype==3)
1406 return complex<double>((*e._CPLXptr)._DOUBLE_val,(*(e._CPLXptr+1))._DOUBLE_val);
1407 gen ee=e.evalf_double(1,context0); // ok
1408 if (ee.type==_DOUBLE_) return complex<double>(ee._DOUBLE_val,0);
1409 if (ee.type!=_CPLX){
1410 #ifndef NO_STDEXCEPT
1411 setsizeerr(gettext("complex<double>"));
1412 #endif
1413 return complex<double>(nan(),nan());
1414 }
1415 return complex<double>((*ee._CPLXptr)._DOUBLE_val,(*(ee._CPLXptr+1))._DOUBLE_val);
1416 }
1417 if (e.type==_DOUBLE_)
1418 return complex<double>(e._DOUBLE_val,0);
1419 if (e.type==_INT_)
1420 return complex<double>(e.val,0);
1421 if (e.type==_ZINT)
1422 return complex<double>(e.evalf(1,context0)._DOUBLE_val,0); // ok
1423 #ifndef NO_STDEXCEPT
1424 setsizeerr(gettext("complex<double>"));
1425 #endif
1426 return complex<double>(nan(),nan());
1427 }
1428
gen(const sparse_poly1 & p)1429 gen::gen(const sparse_poly1 & p){
1430 if (p.empty()){
1431 type=0;
1432 subtype=0;
1433 val=0;
1434 }
1435 else {
1436 if (is_undef(p.front().exponent)){
1437 type=0;
1438 *this=undef;
1439 }
1440 else {
1441 #ifdef SMARTPTR64
1442 * ((ulonglong * ) this) = ulonglong(new ref_sparse_poly1(p)) << 16;
1443 #else
1444 __SPOL1ptr= new ref_sparse_poly1(p);
1445 #endif
1446 #ifdef KHICAS
1447 if ((size_t) _SPOL1ptr > stackptr)
1448 ctrl_c=interrupted=true;
1449 #endif
1450 subtype=0;
1451 type=_SPOL1;
1452 }
1453 }
1454 }
1455
gen(const unary_function_ptr * f,int nargs)1456 gen::gen(const unary_function_ptr * f,int nargs){
1457 #if defined SMARTPTR64
1458 * ((ulonglong * ) this) = ulonglong(new ref_unary_function_ptr(*f)) << 16;
1459 #else
1460 _FUNC_ = (size_t) (* (size_t*) f);
1461 // __FUNCptr= new ref_unary_function_ptr(f);
1462 #endif
1463 type=_FUNC;
1464 subtype=nargs;
1465 }
1466
gen(const unary_function_ptr & f,int nargs)1467 gen::gen(const unary_function_ptr & f,int nargs){
1468 #ifdef SMARTPTR64
1469 * ((ulonglong * ) this) = ulonglong(new ref_unary_function_ptr(f)) << 16;
1470 #else
1471 _FUNC_ = (size_t)(* (size_t *) &f);
1472 // __FUNCptr= new ref_unary_function_ptr(f);
1473 #endif
1474 type=_FUNC;
1475 subtype=nargs;
1476 }
1477
gen(const giac_float & f)1478 gen::gen(const giac_float & f){
1479 #ifdef DOUBLEVAL
1480 _FLOAT_val=f;
1481 #else
1482 #ifdef BCD
1483 *((giac_float *) this) = f;
1484 #else // BCD
1485 *((double *) this) = f;
1486 #endif // BCD
1487 #endif // DOUBLEVAL
1488 type=_FLOAT_;
1489 }
1490
1491 #ifdef BCD
gen(accurate_bcd_float * b)1492 gen::gen(accurate_bcd_float * b){
1493 giac_float f=fUnExpand(b);
1494 #ifdef DOUBLEVAL
1495 _FLOAT_val=f;
1496 #else
1497 *((giac_float *) this) = f;
1498 #endif // DOUBLEVAL
1499 type=_FLOAT_;
1500 }
1501 #endif // BCD
1502
delete_gen()1503 void gen::delete_gen() {
1504 switch (type) {
1505 #ifdef SMARTPTR64
1506 case _ZINT:
1507 delete (ref_mpz_t *) (* ((ulonglong * ) this) >> 16);
1508 break;
1509 case _REAL: {
1510 ref_real_object * ptr=(ref_real_object *) (* ((ulonglong * ) this) >> 16);
1511 #ifndef NO_RTTI
1512 if (dynamic_cast<real_interval *>(&ptr->r))
1513 delete (ref_real_interval *) ptr;
1514 else
1515 #endif
1516 delete ptr;
1517 break;
1518 }
1519 case _CPLX:
1520 delete (ref_complex *) (* ((ulonglong * ) this) >> 16);
1521 break;
1522 case _IDNT:
1523 delete (ref_identificateur *) (* ((ulonglong * ) this) >> 16);
1524 break;
1525 case _VECT:
1526 delete (ref_vecteur *) (* ((ulonglong * ) this) >> 16);
1527 break;
1528 case _SYMB:
1529 delete (ref_symbolic *) (* ((ulonglong * ) this) >> 16);
1530 break;
1531 case _USER:
1532 delete (ref_gen_user *) (* ((ulonglong * ) this) >> 16);
1533 break;
1534 case _EXT:
1535 delete (ref_algext *) (* ((ulonglong * ) this) >> 16);
1536 break;
1537 case _MOD:
1538 delete (ref_modulo *) (* ((ulonglong * ) this) >> 16);
1539 break;
1540 case _POLY:
1541 delete (ref_polynome *) (* ((ulonglong * ) this) >> 16);
1542 break;
1543 case _FRAC:
1544 delete (ref_fraction *) (* ((ulonglong * ) this) >> 16);
1545 break;
1546 case _SPOL1:
1547 delete (ref_sparse_poly1 *) (* ((ulonglong * ) this) >> 16);
1548 break;
1549 case _STRNG:
1550 delete (ref_string *) (* ((ulonglong * ) this) >> 16);
1551 break;
1552 case _FUNC:
1553 delete (ref_unary_function_ptr *) (* ((ulonglong * ) this) >> 16);
1554 break;
1555 case _MAP:
1556 delete (ref_gen_map *) (* ((ulonglong * ) this) >> 16);
1557 break;
1558 case _EQW:
1559 delete (ref_eqwdata *) (* ((ulonglong * ) this) >> 16);
1560 break;
1561 case _GROB:
1562 delete (ref_grob *) (* ((ulonglong * ) this) >> 16);
1563 break;
1564 case _POINTER_:
1565 if (subtype==_FL_WIDGET_POINTER && fl_widget_delete_function)
1566 fl_widget_delete_function(_POINTER_val);
1567 delete (ref_void_pointer *) (* ((ulonglong * ) this) >> 16);
1568 break;
1569 #else // SMARTPTR64
1570 case _ZINT:
1571 delete __ZINTptr;
1572 break;
1573 case _REAL: {
1574 ref_real_object * ptr=__REALptr;
1575 #ifndef NO_RTTI
1576 if (dynamic_cast<real_interval *>(&ptr->r))
1577 delete (ref_real_interval *) __REALptr;
1578 else
1579 #endif
1580 delete __REALptr;
1581 break;
1582 }
1583 case _CPLX:
1584 deletecomplex(__CPLXptr); // delete __CPLXptr;
1585 break;
1586 case _IDNT:
1587 delete __IDNTptr;
1588 break;
1589 case _VECT:
1590 delete_ref_vecteur(__VECTptr); // delete __VECTptr;
1591 break;
1592 case _SYMB:
1593 deletesymbolic(__SYMBptr); // delete __SYMBptr;
1594 break;
1595 case _USER:
1596 delete __USERptr;
1597 break;
1598 case _EXT:
1599 delete __EXTptr;
1600 break;
1601 case _MOD:
1602 delete __MODptr;
1603 break;
1604 case _POLY:
1605 delete __POLYptr;
1606 break;
1607 case _FRAC:
1608 delete __FRACptr;
1609 break;
1610 case _SPOL1:
1611 delete __SPOL1ptr;
1612 break;
1613 case _STRNG:
1614 delete __STRNGptr;
1615 break;
1616 #ifdef SMARTPTR64
1617 case _FUNC:
1618 delete __FUNCptr;
1619 break;
1620 #endif
1621 case _MAP:
1622 delete __MAPptr;
1623 break;
1624 case _EQW:
1625 delete __EQWptr;
1626 break;
1627 case _GROB:
1628 delete __GROBptr;
1629 break;
1630 case _POINTER_:
1631 if (subtype==_FL_WIDGET_POINTER && fl_widget_delete_function)
1632 fl_widget_delete_function(_POINTER_val);
1633 delete __POINTERptr;
1634 break;
1635 #endif // SMARTPTR64
1636 default:
1637 #ifndef NO_STDEXCEPT
1638 settypeerr(gettext("Gen Destructor"));
1639 #endif
1640 ;
1641 }
1642 }
1643
delete_ptr(signed char subtype,short int type_save,ref_mpz_t * ptr_save)1644 void delete_ptr(signed char subtype,short int type_save,ref_mpz_t * ptr_save) {
1645 #if 0 // def COMPILE_FOR_STABILITY // commented (D.Alm) The call to delete_ptr() would sometimes get cancelled if ctrl_c was being set, which could cause the "Stopped by user interruption." exception somehow to be fired twice, with the second time not being caught properly by my exception handling code.
1646 control_c();
1647 #endif
1648 if (ptr_save && type_save!=_FLOAT_&& ptr_save->ref_count!=-1 && !--(ptr_save->ref_count)){
1649 switch (type_save) {
1650 case _ZINT:
1651 delete ptr_save;
1652 break;
1653 case _REAL: {
1654 ref_real_object * ptr=(ref_real_object *) ptr_save;
1655 #ifndef NO_RTTI
1656 if (dynamic_cast<real_interval *>(&ptr->r))
1657 delete (ref_real_interval *) ptr;
1658 else
1659 #endif
1660 delete ptr;
1661 break;
1662 }
1663 case _CPLX:
1664 deletecomplex((ref_complex *) ptr_save);
1665 break;
1666 case _IDNT:
1667 delete (ref_identificateur *) ptr_save ;
1668 break;
1669 case _SYMB:
1670 deletesymbolic( (ref_symbolic *) ptr_save);
1671 break;
1672 case _USER:
1673 delete (ref_gen_user *) ptr_save;
1674 break;
1675 case _EXT:
1676 delete (ref_algext * ) ptr_save;
1677 break;
1678 case _MOD:
1679 delete (ref_modulo * ) ptr_save;
1680 break;
1681 case _VECT:
1682 delete_ref_vecteur((ref_vecteur *) ptr_save); // delete (ref_vecteur *) ptr_save;
1683 break;
1684 case _POLY:
1685 delete (ref_polynome *) ptr_save;
1686 break;
1687 case _FRAC:
1688 delete (ref_fraction *) ptr_save;
1689 break;
1690 case _SPOL1:
1691 delete (ref_sparse_poly1 *) ptr_save;
1692 break;
1693 case _STRNG:
1694 delete (ref_string *) ptr_save;
1695 break;
1696 #ifdef SMARTPTR64
1697 case _FUNC:
1698 delete (ref_unary_function_ptr *) ptr_save;
1699 break;
1700 #endif
1701 case _MAP:
1702 delete (ref_gen_map *) ptr_save;
1703 break;
1704 case _EQW:
1705 delete (ref_eqwdata *) ptr_save;
1706 break;
1707 case _GROB:
1708 delete (ref_grob *) ptr_save;
1709 break;
1710 case _POINTER_:
1711 if (subtype==_FL_WIDGET_POINTER && fl_widget_delete_function)
1712 fl_widget_delete_function( ((ref_void_pointer *)ptr_save)->p);
1713 delete (ref_void_pointer *) ptr_save;
1714 break;
1715 case _FLOAT_:
1716 break;
1717 default:
1718 #ifndef NO_STDEXCEPT
1719 settypeerr(gettext("Gen Operator ="));
1720 #endif
1721 ;
1722 }
1723 }
1724 }
1725
1726
to_double(GIAC_CONTEXT) const1727 double gen::to_double(GIAC_CONTEXT) const {
1728 if (type==_DOUBLE_)
1729 return _DOUBLE_val;
1730 if (type==_INT_)
1731 return double(val);
1732 gen tmp=evalf_double(1,contextptr);
1733 if (tmp.type==_DOUBLE_)
1734 return tmp._DOUBLE_val;
1735 #ifdef NAN
1736 return NAN;
1737 #else
1738 double d=1.0;
1739 d=d-d/double(1ULL<<53);
1740 return d*2.0/d;
1741 #endif
1742 }
1743
is_vector_of_size(size_t n) const1744 bool gen::is_vector_of_size(size_t n) const {
1745 return type==_VECT && _VECTptr->size()==n;
1746 }
1747
is_identificateur_with_name(const char * s) const1748 bool gen::is_identificateur_with_name(const char * s) const {
1749 return type==_IDNT && strcmp(_IDNTptr->id_name,s)==0;
1750 }
1751
1752
to_int() const1753 int gen::to_int() const {
1754 switch (type ) {
1755 case _INT_:
1756 return val;
1757 case _ZINT:
1758 return mpz_get_si(*_ZINTptr);
1759 case _CPLX:
1760 return _CPLXptr->to_int() ;
1761 default:
1762 #ifndef NO_STDEXCEPT
1763 settypeerr(gettext("To_int"));
1764 #endif
1765 return 0;
1766 }
1767 return 0;
1768 }
1769
uncoerce(size_t s)1770 void gen::uncoerce(size_t s) {
1771 if (type==_INT_){
1772 int tmp =val;
1773 #ifdef SMARTPTR64
1774 * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(s)) << 16;
1775 #else
1776 __ZINTptr = new ref_mpz_t(s);
1777 #endif
1778 type=_ZINT;
1779 mpz_set_si(*_ZINTptr,tmp);
1780 }
1781 }
1782
_FRAC2_SYMB(const fraction & f)1783 gen _FRAC2_SYMB(const fraction & f){
1784 if (is_one(f.num))
1785 return symb_inv(f.den);
1786 if (is_minus_one(f.num))
1787 return -symb_inv(f.den);
1788 return symbolic(at_prod,makesequence(f.num,symb_inv(f.den)));
1789 }
1790
_FRAC2_SYMB(const gen & e)1791 gen _FRAC2_SYMB(const gen & e){
1792 #ifdef DEBUG_SUPPORT
1793 if (e.type!=_FRAC) setsizeerr(gettext("gen.cc/_FRAC2_SYMB"));
1794 #endif
1795 return _FRAC2_SYMB(*e._FRACptr);
1796 }
1797
_FRAC2_SYMB(const gen & n,const gen & d)1798 gen _FRAC2_SYMB(const gen & n,const gen & d){
1799 return symbolic(at_prod,makesequence(n,symb_inv(d)));
1800 }
1801
1802
1803 /* Eval, evalf */
evalf_VECT(const vecteur & v,int subtype,int level,const context * contextptr)1804 gen evalf_VECT(const vecteur & v,int subtype,int level,const context * contextptr){
1805 // bool save_is_inevalf=is_inevalf;
1806 // is_inevalf=true;
1807 vecteur w;
1808 vecteur::const_iterator it=v.begin(), itend=v.end();
1809 w.reserve(itend-it);
1810 for (;it!=itend;++it){
1811 gen tmp=it->evalf(level,contextptr);
1812 if (subtype){
1813 if ((subtype==_SEQ__VECT)&&(tmp.type==_VECT) && (tmp.subtype==_SEQ__VECT)){
1814 const_iterateur jt=tmp._VECTptr->begin(),jtend=tmp._VECTptr->end();
1815 for (;jt!=jtend;++jt)
1816 w.push_back(*jt);
1817 }
1818 else {
1819 if ((subtype!=_SET__VECT) || (!equalposcomp(w,tmp)))
1820 w.push_back(tmp);
1821 }
1822 }
1823 else
1824 w.push_back(tmp);
1825 }
1826 // is_inevalf=save_is_inevalf;
1827 return gen(w,subtype);
1828 }
1829
1830
eval_VECT(const gen & g,gen & evaled,int subtype,int level,const context * contextptr)1831 bool eval_VECT(const gen & g,gen & evaled,int subtype,int level,const context * contextptr){
1832 // const vecteur & v = *g._VECTptr;
1833 gen tmp;
1834 const gen * ansptr;
1835 ref_vecteur * vptr;
1836 const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end(),jt,jtend;
1837 if (subtype!=_SET__VECT && subtype!=_SEQ__VECT){
1838 for (;it!=itend;++it){
1839 if (it->in_eval(level,evaled,contextptr))
1840 break;
1841 }
1842 if (it==itend)
1843 return false;
1844 }
1845 vptr = new_ref_vecteur(0);
1846 vptr->v.reserve(itend-g._VECTptr->begin());
1847 if (subtype!=_SET__VECT && subtype!=_SEQ__VECT){
1848 for (jt=g._VECTptr->begin();jt!=it;++jt)
1849 vptr->v.push_back(*jt);
1850 if (evaled.type==_VECT && evaled.subtype==_SEQ__VECT){
1851 jt=evaled._VECTptr->begin(); jtend=evaled._VECTptr->end();
1852 for (;jt!=jtend;++jt){
1853 if ((subtype!=_SET__VECT) || (!equalposcomp(vptr->v,*jt)))
1854 vptr->v.push_back(*jt);
1855 }
1856 }
1857 else {
1858 if ( subtype!=_SET__VECT || (!equalposcomp(vptr->v,evaled)))
1859 vptr->v.push_back(evaled);
1860 }
1861 ++it;
1862 }
1863 evaled=gen(vptr,subtype);
1864 for (;it!=itend;++it){
1865 if (it->is_symb_of_sommet(at_comment))
1866 continue;
1867 ansptr=(it->in_eval(level,tmp,contextptr))?&tmp:&*it;
1868 if (ansptr->type==_VECT && ansptr->subtype==_SEQ__VECT){
1869 jt=ansptr->_VECTptr->begin(); jtend=ansptr->_VECTptr->end();
1870 for (;jt!=jtend;++jt){
1871 if ((subtype!=_SET__VECT) || (!equalposcomp(vptr->v,*jt)))
1872 vptr->v.push_back(*jt);
1873 }
1874 }
1875 else {
1876 if ( subtype!=_SET__VECT || (!equalposcomp(vptr->v,*ansptr)))
1877 vptr->v.push_back(*ansptr);
1878 }
1879 }
1880 // CERR << "End " << v << " " << w << '\n';
1881 return true;
1882 }
1883
1884 // evalf a real fraction
evalf_FRAC(const fraction & f,GIAC_CONTEXT)1885 gen evalf_FRAC(const fraction & f,GIAC_CONTEXT){
1886 gen n(f.num),d(f.den);
1887 if (n.type==_INT_ && d.type==_INT_)
1888 return evalf(n,1,contextptr)/evalf(d,1,contextptr);
1889 if (is_zero(n))
1890 return evalf(n,0,contextptr);
1891 bool npos=is_positive(n,contextptr),dpos=is_positive(d,contextptr);
1892 bool neg=npos?!dpos:dpos;
1893 if (!npos)
1894 n=-n;
1895 if (!dpos)
1896 d=-d;
1897 bool inf1=is_greater(d,n,contextptr);
1898 #ifdef FXCG
1899 gen m=gen(longlong(1)<<61);
1900 gen md=gen(1.0)/m;
1901 #else
1902 #ifdef BCD
1903 static gen m=gen(longlong(100000000000000));
1904 #else
1905 static gen m=gen(longlong(1)<<61);
1906 #endif
1907 static gen md=gen(1.0)/m;
1908 #endif
1909 if (absint(sizeinbase2(n)-sizeinbase2(d))>=53){
1910 gen a=inf1?iquo(d,n):iquo(n,d);
1911 gen res=evalf(a,1,contextptr);
1912 if (neg) res=-res;
1913 return inf1?inv(res,contextptr):res;
1914 }
1915 gen a=inf1?iquo(d*m,n):iquo(n*m,d);
1916 gen res=evalf(a,1,contextptr);
1917 if (neg) res=-res;
1918 res = md*res;
1919 return inf1?inv(res,contextptr):res;
1920 }
1921
1922 // evaluate _FUNCndary in RPN mode, f must be of type _FUNC
rpneval_FUNC(const gen & f,GIAC_CONTEXT)1923 static gen rpneval_FUNC(const gen & f,GIAC_CONTEXT){
1924 // int s=history_out(contextptr).size();
1925 int nargs=giacmax(f.subtype,0);
1926 if (!nargs){
1927 gen res=(*f._FUNCptr)(gen(history_out(contextptr),_RPN_STACK__VECT),contextptr);
1928 if ( (res.type!=_VECT) || (res.subtype!=_RPN_STACK__VECT))
1929 res=gen(makenewvecteur(res),_RPN_STACK__VECT);
1930 history_out(contextptr)=*res._VECTptr;
1931 history_in(contextptr)=history_out(contextptr);
1932 return res;
1933 }
1934 vecteur v(nargs);
1935 for (int i=nargs-1;i>=0;--i){
1936 v[i]=history_out(contextptr).back();
1937 history_out(contextptr).pop_back();
1938 history_in(contextptr).pop_back();
1939 }
1940 if (nargs==1)
1941 return (*f._FUNCptr)(v.front(),contextptr);
1942 else
1943 return (*f._FUNCptr)(v,contextptr);
1944 }
1945
evalcomment(const vecteur & v,gen & evaled,int level,const context * contextptr)1946 static bool evalcomment(const vecteur & v,gen &evaled,int level,const context * contextptr){
1947 const_iterateur it=v.begin(),itend=v.end();
1948 for (;it!=itend;++it){
1949 if ( (it->type!=_SYMB) || (it->_SYMBptr->sommet!=at_comment) )
1950 break;
1951 }
1952 if (it+1==itend){
1953 evaled=it->eval(level,contextptr);
1954 return true;
1955 }
1956 if (it!=itend){
1957 gen partial=vecteur(it,itend);
1958 if (eval_VECT(partial,evaled,_SEQ__VECT,level,contextptr))
1959 return true;
1960 else {
1961 evaled=partial;
1962 return true;
1963 }
1964 }
1965 evaled=zero;
1966 return true;
1967 }
1968
check_not_assume(const gen & not_evaled,gen & evaled,bool evalf_after,const context * contextptr)1969 bool check_not_assume(const gen & not_evaled,gen & evaled, bool evalf_after,const context * contextptr){
1970 if ( evaled.type==_VECT && evaled.subtype==_ASSUME__VECT ){
1971 if ( evalf_after && evaled._VECTptr->size()==2 && (evaled._VECTptr->back().type<=_CPLX || evaled._VECTptr->back().type==_FRAC || evaled._VECTptr->back().type==_FLOAT_) ){
1972 evaled=evaled._VECTptr->back().evalf(1,contextptr);
1973 return true;
1974 }
1975 if (not_evaled.type==_IDNT && evaled._VECTptr->size()==1 && evaled._VECTptr->front().type==_INT_){
1976 gen tmp=not_evaled;
1977 tmp.subtype=evaled._VECTptr->front().val;
1978 evaled=tmp;
1979 return true;
1980 }
1981 return false;
1982 }
1983 else {
1984 if (evalf_after && evaled.type!=_IDNT){
1985 gen res;
1986 if (has_evalf(evaled,res,0,contextptr)){
1987 evaled=res;
1988 return true;
1989 }
1990 }
1991 return &evaled!=¬_evaled;
1992 }
1993 return false;
1994 }
1995
1996 #if 0
1997 gen gen::eval(int level,const context * contextptr) const{
1998 // CERR << "eval " << *this << " " << level << '\n';
1999 gen res;
2000 // return in_eval(level,res,contextptr)?res:*this;
2001 if (in_eval(level,res,contextptr))
2002 return res;
2003 else
2004 return *this;
2005 }
2006 #endif
2007
in_eval_mod(const gen & g,gen & evaled,int level,GIAC_CONTEXT)2008 static bool in_eval_mod(const gen & g,gen & evaled,int level,GIAC_CONTEXT){
2009 evaled=makemod(g._MODptr->eval(level,contextptr),(g._MODptr+1)->eval(level,contextptr));
2010 return true;
2011 }
2012
in_eval_user(const gen & g,gen & evaled,int level,GIAC_CONTEXT)2013 static bool in_eval_user(const gen & g,gen & evaled,int level,GIAC_CONTEXT){
2014 evaled=g._USERptr->eval(level,contextptr);
2015 return true;
2016 }
2017
in_eval_func(const gen & g,gen * evaledptr,GIAC_CONTEXT)2018 static bool in_eval_func(const gen & g,gen * evaledptr,GIAC_CONTEXT){
2019 if (rpn_mode(contextptr) && (history_out(contextptr).size()>=unsigned(g.subtype)))
2020 *evaledptr=rpneval_FUNC(g,contextptr);
2021 else {
2022 if (g.subtype)
2023 return false;
2024 else
2025 *evaledptr=(*g._FUNCptr)(gen(vecteur(0),_SEQ__VECT),contextptr);
2026 }
2027 return true;
2028 }
2029
in_eval_idnt(const gen & g,gen & evaled,int level,GIAC_CONTEXT)2030 static bool in_eval_idnt(const gen & g,gen & evaled,int level,GIAC_CONTEXT){
2031 identificateur * gptr=g._IDNTptr;
2032 if (strcmp(gptr->id_name,string_pi)==0 || strcmp(gptr->id_name,string_euler_gamma)==0 )
2033 return false;
2034 if (!contextptr && g.subtype==_GLOBAL__EVAL)
2035 evaled=global_eval(*gptr,level);
2036 else {
2037 if (!gptr->in_eval(level-1,g,evaled,contextptr))
2038 return false;
2039 }
2040 if ( evaled.type!=_VECT || evaled.subtype!=_ASSUME__VECT ){
2041 if (evaled.is_symb_of_sommet(at_program))
2042 lastprog_name(gptr->id_name,contextptr);
2043 return true;
2044 }
2045 return check_not_assume(g,evaled,false,contextptr);
2046 }
2047
in_eval_vect(const gen & g,gen & evaled,int level,GIAC_CONTEXT)2048 static bool in_eval_vect(const gen & g,gen & evaled,int level,GIAC_CONTEXT){
2049 #ifdef HAVE_LIBMPFI
2050 if (g.subtype==_INTERVAL__VECT && g._VECTptr->size()==2){
2051 // convert to MPFI real_interval
2052 gen l=eval(g._VECTptr->front(),level,contextptr),u=eval(g._VECTptr->back(),level,contextptr);
2053 if (is_strictly_greater(l,u,contextptr)){
2054 swapgen(l,u);
2055 }
2056 bool lexact=is_integer(l),uexact=is_integer(u);
2057 gen ul=u-l;
2058 if (is_exactly_zero(ul)){
2059 if (u.type==_REAL)
2060 ul=int(mpfr_get_prec(u._REALptr->inf));
2061 else
2062 ul=int(3.2*decimal_digits(contextptr));
2063 }
2064 else {
2065 ul=u-l;
2066 ul=2*ul/(abs(u,contextptr)+abs(l,contextptr));
2067 ul=ln(abs(evalf(ul,1,contextptr),contextptr),contextptr);
2068 ul=-_ceil(ul/ln(evalf(2,1,contextptr),contextptr),contextptr);
2069 }
2070 int nbits=53;
2071 if (ul.type==_INT_ && ul.val>48){
2072 nbits=ul.val+4;
2073 l=accurate_evalf(l,nbits);
2074 u=accurate_evalf(u,nbits);
2075 }
2076 else {
2077 l=evalf(l,level,contextptr); u=evalf(u,level,contextptr);
2078 }
2079 if (l.type==_DOUBLE_ && u.type==_REAL)
2080 u=evalf_double(u,1,contextptr);
2081 if (u.type==_DOUBLE_ && l.type==_REAL)
2082 l=evalf_double(l,1,contextptr);
2083 if (l.type==_DOUBLE_){
2084 // adjust mantissa of l down and mantissa of u up
2085 double epsilon=7e-15; // 2^(-47)
2086 if (!lexact)
2087 l=(1.+(l._DOUBLE_val>0?(-epsilon):(epsilon)))*l;
2088 if (!uexact)
2089 u=(1.+(u._DOUBLE_val>0?(epsilon):(-epsilon)))*u;
2090 }
2091 else { // do the same for MPFR
2092 gen epsilon=pow(plus_two,nbits-2,contextptr); // nbits-3?
2093 epsilon=fraction(1,epsilon);
2094 if (!lexact){
2095 if (is_positive(l,contextptr))
2096 l=(1-epsilon)*l;
2097 else
2098 l=(1+epsilon)*l;
2099 }
2100 if (!uexact){
2101 if (is_positive(u,contextptr))
2102 u=(1+epsilon)*u;
2103 else
2104 u=(1-epsilon)*u;
2105 }
2106 }
2107 if ( (l.type==_DOUBLE_ && u.type==_DOUBLE_) ||
2108 (l.type==_REAL && u.type==_REAL) ){
2109 mpfi_t interv;
2110 mpfi_init(interv);
2111 mpfi_set_prec(interv,nbits);
2112 if (l.type==_DOUBLE_)
2113 mpfi_interv_d(interv,l._DOUBLE_val,u._DOUBLE_val);
2114 else
2115 mpfi_interv_fr(interv,l._REALptr->inf,u._REALptr->inf);
2116 evaled=gen(real_interval(interv));
2117 mpfi_clear(interv);
2118 return true;
2119 }
2120 }
2121 #endif
2122 if (g.subtype==_SPREAD__VECT){
2123 makespreadsheetmatrice(*g._VECTptr,contextptr);
2124 spread_eval(*g._VECTptr,contextptr);
2125 return false;
2126 }
2127 if (g.subtype==_TABLE__VECT){
2128 eval_VECT(g,evaled,g.subtype,level,contextptr);
2129 evaled=_table(evaled,contextptr);
2130 return true;
2131 }
2132 if (g.subtype==_FOLDER__VECT || g.subtype==_RGBA__VECT)
2133 return false;
2134 if ( (g.subtype==_SEQ__VECT) && (!g._VECTptr->empty()) && (g._VECTptr->front().type==_SYMB)
2135 && (g._VECTptr->front().is_symb_of_sommet(at_comment))
2136 && (g._VECTptr->back().type==_SYMB)
2137 && (g._VECTptr->back().is_symb_of_sommet(at_return))
2138 ){
2139 return evalcomment(*g._VECTptr,evaled,level,contextptr);
2140 }
2141 if (g._VECTptr->size()==1 && g._VECTptr->front().is_symb_of_sommet(at_interval))
2142 return in_eval_vect(gen(makevecteur(g._VECTptr->front()[1],g._VECTptr->front()[2]),_INTERVAL__VECT),evaled,1,contextptr);
2143 return eval_VECT(g,evaled,g.subtype,level,contextptr);
2144 }
2145
in_eval(int level,gen & evaled,const context * contextptr) const2146 bool gen::in_eval(int level,gen & evaled,const context * contextptr) const{
2147 #ifdef TIMEOUT
2148 control_c();
2149 #endif
2150 if (ctrl_c || interrupted) {
2151 interrupted = true; ctrl_c=false;
2152 *logptr(contextptr) << "Stopped in in_eval" << '\n';
2153 gensizeerr(gettext("Stopped by user interruption."),evaled);
2154 return true;
2155 }
2156 if (!level)
2157 return false;
2158 switch (type) {
2159 case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL: case _CPLX: case _POLY: case _FRAC: case _SPOL1: case _EXT: case _STRNG: case _MAP: case _EQW: case _GROB: case _POINTER_:
2160 return false;
2161 case _IDNT:
2162 return in_eval_idnt(*this,evaled,level,contextptr);
2163 case _VECT:
2164 return in_eval_vect(*this,evaled,level,contextptr);
2165 case _SYMB:
2166 if (subtype==_SPREAD__SYMB)
2167 return false;
2168 {
2169 symbolic * sptr=_SYMBptr;
2170 unary_function_ptr & Sommet=sptr->sommet;
2171 const gen & feuille=sptr->feuille;
2172 bool is_ifte=false,is_of_local_ifte_bloc=false,is_plus=Sommet==at_plus,is_prod=false,is_pow=false;
2173 if (is_plus || (is_prod=(Sommet==at_prod)) || (is_pow=(Sommet==at_pow)) || (is_of_local_ifte_bloc=(Sommet==at_of || Sommet==at_local || (is_ifte=Sommet==at_ifte) || Sommet==at_bloc)) ){
2174 int & elevel=eval_level(contextptr);
2175 short int slevel=elevel;
2176 // Check if we are not far from stack end
2177 #ifdef RTOS_THREADX
2178 if ((void *)&slevel<= (void *)&mainThreadStack[2048]){
2179 if ((void *)&slevel<= (void *)&mainThreadStack[1024]){
2180 gensizeerr(gettext("Too many recursion levels"),evaled); // two many recursion levels
2181 return true;
2182 }
2183 evaled=nr_eval(*this,level,contextptr);
2184 return true;
2185 }
2186 #else // rtos
2187 #if !defined(WIN32) && defined(HAVE_PTHREAD_H)
2188 void * stackaddr;
2189 if (contextptr && (stackaddr=thread_param_ptr(contextptr)->stackaddr)){
2190 // CERR << &slevel << " " << thread_param_ptr(contextptr)->stackaddr << '\n';
2191 if ( ((size_t) &slevel) < ((size_t) stackaddr)+65536){
2192 if ( ((size_t) &slevel) < ((size_t) stackaddr)+8192){
2193 gensizeerr(gettext("Too many recursion levels"),evaled); // two many recursion levels
2194 return true;
2195 }
2196 *logptr(contextptr) << gettext("Running non recursive evaluator") << '\n';
2197 evaled=nr_eval(*this,level,contextptr);
2198 return true;
2199 }
2200 } else
2201 #endif // pthread
2202 {
2203 debug_struct * dbgptr=debug_ptr(contextptr);
2204 if ( int(dbgptr->sst_at_stack.size()) >= MAX_RECURSION_LEVEL){
2205 if ( int(dbgptr->sst_at_stack.size()) >= MAX_RECURSION_LEVEL+10){
2206 gensizeerr(gettext("Too many recursions)"),evaled);
2207 return true;
2208 }
2209 #ifdef KHICAS
2210 if (warn_nr){
2211 *logptr(contextptr) << gettext("Running non recursive evaluator") << '\n';
2212 warn_nr=false;
2213 }
2214 #else
2215 *logptr(contextptr) << gettext("Running non recursive evaluator") << '\n';
2216 #endif
2217 evaled=nr_eval(*this,level,contextptr);
2218 return true;
2219 }
2220 }
2221 #endif // rtos
2222 const vecteur * vptr;
2223 if ( (is_plus ||is_prod || is_pow) && feuille.type==_VECT && (vptr=feuille._VECTptr)->size()==2){
2224 const gen & vptrfront=vptr->front();
2225 const gen & vptrback=vptr->back();
2226 gen a;
2227 if (!vptrfront.in_eval(level,a,contextptr))
2228 a=vptrfront;
2229 if (a.type!=_VECT || a.subtype!=_SEQ__VECT){
2230 if (!vptrback.in_eval(level,evaled,contextptr))
2231 evaled=vptrback;
2232 if (evaled.type!=_VECT || evaled.subtype!=_SEQ__VECT){
2233 if (is_plus) evaled=operator_plus(a,evaled,contextptr);
2234 else {
2235 if (is_prod) evaled=operator_times(a,evaled,contextptr);
2236 else evaled=pow(a,evaled,contextptr);
2237 }
2238 elevel=slevel;
2239 return true;
2240 }
2241 }
2242 }
2243 if (is_of_local_ifte_bloc){
2244 elevel=level;
2245 evaled=feuille; // FIXME must also set eval_level to level
2246 }
2247 else {
2248 if (!feuille.in_eval(level,evaled,contextptr))
2249 evaled=feuille;
2250 }
2251 if (is_ifte)
2252 evaled=ifte(evaled,true,contextptr);
2253 else
2254 evaled=(*Sommet.ptr())(evaled,contextptr);
2255 elevel=slevel;
2256 }
2257 else
2258 evaled=sptr->eval(level,contextptr);
2259 return true;
2260 }
2261 case _USER:
2262 return in_eval_user(*this,evaled,level,contextptr);
2263 case _MOD:
2264 return in_eval_mod(*this,evaled,level,contextptr);
2265 case _FUNC:
2266 return in_eval_func(*this,&evaled,contextptr);
2267 default:
2268 gentypeerr("Eval",evaled) ;
2269 return false;
2270 }
2271 return false;
2272 }
2273
apply(const polynome & p,const gen_op & f)2274 polynome apply( const polynome & p, const gen_op & f){
2275 polynome res(p.dim);
2276 std::vector< monomial<gen> > :: const_iterator it=p.coord.begin(),itend=p.coord.end();
2277 res.coord.reserve(itend-it);
2278 for (;it!=itend;++it){
2279 gen tmp(f(it->value));
2280 if (!is_zero(tmp,context0))
2281 res.coord.push_back(monomial<gen>(tmp,it->index));
2282 }
2283 return res;
2284 }
2285
apply(const polynome & p,const context * contextptr,gen (* f)(const gen &,const context *))2286 polynome apply( const polynome & p, const context * contextptr, gen (* f) (const gen &, const context *)){
2287 polynome res(p.dim);
2288 std::vector< monomial<gen> > :: const_iterator it=p.coord.begin(),itend=p.coord.end();
2289 res.coord.reserve(itend-it);
2290 for (;it!=itend;++it){
2291 gen tmp(f(it->value,contextptr));
2292 if (!is_zero(tmp,contextptr))
2293 res.coord.push_back(monomial<gen>(tmp,it->index));
2294 }
2295 return res;
2296 }
2297
set_precision(const gen & g,int nbits)2298 static gen set_precision(const gen & g,int nbits){
2299 if (nbits<45)
2300 return evalf_double(g,1,context0);
2301 #ifdef HAVE_LIBMPFR
2302 return real_object(g,nbits);
2303 #else
2304 gen tmp=evalf_double(g,1,context0);
2305 gen G=g;
2306 if (tmp.type==_DOUBLE_ && tmp._DOUBLE_val!=0)
2307 round2(G,int(nbits-std::log(absdouble(tmp._DOUBLE_val))/std::log(2.0)));
2308 return evalf_double(G,1,context0);
2309 #endif
2310 }
2311
accurate_evalf(const gen & g,int nbits)2312 gen accurate_evalf(const gen & g,int nbits){
2313 if (g.type==_FRAC && g._FRACptr->num.type==_VECT)
2314 return inv(accurate_evalf(g._FRACptr->den,nbits),context0)*accurate_evalf(g._FRACptr->num,nbits);
2315 if (g.type==_VECT)
2316 return gen(accurate_evalf(*g._VECTptr,nbits),g.subtype);
2317 gen r,i;reim(g,r,i,context0); // only called for numeric values
2318 if (is_zero(i,context0))
2319 return set_precision(r,nbits);
2320 else
2321 return gen(set_precision(r,nbits),set_precision(i,nbits));
2322 }
2323
accurate_evalf(const vecteur & v,int nbits)2324 vecteur accurate_evalf(const vecteur & v,int nbits){
2325 vecteur res(v);
2326 iterateur it=res.begin(),itend=res.end();
2327 for (;it!=itend;++it)
2328 *it = accurate_evalf(*it,nbits);
2329 return res;
2330 }
2331
evalf(const gen & e,int level,const context * contextptr)2332 gen evalf(const gen & e,int level,const context * contextptr){
2333 return e.evalf(level,contextptr);
2334 }
2335
no_context_evalf(const gen & e)2336 gen no_context_evalf(const gen & e){
2337 gen tmp;
2338 if (has_evalf(e,tmp,1,context0))
2339 return tmp;
2340 else
2341 return e;
2342 }
2343
2344 static const double double0_15[]={0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0};
_int2double(unsigned i)2345 static double _int2double(unsigned i){
2346 if (i<16)
2347 return double0_15[i];
2348 else
2349 return _int2double(i/16)*16.0+double0_15[i%16];
2350 }
2351 // double(int) does not seem to work under GNUWINCE
int2double(int i)2352 double int2double(int i){
2353 if (i<0)
2354 return -_int2double(-i);
2355 else
2356 return _int2double(i);
2357 }
2358
2359
evalf(int level,const context * contextptr) const2360 gen gen::evalf(int level,const context * contextptr) const{
2361 // CERR << "evalf " << *this << " " << level << '\n';
2362 #ifdef TIMEOUT
2363 control_c();
2364 #endif
2365 if (ctrl_c || interrupted) {
2366 interrupted = true; ctrl_c=false;
2367 return gensizeerr(gettext("Stopped by user interruption."));
2368 }
2369 if (level==0)
2370 return *this;
2371 gen evaled;
2372 if (in_evalf(level,evaled,contextptr))
2373 return evaled;
2374 else
2375 return *this;
2376 }
2377
m_pi(GIAC_CONTEXT)2378 gen m_pi(GIAC_CONTEXT){
2379 int nbits=digits2bits(decimal_digits(contextptr));
2380 return m_pi(nbits);
2381 }
2382
m_pi(int nbits)2383 gen m_pi(int nbits){
2384 #ifdef HAVE_LIBMPFR
2385 if (nbits>48){
2386 #ifdef HAVE_LIBPTHREAD
2387 int locked=pthread_mutex_lock(&mpfr_mutex);
2388 #else // HAVE_LIBPTHREAD
2389 int locked=0;
2390 #endif
2391 if (!locked)
2392 mpfr_set_default_prec(nbits);
2393 mpfr_t pi;
2394 mpfr_init(pi);
2395 mpfr_const_pi(pi,MPFR_RNDN);
2396 #ifdef HAVE_LIBPTHREAD
2397 if (!locked)
2398 pthread_mutex_unlock(&mpfr_mutex);
2399 #endif
2400 gen res=real_object(pi);
2401 mpfr_clear(pi);
2402 return res;
2403 }
2404 #endif
2405 #if 0 // def BCD
2406 return fpi();
2407 #else
2408 return M_PI;
2409 #endif
2410 }
2411
m_gamma(int nbits)2412 gen m_gamma(int nbits){
2413 #ifdef HAVE_LIBMPFR
2414 if (nbits>15){
2415 #ifdef HAVE_LIBPTHREAD
2416 int locked=pthread_mutex_lock(&mpfr_mutex);
2417 #else // HAVE_LIBPTHREAD
2418 int locked=0;
2419 #endif
2420 if (!locked)
2421 mpfr_set_default_prec(nbits);
2422 mpfr_t euler_gamma;
2423 mpfr_init(euler_gamma);
2424 mpfr_const_euler(euler_gamma,MPFR_RNDN);
2425 #ifdef HAVE_LIBPTHREAD
2426 if (!locked)
2427 pthread_mutex_unlock(&mpfr_mutex);
2428 #endif
2429 gen res=real_object(euler_gamma);
2430 mpfr_clear(euler_gamma);
2431 return res;
2432 }
2433 #endif
2434 return .577215664901533;
2435 }
2436
m_gamma(GIAC_CONTEXT)2437 gen m_gamma(GIAC_CONTEXT){
2438 int nbits=digits2bits(decimal_digits(contextptr));
2439 return m_gamma(nbits);
2440 }
2441
approx_pnt(int level,const gen & g,gen & evaled,const context * contextptr)2442 static bool approx_pnt(int level,const gen & g,gen & evaled,const context * contextptr){
2443 vecteur v=*g._SYMBptr->feuille._VECTptr;
2444 if (!v[0].in_evalf(level,evaled,contextptr))
2445 return false;
2446 v[0]=evaled;
2447 evaled=symbolic(at_pnt,gen(v,g._SYMBptr->feuille.subtype));
2448 return true;
2449 }
2450
has_evalf(const identificateur & g,int subtype,gen & res,int level,GIAC_CONTEXT)2451 static bool has_evalf(const identificateur & g,int subtype,gen & res,int level,GIAC_CONTEXT){
2452 if (strcmp(g.id_name,string_pi)==0){
2453 res=m_pi(contextptr);
2454 return true;
2455 }
2456 gen tmp=g;
2457 tmp.subtype=subtype;
2458 tmp=tmp.evalf(level,contextptr);
2459 if (tmp.type==_IDNT || tmp.type==_SYMB)
2460 return false;
2461 return has_evalf(tmp,res,0,contextptr);
2462 }
2463
has_evalf(const gen & g,gen & res,int level,GIAC_CONTEXT)2464 bool has_evalf(const gen & g,gen & res,int level,GIAC_CONTEXT){
2465 switch (g.type){
2466 case _DOUBLE_: case _FLOAT_: case _REAL:
2467 res=g;
2468 return true;
2469 case _INT_: case _ZINT: case _CPLX:
2470 res=evalf(g,1,contextptr);
2471 return true;
2472 case _IDNT:
2473 return has_evalf(*g._IDNTptr,g.subtype,res,level,contextptr);
2474 case _SYMB:
2475 if (has_evalf(g._SYMBptr->feuille,res,level,contextptr)){
2476 res=g._SYMBptr->sommet(res,contextptr);
2477 if (res.type==_INT_ || res.type==_ZINT)
2478 res=evalf(res,1,contextptr);
2479 return res.type==_DOUBLE_ || res.type==_FLOAT_ || res.type==_CPLX || res.type==_REAL;
2480 }
2481 else
2482 return false;
2483 }
2484 if (g.type==_EXT){
2485 gen a,b;
2486 if (has_evalf(*g._EXTptr,a,level,contextptr) && has_evalf(*(g._EXTptr+1),b,level,contextptr)){
2487 a=alg_evalf(a,b,contextptr);
2488 return a.type==_EXT?false:has_evalf(a,res,level,contextptr);
2489 }
2490 return false;
2491 }
2492 if (g.type==_FRAC){
2493 if (is_cinteger(g._FRACptr->num) && is_cinteger(g._FRACptr->den)){
2494 return g.in_evalf(1,res,contextptr);
2495 }
2496 gen num,den;
2497 if (has_evalf(g._FRACptr->num,num,level,contextptr) && has_evalf(g._FRACptr->den,den,level,contextptr)){
2498 res=num/den;
2499 return true;
2500 }
2501 else
2502 return false;
2503 }
2504 if (g.type!=_VECT)
2505 return false;
2506 if (g.subtype==_ASSUME__VECT && !g._VECTptr->empty()){
2507 res=g._VECTptr->back();
2508 return true;
2509 }
2510 vecteur v;
2511 const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
2512 v.reserve(itend-it);
2513 for (;it!=itend;++it){
2514 if (!has_evalf(*it,res,level,contextptr))
2515 return false;
2516 v.push_back(res);
2517 }
2518 res=gen(v,g.subtype);
2519 return true;
2520 }
2521
in_evalf(int level,gen & evaled,const context * contextptr) const2522 bool gen::in_evalf(int level,gen & evaled,const context * contextptr) const{
2523 if (!level)
2524 return false;
2525 switch (type) {
2526 case _REAL:
2527 #if 0 // ndef NO_RTTI // infinite recursion with has_evalf and real intervals
2528 if (real_interval * ptr=dynamic_cast<real_interval *>(_REALptr)){
2529 evaled=real_object(ptr->inf);
2530 return true;
2531 }
2532 #endif
2533 return false;
2534 case _DOUBLE_: case _FLOAT_: case _STRNG: case _MAP: case _EQW: case _GROB: case _POINTER_:
2535 return false;
2536 case _INT_:
2537 if (subtype)
2538 return false;
2539 if (decimal_digits(contextptr)>14){
2540 evaled=real_object(*this,digits2bits(decimal_digits(contextptr)));
2541 return true;
2542 }
2543 #if 0 // def BCD
2544 evaled=giac_float(val);
2545 #else
2546 evaled=int2double(val);
2547 #endif
2548 return true;
2549 case _ZINT:
2550 #if 0 // def BCD
2551 evaled=giac_float(_ZINTptr);
2552 #else
2553 if (decimal_digits(contextptr)>14)
2554 evaled=real_object(*this,digits2bits(decimal_digits(contextptr)));
2555 else
2556 evaled=mpz_get_d(*_ZINTptr);
2557 #endif
2558 return true;
2559 case _CPLX:
2560 evaled=gen(_CPLXptr->evalf(level,contextptr),(_CPLXptr+1)->evalf(level,contextptr));
2561 return true;
2562 case _USER:
2563 evaled=_USERptr->evalf(level,contextptr);
2564 return true;
2565 case _IDNT:
2566 if (strcmp(_IDNTptr->id_name,string_pi)==0){
2567 evaled=m_pi(contextptr);
2568 return true;
2569 }
2570 if (strcmp(_IDNTptr->id_name,string_euler_gamma)==0){
2571 evaled=m_gamma(contextptr);
2572 return true;
2573 }
2574 if (!contextptr && subtype==_GLOBAL__EVAL)
2575 evaled=global_evalf(*_IDNTptr,level-1);
2576 else {
2577 if (!_IDNTptr->in_eval(level-1,*this,evaled,contextptr))
2578 return false;
2579 }
2580 return check_not_assume(*this,evaled,true,contextptr);
2581 case _VECT:
2582 evaled=evalf_VECT(*_VECTptr,subtype,level,contextptr);
2583 return true;
2584 case _SYMB:
2585 if (subtype==_SPREAD__SYMB)
2586 return false;
2587 if (_SYMBptr->sommet==at_pow && _SYMBptr->feuille._VECTptr->back().type==_INT_){
2588 evaled=pow(_SYMBptr->feuille._VECTptr->front().evalf(level,contextptr),_SYMBptr->feuille._VECTptr->back(),contextptr);
2589 return true;
2590 }
2591 if (_SYMBptr->sommet==at_integrate || (_SYMBptr->sommet==at_int && xcas_mode(contextptr)!=3)){
2592 evaled=_gaussquad(_SYMBptr->feuille,contextptr); // FIXME: take care of precision (romberg if >14 digits?)
2593 return true;
2594 }
2595 if (_SYMBptr->sommet==at_rootof){
2596 evaled=approx_rootof(_SYMBptr->feuille.evalf(level,contextptr),contextptr);
2597 return true;
2598 }
2599 if (_SYMBptr->sommet==at_cell)
2600 return false;
2601 if (_SYMBptr->sommet==at_pnt && _SYMBptr->feuille.type==_VECT && !_SYMBptr->feuille._VECTptr->empty())
2602 return approx_pnt(level,*this,evaled,contextptr);
2603 evaled=_SYMBptr->evalf(level,contextptr);
2604 return true;
2605 case _FRAC:
2606 #ifdef HAVE_LIBMPFR
2607 if (decimal_digits(contextptr)>14)
2608 evaled=rdiv(_FRACptr->num.evalf(level,contextptr),_FRACptr->den.evalf(level,contextptr),contextptr);
2609 else
2610 #endif
2611 {
2612 if (is_zero(_FRACptr->num.im(contextptr)) && is_zero(_FRACptr->den.im(contextptr)))
2613 evaled=evalf_FRAC(*_FRACptr,contextptr);
2614 else
2615 evaled=re(contextptr).evalf(1,contextptr)+cst_i*im(contextptr).evalf(1,contextptr);
2616 }
2617 return true;
2618 #ifdef HAVE_LIBMPFR
2619 if (decimal_digits(contextptr)<=14)
2620 evaled=set_precision(re(contextptr),60).evalf_double(1,contextptr)+cst_i*set_precision(im(contextptr),60).evalf_double(1,contextptr);
2621 else
2622 #endif
2623 evaled=rdiv(_FRACptr->num.evalf(level,contextptr),_FRACptr->den.evalf(level,contextptr),contextptr);
2624 return true;
2625 case _FUNC:
2626 return in_eval_func(*this,&evaled,contextptr);
2627 case _MOD: case _ROOT:
2628 return false; // replace in RPN mode
2629 case _EXT:
2630 evaled=alg_evalf(_EXTptr->eval(level,contextptr),(_EXTptr+1)->eval(level,contextptr),contextptr);
2631 return true;
2632 case _POLY:
2633 evaled=apply(*_POLYptr,no_context_evalf);
2634 return true;
2635 default:
2636 evaled=gentypeerr(gettext("Evalf")) ;
2637 return false;
2638 }
2639 return false;
2640 }
2641
real2int(const gen & g,GIAC_CONTEXT)2642 gen real2int(const gen & g,GIAC_CONTEXT){
2643 if (g.type==_REAL){
2644 if (is_strictly_positive(-g,contextptr))
2645 return -real2int(-g,contextptr);
2646 if (is_zero(g))
2647 return 0;
2648 #ifdef HAVE_LIBMPFR
2649 ref_mpz_t * m=new ref_mpz_t;
2650 int n=int(mpfr_get_z_exp(m->z,g._REALptr->inf));
2651 gen res(m->z);
2652 if (n>=0)
2653 return res*pow(plus_two,gen(n),contextptr);
2654 return _iquo(makesequence(res,pow(plus_two,gen(-n),contextptr)),contextptr);
2655 #else
2656 return g;
2657 #endif
2658 }
2659 if (g.type!=_VECT)
2660 return g;
2661 return apply(g,real2int,contextptr);
2662 }
2663
real2double(const gen & g)2664 gen real2double(const gen & g){
2665 if (g.type==_REAL)
2666 return g._REALptr->evalf_double();
2667 if (g.type==_FLOAT_)
2668 return get_double(g._FLOAT_val);
2669 if (g.type!=_VECT)
2670 return g;
2671 return apply(g,real2double);
2672 }
2673
evalf_double(int level,const context * contextptr) const2674 gen gen::evalf_double(int level,const context * contextptr) const{
2675 if (type==_DOUBLE_)
2676 return *this;
2677 if (type==_INT_ && subtype==_INT_BOOLEAN)
2678 return double(val);
2679 gen g;
2680 if (has_evalf(*this,g,level,contextptr)){
2681 if (g.type==_CPLX)
2682 return gen(real2double(*g._CPLXptr),real2double(*(g._CPLXptr+1)));
2683 else
2684 return real2double(g);
2685 }
2686 else
2687 return *this;
2688 }
2689
evalf2double_nock(const gen & g0,int level,const context * contextptr)2690 gen evalf2double_nock(const gen & g0,int level,const context * contextptr){
2691 if (g0.type==_INT_)
2692 return double(g0.val);
2693 if (g0.type==_DOUBLE_)
2694 return g0;
2695 if (g0.is_symb_of_sommet(at_program))
2696 return g0;
2697 if (g0.type==_FLOAT_ || g0.type==_FRAC || g0.type==_ZINT || g0.type==_REAL)
2698 return evalf_double(g0,1,contextptr);
2699 if (storcl_38 && level && g0.type==_IDNT){
2700 if (!strcmp(g0._IDNTptr->id_name,"pi"))
2701 return M_PI;
2702 gen res;
2703 // if (storcl_38(res,0,g0._IDNTptr->id_name,undef,false,contextptr)) return evalf2double_nock(res,level-1,contextptr);
2704 }
2705 if (g0.type==_VECT){
2706 ref_vecteur *vptr = new_ref_vecteur(*g0._VECTptr);
2707 iterateur it=vptr->v.begin(),itend=vptr->v.end();
2708 for (;it!=itend;++it)
2709 *it=evalf2double_nock(*it,level,contextptr);
2710 return gen(vptr,g0.subtype);
2711 }
2712 if (is_inf(g0)||is_undef(g0))
2713 return g0;
2714 if (g0.type==_SYMB){
2715 unary_function_ptr & s =g0._SYMBptr->sommet;
2716 gen f =g0._SYMBptr->feuille;
2717 if (s==at_integrate && f._VECTptr->size()==4)
2718 return _gaussquad(f,contextptr);
2719 if (f.type==_VECT && !s.quoted()){
2720 if (s==at_plus){
2721 double res(0);
2722 gen tmp;
2723 iterateur it=f._VECTptr->begin(),itend=f._VECTptr->end();
2724 for (;it!=itend;++it){
2725 tmp=evalf2double_nock(*it,level,contextptr);
2726 if (tmp.type!=_DOUBLE_)
2727 break;
2728 res=res+tmp._DOUBLE_val;
2729 }
2730 if (it==itend)
2731 return res;
2732 }
2733 if (s==at_prod){
2734 double res(1);
2735 gen tmp;
2736 iterateur it=f._VECTptr->begin(),itend=f._VECTptr->end();
2737 for (;it!=itend;++it){
2738 tmp=evalf2double_nock(*it,level,contextptr);
2739 if (tmp.type!=_DOUBLE_)
2740 break;
2741 res=res*tmp._DOUBLE_val;
2742 }
2743 if (it==itend)
2744 return res;
2745 }
2746 if (f._VECTptr->size()==2){
2747 gen tmp1=evalf2double_nock(f._VECTptr->front(),level,contextptr);
2748 gen tmp2=f._VECTptr->back();
2749 if (tmp1.type==_DOUBLE_ && tmp2.type==_INT_ && s==at_pow)
2750 return std::pow(tmp1._DOUBLE_val,double(tmp2.val));
2751 tmp2=evalf2double_nock(tmp2,level,contextptr);
2752 if (s==at_pow)
2753 return pow(tmp1,tmp2,contextptr);
2754 if (s==at_division)
2755 return rdiv(tmp1,tmp2,contextptr);
2756 if (s==at_minus)
2757 return operator_minus(tmp1,tmp2,contextptr);
2758 tmp1=s(gen(makenewvecteur(tmp1,tmp2),f.subtype),contextptr);
2759 if (tmp1.type<_IDNT || tmp1.type==_FRAC)
2760 tmp1=evalf2double_nock(tmp1,1,contextptr);
2761 return tmp1;
2762 }
2763 }
2764 if (s.quoted()) {
2765 if (s==at_quote)
2766 return f;
2767 f=s(f,contextptr);
2768 if (f.type<_IDNT || f.type==_FRAC || (f.type==_SYMB && contains(f,cst_pi)) )
2769 f=evalf2double_nock(f,1,contextptr);
2770 return f;
2771 }
2772 f=s(evalf2double_nock(f,level,contextptr),contextptr);
2773 if (f.type<_IDNT || f.type==_FRAC)
2774 f=evalf2double_nock(f,1,contextptr);
2775 return f;
2776 }
2777 if (g0.type==_CPLX){
2778 if (g0._CPLXptr->type==_DOUBLE_ && (g0._CPLXptr+1)->type==_DOUBLE_){
2779 #if 1
2780 // maybe we should round complex numbers that are close to reals?
2781 if (fabs((g0._CPLXptr+1)->_DOUBLE_val)<1e-12*fabs(g0._CPLXptr->_DOUBLE_val))
2782 return g0._CPLXptr->_DOUBLE_val;
2783 #endif
2784 return g0;
2785 }
2786 return evalf2double_nock(*g0._CPLXptr,1,contextptr)+cst_i*evalf2double_nock(*(g0._CPLXptr+1),1,contextptr);
2787 }
2788 gen g=evalf(g0,level,contextptr);
2789 if (g.type==_FLOAT_)
2790 return evalf_double(g,1,contextptr);
2791 if (g.type==_CPLX)
2792 return evalf2double_nock(*g._CPLXptr,1,contextptr)+cst_i*evalf2double_nock(*(g._CPLXptr+1),1,contextptr);
2793 return g;
2794 }
2795
2796
evalf2double(int level,const context * contextptr) const2797 gen gen::evalf2double(int level,const context * contextptr) const{
2798 /*
2799 gen g=evalf(level,contextptr);
2800 return g.evalf_double(level,contextptr);
2801 */
2802 return evalf2double_nock(*this,level,contextptr);
2803 }
2804
chk_inf_nan(const gen & g0)2805 gen chk_inf_nan(const gen & g0){
2806 if (g0.type==_FLOAT_){
2807 if (fis_nan(g0._FLOAT_val))
2808 return undeferr(gettext("Undefined"));
2809 if (fis_inf_notmax(g0._FLOAT_val))
2810 return undeferr(gettext("Infinity error"));
2811 return g0;
2812 }
2813 if (is_undef(g0)){
2814 if (g0.type==_STRNG)
2815 return g0;
2816 if (g0.type==_VECT && !g0._VECTptr->empty())
2817 return g0._VECTptr->front();
2818 return undeferr(gettext("Undefined"));
2819 }
2820 if (is_inf(g0))
2821 return undeferr(gettext("Infinity error"));
2822 return g0;
2823 }
2824
evalf2bcd_nock(const gen & g0,int level,const context * contextptr)2825 gen evalf2bcd_nock(const gen & g0,int level,const context * contextptr){
2826 if (g0.type==_FLOAT_)
2827 return g0;
2828 if (g0.type==_FRAC)
2829 return evalf_FRAC(*g0._FRACptr,contextptr);
2830 if (g0.type==_INT_)
2831 return giac_float(g0.val);
2832 // FIXME _ZINT should be converted without being evalf-ed to double
2833 #ifdef BCD
2834 if (g0.type==_ZINT)
2835 return giac_float(g0._ZINTptr);
2836 #endif
2837 if (storcl_38 && level && g0.type==_IDNT){
2838 #ifdef BCD
2839 if (!strcmp(g0._IDNTptr->id_name,"pi"))
2840 return fpi();
2841 #endif
2842 gen res;
2843 if (storcl_38(res,0,g0._IDNTptr->id_name,undef,false,contextptr,NULL,false))
2844 return evalf2bcd_nock(res,level-1,contextptr);
2845 }
2846 if (g0.type==_VECT){
2847 ref_vecteur *vptr = new_ref_vecteur(*g0._VECTptr);
2848 iterateur it=vptr->v.begin(),itend=vptr->v.end();
2849 for (;it!=itend;++it)
2850 *it=evalf2bcd_nock(*it,level,contextptr);
2851 return gen(vptr,g0.subtype);
2852 }
2853 if (is_inf(g0)||is_undef(g0))
2854 return g0;
2855 if (g0.type==_SYMB){
2856 /*
2857 if (g0._SYMBptr->sommet==at_unit){
2858 gen f = g0._SYMBptr->feuille;
2859 if (f.type==_VECT && f._VECTptr->size()==2){
2860 f=gen(makevecteur(evalf2bcd_nock(f._VECTptr->front(),level,contextptr),f._VECTptr->back()),f.subtype);
2861 return symbolic(at_unit,f);
2862 }
2863 else
2864 return g0;
2865 }
2866 */
2867 unary_function_ptr & s =g0._SYMBptr->sommet;
2868 gen f =g0._SYMBptr->feuille;
2869 if (s==at_integrate && f._VECTptr->size()==4)
2870 return _gaussquad(f,contextptr);
2871 if (f.type==_VECT && !s.quoted()){
2872 if (s==at_plus){
2873 giac_float res(0);
2874 gen tmp;
2875 iterateur it=f._VECTptr->begin(),itend=f._VECTptr->end();
2876 for (;it!=itend;++it){
2877 tmp=evalf2bcd_nock(*it,level,contextptr);
2878 if (tmp.type!=_FLOAT_)
2879 break;
2880 res=res+tmp._FLOAT_val;
2881 }
2882 if (it==itend)
2883 return res;
2884 }
2885 if (s==at_prod){
2886 giac_float res(1);
2887 gen tmp;
2888 iterateur it=f._VECTptr->begin(),itend=f._VECTptr->end();
2889 for (;it!=itend;++it){
2890 tmp=evalf2bcd_nock(*it,level,contextptr);
2891 if (tmp.type!=_FLOAT_)
2892 break;
2893 res=res*tmp._FLOAT_val;
2894 }
2895 if (it==itend)
2896 return res;
2897 }
2898 if (f._VECTptr->size()==2){
2899 gen tmp1=evalf2bcd_nock(f._VECTptr->front(),level,contextptr);
2900 gen tmp2=f._VECTptr->back();
2901 if (tmp1.type==_FLOAT_ && tmp2.type==_INT_ && s==at_pow)
2902 return fpow(tmp1._FLOAT_val,giac_float(tmp2.val));
2903 tmp2=evalf2bcd_nock(tmp2,level,contextptr);
2904 if (s==at_pow)
2905 return pow(tmp1,tmp2,contextptr);
2906 if (s==at_division)
2907 return rdiv(tmp1,tmp2,contextptr);
2908 if (s==at_minus)
2909 return operator_minus(tmp1,tmp2,contextptr);
2910 tmp1=s(gen(makenewvecteur(tmp1,tmp2),f.subtype),contextptr);
2911 if (tmp1.type<_IDNT || tmp1.type==_FRAC)
2912 tmp1=evalf2bcd_nock(tmp1,1,contextptr);
2913 return tmp1;
2914 }
2915 }
2916 if (s.quoted()) {
2917 if (s==at_quote)
2918 return f;
2919 f=s(f,contextptr);
2920 if (f.type<_IDNT || f.type==_FRAC)
2921 f=evalf2bcd_nock(f,1,contextptr);
2922 return f;
2923 }
2924 f=s(evalf2bcd_nock(f,level,contextptr),contextptr);
2925 if (f.type<_IDNT || f.type==_FRAC)
2926 f=evalf2bcd_nock(f,1,contextptr);
2927 return f;
2928 }
2929 if (g0.type==_CPLX){
2930 if (g0._CPLXptr->type==_FLOAT_ && (g0._CPLXptr+1)->type==_FLOAT_)
2931 return g0;
2932 return evalf2bcd_nock(*g0._CPLXptr,1,contextptr)+cst_i*evalf2bcd_nock(*(g0._CPLXptr+1),1,contextptr);
2933 }
2934 gen g=evalf(g0,level,contextptr);
2935 if (g.type==_DOUBLE_)
2936 return giac_float(g._DOUBLE_val);
2937 if (g.type==_CPLX)
2938 return evalf2bcd_nock(*g._CPLXptr,1,contextptr)+cst_i*evalf2bcd_nock(*(g._CPLXptr+1),1,contextptr);
2939 return g;
2940 }
2941
evalf2bcd(const gen & g0,int level,const context * contextptr)2942 gen evalf2bcd(const gen & g0,int level,const context * contextptr){
2943 return chk_inf_nan(evalf2bcd_nock(g0,level,contextptr));
2944 }
2945
poly_is_real(const polynome & p)2946 bool poly_is_real(const polynome & p){
2947 vector< monomial<gen> >::const_iterator it=p.coord.begin(),itend=p.coord.end();
2948 for (;it!=itend;++it){
2949 if (!it->value.is_real(0)) // context is 0 since coeff do not depend on
2950 return false;
2951 }
2952 return true;
2953 }
2954
vect_is_real(const vecteur & v,GIAC_CONTEXT)2955 bool vect_is_real(const vecteur & v,GIAC_CONTEXT){
2956 const_iterateur it=v.begin(),itend=v.end();
2957 for (;it!=itend;++it){
2958 if (!it->is_real(contextptr))
2959 return false;
2960 }
2961 return true;
2962 }
2963
2964 /* Checking */
is_real(GIAC_CONTEXT) const2965 bool gen::is_real(GIAC_CONTEXT) const {
2966 switch (type) {
2967 case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL:
2968 return true;
2969 case _CPLX:
2970 return (is_zero(*(_CPLXptr+1),contextptr));
2971 case _POLY:
2972 return poly_is_real(*_POLYptr);
2973 case _VECT:
2974 return vect_is_real(*_VECTptr,contextptr);
2975 default:
2976 return is_zero(im(contextptr),contextptr);
2977 }
2978 }
2979
is_approx() const2980 bool gen::is_approx() const {
2981 switch(type){
2982 case _DOUBLE_: case _FLOAT_: case _REAL:
2983 return true;
2984 case _CPLX:
2985 return subtype==3 || (_CPLXptr->is_approx() && (_CPLXptr+1)->is_approx());
2986 case _VECT:
2987 return has_num_coeff(*this);
2988 default:
2989 return false;
2990 }
2991 }
2992
is_cinteger() const2993 bool gen::is_cinteger() const {
2994 switch (type ) {
2995 case _INT_: case _ZINT:
2996 return true;
2997 case _CPLX:
2998 return _CPLXptr->is_integer() && (_CPLXptr+1)->is_integer();
2999 default:
3000 return false;
3001 }
3002 }
3003
is_integer() const3004 bool gen::is_integer() const {
3005 switch (type ) {
3006 case _INT_: case _ZINT:
3007 return true;
3008 case _CPLX:
3009 return is_exactly_zero(*(_CPLXptr+1)) && _CPLXptr->is_integer();
3010 default:
3011 return false;
3012 }
3013 }
3014
_VECT_is_constant(const vecteur & v)3015 bool _VECT_is_constant(const vecteur & v){
3016 const_iterateur it=v.begin(),itend=v.end();
3017 for (;it!=itend;++it)
3018 if (!(it->is_constant()))
3019 return false;
3020 return true;
3021 }
3022
is_constant() const3023 bool gen::is_constant() const {
3024 switch (type ) {
3025 case _INT_: case _DOUBLE_: case _FLOAT_: case _REAL: case _ZINT: case _CPLX:
3026 return true;
3027 case _VECT:
3028 return _VECT_is_constant(*this->_VECTptr);
3029 case _EXT:
3030 return _EXTptr->is_constant() && (_EXTptr+1)->is_constant();
3031 case _POLY:
3032 return Tis_constant<gen>(*_POLYptr) && _POLYptr->coord.front().value.is_constant();
3033 default:
3034 return false;
3035 }
3036 }
3037
is_atomic(const gen & e)3038 bool is_atomic(const gen & e){
3039 return e.type<_POLY || e.type==_FLOAT_ || e.type==_USER;
3040 }
3041
giac_conj(const gen & g,GIAC_CONTEXT)3042 static gen giac_conj(const gen & g,GIAC_CONTEXT){
3043 return conj(g,contextptr);
3044 }
3045
giac_re(const gen & g,GIAC_CONTEXT)3046 static gen giac_re(const gen & g,GIAC_CONTEXT){
3047 return re(g,contextptr);
3048 }
3049
giac_im(const gen & g,GIAC_CONTEXT)3050 static gen giac_im(const gen & g,GIAC_CONTEXT){
3051 return im(g,contextptr);
3052 }
3053
_VECTconj(const vecteur & a,GIAC_CONTEXT)3054 static vecteur _VECTconj(const vecteur & a,GIAC_CONTEXT){
3055 vecteur res;
3056 vecteur::const_iterator it=a.begin(),itend=a.end();
3057 for (;it!=itend;++it)
3058 res.push_back(it->conj(contextptr));
3059 return res;
3060 }
3061
3062 // the complex pointed by res is modified despite being declared const
adjust_complex_display(const gen & res,const gen & a,const gen & b)3063 static gen adjust_complex_display(const gen & res,const gen & a,const gen & b){
3064 int * target = complex_display_ptr(res);
3065 int * aptr = complex_display_ptr(a);
3066 int * bptr = complex_display_ptr(b);
3067 if (target && aptr && bptr)
3068 *target = *aptr & *bptr;
3069 return res;
3070 }
3071
3072 // the complex pointed by res is modified despite being declared const
adjust_complex_display(const gen & res,const gen & a)3073 static gen adjust_complex_display(const gen & res,const gen & a){
3074 int * target = complex_display_ptr(res);
3075 int * aptr = complex_display_ptr(a);
3076 if (target && aptr)
3077 *target = *aptr ;
3078 return res;
3079 }
3080
3081 // change complex display type (in-place, true if changed, false otherwise)
3082 // modifies complex, vecteur and symbolics
adjust_complex_display(gen & res,int value)3083 int adjust_complex_display(gen & res,int value){
3084 if (res.type==_CPLX){
3085 if (value==3)
3086 return 1;
3087 res=gen(*res._CPLXptr,*(res._CPLXptr+1));
3088 int * target = complex_display_ptr(res);
3089 if (value==2)
3090 *target = 1 - (*target);
3091 else
3092 * target = value;
3093 return 1;
3094 }
3095 if (res.type==_VECT){
3096 vecteur v(*res._VECTptr);
3097 int n=int(v.size());
3098 int r=0;
3099 for (int i=0;i<n;++i){
3100 r += adjust_complex_display(v[i],value);
3101 }
3102 if (!r || value==3)
3103 return r;
3104 res = gen(v,res.subtype);
3105 return r;
3106 }
3107 if (res.type!=_SYMB)
3108 return 0;
3109 gen f=res._SYMBptr->feuille;
3110 int r=adjust_complex_display(f,value);
3111 if (!r || value==3)
3112 return r;
3113 res=symbolic(res._SYMBptr->sommet,f);
3114 return r;
3115 }
3116
conj(GIAC_CONTEXT) const3117 gen gen::conj(GIAC_CONTEXT) const {
3118 switch (type ) {
3119 case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL: case _STRNG:
3120 return *this;
3121 case _CPLX:
3122 return adjust_complex_display(gen(*_CPLXptr,-(*(_CPLXptr+1))),*this);
3123 case _VECT:
3124 return gen(_VECTconj(*_VECTptr,contextptr),subtype);
3125 case _MAP:
3126 return apply(*this,giac_conj,contextptr);
3127 case _USER:
3128 return _USERptr->conj(contextptr);
3129 case _IDNT:
3130 if (is_assumed_real(*this,contextptr))
3131 return *this;
3132 /* if ( (_IDNTptr->value) && (is_zero(_IDNTptr->value->im(),contextptr)) )
3133 return *this; */
3134 return new_ref_symbolic(symbolic(at_conj,*this));
3135 case _SYMB:
3136 if (_SYMBptr->sommet==at_conj)
3137 return _SYMBptr->feuille;
3138 if (_SYMBptr->sommet==at_re || _SYMBptr->sommet==at_im)
3139 return *this;
3140 if (_SYMBptr->sommet==at_polar_complex && _SYMBptr->feuille.type==_VECT && _SYMBptr->feuille._VECTptr->size()==2){
3141 vecteur v=*_SYMBptr->feuille._VECTptr;
3142 v[1]=-v[1];
3143 return symbolic(at_polar_complex,gen(v,_SEQ__VECT));
3144 }
3145 if (_SYMBptr->sommet==at_rootof){
3146 gen a;
3147 if (has_evalf(*this,a,1,contextptr) && is_zero(a.im(contextptr),contextptr))
3148 return *this;
3149 if (_SYMBptr->feuille.type==_VECT && _SYMBptr->feuille._VECTptr->size()==2){
3150 vecteur tmp=*_SYMBptr->feuille._VECTptr;
3151 if (lidnt(tmp[1]).empty()){
3152 vecteur w=*tmp[1]._VECTptr;
3153 gen P;
3154 if (conj_in_nf(w,P,contextptr)){
3155 // P is a rootof such that conj(rootof(w))=P
3156 gen c=horner(tmp[0].conj(contextptr),P);
3157 c=normal(c,contextptr);
3158 return c;
3159 }
3160 }
3161 }
3162 }
3163 if (equalposcomp(plot_sommets,_SYMBptr->sommet) || equalposcomp(analytic_sommets,_SYMBptr->sommet) || _SYMBptr->sommet==at_surd || _SYMBptr->sommet==at_erf)
3164 return new_ref_symbolic(symbolic(_SYMBptr->sommet,_SYMBptr->feuille.conj(contextptr)));
3165 else
3166 return new_ref_symbolic(symbolic(at_conj,*this));
3167 case _FRAC:
3168 return fraction(_FRACptr->num.conj(contextptr),_FRACptr->den.conj(contextptr));
3169 case _MOD:
3170 return makemod(_MODptr->conj(contextptr),*(_MODptr+1));
3171 case _EXT:
3172 return algebraic_EXTension(_EXTptr->conj(contextptr),*(_EXTptr+1));
3173 default:
3174 return gentypeerr(gettext("Conj"));
3175 }
3176 return 0;
3177 }
3178
_VECTre(const vecteur & a,GIAC_CONTEXT)3179 static vecteur _VECTre(const vecteur & a,GIAC_CONTEXT){
3180 vecteur res;
3181 vecteur::const_iterator it=a.begin(),itend=a.end();
3182 for (;it!=itend;++it)
3183 res.push_back(it->re(contextptr));
3184 return res;
3185 }
3186
pascal_next_line(const vecteur & v)3187 vecteur pascal_next_line(const vecteur & v){
3188 if (v.empty())
3189 return vecteur(1,plus_one);
3190 const_iterateur it=v.begin(),itend=v.end();
3191 gen current(*it);
3192 vecteur w;
3193 w.reserve(itend-it+1);
3194 w.push_back(current);
3195 for (++it;it!=itend;++it){
3196 w.push_back(*it+current);
3197 current=*it;
3198 }
3199 w.push_back(plus_one);
3200 return w;
3201 }
3202
pascal_nth_line(int n)3203 vecteur pascal_nth_line(int n){
3204 n=absint(n);
3205 vecteur v(1,plus_one);
3206 for (int i=0;i<n;++i)
3207 v=pascal_next_line(v);
3208 return v;
3209 }
3210
algtrim(const gen & g)3211 static gen algtrim(const gen & g){
3212 if (g.type!=_VECT)
3213 return g;
3214 vecteur tmp=trim(*g._VECTptr,0);
3215 if (tmp.empty())
3216 return zero;
3217 if (tmp.size()==1)
3218 return tmp.front();
3219 return tmp;
3220 }
3221
symb_reim(const symbolic & s,gen & r,gen & i,GIAC_CONTEXT)3222 static void symb_reim(const symbolic & s,gen & r,gen & i,GIAC_CONTEXT){
3223 unary_function_ptr u=s.sommet;
3224 gen f=s.feuille;
3225 if ( (u==at_re) || (u==at_im) || (u==at_abs) || (u==at_surd) || (u==at_NTHROOT) || (u==at_innertln)){
3226 r=s;
3227 i=0;
3228 return;
3229 }
3230 if (u==at_conj){
3231 reim(f,r,i,contextptr);
3232 i=-i;
3233 return;
3234 }
3235 if (u==at_plus){
3236 reim(f,r,i,contextptr);
3237 r=_plus(r,contextptr);
3238 i=_plus(i,contextptr);
3239 return;
3240 }
3241 if (u==at_neg){
3242 reim(f,r,i,contextptr);
3243 r=-r;
3244 i=-i;
3245 return;
3246 }
3247 if (u==at_polar_complex && f.type==_VECT && f._VECTptr->size()==2){
3248 i=f._VECTptr->back();
3249 f=f._VECTptr->front();
3250 r=f*cos(i,contextptr);
3251 i=f*sin(i,contextptr);
3252 return;
3253 }
3254 if (u==at_division){
3255 reim(f[0]*inv(f[1],contextptr),r,i,contextptr);
3256 return ;
3257 }
3258 if (u==at_sqrt){
3259 reim(pow(f,plus_one_half,contextptr),r,i,contextptr);
3260 return;
3261 }
3262 if (u==at_prod){
3263 if (f.type!=_VECT){
3264 reim(f,r,i,contextptr);
3265 return;
3266 }
3267 vecteur v(*f._VECTptr);
3268 if (v.empty()){
3269 r=plus_one;
3270 i=0;
3271 return;
3272 }
3273 if (v.size()==1){
3274 reim(v.front(),r,i,contextptr);
3275 return;
3276 }
3277 // cut v in 2 parts and recursive call
3278 // re(a*b)=re(a)*re(b)-im(a)*im(b)
3279 const_iterateur it=v.begin(),itend=v.end();
3280 const_iterateur itm=it+(itend-it+1)/2;
3281 gen a(new_ref_symbolic(symbolic(u,vecteur(it,itm))));
3282 gen b(new_ref_symbolic(symbolic(u,vecteur(itm,itend))));
3283 gen ra,rb,ia,ib;
3284 reim(a,ra,ia,contextptr);
3285 reim(b,rb,ib,contextptr);
3286 r=ra*rb-ia*ib;
3287 i=ra*ib+ia*rb;
3288 return;
3289 }
3290 if (u==at_surd && is_integer(f._VECTptr->back())){
3291 reim(f._VECTptr->front(),r,i,contextptr);
3292 if (is_zero(i,contextptr)){
3293 r=_surd(makesequence(r,f._VECTptr->back()),contextptr);
3294 return;
3295 }
3296 }
3297 if (u==at_derive && f.type==_VECT && !f._VECTptr->empty()){
3298 vecteur v=*f._VECTptr;
3299 reim(v.front(),r,i,contextptr);
3300 v.front()=r;
3301 r=symbolic(at_derive,gen(v,f.subtype));
3302 if (is_zero(i))
3303 return;
3304 v.front()=i;
3305 i=symbolic(at_derive,gen(v,f.subtype));
3306 return;
3307 }
3308 if (u==at_pow){
3309 gen e=f._VECTptr->front(),expo=f._VECTptr->back();
3310 if (expo.type==_INT_){
3311 int n=expo.val;
3312 if (n==0){
3313 r=1;
3314 i=0;
3315 return;
3316 }
3317 reim(e,r,i,contextptr);
3318 if (n==1)
3319 return ;
3320 if (is_zero(i,contextptr)){
3321 r=pow(r,n);
3322 return;
3323 }
3324 if (is_zero(r,contextptr)){
3325 if (n%2){
3326 r=zero;
3327 i=pow(i,n);
3328 if (n%4==3)
3329 i=-i;
3330 return;
3331 }
3332 r=pow(i,n);
3333 i=0;
3334 if (n%4==2)
3335 r=-r;
3336 return;
3337 }
3338 bool n_pos=(n>0);
3339 if (!n_pos){
3340 reim(inv(pow(e,-n),contextptr),r,i,contextptr);
3341 return;
3342 }
3343 vecteur v=pascal_nth_line(n);
3344 vecteur sommer,sommei;
3345 gen signer=1;
3346 const_iterateur it=v.begin();
3347 for (int j=0;j<=n;j+=2){
3348 sommer.push_back(signer*(*it)*pow(r,n-j)*pow(i,j));
3349 ++it;
3350 ++it;
3351 signer=-signer;
3352 }
3353 it=v.begin();
3354 gen signei=1;
3355 ++it;
3356 for (int j=1;j<=n;j+=2){
3357 sommei.push_back(signei*(*it)*pow(r,n-j)*pow(i,j));
3358 ++it;
3359 ++it;
3360 signei=-signei;
3361 }
3362 r=new_ref_symbolic(symbolic(at_plus,sommer));
3363 i=new_ref_symbolic(symbolic(at_plus,sommei));
3364 return ;
3365 } // end integer exponent
3366 if ( is_zero(im(expo,contextptr),contextptr) && is_zero(im(e,contextptr),contextptr) ){
3367 if (!is_integer(expo) && is_positive(-e,contextptr)){
3368 r=pow(-e,expo,contextptr)*cos(cst_pi*expo,contextptr);
3369 i=pow(-e,expo,contextptr)*sin(cst_pi*expo,contextptr);
3370 }
3371 else {
3372 r=s;
3373 i=0;
3374 }
3375 return;
3376 }
3377 if (is_zero(im(expo,contextptr),contextptr)){
3378 reim(e,r,i,contextptr);
3379 gen abse=normal(pow(r,2,contextptr)+pow(i,2,contextptr),contextptr);
3380 gen arge=arg(e,contextptr);
3381 arge=expo*arge;
3382 abse=sqrt(abse,contextptr);
3383 abse=pow(abse,expo,contextptr);
3384 r=abse*cos(arge,contextptr);
3385 i=abse*sin(arge,contextptr);
3386 return;
3387 }
3388 }
3389 if (u==at_rootof && f.type==_VECT && f._VECTptr->size()==2){
3390 vecteur tmp=*f._VECTptr;
3391 // check that the rootof is really real
3392 if (tmp[1].type==_VECT){
3393 int nrealposroot=1;
3394 if (lidnt(tmp[1]).empty()){
3395 vecteur w=*tmp[1]._VECTptr;
3396 gen pol(symb_horner(w,vx_var));
3397 nrealposroot=sturmab(pol,vx_var,0,plus_inf,contextptr);
3398 if (nrealposroot==0 && is_zero(im(tmp[1],contextptr))){
3399 // complex, perhaps the conjugate is in the same nf
3400 gen P;
3401 if (conj_in_nf(w,P,contextptr)){
3402 // P is a rootof such that conj(rootof(w))=P
3403 gen c=horner(conj(tmp[0],contextptr),P);
3404 r=normal((s+c)/2,contextptr);
3405 i=normal((s-c)/2/cst_i,contextptr);
3406 return;
3407 }
3408 }
3409 }
3410 if (nrealposroot>0){
3411 reim(tmp[0],r,i,contextptr);
3412 r=algtrim(r);
3413 if (r.type==_VECT){
3414 tmp[0]=r;
3415 r=new_ref_symbolic(symbolic(u,gen(tmp,f.subtype)));
3416 }
3417 i=algtrim(i);
3418 if (i.type==_VECT){
3419 tmp[0]=i;
3420 i=new_ref_symbolic(symbolic(u,gen(tmp,f.subtype)));
3421 }
3422 return;
3423 }
3424 }
3425 }
3426 gen ref,imf;
3427 if (u==at_integrate){
3428 if (f.type!=_VECT){
3429 reim(f,ref,imf,contextptr);
3430 r=symbolic(at_integrate,ref);
3431 i=is_exactly_zero(imf)?zero:symbolic(at_integrate,imf);
3432 return;
3433 }
3434 vecteur v=*f._VECTptr;
3435 if (v.size()<=2 || (v.size()>=4 && is_exactly_zero(im(v[2],contextptr)) && is_exactly_zero(im(v[3],contextptr)))){
3436 f=v[0];
3437 reim(f,ref,imf,contextptr);
3438 v[0]=ref;
3439 r=is_exactly_zero(ref)?zero:symbolic(at_integrate,gen(v,_SEQ__VECT));
3440 v[0]=imf;
3441 i=is_exactly_zero(imf)?zero:symbolic(at_integrate,gen(v,_SEQ__VECT));
3442 return;
3443 }
3444 }
3445 reim(f,ref,imf,contextptr);
3446 if (is_zero(imf,contextptr) && equalposcomp(reim_op,u)){
3447 r=s; i=0; return;
3448 }
3449 if (u==at_ln){ // FIXME?? might recurse
3450 if (do_lnabs(contextptr)){
3451 r=ln(abs(f,contextptr),contextptr);
3452 i=arg(f,contextptr);
3453 }
3454 else {
3455 r=s; i=0;
3456 }
3457 return ;
3458 }
3459 if (u==at_tan){
3460 reim(rdiv(sin(f,contextptr),cos(f,contextptr),contextptr),r,i,contextptr);
3461 return;
3462 }
3463 if (u==at_tanh){
3464 reim(rdiv(sinh(f,contextptr),cosh(f,contextptr),contextptr),r,i,contextptr);
3465 return;
3466 }
3467 if ((u==at_asin || u==at_acos) && is_zero(imf,contextptr) && is_greater(1,f,contextptr) && is_greater(f,-1,contextptr)){
3468 r=s; i=0; return;
3469 }
3470 if (u==at_inv){
3471 gen tmp=inv(pow(ref,2)+pow(imf,2),contextptr);
3472 r=ref*tmp;
3473 i=-imf*tmp;
3474 return;
3475 }
3476 if (u==at_exp) {
3477 // FIXME?? exp might recurse
3478 r=exp(ref,contextptr)*cos(imf,contextptr);
3479 i=exp(ref,contextptr)*sin(imf,contextptr);
3480 return;
3481 }
3482 if (u==at_cos){
3483 r=cosh(imf,contextptr)*cos(ref,contextptr);
3484 i=-sinh(imf,contextptr)*sin(ref,contextptr);
3485 return;
3486 }
3487 if (u==at_sin){
3488 r=cosh(imf,contextptr)*sin(ref,contextptr);
3489 i=sinh(imf,contextptr)*cos(ref,contextptr);
3490 return;
3491 }
3492 if (u==at_cosh){
3493 r=cos(imf,contextptr)*cosh(ref,contextptr);
3494 i=sin(imf,contextptr)*sinh(ref,contextptr);
3495 return;
3496 }
3497 if (u==at_sinh){
3498 r=cos(imf,contextptr)*sinh(ref,contextptr);
3499 i=sin(imf,contextptr)*cosh(ref,contextptr);
3500 return;
3501 }
3502 if (u==at_floor || u==at_ceil || u==at_round){
3503 r=u(ref,contextptr);
3504 i=u(imf,contextptr);
3505 return;
3506 }
3507 if (u==at_Si && is_zero(imf)){
3508 r=_Si(ref,contextptr); return;
3509 }
3510 if (u==at_Ei && is_zero(imf)){
3511 r=_Ei(ref,contextptr); return;
3512 }
3513 if (u==at_Ci && is_zero(imf) && is_greater(ref,0,contextptr)){
3514 r=_Ci(ref,contextptr); return;
3515 }
3516 if (u==at_erf){ // works for analytic functions
3517 gen conjf=symbolic(u,ref-cst_i*imf);
3518 r=(s+conjf)/2;
3519 i=-cst_i*(s-conjf)/2;
3520 return;
3521 }
3522 r=new_ref_symbolic(symbolic(at_re,gen(s)));
3523 i=new_ref_symbolic(symbolic(at_im,gen(s)));
3524 }
3525
reim_poly(const polynome & p,gen & r,gen & i,GIAC_CONTEXT)3526 static void reim_poly(const polynome & p,gen & r,gen & i,GIAC_CONTEXT){
3527 polynome R(p.dim),I(p.dim);
3528 vector< monomial<gen> >::const_iterator it=p.coord.begin(),itend=p.coord.end();
3529 for (;it!=itend;++it){
3530 reim(it->value,r,i,contextptr);
3531 if (!is_zero(r,contextptr))
3532 R.coord.push_back(monomial<gen>(r,it->index));
3533 if (!is_zero(i,contextptr))
3534 I.coord.push_back(monomial<gen>(i,it->index));
3535 }
3536 r=R;
3537 i=I;
3538 }
3539
reim_vect(const vecteur & v,gen & r,gen & i,int subtype,GIAC_CONTEXT)3540 static void reim_vect(const vecteur & v,gen & r,gen & i,int subtype,GIAC_CONTEXT){
3541 const_iterateur it=v.begin(),itend=v.end();
3542 vecteur R,I;
3543 R.reserve(itend-it);
3544 I.reserve(itend-it);
3545 for (;it!=itend;++it){
3546 reim(*it,r,i,contextptr);
3547 R.push_back(r);
3548 I.push_back(i);
3549 }
3550 if (subtype==_POLY1__VECT){
3551 R=trim(R,0);
3552 I=trim(I,0);
3553 }
3554 r=gen(R,subtype);
3555 i=gen(I,subtype);
3556 }
3557
reim_spol(const sparse_poly1 & p,gen & r,gen & i,GIAC_CONTEXT)3558 static void reim_spol(const sparse_poly1 & p,gen & r,gen & i,GIAC_CONTEXT){
3559 sparse_poly1 R,I;
3560 sparse_poly1::const_iterator it=p.begin(),itend=p.end();
3561 for (;it!=itend;++it){
3562 reim(it->coeff,r,i,contextptr);
3563 if (!is_zero(r,contextptr))
3564 R.push_back(monome(r,it->exponent));
3565 if (!is_zero(i,contextptr))
3566 I.push_back(monome(i,it->exponent));
3567 }
3568 r=R;
3569 i=I;
3570 }
3571
frac_reim(const gen & n,const gen & d,bool findre,GIAC_CONTEXT)3572 static gen frac_reim(const gen & n,const gen & d,bool findre,GIAC_CONTEXT){
3573 gen dbar(conj(d,contextptr)),tmp(n*dbar);
3574 tmp=findre?re(tmp,contextptr):im(tmp,contextptr);
3575 return tmp/(d*dbar);
3576 }
3577
3578 // compute simultaneously real and imaginary part
reim(const gen & g,gen & r,gen & i,GIAC_CONTEXT)3579 void reim(const gen & g,gen & r,gen & i,GIAC_CONTEXT){
3580 switch (g.type ) {
3581 case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL: case _STRNG:
3582 r=g;
3583 i=0;
3584 break;
3585 case _CPLX:
3586 r=*g._CPLXptr;
3587 i=*(g._CPLXptr+1);
3588 break;
3589 case _VECT:
3590 reim_vect(*g._VECTptr,r,i,g.subtype,contextptr);
3591 break;
3592 case _IDNT:
3593 if (is_assumed_real(g,contextptr)){
3594 r=g;
3595 i=0;
3596 }
3597 else {
3598 r=new_ref_symbolic(symbolic(at_re,g));
3599 i=new_ref_symbolic(symbolic(at_im,g));
3600 }
3601 break;
3602 case _SYMB:
3603 if (equalposcomp(plot_sommets,g._SYMBptr->sommet)){
3604 reim(g._SYMBptr->feuille,r,i,contextptr);
3605 r=new_ref_symbolic(symbolic(g._SYMBptr->sommet,r));
3606 i=new_ref_symbolic(symbolic(g._SYMBptr->sommet,i));
3607 }
3608 else {
3609 if (expand_re_im(contextptr))
3610 symb_reim(*g._SYMBptr,r,i,contextptr);
3611 else {
3612 r=new_ref_symbolic(symbolic(at_re,g));
3613 i=new_ref_symbolic(symbolic(at_im,g));
3614 }
3615 }
3616 break;
3617 case _USER:
3618 r=g._USERptr->re(contextptr);
3619 i=g._USERptr->im(contextptr);
3620 break;
3621 case _FRAC:
3622 r=frac_reim(g._FRACptr->num,g._FRACptr->den,true,contextptr);
3623 i=frac_reim(g._FRACptr->num,g._FRACptr->den,false,contextptr);
3624 break;
3625 case _MOD:
3626 reim(*g._MODptr,r,i,contextptr);
3627 r=makemod(r,*(g._MODptr+1));
3628 i=makemod(i,*(g._MODptr+1));
3629 break;
3630 case _EXT:
3631 reim(*g._EXTptr,r,i,contextptr);
3632 r=algebraic_EXTension(r,*(g._EXTptr+1));
3633 i=algebraic_EXTension(i,*(g._EXTptr+1));
3634 break;
3635 case _POLY:
3636 reim_poly(*g._POLYptr,r,i,contextptr);
3637 break;
3638 case _SPOL1:
3639 reim_spol(*g._SPOL1ptr,r,i,contextptr);
3640 break;
3641 default:
3642 r=gentypeerr(gettext("reim"));
3643 i=r;
3644 }
3645 }
3646
symb_re(const symbolic & s,GIAC_CONTEXT)3647 static gen symb_re(const symbolic & s,GIAC_CONTEXT){
3648 unary_function_ptr u=s.sommet;
3649 gen f=s.feuille;
3650 if ( (u==at_re) || (u==at_im) || (u==at_abs) )// re(re), re(im), re(abs)
3651 return s;
3652 if (u==at_conj)
3653 return re(f,contextptr);
3654 if (u==at_plus)
3655 return _plus(re(f,contextptr),contextptr);
3656 if (u==at_neg)
3657 return -re(f,contextptr);
3658 if (u==at_pow){
3659 gen e=f._VECTptr->front(),expo=f._VECTptr->back();
3660 if (expo.type==_INT_){
3661 int n=expo.val;
3662 if (n==0)
3663 return plus_one;
3664 // ? compute conj and use 1/2*(z+-zbar)?
3665 gen r=re(e,contextptr);
3666 if (n==1)
3667 return r;
3668 gen i=im(e,contextptr);
3669 if (n==2)
3670 return pow(r,2)-pow(i,2);
3671 if (is_zero(i,contextptr))
3672 return pow(r,n);
3673 if (is_zero(r,contextptr)){
3674 if (n%2)
3675 return zero;
3676 if (n%4==2)
3677 return -pow(i,n);
3678 else
3679 return pow(i,n);
3680 }
3681 bool n_pos=(n>0);
3682 if (!n_pos)
3683 return re(inv(pow(e,-n),contextptr),contextptr);
3684 vecteur v=pascal_nth_line(n);
3685 vecteur somme;
3686 gen signe=plus_one;
3687 const_iterateur it=v.begin(); //,itend=v.end();
3688 for (int j=0;j<=n;j+=2){
3689 somme.push_back(signe*(*it)*pow(r,n-j)*pow(i,j));
3690 ++it;
3691 ++it;
3692 signe=-signe;
3693 }
3694 gen res=new_ref_symbolic(symbolic(at_plus,somme));
3695 return res;
3696 } // end integer exponent
3697 if ( is_zero(im(expo,contextptr),contextptr) && is_zero(im(e,contextptr),contextptr) ){
3698 gen sgn=atan_tan_no_floor(contextptr)?1:sign(e,contextptr); // workaround for int(sqrt(x+sqrt(x)))
3699 if (!is_integer(expo)){
3700 if (sgn==-1)
3701 return pow(-e,expo,contextptr)*cos(cst_pi*expo,contextptr);
3702 if (sgn!=1)
3703 return symbolic(at_re,s);
3704 }
3705 return s;
3706 }
3707 }
3708 if (u==at_ln) // FIXME?? might recurse
3709 return ln(abs(f,contextptr),contextptr);
3710 gen r,i;
3711 symb_reim(s,r,i,contextptr);
3712 return r;
3713 }
3714
no_context_re(const gen & a)3715 gen no_context_re(const gen & a){
3716 return re(a,context0);
3717 }
3718
no_context_im(const gen & a)3719 gen no_context_im(const gen & a){
3720 return im(a,context0);
3721 }
3722
no_context_conj(const gen & a)3723 gen no_context_conj(const gen & a){
3724 return conj(a,context0);
3725 }
3726
re(GIAC_CONTEXT) const3727 gen gen::re(GIAC_CONTEXT) const {
3728 switch (type ) {
3729 case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL: case _STRNG:
3730 return *this;
3731 case _CPLX:
3732 return *_CPLXptr;
3733 case _VECT:
3734 return gen(subtype==_POLY1__VECT?trim(_VECTre(*_VECTptr,contextptr),0):_VECTre(*_VECTptr,contextptr),subtype);
3735 case _MAP:
3736 return apply(*this,giac_re,contextptr);
3737 case _IDNT:
3738 if (is_assumed_real(*this,contextptr))
3739 return *this;
3740 if ( (_IDNTptr->value) && (is_zero(_IDNTptr->value->im(contextptr),contextptr)) )
3741 return *this;
3742 return new_ref_symbolic(symbolic(at_re,*this));
3743 case _SYMB:
3744 if (equalposcomp(plot_sommets,_SYMBptr->sommet))
3745 return new_ref_symbolic(symbolic(_SYMBptr->sommet,_SYMBptr->feuille.re(contextptr)));
3746 if (expand_re_im(contextptr))
3747 return symb_re(*_SYMBptr,contextptr);
3748 else
3749 return new_ref_symbolic(symbolic(at_re,*this));
3750 case _USER:
3751 return _USERptr->re(contextptr);
3752 case _FRAC:
3753 return frac_reim(_FRACptr->num,_FRACptr->den,true,contextptr);
3754 case _MOD:
3755 return makemod(_MODptr->re(contextptr),*(_MODptr+1));
3756 case _EXT:
3757 return algebraic_EXTension(_EXTptr->re(contextptr),*(_EXTptr+1));
3758 case _POLY:
3759 return apply(*_POLYptr,contextptr,giac_re);
3760 default:
3761 return gentypeerr(gettext("Re"));
3762 }
3763 return 0;
3764 }
3765
_VECTim(const vecteur & a,GIAC_CONTEXT)3766 static vecteur _VECTim(const vecteur & a,GIAC_CONTEXT){
3767 vecteur res;
3768 vecteur::const_iterator it=a.begin(),itend=a.end();
3769 for (;it!=itend;++it)
3770 res.push_back(it->im(contextptr));
3771 return res;
3772 }
3773
symb_im(const symbolic & s,GIAC_CONTEXT)3774 static gen symb_im(const symbolic & s,GIAC_CONTEXT){
3775 unary_function_ptr u=s.sommet;
3776 gen f=s.feuille;
3777 if ( (u==at_re) || (u==at_im) || (u==at_abs) )// im of a real
3778 return zero;
3779 if (u==at_conj)
3780 return -im(f,contextptr);
3781 if (u==at_plus)
3782 return _plus(im(f,contextptr),contextptr);
3783 if (u==at_neg)
3784 return -im(f,contextptr);
3785 if (u==at_pow){
3786 gen e=f._VECTptr->front(),expo=f._VECTptr->back();
3787 if (expo.type==_INT_) {
3788 // ? compute conj and use 1/2*(z+-zbar)?
3789 gen r=re(e,contextptr);
3790 gen i=im(e,contextptr);
3791 int n=f._VECTptr->back().val;
3792 if (n==0)
3793 return zero;
3794 if (is_zero(i,contextptr))
3795 return zero;
3796 if (is_zero(r,contextptr)){
3797 if (n%2==0)
3798 return zero;
3799 if (n%4==1)
3800 return pow(i,n);
3801 else
3802 return -pow(i,n);
3803 }
3804 bool n_pos=(n>0);
3805 if (!n_pos)
3806 return im(inv(pow(e,-n),contextptr),contextptr);
3807 vecteur v=pascal_nth_line(n);
3808 vecteur somme;
3809 gen signe=plus_one;
3810 const_iterateur it=v.begin(); // ,itend=v.end();
3811 ++it;
3812 for (int j=1;j<=n;j+=2){
3813 somme.push_back(signe*(*it)*pow(r,n-j)*pow(i,j));
3814 ++it;
3815 ++it;
3816 signe=-signe;
3817 }
3818 gen res=new_ref_symbolic(symbolic(at_plus,somme));
3819 return res;
3820 } // end integer exponent
3821 if ( is_zero(im(expo,contextptr),contextptr) && is_zero(im(e,contextptr),contextptr) ){
3822 // e must also be positive for non-integral power
3823 if (!is_integer(expo)){
3824 gen sgn=atan_tan_no_floor(contextptr)?1:sign(e,contextptr); // workaround for int(sqrt(x+sqrt(x)))
3825 if (sgn==-1)
3826 return pow(-e,expo,contextptr)*sin(cst_pi*expo,contextptr);
3827 if (sgn!=1)
3828 return symbolic(at_im,s);
3829 }
3830 return zero;
3831 }
3832 }
3833 if (u==at_ln)
3834 return arg(f,contextptr);
3835 gen r,i;
3836 symb_reim(s,r,i,contextptr);
3837 return i;
3838 }
3839
im(GIAC_CONTEXT) const3840 gen gen::im(GIAC_CONTEXT) const {
3841 switch (type) {
3842 case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL: case _STRNG:
3843 return 0;
3844 case _CPLX:
3845 return *(_CPLXptr+1);
3846 case _VECT:
3847 return gen(subtype==_POLY1__VECT?trim(_VECTim(*_VECTptr,contextptr),0):_VECTim(*_VECTptr,contextptr),subtype);
3848 case _MAP:
3849 return apply(*this,giac_im,contextptr);
3850 case _IDNT:
3851 if (is_inf(*this) || is_undef(*this))
3852 return undef;
3853 if (is_assumed_real(*this,contextptr))
3854 return zero;
3855 if ( (_IDNTptr->value) && (is_zero(_IDNTptr->value->im(contextptr),contextptr)) )
3856 return zero;
3857 return new_ref_symbolic(symbolic(at_im,*this));
3858 case _SYMB:
3859 if (equalposcomp(plot_sommets,_SYMBptr->sommet))
3860 return new_ref_symbolic(symbolic(_SYMBptr->sommet,_SYMBptr->feuille.im(contextptr)));
3861 if (expand_re_im(contextptr))
3862 return symb_im(*_SYMBptr,contextptr);
3863 else
3864 return new_ref_symbolic(symbolic(at_im,*this));
3865 case _USER:
3866 return _USERptr->im(contextptr);
3867 case _FRAC:
3868 return frac_reim(_FRACptr->num,_FRACptr->den,false,contextptr);
3869 case _MOD:
3870 return makemod(_MODptr->im(contextptr),*(_MODptr+1));
3871 case _EXT:
3872 return algebraic_EXTension(_EXTptr->im(contextptr),*(_EXTptr+1));
3873 case _POLY:
3874 return apply(*_POLYptr,contextptr,giac_im);
3875 default:
3876 return gentypeerr(gettext("Im"));
3877 }
3878 return 0;
3879 }
3880
_VECTabs(const vecteur & a,GIAC_CONTEXT)3881 static gen _VECTabs(const vecteur & a,GIAC_CONTEXT){
3882 gen res(0);
3883 vecteur::const_iterator it=a.begin(), itend=a.end();
3884 for (;it!=itend;++it){
3885 res=max(res,abs(*it,contextptr),contextptr);
3886 }
3887 return res;
3888 }
3889
real_abs(const gen & s,GIAC_CONTEXT)3890 static gen real_abs(const gen & s,GIAC_CONTEXT){
3891 gen tmp=evalf_double(s,1,contextptr);
3892 if (tmp.type==_DOUBLE_){
3893 if (tmp._DOUBLE_val>epsilon(contextptr))
3894 return s;
3895 if (tmp._DOUBLE_val<-epsilon(contextptr))
3896 return -s;
3897 if (has_num_coeff(s))
3898 return 0.0;
3899 else {
3900 #ifdef HAVE_LIBMPFR
3901 tmp=accurate_evalf(s,ABS_NBITS_EVALF+10)*pow(2,ABS_NBITS_EVALF,contextptr);
3902 if (!is_greater(1,abs(tmp,contextptr),contextptr)){
3903 if (is_positive(tmp,contextptr))
3904 return s;
3905 return -s;
3906 }
3907 #else
3908 return 0;
3909 #endif
3910 }
3911 }
3912 if (tmp.type==_FLOAT_){
3913 if (tmp._FLOAT_val>epsilon(contextptr))
3914 return s;
3915 if (tmp._FLOAT_val<-epsilon(contextptr))
3916 return -s;
3917 return 0.0;
3918 }
3919 int j=sturmsign(s,false,contextptr);
3920 if (!j || j==-2)
3921 return new_ref_symbolic(symbolic(at_abs,gen(s)));
3922 return j*s;
3923 }
3924
idnt_abs(const gen & s,GIAC_CONTEXT)3925 static gen idnt_abs(const gen & s,GIAC_CONTEXT){
3926 if (is_inf(s))
3927 return plus_inf;
3928 if (is_undef(s))
3929 return s;
3930 if (!eval_abs(contextptr) || has_num_coeff(s))
3931 return new_ref_symbolic(symbolic(at_abs,s));
3932 gen r,i;
3933 reim(s,r,i,contextptr);
3934 if (is_zero(i,contextptr))
3935 return real_abs(s,contextptr);
3936 else {
3937 if (i.type==_SYMB && i._SYMBptr->sommet==at_im && !lop(r,at_re).empty())
3938 return new_ref_symbolic(symbolic(at_abs,s));
3939 gen r2i2=pow(r,2)+pow(i,2);
3940 if (has_op(r2i2,*at_cos) || has_op(r2i2,*at_sin)){
3941 r2i2=_tlin(r2i2,contextptr); // _tcollect?
3942 vecteur l=lvar(r2i2);
3943 unsigned count=0;
3944 for (unsigned i=0;i<l.size();++i){
3945 if (l[i].is_symb_of_sommet(at_sin) || l[i].is_symb_of_sommet(at_cos))
3946 ++count;
3947 }
3948 if (count>=2)
3949 r2i2=_tcollect(r2i2,contextptr);
3950 }
3951 return sqrt(r2i2,contextptr);
3952 }
3953 }
3954
symb_abs(const symbolic & s,GIAC_CONTEXT)3955 static gen symb_abs(const symbolic & s,GIAC_CONTEXT){
3956 unary_function_ptr u=s.sommet;
3957 gen f=s.feuille;
3958 if (u==at_abs) // abs(abs)
3959 return s;
3960 if (u==at_neg)
3961 return abs(f,contextptr);
3962 if (!complex_mode(contextptr)){
3963 if (u==at_ln)
3964 return real_abs(s,contextptr);
3965 if (!has_i(s)){
3966 if (u==at_exp || ( (u==at_sqrt && is_positive(f,contextptr)) || (u==at_pow && f[1]==plus_one_half && is_positive(f[0],contextptr)) ) )
3967 return s;
3968 // if (calc_mode(contextptr)==1 && u==at_pow && f.type==_VECT && f._VECTptr->size()==2 && f._VECTptr->back()==plus_one_half && is_positive(f[0],contextptr)) return s;
3969 }
3970 }
3971 else {
3972 if (do_lnabs(contextptr) && u==at_ln)
3973 return new_ref_symbolic(symbolic(at_abs,s));
3974 if (u==at_exp)
3975 return exp(re(f,contextptr),contextptr);
3976 }
3977 if ( (u==at_pow) && (is_zero(im(f._VECTptr->back(),contextptr),contextptr))){
3978 gen fback=f._VECTptr->back();
3979 if (fback.type==_INT_ && (fback.val % 2==0))
3980 return pow(abs(f._VECTptr->front(),contextptr),fback,contextptr);
3981 return new_ref_symbolic(symbolic(u,makesequence(abs(f._VECTptr->front(),contextptr),f._VECTptr->back())));
3982 }
3983 if (u==at_inv)
3984 return inv(abs(f,contextptr),contextptr);
3985 if (u==at_prod)
3986 return new_ref_symbolic(symbolic(u,apply(f,contextptr,abs)));
3987 return idnt_abs(s,contextptr);
3988 }
3989
abs(const gen & a,GIAC_CONTEXT)3990 gen abs(const gen & a,GIAC_CONTEXT){
3991 switch (a.type ) {
3992 case _INT_:
3993 return(absint(a.val));
3994 case _ZINT:
3995 if (mpz_sgn(*a._ZINTptr)<0)
3996 return(-a);
3997 else
3998 return(a);
3999 case _REAL:
4000 return a._REALptr->abs();
4001 case _CPLX:
4002 #ifdef GIAC_HAS_STO_38
4003 {
4004 if (a._CPLXptr->type==_FLOAT_ && (a._CPLXptr+1)->type==_FLOAT_)
4005 {
4006 HP_gen r;
4007 cAbs_g(gen2HP(*a._CPLXptr), gen2HP(*(a._CPLXptr+1)), &r);
4008 return HP2gen(r);
4009 }
4010 return sqrt(sq(*a._CPLXptr)+sq(*(a._CPLXptr+1)),contextptr) ;
4011 }
4012 #else
4013 if (a.subtype==3){
4014 gen * aptr=a._CPLXptr;
4015 double ar=aptr->_DOUBLE_val,ai=(aptr+1)->_DOUBLE_val;
4016 return gen(std::sqrt(ar*ar+ai*ai));
4017 }
4018 return sqrt(sq(*a._CPLXptr)+sq(*(a._CPLXptr+1)),contextptr) ;
4019 #endif
4020 case _DOUBLE_:
4021 return fabs(a._DOUBLE_val);
4022 case _FLOAT_:
4023 return fabs(a._FLOAT_val);
4024 case _VECT:
4025 if (a.subtype==_POINT__VECT || a.subtype==_GGBVECT)
4026 return _l2norm(a,contextptr);
4027 return _VECTabs(*a._VECTptr,contextptr);
4028 case _IDNT:
4029 return idnt_abs(a,contextptr);
4030 case _SYMB:
4031 if (is_equal(a))
4032 return apply_to_equal(a,abs,contextptr);
4033 if (a.is_symb_of_sommet(at_pnt)){
4034 if (is3d(a))
4035 return _l2norm(_coordonnees(a,contextptr),contextptr);
4036 return abs(_affixe(a,contextptr),contextptr);
4037 }
4038 return symb_abs(*a._SYMBptr,contextptr);
4039 case _USER:
4040 return a._USERptr->abs(contextptr);
4041 case _FRAC:
4042 if (is_integer(a._FRACptr->num) && is_integer(a._FRACptr->den))
4043 return fraction(abs(a._FRACptr->num,contextptr),abs(a._FRACptr->den,contextptr));
4044 return rdiv(abs(a._FRACptr->num,contextptr),abs(a._FRACptr->den,contextptr),contextptr);
4045 default:
4046 return gentypeerr(gettext("Abs"));
4047 }
4048 return 0;
4049 }
4050
linfnorm(const gen & a,GIAC_CONTEXT)4051 gen linfnorm(const gen & a,GIAC_CONTEXT){ // L^inf norm is |re|+|im| for a complex
4052 switch (a.type ) {
4053 case _INT_:
4054 return(absint(a.val));
4055 case _ZINT:
4056 if (mpz_sgn(*a._ZINTptr)<0)
4057 return(-a);
4058 else
4059 return(a);
4060 case _CPLX:
4061 return(abs(*a._CPLXptr,contextptr)+abs(*(a._CPLXptr+1),contextptr)) ;
4062 case _DOUBLE_:
4063 return fabs(a._DOUBLE_val);
4064 case _FLOAT_:
4065 return fabs(a._FLOAT_val);
4066 case _FRAC:
4067 return linfnorm(a._FRACptr->num)/linfnorm(a._FRACptr->den);
4068 case _VECT:
4069 return _VECTabs(*a._VECTptr,contextptr);
4070 case _USER:
4071 return a._USERptr->abs(contextptr);
4072 case _IDNT: case _SYMB:
4073 return new_ref_symbolic(symbolic(at_abs,a));
4074 default:
4075 return gentypeerr(gettext("Linfnorm"));
4076 }
4077 return 0;
4078 }
4079
4080 // workaround for intervals
is_zero_or_contains(const gen & g,GIAC_CONTEXT)4081 static bool is_zero_or_contains(const gen & g,GIAC_CONTEXT){
4082 #ifdef NO_RTTI
4083 return is_zero(g,contextptr);
4084 #else
4085 if (is_zero(g,contextptr))
4086 return true;
4087 if (g.type!=_REAL)
4088 return false;
4089 if (real_interval * ptr=dynamic_cast<real_interval *>(g._REALptr))
4090 return ptr->maybe_zero();
4091 return false;
4092 #endif
4093 }
4094
arg_CPLX(const gen & a,GIAC_CONTEXT)4095 gen arg_CPLX(const gen & a,GIAC_CONTEXT){
4096 gen realpart=normal(a.re(contextptr),contextptr),
4097 imagpart=normal(a.im(contextptr),contextptr);
4098 if (realpart.type==_FLOAT_ && imagpart.type==_FLOAT_){
4099 #ifdef GIAC_HAS_STO_38
4100 //grad
4101 return atan2f(realpart._FLOAT_val,imagpart._FLOAT_val,angle_mode(contextptr));
4102 #else
4103 return atan2f(realpart._FLOAT_val,imagpart._FLOAT_val,angle_radian(contextptr));
4104 #endif
4105 }
4106 if (is_zero_or_contains(realpart,contextptr)){
4107 if (is_zero_or_contains(imagpart,contextptr))
4108 return undef;
4109 return (cst_pi_over_2-atan(realpart/imagpart,contextptr))*sign(imagpart,contextptr);
4110 }
4111 if (is_zero_or_contains(imagpart,contextptr))
4112 return (1-sign(realpart,contextptr))*cst_pi_over_2+atan(imagpart/realpart,contextptr);
4113 if ( (realpart.type==_DOUBLE_ || realpart.type==_FLOAT_) || (imagpart.type==_DOUBLE_ || imagpart.type==_FLOAT_) )
4114 return eval(atan(rdiv(imagpart,realpart,contextptr),contextptr)+(1-sign(realpart,contextptr))*sign(imagpart,contextptr)*evalf_double(cst_pi_over_2,1,contextptr),1,contextptr);
4115 else
4116 return atan(rdiv(imagpart,realpart,contextptr),contextptr)+(1-sign(realpart,contextptr))*sign(imagpart,contextptr)*cst_pi_over_2;
4117 }
4118
_VECTarg(const vecteur & a,GIAC_CONTEXT)4119 static gen _VECTarg(const vecteur & a,GIAC_CONTEXT){
4120 vecteur res;
4121 vecteur::const_iterator it=a.begin(), itend=a.end();
4122 for (;it!=itend;++it){
4123 res.push_back(arg(*it,contextptr));
4124 }
4125 return res;
4126 }
4127
arg(const gen & a,GIAC_CONTEXT)4128 gen arg(const gen & a,GIAC_CONTEXT){
4129 if (a.type==_CPLX && a._CPLXptr->type==_DOUBLE_ && (a._CPLXptr+1)->type==_DOUBLE_)
4130 return atan2((a._CPLXptr+1)->_DOUBLE_val,a._CPLXptr->_DOUBLE_val);
4131 if (!angle_radian(contextptr)){
4132 //grad
4133 int mode = get_mode_set_radian(contextptr); //get current mode
4134 gen res=evalf(arg(a,contextptr),1,contextptr);
4135 angle_mode(mode,contextptr); //set back to either degree or grads
4136 if(mode == 1) //if was in degrees
4137 return 180*res/cst_pi;
4138 else
4139 return 200 * res / cst_pi;
4140 }
4141 if (a.is_symb_of_sommet(at_pow)){
4142 gen af=a._SYMBptr->feuille;
4143 if (af.type==_VECT && af._VECTptr->size()==2){
4144 gen res=im(ln(af._VECTptr->front(),contextptr)*af._VECTptr->back(),contextptr);
4145 return _smod(makesequence(res,cst_two_pi),contextptr);
4146 }
4147 }
4148 if (a.is_symb_of_sommet(at_exp))
4149 return _smod(makesequence(im(a._SYMBptr->feuille,contextptr),cst_two_pi),contextptr);
4150 if (a.is_symb_of_sommet(at_prod)){
4151 const gen & af=a._SYMBptr->feuille;
4152 if (af.type==_VECT){
4153 const_iterateur it=af._VECTptr->begin(),itend=af._VECTptr->end();
4154 gen res;
4155 int nonzero=0;
4156 for (;it!=itend;++it){
4157 gen tmp(arg(*it,contextptr));
4158 if (!is_zero(tmp,contextptr)){
4159 res += tmp;
4160 ++nonzero;
4161 }
4162 }
4163 if (nonzero>1)
4164 return _smod(makesequence(res,cst_two_pi),contextptr);
4165 return res;
4166 }
4167 }
4168 if (is_equal(a))
4169 return apply_to_equal(a,arg,contextptr);
4170 switch (a.type ) {
4171 case _INT_: case _ZINT: case _FLOAT_: case _REAL:
4172 if (is_positive(a,contextptr))
4173 return 0;
4174 else
4175 return cst_pi;
4176 case _DOUBLE_:
4177 return a._DOUBLE_val>=0?0.0:M_PI;
4178 case _CPLX:
4179 return arg_CPLX(a,contextptr);
4180 case _VECT:
4181 return _VECTarg(*a._VECTptr,contextptr);
4182 case _IDNT:
4183 case _SYMB:
4184 // if ( is_zero(im(a,contextptr),contextptr) || (evalf(a,eval_level(contextptr),contextptr).type==_CPLX) )
4185 return arg_CPLX(a,contextptr);
4186 // return new symbolic(at_arg,a);
4187 case _USER:
4188 return a._USERptr->arg(contextptr);
4189 case _FRAC:
4190 return arg(a._FRACptr->num*conj(a._FRACptr->den,contextptr),contextptr);
4191 default:
4192 return gentypeerr(gettext("Arg"));
4193 }
4194 return 0;
4195 }
4196
squarenorm(GIAC_CONTEXT) const4197 gen gen::squarenorm(GIAC_CONTEXT) const {
4198 switch (type ) {
4199 case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL:
4200 return (*this) * (*this);
4201 case _CPLX:
4202 return ( (*_CPLXptr)*(*_CPLXptr)+(*(_CPLXptr+1)*(*(_CPLXptr+1))) );
4203 case _FRAC:
4204 return fraction(_FRACptr->num.squarenorm(contextptr),_FRACptr->den.squarenorm(contextptr));
4205 default:
4206 {
4207 gen a,b;
4208 reim(*this,a,b,contextptr);
4209 return a*a+b*b;
4210 }
4211 }
4212 }
4213
sq(const gen & a)4214 gen sq(const gen & a){
4215 return a*a;
4216 }
4217
bindigits() const4218 int gen::bindigits() const{
4219 int res,valeur;
4220 switch (type ) {
4221 case _INT_:
4222 res=0;
4223 valeur=val;
4224 for (;valeur;res++)
4225 valeur = valeur >> 1;
4226 return res;
4227 case _ZINT:
4228 return mpz_sizeinbase(*_ZINTptr,2)+1;
4229 case _CPLX:
4230 return giacmax(_CPLXptr->bindigits(),(_CPLXptr+1)->bindigits() ) ;
4231 default:
4232 #ifndef NO_STDEXCEPT
4233 settypeerr(gettext("Bindigits"));
4234 #endif
4235 return 0;
4236 }
4237 return 0;
4238 }
4239
addpoly(const gen & th,const gen & other)4240 static gen addpoly(const gen & th, const gen & other){
4241 if ((th.type!=_POLY) || (other.type!=_POLY)){
4242 #ifndef NO_STDEXCEPT
4243 settypeerr(gettext("addpoly"));
4244 #endif
4245 return gentypeerr(gettext("addpoly"));
4246 }
4247 // Tensor addition
4248 vector< monomial<gen> >::const_iterator a=th._POLYptr->coord.begin();
4249 vector< monomial<gen> >::const_iterator a_end=th._POLYptr->coord.end();
4250 if (a == a_end) {
4251 return other;
4252 }
4253 vector< monomial<gen> >::const_iterator b=other._POLYptr->coord.begin();
4254 vector< monomial<gen> >::const_iterator b_end=other._POLYptr->coord.end();
4255 if (b==b_end){
4256 return th;
4257 }
4258 ref_polynome * resptr=new ref_polynome(th._POLYptr->dim);
4259 Add_gen(a,a_end,b,b_end,resptr->t.coord,th._POLYptr->is_strictly_greater);
4260 return resptr;
4261 }
4262
addpoly(const polynome & p,const gen & c)4263 polynome addpoly(const polynome & p,const gen & c){
4264 if (is_exactly_zero(c))
4265 return p;
4266 polynome pcopy(p);
4267 if ( (!p.coord.empty()) && p.coord.back().index.is_zero() ) {
4268 pcopy.coord.back().value = pcopy.coord.back().value + c;
4269 if (is_exactly_zero(pcopy.coord.back().value))
4270 pcopy.coord.pop_back();
4271 }
4272 else
4273 pcopy.coord.push_back(monomial<gen>(c,pcopy.dim));
4274 return pcopy;
4275 }
4276
chkmod(const gen & a,const gen & b)4277 gen chkmod(const gen& a,const gen & b){
4278 if ( (b.type!=_MOD) || ((a.type==_MOD) && (*(a._MODptr+1)==*(b._MODptr+1)) ))
4279 return a;
4280 return makemodquoted(a,*(b._MODptr+1));
4281 }
makemod(const gen & a,const gen & b)4282 gen makemod(const gen & a,const gen & b){
4283 if (a.type==_VECT)
4284 return apply1st(a,b,makemod);
4285 if (a.type==_POLY){
4286 polynome res(a._POLYptr->dim);
4287 vector< monomial<gen> >::const_iterator it=a._POLYptr->coord.begin(),itend=a._POLYptr->coord.end();
4288 res.coord.reserve(itend-it);
4289 for (;it!=itend;++it){
4290 gen tmp=makemod(it->value,b);
4291 if (!is_exactly_zero(tmp))
4292 res.coord.push_back(monomial<gen>(tmp,it->index));
4293 }
4294 return res;
4295 }
4296 if (a.type==_MOD){
4297 if (is_exactly_zero(b)) // unmodularize
4298 return *a._MODptr;
4299 if (*(a._MODptr+1)==b) // avoid e.g. 7 % 5 % 5
4300 return a;
4301 }
4302 if (a.type==_USER)
4303 return a;
4304 if (is_exactly_zero(b))
4305 return a;
4306 if (a.type==_DOUBLE_ || a.type==_REAL || a.type==_FLOAT_)
4307 return gensizeerr(context0);
4308 gen res=makemodquoted(0,0);
4309 if ( (b.type==_INT_) || (b.type==_ZINT) )
4310 *res._MODptr=smod(a,b);
4311 else {
4312 if (b.type!=_VECT){
4313 res=0;
4314 #ifdef NO_STDEXCEPT
4315 return gensizeerr(gettext("Bad mod:")+b.print(context0));
4316 #else
4317 setsizeerr(gettext("Bad mod:")+b.print(context0));
4318 #endif
4319 }
4320 if (a.type==_VECT)
4321 *res._MODptr=(*a._VECTptr)%(*b._VECTptr);
4322 else
4323 *res._MODptr=a;
4324 }
4325 *(res._MODptr+1)=b;
4326 return res;
4327 }
4328
makemodquoted(const gen & a,const gen & b)4329 gen makemodquoted(const gen & a,const gen & b){
4330 gen res;
4331 #ifdef SMARTPTR64
4332 * ((ulonglong * ) &res) = ulonglong(new ref_modulo(a,b)) << 16;
4333 #else
4334 res.__MODptr=new ref_modulo(a,b);
4335 #endif
4336 res.type=_MOD;
4337 return res;
4338 }
4339
modadd(const ref_modulo * a,const ref_modulo * b)4340 static gen modadd(const ref_modulo * a,const ref_modulo *b){
4341 if (a->modulo!=b->modulo){
4342 #ifndef NO_STDEXCEPT
4343 setsizeerr(gettext("Mod are different"));
4344 #endif
4345 }
4346 return makemod(a->n+b->n,a->modulo);
4347 }
4348
modsub(const ref_modulo * a,const ref_modulo * b)4349 static gen modsub(const ref_modulo * a,const ref_modulo *b){
4350 #ifndef NO_STDEXCEPT
4351 if (a->modulo!=b->modulo)
4352 setsizeerr(gettext("Mod are different"));
4353 #endif
4354 return makemod(a->n-b->n,a->modulo);
4355 }
4356
modmul(const ref_modulo * a,const ref_modulo * b)4357 static gen modmul(const ref_modulo * a,const ref_modulo *b){
4358 #ifndef NO_STDEXCEPT
4359 if (a->modulo!=b->modulo)
4360 setsizeerr(gettext("Mod are different"));
4361 #endif
4362 return makemod(a->n*b->n,a->modulo);
4363 }
4364
modinv(const gen & a)4365 static gen modinv(const gen & a){
4366 gen modu=*(a._MODptr+1);
4367 if ( ( (modu.type==_INT_) || (modu.type==_ZINT) ) &&
4368 a._MODptr->is_cinteger() )
4369 return makemod(invmod(*a._MODptr,modu),modu);
4370 if (modu.type==_VECT){
4371 modpoly polya,u,v,d;
4372 if (a._MODptr->type!=_VECT)
4373 polya.push_back(*a._MODptr);
4374 else
4375 polya=*a._MODptr->_VECTptr;
4376 egcd(polya,*modu._VECTptr,0,u,v,d);
4377 if (d.size()!=1){
4378 #ifndef NO_STDEXCEPT
4379 setsizeerr(gettext("Not invertible"));
4380 #endif
4381 return 0;
4382 }
4383 return makemod(u/d.front(),modu);
4384 }
4385 return fraction(makemod(plus_one,*(a._MODptr+1)),a);
4386 }
4387
4388 // a and b must be dense univariate polynomials
4389 // WARNING: may modify a in place (suitable inside a += operator)
addgen_poly(const gen & a,const gen & b,bool inplace=false)4390 static gen addgen_poly(const gen & a,const gen & b,bool inplace=false){
4391 vecteur & av=*a._VECTptr;
4392 vecteur & bv=*b._VECTptr;
4393 if (inplace){
4394 /*
4395 int as=av.size(),bs=bv.size();
4396 if (as<bs)
4397 av.insert(av.begin(),bs-as,0);
4398 */
4399 gen res(a);
4400 Addmodpoly(av.begin(),av.end(),bv.begin(),bv.end(),0,av);
4401 return res;
4402 }
4403 gen res(vecteur(0), _POLY1__VECT);
4404 addmodpoly(av,bv,0,*res._VECTptr);
4405 return res._VECTptr->empty()?0:res;
4406 }
4407
operator_plus_eq(gen & a,const gen & b,GIAC_CONTEXT)4408 gen & operator_plus_eq(gen &a,const gen & b,GIAC_CONTEXT){
4409 #ifdef EMCC
4410 a=operator_plus(a,b,contextptr);
4411 return a;
4412 #endif
4413 if (a.type==b.type){
4414
4415 if (a.type==_DOUBLE_){
4416 #ifdef DOUBLEVAL
4417 a._DOUBLE_val += b._DOUBLE_val; return a;
4418 #else
4419 *((double *) &a) += *((double *) &b);
4420 a.type = _DOUBLE_;
4421 return a;
4422 #endif
4423 }
4424 if (a.type==_FLOAT_){
4425 #ifdef DOUBLEVAL
4426 a._FLOAT_val += b._FLOAT_val; return a;
4427 #else
4428 *((giac_float *) &a) += *((giac_float *) &b);
4429 a.type = _FLOAT_;
4430 return a;
4431 #endif
4432 }
4433 if (a.type==_INT_){
4434 longlong tmp=((longlong) a.val+b.val);
4435 a.val=(int)tmp;
4436 if (a.val==tmp)
4437 return a;
4438 return a=tmp;
4439 }
4440 if (a.type==_ZINT && a.ref_count()==1){
4441 mpz_t * ptr=a._ZINTptr;
4442 mpz_add(*ptr,*ptr,*b._ZINTptr);
4443 if (mpz_sizeinbase(*ptr,2)<32){
4444 return a=mpz_get_si(*ptr);
4445 }
4446 return a;
4447 }
4448 if (a.type==_VECT && a.subtype==_POLY1__VECT && a.ref_count()==1){
4449 if (addgen_poly(a,b,true)._VECTptr->empty())
4450 a=0;
4451 return a;
4452 }
4453 }
4454 if (a.type==_ZINT && b.type==_INT_ && a.ref_count()==1){
4455 mpz_t * ptr=a._ZINTptr;
4456 if (b.val<0)
4457 mpz_sub_ui(*ptr,*ptr,-b.val);
4458 else
4459 mpz_add_ui(*ptr,*ptr,b.val);
4460 if (mpz_sizeinbase(*ptr,2)<32){
4461 return a=gen(*ptr);
4462 }
4463 return a;
4464 }
4465 // if (!( (++control_c_counter) & control_c_counter_mask))
4466 #ifdef TIMEOUT
4467 control_c();
4468 #endif
4469 if (ctrl_c || interrupted) {
4470 interrupted = true; ctrl_c=false;
4471 return a=gensizeerr(gettext("Stopped by user interruption."));
4472 }
4473 return a=operator_plus(a,b,contextptr);
4474 }
4475
ck_evalf_double(const gen & g,GIAC_CONTEXT)4476 static gen ck_evalf_double(const gen & g,GIAC_CONTEXT){
4477 gen tmp=evalf_double(g,1,contextptr);
4478 if (tmp.type<=_CPLX)
4479 return tmp;
4480 return gensizeerr(contextptr);
4481 }
4482
operator_plus(const gen & a,const gen & b,unsigned t,GIAC_CONTEXT)4483 gen operator_plus(const gen & a,const gen & b,unsigned t,GIAC_CONTEXT){
4484 static bool warnextend=true;
4485 // if (!( (++control_c_counter) & control_c_counter_mask))
4486 #ifdef TIMEOUT
4487 control_c();
4488 #endif
4489 if (ctrl_c || interrupted) {
4490 interrupted = true; ctrl_c=false;
4491 return gensizeerr(gettext("Stopped by user interruption."));
4492 }
4493 register ref_mpz_t * e;
4494 switch ( t ) {
4495 case _ZINT__ZINT:
4496 e =new ref_mpz_t;
4497 mpz_add(e->z,*a._ZINTptr,*b._ZINTptr);
4498 return e;
4499 case _DOUBLE___DOUBLE_:
4500 return a._DOUBLE_val+b._DOUBLE_val;
4501 case _FLOAT___FLOAT_:
4502 return a._FLOAT_val+b._FLOAT_val;
4503 case _VECT__VECT:
4504 if (// abs_calc_mode(contextptr)==38 &&
4505 (a.subtype==_MATRIX__VECT ||b.subtype==_MATRIX__VECT)){
4506 if (!ckmatrix(a) || !ckmatrix(b))
4507 return gensizeerr(contextptr);
4508 if (a._VECTptr->size()!=b._VECTptr->size() || a._VECTptr->front()._VECTptr->size()!=b._VECTptr->front()._VECTptr->size())
4509 return gendimerr(contextptr);
4510 }
4511 if (a.subtype==_POLY1__VECT)
4512 return addgen_poly(a,b);
4513 if (a.subtype==_PNT__VECT)
4514 return gen(makenewvecteur(a._VECTptr->front()+b,a._VECTptr->back()),a.subtype);
4515 if (a.subtype!=_POINT__VECT && equalposcomp((int *) _GROUP__VECT_subtype,a.subtype))
4516 return sym_add(a,b,contextptr);
4517 if (b.subtype!=_POINT__VECT && equalposcomp((int *)_GROUP__VECT_subtype,b.subtype))
4518 return sym_add(b,a,contextptr);
4519 if (a.subtype==_POINT__VECT && b.subtype==_POINT__VECT)
4520 return gen(addvecteur(*a._VECTptr,*b._VECTptr),0);
4521 if (a.subtype==0 && b.subtype==0 && python_compat(contextptr)==2)
4522 return mergevecteur(*a._VECTptr,*b._VECTptr);
4523 if (warnextend && a.subtype==0 && b.subtype==0 && python_compat(contextptr)){
4524 warnextend=false;
4525 alert(gettext("Warning + is vector addition, run list1.extend(list2) for list concatenation"),contextptr);
4526 }
4527 return gen(addvecteur(*a._VECTptr,*b._VECTptr),a.subtype?a.subtype:b.subtype);
4528 case _MAP__MAP:
4529 {
4530 int arows,acols,an,brows,bcols,bn;
4531 if ( (is_sparse_matrix(a,arows,acols,an) && is_sparse_matrix(b,brows,bcols,bn)) || (is_sparse_vector(a,arows,an) && is_sparse_vector(b,brows,bn)) ){
4532 gen_map res;
4533 gen g(res);
4534 sparse_add(*a._MAPptr,*b._MAPptr,*g._MAPptr);
4535 return g;
4536 }
4537 }
4538 case _INT___ZINT:
4539 e = new ref_mpz_t;
4540 if (a.val<0)
4541 mpz_sub_ui(e->z,*b._ZINTptr,-a.val);
4542 else
4543 mpz_add_ui(e->z,*b._ZINTptr,a.val);
4544 return e;
4545 case _ZINT__INT_:
4546 e = new ref_mpz_t;
4547 if (b.val<0)
4548 mpz_sub_ui(e->z,*a._ZINTptr,-b.val);
4549 else
4550 mpz_add_ui(e->z,*a._ZINTptr,b.val);
4551 return e;
4552 case _DOUBLE___INT_:
4553 return a._DOUBLE_val+b.val;
4554 case _INT___DOUBLE_:
4555 return a.val+b._DOUBLE_val;
4556 case _FLOAT___DOUBLE_:
4557 return a._FLOAT_val+giac_float(b._DOUBLE_val);
4558 case _FLOAT___INT_:
4559 return a._FLOAT_val+giac_float(b.val);
4560 case _FLOAT___FRAC:
4561 return a+evalf2bcd(b,1,contextptr);
4562 case _DOUBLE___FRAC:
4563 return a+ck_evalf_double(b,contextptr);
4564 case _INT___FLOAT_:
4565 return b._FLOAT_val+giac_float(a.val);
4566 case _DOUBLE___FLOAT_:
4567 return b._FLOAT_val+giac_float(a._DOUBLE_val);
4568 case _DOUBLE___ZINT:
4569 return a._DOUBLE_val+mpz_get_d(*b._ZINTptr);
4570 case _DOUBLE___REAL:
4571 return a._DOUBLE_val+real2double(*b._REALptr);
4572 case _REAL__DOUBLE_:
4573 return b._DOUBLE_val+real2double(*a._REALptr);
4574 case _ZINT__DOUBLE_:
4575 return b._DOUBLE_val+mpz_get_d(*a._ZINTptr);
4576 case _CPLX__INT_:
4577 if (b.val==0) return a;
4578 case _CPLX__ZINT: case _CPLX__DOUBLE_: case _CPLX__FLOAT_: case _CPLX__REAL:
4579 return gen(*a._CPLXptr+b,*(a._CPLXptr+1));
4580 case _INT___CPLX:
4581 if (a.val==0) return b;
4582 case _ZINT__CPLX: case _FLOAT___CPLX: case _DOUBLE___CPLX: case _REAL__CPLX:
4583 return gen(a+*b._CPLXptr,*(b._CPLXptr+1));
4584 case _CPLX__CPLX: {
4585 gen * aptr=a._CPLXptr, *bptr=b._CPLXptr;
4586 if (aptr->type==_DOUBLE_ && (aptr+1)->type==_DOUBLE_ && bptr->type ==_DOUBLE_ && (bptr+1)->type ==_DOUBLE_)
4587 return adjust_complex_display(gen(aptr->_DOUBLE_val + bptr->_DOUBLE_val, (aptr+1)->_DOUBLE_val + (bptr+1)->_DOUBLE_val),a,b);
4588 return adjust_complex_display(gen(*aptr + *bptr, *(aptr+1) + *(bptr+1)),a,b);
4589 }
4590 case _POLY__POLY:
4591 return addpoly(a,b);
4592 case _FRAC__FRAC:
4593 return (*a._FRACptr)+(*b._FRACptr);
4594 case _FRAC__FLOAT_:
4595 return evalf2bcd(a,1,contextptr)+b;
4596 case _INT___FRAC: case _ZINT__FRAC:
4597 return a+(*b._FRACptr);
4598 case _FRAC__INT_: case _FRAC_ZINT:
4599 return (*a._FRACptr)+b;
4600 case _FRAC__DOUBLE_:
4601 return ck_evalf_double(a,contextptr)+b;
4602 case _SPOL1__SPOL1:
4603 return spadd(*a._SPOL1ptr,*b._SPOL1ptr,contextptr);
4604 case _EXT__EXT:
4605 return ext_add(a,b,contextptr);
4606 case _STRNG__STRNG:
4607 if (is_undef(a)) return a;
4608 if (is_undef(b)) return b;
4609 return string2gen('"'+(*a._STRNGptr)+(*b._STRNGptr)+'"');
4610 case _POLY__INT_: case _POLY__ZINT: case _POLY__DOUBLE_: case _POLY__FLOAT_: case _POLY__CPLX: case _POLY__MOD: case _POLY__USER: case _POLY__REAL:
4611 return addpoly(*a._POLYptr,b);
4612 case _INT___POLY: case _ZINT__POLY: case _DOUBLE___POLY: case _FLOAT___POLY: case _CPLX__POLY: case _MOD__POLY: case _USER__POLY: case _REAL__POLY:
4613 return addpoly(*b._POLYptr,a);
4614 case _MOD__MOD:
4615 #ifdef SMARTPTR64
4616 return modadd( (ref_modulo *) (* ((ulonglong * ) &a) >> 16),(ref_modulo *) (* ((ulonglong * ) &b) >> 16));
4617 #else
4618 return modadd(a.__MODptr,b.__MODptr);
4619 #endif
4620 case _REAL__REAL:
4621 return (*a._REALptr)+(*b._REALptr);
4622 case _IDNT__IDNT:
4623 if (a==unsigned_inf && b==unsigned_inf)
4624 return undef;
4625 if (b==undef)
4626 return b;
4627 if (a==undef || a==unsigned_inf)
4628 return a;
4629 if (b==unsigned_inf)
4630 return b;
4631 return new_ref_symbolic(symbolic(at_plus,makesequence(a,b)));
4632 case _VECT__MAP:
4633 {
4634 int brows,bcols,an;
4635 if (is_sparse_matrix(b,brows,bcols,an)){
4636 matrice B;
4637 if (!convert(*b._MAPptr,B))
4638 return gendimerr(contextptr);
4639 return a+B;
4640 }
4641 }
4642 case _MAP__VECT:
4643 {
4644 int arows,acols,an;
4645 if (is_sparse_matrix(a,arows,acols,an)){
4646 matrice A;
4647 if (!convert(*a._MAPptr,A))
4648 return gendimerr(contextptr);
4649 return A+b;
4650 }
4651 }
4652 default:
4653 if (a.type==_INT_ && a.val==0 && b.type!=_STRNG)
4654 return b;
4655 if (b.type==_INT_ && b.val==0 && a.type!=_STRNG)
4656 return a;
4657 if (is_undef(a))
4658 return a;
4659 if (is_undef(b))
4660 return b;
4661 if (a.type==_FLOAT_){
4662 if (is_inf(a))
4663 return a;
4664 if (b.type==_VECT)
4665 return sym_add(b,a,contextptr);
4666 gen b1;
4667 if (has_evalf(b,b1,1,contextptr) && b.type!=b1.type)
4668 return operator_plus(a,b1,contextptr);
4669 return operator_plus(evalf_double(a,1,contextptr),b,contextptr);
4670 }
4671 if (b.type==_FLOAT_){
4672 if (is_inf(b))
4673 return b;
4674 if (a.type==_VECT)
4675 return sym_add(a,b,contextptr);
4676 gen a1;
4677 if (has_evalf(a,a1,1,contextptr) && a.type!=a1.type)
4678 return operator_plus(a1,b,contextptr);
4679 return operator_plus(a,evalf_double(b,1,contextptr),contextptr);
4680 }
4681 if (a.type==_STRNG)
4682 return string2gen(*a._STRNGptr+b.print(contextptr),false);
4683 if (b.type==_STRNG)
4684 return string2gen(a.print(contextptr)+*b._STRNGptr,false);
4685 if (a.type==_SPOL1)
4686 return spadd(*a._SPOL1ptr,gen2spol1(b),contextptr);
4687 if (b.type==_SPOL1)
4688 return spadd(gen2spol1(a),*b._SPOL1ptr,contextptr);
4689 if (a.type==_USER)
4690 return (*a._USERptr)+b;
4691 if (b.type==_USER)
4692 return (*b._USERptr)+a;
4693 if (a.type==_REAL)
4694 return a._REALptr->addition(b,contextptr);
4695 if (b.type==_REAL){
4696 return b._REALptr->addition(a,contextptr);
4697 }
4698 return sym_add(a,b,contextptr);
4699 }
4700 }
4701
operator_plus(const gen & a,const gen & b,GIAC_CONTEXT)4702 gen operator_plus (const gen & a,const gen & b,GIAC_CONTEXT){
4703 register unsigned t=(a.type<< _DECALAGE) | b.type;
4704 if (!t)
4705 return((longlong) a.val+b.val);
4706 return operator_plus(a,b,t,contextptr);
4707 }
4708
operator +(const gen & a,const gen & b)4709 gen operator + (const gen & a,const gen & b){
4710 register unsigned t=(a.type<< _DECALAGE) | b.type;
4711 if (!t)
4712 return ((longlong) a.val+b.val);
4713 return operator_plus(a,b,t,context0);
4714 }
4715
4716 // specialization of Tfraction<gen> operator +
operator +(const Tfraction<gen> & a,const Tfraction<gen> & b)4717 Tfraction<gen> operator + (const Tfraction<gen> & a,const Tfraction<gen> &b){
4718 if (is_one(a.den))
4719 return(Tfraction<gen> (a.num+b));
4720 if (is_one(b.den))
4721 return(Tfraction<gen> (b.num+a));
4722 gen da(a.den),db(b.den);
4723 gen den=simplify3(da,db),num;
4724 if (a.num.type==_POLY && b.num.type==_POLY && db.type==_POLY && da.type==_POLY)
4725 num=foisplus(*a.num._POLYptr,*db._POLYptr,*b.num._POLYptr,*da._POLYptr);
4726 else
4727 num=foisplus(a.num,db,b.num,da) ; // (a.num*db+b.num*da);
4728 if (den.type==_FRAC){
4729 num=num * den._FRACptr->den;
4730 den=den._FRACptr->num;
4731 }
4732 if (is_exactly_zero(num))
4733 return Tfraction<gen>(num,1);
4734 simplify3(num,den);
4735 if (den.type==_CPLX){ // 3 jan 2020, avoid complex denominator
4736 gen & a=*den._CPLXptr;
4737 gen & b=*(den._CPLXptr+1);
4738 num=num*gen(a,-b);
4739 den=a*a+b*b;
4740 }
4741 den=den*da*db;
4742 return Tfraction<gen> (num,den);
4743 }
4744
4745
symbolic_plot_makevecteur(const unary_function_ptr & u,const gen & e,bool project,GIAC_CONTEXT)4746 static gen symbolic_plot_makevecteur(const unary_function_ptr & u,const gen & e,bool project,GIAC_CONTEXT){
4747 if ( (u!=at_pnt) || (e.type!=_VECT) || (e.subtype!=_PNT__VECT) )
4748 return symbolic(u,e);
4749 // e is a curve or a pnt
4750 vecteur w(*e._VECTptr);
4751 if ( (w.size()!=2) && (w.size()!=3))
4752 return symbolic(u,e);
4753 gen a0(w[0]);
4754 gen a1(w[1]);
4755 if ( a1.type==_VECT && a1._VECTptr->size()==3 )
4756 return symbolic(u,gen(makenewvecteur(a0,a1,a1._VECTptr->back()),_PNT__VECT));
4757 if ( a1.type==_VECT && a1._VECTptr->size()==2 ){
4758 if (project){
4759 // we must project a0
4760 gen param=a1._VECTptr->back(); // v= [ pnt() t ]
4761 if (param.type==_VECT){
4762 vecteur v=*param._VECTptr;
4763 v[1]=projection(v[0],a0,contextptr);
4764 if (is_undef(v[1]))
4765 return v[1];
4766 a0=remove_at_pnt(parameter2point(v,contextptr)); // same
4767 a1=makenewvecteur(a1._VECTptr->front(),v);
4768 }
4769 }
4770 else
4771 a1=a1._VECTptr->front();
4772 }
4773 return symbolic(u,gen(makenewvecteur(a0,a1),_PNT__VECT));
4774 }
4775
sym_add(const gen & a,const gen & b,GIAC_CONTEXT)4776 gen sym_add(const gen & a,const gen & b,GIAC_CONTEXT){
4777 #ifdef TIMEOUT
4778 control_c();
4779 #endif
4780 if (ctrl_c || interrupted) {
4781 interrupted = true; ctrl_c=false;
4782 return gensizeerr(gettext("Stopped by user interruption."));
4783 }
4784 bool adeuxpoints=a.is_symb_of_sommet(at_deuxpoints);
4785 if ( (a.is_symb_of_sommet(at_interval) || adeuxpoints)&& a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()==2)
4786 return symbolic(a._SYMBptr->sommet,makesequence(a._SYMBptr->feuille._VECTptr->front()+b,a._SYMBptr->feuille._VECTptr->back()+b)); // removed +(adeuxpoints?minus_one:zero) otherwise slicing like v[1:4] does not work
4787 if (a.is_symb_of_sommet(at_unit)){
4788 if (is_zero(b))
4789 return a;
4790 if (equalposcomp(lidnt(b),cst_pi)!=0)
4791 return sym_add(a,evalf(b,1,contextptr),contextptr);
4792 if (b.is_symb_of_sommet(at_unit)){
4793 vecteur & va=*a._SYMBptr->feuille._VECTptr;
4794 vecteur & vb=*b._SYMBptr->feuille._VECTptr;
4795 if (va[1]==vb[1])
4796 return new_ref_symbolic(symbolic(at_unit,makenewvecteur(operator_plus(va[0],vb[0],contextptr),va[1])));
4797 gen g=mksa_reduce(vb[1]/va[1],contextptr);
4798 gen tmp=chk_not_unit(g);
4799 if (is_undef(tmp)) return tmp;
4800 return new_ref_symbolic(symbolic(at_unit,makenewvecteur(operator_plus(va[0],operator_times(g,vb[0],contextptr),contextptr),va[1])));
4801 }
4802 if (lidnt(b).empty()){
4803 gen g=mksa_reduce(a,contextptr);
4804 gen tmp=chk_not_unit(g);
4805 if (is_undef(tmp)) return tmp;
4806 return g+b;
4807 }
4808 }
4809 if (b.is_symb_of_sommet(at_unit)){
4810 if (is_zero(a))
4811 return b;
4812 if (equalposcomp(lidnt(a),cst_pi)!=0)
4813 return sym_add(evalf(a,1,contextptr),b,contextptr);
4814 if (lidnt(a).empty()){
4815 gen g=mksa_reduce(b,contextptr);
4816 gen tmp=chk_not_unit(g);
4817 if (is_undef(tmp)) return tmp;
4818 return a+g;
4819 }
4820 }
4821 if (a.is_approx()){
4822 gen b1;
4823 if (has_evalf(b,b1,1,contextptr) && (b.type!=b1.type || b!=b1)){
4824 #ifdef HAVE_LIBMPFR
4825 if (a.type==_REAL){
4826 gen b2;
4827 #if defined HAVE_LIBMPFI && !defined NO_RTTI
4828 if (real_interval * ptr=dynamic_cast<real_interval *>(a._REALptr))
4829 b2=convert_interval(b,mpfi_get_prec(ptr->infsup),contextptr);
4830 else
4831 #endif
4832 b2=accurate_evalf(b,mpfr_get_prec(a._REALptr->inf));
4833 if (b2.is_approx())
4834 return a+b2;
4835 }
4836 if (a.type==_CPLX && a._CPLXptr->type==_REAL){
4837 gen b2;
4838 #if defined HAVE_LIBMPFI && !defined NO_RTTI
4839 if (real_interval * ptr=dynamic_cast<real_interval *>(a._CPLXptr->_REALptr))
4840 b2=convert_interval(b,mpfi_get_prec(ptr->infsup),contextptr);
4841 else
4842 #endif
4843 b2=accurate_evalf(b,mpfr_get_prec(a._CPLXptr->_REALptr->inf));
4844 if (b2.is_approx())
4845 return a+b2;
4846 }
4847 #endif
4848 return a+b1;
4849 }
4850 }
4851 if (b.is_approx()){
4852 gen a1;
4853 if (has_evalf(a,a1,1,contextptr) && (a.type!=a1.type || a!=a1)){
4854 #ifdef HAVE_LIBMPFR
4855 if (b.type==_REAL){
4856 gen a2;
4857 #if defined HAVE_LIBMPFI && !defined NO_RTTI
4858 if (real_interval * ptr=dynamic_cast<real_interval *>(b._REALptr))
4859 a2=convert_interval(a,mpfi_get_prec(ptr->infsup),contextptr);
4860 else
4861 #endif
4862 a2=accurate_evalf(a,mpfr_get_prec(b._REALptr->inf));
4863 if (a2.is_approx())
4864 return a2+b;
4865 }
4866 if (b.type==_CPLX && b._CPLXptr->type==_REAL){
4867 gen a2;
4868 #if defined HAVE_LIBMPFI && !defined NO_RTTI
4869 if (real_interval * ptr=dynamic_cast<real_interval *>(b._CPLXptr->_REALptr))
4870 a2=convert_interval(a,mpfi_get_prec(ptr->infsup),contextptr);
4871 else
4872 #endif
4873 a2=accurate_evalf(a,mpfr_get_prec(b._CPLXptr->_REALptr->inf));
4874 if (a2.is_approx())
4875 return a2+b;
4876 }
4877 #endif
4878 return a1+b;
4879 }
4880 }
4881 if ( (a.type==_SYMB) && equalposcomp(plot_sommets,a._SYMBptr->sommet) ){
4882 if ( (b.type==_SYMB) && equalposcomp(plot_sommets,b._SYMBptr->sommet) )
4883 return a._SYMBptr->feuille._VECTptr->front()+b._SYMBptr->feuille._VECTptr->front();
4884 else {
4885 if (b.type==_VECT)
4886 return translation(b,a,contextptr);
4887 gen a_(a);
4888 if (a.is_symb_of_sommet(at_curve) && a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()==2 && a._SYMBptr->feuille._VECTptr->front().type==_VECT){
4889 // adjust param and cartesian eq
4890 vecteur v=*a._SYMBptr->feuille._VECTptr->front()._VECTptr;
4891 if (v.size()==7)
4892 v[6] += b;
4893 if (v.size()>=6){
4894 v[5]=subst(v[5],makevecteur(x__IDNT_e,y__IDNT_e),makevecteur(x__IDNT_e-re(b,contextptr),y__IDNT_e-im(b,contextptr)),false,contextptr);
4895 a_=symbolic(at_curve,gen(makevecteur(gen(v,a._SYMBptr->feuille._VECTptr->front().subtype),a._SYMBptr->feuille._VECTptr->back()),a._SYMBptr->feuille.subtype));
4896 }
4897 }
4898 return symbolic_plot_makevecteur( a_._SYMBptr->sommet,a_._SYMBptr->feuille+b,true,contextptr);
4899 }
4900 }
4901 if ( (b.type==_SYMB) && equalposcomp(plot_sommets,b._SYMBptr->sommet) ){
4902 if (a.type==_VECT)
4903 return translation(a,b,contextptr);
4904 return symbolic_plot_makevecteur(b._SYMBptr->sommet,b._SYMBptr->feuille+a,true,contextptr);
4905 }
4906 gen var1,var2,res1,res2;
4907 if (is_algebraic_program(a,var1,res1)){
4908 if (is_algebraic_program(b,var2,res2)){
4909 if (var1!=var2 && is_constant_wrt(res2,var1,contextptr)){
4910 res2=subst(res2,var2,var1,false,contextptr);
4911 var2=var1;
4912 }
4913 if (var1==var2)
4914 return symbolic(at_program,gen(makevecteur(var1,0,operator_plus(res1,res2,contextptr)),_SEQ__VECT));
4915 }
4916 if (!is_constant_wrt(b,var1,contextptr))
4917 *logptr(contextptr) << "Warning function+constant with constant dependant of mute variable" << '\n';
4918 return symbolic(at_program,gen(makevecteur(var1,0,operator_plus(res1,b,contextptr)),_SEQ__VECT));
4919 }
4920 if (is_algebraic_program(b,var2,res2)){
4921 if (!is_constant_wrt(a,var2,contextptr))
4922 *logptr(contextptr) << "Warning constant+function with constant dependant of mute variable" << '\n';
4923 return symbolic(at_program,gen(makevecteur(var2,0,operator_plus(a,res2,contextptr)),_SEQ__VECT));
4924 }
4925 if (a.type==_VECT){
4926 if (is_zero(b,contextptr))
4927 return a;
4928 if (a.subtype==_LIST__VECT)
4929 return apply1st(a,b,contextptr,operator_plus);
4930 vecteur res=*a._VECTptr;
4931 if (res.empty())
4932 return b;
4933 if (a.subtype==_VECTOR__VECT && a._VECTptr->size()==2){
4934 if (b.type==_VECT && b._VECTptr->size()==2){
4935 vecteur & bv=*b._VECTptr;
4936 if (b.subtype==_VECTOR__VECT && res.front()==bv.back())
4937 return _vector(gen(makenewvecteur(bv.front(),bv.back()+res.back()-res.front()),_SEQ__VECT),contextptr);
4938 return _vector(gen(makenewvecteur(res.front(),res.back()+bv.back()-bv.front()),_SEQ__VECT),contextptr);
4939 }
4940 return _point(b+res.back()-res.front(),contextptr);
4941 }
4942 if (b.type==_VECT && b.subtype==_VECTOR__VECT && b._VECTptr->size()==2)
4943 return a+vector2vecteur(*b._VECTptr);
4944 if (a.subtype==_POINT__VECT && a._VECTptr->size()==3 && b.type!=_VECT){
4945 gen reb,imb; reim(b,reb,imb,contextptr);
4946 res[0] += reb;
4947 res[1] += imb;
4948 return res;
4949 }
4950 if (equalposcomp((int *)_GROUP__VECT_subtype,a.subtype)){ // add to each element
4951 iterateur it=res.begin(),itend=res.end();
4952 for (;it!=itend;++it)
4953 *it=*it+b;
4954 return gen(res,a.subtype);
4955 }
4956 if (a.subtype==_PNT__VECT){
4957 res.front()=res.front()+b;
4958 return gen(res,_PNT__VECT);
4959 }
4960 if (a.subtype!=_POLY1__VECT && ckmatrix(a)){ // matrix+cst
4961 int s=int(res.size());
4962 if (unsigned(s)==res.front()._VECTptr->size()){
4963 for (int i=0;i<s;i++){
4964 vecteur v = *res[i]._VECTptr;
4965 v[i] += b;
4966 res[i]=gen(v,res[i].subtype);
4967 }
4968 return gen(res,_MATRIX__VECT);
4969 }
4970 }
4971 // polynomial+cst
4972 res.back()=res.back()+b;
4973 if ( (res.size()==1) && is_exactly_zero(res.back()))
4974 return zero;
4975 else
4976 return gen(res,_POLY1__VECT);
4977 }
4978 if (b.type==_VECT)
4979 return sym_add(b,a,contextptr);
4980 if (is_undef(a))
4981 return a;
4982 if (is_undef(b))
4983 return b;
4984 if (is_inf(a)){
4985 if (is_inf(b)){
4986 if ((a==b) && (a!=unsigned_inf))
4987 return a;
4988 else
4989 return undef;
4990 }
4991 if (a==unsigned_inf || is_zero(im(b,contextptr)))
4992 return a;
4993 return unsigned_inf;
4994 }
4995 if (is_inf(b)){
4996 if (b==unsigned_inf || is_zero(im(a,contextptr)))
4997 return b;
4998 return unsigned_inf;
4999 }
5000 if (b.is_symb_of_sommet(at_neg) && a==b._SYMBptr->feuille)
5001 return chkmod(zero,a);
5002 if (a.is_symb_of_sommet(at_neg) && b==a._SYMBptr->feuille)
5003 return chkmod(zero,b);
5004 if (is_exactly_zero(a))
5005 return b;
5006 if (is_exactly_zero(b))
5007 return a;
5008 if (a.type==_STRNG)
5009 return string2gen(*a._STRNGptr+b.print(context0),false);
5010 if (b.type==_STRNG)
5011 return string2gen(a.print(context0)+*b._STRNGptr,false);
5012 if (a.type==_FRAC){
5013 if ( (b.type!=_SYMB) && (b.type!=_IDNT) )
5014 return (*a._FRACptr)+b;
5015 if (b.is_symb_of_sommet(at_neg))
5016 return a-b._SYMBptr->feuille;
5017 if (b.is_symb_of_sommet(at_inv) && is_cinteger(b._SYMBptr->feuille))
5018 return (*a._FRACptr)+fraction(1,b._SYMBptr->feuille);
5019 if (b.is_symb_of_sommet(at_prod) && b._SYMBptr->feuille.type==_VECT){
5020 const vecteur & bf=*b._SYMBptr->feuille._VECTptr;
5021 if (bf.size()==2 && is_integer(bf[0]) && bf[1].is_symb_of_sommet(at_inv) && is_cinteger(bf[1]._SYMBptr->feuille))
5022 return (*a._FRACptr)+fraction(bf[0],bf[1]._SYMBptr->feuille);
5023 }
5024 return sym_add(_FRAC2_SYMB(a),b,contextptr);
5025 }
5026 if (b.type==_FRAC){
5027 if ( (a.type!=_SYMB) && (a.type!=_IDNT) )
5028 return a+(*b._FRACptr);
5029 if (a.is_symb_of_sommet(at_neg))
5030 return b-a._SYMBptr->feuille;
5031 if (a.is_symb_of_sommet(at_inv) && is_cinteger(a._SYMBptr->feuille))
5032 return fraction(1,a._SYMBptr->feuille)+(*b._FRACptr);
5033 if (a.is_symb_of_sommet(at_prod) && a._SYMBptr->feuille.type==_VECT){
5034 const vecteur & af=*a._SYMBptr->feuille._VECTptr;
5035 if (af.size()==2 && is_integer(af[0]) && af[1].is_symb_of_sommet(at_inv) && is_cinteger(af[1]._SYMBptr->feuille))
5036 return fraction(af[0],af[1]._SYMBptr->feuille)+(*b._FRACptr);
5037 }
5038 return sym_add(a,_FRAC2_SYMB(b),contextptr);
5039 }
5040 if (a.type==_EXT){
5041 if (a.is_constant() && (b.type==_POLY))
5042 return addpoly(*b._POLYptr,a);
5043 /*
5044 if (b.type==_POLY && b.is_constant())
5045 return a+b._POLYptr->coord.front().value;
5046 */
5047 else
5048 return algebraic_EXTension(*a._EXTptr+b,*(a._EXTptr+1));
5049 }
5050 if (b.type==_EXT){
5051 if (b.is_constant() && (a.type==_POLY))
5052 return addpoly(*a._POLYptr,b);
5053 /*
5054 if (a.type==_POLY && a.is_constant())
5055 return a._POLYptr->coord.front().value+b;
5056 */
5057 else
5058 return algebraic_EXTension(a+*b._EXTptr,*(b._EXTptr+1));
5059 }
5060 int ia=is_inequality(a),ib=is_inequality(b);
5061 if (ia){
5062 vecteur & va=*a._SYMBptr->feuille._VECTptr;
5063 if (ia==ib || (ia==1 && ib)){
5064 if (ia==4) // <> + <>
5065 return undef;
5066 vecteur & vb=*b._SYMBptr->feuille._VECTptr;
5067 return new_ref_symbolic(symbolic(b._SYMBptr->sommet,makesequence(va.front()+vb.front(),va.back()+vb.back())));
5068 }
5069 if (ia==1 || !ib) // = +
5070 return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(va.front()+b,va.back()+b)));
5071 if ( (ia==5 && ib==6) || (ia==6 && ib==5)){
5072 vecteur & vb=*b._SYMBptr->feuille._VECTptr;
5073 return new_ref_symbolic(symbolic(at_superieur_strict,makesequence(va.front()+vb.front(),va.back()+vb.back())));
5074 }
5075 }
5076 if (ib)
5077 return b+a;
5078 if (a.is_symb_of_sommet(at_interval)){
5079 gen & f=a._SYMBptr->feuille;
5080 if (f.type==_VECT && f._VECTptr->size()==2){
5081 vecteur & v=*f._VECTptr;
5082 if (b.is_symb_of_sommet(at_interval)){
5083 gen & g=b._SYMBptr->feuille;
5084 if (g.type==_VECT && g._VECTptr->size()==2){
5085 vecteur & w=*g._VECTptr;
5086 return new_ref_symbolic(symbolic(at_interval,gen(makenewvecteur(w[0]+v[0],w[1]+v[1]),_SEQ__VECT)));
5087 }
5088 }
5089 return new_ref_symbolic(symbolic(at_interval,gen(makenewvecteur(b+v[0],b+v[1]),_SEQ__VECT)));
5090 }
5091 }
5092 if (b.is_symb_of_sommet(at_interval))
5093 return b+a;
5094 /* if (xcas_mode(contextptr) && (a.type==_SYMB|| b.type==_SYMB) )
5095 return liste2symbolique(fusion2liste(symbolique2liste(a),symbolique2liste(b))); */
5096 if ((a.type==_SYMB) && (b.type==_SYMB)){
5097 if (a._SYMBptr->sommet==at_plus) {
5098 if (b._SYMBptr->sommet==at_plus)
5099 return new_ref_symbolic(symbolic(at_plus,gen(mergevecteur(*(a._SYMBptr->feuille._VECTptr),*(b._SYMBptr->feuille._VECTptr)),_SEQ__VECT)));
5100 else
5101 return new_ref_symbolic(symbolic(*a._SYMBptr,b));
5102 }
5103 else {
5104 if (b._SYMBptr->sommet==at_plus)
5105 return new_ref_symbolic(symbolic(*(b._SYMBptr),a));
5106 else
5107 return new_ref_symbolic(symbolic(at_plus,makesequence(a,b)));
5108 }
5109 }
5110 if (b.type==_SYMB){
5111 if (b._SYMBptr->sommet==at_plus)
5112 return new_ref_symbolic(symbolic(a,b._SYMBptr->sommet,b._SYMBptr->feuille));
5113 else
5114 return new_ref_symbolic(symbolic(at_plus,makesequence(a,b)));
5115 }
5116 if (a.type==_SYMB){
5117 if ( a._SYMBptr->sommet==at_plus && a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()>1 &&
5118 ( (b==plus_one && a._SYMBptr->feuille._VECTptr->back()==minus_one) || (b==minus_one && a._SYMBptr->feuille._VECTptr->back()==plus_one) )
5119 )
5120 {
5121 vecteur v=*a._SYMBptr->feuille._VECTptr;
5122 v.pop_back();
5123 if (v.size()==1)
5124 return v.front();
5125 else
5126 return new_ref_symbolic(symbolic(at_plus,gen(v,a._SYMBptr->feuille.subtype)));
5127 }
5128 if (a._SYMBptr->sommet==at_plus)
5129 return new_ref_symbolic(symbolic(*a._SYMBptr,b));
5130 else
5131 return new_ref_symbolic(symbolic(at_plus,makesequence(a,b)));
5132 }
5133 if ( (a.type==_IDNT) || (b.type==_IDNT))
5134 return new_ref_symbolic(symbolic(at_plus,makesequence(a,b)));
5135 if (a.type==_MOD)
5136 return a+makemod(b,*(a._MODptr+1));
5137 if (b.type==_MOD)
5138 return makemod(a,*(b._MODptr+1))+b;
5139 return new_ref_symbolic(symbolic(at_plus,makesequence(a,b)));
5140 // settypeerr(gettext("sym_add"));
5141 }
5142
subpoly(const gen & th,const gen & other)5143 static gen subpoly(const gen & th, const gen & other){
5144 if ((th.type!=_POLY) || (other.type!=_POLY)){
5145 #ifndef NO_STDEXCEPT
5146 settypeerr(gettext("subpoly"));
5147 #endif
5148 return gentypeerr(gettext("subpoly"));
5149 }
5150 vector< monomial<gen> >::const_iterator a=th._POLYptr->coord.begin();
5151 vector< monomial<gen> >::const_iterator a_end=th._POLYptr->coord.end();
5152 vector< monomial<gen> >::const_iterator b=other._POLYptr->coord.begin();
5153 vector< monomial<gen> >::const_iterator b_end=other._POLYptr->coord.end();
5154 if (b==b_end){
5155 return th;
5156 }
5157 ref_polynome * resptr=new ref_polynome(th._POLYptr->dim);
5158 Sub_gen(a,a_end,b,b_end,resptr->t.coord,th._POLYptr->is_strictly_greater);
5159 return resptr;
5160 }
5161
subpoly(const polynome & p,const gen & c)5162 polynome subpoly(const polynome & p,const gen & c){
5163 if (is_exactly_zero(c))
5164 return p;
5165 polynome pcopy(p);
5166 if ( (!p.coord.empty()) && p.coord.back().index.is_zero() ) {
5167 pcopy.coord.back().value = pcopy.coord.back().value - c;
5168 if (is_exactly_zero(pcopy.coord.back().value))
5169 pcopy.coord.pop_back();
5170 }
5171 else
5172 pcopy.coord.push_back(monomial<gen>(-c,pcopy.dim));
5173 return pcopy;
5174 }
5175
subpoly(const gen & c,const polynome & p)5176 static polynome subpoly(const gen & c,const polynome & p){
5177 if (is_exactly_zero(c))
5178 return -p;
5179 polynome pcopy(-p);
5180 if ( (!p.coord.empty()) && p.coord.back().index.is_zero() ) {
5181 pcopy.coord.back().value = pcopy.coord.back().value + c;
5182 if (is_exactly_zero(pcopy.coord.back().value))
5183 pcopy.coord.pop_back();
5184 }
5185 else
5186 pcopy.coord.push_back(monomial<gen>(c,pcopy.dim));
5187 return pcopy;
5188 }
5189
subgen_poly(const gen & a,const gen & b,bool inplace=false)5190 static gen subgen_poly(const gen & a,const gen & b,bool inplace=false){
5191 vecteur & av=*a._VECTptr;
5192 vecteur & bv=*b._VECTptr;
5193 if (inplace){
5194 /*
5195 int as=av.size(),bs=bv.size();
5196 if (as<bs)
5197 av.insert(av.begin(),bs-as,0);
5198 */
5199 gen res(a);
5200 Submodpoly(av.begin(),av.end(),bv.begin(),bv.end(),0,av);
5201 return res;
5202 }
5203 gen res(vecteur(0), _POLY1__VECT);
5204 submodpoly(av,bv,0,*res._VECTptr);
5205 return res._VECTptr->empty()?0:res;
5206 }
5207
operator_minus_eq(gen & a,const gen & b,GIAC_CONTEXT)5208 gen & operator_minus_eq (gen & a,const gen & b,GIAC_CONTEXT){
5209 #ifdef EMCC
5210 a=operator_minus(a,b,contextptr);
5211 return a;
5212 #endif
5213 if (a.type==b.type){
5214 #ifdef SMARTPTR64
5215 if (*(ulonglong *)&a==*(ulonglong *)&b && a.type<=_CPLX)
5216 return a=0;
5217 #else
5218 if (&a==&b && a.type<=_CPLX)
5219 return a=0;
5220 #endif
5221 if (a.type==_DOUBLE_){
5222 #ifdef DOUBLEVAL
5223 a._DOUBLE_val -= b._DOUBLE_val; return a;
5224 #else
5225 *((double *) &a) -= *((double *) &b);
5226 a.type = _DOUBLE_;
5227 return a;
5228 #endif
5229 }
5230 if (a.type==_FLOAT_){
5231 #ifdef DOUBLEVAL
5232 a._FLOAT_val -= b._FLOAT_val; return a;
5233 #else
5234 *((double *) &a) -= *((double *) &b);
5235 a.type = _FLOAT_;
5236 return a;
5237 #endif
5238 }
5239 if (a.type==_INT_){
5240 longlong tmp=((longlong) a.val-b.val);
5241 a.val=(int)tmp;
5242 if (a.val==tmp)
5243 return a;
5244 return a=tmp;
5245 }
5246 if (a.type==_ZINT && a.ref_count()==1){
5247 mpz_t * ptr=a._ZINTptr;
5248 mpz_sub(*ptr,*ptr,*b._ZINTptr);
5249 if (mpz_sizeinbase(*ptr,2)<32){
5250 return a=mpz_get_si(*ptr);
5251 }
5252 return a;
5253 }
5254 if (a.type==_VECT && a.subtype==_POLY1__VECT && a.ref_count()==1){
5255 if (subgen_poly(a,b,true)._VECTptr->empty())
5256 a=0;
5257 return a;
5258 }
5259 }
5260 if (a.type==_ZINT && b.type==_INT_ && a.ref_count()==1){
5261 mpz_t * ptr=a._ZINTptr;
5262 if (b.val>0)
5263 mpz_sub_ui(*ptr,*ptr,b.val);
5264 else
5265 mpz_add_ui(*ptr,*ptr,-b.val);
5266 if (mpz_sizeinbase(*ptr,2)<32){
5267 return a=mpz_get_si(*ptr);
5268 }
5269 return a;
5270 }
5271 // if (!( (++control_c_counter) & control_c_counter_mask))
5272 #ifdef TIMEOUT
5273 control_c();
5274 #endif
5275 if (ctrl_c || interrupted) {
5276 interrupted = true; ctrl_c=false;
5277 return a=gensizeerr(gettext("Stopped by user interruption."));
5278 }
5279 return a=operator_minus(a,b,contextptr);
5280 }
5281
operator_minus(const gen & a,const gen & b,unsigned t,GIAC_CONTEXT)5282 gen operator_minus(const gen & a,const gen & b,unsigned t,GIAC_CONTEXT){
5283 // if (!( (++control_c_counter) & control_c_counter_mask))
5284 #ifdef TIMEOUT
5285 control_c();
5286 #endif
5287 if (ctrl_c || interrupted) {
5288 interrupted = true; ctrl_c=false;
5289 return gensizeerr(gettext("Stopped by user interruption."));
5290 }
5291 register ref_mpz_t * e;
5292 switch ( t) {
5293 case _ZINT__ZINT:
5294 e = new ref_mpz_t;
5295 mpz_sub(e->z,*a._ZINTptr,*b._ZINTptr);
5296 return e;
5297 case _DOUBLE___DOUBLE_:
5298 return a._DOUBLE_val-b._DOUBLE_val;
5299 case _FLOAT___FLOAT_:
5300 return a._FLOAT_val-b._FLOAT_val;
5301 case _VECT__VECT:
5302 if (// abs_calc_mode(contextptr)==38 &&
5303 (a.subtype==_MATRIX__VECT ||b.subtype==_MATRIX__VECT)){
5304 if (!ckmatrix(a) || !ckmatrix(b))
5305 return gensizeerr(contextptr);
5306 if (a._VECTptr->size()!=b._VECTptr->size() || a._VECTptr->front()._VECTptr->size()!=b._VECTptr->front()._VECTptr->size())
5307 return gendimerr(contextptr);
5308 }
5309 if (a.subtype==_POLY1__VECT)
5310 return subgen_poly(a,b);
5311 if (a.subtype==_PNT__VECT)
5312 return gen(makenewvecteur(a._VECTptr->front()-b,a._VECTptr->back()),a.subtype);
5313 if (a.subtype!=_POINT__VECT && equalposcomp((int *)_GROUP__VECT_subtype,a.subtype))
5314 return sym_sub(a,b,contextptr);
5315 if (a.subtype==_POINT__VECT && b.subtype==_POINT__VECT)
5316 return gen(subvecteur(*a._VECTptr,*b._VECTptr),0);
5317 return gen(subvecteur(*a._VECTptr,*b._VECTptr),a.subtype);
5318 case _MAP__MAP:
5319 {
5320 int arows,acols,an,brows,bcols,bn;
5321 if ( (is_sparse_matrix(a,arows,acols,an) && is_sparse_matrix(b,brows,bcols,bn)) || (is_sparse_vector(a,arows,an) && is_sparse_vector(b,brows,bn)) ){
5322 gen_map res;
5323 gen g(res);
5324 sparse_sub(*a._MAPptr,*b._MAPptr,*g._MAPptr);
5325 return g;
5326 }
5327 }
5328 case _INT___ZINT:
5329 e = new ref_mpz_t;
5330 if (a.val<0)
5331 mpz_add_ui(e->z,*b._ZINTptr,-a.val);
5332 else
5333 mpz_sub_ui(e->z,*b._ZINTptr,a.val);
5334 mpz_neg(e->z,e->z);
5335 return(e);
5336 case _ZINT__INT_:
5337 e = new ref_mpz_t;
5338 if (b.val<0)
5339 mpz_add_ui(e->z,*a._ZINTptr,-b.val);
5340 else
5341 mpz_sub_ui(e->z,*a._ZINTptr,b.val);
5342 return(e);
5343 case _INT___DOUBLE_:
5344 return a.val-b._DOUBLE_val;
5345 case _DOUBLE___INT_:
5346 return a._DOUBLE_val-b.val;
5347 case _INT___FLOAT_:
5348 return giac_float(a.val)-b._FLOAT_val;
5349 case _FLOAT___INT_:
5350 return a._FLOAT_val-giac_float(b.val);
5351 case _DOUBLE___FLOAT_:
5352 return giac_float(a._DOUBLE_val)-b._FLOAT_val;
5353 case _FLOAT___DOUBLE_:
5354 return a._FLOAT_val-giac_float(b._DOUBLE_val);
5355 case _FLOAT___FRAC:
5356 return a-evalf2bcd(b,1,contextptr);
5357 case _DOUBLE___FRAC:
5358 return a-ck_evalf_double(b,contextptr);
5359 case _FRAC__FLOAT_:
5360 return evalf2bcd(a,1,contextptr)-b;
5361 case _FRAC__DOUBLE_:
5362 return ck_evalf_double(a,contextptr)-b;
5363 case _ZINT__DOUBLE_:
5364 return mpz_get_d(*a._ZINTptr)-b._DOUBLE_val;
5365 case _DOUBLE___ZINT:
5366 return a._DOUBLE_val-mpz_get_d(*b._ZINTptr);
5367 case _DOUBLE___REAL:
5368 return a._DOUBLE_val-real2double(*b._REALptr);
5369 case _REAL__DOUBLE_:
5370 return real2double(*a._REALptr)-b._DOUBLE_val;
5371 case _CPLX__INT_: case _CPLX__ZINT: case _CPLX__DOUBLE_: case _CPLX__FLOAT_: case _CPLX__REAL:
5372 return gen(*a._CPLXptr-b,*(a._CPLXptr+1));
5373 case _INT___CPLX: case _ZINT__CPLX: case _DOUBLE___CPLX: case _FLOAT___CPLX: case _REAL__CPLX:
5374 return gen(a-*b._CPLXptr,-*(b._CPLXptr+1));
5375 case _CPLX__CPLX:
5376 return adjust_complex_display(gen(*a._CPLXptr - *b._CPLXptr, *(a._CPLXptr+1) - *(b._CPLXptr+1)),a,b);
5377 case _POLY__POLY:
5378 return subpoly(a,b);
5379 case _FRAC__FRAC:
5380 return (*a._FRACptr)-(*b._FRACptr);
5381 case _SPOL1__SPOL1:
5382 return spsub(*a._SPOL1ptr,*b._SPOL1ptr,contextptr);
5383 case _EXT__EXT:
5384 return ext_sub(a,b,contextptr);
5385 case _POLY__INT_: case _POLY__ZINT: case _POLY__DOUBLE_: case _POLY__FLOAT_: case _POLY__CPLX: case _POLY__MOD: case _POLY__REAL: case _POLY__USER:
5386 return subpoly(*a._POLYptr,b);
5387 case _INT___POLY: case _ZINT__POLY: case _DOUBLE___POLY: case _FLOAT___POLY: case _CPLX__POLY: case _MOD__POLY:case _USER__POLY: case _REAL__POLY:
5388 return subpoly(a,*b._POLYptr);
5389 case _MOD__MOD:
5390 #ifdef SMARTPTR64
5391 return modsub( (ref_modulo *) (* ((ulonglong * ) &a) >> 16), (ref_modulo *) (* ((ulonglong * ) &b) >> 16) );
5392 #else
5393 return modsub(a.__MODptr,b.__MODptr);
5394 #endif
5395 case _REAL__REAL:
5396 return (*a._REALptr)-(*b._REALptr);
5397 default:
5398 if (is_undef(a))
5399 return a;
5400 if (is_undef(b))
5401 return b;
5402 if (a.type==_FLOAT_){
5403 gen b1;
5404 if (b.type==_VECT)
5405 return sym_sub(a,b,contextptr);
5406 if (has_evalf(b,b1,1,contextptr) && b.type!=b1.type)
5407 return operator_minus(a,b1,contextptr);
5408 return operator_minus(evalf_double(a,1,contextptr),b,contextptr);
5409 }
5410 if (b.type==_FLOAT_){
5411 if (a.type==_VECT)
5412 return sym_sub(a,b,contextptr);
5413 gen a1;
5414 if (has_evalf(a,a1,1,contextptr) && a.type!=a1.type)
5415 return operator_minus(a1,b,contextptr);
5416 return operator_minus(a,evalf_double(b,1,contextptr),contextptr);
5417 }
5418 if (a.type==_SPOL1)
5419 return spsub(*a._SPOL1ptr,gen2spol1(b),contextptr);
5420 if (b.type==_SPOL1)
5421 return spsub(gen2spol1(a),*b._SPOL1ptr,contextptr);
5422 if (a.type==_USER)
5423 return (*a._USERptr)-b;
5424 if (b.type==_USER)
5425 return (-b)+a;
5426 if (a.type==_REAL)
5427 return a._REALptr->substract(b,contextptr);
5428 if (b.type==_REAL)
5429 return operator_plus(-(*b._REALptr),a,contextptr);
5430 if (a.type==_STRNG)
5431 return a;
5432 return sym_sub(a,b,contextptr);
5433 }
5434 }
5435
operator_minus(const gen & a,const gen & b,GIAC_CONTEXT)5436 gen operator_minus (const gen & a,const gen & b,GIAC_CONTEXT){
5437 register unsigned t=(a.type<< _DECALAGE) | b.type;
5438 if (!t)
5439 return((longlong) a.val-b.val);
5440 return operator_minus(a,b,t,contextptr);
5441 }
5442
operator -(const gen & a,const gen & b)5443 gen operator - (const gen & a,const gen & b){
5444 register unsigned t=(a.type<< _DECALAGE) | b.type;
5445 if (!t)
5446 return((longlong) a.val-b.val);
5447 return operator_minus(a,b,t,context0);
5448 }
5449
sym_sub(const gen & a,const gen & b,GIAC_CONTEXT)5450 gen sym_sub(const gen & a,const gen & b,GIAC_CONTEXT){
5451 #ifdef TIMEOUT
5452 control_c();
5453 #endif
5454 if (ctrl_c || interrupted) {
5455 interrupted = true; ctrl_c=false;
5456 return gensizeerr(gettext("Stopped by user interruption."));
5457 }
5458 if (a.is_symb_of_sommet(at_unit) || b.is_symb_of_sommet(at_unit))
5459 return a+(-b);
5460 if ( a.is_approx()){
5461 gen b1;
5462 if (has_evalf(b,b1,1,contextptr) && (b.type!=b1.type || b!=b1)){
5463 #ifdef HAVE_LIBMPFR
5464 if (a.type==_REAL){
5465 gen b2=accurate_evalf(b,mpfr_get_prec(a._REALptr->inf));
5466 if (b2.is_approx())
5467 return a-b2;
5468 }
5469 #endif
5470 return a-b1;
5471 }
5472 }
5473 if ( b.is_approx()){
5474 gen a1;
5475 if (has_evalf(a,a1,1,contextptr) && (a.type!=a1.type || a!=a1)){
5476 #ifdef HAVE_LIBMPFR
5477 if (a.type==_REAL){
5478 gen a2=accurate_evalf(a,mpfr_get_prec(b._REALptr->inf));
5479 if (a2.is_approx())
5480 return a2-b;
5481 }
5482 #endif
5483 return a1-b;
5484 }
5485 }
5486 if ( (a.type==_SYMB) && equalposcomp(plot_sommets,a._SYMBptr->sommet) ){
5487 if ( (b.type==_SYMB) && equalposcomp(plot_sommets,b._SYMBptr->sommet) )
5488 return a._SYMBptr->feuille._VECTptr->front()-b._SYMBptr->feuille._VECTptr->front();
5489 else {
5490 gen a_(a);
5491 if (a.is_symb_of_sommet(at_curve) && a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()==2 && a._SYMBptr->feuille._VECTptr->front().type==_VECT){
5492 // adjust param and cartesian eq
5493 vecteur v=*a._SYMBptr->feuille._VECTptr->front()._VECTptr;
5494 if (v.size()==7)
5495 v[6] -= b;
5496 if (v.size()>=6){
5497 v[5]=subst(v[5],makevecteur(x__IDNT_e,y__IDNT_e),makevecteur(x__IDNT_e+re(b,contextptr),y__IDNT_e+im(b,contextptr)),false,contextptr);
5498 a_=symbolic(at_curve,gen(makevecteur(gen(v,a._SYMBptr->feuille._VECTptr->front().subtype),a._SYMBptr->feuille._VECTptr->back()),a._SYMBptr->feuille.subtype));
5499 }
5500 }
5501 return symbolic_plot_makevecteur(a_._SYMBptr->sommet,a_._SYMBptr->feuille-b,true,contextptr);
5502 }
5503 }
5504 if ( (b.type==_SYMB) && equalposcomp(plot_sommets,b._SYMBptr->sommet) )
5505 return sym_add(-b,a,contextptr);
5506 gen var1,var2,res1,res2;
5507 if (is_algebraic_program(a,var1,res1) && is_algebraic_program(b,var2,res2)){
5508 if (var1!=var2 && is_constant_wrt(res2,var1,contextptr)){
5509 res2=subst(res2,var2,var1,false,contextptr);
5510 var2=var1;
5511 }
5512 if (var1==var2)
5513 return symbolic(at_program,gen(makevecteur(var1,0,operator_minus(res1,res2,contextptr)),_SEQ__VECT));
5514 }
5515 if (a.type==_VECT)
5516 return sym_add(a,-b,contextptr);
5517 if (b.type==_VECT)
5518 return sym_add(-b,a,contextptr);
5519 if (is_undef(a))
5520 return a;
5521 if (is_undef(b))
5522 return b;
5523 if (is_inf(a)){
5524 if (is_inf(b)){
5525 if ((a==plus_inf) && (b==minus_inf))
5526 return a;
5527 if ((a==minus_inf) && (b==plus_inf))
5528 return a;
5529 return undef;
5530 }
5531 else
5532 return a;
5533 }
5534 if (a.type==_FRAC){
5535 if ( (b.type!=_SYMB) && (b.type!=_IDNT) )
5536 return (*a._FRACptr)-b;
5537 if (b.is_symb_of_sommet(at_neg))
5538 return a+b._SYMBptr->feuille;
5539 if (b.is_symb_of_sommet(at_inv) && is_cinteger(b._SYMBptr->feuille))
5540 return (*a._FRACptr)-fraction(1,b._SYMBptr->feuille);
5541 return sym_sub(_FRAC2_SYMB(a),b,contextptr);
5542 }
5543 if (b.type==_FRAC){
5544 if ( (a.type!=_SYMB) && (a.type!=_IDNT) )
5545 return a-(*b._FRACptr);
5546 if (a.is_symb_of_sommet(at_neg))
5547 return -(a._SYMBptr->feuille+b);
5548 if (a.is_symb_of_sommet(at_inv) && is_cinteger(a._SYMBptr->feuille))
5549 return fraction(1,a._SYMBptr->feuille)-(*b._FRACptr);
5550 return sym_sub(a,_FRAC2_SYMB(b),contextptr);
5551 }
5552 if (a.type==_EXT){
5553 if (a.is_constant() && (b.type==_POLY))
5554 return subpoly(a,*b._POLYptr);
5555 else
5556 return algebraic_EXTension(*a._EXTptr-b,*(a._EXTptr+1));
5557 }
5558 if (b.type==_EXT){
5559 if (b.is_constant() && (a.type==_POLY))
5560 return subpoly(*a._POLYptr,b);
5561 else
5562 return algebraic_EXTension(a-*b._EXTptr,*(b._EXTptr+1));
5563 }
5564 if (a==b)
5565 return chkmod(zero,a);
5566 if (is_inf(b))
5567 return -b;
5568 if (is_exactly_zero(b))
5569 return a;
5570 if (is_exactly_zero(a))
5571 return -b;
5572 /*
5573 if (a.type==_SYMB && a._SYMBptr->sommet==at_equal){
5574 vecteur & va=*a._SYMBptr->feuille._VECTptr;
5575 if (b.type==_SYMB && b._SYMBptr->sommet==at_equal){
5576 vecteur & vb=*b._SYMBptr->feuille._VECTptr;
5577 return new_ref_symbolic(symbolic(at_equal,makesequence(va.front()-vb.front(),va.back()-vb.back())));
5578 }
5579 else
5580 return new_ref_symbolic(symbolic(at_equal,makesequence(va.front()-b,va.back()-b)));
5581 }
5582 if (b.type==_SYMB && b._SYMBptr->sommet==at_equal){
5583 vecteur & vb=*b._SYMBptr->feuille._VECTptr;
5584 return new_ref_symbolic(symbolic(at_equal,makesequence(a-vb.front(),a-vb.back())));
5585 }
5586 */
5587 if (is_inequality(a) || is_inequality(b))
5588 return a+(-b);
5589 if ((a.type==_SYMB) && (b.type==_SYMB)){
5590 if (a._SYMBptr->sommet==at_plus) {
5591 if (b._SYMBptr->sommet==at_plus)
5592 return new_ref_symbolic(symbolic(at_plus,gen(mergevecteur(*(a._SYMBptr->feuille._VECTptr),negvecteur(*(b._SYMBptr->feuille._VECTptr))),_SEQ__VECT)));
5593 else
5594 return new_ref_symbolic(symbolic(*a._SYMBptr,-b));
5595 }
5596 else {
5597 if (b._SYMBptr->sommet==at_plus)
5598 return new_ref_symbolic(symbolic(*(-b)._SYMBptr,a));
5599 else
5600 return new_ref_symbolic(symbolic(at_plus,makesequence(a,-b)));
5601 }
5602 }
5603 if (b.type==_SYMB){
5604 if (b._SYMBptr->sommet==at_plus)
5605 return new_ref_symbolic(symbolic(*(-b)._SYMBptr,a));
5606 else
5607 return new_ref_symbolic(symbolic(at_plus,makesequence(a,-b)));
5608 }
5609 if (a.type==_SYMB){
5610 if (a._SYMBptr->sommet==at_plus)
5611 return new_ref_symbolic(symbolic(*a._SYMBptr,-b));
5612 else
5613 return new_ref_symbolic(symbolic(at_plus,makesequence(a,-b)));
5614 }
5615 if ((a.type==_IDNT) || (b.type==_IDNT))
5616 return new_ref_symbolic(symbolic(at_plus,makesequence(a,-b)));
5617 if (a.type==_MOD)
5618 return a-makemod(b,*(a._MODptr+1));
5619 if (b.type==_MOD)
5620 return makemod(a,*(b._MODptr+1))-b;
5621 return new_ref_symbolic(symbolic(at_plus,makesequence(a,-b)));
5622 // settypeerr(gettext("sym_sub"));
5623 }
5624
negfirst(const vecteur & v)5625 static vecteur negfirst(const vecteur & v){
5626 vecteur w(v);
5627 if (!w.empty())
5628 w.front()=-w.front();
5629 return w;
5630 }
5631
operator -(const gen & a)5632 gen operator -(const gen & a){
5633 ref_mpz_t *e ;
5634 switch (a.type ) {
5635 case _INT_:
5636 return(-a.val);
5637 case _ZINT:
5638 e=new ref_mpz_t;
5639 mpz_neg(e->z,*a._ZINTptr);
5640 return(e);
5641 case _DOUBLE_:
5642 return -(a._DOUBLE_val);
5643 case _FLOAT_:
5644 return -(a._FLOAT_val);
5645 case _CPLX: {
5646 const gen * aptr=a._CPLXptr;
5647 if (a.subtype==3)
5648 return adjust_complex_display(gen(-aptr->_DOUBLE_val,-(aptr+1)->_DOUBLE_val),a);
5649 return adjust_complex_display(gen(-*aptr,-*(aptr+1)),a);
5650 }
5651 case _IDNT:
5652 if ((a==undef) || (a==unsigned_inf))
5653 return a;
5654 return new_ref_symbolic(symbolic(at_neg,a));
5655 case _SYMB:
5656 if (a==plus_inf)
5657 return minus_inf;
5658 if (a==minus_inf)
5659 return plus_inf;
5660 if (a._SYMBptr->sommet==at_neg)
5661 return a._SYMBptr->feuille;
5662 if (a._SYMBptr->sommet==at_unit){
5663 // if (equalposcomp(lidnt(a),cst_pi)!=0) return -evalf(b,1,context0);
5664 return new_ref_symbolic(symbolic(at_unit,makenewvecteur(-a._SYMBptr->feuille._VECTptr->front(),a._SYMBptr->feuille._VECTptr->back())));
5665 }
5666 if (a._SYMBptr->sommet==at_plus)
5667 return new_ref_symbolic(symbolic(at_plus,gen(negvecteur(*a._SYMBptr->feuille._VECTptr),_SEQ__VECT)));
5668 if (a._SYMBptr->sommet==at_interval && a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()==2){
5669 return new_ref_symbolic(symbolic(at_interval,gen(makenewvecteur(-a._SYMBptr->feuille._VECTptr->back(),-a._SYMBptr->feuille._VECTptr->front()),_SEQ__VECT)));
5670 }
5671 if (equalposcomp(plot_sommets,a._SYMBptr->sommet)){
5672 return symbolic_plot_makevecteur(a._SYMBptr->sommet,-a._SYMBptr->feuille,false,context0);
5673 }
5674 if (a.is_symb_of_sommet(at_program)){
5675 gen a1,b;
5676 if (is_algebraic_program(a,a1,b))
5677 return symbolic(at_program,gen(makevecteur(a1,0,-b),_SEQ__VECT));
5678 }
5679 if (a._SYMBptr->sommet==at_equal || a._SYMBptr->sommet==at_equal2 || a._SYMBptr->sommet==at_different || a._SYMBptr->sommet==at_same)
5680 return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(-a._SYMBptr->feuille._VECTptr->front(),-a._SYMBptr->feuille._VECTptr->back())));
5681 if (is_inequality(a))
5682 return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(-a._SYMBptr->feuille._VECTptr->back(),-a._SYMBptr->feuille._VECTptr->front())));
5683 return new_ref_symbolic(symbolic(at_neg,a));
5684 case _VECT:
5685 if (a.subtype==_VECTOR__VECT && a._VECTptr->size()==2)
5686 return gen(makenewvecteur(a._VECTptr->back(),a._VECTptr->front()),_VECTOR__VECT);
5687 if (a.subtype==_PNT__VECT)
5688 return gen(negfirst(*a._VECTptr),a.subtype);
5689 return gen(negvecteur(*a._VECTptr),a.subtype);
5690 case _MAP:{
5691 gen_map res;
5692 gen g(res);
5693 *g._MAPptr=*a._MAPptr;
5694 sparse_neg(*g._MAPptr);
5695 return g;
5696 }
5697 case _POLY:
5698 return -(*a._POLYptr);
5699 case _EXT:
5700 return algebraic_EXTension(-(*a._EXTptr),*(a._EXTptr+1));
5701 case _USER:
5702 return -(*a._USERptr);
5703 case _MOD:
5704 return makemod(-*a._MODptr,*(a._MODptr+1));
5705 case _FRAC:
5706 return fraction(-(a._FRACptr->num),a._FRACptr->den);
5707 case _SPOL1:
5708 return spneg(*a._SPOL1ptr,context0);
5709 case _STRNG:
5710 if (is_undef(a)) return a;
5711 return string2gen("-"+(*a._STRNGptr),false);
5712 case _REAL:
5713 return -*a._REALptr;
5714 default:
5715 return new_ref_symbolic(symbolic(at_neg,a));
5716 }
5717 }
5718
mulpoly(const gen & th,const gen & other)5719 static gen mulpoly(const gen & th,const gen & other){
5720 if ((th.type!=_POLY) || (other.type!=_POLY)){
5721 #ifndef NO_STDEXCEPT
5722 settypeerr(gettext("mulpoly"));
5723 #endif
5724 return gentypeerr(gettext("mulpoly"));
5725 }
5726 vector< monomial<gen> >::const_iterator ita = th._POLYptr->coord.begin();
5727 vector< monomial<gen> >::const_iterator ita_end = th._POLYptr->coord.end();
5728 vector< monomial<gen> >::const_iterator itb = other._POLYptr->coord.begin();
5729 vector< monomial<gen> >::const_iterator itb_end = other._POLYptr->coord.end();
5730 // first some trivial cases
5731 if (ita==ita_end)
5732 return(th);
5733 if (itb==itb_end)
5734 return(other);
5735 if (is_one(*th._POLYptr))
5736 return other;
5737 if (is_one(*other._POLYptr))
5738 return th;
5739 // Now look if length a=1 or length b=1, happens frequently
5740 // think of x^3*y^2*z translated to internal form
5741 int c1=int(th._POLYptr->coord.size());
5742 if (c1==1)
5743 return other._POLYptr->shift(th._POLYptr->coord.front().index,th._POLYptr->coord.front().value);
5744 int c2=int(other._POLYptr->coord.size());
5745 if (c2==1)
5746 return th._POLYptr->shift(other._POLYptr->coord.front().index,other._POLYptr->coord.front().value);
5747 ref_polynome * resptr = new ref_polynome(th._POLYptr->dim);
5748 mulpoly(*th._POLYptr,*other._POLYptr,resptr->t,0);
5749 return resptr;
5750 }
5751
multfirst(const gen & a,const vecteur & v)5752 static vecteur multfirst(const gen & a,const vecteur & v){
5753 vecteur w(v);
5754 if (!w.empty())
5755 w.front()=v.front()*a;
5756 return w;
5757 }
5758
multgen_poly(const gen & a,const vecteur & b,int subtype)5759 static gen multgen_poly(const gen & a,const vecteur & b,int subtype){
5760 gen res(vecteur(0),subtype);
5761 multvecteur(a,b,*res._VECTptr);
5762 return res;
5763 }
5764
multgen_poly(const vecteur & a,const vecteur & b)5765 static gen multgen_poly(const vecteur & a,const vecteur & b){
5766 gen res(vecteur(0), _POLY1__VECT);
5767 operator_times(a,b,0,*res._VECTptr);
5768 return res;
5769 }
5770
5771 // a*b -> tmp, modifies tmp in place
type_operator_times(const gen & a,const gen & b,gen & tmp)5772 void type_operator_times(const gen & a,const gen &b,gen & tmp){
5773 register unsigned t=(a.type<< _DECALAGE) | b.type;
5774 #ifndef EMCC
5775 if (tmp.type==_DOUBLE_ && t==_DOUBLE___DOUBLE_){
5776 #ifdef DOUBLEVAL
5777 tmp._DOUBLE_val=a._DOUBLE_val*b._DOUBLE_val;
5778 #else
5779 *((double *) &tmp) = (*((double *) &a)) * (*((double *) &b));
5780 tmp.type = _DOUBLE_;
5781 #endif
5782 return ;
5783 }
5784 #endif
5785 if (!t && tmp.type==_INT_ ){
5786 register longlong ab=longlong(a.val)*b.val;
5787 tmp.val=(int)ab;
5788 #if 1
5789 if (ab>>31)
5790 tmp=ab;
5791 #else
5792 if (tmp.val!=ab)
5793 tmp=ab;
5794 #endif
5795 return;
5796 }
5797 if (tmp.type==_ZINT && tmp.ref_count()==1){
5798 mpz_t * ptr=tmp._ZINTptr;
5799 switch (t){
5800 case _INT___INT_:
5801 tmp=longlong(a.val)*b.val;
5802 return;
5803 case _ZINT__ZINT:
5804 mpz_mul(*ptr,*a._ZINTptr,*b._ZINTptr);
5805 return ;
5806 case _ZINT__INT_:
5807 if (b.val<0){
5808 mpz_mul_ui(*ptr,*a._ZINTptr,-b.val);
5809 mpz_neg(*ptr,*ptr);
5810 }
5811 else
5812 mpz_mul_ui(*ptr,*a._ZINTptr,b.val);
5813 return;
5814 case _INT___ZINT:
5815 if (a.val<0){
5816 mpz_mul_ui(*ptr,*b._ZINTptr,-a.val);
5817 mpz_neg(*ptr,*ptr);
5818 }
5819 else
5820 mpz_mul_ui(*ptr,*b._ZINTptr,a.val);
5821 return;
5822 }
5823 }
5824 tmp=a*b;
5825 }
5826
is_int_zint_vecteur(const vecteur & m)5827 bool is_int_zint_vecteur(const vecteur & m){
5828 const_iterateur it=m.begin(),itend=m.end();
5829 for (;it!=itend;++it){
5830 int t=it->type;
5831 if (t!=_INT_ && t!=_ZINT) return false;
5832 }
5833 return true;
5834 }
5835
type_operator_plus_times(const gen & a,const gen & b,gen & c)5836 void type_operator_plus_times(const gen & a,const gen & b,gen & c){
5837 register unsigned t=(a.type<< _DECALAGE) | b.type;
5838 #ifndef EMCC
5839 if (c.type==_DOUBLE_ && t==_DOUBLE___DOUBLE_){
5840 #ifdef DOUBLEVAL
5841 c._DOUBLE_val += a._DOUBLE_val*b._DOUBLE_val;
5842 #else
5843 *((double *) &c) += (*((double *) &a)) * (*((double *) &b));
5844 c.type = _DOUBLE_;
5845 #endif
5846 return ;
5847 }
5848 #endif
5849 if (c.type==_ZINT && c.ref_count()==1){
5850 switch (t){
5851 case _ZINT__ZINT:
5852 mpz_addmul(*c._ZINTptr,*a._ZINTptr,*b._ZINTptr);
5853 return;
5854 case _ZINT__INT_:
5855 if (b.val<0)
5856 mpz_submul_ui(*c._ZINTptr,*a._ZINTptr,-b.val);
5857 else
5858 mpz_addmul_ui(*c._ZINTptr,*a._ZINTptr,b.val);
5859 return;
5860 case _INT___ZINT:
5861 if (a.val<0){
5862 mpz_submul_ui(*c._ZINTptr,*b._ZINTptr,-a.val);
5863 }
5864 else
5865 mpz_addmul_ui(*c._ZINTptr,*b._ZINTptr,a.val);
5866 return;
5867 }
5868 }
5869 if (c.type==_EXT && a.type==_EXT && b.type==_EXT){
5870 if ((c._EXTptr+1)->type==_VECT && *(a._EXTptr+1)==*(c._EXTptr+1) && *(b._EXTptr+1)==*(c._EXTptr+1) && a._EXTptr->type==_VECT && b._EXTptr->type==_VECT && c._EXTptr->type==_VECT){
5871 vecteur & v = *(c._EXTptr+1)->_VECTptr;
5872 if (v.size()==3 && v[0]==1 && v[1]==0 && a._EXTptr->_VECTptr->size()==2 && b._EXTptr->_VECTptr->size()==2 && c._EXTptr->_VECTptr->size()==2){
5873 gen a1=a._EXTptr->_VECTptr->front(),a0=a._EXTptr->_VECTptr->back(),b1=b._EXTptr->_VECTptr->front(),b0=b._EXTptr->_VECTptr->back(),c1=c._EXTptr->_VECTptr->front(),c0=c._EXTptr->_VECTptr->back();
5874 gen d1=a1*b0+a0*b1+c1,d0=a0*b0-v[2]*a1*b1+c0;
5875 if (is_zero(d1)){ c=d0; return; }
5876 gen d=new ref_vecteur(2);
5877 d._VECTptr->front()=d1;
5878 d._VECTptr->back()=d0;
5879 if (c.ref_count()==1)
5880 *c._EXTptr=d;
5881 else
5882 c=algebraic_EXTension(d,*(c._EXTptr+1));
5883 }
5884 else {
5885 gen d=new ref_vecteur;
5886 vecteur ab,rem;
5887 operator_times(*a._EXTptr->_VECTptr,*b._EXTptr->_VECTptr,0,ab);
5888 addmodpoly(ab,*c._EXTptr->_VECTptr,*d._VECTptr);
5889 if (c.ref_count()==1){
5890 DivRem(*d._VECTptr,v,0,ab,rem); // take remainder!
5891 if (rem.size()<2){ if (rem.empty()) c=0; else c=rem.front();}
5892 else {
5893 //gen dbg=ext_reduce(d,*(c._EXTptr+1));
5894 d._VECTptr->swap(rem);
5895 *c._EXTptr=d;
5896 //if (dbg!=c) CERR << "error" << '\n';
5897 }
5898 }
5899 else
5900 c=ext_reduce(d,*(c._EXTptr+1));
5901 }
5902 return;
5903 }
5904 }
5905 if (c.type==_VECT && c.ref_count()==1 && a.type==_VECT && b.type==_VECT && a._VECTptr->size()<KARAMUL_SIZE && b._VECTptr->size()<KARAMUL_SIZE && is_int_zint_vecteur(*a._VECTptr) && is_int_zint_vecteur(*b._VECTptr) && is_int_zint_vecteur(*c._VECTptr)){
5906 add_mulmodpoly(a._VECTptr->begin(),a._VECTptr->end(),b._VECTptr->begin(),b._VECTptr->end(),0,*c._VECTptr);
5907 return;
5908 }
5909 gen g;
5910 type_operator_times(a,b,g);
5911 if (g.type==_ZINT)
5912 swapgen(c,g);
5913 c += g;
5914 }
5915
type_operator_minus_times(const gen & a,const gen & b,gen & c)5916 void type_operator_minus_times(const gen & a,const gen & b,gen & c){
5917 register unsigned t=(a.type<< _DECALAGE) | b.type;
5918 #ifndef EMCC
5919 if (c.type==_DOUBLE_ && t==_DOUBLE___DOUBLE_){
5920 #ifdef DOUBLEVAL
5921 c._DOUBLE_val -= a._DOUBLE_val*b._DOUBLE_val;
5922 #else
5923 *((double *) &c) -= (*((double *) &a)) * (*((double *) &b));
5924 c.type = _DOUBLE_;
5925 #endif
5926 return ;
5927 }
5928 #endif
5929 if (c.type==_ZINT && c.ref_count()==1){
5930 switch (t){
5931 case _ZINT__ZINT:
5932 mpz_submul(*c._ZINTptr,*a._ZINTptr,*b._ZINTptr);
5933 return;
5934 case _ZINT__INT_:
5935 if (b.val<0)
5936 mpz_addmul_ui(*c._ZINTptr,*a._ZINTptr,-b.val);
5937 else
5938 mpz_submul_ui(*c._ZINTptr,*a._ZINTptr,b.val);
5939 return;
5940 case _INT___ZINT:
5941 if (a.val<0){
5942 mpz_addmul_ui(*c._ZINTptr,*b._ZINTptr,-a.val);
5943 }
5944 else
5945 mpz_submul_ui(*c._ZINTptr,*b._ZINTptr,a.val);
5946 return;
5947 }
5948 }
5949 gen g;
5950 type_operator_times(a,b,g);
5951 c -= g;
5952 }
5953
double_times_frac(const gen & a,const fraction & b,GIAC_CONTEXT)5954 static gen double_times_frac(const gen & a,const fraction & b,GIAC_CONTEXT){
5955 gen n=a*b.num,d=b.den;
5956 return rdiv(n,d,contextptr);
5957 }
5958
mult_cplx(const gen & a,const gen & b,GIAC_CONTEXT)5959 static gen mult_cplx(const gen & a,const gen & b,GIAC_CONTEXT){
5960 gen * aptr=a._CPLXptr,*bptr=b._CPLXptr;
5961 unsigned t= (aptr->type | ((aptr+1)->type << 8) | (bptr->type << 16) | ((bptr+1)->type << 24));
5962 if (t==(_DOUBLE_ | (_DOUBLE_<<8) | (_DOUBLE_ <<16) | (_DOUBLE_ <<24))){
5963 double ar=aptr->_DOUBLE_val,ai=(aptr+1)->_DOUBLE_val,
5964 br=bptr->_DOUBLE_val,bi=(bptr+1)->_DOUBLE_val;
5965 return gen(ar*br-ai* bi, br*ai+ar*bi);
5966 }
5967 if (t==(_ZINT | (_ZINT<<8) | (_ZINT <<16) | (_ZINT <<24))){
5968 mpz_t & ax=*aptr->_ZINTptr;
5969 mpz_t & ay=*((aptr+1)->_ZINTptr);
5970 mpz_t & bx=*bptr->_ZINTptr;
5971 mpz_t & by=*((bptr+1)->_ZINTptr);
5972 // (ax+i*ay)*(bx+i*by)=ax*bx-ay*by+i*(ax*by+ay*bx)
5973 // imaginary part is also (ax+ay)*(bx+by)-ax*bx-ay*by, Karatsuba trick
5974 mpz_t axbx,ayby,r;
5975 #ifdef USE_GMP_REPLACEMENTS
5976 mpz_init(axbx); mpz_init(ayby); mpz_init(r);
5977 #else
5978 int n1=mpz_size(ax)+mpz_size(bx),n2=mpz_size(ay)+mpz_size(by);
5979 mpz_init2(axbx,n1); mpz_init2(ayby,n2); mpz_init2(r,giacmax(n1,n2)+2);
5980 #endif
5981 mpz_mul(axbx,ax,bx);
5982 mpz_add(r,ax,ay);
5983 mpz_add(ayby,bx,by); // temporary use
5984 mpz_mul(r,r,ayby);
5985 mpz_sub(r,r,axbx);
5986 mpz_mul(ayby,ay,by);
5987 mpz_sub(r,r,ayby);
5988 gen I=r;
5989 mpz_sub(r,axbx,ayby);
5990 gen R=r;
5991 R=gen(R,I);
5992 mpz_clear(r); mpz_clear(ayby); mpz_clear(axbx);
5993 return R;
5994 }
5995 #if defined HAVE_LIBMPFR && !defined NO_RTTI
5996 if (t==(_REAL | (_REAL<<8) | (_REAL <<16) | (_REAL <<24))){
5997 real_object & ax=*aptr->_REALptr;
5998 real_object & ay=*((aptr+1)->_REALptr);
5999 real_object & bx=*bptr->_REALptr;
6000 real_object & by=*((bptr+1)->_REALptr);
6001 if (!dynamic_cast<real_interval *>(&ax) ||
6002 !dynamic_cast<real_interval *>(&ay) ||
6003 !dynamic_cast<real_interval *>(&bx) ||
6004 !dynamic_cast<real_interval *>(&by) ){
6005 mpfr_t axbx,ayby,r;
6006 int nbits=mpfr_get_prec(ax.inf);
6007 nbits=giacmin(nbits,mpfr_get_prec(bx.inf));
6008 mpfr_init2(axbx,nbits); mpfr_init2(ayby,nbits); mpfr_init2(r,nbits);
6009 mpfr_mul(axbx,ax.inf,bx.inf,MPFR_RNDN);
6010 mpfr_add(r,ax.inf,ay.inf,MPFR_RNDN);
6011 mpfr_add(ayby,bx.inf,by.inf,MPFR_RNDN); // temporary use
6012 mpfr_mul(r,r,ayby,MPFR_RNDN);
6013 mpfr_sub(r,r,axbx,MPFR_RNDN);
6014 mpfr_mul(ayby,ay.inf,by.inf,MPFR_RNDN);
6015 mpfr_sub(r,r,ayby,MPFR_RNDN);
6016 gen I=real_object(r);
6017 mpfr_sub(r,axbx,ayby,MPFR_RNDN);
6018 gen R=real_object(r);
6019 R=gen(R,I);
6020 mpfr_clear(r); mpfr_clear(ayby); mpfr_clear(axbx);
6021 return R;
6022 }
6023 }
6024 #endif
6025 return gen(*aptr * (*bptr) - *(aptr+1)* (*(bptr+1)),
6026 (*bptr) * (*(aptr+1)) + *(bptr+1) * (*aptr));
6027 }
6028
operator_times(const gen & a,const gen & b,unsigned t,GIAC_CONTEXT)6029 static gen operator_times(const gen & a,const gen & b,unsigned t,GIAC_CONTEXT){
6030 static bool warnpy=true;
6031 // COUT << a << "*" << b << '\n';
6032 // if (!( (++control_c_counter) & control_c_counter_mask))
6033 #ifdef TIMEOUT
6034 control_c();
6035 #endif
6036 if (ctrl_c || interrupted) {
6037 interrupted = true; ctrl_c=false;
6038 return gensizeerr(gettext("Stopped by user interruption."));
6039 }
6040 register ref_mpz_t * e;
6041 switch (t) {
6042 case _ZINT__ZINT:
6043 e=new ref_mpz_t(GIAC_MPZ_INIT_SIZE); // ((mpz_size(*b._ZINTptr)+mpz_size(*b._ZINTptr))*mp_bits_per_limb);
6044 mpz_mul(e->z,*a._ZINTptr,*b._ZINTptr);
6045 return e;
6046 case _DOUBLE___DOUBLE_:
6047 return a._DOUBLE_val*b._DOUBLE_val;
6048 case _FLOAT___FLOAT_:
6049 return a._FLOAT_val*b._FLOAT_val;
6050 case _INT___ZINT:
6051 if (a.val==1) return b;
6052 e=new ref_mpz_t(GIAC_MPZ_INIT_SIZE); // (mpz_size(*b._ZINTptr)*mp_bits_per_limb);
6053 if (a.val<0){
6054 mpz_mul_ui(e->z,*b._ZINTptr,-a.val);
6055 mpz_neg(e->z,e->z);
6056 }
6057 else
6058 mpz_mul_ui(e->z,*b._ZINTptr,a.val);
6059 return gen(e);
6060 case _ZINT__INT_:
6061 if (b.val==1) return a;
6062 e=new ref_mpz_t(GIAC_MPZ_INIT_SIZE); // (mpz_size(*a._ZINTptr)*mp_bits_per_limb);
6063 if (b.val<0){
6064 mpz_mul_ui(e->z,*a._ZINTptr,-b.val);
6065 mpz_neg(e->z,e->z);
6066 }
6067 else
6068 mpz_mul_ui(e->z,*a._ZINTptr,b.val);
6069 return gen(e);
6070 case _INT___DOUBLE_:
6071 return a.val*b._DOUBLE_val;
6072 case _DOUBLE___INT_:
6073 return a._DOUBLE_val*b.val;
6074 case _INT___FLOAT_:
6075 return giac_float(a.val)*b._FLOAT_val;
6076 case _FLOAT___INT_:
6077 return a._FLOAT_val*giac_float(b.val);
6078 case _DOUBLE___FLOAT_:
6079 return giac_float(a._DOUBLE_val)*b._FLOAT_val;
6080 case _FLOAT___DOUBLE_:
6081 return a._FLOAT_val*giac_float(b._DOUBLE_val);
6082 case _FLOAT___FRAC: case _DOUBLE___FRAC:
6083 return double_times_frac(a,*b._FRACptr,contextptr);
6084 case _FRAC__FLOAT_: case _FRAC__DOUBLE_:
6085 return double_times_frac(b,*a._FRACptr,contextptr);
6086 case _INT___FRAC: case _ZINT__FRAC:
6087 return a*(*b._FRACptr);
6088 case _FRAC__INT_: case _FRAC_ZINT:
6089 return (*a._FRACptr)*b;
6090 case _DOUBLE___ZINT:
6091 return a._DOUBLE_val*mpz_get_d(*b._ZINTptr);
6092 case _DOUBLE___REAL:
6093 return a._DOUBLE_val*real2double(*b._REALptr);
6094 case _REAL__DOUBLE_:
6095 return b._DOUBLE_val*real2double(*a._REALptr);
6096 case _ZINT__DOUBLE_:
6097 return mpz_get_d(*a._ZINTptr)*b._DOUBLE_val;
6098 case _CPLX__INT_:
6099 if (b.val==1) return a;
6100 case _CPLX__ZINT: case _CPLX__DOUBLE_: case _CPLX__FLOAT_: case _CPLX__REAL:
6101 return gen(*a._CPLXptr*b,*(a._CPLXptr+1)*b);
6102 case _INT___CPLX:
6103 return a.val==1?b:gen(a*(*b._CPLXptr),a*(*(b._CPLXptr+1)));
6104 case _ZINT__CPLX: case _DOUBLE___CPLX: case _FLOAT___CPLX: case _REAL__CPLX:
6105 return is_one(a)?b:gen(a*(*b._CPLXptr),a*(*(b._CPLXptr+1)));
6106 case _CPLX__CPLX:
6107 return adjust_complex_display(mult_cplx(a,b,contextptr),a,b);
6108 #if 1 //ndef GIAC_GGB
6109 case _INT___STRNG:{
6110 if (b.subtype==-1) return b;
6111 string res;
6112 for (int i=0;i<a.val;++i)
6113 res += *b._STRNGptr;
6114 return string2gen(res,false);
6115 }
6116 case _STRNG__INT_:{
6117 if (a.subtype==-1) return a;
6118 string res;
6119 for (int i=0;i<b.val;++i)
6120 res += *a._STRNGptr;
6121 return string2gen(res,false);
6122 }
6123 #endif
6124 case _VECT__INT_:
6125 if (b.val>=0 && python_compat(contextptr)==2){
6126 vecteur res;
6127 res.reserve(a._VECTptr->size()*b.val);
6128 const_iterateur it,itend=a._VECTptr->end();
6129 int n=b.val;
6130 for (int i=0;i<n;++i){
6131 for (it=a._VECTptr->begin();it!=itend;++it)
6132 res.push_back(*it);
6133 }
6134 return gen(res,a.subtype);
6135 }
6136 case _VECT__ZINT: case _VECT__DOUBLE_: case _VECT__FLOAT_: case _VECT__CPLX: case _VECT__SYMB: case _VECT__IDNT: case _VECT__POLY: case _VECT__EXT: case _VECT__MOD: case _VECT__FRAC: case _VECT__REAL: {
6137 gen A(a),B(b);
6138 if (A.is_approx() && !is_fully_numeric(B))
6139 B=evalf(b,1,contextptr);
6140 else {
6141 if (B.is_approx() && !is_fully_numeric(A)){
6142 A=evalf(a,1,contextptr);
6143 if (A.type!=_VECT)
6144 A=a;
6145 }
6146 }
6147 // matrix * point -> point
6148 if (B.is_symb_of_sommet(at_pnt)){
6149 gen tmp=complex2vecteur(remove_at_pnt(B),contextptr);
6150 if (ckmatrix(A)){
6151 tmp=multmatvecteur(*A._VECTptr,*tmp._VECTptr);
6152 return _point(tmp,contextptr);
6153 }
6154 if (A._VECTptr->size()==tmp._VECTptr->size())
6155 return dotvecteur(*A._VECTptr,*tmp._VECTptr);
6156 }
6157 if (A.subtype==_VECTOR__VECT && A._VECTptr->size()==2)
6158 return vector2vecteur(*A._VECTptr)*B;
6159 if (A.subtype==_PNT__VECT)
6160 return gen(multfirst(B,*A._VECTptr),_PNT__VECT);
6161 if (A.subtype==_POLY1__VECT){
6162 if (is_zero(B,contextptr))
6163 return B;
6164 //if (b.type==_POLY) return a*(*b._POLYptr);
6165 }
6166 return multgen_poly(B,*A._VECTptr,A.subtype); // gen(multvecteur(b,*a._VECTptr),a.subtype);
6167 }
6168 case _INT___VECT:
6169 if (a.val>=0 && python_compat(contextptr)==2)
6170 return operator_times(b,a,contextptr);
6171 if (warnpy && a.val>=0 && python_compat(contextptr)){
6172 alert(gettext("Python compatibility, integer*list will do vector multiplication, run list*integer to duplicate list"),contextptr);
6173 warnpy=false;
6174 }
6175 case _ZINT__VECT: case _DOUBLE___VECT: case _FLOAT___VECT: case _CPLX__VECT: case _SYMB__VECT: case _IDNT__VECT: case _POLY__VECT: case _EXT__VECT: case _MOD__VECT: case _FRAC__VECT: case _REAL__VECT: {
6176 gen A(a),B(b);
6177 if (A.is_approx() && !is_fully_numeric(B)){
6178 B=evalf(b,1,contextptr);
6179 if (B.type!=_VECT)
6180 B=b;
6181 }
6182 else {
6183 if (B.is_approx() && !is_fully_numeric(A)){
6184 A=evalf(a,1,contextptr);
6185 }
6186 }
6187 if (A.is_symb_of_sommet(at_pnt)){
6188 gen tmp=complex2vecteur(remove_at_pnt(A),contextptr);
6189 if (ckmatrix(B))
6190 return _point(multvecteurmat(*tmp._VECTptr,*B._VECTptr),contextptr);
6191 if (tmp._VECTptr->size()==B._VECTptr->size())
6192 return dotvecteur(*tmp._VECTptr,*B._VECTptr,contextptr);
6193 }
6194 if (B.subtype==_VECTOR__VECT && B._VECTptr->size()==2)
6195 return A*vector2vecteur(*B._VECTptr);
6196 if (B.subtype==_PNT__VECT)
6197 return gen(multfirst(A,*B._VECTptr),_PNT__VECT);
6198 if (B.subtype==_POLY1__VECT){
6199 if (is_zero(A,contextptr))
6200 return A;
6201 // if (a.type==_POLY) return b*(*a._POLYptr);
6202 }
6203 return multgen_poly(A,*B._VECTptr,B.subtype); // gen(multvecteur(a,*b._VECTptr),b.subtype);
6204 }
6205 case _VECT__VECT: {
6206 gen A(a),B(b);
6207 if (A.subtype==_SET__VECT && B.subtype==_SET__VECT){
6208 vecteur res; res.reserve(A._VECTptr->size()*B._VECTptr->size());
6209 const_iterateur at=A._VECTptr->begin(),aend=A._VECTptr->end(),bt=B._VECTptr->begin(),bend=B._VECTptr->end();
6210 for (;at!=aend;++at){
6211 for (bt=B._VECTptr->begin();bt!=bend;++bt){
6212 if (at->type==_VECT && at->subtype==_TUPLE__VECT){
6213 if (bt->type==_VECT && bt->subtype==_TUPLE__VECT){
6214 res.push_back(gen(mergevecteur(*at->_VECTptr,*bt->_VECTptr),_TUPLE__VECT));
6215 }
6216 else {
6217 vecteur tmp(*at->_VECTptr);
6218 tmp.push_back(*bt);
6219 res.push_back(gen(tmp,_TUPLE__VECT));
6220 }
6221 }
6222 else {
6223 if (bt->type==_VECT && bt->subtype==_TUPLE__VECT){
6224 vecteur tmp(*bt->_VECTptr);
6225 tmp.insert(tmp.begin(),*at);
6226 res.push_back(gen(tmp,_TUPLE__VECT));
6227 }
6228 else
6229 res.push_back(gen(makevecteur(*at,*bt),_TUPLE__VECT));
6230 }
6231 }
6232 }
6233 return gen(res,_SET__VECT);
6234 }
6235 // FIXME should not convert 0 in B if A has intervals
6236 if (A.is_approx() && !is_fully_numeric(B)){
6237 bool done=false;
6238 #if defined HAVE_LIBMPFI && !defined NO_RTTI
6239 // workaround for lu e.g. a:=ranm(4,4); b:=convert(a,interval); p,l,u:=lu(b):; l*u;
6240 if (!A._VECTptr->empty() && A._VECTptr->back().type==_VECT && !A._VECTptr->back()._VECTptr->empty() && A._VECTptr->back()._VECTptr->front().type==_REAL){
6241 if (real_interval * ptr=dynamic_cast<real_interval *>(A._VECTptr->back()._VECTptr->front()._REALptr)){
6242 B=convert_interval(b,mpfi_get_prec(ptr->infsup),contextptr);
6243 done=true;
6244 }
6245 }
6246 #endif
6247 if (!done)
6248 B=evalf(b,1,contextptr);
6249 if (B.type!=_VECT)
6250 B=b;
6251 }
6252 else {
6253 if (B.is_approx() && !is_fully_numeric(A)){
6254 A=evalf(a,1,contextptr);
6255 if (A.type!=_VECT)
6256 A=a;
6257 }
6258 }
6259 if (// abs_calc_mode(contextptr)==38 &&
6260 (A.subtype==_MATRIX__VECT ||B.subtype==_MATRIX__VECT) && ckmatrix(A) && ckmatrix(B)){
6261 if (A._VECTptr->front()._VECTptr->size()!=B._VECTptr->size())
6262 return gendimerr(contextptr);
6263 gen res(new ref_vecteur(0),_MATRIX__VECT);
6264 mmult(*A._VECTptr,*B._VECTptr,*res._VECTptr);
6265 return res;
6266 }
6267 if ( (A.subtype==_POLY1__VECT) || (B.subtype==_POLY1__VECT) )
6268 return multgen_poly(*A._VECTptr,*B._VECTptr);
6269 if ( (A.subtype==_LIST__VECT) || (B.subtype==_LIST__VECT) )
6270 return matrix_apply(A,B,contextptr,operator_times);
6271 if (A.subtype==_GGBVECT || (b.subtype==_GGBVECT && !ckmatrix(A))){
6272 gen res=dotvecteur(a,b);
6273 if (res.type==_VECT) res.subtype=_GGBVECT;
6274 return res;
6275 }
6276 { gen res=ckmultmatvecteur(*A._VECTptr,*B._VECTptr,contextptr);
6277 if ( (calc_mode(contextptr)==1 || abs_calc_mode(contextptr)==38) && res.type==_VECT){
6278 res.subtype=B.subtype;
6279 if (res.subtype==0)
6280 res.subtype=A.subtype;
6281 }
6282 return res;
6283 }
6284 }
6285 case _POLY__POLY:
6286 return mulpoly(a,b);
6287 case _FRAC__FRAC:
6288 if (a._FRACptr->num.type==_EXT && b._FRACptr->num.type==_EXT)
6289 return ((*a._FRACptr)*(*b._FRACptr)).normal();
6290 return (*a._FRACptr)*(*b._FRACptr);
6291 case _SPOL1__SPOL1:
6292 return spmul(*a._SPOL1ptr,*b._SPOL1ptr,contextptr);
6293 case _EXT__EXT:
6294 return ext_mul(a,b,contextptr);
6295 case _MAP__MAP:
6296 {
6297 int arows,acols,an,brows,bcols,bn;
6298 if (is_sparse_matrix(a,arows,acols,an) && is_sparse_matrix(b,brows,bcols,bn)){
6299 gen_map res;
6300 gen g(res);
6301 sparse_mult(*a._MAPptr,*b._MAPptr,*g._MAPptr);
6302 return g;
6303 }
6304 }
6305 case _MAP__VECT:
6306 {
6307 int arows,acols,an;
6308 if (is_sparse_matrix(a,arows,acols,an)){
6309 if (acols>b._VECTptr->size())
6310 return gendimerr(contextptr);
6311 if (ckmatrix(b)){
6312 vecteur A;
6313 convert(*a._MAPptr,A);
6314 return A*b;
6315 }
6316 smatrix as;
6317 if (convert(*a._MAPptr,as)){
6318 vecteur res;
6319 sparse_mult(as,*b._VECTptr,res);
6320 return res;
6321 }
6322 gen_map res;
6323 gen g(res);
6324 if (!sparse_mult(*a._MAPptr,*b._VECTptr,*g._MAPptr))
6325 return gendimerr(contextptr);
6326 // Should probably check if g is dense or not
6327 return g;
6328 }
6329 }
6330 case _VECT__MAP:
6331 {
6332 int brows,bcols,an;
6333 if (is_sparse_matrix(b,brows,bcols,an)){
6334 if (brows>a._VECTptr->size())
6335 return gendimerr(contextptr);
6336 if (ckmatrix(a)){
6337 vecteur B;
6338 convert(*b._MAPptr,B);
6339 return a*B;
6340 }
6341 smatrix bs;
6342 if (convert(*b._MAPptr,bs)){
6343 vecteur res;
6344 sparse_mult(*a._VECTptr,bs,res);
6345 return res;
6346 }
6347 gen_map res;
6348 gen g(res);
6349 if (!sparse_mult(*a._VECTptr,*b._MAPptr,*g._MAPptr))
6350 return gendimerr(contextptr);
6351 // Should probably check if g is dense or not
6352 return g;
6353 }
6354 }
6355 case _INT___MAP: case _ZINT__MAP: case _DOUBLE___MAP: case _FLOAT___MAP: case _CPLX__MAP: case _SYMB__MAP: case _IDNT__MAP: case _POLY__MAP: case _EXT__MAP: case _MOD__MAP: case _FRAC__MAP: case _REAL__MAP: {
6356 if (is_one(a))
6357 return b;
6358 int brows,bcols,bn;
6359 if (is_sparse_matrix(b,brows,bcols,bn)){
6360 gen_map res;
6361 gen g(res);
6362 if (is_zero(a))
6363 return g;
6364 *g._MAPptr=*b._MAPptr;
6365 sparse_mult(a,*g._MAPptr);
6366 return g;
6367 }
6368 break;
6369 }
6370 case _POLY__INT_: case _POLY__ZINT: case _POLY__DOUBLE_: case _POLY__FLOAT_: case _POLY__CPLX: case _POLY__USER: case _POLY__REAL:
6371 if (is_one(b))
6372 return a;
6373 return (*a._POLYptr) * b;
6374 case _POLY__MOD:
6375 return (*a._POLYptr) * b;
6376 case _INT___POLY: case _ZINT__POLY: case _DOUBLE___POLY: case _FLOAT___POLY: case _CPLX__POLY: case _USER__POLY: case _REAL__POLY:
6377 if (is_one(a))
6378 return b;
6379 return a * (*b._POLYptr);
6380 case _MOD__POLY:
6381 return a * (*b._POLYptr);
6382 case _MOD__MOD:
6383 #ifdef SMARTPTR64
6384 return modmul( (ref_modulo *) (* ((ulonglong * ) &a) >> 16),(ref_modulo *) (* ((ulonglong * ) &b) >> 16) );
6385 #else
6386 return modmul(a.__MODptr,b.__MODptr);
6387 #endif
6388 case _MOD__INT_: case _MOD__ZINT:
6389 return makemod(*a._MODptr*b,*(a._MODptr+1));
6390 case _INT___MOD: case _ZINT__MOD:
6391 return makemod(*b._MODptr*a,*(b._MODptr+1));
6392 case _REAL__REAL:
6393 return (*a._REALptr)*(*b._REALptr);
6394 default:
6395 if (is_undef(a))
6396 return a;
6397 if (is_undef(b))
6398 return b;
6399 if (a.type==_FLOAT_){
6400 gen b1;
6401 if (has_evalf(b,b1,1,contextptr)&& (b.type!=b1.type || b!=b1))
6402 return a*b1;
6403 return operator_times(evalf_double(a,1,contextptr),b,contextptr);
6404 }
6405 if (b.type==_FLOAT_){
6406 gen a1;
6407 if (has_evalf(a,a1,1,contextptr)&& (a.type!=a1.type || a!=a1))
6408 return a1*b;
6409 return operator_times(a,evalf_double(b,1,contextptr),contextptr);
6410 }
6411 if (a.type==_SPOL1)
6412 return spmul(*a._SPOL1ptr,gen2spol1(b),contextptr);
6413 if (b.type==_SPOL1)
6414 return spmul(gen2spol1(a),*b._SPOL1ptr,contextptr);
6415 if (a.type==_USER)
6416 return (*a._USERptr)*b;
6417 if (b.type==_USER)
6418 return (*b._USERptr)*a;
6419 if (a.type==_REAL)
6420 return a._REALptr->multiply(b,contextptr);
6421 if (b.type==_REAL)
6422 return b._REALptr->multiply(a,contextptr);
6423 if (a.type==_STRNG || b.type==_STRNG)
6424 return gensizeerr(contextptr);
6425 return sym_mult(a,b,contextptr);
6426 }
6427 return undef;
6428 }
6429
operator_times(const gen & a,const gen & b,GIAC_CONTEXT)6430 gen operator_times(const gen & a,const gen & b,GIAC_CONTEXT){
6431 register unsigned t=(a.type<< _DECALAGE) | b.type;
6432 if (!t)
6433 return gen((longlong) a.val*b.val);
6434 return operator_times(a,b,t,contextptr);
6435 }
6436
operator *(const gen & a,const gen & b)6437 gen operator * (const gen & a,const gen & b){
6438 register unsigned t=(a.type<< _DECALAGE) | b.type;
6439 if (!t)
6440 return gen((longlong) a.val*b.val);
6441 return operator_times(a,b,t,context0);
6442 }
6443
has_i(const gen & g)6444 bool has_i(const gen & g){
6445 if (g.type==_CPLX)
6446 return true;
6447 if (g.type==_FRAC)
6448 return g._FRACptr->num.type==_CPLX || g._FRACptr->den.type==_CPLX;
6449 if (g.type==_VECT){
6450 const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
6451 for (;it!=itend;++it){
6452 if (has_i(*it))
6453 return true;
6454 }
6455 return false;
6456 }
6457 if (g.type==_SPOL1){
6458 sparse_poly1::const_iterator it=g._SPOL1ptr->begin(),itend=g._SPOL1ptr->end();
6459 for (;it!=itend;++it){
6460 if (has_i(it->coeff))
6461 return true;
6462 }
6463 return false;
6464 }
6465 if (g.type==_EXT)
6466 return has_i(*g._EXTptr);
6467 if (g.type!=_SYMB)
6468 return false;
6469 return has_i(g._SYMBptr->feuille);
6470 }
6471
giac_pow(const gen & base,const gen & exponent,GIAC_CONTEXT)6472 gen giac_pow(const gen & base,const gen & exponent,GIAC_CONTEXT){
6473 return pow(base,exponent,contextptr);
6474 }
6475
6476 // (-1)^n
minus1pow(const gen & exponent,GIAC_CONTEXT,bool allow_recursion=true)6477 static gen minus1pow(const gen & exponent,GIAC_CONTEXT,bool allow_recursion=true){
6478 if (exponent.type==_INT_)
6479 return (exponent.val%2)?-1:1;
6480 if (exponent.type==_ZINT){
6481 gen q,g=irem(exponent,2,q);
6482 if (is_zero(g,contextptr))
6483 return 1;
6484 return -1;
6485 }
6486 if (is_inf(exponent))
6487 return undef;
6488 if (is_undef(exponent))
6489 return exponent;
6490 if (exponent.is_symb_of_sommet(at_neg)){
6491 gen tmp=minus1pow(exponent._SYMBptr->feuille,contextptr);
6492 if (is_assumed_integer(exponent,contextptr))
6493 return tmp;
6494 //else return symb_inv(tmp);
6495 }
6496 if (exponent.is_symb_of_sommet(at_plus)){
6497 gen res(1);
6498 gen & f=exponent._SYMBptr->feuille;
6499 if (f.type!=_VECT)
6500 return minus1pow(f,contextptr);
6501 vecteur & v = *f._VECTptr;
6502 int s=int(v.size());
6503 for (int i=0;i<s;++i)
6504 res = res * minus1pow(v[i],contextptr);
6505 return res;
6506 }
6507 if (exponent.is_symb_of_sommet(at_prod)){
6508 gen & f =exponent._SYMBptr->feuille;
6509 if (f.type==_VECT){
6510 vecteur & v = *f._VECTptr;
6511 int i,s=int(v.size());
6512 bool even=false,perhapsone=true;
6513 gen num=1,den=1;
6514 for (i=0;i<s;++i){
6515 if (v[i].is_symb_of_sommet(at_inv))
6516 den=den*v[i]._SYMBptr->feuille;
6517 else
6518 num=num*v[i];
6519 if (is_integer(v[i]) && is_zero(smod(v[i],2),contextptr))
6520 even=true;
6521 if (!is_assumed_integer(v[i],contextptr))
6522 perhapsone=false;
6523 }
6524 #ifndef NO_STDEXCEPT
6525 if (allow_recursion && perhapsone){
6526 gen num1=undef;
6527 try {
6528 num1=_irem(makesequence(num,2*den),contextptr);
6529 } catch (std::runtime_error & err){
6530 num1=undef;
6531 }
6532 if (!is_undef(num1) && num1!=num) return minus1pow(symb_prod(num1,symb_inv(den)),contextptr,false);
6533 }
6534 #endif
6535 if (even && perhapsone)
6536 return 1;
6537 if (num.type==_INT_ && den.type==_INT_ && den.val<=MAX_ALG_EXT_ORDER_SIZE){
6538 return exp(cst_i*exponent*cst_pi,contextptr);
6539 }
6540 }
6541 }
6542 return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(-1,exponent),_SEQ__VECT)));
6543 }
6544
pow_iterative(const gen & base,const gen & exponent,GIAC_CONTEXT)6545 static gen pow_iterative(const gen & base,const gen & exponent,GIAC_CONTEXT){
6546 if (is_positive(-exponent,contextptr))
6547 return pow_iterative(inv(base,contextptr),-exponent,contextptr);
6548 gen res=1,expo=exponent;
6549 gen basepow=base;
6550 while (!is_zero(expo)){
6551 gen q,r=irem(expo,2,q);
6552 if (!is_zero(r))
6553 res = res*basepow;
6554 expo=q;
6555 if ( !is_zero(expo) )
6556 basepow=basepow*basepow;
6557 }
6558 return res;
6559 }
6560
pow(const gen & base,const gen & exponent,GIAC_CONTEXT)6561 gen pow(const gen & base,const gen & exponent,GIAC_CONTEXT){
6562 // if (!( (++control_c_counter) & control_c_counter_mask))
6563 #ifdef TIMEOUT
6564 control_c();
6565 #endif
6566 if (ctrl_c || interrupted) {
6567 interrupted = true; ctrl_c=false;
6568 return gensizeerr(gettext("Stopped by user interruption."));
6569 }
6570 if (exponent.type==_INT_){
6571 if (exponent.val==1) return base;
6572 if (exponent.val==2 && base.type<=_CPLX){
6573 if (base.type==_CPLX && base.subtype==3){
6574 double a=base._CPLXptr->_DOUBLE_val,b=(base._CPLXptr+1)->_DOUBLE_val;
6575 return gen(a*a-b*b,2.0*a*b);
6576 }
6577 return operator_times(base,base,contextptr);
6578 }
6579 }
6580 if (is_undef(base))
6581 return base;
6582 if (is_undef(exponent))
6583 return exponent;
6584 {
6585 gen a,b;
6586 if (is_algebraic_program(base,a,b))
6587 return symbolic(at_program,gen(makevecteur(a,0,pow(b,exponent,contextptr)),_SEQ__VECT));
6588 if (is_algebraic_program(exponent,a,b))
6589 return symbolic(at_program,gen(makevecteur(a,0,pow(base,b,contextptr)),_SEQ__VECT));
6590 }
6591 if (base.type==_VECT && base.subtype!=_POLY1__VECT && !is_squarematrix(base)){
6592 *logptr(contextptr) << gettext("Warning, ^ is ambiguous on non square matrices. Use .^ to apply ^ element by element.") << '\n';
6593 if (exponent.type==_VECT)
6594 return apply(base,exponent,contextptr,giac_pow);
6595 if (base.subtype!=_LIST__VECT && (exponent.type==_INT_ && exponent.val %2==0) )
6596 return pow(dotvecteur(*base._VECTptr,*base._VECTptr,contextptr),exponent.val/2,contextptr);
6597 return apply1st(base,exponent,contextptr,&giac_pow);
6598 }
6599 if (exponent.type==_VECT)
6600 return apply2nd(base,exponent,contextptr,&giac_pow);
6601 if (exponent.type==_FRAC){
6602 if (base.type<_POLY || base.type==_FLOAT_){
6603 if (exponent==plus_one_half)
6604 return sqrt(base,contextptr);
6605 if (exponent==minus_one_half)
6606 return inv(sqrt(base,contextptr),contextptr);
6607 }
6608 if (exponent._FRACptr->num==1 && exponent._FRACptr->den==2 && base.type==_SYMB){
6609 vecteur v=lvar(base);
6610 if (v.size()==1 && v.front().is_symb_of_sommet(at_pow) && v.front()._SYMBptr->feuille[1]==plus_one_half && is_integer(v.front()._SYMBptr->feuille[0])){
6611 gen a,b,c=v.front()._SYMBptr->feuille[0];
6612 if (is_linear_wrt(base,v.front(),b,a,contextptr) && (is_integer(a) ||a.type==_FRAC) && (is_integer(b) || b.type==_FRAC)){
6613 gen d=a*a-b*b*c;
6614 if (is_positive(d,contextptr)){
6615 d=sqrt(d,contextptr);
6616 if (is_integer(d) || d.type==_FRAC){
6617 return sqrt((a+d)/2,contextptr)+sign(b,contextptr)*sqrt((a-d)/2,contextptr);
6618 }
6619 }
6620 }
6621 }
6622 }
6623 return pow(base,new_ref_symbolic(symbolic(at_prod,makesequence(exponent._FRACptr->num,symb_inv(exponent._FRACptr->den)))),contextptr);
6624 }
6625 if (is_inf(base)){
6626 if (is_zero(exponent,contextptr))
6627 return undef;
6628 if (exponent==plus_inf){
6629 if (base==plus_inf)
6630 return base;
6631 return unsigned_inf;
6632 }
6633 if (exponent==minus_inf)
6634 return 0;
6635 gen d;
6636 bool b=has_evalf(exponent,d,1,contextptr);
6637 if (b && is_strictly_positive(-exponent,contextptr) )
6638 return 0;
6639 if (b && base==plus_inf &&is_strictly_positive(exponent,contextptr))
6640 return plus_inf;
6641 if ( (exponent.type==_INT_) ){
6642 if (exponent.val % 2)
6643 return base;
6644 else
6645 return plus_inf; // for unsigned_inf in _DOUBLE_ mode only!!
6646 }
6647 if (b && is_strictly_positive(exponent,contextptr))
6648 return unsigned_inf;
6649 return undef;
6650 }
6651 if (base.type==_SYMB){
6652 unary_function_ptr & u =base._SYMBptr->sommet;
6653 if (u==at_unit){
6654 vecteur & v=*base._SYMBptr->feuille._VECTptr;
6655 gen v1=v[1];
6656 vecteur w;
6657 if (v1.is_symb_of_sommet(at_prod))
6658 w=gen2vecteur(v1._SYMBptr->feuille);
6659 else
6660 w.push_back(v1);
6661 for (unsigned i=0;i<w.size();++i){
6662 gen & v1=w[i];
6663 if (v1.is_symb_of_sommet(at_pow))
6664 v1=pow(v1._SYMBptr->feuille[0],v1._SYMBptr->feuille[1]*exponent,contextptr);
6665 else
6666 v1=pow(v1,exponent,contextptr);
6667 }
6668 if (w.size()==1) v1=w.front(); else v1=symbolic(at_prod,gen(w,_SEQ__VECT));
6669 return new_ref_symbolic(symbolic(at_unit,makenewvecteur(pow(v[0],exponent,contextptr),v1)));
6670 }
6671 if (u==at_abs && exponent.type==_INT_ && !complex_mode(contextptr) && !has_i(base)){
6672 int n=exponent.val,m;
6673 if (n<0 && n%2)
6674 m=n-1;
6675 else
6676 m=(n/2)*2; // or m=n%2?n-1:n;
6677 gen basep=pow(base._SYMBptr->feuille,m);
6678 if (n%2)
6679 return base*basep;
6680 else
6681 return basep;
6682 }
6683 if (u==at_pnt && exponent.type==_INT_ && exponent.val%2==0){
6684 return pow(abs_norm2(remove_at_pnt(base),contextptr),exponent.val/2,contextptr);
6685 }
6686 if (u==at_sign && exponent.type==_INT_ && !complex_mode(contextptr) && !has_i(base)){
6687 int n=exponent.val;
6688 if (n%2)
6689 return base;
6690 else
6691 return 1;
6692 }
6693 if (u==at_exp){
6694 // (e^a)^b=e^(a*b)
6695 // but we keep (e^a)^b if b is integer and e^(a*b) is not simplified
6696 // for rational dependance
6697 gen res=exp(base._SYMBptr->feuille*exponent,contextptr);
6698 if (exponent.type!=_INT_ || !res.is_symb_of_sommet(at_exp))
6699 return res;
6700 }
6701 if (u==at_inv && base._SYMBptr->feuille.type==_SYMB && (base._SYMBptr->feuille._SYMBptr->sommet==at_exp ||base._SYMBptr->feuille._SYMBptr->sommet==at_pow))
6702 return inv(pow(base._SYMBptr->feuille,exponent,contextptr),contextptr);
6703 if (u==at_pow && !has_i(base)){
6704 vecteur & v=*base._SYMBptr->feuille._VECTptr;
6705 gen & v1=v[1];
6706 gen new_exp=v1*exponent;
6707 if (new_exp.type>_IDNT)
6708 new_exp=normal(new_exp,contextptr);
6709 if ( v1.type==_INT_ && v1.val%2==0
6710 && (new_exp.type!=_INT_ || new_exp.val%2 )
6711 && !complex_mode(contextptr) )
6712 return pow(abs(v[0],contextptr),new_exp,contextptr);
6713 else
6714 return pow(v[0],new_exp,contextptr);
6715 }
6716 if (u==at_equal || u==at_equal2){
6717 vecteur & vb=*base._SYMBptr->feuille._VECTptr;
6718 return new_ref_symbolic(symbolic(base._SYMBptr->sommet,makesequence(pow(vb.front(),exponent,contextptr),pow(vb.back(),exponent,contextptr))));
6719 }
6720 if (exponent.type==_INT_){
6721 if (exponent.val==0)
6722 return 1;
6723 if (exponent.val==1)
6724 return base;
6725 return new_ref_symbolic(symbolic(at_pow,gen(makevecteur(base,exponent),_SEQ__VECT)));
6726 }
6727 }
6728 if (abs_calc_mode(contextptr)==38 && !complex_mode(contextptr) && is_exactly_zero(base) && is_exactly_zero(exponent)) // was is_zero(,.contextptr) changed so that MINREAL^0 is not undef but 1
6729 return undef;
6730 switch ( (base.type<< _DECALAGE) | exponent.type ) {
6731 case _INT___INT_: case _ZINT__INT_: case _REAL__INT_: case _CPLX__INT_: case _IDNT__INT_:
6732 return pow(base,exponent.val);
6733 case _DOUBLE___DOUBLE_:
6734 if (exponent._DOUBLE_val==int(std::floor(exponent._DOUBLE_val+.25)))
6735 return pow(base,int(std::floor(exponent._DOUBLE_val+.25)));
6736 if (base._DOUBLE_val>=0)
6737 #ifdef _SOFTMATH_H
6738 return std::giac_gnuwince_pow(base._DOUBLE_val,exponent._DOUBLE_val);
6739 #else
6740 return std::pow(base._DOUBLE_val,exponent._DOUBLE_val);
6741 #endif
6742 else
6743 return exp(exponent*log(base,contextptr),contextptr);
6744 case _FRAC__DOUBLE_:
6745 return exp(exponent*log(base,contextptr),contextptr);
6746 case _FLOAT___FLOAT_:
6747 if (exponent._FLOAT_val==get_int(exponent._FLOAT_val))
6748 return pow(base,get_int(exponent._FLOAT_val));
6749 if (is_strictly_positive(-base,contextptr))
6750 return exp(exponent*ln(base,contextptr),contextptr);
6751 return fpow(base._FLOAT_val,exponent._FLOAT_val);
6752 case _INT___FLOAT_:
6753 if (exponent._FLOAT_val==get_int(exponent._FLOAT_val))
6754 return pow(base,get_int(exponent._FLOAT_val));
6755 if (is_strictly_positive(-base,contextptr))
6756 return exp(exponent*ln(base,contextptr),contextptr);
6757 return fpow(giac_float(base.val),exponent._FLOAT_val);
6758 case _FLOAT___INT_:
6759 return fpow(base._FLOAT_val,giac_float(exponent.val));
6760 case _DOUBLE___INT_:
6761 if (base._DOUBLE_val>=0)
6762 #ifdef _SOFTMATH_H
6763 return std::giac_gnuwince_pow(base._DOUBLE_val,exponent.val);
6764 #else
6765 return std::pow(base._DOUBLE_val,exponent.val);
6766 #endif
6767 else
6768 return (exponent.val%2?-1:1)*std::pow(-base._DOUBLE_val,exponent.val);//exp(exponent*log(-base,contextptr),contextptr);
6769 case _INT___DOUBLE_:
6770 #ifdef _SOFTMATH_H
6771 return std::giac_gnuwince_pow(base.val,exponent._DOUBLE_val);
6772 #else
6773 return std::pow(double(base.val),exponent._DOUBLE_val);
6774 #endif
6775 case _ZINT__DOUBLE_:
6776 #ifdef _SOFTMATH_H
6777 return std::giac_gnuwince_pow(mpz_get_d(*base._ZINTptr),exponent._DOUBLE_val);
6778 #else
6779 return std::pow(mpz_get_d(*base._ZINTptr),exponent._DOUBLE_val);
6780 #endif
6781 case _DOUBLE___ZINT:
6782 if (base._DOUBLE_val>=0)
6783 #ifdef _SOFTMATH_H
6784 return std::giac_gnuwince_pow(base._DOUBLE_val,mpz_get_d(*exponent._ZINTptr));
6785 #else
6786 return std::pow(base._DOUBLE_val,mpz_get_d(*exponent._ZINTptr));
6787 #endif
6788 else
6789 return exp(exponent*log(base,contextptr),contextptr);
6790 case _POLY__INT_:
6791 if (exponent.val<0)
6792 return fraction(1,pow(*base._POLYptr,-exponent.val));
6793 else
6794 return pow(*base._POLYptr,exponent.val);
6795 case _MAP__INT_:
6796 if (exponent.val>=0)
6797 return pow(base,exponent.val);
6798 case _FRAC__INT_:
6799 return pow(*base._FRACptr,exponent.val);
6800 case _EXT__INT_: case _MOD__INT_: case _VECT__INT_: case _USER__INT_:
6801 return pow(base,exponent.val);
6802 case _MOD__ZINT:
6803 return makemod(powmod(*base._MODptr,exponent,*(base._MODptr+1)),*(base._MODptr+1));
6804 default:
6805 if (is_undef(base))
6806 return base;
6807 if (is_undef(exponent))
6808 return exponent;
6809 if (base.type==_STRNG || exponent.type==_STRNG)
6810 return gensizeerr(contextptr);
6811 if (is_one(base) && !is_inf(exponent))
6812 return base;
6813 if (exponent.is_symb_of_sommet(at_prod) && exponent._SYMBptr->feuille.type==_VECT && exponent._SYMBptr->feuille._VECTptr->size()==2){
6814 gen e1=exponent._SYMBptr->feuille._VECTptr->front();
6815 gen e2=exponent._SYMBptr->feuille._VECTptr->back();
6816 if (e1.is_symb_of_sommet(at_ln) && e2.is_symb_of_sommet(at_inv) && e2._SYMBptr->feuille.is_symb_of_sommet(at_ln) && base==e2._SYMBptr->feuille._SYMBptr->feuille)
6817 return e1._SYMBptr->feuille;
6818 }
6819 if (is_squarematrix(base)){
6820 if ((exponent.type==_REAL || exponent.type==_DOUBLE_ || exponent.type==_FLOAT_))
6821 return matpow(*base._VECTptr,exponent,contextptr);
6822 if (exponent.type>=_IDNT)
6823 *logptr(contextptr) << gettext("Use matpow to force computation of a power of matrix via jordanisation") << '\n';
6824 }
6825 if (base.type==_REAL || base.type==_DOUBLE_ ||
6826 (base.type==_CPLX
6827 // && base.subtype==3
6828 )
6829 || base.type==_FLOAT_ || ( (base.type<_POLY || base.type==_FLOAT_) && (exponent.type==_REAL || exponent.type==_DOUBLE_ || exponent.type==_FLOAT_)))
6830 return exp(exponent*log(base,contextptr),contextptr);
6831 /*
6832 if (base.is_symb_of_sommet(at_neg))
6833 return minus1pow(exponent)*pow(base._SYMBptr->feuille,exponent);
6834 */
6835 if ((base.type==_INT_) && (base.val<0)){
6836 if (exponent==plus_one_half)
6837 return cst_i*sqrt(-base.val,contextptr);
6838 // if (exponent==-one_half)
6839 // return rdiv(cst_i,sqrt(-base.val));
6840 }
6841 if (is_exactly_zero(base)){
6842 gen d;
6843 #if 1
6844 // 0^k should return 0 if k is assumed to be positive
6845 d=sign(exponent,contextptr);
6846 if (is_one(d))
6847 return base;
6848 if (is_minus_one(d))
6849 return unsigned_inf;
6850 #else
6851 bool b=has_evalf(exponent,d,1,contextptr);
6852 if (b && is_positive(exponent,contextptr))
6853 return base;
6854 if (b && is_positive(-exponent,contextptr))
6855 return unsigned_inf;
6856 #endif
6857 return undef;
6858 }
6859 if (base.type==_SPOL1)
6860 return sppow(*base._SPOL1ptr,exponent,contextptr);
6861 if (is_integer(base) && is_positive(-base,contextptr)){
6862 #if 0
6863 if (abs_calc_mode(contextptr)==38 && !complex_mode(contextptr))
6864 return gensizeerr(gettext("Negative to a fractional power"));
6865 #endif
6866 return minus1pow(exponent,contextptr)*pow(-base,exponent,contextptr);
6867 }
6868 if (is_inf(exponent)){
6869 if (base.type==_VECT)
6870 return gensizeerr(contextptr);
6871 return exp(exponent*ln(base,contextptr),contextptr);
6872 }
6873 // extract integral powers in a product exponent
6874 if ((exponent.type==_SYMB) && (exponent._SYMBptr->sommet==at_prod)){
6875 gen subexponent_num(1),subexponent_deno(1);
6876 gen superexponent(1);
6877 const_iterateur it=exponent._SYMBptr->feuille._VECTptr->begin(),itend=exponent._SYMBptr->feuille._VECTptr->end();
6878 for (;it!=itend;++it){
6879 if (it->type==_INT_){
6880 superexponent = superexponent * (*it);
6881 continue;
6882 }
6883 if ( (it->type==_SYMB) && (it->_SYMBptr->sommet==at_inv))
6884 subexponent_deno = subexponent_deno * (it->_SYMBptr->feuille);
6885 else
6886 subexponent_num = subexponent_num * (*it);
6887 }
6888 if (superexponent.type!=_INT_
6889 || (!lidnt(exponent).empty() && absint(superexponent.val)>MAX_COMMON_ALG_EXT_ORDER_SIZE)
6890 )
6891 return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,exponent),_SEQ__VECT)));
6892 if (subexponent_deno.type!=_INT_){
6893 if (is_one(superexponent))
6894 return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,_FRAC2_SYMB(subexponent_num,subexponent_deno)),_SEQ__VECT)));
6895 return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,_FRAC2_SYMB(subexponent_num,subexponent_deno)),_SEQ__VECT))),superexponent),_SEQ__VECT)));
6896 }
6897 int q=superexponent.val / subexponent_deno.val;
6898 int r=superexponent.val % subexponent_deno.val;
6899 gen res(1);
6900 if (r){
6901 if (complex_mode(contextptr) && fastsign(base,contextptr)==-1){ // is_strictly_positive(-base,contextptr)){
6902 gen base1=-base;
6903 res=exp((cst_i*cst_pi*subexponent_num)/subexponent_deno,contextptr);
6904 res=new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(pow(base1,subexponent_num,contextptr),inv(subexponent_deno,contextptr)),_SEQ__VECT)))*res;
6905 }
6906 else
6907 res=new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(pow(base,subexponent_num,contextptr),inv(subexponent_deno,contextptr)),_SEQ__VECT)));
6908 if (r!=1)
6909 res=new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(res,r),_SEQ__VECT)));
6910 }
6911 if (!q)
6912 return res;
6913 if (q==1){
6914 if (is_one(subexponent_num))
6915 return res*base;
6916 return res*new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,subexponent_num),_SEQ__VECT)));
6917 }
6918 if (q==-1)
6919 return res*inv(pow(base,subexponent_num,contextptr),contextptr);
6920 return res*new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(pow(base,subexponent_num,contextptr),q),_SEQ__VECT)));
6921 }
6922 gen var1,var2,res1,res2;
6923 if (is_algebraic_program(base,var1,res1) && is_algebraic_program(exponent,var2,res2)){
6924 if (var1!=var2 && is_constant_wrt(res2,var1,contextptr)){
6925 res2=subst(res2,var2,var1,false,contextptr);
6926 var2=var1;
6927 }
6928 if (var1==var2)
6929 return symbolic(at_program,gen(makevecteur(var1,0,pow(res1,res2,contextptr)),_SEQ__VECT));
6930 }
6931 if (exponent.type==_ZINT){
6932 if (base.type==_USER)
6933 return pow_iterative(base,exponent,contextptr);
6934 return exp(exponent*log(base,contextptr),contextptr);
6935 }
6936 return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,exponent),_SEQ__VECT)));
6937 }
6938 }
6939
sym_mult(const gen & a,const gen & b,GIAC_CONTEXT)6940 gen sym_mult(const gen & a,const gen & b,GIAC_CONTEXT){
6941 #ifdef TIMEOUT
6942 control_c();
6943 #endif
6944 if (ctrl_c || interrupted) {
6945 interrupted = true; ctrl_c=false;
6946 return gensizeerr(gettext("Stopped by user interruption."));
6947 }
6948 if (is_undef(a))
6949 return a;
6950 if (is_undef(b))
6951 return b;
6952 if (is_inequality(a) && !is_equal(a)){
6953 int bs=fastsign(b,contextptr);
6954 if (bs==-1)
6955 return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(a._SYMBptr->feuille._VECTptr->back()*b,a._SYMBptr->feuille._VECTptr->front()*b)));
6956 if (bs==1)
6957 return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(a._SYMBptr->feuille._VECTptr->front()*b,a._SYMBptr->feuille._VECTptr->back()*b)));
6958 }
6959 if (is_inequality(b) && !is_equal(b)){
6960 int bs=fastsign(a,contextptr);
6961 if (bs==-1)
6962 return new_ref_symbolic(symbolic(b._SYMBptr->sommet,makesequence(a*b._SYMBptr->feuille._VECTptr->back(),a*b._SYMBptr->feuille._VECTptr->front())));
6963 if (bs==1)
6964 return new_ref_symbolic(symbolic(b._SYMBptr->sommet,makesequence(a*b._SYMBptr->feuille._VECTptr->front(),a*b._SYMBptr->feuille._VECTptr->back())));
6965 }
6966 if (a.is_symb_of_sommet(at_unit)){
6967 if (equalposcomp(lidnt(b),cst_pi)!=0)
6968 return sym_mult(a,evalf(b,1,contextptr),contextptr);
6969 vecteur & va=*a._SYMBptr->feuille._VECTptr;
6970 if (b.is_symb_of_sommet(at_unit)){
6971 vecteur & v=*b._SYMBptr->feuille._VECTptr;
6972 gen res=va[1]*v[1];
6973 res=ratnormal(res,contextptr);
6974 if (is_one(res))
6975 return va[0]*v[0];
6976 return new_ref_symbolic(symbolic(at_unit,makenewvecteur(operator_times(va[0],v[0],contextptr),res)));
6977 }
6978 else {
6979 if (lidnt(b).empty())
6980 return new_ref_symbolic(symbolic(at_unit,makenewvecteur(operator_times(va[0],b,contextptr),va[1])));
6981 }
6982 }
6983 if (b.is_symb_of_sommet(at_unit)){
6984 if (equalposcomp(lidnt(a),cst_pi)!=0)
6985 return sym_mult(evalf(a,1,contextptr),b,contextptr);
6986 if (lidnt(a).empty()){
6987 vecteur & v=*b._SYMBptr->feuille._VECTptr;
6988 return new_ref_symbolic(symbolic(at_unit,makenewvecteur(operator_times(a,v[0],contextptr),v[1])));
6989 }
6990 }
6991 gen var1,var2,res1,res2;
6992 if (is_algebraic_program(a,var1,res1)){
6993 if (is_algebraic_program(b,var2,res2)){
6994 if (var1!=var2 && is_constant_wrt(res2,var1,contextptr)){
6995 res2=subst(res2,var2,var1,false,contextptr);
6996 var2=var1;
6997 }
6998 if (var1==var2)
6999 return symbolic(at_program,gen(makevecteur(var1,0,operator_times(res1,res2,contextptr)),_SEQ__VECT));
7000 }
7001 if (!is_constant_wrt(b,var1,contextptr))
7002 *logptr(contextptr) << "Warning function*constant with constant dependant of mute variable" << '\n';
7003 return symbolic(at_program,gen(makevecteur(var1,0,operator_times(res1,b,contextptr)),_SEQ__VECT));
7004 }
7005 if (is_algebraic_program(b,var2,res2)){
7006 if (!is_constant_wrt(a,var2,contextptr))
7007 *logptr(contextptr) << "Warning constant*function with constant dependant of mute variable" << '\n';
7008 return symbolic(at_program,gen(makevecteur(var2,0,operator_times(a,res2,contextptr)),_SEQ__VECT));
7009 }
7010 if (is_inf(a)){
7011 if (is_exactly_zero(normal(b,contextptr)))
7012 return undef;
7013 int s=fastsign(a,contextptr)*fastsign(b,contextptr);
7014 if (s==1)
7015 return plus_inf;
7016 if (s)
7017 return minus_inf;
7018 return unsigned_inf;
7019 }
7020 if (is_inf(b)){
7021 if (is_exactly_zero(normal(a,contextptr)))
7022 return undef;
7023 int s=fastsign(a,contextptr)*fastsign(b,contextptr);
7024 if (s==1)
7025 return plus_inf;
7026 if (s)
7027 return minus_inf;
7028 return unsigned_inf;
7029 }
7030 if (a.type==_INT_ && a.val==0 )
7031 return a;
7032 if (a.type==_DOUBLE_ && a._DOUBLE_val==0 )
7033 return a;
7034 if (a.type==_FLOAT_ && is_zero(a._FLOAT_val) )
7035 return a;
7036 if (b.type==_INT_ && b.val==0)
7037 return b;
7038 if (b.type==_DOUBLE_ && b._DOUBLE_val==0 )
7039 return b;
7040 if (b.type==_FLOAT_ && is_zero(b._FLOAT_val) )
7041 return b;
7042 if ( a.is_approx()){
7043 gen b1;
7044 if (has_evalf(b,b1,1,contextptr)&& (b.type!=b1.type || b!=b1)){
7045 #ifdef HAVE_LIBMPFR
7046 if (a.type==_REAL){
7047 gen b2;
7048 #if defined HAVE_LIBMPFI && !defined NO_RTTI
7049 if (real_interval * ptr=dynamic_cast<real_interval *>(a._REALptr))
7050 b2=convert_interval(b,mpfi_get_prec(ptr->infsup),contextptr);
7051 else
7052 #endif
7053 b2=accurate_evalf(b,mpfr_get_prec(a._REALptr->inf));
7054 if (b2.is_approx())
7055 return (*a._REALptr)*b2;
7056 }
7057 if (a.type==_CPLX && a._CPLXptr->type==_REAL){
7058 gen b2;
7059 #if defined HAVE_LIBMPFI && !defined NO_RTTI
7060 if (real_interval * ptr=dynamic_cast<real_interval *>(a._CPLXptr->_REALptr))
7061 b2=convert_interval(b,mpfi_get_prec(ptr->infsup),contextptr);
7062 else
7063 #endif
7064 b2=accurate_evalf(b,mpfr_get_prec(a._CPLXptr->_REALptr->inf));
7065 if (b2.is_approx())
7066 return a*b2;
7067 }
7068 #endif
7069 return a*b1;
7070 }
7071 }
7072 if ( b.is_approx()){
7073 gen a1;
7074 if (has_evalf(a,a1,1,contextptr) && (a.type!=a1.type || a!=a1)){
7075 #ifdef HAVE_LIBMPFR
7076 if (b.type==_REAL){
7077 gen a2;
7078 #if defined HAVE_LIBMPFI && !defined NO_RTTI
7079 if (real_interval * ptr=dynamic_cast<real_interval *>(b._REALptr))
7080 a2=convert_interval(a,mpfi_get_prec(ptr->infsup),contextptr);
7081 else
7082 #endif
7083 a2=accurate_evalf(a,mpfr_get_prec(b._REALptr->inf));
7084 if (a2.is_approx())
7085 return a2*b;
7086 }
7087 if (b.type==_CPLX && b._CPLXptr->type==_REAL){
7088 gen a2;
7089 #if defined HAVE_LIBMPFI && !defined NO_RTTI
7090 if (real_interval * ptr=dynamic_cast<real_interval *>(b._CPLXptr->_REALptr))
7091 a2=convert_interval(a,mpfi_get_prec(ptr->infsup),contextptr);
7092 else
7093 #endif
7094 a2=accurate_evalf(a,mpfr_get_prec(b._CPLXptr->_REALptr->inf));
7095 if (a2.is_approx())
7096 return a2*b;
7097 }
7098 #endif
7099 return a1*b;
7100 }
7101 }
7102 if (is_one(a) && ((a.type!=_MOD) || (b.type==_MOD) ))
7103 return b;
7104 if (is_one(b) && ((b.type!=_MOD) || (a.type==_MOD) ))
7105 return a;
7106 if ((a.type==_SYMB) && equalposcomp(plot_sommets,a._SYMBptr->sommet)){
7107 gen tmp=remove_at_pnt(a);
7108 if (tmp.type==_VECT && tmp.subtype==_VECTOR__VECT){
7109 if (b.type==_SYMB && equalposcomp(plot_sommets,b._SYMBptr->sommet)){
7110 gen tmpb=remove_at_pnt(b);
7111 return dotvecteur(vector2vecteur(*tmp._VECTptr),vector2vecteur(*tmpb._VECTptr));
7112 }
7113 return _vector(vector2vecteur(*tmp._VECTptr)*b,contextptr);
7114 }
7115 if ((b.type==_SYMB) && equalposcomp(plot_sommets,b._SYMBptr->sommet)){
7116 gen tmpb=complex2vecteur(remove_at_pnt(b),contextptr);
7117 tmp=complex2vecteur(tmp,contextptr);
7118 if (tmpb._VECTptr->size()==tmp._VECTptr->size())
7119 return dotvecteur(*tmp._VECTptr,*tmpb._VECTptr,contextptr);
7120 return gensizeerr(gettext("Unable to multiply two graphic objects"));
7121 }
7122 return symbolic_plot_makevecteur(a._SYMBptr->sommet,a._SYMBptr->feuille*b,false,contextptr);
7123 }
7124 if ((b.type==_SYMB) && equalposcomp(plot_sommets,b._SYMBptr->sommet)){
7125 gen tmp=remove_at_pnt(b);
7126 if (tmp.type==_VECT && tmp.subtype==_VECTOR__VECT)
7127 return _vector(a*vector2vecteur(*tmp._VECTptr),contextptr);
7128 gen b_(b);
7129 if (b_.is_symb_of_sommet(at_curve) && b_._SYMBptr->feuille.type==_VECT && b_._SYMBptr->feuille._VECTptr->size()==2 && b_._SYMBptr->feuille._VECTptr->front().type==_VECT){
7130 // adjust param and cartesian eq
7131 vecteur v=*b_._SYMBptr->feuille._VECTptr->front()._VECTptr;
7132 if (v.size()==7)
7133 v[6] =v[6]*a;
7134 if (v.size()>=6){
7135 gen ax,ay;
7136 reim(inv(a,contextptr),ax,ay,contextptr);
7137 v[5]=subst(v[5],makevecteur(x__IDNT_e,y__IDNT_e),makevecteur(ax*x__IDNT_e-ay*y__IDNT_e,ax*y__IDNT_e+ay*x__IDNT_e),false,contextptr);
7138 b_=symbolic(at_curve,gen(makevecteur(gen(v,b_._SYMBptr->feuille._VECTptr->front().subtype),b_._SYMBptr->feuille._VECTptr->back()),b_._SYMBptr->feuille.subtype));
7139 }
7140 }
7141 return symbolic_plot_makevecteur(b_._SYMBptr->sommet,b_._SYMBptr->feuille*a,false,contextptr);
7142 }
7143 if (a.is_symb_of_sommet(at_neg)){
7144 if (b.is_symb_of_sommet(at_neg))
7145 return operator_times(a._SYMBptr->feuille,b._SYMBptr->feuille,contextptr);
7146 return -operator_times(a._SYMBptr->feuille,b,contextptr);
7147 }
7148 if (b.is_symb_of_sommet(at_neg))
7149 return -operator_times(a,b._SYMBptr->feuille,contextptr);
7150 if (a.type==_FRAC){
7151 if (b.is_symb_of_sommet(at_inv) && is_cinteger(b._SYMBptr->feuille))
7152 return (*a._FRACptr)*fraction(1,b._SYMBptr->feuille);
7153 if ( (b.type!=_SYMB) && (b.type!=_IDNT) ) {
7154 if (b.type==_EXT)
7155 return fraction(a._FRACptr->num*b,a._FRACptr->den).normal();
7156 return (*a._FRACptr)*b;
7157 }
7158 return sym_mult(_FRAC2_SYMB(a),b,contextptr);
7159 }
7160 if (b.type==_FRAC){
7161 if (a.is_symb_of_sommet(at_inv) && is_cinteger(a._SYMBptr->feuille))
7162 return fraction(1,a._SYMBptr->feuille)*(*b._FRACptr);
7163 if ( (a.type!=_SYMB) && (a.type!=_IDNT) ){
7164 if (a.type==_EXT)
7165 return fraction(a*b._FRACptr->num,b._FRACptr->den).normal();
7166 return a*(*b._FRACptr);
7167 }
7168 return sym_mult(a,_FRAC2_SYMB(b),contextptr);
7169 }
7170 if (is_cinteger(a) && b.is_symb_of_sommet(at_inv) && is_cinteger(b._SYMBptr->feuille))
7171 return a/b._SYMBptr->feuille;
7172 if (is_cinteger(b) && a.is_symb_of_sommet(at_inv) && is_cinteger(a._SYMBptr->feuille))
7173 return b/a._SYMBptr->feuille;
7174 if (a.type<=_CPLX && b.is_symb_of_sommet(at_inv)&& b._SYMBptr->feuille.type<=_CPLX)
7175 return fraction(a,b._SYMBptr->feuille).normal();
7176 if (b.type<=_CPLX && a.is_symb_of_sommet(at_inv)&& a._SYMBptr->feuille.type<=_CPLX)
7177 return fraction(b,a._SYMBptr->feuille).normal();
7178 if ((a.type<=_REAL || a.type==_FLOAT_) && is_strictly_positive(-a,contextptr))
7179 return -sym_mult(-a,b,contextptr);
7180 if ((b.type<=_REAL || b.type==_FLOAT_) && is_strictly_positive(-b,contextptr))
7181 return -sym_mult(a,-b,contextptr);
7182 if (a.type==_EXT){
7183 if (a.is_constant() && (b.type==_POLY))
7184 return a*(*b._POLYptr);
7185 else
7186 return algebraic_EXTension(b*(*a._EXTptr),*(a._EXTptr+1));
7187 }
7188 if (b.type==_EXT){
7189 if (b.is_constant() && (a.type==_POLY))
7190 return (*a._POLYptr)*b;
7191 else
7192 return algebraic_EXTension(a*(*b._EXTptr),*(b._EXTptr+1));
7193 }
7194 if ( (a.type==_INT_) && (a.val<0) && (a.val!=1<<31)){
7195 if (b.is_symb_of_sommet(at_inv) && (b._SYMBptr->feuille.type<_POLY || b._SYMBptr->feuille.is_symb_of_sommet(at_neg)))
7196 return sym_mult(-a,inv(-b._SYMBptr->feuille,contextptr),contextptr);
7197 else
7198 return -sym_mult(-a,b,contextptr);
7199 }
7200 if ( (b.type==_INT_) && (b.val<0) && (b.val!=1<<31)){
7201 if (a.is_symb_of_sommet(at_inv))
7202 return sym_mult(-b,inv(-a._SYMBptr->feuille,contextptr),contextptr);
7203 else
7204 return -sym_mult(-b,a,contextptr);
7205 }
7206 if (is_equal(a)){
7207 vecteur & va=*a._SYMBptr->feuille._VECTptr;
7208 if (is_equal(b)){
7209 vecteur & vb=*b._SYMBptr->feuille._VECTptr;
7210 return new_ref_symbolic(symbolic(a._SYMBptr->sommet,gen(makenewvecteur(va.front()*vb.front(),va.back()*vb.back()),_SEQ__VECT)));
7211 }
7212 else
7213 return new_ref_symbolic(symbolic(a._SYMBptr->sommet,gen(makenewvecteur(va.front()*b,va.back()*b),_SEQ__VECT)));
7214 }
7215 if (is_equal(b)){
7216 vecteur & vb=*b._SYMBptr->feuille._VECTptr;
7217 return new_ref_symbolic(symbolic(b._SYMBptr->sommet,gen(makenewvecteur(a*vb.front(),a*vb.back()),_SEQ__VECT)));
7218 }
7219 if ((a.type==_SYMB)&& (b.type==_SYMB)){
7220 if ((a._SYMBptr->sommet==at_prod) && (b._SYMBptr->sommet==at_prod))
7221 return new_ref_symbolic(symbolic(at_prod,gen(mergevecteur(*(a._SYMBptr->feuille._VECTptr),*(b._SYMBptr->feuille._VECTptr)),_SEQ__VECT)));
7222 else {
7223 if (a._SYMBptr->sommet==at_prod)
7224 return new_ref_symbolic(symbolic(*a._SYMBptr,b));
7225 else {
7226 if (b._SYMBptr->sommet==at_prod)
7227 return new_ref_symbolic(symbolic(a,b._SYMBptr->sommet,b._SYMBptr->feuille));
7228 else
7229 return new_ref_symbolic(symbolic(at_prod,gen(makenewvecteur(a,b),_SEQ__VECT)));
7230 }
7231 }
7232 }
7233 if (b.type==_SYMB){
7234 if (b._SYMBptr->sommet==at_prod)
7235 return new_ref_symbolic(symbolic(a,b._SYMBptr->sommet,b._SYMBptr->feuille));
7236 else
7237 return new_ref_symbolic(symbolic(at_prod,gen(makenewvecteur(a,b),_SEQ__VECT)));
7238 }
7239 if (a.type==_SYMB){
7240 if (a._SYMBptr->sommet==at_prod)
7241 return new_ref_symbolic(symbolic(*a._SYMBptr,b));
7242 else
7243 return new_ref_symbolic(symbolic(at_prod,gen(b.type==_INT_?makenewvecteur(b,a):makenewvecteur(a,b),_SEQ__VECT)));
7244 }
7245 if ((a.type==_IDNT) || (b.type==_IDNT))
7246 return new_ref_symbolic(symbolic(at_prod,gen(makenewvecteur(a,b),_SEQ__VECT)));
7247 if (a.type==_MOD)
7248 return a*makemod(b,*(a._MODptr+1));
7249 if (b.type==_MOD)
7250 return b*makemod(a,*(b._MODptr+1));
7251 return new_ref_symbolic(symbolic(at_prod,gen(makenewvecteur(a,b),_SEQ__VECT)));
7252 // settypeerr(gettext("sym_mult"));
7253 }
7254
inv__VECT(const vecteur & v,GIAC_CONTEXT)7255 static vecteur inv__VECT(const vecteur & v,GIAC_CONTEXT){
7256 vecteur w;
7257 if (is_squarematrix(v))
7258 w=minv(v,contextptr);
7259 else {
7260 vecteur::const_iterator it=v.begin(),itend=v.end();
7261 for (;it!=itend;++it)
7262 w.push_back(inv(*it,contextptr));
7263 }
7264 return w;
7265 }
7266
invfirst(const vecteur & v)7267 static vecteur invfirst(const vecteur & v){
7268 vecteur w(v);
7269 if (!w.empty())
7270 w.front()=inv(w.front(),context0);
7271 return w;
7272 }
7273
invdistrib(const gen & g,GIAC_CONTEXT)7274 static gen invdistrib(const gen & g,GIAC_CONTEXT){
7275 if (g.type!=_SYMB)
7276 return inv(g,contextptr);
7277 gen & f=g._SYMBptr->feuille;
7278 if (g._SYMBptr->sommet==at_inv)
7279 return f;
7280 if (g._SYMBptr->sommet==at_pow)
7281 return symbolic(at_pow,gen(makevecteur(f[0],-f[1]),_SEQ__VECT));
7282 if (g._SYMBptr->sommet==at_prod && f.type==_VECT){
7283 vecteur v = *f._VECTptr;
7284 iterateur it=v.begin(),itend=v.end();
7285 for (;it!=itend;++it)
7286 *it=invdistrib(*it,contextptr);
7287 return symbolic(at_prod,gen(v,_SEQ__VECT));
7288 }
7289 return inv(g,contextptr);
7290 }
7291
inv_distrib(const gen & b,GIAC_CONTEXT)7292 gen inv_distrib(const gen & b,GIAC_CONTEXT){
7293 if (b.is_symb_of_sommet(at_prod)){
7294 gen f=b._SYMBptr->feuille;
7295 return symbolic(at_prod,inv_distrib(f,contextptr));
7296 }
7297 if (b.is_symb_of_sommet(at_pow))
7298 return pow(b._SYMBptr->feuille[0],-b._SYMBptr->feuille[1],contextptr);
7299 if (b.is_symb_of_sommet(at_inv))
7300 return b._SYMBptr->feuille;
7301 if (b.type==_VECT){
7302 vecteur v(*b._VECTptr);
7303 for (unsigned i=0;i<v.size();++i){
7304 v[i]=inv_distrib(v[i],contextptr);
7305 }
7306 return gen(v,b.subtype);
7307 }
7308 return unitpow(b,-1);
7309 }
7310
inv(const gen & a,GIAC_CONTEXT)7311 gen inv(const gen & a,GIAC_CONTEXT){
7312 #ifdef TIMEOUT
7313 control_c();
7314 #endif
7315 if (ctrl_c || interrupted) {
7316 interrupted = true; ctrl_c=false;
7317 return gensizeerr(gettext("Stopped by user interruption."));
7318 }
7319 if ( (a.type==_DOUBLE_ || a.type==_FLOAT_ )? a==0 : is_exactly_zero(a))
7320 return unsigned_inf;
7321 switch (a.type ) {
7322 case _INT_: case _ZINT:
7323 if (is_one(a) || (is_minus_one(a)) )
7324 return a;
7325 else
7326 return fraction(1,a);
7327 case _REAL:
7328 return a._REALptr->inv();
7329 case _DOUBLE_:
7330 return 1/a._DOUBLE_val;
7331 case _FLOAT_:
7332 return finv(a._FLOAT_val);
7333 case _CPLX:
7334 if (is_exactly_zero(*a._CPLXptr)){
7335 if (is_one(abs(*(a._CPLXptr+1),contextptr)))
7336 return -a;
7337 }
7338 if ( a._CPLXptr->type==_DOUBLE_ || a._CPLXptr->type==_FLOAT_ ||a._CPLXptr->type==_REAL || (a._CPLXptr+1)->type==_DOUBLE_ || (a._CPLXptr+1)->type==_FLOAT_ || (a._CPLXptr+1)->type==_REAL ){
7339 gen a2=no_context_evalf(a.squarenorm(contextptr));
7340 if (is_inf(a2)){
7341 gen theta=arg(a,contextptr);
7342 theta=cos(theta,contextptr)-cst_i*sin(theta,contextptr);
7343 a2=re(a*theta,contextptr);
7344 return inv(a2,contextptr)*theta;
7345 }
7346 return gen(rdiv(no_context_evalf(a.re(contextptr)),a2,contextptr),rdiv(no_context_evalf(-a.im(contextptr)),a2,contextptr));
7347 }
7348 return fraction(1,a);
7349 case _IDNT:
7350 if (a==undef)
7351 return undef;
7352 if (a==unsigned_inf)
7353 return 0;
7354 return new_ref_symbolic(symbolic(at_inv,a));
7355 case _SYMB:
7356 if ((a==plus_inf) || (a==minus_inf))
7357 return 0;
7358 {
7359 vecteur v=alg_lvar(a); // change for limit(1/(1+sqrt(2)*cos(x))*sin(x-3*pi/4),x=3*pi/4); maybe we should only do evalf test and return undef
7360 if (v.size()==1 && v.front().type==_VECT && v.front()._VECTptr->empty() && is_zero(evalf(a,1,contextptr)) && is_exactly_zero(recursive_normal(a,contextptr)))
7361 return unsigned_inf;
7362 }
7363 if (a.is_symb_of_sommet(at_unit)){
7364 if (equalposcomp(lidnt(a),cst_pi)!=0)
7365 return inv(evalf(a,1,contextptr),contextptr);
7366 return new_ref_symbolic(symbolic(at_unit,makenewvecteur(inv(a._SYMBptr->feuille._VECTptr->front(),contextptr),inv_distrib(a._SYMBptr->feuille._VECTptr->back(),contextptr))));
7367 }
7368 if (equalposcomp(plot_sommets,a._SYMBptr->sommet))
7369 return symbolic_plot_makevecteur( a._SYMBptr->sommet,inv(a._SYMBptr->feuille,contextptr),false,contextptr);
7370 if (a._SYMBptr->sommet==at_inv)
7371 return a._SYMBptr->feuille;
7372 if (a._SYMBptr->sommet==at_NTHROOT && a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()==2){
7373 return symbolic(at_NTHROOT,makesequence(-a._SYMBptr->feuille._VECTptr->front(),a._SYMBptr->feuille._VECTptr->back()));
7374 }
7375 if (a._SYMBptr->sommet==at_neg)
7376 return -inv(a._SYMBptr->feuille,contextptr);
7377 else {
7378 if (a._SYMBptr->sommet==at_prod)
7379 return new_ref_symbolic(symbolic(at_prod,gen(inv__VECT(*(a._SYMBptr->feuille._VECTptr),contextptr),a._SYMBptr->feuille.subtype)));
7380 else
7381 return new_ref_symbolic(symbolic(at_inv,a));
7382 }
7383 case _VECT:
7384 if (a.subtype==_PNT__VECT)
7385 return gen(invfirst(*a._VECTptr),a.subtype);
7386 if (a.subtype==_POLY1__VECT)
7387 return fraction(gen(vecteur(1,plus_one),_POLY1__VECT),a);
7388 if (a.subtype==_MATRIX__VECT && !is_squarematrix(a))
7389 return gensizeerr(gettext("Inv of non-square matrix"));
7390 return gen(inv__VECT(*a._VECTptr,contextptr),a.subtype);
7391 case _EXT:
7392 return inv_EXT(a);
7393 case _SPOL1:
7394 return spdiv(gen2spol1(1),*a._SPOL1ptr,contextptr);
7395 case _USER:
7396 return a._USERptr->inv();
7397 case _MOD:
7398 return modinv(a);
7399 case _FRAC:
7400 if (a._FRACptr->num.type==_CPLX)
7401 return fraction(a._FRACptr->den,a._FRACptr->num).normal();
7402 if (is_positive(a._FRACptr->num,contextptr))
7403 return fraction(a._FRACptr->den,a._FRACptr->num);
7404 else
7405 return fraction(-a._FRACptr->den,-a._FRACptr->num);
7406 default:
7407 if (is_undef(a))
7408 return a;
7409 return new_ref_symbolic(symbolic(at_inv,a));
7410 // settypeerr(gettext("Inv"));
7411 }
7412
7413 }
7414
7415 /*
7416 gen inv(const gen & a,GIAC_CONTEXT){
7417 return inv(a,context0);
7418 }
7419 */
7420
inverse(GIAC_CONTEXT) const7421 gen gen::inverse(GIAC_CONTEXT) const { return inv(*this,contextptr); }
7422
inpow(const gen & base,unsigned long int exponent,gen & res)7423 static void inpow(const gen & base,unsigned long int exponent,gen & res){
7424 #if 0
7425 res=1;
7426 gen basepow=base;
7427 while (exponent){
7428 if (exponent%2)
7429 res = res*basepow;
7430 if ( (exponent /=2) )
7431 basepow=basepow*basepow;
7432 }
7433 #else
7434 if (exponent==1)
7435 res=base;
7436 else {
7437 inpow(base,exponent/2,res);
7438 res=res*res;
7439 if (exponent %2)
7440 res=res*base;
7441 }
7442 #endif
7443 }
7444
pow(const gen & base,unsigned long int exponent)7445 gen pow(const gen & base, unsigned long int exponent){
7446 // if (!( (++control_c_counter) & control_c_counter_mask))
7447 #ifdef TIMEOUT
7448 control_c();
7449 #endif
7450 if (ctrl_c || interrupted) {
7451 interrupted = true; ctrl_c=false;
7452 return gensizeerr(gettext("Stopped by user interruption."));
7453 }
7454 ref_mpz_t * e;
7455 gen res;
7456 switch (base.type ) {
7457 case _INT_:
7458 if (base.val<0 && (exponent % 2))
7459 return(-pow(-base.val,exponent));
7460 else
7461 return(pow(absint(base.val),exponent));
7462 case _DOUBLE_:
7463 #ifdef _SOFTMATH_H
7464 return std::giac_gnuwince_pow(base._DOUBLE_val,double(exponent));
7465 #else
7466 return std::pow(base._DOUBLE_val,double(exponent));
7467 #endif
7468 case _FLOAT_:
7469 return fpow(base._FLOAT_val,giac_float(double(exponent)));
7470 case _ZINT:
7471 e=new ref_mpz_t;
7472 mpz_pow_ui(e->z,*base._ZINTptr,exponent);
7473 return e;
7474 case _VECT:
7475 if (base.subtype==_POLY1__VECT && base._VECTptr->size()<5){
7476 vecteur res;
7477 if (miller_pow(*base._VECTptr,exponent,res))
7478 return gen(res,_POLY1__VECT);
7479 }
7480 /* no break, _VECT handled by next case */
7481 case _CPLX: case _REAL: case _EXT: case _MOD: case _USER:
7482 // gauss integer power
7483 if (!exponent){
7484 if (ckmatrix(base))
7485 return midn(int(base._VECTptr->size()));
7486 if (base.type==_USER)
7487 return base*inv(base,context0);
7488 return 1;
7489 }
7490 inpow(base,exponent,res);
7491 return(res);
7492 case _IDNT:
7493 if (is_undef(base))
7494 return base;
7495 if (!exponent)
7496 return 1;
7497 if (exponent==1)
7498 return base;
7499 return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,(longlong)exponent),_SEQ__VECT)));
7500 case _SYMB:
7501 if (!exponent)
7502 return 1;
7503 if (exponent==1)
7504 return base;
7505 if (base._SYMBptr->sommet==at_pow){
7506 res= (*((base._SYMBptr->feuille)._VECTptr))[1];
7507 return pow( (base._SYMBptr->feuille)._VECTptr->front(),gen((longlong) (exponent)) * res,context0) ;
7508 }
7509 if ((exponent % 2==0) && base._SYMBptr->sommet==at_abs)
7510 return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base._SYMBptr->feuille,(longlong) exponent),_SEQ__VECT)));
7511 return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,(longlong) exponent),_SEQ__VECT)));
7512 case _POLY:
7513 return pow(*base._POLYptr,(int) exponent);
7514 case _FRAC:
7515 return pow(*base._FRACptr,(int) exponent);
7516 case _MAP:{
7517 gen res;
7518 inpow(base,exponent,res);
7519 return res;
7520 }
7521 default:
7522 if (is_undef(base))
7523 return base;
7524 return gentypeerr(gettext("Pow")) ;
7525 }
7526 return 0;
7527 }
7528
pow(const gen & base,int exponent)7529 gen pow(const gen & base, int exponent){
7530 if (base==zero){
7531 if (exponent>0)
7532 return base;
7533 if (!exponent)
7534 return undef;
7535 if (exponent %2)
7536 return unsigned_inf;
7537 return plus_inf;
7538 }
7539 if (exponent<0){
7540 if (-exponent<0)
7541 return gensizeerr("pow: int exponent underflow");
7542 return inv(pow(base,-exponent),context0);
7543 }
7544 if (is_one(base))
7545 return base;
7546 if (is_minus_one(base))
7547 return exponent%2?-1:1;
7548 unsigned long int expo=exponent;
7549 gen b;
7550 if (base.type<=_ZINT && has_evalf(base,b,0,context0) && !is_inf(b) &&
7551 is_greater(abs(exponent*log(abs(b,context0),context0),context0),powlog2float,context0)){
7552 return gensizeerr("Exponent overflow");
7553 *logptr(context0) << "Exponent overflow" << '\n';
7554 if (is_strictly_greater(1,abs(b,context0),context0))
7555 return 0;
7556 return (exponent%2==0 || is_greater(b,0,context0))?plus_inf:minus_inf; // overflow
7557 // return pow(b,expo);
7558 }
7559 return(pow(base,expo));
7560 }
7561
pow(unsigned long int base,unsigned long int exponent)7562 gen pow(unsigned long int base, unsigned long int exponent){
7563 ref_mpz_t *e=new ref_mpz_t;
7564 #ifdef EMCC
7565 if (base==int(base)){
7566 mpz_set_si(e->z,1);
7567 for (unsigned long int i=0;i<exponent;++i){
7568 mpz_mul_ui(e->z,e->z,int(base));
7569 }
7570 return e;
7571 }
7572 #endif
7573 mpz_ui_pow_ui(e->z,base,exponent);
7574 return e;
7575 }
7576
_ZINTdiv(const gen & a,const gen & b,ref_mpz_t * & quo)7577 static void _ZINTdiv (const gen & a,const gen & b,ref_mpz_t * & quo){
7578 // at least one is not an int, uncoerce remaining int
7579 ref_mpz_t *aptr,*bptr;
7580 if (a.type!=_INT_)
7581 #ifdef SMARTPTR64
7582 aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
7583 #else
7584 aptr=a.__ZINTptr;
7585 #endif
7586 else {
7587 aptr=new ref_mpz_t;
7588 mpz_set_si(aptr->z,a.val);
7589 }
7590 if (b.type!=_INT_)
7591 #ifdef SMARTPTR64
7592 bptr= (ref_mpz_t *) (* ((ulonglong * ) &b) >> 16);
7593 #else
7594 bptr=b.__ZINTptr;
7595 #endif
7596 else {
7597 bptr=new ref_mpz_t;
7598 mpz_set_si(bptr->z,b.val);
7599 }
7600 quo=new ref_mpz_t;
7601 mpz_tdiv_q(quo->z,aptr->z,bptr->z);
7602 if (a.type==_INT_){
7603 delete aptr;
7604 }
7605 if (b.type==_INT_){
7606 delete bptr;
7607 }
7608 }
7609
7610 // a and b must be integers or Gaussian integers
iquobest(const gen & a,const gen & b)7611 static gen iquobest(const gen & a,const gen & b){
7612 if (is_strictly_positive(-a,0))
7613 return -iquobest(-a,b);
7614 return iquo(a+iquo(b,2),b);
7615 }
7616
7617 // a and b must be integers or Gaussian integers
iquocmplx(const gen & a,const gen & b)7618 static gen iquocmplx(const gen & a,const gen & b){
7619 gen b2=b.squarenorm(0);
7620 gen ab=a*b.conj(0);
7621 gen res(iquobest(re(ab,context0),b2),iquobest(im(ab,context0),b2)); // ok
7622 return res;
7623 }
7624
iquopoly(const polynome & a,const gen & b)7625 static polynome iquopoly(const polynome & a,const gen & b){
7626 polynome res(a);
7627 vector< monomial<gen> >::iterator it=res.coord.begin(),itend=res.coord.end();
7628 for (;it!=itend;++it)
7629 it->value=iquo(it->value,b);
7630 return res;
7631 }
7632
7633 // integer quotient, use rdiv for symbolic division
iquo(const gen & a,const gen & b)7634 gen iquo(const gen & a,const gen & b){
7635 if ((b.type==_INT_)){
7636 switch (b.val){
7637 case 1:
7638 return a;
7639 case -1:
7640 return -a;
7641 case 0:
7642 return gensizeerr(gettext("Division by 0"));
7643 }
7644 }
7645 if (a.type==_POLY) // may be called by resulant interpolation
7646 return iquopoly(*a._POLYptr,b);
7647 ref_mpz_t * quo;
7648 switch ( (a.type<< _DECALAGE) | b.type ) {
7649 case _INT___INT_:
7650 return(a.val/b.val);
7651 case _ZINT__ZINT: case _INT___ZINT: case _ZINT__INT_:
7652 _ZINTdiv(a,b,quo);
7653 return quo;
7654 case _CPLX__INT_: case _CPLX__ZINT:
7655 return gen(iquo(*a._CPLXptr,b),iquo(*(a._CPLXptr+1),b));
7656 case _INT___CPLX: case _ZINT__CPLX:
7657 return iquocmplx(a,b);
7658 case _CPLX__CPLX:
7659 return adjust_complex_display(iquocmplx(a,b),a,b);
7660 default:
7661 return gentypeerr(gettext("iquo"));
7662 }
7663 return 0;
7664 }
7665
7666 // a and b must be integer or Gaussian integers
rdivsimp(const gen & a,const gen & b)7667 static gen rdivsimp(const gen & a,const gen & b){
7668 if (is_positive(-b,context0)) // ok
7669 return rdivsimp(-a,-b);
7670 gen c(gcd(a,b,context0));
7671 if (c.type==_CPLX)
7672 c=gcd(c.re(context0),c.im(context0),context0); // ok
7673 return fraction(iquo(a,c),iquo(b,c));
7674 }
7675
divpoly(const polynome & p,const gen & e)7676 static gen divpoly(const polynome & p, const gen & e){
7677 if (p.coord.empty())
7678 return zero;
7679 gen coefft; int pt=coefftype(p,coefft);
7680 if (pt==_MOD || pt==_USER){
7681 polynome res(p);
7682 mulpoly(res,coefft/(e*coefft),res);
7683 return res;
7684 }
7685 gen d=gcd(Tcontent<gen>(p),e,context0);
7686 if (d.type==_EXT)
7687 d=_gcd(*d._EXTptr,context0);
7688 if (is_one(d)){
7689 if (e==cst_i || e==minus_one || e==-cst_i)
7690 return p/e;
7691 return fraction(p,e);
7692 }
7693 gen den(rdiv(e,d,context0));
7694 gen iden(inv(den,context0));
7695 if ( (iden.type!=_SYMB) && (iden.type!=_FRAC))
7696 return (p/d)*iden;
7697 else
7698 return fraction(p/d,den);
7699 }
7700
divpoly(const gen & e,const polynome & p)7701 static gen divpoly(const gen & e,const polynome & p){
7702 if (is_exactly_zero(e))
7703 return e;
7704 if (Tis_constant<gen>(p)&& p.coord.front().value.type<_POLY)
7705 return rdiv(e,p.coord.front().value,context0);
7706 gen d=gcd(Tcontent<gen>(p),e,context0);
7707 gen tmp=polynome(rdiv(e,d,context0),p.dim);
7708 return fraction(tmp,p/d);
7709 }
7710
divpolypoly(const gen & a,const gen & b)7711 static gen divpolypoly(const gen & a,const gen &b){
7712 polynome ap(*a._POLYptr),bp(*b._POLYptr);
7713 polynome q(ap.dim),r(ap.dim);
7714 if (divrem1(ap,bp,q,r) && r.coord.empty())
7715 return q;
7716 return normal(fraction(a,b),context0); // ok
7717 }
7718
rdiv(const gen & a,const gen & b,GIAC_CONTEXT)7719 gen rdiv(const gen &a,const gen &b,GIAC_CONTEXT){
7720 // if (!( (++control_c_counter) & control_c_counter_mask))
7721 #ifdef TIMEOUT
7722 control_c();
7723 #endif
7724 if (ctrl_c || interrupted) {
7725 interrupted = true; ctrl_c=false;
7726 return gensizeerr(gettext("Stopped by user interruption."));
7727 }
7728 if (b.type==_MOD)
7729 return a*inv(b,contextptr);
7730 switch ( (a.type<< _DECALAGE) | b.type ) {
7731 case _INT___INT_: case _ZINT__INT_: case _ZINT__ZINT:
7732 if (is_exactly_zero(b)){
7733 if (is_exactly_zero(a))
7734 return undef;
7735 return unsigned_inf;
7736 }
7737 if (a==b)
7738 return 1;
7739 if (a==-b)
7740 return -1;
7741 if (is_exactly_zero(a%b))
7742 return iquo(a,b);
7743 else
7744 return rdivsimp(a,b);
7745 case _CPLX__INT_: case _CPLX__ZINT:
7746 if ( (a._CPLXptr->type==_DOUBLE_ || a._CPLXptr->type==_FLOAT_) || ((a._CPLXptr+1)->type==_DOUBLE_ || (a._CPLXptr+1)->type==_FLOAT_) )
7747 return rdiv(no_context_evalf(a),no_context_evalf(b),contextptr);
7748 if (a._CPLXptr->type==_REAL){
7749 if ((a._CPLXptr+1)->type==_REAL)
7750 return rdiv(*a._CPLXptr,b,contextptr)+cst_i*rdiv(*(a._CPLXptr+1),b,contextptr);
7751 #ifdef HAVE_LIBMPFR
7752 return rdiv(*a._CPLXptr,b,contextptr)+cst_i*rdiv(real_object(*(a._CPLXptr+1),mpfr_get_prec(a._CPLXptr->_REALptr->inf)),b,contextptr);
7753 #else
7754 return rdiv(*a._CPLXptr,b,contextptr)+cst_i*rdiv(real_object(*(a._CPLXptr+1)),b,contextptr);
7755 #endif
7756 }
7757 if ((a._CPLXptr+1)->type==_REAL){
7758 #ifdef HAVE_LIBMPFR
7759 return rdiv(real_object(*a._CPLXptr,mpfr_get_prec((a._CPLXptr+1)->_REALptr->inf)),b,contextptr)+cst_i*rdiv(*(a._CPLXptr+1),b,contextptr);
7760 #else
7761 return rdiv(real_object(*a._CPLXptr),b)+cst_i*rdiv(*(a._CPLXptr+1),b,contextptr);
7762 #endif
7763 }
7764 if (is_exactly_zero(b))
7765 return unsigned_inf;
7766 if (is_exactly_zero(a%b))
7767 return iquo(a,b);
7768 else
7769 return rdivsimp(a,b);
7770 case _CPLX__CPLX:
7771 return adjust_complex_display(rdiv(a*conj(b,contextptr),b.squarenorm(contextptr),contextptr),a,b);
7772 case _DOUBLE___CPLX: case _FLOAT___CPLX: case _INT___CPLX: case _ZINT__CPLX: case _REAL__CPLX:
7773 if (is_one(a))
7774 return inv(b,contextptr);
7775 return rdiv(a*conj(b,contextptr),b.squarenorm(contextptr),contextptr);
7776 case _DOUBLE___DOUBLE_:
7777 return a._DOUBLE_val/b._DOUBLE_val;
7778 case _DOUBLE___INT_:
7779 return a._DOUBLE_val/b.val;
7780 case _INT___DOUBLE_:
7781 return a.val/b._DOUBLE_val;
7782 case _FLOAT___FLOAT_:
7783 return a._FLOAT_val/b._FLOAT_val;
7784 case _FLOAT___INT_:
7785 return a._FLOAT_val/giac_float(b.val);
7786 case _INT___FLOAT_:
7787 return giac_float(a.val)/b._FLOAT_val;
7788 #ifdef BCD
7789 case _FLOAT___ZINT:
7790 return a._FLOAT_val/giac_float(b._ZINTptr);
7791 case _ZINT__FLOAT_:
7792 return giac_float(a._ZINTptr)/b._FLOAT_val;
7793 #endif
7794 case _FLOAT___DOUBLE_:
7795 return a._FLOAT_val/giac_float(b._DOUBLE_val);
7796 case _DOUBLE___FLOAT_:
7797 return giac_float(a._DOUBLE_val)/b._FLOAT_val;
7798 case _ZINT__DOUBLE_:
7799 return mpz_get_d(*a._ZINTptr)/b._DOUBLE_val;
7800 case _CPLX__DOUBLE_: case _CPLX__REAL:
7801 return gen(rdiv(*a._CPLXptr,b,contextptr),rdiv(*(a._CPLXptr+1),b,contextptr));
7802 case _DOUBLE___ZINT:
7803 return a._DOUBLE_val/mpz_get_d(*b._ZINTptr);
7804 // _CPLX__DOUBLE_, _DOUBLE___CPLX, _CPLX__CPLX, _ZINT__CPLX, _INT___CPLX
7805 case _VECT__INT_: case _VECT__ZINT: case _VECT__DOUBLE_: case _VECT__FLOAT_: case _VECT__CPLX: case _VECT__FRAC:
7806 case _VECT__SYMB: case _VECT__IDNT: case _VECT__POLY: case _VECT__EXT:
7807 if (a.subtype==_VECTOR__VECT)
7808 return a*inv(b,contextptr);
7809 return gen(divvecteur(*a._VECTptr,b),a.subtype);
7810 case _MAP__INT_: case _MAP__ZINT: case _MAP__DOUBLE_: case _MAP__FLOAT_: case _MAP__CPLX:
7811 case _MAP__SYMB: case _MAP__IDNT: case _MAP__POLY: case _MAP__EXT: {
7812 gen_map m;
7813 gen g(m);
7814 *g._MAPptr=*a._MAPptr;
7815 sparse_div(*g._MAPptr,b);
7816 return g;
7817 }
7818 case _VECT__VECT:
7819 if (a.subtype==_POLY1__VECT || b.subtype==_POLY1__VECT)
7820 return fraction(a,b).normal();
7821 if (is_squarematrix(b)){
7822 if (abs_calc_mode(contextptr)==38){
7823 *logptr(contextptr) << gettext("Warning: A/B with B a square matrix is a misleading notation interpreted as inv(B)*A") << '\n';
7824 return inv(b,contextptr)*a;
7825 }
7826 *logptr(contextptr) << gettext("Warning, pointwise division of a by b. For matrix division, please use inv(b)*a or a*inv(b)") << '\n';
7827 }
7828 if (b._VECTptr->size()==1)
7829 return rdiv(a,b._VECTptr->front(),contextptr);
7830 return apply(a,b,contextptr,rdiv);
7831 case _POLY__POLY:
7832 return divpolypoly(a,b);
7833 case _FRAC__FRAC:
7834 if (a._FRACptr->num.type==_CPLX || a._FRACptr->den.type==_CPLX ||
7835 b._FRACptr->num.type==_CPLX || b._FRACptr->den.type==_CPLX){
7836 gen d=gcd(a._FRACptr->den,b._FRACptr->den,contextptr);
7837 return (a._FRACptr->num*(b._FRACptr->den/d))/((a._FRACptr->den/d)*b._FRACptr->num);
7838 }
7839 return (*a._FRACptr)/(*b._FRACptr);
7840 case _SPOL1__SPOL1:
7841 return spdiv(*a._SPOL1ptr,*b._SPOL1ptr,contextptr);
7842 case _POLY__DOUBLE_: case _POLY__FLOAT_: case _POLY__REAL:
7843 return (*a._POLYptr)/b;
7844 case _POLY__INT_:
7845 if (b.val==1) return a;
7846 case _POLY__ZINT: case _POLY__CPLX:
7847 return divpoly(*a._POLYptr,b);
7848 case _INT___POLY: case _ZINT__POLY: case _CPLX__POLY:
7849 return divpoly(a,*b._POLYptr);
7850 case _INT___FRAC: case _ZINT__FRAC:
7851 if (is_positive(-b._FRACptr->num,contextptr)){
7852 // if (is_one(a)) return fraction(-b._FRACptr->den,-b._FRACptr->num);
7853 return (-b._FRACptr->den*a)/(-b._FRACptr->num);
7854 }
7855 // if (is_one(a)) return fraction(b._FRACptr->den,b._FRACptr->num);
7856 return (b._FRACptr->den*a)/b._FRACptr->num;
7857 case _INT___VECT: case _ZINT__VECT: case _CPLX__VECT: case _DOUBLE___VECT: case _FLOAT___VECT: case _SYMB__VECT:
7858 if (b.subtype==_LIST__VECT)
7859 return apply2nd(a,b,contextptr,rdiv);
7860 if (ckmatrix(b))
7861 return a*inv(b,contextptr);
7862 if (calc_mode(contextptr)==1 && b.subtype!=_POLY1__VECT)
7863 return apply2nd(a,b,contextptr,rdiv);
7864 return fraction(a,b);
7865 default:
7866 #ifdef TIMEOUT
7867 control_c();
7868 #endif
7869 if (ctrl_c || interrupted) {
7870 interrupted = true; ctrl_c=false;
7871 return gensizeerr(gettext("Stopped by user interruption."));
7872 }
7873 if (is_undef(a))
7874 return a;
7875 if (is_undef(b))
7876 return b;
7877 if (a.type==_STRNG || b.type==_STRNG)
7878 return gensizeerr("string /");
7879 {
7880 gen var1,var2,res1,res2;
7881 if (is_algebraic_program(a,var1,res1)){
7882 if (is_algebraic_program(b,var2,res2)){
7883 if (var1!=var2 && is_constant_wrt(res2,var1,contextptr)){
7884 res2=subst(res2,var2,var1,false,contextptr);
7885 var2=var1;
7886 }
7887 if (var1==var2)
7888 return symbolic(at_program,gen(makevecteur(var1,0,rdiv(res1,res2,contextptr)),_SEQ__VECT));
7889 }
7890 if (!is_constant_wrt(b,var1,contextptr))
7891 *logptr(contextptr) << "Warning function/constant with constant dependant of mute variable" << '\n';
7892 return symbolic(at_program,gen(makevecteur(var1,0,rdiv(res1,b,contextptr)),_SEQ__VECT));
7893 }
7894 if (is_algebraic_program(b,var2,res2)){
7895 if (!is_constant_wrt(a,var2,contextptr))
7896 *logptr(contextptr) << "Warning constant/function with constant dependant of mute variable" << '\n';
7897 return symbolic(at_program,gen(makevecteur(var2,0,rdiv(a,res2,contextptr)),_SEQ__VECT));
7898 }
7899 }
7900 if (a.type==_FLOAT_)
7901 return rdiv(evalf_double(a,1,contextptr),b,contextptr);
7902 if (b.type==_FLOAT_)
7903 return rdiv(a,evalf_double(b,1,contextptr),contextptr);
7904 if (a.is_symb_of_sommet(at_unit) || b.is_symb_of_sommet(at_unit))
7905 return operator_times(a,inv(b,contextptr),contextptr);
7906 if (is_one(b))
7907 return chkmod(a,b);
7908 if (is_minus_one(b))
7909 return chkmod(-a,b);
7910 if (is_exactly_zero(a)){
7911 if (!is_exactly_zero(normal(b,contextptr)))
7912 return a;
7913 else
7914 return undef;
7915 }
7916 if (is_exactly_zero(b))
7917 return unsigned_inf;
7918 if (is_inf(a)){
7919 if (is_inf(b))
7920 return undef;
7921 if (is_zero(b))
7922 return unsigned_inf;
7923 return a*b;
7924 }
7925 if (is_inf(b)){
7926 if (is_inf(a))
7927 return undef;
7928 else
7929 return zero;
7930 }
7931 if (a==b && a.type!=_REAL && b.type!=_REAL)
7932 return chkmod(plus_one,a);
7933 if (a.is_approx()){
7934 gen b1;
7935 if (has_evalf(b,b1,1,contextptr) && (b.type!=b1.type || b!=b1)){
7936 #ifdef HAVE_LIBMPFR
7937 if (a.type==_REAL){
7938 gen b2=accurate_evalf(b,mpfr_get_prec(a._REALptr->inf));
7939 if (b2.is_approx())
7940 return rdiv(a,b2,contextptr);
7941 }
7942 if (a.type==_CPLX && a._CPLXptr->type==_REAL){
7943 gen b2=accurate_evalf(b,mpfr_get_prec(a._CPLXptr->_REALptr->inf));
7944 if (b2.is_approx())
7945 return rdiv(a,b2,contextptr);
7946 }
7947 #endif
7948 return rdiv(a,b1,contextptr);
7949 }
7950 }
7951 if (b.is_approx()){
7952 gen a1;
7953 if (has_evalf(a,a1,1,contextptr) && (a.type!=a1.type || a!=a1)){
7954 #ifdef HAVE_LIBMPFR
7955 if (b.type==_REAL){
7956 gen a2=accurate_evalf(a,mpfr_get_prec(b._REALptr->inf));
7957 if (a2.is_approx())
7958 return rdiv(a2,b,contextptr);
7959 }
7960 if (b.type==_CPLX && b._CPLXptr->type==_REAL){
7961 gen a2=accurate_evalf(a,mpfr_get_prec(b._CPLXptr->_REALptr->inf));
7962 if (a2.is_approx())
7963 return rdiv(a2,b,contextptr);
7964 }
7965 #endif
7966 return rdiv(a1,b,contextptr);
7967 }
7968 }
7969 if (a.type==_REAL)
7970 return (*a._REALptr)*inv(b,contextptr);
7971 if (b.type==_REAL)
7972 return a*b._REALptr->inv();
7973 if (a.type==_SPOL1)
7974 return spdiv(*a._SPOL1ptr,gen2spol1(b),contextptr);
7975 if (b.type==_SPOL1)
7976 return spdiv(gen2spol1(a),*b._SPOL1ptr,contextptr);
7977 if (a.type==_USER && b.type!=_USER)
7978 return (*a._USERptr)/b;
7979 if (a.type==_USER || b.type==_USER)
7980 return a*inv(b,contextptr);
7981 if (a.type==_FRAC){
7982 if ( (b.type!=_SYMB) && (b.type!=_IDNT) )
7983 return (*a._FRACptr)/b;
7984 return rdiv(_FRAC2_SYMB(a),b,contextptr);
7985 }
7986 if (b.type==_FRAC){
7987 if ( a.type!=_SYMB && a.type!=_IDNT && !(a.type==_VECT && a.subtype==_POLY1__VECT) ) // POLY1__VECT check added feb 2017 for poly hermite normal form
7988 return a/(*b._FRACptr);
7989 //return rdiv(a,_FRAC2_SYMB(b),contextptr);
7990 // return symbolic(at_prod,makesequence(a,b._FRACptr->den,symbolic(at_inv,b._FRACptr->num)));
7991 return (b._FRACptr->den*a)/b._FRACptr->num;
7992 }
7993 if (is_equal(a)){
7994 vecteur & va=*a._SYMBptr->feuille._VECTptr;
7995 if (is_equal(b)){
7996 vecteur & vb=*b._SYMBptr->feuille._VECTptr;
7997 return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(rdiv(va.front(),vb.front(),contextptr),rdiv(va.back(),vb.back(),contextptr))));
7998 }
7999 else
8000 return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(rdiv(va.front(),b,contextptr),rdiv(va.back(),b,contextptr))));
8001 }
8002 if (is_equal(b)){
8003 vecteur & vb=*b._SYMBptr->feuille._VECTptr;
8004 return new_ref_symbolic(symbolic(b._SYMBptr->sommet,makesequence(rdiv(a,vb.front(),contextptr),rdiv(a,vb.back(),contextptr))));
8005 }
8006 /* commented since * is not always commutative
8007 if (a.is_symb_of_sommet(at_prod) && a._SYMBptr->feuille.type==_VECT){
8008 int i=equalposcomp(*a._SYMBptr->feuille._VECTptr,b);
8009 if (i){
8010 vecteur v(*a._SYMBptr->feuille._VECTptr);
8011 v.erase(v.begin()+i-1);
8012 if (v.size()==1)
8013 return v.front();
8014 else
8015 return new_ref_symbolic(symbolic(at_prod,v));
8016 }
8017 }
8018 */
8019 if (b.is_symb_of_sommet(at_neg))
8020 return -rdiv(a,b._SYMBptr->feuille,contextptr);
8021 if ((b.type<=_REAL || b.type==_FLOAT_) && is_strictly_positive(-b,context0))
8022 return -rdiv(a,-b,contextptr);
8023 if ( (a.type==_SYMB) || (a.type==_IDNT) || (a.type==_FUNC) || (b.type==_SYMB) || (b.type==_IDNT) || (b.type==_FUNC) ){
8024 if (is_one(a)) return symb_inv(b);
8025 if (is_minus_one(a)) return -symb_inv(b);
8026 if (a.is_symb_of_sommet(at_prod) && a._SYMBptr->feuille.type==_VECT){
8027 ref_vecteur * vptr = new_ref_vecteur(0);
8028 vptr->v.reserve(a._SYMBptr->feuille._VECTptr->size()+1);
8029 vptr->v=*a._SYMBptr->feuille._VECTptr;
8030 vptr->v.push_back(symb_inv(b));
8031 return symbolic(at_prod,gen(vptr,_SEQ__VECT));
8032 }
8033 return operator_times(a,symb_inv(b),contextptr);
8034 }
8035 if (a.type==_STRNG || b.type==_STRNG)
8036 return gentypeerr(gettext("rdiv"));
8037 return fraction(a,b).normal();
8038 }
8039 }
8040
8041 /* Tests */
8042 // 0 if unknown, 1 if >0, -1 if <0
8043 // no test for symbolics if context_ptr=0
fastsign(const gen & a,GIAC_CONTEXT)8044 int fastsign(const gen & a,GIAC_CONTEXT){
8045 if (is_zero(a,contextptr) || is_undef(a))
8046 return 0;
8047 if (is_inf(a)){
8048 if (a==plus_inf)
8049 return 1;
8050 if (a==minus_inf)
8051 return -1;
8052 return 0;
8053 }
8054 switch (a.type) {
8055 case _INT_:
8056 if (a.val>0)
8057 return 1;
8058 else
8059 return -1;
8060 case _ZINT:
8061 return signint(mpz_cmp_si(*a._ZINTptr,0));
8062 case _FRAC:
8063 return fastsign(a._FRACptr->num,contextptr)*fastsign(a._FRACptr->den,contextptr);
8064 case _CPLX:
8065 return 0;
8066 case _DOUBLE_:
8067 if (a._DOUBLE_val>0)
8068 return 1;
8069 else
8070 return -1;
8071 case _FLOAT_:
8072 return fsign(a._FLOAT_val);
8073 case _REAL:
8074 if (a._REALptr->maybe_zero())
8075 return 0;
8076 return a._REALptr->is_positive(); // this is the sign
8077 case _SYMB:
8078 if (a._SYMBptr->sommet==at_neg)
8079 return -fastsign(a._SYMBptr->feuille,contextptr);
8080 if (a._SYMBptr->sommet==at_inv)
8081 return fastsign(a._SYMBptr->feuille,contextptr);
8082 if (a._SYMBptr->sommet==at_abs || (a._SYMBptr->sommet==at_exp && is_real(a._SYMBptr->feuille,contextptr)))
8083 return 1;
8084 }
8085 if (a.type==_SYMB){
8086 bool aplus=a.is_symb_of_sommet(at_plus);
8087 if (aplus || a.is_symb_of_sommet(at_prod)){
8088 gen f=a._SYMBptr->feuille;
8089 if (f.type==_VECT){
8090 vecteur & v=*f._VECTptr;
8091 int i=0,fs=v.size(),curs=0;
8092 for (;i<fs;++i){
8093 int news=fastsign(v[i],contextptr);
8094 if (news==0)
8095 break;
8096 if (i==0) {
8097 curs=news;
8098 continue;
8099 }
8100 if (aplus && curs!=news)
8101 break;
8102 if (!aplus)
8103 curs=curs*news;
8104 }
8105 if (i==fs)
8106 return curs;
8107 }
8108 }
8109 if (a.is_symb_of_sommet(at_pow)){
8110 gen & f =a._SYMBptr->feuille;
8111 if (f.type==_VECT && f._VECTptr->size()==2){
8112 gen & ex = f._VECTptr->back();
8113 if (ex.type==_INT_){
8114 if (ex.val%2==0)
8115 return 1;
8116 return fastsign(f._VECTptr->front(),contextptr);
8117 }
8118 if (ex.type==_FRAC && ex._FRACptr->den.type==_INT_ && ex._FRACptr->den.val % 2 ==0 )
8119 return 1;
8120 }
8121 }
8122 }
8123 if (is_inf(a)){
8124 if (a==plus_inf)
8125 return 1;
8126 if (a==minus_inf)
8127 return -1;
8128 return 0;
8129 }
8130 if (a.type==_IDNT){
8131 vecteur v;
8132 if (find_range(a,v,contextptr) && v.size()==1 && v.front().type==_VECT && v.front()._VECTptr->size()==2){
8133 if (is_positive(v.front()._VECTptr->front(),contextptr))
8134 return 1;
8135 if (is_positive(-v.front()._VECTptr->back(),contextptr))
8136 return -1;
8137 }
8138 }
8139 gen approx;
8140 if (has_evalf(a,approx,1,contextptr) && (a.type!=approx.type ||a!=approx))
8141 return fastsign(approx,contextptr);
8142 // FIXME GIAC_CONTEXT??
8143 /*
8144 if (contextptr){
8145 gen test=superieur_strict(a,0,contextptr);
8146 if (test.type==_INT_){
8147 if (test.val)
8148 return test.val;
8149 test=inferieur_strict(a,0,contextptr);
8150 if (test.type==_INT_)
8151 return -test.val;
8152 }
8153 }
8154 */
8155 return 0;
8156 }
8157
is_greater(const gen & a,const gen & b,GIAC_CONTEXT)8158 bool is_greater(const gen & a,const gen &b,GIAC_CONTEXT){
8159 gen test=superieur_egal(a,b,contextptr);
8160 if ((test.type==_INT_) && (test.val==1))
8161 return true;
8162 else
8163 return false;
8164 }
8165
is_strictly_greater(const gen & a,const gen & b,GIAC_CONTEXT)8166 bool is_strictly_greater(const gen & a,const gen &b,GIAC_CONTEXT){
8167 gen test=superieur_strict(a,b,contextptr);
8168 if ((test.type==_INT_) && (test.val==1))
8169 return true;
8170 else
8171 return false;
8172 }
8173
is_positive(const gen & a,GIAC_CONTEXT)8174 bool is_positive(const gen & a,GIAC_CONTEXT){
8175 switch (a.type){
8176 case _INT_:
8177 return a.val>=0;
8178 case _CPLX:
8179 return is_zero(*(a._CPLXptr+1)) && is_positive(*a._CPLXptr,contextptr);
8180 case _REAL:
8181 return (a._REALptr->is_positive()>0) || a._REALptr->is_zero();
8182 case _ZINT:
8183 if (mpz_sgn(*a._ZINTptr)==-1)
8184 return false;
8185 else
8186 return true;
8187 case _POLY:
8188 return is_positive(a._POLYptr->coord.front());
8189 case _FRAC:
8190 return (is_positive(a._FRACptr->num,contextptr) && is_positive(a._FRACptr->den,contextptr)) || (is_positive(-a._FRACptr->num,contextptr) && is_positive(-a._FRACptr->den,contextptr));
8191 case _EXT:
8192 return false;
8193 case _SYMB:
8194 if (a==plus_inf)
8195 return true;
8196 if (a==minus_inf)
8197 return false;
8198 if (a._SYMBptr->sommet==at_exp)
8199 return true;
8200 if (a._SYMBptr->sommet==at_ln)
8201 return is_positive(a._SYMBptr->feuille-1,contextptr);
8202 if (a._SYMBptr->sommet==at_program)
8203 return true;
8204 return is_greater(a,0,contextptr);
8205 case _FUNC:
8206 return true;
8207 default:
8208 return is_greater(a,0,contextptr);
8209 }
8210 }
8211
is_strictly_positive(const gen & a,GIAC_CONTEXT)8212 bool is_strictly_positive(const gen & a,GIAC_CONTEXT){
8213 if (a.type==_REAL){
8214 if (a._REALptr->maybe_zero())
8215 return false;
8216 } else {
8217 if (is_exactly_zero(a))
8218 return false;
8219 }
8220 return is_positive(a,contextptr);
8221 }
8222
ck_is_greater(const gen & a,const gen & b,GIAC_CONTEXT)8223 bool ck_is_greater(const gen & a,const gen &b,GIAC_CONTEXT){
8224 if (a==b)
8225 return true;
8226 gen test=superieur_strict(a,b,contextptr);
8227 if (test.type!=_INT_)
8228 cksignerr(test);
8229 if (test.val==1)
8230 return true;
8231 else
8232 return false;
8233 }
8234
ck_is_strictly_greater(const gen & a,const gen & b,GIAC_CONTEXT)8235 bool ck_is_strictly_greater(const gen & a,const gen &b,GIAC_CONTEXT){
8236 gen test=superieur_strict(a,b,contextptr);
8237 if (test.type!=_INT_)
8238 cksignerr(test);
8239 if (test.val==1)
8240 return true;
8241 else
8242 return false;
8243 }
8244
ck_is_positive(const gen & a,GIAC_CONTEXT)8245 bool ck_is_positive(const gen & a,GIAC_CONTEXT){
8246 switch (a.type){
8247 case _INT_:
8248 return a.val>=0;
8249 case _ZINT:
8250 if (mpz_sgn(*a._ZINTptr)==-1)
8251 return false;
8252 else
8253 return true;
8254 case _SYMB:
8255 if (a==plus_inf)
8256 return true;
8257 if (a==minus_inf)
8258 return false;
8259 if (a._SYMBptr->sommet==at_exp)
8260 return true;
8261 if (a._SYMBptr->sommet==at_ln)
8262 return ck_is_positive(a._SYMBptr->feuille-1,contextptr);
8263 return ck_is_greater(a,0,contextptr);
8264 default:
8265 return ck_is_greater(a,0,contextptr);
8266 }
8267 }
8268
ck_is_strictly_positive(const gen & a,GIAC_CONTEXT)8269 bool ck_is_strictly_positive(const gen & a,GIAC_CONTEXT){
8270 if (is_zero(a,contextptr))
8271 return false;
8272 return ck_is_positive(a,contextptr);
8273 }
8274
min(const gen & a,const gen & b,GIAC_CONTEXT)8275 gen min(const gen & a, const gen & b,GIAC_CONTEXT){
8276 if (a.type==_DOUBLE_ && b.type==_DOUBLE_)
8277 return a._DOUBLE_val<b._DOUBLE_val?a._DOUBLE_val:b._DOUBLE_val;
8278 if (a.type==_REAL && b.type==_REAL){
8279 gen s=sign(a-b,contextptr);
8280 if (s==1) return b;
8281 if (s==-1) return a;
8282 }
8283 if (a==b)
8284 return a;
8285 if (is_inf(a)){
8286 if (a==plus_inf)
8287 return b;
8288 if (a==minus_inf)
8289 return a;
8290 if (!is_inf(b))
8291 return undef;
8292 }
8293 if (is_inf(b)){
8294 if (b==plus_inf)
8295 return a;
8296 if (b==minus_inf)
8297 return b;
8298 return undef;
8299 }
8300 if (is_undef(a))
8301 return a;
8302 if (is_undef(b))
8303 return b;
8304 gen test=superieur_strict(a,b,contextptr);
8305 if (test.type==_INT_){
8306 if (test.val==1)
8307 return b;
8308 else
8309 return a;
8310 }
8311 return new_ref_symbolic(symbolic(at_min,makesequence(a,b)));
8312 }
8313
max(const gen & a,const gen & b,GIAC_CONTEXT)8314 gen max(const gen & a, const gen & b,GIAC_CONTEXT){
8315 if (a.type==_INT_ && b.type==_INT_)
8316 return a.val<b.val?b.val:a.val;
8317 if (a.type==_DOUBLE_ && b.type==_DOUBLE_)
8318 return a._DOUBLE_val<b._DOUBLE_val?b._DOUBLE_val:a._DOUBLE_val;
8319 if (a.type==_REAL && b.type==_REAL){
8320 gen s=sign(a-b,contextptr);
8321 if (s==1) return a;
8322 if (s==-1) return b;
8323 }
8324 if (a==b)
8325 return a;
8326 if (is_inf(a)){
8327 if (a==plus_inf)
8328 return a;
8329 if (a==minus_inf)
8330 return b;
8331 if (!is_inf(b))
8332 return undef;
8333 }
8334 if (is_inf(b)){
8335 if (b==plus_inf)
8336 return b;
8337 if (b==minus_inf)
8338 return a;
8339 return undef;
8340 }
8341 if (is_undef(a))
8342 return a;
8343 if (is_undef(b))
8344 return b;
8345 gen test=superieur_strict(a,b,contextptr);
8346 if (test.type==_INT_){
8347 if (test.val==1)
8348 return a;
8349 else
8350 return b;
8351 }
8352 return new_ref_symbolic(symbolic(at_max,makesequence(a,b)));
8353 }
8354
operator !(const gen & a)8355 gen operator !(const gen & a){
8356 if (is_undef(a)) return a;
8357 switch (a.type){
8358 case _INT_: case _ZINT: case _CPLX: case _DOUBLE_: case _FLOAT_:
8359 return change_subtype(is_zero(a,context0),_INT_BOOLEAN);
8360 default:
8361 bool as=a.is_symb_of_sommet(at_superieur_strict);
8362 bool ae=a.is_symb_of_sommet(at_superieur_egal);
8363 if (as || ae){
8364 gen f=a._SYMBptr->feuille;
8365 if (f.type==_VECT && f._VECTptr->size()==2){
8366 return symbolic(ae?at_superieur_strict:at_superieur_egal,makesequence(f._VECTptr->back(),f._VECTptr->front()));
8367 }
8368 }
8369 if (a.is_symb_of_sommet(at_and)){
8370 gen f=_not(a._SYMBptr->feuille,context0);
8371 return symbolic(at_ou,f);
8372 }
8373 if (a.is_symb_of_sommet(at_ou)){
8374 gen f=_not(a._SYMBptr->feuille,context0);
8375 return symbolic(at_and,f);
8376 }
8377 return symb_not(a);
8378 }
8379 }
8380
8381 struct islesscomplexthanf_compare {
islesscomplexthanf_comparegiac::islesscomplexthanf_compare8382 islesscomplexthanf_compare() {}
operator ()giac::islesscomplexthanf_compare8383 bool operator ()(const gen & a,const gen &b){ return islesscomplexthanf(a,b); }
8384 };
8385
islesscomplexthanf_sort(iterateur it,iterateur itend)8386 void islesscomplexthanf_sort(iterateur it,iterateur itend){
8387 islesscomplexthanf_compare m;
8388 sort(it,itend,m);
8389 }
8390
8391 struct f_compare {
8392 bool (*f)(const gen &a,const gen &b);
f_comparegiac::f_compare8393 f_compare():f(islesscomplexthanf){}
f_comparegiac::f_compare8394 f_compare(bool (*f_)(const gen &a,const gen &b)):f(f_){}
operator ()giac::f_compare8395 inline bool operator () (const gen & a,const gen &b){ return f(a,b); }
8396 };
8397
gen_sort_f(iterateur it,iterateur itend,bool (* f)(const gen & a,const gen & b))8398 void gen_sort_f(iterateur it,iterateur itend,bool (*f)(const gen &a,const gen &b)){
8399 f_compare m(f);
8400 sort(it,itend,m);
8401 }
8402
8403
8404 // equality of vecteurs representing geometrical lines
geo_equal(const vecteur & v,const vecteur & w,int subtype,GIAC_CONTEXT)8405 static bool geo_equal(const vecteur &v,const vecteur & w,int subtype,GIAC_CONTEXT){
8406 int vs=int(v.size()),ws=int(w.size());
8407 if (vs!=ws)
8408 return false;
8409 if (v==w)
8410 return true;
8411 if ( (subtype==_LINE__VECT) && (vs==2)){
8412 if (v[1]==v[0])
8413 return v==w;
8414 // v[1]!=v[0]
8415 if (!is_zero(im(rdiv(w[0]-v[0],v[1]-v[0],contextptr),contextptr),contextptr))
8416 return false;
8417 if (!is_zero(im(rdiv(w[1]-v[0],v[1]-v[0],contextptr),contextptr),contextptr))
8418 return false;
8419 return true;
8420 }
8421 if (subtype==_SET__VECT){
8422 vecteur w1(w),v1(v);
8423 #if 1
8424 islesscomplexthanf_sort(w1.begin(),w1.end());
8425 islesscomplexthanf_sort(v1.begin(),v1.end());
8426 #else
8427 sort(w1.begin(),w1.end(),islesscomplexthanf);
8428 sort(v1.begin(),v1.end(),islesscomplexthanf);
8429 #endif
8430 return w1==v1;
8431 }
8432 return false;
8433 }
8434
operator_equal(const gen & a,const gen & b,GIAC_CONTEXT)8435 bool operator_equal(const gen & a,const gen & b,GIAC_CONTEXT){
8436 switch ( (a.type<< _DECALAGE) | b.type ) {
8437 case _INT___INT_:
8438 return (a.val==b.val);
8439 case _INT___MOD: case _ZINT__MOD:
8440 return a==*b._MODptr;
8441 case _MOD__INT_: case _MOD__ZINT:
8442 return b==*a._MODptr;
8443 case _INT___ZINT:
8444 return (mpz_cmp_si(*b._ZINTptr,a.val)==0);
8445 case _INT___DOUBLE_:
8446 return double(a.val)==b._DOUBLE_val;
8447 case _DOUBLE___INT_:
8448 return a._DOUBLE_val==double(b.val);
8449 case _REAL__INT_: case _INT___REAL: case _REAL__ZINT: case _ZINT__REAL: case _REAL__FRAC: case _FRAC__REAL: case _DOUBLE___FRAC: case _FRAC__DOUBLE_: case _FRAC__FLOAT_: case _FLOAT___FRAC:
8450 return is_exactly_zero(a-b);
8451 case _INT___FLOAT_:
8452 return giac_float(a.val)==b._FLOAT_val;
8453 case _FLOAT___INT_:
8454 return a._FLOAT_val==giac_float(b.val);
8455 case _ZINT__INT_:
8456 return (mpz_cmp_si(*a._ZINTptr,b.val)==0);
8457 case _ZINT__ZINT:
8458 return (mpz_cmp(*a._ZINTptr,*b._ZINTptr)==0);
8459 case _INT___CPLX: case _ZINT__CPLX:
8460 return ( operator_equal(a,re(b,contextptr),contextptr) && is_zero(im(b,contextptr),contextptr));
8461 case _CPLX__ZINT: case _CPLX__INT_:
8462 return ( operator_equal(re(a,contextptr),b,contextptr) && is_zero(im(a,contextptr),contextptr)) ;
8463 case _CPLX__CPLX:
8464 return( operator_equal(*a._CPLXptr,*b._CPLXptr,contextptr) && operator_equal(*(a._CPLXptr+1),*(b._CPLXptr+1),contextptr) );
8465 case _DOUBLE___DOUBLE_:
8466 if (a._DOUBLE_val==b._DOUBLE_val)
8467 return true;
8468 if (my_isnan(a._DOUBLE_val) && my_isnan(b._DOUBLE_val))
8469 return true; // avoid infinite loop in evalf
8470 return absdouble(a._DOUBLE_val-b._DOUBLE_val)<absdouble(a._DOUBLE_val)*epsilon(contextptr);
8471 case _FLOAT___FLOAT_:
8472 if (a._FLOAT_val==b._FLOAT_val)
8473 return true;
8474 #ifdef BCD
8475 if (fis_nan(a._FLOAT_val) && fis_nan(b._FLOAT_val))
8476 return true; // avoid infinite loop in evalf
8477 return false;
8478 #else
8479 if (my_isnan(a._FLOAT_val) && my_isnan(b._FLOAT_val))
8480 return true; // avoid infinite loop in evalf
8481 #endif
8482 return fabs(a._FLOAT_val-b._FLOAT_val)<giac_float(epsilon(contextptr));
8483 case _IDNT__IDNT:
8484 // return a.subtype==b.subtype && (a._IDNTptr->name==b._IDNTptr->name || *a._IDNTptr->name==*b._IDNTptr->name);
8485 return a._IDNTptr->id_name==b._IDNTptr->id_name || strcmp(a._IDNTptr->id_name,b._IDNTptr->id_name)==0;
8486 case _SYMB__SYMB:
8487 if (a._SYMBptr==b._SYMBptr)
8488 return true;
8489 if (a._SYMBptr->sommet!=b._SYMBptr->sommet)
8490 return false;
8491 return (a._SYMBptr->feuille==b._SYMBptr->feuille);
8492 case _VECT__VECT:
8493 if (a._VECTptr==b._VECTptr)
8494 return true;
8495 if (a.subtype!=b.subtype){
8496 if ( (a.subtype==_MATRIX__VECT && b.subtype==0) ||
8497 (b.subtype==_MATRIX__VECT && a.subtype==0) )
8498 ; // don't consider them different
8499 else
8500 return false;
8501 }
8502 if (a.subtype)
8503 return geo_equal(*a._VECTptr,*b._VECTptr,a.subtype,contextptr);
8504 return *a._VECTptr==*b._VECTptr;
8505 case _POLY__POLY:
8506 if (a._POLYptr==b._POLYptr)
8507 return true;
8508 return (a._POLYptr->dim==b._POLYptr->dim) && (a._POLYptr->coord==b._POLYptr->coord);
8509 case _FRAC__FRAC:
8510 return (a._FRACptr->num==b._FRACptr->num) && (a._FRACptr->den==b._FRACptr->den);
8511 case _STRNG__STRNG:
8512 if (is_undef(a)) return false;
8513 if (is_undef(b)) return false;
8514 return (a._STRNGptr==b._STRNGptr) || (*a._STRNGptr==*b._STRNGptr);
8515 case _FUNC__FUNC:
8516 return (a._FUNCptr==b._FUNCptr) || (*a._FUNCptr==*b._FUNCptr);
8517 case _MOD__MOD:
8518 return ( (*a._MODptr==*b._MODptr) && (*(a._MODptr+1)==*(b._MODptr+1)) );
8519 case _EXT__EXT:
8520 return ( change_subtype(*a._EXTptr,_POLY1__VECT)==change_subtype(*b._EXTptr,_POLY1__VECT) && (*(a._EXTptr+1)==*(b._EXTptr+1)) );
8521 case _SPOL1__SPOL1:
8522 return *a._SPOL1ptr==*b._SPOL1ptr;
8523 default: // Check pointers, type subtype
8524 if ((a.type==b.type) && (a.subtype==b.subtype) && (a.val==b.val) && a._ZINTptr==b._ZINTptr)
8525 return true;
8526 if (a.type<=_REAL && b.type<=_REAL)
8527 return is_zero(a-b,contextptr);
8528 if ( (a.type==_FLOAT_ || a.type==_DOUBLE_ || a.type==_REAL) && (b.type<=_REAL || b.type==_FRAC || b.type==_FLOAT_))
8529 return is_zero(a-evalf(b,1,contextptr));
8530 if ( (b.type==_FLOAT_ || b.type==_DOUBLE_ || b.type==_REAL) && (a.type<=_REAL || a.type==_FRAC || a.type==_FLOAT_))
8531 return is_zero(evalf(a,1,contextptr)-b);
8532 if (a.type==_USER)
8533 return *a._USERptr==b;
8534 if (b.type==_USER)
8535 return *b._USERptr==a;
8536 if (a.type==_INT_ && a.subtype==_INT_TYPE && b.type==_FUNC){
8537 if (a==_STRNG && b==at_string) return true;
8538 if (a==_VECT && b==at_vector) return true;
8539 if (a==_FLOAT_ && b==at_float) return true;
8540 if (a==_DOUBLE_ && b==at_real) return true;
8541 if (a==_CPLX && b==at_complex) return true;
8542 if ( (a==_INT_||a==_ZINT) && b==at_int) return true;
8543 }
8544 if (b.type==_INT_ && b.subtype==_INT_TYPE && a.type==_FUNC)
8545 return operator_equal(b,a,contextptr);
8546 return false;
8547 }
8548 }
8549
operator ==(const identificateur & i)8550 bool identificateur::operator ==(const identificateur & i){
8551 return id_name==i.id_name || !strcmp(id_name,i.id_name);
8552 }
8553
operator ==(const gen & a,const identificateur & i)8554 bool operator ==(const gen & a,const identificateur & i){
8555 return a.type==_IDNT && (a._IDNTptr->id_name==i.id_name || !strcmp(a._IDNTptr->id_name,i.id_name));
8556 }
8557
operator ==(const gen & i)8558 bool identificateur::operator ==(const gen & i){
8559 return i.type==_IDNT && (id_name==i._IDNTptr->id_name || !strcmp(id_name,i._IDNTptr->id_name));
8560 }
8561
operator ==(const gen & a,const gen & b)8562 bool operator ==(const gen & a,const gen & b){
8563 return operator_equal(a,b,context0);
8564 }
8565
operator !=(const gen & a,const gen & b)8566 bool operator !=(const gen & a,const gen & b){
8567 return !(a==b);
8568 }
8569
equal(const gen & a,const gen & b,GIAC_CONTEXT)8570 gen equal(const gen & a,const gen &b,GIAC_CONTEXT){
8571 if (a.type==_VECT && b.type==_VECT && !b._VECTptr->empty()){
8572 if (calc_mode(contextptr)==1 && a.subtype==_GGBVECT && b.subtype==_GGBVECT){
8573 return symbolic(at_equal,makesequence(a,b));
8574 }
8575 else {
8576 if (a._VECTptr->size()==b._VECTptr->size())
8577 return apply(a,b,contextptr,equal);
8578 return apply2nd(a,b,contextptr,equal);
8579 }
8580 }
8581 if (is_equal(a)) // so that equal(a=0 ,1) returns a=1, used for fsolve
8582 return equal(a._SYMBptr->feuille[0],b,contextptr);
8583 // only in ggb mode, because we want to be able to do subst(x[1],x=[1,2])
8584 if (calc_mode(contextptr)==1 && a.type==_IDNT && b.type==_VECT && b.subtype!=_SEQ__VECT && b.subtype!=_GGB__VECT){
8585 vecteur v=*b._VECTptr;
8586 for (unsigned i=0;i<v.size();++i){
8587 v[i]=symbolic(at_equal,makesequence(a,v[i]));
8588 }
8589 return gen(v,b.subtype);
8590 }
8591 gen res=symbolic(at_equal,makesequence(a,b));
8592 if (a.type==_INT_ && a.subtype==_INT_PLOT && io_graph(contextptr))
8593 __interactive.op(res,contextptr);
8594 return res;
8595 }
8596
equal2(const gen & a,const gen & b,GIAC_CONTEXT)8597 gen equal2(const gen & a,const gen &b,GIAC_CONTEXT){
8598 if (is_equal(a)) // so that equal(a=0 ,1) returns a=1, used for fsolve
8599 return equal(a._SYMBptr->feuille[0],b,contextptr);
8600 // only in ggb mode, because we want to be able to do subst(x[1],x=[1,2])
8601 if (calc_mode(contextptr)==1 && a.type==_IDNT && b.type==_VECT){
8602 vecteur v=*b._VECTptr;
8603 for (unsigned i=0;i<v.size();++i){
8604 v[i]=symbolic(at_equal2,makesequence(a,v[i]));
8605 }
8606 return gen(v,b.subtype);
8607 }
8608 gen res=symbolic(at_equal2,makesequence(a,b));
8609 if (a.type==_INT_ && a.subtype==_INT_PLOT && io_graph(contextptr))
8610 __interactive.op(res,contextptr);
8611 return res;
8612 }
8613
sign(const gen & a,GIAC_CONTEXT)8614 gen sign(const gen & a,GIAC_CONTEXT){
8615 if (is_equal(a))
8616 return apply_to_equal(a,sign,contextptr);
8617 if (complex_mode(contextptr)==0 && !has_i(a)){
8618 if (a.is_symb_of_sommet(at_exp))
8619 return 1;
8620 if (a.is_symb_of_sommet(at_pow)){
8621 gen f=a._SYMBptr->feuille[1];
8622 if (f.type==_FRAC && f._FRACptr->den.type==_INT_ && f._FRACptr->den.val %2==0)
8623 return 1;
8624 }
8625 }
8626 if (a.is_symb_of_sommet(at_neg) && !is_inf(a))
8627 return -sign(a._SYMBptr->feuille,contextptr);
8628 if (a.is_symb_of_sommet(at_inv))
8629 return sign(a._SYMBptr->feuille,contextptr);
8630 if (a.is_symb_of_sommet(at_prod)){
8631 vecteur v=gen2vecteur(a._SYMBptr->feuille);
8632 gen res=1;
8633 for (int i=0;i<int(v.size());++i){
8634 res=res*sign(v[i],contextptr);
8635 }
8636 return res;
8637 }
8638 if (is_exactly_zero(a)){
8639 if (a.type==_DOUBLE_ || a.type==_FLOAT_)
8640 return 0.0;
8641 else
8642 return 0;
8643 }
8644 if (a==plus_inf)
8645 return 1;
8646 if (a==minus_inf)
8647 return -1;
8648 if (is_undef(a))
8649 return a;
8650 if (is_inf(a))
8651 return undef;
8652 double eps=epsilon(contextptr);
8653 if (eps>1e-6)
8654 *logptr(contextptr) << gettext("Warning, sign might return 0 incorrectly because the value of eps is too large ") << eps << '\n';
8655 switch (a.type){
8656 case _INT_: case _ZINT:
8657 if (is_positive(a,contextptr))
8658 return 1;
8659 else
8660 return -1;
8661 case _DOUBLE_:
8662 if (a._DOUBLE_val>eps)
8663 return 1.0;
8664 if (a._DOUBLE_val<-eps)
8665 return -1.0;
8666 return 0.0;
8667 case _FLOAT_: // NOTE: does not follow eps rule
8668 if (a._FLOAT_val>0)
8669 return giac_float(1.0);
8670 if (a._FLOAT_val<0)
8671 return giac_float(-1.0);
8672 return giac_float(0.0);
8673 case _REAL:
8674 {
8675 if (a._REALptr->is_zero())
8676 return 0;
8677 if (a._REALptr->maybe_zero())
8678 return undef;
8679 int res=a._REALptr->is_positive();
8680 if (res)
8681 return res;
8682 return undef;
8683 }
8684 return -1;
8685 case _CPLX:
8686 return a/abs(a,contextptr);
8687 case _FRAC:
8688 return sign(a._FRACptr->num,contextptr)*sign(a._FRACptr->den,contextptr);
8689 }
8690 int fs=fastsign(a,contextptr);
8691 if (fs)
8692 return fs;
8693 gen b=evalf_double(a,1,contextptr);
8694 if (b.type==_DOUBLE_){
8695 if (b._DOUBLE_val>eps)
8696 return plus_one;
8697 if (b._DOUBLE_val<-eps)
8698 return minus_one;
8699 #ifdef HAVE_LIBMPFR // FIXME try to avoid rounding errors
8700 b=accurate_evalf(eval(a,1,contextptr),1000);
8701 if (is_greater(b,1e-250,contextptr))
8702 return plus_one;
8703 if (is_greater(-1e-250,b,contextptr))
8704 return minus_one;
8705 #endif
8706 // return zero; // returning 0 is wrong, sign(a) is much better!
8707 }
8708 if (b.type==_FLOAT_){
8709 if (b._FLOAT_val>eps)
8710 return plus_one;
8711 if (b._FLOAT_val<-eps)
8712 return minus_one;
8713 return zero;
8714 }
8715 if (is_zero(im(a,contextptr),contextptr)){
8716 int s=sturmsign(a,true,contextptr);
8717 if (s && s!=-2)
8718 return s;
8719 }
8720 return new_ref_symbolic(symbolic(at_sign,a));
8721 }
8722
sym_is_greater(const gen & a,const gen & b,GIAC_CONTEXT)8723 static gen sym_is_greater(const gen & a,const gen & b,GIAC_CONTEXT){
8724 if (is_undef(a))
8725 return a;
8726 if (is_undef(b))
8727 return b;
8728 if (a==unsigned_inf || b==unsigned_inf || a.type==_VECT || b.type==_VECT)
8729 return undef;
8730 if (a==b)
8731 return false;
8732 if ( (b==plus_inf) || (a==minus_inf) )
8733 return false;
8734 if ( (b==minus_inf) || (a==plus_inf) )
8735 return true;
8736 if (is_equal(a) && is_equal(b) ){
8737 gen & af=a._SYMBptr->feuille;
8738 gen & bf=b._SYMBptr->feuille;
8739 if (af.type==_VECT && bf.type==_VECT && af._VECTptr->size()==2 && bf._VECTptr->size()==2 && af._VECTptr->front()==bf._VECTptr->front())
8740 return sym_is_greater(af._VECTptr->back(),bf._VECTptr->back(),contextptr);
8741 }
8742 if (a.type==_STRNG && b.type==_STRNG)
8743 return *a._STRNGptr>=*b._STRNGptr;
8744 if (a.type==_USER)
8745 return (*a._USERptr>b);
8746 if (b.type==_USER)
8747 return (*b._USERptr<=a);
8748 if (a.is_symb_of_sommet(at_superieur_strict) || a.is_symb_of_sommet(at_superieur_egal) || a.is_symb_of_sommet(at_inferieur_strict) || a.is_symb_of_sommet(at_inferieur_egal) )
8749 return false;
8750 if (b.is_symb_of_sommet(at_superieur_strict) || b.is_symb_of_sommet(at_superieur_egal) || b.is_symb_of_sommet(at_inferieur_strict) || b.is_symb_of_sommet(at_inferieur_egal) )
8751 return false;
8752 if (a.type==_CPLX || b.type==_CPLX)
8753 return symb_superieur_strict(a,b);
8754 gen approx;
8755 if (has_evalf(a,approx,1,contextptr) && approx.type==_CPLX && !is_zero(im(approx,contextptr)/re(approx,contextptr),contextptr))
8756 return symb_superieur_strict(a,b);
8757 if (has_evalf(a-b,approx,1,contextptr)){
8758 if (approx.type==_CPLX && is_zero(im(approx,contextptr)/re(approx,contextptr),contextptr))
8759 approx=re(approx,contextptr);
8760 if (approx.type==_DOUBLE_ ){
8761 #ifdef HAVE_LIBMPFR
8762 // FIXME?? try to avoid rounding error with more digits
8763 if (fabs(approx._DOUBLE_val)<1e-5 && (a-b).type!=_FRAC){
8764 gen tmp=accurate_evalf(eval(a-b,1,contextptr),1000);
8765 tmp=evalf_double(tmp,1,contextptr);
8766 if (tmp.type==_DOUBLE_)
8767 approx=tmp;
8768 }
8769 #endif
8770 return (approx._DOUBLE_val>0);
8771 }
8772 if (approx.type==_REAL)
8773 return is_strictly_positive(approx,contextptr);
8774 if (approx.type==_FLOAT_ )
8775 return (approx._FLOAT_val>0);
8776 }
8777 gen g=sign(a-b,contextptr);
8778 if (is_one(g))
8779 return plus_one;
8780 if (is_minus_one(g))
8781 return false;
8782 return symb_superieur_strict(a,b);
8783 }
8784
superieur_strict(const gen & a,const gen & b,GIAC_CONTEXT)8785 gen superieur_strict(const gen & a,const gen & b,GIAC_CONTEXT){
8786 switch ( (a.type<< _DECALAGE) | b.type ) {
8787 case _INT___INT_:
8788 return (a.val>b.val);
8789 case _INT___ZINT:
8790 return (mpz_cmp_si(*b._ZINTptr,a.val)<0);
8791 case _ZINT__INT_:
8792 return (mpz_cmp_si(*a._ZINTptr,b.val)>0);
8793 case _ZINT__ZINT:
8794 return (mpz_cmp(*a._ZINTptr,*b._ZINTptr)>0);
8795 case _DOUBLE___DOUBLE_:
8796 return a._DOUBLE_val>b._DOUBLE_val;
8797 case _FRAC__FRAC:
8798 if (is_positive(a._FRACptr->den,contextptr) && is_positive(b._FRACptr->den,contextptr))
8799 return superieur_strict(a._FRACptr->num*b._FRACptr->den,a._FRACptr->den*b._FRACptr->num,contextptr);
8800 break;
8801 case _FRAC__INT_:
8802 if (is_positive(a._FRACptr->den,contextptr))
8803 return superieur_strict(a._FRACptr->num,a._FRACptr->den*b,contextptr);
8804 break;
8805 case _INT___FRAC:
8806 if (is_positive(b._FRACptr->den,contextptr))
8807 return superieur_strict(b._FRACptr->den*a,b._FRACptr->num,contextptr);
8808 break;
8809 case _DOUBLE___INT_:
8810 return a._DOUBLE_val>b.val;
8811 case _INT___DOUBLE_:
8812 return a.val>b._DOUBLE_val;
8813 case _FLOAT___FLOAT_:
8814 return a._FLOAT_val>b._FLOAT_val;
8815 case _FLOAT___INT_:
8816 return a._FLOAT_val>b.val;
8817 case _INT___FLOAT_:
8818 return a.val>b._FLOAT_val;
8819 case _DOUBLE___ZINT:
8820 return a._DOUBLE_val>mpz_get_d(*b._ZINTptr);
8821 case _ZINT__DOUBLE_:
8822 return mpz_get_d(*a._ZINTptr)>b._DOUBLE_val;
8823 }
8824 if (a.type<=_REAL && b.type<=_REAL)
8825 return is_strictly_positive(a-b,contextptr);
8826 return sym_is_greater(a,b,contextptr);
8827 }
8828
inferieur_strict(const gen & a,const gen & b,GIAC_CONTEXT)8829 gen inferieur_strict(const gen & a,const gen & b,GIAC_CONTEXT){
8830 return superieur_strict(b,a,contextptr);
8831 }
8832
superieur_egal(const gen & a,const gen & b,GIAC_CONTEXT)8833 gen superieur_egal(const gen & a,const gen & b,GIAC_CONTEXT){
8834 if ( (a.type==_REAL && b.type<=_REAL) ||
8835 (b.type==_REAL && a.type<=_REAL) ){
8836 if (is_positive(a-b,contextptr))
8837 return 1;
8838 return 0;
8839 }
8840 gen g=!superieur_strict(b,a,contextptr);
8841 if (is_undef(g)) return g;
8842 if (g.type==_INT_)
8843 return g;
8844 return symb_superieur_egal(a,b);
8845 }
8846
inferieur_egal(const gen & a,const gen & b,GIAC_CONTEXT)8847 gen inferieur_egal(const gen & a,const gen & b,GIAC_CONTEXT){
8848 return superieur_egal(b,a,contextptr);
8849 }
8850
has_inf_or_undef(const gen & g)8851 bool has_inf_or_undef(const gen & g){
8852 if (g.type!=_VECT)
8853 return is_inf(g) || is_undef(g);
8854 const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
8855 for (;it!=itend;++it){
8856 if (has_inf_or_undef(*it))
8857 return true;
8858 }
8859 return false;
8860 }
8861
is_inf(const gen & e)8862 bool is_inf(const gen & e){
8863 switch (e.type){
8864 case _IDNT:
8865 return !strcmp(e._IDNTptr->id_name,string_infinity);
8866 case _SYMB:
8867 return is_inf(e._SYMBptr->feuille);
8868 case _DOUBLE_:
8869 return my_isinf(e._DOUBLE_val);
8870 case _FLOAT_:
8871 return fis_inf(e._FLOAT_val);
8872 default:
8873 return false;
8874 }
8875 }
is_undef(const vecteur & v)8876 bool is_undef(const vecteur & v){
8877 return !v.empty() && is_undef(v.front());
8878 }
is_undef(const polynome & p)8879 bool is_undef(const polynome & p){
8880 return !p.coord.empty() && is_undef(p.coord.front());
8881 }
8882 // we are using exponent as undef marker because coeff=undef is used
8883 // for Landau notation O(x^exponent)
is_undef(const sparse_poly1 & s)8884 bool is_undef(const sparse_poly1 & s){
8885 return !s.empty() && is_undef(s.front().exponent);
8886 }
is_undef(const gen & e)8887 bool is_undef(const gen & e){
8888 switch (e.type){
8889 case _IDNT:
8890 return !strcmp(e._IDNTptr->id_name,string_undef);
8891 case _STRNG:
8892 return e.subtype==-1;
8893 case _VECT:
8894 return !e._VECTptr->empty() && is_undef(e._VECTptr->front());
8895 case _POLY:
8896 return !e._POLYptr->coord.empty() && is_undef(e._POLYptr->coord.front().value);
8897 case _SPOL1:
8898 return !e._SPOL1ptr->empty() && is_undef(e._SPOL1ptr->front().exponent);
8899 case _FLOAT_:
8900 return fis_nan(e._FLOAT_val);
8901 case _DOUBLE_:
8902 return my_isnan(e._DOUBLE_val);
8903 case _CPLX:
8904 return is_undef(*e._CPLXptr) || is_undef(*(e._CPLXptr+1));
8905 case _FRAC:
8906 return is_undef(e._FRACptr->num);
8907 default:
8908 return false;
8909 }
8910 }
8911
is_zero__VECT(const vecteur & v,GIAC_CONTEXT)8912 bool is_zero__VECT(const vecteur & v,GIAC_CONTEXT){
8913 vecteur::const_iterator it=v.begin(),itend=v.end();
8914 for (;it!=itend;++it){
8915 if (!is_zero(*it,contextptr))
8916 return false;
8917 }
8918 return true;
8919 }
8920
is_zero(const gen & a,GIAC_CONTEXT)8921 bool is_zero(const gen & a,GIAC_CONTEXT){
8922 switch (a.type ) {
8923 case _INT_:
8924 return !a.val;
8925 case _ZINT:
8926 return (!mpz_sgn(*a._ZINTptr));
8927 case _REAL:
8928 return fabs(evalf_double(a,1,contextptr)._DOUBLE_val)<=epsilon(contextptr);// return a._REALptr->is_zero();
8929 case _CPLX:
8930 return (is_zero(*a._CPLXptr,contextptr) && is_zero(*(a._CPLXptr+1),contextptr));
8931 case _DOUBLE_:
8932 return (fabs(a._DOUBLE_val)<=epsilon(contextptr));
8933 case _FLOAT_:
8934 return is_exactly_zero(a._FLOAT_val);
8935 case _VECT:
8936 return is_zero__VECT(*a._VECTptr,contextptr);
8937 case _POLY:
8938 return a._POLYptr->coord.empty();
8939 case _FRAC:
8940 return is_zero(a._FRACptr->num,contextptr);
8941 case _MOD:
8942 return is_zero(*a._MODptr,contextptr);
8943 case _USER:
8944 return a._USERptr->is_zero();
8945 case _SYMB:
8946 if (a._SYMBptr->sommet==at_unit)
8947 return is_zero(a._SYMBptr->feuille[0]);
8948 default:
8949 return false;
8950 }
8951 }
8952
is_exactly_zero(const gen & a)8953 bool is_exactly_zero(const gen & a){
8954 switch (a.type ) {
8955 case _INT_:
8956 return !a.val;
8957 case _ZINT:
8958 return (!mpz_sgn(*a._ZINTptr));
8959 case _REAL:
8960 return a._REALptr->is_zero();
8961 case _CPLX:
8962 return (is_exactly_zero(*a._CPLXptr) && is_exactly_zero(*(a._CPLXptr+1)));
8963 case _DOUBLE_:
8964 return a._DOUBLE_val==0;
8965 case _FLOAT_:
8966 return fis_exactly_zero(a._FLOAT_val);
8967 case _POLY:
8968 return a._POLYptr->coord.empty();
8969 case _FRAC:
8970 return is_exactly_zero(a._FRACptr->num);
8971 case _MOD:
8972 return is_exactly_zero(*a._MODptr);
8973 case _USER:
8974 return a._USERptr->is_zero();
8975 default:
8976 return false;
8977 }
8978 }
8979
is_one(const gen & a)8980 bool is_one(const gen & a){
8981 switch (a.type ) {
8982 case _INT_:
8983 return a.val==1;
8984 case _ZINT:
8985 return mpz_cmp_si(*a._ZINTptr,1)==0;
8986 case _CPLX:
8987 return is_one(*a._CPLXptr) && is_zero(*(a._CPLXptr+1));
8988 case _DOUBLE_:
8989 return a._DOUBLE_val==1;
8990 case _FLOAT_:
8991 return a._FLOAT_val==giac_float(1);
8992 case _REAL:
8993 return is_exactly_zero(a-1);
8994 case _VECT:
8995 return a._VECTptr->size()==1 && is_one(a._VECTptr->front());
8996 case _POLY:
8997 return Tis_constant(*a._POLYptr) && (is_one(a._POLYptr->coord.front().value));
8998 case _FRAC:
8999 return a._FRACptr->num == a._FRACptr->den;
9000 case _MOD:
9001 return is_one(*a._MODptr);
9002 case _USER:
9003 return a._USERptr->is_one();
9004 default:
9005 return false;
9006 }
9007 }
9008
is_minus_one(const gen & a)9009 bool is_minus_one(const gen & a){
9010 switch (a.type ) {
9011 case _INT_:
9012 return a.val==-1;
9013 case _ZINT:
9014 return mpz_cmp_si(*a._ZINTptr,-1)==0;
9015 case _CPLX:
9016 return (is_minus_one(*a._CPLXptr) && is_zero(*(a._CPLXptr+1),context0));
9017 case _DOUBLE_:
9018 return a._DOUBLE_val==-1;
9019 case _FLOAT_:
9020 return a._FLOAT_val==giac_float(-1);
9021 case _REAL:
9022 return is_exactly_zero(a+1);
9023 case _VECT:
9024 return a._VECTptr->size()==1 && is_minus_one(a._VECTptr->front());
9025 case _POLY:
9026 return Tis_constant(*a._POLYptr) && (is_minus_one(a._POLYptr->coord.front().value));
9027 case _FRAC:
9028 return a._FRACptr->num == -a._FRACptr->den;
9029 case _MOD:
9030 if (*(a._MODptr+1)==plus_two)
9031 return is_one(*a._MODptr);
9032 else
9033 return is_minus_one(*a._MODptr);
9034 case _SYMB:
9035 return a._SYMBptr->sommet==at_neg && is_one(a._SYMBptr->feuille);
9036 case _USER:
9037 return a._USERptr->is_minus_one();
9038 default:
9039 return false;
9040 }
9041 }
9042
is_sq_minus_one(const gen & a)9043 bool is_sq_minus_one(const gen & a){
9044 switch (a.type ) {
9045 case _CPLX: case _MOD: case _USER:
9046 return is_minus_one(a*a);
9047 case _VECT:
9048 return a._VECTptr->size()==1 && is_sq_minus_one(a._VECTptr->front());
9049 case _POLY:
9050 return Tis_constant(*a._POLYptr) && (is_sq_minus_one(a._POLYptr->coord.front().value));
9051 default:
9052 return false;
9053 }
9054 }
9055
operator [](int i) const9056 gen gen::operator [] (int i) const{
9057 return operator_at(i,context0);
9058 }
9059
operator_at(int i,GIAC_CONTEXT) const9060 gen gen::operator_at(int i,GIAC_CONTEXT) const{
9061 if (type==_SYMB){
9062 if (!i)
9063 return _SYMBptr->sommet;
9064 if (_SYMBptr->feuille.type!=_VECT){
9065 if (i==1)
9066 return _SYMBptr->feuille;
9067 else
9068 return gendimerr(contextptr);
9069 }
9070 if (unsigned(i)>_SYMBptr->feuille._VECTptr->size())
9071 return gendimerr(contextptr);
9072 return (*(_SYMBptr->feuille._VECTptr))[i-1];
9073 }
9074 if (type==_MOD){
9075 if (!i)
9076 return _MOD;
9077 if (i==1)
9078 return *_MODptr;
9079 if (i==2)
9080 return *(_MODptr+1);
9081 return gendimerr(contextptr);
9082 }
9083 if (type==_IDNT)
9084 return symb_at(makesequence(*this,i));
9085 if (type==_FUNC){
9086 if (*this==at_ln){
9087 i=i+array_start(contextptr); // (xcas_mode(contextptr)!=0);
9088 return inv(ln(i,contextptr),contextptr)*(*this);
9089 }
9090 if (*this==at_maple_root){
9091 identificateur tmp(" x");
9092 gen g=symb_program(tmp,zero,new_ref_symbolic(symbolic(at_makesuite,i,tmp)),contextptr);
9093 g=makesequence(at_maple_root,g);
9094 return symb_compose(g);
9095 }
9096 }
9097 if (this->type!=_VECT){
9098 if (calc_mode(contextptr)==1)
9099 return *this;
9100 return gentypeerr(gettext("Gen [int]"));
9101 }
9102 if (i<0) i+=_VECTptr->size();
9103 if (unsigned(i)>=_VECTptr->size()){
9104 if (array_start(contextptr))//(xcas_mode(contextptr)!=0 || abs_calc_mode(contextptr)==38)
9105 ++i;
9106 return gendimerr(gettext("Index outside range : ")+ print_INT_(i)+", vector size is "+print_INT_(int(_VECTptr->size()))
9107 #ifndef GIAC_HAS_STO_38
9108 +", syntax compatibility mode "+print_program_syntax(xcas_mode(contextptr))
9109 #endif
9110 +"\n");
9111 }
9112 return (*(this->_VECTptr))[i];
9113 }
9114
operator [](const gen & i) const9115 gen gen::operator [] (const gen & i) const {
9116 return operator_at(i,context0);
9117 }
9118
operator_at(const gen & i,GIAC_CONTEXT) const9119 gen gen::operator_at(const gen & i,GIAC_CONTEXT) const {
9120 if (type==_STRNG && subtype==-1) return *this;
9121 if (i.type==_DOUBLE_){
9122 double id=i._DOUBLE_val;
9123 if (int(id)==id)
9124 return (*this)[int(id)];
9125 }
9126 if (i.type==_FLOAT_){
9127 giac_float id=i._FLOAT_val;
9128 if (giac_float(get_int(id))==id)
9129 return (*this)[get_int(id)];
9130 }
9131 if (i.type==_REAL){
9132 double id=i.evalf_double(1,contextptr)._DOUBLE_val;
9133 if (int(id)==id)
9134 return (*this)[int(id)];
9135 }
9136 if ((type==_STRNG) && (i.type==_INT_)){
9137 int s=int(_STRNGptr->size()),I=i.val;
9138 if (I<0) I+=s;
9139 if ( (I<s) && (I>=0))
9140 return string2gen(string()+'"'+(*_STRNGptr)[I]+'"');
9141 }
9142 if (type==_IDNT)
9143 return new_ref_symbolic(symbolic(at_at,gen(makenewvecteur(*this,i),_SEQ__VECT)));
9144 if (type==_USER)
9145 return (*_USERptr)[i];
9146 if (type==_MAP){
9147 gen_map::const_iterator it=_MAPptr->find(i),itend=_MAPptr->end();
9148 if (it!=itend)
9149 return it->second;
9150 if (subtype==_SPARSE_MATRIX)
9151 return 0;
9152 }
9153 if (type==_SPOL1){
9154 sparse_poly1::const_iterator it=_SPOL1ptr->begin(),itend=_SPOL1ptr->end();
9155 for (;it!=itend;++it){
9156 if (it->exponent==i)
9157 return it->coeff;
9158 }
9159 return 0;
9160 }
9161 if (is_symb_of_sommet(at_at)){ // add i at the end of the index
9162 if (_SYMBptr->feuille.type==_VECT && _SYMBptr->feuille._VECTptr->size()==2){
9163 gen operand=_SYMBptr->feuille._VECTptr->front();
9164 vecteur indice=makevecteur(_SYMBptr->feuille._VECTptr->back());
9165 indice.push_back(i);
9166 return symb_at(makenewvecteur(operand,gen(indice,_SEQ__VECT)));
9167 }
9168 }
9169 if (i.type==_DOUBLE_)
9170 return (*this)[(int) i._DOUBLE_val];
9171 if (i.type==_FLOAT_)
9172 return (*this)[ get_int(i._FLOAT_val) ];
9173 if (i.type==_SYMB){
9174 bool ideuxpoints=i._SYMBptr->sommet==at_deuxpoints;
9175 if (i._SYMBptr->sommet==at_interval || ideuxpoints) {
9176 gen i1=_ceil(i._SYMBptr->feuille._VECTptr->front(),contextptr);
9177 gen iback=i._SYMBptr->feuille._VECTptr->back();
9178 int step=1;
9179 if (ideuxpoints && iback.is_symb_of_sommet(at_deuxpoints)){
9180 gen istep=iback._SYMBptr->feuille;
9181 iback=istep[0];
9182 istep=istep[1]+array_start(contextptr);
9183 if (!is_integral(istep) || istep.type!=_INT_ || istep.val==0)
9184 return gendimerr(contextptr);
9185 step=istep.val;
9186 if (step<0 && is_zero(i1))
9187 i1=minus_one;
9188 if (0 && step<0 && is_zero(iback)){ // detected during translation
9189 *logptr(contextptr) << gettext("Warning, using :0:-step, use :-1:-step for ::") << '\n';
9190 }
9191 }
9192 gen i2=_floor(iback,contextptr);
9193 if (is_integral(i1) && is_integral(i2)){
9194 int debut=i1.val,fin=i2.val+(ideuxpoints?(step<0?1:-1):0);
9195 int S=1;
9196 if (type==_STRNG) S=int(_STRNGptr->size());
9197 if (type==_VECT) S=int(_VECTptr->size());
9198 if (debut>=S)
9199 return (type==_STRNG)?string2gen("",false):gen(vecteur(0),subtype);
9200 if (debut<0) debut+=S;
9201 if (fin<0) fin+=S;
9202 fin=giacmin(fin,S-1);
9203 debut=giacmin(debut,S-1);
9204 if (debut<0 || step*double(fin-debut)<0 )
9205 return (type==_STRNG)?string2gen("",false):gen(vecteur(0),subtype); // swap(debut,fin);
9206 if (step==1){
9207 if (type==_STRNG)
9208 return string2gen('"'+_STRNGptr->substr(debut,fin-debut+1)+'"');
9209 if (type==_VECT)
9210 return gen(vecteur(_VECTptr->begin()+debut,_VECTptr->begin()+fin+1),subtype);
9211 }
9212 if (type==_STRNG){
9213 const string & s=*_STRNGptr;
9214 string res;
9215 if (step<0){
9216 for (;debut>=fin;debut+=step)
9217 res += s[debut];
9218 }
9219 else {
9220 for (;debut<=fin;debut+=step)
9221 res += s[debut];
9222 }
9223 return string2gen(res,false);
9224 }
9225 if (type==_VECT){
9226 const vecteur & v=*_VECTptr;
9227 vecteur res;
9228 res.reserve(absint(fin-debut)/step+1);
9229 if (step<0){
9230 for (;debut>=fin;debut+=step)
9231 res.push_back(v[debut]);
9232 }
9233 else {
9234 for (;debut<=fin;debut+=step)
9235 res.push_back(v[debut]);
9236 }
9237 return gen(res,subtype);
9238 }
9239 }
9240 }
9241 }
9242 if (i.type==_VECT){
9243 const_iterateur it=i._VECTptr->begin(),itend=i._VECTptr->end();
9244 gen res (*this);
9245 for (;it!=itend;++it){
9246 if (it->type==_VECT){
9247 vecteur tmp;
9248 const_iterateur jt=it->_VECTptr->begin(),jtend=it->_VECTptr->end();
9249 for (;jt!=jtend;++jt){
9250 tmp.push_back(res[*jt]);
9251 }
9252 return gen(tmp,it->subtype);
9253 }
9254 bool itdeuxpoints=it->type==_SYMB && it->_SYMBptr->sommet==at_deuxpoints;
9255 if ( (it->type==_SYMB) && (it->_SYMBptr->sommet==at_interval || itdeuxpoints) && (it+1!=itend) ){
9256 // submatrix extraction
9257 gen i1=it->_SYMBptr->feuille._VECTptr->front(),iback=it->_SYMBptr->feuille._VECTptr->back();
9258 int step=1;
9259 if (itdeuxpoints && iback.is_symb_of_sommet(at_deuxpoints)){
9260 gen istep=iback._SYMBptr->feuille;
9261 iback=istep[0];
9262 istep=istep[1]+array_start(contextptr);
9263 if (!is_integral(istep) || istep.type!=_INT_ || istep==0)
9264 return gendimerr(contextptr);
9265 step=istep.val;
9266 if (step<0 && is_zero(i1))
9267 i1=minus_one;
9268 if (step<0 && is_zero(iback)){
9269 *logptr(contextptr) << gettext("Warning, using :0:-step, use :-1:-step for ::") << '\n';
9270 }
9271 }
9272 if (i1.type==_INT_ && iback.type==_INT_){
9273 int debut=i1.val,fin=iback.val+(itdeuxpoints?(step<0?1:-1):0);
9274 if (res.type==_VECT){
9275 int S=int(res._VECTptr->size());
9276 if (debut<0) debut +=S;
9277 if (fin<0) fin +=S;
9278 fin=giacmin(fin,S-1);
9279 debut=giacmin(debut,S-1);
9280 if (debut<0 || step*double(fin-debut)<0 )
9281 return gendimerr(contextptr);
9282 iterateur jt=res._VECTptr->begin()+debut,jtend=_VECTptr->begin()+fin;
9283 gen fin_it(vecteur(it+1,itend),_SEQ__VECT);
9284 vecteur v;
9285 v.reserve(absint(jtend-jt)/step+1);
9286 if (step<0){
9287 for (;jt>=jtend;jt+=step)
9288 v.push_back((*jt)[fin_it]);
9289 }
9290 else {
9291 for (;jt<=jtend;jt+=step)
9292 v.push_back((*jt)[fin_it]);
9293 }
9294 if (res.subtype==_MATRIX__VECT && !ckmatrix(v))
9295 return v;
9296 return gen(v,res.subtype);
9297 }
9298 }
9299 }
9300 res = res[*it];
9301 }
9302 return res;
9303 }
9304 if (i.type!=_INT_)
9305 return symb_at(makesequence(*this,i));
9306 return this->operator_at(i.val,contextptr);
9307 }
9308
9309 /*
9310 gen & gen::operator [](int i){
9311 if (this->type!=_VECT)
9312 return gentypeerr(gettext("Gen [int]"));
9313 if (i>=_VECTptr->size())
9314 return gendimerr(contextptr);
9315 return (*(this->_VECTptr))[i];
9316 }
9317
9318 gen & gen::operator [] (const gen & i) {
9319 if (i.type==_DOUBLE_)
9320 return (*this)[(int) i._DOUBLE_val];
9321 if (i.type!=_INT_)
9322 return gentypeerr(gettext("Gen [gen]"));
9323 if (this->type!=_VECT)
9324 return gentypeerr(gettext("Gen [gen]"));
9325 if (i.val>=_VECTptr->size())
9326 return gendimerr(gettext("Gen [_VECT]"));
9327 return (*(this->_VECTptr))[i.val];
9328 }
9329 */
9330
operator ()(const gen & i,const context * contextptr) const9331 gen gen::operator () (const gen & i,const context * contextptr) const{
9332 return (*this)(i,undef,contextptr);
9333 }
9334
operator ()(const gen & i,const gen & progname,const context * contextptr) const9335 gen gen::operator () (const gen & i,const gen & progname,const context * contextptr) const{
9336 bool isprog=type==_FUNC || this->is_symb_of_sommet(at_program) || this->is_symb_of_sommet(*at_program);
9337 if (!isprog){
9338 if (i.is_symb_of_sommet(at_equal))
9339 return _subst(makesequence(*this,i),contextptr);
9340 if (i.type==_VECT){
9341 vecteur & v = *i._VECTptr;
9342 vecteur vin,vout;
9343 for (unsigned j=0;j<v.size();++j){
9344 if (!v[j].is_symb_of_sommet(at_equal))
9345 break;
9346 vin.push_back(v[j]._SYMBptr->feuille[0]);
9347 vout.push_back(v[j]._SYMBptr->feuille[1]);
9348 }
9349 if (vin.size()==v.size())
9350 return subst(*this,vin,vout,false,contextptr);
9351 }
9352 }
9353 if (type==_SYMB){
9354 // Functional case for sommet
9355 if (_SYMBptr->sommet==at_program) {
9356 gen tmp=_SYMBptr->feuille;
9357 if (tmp.type!=_VECT)
9358 return gensizeerr(contextptr);
9359 vecteur tmpv=*tmp._VECTptr; tmpv[1]=i;
9360 return _program(gen(tmpv,tmp.subtype),progname,contextptr);
9361 }
9362 #ifndef RTOS_THREADX
9363 if (_SYMBptr->sommet==at_rpn_prog){
9364 vecteur pile;
9365 if (rpn_mode(contextptr))
9366 pile=history_out(contextptr);
9367 if ( (i.type!=_VECT) || (i.subtype!=_SEQ__VECT))
9368 pile.push_back(i);
9369 else
9370 pile=mergevecteur(pile,*i._VECTptr);
9371 vecteur prog;
9372 if (_SYMBptr->feuille.type==_VECT)
9373 prog=*_SYMBptr->feuille._VECTptr;
9374 else
9375 prog=vecteur(1,_SYMBptr->feuille);
9376 return gen(rpn_eval(prog,pile,contextptr),_RPN_STACK__VECT);
9377 }
9378 #endif
9379 if (_SYMBptr->sommet==at_compose){
9380 gen tmp=_SYMBptr->feuille;
9381 if (tmp.type!=_VECT)
9382 return tmp(i,contextptr);
9383 gen res=i;
9384 const_iterateur it=tmp._VECTptr->begin(),itend=tmp._VECTptr->end();
9385 for (;itend!=it;){
9386 --itend;
9387 res=(*itend)(res,contextptr);
9388 }
9389 return res;
9390 }
9391 if (_SYMBptr->sommet==at_composepow){
9392 gen tmp=_SYMBptr->feuille;
9393 if (tmp.type!=_VECT || tmp._VECTptr->size()!=2 || tmp._VECTptr->back().type!=_INT_)
9394 return symb_of(tmp,i);
9395 gen res=i;
9396 int n=tmp._VECTptr->back().val;
9397 if (n<0){
9398 // try to invert the function
9399 gen x(identificateur("xinvert")),y(identificateur("yinvert"));
9400 gen f=tmp._VECTptr->front();
9401 gen s=_solve(makesequence(symb_equal(f(x,contextptr),y),x),contextptr);
9402 if (s.type!=_VECT || s._VECTptr->size()<1 || is_undef(s._VECTptr->front()))
9403 return gensizeerr("Unable to invert function");
9404 if (s._VECTptr->size()>1)
9405 *logptr(contextptr) << "Choosing first solution in "<<s<<'\n';
9406 f=symb_program(y,0,s._VECTptr->front(),contextptr);
9407 n=-n;
9408 tmp=makesequence(f,n);
9409 }
9410 if (!n)
9411 return i;
9412 int ratnormal_test=MAX_RECURSION_LEVEL/2;
9413 // otherwise f(x):=-3x+2; g:=(f@@300)(x):; simplifier(g); might segfault
9414 tmp=tmp._VECTptr->front();
9415 for (int j=0;j<n;++j){
9416 res=tmp(res,contextptr);
9417 if (j%ratnormal_test==ratnormal_test-1)
9418 res=ratnormal(res);
9419 }
9420 return res;
9421 }
9422 if (_SYMBptr->sommet==at_derive || _SYMBptr->sommet==at_function_diff || _SYMBptr->sommet==at_of || _SYMBptr->sommet==at_at)
9423 return new_ref_symbolic(symbolic(at_of,makesequence(*this,i)));
9424 gen & f=_SYMBptr->feuille;
9425 // distributions laws: add arguments and reeval
9426 if (is_distribution(_SYMBptr->sommet)){
9427 vecteur args(gen2vecteur(f));
9428 if (i.type==_VECT && i.subtype==_SEQ__VECT)
9429 args=mergevecteur(args,*i._VECTptr);
9430 else
9431 args.push_back(i);
9432 return _SYMBptr->sommet(gen(args,_SEQ__VECT),contextptr);
9433 }
9434 if (string(_SYMBptr->sommet.ptr()->s)=="pari"){
9435 vecteur argv(gen2vecteur(f));
9436 if (i.type==_VECT && i.subtype!=_SEQ__VECT)
9437 argv=mergevecteur(argv,vecteur(1,i));
9438 else
9439 argv=mergevecteur(argv,gen2vecteur(i));
9440 return _SYMBptr->sommet(gen(argv,_SEQ__VECT),contextptr);
9441 }
9442 if (f==makenewvecteur(zero)){
9443 return _SYMBptr->sommet(i,contextptr);
9444 }
9445 // other case, apply feuille to i then apply sommet
9446 if (f.type!=_VECT)
9447 return _SYMBptr->sommet(f(i,contextptr),contextptr);
9448 vecteur lid(lidnt(*this));
9449 if (lid.size()==1 && !has_algebraic_program(*this)){
9450 if (lid.front()==vx_var)
9451 // suspect something like P:=x^3+1 then P(2)
9452 *logptr(contextptr) << "Warning, evaluating univariate expression of x(value) like if expression was a function.\nYou should write subst(" << *this << "," << lid.front() << "," << i << ")" << '\n';
9453 else
9454 return gensizeerr("Expression used like a function "+this->print(contextptr)+"\nYou should write subst("+this->print(contextptr)+","+lid.front().print(contextptr)+","+i.print(contextptr)+")");
9455 return subst(*this,lid.front(),i,false,contextptr);
9456 }
9457 vecteur res(*f._VECTptr);
9458 iterateur it=res.begin(),itend=res.end();
9459 bool warn=false;
9460 for (;it!=itend;++it){
9461 if (it->type==_IDNT)
9462 warn=true;
9463 *it=(*it)(i,contextptr);
9464 }
9465 if (warn)
9466 *logptr(contextptr) << gettext("Warning, evaluating (") << *this << ")(" << i << ") as a function not as a product" << '\n';
9467 return _SYMBptr->sommet(res,contextptr);
9468 }
9469 if (type==_FUNC){
9470 if ( (i.type==_VECT) && (i.subtype==_SEQ__VECT) && (i._VECTptr->size()==1))
9471 return (*_FUNCptr)(i._VECTptr->front(),contextptr);
9472 else
9473 return (*_FUNCptr)(i,contextptr);
9474 }
9475 if (i.type==_DOUBLE_ && giac_floor(i._DOUBLE_val)==i._DOUBLE_val )
9476 return (*this)((int) i._DOUBLE_val,contextptr);
9477 if (i.type==_FLOAT_ && ffloor(i._FLOAT_val)==i._FLOAT_val )
9478 return (*this)(get_int(i._FLOAT_val),contextptr);
9479 if (type==_INT_ && subtype==_INT_TYPE && i.type==_VECT){
9480 return gen(*i._VECTptr,type);
9481 }
9482 if (type<_IDNT )
9483 return *this;
9484 if (type==_USER)
9485 return (*_USERptr)(i,contextptr);
9486 if (type==_STRNG){
9487 gen ii(i);
9488 if (!is_integral(ii))
9489 return gensizeerr(gettext("Bad index"));
9490 if (ii.val<1 || ii.val>int(_STRNGptr->size()))
9491 return gendimerr(gettext("Index out of range"));
9492 return string2gen(string(1,(*_STRNGptr)[ii.val-1]),false);
9493 }
9494 if (type==_VECT){
9495 if (of_pointer_38 && _VECTptr->size()==2 && _VECTptr->front().type==_POINTER_ && _VECTptr->front().subtype==_APPLET_POINTER && _VECTptr->back().type==_POINTER_ && _VECTptr->back().subtype==_VARFUNCDEF_POINTER )
9496 return of_pointer_38(_VECTptr->front()._POINTER_val,_VECTptr->back()._POINTER_val,i);
9497 if (1 ||
9498 abs_calc_mode(contextptr)==38){
9499 if (i.type==_VECT){
9500 gen res=*this;
9501 int is=int(i._VECTptr->size());
9502 for (int k=0;k<is;++k){
9503 res=res(i[k],contextptr);
9504 }
9505 return res;
9506 }
9507 if (i.is_symb_of_sommet(at_interval)){
9508 const gen & ife =i._SYMBptr->feuille;
9509 if (ife.type==_VECT && ife._VECTptr->size()==2){
9510 const gen & if1=ife._VECTptr->front();
9511 const gen & if2=ife._VECTptr->back();
9512 if (if1.type==_INT_ && if2.type==_INT_ && if1.val>=1 && if2.val>=1 && if1.val<=if2.val && if1.val<=int(_VECTptr->size()) && if2.val<=int(_VECTptr->size()))
9513 return gen(vecteur(_VECTptr->begin()+if1.val-1,_VECTptr->begin()+if2.val),subtype);
9514 }
9515 }
9516 gen tmp=_floor(i,contextptr);
9517 if (tmp.type!=_INT_)
9518 return gendimerr(contextptr);
9519 if (tmp.val<1 || tmp.val>int(_VECTptr->size()) )
9520 return gendimerr(contextptr);
9521 return (*_VECTptr)[tmp.val-1];
9522 }
9523 // Old code for _VECT type was just return (*this)[i];
9524 vecteur w(*_VECTptr);
9525 iterateur it=w.begin(),itend=w.end();
9526 for (;it!=itend;++it)
9527 *it=(*it)(i,contextptr);
9528 return gen(w,subtype);
9529 }
9530 else {
9531 if (has_inf_or_undef(i))
9532 return undef;
9533 return symb_of(*this,i);
9534 }
9535 }
9536
compare_VECT(const vecteur & v,const vecteur & w)9537 static bool compare_VECT(const vecteur & v,const vecteur & w){
9538 int s1=int(v.size()),s2=int(w.size());
9539 if (s1!=s2)
9540 return s1<s2;
9541 const_iterateur it=v.begin(),itend=v.end(),jt=w.begin();
9542 for (;it!=itend;++it,++jt){
9543 if (*it!=*jt){
9544 return it->islesscomplexthan(*jt);
9545 }
9546 }
9547 // setsizeerr(); should not happen... commented because it happens!
9548 return false;
9549 }
9550
9551 // return true if *this is "strictly less complex" than other
islesscomplexthan(const gen & other) const9552 bool gen::islesscomplexthan (const gen & other ) const {
9553 // FIXME it is not the natural order, but used for pivot selection
9554 if (type<_IDNT && is_zero(*this,context0)){
9555 // if (type==_INT_ && other.type==_INT_) return val<other.val;
9556 return false;
9557 }
9558 if (other.type<_IDNT && is_zero(other,context0))
9559 return true;
9560 if (type != other.type)
9561 return type < other.type;
9562 if (*this==other)
9563 return false;
9564 if (type<_POLY && type!=_CPLX && *this==-other)
9565 return is_strictly_positive(*this,context0);
9566 switch ( type) {
9567 case _INT_:
9568 return absint(val)<absint(other.val);
9569 case _ZINT:
9570 return is_greater(abs(other,context0),abs(*this,context0),context0);
9571 case _DOUBLE_: case _FLOAT_: case _REAL:
9572 return is_greater(abs(*this,context0),abs(other,context0),context0);
9573 case _CPLX:
9574 {
9575 gen a1=abs(*this,context0),a2=abs(other,context0);
9576 if (a1!=a2)
9577 return is_strictly_greater(a1,a2,context0);
9578 a1=re(context0);
9579 a2=other.re(context0);
9580 if (a1!=a2)
9581 return is_strictly_greater(a1,a2,context0);
9582 a1=im(context0);
9583 a2=other.im(context0);
9584 return is_greater(a1,a2,context0);
9585 }
9586 case _IDNT:
9587 return strcmp(_IDNTptr->id_name,other._IDNTptr->id_name)<0;
9588 case _POLY:
9589 if (_POLYptr->coord.size()!=other._POLYptr->coord.size())
9590 return _POLYptr->coord.size()<other._POLYptr->coord.size();
9591 return _POLYptr->coord.front().value.islesscomplexthan(other._POLYptr->coord.front().value);
9592 case _MOD:
9593 if (*(_MODptr+1)!=*(other._MODptr+1)){
9594 #ifndef NO_STDEXCEPT
9595 setsizeerr(gettext("islesscomplexthan mod"));
9596 #endif
9597 }
9598 return _MODptr->islesscomplexthan(*other._MODptr);
9599 case _SYMB:
9600 if (_SYMBptr->sommet !=other._SYMBptr->sommet ){
9601 #ifdef GIAC_HAS_STO_38 // otherwise 1 test of chk_xavier fails, needs to check
9602 int c=strcmp(_SYMBptr->sommet.ptr()->s,other._SYMBptr->sommet.ptr()->s);
9603 if (c) return c<0;
9604 #endif
9605 return (alias_type) _SYMBptr->sommet.ptr() <(alias_type) other._SYMBptr->sommet.ptr();
9606 }
9607 return _SYMBptr->feuille.islesscomplexthan(other._SYMBptr->feuille);
9608 // return false;
9609 case _VECT:
9610 return compare_VECT(*_VECTptr,*other._VECTptr);
9611 case _EXT:
9612 if (*(_EXTptr+1)!=*(other._EXTptr+1))
9613 return (_EXTptr+1)->islesscomplexthan(*(other._EXTptr+1));
9614 return _EXTptr->islesscomplexthan(*(other._EXTptr));
9615 case _STRNG:
9616 return *_STRNGptr<*other._STRNGptr;
9617 default:
9618 return this->print(context0)< other.print(context0);
9619 }
9620 }
9621
islesscomplexthanf(const gen & a,const gen & b)9622 bool islesscomplexthanf(const gen & a,const gen & b){
9623 return a.islesscomplexthan(b);
9624 }
9625
monomial_degree(const gen & a)9626 static gen monomial_degree(const gen & a){
9627 if (a.type<_IDNT)
9628 return 0;
9629 if (a.type==_IDNT){
9630 // detect constants of integration
9631 if (strlen(a._IDNTptr->id_name)>=3 && a._IDNTptr->id_name[0]=='c' && a._IDNTptr->id_name[1]=='_')
9632 return 0;
9633 return 1;
9634 }
9635 if (a.type!=_SYMB)
9636 return 0;
9637 if (a._SYMBptr->sommet==at_neg)
9638 return monomial_degree(a._SYMBptr->feuille);
9639 if (a._SYMBptr->sommet==at_inv)
9640 return -monomial_degree(a._SYMBptr->feuille);
9641 if (a._SYMBptr->sommet==at_pow && a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()==2)
9642 return (*a._SYMBptr->feuille._VECTptr)[1];
9643 if (a._SYMBptr->sommet==at_plus){
9644 gen af=a._SYMBptr->feuille;
9645 if (af.type!=_VECT)
9646 return monomial_degree(af);
9647 gen res(0);
9648 for (unsigned i=0;i<af._VECTptr->size();++i){
9649 res = max(res,monomial_degree((*af._VECTptr)[i]),context0);
9650 }
9651 return res;
9652 }
9653 if (a._SYMBptr->sommet!=at_prod)
9654 return 0;
9655 gen af=a._SYMBptr->feuille;
9656 if (af.type!=_VECT)
9657 return monomial_degree(af);
9658 gen res(0);
9659 for (unsigned i=0;i<af._VECTptr->size();++i){
9660 res += monomial_degree((*af._VECTptr)[i]);
9661 }
9662 return res;
9663 }
9664
is_monomial(const gen & a)9665 static bool is_monomial(const gen & a){
9666 if (a.type<=_IDNT)
9667 return true;
9668 if (a.type!=_SYMB)
9669 return false;
9670 if (a._SYMBptr->sommet==at_pow)
9671 return true;
9672 if (a._SYMBptr->sommet!=at_prod && a._SYMBptr->sommet!=at_plus && a._SYMBptr->sommet!=at_neg && a._SYMBptr->sommet!=at_inv)
9673 return false;
9674 gen af=a._SYMBptr->feuille;
9675 if (af.type!=_VECT)
9676 return is_monomial(af);
9677 for (unsigned i=0;i<af._VECTptr->size();++i){
9678 if (!is_monomial((*af._VECTptr)[i]))
9679 return false;
9680 }
9681 return true;
9682 }
9683
islesscomplexthanf2(const gen & a,const gen & b,GIAC_CONTEXT)9684 static bool islesscomplexthanf2(const gen & a,const gen & b,GIAC_CONTEXT){
9685 if (a==b)
9686 return false;
9687 if (a.type==_VECT && b.type==_VECT && a._VECTptr->size()==2 && b._VECTptr->size()==2){
9688 gen & a2=a._VECTptr->back();
9689 gen & b2=b._VECTptr->back();
9690 if (a2!=b2)
9691 return islesscomplexthanf2(a2,b2,contextptr);
9692 }
9693 if (is_monomial(a) && is_monomial(b)){
9694 gen da=monomial_degree(a);
9695 gen db=monomial_degree(b);
9696 if (da!=db)
9697 return increasing_power(contextptr)?is_greater(db,da,contextptr):is_greater(da,db,contextptr);
9698 }
9699 if (a.type==b.type)
9700 return a.islesscomplexthan(b);
9701 if (a.type==_FRAC && b.type>=_POLY)
9702 return false;
9703 if (a.type>=_POLY && b.type==_FRAC)
9704 return true;
9705 return !a.islesscomplexthan(b);
9706 }
9707
9708 struct f_compare_context {
9709 bool (*f)(const gen &a,const gen &b,GIAC_CONTEXT);
9710 const context * ptr;
f_compare_contextgiac::f_compare_context9711 f_compare_context():f(islesscomplexthanf2),ptr(context0){}
f_compare_contextgiac::f_compare_context9712 f_compare_context(bool (*f_)(const gen &a,const gen &b,GIAC_CONTEXT),GIAC_CONTEXT):f(f_),ptr(contextptr){}
operator ()giac::f_compare_context9713 inline bool operator () (const gen & a,const gen &b){ return f(a,b,ptr); }
9714 };
9715
gen_sort_f_context(iterateur it,iterateur itend,bool (* f)(const gen & a,const gen & b,GIAC_CONTEXT),GIAC_CONTEXT)9716 void gen_sort_f_context(iterateur it,iterateur itend,bool (*f)(const gen &a,const gen &b,GIAC_CONTEXT),GIAC_CONTEXT){
9717 f_compare_context m(f,contextptr);
9718 sort(it,itend,m);
9719 }
9720
symb_size() const9721 int gen::symb_size () const {
9722 if (type==_SYMB)
9723 return _SYMBptr->size();
9724 else
9725 return 1;
9726 }
9727
symb_size_less(const gen & a,const gen & b)9728 bool symb_size_less(const gen & a,const gen & b){
9729 return a.symb_size() < b.symb_size();
9730 }
9731
is_symb_of_sommet(const unary_function_ptr & u) const9732 bool gen::is_symb_of_sommet(const unary_function_ptr & u) const {
9733 return type==_SYMB && _SYMBptr->sommet==u;
9734 }
9735
is_symb_of_sommet(const unary_function_ptr * u) const9736 bool gen::is_symb_of_sommet(const unary_function_ptr * u) const {
9737 return type==_SYMB && _SYMBptr->sommet==u;
9738 }
9739
operator &&(const gen & a,const gen & b)9740 gen operator && (const gen & a,const gen & b){
9741 if (is_zero(a,context0)){
9742 if (b.type==_DOUBLE_)
9743 return 0.0;
9744 if (b.type==_FLOAT_)
9745 return giac_float(0);
9746 return change_subtype(!is_zero(a),_INT_BOOLEAN);
9747 }
9748 if (is_zero(b,context0)){
9749 if (a.type==_DOUBLE_ )
9750 return 0.0;
9751 if (a.type==_FLOAT_)
9752 return giac_float(0);
9753 return change_subtype(!is_zero(b),_INT_BOOLEAN);
9754 }
9755 if (a.type<=_CPLX || a.type==_FLOAT_ || a.type==_FRAC){
9756 if (b.type<=_CPLX || b.type==_FLOAT_ || b.type==_FRAC)
9757 return change_subtype(!is_zero(b),_INT_BOOLEAN);
9758 return b;
9759 }
9760 if (b.type<=_CPLX || b.type==_FLOAT_ || b.type==_FRAC){
9761 if (a.type<=_CPLX || a.type==_FLOAT_ || a.type==_FRAC)
9762 return change_subtype(!is_zero(a),_INT_BOOLEAN);
9763 return a;
9764 }
9765 if (a.is_symb_of_sommet(at_and)){
9766 if (b.is_symb_of_sommet(at_and))
9767 return new_ref_symbolic(symbolic(at_and,gen(mergevecteur(*a._SYMBptr->feuille._VECTptr,*b._SYMBptr->feuille._VECTptr),_SEQ__VECT)));
9768 vecteur v=*a._SYMBptr->feuille._VECTptr;
9769 v.push_back(b);
9770 return new_ref_symbolic(symbolic(at_and,v));
9771 }
9772 if (b.is_symb_of_sommet(at_and)){
9773 vecteur v=*b._SYMBptr->feuille._VECTptr;
9774 v.push_back(a);
9775 return new_ref_symbolic(symbolic(at_and,v));
9776 }
9777 if ( ((a.type==_IDNT) || (a.type==_SYMB)) || ((b.type==_IDNT) || (b.type==_SYMB)) )
9778 return symb_and(a,b);
9779 if ( (a.type==_DOUBLE_) || (b.type==_DOUBLE_) )
9780 return 1.0;
9781 if ( (a.type==_FLOAT_) || (b.type==_FLOAT_) )
9782 return giac_float(1);
9783 return change_subtype(plus_one,_INT_BOOLEAN);
9784 }
9785
operator ||(const gen & a,const gen & b)9786 gen operator || (const gen & a,const gen & b){
9787 if (is_zero(a,context0))
9788 return change_subtype(!is_zero(b),_INT_BOOLEAN);
9789 if (is_zero(b,context0))
9790 return change_subtype(!is_zero(a),_INT_BOOLEAN);
9791 if (a.is_symb_of_sommet(at_ou)){
9792 if (b.is_symb_of_sommet(at_ou))
9793 return new_ref_symbolic(symbolic(at_ou,gen(mergevecteur(*a._SYMBptr->feuille._VECTptr,*b._SYMBptr->feuille._VECTptr),_SEQ__VECT)));
9794 vecteur v=*a._SYMBptr->feuille._VECTptr;
9795 v.push_back(b);
9796 return new_ref_symbolic(symbolic(at_ou,v));
9797 }
9798 if (b.is_symb_of_sommet(at_ou)){
9799 vecteur v=*b._SYMBptr->feuille._VECTptr;
9800 v.push_back(a);
9801 return new_ref_symbolic(symbolic(at_ou,v));
9802 }
9803 if ( ((a.type==_IDNT) || (a.type==_SYMB)) || ((b.type==_IDNT) || (b.type==_SYMB)) )
9804 return symb_ou(a,b);
9805 if ( (a.type==_DOUBLE_) || (b.type==_DOUBLE_) )
9806 return 1.0;
9807 if ( (a.type==_FLOAT_) || (b.type==_FLOAT_) )
9808 return giac_float(1);
9809 return change_subtype(plus_one,_INT_BOOLEAN);
9810 }
9811
collect(const gen & g,GIAC_CONTEXT)9812 gen collect(const gen & g,GIAC_CONTEXT){
9813 if (g.type==_VECT)
9814 return apply(g,collect,contextptr);
9815 if (is_inf(g))
9816 return g;
9817 return liste2symbolique(symbolique2liste(g,contextptr));
9818 }
9819
modified_islesscomplexthanf(const gen & a,const gen & b)9820 static bool modified_islesscomplexthanf(const gen& a,const gen& b){
9821 if (a.type!=b.type && (a.type<=_CPLX || b.type<=_CPLX))
9822 return a.type<b.type;
9823 if (a.is_symb_of_sommet(at_neg)){
9824 if (b.is_symb_of_sommet(at_neg))
9825 return modified_islesscomplexthanf(a._SYMBptr->feuille,b._SYMBptr->feuille);
9826 return modified_islesscomplexthanf(a._SYMBptr->feuille,b);
9827 }
9828 if (b.is_symb_of_sommet(at_neg))
9829 return modified_islesscomplexthanf(a,b._SYMBptr->feuille);
9830 if (a.is_symb_of_sommet(at_inv)){
9831 if (b.is_symb_of_sommet(at_inv))
9832 return modified_islesscomplexthanf(a._SYMBptr->feuille,b._SYMBptr->feuille);
9833 if (a._SYMBptr->feuille.type<_IDNT)
9834 return modified_islesscomplexthanf(a._SYMBptr->feuille,b);
9835 return false;
9836 }
9837 if (b.is_symb_of_sommet(at_inv)){
9838 if (b._SYMBptr->feuille.type<_IDNT)
9839 return modified_islesscomplexthanf(a,b._SYMBptr->feuille);
9840 return true;
9841 }
9842 if (a.is_symb_of_sommet(at_pow)){
9843 if (b.is_symb_of_sommet(at_pow))
9844 return modified_islesscomplexthanf(a._SYMBptr->feuille[0],b._SYMBptr->feuille[0]);
9845 return modified_islesscomplexthanf(a._SYMBptr->feuille[0],b);
9846 }
9847 if (b.is_symb_of_sommet(at_pow))
9848 return modified_islesscomplexthanf(a,b._SYMBptr->feuille[0]);
9849 if (a.type!=b.type){
9850 if (a.type==_FRAC && b.type>=_POLY)
9851 return true;
9852 if (b.type==_FRAC && a.type>=_POLY)
9853 return false;
9854 }
9855 return islesscomplexthanf(a,b);
9856 }
9857
9858 class modified_compare {
9859 public:
modified_compare()9860 modified_compare(){}
operator ()(const gen & a,const gen & b)9861 bool operator ()(const gen &a,const gen &b){ return modified_islesscomplexthanf(a,b);}
9862 };
9863
9864 // return true if a is -basis^exp
power_basis_exp(const gen & a,gen & basis,gen & expa)9865 static bool power_basis_exp(const gen& a,gen & basis,gen & expa){
9866 if (a.is_symb_of_sommet(at_neg))
9867 return !power_basis_exp(a._SYMBptr->feuille,basis,expa);
9868 if (a.is_symb_of_sommet(at_inv)){
9869 gen & tmp=a._SYMBptr->feuille;
9870 bool b=power_basis_exp(tmp,basis,expa);
9871 expa=-expa;
9872 return b;
9873 } // de-commented 2/2/2013 so that regrouper(x^2/x) works
9874 if (a.is_symb_of_sommet(at_pow)){
9875 gen & tmp=a._SYMBptr->feuille;
9876 if (tmp.type!=_VECT || tmp._VECTptr->size()!=2){
9877 #ifndef NO_STDEXCEPT
9878 setsizeerr(gettext("power_basis_exp"));
9879 #endif
9880 return false;
9881 }
9882 expa=tmp._VECTptr->back();
9883 basis=tmp._VECTptr->front();
9884 }
9885 else {
9886 basis=a;
9887 expa=plus_one;
9888 }
9889 return false;
9890 }
9891
regroup_inv(const vecteur & vtmp)9892 static gen regroup_inv(const vecteur & vtmp){
9893 vecteur vtmp1,vtmp2;
9894 gen tt(1);
9895 for (unsigned i=0;i<vtmp.size();++i){
9896 if (vtmp[i].is_symb_of_sommet(at_inv))
9897 vtmp2.push_back(vtmp[i]._SYMBptr->feuille);
9898 else
9899 vtmp1.push_back(vtmp[i]);
9900 }
9901 if (!vtmp1.empty()){
9902 if (vtmp1.size()==1)
9903 tt=vtmp1.front();
9904 else
9905 tt=new_ref_symbolic(symbolic(at_prod,gen(vtmp1,_SORTED__VECT)));
9906 }
9907 if (!vtmp2.empty()){
9908 if (vtmp2.size()==1)
9909 tt=tt/vtmp2.front();
9910 else
9911 tt=tt/new_ref_symbolic(symbolic(at_prod,gen(vtmp2,_SORTED__VECT)));
9912 }
9913 return tt;
9914 }
9915
9916 // Helpers for symbolic addition
9917 // from a product returns a list with the numeric coeff and the monomial
terme2unitaire(const gen & x,bool sorted,GIAC_CONTEXT)9918 static vecteur terme2unitaire(const gen & x,bool sorted,GIAC_CONTEXT){
9919 if (x.type<_POLY)
9920 return makevecteur(x,plus_one);
9921 gen tmp;
9922 if (x.type!=_SYMB || x._SYMBptr->sommet==at_program || x._SYMBptr->sommet==at_when)
9923 return makevecteur(1,x);
9924 if (x._SYMBptr->sommet==at_neg){
9925 vecteur v=terme2unitaire(x._SYMBptr->feuille,sorted,contextptr);
9926 v[0]=-v[0];
9927 return v;
9928 }
9929 if (x._SYMBptr->sommet==at_binary_minus){
9930 vecteur v=terme2unitaire(x._SYMBptr->feuille,sorted,contextptr);
9931 v[1]=-v[1];
9932 return v;
9933 }
9934 if (x._SYMBptr->sommet==at_prod && (tmp=x._SYMBptr->feuille).type==_VECT && !tmp._VECTptr->empty() ){
9935 vecteur & v = *tmp._VECTptr;
9936 int s=int(v.size());
9937 if (s==2 && (sorted || tmp.subtype==_SORTED__VECT))
9938 return makevecteur(v[0],v[1]);
9939 vecteur vtmp(v.begin(),v.end());
9940 for (unsigned i=0;i<vtmp.size();++i){
9941 vtmp[i]=simplifier(vtmp[i],contextptr);
9942 if (vtmp[i].is_symb_of_sommet(at_inv) && vtmp[i]._SYMBptr->feuille.is_symb_of_sommet(at_pow)){
9943 gen f= vtmp[i]._SYMBptr->feuille._SYMBptr->feuille;
9944 if (f.type==_VECT && f._VECTptr->size()==2)
9945 vtmp[i]=symbolic(at_pow,makesequence(f._VECTptr->front(),-f._VECTptr->back()));
9946 }
9947 }
9948 if (equalposcomp(vtmp,undef))
9949 return makevecteur(1,undef);
9950 if (equalposcomp(vtmp,0)){
9951 if (equalposcomp(vtmp,unsigned_inf))
9952 return makevecteur(1,undef);
9953 return makevecteur(0,plus_one);
9954 }
9955 #if 1 // def NSPIRE
9956 // COUT << "modified " << (int) modified_islesscomplexthanf << '\n'; wait_key_pressed() ;
9957 modified_compare m;
9958 sort(vtmp.begin(),vtmp.end(),m);
9959 // COUT << "after modified " << '\n'; wait_key_pressed() ;
9960 #else
9961 sort(vtmp.begin(),vtmp.end(),modified_islesscomplexthanf);
9962 #endif
9963 // collect term with the same power
9964 const_iterateur it=vtmp.begin(),itend=vtmp.end();
9965 vecteur vsorted;
9966 vsorted.reserve(itend-it);
9967 gen precbasis,precexpo,basis,expo,constcoeff(plus_one);
9968 for (;it!=itend;++it){
9969 if (it->type<=_CPLX)
9970 constcoeff=constcoeff*(*it);
9971 else {
9972 if (it->is_symb_of_sommet(at_inv) && it->_SYMBptr->feuille.type<=_CPLX)
9973 constcoeff=constcoeff/it->_SYMBptr->feuille;
9974 else
9975 break;
9976 }
9977 }
9978 if (!is_one(constcoeff))
9979 vsorted.push_back(constcoeff);
9980 bool isneg(false),hasneg(false);
9981 if (it!=itend){
9982 power_basis_exp(*it,precbasis,precexpo);
9983 precexpo=zero;
9984 for (;it!=itend;++it){
9985 if (power_basis_exp(*it,basis,expo)){
9986 isneg=!isneg;
9987 hasneg=true;
9988 }
9989 if (!vsorted.empty() && basis==vsorted.back()){
9990 vsorted.pop_back();
9991 expo+=1;
9992 }
9993 if (basis==precbasis)
9994 precexpo=precexpo+expo;
9995 else {
9996 if (!is_zero(precexpo,contextptr)){
9997 if (is_strictly_positive(-precexpo,contextptr))
9998 vsorted.push_back(inv(pow(precbasis,-precexpo,contextptr),contextptr));
9999 else
10000 vsorted.push_back(pow(precbasis,precexpo,contextptr));
10001 }
10002 // vsorted.push_back(pow(precbasis,precexpo,contextptr));
10003 precbasis=basis;
10004 precexpo=expo;
10005 }
10006 }
10007 if (!is_zero(precexpo,contextptr)){
10008 if (is_strictly_positive(-precexpo,contextptr)){
10009 gen tmp=pow(precbasis,-precexpo,contextptr);
10010 if (tmp.is_symb_of_sommet(at_prod))
10011 tmp=symbolic(at_inv,tmp);
10012 else
10013 tmp=inv(tmp,contextptr);
10014 vsorted.push_back(tmp);
10015 }
10016 else
10017 vsorted.push_back(pow(precbasis,precexpo,contextptr));
10018 }
10019 }
10020 vecteur res;
10021 if (hasneg){
10022 res=terme2unitaire(_prod(vsorted,contextptr),sorted,contextptr);
10023 if (isneg)
10024 res[0]=-res[0];
10025 return res;
10026 }
10027 if (vsorted.empty())
10028 vsorted.push_back(1);
10029 if (vsorted.front().type<_POLY || vsorted.front().type==_FRAC){
10030 vtmp=vecteur(vsorted.begin()+1,vsorted.end());
10031 gen tt(1);
10032 if (!vtmp.empty()){
10033 if (vtmp.size()==1)
10034 tt=vtmp.front();
10035 else
10036 tt=regroup_inv(vtmp);
10037 }
10038 res=makevecteur(vsorted.front(),tt);
10039 }
10040 else
10041 res=makevecteur(plus_one,regroup_inv(vsorted));
10042 return res;
10043 }
10044 // recurse
10045 if (x._SYMBptr->sommet==at_pow)
10046 return makevecteur(plus_one,x._SYMBptr->sommet(collect(x._SYMBptr->feuille,contextptr),contextptr));
10047 tmp=collect(x._SYMBptr->feuille,contextptr);
10048 if (x._SYMBptr->sommet==at_inv){
10049 if (is_zero(tmp))
10050 return makevecteur(1,unsigned_inf);
10051 }
10052 return makevecteur(plus_one,new_ref_symbolic(symbolic(x._SYMBptr->sommet,tmp)));
10053 }
10054
10055 // assumes v is a sorted list, shrink it
10056 // should be written to a gen of type _VECT and subtype _SORTED__VECT
fusionliste(const vecteur & v)10057 static vecteur fusionliste(const vecteur & v){
10058 const_iterateur it=v.begin(),itend=v.end();
10059 if (itend-it<2)
10060 return v;
10061 vecteur res;
10062 gen current=(*it)[1];
10063 gen current_coeff=(*it)[0];
10064 ++it;
10065 for (;it!=itend;++it){
10066 if ((*it)[1].type!=current.type || (current.type==_DOUBLE_ && current._DOUBLE_val!=(*it)[1]._DOUBLE_val) || (*it)[1]!=current ){
10067 res.push_back(makenewvecteur(current_coeff,current));
10068 current_coeff=(*it)[0];
10069 current=(*it)[1];
10070 }
10071 else
10072 current_coeff=current_coeff+(*it)[0];
10073 }
10074 res.push_back(makenewvecteur(current_coeff,current));
10075 return res;
10076 }
10077
10078 struct tri_context {
10079 const context * contextptr;
operator ()giac::tri_context10080 bool operator()(const gen & a,const gen &b){ return islesscomplexthanf2(a,b,contextptr); }
tri_contextgiac::tri_context10081 tri_context(const context * ptr):contextptr(ptr){};
tri_contextgiac::tri_context10082 tri_context():contextptr(0){};
10083 };
10084
10085 // from a sum in x returns a list of [coeff monomial]
10086 // e.g. 5+2x+3*x*y -> [ [5 1] [2 x] [ 3 x*y] ]
symbolique2liste(const gen & x,GIAC_CONTEXT)10087 vecteur symbolique2liste(const gen & x,GIAC_CONTEXT){
10088 if (!x.is_symb_of_sommet(at_plus))
10089 return vecteur(1,terme2unitaire(x,false,contextptr));
10090 bool sorted=x._SYMBptr->feuille.subtype==_SORTED__VECT;
10091 gen number;
10092 vecteur varg=gen2vecteur(x._SYMBptr->feuille);
10093 vecteur vres;
10094 const_iterateur it=varg.begin(),itend=varg.end();
10095 for (;it!=itend;++it){
10096 if (it->type<_POLY || it->type==_FRAC)
10097 number=number+(*it);
10098 else
10099 vres.push_back(terme2unitaire(*it,sorted,contextptr));
10100 }
10101 if (!is_exactly_zero(number))
10102 vres.push_back(makenewvecteur(1,number));
10103 if (x._SYMBptr->feuille.subtype==_SORTED__VECT)
10104 return vres;
10105 sort(vres.begin(),vres.end(),tri_context(contextptr));
10106 return fusionliste(vres);
10107 }
10108
10109 /*
10110 // assumes v1, v2 are sorted and shrinked, merge them -> sorted and shrinked
10111 static vecteur fusion2liste(const vecteur & v1,const vecteur & v2){
10112 const_iterateur it=v1.begin(),itend=v1.end(),jt=v2.begin(),jtend=v2.end();
10113 vecteur res;
10114 gen tmp;
10115 for (;it!=itend;){
10116 if (jt==jtend){
10117 for (;it!=itend;++it)
10118 res.push_back(*it);
10119 return res;
10120 }
10121 // both iterator are valid
10122 vecteur & vi=*it->_VECTptr;
10123 vecteur & vj=*jt->_VECTptr;
10124 if (vi[1]==vj[1]){
10125 tmp=vi[0]+vj[0];
10126 if (!is_exactly_zero(tmp))
10127 res.push_back(makenewvecteur(tmp,vi[1]));
10128 ++it;
10129 ++jt;
10130 }
10131 else {
10132 if (vi[1].islesscomplexthan(vj[1])){
10133 res.push_back(*it);
10134 ++it;
10135 }
10136 else {
10137 res.push_back(*jt);
10138 ++jt;
10139 }
10140 } // end tests
10141 } // end for loop
10142 // finish jt
10143 for (;jt!=jtend;++jt)
10144 res.push_back(*jt);
10145 return res;
10146 }
10147 */
10148
10149 // v should be sorted and shrinked
liste2symbolique(const vecteur & v)10150 gen liste2symbolique(const vecteur & v){
10151 vecteur res;
10152 const_iterateur it=v.begin(),itend=v.end();
10153 res.reserve(itend-it);
10154 for (;it!=itend;++it){
10155 vecteur & vtmp(*it->_VECTptr);
10156 gen & tmp = vtmp.back();
10157 gen coeff=eval(vtmp.front(),1,context0);
10158 if (is_exactly_zero(coeff))
10159 continue;
10160 if (tmp.is_symb_of_sommet(at_prod) && tmp._SYMBptr->feuille.type==_VECT && tmp._SYMBptr->feuille._VECTptr->size()==1){
10161 res.push_back(coeff*tmp._SYMBptr->feuille._VECTptr->front());
10162 continue;
10163 }
10164 if (coeff.is_symb_of_sommet(at_neg)){
10165 res.push_back(-(coeff._SYMBptr->feuille*tmp));
10166 continue;
10167 }
10168 if ( (coeff.type==_FRAC || is_integer(coeff)) && is_positive(-coeff,context0))
10169 res.push_back(-((-coeff)*tmp));
10170 else
10171 res.push_back(coeff*tmp);
10172 }
10173 int s=int(res.size());
10174 if (!s)
10175 return zero;
10176 if (s==1)
10177 return res.front();
10178 return new_ref_symbolic(symbolic(at_plus,gen(res,_SORTED__VECT)));
10179 }
10180
10181 /* Euclidean-like Arithmetic */
swap(int & a,int & b)10182 static void swap(int & a,int & b){
10183 int t=a;
10184 a=b;
10185 b=t;
10186 }
10187
absint(int a)10188 int absint(int a){
10189 if (a<0)
10190 return -a;
10191 else
10192 return a;
10193 }
10194
absdouble(double a)10195 double absdouble(double a){
10196 if (a<0)
10197 return -a;
10198 else
10199 return a;
10200 }
10201
giacmin(int a,int b)10202 int giacmin(int a, int b){
10203 if (a<b)
10204 return a;
10205 else
10206 return b;
10207 }
10208
giacmax(int a,int b)10209 int giacmax(int a, int b){
10210 if (a<b)
10211 return b;
10212 else
10213 return a;
10214 }
10215
invmod(int a,int b)10216 int invmod(int a,int b){
10217 if (a==1 || a==-1 || a==1-b)
10218 return a;
10219 int aa(1),ab(0),ar(0);
10220 div_t qr;
10221 while (b){
10222 qr=div(a,b);
10223 ar=aa-qr.quot*ab;
10224 a=b;
10225 b=qr.rem;
10226 aa=ab;
10227 ab=ar;
10228 }
10229 if (a==1)
10230 return aa;
10231 if (a!=-1){
10232 #ifndef NO_STDEXCEPT
10233 setsizeerr(gettext("Not invertible"));
10234 #endif
10235 return 0;
10236 }
10237 return -aa;
10238 }
10239
invmod(unsigned a,int b)10240 unsigned invmod(unsigned a,int b){
10241 int i=invmod(int(a),int(b));
10242 if (i<0)
10243 i+=b;
10244 return unsigned(i);
10245 }
10246
invmod(longlong a,int b)10247 int invmod(longlong a,int b){
10248 return invmod(int(a%b),b);
10249 }
10250
10251 #ifdef INT128
invmod(int128_t a,int b)10252 int invmod(int128_t a,int b){
10253 return invmod(int(a%b),b);
10254 }
10255 #endif
10256
invmodll(longlong a,longlong b)10257 longlong invmodll(longlong a,longlong b){
10258 if (a==1 || a==-1 || a==1-b)
10259 return a;
10260 longlong aa(1),ab(0),ar(0);
10261 #ifdef VISUALC
10262 longlong q,r;
10263 while (b){
10264 q=a/b;
10265 r=a-q*b;
10266 ar=aa-q*ab;
10267 a=b;
10268 b=r;
10269 aa=ab;
10270 ab=ar;
10271 }
10272 #else
10273 lldiv_t qr;
10274 while (b){
10275 qr=lldiv(a,b);
10276 ar=aa-qr.quot*ab;
10277 a=b;
10278 b=qr.rem;
10279 aa=ab;
10280 ab=ar;
10281 }
10282 #endif
10283 if (a==1)
10284 return aa;
10285 if (a!=-1){
10286 #ifndef NO_STDEXCEPT
10287 setsizeerr(gettext("Not invertible"));
10288 #endif
10289 return 0;
10290 }
10291 return -aa;
10292 }
10293
10294 /*
10295 int powmod(int a,unsigned long n,int m){
10296 if (!n)
10297 return 1;
10298 int b=powmod(a,n/2,m);
10299 longlong tmp=b;
10300 b=(tmp*b) % m;
10301 tmp=b;
10302 if (n % 2)
10303 return (tmp*a) % m;
10304 else
10305 return b;
10306 }
10307 */
10308
powmod(int a,unsigned long n,int m)10309 int powmod(int a,unsigned long n,int m){
10310 if (!n)
10311 return 1;
10312 if (n==1)
10313 return a;
10314 if (n==2)
10315 return (a*longlong(a))%m;
10316 int b=a%m,c=1;
10317 if (m<46340){
10318 while (n>0){
10319 if (n%2)
10320 c=(c*b)%m;
10321 n /= 2;
10322 b=(b*b)%m;
10323 }
10324 }
10325 else {
10326 while (n>0){
10327 if (n%2)
10328 c=(c*longlong(b))%m;
10329 n /= 2;
10330 b=(b*longlong(b))%m;
10331 }
10332 }
10333 return c;
10334 }
10335
smod(int r,int m)10336 int smod(int r,int m){
10337 if (m<=0){
10338 if (!m)
10339 return r;
10340 m=-m;
10341 }
10342 r = r % m;
10343 #if 1
10344 r += (unsigned(r)>>31)*m; // make positive
10345 return r-(unsigned((m>>1)-r)>>31)*m;
10346 #else
10347 longlong tmp= longlong(r)+r;
10348 if (tmp>m)
10349 return r-m;
10350 if (tmp<=-m)
10351 return r+m;
10352 return r;
10353 #endif
10354 }
10355
smod(longlong r,int m)10356 int smod(longlong r,int m){
10357 int R=r%m;
10358 R += (unsigned(R)>>31)*m; // make positive
10359 int res2=R-(unsigned((m>>1)-R)>>31)*m;
10360 return res2;
10361 int res1=(R>m/2)?R-m:R;
10362 if (res1!=res2)
10363 CERR << "smod longlong " << r << " " << m << '\n';
10364 return res1;
10365 //return smod(R,m);
10366 }
10367
smodll(longlong a,longlong b)10368 longlong smodll(longlong a,longlong b){
10369 longlong r=a%b;
10370 if (r>b/2)
10371 r -= b;
10372 else {
10373 if (r<=-b/2)
10374 r += b;
10375 }
10376 return r;
10377 }
10378
gcd(int a,int b)10379 int gcd(int a,int b){
10380 if (a!=b){
10381 int r;
10382 while (b){
10383 r=a%b;
10384 a=b;
10385 b=r;
10386 }
10387 }
10388 return absint(a);
10389 }
10390
10391 #ifdef EMCC
my_mpz_gcd(mpz_t & z,const mpz_t & A,const mpz_t & B)10392 void my_mpz_gcd(mpz_t &z,const mpz_t & A,const mpz_t & B){
10393 mpz_t a,b;
10394 mpz_init_set(a,A);
10395 mpz_init_set(b,B);
10396 while (mpz_cmp_si(b,0)){
10397 mpz_cdiv_r(z,a,b);
10398 mpz_swap(a,b);
10399 mpz_swap(b,z);
10400 }
10401 mpz_set(z,a);
10402 mpz_abs(z,z);
10403 mpz_clear(a);
10404 mpz_clear(b);
10405 }
my_mpz_gcdext(mpz_t & d,mpz_t & u,mpz_t & v,const mpz_t & a,const mpz_t & b)10406 void my_mpz_gcdext(mpz_t & d,mpz_t & u,mpz_t &v,const mpz_t & a,const mpz_t & b){
10407 mpz_t q,r1,r2,u1,u2,v1,v2;
10408 // mpz_t r3,u3,v3;
10409 mpz_init_set(r1,a); mpz_init_set(r2,b);
10410 mpz_init_set_ui(u1,1); mpz_init_set_ui(u2,0);
10411 mpz_init_set_ui(v1,0); mpz_init_set_ui(v2,1);
10412 mpz_init(q);
10413 // mpz_init(r3); mpz_init(u3); mpz_init(v3);
10414 while (mpz_cmp_si(r2,0)){
10415 // CERR << "iegcd " << gen(r1) << " " << gen(r2) << '\n';
10416 mpz_cdiv_qr(q,r1,r1,r2);
10417 mpz_swap(r1,r2);
10418 mpz_submul(u1,q,u2);
10419 mpz_swap(u1,u2);
10420 mpz_submul(v1,q,v2);
10421 mpz_swap(v1,v2);
10422 }
10423 if (mpz_cmp_si(r1,0)<0){
10424 mpz_neg(r1,r1); mpz_neg(u1,u1); mpz_neg(v1,v1);
10425 }
10426 mpz_swap(d,r1); mpz_swap(u,u1); mpz_swap(v,v1);
10427 #if 0 // debugging
10428 CERR << gen(d) << " " << gen(u) << " " << gen(v) << '\n';
10429 mpz_gcdext(d,u,v,a,b);
10430 CERR << gen(d) << " " << gen(u) << " " << gen(v) << '\n';
10431 #endif
10432 mpz_clear(q); mpz_clear(r1); mpz_clear(r2);
10433 mpz_clear(u1); mpz_clear(u2);
10434 mpz_clear(v1); mpz_clear(v2);
10435 // mpz_clear(u3); mpz_clear(v3); mpz_clear(r3);
10436 }
my_mpz_invert(mpz_t & ainv,const mpz_t & a,const mpz_t & m)10437 bool my_mpz_invert(mpz_t & ainv,const mpz_t & a,const mpz_t & m){
10438 mpz_t d,v;
10439 mpz_init(d); mpz_init(v);
10440 my_mpz_gcdext(d,ainv,v,a,m);
10441 mpz_clear(v);
10442 bool ok=mpz_cmp_si(d,1)==0;
10443 mpz_clear(d);
10444 return ok;
10445 }
10446 #else
my_mpz_gcd(mpz_t & z,const mpz_t & a,const mpz_t & b)10447 void my_mpz_gcd(mpz_t &z,const mpz_t & a,const mpz_t & b){
10448 mpz_gcd(z,a,b);
10449 }
my_mpz_gcdext(mpz_t & d,mpz_t & u,mpz_t & v,const mpz_t & a,const mpz_t & b)10450 void my_mpz_gcdext(mpz_t & d,mpz_t & u,mpz_t &v,const mpz_t & a,const mpz_t & b){
10451 mpz_gcdext(d,u,v,a,b);
10452 }
my_mpz_invert(mpz_t & ainv,const mpz_t & a,const mpz_t & m)10453 bool my_mpz_invert(mpz_t & ainv,const mpz_t & a,const mpz_t & m){
10454 return mpz_invert(ainv,a,m)!=0;
10455 }
10456 #endif
10457
simplify(int & a,int & b)10458 int simplify(int & a,int & b){
10459 int d=gcd(a,b);
10460 a=a/d;
10461 b=b/d;
10462 return d;
10463 }
10464
_CPLXgcd(const gen & a,const gen & b)10465 static gen _CPLXgcd(const gen & a,const gen & b){ // a & b must be gen
10466 if (!is_cinteger(a) || !is_cinteger(b) )
10467 return plus_one;
10468 gen acopy(a),bcopy(b),r;
10469 for (;;){
10470 if (is_exactly_zero(bcopy)){
10471 complex<double> c=gen2complex_d(acopy);
10472 double d=arg(c);
10473 int quadrant=int(std::floor((2*d)/M_PI));
10474 switch (quadrant){
10475 case 0:
10476 return acopy;
10477 case 1:
10478 return acopy*(-cst_i);
10479 case -1:
10480 return acopy*cst_i;
10481 case 2: case -2:
10482 return -acopy;
10483 default:
10484 return acopy;
10485 }
10486 }
10487 r=acopy%bcopy;
10488 acopy=bcopy;
10489 bcopy=r;
10490 }
10491 }
10492
polygcd(const polynome & a,const polynome & b)10493 static gen polygcd(const polynome & a,const polynome & b){
10494 ref_polynome * resptr=new ref_polynome(a.dim);
10495 gcd(a,b,resptr->t);
10496 return resptr;
10497 }
10498
10499 // gcd(undef,x)=x to be used inside series
symgcd(const gen & a,const gen & b,GIAC_CONTEXT)10500 static gen symgcd(const gen & a,const gen& b,GIAC_CONTEXT){
10501 if (is_exactly_zero(a) || is_undef(a) || (is_one(b)))
10502 return b;
10503 if (is_one(a) || is_undef(b) || (is_exactly_zero(b)))
10504 return a;
10505 if (a==b)
10506 return a;
10507 if ( (a.type==_MOD) && (b.type==_MOD) && (a._MODptr->type<=_CPLX) && (b._MODptr->type<= _CPLX) )
10508 return chkmod(plus_one,a);
10509 if (a.type==_MOD || b.type==_MOD || a.type==_DOUBLE_ || a.type==_FLOAT_ || a.type==_REAL || b.type==_DOUBLE_ || b.type==_FLOAT_ || b.type==_REAL )
10510 return plus_one;
10511 if ( (a.type==_POLY) && (b.type==_POLY) )
10512 return polygcd(*a._POLYptr,*b._POLYptr);
10513 if ( (a.type==_EXT) && (b.type ==_EXT) ){
10514 if ( (*(a._EXTptr+1)!=*(b._EXTptr+1)) || (a._EXTptr->type!=_VECT) || (b._EXTptr->type!=_VECT) )
10515 return plus_one;
10516 environment *env=new environment;
10517 vecteur g=gcd(*a._EXTptr->_VECTptr,*b._EXTptr->_VECTptr,env);
10518 delete env;
10519 return ext_reduce(g,*(a._EXTptr+1));
10520 }
10521 if ( (a.type==_FRAC) || (b.type==_FRAC))
10522 return plus_one;
10523 if (a.type==_EXT){
10524 if (a._EXTptr->type!=_VECT)
10525 return gentypeerr(gettext("symgcd"));
10526 if ( (a._EXTptr+1)->type!=_VECT)
10527 return symgcd(ext_reduce(a),b,contextptr);
10528 gen aa(lgcd(*a._EXTptr->_VECTptr));
10529 gen res=gcd(aa,b,contextptr),b2(rdiv(b,res,contextptr));
10530 if (is_one(b2) || is_minus_one(b2))// || b2.type==_POLY)
10531 return res;
10532 vecteur ua,u,v,dd;
10533 divvecteur(*(a._EXTptr->_VECTptr),aa,ua);
10534 const vecteur & uv=*((a._EXTptr+1)->_VECTptr);
10535 egcd(ua,uv,0,u,v,dd);
10536 // u and v are not used but we can't use gcd here because we want to
10537 // "factor" dd=extension(ua,uv)*extension(u,uv)
10538 gen dd0(dd.front());
10539 simplify(b2,dd0);
10540 if (is_one(dd0))
10541 return res*algebraic_EXTension(ua,*(a._EXTptr+1));
10542 return res;
10543 }
10544 if (b.type==_EXT)
10545 return symgcd(b,a,contextptr);
10546 if (a.type==_POLY)
10547 return gcd(*a._POLYptr,polynome(b,a._POLYptr->dim));
10548 if (b.type==_POLY)
10549 return gcd(*b._POLYptr,polynome(a,b._POLYptr->dim));
10550 if ( a.type!=_DOUBLE_ && a.type!=_FLOAT_ && a.type!=_VECT && b.type!=_DOUBLE_ && b.type!=_FLOAT_ && b.type!=_VECT )
10551 return rationalgcd(a,b,contextptr);
10552 return plus_one; // return gentypeerr(gettext("symgcd"));
10553 }
10554
simplify(gen & n,gen & d)10555 gen simplify(gen & n, gen & d){
10556 if ( (d.type==_DOUBLE_ || d.type==_FLOAT_) ||
10557 ( (d.type==_CPLX) &&
10558 ((d._CPLXptr->type==_DOUBLE_ || d._CPLXptr->type==_FLOAT_) ||
10559 ((d._CPLXptr+1)->type==_DOUBLE_ || (d._CPLXptr+1)->type==_FLOAT_)) )
10560 ){
10561 gen dd=no_context_evalf(d);
10562 gen nn=no_context_evalf(n);
10563 // if (d==dd && n==nn) return 1; // avoid infinite recursion?
10564 n=rdiv(nn,dd,context0);
10565 d=plus_one;
10566 return dd;
10567 }
10568 if ( (n.type==_DOUBLE_ || n.type==_FLOAT_) ||
10569 ( (n.type==_CPLX) &&
10570 ((n._CPLXptr->type==_DOUBLE_ || n._CPLXptr->type==_FLOAT_) ||
10571 ((n._CPLXptr+1)->type==_DOUBLE_ || (n._CPLXptr+1)->type==_FLOAT_)) )
10572 ){
10573 gen nn=no_context_evalf(n);
10574 n=plus_one;
10575 d=rdiv(no_context_evalf(d),nn,context0);
10576 return nn*simplify(n,d);
10577 }
10578 if (n.type==_FRAC || d.type==_FRAC)
10579 return plus_one;
10580 if (is_one(d))
10581 return d;
10582 if (is_zero(d)){
10583 n=undef;
10584 d=1;
10585 return n;
10586 }
10587 if (is_zero(n)){
10588 gen tmp=d;
10589 d=1;
10590 return tmp;
10591 }
10592 if ( (n.type==_MOD) && (d.type!=_MOD) )
10593 d=makemod(d,*(n._MODptr+1));
10594 if (d.type==_MOD){
10595 if (d._MODptr->is_cinteger()){
10596 gen dd(d);
10597 n=n*inv(dd,context0);
10598 d=makemodquoted(plus_one,*(d._MODptr+1));
10599 return dd;
10600 }
10601 }
10602 if (is_one(n))
10603 return n;
10604 if ((n.type==_POLY) && (d.type==_POLY)){
10605 polynome np(*n._POLYptr),dp(*d._POLYptr);
10606 if (np.dim && dp.dim && np.dim!=dp.dim)
10607 return gensizeerr(gettext("simplify: Polynomials do not have the same dimension"));
10608 polynome g(np.dim);
10609 g=simplify(np,dp);
10610 n=np;
10611 d=dp;
10612 return g;
10613 }
10614 if (n.type==_VECT){
10615 if (d.type==_VECT){
10616 environment * env=new environment;
10617 vecteur g=gcd(*n._VECTptr,*d._VECTptr,env);
10618 delete env;
10619 n=gen(*n._VECTptr/g,_POLY1__VECT);
10620 d=gen(*d._VECTptr/g,_POLY1__VECT);
10621 return gen(g,_POLY1__VECT);
10622 }
10623 gen gg=lgcd(*n._VECTptr,d);
10624 if (!is_one(gg)){
10625 n=divvecteur(*n._VECTptr,gg);
10626 d=d/gg;
10627 }
10628 return gg;
10629 // old code
10630 gen nd=_gcd(n,context0);
10631 gen g=simplify(nd,d);
10632 if (!is_one(g)) n=divvecteur(*n._VECTptr,g);
10633 return g;
10634 }
10635 if (d.type==_VECT){
10636 gen dd=_gcd(d,context0);
10637 gen g=simplify(n,dd);
10638 d=divvecteur(*d._VECTptr,g);
10639 return g;
10640 }
10641 if (d.type==_EXT){
10642 if ( (d._EXTptr->type==_INT_) || (d._EXTptr->type==_ZINT) ){
10643 n=n*inv(d,context0);
10644 gen d_copy=d;
10645 d=1;
10646 return d_copy;
10647 }
10648 if ( (d._EXTptr+1)->type==_EXT || (d._EXTptr+1)->type==_FRAC){
10649 d=ext_reduce(d);
10650 return simplify(n,d);
10651 }
10652 if (d._EXTptr->type==_VECT){
10653 vecteur u,v,dd;
10654 if ( (d._EXTptr+1)->type!=_VECT)
10655 return gensizeerr(gettext("gen.cc:simplify"));
10656 egcd(*(d._EXTptr->_VECTptr),*((d._EXTptr+1)->_VECTptr),0,u,v,dd);
10657 gen tmp=algebraic_EXTension(u,*((d._EXTptr+1)->_VECTptr));
10658 if (tmp.type!=_EXT){
10659 return gensizeerr(gettext("gen.cc:simplify/tmp.type!=_EXT"));
10660 // return 1;
10661 }
10662 n=n*tmp;
10663 d=d*tmp;
10664 return simplify(n,d)*inv_EXT(tmp);
10665 }
10666 return gentypeerr(gettext("simplify"));
10667 }
10668 if (n.type==_EXT){
10669 gen n_EXT=*n._EXTptr;
10670 gen g=simplify(n_EXT,d);
10671 n=algebraic_EXTension(n_EXT,*(n._EXTptr+1));
10672 return g;
10673 }
10674 if (n.type==_POLY) {
10675 return simplify3(n,d); // changed made 18 dec 2016 for speed
10676 polynome np(*n._POLYptr),dp(d,n._POLYptr->dim);
10677 polynome g(np.dim);
10678 g=simplify(np,dp);
10679 n=np;
10680 d=dp;
10681 return g;
10682 }
10683 if (d.type==_POLY){
10684 polynome np(n,d._POLYptr->dim),dp(*d._POLYptr);
10685 polynome g(np.dim);
10686 g=simplify(np,dp);
10687 n=np;
10688 d=dp;
10689 return g;
10690 }
10691 vecteur l(lvar(n));
10692 lvar(d,l);
10693 gen num=e2r(n,l,context0),den=e2r(d,l,context0),g=gcd(num,den,context0); // ok
10694 den=rdiv(den,g,context0);
10695 if (is_exactly_zero(re(den,context0))){ //ok
10696 den=cst_i*den;
10697 g=-cst_i*g;
10698 }
10699 if (is_positive(-den,context0)){ // ok
10700 den=-den;
10701 g=-g;
10702 }
10703 n=r2sym(rdiv(num,g,context0),l,context0); // ok
10704 d=r2sym(den,l,context0); // ok
10705 return r2sym(g,l,context0); // ok
10706 }
10707
gcd(const gen & a,const gen & b)10708 gen gcd(const gen & a,const gen & b){
10709 return gcd(a,b,context0);
10710 }
gcd(const gen & a,const gen & b,GIAC_CONTEXT)10711 gen gcd(const gen & a,const gen & b,GIAC_CONTEXT){
10712 ref_mpz_t * res;
10713 switch ( (a.type<< _DECALAGE) | b.type ) {
10714 case _INT___INT_:
10715 return(gcd(a.val,b.val));
10716 case _INT___ZINT:
10717 if (a.val)
10718 return(int(mpz_gcd_ui(NULL,*b._ZINTptr,absint(a.val))));
10719 else
10720 return is_positive(b,contextptr)?b:-b;
10721 case _ZINT__INT_:
10722 if (b.val)
10723 return(int(mpz_gcd_ui(NULL,*a._ZINTptr,absint(b.val))));
10724 else
10725 return is_positive(a,contextptr)?a:-a;
10726 case _ZINT__ZINT:
10727 #ifndef USE_GMP_REPLACEMENTS
10728 {
10729 int test=mpz_cmp(*a._ZINTptr,*b._ZINTptr);
10730 if (test==0 || (test>0 && mpz_divisible_p(*a._ZINTptr,*b._ZINTptr)))
10731 return abs(b,contextptr);
10732 if (test<0 && mpz_divisible_p(*b._ZINTptr,*a._ZINTptr))
10733 return abs(a,contextptr);
10734 }
10735 #endif
10736 res = new ref_mpz_t;
10737 my_mpz_gcd(res->z,*a._ZINTptr,*b._ZINTptr);
10738 return(res);
10739 case _INT___CPLX: case _ZINT__CPLX:
10740 case _CPLX__INT_: case _CPLX__ZINT:
10741 case _CPLX__CPLX:
10742 return _CPLXgcd(a,b);
10743 case _POLY__POLY:
10744 return polygcd(*a._POLYptr,*b._POLYptr);
10745 case _VECT__VECT:
10746 return gen(gcd(*a._VECTptr,*b._VECTptr,0,ntl_on(contextptr) && a._VECTptr->size()>=NTL_MODGCD && b._VECTptr->size()>=NTL_MODGCD),_POLY1__VECT);
10747 case _FRAC__FRAC:
10748 return fraction(gcd(a._FRACptr->num,b._FRACptr->num,contextptr),lcm(a._FRACptr->den,b._FRACptr->den));
10749 default:
10750 if (a.type==_FRAC)
10751 return fraction(gcd(a._FRACptr->num,b,contextptr),a._FRACptr->den);
10752 if (b.type==_FRAC)
10753 return fraction(gcd(b._FRACptr->num,a,contextptr),b._FRACptr->den);
10754 if (a.type==_USER)
10755 return a._USERptr->gcd(b);
10756 if (b.type==_USER)
10757 return b._USERptr->gcd(a);
10758 {
10759 gen aa(a),bb(b);
10760 if (is_integral(aa) && is_integral(bb))
10761 return gcd(aa,bb,contextptr);
10762 }
10763 return symgcd(a,b,contextptr);
10764 }
10765 }
10766
lcm(const gen & a,const gen & b)10767 gen lcm(const gen & a,const gen & b){
10768 return normal(rdiv(a,gcd(a,b,context0),context0),context0)*b; // ok
10769 }
10770
ciegcd(const gen & a_orig,const gen & b_orig,gen & u,gen & v,gen & d)10771 static void ciegcd(const gen &a_orig,const gen &b_orig, gen & u,gen &v,gen &d ){
10772 gen a(a_orig),b(b_orig),au(plus_one),bu(zero),q,r,ru;
10773 while (!is_exactly_zero(b)){
10774 q=iquo(a,b);
10775 r=a-b*q;
10776 a=b;
10777 b=r;
10778 ru=au-bu*q;
10779 au=bu;
10780 bu=ru;
10781 }
10782 u=au;
10783 d=a;
10784 v=iquo(d-a_orig*u,b_orig);
10785 }
10786
iegcd(int a_,int b_,int & u,int & v)10787 int iegcd(int a_,int b_,int &u,int & v){
10788 int a(a_),b(b_),au(1),bu(0),r,ru;
10789 longlong q;
10790 while (b){
10791 q=a/b;
10792 r=a-b*q;
10793 a=b;
10794 b=r;
10795 ru=au-bu*q;
10796 au=bu;
10797 bu=ru;
10798 }
10799 u=au;
10800 v=(a-longlong(a_)*u)/b_;
10801 return a;
10802 }
10803
egcd(const gen & ac,const gen & bc,gen & u,gen & v,gen & d)10804 void egcd(const gen &ac,const gen &bc, gen & u,gen &v,gen &d ){
10805 gen a(ac),b(bc);
10806 switch ( (a.type<< _DECALAGE) | b.type ) {
10807 case _INT___INT_: case _INT___ZINT: case _ZINT__INT_: case _ZINT__ZINT:
10808 if (a.type==_INT_)
10809 a.uncoerce();
10810 if (b.type==_INT_)
10811 b.uncoerce();
10812 if (!u.type)
10813 u.uncoerce();
10814 if (!v.type)
10815 v.uncoerce();
10816 if (!d.type)
10817 d.uncoerce();
10818 my_mpz_gcdext(*d._ZINTptr,*u._ZINTptr,*v._ZINTptr,*a._ZINTptr,*b._ZINTptr);
10819 if (mpz_sizeinbase(*u._ZINTptr,2)<32)
10820 u=mpz_get_si(*u._ZINTptr);
10821 if (mpz_sizeinbase(*v._ZINTptr,2)<32)
10822 v=mpz_get_si(*v._ZINTptr);
10823 if (mpz_sizeinbase(*d._ZINTptr,2)<32)
10824 d=mpz_get_si(*d._ZINTptr);
10825 break;
10826 default:
10827 ciegcd(a,b,u,v,d);
10828 break;
10829 }
10830 }
10831
_ZINTmod(const gen & a,const gen & b,ref_mpz_t * & rem)10832 static void _ZINTmod (const gen & a,const gen & b,ref_mpz_t * & rem){
10833 if (is_strictly_positive(-b,context0))
10834 return _ZINTmod(a,-b,rem);
10835 // at least one is not an int, uncoerce remaining int
10836 ref_mpz_t *aptr,*bptr;
10837 if (a.type!=_INT_)
10838 #ifdef SMARTPTR64
10839 aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
10840 #else
10841 aptr=a.__ZINTptr;
10842 #endif
10843 else {
10844 aptr=new ref_mpz_t;
10845 mpz_set_si(aptr->z,a.val);
10846 }
10847 if (b.type!=_INT_)
10848 #ifdef SMARTPTR64
10849 bptr= (ref_mpz_t *) (* ((ulonglong * ) &b) >> 16);
10850 #else
10851 bptr=b.__ZINTptr;
10852 #endif
10853 else {
10854 bptr=new ref_mpz_t;
10855 mpz_set_si(bptr->z,b.val);
10856 }
10857 rem=new ref_mpz_t;
10858 mpz_tdiv_r(rem->z,aptr->z,bptr->z);
10859 if (a.type==_INT_)
10860 delete aptr;
10861 if (b.type==_INT_)
10862 delete bptr;
10863 }
10864
operator %(const gen & a,const gen & b)10865 gen operator %(const gen & a,const gen & b){
10866 ref_mpz_t * rem;
10867 switch ( (a.type<< _DECALAGE) | b.type ) {
10868 case _INT___INT_:
10869 if (b.val)
10870 return(a.val % b.val);
10871 else
10872 return a.val;
10873 case _ZINT__ZINT: case _INT___ZINT: case _ZINT__INT_:
10874 _ZINTmod(a,b,rem);
10875 return(rem);
10876 case _CPLX__INT_: case _CPLX__ZINT:
10877 return gen(smod((*a._CPLXptr), b), smod(*(a._CPLXptr+1), b) );
10878 case _INT___CPLX: case _ZINT__CPLX: case _CPLX__CPLX:
10879 return(a-b*iquo(a,b));
10880 case _VECT__VECT:
10881 return (*a._VECTptr)%(*b._VECTptr);
10882 default:
10883 return gentypeerr(gettext("%"));
10884 }
10885 return 0;
10886 }
10887
is_multiple(const gen & a,const gen & b)10888 bool is_multiple(const gen & a,const gen &b){
10889 if (a.type==_INT_){
10890 if (b.type!=_INT_)
10891 return false;
10892 return a.val%b.val==0;
10893 }
10894 if (a.type!=_ZINT)
10895 return false;
10896 if (b.type==_INT_)
10897 return modulo(*a._ZINTptr,b.val)==0;
10898 return a%b==0;
10899 }
10900
_ZINTrem(const gen & a,const gen & b,gen & q,ref_mpz_t * & rem)10901 static void _ZINTrem(const gen & a,const gen &b,gen & q,ref_mpz_t * & rem){
10902 // COUT << a << " irem " << b << '\n';
10903 ref_mpz_t *aptr,*bptr;
10904 if (a.type!=_INT_)
10905 #ifdef SMARTPTR64
10906 aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
10907 #else
10908 aptr=a.__ZINTptr;
10909 #endif
10910 else {
10911 aptr = new ref_mpz_t;
10912 mpz_set_si(aptr->z,a.val);
10913 }
10914 if (b.type!=_INT_)
10915 #ifdef SMARTPTR64
10916 bptr= (ref_mpz_t *) (* ((ulonglong * ) &b) >> 16);
10917 #else
10918 bptr=b.__ZINTptr;
10919 #endif
10920 else {
10921 bptr = new ref_mpz_t;
10922 mpz_set_si(bptr->z,b.val);
10923 }
10924 rem=new ref_mpz_t;
10925 q.uncoerce();
10926 mpz_tdiv_qr(*q._ZINTptr,rem->z,aptr->z,bptr->z);
10927 if (a.type==_INT_)
10928 delete aptr;
10929 if (b.type==_INT_)
10930 delete bptr;
10931 }
10932
irem(const gen & a,const gen & b,gen & q)10933 gen irem(const gen & a,const gen & b,gen & q){
10934 ref_mpz_t * rem;
10935 register int r;
10936 switch ( (a.type<< _DECALAGE) | b.type ) {
10937 case _INT___INT_:
10938 if (!b.val)
10939 return a;
10940 r=a.val % b.val;
10941 /*
10942 if (r<0){
10943 if (b.val>0){
10944 q=gen(a.val/b.val-1);
10945 r += b.val;
10946 }
10947 else {
10948 q=gen(a.val/b.val+1);
10949 r -= b.val;
10950 }
10951 }
10952 else
10953 */
10954 q=gen(a.val/b.val);
10955 return r;
10956 case _ZINT__ZINT: case _INT___ZINT: case _ZINT__INT_:
10957 _ZINTrem(a,b,q,rem);
10958 return(rem);
10959 case _INT___CPLX: case _ZINT__CPLX: case _CPLX__CPLX: case _CPLX__INT_: case _CPLX__ZINT:
10960 q=iquo(a,b);
10961 return(a-b*q);
10962 default:
10963 return gentypeerr(gettext("irem"));
10964 }
10965 return 0;
10966 }
10967
_ZINTsmod(const gen & a,const gen & b,ref_mpz_t * & rem)10968 static void _ZINTsmod(const gen & a, const gen & b, ref_mpz_t * & rem){
10969 // at least one is not an int, uncoerce remaining int
10970 ref_mpz_t *aptr,*bptr;
10971 if (a.type!=_INT_)
10972 #ifdef SMARTPTR64
10973 aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
10974 #else
10975 aptr=a.__ZINTptr;
10976 #endif
10977 else {
10978 aptr = new ref_mpz_t;
10979 mpz_set_si(aptr->z,a.val);
10980 }
10981 if (b.type!=_INT_)
10982 #ifdef SMARTPTR64
10983 bptr= (ref_mpz_t *) (* ((ulonglong * ) &b) >> 16);
10984 #else
10985 bptr=b.__ZINTptr;
10986 #endif
10987 else {
10988 bptr = new ref_mpz_t;
10989 mpz_set_si(bptr->z,b.val);
10990 }
10991 rem = new ref_mpz_t;
10992 mpz_t rem1,rem2,rem3;
10993 mpz_init(rem1); mpz_init(rem2); mpz_init(rem3);
10994 mpz_mod(rem1,aptr->z,bptr->z); // rem1 positive remainder
10995 if (mpz_sgn(bptr->z)>0)
10996 mpz_sub(rem2,rem1,bptr->z); // negative remainder
10997 else
10998 mpz_add(rem2,rem1,bptr->z);
10999 // choose smallest one in abs value
11000 mpz_neg(rem3,rem2);
11001 if (mpz_cmp(rem1,rem3)>0)
11002 mpz_set(rem->z,rem2);
11003 else
11004 mpz_set(rem->z,rem1);
11005 if (a.type==_INT_)
11006 delete aptr;
11007 if (b.type==_INT_)
11008 delete bptr;
11009 mpz_clear(rem1); mpz_clear(rem2); mpz_clear(rem3);
11010 }
11011
smod(const vecteur & v,const gen & g,vecteur & w)11012 void smod(const vecteur & v,const gen & g,vecteur & w){
11013 const_iterateur it=v.begin(),itend=v.end();
11014 w.resize(itend-it);
11015 iterateur jt=w.begin();
11016 for (;it!=itend;++jt,++it)
11017 *jt=smod(*it,g);
11018 }
11019
smod(const vecteur & v,const gen & g)11020 vecteur smod(const vecteur & v,const gen & g){
11021 vecteur w(v);
11022 smod(w,g,w);
11023 return w;
11024 }
11025
smodSYMB(const gen & a,const gen & b)11026 static gen smodSYMB(const gen & a,const gen & b){
11027 vecteur lv(lvar(a));
11028 gen n,d,f;
11029 f=e2r(a,lv,context0); // ok
11030 fxnd(f,n,d);
11031 n=smod(n,b);
11032 d=smod(d,b);
11033 f=n/d;
11034 return r2e(f,lv,context0); // ok
11035 }
11036
fixfracmod(const gen & res,int modulo)11037 static gen fixfracmod(const gen & res, int modulo){
11038 gen n=res._FRACptr->num,d=res._FRACptr->den;
11039 if (n.type!=_POLY)
11040 return res;
11041 if (d.type==_INT_)
11042 return invmod(d.val,modulo)*n;
11043 if (d.type!=_POLY)
11044 return res;
11045 polynome np=*n._POLYptr,dp=*d._POLYptr,tmp,quo,rem;
11046 np=smod(np,modulo);
11047 tmp=gcdmod(np,dp,modulo);
11048 divremmod(np,tmp,modulo,quo,rem);
11049 np=quo;
11050 divremmod(dp,tmp,modulo,quo,rem);
11051 dp=quo;
11052 if (is_one(dp))
11053 return np;
11054 return fraction(np,dp);
11055 }
11056
smod(const gen & a,const gen & b)11057 gen smod(const gen & a,const gen & b){
11058 if (b.type==_INT_ && b.val==0)
11059 return a;
11060 ref_mpz_t * rem;
11061 switch ( (a.type<< _DECALAGE) | b.type ) {
11062 case _INT___INT_:
11063 return smod(a.val,b.val);
11064 case _ZINT__INT_:
11065 return smod(modulo(*a._ZINTptr,absint(b.val)),b.val);
11066 case _INT___ZINT: case _ZINT__ZINT:
11067 _ZINTsmod(a,b,rem);
11068 return(rem);
11069 case _CPLX__INT_: case _CPLX__ZINT:
11070 return gen(smod(*a._CPLXptr,b),smod(*(a._CPLXptr+1),b));
11071 case _POLY__INT_: case _POLY__ZINT:
11072 return smod(*a._POLYptr,b);
11073 case _VECT__INT_: case _VECT__ZINT:
11074 if (a.ref_count()==1){
11075 smod(*a._VECTptr,b,*a._VECTptr);
11076 if (a.subtype==_POLY1__VECT)
11077 *a._VECTptr=trim(*a._VECTptr,0);
11078 return a;
11079 }
11080 {
11081 gen res(new_ref_vecteur(*a._VECTptr),a.subtype);
11082 smod(*res._VECTptr,b,*res._VECTptr);
11083 if (a.subtype==_POLY1__VECT)
11084 *res._VECTptr=trim(*res._VECTptr,0);
11085 return res;
11086 }
11087 default:
11088 if (a.type==_SYMB)
11089 return smodSYMB(a,b);
11090 if (a.type==_FRAC && is_integer(b) && is_integer(a._FRACptr->den))
11091 return smod(a._FRACptr->num*invmod(a._FRACptr->den,b),b);
11092 if (a.type==_FRAC && b.type==_INT_)
11093 return fixfracmod(a,b.val);
11094 if ( (b.type==_INT_) || (b.type==_ZINT) )
11095 return a;
11096 // error, b must be _DOUBLE_
11097 #ifndef NO_STDEXCEPT
11098 throw(std::runtime_error("smod 2nd argument must be _DOUBLE_"));
11099 #endif
11100 return undef;
11101 }
11102 }
11103
_ZINTinvmod(const gen & a,const gen & modulo,ref_mpz_t * & res)11104 static bool _ZINTinvmod(const gen & a,const gen & modulo, ref_mpz_t * & res){
11105 ref_mpz_t *aptr,*bptr;
11106 if (a.type!=_INT_)
11107 #ifdef SMARTPTR64
11108 aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
11109 #else
11110 aptr = a.__ZINTptr;
11111 #endif
11112 else {
11113 aptr = new ref_mpz_t;
11114 mpz_set_si(aptr->z,a.val);
11115 }
11116 if (modulo.type)
11117 #ifdef SMARTPTR64
11118 bptr= (ref_mpz_t *) (* ((ulonglong * ) &modulo) >> 16);
11119 #else
11120 bptr = modulo.__ZINTptr;
11121 #endif
11122 else {
11123 bptr = new ref_mpz_t;
11124 mpz_set_si(bptr->z,modulo.val);
11125 }
11126 res = new ref_mpz_t;
11127 bool ok=my_mpz_invert(res->z,aptr->z,bptr->z)!=0;
11128 if (a.type==_INT_)
11129 delete aptr;
11130 if (!modulo.type)
11131 delete bptr;
11132 if (!ok){
11133 #ifndef NO_STDEXCEPT
11134 setsizeerr(gettext("Not invertible ")+a.print(context0)+" mod "+modulo.print(context0));
11135 #endif
11136 delete res;
11137 res=0;
11138 return false;
11139 }
11140 return true;
11141 }
11142
invmod(const gen & a,const gen & modulo)11143 gen invmod(const gen & a,const gen & modulo){
11144 if (a.type==_USER)
11145 return a._USERptr->inv();
11146 if (a.type==_MOD){
11147 if (*(a._MODptr+1)!=modulo)
11148 return gensizeerr("Incompatible modulo "+a.print(context0)+","+modulo.print(context0));
11149 return inv(a,context0);
11150 }
11151 if (a.type==_CPLX){
11152 gen r=re(a,context0),i=im(a,context0); // ok
11153 gen n=invmod(r*r+i*i,modulo);
11154 return smod(r*n,modulo)-cst_i*smod(i*n,modulo);
11155 }
11156 if (a.type==_POLY)
11157 return fraction(1,a);
11158 ref_mpz_t * res;
11159 switch ( (a.type<< _DECALAGE) | modulo.type) {
11160 case _INT___INT_:
11161 return(invmod(a.val,modulo.val));
11162 case _INT___ZINT: case _ZINT__INT_: case _ZINT__ZINT:
11163 if (!_ZINTinvmod(a,modulo,res))
11164 return gentypeerr(gettext("invmod"));
11165 return gen(res);
11166 default:
11167 return gentypeerr(gettext("invmod"));
11168 }
11169 return 0;
11170 }
11171
in_fracmod(const gen & m,const gen & a,mpz_t & d,mpz_t & d1,mpz_t & absd1,mpz_t & u,mpz_t & u1,mpz_t & ur,mpz_t & q,mpz_t & r,mpz_t & sqrtm,mpz_t & tmp,gen & num,gen & den)11172 bool in_fracmod(const gen &m,const gen & a,mpz_t & d,mpz_t & d1,mpz_t & absd1,mpz_t &u,mpz_t & u1,mpz_t & ur,mpz_t & q,mpz_t & r,mpz_t &sqrtm,mpz_t & tmp,gen & num,gen & den){
11173 mpz_set(d,*m._ZINTptr);
11174 mpz_set(d1,*a._ZINTptr);
11175 mpz_set_si(u,0);
11176 mpz_set_si(u1,1);
11177 mpz_tdiv_q_2exp(q,*m._ZINTptr,1);
11178 mpz_sqrt(sqrtm,q);
11179 // int signe;
11180 for (;;){
11181 mpz_abs(absd1,d1);
11182 if (mpz_cmp(absd1,sqrtm)<=0)
11183 break;
11184 mpz_fdiv_qr(q,r,d,d1);
11185 // u-q*u1->ur, v-q*v1->vr
11186 mpz_mul(tmp,q,u1);
11187 mpz_sub(ur,u,tmp);
11188 // u1 -> u, ur -> u1 ; v1 -> v, vr -> v1, d1 -> d, r -> d1
11189 #ifdef USE_GMP_REPLACEMENTS
11190 mpz_set(u,u1);
11191 mpz_set(u1,ur);
11192 mpz_set(d,d1);
11193 mpz_set(d1,r);
11194 #else
11195 mpz_swap(u,u1);
11196 mpz_swap(u1,ur);
11197 mpz_swap(d,d1);
11198 mpz_swap(d1,r);
11199 #endif
11200 }
11201 // u1*a+v1*m=d1 -> a=d1/u1 modulo m
11202 if (mpz_sizeinbase(d1,2)<=30)
11203 num=int(mpz_get_si(d1));
11204 else
11205 num=d1;
11206 if (mpz_sizeinbase(u1,2)<=30)
11207 den=int(mpz_get_si(u1));
11208 else
11209 den=u1;
11210 mpz_set(q,*m._ZINTptr);
11211 my_mpz_gcd(r,q,u1);
11212 bool ok=mpz_cmp_ui(r,1)==0;
11213 if (!ok){
11214 CERR << "Bad reconstruction " << a << " " << m << " " << gen(r) << '\n';
11215 simplify3(num,den);
11216 return false;
11217 }
11218 return true;
11219 }
11220
alloc_fracmod(const gen & a_orig,const gen & modulo,gen & res,mpz_t & d,mpz_t & d1,mpz_t & absd1,mpz_t & u,mpz_t & u1,mpz_t & ur,mpz_t & q,mpz_t & r,mpz_t & sqrtm,mpz_t & tmp)11221 bool alloc_fracmod(const gen & a_orig,const gen & modulo,gen & res,mpz_t & d,mpz_t & d1,mpz_t & absd1,mpz_t &u,mpz_t & u1,mpz_t & ur,mpz_t & q,mpz_t & r,mpz_t &sqrtm,mpz_t & tmp){
11222 // write a as p/q with |p| and |q|<sqrt(modulo/2)
11223 if (a_orig.type==_VECT){
11224 const_iterateur it=a_orig._VECTptr->begin(),itend=a_orig._VECTptr->end();
11225 vecteur v;
11226 v.reserve(itend-it);
11227 for (;it!=itend;++it){
11228 if (!alloc_fracmod(*it,modulo,res,d,d1,absd1,u,u1,ur,q,r,sqrtm,tmp))
11229 return false;
11230 v.push_back(res);
11231 }
11232 res=gen(v,a_orig.subtype);
11233 return true;
11234 }
11235 if (a_orig.type==_POLY){
11236 vector< monomial<gen> >::const_iterator it=a_orig._POLYptr->coord.begin(),itend=a_orig._POLYptr->coord.end();
11237 polynome v(a_orig._POLYptr->dim);
11238 v.coord.reserve(itend-it);
11239 for (;it!=itend;++it){
11240 if (!alloc_fracmod(it->value,modulo,res,d,d1,absd1,u,u1,ur,q,r,sqrtm,tmp))
11241 return false;
11242 v.coord.push_back(monomial<gen>(res,it->index));
11243 }
11244 res=gen(v);
11245 return true;
11246 }
11247 if (a_orig.type==_CPLX){
11248 gen reres,imres;
11249 if ( !alloc_fracmod(*a_orig._CPLXptr,modulo,reres,d,d1,absd1,u,u1,ur,q,r,sqrtm,tmp) || !alloc_fracmod(*(a_orig._CPLXptr+1),modulo,imres,d,d1,absd1,u,u1,ur,q,r,sqrtm,tmp) )
11250 return false;
11251 res=reres+cst_i*imres;
11252 return true;
11253 }
11254 gen a(a_orig),m(modulo),num,den;
11255 if (a.type==_INT_)
11256 a.uncoerce();
11257 if (m.type==_INT_)
11258 m.uncoerce();
11259 if ( (a.type!=_ZINT) || (m.type!=_ZINT) )
11260 return false;
11261 bool ok=in_fracmod(m,a,d,d1,absd1,u,u1,ur,q,r,sqrtm,tmp,num,den);
11262 if (num.type==_ZINT && mpz_sizeinbase(*num._ZINTptr,2)<=30)
11263 num=int(mpz_get_si(*num._ZINTptr));
11264 if (den.type==_ZINT && mpz_sizeinbase(*den._ZINTptr,2)<=30)
11265 den=int(mpz_get_si(*den._ZINTptr));
11266 if (is_positive(den,context0)) // ok
11267 res=fraction(num,den);
11268 else
11269 res=fraction(-num,-den);
11270 return ok;
11271 }
11272
fracmod(const gen & a_orig,const gen & modulo,gen & res)11273 bool fracmod(const gen & a_orig,const gen & modulo,gen & res){
11274 unsigned prealloc=a_orig.type==_ZINT?mpz_sizeinbase(*a_orig._ZINTptr,2):0;
11275 mpz_t u,d,u1,d1,absd1,sqrtm,q,ur,r,tmp;
11276 mpz_init2(u,prealloc);
11277 mpz_init2(d,prealloc);
11278 mpz_init2(u1,prealloc);
11279 mpz_init(d1);
11280 mpz_init(absd1);
11281 mpz_init(sqrtm);
11282 mpz_init(q);
11283 mpz_init2(ur,prealloc);
11284 mpz_init2(r,prealloc);
11285 mpz_init2(tmp,prealloc);
11286 bool b=alloc_fracmod(a_orig,modulo,res,d,d1,absd1,u,u1,ur,q,r,sqrtm,tmp);
11287 mpz_clear(d);
11288 mpz_clear(u);
11289 mpz_clear(u1);
11290 mpz_clear(d1);
11291 mpz_clear(absd1);
11292 mpz_clear(sqrtm);
11293 mpz_clear(q);
11294 mpz_clear(ur);
11295 mpz_clear(r);
11296 mpz_clear(tmp);
11297 return b;
11298 }
11299
fracmod(const gen & a_orig,const gen & modulo)11300 gen fracmod(const gen & a_orig,const gen & modulo){
11301 if (a_orig==0)
11302 return a_orig;
11303 gen res;
11304 if (!fracmod(a_orig,modulo,res))
11305 return gensizeerr(gettext("Reconstructed denominator is not prime with modulo"));
11306 return res;
11307 }
11308
_ZINTpowmod(const gen & base,const gen & expo,const gen & modulo,ref_mpz_t * & res)11309 static void _ZINTpowmod(const gen & base,const gen & expo,const gen & modulo, ref_mpz_t * & res){
11310 ref_mpz_t *aptr,*bptr;
11311 if (base.type)
11312 #ifdef SMARTPTR64
11313 aptr= (ref_mpz_t *) (* ((ulonglong * ) &base) >> 16);
11314 #else
11315 aptr=base.__ZINTptr;
11316 #endif
11317 else {
11318 aptr = new ref_mpz_t;
11319 mpz_set_si(aptr->z,base.val);
11320 }
11321 if (modulo.type)
11322 #ifdef SMARTPTR64
11323 bptr= (ref_mpz_t *) (* ((ulonglong * ) &modulo) >> 16);
11324 #else
11325 bptr=modulo.__ZINTptr;
11326 #endif
11327 else {
11328 bptr = new ref_mpz_t;
11329 mpz_set_si(bptr->z,modulo.val);
11330 }
11331 res = new ref_mpz_t;
11332 if (!expo.type)
11333 mpz_powm_ui(res->z,aptr->z,expo.val,*modulo._ZINTptr);
11334 else
11335 mpz_powm (res->z,aptr->z,*expo._ZINTptr,bptr->z);
11336 if (!base.type)
11337 delete aptr;
11338 if (!modulo.type)
11339 delete bptr;
11340 }
11341
powmod(const gen & base,const gen & expo,const gen & modulo)11342 gen powmod(const gen &base,const gen & expo,const gen & modulo){
11343 if (is_exactly_zero(modulo))
11344 return pow(base,expo,context0);
11345 if (base.type==_VECT){
11346 const_iterateur it=base._VECTptr->begin(),itend=base._VECTptr->end();
11347 vecteur res;
11348 for (;it!=itend;++it)
11349 res.push_back(powmod(*it,expo,modulo));
11350 return gen(res,base.subtype);
11351 }
11352 if ((expo.type!=_INT_) && (expo.type!=_ZINT))
11353 return gensizeerr(gettext("powmod")); // exponent must be a _DOUBLE_ integer
11354 if (!is_positive(expo,context0)) // ok
11355 return(powmod(invmod(base,modulo),-expo,modulo));
11356 if (modulo.type==_INT_){
11357 // try converting base to int and expo to a long
11358 gen mybase(base % modulo);
11359 if ( (expo.type==_INT_) && (mybase.type==_INT_) ){
11360 unsigned long tmp=expo.val;
11361 return powmod(mybase.val,tmp,modulo.val);
11362 }
11363 }
11364 ref_mpz_t * res;
11365 switch ( (base.type<< _DECALAGE) | modulo.type) {
11366 case _INT___INT_: case _INT___ZINT: case _ZINT__INT_: case _ZINT__ZINT:
11367 _ZINTpowmod(base,expo,modulo,res);
11368 return(res);
11369 default:
11370 return gentypeerr(gettext("powmod"));
11371 }
11372 return 0;
11373 }
11374
11375 // assuming amod and bmod are prime together, find c such that
11376 // c = a mod amod and c = b mod bmod
11377 // hence a + A*amod = b + B*bmod
11378 // or A*amod -B*bmod = b - a
ichinrem(const gen & a,const gen & b,const gen & amod,const gen & bmod)11379 gen ichinrem(const gen & a,const gen &b,const gen & amod, const gen & bmod){
11380 if (a.type==_INT_ && b.type==_INT_ && amod.type==_INT_ && bmod.type==_INT_ && gcd(amod.val,bmod.val)==1){
11381 int amodinv=invmod(amod.val,bmod.val);
11382 longlong res=a.val+((longlong(amodinv)*(b.val-longlong(a.val)))%bmod.val)*amod.val;
11383 return res;
11384 }
11385 gen A,B,d,q;
11386 egcd(amod,bmod,A,B,d);
11387 if (is_one(d))
11388 q=b-a;
11389 else
11390 if (!is_exactly_zero(irem(b-a,d,q)))
11391 return gensizeerr(gettext("No Integer Solution"));
11392 A=A*q;
11393 return smod(A*amod+a,amod*bmod);
11394 }
11395
isqrt(const gen & a)11396 gen isqrt(const gen & a){
11397 if ( (a.type!=_INT_) && (a.type!=_ZINT))
11398 return gentypeerr(gettext("isqrt"));
11399 ref_mpz_t *aptr;
11400 if (a.type!=_INT_)
11401 #ifdef SMARTPTR64
11402 aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
11403 #else
11404 aptr=a.__ZINTptr;
11405 #endif
11406 else {
11407 aptr = new ref_mpz_t;
11408 mpz_set_si(aptr->z,a.val);
11409 }
11410 ref_mpz_t *res = new ref_mpz_t;
11411 mpz_sqrt(res->z,aptr->z);
11412 if (a.type==_INT_)
11413 delete aptr;
11414 return res;
11415 }
11416
is_perfect_square(const gen & a)11417 int is_perfect_square(const gen & a){
11418 if ( (a.type!=_INT_) && (a.type!=_ZINT))
11419 return false;
11420 ref_mpz_t *aptr;
11421 if (a.type!=_INT_)
11422 #ifdef SMARTPTR64
11423 aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
11424 #else
11425 aptr=a.__ZINTptr;
11426 #endif
11427 else {
11428 aptr = new ref_mpz_t;
11429 mpz_set_si(aptr->z,a.val);
11430 }
11431 int res= mpz_perfect_square_p(aptr->z);
11432 if (a.type==_INT_)
11433 delete aptr;
11434 return res;
11435 }
11436
is_probab_prime_p(const gen & a)11437 int is_probab_prime_p(const gen & a){
11438 if ( (a.type!=_INT_) && (a.type!=_ZINT)){
11439 #ifndef NO_STDEXCEPT
11440 settypeerr(gettext("is_probab_prime_p"));
11441 #endif
11442 return false;
11443 }
11444 if (a.type==_INT_ && a.val<2)
11445 return false;
11446 if (a.type==_INT_ && a.val<(1<<20)){
11447 for (int i=0;;++i){
11448 int p=giac_primes[i];
11449 if (p*p>a.val)
11450 return true;
11451 if (a.val%p==0)
11452 return false;
11453 }
11454 }
11455 ref_mpz_t *aptr;
11456 if (a.type!=_INT_)
11457 #ifdef SMARTPTR64
11458 aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
11459 #else
11460 aptr=a.__ZINTptr;
11461 #endif
11462 else {
11463 aptr = new ref_mpz_t;
11464 mpz_set_si(aptr->z,a.val);
11465 }
11466 int res= mpz_probab_prime_p(aptr->z,TEST_PROBAB_PRIME);
11467 if (a.type==_INT_)
11468 delete aptr;
11469 return res;
11470 }
11471
nextprime(const gen & a)11472 gen nextprime(const gen & a){
11473 if ( (a.type!=_INT_) && (a.type!=_ZINT))
11474 return gentypeerr(gettext("nextprime"));
11475 gen res(a);
11476 if (is_exactly_zero(smod(res,plus_two)))
11477 res=res+1;
11478 for ( ; ; res=res+2){
11479 #ifdef TIMEOUT
11480 control_c();
11481 #endif
11482 if (ctrl_c || interrupted)
11483 return gensizeerr(gettext("Interrupted"));
11484 if (is_probab_prime_p(res))
11485 return(res);
11486 }
11487 }
11488
prevprime(const gen & a)11489 gen prevprime(const gen & a){
11490 if ( (a.type!=_INT_) && (a.type!=_ZINT))
11491 return gentypeerr(gettext("prevprime"));
11492 if (a==2)
11493 return a;
11494 if (is_greater(2,a,context0))
11495 return gensizeerr(context0);
11496 gen res(a);
11497 if (is_exactly_zero(smod(res,plus_two)))
11498 res=res-1;
11499 for ( ; res.type==_ZINT || (res.type==_INT_ && res.val>1); res=res-2){
11500 #ifdef TIMEOUT
11501 control_c();
11502 #endif
11503 if (ctrl_c || interrupted)
11504 return gensizeerr(gettext("Interrupted"));
11505 if (is_probab_prime_p(res))
11506 return(res);
11507 }
11508 return zero;
11509 }
11510
jacobi(const gen & a,const gen & b)11511 int jacobi(const gen & a, const gen &b){
11512 if ( (a.type!=_INT_ && a.type!=_ZINT) || (b.type!=_INT_ && b.type!=_ZINT)){
11513 #ifndef NO_STDEXCEPT
11514 settypeerr(gettext("jacobi"));
11515 #endif
11516 return -RAND_MAX;
11517 }
11518 ref_mpz_t *aptr,*bptr;
11519 if (a.type!=_INT_)
11520 #ifdef SMARTPTR64
11521 aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
11522 #else
11523 aptr = a.__ZINTptr;
11524 #endif
11525 else {
11526 aptr = new ref_mpz_t;
11527 mpz_set_si(aptr->z,a.val);
11528 }
11529 if (b.type!=_INT_)
11530 #ifdef SMARTPTR64
11531 bptr= (ref_mpz_t *) (* ((ulonglong * ) &b) >> 16);
11532 #else
11533 bptr=b.__ZINTptr;
11534 #endif
11535 else {
11536 bptr = new ref_mpz_t;
11537 mpz_set_si(bptr->z,b.val);
11538 }
11539 int res= mpz_jacobi(aptr->z,bptr->z);
11540 if (a.type==_INT_)
11541 delete aptr;
11542 if (b.type==_INT_)
11543 delete bptr;
11544 return res;
11545 }
11546
legendre(const gen & a,const gen & b)11547 int legendre(const gen & a, const gen & b){
11548 if ( (a.type!=_INT_ && a.type!=_ZINT) || (b.type!=_INT_ && b.type!=_ZINT)){
11549 #ifndef NO_STDEXCEPT
11550 settypeerr(gettext("legendre"));
11551 #endif
11552 return -RAND_MAX;
11553 }
11554 ref_mpz_t *aptr,*bptr;
11555 if (a.type!=_INT_)
11556 #ifdef SMARTPTR64
11557 aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
11558 #else
11559 aptr=a.__ZINTptr;
11560 #endif
11561 else {
11562 aptr= new ref_mpz_t;
11563 mpz_set_si(aptr->z,a.val);
11564 }
11565 if (b.type!=_INT_)
11566 #ifdef SMARTPTR64
11567 bptr= (ref_mpz_t *) (* ((ulonglong * ) &b) >> 16);
11568 #else
11569 bptr=b.__ZINTptr;
11570 #endif
11571 else {
11572 bptr= new ref_mpz_t;
11573 mpz_set_si(bptr->z,b.val);
11574 }
11575 int res=mpz_legendre(aptr->z,bptr->z);
11576 if (a.type==_INT_)
11577 delete aptr;
11578 if (b.type==_INT_)
11579 delete bptr;
11580 return res;
11581 }
11582
has_denominator(const gen & n)11583 bool has_denominator(const gen & n){
11584 switch (n.type ) {
11585 case _INT_: case _ZINT: case _CPLX: case _DOUBLE_: case _FLOAT_: case _IDNT: case _EXT: case _POLY: case _MOD: case _USER: case _REAL: case _VECT:
11586 return false;
11587 case _SYMB: case _FRAC:
11588 return true;
11589 default:
11590 #ifndef NO_STDEXCEPT
11591 settypeerr(gettext("has_denominator"));
11592 #endif
11593 return false;
11594 }
11595 return 0;
11596 }
11597
11598
factorial(unsigned long int i)11599 gen factorial(unsigned long int i){
11600 if (i>(unsigned long int)FACTORIAL_SIZE_LIMIT){
11601 #ifndef NO_STDEXCEPT
11602 setstabilityerr();
11603 #endif
11604 return plus_inf;
11605 }
11606 ref_mpz_t * e = new ref_mpz_t;
11607 mpz_fac_ui(e->z,i);
11608 return e;
11609 }
11610
comb(unsigned long int i,unsigned long j)11611 gen comb(unsigned long int i,unsigned long j){
11612 if (i>(unsigned long int)FACTORIAL_SIZE_LIMIT){
11613 double d=std::min(j,i-j)*std::log10(double(i));
11614 if (d>2*FACTORIAL_SIZE_LIMIT){
11615 #ifndef NO_STDEXCEPT
11616 setstabilityerr();
11617 #endif
11618 return undef;
11619 }
11620 }
11621 ref_mpz_t * e = new ref_mpz_t;
11622 if (i<j)
11623 return e;
11624 #ifdef mpz_bin_uiui
11625 mpz_bin_uiui(e->z,i,j);
11626 #else
11627 mpz_set_ui(e->z,1);
11628 for (unsigned long int k=i;k>i-j;--k)
11629 mpz_mul_ui(e->z,e->z,k);
11630 mpz_t tmp;
11631 mpz_init(tmp);
11632 mpz_fac_ui(tmp,j);
11633 mpz_fdiv_q(e->z,e->z,tmp);
11634 mpz_clear(tmp);
11635 #endif
11636 return e;
11637 }
11638
perm(unsigned long int i,unsigned long j)11639 gen perm(unsigned long int i,unsigned long j){
11640 if (i>(unsigned long int)FACTORIAL_SIZE_LIMIT){
11641 double d=j*std::log10(double(i));
11642 if (d>2*FACTORIAL_SIZE_LIMIT){
11643 #ifndef NO_STDEXCEPT
11644 setstabilityerr();
11645 #endif
11646 return undef;
11647 }
11648 }
11649 ref_mpz_t * e = new ref_mpz_t;
11650 if (i<j)
11651 return e;
11652 mpz_set_ui(e->z,1);
11653 for (unsigned long int k=i;k>i-j;--k)
11654 mpz_mul_ui(e->z,e->z,k);
11655 return e;
11656 }
11657
11658 /* I/O: Input routines */
11659
chartab2gen(char * s,GIAC_CONTEXT)11660 gen chartab2gen(char * s,GIAC_CONTEXT){
11661 gen res;
11662 // subtype=0;
11663 // initialize as a null _INT_
11664 // type = _INT_;
11665 // val = 0;
11666 if (!*s)
11667 return res;
11668 #ifdef EMCC
11669 int base=10;
11670 #else
11671 int base=(abs_calc_mode(contextptr)==38 || calc_mode(contextptr)==1)?10:0;
11672 #endif
11673 if (s[0]=='#' || s[0]=='0') {
11674 if (s[1]=='x' || s[1]=='X'){
11675 s[0]='0';
11676 s[1]='0';
11677 base=16;
11678 }
11679 if (s[1]=='o' || s[1]=='O'){
11680 s[0]='0';
11681 s[1]='0';
11682 base=8;
11683 }
11684 }
11685 if (s[1]=='b' || s[1]=='B'){
11686 s[0]='0';
11687 s[1]='0';
11688 base=2;
11689 }
11690 #ifdef _LIB_CE_ERRNO_H
11691 #ifndef BESTA_OS
11692 __set_errno(0);
11693 #endif
11694 #else
11695 errno = 0;
11696 #endif
11697 char * endchar;
11698 #ifdef VISUALC
11699 longlong ll=strtol(s,&endchar,base);
11700 #else
11701 longlong ll=strtoll(s,&endchar,base);
11702 #endif
11703 int l =int(strlen(s));
11704 if (l>0 && s[l-1]=='.'){
11705 // make a copy of s, call chartab2gen recursivly,
11706 // because some implementations of strtod do not like a . at the end
11707 #if 1 // def FREERTOS
11708 ALLOCA(char, scopy, l+2);
11709 #else
11710 char * scopy=(char *)alloca(l+2);
11711 #endif
11712 strcpy(scopy,s);
11713 scopy[l]='0';
11714 scopy[l+1]=0;
11715 return chartab2gen(scopy,contextptr);
11716 }
11717 if (*endchar) {// non integer
11718 int digits=decimal_digits(contextptr);
11719 // count numeric char
11720 int delta=0;
11721 if (l && s[0]=='0')
11722 ++delta;
11723 for (int k=0;k<l;++k){
11724 if (s[k]=='e' || s[k]=='E'){
11725 delta += l-k;
11726 break;
11727 }
11728 if (s[k]<'0' || s[k]>'9')
11729 ++delta;
11730 }
11731 if (l>digits+delta)
11732 digits=l-delta;
11733 #ifdef HAVE_LIBMPFR // #ifndef GIAC_HAS_STO_38
11734 if (digits>14){
11735 #if 1 // def HAVE_LIBMPFR
11736 int nbits=digits2bits(digits);
11737 #ifdef HAVE_LIBPTHREAD
11738 int locked=pthread_mutex_trylock(&mpfr_mutex);
11739 if (!locked)
11740 mpfr_set_default_prec(nbits);
11741 // mpf_set_default_prec (decimal_digits);
11742 real_object r;
11743 int res=mpfr_set_str(r.inf,s,10,MPFR_RNDN);
11744 if (!locked)
11745 pthread_mutex_unlock(&mpfr_mutex);
11746 #else
11747 real_object r;
11748 mpfr_set_default_prec(nbits);
11749 int res=mpfr_set_str(r.inf,s,10,MPFR_RNDN);
11750 #endif // HAVE_LIBPTHREAD
11751 #else // LIBMPFR
11752 real_object r;
11753 int res=mpf_set_str(r.inf,s,10);
11754 #endif // LIBMPFR
11755 gen rg(r);
11756 // rg.dbgprint();
11757 if (!res)
11758 return rg;
11759 } // end if (digits>14)
11760 #endif // LIBMPFR was GIAC_HAS_STO_38
11761 double d;
11762 #if defined NSPIRE || defined FXCG
11763 #ifdef NSPIRE
11764 d=Strtod(s,&endchar);
11765 #else
11766 d=strtod(s,&endchar);
11767 #endif // NSPIRE
11768 #else // NSPIRE || FXCG
11769 #ifdef HAVE_LIBPTHREAD
11770 int locked=pthread_mutex_trylock(&locale_mutex);
11771 if (!locked){
11772 char * lc=setlocale(LC_NUMERIC,(char *)NULL);
11773 setlocale(LC_NUMERIC,"POSIX");
11774 d=strtod(s,&endchar);
11775 setlocale(LC_NUMERIC,lc);
11776 pthread_mutex_unlock(&locale_mutex);
11777 }
11778 else
11779 d=strtod(s,&endchar);
11780 #else
11781 char * lc=setlocale(LC_NUMERIC,(char const *)NULL);
11782 setlocale(LC_NUMERIC,"POSIX");
11783 d=strtod(s,&endchar);
11784 setlocale(LC_NUMERIC,lc);
11785 #endif // PTHREAD
11786 #endif // NSPIRE
11787 if (*endchar){
11788 #ifdef BCD
11789 giac_float gf;
11790 gf=strtobcd(s,(const char **)&endchar);
11791 if (!*endchar)
11792 return gf;
11793 for (int i=0;i<l;++i){
11794 unsigned si=(unsigned char)s[i];
11795 if (si==226 || si==194)
11796 return gf;
11797 }
11798 // if (abs_calc_mode(contextptr)==38) return gensizeerr(gettext("Invalid float"));
11799 #endif
11800 for (int i=0;i<l;++i){
11801 unsigned si=(unsigned char)s[i];
11802 if (si==226 || si==194)
11803 return undef;
11804 }
11805 return gen(string(s),contextptr);
11806 }
11807 return gen(d);
11808 } // end non integer if (*endchar)
11809 if (!errno ){
11810 // this converts 0xFFFFFFFF to -1, because we want two's complement, if possible
11811 // it makes positive numbers 0x80000000 to 0xFFFFFFFF unavailable (only in base-2 notation),
11812 // but I am aware of that
11813 if (ll==int(ll) ||
11814 ( (base == 2 ||base == 8 || base == 16) &&
11815 ll == (unsigned int)(ll) )
11816 )
11817 return gen ( int(ll));
11818 else
11819 return gen(longlong(ll));
11820 }
11821 // check if a non 0-9 char is there
11822 if (!base){
11823 base=10;
11824 for (int i=0;i<l;++i){
11825 if ((s[i]<'0') || (s[i]>'9'))
11826 base=16;
11827 }
11828 }
11829 int maxsize = 5 + (s[0]=='-');
11830 if (base==10 && l<maxsize){
11831 res.type=_INT_;
11832 res.val = atoi(s);
11833 return res;
11834 }
11835 else {
11836 ref_mpz_t * ptr= new ref_mpz_t;
11837 mpz_set_str(ptr->z,s,base);
11838 res= gen(ptr);
11839 return res;
11840 }
11841 }
11842
string2gen(const string & ss,bool remove_ss_quotes)11843 gen string2gen(const string & ss,bool remove_ss_quotes){
11844 gen res;
11845 #ifdef SMARTPTR64
11846 * ((ulonglong * ) &res) = ulonglong(new ref_string(remove_ss_quotes?ss.substr(1,ss.size()-2):ss)) << 16;
11847 #else
11848 res.__STRNGptr = new ref_string(remove_ss_quotes?ss.substr(1,ss.size()-2):ss);
11849 #endif
11850 res.type=_STRNG;
11851 return res;
11852 }
11853
11854 int giac_yyparse(void * scanner);
11855
try_parse(const string & s_orig,GIAC_CONTEXT)11856 static int try_parse(const string & s_orig,GIAC_CONTEXT){
11857 string s=s_orig;
11858 if (1 || abs_calc_mode(contextptr)!=38){
11859 // remove leading spaces
11860 for (int i=0;i<s.size();++i){
11861 if (s[i]!=' '){
11862 if (i)
11863 s=s.substr(i,s.size()-i);
11864 break;
11865 }
11866 }
11867 if (s.size()>10 && (s.substr(0,5)=="\"def " || s.substr(0,10)=="\"function ")){
11868 string news="";
11869 int ss=s.size()-1;
11870 for (;ss>5;--ss){
11871 if (s[ss]=='"')
11872 break;
11873 }
11874 for (int i=1;i<ss;++i){
11875 char ch=s[i];
11876 if (ch==char(0xa)){
11877 news+='\n';
11878 continue;
11879 }
11880 if (ch=='"' && s[i+1]=='"')
11881 ++i;
11882 if (ch=='`')
11883 news+='"';
11884 else
11885 news+=ch;
11886 }
11887 s=news;
11888 }
11889 s=python2xcas(s,contextptr);
11890 if (s.empty()){
11891 parsed_gen(undef,contextptr);
11892 return 1;
11893 }
11894 }
11895 #if !defined(WIN32) && defined(HAVE_PTHREAD_H)
11896 if (contextptr && thread_param_ptr(contextptr)->stackaddr && thread_param_ptr(contextptr)->stacksize/2){
11897 gen er;
11898 short int err=s.size();
11899 if (debug_infolevel>10000)
11900 CERR << (size_t) &err << " " << ((size_t) thread_param_ptr(contextptr)->stackaddr)+4*65536 << '\n';
11901 if ( ((size_t) &err) < ((size_t) thread_param_ptr(contextptr)->stackaddr)+4*65536){
11902 gensizeerr(gettext("Too many recursion levels"),er);
11903 parsed_gen(er,contextptr);
11904 return 1;
11905 }
11906 }
11907 #endif // pthread
11908 int res;
11909 int isqrt=i_sqrt_minus1(contextptr);
11910 #ifndef NO_STDEXCEPT
11911 try {
11912 #endif
11913 void * scanner;
11914 YY_BUFFER_STATE state=set_lexer_string(s,scanner,contextptr);
11915 if (xcas_mode(contextptr)==0 && try_parse_i(contextptr))
11916 i_sqrt_minus1(0,contextptr);
11917 res=giac_yyparse(scanner);
11918 delete_lexer_string(state,scanner);
11919 // if xcas_mode(contextptr)<=0 scan for i:=something, if not present replace i by sqrt(-1)
11920 if (xcas_mode(contextptr)==0 && try_parse_i(contextptr)){
11921 const gen& p = parsed_gen(contextptr);
11922 if (1) { // p.type==_SYMB || p.type==_VECT){
11923 vecteur v(rlvarx(p,i__IDNT_e));
11924 if (!v.empty()){
11925 vecteur w=lop(v,at_program);
11926 int i,vs=int(w.size());
11927 for (i=0;i<vs;i++){
11928 gen & args = w[i]._SYMBptr->feuille;
11929 if (args.type!=_VECT || args._VECTptr->empty())
11930 continue;
11931 if (contains(args._VECTptr->front(),i__IDNT_e)){
11932 *logptr(contextptr) << gettext("Warning, i is usually sqrt(-1), I'm using a symbolic variable instead but you should check your input") << '\n';
11933 return res;
11934 }
11935 }
11936 w=lop(v,at_local);
11937 vs=int(w.size());
11938 for (i=0;i<vs;i++){
11939 gen & args = w[i]._SYMBptr->feuille;
11940 if (args.type!=_VECT || args._VECTptr->empty())
11941 continue;
11942 if (contains(args._VECTptr->front(),i__IDNT_e)){
11943 *logptr(contextptr) << gettext("Warning, i is usually sqrt(-1), I'm using a symbolic variable instead but you should check your input") << '\n';
11944 return res;
11945 }
11946 }
11947 v=lop(v,at_sto);
11948 vs=int(v.size());
11949 for (i=0;i<vs;i++){
11950 if (v[i]._SYMBptr->feuille[1]==i__IDNT_e){
11951 *logptr(contextptr) << gettext("Warning, i is usually sqrt(-1), I'm using a symbolic variable instead but you should check your input") << '\n';
11952 break;
11953 }
11954 }
11955 if (i==vs){
11956 #ifndef NSPIRE
11957 my_ostream * log = logptr(contextptr);
11958 logptr(0,contextptr);
11959 #endif
11960 i_sqrt_minus1(1,contextptr);
11961 void * scanner2;
11962 YY_BUFFER_STATE state2=set_lexer_string(s,scanner2,contextptr);
11963 res=giac_yyparse(scanner2);
11964 #ifndef NSPIRE
11965 logptr(log,contextptr);
11966 #endif
11967 delete_lexer_string(state2,scanner2);
11968 }
11969 }
11970 }
11971 } // end if (xcas_mode(contextptr)==0 ...
11972 #ifndef NO_STDEXCEPT
11973 }
11974 catch (std::runtime_error & error){
11975 i_sqrt_minus1(isqrt,contextptr);
11976 if (!first_error_line(contextptr))
11977 first_error_line(lexer_line_number(contextptr),contextptr);
11978 parser_error(error.what(),contextptr);
11979 #ifdef HAVE_SIGNAL_H_OLD
11980 messages_to_print += string(error.what()) + '\n';
11981 #endif
11982 return 1;
11983 }
11984 #endif
11985 i_sqrt_minus1(isqrt,contextptr);
11986 return res;
11987 }
11988
aplatir_plus(const gen & g)11989 static gen aplatir_plus(const gen & g){
11990 // Quick check for embedded + at the left coming from parser
11991 if (g.is_symb_of_sommet(at_plus) && g._SYMBptr->feuille.type==_VECT){
11992 iterateur it=g._SYMBptr->feuille._VECTptr->begin(),itend=g._SYMBptr->feuille._VECTptr->end();
11993 if (it==itend)
11994 return 0;
11995 vecteur v;
11996 v.reserve(itend-it+1);
11997 gen f;
11998 for (;it!=itend;){
11999 for (--itend;itend!=it;--itend)
12000 v.push_back(aplatir_fois_plus(*itend));
12001 if (!it->is_symb_of_sommet(at_plus)){
12002 v.push_back(aplatir_fois_plus(*it));
12003 break;
12004 }
12005 f=it->_SYMBptr->feuille;
12006 if (f.type!=_VECT){
12007 v.push_back(*it);
12008 break;
12009 }
12010 it=f._VECTptr->begin();
12011 itend=f._VECTptr->end();
12012 }
12013 reverse(v.begin(),v.end());
12014 return new_ref_symbolic(symbolic(at_plus,gen(v,_SEQ__VECT)));
12015 }
12016 return g;
12017 }
12018
aplatir_fois_plus(const gen & g)12019 gen aplatir_fois_plus(const gen & g){
12020 if (g.type==_VECT){
12021 vecteur v(*g._VECTptr);
12022 iterateur it=v.begin(),itend=v.end();
12023 for (;it!=itend;++it)
12024 *it=aplatir_fois_plus(*it);
12025 return gen(v,g.subtype);
12026 }
12027 if (g.type!=_SYMB)
12028 return g;
12029 if (g._SYMBptr->sommet==at_pow && g._SYMBptr->feuille.type==_VECT && g._SYMBptr->feuille.subtype!=_SEQ__VECT)
12030 return symbolic(at_pow,change_subtype(g._SYMBptr->feuille,_SEQ__VECT));
12031 if (g._SYMBptr->sommet==at_plus)
12032 return aplatir_plus(g);
12033 gen & f=g._SYMBptr->feuille;
12034 if (g._SYMBptr->sommet==at_prod && f.type==_VECT && f._VECTptr->size()==2)
12035 return sym_mult(aplatir_fois_plus(f._VECTptr->front()),aplatir_fois_plus(f._VECTptr->back()),context0);
12036 return new_ref_symbolic(symbolic(g._SYMBptr->sommet,aplatir_fois_plus(f)));
12037 }
12038
aplatir_plus_only(const gen & g)12039 static gen aplatir_plus_only(const gen & g){
12040 if (g.type==_VECT){
12041 const vecteur & v=*g._VECTptr;
12042 vecteur w(v);
12043 const_iterateur it=v.begin(),itend=v.end();
12044 iterateur jt=w.begin();
12045 for (;it!=itend;++jt,++it)
12046 *jt=aplatir_plus_only(*it);
12047 return gen(w,g.subtype);
12048 }
12049 if (g.type!=_SYMB)
12050 return g;
12051 // Quick check for embedded + at the left coming from parser
12052 if (g.is_symb_of_sommet(at_plus) && g._SYMBptr->feuille.type==_VECT){
12053 const_iterateur it=g._SYMBptr->feuille._VECTptr->begin(),itend=g._SYMBptr->feuille._VECTptr->end();
12054 if (it==itend)
12055 return 0;
12056 vecteur v;
12057 v.reserve(itend-it+1);
12058 register const gen * f;
12059 for (;it!=itend;){
12060 for (--itend;itend!=it;--itend)
12061 v.push_back(*itend);
12062 // Check first element of the vector g, if it's not a + add it to v and end
12063 if (it->type!=_SYMB || it->_SYMBptr->sommet!=at_plus || (f=&it->_SYMBptr->feuille,f->type!=_VECT) ){
12064 v.push_back(*it);
12065 break;
12066 }
12067 // first element was a plus, restart with all it's arguments
12068 itend=f->_VECTptr->end();
12069 it=f->_VECTptr->begin();
12070 }
12071 reverse(v.begin(),v.end());
12072 return gen(new_ref_symbolic(symbolic(at_plus,gen(v,_SEQ__VECT)))).change_subtype(g.subtype);
12073 }
12074 return gen(new_ref_symbolic(symbolic(g._SYMBptr->sommet,aplatir_plus_only(g._SYMBptr->feuille)))).change_subtype(g.subtype);
12075 }
12076
protected_giac_yyparse(const string & chaine,gen & parse_result,GIAC_CONTEXT)12077 static int protected_giac_yyparse(const string & chaine,gen & parse_result,GIAC_CONTEXT){
12078 int s;
12079 s=int(chaine.size());
12080 if (!s)
12081 return 1;
12082 #ifdef HAVE_LIBPTHREAD
12083 static pthread_mutex_t parse_mutex = PTHREAD_MUTEX_INITIALIZER;
12084 int locked = pthread_mutex_lock(&parse_mutex);
12085 #else // HAVE_LIBPTHREAD
12086 int locked = 0;
12087 #endif
12088 int res = 1;
12089 #ifndef NO_STDEXCEPT
12090 try {
12091 #endif
12092 res=try_parse(chaine,contextptr);
12093 gen g=parsed_gen(contextptr);
12094 if (g.type<=_FLOAT_){
12095 parse_result=aplatir_plus_only(g);
12096 // parse_result=aplatir_fois_plus(g);
12097 if (g.type==_SYMB && parse_result.type==_SYMB)
12098 parse_result.subtype=g.subtype;
12099 #ifdef HAVE_LIBPTHREAD
12100 if (!locked)
12101 pthread_mutex_unlock(&parse_mutex);
12102 #endif
12103 return res;
12104 }
12105 parsed_gen(0,contextptr);
12106 parse_result.type=0;
12107 parse_result=0;
12108 CERR << "Incomplete parse" << '\n';
12109 #ifdef HAVE_LIBPTHREAD
12110 if (!locked)
12111 pthread_mutex_unlock(&parse_mutex);
12112 #endif
12113 #ifndef NO_STDEXCEPT
12114 } catch (std::runtime_error &e) {
12115 #ifdef HAVE_LIBPTHREAD
12116 if (!locked)
12117 pthread_mutex_unlock(&parse_mutex);
12118 #endif
12119 }
12120 #endif // exception
12121 return res;
12122 }
12123
gen(const string & s,GIAC_CONTEXT)12124 gen::gen(const string & s,GIAC_CONTEXT){
12125 subtype=0;
12126 string ss(s);
12127 /*
12128 string::iterator it=ss.begin(),itend=ss.end();
12129 for (;it!=itend;++it)
12130 if (*it=='\\')
12131 *it=' ';
12132 */
12133 type=_INT_;
12134 if (s==string(s.size(),' ')){
12135 *this=undef;
12136 return;
12137 }
12138 if (protected_giac_yyparse(s,*this,contextptr)){
12139 if (ss.empty())
12140 ss="""""";
12141 if (ss[0]!='"')
12142 ss = '"'+ss;
12143 if ((ss.size()==1) || (ss[ss.size()-1]!='"'))
12144 ss += '"';
12145 #ifdef SMARTPTR64
12146 * ((ulonglong * ) this) = ulonglong(new ref_string(ss.substr(1,ss.size()-2))) << 16;
12147 subtype=0;
12148 #else
12149 __STRNGptr = new ref_string(ss.substr(1,ss.size()-2));
12150 #endif
12151 type=_STRNG;
12152 }
12153 }
12154
genfromstring(const string & s)12155 gen genfromstring(const string & s){
12156 return gen(s,context0);
12157 }
12158
12159 /*
12160 gen::gen(const string & s,const vecteur & l,GIAC_CONTEXT){
12161 type=_INT_;
12162 if (protected_giac_yyparse(s,*this,contextptr)){
12163 string ss(s);
12164 if (ss.empty())
12165 ss="""""";
12166 if (ss[0]!='"')
12167 ss = '"'+ss;
12168 if ((ss.size()==1) || (ss[ss.size()-1]!='"'))
12169 ss += '"';
12170 #ifdef SMARTPTR64
12171 * ((ulonglong * ) this) = ulonglong(new ref_string(ss.substr(1,ss.size()-2))) << 16;
12172 #else
12173 __STRNGptr = new ref_string(ss.substr(1,ss.size()-2));
12174 #endif
12175 type=_STRNG;
12176 }
12177 subtype=0;
12178 }
12179 */
12180
gen(const wchar_t * ws,GIAC_CONTEXT)12181 gen::gen(const wchar_t * ws,GIAC_CONTEXT){
12182 size_t l=0;
12183 const wchar_t * ptr=ws;
12184 for (;*ptr;++ptr){ ++l; }
12185 char * line=new char[4*l+1];
12186 unicode2utf8(ws,line,int(l));
12187 string ss(line);
12188 delete [] line;
12189 subtype=0;
12190 type=_INT_;
12191 if (ss==string(ss.size(),' ')){
12192 *this=undef;
12193 return;
12194 }
12195 #ifdef HAVE_SSTREAM
12196 ostringstream warnstream;
12197 #endif // HAVE_SSTREAM
12198 #ifndef NSPIRE
12199 my_ostream * oldptr = logptr(contextptr);
12200 #ifdef WITH_MYOSTREAM
12201 my_ostream newptr(&warnstream);
12202 logptr(&newptr,contextptr);
12203 #else
12204 #if !defined HAVE_SSTREAM || defined NSPIRE
12205 logptr(&COUT,contextptr);
12206 #else
12207 #ifndef KHICAS
12208 logptr(&warnstream,contextptr);
12209 #endif
12210 #endif // HAVE_SSTREAM
12211 #endif // WITH_MYIOSTREAM
12212 #endif // NSPIRE
12213 if (protected_giac_yyparse(ss,*this,contextptr)){
12214 if (ss.empty())
12215 ss="""""";
12216 if (ss[0]!='"')
12217 ss = '"'+ss;
12218 if ((ss.size()==1) || (ss[ss.size()-1]!='"'))
12219 ss += '"';
12220 #ifdef SMARTPTR64
12221 * ((ulonglong * ) this) = ulonglong(new ref_string(ss.substr(1,ss.size()-2))) << 16;
12222 subtype=0;
12223 #else
12224 __STRNGptr = new ref_string(ss.substr(1,ss.size()-2));
12225 #endif
12226 type=_STRNG;
12227 }
12228 #ifndef NSPIRE
12229 logptr(oldptr,contextptr);
12230 #endif
12231 #if !defined HAVE_SSTREAM || defined NSPIRE
12232 #else
12233 if (!warnstream.str().empty())
12234 parser_error(warnstream.str(),contextptr);
12235 #endif
12236 }
12237
12238 /* I/O: Print routines */
sprint_int(char * s,int r)12239 int sprint_int(char * s,int r){
12240 char * ptr=s;
12241 if (r<0){
12242 *ptr='-';
12243 ++ptr;
12244 r=-r;
12245 }
12246 int i;
12247 if (r==0){
12248 *ptr='0';
12249 *(ptr+1)=0;
12250 return 1;
12251 }
12252 *(ptr+10)=0;
12253 for (i=9;r;--i){
12254 *(ptr+i)='0'+r%10;
12255 r/=10;
12256 }
12257 ++i;
12258 if (i>0){ // shift left i char
12259 char * buf;
12260 for (buf=ptr+i;buf<=ptr+9;++buf){
12261 *(buf-i)=*buf;
12262 }
12263 *(buf-i)=0;
12264 ptr=buf-i;
12265 }
12266 else
12267 ptr += 10;
12268 return ptr-s;
12269 }
12270
sprint_double(char * s,double d)12271 void sprint_double(char * s,double d){
12272 char * buf=s;
12273 if (d==0){
12274 strcpy(buf,"0.0");
12275 return;
12276 }
12277 if (d<0){
12278 *buf='-';
12279 ++buf;
12280 d=-d;
12281 }
12282 int i=d;
12283 if (i==d && d<1e9){
12284 sprint_int(buf,i);
12285 return;
12286 }
12287 for (i=0;i<280 && d>=1.0;i+=14){
12288 d=d*1e-14;
12289 }
12290 for (;i>-280 && d<1.0;i-=14){
12291 d=d*1e14;
12292 }
12293 for (;i<310 && d>=1.0;++i){
12294 d=d*.1;
12295 }
12296 if (i==310){
12297 strcpy(buf,"inf");
12298 return;
12299 }
12300 for (;i>-310 && d<1.0;--i){
12301 d=d*10;
12302 }
12303 if (i==-310){
12304 strcpy(buf,"0.0");
12305 return;
12306 }
12307 // 1.0<=d<10, d*10^i
12308 d=d/10; ++i; // 0.1<=d<1, d*10^i
12309 *buf='.';
12310 char * ptr=buf;
12311 ++buf;
12312 int r=(int)(d*1e9+.5);
12313 if (r>=1e9){
12314 r=r/10;
12315 ++i;
12316 }
12317 buf += sprint_int(buf,r);
12318 if (i>0 && i<7){
12319 // move . i positions to the right
12320 for (int j=0;j<i;++j){
12321 *ptr=*(ptr+1);
12322 ++ptr;
12323 }
12324 *ptr='.';
12325 i=0;
12326 }
12327 for (;;--buf){
12328 char ch=*(buf-1);
12329 if (ch!='0'){
12330 *buf=0;
12331 break;
12332 }
12333 }
12334 if (i!=0){
12335 if (!os_shell){
12336 *buf='*';
12337 ++buf;
12338 *buf='1';
12339 ++buf;
12340 *buf='0';
12341 ++buf;
12342 *buf='^';
12343 ++buf;
12344 } else {
12345 *buf='e';
12346 ++buf;
12347 }
12348 sprint_int(buf,i);
12349 }
12350 }
12351
print_DOUBLE_(double d,GIAC_CONTEXT)12352 string print_DOUBLE_(double d,GIAC_CONTEXT){
12353 #if defined KHICAS && !defined NSPIRE_NEWLIB
12354 {
12355 char s[256];
12356 sprint_double(s,d);
12357 return s;
12358 }
12359 #endif
12360 if (my_isnan(d))
12361 return calc_mode(contextptr)==1?"?":"undef";
12362 if (my_isinf(d))
12363 return "infinity";
12364 #ifdef BCD
12365 if (bcd_printdouble(contextptr))
12366 return print_FLOAT_(giac_float(d),contextptr);
12367 #endif
12368 #ifndef DOUBLEVAL
12369 // roundoff
12370 unsigned char * u = (unsigned char *)(&d);
12371 *u &= 0xe0;
12372 #endif
12373 if (d<0 && calc_mode(contextptr)==38)
12374 return "−"+print_DOUBLE_(-d,contextptr);
12375 string & forme=format_double(contextptr);
12376 if (!forme.empty()){
12377 char ch=forme[0];
12378 if (tolower(ch)!='g' && tolower(ch)!='a' && tolower(ch)!='f' && tolower(ch)!='e' )
12379 ch='g';
12380 if (calc_mode(contextptr)==1)
12381 ch=toupper(ch);
12382 if (forme.size()<2 || forme.size()>3 || forme[1]<'0' || forme[1]>'9' || (forme.size()==3 && forme[2]<'0' && forme[2]>'9'))
12383 return "invalid format";
12384 if (my_isnan(d))
12385 return "undef";
12386 if (my_isinf(d))
12387 return "infinity";
12388 char s[256];
12389 string f2=string("%.")+forme.substr(1,forme.size()-1)+ch;
12390 sprintfdouble(s,f2.c_str(),d);
12391 return s;
12392 }
12393 if (xcas_mode(contextptr)==3 && double(int(d))==d)
12394 return print_INT_(int(d));
12395 char s[256];
12396 #ifdef SOFTMATH
12397 sprintfdouble(s,"%.14g",d);
12398 return s;
12399 #else
12400 string form("%."+print_INT_(giacmin(decimal_digits(contextptr),14)));
12401 int sf=scientific_format(contextptr);
12402 switch (sf){
12403 case 0: case 2:
12404 if (abs_calc_mode(contextptr)==38)
12405 form += 'G';
12406 else
12407 form += "g";
12408 break;
12409 case 1:
12410 form += "e"; // or "f" ??
12411 break;
12412 case 3:
12413 form += "a";
12414 }
12415 if (calc_mode(contextptr)==1)
12416 form[form.size()-1]=toupper(form[form.size()-1]);
12417 if (sf==2){
12418 // engineering format
12419 int ndigits=int(giac_floor(std::log10(d)+0.5));
12420 ndigits = 3*(ndigits /3);
12421 sprintfdouble(s,form.c_str(),d/std::pow(10.0,ndigits));
12422 return s+("e"+print_INT_(ndigits));
12423 }
12424 sprintfdouble(s,form.c_str(),d);
12425 // 1073741824=2^30, fixme always try with a .0 for large numbers if longfloat not available?
12426 if (sf
12427 #if 1 // def HAVE_LIBMPFR
12428 || d>=1073741824 || d<=-1073741824
12429 #endif
12430 )
12431 return s;
12432 for (int i=0;s[i];++i){
12433 if (s[i]=='.' || s[i]==',' || s[i]=='e' || s[i]=='E')
12434 return s;
12435 }
12436 return string(s)+".0";
12437 #endif
12438 }
12439
maptoarray(const gen_map & m,GIAC_CONTEXT)12440 gen maptoarray(const gen_map & m,GIAC_CONTEXT){
12441 vecteur res;
12442 gen_map::const_iterator it=m.begin(),itend=m.end();
12443 if (it==itend)
12444 return gendimerr(gettext("Empty array"));
12445 gen_map::const_reverse_iterator lastit=m.rbegin();
12446 // find index ranges
12447 gen premidx=it->first,lastidx=lastit->first;
12448 if (premidx.type!=_VECT || lastidx.type!=_VECT)
12449 return gentypeerr(gettext("Bad array indexes"));
12450 vecteur & pv=*premidx._VECTptr;
12451 vecteur & lv=*lastidx._VECTptr;
12452 unsigned ps=unsigned(pv.size());
12453 vector<int> indexes(ps);
12454 if (ps==0)
12455 return res;
12456 if (lv.size()!=ps )
12457 return gendimerr(contextptr);
12458 for (unsigned i=0;i<ps;++i){
12459 res.push_back(symb_interval(pv[i]+array_start(contextptr),lv[i]+array_start(contextptr))); // res.push_back(symb_interval(pv[i]+(xcas_mode(contextptr)!=0),lv[i]+(xcas_mode(contextptr)!=0)));
12460 if (lv[i].type!=_INT_ || pv[i].type!=_INT_ || lv[i].val<pv[i].val)
12461 return gendimerr(contextptr);
12462 indexes[i]=(lv[i]-pv[i]).val+1;
12463 }
12464 if (ps==1){
12465 vecteur tmp;
12466 for (;it!=itend;++it){
12467 tmp.push_back(it->second);
12468 }
12469 res.push_back(tmp);
12470 }
12471 else {
12472 vecteur tmp(indexes[ps-1]);
12473 for (int i=ps-2;i>=0;--i){
12474 vecteur newtmp;
12475 for (int j=0;j<indexes[i];++j)
12476 newtmp.push_back(tmp);
12477 tmp=newtmp;
12478 }
12479 gen tab=tmp;
12480 for (;it!=itend;++it){
12481 gen * tmpptr=&tab;
12482 if (tmpptr->type!=_VECT)
12483 return gendimerr(contextptr);
12484 for (unsigned i=0;i<ps;++i){
12485 int pos=(it->first[i]-pv[i]).val;
12486 if (pos<0 || unsigned(pos)>=tmpptr->_VECTptr->size())
12487 return gendimerr(contextptr);
12488 tmpptr=&((*tmpptr->_VECTptr)[pos]);
12489 }
12490 *tmpptr = it->second;
12491 }
12492 res.push_back(tmp);
12493 }
12494 return new_ref_symbolic(symbolic(at_array,res));
12495 }
12496
printmap(const gen_map & m,GIAC_CONTEXT)12497 static string printmap(const gen_map & m,GIAC_CONTEXT){
12498 string s("table(\n");
12499 gen_map::const_iterator it=m.begin(),itend=m.end();
12500 for (;it!=itend;){
12501 gen bb=it->first;
12502 if (bb.type!=_STRNG && array_start(contextptr)){
12503 if (bb.type==_VECT)
12504 bb=bb+vecteur(bb._VECTptr->size(),plus_one);
12505 else
12506 bb=bb+plus_one;
12507 }
12508 if (bb.type==_VECT && bb.subtype==_SEQ__VECT)
12509 s+='(';
12510 s += bb.print(contextptr);
12511 if (bb.type==_VECT && bb.subtype==_SEQ__VECT)
12512 s+=')';
12513 s += " = " + it->second.print(contextptr);
12514 ++it;
12515 if (it!=itend)
12516 s += ',';
12517 s += '\n';
12518 }
12519 return s+")";
12520 }
12521
printmpf_t(const mpf_t & inf,GIAC_CONTEXT)12522 std::string printmpf_t(const mpf_t & inf,GIAC_CONTEXT){
12523 #ifndef USE_GMP_REPLACEMENTS
12524 #ifdef VISUALC
12525 char * ptr=new char[decimal_digits(contextptr)+30];
12526 #else
12527 char ptr[decimal_digits(contextptr)+30];
12528 #endif
12529 bool negatif=mpf_sgn(inf)<0;
12530 mp_exp_t expo;
12531 if (negatif){
12532 mpf_t inf2;
12533 mpf_init(inf2);
12534 mpf_neg(inf2,inf);
12535 mpf_get_str(ptr,&expo,10,decimal_digits(contextptr),inf2);
12536 mpf_clear(inf2);
12537 }
12538 else
12539 mpf_get_str(ptr,&expo,10,decimal_digits(contextptr),inf);
12540 std::string res(ptr),reste(res.substr(1,res.size()-1));
12541 #ifdef VISUALC
12542 delete [] ptr;
12543 #endif
12544 res=res[0]+("."+reste);
12545 if (expo!=1)
12546 res += "e"+print_INT_(expo-1);
12547 if (negatif)
12548 return "-"+res;
12549 else
12550 return res;
12551 #else // USE_GMP_REPLACEMENTS
12552 #if defined NSPIRE || defined FXCG || defined KHICAS
12553 return "mpf_t not implemented";
12554 #else
12555 std::ostringstream out;
12556 #ifdef LONGFLOAT_DOUBLE
12557 out << std::setprecision(decimal_digits(contextptr)) << inf;
12558 #else
12559 out << std::setprecision(decimal_digits(contextptr)) << *inf;
12560 #endif
12561 return out.str();
12562 #endif // NSPIRE
12563 #endif // USE_GMP_REPLACEMENTS
12564 }
12565
12566
print_ZINT(const mpz_t & a)12567 string print_ZINT(const mpz_t & a){
12568 /*
12569 char * s =mpz_get_str (NULL, 10,a) ;
12570 string res(s);
12571 free(s);
12572 return res;
12573 */
12574 size_t l=mpz_sizeinbase (a, 10) + 2;
12575 if (l>unsigned(MAX_PRINTABLE_ZINT))
12576 return "Integer_too_large_for_display";
12577 #if defined( VISUALC ) || defined( BESTA_OS )
12578 ALLOCA(char, s, l); //s = ( char * )alloca( l );
12579 #else
12580 char s[l];
12581 #endif
12582 mpz_get_str (s, 10,a) ;
12583 string tmp(s);
12584
12585 return tmp;
12586 }
12587
hexa_print_ZINT(const mpz_t & a)12588 string hexa_print_ZINT(const mpz_t & a){
12589 size_t l=mpz_sizeinbase (a, 16) + 2;
12590 if (l>unsigned(MAX_PRINTABLE_ZINT))
12591 return "Integer_too_large";
12592 #if defined( VISUALC ) || defined( BESTA_OS )
12593 ALLOCA(char, s, l);//char * s = ( char * )alloca( l );
12594 #else
12595 char s[l];
12596 #endif
12597 string res("0x");
12598 #ifdef USE_GMP_REPLACEMENTS
12599 if (mpz_sgn(a) == -1){
12600 mpz_t tmpint;
12601 mpz_init(tmpint);
12602 mpz_neg(tmpint, a);
12603 mpz_get_str(s,16,tmpint);
12604 mpz_clear(tmpint);
12605
12606 res = "-" + res + s;
12607 }
12608 else {
12609 mpz_get_str(s,16,a);
12610 res += s;
12611 }
12612 #else
12613 mpz_get_str (s,16,a) ;
12614 res += s;
12615 #endif // USE_GMP_REPLACEMENTS
12616
12617 return res;
12618 }
12619
octal_print_ZINT(const mpz_t & a)12620 string octal_print_ZINT(const mpz_t & a){
12621 size_t l=mpz_sizeinbase (a, 8) + 2;
12622 if (l>unsigned(MAX_PRINTABLE_ZINT))
12623 return "Integer_too_large";
12624 #if defined( VISUALC ) || defined( BESTA_OS )
12625 ALLOCA(char, s, l);//char * s = ( char * )alloca( l );
12626 #else
12627 char s[l];
12628 #endif
12629 string res("0");
12630 #ifdef USE_GMP_REPLACEMENTS
12631 if (mpz_sgn(a) == -1){
12632 mpz_t tmpint;
12633 mpz_init(tmpint);
12634 mpz_neg(tmpint, a);
12635 mpz_get_str(s,8,tmpint);
12636 mpz_clear(tmpint);
12637 res = "-" + res + s;
12638 }
12639 else {
12640 mpz_get_str(s,8,a);
12641 res += s;
12642 }
12643 #else
12644 mpz_get_str (s,8,a) ;
12645 res += s;
12646 #endif // USE_GMP_REPLACEMENTS
12647
12648 return res;
12649 }
12650
binary_print_ZINT(const mpz_t & a)12651 string binary_print_ZINT(const mpz_t & a){
12652 size_t l=mpz_sizeinbase (a, 2) + 2;
12653 if (l>unsigned(MAX_PRINTABLE_ZINT))
12654 return "Integer_too_large";
12655 #if defined( VISUALC ) || defined( BESTA_OS )
12656 ALLOCA(char, s, l);//char * s = ( char * )alloca( l );
12657 #else
12658 char s[l];
12659 #endif
12660 string res("0b");
12661 #ifdef USE_GMP_REPLACEMENTS
12662 if (mpz_sgn(a) == -1){
12663 mpz_t tmpint;
12664 mpz_init(tmpint);
12665 mpz_neg(tmpint, a);
12666 mpz_get_str(s,2,tmpint);
12667 mpz_clear(tmpint);
12668 res = "-" + res + s;
12669 }
12670 else {
12671 mpz_get_str(s,2,a);
12672 res += s;
12673 }
12674 #else
12675 mpz_get_str (s,2,a) ;
12676 res += s;
12677 #endif // USE_GMP_REPLACEMENTS
12678
12679 return res;
12680 }
12681
printinner_VECT(const vecteur & v,int subtype,GIAC_CONTEXT)12682 string printinner_VECT(const vecteur & v, int subtype,GIAC_CONTEXT){
12683 string s;
12684 return add_printinner_VECT(s,v,subtype,contextptr);
12685 }
12686
add_printinner_VECT(string & s,const vecteur & v,int subtype,GIAC_CONTEXT)12687 string & add_printinner_VECT(string & s,const vecteur &v,int subtype,GIAC_CONTEXT){
12688 vecteur::const_iterator it=v.begin(), itend=v.end();
12689 if (it==itend)
12690 return s;
12691 for(;;){
12692 if ( (subtype==_RPN_FUNC__VECT) && (it->type==_SYMB) && (it->_SYMBptr->sommet==at_quote))
12693 s += "'"+it->_SYMBptr->feuille.print(contextptr)+"'";
12694 else {
12695 if ( (it->type==_SYMB && it->_SYMBptr->sommet==at_sto)
12696 // || (it->type==_VECT && it->subtype==_SEQ__VECT && it->_VECTptr->size()>=2)
12697 )
12698 s += "("+it->print(contextptr)+")";
12699 else
12700 add_print(s,*it,contextptr); // s += it->print(contextptr);
12701 }
12702 ++it;
12703 if (it==itend){
12704 return s;
12705 }
12706 if ( (subtype!=_RPN_FUNC__VECT) &&
12707 // (subtype || (!rpn_mode(contextptr)) ) &&
12708 ( ((it-1)->type!=_SYMB) || ((it-1)->_SYMBptr->sommet!=at_comment) )
12709 )
12710 s += ',';
12711 else
12712 s += ' ';
12713 }
12714 }
12715
begin_VECT_string(int subtype,bool tex,GIAC_CONTEXT)12716 string begin_VECT_string(int subtype,bool tex,GIAC_CONTEXT){
12717 string s;
12718 switch (subtype){
12719 case _SEQ__VECT:
12720 break;
12721 case _SET__VECT:
12722 if (xcas_mode(contextptr)>0 || calc_mode(contextptr)==1){
12723 if (tex)
12724 s+="\\{";
12725 else
12726 s="{";
12727 }
12728 else
12729 s="set[";
12730 break;
12731 case _RPN_STACK__VECT:
12732 s="stack(";
12733 break;
12734 case _RPN_FUNC__VECT:
12735 s="<< ";
12736 break;
12737 case _GROUP__VECT:
12738 s="group[";
12739 break;
12740 #ifdef HAVE_LIBMPFI
12741 case _INTERVAL__VECT:
12742 s="i[";
12743 break;
12744 #endif
12745 case _LINE__VECT:
12746 s="line[";
12747 break;
12748 case _VECTOR__VECT:
12749 s="vector[";
12750 break;
12751 case _GGBVECT:
12752 s=(calc_mode(contextptr)==1?"ggbvect(":"ggbvect[");
12753 break;
12754 #ifndef EMCC
12755 case _LOGO__VECT:
12756 s="logo[";
12757 break;
12758 #endif
12759 case _PNT__VECT:
12760 s="pnt[";
12761 break;
12762 case _POINT__VECT:
12763 s="point[";
12764 break;
12765 case _TUPLE__VECT:
12766 s="tuple[";
12767 break;
12768 case _MATRIX__VECT:
12769 if (calc_mode(contextptr)==1)
12770 s="{";
12771 else {
12772 // s="matrix[";
12773 if (!os_shell)
12774 s="[";
12775 else
12776 s=abs_calc_mode(contextptr)==38?"[":"matrix[";
12777 }
12778 break;
12779 case _POLY1__VECT:
12780 if (!os_shell)
12781 s="[";
12782 else
12783 s="poly1[";
12784 break;
12785 case _ASSUME__VECT:
12786 s = "assume[";
12787 break;
12788 case _FOLDER__VECT:
12789 s = "folder[";
12790 break;
12791 case _POLYEDRE__VECT:
12792 s= "polyedre[";
12793 break;
12794 case _RGBA__VECT:
12795 s= "rgba[";
12796 break;
12797 case _LIST__VECT:
12798 if (!os_shell)
12799 s="[";
12800 else {
12801 if (tex)
12802 s="\\{";
12803 else
12804 s=abs_calc_mode(contextptr)==38?"{":"list[";
12805 }
12806 break;
12807 case _GGB__VECT:
12808 if (calc_mode(contextptr)==1)
12809 s="("; // warning: can not be reparsed from giac
12810 else
12811 s="ggbpnt[";
12812 break;
12813 case _TABLE__VECT:
12814 s="{/";
12815 break;
12816 default:
12817 s=calc_mode(contextptr)==1?"{":"[";
12818 }
12819 return s;
12820 }
12821
end_VECT_string(int subtype,bool tex,GIAC_CONTEXT)12822 string end_VECT_string(int subtype,bool tex,GIAC_CONTEXT){
12823 string s;
12824 switch (subtype){
12825 case _SEQ__VECT:
12826 return s;
12827 case _SET__VECT:
12828 if (xcas_mode(contextptr)>0 || calc_mode(contextptr)==1){
12829 if (tex)
12830 return "\\}";
12831 else
12832 return "}";
12833 }
12834 else
12835 return "]";
12836 case _RPN_STACK__VECT:
12837 return ")";
12838 case _RPN_FUNC__VECT:
12839 return " >>";
12840 case _LIST__VECT:
12841 if (tex)
12842 return "\\}";
12843 else
12844 return abs_calc_mode(contextptr)==38?"}":"]";
12845 case _GGB__VECT:
12846 if (calc_mode(contextptr)==1)
12847 return ")";
12848 else
12849 return "]";
12850 case _POINT__VECT: case _VECTOR__VECT: case _POLY1__VECT: case _PNT__VECT:
12851 return "]";
12852 case _GGBVECT:
12853 return calc_mode(contextptr)==1?")":"]";
12854 case 0: case _MATRIX__VECT:
12855 return calc_mode(contextptr)==1?"}":"]";
12856 case _TABLE__VECT:
12857 return "/}";
12858 default:
12859 return calc_mode(contextptr)==1?"}":"]";
12860 }
12861 }
12862
svg2doutput(const gen & g,string & S,GIAC_CONTEXT)12863 const char * svg2doutput(const gen & g,string & S,GIAC_CONTEXT){
12864 #ifdef EMCC
12865 bool fullview=true;
12866 vector<double> vx,vy,vz;
12867 double window_xmin,window_xmax,window_ymin,window_ymax,window_zmin,window_zmax;
12868 bool ortho=autoscaleg(g,vx,vy,vz,contextptr);
12869 autoscaleminmax(vx,window_xmin,window_xmax,fullview);
12870 autoscaleminmax(vy,window_ymin,window_ymax,fullview);
12871 double xscale=window_xmax-window_xmin,yscale=window_ymax-window_ymin;
12872 double ratio=yscale/xscale;
12873 double gratio=0.6,gwidth=9;
12874 #ifndef GIAC_GGB
12875 gwidth=EM_ASM_DOUBLE_V({
12876 var hw=window.innerWidth;
12877 if (hw>=1000)
12878 return 9.0*hw/1000.0;
12879 else
12880 return hw/60.0;
12881 });
12882 #endif // GIAC_GGB
12883 //CERR << gwidth << '\n';
12884 int maxgratio=ortho?10:3;
12885 if (ratio<gratio/maxgratio || ratio>maxgratio*gratio) ortho=false; else ortho=true;
12886 if (ortho){
12887 if (ratio>gratio){ // yscale>gratio*xscale, use yscale for x
12888 double xc=(window_xmax+window_xmin)/2;
12889 window_xmin=xc-yscale/(2*gratio);
12890 window_xmax=xc+yscale/(2*gratio);
12891 }
12892 else { // xscale>yscale/gratio
12893 double yc=(window_ymax+window_ymin)/2;
12894 window_ymin=yc-gratio*xscale/2;
12895 window_ymax=yc+gratio*xscale/2;
12896 }
12897 ratio=gratio;
12898 ortho=false;
12899 }
12900 bool axes=overwrite_viewbox(g,window_xmin,window_xmax,window_ymin,window_ymax,window_zmin,window_zmax);
12901 xscale=window_xmax-window_xmin;yscale=window_ymax-window_ymin;
12902 ratio=yscale/xscale;
12903 //COUT << window_xmin << " " << window_xmax << " " << window_ymin << " " << window_ymax << '\n';
12904 //g=_symetrie(makesequence(_droite(makesequence(0,1),contextptr),g),contextptr);
12905 //S='"'+svg_preamble(7,7,gnuplot_xmin,gnuplot_xmax,gnuplot_ymin,gnuplot_ymax,ortho,false)+gen2svg(g,contextptr)+svg_grid(gnuplot_xmin,gnuplot_xmax,gnuplot_ymin,gnuplot_ymax)+"</svg>\"";
12906 S='"'+svg_preamble_pixel(g,gwidth,gwidth*gratio,window_xmin,window_xmax,window_ymin,window_ymax,ortho,false);
12907 plot_attr P;
12908 title_legende(g,P);
12909 S= S+(gen2svg(g,window_xmin,window_xmax,window_ymin,window_ymax,ratio/gratio,contextptr,false)+(axes?svg_grid(window_xmin,window_xmax,window_ymin,window_ymax,P)+"</svg>\"":""));
12910 #endif
12911 return S.c_str();
12912 }
12913
print_VECT(const vecteur & v,int subtype,GIAC_CONTEXT)12914 string print_VECT(const vecteur & v,int subtype,GIAC_CONTEXT){
12915 if (v.empty()){
12916 switch (subtype){
12917 case _SEQ__VECT:
12918 return xcas_mode(contextptr)==1?"NULL":"seq[]";
12919 case _SET__VECT:
12920 if (xcas_mode(contextptr)>0 || calc_mode(contextptr)==1)
12921 return "{ }";
12922 else
12923 return "set[ ]";
12924 case _RPN_FUNC__VECT:
12925 return "<< >>";
12926 case _RPN_STACK__VECT:
12927 return "stack()";
12928 }
12929 }
12930 #if 1 // for debugging/profiling pixon_print
12931 if (!v.empty() && is_pnt_or_pixon(v.back())){
12932 gen f=v.back();
12933 if (f.is_symb_of_sommet(at_pnt)){
12934 f=f._SYMBptr->feuille;
12935 if (f.type==_VECT)
12936 f=f._VECTptr->front();
12937 }
12938 if (f.is_symb_of_sommet(at_pixon)){
12939 string S;
12940 pixon_print(v,S,contextptr);
12941 return S;
12942 }
12943 }
12944 #endif
12945 string s;
12946 if (subtype==_SPREAD__VECT && !v.empty() && v.front().type==_VECT){
12947 #ifdef EMCC
12948 bool add_quotes=true;
12949 s = "[";
12950 #else
12951 bool add_quotes=false;
12952 s = "spreadsheet[";
12953 #endif
12954 int nr=int(v.size());
12955 int nc=int(v.front()._VECTptr->size());
12956 for (int i=0;;){
12957 int save_r,save_c;
12958 vecteur & w=*v[i]._VECTptr;
12959 s +='[';
12960 for (int j=0;;){
12961 save_r=printcell_current_row(contextptr);
12962 save_c=printcell_current_col(contextptr);
12963 printcell_current_row(contextptr)=i;
12964 printcell_current_col(contextptr)=j;
12965 if (add_quotes){
12966 gen tmp=w[j];
12967 if (tmp.type==_VECT && tmp._VECTptr->size()>=2){
12968 vecteur & w=*tmp._VECTptr;
12969 s += "['"+w[0].print(contextptr)+"',";
12970 s += "'"+w[1].print(contextptr)+"',";
12971 // COUT << i << " " << j << " " << w[1] << '\n';
12972 if (w[1].type==_STRNG && *w[1]._STRNGptr=="")
12973 s += "' ']";
12974 else {
12975 string ms;
12976 if (w[1].is_symb_of_sommet(at_pnt)){
12977 svg2doutput(w[1],ms,contextptr); // remove quotes
12978 if (ms[0]=='"' && ms[ms.size()-1]=='"')
12979 ms=ms.substr(1,ms.size()-2);
12980 }
12981 #ifndef GIAC_HAS_STO_38
12982 else
12983 ms=*_mathml(makesequence(w[1],1),contextptr)._STRNGptr;
12984 #endif
12985 string res;
12986 int l=ms.size();
12987 res.reserve(l);
12988 const char * ch=ms.c_str();
12989 for (int i=0;i<l;++i,++ch){
12990 res+= (*ch=='\n'? ' ': *ch);
12991 }
12992 s += "' "+res+" ']";
12993 }
12994 }
12995 else
12996 s += w[j].print(contextptr);
12997 }
12998 else
12999 s += w[j].print(contextptr);
13000 printcell_current_row(contextptr)=save_r;
13001 printcell_current_col(contextptr)=save_c;
13002 ++j;
13003 if (j==nc)
13004 break;
13005 else
13006 s+=',';
13007 }
13008 s+=']';
13009 ++i;
13010 if (i==nr)
13011 break;
13012 else
13013 s+=',';
13014 }
13015 return s+']';
13016 }
13017 if ( ( subtype==_SEQ__VECT) && (v.size()==1) && !xcas_mode(contextptr))
13018 return "seq["+v.front().print(contextptr)+"]";
13019 else
13020 s=begin_VECT_string(subtype,false,contextptr);
13021 s += printinner_VECT(v,subtype,contextptr);
13022 return s+end_VECT_string(subtype,false,contextptr);
13023 }
13024
print_SPOL1(const sparse_poly1 & p,GIAC_CONTEXT)13025 string print_SPOL1(const sparse_poly1 & p,GIAC_CONTEXT){
13026 if (p.empty())
13027 return "0";
13028 int sf=series_flags(contextptr);
13029 if (sf & (1<<5) && !(sf & (1<<4))){
13030 identificateur tt(string(1,series_variable_name(contextptr)));
13031 gen remains,g=sparse_poly12gen(p,tt,remains,!(sf & (1<<6)));
13032 if ( (sf & (1<<6)) && !is_zero(remains))
13033 g += symb_of(gen(abs_calc_mode(contextptr)==38?"b":"O",contextptr),remains);
13034 return g.print(contextptr);
13035 }
13036 string s;
13037 sparse_poly1::const_iterator it=p.begin(), itend=p.end();
13038 bool paren=itend-it>1;
13039 if (paren) s+='(';
13040 for(;;){
13041 s += it->print(contextptr);
13042 ++it;
13043 if (it==itend){
13044 if (paren)
13045 return s+')';
13046 return s;
13047 }
13048 s += '+';
13049 }
13050 }
13051
print_the_type(int val,GIAC_CONTEXT)13052 string print_the_type(int val,GIAC_CONTEXT){
13053 if (xcas_mode(contextptr)==1){
13054 switch(val){
13055 case _INT_:
13056 return "integer";
13057 case _DOUBLE_:
13058 return "double";
13059 case _FLOAT_:
13060 return "float";
13061 case _ZINT:
13062 return "integer";
13063 case _CPLX:
13064 return "complex";
13065 case _VECT:
13066 return "vector";
13067 case _IDNT:
13068 return "symbol";
13069 case _SYMB:
13070 return "algebraic";
13071 case _FRAC:
13072 return "rational";
13073 case _MAPLE_LIST:
13074 return "list";
13075 }
13076 }
13077 if (abs_calc_mode(contextptr)!=38){
13078 switch(val){
13079 case _DOUBLE_:
13080 return "real";
13081 case _ZINT:
13082 return "integer";
13083 case _CPLX:
13084 return "complex";
13085 case _VECT:
13086 return "vector";
13087 case _IDNT:
13088 return "identifier";
13089 case _SYMB:
13090 return "expression";
13091 case _FRAC:
13092 return "rational";
13093 case _STRNG:
13094 return "string";
13095 case _FUNC:
13096 return "func";
13097 }
13098 }
13099 switch(val){
13100 case _INT_:
13101 return "DOM_int";
13102 case _DOUBLE_:
13103 return "DOM_FLOAT";
13104 case _FLOAT_:
13105 return "DOM_SPECIALFLOAT";
13106 case _ZINT:
13107 return "DOM_INT";
13108 case _CPLX:
13109 return "DOM_COMPLEX";
13110 case _VECT:
13111 return "DOM_LIST";
13112 case _IDNT:
13113 return "DOM_IDENT";
13114 case _SYMB:
13115 return "DOM_SYMBOLIC";
13116 case _FRAC:
13117 return "DOM_RAT";
13118 case _STRNG:
13119 return "DOM_STRING";
13120 case _FUNC:
13121 return "DOM_FUNC";
13122 case _REAL:
13123 return "DOM_LONGFLOAT";
13124 case _MAP:
13125 return "DOM_MAP";
13126 case _SPOL1:
13127 return "DOM_SERIES";
13128 }
13129 return print_INT_(val);
13130 }
13131
print_STRNG(const string & s)13132 string print_STRNG(const string & s){
13133 string res("\"");
13134 int l=int(s.size());
13135 for (int i=0;i<l;++i){
13136 res += s[i];
13137 if (s[i]=='"')
13138 res += '"';
13139 }
13140 return res+'"';
13141 }
13142
printi(GIAC_CONTEXT)13143 const char * printi(GIAC_CONTEXT){
13144 #ifdef KHICAS
13145 return os_shell?"i":"";
13146 #endif
13147 if (calc_mode(contextptr)==1)
13148 return "ί";
13149 if (abs_calc_mode(contextptr)==38)
13150 return ""; // "\xe2\x81\xb1";
13151 if (xcas_mode(contextptr)==3)
13152 return "\xa1";
13153 if (xcas_mode(contextptr)>0)
13154 return "I";
13155 else
13156 return "i";
13157 }
13158
print_EQW(const eqwdata & e)13159 static string print_EQW(const eqwdata & e){
13160 string s;
13161 s += "eqwdata(position"+print_INT_(e.x)+","+print_INT_(e.y)+",dxdy,"+print_INT_(e.dx)+","+print_INT_(e.dy);
13162 s += ",font,"+print_INT_(e.eqw_attributs.fontsize);
13163 s += ",background," +print_INT_(e.eqw_attributs.background);
13164 s += ",text_color," +print_INT_(e.eqw_attributs.text_color)+",";
13165 if (e.selected)
13166 s +="selected,";
13167 if (e.active)
13168 s +="active,";
13169 s += e.g.print(context0)+")";
13170 return s;
13171 }
13172
print() const13173 string gen::print() const{
13174 return print(context0);
13175 }
13176
13177 // FIXME!!!
sprint(std::string * sptr,GIAC_CONTEXT) const13178 int gen::sprint(std::string * sptr,GIAC_CONTEXT) const{
13179 return 0;
13180 }
13181
print_universal(GIAC_CONTEXT) const13182 string gen::print_universal(GIAC_CONTEXT) const{
13183 int lang=language(contextptr);
13184 language(-1,contextptr);
13185 string res;
13186 #ifdef NO_STDEXCEPT
13187 res=print(contextptr);
13188 #else
13189 try {
13190 res=print(contextptr);
13191 }
13192 catch (...){ }
13193 #endif
13194 language(lang,contextptr);
13195 return res;
13196 }
13197
wprint(GIAC_CONTEXT) const13198 wchar_t * gen::wprint(GIAC_CONTEXT) const {
13199 string s=print(contextptr);
13200 unsigned int ss=unsigned(s.size());
13201 wchar_t * ptr = (wchar_t *) malloc(sizeof(wchar_t)*(ss+1));
13202 /*
13203 unsigned int l=utf82unicode(s.c_str(),ptr,ss);
13204 if (l<ss){ // realloc
13205 wchar_t * newptr=(wchar_t *)malloc(sizeof(wchar_t)*(l+1));
13206 wstrcpy(newptr,ptr);
13207 free(ptr);
13208 ptr=newptr;
13209 }
13210 */
13211 return ptr;
13212 }
13213
printint32(int val,int subtype,GIAC_CONTEXT)13214 string printint32(int val,int subtype,GIAC_CONTEXT){
13215 if (subtype==_INT_TYPE)
13216 return print_the_type(val,contextptr);
13217
13218 if (subtype==_INT_SOLVER){
13219 switch (val){
13220 case _UNFACTORED:
13221 return "unfactored";
13222 case _BISECTION_SOLVER:
13223 return "bisection_solver";
13224 case _FALSEPOS_SOLVER:
13225 return "falsepos_solver";
13226 case _BRENT_SOLVER:
13227 return "brent_solver";
13228 case _NEWTON_SOLVER:
13229 return "newton_solver";
13230 case _DNEWTON_SOLVER:
13231 return "dnewton_solver";
13232 case _NEWTONJ_SOLVER:
13233 return "newtonj_solver";
13234 case _SECANT_SOLVER:
13235 return "secant_solver";
13236 case _STEFFENSON_SOLVER:
13237 return "steffenson_solver";
13238 case _HYBRIDSJ_SOLVER:
13239 return "hybridsj_solver";
13240 case _HYBRIDJ_SOLVER:
13241 return "hybridj_solver";
13242 case _HYBRIDS_SOLVER:
13243 return "hybrids_solver";
13244 case _HYBRID_SOLVER:
13245 return "hybrid_solver";
13246 case _GOLUB_REINSCH_DECOMP:
13247 return "golub_reinsch_decomp";
13248 case _GOLUB_REINSCH_MOD_DECOMP:
13249 return "golub_reinsch_mode_decomp";
13250 case _JACOBI_DECOMP:
13251 return "jacobi_decomp";
13252 case _MINOR_DET:
13253 return "minor_det";
13254 case _HESSENBERG_PCAR:
13255 return "hessenberg_pcar";
13256 case _RATIONAL_DET:
13257 return "rational_det";
13258 case _KEEP_PIVOT:
13259 return "keep_pivot";
13260 case _FADEEV:
13261 return "fadeev";
13262 case _BAREISS:
13263 return "bareiss";
13264 case _RECTANGLE_GAUCHE:
13265 return "left_rectangle";
13266 case _RECTANGLE_DROIT:
13267 return "right_rectangle";
13268 case _POINT_MILIEU:
13269 return "middle_point";
13270 case _TRAPEZE:
13271 return "trapezoid";
13272 case _SIMPSON:
13273 return "simpson";
13274 case _ROMBERGT:
13275 return "rombergt";
13276 case _ROMBERGM:
13277 return "rombergm";
13278 case _GAUSS15:
13279 return "gauss15";
13280 default:
13281 return print_INT_(val);
13282 }
13283 }
13284 if (subtype==_INT_BOOLEAN){
13285 if (python_compat(contextptr)){
13286 if (val)
13287 return "True";
13288 else
13289 return "False";
13290 }
13291 if (xcas_mode(contextptr)==2){
13292 if (val)
13293 return "TRUE";
13294 else
13295 return "FALSE";
13296 }
13297 else {
13298 if (val)
13299 return "true";
13300 else
13301 return "false";
13302 }
13303 }
13304 if (subtype==_INT_COLOR){
13305 switch (language(contextptr)){
13306 case 1:
13307 switch (val){
13308 case _BLACK:
13309 return "noir";
13310 case _RED:
13311 return "rouge";
13312 case _GREEN:
13313 return "vert";
13314 case _YELLOW:
13315 return "jaune";
13316 case _BLUE:
13317 return "bleu";
13318 case _MAGENTA:
13319 return "magenta";
13320 case _CYAN:
13321 return "cyan";
13322 case _WHITE:
13323 return "blanc";
13324 case _FILL_POLYGON:
13325 return "rempli";
13326 case _QUADRANT2:
13327 return "quadrant2";
13328 case _QUADRANT3:
13329 return "quadrant3";
13330 case _QUADRANT4:
13331 return "quadrant4";
13332 case _POINT_LOSANGE:
13333 return "point_losange";
13334 case _POINT_CARRE:
13335 return "point_carre";
13336 case _POINT_PLUS:
13337 return "point_plus";
13338 case _POINT_TRIANGLE:
13339 return "point_triangle";
13340 case _POINT_ETOILE:
13341 return "point_etoile";
13342 case _POINT_POINT:
13343 return "point_point";
13344 case _POINT_INVISIBLE:
13345 return "point_invisible";
13346 case 49:
13347 return "gomme";
13348 case _LINE_WIDTH_2:
13349 return "epaisseur_ligne_2";
13350 case _LINE_WIDTH_3:
13351 return "epaisseur_ligne_3";
13352 case _LINE_WIDTH_4:
13353 return "epaisseur_ligne_4";
13354 case _LINE_WIDTH_5:
13355 return "epaisseur_ligne_5";
13356 case _LINE_WIDTH_6:
13357 return "epaisseur_ligne_6";
13358 case _LINE_WIDTH_7:
13359 return "epaisseur_ligne_7";
13360 case _LINE_WIDTH_8:
13361 return "epaisseur_ligne_8";
13362 case _POINT_WIDTH_2:
13363 return "epaisseur_point_2";
13364 case _POINT_WIDTH_3:
13365 return "epaisseur_point_3";
13366 case _POINT_WIDTH_4:
13367 return "epaisseur_point_4";
13368 case _POINT_WIDTH_5:
13369 return "epaisseur_point_5";
13370 case _POINT_WIDTH_6:
13371 return "epaisseur_point_6";
13372 case _POINT_WIDTH_7:
13373 return "epaisseur_point_7";
13374 case _POINT_WIDTH_8:
13375 return "epaisseur_point_8";
13376 case _HIDDEN_NAME:
13377 return "nom_cache";
13378 case _DASH_LINE:
13379 return "ligne_tiret";
13380 case _DOT_LINE:
13381 return "ligne_point";
13382 case _DASHDOT_LINE:
13383 return "ligne_tiret_point";
13384 case _DASHDOTDOT_LINE:
13385 return "ligne_tiret_pointpoint";
13386 case _CAP_FLAT_LINE:
13387 return "ligne_chapeau_plat";
13388 case _CAP_ROUND_LINE:
13389 return "ligne_chapeau_rond";
13390 case _CAP_SQUARE_LINE:
13391 return "ligne_chapeau_carre";
13392 }
13393 break;
13394 case 4:
13395 switch (val){
13396 case _BLACK:
13397 return "black";
13398 case _RED:
13399 return "red";
13400 case _GREEN:
13401 return "green";
13402 case _YELLOW:
13403 return "yellow";
13404 case _BLUE:
13405 return "blue";
13406 case _MAGENTA:
13407 return "magenta";
13408 case _CYAN:
13409 return "cyan";
13410 case _WHITE:
13411 return "white";
13412 case _FILL_POLYGON:
13413 return "filled";
13414 case _QUADRANT2:
13415 return "quadrant2";
13416 case _QUADRANT3:
13417 return "quadrant3";
13418 case _QUADRANT4:
13419 return "quadrant4";
13420 case _POINT_LOSANGE:
13421 return "ρομβοειδές_σημείο";
13422 case _POINT_CARRE:
13423 return "τετραγωνικό_σημείο";
13424 case _POINT_PLUS:
13425 return "σταυροειδές_σημείο";
13426 case _POINT_TRIANGLE:
13427 return "τριγωνικό_σημείο";
13428 case _POINT_ETOILE:
13429 return "αστροειδές_σημείο";
13430 case _POINT_POINT:
13431 return "point_point";
13432 case _POINT_INVISIBLE:
13433 return "αόρατο_σημείο";
13434 case 49:
13435 return "gomme";
13436 case _LINE_WIDTH_2:
13437 return "εύρος_γραμμής_2";
13438 case _LINE_WIDTH_3:
13439 return "εύρος_γραμμής_3";
13440 case _LINE_WIDTH_4:
13441 return "εύρος_γραμμής_4";
13442 case _LINE_WIDTH_5:
13443 return "εύρος_γραμμής_5";
13444 case _LINE_WIDTH_6:
13445 return "εύρος_γραμμής_6";
13446 case _LINE_WIDTH_7:
13447 return "εύρος_γραμμής_7";
13448 case _LINE_WIDTH_8:
13449 return "εύρος_γραμμής_8";
13450 case _POINT_WIDTH_2:
13451 return "εύρος_σημείου_2";
13452 case _POINT_WIDTH_3:
13453 return "εύρος_σημείου_3";
13454 case _POINT_WIDTH_4:
13455 return "εύρος_σημείου_4";
13456 case _POINT_WIDTH_5:
13457 return "εύρος_σημείου_5";
13458 case _POINT_WIDTH_6:
13459 return "εύρος_σημείου_6";
13460 case _POINT_WIDTH_7:
13461 return "εύρος_σημείου_7";
13462 case _POINT_WIDTH_8:
13463 return "εύρος_σημείου_8";
13464 case _HIDDEN_NAME:
13465 return "hidden_name";
13466 case _DASH_LINE:
13467 return "γραμμή_διακεκομμένη";
13468 case _DOT_LINE:
13469 return "παύλα_τελεία";
13470 case _DASHDOT_LINE:
13471 return "γραμμή_παύλα_τελεία";
13472 case _DASHDOTDOT_LINE:
13473 return "γραμμή_παύλα_τελείατελεία";
13474 case _CAP_FLAT_LINE:
13475 return "γραμμή_επίπεδο_καβούκι";
13476 case _CAP_ROUND_LINE:
13477 return "γραμμή_στρογγυλό_καβούκι";
13478 case _CAP_SQUARE_LINE:
13479 return "γραμμή_τετράγωνο_καβούκι";
13480 }
13481 default:
13482 switch (val){
13483 case _BLACK:
13484 return "black";
13485 case _RED:
13486 return "red";
13487 case _GREEN:
13488 return "green";
13489 case _YELLOW:
13490 return "yellow";
13491 case _BLUE:
13492 return "blue";
13493 case _MAGENTA:
13494 return "magenta";
13495 case _CYAN:
13496 return "cyan";
13497 case _WHITE:
13498 return "white";
13499 case _FILL_POLYGON:
13500 return "filled";
13501 case _QUADRANT2:
13502 return "quadrant2";
13503 case _QUADRANT3:
13504 return "quadrant3";
13505 case _QUADRANT4:
13506 return "quadrant4";
13507 case _POINT_LOSANGE:
13508 return "rhombus_point";
13509 case _POINT_CARRE:
13510 return "square_point";
13511 case _POINT_PLUS:
13512 return "plus_point";
13513 case _POINT_TRIANGLE:
13514 return "triangle_point";
13515 case _POINT_ETOILE:
13516 return "star_point";
13517 case _POINT_POINT:
13518 return "point_point";
13519 case _POINT_INVISIBLE:
13520 return "invisible_point";
13521 case 49:
13522 return "gomme";
13523 case _LINE_WIDTH_2:
13524 return "line_width_2";
13525 case _LINE_WIDTH_3:
13526 return "line_width_3";
13527 case _LINE_WIDTH_4:
13528 return "line_width_4";
13529 case _LINE_WIDTH_5:
13530 return "line_width_5";
13531 case _LINE_WIDTH_6:
13532 return "line_width_6";
13533 case _LINE_WIDTH_7:
13534 return "line_width_7";
13535 case _LINE_WIDTH_8:
13536 return "line_width_8";
13537 case _POINT_WIDTH_2:
13538 return "point_width_2";
13539 case _POINT_WIDTH_3:
13540 return "point_width_3";
13541 case _POINT_WIDTH_4:
13542 return "point_width_4";
13543 case _POINT_WIDTH_5:
13544 return "point_width_5";
13545 case _POINT_WIDTH_6:
13546 return "point_width_6";
13547 case _POINT_WIDTH_7:
13548 return "point_width_7";
13549 case _POINT_WIDTH_8:
13550 return "point_width_8";
13551 case _HIDDEN_NAME:
13552 return "hidden_name";
13553 case _DASH_LINE:
13554 return "dash_line";
13555 case _DOT_LINE:
13556 return "dot_line";
13557 case _DASHDOT_LINE:
13558 return "dashdot_line";
13559 case _DASHDOTDOT_LINE:
13560 return "dashdotdot_line";
13561 case _CAP_FLAT_LINE:
13562 return "cap_flat_line";
13563 case _CAP_ROUND_LINE:
13564 return "cap_round_line";
13565 case _CAP_SQUARE_LINE:
13566 return "cap_square_line";
13567 }
13568 }
13569 // switch (val){ }
13570 }
13571 if (subtype==_INT_PLOT){
13572 switch(val){
13573 case _ADAPTIVE:
13574 return "adaptive";
13575 case _AXES:
13576 return "axes";
13577 case _COLOR:
13578 return "color";
13579 case _FILLED:
13580 return "filled";
13581 case _FONT:
13582 return "font";
13583 case _LABELS:
13584 return "labels";
13585 case _LEGEND:
13586 return "legend";
13587 case _LINESTYLE:
13588 return "linestyle";
13589 case _RESOLUTION:
13590 return "resolution";
13591 case _SAMPLE:
13592 return "sample";
13593 case _SCALING:
13594 return "scaling";
13595 case _STYLE:
13596 return "style";
13597 case _SYMBOL:
13598 return "symbol";
13599 case _SYMBOLSIZE:
13600 return "symbolsize";
13601 case _THICKNESS:
13602 return "thickness";
13603 case _TITLE:
13604 return "title";
13605 case _TITLEFONT:
13606 return "titlefont";
13607 case _VIEW:
13608 return "view";
13609 case _AXESFONT:
13610 return "axesfont";
13611 case _COORDS:
13612 return "coords";
13613 case _LABELFONT:
13614 return "labelfont";
13615 case _LABELDIRECTIONS:
13616 return "labeldirections";
13617 case _NUMPOINTS:
13618 return "numpoints";
13619 case _TICKMARKS:
13620 return "tickmarks";
13621 case _XTICKMARKS:
13622 return "xtickmarks";
13623 case _NSTEP:
13624 return "nstep";
13625 case _XSTEP:
13626 return "xstep";
13627 case _YSTEP:
13628 return "ystep";
13629 case _ZSTEP:
13630 return "zstep";
13631 case _TSTEP:
13632 return "tstep";
13633 case _USTEP:
13634 return "ustep";
13635 case _VSTEP:
13636 return "vstep";
13637 case _FRAMES:
13638 return "frames";
13639 case _GL_TEXTURE:
13640 return "gl_texture";
13641 case _GL_LIGHT0:
13642 return "gl_light0";
13643 case _GL_LIGHT1:
13644 return "gl_light1";
13645 case _GL_LIGHT2:
13646 return "gl_light2";
13647 case _GL_LIGHT3:
13648 return "gl_light3";
13649 case _GL_LIGHT4:
13650 return "gl_light4";
13651 case _GL_LIGHT5:
13652 return "gl_light5";
13653 case _GL_LIGHT6:
13654 return "gl_light6";
13655 case _GL_LIGHT7:
13656 return "gl_light7";
13657 case _GL_AMBIENT:
13658 return "gl_ambient";
13659 case _GL_SPECULAR:
13660 return "gl_specular";
13661 case _GL_DIFFUSE:
13662 return "gl_diffuse";
13663 case _GL_POSITION:
13664 return "gl_position";
13665 case _GL_SPOT_DIRECTION:
13666 return "gl_spot_direction";
13667 case _GL_SPOT_EXPONENT:
13668 return "gl_spot_exponent";
13669 case _GL_SPOT_CUTOFF:
13670 return "gl_spot_cutoff";
13671 case _GL_CONSTANT_ATTENUATION:
13672 return "gl_constant_attenuation";
13673 case _GL_LINEAR_ATTENUATION:
13674 return "gl_linear_attenuation";
13675 case _GL_QUADRATIC_ATTENUATION:
13676 return "gl_quadratic_attenuation";
13677 case _GL_OPTION:
13678 return "gl_option";
13679 case _GL_SMOOTH:
13680 return "gl_smooth";
13681 case _GL_FLAT:
13682 return "gl_flat";
13683 case _GL_SHININESS:
13684 return "gl_shininess";
13685 case _GL_FRONT:
13686 return "gl_front";
13687 case _GL_BACK:
13688 return "gl_back";
13689 case _GL_FRONT_AND_BACK:
13690 return "gl_front_and_back";
13691 case _GL_AMBIENT_AND_DIFFUSE:
13692 return "gl_ambient_and_diffuse";
13693 case _GL_EMISSION:
13694 return "gl_emission";
13695 case _GL_LIGHT_MODEL_AMBIENT:
13696 return "gl_light_model_ambient";
13697 case _GL_LIGHT_MODEL_LOCAL_VIEWER:
13698 return "gl_light_model_local_viewer";
13699 case _GL_LIGHT_MODEL_TWO_SIDE:
13700 return "gl_light_model_two_side";
13701 case _GL_LIGHT_MODEL_COLOR_CONTROL:
13702 return "gl_light_model_color_control";
13703 case _GL_BLEND:
13704 return "gl_blend";
13705 case _GL_SRC_ALPHA:
13706 return "gl_src_alpha";
13707 case _GL_ONE_MINUS_SRC_ALPHA:
13708 return "gl_one_minus_src_alpha";
13709 case _GL_SEPARATE_SPECULAR_COLOR:
13710 return "gl_separate_specular_color";
13711 case _GL_SINGLE_COLOR:
13712 return "gl_single_color";
13713 case _GL_MATERIAL:
13714 return "gl_material";
13715 case _GL_COLOR_INDEXES:
13716 return "gl_color_indexes";
13717 case _GL_LIGHT:
13718 return "gl_light";
13719 case _GL_PERSPECTIVE:
13720 return "gl_perspective";
13721 case _GL_ORTHO:
13722 return "gl_ortho";
13723 case _GL_QUATERNION:
13724 return "gl_quaternion";
13725 case _GL_ROTATION_AXIS:
13726 return "gl_rotation_axis";
13727 case _GL_X:
13728 return "gl_x";
13729 case _GL_Y:
13730 return "gl_y";
13731 case _GL_Z:
13732 return "gl_z";
13733 case _GL_XTICK:
13734 return "gl_xtick";
13735 case _GL_YTICK:
13736 return "gl_ytick";
13737 case _GL_ZTICK:
13738 return "gl_ztick";
13739 case _GL_ANIMATE:
13740 return "gl_animate";
13741 case _GL_SHOWAXES:
13742 return "gl_showaxes";
13743 case _GL_SHOWNAMES:
13744 return "gl_shownames";
13745 case _GL_X_AXIS_NAME:
13746 return "gl_x_axis_name";
13747 case _GL_Y_AXIS_NAME:
13748 return "gl_y_axis_name";
13749 case _GL_Z_AXIS_NAME:
13750 return "gl_z_axis_name";
13751 case _GL_X_AXIS_UNIT:
13752 return "gl_x_axis_unit";
13753 case _GL_Y_AXIS_UNIT:
13754 return "gl_y_axis_unit";
13755 case _GL_Z_AXIS_UNIT:
13756 return "gl_z_axis_unit";
13757 case _GL_LOGX:
13758 return "gl_logx";
13759 case _GL_LOGY:
13760 return "gl_logy";
13761 case _GL_LOGZ:
13762 return "gl_logz";
13763 }
13764 }
13765 if (subtype==_INT_MAPLELIB){
13766 switch (val){
13767 case _LINALG:
13768 return "linalg";
13769 case _NUMTHEORY:
13770 return "numtheory";
13771 case _GROEBNER:
13772 return "groebner";
13773 }
13774 }
13775 if (subtype==_INT_MAPLECONVERSION){
13776 switch (val){
13777 case _MAPLE_LIST:
13778 return "list";
13779 case _SET__VECT:
13780 return "set";
13781 case _MATRIX__VECT:
13782 return "matrix";
13783 case _POLY1__VECT:
13784 return "polynom";
13785 case _TRIG:
13786 return "trig";
13787 case _EXPLN:
13788 return "expln";
13789 case _PARFRAC:
13790 return "parfrac";
13791 case _FULLPARFRAC:
13792 return "fullparfrac";
13793 case _CONFRAC:
13794 return "confrac";
13795 case _BASE:
13796 return "base";
13797 case _POSINT:
13798 return "posint";
13799 case _NEGINT:
13800 return "negint";
13801 case _NONPOSINT:
13802 return "nonposint";
13803 case _NONNEGINT:
13804 return "nonnegint";
13805 case _LP_ASSUME:
13806 return "lp_assume";
13807 case _LP_BINARY:
13808 return "lp_binary";
13809 case _LP_BINARYVARIABLES:
13810 return "lp_binaryvariables";
13811 case _LP_DEPTHLIMIT:
13812 return "lp_depthlimit";
13813 case _LP_MAXIMIZE:
13814 return "lp_maximize";
13815 case _LP_NONNEGATIVE:
13816 return "lp_nonnegative";
13817 case _LP_NONNEGINT:
13818 return "lp_nonnegint";
13819 case _LP_VARIABLES:
13820 return "lp_variables";
13821 case _LP_INTEGER:
13822 return "lp_integer";
13823 case _LP_INTEGERVARIABLES:
13824 return "lp_integervariables";
13825 }
13826 }
13827 if (subtype==_INT_MUPADOPERATOR){
13828 switch (val){
13829 case _DELETE_OPERATOR:
13830 return "Delete";
13831 case _PREFIX_OPERATOR:
13832 return "Prefix";
13833 case _POSTFIX_OPERATOR:
13834 return "Postfix";
13835 case _BINARY_OPERATOR:
13836 return "Binary";
13837 case _NARY_OPERATOR:
13838 return "Nary";
13839 }
13840 }
13841 if (subtype==_INT_GROEBNER){
13842 switch (val){
13843 case _REVLEX_ORDER:
13844 return "revlex";
13845 case _PLEX_ORDER:
13846 return "plex";
13847 case _TDEG_ORDER:
13848 return "tdeg";
13849 case _WITH_COCOA:
13850 return "with_cocoa";
13851 case _WITH_F5:
13852 return "with_f5";
13853 case _MODULAR_CHECK:
13854 return "modular_check";
13855 case _RUR_REVLEX:
13856 return "rur";
13857 }
13858 }
13859 return print_INT_(val);
13860 }
13861
print_float(const float & f,char * ch)13862 static void print_float(const float & f,char * ch){
13863 sprintfdouble(ch,"%.14g",f);
13864 }
13865
print_FLOAT_(const giac_float & f,GIAC_CONTEXT)13866 string print_FLOAT_(const giac_float & f,GIAC_CONTEXT){
13867 char ch[64];
13868 #ifdef BCD
13869 #ifndef CAS38_DISABLED
13870 int i=get_int(f);
13871 if (is_zero(f-i))
13872 return print_INT_(i)+'.';
13873 #endif
13874 print_float(f,ch);
13875 #else
13876 print_float(f,ch);
13877 #endif
13878 return ch;
13879 }
13880
print_FRAC(const gen & f,GIAC_CONTEXT)13881 static string print_FRAC(const gen & f,GIAC_CONTEXT){
13882 if (f._FRACptr->num.type==_INT_ && f._FRACptr->den.type==_INT_){
13883 string s(f._FRACptr->num.print(contextptr));
13884 s += "/";
13885 add_print(s,f._FRACptr->den,contextptr);
13886 return s;
13887 }
13888 if (calc_mode(contextptr)==1 && f._FRACptr->den.type==_CPLX){
13889 gen n=f._FRACptr->num,d=f._FRACptr->den,dr,di;
13890 reim(d,dr,di,contextptr);
13891 n=n*gen(dr,-di);
13892 d=dr*dr+di*di;
13893 gen nd=fraction(n,d);
13894 if (nd.type==_FRAC)
13895 return print_FRAC(nd,contextptr);
13896 else
13897 return nd.print(contextptr);
13898 }
13899 return _FRAC2_SYMB(f).print(contextptr);
13900 }
13901
print(GIAC_CONTEXT) const13902 string gen::print(GIAC_CONTEXT) const{
13903 switch (type ) {
13904 case _INT_:
13905 if (val<0 && val != (1<<31) && calc_mode(contextptr)==38)
13906 return "−"+(-*this).print(contextptr);
13907 if (subtype)
13908 return localize(printint32(val,subtype,contextptr),language(contextptr));
13909 switch (integer_format(contextptr)){
13910 case 16:
13911 return hexa_print_INT_(val);
13912 case 8:
13913 return octal_print_INT_(val);
13914 case 2:
13915 return binary_print_INT_(val);
13916 default:
13917 return print_INT_(val);
13918 }
13919 case _DOUBLE_:
13920 return print_DOUBLE_(_DOUBLE_val,contextptr);
13921 case _FLOAT_:
13922 if (abs_calc_mode(contextptr)==38 && is_strictly_positive(-*this,contextptr)) return "−"+print_FLOAT_(-_FLOAT_val,contextptr);
13923 return print_FLOAT_(_FLOAT_val,contextptr);
13924 case _ZINT:
13925 if (abs_calc_mode(contextptr)==38 && is_strictly_positive(-*this,contextptr))
13926 return "−"+(-*this).print(contextptr);
13927 switch (integer_format(contextptr)){
13928 case 16:
13929 return hexa_print_ZINT(*_ZINTptr);
13930 case 8:
13931 return octal_print_ZINT(*_ZINTptr);
13932 default:
13933 return print_ZINT(*_ZINTptr);
13934 }
13935 case _REAL:
13936 return _REALptr->print(contextptr);
13937 case _CPLX:
13938 // if (abs_calc_mode(contextptr)==38) return "("+_CPLXptr->print(contextptr)+","+(_CPLXptr+1)->print(contextptr)+")";
13939 if (is_exactly_zero(*(_CPLXptr+1)))
13940 return _CPLXptr->print(contextptr);
13941 #ifndef GIAC_GGB
13942 if (*complex_display_ptr(*this) &1){
13943 #ifdef BCD
13944 if (_CPLXptr->type==_FLOAT_ && (_CPLXptr+1)->type==_FLOAT_)
13945 #ifdef GIAC_HAS_STO_38
13946 //grad
13947 return abs(*this,contextptr).print(contextptr)+"\xe2\x88\xa1"+print_FLOAT_(atan2f(_CPLXptr->_FLOAT_val,(_CPLXptr+1)->_FLOAT_val,angle_radian(contextptr)?AMRad:(angle_degree(contextptr)?AMDeg:AMGrad)),contextptr);
13948 #else
13949 return abs(*this,contextptr).print(contextptr)+"\xe2\x88\xa1"+print_FLOAT_(atan2f(_CPLXptr->_FLOAT_val,(_CPLXptr+1)->_FLOAT_val,angle_radian(contextptr)),contextptr);
13950 #endif
13951 #endif
13952 // return abs(*this,contextptr).print(contextptr)+"\xe2\x88\xa1"+(angle_radian(contextptr)?arg(*this,contextptr):arg(*this,contextptr)*rad2deg_g).print(contextptr);
13953 return abs(*this,contextptr).print(contextptr)+"\xe2\x88\xa1"+arg(*this,contextptr).print(contextptr);
13954 }
13955 #endif // GIAC_GGB
13956 if (is_exactly_zero(*_CPLXptr)){
13957 if (is_one(*(_CPLXptr+1)))
13958 return printi(contextptr);
13959 if (is_minus_one(*(_CPLXptr+1)))
13960 return (abs_calc_mode(contextptr)==38?string("−"):string("-"))+printi(contextptr);
13961 return ((_CPLXptr+1)->print(contextptr) + string("*"))+printi(contextptr);
13962 }
13963 if (is_one(*(_CPLXptr+1)))
13964 return (_CPLXptr->print(contextptr) + string("+"))+printi(contextptr);
13965 if (is_minus_one(*(_CPLXptr+1)))
13966 return (_CPLXptr->print(contextptr) + string("-"))+printi(contextptr);
13967 if (is_positive(-(*(_CPLXptr+1)),contextptr))
13968 return (_CPLXptr->print(contextptr) + string("-") + (-(*(_CPLXptr+1))).print(contextptr) + "*")+printi(contextptr);
13969 return (_CPLXptr->print(contextptr) + string("+") + (_CPLXptr+1)->print(contextptr) + "*")+printi(contextptr);
13970 case _IDNT:
13971 if (calc_mode(contextptr)==1 && (is_inf(*this) || is_undef(*this)))
13972 return "?";
13973 return _IDNTptr->print(contextptr);
13974 case _SYMB:
13975 {
13976 int d=depth(*this,0,print_max_depth);
13977 if (d>=print_max_depth)
13978 return "Too many embeddings";
13979 }
13980 if (is_inf(_SYMBptr->feuille)){
13981 if (_SYMBptr->sommet==at_plus){
13982 #ifdef KHICAS
13983 return "oo";
13984 #else
13985 if (
13986 // calc_mode(contextptr)!=1
13987 abs_calc_mode(contextptr)==38
13988 )
13989 return "∞";
13990 else
13991 return "+infinity";
13992 #endif
13993 }
13994 if (_SYMBptr->sommet==at_neg){
13995 #ifdef KHICAS
13996 return "-oo";
13997 #else
13998 if (
13999 // calc_mode(contextptr)!=1
14000 abs_calc_mode(contextptr)==38
14001 )
14002 return "-∞";
14003 else
14004 return "-infinity";
14005 #endif
14006 }
14007 }
14008 if (subtype==_SPREAD__SYMB){
14009 if (_SYMBptr->sommet==at_sto)
14010 return "=("+_SYMBptr->print(contextptr)+")";
14011 return "="+_SYMBptr->print(contextptr);
14012 }
14013 else
14014 return _SYMBptr->print(contextptr);
14015 case _VECT:
14016 if (subtype==_GRAPH__VECT){
14017 string s;
14018 if (is_graphe(*this,s,contextptr))
14019 return '"'+s+'"';
14020 }
14021 return print_VECT(*_VECTptr,subtype,contextptr);
14022 case _POLY:
14023 return _POLYptr->print() ;
14024 case _SPOL1:
14025 return print_SPOL1(*_SPOL1ptr,contextptr);
14026 case _EXT: {
14027 string s("%%{");
14028 s += _EXTptr->print(contextptr);
14029 s += ':';
14030 s += (*(_EXTptr+1)).print(contextptr);
14031 s += "%%}";
14032 return s;
14033 }
14034 case _USER:
14035 return _USERptr->print(contextptr);
14036 case _MOD:
14037 #ifdef GIAC_HAS_STO_38
14038 if ( (_MODptr->type==_SYMB && _MODptr->_SYMBptr->sommet!=at_pow) || (_MODptr->type==_VECT && _MODptr->subtype==_SEQ__VECT) )
14039 return "("+_MODptr->print(contextptr)+") %% "+(*(_MODptr+1)).print(contextptr);
14040 return _MODptr->print(contextptr)+" %% "+(*(_MODptr+1)).print(contextptr);
14041 #else
14042 if ( (_MODptr->type==_SYMB && _MODptr->_SYMBptr->sommet!=at_pow) || (_MODptr->type==_VECT && _MODptr->subtype==_SEQ__VECT) )
14043 return "("+_MODptr->print(contextptr)+")"+(python_compat(contextptr)?" mod ":" % ")+(*(_MODptr+1)).print(contextptr);
14044 return _MODptr->print(contextptr)+(python_compat(contextptr)?" mod ":" % ")+(*(_MODptr+1)).print(contextptr);
14045 #endif
14046 case _FRAC:
14047 return print_FRAC(*this,contextptr);
14048 case _STRNG:
14049 #ifdef GIAC_HAS_STO_38
14050 // if (subtype==-1)
14051 // return AspenPrintErrorString(*_STRNGptr);
14052 #endif
14053 return print_STRNG(*_STRNGptr);
14054 case _FUNC:
14055 if (*this==at_return){
14056 if (xcas_mode(contextptr)==3)
14057 return "Return";
14058 else
14059 return "return ;";
14060 }
14061 if (rpn_mode(contextptr) || _FUNCptr->ptr()->printsommet==&printastifunction || subtype==0)
14062 return _FUNCptr->ptr()->print(contextptr);
14063 else
14064 return string("'")+_FUNCptr->ptr()->print(contextptr)+"'";
14065 case _MAP:
14066 if (subtype==1)
14067 return maptoarray(*_MAPptr,contextptr).print(contextptr);
14068 else
14069 return printmap(*_MAPptr,contextptr);
14070 case _EQW:
14071 return print_EQW(*_EQWptr);
14072 case _POINTER_: {
14073 // handle 64 bits pointers
14074 unsigned long long u=(unsigned long long)_POINTER_val;
14075 if (u<(1U<<31))
14076 return "pointer("+hexa_print_INT_(int((alias_type)_POINTER_val))+","+print_INT_(subtype)+")";
14077 gen z=longlong(u);
14078 return "pointer("+hexa_print_ZINT(*z._ZINTptr)+","+print_INT_(subtype)+")";
14079 }
14080 default:
14081 #ifndef NO_STDEXCEPT
14082 settypeerr(gettext("print"));
14083 #endif
14084 return "print error";
14085 }
14086 return "print error";
14087 }
14088
14089 #ifdef ConnectivityKit
dbgprint() const14090 const char * gen::dbgprint() const { return "Done";}
14091 #else
14092 #if defined(VISUALC) && !defined(MS_SMART)
dbgprint() const14093 const char * gen::dbgprint() const { ATLTRACE2("%s\r\n", this->print(0).c_str()); return "Done";}
14094 #else
dbgprint() const14095 const char * gen::dbgprint() const{
14096 if (this->type==_POLY)
14097 return _POLYptr->dbgprint();
14098 static string *sptr=0;
14099 if (!sptr) sptr=new string;
14100 *sptr=this->print(context0);
14101 #if 0 // ndef NSPIRE
14102 COUT << *sptr;
14103 #endif
14104 return sptr->c_str();
14105 }
14106 #endif
14107 #endif
14108
14109 #ifdef KHICAS
operator <<(stdostream & os,const gen & a)14110 stdostream & operator << (stdostream & os,const gen & a){
14111 return os << a.print(context0);
14112 }
14113 #endif
14114 #ifndef NSPIRE
operator <<(ostream & os,const gen & a)14115 ostream & operator << (ostream & os,const gen & a) { return os << a.print(context0); }
14116 #endif
14117
print(GIAC_CONTEXT) const14118 string monome::print(GIAC_CONTEXT) const {
14119 // if (abs_calc_mode(contextptr)==38 )
14120 return "%%%{" + coeff.print(contextptr) + ',' + exponent.print(contextptr) + "%%%}" ;
14121 //return "<<" + coeff.print(contextptr) + ',' + exponent.print(contextptr) + ">>" ;
14122 }
14123
dbgprint() const14124 const char * monome::dbgprint() const {
14125 static string *sptr=0;
14126 if (!sptr) sptr=new string;
14127 *sptr=this->print(context0);
14128 #if 0 // ndef NSPIRE
14129 COUT << *sptr;
14130 #endif
14131 return sptr->c_str();
14132 }
14133
14134 #ifndef NSPIRE
operator <<(ostream & os,const monome & m)14135 ostream & operator << (ostream & os,const monome & m){
14136 return os << m.print(context0) ;
14137 }
14138 #endif
14139
14140 /*
14141 gen string2_ZINT(string s,int l,int & pos){
14142 char ss[l+1];
14143 int neg=1;
14144 if (s[pos]=='-'){
14145 pos++;
14146 neg=-1;
14147 }
14148 int i=0;
14149 for (;(pos<l) && (s[pos]>='0') && (s[pos]<='9');pos++,i++)
14150 ss[i]=s[pos];
14151 if ((!i) && (s[pos]=='i') || (s[pos]=='I')){
14152 return(neg);
14153 }
14154 assert(i);
14155 ss[i]=char(0);
14156 mpz_t *mpzin = new mpz_t[1];
14157 mpz_init(*mpzin);
14158 mpz_set_str (*mpzin, ss, 10);
14159 if (neg>0)
14160 return(gen(mpzin));
14161 else
14162 return(-gen(mpzin));
14163 }
14164
14165 istream & operator >> (istream & is,gen & a){
14166 string s;
14167 is >> s;
14168 int l=s.size();
14169 int pos=0;
14170 a=gen(0);
14171 while (pos<l){
14172 if ((s[pos]=='i') || (s[pos]=='I')){
14173 a=a+gen(0,1);
14174 pos++;
14175 }
14176 else {
14177 if (s[pos]=='+')
14178 pos++;
14179 else {
14180 gen tmp(string2_ZINT(s,l,pos));
14181 if (s[pos]=='*'){
14182 pos++;
14183 assert( (s[pos]=='i') || (s[pos]=='I') );
14184 pos++; // skip *I
14185 a=a+tmp*cst_i;
14186 }
14187 else {
14188 if ((s[pos]=='i') || (s[pos]=='I')){
14189 pos++; // skip I
14190 a=a+tmp*cst_i;
14191 }
14192 else
14193 a=a+tmp;
14194 }
14195 }
14196 }
14197 }
14198 return is;
14199 }
14200 */
14201 #ifdef NSPIRE
operator >>(nio::ios_base<T> & is,gen & a)14202 template<class T> nio::ios_base<T> & operator>>(nio::ios_base<T> & is,gen & a){
14203 string s;
14204 is >> s;
14205 a = gen(s,context0);
14206 return is;
14207 }
14208 #else
operator >>(istream & is,gen & a)14209 istream & operator >> (istream & is,gen & a){
14210 string s;
14211 is >> s;
14212 a = gen(s,context0);
14213 return is;
14214 }
14215 #endif
14216
14217 /* Some string utilities not use anymore */
14218 // Note that this function should be optimized for large input
cut_string(const string & chaine,int nchar,vector<int> & ligne_end)14219 string cut_string(const string & chaine,int nchar,vector<int> & ligne_end) {
14220 // CERR << CLOCK() << '\n';
14221 int pos;
14222 if (ligne_end.empty())
14223 pos=0;
14224 else
14225 pos=ligne_end.back()+1;
14226 int l=int(chaine.size());
14227 string res;
14228 for (int i=0;i<l;){
14229 // look for \n between i and l
14230 int k=int(chaine.find_first_of('\n',i));
14231 if ( (l-i<nchar) && ((k<i)||(k>=l-1)) ){
14232 ligne_end.push_back(pos+l);
14233 // CERR << CLOCK() << '\n';
14234 return res+chaine.substr(i,l-i);
14235 }
14236 if ((k>=i) && (k<i+nchar+4*(i==0)) ){
14237 ligne_end.push_back(pos+k);
14238 res += chaine.substr(i,k+1-i);
14239 i=k+1;
14240 }
14241 else {
14242 int j;
14243 int j1=int(chaine.find_last_of('+',i+nchar+4*(i==0)));
14244 int j2=int(chaine.find_last_of('-',i+nchar+4*(i==0)));
14245 int j3=int(chaine.find_last_of(',',i+nchar+4*(i==0)));
14246 j=giacmax(j1,giacmax(j2,j3));
14247 if ((j-i)<(nchar/2))
14248 j=i+nchar+4*(i==0);
14249 ligne_end.push_back(pos+giacmin(j,l));
14250 res += chaine.substr(i,j-i);
14251 i=j;
14252 if (i<l){
14253 res +="\\\n ";
14254 pos +=7;
14255 }
14256 }
14257 }
14258 // CERR << CLOCK() << '\n';
14259 return res;
14260 }
14261
calc_endlines_positions(const vecteur & history_in,const vecteur & history_out,int nchar,vector<int> & endlines,vector<int> & positions)14262 string calc_endlines_positions(const vecteur & history_in,const vecteur & history_out,int nchar,vector<int> & endlines,vector<int> & positions){
14263 string res;
14264 endlines.clear();
14265 positions.clear();
14266 int s_in=int(history_in.size()),s_out=int(history_out.size());
14267 int s=giacmax(s_in,s_out);
14268 for (int i=0;i<s;++i){
14269 string chaine;
14270 if (rpn_mode(context0))
14271 chaine=print_INT_(s-i)+": ";
14272 else
14273 chaine=print_INT_(i)+": ";
14274 if (!rpn_mode(context0)){
14275 if (i<s_in)
14276 chaine+=history_in[i].print(context0)+" = ";
14277 }
14278 else
14279 chaine +=" ";
14280 if (i<s_out)
14281 chaine += history_out[i].print(context0);
14282 if (i)
14283 res +='\n';
14284 res += cut_string(chaine,nchar,endlines);
14285 positions.push_back(endlines.back());
14286 }
14287 return res;
14288 }
14289
is_operator_char(char c)14290 bool is_operator_char(char c){
14291 switch(c){
14292 case '+': case '-': case '*': case '/': case '^': case '%':
14293 return true;
14294 }
14295 return false;
14296 }
14297
is_operator_char(char c,char op)14298 static bool is_operator_char(char c,char op){
14299 switch(c){
14300 case '+': case '-':
14301 return true;
14302 case '*': case '/': case '^': case '%':
14303 return c==op;
14304 }
14305 return false;
14306 }
14307
matchpos(const string & s,int & pos)14308 bool matchpos(const string & s,int & pos){
14309 char c=s[pos];
14310 char c_orig=c;
14311 int l=int(s.size());
14312 int counter1=0,counter2=0,counter3=0,incr;
14313 if ( (c==')') || (c==']') || (c=='}') )
14314 incr=-1;
14315 else
14316 incr=1;
14317 for (;(pos>=0) && (pos<l);pos+=incr){
14318 switch (c=s[pos]){
14319 case '(':
14320 counter1++;
14321 break;
14322 case ')':
14323 counter1--;
14324 break;
14325 case '[':
14326 counter2++;
14327 break;
14328 case ']':
14329 counter2--;
14330 break;
14331 case '{':
14332 counter3++;
14333 break;
14334 case '}':
14335 counter3--;
14336 break;
14337 }
14338 if ( (!counter1) && (!counter2) && (!counter3) ){
14339 bool res=false;
14340 switch (c_orig){
14341 case '(':
14342 res=c==')';
14343 break;
14344 case '[':
14345 res=c==']';
14346 break;
14347 case '{':
14348 res=c=='}';
14349 break;
14350 case ')':
14351 res=c=='(';
14352 break;
14353 case ']':
14354 res=c=='[';
14355 break;
14356 case '}':
14357 res=c=='{';
14358 break;
14359 }
14360 return res;
14361 }
14362 }
14363 return false;
14364 }
14365
find_left(const string & s,int & pos1,int & pos2)14366 static void find_left(const string & s,int & pos1,int & pos2){
14367 int l=int(s.size());
14368 pos1=giacmin(giacmax(pos1,0),l);
14369 int pos1orig=pos1;
14370 if (!pos1)
14371 return;
14372 pos2=giacmax(giacmin(pos2,l),0);
14373 int counter1=0,counter2=0;
14374 if (pos2==l){
14375 int i=pos2;
14376 for (;i>pos1;){
14377 --i;
14378 char ch = s[i];
14379 if (ch=='(')
14380 ++counter1;
14381 if (ch==')')
14382 --counter1;
14383 if (ch=='[')
14384 ++counter2;
14385 if (ch==']')
14386 --counter2;
14387 }
14388 }
14389 for (;pos1>=0;--pos1){
14390 char ch=s[pos1];
14391 if ( (!counter1) && (!counter2) && ( (ch=='(') || (ch=='[') || (ch=='+') || (ch=='-') || (ch==',') )){
14392 if ( (pos1<pos1orig) && ( (ch!='(') || (s[pos2-1]!=')') ) )
14393 ++pos1;
14394 break;
14395 }
14396 if (ch=='('){
14397 ++counter1;
14398 if ( (!counter1) && (!counter2) ){
14399 if (s[pos2-1]==')')
14400 break;
14401 if ( pos1 && isalphan(s[pos1-1])){
14402 --pos1;
14403 for (;pos1>=0;--pos1)
14404 if (!isalphan(s[pos1]))
14405 break;
14406 ++pos1;
14407 }
14408 break;
14409 }
14410 }
14411 if (ch==')')
14412 --counter1;
14413 if (ch=='['){
14414 ++counter2;
14415 if ( (!counter1) && (!counter2) ){
14416 if (s[pos2-1]==']')
14417 break;
14418 if ( pos1 && isalphan(s[pos1-1])){
14419 --pos1;
14420 for (;pos1>=0;--pos1)
14421 if (!isalphan(s[pos1]))
14422 break;
14423 ++pos1;
14424 }
14425 break;
14426 }
14427 }
14428 if (ch==']')
14429 --counter2;
14430 }
14431 }
14432
find_right(const string & s,int & pos1,int & pos2)14433 static void find_right(const string & s,int & pos1,int & pos2){
14434 int l=int(s.size());
14435 pos1=giacmin(giacmax(pos1,0),l);
14436 pos2=giacmax(giacmin(pos2,l),0);
14437 int pos2orig=pos2;
14438 int counter1=0,counter2=0;
14439 for (int i=pos1;(i<pos2-1) && (i<l);++i){
14440 char ch=s[i];
14441 if (ch=='(')
14442 ++counter1;
14443 if (ch==')')
14444 --counter1;
14445 if (ch=='[')
14446 ++counter2;
14447 if (ch==']')
14448 --counter2;
14449 if ( (counter1<0) && (pos1) ){ // restart at an earlier position
14450 pos1=int(s.find_last_of('(',pos1-1));
14451 if (pos1<0)
14452 pos1=0;
14453 i=pos1-1;
14454 counter1=0;
14455 counter2=0;
14456 }
14457 }
14458 for (;pos2<=l;++pos2){
14459 char ch=s[pos2-1];
14460 if ( (!counter1) && (!counter2) && ( (ch==')') || (ch==']') || (ch=='+') || (ch=='-') || (ch==',') ) && (pos2>pos2orig)){
14461 --pos2;
14462 break;
14463 }
14464 if (ch=='(')
14465 ++counter1;
14466 if (ch==')'){
14467 --counter1;
14468 if ( (!counter1) && (!counter2) ){
14469 if ( (pos1>0) && (s[pos1]=='(') && isalphan(s[pos1-1])){
14470 --pos1;
14471 for (;pos1>=0;--pos1)
14472 if (!isalphan(s[pos1]))
14473 break;
14474 ++pos1;
14475 }
14476 break;
14477 }
14478 }
14479 if (ch=='[')
14480 ++counter2;
14481 if (ch==']'){
14482 --counter2;
14483 if ( (!counter1) && (!counter2) ){
14484 if ( (pos1>0) && (s[pos1]=='[') && isalphan(s[pos1-1])){
14485 --pos1;
14486 for (;pos1>=0;--pos1)
14487 if (!isalphan(s[pos1]))
14488 break;
14489 ++pos1;
14490 }
14491 break;
14492 }
14493 }
14494 }
14495 if (pos2==l+1)
14496 find_left(s,pos1,pos2);
14497 }
14498
increase_selection(const string & s,int & pos1,int & pos2)14499 void increase_selection(const string & s,int & pos1,int& pos2){
14500 int l=int(s.size());
14501 int pos1_orig(pos1),pos2_orig(pos2);
14502 // adjust selection (does not change anything on a valid selection)
14503 find_left(s,pos1,pos2);
14504 find_right(s,pos1,pos2);
14505 if ( (pos1!=pos1_orig) || (pos2!=pos2_orig) )
14506 return;
14507 if (pos1 && (pos2<l) && ( (s[pos1-1]=='(') || (s[pos1-1]==',')) && (s[pos2]!=')') && (s[pos2]!=',')){
14508 ++pos2;
14509 find_right(s,pos1,pos2);
14510 return;
14511 }
14512 if (pos1>1){
14513 char op=s[pos1-1];
14514 --pos1;
14515 for (;pos1;--pos1){
14516 if (s[pos1]==',')
14517 op=0;
14518 if (!is_operator_char(s[pos1],op))
14519 break;
14520 }
14521 if (s[pos1]=='(' && pos1){
14522 --pos1;
14523 for (;pos1;--pos1){
14524 if (!isalphan(s[pos1]))
14525 break;
14526 }
14527 ++pos1;
14528 }
14529 find_left(s,pos1,pos2);
14530 find_right(s,pos1,pos2);
14531 return;
14532 }
14533 pos1=0;
14534 ++pos2;
14535 find_right(s,pos1,pos2);
14536 }
14537
decrease_selection(const string & s,int & pos1,int & pos2)14538 void decrease_selection(const string & s,int & pos1,int& pos2){
14539 int l=int(s.size());
14540 int pos2_orig(pos2);
14541 // adjust selection (does not change anything on a valid selection)
14542 find_left(s,pos1,pos2);
14543 if (pos2!=l)
14544 --pos2;
14545 if (!pos2)
14546 return;
14547 int counter1=0,counter2=0;
14548 char op=' ';
14549 if (pos2<l-1)
14550 op=s[pos2+1];
14551 for (;pos2>pos1;--pos2){
14552 char ch=s[pos2];
14553 if (ch=='('){
14554 ++counter1;
14555 if ( (!counter1) && (!counter2) && pos2_orig && (s[pos2_orig-1]==')') ){
14556 pos1=pos2+1;
14557 pos2=pos2_orig-1;
14558 return;
14559 }
14560 }
14561 if (ch==')')
14562 --counter1;
14563 if (ch=='[')
14564 ++counter2;
14565 if (ch==']')
14566 --counter2;
14567 if (ch==',')
14568 op=0;
14569 if ( (!counter1) && (!counter2) && ( is_operator_char(ch,op) || (ch==',')) )
14570 return;
14571 }
14572 for (;pos1<l;++pos1){
14573 char ch=s[pos1];
14574 if ( (ch=='(') || (ch=='[') || (ch=='+') || (ch==','))
14575 break;
14576 }
14577 ++pos1;
14578 pos2=pos1+1;
14579 find_right(s,pos1,pos2);
14580 }
14581
move_selection_right(const string & s,int & pos1,int & pos2)14582 void move_selection_right(const string & s,int & pos1, int & pos2){
14583 int l=int(s.size());
14584 // int pos1_orig(pos1),pos2_orig(pos2);
14585 // adjust selection (does not change anything on a valid selection)
14586 find_right(s,pos1,pos2);
14587 pos1=pos2;
14588 char op=s[pos1];
14589 for (;pos1<l;++pos1){
14590 if (s[pos1]==',')
14591 op=0;
14592 if (!is_operator_char(s[pos1],op) && (s[pos1]!=')') && (s[pos1]!=']'))
14593 break;
14594 }
14595 pos2=pos1+1;
14596 find_right(s,pos1,pos2);
14597 }
14598
move_selection_left(const string & s,int & pos1,int & pos2)14599 void move_selection_left(const string & s,int & pos1, int & pos2){
14600 // int l=s.size();
14601 // int pos1_orig(pos1),pos2_orig(pos2);
14602 // adjust selection (does not change anything on a valid selection)
14603 find_left(s,pos1,pos2);
14604 pos2=pos1-1;
14605 char op=s[pos2];
14606 for (;pos2>0;--pos2){
14607 if (s[pos2-1]==',')
14608 op=0;
14609 if (!is_operator_char(s[pos2-1],op) && (s[pos2-1]!='(') && (s[pos2-1]!='[') )
14610 break;
14611 }
14612 if (pos2<=0){
14613 pos1=0;
14614 pos2=0;
14615 return;
14616 }
14617 pos1=pos2-1;
14618 find_left(s,pos1,pos2);
14619 find_right(s,pos1,pos2);
14620 }
14621
remove_extension(const string & chaine)14622 string remove_extension(const string & chaine){
14623 int s=int(chaine.size());
14624 if (s>4 && chaine.substr(s-4,4)==".tns")
14625 return remove_extension(chaine.substr(0,s-4));
14626 int l=int(chaine.find_last_of('.',s));
14627 int ll=int(chaine.find_last_of('/',s));
14628 if (l>0 && l<s){
14629 if ( ll<=0 || ll>=s || l>ll)
14630 return chaine.substr(0,l);
14631 }
14632 return chaine;
14633 }
14634
14635 //environment * env=new environment;
14636
14637 // Real object and real interval functions
14638
operator =(const real_object & g)14639 real_object & real_object::operator = (const real_object & g) {
14640 #ifdef HAVE_LIBMPFR
14641 mpfr_clear(inf);
14642 mpfr_init2(inf,mpfr_get_prec(g.inf));
14643 mpfr_set(inf,g.inf,MPFR_RNDN);
14644 #else
14645 mpf_clear(inf);
14646 mpf_init_set(inf,g.inf);
14647 #endif
14648 return *this;
14649 }
14650
14651 #ifdef HAVE_LIBMPFI
real_interval(const mpfi_t & interv)14652 real_interval::real_interval(const mpfi_t & interv) {
14653 int nbits=mpfi_get_prec(interv);
14654 mpfr_set_prec(inf,nbits);
14655 mpfi_get_fr(inf,interv);
14656 mpfi_init2(infsup,nbits);
14657 mpfi_set(infsup,interv);
14658 }
14659 #endif
14660
operator =(const real_interval & g)14661 real_object & real_interval::operator = (const real_interval & g) {
14662 #ifdef HAVE_LIBMPFR
14663 mpfr_clear(inf);
14664 #else
14665 mpf_clear(inf);
14666 #endif
14667 #ifdef HAVE_LIBMPFI
14668 mpfi_clear(infsup);
14669 #else
14670 #ifdef HAVE_LIBMPFR
14671 mpfr_clear(sup);
14672 #else
14673 mpf_clear(sup);
14674 #endif
14675 #endif
14676 #ifdef HAVE_LIBMPFR
14677 mpfr_init2(inf,mpfr_get_prec(g.inf));
14678 mpfr_set(inf,g.inf,MPFR_RNDN);
14679 #else
14680 mpf_init_set(inf,g.inf);
14681 #endif
14682 #ifdef HAVE_LIBMPFI
14683 mpfi_init2(infsup,mpfi_get_prec(g.infsup));
14684 mpfi_set(infsup,g.infsup);
14685 #else
14686 #ifdef HAVE_LIBMPFR
14687 mpfr_init2(sup,mpfr_get_prec(g.sup));
14688 mpfr_set(sup,g.sup,MPFR_RNDN);
14689 #else
14690 mpf_init_set(sup,g.sup);
14691 #endif
14692 #endif
14693 return *this;
14694 }
14695
operator =(const real_object & g)14696 real_object & real_interval::operator = (const real_object & g) {
14697 #ifdef NO_RTTI
14698 const real_interval * ptr=0;
14699 #else
14700 const real_interval * ptr=dynamic_cast<const real_interval *> (&g);
14701 #endif
14702 if (ptr)
14703 return *this=*ptr;
14704 #ifdef HAVE_LIBMPFR
14705 mpfr_clear(inf);
14706 #ifdef HAVE_LIBMPFI
14707 mpfi_clear(infsup);
14708 #else
14709 mpfr_clear(sup);
14710 #endif
14711 mpfr_init2(inf,mpfr_get_prec(g.inf));
14712 mpfr_set(inf,g.inf,MPFR_RNDN);
14713 #ifdef HAVE_LIBMPFI
14714 mpfi_init2(infsup,mpfr_get_prec(g.inf));
14715 mpfi_set_fr(infsup,g.inf);
14716 #else
14717 mpfr_init2(sup,mpfr_get_prec(g.inf));
14718 mpfr_set(sup,g.inf,MPFR_RNDN);
14719 #endif
14720 #else // HAVE_LIBMPFR
14721 mpf_clear(inf);
14722 #ifdef HAVE_LIBMPFI
14723 mpfi_clear(infsup);
14724 #else
14725 mpf_clear(sup);
14726 #endif
14727 mpf_init_set(inf,g.inf);
14728 #ifdef HAVE_LIBMPFI
14729 mpfi_init_set_fr(infsup,g.inf);
14730 #else
14731 mpf_init_set(sup,g.inf);
14732 #endif
14733 #endif // HAVE_LIBMPFR
14734 return *this;
14735 }
14736
real_object()14737 real_object::real_object() {
14738 #ifdef HAVE_LIBMPFR
14739 mpfr_init(inf);
14740 #else
14741 mpf_init(inf);
14742 #endif
14743 }
14744
real_object(const real_object & g)14745 real_object::real_object(const real_object & g){
14746 #ifdef HAVE_LIBMPFR
14747 mpfr_init2(inf,mpfr_get_prec(g.inf));
14748 mpfr_set(inf,g.inf,MPFR_RNDN);
14749 #else
14750 mpf_init_set(inf,g.inf);
14751 #endif
14752 }
14753
real_object(double d)14754 real_object::real_object(double d) {
14755 #ifdef HAVE_LIBMPFR
14756 mpfr_init_set_d(inf,d,MPFR_RNDN);
14757 #else
14758 mpf_init_set_d(inf,d);
14759 #endif
14760 }
14761
14762 #ifdef HAVE_LIBMPFR
real_object(const mpfr_t & d)14763 real_object::real_object(const mpfr_t & d) {
14764 mpfr_init2(inf,mpfr_get_prec(d));
14765 mpfr_set(inf,d,MPFR_RNDN);
14766 }
14767 #endif
14768
real_object(const mpf_t & d)14769 real_object::real_object(const mpf_t & d) {
14770 #ifdef HAVE_LIBMPFR
14771 mpfr_init(inf);
14772 mpfr_set_f(inf,d,MPFR_RNDN);
14773 #else
14774 mpf_init_set(inf,d);
14775 #endif
14776 }
14777
real_object(const gen & g)14778 real_object::real_object(const gen & g){
14779 switch (g.type){
14780 case _INT_:
14781 #ifdef HAVE_LIBMPFR
14782 mpfr_init_set_si(inf,g.val,MPFR_RNDN);
14783 #else
14784 mpf_init_set_si(inf,g.val);
14785 #endif
14786 return;
14787 case _DOUBLE_:
14788 #ifdef HAVE_LIBMPFR
14789 mpfr_init_set_d(inf,g._DOUBLE_val,MPFR_RNDN);
14790 #else
14791 mpf_init_set_d(inf,g._DOUBLE_val);
14792 #endif
14793 return;
14794 case _ZINT:
14795 #ifdef HAVE_LIBMPFR
14796 mpfr_init(inf);
14797 mpfr_set_z(inf,*g._ZINTptr,MPFR_RNDN);
14798 #else
14799 mpf_init(inf);
14800 mpf_set_z(inf,*g._ZINTptr);
14801 #endif
14802 return;
14803 case _REAL:
14804 #ifdef HAVE_LIBMPFR
14805 mpfr_init2(inf,mpfr_get_prec(g._REALptr->inf));
14806 mpfr_set(inf,g._REALptr->inf,MPFR_RNDN);
14807 #else
14808 mpf_init_set(inf,g._REALptr->inf);
14809 #endif
14810 return;
14811 }
14812 if (g.type==_FRAC){
14813 gen tmp=real_object(g._FRACptr->num)/real_object(g._FRACptr->den);
14814 if (tmp.type==_REAL){
14815 #ifdef HAVE_LIBMPFR
14816 mpfr_init2(inf,mpfr_get_prec(tmp._REALptr->inf));
14817 mpfr_set(inf,tmp._REALptr->inf,MPFR_RNDN);
14818 #else
14819 mpf_init_set(inf,tmp._REALptr->inf);
14820 #endif
14821 return;
14822 }
14823 }
14824 #ifndef NO_STDEXCEPT
14825 setsizeerr(gettext("Unable to convert to real ")+g.print(context0));
14826 #endif
14827 return;
14828 }
14829
real_object(const gen & g,unsigned int precision)14830 real_object::real_object(const gen & g,unsigned int precision){
14831 switch (g.type){
14832 case _INT_:
14833 #ifdef HAVE_LIBMPFR
14834 mpfr_init2(inf,precision);
14835 mpfr_set_si(inf,g.val,MPFR_RNDN);
14836 #else
14837 mpf_init_set_si(inf,g.val);
14838 #endif
14839 return;
14840 case _DOUBLE_:
14841 #ifdef HAVE_LIBMPFR
14842 mpfr_init2(inf,precision);
14843 mpfr_set_d(inf,g._DOUBLE_val,MPFR_RNDN);
14844 #else
14845 mpf_init_set_d(inf,g._DOUBLE_val);
14846 #endif
14847 return;
14848 case _ZINT:
14849 #ifdef HAVE_LIBMPFR
14850 mpfr_init2(inf,precision);
14851 mpfr_set_z(inf,*g._ZINTptr,MPFR_RNDN);
14852 #else
14853 mpf_init(inf);
14854 mpf_set_z(inf,*g._ZINTptr);
14855 #endif
14856 return;
14857 case _REAL:
14858 #ifdef HAVE_LIBMPFR
14859 mpfr_init2(inf,precision);
14860 mpfr_set(inf,g._REALptr->inf,MPFR_RNDN);
14861 #else
14862 mpf_init_set(inf,g._REALptr->inf);
14863 #endif
14864 return;
14865 }
14866 if (g.type==_FRAC){
14867 gen tmp=real_object(g._FRACptr->num,precision)/real_object(g._FRACptr->den,precision);
14868 if (tmp.type==_REAL){
14869 #ifdef HAVE_LIBMPFR
14870 mpfr_init2(inf,mpfr_get_prec(tmp._REALptr->inf));
14871 mpfr_set(inf,tmp._REALptr->inf,MPFR_RNDN);
14872 #else
14873 mpf_init_set(inf,tmp._REALptr->inf);
14874 #endif
14875 return;
14876 }
14877 }
14878 int save_decimal_digits=decimal_digits(context0);
14879 set_decimal_digits(precision,context0);
14880 gen tmp=re(evalf(g,1,context0),context0);
14881 set_decimal_digits(save_decimal_digits,context0);
14882 if (tmp.type!=_REAL){
14883 #ifndef NO_STDEXCEPT
14884 setsizeerr(gettext("Unable to convert to real ")+g.print(context0));
14885 #endif
14886 return;
14887 }
14888 #ifdef HAVE_LIBMPFR
14889 mpfr_init2(inf,precision);
14890 mpfr_set(inf,tmp._REALptr->inf,MPFR_RNDN);
14891 #else
14892 mpf_init_set(inf,tmp._REALptr->inf);
14893 #endif
14894 }
14895
gen(const real_object & g)14896 gen::gen(const real_object & g){
14897 #ifdef SMARTPTR64
14898 * ((ulonglong * ) this) = ulonglong(new ref_real_object) << 16;
14899 #else
14900 __REALptr = new ref_real_object;
14901 #endif
14902 type = _REAL;
14903 subtype=0;
14904 #ifdef HAVE_LIBMPFR
14905 mpfr_set_prec(_REALptr->inf,mpfr_get_prec(g.inf));
14906 mpfr_set(_REALptr->inf,g.inf,MPFR_RNDN);
14907 #else
14908 mpf_set(_REALptr->inf,g.inf);
14909 #endif
14910 #ifdef KHICAS
14911 if ((size_t) _REALptr > stackptr)
14912 ctrl_c=interrupted=true;
14913 #endif
14914 }
14915
gen(const real_interval & g)14916 gen::gen(const real_interval & g){
14917 #ifdef SMARTPTR64
14918 * ((ulonglong * ) this) = ulonglong(new ref_real_interval) << 16;
14919 #else
14920 __REALptr = (ref_real_object *) new ref_real_interval;
14921 #endif
14922 #ifdef KHICAS
14923 if ((size_t) _REALptr > stackptr)
14924 ctrl_c=interrupted=true;
14925 #endif
14926 type = _REAL;
14927 subtype=0;
14928 #ifdef NO_RTTI
14929 real_interval * ptr=0;
14930 #else
14931 real_interval * ptr=dynamic_cast<real_interval *>(_REALptr);
14932 #endif
14933 #ifdef HAVE_LIBMPFR
14934 mpfr_set_prec(ptr->inf,mpfr_get_prec(g.inf));
14935 mpfr_set(ptr->inf,g.inf,MPFR_RNDN);
14936 #else
14937 mpf_set(ptr->inf,g.inf);
14938 #endif
14939 #ifdef HAVE_LIBMPFI
14940 int nbits=mpfi_get_prec(g.infsup);
14941 mpfi_set_prec(ptr->infsup,nbits);
14942 mpfi_set(ptr->infsup,g.infsup);
14943 #else
14944 #ifdef HAVE_LIBMPFR
14945 mpfr_set(ptr->sup,g.sup,MPFR_RNDN);
14946 #else
14947 mpf_set(ptr->sup,g.sup);
14948 #endif
14949 #endif
14950 }
14951
evalf_double() const14952 double real_object::evalf_double() const{
14953 #ifdef HAVE_LIBMPFR
14954 return mpfr_get_d(inf,MPFR_RNDN);
14955 #else
14956 return mpf_get_d(inf);
14957 #endif
14958 }
14959
addition(const gen & g,GIAC_CONTEXT) const14960 gen real_object::addition (const gen & g,GIAC_CONTEXT) const{
14961 switch (g.type){
14962 case _REAL:
14963 return *this+*g._REALptr;
14964 case _CPLX:
14965 return gen(this->addition(*g._CPLXptr,contextptr),*(g._CPLXptr+1));
14966 case _FRAC:
14967 if (!is_integer(g._FRACptr->num) || !is_integer(g._FRACptr->den))
14968 return sym_add(*this,g,contextptr);
14969 case _INT_: case _DOUBLE_: case _ZINT:
14970 #ifdef HAVE_LIBMPFR
14971 return *this+real_object(g,mpfr_get_prec(inf));
14972 #else
14973 return *this+real_object(g);
14974 #endif
14975 default:
14976 return sym_add(*this,g,contextptr);
14977 }
14978 return gensizeerr(gettext("real_object + gen")+this->print(contextptr)+","+g.print(contextptr));
14979 }
14980
addition(const gen & g,GIAC_CONTEXT) const14981 gen real_interval::addition (const gen & g,GIAC_CONTEXT) const{
14982 switch (g.type){
14983 case _REAL:
14984 return *this+*g._REALptr;
14985 case _CPLX:
14986 return gen(this->addition(*g._CPLXptr,contextptr),*(g._CPLXptr+1));
14987 case _FRAC:
14988 if (!is_integer(g._FRACptr->num) || !is_integer(g._FRACptr->den))
14989 return sym_add(*this,g,contextptr);
14990 case _INT_: case _DOUBLE_: case _ZINT:
14991 #ifdef HAVE_LIBMPFR
14992 return *this+real_object(g,mpfr_get_prec(inf));
14993 #else
14994 return *this+real_object(g);
14995 #endif
14996 default:
14997 return sym_add(*this,g,contextptr);
14998 }
14999 return gensizeerr(gettext("real_object + gen")+this->print(contextptr)+","+g.print(contextptr));
15000 }
15001
operator +(const gen & g) const15002 gen real_object::operator + (const gen & g) const{
15003 return addition(g,context0);
15004 }
15005
add(const real_interval & i,const real_interval & g)15006 static real_interval add(const real_interval & i,const real_interval & g){
15007 real_interval res(i);
15008 #ifdef HAVE_LIBMPFR
15009 mpfr_add(res.inf,i.inf,g.inf,MPFR_RNDD);
15010 #ifdef HAVE_LIBMPFI
15011 mpfi_add(res.infsup,i.infsup,g.infsup);
15012 #else
15013 mpfr_add(res.sup,i.sup,g.sup,MPFR_RNDU);
15014 #endif
15015 #else // HAVE_LIBMPFR
15016 mpf_add(res.inf,i.inf,g.inf);
15017 #ifdef HAVE_LIBMPFI
15018 mpfi_add(res.infsup,i.infsup,g.infsup);
15019 #else
15020 mpf_add(res.sup,i.sup,g.sup);
15021 #endif
15022 #endif // HAVE_LIBMPFR
15023 return res;
15024 }
15025
operator +(const real_interval & g) const15026 real_interval real_interval::operator + (const real_interval & g) const{
15027 return add(*this,g);
15028 }
15029
add(const real_interval & i,const real_object & g)15030 static real_interval add(const real_interval & i,const real_object & g){
15031 #ifdef NO_RTTI
15032 const real_interval * ptr=0;
15033 #else
15034 const real_interval * ptr=dynamic_cast<const real_interval *>(&g);
15035 #endif
15036 if (ptr)
15037 return add(i,*ptr);
15038 real_interval res(i);
15039 #ifdef HAVE_LIBMPFR
15040 mpfr_add(res.inf,i.inf,g.inf,MPFR_RNDD);
15041 #ifdef HAVE_LIBMPFI
15042 mpfi_add_fr(res.infsup,i.infsup,g.inf);
15043 #else
15044 mpfr_add(res.sup,i.sup,g.inf,MPFR_RNDU);
15045 #endif
15046 #else // HAVE_LIBMPFR
15047 mpf_add(res.inf,i.inf,g.inf);
15048 #ifdef HAVE_LIBMPFI
15049 mpfi_add_fr(res.infsup,i.infsup,g.inf);
15050 #else
15051 mpf_add(res.sup,i.sup,g.inf);
15052 #endif
15053 #endif // HAVE_LIBMPFR
15054 return res;
15055 }
15056
operator +(const real_object & g) const15057 gen real_interval::operator + (const real_object & g) const{
15058 return add(*this,g);
15059 }
15060
operator +(const real_object & g) const15061 gen real_object::operator + (const real_object & g) const{
15062 #ifdef NO_RTTI
15063 const real_interval * ptr=0;
15064 #else
15065 const real_interval * ptr=dynamic_cast<const real_interval *>(&g);
15066 #endif
15067 if (ptr)
15068 return add(*ptr,*this);
15069 #ifdef HAVE_LIBMPFR
15070 mpfr_t sum;
15071 mpfr_init2(sum,giacmin(mpfr_get_prec(this->inf),mpfr_get_prec(g.inf)));
15072 mpfr_add(sum,this->inf,g.inf,MPFR_RNDN);
15073 real_object res(sum);
15074 mpfr_clear(sum);
15075 #else
15076 mpf_t sum;
15077 mpf_init(sum);
15078 mpf_add(sum,this->inf,g.inf);
15079 #ifdef LONGFLOAT_DOUBLE
15080 real_object res; res.inf=sum;
15081 #else
15082 real_object res(sum);
15083 #endif
15084 mpf_clear(sum);
15085 #endif
15086 return res;
15087 }
15088
substract(const gen & g,GIAC_CONTEXT) const15089 gen real_object::substract (const gen & g,GIAC_CONTEXT) const{
15090 switch (g.type){
15091 case _REAL:
15092 return *this-*g._REALptr;
15093 case _FRAC:
15094 if (!is_integer(g._FRACptr->num) || !is_integer(g._FRACptr->den))
15095 return sym_sub(*this,g,contextptr);
15096 case _INT_: case _DOUBLE_: case _ZINT:
15097 #ifdef HAVE_LIBMPFR
15098 return *this - real_object(g,mpfr_get_prec(inf));
15099 #else
15100 return *this - real_object(g);
15101 #endif
15102 default:
15103 return sym_sub(*this,g,contextptr);
15104 }
15105 return gensizeerr(gettext("real_object + gen")+this->print(contextptr)+","+g.print(contextptr));
15106 }
15107
substract(const gen & g,GIAC_CONTEXT) const15108 gen real_interval::substract (const gen & g,GIAC_CONTEXT) const{
15109 switch (g.type){
15110 case _REAL:
15111 return *this-*g._REALptr;
15112 case _FRAC:
15113 if (!is_integer(g._FRACptr->num) || !is_integer(g._FRACptr->den))
15114 return sym_sub(*this,g,contextptr);
15115 case _INT_: case _DOUBLE_: case _ZINT:
15116 #ifdef HAVE_LIBMPFR
15117 return *this - real_object(g,mpfr_get_prec(inf));
15118 #else
15119 return *this - real_object(g);
15120 #endif
15121 default:
15122 return sym_sub(*this,g,contextptr);
15123 }
15124 return gensizeerr(gettext("real_object + gen")+this->print(contextptr)+","+g.print(contextptr));
15125 }
15126
operator -(const gen & g) const15127 gen real_object::operator - (const gen & g) const{
15128 return substract(g,context0);
15129 }
15130
sub(const real_interval & i,const real_interval & g)15131 static real_interval sub(const real_interval & i,const real_interval & g){
15132 real_interval res(i);
15133 #ifdef HAVE_LIBMPFI
15134 mpfi_sub(res.infsup,i.infsup,g.infsup);
15135 mpfr_sub(res.inf,i.inf,g.inf,MPFR_RNDD);
15136 #else
15137 #ifdef HAVE_LIBMPFR
15138 mpfr_sub(res.inf,i.sup,g.inf,MPFR_RNDD);
15139 mpfr_sub(res.sup,i.inf,g.sup,MPFR_RNDU);
15140 #else
15141 mpf_sub(res.inf,i.sup,g.inf);
15142 mpf_sub(res.sup,i.inf,g.sup);
15143 #endif
15144 #endif
15145 return res;
15146 }
15147
operator -(const real_interval & g) const15148 real_interval real_interval::operator - (const real_interval & g) const{
15149 return sub(*this,g);
15150 }
15151
sub(const real_interval & i,const real_object & g)15152 static real_interval sub(const real_interval & i,const real_object & g){
15153 #ifdef NO_RTTI
15154 const real_interval * ptr=0;
15155 #else
15156 const real_interval * ptr=dynamic_cast<const real_interval *>(&g);
15157 #endif
15158 if (ptr)
15159 return sub(i,*ptr);
15160 real_interval res(i);
15161 #ifdef HAVE_LIBMPFI
15162 mpfi_sub_fr(res.infsup,i.infsup,g.inf);
15163 mpfr_sub(res.inf,i.inf,g.inf,MPFR_RNDD);
15164 #else
15165 #ifdef HAVE_LIBMPFR
15166 mpfr_sub(res.inf,i.sup,g.inf,MPFR_RNDD);
15167 mpfr_sub(res.sup,i.inf,g.inf,MPFR_RNDU);
15168 #else
15169 mpf_sub(res.inf,i.sup,g.inf);
15170 mpf_sub(res.sup,i.inf,g.inf);
15171 #endif
15172 #endif
15173 return res;
15174 }
15175
operator -(const real_object & g) const15176 gen real_interval::operator - (const real_object & g) const{
15177 return sub(*this,g);
15178 }
15179
operator -(const real_object & g) const15180 gen real_object::operator - (const real_object & g) const{
15181 #ifdef NO_RTTI
15182 const real_interval * ptr=0;
15183 #else
15184 const real_interval * ptr=dynamic_cast<const real_interval *>(&g);
15185 #endif
15186 if (ptr)
15187 return -(*ptr)+(*this);
15188 #ifdef HAVE_LIBMPFR
15189 mpfr_t sum;
15190 mpfr_init2(sum,giacmin(mpfr_get_prec(this->inf),mpfr_get_prec(g.inf)));
15191 mpfr_sub(sum,this->inf,g.inf,MPFR_RNDN);
15192 real_object res(sum);
15193 mpfr_clear(sum);
15194 #else
15195 mpf_t sum;
15196 mpf_init(sum);
15197 mpf_sub(sum,this->inf,g.inf);
15198 #ifdef LONGFLOAT_DOUBLE
15199 real_object res; res.inf=sum;
15200 #else
15201 real_object res(sum);
15202 #endif
15203 mpf_clear(sum);
15204 #endif
15205 return res;
15206 }
15207
operator -() const15208 gen real_object::operator -() const {
15209 #ifdef NO_RTTI
15210 const real_interval * ptr=0;
15211 #else
15212 const real_interval * ptr=dynamic_cast<const real_interval *>(this);
15213 #endif
15214 if (ptr)
15215 return -*ptr;
15216 real_object res(*this);
15217 #ifdef HAVE_LIBMPFR
15218 mpfr_neg(res.inf,res.inf,MPFR_RNDN);
15219 #else
15220 mpf_neg(res.inf,res.inf);
15221 #endif
15222 return res;
15223 }
15224
inv() const15225 gen real_object::inv() const {
15226 real_object res(*this);
15227 #ifdef HAVE_LIBMPFR
15228 mpfr_ui_div(res.inf,1,res.inf,MPFR_RNDN);
15229 #else
15230 mpf_ui_div(res.inf,1,res.inf);
15231 #endif
15232 return res;
15233 }
15234
sqrt() const15235 gen real_object::sqrt() const {
15236 #ifdef LONGFLOAT_DOUBLE
15237 real_object res; res.inf=std::sqrt(inf); return res;
15238 #else
15239 real_object res(*this);
15240 #ifdef HAVE_LIBMPFR
15241 mpfr_sqrt(res.inf,res.inf,MPFR_RNDN);
15242 #else
15243 mpf_sqrt(res.inf,res.inf);
15244 #endif
15245 return res;
15246 #endif
15247 }
15248
abs() const15249 gen real_object::abs() const {
15250 #ifdef HAVE_LIBMPFR
15251 if (mpfr_sgn(inf)>=0)
15252 #else
15253 if (mpf_sgn(inf)>=0)
15254 #endif
15255 return *this;
15256 return -(*this);
15257 }
15258
15259 #ifndef HAVE_LIBMPFR
compile_with_mpfr()15260 static void compile_with_mpfr(){
15261 setsizeerr(gettext("Compile with MPFR or USE_GMP_REPLACEMENTS if you want transcendental long float support"));
15262 }
15263 #endif
15264
exp() const15265 gen real_object::exp() const {
15266 real_object res(*this);
15267 #ifdef USE_GMP_REPLACEMENTS
15268 #ifdef LONGFLOAT_DOUBLE
15269 res.inf=std::exp(res.inf);
15270 #else
15271 *res.inf = ::exp(*res.inf);
15272 #endif
15273 #else
15274 #ifdef HAVE_LIBMPFR
15275 mpfr_exp(res.inf,res.inf,MPFR_RNDN);
15276 #else
15277 compile_with_mpfr();
15278 #endif
15279 #endif // USE_GMP_REPLACEMENTS
15280 return res;
15281 }
15282
log() const15283 gen real_object::log() const {
15284 real_object res(*this);
15285 #ifdef USE_GMP_REPLACEMENTS
15286 #ifdef LONGFLOAT_DOUBLE
15287 res.inf=std::log(res.inf);
15288 #else
15289 *res.inf = ::log(*res.inf);
15290 #endif
15291 #else
15292 #ifdef HAVE_LIBMPFR
15293 mpfr_log(res.inf,res.inf,MPFR_RNDN);
15294 #else
15295 compile_with_mpfr();
15296 #endif
15297 #endif
15298 return res;
15299 }
15300
sin() const15301 gen real_object::sin() const {
15302 real_object res(*this);
15303 #ifdef USE_GMP_REPLACEMENTS
15304 #ifdef LONGFLOAT_DOUBLE
15305 res.inf=std::sin(res.inf);
15306 #else
15307 *res.inf = ::sin(*res.inf);
15308 #endif
15309 #else
15310 #ifdef HAVE_LIBMPFR
15311 mpfr_sin(res.inf,res.inf,MPFR_RNDN);
15312 #else
15313 compile_with_mpfr();
15314 #endif
15315 #endif
15316 return res;
15317 }
15318
cos() const15319 gen real_object::cos() const {
15320 real_object res(*this);
15321 #ifdef USE_GMP_REPLACEMENTS
15322 #ifdef LONGFLOAT_DOUBLE
15323 res.inf=std::cos(res.inf);
15324 #else
15325 *res.inf = ::cos(*res.inf);
15326 #endif
15327 #else
15328 #ifdef HAVE_LIBMPFR
15329 mpfr_cos(res.inf,res.inf,MPFR_RNDN);
15330 #else
15331 compile_with_mpfr();
15332 #endif
15333 #endif
15334 return res;
15335 }
15336
tan() const15337 gen real_object::tan() const {
15338 real_object res(*this);
15339 #ifdef USE_GMP_REPLACEMENTS
15340 #ifdef LONGFLOAT_DOUBLE
15341 res.inf=std::tan(res.inf);
15342 #else
15343 *res.inf = ::tan(*res.inf);
15344 #endif
15345 #else
15346 #ifdef HAVE_LIBMPFR
15347 mpfr_tan(res.inf,res.inf,MPFR_RNDN);
15348 #else
15349 compile_with_mpfr();
15350 #endif
15351 #endif
15352 return res;
15353 }
15354
sinh() const15355 gen real_object::sinh() const {
15356 real_object res(*this);
15357 #ifdef USE_GMP_REPLACEMENTS
15358 #ifdef LONGFLOAT_DOUBLE
15359 res.inf=std::sinh(res.inf);
15360 #else
15361 *res.inf = ::sinh(*res.inf);
15362 #endif
15363 #else
15364 #ifdef HAVE_LIBMPFR
15365 mpfr_sinh(res.inf,res.inf,MPFR_RNDN);
15366 #else
15367 compile_with_mpfr();
15368 #endif
15369 #endif
15370 return res;
15371 }
15372
cosh() const15373 gen real_object::cosh() const {
15374 real_object res(*this);
15375 #ifdef USE_GMP_REPLACEMENTS
15376 #ifdef LONGFLOAT_DOUBLE
15377 res.inf=std::cosh(res.inf);
15378 #else
15379 *res.inf = ::cosh(*res.inf);
15380 #endif
15381 #else
15382 #ifdef HAVE_LIBMPFR
15383 mpfr_cosh(res.inf,res.inf,MPFR_RNDN);
15384 #else
15385 compile_with_mpfr();
15386 #endif
15387 #endif
15388 return res;
15389 }
15390
tanh() const15391 gen real_object::tanh() const {
15392 real_object res(*this);
15393 #ifdef USE_GMP_REPLACEMENTS
15394 #ifdef LONGFLOAT_DOUBLE
15395 res.inf=std::tanh(res.inf);
15396 #else
15397 *res.inf = ::tanh(*res.inf);
15398 #endif
15399 #else
15400 #ifdef HAVE_LIBMPFR
15401 mpfr_tanh(res.inf,res.inf,MPFR_RNDN);
15402 #else
15403 compile_with_mpfr();
15404 #endif
15405 #endif
15406 return res;
15407 }
15408
asin() const15409 gen real_object::asin() const {
15410 real_object res(*this);
15411 #ifdef USE_GMP_REPLACEMENTS
15412 #ifdef LONGFLOAT_DOUBLE
15413 res.inf=std::asin(res.inf);
15414 #else
15415 *res.inf = ::asin(*res.inf);
15416 #endif
15417 #else
15418 #ifdef HAVE_LIBMPFR
15419 mpfr_asin(res.inf,res.inf,MPFR_RNDN);
15420 #else
15421 compile_with_mpfr();
15422 #endif
15423 #endif
15424 return res;
15425 }
15426
acos() const15427 gen real_object::acos() const {
15428 real_object res(*this);
15429 #ifdef USE_GMP_REPLACEMENTS
15430 #ifdef LONGFLOAT_DOUBLE
15431 res.inf=std::acos(res.inf);
15432 #else
15433 *res.inf = ::acos(*res.inf);
15434 #endif
15435 #else
15436 #ifdef HAVE_LIBMPFR
15437 mpfr_acos(res.inf,res.inf,MPFR_RNDN);
15438 #else
15439 compile_with_mpfr();
15440 #endif
15441 #endif
15442 return res;
15443 }
15444
atan() const15445 gen real_object::atan() const {
15446 real_object res(*this);
15447 #ifdef USE_GMP_REPLACEMENTS
15448 #ifdef LONGFLOAT_DOUBLE
15449 res.inf=std::atan(res.inf);
15450 #else
15451 *res.inf = ::atan(*res.inf);
15452 #endif
15453 #else
15454 #ifdef HAVE_LIBMPFR
15455 mpfr_atan(res.inf,res.inf,MPFR_RNDN);
15456 #else
15457 compile_with_mpfr();
15458 #endif
15459 #endif
15460 return res;
15461 }
15462
asinh() const15463 gen real_object::asinh() const {
15464 real_object res(*this);
15465 #ifdef USE_GMP_REPLACEMENTS
15466 #ifdef LONGFLOAT_DOUBLE
15467 res.inf= std::log(res.inf+std::sqrt(res.inf*res.inf+1));
15468 #else
15469 *res.inf = ::asinh(*res.inf);
15470 #endif
15471 #else
15472 #ifdef HAVE_LIBMPFR
15473 mpfr_asinh(res.inf,res.inf,MPFR_RNDN);
15474 #else
15475 compile_with_mpfr();
15476 #endif
15477 #endif
15478 return res;
15479 }
15480
acosh() const15481 gen real_object::acosh() const {
15482 real_object res(*this);
15483 #ifdef USE_GMP_REPLACEMENTS
15484 #ifdef LONGFLOAT_DOUBLE
15485 res.inf=std::log(res.inf+std::sqrt(res.inf+1)*std::sqrt(res.inf-1));
15486 #else
15487 *res.inf = ::acosh(*res.inf);
15488 #endif
15489 #else
15490 #ifdef HAVE_LIBMPFR
15491 mpfr_acosh(res.inf,res.inf,MPFR_RNDN);
15492 #else
15493 compile_with_mpfr();
15494 #endif
15495 #endif
15496 return res;
15497 }
15498
atanh() const15499 gen real_object::atanh() const {
15500 real_object res(*this);
15501 #ifdef USE_GMP_REPLACEMENTS
15502 #ifdef LONGFLOAT_DOUBLE
15503 res.inf=std::log((1+res.inf)/(1-res.inf))/2;
15504 #else
15505 *res.inf = ::atanh(*res.inf);
15506 #endif
15507 #else
15508 #ifdef HAVE_LIBMPFR
15509 mpfr_atanh(res.inf,res.inf,MPFR_RNDN);
15510 #else
15511 compile_with_mpfr();
15512 #endif
15513 #endif
15514 return res;
15515 }
15516
operator -() const15517 gen real_interval::operator -() const {
15518 real_interval res(*this);
15519 #ifdef HAVE_LIBMPFR
15520 mpfr_neg(res.inf,res.inf,MPFR_RNDU);
15521 #ifdef HAVE_LIBMPFI
15522 mpfi_neg(res.infsup,res.infsup);
15523 #else
15524 mpfr_neg(res.sup,res.sup,MPFR_RNDD);
15525 mpfr_swap(res.inf,res.sup);
15526 #endif
15527 #else // MPFR
15528 mpf_neg(res.inf,res.inf);
15529 #ifdef HAVE_LIBMPFI
15530 mpfi_neg(res.infsup,res.infsup);
15531 #else
15532 mpf_neg(res.sup,res.sup);
15533 #ifdef mpf_swap
15534 mpf_swap(res.inf,res.sup);
15535 #endif
15536 #endif
15537 #endif // MPFR
15538 return res;
15539 }
15540
inv() const15541 gen real_interval::inv() const {
15542 real_interval res(*this);
15543 #ifdef HAVE_LIBMPFI
15544 mpfi_ui_div(res.infsup,1,res.infsup);
15545 mpfr_ui_div(res.inf,1,res.inf,MPFR_RNDD);
15546 #else
15547 // FIXME check sign
15548 #ifndef NO_STDEXCEPT
15549 setsizeerr(gettext("real_interval inv"));
15550 #endif
15551 /* mpf_neg(res.inf,res.inf);
15552 mpf_neg(res.sup,res.sup);
15553 mpf_swap(res.inf,res.sup); */
15554 #endif
15555 return res;
15556 }
15557
sqrt() const15558 gen real_interval::sqrt() const {
15559 real_interval res(*this);
15560 #ifdef HAVE_LIBMPFI
15561 mpfi_sqrt(res.infsup,res.infsup);
15562 mpfr_sqrt(res.inf,res.inf,MPFR_RNDD);
15563 return res;
15564 #else
15565 return gensizeerr(gettext("real_interval sqrt"));
15566 #endif
15567 }
15568
abs() const15569 gen real_interval::abs() const {
15570 real_interval res(*this);
15571 #ifdef HAVE_LIBMPFI
15572 mpfi_abs(res.infsup,res.infsup);
15573 mpfr_abs(res.inf,res.inf,MPFR_RNDD);
15574 return res;
15575 #else
15576 return gensizeerr(gettext("real_interval abs"));
15577 #endif
15578 }
15579
exp() const15580 gen real_interval::exp() const {
15581 real_interval res(*this);
15582 #ifdef HAVE_LIBMPFI
15583 mpfi_exp(res.infsup,res.infsup);
15584 mpfr_exp(res.inf,res.inf,MPFR_RNDD);
15585 return res;
15586 #else
15587 return gensizeerr(gettext("real_interval sqrt"));
15588 #endif
15589 }
15590
log() const15591 gen real_interval::log() const {
15592 real_interval res(*this);
15593 #ifdef HAVE_LIBMPFI
15594 mpfi_log(res.infsup,res.infsup);
15595 mpfr_log(res.inf,res.inf,MPFR_RNDD);
15596 return res;
15597 #else
15598 return gensizeerr(gettext("real_interval sqrt"));
15599 #endif
15600 }
15601
sin() const15602 gen real_interval::sin() const {
15603 real_interval res(*this);
15604 #ifdef HAVE_LIBMPFI
15605 mpfi_sin(res.infsup,res.infsup);
15606 mpfr_sin(res.inf,res.inf,MPFR_RNDD);
15607 return res;
15608 #else
15609 return gensizeerr(gettext("real_interval sqrt"));
15610 #endif
15611 }
15612
cos() const15613 gen real_interval::cos() const {
15614 real_interval res(*this);
15615 #ifdef HAVE_LIBMPFI
15616 mpfi_cos(res.infsup,res.infsup);
15617 mpfr_cos(res.inf,res.inf,MPFR_RNDD);
15618 return res;
15619 #else
15620 return gensizeerr(gettext("real_interval sqrt"));
15621 #endif
15622 }
15623
tan() const15624 gen real_interval::tan() const {
15625 real_interval res(*this);
15626 #ifdef HAVE_LIBMPFI
15627 mpfi_tan(res.infsup,res.infsup);
15628 mpfr_tan(res.inf,res.inf,MPFR_RNDD);
15629 return res;
15630 #else
15631 return gensizeerr(gettext("real_interval sqrt"));
15632 #endif
15633 }
15634
sinh() const15635 gen real_interval::sinh() const {
15636 real_interval res(*this);
15637 #ifdef HAVE_LIBMPFI
15638 mpfi_sinh(res.infsup,res.infsup);
15639 mpfr_sinh(res.inf,res.inf,MPFR_RNDD);
15640 return res;
15641 #else
15642 return gensizeerr(gettext("real_interval sqrt"));
15643 #endif
15644 }
15645
cosh() const15646 gen real_interval::cosh() const {
15647 real_interval res(*this);
15648 #ifdef HAVE_LIBMPFI
15649 mpfi_cosh(res.infsup,res.infsup);
15650 mpfr_cosh(res.inf,res.inf,MPFR_RNDD);
15651 return res;
15652 #else
15653 return gensizeerr(gettext("real_interval sqrt"));
15654 #endif
15655 }
15656
tanh() const15657 gen real_interval::tanh() const {
15658 real_interval res(*this);
15659 #ifdef HAVE_LIBMPFI
15660 mpfi_tanh(res.infsup,res.infsup);
15661 mpfr_tanh(res.inf,res.inf,MPFR_RNDD);
15662 return res;
15663 #else
15664 return gensizeerr(gettext("real_interval sqrt"));
15665 #endif
15666 }
15667
asin() const15668 gen real_interval::asin() const {
15669 real_interval res(*this);
15670 #ifdef HAVE_LIBMPFI
15671 mpfi_asin(res.infsup,res.infsup);
15672 mpfr_asin(res.inf,res.inf,MPFR_RNDD);
15673 return res;
15674 #else
15675 return gensizeerr(gettext("real_interval sqrt"));
15676 #endif
15677 }
15678
acos() const15679 gen real_interval::acos() const {
15680 real_interval res(*this);
15681 #ifdef HAVE_LIBMPFI
15682 mpfi_acos(res.infsup,res.infsup);
15683 mpfr_acos(res.inf,res.inf,MPFR_RNDD);
15684 return res;
15685 #else
15686 return gensizeerr(gettext("real_interval sqrt"));
15687 #endif
15688 }
15689
atan() const15690 gen real_interval::atan() const {
15691 real_interval res(*this);
15692 #ifdef HAVE_LIBMPFI
15693 mpfi_atan(res.infsup,res.infsup);
15694 mpfr_atan(res.inf,res.inf,MPFR_RNDD);
15695 return res;
15696 #else
15697 return gensizeerr(gettext("real_interval sqrt"));
15698 #endif
15699 }
15700
asinh() const15701 gen real_interval::asinh() const {
15702 real_interval res(*this);
15703 #ifdef HAVE_LIBMPFI
15704 mpfi_asinh(res.infsup,res.infsup);
15705 mpfr_asinh(res.inf,res.inf,MPFR_RNDD);
15706 return res;
15707 #else
15708 return gensizeerr(gettext("real_interval sqrt"));
15709 #endif
15710 }
15711
acosh() const15712 gen real_interval::acosh() const {
15713 real_interval res(*this);
15714 #ifdef HAVE_LIBMPFI
15715 mpfi_acosh(res.infsup,res.infsup);
15716 mpfr_acosh(res.inf,res.inf,MPFR_RNDD);
15717 return res;
15718 #else
15719 return gensizeerr(gettext("real_interval sqrt"));
15720 #endif
15721 }
15722
atanh() const15723 gen real_interval::atanh() const {
15724 real_interval res(*this);
15725 #ifdef HAVE_LIBMPFI
15726 mpfi_atanh(res.infsup,res.infsup);
15727 mpfr_atanh(res.inf,res.inf,MPFR_RNDD);
15728 return res;
15729 #else
15730 return gensizeerr(gettext("real_interval sqrt"));
15731 #endif
15732 }
15733
multiply(const gen & g,GIAC_CONTEXT) const15734 gen real_object::multiply (const gen & g,GIAC_CONTEXT) const{
15735 switch (g.type){
15736 case _REAL:
15737 return *this * *g._REALptr;
15738 case _CPLX:
15739 return gen(this->multiply(*g._CPLXptr,contextptr),this->multiply(*(g._CPLXptr+1),contextptr));
15740 case _FRAC:
15741 if (!is_integer(g._FRACptr->num) || !is_integer(g._FRACptr->den))
15742 return sym_mult(*this,g,contextptr);
15743 case _INT_: case _DOUBLE_: case _ZINT:
15744 #ifdef HAVE_LIBMPFR
15745 return *this * real_object(g,mpfr_get_prec(inf));
15746 #else
15747 return *this * real_object(g);
15748 #endif
15749 default:
15750 return sym_mult(*this,g,contextptr);
15751 }
15752 }
15753
multiply(const gen & g,GIAC_CONTEXT) const15754 gen real_interval::multiply (const gen & g,GIAC_CONTEXT) const{
15755 switch (g.type){
15756 case _REAL:
15757 return *this * *g._REALptr;
15758 case _CPLX:
15759 return gen(this->multiply(*g._CPLXptr,contextptr),this->multiply(*(g._CPLXptr+1),contextptr));
15760 case _FRAC:
15761 if (!is_integer(g._FRACptr->num) || !is_integer(g._FRACptr->den))
15762 return sym_mult(*this,g,contextptr);
15763 case _INT_: case _DOUBLE_: case _ZINT:
15764 #ifdef HAVE_LIBMPFR
15765 return *this * real_object(g,mpfr_get_prec(inf));
15766 #else
15767 return *this * real_object(g);
15768 #endif
15769 default:
15770 return sym_mult(*this,g,contextptr);
15771 }
15772 }
15773
operator *(const gen & g) const15774 gen real_object::operator * (const gen & g) const{
15775 return multiply(g,context0);
15776 }
15777
operator /(const gen & g) const15778 gen real_object::operator / (const gen & g) const{
15779 return *this * g.inverse(context0);
15780 }
15781
divide(const gen & g,GIAC_CONTEXT) const15782 gen real_object::divide (const gen & g,GIAC_CONTEXT) const{
15783 return multiply(g.inverse(contextptr),contextptr);
15784 }
15785
divide(const gen & g,GIAC_CONTEXT) const15786 gen real_interval::divide (const gen & g,GIAC_CONTEXT) const{
15787 return multiply(g.inverse(contextptr),contextptr);
15788 }
15789
operator /(const real_object & g) const15790 gen real_object::operator / (const real_object & g) const{
15791 return *this * g.inv();
15792 }
15793
mul(const real_interval & i,const real_interval & g)15794 static real_interval mul(const real_interval & i,const real_interval & g){
15795 real_interval res(i);
15796 #ifdef HAVE_LIBMPFR
15797 mpfr_mul(res.inf,i.inf,g.inf,MPFR_RNDN);
15798 #else
15799 mpf_mul(res.inf,i.inf,g.inf);
15800 #endif
15801 #ifdef HAVE_LIBMPFI
15802 mpfi_mul(res.infsup,i.infsup,g.infsup);
15803 #else
15804 // FIXME: should check signs for interval arithmetic!!
15805 #ifndef NO_STDEXCEPT
15806 setsizeerr(gettext("real_interval mul"));
15807 #endif
15808 // mpf_mul(res.sup,i.sup,g.sup);
15809 #endif
15810 return res;
15811 }
15812
operator *(const real_interval & g) const15813 real_interval real_interval::operator * (const real_interval & g) const{
15814 return mul(*this,g);
15815 }
15816
mul(const real_interval & i,const real_object & g)15817 static real_interval mul(const real_interval & i,const real_object & g){
15818 #ifdef NO_RTTI
15819 const real_interval * ptr=0;
15820 #else
15821 const real_interval * ptr=dynamic_cast<const real_interval *>(&g);
15822 #endif
15823 if (ptr)
15824 return mul(i,*ptr);
15825 real_interval res(i);
15826 #ifdef HAVE_LIBMPFR
15827 mpfr_mul(res.inf,i.inf,g.inf,MPFR_RNDN);
15828 #else
15829 mpf_mul(res.inf,i.inf,g.inf);
15830 #endif
15831 #ifdef HAVE_LIBMPFI
15832 mpfi_mul_fr(res.infsup,i.infsup,g.inf);
15833 #else
15834 // FIXME: should check signs for interval arithmetic!!
15835 #ifndef NO_STDEXCEPT
15836 setsizeerr(gettext("real_interval mul 2"));
15837 #endif
15838 // mpf_mul(res.sup,i.sup,g.inf);
15839 #endif
15840 return res;
15841 }
15842
operator *(const real_object & g) const15843 gen real_interval::operator * (const real_object & g) const{
15844 return mul(*this,g);
15845 }
15846
operator *(const real_object & g) const15847 gen real_object::operator * (const real_object & g) const{
15848 #ifdef NO_RTTI
15849 const real_interval * ptr=0;
15850 #else
15851 const real_interval * ptr=dynamic_cast<const real_interval *>(&g);
15852 #endif
15853 if (ptr)
15854 return mul(*ptr,*this);
15855 #ifdef HAVE_LIBMPFR
15856 mpfr_t sum;
15857 mpfr_init2(sum,giacmin(mpfr_get_prec(this->inf),mpfr_get_prec(g.inf)));
15858 mpfr_mul(sum,this->inf,g.inf,MPFR_RNDN);
15859 real_object res(sum);
15860 mpfr_clear(sum);
15861 #else
15862 mpf_t sum;
15863 mpf_init(sum);
15864 mpf_mul(sum,this->inf,g.inf);
15865 #ifdef LONGFLOAT_DOUBLE
15866 real_object res; res.inf=sum;
15867 #else
15868 real_object res(sum);
15869 #endif
15870 mpf_clear(sum);
15871 #endif
15872 return res;
15873 }
15874
is_positive() const15875 int real_object::is_positive() const{
15876 #ifdef HAVE_LIBMPFR
15877 return mpfr_sgn(inf);
15878 #else
15879 return mpf_sgn(inf);
15880 #endif
15881 }
15882
is_positive() const15883 int real_interval::is_positive() const{
15884 #ifdef HAVE_LIBMPFI
15885 if (mpfi_is_zero(infsup)>0)
15886 return 0;
15887 if (mpfi_is_pos(infsup))
15888 return 1;
15889 if (mpfi_is_nonpos(infsup))
15890 return -1;
15891 return 0;
15892 #else
15893 #ifdef HAVE_LIBMPFR
15894 return mpfr_sgn(inf);
15895 #else
15896 return mpf_sgn(inf);
15897 #endif
15898 #endif
15899 }
15900
print_binary(const real_object & r)15901 string print_binary(const real_object & r){
15902 #ifdef HAVE_LIBMPFR
15903 mp_exp_t expo;
15904 int dd=mpfr_get_prec(r.inf);
15905 #ifdef VISUALC
15906 char * ptr=new char[dd+2];
15907 #else
15908 char ptr[dd+2];
15909 #endif
15910 if (!mpfr_get_str(ptr,&expo,2,dd,r.inf,MPFR_RNDN) || !(*ptr))
15911 return "MPFR print binary error "+r.print(context0);
15912 string res;
15913 if (ptr[0]=='-')
15914 res="-0000."+string(ptr+1);
15915 else
15916 res="0000."+string(ptr);
15917 #ifdef VISUALC
15918 delete [] ptr;
15919 #endif // VISUALC
15920 return res+"E"+print_INT_(expo);
15921 #else // MPFR
15922 return "Error no MPFR printing "+r.print(context0);
15923 #endif
15924 }
15925
read_binary(const string & s,unsigned int precision)15926 gen read_binary(const string & s,unsigned int precision){
15927 #ifdef HAVE_LIBMPFR
15928 real_object r;
15929 mpfr_set_prec(r.inf,precision);
15930 #ifndef HAVE_MPFR_SET_STR_RAW
15931 // MPFR 2.2
15932 mpfr_strtofr (r.inf, (char *)s.c_str(), 0, 2, MPFR_RNDN);
15933 #else
15934 // FOR MPFR 2.0 use instead
15935 mpfr_set_str_raw(r.inf,(char *)s.c_str());
15936 #endif // GNUWINCE
15937 return r;
15938 return gensizeerr(gettext("MPFR error reading binary ")+s);
15939 #else // HAVE_LIBMPFR
15940 return gensizeerr(gettext("Error no MPFR reading ")+s);
15941 #endif // HAVE_LIBMPFR
15942 return undef;
15943 }
15944
print(GIAC_CONTEXT) const15945 std::string real_object::print(GIAC_CONTEXT) const{
15946 #if defined HAVE_LIBMPFI && !defined NO_RTTI
15947 if (const real_interval * ptr=dynamic_cast<const real_interval *>(this)){
15948 mpfr_t l,u;
15949 int nbits=mpfi_get_prec(ptr->infsup);
15950 mpfr_init2(l,nbits); mpfr_init2(u,nbits);
15951 mpfi_get_left(l,ptr->infsup); mpfi_get_right(u,ptr->infsup);
15952 real_object L(l),U(u);
15953 mpfr_clear(l); mpfr_clear(u);
15954 string s("[");
15955 s += L.print(contextptr);
15956 s += "..";
15957 s += U.print(contextptr);
15958 s += "]";
15959 return s;
15960 }
15961 #endif
15962 #ifdef HAVE_LIBMPFR
15963 if (mpfr_nan_p(inf))
15964 return "undef";
15965 bool negatif=mpfr_sgn(inf)<0;
15966 if (mpfr_inf_p(inf))
15967 return negatif?"-infinity":"+infinity";
15968 mp_exp_t expo;
15969 int dd=mpfr_get_prec(inf);
15970 #ifdef EMCC // workaround: mpfr_set_prec or get_prec has problems with emcc
15971 if (dd==53)
15972 dd=100;
15973 #endif
15974 dd=bits2digits(dd);
15975 dd--;
15976 #ifdef VISUALC
15977 char * ptr=new char[dd+2];
15978 #else
15979 char ptr[dd+2];
15980 #endif
15981 if (negatif){
15982 mpfr_t inf2;
15983 mpfr_init2(inf2,mpfr_get_prec(inf));
15984 mpfr_neg(inf2,inf,MPFR_RNDN);
15985 mpfr_get_str(ptr,&expo,10,dd,inf2,MPFR_RNDN);
15986 mpfr_clear(inf2);
15987 }
15988 else
15989 mpfr_get_str(ptr,&expo,10,dd,inf,MPFR_RNDN);
15990 std::string res(ptr);
15991 if (expo){
15992 if (expo==1){
15993 string reste(res.substr(1,res.size()-1));
15994 res=res[0]+("."+reste);
15995 }
15996 else {
15997 res = "0."+res;
15998 res += calc_mode(contextptr)==1?'E':'e';
15999 res += print_INT_(expo);
16000 }
16001 }
16002 else
16003 res="0."+res;
16004 #ifdef VISUALC
16005 delete [] ptr;
16006 #endif
16007 if (negatif)
16008 return "-"+res;
16009 else
16010 return res;
16011 #else
16012 return printmpf_t(inf,contextptr);
16013 #endif
16014 }
16015
is_zero() const16016 bool real_object::is_zero() const{
16017 #ifdef HAVE_LIBMPFR
16018 return !mpfr_sgn(inf);
16019 #else
16020 return mpf_sgn(inf)==0;
16021 #endif
16022 }
16023
maybe_zero() const16024 bool real_object::maybe_zero() const{
16025 #ifdef HAVE_LIBMPFR
16026 return !mpfr_sgn(inf);
16027 #else
16028 return mpf_sgn(inf)==0;
16029 #endif
16030 }
16031
is_zero() const16032 bool real_interval::is_zero() const {
16033 #ifdef HAVE_LIBMPFI
16034 return mpfi_is_zero(infsup);
16035 #else
16036 return real_object::is_zero();
16037 #endif
16038 }
16039
maybe_zero() const16040 bool real_interval::maybe_zero() const{
16041 #ifdef HAVE_LIBMPFI
16042 return mpfi_has_zero(infsup);
16043 #else
16044 return real_object::maybe_zero();
16045 #endif
16046 }
16047
is_inf() const16048 bool real_object::is_inf() const{
16049 #ifdef HAVE_LIBMPFR
16050 return !mpfr_inf_p(inf);
16051 #else
16052 #ifndef NO_STDEXCEPT
16053 setsizeerr();
16054 #endif
16055 return false;
16056 #endif
16057 }
16058
is_inf() const16059 bool real_interval::is_inf() const{
16060 #ifdef HAVE_LIBMPFI
16061 return !mpfi_inf_p(infsup);
16062 #else
16063 return real_object::is_inf();
16064 #endif
16065 }
16066
is_nan() const16067 bool real_object::is_nan() const{
16068 #ifdef HAVE_LIBMPFR
16069 return !mpfr_nan_p(inf);
16070 #else
16071 #ifndef NO_STDEXCEPT
16072 setsizeerr();
16073 #endif
16074 return false;
16075 #endif
16076 }
16077
is_nan() const16078 bool real_interval::is_nan() const{
16079 #ifdef HAVE_LIBMPFI
16080 return !mpfi_nan_p(infsup);
16081 #else
16082 return real_object::is_nan();
16083 #endif
16084 }
16085
iprotecteval(const gen & g,int level,GIAC_CONTEXT)16086 gen iprotecteval(const gen & g,int level,GIAC_CONTEXT){
16087 #ifdef KHICAS
16088 enable_back_interrupt();
16089 gen res=protecteval(g,level,contextptr);
16090 disable_back_interrupt();
16091 return res;
16092 #else
16093 return protecteval(g,level,contextptr);
16094 #endif
16095 }
16096
16097 #if 0 // def KHICAS
16098 #undef HAVE_LIBPTHREAD
16099 #endif
16100
16101 #ifdef HAVE_LIBPTHREAD
16102 struct caseval_param{
16103 const char * s;
16104 gen ans;
16105 context * contextptr;
16106 pthread_mutex_t mutex;
16107 };
thread_caseval(void * ptr_)16108 void * thread_caseval(void * ptr_){
16109 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
16110 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
16111 caseval_param * ptr=(caseval_param *)ptr_;
16112 pthread_mutex_lock(&ptr->mutex);
16113 gen g(ptr->s,ptr->contextptr);
16114 g=equaltosto(g,ptr->contextptr);
16115 ptr->ans=iprotecteval(g,1,ptr->contextptr);
16116 pthread_mutex_unlock(&ptr->mutex);
16117 return ptr;
16118 }
16119 #endif
16120
islogo(const gen & g)16121 bool islogo(const gen & g){
16122 if (g.type!=_VECT || g._VECTptr->empty()) return false;
16123 if (g.subtype==_LOGO__VECT) return true;
16124 const vecteur & v=*g._VECTptr;
16125 if (islogo(v.back()))
16126 return true;
16127 for (size_t i=0;i<v.size();++i){
16128 if (v[i].type==_VECT && v[i].subtype==_LOGO__VECT)
16129 return true;
16130 }
16131 return false;
16132 }
16133 #ifdef KHICAS
16134 extern logo_turtle * turtleptr;
16135 gen _efface_logo(const gen & g,GIAC_CONTEXT);
16136 #endif
16137
caseval(const char * s)16138 const char * caseval(const char *s){
16139 ctrl_c=interrupted=false;
16140 static string * sptr=0;
16141 if (!sptr) sptr=new string;
16142 string & S=*sptr;
16143 static context * contextptr=0;
16144 if (!contextptr) contextptr=new context;
16145 context & C=*contextptr;
16146 if (!strcmp(s,"shell off")){
16147 os_shell=false;
16148 return "shell off";
16149 }
16150 if (!strcmp(s,"warn off")){
16151 warn_symb_program_sto=false;
16152 return "warn off";
16153 }
16154 if (!strcmp(s,"shell on")){
16155 os_shell=true;
16156 return "shell on";
16157 }
16158 if (!strcmp(s,"warn on")){
16159 warn_symb_program_sto=true;
16160 return "warn on";
16161 }
16162 #ifdef KHICAS
16163 if (!turtleptr){
16164 turtle();
16165 _efface_logo(vecteur(0),contextptr);
16166 }
16167 #ifndef NSPIRE_NEWLIB
16168 if (!strcmp(s,"*")){
16169 int res=xcas::console_main(contextptr);
16170 S=printint(res);
16171 return S.c_str();
16172 }
16173 #endif
16174 if (!strcmp(s,"+")){
16175 char buf[4096]="def f(x):\n return x*x\n";
16176 if (file_exists("temp.py")){
16177 const char * ch=read_file("temp.py");
16178 S=ch;
16179 if (S.size()>sizeof(buf))
16180 S=S.substr(0,sizeof(buf)-1);
16181 strcpy(buf,S.c_str());
16182 }
16183 xcas::textedit(buf,sizeof(buf),contextptr);
16184 S=buf;
16185 return S.c_str();
16186 }
16187 if (!strcmp(s,"toolbox menu")){
16188 char buf[1024]="";
16189 showCatalog(buf,0,0,&C);
16190 drawRectangle(0,0,320,222,_WHITE);
16191 S=buf;
16192 return S.c_str();
16193 }
16194 if (!strcmp(s,"var menu")){
16195 gen g=select_var(contextptr);
16196 drawRectangle(0,0,320,222,_WHITE);
16197 S=g.type==_STRNG?*g._STRNGptr:g.print(contextptr);
16198 if (!strcmp(S.c_str(),"undef"))
16199 S="";
16200 return S.c_str();
16201 }
16202 if (!strcmp(s,".")){
16203 xcas::displaylogo();
16204 S=turtle_state(contextptr).print(&C);
16205 return S.c_str();
16206 }
16207 if (!strcmp(s,"..")){
16208 _efface_logo(vecteur(0),contextptr);
16209 return "turtle cleared";
16210 }
16211 #endif
16212 const char init[]="init geogebra";
16213 const char close[]="close geogebra";
16214 if (!strcmp(s,init)){
16215 init_geogebra(1,&C);
16216 return "geogebra mode on";
16217 }
16218 if (!strcmp(s,close)){
16219 init_geogebra(0,&C);
16220 return "geogebra mode off";
16221 }
16222 #ifdef TIMEOUT
16223 if (strlen(s)>8){
16224 string args(s);
16225 if (args.substr(0,8)=="timeout "){
16226 string t=args.substr(8,args.size()-8);
16227 double f=atof(t.c_str());
16228 if (f>=0 && f<24*60){
16229 caseval_maxtime=f;
16230 S="Max eval time set to "+gen(f).print();
16231 return S.c_str();
16232 }
16233 }
16234 if (args.substr(0,8)=="ckevery "){
16235 string t=args.substr(8,args.size()-8);
16236 int f=atoi(t.c_str());
16237 if (f>0 && f<1e6){
16238 caseval_mod=f;
16239 S="Check every "+gen(f).print();
16240 return S.c_str();
16241 }
16242 }
16243 }
16244 ctrl_c=false;
16245 interrupted=false;
16246 caseval_begin=time(0);
16247 #endif
16248 #ifdef HAVE_LIBPTHREAD
16249 gen g;
16250 caseval_param cp={s,0,&C,PTHREAD_MUTEX_INITIALIZER};
16251 pthread_t pth;
16252 pthread_attr_t attr;
16253 pthread_attr_init(&attr);
16254 int cres=pthread_create(&pth,&attr,thread_caseval,(void *)&cp);
16255 if (cres){
16256 g=gen(s,&C);
16257 g=equaltosto(g,&C);
16258 g=iprotecteval(g,1,&C);
16259 }
16260 else {
16261 // void * ptr;
16262 #ifdef TIMEOUT
16263 double d=caseval_maxtime;
16264 #else
16265 double d=3;
16266 #endif
16267 usleep(10000);
16268 for (;d>0;--d){
16269 for (unsigned k=0;k<100;++k){
16270 if (ctrl_c || interrupted){
16271 d=0;
16272 break;
16273 }
16274 int locked=pthread_mutex_trylock(&cp.mutex);
16275 if (!locked){
16276 pthread_mutex_unlock(&cp.mutex);
16277 void * ptr;
16278 cres=pthread_join(pth,&ptr);
16279 d=-1;
16280 if (cres){
16281 g=string2gen("Thread join error",false);
16282 g.subtype=-1;
16283 }
16284 else
16285 g=cp.ans;
16286 break;
16287 }
16288 usleep(10000);
16289 }
16290 }
16291 if (d==0){
16292 ctrl_c=interrupted=true;
16293 usleep(200000);
16294 pthread_cancel(pth);
16295 // cres=pthread_join(pth,NULL); // does not work
16296 g=string2gen("Timeout",false);
16297 g.subtype=-1;
16298 }
16299 pthread_attr_destroy(&attr);
16300 }
16301 #else
16302 gen g(s,&C);
16303 g=equaltosto(g,&C);
16304 if (g.type==_VECT && !g._VECTptr->empty() && g._VECTptr->front().is_symb_of_sommet(at_set_language)){
16305 vecteur v=*g._VECTptr;
16306 iprotecteval(v.front(),1,&C);
16307 v.erase(v.begin());
16308 if (g.subtype==_SEQ__VECT && v.size()==1)
16309 g=v.front();
16310 else
16311 g=gen(v,g.subtype);
16312 }
16313 gen gp=g;
16314 if (gp.is_symb_of_sommet(at_add_autosimplify))
16315 gp=gp._SYMBptr->feuille;
16316 #ifdef KHICAS
16317 bool push=false;
16318 #else
16319 bool push=!gp.is_symb_of_sommet(at_mathml) && !gp.is_symb_of_sommet(at_set_language);
16320 #endif
16321 //bool push=!g.is_symb_of_sommet(at_mathml);
16322 if (push){
16323 history_in(&C).push_back(g);
16324 // COUT << "hin " << g << '\n';
16325 }
16326 g=iprotecteval(g,1,&C);
16327 if (push){
16328 history_out(&C).push_back(g);
16329 // COUT << "hout " << g << '\n';
16330 }
16331 #endif
16332 #ifdef EMCC
16333 // compile with -s LEGACY_GL_EMULATION=1
16334 gen last=g;
16335 while (last.type==_VECT && last.subtype!=_LOGO__VECT && !last._VECTptr->empty()){
16336 gen tmp=last._VECTptr->back();
16337 if (tmp.is_symb_of_sommet(at_equal))
16338 last=vecteur(last._VECTptr->begin(),last._VECTptr->end()-1);
16339 else
16340 last=tmp;
16341 }
16342 if (last.type==_VECT && last.subtype==_LOGO__VECT){
16343 S="gr2d(logo("+last.print(&C)+"))";
16344 return S.c_str();
16345 }
16346 if (calc_mode(&C)!=1 && (last.is_symb_of_sommet(at_pnt) || last.is_symb_of_sommet(at_pixon))){
16347 #if !defined(GIAC_GGB) && defined(EMCC)
16348 if (is3d(last)){
16349 bool worker=false;
16350 worker=EM_ASM_INT_V({
16351 if (Module.worker) return 1; else return 0;
16352 });
16353 if (worker) return "3d not supported if workers are enabled";
16354 //giac_renderer(last.print(&C).c_str());
16355 int n=giac_gen_renderer(g,&C);
16356 S="gl3d "+print_INT_(n);
16357 return S.c_str();
16358 }
16359 #endif // GIAC_GGB
16360 last=remove_at_pnt(last);
16361 if (last.is_symb_of_sommet(at_pixon)){
16362 S="gr2d(pixon(";
16363 pixon_print(g,S,&C);
16364 S+="))";
16365 return S.c_str();
16366 }
16367 return svg2doutput(g,S,&C);
16368 }
16369 #endif // EMCC
16370 if (calc_mode(&C)==1 && !lop(g,at_rootof).empty())
16371 g=evalf(g,1,&C);
16372 if (has_undef_stringerr(g,S)){
16373 S="GIAC_ERROR: "+S;
16374 }
16375 else {
16376 #ifdef KHICAS // replace ],[ by ][
16377 gen last=g;
16378 while (last.type==_VECT && last.subtype!=_LOGO__VECT && !last._VECTptr->empty()){
16379 gen tmp=last._VECTptr->back();
16380 if (tmp.is_symb_of_sommet(at_equal))
16381 last=vecteur(last._VECTptr->begin(),last._VECTptr->end()-1);
16382 else
16383 last=tmp;
16384 }
16385 if (last.is_symb_of_sommet(at_pnt)){
16386 if (os_shell)
16387 xcas::displaygraph(g,&C);
16388 S="Graphic_object";
16389 }
16390 else {
16391 if (os_shell){
16392 if (islogo(g))
16393 xcas::displaylogo();
16394 else {
16395 if ( (g.type==_SYMB || (warn_symb_program_sto && g.type==_VECT)) && taille(g,256)<=256)
16396 g=xcas::eqw(g,true,&C);
16397 }
16398 }
16399 if (taille(g,100)>=100)
16400 S="Large_object";
16401 else
16402 S=g.print(&C);
16403 }
16404 if (!os_shell){
16405 string S_;
16406 S_ += S[0];
16407 for (size_t i=1;i+1<S.size();++i){
16408 if (S[i-1]==']' && S[i]==',' && S[i+1]=='[')
16409 ;
16410 else
16411 S_ += S[i];
16412 }
16413 if (S.size()>1)
16414 S_ +=S[S.size()-1];
16415 S=S_;
16416 if (S.size()>=3 && S[0]=='[' && S[1]!='[' && S[S.size()-1]==']')
16417 S='['+S+']'; // vector/list not allowed in Numworks calc app
16418 }
16419 #else
16420 S=g.print(&C);
16421 #if !defined GIAC_GGB
16422 if (g.type==_FRAC || g.type==_ZINT){
16423 S += "=";
16424 S += evalf_double(g,1,&C).print(&C);
16425 }
16426 if (g.type==_SYMB){
16427 g=evalf_double(g,1,&C);
16428 if (g.type<=_CPLX){
16429 S += "=";
16430 S += g.print(&C);
16431 }
16432 }
16433 #endif // !defined GIAC_GGB
16434 #endif // NUWMORKS
16435 }
16436 return S.c_str();
16437 }
16438
16439 #ifdef EMCC_BIND
EMSCRIPTEN_BINDINGS(cas)16440 EMSCRIPTEN_BINDINGS(cas){
16441 emscripten::function("caseval",&caseval,emscripten::allow_raw_pointers());
16442 }
16443 #endif
16444
16445 #ifndef NO_NAMESPACE_GIAC
16446 } // namespace giac
16447 #endif // ndef NO_NAMESPACE_GIAC
16448
16449