Ejemplo n.º 1
0
/* g in Z[X] potentially defines a subfield of Q[X]/f. It is a subfield iff A
 * (cf subfield) was a block system; then there
 * exists h in Q[X] such that f | g o h. listdelta determines h s.t f | g o h
 * in Fp[X] (cf chinese_retrieve_pol). Try to lift it; den is a
 * multiplicative bound for denominator of lift. */
static GEN
embedding(GEN g, GEN DATA, primedata *S, GEN den, GEN listdelta)
{
  GEN TR, w0_Q, w0, w1_Q, w1, wpow, h0, gp, T, q2, q, maxp, a, p = S->p;
  long rt;
  pari_sp av;

  T   = gel(DATA,1); rt = brent_kung_optpow(degpol(T), 2);
  maxp= gel(DATA,7);
  gp = derivpol(g); av = avma;
  w0 = chinese_retrieve_pol(DATA, S, listdelta);
  w0_Q = centermod(gmul(w0,den), p);
  h0 = FpXQ_inv(FpX_FpXQ_compo(gp,w0, T,p), T,p); /* = 1/g'(w0) mod (T,p) */
  wpow = NULL; q = sqri(p);
  for(;;)
  {/* Given g,w0,h0 in Z[x], s.t. h0.g'(w0) = 1 and g(w0) = 0 mod (T,p), find
    * [w1,h1] satisfying the same conditions mod p^2, [w1,h1] = [w0,h0] (mod p)
    * (cf. Dixon: J. Austral. Math. Soc., Series A, vol.49, 1990, p.445) */
    if (DEBUGLEVEL>1)
      fprintferr("lifting embedding mod p^k = %Z^%ld\n",p, Z_pval(q,p));

    /* w1 := w0 - h0 g(w0) mod (T,q) */
    if (wpow)
      a = FpX_FpXQV_compo(g,wpow, T,q);
    else
      a = FpX_FpXQ_compo(g,w0, T,q); /* first time */
    /* now, a = 0 (p) */
    a = gmul(gneg(h0), gdivexact(a, p));
    w1 = gadd(w0, gmul(p, FpX_rem(a, T,p)));

    w1_Q = centermod(gmul(w1, remii(den,q)), q);
    if (gequal(w1_Q, w0_Q) || cmpii(q,maxp) > 0)
    {
      GEN G = gcmp1(den)? g: RgX_rescale(g,den);
      if (gcmp0(RgX_RgXQ_compo(G, w1_Q, T))) break;
    }
    if (cmpii(q, maxp) > 0)
    {
      if (DEBUGLEVEL) fprintferr("coeff too big for embedding\n");
      return NULL;
    }
    gerepileall(av, 5, &w1,&h0,&w1_Q,&q,&p);
    q2 = sqri(q);
    wpow = FpXQ_powers(w1, rt, T, q2);
    /* h0 := h0 * (2 - h0 g'(w1)) mod (T,q)
     *     = h0 + h0 * (1 - h0 g'(w1)) */
    a = gmul(gneg(h0), FpX_FpXQV_compo(gp, FpXV_red(wpow,q),T,q));
    a = ZX_Z_add(FpX_rem(a, T,q), gen_1); /* 1 - h0 g'(w1) = 0 (p) */
    a = gmul(h0, gdivexact(a, p));
    h0 = gadd(h0, gmul(p, FpX_rem(a, T,p)));
    w0 = w1; w0_Q = w1_Q; p = q; q = q2;
  }
  TR = gel(DATA,5);
  if (!gcmp0(TR)) w1_Q = translate_pol(w1_Q, TR);
  return gdiv(w1_Q,den);
}
Ejemplo n.º 2
0
Archivo: aprcl.c Proyecto: jpflori/pari
static GEN
sqrconst(GEN pol, Red *R)
{
  GEN z = cgetg(3,t_POL);
  gel(z,2) = centermodii(sqri(gel(pol,2)), R->N, R->N2);
  z[1] = pol[1]; return z;
}
Ejemplo n.º 3
0
static GEN
F2xq_elltrace_Harley(GEN a6, GEN T2)
{
  pari_sp ltop = avma;
  pari_timer ti;
  GEN T, sqx;
  GEN x, x2, t;
  long n = F2x_degree(T2), N = ((n + 1)>>1) + 2;
  long ispcyc;
  if (n==1) return gen_m1;
  if (n==2) return F2x_degree(a6) ? gen_1 : stoi(-3);
  if (n==3) return F2x_degree(a6) ? (F2xq_trace(a6,T2) ?  stoi(-3): gen_1)
                                  : stoi(5);
  timer_start(&ti);
  sqx = mkvec2(F2xq_sqrt(polx_F2x(T2[1]),T2), T2);
  if (DEBUGLEVEL>1) timer_printf(&ti,"Sqrtx");
  ispcyc = zx_is_pcyc(F2x_to_Flx(T2));
  T = ispcyc? F2x_to_ZX(T2): F2x_canonlift(T2, N-2);
  if (DEBUGLEVEL>1) timer_printf(&ti,"Teich");
  T = FpX_get_red(T, int2n(N));
  if (DEBUGLEVEL>1) timer_printf(&ti,"Barrett");
  x = solve_AGM_eqn(F2x_to_ZX(a6), N-2, T, sqx);
  if (DEBUGLEVEL>1) timer_printf(&ti,"Lift");
  x2 = ZX_Z_add_shallow(ZX_shifti(x,2), gen_1);
  t = (ispcyc? Z2XQ_invnorm_pcyc: Z2XQ_invnorm)(x2, T, N);
  if (DEBUGLEVEL>1) timer_printf(&ti,"Norm");
  if (cmpii(sqri(t), int2n(n + 2)) > 0)
    t = subii(t, int2n(N));
  return gerepileuptoint(ltop, t);
}
Ejemplo n.º 4
0
/* return a bound for T_2(P), P | polbase in C[X]
 * NB: Mignotte bound: A | S ==>
 *  |a_i| <= binom(d-1, i-1) || S ||_2 + binom(d-1, i) lc(S)
 *
 * Apply to sigma(S) for all embeddings sigma, then take the L_2 norm over
 * sigma, then take the sup over i.
 **/
static GEN
nf_Mignotte_bound(GEN nf, GEN polbase)
{
  GEN G = gmael(nf,5,2), lS = leading_term(polbase); /* t_INT */
  GEN p1, C, N2, matGS, binlS, bin;
  long prec, i, j, d = degpol(polbase), n = degpol(nf[1]), r1 = nf_get_r1(nf);

  binlS = bin = vecbinome(d-1);
  if (!gcmp1(lS)) binlS = gmul(lS, bin);

  N2 = cgetg(n+1, t_VEC);
  prec = gprecision(G);
  for (;;)
  {
    nffp_t F;

    matGS = cgetg(d+2, t_MAT);
    for (j=0; j<=d; j++) gel(matGS,j+1) = arch_for_T2(G, gel(polbase,j+2));
    matGS = shallowtrans(matGS);
    for (j=1; j <= r1; j++) /* N2[j] = || sigma_j(S) ||_2 */
    {
      gel(N2,j) = gsqrt( QuickNormL2(gel(matGS,j), DEFAULTPREC), DEFAULTPREC );
      if (lg(N2[j]) < DEFAULTPREC) goto PRECPB;
    }
    for (   ; j <= n; j+=2)
    {
      GEN q1 = QuickNormL2(gel(matGS,j  ), DEFAULTPREC);
      GEN q2 = QuickNormL2(gel(matGS,j+1), DEFAULTPREC);
      p1 = gmul2n(mpadd(q1, q2), -1);
      gel(N2,j) = gel(N2,j+1) = gsqrt( p1, DEFAULTPREC );
      if (lg(N2[j]) < DEFAULTPREC) goto PRECPB;
    }
    if (j > n) break; /* done */
PRECPB:
    prec = (prec<<1)-2;
    remake_GM(nf, &F, prec); G = F.G;
    if (DEBUGLEVEL>1) pari_warn(warnprec, "nf_factor_bound", prec);
  }

  /* Take sup over 0 <= i <= d of
   * sum_sigma | binom(d-1, i-1) ||sigma(S)||_2 + binom(d-1,i) lc(S) |^2 */

  /* i = 0: n lc(S)^2 */
  C = mulsi(n, sqri(lS));
  /* i = d: sum_sigma ||sigma(S)||_2^2 */
  p1 = gnorml2(N2); if (gcmp(C, p1) < 0) C = p1;
  for (i = 1; i < d; i++)
  {
    GEN s = gen_0;
    for (j = 1; j <= n; j++)
    {
      p1 = mpadd( mpmul(gel(bin,i), gel(N2,j)), gel(binlS,i+1) );
      s = mpadd(s, gsqr(p1));
    }
    if (gcmp(C, s) < 0) C = s;
  }
  return C;
}
Ejemplo n.º 5
0
Archivo: aprcl.c Proyecto: jpflori/pari
/* pol^2 mod (polcyclo(5),N) */
static GEN
sqrmod5(GEN pol, Red *R)
{
  GEN c2,b,c,d,A,B,C,D;
  long lv = lg(pol);

  if (lv==2) return pol;
  if (lv==3) return sqrconst(pol, R);
  c = gel(pol,3); c2 = shifti(c,1);
  d = gel(pol,2);
  if (lv==4)
  {
    A = sqri(d);
    B = mulii(c2, d);
    C = sqri(c);
    A = centermodii(A, R->N, R->N2);
    B = centermodii(B, R->N, R->N2);
    C = centermodii(C, R->N, R->N2); return mkpoln(3,A,B,C);
  }
  b = gel(pol,4);
  if (lv==5)
  {
    A = mulii(b, subii(c2,b));
    B = addii(sqri(c), mulii(b, subii(shifti(d,1),b)));
    C = subii(mulii(c2,d), sqri(b));
    D = mulii(subii(d,b), addii(d,b));
  }
  else
  { /* lv == 6 */
    GEN a = gel(pol,5), a2 = shifti(a,1);
    /* 2a(d - c) + b(2c - b) */
    A = addii(mulii(a2, subii(d,c)), mulii(b, subii(c2,b)));
    /* c(c - 2a) + b(2d - b) */
    B = addii(mulii(c, subii(c,a2)), mulii(b, subii(shifti(d,1),b)));
    /* (a-b)(a+b) + 2c(d - a) */
    C = addii(mulii(subii(a,b),addii(a,b)), mulii(c2,subii(d,a)));
    /* 2a(b - c) + (d-b)(d+b) */
    D = addii(mulii(a2, subii(b,c)), mulii(subii(d,b), addii(d,b)));
  }
  A = centermodii(A, R->N, R->N2);
  B = centermodii(B, R->N, R->N2);
  C = centermodii(C, R->N, R->N2);
  D = centermodii(D, R->N, R->N2); return mkpoln(4,A,B,C,D);
}
Ejemplo n.º 6
0
static void
subfields_poldata(GEN T, poldata *PD)
{
  GEN  nf,L,dis;

  T = shallowcopy(get_nfpol(T, &nf));
  PD->pol = T; setvarn(T, 0);
  if (nf)
  {
    PD->den = Q_denom(gel(nf,7));
    PD->roo = gel(nf,6);
    PD->dis = mulii(absi(gel(nf,3)), sqri(gel(nf,4)));
  }
  else
  {
    PD->den = initgaloisborne(T,NULL,ZX_get_prec(T), &L,NULL,&dis);
    PD->roo = L;
    PD->dis = absi(dis);
  }
}
Ejemplo n.º 7
0
/* return a bound for T_2(P), P | polbase
 * max |b_i|^2 <= 3^{3/2 + d} / (4 \pi d) [P]_2,
 * where [P]_2 is Bombieri's 2-norm
 * Sum over conjugates
*/
static GEN
nf_Beauzamy_bound(GEN nf, GEN polbase)
{
  GEN lt,C,run,s, G = gmael(nf,5,2), POL, bin;
  long i,prec,precnf, d = degpol(polbase), n = degpol(nf[1]);

  precnf = gprecision(G);
  prec   = MEDDEFAULTPREC;
  bin = vecbinome(d);
  POL = polbase + 2;
  /* compute [POL]_2 */
  for (;;)
  {
    run= real_1(prec);
    s = real_0(prec);
    for (i=0; i<=d; i++)
    {
      GEN p1 = gnorml2(arch_for_T2(G, gmul(run, gel(POL,i)))); /* T2(POL[i]) */
      if (!signe(p1)) continue;
      if (lg(p1) == 3) break;
      /* s += T2(POL[i]) / binomial(d,i) */
      s = addrr(s, gdiv(p1, gel(bin,i+1)));
    }
    if (i > d) break;

    prec = (prec<<1)-2;
    if (prec > precnf)
    {
      nffp_t F; remake_GM(nf, &F, prec); G = F.G;
      if (DEBUGLEVEL>1) pari_warn(warnprec, "nf_factor_bound", prec);
    }
  }
  lt = leading_term(polbase);
  s = gmul(s, mulis(sqri(lt), n));
  C = powrshalf(stor(3,DEFAULTPREC), 3 + 2*d); /* 3^{3/2 + d} */
  return gdiv(gmul(C, s), gmulsg(d, mppi(DEFAULTPREC)));
}
Ejemplo n.º 8
0
void tileMap::pickRowDelta(bool showProgress,Fl_Progress *progress,int alg,int order){
	if(currentProject->pal->rowCntPal<=1){
		fl_alert("This function needs more than one palette row to work");
		return;
	}
	if(alg<0){
		alg=menuPopupArray(deltaAlgLbl,deltaAlgTooltip,0,deltaChoices);
		if(alg<0)
			return;
	}
	pushTilemapAll(true);
	pushTilesAll(tTypeTile);
	if(order<0){
		order=menuPopupArray(deltaAlgLbl,deltaAlgTooltip,0,deltaOrderChoices);
		if(order<0)
			return;
	}
	if(order>0){
		pushPaletteAll();
		sortBy(order>3?order-4:order-1,order<4);
	}
	unsigned type_temp=palTypeGen;
	uint8_t tempSet=0;
	double d[4];//Delta
	uint32_t di[4];//Delta integer
	uint32_t x;
	uint8_t t;
	uint8_t temp[256];//Just as a word of caution this is used for both sprintf temporary buffer and temporary truecolor tile buffer
	uint32_t w,h;
	w=mapSizeW*8;
	h=mapSizeHA*8;
	uint8_t * imagein=(uint8_t*)malloc(w*h*4);
	truecolor_to_image(imagein,-1);
	uint8_t **imageout=(uint8_t**)malloc(currentProject->pal->rowCntPal*sizeof(void*));
	uint32_t xtile=0,ytile=0;
	if(showProgress){
		progress->maximum(currentProject->pal->rowCntPal*3);
		progress->value(0);
	}
	for(x=0;x<currentProject->pal->rowCntPal;++x){//This function has too many hard coded values The four should be a variable with the amount of palette rows
		if(showProgress){
			snprintf((char*)temp,256,"Dithering %d",x);
			progress->label((char*)temp);
			Fl::check();
		}
		imageout[x]=(uint8_t*)malloc(w*h*4);
		truecolor_to_image(imageout[x],-1);
		if(showProgress){
			progress->value((x*3)+1);
			Fl::check();
		}
		ditherImage(imageout[x],w,h,true,true,true,x);
		if(showProgress){
			progress->value((x*3)+2);
			Fl::check();
		}
		ditherImage(imageout[x],w,h,true,false,true,x);
		if(showProgress){
			progress->value((x*3)+3);
			Fl::check();
		}
	}
	if(showProgress){
		progress->maximum(mapSizeHA);
		progress->label("Picking tiles based on delta");
	}
	unsigned per;
	if((currentProject->gameSystem==NES)&&(currentProject->subSystem&NES2x2))
		per=2;
	else
		per=1;
	for (uint_fast32_t a=0;a<(h*w*4)-(w*4*per);a+=w*4*8*per){//a tiles y
		for (uint_fast32_t b=0;b<w*4;b+=32*per){//b tiles x
			if(alg==2||alg==1)
				memset(di,0,currentProject->pal->rowCntPal*sizeof(uint32_t));
			else{
				std::fill(d,d+currentProject->pal->rowCntPal,0.);
			}
			if ((type_temp != 0) && (currentProject->gameSystem == segaGenesis)){
				tempSet=(currentProject->tms->maps[currentProject->curPlane].get_prio(xtile,ytile)^1)*8;
				set_palette_type_force(tempSet);
			}
			for(t=0;t<currentProject->pal->rowCntPal;++t){
				for(unsigned c=0;c<per*w*4*8;c+=w*4*8){
					for(uint32_t y=0;y<w*4*8;y+=w*4){//pixels y
						for(unsigned e=0;e<per*32;e+=32){
							if(imagein[a+b+y+x+3+c+e]!=0){//Avoid checking transparency
								switch(alg){
									case 0:
										for(x=0;x<32;x+=4)
											d[t]+=std::abs(ciede2000rgb(imagein[a+b+y+x+c+e],imagein[a+b+y+x+1+c+e],imagein[a+b+y+x+2+c+e],imageout[t][a+b+y+x+c+e],imageout[t][a+b+y+x+1+c+e],imageout[t][a+b+y+x+2+c+e]));
									break;
									case 1:
										for(x=0;x<32;x+=4)
											di[t]+=ColourDistance(imagein[a+b+y+x+c+e],imagein[a+b+y+x+1+c+e],imagein[a+b+y+x+2+c+e],imageout[t][a+b+y+x+c+e],imageout[t][a+b+y+x+1+c+e],imageout[t][a+b+y+x+2+c+e]);
									break;
									case 3:
									case 4:
									case 5:
										for(x=0;x<32;x+=4){
											double h[2],l[2],s[2];
											rgbToHsl255(imagein[a+b+y+x+c+e],imagein[a+b+y+x+1+c+e],imagein[a+b+y+x+2+c+e],h,s,l);
											rgbToHsl255(imageout[t][a+b+y+x+c+e],imageout[t][a+b+y+x+1+c+e],imageout[t][a+b+y+x+2+c+e],h+1,s+1,l+1);
											d[t]+=std::abs(pickIt(h[0],s[0],l[0],alg-3)-pickIt(h[1],s[1],l[1],alg-3));
										}
									break;
									default://Usually case 2
										for(x=0;x<32;x+=4)
											di[t]+=sqri(imagein[a+b+y+x+c+e]-imageout[t][a+b+y+x+c+e])+sqri(imagein[a+b+y+x+1+c+e]-imageout[t][a+b+y+x+1+c+e])+sqri(imagein[a+b+y+x+2+c+e]-imageout[t][a+b+y+x+2+c+e]);
								}
							}
						}
					}
				}
			}
			unsigned sillyrow;
			if(alg==2||alg==1)
				sillyrow=pick4Delta(di,currentProject->pal->rowCntPal);
			else
				sillyrow=pick4Delta(d,currentProject->pal->rowCntPal);
			set_pal_row(xtile,ytile,sillyrow);
			for(unsigned c=0,i=0;c<per*w*4*8;c+=w*4*8,++i){
				for(unsigned e=0,j=0;e<per*32;e+=32,++j){
					uint_fast32_t truecolor_tile_ptr=0;
					for (uint_fast32_t y=0;y<w*4*8;y+=w*4){//pixels y
						memcpy(&temp[truecolor_tile_ptr],&imageout[sillyrow][a+b+y+c+e],32);
						truecolor_tile_ptr+=32;
					}
					currentProject->tileC->truecolor_to_tile_ptr(sillyrow,get_tile(xtile+j,ytile+i),temp,false,false);
				}
			}
			xtile+=per;
		}
		if(showProgress){
			if((a%(w*4*8*16))==0){
				progress->value(ytile);
				if(window){
					window->redraw();
					Fl::check();
				}
			}
		}
		xtile=0;
		ytile+=per;
	}
	free(imagein);
	for(unsigned i=0;i<currentProject->pal->rowCntPal;++i)
		free(imageout[i]);
	free(imageout);
	if(currentProject->gameSystem == segaGenesis)
		set_palette_type();
}
Ejemplo n.º 9
0
int G3AccumVertColor (int nVertex, CFloatVector3 *pColorSum, CVertColorData *vcdP, int nThread)
{
	int					i, j, nLights, nType, 
							bSkipHeadlight = gameOpts->ogl.bHeadlight && !gameStates.render.nState,
							bTransform = gameStates.render.nState && !gameStates.ogl.bUseTransform,
							nSaturation = gameOpts->render.color.nSaturation;
	int					nBrightness, nMaxBrightness = 0;
	float					fLightDist, fAttenuation, fLightAngle, spotEffect, NdotL, RdotE;
	CFloatVector3		spotDir, lightDir, lightPos, vertPos, vReflect;
	CFloatVector3		lightColor, colorSum, vertColor = CFloatVector3::Create (0.0f, 0.0f, 0.0f);
	CDynLight*			prl;
	CDynLightIndex*	sliP = &lightManager.Index (0) [nThread];
	CActiveDynLight*	activeLightsP = lightManager.Active (nThread) + sliP->nFirst;
	CVertColorData		vcd = *vcdP;

#if DBG
if (nThread == 0)
	nThread = nThread;
if (nThread == 1)
	nThread = nThread;
#endif
colorSum = *pColorSum;
vertPos = *vcd.vertPosP - *transformation.m_info.posf [1].XYZ ();
vertPos.Neg ();
CFloatVector3::Normalize (vertPos);
nLights = sliP->nActive;
if (nLights > lightManager.LightCount (0))
	nLights = lightManager.LightCount (0);
i = sliP->nLast - sliP->nFirst + 1;
#if DBG
if ((nDbgVertex >= 0) && (nVertex == nDbgVertex))
	nDbgVertex = nDbgVertex;
#endif
for (j = 0; (i > 0) && (nLights > 0); activeLightsP++, i--) {
#if 1
	if (!(prl = activeLightsP->pl))
#else
	if (!(prl = GetActiveRenderLight (activeLightsP, nThread)))
#endif
		continue;
	nLights--;
#if DBG
	if ((nDbgSeg >= 0) && (prl->info.nSegment == nDbgSeg) && ((nDbgSide < 0) || (prl->info.nSide == nDbgSide)))
		nDbgSeg = nDbgSeg;
#	if 0
	else
		continue;
#	endif
#endif
	if (!prl->render.bState)
		continue;
#if 0
	if (i == vcd.nMatLight)
		continue;
#endif
	nType = prl->render.nType;
	if (bSkipHeadlight && (nType == 3))
		continue;
#if ONLY_HEADLIGHT
	if (nType != 3)
		continue;
#endif
	if (prl->info.bVariable && gameData.render.vertColor.bDarkness)
		continue;
	lightColor = *(reinterpret_cast<CFloatVector3*> (&prl->info.color));

	spotDir = *prl->info.vDirf.XYZ (); 
	lightPos = *prl->render.vPosf [bTransform].XYZ ();
	lightDir = lightPos - *vcd.vertPosP;
	if (IsLightVert (nVertex, prl)) {
		fLightDist = 0.0f;
		NdotL = 1.0f;
		}
	else {
		fLightDist = lightDir.Mag () * gameStates.ogl.fLightRange;
		if (lightDir.IsZero ())
			lightDir = vcd.vertNorm;
		else
			CFloatVector3::Normalize (lightDir);
		if ((fLightDist <= 0.1f) || vcd.vertNorm.IsZero ())
			NdotL = 1.0f;
		else {
			NdotL = CFloatVector3::Dot (vcd.vertNorm, lightDir);
			if ((NdotL < 0.0f) && (NdotL > -0.01f))
				NdotL = 0.0f;
			}
		}

#if USE_FACE_DIST
	if (/*(nVertex < 0) &&*/ (nType < 2)) {
		bool bInRad = DistToFace (lightPos, *vcd.vertPosP, prl->info.nSegment, ubyte (prl->info.nSide)) == 0;
		CFloatVector3 dir = lightPos - *vcd.vertPosP;
		fLightDist = dir.Mag () * gameStates.ogl.fLightRange;
		CFloatVector3::Normalize (dir);
		float dot = CFloatVector3::Dot (vcd.vertNorm, dir);
		if (NdotL <= dot) {
			NdotL = dot;
			lightDir = dir;
			}
		if (fabs (fLightDist) < 1.0f)
			fLightDist = 0.0f;
		}
#endif
	if ((gameStates.render.nState || (nType < 2)) && (fLightDist > 0.0f)) {
		// decrease the distance between light and vertex by the light's radius
		// check whether the vertex is behind the light or the light shines at the vertice's back
		// if any of these conditions apply, decrease the light radius, chosing the smaller negative angle
		fLightAngle = (fLightDist > 0.1f) ? -CFloatVector3::Dot (lightDir, spotDir) + 0.01f : 1.0f;
#if !USE_FACE_DIST
		float lightRad = (fLightAngle < 0.0f) ? 0.0f : prl->info.fRad * (1.0f - 0.9f * float (sqrt (fabs (fLightAngle))));	// make rad smaller the greater the angle 
		fLightDist -= lightRad * gameStates.ogl.fLightRange; //make light darker if face behind light source
#endif
		}
	else
		fLightAngle = 1.0f;
	if	(fLightDist <= 0.0f) {
		NdotL = 1.0f;
		fLightDist = 0.0f;
		fAttenuation = 1.0f / prl->info.fBrightness;
		}
	else {	//make it decay faster
		float decay = min (fLightAngle, NdotL);
		if (decay < 0.0f) {
#if 0
			fLightDist -= 1e2f * decay;
#else
			decay += 1.0000001f;
			fLightDist /= decay * decay;
#endif
			}	
		//if ((nType < 2) && (nVertex < 0))
		//fLightDist *= 0.9f;
#if USE_FACE_DIST
		if (/*(nVertex < 0) &&*/ (nType < 2)) 
			fAttenuation = (1.0f + GEO_LIN_ATT * fLightDist + GEO_QUAD_ATT * fLightDist * fLightDist);
		else
#endif
			fAttenuation = (1.0f + GEO_LIN_ATT * fLightDist + GEO_QUAD_ATT * fLightDist * fLightDist);
#if USE_FACE_DIST
		if ((nType < 2) && (prl->info.fRad > 0.0f))
#else
		if ((nVertex > -1) && (prl->info.fRad > 0.0f))
#endif
			NdotL += (1.0f - NdotL) / (0.5f + fAttenuation / 2.0f);
		fAttenuation /= prl->info.fBrightness;
		}
	if (prl->info.bSpot) {
		if (NdotL <= 0.0f)
			continue;
		CFloatVector3::Normalize (spotDir);
		lightDir = -lightDir;
		/*
		lightDir [Y] = -lightDir [Y];
		lightDir [Z] = -lightDir [Z];
		*/
		//spotEffect = G3_DOTF (spotDir, lightDir);
		spotEffect = CFloatVector3::Dot (spotDir, lightDir);

		if (spotEffect <= prl->info.fSpotAngle)
			continue;
		if (prl->info.fSpotExponent)
			spotEffect = (float) pow (spotEffect, prl->info.fSpotExponent);
		fAttenuation /= spotEffect * gameStates.ogl.fLightRange;
		vertColor = *gameData.render.vertColor.matAmbient.XYZ () + (*gameData.render.vertColor.matDiffuse.XYZ () * NdotL);
		}
	else {
		vertColor = *gameData.render.vertColor.matAmbient.XYZ ();
		if (NdotL > 0.1f)
			vertColor += (*gameData.render.vertColor.matDiffuse.XYZ () * NdotL);
		else if (NdotL >= 0.0f)
			vertColor += (*gameData.render.vertColor.matDiffuse.XYZ () * 0.1f);
		else
			NdotL = 0.0f;
		}
	vertColor *= lightColor;
	if ((NdotL > 0.0f) && (fLightDist > 0.0f) && (vcd.fMatShininess > 0.0f) /* && vcd.bMatSpecular */) {
		//RdotV = max (dot (Reflect (-Normalize (lightDir), Normal), Normalize (-vertPos)), 0.0);
		if (!prl->info.bSpot)	//need direction from light to vertex now
			lightDir.Neg ();
		vReflect = CFloatVector3::Reflect (lightDir, vcd.vertNorm);
		CFloatVector3::Normalize (vReflect);
#if DBG
		if ((nDbgVertex >= 0) && (nVertex == nDbgVertex))
			nDbgVertex = nDbgVertex;
#endif
		RdotE = CFloatVector3::Dot (vReflect, vertPos);
		if (RdotE > 0.0f) {
			//spec = pow (Reflect dot lightToEye, matShininess) * matSpecular * lightSpecular
			vertColor += (lightColor * (float) pow (RdotE, vcd.fMatShininess));
			}
		}
	if ((nSaturation < 2) || gameStates.render.bHaveLightmaps) {//sum up color components
		colorSum = colorSum + vertColor * (1.0f / fAttenuation);
		}
	else {	//use max. color components
		vertColor = vertColor * fAttenuation;
		nBrightness = sqri ((int) (vertColor [R] * 1000)) + sqri ((int) (vertColor [G] * 1000)) + sqri ((int) (vertColor [B] * 1000));
		if (nMaxBrightness < nBrightness) {
			nMaxBrightness = nBrightness;
			colorSum = vertColor;
			}
		else if (nMaxBrightness == nBrightness) {
			if (colorSum [R] < vertColor [R])
				colorSum [R] = vertColor [R];
			if (colorSum [G] < vertColor [G])
				colorSum [G] = vertColor [G];
			if (colorSum [B] < vertColor [B])
				colorSum [B] = vertColor [B];
			}
		}
	j++;
	}
if (j) {
	if ((nSaturation == 1) || gameStates.render.bHaveLightmaps) { //if a color component is > 1, cap color components using highest component value
		float	cMax = colorSum [R];
		if (cMax < colorSum [G])
			cMax = colorSum [G];
		if (cMax < colorSum [B])
			cMax = colorSum [B];
		if (cMax > 1) {
			colorSum [R] /= cMax;
			colorSum [G] /= cMax;
			colorSum [B] /= cMax;
			}
		}
	*pColorSum = colorSum;
	}
#if DBG
if (nLights)
	nLights = 0;
#endif
if (!RENDERPATH)
	lightManager.ResetNearestToVertex (nVertex, nThread);
return j;
}