//This function takes a noise function onto a "nearby" (in terms of function distance) noise function. //Given the noise function, its dimension, its bounds, a uniform distribution of perturbation [-amt, amt], the fraction of points to be perturbed, and the amount of saturation to apply on renormalization. //The exact bound is extremely difficult to calculate, but for saturation = 1, assuming fraction * number of samples is an integer, and assuming no sample is taken out of bounds, the maximum change to the integral over the unit hypercube is fraction * amt. void perturb_noise_sum(noise_sum* n, unsigned dimension, float n0, float n1, float amt, float fraction, float saturation) { assert(n0 <= n1); unsigned ncount = upow(n->n.count, dimension); unsigned perturbCt = uceilf(ncount * fraction + 1.0 - EPSILON); for(unsigned i = 0; i < perturbCt; i++) { unsigned idx = uniformNatural(ncount); //This check should never be violated. However, we may want to be more tolerant in the future: if this is violated for good reasons, we may want to remove the check. assert(n->n.values[idx] >= n0 && n->n.values[idx] <= n1); n->n.values[idx] = n->n.values[idx] + uniformFloatS(amt); } //Apply some blur blur_noise(&n->n, dimension, 0.25); //Convert to 1d noise. unsigned ocount = n->n.count; n->n.count = ncount; //Normalize noise_rescale_out(&n->n, n0, n1); //Saturate noise_saturate(&n->n, saturation); //Convert back to d dimensional noise. n->n.count = ocount; }
void prepare() { for (int d = 2; d <= 4; ++d) for (int i = 1; i <= MAXN; ++i) S[d][i] = S[d][i - 1] + upow(i, d); for (int i = 1; i <= MAXN; ++i) A[1][i] = A[1][i - 1] + i; for (int d = 2; d <= 4; ++d) for (int i = 1; i <= MAXN; ++i) { A[d][i] = A[d - 1][i] * A[1][i]; R[d][i] = A[d][i] - S[d][i]; } }
//Randomly selects half the pixels (with replacement) and blurs them evenly with their neighbors. Note: this function is lagely subsumed by convolution. void blur_noise(noise* n, unsigned dimension, float fraction) { assert(dimension == 2); //TODO hardcoded for dimension 2. Make this generic. assert(!(n->count & 1)); //No odd noise functions. unsigned totalCount = upow(n->count, dimension); unsigned numToBlur = uroundf(fraction * totalCount); for(unsigned i = 0; i < numToBlur; i++) { unsigned x = uniformNatural(n->count); unsigned y = uniformNatural(n->count); *noise_2d_value(n, x, y) = ( *noise_2d_value(n, x, y) + *noise_2d_value(n, x + 1, y) + *noise_2d_value(n, x, y + 1) + *noise_2d_value(n, x - 1, y) + *noise_2d_value(n, x, y - 1) ) / 5; } }
double upow(double x, double y) { double z,a,aa,error, t,a1,a2,y1,y2,gor=1.0; mynumber u,v; int k; int4 qx,qy; v.x=y; u.x=x; if (y==0.0) return 1.0; if (x==1.0) return 1.0; if (v.i[LOW_HALF] == 0) { /* of y */ qx = u.i[HIGH_HALF]&0x7fffffff; /* Checking if x is not too small to compute */ if (((qx==0x7ff00000)&&(u.i[LOW_HALF]!=0))||(qx>0x7ff00000)) return NaNQ.x; if (y == 1.0) return x; if (y == 2.0) return x*x; if ((y == -1.0) && (x!=0)) return 1.0/x; } /* else */ if(((u.i[HIGH_HALF]>0 && u.i[HIGH_HALF]<0x7ff00000)|| /* x>0 and not x->0 */ (u.i[HIGH_HALF]==0 && u.i[LOW_HALF]!=0)) && /* 2^-1023< x<= 2^-1023 * 0x1.0000ffffffff */ (v.i[HIGH_HALF]&0x7fffffff) < 0x4ff00000) { /* if y<-1 or y>1 */ z = logg1(x,&aa,&error); /* x^y =e^(y log (X)) */ t = y*134217729.0; y1 = t - (t-y); y2 = y - y1; t = z*134217729.0; a1 = t - (t-z); a2 = (z - a1)+aa; a = y1*a1; aa = y2*a1 + y*a2; a1 = a+aa; a2 = (a-a1)+aa; error = error*ABS(y); t = exp1(a1,a2,1.9e16*error); /* return -10 or 0 if wasn't computed exactly */ return (t>0)?t:power1(x,y); } if (x == 0.0) { /*if (ABS(y) > 1.0e20) return (y>0)?0:NaNQ.x;*/ k = checkint(y); if (y < 0.0 ) return ((k==-1) && (u.i[HIGH_HALF]==0x80000000))? -INF.x:INF.x; /* y>0 */ else return (k==-1)?x:0; /* return signed 0 */ } qx = u.i[HIGH_HALF]&0x7fffffff; /* no sign */ qy = v.i[HIGH_HALF]&0x7fffffff; /* no sign */ if (qx > 0x7ff00000 || (qx == 0x7ff00000 && u.i[LOW_HALF] != 0)) return NaNQ.x; if (qy > 0x7ff00000 || (qy == 0x7ff00000 && v.i[LOW_HALF] != 0)) return NaNQ.x; /* if x<0 */ if (u.i[HIGH_HALF] < 0) { if ((x==-1.0) && (qy == 0x7ff00000)) return 1.0; k = checkint(y); if (k==0) return NaNQ.x; /* y not integer and x<0 */ return (k==1)?upow(-x,y):-upow(-x,y); /* if y even or odd */ } /* x>0 */ if (qx == 0x7ff00000) return (y>0)?x:0; if (y>0) return (x>1.0)?INF.x:0; if (y<0) return (x<1.0)?INF.x:0; return 0; /* unreachable, to make the compiler happy */ }