gsl_multiroots__dnewton.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /* multiroots/dnewton.c
  2. *
  3. * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough
  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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. #include "gsl__config.h"
  20. #include <stddef.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <math.h>
  24. #include <float.h>
  25. #include "gsl_math.h"
  26. #include "gsl_errno.h"
  27. #include "gsl_multiroots.h"
  28. #include "gsl_linalg.h"
  29. /* Newton method using a finite difference approximation to the jacobian.
  30. The derivatives are estimated using a step size of
  31. h_i = sqrt(DBL_EPSILON) * x_i
  32. */
  33. typedef struct
  34. {
  35. gsl_matrix * J;
  36. gsl_matrix * lu;
  37. gsl_permutation * permutation;
  38. }
  39. dnewton_state_t;
  40. static int dnewton_alloc (void * vstate, size_t n);
  41. static int dnewton_set (void * vstate, gsl_multiroot_function * function, gsl_vector * x, gsl_vector * f, gsl_vector * dx);
  42. static int dnewton_iterate (void * vstate, gsl_multiroot_function * function, gsl_vector * x, gsl_vector * f, gsl_vector * dx);
  43. static void dnewton_free (void * vstate);
  44. static int
  45. dnewton_alloc (void * vstate, size_t n)
  46. {
  47. dnewton_state_t * state = (dnewton_state_t *) vstate;
  48. gsl_permutation * p;
  49. gsl_matrix * m, * J;
  50. m = gsl_matrix_calloc (n,n);
  51. if (m == 0)
  52. {
  53. GSL_ERROR ("failed to allocate space for lu", GSL_ENOMEM);
  54. }
  55. state->lu = m ;
  56. p = gsl_permutation_calloc (n);
  57. if (p == 0)
  58. {
  59. gsl_matrix_free(m);
  60. GSL_ERROR ("failed to allocate space for permutation", GSL_ENOMEM);
  61. }
  62. state->permutation = p ;
  63. J = gsl_matrix_calloc (n,n);
  64. if (J == 0)
  65. {
  66. gsl_permutation_free(p);
  67. gsl_matrix_free(m);
  68. GSL_ERROR ("failed to allocate space for d", GSL_ENOMEM);
  69. }
  70. state->J = J;
  71. return GSL_SUCCESS;
  72. }
  73. static int
  74. dnewton_set (void * vstate, gsl_multiroot_function * function, gsl_vector * x, gsl_vector * f, gsl_vector * dx)
  75. {
  76. dnewton_state_t * state = (dnewton_state_t *) vstate;
  77. size_t i, n = function->n ;
  78. int status;
  79. status = GSL_MULTIROOT_FN_EVAL (function, x, f);
  80. if (status)
  81. return status;
  82. status = gsl_multiroot_fdjacobian (function, x, f, GSL_SQRT_DBL_EPSILON,
  83. state->J);
  84. if (status)
  85. return status;
  86. for (i = 0; i < n; i++)
  87. {
  88. gsl_vector_set (dx, i, 0.0);
  89. }
  90. return GSL_SUCCESS;
  91. }
  92. static int
  93. dnewton_iterate (void * vstate, gsl_multiroot_function * function, gsl_vector * x, gsl_vector * f, gsl_vector * dx)
  94. {
  95. dnewton_state_t * state = (dnewton_state_t *) vstate;
  96. int signum ;
  97. size_t i;
  98. size_t n = function->n ;
  99. gsl_matrix_memcpy (state->lu, state->J);
  100. {
  101. int status = gsl_linalg_LU_decomp (state->lu, state->permutation, &signum);
  102. if (status)
  103. return status;
  104. }
  105. {
  106. int status = gsl_linalg_LU_solve (state->lu, state->permutation, f, dx);
  107. if (status)
  108. return status;
  109. }
  110. for (i = 0; i < n; i++)
  111. {
  112. double e = gsl_vector_get (dx, i);
  113. double y = gsl_vector_get (x, i);
  114. gsl_vector_set (dx, i, -e);
  115. gsl_vector_set (x, i, y - e);
  116. }
  117. {
  118. int status = GSL_MULTIROOT_FN_EVAL (function, x, f);
  119. if (status != GSL_SUCCESS)
  120. {
  121. return GSL_EBADFUNC;
  122. }
  123. }
  124. gsl_multiroot_fdjacobian (function, x, f, GSL_SQRT_DBL_EPSILON, state->J);
  125. return GSL_SUCCESS;
  126. }
  127. static void
  128. dnewton_free (void * vstate)
  129. {
  130. dnewton_state_t * state = (dnewton_state_t *) vstate;
  131. gsl_matrix_free(state->J);
  132. gsl_matrix_free(state->lu);
  133. gsl_permutation_free(state->permutation);
  134. }
  135. static const gsl_multiroot_fsolver_type dnewton_type =
  136. {"dnewton", /* name */
  137. sizeof (dnewton_state_t),
  138. &dnewton_alloc,
  139. &dnewton_set,
  140. &dnewton_iterate,
  141. &dnewton_free};
  142. const gsl_multiroot_fsolver_type * gsl_multiroot_fsolver_dnewton = &dnewton_type;