1
2 /*
3 * Math2
4 * Copyright (c) 2003-2007 by Mattias Hultgren <tilda_o_tize@hotmail.com>
5 *
6 * See math2.h
7 */
8
9 #include "math2.h"
10 #include "math2.intern.h"
11 #include "keyfile.h"
12 #include <stdlib.h>
13 #include <sys/time.h>
14
15
16
17 namespace math
18 {
19
20 #ifdef DEVELOP
21 #define both_left_and_right if( left == 0 || right == 0 ) THROW_ERROR( ErrorType_General, "Internal error: builtin function wasn't called the right way" );
22 #define only_left if( left == 0 || right != 0 ) THROW_ERROR( ErrorType_General, "Internal error: builtin function wasn't called the right way" );
23 #define only_right if( left != 0 || right == 0 ) THROW_ERROR( ErrorType_General, "Internal error: builtin function wasn't called the right way" );
24 #define neither_left_or_right if( left != 0 || right != 0 ) THROW_ERROR( ErrorType_General, "Internal error: builtin function wasn't called the right way" );
25 #else
26 #define both_left_and_right ;
27 #define only_left ;
28 #define only_right ;
29 #define neither_left_or_right ;
30 #endif
31
32
builtin_set(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)33 void builtin_set(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
34 {
35 both_left_and_right;
36
37 if(left != right)
38 *left = *right;
39
40 if( res != 0 )
41 *res = *left;
42 }
43
builtin_set_add(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)44 void builtin_set_add(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
45 {
46 builtin_plus( left, left, right, private_varlist );
47
48 if( res != 0 )
49 *res = *left;
50 }
builtin_set_sub(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)51 void builtin_set_sub(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
52 {
53 builtin_minus( left, left, right, private_varlist );
54
55 if( res != 0 )
56 *res = *left;
57 }
builtin_set_mul(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)58 void builtin_set_mul(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
59 {
60 builtin_mul( left, left, right, private_varlist );
61
62 if( res != 0 )
63 *res = *left;
64 }
builtin_set_div(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)65 void builtin_set_div(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
66 {
67 builtin_div( left, left, right, private_varlist );
68
69 if( res != 0 )
70 *res = *left;
71 }
builtin_set_intdiv(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)72 void builtin_set_intdiv(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
73 {
74 builtin_intdiv( left, left, right, private_varlist );
75
76 if( res != 0 )
77 *res = *left;
78 }
builtin_set_pow(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)79 void builtin_set_pow(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
80 {
81 builtin_pow( left, left, right, private_varlist );
82
83 if( res != 0 )
84 *res = *left;
85 }
builtin_inc(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)86 void builtin_inc(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
87 {
88 only_left;
89
90 if(left->get_type() != VariableType_Complex)
91 {
92 char tmp_err[ERROR_OBJ_MSG_LEN];
93 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "++" );
94 THROW_ERROR( ErrorType_General, tmp_err );
95 }
96
97 left->get_complex_rw()->real++;
98 left->signal_changed();
99
100
101 if( res != 0 )
102 *res = *left;
103 }
builtin_decrement(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)104 void builtin_decrement(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
105 {
106 only_left;
107
108 if(left->get_type() != VariableType_Complex)
109 {
110 char tmp_err[ERROR_OBJ_MSG_LEN];
111 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "--" );
112 THROW_ERROR( ErrorType_General, tmp_err );
113 }
114
115 left->get_complex_rw()->real--;
116 left->signal_changed();
117
118 if( res != 0 )
119 *res = *left;
120 }
121
builtin_and(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)122 void builtin_and(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
123 {
124 both_left_and_right;
125
126 if( res == 0 )
127 return;
128
129 if( left->get_type() != VariableType_Boolean ||
130 right->get_type() != VariableType_Boolean )
131 {
132 char tmp_err[ERROR_OBJ_MSG_LEN];
133 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "and" );
134 THROW_ERROR( ErrorType_General, tmp_err );
135 }
136
137 res->set_boolean( left->get_boolean() && right->get_boolean() );
138 }
139
builtin_or(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)140 void builtin_or(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
141 {
142 both_left_and_right;
143
144 if( res == 0 )
145 return;
146
147 if( left->get_type() != VariableType_Boolean ||
148 right->get_type() != VariableType_Boolean )
149 {
150 char tmp_err[ERROR_OBJ_MSG_LEN];
151 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "or" );
152 THROW_ERROR( ErrorType_General, tmp_err );
153 }
154
155 res->set_boolean( left->get_boolean() || right->get_boolean() );
156 }
157
builtin_xor(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)158 void builtin_xor(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
159 {
160 both_left_and_right;
161
162 if( res == 0 )
163 return;
164
165 if( left->get_type() != VariableType_Boolean ||
166 right->get_type() != VariableType_Boolean )
167 {
168 char tmp_err[ERROR_OBJ_MSG_LEN];
169 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "xor" );
170 THROW_ERROR( ErrorType_General, tmp_err );
171 }
172
173 res->set_boolean( left->get_boolean() ^ right->get_boolean() );
174 }
175
builtin_not(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)176 void builtin_not(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
177 {
178 only_right;
179
180 if( res == 0 )
181
182 if(right->get_type() != VariableType_Boolean )
183 {
184 char tmp_err[ERROR_OBJ_MSG_LEN];
185 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "not" );
186 THROW_ERROR( ErrorType_General, tmp_err );
187 }
188
189 res->set_boolean( !right->get_boolean() );
190 }
191
builtin_equal(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)192 void builtin_equal(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
193 {
194 both_left_and_right;
195
196 if( res != 0 )
197 res->set_boolean( *left == *right );
198 }
199
builtin_notequal(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)200 void builtin_notequal(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
201 {
202 both_left_and_right;
203
204 if( res != 0 )
205 res->set_boolean( *left != *right );
206 }
207
builtin_greater(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)208 void builtin_greater(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
209 {
210 both_left_and_right;
211
212 if( left->get_type() == VariableType_Complex && right->get_type() == VariableType_Complex )
213 {
214 if( res != 0 )
215 res->set_boolean(*left->get_complex() > *right->get_complex());
216 }
217 else
218 {
219 char tmp_err[ERROR_OBJ_MSG_LEN];
220 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), ">" );
221 THROW_ERROR( ErrorType_General, tmp_err );
222 }
223 }
224
builtin_smaller(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)225 void builtin_smaller(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
226 {
227 both_left_and_right;
228
229 if( left->get_type() == VariableType_Complex && right->get_type() == VariableType_Complex )
230 {
231 if( res != 0 )
232 res->set_boolean(*left->get_complex() < *right->get_complex());
233 }
234 else
235 {
236 char tmp_err[ERROR_OBJ_MSG_LEN];
237 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "<" );
238 THROW_ERROR( ErrorType_General, tmp_err );
239 }
240 }
241
builtin_greater_eq(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)242 void builtin_greater_eq(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
243 {
244 both_left_and_right;
245
246 if( left->get_type() == VariableType_Complex && right->get_type() == VariableType_Complex )
247 {
248 if( res != 0 )
249 res->set_boolean(*left->get_complex() >= *right->get_complex());
250 }
251 else
252 {
253 char tmp_err[ERROR_OBJ_MSG_LEN];
254 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), ">=" );
255 THROW_ERROR( ErrorType_General, tmp_err );
256 }
257 }
258
builtin_smaller_eq(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)259 void builtin_smaller_eq(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
260 {
261 both_left_and_right;
262
263 if( left->get_type() == VariableType_Complex && right->get_type() == VariableType_Complex )
264 {
265 if( res != 0 )
266 res->set_boolean(*left->get_complex() <= *right->get_complex());
267 }
268 else
269 {
270 char tmp_err[ERROR_OBJ_MSG_LEN];
271 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "<=" );
272 THROW_ERROR( ErrorType_General, tmp_err );
273 }
274 }
275
builtin_almost_eq(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)276 void builtin_almost_eq(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
277 {
278 bool ret_bool;
279
280 both_left_and_right;
281
282 if( left->get_type() != right->get_type() )
283 ret_bool = false;
284
285 else if( left->get_type() == VariableType_Complex && right->get_type() == VariableType_Complex )
286 ret_bool = complex_almost_equal(*(left->get_complex()),*(right->get_complex()));
287
288 else if( left->get_type() == VariableType_Matrix && right->get_type() == VariableType_Matrix )
289 {
290 const Matrix *matr1,*matr2;
291 uint32 r,c;
292
293 matr1 = left->get_matrix();
294 matr2 = right->get_matrix();
295
296 if((matr1->get_width() != matr2->get_width()) | (matr1->get_height() != matr2->get_height()))
297 ret_bool = false;
298 else
299 {
300 ret_bool = true;
301 for(r=1;r<=matr1->get_height();r++)
302 {
303 for(c=1;c<=matr1->get_width();c++)
304 {
305 if( complex_almost_equal(matr1->get_complex(r,c),matr2->get_complex(r,c)) == false )
306 {
307 ret_bool = false;
308 break;
309 }
310 }
311 if(c <= matr1->get_height())
312 break;
313 }
314 }
315 }
316 else
317 {
318 char tmp_err[ERROR_OBJ_MSG_LEN];
319 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "~=" );
320 THROW_ERROR( ErrorType_General, tmp_err );
321 }
322
323 if( res != 0 )
324 res->set_boolean( ret_bool );
325 }
326
builtin_plus(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)327 void builtin_plus(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
328 {
329 both_left_and_right;
330
331 if( res == 0 )
332 return;
333
334 if( left->get_type() == VariableType_Complex && right->get_type() == VariableType_Complex )
335 res->set_complex( *(left->get_complex()) + *(right->get_complex()) );
336 else if( left->get_type() == VariableType_Matrix && right->get_type() == VariableType_Matrix )
337 {
338 Matrix matr_res;
339 const Matrix *matr1,*matr2;
340
341 matr1 = left->get_matrix();
342 matr2 = right->get_matrix();
343 matrix_add(&matr_res,matr1,matr2);
344
345 res->set_matrix( &matr_res );
346 }
347 else if( left->get_type() == VariableType_String )
348 {
349 if( right->get_type() == VariableType_String )
350 {
351 utf8_string str;
352
353 str = *(left->get_string());
354 str.append( *(right->get_string()) );
355
356 res->set_string( str );
357 }
358 else
359 {
360 utf8_string str;
361 Format int_format;
362
363 if(intern_format != 0)
364 int_format = *intern_format;
365
366 str = *(left->get_string());
367 right->append_to_string( str, int_format, false );
368
369 res->set_string( str );
370 }
371 }
372 else
373 {
374 char tmp_err[ERROR_OBJ_MSG_LEN];
375 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "+" );
376 THROW_ERROR( ErrorType_General, tmp_err );
377 }
378 }
379
builtin_neg(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)380 void builtin_neg(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
381 {
382 Matrix matr_res;
383
384 only_right;
385
386 if( res == 0 )
387 return;
388
389 if( right->get_type() == VariableType_Complex )
390 res->set_complex( - *(right->get_complex()) );
391 else if( right->get_type() == VariableType_Matrix )
392 {
393 matr_res = *right->get_matrix();
394
395 for(uint32 y=1; y <= matr_res.get_height() ; y++)
396 {
397 for(uint32 x=1; x <= matr_res.get_width() ; x++)
398 matr_res.set_complex(x,y,-matr_res.get_complex(x,y));
399 }
400
401 res->set_matrix( &matr_res );
402 }
403 else
404 {
405 char tmp_err[ERROR_OBJ_MSG_LEN];
406 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "- (neg)" );
407 THROW_ERROR( ErrorType_General, tmp_err );
408 }
409 }
410
builtin_minus(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)411 void builtin_minus(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
412 {
413 Matrix matr_res;
414 const Matrix *matr1,*matr2;
415
416 both_left_and_right;
417
418 if( res == 0 )
419 return;
420
421 if( left->get_type() == VariableType_Complex && right->get_type() == VariableType_Complex )
422 res->set_complex( *(left->get_complex()) - *(right->get_complex()) );
423 else if( left->get_type() == VariableType_Matrix && right->get_type() == VariableType_Matrix )
424 {
425 matr1 = left->get_matrix();
426 matr2 = right->get_matrix();
427 matrix_sub(&matr_res,matr1,matr2);
428
429 res->set_matrix( &matr_res );
430 }
431 else
432 {
433 char tmp_err[ERROR_OBJ_MSG_LEN];
434 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "-" );
435 THROW_ERROR( ErrorType_General, tmp_err );
436 }
437 }
438
builtin_mul(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)439 void builtin_mul(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
440 {
441 Matrix matr_res;
442 const Matrix *matr1,*matr2;
443
444 both_left_and_right;
445
446 if( res == 0 )
447 return;
448
449 if( left->get_type() == VariableType_Complex && right->get_type() == VariableType_Complex )
450 res->set_complex( *(left->get_complex()) * *(right->get_complex()) );
451 else if( left->get_type() == VariableType_Matrix && right->get_type() == VariableType_Complex )
452 {
453 matr_res = *left->get_matrix();
454 matr_res.mul( *(right->get_complex()) );
455
456 res->set_matrix( &matr_res );
457 }
458 else if( left->get_type() == VariableType_Complex && right->get_type() == VariableType_Matrix )
459 {
460 matr_res = *right->get_matrix();
461 matr_res.mul( *(left->get_complex()) );
462
463 res->set_matrix( &matr_res );
464 }
465 else if( left->get_type() == VariableType_Matrix && right->get_type() == VariableType_Matrix )
466 {
467 matr1 = left->get_matrix();
468 matr2 = right->get_matrix();
469 matrix_mul( &matr_res, matr1, matr2 );
470
471 res->set_matrix( &matr_res );
472 }
473 else
474 {
475 char tmp_err[ERROR_OBJ_MSG_LEN];
476 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "*" );
477 THROW_ERROR( ErrorType_General, tmp_err );
478 }
479 }
480
builtin_div(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)481 void builtin_div(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
482 {
483 both_left_and_right;
484
485 if( res == 0 )
486 return;
487
488 if( left->get_type() == VariableType_Complex && right->get_type() == VariableType_Complex )
489 res->set_complex( *(left->get_complex()) / *(right->get_complex()) );
490 else
491 {
492 char tmp_err[ERROR_OBJ_MSG_LEN];
493 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "/" );
494 THROW_ERROR( ErrorType_General, tmp_err );
495 }
496 }
497
builtin_intdiv(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)498 void builtin_intdiv(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
499 {
500 both_left_and_right;
501
502 if( res == 0 )
503 return;
504
505 if( left->get_type() == VariableType_Complex && right->get_type() == VariableType_Complex )
506 {
507 const Complex *a, *b;
508 Integer ai, bi;
509
510 a = left->get_complex();
511 b = right->get_complex();
512 if( floatx(a->imaginary) != 0.0 || floatx(b->imaginary) != 0.0 ||
513 !(a->real.isInteger()) || !(a->real.isInteger()) )
514 {
515 char tmp_err[ERROR_OBJ_MSG_LEN];
516 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "\\" );
517 THROW_ERROR( ErrorType_General, tmp_err );
518 }
519 a->real.get_top( &ai );
520 b->real.get_top( &bi );
521
522 res->set_complex( Real( ai / bi ) );
523 }
524 else
525 {
526 char tmp_err[ERROR_OBJ_MSG_LEN];
527 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "\\" );
528 THROW_ERROR( ErrorType_General, tmp_err );
529 }
530 }
531
builtin_modulo(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)532 void builtin_modulo(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
533 {
534 both_left_and_right;
535
536 if( res == 0 )
537 return;
538
539 if( left->get_type() == VariableType_Complex && right->get_type() == VariableType_Complex )
540 {
541 const Complex *a, *b;
542 Integer ai, bi;
543
544 a = left->get_complex();
545 b = right->get_complex();
546 if( floatx(a->imaginary) != 0.0 || floatx(b->imaginary) != 0.0 ||
547 !(a->real.isInteger()) || !(b->real.isInteger()) )
548 {
549 char tmp_err[ERROR_OBJ_MSG_LEN];
550 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "mod" );
551 THROW_ERROR( ErrorType_General, tmp_err );
552 }
553 a->real.get_top( &ai );
554 b->real.get_top( &bi );
555
556 res->set_complex( Real( ai % bi ) );
557 }
558 else
559 {
560 char tmp_err[ERROR_OBJ_MSG_LEN];
561 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "mod" );
562 THROW_ERROR( ErrorType_General, tmp_err );
563 }
564 }
565
builtin_pow(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)566 void builtin_pow(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
567 {
568 Complex tmp;
569
570 both_left_and_right;
571
572 if( res == 0 )
573 return;
574
575 if( left->get_type() == VariableType_Complex && right->get_type() == VariableType_Complex )
576 {
577 if( left->has_name() )
578 {
579 if( *(left->get_name()) == "e" && *(left->get_complex()) == Complex( E ) )
580 {
581 Complex tmp2;
582
583 tmp = *(right->get_complex());
584 tmp.real = expx(tmp.real);
585
586 tmp2 = degfix * Complex( Real(0), tmp.imaginary );
587
588 tmp.real *= expx(tmp2.real);
589 tmp.imaginary = tmp2.imaginary;
590
591 res->set_complex( Complex( tmp.real*Real(cosx(tmp.imaginary)),
592 tmp.real*Real(sinx(tmp.imaginary)) ) );
593 }
594 else
595 res->set_complex( power( *(left->get_complex()), *(right->get_complex()) ) );
596 }
597 else
598 res->set_complex( power( *(left->get_complex()), *(right->get_complex()) ) );
599 }
600 else if( left->get_type() == VariableType_Matrix && right->get_type() == VariableType_Complex )
601 {
602 Matrix matr,matr_res;
603 Integer power;
604
605 tmp = *(right->get_complex());
606 if( floatx(tmp.imaginary) != 0.0)
607 THROW_ERROR( ErrorType_Domain, _("Domain error: Imaginary part must be zero.") );
608 if( !tmp.real.isInteger() )
609 THROW_ERROR( ErrorType_Domain, _("Domain error: Can't raise a matrix to a non integer number.") );
610
611 matr = *left->get_matrix();
612 tmp.real.get_top( &power );
613
614 matrix_pow( &matr_res, &matr, power );
615
616 res->set_matrix( &matr_res );
617 }
618 else
619 {
620 char tmp_err[ERROR_OBJ_MSG_LEN];
621 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "^" );
622 THROW_ERROR( ErrorType_General, tmp_err );
623 }
624 }
625
builtin_faculty(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)626 void builtin_faculty(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
627 {
628 only_left;
629
630 if( res == 0 )
631 return;
632
633 if(left->get_type() != VariableType_Complex)
634 {
635 char tmp_err[ERROR_OBJ_MSG_LEN];
636 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "!" );
637 THROW_ERROR( ErrorType_General, tmp_err );
638 }
639 Complex tmp;
640 Integer val;
641
642 tmp = *(left->get_complex());
643
644 if(floatx(tmp.imaginary) != 0.0)
645 THROW_ERROR( ErrorType_Domain, _("Domain error: Imaginary part must be zero.") );
646
647 if( !tmp.real.isInteger() )
648 THROW_ERROR( ErrorType_Domain, _("Domain error: Can't calculate faculty of a non integer number.") );
649
650 tmp.real.get_top( &val );
651
652 val.faculty();
653 tmp.real = val;
654 tmp.imaginary = 0;
655
656 res->set_complex( tmp );
657 }
658
builtin_ipart(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)659 void builtin_ipart(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
660 {
661 only_right;
662
663 if( res == 0 )
664 return;
665
666 if(right->get_type() == VariableType_Complex)
667 res->set_complex( ipart( *(right->get_complex()) ) );
668 else if(right->get_type() == VariableType_Matrix)
669 {
670 Matrix matr;
671
672 matr = *right->get_matrix();
673
674 for(uint32 y=1; y <= matr.get_height() ; y++)
675 {
676 for(uint32 x=1; x <= matr.get_width() ; x++)
677 matr.set_complex(x,y,ipart(matr.get_complex(x,y)));
678 }
679
680 res->set_matrix( &matr );
681 }
682 else
683 {
684 char tmp_err[ERROR_OBJ_MSG_LEN];
685 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "iPart" );
686 THROW_ERROR( ErrorType_General, tmp_err );
687 }
688 }
689
builtin_sin(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)690 void builtin_sin(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
691 {
692 only_right;
693
694 if(right->get_type() != VariableType_Complex)
695 {
696 char tmp_err[ERROR_OBJ_MSG_LEN];
697 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "sin" );
698 THROW_ERROR( ErrorType_General, tmp_err );
699 }
700 if( res != 0 )
701 res->set_complex( sinc( degfix * *(right->get_complex()) ) );
702 }
703
builtin_cos(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)704 void builtin_cos(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
705 {
706 only_right;
707
708 if(right->get_type() != VariableType_Complex)
709 {
710 char tmp_err[ERROR_OBJ_MSG_LEN];
711 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "cos" );
712 THROW_ERROR( ErrorType_General, tmp_err );
713 }
714 if( res != 0 )
715 res->set_complex( cosc( degfix * *(right->get_complex()) ) );
716 }
717
builtin_tan(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)718 void builtin_tan(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
719 {
720 only_right;
721
722 if(right->get_type() != VariableType_Complex)
723 {
724 char tmp_err[ERROR_OBJ_MSG_LEN];
725 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "tan" );
726 THROW_ERROR( ErrorType_General, tmp_err );
727 }
728 if( res != 0 )
729 res->set_complex( tanc( degfix * *(right->get_complex()) ) );
730 }
731
builtin_asin(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)732 void builtin_asin(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
733 {
734 only_right;
735
736 if(right->get_type() != VariableType_Complex)
737 {
738 char tmp_err[ERROR_OBJ_MSG_LEN];
739 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "asin" );
740 THROW_ERROR( ErrorType_General, tmp_err );
741 }
742 if( res != 0 )
743 res->set_complex( asinc( *(right->get_complex()) ) / degfix );
744 }
745
builtin_acos(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)746 void builtin_acos(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
747 {
748 only_right;
749
750 if(right->get_type() != VariableType_Complex)
751 {
752 char tmp_err[ERROR_OBJ_MSG_LEN];
753 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "acos" );
754 THROW_ERROR( ErrorType_General, tmp_err );
755 }
756 if( res != 0 )
757 res->set_complex( acosc( *(right->get_complex()) ) / degfix );
758 }
759
builtin_atan(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)760 void builtin_atan(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
761 {
762 only_right;
763
764 if(right->get_type() != VariableType_Complex)
765 {
766 char tmp_err[ERROR_OBJ_MSG_LEN];
767 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "atan" );
768 THROW_ERROR( ErrorType_General, tmp_err );
769 }
770 if( res != 0 )
771 res->set_complex( atanc( *(right->get_complex()) ) / degfix );
772 }
773
builtin_sqrt(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)774 void builtin_sqrt(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
775 {
776 only_right;
777
778 if(right->get_type() != VariableType_Complex)
779 {
780 char tmp_err[ERROR_OBJ_MSG_LEN];
781 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "sqrt" );
782 THROW_ERROR( ErrorType_General, tmp_err );
783 }
784 if( res != 0 )
785 res->set_complex( sqroot( *(right->get_complex()) ) );
786 }
787
builtin_isqrt(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)788 void builtin_isqrt(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
789 {
790 only_right;
791 const Complex *tmp;
792
793 if(right->get_type() != VariableType_Complex)
794 {
795 char tmp_err[ERROR_OBJ_MSG_LEN];
796 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "iSqrt" );
797 THROW_ERROR( ErrorType_General, tmp_err );
798 }
799 tmp = right->get_complex();
800 if( floatx(tmp->imaginary) != 0.0 )
801 THROW_ERROR( ErrorType_Domain, _("Domain error: Imaginary part must be zero.") );
802 if( !tmp->real.isInteger() )
803 THROW_ERROR( ErrorType_Domain, _("Domain error: The number must be an integer.") );
804
805 Integer tmp_int;
806
807 tmp->real.get_top( &tmp_int );
808
809
810 if( res != 0 )
811 res->set_complex( Real( iSqrt( tmp_int ) ) );
812 }
813
builtin_ln(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)814 void builtin_ln(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
815 {
816 only_right;
817
818 if(right->get_type() != VariableType_Complex)
819 {
820 char tmp_err[ERROR_OBJ_MSG_LEN];
821 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "ln" );
822 THROW_ERROR( ErrorType_General, tmp_err );
823 }
824 if( res != 0 )
825 res->set_complex( logc( *(right->get_complex()) ) );
826 }
827
builtin_log(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)828 void builtin_log(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
829 {
830 only_right;
831
832 if(right->get_type() != VariableType_Complex)
833 {
834 char tmp_err[ERROR_OBJ_MSG_LEN];
835 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "log" );
836 THROW_ERROR( ErrorType_General, tmp_err );
837 }
838 if( res != 0 )
839 res->set_complex( log10c( *(right->get_complex()) ) );
840 }
841
builtin_log2(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)842 void builtin_log2(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
843 {
844 only_right;
845
846 if(right->get_type() != VariableType_Complex)
847 {
848 char tmp_err[ERROR_OBJ_MSG_LEN];
849 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "log2" );
850 THROW_ERROR( ErrorType_General, tmp_err );
851 }
852 if( res != 0 )
853 res->set_complex( log2c( *(right->get_complex()) ) );
854 }
855
builtin_abs(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)856 void builtin_abs(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
857 {
858 only_right;
859
860 if( res == 0 )
861 return;
862
863 if(right->get_type() == VariableType_Complex)
864 res->set_complex( abs( *(right->get_complex()) ) );
865 else if(right->get_type() == VariableType_Matrix)
866 {
867 Matrix matr;
868
869 matr = *right->get_matrix();
870
871 for(uint32 y=1; y <= matr.get_height() ; y++)
872 {
873 for(uint32 x=1; x <= matr.get_width() ; x++)
874 matr.set_complex(x,y,abs(matr.get_complex(x,y)));
875 }
876
877 res->set_matrix( &matr );
878 }
879 else
880 {
881 char tmp_err[ERROR_OBJ_MSG_LEN];
882 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "abs" );
883 THROW_ERROR( ErrorType_General, tmp_err );
884 }
885 }
886
builtin_re(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)887 void builtin_re(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
888 {
889 only_right;
890
891 if( res == 0 )
892 return;
893
894 if(right->get_type() == VariableType_Complex)
895 res->set_complex( Complex( right->get_complex()->real ) );
896 else if(right->get_type() == VariableType_Matrix)
897 {
898 Matrix matr;
899 uint32 x,y;
900
901 matr = *right->get_matrix();
902
903 for(y=1; y <= matr.get_height() ; y++)
904 {
905 for(x=1; x <= matr.get_width() ; x++)
906 matr.set_complex(x,y, Complex( matr.get_complex(x,y).real ) );
907 }
908
909 res->set_matrix( &matr );
910 }
911 else
912 {
913 char tmp_err[ERROR_OBJ_MSG_LEN];
914 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "re" );
915 THROW_ERROR( ErrorType_General, tmp_err );
916 }
917 }
918
builtin_im(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)919 void builtin_im(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
920 {
921 only_right;
922
923 if( res == 0 )
924 return;
925
926 if(right->get_type() == VariableType_Complex)
927 res->set_complex( Complex( right->get_complex()->imaginary ) );
928 else if(right->get_type() == VariableType_Matrix)
929 {
930 Matrix matr;
931 uint32 x,y;
932
933 matr = *right->get_matrix();
934
935 for(y=1; y <= matr.get_height() ; y++)
936 {
937 for(x=1; x <= matr.get_width() ; x++)
938 matr.set_complex(x,y, Complex( matr.get_complex(x,y).imaginary ) );
939 }
940 res->set_matrix( &matr );
941 }
942 else
943 {
944 char tmp_err[ERROR_OBJ_MSG_LEN];
945 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "im" );
946 THROW_ERROR( ErrorType_General, tmp_err );
947 }
948 }
949
builtin_rand(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)950 void builtin_rand(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
951 {
952 neither_left_or_right;
953
954 if( res != 0 )
955 res->set_complex( Complex( floatx(rand()) / floatx( int64(RAND_MAX) + 1 ) ) );
956 }
957
builtin_arg(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)958 void builtin_arg(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
959 {
960 only_right;
961
962 if( res == 0 )
963 return;
964
965 if(right->get_type() == VariableType_Complex)
966 res->set_complex( arg( *(right->get_complex()) ) / degfix );
967 else if(right->get_type() == VariableType_Matrix)
968 {
969 Matrix matr;
970 uint32 r,c;
971
972 matr = *right->get_matrix();
973
974 for(r=1;r<=matr.get_height();r++)
975 {
976 for(c=1;c<=matr.get_width();c++)
977 matr.set_complex(r,c,arg(matr.get_complex(r,c)) / degfix );
978 }
979
980 res->set_matrix( &matr );
981 }
982 else
983 {
984 char tmp_err[ERROR_OBJ_MSG_LEN];
985 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "arg" );
986 THROW_ERROR( ErrorType_General, tmp_err );
987 }
988 }
989
builtin_time(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)990 void builtin_time(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
991 {
992 timeval tmp;
993
994 neither_left_or_right;
995
996 gettimeofday( &tmp, 0 );
997
998 if( res != 0 )
999 res->set_complex( Complex( floatx( int64(tmp.tv_sec)*int64(1000000) + tmp.tv_usec ) / 1000000.0 ) );
1000 }
1001
builtin_fpart(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1002 void builtin_fpart(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1003 {
1004 only_right;
1005
1006 if( res == 0 )
1007 return;
1008
1009 if(right->get_type() == VariableType_Complex)
1010 res->set_complex( fpart(*right->get_complex()) );
1011 else if(right->get_type() == VariableType_Matrix)
1012 {
1013 Matrix matr;
1014
1015 matr = *right->get_matrix();
1016
1017 for(uint32 y=1; y <= matr.get_height() ; y++)
1018 {
1019 for(uint32 x=1; x <= matr.get_width() ; x++)
1020 matr.set_complex(x,y,fpart(matr.get_complex(x,y)));
1021 }
1022
1023 res->set_matrix( &matr );
1024 }
1025 else
1026 {
1027 char tmp_err[ERROR_OBJ_MSG_LEN];
1028 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "fPart" );
1029 THROW_ERROR( ErrorType_General, tmp_err );
1030 }
1031 }
1032
builtin_sinh(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1033 void builtin_sinh(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1034 {
1035 only_right;
1036
1037 if(right->get_type() != VariableType_Complex)
1038 {
1039 char tmp_err[ERROR_OBJ_MSG_LEN];
1040 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "sinh" );
1041 THROW_ERROR( ErrorType_General, tmp_err );
1042 }
1043
1044 if( res != 0 )
1045 res->set_complex( sinhc( *right->get_complex() ) );
1046 }
1047
builtin_cosh(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1048 void builtin_cosh(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1049 {
1050 only_right;
1051
1052 if(right->get_type() != VariableType_Complex)
1053 {
1054 char tmp_err[ERROR_OBJ_MSG_LEN];
1055 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "cosh" );
1056 THROW_ERROR( ErrorType_General, tmp_err );
1057 }
1058
1059 if( res != 0 )
1060 res->set_complex( coshc( *right->get_complex() ) );
1061 }
1062
builtin_tanh(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1063 void builtin_tanh(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1064 {
1065 only_right;
1066
1067 if(right->get_type() != VariableType_Complex)
1068 {
1069 char tmp_err[ERROR_OBJ_MSG_LEN];
1070 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "tanh" );
1071 THROW_ERROR( ErrorType_General, tmp_err );
1072 }
1073
1074 if( res != 0 )
1075 res->set_complex( tanhc( *right->get_complex() ) );
1076 }
1077
builtin_asinh(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1078 void builtin_asinh(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1079 {
1080 only_right;
1081
1082 if(right->get_type() != VariableType_Complex)
1083 {
1084 char tmp_err[ERROR_OBJ_MSG_LEN];
1085 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "asinh" );
1086 THROW_ERROR( ErrorType_General, tmp_err );
1087 }
1088
1089 if( res != 0 )
1090 res->set_complex( asinhc( *right->get_complex() ) );
1091 }
1092
builtin_acosh(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1093 void builtin_acosh(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1094 {
1095 only_right;
1096
1097 if(right->get_type() != VariableType_Complex)
1098 {
1099 char tmp_err[ERROR_OBJ_MSG_LEN];
1100 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "acosh" );
1101 THROW_ERROR( ErrorType_General, tmp_err );
1102 }
1103
1104 if( res != 0 )
1105 res->set_complex( acoshc( *right->get_complex() ) );
1106 }
1107
builtin_atanh(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1108 void builtin_atanh(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1109 {
1110 only_right;
1111
1112 if(right->get_type() != VariableType_Complex)
1113 {
1114 char tmp_err[ERROR_OBJ_MSG_LEN];
1115 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "atanh" );
1116 THROW_ERROR( ErrorType_General, tmp_err );
1117 }
1118
1119 if( res != 0 )
1120 res->set_complex( atanhc( *right->get_complex() ) );
1121 }
1122
builtin_det(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1123 void builtin_det(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1124 {
1125 only_right;
1126
1127 if(right->get_type() != VariableType_Matrix)
1128 {
1129 char tmp_err[ERROR_OBJ_MSG_LEN];
1130 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "det" );
1131 THROW_ERROR( ErrorType_General, tmp_err );
1132 }
1133
1134 if( res != 0 )
1135 res->set_complex( right->get_matrix()->det() );
1136 }
1137
builtin_adj(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1138 void builtin_adj(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1139 {
1140 only_right;
1141
1142 if( res == 0 )
1143 return;
1144
1145 if(right->get_type() != VariableType_Matrix)
1146 {
1147 char tmp_err[ERROR_OBJ_MSG_LEN];
1148 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "adj" );
1149 THROW_ERROR( ErrorType_General, tmp_err );
1150 }
1151
1152 Matrix matr;
1153
1154 matr = *right->get_matrix();
1155 matr.adjoint();
1156
1157 res->set_matrix( &matr );
1158 }
1159
builtin_delete(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1160 void builtin_delete(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1161 {
1162 const utf8_string *str;
1163
1164 only_right;
1165
1166 if( right->has_name() )
1167 str = right->get_name();
1168 else if( right->get_type() == VariableType_String )
1169 str = right->get_string();
1170 else
1171 {
1172 char tmp_err[ERROR_OBJ_MSG_LEN];
1173 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "delete" );
1174 THROW_ERROR( ErrorType_General, tmp_err );
1175 }
1176
1177 switch( function_list.delete_function( *str ) )
1178 {
1179 case 1:
1180 res->set_string( _("Function deleted") );
1181 return;
1182
1183 case -1:
1184 THROW_ERROR( ErrorType_General, _("Function is undeletable") );
1185
1186 default: // no function named str
1187 break;
1188 }
1189
1190 // Searching for a Variable
1191 if( private_varlist )
1192 {
1193 try{ private_varlist->remove( private_varlist->get_id(str->c_str()) ); }
1194 catch(error_obj error)
1195 {
1196 if( error.type != ErrorType_Variable_not_found )
1197 throw error;
1198 }
1199 }
1200
1201 try{ global_varlist.remove( global_varlist.get_id(str->c_str()) ); }
1202 catch(error_obj error)
1203 {
1204 if( error.type == ErrorType_Variable_not_found )
1205 snprintf( error.msg, ERROR_OBJ_MSG_LEN, _("Variable/function not found") );
1206 throw error;
1207 }
1208
1209 res->set_string( _("Variable deleted") );
1210 }
1211
builtin_make_undeletable(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1212 void builtin_make_undeletable(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1213 {
1214 const utf8_string *str;
1215
1216 only_right;
1217
1218 if(right->has_name())
1219 str = right->get_name();
1220 else if(right->get_type() == VariableType_String)
1221 str = right->get_string();
1222 else
1223 {
1224 char tmp_err[ERROR_OBJ_MSG_LEN];
1225 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "make_undeletable" );
1226 THROW_ERROR( ErrorType_General, tmp_err );
1227 }
1228
1229 if( function_list.set_undeletable( *str ) )
1230 {
1231 res->set_string( "Function is undeletable" );
1232 return;
1233 }
1234
1235 // Searching for a Variable
1236 if(private_varlist)
1237 {
1238 try{ private_varlist->make_undeletable( private_varlist->get_id(str->c_str()) ); }
1239 catch(error_obj error)
1240 {
1241 if( error.type != ErrorType_Variable_not_found )
1242 throw error;
1243 }
1244 }
1245
1246 try{ global_varlist.make_undeletable( global_varlist.get_id(str->c_str()) ); }
1247 catch(error_obj error)
1248 {
1249 if( error.type == ErrorType_Variable_not_found )
1250 snprintf( error.msg, ERROR_OBJ_MSG_LEN, _("Variable/function not found") );
1251 throw error;
1252 }
1253
1254 res->set_string( _("Variable is undeletable") );
1255 }
1256
builtin_make_constant(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1257 void builtin_make_constant(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1258 {
1259 const utf8_string *str;
1260
1261 only_right;
1262
1263 if(right->has_name())
1264 str = right->get_name();
1265 else if(right->get_type() == VariableType_String)
1266 str = right->get_string();
1267 else
1268 {
1269 char tmp_err[ERROR_OBJ_MSG_LEN];
1270 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "make_constant" );
1271 THROW_ERROR( ErrorType_General, tmp_err );
1272 }
1273
1274 // Searching for a Variable
1275 if(private_varlist)
1276 {
1277 try{ private_varlist->get_pointer_rw( private_varlist->get_id(str->c_str()) )->set_to_constant(); }
1278 catch(error_obj error)
1279 {
1280 if( error.type != ErrorType_Variable_not_found )
1281 throw error;
1282 }
1283 }
1284
1285 try{ global_varlist.get_pointer_rw( global_varlist.get_id(str->c_str()) )->set_to_constant(); }
1286 catch(error_obj error)
1287 {
1288
1289 throw error;
1290 }
1291
1292 res->set_string( _("Variable is now a constant") );
1293 }
1294
builtin_make_type_locked(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1295 void builtin_make_type_locked(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1296 {
1297 const utf8_string *str;
1298
1299 only_right;
1300
1301 if(right->has_name())
1302 str = right->get_name();
1303 else if(right->get_type() == VariableType_String)
1304 str = right->get_string();
1305 else
1306 {
1307 char tmp_err[ERROR_OBJ_MSG_LEN];
1308 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "make_type_locked" );
1309 THROW_ERROR( ErrorType_General, tmp_err );
1310 }
1311
1312 // Searching for a Variable
1313 if(private_varlist)
1314 {
1315 try{ private_varlist->get_pointer_rw( private_varlist->get_id(str->c_str()) )->set_can_change_type(false); }
1316 catch(error_obj error)
1317 {
1318 if( error.type != ErrorType_Variable_not_found )
1319 throw error;
1320 }
1321 }
1322
1323 try{ global_varlist.get_pointer_rw( global_varlist.get_id(str->c_str()) )->set_can_change_type(false); }
1324 catch(error_obj error)
1325 {
1326 throw error;
1327 }
1328
1329 res->set_string( _("Variable is now type locked") );
1330 }
1331
builtin_sum(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1332 void builtin_sum(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1333 {
1334 Variable func,*n_var,tmp,tmp_n_var;
1335 int64 start,stop;
1336 Matrix matr1,matr_res;
1337 const Matrix *matr2;
1338 utf8_string func_str,var_name;
1339
1340 only_right;
1341
1342 if( res == 0 )
1343 return;
1344
1345 argument_check( "sum", right,
1346 type_string, &func_str,
1347 type_name, &var_name,
1348 type_int64, &start,
1349 type_int64, &stop,
1350 type_end );
1351
1352 func.set_code_line( func_str.c_str() );
1353
1354 if(private_varlist)
1355 {
1356 try{
1357 n_var = private_varlist->get_pointer_rw( private_varlist->get_id( var_name.c_str() ) );
1358 }
1359 catch(...) {
1360 n_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
1361 }
1362 }
1363 else
1364 n_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
1365 tmp_n_var = *n_var;
1366
1367 if(start > stop)
1368 THROW_ERROR( ErrorType_Domain, _("Domain error: Start mustn't be larger than stop.") );
1369
1370 n_var->set_complex( Complex( start ) );
1371 try{ func.calc_code_line( res ); }
1372 catch(...)
1373 {
1374 try{ *n_var = tmp_n_var; } catch(...) { } // this is empty by a reason
1375 throw;
1376 }
1377
1378 if(res->get_type() == VariableType_Matrix)
1379 matr_res = *(res->get_matrix());
1380
1381 for(start++;start <= stop;start++)
1382 {
1383 n_var->set_complex( Complex( start ) );
1384 try{ func.calc_code_line( &tmp ); }
1385 catch(...)
1386 {
1387 try{ *n_var = tmp_n_var; } catch(...) { } // this is empty by a reason
1388 throw;
1389 }
1390
1391 if( res->get_type() != tmp.get_type() )
1392 {
1393 try{ *n_var = tmp_n_var; } catch(...) { } // this is empty by a reason
1394
1395 char tmp_err[ERROR_OBJ_MSG_LEN];
1396 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "sum" );
1397 THROW_ERROR( ErrorType_General, tmp_err );
1398 }
1399
1400 if( res->get_type() == VariableType_Complex )
1401 res->set_complex( *(res->get_complex()) + *(tmp.get_complex()) );
1402 else if( res->get_type() == VariableType_Matrix )
1403 {
1404 matr1 = matr_res;
1405 matr2 = tmp.get_matrix();
1406
1407 matrix_add(&matr_res,&matr1,matr2);
1408 }
1409 else
1410 {
1411 try{ *n_var = tmp_n_var; } catch(...) { } // this is empty by a reason
1412
1413 char tmp_err[ERROR_OBJ_MSG_LEN];
1414 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "sum" );
1415 THROW_ERROR( ErrorType_General, tmp_err );
1416 }
1417 }
1418
1419 *n_var = tmp_n_var;
1420 if( res->get_type() == VariableType_Matrix )
1421 res->set_matrix( &matr_res );
1422 }
1423
builtin_nderiv(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1424 void builtin_nderiv(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1425 {
1426 Variable func, *x_var, tmp_res, tmp_x_var;
1427 Complex point, step, tmp;
1428 utf8_string func_str, var_name;
1429
1430 only_right;
1431
1432 if( res == 0 )
1433 return;
1434
1435 step = Complex( Real(1,1000000) );
1436 argument_check( "nDeriv", right,
1437 type_string, &func_str,
1438 type_name, &var_name,
1439 type_complex, &point,
1440 type_complex_default, &step,
1441 type_end );
1442
1443 func.set_code_line( func_str.c_str() );
1444
1445 if(private_varlist)
1446 {
1447 try{
1448 x_var = private_varlist->get_pointer_rw( private_varlist->get_id( var_name.c_str() ) );
1449 }
1450 catch(...) {
1451 x_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
1452 }
1453 }
1454 else
1455 x_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
1456 tmp_x_var = *x_var;
1457
1458 x_var->set_complex(point + step);
1459 try{ func.calc_code_line( &tmp_res ); }
1460 catch(...)
1461 {
1462 try{ *x_var = tmp_x_var; } catch(...) { } // this is empty by a reason
1463 throw;
1464 }
1465
1466 if( tmp_res.get_type() != VariableType_Complex )
1467 {
1468 try{ *x_var = tmp_x_var; } catch(...) { } // this is empty by a reason
1469
1470 char tmp_err[ERROR_OBJ_MSG_LEN];
1471 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "nDeriv" );
1472 THROW_ERROR( ErrorType_General, tmp_err );
1473 }
1474
1475 tmp = *(tmp_res.get_complex());
1476
1477 x_var->set_complex(point - step);
1478 try{ func.calc_code_line( &tmp_res ); }
1479 catch(...)
1480 {
1481 try{ *x_var = tmp_x_var; } catch(...) { } // this is empty by a reason
1482 throw;
1483 }
1484 if( tmp_res.get_type() != VariableType_Complex )
1485 {
1486 try{ *x_var = tmp_x_var; } catch(...) { } // this is empty by a reason
1487
1488 char tmp_err[ERROR_OBJ_MSG_LEN];
1489 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "nDeriv" );
1490 THROW_ERROR( ErrorType_General, tmp_err );
1491 }
1492
1493 tmp = (tmp - *(tmp_res.get_complex())) / (2.0 * step);
1494
1495 *x_var = tmp_x_var;
1496
1497 res->set_complex( tmp );
1498 }
1499
builtin_nint(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1500 void builtin_nint(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1501 {
1502 Variable func, *x_var, partres, tmp_x_var;
1503 const Complex *tmp;
1504 Complex prev;
1505 floatx start, stop, step;
1506 int64 steps;
1507 utf8_string func_str, var_name;
1508 bool gotprev=false;
1509 bool negate_result = false;
1510
1511 only_right;
1512
1513 if( res == 0 )
1514 return;
1515
1516 steps = 1000;
1517 argument_check( "nInt", right,
1518 type_string, &func_str,
1519 type_name, &var_name,
1520 type_floatx, &start,
1521 type_floatx, &stop,
1522 type_int64_default, &steps,
1523 type_end );
1524
1525 if( steps <= 0 || steps > 1000000000 )
1526 THROW_ERROR( ErrorType_Domain, _("Domain error: Value out of range.") );
1527
1528 if( start > stop )
1529 {
1530 negate_result = true;
1531 step = start;
1532 start = stop;
1533 stop = step;
1534 }
1535
1536 res->set_complex( Complex( 0 ) );
1537 if(start == stop)
1538 {
1539 res->set_complex( Real( 0 ) );
1540 return;
1541 }
1542
1543 func.set_code_line( func_str.c_str() );
1544
1545 if(private_varlist)
1546 {
1547 try{
1548 x_var = private_varlist->get_pointer_rw( private_varlist->get_id( var_name.c_str() ) );
1549 }
1550 catch(...) {
1551 x_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
1552 }
1553 }
1554 else
1555 x_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
1556 tmp_x_var = *x_var;
1557
1558 step = (stop - start) / floatx(steps);
1559 for(; start <= stop; start+=step)
1560 {
1561 x_var->set_complex( Complex( start ) );
1562 try{ func.calc_code_line( &partres ); }
1563 catch(...)
1564 {
1565 try{ *x_var = tmp_x_var; } catch(...) { } // this is empty by a reason
1566 throw;
1567 }
1568
1569 if( partres.get_type() != VariableType_Complex )
1570 {
1571 try{ *x_var = tmp_x_var; } catch(...) { } // this is empty by a reason
1572
1573 char tmp_err[ERROR_OBJ_MSG_LEN];
1574 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "nInt" );
1575 THROW_ERROR( ErrorType_General, tmp_err );
1576 }
1577
1578 if( partres.get_type() != VariableType_Complex )
1579 {
1580 gotprev = false;
1581 continue;
1582 }
1583
1584 tmp = partres.get_complex();
1585 if(floatx(tmp->imaginary) != 0.0)
1586 gotprev = false;
1587 else
1588 {
1589 if(gotprev)
1590 res->set_complex( *(res->get_complex()) + (*tmp + prev) * step / 2.0 );
1591
1592 gotprev = true;
1593 prev = *tmp;
1594 }
1595 }
1596
1597 *x_var = tmp_x_var;
1598 if( negate_result )
1599 res->set_complex( Complex(Real(0)) - *res->get_complex() );
1600 }
1601
builtin_nsolve(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1602 void builtin_nsolve(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1603 {
1604 Variable func, *x_var, tmp_res;
1605 Complex point, step, tmp, prev;
1606 int sign;
1607
1608 only_right;
1609
1610 if( res == 0 )
1611 return;
1612
1613 {
1614 utf8_string func_str,var_name;
1615
1616 point = Complex( 0 );
1617 step = Complex( Real(1,1000000) );
1618 argument_check( "nSolve", right,
1619 type_string, &func_str,
1620 type_name, &var_name,
1621 type_complex_default, &point,
1622 type_complex_default, &step,
1623 type_end );
1624
1625 func.set_code_line( func_str.c_str() );
1626
1627 if(private_varlist)
1628 {
1629 try{
1630 x_var = private_varlist->get_pointer_rw( private_varlist->get_id( var_name.c_str() ) );
1631 }
1632 catch(...) {
1633 x_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
1634 }
1635 }
1636 else
1637 x_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
1638 }
1639
1640 for(int i=0;i<1000;i++)
1641 {
1642 // Calculates nDeriv at point
1643 x_var->set_complex(point + step);
1644 func.calc_code_line( &tmp_res );
1645
1646 if( tmp_res.get_type() != VariableType_Complex )
1647 {
1648 char tmp_err[ERROR_OBJ_MSG_LEN];
1649 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "nSolve" );
1650 THROW_ERROR( ErrorType_General, tmp_err );
1651 }
1652
1653 tmp = *tmp_res.get_complex();
1654
1655 x_var->set_complex(point - step);
1656 func.calc_code_line( &tmp_res );
1657
1658 if( tmp_res.get_type() != VariableType_Complex )
1659 {
1660 char tmp_err[ERROR_OBJ_MSG_LEN];
1661 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "nSolve" );
1662 THROW_ERROR( ErrorType_General, tmp_err );
1663 }
1664
1665 tmp = (tmp - *tmp_res.get_complex()) / (2.0 * step);
1666
1667 if( floatx(tmp.real) < 0.0 )
1668 {
1669 if((sign == 1) & (i > 10))
1670 THROW_ERROR( ErrorType_General, _("No solution found") );
1671 sign = -1;
1672 }
1673 else
1674 {
1675 if((sign == -1) & (i > 10))
1676 THROW_ERROR( ErrorType_General, _("No solution found") );
1677 sign = 1;
1678 }
1679 // tmp = nDeriv
1680
1681 x_var->set_complex(point);
1682 func.calc_code_line( &tmp_res );
1683
1684 if( tmp_res.get_type() != VariableType_Complex )
1685 {
1686 char tmp_err[ERROR_OBJ_MSG_LEN];
1687 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "nSolve" );
1688 THROW_ERROR( ErrorType_General, tmp_err );
1689 }
1690
1691 tmp = point - *tmp_res.get_complex() / tmp;
1692
1693 if(tmp == point) // solution found
1694 break;
1695
1696 if(i >= 1 && tmp == prev)
1697 { // solution is between tmp and point...
1698 point = (point + tmp) / floatx(2.0); // this probobly doesn't make it more accurate..but it wont hurt
1699 break;
1700 }
1701
1702 prev = point;
1703 point = tmp;
1704 }
1705 res->set_complex( point );
1706 }
1707
builtin_picture(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1708 void builtin_picture(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1709 {
1710 Picture pic;
1711 int64 width,height;
1712 floatx xmin, xmax, bottom, top;
1713 Matrix colormatrix;
1714
1715 only_right;
1716
1717 if( res == 0 )
1718 return;
1719
1720 colorrgb_to_colormatrix( picture_h::color::WHITE, &colormatrix);
1721 xmin = -10.0;
1722 bottom = xmin;
1723 xmax = 10.0;
1724 top = xmax;
1725
1726 argument_check( "picture", right,
1727 type_int64, &width,
1728 type_int64, &height,
1729 type_floatx_default, &xmin,
1730 type_floatx_default, &xmax,
1731 type_floatx_default, &bottom,
1732 type_floatx_default, &top,
1733 type_matrix_default, &colormatrix,
1734 type_end );
1735
1736 colormatrix_to_colorrgb( colormatrix, &pic.bgcolor );
1737
1738 pic.set_size( width, height, xmin, xmax, bottom, top );
1739 pic.clear();
1740
1741 res->set_picture( &pic );
1742 }
1743
builtin_shade(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1744 void builtin_shade(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1745 {
1746 Variable func1, func2, res1, res2, *x_var;
1747 Picture pic;
1748 const Complex *tmp1, *tmp2;
1749 picture_h::colorrgb color;
1750 floatx x, xstep, xmax;
1751 int64 shade = 1;
1752 int32 x_val;
1753
1754 only_right;
1755
1756 if( res == 0 )
1757 return;
1758
1759 {
1760 utf8_string func1_str,func2_str,var_name;
1761 Matrix colormatrix;
1762
1763 colorrgb_to_colormatrix( picture_h::color::BLUE, &colormatrix);
1764
1765 argument_check( "shade", right,
1766 type_picture, &pic,
1767 type_string, &func1_str,
1768 type_string, &func2_str,
1769 type_name, &var_name,
1770 type_floatx, &x,
1771 type_floatx, &xmax,
1772 type_int64_default, &shade,
1773 type_matrix_default, &colormatrix,
1774 type_end );
1775
1776 func1.set_code_line( func1_str.c_str() );
1777 func2.set_code_line( func2_str.c_str() );
1778
1779 if(private_varlist)
1780 {
1781 try{
1782 x_var = private_varlist->get_pointer_rw( private_varlist->get_id( var_name.c_str() ) );
1783 }
1784 catch(...) {
1785 x_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
1786 }
1787 }
1788 else
1789 x_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
1790
1791 if(x > xmax)
1792 {
1793 xstep = x;
1794 x = xmax;
1795 xmax = xstep;
1796 }
1797
1798 if(shade < 0)
1799 shade = 1;
1800 colormatrix_to_colorrgb( colormatrix, &color );
1801 }
1802
1803 xstep = (pic.get_right() - pic.get_left()) / floatx(pic.pic.get_width());
1804 xstep *= floatx(shade+1);
1805
1806 x_val = pic.get_x_pixel( x );
1807
1808
1809 for( ;x<=xmax; x+=xstep, x_val += (1+int32(shade)) )
1810 {
1811 x_var->set_complex( Complex( x ) );
1812 func1.calc_code_line( &res1 );
1813 func2.calc_code_line( &res2 );
1814
1815 if( res1.get_type() != VariableType_Complex || res2.get_type() != VariableType_Complex )
1816 continue;
1817
1818 tmp1 = res1.get_complex();
1819 tmp2 = res2.get_complex();
1820 if( floatx(tmp1->imaginary) == 0.0 && floatx(tmp2->imaginary) == 0.0 )
1821 pic.pic.line( x_val, pic.get_y_pixel( floatx(tmp1->real) ),
1822 x_val, pic.get_y_pixel( floatx(tmp2->real) ), color);
1823 }
1824
1825 res->set_picture( &pic );
1826 }
1827
builtin_axes(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1828 void builtin_axes(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1829 {
1830 Picture *pic;
1831 picture_h::colorrgb color;
1832 Matrix colormatrix;
1833 floatx scalex, scaley;
1834 int64 length = 3;
1835
1836 both_left_and_right;
1837
1838 if( left->get_type() != VariableType_Picture )
1839 {
1840 char tmp_err[ERROR_OBJ_MSG_LEN];
1841 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "axes" );
1842 THROW_ERROR( ErrorType_General, tmp_err );
1843 }
1844
1845 pic = left->get_picture_rw();
1846
1847 scalex = 1.0;
1848 scaley = scalex;
1849 colorrgb_to_colormatrix( picture_h::color::BLACK, &colormatrix);
1850
1851 argument_check( "axes", right,
1852 type_floatx_default, &scalex,
1853 type_floatx_default, &scaley,
1854 type_int64_default, &length,
1855 type_matrix_default, &colormatrix,
1856 type_end );
1857
1858 if( length < 0 || length > 100 || scalex < 0.0 || scaley < 0.0 )
1859 THROW_ERROR( ErrorType_Domain, _("Domain error: Value out of range.") );
1860 colormatrix_to_colorrgb( colormatrix, &color );
1861
1862 pic->line( 0.0, pic->get_top(), 0.0, pic->get_bottom(), false, color );
1863
1864 pic->line( pic->get_left(), 0.0, pic->get_right(), 0.0, false, color );
1865
1866 {
1867 int32 x0,y0;
1868 floatx act_scale,start,stop;
1869
1870 x0 = pic->get_x_pixel( 0.0 );
1871 y0 = pic->get_y_pixel( 0.0 );
1872
1873 if((scalex != 0.0) & (length > 0))
1874 {
1875 start = truncx( pic->get_left() / scalex ) * scalex - scalex;
1876 if( (pic->get_right()-pic->get_left())/scalex > pic->pic.get_width())
1877 act_scale = (pic->get_right()-pic->get_left()) / floatx(pic->pic.get_width());
1878 else
1879 act_scale = scalex;
1880 stop = pic->get_right();
1881 for(;start <= stop;start += act_scale)
1882 {
1883 if( start > (act_scale/2.0) || start < (-act_scale/2.0) )
1884 pic->pic.line( pic->get_x_pixel(start), y0, pic->get_x_pixel(start), y0-length, color );
1885 }
1886 }
1887 if((scalex != 0.0) & (length > 0))
1888 {
1889 start = truncx( pic->get_bottom() / scaley ) * scaley - scaley;
1890 if( (pic->get_top()-pic->get_bottom())/scaley > pic->pic.get_height())
1891 act_scale = (pic->get_top()-pic->get_bottom()) / floatx(pic->pic.get_height());
1892 else
1893 act_scale = scaley;
1894 stop = pic->get_top();
1895 for(;start <= stop;start += act_scale)
1896 {
1897 if( start > (act_scale/2.0) || start < (-act_scale/2.0) )
1898 pic->pic.line( x0, pic->get_y_pixel(start), x0+length, pic->get_y_pixel(start), color );
1899 }
1900 }
1901 }
1902 left->signal_changed();
1903
1904 if( res != 0 )
1905 res->set_void();
1906 }
1907
builtin_grid(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)1908 void builtin_grid(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
1909 {
1910 Picture *pic;
1911 picture_h::colorrgb color;
1912 Matrix colormatrix;
1913 floatx scale1, scale2;
1914 utf8_string type;
1915 bool antialiasing = false;
1916
1917 both_left_and_right;
1918
1919 if( left->get_type() != VariableType_Picture )
1920 {
1921 char tmp_err[ERROR_OBJ_MSG_LEN];
1922 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "grid" );
1923 THROW_ERROR( ErrorType_General, tmp_err );
1924 }
1925
1926 pic = left->get_picture_rw();
1927
1928 scale1 = 1.0;
1929 scale2 = 1.0;
1930 type = "Rect";
1931 colorrgb_to_colormatrix( picture_h::color::LIGHT_GRAY, &colormatrix);
1932
1933 argument_check( "grid", right,
1934 type_string_default, &type,
1935 type_floatx_default, &scale1,
1936 type_floatx_default, &scale2,
1937 type_boolean_default, &antialiasing,
1938 type_matrix_default, &colormatrix,
1939 type_end );
1940
1941 colormatrix_to_colorrgb( colormatrix, &color );
1942
1943
1944 if(type == "Rect")
1945 {
1946 floatx act_scale,start,stop;
1947 int32 x0,y0;
1948
1949 x0 = pic->get_x_pixel( 0.0 );
1950 y0 = pic->get_y_pixel( 0.0 );
1951
1952 if(scale1 != 0.0)
1953 {
1954 start = truncx( pic->get_left() / scale1 ) * scale1 - scale1;
1955 if( (pic->get_right()-pic->get_left())/scale1 > pic->pic.get_width())
1956 act_scale = (pic->get_right()-pic->get_left()) / floatx(pic->pic.get_width());
1957 else
1958 act_scale = scale1;
1959 stop = pic->get_right();
1960 for(;start <= stop;start += act_scale)
1961 pic->line( start, pic->get_top(), start, pic->get_bottom(), false, color );
1962 }
1963 if(scale2 != 0.0)
1964 {
1965 start = truncx( pic->get_bottom() / scale2 ) * scale2 - scale2;
1966 if( (pic->get_top()-pic->get_bottom())/scale2 > pic->pic.get_height())
1967 act_scale = (pic->get_top()-pic->get_bottom()) / floatx(pic->pic.get_height());
1968 else
1969 act_scale = scale2;
1970 stop = pic->get_top();
1971 for(;start <= stop;start += act_scale)
1972 pic->line( pic->get_left(), start, pic->get_right(), start, false, color );
1973 }
1974 }
1975 else if(type == "Polar")
1976 {
1977 floatx act_scale,start,stop;
1978
1979 if(scale1 != 0.0)
1980 {
1981 floatx tmp;
1982 stop = sqrtx( pic->get_left()*pic->get_left() + pic->get_top()*pic->get_top() );
1983 start = stop;
1984 tmp = sqrtx( pic->get_right()*pic->get_right() + pic->get_top()*pic->get_top() );
1985 stop = (stop > tmp) ? stop : tmp;
1986 start = (start < tmp) ? start : tmp;
1987 tmp = sqrtx( pic->get_right()*pic->get_right() + pic->get_bottom()*pic->get_bottom() );
1988 stop = (stop > tmp) ? stop : tmp;
1989 start = (start < tmp) ? start : tmp;
1990 tmp = sqrtx( pic->get_left()*pic->get_left() + pic->get_bottom()*pic->get_bottom() );
1991 stop = (stop > tmp) ? stop : tmp;
1992 start = (start < tmp) ? start : tmp;
1993 if( 0.0 >= pic->get_left() && 0.0 <= pic->get_right() && 0.0 >= pic->get_bottom() &&
1994 0.0 <= pic->get_top() )
1995 start = 0.0;
1996 else
1997 {
1998 if( fabsx(pic->get_left()) < start )
1999 start = fabsx(pic->get_left());
2000 if( fabsx(pic->get_right()) < start )
2001 start = fabsx(pic->get_right());
2002 if( fabsx(pic->get_top()) < start )
2003 start = fabsx(pic->get_top());
2004 if( fabsx(pic->get_bottom()) < start )
2005 start = fabsx(pic->get_bottom());
2006 }
2007
2008 if( (stop-start)/scale1 > sqrtx( floatx(pic->pic.get_height())*floatx(pic->pic.get_height())
2009 + floatx(pic->pic.get_width())*floatx(pic->pic.get_width()) ) )
2010 act_scale = (stop-start) / sqrtx( floatx(pic->pic.get_height())*floatx(pic->pic.get_height())
2011 + floatx(pic->pic.get_width())*floatx(pic->pic.get_width()) );
2012 else
2013 act_scale = scale1;
2014
2015 start = truncx(start / act_scale) * act_scale;
2016
2017 for(;start <= stop; start += act_scale)
2018 pic->pic.ellipse( pic->get_x_pixel(0.0), pic->get_y_pixel(0.0), uint32(start / pic->get_unit_x_pixel()),
2019 uint32(start / pic->get_unit_y_pixel()), color, antialiasing );
2020
2021 {
2022 floatx twopi = 2.0 * PI;
2023
2024 if(floatx(degfix.imaginary) != 0.0)
2025 THROW_ERROR( ErrorType_Domain, _("Domain error: Imaginary part must be zero.") );
2026 scale2 *= floatx(degfix.real);
2027
2028 for( tmp = 0.0; tmp < twopi; tmp += scale2 )
2029 pic->line( 0.0, 0.0, cosx(tmp)*stop, sinx(tmp)*stop, antialiasing, color );
2030 }
2031 }
2032 }
2033 else
2034 {
2035 error_obj error;
2036
2037 error.type = ErrorType_General;
2038 snprintf(error.msg,ERROR_OBJ_MSG_LEN, "Unknown symbol '%s'",type.c_str());
2039 throw error;
2040 }
2041 left->signal_changed();
2042
2043 if( res != 0 )
2044 res->set_void();
2045 }
2046
builtin_perm(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2047 void builtin_perm(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2048 {
2049 Integer i, i2, tmp;
2050
2051 only_right;
2052
2053 if( res == 0 )
2054 return;
2055
2056 argument_check( "perm", right,
2057 type_integer, &i,
2058 type_integer, &i2,
2059 type_end );
2060
2061 tmp.perm( i, i2 );
2062
2063 res->set_complex( Real( tmp ) );
2064 }
2065
builtin_comb(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2066 void builtin_comb(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2067 {
2068 Integer up, down, tmp;
2069
2070 only_right;
2071
2072 if( res == 0 )
2073 return;
2074
2075 argument_check( "comb", right,
2076 type_integer, &up,
2077 type_integer, &down,
2078 type_end );
2079
2080 tmp.comb( up, down );
2081
2082 res->set_complex( Real( tmp ) );
2083 }
2084
builtin_get_type(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2085 void builtin_get_type(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2086 {
2087 only_left;
2088
2089 if( res != 0 )
2090 res->set_string( VARIABLE_TYPE_NAMES[left->get_type()] );
2091 }
2092
builtin_set_point(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2093 void builtin_set_point(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2094 {
2095 floatx x,y;
2096 Matrix colormatrix;
2097 picture_h::colorrgb color;
2098
2099 both_left_and_right;
2100
2101 if( left->get_type() != VariableType_Picture )
2102 {
2103 char tmp_err[ERROR_OBJ_MSG_LEN];
2104 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "set_point" );
2105 THROW_ERROR( ErrorType_General, tmp_err );
2106 }
2107
2108 colorrgb_to_colormatrix( picture_h::color::BLACK, &colormatrix );
2109
2110 argument_check( "set_point", right,
2111 type_floatx, &x,
2112 type_floatx, &y,
2113 type_matrix_default, &colormatrix,
2114 type_end );
2115
2116 colormatrix_to_colorrgb( colormatrix, &color );
2117
2118 left->get_picture_rw()->point( x, y, color);
2119 left->signal_changed();
2120
2121 if( res != 0 )
2122 res->set_void();
2123 }
2124
builtin_round_eval(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2125 void builtin_round_eval(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2126 {
2127 both_left_and_right;
2128
2129 switch(left->get_type())
2130 {
2131 case VariableType_String:
2132 eval_one_only:
2133 if(right->get_type() != VariableType_Array)
2134 {
2135 // setting the x-value
2136 Variable *xvar;
2137 xvar = global_varlist.get_pointer_rw( global_varlist.get_id("x") );
2138 *xvar = *right;
2139 // x is now set to the new value
2140 }
2141 else
2142 {
2143 Variable *xyvar;
2144 const Array *array;
2145
2146 array = right->get_array();
2147
2148 if( array->get_size() == 1 )
2149 {
2150 right = array->get_variable(0);
2151 goto eval_one_only;
2152 }
2153
2154 if( array->get_size() != 2 )
2155 THROW_ERROR( ErrorType_General, _("function(variable_values): Array's size don't match.") );
2156
2157
2158 // setting the x & y-value
2159 xyvar = global_varlist.get_pointer_rw( global_varlist.get_id("x") );
2160 *xyvar = *( array->get_variable(0) );
2161
2162 xyvar = global_varlist.get_pointer_rw( global_varlist.get_id("y") );
2163 *xyvar = *( array->get_variable(1) );
2164 // x & y is now set to the new value
2165 }
2166 left->calc_code_line( res );
2167 break;
2168
2169 default:
2170 builtin_mul( res, left, right, private_varlist );
2171 break;
2172 }
2173 }
2174
builtin_hook_set(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2175 void builtin_hook_set(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2176 {
2177 both_left_and_right;
2178
2179 switch( left->get_type() )
2180 {
2181 case VariableType_Array:
2182 {
2183 int64 index;
2184 Variable var;
2185 Array *array;
2186
2187 argument_check( "Array[index]=...", right, type_int64, &index,
2188 type_variable, &var, type_end );
2189
2190 array = left->get_array_rw();
2191
2192 if( index < 0 || index >= array->get_size() )
2193 THROW_ERROR( ErrorType_Domain, _("Domain error: Array[index]=...: index out of range") );
2194
2195 array->set_variable( index, var );
2196 left->signal_changed();
2197
2198 if( res != 0 )
2199 *res = var;
2200 }
2201 break;
2202
2203 case VariableType_Matrix:
2204 {
2205 int64 row, col;
2206 Complex val;
2207 Variable var;
2208 Matrix *matr;
2209
2210 argument_check( "Matrix[row,col]=...", right, type_variable, &var,
2211 type_complex, &val, type_end );
2212 argument_check( "Matrix[row,col]=...", &var, type_int64, &row,
2213 type_int64, &col, type_end );
2214
2215 matr = left->get_matrix_rw();
2216 if( row < 1 || row > matr->get_height() )
2217 THROW_ERROR( ErrorType_Domain, _("Domain error: Matrix[row,col]: row out of range") );
2218 if( col < 1 || col > matr->get_width() )
2219 THROW_ERROR( ErrorType_Domain, _("Domain error: Matrix[row,col]: col out of range") );
2220
2221 matr->set_complex( col, row, val);
2222 left->signal_changed();
2223
2224 if( res != 0 )
2225 res->set_complex( val );
2226 }
2227 break;
2228
2229 case VariableType_String:
2230 {
2231 utf8_string *str, ins_str;
2232 int64 start, length=1;
2233 Variable var;
2234
2235 argument_check( "String[start (,length)]=...", right,
2236 type_variable, &var,
2237 type_string, &ins_str,
2238 type_end );
2239 argument_check( "String[start (,length)]=...", &var,
2240 type_int64, &start,
2241 type_int64_default, &length,
2242 type_end );
2243
2244 str = left->get_string_rw();
2245 if( start < 0 || start >= str->get_length() )
2246 THROW_ERROR( ErrorType_Domain, _("Domain error: String[start (,length)]: start out of range") );
2247 if( length < 1 )
2248 THROW_ERROR( ErrorType_Domain, _("Domain error: String[start (,length)]: length out of range") );
2249
2250 try
2251 {
2252 str->replace( start, length, ins_str );
2253 left->signal_changed();
2254
2255 if( res != 0 )
2256 res->set_string( *str );
2257 }
2258 catch(error_obj error) { throw; }
2259 catch(...) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
2260 }
2261 break;
2262
2263 default:
2264 THROW_ERROR( ErrorType_General, _("Illegal variable type for 'var[index_expr]=...' syntax") );
2265 }
2266 }
2267
builtin_hook_get(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2268 void builtin_hook_get(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2269 {
2270 both_left_and_right;
2271
2272 switch( left->get_type() )
2273 {
2274 case VariableType_Array:
2275 {
2276 const Array *array;
2277 int64 index;
2278
2279 array = left->get_array();
2280
2281 argument_check( "Array[index]", right, type_int64, &index, type_end );
2282
2283 if( index < 0 || index >= array->get_size() )
2284 THROW_ERROR( ErrorType_Domain, _("Domain error: Array[index]: Index out of range") );
2285
2286 if( res != 0 )
2287 *res = *( array->get_variable(index) );
2288 }
2289 break;
2290
2291 case VariableType_Matrix:
2292 {
2293 const Matrix *matr;
2294 int64 row, col;
2295
2296 matr = left->get_matrix();
2297
2298 argument_check( "Matrix[row,col]", right, type_int64, &row,
2299 type_int64, &col, type_end );
2300
2301 if( row < 1 || row > matr->get_height() )
2302 THROW_ERROR( ErrorType_General, _("Domain error: Matrix[row,col]: row out of range") );
2303 if( col < 1 || col > matr->get_width() )
2304 THROW_ERROR( ErrorType_General, _("Domain error: Matrix[row,col]: col out of range") );
2305
2306 if( res != 0 )
2307 res->set_complex( matr->get_complex(col,row) );
2308 }
2309 break;
2310
2311 case VariableType_String:
2312 {
2313 const utf8_string *str;
2314 int64 start, length=1;
2315
2316 str = left->get_string();
2317
2318 argument_check( "String[start (,length)]", right,
2319 type_int64, &start,
2320 type_int64_default, &length,
2321 type_end );
2322
2323 if( start < 0 || start >= str->get_length() )
2324 THROW_ERROR( ErrorType_Domain, _("Domain error: String[start (,length)]: start out of range") );
2325 if( length < 1 )
2326 THROW_ERROR( ErrorType_Domain, _("Domain error: String[start (,length)]: length out of range") );
2327
2328 if( res != 0 )
2329 {
2330 try
2331 {
2332 res->set_string( str->substr( start, length ) );
2333 }
2334 catch(error_obj error) { throw; }
2335 catch(...) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
2336 }
2337 }
2338 break;
2339
2340 default:
2341 THROW_ERROR( ErrorType_General, _("Illegal variable type for the 'var[index_expr]' syntax.") );
2342 }
2343 }
2344
builtin_set_pixel(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2345 void builtin_set_pixel(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2346 {
2347 floatx x,y;
2348 Matrix colormatrix;
2349 picture_h::colorrgb color;
2350
2351 both_left_and_right;
2352
2353 if( left->get_type() != VariableType_Picture )
2354 {
2355 char tmp_err[ERROR_OBJ_MSG_LEN];
2356 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "set_pixel" );
2357 THROW_ERROR( ErrorType_General, tmp_err );
2358 }
2359
2360 colorrgb_to_colormatrix( picture_h::color::BLACK, &colormatrix );
2361
2362 argument_check( "set_pixel", right,
2363 type_floatx, &x,
2364 type_floatx, &y,
2365 type_matrix_default, &colormatrix,
2366 type_end );
2367
2368 colormatrix_to_colorrgb( colormatrix, &color );
2369
2370 left->get_picture_rw()->pic.set_pixel( int32(x), int32(y), color);
2371 left->signal_changed();
2372
2373 if( res != 0 )
2374 res->set_void();
2375 }
2376
builtin_line(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2377 void builtin_line(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2378 {
2379 floatx x1,x2,y1,y2;
2380 Matrix colormatrix;
2381 picture_h::colorrgb color;
2382 bool antialiasing = false;
2383
2384 both_left_and_right;
2385
2386 if( left->get_type() != VariableType_Picture )
2387 {
2388 char tmp_err[ERROR_OBJ_MSG_LEN];
2389 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "line" );
2390 THROW_ERROR( ErrorType_General, tmp_err );
2391 }
2392
2393 colorrgb_to_colormatrix( picture_h::color::BLACK, &colormatrix );
2394
2395 argument_check( "line", right,
2396 type_floatx, &x1, type_floatx, &y1,
2397 type_floatx, &x2, type_floatx, &y2,
2398 type_boolean_default, &antialiasing,
2399 type_matrix_default, &colormatrix,
2400 type_end );
2401
2402 colormatrix_to_colorrgb( colormatrix, &color );
2403
2404 left->get_picture_rw()->line( x1, y1, x2, y2, antialiasing, color );
2405 left->signal_changed();
2406
2407 if( res != 0 )
2408 res->set_void();
2409 }
2410
builtin_pixel_line(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2411 void builtin_pixel_line(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2412 {
2413 floatx x1,x2,y1,y2;
2414 Matrix colormatrix;
2415 picture_h::colorrgb color;
2416 bool antialiasing = false;
2417
2418 both_left_and_right;
2419
2420 if( left->get_type() != VariableType_Picture )
2421 {
2422 char tmp_err[ERROR_OBJ_MSG_LEN];
2423 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "pixel_line" );
2424 THROW_ERROR( ErrorType_General, tmp_err );
2425 }
2426
2427 colorrgb_to_colormatrix( picture_h::color::BLACK, &colormatrix );
2428
2429 argument_check( "pixel_line", right,
2430 type_floatx, &x1, type_floatx, &y1,
2431 type_floatx, &x2, type_floatx, &y2,
2432 type_boolean_default, &antialiasing,
2433 type_matrix_default, &colormatrix,
2434 type_end );
2435
2436 colormatrix_to_colorrgb( colormatrix, &color );
2437 if( antialiasing )
2438 left->get_picture_rw()->pic.line_antialiasing( x1, y1, x2, y2, color );
2439 else
2440 left->get_picture_rw()->pic.line( int32(x1), int32(y1), int32(x2), int32(y2), color );
2441 left->signal_changed();
2442
2443 if( res != 0 )
2444 res->set_void();
2445 }
2446
builtin_circle(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2447 void builtin_circle(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2448 {
2449 Picture *pic;
2450 floatx x,y;
2451 int64 r;
2452 Matrix colormatrix;
2453 picture_h::colorrgb color;
2454 bool filled = false, antialiasing = false;
2455
2456 both_left_and_right;
2457
2458 if( left->get_type() != VariableType_Picture )
2459 {
2460 char tmp_err[ERROR_OBJ_MSG_LEN];
2461 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "circle" );
2462 THROW_ERROR( ErrorType_General, tmp_err );
2463 }
2464
2465 colorrgb_to_colormatrix( picture_h::color::BLACK, &colormatrix );
2466
2467 argument_check( "circle", right,
2468 type_floatx, &x,
2469 type_floatx, &y,
2470 type_int64, &r,
2471 type_boolean_default, &filled,
2472 type_boolean_default, &antialiasing,
2473 type_matrix_default, &colormatrix,
2474 type_end );
2475
2476 colormatrix_to_colorrgb( colormatrix, &color );
2477
2478 pic = left->get_picture_rw();
2479 if(filled)
2480 pic->pic.filled_circle( pic->get_x_pixel(x), pic->get_y_pixel(y), r, color, antialiasing );
2481 else
2482 pic->pic.circle( pic->get_x_pixel(x), pic->get_y_pixel(y), r, color, antialiasing );
2483 left->signal_changed();
2484
2485 if( res != 0 )
2486 res->set_void();
2487 }
2488
builtin_pixel_circle(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2489 void builtin_pixel_circle(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2490 {
2491 floatx x,y;
2492 int64 r;
2493 Matrix colormatrix;
2494 picture_h::colorrgb color;
2495 bool filled = false, antialiasing = false;
2496
2497 both_left_and_right;
2498
2499 if( left->get_type() != VariableType_Picture )
2500 {
2501 char tmp_err[ERROR_OBJ_MSG_LEN];
2502 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "pixel_circle" );
2503 THROW_ERROR( ErrorType_General, tmp_err );
2504 }
2505
2506 colorrgb_to_colormatrix( picture_h::color::BLACK, &colormatrix );
2507
2508 argument_check( "pixel_circle", right,
2509 type_floatx, &x,
2510 type_floatx, &y,
2511 type_int64, &r,
2512 type_boolean_default, &filled,
2513 type_boolean_default, &antialiasing,
2514 type_matrix_default, &colormatrix,
2515 type_end );
2516
2517 colormatrix_to_colorrgb( colormatrix, &color );
2518 if(filled)
2519 left->get_picture_rw()->pic.filled_circle( int32(x), int32(y), r, color);
2520 else
2521 left->get_picture_rw()->pic.circle( int32(x), int32(y), r, color, antialiasing );
2522 left->signal_changed();
2523
2524 if( res != 0 )
2525 res->set_void();
2526 }
2527
builtin_table2d(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2528 void builtin_table2d(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2529 {
2530 Variable func, *n_var, tmp, tmp_n_var, *n2_var, tmp_n2_var;
2531 Complex replace;
2532 Complex start, tmp_start, stop, step, start2, stop2, step2;
2533 Matrix matr;
2534 int64 steps, steps2;
2535 bool abort_on_error = true;
2536 bool all_failed_the_same = false;
2537 error_obj error;
2538 error.type = ErrorType_None;
2539
2540 only_right;
2541
2542 if( res == 0 )
2543 return;
2544
2545 {
2546 utf8_string func_str, var_name, var_name2;
2547
2548 replace = Complex( asinx(1.0) * 6.0, expx(2.0) ); // 3*pi + i*(e^2)
2549 argument_check( "table2d", right,
2550 type_string, &func_str,
2551 type_name, &var_name,
2552 type_complex, &start,
2553 type_complex, &stop,
2554 type_int64, &steps,
2555 type_name, &var_name2,
2556 type_complex, &start2,
2557 type_complex, &stop2,
2558 type_int64, &steps2,
2559 type_complex_default, &replace,
2560 type_end );
2561
2562 if( replace != Complex( asinx(1.0) * 6.0, expx(2.0) ) )
2563 abort_on_error = false;
2564
2565 if( steps <= 1 || steps2 <= 1 )
2566 THROW_ERROR( ErrorType_Domain, _("Domain error: Step must be greater than 1.") );
2567
2568 if( floatx(start.imaginary) != 0.0 || floatx(start2.imaginary) != 0.0 )
2569 THROW_ERROR( ErrorType_Domain, _("Domain error: Start must be a real value.") );
2570
2571 if( floatx(stop.imaginary) != 0.0 || floatx(stop2.imaginary) != 0.0 )
2572 THROW_ERROR( ErrorType_Domain, _("Domain error: Stop must be a real value.") );
2573
2574 step = (stop - start) / (steps-1);
2575 step2 = (stop2 - start2) / (steps2-1);
2576
2577 func.set_code_line( func_str.c_str() );
2578 if( private_varlist )
2579 {
2580 try{
2581 n_var = private_varlist->get_pointer_rw( private_varlist->get_id( var_name.c_str() ) );
2582 }
2583 catch(...) {
2584 n_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
2585 }
2586 }
2587 else
2588 n_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
2589 if( private_varlist )
2590 {
2591 try{
2592 n2_var = private_varlist->get_pointer_rw( private_varlist->get_id( var_name2.c_str() ) );
2593 }
2594 catch(...) {
2595 n2_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name2.c_str() ) );
2596 }
2597 }
2598 else
2599 n2_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name2.c_str() ) );
2600
2601 matr.set_size( uint32(steps), uint32(steps2) );
2602 }
2603 tmp_n_var = *n_var;
2604 tmp_n2_var = *n2_var;
2605
2606 if( start > stop || start2 > stop2 )
2607 THROW_ERROR( ErrorType_Domain, _("Domain error: Start mustn't be larger than stop.") );
2608
2609 tmp_start = start;
2610 for( int64 i2=0; i2 < steps2; start2 += step2, i2++ )
2611 {
2612 start = tmp_start;
2613 n2_var->set_complex( start2 );
2614 for( int64 i=0; i < steps; start += step, i++ )
2615 {
2616 n_var->set_complex( start );
2617 try{ func.calc_code_line( &tmp ); all_failed_the_same = false; }
2618 catch(error_obj error2)
2619 {
2620 if( error.type == ErrorType_None && i == 0 && i2 == 0 )
2621 {
2622 error = error2;
2623 all_failed_the_same = true;
2624 }
2625 else if( error.type != error2.type )
2626 all_failed_the_same = false;
2627
2628 if(abort_on_error)
2629 throw;
2630 else
2631 tmp.set_complex( replace );
2632 }
2633
2634 if( tmp.get_type() != VariableType_Complex )
2635 {
2636 if(abort_on_error)
2637 {
2638 try{ *n_var = tmp_n_var; *n2_var = tmp_n2_var; }
2639 catch(...) { } // this catch is empty not by mistake
2640 {
2641 char tmp_err[ERROR_OBJ_MSG_LEN];
2642 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "table2d" );
2643 THROW_ERROR( ErrorType_General, tmp_err );
2644 }
2645 }
2646 else
2647 tmp.set_complex( replace );
2648 }
2649
2650 matr.set_complex( i+1, i2+1, *tmp.get_complex() );
2651 }
2652 }
2653
2654 *n_var = tmp_n_var;
2655 *n2_var = tmp_n2_var;
2656
2657 if( all_failed_the_same )
2658 throw error;
2659
2660 res->set_matrix( &matr );
2661 }
2662
builtin_table(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2663 void builtin_table(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2664 {
2665 Variable func, *n_var, tmp, tmp_n_var;
2666 Complex replace;
2667 Complex start, stop, step;
2668 Matrix matr;
2669 int64 steps;
2670 bool abort_on_error = true;
2671 bool all_failed_the_same = false;
2672 error_obj error;
2673 error.type = ErrorType_None;
2674
2675 only_right;
2676
2677 if( res == 0 )
2678 return;
2679
2680 {
2681 utf8_string func_str,var_name;
2682
2683 replace = Complex( asinx(1.0) * 6.0, expx(2.0) ); // 3*pi + i*(e^2)
2684 argument_check( "table", right,
2685 type_string, &func_str,
2686 type_name, &var_name,
2687 type_complex, &start,
2688 type_complex, &stop,
2689 type_int64, &steps,
2690 type_complex_default, &replace,
2691 type_end );
2692
2693 if(replace != Complex( asinx(1.0) * 6.0, expx(2.0) ))
2694 abort_on_error = false;
2695
2696 if(steps <= 1)
2697 THROW_ERROR( ErrorType_Domain, _("Domain error: Step must be greater than 1.") );
2698
2699 if( floatx(start.imaginary) != 0.0 )
2700 THROW_ERROR( ErrorType_Domain, _("Domain error: Imaginary part must be zero.") );
2701
2702 if( floatx(stop.imaginary) != 0.0 )
2703 THROW_ERROR( ErrorType_Domain, _("Domain error: Imaginary part must be zero.") );
2704
2705 step = (stop - start) / (steps-1);
2706
2707 func.set_code_line( func_str.c_str() );
2708 if(private_varlist)
2709 {
2710 try{
2711 n_var = private_varlist->get_pointer_rw( private_varlist->get_id( var_name.c_str() ) );
2712 }
2713 catch(...) {
2714 n_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
2715 }
2716 }
2717 else
2718 n_var = global_varlist.get_pointer_rw( global_varlist.get_id( var_name.c_str() ) );
2719
2720 matr.set_size( uint32(steps), 1 );
2721 }
2722 tmp_n_var = *n_var;
2723
2724 if(start > stop)
2725 THROW_ERROR( ErrorType_Domain, _("Domain error: Start mustn't be larger than stop.") );
2726
2727 for( int64 i=0; i < steps; start += step,i++ )
2728 {
2729 n_var->set_complex( start );
2730 try{ func.calc_code_line( &tmp ); all_failed_the_same = false; }
2731 catch(error_obj error2)
2732 {
2733 if( error.type == ErrorType_None && i == 0 )
2734 {
2735 error = error2;
2736 all_failed_the_same = true;
2737 }
2738 else if( error.type != error2.type )
2739 all_failed_the_same = false;
2740
2741 if(abort_on_error)
2742 throw;
2743 else
2744 tmp.set_complex( replace );
2745 }
2746
2747 if(tmp.get_type() != VariableType_Complex)
2748 {
2749 if(abort_on_error)
2750 {
2751 try{ *n_var = tmp_n_var; }
2752 catch(...) { } // this catch is empty not by mistake
2753 {
2754 char tmp_err[ERROR_OBJ_MSG_LEN];
2755 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "table" );
2756 THROW_ERROR( ErrorType_General, tmp_err );
2757 }
2758 }
2759 else
2760 tmp.set_complex( replace );
2761 }
2762
2763 matr.set_complex( i+1, 1, *tmp.get_complex() );
2764 }
2765
2766 *n_var = tmp_n_var;
2767
2768 if(all_failed_the_same)
2769 throw error;
2770
2771 res->set_matrix( &matr );
2772 }
2773
builtin_plot(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)2774 void builtin_plot(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
2775 {
2776 enum PLOT_MARKS { PLOT_DOT, PLOT_PLUS, PLOT_SQUARE, PLOT_RHOMB, PLOT_HEART };
2777 enum PLOT_MODES { MODE_DOTS, MODE_CONNECTED, MODE_CONNECTED_WITHOUT_ASYMPTOTES };
2778 Picture *pic;
2779 Complex tmp;
2780 picture_h::colorrgb color;
2781 Matrix xlist, ylist;
2782 floatx x, y;
2783 PLOT_MARKS mark = PLOT_PLUS;
2784 PLOT_MODES plot_mode;
2785 int64 size = 2;
2786 bool abort = true, prev = false, antialiasing = false;
2787 float *vertex=0, *vertex_mark=0;
2788 uint32 *lines=0, *lines_mark=0, nroflines=0, next_vertex=0;
2789
2790 both_left_and_right;
2791
2792 if( left->get_type() != VariableType_Picture )
2793 {
2794 char tmp_err[ERROR_OBJ_MSG_LEN];
2795 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "plot" );
2796 THROW_ERROR( ErrorType_General, tmp_err );
2797 }
2798
2799 pic = left->get_picture_rw();
2800
2801 {
2802 utf8_string smark("Plus"), splot_mode( "Dots" );
2803 Matrix colormatrix;
2804
2805 colorrgb_to_colormatrix( picture_h::color::BLUE, &colormatrix );
2806
2807 argument_check( "plot", right,
2808 type_matrix, &xlist,
2809 type_matrix, &ylist,
2810 type_string_default, &splot_mode,
2811 type_string_default, &smark,
2812 type_int64_default, &size,
2813 type_boolean_default, &abort,
2814 type_boolean_default, &antialiasing,
2815 type_matrix_default, &colormatrix,
2816 type_end );
2817
2818 if(smark == "Dot")
2819 mark = PLOT_DOT;
2820 else if(smark == "Plus")
2821 mark = PLOT_PLUS;
2822 else if(smark == "Square")
2823 mark = PLOT_SQUARE;
2824 else if(smark == "Rhomb")
2825 mark = PLOT_RHOMB;
2826 else if(smark == "Heart")
2827 mark = PLOT_HEART;
2828 else
2829 {
2830 smark.prepend( _("Unknown mark: ") );
2831 THROW_ERROR( ErrorType_General, smark.c_str() );
2832 }
2833
2834 if( splot_mode == "Dots" )
2835 plot_mode = MODE_DOTS;
2836 else if(splot_mode == "Connected" )
2837 plot_mode = MODE_CONNECTED;
2838 else if(splot_mode == "Connected without asymptotes" )
2839 plot_mode = MODE_CONNECTED_WITHOUT_ASYMPTOTES;
2840 else
2841 {
2842 splot_mode.prepend( _("Unknown plot mode: ") );
2843 THROW_ERROR( ErrorType_General, splot_mode.c_str() );
2844 }
2845
2846 if( size < 0 || size > 50 )
2847 THROW_ERROR( ErrorType_Domain, _("Domain error: Value out of range.") );
2848
2849 colormatrix_to_colorrgb( colormatrix, &color );
2850 }
2851
2852 if( xlist.get_width() != ylist.get_width() || xlist.get_height() != 1 ||
2853 ylist.get_height() != 1 )
2854 THROW_ERROR( ErrorType_General, _("Matrix size don't match") );
2855
2856 try
2857 {
2858 if( plot_mode != MODE_DOTS )
2859 {
2860 try{
2861 vertex = new float [xlist.get_width()*2];
2862 lines = new uint32 [xlist.get_width()*2];
2863 }
2864 catch( ... ) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
2865 }
2866 if( antialiasing )
2867 {
2868 try{
2869 vertex_mark = new float [12];
2870 lines_mark = new uint32 [12];
2871 }
2872 catch( ... ) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
2873
2874 if( mark == PLOT_PLUS )
2875 {
2876 lines_mark[0] = 0;
2877 lines_mark[1] = 2;
2878 lines_mark[2] = 4;
2879 lines_mark[3] = 6;
2880 }
2881 else
2882 {
2883 lines_mark[0] = 0;
2884 lines_mark[1] = 2;
2885 lines_mark[2] = 2;
2886 lines_mark[3] = 4;
2887 lines_mark[4] = 4;
2888 lines_mark[5] = 6;
2889 lines_mark[6] = 6;
2890 lines_mark[7] = 8;
2891 lines_mark[8] = 8;
2892 lines_mark[9] = 10;
2893 lines_mark[10] = 10;
2894 lines_mark[11] = 0;
2895 }
2896 }
2897
2898 for(uint32 i=0;i<xlist.get_width();i++)
2899 {
2900 tmp = xlist.get_complex(i+1,1);
2901 if( floatx(tmp.imaginary) != 0.0)
2902 {
2903 if(abort)
2904 {
2905 THROW_ERROR( ErrorType_Domain, _("Domain error: Imaginary part must be zero.") );
2906 }
2907 else
2908 {
2909 prev = false;
2910 continue;
2911 }
2912 }
2913 x = floatx(tmp.real);
2914
2915 tmp = ylist.get_complex(i+1,1);
2916 if( floatx(tmp.imaginary) != 0.0)
2917 {
2918 if(abort)
2919 {
2920 THROW_ERROR( ErrorType_Domain, _("Domain error: Imaginary part must be zero.") );
2921 }
2922 else
2923 {
2924 prev = false;
2925 continue;
2926 }
2927 }
2928 y = floatx(tmp.real);
2929
2930 if( size == 0 )
2931 {
2932 if( plot_mode == MODE_DOTS )
2933 pic->point( x, y, color );
2934 }
2935 else
2936 {
2937 switch(mark)
2938 {
2939 case PLOT_DOT:
2940 pic->pic.filled_circle( pic->get_x_pixel(x), pic->get_y_pixel(y), uint32(size),
2941 color, antialiasing);
2942 break;
2943
2944 case PLOT_PLUS:
2945 { // this mark doesn't look better in antialiased mode, so no such mode exists
2946 int32 tx,ty;
2947 tx = pic->get_x_pixel( x );
2948 ty = pic->get_y_pixel( y );
2949
2950 pic->pic.line(tx-size,ty,tx+size,ty,color);
2951 pic->pic.line(tx,ty-size,tx,ty+size,color);
2952 }
2953 break;
2954
2955 case PLOT_SQUARE:
2956 // this mark doesn't look better in antialiased mode, so no such mode exists
2957 pic->pic.box( pic->get_x_pixel( x )-size, pic->get_y_pixel( y )-size,
2958 2*size, 2*size, color );
2959 break;
2960
2961 case PLOT_RHOMB:
2962 if( antialiasing )
2963 {
2964 float fx, fy ,fsize=float(size);
2965 fx = pic->get_float_x_pixel(x);
2966 fy = pic->get_float_y_pixel(y);
2967
2968 vertex_mark[0] = fx-fsize;
2969 vertex_mark[1] = fy;
2970 vertex_mark[2] = fx;
2971 vertex_mark[3] = fy-fsize;
2972 vertex_mark[4] = fx+fsize;
2973 vertex_mark[5] = fy;
2974 vertex_mark[6] = fx;
2975 vertex_mark[7] = fy+fsize;
2976 vertex_mark[8] = fx-fsize;
2977 vertex_mark[9] = fy;
2978 pic->pic.draw_lines( vertex_mark, lines_mark, 4, color, true );
2979 }
2980 else
2981 {
2982 int32 tx,ty;
2983 tx = pic->get_x_pixel( x );
2984 ty = pic->get_y_pixel( y );
2985
2986 pic->pic.line(tx-size,ty,tx,ty-size,color);
2987 pic->pic.line(tx,ty-size,tx+size,ty,color);
2988 pic->pic.line(tx+size,ty,tx,ty+size,color);
2989 pic->pic.line(tx,ty+size,tx-size,ty,color);
2990 }
2991 break;
2992
2993 case PLOT_HEART:
2994 if( antialiasing )
2995 {
2996 float fx, fy, fsize = float(size);
2997 fx = pic->get_float_x_pixel(x);
2998 fy = pic->get_float_y_pixel(y);
2999
3000 vertex_mark[0] = fx;
3001 vertex_mark[1] = fy;
3002 vertex_mark[2] = fx+fsize/2.0f;
3003 vertex_mark[3] = fy-fsize/2.0f;
3004 vertex_mark[4] = fx+fsize;
3005 vertex_mark[5] = fy;
3006 vertex_mark[6] = fx;
3007 vertex_mark[7] = fy+fsize*1.5f;
3008 vertex_mark[8] = fx-fsize;
3009 vertex_mark[9] = fy;
3010 vertex_mark[10] = fx-fsize/2.0f;
3011 vertex_mark[11] = fy-fsize/2.0f;
3012 pic->pic.draw_lines( vertex_mark, lines_mark, 6, color, true );
3013 }
3014 else
3015 {
3016 int32 tx,ty;
3017 tx = pic->get_x_pixel( x );
3018 ty = pic->get_y_pixel( y );
3019
3020 pic->pic.line( tx, ty, tx+size/2, ty-size/2, color );
3021 pic->pic.line( tx+size/2, ty-size/2, tx+size, ty, color );
3022 pic->pic.line( tx+size, ty, tx, ty+(size*3)/2, color );
3023
3024 pic->pic.line( tx, ty, tx-size/2, ty-size/2, color );
3025 pic->pic.line( tx-size/2, ty-size/2, tx-size, ty, color );
3026 pic->pic.line( tx-size, ty, tx, ty+(size*3)/2, color );
3027 }
3028 break;
3029
3030 default:
3031 THROW_ERROR( ErrorType_Internal, "Internal error: Unknown mark" );
3032 }
3033 }
3034
3035 if( plot_mode != MODE_DOTS )
3036 {
3037 vertex[next_vertex] = pic->get_float_x_pixel(x);
3038 vertex[next_vertex+1] = pic->get_float_y_pixel(y);
3039 next_vertex += 2;
3040 }
3041 if( prev )
3042 {
3043 if( plot_mode == MODE_CONNECTED )
3044 {
3045 lines[nroflines*2] = next_vertex-4;
3046 lines[nroflines*2+1] = next_vertex-2;
3047 nroflines++;
3048 }
3049 else if( plot_mode == MODE_CONNECTED_WITHOUT_ASYMPTOTES )
3050 {
3051 if( !( vertex[next_vertex-3] < 0.0f &&
3052 vertex[next_vertex-1] > float(pic->pic.get_height()) ||
3053 vertex[next_vertex-3] > float(pic->pic.get_height()) &&
3054 vertex[next_vertex-1] < 0.0f ) )
3055 {
3056 lines[nroflines*2] = next_vertex-4;
3057 lines[nroflines*2+1] = next_vertex-2;
3058 nroflines++;
3059 }
3060 }
3061 }
3062 prev = true;
3063 }
3064 }
3065 catch( ... )
3066 {
3067 if( plot_mode != MODE_DOTS )
3068 {
3069 delete [] vertex;
3070 delete [] lines;
3071 }
3072 if( antialiasing )
3073 {
3074 delete [] vertex_mark;
3075 delete [] lines_mark;
3076 }
3077 left->signal_changed();
3078 throw;
3079 }
3080 if( plot_mode != MODE_DOTS )
3081 {
3082 pic->pic.draw_lines( vertex, lines, nroflines, color, antialiasing );
3083
3084 delete [] vertex;
3085 delete [] lines;
3086 }
3087 if( antialiasing )
3088 {
3089 delete [] vertex_mark;
3090 delete [] lines_mark;
3091 }
3092 left->signal_changed();
3093
3094 if( res != 0 )
3095 res->set_void();
3096 }
3097
builtin_polyreg(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3098 void builtin_polyreg(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3099 {
3100 utf8_string str, tmp_str;
3101 Matrix x, y, a, b;
3102 Complex tmp;
3103 int64 grad, max_decimals=10;
3104 Format fmt;
3105
3106 only_right;
3107
3108 if( res == 0 )
3109 return;
3110
3111 argument_check( "polyreg", right,
3112 type_matrix, &x, type_matrix, &y,
3113 type_int64, &grad,
3114 type_int64_default, &max_decimals,
3115 type_end );
3116
3117 if( x.get_width() != y.get_width() || x.get_height() != 1 || y.get_height() != 1 )
3118 THROW_ERROR( ErrorType_General, _("Matrix size don't match") );
3119
3120 if( max_decimals < 0 || max_decimals > 50 )
3121 THROW_ERROR( ErrorType_Domain, _("Domain error: Value out of range.") );
3122
3123 if( grad < 0 || grad > 99 )
3124 THROW_ERROR( ErrorType_Domain, _("Domain error: Value out of range.") );
3125
3126 if( grad >= x.get_width() )
3127 THROW_ERROR( ErrorType_Domain, _("Domain error: Value out of range.") );
3128
3129 // Setting the a and b Matrix up
3130 a.set_size(grad+1,x.get_width());
3131 {
3132 uint32 row,col;
3133 for(row=1;row<=a.get_height();row++)
3134 {
3135 tmp = x.get_complex(row,1);
3136 if( floatx(tmp.imaginary) != 0.0)
3137 THROW_ERROR( ErrorType_Domain, ("Domain error: Imaginary part must be zero.") );
3138
3139 for(col=1;col<=a.get_width();col++)
3140 a.set_complex( col, row, Complex( powx( floatx(tmp.real), floatx(col-1)) ) );
3141 }
3142 }
3143 b = y;
3144 b.trans();
3145 // a and b Matrix done
3146
3147 // make the calculating bit
3148 x = a;
3149 x.trans();
3150 matrix_mul(&y,&x,&a); // y = (trans(a)*a)
3151 y.inverse(); // y = ((trans(a)*a)^-1)
3152 matrix_mul(&a,&y,&x); // a = ((trans(a)*a)^-1) * trans(a)
3153 matrix_mul(&x,&a,&b); // x = ((trans(a)*a)^-1) * trans(a) * b ... minstakvadrat anpassat
3154 // calculating done
3155
3156 {
3157 Complex tmpcomplex;
3158 bool changed_sign;
3159
3160 fmt.set_max_decimals( max_decimals );
3161
3162 try
3163 {
3164 for(int32 i=grad;i>=0;i--)
3165 {
3166 tmpcomplex = x.get_complex(1,i+1);
3167 changed_sign = false;
3168 if(( floatx(tmpcomplex.imaginary) == 0.0) & (floatx(tmpcomplex.real) < 0.0) & (i != grad))
3169 {
3170 changed_sign = true;
3171 tmpcomplex = -tmpcomplex;
3172 }
3173
3174 if(i != grad)
3175 {
3176 if(changed_sign)
3177 tmp_str = " - ";
3178 else
3179 tmp_str = " + ";
3180 str.append( tmp_str );
3181 }
3182
3183 if( floatx(tmpcomplex.imaginary) != 0.0 )
3184 {
3185 tmp_str = "(";
3186 str.append( tmp_str );
3187 }
3188
3189 tmpcomplex.append_to_string( str, fmt );
3190
3191 if( floatx(tmpcomplex.imaginary) != 0.0 )
3192 {
3193 tmp_str = ")";
3194 str.append( tmp_str );
3195 }
3196
3197 if( i >= 2 )
3198 {
3199 char tmp[10];
3200 snprintf( tmp, 10, " x^%ld", i );
3201 tmp_str = tmp;
3202 str.append( tmp_str );
3203 }
3204 else if( i == 1 )
3205 {
3206 tmp_str = " x";
3207 str.append( tmp_str );
3208 }
3209 }
3210 }
3211 catch(error_obj error) { throw; }
3212 catch(...) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
3213 }
3214
3215 res->set_string( str );
3216 }
3217
builtin_set_window(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3218 void builtin_set_window(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3219 {
3220 Picture *pic;
3221 floatx newleft,newright,newbottom,newtop;
3222
3223 both_left_and_right;
3224
3225 if( left->get_type() != VariableType_Picture )
3226 {
3227 char tmp_err[ERROR_OBJ_MSG_LEN];
3228 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "set_window" );
3229 THROW_ERROR( ErrorType_General, tmp_err );
3230 }
3231
3232 argument_check( "set_window", right,
3233 type_floatx, &newleft,
3234 type_floatx, &newright,
3235 type_floatx, &newbottom,
3236 type_floatx, &newtop,
3237 type_end );
3238
3239 pic = left->get_picture_rw();
3240 pic->set_window(newleft, newright, newbottom, newtop);
3241 pic->clear();
3242 left->signal_changed();
3243
3244 if( res != 0 )
3245 res->set_void();
3246 }
3247
builtin_get_width(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3248 void builtin_get_width(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3249 {
3250 uint32 width;
3251
3252 only_left;
3253
3254 switch( left->get_type() )
3255 {
3256 case VariableType_Picture:
3257 width = left->get_picture()->pic.get_width();
3258 break;
3259
3260 case VariableType_Matrix:
3261 width = left->get_matrix()->get_width();
3262 break;
3263
3264 case VariableType_Array:
3265 width = left->get_array()->get_size();
3266 break;
3267
3268 case VariableType_String:
3269 width = left->get_string()->get_length();
3270 break;
3271
3272 default:
3273 {
3274 char tmp_err[ERROR_OBJ_MSG_LEN];
3275 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "get_width" );
3276 THROW_ERROR( ErrorType_General, tmp_err );
3277 }
3278 }
3279
3280 if( res != 0 )
3281 res->set_complex( Complex( int64(width) ) );
3282 }
3283
builtin_get_height(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3284 void builtin_get_height(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3285 {
3286 uint32 height;
3287
3288 only_left;
3289
3290 switch( left->get_type() )
3291 {
3292 case VariableType_Picture:
3293 height = left->get_picture()->pic.get_height();
3294 break;
3295
3296 case VariableType_Matrix:
3297 height = left->get_matrix()->get_height();
3298 break;
3299
3300 default:
3301 {
3302 char tmp_err[ERROR_OBJ_MSG_LEN];
3303 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "get_height" );
3304 THROW_ERROR( ErrorType_General, tmp_err );
3305 }
3306 }
3307
3308 if( res != 0 )
3309 res->set_complex( Complex( int64(height) ) );
3310 }
3311
builtin_clear(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3312 void builtin_clear(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3313 {
3314 only_right;
3315
3316 switch(right->get_type())
3317 {
3318 case VariableType_Picture:
3319 {
3320 Picture pic = *right->get_picture();
3321
3322 pic.clear();
3323
3324 if( res != 0 )
3325 res->set_picture( &pic );
3326 }
3327 break;
3328
3329 case VariableType_Matrix:
3330 {
3331 Matrix matr = *right->get_matrix();
3332
3333 matr.fill( Complex( 0 ) );
3334
3335 if( res != 0 )
3336 res->set_matrix( &matr );
3337 }
3338 break;
3339
3340 default:
3341 {
3342 char tmp_err[ERROR_OBJ_MSG_LEN];
3343 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "clear" );
3344 THROW_ERROR( ErrorType_General, tmp_err );
3345 }
3346 }
3347 }
3348
builtin_get_left(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3349 void builtin_get_left(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3350 {
3351 only_left;
3352
3353 if(left->get_type() != VariableType_Picture)
3354 {
3355 char tmp_err[ERROR_OBJ_MSG_LEN];
3356 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "get_left" );
3357 THROW_ERROR( ErrorType_General, tmp_err );
3358 }
3359
3360 if( res != 0 )
3361 res->set_complex( Complex( left->get_picture()->get_left() ) );
3362 }
3363
builtin_get_right(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3364 void builtin_get_right(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3365 {
3366 only_left;
3367
3368 if(left->get_type() != VariableType_Picture)
3369 {
3370 char tmp_err[ERROR_OBJ_MSG_LEN];
3371 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "get_right" );
3372 THROW_ERROR( ErrorType_General, tmp_err );
3373 }
3374
3375 if( res != 0 )
3376 res->set_complex( Complex( left->get_picture()->get_right() ) );
3377 }
3378
builtin_get_top(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3379 void builtin_get_top(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3380 {
3381 only_left;
3382
3383 if(left->get_type() != VariableType_Picture)
3384 {
3385 char tmp_err[ERROR_OBJ_MSG_LEN];
3386 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "get_top" );
3387 THROW_ERROR( ErrorType_General, tmp_err );
3388 }
3389
3390 if( res != 0 )
3391 res->set_complex( Complex( left->get_picture()->get_top() ) );
3392 }
3393
builtin_get_bottom(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3394 void builtin_get_bottom(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3395 {
3396 only_left;
3397
3398 if(left->get_type() != VariableType_Picture)
3399 {
3400 char tmp_err[ERROR_OBJ_MSG_LEN];
3401 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "get_bottom" );
3402 THROW_ERROR( ErrorType_General, tmp_err );
3403 }
3404
3405 if( res != 0 )
3406 res->set_complex( Complex( left->get_picture()->get_bottom() ) );
3407 }
3408
builtin_dec(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3409 void builtin_dec(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3410 {
3411 Complex tmp;
3412
3413 only_right;
3414
3415 if( res == 0 )
3416 return;
3417
3418 if(right->get_type() == VariableType_Complex)
3419 {
3420 tmp = *(right->get_complex());
3421
3422 tmp.real = floatx(tmp.real);
3423 tmp.imaginary = floatx(tmp.imaginary);
3424
3425 res->set_complex( tmp );
3426 }
3427 else if(right->get_type() == VariableType_Matrix)
3428 {
3429 Matrix matr;
3430
3431 matr = *right->get_matrix();
3432
3433 for(uint32 y=1; y <= matr.get_height() ; y++)
3434 {
3435 for(uint32 x=1; x <= matr.get_width() ; x++)
3436 {
3437 tmp = matr.get_complex( x, y );
3438
3439 tmp.real = floatx(tmp.real);
3440 tmp.imaginary = floatx(tmp.imaginary);
3441
3442 matr.set_complex( x, y, tmp );
3443 }
3444 }
3445
3446 res->set_matrix( &matr );
3447 }
3448 else
3449 {
3450 char tmp_err[ERROR_OBJ_MSG_LEN];
3451 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "dec" );
3452 THROW_ERROR( ErrorType_General, tmp_err );
3453 }
3454 }
3455
builtin_frac(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3456 void builtin_frac(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3457 {
3458 only_right;
3459 Complex tmp;
3460 Variable var;
3461 Integer highest_bottom(1000);
3462
3463 if( res == 0 )
3464 return;
3465
3466 argument_check( "frac", right,
3467 type_variable, &var,
3468 type_integer_default, &highest_bottom,
3469 type_end );
3470
3471 if( highest_bottom > int32_max )
3472 THROW_ERROR( ErrorType_Domain, _("Domain error: The denominator mustn't be larger than 2^31-1.") );
3473
3474 if(var.get_type() == VariableType_Complex)
3475 {
3476 tmp = *(var.get_complex());
3477
3478 tmp.real = frac(tmp.real, int64(highest_bottom) );
3479 tmp.imaginary = frac(tmp.imaginary, int64(highest_bottom));
3480
3481 res->set_complex( tmp );
3482 }
3483 else if(var.get_type() == VariableType_Matrix)
3484 {
3485 Matrix matr;
3486 uint32 x,y;
3487
3488 matr = *(var.get_matrix());
3489
3490 for(y=1; y <= matr.get_height(); y++)
3491 {
3492 for(x=1; x <= matr.get_width(); x++)
3493 {
3494 tmp = matr.get_complex( x, y );
3495
3496 tmp.real = frac(tmp.real, int64(highest_bottom) );
3497 tmp.imaginary = frac(tmp.imaginary, int64(highest_bottom) );
3498
3499 matr.set_complex( x, y, tmp );
3500 }
3501 }
3502
3503 res->set_matrix( &matr );
3504 }
3505 else
3506 {
3507 char tmp_err[ERROR_OBJ_MSG_LEN];
3508 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "frac" );
3509 THROW_ERROR( ErrorType_General, tmp_err );
3510 }
3511 }
3512
builtin_get_col(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3513 void builtin_get_col(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3514 {
3515 both_left_and_right;
3516 Matrix matr, dest;
3517 int64 c;
3518 uint32 col, row;
3519
3520 if( res == 0 )
3521 return;
3522
3523 argument_check( "get_col", left,
3524 type_matrix, &matr,
3525 type_end );
3526 argument_check( "get_col", right,
3527 type_int64, &c,
3528 type_end );
3529
3530 if( c <= 0 || c > int64(matr.get_width()) )
3531 THROW_ERROR( ErrorType_Domain, _("Domain error: Value out of range.") );
3532
3533 col = c;
3534 dest.set_size( 1, matr.get_height() );
3535
3536 for( row=1; row <= matr.get_height(); row++ )
3537 dest.set_complex( 1, row, matr.get_complex( col, row ) );
3538
3539 res->set_matrix( &dest );
3540 }
3541
builtin_get_row(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3542 void builtin_get_row(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3543 {
3544 both_left_and_right;
3545 Matrix matr, dest;
3546 int64 r;
3547 uint32 col, row;
3548
3549 if( res == 0 )
3550 return;
3551
3552 argument_check( "get_row", left,
3553 type_matrix, &matr,
3554 type_end );
3555 argument_check( "get_row", right,
3556 type_int64, &r,
3557 type_end );
3558
3559 if( r <= 0 || r > int64(matr.get_width()) )
3560 THROW_ERROR( ErrorType_Domain, _("Domain error: Value out of range.") );
3561
3562 row = r;
3563 dest.set_size( matr.get_width(), 1 );
3564
3565 for( col=1; col <= matr.get_width(); col++ )
3566 dest.set_complex( col, 1, matr.get_complex( col, row ) );
3567
3568 res->set_matrix( &dest );
3569 }
3570
builtin_error(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3571 void builtin_error(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3572 {
3573 only_right;
3574
3575 utf8_string str, type("General");
3576 error_obj error;
3577
3578 argument_check( "error", right,
3579 type_string, &str,
3580 type_string_default, &type,
3581 type_end );
3582
3583 if( type == "General" )
3584 error.type = ErrorType_UmpCode_General;
3585 else if( type == "Domain" )
3586 error.type = ErrorType_UmpCode_Domain;
3587 else if( type == "Divide by zero" )
3588 error.type = ErrorType_UmpCode_Divide_by_zero;
3589 else
3590 {
3591 error_obj error;
3592 error.type = ErrorType_General;
3593 snprintf( error.msg, ERROR_OBJ_MSG_LEN, _("Unknown type (%s) in function error"), type.c_str() );
3594 throw error;
3595 }
3596 snprintf( error.msg, ERROR_OBJ_MSG_LEN, "%s", str.c_str() );
3597
3598 throw error;
3599 }
3600
builtin_merge(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3601 void builtin_merge(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3602 {
3603 both_left_and_right;
3604 utf8_string str;
3605 Matrix *matr, matr2, tmp;
3606 uint32 col, row;
3607
3608 if( left->get_type() != VariableType_Matrix )
3609 {
3610 char tmp_err[ERROR_OBJ_MSG_LEN];
3611 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "merge" );
3612 THROW_ERROR( ErrorType_General, tmp_err );
3613 }
3614
3615 argument_check( "merge", right,
3616 type_matrix, &matr2,
3617 type_string, &str,
3618 type_end );
3619
3620 matr = left->get_matrix_rw();
3621 if( matr->get_height() == 0 )
3622 *matr = matr2;
3623 else if( matr2.get_height() == 0 )
3624 ;
3625 else if( str == "Side" )
3626 {
3627 if( matr->get_height() != matr2.get_height() )
3628 THROW_ERROR( ErrorType_General, _("Matrix size don't match") );
3629
3630 tmp = *matr;
3631 matr->set_size( tmp.get_width() + matr2.get_width(), tmp.get_height() );
3632
3633 for( row=1; row <= tmp.get_height(); row++ )
3634 {
3635 for( col=1; col <= tmp.get_width(); col++ )
3636 matr->set_complex( col, row, tmp.get_complex( col, row ) );
3637
3638 for( col=1; col <= matr2.get_width(); col++ )
3639 matr->set_complex( col + tmp.get_width(), row, matr2.get_complex( col, row ) );
3640 }
3641 }
3642 else if( str == "Under" )
3643 {
3644 if( matr->get_width() != matr2.get_width() )
3645 THROW_ERROR( ErrorType_General, _("Matrix size don't match") );
3646
3647 tmp = *matr;
3648 matr->set_size( tmp.get_width(), tmp.get_height() + matr2.get_height() );
3649
3650 for( col=1; col <= tmp.get_width(); col++ )
3651 {
3652 for( row=1; row <= tmp.get_height(); row++ )
3653 matr->set_complex( col, row, tmp.get_complex( col, row ) );
3654
3655 for( row=1; row <= matr2.get_height(); row++ )
3656 matr->set_complex( col, row + tmp.get_height(), matr2.get_complex( col, row ) );
3657 }
3658 }
3659 else
3660 {
3661 char tmp_err[ERROR_OBJ_MSG_LEN];
3662 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Unknown symbol '%s'"), str.c_str() );
3663 THROW_ERROR( ErrorType_General, tmp_err );
3664 }
3665
3666 left->signal_changed();
3667
3668 if( res != 0 )
3669 res->set_void();
3670 }
3671
builtin_hook_set_next(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3672 void builtin_hook_set_next(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3673 {
3674 both_left_and_right;
3675
3676 if( left->get_type() != VariableType_Matrix )
3677 {
3678 char tmp_err[ERROR_OBJ_MSG_LEN];
3679 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "[set_next]" );
3680 THROW_ERROR( ErrorType_General, tmp_err );
3681 }
3682
3683 if( right->get_type() != VariableType_Complex )
3684 {
3685 char tmp_err[ERROR_OBJ_MSG_LEN];
3686 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "[set_next]" );
3687 THROW_ERROR( ErrorType_General, tmp_err );
3688 }
3689
3690 left->get_matrix_rw()->set_next( *right->get_complex() );
3691 left->signal_changed();
3692
3693 if( res != 0 )
3694 res->set_void();
3695 }
3696
builtin_matrix(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3697 void builtin_matrix(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3698 {
3699 only_right;
3700 int64 rows, cols;
3701 Matrix matr;
3702
3703 if( res == 0 )
3704 return;
3705
3706 argument_check( "matrix", right,
3707 type_int64, &rows,
3708 type_int64, &cols,
3709 type_end );
3710
3711 if( rows < 0 || rows > int64(uint32_max) || cols < 0 || cols > int64(uint32_max) )
3712 THROW_ERROR( ErrorType_Domain, _("Domain error: Rows/columns out of range.") );
3713
3714 matr.set_size( cols, rows );
3715
3716 res->set_matrix( &matr );
3717 }
3718
builtin_array(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3719 void builtin_array(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3720 {
3721 only_right;
3722 int64 size;
3723 Array array;
3724
3725 if( res == 0 )
3726 return;
3727
3728 argument_check( "array", right,
3729 type_int64, &size,
3730 type_end );
3731
3732 if( size < 0 || size > int64(uint32_max) )
3733 THROW_ERROR( ErrorType_Domain, _("Domain error: Array size out of range.") );
3734
3735 array.set_size( uint32(size) );
3736
3737 res->set_array( &array );
3738 }
3739
builtin_insert(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3740 void builtin_insert(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3741 {
3742 Variable var;
3743 int64 index;
3744
3745 both_left_and_right;
3746
3747 if( left->get_type() != VariableType_Array )
3748 {
3749 char tmp_err[ERROR_OBJ_MSG_LEN];
3750 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "insert" );
3751 THROW_ERROR( ErrorType_General, tmp_err );
3752 }
3753
3754 argument_check( "insert", right,
3755 type_variable, &var,
3756 type_int64, &index,
3757 type_end );
3758
3759 if( index == -1 )
3760 index = int64(uint32_max); // this will append the variable
3761
3762 if( index < 0 || index > int64(uint32_max) )
3763 THROW_ERROR( ErrorType_Domain, _("Domain error: Insert index out of range.") );
3764
3765 left->get_array_rw()->insert( &var, uint32(index) );
3766 left->signal_changed();
3767
3768 if( res != 0 )
3769 res->set_void();
3770 }
3771
builtin_append(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3772 void builtin_append(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3773 {
3774 both_left_and_right;
3775
3776 if( left->get_type() != VariableType_Array )
3777 {
3778 char tmp_err[ERROR_OBJ_MSG_LEN];
3779 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "append" );
3780 THROW_ERROR( ErrorType_General, tmp_err );
3781 }
3782
3783 left->get_array_rw()->insert( right, uint32_max );
3784 left->signal_changed();
3785
3786 if( res != 0 )
3787 res->set_void();
3788 }
3789
builtin_remove(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3790 void builtin_remove(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3791 {
3792 both_left_and_right;
3793 int64 index, range = 1;
3794
3795 if( left->get_type() != VariableType_Array )
3796 {
3797 char tmp_err[ERROR_OBJ_MSG_LEN];
3798 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "remove" );
3799 THROW_ERROR( ErrorType_General, tmp_err );
3800 }
3801
3802 argument_check( "remove", right,
3803 type_int64, &index,
3804 type_int64_default, &range,
3805 type_end );
3806
3807 if( index < 0 || index > int64(uint32_max) )
3808 THROW_ERROR( ErrorType_Domain, _("Domain error: Remove index out of range.") );
3809
3810 if( range < 0 || range > int64(uint32_max) )
3811 THROW_ERROR( ErrorType_Domain, _("Domain error: Remove index out of range.") );
3812
3813 left->get_array_rw()->remove_range( uint32(index), uint32(range) );
3814 left->signal_changed();
3815
3816 if( res != 0 )
3817 res->set_void();
3818 }
3819
builtin_array_of_two(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3820 void builtin_array_of_two(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3821 {
3822 // intern function used by CodeLine::parse_pow_mods
3823 both_left_and_right;
3824 Array array;
3825
3826 if( res == 0 )
3827 return;
3828
3829 array.add_variable( left );
3830 array.add_variable( right );
3831
3832 res->set_array( &array );
3833 }
3834
builtin_pow_mod(Variable * res,Variable * left,const Variable * right,VariableList * private_varlist)3835 void builtin_pow_mod(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist) throw(error_obj)
3836 {
3837 both_left_and_right;
3838 try
3839 {
3840 Integer n, p, m, tmp;
3841
3842
3843 if( res == 0 )
3844 return;
3845
3846 argument_check( "(powMod)", left,
3847 type_integer, &n,
3848 type_end );
3849
3850 argument_check( "(powMod)", right,
3851 type_integer, &p,
3852 type_integer, &m,
3853 type_end );
3854
3855 powMod( &tmp, n, p, m );
3856
3857 res->set_complex( Real( tmp ) );
3858 }
3859 catch( ... ) // if this failes, let's fall back to the normal pow and mod functions
3860 {
3861 Variable tmp;
3862
3863 if( right->get_type() != VariableType_Array )
3864 THROW_ERROR( ErrorType_Internal, "Internal error: (powMod)'s right isn't an array!!" );
3865
3866 const Array *array = right->get_array();
3867 if( array->get_size() != 2 )
3868 THROW_ERROR( ErrorType_Internal, "Internal error: (powMod)'s right array hasn't size 2!!" );
3869
3870 builtin_pow( &tmp, left, array->get_variable(0), private_varlist );
3871 builtin_modulo( res, &tmp, array->get_variable(1), private_varlist );
3872 }
3873 }
3874
3875 } // namespace math
3876