 /*
  * Khoros: $Id: ldfht.c,v 1.2 1992/03/20 23:25:37 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: ldfht.c,v 1.2 1992/03/20 23:25:37 dkhoros Exp $";
#endif

 /*
  * $Log: ldfht.c,v $
 * Revision 1.2  1992/03/20  23:25:37  dkhoros
 * VirtualPatch5
 *
  */

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1992, University of New Mexico.  All rights reserved.
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as to the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including, for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

#include "unmcopyright.h"        /* Copyright 1992 by UNM */

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 >>>>
 >>>>         File Name: ldfht.c
 >>>>
 >>>>      Program Name: dfht
 >>>>
 >>>> Date Last Updated: Thu Mar  5 10:34:55 1992 
 >>>>
 >>>>          Routines: ldfht - the library call for dfht
 >>>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/


#include "vinclude.h"


/* -library_includes */
#define CHECKLIBINPUT(program, img) { \
        if (!propertype (program, img, VFF_TYP_FLOAT, FALSE)) {               \
            fprintf (stderr, "error in ldfht: input image must ");            \
            fprintf (stderr, "be VFF_TYP_FLOAT: returning with an error\n");  \
            return (0);                                                       \
        }                                                                     \
        if (!proper_loc_type (program, img, VFF_LOC_IMPLICIT, FALSE)) {       \
            fprintf (stderr, "error in ldfht: input image must ");            \
            fprintf (stderr,"be VFF_LOC_IMPLICIT: returning with an error\n");\
            return (0);                                                       \
        }                                                                     \
        if (!proper_map_type (program, img, VFF_MAPTYP_NONE, FALSE)) {        \
            fprintf (stderr, "error in ldfht: input image must ");            \
            fprintf (stderr,"be VFF_MAPTYP_NONE: returning with an error\n"); \
            return (0);                                                       \
        }                                                                     \
        if (!proper_map_enable (program, img, VFF_MAP_OPTIONAL, FALSE)) {     \
            fprintf (stderr, "error in ldfht: input image must ");            \
            fprintf (stderr,"be VFF_MAP_OPTIONAL: returning with an error\n");\
            return (0);                                                       \
        }                                                                     \
        if (!proper_map_scheme (program, img, VFF_MS_NONE, FALSE)) {          \
            fprintf (stderr, "error in ldfht: input image must ");            \
            fprintf (stderr,"be VFF_MS_NONE: returning with an error\n");     \
            return (0);                                                       \
        }                                                                     \
        if (!proper_num_images (program, img, 1, FALSE)) {                    \
            fprintf (stderr, "error in ldfht: input image must ");            \
            fprintf(stderr,"contain only 1 image: returning with an error\n");\
            return (0);                                                       \
        } }

#define NOSCALE 0
#define SCALE_BY_N 1
#define SCALE_BY_ROOT_N 2
/* -library_includes_end */


/****************************************************************
*
* Routine Name: ldfht - library call for dfht
*
* Purpose:
*    
*    Take the 1-D Fast Hadamard Transform of a signal.
*    
*    

* Input:
*    
*         1.  img - a pointer to an xvimage structure  containing  the
*         signal to be transformed
*    
*         2.  scale_flag - an integer which specifies whether the out-
*         put from the transform should be left unscaled(0), scaled by
*         1/N(1), or scaled by 1/sqrt(N)(2).
*    
*         3.  dir_flag  -  an  integer  which  specifies  whether  the
*         transform   should   be  taken  down  vectors(0)  or  across
*         bands(1).
*    
*    

* Output:
*    
*         1.  img - the input image is overwritten and the  output  is
*         returned  in  its place.  Be careful not to overwrite impor-
*         tant data.
*    
*         ldfht returns 1 upon success and 0 on failure.
*    
*    

*
* Written By: Per Lysne
*    
*    Jeremy Worley 03 Apr 1991 21:01 MST
*              Removed a  restriction  that  forced  the  data  to  be
*              oriented  as  1  row by n columns.  It may now have any
*              orientation.
*    
*    Jeremy Worley 05 Mar 1992 10:33 MST
*              Fixed up many implicit declarations of functions.
*    
*    

****************************************************************/


/* -library_def */
int ldfht (img, scale_flag, dir_flag)
struct xvimage *img;
int scale_flag, dir_flag;
/* -library_def_end */

/* -library_code */
{
    int N, i, j, k, l, le, ip, num_vects, num;
    float **data, temp, scale;
    char *program="ldfht", **dload_vector();
    int propertype(), proper_loc_type(), proper_map_type(), 
        proper_map_enable(), proper_map_scheme(), proper_num_images(), 
        powtwo(), dunload_vector();

    /* Check for a bad input pointer. */
    if (img==NULL) {
        fprintf (stderr, "error in ldfht: bad input xvimage pointer: ");
        fprintf (stderr, "returning false\n");
        return (0);
    }

    /* Check for a correct type of input image. */
    CHECKLIBINPUT (program, img);

    /* Read the vectors from the image input file. */
    data = (float **) dload_vector(img, &num_vects, &N, dir_flag);
    if (data==NULL) {
        fprintf (stderr, "error in ldfht: dload_vect failed: ");
        fprintf (stderr, " returning false\n");
        return(0);
    }
        
    /* Check for legal size vectors to operate on. */
    if (N==0) {
        fprintf (stderr, "error in ldfht: vector length may ");
        fprintf (stderr, "not be 0: returning false\n");
        return(0);
    }
    if (!powtwo(N)) {
        fprintf (stderr, "error in ldfht: vector length must be a power ");
        fprintf (stderr, "of two: returning false\n");
        return(0);
    }

    /* Do the Fast Hadamard Transform on each vector. */
    for (num=0; num<num_vects; num++) {
        /*
         * This loop reorders the input data.
         */
        j=0;
        for (i=0; i<N-1; i++) {
            if (i<j) {
                temp=data[num][j];
                data[num][j]=data[num][i];
                data[num][i]=temp;
            }
            k=N/2;
            while (k<=j) {
                j=j-k;
                k=k/2;
            }
            j=j+k;
        }
    
        /*
         * This loop does the Hadamard Transform.
         */
        l=1;
        while (l<N) {
            le=l;
            l=l*2;
            for (j=0; j<le; j++) {
                for (i=j; i<N; i=i+l) {
                    ip=i+le;
                    temp=data[num][ip];
                    data[num][ip]=data[num][i]-temp;
                    data[num][i]=data[num][i]+temp;
                }
            }
        }

        /* Scale the output of the transform. */
        if (scale_flag==SCALE_BY_N) {
            for (i=0; i<N; i++)
                data[num][i]=data[num][i]/N;
        }
        else if (scale_flag==SCALE_BY_ROOT_N) {
            scale = sqrt((float)N);
            for (i=0; i<N; i++)
                data[num][i]=data[num][i]/scale;
        }
    }

    /* Write the vectors back into the image. */
    if (!dunload_vector((char **)data, img,(unsigned long)VFF_TYP_FLOAT,
         num_vects, N, dir_flag)) {
        fprintf (stderr, "error in ldfht: dunload_vector failed: ");
        fprintf (stderr, "returning false\n");
        return(0);
    }

    return(1);
}
/* -library_code_end */
