Update procedures
[shapes.git] / source / pdffunctiontypes.cc
blob10b961ccb3958c22cea3d03f5648b61d8e727f7c
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 "Shapes_Helpers_decls.h"
21 #include "pdffunctiontypes.h"
22 #include "globals.h"
23 #include "shapescore.h"
24 #include "ast.h"
26 using namespace Shapes;
28 const Ast::FileID * PDF_Function_FileID = Ast::FileID::build_internal( "< PDF-able function >" );
30 Lang::PDF_Function::PDF_Function( SubType subType, size_t outputDimension, size_t inputDimension, bool rangeIsActive )
31 : Lang::Function( new Kernel::EvaluatedFormals( PDF_Function_FileID, true ) ),
32 subType_( subType ), outputDimension_( outputDimension ), inputDimension_( inputDimension ), rangeIsActive_( rangeIsActive ),
33 storage( NullPtr< SimplePDF::PDF_Indirect_out >( ) ),
34 coreLoc_( new Interaction::FileIDLocation( PDF_Function_FileID ) ) /* Temporary value just for initialization. */
36 if( outputDimension_ == 0 )
38 throw Exceptions::OutOfRange( strrefdup( "The output dimension of a PDF function cannot be 0." ) );
40 switch( subType_ )
42 case INTERPOLATION:
43 coreLoc_ = RefCountPtr< const Interaction::CoreLocation >( new Interaction::CharPtrLocation( "< Interpolation function >" ) );
44 break;
45 case EXPONENTIAL:
46 coreLoc_ = RefCountPtr< const Interaction::CoreLocation >( new Interaction::CharPtrLocation( "< Exponential interpolation function >" ) );
47 break;
48 case STITCHING:
49 coreLoc_ = RefCountPtr< const Interaction::CoreLocation >( new Interaction::CharPtrLocation( "< Stiching function >" ) );
50 break;
51 case CALCULATOR:
52 coreLoc_ = RefCountPtr< const Interaction::CoreLocation >( new Interaction::CharPtrLocation( "< Calculator function >" ) );
53 break;
54 default:
55 throw Exceptions::InternalError( "PDF_Function::PDF_Function: subType_ out of range in switch." );
59 Lang::PDF_Function::~PDF_Function( )
60 { }
63 void
64 Lang::PDF_Function::addCommonFields( SimplePDF::PDF_Dictionary * dst ) const
66 (*dst)[ "FunctionType" ] = SimplePDF::newInt( subType_ );
68 if( domain_.size( ) != inputDimension_ )
70 throw Exceptions::InternalError( strrefdup( "The size of domain_ does not match inputDimension_." ) );
73 RefCountPtr< SimplePDF::PDF_Vector > tmpVector;
74 SimplePDF::PDF_Vector::VecType & dstRef( tmpVector->vec );
75 dstRef.reserve( 2 * inputDimension_ );
76 typedef typeof domain_ ListType;
77 for( ListType::const_iterator i = domain_.begin( ); i != domain_.end( ); ++i )
79 dstRef.push_back( SimplePDF::newFloat( i->first ) );
80 dstRef.push_back( SimplePDF::newFloat( i->second ) );
82 (*dst)[ "Domain" ] = tmpVector;
85 if( rangeIsActive_ )
87 if( range_.size( ) != inputDimension_ )
89 throw Exceptions::InternalError( strrefdup( "The size of range_ does not match outputDimension_." ) );
92 RefCountPtr< SimplePDF::PDF_Vector > tmpVector;
93 SimplePDF::PDF_Vector::VecType & dstRef( tmpVector->vec );
94 dstRef.reserve( 2 * outputDimension_ );
95 typedef typeof range_ ListType;
96 for( ListType::const_iterator i = range_.begin( ); i != range_.end( ); ++i )
98 dstRef.push_back( SimplePDF::newFloat( i->first ) );
99 dstRef.push_back( SimplePDF::newFloat( i->second ) );
101 (*dst)[ "Range" ] = tmpVector;
104 else
106 if( subType_ == INTERPOLATION || subType_ == CALCULATOR )
108 throw Exceptions::InternalError( strrefdup( "Range must be active for this type of function." ) );
114 std::auto_ptr< const std::vector< double > >
115 Lang::PDF_Function::callImpl( const std::vector< double > & arg ) const
117 throw Exceptions::NotImplemented( "Emulation of PDF functions (of this kind)." );
120 void
121 Lang::PDF_Function::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
123 std::vector< double > argVector;
124 argVector.reserve( inputDimension_ );
125 if( args.size( ) == 1 )
127 const Lang::Value * argPtr = args.getValue( 0 ).getPtr( );
128 switch( inputDimension_ )
130 case 1:
132 typedef const Lang::Float ArgType;
133 ArgType * arg = dynamic_cast< ArgType * >( argPtr );
134 if( arg != 0 )
136 argVector.push_back( arg->val_ );
137 goto done;
140 break;
141 case 2:
143 typedef const Lang::FloatPair ArgType;
144 ArgType * arg = dynamic_cast< ArgType * >( argPtr );
145 if( arg != 0 )
147 argVector.push_back( arg->x_ );
148 argVector.push_back( arg->y_ );
149 goto done;
152 break;
153 case 3:
155 typedef const Lang::FloatTriple ArgType;
156 ArgType * arg = dynamic_cast< ArgType * >( argPtr );
157 if( arg != 0 )
159 argVector.push_back( arg->x_ );
160 argVector.push_back( arg->y_ );
161 argVector.push_back( arg->z_ );
162 goto done;
165 break;
168 typedef const Lang::VectorFunction ArgType;
169 ArgType * arg = dynamic_cast< ArgType * >( argPtr );
170 if( arg != 0 )
172 RefCountPtr< const std::vector< double > > argVec = arg->getNumeric( callLoc );
173 if( argVec->size( ) != inputDimension_ )
175 throw Exceptions::CoreArityMismatch( coreLoc_, inputDimension_, argVec->size( ) );
177 for( size_t i = 0; i < inputDimension_; ++i )
179 argVector.push_back( (*argVec)[ i ] );
181 goto done;
185 throw Exceptions::CoreTypeMismatch( callLoc, coreLoc_, args, 0, Helpers::typeSetString( Lang::Float::staticTypeName( ), Lang::FloatPair::staticTypeName( ), Lang::FloatTriple::staticTypeName( ), Lang::VectorFunction::staticTypeName( ) ) );
188 else if( args.size( ) == inputDimension_ )
190 for( size_t i = 0; i < inputDimension_; ++i )
192 argVector.push_back( Helpers::down_cast_CoreArgument< const Lang::Float >( coreLoc_, args, i, callLoc )->val_ );
195 else
197 throw Exceptions::CoreArityMismatch( coreLoc_, inputDimension_, args.size( ) );
199 done:
201 std::auto_ptr< const std::vector< double > > resVector = this->callImpl( argVector );
203 if( resVector->size( ) != outputDimension_ )
205 throw Exceptions::InternalError( strrefdup( "The PDF function call emulation returned with the wrong arity." ) );
207 RefCountPtr< const Lang::Value > res = NullPtr< const Lang::Value >( );
208 switch( resVector->size( ) )
210 case 0:
212 throw Exceptions::InternalError( strrefdup( "PDF function with output arity 0 detected upon return. " ) );
214 break;
215 case 1:
217 res = RefCountPtr< const Lang::Value >( new Lang::Float( (*resVector)[ 0 ] ) );
219 break;
220 case 2:
222 res = RefCountPtr< const Lang::Value >( new Lang::FloatPair( (*resVector)[ 0 ], (*resVector)[ 1 ] ) );
224 break;
225 case 3:
227 res = RefCountPtr< const Lang::Value >( new Lang::FloatTriple( (*resVector)[ 0 ], (*resVector)[ 1 ], (*resVector)[ 2 ] ) );
229 break;
230 default:
232 std::vector< Kernel::ValueRef > * tmpRes = new typeof *tmpRes;
233 tmpRes->reserve( resVector->size( ) );
234 typedef typeof *resVector VectorType;
235 for( VectorType::const_iterator i = resVector->begin( ); i != resVector->end( ); ++i )
237 tmpRes->push_back( RefCountPtr< const Lang::Value >( new Lang::Float( *i ) ) );
239 res = RefCountPtr< const Lang::Value >( new Lang::VectorFunction( tmpRes ) );
243 Kernel::ContRef cont = evalState->cont_;
244 cont->takeValue( res, evalState );
247 bool
248 Lang::PDF_Function::matchesDimensions( size_t outputDimension, size_t inputDimension ) const
250 return
251 outputDimension_ == outputDimension &&
252 inputDimension_ == inputDimension;
255 RefCountPtr< SimplePDF::PDF_Indirect_out >
256 Lang::PDF_Function::getFunction( ) const
258 return storage.unconst_cast< SimplePDF::PDF_Indirect_out >( );
262 Lang::PDF_InterpolationFunction::PDF_InterpolationFunction( const std::vector< std::pair< double, double > > & range,
263 const std::vector< std::pair< double, double > > & domain,
264 const std::vector< double > & size,
265 unsigned char bitsPerSample,
266 bool cubic,
267 const std::vector< std::pair< double, double > > & encode,
268 const std::vector< std::pair< double, double > > & decode,
269 const std::vector< double > table )
270 : Lang::PDF_Function( Lang::PDF_Function::INTERPOLATION, range.size( ), domain.size( ), true )
272 throw Exceptions::NotImplemented( "PDF_InterpolationFunction::PDF_InterpolationFunction" );
275 Lang::PDF_InterpolationFunction::~PDF_InterpolationFunction( )