/* Next available MSG number is   6 */

/***************************************************************************
   Module Name:  sqr.cc

   Copyright (C) 1994,1996 by Autodesk, Inc.
 
   Permission to use, copy, modify, and distribute this software in 
   object code form for any purpose and without fee is hereby granted, 
   provided that the above copyright notice appears in all copies and 
   that both that copyright notice and the limited warranty and 
   restricted rights notice below appear in all supporting 
   documentation.
 
   AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.  
   AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 
   MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
   DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 
   UNINTERRUPTED OR ERROR FREE.
 
   Use, duplication, or disclosure by the U.S. Government is subject to 
   restrictions set forth in FAR 52.227-19 (Commercial Computer 
   Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) 
   (Rights in Technical Data and Computer Software), as applicable.
    
   .

   Description:Another Sample RXADS application

   Author     :  
                 Autodesk, Inc.
                 2320 Marinship Way
                 Sausalito, CA. 94965
                 (415)332-2344

    This Arx application is a conversion from the original sample ADS app
    sqr.c.

    Original creation - by Mark Barrow - 3/14/90
    Comments and revisions - Randy Clark, 4/23/90
    Converted to Arx by:  William Howison, January 1994

    Function Entry Points:
      AcRx::AppRetCode
        acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt);

    Notes and restrictions on use:
 
 
***************************************************************************/
 

/**************************************************************************/
/*  MODULE NAME  */
/**************************************************************************/
#define    SQR


/**************************************************************************/
/*  INCLUDES  */
/**************************************************************************/

#include <stdio.h>
#include <math.h>
#include "adslib.h"
#include "rxdefs.h"
#include "adesk.h"
#include "ol_errno.h"

extern "C" {
/****************************************************************************/
/*  LOCALLY DEFINED ENTRY POINT INVOKED BY Arx                              */
/****************************************************************************/
AcRx::AppRetCode acrxEntryPoint(AcRx::AppMsgCode msg, void*);
}
 
#define ExtFuncCount    1             /* Must increase this count if new
                                         external functions are added */

/****************************************************************************/
/*  LOCAL FUNCTION FORWARD DECLARATIONS  */
/****************************************************************************/
int funcload _((void));
int funcunload _((void));
int dofun _((void));

/**************************************************************************/
/*  GLOBAL VARIABLES  */
/**************************************************************************/
char *exfun[] = {/*MSG0*/"sqr"};      /* No "C:" -- to be called as an AutoLISP
                                         function, not as an AutoCAD command */

/* More functions could be added to this table.  For example:
   char *exfun[] = {"C:sqr", "C:shaft", "PIN"}; */

/*-----------------------------------------------------------------------*/
/* FUNCLOAD  --  Define this application's external functions  */

int funcload()
{
    int i;
    for (i = 0; i < ExtFuncCount; i++) {
        if (!ads_defun(exfun[i], i))
            return RTERROR;
    }
    return RTNORM;
}
/*-----------------------------------------------------------------------*/
/* FUNCUNLOAD  --  Unload external functions */

int funcunload()
{
    int i;

    /* Undefine each function we defined */

    for (i = 0; i < ExtFuncCount; i++) {
        ads_undef(exfun[i],i);
    }
    return RTNORM;
}
/*-----------------------------------------------------------------------*/
/* DOFUN -- Execute external function (called upon an RQSUBR request) */

int dofun()
{
    struct resbuf *rb;
    int val;
    ads_real x;
    extern ads_real rsqr _((ads_real));

    if ((val = ads_getfuncode()) < 0)
        return 0;

    if ((rb = ads_getargs()) == NULL)
        return 0;

    switch (val) {                    /* The 'sqr' function was defined
                                         to have a funcode of 0 */

    case 0:
        if (rb->restype == RTSHORT) {   /* Save in local variable */
            x = (ads_real) rb->resval.rint;
        } else if (rb->restype == RTREAL) {
            x = rb->resval.rreal;     /* Can accept either real
                                         or integer */
        } else {
            ads_fail(/*MSG3*/"Argument should be a real or integer value.");
            return 0;
        }
        if (x < 0) {                  /* Check argument range */
            ads_fail(/*MSG4*/"Argument should be positive.");
            return 0;
        }

        ads_retreal(rsqr(x));         /* Call the function itself, and
                                         return the value to AutoLISP */

        return 1;

    default:
        ads_fail(/*MSG5*/"Received nonexistent function code.");
        return 0;
    }
}
/*-----------------------------------------------------------------------*/
/* This is the implementation of the actual external function */

ads_real rsqr(ads_real x)       /* Figure square root (Newton-Raphson method) */
{
    ads_real y, c, cl;
    int n;

    if (x == 0.0) {
        return 0.0;
    }

#ifdef __STDC__
    y = frexp(x, &n);        /* split x to get exponent */
    y = ldexp(1.0, n / 2);   /* good guess at sqrt */
    n = 10;                  /* it will converge faster than this */
#else
    y = (0.154116 + 1.893872 * x) / (1.0 + 1.047988 * x);
    /* It takes a lot of iterations to get sqrt(1E22) from
       an initial guess of 1.9 */
    n = 50;
#endif
    c = 0.0;
    do {
        cl = c;
        c = (y - x / y) * 0.5;
        y -=  c;
    } while (c != cl && --n);
    return y;
}

/* =================== Arx Module Interface Functions ================ */


AcRx::AppRetCode
/*FCN*/acrxEntryPoint(AcRx::AppMsgCode msg, void * ptr)
{

    switch(msg) {
        case AcRx::kInitAppMsg:
             acrxUnlockApplication(ptr);
            break;
        case AcRx::kInvkSubrMsg:
            dofun();
            break;
        case AcRx::kLoadDwgMsg:
            funcload();
            break;
        case AcRx::kUnloadDwgMsg:
            funcunload();
            ads_printf(/*MSG2*/"Unloading.\n");
            break;
        case AcRx::kUnloadAppMsg:
        default:
            break;
    }
    return AcRx::kRetOK;
}

