Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / pdffunctiontypes.cc
blobcc85fb8b667162374addad86ffd2cd836cbab7c7
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 >( ) )
35 if( outputDimension_ == 0 )
37 throw Exceptions::OutOfRange( strrefdup( "The output dimension of a PDF function cannot be 0." ) );
39 switch( subType_ )
41 case INTERPOLATION:
42 title_ = "< Interpolation function >";
43 break;
44 case EXPONENTIAL:
45 title_ = "< Exponential interpolation function >";
46 break;
47 case STITCHING:
48 title_ = "< Stiching function >";
49 break;
50 case CALCULATOR:
51 title_ = "< Calculator function >";
52 break;
53 default:
54 throw Exceptions::InternalError( "PDF_Function::PDF_Function: subType_ out of range in switch." );
58 Lang::PDF_Function::~PDF_Function( )
59 { }
62 void
63 Lang::PDF_Function::addCommonFields( SimplePDF::PDF_Dictionary * dst ) const
65 (*dst)[ "FunctionType" ] = SimplePDF::newInt( subType_ );
67 if( domain_.size( ) != inputDimension_ )
69 throw Exceptions::InternalError( strrefdup( "The size of domain_ does not match inputDimension_." ) );
72 RefCountPtr< SimplePDF::PDF_Vector > tmpVector;
73 SimplePDF::PDF_Vector::VecType & dstRef( tmpVector->vec );
74 dstRef.reserve( 2 * inputDimension_ );
75 typedef typeof domain_ ListType;
76 for( ListType::const_iterator i = domain_.begin( ); i != domain_.end( ); ++i )
78 dstRef.push_back( SimplePDF::newFloat( i->first ) );
79 dstRef.push_back( SimplePDF::newFloat( i->second ) );
81 (*dst)[ "Domain" ] = tmpVector;
84 if( rangeIsActive_ )
86 if( range_.size( ) != inputDimension_ )
88 throw Exceptions::InternalError( strrefdup( "The size of range_ does not match outputDimension_." ) );
91 RefCountPtr< SimplePDF::PDF_Vector > tmpVector;
92 SimplePDF::PDF_Vector::VecType & dstRef( tmpVector->vec );
93 dstRef.reserve( 2 * outputDimension_ );
94 typedef typeof range_ ListType;
95 for( ListType::const_iterator i = range_.begin( ); i != range_.end( ); ++i )
97 dstRef.push_back( SimplePDF::newFloat( i->first ) );
98 dstRef.push_back( SimplePDF::newFloat( i->second ) );
100 (*dst)[ "Range" ] = tmpVector;
103 else
105 if( subType_ == INTERPOLATION || subType_ == CALCULATOR )
107 throw Exceptions::InternalError( strrefdup( "Range must be active for this type of function." ) );
113 std::auto_ptr< const std::vector< double > >
114 Lang::PDF_Function::callImpl( const std::vector< double > & arg ) const
116 throw Exceptions::NotImplemented( "Emulation of PDF functions (of this kind)." );
119 void
120 Lang::PDF_Function::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
122 std::vector< double > argVector;
123 argVector.reserve( inputDimension_ );
124 if( args.size( ) == 1 )
126 const Lang::Value * argPtr = args.getValue( 0 ).getPtr( );
127 switch( inputDimension_ )
129 case 1:
131 typedef const Lang::Float ArgType;
132 ArgType * arg = dynamic_cast< ArgType * >( argPtr );
133 if( arg != 0 )
135 argVector.push_back( arg->val_ );
136 goto done;
139 break;
140 case 2:
142 typedef const Lang::FloatPair ArgType;
143 ArgType * arg = dynamic_cast< ArgType * >( argPtr );
144 if( arg != 0 )
146 argVector.push_back( arg->x_ );
147 argVector.push_back( arg->y_ );
148 goto done;
151 break;
152 case 3:
154 typedef const Lang::FloatTriple ArgType;
155 ArgType * arg = dynamic_cast< ArgType * >( argPtr );
156 if( arg != 0 )
158 argVector.push_back( arg->x_ );
159 argVector.push_back( arg->y_ );
160 argVector.push_back( arg->z_ );
161 goto done;
164 break;
167 typedef const Lang::VectorFunction ArgType;
168 ArgType * arg = dynamic_cast< ArgType * >( argPtr );
169 if( arg != 0 )
171 RefCountPtr< const std::vector< double > > argVec = arg->getNumeric( callLoc );
172 if( argVec->size( ) != inputDimension_ )
174 throw Exceptions::CoreArityMismatch( title_, inputDimension_, argVec->size( ) );
176 for( size_t i = 0; i < inputDimension_; ++i )
178 argVector.push_back( (*argVec)[ i ] );
180 goto done;
184 throw Exceptions::CoreTypeMismatch( callLoc, title_, args.getLoc( 0 ), args.getValue( 0 )->getTypeName( ), Helpers::typeSetString( Lang::Float::staticTypeName( ), Lang::FloatPair::staticTypeName( ), Lang::FloatTriple::staticTypeName( ), Lang::VectorFunction::staticTypeName( ) ) );
187 else if( args.size( ) == inputDimension_ )
189 for( size_t i = 0; i < inputDimension_; ++i )
191 argVector.push_back( Helpers::down_cast_CoreArgument< const Lang::Float >( title_, args, i, callLoc )->val_ );
194 else
196 throw Exceptions::CoreArityMismatch( title_, inputDimension_, args.size( ) );
198 done:
200 std::auto_ptr< const std::vector< double > > resVector = this->callImpl( argVector );
202 if( resVector->size( ) != outputDimension_ )
204 throw Exceptions::InternalError( strrefdup( "The PDF function call emulation returned with the wrong arity." ) );
206 RefCountPtr< const Lang::Value > res = NullPtr< const Lang::Value >( );
207 switch( resVector->size( ) )
209 case 0:
211 throw Exceptions::InternalError( strrefdup( "PDF function with output arity 0 detected upon return. " ) );
213 break;
214 case 1:
216 res = RefCountPtr< const Lang::Value >( new Lang::Float( (*resVector)[ 0 ] ) );
218 break;
219 case 2:
221 res = RefCountPtr< const Lang::Value >( new Lang::FloatPair( (*resVector)[ 0 ], (*resVector)[ 1 ] ) );
223 break;
224 case 3:
226 res = RefCountPtr< const Lang::Value >( new Lang::FloatTriple( (*resVector)[ 0 ], (*resVector)[ 1 ], (*resVector)[ 2 ] ) );
228 break;
229 default:
231 std::vector< Kernel::ValueRef > * tmpRes = new typeof *tmpRes;
232 tmpRes->reserve( resVector->size( ) );
233 typedef typeof *resVector VectorType;
234 for( VectorType::const_iterator i = resVector->begin( ); i != resVector->end( ); ++i )
236 tmpRes->push_back( RefCountPtr< const Lang::Value >( new Lang::Float( *i ) ) );
238 res = RefCountPtr< const Lang::Value >( new Lang::VectorFunction( tmpRes ) );
242 Kernel::ContRef cont = evalState->cont_;
243 cont->takeValue( res, evalState );
246 bool
247 Lang::PDF_Function::matchesDimensions( size_t outputDimension, size_t inputDimension ) const
249 return
250 outputDimension_ == outputDimension &&
251 inputDimension_ == inputDimension;
254 RefCountPtr< SimplePDF::PDF_Indirect_out >
255 Lang::PDF_Function::getFunction( ) const
257 return storage.unconst_cast< SimplePDF::PDF_Indirect_out >( );
261 Lang::PDF_InterpolationFunction::PDF_InterpolationFunction( const std::vector< std::pair< double, double > > & range,
262 const std::vector< std::pair< double, double > > & domain,
263 const std::vector< double > & size,
264 unsigned char bitsPerSample,
265 bool cubic,
266 const std::vector< std::pair< double, double > > & encode,
267 const std::vector< std::pair< double, double > > & decode,
268 const std::vector< double > table )
269 : Lang::PDF_Function( Lang::PDF_Function::INTERPOLATION, range.size( ), domain.size( ), true )
271 throw Exceptions::NotImplemented( "PDF_InterpolationFunction::PDF_InterpolationFunction" );
274 Lang::PDF_InterpolationFunction::~PDF_InterpolationFunction( )