package Current.popups.Deg100; import Current.*; import Current.basic.*; import java.math.*; import java.io.*; public class Deg100Trig { FileWriter FW; public Deg100Trig() {} /************************************************************** The purpose of this class is to define the two functions intervalCos(k,n) and intervalSin(k,n). intervalCos(k,n) is an interval of integers which contains 2^53 cos(pi/2 k/2^n) as long as 0<=n<=20 and k are integers. intervalSin(k,n) is an interval of integers which contains 2^53 sin(pi/2 k/2^n) as long as 0<=n<=20 and k are integers. The sine function is derived from the cosine function. Our method for generating the cosing function is just to take the naturally computed Java cosine, multiply by 2^53, take the floor, then round outward by 4 in each direction. The programs which verify that this method works are at the end of the file. Since we derive the since function from the cosine function, so our proof only needs to check the cosine function */ public static BigInterval intervalCos(int k,int n) { return(new BigInterval(cosLowerApprox(k,n),cosUpperApprox(k,n))); } public static BigInterval intervalSin(int k,int n) { int kk=(int)(Math.pow(2,n))-k; return(intervalCos(kk,n)); } public static BigInteger getBIG() { BigInteger BIG=new BigInteger("9007199254740992"); //2^{53} return(BIG); } /**here's the naturally computed cosine, times 2^53*/ public static BigInteger cosBestApprox(int k,int n) { double d=Math.PI/2.0; d=d*k/Math.pow(2.0,n); d=Math.cos(d); BigDecimal Y1=new BigDecimal(d); BigInteger BIG=getBIG(); BigDecimal Y2=new BigDecimal(BIG); Y1=Y1.multiply(Y2); BigInteger X=Y1.toBigInteger(); return(X); } /**here are our ourward rounds*/ public static BigInteger cosLowerApprox(int k,int n) { int kk=0; kk=k; int RANGE=(int)(Math.pow(2,n+2)); int HALF=(int)(Math.pow(2,n+1)); kk=kk%RANGE; kk=Math.abs(kk); if(kk>HALF) kk=RANGE-kk; BigInteger X=cosBestApprox(kk,n); return(X.subtract(new BigInteger("4"))); } public static BigInteger cosUpperApprox(int k,int n) { int kk=0; kk=k; int RANGE=(int)(Math.pow(2,n+2)); int HALF=(int)(Math.pow(2,n+1)); kk=kk%RANGE; kk=Math.abs(kk); if(kk>HALF) kk=RANGE-kk; BigInteger X=cosBestApprox(kk,n); return(X.add(new BigInteger("4"))); } /**This part if the file is devoted to testing that our cosine function is legitimate in the range of interest to us. Specificaly, this means that. intervalCos(k,n) is an interval of integers which contains 2^53 cos(pi/2 k/2^n) as long as 0<=n<=20 and k are integers We test this essentially by using the 8th and 10th order Taylor series approximations for the above expression, multiplying through by an enormous integer so that we can work exactly with integer series. Our verification implements exact integer arithmetic - arbitrary length*/ /**some useful big integers*/ public static BigInteger getHUGE2() { BigInteger BIG=new BigInteger("2432902008176640000"); //20 Factorial return(BIG); } public static BigInteger getHUGE1() { BigInteger BIG=new BigInteger("286687326998758938951352611912760867599570623646035140467198604923365359511060601008752319138765710819328"); //2^{347} return(BIG); } public static int testCosine(int k) { //the Taylor series version BigInterval I1=new BigInterval(); BigInterval I2=new BigInterval(); if(k<=Math.pow(2,20)) I1=seriesCosine(k); if(k>Math.pow(2,20)) { I1=seriesCosine((int)(Math.pow(2,21))-k); I1=new BigInterval(I1.R.negate(),I1.L.negate()); } //the functions we want to use I2=intervalCos(k,20); I2.L=I2.L.multiply(getHUGE1()); I2.L=I2.L.multiply(getHUGE2()); I2.R=I2.R.multiply(getHUGE1()); I2.R=I2.R.multiply(getHUGE2()); int test1=I2.L.compareTo(I1.L); if(test1!=-1) return(0); int test2=I2.R.compareTo(I1.R); if(test2!=1) return(0); return(1); //means pass } /************************************************** Here is the mathematica code which generates these constants f[k_]:=Floor[Power[Pi/2,k]*Power[2,400-20 k]*20!/k!]; The table below is f[0],f[2],...,f[10] ****************************************************/ public static BigInterval cosSeriesConstant(int k) { BigInterval I=new BigInterval(); if(k==0) I.L=new BigInteger("6282360914011523724751605315928646533647196894905049116691878953798137201964537948184637824942497271820577896930904634208703216237936640000"); if(k==1) I.L=new BigInteger("7049086085107762779991869217012516429873856083348447476281600978302368061621898094476221078394825883611352688608884797332361755"); if(k==2) I.L=new BigInteger("1318230925055508515494436136860366720197786542602645386598139245347239689915799152533101367219199874841883004539723"); if(k==3) I.L=new BigInteger("98607550016670630525252645720074444528094332287908896151235557195192296698516053595825869069565291202"); if(k==4) I.L=new BigInteger("3951500753021148580353469093444178791088810564701614080206054284774028105065594365695813"); if(k==5) I.L=new BigInteger("98527959135343237005208017653247976977470404908342294504205780411881685863"); if(k==6) I.L=new BigInteger("1675041160676921196339481220279220765292188488207204687351672"); if(k==7) I.L=new BigInteger("20653517306775969939320067430838381452820416178"); if(k==8) I.L=new BigInteger("193117979382323170336391434868704"); if(k==9) I.L=new BigInteger("1416254196461936667"); if(k==10) I.L=new BigInteger("8363"); I.R=I.L.add(new BigInteger("1")); return(I); } public static BigInteger cosUpperSeriesConstant(int k) { BigInterval I=cosSeriesConstant(k); if(k%2==1) return(I.L); return(I.R); } public static BigInteger cosLowerSeriesConstant(int k) { BigInterval I=cosSeriesConstant(k); if(k%2==0) return(I.L); return(I.R); } //an integer lower&upper bound for 2^400 20! Cos[(Pi/2) k/2^20)] public static BigInteger seriesCosineUpper(int k) { Integer IK=new Integer(k); BigInteger K=new BigInteger(IK.toString()); BigInteger SUM=new BigInteger("0"); for(int i=0;i<=9;++i) { BigInteger A1=K.pow(2*i); if(i%2==1) A1=A1.negate(); BigInteger A2=cosUpperSeriesConstant(i); BigInteger A3=A1.multiply(A2); SUM=SUM.add(A3); } return(SUM); } public static BigInteger seriesCosineLower(int k) { Integer IK=new Integer(k); BigInteger K=new BigInteger(IK.toString()); BigInteger SUM=new BigInteger("0"); for(int i=0;i<=10;++i) { BigInteger A1=K.pow(2*i); if(i%2==1) A1=A1.negate(); BigInteger A2=cosLowerSeriesConstant(i); BigInteger A3=A1.multiply(A2); SUM=SUM.add(A3); } return(SUM); } public static BigInterval seriesCosine(int k) { BigInterval I=new BigInterval(); I.L=seriesCosineLower(k); I.R=seriesCosineUpper(k); return(I); } }