From 7ad342b85ca22f506f4f39f0b1265b2ee8f29596 Mon Sep 17 00:00:00 2001 From: Gatecraft Date: Thu, 14 Jul 2016 23:08:50 +0200 Subject: [PATCH] Update --- res/font_big.ttf | Bin 0 -> 18280 bytes res/font_small.ttf | Bin 0 -> 17784 bytes res/skin.png | Bin 0 -> 1441 bytes res/skin.xcf | Bin 0 -> 8128 bytes src/com/rits/cloning/Cloner.java | 613 ++++++++++++++ src/com/rits/cloning/CloningException.java | 20 + src/com/rits/cloning/FastClonerArrayList.java | 25 + src/com/rits/cloning/FastClonerCalendar.java | 22 + .../cloning/FastClonerConcurrentHashMap.java | 26 + .../cloning/FastClonerCustomCollection.java | 26 + src/com/rits/cloning/FastClonerCustomMap.java | 28 + src/com/rits/cloning/FastClonerHashMap.java | 26 + src/com/rits/cloning/FastClonerHashSet.java | 24 + .../rits/cloning/FastClonerLinkedList.java | 24 + src/com/rits/cloning/FastClonerTreeMap.java | 25 + src/com/rits/cloning/IDeepCloner.java | 20 + src/com/rits/cloning/IDumpCloned.java | 14 + src/com/rits/cloning/IFastCloner.java | 14 + src/com/rits/cloning/IFreezable.java | 12 + .../rits/cloning/IInstantiationStrategy.java | 11 + src/com/rits/cloning/Immutable.java | 25 + .../ObjenesisInstantiationStrategy.java | 26 + src/com/rits/perspectives/Perspectives.java | 73 ++ src/org/nevec/rjm/NumeroAvanzato.java | 744 +++++++++++++++++ src/org/nevec/rjm/NumeroAvanzatoVec.java | 752 ++++++++++++++++++ src/org/warp/engine/lwjgl/Display.java | 696 ++++++++++++++++ src/org/warp/engine/lwjgl/GLFWUtil.java | 47 ++ src/org/warp/engine/lwjgl/IOUtil.java | 69 ++ src/org/warp/engine/lwjgl/Screen.java | 23 + src/org/warpgate/pi/calculator/BMPFile.java | 212 +++++ src/org/warpgate/pi/calculator/Equazione.java | 46 ++ src/org/warpgate/pi/calculator/Incognita.java | 42 + src/org/warpgate/pi/calculator/Incognite.java | 388 +++++++++ src/org/warpgate/pi/calculator/Keyboard.java | 6 + .../warpgate/pi/calculator/ParteSistema.java | 63 ++ .../warpgate/pi/calculator/Sottrazione.java | 22 + src/org/warpgate/pi/calculator/Tecnica.java | 9 + .../pi/calculator/screens/EmptyScreen.java | 29 + .../pi/calculator/screens/EquationScreen.java | 203 +++++ 39 files changed, 4405 insertions(+) create mode 100644 res/font_big.ttf create mode 100644 res/font_small.ttf create mode 100644 res/skin.png create mode 100644 res/skin.xcf create mode 100644 src/com/rits/cloning/Cloner.java create mode 100644 src/com/rits/cloning/CloningException.java create mode 100644 src/com/rits/cloning/FastClonerArrayList.java create mode 100644 src/com/rits/cloning/FastClonerCalendar.java create mode 100644 src/com/rits/cloning/FastClonerConcurrentHashMap.java create mode 100644 src/com/rits/cloning/FastClonerCustomCollection.java create mode 100644 src/com/rits/cloning/FastClonerCustomMap.java create mode 100644 src/com/rits/cloning/FastClonerHashMap.java create mode 100644 src/com/rits/cloning/FastClonerHashSet.java create mode 100644 src/com/rits/cloning/FastClonerLinkedList.java create mode 100644 src/com/rits/cloning/FastClonerTreeMap.java create mode 100644 src/com/rits/cloning/IDeepCloner.java create mode 100644 src/com/rits/cloning/IDumpCloned.java create mode 100644 src/com/rits/cloning/IFastCloner.java create mode 100644 src/com/rits/cloning/IFreezable.java create mode 100644 src/com/rits/cloning/IInstantiationStrategy.java create mode 100644 src/com/rits/cloning/Immutable.java create mode 100644 src/com/rits/cloning/ObjenesisInstantiationStrategy.java create mode 100644 src/com/rits/perspectives/Perspectives.java create mode 100644 src/org/nevec/rjm/NumeroAvanzato.java create mode 100644 src/org/nevec/rjm/NumeroAvanzatoVec.java create mode 100644 src/org/warp/engine/lwjgl/Display.java create mode 100644 src/org/warp/engine/lwjgl/GLFWUtil.java create mode 100644 src/org/warp/engine/lwjgl/IOUtil.java create mode 100644 src/org/warp/engine/lwjgl/Screen.java create mode 100644 src/org/warpgate/pi/calculator/BMPFile.java create mode 100644 src/org/warpgate/pi/calculator/Equazione.java create mode 100644 src/org/warpgate/pi/calculator/Incognita.java create mode 100644 src/org/warpgate/pi/calculator/Incognite.java create mode 100644 src/org/warpgate/pi/calculator/Keyboard.java create mode 100644 src/org/warpgate/pi/calculator/ParteSistema.java create mode 100644 src/org/warpgate/pi/calculator/Sottrazione.java create mode 100644 src/org/warpgate/pi/calculator/Tecnica.java create mode 100644 src/org/warpgate/pi/calculator/screens/EmptyScreen.java create mode 100644 src/org/warpgate/pi/calculator/screens/EquationScreen.java diff --git a/res/font_big.ttf b/res/font_big.ttf new file mode 100644 index 0000000000000000000000000000000000000000..3121e7f1a838e2b5818ec212f36d08874ed3600b GIT binary patch literal 18280 zcmeHPdyr;DbwBss?=iEpGrP01-wylumYp4zWf_Fo`SxRh*@4UQQo%GSIDJ0pRJ42hFS-h1}h=f7p!i#H64oO2#(SDka_S!c^4 zS&ir8@VxqM?>u4Z=Ks0sZ$yF}c)oDk?%93I<-5B@O1n_^{%r^LuaULkO(Nyz@V<1# z>^1x5<^&kdISS8xSM0j(@^f#yvm{bIQ)J8aJ1(2u-uKLHHN5*Nt`m2lqOv+dIbi#v zcI@7NaLK^HGk8u!!UuNk-8TEzXFl;f;Iqv|yJrvXlS6U?%5OybHG5`vU$*X{_cTS$ zK>OgneS5Fj|8Ez(`x7E(k-onqCA_|K!bNwzXVI2l$N)$|`oRtN62H&q;xLK$*e4+~ zB=m`7E|!a}eV8aDduR9iwdQ_#yMTL0>=|fXEXQk25Zo2~T*`R$x$p_peBAQjC(;P| z*`cCHwQVFpX{(lSo7%tsa*1WlBxw-27|jw?b1cjb$Xd-WKsnZGr@2G9aIp{SW4(O6 zwB_2KZ3_LmmDx}G#vVtSC#^WU_0=hG^Jw>KZN$S!bF}wk%xO!|CPuyM#HV$5rSv4N z?<0{ojIB=dly9*(JjXV-a*SsIUgo&imu-tM z(z=xHFhO5`rENWpt@DUBDc)YW^3UTWd>tq77u%A${rpNEO2#S~OPfv*TiKCfcJ%cxYYRQviD3@jWRTC{k0$;i^$ve6@! zuUNUNzWT^DV{6BcT6gsNV>TQ+aoih@KVfp?RAW=~#LXw2e9H8enNv@TPv3e*5ngK< zHuM~M->yCT4u0?>H~qoQAG_t&+wb`JCqDVUCxdSW&j$Y) zR>Gy>RJc8K;bY;U=;-L8=#J>o=um00bav_D(v78iOHY;#l{b}lmG3G4uu`fVUwLcg zmdYcQ?^Rx`PF3Gp{ZRFx>N9U32898y}!jXd`pB;I0X=&++OK)8IRPE^6!P^P< zPmaEF#3@G{IO2gLo?gCi`I*ZPEdT2Ae_gR^#ikYKt=PBX))h~!3|CIAymaLkRz9<8 z*{YLPZC`cks;{kjzP_w}e*MP!WAztSFI#=;>Qf<6YawG(;eC+ZsvQ4tASY~jq*{`n zO+8#GKfUFVC`3^nj#yo0^&{0v@Y0q?AdWwqY7CDJuWt;GuMHNz@Wd10eJ@|QHoTlt z>M(0b7z5^rNTb=Pt)Hnh>J=9=*6%F zy#rytGh>BaSR}? z7?qWZsW}lery~H}%rQ=c&FK&|jm?ePL!gV5!M+ITB-% zF&)Af;6+**);n&snGoz@0X%sn$$_C1=+m4qbG#ur9ZZfV0-m~z$vW8}ZvY;S0<>cY z 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 literal 0 HcmV?d00001 diff --git a/res/font_small.ttf b/res/font_small.ttf new file mode 100644 index 0000000000000000000000000000000000000000..07eb5543179ac751b1011fd5737c878fbf4af6d1 GIT binary patch literal 17784 zcmeHPdvG1qdH;6z-YdzrY|HYs{Llr;3@opS;1d4#WL= z+#hz3^>HOOaq3?l*4UF}Ztzd~1hDX*>F^*}QMhVp$U2C{lh2&r6q0UbTB_ zN`T?i)wu7zZ2Q%h-m&{XFB9oHMP%KcZCfX|bbtSrr||3*eAaA3N9C{x?O-YHmu}m! zXMf)}XDq>eA`(8deb?s6YahP(p8%g@F4!@-f496T*P(p|#xLGExnt|T`CpwTa?<1I z`>Wl%uG;hO=U;TY$jR5@{!d8>KTA%zcklaWt^bKkFQG%^yVu?KxA}D{4wHzt-4gPG z19KvoiseEZA0`UPp4s_9?RiknmR{}P%s~5MS)n~aa98kSDT9yChR>kq6Lt-LB=w*N zy;4!6IyRD^v_V@qt=hBaQi)~pC}|M65W^C5lNVn0$r8Puk9MrxPOlE_!iRIv?=US+ z`^7&`ui78y&(m?uSB}>?vB!~KlSZ7)^Yk85+xEMkvOk5BUNPVEnA4U3W{iH<3S0Z| zh+?F56={kfqcFBUy;3Ijak!67xsavF)1`AU&-sta811{U;skY1FwXF7ViR54hPg-&Xl~oP@7@HjPXB!nk!l;o*7APX;@| zIDAT?2goNoGU)Ah5AKL+5Cbm2b&kwNPbinj@5nI7`TP_QJd8@^N>_K!wCOW?XU>}4 zH>ZDYb>6`I1q&Aq)($&-@z9dtrOS>OIr6BZmml-46~~UQTvcB^wr1^d$FCb-KXJl| z@ktv_F2ZYUBZi(XAKbok_x=xm?8e`_>Ek!wa@!|Aar+&g{?zZ^`I*ms_76UP*B9=& z_lxoyzxJN90gGJ7nlw1Gs(s!SCKicPRk~1#*0AiUPcgvSW zzM}1malZVDZCCEvvv=QB*L+B>zV4$AT^sRvKR!4#F3ZvWCx(RYkiU^Pf;GVz!KUEa z;IZJ@;DzAz;6OMSo)K;eKOH_Dz8)=(&W`p(4@J*Mua_#N(bD@$`%CwgUM$ZjuPbjW z-%)xNlR&z?E^oY{BHes=bo zeMk0f>ib;ZlYIx~teLZM&i*-{ne%vmseeuX4gJr}J!0upyKCOF^9~HG8`wAS(7+4xXUsok{=WJ5&;Q|q!3C=qym!Iw1-C4CZeh4^)xu2+ z?_T)*Me`ONw`j|vTNZt7(aVGL2G1M3VepB;*J|@>>uT#@QA=QBtHK9hyIr#4(Ljz} z|5#T^US0KQrToJB$D$BTc{E~onca_dRf4zHKL&GrbydA@sBfg+H@qa6{n|6ngb%#E zaY=Y7t<*tl3H&HxPN|R8t0NOpy%xEchn>;DAUYS54g8Gwd!=8bALEDdSvwKbYr*mW zm#T{s%)`t;Fflv4M+7nE56cK}O$5WWU>N7I`WQY6!k??dRRFF9BV)tWBm;4<21b#_ zGEa(QI%oY>WX3aN#q85#*V&1Evz+^z$z*~gR zfQRQ&bpGn$a~k|sc_M9n@CaBcEgxPGsH+c|%GRo1Bs$;ZV{H$xcu8Uf30grkVh8D= zHBN+(HmtDJs(enzBxFfXO9WczIW<_d+Lv)czUnkzS`a_xt_AZg5JD!C!abY0e>zBQ zx?))b{~XD&DCg8Ejbp8gB=)rxH#lMOAo94 z>O(~o2G142YCE;xkVs(X4pDfKdJja5NH|_XnAb>8@o0W%gyC&fI{^Y7l-Vn@47E2b z%Uh&D>oB9G_Mpr0prZ-X-IGSF>0LoCWoR+;57_e&8sat=!i6)l4Zz`F$D5scJ)!DVJxOty6`fRAc2h+W1?knm^IyzABu)_ z^OJa#?JkBN*zp5O2Sk?n$U+-zidZ=Sr_851YeP>FKWP{#(3XQ~ZGoONR^&W-AG7?% zATdDhm|M+vK@HTwb9y+X4`)4G46t6`4zlZkzK@c+@fy*70?kE3@ZxYB(H;?vsR>oW zc$8Twpk-|jxbp=gbDY#IYm&5DSRT?X5GKY$h6|>^G>0`}NLmr31Bx-I2izcLAZ-C~ zeE?jPQTDJzgWrvZRS2pWh+2U*_rQ~Js82JN&O*E%!abzk?mPl-( z-F8YS6xh3m-D|OkH6Tb0YS91`Q6|Ag@^EW`Rsfba0WO1yETI6hn=sxghHg3G71 zYmu}J7NXh8MmS-+Ilhn6@>m*zrS8!)>cg7UJ}O1;Z$US$wk)P^_{fW*gs(e7~2>Wg}c zR8M9zO%#K8HJzf#bbzYefZI*rg;>W`23K8(sr223h=*JOMbevXiJ*QBTuy;C#6I>V z+O28BH_@T!GMx0ki4qGAgsY%dayF&u%;CB3b)h!=cXHMXnYFz! zB#@7znDCn(g=X4?Yql0N_{EhV@c8w&;emS6T*?}Rf~6LR&~G-8q-p`GoFyVdM}8D} zvPz3JB6tD=EDa5^;%qOZ6pezU{&F8?m0x9Cuv&}7cVX?rssp7ns6CX!$2`RH1e!FP zn5ZCegDTxBHgd|=!KeW&%}FT@EI_fwRHF`S71x0cPXktx zF=)^0S@k+bkK)?CQFjg05RT7@!WuTKU>ioojPn@A`cL;Zm|U#3SNhVysayo(Xv^H^ zf!^tB!Pv@7GFH)BZ_+_!aLy*?*bj=|d#UO~HKURy6qkWY z8(9zK1KVSS^StXGULPf_T+#kCq-nfz7PV}_L13H@+2J4$ln8iW$cZp7#im#8k|_OC ziN;e}RUfJZSo#1qtXN)DDRw$2oQ9!*3puraO!Y^h1kxVL#`$Nwl9DtQQkRD_8_>s5 zxnRYj#iR+!@7>hY5bQaja42p88WxYsUldUShViBu9tYk4y|~urDsluEplx8V zC<*6cVbaBG!3tmv={|5SXUC?V6jj3sC^eQ6uh7$%VNnU$m1;$@{S=Jt1@96jA^osO z<1pktE+@(9@*eXUQcKFXdLQy_MljtstJcdfmJ*4tRTvPkLc%i*5Hz0<^?ytyCv?;- z9vpB=2+pYu>wPGCiQ~5u-{^dCARml^12BMCrTes9W8>wZd2S>z#xjRH)rq|c@tL8p zvq-{C&j!KV%|j~!H93b8#@yRyB>=og3u=v;9hk(!T3BzPC2lxe!yRrwV@WLse1R>i z@#rr#6*%@jK_vH1n5G+NdsNy<*^~=#ESjT6U}*Copd9+Pfoh;5Q;8t}O`*6D%Ja6O zP$(=s4{fH7iSZ2yf&VT-yp@589+*T~cP6=Rrc2R_u_8;6c|1vaU%WPT0zP!jH(8(o zn(Jp2Wg4QNqWTVN<;EG!8H1CdeO))hTqp+@lK@EBO@TKY<_E}kwsfWWI*ia-K(8qb z(16{(ey)1U21Os+m=LId31g-sjsX+Ng!+&$(S+2{;z);2u0r1702S{LJNP~fgz0-R zwF0#DicXCob_L~$MT#_BI7MJ*ZRRILT<2qf?eH^SF=sLoAa82yBNrvc0#dL{c~9>c z9oWlHm|{2}K;V5o_WquuL@Q~yQ-Pq1({RBrWHBS7%XGtc4?{{DDLYY4W>(E{8&xSK zEFJh1)Z)C1^oJ?M9OGi5L39Exe*igDk`bFfNC)tW-sbS+v=ovkwHEZUGbU9N;GG$qtQ2YGY3L4)!S6*BEMZ%(l%U zZscMw48K9@CF(VyDo}0Q20Oqk5^T!wR?Y`)m^LyJUVt51Le}^d9VU;8$pb-=dg(<* ztIP34%~133r9;pt%94-nzNKp}D zbQOWS#>y3i6P6hfGDDUM+r!LyNi)HscGmS7eUrN4KCZrJW2E33$|9a^(wStqc@t*U zD~JS@=|KS{cB78t+t!0~LZr|am|{LV5i(j{K^pHyxmUr0trm?(EKRh9}iPguCux)1&$ zkuvmh*EL!{-wqfAd^>V?z)@*)pqgirsdE&Ebg(q7xR=xP_9jb!jW= zgw;eL&t@f2W9oee%ItB-0K)8&>V~oFSM(i{>^P`Ven?xX{NDYu>X+GqOVeMdj_LpT z`~UP^m*(#5Z3n-mh{`cfNon>@$f&O$tsNV6+Fv~BQ?n<5MI~6d<@*=Hx*pE1J1d0E zFz9@ab44&|o^jZt>F0XY=NTkR?#!XsK_~zu{ICEh)k=kI(*UUmwXv;hc_4C#M`i4E z9tEFNJi!=NYQvgFL%1GZQ`s73qNiT#*7%cSNE%@t%H97zyta3UNT{~J?>wNMqm?7- z>DQukm#1KTP^K=FC{A0ouuN!KwXln}Rw~3US~ONJgdS;@jksjt(w@0egD5vX`tTeJ zeodd%P|`Y!5c4Axpv0%$L4p!K0RB+%BeS6v#;#~%cE=hF)ubl1DsXC|Lq4lT!#bTH zvcqMq)<%+dk>`jwb-$&IHFv>sC%UmatU04ck!f;;3D@8=NN8GLJB3w%n8SYOR%gIG$Kq`|B}BFPg?&U3Jz!!%I<`t9f~{_8hrZy%7gOZgQ5RU zTt{4ms=a_W(YEpxgD=J$eqV5ewu)+liw@>@gf{HS)hYoO-q@~H??CB}R$Vn`AX$1i zYj!x>V2rVPiTOR1C*v`9(y{vC+L7_Nzq9rdSb2`hTK?YqWd4*MK{UDU_+1_SKB}!! zJK9JQMhlL-x`_=#3O~ksRsTH~=7$LW%!~k8jd9t7x(Slicb#}pP#C}{qyl4E7a2&` zaSmRVuH&+AEp%ANQG185j+2(e>EeRCdUUM|%@{xW{W)elm;xAz3_+7aIisED#G3wM zH(=7irBa#k{SDXC?|=hBEIJe*q(_oA3Rgo>s4ol$V{zkm0b6+K;8ZRLp7>^4zp`<( zxkmf$1Ba;NX?1GfY8~yRSu}71rw9{0$1QmW>aslqec#PD0Q{B-0;}1D&C1VoKg$og zb}NkMZe1{zkJOe9FX+m?n~xoJ!$E$SGtCYhrXUg|I<+!DdV_!kmm*mFXTA#M<@$yDD#f@#ZXh+fDpWu{#?oG#h8^N7KWTPYd` zlv!d=JJHwnAREpZp zuv+H7>w$$AV{(X!ICpOIJ%ekNiO1nD1r+8Kxm_L-d=qdR_yxe$^gd_0qFhq=%qpmu zv#P#@hen@khpVlx5v}7XrYbCdCdgy75!(es?bFFZ)I(r&WiUuhF%zIjX|fG2Dh!3< zX@4^Fws4-(LH?Q7OoOnFqUURM*&>D9aT@g4;_xH_PEY%Dc&A89Wd78*#1Xg|05|$x zQ*695Js}0AX6BV#&$iIK8!k=tO1D`>)2*XP}902Kj5M=Hf{A-jUXn~6& zY-1uU`LD!Uw8?TH72Niqa1RAu(-vPxgNYR&Xw3b9^7G$hWVoQku>JtO&`|_>>21~n zdJ6%rfW&Md^K;J%h8JR|=?QYqY@tOev;pTQ6MCD9#y^F<{~Osy`h*8fAG$VOC|q3 z%$$WBsJ1ei36B*aGqTZH3-KZvnL<~1umFz7N2j65!|9nPz~O&wco@6gcJyX{Q5^v8 z3BDiyQ~-YhY-1Q*Z}sgG#{8LYm+=?Z|K{5j=?SL6YlBh`z%Inc+5!G9`)J<|@wWC1 z-;VIV4KDKS62^SVx686v{@S-I=>Kng&t#`;kt=1ZOyX_sr0m0IJAN+5|7zH|<;ty- zCr|F1+`b*Re7apW%ek_{kCBrnw{Jdo2Oi^(q5)wGX6?mOIdkil%lG2i8Th((;2IFF zD*!(@>Wx5srCbH%yTHt18O6^^2!Pj7+{?zTS6+4buAPfVM^~;G9UVo_!2zcApG-Mc zw{4CG(T8nzNU{X$t03NWLvzzmh0TEN%tZ8`4G)`xovpc8AI*b?=Od#mgjEeAnuTbRlvR)@n8-19F9YMwhr&y*P}{10dIn0 z2zLYcxEOy%eu+#5p?p!Um*17YkUQlixj}A|kIU!fkK{hNS)P}V$)|!SD9NosS#E>{ zyokTOzgr%VpU9741NX`w%QxgHSnVe0_mj}$HzCrm%hU2Lc}D(Do|XTQOXa)rZTWlo zs$3?o%kA=<{Db_XY?B|!t8$Zk0K)$uG`}4RxCd&uLUyZ4_R1bu)NjknvR|%|tMPvV zJ}lSDy?N!+!{QMP8FX54z+_L3hy8wRh*`qoXH{+I7P!f35rLn7h($ literal 0 HcmV?d00001 diff --git a/res/skin.png b/res/skin.png new file mode 100644 index 0000000000000000000000000000000000000000..ce06a18824f47e100e25e4379ba68ef9ceea237f GIT binary patch literal 1441 zcmeHG{WIHl9RHM&%89C@ijdrN*P@ig+6GA$rIBiJ%DTowtW-*udVUHK6LoW1o$15K zj% z00^?5PcQ)bOS(ShsG%-fV6El4VtC7+_uip z8d~Gwc9GS*kFrJ1JG1^)U;=smEbWJ)#fDuJ021<(@9x1(zGqqF&gbiI&p%W)8!mP` zvS#!|eb6A5G)ypHKXy)hC##RD9Ow=yoZbo)<AJnabGqIA!A z3|4yJA(lSK3)@~fIi)r(XcdVV4&9~1?eyfti#A8=6M_pv;GncE&28}te+4mjoupCOIlWE_S3nA4R(#`) zFvs~LVBv&>t2SU_Vq+21Z^~ZNWEqU0-SM6F6Kyg)Nmf>KWm;*Zxr6MfPNmPKhh}^a~aEG#(0Dqp@EaO~EqK z7la6vywI_x;hnwv^HW(wFL@L@LjUSg~R1#{v@;#JC`aL`rGPOG?|cg%pE6 zRt6JHSg2vaf}O;$aA6_~7A{$^aN&XlCM=1;i18y8O2^;1cW!6qz1M=0U?a?X|CuxQ zo_p>&=iZt7pF3VTI$fF{87mzxmtRs!#cy#s4CH79u^6XyAoJ$u-faPLJ4k@Dpu?9% zZ$0`OxwedBwy$z@czm>Pe5Ru9N&Qmq?A(co(bDYHMCI_-T<_TU$kfEtOsQ92`ew!t z4VTIw8Mzxs zx%BNH&U;2!o=em_A1T$u)M;8EaPFI1qB?Q>OTMdAdJo-xhP&@8RTu<&!2vJ82=5c`2$>Zo*5d zgqLtRyUCDF+;a%pA;7qc1mY20N7p%utFA+G<6c_pb9Np2NCK%x0_b^Jea|@}hx-ld zM9b^#t)+TWTp-*a=T6O-R11!(GPf-rV$2-Ih8P)}B>76K1i9o)o>Rzimow!Va_+dC zDcAYdW1#cxj|1)eaX_Eki=K?HgAF8I)@Zy$FQILUUINItNm;$UdcCM$_4VO+8uueU zN^HhQ6JI008~MY$tII>}e2nI?etyLx`LD14*JIw}KbIvLUSJ-}ZX6CCAi0xa5}09< zG^|rg9&c4nG6XS|)9J}E6=Gf!NJUDMw9SL0E{*A{q%+2pa@+(xXF=j2YHL#$wOm^p zc=Mnbq7jF)QSx)t<3C5$LeKKEBhOHeB%w)8+x*x|CM`NaCbGQxgH_P}6OlW41!h1& zTIr0YmL(Yz$xIQ;8DllZK%povMagrsS`@P~1iE?j?w+SSkA;saZM5jy%c;B6@XKN% zXY$x^#5{g4FXNDwgoB#rGK7k2?uKJXrnw99#3@4YcUa-VIZS! zez~i_PO~WK(6rCFRaL0viM#JAubDYzl8{yRT%}wYXP0i9y-i|~p>!F_pHY>c{>z1% zjdYP!f9giGllk?VRPQ}d5TUJigyjv_&H_JSQ? z2<(mO6hGyQmv7*<5k7dC_UoBC9rNHcI0r6*%it=w4sL-3r8Zdgi6Iyw%NIm&wYF?|aBtaK(4VZ;*3P5rwfJ$i z`El32_UiLt*rfO_%va(Q7BBb0l;z&CcPXKDxgH3Exbp4>zrVrSB|BB7}H^4jK zCb*-Nu;wkyuq`D}218&UI0&Y}DR35C0AGXe!1v%LxI> ignored = new HashSet>(); + private final Set> ignoredInstanceOf = new HashSet>(); + private final Set> nullInstead = new HashSet>(); + private final Map, IFastCloner> fastCloners = new HashMap, IFastCloner>(); + private final Map ignoredInstances = new IdentityHashMap(); + private final ConcurrentHashMap, List> fieldsCache = new ConcurrentHashMap, List>(); + + public IDumpCloned getDumpCloned() { + return dumpCloned; + } + + /** + * provide a cloned classes dumper (so i.e. they can be logged or stored in a file + * instead of the default behaviour which is to println(cloned) ) + * + * @param dumpCloned an implementation of the interface which can dump the + * cloned classes. + */ + public void setDumpCloned(IDumpCloned dumpCloned) { + this.dumpCloned = dumpCloned; + } + + private IDumpCloned dumpCloned = null; + private boolean cloningEnabled = true; + private boolean nullTransient = false; + private boolean cloneSynthetics = true; + + public Cloner() { + this.instantiationStrategy = ObjenesisInstantiationStrategy.getInstance(); + init(); + } + + public Cloner(final IInstantiationStrategy instantiationStrategy) { + this.instantiationStrategy = instantiationStrategy; + init(); + } + + public boolean isNullTransient() { + return nullTransient; + } + + /** + * this makes the cloner to set a transient field to null upon cloning. + * + * NOTE: primitive types can't be nulled. Their value will be set to default, i.e. 0 for int + * + * @param nullTransient true for transient fields to be nulled + */ + public void setNullTransient(final boolean nullTransient) { + this.nullTransient = nullTransient; + } + + public void setCloneSynthetics(final boolean cloneSynthetics) { + this.cloneSynthetics = cloneSynthetics; + } + + private void init() { + registerKnownJdkImmutableClasses(); + registerKnownConstants(); + registerFastCloners(); + } + + /** + * registers a std set of fast cloners. + */ + protected void registerFastCloners() { + fastCloners.put(GregorianCalendar.class, new FastClonerCalendar()); + fastCloners.put(ArrayList.class, new FastClonerArrayList()); + fastCloners.put(LinkedList.class, new FastClonerLinkedList()); + fastCloners.put(HashSet.class, new FastClonerHashSet()); + fastCloners.put(HashMap.class, new FastClonerHashMap()); + fastCloners.put(TreeMap.class, new FastClonerTreeMap()); + fastCloners.put(ConcurrentHashMap.class, new FastClonerConcurrentHashMap()); + } + + private IDeepCloner deepCloner = new IDeepCloner() { + public T deepClone(T o, Map clones) { + try { + return cloneInternal(o, clones); + } catch (IllegalAccessException e) { + // just rethrow unchecked + throw new IllegalStateException(e); + } + } + }; + + protected Object fastClone(final Object o, final Map clones) throws IllegalAccessException { + final Class c = o.getClass(); + final IFastCloner fastCloner = fastCloners.get(c); + if (fastCloner != null) return fastCloner.clone(o, deepCloner, clones); + return null; + } + + public void registerConstant(final Object o) { + ignoredInstances.put(o, true); + } + + public void registerConstant(final Class c, final String privateFieldName) { + try { + final Field field = c.getDeclaredField(privateFieldName); + field.setAccessible(true); + final Object v = field.get(null); + ignoredInstances.put(v, true); + } catch (final SecurityException e) { + throw new RuntimeException(e); + } catch (final NoSuchFieldException e) { + throw new RuntimeException(e); + } catch (final IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (final IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + /** + * registers some known JDK immutable classes. Override this to register your + * own list of jdk's immutable classes + */ + protected void registerKnownJdkImmutableClasses() { + registerImmutable(String.class); + registerImmutable(Integer.class); + registerImmutable(Long.class); + registerImmutable(Boolean.class); + registerImmutable(Class.class); + registerImmutable(Float.class); + registerImmutable(Double.class); + registerImmutable(Character.class); + registerImmutable(Byte.class); + registerImmutable(Short.class); + registerImmutable(Void.class); + + registerImmutable(BigDecimal.class); + registerImmutable(BigInteger.class); + registerImmutable(URI.class); + registerImmutable(URL.class); + registerImmutable(UUID.class); + registerImmutable(Pattern.class); + } + + protected void registerKnownConstants() { + // registering known constants of the jdk. + registerStaticFields(TreeSet.class, HashSet.class, HashMap.class, TreeMap.class); + } + + /** + * registers all static fields of these classes. Those static fields won't be cloned when an instance + * of the class is cloned. + * + * This is useful i.e. when a static field object is added into maps or sets. At that point, there is no + * way for the cloner to know that it was static except if it is registered. + * + * @param classes array of classes + */ + public void registerStaticFields(final Class... classes) { + for (final Class c : classes) { + final List fields = allFields(c); + for (final Field field : fields) { + final int mods = field.getModifiers(); + if (Modifier.isStatic(mods) && !field.getType().isPrimitive()) { + registerConstant(c, field.getName()); + } + } + } + } + + /** + * spring framework friendly version of registerStaticFields + * + * @param set a set of classes which will be scanned for static fields + */ + public void setExtraStaticFields(final Set> set) { + registerStaticFields((Class[]) set.toArray()); + } + + /** + * instances of classes that shouldn't be cloned can be registered using this method. + * + * @param c The class that shouldn't be cloned. That is, whenever a deep clone for + * an object is created and c is encountered, the object instance of c will + * be added to the clone. + */ + public void dontClone(final Class... c) { + for (final Class cl : c) { + ignored.add(cl); + } + } + + public void dontCloneInstanceOf(final Class... c) { + for (final Class cl : c) { + ignoredInstanceOf.add(cl); + } + } + + public void setDontCloneInstanceOf(final Class... c) { + dontCloneInstanceOf(c); + } + + /** + * instead of cloning these classes will set the field to null + * + * @param c the classes to nullify during cloning + */ + public void nullInsteadOfClone(final Class... c) { + for (final Class cl : c) { + nullInstead.add(cl); + } + } + + // spring framework friendly version of nullInsteadOfClone + public void setExtraNullInsteadOfClone(final Set> set) { + nullInstead.addAll(set); + } + + /** + * registers an immutable class. Immutable classes are not cloned. + * + * @param c the immutable class + */ + public void registerImmutable(final Class... c) { + for (final Class cl : c) { + ignored.add(cl); + } + } + + // spring framework friendly version of registerImmutable + public void setExtraImmutables(final Set> set) { + ignored.addAll(set); + } + + public void registerFastCloner(final Class c, final IFastCloner fastCloner) { + if (fastCloners.containsKey(c)) throw new IllegalArgumentException(c + " already fast-cloned!"); + fastCloners.put(c, fastCloner); + } + + public void unregisterFastCloner(final Class c) { + fastCloners.remove(c); + } + + /** + * creates a new instance of c. Override to provide your own implementation + * + * @param the type of c + * @param c the class + * @return a new instance of c + */ + protected T newInstance(final Class c) { + return instantiationStrategy.newInstance(c); + } + + @SuppressWarnings("unchecked") + public T fastCloneOrNewInstance(final Class c) { + try { + final T fastClone = (T) fastClone(c, null); + if (fastClone != null) return fastClone; + } catch (final IllegalAccessException e) { + throw new RuntimeException(e); + } + return newInstance(c); + + } + + /** + * deep clones "o". + * + * @param the type of "o" + * @param o the object to be deep-cloned + * @return a deep-clone of "o". + */ + public T deepClone(final T o) { + if (o == null) return null; + if (!cloningEnabled) return o; + if (dumpCloned != null) { + dumpCloned.startCloning(o.getClass()); + } + final Map clones = new IdentityHashMap(16); + try { + return cloneInternal(o, clones); + } catch (final IllegalAccessException e) { + throw new CloningException("error during cloning of " + o, e); + } + } + + public T deepCloneDontCloneInstances(final T o, final Object... dontCloneThese) { + if (o == null) return null; + if (!cloningEnabled) return o; + if (dumpCloned != null) { + dumpCloned.startCloning(o.getClass()); + } + final Map clones = new IdentityHashMap(16); + for (final Object dc : dontCloneThese) { + clones.put(dc, dc); + } + try { + return cloneInternal(o, clones); + } catch (final IllegalAccessException e) { + throw new CloningException("error during cloning of " + o, e); + } + } + + /** + * shallow clones "o". This means that if c=shallowClone(o) then + * c!=o. Any change to c won't affect o. + * + * @param the type of o + * @param o the object to be shallow-cloned + * @return a shallow clone of "o" + */ + public T shallowClone(final T o) { + if (o == null) return null; + if (!cloningEnabled) return o; + try { + return cloneInternal(o, null); + } catch (final IllegalAccessException e) { + throw new CloningException("error during cloning of " + o, e); + } + } + + // caches immutables for quick reference + private final ConcurrentHashMap, Boolean> immutables = new ConcurrentHashMap, Boolean>(); + private boolean cloneAnonymousParent = true; + + /** + * override this to decide if a class is immutable. Immutable classes are not cloned. + * + * @param clz the class under check + * @return true to mark clz as immutable and skip cloning it + */ + protected boolean considerImmutable(final Class clz) { + return false; + } + + protected Class getImmutableAnnotation() { + return Immutable.class; + } + + /** + * decides if a class is to be considered immutable or not + * + * @param clz the class under check + * @return true if the clz is considered immutable + */ + private boolean isImmutable(final Class clz) { + final Boolean isIm = immutables.get(clz); + if (isIm != null) return isIm; + if (considerImmutable(clz)) return true; + + final Class immutableAnnotation = getImmutableAnnotation(); + for (final Annotation annotation : clz.getDeclaredAnnotations()) { + if (annotation.annotationType() == immutableAnnotation) { + immutables.put(clz, Boolean.TRUE); + return true; + } + } + Class c = clz.getSuperclass(); + while (c != null && c != Object.class) { + for (final Annotation annotation : c.getDeclaredAnnotations()) { + if (annotation.annotationType() == Immutable.class) { + final Immutable im = (Immutable) annotation; + if (im.subClass()) { + immutables.put(clz, Boolean.TRUE); + return true; + } + } + } + c = c.getSuperclass(); + } + immutables.put(clz, Boolean.FALSE); + return false; + } + + @SuppressWarnings("unchecked") + protected T cloneInternal(final T o, final Map clones) throws IllegalAccessException { + if (o == null) return null; + if (o == this) return null; // don't clone the cloner! + if (ignoredInstances.containsKey(o)) return o; + if (o instanceof Enum) return o; + final Class clz = (Class) o.getClass(); + // skip cloning ignored classes + if (nullInstead.contains(clz)) return null; + if (ignored.contains(clz)) return o; + for (final Class iClz : ignoredInstanceOf) { + if (iClz.isAssignableFrom(clz)) return o; + } + if (isImmutable(clz)) return o; + if (o instanceof IFreezable) { + final IFreezable f = (IFreezable) o; + if (f.isFrozen()) return o; + } + final Object clonedPreviously = clones != null ? clones.get(o) : null; + if (clonedPreviously != null) return (T) clonedPreviously; + + final Object fastClone = fastClone(o, clones); + if (fastClone != null) { + if (clones != null) { + clones.put(o, fastClone); + } + return (T) fastClone; + } + + if (dumpCloned != null) { + dumpCloned.startCloning(o.getClass()); + } + if (clz.isArray()) { + return cloneArray(o, clones); + } + + return cloneObject(o, clones, clz); + } + + // clones o, no questions asked! + private T cloneObject(T o, Map clones, Class clz) throws IllegalAccessException { + final T newInstance = newInstance(clz); + if (clones != null) { + clones.put(o, newInstance); + } + final List fields = allFields(clz); + for (final Field field : fields) { + final int modifiers = field.getModifiers(); + if (!Modifier.isStatic(modifiers)) { + if ( ! (nullTransient && Modifier.isTransient(modifiers)) ) { + // request by Jonathan : transient fields can be null-ed + final Object fieldObject = field.get(o); + final boolean shouldClone = (cloneSynthetics || !field.isSynthetic()) && (cloneAnonymousParent || !isAnonymousParent(field)); + final Object fieldObjectClone = clones != null ? (shouldClone ? cloneInternal(fieldObject, clones) : fieldObject) : fieldObject; + field.set(newInstance, fieldObjectClone); + if (dumpCloned != null && fieldObjectClone != fieldObject) { + dumpCloned.cloning(field, o.getClass()); + } + } + } + } + return newInstance; + } + + @SuppressWarnings("unchecked") + private T cloneArray(T o, Map clones) throws IllegalAccessException { + final Class clz = (Class) o.getClass(); + final int length = Array.getLength(o); + final T newInstance = (T) Array.newInstance(clz.getComponentType(), length); + if (clones != null) { + clones.put(o, newInstance); + } + if(clz.getComponentType().isPrimitive() || isImmutable(clz.getComponentType())) { + System.arraycopy(o, 0, newInstance, 0, length); + } else { + for (int i = 0; i < length; i++) { + final Object v = Array.get(o, i); + final Object clone = clones != null ? cloneInternal(v, clones) : v; + Array.set(newInstance, i, clone); + } + } + return newInstance; + } + + private boolean isAnonymousParent(final Field field) { + return "this$0".equals(field.getName()); + } + + /** + * copies all properties from src to dest. Src and dest can be of different class, provided they contain same field names/types + * + * @param src the source object + * @param dest the destination object which must contain as minimum all the fields of src + */ + public void copyPropertiesOfInheritedClass(final T src, final E dest) { + if (src == null) throw new IllegalArgumentException("src can't be null"); + if (dest == null) throw new IllegalArgumentException("dest can't be null"); + final Class srcClz = src.getClass(); + final Class destClz = dest.getClass(); + if (srcClz.isArray()) { + if (!destClz.isArray()) + throw new IllegalArgumentException("can't copy from array to non-array class " + destClz); + final int length = Array.getLength(src); + for (int i = 0; i < length; i++) { + final Object v = Array.get(src, i); + Array.set(dest, i, v); + } + return; + } + final List fields = allFields(srcClz); + final List destFields = allFields(dest.getClass()); + for (final Field field : fields) { + if (!Modifier.isStatic(field.getModifiers())) { + try { + final Object fieldObject = field.get(src); + field.setAccessible(true); + if (destFields.contains(field)) { + field.set(dest, fieldObject); + } + } catch (final IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (final IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } + } + + /** + * reflection utils + */ + private void addAll(final List l, final Field[] fields) { + for (final Field field : fields) { + if (!field.isAccessible()) { + field.setAccessible(true); + } + l.add(field); + } + } + + /** + * reflection utils, override this to choose which fields to clone + */ + protected List allFields(final Class c) { + List l = fieldsCache.get(c); + if (l == null) { + l = new LinkedList(); + final Field[] fields = c.getDeclaredFields(); + addAll(l, fields); + Class sc = c; + while ((sc = sc.getSuperclass()) != Object.class && sc != null) { + addAll(l, sc.getDeclaredFields()); + } + fieldsCache.putIfAbsent(c, l); + } + return l; + } + + public boolean isDumpClonedClasses() { + return dumpCloned != null; + } + + /** + * will println() all cloned classes. Useful for debugging only. Use + * setDumpCloned() if you want to control where to print the cloned + * classes. + * + * @param dumpClonedClasses true to enable printing all cloned classes + */ + public void setDumpClonedClasses(final boolean dumpClonedClasses) { + if (dumpClonedClasses) { + dumpCloned = new IDumpCloned() { + public void startCloning(Class clz) { + System.out.println("clone>" + clz); + } + + public void cloning(Field field, Class clz) { + System.out.println("cloned field>" + field + " -- of class " + clz); + } + }; + } else dumpCloned = null; + } + + public boolean isCloningEnabled() { + return cloningEnabled; + } + + public void setCloningEnabled(final boolean cloningEnabled) { + this.cloningEnabled = cloningEnabled; + } + + /** + * if false, anonymous classes parent class won't be cloned. Default is true + */ + public void setCloneAnonymousParent(final boolean cloneAnonymousParent) { + this.cloneAnonymousParent = cloneAnonymousParent; + } + + public boolean isCloneAnonymousParent() { + return cloneAnonymousParent; + } + + /** + * @return a standard cloner instance, will do for most use cases + */ + public static Cloner standard() { + return new Cloner(); + } + + /** + * @return if Cloner lib is in a shared jar folder for a container (i.e. tomcat/shared), then + * this method is preferable in order to instantiate cloner. Please + * see https://code.google.com/p/cloning/issues/detail?id=23 + */ + public static Cloner shared() { + return new Cloner(new ObjenesisInstantiationStrategy()); + } + +} diff --git a/src/com/rits/cloning/CloningException.java b/src/com/rits/cloning/CloningException.java new file mode 100644 index 00000000..09b26786 --- /dev/null +++ b/src/com/rits/cloning/CloningException.java @@ -0,0 +1,20 @@ +package com.rits.cloning; + +/** + * thrown if cloning fails + * + * @author kostantinos.kougios + * + * 18 Jan 2009 + */ +public class CloningException extends RuntimeException +{ + private static final long serialVersionUID = 3815175312001146867L; + + public CloningException(final String message, final Throwable cause) + { + super(message, cause); + + } + +} diff --git a/src/com/rits/cloning/FastClonerArrayList.java b/src/com/rits/cloning/FastClonerArrayList.java new file mode 100644 index 00000000..51a67783 --- /dev/null +++ b/src/com/rits/cloning/FastClonerArrayList.java @@ -0,0 +1,25 @@ +package com.rits.cloning; + +import java.util.ArrayList; +import java.util.Map; + +/** + * @author kostantinos.kougios + * + * 21 May 2009 + */ +public class FastClonerArrayList implements IFastCloner +{ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Object clone(final Object t, final IDeepCloner cloner, final Map clones) { + final ArrayList al = (ArrayList) t; + final ArrayList l = new ArrayList(al.size()); + for (final Object o : al) + { + final Object cloneInternal = cloner.deepClone(o, clones); + l.add(cloneInternal); + } + return l; + } + +} diff --git a/src/com/rits/cloning/FastClonerCalendar.java b/src/com/rits/cloning/FastClonerCalendar.java new file mode 100644 index 00000000..80c6b45a --- /dev/null +++ b/src/com/rits/cloning/FastClonerCalendar.java @@ -0,0 +1,22 @@ +package com.rits.cloning; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.Map; +import java.util.TimeZone; + +/** + * @author kostantinos.kougios + * + * 21 May 2009 + */ +public class FastClonerCalendar implements IFastCloner +{ + public Object clone(final Object t, final IDeepCloner cloner, final Map clones) { + final GregorianCalendar gc = new GregorianCalendar(); + Calendar c = (Calendar) t; + gc.setTimeInMillis(c.getTimeInMillis()); + gc.setTimeZone((TimeZone) c.getTimeZone().clone()); + return gc; + } +} diff --git a/src/com/rits/cloning/FastClonerConcurrentHashMap.java b/src/com/rits/cloning/FastClonerConcurrentHashMap.java new file mode 100644 index 00000000..55fa7691 --- /dev/null +++ b/src/com/rits/cloning/FastClonerConcurrentHashMap.java @@ -0,0 +1,26 @@ +package com.rits.cloning; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author kostantinos.kougios + * + * 18 Oct 2011 + */ +public class FastClonerConcurrentHashMap implements IFastCloner +{ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Object clone(final Object t, final IDeepCloner cloner, final Map clones) { + final ConcurrentHashMap m = (ConcurrentHashMap) t; + final ConcurrentHashMap result = new ConcurrentHashMap(); + for (final Map.Entry e : m.entrySet()) + { + final Object key = cloner.deepClone(e.getKey(), clones); + final Object value = cloner.deepClone(e.getValue(), clones); + + result.put(key, value); + } + return result; + } +} diff --git a/src/com/rits/cloning/FastClonerCustomCollection.java b/src/com/rits/cloning/FastClonerCustomCollection.java new file mode 100644 index 00000000..48a6db55 --- /dev/null +++ b/src/com/rits/cloning/FastClonerCustomCollection.java @@ -0,0 +1,26 @@ +package com.rits.cloning; + +import java.util.Collection; +import java.util.Map; + +/** + * @author kostantinos.kougios + * + * 21 May 2009 + */ +@SuppressWarnings({ "unchecked", "rawtypes" }) +public abstract class FastClonerCustomCollection implements IFastCloner +{ + public abstract T getInstance(T o); + + public Object clone(final Object t, final IDeepCloner cloner, final Map clones) { + final T c = getInstance((T) t); + final T l = (T) t; + for (final Object o : l) + { + final Object clone = cloner.deepClone(o, clones); + c.add(clone); + } + return c; + } +} diff --git a/src/com/rits/cloning/FastClonerCustomMap.java b/src/com/rits/cloning/FastClonerCustomMap.java new file mode 100644 index 00000000..8454b3fc --- /dev/null +++ b/src/com/rits/cloning/FastClonerCustomMap.java @@ -0,0 +1,28 @@ +package com.rits.cloning; + +import java.util.Map; +import java.util.Set; + +/** + * @author kostantinos.kougios + * + * 21 May 2009 + */ +@SuppressWarnings({ "unchecked", "rawtypes" }) +public abstract class FastClonerCustomMap implements IFastCloner +{ + public Object clone(final Object t, final IDeepCloner cloner, final Map clones) { + final T m = (T) t; + final T result = getInstance((T) t); + final Set> entrySet = m.entrySet(); + for (final Map.Entry e : entrySet) + { + final Object key = cloner.deepClone(e.getKey(), clones); + final Object value = cloner.deepClone(e.getValue(), clones); + result.put(key, value); + } + return result; + } + + protected abstract T getInstance(T t); +} diff --git a/src/com/rits/cloning/FastClonerHashMap.java b/src/com/rits/cloning/FastClonerHashMap.java new file mode 100644 index 00000000..09d0a4b3 --- /dev/null +++ b/src/com/rits/cloning/FastClonerHashMap.java @@ -0,0 +1,26 @@ +package com.rits.cloning; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author kostantinos.kougios + * + * 21 May 2009 + */ +public class FastClonerHashMap implements IFastCloner +{ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Object clone(final Object t, final IDeepCloner cloner, final Map clones) { + final HashMap m = (HashMap) t; + final HashMap result = new HashMap(); + for (final Map.Entry e : m.entrySet()) + { + final Object key = cloner.deepClone(e.getKey(), clones); + final Object value = cloner.deepClone(e.getValue(), clones); + + result.put(key, value); + } + return result; + } +} diff --git a/src/com/rits/cloning/FastClonerHashSet.java b/src/com/rits/cloning/FastClonerHashSet.java new file mode 100644 index 00000000..94aa127e --- /dev/null +++ b/src/com/rits/cloning/FastClonerHashSet.java @@ -0,0 +1,24 @@ +package com.rits.cloning; + +import java.util.HashSet; +import java.util.Map; + +/** + * @author kostantinos.kougios + * + * 21 May 2009 + */ +public class FastClonerHashSet implements IFastCloner +{ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Object clone(final Object t, final IDeepCloner cloner, final Map clones) { + final HashSet al = (HashSet) t; + final HashSet l = new HashSet(); + for (final Object o : al) + { + final Object cloneInternal = cloner.deepClone(o, clones); + l.add(cloneInternal); + } + return l; + } +} diff --git a/src/com/rits/cloning/FastClonerLinkedList.java b/src/com/rits/cloning/FastClonerLinkedList.java new file mode 100644 index 00000000..488289e7 --- /dev/null +++ b/src/com/rits/cloning/FastClonerLinkedList.java @@ -0,0 +1,24 @@ +package com.rits.cloning; + +import java.util.LinkedList; +import java.util.Map; + +/** + * @author kostantinos.kougios + * + * 21 May 2009 + */ +public class FastClonerLinkedList implements IFastCloner +{ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Object clone(final Object t, final IDeepCloner cloner, final Map clones) { + final LinkedList al = (LinkedList) t; + final LinkedList l = new LinkedList(); + for (final Object o : al) + { + final Object cloneInternal = cloner.deepClone(o, clones); + l.add(cloneInternal); + } + return l; + } +} diff --git a/src/com/rits/cloning/FastClonerTreeMap.java b/src/com/rits/cloning/FastClonerTreeMap.java new file mode 100644 index 00000000..c545a627 --- /dev/null +++ b/src/com/rits/cloning/FastClonerTreeMap.java @@ -0,0 +1,25 @@ +package com.rits.cloning; + +import java.util.Map; +import java.util.TreeMap; + +/** + * @author kostantinos.kougios + * + * 21 May 2009 + */ +public class FastClonerTreeMap implements IFastCloner +{ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Object clone(final Object t, final IDeepCloner cloner, final Map clones) { + final TreeMap m = (TreeMap) t; + final TreeMap result = new TreeMap(m.comparator()); + for (final Map.Entry e : m.entrySet()) + { + final Object key = cloner.deepClone(e.getKey(), clones); + final Object value = cloner.deepClone(e.getValue(), clones); + result.put(key, value); + } + return result; + } +} diff --git a/src/com/rits/cloning/IDeepCloner.java b/src/com/rits/cloning/IDeepCloner.java new file mode 100644 index 00000000..bb1867b2 --- /dev/null +++ b/src/com/rits/cloning/IDeepCloner.java @@ -0,0 +1,20 @@ +package com.rits.cloning; + +import java.util.Map; + +/** + * used by fast cloners to deep clone objects + * + * @author kostas.kougios Date 24/06/14 + */ +public interface IDeepCloner { + /** + * deep clones o + * + * @param o the object to be deep cloned + * @param clones pass on the same map from IFastCloner + * @param the type of o + * @return a clone of o + */ + T deepClone(final T o, final Map clones); +} diff --git a/src/com/rits/cloning/IDumpCloned.java b/src/com/rits/cloning/IDumpCloned.java new file mode 100644 index 00000000..92358917 --- /dev/null +++ b/src/com/rits/cloning/IDumpCloned.java @@ -0,0 +1,14 @@ +package com.rits.cloning; + +import java.lang.reflect.Field; + +/** + * @author: kostas.kougios + * Date: 06/08/13 + */ +public interface IDumpCloned +{ + void startCloning(Class clz); + + void cloning(Field field, Class clz); +} diff --git a/src/com/rits/cloning/IFastCloner.java b/src/com/rits/cloning/IFastCloner.java new file mode 100644 index 00000000..1c0ddd6c --- /dev/null +++ b/src/com/rits/cloning/IFastCloner.java @@ -0,0 +1,14 @@ +package com.rits.cloning; + +import java.util.Map; + +/** + * allows a custom cloner to be created for a specific class. + * (it has to be registered with Cloner) + * + * @author kostantinos.kougios + * 21 May 2009 + */ +public interface IFastCloner { + public Object clone(Object t, IDeepCloner cloner, Map clones); +} diff --git a/src/com/rits/cloning/IFreezable.java b/src/com/rits/cloning/IFreezable.java new file mode 100644 index 00000000..73085831 --- /dev/null +++ b/src/com/rits/cloning/IFreezable.java @@ -0,0 +1,12 @@ +package com.rits.cloning; + +/** + * @author kostantinos.kougios + * + * 15 Nov 2010 + */ +public interface IFreezable +{ + public boolean isFrozen(); + +} diff --git a/src/com/rits/cloning/IInstantiationStrategy.java b/src/com/rits/cloning/IInstantiationStrategy.java new file mode 100644 index 00000000..acafb732 --- /dev/null +++ b/src/com/rits/cloning/IInstantiationStrategy.java @@ -0,0 +1,11 @@ +package com.rits.cloning; + +/** + * @author kostantinos.kougios + * + * 17 Jul 2012 + */ +public interface IInstantiationStrategy +{ + T newInstance(final Class c); +} diff --git a/src/com/rits/cloning/Immutable.java b/src/com/rits/cloning/Immutable.java new file mode 100644 index 00000000..16347f0e --- /dev/null +++ b/src/com/rits/cloning/Immutable.java @@ -0,0 +1,25 @@ +package com.rits.cloning; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * marks the specific class as immutable and the cloner avoids cloning it + * + * @author kostantinos.kougios + * + * 24 Mar 2011 + */ +@Target(TYPE) +@Retention(RUNTIME) +public @interface Immutable +{ + /** + * by default all subclasses of the @Immutable class are not immutable. This can override it. + * @return true for subclasses of @Immutable class to be regarded as immutable from the cloner + */ + boolean subClass() default false; +} diff --git a/src/com/rits/cloning/ObjenesisInstantiationStrategy.java b/src/com/rits/cloning/ObjenesisInstantiationStrategy.java new file mode 100644 index 00000000..d1457fed --- /dev/null +++ b/src/com/rits/cloning/ObjenesisInstantiationStrategy.java @@ -0,0 +1,26 @@ +package com.rits.cloning; + +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; + +/** + * @author kostantinos.kougios + * + * 17 Jul 2012 + */ +public class ObjenesisInstantiationStrategy implements IInstantiationStrategy +{ + private final Objenesis objenesis = new ObjenesisStd(); + + public T newInstance(Class c) + { + return objenesis.newInstance(c); + } + + private static ObjenesisInstantiationStrategy instance = new ObjenesisInstantiationStrategy(); + + public static ObjenesisInstantiationStrategy getInstance() + { + return instance; + } +} diff --git a/src/com/rits/perspectives/Perspectives.java b/src/com/rits/perspectives/Perspectives.java new file mode 100644 index 00000000..03383412 --- /dev/null +++ b/src/com/rits/perspectives/Perspectives.java @@ -0,0 +1,73 @@ +package com.rits.perspectives; + +import java.util.Collection; + +import com.rits.cloning.Cloner; + +/** + * Perspectives: an object instance of a class behaving differently according to the "view angle". + * + * @author kostantinos.kougios + * + * 30 Nov 2009 + */ +public class Perspectives +{ + private final Cloner cloner; + + public Perspectives(final Cloner cloner) + { + this.cloner = cloner; + } + + /** + * Sample: if o is an instance of Product and c is OrderedProduct.class then this returns + * and instance of OrderedProduct.class which has equal field values to those of the instance of Product. + * In other words, the returned instance of OrderedProduct.class is the Product instance from the perspective + * of an OrderedProduct + * + * View an object o from the perspective of class c. (view o as an instance of c). c must be instanceof o.getClass() + * + * @param the object + * @param this will be the returned type and it must be instanceof T. All properties of o will be copied to this instance. + * @param c the class of E. This is used to generate new instances of c + * @param o the object that must be viewed from a different perspective + * @return the E perspective of o + */ + public E viewAs(final Class c, final T o) + { + if (o == null) return null; + if (o instanceof Collection) throw new IllegalArgumentException("for collections please use viewCollectionAs() method. Invalid object " + o); + final E newInstance = cloner.fastCloneOrNewInstance(c); + cloner.copyPropertiesOfInheritedClass(o, newInstance); + return newInstance; + } + + /** + * Sample: if o is a [ Products extends LinkedList ] then the returned instance + * is a [ OrderedProducts extends LinkedList ]. + * + * View a collection o from the perspective of collection E. + * + * NOTE: order of the items might not be preserved, depending on the collection type + * + * @param the type of the collection o + * @param the type of the elements of the collection o + * @param the type of the perspective collection + * @param the type of the perspective's elements + * @param newCollection the collection to which the adapted instances should be added + * @param currentCollection the collection with the instances to be adapted + * @param perspectiveCollectionItemClass the class of the NI + * @return E, the collection from a different perspective or null if currentCollection is null + */ + public , E extends Collection> E viewCollectionAs(final E newCollection, final Class perspectiveCollectionItemClass, final T currentCollection) + { + if (currentCollection == null) return null; + for (final I item : currentCollection) + { + final NI newItem = viewAs(perspectiveCollectionItemClass, item); + newCollection.add(newItem); + } + return newCollection; + } +} diff --git a/src/org/nevec/rjm/NumeroAvanzato.java b/src/org/nevec/rjm/NumeroAvanzato.java new file mode 100644 index 00000000..dc5240ba --- /dev/null +++ b/src/org/nevec/rjm/NumeroAvanzato.java @@ -0,0 +1,744 @@ +package org.nevec.rjm; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.security.ProviderException; + +import org.warpgate.pi.calculator.Errore; +import org.warpgate.pi.calculator.Incognita; +import org.warpgate.pi.calculator.Incognite; +import org.warpgate.pi.calculator.Utils; + +/** + * Square roots on the real line. These represent numbers which are a product of + * a (signed) fraction by a square root of a non-negative fraction. This might + * be extended to values on the imaginary axis by allowing negative values + * underneath the square root, but this is not yet implemented. + * + * @since 2011-02-12 + * @author Richard J. Mathar + */ +public class NumeroAvanzato implements Cloneable { + /** + * The value of zero. + */ + public static final NumeroAvanzato ZERO = new NumeroAvanzato(); + + /** + * The value of one. + */ + public static final NumeroAvanzato ONE = new NumeroAvanzato(Rational.ONE, Rational.ONE); + /** + * Prefactor + */ + Rational pref; + + private Incognite incognitex; + + private Incognite incognitey; + + private Incognite incognitez; + + /** + * The number underneath the square root, always non-negative. The + * mathematical object has the value pref*sqrt(disc). + */ + Rational disc; + + /** + * Default ctor, which represents the zero. + * + * @since 2011-02-12 + */ + public NumeroAvanzato() { + pref = Rational.ZERO; + disc = Rational.ZERO; + incognitex = new Incognite(); + incognitey = new Incognite(); + incognitez = new Incognite(); + } + + /** + * ctor given the prefactor and the basis of the root. This creates an + * object of value a*sqrt(b). + * + * @param a + * the prefactor. + * @param b + * the discriminant. + * @throws Errore + * @since 2011-02-12 + */ + public NumeroAvanzato(Rational a, Rational b) { + this.pref = a; + /* + * reject attempts to use a negative b + */ + if (b.signum() < 0) + throw new ProviderException("Not implemented: imaginary surds"); + this.disc = b; + incognitex = new Incognite(); + incognitey = new Incognite(); + incognitez = new Incognite(); + try { + normalize(); + normalizeG(); + } catch (Errore e) { + e.printStackTrace(); + } + } + + public NumeroAvanzato(Rational a, Rational b, Incognite x, Incognite y, Incognite z) { + this.pref = a; + /* + * reject attempts to use a negative b + */ + if (b.signum() < 0) + throw new ProviderException("Not implemented: imaginary surds"); + this.disc = b; + incognitex = x; + incognitey = y; + incognitez = z; + try { + normalize(); + normalizeG(); + } catch (Errore e) { + e.printStackTrace(); + } + } + + /** + * ctor given the numerator and denominator of the root. This creates an + * object of value sqrt(a/b). + * + * @param a + * the numerator + * @param b + * the denominator. + * @since 2011-02-12 + */ + public NumeroAvanzato(int a, int b) { + this(Rational.ONE, new Rational(a, b)); + } + + /** + * ctor given the value under the root. This creates an object of value + * sqrt(a). + * + * @param a + * the discriminant. + * @since 2011-02-12 + */ + public NumeroAvanzato(BigInteger a) { + this(Rational.ONE, new Rational(a, BigInteger.ONE)); + } + + public NumeroAvanzato(Rational a) { + this(Rational.ONE, a); + } + + /** + * Create a deep copy. + * + * @since 2011-02-12 + */ + public NumeroAvanzato clone() { + Rational fclon = pref.clone(); + Rational dclon = disc.clone(); + Incognite incognitexb = incognitex; + Incognite incogniteyb = incognitey; + Incognite incognitezb = incognitez; + /* + * the main intent here is to bypass any attempt to reduce the + * discriminant by figuring out the square-free part in normalize(), + * which has already done in the current copy of the number. + */ + NumeroAvanzato cl = new NumeroAvanzato(); + cl.pref = fclon; + cl.disc = dclon; + cl.incognitex = incognitexb; + cl.incognitey = incogniteyb; + cl.incognitez = incognitezb; + return cl; + } /* NumeroAvanzato.clone */ + + /** + * Add two surds of compatible discriminant. + * + * @param val + * The value to be added to this. + */ + + public NumeroAvanzatoVec add(final NumeroAvanzato val) { + // zero plus somethings yields something + if (signum() == 0) + return new NumeroAvanzatoVec(val); + else if (val.signum() == 0) + return new NumeroAvanzatoVec(this); + else + // let the ctor of NumeroAvanzatoVec to the work + return new NumeroAvanzatoVec(this, val); + } /* NumeroAvanzato.add */ + + /** + * Multiply by another square root. + * + * @param val + * a second number of this type. + * @return the product of this with the val. + * @since 2011-02-12 + */ + public NumeroAvanzato multiply(final NumeroAvanzato val) { + return new NumeroAvanzato(pref.multiply(val.pref), disc.multiply(val.disc), incognitex.multiply(val.incognitex), + incognitey.multiply(val.incognitey), incognitez.multiply(val.incognitez)); + } /* NumeroAvanzato.multiply */ + + /** + * Multiply by a rational number. + * + * @param val + * the factor. + * @return the product of this with the val. + * @since 2011-02-15 + */ + public NumeroAvanzato multiply(final Rational val) { + return new NumeroAvanzato(pref.multiply(val), disc, incognitex, incognitey, incognitez); + } /* NumeroAvanzato.multiply */ + + /** + * Multiply by a BigInteger. + * + * @param val + * a second number. + * @return the product of this with the value. + * @since 2011-02-12 + */ + public NumeroAvanzato multiply(final BigInteger val) { + return new NumeroAvanzato(pref.multiply(val), disc, incognitex, incognitey, incognitez); + } /* NumeroAvanzato.multiply */ + + /** + * Multiply by an integer. + * + * @param val + * a second number. + * @return the product of this with the value. + * @since 2011-02-12 + */ + public NumeroAvanzato multiply(final int val) { + BigInteger tmp = new BigInteger("" + val); + return multiply(tmp); + } /* NumeroAvanzato.multiply */ + + /** + * Compute the square. + * + * @return this value squared. + * @throws Errore + * @since 2011-02-12 + */ + public NumeroAvanzato pow2() throws Errore { + NumeroAvanzato res = new NumeroAvanzato(); + BigInteger a = pref.a; + BigInteger b = pref.b; + BigInteger c = disc.a; + BigInteger d = disc.b; + res.pref = new Rational(a.pow(2).multiply(c).multiply(d), b.pow(2).multiply(d)); + res.disc = new Rational(0, 1); + res.normalize(); + res.incognitex = incognitex; + res.incognitey = incognitey.multiply(incognitey); + res.incognitez = incognitez.multiply(incognitez); + return res; + } /* NumeroAvanzato.sqr */ + + /** + * Divide by another square root. + * + * @param val + * A second number of this type. + * @return The value of this/val + * @throws Errore + * @since 2011-02-12 + */ + public NumeroAvanzato divide(final NumeroAvanzato val) throws Errore { + if (val.signum() == 0) + throw new ArithmeticException("Dividing " + toFancyString() + " through zero."); + NumeroAvanzato result = new NumeroAvanzato(pref.divide(val.pref), disc.divide(val.disc)); + result.incognitex = incognitex.divide(val.incognitex); + result.incognitey = incognitey.divide(val.incognitey); + result.incognitez = incognitez.divide(val.incognitez); + result.normalize(); + return result; + } /* NumeroAvanzato.divide */ + + private String toFancyString() throws Errore { + return new NumeroAvanzatoVec(this).toFancyString(); + } + + /** + * Divide by an integer. + * + * @param val + * a second number. + * @return the value of this/val + * @throws Errore + * @since 2011-02-12 + */ + public NumeroAvanzato divide(final BigInteger val) throws Errore { + if (val.signum() == 0) + throw new ArithmeticException("Dividing " + toFancyString() + " through zero."); + return new NumeroAvanzato(pref.divide(val), disc); + } /* NumeroAvanzato.divide */ + + /** + * Divide by an integer. + * + * @param val + * A second number. + * @return The value of this/val + * @throws Errore + * @since 2011-02-12 + */ + public NumeroAvanzato divide(int val) throws Errore { + if (val == 0) + throw new ArithmeticException("Dividing " + toFancyString() + " through zero."); + return new NumeroAvanzato(pref.divide(val), disc); + } /* NumeroAvanzato.divide */ + + /** + * Compute the negative. + * + * @return -this. + * @since 2011-02-12 + */ + public NumeroAvanzato negate() { + /* + * This is trying to be quick, avoiding normalize(), by toggling the + * sign in a clone() + */ + NumeroAvanzato n = clone(); + n.pref = n.pref.negate(); + return n; + } /* NumeroAvanzato.negate */ + + /** + * Absolute value. + * + * @return The absolute (non-negative) value of this. + * @since 2011-02-12 + */ + public NumeroAvanzato abs() { + return new NumeroAvanzato(pref.abs(), disc); + } + + /** + * Compares the value of this with another constant. + * + * @param val + * the other constant to compare with + * @return -1, 0 or 1 if this number is numerically less than, equal to, or + * greater than val. + * @throws Errore + * @since 2011-02-12 + */ + public int signumComparedTo(final NumeroAvanzato val) throws Errore { + /* + * Since we keep the discriminant positive, the rough estimate comes + * from comparing the signs of the prefactors. + */ + final int sig = signum(); + final int sigv = val.signum(); + if (sig < 0 && sigv >= 0) + return -1; + if (sig > 0 && sigv <= 0) + return 1; + if (sig == 0 && sigv == 0) + return 0; + if (sig == 0 && sigv > 0) + return -1; + if (sig == 0 && sigv < 0) + return 1; + + /* + * Work out the cases of equal sign. Compare absolute values by + * comparison of the squares which is forwarded to the comparison of the + * Rational class. + */ + final Rational this2 = pow2().pref; + final Rational val2 = val.pow2().pref; + final int c2 = this2.compareTo(val2); + if (c2 == 0) + return 0; + /* + * If both values have negative sign, the one with the smaller square is + * the larger number. + */ + else if (sig > 0 && c2 > 0 || sig < 0 && c2 < 0) + return 1; + else + return -1; + } /* NumeroAvanzato.compareTo */ + + /** + * Return a string in the format (number/denom)*()^(1/2). If the + * discriminant equals 1, print just the prefactor. + * + * @return the human-readable version in base 10 + * @since 2011-02-12 + */ + public String toString() { + try { + return toFancyString(); + } catch (Errore e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + /* + if (disc.compareTo(Rational.ONE) != 0 && disc.compareTo(Rational.ZERO) != 0) + return ("(" + pref.toString() + ")*(" + disc.toString() + ")^(1/2)"); + else + return pref.toString(); + */ + return "err"; + } /* NumeroAvanzato.toString */ + + /** + * Return a double value representation. + * + * @return The value with double precision. + * @since 2011-02-12 + */ + public double doubleValue() { + /* + * First compute the square to prevent overflows if the two pieces of + * the prefactor and the discriminant are of very different magnitude. + */ + Rational p2 = pref.pow(2).multiply(disc); + System.out.println("dv sq " + p2.toString()); + double res = p2.doubleValue(); + System.out.println("dv sq " + res); + return (pref.signum() >= 0) ? Math.sqrt(res) : -Math.sqrt(res); + } /* NumeroAvanzato.doubleValue */ + + /** + * Return a float value representation. + * + * @return The value with single precision. + * @since 2011-02-12 + */ + public float floatValue() { + return (float) (doubleValue()); + } /* NumeroAvanzato.floatValue */ + + /** + * True if the value is integer. Equivalent to the indication whether a + * conversion to an integer can be exact. + * @param hasBigIntegerVariables + * + * @since 2011-02-12 + */ + public boolean isBigInteger(boolean hasBigIntegerVariables) { + if (pref.isBigInteger() && (disc.signum() == 0 || disc.compareTo(Rational.ONE) == 0)) { + if (disc.signum() != 0 && incognitex.count() > 0) { + return false; + } + if (hasBigIntegerVariables == false && incognitey.count() > 0) { + return false; + } + if (pref.b.compareTo(BigInteger.ZERO) != 0 && disc.b.compareTo(BigInteger.ZERO) != 0 && incognitez.count() > 0) { + return false; + } + return true; + } + return false; + } /* NumeroAvanzato.isBigInteger */ + + public boolean isRational(boolean hasRationalVariables) { + if (disc.signum() == 0 || disc.compareTo(new Rational(1, 1)) == 0) { + if (incognitex.count() > 0) { + return false; + } else if (hasRationalVariables == false) { + if (incognitey.count() > 0 || incognitez.count() > 0) { + return false; + } + } + + if (this.pref.b.compareTo(new BigInteger("10000")) > 0) { + return false; + } + return true; + } + return false; + + } /* NumeroAvanzato.isRational */ + + public boolean isTooPreciseRational(boolean hasRationalVariables) { + if (disc.signum() == 0 || disc.compareTo(new Rational(1, 1)) == 0) { + if (incognitex.count() > 0) { + return false; + } else if (hasRationalVariables == false) { + if (incognitey.count() > 0 || incognitez.count() > 0) { + return false; + } + } + + if (this.pref.b.compareTo(new BigInteger("10000")) > 0) { + return true; + } + return false; + } + return false; + } /* NumeroAvanzato.isRational */ + + /** + * Convert to a rational value if possible + * @throws Errore + * + * @since 2012-02-15 + */ + public Rational toRational(boolean hasRationalVariables) throws Errore { + if (isRational(hasRationalVariables) || isTooPreciseRational(hasRationalVariables)) + return pref; + else + throw new ArithmeticException("Undefined conversion " + toFancyString() + " to Rational."); + } /* NumeroAvanzato.toRational */ + + public Rational toRational() throws Errore { + if (isRational(true)) + return pref; + else + throw new ArithmeticException("Undefined conversion " + toFancyString() + " to Rational."); + } + + /** + * The sign: 1 if the number is >0, 0 if ==0, -1 if <0 + * + * @return the signum of the value. + * @since 2011-02-12 + */ + public int signum() { + /* + * Since the disc is kept positive, this is the same as the sign of the + * prefactor. This works because a zero discriminant is always copied + * over to the prefactor, not hidden. + */ + return pref.signum(); + } /* NumeroAvanzato.signum */ + + /** + * Normalize to squarefree discriminant. + * @throws Errore + * + * @since 2011-02-12 + */ + protected void normalize() throws Errore { + /* + * Move squares out of the numerator and denominator of the discriminant + */ + if (disc.signum() != 0) { + /* + * square-free part of the numerator: numer = numC*some^2 + */ + BigInteger numC = BigIntegerMath.core(disc.numer()); + /* + * extract the perfect square of the numerator + */ + BigInteger sq = disc.numer().divide(numC); + /* + * extract the associated square root + */ + BigInteger sqf = BigIntegerMath.isqrt(sq); + + /* + * move sqf over to the pre-factor + */ + pref = pref.multiply(sqf); + + BigInteger denC = BigIntegerMath.core(disc.denom()); + sq = disc.denom().divide(denC); + sqf = BigIntegerMath.isqrt(sq); + try { + pref = pref.divide(sqf); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + disc = new Rational(numC, denC); + + if (disc.b.compareTo(BigInteger.ZERO) == 0 || disc.a.compareTo(BigInteger.ZERO) == 0 || pref.a.compareTo(BigInteger.ZERO) == 0) { + incognitex = new Incognite(); + incognitey = new Incognite(); + } + + if (disc.b.compareTo(BigInteger.ZERO) == 0 || pref.b.compareTo(BigInteger.ZERO) == 0) { + incognitez = new Incognite(); + } + + if (incognitey.compareTo(incognitez)) { + incognitey = new Incognite(); + incognitez = new Incognite(); + } + + /**/ + Incognite[] incognitetemp = new Incognite[]{incognitex, incognitey, incognitez}; + incognitetemp = Incognite.normalizeBigSurdVariables(incognitetemp); + incognitex = incognitetemp[0]; + incognitey = incognitetemp[1]; + incognitez = incognitetemp[2]; + /**/ + } else { + pref = Rational.ZERO; + incognitex = new Incognite(); + incognitey = new Incognite(); + incognitez = new Incognite(); + } + } /* NumeroAvanzato.normalize */ + + /** + * Normalize to coprime numerator and denominator in prefactor and + * discriminant + * @throws Errore + * + * @since 2011-02-12 + */ + protected void normalizeG() throws Errore { + /* + * Is there a common factor between the numerator of the prefactor and + * the denominator of the discriminant ? + */ + BigInteger d = pref.numer().abs().gcd(disc.denom()); + if (d.compareTo(BigInteger.ONE) > 0) { + try { + pref = pref.divide(d); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + /* + * instead of multiplying with the square of d, using two steps + * offers a change to recognize the common factor.. + */ + disc = disc.multiply(d); + disc = disc.multiply(d); + } + /* + * Is there a common factor between the denominator of the prefactor and + * the numerator of the discriminant ? + */ + d = pref.denom().gcd(disc.numer()); + if (d.compareTo(BigInteger.ONE) > 0) { + pref = pref.multiply(d); + /* + * instead of dividing through the square of d, using two steps + * offers a change to recognize the common factor.. + */ + disc = disc.divide(d); + disc = disc.divide(d); + } + } /* NumeroAvanzato.normalizeG */ + + /** + * Return the approximate floating point representation. + * + * @param mc + * Description of the accuracy needed. + * @return A representation with digits valid as described by mc + * @since 2012-02-15 + */ + public BigDecimal BigDecimalValue(MathContext mc) { + /* + * the relative error of the result equals the relative error of the + * prefactor plus half of the relative error of the discriminant. So + * adding 3 digits temporarily is sufficient. + */ + final MathContext locmc = new MathContext(mc.getPrecision() + 3, mc.getRoundingMode()); + /* + * first the square root of the discriminant + */ + BigDecimal sqrdis = BigDecimalMath.sqrt(disc.BigDecimalValue(locmc), locmc); + /* + * Then multiply by the prefactor. If sqrdis is a terminating decimal + * fraction, we prevent early truncation of the result by truncating + * later. + */ + BigDecimal res = sqrdis.multiply(pref.BigDecimalValue(mc)); + return BigDecimalMath.scalePrec(res, mc); + } /* BigDecimalValue */ + + @Override + public boolean equals(Object val) { + if (val instanceof NumeroAvanzato) { + NumeroAvanzato na = (NumeroAvanzato) val; + try { + if (pow2().pref == na.pow2().pref) { + if (pow2().pref == Rational.ZERO) { + return true; + } else { + if (incognitex == na.incognitex) { + if (incognitey == na.incognitey) { + if (incognitez == na.incognitez) { + return true; + } + } + } + } + } + } catch (Errore e) { + e.printStackTrace(); + } + } + return false; + } + + public Incognite getIncognitex() { + if (incognitex == null) { + return incognitex; + } + return incognitex.clone(); + } + + public NumeroAvanzato setIncognitex(Incognite incognitex) { + NumeroAvanzato result = this.clone(); + result.incognitex = incognitex; + return result; + } + + public Incognite getIncognitey() { + if (incognitey == null) { + return incognitey; + } + return incognitey.clone(); + } + + public NumeroAvanzato setIncognitey(Incognite incognitey) { + NumeroAvanzato result = this.clone(); + result.incognitey = incognitey; + return result; + } + + public Incognite getIncognitez() { + if (incognitez == null) { + return incognitez; + } + return incognitez.clone(); + } + + public NumeroAvanzato setIncognitez(Incognite incognitez) { + NumeroAvanzato result = this.clone(); + result.incognitez = incognitez; + return result; + } + + public NumeroAvanzato divideUnsafe(BigInteger denominator) { + try { + return divide(denominator); + } catch (Errore e) { + e.printStackTrace(); + return new NumeroAvanzato(); + } + } + +} /* NumeroAvanzato */ diff --git a/src/org/nevec/rjm/NumeroAvanzatoVec.java b/src/org/nevec/rjm/NumeroAvanzatoVec.java new file mode 100644 index 00000000..6fd6568e --- /dev/null +++ b/src/org/nevec/rjm/NumeroAvanzatoVec.java @@ -0,0 +1,752 @@ +package org.nevec.rjm; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.util.Comparator; +import java.util.Vector; + +import org.warpgate.pi.calculator.Errore; +import org.warpgate.pi.calculator.Incognita; +import org.warpgate.pi.calculator.Incognite; +import org.warpgate.pi.calculator.Utils; + +/** + * A NumeroAvanzatoVec represents an algebraic sum or differences of values which each + * term an instance of NumeroAvanzato. This mainly means that sums or differences of + * two NumeroAvanzato (or two NumeroAvanzatoVec) can be represented (exactly) as a NumeroAvanzatoVec. + * + * @since 2012-02-15 + * @author Richard J. Mathar + */ +public class NumeroAvanzatoVec implements Comparable { + /** + * The value of zero. + */ + public static final NumeroAvanzatoVec ZERO = new NumeroAvanzatoVec(); + + /** + * The value of one. + */ + public static final NumeroAvanzatoVec ONE = new NumeroAvanzatoVec(NumeroAvanzato.ONE); + + /** + * Internal representation: Each term as a single NumeroAvanzato. The value zero is + * represented by an empty vector. + */ + Vector terms; + + /** + * Default ctor, which represents the zero. + * + * @since 2012-02-15 + */ + public NumeroAvanzatoVec() { + terms = new Vector(); + } /* ctor */ + + /** + * ctor given the value of a NumeroAvanzato. + * + * @param a + * The value to be represented by this vector. + * @since 2012-02-15 + */ + public NumeroAvanzatoVec(NumeroAvanzato a) { + terms = new Vector(1); + terms.add(a); + } /* ctor */ + + /** + * ctor given two values, which (when added) represent this number a+b. + * + * @param a + * The value to be represented by the first term of the vector. + * @param b + * The value to be represented by the second term of the vector. + * @since 2012-02-15 + */ + public NumeroAvanzatoVec(NumeroAvanzato a, NumeroAvanzato b) { + terms = new Vector(2); + terms.add(a); + terms.add(b); + try { + normalize(); + } catch (Errore e) { + e.printStackTrace(); + } + } /* ctor */ + + /** + * Combine terms that can be written as a single surd. This unites for + * example the terms sqrt(90) and sqrt(10) to 4*sqrt(10). + * @throws Errore + * + * @since 2012-02-15 + */ + protected void normalize() throws Errore { + /* + * nothing to be done if at most one term + */ + if (terms.size() <= 1) + return; + + Vector newter = new Vector(); + newter.add(terms.firstElement()); + /* + * add j-th element to the existing vector and combine were possible + */ + for (int j = 1; j < terms.size(); j++) { + NumeroAvanzato todo = terms.elementAt(j); + boolean merged = false; + for (int ex = 0; ex < newter.size(); ex++) { + NumeroAvanzato v = newter.elementAt(ex); + /* + * try to merge terms[j] and newter[ex]. todo = r * v with r a + * rational number is needed. Replaces v with v+todo = v*(1+r) + * if this reduction works. + */ + NumeroAvanzato r = todo.divide(v); + if ((r.isRational(true) || r.isTooPreciseRational(true)) && todo.getIncognitex().compareTo(v.getIncognitex()) && todo.getIncognitey().compareTo(v.getIncognitey()) && todo.getIncognitez().compareTo(v.getIncognitez())) { + /* compute r+1 */ + Rational newpref = r.toRational(true).add(1); + /* + * eliminate accidental zeros; overwrite with v*(1+r). + */ + if (newpref.compareTo(Rational.ZERO) == 0) + newter.removeElementAt(ex); + else { + v = v.multiply(newpref); + newter.setElementAt(v, ex); + } + merged = true; + break; + } + } + /* + * append if none of the existing elements matched + */ + if (!merged) + newter.add(todo); + } + + newter.sort(new Comparator() { + @Override + public int compare(NumeroAvanzato o1, NumeroAvanzato o2) { + int index1 = Incognite.priorità(o1.getIncognitex().sqrt().multiply(o1.getIncognitey()).divide(o1.getIncognitez())); + int index2 = Incognite.priorità(o2.getIncognitex().sqrt().multiply(o2.getIncognitey()).divide(o2.getIncognitez())); + return index2-index1; + } + }); + + /* overwrite old version */ + terms = newter; + } /* normalize */ + + /** + * Compare algebraic value with oth. Returns -1, 0 or +1 depending on + * whether this is smaller, equal to or larger than oth. + * + * @param oth + * The value with which this is to be compared. + * @return 0 or +-1. + * @since 2012-02-15 + */ + public int compareTo(NumeroAvanzatoVec oth) { + NumeroAvanzatoVec diff; + try { + diff = this.subtract(oth); + return diff.signum(); + } catch (Errore e) { + e.printStackTrace(); + return 0; + } + } /* compareTo */ + + /** + * Sign function. Returns -1, 0 or +1 depending on whether this is smaller, + * equal to or larger than zero. + * + * @return 0 or +-1. + * @throws Errore + * @since 2012-02-15 + */ + public int signum() throws Errore { + /* + * the case of zero is unique, because no (reduced) vector of surds + * other than the one element 0 itself can add/subtract to zero. + */ + if (terms.size() == 0) + return 0; + + /* + * if there is one term: forward to the signum function of NumeroAvanzato + */ + if (terms.size() == 1) + return terms.firstElement().signum(); + + /* + * if all terms have a common sign: take that one offsig is the index of + * the first "offending" term in the sense that its sign doese not agree + * with the term[0]. + */ + int sig0 = terms.elementAt(0).signum(); + int offsig = 1; + for (; offsig < terms.size(); offsig++) + if (terms.elementAt(offsig).signum() != sig0) + break; + if (offsig >= terms.size()) + return sig0; + + /* + * if there are two terms (now known to have different sign): forward to + * the comparison of the two elements as NumeroAvanzatos + */ + if (terms.size() == 2) + return terms.elementAt(0).signumComparedTo(terms.elementAt(1).negate()); + + /* + * if there are three terms, move the one with the offending sign to the + * other side and square both sides (which looses the sign) to remove + * all but one surds. The difference of the squared sides contains at + * most two terms, which reduces to the case above. t(0)+t(offbar) <> + * -t(offs) + */ + if (terms.size() == 3) { + NumeroAvanzatoVec lhs; + if (offsig == 2) + lhs = new NumeroAvanzatoVec(terms.elementAt(0), terms.elementAt(1)); + else + lhs = new NumeroAvanzatoVec(terms.elementAt(0), terms.elementAt(2)); + lhs = lhs.sqr(); + /* + * Strange line: this line isn't used, but it's present in this code! + * + * + * + NumeroAvanzato rhs = new NumeroAvanzato(terms.elementAt(offsig).sqr(), Rational.ONE); + * + * + * + */ + if (lhs.compareTo(lhs) > 0) + /* + * dominating sign was t(0)+t(offbar) + */ + return terms.elementAt(0).signum(); + else + return terms.elementAt(offsig).signum(); + } + + /* + * for a larger number of terms: take a floating point representation + * with a small but correct number of digits, and resume with the sign + * of that one. + */ + return (floatValue() > 0.) ? 1 : -1; + + } /* signum */ + + /** + * Construct an approximate floating point representation + * + * @param mc + * The intended accuracy of the result. + * @return A truncated version with the precision described by mc + */ + public BigDecimal BigDecimalValue(MathContext mc) { + /* + * simple cases with one term forwarded to the NumeroAvanzato class + */ + if (terms.size() == 0) + return BigDecimal.ZERO; + else if (terms.size() == 1) { + return terms.firstElement().BigDecimalValue(mc); + } + + /* + * To reduce cancellation errors, loop over increasing local precision + * until we are stable to the required result. Keep the old (less + * precise) estimate in res[0], and the newer, more precise in res[1]. + */ + BigDecimal[] res = new BigDecimal[2]; + res[0] = BigDecimal.ZERO; + for (int addpr = 1;; addpr += 3) { + MathContext locmc = new MathContext(mc.getPrecision() + addpr, mc.getRoundingMode()); + res[1] = BigDecimal.ZERO; + for (NumeroAvanzato j : terms) + res[1] = BigDecimalMath.addRound(res[1], j.BigDecimalValue(locmc)); + if (addpr > 1) { + BigDecimal err = res[1].subtract(res[0]).abs(); + int prec = BigDecimalMath.err2prec(res[1], err); + if (prec == Integer.MIN_VALUE) { + break; + } + if (prec > mc.getPrecision()) + break; + } + res[0] = res[1]; + } + return BigDecimalMath.scalePrec(res[1], mc); + + } /* BigDecimalValue */ + + /** + * Construct an approximate floating point representation + * + * @return A truncated version with the precision described by mc + */ + public double doubleValue() { + BigDecimal bd = BigDecimalValue(MathContext.DECIMAL128); + return bd.doubleValue(); + } /* doubleValue */ + + /** + * Construct an approximate floating point representation + * + * @return A truncated version with the precision described by mc + */ + public double floatValue() { + BigDecimal bd = BigDecimalValue(MathContext.DECIMAL64); + return bd.floatValue(); + } /* floatValue */ + + /** + * Add two vectors algebraically. + * + * @param val + * The value to be added to this. + * @return The new value representing this+val. + * @throws Errore + */ + public NumeroAvanzatoVec add(final NumeroAvanzatoVec val) throws Errore { + NumeroAvanzatoVec sum = new NumeroAvanzatoVec(); + /* + * concatenate the vectors and eliminate common overlaps + */ + for (NumeroAvanzato term : terms) { + if (term.signumComparedTo(NumeroAvanzato.ZERO) != 0) { + sum.terms.add(term); + } + } + for (NumeroAvanzato term : val.terms) { + if (term.signumComparedTo(NumeroAvanzato.ZERO) != 0) { + sum.terms.add(term); + } + } + sum.normalize(); + return sum; + } /* add */ + + /** + * Add two vectors algebraically. + * + * @param val + * The value to be added to this. + * @return The new value representing this+val. + * @throws Errore + */ + public NumeroAvanzatoVec add(final NumeroAvanzato val) throws Errore { + NumeroAvanzatoVec sum = new NumeroAvanzatoVec(); + /* + * concatenate the vectors and eliminate common overlaps + */ + sum.terms.addAll(terms); + sum.terms.add(val); + sum.normalize(); + return sum; + } /* add */ + + /** + * Subtract another number. + * + * @param val + * The value to be subtracted from this. + * @return The new value representing this-val. + * @throws Errore + */ + public NumeroAvanzatoVec subtract(final NumeroAvanzatoVec val) throws Errore { + NumeroAvanzatoVec sum = new NumeroAvanzatoVec(); + /* + * concatenate the vectors and eliminate common overlaps + */ + sum.terms.addAll(terms); + for (NumeroAvanzato s : val.terms) + sum.terms.add(s.negate()); + sum.normalize(); + return sum; + } /* subtract */ + + /** + * Subtract another number. + * + * @param val + * The value to be subtracted from this. + * @return The new value representing this-val. + * @throws Errore + */ + public NumeroAvanzatoVec subtract(final NumeroAvanzato val) throws Errore { + NumeroAvanzatoVec sum = new NumeroAvanzatoVec(); + /* + * concatenate the vectors and eliminate common overlaps + */ + sum.terms.addAll(terms); + sum.terms.add(val.negate()); + sum.normalize(); + return sum; + } /* subtract */ + + /** + * Compute the negative. + * + * @return -this. + * @since 2012-02-15 + */ + public NumeroAvanzatoVec negate() { + /* + * accumulate the negated elements of term one by one + */ + NumeroAvanzatoVec resul = new NumeroAvanzatoVec(); + for (NumeroAvanzato s : terms) + resul.terms.add(s.negate()); + /* + * no normalization step here, because the negation of all terms does + * not introduce new common factors + */ + return resul; + } /* negate */ + + /** + * Compute the square. + * + * @return this value squared. + * @throws Errore + * @since 2012-02-15 + */ + public NumeroAvanzatoVec sqr() throws Errore { + /* + * Binomial expansion. First the sum of the terms squared, then 2 times + * the mixed products. + */ + NumeroAvanzatoVec resul = new NumeroAvanzatoVec(); + for (int i = 0; i < terms.size(); i++) + resul.terms.add(terms.elementAt(i).pow2()); + for (int i = 0; i < terms.size() - 1; i++) + for (int j = i + 1; j < terms.size(); j++) + resul.terms.add(terms.elementAt(i).multiply(terms.elementAt(j)).multiply(2)); + resul.normalize(); + return resul; + } /* sqr */ + + /** + * Multiply by another square root. + * + * @param val + * a second number of this type. + * @return the product of this with the val. + * @throws Errore + * @since 2011-02-12 + */ + public NumeroAvanzatoVec multiply(final NumeroAvanzato val) throws Errore { + NumeroAvanzatoVec resul = new NumeroAvanzatoVec(); + for (NumeroAvanzato s : terms) + resul.terms.add(s.multiply(val)); + resul.normalize(); + return resul; + } /* multiply */ + + public NumeroAvanzatoVec multiply(final NumeroAvanzatoVec val) throws Errore { + NumeroAvanzatoVec resul = new NumeroAvanzatoVec(); + for (NumeroAvanzato s : terms) { + for (NumeroAvanzato s2 : val.terms) { + resul = resul.add(s.multiply(s2)); + } + } + return resul; + } /* multiply */ + + public NumeroAvanzatoVec divide(final NumeroAvanzato val) throws Errore { + NumeroAvanzatoVec resul = new NumeroAvanzatoVec(); + for (NumeroAvanzato s : terms) { + resul.terms.add(s.divide(val)); + } + resul.normalize(); + return resul; + } /* divide */ + + public NumeroAvanzatoVec divide(final NumeroAvanzatoVec val) throws Errore { + NumeroAvanzatoVec resul = new NumeroAvanzatoVec(); + resul.terms = this.terms; + for (NumeroAvanzato s : val.terms) { + resul = resul.divide(s); + } + return resul; + } /* divide */ + + /** + * True if the value is rational. Equivalent to the indication whether a + * conversion to a Rational can be exact. + * + * @since 2011-02-12 + */ + public boolean isRational(boolean hasRationalVariables) { + boolean val = false; + for (NumeroAvanzato s : terms) { + val = s.isRational(hasRationalVariables); + if (val == false) { + break; + } + } + return val; + } /* NumeroAvanzatoVec.isRational */ + + public boolean isNumeroAvanzato() { + return (this.terms.size() <= 1); + } + + /** + * True if the value is BigInteger. Equivalent to the indication whether a + * conversion to a BigInteger can be exact. + * + * @since 2011-02-12 + */ + public boolean isBigInteger(boolean hasBigIntegerVariables) { + boolean val = false; + for (NumeroAvanzato s : terms) { + val = s.isBigInteger(hasBigIntegerVariables); + if (val == true) { + if (s.getIncognitex().count() > 0 || s.getIncognitez().count() > 0) { + val = false; + } + } + if (val == false) { + break; + } + } + return val; + } /* NumeroAvanzatoVec.isRational */ + + /** + * Convert to a rational value if possible + * + * @since 2012-02-15 + */ + public Rational toRational(boolean hasRationalVariables) { + Rational rat = Rational.ZERO; + if (isRational(hasRationalVariables) == false) + throw new ArithmeticException("Undefined conversion " + toString() + " to Rational."); + for (NumeroAvanzato s : terms) { + rat = rat.add(s.pref); + } + return rat; + } /* NumeroAvanzato.toRational */ + + /** + * Convert to a BigInteger value if possible + * + * @since 2012-02-15 + */ + public BigInteger toBigInteger(boolean hasBigIntegerVariables) { + BigDecimal tmp = BigDecimal.ZERO.setScale(Utils.scale, Utils.scaleMode); + if (isBigInteger(hasBigIntegerVariables) == false) + throw new ArithmeticException("Undefined conversion " + toString() + " to Rational."); + for (NumeroAvanzato s : terms) { + tmp = BigDecimalMath.addRound(tmp, s.pref.BigDecimalValue(new MathContext(Utils.scale, Utils.scaleMode2))); + } + return tmp.toBigInteger(); + } /* NumeroAvanzato.toRational */ + + /** + * Convert to a BigDecimal value if possible + * + * @since 2012-02-15 + */ + public BigDecimal toBigDecimal() { + BigDecimal tmp = BigDecimal.ZERO.setScale(Utils.scale, Utils.scaleMode); + for (NumeroAvanzato s : terms) { + tmp = BigDecimalMath.addRound(tmp, s.BigDecimalValue(new MathContext(Utils.scale, Utils.scaleMode2))); + } + return tmp; + } /* NumeroAvanzato.toBigDecimal */ + + + public NumeroAvanzato toNumeroAvanzato() { + if (this.terms.size() == 0) { + return NumeroAvanzato.ZERO; + } + return this.terms.get(0); + } + + /** + * Return a string in the format (number/denom)*()^(1/2). If the + * discriminant equals 1, print just the prefactor. + * + * @return the human-readable version in base 10 + * @since 2012-02-16 + */ + public String toString() { + /* + * simple cases with one term forwarded to the NumeroAvanzato class + */ + return toFancyString(); + /* + if (terms.size() == 0) + return new String("0"); + else { + String s = new String(); + for (int t = 0; t < terms.size(); t++) { + NumeroAvanzato bs = terms.elementAt(t); + if (bs.signum() > 0) + s += "+"; + s += bs.toString(); + } + return s; + } + */ + } /* toString */ + + public String toFancyString() { + if (terms.size() == 0) { + return new String("0"); + } else if (terms.size() == 1 && terms.elementAt(0).isTooPreciseRational(true)) { + String s = ""; + NumeroAvanzato bs = terms.elementAt(0).clone(); + String num = bs.BigDecimalValue(new MathContext(Utils.resultScale, Utils.scaleMode2)).toEngineeringString(); + if (num.contains("E")) { + s += "("+num.replace("E+", "*10^")+")"; + } else { + s += num; + } + s += bs.getIncognitey().toString(); + return s; + } else { + BigInteger denominator = BigInteger.ONE; + Incognite incognitedenom = new Incognite(); + for (int i = 0; i < terms.size(); i++) { + denominator = BigIntegerMath.lcm(denominator, terms.elementAt(i).pref.b); + //denominator = denominator.multiply(terms.elementAt(i).pref.b); + Incognite iz = terms.elementAt(i).getIncognitez(); + incognitedenom = Incognite.lcm(incognitedenom, iz); + } + String s = ""; + + if (denominator.abs().compareTo(new BigInteger("10000")) > 0) { + for (int i = 0; i < terms.size(); i++) { + NumeroAvanzato bs = terms.elementAt(i).clone(); + String num = bs.BigDecimalValue(new MathContext(Utils.resultScale, Utils.scaleMode2)).toEngineeringString().replaceAll("\\.0+$", "").replaceAll("\\.0+E", "E"); + if (num.contains("E")) { + if (bs.signum() > 0) { + s += "+"; + } + num = num.replace("E+", "*10^")+")"; + if (num.contains("*10^1)")) { + num = num.replace("*10^1)", ")"); + } else { + num = "("+num; + } + s += num; + } else { + if (bs.signum() > 0) { + s += "+"; + } + s += num; + } + s += bs.getIncognitey().toString(); + } + return s; + } + + if (denominator.compareTo(BigInteger.ONE) != 0 || incognitedenom.count() > 0) { + if (terms.size() == 1 && terms.get(0).multiply(denominator).isBigInteger(true) == false) { + s += "("; + } + } + for (int t = 0; t < terms.size(); t++) { + NumeroAvanzato bs = terms.elementAt(t).clone(); + + bs = bs.setIncognitey(bs.getIncognitey().divide(bs.getIncognitez())); + bs = bs.setIncognitey(bs.getIncognitey().multiply(incognitedenom)); + bs = bs.multiply(denominator); + bs = bs.setIncognitez(incognitedenom); + + bs.pref = new Rational(bs.pref.a, BigInteger.ONE); + if (bs.signum() > 0 && t > 0) + s += "+"; + if (bs.isBigInteger(true)) { + String numb; + try { + numb = bs.toRational(true).a.toString(); + } catch (Errore e) { + // TODO Auto-generated catch block + e.printStackTrace(); + numb = ""; + } + String incognite = bs.getIncognitey().toString(); + if (((numb.equals("1") || numb.equals("-1")) == false && incognite.length() > 0) || incognite.length() == 0) { + s += numb; + } else if (numb.equals("-1")) { + s += "-"; + } + s +=incognite; + } else if (bs.isRational(true) || bs.isTooPreciseRational(true)) { + try { + s += bs.toRational(true).toString(); + } catch (Errore e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + s += bs.getIncognitey().toString(); + } else { + BigInteger numerator = bs.pref.numer(); + if ((numerator.compareTo(BigInteger.ONE) != 0 || bs.getIncognitey().count() > 0) && (bs.disc.compareTo(BigInteger.ONE) != 0 || bs.getIncognitex().count() > 0)) { + if (((bs.getIncognitey().count() > 0) || (bs.getIncognitey().count() == 0 && numerator.toString().length() > 0))) { + if ((bs.getIncognitey().count() > 0 && (numerator.toString().equals("1") || numerator.toString().equals("-1")) == false) || bs.getIncognitey().count() == 0) { + s += numerator.toString(); + } else if (numerator.toString().equals("-1")) { + s += "-"; + } + } + //s += "("; + } + if (bs.disc.isInteger() && bs.getIncognitex().count() == 0) { + s += "Ⓐ("; + s += bs.disc.toString(); + s += ")"; + } else if((bs.disc.toString().equals("1") || bs.disc.toString().equals("-1")) && bs.getIncognitex().count() > 0) { + s += "Ⓐ("; + if (bs.disc.toString().equals("-1")) { + s += "-"; + } + s += bs.getIncognitex().toString(); + s += ")"; + } else { + s += "Ⓐ("+bs.disc.toString()+bs.getIncognitex().toString()+")"; + } + if ((numerator.compareTo(BigInteger.ONE) != 0 || bs.getIncognitey().count() > 0) && (bs.disc.compareTo(BigInteger.ONE) != 0 || bs.getIncognitex().count() > 0)) { + if (((bs.getIncognitey().count() > 0) || (bs.getIncognitey().count() == 0 && numerator.toString().length() > 0))) { + s += bs.getIncognitey().toString(); + } + //s += "("; + } + if ((numerator.compareTo(BigInteger.ONE) != 0 || bs.getIncognitey().count() > 0) && (bs.disc.compareTo(BigInteger.ONE) != 0 || bs.getIncognitex().count() > 0)) { + //s += ")"; + } + } + } + if (denominator.compareTo(BigInteger.ONE) != 0 || incognitedenom.count() > 0) { + if (terms.size() == 1 && terms.get(0).multiply(denominator).isBigInteger(true) == false) { + s += ")"; + } + s += "/"; + if ((incognitedenom.count() > 0 && (denominator.toString().equals("1") || denominator.toString().equals("-1")) == false) || incognitedenom.count() == 0) { + s += denominator; + } else if (denominator.toString().equals("-1")) { + s += "-"; + } + s += incognitedenom.toString(); + } + return s; + } + } + +} /* NumeroAvanzatoVec */ diff --git a/src/org/warp/engine/lwjgl/Display.java b/src/org/warp/engine/lwjgl/Display.java new file mode 100644 index 00000000..41fb926f --- /dev/null +++ b/src/org/warp/engine/lwjgl/Display.java @@ -0,0 +1,696 @@ +package org.warp.engine.lwjgl; +import org.lwjgl.BufferUtils; +import org.lwjgl.glfw.GLFWErrorCallback; +import org.lwjgl.glfw.GLFWFramebufferSizeCallback; +import org.lwjgl.glfw.GLFWKeyCallback; +import org.lwjgl.glfw.GLFWVidMode; +import org.lwjgl.glfw.GLFWWindowSizeCallback; +import org.lwjgl.opengl.GL; +import org.lwjgl.opengl.GLCapabilities; +import org.lwjgl.opengl.GLUtil; +import org.lwjgl.stb.STBTTAlignedQuad; +import org.lwjgl.stb.STBTTPackContext; +import org.lwjgl.stb.STBTTPackedchar; +import org.warpgate.pi.calculator.Calculator; +import org.warpgate.pi.calculator.Keyboard; +import org.warpgate.pi.calculator.Main; +import org.warpgate.pi.calculator.Utils; + +import de.matthiasmann.twl.utils.PNGDecoder; +import de.matthiasmann.twl.utils.PNGDecoder.Format; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +import static org.warp.engine.lwjgl.GLFWUtil.*; +import static org.warp.engine.lwjgl.IOUtil.*; +import static org.lwjgl.glfw.Callbacks.*; +import static org.lwjgl.glfw.GLFW.*; +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL13.*; +import static org.lwjgl.opengl.GL30.*; +import static org.lwjgl.stb.STBTruetype.*; +import static org.lwjgl.system.MemoryUtil.*; +import static org.lwjgl.stb.STBImage.*; + +/** + * STB Truetype oversampling demo. + * + *

This is a Java port of https://github + * .com/nothings/stb/blob/master/tests/oversample/main.c.

+ */ +public final class Display { + + private static final int BITMAP_W = 5*128; + private static final int BITMAP_H = 9*256; + + private static final float[] scale = { + 30.0f, + 15.0f + }; + + // ---- + + private final STBTTAlignedQuad q = STBTTAlignedQuad.malloc(); + private final FloatBuffer xb = memAllocFloat(1); + private final FloatBuffer yb = memAllocFloat(1); + + private long window; + + // ---- + + private int ww = 480; + private int wh = 320; + + private int fbw = ww; + private int fbh = wh; + + private int font_tex; + private int skin_tex; + private int skin_w; + private int skin_h; + private int skin_comp; + private ByteBuffer skin; + + private STBTTPackedchar.Buffer chardata; + + private boolean black_on_white; + private boolean integer_align; + private boolean translating; + private boolean rotating; + + private boolean supportsSRGB; + private boolean srgb; + + private float rotate_t, translate_t; + + private boolean show_tex; + + private int font = 0; + + private final int maxCharIndex = 9500; + private float[] background = new float[]{0f,0f,0f}; + public boolean loading = true; + public String error = null; + public String[] errorStackTrace = null; + public final int[] glyphsHeight = new int[]{9, 6}; + public float translation = 0.0f; + public boolean translation_top_to_bottom = true; + public static float brightness = 1.0f; + + private Screen screen; + + public Display(Screen screen, int ww, int wh) { + this.ww = ww; + this.wh = wh; + setScreen(screen); + } +/* + private void load_skin() { + try { + skin_tex = glGenTextures(); + glBindTexture(GL_TEXTURE_2D, skin_tex); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + InputStream in = new FileInputStream("res/skin.png"); + PNGDecoder decoder = new PNGDecoder(in); + + System.out.println("width="+decoder.getWidth()); + System.out.println("height="+decoder.getHeight()); + + ByteBuffer buf = ByteBuffer.allocateDirect(4*decoder.getWidth()*decoder.getHeight()); + decoder.decode(buf, decoder.getWidth()*4, Format.RGBA); + buf.flip(); + + skin = buf; + skin_w = decoder.getWidth(); + skin_h = decoder.getHeight(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, skin_w, + skin_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, skin); + } catch (IOException ex) { + ex.printStackTrace(); + } + }*/ + + + private void setScreen(Screen screen) { + if (screen.initialized == false) { + if (screen.canBeInHistory) { + Calculator.currentSession = 0; + for (int i = 1; i < Calculator.sessions.length; i++) { + Calculator.sessions[i] = Calculator.sessions[i-1]; + } + Calculator.sessions[0] = this.screen; + } + } + screen.d = this; + try { + screen.initialize(); + this.screen = screen; + } catch (Exception e) { + e.printStackTrace(); + } + } + + private boolean canGoBack() { + if (this.screen != Calculator.sessions[Calculator.currentSession]) { + + } else if (Calculator.currentSession+1 < Calculator.sessions.length) { + if (Calculator.sessions[Calculator.currentSession + 1] != null) { + + } else { + return false; + } + } else { + return false; + } + if (Calculator.sessions[Calculator.currentSession] != null) { + return true; + } + return false; + } + + private void goBack() { + if (canGoBack()) { + if (this.screen != Calculator.sessions[Calculator.currentSession]) { + + } else { + Calculator.currentSession += 1; + } + this.screen = Calculator.sessions[Calculator.currentSession]; + } + } + + + private boolean canGoForward() { + if (this.screen != Calculator.sessions[Calculator.currentSession]) { + + } else if (Calculator.currentSession > 0) { + if (Calculator.sessions[Calculator.currentSession - 1] != null) { + + } else { + return false; + } + } else { + return false; + } + if (Calculator.sessions[Calculator.currentSession] != null) { + return true; + } + return false; + } + + private void goForward() { + if (canGoForward()) { + if (this.screen != Calculator.sessions[Calculator.currentSession]) { + + } else { + Calculator.currentSession -= 1; + } + this.screen = Calculator.sessions[Calculator.currentSession]; + } + } + + private Screen getScreen() { + return this.screen; + } + + + private void load_skin() { + ByteBuffer imageBuffer; + try { + imageBuffer = ioResourceToByteBuffer("skin.png", 8 * 1024); + } catch (IOException e) { + throw new RuntimeException(e); + } + skin_tex = glGenTextures(); + glBindTexture(GL_TEXTURE_2D, skin_tex); + IntBuffer w = BufferUtils.createIntBuffer(1); + IntBuffer h = BufferUtils.createIntBuffer(1); + IntBuffer comp = BufferUtils.createIntBuffer(1); + + skin = stbi_load_from_memory(imageBuffer, w, h, comp, 0); + + if ( skin == null ) + throw new RuntimeException("Failed to load image: " + stbi_failure_reason()); + skin_w = w.get(0); + skin_h = h.get(0); + skin_comp = comp.get(0); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + if ( skin_comp == 3 ) { + if ( (skin_w & 3) != 0 ) + glPixelStorei(GL_UNPACK_ALIGNMENT, 2 - (skin_w & 1)); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, skin_w, skin_h, 0, GL_RGB, GL_UNSIGNED_BYTE, skin); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, skin_w, skin_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, skin); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + glBindTexture(GL_TEXTURE_2D, 0); + + stbi_image_free(skin); + } + + private void load_fonts() { + font_tex = glGenTextures(); + chardata = STBTTPackedchar.mallocBuffer(6*maxCharIndex); + glBindTexture(GL_TEXTURE_2D, font_tex); + + + try { + STBTTPackContext pc = STBTTPackContext.malloc(); + ByteBuffer ttfBig = ioResourceToByteBuffer("font_big.ttf", 18000); + ByteBuffer ttfSmall = ioResourceToByteBuffer("font_small.ttf", 18000); + + ByteBuffer bitmap = BufferUtils.createByteBuffer(BITMAP_W * BITMAP_H); + + stbtt_PackBegin(pc, bitmap, BITMAP_W, BITMAP_H, 0, 1, null); + chardata.limit(maxCharIndex); + chardata.position(0); + stbtt_PackSetOversampling(pc, 1, 1); + stbtt_PackFontRange(pc, ttfBig, 0, 15 /* Font size */, 0, chardata); + chardata.clear(); + chardata.limit(maxCharIndex*2); + chardata.position(maxCharIndex); + stbtt_PackSetOversampling(pc, 1, 1); + stbtt_PackFontRange(pc, ttfSmall, 0, 15 /* Font size */, 0, chardata); + chardata.clear(); + stbtt_PackEnd(pc); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_W, BITMAP_H, 0, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void draw_init() { + glDisable(GL_CULL_FACE); + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glViewport(0, 0, fbw, fbh); + clearColor(background[0], background[1], background[2], 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0.0, ww, wh, 0.0, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + } + + private static void drawBoxTC(float x0, float y0, float x1, float y1, float s0, float t0, float s1, float t1) { + glTexCoord2f(s0, t0); + glVertex2f(x0, y0); + glTexCoord2f(s1, t0); + glVertex2f(x1, y0); + glTexCoord2f(s1, t1); + glVertex2f(x1, y1); + glTexCoord2f(s0, t1); + glVertex2f(x0, y1); + } + + private void print(float x, float y, int font, String text) { + xb.put(0, x); + yb.put(0, y+glyphsHeight[font]); + + chardata.position(font * maxCharIndex); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, font_tex); + + glBegin(GL_QUADS); + for ( int i = 0; i < text.length(); i++ ) { + stbtt_GetPackedQuad(chardata, BITMAP_W, BITMAP_H, text.charAt(i), xb, yb, q, (font == 0 && integer_align)?1:0); + drawBoxTC( + q.x0(), q.y0(), q.x1(), q.y1(), + q.s0(), q.t0(), q.s1(), q.t1() + ); + } + glEnd(); + glDisable( GL_TEXTURE_2D ); + } + + private int[] textSize(int font, String text) { + float[] size = new float[]{0,0}; + xb.put(0, 0); + yb.put(0, 0); + + chardata.position(font * maxCharIndex); + + for ( int i = 0; i < text.length(); i++ ) { + stbtt_GetPackedQuad(chardata, BITMAP_W, BITMAP_H, text.charAt(i), xb, yb, q, (font == 0 && integer_align)?1:0); + size[0]=q.x1(); + size[1]=q.y1(); + } + return new int[]{(int) size[0], (int) size[1]}; + } + + private void drawSkinPart(int[] posOnScreen, float[] posOnSkin) { + glEnable(GL_TEXTURE_2D); + colore(1, 1, 1, 1); + glBindTexture(GL_TEXTURE_2D, skin_tex); + + glBegin(GL_QUADS); + drawBoxTC(posOnScreen[0],posOnScreen[1],posOnScreen[2], posOnScreen[3], posOnSkin[0]/1000, posOnSkin[1]/100, posOnSkin[2]/1000, posOnSkin[3]/100); + glEnd(); + glDisable( GL_TEXTURE_2D ); + } + + private void drawLine(int[]... pos) { + glLineWidth(1.0f); + glBegin(GL_LINE_STRIP); + + for (int[] single_pos : pos) { + glVertex2d(single_pos[0], single_pos[1]); + glVertex2d(single_pos[2], single_pos[3]); + } + glEnd(); + } + + private void drawRect(int[]... pos) { + glLineWidth(1.0f); + glBegin(GL_QUADS); + + for (int[] single_pos : pos) { + glVertex2d(single_pos[0], single_pos[1]); + glVertex2d(single_pos[2], single_pos[1]); + glVertex2d(single_pos[2], single_pos[3]); + glVertex2d(single_pos[0], single_pos[3]); + } + glEnd(); + } + + + private void draw_status() { + colore(background[0],background[1],background[2]); + drawRect(new int[]{0,0,ww,20}); + colore(0,0,0); + drawLine(new int[]{0,20,ww,20}); + colore(0,0,0); + if (Keyboard.shift) { + drawSkinPart(new int[]{2+18*0,2,2+16+18*0,2+16}, new float[]{16*2,16*0,16+16*2,16+16*0}); + } else { + drawSkinPart(new int[]{2+18*0,2,2+16+18*0,2+16}, new float[]{16*3,16*0,16+16*3,16+16*0}); + } + if (Keyboard.alpha) { + drawSkinPart(new int[]{2+18*1,2,2+16+18*1,2+16}, new float[]{16*0,16*0,16+16*0,16+16*0}); + } else { + drawSkinPart(new int[]{2+18*1,2,2+16+18*1,2+16}, new float[]{16*1,16*0,16+16*1,16+16*0}); + } + if (Calculator.angleMode == "deg") { + drawSkinPart(new int[]{8+18*2,2,8+16+18*2,2+16}, new float[]{16*4,16*0,16+16*4,16+16*0}); + drawSkinPart(new int[]{8+18*3,2,8+16+18*3,2+16}, new float[]{16*7,16*0,16+16*7,16+16*0}); + drawSkinPart(new int[]{8+18*4,2,8+16+18*4,2+16}, new float[]{16*9,16*0,16+16*9,16+16*0}); + } else if (Calculator.angleMode == "rad") { + drawSkinPart(new int[]{8+18*2,2,8+16+18*2,2+16}, new float[]{16*5,16*0,16+16*5,16+16*0}); + drawSkinPart(new int[]{8+18*3,2,8+16+18*3,2+16}, new float[]{16*6,16*0,16+16*6,16+16*0}); + drawSkinPart(new int[]{8+18*4,2,8+16+18*4,2+16}, new float[]{16*9,16*0,16+16*9,16+16*0}); + } else if (Calculator.angleMode == "gra") { + drawSkinPart(new int[]{8+18*2,2,8+16+18*2,2+16}, new float[]{16*5,16*0,16+16*5,16+16*0}); + drawSkinPart(new int[]{8+18*3,2,8+16+18*3,2+16}, new float[]{16*7,16*0,16+16*7,16+16*0}); + drawSkinPart(new int[]{8+18*4,2,8+16+18*4,2+16}, new float[]{16*8,16*0,16+16*8,16+16*0}); + } else { + drawSkinPart(new int[]{8+18*2,2,8+16+18*2,2+16}, new float[]{16*5,16*0,16+16*5,16+16*0}); + drawSkinPart(new int[]{8+18*3,2,8+16+18*3,2+16}, new float[]{16*7,16*0,16+16*7,16+16*0}); + drawSkinPart(new int[]{8+18*4,2,8+16+18*4,2+16}, new float[]{16*9,16*0,16+16*9,16+16*0}); + } + + int padding = 2; + + int brightness = (int)(Display.brightness * 4); + if (brightness == 1) { + drawSkinPart(new int[]{ww-(padding+18*0),2,ww-(padding+16+18*0),2+16}, new float[]{16*10,16*0,16+16*10,16+16*0}); + } else if (brightness == 2) { + drawSkinPart(new int[]{ww-(padding+18*0),2,ww-(padding+16+18*0),2+16}, new float[]{16*11,16*0,16+16*11,16+16*0}); + } else if (brightness == 3) { + drawSkinPart(new int[]{ww-(padding+18*0),2,ww-(padding+16+18*0),2+16}, new float[]{16*12,16*0,16+16*12,16+16*0}); + } else if (brightness == 4) { + drawSkinPart(new int[]{ww-(padding+18*0),2,ww-(padding+16+18*0),2+16}, new float[]{16*13,16*0,16+16*13,16+16*0}); + } + + padding += 18+6; + + boolean canGoBack = canGoBack(); + boolean canGoForward = canGoForward(); + + + if (Calculator.haxMode) { + drawSkinPart(new int[]{ww-(padding+16),2,ww-padding,2+16}, new float[]{16*18,16*0,16+16*18,16+16*0}); + padding += 18+6; + } + + if (canGoBack && canGoForward) { + drawSkinPart(new int[]{ww-(padding+16),2,ww-padding,2+16}, new float[]{16*14,16*0,16+16*14,16+16*0}); + } else if (canGoBack) { + drawSkinPart(new int[]{ww-(padding+16),2,ww-padding,2+16}, new float[]{16*15,16*0,16+16*15,16+16*0}); + } else if (canGoForward) { + drawSkinPart(new int[]{ww-(padding+16),2,ww-padding,2+16}, new float[]{16*16,16*0,16+16*16,16+16*0}); + } else { + drawSkinPart(new int[]{ww-(padding+16),2,ww-padding,2+16}, new float[]{16*17,16*0,16+16*17,16+16*0}); + } + + padding += 18; + + } + + + private void draw_screen() { + screen.render(); + } + + + private void draw_bottom() { + + } + + private void draw_world() { + float x = 20; + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + colore(1.0f, 1.0f, 1.0f); + + if (error != null) { + colore(0.0f, 0.0f, 0.0f, 0.75f); + print(ww-textSize(1, "ANDREA CAVALLI'S CALCULATOR")[0]-2, wh-this.glyphsHeight[1]-2, 1, "ANDREA CAVALLI'S CALCULATOR"); + colore(0.0f, 0.0f, 0.0f, 0.75f); + print((ww/2)-(textSize(0, "UNEXPECTED EXCEPTION")[0]/2), 11, 0, "UNEXPECTED EXCEPTION"); + colore(0.0f, 0.0f, 0.0f, 0.5f); + print((ww/2)-(textSize(1, error)[0]/2), 22, 1, error); + colore(0.0f, 0.0f, 0.0f, 0.4f); + int i = 22; + for (String stackPart : errorStackTrace) { + print(2, 22+i, 1, stackPart); + i+=11; + } + } else if (loading) { + colore(1.0f, 1.0f, 1.0f, 1.0f); + int titlew = textSize(0, "ANDREA CAVALLI'S CALCULATOR")[0]; + print((ww/2)-(titlew/2)-1, (wh/2)-25+translation, 0, "ANDREA CAVALLI'S CALCULATOR"); + colore(1.0f, 1.0f, 1.0f, 1.0f); + print((ww/2)-(titlew/2)+1, (wh/2)-25+translation, 0, "ANDREA CAVALLI'S CALCULATOR"); + colore(1.0f, 1.0f, 1.0f, 1.0f); + print((ww/2)-(titlew/2), (wh/2)-25-1+translation, 0, "ANDREA CAVALLI'S CALCULATOR"); + colore(1.0f, 1.0f, 1.0f, 1.0f); + print((ww/2)-(titlew/2), (wh/2)-25+1+translation, 0, "ANDREA CAVALLI'S CALCULATOR"); + colore(1.0f, 0.5f, 0.0f, 1.0f); + print((ww/2)-(titlew/2), (wh/2)-25+translation, 0, "ANDREA CAVALLI'S CALCULATOR"); + colore(0.0f, 0.0f, 0.0f, 0.75f); + print((ww/2)-(textSize(0, "LOADING")[0]/2), (wh/2)+11, 0, "LOADING"); + colore(0.0f, 0.0f, 0.0f, 0.5f); + print((ww/2)-(textSize(1, "PLEASE WAIT...")[0]/2), (wh/2)+22, 1, "PLEASE WAIT..."); + } else { + draw_status(); + draw_screen(); + draw_bottom(); + } + } + + private void draw() { + draw_init(); + draw_world(); + glfwSwapBuffers(window); + } + + private void loopmode(float dt) { + + rotate_t += dt; + translate_t += dt; + + /* + * Calcoli + */ + + if (translation >= 10.0f) { + translation = 10.0f; + translation_top_to_bottom = false; + } else if (translation <= -10.0f) { + translation = -10.0f; + translation_top_to_bottom = true; + } + + if (translation_top_to_bottom) { + translation += dt*15; + } else { + translation -= dt*15; + } + + screen.beforeRender(dt); + + draw(); + } + + private GLFWKeyCallback keyCallback = new GLFWKeyCallback() { + @Override + public void invoke(long window, int key, int scancode, int action, int mods) { + if ( action == GLFW_RELEASE ) + return; + switch ( key ) { + case GLFW_KEY_ESCAPE: + glfwSetWindowShouldClose(window, GLFW_TRUE); + break; + case GLFW_KEY_F: + font = 1; + break; + case GLFW_KEY_R: + rotating = !rotating; + rotate_t = 0.0f; + break; + case GLFW_KEY_P: + integer_align = !integer_align; + break; + case GLFW_KEY_G: + font = 0; + break; + case GLFW_KEY_V: + show_tex = !show_tex; + break; + case GLFW_KEY_B: + black_on_white = !black_on_white; + break; + } + } + }; + + private GLFWWindowSizeCallback sizecallback = new GLFWWindowSizeCallback() { + @Override + public void invoke(long window, int width, int height) { + Display.this.ww = width; + Display.this.wh = height; + } + }; + + private GLFWFramebufferSizeCallback fbsizecallback = new GLFWFramebufferSizeCallback() { + @Override + public void invoke(long window, int width, int height) { + Display.this.fbw = width; + Display.this.fbh = height; + } + }; + + private void createWindow(String title) { + GLFWErrorCallback.createPrint().set(); + if ( glfwInit() == GLFW_FALSE ) + throw new IllegalStateException("Unable to initialize GLFW"); + + glfwDefaultWindowHints(); + glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); + glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); + + this.window = glfwCreateWindow(ww, wh, title, NULL, NULL); + if ( window == NULL ) + throw new RuntimeException("Failed to create the GLFW window"); + + glfwSetWindowSizeCallback(window, sizecallback); + glfwSetFramebufferSizeCallback(window, fbsizecallback); + glfwSetKeyCallback(window, keyCallback); + + // Center window + GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); + + glfwSetWindowPos( + window, + (vidmode.width() - ww) / 2, + (vidmode.height() - wh) / 2 + ); + + // Create context + glfwMakeContextCurrent(window); + GL.createCapabilities(); + + glfwSwapInterval(1); + glfwShowWindow(window); + + glfwInvoke(window, sizecallback, fbsizecallback); + + // Detect sRGB support + GLCapabilities caps = GL.getCapabilities(); + supportsSRGB = caps.OpenGL30 || caps.GL_ARB_framebuffer_sRGB || caps.GL_EXT_framebuffer_sRGB; + } + + public void run(String title) { + try { + createWindow(title); + load_skin(); + load_fonts(); + + long time = System.nanoTime(); + while ( glfwWindowShouldClose(window) == GLFW_FALSE ) { + glfwPollEvents(); + + long t = System.nanoTime(); + float dt = (float)((t - time) / 1000000000.0); + time = t; + + loopmode(dt); + } + } finally { + try { + destroy(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void destroy() { + chardata.clear(); + + glfwTerminate(); + glfwSetErrorCallback(null); + + memFree(yb); + memFree(xb); + + q.free(); + } + + public void setBackground(float d, float e, float f) { + background = new float[]{d,e,f}; + } + + public void colore(float f1, float f2, float f3) { + glColor3f(f1*brightness, f2*brightness, f3*brightness); + } + + public void colore(float f1, float f2, float f3, float f4) { + glColor4f(f1*brightness, f2*brightness, f3*brightness, f4); + } + + public void clearColor(float f1, float f2, float f3, float f4) { + glClearColor(f1*brightness,f2*brightness,f3*brightness,f4); + } +} \ No newline at end of file diff --git a/src/org/warp/engine/lwjgl/GLFWUtil.java b/src/org/warp/engine/lwjgl/GLFWUtil.java new file mode 100644 index 00000000..f40da149 --- /dev/null +++ b/src/org/warp/engine/lwjgl/GLFWUtil.java @@ -0,0 +1,47 @@ +package org.warp.engine.lwjgl; + +import org.lwjgl.glfw.GLFWFramebufferSizeCallbackI; +import org.lwjgl.glfw.GLFWWindowSizeCallbackI; +import org.lwjgl.system.MemoryStack; + +import java.nio.IntBuffer; + +import static org.lwjgl.glfw.GLFW.*; +import static org.lwjgl.system.MemoryStack.*; + +/** GLFW demo utilities. */ +public final class GLFWUtil { + + private GLFWUtil() { + } + + /** + * Invokes the specified callbacks using the current window and framebuffer sizes of the specified GLFW window. + * + * @param window the GLFW window + * @param windowSizeCB the window size callback, may be null + * @param framebufferSizeCB the framebuffer size callback, may be null + */ + public static void glfwInvoke( + long window, + GLFWWindowSizeCallbackI windowSizeCB, + GLFWFramebufferSizeCallbackI framebufferSizeCB + ) { + try ( MemoryStack stack = stackPush() ) { + IntBuffer w = stack.mallocInt(1); + IntBuffer h = stack.mallocInt(1); + + if ( windowSizeCB != null ) { + glfwGetWindowSize(window, w, h); + windowSizeCB.invoke(window, w.get(0), h.get(0)); + } + + if ( framebufferSizeCB != null ) { + glfwGetFramebufferSize(window, w, h); + framebufferSizeCB.invoke(window, w.get(0), h.get(0)); + } + } + + } + +} diff --git a/src/org/warp/engine/lwjgl/IOUtil.java b/src/org/warp/engine/lwjgl/IOUtil.java new file mode 100644 index 00000000..630d262d --- /dev/null +++ b/src/org/warp/engine/lwjgl/IOUtil.java @@ -0,0 +1,69 @@ +package org.warp.engine.lwjgl; + +import org.lwjgl.BufferUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.SeekableByteChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.lwjgl.BufferUtils.*; + +public final class IOUtil { + + private IOUtil() { + } + + private static ByteBuffer resizeBuffer(ByteBuffer buffer, int newCapacity) { + ByteBuffer newBuffer = BufferUtils.createByteBuffer(newCapacity); + buffer.flip(); + newBuffer.put(buffer); + return newBuffer; + } + + /** + * Reads the specified resource and returns the raw data as a ByteBuffer. + * + * @param resource the resource to read + * @param bufferSize the initial buffer size + * + * @return the resource data + * + * @throws IOException if an IO error occurs + */ + public static ByteBuffer ioResourceToByteBuffer(String resource, int bufferSize) throws IOException { + ByteBuffer buffer; + + Path path = Paths.get(resource); + if ( Files.isReadable(path) ) { + try (SeekableByteChannel fc = Files.newByteChannel(path)) { + buffer = BufferUtils.createByteBuffer((int)fc.size() + 1); + while ( fc.read(buffer) != -1 ) ; + } + } else { + try ( + InputStream source = IOUtil.class.getClassLoader().getResourceAsStream(resource); + ReadableByteChannel rbc = Channels.newChannel(source) + ) { + buffer = createByteBuffer(bufferSize); + + while ( true ) { + int bytes = rbc.read(buffer); + if ( bytes == -1 ) + break; + if ( buffer.remaining() == 0 ) + buffer = resizeBuffer(buffer, buffer.capacity() * 2); + } + } + } + + buffer.flip(); + return buffer; + } + +} \ No newline at end of file diff --git a/src/org/warp/engine/lwjgl/Screen.java b/src/org/warp/engine/lwjgl/Screen.java new file mode 100644 index 00000000..9316d88d --- /dev/null +++ b/src/org/warp/engine/lwjgl/Screen.java @@ -0,0 +1,23 @@ +package org.warp.engine.lwjgl; + +public abstract class Screen { + public Display d; + public boolean initialized = false; + public boolean canBeInHistory = false; + + public Screen() { + } + + public void initialize() throws InterruptedException { + if (!initialized) { + initialized = true; + init(); + } + } + + public abstract void init() throws InterruptedException; + + public abstract void render(); + + public abstract void beforeRender(float dt); +} diff --git a/src/org/warpgate/pi/calculator/BMPFile.java b/src/org/warpgate/pi/calculator/BMPFile.java new file mode 100644 index 00000000..fb24a7e7 --- /dev/null +++ b/src/org/warpgate/pi/calculator/BMPFile.java @@ -0,0 +1,212 @@ +package org.warpgate.pi.calculator; +import java.awt.*; +import java.io.*; +import java.awt.image.*; +public class BMPFile extends Component { + //--- Private constants + private final static int BITMAPFILEHEADER_SIZE = 14; + private final static int BITMAPINFOHEADER_SIZE = 40; + //--- Private variable declaration + //--- Bitmap file header + private byte bitmapFileHeader [] = new byte [14]; + private byte bfType [] = {'B', 'M'}; + private int bfSize = 0; + private int bfReserved1 = 0; + private int bfReserved2 = 0; + private int bfOffBits = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE; + //--- Bitmap info header + private byte bitmapInfoHeader [] = new byte [40]; + private int biSize = BITMAPINFOHEADER_SIZE; + private int biWidth = 0; + private int biHeight = 0; + private int biPlanes = 1; + private int biBitCount = 24; + private int biCompression = 0; + private int biSizeImage = 0x030000; + private int biXPelsPerMeter = 0x0; + private int biYPelsPerMeter = 0x0; + private int biClrUsed = 0; + private int biClrImportant = 0; + //--- Bitmap raw data + private int bitmap []; + //--- File section + private FileOutputStream fo; + //--- Default constructor + public BMPFile() { + } + public void saveBitmap (String parFilename, Image parImage, int +parWidth, int parHeight) { + try { + fo = new FileOutputStream (parFilename); + save (parImage, parWidth, parHeight); + fo.close (); + } + catch (Exception saveEx) { + saveEx.printStackTrace (); + } + } + /* + * The saveMethod is the main method of the process. This method + * will call the convertImage method to convert the memory image to + * a byte array; method writeBitmapFileHeader creates and writes + * the bitmap file header; writeBitmapInfoHeader creates the + * information header; and writeBitmap writes the image. + * + */ + private void save (Image parImage, int parWidth, int parHeight) { + try { + convertImage (parImage, parWidth, parHeight); + writeBitmapFileHeader (); + writeBitmapInfoHeader (); + writeBitmap (); + } + catch (Exception saveEx) { + saveEx.printStackTrace (); + } + } + /* + * convertImage converts the memory image to the bitmap format (BRG). + * It also computes some information for the bitmap info header. + * + */ + private boolean convertImage (Image parImage, int parWidth, int parHeight) { + int pad; + bitmap = new int [parWidth * parHeight]; + PixelGrabber pg = new PixelGrabber (parImage, 0, 0, parWidth, parHeight, + bitmap, 0, parWidth); + try { + pg.grabPixels (); + } + catch (InterruptedException e) { + e.printStackTrace (); + return (false); + } + pad = (4 - ((parWidth * 3) % 4)) * parHeight; + biSizeImage = ((parWidth * parHeight) * 3) + pad; + bfSize = biSizeImage + BITMAPFILEHEADER_SIZE + +BITMAPINFOHEADER_SIZE; + biWidth = parWidth; + biHeight = parHeight; + return (true); + } + /* + * writeBitmap converts the image returned from the pixel grabber to + * the format required. Remember: scan lines are inverted in + * a bitmap file! + * + * Each scan line must be padded to an even 4-byte boundary. + */ + private void writeBitmap () { + int size; + int value; + int j; + int i; + int rowCount; + int rowIndex; + int lastRowIndex; + int pad; + int padCount; + byte rgb [] = new byte [3]; + size = (biWidth * biHeight) - 1; + pad = 4 - ((biWidth * 3) % 4); + if (pad == 4) // <==== Bug correction + pad = 0; // <==== Bug correction + rowCount = 1; + padCount = 0; + rowIndex = size - biWidth; + lastRowIndex = rowIndex; + try { + for (j = 0; j < size; j++) { + value = bitmap [rowIndex]; + rgb [0] = (byte) (value & 0xFF); + rgb [1] = (byte) ((value >> 8) & 0xFF); + rgb [2] = (byte) ((value >> 16) & 0xFF); + fo.write (rgb); + if (rowCount == biWidth) { + padCount += pad; + for (i = 1; i <= pad; i++) { + fo.write (0x00); + } + rowCount = 1; + rowIndex = lastRowIndex - biWidth; + lastRowIndex = rowIndex; + } + else + rowCount++; + rowIndex++; + } + //--- Update the size of the file + bfSize += padCount - pad; + biSizeImage += padCount - pad; + } + catch (Exception wb) { + wb.printStackTrace (); + } + } + /* + * writeBitmapFileHeader writes the bitmap file header to the file. + * + */ + private void writeBitmapFileHeader () { + try { + fo.write (bfType); + fo.write (intToDWord (bfSize)); + fo.write (intToWord (bfReserved1)); + fo.write (intToWord (bfReserved2)); + fo.write (intToDWord (bfOffBits)); + } + catch (Exception wbfh) { + wbfh.printStackTrace (); + } + } + /* + * + * writeBitmapInfoHeader writes the bitmap information header + * to the file. + * + */ + private void writeBitmapInfoHeader () { + try { + fo.write (intToDWord (biSize)); + fo.write (intToDWord (biWidth)); + fo.write (intToDWord (biHeight)); + fo.write (intToWord (biPlanes)); + fo.write (intToWord (biBitCount)); + fo.write (intToDWord (biCompression)); + fo.write (intToDWord (biSizeImage)); + fo.write (intToDWord (biXPelsPerMeter)); + fo.write (intToDWord (biYPelsPerMeter)); + fo.write (intToDWord (biClrUsed)); + fo.write (intToDWord (biClrImportant)); + } + catch (Exception wbih) { + wbih.printStackTrace (); + } + } + /* + * + * intToWord converts an int to a word, where the return + * value is stored in a 2-byte array. + * + */ + private byte [] intToWord (int parValue) { + byte retValue [] = new byte [2]; + retValue [0] = (byte) (parValue & 0x00FF); + retValue [1] = (byte) ((parValue >> 8) & 0x00FF); + return (retValue); + } + /* + * + * intToDWord converts an int to a double word, where the return + * value is stored in a 4-byte array. + * + */ + private byte [] intToDWord (int parValue) { + byte retValue [] = new byte [4]; + retValue [0] = (byte) (parValue & 0x00FF); + retValue [1] = (byte) ((parValue >> 8) & 0x000000FF); + retValue [2] = (byte) ((parValue >> 16) & 0x000000FF); + retValue [3] = (byte) ((parValue >> 24) & 0x000000FF); + return (retValue); + } +} \ No newline at end of file diff --git a/src/org/warpgate/pi/calculator/Equazione.java b/src/org/warpgate/pi/calculator/Equazione.java new file mode 100644 index 00000000..c82b4253 --- /dev/null +++ b/src/org/warpgate/pi/calculator/Equazione.java @@ -0,0 +1,46 @@ +package org.warpgate.pi.calculator; + +import java.util.Vector; + +import com.rits.cloning.Cloner; + +public class Equazione extends FunzioneDueValori { + + public Equazione(Funzione value1, Funzione value2) { + super(value1, value2); + } + + @Override + public String simbolo() { + return Simboli.EQUATION; + } + + @Override + public Termine calcola() throws Errore { + return new Sottrazione(getVariable1().calcola(),getVariable2().calcola()).calcola(); + } + + public Vector risolviPassaggio(char charIncognita) { + Vector result = new Vector(); + result.add(this.clone()); + for (Tecnica t : Tecnica.tecniche) { + Vector newResults = new Vector(); + final int sz = result.size(); + for (int n = 0; n < sz; n++) { + Vector singleResult = t.risolvi(result.get(n)); + final int sz2 = singleResult.size(); + for (int n2 = 0; n2 < sz2; n2++) { + + } + } + } + //TODO: finire + return result; + } + + public Equazione clone() { + Cloner cloner = new Cloner(); + return cloner.deepClone(this); + } + +} \ No newline at end of file diff --git a/src/org/warpgate/pi/calculator/Incognita.java b/src/org/warpgate/pi/calculator/Incognita.java new file mode 100644 index 00000000..34da74c3 --- /dev/null +++ b/src/org/warpgate/pi/calculator/Incognita.java @@ -0,0 +1,42 @@ +package org.warpgate.pi.calculator; + +import java.math.BigInteger; + +import org.nevec.rjm.Rational; + +public class Incognita { + public char simbolo = 'X'; + public Rational esponente = Rational.ONE; + + public Incognita(char simbolo, Rational esponente) { + this.simbolo = simbolo; + this.esponente = esponente; + } + + public Incognita(char simbolo, int a, int b) { + this.simbolo = simbolo; + this.esponente = new Rational(a, b); + } + + public Incognita(char simbolo) { + this.simbolo = simbolo; + this.esponente = new Rational(1, 1); + } + + @Override + public boolean equals(Object o) { + if (o instanceof Incognita) { + if (this.simbolo == ((Incognita) o).simbolo) { + if (this.esponente == ((Incognita) o).esponente) { + return true; + } + } + } + return false; + } + + @Override + public int hashCode() { + return Character.getNumericValue(simbolo)*3+esponente.hashCode(); + } +} diff --git a/src/org/warpgate/pi/calculator/Incognite.java b/src/org/warpgate/pi/calculator/Incognite.java new file mode 100644 index 00000000..4085d2ec --- /dev/null +++ b/src/org/warpgate/pi/calculator/Incognite.java @@ -0,0 +1,388 @@ +package org.warpgate.pi.calculator; + +import java.math.BigInteger; +import java.text.Collator; +import java.util.Comparator; +import java.util.List; +import java.util.Vector; + +import org.nevec.rjm.BigIntegerMath; +import org.nevec.rjm.Rational; + +public class Incognite { + + Vector incognite; + + public Incognite() { + incognite = new Vector(); + } + + public Incognite(Incognita[] value) { + this(); + for (Incognita i : value) { + incognite.add(i); + } + } + + public Incognite(Vector value) { + this(); + incognite = value; + } + + public Incognite(Incognita value) { + this(); + incognite.add(value); + } + + public int count() { + return incognite.size(); + } + + public boolean contieneSimbolo(char simbolo) { + for (Incognita i : incognite) { + if (i.simbolo == simbolo) { + return true; + } + } + return false; + } + + public Rational prendiEsponenteSimbolo(char simbolo) { + for (Incognita i : incognite) { + if (i.simbolo == simbolo) { + return i.esponente; + } + } + return new Rational(0, 1); + } + + public void impostaEsponenteSimbolo(char simbolo, Rational esponente) { + for (Incognita i : incognite) { + if (i.simbolo == simbolo) { + i.esponente = esponente; + } + } + } + + @SuppressWarnings("unchecked") + @Override + public Incognite clone() { + return new Incognite((Vector) incognite.clone()).normalize(); + } + + public Incognite multiply(Incognite val) { + Incognite result = new Incognite(); + //Passaggio 1: test vari + //Se il primo gruppo di incognite è nullo allora ritorna il secondo gruppo + if (this.count() == 0) { + result = val.clone(); + return result; + } + //Se il secondo gruppo di incognite è nullo allora ritorna il primo gruppo + if (val.count() == 0) { + result = this.clone(); + return result; + } + + //Passaggio 2: le incognite doppie vengono raggruppate. + for (Incognita i1 : incognite) { + for (Incognita i2 : val.incognite) { + if (i1.simbolo == i2.simbolo) { + if (!result.contieneSimbolo(i1.simbolo)) { + Incognita ir = new Incognita(i1.simbolo, i1.esponente.add(i2.esponente)); + result.incognite.add(ir); + } + } + } + } + //Passaggio 3: le incognite non ancora presenti vengono aggiunte. + for (Incognita i : incognite) { + if (!result.contieneSimbolo(i.simbolo)) { + result.incognite.add(i); + } + } + for (Incognita i : val.incognite) { + if (!result.contieneSimbolo(i.simbolo)) { + result.incognite.add(i); + } + } + return result.normalize(); + } + + public Incognite divide(Incognite val) { + Incognite result = new Incognite(); + + //Passaggio 2: le incognite doppie vengono raggruppate. + for (Incognita i1 : incognite) { + for (Incognita i2 : val.incognite) { + if (i1.simbolo == i2.simbolo) { + if (!result.contieneSimbolo(i1.simbolo)) { + Incognita ir = new Incognita(i1.simbolo, i1.esponente.add(i2.esponente.multiply(new Rational(-1, 1)))); + result.incognite.add(ir); + } + } + } + } + //Passaggio 3: le incognite non ancora presenti vengono aggiunte. + for (Incognita i : incognite) { + if (!result.contieneSimbolo(i.simbolo)) { + result.incognite.add(i); + } + } + for (Incognita i : val.incognite) { + if (!result.contieneSimbolo(i.simbolo)) { + result.incognite.add(new Incognita(i.simbolo, i.esponente.multiply(new Rational(-1, 1)))); + } + } + return result.normalize(); + } + + public Incognite sqrt() { + Incognite result = new Incognite(); + for (Incognita i1 : incognite) { + Incognita ir = null; + try { + ir = new Incognita(i1.simbolo, i1.esponente.divide(new Rational(2, 1))); + } catch (Errore e) { + e.printStackTrace(); + } + result.incognite.add(ir); + } + return result.normalize(); + } + + public Incognite normalize() { + Incognite result = new Incognite(); + for (Incognita i1 : incognite) { + if (i1.esponente.compareTo(Rational.ZERO) != 0) { + result.incognite.add(i1); + } + } + result.incognite.sort(new Comparator() { + @Override + public int compare(Incognita o1, Incognita o2) { + int index1 = letterIndex(o1.simbolo); + int index2 = letterIndex(o2.simbolo); + return index1-index2; + } + }); + return result; + } + + public byte letterIndex(char l) { + return letterIndex(l, false); + } + public static byte letterIndex(char l, boolean reverse) { + int total = Simboli.incognite().length-1; + for (byte x = 0; x < Simboli.incognite().length; x++) { + if (Simboli.incognite()[x].equals(""+l)) { + if (reverse) { + return (byte) (total-x); + } else { + return x; + } + } + } + + return -1; + } + + public boolean compareTo(Incognite val) { + if (this.equals(val)) return true; + return false; + } + + @Override + public boolean equals(Object val) { + if (val == null) return false; + if (val instanceof Incognite) { + Incognite ii2 = (Incognite) val; + for (Incognita i1 : incognite) { + boolean found = false; + for (Incognita i2 : ii2.incognite) { + if (i1.simbolo == i2.simbolo) { + if (i1.esponente.compareTo(i2.esponente) != 0) + return false; + found = true; + } + } + if (!found) { + return false; + } + } + for (Incognita i1 : ii2.incognite) { + boolean found = false; + for (Incognita i2 : incognite) { + if (i1.simbolo == i2.simbolo) { + if (i1.esponente.compareTo(i2.esponente) != 0) + return false; + found = true; + } + } + if (!found) { + return false; + } + } + return true; + } + return false; + } + + @Override + public String toString() { + String result = ""; + if (incognite.size() != 1) { + for (Incognita i : incognite) { + if (i.esponente.compareTo(Rational.ONE) != 0) { + result += "("+i.simbolo+"^"+i.esponente+")"; + } else { + result += i.simbolo; + } + } + } else if (incognite.size() == 1) { + Incognita i = incognite.get(0); + if (i.esponente.compareTo(Rational.ONE) != 0) { + result += ""+i.simbolo+"^"+i.esponente+""; + } else if (i.esponente.compareTo(Rational.ONE) == 0) { + result += i.simbolo; + } + } + return result; + } + + public static Incognite lcm(Incognite val1, Incognite val2) { + Incognite result = new Incognite(); + //Passaggio 1: test vari + //Se il primo gruppo di incognite è nullo allora ritorna il secondo gruppo + if (val1.count() == 0) { + result = val2.clone(); + return result; + } + //Se il secondo gruppo di incognite è nullo allora ritorna il primo gruppo + if (val2.count() == 0) { + result = val1.clone(); + return result; + } + + //Passaggio 2: le incognite doppie vengono raggruppate. + for (Incognita i1 : val1.incognite) { + for (Incognita i2 : val2.incognite) { + if (i1.simbolo == i2.simbolo) { + if (!result.contieneSimbolo(i1.simbolo)) { + Incognita ir = new Incognita(i1.simbolo); + if (i1.esponente.compareTo(i2.esponente) > 0) { + ir.esponente = i1.esponente; + } else { + ir.esponente = i2.esponente; + } + result.incognite.add(ir); + } + } + } + } + //Passaggio 3: le incognite non ancora presenti vengono aggiunte. + for (Incognita i : val1.incognite) { + if (!result.contieneSimbolo(i.simbolo)) { + result.incognite.add(i); + } + } + for (Incognita i : val2.incognite) { + if (!result.contieneSimbolo(i.simbolo)) { + result.incognite.add(i); + } + } + return result.normalize(); + } + + @SuppressWarnings("unchecked") + public Vector listaIncognite() { + return (Vector) this.incognite.clone(); + } + + public static Incognite[] normalizeBigSurdVariables(Incognite[] incognitetemp) throws Errore { + Incognite incognitex = incognitetemp[0].clone(); + Incognite incognitey = incognitetemp[1].clone(); + Incognite incognitez = incognitetemp[2].clone(); + + Incognite newincognitex = new Incognite(); + for (Incognita i : incognitex.incognite) { + Vector divisori = BigIntegerMath.divisors(i.esponente.divide(2).denom()); + if (divisori.contains(new BigInteger("2"))) { + newincognitex = newincognitex.multiply(new Incognite(i)); + } else { + incognitey = incognitey.multiply(new Incognite(new Incognita(i.simbolo, i.esponente.divide(2)))); + } + } + incognitex = newincognitex; + + + for (Incognita i : incognitey.incognite) { + if (i.esponente.signum() < 0) { + incognitey = incognitey.divide(new Incognite(i)); + incognitez = incognitez.divide(new Incognite(i)); + } + } + for (Incognita i : incognitez.incognite) { + if (i.esponente.signum() < 0) { + incognitey = incognitey.divide(new Incognite(i)); + incognitez = incognitez.divide(new Incognite(i)); + } + } + + //TODO: SPOSTARE LE Y NEGATIVE SOTTO LA FRAZIONE, DALLA Y ALLA Z + + + Incognite incogniteyresult = new Incognite(); + Incognite incognitezresult = new Incognite(); + //Le incognite doppie vengono tolte + for (Incognita i1 : incognitey.incognite) { + for (Incognita i2 : incognitez.incognite) { + if (i1.simbolo == i2.simbolo) { + if (i1.esponente.compareTo(i2.esponente) > 0) { + incogniteyresult = incogniteyresult.multiply(new Incognite(new Incognita(i1.simbolo, i1.esponente.subtract(i2.esponente)))); + } else if (i2.esponente.compareTo(i1.esponente) > 0) { + incognitezresult = incognitezresult.multiply(new Incognite(new Incognita(i1.simbolo, i2.esponente.subtract(i1.esponente)))); + } + } + } + } + + //Le altre incognite vengono ri-messe + for (Incognita i : incognitey.incognite) { + if (!incogniteyresult.contieneSimbolo(i.simbolo)) { + incogniteyresult = incogniteyresult.multiply(new Incognite(i)); + } + } + for (Incognita i : incognitez.incognite) { + if (!incognitezresult.contieneSimbolo(i.simbolo)) { + incognitezresult = incognitezresult.multiply(new Incognite(i)); + } + } + + incognitey = incogniteyresult; + incognitez = incognitezresult; + + return new Incognite[]{incognitex, incognitey, incognitez}; + } + + public static int priorità(Incognite ii) { + double priorità = 0; + double letterMax = 0; + for(Incognita i : ii.incognite) { + int lettIndex = letterIndex(i.simbolo, true); + if (lettIndex > letterMax) { + letterMax = lettIndex; + } + } + priorità+=letterMax*100000; + + for(Incognita i : ii.incognite) { + int lettIndex = letterIndex(i.simbolo, true); + if (letterMax == lettIndex) { + priorità+=i.esponente.doubleValue()*100000; + } + priorità+=+i.esponente.doubleValue(); + } + return (int) priorità; + } +} diff --git a/src/org/warpgate/pi/calculator/Keyboard.java b/src/org/warpgate/pi/calculator/Keyboard.java new file mode 100644 index 00000000..f9f9da65 --- /dev/null +++ b/src/org/warpgate/pi/calculator/Keyboard.java @@ -0,0 +1,6 @@ +package org.warpgate.pi.calculator; + +public class Keyboard { + public static boolean alpha = false; + public static boolean shift = false; +} diff --git a/src/org/warpgate/pi/calculator/ParteSistema.java b/src/org/warpgate/pi/calculator/ParteSistema.java new file mode 100644 index 00000000..f49f568b --- /dev/null +++ b/src/org/warpgate/pi/calculator/ParteSistema.java @@ -0,0 +1,63 @@ +package org.warpgate.pi.calculator; + +import java.awt.Color; + +import org.nevec.rjm.Rational; +import org.warp.engine.Display; + +public class ParteSistema extends FunzioneAnteriore { + + public ParteSistema(Funzione value) { + super(value); + } + + @Override + public String simbolo() { + return Simboli.SYSTEM; + } + + @Override + public Termine calcola() throws NumberFormatException, Errore { + //TODO implementare il calcolo dei sistemi + return variable.calcola(); + } + + + @Override + public void draw(int x, int y, Display g, boolean small) { + small = false; + final int h = this.getHeight(small)-1; + final int varLine = variable.getLine(small); + final int paddingTop = 3; + final int spazioSotto = (h-3-2)/2+paddingTop; + final int spazioSopra = h - spazioSotto; + variable.draw(x+5, y+paddingTop, g, small); + g.setColor(Color.black); + g.drawOrthoLine(x+2, y+0, x+3, y+0); + g.drawOrthoLine(x+1, y+1, x+1, y+spazioSotto/2); + g.drawOrthoLine(x+2, y+spazioSotto/2+1, x+2, y+spazioSotto-1); + g.drawOrthoLine(x+0, y+spazioSotto, x+1, y+spazioSotto); + g.drawOrthoLine(x+2, y+spazioSotto+1, x+2, y+spazioSotto+spazioSopra/2-1); + g.drawOrthoLine(x+1, y+spazioSotto+spazioSopra/2, x+1, y+h-1); + g.drawOrthoLine(x+2, y+h, x+3, y+h); + } + + @Override + public int getWidth() { + return 5+getVariable().getWidth(); + } + + @Override + public int getHeight(boolean small) { + small = false; + int h1 = 3+getVariable().getHeight(small)+2; + return h1; + } + + @Override + public int getLine(boolean small) { + small = false; + int h1 = 3+getVariable().getLine(small); + return h1; + } +} diff --git a/src/org/warpgate/pi/calculator/Sottrazione.java b/src/org/warpgate/pi/calculator/Sottrazione.java new file mode 100644 index 00000000..60b1ff37 --- /dev/null +++ b/src/org/warpgate/pi/calculator/Sottrazione.java @@ -0,0 +1,22 @@ +package org.warpgate.pi.calculator; + +import java.awt.Color; +import java.awt.Graphics; + +public class Sottrazione extends FunzioneDueValori { + + public Sottrazione(Funzione value1, Funzione value2) { + super(value1, value2); + } + + @Override + public String simbolo() { + return Simboli.SUBTRACTION; + } + + @Override + public Termine calcola() throws Errore { + return getVariable1().calcola().add(getVariable2().calcola().multiply(new Termine("-1"))); + } + +} \ No newline at end of file diff --git a/src/org/warpgate/pi/calculator/Tecnica.java b/src/org/warpgate/pi/calculator/Tecnica.java new file mode 100644 index 00000000..aa70269c --- /dev/null +++ b/src/org/warpgate/pi/calculator/Tecnica.java @@ -0,0 +1,9 @@ +package org.warpgate.pi.calculator; + +import java.util.Vector; + +public interface Tecnica { + public static final Tecnica[] tecniche = new Tecnica[] {}; + + public abstract Vector risolvi(Equazione equazione); +} diff --git a/src/org/warpgate/pi/calculator/screens/EmptyScreen.java b/src/org/warpgate/pi/calculator/screens/EmptyScreen.java new file mode 100644 index 00000000..db2c4a2b --- /dev/null +++ b/src/org/warpgate/pi/calculator/screens/EmptyScreen.java @@ -0,0 +1,29 @@ +package org.warpgate.pi.calculator.screens; + +import org.warp.engine.lwjgl.Screen; + +public class EmptyScreen extends Screen { + + public float endLoading; + + @Override + public void init() throws InterruptedException { + canBeInHistory = true; + endLoading = 0; + } + + @Override + public void render() { + // TODO Auto-generated method stub + + } + + @Override + public void beforeRender(float dt) { + endLoading += dt; + if (d.loading & endLoading >= 2.5) { + d.loading = false; + } + } + +} diff --git a/src/org/warpgate/pi/calculator/screens/EquationScreen.java b/src/org/warpgate/pi/calculator/screens/EquationScreen.java new file mode 100644 index 00000000..116d1a06 --- /dev/null +++ b/src/org/warpgate/pi/calculator/screens/EquationScreen.java @@ -0,0 +1,203 @@ +package org.warpgate.pi.calculator.screens; + +import java.awt.Color; +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.warp.engine.lwjgl.Screen; +import org.warpgate.pi.calculator.Calculator; +import org.warpgate.pi.calculator.Errore; +import org.warpgate.pi.calculator.Errori; +import org.warpgate.pi.calculator.Funzione; +import org.warpgate.pi.calculator.Main; +import org.warpgate.pi.calculator.Parentesi; +import org.warpgate.pi.calculator.RisultatoEquazione; +import org.warpgate.pi.calculator.Termine; + +public class EquationScreen extends Screen { + + public float endLoading; + public static volatile String equazione = ""; + public static Parentesi f; + public static Funzione f2; + public static int ew1; + public static int ew2; + public static int eh2; + public static int x1; + public static int x2; + public static boolean requiresleep1; + public static boolean requiresleep2; + public static boolean aftersleep; + public static boolean autoscroll; + + @Override + public void init() throws InterruptedException { + canBeInHistory = true; + endLoading = 0; + try { + /* Fine caricamento */ + + //Parentesi f = new Parentesi("(â’¶(2X)*3Y)/(5Z^2)+(â’¶(11A)*13B)/(7CZ)=19XZ"); + //PARENTESI CON CALCOLI + //Funzione f = new Sottrazione(new Somma(new Parentesi("â’¶9/2+â’¶7/2", "").calcola(), new Termine("3.5")), new Parentesi("3*2√14","").calcola()); + //PARENTESI CON DUE NUMERI FRAZIONALI COMPLETI CON INCOGNITE: + //Funzione f = new Parentesi("(â’¶(2X)*3Y)/(5Z^2)+(â’¶(11A)*13B)/(7CZ)", ""); + //PARENTESI CON DUE NUMERI FRAZIONALI DISALLINEATI GRAFICAMENTE: + //Funzione f = new Parentesi("((5^2-1)/2)/5-5/(5/2)=2", ""); + //TERMINE DI PROVA COMPLETO: + //Funzione f = new Termine(new NumeroAvanzato(new Rational(3, 2), new Rational(7, 1), new Incognite(new Incognita('X', Rational.ONE)), new Incognite(new Incognita('Y', Rational.ONE)), new Incognite(new Incognita('z', Rational.ONE)))); + //PARENTESI REALISTICA CON INCOGNITE: + //Funzione f = new Equazione(new Parentesi("X^2+(MX-M+4)^2-4X-4(MX-M+4)^2+7", ""), new Termine("0")); + //POTENZA: + //Funzione f = new Parentesi("(MX-M+4)^2", ""); + //NUMERO SEMPLICE LUNGO: + //Funzione f = new Parentesi("-1219999799999996934.42229", ""); + //: + //Funzione f = new Parentesi("5Y+XY=2", "") + + equazione = "0"; + f = new Parentesi(equazione); + f2 = f.calcolaSistema(); + + + ew1 = f.getWidth(); + ew2 = f2.getWidth(); + eh2 = f2.getHeight(false); + x1 = 2; + x2 = 2; + requiresleep1 = false; + requiresleep2 = false; + aftersleep = false; + autoscroll = false; + + long start = System.nanoTime(); + Termine result = Calculator.calcolarisultato("((5â’·2+3√(100/0.1))*â’¶7+9/15*2√(26/2))/21"); + long end = System.nanoTime(); + long timeElapsed = end-start; + System.out.println("RESULT: " + result); + System.out.println("DECIMAl RESULT: " + result.getTerm().toBigDecimal()); + System.out.println("Time elapsed: " + (double) timeElapsed / 1000000 + " milliseconds\n"); + + + start = System.nanoTime(); + RisultatoEquazione eresult = Calculator.calcolaequazione("((5â’·2+3√(100/0.1))*â’¶7+9/15*2√(26/2))/21=(175*(2√7)+3*(2√13))/105"); + end = System.nanoTime(); + timeElapsed = end-start; + System.out.println("Is an equation: " + eresult.isAnEquation); + System.out.println("L-R: " + eresult.LR); + System.out.println("Time elapsed: " + (double) timeElapsed / 1000000 + " milliseconds\n"); + } catch (Errore e) { + d.setBackground(0.99609375f,102f/256f,34f/256f); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + d.errorStackTrace = sw.toString().toUpperCase().replace("\t", " ").replace("\r", "").split("\n"); + d.error = e.id.toString(); + System.err.println(e.id); + } + } + + public void calcola(String eqn) { + equazione = eqn.replace("sqrt", "â’¶").replace("^", "â’·"); + try { + f = new Parentesi(equazione); + } catch (Errore e) { + e.printStackTrace(); + } + try { + f2 = f.calcolaSistema(); + } catch (Errore e) { + e.printStackTrace(); + } + ew1 = f.getWidth(); + ew2 = f2.getWidth(); + eh2 = f2.getHeight(false); + x1 = 2; + x2 = 2; + requiresleep1 = false; + requiresleep2 = false; + aftersleep = false; + autoscroll = false; + } + + @Override + public void beforeRender(float dt) { + endLoading += dt; + if (endLoading >= 2.5) { + d.loading = false; + } + } + + @Override + public void render() { + d.setBackground(0.796875f, 0.90234375f, 0.828125f); + try { +// long delta = System.currentTimeMillis(); +// +// if (equazione == "") { +// throw new Errore(Errori.SYNTAX_ERROR); +// } else { +// if (ew1 + x1 + 5 > screenSize[0] && !requiresleep1 && autoscroll) { +// x1-=1; +// } else if(autoscroll) { +// requiresleep1 = true; +// } +// +// if (ew2 + x2 + 5 > screenSize[0] && !requiresleep2 && autoscroll) { +// x2-=1; +// } else if(autoscroll) { +// requiresleep2 = true; +// } +// +// if (requiresleep1 && requiresleep2 && autoscroll) { +// requiresleep1 = false; +// requiresleep2 = false; +// try { +// Thread.sleep(500); +// } catch (InterruptedException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// x1 = 2; +// x2 = 2; +// aftersleep = true; +// } +// +// f.draw(x1,2,d, false); +// f2.draw(x2,screenSize[1]-2-eh2,d, false); +// } +// +// if (aftersleep && autoscroll) { +// aftersleep = false; +// try { +// Thread.sleep(500); +// } catch (InterruptedException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// } +// +// try { +// delta = System.currentTimeMillis() - delta; +// if (50-delta > 0 && autoscroll) { +// Thread.sleep(50-delta); +// } +// } catch (InterruptedException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } + if (false) { + throw new Errore(Errori.SYNTAX_ERROR); + } + } catch (Errore e) { + d.setBackground(0.99609375f,102f/256f,34f/256f); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + d.errorStackTrace = sw.toString().toUpperCase().replace("\t", " ").replace("\r", "").split("\n"); + d.error = e.id.toString(); + System.err.println(e.id); + } + } + +}