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
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
21 #include "Shapes_Helpers_decls.h"
23 #include "shapescore.h"
26 #include "shapesexceptions.h"
28 #include "simplepdfi.h"
29 #include "autoonoff.h"
37 #define min(a,b) (((a)<(b))?(a):(b))
38 #define max(a,b) (((a)>(b))?(a):(b))
41 /* Use definition from stdlib.h */
42 #define RANDOM_MAX RAND_MAX
43 #define TWO_DIV_RANDOM_MAX (2. / RAND_MAX)
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. ))
50 using namespace Shapes
;
56 class Core_mod
: public Lang::CoreFunction
59 Core_mod( const char * title
) : CoreFunction( title
) { }
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_
);
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_
) ),
77 catch( const NonLocalExit::NotThisType
& ball
)
79 /* Wrong type; never mind!.. but see below!
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_
) ) ),
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( ) ) ) ),
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
124 Core_floor( const char * title
) : CoreFunction( title
) { }
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_
) ) ) ),
140 class Core_ceil
: public Lang::CoreFunction
143 Core_ceil( const char * title
) : CoreFunction( title
) { }
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_
) ) ) ),
159 class Core_rint
: public Lang::CoreFunction
162 Core_rint( const char * title
) : CoreFunction( title
) { }
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_
) ) ) ),
178 class Core_cos
: public Lang::CoreFunction
181 Core_cos( const char * title
) : CoreFunction( title
) { }
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_
) ) ),
197 class Core_sin
: public Lang::CoreFunction
200 Core_sin( const char * title
) : CoreFunction( title
) { }
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_
) ) ),
216 class Core_tan
: public Lang::CoreFunction
219 Core_tan( const char * title
) : CoreFunction( title
) { }
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_
) ) ),
235 class Core_cot
: public Lang::CoreFunction
238 Core_cot( const char * title
) : CoreFunction( title
) { }
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_
) ) ),
254 class Core_arccos
: public Lang::CoreFunction
257 Core_arccos( const char * title
) : CoreFunction( title
) { }
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_
) ) ),
273 class Core_arcsin
: public Lang::CoreFunction
276 Core_arcsin( const char * title
) : CoreFunction( title
) { }
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_
) ) ),
292 class Core_arctan
: public Lang::CoreFunction
295 Core_arctan( const char * title
) : CoreFunction( title
) { }
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_
) ) ),
311 class Core_min
: public Lang::CoreFunction
314 Core_min( const char * title
) : CoreFunction( title
) { }
316 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
320 Kernel::ContRef cont
= evalState
->cont_
;
321 cont
->takeValue( Kernel::ValueRef( new Lang::Float( HUGE_VAL
) ),
327 typedef const Lang::Float ArgType
;
329 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( i
).getPtr( ) );
332 double res
= arg
->val_
;
333 typedef typeof args ListType
;
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
) ),
348 typedef const Lang::Length ArgType
;
350 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( i
).getPtr( ) );
353 Concrete::Length res
= arg
->get( );
354 typedef typeof args ListType
;
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
) ),
369 typedef const Lang::Integer ArgType
;
371 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( i
).getPtr( ) );
374 Lang::Integer::ValueType res
= arg
->val_
;
375 typedef typeof args ListType
;
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
) ),
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
396 Core_max( const char * title
) : CoreFunction( title
) { }
398 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
402 Kernel::ContRef cont
= evalState
->cont_
;
403 cont
->takeValue( Kernel::ValueRef( new Lang::Float( -HUGE_VAL
) ),
409 typedef const Lang::Float ArgType
;
411 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( i
).getPtr( ) );
414 double res
= arg
->val_
;
415 typedef typeof args ListType
;
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
) ),
430 typedef const Lang::Length ArgType
;
432 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( i
).getPtr( ) );
435 Concrete::Length res
= arg
->get( );
436 typedef typeof args ListType
;
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
) ),
452 typedef const Lang::Integer ArgType
;
454 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( i
).getPtr( ) );
457 Lang::Integer::ValueType res
= arg
->val_
;
458 typedef typeof args ListType
;
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
) ),
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
480 Core_sqrt( const char * title
) : CoreFunction( title
) { }
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_
) ) ),
496 class Core_angle
: public Lang::CoreFunction
499 Core_angle( const char * title
) : CoreFunction( title
) { }
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( ) );
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( ) ) ) ),
523 typedef const Lang::FloatPair ArgType
;
524 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
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_
) ) ),
538 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, 0, Interaction::SEVERAL_TYPES
);
542 class Core_dir
: public Lang::CoreFunction
545 Core_dir( const char * title
) : CoreFunction( title
) { }
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_
) ) ),
561 class Core_abs
: public Lang::CoreFunction
564 Core_abs( const char * title
) : CoreFunction( title
) { }
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
);
578 Kernel::ContRef cont
= evalState
->cont_
;
579 cont
->takeValue( Kernel::ValueRef( new Lang::Float( fabs( arg
->val_
) ) ),
586 typedef const Lang::Length ArgType
;
587 ArgType
* arg
= dynamic_cast< ArgType
* >( untypedArg
);
590 Kernel::ContRef cont
= evalState
->cont_
;
591 cont
->takeValue( Kernel::ValueRef( new Lang::Length( arg
->get( ).abs( ) ) ),
598 typedef const Lang::FloatPair ArgType
;
599 ArgType
* arg
= dynamic_cast< ArgType
* >( untypedArg
);
602 Kernel::ContRef cont
= evalState
->cont_
;
603 cont
->takeValue( Kernel::ValueRef( new Lang::Float( hypot( arg
->x_
, arg
->y_
) ) ),
610 typedef const Lang::Coords2D ArgType
;
611 ArgType
* arg
= dynamic_cast< ArgType
* >( untypedArg
);
614 Kernel::ContRef cont
= evalState
->cont_
;
615 cont
->takeValue( Kernel::ValueRef( new Lang::Length( hypotPhysical( arg
->x_
.get( ), arg
->y_
.get( ) ) ) ),
622 typedef const Lang::FloatTriple ArgType
;
623 ArgType
* arg
= dynamic_cast< ArgType
* >( untypedArg
);
626 Kernel::ContRef cont
= evalState
->cont_
;
627 cont
->takeValue( Kernel::ValueRef( new Lang::Float( Concrete::Scalar::hypot3( arg
->x_
, arg
->y_
, arg
->z_
) ) ),
634 typedef const Lang::Coords3D ArgType
;
635 ArgType
* arg
= dynamic_cast< ArgType
* >( untypedArg
);
638 Kernel::ContRef cont
= evalState
->cont_
;
639 cont
->takeValue( Kernel::ValueRef( new Lang::Length( hypotPhysical( arg
->x_
.get( ), arg
->y_
.get( ), arg
->z_
.get( ) ) ) ),
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( ) ) ),
655 catch( NonLocalExit::NotThisType
& ball
)
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( ) ) ),
671 catch( NonLocalExit::NotThisType
& ball
)
678 typedef const Lang::Integer ArgType
;
679 ArgType
* arg
= dynamic_cast< ArgType
* >( untypedArg
);
682 Kernel::ContRef cont
= evalState
->cont_
;
683 cont
->takeValue( Kernel::ValueRef( new Lang::Integer( ( arg
->val_
>= 0 ) ? (arg
->val_
) : (-arg
->val_
) ) ),
690 typedef const Lang::Dash ArgType
;
691 ArgType
* arg
= dynamic_cast< ArgType
* >( untypedArg
);
694 Kernel::ContRef cont
= evalState
->cont_
;
695 cont
->takeValue( Kernel::ValueRef( new Lang::Length( arg
->length( ) ) ),
701 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, 0, Interaction::SEVERAL_TYPES
);
705 class Core_normalized
: public Lang::CoreFunction
708 Core_normalized( const char * title
) : CoreFunction( title
) { }
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( ) );
720 double norm
= hypot( arg
->x_
, arg
->y_
);
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
) ),
733 typedef const Lang::Coords2D ArgType
;
734 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
737 Concrete::Length norm
= hypotPhysical( arg
->x_
.get( ), arg
->y_
.get( ) );
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
) ),
750 typedef const Lang::FloatTriple ArgType
;
751 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
754 double norm
= Concrete::Scalar::hypot3( arg
->x_
, arg
->y_
, arg
->z_
);
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
) ),
767 typedef const Lang::Coords3D ArgType
;
768 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
771 Concrete::Length norm
= hypotPhysical( arg
->x_
.get( ), arg
->y_
.get( ), arg
->z_
.get( ) );
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
) ),
784 typedef const Lang::Float ArgType
;
785 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
790 Kernel::ContRef cont
= evalState
->cont_
;
791 cont
->takeValue( Kernel::ValueRef( new Lang::Float( 1 ) ),
797 Kernel::ContRef cont
= evalState
->cont_
;
798 cont
->takeValue( Kernel::ValueRef( new Lang::Float( -1 ) ),
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( ) );
811 if( arg
->get( ) > 0 )
813 Kernel::ContRef cont
= evalState
->cont_
;
814 cont
->takeValue( Kernel::ValueRef( new Lang::Float( 1 ) ),
818 if( arg
->get( ) < 0 )
820 Kernel::ContRef cont
= evalState
->cont_
;
821 cont
->takeValue( Kernel::ValueRef( new Lang::Float( -1 ) ),
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( ) );
836 Kernel::ContRef cont
= evalState
->cont_
;
837 cont
->takeValue( Kernel::ValueRef( new Lang::Integer( 1 ) ),
843 Kernel::ContRef cont
= evalState
->cont_
;
844 cont
->takeValue( Kernel::ValueRef( new Lang::Integer( -1 ) ),
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
860 Core_cross( const char * title
) : CoreFunction( title
) { }
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_
);
873 bool isLength
= false;
876 typedef const Lang::FloatTriple ArgType
;
877 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
888 typedef const Lang::Coords3D ArgType
;
889 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
893 x1
= arg
->x_
.get( ).offtype
< 1, 0 >( );
894 y1
= arg
->y_
.get( ).offtype
< 1, 0 >( );
895 z1
= arg
->z_
.get( ).offtype
< 1, 0 >( );
900 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, 0, Helpers::typeSetString( Lang::FloatTriple::staticTypeName( ), Lang::Coords3D::staticTypeName( ) ) );
904 typedef const Lang::FloatTriple ArgType
;
905 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( 1 ).getPtr( ) );
911 goto multiplyArguments
;
916 typedef const Lang::Coords3D ArgType
;
917 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( 1 ).getPtr( ) );
922 throw Exceptions::CoreOutOfRange( title_
, args
, 1, "Can't multiply two coordinate vectors. Try normalizing one of them!" );
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( ) ) );
935 Kernel::ContRef cont
= evalState
->cont_
;
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
) ) ),
943 cont
->takeValue( Kernel::ValueRef( new Lang::FloatTriple( y1
*z2
-z1
*y2
, z1
*x2
-x1
*z2
, x1
*y2
-y1
*x2
) ),
949 class Core_orthogonal
: public Lang::CoreFunction
952 Core_orthogonal( const char * title
) : CoreFunction( title
) { }
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( ) );
964 Kernel::ContRef cont
= evalState
->cont_
;
965 cont
->takeValue( Kernel::ValueRef( new Lang::FloatPair( -arg
->y_
, arg
->x_
) ),
972 typedef const Lang::FloatTriple ArgType
;
973 ArgType
* arg
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
979 if( fabs( arg
->x_
) < fabs( arg
->y_
) )
981 // arg is more parallell to y; cross with x
988 // arg is more parallell to x; cross with y
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
) ),
1001 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, 0, Helpers::typeSetString( Lang::FloatPair::staticTypeName( ), Lang::FloatTriple::staticTypeName( ) ) );
1005 class Core_randomNatural
: public Lang::CoreFunction
1008 Core_randomNatural( const char * title
)
1009 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
1011 formals_
->appendCoreStateFormal( "state" );
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
);
1023 Kernel::ContRef cont
= evalState
->cont_
;
1024 cont
->takeValue( Kernel::ValueRef( new Lang::Float( TWO_DIV_RANDOM_MAX
* static_cast< double >( random( ) ) - 1 ) ),
1029 class Core_randomBall1D
: public Lang::CoreFunction
1032 Core_randomBall1D( const char * title
)
1033 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
1035 formals_
->appendCoreStateFormal( "state" );
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
);
1047 Kernel::ContRef cont
= evalState
->cont_
;
1048 cont
->takeValue( Kernel::ValueRef( new Lang::Float( TWO_DIV_RANDOM_MAX
* static_cast< double >( random( ) ) - 1 ) ),
1053 class Core_randomBall2D
: public Lang::CoreFunction
1056 Core_randomBall2D( const char * title
)
1057 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
1059 formals_
->appendCoreStateFormal( "state" );
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
);
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
) ),
1085 class Core_randomBall3D
: public Lang::CoreFunction
1088 Core_randomBall3D( const char * title
)
1089 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
1091 formals_
->appendCoreStateFormal( "state" );
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
);
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
) ),
1119 class Core_gensym
: public Lang::CoreFunction
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( ) ),
1136 RefCountPtr
< const Lang::CoreFunction
> Lang::THE_FUNCTION_ABS( new Lang::Core_abs( "abs" ) );
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" ) );