Update procedures
[shapes.git] / source / coreelem.cc
blob55d3425cdc6d2baabcc905951eda0c277c63d1de
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, 2014, 2015 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 <algorithm>
36 #include <stdio.h>
37 #include <stdlib.h>
39 #ifdef RAND_MAX
40 /* Use definition from stdlib.h */
41 #define RANDOM_MAX RAND_MAX
42 #define TWO_DIV_RANDOM_MAX (2. / RAND_MAX)
43 #else
44 /* Use BSD man page specification. */
45 #define RANDOM_MAX (((long)(1)<<31)-1)
46 #define TWO_DIV_RANDOM_MAX (2. / ( ((long)(1)<<31)-1. ))
47 #endif
49 using namespace Shapes;
51 namespace Shapes
53 namespace Lang
56 class Core_nonNegativeModulo : public Lang::CoreFunction
58 Lang::Float::ValueType floatImpl( Lang::Float::ValueType num, Lang::Float::ValueType den ) const
60 Lang::Float::ValueType absDen = fabs( den );
61 return num - floor( num / absDen ) * absDen;
63 public:
64 Core_nonNegativeModulo( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name )
65 : CoreFunction( ns, name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
67 formals_->appendEvaluatedCoreFormal( "dividend", Kernel::THE_SLOT_VARIABLE );
68 formals_->appendEvaluatedCoreFormal( "divisor", Kernel::THE_SLOT_VARIABLE );
70 virtual void
71 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
73 args.applyDefaults( callLoc );
75 try
77 typedef const Lang::Integer ArgType;
78 Lang::Integer::ValueType num = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) )->val_;
79 Lang::Integer::ValueType den = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 1, callLoc )->val_;
81 /* Division num / abs(den) with rounding towards negative infinity.
83 Lang::Integer::ValueType absDen = (den >= 0) ? den : (-den);
84 Lang::Integer::ValueType n = 0; /* Initialize to suppress warnings. */
85 if (den != 0) {
86 if (num >= 0)
87 n = num / absDen;
88 else
89 n = -( 1 + (-num - 1) / absDen );
90 } else {
91 throw Exceptions::CoreOutOfRange( id_, args, 1, "The remainder is not defined when the denominator is zero." );
94 Kernel::ContRef cont = evalState->cont_;
95 cont->takeValue( Kernel::ValueRef( new Lang::Integer( num - n * absDen ) ),
96 evalState );
97 return;
99 catch( const NonLocalExit::NotThisType & ball )
101 /* Wrong type; never mind!.. but see below!
107 typedef const Lang::Float ArgType;
108 RefCountPtr< ArgType > num = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
109 RefCountPtr< ArgType > den = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 1, callLoc );
111 Kernel::ContRef cont = evalState->cont_;
112 cont->takeValue( Kernel::ValueRef( new Lang::Float( floatImpl( num->val_, den->val_ ) ) ),
113 evalState );
114 return;
116 catch( const NonLocalExit::NotThisType & ball )
118 /* Wrong type; never mind!.. but see below!
124 typedef const Lang::Length ArgType;
125 RefCountPtr< ArgType > num = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
126 RefCountPtr< ArgType > den = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 1, callLoc );
128 Kernel::ContRef cont = evalState->cont_;
129 cont->takeValue( Kernel::ValueRef( new Lang::Length( floatImpl( num->getScalar( ), den->getScalar( ) ) ) ),
130 evalState );
131 return;
133 catch( const NonLocalExit::NotThisType & ball )
135 /* Wrong type; never mind!.. but see below!
139 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 0, Helpers::typeSetString( Lang::Integer::staticTypeName( ), Lang::Float::staticTypeName( ), Lang::Length::staticTypeName( ) ) );
143 class Core_denominatorSignModulo : public Lang::CoreFunction
145 Lang::Float::ValueType floatImpl( Lang::Float::ValueType num, Lang::Float::ValueType den ) const
147 return num - floor( num / den ) * den;
149 public:
150 Core_denominatorSignModulo( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name )
151 : CoreFunction( ns, name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
153 formals_->appendEvaluatedCoreFormal( "dividend", Kernel::THE_SLOT_VARIABLE );
154 formals_->appendEvaluatedCoreFormal( "divisor", Kernel::THE_SLOT_VARIABLE );
156 virtual void
157 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
159 args.applyDefaults( callLoc );
163 typedef const Lang::Integer ArgType;
164 Lang::Integer::ValueType num = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) )->val_;
165 Lang::Integer::ValueType den = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 1, callLoc )->val_;
167 /* Division with rounding towards negative infinity.
169 Lang::Integer::ValueType n = 0; /* Initialize to suppress warnings. */
170 if (den > 0) {
171 if (num >= 0)
172 n = num / den;
173 else
174 n = -( 1 + (-num - 1) / den );
175 } else if (den < 0) {
176 if (num > 0)
177 n = -( 1 + (num - 1) / (-den) );
178 else
179 n = (-num) / (-den);
180 } else {
181 throw Exceptions::CoreOutOfRange( id_, args, 1, "The remainder is not defined when the denominator is zero." );
184 Kernel::ContRef cont = evalState->cont_;
185 cont->takeValue( Kernel::ValueRef( new Lang::Integer( num - n * den ) ),
186 evalState );
187 return;
189 catch( const NonLocalExit::NotThisType & ball )
191 /* Wrong type; never mind!.. but see below!
197 typedef const Lang::Float ArgType;
198 RefCountPtr< ArgType > num = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
199 RefCountPtr< ArgType > den = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 1, callLoc );
201 Kernel::ContRef cont = evalState->cont_;
202 cont->takeValue( Kernel::ValueRef( new Lang::Float( floatImpl( num->val_, den->val_ ) ) ),
203 evalState );
204 return;
206 catch( const NonLocalExit::NotThisType & ball )
208 /* Wrong type; never mind!.. but see below!
214 typedef const Lang::Length ArgType;
215 RefCountPtr< ArgType > num = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
216 RefCountPtr< ArgType > den = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 1, callLoc );
218 Kernel::ContRef cont = evalState->cont_;
219 cont->takeValue( Kernel::ValueRef( new Lang::Length( floatImpl( num->getScalar( ), den->getScalar( ) ) ) ),
220 evalState );
221 return;
223 catch( const NonLocalExit::NotThisType & ball )
225 /* Wrong type; never mind!.. but see below!
229 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 0, Helpers::typeSetString( Lang::Integer::staticTypeName( ), Lang::Float::staticTypeName( ), Lang::Length::staticTypeName( ) ) );
233 class Core_numeratorSignModulo : public Lang::CoreFunction
235 Lang::Float::ValueType floatImpl( Lang::Float::ValueType num, Lang::Float::ValueType den ) const
237 return fmod( num, den );
239 public:
240 Core_numeratorSignModulo( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name )
241 : CoreFunction( ns, name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
243 formals_->appendEvaluatedCoreFormal( "dividend", Kernel::THE_SLOT_VARIABLE );
244 formals_->appendEvaluatedCoreFormal( "divisor", Kernel::THE_SLOT_VARIABLE );
246 virtual void
247 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
249 args.applyDefaults( callLoc );
253 typedef const Lang::Integer ArgType;
254 Lang::Integer::ValueType num = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) )->val_;
255 Lang::Integer::ValueType den = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 1, callLoc )->val_;
257 /* Division with rounding towards zero.
259 Lang::Integer::ValueType n = 0; /* Initialize to suppress warnings. */
260 if (den > 0) {
261 if (num >= 0)
262 n = num / den;
263 else
264 n = -( (-num) / den );
265 } else if (den < 0) {
266 if (num >= 0)
267 n = -( num / (-den) );
268 else
269 n = (-num) / (-den);
270 } else {
271 throw Exceptions::CoreOutOfRange( id_, args, 1, "The remainder is not defined when the denominator is zero." );
274 Kernel::ContRef cont = evalState->cont_;
275 cont->takeValue( Kernel::ValueRef( new Lang::Integer( num - n * den ) ),
276 evalState );
277 return;
279 catch( const NonLocalExit::NotThisType & ball )
281 /* Wrong type; never mind!.. but see below!
287 typedef const Lang::Float ArgType;
288 RefCountPtr< ArgType > num = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
289 RefCountPtr< ArgType > den = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 1, callLoc );
291 Kernel::ContRef cont = evalState->cont_;
292 cont->takeValue( Kernel::ValueRef( new Lang::Float( floatImpl( num->val_, den->val_ ) ) ),
293 evalState );
294 return;
296 catch( const NonLocalExit::NotThisType & ball )
298 /* Wrong type; never mind!.. but see below!
304 typedef const Lang::Length ArgType;
305 RefCountPtr< ArgType > num = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
306 RefCountPtr< ArgType > den = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 1, callLoc );
308 Kernel::ContRef cont = evalState->cont_;
309 cont->takeValue( Kernel::ValueRef( new Lang::Length( floatImpl( num->getScalar( ), den->getScalar( ) ) ) ),
310 evalState );
311 return;
313 catch( const NonLocalExit::NotThisType & ball )
315 /* Wrong type; never mind!.. but see below!
319 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 0, Helpers::typeSetString( Lang::Integer::staticTypeName( ), Lang::Float::staticTypeName( ), Lang::Length::staticTypeName( ) ) );
323 class Core_floor : public Lang::CoreFunction
325 public:
326 Core_floor( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
327 virtual void
328 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
330 const size_t ARITY = 1;
331 CHECK_ARITY( args, ARITY, id_ );
333 typedef const Lang::Float ArgType;
334 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
336 /* Warning, unhandled overflow in the static_cast from floating point to integral type.
338 Kernel::ContRef cont = evalState->cont_;
339 cont->takeValue( Kernel::ValueRef( new Lang::Integer( static_cast< Lang::Integer::ValueType >( floor( arg->val_ ) ) ) ),
340 evalState );
344 class Core_ceil : public Lang::CoreFunction
346 public:
347 Core_ceil( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
348 virtual void
349 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
351 const size_t ARITY = 1;
352 CHECK_ARITY( args, ARITY, id_ );
354 typedef const Lang::Float ArgType;
355 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
357 /* Warning, unhandled overflow in the static_cast from floating point to integral type.
359 Kernel::ContRef cont = evalState->cont_;
360 cont->takeValue( Kernel::ValueRef( new Lang::Integer( static_cast< Lang::Integer::ValueType >( ceil( arg->val_ ) ) ) ),
361 evalState );
365 class Core_round : public Lang::CoreFunction
367 public:
368 Core_round( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
369 virtual void
370 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
372 const size_t ARITY = 1;
373 CHECK_ARITY( args, ARITY, id_ );
375 typedef const Lang::Float ArgType;
376 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
378 /* Warning, there are two sources of unhandled overflow here.
379 * 1) The range of a double is much greater than the range of a long (the result of lround).
380 * 2) lround produces a long, while Lang::Integer::ValueType is currently int.
382 Kernel::ContRef cont = evalState->cont_;
383 cont->takeValue( Kernel::ValueRef( new Lang::Integer( lround( arg->val_ ) ) ),
384 evalState );
388 class Core_cos : public Lang::CoreFunction
390 public:
391 Core_cos( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
392 virtual void
393 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
395 const size_t ARITY = 1;
396 CHECK_ARITY( args, ARITY, id_ );
398 typedef const Lang::Float ArgType;
399 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
401 Kernel::ContRef cont = evalState->cont_;
402 cont->takeValue( Kernel::ValueRef( new Lang::Float( cos( arg->val_ ) ) ),
403 evalState );
407 class Core_sin : public Lang::CoreFunction
409 public:
410 Core_sin( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
411 virtual void
412 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
414 const size_t ARITY = 1;
415 CHECK_ARITY( args, ARITY, id_ );
417 typedef const Lang::Float ArgType;
418 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
420 Kernel::ContRef cont = evalState->cont_;
421 cont->takeValue( Kernel::ValueRef( new Lang::Float( sin( arg->val_ ) ) ),
422 evalState );
426 class Core_tan : public Lang::CoreFunction
428 public:
429 Core_tan( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
430 virtual void
431 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
433 const size_t ARITY = 1;
434 CHECK_ARITY( args, ARITY, id_ );
436 typedef const Lang::Float ArgType;
437 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
439 Kernel::ContRef cont = evalState->cont_;
440 cont->takeValue( Kernel::ValueRef( new Lang::Float( tan( arg->val_ ) ) ),
441 evalState );
445 class Core_cot : public Lang::CoreFunction
447 public:
448 Core_cot( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
449 virtual void
450 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
452 const size_t ARITY = 1;
453 CHECK_ARITY( args, ARITY, id_ );
455 typedef const Lang::Float ArgType;
456 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
458 Kernel::ContRef cont = evalState->cont_;
459 cont->takeValue( Kernel::ValueRef( new Lang::Float( 1 / tan( arg->val_ ) ) ),
460 evalState );
464 class Core_arccos : public Lang::CoreFunction
466 public:
467 Core_arccos( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
468 virtual void
469 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
471 const size_t ARITY = 1;
472 CHECK_ARITY( args, ARITY, id_ );
474 typedef const Lang::Float ArgType;
475 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
477 Kernel::ContRef cont = evalState->cont_;
478 cont->takeValue( Kernel::ValueRef( new Lang::Float( acos( arg->val_ ) ) ),
479 evalState );
483 class Core_arcsin : public Lang::CoreFunction
485 public:
486 Core_arcsin( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
487 virtual void
488 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
490 const size_t ARITY = 1;
491 CHECK_ARITY( args, ARITY, id_ );
493 typedef const Lang::Float ArgType;
494 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
496 Kernel::ContRef cont = evalState->cont_;
497 cont->takeValue( Kernel::ValueRef( new Lang::Float( asin( arg->val_ ) ) ),
498 evalState );
502 class Core_arctan : public Lang::CoreFunction
504 public:
505 Core_arctan( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
506 virtual void
507 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
509 const size_t ARITY = 1;
510 CHECK_ARITY( args, ARITY, id_ );
512 typedef const Lang::Float ArgType;
513 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
515 Kernel::ContRef cont = evalState->cont_;
516 cont->takeValue( Kernel::ValueRef( new Lang::Float( atan( arg->val_ ) ) ),
517 evalState );
521 class Core_pow : public Lang::CoreFunction
523 public:
524 Core_pow( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
525 virtual void
526 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
528 const size_t ARITY = 2;
529 CHECK_ARITY( args, ARITY, id_ );
533 typedef const Lang::Float ArgTypeBase;
534 RefCountPtr< ArgTypeBase > b = Helpers::try_cast_CoreArgument< ArgTypeBase >( args.getValue( 0 ) );
538 typedef const Lang::Float ArgTypeExp;
539 RefCountPtr< ArgTypeExp > e = Helpers::try_cast_CoreArgument< ArgTypeExp >( args.getValue( 1 ) );
541 Kernel::ContRef cont = evalState->cont_;
542 cont->takeValue( Kernel::ValueRef( new Lang::Float( pow( b->val_, e->val_ ) ) ),
543 evalState );
544 return;
546 catch( const NonLocalExit::NotThisType & ball )
548 /* Wrong type; never mind!.. but see below!
554 typedef const Lang::Integer ArgTypeExp;
555 RefCountPtr< ArgTypeExp > e = Helpers::try_cast_CoreArgument< ArgTypeExp >( args.getValue( 1 ) );
557 Kernel::ContRef cont = evalState->cont_;
558 cont->takeValue( Kernel::ValueRef( new Lang::Float( pow( b->val_, e->val_ ) ) ),
559 evalState );
560 return;
562 catch( const NonLocalExit::NotThisType & ball )
564 /* Wrong type; never mind!.. but see below!
568 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 1, Helpers::typeSetString( Lang::Float::staticTypeName( ), Lang::Integer::staticTypeName( ) ) );
571 catch( const NonLocalExit::NotThisType & ball )
573 /* Wrong type; never mind!.. but see below!
579 typedef const Lang::Integer ArgType;
580 ArgType::ValueType b = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) )->val_;
581 ArgType::ValueType e = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 1, callLoc )->val_;
583 if( e < 0 )
585 throw Exceptions::CoreOutOfRange( id_, args, 1, "Power with integer base must have non-negative exponent." );
588 ArgType::ValueType result = 1;
589 while( e > 0 ){
590 if( ( e % 2 ) != 0 ){
591 result *= b;
593 b = b * b;
594 e /= 2;
597 Kernel::ContRef cont = evalState->cont_;
598 cont->takeValue( Kernel::ValueRef( new Lang::Integer( result ) ),
599 evalState );
600 return;
602 catch( const NonLocalExit::NotThisType & ball )
604 /* Wrong type; never mind!.. but see below!
608 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 0, Helpers::typeSetString( Lang::Float::staticTypeName( ), Lang::Integer::staticTypeName( ) ) );
612 class Core_exp : public Lang::CoreFunction
614 public:
615 Core_exp( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
616 virtual void
617 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
619 const size_t ARITY = 1;
620 CHECK_ARITY( args, ARITY, id_ );
622 typedef const Lang::Float ArgType;
623 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
625 Kernel::ContRef cont = evalState->cont_;
626 cont->takeValue( Kernel::ValueRef( new Lang::Float( exp( arg->val_ ) ) ),
627 evalState );
631 class Core_log : public Lang::CoreFunction
633 public:
634 Core_log( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
635 virtual void
636 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
638 const size_t ARITY = 1;
639 CHECK_ARITY( args, ARITY, id_ );
641 typedef const Lang::Float ArgType;
642 ArgType::ValueType arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc )->val_;
643 if( arg <= 0.0 )
645 throw Exceptions::CoreOutOfRange( id_, args, 0, "Argument must be strictly positive." );
648 Kernel::ContRef cont = evalState->cont_;
649 cont->takeValue( Kernel::ValueRef( new Lang::Float( log( arg ) ) ),
650 evalState );
654 class Core_log10 : public Lang::CoreFunction
656 public:
657 Core_log10( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
658 virtual void
659 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
661 const size_t ARITY = 1;
662 CHECK_ARITY( args, ARITY, id_ );
664 typedef const Lang::Float ArgType;
665 ArgType::ValueType arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc )->val_;
666 if( arg <= 0.0 )
668 throw Exceptions::CoreOutOfRange( id_, args, 0, "Argument must be strictly positive." );
671 Kernel::ContRef cont = evalState->cont_;
672 cont->takeValue( Kernel::ValueRef( new Lang::Float( log10( arg ) ) ),
673 evalState );
677 class Core_min : public Lang::CoreFunction
679 public:
680 Core_min( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
681 virtual void
682 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
684 if( args.empty( ) )
686 Kernel::ContRef cont = evalState->cont_;
687 cont->takeValue( Kernel::ValueRef( new Lang::Float( HUGE_VAL ) ),
688 evalState );
689 return;
693 typedef const Lang::Float ArgType;
694 size_t i = 0;
695 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( i ).getPtr( ) );
696 if( arg != 0 )
698 double res = arg->val_;
699 ++i;
700 const size_t & end = args.size( );
701 for( ; i != end; ++i )
703 res = std::min( res, Helpers::down_cast_CoreArgument< ArgType >( id_, args, i, callLoc )->val_ );
705 Kernel::ContRef cont = evalState->cont_;
706 cont->takeValue( Kernel::ValueRef( new ArgType( res ) ),
707 evalState );
708 return;
713 typedef const Lang::Length ArgType;
714 size_t i = 0;
715 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( i ).getPtr( ) );
716 if( arg != 0 )
718 Concrete::Length res = arg->get( );
719 ++i;
720 const size_t & end = args.size( );
721 for( ; i != end; ++i )
723 res = std::min( res, Helpers::down_cast_CoreArgument< ArgType >( id_, args, i, callLoc )->get( ) );
725 Kernel::ContRef cont = evalState->cont_;
726 cont->takeValue( Kernel::ValueRef( new ArgType( res ) ),
727 evalState );
728 return;
733 typedef const Lang::Integer ArgType;
734 size_t i = 0;
735 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( i ).getPtr( ) );
736 if( arg != 0 )
738 Lang::Integer::ValueType res = arg->val_;
739 ++i;
740 const size_t & end = args.size( );
741 for( ; i != end; ++i )
743 res = std::min( res, Helpers::down_cast_CoreArgument< ArgType >( id_, args, i, callLoc )->val_ );
745 Kernel::ContRef cont = evalState->cont_;
746 cont->takeValue( Kernel::ValueRef( new ArgType( res ) ),
747 evalState );
748 return;
752 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 0, Helpers::typeSetString( Lang::Float::staticTypeName( ), Lang::Integer::staticTypeName( ), Lang::Length::staticTypeName( ) ) );
756 class Core_max : public Lang::CoreFunction
758 public:
759 Core_max( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
760 virtual void
761 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
763 if( args.empty( ) )
765 Kernel::ContRef cont = evalState->cont_;
766 cont->takeValue( Kernel::ValueRef( new Lang::Float( -HUGE_VAL ) ),
767 evalState );
768 return;
772 typedef const Lang::Float ArgType;
773 size_t i = 0;
774 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( i ).getPtr( ) );
775 if( arg != 0 )
777 double res = arg->val_;
778 ++i;
779 const size_t & end = args.size( );
780 for( ; i != end; ++i )
782 res = std::max( res, Helpers::down_cast_CoreArgument< ArgType >( id_, args, i, callLoc )->val_ );
784 Kernel::ContRef cont = evalState->cont_;
785 cont->takeValue( Kernel::ValueRef( new ArgType( res ) ),
786 evalState );
787 return;
792 typedef const Lang::Length ArgType;
793 size_t i = 0;
794 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( i ).getPtr( ) );
795 if( arg != 0 )
797 Concrete::Length res = arg->get( );
798 ++i;
799 const size_t & end = args.size( );
800 for( ; i != end; ++i )
802 res = std::max( res, Helpers::down_cast_CoreArgument< ArgType >( id_, args, i, callLoc )->get( ) );
804 Kernel::ContRef cont = evalState->cont_;
805 cont->takeValue( Kernel::ValueRef( new ArgType( res ) ),
806 evalState );
807 return;
813 typedef const Lang::Integer ArgType;
814 size_t i = 0;
815 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( i ).getPtr( ) );
816 if( arg != 0 )
818 Lang::Integer::ValueType res = arg->val_;
819 ++i;
820 const size_t & end = args.size( );
821 for( ; i != end; ++i )
823 res = std::max( res, Helpers::down_cast_CoreArgument< ArgType >( id_, args, i, callLoc )->val_ );
825 Kernel::ContRef cont = evalState->cont_;
827 cont->takeValue( Kernel::ValueRef( new ArgType( res ) ),
828 evalState );
829 return;
833 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 0, Helpers::typeSetString( Lang::Float::staticTypeName( ), Lang::Integer::staticTypeName( ), Lang::Length::staticTypeName( ) ) );
837 class Core_sqrt : public Lang::CoreFunction
839 public:
840 Core_sqrt( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
841 virtual void
842 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
844 const size_t ARITY = 1;
845 CHECK_ARITY( args, ARITY, id_ );
847 typedef const Lang::Float ArgType;
848 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
850 if( arg->val_ < 0.0 )
852 throw Exceptions::CoreOutOfRange( id_, args, 0, "The square root is not defined for negative values." );
855 Kernel::ContRef cont = evalState->cont_;
856 cont->takeValue( Kernel::ValueRef( new Lang::Float( sqrt( arg->val_ ) ) ),
857 evalState );
861 class Core_angle : public Lang::CoreFunction
863 public:
864 Core_angle( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
865 virtual void
866 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
868 const size_t ARITY = 1;
869 CHECK_ARITY( args, ARITY, id_ );
872 typedef const Lang::Coords2D ArgType;
873 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
874 if( arg != 0 )
876 if( arg->x_.get( ) == 0 && arg->y_.get( ) == 0 )
878 throw Exceptions::CoreOutOfRange( id_, args, 0, "Can't take the angle of something of norm 0." );
880 Kernel::ContRef cont = evalState->cont_;
881 cont->takeValue( Kernel::ValueRef( new Lang::Float( atan2( arg->y_.getScalar( ), arg->x_.getScalar( ) ) ) ),
882 evalState );
883 return;
888 typedef const Lang::FloatPair ArgType;
889 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
890 if( arg != 0 )
892 if( arg->x_ == 0 && arg->y_ == 0 )
894 throw Exceptions::CoreOutOfRange( id_, args, 0, "Can't take the angle of something of norm 0." );
896 Kernel::ContRef cont = evalState->cont_;
897 cont->takeValue( Kernel::ValueRef( new Lang::Float( atan2( arg->y_, arg->x_ ) ) ),
898 evalState );
899 return;
903 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 0, Interaction::SEVERAL_TYPES );
907 class Core_dir : public Lang::CoreFunction
909 public:
910 Core_dir( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
911 virtual void
912 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
914 const size_t ARITY = 1;
915 CHECK_ARITY( args, ARITY, id_ );
917 typedef const Lang::Float ArgType;
918 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
920 Kernel::ContRef cont = evalState->cont_;
921 cont->takeValue( Kernel::ValueRef( new Lang::FloatPair( cos( arg->val_ ), sin( arg->val_ ) ) ),
922 evalState );
926 class Core_abs : public Lang::CoreFunction
928 public:
929 Core_abs( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
930 virtual void
931 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
933 const size_t ARITY = 1;
934 CHECK_ARITY( args, ARITY, id_ );
936 const Lang::Value * untypedArg = args.getValue( 0 ).getPtr( );
939 typedef const Lang::Float ArgType;
940 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
941 if( arg != 0 )
943 Kernel::ContRef cont = evalState->cont_;
944 cont->takeValue( Kernel::ValueRef( new Lang::Float( fabs( arg->val_ ) ) ),
945 evalState );
946 return;
951 typedef const Lang::Length ArgType;
952 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
953 if( arg != 0 )
955 Kernel::ContRef cont = evalState->cont_;
956 cont->takeValue( Kernel::ValueRef( new Lang::Length( arg->get( ).abs( ) ) ),
957 evalState );
958 return;
963 typedef const Lang::FloatPair ArgType;
964 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
965 if( arg != 0 )
967 Kernel::ContRef cont = evalState->cont_;
968 cont->takeValue( Kernel::ValueRef( new Lang::Float( hypot( arg->x_, arg->y_ ) ) ),
969 evalState );
970 return;
975 typedef const Lang::Coords2D ArgType;
976 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
977 if( arg != 0 )
979 Kernel::ContRef cont = evalState->cont_;
980 cont->takeValue( Kernel::ValueRef( new Lang::Length( hypotPhysical( arg->x_.get( ), arg->y_.get( ) ) ) ),
981 evalState );
982 return;
987 typedef const Lang::FloatTriple ArgType;
988 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
989 if( arg != 0 )
991 Kernel::ContRef cont = evalState->cont_;
992 cont->takeValue( Kernel::ValueRef( new Lang::Float( Concrete::Scalar::hypot3( arg->x_, arg->y_, arg->z_ ) ) ),
993 evalState );
994 return;
999 typedef const Lang::Coords3D ArgType;
1000 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
1001 if( arg != 0 )
1003 Kernel::ContRef cont = evalState->cont_;
1004 cont->takeValue( Kernel::ValueRef( new Lang::Length( hypotPhysical( arg->x_.get( ), arg->y_.get( ), arg->z_.get( ) ) ) ),
1005 evalState );
1006 return;
1011 typedef const Lang::ElementaryPath2D ArgType;
1014 RefCountPtr< ArgType > p = Helpers::elementaryPathTry2D( args.getValue( 0 ) );
1015 Kernel::ContRef cont = evalState->cont_;
1016 cont->takeValue( RefCountPtr< const Lang::Length >( new Lang::Length( p->arcLength( ) ) ),
1017 evalState );
1018 return;
1020 catch( NonLocalExit::NotThisType & ball )
1022 /* Never mind */
1027 typedef const Lang::ElementaryPath3D ArgType;
1030 RefCountPtr< ArgType > p = Helpers::elementaryPathTry3D( args.getValue( 0 ) );
1031 Kernel::ContRef cont = evalState->cont_;
1032 cont->takeValue( RefCountPtr< const Lang::Length >( new Lang::Length( p->arcLength( ) ) ),
1033 evalState );
1034 return;
1036 catch( NonLocalExit::NotThisType & ball )
1038 /* Never mind */
1043 typedef const Lang::Integer ArgType;
1044 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
1045 if( arg != 0 )
1047 Kernel::ContRef cont = evalState->cont_;
1048 cont->takeValue( Kernel::ValueRef( new Lang::Integer( ( arg->val_ >= 0 ) ? (arg->val_) : (-arg->val_) ) ),
1049 evalState );
1050 return;
1055 typedef const Lang::Dash ArgType;
1056 ArgType * arg = dynamic_cast< ArgType * >( untypedArg );
1057 if( arg != 0 )
1059 Kernel::ContRef cont = evalState->cont_;
1060 cont->takeValue( Kernel::ValueRef( new Lang::Length( arg->length( ) ) ),
1061 evalState );
1062 return;
1066 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 0, Interaction::SEVERAL_TYPES );
1070 class Core_normalized : public Lang::CoreFunction
1072 public:
1073 Core_normalized( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
1074 virtual void
1075 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1077 const size_t ARITY = 1;
1078 CHECK_ARITY( args, ARITY, id_ );
1081 typedef const Lang::FloatPair ArgType;
1082 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1083 if( arg != 0 )
1085 double norm = hypot( arg->x_, arg->y_ );
1086 if( norm == 0 )
1088 throw Exceptions::CoreOutOfRange( id_, args, 0, "Can't normalize something of norm 0" );
1090 Kernel::ContRef cont = evalState->cont_;
1091 cont->takeValue( Kernel::ValueRef( new Lang::FloatPair( arg->x_ / norm, arg->y_ / norm ) ),
1092 evalState );
1093 return;
1098 typedef const Lang::Coords2D ArgType;
1099 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1100 if( arg != 0 )
1102 Concrete::Length norm = hypotPhysical( arg->x_.get( ), arg->y_.get( ) );
1103 if( norm == 0 )
1105 throw Exceptions::CoreOutOfRange( id_, args, 0, "Can't normalize something of norm 0" );
1107 Kernel::ContRef cont = evalState->cont_;
1108 cont->takeValue( Kernel::ValueRef( new Lang::FloatPair( arg->x_.get( ) / norm, arg->y_.get( ) / norm ) ),
1109 evalState );
1110 return;
1115 typedef const Lang::FloatTriple ArgType;
1116 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1117 if( arg != 0 )
1119 double norm = Concrete::Scalar::hypot3( arg->x_, arg->y_, arg->z_ );
1120 if( norm == 0 )
1122 throw Exceptions::CoreOutOfRange( id_, args, 0, "Can't normalize something of norm 0" );
1124 Kernel::ContRef cont = evalState->cont_;
1125 cont->takeValue( Kernel::ValueRef( new Lang::FloatTriple( arg->x_ / norm, arg->y_ / norm, arg->z_ / norm ) ),
1126 evalState );
1127 return;
1132 typedef const Lang::Coords3D ArgType;
1133 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1134 if( arg != 0 )
1136 Concrete::Length norm = hypotPhysical( arg->x_.get( ), arg->y_.get( ), arg->z_.get( ) );
1137 if( norm == 0 )
1139 throw Exceptions::CoreOutOfRange( id_, args, 0, "Can't normalize something of norm 0" );
1141 Kernel::ContRef cont = evalState->cont_;
1142 cont->takeValue( Kernel::ValueRef( new Lang::FloatTriple( arg->x_.get( ) / norm, arg->y_.get( ) / norm, arg->z_.get( ) / norm ) ),
1143 evalState );
1144 return;
1149 typedef const Lang::Float ArgType;
1150 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1151 if( arg != 0 )
1153 if( arg->val_ > 0 )
1155 Kernel::ContRef cont = evalState->cont_;
1156 cont->takeValue( Kernel::ValueRef( new Lang::Float( 1 ) ),
1157 evalState );
1158 return;
1160 if( arg->val_ < 0 )
1162 Kernel::ContRef cont = evalState->cont_;
1163 cont->takeValue( Kernel::ValueRef( new Lang::Float( -1 ) ),
1164 evalState );
1165 return;
1167 throw Exceptions::CoreOutOfRange( id_, args, 0, "Can't normalize something of norm 0" );
1172 typedef const Lang::Length ArgType;
1173 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1174 if( arg != 0 )
1176 if( arg->get( ) > 0 )
1178 Kernel::ContRef cont = evalState->cont_;
1179 cont->takeValue( Kernel::ValueRef( new Lang::Float( 1 ) ),
1180 evalState );
1181 return;
1183 if( arg->get( ) < 0 )
1185 Kernel::ContRef cont = evalState->cont_;
1186 cont->takeValue( Kernel::ValueRef( new Lang::Float( -1 ) ),
1187 evalState );
1188 return;
1190 throw Exceptions::CoreOutOfRange( id_, args, 0, "Can't normalize something of norm 0" );
1195 typedef const Lang::Integer ArgType;
1196 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1197 if( arg != 0 )
1199 if( arg->val_ > 0 )
1201 Kernel::ContRef cont = evalState->cont_;
1202 cont->takeValue( Kernel::ValueRef( new Lang::Integer( 1 ) ),
1203 evalState );
1204 return;
1206 if( arg->val_ < 0 )
1208 Kernel::ContRef cont = evalState->cont_;
1209 cont->takeValue( Kernel::ValueRef( new Lang::Integer( -1 ) ),
1210 evalState );
1211 return;
1213 throw Exceptions::CoreOutOfRange( id_, args, 0, "Can't normalize something of norm 0" );
1218 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 0, Interaction::SEVERAL_TYPES );
1222 class Core_cross : public Lang::CoreFunction
1224 public:
1225 Core_cross( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
1226 virtual void
1227 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1229 const size_t ARITY = 2;
1230 CHECK_ARITY( args, ARITY, id_ );
1232 double x1;
1233 double y1;
1234 double z1;
1235 double x2;
1236 double y2;
1237 double z2;
1238 bool isLength = false;
1241 typedef const Lang::FloatTriple ArgType;
1242 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1243 if( arg != 0 )
1245 x1 = arg->x_;
1246 y1 = arg->y_;
1247 z1 = arg->z_;
1248 goto secondArgument;
1253 typedef const Lang::Coords3D ArgType;
1254 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1255 if( arg != 0 )
1257 isLength = true;
1258 x1 = arg->x_.get( ).offtype< 1, 0 >( );
1259 y1 = arg->y_.get( ).offtype< 1, 0 >( );
1260 z1 = arg->z_.get( ).offtype< 1, 0 >( );
1261 goto secondArgument;
1265 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 0, Helpers::typeSetString( Lang::FloatTriple::staticTypeName( ), Lang::Coords3D::staticTypeName( ) ) );
1267 secondArgument:
1269 typedef const Lang::FloatTriple ArgType;
1270 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 1 ).getPtr( ) );
1271 if( arg != 0 )
1273 x2 = arg->x_;
1274 y2 = arg->y_;
1275 z2 = arg->z_;
1276 goto multiplyArguments;
1281 typedef const Lang::Coords3D ArgType;
1282 ArgType * arg = dynamic_cast< ArgType * >( args.getValue( 1 ).getPtr( ) );
1283 if( arg != 0 )
1285 if( isLength )
1287 throw Exceptions::CoreOutOfRange( id_, args, 1, "Can't multiply two coordinate vectors. Try normalizing one of them!" );
1289 isLength = true;
1290 x2 = arg->x_.get( ).offtype< 1, 0 >( );
1291 y2 = arg->y_.get( ).offtype< 1, 0 >( );
1292 z2 = arg->z_.get( ).offtype< 1, 0 >( );
1293 goto multiplyArguments;
1297 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 1, Helpers::typeSetString( Lang::FloatTriple::staticTypeName( ), Lang::Coords3D::staticTypeName( ) ) );
1299 multiplyArguments:
1300 Kernel::ContRef cont = evalState->cont_;
1301 if( isLength )
1303 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 ) ) ),
1304 evalState );
1306 else
1308 cont->takeValue( Kernel::ValueRef( new Lang::FloatTriple( y1*z2-z1*y2, z1*x2-x1*z2, x1*y2-y1*x2 ) ),
1309 evalState );
1314 class Core_orthogonal : public Lang::CoreFunction
1316 public:
1317 Core_orthogonal( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
1318 virtual void
1319 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1321 const size_t ARITY = 1;
1322 CHECK_ARITY( args, ARITY, id_ );
1324 typedef const Lang::FloatPair ArgType;
1325 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
1327 Kernel::ContRef cont = evalState->cont_;
1328 cont->takeValue( Kernel::ValueRef( new Lang::FloatPair( -arg->y_, arg->x_ ) ),
1329 evalState );
1333 class Core_orthogonal3D : public Lang::CoreFunction
1335 public:
1336 Core_orthogonal3D( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
1337 virtual void
1338 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1340 const size_t ARITY = 1;
1341 CHECK_ARITY( args, ARITY, id_ );
1343 typedef const Lang::FloatTriple ArgType;
1344 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
1346 double x;
1347 double y;
1348 double z;
1349 if( fabs( arg->x_ ) < fabs( arg->y_ ) )
1351 // arg is more parallell to y; cross with x
1352 x = 0;
1353 y = - arg->z_;
1354 z = arg->y_;
1356 else
1358 // arg is more parallell to x; cross with y
1359 x = arg->z_;
1360 y = 0;
1361 z = - arg->x_;
1363 double scale = sqrt( ( (arg->x_)*(arg->x_) + (arg->y_)*(arg->y_) + (arg->z_)*(arg->z_) ) / ( x*x + y*y + z*z ) );
1364 Kernel::ContRef cont = evalState->cont_;
1365 cont->takeValue( Kernel::ValueRef( new Lang::FloatTriple( x * scale, y * scale, z * scale ) ),
1366 evalState );
1370 class Core_randomBall1D : public Lang::CoreFunction
1372 public:
1373 Core_randomBall1D( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name )
1374 : CoreFunction( ns, name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
1376 formals_->appendCoreStateFormal( "state" );
1378 virtual void
1379 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1381 args.applyDefaults( callLoc );
1383 typedef Kernel::WarmRandomState StateType;
1384 StateType * st = Helpers::down_cast_CoreState< StateType >( id_, args, 0, callLoc );
1386 st->setState( );
1388 Kernel::ContRef cont = evalState->cont_;
1389 cont->takeValue( Kernel::ValueRef( new Lang::Float( TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1 ) ),
1390 evalState );
1394 class Core_randomBall2D : public Lang::CoreFunction
1396 public:
1397 Core_randomBall2D( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name )
1398 : CoreFunction( ns, name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
1400 formals_->appendCoreStateFormal( "state" );
1402 virtual void
1403 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1405 args.applyDefaults( callLoc );
1407 typedef Kernel::WarmRandomState StateType;
1408 StateType * st = Helpers::down_cast_CoreState< StateType >( id_, args, 0, callLoc );
1410 st->setState( );
1412 double x1 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1413 double x2 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1414 while( x1 * x1 + x2 * x2 > 1 )
1416 x1 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1417 x2 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1420 Kernel::ContRef cont = evalState->cont_;
1421 cont->takeValue( Kernel::ValueRef( new Lang::FloatPair( x1, x2 ) ),
1422 evalState );
1426 class Core_randomBall3D : public Lang::CoreFunction
1428 public:
1429 Core_randomBall3D( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name )
1430 : CoreFunction( ns, name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
1432 formals_->appendCoreStateFormal( "state" );
1434 virtual void
1435 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1437 args.applyDefaults( callLoc );
1439 typedef Kernel::WarmRandomState StateType;
1440 StateType * st = Helpers::down_cast_CoreState< StateType >( id_, args, 0, callLoc );
1442 st->setState( );
1444 double x1 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1445 double x2 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1446 double x3 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1447 while( x1 * x1 + x2 * x2 + x3 * x3 > 1 )
1449 x1 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1450 x2 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1451 x3 = TWO_DIV_RANDOM_MAX * static_cast< double >( random( ) ) - 1;
1454 Kernel::ContRef cont = evalState->cont_;
1455 cont->takeValue( Kernel::ValueRef( new Lang::FloatTriple( x1, x2, x3 ) ),
1456 evalState );
1460 class Core_gensym : public Lang::CoreFunction
1462 public:
1463 Core_gensym( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name )
1464 : CoreFunction( ns, name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
1466 formals_->appendCoreStateFormal( "state" );
1468 virtual void call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1470 args.applyDefaults( callLoc );
1472 typedef Kernel::WarmTime StateType;
1473 Helpers::down_cast_CoreState< StateType >( id_, args, 0, callLoc ); /* Ignore result, just make sure that a time state was given. */
1475 Kernel::ContRef cont = evalState->cont_;
1476 cont->takeValue( Kernel::ValueRef( new Lang::Symbol( ) ),
1477 evalState );
1484 RefCountPtr< const Lang::CoreFunction > Lang::THE_FUNCTION_ABS( new Lang::Core_abs( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "abs" ) );
1486 void
1487 Kernel::registerCore_elem( Kernel::Environment * env )
1489 env->initDefineCoreFunction( new Lang::Core_nonNegativeModulo( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "modulo" ) );
1490 env->initDefineCoreFunction( new Lang::Core_denominatorSignModulo( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "mod" ) );
1491 env->initDefineCoreFunction( new Lang::Core_numeratorSignModulo( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "rem" ) );
1492 env->initDefineCoreFunction( new Lang::Core_ceil( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "ceil" ) );
1493 env->initDefineCoreFunction( new Lang::Core_floor( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "floor" ) );
1494 env->initDefineCoreFunction( new Lang::Core_round( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "round" ) );
1495 env->initDefineCoreFunction( new Lang::Core_cos( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "cos" ) );
1496 env->initDefineCoreFunction( new Lang::Core_sin( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "sin" ) );
1497 env->initDefineCoreFunction( new Lang::Core_tan( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "tan" ) );
1498 env->initDefineCoreFunction( new Lang::Core_cot( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "cot" ) );
1499 env->initDefineCoreFunction( new Lang::Core_arccos( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "arccos" ) );
1500 env->initDefineCoreFunction( new Lang::Core_arcsin( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "arcsin" ) );
1501 env->initDefineCoreFunction( new Lang::Core_arctan( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "arctan" ) );
1502 env->initDefineCoreFunction( new Lang::Core_pow( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "pow" ) );
1503 env->initDefineCoreFunction( new Lang::Core_exp( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "exp" ) );
1504 env->initDefineCoreFunction( new Lang::Core_log( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "log" ) );
1505 env->initDefineCoreFunction( new Lang::Core_log10( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "log10" ) );
1506 env->initDefineCoreFunction( new Lang::Core_min( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "min" ) );
1507 env->initDefineCoreFunction( new Lang::Core_max( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "max" ) );
1508 env->initDefineCoreFunction( new Lang::Core_sqrt( Lang::THE_NAMESPACE_Shapes_Numeric_Math, "sqrt" ) );
1509 env->initDefineCoreFunction( Lang::THE_FUNCTION_ABS );
1510 env->initDefineCoreFunction( new Lang::Core_angle( Lang::THE_NAMESPACE_Shapes_Geometry, "angle" ) );
1511 env->initDefineCoreFunction( new Lang::Core_dir( Lang::THE_NAMESPACE_Shapes_Geometry, "dir" ) );
1512 env->initDefineCoreFunction( new Lang::Core_normalized( Lang::THE_NAMESPACE_Shapes_Geometry, "normalized" ) );
1513 env->initDefineCoreFunction( new Lang::Core_cross( Lang::THE_NAMESPACE_Shapes_Geometry3D, "cross" ) );
1514 env->initDefineCoreFunction( new Lang::Core_orthogonal( Lang::THE_NAMESPACE_Shapes_Geometry, "orthogonal" ) );
1515 env->initDefineCoreFunction( new Lang::Core_orthogonal3D( Lang::THE_NAMESPACE_Shapes_Geometry3D, "orthogonal" ) );
1517 env->initDefineCoreFunction( new Lang::Core_randomBall1D( Lang::THE_NAMESPACE_Shapes_Numeric_Random, "ball1D" ) );
1518 env->initDefineCoreFunction( new Lang::Core_randomBall2D( Lang::THE_NAMESPACE_Shapes_Numeric_Random, "ball2D" ) );
1519 env->initDefineCoreFunction( new Lang::Core_randomBall3D( Lang::THE_NAMESPACE_Shapes_Numeric_Random, "ball3D" ) );
1521 env->initDefineCoreFunction( new Lang::Core_gensym( Lang::THE_NAMESPACE_Shapes, "gensym" ) );