⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wy__numstr_basic.h

📁 一个不错
💻 H
字号:
/* Copyright is licensed by GNU LGPL.                         by I.J.Wang 2005   This file is template or inline functions for include in implementaion   for each instantiated type*/#ifndef WY__NUMSTR_BASIC_H__#define WY__NUMSTR_BASIC_H__#define WYLIB_SOURCE#include "wystr.h"#include <cstdlib>#include <cstring>#include <cmath>#include <limits>namespace WyMath { extern double _scif(double x, double& p10);};static const char WY__EToken('e');// [Internal] Break num into radix notation and store into buf//// Note: 1. buf have to have enough space before call//       2. buf can not be 0, radix should be >=2//       3. the stored 'digit' is saved in reversed order//       4. if num is negative, the stored 'digit' is negative//       5. the stored 'digit' is in range [0-radix)// // [Ret] number of digits stored into buf//inline int wy__brknum(char* buf,int num, int radix) WY__TSPC(){ std::div_t dt={num,0}; //dt.quot=num; int n=0; do {   dt=std::div(dt.quot,radix);   buf[n++]=(char)(dt.rem); } while(dt.quot!=0); return(n);};inline int wy__brknum(char* buf,long num, int radix) WY__TSPC(){ std::ldiv_t dt={num,0}; //dt.quot=num; int n=0; do {   dt=std::ldiv(dt.quot,radix);   buf[n++]=(char)(dt.rem); } while(dt.quot!=0); return(n);};inline static int wy__brknum(char* buf,long long num, int radix) WY__TSPC(){ std::lldiv_t dt={num,0}; //dt.quot=num; int n=0; do {   dt=std::lldiv(dt.quot,radix);   buf[n++]=(char)(dt.rem); } while(dt.quot!=0); return(n);};inline int wy__brknum(char* buf,unsigned int num, int radix){ if(num<=(unsigned int)(std::numeric_limits<int>::max())) {   return( wy__brknum(buf,(int)num,radix) ); } const unsigned int q=num/radix; if(q>(unsigned int)(std::numeric_limits<int>::max())) {   // assertion fail   WY_THROW(WyRet(Wym_ERANGE));    } buf[0]= char(num%radix); return( wy__brknum(buf+1,(int)q,radix)+1 );};inline int wy__brknum(char* buf,unsigned long num, int radix){ if(num<=(unsigned long)(std::numeric_limits<long>::max())) {   return( wy__brknum(buf,(long)num,radix) ); } const unsigned long q=num/radix; if(q>(unsigned long)(std::numeric_limits<long>::max())) {   // assertion fail   WY_THROW(WyRet(Wym_ERANGE));    } buf[0]= char(num%radix); return( wy__brknum(buf+1,(long)q,radix)+1 );};inline static int wy__brknum(char* buf,unsigned long long num, int radix){ if(num<=(unsigned long long)(std::numeric_limits<signed long long>::max())) {   return( wy__brknum(buf,(long long)num,radix) ); } const unsigned long long q=num/radix; if(q>(unsigned long long)(std::numeric_limits<signed long long>::max())) {   // assertion fail   WY_THROW(WyRet(Wym_ERANGE));    } buf[0]= char(num%radix); return( wy__brknum(buf+1,(signed long long)q,radix)+1 );};inline int wy__brknum(char*,double, int){ // This function exist for compiling reason. should not be actually called WY_TERMINATE("");};//// [Internal] Convert the broken down representation in buf/blen//            to ascii//// Note: buf can not be 0, blen must be >0//inline void wy__cvrrev_pos(char* buf, int blen) WY__TSPC(){ int i,j; for(i=0, j=blen-1; i<=j; ++i,--j) {   char ch1=buf[i];   char ch2=buf[j];   ch1= (ch1>9)? (ch1+'7'):(ch1+'0');   ch2= (ch2>9)? (ch2+'7'):(ch2+'0');   buf[i]=ch2;   buf[j]=ch1; }};//// [Internal] Convert the broken down representation in buf/blen//            to ascii//// Note: buf can not be 0, blen must be >0// Note: buf contaions one more character ('-') after return//inline void wy__cvrrev_neg(char* buf, int blen) WY__TSPC(){ {   const char ch0=-buf[0];   buf[blen]=(ch0>9)? (ch0+'7'):(ch0+'0');   buf[0]='-'; } int i,j; for(i=1, j=blen-1; i<=j; ++i,--j) {   char ch1=-buf[i];   char ch2=-buf[j];   ch1= (ch1>9)? (ch1+'7'):(ch1+'0');   ch2= (ch2>9)? (ch2+'7'):(ch2+'0');   buf[i]=ch2;   buf[j]=ch1; }};// [Interna] Convert number(integer type) to string//// [Ret] Ok//       Wym_EINVAL      radix invalid//       Wym_EFBIG       str size exceeds the maximum//       Wym_ENOMEM      Not enough memory//template <typename NumT>inline WyRet wy__setnum_integer(WyStr &str, NumT num, int radix){ if(std::numeric_limits<NumT>::is_integer==false) {   WY_TERMINATE(""); } if((radix<2)||(radix>36)) {   WY_RETURN(Wym_EINVAL); } char dbuf[std::numeric_limits<NumT>::digits+2]; // digits*('0'|'1') +'-' + 0 int n=wy__brknum(dbuf,num,radix); if(std::numeric_limits<NumT>::is_signed) {   if(num<0) {     wy__cvrrev_neg(dbuf,n);     ++n;   } else {     wy__cvrrev_pos(dbuf,n);   } } else {   wy__cvrrev_pos(dbuf,n); } WY_RETURN( str.reset( WyCSeg(dbuf,(size_t)n) ) );};//  [Syn] Convert number num into radix string//        representation, reset str with the result. The number of//        characters for fraction is specified by frdig.//        [-]ddd.ddd////    Note: There may be truncate or round-up error //    //    Implementation works only for radix equal to 10////  [Ret] Ok              Succeed//        Wym_EINVAL      radix invalid//        Wym_EFBIG       str size exceeds the maximum//        Wym_ENOMEM      Not enough memory//inline WyRet wy__setnum_double(WyStr &str,double num,int radix,size_t frdig)try { typedef long long int FI_INT;   // int type capable holding (int)double const size_t FI_INT_DIG10( size_t(std::numeric_limits<FI_INT>::digits10) ); if(radix!=10) {   WY_RETURN(Wym_EINVAL); } if(frdig>FI_INT_DIG10) {   frdig=FI_INT_DIG10; } if(isnan(num)) {   str.reset("nan");   return(Ok); } if(isinf(num)) {   if(isinf(num)>0) {     str.reset("inf");   } else {     str.reset("-inf");   }   return(Ok); } WyRet r; WyStr stmp; double wnum;   // whole num double frac;   // fraction if(num<0) {   stmp.reset(1,'-');   // always Ok   num=-num; } frac=std::modf(num,&wnum); {   WyStr tmp;   size_t n_dig( static_cast<size_t>(std::log10(wnum)+1.0) );  // dig10 of wnum   if(n_dig>=FI_INT_DIG10) {     wnum/= std::pow((double)10.0,(double)(n_dig-FI_INT_DIG10+1));   }   r=wy__setnum_integer(tmp,static_cast<FI_INT>(wnum),10);     if(r!=Ok) {     WY_RETURN(r);   }   if(n_dig>=FI_INT_DIG10) {     if((r=tmp.append(n_dig-FI_INT_DIG10+1,'0'))!=Ok) {       WY_RETURN(r);     }   }   stmp+=tmp;   if(frdig<=0) {     if(wnum<=0) {       WY_RETURN( str.reset("0") );     } else {       WY_RETURN( str.reset(stmp) );     }   }   stmp+='.'; } std::modf(frac*std::pow(10.0,static_cast<double>(frdig))           +std::numeric_limits<double>::epsilon()   // roundup?           ,&wnum); {   WyStr tmp;   r=wy__setnum_integer(tmp,static_cast<FI_INT>(wnum),10);   if(r!=Ok) {     WY_RETURN(r);   }   if(frdig<tmp.size()) {     WY_THROW(WyRet(Wym_ERANGE));   }   if((r=stmp.append(frdig-tmp.size(),'0'))!=Ok) {     WY_RETURN(r);   }   stmp+=tmp; } str.swap(stmp); return(Ok);}catch(const WyStr::Reply& e) { return(e);};template <typename NumT>WyRet wy__setnum(WyStr &str, NumT num, int radix)try { if(std::numeric_limits<NumT>::is_integer) {   WY_RETURN( wy__setnum_integer(str,num,radix) ); } else {   // float NumT assumed   typedef signed long long int FI_INT;  // int type capable holding (int)double   const int FrRadix=10;                 // float type always use radix 10   const size_t DftFracDig=6;            // number of digits for fraction   if(radix==FrRadix) {     WY_RETURN(wy__setnum_double(str,num,radix,DftFracDig));   } else if (radix!=0) {     WY_RETURN(Wym_EINVAL);   } else {     // FALL_THROUGH with radix==0   }   double fnorm,p10;   WyRet r;   WyStr tmp1;   fnorm=WyMath::_scif(num,p10);   if((r=wy__setnum_double(tmp1,fnorm,FrRadix,DftFracDig))!=Ok) {     WY_RETURN(r);   }   {     WyStr tmp2;     if((r=wy__setnum_integer(tmp2,static_cast<FI_INT>(p10),FrRadix))!=Ok) {       WY_RETURN(r);     }     tmp1+=WY__EToken;     if(p10>=0) {       tmp1+='+';     }     tmp1+=tmp2;   }   return( str.reset(tmp1) ); }}catch(const WyStr::Reply& e) { WY_RETURN( WyRet(e) );};template <typename NumT>WyRet wy__setnum(WyStr &str, NumT num, int radix, size_t frdig)try { if(std::numeric_limits<NumT>::is_integer) {   if(frdig!=0) {     WY_RETURN(Wym_EINVAL);   }   WY_RETURN( wy__setnum_integer(str,num,radix) ); } else {   // float NumT assumed   typedef signed long long int FI_INT;  // int type capable holding (int)double   const int FrRadix=10;                 // float type always use radix 10   if(radix==FrRadix) {     WY_RETURN(wy__setnum_double(str,num,radix,frdig));   } else if (radix!=0) {     WY_RETURN(Wym_EINVAL);   } else {     // FALL_THROUGH with radix==0   }   if(isnan(num)) {     str.reset("nan");     return(Ok);   }   if(isinf(num)) {     if(isinf(num)>0) {       str.reset("inf");     } else {       str.reset("-inf");     }     return(Ok);   }   double fnorm,p10;   WyRet r;   WyStr tmp1;   fnorm=WyMath::_scif(num,p10);   if((r=wy__setnum_double(tmp1,fnorm,FrRadix,frdig))!=Ok) {     WY_RETURN(r);   }   {     WyStr tmp2;     if((r=wy__setnum_integer(tmp2,static_cast<FI_INT>(p10),FrRadix))!=Ok) {       WY_RETURN(r);     }     tmp1+=WY__EToken;     if(p10>=0) {       tmp1+='+';     }     tmp1+=tmp2;   }   return( str.reset(tmp1) ); }}catch(const WyStr::Reply& e) { WY_RETURN( WyRet(e) );};template <typename NumT>WyRet wy__apdnum_integer(WyStr &str, NumT num, int radix){ if((radix<2)||(radix>36)) {   WY_RETURN(Wym_EINVAL); } char dbuf[std::numeric_limits<NumT>::digits+2]; // digits*('0'|'1') +'-' + 0 int n=wy__brknum(dbuf,num,radix); if(std::numeric_limits<NumT>::is_signed) {   if(num<0) {     wy__cvrrev_neg(dbuf,n);     ++n;   } else {     wy__cvrrev_pos(dbuf,n);   } } else {   wy__cvrrev_pos(dbuf,n); } WY_RETURN( str.append( WyCSeg(dbuf,(size_t)n) ) );};//  [Syn] Convert number num into radix string//        representation, append the result to str. The number of//        characters for fraction is specified by frdig.//        [-]ddd.ddd////    Note: There may be truncate or round-up error //    //    Implementation works only for radix equal to 10////  [Ret] Ok              Succeed//        Wym_EINVAL      radix invalid//        Wym_EFBIG       str size exceeds the maximum//        Wym_ENOMEM      Not enough memory//inline WyRet wy__apdnum_double(WyStr &str,double num,int radix,size_t frdig)try { typedef long long int FI_INT;   // int type capable holding (int)double const size_t FI_INT_DIG10( size_t(std::numeric_limits<FI_INT>::digits10) ); if(radix!=10) {   WY_RETURN(Wym_EINVAL); } if(frdig>FI_INT_DIG10) {   frdig=FI_INT_DIG10; }  if(isnan(num)) {   WY_RETURN( str.append("nan") ); } if(isinf(num)) {   if(isinf(num)>0) {     WY_RETURN( str.append("inf") );   } else {     WY_RETURN( str.append("-inf") );   } } WyRet r; WyStr stmp; double wnum;   // whole num double frac;   // fraction if(num<0) {   stmp.reset(1,'-');   // always Ok   num=-num; } frac=std::modf(num,&wnum); {   WyStr tmp;   size_t n_dig( static_cast<size_t>(std::log10(wnum)+1.0) );  // dig10 of wnum   if(n_dig>=FI_INT_DIG10) {     wnum/= std::pow((double)10.0,(double)(n_dig-FI_INT_DIG10+1));   }   r=wy__setnum_integer(tmp,static_cast<FI_INT>(wnum),10);     if(r!=Ok) {     WY_RETURN(r);   }   if(n_dig>=FI_INT_DIG10) {     if((r=tmp.append(n_dig-FI_INT_DIG10+1,'0'))!=Ok) {       WY_RETURN(r);     }   }   stmp+=tmp;   if(frdig<=0) {     if(wnum<=0) {       WY_RETURN( str.append(char('0')) );     } else {       WY_RETURN( str.append(stmp) );     }   }   stmp+='.'; } std::modf(frac*std::pow(10.0,static_cast<double>(frdig))           +std::numeric_limits<double>::epsilon()   // roundup?           ,&wnum); {   WyStr tmp;   r=wy__setnum_integer(tmp,static_cast<FI_INT>(wnum),10);   if(r!=Ok) {     WY_RETURN(r);   }   if(frdig<tmp.size()) {     WY_TERMINATE("");   }   if((r=stmp.append(frdig-tmp.size(),'0'))!=Ok) {     WY_RETURN(r);   }   stmp+=tmp; } WY_RETURN( str.append(stmp) );}catch(const WyStr::Reply& e) { return(e);};template <typename NumT>WyRet wy__apdnum(WyStr &str, NumT num, int radix)try { if(std::numeric_limits<NumT>::is_integer) {   WY_RETURN( wy__apdnum_integer(str,num,radix) ); } else {   // float NumT assumed   typedef signed long long int FI_INT;  // int type capable holding (int)double   const int FrRadix=10;                 // float types always use radix 10   const size_t DftFracDig=6;            // number of digits for fraction   if(radix==FrRadix) {     WY_RETURN(wy__apdnum_double(str,num,radix,DftFracDig));   } else if (radix!=0) {     WY_RETURN(Wym_EINVAL);   } else {     // FALL_THROUGH with radix==0   }   if(isnan(num)) {     str.reset("nan");     return(Ok);   }   if(isinf(num)) {     if(isinf(num)>0) {       str.reset("inf");     } else {       str.reset("-inf");     }     return(Ok);   }   double fnorm,p10;   WyRet r;   WyStr tmp1;   fnorm=WyMath::_scif(num,p10);   if((r=wy__setnum_double(tmp1,fnorm,FrRadix,DftFracDig))!=Ok) {     WY_RETURN(r);   }   {     WyStr tmp2;     if((r=wy__setnum_integer(tmp2,static_cast<FI_INT>(p10),FrRadix))!=Ok) {       WY_RETURN(r);     }     tmp1+=WY__EToken;     if(p10>=0) {       tmp1+='+';     }     tmp1+=tmp2;   }   return( str.append(tmp1) ); }}catch(const WyStr::Reply& e) { return(e);};template <typename NumT>WyRet wy__apdnum(WyStr &str, NumT num, int radix, size_t frdig)try { if(std::numeric_limits<NumT>::is_integer) {   if(frdig!=0) {     WY_RETURN(Wym_EINVAL);   }   WY_RETURN( wy__apdnum_integer(str,num,radix) ); } else {   // float NumT assumed   typedef signed long long int FI_INT;  // int type capable holding (int)double   const int FrRadix=10;                 // float types always use radix 10   if(radix==FrRadix) {     WY_RETURN(wy__apdnum_double(str,num,radix,frdig));   } else if (radix!=0) {     WY_RETURN(Wym_EINVAL);   } else {     // FALL_THROUGH with radix==0   }   double fnorm,p10;   WyRet r;   WyStr tmp1;   fnorm=WyMath::_scif(num,p10);   if((r=wy__setnum_double(tmp1,fnorm,FrRadix,frdig))!=Ok) {     WY_RETURN(r);   }   {     WyStr tmp2;     if((r=wy__setnum_integer(tmp2,static_cast<FI_INT>(p10),FrRadix))!=Ok) {       WY_RETURN(r);     }     tmp1+=WY__EToken;     if(p10>=0) {       tmp1+='+';     }     tmp1+=tmp2;   }   return( str.append(tmp1) ); }}catch(const WyStr::Reply& e) { return(e);};#endif // end of WY__NUMSTR_BASIC_H__

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -