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