1 2 #include <../src/sys/classes/draw/utils/axisimpl.h> 3 4 #undef __FUNCT__ 5 #define __FUNCT__ "PetscRint" 6 static PetscErrorCode PetscRint(PetscReal x,PetscReal *result) 7 { 8 PetscFunctionBegin; 9 if (x > 0) *result = floor(x + 0.5); 10 else *result = floor(x - 0.5); 11 PetscFunctionReturn(0); 12 } 13 14 #undef __FUNCT__ 15 #define __FUNCT__ "PetscDrawAxisSetLimits" 16 /*@ 17 PetscDrawAxisSetLimits - Sets the limits (in user coords) of the axis 18 19 Not Collective (ignored on all processors except processor 0 of PetscDrawAxis) 20 21 Input Parameters: 22 + axis - the axis 23 . xmin,xmax - limits in x 24 - ymin,ymax - limits in y 25 26 Level: advanced 27 28 .seealso: PetscDrawAxisSetHoldLimits() 29 30 @*/ 31 PetscErrorCode PetscDrawAxisSetLimits(PetscDrawAxis axis,PetscReal xmin,PetscReal xmax,PetscReal ymin,PetscReal ymax) 32 { 33 PetscFunctionBegin; 34 if (!axis) PetscFunctionReturn(0); 35 if (axis->hold) PetscFunctionReturn(0); 36 axis->xlow = xmin; 37 axis->xhigh= xmax; 38 axis->ylow = ymin; 39 axis->yhigh= ymax; 40 PetscFunctionReturn(0); 41 } 42 43 #undef __FUNCT__ 44 #define __FUNCT__ "PetscDrawAxisGetLimits" 45 /*@ 46 PetscDrawAxisGetLimits - Gets the limits (in user coords) of the axis 47 48 Not Collective (ignored on all processors except processor 0 of PetscDrawAxis) 49 50 Input Parameters: 51 + axis - the axis 52 . xmin,xmax - limits in x 53 - ymin,ymax - limits in y 54 55 Level: advanced 56 57 .seealso: PetscDrawAxisSetLimits() 58 59 @*/ 60 PetscErrorCode PetscDrawAxisGetLimits(PetscDrawAxis axis,PetscReal *xmin,PetscReal *xmax,PetscReal *ymin,PetscReal *ymax) 61 { 62 PetscFunctionBegin; 63 if (!axis) PetscFunctionReturn(0); 64 if (axis->hold) PetscFunctionReturn(0); 65 *xmin = axis->xlow; 66 *xmax = axis->xhigh; 67 *ymin = axis->ylow; 68 *ymax = axis->yhigh; 69 PetscFunctionReturn(0); 70 } 71 72 #undef __FUNCT__ 73 #define __FUNCT__ "PetscADefLabel" 74 /* 75 val is the label value. sep is the separation to the next (or previous) 76 label; this is useful in determining how many significant figures to 77 keep. 78 */ 79 PetscErrorCode PetscADefLabel(PetscReal val,PetscReal sep,char **p) 80 { 81 static char buf[40]; 82 char fmat[10]; 83 PetscErrorCode ierr; 84 int w,d; 85 PetscReal rval; 86 87 PetscFunctionBegin; 88 /* Find the string */ 89 if (PetscAbsReal(val)/sep < 1.e-6) { 90 buf[0] = '0'; buf[1] = 0; 91 } else if (PetscAbsReal(val) < 1.0e6 && PetscAbsReal(val) > 1.e-4) { 92 /* Compute the number of digits */ 93 w = 0; 94 d = 0; 95 if (sep > 0.0) { 96 d = (int)ceil(- log10 (sep)); 97 if (d < 0) d = 0; 98 if (PetscAbsReal(val) < 1.0e-6*sep) { 99 /* This is the case where we are near zero and less than a small 100 fraction of the sep. In this case, we use 0 as the value */ 101 val = 0.0; 102 w = d; 103 } 104 else if (val == 0.0) w = d; 105 else w = (int)(ceil(log10(PetscAbsReal(val))) + d); 106 if (w < 1) w ++; 107 if (val < 0) w ++; 108 } 109 110 ierr = PetscRint(val,&rval);CHKERRQ(ierr); 111 if (rval == val) { 112 if (w > 0) sprintf(fmat,"%%%dd",w); 113 else {ierr = PetscStrcpy(fmat,"%d");CHKERRQ(ierr);} 114 sprintf(buf,fmat,(int)val); 115 ierr = PetscStripInitialZero(buf);CHKERRQ(ierr); 116 ierr = PetscStripAllZeros(buf);CHKERRQ(ierr); 117 ierr = PetscStripTrailingZeros(buf);CHKERRQ(ierr); 118 } else { 119 /* The code used here is inappropriate for a val of 0, which 120 tends to print with an excessive numer of digits. In this 121 case, we should look at the next/previous values and 122 use those widths */ 123 if (w > 0) sprintf(fmat,"%%%d.%dlf",w + 1,d); 124 else {ierr = PetscStrcpy(fmat,"%lf");CHKERRQ(ierr);} 125 sprintf(buf,fmat,(double)val); 126 ierr = PetscStripInitialZero(buf);CHKERRQ(ierr); 127 ierr = PetscStripAllZeros(buf);CHKERRQ(ierr); 128 ierr = PetscStripTrailingZeros(buf);CHKERRQ(ierr); 129 } 130 } else { 131 ierr = PetscSNPrintf(buf,40,"%g",(double)val); 132 /* remove the extraneous 0 before the e */ 133 ierr = PetscStripZeros(buf);CHKERRQ(ierr); 134 ierr = PetscStripZerosPlus(buf);CHKERRQ(ierr); 135 ierr = PetscStripInitialZero(buf);CHKERRQ(ierr); 136 ierr = PetscStripAllZeros(buf);CHKERRQ(ierr); 137 ierr = PetscStripTrailingZeros(buf);CHKERRQ(ierr); 138 } 139 *p =buf; 140 PetscFunctionReturn(0); 141 } 142 143 #undef __FUNCT__ 144 #define __FUNCT__ "PetscADefTicks" 145 /* Finds "nice" locations for the ticks */ 146 PetscErrorCode PetscADefTicks(PetscReal low,PetscReal high,int num,int *ntick,PetscReal * tickloc,int maxtick) 147 { 148 PetscErrorCode ierr; 149 int i,power; 150 PetscReal x = 0.0,base=0.0; 151 152 PetscFunctionBegin; 153 /* patch if low == high */ 154 if (low == high) { 155 low -= .01; 156 high += .01; 157 } 158 159 /* if (PetscAbsReal(low-high) < 1.e-8) { 160 low -= .01; 161 high += .01; 162 } */ 163 164 ierr = PetscAGetBase(low,high,num,&base,&power);CHKERRQ(ierr); 165 ierr = PetscAGetNice(low,base,-1,&x);CHKERRQ(ierr); 166 167 /* Values are of the form j * base */ 168 /* Find the starting value */ 169 if (x < low) x += base; 170 171 i = 0; 172 while (i < maxtick && x <= high) { 173 tickloc[i++] = x; 174 x += base; 175 } 176 *ntick = i; 177 178 if (i < 2 && num < 10) { 179 ierr = PetscADefTicks(low,high,num+1,ntick,tickloc,maxtick);CHKERRQ(ierr); 180 } 181 PetscFunctionReturn(0); 182 } 183 184 #define EPS 1.e-6 185 186 #undef __FUNCT__ 187 #define __FUNCT__ "PetscExp10" 188 PetscErrorCode PetscExp10(PetscReal d,PetscReal *result) 189 { 190 PetscFunctionBegin; 191 *result = pow((PetscReal)10.0,d); 192 PetscFunctionReturn(0); 193 } 194 195 #undef __FUNCT__ 196 #define __FUNCT__ "PetscMod" 197 PetscErrorCode PetscMod(PetscReal x,PetscReal y,PetscReal *result) 198 { 199 int i; 200 201 PetscFunctionBegin; 202 if (y == 1) { 203 *result = 0.0; 204 PetscFunctionReturn(0); 205 } 206 i = ((int)x) / ((int)y); 207 x = x - i * y; 208 while (x > y) x -= y; 209 *result = x; 210 PetscFunctionReturn(0); 211 } 212 213 #undef __FUNCT__ 214 #define __FUNCT__ "PetscCopysign" 215 PetscErrorCode PetscCopysign(PetscReal a,PetscReal b,PetscReal *result) 216 { 217 PetscFunctionBegin; 218 if (b >= 0) *result = a; 219 else *result = -a; 220 PetscFunctionReturn(0); 221 } 222 223 #undef __FUNCT__ 224 #define __FUNCT__ "PetscAGetNice" 225 /* 226 Given a value "in" and a "base", return a nice value. 227 based on "sign", extend up (+1) or down (-1) 228 */ 229 PetscErrorCode PetscAGetNice(PetscReal in,PetscReal base,int sign,PetscReal *result) 230 { 231 PetscReal etmp,s,s2,m; 232 PetscErrorCode ierr; 233 234 PetscFunctionBegin; 235 ierr = PetscCopysign (0.5,(double)sign,&s);CHKERRQ(ierr); 236 etmp = in / base + 0.5 + s; 237 ierr = PetscCopysign (0.5,etmp,&s);CHKERRQ(ierr); 238 ierr = PetscCopysign (EPS * etmp,(double)sign,&s2);CHKERRQ(ierr); 239 etmp = etmp - 0.5 + s - s2; 240 ierr = PetscMod(etmp,1.0,&m);CHKERRQ(ierr); 241 etmp = base * (etmp - m); 242 *result = etmp; 243 PetscFunctionReturn(0); 244 } 245 246 #undef __FUNCT__ 247 #define __FUNCT__ "PetscAGetBase" 248 PetscErrorCode PetscAGetBase(PetscReal vmin,PetscReal vmax,int num,PetscReal*Base,int*power) 249 { 250 PetscReal base,ftemp,e10; 251 static PetscReal base_try[5] = {10.0,5.0,2.0,1.0,0.5}; 252 PetscErrorCode ierr; 253 int i; 254 255 PetscFunctionBegin; 256 /* labels of the form n * BASE */ 257 /* get an approximate value for BASE */ 258 base = (vmax - vmin) / (double)(num + 1); 259 260 /* make it of form m x 10^power, m in [1.0, 10) */ 261 if (base <= 0.0) { 262 base = PetscAbsReal(vmin); 263 if (base < 1.0) base = 1.0; 264 } 265 ftemp = log10((1.0 + EPS) * base); 266 if (ftemp < 0.0) ftemp -= 1.0; 267 *power = (int)ftemp; 268 ierr = PetscExp10((double)- *power,&e10);CHKERRQ(ierr); 269 base = base * e10; 270 if (base < 1.0) base = 1.0; 271 /* now reduce it to one of 1, 2, or 5 */ 272 for (i=1; i<5; i++) { 273 if (base >= base_try[i]) { 274 ierr = PetscExp10((double)*power,&e10);CHKERRQ(ierr); 275 base = base_try[i-1] * e10; 276 if (i == 1) *power = *power + 1; 277 break; 278 } 279 } 280 *Base = base; 281 PetscFunctionReturn(0); 282 } 283 284 285 286 287 288 289