sincos.hpp Gecode Gecode::Float Gecode::Float::Trigonometric I0__PI_2I FloatVal(0,pi_half_upper()) IPI_2__PII FloatVal(pi_half_lower(),pi_upper()) IPI__3PI_2I FloatVal(pi_lower(),3*pi_half_upper()) I3PI_2__2PII FloatVal(3*pi_half_lower(),pi_twice_upper()) POS X ((I0__PI_2I.in(X))?0: (IPI_2__PII.in(X))?1: (IPI__3PI_2I.in(X))?2: 3 ) ASININF_DOWN r.asin_down(aSinIv.min()) ASINSUP_UP r.asin_up(aSinIv.max()) /*-*-mode:C++;c-basic-offset:2;indent-tabs-mode:nil-*-*/ /* *Mainauthors: *VincentBarichard<Vincent.Barichard@univ-angers.fr> * *Copyright: *VincentBarichard,2012 * *Lastmodified: *$Date:2013-02-0421:28:39+0100(Mon,04Feb2013)$by$Author:schulte$ *$Revision:13262$ * *ThisfileispartofGecode,thegenericconstraint *developmentenvironment: *http://www.gecode.org * *Permissionisherebygranted,freeofcharge,toanypersonobtaining *acopyofthissoftwareandassociateddocumentationfiles(the *"Software"),todealintheSoftwarewithoutrestriction,including *withoutlimitationtherightstouse,copy,modify,merge,publish, *distribute,sublicense,and/orsellcopiesoftheSoftware,andto *permitpersonstowhomtheSoftwareisfurnishedtodoso,subjectto *thefollowingconditions: * *Theabovecopyrightnoticeandthispermissionnoticeshallbe *includedinallcopiesorsubstantialportionsoftheSoftware. * *THESOFTWAREISPROVIDED"ASIS",WITHOUTWARRANTYOFANYKIND, *EXPRESSORIMPLIED,INCLUDINGBUTNOTLIMITEDTOTHEWARRANTIESOF *MERCHANTABILITY,FITNESSFORAPARTICULARPURPOSEAND *NONINFRINGEMENT.INNOEVENTSHALLTHEAUTHORSORCOPYRIGHTHOLDERSBE *LIABLEFORANYCLAIM,DAMAGESOROTHERLIABILITY,WHETHERINANACTION *OFCONTRACT,TORTOROTHERWISE,ARISINGFROM,OUTOFORINCONNECTION *WITHTHESOFTWAREORTHEUSEOROTHERDEALINGSINTHESOFTWARE. * */ namespaceGecode{namespaceFloat{namespaceTrigonometric{ /* *ASinprojectionfunction * */ template<classV> voidaSinProject(Rounding&r,constV&aSinIv,FloatNum&iv_min,FloatNum&iv_max,int&n_min,int&n_max){ #defineI0__PI_2IFloatVal(0,pi_half_upper()) #defineIPI_2__PIIFloatVal(pi_half_lower(),pi_upper()) #defineIPI__3PI_2IFloatVal(pi_lower(),3*pi_half_upper()) #defineI3PI_2__2PIIFloatVal(3*pi_half_lower(),pi_twice_upper()) #definePOS(X)((I0__PI_2I.in(X))?0:(IPI_2__PII.in(X))?1:(IPI__3PI_2I.in(X))?2:3) #defineASININF_DOWNr.asin_down(aSinIv.min()) #defineASINSUP_UPr.asin_up(aSinIv.max()) //0<=>in[0;PI/2] //1<=>in[PI/2;PI] //2<=>in[PI;3*PI/2] //3<=>in[3*PI/2;2*PI] switch(POS(iv_min)) { case0: if(r.sin_down(iv_min)>aSinIv.max()){n_min++;iv_min=-ASINSUP_UP;} elseif(r.sin_up(iv_min)<aSinIv.min()){iv_min=ASININF_DOWN;} break; case1: if(r.sin_down(iv_min)>aSinIv.max()){n_min++;iv_min=-ASINSUP_UP;} elseif(r.sin_up(iv_min)<aSinIv.min()){n_min+=2;iv_min=ASININF_DOWN;} break; case2: if(r.sin_down(iv_min)>aSinIv.max()){n_min++;iv_min=-ASINSUP_UP;} elseif(r.sin_up(iv_min)<aSinIv.min()){n_min+=2;iv_min=ASININF_DOWN;} break; case3: if(r.sin_down(iv_min)>aSinIv.max()){n_min+=3;iv_min=-ASINSUP_UP;} elseif(r.sin_up(iv_min)<aSinIv.min()){n_min+=2;iv_min=ASININF_DOWN;} break; default: GECODE_NEVER; break; } //0<=>in[0;PI/2] //1<=>in[PI/2;PI] //2<=>in[PI;3*PI/2] //3<=>in[3*PI/2;2*PI] switch(POS(iv_max)) { case0: if(r.sin_down(iv_max)>aSinIv.max()){iv_max=ASINSUP_UP;} elseif(r.sin_up(iv_max)<aSinIv.min()){n_max--;iv_max=-ASININF_DOWN;} break; case1: if(r.sin_down(iv_max)>aSinIv.max()){iv_max=ASINSUP_UP;} elseif(r.sin_up(iv_max)<aSinIv.min()){n_max++;iv_max=-ASININF_DOWN;} break; case2: if(r.sin_down(iv_max)>aSinIv.max()){iv_max=ASINSUP_UP;} elseif(r.sin_up(iv_max)<aSinIv.min()){n_max++;iv_max=-ASININF_DOWN;} break; case3: if(r.sin_down(iv_max)>aSinIv.max()){n_max+=2;iv_max=ASINSUP_UP;} elseif(r.sin_up(iv_max)<aSinIv.min()){n_max++;iv_max=-ASININF_DOWN;} break; default: GECODE_NEVER; break; } #undefASININF_DOWN #undefASINSUP_UP #undefPOS #undefI0__PI_2I #undefIPI_2__PII #undefIPI__3PI_2I #undefI3PI_2__2PII } /* *Boundsconsistentsinusoperator * */ template<classA,classB> forceinline Sin<A,B>::Sin(Homehome,Ax0,Bx1) :MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,x0,x1){} template<classA,classB> ExecStatus Sin<A,B>::post(Homehome,Ax0,Bx1){ if(same(x0,x1)){ GECODE_ME_CHECK(x0.eq(home,0.0)); }else{ GECODE_ME_CHECK(x1.gq(home,-1.0)); GECODE_ME_CHECK(x1.lq(home,1.0)); (void)new(home)Sin<A,B>(home,x0,x1); } returnES_OK; } template<classA,classB> forceinline Sin<A,B>::Sin(Space&home,boolshare,Sin<A,B>&p) :MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,share,p){} template<classA,classB> Actor* Sin<A,B>::copy(Space&home,boolshare){ returnnew(home)Sin<A,B>(home,share,*this); } template<classA,classB> ExecStatus Sin<A,B>::propagate(Space&home,constModEventDelta&){ GECODE_ME_CHECK(x1.eq(home,sin(x0.val()))); Roundingr; intn_min=2*static_cast<int>(r.div_up(x0.min(),pi_twice_upper())); intn_max=2*static_cast<int>(r.div_up(x0.max(),pi_twice_upper())); if(x0.min()<0)n_min-=2; if(x0.max()<0)n_max-=2; FloatNumiv_min=r.sub_down(x0.min(),r.mul_down(n_min,pi_upper())); FloatNumiv_max=r.sub_up(x0.max(),r.mul_down(n_max,pi_upper())); aSinProject(r,x1,iv_min,iv_max,n_min,n_max); FloatNumn_iv_min=r.add_down(iv_min,r.mul_down(n_min,pi_upper())); FloatNumn_iv_max=r.add_up(iv_max,r.mul_down(n_max,pi_upper())); if(n_iv_min>n_iv_max)returnES_FAILED; GECODE_ME_CHECK(x0.eq(home,FloatVal(n_iv_min,n_iv_max))); GECODE_ME_CHECK(x1.eq(home,sin(x0.val())));//Redosinbecausewithx0reduction,sinmaybemoreaccurate return(x0.assigned())?home.ES_SUBSUMED(*this):ES_FIX; } /* *Boundsconsistentcosinusoperator * */ template<classA,classB> forceinline Cos<A,B>::Cos(Homehome,Ax0,Bx1) :MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,x0,x1){} template<classA,classB> ExecStatus Cos<A,B>::post(Homehome,Ax0,Bx1){ if(same(x0,x1)){ GECODE_ME_CHECK(x0.gq(home,0.7390851332151)); GECODE_ME_CHECK(x0.lq(home,0.7390851332152)); boolmod; do{ mod=false; GECODE_ME_CHECK_MODIFIED(mod,x0.eq(home,cos(x0.val()))); }while(mod); }else{ GECODE_ME_CHECK(x1.gq(home,-1.0)); GECODE_ME_CHECK(x1.lq(home,1.0)); (void)new(home)Cos<A,B>(home,x0,x1); } returnES_OK; } template<classA,classB> forceinline Cos<A,B>::Cos(Space&home,boolshare,Cos<A,B>&p) :MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,share,p){} template<classA,classB> Actor* Cos<A,B>::copy(Space&home,boolshare){ returnnew(home)Cos<A,B>(home,share,*this); } template<classA,classB> ExecStatus Cos<A,B>::propagate(Space&home,constModEventDelta&){ GECODE_ME_CHECK(x1.eq(home,cos(x0.val()))); Roundingr; FloatValx0Trans=x0.val()+FloatVal::pi_half(); intn_min=2*static_cast<int>(r.div_up(x0Trans.min(),pi_twice_upper())); intn_max=2*static_cast<int>(r.div_up(x0Trans.max(),pi_twice_upper())); if(x0Trans.min()<0)n_min-=2; if(x0Trans.max()<0)n_max-=2; FloatNumiv_min=r.sub_down(x0Trans.min(),r.mul_down(n_min,pi_upper())); FloatNumiv_max=r.sub_up(x0Trans.max(),r.mul_down(n_max,pi_upper())); aSinProject(r,x1,iv_min,iv_max,n_min,n_max); FloatNumn_iv_min=r.add_down(iv_min,r.mul_down(n_min,pi_upper())); FloatNumn_iv_max=r.add_up(iv_max,r.mul_down(n_max,pi_upper())); if(n_iv_min>n_iv_max)returnES_FAILED; GECODE_ME_CHECK(x0.eq(home,FloatVal(n_iv_min,n_iv_max)-FloatVal::pi_half())); GECODE_ME_CHECK(x1.eq(home,cos(x0.val())));//Redosinbecausewithx0reduction,sinmaybemoreaccurate return(x0.assigned())?home.ES_SUBSUMED(*this):ES_FIX; } }}} //STATISTICS:float-prop