ccgsl 2.7.2
C++wrappersforGnuScientificLibrary
multilarge_nlinear_function_fdf.hpp
Go to the documentation of this file.
1/*
2 * $Id
3 * Copyright (C) 2010, 2011, 2012, 2020 John D Lamb
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at
8 * your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#ifndef CCGSL_MULTILARGE_NLINEAR_FUNCTION_FDF_HPP
21#define CCGSL_MULTILARGE_NLINEAR_FUNCTION_FDF_HPP
22
23// For std::swap
24#if __cplusplus <= 199711L
25#include<algorithm>
26#else
27#include<utility>
28#endif
29#include<gsl/gsl_multilarge_nlinear.h>
30#include"vector.hpp"
31#include"matrix.hpp"
32
33namespace gsl {
34 namespace multilarge {
35 namespace nlinear {
36 class function_fdf;
37 template<typename T> void function_constructor( function_fdf& f, T& t );
56 class function_fdf : public gsl_multilarge_nlinear_fdf {
57 public:
65 struct concept_fdf {
73 virtual int f( gsl::vector const& x, gsl::vector& f ) = 0;
86 virtual int df( CBLAS_TRANSPOSE_t TransJ, gsl::vector const& x, gsl::vector const& u,
87 gsl::vector& v,gsl::matrix& JTJ ) = 0;
91 virtual size_t xSize() const = 0;
95 virtual size_t fSize() const = 0;
96 };
104 struct concept_fvv {
114 virtual int fvv( gsl::vector const& x, gsl::vector const& v, gsl::vector& fvv ) = 0;
115 };
116#ifndef DOXYGEN_SKIP
117 struct address_of {
118 typedef int (*f_t)(gsl_vector const*,void*,gsl_vector*);
119 typedef int (*df_t)(CBLAS_TRANSPOSE_t,gsl_vector const*,
120 gsl_vector const*,void*,gsl_vector*,gsl_matrix*);
121 typedef int (*fvv_t)(gsl_vector const*,gsl_vector const*,void*,gsl_vector*);
122 // Maybe not needed: f must not be nullptr
123 template<typename U, int (U::*)(gsl::vector const&, gsl::vector&)>
124 struct fSfinae {};
125 template<typename U, int (U::*)(gsl::vector const&, gsl::vector&) const>
126 struct fSfinaeC {};
127 template<typename U> static f_t f(fSfinae<U,&U::f>*){return &F<U>::fn;}
128 template<typename U> static f_t f(fSfinaeC<U,&U::f>*){return &F<U>::fn;}
129 template<typename U> static f_t f(...){return 0;}
130 // address_of<X>::f = nonzero if f implemented
131 template<typename U, int (U::*)(CBLAS_TRANSPOSE_t,gsl::vector const&,
132 gsl::vector const&,gsl_vector*,gsl::matrix&)>
133 struct dfSfinae {};
134 template<typename U, int (U::*)(CBLAS_TRANSPOSE_t,gsl::vector const&,
135 gsl::vector const&,gsl_vector*,gsl::matrix&) const>
136 struct dfSfinaeC {};
137 template<typename U> static df_t df(dfSfinae<U,&U::df>*){return &F<U>::dfn;}
138 template<typename U> static df_t df(dfSfinaeC<U,&U::df>*){return &F<U>::dfn;}
139 template<typename U> static df_t df(...){return 0;}
140 // address_of<X>::df = nonzero if df implemented
141 template<typename U, int (U::*)(gsl::vector const&, gsl::vector const&, gsl::vector&)>
142 struct fvvSfinae {};
143 template<typename U, int (U::*)(gsl::vector const&, gsl::vector const&, gsl::vector&)
144 const>
145 struct fvvSfinaeC {};
146 template<typename U> static fvv_t fvv(fvvSfinae<U,&U::fvv>*){return &F<U>::fvvn;}
147 template<typename U> static fvv_t fvv(fvvSfinaeC<U,&U::fvv>*){return &F<U>::fvvn;}
148 template<typename U> static fvv_t fvv(...){return 0;}
149 // address_of<X>::fvv = nonzero if fvv implemented
150 };
151 private:
155 struct base_F {
159 typedef int (*function_t)(gsl_vector const*,void*,gsl_vector*);
163 typedef int (*dfunction_t)(CBLAS_TRANSPOSE_t,gsl_vector const*,
164 gsl_vector const*,void*,gsl_vector*,gsl_matrix*);
168 typedef int (*fvvfunction_t)(gsl_vector const*,gsl_vector const*,void*,gsl_vector*);
169 };
173 template<typename T>
174 struct F : public base_F {
175 public:
180 F( T& t ) : t( t ){
181 xv.wrap_gsl_vector_without_ownership( 0 );
182 uv.wrap_gsl_vector_without_ownership( 0 );
183 vv.wrap_gsl_vector_without_ownership( 0 );
184 fv.wrap_gsl_vector_without_ownership( 0 );
185 JTJv.wrap_gsl_matrix_without_ownership( 0 );
186 }
187 public:
196 static int fn( gsl_vector const* x, void* params, gsl_vector* f ){
197 // share gsl_vector* and gsl::vector contents.
198 F<T>* ft = reinterpret_cast<F<T>*>( params );
199 ft->xv.ccgsl_pointer = const_cast<gsl_vector*>( x );
200 ft->fv.ccgsl_pointer = f;
201 return ft->t.f( ft->xv, ft->fv ); }
213 static int dfn( CBLAS_TRANSPOSE_t TransJ, gsl_vector const* x, gsl_vector const* u,
214 void* params, gsl_vector* v, gsl_matrix* JTJ ){
215 // share gsl_vector* and gsl::vector contents.
216 F<T>* ft = reinterpret_cast<F<T>*>( params );
217 ft->xv.ccgsl_pointer = const_cast<gsl_vector*>( x );
218 ft->uv.ccgsl_pointer = const_cast<gsl_vector*>( u );
219 ft->vv.ccgsl_pointer = v;
220 ft->JTJv.ccgsl_pointer = JTJ;
221 return ft->t.df( TransJ, ft->xv, ft->uv, ft->vv, ft->JTJv ); }
231 static int fvvn( gsl_vector const* x, gsl_vector const* v,
232 void* params, gsl_vector* f ){
233 // share gsl_vector* and gsl::vector contents.
234 F<T>* ft = reinterpret_cast<F<T>*>( params );
235 ft->xv.ccgsl_pointer = const_cast<gsl_vector*>( x );
236 ft->vv.ccgsl_pointer = const_cast<gsl_vector*>( v );
237 ft->fv.ccgsl_pointer = f;
238 return ft->t.fvv( ft->xv, ft->vv, ft->fv ); }
239 private:
243 T& t;
247 gsl::vector xv;
251 gsl::vector uv;
255 gsl::vector vv;
259 gsl::vector fv;
263 gsl::matrix JTJv;
264 };
268 class Fn : public base_F {
269 public:
275 Fn( int (*const f)(gsl::vector const&,gsl::vector&),
276 int (*const df)(CBLAS_TRANSPOSE_t,gsl::vector const&,gsl::vector const&,
278 int (*const fvv)(gsl::vector const&,gsl::vector&,gsl::vector&),
279 size_t const xSize, size_t fSize )
280 : f( f ), df( df ), fvv( fvv ), xSize( xSize ), fSize( fSize ){}
284 function_t function(){ return &fn; }
288 dfunction_t dfunction(){ return &dfn; }
292 fvvfunction_t fvvfunction(){ return &fvvn; }
293 private:
297 int (*const f)(gsl::vector const&,gsl::vector&);
301 int (*const df)(CBLAS_TRANSPOSE_t,gsl::vector const&,gsl::vector const&,
306 int (*const fvv)(gsl::vector const&,gsl::vector&,gsl::vector&);
307 public:
311 size_t const xSize;
315 size_t const fSize;
324 static int fn( gsl_vector const* x, void* params, gsl_vector* f ){
325 // share gsl_vector* and gsl::vector contents.
326 Fn* ft = reinterpret_cast<Fn*>( params );
327 ft->fv.ccgsl_pointer = f;
328 return ft->f( ft->xv, ft->fv ); }
340 static int dfn( CBLAS_TRANSPOSE_t TransJ, gsl_vector const* x, gsl_vector const* u,
341 void* params, gsl_vector* v, gsl_matrix* JTJ ){
342 // share gsl_vector* and gsl::vector contents.
343 Fn* ft = reinterpret_cast<Fn*>( params );
344 ft->xv.ccgsl_pointer = const_cast<gsl_vector*>( x );
345 ft->uv.ccgsl_pointer = const_cast<gsl_vector*>( u );
346 ft->vv.ccgsl_pointer = v;
347 ft->JTJv.ccgsl_pointer = JTJ;
348 return ft->df( TransJ, ft->xv, ft->uv, ft->vv, ft->JTJv ); }
358 static int fvvn( gsl_vector const* x, gsl_vector const* v,
359 void* params, gsl_vector* f ){
360 // share gsl_vector* and gsl::vector contents.
361 Fn* ft = reinterpret_cast<Fn*>( params );
362 ft->xv.ccgsl_pointer = const_cast<gsl_vector*>( x );
363 ft->vv.ccgsl_pointer = const_cast<gsl_vector*>( v );
364 ft->fv.ccgsl_pointer = f;
365 return ft->fvv( ft->xv, ft->vv, ft->fv ); }
366 private:
370 gsl::vector xv;
374 gsl::vector vv;
378 gsl::vector uv;
382 gsl::vector fv;
386 gsl::matrix JTJv;
387 };
388#endif
392 base_F* func;
396 size_t* count;
397 public:
402 func = 0;
403 f = 0;
404 df = 0;
405 fvv = 0;
406 p = 0;
407 n = 0;
408 params = 0;
409 count = 0; // initially nullptr will do
410 }
411 template<typename T>
419 explicit function_fdf( gsl_multilarge_nlinear_fdf& v ){
420 // explicitly set function = 0 to indicate nothing to be deleted.
421 func = 0;
422 // copy
423 f = v.f;
424 df = v.df;
425 fvv = v.fvv;
426 p = v.p;
427 n = v.n;
428 params = v.params;
429 // just plausibly we could fail to allocate count: no further action needed.
430 count = new size_t;
431 *count = 1; // initially there is just one reference to function
432 }
438 template<typename T>
439 function_fdf( T& t ){ function_constructor<T>( *this, t ); }
449 function_fdf( int (* const f)(gsl::vector const&, gsl::vector&),
450 int (* const df)(CBLAS_TRANSPOSE_t,gsl::vector const&, gsl::vector const&,
452 int (* const fvv)(gsl::vector const&, gsl::vector&, gsl::vector&),
453 size_t const xSize, size_t const fSize ){
454 func = 0;
455 count = 0;
456 func = new function_fdf::Fn( f, df, fvv, xSize, fSize );
457 this->f = (0 == f) ? 0 : Fn::fn;
458 this->df = (0 == df) ? 0 : Fn::dfn;
459 this->fvv = (0 == fvv) ? 0 : Fn::fvvn;
460 this->n = fSize;
461 this->p = xSize;
462 params = func;
463 // just plausibly we could fail to allocate count: no further action needed.
464 count = new size_t;
465 *count = 1; // initially there is just one reference to function
466 }
467
468 // Copy and move constructors
469 // copy constructor
476 function_fdf( function_fdf const& v ) : func( v.func ), count( v.count ){
477 f = v.f;
478 df = v.df;
479 fvv = v.fvv;
480 n = v.n;
481 p = v.p;
482 params = v.params;
483 if( count != 0 ) ++*count; // function is now shared.
484 }
485 // assignment operator
491 // first, possibly delete anything pointed to by this
492 if( count == 0 or --*count == 0 ){
493 delete func;
494 delete count;
495 }
496 // Then copy
497 func = v.func;
498 f = v.f;
499 df = v.df;
500 fvv = v.fvv;
501 n = v.n;
502 p = v.p;
503 params = v.params;
504 // count = v.count;
505 if( count != 0 ) ++*count; // function is now shared.
506 return *this;
507 }
508#ifdef __GXX_EXPERIMENTAL_CXX0X__
513 function_fdf( function_fdf&& v ) : func( v.func ), count( nullptr ){
514 std::swap( f, v.f );
515 std::swap( df, v.df );
516 std::swap( fvv, v.fvv );
517 std::swap( n, v.n );
518 std::swap( p, v.p );
519 std::swap( params, v.params );
520 std::swap( count, v.count );
521 v.func = nullptr;
522 }
529 std::swap( func, v.func );
530 std::swap( f, v.f );
531 std::swap( df, v.df );
532 std::swap( fvv, v.fvv );
533 std::swap( n, v.n );
534 std::swap( p, v.p );
535 std::swap( params, v.params );
536 std::swap( count, v.count );
537 return *this;
538 }
539#endif
544 // first, possibly delete anything pointed to by f
545 if( count == 0 or --*count == 0 ){
546 delete func;
547 delete count;
548 }
549 }
550 };
551#ifndef DOXYGEN_SKIP
559 template<typename T>
560 inline void function_constructor( function_fdf& f, T& t ){
561 f.func = 0;
562 f.count = 0;
563 // try constructing from T
564 f.func = new function_fdf::F<T>( t );
565 f.f = function_fdf::address_of::f<T>(0);
566 f.df = function_fdf::address_of::df<T>(0);
567 f.fvv = function_fdf::address_of::fvv<T>(0);
568 // Checks coplete
569 f.n = t.fSize();
570 f.p = t.xSize();
571 f.params = f.func;
572 // just plausibly we could fail to allocate count: no further action needed.
573 f.count = new size_t;
574 *f.count = 1; // initially there is just one reference to function
575 }
581 template<>
582 inline void function_constructor( function_fdf& f, function_fdf& v ){
583 f.func = v.func; f.count = v.count; f.f = v.f; f.df = v.df; f.fvv = v.fvv;
584 f.n = v.n; f.p = v.p; f.params = v.params; if( f.count != 0 ) ++*f.count;
585 /* function is now shared. */ }
591 template<>
592 inline void function_constructor( function_fdf& f, gsl_multilarge_nlinear_fdf& v ){
593 f.f = v.f; f.df = v.df; f.fvv = v.fvv; f.n = v.n; f.p = v.p; f.params = v.params; }
594#endif
600 template<typename T>
602 function_fdf fn( t );
603 return fn;
604 }
605 }
606 }
607}
608
609#endif
Class that extends gsl_function_fdf so that it can be constructed from arbitrary function objects.
size_t * count
The shared reference count: used for copying this.
This class handles matrix objects as shared handles.
Definition: matrix.hpp:72
Class that extends gsl_multilarge_nlinear_fdf so that it can be constructed from arbitrary function o...
function_fdf(T &t)
Construct from an object that implements gsl::multilarge::nlinear::function_fdf::concept.
base_F * func
This gives something for params to point to.
friend void function_constructor(function_fdf &, T &)
function_fdf & operator=(function_fdf const &v)
The assignment operator.
function_fdf()
The default constructor is only really useful for assigning to.
function_fdf(gsl_multilarge_nlinear_fdf &v)
Could construct from a gsl_multilarge_nlinear_fdf.
function_fdf(int(*const f)(gsl::vector const &, gsl::vector &), int(*const df)(CBLAS_TRANSPOSE_t, gsl::vector const &, gsl::vector const &, gsl::vector &, gsl::matrix &), int(*const fvv)(gsl::vector const &, gsl::vector &, gsl::vector &), size_t const xSize, size_t const fSize)
Construct from a function with no parameters (but with n function values and arguments).
~function_fdf()
The destructor unshares any shared resource.
function_fdf & operator=(function_fdf &&v)
Move operator.
function_fdf(function_fdf const &v)
The copy constructor.
size_t * count
The shared reference count: used for copying this.
This class handles vector objects as shared handles.
Definition: vector.hpp:74
void function_constructor(function_fdf &f, T &t)
function_fdf make_function_fdf(T &t)
Make a gsl::multilarge::nlinear::function_fdf from a function object that implements gsl::multilarge:...
int df(double const h, fdtype const fdtype, vector const &x, vector const &wts, gsl::multilarge::nlinear::function_fdf &fdf, vector const &f, matrix &J, vector &work)
C++ version of gsl_multilarge_nlinear_df().
size_t n(workspace const &w)
C++ version of gsl_rstat_n().
Definition: rstat.hpp:299
double F(double phi, double k, mode_t mode)
C++ version of gsl_sf_ellint_F().
Definition: sf_ellint.hpp:138
The gsl package creates an interface to the GNU Scientific Library for C++.
Definition: blas.hpp:34
virtual int f(gsl::vector const &x, gsl::vector &f)=0
The function.
virtual size_t fSize() const =0
This function should return the number of elements of f in f().
virtual size_t xSize() const =0
This function should return the number of elements of x in f().
virtual int df(CBLAS_TRANSPOSE_t TransJ, gsl::vector const &x, gsl::vector const &u, gsl::vector &v, gsl::matrix &JTJ)=0
The derivatives (as Jacobian matrix).
virtual int fvv(gsl::vector const &x, gsl::vector const &v, gsl::vector &fvv)=0
The second directional derivatives.