1 /* 2 * conn_parameter.h 3 * 4 * This file is part of NEST. 5 * 6 * Copyright (C) 2004 The NEST Initiative 7 * 8 * NEST is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation, either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * NEST is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with NEST. If not, see <http://www.gnu.org/licenses/>. 20 * 21 */ 22 23 #ifndef CONN_PARAMETER_H 24 #define CONN_PARAMETER_H 25 26 // C++ includes: 27 #include <limits> 28 #include <vector> 29 30 // Includes from nestkernel: 31 #include "exceptions.h" 32 #include "parameter.h" 33 #include "nest_datums.h" 34 35 // Includes from sli: 36 #include "token.h" 37 38 /** 39 * Base class for parameters provided to connection routines. 40 * 41 * Principles for these parameters are 42 * - Each parameter is a single scalar value. 43 * - The parameter will be returned as type double. 44 * - The parameter values can be given either as 45 * - a single scalar: the same value is returned for each call 46 * - a random deviate generator: a new random values is returned for each call 47 * - an array of scalars: values are returned in order 48 */ 49 50 namespace nest 51 { 52 53 class ConnParameter 54 { 55 56 public: ConnParameter()57 ConnParameter() 58 { 59 } 60 ~ConnParameter()61 virtual ~ConnParameter() 62 { 63 } 64 65 /** 66 * Return parameter value. 67 * 68 * The parameter value may depend on target threads 69 * and random numbers. Both must be supplied, even if 70 * a concrete parameter type does not use them. 71 * 72 * @param target_thread will be ignored except for array parameters. 73 * @param rng random number generator pointer 74 * will be ignored except for random parameters. 75 */ 76 virtual double value_double( thread, RngPtr, index, Node* ) const = 0; 77 virtual long value_int( thread, RngPtr, index, Node* ) const = 0; skip(thread,size_t)78 virtual void skip( thread, size_t ) const 79 { 80 } 81 virtual bool is_array() const = 0; 82 83 virtual bool is_scalar()84 is_scalar() const 85 { 86 return false; 87 } 88 89 virtual bool provides_long()90 provides_long() const 91 { 92 return false; 93 } 94 95 virtual void reset()96 reset() const 97 { 98 throw NotImplemented( "Symmetric connections require parameters that can be reset." ); 99 } 100 101 /** 102 * Returns number of values available. 103 * 104 * 0 indicates scalar/unlimited supply. 105 */ 106 virtual size_t number_of_values()107 number_of_values() const 108 { 109 return 0; 110 } 111 112 /** 113 * @param t parameter 114 * type is established by casts to all acceptedpossibilities 115 * @param nthread number of threads 116 * required to fix number pointers to the iterator (one for each thread) 117 */ 118 static ConnParameter* create( const Token&, const size_t ); 119 }; 120 121 122 /** 123 * Single double value. 124 * 125 * On each request, it returns the same value. 126 */ 127 class ScalarDoubleParameter : public ConnParameter 128 { 129 public: ScalarDoubleParameter(double value,const size_t)130 ScalarDoubleParameter( double value, const size_t ) 131 : value_( value ) 132 { 133 } 134 135 double value_double(thread,RngPtr,index,Node *)136 value_double( thread, RngPtr, index, Node* ) const 137 { 138 return value_; 139 } 140 141 long value_int(thread,RngPtr,index,Node *)142 value_int( thread, RngPtr, index, Node* ) const 143 { 144 throw KernelException( "ConnParameter calls value function with false return type." ); 145 } 146 147 inline bool is_array()148 is_array() const 149 { 150 return false; 151 } 152 153 void reset()154 reset() const 155 { 156 } 157 158 bool is_scalar()159 is_scalar() const 160 { 161 return true; 162 } 163 164 private: 165 double value_; 166 }; 167 168 /** 169 * Single integer value. 170 * 171 * On each request, it returns the same value. 172 */ 173 class ScalarIntegerParameter : public ConnParameter 174 { 175 public: ScalarIntegerParameter(long value,const size_t)176 ScalarIntegerParameter( long value, const size_t ) 177 : value_( value ) 178 { 179 } 180 181 double value_double(thread,RngPtr,index,Node *)182 value_double( thread, RngPtr, index, Node* ) const 183 { 184 return static_cast< double >( value_ ); 185 } 186 187 long value_int(thread,RngPtr,index,Node *)188 value_int( thread, RngPtr, index, Node* ) const 189 { 190 return value_; 191 } 192 193 inline bool is_array()194 is_array() const 195 { 196 return false; 197 } 198 199 void reset()200 reset() const 201 { 202 } 203 204 bool is_scalar()205 is_scalar() const 206 { 207 return true; 208 } 209 210 bool provides_long()211 provides_long() const 212 { 213 return true; 214 } 215 216 private: 217 long value_; 218 }; 219 220 221 /** 222 * Array parameter classes, returning double values in order. 223 * 224 * - The array of values must not be empty 225 * (so return 0 for number_of_values can signal non-array parameter) 226 * - Throws exception if more values requested than available. 227 * - The class contains nthread number of pointers (one for each thread) 228 * to an iterator, which runs over the parameters initialised in an array. 229 * Each pointer is moved along the parameter array by the function 230 * value_double(), which returns the current parameter value and moves the 231 * pointer to the subsequent position. 232 * - All parameters are doubles, thus calling the function value_int() 233 * throws an error. 234 */ 235 236 class ArrayDoubleParameter : public ConnParameter 237 { 238 public: ArrayDoubleParameter(const std::vector<double> & values,const size_t nthreads)239 ArrayDoubleParameter( const std::vector< double >& values, const size_t nthreads ) 240 : values_( &values ) 241 , next_( nthreads, values_->begin() ) 242 { 243 } 244 245 void skip(thread tid,size_t n_skip)246 skip( thread tid, size_t n_skip ) const 247 { 248 if ( next_[ tid ] < values_->end() ) 249 { 250 next_[ tid ] += n_skip; 251 } 252 else 253 { 254 throw KernelException( "Parameter values exhausted." ); 255 } 256 } 257 258 size_t number_of_values()259 number_of_values() const 260 { 261 return values_->size(); 262 } 263 264 double value_double(thread tid,RngPtr,index,Node *)265 value_double( thread tid, RngPtr, index, Node* ) const 266 { 267 if ( next_[ tid ] != values_->end() ) 268 { 269 return *next_[ tid ]++; 270 } 271 else 272 { 273 throw KernelException( "Parameter values exhausted." ); 274 } 275 } 276 277 long value_int(thread,RngPtr,index,Node *)278 value_int( thread, RngPtr, index, Node* ) const 279 { 280 throw KernelException( "ConnParameter calls value function with false return type." ); 281 } 282 283 inline bool is_array()284 is_array() const 285 { 286 return true; 287 } 288 289 void reset()290 reset() const 291 { 292 for ( std::vector< std::vector< double >::const_iterator >::iterator it = next_.begin(); it != next_.end(); ++it ) 293 { 294 *it = values_->begin(); 295 } 296 } 297 298 private: 299 const std::vector< double >* values_; 300 mutable std::vector< std::vector< double >::const_iterator > next_; 301 }; 302 303 /** 304 * Array parameter classes, returning integer values in order. 305 * 306 * - The array of values must not be empty 307 * (so return 0 for number_of_values can signal non-array parameter) 308 * - Throws exception if more values requested than available. 309 * - The class contains nthread number of pointers (one for each thread) 310 * to an iterator, which runs over the parameters initialised in an array. 311 * Each pointer is moved along the parameter array by the function 312 * value_int(), which returns the current parameter value and moves the 313 * pointer to the subsequent position. 314 * - All parameters are integer, thus calling the function value_double() 315 * throws an error. 316 */ 317 318 class ArrayIntegerParameter : public ConnParameter 319 { 320 public: ArrayIntegerParameter(const std::vector<long> & values,const size_t nthreads)321 ArrayIntegerParameter( const std::vector< long >& values, const size_t nthreads ) 322 : values_( &values ) 323 , next_( nthreads, values_->begin() ) 324 { 325 } 326 327 void skip(thread tid,size_t n_skip)328 skip( thread tid, size_t n_skip ) const 329 { 330 if ( next_[ tid ] < values_->end() ) 331 { 332 next_[ tid ] += n_skip; 333 } 334 else 335 { 336 throw KernelException( "Parameter values exhausted." ); 337 } 338 } 339 340 size_t number_of_values()341 number_of_values() const 342 { 343 return values_->size(); 344 } 345 346 long value_int(thread tid,RngPtr,index,Node *)347 value_int( thread tid, RngPtr, index, Node* ) const 348 { 349 if ( next_[ tid ] != values_->end() ) 350 { 351 return *next_[ tid ]++; 352 } 353 else 354 { 355 throw KernelException( "Parameter values exhausted." ); 356 } 357 } 358 359 double value_double(thread tid,RngPtr,index,Node *)360 value_double( thread tid, RngPtr, index, Node* ) const 361 { 362 if ( next_[ tid ] != values_->end() ) 363 { 364 return static_cast< double >( *next_[ tid ]++ ); 365 } 366 else 367 { 368 throw KernelException( "Parameter values exhausted." ); 369 } 370 } 371 372 inline bool is_array()373 is_array() const 374 { 375 return true; 376 } 377 378 bool provides_long()379 provides_long() const 380 { 381 return true; 382 } 383 384 void reset()385 reset() const 386 { 387 for ( std::vector< std::vector< long >::const_iterator >::iterator it = next_.begin(); it != next_.end(); ++it ) 388 { 389 *it = values_->begin(); 390 } 391 } 392 393 private: 394 const std::vector< long >* values_; 395 mutable std::vector< std::vector< long >::const_iterator > next_; 396 }; 397 398 class ParameterConnParameterWrapper : public ConnParameter 399 { 400 public: 401 ParameterConnParameterWrapper( const ParameterDatum&, const size_t ); 402 403 double value_double( thread target_thread, RngPtr rng, index snode_id, Node* target ) const; 404 405 long value_int(thread target_thread,RngPtr rng,index snode_id,Node * target)406 value_int( thread target_thread, RngPtr rng, index snode_id, Node* target ) const 407 { 408 return value_double( target_thread, rng, snode_id, target ); 409 } 410 411 inline bool is_array()412 is_array() const 413 { 414 return false; 415 } 416 417 bool provides_long()418 provides_long() const 419 { 420 return parameter_->returns_int_only(); 421 } 422 423 private: 424 Parameter* parameter_; 425 }; 426 427 } // namespace nest 428 429 #endif 430