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
>( ) )
35 if( outputDimension_
== 0 )
37 throw Exceptions::OutOfRange( strrefdup( "The output dimension of a PDF function cannot be 0." ) );
42 title_
= "< Interpolation function >";
45 title_
= "< Exponential interpolation function >";
48 title_
= "< Stiching function >";
51 title_
= "< Calculator function >";
54 throw Exceptions::InternalError( "PDF_Function::PDF_Function: subType_ out of range in switch." );
58 Lang::PDF_Function::~PDF_Function( )
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
;
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
;
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)." );
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_
)
131 typedef const Lang::Float ArgType
;
132 ArgType
* arg
= dynamic_cast< ArgType
* >( argPtr
);
135 argVector
.push_back( arg
->val_
);
142 typedef const Lang::FloatPair ArgType
;
143 ArgType
* arg
= dynamic_cast< ArgType
* >( argPtr
);
146 argVector
.push_back( arg
->x_
);
147 argVector
.push_back( arg
->y_
);
154 typedef const Lang::FloatTriple ArgType
;
155 ArgType
* arg
= dynamic_cast< ArgType
* >( argPtr
);
158 argVector
.push_back( arg
->x_
);
159 argVector
.push_back( arg
->y_
);
160 argVector
.push_back( arg
->z_
);
167 typedef const Lang::VectorFunction ArgType
;
168 ArgType
* arg
= dynamic_cast< ArgType
* >( argPtr
);
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
] );
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_
);
196 throw Exceptions::CoreArityMismatch( title_
, inputDimension_
, args
.size( ) );
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( ) )
211 throw Exceptions::InternalError( strrefdup( "PDF function with output arity 0 detected upon return. " ) );
216 res
= RefCountPtr
< const Lang::Value
>( new Lang::Float( (*resVector
)[ 0 ] ) );
221 res
= RefCountPtr
< const Lang::Value
>( new Lang::FloatPair( (*resVector
)[ 0 ], (*resVector
)[ 1 ] ) );
226 res
= RefCountPtr
< const Lang::Value
>( new Lang::FloatTriple( (*resVector
)[ 0 ], (*resVector
)[ 1 ], (*resVector
)[ 2 ] ) );
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
);
247 Lang::PDF_Function::matchesDimensions( size_t outputDimension
, size_t inputDimension
) const
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
,
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( )