/* curve.c ********************************************************************************
* curve.c -- Routines for curve function objects
*
* User routines
* Pro_CurveValue() returns the value and slope of a curve.
* Pro_CurveInverse() evaluates the inverse value of a curve.
* Pro_CurveSegments() returns the number of "segments" (i.e. monotonic
* subregions) within the domain of a curve.
* Pro_CurveExtremum() returns the extreme value at a boundary between
* segments.
*
* Programmer routines
* XPro_MakeCurve() used to create a new curve object.
* XPro_CurvePtr() returns a pointer to the sub-object.
*
* Version 1.0: Original release.
* Mark Showalter, PDS Ring-Moon Systems Node, March 1998.
* Version 1.1: QUICK compilation mode added.
* Mark Showalter, October 1999.
*******************************************************************************/
#include <stdio.h>
#include "profile.h"
#include "fortran.h"
/********************
* Type definitions *
********************/
typedef struct ZPRO_CURVE_STRUCT {
XPRO_CLASS class;
RL_INT4 nsegments;
struct ZPRO_SEGMENT_STRUCT {RL_FLT8 x, y; RL_INT4 type;}
*segments;
RL_FLT8 (*evalfunc) RL_PROTO((RL_VOID *pointer, RL_FLT8 x,
RL_FLT8 *slope));
RL_FLT8 (*invfunc) RL_PROTO((RL_VOID *pointer, RL_FLT8 y,
RL_FLT8 x1, RL_FLT8 x2));
void (*freefunc) RL_PROTO((RL_VOID *pointer));
void (*printfunc) RL_PROTO((RL_VOID *pointer));
} ZPRO_CURVE;
typedef struct ZPRO_SEGMENT_STRUCT ZPRO_SEGMENT;
/********************
* Static variables *
********************/
static RL_INT4 seg1, seg2; /* Values retained from most recent call to
Pro_CurveSegments(). They can then be used
by Pro_CurveExtremum() */
static XPRO_CLASS curve_class = {XPRO_CURVE_CLASS, "curve", NULL};
/********************************
* Internal function prototypes *
********************************/
static RL_FLT8 ZPro_CurveValue RL_PROTO((RL_VOID *pointer, RL_FLT8 x));
static RL_FLT8 ZPro_CurveSlope RL_PROTO((RL_VOID *pointer, RL_FLT8 x));
static void ZPro_FreeCurve RL_PROTO((RL_VOID *pointer));
static void ZPro_PrintCurve RL_PROTO((RL_VOID *pointer));
static void ZPro_PrintSlope RL_PROTO((RL_VOID *pointer));
static ZPRO_CURVE *ZPro_GetCurve RL_PROTO((PRO_OBJECT *object));
/**********
* Macros *
**********/
#define ISIGN(x) ((x) < 0. ? -1 : ((x) == 0. ? 0 : 1))
#ifdef QUICK
#define ZPro_GetCurve(object) ((ZPRO_CURVE *) XPro_SeriesPtr(object))
#endif
/*
********************************************************************************
* EXPORTED USER ROUTINES
********************************************************************************
*$ Component_name:
* Pro_CurveValue (curve.c)
*$ Abstract:
* This routine returns the value and slope of a curve at a given location.
*$ Keywords:
* PROFILE, FUNCTION, CURVE
* C, PUBLIC, SUBROUTINE
*$ Declarations:
* RL_FLT8 Pro_CurveValue(object, x, slope)
* PRO_OBJECT *object;
* RL_FLT8 x, *slope;
*$ Inputs:
* object pointer to the curve object.
* x location at which to evaluate curve.
*$ Outputs:
* *slope slope of curve at x; not returned if slope==NULL.
* Zero is returned on non-fatal error.
*$ Returns:
* value of curve at argument. Zero is returned on a non-fatal class
* error; the value at the nearest endpoint of the domain is returned on a
* non-fatal domain error.
*$ Detailed_description:
* This routine returns the value and (optionally) slope of a curve at a
* given location. A curve object extends the properties of a function
* object in that it has a continuous, calculable slope.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* Suppose square is a curve that returns x squared between -3. and 3.
*
* Then Pro_CurveValue(square, 3., &dydx) returns 9. and sets dydx to 6.
*$ Error_handling:
* Profile library error handling is in effect.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or is not a curve.
* PRO_DOMAIN_ERROR if x-value is outside the curve's domain.
* PRO_EVALUATION_FAILURE if curve could not be evaluated.
*
* On a non-fatal PRO_DOMAIN_ERROR the value at the nearest endpoint is
* returned; on other non-fatal errors, 0. is returned. In any case, the
* value of the slope returned is zero.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
* 1.1: October 1999
*$ Change_history:
* 1.1: QUICK mode compile option added.
*******************************************************************************/
RL_FLT8 Pro_CurveValue(object, x, slope)
PRO_OBJECT *object;
RL_FLT8 x, *slope;
{
ZPRO_CURVE *curve;
RL_FLT8 value, x1, x2;
curve = ZPro_GetCurve(object);
#ifndef QUICK
if (curve == NULL) {
if (slope != NULL) *slope = 0.;
return 0.;
}
#endif
/* Make sure x is inside domain */
#ifdef QUICK
x1 = object->x1;
x2 = object->x2;
#else
(void) Pro_ObjectDomain(object, &x1, &x2);
#endif
if (x < x1 || x > x2) {
XPro_DomainError("x value", object, x1, x2, x);
/* Evaluate function at nearest endpoint */
if (x < x1) value = (curve->evalfunc)(curve->class.pointer, x1, NULL);
else value = (curve->evalfunc)(curve->class.pointer, x2, NULL);
/* Set slope to zero since value is constant outside domain */
if (slope != NULL) *slope = 0.;
return value;
}
/* Return value of function */
return (curve->evalfunc)(curve->class.pointer, x, slope);
}
/*
********************************************************************************
*$ Component_name:
* Pro_CurveInverse (curve.c)
*$ Abstract:
* This routine returns the inverse of the given curve.
*$ Keywords:
* PROFILE, FUNCTION, CURVE
* C, PUBLIC, SUBROUTINE
*$ Declarations:
* RL_FLT8 Pro_CurveInverse(object, segment, y)
* PRO_OBJECT *object;
* RL_INT4 segment;
* RL_FLT8 y;
*$ Inputs:
* object pointer to the curve object.
* segment segment number in which to search. A segment is a
* monotonic section of a curve, numbered starting at 1.
* y value of curve sought.
*$ Outputs:
* none
*$ Returns:
* location within the segment where the curve equals the given y-value.
* An error is raised if the curve cannot be inverted; if this condition is
* non-fatal, the x-value at the endpoint with the closest y-value is
* returned.
*$ Detailed_description:
* This routine returns the inverse of the given curve, i.e. the location
* within the segment where the curve equals the given y-value.
*
* Inverses are calculated within a specified segment, which is a monotonic
* section of a curve. Segments are separated by extrema and points of
* inflection, where segment #1 runs from the lower endpoint to the first
* extremum/inflection point, or to the upper endpoint if that comes first.
*
* An error is raised if the curve cannot be inverted; if this condition
* is non-fatal, the x-value at the endpoint of the segment with the
* closest y-value is returned.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* Suppose square is a curve that returns x squared between -3. and 3.
*
* Then Pro_CurveInverse(square, 1, 2.25) returns -1.5;
* Pro_CurveInverse(square, 2, 2.25) returns 1.5;
*$ Error_handling:Pro_CurveInverse(square, 1, 2.25) returns -1.5;
* Profile library error handling is in effect.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or is not a curve.
* PRO_DOMAIN_ERROR if the segment index is out of range for the
* curve.
* PRO_EVALUATION_FAILURE if curve could not be inverted.
*
* For a non-fatal PRO_CLASS_ERROR, zero is returned; for a non-fatal
* PRO_DOMAIN_ERROR or PRO_EVALUATION_FAILURE, the x-value at the nearest
* segment endpoint is returned.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
* 1.1: October 1999
*$ Change_history:
* 1.1: QUICK mode compile option added.
*******************************************************************************/
RL_FLT8 Pro_CurveInverse(object, segment, y)
PRO_OBJECT *object;
RL_INT4 segment;
RL_FLT8 y;
{
ZPRO_CURVE *curve;
RL_FLT8 x1, x2, value;
RL_INT4 nsegments;
curve = ZPro_GetCurve(object);
#ifndef QUICK
if (curve == NULL) return 0.;
#endif
x1 = Pro_CurveExtremum(object, segment-1, NULL, NULL);
x2 = Pro_CurveExtremum(object, segment, NULL, NULL);
value = (curve->invfunc)(curve->class.pointer, y, x1, x2);
return value;
}
/*
********************************************************************************
*$ Component_name:
* Pro_CurveSegments (curve.c)
*$ Abstract:
* This function returns the number of segments in the curve domain. A
* segment is the region from one endpoint, extremum, or inflection point
* to the next.
*$ Keywords:
* PROFILE, FUNCTION, CURVE
* C, PUBLIC, SUBROUTINE
*$ Declarations:
* RL_INT4 Pro_CurveSegments(object)
* PRO_OBJECT *object;
*$ Inputs:
* object pointer to the curve object.
*$ Outputs:
* none
*$ Returns:
* number of segments, or 0 on error.
*$ Detailed_description:
* This function returns the number of segments in the curve domain. A
* segment is the region from one endpoint, extremum, or inflection point
* to the next.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* Suppose square is a curve that returns x squared between -3. and 3.
*
* Then Pro_CurveSegments(square) returns 2.
*$ Error_handling:
* Profile library error handling is in effect. On non-fatal error, the
* routine returns 0.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or is not a curve.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
*******************************************************************************/
RL_INT4 Pro_CurveSegments(object)
PRO_OBJECT *object;
{
ZPRO_CURVE *curve;
RL_INT4 segments;
RL_FLT8 x1, x2;
curve = ZPro_GetCurve(object);
if (curve == NULL) return 0;
/* Find segments where domain limits fall (and save as static variables)
This is needed in case the curve has been windowed */
Pro_ObjectDomain(object, &x1, &x2);
for (seg1 = 1; seg1 <= curve->nsegments; seg1++)
if (x1 < curve->segments[seg1].x) break;
seg1--;
for (seg2 = curve->nsegments-1; seg2 > seg1; seg2--)
if (x2 > curve->segments[seg2].x) break;
seg2++;
/* Calculate difference */
segments = seg2 - seg1;
return segments;
}
/*
********************************************************************************
*$ Component_name:
* Pro_CurveExtremum (curve.c)
*$ Abstract:
* This routine returns the location of the given extremum, inflection
* point or domain endpoint.
*$ Keywords:
* PROFILE, FUNCTION, CURVE
* C, PUBLIC, SUBROUTINE
*$ Declarations:
* RL_FLT8 Pro_CurveExtremum(object, segment, value, type)
* PRO_OBJECT *object;
* RL_INT4 segment, *type;
* RL_FLT8 *value;
*$ Inputs:
* object pointer to the curve object.
* segment segment number (0 to number of segments).
*$ Outputs:
* *value value of the curve at this location. Not returned if
* value == NULL.
* *type +1 if extremum is a local maximum; -1 if extremum is a
* local minimum; 0 if extremum is an inflection point.
* Not returned if type == NULL.
*$ Returns:
* location of extremum, or 0. on error.
*$ Detailed_description:
* This routine returns the location of the given extremum, inflection
* point or domain endpoint.
*
* Points are identified by 0 through N, where N is the number of segments
* in the curve. Here 0 and N refers to the lower and upper limits of the
* domain, and 1 to N-1 refer to the local extrema and inflection points in
* between. Hence, segment #n is bounded by points #n-1 and #n.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* Suppose square is a curve that returns x squared between -3. and 3.
*
* Then Pro_CurveExtremum(square, 0, &value, &type) returns -3., sets value
* to 9. and sets type to +1 (maximum);
* Pro_CurveExtremum(square, 1, &value, &type) returns 0., sets value
* to 0. and sets type to -1 (minimum);
* Pro_CurveExtremum(square, 2, &value, &type) returns 3., sets value
* to 9. and sets type to +1 (maximum).
*$ Error_handling:
* Profile library error handling is in effect. On non-fatal error, the
* routine returns 0.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or is not a curve.
* PRO_DOMAIN_ERROR if the segment index is out of range for the
* curve; in this case properties of the nearest
* domain endpoint are returned.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
*******************************************************************************/
RL_FLT8 Pro_CurveExtremum(object, segment, value, type)
PRO_OBJECT *object;
RL_INT4 segment, *type;
RL_FLT8 *value;
{
ZPRO_CURVE *curve;
RL_INT4 nsegments;
RL_FLT8 x1, x2, y;
curve = ZPro_GetCurve(object);
if (curve == NULL) return 0.;
/* Note that this call also defines static variables seg1 and seg2 */
nsegments = Pro_CurveSegments(object);
/* Check segment index */
if (segment < 0 || segment > nsegments) {
XPro_IDomainError("extremum index", object, 0, nsegments, segment);
}
/* Handle domain boundary segments */
if (segment <= 0) {
Pro_ObjectDomain(object, &x1, &x2);
y = Pro_CurveValue(object, x1, NULL);
if (value != NULL) *value = y;
if (type != NULL) *type = ISIGN(y - curve->segments[seg1+1].y);
return x1;
}
if (segment >= nsegments) {
Pro_ObjectDomain(object, &x1, &x2);
y = Pro_CurveValue(object, x2, NULL);
if (value != NULL) *value = y;
if (type != NULL) *type = ISIGN(y - curve->segments[seg2-1].y);
return x2;
}
/* Adjust segment index in case function has been windowed */
segment += seg1;
if (value != NULL) *value = curve->segments[segment].y;
if (type != NULL) *type = curve->segments[segment].type;
return curve->segments[segment].x;
}
/*
********************************************************************************
* PROGRAMMER ROUTINES
********************************************************************************
* XPro_MakeCurve(x1, x2, nextrema, xextrema, evalfunc, invfunc, freefunc,
* printfunc, pointer)
*
* This routine creates and initializes a curve object.
*
* Inputs:
* x1, x2 domain limits.
* nextrema number of extrema in array xextrema[]. This list must
* contain every extremum or inflection point at least
* within the domain, in increasing order.
* xextrema locations of extrema.
* evalfunc routine to evaluate function.
* invfunc routine to evaluate inverse of function.
* freefunc routine to free data structure.
* printfunc routine to print curve information.
* pointer pointer to an arbitrary data structure describing the
* curve.
*
* Returns: new curve object, or NULL on error.
*
* Errors:
* RL_MEMORY_ERROR on memory allocation failure.
*******************************************************************************/
PRO_OBJECT *XPro_MakeCurve(x1, x2, nextrema, xextrema,
evalfunc, invfunc, freefunc, printfunc, pointer)
RL_FLT8 x1, x2, *xextrema;
RL_INT4 nextrema;
RL_FLT8 (*evalfunc) RL_PROTO((RL_VOID *pointer, RL_FLT8 x,
RL_FLT8 *slope));
RL_FLT8 (*invfunc) RL_PROTO((RL_VOID *pointer, RL_FLT8 y,
RL_FLT8 x1, RL_FLT8 x2));
void (*freefunc) RL_PROTO((RL_VOID *pointer));
void (*printfunc) RL_PROTO((RL_VOID *pointer));
RL_VOID *pointer;
{
ZPRO_CURVE *curve;
ZPRO_SEGMENT *segs;
RL_INT4 i, j, type1, type2;
PRO_OBJECT *new;
/* Allocate new curve object from memory */
curve = (ZPRO_CURVE *) XRL_Malloc(sizeof(ZPRO_CURVE));
if (curve == NULL) return NULL;
curve->segments = (ZPRO_SEGMENT *)
XRL_Malloc((nextrema+2) * sizeof(ZPRO_SEGMENT));
if (curve->segments == NULL) {
XRL_Free((RL_VOID *) curve);
return NULL;
}
/* Fill in fields */
curve->class = curve_class;
curve->class.pointer = pointer;
curve->evalfunc = evalfunc;
curve->invfunc = invfunc;
curve->freefunc = freefunc;
curve->printfunc = printfunc;
/* Copy table of extreme x-values into segment structure */
segs = curve->segments;
for (i=0; i<nextrema; i++) {
if (xextrema[i] > x1) break;
}
for (j=1; i<nextrema; i++, j++) {
if (xextrema[i] >= x2) break;
segs[j].x = xextrema[i];
}
segs[0].x = x1;
segs[j].x = x2;
curve->nsegments = j;
/* Fill in y-values */
for (j=0; j <= curve->nsegments; j++) {
segs[j].y = (*evalfunc)(pointer, segs[j].x, NULL);
}
/* Fill in extremum types */
for (j=1; j < curve->nsegments; j++) {
type1 = ISIGN(segs[j].y - segs[j-1].y);
type2 = ISIGN(segs[j].y - segs[j+1].y);
if (type1 == type2) segs[j].type = type1;
else segs[j].type = 0;
}
j = curve->nsegments;
segs[j].type = ISIGN(segs[j].y - segs[j-1].y);
segs[0].type = ISIGN(segs[0].y - segs[1].y);
/* Create new object */
new = XPro_MakeFunc(x1, x2,
ZPro_CurveValue, ZPro_FreeCurve, ZPro_PrintCurve,
(RL_VOID *) curve);
return new;
}
/*
********************************************************************************
* XPro_CurvePtr(object)
*
* This routine returns a pointer to the curve sub-object.
*
* Inputs:
* object curve object.
*
* Return: pointer field of the object; NULL on error.
*
* Errors:
* PRO_CLASS_ERROR if the object is NULL or not a curve.
****************************************************************************/
#ifndef QUICK /* In QUICK mode, this is defined as a macro in profile.h */
RL_VOID *XPro_CurvePtr(object)
PRO_OBJECT *object;
{
ZPRO_CURVE *curve;
curve = ZPro_GetCurve(object);
if (curve == NULL) return NULL;
if (curve->class.pointer == NULL)
XPro_NullError("curve sub-object", object);
return curve->class.pointer;
}
#endif
/*
********************************************************************************
* INTERNAL ROUTINES
********************************************************************************
* ZPro_CurveValue(pointer, x)
*
* This internal routine evaluates the curve. It serves as the standard
* "evalfunc" for the parent function object.
*
* Inputs:
* pointer pointer to the ZPRO_CURVE structure.
* x location at which to evaluate the curve.
*
* Returns: value of curve at x.
*******************************************************************************/
static RL_FLT8 ZPro_CurveValue(pointer, x)
RL_VOID *pointer;
RL_FLT8 x;
{
ZPRO_CURVE *curve;
RL_FLT8 value;
curve = (ZPRO_CURVE *) pointer;
value = (curve->evalfunc)(curve->class.pointer, x, NULL);
return value;
}
/*
********************************************************************************
* ZPro_FreeCurve(pointer)
*
* This internal routine deallocates the memory used by a curve object. It
* serves as the standard "freefunc" for the parent function object.
*
* Input:
* pointer pointer to the ZPRO_CURVE structure.
*******************************************************************************/
static void ZPro_FreeCurve(pointer)
RL_VOID *pointer;
{
ZPRO_CURVE *curve;
curve = (ZPRO_CURVE *) pointer;
(curve->freefunc)(curve->class.pointer);
XRL_Free(curve->segments);
XRL_Free(curve);
}
/*
********************************************************************************
* ZPro_PrintCurve(pointer)
*
* This internal routine prints information about a curve object. It serves as
* the standard "printfunc" for the parent function object.
*
* Input:
* pointer pointer to the ZPRO_CURVE structure.
*******************************************************************************/
static void ZPro_PrintCurve(pointer)
RL_VOID *pointer;
{
ZPRO_CURVE *curve;
RL_INT4 i;
RL_CHAR *type;
curve = (ZPRO_CURVE *) pointer;
/* Make sure object is not NULL */
if (curve == NULL) {
printf("PRINT ERROR: Curve pointer is NULL\n");
return;
}
/* Make sure object is a curve function */
if (curve->class.id != XPRO_CURVE_CLASS) {
printf("PRINT ERROR: Object is not a curve\n");
return;
}
/* Print object info... */
printf("\nCurve parameters...\n");
for (i = 0; i <= curve->nsegments; i++) {
if (curve->segments[i].type < 0) type = "minimum";
else if (curve->segments[i].type > 0) type = "maximum";
else type = "inflection";
printf("segment #%1d: (% #g, % #g) %s\n", i,
curve->segments[i].x, curve->segments[i].y, type);
}
(curve->printfunc)(curve->class.pointer);
return;
}
/*
********************************************************************************
* ZPro_GetCurve(object)
*
* This internal routine confirms that the given object is a curve and returns
* a pointer to the ZPRO_CURVE data structure.
*
* Input:
* object curve object.
*
* Errors:
* PRO_CLASS_ERROR if object is NULL or is not a curve.
*******************************************************************************/
#ifndef QUICK /* In QUICK mode, this is defined as a macro above */
static ZPRO_CURVE *ZPro_GetCurve(object)
PRO_OBJECT *object;
{
ZPRO_CURVE *curve;
/* Find curve object pointer */
curve = (ZPRO_CURVE *) XPro_FuncPtr(object);
if (curve == NULL) return NULL;
/* Make sure curve is not NULL */
if (curve == NULL) {
XPro_NullError("curve", object);
return NULL;
}
/* Make sure object is a curve */
if (curve->class.id != XPRO_CURVE_CLASS) {
XPro_ClassError("curve", object);
return NULL;
}
return curve;
}
#endif
/*
********************************************************************************
* FORTRAN INTERFACE ROUTINES
********************************************************************************
*$ Component_name:
* FPro_CurveValue (curve.c)
*$ Abstract:
* This routine returns the value and slope of a curve at a given location.
*$ Keywords:
* PROFILE, FUNCTION, CURVE
* FORTRAN, PUBLIC, SUBROUTINE
*$ Declarations:
* real*8 function FPro_CurveValue(object, x, slope)
* integer*4 object
* real*8 x, slope
*$ Inputs:
* object FORTRAN pointer to the curve object.
* x location at which to evaluate curve.
*$ Outputs:
* slope slope of curve at x. Zero is returned on a non-fatal
* error.
*$ Returns:
* value of curve at argument. Zero is returned on a non-fatal class
* error; the value at the nearest endpoint of the domain is returned on a
* non-fatal domain error.
*$ Detailed_description:
* This routine returns the value and (optionally) slope of a curve at a
* given location. A curve object extends the properties of a function
* object in that it has a continuous, calculable slope.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* Suppose square is a curve that returns x squared between -3.d0 and 3.d0.
*
* Then FPro_CurveValue(square, 3.d0, dydx) returns 9.d0 and sets dydx to
* 6.d0.
*$ Error_handling:
* Profile library error handling is in effect.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or is not a curve.
* PRO_DOMAIN_ERROR if x-value is outside the curve's domain.
* PRO_EVALUATION_FAILURE if curve could not be evaluated.
* FORTRAN_POINTER_ERROR if object is not a valid FORTRAN object pointer.
*
* On a non-fatal PRO_DOMAIN_ERROR the value at the nearest endpoint is
* returned; on other non-fatal errors, 0. is returned. In any case, the
* value of the slope returned is zero.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
* 1.1: October 1999
*$ Change_history:
* 1.1: QUICK mode compile option added.
*******************************************************************************/
RL_FLT8 FORTRAN_NAME(fpro_curvevalue) (object, x, slope)
RL_INT4 *object;
RL_FLT8 *x, *slope;
{
RL_VOID *ptr;
/* Look up object pointer */
ptr = FORT_GetPointer(*object);
#ifndef QUICK
if (ptr == NULL) return 0.;
#endif
/* Call function */
return Pro_CurveValue((PRO_OBJECT *) ptr, *x, slope);
}
/*
********************************************************************************
*$ Component_name:
* FPro_CurveInverse (curve.c)
*$ Abstract:
* This routine returns the inverse of the given curve.
*$ Keywords:
* PROFILE, FUNCTION, CURVE
* FORTRAN, PUBLIC, SUBROUTINE
*$ Declarations:
* real*8 function FPro_CurveInverse(object, segment, y)
* integer*4 object, segment
* real*8 y
*$ Inputs:
* object FORTRAN pointer to the curve object.
* segment segment number in which to search. A segment is a
* monotonic section of a curve, numbered starting at 1.
* y value of curve sought.
*$ Outputs:
* none
*$ Returns:
* location within the segment where the curve equals the given y-value.
* An error is raised if the curve cannot be inverted; if this condition is
* non-fatal, the x-value at the endpoint with the closest y-value is
* returned.
*$ Detailed_description:
* This routine returns the inverse of the given curve, i.e. the location
* within the segment where the curve equals the given y-value.
*
* Inverses are calculated within a specified segment, which is a monotonic
* section of a curve. Segments are separated by extrema and points of
* inflection, where segment #1 runs from the lower endpoint to the first
* extremum/inflection point, or to the upper endpoint if that comes first.
*
* An error is raised if the curve cannot be inverted; if this condition
* is non-fatal, the x-value at the endpoint of the segment with the
* closest y-value is returned.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* Suppose square is a curve that returns x squared between -3.d0 and 3.d0.
*
* Then FPro_CurveInverse(square, 1, 2.25d0) returns -1.5d0;
* FPro_CurveInverse(square, 2, 2.25d0) returns 1.5d0.
*$ Error_handling:
* Profile library error handling is in effect.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or is not a curve.
* PRO_DOMAIN_ERROR if the segment index is out of range for the
* curve.
* PRO_EVALUATION_FAILURE if curve could not be inverted.
* FORTRAN_POINTER_ERROR if object is not a valid FORTRAN object pointer.
*
* For a non-fatal PRO_CLASS_ERROR or FORTRAN_POINTER_ERROR, zero is
* returned; for a non-fatal PRO_DOMAIN_ERROR or PRO_EVALUATION_FAILURE,
* the x-value at the nearest segment endpoint is returned.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
* 1.1: October 1999
*$ Change_history:
* 1.1: QUICK mode compile option added.
*******************************************************************************/
RL_FLT8 FORTRAN_NAME(fpro_curveinverse) (object, segment, y)
RL_INT4 *object, *segment;
RL_FLT8 *y;
{
RL_VOID *ptr;
/* Look up object pointer */
ptr = FORT_GetPointer(*object);
#ifndef QUICK
if (ptr == NULL) return 0.;
#endif
/* Call function */
return Pro_CurveInverse((PRO_OBJECT *) ptr, *segment, *y);
}
/*
********************************************************************************
*$ Component_name:
* FPro_CurveSegments (curve.c)
*$ Abstract:
* This function returns the number of segments in the curve domain. A
* segment is the region from one endpoint, extremum, or inflection point
* to the next.
*$ Keywords:
* PROFILE, FUNCTION, CURVE
* FORTRAN, PUBLIC, SUBROUTINE
*$ Declarations:
* integer*4 function FPro_CurveSegments(object)
* integer*4 object
*$ Inputs:
* object FORTRAN pointer to the curve object.
*$ Outputs:
* none
*$ Returns:
* number of segments, or 0 on error.
*$ Detailed_description:
* This function returns the number of segments in the curve domain. A
* segment is the region from one endpoint, extremum, or inflection point
* to the next.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* Suppose square is a curve that returns x squared between -3.d0 and 3.d0.
*
* Then FPro_CurveSegments(square) returns 2.
*$ Error_handling:
* Profile library error handling is in effect. On non-fatal error, the
* routine returns 0.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or is not a curve.
* FORTRAN_POINTER_ERROR if object is not a valid FORTRAN object pointer.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
*******************************************************************************/
RL_INT4 FORTRAN_NAME(fpro_curvesegments) (object)
RL_INT4 *object;
{
RL_VOID *ptr;
/* Look up object pointer */
ptr = FORT_GetPointer(*object);
if (ptr == NULL) return 0;
/* Call function */
return Pro_CurveSegments((PRO_OBJECT *) ptr);
}
/*
********************************************************************************
*$ Component_name:
* FPro_CurveExtremum (curve.c)
*$ Abstract:
* This routine returns the location of the given extremum, inflection
* point or domain endpoint.
*$ Keywords:
* PROFILE, FUNCTION, CURVE
* FORTRAN, PUBLIC, SUBROUTINE
*$ Declarations:
* real*8 function FPro_CurveExtremum(object, segment, value, type)
* integer*4 object, segment, type
* real*8 value
*$ Inputs:
* object FORTRAN pointer to the curve object.
* segment segment number (0 to number of segments).
*$ Outputs:
* value value of the curve at this location.
* type +1 if extremum is a local maximum; -1 if extremum is a
* local minimum; 0 if extremum is an inflection point.
*$ Returns:
* location of extremum, or 0. on error.
*$ Detailed_description:
* This routine returns the location of the given extremum, inflection
* point or domain endpoint.
*
* Points are identified by 0 through N, where N is the number of segments
* in the curve. Here 0 and N refers to the lower and upper limits of the
* domain, and 1 to N-1 refer to the local extrema and inflection points in
* between. Hence, segment #n is bounded by points #n-1 and #n.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* Suppose square is a curve that returns x squared between -3.d0 and 3.d0.
*
* Then FPro_CurveExtremum(square, 0, value, type) returns -3.d0, sets
* value to 9.d0 and sets type to +1 (maximum);
* FPro_CurveExtremum(square, 1, value, type) returns 0.d0, sets
* value to 0.d0 and sets type to -1 (minimum);
* FPro_CurveExtremum(square, 2, value, type) returns 3.d0, sets
* value to 9.d0 and sets type to +1 (maximum).
*$ Error_handling:
* Profile library error handling is in effect. On non-fatal error, the
* routine returns 0.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or is not a curve.
* PRO_DOMAIN_ERROR if the segment index is out of range for the
* curve; in this case properties of the nearest
* domain endpoint are returned.
* FORTRAN_POINTER_ERROR if object is not a valid FORTRAN object pointer.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
*******************************************************************************/
RL_FLT8 FORTRAN_NAME(fpro_curveextremum) (object, segment, value, type)
RL_INT4 *object, *segment, *type;
RL_FLT8 *value;
{
RL_VOID *ptr;
/* Look up object pointer */
ptr = FORT_GetPointer(*object);
if (ptr == NULL) return 0.;
/* Call function */
return Pro_CurveExtremum((PRO_OBJECT *) ptr, *segment, value, type);
}
/*******************************************************************************
*/