/*************************************************************************** * Copyright 2013 CertiVox UK Ltd. * * This file is part of CertiVox MIRACL Crypto SDK. * * The CertiVox MIRACL Crypto SDK provides developers with an * extensive and efficient set of cryptographic functions. * For further information about its features and functionalities please * refer to http://www.certivox.com * * * The CertiVox MIRACL Crypto SDK is free software: you can * redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the * Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * * The CertiVox MIRACL Crypto SDK is distributed in the hope * that it will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * * You should have received a copy of the GNU Affero General Public * License along with CertiVox MIRACL Crypto SDK. * If not, see . * * You can be released from the requirements of the license by purchasing * a commercial license. Buying such a license is mandatory as soon as you * develop commercial activities involving the CertiVox MIRACL Crypto SDK * without disclosing the source code of your own applications, or shipping * the CertiVox MIRACL Crypto SDK with a closed source product. * * ***************************************************************************/ /* * MIRACL flash roots and powers * mrflsh1.c */ #include #include "miracl.h" #ifdef MR_FLASH static int quad(_MIPD_ big w,int n) { /* generator for C.F. of square root of small integer */ int t; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (n==0) { mr_mip->oldn=(-1); mr_mip->b=2*mr_mip->RD; mr_mip->c=mr_mip->b; mr_mip->a=1; mr_mip->d=mr_mip->RS; mr_mip->r=mr_mip->RD; if (mr_mip->r>=MR_TOOBIG) { convert(_MIPP_ mr_mip->r,w); return MR_TOOBIG; } return (mr_mip->r); } else if (n==mr_mip->oldn) return (mr_mip->r); t=mr_mip->a; mr_mip->a=mr_mip->r*(mr_mip->c-mr_mip->b)+mr_mip->d; mr_mip->d=t; mr_mip->r=mr_mip->b/mr_mip->a; mr_mip->c=mr_mip->b; mr_mip->b=2*mr_mip->RD-mr_mip->b%mr_mip->a; mr_mip->oldn=n; if (mr_mip->r>=MR_TOOBIG) { convert(_MIPP_ mr_mip->r,w); return (MR_TOOBIG); } return mr_mip->r; } void fpower(_MIPD_ flash x,int n,flash w) { /* raise floating-slash number to integer power w=x^n */ #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif copy(x,mr_mip->w8); zero(w); if (mr_mip->ERNUM || size(mr_mip->w8)==0) return; convert(_MIPP_ 1,w); if (n==0) return; MR_IN(51) if (n<0) { n=(-n); frecip(_MIPP_ mr_mip->w8,mr_mip->w8); } if (n==1) { copy(mr_mip->w8,w); MR_OUT return; } forever { if (n%2!=0) fmul(_MIPP_ w,mr_mip->w8,w); n/=2; if (mr_mip->ERNUM || n==0) break; fmul(_MIPP_ mr_mip->w8,mr_mip->w8,mr_mip->w8); } MR_OUT } BOOL froot(_MIPD_ flash x,int n,flash w) { /* extract nth root of x - w=x^(1/n) using Newtons method */ BOOL minus,rn,rm,hack; int nm,dn,s,op[5]; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif copy(x,w); if (mr_mip->ERNUM || n==1) return TRUE; if (n==(-1)) { frecip(_MIPP_ w,w); return TRUE; } MR_IN(52) minus=FALSE; if (n<0) { minus=TRUE; n=(-n); } s=exsign(w); if (n%2==0 && s==MINUS) { mr_berror(_MIPP_ MR_ERR_NEG_ROOT); MR_OUT return FALSE; } insign(PLUS,w); numer(_MIPP_ w,mr_mip->w8); denom(_MIPP_ w,mr_mip->w9); rn=nroot(_MIPP_ mr_mip->w8,n,mr_mip->w8); rm=nroot(_MIPP_ mr_mip->w9,n,mr_mip->w9); if (rn && rm) { fpack(_MIPP_ mr_mip->w8,mr_mip->w9,w); if (minus) frecip(_MIPP_ w,w); insign(s,w); MR_OUT return TRUE; } nm=size(mr_mip->w8); dn=size(mr_mip->w9); if (n==2 && ((nmw8,mr_mip->w8,mr_mip->w8); numer(_MIPP_ w,mr_mip->w7); subtract(_MIPP_ mr_mip->w7,mr_mip->w8,mr_mip->w8); mr_mip->RS=(int)(mr_mip->w8->w[0]+mr_mip->base*mr_mip->w8->w[1]); mr_mip->RD=nm; build(_MIPP_ mr_mip->w8,quad); } if (!rm && dnw9,mr_mip->w9,mr_mip->w9); denom(_MIPP_ w,mr_mip->w7); subtract(_MIPP_ mr_mip->w7,mr_mip->w9,mr_mip->w9); mr_mip->RS=(int)(mr_mip->w9->w[0]+mr_mip->base*mr_mip->w9->w[2]); mr_mip->RD=dn; build(_MIPP_ mr_mip->w9,quad); } if (size(mr_mip->w9)==1) copy(mr_mip->w8,w); else fdiv(_MIPP_ mr_mip->w8,mr_mip->w9,w); if (minus) frecip(_MIPP_ w,w); insign(s,w); MR_OUT return FALSE; } hack=FALSE; if (mr_lent(w)<=2) { /* for 'simple' w only */ hack=TRUE; fpi(_MIPP_ mr_mip->pi); fpmul(_MIPP_ mr_mip->pi,1,3,mr_mip->w10); fpower(_MIPP_ mr_mip->w10,n,mr_mip->w10); fmul(_MIPP_ w,mr_mip->w10,w); } op[0]=0x6C; /* set up for [(n-1).x+y]/n */ op[1]=n-1; op[2]=1; op[3]=n; op[4]=0; mr_mip->workprec=mr_mip->stprec; dconv(_MIPP_ pow(fdsize(_MIPP_ w),1.0/(double)n),mr_mip->w10); while (mr_mip->workprec!=mr_mip->nib) { /* Newtons iteration w10=(w/w10^(n-1)+(n-1)*w10)/n */ if (mr_mip->workprecnib) mr_mip->workprec*=2; if (mr_mip->workprec>=mr_mip->nib) mr_mip->workprec=mr_mip->nib; else if (mr_mip->workprec*2>mr_mip->nib) mr_mip->workprec=(mr_mip->nib+1)/2; fpower(_MIPP_ mr_mip->w10,n-1,mr_mip->w9); fdiv(_MIPP_ w,mr_mip->w9,mr_mip->w9); flop(_MIPP_ mr_mip->w10,mr_mip->w9,op,mr_mip->w10); } copy(mr_mip->w10,w); op[0]=0x48; op[1]=3; op[3]=1; op[2]=op[4]=0; if (hack) flop(_MIPP_ w,mr_mip->pi,op,w); if (minus) frecip(_MIPP_ w,w); insign(s,w); MR_OUT return FALSE; } #endif