
/*
 * Copyright (1987) Jeff Elman.  University of California, San Diego
 * This software may be redistributed without charge; this notice
 * should be preserved.
 */

#include <stdio.h>
#include "defs.h"

update_weight2()
{
	float 	I;
	extern	float alpha;
	extern	float beta;
	extern	float **d_tokenp;
	extern	int debug;
	extern	int cur_token;
	extern	float rate;
	extern	float *nodep;
	extern	int *onlys;
	extern	float *biasp;
	extern	float *dbiasp;
	extern	float *ibiasp;
	extern	float *deltap;
	extern	float **weightp;
	extern	float **dweightp;
	extern	float **iweightp;
	extern	int **condown;
	extern	int numtotal;
	extern	int nobias;
	extern	int bipolar;
	extern	int only;
	extern	int rbp;
	extern	int update;
	extern	int updatenow;
	extern	float momentum;
	register float *np;
	register float *bp;
	register float *dbp;
	register float *ibp;
	register float *dp;
	register int *cdp;
	register float **wp;
	register float **dwp;
	register float **iwp;
	register int i;
	float	*tmp1;
	float	*tmp2;
	float	*tmp3;
	float	*tmp4;
	float	*winc;
	float	*wt_ij; 
	float	*z_i;
	float	*x_j;
	float	*d_wt_ij;
	float	u_i;
	float	mom;
	float	deriv;
	int	**cdpp;

	wp = weightp;
	dwp = dweightp;
	iwp = iweightp;
	np = nodep;
	dp = deltap;
	bp = biasp;
	dbp = dbiasp;
	ibp = ibiasp;
	if (debug > 5)
		fprintf(stdout, "W [%d]: \n", cur_token);
	for (i=numtotal-1, cdpp= condown+numtotal-1; i>=0; i--,cdpp--) {
		if (rbp == 1){
		    I = *(*(d_tokenp+cur_token)+i);
		    if (I <= -999999999.)
			I = 0.0;
		    u_i = (alpha * *(nodep+i) - I) / beta;
		    if (bipolar==0)
			    deriv = (1. - u_i) * u_i;
		    else
			    deriv = .5 * (1. - u_i) * (1. + u_i);
		}
		for (cdp= *cdpp; *cdp != -1; cdp++) {
		    if ((only == 1) && ((onlys[i] == 0) || (onlys[*cdp] == 0)))
			continue;
			if (rbp == 0) {
			    tmp1 = (*(wp+*cdp)+i);
			    tmp2 = dp+i;
			    tmp3 = (np+*cdp);
			    tmp4 = (*(dwp+*cdp)+i);
			    if (update == 0){ /* update after each sweep */
			        *tmp4 = *tmp2 * *tmp3 * rate + momentum * *tmp4;
			        *tmp1 += *tmp4;
			    } else if (update == 1){ /* update after epoch */
			        winc = (*(iwp+*cdp)+i);
				if (updatenow == 0){
				    *winc += *tmp2 * *tmp3 * rate;
				}
				else {
				    *winc += *tmp2 * *tmp3 * rate;
				    *tmp4 = *winc + momentum * *tmp4;
			            *tmp1 += *tmp4;
				    *winc = 0.;
				}
			    }
			    /*
			    tmp1 = (*(wp+*cdp)+i);
			    tmp2 = dp+i;
			    tmp3 = (np+*cdp);
			    *tmp1 += *tmp2 * *tmp3 * rate;
			    */
			    /*
			    *(*(wp+*cdp)+i) += *(dp+i) * *(np+*cdp) * rate;
			    */
			} else if (rbp == 1) {
			    wt_ij = (*(wp+*cdp)+i);
			    d_wt_ij = (*(dwp+*cdp)+i);
			    mom = *d_wt_ij * momentum;
			    z_i = dp+i;
			    x_j = (np+*cdp);
			    *d_wt_ij = deriv * *z_i * *x_j * rate + mom;
			    /*
			    *d_wt_ij = deriv * *z_i * *x_j;
			    */
			    if (debug > 5)
				    fprintf(stdout, "%f ", *d_wt_ij);
			    *wt_ij += *d_wt_ij;
			    /*
			    *wt_ij += (*d_wt_ij * rate) + mom ;
			    */
			}
		}
		if (debug > 5)
			fprintf(stdout, "\n");
		/*
		 * if nobias==0, we do calculate biases
		 */
		if ((only == 1) && (onlys[i] == 0))
			continue;
		if (nobias==0){
		    if (rbp == 0) {
		        if (update == 0){ /* update after each sweep */
			    *(dbp+i) = *(dp+i) * rate + momentum * *(dbp+i);
			    *(bp+i) += *(dbp+i);
		        } else if (update == 1){ /* update after epoch */
			    if (updatenow == 0){
				*(ibp+i) += *(dp+i) * rate;
			    }
			    else {
				*(ibp+i) += *(dp+i) * rate;
				*(dbp+i) = *(ibp+i) + momentum * *(dbp+i);
				*(bp+i) += *(dbp+i);
				*(ibp+i) = 0.;
			    }
		        }
			/*
			*(bp+i) += *(dp+i) * rate;
			*/
		    } else if (rbp == 1) {
			*(dbp+i) = *(dp+i) * rate * deriv + momentum * *(dbp+i);
			*(bp+i) += *(dbp+i);
		    }
		}
	}
		
	constrain_weights();
}
