home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / octave-1.1.1p1-src.tgz / tar.out / fsf / octave / liboctave / NPSOL.cc < prev    next >
C/C++ Source or Header  |  1996-09-28  |  16KB  |  775 lines

  1. // NPSOL.cc                                                -*- C++ -*-
  2. /*
  3.  
  4. Copyright (C) 1992, 1993, 1994, 1995 John W. Eaton
  5.  
  6. This file is part of Octave.
  7.  
  8. Octave is free software; you can redistribute it and/or modify it
  9. under the terms of the GNU General Public License as published by the
  10. Free Software Foundation; either version 2, or (at your option) any
  11. later version.
  12.  
  13. Octave is distributed in the hope that it will be useful, but WITHOUT
  14. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16. for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with Octave; see the file COPYING.  If not, write to the Free
  20. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22. */
  23.  
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #endif
  27.  
  28. #include <math.h>
  29. #include <float.h>
  30. #include <string.h>
  31. #include <strstream.h>
  32.  
  33. #ifndef NPSOL_MISSING
  34.  
  35. #include "dMatrix.h"
  36.  
  37. #include "NPSOL.h"
  38. #include "f77-uscore.h"
  39. #include "sun-utils.h"
  40.  
  41. extern "C"
  42. {
  43.   int F77_FCN (npoptn) (char *, long);
  44.  
  45.   int F77_FCN (npsol) (int *, int *, int *, int *, int *, int *,
  46.                double *, double *, double *,
  47.                int (*)(int*, int*, int*, int*, int*, double*,
  48.                    double*, double*, int*),
  49.                int (*)(int*, int*, double*, double*, double*, int*),
  50.                int *, int *, int *, double *,
  51.                double *, double *, double *, double *,
  52.                double *, double *, int *, int *, double *,
  53.                int *);
  54. }
  55.  
  56. // XXX FIXME XXX -- would be nice to not have to have this global
  57. // variable.
  58. // Nonzero means an error occurred in the calculation of the objective
  59. // function, and the user wants us to quit.
  60. int npsol_objective_error = 0;
  61.  
  62. static objective_fcn user_phi;
  63. static gradient_fcn user_grad;
  64. static nonlinear_fcn user_g;
  65. static jacobian_fcn user_jac;
  66.  
  67. int
  68. npsol_objfun (int *mode, int *n, double *xx, double *objf,
  69.           double *objgrd, int *nstate)
  70. {
  71.   int nn = *n;
  72.   Vector tmp_x (nn);
  73.  
  74.   npsol_objective_error = 0;
  75.  
  76.   for (int i = 0; i < nn; i++)
  77.     tmp_x.elem (i) = xx[i];
  78.  
  79.   if (*mode == 0 || *mode == 2)
  80.     {
  81.       double value = (*user_phi) (tmp_x);
  82.  
  83.       if (npsol_objective_error)
  84.     {
  85.       *mode = -1;
  86.       return 0;
  87.     }
  88.  
  89. #if defined (sun) && defined (__GNUC__)
  90.       assign_double (objf, value);
  91. #else
  92.       *objf = value;
  93. #endif
  94.     }
  95.  
  96.   if ((*mode == 1 || *mode == 2) && user_grad)
  97.     {
  98.       Vector tmp_grad (nn);
  99.  
  100.       tmp_grad = (*user_grad) (tmp_x);
  101.  
  102.       if (tmp_grad.length () == 0)
  103.     *mode = -1;
  104.       else
  105.     {
  106.       for (i = 0; i < nn; i++)
  107.         objgrd[i] = tmp_grad.elem (i);
  108.     }
  109.     }
  110.  
  111.   return 0;
  112. }
  113.  
  114. int
  115. npsol_confun (int *mode, int *ncnln, int *n, int *nrowj, int *needc,
  116.           double *xx, double *cons, double *cjac, int *nstate)
  117. {
  118.   int nn = *n, nncnln = *ncnln;
  119.   Vector tmp_x (nn);
  120.   Vector tmp_c (nncnln);
  121.  
  122.   for (int i = 0; i < nn; i++)
  123.     tmp_x.elem (i) = xx[i];
  124.  
  125.   tmp_c = (*user_g) (tmp_x);
  126.  
  127.   if (tmp_c.length () == 0)
  128.     {
  129.       *mode = -1;
  130.       return 0;
  131.     }
  132.   else
  133.     {
  134.       for (i = 0; i < nncnln; i++)
  135.     cons[i] = tmp_c.elem (i);
  136.     }
  137.  
  138.   if (user_jac)
  139.     {
  140.       Matrix tmp_jac (nncnln, nn);
  141.  
  142.       tmp_jac = (*user_jac) (tmp_x);
  143.  
  144.       if (tmp_jac.rows () == 0 || tmp_jac.columns () == 0)
  145.     *mode = -1;
  146.       else
  147.     {
  148.       int ld = *nrowj;
  149.       for (int j = 0; j < nn; j++)
  150.         for (i = 0; i < nncnln; i++)
  151.           cjac[i+j*ld] = tmp_jac (i, j);
  152.     }
  153.     }
  154.  
  155.   return 0;
  156. }
  157.  
  158. Vector
  159. NPSOL::minimize (void)
  160. {
  161.   double objf;
  162.   int inform;
  163.   Vector lambda;
  164.   return minimize (objf, inform, lambda);
  165. }
  166.  
  167. Vector
  168. NPSOL::minimize (double& objf)
  169. {
  170.   int inform;
  171.   Vector lambda;
  172.   return minimize (objf, inform, lambda);
  173. }
  174.  
  175. Vector
  176. NPSOL::minimize (double& objf, int& inform)
  177. {
  178.   Vector lambda;
  179.   return minimize (objf, inform, lambda);
  180. }
  181.  
  182. Vector
  183. NPSOL::minimize (double& objf, int& inform, Vector& lambda)
  184. {
  185. // Dimensions of various things.
  186.  
  187.   int n     = x.capacity ();
  188.   int nclin = lc.size ();
  189.   int ncnln = nlc.size ();
  190.   int nrowa = 1 > nclin ? 1 : nclin;
  191.   int nrowj = 1 > ncnln ? 1 : ncnln;
  192.   int nrowr = n;
  193.  
  194. // Informative stuff.
  195.  
  196.   int iter;
  197.   int *istate = new int [n+nclin+ncnln];
  198.  
  199. // User defined function stuff is defined above in the functions
  200. // npsol_confun() and npsol_objfun();
  201.  
  202. // Constraint stuff.
  203.  
  204.   double dummy;
  205.   double *pclin = &dummy;
  206.   Matrix clin;
  207.   if (nclin > 0)
  208.     {
  209.       clin = lc.constraint_matrix ();
  210.       pclin  = clin.fortran_vec ();
  211.     }
  212.  
  213.   double *clow = new double [n+nclin+ncnln];
  214.   double *cup = new double [n+nclin+ncnln];
  215.  
  216.   if (bnds.size () > 0)
  217.     {
  218.       for (int i = 0; i < n; i++)
  219.     {
  220.       clow[i] = bnds.lower_bound (i);
  221.       cup[i] = bnds.upper_bound (i);
  222.     }
  223.     }
  224.   else
  225.     {
  226.       double huge = 1.0e30;
  227.       for (int i = 0; i < n; i++)
  228.     {
  229.       clow[i] = -huge;
  230.       cup[i] = huge;
  231.     }
  232.     }
  233.  
  234.   for (int i = 0; i < nclin; i++)
  235.     {
  236.       clow[i+n] = lc.lower_bound (i);
  237.       cup[i+n] = lc.upper_bound (i);
  238.     }
  239.  
  240.   for (i = 0; i < ncnln; i++)
  241.     {
  242.       clow[i+n+nclin] = nlc.lower_bound (i);
  243.       cup[i+n+nclin] = nlc.upper_bound (i);
  244.     }
  245.  
  246.   double *c = 0;
  247.   double *cjac = 0;
  248.   if (ncnln > 0)
  249.     {
  250.       c = new double [ncnln];
  251.       cjac = new double [nrowj*n];
  252.     }
  253.  
  254. // Objective stuff.
  255.  
  256.   double *objgrd = new double [n];
  257.  
  258. // Other stuff.
  259.  
  260.   double *r = new double [n*n];
  261.  
  262.   lambda.resize (n+nclin+ncnln);
  263.   double *pclambda = lambda.fortran_vec ();
  264.  
  265. // Decision variable stuff.
  266.  
  267.   double *px = x.fortran_vec ();
  268.  
  269. // Workspace parameters.
  270.  
  271.   int lenw;
  272.   int leniw = 3 * n + nclin + 2 * ncnln;
  273.   if (nclin == 0 && ncnln == 0)
  274.     lenw = 20*n;
  275.   else if (ncnln == 0)
  276.     lenw = 2*n*(10 + n) + 11*nclin;
  277.   else
  278.     lenw = 2*n*(n + 10) + nclin*(n + 11) + ncnln*(2*n + 21);
  279.  
  280.   int *iw = new int [leniw];
  281.   double *w = new double [lenw];
  282.  
  283.   user_phi  = phi.objective_function ();
  284.   user_grad = phi.gradient_function ();
  285.   user_g    = nlc.function ();
  286.   user_jac  = nlc.jacobian_function ();
  287.  
  288.   pass_options_to_npsol ();
  289.  
  290.   if (! user_jac && ! user_grad)
  291.     F77_FCN (npoptn) ("Derivative Level 0", 18L);
  292.   else if (! user_jac && user_grad)
  293.     F77_FCN (npoptn) ("Derivative Level 1", 18L);
  294.   else if (user_jac && ! user_grad)
  295.     F77_FCN (npoptn) ("Derivative Level 2", 18L);
  296.   else if (user_jac && user_grad)
  297.     F77_FCN (npoptn) ("Derivative Level 3", 18L);
  298.  
  299.   int attempt = 0;
  300.   while (attempt++ < 5)
  301.     {
  302.  
  303.       F77_FCN (npsol) (&n, &nclin, &ncnln, &nrowa, &nrowj, &nrowr, pclin,
  304.                clow, cup, npsol_confun, npsol_objfun, &inform,
  305.                &iter, istate, c, cjac, pclambda, &objf, objgrd, r,
  306.                px, iw, &leniw, w, &lenw);
  307.  
  308.       if (inform == 6 || inform == 1)
  309.     continue;
  310.       else
  311.     break;
  312.     }
  313.  
  314. // Clean up.
  315.  
  316.   delete [] istate;
  317.   delete [] clow;
  318.   delete [] cup;
  319.   delete [] c;
  320.   delete [] cjac;
  321.   delete [] objgrd;
  322.   delete [] r;
  323.   delete [] iw;
  324.   delete [] w;
  325.  
  326. // See how it went.
  327.  
  328.   return x;
  329. }
  330.  
  331. Vector
  332. NPSOL::minimize (const Vector& xnew)
  333. {
  334.   x = xnew;
  335.   return minimize ();
  336. }
  337.  
  338. Vector
  339. NPSOL::minimize (const Vector& xnew, double& objf)
  340. {
  341.   x = xnew;
  342.   return minimize (objf);
  343. }
  344.  
  345. Vector
  346. NPSOL::minimize (const Vector& xnew, double& objf, int& inform)
  347. {
  348.   x = xnew;
  349.   return minimize (objf, inform);
  350. }
  351.  
  352. Vector
  353. NPSOL::minimize (const Vector& xnew, double& objf, int& inform, Vector& lambda)
  354. {
  355.   x = xnew;
  356.   return minimize (objf, inform, lambda);
  357. }
  358.  
  359. NPSOL&
  360. NPSOL::option (char *s)
  361. {
  362.   cerr << "This function no longer has any effect.\n"
  363.        << "Use the NPSOL_option class instead\n";
  364.  
  365.   return *this;
  366. }
  367.  
  368. NPSOL_options::NPSOL_options (void)
  369. {
  370.   init ();
  371. }
  372.  
  373. NPSOL_options::NPSOL_options (const NPSOL_options& opt)
  374. {
  375.   copy (opt);
  376. }
  377.  
  378. NPSOL_options&
  379. NPSOL_options::operator = (const NPSOL_options& opt)
  380. {
  381.   if (this != &opt)
  382.     copy (opt);
  383.  
  384.   return *this;
  385. }
  386.  
  387. NPSOL_options::~NPSOL_options (void)
  388. {
  389. }
  390.  
  391. void
  392. NPSOL_options::init (void)
  393. {
  394.   x_central_difference_interval = -1.0;
  395.   x_crash_tolerance = 0.1;
  396.   x_difference_interval = -1.0;
  397.   x_function_precision = pow (DBL_EPSILON, 0.9);
  398.   x_infinite_bound = 1.0e+30;
  399.   x_infinite_step = 1.0e+30;
  400.   x_linear_feasibility_tolerance = sqrt (DBL_EPSILON);
  401.   x_linesearch_tolerance = 0.9;
  402.   x_nonlinear_feasibility_tolerance = sqrt (DBL_EPSILON);
  403.   x_optimality_tolerance = pow (DBL_EPSILON, 0.8);
  404.   x_derivative_level = 0;
  405.   x_major_iteration_limit = -1;
  406.   x_minor_iteration_limit = -1;
  407.   x_major_print_level = 0;
  408.   x_minor_print_level = 0;
  409.   x_start_objective_check = 1;
  410.   x_start_constraint_check = 1;
  411.   x_stop_objective_check = -1;
  412.   x_stop_constraint_check = -1;
  413.   x_verify_level = 0;
  414. }
  415.  
  416. void
  417. NPSOL_options::copy (const NPSOL_options& opt)
  418. {
  419.   x_central_difference_interval = opt.x_central_difference_interval;
  420.   x_crash_tolerance = opt.x_crash_tolerance;
  421.   x_difference_interval = opt.x_difference_interval;
  422.   x_function_precision = opt.x_function_precision;
  423.   x_infinite_bound = opt.x_infinite_bound;
  424.   x_infinite_step = opt.x_infinite_step;
  425.   x_linear_feasibility_tolerance = opt.x_linear_feasibility_tolerance;
  426.   x_linesearch_tolerance = opt.x_linesearch_tolerance;
  427.   x_nonlinear_feasibility_tolerance = opt.x_nonlinear_feasibility_tolerance;
  428.   x_optimality_tolerance = opt.x_optimality_tolerance;
  429.   x_derivative_level = opt.x_derivative_level;
  430.   x_major_iteration_limit = opt.x_major_iteration_limit;
  431.   x_minor_iteration_limit = opt.x_minor_iteration_limit;
  432.   x_major_print_level = opt.x_major_print_level;
  433.   x_minor_print_level = opt.x_minor_print_level;
  434.   x_start_objective_check = opt.x_start_objective_check;
  435.   x_start_constraint_check = opt.x_start_constraint_check;
  436.   x_stop_objective_check = opt.x_stop_objective_check;
  437.   x_stop_constraint_check = opt.x_stop_constraint_check;
  438.   x_verify_level = opt.x_verify_level;
  439. }
  440.  
  441. void
  442. NPSOL_options::set_default_options (void)
  443. {
  444.   init ();
  445. }
  446.  
  447. /*
  448.  * Passing invalid values to the set_* functions will result in
  449.  * setting the default option.
  450.  */
  451.  
  452. void
  453. NPSOL_options::set_central_difference_interval (double val)
  454. {
  455.   x_central_difference_interval = (val > 0.0) ? val : -1.0;
  456. }
  457.  
  458. void
  459. NPSOL_options::set_crash_tolerance (double val)
  460. {
  461.   x_crash_tolerance = (val >= 0.0) ? val : 0.1;
  462. }
  463.  
  464. void
  465. NPSOL_options::set_difference_interval (double val)
  466. {
  467.   x_difference_interval = (val > 0.0) ? val : -1.0;
  468. }
  469.  
  470. void
  471. NPSOL_options::set_function_precision (double val)
  472. {
  473.   x_function_precision = (val > 0.0) ? val : pow (DBL_EPSILON, 0.9);
  474. }
  475.  
  476. void
  477. NPSOL_options::set_infinite_bound (double val)
  478. {
  479.   x_infinite_bound = (val > 0.0) ? val : 1.0e+30;
  480. }
  481.  
  482. void
  483. NPSOL_options::set_infinite_step (double val)
  484. {
  485.   x_infinite_step = (val > 0.0) ? val : 1.0e+30;
  486. }
  487.  
  488. void
  489. NPSOL_options::set_linear_feasibility_tolerance (double val)
  490. {
  491.   x_linear_feasibility_tolerance = (val > 0.0) ? val : sqrt (DBL_EPSILON);
  492. }
  493.  
  494. void
  495. NPSOL_options::set_linesearch_tolerance (double val)
  496. {
  497.   x_linesearch_tolerance = (val >= 0.0 && val < 1.0) ? val : 0.9;
  498. }
  499.  
  500. void
  501. NPSOL_options::set_nonlinear_feasibility_tolerance (double val)
  502. {
  503.   x_nonlinear_feasibility_tolerance = (val > 0.0) ? val : sqrt (DBL_EPSILON);
  504. }
  505.  
  506. void
  507. NPSOL_options::set_optimality_tolerance (double val)
  508. {
  509.   x_optimality_tolerance = (val > 0.0) ? val : pow (DBL_EPSILON, 0.8);
  510. }
  511.  
  512. void
  513. NPSOL_options::set_derivative_level (int val)
  514. {
  515.   x_derivative_level = (val >= 0 && val < 4) ? val : 0;
  516. }
  517.  
  518. void
  519. NPSOL_options::set_major_iteration_limit (int val)
  520. {
  521.   x_major_iteration_limit = (val > 0) ? val : -1;
  522. }
  523.  
  524. void
  525. NPSOL_options::set_minor_iteration_limit (int val)
  526. {
  527.   x_minor_iteration_limit = (val > 0) ? val : -1;
  528. }
  529.  
  530. void
  531. NPSOL_options::set_major_print_level (int val)
  532. {
  533.   x_major_print_level = (val >= 0) ? val : -1;
  534. }
  535.  
  536. void
  537. NPSOL_options::set_minor_print_level (int val)
  538. {
  539.   x_minor_print_level = (val >= 0) ? val : -1;
  540. }
  541.  
  542. void
  543. NPSOL_options::set_start_objective_check (int val)
  544. {
  545.   x_start_objective_check = (val >= 0) ? val : -1;
  546. }
  547.  
  548. void
  549. NPSOL_options::set_start_constraint_check (int val)
  550. {
  551.   x_start_constraint_check = (val >= 0) ? val : -1;
  552. }
  553.  
  554. void
  555. NPSOL_options::set_stop_objective_check (int val)
  556. {
  557.   x_stop_objective_check = (val >= 0) ? val : -1;
  558. }
  559.  
  560. void
  561. NPSOL_options::set_stop_constraint_check (int val)
  562. {
  563.   x_stop_constraint_check = (val >= 0) ? val : -1;
  564. }
  565.  
  566. void
  567. NPSOL_options::set_verify_level (int val)
  568. {
  569.   x_verify_level = ((val > -1 && val < 4) || (val > 9 && val < 14)) ? val : 0;
  570. }
  571.  
  572. double
  573. NPSOL_options::central_difference_interval (void) const
  574. {
  575.   return x_central_difference_interval;
  576. }
  577.  
  578. double
  579. NPSOL_options::crash_tolerance (void) const
  580. {
  581.   return x_crash_tolerance;
  582. }
  583.  
  584. double
  585. NPSOL_options::difference_interval (void) const
  586. {
  587.   return x_difference_interval;
  588. }
  589.  
  590. double
  591. NPSOL_options::function_precision (void) const
  592. {
  593.   return x_function_precision;
  594. }
  595.  
  596. double
  597. NPSOL_options::infinite_bound (void) const
  598. {
  599.   return x_infinite_bound;
  600. }
  601.  
  602. double
  603. NPSOL_options::infinite_step (void) const
  604. {
  605.   return x_infinite_step;
  606. }
  607.  
  608. double
  609. NPSOL_options::linear_feasibility_tolerance (void) const
  610. {
  611.   return x_linear_feasibility_tolerance;
  612. }
  613.  
  614. double
  615. NPSOL_options::linesearch_tolerance (void) const
  616. {
  617.   return x_linesearch_tolerance;
  618. }
  619.  
  620. double
  621. NPSOL_options::nonlinear_feasibility_tolerance (void) const
  622. {
  623.   return x_nonlinear_feasibility_tolerance;
  624. }
  625.  
  626. double
  627. NPSOL_options::optimality_tolerance (void) const
  628. {
  629.   return x_optimality_tolerance;
  630. }
  631.  
  632. int
  633. NPSOL_options::derivative_level (void) const
  634. {
  635.   return x_derivative_level;
  636. }
  637.  
  638. int
  639. NPSOL_options::major_iteration_limit (void) const
  640. {
  641.   return x_major_iteration_limit;
  642. }
  643.  
  644. int
  645. NPSOL_options::minor_iteration_limit (void) const
  646. {
  647.   return x_minor_iteration_limit;
  648. }
  649.  
  650. int
  651. NPSOL_options::major_print_level (void) const
  652. {
  653.   return x_major_print_level;
  654. }
  655.  
  656. int
  657. NPSOL_options::minor_print_level (void) const
  658. {
  659.   return x_minor_print_level;
  660. }
  661.  
  662. int
  663. NPSOL_options::start_objective_check (void) const
  664. {
  665.   return x_start_objective_check;
  666. }
  667.  
  668. int
  669. NPSOL_options::start_constraint_check (void) const
  670. {
  671.   return x_start_constraint_check;
  672. }
  673.  
  674. int
  675. NPSOL_options::stop_objective_check (void) const
  676. {
  677.   return x_stop_objective_check;
  678. }
  679.  
  680. int
  681. NPSOL_options::stop_constraint_check (void) const
  682. {
  683.   return x_stop_constraint_check;
  684. }
  685.  
  686. int
  687. NPSOL_options::verify_level (void) const
  688. {
  689.   return x_verify_level;
  690. }
  691.  
  692. void
  693. NPSOL_options::pass_options_to_npsol (void)
  694. {
  695.   F77_FCN (npoptn) ("Nolist", 6L);
  696.   F77_FCN (npoptn) ("Defaults", 8L);
  697.  
  698.   if (x_central_difference_interval > 0.0)
  699.     set_option ("Central Difference", x_central_difference_interval);
  700.  
  701.   set_option ("Crash Tolerance", x_crash_tolerance);
  702.  
  703.   if (x_difference_interval > 0.0)
  704.     set_option ("Difference Interval", x_difference_interval);
  705.  
  706.   set_option ("Function Precision", x_function_precision);
  707.  
  708.   set_option ("Infinite Bound", x_infinite_bound);
  709.  
  710.   set_option ("Infinite Step", x_infinite_step);
  711.  
  712.   set_option ("Linear Feasibility", x_linear_feasibility_tolerance);
  713.  
  714.   set_option ("Linesearch Tolerance", x_linesearch_tolerance);
  715.  
  716.   set_option ("Nonlinear Feasibility", x_nonlinear_feasibility_tolerance);
  717.  
  718.   set_option ("Optimality Tolerance", x_optimality_tolerance);
  719.  
  720.   set_option ("Derivative Level", x_derivative_level);
  721.  
  722.   if (x_major_iteration_limit > 0)
  723.     set_option ("Major Iteration", x_major_iteration_limit);
  724.  
  725.   if (x_minor_iteration_limit > 0)
  726.     set_option ("Minor Iteration", x_minor_iteration_limit);
  727.  
  728.   set_option ("Major Print", x_major_print_level);
  729.  
  730.   set_option ("Minor Print", x_minor_print_level);
  731.  
  732.   set_option ("Start Objective", x_start_objective_check);
  733.  
  734.   set_option ("Start Constraint", x_start_constraint_check);
  735.  
  736.   if (x_stop_objective_check > 0)
  737.     set_option ("Stop Objective", x_stop_objective_check);
  738.  
  739.   if (x_stop_constraint_check > 0)
  740.     set_option ("Stop Constraint", x_stop_constraint_check);
  741.  
  742.   set_option ("Verify Level", x_verify_level);
  743. }
  744.  
  745. void
  746. NPSOL_options::set_option (const char *key, int opt)
  747. {
  748.   ostrstream buf;
  749.   buf << key << " " << opt << ends;
  750.   char *command = buf.str ();
  751.   size_t len = strlen (command);
  752.   F77_FCN (npoptn) (command, (long) len);
  753.   delete [] command;
  754. }
  755.  
  756. void
  757. NPSOL_options::set_option (const char *key, double opt)
  758. {
  759.   ostrstream buf;
  760.   buf << key << " " << opt << ends;
  761.   char *command = buf.str ();
  762.   size_t len = strlen (command);
  763.   F77_FCN (npoptn) (command, (long) len);
  764.   delete [] command;
  765. }
  766.  
  767. #endif /* NPSOL_MISSING */
  768.  
  769. /*
  770. ;;; Local Variables: ***
  771. ;;; mode: C++ ***
  772. ;;; page-delimiter: "^/\\*" ***
  773. ;;; End: ***
  774. */
  775.