// bivariate power polynomial entry point public static projUV bpseval(projUV @in, Tseries T) { projUV @out; @[email protected]=0.0; for(int i=T.mu; i>=0; --i) { double row=0.0; int m=T.cu[i].m; if(m!=0) { int c=m; while((m--)!=0) row=T.cu[i].c[--c][email protected]*row; } @[email protected]*@out.u; } for(int i=T.mv; i>=0; --i) { double row=0.0; int m=T.cv[i].m; if(m!=0) { int c=m; while((m--)!=0) row=T.cv[i].c[--c][email protected]*row; } @[email protected]*@out.v; } return @out; }
// general entry point selecting evaluation mode public static projUV biveval(projUV @in, Tseries T) { if (T.power != 0) { return(bpseval(@in, T)); } return(bcheval(@in, T)); }
public static void p_series(Tseries T, TextWriter file, string fmt) { const int CUT = 60; // check length of line string format = " {0:" + fmt + "}%n"; file.WriteLine("u: {0}", T.mu + 1); for (int i = 0; i <= T.mu; i++) { if (T.cu[i].m != 0) { string tmp = string.Format("{0} {1}", i, T.cu[i].m); file.Write(tmp); int L = tmp.Length; int n = 0; for (int j = 0; j < T.cu[i].m; j++) { L += n; if (L > CUT) { file.Write("\n "); L = 1; } tmp = string.Format(format, T.cu[i].c[j]); file.Write(tmp); n = tmp.Length; } file.WriteLine(); } } file.WriteLine("v: {0}", T.mv + 1); for (int i = 0; i <= T.mv; i++) { if (T.cv[i].m != 0) { string tmp = string.Format("{0} {1}", i, T.cv[i].m); file.Write(tmp); int L = tmp.Length; int n = 0; for (int j = 0; j < T.cv[i].m; j++) { L += n; if (L > CUT) { file.Write("\n "); L = 1; } tmp = string.Format(format, T.cv[i].c[j]); file.Write(tmp); n = tmp.Length; } file.WriteLine(); } } }
public static void p_series(Tseries T, TextWriter file, string fmt) { const int CUT=60; // check length of line string format=" {0:"+fmt+"}%n"; file.WriteLine("u: {0}", T.mu+1); for(int i=0; i<=T.mu; i++) { if(T.cu[i].m!=0) { string tmp=string.Format("{0} {1}", i, T.cu[i].m); file.Write(tmp); int L=tmp.Length; int n=0; for(int j=0; j<T.cu[i].m; j++) { L+=n; if(L>CUT) { file.Write("\n "); L=1; } tmp=string.Format(format, T.cu[i].c[j]); file.Write(tmp); n=tmp.Length; } file.WriteLine(); } } file.WriteLine("v: {0}", T.mv+1); for(int i=0; i<=T.mv; i++) { if(T.cv[i].m!=0) { string tmp=string.Format("{0} {1}", i, T.cv[i].m); file.Write(tmp); int L=tmp.Length; int n=0; for(int j=0; j<T.cv[i].m; j++) { L+=n; if(L>CUT) { file.Write("\n "); L=1; } tmp=string.Format(format, T.cv[i].c[j]); file.Write(tmp); n=tmp.Length; } file.WriteLine(); } } }
// create power series structure static Tseries makeT(int nru, int nrv) { try { Tseries T = new Tseries(); T.cu = new PW_COEF[nru]; T.cv = new PW_COEF[nrv]; for (int i = 0; i < nru; i++) { T.cu[i].c = null; } for (int i = 0; i < nrv; i++) { T.cv[i].c = null; } return(T); } catch { return(null); } }
// bivariate power polynomial entry point public static projUV bpseval(projUV @in, Tseries T) { projUV @out; @out.u = @out.v = 0.0; for (int i = T.mu; i >= 0; --i) { double row = 0.0; int m = T.cu[i].m; if (m != 0) { int c = m; while ((m--) != 0) { row = T.cu[i].c[--c] + @in.v * row; } } @out.u = row + @in.u * @out.u; } for (int i = T.mv; i >= 0; --i) { double row = 0.0; int m = T.cv[i].m; if (m != 0) { int c = m; while ((m--) != 0) { row = T.cv[i].c[--c] + @in.v * row; } } @out.v = row + @in.u * @out.v; } return(@out); }
// bivariate Chebyshev polynomial entry point public static projUV bcheval(projUV @in, Tseries T) { projUV w2, w, @out; // scale to +-1 w.u=(@[email protected])*T.b.u; w.v=(@[email protected])*T.b.v; if(Math.Abs(w.u)>NEAR_ONE||Math.Abs(w.v)>NEAR_ONE) { @[email protected]=Libc.HUGE_VAL; Proj.pj_errno=-36; } else { // double evaluation w2.u=w.u+w.u; w2.v=w.v+w.v; @out.u=ceval(T.cu, T.mu, w, w2); @out.v=ceval(T.cv, T.mv, w, w2); } return @out; }
// bivariate Chebyshev polynomial entry point public static projUV bcheval(projUV @in, Tseries T) { projUV w2, w, @out; // scale to +-1 w.u = (@in.u + @in.u - T.a.u) * T.b.u; w.v = (@in.v + @in.v - T.a.v) * T.b.v; if (Math.Abs(w.u) > NEAR_ONE || Math.Abs(w.v) > NEAR_ONE) { @out.u = @out.v = Libc.HUGE_VAL; Proj.pj_errno = -36; } else { // double evaluation w2.u = w.u + w.u; w2.v = w.v + w.v; @out.u = ceval(T.cu, T.mu, w, w2); @out.v = ceval(T.cv, T.mv, w, w2); } return(@out); }
// general entry point selecting evaluation mode public static projUV biveval(projUV @in, Tseries T) { if(T.power!=0) return bpseval(@in, T); return bcheval(@in, T); }
public static Tseries mk_cheby(projUV a, projUV b, double res, ref projUV resid, ProjFunc func, int nu, int nv, bool power) { try { projUV[][] w = new projUV[nu][]; for (int k = 0; k < nu; k++) { w[k] = new projUV[nv]; } if (bchgen(a, b, nu, nv, w, func)) { return(null); } // analyse coefficients and adjust until residual OK double cutres = res; int i = 4; for (; i > 0; i--) { eval(w, nu, nv, cutres, ref resid); if (resid.u < res && resid.v < res) { break; } cutres *= 0.5; } // warn of too many tries if (i <= 0) { resid.u = -resid.u; } double ab; double[] p; int[] ncu = new int[nu]; int[] ncv = new int[nv]; // apply cut resolution and set pointers int nru = 0, nrv = 0; for (int j = 0; j < nu; ++j) { ncu[j] = ncv[j] = 0; // clear column maxes projUV[] s = w[j]; for (i = 0; i < nv; i++) { // < resolution ? ab = Math.Abs(s[i].u); if (ab < cutres) { s[i].u = 0.0; // clear coefficient } else { ncu[j] = i + 1; // update column max } ab = Math.Abs(s[i].v); if (ab < cutres) { s[i].v = 0.0; // same for v coef's } else { ncv[j] = i + 1; } } if (ncu[j] != 0) { nru = j + 1; // update row max } if (ncv[j] != 0) { nrv = j + 1; } } if (power) { // convert to bivariate power series if (!bch2bps(a, b, w, nu, nv)) { return(null); } // possible change in some row counts, so readjust nru = nrv = 0; for (int j = 0; j < nu; ++j) { ncu[j] = ncv[j] = 0; // clear column maxes projUV[] s = w[j]; for (i = 0; i < nv; i++) { if (s[i].u != 0) { ncu[j] = i + 1; // update column max } if (s[i].v != 0) { ncv[j] = i + 1; } } if (ncu[j] != 0) { nru = j + 1; // update row max } if (ncv[j] != 0) { nrv = j + 1; } } Tseries T = makeT(nru, nrv); if (T != null) { T.a = a; T.b = b; T.mu = nru - 1; T.mv = nrv - 1; T.power = 1; for (i = 0; i < nru; ++i) // store coefficient rows for u { T.cu[i].m = ncu[i]; if (T.cu[i].m != 0) { p = T.cu[i].c = new double[ncu[i]]; projUV[] s = w[i]; for (int j = 0; j < ncu[i]; j++) { p[j] = s[j].u; } } } for (i = 0; i < nrv; ++i) // same for v { T.cv[i].m = ncv[i]; if (T.cv[i].m != 0) { p = T.cv[i].c = new double[ncv[i]]; projUV[] s = w[i]; for (int j = 0; j < ncv[i]; j++) { p[j] = s[j].v; } } } } return(T); } else { Tseries T = makeT(nru, nrv); if (T != null) { // else make returned Chebyshev coefficient structure T.mu = nru - 1; // save row degree T.mv = nrv - 1; T.a.u = a.u + b.u; // set argument scaling T.a.v = a.v + b.v; T.b.u = 1.0 / (b.u - a.u); T.b.v = 1.0 / (b.v - a.v); T.power = 0; for (i = 0; i < nru; ++i) // store coefficient rows for u { T.cu[i].m = ncu[i]; if (T.cu[i].m != 0) { p = T.cu[i].c = new double[ncu[i]]; projUV[] s = w[i]; for (int j = 0; j < ncu[i]; j++) { p[j] = s[j].u; } } } for (i = 0; i < nrv; ++i) // same for v { T.cv[i].m = ncv[i]; if (T.cv[i].m != 0) { p = T.cv[i].c = new double[ncv[i]]; projUV[] s = w[i]; for (int j = 0; j < ncv[i]; j++) { p[j] = s[j].v; } } } } return(T); } } catch { return(null); } }
// create power series structure static Tseries makeT(int nru, int nrv) { try { Tseries T=new Tseries(); T.cu=new PW_COEF[nru]; T.cv=new PW_COEF[nrv]; for(int i=0; i<nru; i++) T.cu[i].c=null; for(int i=0; i<nrv; i++) T.cv[i].c=null; return T; } catch { return null; } }
public static void gen_cheb(bool inverse, ProjFunc proj, string s, PJ P, int iargc, string[] iargv) { InputFunc input = Proj.dmstor; if (inverse) { input = Libc.strtod; } int errin = 0; projUV low, upp; low.u = low.v = upp.u = upp.v = 0; if (s.Length > 0) { low.u = input(s, out s); } else { errin++; } if (s.Length > 1 && s[0] == ',') { upp.u = input(s.Substring(1), out s); } else { errin++; } if (s.Length > 1 && s[0] == ',') { low.v = input(s.Substring(1), out s); } else { errin++; } if (s.Length > 1 && s[0] == ',') { upp.v = input(s.Substring(1), out s); } else { errin++; } if (errin != 0) { emess(16, "null or absent -T parameters"); } int NU = 15, NV = 15, res = -1; if (s.Length > 1 && s[0] == ',') { s = s.Substring(1); if (s[0] != ',') { res = Libc.strtol(s, out s, 10); } } if (s.Length > 1 && s[0] == ',') { s = s.Substring(1); if (s[0] != ',') { NU = Libc.strtol(s, out s, 10); } } if (s.Length > 1 && s[0] == ',') { s = s.Substring(1); if (s[0] != ',') { NV = Libc.strtol(s, out s, 10); } } bool pwr = s.Length > 0 && s.StartsWith(",P"); Console.WriteLine("#proj_{0}\n#\trun-line:", pwr?"Power":"Chebyshev"); // proj execution audit trail if (iargc > 0) { int n = 0; for (int i = 0; i < iargc; i++) { string arg = iargv[i]; if (arg[0] != '+') { if (n == 0) { Console.Write("#"); n++; } Console.Write(" " + arg); n += arg.Length + 1; if (n > 50) { Console.WriteLine(); n = 0; } } } if (n != 0) { Console.WriteLine(); } } Console.WriteLine("# projection parameters"); Console.WriteLine("#" + P.DescriptionName); Console.WriteLine("#" + P.DescriptionParameters); Console.WriteLine("#" + P.DescriptionType); Console.WriteLine("#" + P.ToProj4String()); if (low.u == upp.u || low.v >= upp.v) { emess(16, "approx. argument range error"); } if (low.u > upp.u) { low.u -= Proj.TWOPI; } if (NU < 2 || NV < 2) { emess(16, "approx. work dimensions ({0} {1}) too small", NU, NV); } projUV resid = new projUV(); Tseries F = mk_cheby(low, upp, Math.Pow(10.0, res) * 0.5, ref resid, proj, NU, NV, pwr); if (F == null) { emess(16, "generation of approx failed\nreason: {0}\n", Proj.pj_strerrno(Libc.errno)); } Console.WriteLine("{0},{1:G12},{2:G12},{3:G12},{4:G12},{5:G12}", inverse?'I':'F', P.lam0 * Proj.RAD_TO_DEG, low.u * (inverse?1.0:Proj.RAD_TO_DEG), upp.u * (inverse?1.0:Proj.RAD_TO_DEG), low.v * (inverse?1.0:Proj.RAD_TO_DEG), upp.v * (inverse?1.0:Proj.RAD_TO_DEG)); string fmt; if (pwr) { fmt = "G15"; } else if (res <= 0) { fmt = string.Format("F{0}", -res + 1); } else { fmt = "F0"; } p_series(F, Console.Out, fmt); Console.WriteLine("# |u,v| sums {0} {1}\n#end_proj_{2}", resid.u, resid.v, pwr?"Power":"Chebyshev"); }