Improved semantics of look-in namespaces
[shapes.git] / source / coreelem.cc
blob824a3e07fd654793803d45472a49f67cffcebf60
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008 Henrik Tidefelt
19 #include <cmath>
21 #include "Shapes_Helpers_decls.h"
23 #include "shapescore.h"
24 #include "ast.h"
25 #include "globals.h"
26 #include "shapesexceptions.h"
27 #include "consts.h"
28 #include "simplepdfi.h"
29 #include "autoonoff.h"
31 #include <iostream>
32 #include <sstream>
33 #include <fstream>
34 #include <vector>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #define min(a,b) (((a)<(b))?(a):(b))
38 #define max(a,b) (((a)>(b))?(a):(b))
40 #ifdef RAND_MAX
41 /* Use definition from stdlib.h */
42 #define RANDOM_MAX RAND_MAX
43 #define TWO_DIV_RANDOM_MAX (2. / RAND_MAX)
44 #else
45 /* Use BSD man page specification. */
46 #define RANDOM_MAX (((long)(1)<<31)-1)
47 #define TWO_DIV_RANDOM_MAX (2. / ( ((long)(1)<<31)-1. ))
48 #endif
50 using namespace Shapes;
52 namespace Shapes
54 namespace Lang
56 class Core_mod : public Lang::CoreFunction
58 public:
59 Core_mod( const char * title ) : CoreFunction( title ) { }
60 virtual void
61 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
63 const size_t ARITY = 2;
64 CHECK_ARITY( args, ARITY, title_ );
66 try
68 typedef const Lang::Integer ArgType;
69 RefCountPtr< ArgType > num = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
70 RefCountPtr< ArgType > den = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 1, callLoc );
72 Kernel::ContRef cont = evalState->cont_;
73 cont->takeValue( Kernel::ValueRef( new Lang::Integer( num->val_ % den->val_ ) ),
74 evalState );
75 return;
77 catch( const NonLocalExit::NotThisType & ball )
79 /* Wrong type; never mind!.. but see below!
83 try
85 typedef const Lang::Float ArgType;
86 RefCountPtr< ArgType > num = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
87 RefCountPtr< ArgType > den = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 1, callLoc );
89 Kernel::ContRef cont = evalState->cont_;
90 cont->takeValue( Kernel::ValueRef( new Lang::Float( fmod( num->val_, den->val_ ) ) ),
91 evalState );
92 return;
94 catch( const NonLocalExit::NotThisType & ball )
96 /* Wrong type; never mind!.. but see below!
102 typedef const Lang::Length ArgType;
103 RefCountPtr< ArgType > num = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
104 RefCountPtr< ArgType > den = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 1, callLoc );
106 Kernel::ContRef cont = evalState->cont_;
107 cont->takeValue( Kernel::ValueRef( new Lang::Length( fmod( num->getScalar( ), den->getScalar( ) ) ) ),
108 evalState );
109 return;
111 catch( const NonLocalExit::NotThisType & ball )
113 /* Wrong type; never mind!.. but see below!
117 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::Integer::staticTypeName( ), Lang::Float::staticTypeName( ), Lang::Length::staticTypeName( ) ) );
121 class Core_floor : public Lang::CoreFunction
123 public:
124 Core_floor( const char * title ) : CoreFunction( title ) { }
125 virtual void
126 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
128 const size_t ARITY = 1;
129 CHECK_ARITY( args, ARITY, title_ );
131 typedef const Lang::Float ArgType;
132 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
134 Kernel::ContRef cont = evalState->cont_;
135 cont->takeValue( Kernel::ValueRef( new Lang::Integer( static_cast< Lang::Integer::ValueType >( floor( arg->val_ ) ) ) ),
136 evalState );
140 class Core_ceil : public Lang::CoreFunction
142 public:
143 Core_ceil( const char * title ) : CoreFunction( title ) { }
144 virtual void
145 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
147 const size_t ARITY = 1;
148 CHECK_ARITY( args, ARITY, title_ );
150 typedef const Lang::Float ArgType;
151 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
153 Kernel::ContRef cont = evalState->cont_;
154 cont->takeValue( Kernel::ValueRef( new Lang::Integer( static_cast< Lang::Integer::ValueType >( ceil( arg->val_ ) ) ) ),
155 evalState );
159 class Core_rint : public Lang::CoreFunction
161 public:
162 Core_rint( const char * title ) : CoreFunction( title ) { }
163 virtual void
164 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
166 const size_t ARITY = 1;
167 CHECK_ARITY( args, ARITY, title_ );
169 typedef const Lang::Float ArgType;
170 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
172 Kernel::ContRef cont = evalState->cont_;
173 cont->takeValue( Kernel::ValueRef( new Lang::Integer( static_cast< Lang::Integer::ValueType >( rint( arg->val_ ) ) ) ),
174 evalState );
178 class Core_cos : public Lang::CoreFunction
180 public:
181 Core_cos( const char * title ) : CoreFunction( title ) { }
182 virtual void
183 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
185 const size_t ARITY = 1;
186 CHECK_ARITY( args, ARITY, title_ );
188 typedef const Lang::Float ArgType;
189 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
191 Kernel::ContRef cont = evalState->cont_;
192 cont->takeValue( Kernel::ValueRef( new Lang::Float( cos( arg->val_ ) ) ),
193 evalState );
197 class Core_sin : public Lang::CoreFunction
199 public:
200 Core_sin( const char * title ) : CoreFunction( title ) { }
201 virtual void
202 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
204 const size_t ARITY = 1;
205 CHECK_ARITY( args, ARITY, title_ );
207 typedef const Lang::Float ArgType;
208 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
210 Kernel::ContRef cont = evalState->cont_;
211 cont->takeValue( Kernel::ValueRef( new Lang::Float( sin( arg->val_ ) ) ),
212 evalState );
216 class Core_tan : public Lang::CoreFunction
218 public:
219 Core_tan( const char * title ) : CoreFunction( title ) { }
220 virtual void
221 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
223 const size_t ARITY = 1;
224 CHECK_ARITY( args, ARITY, title_ );
226 typedef const Lang::Float ArgType;
227 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
229 Kernel::ContRef cont = evalState->cont_;
230 cont->takeValue( Kernel::ValueRef( new Lang::Float( tan( arg->val_ ) ) ),
231 evalState );
235 class Core_cot : public Lang::CoreFunction
237 public:
238 Core_cot( const char * title ) : CoreFunction( title ) { }
239 virtual void
240 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
242 const size_t ARITY = 1;
243 CHECK_ARITY( args, ARITY, title_ );
245 typedef const Lang::Float ArgType;
246 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
248 Kernel::ContRef cont = evalState->cont_;
249 cont->takeValue( Kernel::ValueRef( new Lang::Float( 1 / tan( arg->val_ ) ) ),
250 evalState );
254 class Core_arccos : public Lang::CoreFunction
256 public:
257 Core_arccos( const char * title ) : CoreFunction( title ) { }
258 virtual void
259 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
261 const size_t ARITY = 1;
262 CHECK_ARITY( args, ARITY, title_ );
264 typedef const Lang::Float ArgType;
265 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
267 Kernel::ContRef cont = evalState->cont_;
268 cont->takeValue( Kernel::ValueRef( new Lang::Float( acos( arg->val_ ) ) ),
269 evalState );
273 class Core_arcsin : public Lang::CoreFunction
275 public:
276 Core_arcsin( const char * title ) : CoreFunction( title ) { }
277 virtual void
278 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
280 const size_t ARITY = 1;
281 CHECK_ARITY( args, ARITY, title_ );
283 typedef const Lang::Float ArgType;
284 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
286 Kernel::ContRef cont = evalState->cont_;
287 cont->takeValue( Kernel::ValueRef( new Lang::Float( asin( arg->val_ ) ) ),
288 evalState );
292 class Core_arctan : public Lang::CoreFunction
294 public:
295 Core_arctan( const char * title ) : CoreFunction( title ) { }
296 virtual void
297 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
299 const size_t ARITY = 1;
300 CHECK_ARITY( args, ARITY, title_ );
302 typedef const Lang::Float ArgType;
303 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
305 Kernel::ContRef cont = evalState->cont_;
306 cont->takeValue( Kernel::ValueRef( new Lang::Float( atan( arg->val_ ) ) ),
307 evalState );
311 class Core_min : public Lang::CoreFunction
313 public:
314 Core_min( const char * title ) : CoreFunction( title ) { }
315 virtual void
316 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
318 if( args.empty( ) )
320 Kernel::ContRef cont = evalState->cont_;
321 cont->takeValue( Kernel::ValueRef( new Lang::Float( HUGE_VAL ) ),
322 evalState );
323 return;
327 typedef const Lang::Float ArgType;
328 size_t i = 0;
329 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( i ).getPtr( ) );
330 if( arg != 0 )
332 double res = arg->val_;
333 typedef typeof args ListType;
334 ++i;
335 const size_t & end = args.size( );
336 for( ; i != end; ++i )
338 res = min( res, Helpers::down_cast_CoreArgument< ArgType >( title_, args, i, callLoc )->val_ );
340 Kernel::ContRef cont = evalState->cont_;
341 cont->takeValue( Kernel::ValueRef( new ArgType( res ) ),
342 evalState );
343 return;
348 typedef const Lang::Length ArgType;
349 size_t i = 0;
350 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( i ).getPtr( ) );
351 if( arg != 0 )
353 Concrete::Length res = arg->get( );
354 typedef typeof args ListType;
355 ++i;
356 const size_t & end = args.size( );
357 for( ; i != end; ++i )
359 res = min( res, Helpers::down_cast_CoreArgument< ArgType >( title_, args, i, callLoc )->get( ) );
361 Kernel::ContRef cont = evalState->cont_;
362 cont->takeValue( Kernel::ValueRef( new ArgType( res ) ),
363 evalState );
364 return;
369 typedef const Lang::Integer ArgType;
370 size_t i = 0;
371 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( i ).getPtr( ) );
372 if( arg != 0 )
374 Lang::Integer::ValueType res = arg->val_;
375 typedef typeof args ListType;
376 ++i;
377 const size_t & end = args.size( );
378 for( ; i != end; ++i )
380 res = min( res, Helpers::down_cast_CoreArgument< ArgType >( title_, args, i, callLoc )->val_ );
382 Kernel::ContRef cont = evalState->cont_;
383 cont->takeValue( Kernel::ValueRef( new ArgType( res ) ),
384 evalState );
385 return;
389 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::Float::staticTypeName( ), Lang::Integer::staticTypeName( ), Lang::Length::staticTypeName( ) ) );
393 class Core_max : public Lang::CoreFunction
395 public:
396 Core_max( const char * title ) : CoreFunction( title ) { }
397 virtual void
398 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
400 if( args.empty( ) )
402 Kernel::ContRef cont = evalState->cont_;
403 cont->takeValue( Kernel::ValueRef( new Lang::Float( -HUGE_VAL ) ),
404 evalState );
405 return;
409 typedef const Lang::Float ArgType;
410 size_t i = 0;
411 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( i ).getPtr( ) );
412 if( arg != 0 )
414 double res = arg->val_;
415 typedef typeof args ListType;
416 ++i;
417 const size_t & end = args.size( );
418 for( ; i != end; ++i )
420 res = max( res, Helpers::down_cast_CoreArgument< ArgType >( title_, args, i, callLoc )->val_ );
422 Kernel::ContRef cont = evalState->cont_;
423 cont->takeValue( Kernel::ValueRef( new ArgType( res ) ),
424 evalState );
425 return;
430 typedef const Lang::Length ArgType;
431 size_t i = 0;
432 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( i ).getPtr( ) );
433 if( arg != 0 )
435 Concrete::Length res = arg->get( );
436 typedef typeof args ListType;
437 ++i;
438 const size_t & end = args.size( );
439 for( ; i != end; ++i )
441 res = max( res, Helpers::down_cast_CoreArgument< ArgType >( title_, args, i, callLoc )->get( ) );
443 Kernel::ContRef cont = evalState->cont_;
444 cont->takeValue( Kernel::ValueRef( new ArgType( res ) ),
445 evalState );
446 return;
452 typedef const Lang::Integer ArgType;
453 size_t i = 0;
454 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( i ).getPtr( ) );
455 if( arg != 0 )
457 Lang::Integer::ValueType res = arg->val_;
458 typedef typeof args ListType;
459 ++i;
460 const size_t & end = args.size( );
461 for( ; i != end; ++i )
463 res = max( res, Helpers::down_cast_CoreArgument< ArgType >( title_, args, i, callLoc )->val_ );
465 Kernel::ContRef cont = evalState->cont_;
467 cont->takeValue( Kernel::ValueRef( new ArgType( res ) ),
468 evalState );
469 return;
473 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::Float::staticTypeName( ), Lang::Integer::staticTypeName( ), Lang::Length::staticTypeName( ) ) );
477 class Core_sqrt : public Lang::CoreFunction
479 public:
480 Core_sqrt( const char * title ) : CoreFunction( title ) { }
481 virtual void
482 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
484 const size_t ARITY = 1;
485 CHECK_ARITY( args, ARITY, title_ );
487 typedef const Lang::Float ArgType;
488 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
490 Kernel::ContRef cont = evalState->cont_;
491 cont->takeValue( Kernel::ValueRef( new Lang::Float( sqrt( arg->val_ ) ) ),
492 evalState );
496 class Core_angle : public Lang::CoreFunction
498 public:
499 Core_angle( const char * title ) : CoreFunction( title ) { }
500 virtual void
501 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
503 const size_t ARITY = 1;
504 CHECK_ARITY( args, ARITY, title_ );
507 typedef const Lang::Coords2D ArgType;
508 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
509 if( arg != 0 )
511 if( arg->x_.get( ) == 0 && arg->y_.get( ) == 0 )
513 throw Exceptions::CoreOutOfRange( title_, args, 0, "Can't take the angle of something of norm 0." );
515 Kernel::ContRef cont = evalState->cont_;
516 cont->takeValue( Kernel::ValueRef( new Lang::Float( atan2( arg->y_.getScalar( ), arg->x_.getScalar( ) ) ) ),
517 evalState );
518 return;
523 typedef const Lang::FloatPair ArgType;
524 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
525 if( arg != 0 )
527 if( arg->x_ == 0 && arg->y_ == 0 )
529 throw Exceptions::CoreOutOfRange( title_, args, 0, "Can't take the angle of something of norm 0." );
531 Kernel::ContRef cont = evalState->cont_;
532 cont->takeValue( Kernel::ValueRef( new Lang::Float( atan2( arg->y_, arg->x_ ) ) ),
533 evalState );
534 return;
538 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Interaction::SEVERAL_TYPES );
542 class Core_dir : public Lang::CoreFunction
544 public:
545 Core_dir( const char * title ) : CoreFunction( title ) { }
546 virtual void
547 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
549 const size_t ARITY = 1;
550 CHECK_ARITY( args, ARITY, title_ );
552 typedef const Lang::Float ArgType;
553 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
555 Kernel::ContRef cont = evalState->cont_;
556 cont->takeValue( Kernel::ValueRef( new Lang::FloatPair( cos( arg->val_ ), sin( arg->val_ ) ) ),
557 evalState );
561 class Core_abs : public Lang::CoreFunction
563 public:
564 Core_abs( const char * title ) : CoreFunction( title ) { }
565 virtual void
566 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
568 const size_t ARITY = 1;
569 CHECK_ARITY( args, ARITY, title_ );
571 const Lang::Value * untypedArg = args.getValue( 0 ).getPtr( );
574 typedef const Lang::Float ArgType;
575 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
576 if( arg != 0 )
578 Kernel::ContRef cont = evalState->cont_;
579 cont->takeValue( Kernel::ValueRef( new Lang::Float( fabs( arg->val_ ) ) ),
580 evalState );
581 return;
586 typedef const Lang::Length ArgType;
587 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
588 if( arg != 0 )
590 Kernel::ContRef cont = evalState->cont_;
591 cont->takeValue( Kernel::ValueRef( new Lang::Length( arg->get( ).abs( ) ) ),
592 evalState );
593 return;
598 typedef const Lang::FloatPair ArgType;
599 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
600 if( arg != 0 )
602 Kernel::ContRef cont = evalState->cont_;
603 cont->takeValue( Kernel::ValueRef( new Lang::Float( hypot( arg->x_, arg->y_ ) ) ),
604 evalState );
605 return;
610 typedef const Lang::Coords2D ArgType;
611 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
612 if( arg != 0 )
614 Kernel::ContRef cont = evalState->cont_;
615 cont->takeValue( Kernel::ValueRef( new Lang::Length( hypotPhysical( arg->x_.get( ), arg->y_.get( ) ) ) ),
616 evalState );
617 return;
622 typedef const Lang::FloatTriple ArgType;
623 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
624 if( arg != 0 )
626 Kernel::ContRef cont = evalState->cont_;
627 cont->takeValue( Kernel::ValueRef( new Lang::Float( Concrete::Scalar::hypot3( arg->x_, arg->y_, arg->z_ ) ) ),
628 evalState );
629 return;
634 typedef const Lang::Coords3D ArgType;
635 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
636 if( arg != 0 )
638 Kernel::ContRef cont = evalState->cont_;
639 cont->takeValue( Kernel::ValueRef( new Lang::Length( hypotPhysical( arg->x_.get( ), arg->y_.get( ), arg->z_.get( ) ) ) ),
640 evalState );
641 return;
646 typedef const Lang::ElementaryPath2D ArgType;
649 RefCountPtr< ArgType > p = Helpers::elementaryPathTry2D( args.getValue( 0 ) );
650 Kernel::ContRef cont = evalState->cont_;
651 cont->takeValue( RefCountPtr< const Lang::Length >( new Lang::Length( p->arcLength( ) ) ),
652 evalState );
653 return;
655 catch( NonLocalExit::NotThisType & ball )
657 /* Never mind */
662 typedef const Lang::ElementaryPath3D ArgType;
665 RefCountPtr< ArgType > p = Helpers::elementaryPathTry3D( args.getValue( 0 ) );
666 Kernel::ContRef cont = evalState->cont_;
667 cont->takeValue( RefCountPtr< const Lang::Length >( new Lang::Length( p->arcLength( ) ) ),
668 evalState );
669 return;
671 catch( NonLocalExit::NotThisType & ball )
673 /* Never mind */
678 typedef const Lang::Integer ArgType;
679 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
680 if( arg != 0 )
682 Kernel::ContRef cont = evalState->cont_;
683 cont->takeValue( Kernel::ValueRef( new Lang::Integer( ( arg->val_ >= 0 ) ? (arg->val_) : (-arg->val_) ) ),
684 evalState );
685 return;
690 typedef const Lang::Dash ArgType;
691 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
692 if( arg != 0 )
694 Kernel::ContRef cont = evalState->cont_;
695 cont->takeValue( Kernel::ValueRef( new Lang::Length( arg->length( ) ) ),
696 evalState );
697 return;
701 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Interaction::SEVERAL_TYPES );
705 class Core_normalized : public Lang::CoreFunction
707 public:
708 Core_normalized( const char * title ) : CoreFunction( title ) { }
709 virtual void
710 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
712 const size_t ARITY = 1;
713 CHECK_ARITY( args, ARITY, title_ );
716 typedef const Lang::FloatPair ArgType;
717 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
718 if( arg != 0 )
720 double norm = hypot( arg->x_, arg->y_ );
721 if( norm == 0 )
723 throw Exceptions::CoreOutOfRange( title_, args, 0, "Can't normalize something of norm 0" );
725 Kernel::ContRef cont = evalState->cont_;
726 cont->takeValue( Kernel::ValueRef( new Lang::FloatPair( arg->x_ / norm, arg->y_ / norm ) ),
727 evalState );
728 return;
733 typedef const Lang::Coords2D ArgType;
734 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
735 if( arg != 0 )
737 Concrete::Length norm = hypotPhysical( arg->x_.get( ), arg->y_.get( ) );
738 if( norm == 0 )
740 throw Exceptions::CoreOutOfRange( title_, args, 0, "Can't normalize something of norm 0" );
742 Kernel::ContRef cont = evalState->cont_;
743 cont->takeValue( Kernel::ValueRef( new Lang::FloatPair( arg->x_.get( ) / norm, arg->y_.get( ) / norm ) ),
744 evalState );
745 return;
750 typedef const Lang::FloatTriple ArgType;
751 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
752 if( arg != 0 )
754 double norm = Concrete::Scalar::hypot3( arg->x_, arg->y_, arg->z_ );
755 if( norm == 0 )
757 throw Exceptions::CoreOutOfRange( title_, args, 0, "Can't normalize something of norm 0" );
759 Kernel::ContRef cont = evalState->cont_;
760 cont->takeValue( Kernel::ValueRef( new Lang::FloatTriple( arg->x_ / norm, arg->y_ / norm, arg->z_ / norm ) ),
761 evalState );
762 return;
767 typedef const Lang::Coords3D ArgType;
768 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
769 if( arg != 0 )
771 Concrete::Length norm = hypotPhysical( arg->x_.get( ), arg->y_.get( ), arg->z_.get( ) );
772 if( norm == 0 )
774 throw Exceptions::CoreOutOfRange( title_, args, 0, "Can't normalize something of norm 0" );
776 Kernel::ContRef cont = evalState->cont_;
777 cont->takeValue( Kernel::ValueRef( new Lang::FloatTriple( arg->x_.get( ) / norm, arg->y_.get( ) / norm, arg->z_.get( ) / norm ) ),
778 evalState );
779 return;
784 typedef const Lang::Float ArgType;
785 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
786 if( arg != 0 )
788 if( arg->val_ > 0 )
790 Kernel::ContRef cont = evalState->cont_;
791 cont->takeValue( Kernel::ValueRef( new Lang::Float( 1 ) ),
792 evalState );
793 return;
795 if( arg->val_ < 0 )
797 Kernel::ContRef cont = evalState->cont_;
798 cont->takeValue( Kernel::ValueRef( new Lang::Float( -1 ) ),
799 evalState );
800 return;
802 throw Exceptions::CoreOutOfRange( title_, args, 0, "Can't normalize something of norm 0" );
807 typedef const Lang::Length ArgType;
808 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
809 if( arg != 0 )
811 if( arg->get( ) > 0 )
813 Kernel::ContRef cont = evalState->cont_;
814 cont->takeValue( Kernel::ValueRef( new Lang::Float( 1 ) ),
815 evalState );
816 return;
818 if( arg->get( ) < 0 )
820 Kernel::ContRef cont = evalState->cont_;
821 cont->takeValue( Kernel::ValueRef( new Lang::Float( -1 ) ),
822 evalState );
823 return;
825 throw Exceptions::CoreOutOfRange( title_, args, 0, "Can't normalize something of norm 0" );
830 typedef const Lang::Integer ArgType;
831 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
832 if( arg != 0 )
834 if( arg->val_ > 0 )
836 Kernel::ContRef cont = evalState->cont_;
837 cont->takeValue( Kernel::ValueRef( new Lang::Integer( 1 ) ),
838 evalState );
839 return;
841 if( arg->val_ < 0 )
843 Kernel::ContRef cont = evalState->cont_;
844 cont->takeValue( Kernel::ValueRef( new Lang::Integer( -1 ) ),
845 evalState );
846 return;
848 throw Exceptions::CoreOutOfRange( title_, args, 0, "Can't normalize something of norm 0" );
853 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Interaction::SEVERAL_TYPES );
857 class Core_cross : public Lang::CoreFunction
859 public:
860 Core_cross( const char * title ) : CoreFunction( title ) { }
861 virtual void
862 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
864 const size_t ARITY = 2;
865 CHECK_ARITY( args, ARITY, title_ );
867 double x1;
868 double y1;
869 double z1;
870 double x2;
871 double y2;
872 double z2;
873 bool isLength = false;
876 typedef const Lang::FloatTriple ArgType;
877 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
878 if( arg != 0 )
880 x1 = arg->x_;
881 y1 = arg->y_;
882 z1 = arg->z_;
883 goto secondArgument;
888 typedef const Lang::Coords3D ArgType;
889 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
890 if( arg != 0 )
892 isLength = true;
893 x1 = arg->x_.get( ).offtype< 1, 0 >( );
894 y1 = arg->y_.get( ).offtype< 1, 0 >( );
895 z1 = arg->z_.get( ).offtype< 1, 0 >( );
896 goto secondArgument;
900 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::FloatTriple::staticTypeName( ), Lang::Coords3D::staticTypeName( ) ) );
902 secondArgument:
904 typedef const Lang::FloatTriple ArgType;
905 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 1 ).getPtr( ) );
906 if( arg != 0 )
908 x2 = arg->x_;
909 y2 = arg->y_;
910 z2 = arg->z_;
911 goto multiplyArguments;
916 typedef const Lang::Coords3D ArgType;
917 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 1 ).getPtr( ) );
918 if( arg != 0 )
920 if( isLength )
922 throw Exceptions::CoreOutOfRange( title_, args, 1, "Can't multiply two coordinate vectors. Try normalizing one of them!" );
924 isLength = true;
925 x2 = arg->x_.get( ).offtype< 1, 0 >( );
926 y2 = arg->y_.get( ).offtype< 1, 0 >( );
927 z2 = arg->z_.get( ).offtype< 1, 0 >( );
928 goto multiplyArguments;
932 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 1, Helpers::typeSetString( Lang::FloatTriple::staticTypeName( ), Lang::Coords3D::staticTypeName( ) ) );
934 multiplyArguments:
935 Kernel::ContRef cont = evalState->cont_;
936 if( isLength )
938 cont->takeValue( Kernel::ValueRef( new Lang::Coords3D( Concrete::Length( y1*z2-z1*y2 ), Concrete::Length( z1*x2-x1*z2 ), Concrete::Length( x1*y2-y1*x2 ) ) ),
939 evalState );
941 else
943 cont->takeValue( Kernel::ValueRef( new Lang::FloatTriple( y1*z2-z1*y2, z1*x2-x1*z2, x1*y2-y1*x2 ) ),
944 evalState );
949 class Core_orthogonal : public Lang::CoreFunction
951 public:
952 Core_orthogonal( const char * title ) : CoreFunction( title ) { }
953 virtual void
954 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
956 const size_t ARITY = 1;
957 CHECK_ARITY( args, ARITY, title_ );
960 typedef const Lang::FloatPair ArgType;
961 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
962 if( arg != 0 )
964 Kernel::ContRef cont = evalState->cont_;
965 cont->takeValue( Kernel::ValueRef( new Lang::FloatPair( -arg->y_, arg->x_ ) ),
966 evalState );
967 return;
972 typedef const Lang::FloatTriple ArgType;
973 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
974 if( arg != 0 )
976 double x;
977 double y;
978 double z;
979 if( fabs( arg->x_ ) < fabs( arg->y_ ) )
981 // arg is more parallell to y; cross with x
982 x = 0;
983 y = - arg->z_;
984 z = arg->y_;
986 else
988 // arg is more parallell to x; cross with y
989 x = arg->z_;
990 y = 0;
991 z = - arg->x_;
993 double scale = sqrt( ( (arg->x_)*(arg->x_) + (arg->y_)*(arg->y_) + (arg->z_)*(arg->z_) ) / ( x*x + y*y + z*z ) );
994 Kernel::ContRef cont = evalState->cont_;
995 cont->takeValue( Kernel::ValueRef( new Lang::FloatTriple( x * scale, y * scale, z * scale ) ),
996 evalState );
997 return;
1001 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::FloatPair::staticTypeName( ), Lang::FloatTriple::staticTypeName( ) ) );
1005 class Core_randomNatural : public Lang::CoreFunction
1007 public:
1008 Core_randomNatural( const char * title )
1009 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1011 formals_->appendCoreStateFormal( "state" );
1013 virtual void
1014 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1016 args.applyDefaults( );
1018 typedef Kernel::WarmRandomState StateType;
1019 StateType * st = Helpers::down_cast_CoreState< StateType >( title_, args, 0, callLoc );
1021 st->setState( );
1023 Kernel::ContRef cont = evalState->cont_;
1024 cont->takeValue( Kernel::ValueRef( new Lang::Float( TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1 ) ),
1025 evalState );
1029 class Core_randomBall1D : public Lang::CoreFunction
1031 public:
1032 Core_randomBall1D( const char * title )
1033 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1035 formals_->appendCoreStateFormal( "state" );
1037 virtual void
1038 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1040 args.applyDefaults( );
1042 typedef Kernel::WarmRandomState StateType;
1043 StateType * st = Helpers::down_cast_CoreState< StateType >( title_, args, 0, callLoc );
1045 st->setState( );
1047 Kernel::ContRef cont = evalState->cont_;
1048 cont->takeValue( Kernel::ValueRef( new Lang::Float( TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1 ) ),
1049 evalState );
1053 class Core_randomBall2D : public Lang::CoreFunction
1055 public:
1056 Core_randomBall2D( const char * title )
1057 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1059 formals_->appendCoreStateFormal( "state" );
1061 virtual void
1062 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1064 args.applyDefaults( );
1066 typedef Kernel::WarmRandomState StateType;
1067 StateType * st = Helpers::down_cast_CoreState< StateType >( title_, args, 0, callLoc );
1069 st->setState( );
1071 double x1 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1072 double x2 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1073 while( x1 * x1 + x2 * x2 > 1 )
1075 x1 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1076 x2 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1079 Kernel::ContRef cont = evalState->cont_;
1080 cont->takeValue( Kernel::ValueRef( new Lang::FloatPair( x1, x2 ) ),
1081 evalState );
1085 class Core_randomBall3D : public Lang::CoreFunction
1087 public:
1088 Core_randomBall3D( const char * title )
1089 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1091 formals_->appendCoreStateFormal( "state" );
1093 virtual void
1094 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1096 args.applyDefaults( );
1098 typedef Kernel::WarmRandomState StateType;
1099 StateType * st = Helpers::down_cast_CoreState< StateType >( title_, args, 0, callLoc );
1101 st->setState( );
1103 double x1 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1104 double x2 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1105 double x3 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1106 while( x1 * x1 + x2 * x2 + x3 * x3 > 1 )
1108 x1 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1109 x2 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1110 x3 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1113 Kernel::ContRef cont = evalState->cont_;
1114 cont->takeValue( Kernel::ValueRef( new Lang::FloatTriple( x1, x2, x3 ) ),
1115 evalState );
1119 class Core_gensym : public Lang::CoreFunction
1121 public:
1122 Core_gensym( const char * title ) : CoreFunction( title ) { }
1123 virtual void call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1125 const size_t ARITY = 0;
1126 CHECK_ARITY( args, ARITY, title_ );
1128 Kernel::ContRef cont = evalState->cont_;
1129 cont->takeValue( Kernel::ValueRef( new Lang::Symbol( ) ),
1130 evalState );
1136 RefCountPtr< const Lang::CoreFunction > Lang::THE_FUNCTION_ABS( new Lang::Core_abs( "abs" ) );
1138 void
1139 Kernel::registerCore_elem( Kernel::Environment * env )
1141 env->initDefineCoreFunction( new Lang::Core_mod( "mod" ) );
1142 env->initDefineCoreFunction( new Lang::Core_ceil( "ceil" ) );
1143 env->initDefineCoreFunction( new Lang::Core_floor( "floor" ) );
1144 env->initDefineCoreFunction( new Lang::Core_rint( "round" ) );
1145 env->initDefineCoreFunction( new Lang::Core_cos( "cos" ) );
1146 env->initDefineCoreFunction( new Lang::Core_sin( "sin" ) );
1147 env->initDefineCoreFunction( new Lang::Core_tan( "tan" ) );
1148 env->initDefineCoreFunction( new Lang::Core_cot( "cot" ) );
1149 env->initDefineCoreFunction( new Lang::Core_arccos( "arccos" ) );
1150 env->initDefineCoreFunction( new Lang::Core_arcsin( "arcsin" ) );
1151 env->initDefineCoreFunction( new Lang::Core_arctan( "arctan" ) );
1152 env->initDefineCoreFunction( new Lang::Core_min( "min" ) );
1153 env->initDefineCoreFunction( new Lang::Core_max( "max" ) );
1154 env->initDefineCoreFunction( new Lang::Core_sqrt( "sqrt" ) );
1155 env->initDefineCoreFunction( Lang::THE_FUNCTION_ABS );
1156 env->initDefineCoreFunction( new Lang::Core_angle( "angle" ) );
1157 env->initDefineCoreFunction( new Lang::Core_dir( "dir" ) );
1158 env->initDefineCoreFunction( new Lang::Core_normalized( "normalized" ) );
1159 env->initDefineCoreFunction( new Lang::Core_cross( "cross" ) );
1160 env->initDefineCoreFunction( new Lang::Core_orthogonal( "orthogonal" ) );
1162 env->initDefineCoreFunction( new Lang::Core_randomNatural( "randomN" ) );
1163 env->initDefineCoreFunction( new Lang::Core_randomBall1D( "random1D" ) );
1164 env->initDefineCoreFunction( new Lang::Core_randomBall2D( "random2D" ) );
1165 env->initDefineCoreFunction( new Lang::Core_randomBall3D( "random3D" ) );
1167 env->initDefineCoreFunction( new Lang::Core_gensym( "gensym" ) );