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
19 #include "Shapes_Helpers_decls.h"
21 #include "pdffunctiontypes.h"
23 #include "shapescore.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." ) );
43 coreLoc_
= RefCountPtr
< const Interaction::CoreLocation
>( new Interaction::CharPtrLocation( "< Interpolation function >" ) );
46 coreLoc_
= RefCountPtr
< const Interaction::CoreLocation
>( new Interaction::CharPtrLocation( "< Exponential interpolation function >" ) );
49 coreLoc_
= RefCountPtr
< const Interaction::CoreLocation
>( new Interaction::CharPtrLocation( "< Stiching function >" ) );
52 coreLoc_
= RefCountPtr
< const Interaction::CoreLocation
>( new Interaction::CharPtrLocation( "< Calculator function >" ) );
55 throw Exceptions::InternalError( "PDF_Function::PDF_Function: subType_ out of range in switch." );
59 Lang::PDF_Function::~PDF_Function( )
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
;
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
;
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)." );
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_
)
132 typedef const Lang::Float ArgType
;
133 ArgType
* arg
= dynamic_cast< ArgType
* >( argPtr
);
136 argVector
.push_back( arg
->val_
);
143 typedef const Lang::FloatPair ArgType
;
144 ArgType
* arg
= dynamic_cast< ArgType
* >( argPtr
);
147 argVector
.push_back( arg
->x_
);
148 argVector
.push_back( arg
->y_
);
155 typedef const Lang::FloatTriple ArgType
;
156 ArgType
* arg
= dynamic_cast< ArgType
* >( argPtr
);
159 argVector
.push_back( arg
->x_
);
160 argVector
.push_back( arg
->y_
);
161 argVector
.push_back( arg
->z_
);
168 typedef const Lang::VectorFunction ArgType
;
169 ArgType
* arg
= dynamic_cast< ArgType
* >( argPtr
);
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
] );
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_
);
197 throw Exceptions::CoreArityMismatch( coreLoc_
, inputDimension_
, args
.size( ) );
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( ) )
212 throw Exceptions::InternalError( strrefdup( "PDF function with output arity 0 detected upon return. " ) );
217 res
= RefCountPtr
< const Lang::Value
>( new Lang::Float( (*resVector
)[ 0 ] ) );
222 res
= RefCountPtr
< const Lang::Value
>( new Lang::FloatPair( (*resVector
)[ 0 ], (*resVector
)[ 1 ] ) );
227 res
= RefCountPtr
< const Lang::Value
>( new Lang::FloatTriple( (*resVector
)[ 0 ], (*resVector
)[ 1 ], (*resVector
)[ 2 ] ) );
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
);
248 Lang::PDF_Function::matchesDimensions( size_t outputDimension
, size_t inputDimension
) const
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
,
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( )